diff options
author | Caolán McNamara <caolanm@redhat.com> | 2018-06-01 12:56:39 +0100 |
---|---|---|
committer | Caolán McNamara <caolanm@redhat.com> | 2018-06-02 18:02:20 +0200 |
commit | 40b7062ffa972ae0a8f51da0b257becfab749d53 (patch) | |
tree | 704fdfa33ab9e82a7974e9e3a76d3440606ecaba | |
parent | 3a8eb264b912b76a12af7a94b24b5ac6acc2347d (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.cxx | 47 | ||||
-rw-r--r-- | vcl/inc/headless/svpgdi.hxx | 11 | ||||
-rw-r--r-- | vcl/unx/generic/gdi/salgdi.cxx | 127 |
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; |