summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
authorNoel Grandin <noel.grandin@collabora.co.uk>2022-11-12 14:53:46 +0200
committerNoel Grandin <noel.grandin@collabora.co.uk>2022-11-14 17:24:36 +0100
commit95dceefe207da45bd955d07a88bf7a956b274081 (patch)
tree0cf2b732fb2c7d2ae31f9a28f87ce7d6364fbfc3 /vcl
parentc3ca46945aa498907a938e33b2df7937f45199db (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.cxx194
-rw-r--r--vcl/inc/headless/CairoCommon.hxx6
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