diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 4ba2fde..77c3811 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -273,13 +273,16 @@ namespace drawinglayer } } + // tdf#92849 added bAddEmphasisAscent basegfx::B2DRange TextLayouterDevice::getTextBoundRect( const OUString& rText, sal_uInt32 nIndex, - sal_uInt32 nLength) const + sal_uInt32 nLength, + bool bAddEmphasisAscent) const { sal_uInt32 nTextLength(nLength); const sal_uInt32 nStringLength(rText.getLength()); + basegfx::B2DRange aRetval; if(nTextLength + nIndex > nStringLength) { @@ -300,13 +303,21 @@ namespace drawinglayer // #i104432#, #i102556# take empty results into account if(!aRect.IsEmpty()) { - return basegfx::B2DRange( + aRetval = basegfx::B2DRange( aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); } } - return basegfx::B2DRange(); + // tdf#92849 expand in Y by EmphasisAscent if asked for + if(bAddEmphasisAscent && !aRetval.isEmpty()) + { + aRetval = basegfx::B2DRange( + aRetval.getMinX(), aRetval.getMinY() - mrDevice.getEmphasisAscent(), + aRetval.getMaxX(), aRetval.getMaxY() + mrDevice.getEmphasisAscent()); + } + + return aRetval; } double TextLayouterDevice::getFontAscent() const diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 43aaa2b..5e86a9a 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -159,7 +159,8 @@ namespace drawinglayer if(nCount) { - // prepare object transformation for polygons + // prepare object transformation for range. Do not use getTextTransform(), aScale + // may have beed adapted by getCorrectedScaleAndFontScale rTransformation = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( aScale, fShearX, fRotate, aTranslate); } @@ -167,6 +168,52 @@ namespace drawinglayer } } + // tdf#92849 added bAddEmphasisAscent + basegfx::B2DRange TextSimplePortionPrimitive2D::getTextBackgroundRange( + basegfx::B2DHomMatrix& rTransformation, + bool bAddEmphasisAscent) const + { + basegfx::B2DRange aRetval; + + if(getTextLength()) + { + // decompose object transformation to single values + basegfx::B2DVector aScale, aTranslate; + double fRotate, fShearX; + + if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)) + { + // for the TextLayouterDevice, it is necessary to have a scaling representing + // the font size. Since we want to extract polygons here, it is okay to + // work just with scaling and to ignore shear, rotation and translation, + // all that can be applied to the polygons later + const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); + + // prepare textlayoutdevice + TextLayouterDevice aTextLayouter; + aTextLayouter.setFontAttribute( + getFontAttribute(), + aFontScale.getX(), + aFontScale.getY(), + getLocale()); + + // get text range + // tdf#92849 added bAddEmphasisAscent + aRetval = aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength(), bAddEmphasisAscent); + + if(!aRetval.isEmpty()) + { + // prepare object transformation for range. Do not use getTextTransform(), aScale + // may have beed adapted by getCorrectedScaleAndFontScale + rTransformation = basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( + aScale, fShearX, fRotate, aTranslate); + } + } + } + + return aRetval; + } + Primitive2DSequence TextSimplePortionPrimitive2D::create2DDecomposition(const geometry::ViewInformation2D& /*rViewInformation*/) const { Primitive2DSequence aRetval; @@ -283,43 +330,19 @@ namespace drawinglayer { if(maB2DRange.isEmpty() && getTextLength()) { - // get TextBoundRect as base size - // decompose object transformation to single values - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; + // get untransformed range and range transformation from helper + // tdf#92849 added bAddEmphasisAscent, use local helper + basegfx::B2DHomMatrix aRangeTransformation; + basegfx::B2DRange aNewRange = getTextBackgroundRange(aRangeTransformation, false); - if(getTextTransform().decompose(aScale, aTranslate, fRotate, fShearX)) + // only apply and set when range is not empty + if(!aNewRange.isEmpty()) { - // for the TextLayouterDevice, it is necessary to have a scaling representing - // the font size. Since we want to extract polygons here, it is okay to - // work just with scaling and to ignore shear, rotation and translation, - // all that can be applied to the polygons later - const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); - - // prepare textlayoutdevice - TextLayouterDevice aTextLayouter; - aTextLayouter.setFontAttribute( - getFontAttribute(), - aFontScale.getX(), - aFontScale.getY(), - getLocale()); + // apply range transformation to it + aNewRange.transform(aRangeTransformation); - // get basic text range - basegfx::B2DRange aNewRange(aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength())); - - // #i104432#, #i102556# take empty results into account - if(!aNewRange.isEmpty()) - { - // prepare object transformation for range - const basegfx::B2DHomMatrix aRangeTransformation(basegfx::tools::createScaleShearXRotateTranslateB2DHomMatrix( - aScale, fShearX, fRotate, aTranslate)); - - // apply range transformation to it - aNewRange.transform(aRangeTransformation); - - // assign to buffered value - const_cast< TextSimplePortionPrimitive2D* >(this)->maB2DRange = aNewRange; - } + // assign to buffered value + const_cast< TextSimplePortionPrimitive2D* >(this)->maB2DRange = aNewRange; } } diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index b50c836a..582e8da 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -268,9 +268,30 @@ namespace drawinglayer mpOutputDevice->SetLayoutMode(nRTLLayoutMode); } + // tdf#92849 font needs to be set before text background gets processed mpOutputDevice->SetFont(aFont); mpOutputDevice->SetTextColor(Color(aRGBFontColor)); + // tdf#92849 + static bool bOwnHandlingOfTextBackgroundColor = true; + + if(bOwnHandlingOfTextBackgroundColor && !aFont.IsTransparent()) + { + basegfx::B2DHomMatrix aTextRangeTransformation; + const basegfx::B2DRange aTextRange = rTextCandidate.getTextBackgroundRange(aTextRangeTransformation, true); + + if(!aTextRange.isEmpty()) + { + basegfx::B2DPolygon aOutline(basegfx::tools::createPolygonFromRect(aTextRange)); + aOutline.transform(aTextRangeTransformation); + const primitive2d::PolyPolygonColorPrimitive2D aTextBackgroundColorPrimitive( + basegfx::B2DPolyPolygon(aOutline), + aFont.GetFillColor().getBColor()); + processBasePrimitive2D(aTextBackgroundColorPrimitive); + aFont.SetTransparent(true); + } + } + OUString aText( rTextCandidate.getText() ); sal_Int32 nPos = rTextCandidate.getTextPosition(); sal_Int32 nLen = rTextCandidate.getTextLength(); diff --git a/include/drawinglayer/primitive2d/textlayoutdevice.hxx b/include/drawinglayer/primitive2d/textlayoutdevice.hxx index 720a273..0bf06e8 100644 --- a/include/drawinglayer/primitive2d/textlayoutdevice.hxx +++ b/include/drawinglayer/primitive2d/textlayoutdevice.hxx @@ -91,10 +91,12 @@ namespace drawinglayer sal_uInt32 nLength, const ::std::vector< double >& rDXArray) const; + // tdf#92849 added bAddEmphasisAscent basegfx::B2DRange getTextBoundRect( const rtl::OUString& rText, sal_uInt32 nIndex, - sal_uInt32 nLength) const; + sal_uInt32 nLength, + bool bAddEmphasisAscent) const; double getFontAscent() const; double getFontDescent() const; diff --git a/include/drawinglayer/primitive2d/textprimitive2d.hxx b/include/drawinglayer/primitive2d/textprimitive2d.hxx index bfd4f20..512e9f3 100644 --- a/include/drawinglayer/primitive2d/textprimitive2d.hxx +++ b/include/drawinglayer/primitive2d/textprimitive2d.hxx @@ -159,6 +159,13 @@ namespace drawinglayer */ void getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const; + /** tdf#92849 get the text background range and it's according ObjectTransformation. This is e.g. + used to visualize the area behind the text when it is filled with a color (TextBackgroundColor). + */ + basegfx::B2DRange getTextBackgroundRange( + basegfx::B2DHomMatrix& rTransformation, + bool bAddEmphasisAscent) const; + /// data read access const basegfx::B2DHomMatrix& getTextTransform() const { return maTextTransform; } const OUString& getText() const { return maText; } diff --git a/include/vcl/outdev.hxx b/include/vcl/outdev.hxx index f4cbc5f..fb43142 100644 --- a/include/vcl/outdev.hxx +++ b/include/vcl/outdev.hxx @@ -1265,6 +1265,9 @@ public: bool GetFontCharMap( FontCharMapPtr& rFontCharMap ) const; bool GetFontCapabilities( vcl::FontCapabilities& rFontCapabilities ) const; + // tdf#92849 allow read access to EmphasisAscent + long getEmphasisAscent() const { return mnEmphasisAscent; } + /** Retrieve detailed font information in platform independent structure @param nFallbacklevel Fallback font level (0 = best matching font) diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index 5e2c380..4255ea6 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -593,9 +593,10 @@ namespace drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; aTextLayouterDevice.setFont(pInfo->mrFont); + // tdf#92849 added bAddEmphasisAscent const basegfx::B2DRange aTextBoundRect( aTextLayouterDevice.getTextBoundRect( - pInfo->maText, pInfo->mnTextStart, pInfo->mnTextLen)); + pInfo->maText, pInfo->mnTextStart, pInfo->mnTextLen, false)); const basegfx::B2DPoint aTopLeft(aTextBoundRect.getMinimum() + aStartPosition); if(!maClipRange.isInside(aTopLeft))