|
|
2dcfccb |
From f940d97bfe93d2c5adc97cde64100f01240f7dfa Mon Sep 17 00:00:00 2001
|
|
|
2dcfccb |
From: =?UTF-8?q?Caol=C3=A1n=20McNamara?= <caolanm@redhat.com>
|
|
|
2dcfccb |
Date: Fri, 20 Nov 2015 11:18:52 +0000
|
|
|
2dcfccb |
Subject: [PATCH] Resolves: tdf#92687 implement drawPolyPolygon via cairo
|
|
|
2dcfccb |
|
|
|
2dcfccb |
modeled on the quartz impl
|
|
|
2dcfccb |
|
|
|
2dcfccb |
(cherry picked from commit 742da70e6dd2407641835cbcac54b09aeddcb9db)
|
|
|
2dcfccb |
|
|
|
2dcfccb |
Change-Id: I2f6776c14c7350954932df2bffcca36172f13473
|
|
|
2dcfccb |
---
|
|
|
2dcfccb |
vcl/headless/svpgdi.cxx | 173 ++++++++++++++++++++++++++++++++++++++++++------
|
|
|
2dcfccb |
1 file changed, 151 insertions(+), 22 deletions(-)
|
|
|
2dcfccb |
|
|
|
2dcfccb |
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
|
|
|
2dcfccb |
index ed2fe18..effbeda 100644
|
|
|
2dcfccb |
--- a/vcl/headless/svpgdi.cxx
|
|
|
2dcfccb |
+++ b/vcl/headless/svpgdi.cxx
|
|
|
2dcfccb |
@@ -28,6 +28,7 @@
|
|
|
2dcfccb |
#include <basegfx/range/b2drange.hxx>
|
|
|
2dcfccb |
#include <basegfx/range/b2ibox.hxx>
|
|
|
2dcfccb |
#include <basegfx/polygon/b2dpolypolygon.hxx>
|
|
|
2dcfccb |
+#include <basegfx/polygon/b2dpolypolygontools.hxx>
|
|
|
2dcfccb |
#include <basegfx/polygon/b2dpolygon.hxx>
|
|
|
2dcfccb |
#include <basegfx/polygon/b2dpolygontools.hxx>
|
|
|
2dcfccb |
#include <basebmp/scanlineformats.hxx>
|
|
|
2dcfccb |
@@ -134,6 +135,27 @@ void SvpSalGraphics::clipRegion(cairo_t* cr)
|
|
|
2dcfccb |
cairo_clip(cr);
|
|
|
2dcfccb |
}
|
|
|
2dcfccb |
}
|
|
|
2dcfccb |
+namespace
|
|
|
2dcfccb |
+{
|
|
|
2dcfccb |
+ cairo_rectangle_int_t getFillDamage(cairo_t* cr)
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ cairo_rectangle_int_t extents;
|
|
|
2dcfccb |
+ double x1, y1, x2, y2;
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_clip_extents(cr, &x1, &y1, &x2, &y2;;
|
|
|
2dcfccb |
+ extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
|
|
|
2dcfccb |
+ cairo_region_t *region = cairo_region_create_rectangle(&extents);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_fill_extents(cr, &x1, &y1, &x2, &y2;;
|
|
|
2dcfccb |
+ extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
|
|
|
2dcfccb |
+ cairo_region_intersect_rectangle(region, &extents);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_region_get_extents(region, &extents);
|
|
|
2dcfccb |
+ cairo_region_destroy(region);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ return extents;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+}
|
|
|
2dcfccb |
|
|
|
2dcfccb |
#endif
|
|
|
2dcfccb |
|
|
|
2dcfccb |
@@ -144,7 +166,10 @@ bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight,
|
|
|
2dcfccb |
#if ENABLE_CAIRO_CANVAS
|
|
|
2dcfccb |
#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
|
|
|
2dcfccb |
if (m_bUseLineColor || !m_bUseFillColor)
|
|
|
2dcfccb |
- return bRet;
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawAlphaRect case");
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
|
|
|
2dcfccb |
cairo_t* cr = createCairoContext(m_aDevice);
|
|
|
2dcfccb |
if (!cr)
|
|
|
2dcfccb |
@@ -165,24 +190,10 @@ bool SvpSalGraphics::drawAlphaRect(long nX, long nY, long nWidth, long nHeight,
|
|
|
2dcfccb |
fTransparency);
|
|
|
2dcfccb |
cairo_rectangle(cr, nX, nY, nWidth, nHeight);
|
|
|
2dcfccb |
|
|
|
2dcfccb |
-
|
|
|
2dcfccb |
cairo_rectangle_int_t extents;
|
|
|
2dcfccb |
basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker());
|
|
|
2dcfccb |
if (xDamageTracker)
|
|
|
2dcfccb |
- {
|
|
|
2dcfccb |
- double x1, y1, x2, y2;
|
|
|
2dcfccb |
-
|
|
|
2dcfccb |
- cairo_clip_extents(cr, &x1, &y1, &x2, &y2;;
|
|
|
2dcfccb |
- extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
|
|
|
2dcfccb |
- cairo_region_t *region = cairo_region_create_rectangle(&extents);
|
|
|
2dcfccb |
-
|
|
|
2dcfccb |
- cairo_fill_extents(cr, &x1, &y1, &x2, &y2;;
|
|
|
2dcfccb |
- extents.x = x1, extents.y = x2, extents.width = x2-x1, extents.height = y2-y1;
|
|
|
2dcfccb |
- cairo_region_intersect_rectangle(region, &extents);
|
|
|
2dcfccb |
-
|
|
|
2dcfccb |
- cairo_region_get_extents(region, &extents);
|
|
|
2dcfccb |
- cairo_region_destroy(region);
|
|
|
2dcfccb |
- }
|
|
|
2dcfccb |
+ extents = getFillDamage(cr);
|
|
|
2dcfccb |
|
|
|
2dcfccb |
cairo_fill(cr);
|
|
|
2dcfccb |
|
|
|
2dcfccb |
@@ -644,10 +655,118 @@ bool SvpSalGraphics::drawPolyPolygonBezier( sal_uInt32,
|
|
|
2dcfccb |
return false;
|
|
|
2dcfccb |
}
|
|
|
2dcfccb |
|
|
|
2dcfccb |
-bool SvpSalGraphics::drawPolyPolygon( const basegfx::B2DPolyPolygon&, double /*fTransparency*/ )
|
|
|
2dcfccb |
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
|
|
|
2dcfccb |
+static void AddPolygonToPath(cairo_t* cr, const basegfx::B2DPolygon& rPolygon, bool bClosePath)
|
|
|
2dcfccb |
{
|
|
|
2dcfccb |
- // TODO: maybe BaseBmp can draw B2DPolyPolygons directly
|
|
|
2dcfccb |
- return false;
|
|
|
2dcfccb |
+ // short circuit if there is nothing to do
|
|
|
2dcfccb |
+ const int nPointCount = rPolygon.count();
|
|
|
2dcfccb |
+ if( nPointCount <= 0 )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ return;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ const bool bHasCurves = rPolygon.areControlPointsUsed();
|
|
|
2dcfccb |
+ for( int nPointIdx = 0, nPrevIdx = 0;; nPrevIdx = nPointIdx++ )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ int nClosedIdx = nPointIdx;
|
|
|
2dcfccb |
+ if( nPointIdx >= nPointCount )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ // prepare to close last curve segment if needed
|
|
|
2dcfccb |
+ if( bClosePath && (nPointIdx == nPointCount) )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ nClosedIdx = 0;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+ else
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ break;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ basegfx::B2DPoint aPoint = rPolygon.getB2DPoint( nClosedIdx );
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ if( !nPointIdx )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ // first point => just move there
|
|
|
2dcfccb |
+ cairo_move_to(cr, aPoint.getX(), aPoint.getY());
|
|
|
2dcfccb |
+ continue;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ bool bPendingCurve = false;
|
|
|
2dcfccb |
+ if( bHasCurves )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ bPendingCurve = rPolygon.isNextControlPointUsed( nPrevIdx );
|
|
|
2dcfccb |
+ bPendingCurve |= rPolygon.isPrevControlPointUsed( nClosedIdx );
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ if( !bPendingCurve ) // line segment
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ cairo_line_to(cr, aPoint.getX(), aPoint.getY());
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+ else // cubic bezier segment
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ basegfx::B2DPoint aCP1 = rPolygon.getNextControlPoint( nPrevIdx );
|
|
|
2dcfccb |
+ basegfx::B2DPoint aCP2 = rPolygon.getPrevControlPoint( nClosedIdx );
|
|
|
2dcfccb |
+ cairo_curve_to(cr, aCP1.getX(), aCP1.getY(), aCP2.getX(), aCP2.getY(),
|
|
|
2dcfccb |
+ aPoint.getX(), aPoint.getY());
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ if( bClosePath )
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ cairo_close_path(cr);
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+}
|
|
|
2dcfccb |
+#endif
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+bool SvpSalGraphics::drawPolyPolygon(const basegfx::B2DPolyPolygon& rPolyPoly, double fTransparency)
|
|
|
2dcfccb |
+{
|
|
|
2dcfccb |
+ bool bRet = false;
|
|
|
2dcfccb |
+ (void)rPolyPoly; (void)fTransparency;
|
|
|
2dcfccb |
+#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)
|
|
|
2dcfccb |
+ if (m_bUseLineColor || !m_bUseFillColor)
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ SAL_WARN("vcl.gdi", "unsupported SvpSalGraphics::drawPolyPolygon case");
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_t* cr = createCairoContext(m_aDevice);
|
|
|
2dcfccb |
+ if (!cr)
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ if (!m_aDevice->isTopDown())
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ cairo_scale(cr, 1, -1.0);
|
|
|
2dcfccb |
+ cairo_translate(cr, 0.0, -m_aDevice->getSize().getY());
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ clipRegion(cr);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_set_source_rgba(cr, m_aFillColor.getRed()/255.0,
|
|
|
2dcfccb |
+ m_aFillColor.getGreen()/255.0,
|
|
|
2dcfccb |
+ m_aFillColor.getBlue()/255.0,
|
|
|
2dcfccb |
+ 1.0-fTransparency);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ for (const basegfx::B2DPolygon* pPoly = rPolyPoly.begin(); pPoly != rPolyPoly.end(); ++pPoly)
|
|
|
2dcfccb |
+ AddPolygonToPath(cr, *pPoly, true);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_rectangle_int_t extents;
|
|
|
2dcfccb |
+ basebmp::IBitmapDeviceDamageTrackerSharedPtr xDamageTracker(m_aDevice->getDamageTracker());
|
|
|
2dcfccb |
+ if (xDamageTracker)
|
|
|
2dcfccb |
+ extents = getFillDamage(cr);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_fill(cr);
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ cairo_surface_flush(cairo_get_target(cr));
|
|
|
2dcfccb |
+ cairo_destroy(cr); // unref
|
|
|
2dcfccb |
+
|
|
|
2dcfccb |
+ if (xDamageTracker)
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ xDamageTracker->damaged(basegfx::B2IBox(extents.x, extents.y, extents.x + extents.width,
|
|
|
2dcfccb |
+ extents.y + extents.height));
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+ bRet = true;
|
|
|
2dcfccb |
+#endif
|
|
|
2dcfccb |
+ return bRet;
|
|
|
2dcfccb |
}
|
|
|
2dcfccb |
|
|
|
2dcfccb |
void SvpSalGraphics::copyArea( long nDestX,
|
|
|
2dcfccb |
@@ -883,9 +1002,19 @@ SystemGraphicsData SvpSalGraphics::GetGraphicsData() const
|
|
|
2dcfccb |
bool SvpSalGraphics::supportsOperation(OutDevSupportType eType) const
|
|
|
2dcfccb |
{
|
|
|
2dcfccb |
#if ENABLE_CAIRO_CANVAS
|
|
|
2dcfccb |
- return m_aDrawMode != basebmp::DrawMode_XOR &&
|
|
|
2dcfccb |
- OutDevSupport_TransparentRect == eType &&
|
|
|
2dcfccb |
- isCairoCompatible(m_aDevice);
|
|
|
2dcfccb |
+ if (m_aDrawMode == basebmp::DrawMode_XOR)
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
+ if (!isCairoCompatible(m_aDevice))
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
+ switch (eType)
|
|
|
2dcfccb |
+ {
|
|
|
2dcfccb |
+ case OutDevSupport_TransparentRect:
|
|
|
2dcfccb |
+ case OutDevSupport_B2DDraw:
|
|
|
2dcfccb |
+ return true;
|
|
|
2dcfccb |
+ case OutDevSupport_B2DClip: //what's this one ?
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
+ }
|
|
|
2dcfccb |
+ return false;
|
|
|
2dcfccb |
#else
|
|
|
2dcfccb |
(void)eType;
|
|
|
2dcfccb |
return false;
|
|
|
2dcfccb |
--
|
|
|
2dcfccb |
2.5.0
|
|
|
2dcfccb |
|