diff options
Diffstat (limited to 'svx/source/sdr/primitive2d/sdrdecompositiontools.cxx')
-rw-r--r-- | svx/source/sdr/primitive2d/sdrdecompositiontools.cxx | 337 |
1 files changed, 184 insertions, 153 deletions
diff --git a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx index 4a27eb73de8e..9666bd2c1ac1 100644 --- a/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx +++ b/svx/source/sdr/primitive2d/sdrdecompositiontools.cxx @@ -67,13 +67,13 @@ namespace drawinglayer namespace primitive2d { Primitive2DReference createPolyPolygonFillPrimitive( - const ::basegfx::B2DPolyPolygon& rUnitPolyPolygon, - const ::basegfx::B2DHomMatrix& rObjectTransform, + const basegfx::B2DPolyPolygon& rUnitPolyPolygon, + const basegfx::B2DHomMatrix& rObjectTransform, const attribute::SdrFillAttribute& rFill, const attribute::FillGradientAttribute* pFillGradient) { // prepare fully scaled polygon - ::basegfx::B2DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon); + basegfx::B2DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon); aScaledPolyPolygon.transform(rObjectTransform); BasePrimitive2D* pNewFillPrimitive = 0L; @@ -87,7 +87,7 @@ namespace drawinglayer } else if(rFill.isBitmap()) { - const ::basegfx::B2DRange aRange(::basegfx::tools::getRange(aScaledPolyPolygon)); + const basegfx::B2DRange aRange(basegfx::tools::getRange(aScaledPolyPolygon)); pNewFillPrimitive = new PolyPolygonBitmapPrimitive2D(aScaledPolyPolygon, rFill.getColor(), rFill.getBitmap()->getFillBitmapAttribute(aRange)); } else @@ -110,7 +110,7 @@ namespace drawinglayer // create FillGradientPrimitive2D for transparence and add to new sequence // fillGradientPrimitive is enough here (compared to PolyPolygonGradientPrimitive2D) since float transparence will be masked anyways - const ::basegfx::B2DRange aRange(::basegfx::tools::getRange(aScaledPolyPolygon)); + const basegfx::B2DRange aRange(basegfx::tools::getRange(aScaledPolyPolygon)); const Primitive2DReference xRefB(new FillGradientPrimitive2D(aRange, *pFillGradient)); const Primitive2DSequence aAlpha(&xRefB, 1L); @@ -125,13 +125,13 @@ namespace drawinglayer } Primitive2DReference createPolygonLinePrimitive( - const ::basegfx::B2DPolygon& rUnitPolygon, - const ::basegfx::B2DHomMatrix& rObjectTransform, + const basegfx::B2DPolygon& rUnitPolygon, + const basegfx::B2DHomMatrix& rObjectTransform, const attribute::SdrLineAttribute& rLine, const attribute::SdrLineStartEndAttribute* pStroke) { // prepare fully scaled polygon - ::basegfx::B2DPolygon aScaledPolygon(rUnitPolygon); + basegfx::B2DPolygon aScaledPolygon(rUnitPolygon); aScaledPolygon.transform(rObjectTransform); // create line and stroke attribute @@ -168,15 +168,15 @@ namespace drawinglayer } Primitive2DReference createTextPrimitive( - const ::basegfx::B2DPolyPolygon& rUnitPolyPolygon, - const ::basegfx::B2DHomMatrix& rObjectTransform, + const basegfx::B2DPolyPolygon& rUnitPolyPolygon, + const basegfx::B2DHomMatrix& rObjectTransform, const attribute::SdrTextAttribute& rText, const attribute::SdrLineAttribute* pStroke, bool bCellText, bool bWordWrap) { - ::basegfx::B2DHomMatrix aAnchorTransform(rObjectTransform); - SdrTextPrimitive2D* pNew = 0L; + basegfx::B2DHomMatrix aAnchorTransform(rObjectTransform); + SdrTextPrimitive2D* pNew = 0; if(rText.isContour()) { @@ -185,20 +185,20 @@ namespace drawinglayer { // take line width into account and shrink contour polygon accordingly // decompose to get scale - ::basegfx::B2DVector aScale, aTranslate; + basegfx::B2DVector aScale, aTranslate; double fRotate, fShearX; rObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX); // scale outline to object's size to allow growing with value relative to that size // and also to keep aspect ratio - ::basegfx::B2DHomMatrix aScaleTransform; + basegfx::B2DHomMatrix aScaleTransform; aScaleTransform.set(0, 0, fabs(aScale.getX())); aScaleTransform.set(1, 1, fabs(aScale.getY())); - ::basegfx::B2DPolyPolygon aScaledUnitPolyPolygon(rUnitPolyPolygon); + basegfx::B2DPolyPolygon aScaledUnitPolyPolygon(rUnitPolyPolygon); aScaledUnitPolyPolygon.transform(aScaleTransform); // grow the polygon. To shrink, use negative value (half width) - aScaledUnitPolyPolygon = ::basegfx::tools::growInNormalDirection(aScaledUnitPolyPolygon, -(pStroke->getWidth() * 0.5)); + aScaledUnitPolyPolygon = basegfx::tools::growInNormalDirection(aScaledUnitPolyPolygon, -(pStroke->getWidth() * 0.5)); // scale back to unit polygon aScaleTransform.set(0, 0, 0.0 != aScale.getX() ? 1.0 / aScale.getX() : 1.0); @@ -206,48 +206,60 @@ namespace drawinglayer aScaledUnitPolyPolygon.transform(aScaleTransform); // create with unit polygon - pNew = new SdrContourTextPrimitive2D(rText.getSdrText(), rText.getOutlinerParaObject(), aScaledUnitPolyPolygon, rObjectTransform); + pNew = new SdrContourTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + aScaledUnitPolyPolygon, + rObjectTransform); } else { // create with unit polygon - pNew = new SdrContourTextPrimitive2D(rText.getSdrText(), rText.getOutlinerParaObject(), rUnitPolyPolygon, rObjectTransform); + pNew = new SdrContourTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + rUnitPolyPolygon, + rObjectTransform); } } - else if(rText.isFontwork() && !rText.isScroll()) + else if(rText.getSdrFormTextAttribute()) { - // text on path, use scaled polygon. Not allowed when text scrolling is used. - ::basegfx::B2DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon); + // text on path, use scaled polygon + basegfx::B2DPolyPolygon aScaledPolyPolygon(rUnitPolyPolygon); aScaledPolyPolygon.transform(rObjectTransform); - pNew = new SdrPathTextPrimitive2D(rText.getSdrText(), rText.getOutlinerParaObject(), aScaledPolyPolygon); + pNew = new SdrPathTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + aScaledPolyPolygon, + *rText.getSdrFormTextAttribute()); } else { // rObjectTransform is the whole SdrObject transformation from unit rectangle // to it's size and position. Decompose to allow working with single values. - ::basegfx::B2DVector aScale, aTranslate; + basegfx::B2DVector aScale, aTranslate; double fRotate, fShearX; rObjectTransform.decompose(aScale, aTranslate, fRotate, fShearX); // extract mirroring - const bool bMirrorX(::basegfx::fTools::less(aScale.getX(), 0.0)); - const bool bMirrorY(::basegfx::fTools::less(aScale.getY(), 0.0)); + const bool bMirrorX(basegfx::fTools::less(aScale.getX(), 0.0)); + const bool bMirrorY(basegfx::fTools::less(aScale.getY(), 0.0)); aScale = basegfx::absolute(aScale); // Get the real size, since polygon ountline and scale // from the object transformation may vary (e.g. ellipse segments) - ::basegfx::B2DHomMatrix aJustScaleTransform; + basegfx::B2DHomMatrix aJustScaleTransform; aJustScaleTransform.set(0, 0, aScale.getX()); aJustScaleTransform.set(1, 1, aScale.getY()); - ::basegfx::B2DPolyPolygon aScaledUnitPolyPolygon(rUnitPolyPolygon); + basegfx::B2DPolyPolygon aScaledUnitPolyPolygon(rUnitPolyPolygon); aScaledUnitPolyPolygon.transform(aJustScaleTransform); - const ::basegfx::B2DRange aSnapRange(::basegfx::tools::getRange(aScaledUnitPolyPolygon)); + const basegfx::B2DRange aSnapRange(basegfx::tools::getRange(aScaledUnitPolyPolygon)); // create a range describing the wanted text position and size (aTextAnchorRange). This // means to use the text distance values here - const ::basegfx::B2DPoint aTopLeft(aSnapRange.getMinX() + rText.getTextLeftDistance(), aSnapRange.getMinY() + rText.getTextUpperDistance()); - const ::basegfx::B2DPoint aBottomRight(aSnapRange.getMaxX() - rText.getTextRightDistance(), aSnapRange.getMaxY() - rText.getTextLowerDistance()); - ::basegfx::B2DRange aTextAnchorRange; + const basegfx::B2DPoint aTopLeft(aSnapRange.getMinX() + rText.getTextLeftDistance(), aSnapRange.getMinY() + rText.getTextUpperDistance()); + const basegfx::B2DPoint aBottomRight(aSnapRange.getMaxX() - rText.getTextRightDistance(), aSnapRange.getMaxY() - rText.getTextLowerDistance()); + basegfx::B2DRange aTextAnchorRange; aTextAnchorRange.expand(aTopLeft); aTextAnchorRange.expand(aBottomRight); @@ -267,12 +279,21 @@ namespace drawinglayer if(rText.isFitToSize()) { // streched text in range - pNew = new SdrStretchTextPrimitive2D(rText.getSdrText(), rText.getOutlinerParaObject(), aAnchorTransform); + pNew = new SdrStretchTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + aAnchorTransform); } else // text in range { // build new primitive - pNew = new SdrBlockTextPrimitive2D(rText.getSdrText(), rText.getOutlinerParaObject(), aAnchorTransform, rText.isScroll(), bCellText, bWordWrap); + pNew = new SdrBlockTextPrimitive2D( + &rText.getSdrText(), + rText.getOutlinerParaObject(), + aAnchorTransform, + rText.isScroll(), + bCellText, + bWordWrap); } } @@ -299,154 +320,164 @@ namespace drawinglayer return Primitive2DReference(pNew); } } - else if(rText.isScroll()) - { - // get scroll direction - const SdrTextAniDirection eDirection(rText.getSdrText().GetObject().GetTextAniDirection()); - const bool bHorizontal(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection); - - // decompose to get separated values for the scroll box - ::basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - aAnchorTransform.decompose(aScale, aTranslate, fRotate, fShearX); - - // build transform from scaled only to full AnchorTransform and inverse - ::basegfx::B2DHomMatrix aSRT; - aSRT.shearX(fShearX); - aSRT.rotate(fRotate); - aSRT.translate(aTranslate.getX(), aTranslate.getY()); - ::basegfx::B2DHomMatrix aISRT(aSRT); - aISRT.invert(); - - // bring the primitive back to scaled only and get scaled range, create new clone for this - SdrTextPrimitive2D* pNew2 = pNew->createTransformedClone(aISRT); - OSL_ENSURE(pNew2, "createTextPrimitive: Could not create transformed clone of text primitive (!)"); - delete pNew; - pNew = pNew2; - - // create neutral geometry::ViewInformation2D for local range and decompose calls. This is okay - // since the decompose is view-independent - const uno::Sequence< beans::PropertyValue > xViewParameters; - geometry::ViewInformation2D aViewInformation2D(xViewParameters); - - // get range - const ::basegfx::B2DRange aScaledRange(pNew->getB2DRange(aViewInformation2D)); - - // create left outside and right outside transformations. Also take care - // of the clip rectangle - ::basegfx::B2DHomMatrix aLeft, aRight; - ::basegfx::B2DPoint aClipTopLeft(0.0, 0.0); - ::basegfx::B2DPoint aClipBottomRight(aScale.getX(), aScale.getY()); - - if(bHorizontal) - { - aClipTopLeft.setY(aScaledRange.getMinY()); - aClipBottomRight.setY(aScaledRange.getMaxY()); - aLeft.translate(-aScaledRange.getMaxX(), 0.0); - aRight.translate(aScale.getX() - aScaledRange.getMinX(), 0.0); - } - else - { - aClipTopLeft.setX(aScaledRange.getMinX()); - aClipBottomRight.setX(aScaledRange.getMaxX()); - aLeft.translate(0.0, -aScaledRange.getMaxY()); - aRight.translate(0.0, aScale.getY() - aScaledRange.getMinY()); - } - - aLeft *= aSRT; - aRight *= aSRT; - // prepare animation list - drawinglayer::animation::AnimationEntryList aAnimationList; - - if(bHorizontal) - { - rText.getScrollTextTiming(aAnimationList, aScale.getX(), aScaledRange.getWidth()); - } - else + if(rText.isScroll()) + { + // suppress scroll when FontWork + if(!rText.getSdrFormTextAttribute()) { - rText.getScrollTextTiming(aAnimationList, aScale.getY(), aScaledRange.getHeight()); - } + // get scroll direction + const SdrTextAniDirection eDirection(rText.getSdrText().GetObject().GetTextAniDirection()); + const bool bHorizontal(SDRTEXTANI_LEFT == eDirection || SDRTEXTANI_RIGHT == eDirection); - if(0.0 != aAnimationList.getDuration()) - { - // create a new Primitive2DSequence containing the animated text in it's scaled only state. - // use the decomposition to force to simple text primitives, those will no longer - // need the outliner for formatting (alternatively it is also possible to just add - // pNew to aNewPrimitiveSequence) - Primitive2DSequence aAnimSequence(pNew->get2DDecomposition(aViewInformation2D)); + // decompose to get separated values for the scroll box + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + aAnchorTransform.decompose(aScale, aTranslate, fRotate, fShearX); + + // build transform from scaled only to full AnchorTransform and inverse + basegfx::B2DHomMatrix aSRT; + aSRT.shearX(fShearX); + aSRT.rotate(fRotate); + aSRT.translate(aTranslate.getX(), aTranslate.getY()); + basegfx::B2DHomMatrix aISRT(aSRT); + aISRT.invert(); + + // bring the primitive back to scaled only and get scaled range, create new clone for this + SdrTextPrimitive2D* pNew2 = pNew->createTransformedClone(aISRT); + OSL_ENSURE(pNew2, "createTextPrimitive: Could not create transformed clone of text primitive (!)"); delete pNew; + pNew = pNew2; + + // create neutral geometry::ViewInformation2D for local range and decompose calls. This is okay + // since the decompose is view-independent + const uno::Sequence< beans::PropertyValue > xViewParameters; + geometry::ViewInformation2D aViewInformation2D(xViewParameters); + + // get range + const basegfx::B2DRange aScaledRange(pNew->getB2DRange(aViewInformation2D)); + + // create left outside and right outside transformations. Also take care + // of the clip rectangle + basegfx::B2DHomMatrix aLeft, aRight; + basegfx::B2DPoint aClipTopLeft(0.0, 0.0); + basegfx::B2DPoint aClipBottomRight(aScale.getX(), aScale.getY()); + + if(bHorizontal) + { + aClipTopLeft.setY(aScaledRange.getMinY()); + aClipBottomRight.setY(aScaledRange.getMaxY()); + aLeft.translate(-aScaledRange.getMaxX(), 0.0); + aRight.translate(aScale.getX() - aScaledRange.getMinX(), 0.0); + } + else + { + aClipTopLeft.setX(aScaledRange.getMinX()); + aClipBottomRight.setX(aScaledRange.getMaxX()); + aLeft.translate(0.0, -aScaledRange.getMaxY()); + aRight.translate(0.0, aScale.getY() - aScaledRange.getMinY()); + } + + aLeft *= aSRT; + aRight *= aSRT; + + // prepare animation list + drawinglayer::animation::AnimationEntryList aAnimationList; + + if(bHorizontal) + { + rText.getScrollTextTiming(aAnimationList, aScale.getX(), aScaledRange.getWidth()); + } + else + { + rText.getScrollTextTiming(aAnimationList, aScale.getY(), aScaledRange.getHeight()); + } + + if(0.0 != aAnimationList.getDuration()) + { + // create a new Primitive2DSequence containing the animated text in it's scaled only state. + // use the decomposition to force to simple text primitives, those will no longer + // need the outliner for formatting (alternatively it is also possible to just add + // pNew to aNewPrimitiveSequence) + Primitive2DSequence aAnimSequence(pNew->get2DDecomposition(aViewInformation2D)); + delete pNew; + + // create a new animatedInterpolatePrimitive and add it + std::vector< basegfx::B2DHomMatrix > aMatrixStack; + aMatrixStack.push_back(aLeft); + aMatrixStack.push_back(aRight); + const Primitive2DReference xRefA(new AnimatedInterpolatePrimitive2D(aMatrixStack, aAnimationList, aAnimSequence, true)); + const Primitive2DSequence aContent(&xRefA, 1L); + + // scrolling needs an encapsulating clipping primitive + const basegfx::B2DRange aClipRange(aClipTopLeft, aClipBottomRight); + basegfx::B2DPolygon aClipPolygon(basegfx::tools::createPolygonFromRect(aClipRange)); + aClipPolygon.transform(aSRT); + return Primitive2DReference(new MaskPrimitive2D(basegfx::B2DPolyPolygon(aClipPolygon), aContent)); + } + else + { + // add to decomposition + return Primitive2DReference(pNew); + } + } + } - // create a new animatedInterpolatePrimitive and add it - std::vector< basegfx::B2DHomMatrix > aMatrixStack; - aMatrixStack.push_back(aLeft); - aMatrixStack.push_back(aRight); - const Primitive2DReference xRefA(new AnimatedInterpolatePrimitive2D(aMatrixStack, aAnimationList, aAnimSequence, true)); - const Primitive2DSequence aContent(&xRefA, 1L); + if(rText.isInEditMode()) + { + // #i97628# + // encapsulate with TextHierarchyEditPrimitive2D to allow renderers + // to suppress actively edited content if needed + const Primitive2DReference xRefA(pNew); + const Primitive2DSequence aContent(&xRefA, 1L); - // scrolling needs an encapsulating clipping primitive - const ::basegfx::B2DRange aClipRange(aClipTopLeft, aClipBottomRight); - ::basegfx::B2DPolygon aClipPolygon(::basegfx::tools::createPolygonFromRect(aClipRange)); - aClipPolygon.transform(aSRT); - return Primitive2DReference(new MaskPrimitive2D(::basegfx::B2DPolyPolygon(aClipPolygon), aContent)); - } - else - { - // add to decomposition - return Primitive2DReference(pNew); - } + // create and add TextHierarchyEditPrimitive2D primitive + return Primitive2DReference(new TextHierarchyEditPrimitive2D(aContent)); } else { - if(rText.isInEditMode()) - { - // #i97628# - // encapsulate with TextHierarchyEditPrimitive2D to allow renderers - // to suppress actively edited content if needed - const Primitive2DReference xRefA(pNew); - const Primitive2DSequence aContent(&xRefA, 1L); - - // create and add TextHierarchyEditPrimitive2D primitive - return Primitive2DReference(new TextHierarchyEditPrimitive2D(aContent)); - } - else - { - // add to decomposition - return Primitive2DReference(pNew); - } + // add to decomposition + return Primitive2DReference(pNew); } } - Primitive2DReference createShadowPrimitive( - const Primitive2DSequence& rSource, + Primitive2DSequence createEmbeddedShadowPrimitive( + const Primitive2DSequence& rContent, const attribute::SdrShadowAttribute& rShadow) { - // create Shadow primitives. Need to be added in front, should use already created primitives - if(rSource.hasElements()) + if(rContent.hasElements()) { + Primitive2DSequence aRetval(2); + basegfx::B2DHomMatrix aShadowOffset; + // prepare shadow offset - ::basegfx::B2DHomMatrix aShadowOffset; aShadowOffset.set(0, 2, rShadow.getOffset().getX()); aShadowOffset.set(1, 2, rShadow.getOffset().getY()); // create shadow primitive and add content - const Primitive2DReference xRefShadow(new ShadowPrimitive2D(aShadowOffset, rShadow.getColor(), rSource)); + aRetval[0] = Primitive2DReference( + new ShadowPrimitive2D( + aShadowOffset, + rShadow.getColor(), + rContent)); if(0.0 != rShadow.getTransparence()) { // create SimpleTransparencePrimitive2D - const Primitive2DSequence aContent(&xRefShadow, 1L); - return Primitive2DReference(new UnifiedAlphaPrimitive2D(aContent, rShadow.getTransparence())); - } - else - { - // return directly - return xRefShadow; + const Primitive2DSequence aTempContent(&aRetval[0], 1); + + aRetval[0] = Primitive2DReference( + new UnifiedAlphaPrimitive2D( + aTempContent, + rShadow.getTransparence())); } + + aRetval[1] = Primitive2DReference(new GroupPrimitive2D(rContent)); + return aRetval; } else { - return Primitive2DReference(); + return rContent; } } } // end of namespace primitive2d |