Commit b3aa6160 authored by Oleg.Korshul's avatar Oleg.Korshul Committed by Alexander Trofimov

очень много правок (клавиатура, графика, контекстное меню)

git-svn-id: svn://fileserver/activex/AVS/Sources/TeamlabOffice/trunk/ServerComponents@60903 954022d7-b5bf-4e40-9824-e11837661b57
parent 159caaf0
...@@ -387,6 +387,7 @@ namespace Aggplus ...@@ -387,6 +387,7 @@ namespace Aggplus
m_pImage = NULL; m_pImage = NULL;
m_bReleaseImage = FALSE; m_bReleaseImage = FALSE;
m_bUsePattern = FALSE; m_bUsePattern = FALSE;
Alpha = 255;
} }
CBrushTexture::CBrushTexture(const std::wstring& strName, WrapMode wrapMode) : CBrush(BrushTypeTextureFill), m_wrapMode(wrapMode) CBrushTexture::CBrushTexture(const std::wstring& strName, WrapMode wrapMode) : CBrush(BrushTypeTextureFill), m_wrapMode(wrapMode)
...@@ -394,6 +395,7 @@ namespace Aggplus ...@@ -394,6 +395,7 @@ namespace Aggplus
m_pImage = new CImage(strName); m_pImage = new CImage(strName);
m_bReleaseImage = TRUE; m_bReleaseImage = TRUE;
m_bUsePattern = FALSE; m_bUsePattern = FALSE;
Alpha = 255;
} }
CBrushTexture::CBrushTexture(CImage *pImage, WrapMode wrapMode) : CBrush(BrushTypeTextureFill), m_wrapMode(wrapMode) CBrushTexture::CBrushTexture(CImage *pImage, WrapMode wrapMode) : CBrush(BrushTypeTextureFill), m_wrapMode(wrapMode)
...@@ -401,6 +403,7 @@ namespace Aggplus ...@@ -401,6 +403,7 @@ namespace Aggplus
m_pImage = pImage; m_pImage = pImage;
m_bReleaseImage = FALSE; m_bReleaseImage = FALSE;
m_bUsePattern = FALSE; m_bUsePattern = FALSE;
Alpha = 255;
} }
CBrushTexture::~CBrushTexture() CBrushTexture::~CBrushTexture()
......
...@@ -168,6 +168,8 @@ public: ...@@ -168,6 +168,8 @@ public:
INT m_bUsePattern; INT m_bUsePattern;
CColor m_colors[2]; CColor m_colors[2];
BYTE Alpha;
}; };
} }
......
...@@ -1209,7 +1209,16 @@ namespace Aggplus ...@@ -1209,7 +1209,16 @@ namespace Aggplus
typedef agg::renderer_scanline_aa<base_renderer_type, gradient_span_alloc, gradient_span_gen> renderer_gradient_type; typedef agg::renderer_scanline_aa<base_renderer_type, gradient_span_alloc, gradient_span_gen> renderer_gradient_type;
renderer_gradient_type ren_gradient( m_frame_buffer.ren_base(), span_alloc, span_gen ); renderer_gradient_type ren_gradient( m_frame_buffer.ren_base(), span_alloc, span_gen );
render_scanlines(ren_gradient); if (fabs(m_dGlobalAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ren_gradient);
}
else
{
m_rasterizer.gamma_multi(m_dGlobalAlpha);
render_scanlines(ren_gradient);
m_rasterizer.gamma(1.0);
}
if( pSubColors ) delete [] pSubColors; if( pSubColors ) delete [] pSubColors;
if( pSubBlends ) delete [] pSubBlends; if( pSubBlends ) delete [] pSubBlends;
...@@ -1278,7 +1287,16 @@ namespace Aggplus ...@@ -1278,7 +1287,16 @@ namespace Aggplus
typedef agg::renderer_scanline_aa<base_renderer_type, gradient_span_alloc, gradient_span_gen> renderer_gradient_type; typedef agg::renderer_scanline_aa<base_renderer_type, gradient_span_alloc, gradient_span_gen> renderer_gradient_type;
renderer_gradient_type ren_gradient( m_frame_buffer.ren_base(), span_alloc, span_gen ); renderer_gradient_type ren_gradient( m_frame_buffer.ren_base(), span_alloc, span_gen );
render_scanlines(ren_gradient); if (fabs(m_dGlobalAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ren_gradient);
}
else
{
m_rasterizer.gamma_multi(m_dGlobalAlpha);
render_scanlines(ren_gradient);
m_rasterizer.gamma(1.0);
}
if( pSubColors ) delete [] pSubColors; if( pSubColors ) delete [] pSubColors;
if( pSubBlends ) delete [] pSubBlends; if( pSubBlends ) delete [] pSubBlends;
...@@ -1328,7 +1346,16 @@ namespace Aggplus ...@@ -1328,7 +1346,16 @@ namespace Aggplus
typedef agg::renderer_scanline_aa<base_renderer_type, hatch_span_alloc, hatch_span_gen> renderer_hatch_type; typedef agg::renderer_scanline_aa<base_renderer_type, hatch_span_alloc, hatch_span_gen> renderer_hatch_type;
renderer_hatch_type ren_hatch( m_frame_buffer.ren_base(), span_alloc, span_gen ); renderer_hatch_type ren_hatch( m_frame_buffer.ren_base(), span_alloc, span_gen );
render_scanlines(ren_hatch); if (fabs(m_dGlobalAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ren_hatch);
}
else
{
m_rasterizer.gamma_multi(m_dGlobalAlpha);
render_scanlines(ren_hatch);
m_rasterizer.gamma(1.0);
}
#else #else
agg::rgba8 c1 = agg::rgba8(pBrush->m_dwColor1.GetB(), pBrush->m_dwColor1.GetG(), pBrush->m_dwColor1.GetR(), pBrush->m_dwColor1.GetA()); agg::rgba8 c1 = agg::rgba8(pBrush->m_dwColor1.GetB(), pBrush->m_dwColor1.GetG(), pBrush->m_dwColor1.GetR(), pBrush->m_dwColor1.GetA());
agg::rgba8 c2 = agg::rgba8(pBrush->m_dwColor2.GetB(), pBrush->m_dwColor2.GetG(), pBrush->m_dwColor2.GetR(), pBrush->m_dwColor2.GetA()); agg::rgba8 c2 = agg::rgba8(pBrush->m_dwColor2.GetB(), pBrush->m_dwColor2.GetG(), pBrush->m_dwColor2.GetR(), pBrush->m_dwColor2.GetA());
...@@ -1358,7 +1385,16 @@ namespace Aggplus ...@@ -1358,7 +1385,16 @@ namespace Aggplus
span_gen_type sg(img_src, interpolator); span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg); renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
render_scanlines(ri); if (fabs(m_dGlobalAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ri);
}
else
{
m_rasterizer.gamma_multi(m_dGlobalAlpha);
render_scanlines(ri);
m_rasterizer.gamma(1.0);
}
RELEASEARRAYOBJECTS(pPattern); RELEASEARRAYOBJECTS(pPattern);
#endif #endif
...@@ -1400,7 +1436,7 @@ namespace Aggplus ...@@ -1400,7 +1436,7 @@ namespace Aggplus
} }
} }
void CGraphics::DoFillPathTextureClampSz2(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride) void CGraphics::DoFillPathTextureClampSz2(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride, BYTE Alpha)
{ {
if (!m_bSwapRGB) if (!m_bSwapRGB)
{ {
...@@ -1441,13 +1477,14 @@ namespace Aggplus ...@@ -1441,13 +1477,14 @@ namespace Aggplus
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg); renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
//agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri); //agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri);
if (fabs(m_dGlobalAlpha - 1.0) < FLT_EPSILON) double dAlpha = m_dGlobalAlpha * Alpha / 255.0;
if (fabs(dAlpha - 1.0) < FLT_EPSILON)
{ {
render_scanlines(ri); render_scanlines(ri);
} }
else else
{ {
m_rasterizer.gamma_multi(m_dGlobalAlpha); m_rasterizer.gamma_multi(dAlpha);
render_scanlines(ri); render_scanlines(ri);
m_rasterizer.gamma(1.0); m_rasterizer.gamma(1.0);
} }
...@@ -1492,19 +1529,155 @@ namespace Aggplus ...@@ -1492,19 +1529,155 @@ namespace Aggplus
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg); renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
//agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri); //agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri);
if (fabs(m_dGlobalAlpha - 1.0) < FLT_EPSILON) double dAlpha = m_dGlobalAlpha * Alpha / 255.0;
if (fabs(dAlpha - 1.0) < FLT_EPSILON)
{ {
render_scanlines(ri); render_scanlines(ri);
} }
else else
{ {
m_rasterizer.gamma_multi(m_dGlobalAlpha); m_rasterizer.gamma_multi(dAlpha);
render_scanlines(ri); render_scanlines(ri);
m_rasterizer.gamma(1.0); m_rasterizer.gamma(1.0);
} }
} }
} }
} }
template<class ColorSpacePix>
void CGraphics::DoFillPathTextureClampSz3(const CMatrix &matrix, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride, Aggplus::WrapMode wrapmode, BYTE Alpha)
{
agg::trans_affine mtx_Work( matrix.m_agg_mtx );
agg::trans_affine coords = m_oCoordTransform.m_agg_mtx;
coords.invert();
mtx_Work.multiply(coords);
//mtx_Work.multiply(m_oFullTransform.m_agg_mtx);
mtx_Work.invert();
span_alloc_type span_allocator; // Span Allocator
interpolator_type_linear interpolator(mtx_Work);
//agg::rendering_buffer PatRendBuff((BYTE *)pImgBuff, dwImgWidth, dwImgHeight, nImgStride);
agg::rendering_buffer PatRendBuff;
if (nImgStride < 0)
{
BYTE* pBuffer = (BYTE*)pImgBuff + (dwImgHeight - 1) * nImgStride;
PatRendBuff.attach(pBuffer, dwImgWidth, dwImgHeight, nImgStride);
}
else
{
PatRendBuff.attach((BYTE*)pImgBuff, dwImgWidth, dwImgHeight, nImgStride);
}
typedef ColorSpacePix pixfmt;
if(wrapmode == WrapModeTileFlipX)
{
//image_accessor_wrap
typedef agg::wrap_mode_reflect wrap_x_type;
typedef agg::wrap_mode_repeat wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
double dAlpha = m_dGlobalAlpha * Alpha / 255.0;
if (fabs(dAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ri);
}
else
{
m_rasterizer.gamma_multi(dAlpha);
render_scanlines(ri);
m_rasterizer.gamma(1.0);
}
}
else if(wrapmode == WrapModeTileFlipY)
{
//image_accessor_wrap
typedef agg::wrap_mode_repeat wrap_x_type;
typedef agg::wrap_mode_reflect wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
double dAlpha = m_dGlobalAlpha * Alpha / 255.0;
if (fabs(dAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ri);
}
else
{
m_rasterizer.gamma_multi(dAlpha);
render_scanlines(ri);
m_rasterizer.gamma(1.0);
}
}
else if(wrapmode == WrapModeTileFlipXY)
{
//image_accessor_wrap
typedef agg::wrap_mode_reflect wrap_x_type;
typedef agg::wrap_mode_reflect wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
double dAlpha = m_dGlobalAlpha * Alpha / 255.0;
if (fabs(dAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ri);
}
else
{
m_rasterizer.gamma_multi(dAlpha);
render_scanlines(ri);
m_rasterizer.gamma(1.0);
}
}
else //Repeat
{
//image_accessor_wrap
typedef agg::wrap_mode_repeat wrap_x_type;
typedef agg::wrap_mode_repeat wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
double dAlpha = m_dGlobalAlpha * Alpha / 255.0;
if (fabs(dAlpha - 1.0) < FLT_EPSILON)
{
render_scanlines(ri);
}
else
{
m_rasterizer.gamma_multi(dAlpha);
render_scanlines(ri);
m_rasterizer.gamma(1.0);
}
}
}
void CGraphics::DoFillPath(const CBrush* Brush) void CGraphics::DoFillPath(const CBrush* Brush)
{ {
...@@ -1575,102 +1748,18 @@ namespace Aggplus ...@@ -1575,102 +1748,18 @@ namespace Aggplus
if(wrapmode == WrapModeClamp) if(wrapmode == WrapModeClamp)
{ {
DoFillPathTextureClampSz2( matrix, pImgBuff, dwImgWidth, dwImgHeight, nImgStride); DoFillPathTextureClampSz2( matrix, pImgBuff, dwImgWidth, dwImgHeight, nImgStride, ptxBrush->Alpha);
} }
else else
{ {
agg::trans_affine mtx_Work( matrix.m_agg_mtx ); if (!m_bSwapRGB)
//mtx_Work.multiply(m_oFullTransform.m_agg_mtx); {
mtx_Work.invert(); DoFillPathTextureClampSz3<agg::pixfmt_bgra32>(matrix, pImgBuff, dwImgWidth, dwImgHeight, nImgStride, wrapmode, ptxBrush->Alpha);
}
span_alloc_type span_allocator; // Span Allocator else
interpolator_type_linear interpolator(mtx_Work); {
DoFillPathTextureClampSz3<agg::pixfmt_rgba32>(matrix, pImgBuff, dwImgWidth, dwImgHeight, nImgStride, wrapmode, ptxBrush->Alpha);
//agg::rendering_buffer PatRendBuff((BYTE *)pImgBuff, dwImgWidth, dwImgHeight, nImgStride); }
agg::rendering_buffer PatRendBuff;
if (nImgStride < 0)
{
BYTE* pBuffer = (BYTE*)pImgBuff + (dwImgHeight - 1) * nImgStride;
PatRendBuff.attach(pBuffer, dwImgWidth, dwImgHeight, nImgStride);
}
else
{
PatRendBuff.attach((BYTE*)pImgBuff, dwImgWidth, dwImgHeight, nImgStride);
}
if(wrapmode == WrapModeTileFlipX)
{
typedef agg::pixfmt_bgra32 pixfmt;
//image_accessor_wrap
typedef agg::wrap_mode_reflect wrap_x_type;
typedef agg::wrap_mode_repeat wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
//agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri);
render_scanlines(ri);
}
else if(wrapmode == WrapModeTileFlipY)
{
typedef agg::pixfmt_bgra32 pixfmt;
//image_accessor_wrap
typedef agg::wrap_mode_repeat wrap_x_type;
typedef agg::wrap_mode_reflect wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
//agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri);
render_scanlines(ri);
}
else if(wrapmode == WrapModeTileFlipXY)
{
typedef agg::pixfmt_bgra32 pixfmt;
//image_accessor_wrap
typedef agg::wrap_mode_reflect wrap_x_type;
typedef agg::wrap_mode_reflect wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
//agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri);
render_scanlines(ri);
}
else //Repeat
{
typedef agg::pixfmt_bgra32 pixfmt;
//image_accessor_wrap
typedef agg::wrap_mode_repeat wrap_x_type;
typedef agg::wrap_mode_repeat wrap_y_type;
typedef agg::image_accessor_wrap<pixfmt, wrap_x_type, wrap_y_type> img_source_type;
typedef agg::span_image_filter_rgba_bilinear<img_source_type, interpolator_type_linear> span_gen_type;
typedef agg::renderer_scanline_aa<base_renderer_type, span_alloc_type, span_gen_type> renderer_type;
pixfmt img_pixf(PatRendBuff);
img_source_type img_src(img_pixf);
span_gen_type sg(img_src, interpolator);
renderer_type ri(m_frame_buffer.ren_base(), span_allocator, sg);
//agg::render_scanlines(m_rasterizer.get_rasterizer(), m_rasterizer.get_scanline(), ri);
render_scanlines(ri);
}
} }
if( pTmpBuffer ) if( pTmpBuffer )
......
...@@ -304,7 +304,11 @@ protected: ...@@ -304,7 +304,11 @@ protected:
void DoFillPathGradient2(CBrushLinearGradient *pBrush); void DoFillPathGradient2(CBrushLinearGradient *pBrush);
void DoFillPathHatch(CBrushHatch *pBrush); void DoFillPathHatch(CBrushHatch *pBrush);
void DoFillPathTextureClampSz(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride); void DoFillPathTextureClampSz(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride);
void DoFillPathTextureClampSz2(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride); void DoFillPathTextureClampSz2(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride, BYTE Alpha = 255);
template<class ColorSpacePix>
void DoFillPathTextureClampSz3(const CMatrix &mImgMtx, const void *pImgBuff, DWORD dwImgWidth, DWORD dwImgHeight, int nImgStride, Aggplus::WrapMode wrapmode, BYTE Alpha = 255);
void DoFillPath(const CBrush* Brush); void DoFillPath(const CBrush* Brush);
// text methods // text methods
......
...@@ -806,6 +806,8 @@ HRESULT CGraphicsRenderer::DrawPath(const LONG& nType) ...@@ -806,6 +806,8 @@ HRESULT CGraphicsRenderer::DrawPath(const LONG& nType)
pTextureBrush->m_colors[0] = Aggplus::CColor((BYTE)m_oBrush.Alpha1, m_oBrush.Color1); pTextureBrush->m_colors[0] = Aggplus::CColor((BYTE)m_oBrush.Alpha1, m_oBrush.Color1);
pTextureBrush->m_colors[1] = Aggplus::CColor((BYTE)m_oBrush.Alpha2, m_oBrush.Color2); pTextureBrush->m_colors[1] = Aggplus::CColor((BYTE)m_oBrush.Alpha2, m_oBrush.Color2);
} }
pTextureBrush->Alpha = (BYTE)m_oBrush.TextureAlpha;
} }
pBrush = pTextureBrush; pBrush = pTextureBrush;
......
...@@ -98,13 +98,13 @@ public: ...@@ -98,13 +98,13 @@ public:
if (nCount >= m_lMaxCount) if (nCount >= m_lMaxCount)
{ {
int nNeedDelete = nCount - m_lMaxCount; int nNeedDelete = nCount - m_lMaxCount;
for (std::map<std::wstring,CCacheImage*>::iterator it2 = m_mapImages.begin(); it2 != m_mapImages.end(); ++it2)
std::map<std::wstring,CCacheImage*>::iterator it2 = m_mapImages.begin();
while (nNeedDelete > 0 && it2 != m_mapImages.end())
{ {
if (nNeedDelete == 0)
break;
it2->second->Release(); it2->second->Release();
m_mapImages.erase(it2); it2 = m_mapImages.erase(it2);
--nNeedDelete;
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment