From 2bb7512e2923c860fa6d6bb55dcb000737f3a7ec Mon Sep 17 00:00:00 2001 From: Armin Le Grand Date: Tue, 2 Feb 2010 12:16:54 +0100 Subject: aw079 #i108440# Support MetaStretchTextAction in MetafilePrimitive2D decomposition --- .../drawinglayer/primitive2d/textlayoutdevice.hxx | 21 ++- .../source/primitive2d/metafileprimitive2d.cxx | 176 +++++++++++++++++---- .../source/primitive2d/textlayoutdevice.cxx | 69 ++++++-- 3 files changed, 214 insertions(+), 52 deletions(-) (limited to 'drawinglayer') diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx index f3de43c22fd7..2d2f77f34fe5 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx @@ -101,20 +101,20 @@ namespace drawinglayer double getTextWidth( const String& rText, - xub_StrLen nIndex, - xub_StrLen nLength) const; + sal_uInt32 nIndex, + sal_uInt32 nLength) const; bool getTextOutlines( basegfx::B2DPolyPolygonVector&, const String& rText, - xub_StrLen nIndex, - xub_StrLen nLength, - const ::std::vector< double >& rDXArray); + sal_uInt32 nIndex, + sal_uInt32 nLength, + const ::std::vector< double >& rDXArray) const; basegfx::B2DRange getTextBoundRect( const String& rText, - xub_StrLen nIndex, - xub_StrLen nLength) const; + sal_uInt32 nIndex, + sal_uInt32 nLength) const; double getFontAscent() const; double getFontDescent() const; @@ -123,7 +123,12 @@ namespace drawinglayer const Rectangle& rRectangle, const String& rText, sal_uInt16 nStyle, - GDIMetaFile& rGDIMetaFile); + GDIMetaFile& rGDIMetaFile) const; + + ::std::vector< double > getTextArray( + const String& rText, + sal_uInt32 nIndex, + sal_uInt32 nLength) const; }; } // end of namespace primitive2d } // end of namespace drawinglayer diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx index 4bb123380ee6..e621bed175e8 100644 --- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx @@ -981,7 +981,42 @@ namespace TargetHolders& rTargetHolders, PropertyHolders& rPropertyHolders) { - // process evtl. created primitives which belong to the current region settings + const bool bNewActive(pRegion && !pRegion->IsEmpty()); + + // #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 + // 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 + // of the properties next on the stack. + // This ClipRegion 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 + // solves the problem. + + if(!rPropertyHolders.Current().getRegionActive() && !bNewActive) + { + // no active region exchanged by no new one, done + return; + } + + if(rPropertyHolders.Current().getRegionActive() && bNewActive) + { + // active region and new active region + if(rPropertyHolders.Current().getRegion() == *pRegion) + { + // new region is the same as the old region, done + return; + } + } + + // Here the old region and the new one 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 + // MaskPrimitive2D accordingly. if(rPropertyHolders.Current().getRegionActive() && rTargetHolders.size() > 1) { drawinglayer::primitive2d::Primitive2DSequence aSubContent; @@ -1001,8 +1036,8 @@ namespace } } - // apply new settings - const bool bNewActive(pRegion && !pRegion->IsEmpty()); + // apply new settings to current properties by setting + // the new region now rPropertyHolders.Current().setRegionActive(bNewActive); if(bNewActive) @@ -1259,13 +1294,12 @@ namespace const XubString& rText, sal_uInt16 nTextStart, sal_uInt16 nTextLength, - sal_Int32* pDXArray, + const ::std::vector< double >& rDXArray, TargetHolder& rTarget, PropertyHolder& rProperty) { drawinglayer::primitive2d::BasePrimitive2D* pResult = 0; const Font& rFont = rProperty.getFont(); - std::vector< double > aDXArray; basegfx::B2DVector aAlignmentOffset(0.0, 0.0); if(nTextLength) @@ -1283,17 +1317,6 @@ namespace // add TextStartPosition aTextTransform.translate(rTextStartPosition.X(), rTextStartPosition.Y()); - // preapare DXArray (if used) - if(pDXArray && nTextLength) - { - aDXArray.reserve(nTextLength); - - for(xub_StrLen a(0); a < nTextLength; a++) - { - aDXArray.push_back((double)(*(pDXArray + a))); - } - } - // prepare FontColor and Locale const basegfx::BColor aFontColor(rProperty.getTextColor()); const com::sun::star::lang::Locale aLocale(MsLangId::convertLanguageToLocale(rProperty.getLanguageType())); @@ -1353,7 +1376,7 @@ namespace rText, nTextStart, nTextLength, - aDXArray, + rDXArray, aFontAttribute, aLocale, aFontColor, @@ -1380,7 +1403,7 @@ namespace rText, nTextStart, nTextLength, - aDXArray, + rDXArray, aFontAttribute, aLocale, aFontColor); @@ -1396,13 +1419,13 @@ namespace // get text width double fTextWidth(0.0); - if(aDXArray.empty()) + if(rDXArray.empty()) { fTextWidth = aTextLayouterDevice.getTextWidth(rText, nTextStart, nTextLength); } else { - fTextWidth = aDXArray.back(); + fTextWidth = rDXArray.back(); } if(basegfx::fTools::more(fTextWidth, 0.0)) @@ -1957,15 +1980,24 @@ namespace { /** CHECKED, WORKS WELL */ const MetaTextAction* pA = (const MetaTextAction*)pAction; + sal_uInt32 nTextLength(pA->GetLen()); + const sal_uInt32 nTextIndex(pA->GetIndex()); + const sal_uInt32 nStringLength(pA->GetText().Len()); + + if(nTextLength + nTextIndex > nStringLength) + { + nTextLength = nStringLength - nTextIndex; + } - if(pA->GetLen() && rPropertyHolders.Current().getTextColorActive()) + if(nTextLength && rPropertyHolders.Current().getTextColorActive()) { + const std::vector< double > aDXArray; proccessMetaTextAction( pA->GetPoint(), pA->GetText(), - pA->GetIndex(), - pA->GetLen(), - 0, + nTextIndex, + nTextLength, + aDXArray, rTargetHolders.Current(), rPropertyHolders.Current()); } @@ -1976,15 +2008,37 @@ namespace { /** CHECKED, WORKS WELL */ const MetaTextArrayAction* pA = (const MetaTextArrayAction*)pAction; + sal_uInt32 nTextLength(pA->GetLen()); + const sal_uInt32 nTextIndex(pA->GetIndex()); + const sal_uInt32 nStringLength(pA->GetText().Len()); - if(pA->GetLen() && rPropertyHolders.Current().getTextColorActive()) + if(nTextLength + nTextIndex > nStringLength) { + nTextLength = nStringLength - nTextIndex; + } + + if(nTextLength && rPropertyHolders.Current().getTextColorActive()) + { + // preapare DXArray (if used) + std::vector< double > aDXArray; + sal_Int32* pDXArray = pA->GetDXArray(); + + if(pDXArray) + { + aDXArray.reserve(nTextLength); + + for(sal_uInt32 a(0); a < nTextLength; a++) + { + aDXArray.push_back((double)(*(pDXArray + a))); + } + } + proccessMetaTextAction( pA->GetPoint(), pA->GetText(), - pA->GetIndex(), - pA->GetLen(), - pA->GetDXArray(), + nTextIndex, + nTextLength, + aDXArray, rTargetHolders.Current(), rPropertyHolders.Current()); } @@ -1993,10 +2047,65 @@ namespace } case META_STRETCHTEXT_ACTION : { - /** NEEDS IMPLEMENTATION */ - OSL_ENSURE(false, "META_STRETCHTEXT_ACTION requested (!)"); - // use OutputDevice::GetTextArray() to map the... - // const MetaStretchTextAction* pA = (const MetaStretchTextAction*)pAction; + // #i108440# StarMath uses MetaStretchTextAction, thus support is needed. + // It looks as if it pretty never really uses a width different from + // the default text-layout width, but it's not possible to be sure. + // Implemented getting the DXArray and checking for scale at all. If + // scale is more than 3.5% different, scale the DXArray before usage. + // New status: + + /** CHECKED, WORKS WELL */ + const MetaStretchTextAction* pA = (const MetaStretchTextAction*)pAction; + sal_uInt32 nTextLength(pA->GetLen()); + const sal_uInt32 nTextIndex(pA->GetIndex()); + const sal_uInt32 nStringLength(pA->GetText().Len()); + + if(nTextLength + nTextIndex > nStringLength) + { + nTextLength = nStringLength - nTextIndex; + } + + if(nTextLength && rPropertyHolders.Current().getTextColorActive()) + { + drawinglayer::primitive2d::TextLayouterDevice aTextLayouterDevice; + aTextLayouterDevice.setFont(rPropertyHolders.Current().getFont()); + + ::std::vector< double > aTextArray( + aTextLayouterDevice.getTextArray( + pA->GetText(), + nTextIndex, + nTextLength)); + + if(!aTextArray.empty()) + { + const double fTextLength(aTextArray.back()); + + if(0.0 != fTextLength && pA->GetWidth()) + { + const double fRelative(pA->GetWidth() / fTextLength); + + if(fabs(fRelative - 1.0) >= 0.035) + { + // when derivation is more than 3,5% from default text size, + // scale the DXArray + for(sal_uInt32 a(0); a < aTextArray.size(); a++) + { + aTextArray[a] *= fRelative; + } + } + } + } + + proccessMetaTextAction( + pA->GetPoint(), + pA->GetText(), + nTextIndex, + nTextLength, + aTextArray, + rTargetHolders.Current(), + rPropertyHolders.Current()); + } + break; } case META_TEXTRECT_ACTION : @@ -2005,8 +2114,9 @@ namespace // OSL_ENSURE(false, "META_TEXTRECT_ACTION requested (!)"); const MetaTextRectAction* pA = (const MetaTextRectAction*)pAction; const Rectangle& rRectangle = pA->GetRect(); + const sal_uInt32 nStringLength(pA->GetText().Len()); - if(!rRectangle.IsEmpty() && 0 != pA->GetText().Len()) + if(!rRectangle.IsEmpty() && 0 != nStringLength) { // The problem with this action is that it describes unlayouted text // and the layout capabilities are in EditEngine/Outliner in SVX. The diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 2950427d6b57..c7e2fcebb96f 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -223,8 +223,8 @@ namespace drawinglayer double TextLayouterDevice::getTextWidth( const String& rText, - xub_StrLen nIndex, - xub_StrLen nLength) const + sal_uInt32 nIndex, + sal_uInt32 nLength) const { return mrDevice.GetTextWidth(rText, nIndex, nLength); } @@ -232,15 +232,22 @@ namespace drawinglayer bool TextLayouterDevice::getTextOutlines( basegfx::B2DPolyPolygonVector& rB2DPolyPolyVector, const String& rText, - xub_StrLen nIndex, - xub_StrLen nLength, - const ::std::vector< double >& rDXArray) + sal_uInt32 nIndex, + sal_uInt32 nLength, + const ::std::vector< double >& rDXArray) const { const sal_uInt32 nDXArrayCount(rDXArray.size()); + sal_uInt32 nTextLength(nLength); + const sal_uInt32 nStringLength(rText.Len()); + + if(nTextLength + nIndex > nStringLength) + { + nTextLength = nStringLength - nIndex; + } if(nDXArrayCount) { - OSL_ENSURE(nDXArrayCount == nLength, "DXArray size does not correspond to text portion size (!)"); + OSL_ENSURE(nDXArrayCount == nTextLength, "DXArray size does not correspond to text portion size (!)"); std::vector< sal_Int32 > aIntegerDXArray(nDXArrayCount); for(sal_uInt32 a(0); a < nDXArrayCount; a++) @@ -274,10 +281,18 @@ namespace drawinglayer basegfx::B2DRange TextLayouterDevice::getTextBoundRect( const String& rText, - xub_StrLen nIndex, - xub_StrLen nLength) const + sal_uInt32 nIndex, + sal_uInt32 nLength) const { - if(nLength) + sal_uInt32 nTextLength(nLength); + const sal_uInt32 nStringLength(rText.Len()); + + if(nTextLength + nIndex > nStringLength) + { + nTextLength = nStringLength - nIndex; + } + + if(nTextLength) { Rectangle aRect; @@ -291,7 +306,9 @@ namespace drawinglayer // #i104432#, #i102556# take empty results into account if(!aRect.IsEmpty()) { - return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); + return basegfx::B2DRange( + aRect.Left(), aRect.Top(), + aRect.Right(), aRect.Bottom()); } } @@ -314,11 +331,41 @@ namespace drawinglayer const Rectangle& rRectangle, const String& rText, sal_uInt16 nStyle, - GDIMetaFile& rGDIMetaFile) + GDIMetaFile& rGDIMetaFile) const { mrDevice.AddTextRectActions( rRectangle, rText, nStyle, rGDIMetaFile); } + + ::std::vector< double > TextLayouterDevice::getTextArray( + const String& rText, + sal_uInt32 nIndex, + sal_uInt32 nLength) const + { + ::std::vector< double > aRetval; + sal_uInt32 nTextLength(nLength); + const sal_uInt32 nStringLength(rText.Len()); + + if(nTextLength + nIndex > nStringLength) + { + nTextLength = nStringLength - nIndex; + } + + if(nTextLength) + { + aRetval.reserve(nTextLength); + sal_Int32* pArray = new sal_Int32[nTextLength]; + mrDevice.GetTextArray(rText, pArray, nIndex, nLength); + + for(sal_uInt32 a(0); a < nTextLength; a++) + { + aRetval.push_back(pArray[a]); + } + } + + return aRetval; + } + } // end of namespace primitive2d } // end of namespace drawinglayer -- cgit v1.2.3