summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2018-06-01 12:56:39 +0100
committerCaolán McNamara <caolanm@redhat.com>2018-06-02 18:02:20 +0200
commit40b7062ffa972ae0a8f51da0b257becfab749d53 (patch)
tree704fdfa33ab9e82a7974e9e3a76d3440606ecaba
parent3a8eb264b912b76a12af7a94b24b5ac6acc2347d (diff)
share the cairo polyline drawing code
Change-Id: I35c04f33f3a87962a3d0e731213228d5b2e8590e Reviewed-on: https://gerrit.libreoffice.org/55179 Tested-by: Jenkins <ci@libreoffice.org> Reviewed-by: Caolán McNamara <caolanm@redhat.com> Tested-by: Caolán McNamara <caolanm@redhat.com>
-rw-r--r--vcl/headless/svpgdi.cxx47
-rw-r--r--vcl/inc/headless/svpgdi.hxx11
-rw-r--r--vcl/unx/generic/gdi/salgdi.cxx127
3 files changed, 47 insertions, 138 deletions
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 553b43ed9f6b..8bc15fb861dc 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -875,7 +875,10 @@ void SvpSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
releaseCairoContext(cr, false, extents);
}
-bool SvpSalGraphics::drawPolyLine(
+basegfx::B2DRange SvpSalGraphics::drawPolyLine(
+ cairo_t* cr,
+ const Color& rLineColor,
+ bool bAntiAliasB2DDraw,
const basegfx::B2DPolygon& rPolyLine,
double fTransparency,
const basegfx::B2DVector& rLineWidths,
@@ -883,18 +886,8 @@ bool SvpSalGraphics::drawPolyLine(
css::drawing::LineCap eLineCap,
double fMiterMinimumAngle)
{
- // short circuit if there is nothing to do
- const int nPointCount = rPolyLine.count();
- if (nPointCount <= 0)
- {
- return true;
- }
-
const bool bNoJoin = (basegfx::B2DLineJoin::NONE == eLineJoin && basegfx::fTools::more(rLineWidths.getX(), 0.0));
- cairo_t* cr = getCairoContext(false);
- clipRegion(cr);
-
// setup line attributes
cairo_line_join_t eCairoLineJoin = CAIRO_LINE_JOIN_MITER;
switch (eLineJoin)
@@ -936,9 +929,9 @@ bool SvpSalGraphics::drawPolyLine(
}
}
- cairo_set_source_rgba(cr, m_aLineColor.GetRed()/255.0,
- m_aLineColor.GetGreen()/255.0,
- m_aLineColor.GetBlue()/255.0,
+ cairo_set_source_rgba(cr, rLineColor.GetRed()/255.0,
+ rLineColor.GetGreen()/255.0,
+ rLineColor.GetBlue()/255.0,
1.0-fTransparency);
cairo_set_line_join(cr, eCairoLineJoin);
@@ -951,12 +944,13 @@ bool SvpSalGraphics::drawPolyLine(
if (!bNoJoin)
{
- AddPolygonToPath(cr, rPolyLine, rPolyLine.isClosed(), !getAntiAliasB2DDraw(), true);
+ AddPolygonToPath(cr, rPolyLine, rPolyLine.isClosed(), !bAntiAliasB2DDraw, true);
extents = getClippedStrokeDamage(cr);
cairo_stroke(cr);
}
else
{
+ const int nPointCount = rPolyLine.count();
// emulate rendering::PathJoinType::NONE by painting single edges
const sal_uInt32 nEdgeCount(rPolyLine.isClosed() ? nPointCount : nPointCount - 1);
basegfx::B2DPolygon aEdge;
@@ -970,7 +964,7 @@ bool SvpSalGraphics::drawPolyLine(
aEdge.setNextControlPoint(0, rPolyLine.getNextControlPoint(i % nPointCount));
aEdge.setPrevControlPoint(1, rPolyLine.getPrevControlPoint(nNextIndex));
- AddPolygonToPath(cr, aEdge, false, !getAntiAliasB2DDraw(), true);
+ AddPolygonToPath(cr, aEdge, false, !bAntiAliasB2DDraw, true);
extents.expand(getStrokeDamage(cr));
@@ -983,6 +977,27 @@ bool SvpSalGraphics::drawPolyLine(
extents.intersect(getClipBox(cr));
}
+ return extents;
+}
+
+bool SvpSalGraphics::drawPolyLine(
+ const basegfx::B2DPolygon& rPolyLine,
+ double fTransparency,
+ const basegfx::B2DVector& rLineWidths,
+ basegfx::B2DLineJoin eLineJoin,
+ css::drawing::LineCap eLineCap,
+ double fMiterMinimumAngle)
+{
+ // short circuit if there is nothing to do
+ if (rPolyLine.count() <= 0)
+ return true;
+
+ cairo_t* cr = getCairoContext(false);
+ clipRegion(cr);
+
+ basegfx::B2DRange extents = drawPolyLine(cr, m_aLineColor, getAntiAliasB2DDraw(), rPolyLine,
+ fTransparency, rLineWidths, eLineJoin, eLineCap, fMiterMinimumAngle);
+
releaseCairoContext(cr, false, extents);
return true;
diff --git a/vcl/inc/headless/svpgdi.hxx b/vcl/inc/headless/svpgdi.hxx
index 25e828e8618c..37ae2822bf53 100644
--- a/vcl/inc/headless/svpgdi.hxx
+++ b/vcl/inc/headless/svpgdi.hxx
@@ -96,6 +96,17 @@ public:
cairo_surface_t* getSurface() const { return m_pSurface; }
static cairo_user_data_key_t* getDamageKey();
+ static basegfx::B2DRange drawPolyLine(
+ cairo_t* cr,
+ const Color& rLineColor,
+ bool bAntiAliasB2DDraw,
+ const basegfx::B2DPolygon& rPolyLine,
+ double fTransparency,
+ const basegfx::B2DVector& rLineWidths,
+ basegfx::B2DLineJoin eLineJoin,
+ css::drawing::LineCap eLineCap,
+ double fMiterMinimumAngle);
+
private:
void invert(const basegfx::B2DPolygon &rPoly, SalInvert nFlags);
void copySource(const SalTwoRect& rTR, cairo_surface_t* source);
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index bc31846f0159..dd09e8d3c62b 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -39,6 +39,8 @@
#include <basegfx/polygon/b2dtrapezoid.hxx>
#include <basegfx/curve/b2dcubicbezier.hxx>
+#include <headless/svpgdi.hxx>
+
#include <vcl/jobdata.hxx>
#include <vcl/sysdata.hxx>
#include <vcl/virdev.hxx>
@@ -732,129 +734,10 @@ bool X11SalGraphics::drawPolyLine(
{
cairo_t* cr = getCairoContext();
clipRegion(cr);
- cairo_line_join_t eCairoLineJoin(CAIRO_LINE_JOIN_MITER);
- bool bNoJoin(false);
-
- switch(eLineJoin)
- {
- case basegfx::B2DLineJoin::Bevel:
- eCairoLineJoin = CAIRO_LINE_JOIN_BEVEL;
- break;
- case basegfx::B2DLineJoin::Round:
- eCairoLineJoin = CAIRO_LINE_JOIN_ROUND;
- break;
- case basegfx::B2DLineJoin::NONE:
- bNoJoin = true;
- SAL_FALLTHROUGH;
- case basegfx::B2DLineJoin::Miter:
- eCairoLineJoin = CAIRO_LINE_JOIN_MITER;
- break;
- }
-
- // setup cap attribute
- cairo_line_cap_t eCairoLineCap(CAIRO_LINE_CAP_BUTT);
- switch(eLineCap)
- {
- default: // css::drawing::LineCap_BUTT:
- {
- eCairoLineCap = CAIRO_LINE_CAP_BUTT;
- break;
- }
- case css::drawing::LineCap_ROUND:
- {
- eCairoLineCap = CAIRO_LINE_CAP_ROUND;
- break;
- }
- case css::drawing::LineCap_SQUARE:
- {
- eCairoLineCap = CAIRO_LINE_CAP_SQUARE;
- break;
- }
- }
-
- cairo_set_source_rgba(cr,
- mnPenColor.GetRed()/255.0,
- mnPenColor.GetGreen()/255.0,
- mnPenColor.GetBlue()/255.0,
- 1.0 - fTransparency);
- cairo_set_line_join(cr, eCairoLineJoin);
- cairo_set_line_cap(cr, eCairoLineCap);
- cairo_set_line_width(cr, (fabs(rLineWidth.getX()) + fabs(rLineWidth.getY())) * 0.5);
-
- if(CAIRO_LINE_JOIN_MITER == eCairoLineJoin)
- {
- cairo_set_miter_limit(cr, 15.0);
- }
-
- const sal_uInt32 nEdgeCount(rPolygon.isClosed() ? nPointCount : nPointCount - 1);
- if(nEdgeCount)
- {
- const bool bSnapPoints(!getAntiAliasB2DDraw());
- static basegfx::B2DHomMatrix aHalfPointTransform(basegfx::utils::createTranslateB2DHomMatrix(0.5, 0.5));
- basegfx::B2DCubicBezier aEdge;
- basegfx::B2DPoint aStart;
-
- for(sal_uInt32 i = 0; i < nEdgeCount; ++i)
- {
- rPolygon.getBezierSegment(i, aEdge);
-
- aEdge.transform(aHalfPointTransform);
-
- if(bSnapPoints)
- {
- aEdge.fround();
- }
-
- if(!i || bNoJoin)
- {
- aStart = aEdge.getStartPoint();
- cairo_move_to(cr, aStart.getX(), aStart.getY());
- }
-
- const basegfx::B2DPoint aEnd(aEdge.getEndPoint());
-
- if(aEdge.isBezier())
- {
- basegfx::B2DPoint aCP1(aEdge.getControlPointA());
- basegfx::B2DPoint aCP2(aEdge.getControlPointB());
-
- // tdf#99165 cairo has problems in creating the evtl. needed
- // miter graphics (and maybe others) when empty control points
- // are used, so fallback to the mathematical 'default' control
- // points in that case
- // tdf#101026 The 1st attempt to create a mathematically correct replacement control
- // vector was wrong. Best alternative is one as close as possible which means short.
- if (aStart.equal(aCP1))
- {
- aCP1 = aStart + ((aCP2 - aStart) * 0.0005);
- }
-
- if(aEnd.equal(aCP2))
- {
- aCP2 = aEnd + ((aCP1 - aEnd) * 0.0005);
- }
-
- cairo_curve_to(cr,
- aCP1.getX(), aCP1.getY(),
- aCP2.getX(), aCP2.getY(),
- aEnd.getX(), aEnd.getY());
- }
- else
- {
- cairo_line_to(cr, aEnd.getX(), aEnd.getY());
- }
-
- aStart = aEnd;
- }
-
- if(rPolygon.isClosed() && !bNoJoin)
- {
- cairo_close_path(cr);
- }
-
- cairo_stroke(cr);
- }
+ SvpSalGraphics::drawPolyLine(cr, mnPenColor, getAntiAliasB2DDraw(),
+ rPolygon, fTransparency, rLineWidth,
+ eLineJoin, eLineCap, fMiterMinimumAngle);
releaseCairoContext(cr);
return true;