diff options
Diffstat (limited to 'drawinglayer/source/processor2d/vclpixelprocessor2d.cxx')
-rw-r--r-- | drawinglayer/source/processor2d/vclpixelprocessor2d.cxx | 257 |
1 files changed, 234 insertions, 23 deletions
diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index a320d1a88c78..a486dd84b578 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -92,6 +92,141 @@ namespace drawinglayer mpOutputDevice->SetAntialiasing(mpOutputDevice->GetAntialiasing() & ~ANTIALIASING_ENABLE_B2DDRAW); } + bool VclPixelProcessor2D::tryDrawPolyPolygonColorPrimitive2DDirect(const drawinglayer::primitive2d::PolyPolygonColorPrimitive2D& rSource, double fTransparency) + { + basegfx::B2DPolyPolygon aLocalPolyPolygon(rSource.getB2DPolyPolygon()); + + if(!aLocalPolyPolygon.count()) + { + // no geometry, done + return true; + } + + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rSource.getBColor())); + + mpOutputDevice->SetFillColor(Color(aPolygonColor)); + mpOutputDevice->SetLineColor(); + aLocalPolyPolygon.transform(maCurrentTransformation); + mpOutputDevice->DrawTransparent( + aLocalPolyPolygon, + fTransparency); + + return true; + } + + bool VclPixelProcessor2D::tryDrawPolygonHairlinePrimitive2DDirect(const drawinglayer::primitive2d::PolygonHairlinePrimitive2D& rSource, double fTransparency) + { + basegfx::B2DPolygon aLocalPolygon(rSource.getB2DPolygon()); + + if(!aLocalPolygon.count()) + { + // no geometry, done + return true; + } + + const basegfx::BColor aLineColor(maBColorModifierStack.getModifiedColor(rSource.getBColor())); + + mpOutputDevice->SetFillColor(); + mpOutputDevice->SetLineColor(Color(aLineColor)); + aLocalPolygon.transform(maCurrentTransformation); + + // try drawing; if it did not work, use standard fallback + if(mpOutputDevice->TryDrawPolyLineDirect( + aLocalPolygon, + 0.0, + fTransparency)) + { + return true; + } + + return false; + } + + bool VclPixelProcessor2D::tryDrawPolygonStrokePrimitive2DDirect(const drawinglayer::primitive2d::PolygonStrokePrimitive2D& rSource, double fTransparency) + { + basegfx::B2DPolygon aLocalPolygon(rSource.getB2DPolygon()); + + if(!aLocalPolygon.count()) + { + // no geometry, done + return true; + } + + aLocalPolygon = basegfx::tools::simplifyCurveSegments(aLocalPolygon); + basegfx::B2DPolyPolygon aHairLinePolyPolygon; + + if(rSource.getStrokeAttribute().isDefault() || 0.0 == rSource.getStrokeAttribute().getFullDotDashLen()) + { + // no line dashing, just copy + aHairLinePolyPolygon.append(aLocalPolygon); + } + else + { + // apply LineStyle + basegfx::tools::applyLineDashing( + aLocalPolygon, + rSource.getStrokeAttribute().getDotDashArray(), + &aHairLinePolyPolygon, + 0, + rSource.getStrokeAttribute().getFullDotDashLen()); + } + + if(!aHairLinePolyPolygon.count()) + { + // no geometry, done + return true; + } + + const basegfx::BColor aLineColor( + maBColorModifierStack.getModifiedColor( + rSource.getLineAttribute().getColor())); + + mpOutputDevice->SetFillColor(); + mpOutputDevice->SetLineColor(Color(aLineColor)); + aHairLinePolyPolygon.transform(maCurrentTransformation); + + double fLineWidth(rSource.getLineAttribute().getWidth()); + + if(basegfx::fTools::more(fLineWidth, 0.0)) + { + basegfx::B2DVector aLineWidth(fLineWidth, 0.0); + + aLineWidth = maCurrentTransformation * aLineWidth; + fLineWidth = aLineWidth.getLength(); + } + + bool bHasPoints(false); + bool bTryWorked(false); + + for(sal_uInt32 a(0); a < aHairLinePolyPolygon.count(); a++) + { + const basegfx::B2DPolygon aSingle(aHairLinePolyPolygon.getB2DPolygon(a)); + + if(aSingle.count()) + { + bHasPoints = true; + + if(mpOutputDevice->TryDrawPolyLineDirect( + aSingle, + fLineWidth, + fTransparency, + rSource.getLineAttribute().getLineJoin(), + rSource.getLineAttribute().getLineCap())) + { + bTryWorked = true; + } + } + } + + if(!bTryWorked && !bHasPoints) + { + // no geometry despite try + bTryWorked = true; + } + + return bTryWorked; + } + void VclPixelProcessor2D::processBasePrimitive2D(const primitive2d::BasePrimitive2D& rCandidate) { switch(rCandidate.getPrimitive2DID()) @@ -169,8 +304,17 @@ namespace drawinglayer } case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D : { + // try to use directly + const primitive2d::PolygonHairlinePrimitive2D& rPolygonHairlinePrimitive2D = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate); + static bool bAllowed(true); + + if(bAllowed && tryDrawPolygonHairlinePrimitive2DDirect(rPolygonHairlinePrimitive2D, 0.0)) + { + break; + } + // direct draw of hairline - RenderPolygonHairlinePrimitive2D(static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate), true); + RenderPolygonHairlinePrimitive2D(rPolygonHairlinePrimitive2D, true); break; } case PRIMITIVE2D_ID_BITMAPPRIMITIVE2D : @@ -240,8 +384,53 @@ namespace drawinglayer } case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : { - // direct draw of PolyPolygon with color - RenderPolyPolygonColorPrimitive2D(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate)); + // try to use directly + const primitive2d::PolyPolygonColorPrimitive2D& rPolyPolygonColorPrimitive2D = static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon; + static bool bAllowed(true); + + if(bAllowed && tryDrawPolyPolygonColorPrimitive2DDirect(rPolyPolygonColorPrimitive2D, 0.0)) + { + // okay, done. In this case no gaps should have to be repaired, too + } + else + { + // direct draw of PolyPolygon with color + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor())); + + mpOutputDevice->SetFillColor(Color(aPolygonColor)); + mpOutputDevice->SetLineColor(); + aLocalPolyPolygon = rPolyPolygonColorPrimitive2D.getB2DPolyPolygon(); + aLocalPolyPolygon.transform(maCurrentTransformation); + mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon); + } + + // when AA is on and this filled polygons are the result of stroked line geometry, + // draw the geometry once extra as lines to avoid AA 'gaps' between partial polygons + // Caution: This is needed in both cases (!) + if(mnPolygonStrokePrimitive2D + && getOptionsDrawinglayer().IsAntiAliasing() + && (mpOutputDevice->GetAntialiasing() & ANTIALIASING_ENABLE_B2DDRAW)) + { + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolyPolygonColorPrimitive2D.getBColor())); + sal_uInt32 nCount(aLocalPolyPolygon.count()); + + if(!nCount) + { + aLocalPolyPolygon = rPolyPolygonColorPrimitive2D.getB2DPolyPolygon(); + aLocalPolyPolygon.transform(maCurrentTransformation); + nCount = aLocalPolyPolygon.count(); + } + + mpOutputDevice->SetFillColor(); + mpOutputDevice->SetLineColor(Color(aPolygonColor)); + + for(sal_uInt32 a(0); a < nCount; a++) + { + mpOutputDevice->DrawPolyLine(aLocalPolyPolygon.getB2DPolygon(a), 0.0); + } + } + break; } case PRIMITIVE2D_ID_METAFILEPRIMITIVE2D : @@ -313,25 +502,41 @@ namespace drawinglayer // single transparent PolyPolygon identified, use directly const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = static_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(pBasePrimitive); OSL_ENSURE(pPoPoColor, "OOps, PrimitiveID and PrimitiveType do not match (!)"); - const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor())); - mpOutputDevice->SetFillColor(Color(aPolygonColor)); - mpOutputDevice->SetLineColor(); - - basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon()); - aLocalPolyPolygon.transform(maCurrentTransformation); - - mpOutputDevice->DrawTransparent(aLocalPolyPolygon, rUniTransparenceCandidate.getTransparence()); - bDrawTransparentUsed = true; + bDrawTransparentUsed = tryDrawPolyPolygonColorPrimitive2DDirect(*pPoPoColor, rUniTransparenceCandidate.getTransparence()); + break; + } + case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D: + { + // single transparent PolygonHairlinePrimitive2D identified, use directly + const primitive2d::PolygonHairlinePrimitive2D* pPoHair = static_cast< const primitive2d::PolygonHairlinePrimitive2D* >(pBasePrimitive); + OSL_ENSURE(pPoHair, "OOps, PrimitiveID and PrimitiveType do not match (!)"); + + // do no tallow by default - problem is that self-overlapping parts of this geometry will + // not be in a all-same transparency but will already alpha-cover themselves with blending. + // This is not what the UnifiedTransparencePrimitive2D defines: It requires all it's + // content to be uniformely transparent. + // For hairline the effect is pretty minimal, but still not correct. + static bool bAllowed(false); + + bDrawTransparentUsed = bAllowed && tryDrawPolygonHairlinePrimitive2DDirect(*pPoHair, rUniTransparenceCandidate.getTransparence()); + break; + } + case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D: + { + // single transparent PolygonStrokePrimitive2D identified, use directly + const primitive2d::PolygonStrokePrimitive2D* pPoStroke = static_cast< const primitive2d::PolygonStrokePrimitive2D* >(pBasePrimitive); + OSL_ENSURE(pPoStroke, "OOps, PrimitiveID and PrimitiveType do not match (!)"); + + // do no tallow by default - problem is that self-overlapping parts of this geometry will + // not be in a all-same transparency but will already alpha-cover themselves with blending. + // This is not what the UnifiedTransparencePrimitive2D defines: It requires all it's + // content to be uniformely transparent. + // To check, acitvate and draw a wide transparent self-crossing line/curve + static bool bAllowed(false); + + bDrawTransparentUsed = bAllowed && tryDrawPolygonStrokePrimitive2DDirect(*pPoStroke, rUniTransparenceCandidate.getTransparence()); break; } - // #i# need to wait for #i101378# which is in CWS vcl112 to directly paint transparent hairlines - //case PRIMITIVE2D_ID_POLYGONHAIRLINEPRIMITIVE2D: - //{ - // // single transparent PolygonHairlinePrimitive2D identified, use directly - // const primitive2d::PolygonHairlinePrimitive2D* pPoHair = static_cast< const primitive2d::PolygonHairlinePrimitive2D* >(pBasePrimitive); - // OSL_ENSURE(pPoHair, "OOps, PrimitiveID and PrimitiveType do not match (!)"); - // break; - //} } } } @@ -431,6 +636,14 @@ namespace drawinglayer } case PRIMITIVE2D_ID_POLYGONSTROKEPRIMITIVE2D: { + // try to use directly + const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive2D = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate); + + if(tryDrawPolygonStrokePrimitive2DDirect(rPolygonStrokePrimitive2D, 0.0)) + { + break; + } + // the stroke primitive may be decomposed to filled polygons. To keep // evtl. set DrawModes aka DRAWMODE_BLACKLINE, DRAWMODE_GRAYLINE, // DRAWMODE_GHOSTEDLINE, DRAWMODE_WHITELINE or DRAWMODE_SETTINGSLINE @@ -459,9 +672,7 @@ namespace drawinglayer // as filled polygons is geometrically corret but looks wrong since polygon filling avoids // the right and bottom pixels. The used method evaluates that and takes the correct action, // including calling recursively with decomposition if line is wide enough - const primitive2d::PolygonStrokePrimitive2D& rPolygonStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate); - - RenderPolygonStrokePrimitive2D(rPolygonStrokePrimitive); + RenderPolygonStrokePrimitive2D(rPolygonStrokePrimitive2D); } // restore DrawMode |