diff options
author | Armin Le Grand (Collabora) <Armin.Le.Grand@me.com> | 2020-02-06 18:53:12 +0100 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@me.com> | 2020-02-07 18:49:18 +0100 |
commit | 5f61c9fe99ac93087b898adddbb4d4733f1fcd07 (patch) | |
tree | 50e5e98702db8a12eba1e4f5dc730e76db2cca1e /vcl/headless | |
parent | 1fb4887613f2487be6081dd62c4df30f6170e2c0 (diff) |
tdf#130478 Enhance Dashed line drawing on all systems
For more info and explanation including state of process
information and discussion(s) see task please.
Adding corrections for gerrit build
Change-Id: Ie10fb8093a86459dee80db5ab4355b47e46c1f8c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/88130
Tested-by: Jenkins
Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
Diffstat (limited to 'vcl/headless')
-rw-r--r-- | vcl/headless/svpgdi.cxx | 139 |
1 files changed, 101 insertions, 38 deletions
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx index 0d4a366fc4f1..80a24fad54f9 100644 --- a/vcl/headless/svpgdi.cxx +++ b/vcl/headless/svpgdi.cxx @@ -20,6 +20,8 @@ #include <config_features.h> #include <memory> +#include <numeric> + #ifndef IOS #include <headless/svpgdi.hxx> #endif @@ -783,6 +785,7 @@ void SvpSalGraphics::drawPolyLine(sal_uInt32 nPoints, const SalPoint* pPtAry) aPoly, 0.0, basegfx::B2DVector(1.0, 1.0), + nullptr, // MM01 basegfx::B2DLineJoin::Miter, css::drawing::LineCap_BUTT, basegfx::deg2rad(15.0) /*default*/, @@ -1064,6 +1067,7 @@ private: // need to be compared with to check for data validity bool mbNoJoin; bool mbAntiAliasB2DDraw; + std::vector< double > maStroke; public: SystemDependentData_CairoPath( @@ -1071,12 +1075,15 @@ public: size_t nSizeMeasure, cairo_t* cr, bool bNoJoin, - bool bAntiAliasB2DDraw); + bool bAntiAliasB2DDraw, + const std::vector< double >* pStroke); // MM01 virtual ~SystemDependentData_CairoPath() override; + // read access cairo_path_t* getCairoPath() { return mpCairoPath; } bool getNoJoin() const { return mbNoJoin; } bool getAntiAliasB2DDraw() const { return mbAntiAliasB2DDraw; } + const std::vector< double >& getStroke() const { return maStroke; } virtual sal_Int64 estimateUsageInBytes() const override; }; @@ -1088,17 +1095,24 @@ SystemDependentData_CairoPath::SystemDependentData_CairoPath( size_t nSizeMeasure, cairo_t* cr, bool bNoJoin, - bool bAntiAliasB2DDraw) + bool bAntiAliasB2DDraw, + const std::vector< double >* pStroke) : basegfx::SystemDependentData(rSystemDependentDataManager), mpCairoPath(nullptr), mbNoJoin(bNoJoin), - mbAntiAliasB2DDraw(bAntiAliasB2DDraw) + mbAntiAliasB2DDraw(bAntiAliasB2DDraw), + maStroke() { // tdf#129845 only create a copy of the path when nSizeMeasure is // bigger than some decent threshold if(nSizeMeasure > 50) { mpCairoPath = cairo_copy_path(cr); + + if(nullptr != pStroke) + { + maStroke = *pStroke; + } } } @@ -1134,7 +1148,8 @@ bool SvpSalGraphics::drawPolyLine( const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolygon& rPolyLine, double fTransparency, - const basegfx::B2DVector& rLineWidths, + const basegfx::B2DVector& rLineWidth, + const std::vector< double >* pStroke, // MM01 basegfx::B2DLineJoin eLineJoin, css::drawing::LineCap eLineCap, double fMiterMinimumAngle, @@ -1165,7 +1180,8 @@ bool SvpSalGraphics::drawPolyLine( rObjectToDevice, rPolyLine, fTransparency, - rLineWidths, + rLineWidth, + pStroke, // MM01 eLineJoin, eLineCap, fMiterMinimumAngle, @@ -1184,7 +1200,8 @@ bool SvpSalGraphics::drawPolyLine( const basegfx::B2DHomMatrix& rObjectToDevice, const basegfx::B2DPolygon& rPolyLine, double fTransparency, - const basegfx::B2DVector& rLineWidths, + const basegfx::B2DVector& rLineWidth, + const std::vector< double >* pStroke, // MM01 basegfx::B2DLineJoin eLineJoin, css::drawing::LineCap eLineCap, double fMiterMinimumAngle, @@ -1197,10 +1214,10 @@ bool SvpSalGraphics::drawPolyLine( } // need to check/handle LineWidth when ObjectToDevice transformation is used - basegfx::B2DVector aLineWidths(rLineWidths); + basegfx::B2DVector aLineWidth(rLineWidth); const bool bObjectToDeviceIsIdentity(rObjectToDevice.isIdentity()); - const basegfx::B2DVector aDeviceLineWidths(bObjectToDeviceIsIdentity ? rLineWidths : rObjectToDevice * rLineWidths); - const bool bCorrectLineWidth(!bObjectToDeviceIsIdentity && aDeviceLineWidths.getX() < 1.0 && aLineWidths.getX() >= 1.0); + const basegfx::B2DVector aDeviceLineWidth(bObjectToDeviceIsIdentity ? rLineWidth : rObjectToDevice * rLineWidth); + const bool bCorrectLineWidth(!bObjectToDeviceIsIdentity && aDeviceLineWidth.getX() < 1.0 && aLineWidth.getX() >= 1.0); // on-demand inverse of ObjectToDevice transformation basegfx::B2DHomMatrix aObjectToDeviceInv; @@ -1214,12 +1231,11 @@ bool SvpSalGraphics::drawPolyLine( } // calculate-back logical LineWidth for a hairline - aLineWidths = aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0); + aLineWidth = aObjectToDeviceInv * basegfx::B2DVector(1.0, 1.0); } // PixelOffset used: Need to reflect in linear transformation cairo_matrix_t aMatrix; - basegfx::B2DHomMatrix aDamageMatrix(basegfx::utils::createTranslateB2DHomMatrix(0.5, 0.5)); if (bObjectToDeviceIsIdentity) @@ -1245,8 +1261,6 @@ bool SvpSalGraphics::drawPolyLine( // set linear transformation cairo_set_matrix(cr, &aMatrix); - const bool bNoJoin((basegfx::B2DLineJoin::NONE == eLineJoin && basegfx::fTools::more(aLineWidths.getX(), 0.0))); - // setup line attributes cairo_line_join_t eCairoLineJoin = CAIRO_LINE_JOIN_MITER; switch (eLineJoin) @@ -1297,13 +1311,35 @@ bool SvpSalGraphics::drawPolyLine( cairo_set_line_join(cr, eCairoLineJoin); cairo_set_line_cap(cr, eCairoLineCap); - cairo_set_line_width(cr, aLineWidths.getX()); + cairo_set_line_width(cr, aLineWidth.getX()); cairo_set_miter_limit(cr, fMiterLimit); // try to access buffered data std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath( rPolyLine.getSystemDependentData<SystemDependentData_CairoPath>()); + // MM01 need to do line dashing as fallback stuff here now + const double fDotDashLength(nullptr != pStroke ? std::accumulate(pStroke->begin(), pStroke->end(), 0.0) : 0.0); + const bool bStrokeUsed(0.0 != fDotDashLength); + + if(pSystemDependentData_CairoPath) + { + // MM01 - check on stroke change. Used against not used, or if both used, + // equal or different? + const bool bStrokeWasUsed(!pSystemDependentData_CairoPath->getStroke().empty()); + + if(bStrokeWasUsed != bStrokeUsed + || (bStrokeUsed && *pStroke != pSystemDependentData_CairoPath->getStroke())) + { + // data invalid, forget + pSystemDependentData_CairoPath.reset(); + } + } + + // check for basegfx::B2DLineJoin::NONE to react accordingly + const bool bNoJoin((basegfx::B2DLineJoin::NONE == eLineJoin + && basegfx::fTools::more(aLineWidth.getX(), 0.0))); + if(pSystemDependentData_CairoPath) { // check data validity @@ -1327,42 +1363,67 @@ bool SvpSalGraphics::drawPolyLine( // create data size_t nSizeMeasure(0); - if (!bNoJoin) + // MM01 need to do line dashing as fallback stuff here now + basegfx::B2DPolyPolygon aPolyPolygonLine; + + if(bStrokeUsed) { - // PixelOffset now reflected in linear transformation used - nSizeMeasure += AddPolygonToPath( - cr, - rPolyLine, - rObjectToDevice, // ObjectToDevice *without* LineDraw-Offset - !bAntiAliasB2DDraw, - bPixelSnapHairline); + // apply LineStyle + basegfx::utils::applyLineDashing( + rPolyLine, // source + *pStroke, // pattern + &aPolyPolygonLine, // traget for lines + nullptr, // target for gaps + fDotDashLength); // full length if available } else { - const sal_uInt32 nPointCount(rPolyLine.count()); - const sal_uInt32 nEdgeCount(rPolyLine.isClosed() ? nPointCount : nPointCount - 1); - basegfx::B2DPolygon aEdge; + // no line dashing, just copy + aPolyPolygonLine.append(rPolyLine); + } - aEdge.append(rPolyLine.getB2DPoint(0)); - aEdge.append(basegfx::B2DPoint(0.0, 0.0)); + // MM01 checked/verified for Cairo + for(sal_uInt32 a(0); a < aPolyPolygonLine.count(); a++) + { + const basegfx::B2DPolygon aPolyLine(aPolyPolygonLine.getB2DPolygon(a)); - for (sal_uInt32 i(0); i < nEdgeCount; i++) + if (!bNoJoin) { - const sal_uInt32 nNextIndex((i + 1) % nPointCount); - aEdge.setB2DPoint(1, rPolyLine.getB2DPoint(nNextIndex)); - aEdge.setNextControlPoint(0, rPolyLine.getNextControlPoint(i)); - aEdge.setPrevControlPoint(1, rPolyLine.getPrevControlPoint(nNextIndex)); - // PixelOffset now reflected in linear transformation used nSizeMeasure += AddPolygonToPath( cr, - aEdge, + aPolyLine, rObjectToDevice, // ObjectToDevice *without* LineDraw-Offset !bAntiAliasB2DDraw, bPixelSnapHairline); + } + else + { + const sal_uInt32 nPointCount(aPolyLine.count()); + const sal_uInt32 nEdgeCount(aPolyLine.isClosed() ? nPointCount : nPointCount - 1); + basegfx::B2DPolygon aEdge; + + aEdge.append(aPolyLine.getB2DPoint(0)); + aEdge.append(basegfx::B2DPoint(0.0, 0.0)); - // prepare next step - aEdge.setB2DPoint(0, aEdge.getB2DPoint(1)); + for (sal_uInt32 i(0); i < nEdgeCount; i++) + { + const sal_uInt32 nNextIndex((i + 1) % nPointCount); + aEdge.setB2DPoint(1, aPolyLine.getB2DPoint(nNextIndex)); + aEdge.setNextControlPoint(0, aPolyLine.getNextControlPoint(i)); + aEdge.setPrevControlPoint(1, aPolyLine.getPrevControlPoint(nNextIndex)); + + // PixelOffset now reflected in linear transformation used + nSizeMeasure += AddPolygonToPath( + cr, + aEdge, + rObjectToDevice, // ObjectToDevice *without* LineDraw-Offset + !bAntiAliasB2DDraw, + bPixelSnapHairline); + + // prepare next step + aEdge.setB2DPoint(0, aEdge.getB2DPoint(1)); + } } } @@ -1374,7 +1435,8 @@ bool SvpSalGraphics::drawPolyLine( nSizeMeasure, cr, bNoJoin, - bAntiAliasB2DDraw); + bAntiAliasB2DDraw, + pStroke); } } @@ -1454,7 +1516,8 @@ namespace nSizeMeasure, cr, false, - false); + false, + nullptr); } } } |