diff options
author | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-09-17 10:29:02 +0000 |
---|---|---|
committer | Jens-Heiner Rechtien <hr@openoffice.org> | 2009-09-17 10:29:02 +0000 |
commit | 762181f6f1168e0eb54009990222d7cb4cebebd5 (patch) | |
tree | eae0197fb4e9ee2549d31e358f01386145cff5a9 /drawinglayer | |
parent | 4e5d76b3cef5a863d5961e33a0c08c26b0b6dc2d (diff) |
CWS-TOOLING: integrate CWS aw077
2009-09-17 Armin Le Grand #resolved conflicts for integration
2009-09-07 Armin Le Grand #i103058# re-added handling of StatusBar texts for DrawObject creation, added FullDrag for circle-similar shapes (all in the ellipse toolbar)
2009-09-03 Armin Le Grand #i100514# extended TextAttributes and handling, adapted for super/subscript, adapted WordBreaking (again)
2009-09-02 Armin Le Grand #i104432# secured TextLayouterDevice::getTextBoundRect implementation and usage
2009-09-02 Armin Le Grand #i104232#, #i100514# Mainly solved 1st one, no more local SpellCheck remembering, but adding to compare op's where needed
2009-08-19 Armin Le Grand #i100514# commited in-between version due to 2week holiday
2009-08-13 Armin Le Grand #i99157# applied changes to BitmapEx and SdrHdlBitmapSet
2009-08-06 Armin Le Grand #i100357# added clipping for too big MetaFiles
Diffstat (limited to 'drawinglayer')
7 files changed, 353 insertions, 290 deletions
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx index b9639aeacc50..df09718a7582 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textlayoutdevice.hxx @@ -76,8 +76,11 @@ namespace drawinglayer ~TextLayouterDevice(); void setFont(const Font& rFont); - void setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform, const ::com::sun::star::lang::Locale & rLocale); - void setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, const ::com::sun::star::lang::Locale & rLocale); + void setFontAttributes( + const FontAttributes& rFontAttributes, + double fFontScaleX, + double fFontScaleY, + const ::com::sun::star::lang::Locale & rLocale); double getTextHeight() const; double getOverlineHeight() const; @@ -85,9 +88,6 @@ namespace drawinglayer double getUnderlineHeight() const; double getUnderlineOffset() const; double getStrikeoutOffset() const; -#ifdef WIN32 - double getCurrentFontRelation() const; -#endif double getTextWidth( const String& rText, @@ -99,9 +99,7 @@ namespace drawinglayer const String& rText, xub_StrLen nIndex, xub_StrLen nLength, - // #i89784# added suppirt for DXArray for justified text - const ::std::vector< double >& rDXArray, - double fFontScaleWidth); + const ::std::vector< double >& rDXArray); basegfx::B2DRange getTextBoundRect( const String& rText, @@ -112,27 +110,33 @@ namespace drawinglayer } // end of namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// +// helper methods for vcl font handling namespace drawinglayer { namespace primitive2d { - // helper methods for vcl font handling + // Create a VCL-Font based on the definitions in FontAttributes + // and the given FontScaling. The FontScaling defines the FontHeight + // (fFontScaleY) and the FontWidth (fFontScaleX). The combination of + // both defines FontStretching, where no stretching happens at + // fFontScaleY == fFontScaleX Font getVclFontFromFontAttributes( const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, double fFontRotation, - const ::com::sun::star::lang::Locale & rLocale, - const OutputDevice& rOutDev); - - Font getVclFontFromFontAttributes( - const FontAttributes& rFontAttributes, - const basegfx::B2DHomMatrix& rTransform, - const ::com::sun::star::lang::Locale & rLocale, - const OutputDevice& rOutDev); - - FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong); + const ::com::sun::star::lang::Locale & rLocale); + + // Generate FontAttributes DataSet derived from the given VCL-Font. + // The FontScaling with fFontScaleY, fFontScaleX relationship (see + // above) will be set in return parameter o_rSize to allow further + // processing + FontAttributes getFontAttributesFromVclFont( + basegfx::B2DVector& o_rSize, + const Font& rFont, + bool bRTL, + bool bBiDiStrong); } // end of namespace primitive2d } // end of namespace drawinglayer diff --git a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx index 9515fcc22ee8..d7f9bdb1e89a 100644 --- a/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx +++ b/drawinglayer/inc/drawinglayer/primitive2d/textprimitive2d.hxx @@ -158,14 +158,6 @@ namespace drawinglayer // the necessary VCL outline extractins, scaling adaptions and other stuff. void getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const; - // adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted - // scale from a text transformation. A copy goes to rFontScale and is modified so that - // it contains only positive scalings and XY-equal scalings to allow to get a non-X-scaled - // Vcl-Font for TextLayouter. rScale is adapted accordingly to contain the corrected scale - // which would need to be applied to e.g. outlines received from TextLayouter under - // usage of fontScale. This includes Y-Scale, X-Scale-correction and mirrorings. - void getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale, basegfx::B2DVector& rFontScale) const; - // get data const basegfx::B2DHomMatrix& getTextTransform() const { return maTextTransform; } const String& getText() const { return maText; } diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx index ffceaf8ce04a..1ed826dab562 100644 --- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx @@ -266,7 +266,38 @@ namespace drawinglayer case GRAPHIC_GDIMETAFILE : { - xPrimitive = Primitive2DReference(new MetafilePrimitive2D(getTransform(), aTransformedGraphic.GetGDIMetaFile())); + // create MetafilePrimitive2D + const GDIMetaFile& rMetafile = aTransformedGraphic.GetGDIMetaFile(); + + xPrimitive = Primitive2DReference( + new MetafilePrimitive2D( + getTransform(), + rMetafile)); + + // #i100357# find out if clipping is needed for this primitive. Unfortunately, + // there exist Metafiles who's content is bigger than the proposed PrefSize set + // at them. This is an error, but we need to work around this + const Size aMetaFilePrefSize(rMetafile.GetPrefSize()); + const Size aMetaFileRealSize( + const_cast< GDIMetaFile& >(rMetafile).GetBoundRect( + *Application::GetDefaultDevice()).GetSize()); + + if(aMetaFileRealSize.getWidth() > aMetaFilePrefSize.getWidth() + || aMetaFileRealSize.getHeight() > aMetaFilePrefSize.getHeight()) + { + // clipping needed. Embed to MaskPrimitive2D. Create childs and mask polygon + const primitive2d::Primitive2DSequence aChildContent(&xPrimitive, 1); + basegfx::B2DPolygon aMaskPolygon( + basegfx::tools::createPolygonFromRect( + basegfx::B2DRange(0.0, 0.0, 1.0, 1.0))); + aMaskPolygon.transform(getTransform()); + + xPrimitive = Primitive2DReference( + new MaskPrimitive2D( + basegfx::B2DPolyPolygon(aMaskPolygon), + aChildContent)); + } + break; } diff --git a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx index 94e92a149e50..d337950c6c6b 100644 --- a/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textdecoratedprimitive2d.cxx @@ -277,15 +277,16 @@ namespace drawinglayer const FontAttributes& rFontAttributes) const { // create the SimpleTextPrimitive needed in any case - rTarget.push_back(Primitive2DReference(new TextSimplePortionPrimitive2D( - rDecTrans.getB2DHomMatrix(), - rText, - aTextPosition, - aTextLength, - rDXArray, - rFontAttributes, - getLocale(), - getFontColor()))); + rTarget.push_back(Primitive2DReference( + new TextSimplePortionPrimitive2D( + rDecTrans.getB2DHomMatrix(), + rText, + aTextPosition, + aTextLength, + rDXArray, + rFontAttributes, + getLocale(), + getFontColor()))); // see if something else needs to be done const bool bOverlineUsed(FONT_UNDERLINE_NONE != getFontOverline()); @@ -305,7 +306,11 @@ namespace drawinglayer // TextLayouterDevice is needed to get metrics for text decorations like // underline/strikeout/emphasis marks from it. For setup, the font size is needed - aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY(), getLocale()); + aTextLayouter.setFontAttributes( + getFontAttributes(), + rDecTrans.getScale().getX(), + rDecTrans.getScale().getY(), + getLocale()); // get text width double fTextWidth(0.0); @@ -317,6 +322,14 @@ namespace drawinglayer else { fTextWidth = rDXArray.back() * rDecTrans.getScale().getX(); + const double fFontScaleX(rDecTrans.getScale().getX()); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + // need to take FontScaling out of the DXArray + fTextWidth /= fFontScaleX; + } } if(bOverlineUsed) @@ -343,28 +356,26 @@ namespace drawinglayer const String aSingleCharString(aStrikeoutChar); const double fStrikeCharWidth(aTextLayouter.getTextWidth(aSingleCharString, 0, 1)); const double fStrikeCharCount(fabs(fTextWidth/fStrikeCharWidth)); - const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.9)); - const double fScaleX(rDecTrans.getScale().getX()); - const double fStrikeCharWidthUnscaled(basegfx::fTools::equalZero(fScaleX) ? fStrikeCharWidth : fStrikeCharWidth/fScaleX); - + const sal_uInt32 nStrikeCharCount(static_cast< sal_uInt32 >(fStrikeCharCount + 0.5)); std::vector<double> aDXArray(nStrikeCharCount); String aStrikeoutString; for(sal_uInt32 a(0); a < nStrikeCharCount; a++) { aStrikeoutString += aSingleCharString; - aDXArray[a] = (a + 1) * fStrikeCharWidthUnscaled; + aDXArray[a] = (a + 1) * fStrikeCharWidth; } - rTarget.push_back(Primitive2DReference(new TextSimplePortionPrimitive2D( - rDecTrans.getB2DHomMatrix(), - aStrikeoutString, - 0, - aStrikeoutString.Len(), - aDXArray, - rFontAttributes, - getLocale(), - getFontColor()))); + rTarget.push_back(Primitive2DReference( + new TextSimplePortionPrimitive2D( + rDecTrans.getB2DHomMatrix(), + aStrikeoutString, + 0, + aStrikeoutString.Len(), + aDXArray, + rFontAttributes, + getLocale(), + getFontColor()))); } else { @@ -483,17 +494,15 @@ namespace drawinglayer xLocalBreakIterator.set(xMSF->createInstance(rtl::OUString::createFromAscii("com.sun.star.i18n.BreakIterator")), ::com::sun::star::uno::UNO_QUERY); } - if(xLocalBreakIterator.is()) + if(xLocalBreakIterator.is() && getTextLength()) { // init word iterator, get first word and truncate to possibilities ::com::sun::star::i18n::Boundary aNextWordBoundary(xLocalBreakIterator->getWordBoundary( getText(), getTextPosition(), getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True)); - if(aNextWordBoundary.endPos == getTextPosition() && getTextLength() > 0) + if(aNextWordBoundary.endPos == getTextPosition()) { - // #i96474# - // a word before was found (this can happen when search starts on a whitespace and a word - // in front of it exists), force to look one position further + // backward hit, force next word aNextWordBoundary = xLocalBreakIterator->getWordBoundary( getText(), getTextPosition() + 1, getLocale(), ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); } @@ -526,7 +535,11 @@ namespace drawinglayer if(bNoDXArray) { // ..but only completely when no DXArray - aTextLayouter.setFontAttributes(getFontAttributes(), rDecTrans.getScale().getX(), rDecTrans.getScale().getY(),getLocale()); + aTextLayouter.setFontAttributes( + getFontAttributes(), + rDecTrans.getScale().getX(), + rDecTrans.getScale().getY(), + getLocale()); } // do iterate over single words @@ -566,12 +579,25 @@ namespace drawinglayer fOffset = getDXArray()[nIndex - 1]; } + // need offset without FontScale for building the new transformation. The + // new transformation will be multiplied with the current text transformation + // so FontScale would be double + double fOffsetNoScale(fOffset); + const double fFontScaleX(rDecTrans.getScale().getX()); + + if(!basegfx::fTools::equal(fFontScaleX, 1.0) + && !basegfx::fTools::equalZero(fFontScaleX)) + { + fOffsetNoScale /= fFontScaleX; + } + // apply needed offset to transformation - aNewTransform.translate(fOffset, 0.0); + aNewTransform.translate(fOffsetNoScale, 0.0); if(!bNoDXArray) { - // DXArray values need to be corrected with the offset, too + // DXArray values need to be corrected with the offset, too. Here, + // take the scaled offset since the DXArray is scaled const sal_uInt32 nArraySize(aNewDXArray.size()); for(sal_uInt32 a(0); a < nArraySize; a++) @@ -591,12 +617,30 @@ namespace drawinglayer impCreateGeometryContent(rTarget, aDecTrans, getText(), nNewTextStart, nNewTextEnd - nNewTextStart, aNewDXArray, aNewFontAttributes); - // prepare next word and truncate to possibilities - aNextWordBoundary = xLocalBreakIterator->nextWord( - getText(), aNextWordBoundary.endPos, getLocale(), - ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES); + if(aNextWordBoundary.endPos >= getTextPosition() + getTextLength()) + { + // end reached + aNextWordBoundary.startPos = aNextWordBoundary.endPos; + } + else + { + // get new word portion + const sal_Int32 nLastEndPos(aNextWordBoundary.endPos); + + aNextWordBoundary = xLocalBreakIterator->getWordBoundary( + getText(), aNextWordBoundary.endPos, getLocale(), + ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); - impCorrectTextBoundary(aNextWordBoundary); + if(nLastEndPos == aNextWordBoundary.endPos) + { + // backward hit, force next word + aNextWordBoundary = xLocalBreakIterator->getWordBoundary( + getText(), nLastEndPos + 1, getLocale(), + ::com::sun::star::i18n::WordType::ANYWORD_IGNOREWHITESPACES, sal_True); + } + + impCorrectTextBoundary(aNextWordBoundary); + } } } } diff --git a/drawinglayer/source/primitive2d/textlayoutdevice.cxx b/drawinglayer/source/primitive2d/textlayoutdevice.cxx index 0055af3ea4bd..e321783c8406 100644 --- a/drawinglayer/source/primitive2d/textlayoutdevice.cxx +++ b/drawinglayer/source/primitive2d/textlayoutdevice.cxx @@ -43,6 +43,7 @@ #include <vcl/metric.hxx> #include <i18npool/mslangid.hxx> #include <drawinglayer/primitive2d/textprimitive2d.hxx> +#include <vcl/svapp.hxx> ////////////////////////////////////////////////////////////////////////////// // VDev RevDevice provider @@ -166,14 +167,18 @@ namespace drawinglayer mrDevice.SetFont( rFont ); } - void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, const basegfx::B2DHomMatrix& rTransform, const ::com::sun::star::lang::Locale & rLocale) - { - setFont(getVclFontFromFontAttributes(rFontAttributes, rTransform, rLocale, mrDevice)); - } - - void TextLayouterDevice::setFontAttributes(const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, const ::com::sun::star::lang::Locale & rLocale) + void TextLayouterDevice::setFontAttributes( + const FontAttributes& rFontAttributes, + double fFontScaleX, + double fFontScaleY, + const ::com::sun::star::lang::Locale& rLocale) { - setFont(getVclFontFromFontAttributes(rFontAttributes, fFontScaleX, fFontScaleY, 0.0, rLocale, mrDevice)); + setFont(getVclFontFromFontAttributes( + rFontAttributes, + fFontScaleX, + fFontScaleY, + 0.0, + rLocale)); } double TextLayouterDevice::getOverlineOffset() const @@ -197,18 +202,6 @@ namespace drawinglayer return fRet; } -#ifdef WIN32 - double TextLayouterDevice::getCurrentFontRelation() const - { - const Font aFont(mrDevice.GetFont()); - const FontMetric aFontMetric(mrDevice.GetFontMetric(aFont)); - const double fWidth(aFontMetric.GetWidth()); - const double fHeight(aFont.GetHeight()); - - return basegfx::fTools::equalZero(fWidth) ? 1.0 : fHeight / fWidth; - } -#endif - double TextLayouterDevice::getOverlineHeight() const { const ::FontMetric& rMetric = mrDevice.GetFontMetric(); @@ -241,33 +234,42 @@ namespace drawinglayer const String& rText, xub_StrLen nIndex, xub_StrLen nLength, - // #i89784# added suppirt for DXArray for justified text - const ::std::vector< double >& rDXArray, - double fFontScaleWidth) + const ::std::vector< double >& rDXArray) { - std::vector< sal_Int32 > aTransformedDXArray; - const sal_uInt32 nDXArraySize(rDXArray.size()); + const sal_uInt32 nDXArrayCount(rDXArray.size()); - if(nDXArraySize && basegfx::fTools::more(fFontScaleWidth, 0.0)) + if(nDXArrayCount) { - OSL_ENSURE(nDXArraySize == nLength, "DXArray size does not correspond to text portion size (!)"); - aTransformedDXArray.reserve(nDXArraySize); + OSL_ENSURE(nDXArrayCount == nLength, "DXArray size does not correspond to text portion size (!)"); + std::vector< sal_Int32 > aIntegerDXArray(nDXArrayCount); - for(std::vector< double >::const_iterator aStart(rDXArray.begin()); aStart != rDXArray.end(); aStart++) + for(sal_uInt32 a(0); a < nDXArrayCount; a++) { - aTransformedDXArray.push_back(basegfx::fround((*aStart) * fFontScaleWidth)); + aIntegerDXArray[a] = basegfx::fround(rDXArray[a]); } - } - return mrDevice.GetTextOutlines( - rB2DPolyPolyVector, - rText, - nIndex, - nIndex, - nLength, - true, - 0, - nDXArraySize ? &(aTransformedDXArray[0]) : 0); + return mrDevice.GetTextOutlines( + rB2DPolyPolyVector, + rText, + nIndex, + nIndex, + nLength, + true, + 0, + &(aIntegerDXArray[0])); + } + else + { + return mrDevice.GetTextOutlines( + rB2DPolyPolyVector, + rText, + nIndex, + nIndex, + nLength, + true, + 0, + 0); + } } basegfx::B2DRange TextLayouterDevice::getTextBoundRect( @@ -286,7 +288,7 @@ namespace drawinglayer nIndex, nLength); - // #i102556# take empty results into account + // #i104432#, #i102556# take empty results into account if(!aRect.IsEmpty()) { return basegfx::B2DRange(aRect.Left(), aRect.Top(), aRect.Right(), aRect.Bottom()); @@ -307,38 +309,36 @@ namespace drawinglayer { Font getVclFontFromFontAttributes( const FontAttributes& rFontAttributes, - const basegfx::B2DHomMatrix& rTransform, - const ::com::sun::star::lang::Locale & rLocale, - const OutputDevice& rOutDev) - { - // decompose matrix to have position and size of text - basegfx::B2DVector aScale, aTranslate; - double fRotate, fShearX; - - rTransform.decompose(aScale, aTranslate, fRotate, fShearX); - - return getVclFontFromFontAttributes(rFontAttributes, aScale.getX(), aScale.getY(), fRotate, rLocale, rOutDev); - } - - Font getVclFontFromFontAttributes( - const FontAttributes& rFontAttributes, double fFontScaleX, double fFontScaleY, double fFontRotation, - const ::com::sun::star::lang::Locale & rLocale, - const OutputDevice& /*rOutDev*/) + const ::com::sun::star::lang::Locale& rLocale) { - sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX))); - sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY))); + // detect FontScaling + const sal_uInt32 nHeight(basegfx::fround(fabs(fFontScaleY))); + const sal_uInt32 nWidth(basegfx::fround(fabs(fFontScaleX))); + const bool bFontIsScaled(nHeight != nWidth); + +#ifdef WIN32 + // for WIN32 systems, start with creating an unscaled font. If FontScaling + // is wanted, that width needs to be adapted using FontMetric again to get a + // width of the unscaled font Font aRetval( rFontAttributes.getFamilyName(), rFontAttributes.getStyleName(), -#ifdef WIN32 Size(0, nHeight)); #else - Size(nWidth, nHeight)); + // for non-WIN32 systems things are easier since these accept a Font creation + // with initially nWidth != nHeight for FontScaling. Despite that, use zero for + // FontWidth when no scaling is used to explicitely have that zero when e.g. the + // Font would be recorded in a MetaFile (The MetaFile FontAction WILL record a + // set FontWidth; import that in a WIN32 system, and trouble is there) + Font aRetval( + rFontAttributes.getFamilyName(), + rFontAttributes.getStyleName(), + Size(bFontIsScaled ? nWidth : 0, nHeight)); #endif - + // define various other FontAttributes aRetval.SetAlign(ALIGN_BASELINE); aRetval.SetCharSet(rFontAttributes.getSymbol() ? RTL_TEXTENCODING_SYMBOL : RTL_TEXTENCODING_UNICODE); aRetval.SetVertical(rFontAttributes.getVertical() ? TRUE : FALSE); @@ -348,32 +348,20 @@ namespace drawinglayer aRetval.SetLanguage(MsLangId::convertLocaleToLanguage(rLocale)); #ifdef WIN32 - // #100424# use higher precision - if(!basegfx::fTools::equal(fFontScaleX, fFontScaleY)) + // for WIN32 systems, correct the FontWidth if FontScaling is used + if(bFontIsScaled && nHeight > 0) { - // #i92757# - // Removed the relative calculation with GetFontMetric() usage again. On - // the one hand it was wrong (integer division always created zero), OTOH - // calculating a scale factor from current to target width and then using - // it to actually scale the current width does nothing but set the target - // value directly. Maybe more is needed here with WIN version of font - // width/height handling, but currently, this works the simple way. - // - // As can be seen, when this can stay the simple way, the OutputDevice - // can be removed from the whole getVclFontFromFontAttributes implementations - // again and make it more VCL-independent. - // - // Adapted nWidth usage to nWidth-1 to be completely compatible with - // non-primitive version. - // - // previous stuff: - // const FontMetric aFontMetric(rOutDev.GetFontMetric(aRetval)); - // const double fCurrentWidth(aFontMetric.GetWidth()); - // aRetval.SetWidth(basegfx::fround(fCurrentWidth * ((double)nWidth/(double)nHeight))); - aRetval.SetWidth(nWidth ? nWidth - 1 : 0); + const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aRetval)); + + if(aUnscaledFontMetric.GetWidth() > 0) + { + const double fScaleFactor((double)nWidth / (double)nHeight); + const sal_uInt32 nScaledWidth(basegfx::fround((double)aUnscaledFontMetric.GetWidth() * fScaleFactor)); + aRetval.SetWidth(nScaledWidth); + } } #endif - + // handle FontRotation (if defined) if(!basegfx::fTools::equalZero(fFontRotation)) { sal_Int16 aRotate10th((sal_Int16)(fFontRotation * (-1800.0/F_PI))); @@ -383,9 +371,13 @@ namespace drawinglayer return aRetval; } - FontAttributes getFontAttributesFromVclFont(basegfx::B2DVector& rSize, const Font& rFont, bool bRTL, bool bBiDiStrong) + FontAttributes getFontAttributesFromVclFont( + basegfx::B2DVector& o_rSize, + const Font& rFont, + bool bRTL, + bool bBiDiStrong) { - FontAttributes aRetval( + const FontAttributes aRetval( rFont.GetName(), rFont.GetStyleName(), static_cast<sal_uInt16>(rFont.GetWeight()), @@ -397,12 +389,38 @@ namespace drawinglayer bBiDiStrong); // TODO: eKerning - const sal_Int32 nWidth(rFont.GetSize().getWidth()); - const sal_Int32 nHeight(rFont.GetSize().getHeight()); + // set FontHeight and init to no FontScaling + o_rSize.setY(rFont.GetSize().getHeight() > 0 ? rFont.GetSize().getHeight() : 0); + o_rSize.setX(o_rSize.getY()); - rSize.setX(nWidth ? nWidth : nHeight); - rSize.setY(nHeight); +#ifdef WIN32 + // for WIN32 systems, the FontScaling at the Font is detected by + // checking that FontWidth != 0. When FontScaling is used, WIN32 + // needs to do extra stuff to detect the correct width (since it's + // zero and not equal the font height) and it's relationship to + // the height + if(rFont.GetSize().getWidth() > 0) + { + Font aUnscaledFont(rFont); + aUnscaledFont.SetWidth(0); + const FontMetric aUnscaledFontMetric(Application::GetDefaultDevice()->GetFontMetric(aUnscaledFont)); + if(aUnscaledFontMetric.GetWidth() > 0) + { + const double fScaleFactor((double)rFont.GetSize().getWidth() / (double)aUnscaledFontMetric.GetWidth()); + o_rSize.setX(fScaleFactor * o_rSize.getY()); + } + } +#else + // For non-WIN32 systems the detection is the same, but the value + // is easier achieved since width == height is interpreted as no + // scaling. Ergo, Width == 0 means width == height, and width != 0 + // means the scaling is in the direct relation of width to height + if(rFont.GetSize().getWidth() > 0) + { + o_rSize.setX((double)rFont.GetSize().getWidth()); + } +#endif return aRetval; } } // end of namespace primitive2d diff --git a/drawinglayer/source/primitive2d/textprimitive2d.cxx b/drawinglayer/source/primitive2d/textprimitive2d.cxx index 7c62c235c21d..f8e413da0e8c 100644 --- a/drawinglayer/source/primitive2d/textprimitive2d.cxx +++ b/drawinglayer/source/primitive2d/textprimitive2d.cxx @@ -70,49 +70,63 @@ namespace drawinglayer ////////////////////////////////////////////////////////////////////////////// -namespace drawinglayer +namespace { - namespace primitive2d + // adapts fontScale for usage with TextLayouter. Input is rScale which is the extracted + // scale from a text transformation. A copy is modified so that it contains only positive + // scalings and XY-equal scalings to allow to get a non-X-scaled Vcl-Font for TextLayouter. + // rScale is adapted accordingly to contain the corrected scale which would need to be + // applied to e.g. outlines received from TextLayouter under usage of fontScale. This + // includes Y-Scale, X-Scale-correction and mirrorings. + basegfx::B2DVector getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale) { - void TextSimplePortionPrimitive2D::getCorrectedScaleAndFontScale(basegfx::B2DVector& rScale, basegfx::B2DVector& rFontScale) const - { - // copy input value - rFontScale = rScale; + // copy input value + basegfx::B2DVector aFontScale(rScale); - if(basegfx::fTools::equalZero(rFontScale.getY())) - { - // no font height; choose one and adapt scale to get back to original scaling - static double fDefaultFontScale(100.0); - rScale.setY(1.0 / fDefaultFontScale); - rFontScale.setY(fDefaultFontScale); - } - else if(basegfx::fTools::less(rFontScale.getY(), 0.0)) - { - // negative font height; invert and adapt scale to get back to original scaling - rFontScale.setY(-rFontScale.getY()); - rScale.setY(-1.0); - } - else - { - // positive font height; adapt scale; scaling will be part of the polygons - rScale.setY(1.0); - } + // correct FontHeight settings + if(basegfx::fTools::equalZero(aFontScale.getY())) + { + // no font height; choose one and adapt scale to get back to original scaling + static double fDefaultFontScale(100.0); + rScale.setY(1.0 / fDefaultFontScale); + aFontScale.setY(fDefaultFontScale); + } + else if(basegfx::fTools::less(aFontScale.getY(), 0.0)) + { + // negative font height; invert and adapt scale to get back to original scaling + aFontScale.setY(-aFontScale.getY()); + rScale.setY(-1.0); + } + else + { + // positive font height; adapt scale; scaling will be part of the polygons + rScale.setY(1.0); + } - if(basegfx::fTools::equal(rFontScale.getX(), rFontScale.getY())) - { - // adapt scale in X - rScale.setX(1.0); - } - else - { - // If font scale is different in X and Y, force font scale to equal - // in X and Y to get a non-scaled VCL font. - // Adapt scaling in X accordingly. FontScaleY cannot be zero here. - rScale.setX(rFontScale.getX()/rFontScale.getY()); - rFontScale.setX(rFontScale.getY()); - } + // correct FontWidth settings + if(basegfx::fTools::equal(aFontScale.getX(), aFontScale.getY())) + { + // no FontScale, adapt scale + rScale.setX(1.0); } + else + { + // If FontScale is used, force to no FontScale to get a non-scaled VCL font. + // Adapt scaling in X accordingly. + rScale.setX(aFontScale.getX() / aFontScale.getY()); + aFontScale.setX(aFontScale.getY()); + } + + return aFontScale; + } +} // end of anonymous namespace +////////////////////////////////////////////////////////////////////////////// + +namespace drawinglayer +{ + namespace primitive2d + { void TextSimplePortionPrimitive2D::getTextOutlinesAndTransformation(basegfx::B2DPolyPolygonVector& rTarget, basegfx::B2DHomMatrix& rTransformation) const { if(getTextLength()) @@ -137,33 +151,47 @@ namespace drawinglayer // 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 -#ifdef WIN32 - const bool bCorrectScale(!basegfx::fTools::equal(fabs(aScale.getX()), fabs(aScale.getY()))); -#endif - basegfx::B2DVector aFontScale; - getCorrectedScaleAndFontScale(aScale, aFontScale); + const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); // prepare textlayoutdevice TextLayouterDevice aTextLayouter; - aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY(), getLocale()); -#ifdef WIN32 - // when under Windows and the font is unequally scaled, need to correct font X-Scaling factor - if(bCorrectScale) + aTextLayouter.setFontAttributes( + getFontAttributes(), + aFontScale.getX(), + aFontScale.getY(), + getLocale()); + + // When getting outlines from stretched text (aScale.getX() != 1.0) it + // is necessary to inverse-scale the DXArray (if used) to not get the + // outlines already aligned to given, but wrong DXArray + if(getDXArray().size() && !basegfx::fTools::equal(aScale.getX(), 1.0)) + { + ::std::vector< double > aScaledDXArray = getDXArray(); + const double fDXArrayScale(1.0 / aScale.getX()); + + for(sal_uInt32 a(0); a < aScaledDXArray.size(); a++) + { + aScaledDXArray[a] *= fDXArrayScale; + } + + // get the text outlines + aTextLayouter.getTextOutlines( + rTarget, + getText(), + getTextPosition(), + getTextLength(), + aScaledDXArray); + } + else { - const double fFontRelation(aTextLayouter.getCurrentFontRelation()); - aScale.setX(aScale.getX() * fFontRelation); - aFontScale.setX(aFontScale.getX() / fFontRelation); + // get the text outlines + aTextLayouter.getTextOutlines( + rTarget, + getText(), + getTextPosition(), + getTextLength(), + getDXArray()); } -#endif - // get the text outlines. No DXArray is given (would contain integers equal to unit vector - // transformed by object's transformation), let VCL do the job - aTextLayouter.getTextOutlines( - rTarget, getText(), - getTextPosition(), - getTextLength(), - // #i89784# added support for DXArray for justified text - getDXArray(), - aFontScale.getX()); // create primitives for the outlines const sal_uInt32 nCount(rTarget.size()); @@ -300,29 +328,22 @@ namespace drawinglayer // 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 -#ifdef WIN32 - const bool bCorrectScale(!basegfx::fTools::equal(fabs(aScale.getX()), fabs(aScale.getY()))); -#endif - basegfx::B2DVector aFontScale; - getCorrectedScaleAndFontScale(aScale, aFontScale); + const basegfx::B2DVector aFontScale(getCorrectedScaleAndFontScale(aScale)); // prepare textlayoutdevice TextLayouterDevice aTextLayouter; - aTextLayouter.setFontAttributes(getFontAttributes(), aFontScale.getX(), aFontScale.getY(), getLocale()); + aTextLayouter.setFontAttributes( + getFontAttributes(), + aFontScale.getX(), + aFontScale.getY(), + getLocale()); // get basic text range basegfx::B2DRange aNewRange(aTextLayouter.getTextBoundRect(getText(), getTextPosition(), getTextLength())); - // #i102556# take empty results into account + // #i104432#, #i102556# take empty results into account if(!aNewRange.isEmpty()) { -#ifdef WIN32 - // when under Windows and the font is unequally scaled, need to correct font X-Scaling factor - if(bCorrectScale) - { - aScale.setX(aScale.getX() * aTextLayouter.getCurrentFontRelation()); - } -#endif // prepare object transformation for range basegfx::B2DHomMatrix aRangeTransformation; diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx index daf8ce5d525f..e5a88812dd10 100644 --- a/drawinglayer/source/processor2d/vclprocessor2d.cxx +++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx @@ -138,79 +138,31 @@ namespace drawinglayer { // decompose matrix to have position and size of text basegfx::B2DHomMatrix aLocalTransform(maCurrentTransformation * rTextCandidate.getTextTransform()); - basegfx::B2DVector aScale, aTranslate; + basegfx::B2DVector aFontScaling, aTranslate; double fRotate, fShearX; - aLocalTransform.decompose(aScale, aTranslate, fRotate, fShearX); + aLocalTransform.decompose(aFontScaling, aTranslate, fRotate, fShearX); bool bPrimitiveAccepted(false); if(basegfx::fTools::equalZero(fShearX)) { - if(basegfx::fTools::less(aScale.getX(), 0.0) && basegfx::fTools::less(aScale.getY(), 0.0)) + if(basegfx::fTools::less(aFontScaling.getX(), 0.0) && basegfx::fTools::less(aFontScaling.getY(), 0.0)) { // handle special case: If scale is negative in (x,y) (3rd quadrant), it can - // be expressed as rotation by PI - aScale = basegfx::absolute(aScale); + // be expressed as rotation by PI. Use this since the Font rendering will not + // apply the negative scales in any form + aFontScaling = basegfx::absolute(aFontScaling); fRotate += F_PI; } - if(basegfx::fTools::more(aScale.getX(), 0.0) && basegfx::fTools::more(aScale.getY(), 0.0)) + if(basegfx::fTools::more(aFontScaling.getX(), 0.0) && basegfx::fTools::more(aFontScaling.getY(), 0.0)) { - // #i96581# Get the font forced without FontStretching (use FontHeight as FontWidth) + // Get the VCL font (use FontHeight as FontWidth) Font aFont(primitive2d::getVclFontFromFontAttributes( rTextCandidate.getFontAttributes(), - - // #i100373# FontScaling - // - // There are two different definitions for unscaled fonts, (1) 0==width and - // (2) height==width where (2) is the more modern one supported on all non-WIN32 - // systems and (1) is the old one coming from WIN16-VCL definitions where - // that ominous FontWidth (available over FontMetric) is involved. While - // WIN32 only supports (1), all other systems support (2). When on WIN32, the - // support for (1) is ensured inside getVclFontFromFontAttributes. - // - // The former usage of (2) leads to problems when it is used on non-WIN32 systems - // and exported to MetaFile FontActions where the scale is taken over unseen. When - // such a MetaFile is imported on a WIN32-System supporting (1), all fonts are - // seen as scaled an look wrong. - // - // The simplest and fastest solution is to fallback to (1) independent from the - // system we are running on. - // - // The best solution would be a system-independent Y-value just expressing the - // font scaling, e.g. when (2) is used and width == height, use 1.0 as Y-Value, - // which would also solve the involved ominous FontWidth value for WIN32-systems. - // This is a region which needs redesign urgently. - // - 0, // aScale.getY(), - - aScale.getY(), + aFontScaling.getX(), + aFontScaling.getY(), fRotate, - rTextCandidate.getLocale(), - *mpOutputDevice)); - - if(!basegfx::fTools::equal(aScale.getX(), aScale.getY())) - { - // #100424# We have a hint on FontScaling here. To decide a look - // at the pure font's scale is needed, since e.g. SC uses unequally scaled - // MapModes (was: #i96581#, but use available full precision from primitive - // now). aTranslate and fShearX can be reused since no longer needed. - basegfx::B2DVector aFontScale; - double fFontRotate; - rTextCandidate.getTextTransform().decompose(aFontScale, aTranslate, fFontRotate, fShearX); - - if(!basegfx::fTools::equal(aFontScale.getX(), aFontScale.getY())) - { - // indeed a FontScaling. Set at Font. Use the combined scale - // and rotate here - aFont = primitive2d::getVclFontFromFontAttributes( - rTextCandidate.getFontAttributes(), - aScale.getX(), - aScale.getY(), - fRotate, - rTextCandidate.getLocale(), - *mpOutputDevice); - } - } + rTextCandidate.getLocale())); // handle additional font attributes const primitive2d::TextDecoratedPortionPrimitive2D* pTCPP = @@ -314,10 +266,11 @@ namespace drawinglayer if(rTextCandidate.getDXArray().size()) { aTransformedDXArray.reserve(rTextCandidate.getDXArray().size()); - const basegfx::B2DVector aPixelVector(aLocalTransform * basegfx::B2DVector(1.0, 0.0)); + const basegfx::B2DVector aPixelVector(maCurrentTransformation * basegfx::B2DVector(1.0, 0.0)); const double fPixelVectorFactor(aPixelVector.getLength()); - for(::std::vector< double >::const_iterator aStart(rTextCandidate.getDXArray().begin()); aStart != rTextCandidate.getDXArray().end(); aStart++) + for(::std::vector< double >::const_iterator aStart(rTextCandidate.getDXArray().begin()); + aStart != rTextCandidate.getDXArray().end(); aStart++) { aTransformedDXArray.push_back(basegfx::fround((*aStart) * fPixelVectorFactor)); } |