diff options
author | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-11-12 14:53:46 +0200 |
---|---|---|
committer | Noel Grandin <noel.grandin@collabora.co.uk> | 2022-11-14 17:24:36 +0100 |
commit | 95dceefe207da45bd955d07a88bf7a956b274081 (patch) | |
tree | 0cf2b732fb2c7d2ae31f9a28f87ce7d6364fbfc3 /vcl | |
parent | c3ca46945aa498907a938e33b2df7937f45199db (diff) |
split CairoCommon XOR code into its own method
Change-Id: If615f08a44a083d53c75f58af3578e59634f9a11
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/142700
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/headless/CairoCommon.cxx | 194 | ||||
-rw-r--r-- | vcl/inc/headless/CairoCommon.hxx | 6 |
2 files changed, 106 insertions, 94 deletions
diff --git a/vcl/headless/CairoCommon.cxx b/vcl/headless/CairoCommon.cxx index 08a14b51bc08..cba7a7328fd4 100644 --- a/vcl/headless/CairoCommon.cxx +++ b/vcl/headless/CairoCommon.cxx @@ -448,114 +448,120 @@ void CairoCommon::releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, //are some edge cases where legacy stuff still supports it, so //emulate it (slowly) here. if (bXoring) + doXorOnRelease(nExtentsLeft, nExtentsTop, nExtentsRight, nExtentsBottom, surface, nWidth); + + cairo_destroy(cr); // unref + + DamageHandler* pDamage + = static_cast<DamageHandler*>(cairo_surface_get_user_data(m_pSurface, getDamageKey())); + + if (pDamage) { - cairo_surface_t* target_surface = m_pSurface; - if (cairo_surface_get_type(target_surface) != CAIRO_SURFACE_TYPE_IMAGE) - { - //in the unlikely case we can't use m_pSurface directly, copy contents - //to another temp image surface - cairo_t* copycr = createTmpCompatibleCairoContext(); - cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - nExtentsLeft, - nExtentsBottom - nExtentsTop); - cairo_set_source_surface(copycr, m_pSurface, 0, 0); - cairo_paint(copycr); - target_surface = cairo_get_target(copycr); - cairo_destroy(copycr); - } + pDamage->damaged(pDamage->handle, nExtentsLeft, nExtentsTop, nExtentsRight - nExtentsLeft, + nExtentsBottom - nExtentsTop); + } +} - cairo_surface_flush(target_surface); - unsigned char* target_surface_data = cairo_image_surface_get_data(target_surface); - unsigned char* xor_surface_data = cairo_image_surface_get_data(surface); - - cairo_format_t nFormat = cairo_image_surface_get_format(target_surface); - assert(nFormat == CAIRO_FORMAT_ARGB32 - && "need to implement CAIRO_FORMAT_A1 after all here"); - sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth * m_fScale); - sal_Int32 nUnscaledExtentsLeft = nExtentsLeft * m_fScale; - sal_Int32 nUnscaledExtentsRight = nExtentsRight * m_fScale; - sal_Int32 nUnscaledExtentsTop = nExtentsTop * m_fScale; - sal_Int32 nUnscaledExtentsBottom = nExtentsBottom * m_fScale; - - // Handle headless size forced to (1,1) by SvpSalFrame::GetSurfaceFrameSize(). - int target_surface_width = cairo_image_surface_get_width(target_surface); - if (nUnscaledExtentsLeft > target_surface_width) - nUnscaledExtentsLeft = target_surface_width; - if (nUnscaledExtentsRight > target_surface_width) - nUnscaledExtentsRight = target_surface_width; - int target_surface_height = cairo_image_surface_get_height(target_surface); - if (nUnscaledExtentsTop > target_surface_height) - nUnscaledExtentsTop = target_surface_height; - if (nUnscaledExtentsBottom > target_surface_height) - nUnscaledExtentsBottom = target_surface_height; +void CairoCommon::doXorOnRelease(sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop, + sal_Int32 nExtentsRight, sal_Int32 nExtentsBottom, + cairo_surface_t* const surface, sal_Int32 nWidth) const +{ + //For the most part we avoid the use of XOR these days, but there + //are some edge cases where legacy stuff still supports it, so + //emulate it (slowly) here. + cairo_surface_t* target_surface = m_pSurface; + if (cairo_surface_get_type(target_surface) != CAIRO_SURFACE_TYPE_IMAGE) + { + //in the unlikely case we can't use m_pSurface directly, copy contents + //to another temp image surface + cairo_t* copycr = createTmpCompatibleCairoContext(); + cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - nExtentsLeft, + nExtentsBottom - nExtentsTop); + cairo_set_source_surface(copycr, m_pSurface, 0, 0); + cairo_paint(copycr); + target_surface = cairo_get_target(copycr); + cairo_destroy(copycr); + } + + cairo_surface_flush(target_surface); + unsigned char* target_surface_data = cairo_image_surface_get_data(target_surface); + unsigned char* xor_surface_data = cairo_image_surface_get_data(surface); + + cairo_format_t nFormat = cairo_image_surface_get_format(target_surface); + assert(nFormat == CAIRO_FORMAT_ARGB32 && "need to implement CAIRO_FORMAT_A1 after all here"); + sal_Int32 nStride = cairo_format_stride_for_width(nFormat, nWidth * m_fScale); + sal_Int32 nUnscaledExtentsLeft = nExtentsLeft * m_fScale; + sal_Int32 nUnscaledExtentsRight = nExtentsRight * m_fScale; + sal_Int32 nUnscaledExtentsTop = nExtentsTop * m_fScale; + sal_Int32 nUnscaledExtentsBottom = nExtentsBottom * m_fScale; + + // Handle headless size forced to (1,1) by SvpSalFrame::GetSurfaceFrameSize(). + int target_surface_width = cairo_image_surface_get_width(target_surface); + if (nUnscaledExtentsLeft > target_surface_width) + nUnscaledExtentsLeft = target_surface_width; + if (nUnscaledExtentsRight > target_surface_width) + nUnscaledExtentsRight = target_surface_width; + int target_surface_height = cairo_image_surface_get_height(target_surface); + if (nUnscaledExtentsTop > target_surface_height) + nUnscaledExtentsTop = target_surface_height; + if (nUnscaledExtentsBottom > target_surface_height) + nUnscaledExtentsBottom = target_surface_height; #if !ENABLE_WASM_STRIP_PREMULTIPLY - vcl::bitmap::lookup_table const& unpremultiply_table - = vcl::bitmap::get_unpremultiply_table(); - vcl::bitmap::lookup_table const& premultiply_table = vcl::bitmap::get_premultiply_table(); + vcl::bitmap::lookup_table const& unpremultiply_table = vcl::bitmap::get_unpremultiply_table(); + vcl::bitmap::lookup_table const& premultiply_table = vcl::bitmap::get_premultiply_table(); #endif - for (sal_Int32 y = nUnscaledExtentsTop; y < nUnscaledExtentsBottom; ++y) + for (sal_Int32 y = nUnscaledExtentsTop; y < nUnscaledExtentsBottom; ++y) + { + unsigned char* true_row = target_surface_data + (nStride * y); + unsigned char* xor_row = xor_surface_data + (nStride * y); + unsigned char* true_data = true_row + (nUnscaledExtentsLeft * 4); + unsigned char* xor_data = xor_row + (nUnscaledExtentsLeft * 4); + for (sal_Int32 x = nUnscaledExtentsLeft; x < nUnscaledExtentsRight; ++x) { - unsigned char* true_row = target_surface_data + (nStride * y); - unsigned char* xor_row = xor_surface_data + (nStride * y); - unsigned char* true_data = true_row + (nUnscaledExtentsLeft * 4); - unsigned char* xor_data = xor_row + (nUnscaledExtentsLeft * 4); - for (sal_Int32 x = nUnscaledExtentsLeft; x < nUnscaledExtentsRight; ++x) - { - sal_uInt8 a = true_data[SVP_CAIRO_ALPHA]; - sal_uInt8 xor_a = xor_data[SVP_CAIRO_ALPHA]; + sal_uInt8 a = true_data[SVP_CAIRO_ALPHA]; + sal_uInt8 xor_a = xor_data[SVP_CAIRO_ALPHA]; #if ENABLE_WASM_STRIP_PREMULTIPLY - sal_uInt8 b = vcl::bitmap::unpremultiply(a, true_data[SVP_CAIRO_BLUE]) - ^ vcl::bitmap::unpremultiply(xor_a, xor_data[SVP_CAIRO_BLUE]); - sal_uInt8 g = vcl::bitmap::unpremultiply(a, true_data[SVP_CAIRO_GREEN]) - ^ vcl::bitmap::unpremultiply(xor_a, xor_data[SVP_CAIRO_GREEN]); - sal_uInt8 r = vcl::bitmap::unpremultiply(a, true_data[SVP_CAIRO_RED]) - ^ vcl::bitmap::unpremultiply(xor_a, xor_data[SVP_CAIRO_RED]); - true_data[SVP_CAIRO_BLUE] = vcl::bitmap::premultiply(a, b); - true_data[SVP_CAIRO_GREEN] = vcl::bitmap::premultiply(a, g); - true_data[SVP_CAIRO_RED] = vcl::bitmap::premultiply(a, r); + sal_uInt8 b = vcl::bitmap::unpremultiply(a, true_data[SVP_CAIRO_BLUE]) + ^ vcl::bitmap::unpremultiply(xor_a, xor_data[SVP_CAIRO_BLUE]); + sal_uInt8 g = vcl::bitmap::unpremultiply(a, true_data[SVP_CAIRO_GREEN]) + ^ vcl::bitmap::unpremultiply(xor_a, xor_data[SVP_CAIRO_GREEN]); + sal_uInt8 r = vcl::bitmap::unpremultiply(a, true_data[SVP_CAIRO_RED]) + ^ vcl::bitmap::unpremultiply(xor_a, xor_data[SVP_CAIRO_RED]); + true_data[SVP_CAIRO_BLUE] = vcl::bitmap::premultiply(a, b); + true_data[SVP_CAIRO_GREEN] = vcl::bitmap::premultiply(a, g); + true_data[SVP_CAIRO_RED] = vcl::bitmap::premultiply(a, r); #else - sal_uInt8 b = unpremultiply_table[a][true_data[SVP_CAIRO_BLUE]] - ^ unpremultiply_table[xor_a][xor_data[SVP_CAIRO_BLUE]]; - sal_uInt8 g = unpremultiply_table[a][true_data[SVP_CAIRO_GREEN]] - ^ unpremultiply_table[xor_a][xor_data[SVP_CAIRO_GREEN]]; - sal_uInt8 r = unpremultiply_table[a][true_data[SVP_CAIRO_RED]] - ^ unpremultiply_table[xor_a][xor_data[SVP_CAIRO_RED]]; - true_data[SVP_CAIRO_BLUE] = premultiply_table[a][b]; - true_data[SVP_CAIRO_GREEN] = premultiply_table[a][g]; - true_data[SVP_CAIRO_RED] = premultiply_table[a][r]; + sal_uInt8 b = unpremultiply_table[a][true_data[SVP_CAIRO_BLUE]] + ^ unpremultiply_table[xor_a][xor_data[SVP_CAIRO_BLUE]]; + sal_uInt8 g = unpremultiply_table[a][true_data[SVP_CAIRO_GREEN]] + ^ unpremultiply_table[xor_a][xor_data[SVP_CAIRO_GREEN]]; + sal_uInt8 r = unpremultiply_table[a][true_data[SVP_CAIRO_RED]] + ^ unpremultiply_table[xor_a][xor_data[SVP_CAIRO_RED]]; + true_data[SVP_CAIRO_BLUE] = premultiply_table[a][b]; + true_data[SVP_CAIRO_GREEN] = premultiply_table[a][g]; + true_data[SVP_CAIRO_RED] = premultiply_table[a][r]; #endif - true_data += 4; - xor_data += 4; - } + true_data += 4; + xor_data += 4; } - cairo_surface_mark_dirty(target_surface); - - if (target_surface != m_pSurface) - { - cairo_t* copycr = cairo_create(m_pSurface); - //unlikely case we couldn't use m_pSurface directly, copy contents - //back from image surface - cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - nExtentsLeft, - nExtentsBottom - nExtentsTop); - cairo_set_source_surface(copycr, target_surface, 0, 0); - cairo_paint(copycr); - cairo_destroy(copycr); - cairo_surface_destroy(target_surface); - } - - cairo_surface_destroy(surface); } + cairo_surface_mark_dirty(target_surface); - cairo_destroy(cr); // unref - - DamageHandler* pDamage - = static_cast<DamageHandler*>(cairo_surface_get_user_data(m_pSurface, getDamageKey())); - - if (pDamage) + if (target_surface != m_pSurface) { - pDamage->damaged(pDamage->handle, nExtentsLeft, nExtentsTop, nExtentsRight - nExtentsLeft, - nExtentsBottom - nExtentsTop); + cairo_t* copycr = cairo_create(m_pSurface); + //unlikely case we couldn't use m_pSurface directly, copy contents + //back from image surface + cairo_rectangle(copycr, nExtentsLeft, nExtentsTop, nExtentsRight - nExtentsLeft, + nExtentsBottom - nExtentsTop); + cairo_set_source_surface(copycr, target_surface, 0, 0); + cairo_paint(copycr); + cairo_destroy(copycr); + cairo_surface_destroy(target_surface); } + + cairo_surface_destroy(surface); } cairo_t* CairoCommon::createTmpCompatibleCairoContext() const diff --git a/vcl/inc/headless/CairoCommon.hxx b/vcl/inc/headless/CairoCommon.hxx index 476b031c451b..3fc0144ef34a 100644 --- a/vcl/inc/headless/CairoCommon.hxx +++ b/vcl/inc/headless/CairoCommon.hxx @@ -169,6 +169,7 @@ struct VCL_DLLPUBLIC CairoCommon cairo_t* getCairoContext(bool bXorModeAllowed, bool bAntiAlias) const; void releaseCairoContext(cairo_t* cr, bool bXorModeAllowed, const basegfx::B2DRange& rExtents) const; + cairo_t* createTmpCompatibleCairoContext() const; void applyColor(cairo_t* cr, Color rColor, double fTransparency = 0.0); @@ -198,6 +199,11 @@ struct VCL_DLLPUBLIC CairoCommon void invert(const basegfx::B2DPolygon& rPoly, SalInvert nFlags, bool bAntiAlias); static cairo_surface_t* createCairoSurface(const BitmapBuffer* pBuffer); + +private: + void doXorOnRelease(sal_Int32 nExtentsLeft, sal_Int32 nExtentsTop, sal_Int32 nExtentsRight, + sal_Int32 nExtentsBottom, cairo_surface_t* const surface, + sal_Int32 nWidth) const; }; class SurfaceHelper |