diff options
author | Armin Le Grand <Armin.Le.Grand@Sun.COM> | 2010-06-17 18:02:36 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@Sun.COM> | 2010-06-17 18:02:36 +0200 |
commit | 12f9037a5313240ce598b17369bf002f0f7fd9f2 (patch) | |
tree | 7828ae6c6f8bebf3a9a1f82cca8e13e6a6ec68b5 /drawinglayer | |
parent | f288b50cef4d2a13cfb100af3a71f14b171d066a (diff) | |
parent | bf8660708144ccb693063a20954f64a66a1c979d (diff) |
aw083: added aw082 due to possible conflicts in vclmetafileprocessor2d.cxx
Diffstat (limited to 'drawinglayer')
7 files changed, 557 insertions, 220 deletions
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx index 0f426c6ad2ba..6c67bded2b17 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx @@ -62,11 +62,48 @@ namespace drawinglayer To get better text quality, it is suggested to handle tis primitive directly in a renderer. In that case, e.g. hintings on the system can be supported. + + @param maTextTransform + The text transformation contains the text start position (always baselined) + as translation, the FontSize as scale (where width relative to height defines + font scaling and width == height means no font scaling) and the font rotation + and shear. + When shear is used and a renderer does not support it, it may be better to use + the decomposition which will do everything correctly. Same is true for mirroring + which would be expressed as negative scalings. + + @param rText + The text to be used. Only a part may be used, but a bigger part of the string + may be necessary for correct layouting (e.g. international) + + @param aTextPosition + The index to the first character to use from rText + + @param aTextLength + The number of characters to use from rText + + @param rDXArray + The distances between the characters. This parameter may be empty, in that case + the renderer is responsible to do something useful. If it is given, it has to be of + the size aTextLength. Its values are in logical coordinates and describe the + distance for each character to use. This is independent from the font width which + is given with maTextTransform. The first value is the offset to use from the start + point in FontCoordinateSystem X-Direction (given by maTextTransform) to the start + point of the second character + + @param rFontAttribute + The font definition + + @param rLocale + The locale to use + + @param rFontColor + The font color to use */ class TextSimplePortionPrimitive2D : public BufferedDecompositionPrimitive2D { private: - /// text range transformation from unit range ([0.0 .. 1.0]) to text range + /// text transformation (FontCoordinateSystem) basegfx::B2DHomMatrix maTextTransform; /// The text, used from maTextPosition up to maTextPosition + maTextLength @@ -78,10 +115,10 @@ namespace drawinglayer /// The length for maText usage, starting from maTextPosition xub_StrLen maTextLength; - /// The DX array scale-independent in unit coordinates + /// The DX array in logic units ::std::vector< double > maDXArray; - /// The font to use + /// The font definition attribute::FontAttribute maFontAttribute; /// The Locale for the text @@ -90,7 +127,7 @@ namespace drawinglayer /// font color basegfx::BColor maFontColor; - /// #i96669# add simple range buffering for this primitive + /// #i96669# internal: add simple range buffering for this primitive basegfx::B2DRange maB2DRange; protected: diff --git a/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx b/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx index 23d8e7edd913..93ebfeab48e7 100644 --- a/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx +++ b/drawinglayer/inc/drawinglayer/processor3d/shadow3dextractor.hxx @@ -54,9 +54,12 @@ namespace drawinglayer class Shadow3DExtractingProcessor : public BaseProcessor3D { private: + /// typedef for data handling + typedef std::vector< primitive2d::BasePrimitive2D* > BasePrimitive2DVector; + /// result holding vector (2D) and target vector for stacking (inited to &maPrimitive2DSequence) - primitive2d::Primitive2DSequence maPrimitive2DSequence; - primitive2d::Primitive2DSequence* mpPrimitive2DSequence; + BasePrimitive2DVector maPrimitive2DSequence; + BasePrimitive2DVector* mpPrimitive2DSequence; /// object transformation for scene for 2d definition basegfx::B2DHomMatrix maObjectTransformation; @@ -93,6 +96,10 @@ namespace drawinglayer */ virtual void processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate); + /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence + const primitive2d::Primitive2DSequence getPrimitive2DSequenceFromBasePrimitive2DVector( + const BasePrimitive2DVector& rVector) const; + public: Shadow3DExtractingProcessor( const geometry::ViewInformation3D& rViewInformation, @@ -100,9 +107,10 @@ namespace drawinglayer const basegfx::B3DVector& rLightNormal, double fShadowSlant, const basegfx::B3DRange& rContained3DRange); + virtual ~Shadow3DExtractingProcessor(); /// data read access - const primitive2d::Primitive2DSequence& getPrimitive2DSequence() const { return maPrimitive2DSequence; } + const primitive2d::Primitive2DSequence getPrimitive2DSequence() const; const basegfx::B2DHomMatrix& getObjectTransformation() const { return maObjectTransformation; } const basegfx::B3DHomMatrix& getWorldToEye() const { return maWorldToEye; } const basegfx::B3DHomMatrix& getEyeToView() const { return maEyeToView; } diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx index 480fa99e07fe..0d57e566ef8a 100644 --- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -94,8 +94,10 @@ namespace basegfx::BColor maTextLineColor; basegfx::BColor maOverlineColor; - /// clipping, font, etc. - Region maRegion; + /// clipping + basegfx::B2DPolyPolygon maClipPolyPoygon; + + /// font, etc. Font maFont; RasterOp maRasterOp; sal_uInt32 mnLayoutMode; @@ -110,7 +112,7 @@ namespace bool mbTextFillColor : 1; bool mbTextLineColor : 1; bool mbOverlineColor : 1; - bool mbRegion : 1; + bool mbClipPolyPolygonActive : 1; public: PropertyHolder() @@ -122,7 +124,7 @@ namespace maTextFillColor(), maTextLineColor(), maOverlineColor(), - maRegion(), + maClipPolyPoygon(), maFont(), maRasterOp(ROP_OVERPAINT), mnLayoutMode(0), @@ -134,7 +136,7 @@ namespace mbTextFillColor(false), mbTextLineColor(false), mbOverlineColor(false), - mbRegion(false) + mbClipPolyPolygonActive(false) { } @@ -179,10 +181,10 @@ namespace bool getOverlineColorActive() const { return mbOverlineColor; } void setOverlineColorActive(bool bNew) { if(bNew != mbOverlineColor) mbOverlineColor = bNew; } - const Region& getRegion() const { return maRegion; } - void setRegion(const Region& rRegion) { if(rRegion != maRegion) maRegion = rRegion; } - bool getRegionActive() const { return mbRegion; } - void setRegionActive(bool bNew) { if(bNew != mbRegion) mbRegion = bNew; } + const basegfx::B2DPolyPolygon& getClipPolyPolygon() const { return maClipPolyPoygon; } + void setClipPolyPolygon(const basegfx::B2DPolyPolygon& rNew) { if(rNew != maClipPolyPoygon) maClipPolyPoygon = rNew; } + bool getClipPolyPolygonActive() const { return mbClipPolyPolygonActive; } + void setClipPolyPolygonActive(bool bNew) { if(bNew != mbClipPolyPolygonActive) mbClipPolyPolygonActive = bNew; } const Font& getFont() const { return maFont; } void setFont(const Font& rFont) { if(rFont != maFont) maFont = rFont; } @@ -235,6 +237,12 @@ namespace return maPropertyHolders.size(); } + void PushDefault() + { + PropertyHolder* pNew = new PropertyHolder(); + maPropertyHolders.push_back(pNew); + } + void Push(sal_uInt16 nPushFlags) { if(nPushFlags) @@ -291,8 +299,8 @@ namespace } if(!(nPushFlags & PUSH_CLIPREGION )) { - pLast->setRegion(pTip->getRegion()); - pLast->setRegionActive(pTip->getRegionActive()); + pLast->setClipPolyPolygon(pTip->getClipPolyPolygon()); + pLast->setClipPolyPolygonActive(pTip->getClipPolyPolygonActive()); } if(!(nPushFlags & PUSH_RASTEROP )) { @@ -336,11 +344,11 @@ namespace } } } - - // execute the pop - delete maPropertyHolders.back(); - maPropertyHolders.pop_back(); } + + // execute the pop + delete maPropertyHolders.back(); + maPropertyHolders.pop_back(); } } @@ -465,25 +473,18 @@ namespace // the buffer to not delete them in the destructor. aTargets.clear(); - if(xRetval.hasElements() && rPropertyHolder.getRegionActive()) + if(xRetval.hasElements() && rPropertyHolder.getClipPolyPolygonActive()) { - const Region& rRegion = rPropertyHolder.getRegion(); + const basegfx::B2DPolyPolygon& rClipPolyPolygon = rPropertyHolder.getClipPolyPolygon(); - if(!rRegion.IsEmpty()) + if(rClipPolyPolygon.count()) { - basegfx::B2DPolyPolygon aClipPolyPolygon(getB2DPolyPolygonFromRegion(rRegion)); + const drawinglayer::primitive2d::Primitive2DReference xMask( + new drawinglayer::primitive2d::MaskPrimitive2D( + rClipPolyPolygon, + xRetval)); - if(aClipPolyPolygon.count()) - { - aClipPolyPolygon.transform(rPropertyHolder.getTransformation()); - - const drawinglayer::primitive2d::Primitive2DReference xMask( - new drawinglayer::primitive2d::MaskPrimitive2D( - aClipPolyPolygon, - xRetval)); - - xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1); - } + xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xMask, 1); } } @@ -943,14 +944,17 @@ namespace default : // case HATCH_SINGLE : { aHatchStyle = drawinglayer::attribute::HATCHSTYLE_SINGLE; + break; } case HATCH_DOUBLE : { aHatchStyle = drawinglayer::attribute::HATCHSTYLE_DOUBLE; + break; } case HATCH_TRIPLE : { aHatchStyle = drawinglayer::attribute::HATCHSTYLE_TRIPLE; + break; } } @@ -969,53 +973,56 @@ namespace a new target for embracing new geometry to the current region */ void HandleNewClipRegion( - const Region* pRegion, + const basegfx::B2DPolyPolygon& rClipPolyPolygon, TargetHolders& rTargetHolders, PropertyHolders& rPropertyHolders) { - const bool bNewActive(pRegion && !pRegion->IsEmpty()); + const bool bNewActive(rClipPolyPolygon.count()); - // #i108636# The handlig of new ClipRegions was not done as good as possible - // in the first version of this interpreter; e.g. when a ClipRegion was set + // #i108636# The handlig of new ClipPolyPolygons was not done as good as possible + // in the first version of this interpreter; e.g. when a ClipPolyPolygon was set // initially and then using a lot of push/pop actions, the pop always leads - // to setting a 'new' ClipRegion which indeed is the return to the ClipRegion + // to setting a 'new' ClipPolyPolygon which indeed is the return to the ClipPolyPolygon // of the properties next on the stack. - // This ClipRegion is identical to the current one, so there is no need to + // + // This ClipPolyPolygon is identical to the current one, so there is no need to // create a MaskPrimitive2D containing the up-to-now created primitives, but // this was done before. While this does not lead to wrong primitive // representations of the metafile data, it creates unneccesarily expensive - // representations. Just detecting when no really 'new' ClipRegion gets set + // representations. Just detecting when no really 'new' ClipPolyPolygon gets set // solves the problem. - if(!rPropertyHolders.Current().getRegionActive() && !bNewActive) + if(!rPropertyHolders.Current().getClipPolyPolygonActive() && !bNewActive) { - // no active region exchanged by no new one, done + // no active ClipPolyPolygon exchanged by no new one, done return; } - if(rPropertyHolders.Current().getRegionActive() && bNewActive) + if(rPropertyHolders.Current().getClipPolyPolygonActive() && bNewActive) { - // active region and new active region - if(rPropertyHolders.Current().getRegion() == *pRegion) + // active ClipPolyPolygon and new active ClipPolyPolygon + if(rPropertyHolders.Current().getClipPolyPolygon() == rClipPolyPolygon) { - // new region is the same as the old region, done + // new is the same as old, done return; } } - // Here the old region and the new one are definitively different, maybe + // Here the old and the new are definitively different, maybe // old one and/or new one is not active. - // Handle deletion of old region.The process evtl. created primitives which - // belong to this active region. These need to be embedded to a + // Handle deletion of old ClipPolyPolygon. The process evtl. created primitives which + // belong to this active ClipPolyPolygon. These need to be embedded to a // MaskPrimitive2D accordingly. - if(rPropertyHolders.Current().getRegionActive() && rTargetHolders.size() > 1) + if(rPropertyHolders.Current().getClipPolyPolygonActive() && rTargetHolders.size() > 1) { drawinglayer::primitive2d::Primitive2DSequence aSubContent; - if(!rPropertyHolders.Current().getRegion().IsEmpty() && rTargetHolders.Current().size()) + if(rPropertyHolders.Current().getClipPolyPolygon().count() + && rTargetHolders.Current().size()) { - aSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()); + aSubContent = rTargetHolders.Current().getPrimitive2DSequence( + rPropertyHolders.Current()); } rTargetHolders.Pop(); @@ -1030,11 +1037,11 @@ namespace // apply new settings to current properties by setting // the new region now - rPropertyHolders.Current().setRegionActive(bNewActive); + rPropertyHolders.Current().setClipPolyPolygonActive(bNewActive); if(bNewActive) { - rPropertyHolders.Current().setRegion(*pRegion); + rPropertyHolders.Current().setClipPolyPolygon(rClipPolyPolygon); // prepare new content holder for new active region rTargetHolders.Push(); @@ -2134,8 +2141,11 @@ namespace drawinglayer::primitive2d::Primitive2DSequence xSubContent; { rTargetHolders.Push(); + // #i# for sub-Mteafile contents, do start with new, default render state + rPropertyHolders.PushDefault(); interpretMetafile(aGDIMetaFile, rTargetHolders, rPropertyHolders, rViewInformation); xSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()); + rPropertyHolders.Pop(); rTargetHolders.Pop(); } @@ -2424,13 +2434,18 @@ namespace if(pA->IsClipping()) { - // new clipping - HandleNewClipRegion(&pA->GetRegion(), rTargetHolders, rPropertyHolders); + // new clipping. Get PolyPolygon and transform with current transformation + basegfx::B2DPolyPolygon aNewClipPolyPolygon(getB2DPolyPolygonFromRegion(pA->GetRegion())); + + aNewClipPolyPolygon.transform(rPropertyHolders.Current().getTransformation()); + HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders); } else { // end clipping - HandleNewClipRegion(0, rTargetHolders, rPropertyHolders); + const basegfx::B2DPolyPolygon aEmptyPolyPolygon; + + HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); } break; @@ -2444,49 +2459,60 @@ namespace if(rRectangle.IsEmpty()) { // intersect with empty rectangle will always give empty - // region; start new clipping with empty region - const Region aNewRegion; - HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders); + // ClipPolyPolygon; start new clipping with empty PolyPolygon + const basegfx::B2DPolyPolygon aEmptyPolyPolygon; + + HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); } else { - if(rPropertyHolders.Current().getRegionActive()) + // create transformed ClipRange + basegfx::B2DRange aClipRange( + rRectangle.Left(), rRectangle.Top(), + rRectangle.Right(), rRectangle.Bottom()); + + aClipRange.transform(rPropertyHolders.Current().getTransformation()); + + if(rPropertyHolders.Current().getClipPolyPolygonActive()) { - if(rPropertyHolders.Current().getRegion().IsEmpty()) + if(0 == rPropertyHolders.Current().getClipPolyPolygon().count()) { - // nothing to do, empty active clip region will stay + // nothing to do, empty active clipPolyPolygon will stay // empty when intersecting } else { - // AND existing region and new rectangle + // AND existing region and new ClipRange const basegfx::B2DPolyPolygon aOriginalPolyPolygon( - getB2DPolyPolygonFromRegion(rPropertyHolders.Current().getRegion())); + rPropertyHolders.Current().getClipPolyPolygon()); basegfx::B2DPolyPolygon aClippedPolyPolygon; if(aOriginalPolyPolygon.count()) { - const basegfx::B2DRange aIntersectRange( - rRectangle.Left(), rRectangle.Top(), - rRectangle.Right(), rRectangle.Bottom()); - aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnRange( - aOriginalPolyPolygon, aIntersectRange, true, false); + aOriginalPolyPolygon, + aClipRange, + true, + false); } if(aClippedPolyPolygon != aOriginalPolyPolygon) { // start new clipping with intersected region - const Region aNewRegion(aClippedPolyPolygon); - HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders); + HandleNewClipRegion( + aClippedPolyPolygon, + rTargetHolders, + rPropertyHolders); } } } else { - // start new clipping with rectangle - const Region aNewRegion(rRectangle); - HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders); + // start new clipping with ClipRange + const basegfx::B2DPolyPolygon aNewClipPolyPolygon( + basegfx::tools::createPolygonFromRect(aClipRange)); + + HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders); } } @@ -2501,50 +2527,48 @@ namespace if(rNewRegion.IsEmpty()) { // intersect with empty region will always give empty - // region; start new clipping with empty region - const Region aNewRegion; - HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders); + // region; start new clipping with empty PolyPolygon + const basegfx::B2DPolyPolygon aEmptyPolyPolygon; + + HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); } else { - if(rPropertyHolders.Current().getRegionActive()) + // get new ClipPolyPolygon, transform it with current transformation + basegfx::B2DPolyPolygon aNewClipPolyPolygon(getB2DPolyPolygonFromRegion(rNewRegion)); + aNewClipPolyPolygon.transform(rPropertyHolders.Current().getTransformation()); + + if(rPropertyHolders.Current().getClipPolyPolygonActive()) { - if(rPropertyHolders.Current().getRegion().IsEmpty()) + if(0 == rPropertyHolders.Current().getClipPolyPolygon().count()) { - // nothing to do, empty active clip region will stay empty + // nothing to do, empty active clipPolyPolygon will stay empty // when intersecting with any region } else { // AND existing and new region const basegfx::B2DPolyPolygon aOriginalPolyPolygon( - getB2DPolyPolygonFromRegion(rPropertyHolders.Current().getRegion())); + rPropertyHolders.Current().getClipPolyPolygon()); basegfx::B2DPolyPolygon aClippedPolyPolygon; if(aOriginalPolyPolygon.count()) { - const basegfx::B2DPolyPolygon aClipPolyPolygon( - getB2DPolyPolygonFromRegion(rNewRegion)); - - if(aClipPolyPolygon.count()) - { - aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon( - aOriginalPolyPolygon, aClipPolyPolygon, true, false); - } + aClippedPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon( + aOriginalPolyPolygon, aNewClipPolyPolygon, true, false); } if(aClippedPolyPolygon != aOriginalPolyPolygon) { - // start new clipping with intersected region - const Region aNewRegion(aClippedPolyPolygon); - HandleNewClipRegion(&aNewRegion, rTargetHolders, rPropertyHolders); + // start new clipping with intersected ClipPolyPolygon + HandleNewClipRegion(aClippedPolyPolygon, rTargetHolders, rPropertyHolders); } } } else { - // start new clipping with new region - HandleNewClipRegion(&rNewRegion, rTargetHolders, rPropertyHolders); + // start new clipping with new ClipPolyPolygon + HandleNewClipRegion(aNewClipPolyPolygon, rTargetHolders, rPropertyHolders); } } @@ -2555,24 +2579,31 @@ namespace /** CHECKED, WORKS WELL */ const MetaMoveClipRegionAction* pA = (const MetaMoveClipRegionAction*)pAction; - if(rPropertyHolders.Current().getRegionActive()) + if(rPropertyHolders.Current().getClipPolyPolygonActive()) { - if(rPropertyHolders.Current().getRegion().IsEmpty()) + if(0 == rPropertyHolders.Current().getClipPolyPolygon().count()) { // nothing to do } else { - // move using old interface - Region aRegion(rPropertyHolders.Current().getRegion()); - const sal_Int32 nHor(pA->GetHorzMove()); const sal_Int32 nVer(pA->GetVertMove()); if(0 != nHor || 0 != nVer) { - aRegion.Move(nHor, nVer); - HandleNewClipRegion(&aRegion, rTargetHolders, rPropertyHolders); + // prepare translation, add current transformation + basegfx::B2DVector aVector(pA->GetHorzMove(), pA->GetVertMove()); + aVector *= rPropertyHolders.Current().getTransformation(); + basegfx::B2DHomMatrix aTransform( + basegfx::tools::createTranslateB2DHomMatrix(aVector)); + + // transform existing region + basegfx::B2DPolyPolygon aClipPolyPolygon( + rPropertyHolders.Current().getClipPolyPolygon()); + + aClipPolyPolygon.transform(aTransform); + HandleNewClipRegion(aClipPolyPolygon, rTargetHolders, rPropertyHolders); } } } @@ -2777,10 +2808,12 @@ namespace const bool bRegionMayChange(rPropertyHolders.Current().getPushFlags() & PUSH_CLIPREGION); const bool bRasterOpMayChange(rPropertyHolders.Current().getPushFlags() & PUSH_RASTEROP); - if(bRegionMayChange && rPropertyHolders.Current().getRegionActive()) + if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive()) { // end evtl. clipping - HandleNewClipRegion(0, rTargetHolders, rPropertyHolders); + const basegfx::B2DPolyPolygon aEmptyPolyPolygon; + + HandleNewClipRegion(aEmptyPolyPolygon, rTargetHolders, rPropertyHolders); } if(bRasterOpMayChange && rPropertyHolders.Current().isRasterOpActive()) @@ -2797,10 +2830,11 @@ namespace HandleNewRasterOp(rPropertyHolders.Current().getRasterOp(), rTargetHolders, rPropertyHolders); } - if(bRegionMayChange && rPropertyHolders.Current().getRegionActive()) + if(bRegionMayChange && rPropertyHolders.Current().getClipPolyPolygonActive()) { // start evtl. clipping - HandleNewClipRegion(&rPropertyHolders.Current().getRegion(), rTargetHolders, rPropertyHolders); + HandleNewClipRegion( + rPropertyHolders.Current().getClipPolyPolygon(), rTargetHolders, rPropertyHolders); } break; @@ -2948,8 +2982,11 @@ namespace drawinglayer::primitive2d::Primitive2DSequence xSubContent; { rTargetHolders.Push(); + // #i# for sub-Mteafile contents, do start with new, default render state + rPropertyHolders.PushDefault(); interpretMetafile(rContent, rTargetHolders, rPropertyHolders, rViewInformation); xSubContent = rTargetHolders.Current().getPrimitive2DSequence(rPropertyHolders.Current()); + rPropertyHolders.Pop(); rTargetHolders.Pop(); } diff --git a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx index 68ca424cca78..dc954de7bb2a 100644 --- a/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclmetafileprocessor2d.cxx @@ -94,6 +94,147 @@ using namespace com::sun::star; ////////////////////////////////////////////////////////////////////////////// +// #112245# definition for maximum allowed point count due to Metafile target. +// To be on the safe side with the old tools polygon, use slightly less then +// the theoretical maximum (bad experiences with tools polygon) + +#define MAX_POLYGON_POINT_COUNT_METAFILE (0x0000fff0) + +////////////////////////////////////////////////////////////////////////////// + +namespace +{ + // #112245# helper to split line polygon in half + void splitLinePolygon( + const basegfx::B2DPolygon& rBasePolygon, + basegfx::B2DPolygon& o_aLeft, + basegfx::B2DPolygon& o_aRight) + { + const sal_uInt32 nCount(rBasePolygon.count()); + + if(nCount) + { + const sal_uInt32 nHalfCount((nCount - 1) >> 1); + + o_aLeft = basegfx::B2DPolygon(rBasePolygon, 0, nHalfCount + 1); + o_aLeft.setClosed(false); + + o_aRight = basegfx::B2DPolygon(rBasePolygon, nHalfCount, nCount - nHalfCount); + o_aRight.setClosed(false); + + if(rBasePolygon.isClosed()) + { + o_aRight.append(rBasePolygon.getB2DPoint(0)); + + if(rBasePolygon.areControlPointsUsed()) + { + o_aRight.setControlPoints( + o_aRight.count() - 1, + rBasePolygon.getPrevControlPoint(0), + rBasePolygon.getNextControlPoint(0)); + } + } + } + else + { + o_aLeft.clear(); + o_aRight.clear(); + } + } + + // #112245# helper to evtl. split filled polygons to maximum metafile point count + bool fillPolyPolygonNeededToBeSplit(basegfx::B2DPolyPolygon& rPolyPolygon) + { + bool bRetval(false); + const sal_uInt32 nPolyCount(rPolyPolygon.count()); + + if(nPolyCount) + { + basegfx::B2DPolyPolygon aSplitted; + + for(sal_uInt32 a(0); a < nPolyCount; a++) + { + const basegfx::B2DPolygon aCandidate(rPolyPolygon.getB2DPolygon(a)); + const sal_uInt32 nPointCount(aCandidate.count()); + bool bNeedToSplit(false); + + if(aCandidate.areControlPointsUsed()) + { + // compare with the maximum for bezier curved polygons + bNeedToSplit = nPointCount > ((MAX_POLYGON_POINT_COUNT_METAFILE / 3L) - 1L); + } + else + { + // compare with the maximum for simple point polygons + bNeedToSplit = nPointCount > (MAX_POLYGON_POINT_COUNT_METAFILE - 1); + } + + if(bNeedToSplit) + { + // need to split the partial polygon + const basegfx::B2DRange aRange(aCandidate.getB2DRange()); + const basegfx::B2DPoint aCenter(aRange.getCenter()); + + if(aRange.getWidth() > aRange.getHeight()) + { + // clip in left and right + const basegfx::B2DPolyPolygon aLeft( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + false, + true, + aCenter.getX(), + false)); + const basegfx::B2DPolyPolygon aRight( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + false, + false, + aCenter.getX(), + false)); + + aSplitted.append(aLeft); + aSplitted.append(aRight); + } + else + { + // clip in top and bottom + const basegfx::B2DPolyPolygon aTop( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + true, + true, + aCenter.getY(), + false)); + const basegfx::B2DPolyPolygon aBottom( + basegfx::tools::clipPolygonOnParallelAxis( + aCandidate, + true, + false, + aCenter.getY(), + false)); + + aSplitted.append(aTop); + aSplitted.append(aBottom); + } + } + else + { + aSplitted.append(aCandidate); + } + } + + if(aSplitted.count() != nPolyCount) + { + rPolyPolygon = aSplitted; + } + } + + return bRetval; + } +} // end of anonymous namespace + +////////////////////////////////////////////////////////////////////////////// namespace drawinglayer { @@ -985,14 +1126,12 @@ namespace drawinglayer const primitive2d::PolygonHairlinePrimitive2D& rHairlinePrimitive = static_cast< const primitive2d::PolygonHairlinePrimitive2D& >(rCandidate); const basegfx::B2DPolygon& rBasePolygon = rHairlinePrimitive.getB2DPolygon(); - if(rBasePolygon.count() > (0x0000ffff - 1)) + if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) { // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points // per polygon. If there are more, split the polygon in half and call recursively - const sal_uInt32 nCount(rBasePolygon.count()); - const sal_uInt32 nHalfCount((nCount - 1) >> 1); - const basegfx::B2DPolygon aLeft(rBasePolygon, 0, nHalfCount + 1); - const basegfx::B2DPolygon aRight(rBasePolygon, nHalfCount, nCount - nHalfCount); + basegfx::B2DPolygon aLeft, aRight; + splitLinePolygon(rBasePolygon, aLeft, aRight); const primitive2d::PolygonHairlinePrimitive2D aPLeft(aLeft, rHairlinePrimitive.getBColor()); const primitive2d::PolygonHairlinePrimitive2D aPRight(aRight, rHairlinePrimitive.getBColor()); @@ -1020,14 +1159,12 @@ namespace drawinglayer const primitive2d::PolygonStrokePrimitive2D& rStrokePrimitive = static_cast< const primitive2d::PolygonStrokePrimitive2D& >(rCandidate); const basegfx::B2DPolygon& rBasePolygon = rStrokePrimitive.getB2DPolygon(); - if(rBasePolygon.count() > (0x0000ffff - 1)) + if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) { // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points // per polygon. If there are more, split the polygon in half and call recursively - const sal_uInt32 nCount(rBasePolygon.count()); - const sal_uInt32 nHalfCount((nCount - 1) >> 1); - const basegfx::B2DPolygon aLeft(rBasePolygon, 0, nHalfCount + 1); - const basegfx::B2DPolygon aRight(rBasePolygon, nHalfCount, nCount - nHalfCount); + basegfx::B2DPolygon aLeft, aRight; + splitLinePolygon(rBasePolygon, aLeft, aRight); const primitive2d::PolygonStrokePrimitive2D aPLeft( aLeft, rStrokePrimitive.getLineAttribute(), rStrokePrimitive.getStrokeAttribute()); const primitive2d::PolygonStrokePrimitive2D aPRight( @@ -1099,14 +1236,12 @@ namespace drawinglayer const primitive2d::PolygonStrokeArrowPrimitive2D& rStrokeArrowPrimitive = static_cast< const primitive2d::PolygonStrokeArrowPrimitive2D& >(rCandidate); const basegfx::B2DPolygon& rBasePolygon = rStrokeArrowPrimitive.getB2DPolygon(); - if(rBasePolygon.count() > (0x0000ffff - 1)) + if(rBasePolygon.count() > (MAX_POLYGON_POINT_COUNT_METAFILE - 1)) { // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points // per polygon. If there are more, split the polygon in half and call recursively - const sal_uInt32 nCount(rBasePolygon.count()); - const sal_uInt32 nHalfCount((nCount - 1) >> 1); - const basegfx::B2DPolygon aLeft(rBasePolygon, 0, nHalfCount + 1); - const basegfx::B2DPolygon aRight(rBasePolygon, nHalfCount, nCount - nHalfCount); + basegfx::B2DPolygon aLeft, aRight; + splitLinePolygon(rBasePolygon, aLeft, aRight); const attribute::LineStartEndAttribute aEmpty; const primitive2d::PolygonStrokeArrowPrimitive2D aPLeft( aLeft, @@ -1150,16 +1285,26 @@ namespace drawinglayer case PRIMITIVE2D_ID_POLYPOLYGONBITMAPPRIMITIVE2D : { // need to handle PolyPolygonBitmapPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END - SvtGraphicFill* pSvtGraphicFill = 0; + const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon()); - if(!mnSvtGraphicFillCount) + if(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) { - const primitive2d::PolyPolygonBitmapPrimitive2D& rBitmapCandidate = static_cast< const primitive2d::PolyPolygonBitmapPrimitive2D& >(rCandidate); - basegfx::B2DPolyPolygon aLocalPolyPolygon(rBitmapCandidate.getB2DPolyPolygon()); - aLocalPolyPolygon.transform(maCurrentTransformation); + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. If there are more use the splitted polygon and call recursively + const primitive2d::PolyPolygonBitmapPrimitive2D aSplitted( + aLocalPolyPolygon, + rBitmapCandidate.getFillBitmap()); - if(aLocalPolyPolygon.count()) + processBasePrimitive2D(aSplitted); + } + else + { + SvtGraphicFill* pSvtGraphicFill = 0; + + if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) { + aLocalPolyPolygon.transform(maCurrentTransformation); // calculate transformation. Get real object size, all values in FillBitmapAttribute // are relative to the unified object const attribute::FillBitmapAttribute& rFillBitmapAttribute = rBitmapCandidate .getFillBitmap(); @@ -1216,84 +1361,100 @@ namespace drawinglayer 0, aFillGraphic); } - } - // Do use decomposition; encapsulate with SvtGraphicFill - impStartSvtGraphicFill(pSvtGraphicFill); - process(rCandidate.get2DDecomposition(getViewInformation2D())); - impEndSvtGraphicFill(pSvtGraphicFill); + // Do use decomposition; encapsulate with SvtGraphicFill + impStartSvtGraphicFill(pSvtGraphicFill); + process(rCandidate.get2DDecomposition(getViewInformation2D())); + impEndSvtGraphicFill(pSvtGraphicFill); + } break; } case PRIMITIVE2D_ID_POLYPOLYGONHATCHPRIMITIVE2D : { // need to handle PolyPolygonHatchPrimitive2D here to support XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END + const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; + SvtGraphicFill* pSvtGraphicFill = 0; + const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); + aLocalPolyPolygon.transform(maCurrentTransformation); - if(!mnSvtGraphicFillCount) + if(!mnSvtGraphicFillCount && aLocalPolyPolygon.count()) { - const primitive2d::PolyPolygonHatchPrimitive2D& rHatchCandidate = static_cast< const primitive2d::PolyPolygonHatchPrimitive2D& >(rCandidate); - basegfx::B2DPolyPolygon aLocalPolyPolygon(rHatchCandidate.getB2DPolyPolygon()); - aLocalPolyPolygon.transform(maCurrentTransformation); + // re-create a VCL hatch as base data + SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle); - if(aLocalPolyPolygon.count()) + switch(rFillHatchAttribute.getStyle()) { - // re-create a VCL hatch as base data - const attribute::FillHatchAttribute& rFillHatchAttribute = rHatchCandidate.getFillHatch(); - SvtGraphicFill::HatchType eHatch(SvtGraphicFill::hatchSingle); - - switch(rFillHatchAttribute.getStyle()) + default: // attribute::HATCHSTYLE_SINGLE : { - default: // attribute::HATCHSTYLE_SINGLE : - { - eHatch = SvtGraphicFill::hatchSingle; - break; - } - case attribute::HATCHSTYLE_DOUBLE : - { - eHatch = SvtGraphicFill::hatchDouble; - break; - } - case attribute::HATCHSTYLE_TRIPLE : - { - eHatch = SvtGraphicFill::hatchTriple; - break; - } + eHatch = SvtGraphicFill::hatchSingle; + break; + } + case attribute::HATCHSTYLE_DOUBLE : + { + eHatch = SvtGraphicFill::hatchDouble; + break; } + case attribute::HATCHSTYLE_TRIPLE : + { + eHatch = SvtGraphicFill::hatchTriple; + break; + } + } - SvtGraphicFill::Transform aTransform; + SvtGraphicFill::Transform aTransform; - // scale - aTransform.matrix[0] *= rFillHatchAttribute.getDistance(); - aTransform.matrix[4] *= rFillHatchAttribute.getDistance(); + // scale + aTransform.matrix[0] *= rFillHatchAttribute.getDistance(); + aTransform.matrix[4] *= rFillHatchAttribute.getDistance(); - // rotate (was never correct in impgrfll anyways, use correct angle now) - aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle()); - aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle()); - aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle()); - aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle()); + // rotate (was never correct in impgrfll anyways, use correct angle now) + aTransform.matrix[0] *= cos(rFillHatchAttribute.getAngle()); + aTransform.matrix[1] *= -sin(rFillHatchAttribute.getAngle()); + aTransform.matrix[3] *= sin(rFillHatchAttribute.getAngle()); + aTransform.matrix[4] *= cos(rFillHatchAttribute.getAngle()); - pSvtGraphicFill = new SvtGraphicFill( - PolyPolygon(aLocalPolyPolygon), - Color(), - 0.0, - SvtGraphicFill::fillEvenOdd, - SvtGraphicFill::fillHatch, - aTransform, - false, - eHatch, - Color(rFillHatchAttribute.getColor()), - SvtGraphicFill::gradientLinear, - Color(), - Color(), - 0, - Graphic()); - } + pSvtGraphicFill = new SvtGraphicFill( + PolyPolygon(aLocalPolyPolygon), + Color(), + 0.0, + SvtGraphicFill::fillEvenOdd, + SvtGraphicFill::fillHatch, + aTransform, + false, + eHatch, + Color(rFillHatchAttribute.getColor()), + SvtGraphicFill::gradientLinear, + Color(), + Color(), + 0, + Graphic()); } // Do use decomposition; encapsulate with SvtGraphicFill impStartSvtGraphicFill(pSvtGraphicFill); - process(rCandidate.get2DDecomposition(getViewInformation2D())); + + // #i111954# do NOT use decomposition, but use direct VCL-command + // process(rCandidate.get2DDecomposition(getViewInformation2D())); + const PolyPolygon aToolsPolyPolygon(aLocalPolyPolygon); + const HatchStyle aHatchStyle( + attribute::HATCHSTYLE_SINGLE == rFillHatchAttribute.getStyle() ? HATCH_SINGLE : + attribute::HATCHSTYLE_DOUBLE == rFillHatchAttribute.getStyle() ? HATCH_DOUBLE : + HATCH_TRIPLE); + + mpOutputDevice->DrawHatch(aToolsPolyPolygon, + Hatch(aHatchStyle, + Color(rFillHatchAttribute.getColor()), + basegfx::fround(rFillHatchAttribute.getDistance()), + basegfx::fround(rFillHatchAttribute.getAngle() / F_PI1800))); + impEndSvtGraphicFill(pSvtGraphicFill); break; @@ -1301,13 +1462,18 @@ namespace drawinglayer case PRIMITIVE2D_ID_POLYPOLYGONGRADIENTPRIMITIVE2D : { const primitive2d::PolyPolygonGradientPrimitive2D& rGradientCandidate = static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate); + basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; // for support of MetaCommentActions of the form XGRAD_SEQ_BEGIN, XGRAD_SEQ_END // it is safest to use the VCL OutputDevice::DrawGradient method which creates those. // re-create a VCL-gradient from FillGradientPrimitive2D and the needed tools PolyPolygon Gradient aVCLGradient; impConvertFillGradientAttributeToVCLGradient(aVCLGradient, rGradientCandidate.getFillGradient(), false); - basegfx::B2DPolyPolygon aLocalPolyPolygon(rGradientCandidate.getB2DPolyPolygon()); aLocalPolyPolygon.transform(maCurrentTransformation); // #i82145# ATM VCL printing of gradients using curved shapes does not work, @@ -1365,13 +1531,20 @@ namespace drawinglayer // NO usage of common own gradient randerer, not used ATM for VCL MetaFile, see text above // RenderPolyPolygonGradientPrimitive2D(static_cast< const primitive2d::PolyPolygonGradientPrimitive2D& >(rCandidate)); + break; } case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D : { const primitive2d::PolyPolygonColorPrimitive2D& rPolygonCandidate(static_cast< const primitive2d::PolyPolygonColorPrimitive2D& >(rCandidate)); - const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); basegfx::B2DPolyPolygon aLocalPolyPolygon(rPolygonCandidate.getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; + + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rPolygonCandidate.getBColor())); aLocalPolyPolygon.transform(maCurrentTransformation); // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support @@ -1433,7 +1606,11 @@ namespace drawinglayer { // there is already a clip polygon set; build clipped union of // current mask polygon and new one - maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon(aMask, maClipPolyPolygon, false, false); + maClipPolyPolygon = basegfx::tools::clipPolyPolygonOnPolyPolygon( + aMask, + maClipPolyPolygon, + true, // #i106516# we want the inside of aMask, not the outside + false); } else { @@ -1535,6 +1712,13 @@ namespace drawinglayer // single transparent PolyPolygon identified, use directly const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(pPoPoColor->getBColor())); basegfx::B2DPolyPolygon aLocalPolyPolygon(pPoPoColor->getB2DPolyPolygon()); + + // #i112245# Metafiles use tools Polygon and are not able to have more than 65535 points + // per polygon. Split polygon until there are less than that + while(fillPolyPolygonNeededToBeSplit(aLocalPolyPolygon)) + ; + + // now transform aLocalPolyPolygon.transform(maCurrentTransformation); // XPATHFILL_SEQ_BEGIN/XPATHFILL_SEQ_END support diff --git a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx index a1b1393a2fac..6a280fcad95e 100644 --- a/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclpixelprocessor2d.cxx @@ -284,20 +284,37 @@ namespace drawinglayer if(bAllowUsingDrawTransparent && 1 == rContent.getLength()) { const primitive2d::Primitive2DReference xReference(rContent[0]); - const primitive2d::PolyPolygonColorPrimitive2D* pPoPoColor = dynamic_cast< const primitive2d::PolyPolygonColorPrimitive2D* >(xReference.get()); + const primitive2d::BasePrimitive2D* pBasePrimitive = dynamic_cast< const primitive2d::BasePrimitive2D* >(xReference.get()); - if(pPoPoColor && PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D == pPoPoColor->getPrimitive2DID()) + if(pBasePrimitive) { - // single transparent PolyPolygon identified, use directly - 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; + switch(pBasePrimitive->getPrimitive2DID()) + { + case PRIMITIVE2D_ID_POLYPOLYGONCOLORPRIMITIVE2D: + { + // 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; + 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; + //} + } } } @@ -469,19 +486,29 @@ namespace drawinglayer // This is wrong in principle, but looks nicer. This could also be done here directly // without VCL usage if needed const primitive2d::FillHatchPrimitive2D& rFillHatchPrimitive = static_cast< const primitive2d::FillHatchPrimitive2D& >(rCandidate); + const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch(); // create hatch polygon in range size and discrete coordinates basegfx::B2DRange aHatchRange(rFillHatchPrimitive.getObjectRange()); aHatchRange.transform(maCurrentTransformation); const basegfx::B2DPolygon aHatchPolygon(basegfx::tools::createPolygonFromRect(aHatchRange)); + if(rFillHatchAttributes.isFillBackground()) + { + // #i111846# background fill is active; draw fill polygon + const basegfx::BColor aPolygonColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor())); + + mpOutputDevice->SetFillColor(Color(aPolygonColor)); + mpOutputDevice->SetLineColor(); + mpOutputDevice->DrawPolygon(aHatchPolygon); + } + // set hatch line color const basegfx::BColor aHatchColor(maBColorModifierStack.getModifiedColor(rFillHatchPrimitive.getBColor())); mpOutputDevice->SetFillColor(); mpOutputDevice->SetLineColor(Color(aHatchColor)); // get hatch style - const attribute::FillHatchAttribute& rFillHatchAttributes = rFillHatchPrimitive.getFillHatch(); HatchStyle eHatchStyle(HATCH_SINGLE); switch(rFillHatchAttributes.getStyle()) diff --git a/drawinglayer/source/processor3d/shadow3dextractor.cxx b/drawinglayer/source/processor3d/shadow3dextractor.cxx index 2abbcaa9f83f..9e0c0674ea66 100644 --- a/drawinglayer/source/processor3d/shadow3dextractor.cxx +++ b/drawinglayer/source/processor3d/shadow3dextractor.cxx @@ -51,6 +51,25 @@ namespace drawinglayer { namespace processor3d { + /// helper to convert from BasePrimitive2DVector to primitive2d::Primitive2DSequence + const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequenceFromBasePrimitive2DVector( + const BasePrimitive2DVector& rVector) const + { + const sal_uInt32 nCount(rVector.size()); + primitive2d::Primitive2DSequence aRetval(nCount); + + for(sal_uInt32 a(0); a < nCount; a++) + { + aRetval[a] = rVector[a]; + } + + // all entries taken over; no need to delete entries, just reset to + // mark as empty + const_cast< BasePrimitive2DVector& >(rVector).clear(); + + return aRetval; + } + // as tooling, the process() implementation takes over API handling and calls this // virtual render method when the primitive implementation is BasePrimitive3D-based. void Shadow3DExtractingProcessor::processBasePrimitive3D(const primitive3d::BasePrimitive3D& rCandidate) @@ -64,8 +83,8 @@ namespace drawinglayer const primitive3d::ShadowPrimitive3D& rPrimitive = static_cast< const primitive3d::ShadowPrimitive3D& >(rCandidate); // set new target - primitive2d::Primitive2DSequence aNewSubList; - primitive2d::Primitive2DSequence* pLastTargetSequence = mpPrimitive2DSequence; + BasePrimitive2DVector aNewSubList; + BasePrimitive2DVector* pLastTargetSequence = mpPrimitive2DSequence; mpPrimitive2DSequence = &aNewSubList; // activate convert @@ -84,21 +103,26 @@ namespace drawinglayer mbConvert = bLastConvert; mpPrimitive2DSequence = pLastTargetSequence; - // create 2d shadow primitive with result - const primitive2d::Primitive2DReference xRef(new primitive2d::ShadowPrimitive2D(rPrimitive.getShadowTransform(), rPrimitive.getShadowColor(), aNewSubList)); + // create 2d shadow primitive with result. This also fetches all entries + // from aNewSubList, so there is no need to delete them + primitive2d::BasePrimitive2D* pNew = new primitive2d::ShadowPrimitive2D( + rPrimitive.getShadowTransform(), + rPrimitive.getShadowColor(), + getPrimitive2DSequenceFromBasePrimitive2DVector(aNewSubList)); if(basegfx::fTools::more(rPrimitive.getShadowTransparence(), 0.0)) { // create simpleTransparencePrimitive, add created primitives - const primitive2d::Primitive2DSequence aNewTransPrimitiveVector(&xRef, 1L); - const primitive2d::Primitive2DReference xRef2(new primitive2d::UnifiedTransparencePrimitive2D(aNewTransPrimitiveVector, rPrimitive.getShadowTransparence())); - primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef2); - } - else - { - // add directly - primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef); + const primitive2d::Primitive2DReference xRef(pNew); + const primitive2d::Primitive2DSequence aNewTransPrimitiveVector(&xRef, 1); + + pNew = new primitive2d::UnifiedTransparencePrimitive2D( + aNewTransPrimitiveVector, + rPrimitive.getShadowTransparence()); } + + mpPrimitive2DSequence->push_back(pNew); + break; } case PRIMITIVE3D_ID_TRANSFORMPRIMITIVE3D : @@ -161,8 +185,10 @@ namespace drawinglayer if(a2DHairline.count()) { a2DHairline.transform(getObjectTransformation()); - const primitive2d::Primitive2DReference xRef(new primitive2d::PolygonHairlinePrimitive2D(a2DHairline, maPrimitiveColor)); - primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef); + mpPrimitive2DSequence->push_back( + new primitive2d::PolygonHairlinePrimitive2D( + a2DHairline, + maPrimitiveColor)); } } break; @@ -190,8 +216,10 @@ namespace drawinglayer if(a2DFill.count()) { a2DFill.transform(getObjectTransformation()); - const primitive2d::Primitive2DReference xRef(new primitive2d::PolyPolygonColorPrimitive2D(a2DFill, maPrimitiveColor)); - primitive2d::appendPrimitive2DReferenceToPrimitive2DSequence(*mpPrimitive2DSequence, xRef); + mpPrimitive2DSequence->push_back( + new primitive2d::PolyPolygonColorPrimitive2D( + a2DFill, + maPrimitiveColor)); } } break; @@ -251,6 +279,16 @@ namespace drawinglayer } } + Shadow3DExtractingProcessor::~Shadow3DExtractingProcessor() + { + OSL_ENSURE(0 == maPrimitive2DSequence.size(), + "OOps, someone used Shadow3DExtractingProcessor, but did not fetch the results (!)"); + for(sal_uInt32 a(0); a < maPrimitive2DSequence.size(); a++) + { + delete maPrimitive2DSequence[a]; + } + } + basegfx::B2DPolygon Shadow3DExtractingProcessor::impDoShadowProjection(const basegfx::B3DPolygon& rSource) { basegfx::B2DPolygon aRetval; @@ -291,6 +329,12 @@ namespace drawinglayer return aRetval; } + + const primitive2d::Primitive2DSequence Shadow3DExtractingProcessor::getPrimitive2DSequence() const + { + return getPrimitive2DSequenceFromBasePrimitive2DVector(maPrimitive2DSequence); + } + } // end of namespace processor3d } // end of namespace drawinglayer diff --git a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx index 326b9d392999..b06718d01ccb 100644 --- a/drawinglayer/source/processor3d/zbufferprocessor3d.cxx +++ b/drawinglayer/source/processor3d/zbufferprocessor3d.cxx @@ -487,7 +487,7 @@ private: boost::shared_ptr< drawinglayer::texture::GeoTexSvx > mpTransparenceGeoTexSvx; drawinglayer::attribute::MaterialAttribute3D maMaterial; basegfx::B3DPolyPolygon maPolyPolygon; - sal_uInt32 mfCenterZ; + double mfCenterZ; // bitfield bool mbModulate : 1; |