diff options
31 files changed, 452 insertions, 258 deletions
diff --git a/editeng/source/editeng/editeng.cxx b/editeng/source/editeng/editeng.cxx index 32fad4d8fc35..69fef679c7f3 100644 --- a/editeng/source/editeng/editeng.cxx +++ b/editeng/source/editeng/editeng.cxx @@ -2006,14 +2006,13 @@ Point EditEngine::GetDocPosTopLeft( sal_Int32 nParagraph ) else { const SvxLRSpaceItem& rLRItem = pImpEditEngine->GetLRSpaceItem( pPPortion->GetNode() ); -// TL_NF_LR aPoint.X() = pImpEditEngine->GetXValue( (short)(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset()) ); sal_Int32 nSpaceBefore = 0; pImpEditEngine->GetSpaceBeforeAndMinLabelWidth( pPPortion->GetNode(), &nSpaceBefore ); short nX = static_cast<short>(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore); - aPoint.setX( pImpEditEngine->GetXValue( nX - ) ); + + aPoint.setX(pImpEditEngine->scaleXSpacingValue(nX)); } aPoint.setY( pImpEditEngine->GetParaPortions().GetYOffset( pPPortion ) ); } @@ -2266,14 +2265,24 @@ bool EditEngine::HasText( const SvxSearchItem& rSearchItem ) return pImpEditEngine->HasText( rSearchItem ); } -void EditEngine::SetGlobalCharStretching(double nX, double nY) +void EditEngine::setGlobalScale(double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY) +{ + pImpEditEngine->setScale(fFontScaleX, fFontScaleY, fSpacingScaleX, fSpacingScaleY); +} + +void EditEngine::getGlobalSpacingScale(double& rX, double& rY) const +{ + pImpEditEngine->getSpacingScale(rX, rY); +} + +void EditEngine::getGlobalFontScale(double& rX, double& rY) const { - pImpEditEngine->SetCharStretching( nX, nY ); + pImpEditEngine->getFontScale(rX, rY); } -void EditEngine::GetGlobalCharStretching(double& rX, double& rY) const +void EditEngine::setRoundFontSizeToPt(bool bRound) const { - pImpEditEngine->GetCharStretching( rX, rY ); + pImpEditEngine->setRoundToNearestPt(bRound); } bool EditEngine::ShouldCreateBigTextObject() const diff --git a/editeng/source/editeng/editobj.cxx b/editeng/source/editeng/editobj.cxx index 437754d70def..d0ec8632f134 100644 --- a/editeng/source/editeng/editobj.cxx +++ b/editeng/source/editeng/editobj.cxx @@ -70,11 +70,14 @@ void XEditAttribute::SetItem(const SfxPoolItem& rNew) pItem = &rNew; } -XParaPortionList::XParaPortionList( - OutputDevice* pRefDev, sal_uInt32 nPW, double nStretchX, double nStretchY) +XParaPortionList::XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, + double fFontScaleX, double fFontScaleY, + double fSpacingScaleX, double fSpacingScaleY) : pRefDevPtr(pRefDev) - , mnStretchX(nStretchX) - , mnStretchY(nStretchY) + , mfFontScaleX(fFontScaleX) + , mfFontScaleY(fFontScaleY) + , mfSpacingScaleX(fSpacingScaleX) + , mfSpacingScaleY(fSpacingScaleY) , nPaperWidth(nPW) { } diff --git a/editeng/source/editeng/editobj2.hxx b/editeng/source/editeng/editobj2.hxx index 86a2e379be20..86c81e23f94e 100644 --- a/editeng/source/editeng/editobj2.hxx +++ b/editeng/source/editeng/editobj2.hxx @@ -94,12 +94,14 @@ class XParaPortionList ListType maList; VclPtr<OutputDevice> pRefDevPtr; - double mnStretchX; - double mnStretchY; + double mfFontScaleX; + double mfFontScaleY; + double mfSpacingScaleX; + double mfSpacingScaleY; sal_uInt32 nPaperWidth; public: - XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, double nStretchX, double nStretchY); + XParaPortionList(OutputDevice* pRefDev, sal_uInt32 nPW, double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY); void push_back(XParaPortion* p); const XParaPortion& operator[](size_t i) const; @@ -108,8 +110,10 @@ public: sal_uInt32 GetPaperWidth() const { return nPaperWidth; } bool RefDevIsVirtual() const {return pRefDevPtr->IsVirtual();} const MapMode& GetRefMapMode() const { return pRefDevPtr->GetMapMode(); } - double GetStretchX() const { return mnStretchX; } - double GetStretchY() const { return mnStretchY; } + double getFontScaleX() const { return mfFontScaleX; } + double getFontScaleY() const { return mfFontScaleY; } + double getSpacingScaleX() const { return mfSpacingScaleX; } + double getSpacingScaleY() const { return mfSpacingScaleY; } }; class ContentInfo diff --git a/editeng/source/editeng/impedit.hxx b/editeng/source/editeng/impedit.hxx index fd8ff61f66ca..7bbd0fd9e765 100644 --- a/editeng/source/editeng/impedit.hxx +++ b/editeng/source/editeng/impedit.hxx @@ -528,8 +528,11 @@ private: Color maBackgroundColor; - double mnStretchX; - double mnStretchY; + double mfFontScaleX; + double mfFontScaleY; + double mfSpacingScaleX; + double mfSpacingScaleY; + bool mbRoundToNearestPt; CharCompressType nAsianCompressionMode; @@ -733,11 +736,40 @@ private: std::vector<std::unique_ptr<SvxFontItem>>& rFontTable, SvxColorList& rColorList ); sal_Int32 LogicToTwips( sal_Int32 n ); - inline short GetXValue( short nXValue ) const; - inline tools::Long GetXValue( tools::Long nXValue ) const; + double scaleXSpacingValue(tools::Long nXValue) const + { + if (!aStatus.DoStretch() || mfSpacingScaleX == 100.0) + return nXValue; + + return double(nXValue) * mfSpacingScaleX / 100.0; + } - inline short GetYValue( short nYValue ) const; - inline sal_uInt16 GetYValue( sal_uInt16 nYValue ) const; + double scaleYSpacingValue(sal_uInt16 nYValue) const + { + if (!aStatus.DoStretch() || mfSpacingScaleY == 100.0) + return nYValue; + + return double(nYValue) * mfSpacingScaleY / 100.0; + } + + double scaleYFontValue(sal_uInt16 nYValue) const + { + if (!aStatus.DoStretch() || (mfFontScaleY == 100.0)) + return nYValue; + + return double(nYValue) * mfFontScaleY / 100.0; + } + + double scaleXFontValue(tools::Long nXValue) const + { + if (!aStatus.DoStretch() || (mfFontScaleX == 100.0)) + return nXValue; + + return double(nXValue) * mfFontScaleY / 100.0; + } + + void setRoundToNearestPt(bool bRound) { mbRoundToNearestPt = bRound; } + double roundToNearestPt(double fInput) const; ContentNode* GetPrevVisNode( ContentNode const * pCurNode ); ContentNode* GetNextVisNode( ContentNode const * pCurNode ); @@ -1080,8 +1112,19 @@ public: SvxCellJustifyMethod GetJustifyMethod( sal_Int32 nPara ) const; SvxCellVerJustify GetVerJustification( sal_Int32 nPara ) const; - void SetCharStretching(double nX, double nY); - inline void GetCharStretching(double& rX, double& rY) const; + void setScale(double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY); + + void getFontScale(double& rX, double& rY) const + { + rX = mfFontScaleX; + rY = mfFontScaleY; + } + + void getSpacingScale(double& rX, double& rY) const + { + rX = mfSpacingScaleX; + rY = mfSpacingScaleY; + } sal_Int32 GetBigTextObjectStart() const { return nBigTextObjectStart; } @@ -1282,45 +1325,6 @@ inline ParaPortion* ImpEditEngine::FindParaPortion( ContentNode const * pNode ) return GetParaPortions()[ nPos ]; } -inline void ImpEditEngine::GetCharStretching(double& rX, double& rY) const -{ - rX = mnStretchX; - rY = mnStretchY; -} - -inline short ImpEditEngine::GetXValue( short nXValue ) const -{ - if ( !aStatus.DoStretch() || ( mnStretchX == 100.0 ) ) - return nXValue; - - return basegfx::fround(double(nXValue) * mnStretchX / 100.0); -} - - -inline tools::Long ImpEditEngine::GetXValue( tools::Long nXValue ) const -{ - if ( !aStatus.DoStretch() || ( mnStretchX == 100.0 ) ) - return nXValue; - - return basegfx::fround(nXValue * mnStretchX / 100.0); -} - -inline short ImpEditEngine::GetYValue( short nYValue ) const -{ - if ( !aStatus.DoStretch() || ( mnStretchY == 100.0 ) ) - return nYValue; - - return basegfx::fround(double(nYValue) * mnStretchY / 100.0); -} - -inline sal_uInt16 ImpEditEngine::GetYValue( sal_uInt16 nYValue ) const -{ - if ( !aStatus.DoStretch() || ( mnStretchY == 100.0 ) ) - return nYValue; - - return basegfx::fround(double(nYValue) * mnStretchY / 100.0); -} - inline PointerStyle ImpEditView::GetPointer() { if ( !mxPointer ) diff --git a/editeng/source/editeng/impedit2.cxx b/editeng/source/editeng/impedit2.cxx index 4e87e36af5d3..e6cbdcfbdeb9 100644 --- a/editeng/source/editeng/impedit2.cxx +++ b/editeng/source/editeng/impedit2.cxx @@ -98,8 +98,11 @@ ImpEditEngine::ImpEditEngine( EditEngine* pEE, SfxItemPool* pItemPool ) : pUndoManager(nullptr), aWordDelimiters(" .,;:-`'?!_=\"{}()[]"), maBackgroundColor(COL_AUTO), - mnStretchX(100.0), - mnStretchY(100.0), + mfFontScaleX(100.0), + mfFontScaleY(100.0), + mfSpacingScaleX(100.0), + mfSpacingScaleY(100.0), + mbRoundToNearestPt(false), nAsianCompressionMode(CharCompressType::NONE), eDefaultHorizontalTextDirection(EEHorizontalTextDirection::Default), nBigTextObjectStart(20), @@ -3222,7 +3225,7 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); nSBL = (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix) - ? GetYValue(rLSItem.GetInterLineSpace()) + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; } @@ -3266,7 +3269,7 @@ void ImpEditEngine::IterateLineAreas(const IterateLinesAreasFunc& f, IterFlag eO { const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); - tools::Long nUL = GetYValue(rULItem.GetLower()); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); adjustYDirectionAware(aLineStart, nUL); } } @@ -3402,10 +3405,10 @@ sal_uInt32 ImpEditEngine::CalcParaWidth( sal_Int32 nPara, bool bIgnoreExtraSpace // width, here not preferred. I general, it is best not leave it // to StartPosX, also the right indents have to be taken into // account! - tools::Long nCurWidth = GetXValue( rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth ); + tools::Long nCurWidth = scaleXSpacingValue(rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth); if ( nLine == 0 ) { - tools::Long nFI = GetXValue( rLRItem.GetTextFirstLineOffset() ); + tools::Long nFI = scaleXSpacingValue(rLRItem.GetTextFirstLineOffset()); nCurWidth -= nFI; if ( pPortion->GetBulletX() > nCurWidth ) { @@ -3414,7 +3417,7 @@ sal_uInt32 ImpEditEngine::CalcParaWidth( sal_Int32 nPara, bool bIgnoreExtraSpace nCurWidth = pPortion->GetBulletX(); } } - nCurWidth += GetXValue( rLRItem.GetRight() ); + nCurWidth += scaleXSpacingValue(rLRItem.GetRight()); nCurWidth += CalcLineWidth( pPortion, &rLine, bIgnoreExtraSpace ); if ( nCurWidth > nMaxWidth ) { @@ -4337,7 +4340,7 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); - sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + sal_Int32 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; if ( nSBL ) { @@ -4350,14 +4353,14 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) sal_Int32 nPortion = GetParaPortions().GetPos( pPortion ); if ( nPortion ) { - sal_uInt16 nUpper = GetYValue( rULItem.GetUpper() ); + sal_uInt16 nUpper = scaleYSpacingValue(rULItem.GetUpper()); pPortion->nHeight += nUpper; pPortion->nFirstLineOffset = nUpper; } if ( nPortion != (GetParaPortions().Count()-1) ) { - pPortion->nHeight += GetYValue( rULItem.GetLower() ); // not in the last + pPortion->nHeight += scaleYSpacingValue(rULItem.GetLower()); // not in the last } @@ -4377,7 +4380,7 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) // Only Writer3: Do not add up, but minimum distance. // check if distance by LineSpacing > Upper: - sal_uInt16 nExtraSpace = GetYValue( lcl_CalcExtraSpace( rLSItem ) ); + sal_uInt16 nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rLSItem)); if ( nExtraSpace > pPortion->nFirstLineOffset ) { // Paragraph becomes 'bigger': @@ -4386,7 +4389,7 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) } // Determine nFirstLineOffset now f(pNode) => now f(pNode, pPrev): - sal_uInt16 nPrevLower = GetYValue( rPrevULItem.GetLower() ); + sal_uInt16 nPrevLower = scaleYSpacingValue(rPrevULItem.GetLower()); // This PrevLower is still in the height of PrevPortion ... if ( nPrevLower > pPortion->nFirstLineOffset ) @@ -4408,7 +4411,7 @@ void ImpEditEngine::CalcHeight( ParaPortion* pPortion ) if ( pPrev->IsInvalid() ) return; - nExtraSpace = GetYValue( lcl_CalcExtraSpace( rPrevLSItem ) ); + nExtraSpace = scaleYSpacingValue(lcl_CalcExtraSpace(rPrevLSItem)); if ( nExtraSpace > nPrevLower ) { sal_uInt16 nMoreLower = nExtraSpace - nPrevLower; diff --git a/editeng/source/editeng/impedit3.cxx b/editeng/source/editeng/impedit3.cxx index 376d1df7ad13..6cb45a385748 100644 --- a/editeng/source/editeng/impedit3.cxx +++ b/editeng/source/editeng/impedit3.cxx @@ -668,7 +668,8 @@ void ImpEditEngine::CheckPageOverflow() static sal_Int32 ImplCalculateFontIndependentLineSpacing( const sal_Int32 nFontHeight ) { - return ( nFontHeight * 12 ) / 10; // + 20% + constexpr const double f120Percent = 12.0 / 10.0; + return basegfx::fround(nFontHeight * f120Percent); // + 20% } tools::Long ImpEditEngine::GetColumnWidth(const Size& rPaperSize) const @@ -827,7 +828,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( pParaPortion ) ); if ( !aBulletArea.IsWidthEmpty() && aBulletArea.Right() > 0 ) - pParaPortion->SetBulletX( static_cast<sal_Int32>(GetXValue( aBulletArea.Right() )) ); + pParaPortion->SetBulletX(sal_Int32(scaleXSpacingValue(aBulletArea.Right()))); else pParaPortion->SetBulletX( 0 ); // if Bullet is set incorrectly } @@ -861,10 +862,10 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) sal_Int32 nPortionStart = 0; sal_Int32 nPortionEnd = 0; - tools::Long nStartX = GetXValue( rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth ); + tools::Long nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + nSpaceBeforeAndMinLabelWidth); if ( nIndex == 0 ) { - tools::Long nFI = GetXValue( rLRItem.GetTextFirstLineOffset() ); + tools::Long nFI = scaleXSpacingValue(rLRItem.GetTextFirstLineOffset()); nStartX += nFI; if ( !nLine && ( pParaPortion->GetBulletX() > nStartX ) ) @@ -876,13 +877,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) const bool bAutoSize = IsEffectivelyVertical() ? aStatus.AutoPageHeight() : aStatus.AutoPageWidth(); tools::Long nMaxLineWidth = GetColumnWidth(bAutoSize ? aMaxAutoPaperSize : aPaperSize); - nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); + nMaxLineWidth -= scaleXSpacingValue(rLRItem.GetRight()); nMaxLineWidth -= nStartX; // If PaperSize == long_max, one cannot take away any negative // first line indent. (Overflow) if ( ( nMaxLineWidth < 0 ) && ( nStartX < 0 ) ) - nMaxLineWidth = GetColumnWidth(aPaperSize) - GetXValue(rLRItem.GetRight()); + nMaxLineWidth = GetColumnWidth(aPaperSize) - scaleXSpacingValue(rLRItem.GetRight()); // If still less than 0, it may be just the right edge. if ( nMaxLineWidth <= 0 ) @@ -962,7 +963,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } nXWidth = nMaxRangeWidth; if ( nXWidth ) - nMaxLineWidth = nXWidth - nStartX - GetXValue( rLRItem.GetRight() ); + nMaxLineWidth = nXWidth - nStartX - scaleXSpacingValue(rLRItem.GetRight()); else { // Try further down in the polygon. @@ -1052,14 +1053,14 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) tools::Long nOldTmpWidth = nTmpWidth; // Search for Tab-Pos... - tools::Long nCurPos = nTmpWidth+nStartX; + tools::Long nCurPos = nTmpWidth + nStartX; // consider scaling - if ( aStatus.DoStretch() && ( mnStretchX != 100.0 ) ) - nCurPos = basegfx::fround(double(nCurPos) * 100.0 / std::max(mnStretchX, 1.0)); + if (aStatus.DoStretch() && (mfFontScaleX != 100.0)) + nCurPos = basegfx::fround(double(nCurPos) * 100.0 / std::max(mfFontScaleX, 1.0)); short nAllSpaceBeforeText = static_cast< short >(rLRItem.GetTextLeft()/* + rLRItem.GetTextLeft()*/ + nSpaceBeforeAndMinLabelWidth); aCurrentTab.aTabStop = pNode->GetContentAttribs().FindTabStop( nCurPos - nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/, aEditDoc.GetDefTab() ); - aCurrentTab.nTabPos = GetXValue( static_cast<tools::Long>( aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText /*rLRItem.GetTextLeft()*/ ) ); + aCurrentTab.nTabPos = scaleXFontValue(tools::Long(aCurrentTab.aTabStop.GetTabPos() + nAllSpaceBeforeText/*rLRItem.GetTextLeft()*/)); aCurrentTab.bValid = false; // Switch direction in R2L para... @@ -1286,8 +1287,8 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // No spacing within L2R/R2L nesting if ( bAllow ) { - tools::Long nExtraSpace = pPortion->GetSize().Height()/5; - nExtraSpace = GetXValue( nExtraSpace ); + tools::Long nExtraSpace = pPortion->GetSize().Height() / 5; + nExtraSpace = scaleXSpacingValue(nExtraSpace); pPortion->adjustSize(nExtraSpace, 0); nTmpWidth += nExtraSpace; } @@ -1500,12 +1501,13 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) bSameLineAgain = true; } - if ( !bSameLineAgain && !aStatus.IsOutliner() ) { if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Min ) { - sal_uInt16 nMinHeight = GetYValue( rLSItem.GetLineHeight() ); + double fMinHeight = scaleYSpacingValue(rLSItem.GetLineHeight()); + sal_uInt16 nMinHeight = basegfx::fround(fMinHeight); + sal_uInt16 nTxtHeight = pLine->GetHeight(); if ( nTxtHeight < nMinHeight ) { @@ -1517,7 +1519,9 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) } else if ( rLSItem.GetLineSpaceRule() == SvxLineSpaceRule::Fix ) { - sal_uInt16 nFixHeight = GetYValue( rLSItem.GetLineHeight() ); + double fFixHeight = scaleYSpacingValue(rLSItem.GetLineHeight()); + sal_uInt16 nFixHeight = basegfx::fround(fFixHeight); + sal_uInt16 nTxtHeight = pLine->GetHeight(); pLine->SetMaxAscent( static_cast<sal_uInt16>(pLine->GetMaxAscent() + ( nFixHeight - nTxtHeight ) ) ); pLine->SetHeight( nFixHeight, nTxtHeight ); @@ -1526,29 +1530,51 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) { // There are documents with PropLineSpace 0, why? // (cmc: re above question :-) such documents can be seen by importing a .ppt - if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() < 100 ) ) + sal_uInt16 nPropLineSpace = rLSItem.GetPropLineSpace(); + double fProportionalScale = double(nPropLineSpace) / 100.0; + constexpr const double f80Percent = 8.0 / 10.0; + double fSpacingFactor = mfSpacingScaleY / 100.0; + if (nPropLineSpace && nPropLineSpace < 100) { // Adapted code from sw/source/core/text/itrform2.cxx - sal_uInt16 nPropLineSpace = rLSItem.GetPropLineSpace(); sal_uInt16 nAscent = pLine->GetMaxAscent(); - sal_uInt16 nNewAscent = pLine->GetTxtHeight() * nPropLineSpace / 100 * 4 / 5; // 80% - if ( !nAscent || nAscent > nNewAscent ) - { - pLine->SetMaxAscent( nNewAscent ); - } - sal_uInt16 nHeight = pLine->GetHeight() * nPropLineSpace / 100; - pLine->SetHeight( nHeight, pLine->GetTxtHeight() ); + sal_uInt16 nNewAscent = basegfx::fround(pLine->GetTxtHeight() * fSpacingFactor * fProportionalScale * f80Percent); + if (!nAscent || nAscent > nNewAscent) + pLine->SetMaxAscent(nNewAscent); + sal_uInt16 nHeight = basegfx::fround(pLine->GetHeight() * fProportionalScale * fSpacingFactor); + + pLine->SetHeight(nHeight, pLine->GetTxtHeight()); } - else if ( rLSItem.GetPropLineSpace() && ( rLSItem.GetPropLineSpace() != 100 ) ) + else if (nPropLineSpace && nPropLineSpace != 100) { sal_uInt16 nTxtHeight = pLine->GetHeight(); - sal_Int32 nPropTextHeight = nTxtHeight * rLSItem.GetPropLineSpace() / 100; + sal_Int32 nPropTextHeight = nTxtHeight * fProportionalScale * fSpacingFactor; // The Ascent has to be adjusted for the difference: tools::Long nDiff = pLine->GetHeight() - nPropTextHeight; pLine->SetMaxAscent( static_cast<sal_uInt16>( pLine->GetMaxAscent() - nDiff ) ); pLine->SetHeight( static_cast<sal_uInt16>( nPropTextHeight ), nTxtHeight ); } } + else if (rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Off) + { + if (mfSpacingScaleY < 100.0) + { + double fSpacingFactor = mfSpacingScaleY / 100.0; + sal_uInt16 nPropLineSpace = basegfx::fround(100.0 * fSpacingFactor); + if (nPropLineSpace && nPropLineSpace < 100) + { + // Adapted code from sw/source/core/text/itrform2.cxx + sal_uInt16 nAscent = pLine->GetMaxAscent(); + sal_uInt16 nNewAscent = basegfx::fround(pLine->GetTxtHeight() * fSpacingFactor); + if (!nAscent || nAscent > nNewAscent) + pLine->SetMaxAscent(nNewAscent); + sal_uInt16 nHeight = basegfx::fround(pLine->GetHeight() * fSpacingFactor); + + pLine->SetHeight(nHeight, pLine->GetTxtHeight()); + } + + } + } } if ( ( !IsEffectivelyVertical() && aStatus.AutoPageWidth() ) || @@ -1558,8 +1584,7 @@ bool ImpEditEngine::CreateLines( sal_Int32 nPara, sal_uInt32 nStartPosY ) // has to be used for the Alignment. If it does not fit or if it // will change the paper width, it will be formatted again for // Justification! = LEFT anyway. - tools::Long nMaxLineWidthFix = GetColumnWidth(aPaperSize) - - GetXValue( rLRItem.GetRight() ) - nStartX; + tools::Long nMaxLineWidthFix = GetColumnWidth(aPaperSize) - scaleXSpacingValue(rLRItem.GetRight()) - nStartX; if ( aTextSize.Width() < nMaxLineWidthFix ) nMaxLineWidth = nMaxLineWidthFix; } @@ -1784,23 +1809,23 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) sal_Int32 nSpaceBeforeAndMinLabelWidth = GetSpaceBeforeAndMinLabelWidth( pParaPortion->GetNode(), &nSpaceBefore ); const SvxLRSpaceItem& rLRItem = GetLRSpaceItem( pParaPortion->GetNode() ); const SvxLineSpacingItem& rLSItem = pParaPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); - tools::Long nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore ); + tools::Long nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBefore); tools::Rectangle aBulletArea { Point(), Point() }; if ( bLineBreak ) { - nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth ); + nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth); } else { aBulletArea = GetEditEnginePtr()->GetBulletArea( GetParaPortions().GetPos( pParaPortion ) ); if ( !aBulletArea.IsEmpty() && aBulletArea.Right() > 0 ) - pParaPortion->SetBulletX( static_cast<sal_Int32>(GetXValue( aBulletArea.Right() )) ); + pParaPortion->SetBulletX(sal_Int32(scaleXSpacingValue(aBulletArea.Right()))); else pParaPortion->SetBulletX( 0 ); // If Bullet set incorrectly. if ( pParaPortion->GetBulletX() > nStartX ) { - nStartX = GetXValue( rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth ); + nStartX = scaleXSpacingValue(rLRItem.GetTextLeft() + rLRItem.GetTextFirstLineOffset() + nSpaceBeforeAndMinLabelWidth); if ( pParaPortion->GetBulletX() > nStartX ) nStartX = pParaPortion->GetBulletX(); } @@ -1828,7 +1853,7 @@ void ImpEditEngine::CreateAndInsertEmptyLine( ParaPortion* pParaPortion ) sal_Int32 nPara = GetParaPortions().GetPos( pParaPortion ); SvxAdjust eJustification = GetJustification( nPara ); tools::Long nMaxLineWidth = GetColumnWidth(aPaperSize); - nMaxLineWidth -= GetXValue( rLRItem.GetRight() ); + nMaxLineWidth -= scaleXSpacingValue(rLRItem.GetRight()); if ( nMaxLineWidth < 0 ) nMaxLineWidth = 1; if ( eJustification == SvxAdjust::Center ) @@ -2994,20 +3019,24 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo if ( aStatus.DoStretch() ) { - if (mnStretchY != 100.0) + if (mfFontScaleY != 100.0) { - double fNewHeight = (double(aRealSz.Height()) * mnStretchY) / 100.0; + double fHeightRounded = roundToNearestPt(aRealSz.Height()); + double fNewHeight = fHeightRounded * (mfFontScaleY / 100.0); + fNewHeight = roundToNearestPt(fNewHeight); aRealSz.setHeight(basegfx::fround(fNewHeight)); } - if (mnStretchX != 100.0) + if (mfFontScaleX != 100.0) { - if (mnStretchX == mnStretchY && nRelWidth == 100 ) + if (mfFontScaleX == mfFontScaleY && nRelWidth == 100 ) { aRealSz.setWidth( 0 ); } else { - double fNewWidth = (double(aRealSz.Width()) * mnStretchX) / 100.0; + double fWidthRounded = roundToNearestPt(aRealSz.Width()); + double fNewWidth = fWidthRounded * (mfFontScaleX / 100.0); + fNewWidth = roundToNearestPt(fNewWidth); aRealSz.setWidth(basegfx::fround(fNewWidth)); // Also the Kerning: (long due to handle Interim results) @@ -3023,15 +3052,15 @@ void ImpEditEngine::SeekCursor( ContentNode* pNode, sal_Int32 nPos, SvxFont& rFo >0 >100 > (Proportional) <0 >100 < (The amount, thus disproportional) */ - if (nKerning < 0 && mnStretchX > 100.0) + if (nKerning < 0 && mfFontScaleX > 100.0) { // disproportional - nKerning = basegfx::fround((double(nKerning) * 100.0) / mnStretchX); + nKerning = basegfx::fround((double(nKerning) * 100.0) / mfFontScaleX); } else if ( nKerning ) { // Proportional - nKerning = basegfx::fround((double(nKerning) * mnStretchX) / 100.0); + nKerning = basegfx::fround((double(nKerning) * mfFontScaleX) / 100.0); } rFont.SetFixKerning( static_cast<short>(nKerning) ); } @@ -3369,7 +3398,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_SBL ); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) - ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; bool bPaintBullet (false); for ( sal_Int32 nLine = 0; nLine < nLines; nLine++ ) @@ -4033,7 +4062,7 @@ void ImpEditEngine::Paint( OutputDevice& rOutDev, tools::Rectangle aClipRect, Po if ( !aStatus.IsOutliner() ) { const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem( EE_PARA_ULSPACE ); - tools::Long nUL = GetYValue( rULItem.GetLower() ); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); adjustYDirectionAware(aStartPos, nUL); } @@ -4359,10 +4388,10 @@ tools::Long ImpEditEngine::CalcVertLineSpacing(Point& rStartPos) const const SvxLineSpacingItem& rLSItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_SBL); sal_uInt16 nSBL = ( rLSItem.GetInterLineSpaceRule() == SvxInterLineSpaceRule::Fix ) - ? GetYValue( rLSItem.GetInterLineSpace() ) : 0; + ? scaleYSpacingValue(rLSItem.GetInterLineSpace()) : 0; const SvxULSpaceItem& rULItem = pPortion->GetNode()->GetContentAttribs().GetItem(EE_PARA_ULSPACE); - tools::Long nUL = GetYValue( rULItem.GetLower() ); + tools::Long nUL = scaleYSpacingValue(rULItem.GetLower()); const EditLineList& rLines = pPortion->GetLines(); sal_Int32 nLineCount = rLines.Count(); @@ -4459,28 +4488,35 @@ void ImpEditEngine::SetFlatMode( bool bFlat ) pActiveView->ShowCursor(); } -void ImpEditEngine::SetCharStretching(double nX, double nY) +void ImpEditEngine::setScale(double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY) { bool bChanged; - if ( !IsEffectivelyVertical() ) + + if (!IsEffectivelyVertical()) { - bChanged = mnStretchX != nX || mnStretchY != nY; - mnStretchX = nX; - mnStretchY = nY; + bChanged = mfFontScaleX != fFontScaleX || mfFontScaleY != fFontScaleY || + mfSpacingScaleX != fSpacingScaleX || mfSpacingScaleY != fSpacingScaleY; + mfFontScaleX = fFontScaleX; + mfFontScaleY = fFontScaleY; + mfSpacingScaleX = fSpacingScaleX; + mfSpacingScaleY = fSpacingScaleY; } else { - bChanged = mnStretchX != nY || mnStretchY != nX; - mnStretchX = nY; - mnStretchY = nX; + bChanged = mfFontScaleX != fFontScaleY || mfFontScaleY != fFontScaleX || + mfSpacingScaleX != fSpacingScaleY || mfSpacingScaleY != fSpacingScaleX; + mfFontScaleX = fFontScaleY; + mfFontScaleY = fFontScaleX; + mfSpacingScaleX = fSpacingScaleY; + mfSpacingScaleY = fSpacingScaleX; } if (bChanged && aStatus.DoStretch()) { FormatFullDoc(); // (potentially) need everything redrawn - aInvalidRect=tools::Rectangle(0,0,1000000,1000000); - UpdateViews( GetActiveView() ); + aInvalidRect = tools::Rectangle(0, 0, 1000000, 1000000); + UpdateViews(GetActiveView()); } } diff --git a/editeng/source/editeng/impedit4.cxx b/editeng/source/editeng/impedit4.cxx index 5affeff55455..424b43aadaeb 100644 --- a/editeng/source/editeng/impedit4.cxx +++ b/editeng/source/editeng/impedit4.cxx @@ -1093,7 +1093,7 @@ std::unique_ptr<EditTextObject> ImpEditEngine::CreateTextObject( EditSelection a // sleeper set up when Olli paragraphs not hacked! if ( bAllowBigObjects && bOnlyFullParagraphs && IsFormatted() && IsUpdateLayout() && ( nTextPortions >= nBigObjectStart ) ) { - XParaPortionList* pXList = new XParaPortionList( GetRefDevice(), GetColumnWidth(aPaperSize), mnStretchX, mnStretchY ); + XParaPortionList* pXList = new XParaPortionList(GetRefDevice(), GetColumnWidth(aPaperSize), mfFontScaleX, mfFontScaleY, mfSpacingScaleX, mfSpacingScaleY); pTxtObj->SetPortionInfo(std::unique_ptr<XParaPortionList>(pXList)); for ( nNode = nStartNode; nNode <= nEndNode; nNode++ ) { @@ -1178,9 +1178,11 @@ EditSelection ImpEditEngine::InsertTextObject( const EditTextObject& rTextObject XParaPortionList* pPortionInfo = rTextObjectImpl.GetPortionInfo(); if ( pPortionInfo && ( static_cast<tools::Long>(pPortionInfo->GetPaperWidth()) == GetColumnWidth(aPaperSize) ) - && ( pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() ) - && ( pPortionInfo->GetStretchX() == mnStretchX) - && ( pPortionInfo->GetStretchY() == mnStretchY)) + && pPortionInfo->GetRefMapMode() == GetRefDevice()->GetMapMode() + && pPortionInfo->getFontScaleX() == mfFontScaleX + && pPortionInfo->getFontScaleY() == mfFontScaleY + && pPortionInfo->getSpacingScaleX() == mfSpacingScaleX + && pPortionInfo->getSpacingScaleY() == mfSpacingScaleY) { if ( (pPortionInfo->GetRefDevPtr() == GetRefDevice()) || (pPortionInfo->RefDevIsVirtual() && GetRefDevice()->IsVirtual()) ) @@ -3103,4 +3105,18 @@ sal_Int32 ImpEditEngine::LogicToTwips(sal_Int32 n) return aSz.Width(); } +double ImpEditEngine::roundToNearestPt(double fInput) const +{ + if (mbRoundToNearestPt) + { + double fInputPt = o3tl::convert(fInput, o3tl::Length::mm100, o3tl::Length::pt); + auto nInputRounded = basegfx::fround(fInputPt); + return o3tl::convert(double(nInputRounded), o3tl::Length::pt, o3tl::Length::mm100); + } + else + { + return fInput; + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/editeng/source/outliner/outlin2.cxx b/editeng/source/outliner/outlin2.cxx index 013c680df152..c3a672499ef5 100644 --- a/editeng/source/outliner/outlin2.cxx +++ b/editeng/source/outliner/outlin2.cxx @@ -482,7 +482,7 @@ void Outliner::QuickFormatDoc() pEditEngine->QuickFormatDoc(); } -void Outliner::SetGlobalCharStretching(double nX, double nY) +void Outliner::setGlobalScale(double rFontX, double rFontY, double rSpacingX, double rSpacingY) { // reset bullet size sal_Int32 nParagraphs = pParaList->GetParagraphCount(); @@ -493,12 +493,18 @@ void Outliner::SetGlobalCharStretching(double nX, double nY) pPara->aBulSize.setWidth( -1 ); } - pEditEngine->SetGlobalCharStretching( nX, nY ); + pEditEngine->setGlobalScale(rFontX, rFontY, rSpacingX, rSpacingY); } -void Outliner::GetGlobalCharStretching(double& rX, double& rY) const +void Outliner::getGlobalScale(double& rFontX, double& rFontY, double& rSpacingX, double& rSpacingY) const { - pEditEngine->GetGlobalCharStretching(rX, rY); + pEditEngine->getGlobalFontScale(rFontX, rFontY); + pEditEngine->getGlobalSpacingScale(rSpacingX, rSpacingY); +} + +void Outliner::setRoundFontSizeToPt(bool bRound) const +{ + pEditEngine->setRoundFontSizeToPt(bRound); } void Outliner::EraseVirtualDevice() diff --git a/editeng/source/outliner/outliner.cxx b/editeng/source/outliner/outliner.cxx index 72340587ba05..6cd7ab274b0a 100644 --- a/editeng/source/outliner/outliner.cxx +++ b/editeng/source/outliner/outliner.cxx @@ -48,6 +48,7 @@ #include <sal/log.hxx> #include <o3tl/safeint.hxx> #include <o3tl/string_view.hxx> +#include <o3tl/temporary.hxx> #include <osl/diagnose.h> #include <memory> @@ -801,7 +802,6 @@ bool Outliner::Collapse( Paragraph const * pPara ) return true; } - vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const { const SvxNumberFormat* pFmt = GetNumberFormat( nPara ); @@ -840,16 +840,16 @@ vcl::Font Outliner::ImpCalcBulletFont( sal_Int32 nPara ) const } // Use original scale... - double nStretchX, nStretchY; - GetGlobalCharStretching(nStretchX, nStretchY); + double nStretchY = 100.0; + getGlobalScale(o3tl::temporary(double()), nStretchY, o3tl::temporary(double()), o3tl::temporary(double())); - sal_uInt16 nScale = pFmt->GetBulletRelSize() * nStretchY / 100; - tools::Long nScaledLineHeight = aStdFont.GetFontSize().Height(); - nScaledLineHeight *= nScale*10; - nScaledLineHeight /= 1000; + double fScale = pFmt->GetBulletRelSize() * nStretchY / 100.0; + double fScaledLineHeight = aStdFont.GetFontSize().Height(); + fScaledLineHeight *= fScale * 10; + fScaledLineHeight /= 1000.0; aBulletFont.SetAlignment( ALIGN_BOTTOM ); - aBulletFont.SetFontSize( Size( 0, nScaledLineHeight ) ); + aBulletFont.SetFontSize(Size(0, basegfx::fround(fScaledLineHeight))); bool bVertical = IsVertical(); aBulletFont.SetVertical( bVertical ); aBulletFont.SetOrientation( Degree10(bVertical ? (IsTopToBottom() ? 2700 : 900) : 0) ); @@ -887,8 +887,11 @@ void Outliner::PaintBullet(sal_Int32 nPara, const Point& rStartPos, const Point& bool bRightToLeftPara = pEditEngine->IsRightToLeft( nPara ); tools::Rectangle aBulletArea( ImpCalcBulletArea( nPara, true, false ) ); - double nStretchX, nStretchY; - GetGlobalCharStretching(nStretchX, nStretchY); + + double nStretchX = 100.0; + getGlobalScale(o3tl::temporary(double()), o3tl::temporary(double()), + nStretchX, o3tl::temporary(double())); + tools::Long nStretchBulletX = basegfx::fround(double(aBulletArea.Left()) * nStretchX / 100.0); tools::Long nStretchBulletWidth = basegfx::fround(double(aBulletArea.GetWidth()) * nStretchX / 100.0); aBulletArea = tools::Rectangle(Point(nStretchBulletX, aBulletArea.Top()), diff --git a/include/editeng/editeng.hxx b/include/editeng/editeng.hxx index f5487e779a4b..0693d06821f9 100644 --- a/include/editeng/editeng.hxx +++ b/include/editeng/editeng.hxx @@ -414,8 +414,12 @@ public: void QuickDelete( const ESelection& rSel ); void QuickMarkToBeRepainted( sal_Int32 nPara ); - void SetGlobalCharStretching(double nX, double nY); - void GetGlobalCharStretching(double& rX, double& rY) const; + void setGlobalScale(double fFontScaleX, double fFontScaleY, double fSpacingScaleX, double fSpacingScaleY); + + void getGlobalSpacingScale(double& rX, double& rY) const; + void getGlobalFontScale(double& rX, double& rY) const; + + void setRoundFontSizeToPt(bool bRound) const; void SetEditTextObjectPool( SfxItemPool* pPool ); SfxItemPool* GetEditTextObjectPool() const; diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index a4f02568a64f..192b30d01634 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -931,8 +931,10 @@ public: bool IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder ); bool IsTextPos( const Point& rPaperPos, sal_uInt16 nBorder, bool* pbBulletPos ); - void SetGlobalCharStretching(double nX = 100.0, double nY = 100.0); - void GetGlobalCharStretching(double& rX, double& rY) const; + void setGlobalScale(double rFontX = 100.0, double rFontY = 100.0, double rSpacingX = 100.0, double rSpacingY = 100.0); + void getGlobalScale(double& rFontX, double& rFontY, double& rSpacingX, double& rSpacingY) const; + void setRoundFontSizeToPt(bool bRound) const; + void EraseVirtualDevice(); bool ShouldCreateBigTextObject() const; diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index 59c9ace37113..2a72225680fb 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -315,7 +315,7 @@ public: @returns true if any paragraph properties were written */ - bool WriteParagraphProperties(const css::uno::Reference< css::text::XTextContent >& rParagraph, const css::uno::Reference<css::beans::XPropertySet>& rXShapePropSet, float fFirstCharHeight, sal_Int32 nElement); + bool WriteParagraphProperties(const css::uno::Reference< css::text::XTextContent >& rParagraph, float fFirstCharHeight, sal_Int32 nElement); void WriteParagraphNumbering(const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, float fFirstCharHeight, sal_Int16 nLevel ); void WriteParagraphTabStops(const css::uno::Reference<css::beans::XPropertySet>& rXPropSet); diff --git a/include/svx/sdtfsitm.hxx b/include/svx/sdtfsitm.hxx index d98e431dab68..ccdcb7c4dbe9 100644 --- a/include/svx/sdtfsitm.hxx +++ b/include/svx/sdtfsitm.hxx @@ -35,14 +35,17 @@ class SVXCORE_DLLPUBLIC SdrTextFitToSizeTypeItem final { public: static SfxPoolItem* CreateDefault(); - SdrTextFitToSizeTypeItem( - css::drawing::TextFitToSizeType const eFit = css::drawing::TextFitToSizeType_NONE) - : SfxEnumItem(SDRATTR_TEXT_FITTOSIZE, eFit) {} + SdrTextFitToSizeTypeItem(css::drawing::TextFitToSizeType const eFit = css::drawing::TextFitToSizeType_NONE) + : SfxEnumItem(SDRATTR_TEXT_FITTOSIZE, eFit) + { + } + SdrTextFitToSizeTypeItem(const SdrTextFitToSizeTypeItem& rItem) - : SfxEnumItem(rItem), - m_nMaxScale(rItem.GetMaxScale()) + : SfxEnumItem(rItem) + , m_nMaxScale(rItem.GetMaxScale()) { } + virtual SdrTextFitToSizeTypeItem* Clone(SfxItemPool* pPool=nullptr) const override; bool operator==(const SfxPoolItem& rItem) const override; virtual sal_uInt16 GetValueCount() const override; @@ -55,10 +58,11 @@ public: virtual bool HasBoolValue() const override; virtual bool GetBoolValue() const override; virtual void SetBoolValue(bool bVal) override; - void SetMaxScale(sal_Int16 nMaxScale) { m_nMaxScale = nMaxScale; } - sal_Int16 GetMaxScale() const { return m_nMaxScale; } + + void SetMaxScale(double nMaxScale) { m_nMaxScale = nMaxScale; } + double GetMaxScale() const { return m_nMaxScale; } private: - sal_Int16 m_nMaxScale = 0; + double m_nMaxScale = 0.0; }; #endif diff --git a/include/svx/svdotext.hxx b/include/svx/svdotext.hxx index a1cccb0804a4..ccecae20e2f8 100644 --- a/include/svx/svdotext.hxx +++ b/include/svx/svdotext.hxx @@ -275,6 +275,8 @@ private: Fraction& aFitXCorrection ) const; void ImpAutoFitText( SdrOutliner& rOutliner ) const; void ImpAutoFitText( SdrOutliner& rOutliner, const Size& rShapeSize, bool bIsVerticalWriting ) const; + void autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size& rShapeSize) const; + SVX_DLLPRIVATE rtl::Reference<SdrObject> ImpConvertContainedTextToSdrPathObjs(bool bToPoly) const; SVX_DLLPRIVATE void ImpRegisterLink(); SVX_DLLPRIVATE void ImpDeregisterLink(); @@ -403,7 +405,9 @@ public: // FitToSize and Fontwork are not taken into account in GetTextSize()! virtual const Size& GetTextSize() const; void FitFrameToTextSize(); - sal_uInt16 GetFontScaleY() const; + + double GetFontScale() const; + double GetSpacingScale() const; // Simultaneously sets the text into the Outliner (possibly // the one of the EditOutliner) and sets the PaperSize. diff --git a/include/svx/unoshprp.hxx b/include/svx/unoshprp.hxx index 70be33007013..8a6302659702 100644 --- a/include/svx/unoshprp.hxx +++ b/include/svx/unoshprp.hxx @@ -363,7 +363,7 @@ { UNO_NAME_MISC_OBJ_SIZEPROTECT, SDRATTR_OBJSIZEPROTECT , cppu::UnoType<bool>::get(), 0, 0},\ { u"UINameSingular", OWN_ATTR_UINAME_SINGULAR , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, \ { u"UINamePlural", OWN_ATTR_UINAME_PLURAL , ::cppu::UnoType<OUString>::get(), css::beans::PropertyAttribute::READONLY, 0}, \ - { u"TextFitToSizeScale", OWN_ATTR_TEXTFITTOSIZESCALE, ::cppu::UnoType<sal_Int16>::get(), 0, 0}, \ + { u"TextFitToSizeScale", OWN_ATTR_TEXTFITTOSIZESCALE, ::cppu::UnoType<double>::get(), 0, 0}, \ /* #i68101# */ \ { UNO_NAME_MISC_OBJ_TITLE, OWN_ATTR_MISC_OBJ_TITLE , ::cppu::UnoType<OUString>::get(), 0, 0}, \ { UNO_NAME_MISC_OBJ_DESCRIPTION, OWN_ATTR_MISC_OBJ_DESCRIPTION , ::cppu::UnoType<OUString>::get(), 0, 0}, \ diff --git a/oox/inc/drawingml/textparagraph.hxx b/oox/inc/drawingml/textparagraph.hxx index 4920c99da7c5..1f43249372a5 100644 --- a/oox/inc/drawingml/textparagraph.hxx +++ b/oox/inc/drawingml/textparagraph.hxx @@ -77,8 +77,7 @@ public: const TextListStyle& rMasterTextListStyle, const TextListStyle& rTextListStyle, bool bFirst, - float nDefaultCharHeight, - sal_Int32 nAutofitFontScale) const; + float nDefaultCharHeight) const; bool HasMathXml() const { diff --git a/oox/inc/drawingml/textparagraphproperties.hxx b/oox/inc/drawingml/textparagraphproperties.hxx index d3742e7377e0..e362119ed6f9 100644 --- a/oox/inc/drawingml/textparagraphproperties.hxx +++ b/oox/inc/drawingml/textparagraphproperties.hxx @@ -104,7 +104,6 @@ public: const BulletList* pMasterBuList, bool bApplyBulletList, float fFontSize, - sal_Int32 nAutofitFontScale = 100000, bool bPushDefaultValues = false ) const; /** Returns the largest character size of this paragraph. If possible the diff --git a/oox/source/drawingml/diagram/diagram.cxx b/oox/source/drawingml/diagram/diagram.cxx index efba958fa0e4..7927b7aa6945 100644 --- a/oox/source/drawingml/diagram/diagram.cxx +++ b/oox/source/drawingml/diagram/diagram.cxx @@ -186,13 +186,13 @@ void Diagram::syncDiagramFontHeights() { // Find out the minimum scale within this group. const ShapePairs& rShapePairs = rNameAndPairs.second; - sal_Int16 nMinScale = 100; + double nMinScale = 100.0; for (const auto& rShapePair : rShapePairs) { uno::Reference<beans::XPropertySet> xPropertySet(rShapePair.second, uno::UNO_QUERY); if (xPropertySet.is()) { - sal_Int16 nTextFitToSizeScale = 0; + double nTextFitToSizeScale = 0.0; xPropertySet->getPropertyValue("TextFitToSizeScale") >>= nTextFitToSizeScale; if (nTextFitToSizeScale > 0 && nTextFitToSizeScale < nMinScale) { @@ -202,7 +202,7 @@ void Diagram::syncDiagramFontHeights() } // Set that minimum scale for all members of the group. - if (nMinScale < 100) + if (nMinScale < 100.0) { for (const auto& rShapePair : rShapePairs) { diff --git a/oox/source/drawingml/textbody.cxx b/oox/source/drawingml/textbody.cxx index 1be15c4f885d..266ff44b22f9 100644 --- a/oox/source/drawingml/textbody.cxx +++ b/oox/source/drawingml/textbody.cxx @@ -65,7 +65,7 @@ void TextBody::insertAt( for (auto const& paragraph : maParagraphs) { paragraph->insertAt(rFilterBase, xText, xAt, rTextStyleProperties, aMasterTextStyle, - maTextListStyle, (nIndex == 0), nCharHeight, getTextProperties().mnFontScale); + maTextListStyle, (nIndex == 0), nCharHeight); ++nIndex; } } @@ -149,7 +149,7 @@ void TextBody::ApplyStyleEmpty( TextParagraphProperties aParaProp; aParaProp.apply(*pTextParagraphStyle); aParaProp.pushToPropSet(&rFilterBase, xProps, aioBulletList, &pTextParagraphStyle->getBulletList(), - true, nCharHeight, getTextProperties().mnFontScale, true); + true, nCharHeight, true); } } diff --git a/oox/source/drawingml/textparagraph.cxx b/oox/source/drawingml/textparagraph.cxx index f08efdbff3c3..e33cbb690ee9 100644 --- a/oox/source/drawingml/textparagraph.cxx +++ b/oox/source/drawingml/textparagraph.cxx @@ -88,7 +88,7 @@ void TextParagraph::insertAt( const TextCharacterProperties& rTextStyleProperties, const TextListStyle& rMasterTextListStyle, const TextListStyle& rTextListStyle, bool bFirst, - float nDefaultCharHeight, sal_Int32 nAutofitFontScale) const + float nDefaultCharHeight) const { try { sal_Int32 nParagraphSize = 0; @@ -176,7 +176,7 @@ void TextParagraph::insertAt( } float fCharacterSize = nCharHeight > 0 ? GetFontHeight ( nCharHeight ) : pTextParagraphStyle->getCharHeightPoints( 12 ); - aParaProp.pushToPropSet( &rFilterBase, xProps, aioBulletList, &pTextParagraphStyle->getBulletList(), true, fCharacterSize, nAutofitFontScale, true ); + aParaProp.pushToPropSet( &rFilterBase, xProps, aioBulletList, &pTextParagraphStyle->getBulletList(), true, fCharacterSize, true ); } // empty paragraphs do not have bullets in ppt diff --git a/oox/source/drawingml/textparagraphproperties.cxx b/oox/source/drawingml/textparagraphproperties.cxx index af65e0037d16..8122c4e53324 100644 --- a/oox/source/drawingml/textparagraphproperties.cxx +++ b/oox/source/drawingml/textparagraphproperties.cxx @@ -407,7 +407,7 @@ void TextParagraphProperties::apply( const TextParagraphProperties& rSourceProps void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* pFilterBase, const Reference < XPropertySet >& xPropSet, PropertyMap& rioBulletMap, const BulletList* pMasterBuList, bool bApplyBulletMap, float fCharacterSize, - sal_Int32 nAutofitFontScale, bool bPushDefaultValues ) const + bool bPushDefaultValues ) const { PropertySet aPropSet( xPropSet ); aPropSet.setProperties( maTextParagraphPropertyMap ); @@ -433,14 +433,6 @@ void TextParagraphProperties::pushToPropSet( const ::oox::core::XmlFilterBase* p std::optional< sal_Int32 > noParaLeftMargin( moParaLeftMargin ); std::optional< sal_Int32 > noFirstLineIndentation( moFirstLineIndentation ); - // tdf#149961 Impress scales the indents when text is autofitted while Powerpoint doesn't - // Try to counteract this by multiplying indents by the inverse of the autofit font scale. - if ( nAutofitFontScale ) - { - if ( noParaLeftMargin ) noParaLeftMargin = *noParaLeftMargin * MAX_PERCENT / nAutofitFontScale; - if ( noFirstLineIndentation ) noFirstLineIndentation = *noFirstLineIndentation * MAX_PERCENT / nAutofitFontScale; - } - if ( nNumberingType != NumberingType::NUMBER_NONE ) { if ( noParaLeftMargin ) diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 5335dca58486..d610435d0eb2 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -3200,7 +3200,7 @@ void DrawingML::WriteLinespacing(const LineSpacing& rSpacing, float fFirstCharHe } } -bool DrawingML::WriteParagraphProperties(const Reference<XTextContent>& rParagraph, const Reference<XPropertySet>& rXShapePropSet, float fFirstCharHeight, sal_Int32 nElement) +bool DrawingML::WriteParagraphProperties(const Reference<XTextContent>& rParagraph, float fFirstCharHeight, sal_Int32 nElement) { Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY ); Reference< XPropertyState > rXPropState( rParagraph, UNO_QUERY ); @@ -3294,24 +3294,6 @@ bool DrawingML::WriteParagraphProperties(const Reference<XTextContent>& rParagra if (GetProperty(rXPropSet, "ParaTabStopDefaultDistance")) mAny >>= nParaDefaultTabSize; - // for autofitted textboxes, scale the indents - if (GetProperty(rXShapePropSet, "TextFitToSize") && mAny.get<TextFitToSizeType>() == TextFitToSizeType_AUTOFIT) - { - SvxShapeText* pTextShape = dynamic_cast<SvxShapeText*>(rXShapePropSet.get()); - if (pTextShape) - { - SdrTextObj* pTextObject = DynCastSdrTextObj(pTextShape->GetSdrObject()); - if (pTextObject) - { - const auto nFontScaleY = pTextObject->GetFontScaleY(); - nLeftMargin = nLeftMargin * nFontScaleY / 100; - nLineIndentation = nLineIndentation * nFontScaleY / 100; - nParaLeftMargin = nParaLeftMargin * nFontScaleY / 100; - nParaFirstLineIndent = nParaFirstLineIndent * nFontScaleY / 100; - } - } - } - if (nParaLeftMargin) // For Paragraph mpFS->startElementNS( XML_a, nElement, XML_lvl, sax_fastparser::UseIf(OString::number(nLevel), nLevel > 0), @@ -3401,7 +3383,7 @@ void DrawingML::WriteLstStyles(const css::uno::Reference<css::text::XTextContent fFirstCharHeight = xFirstRunPropSet->getPropertyValue("CharHeight").get<float>(); mpFS->startElementNS(XML_a, XML_lstStyle); - if( !WriteParagraphProperties(rParagraph, rXShapePropSet, fFirstCharHeight, XML_lvl1pPr) ) + if( !WriteParagraphProperties(rParagraph, fFirstCharHeight, XML_lvl1pPr) ) mpFS->startElementNS(XML_a, XML_lvl1pPr); WriteRunProperties(xFirstRunPropSet, false, XML_defRPr, true, rbOverridingCharHeight, rnCharHeight, GetScriptType(rRun->getString()), rXShapePropSet); @@ -3443,7 +3425,7 @@ void DrawingML::WriteParagraph( const Reference< XTextContent >& rParagraph, rnCharHeight = 100 * fFirstCharHeight; rbOverridingCharHeight = true; } - WriteParagraphProperties(rParagraph, rXShapePropSet, fFirstCharHeight, XML_pPr); + WriteParagraphProperties(rParagraph, fFirstCharHeight, XML_pPr); bPropertiesWritten = true; } WriteRun( run, rbOverridingCharHeight, rnCharHeight, rXShapePropSet); @@ -3994,16 +3976,29 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo { const sal_Int32 MAX_SCALE_VAL = 100000; sal_Int32 nFontScale = MAX_SCALE_VAL; + sal_Int32 nSpacingReduction = 0; SvxShapeText* pTextShape = dynamic_cast<SvxShapeText*>(rXIface.get()); if (pTextShape) { SdrTextObj* pTextObject = DynCastSdrTextObj(pTextShape->GetSdrObject()); if (pTextObject) - nFontScale = pTextObject->GetFontScaleY() * 1000; + { + nFontScale = sal_Int32(pTextObject->GetFontScale() * 1000.0); + nSpacingReduction = sal_Int32((100.0 - pTextObject->GetSpacingScale()) * 1000.0); + } } - mpFS->singleElementNS(XML_a, XML_normAutofit, XML_fontScale, - sax_fastparser::UseIf(OString::number(nFontScale), nFontScale < MAX_SCALE_VAL && nFontScale > 0)); + bool bExportFontScale = false; + if (nFontScale < MAX_SCALE_VAL && nFontScale > 0) + bExportFontScale = true; + + bool bExportSpaceReduction = false; + if (nSpacingReduction < MAX_SCALE_VAL && nSpacingReduction > 0) + bExportSpaceReduction = true; + + mpFS->singleElementNS(XML_a, XML_normAutofit, + XML_fontScale, sax_fastparser::UseIf(OString::number(nFontScale), bExportFontScale), + XML_lnSpcReduction, sax_fastparser::UseIf(OString::number(nSpacingReduction), bExportSpaceReduction)); } else { @@ -4091,7 +4086,7 @@ void DrawingML::WriteText(const Reference<XInterface>& rXIface, bool bBodyPr, bo if( aAny >>= xParagraph ) { mpFS->startElementNS(XML_a, XML_p); - WriteParagraphProperties(xParagraph, rXPropSet, nCharHeight, XML_pPr); + WriteParagraphProperties(xParagraph, nCharHeight, XML_pPr); sal_Int16 nDummy = -1; WriteRunProperties(rXPropSet, false, XML_endParaRPr, false, bOverridingCharHeight, nCharHeight, nDummy, rXPropSet); diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index b4d993a3c0c9..7d04d29886ec 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -1823,10 +1823,10 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTextColumns_3columns) CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(300)), xColProps->getPropertyValue("AutomaticDistance")); // Scale value may be unstable; just test that the text is actually scaled - sal_Int16 nScale; - CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeScale") >>= nScale); - CPPUNIT_ASSERT_GREATER(sal_Int16(0), nScale); - CPPUNIT_ASSERT_LESS(sal_Int16(100), nScale); + double fScale; + CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeScale") >>= fScale); + CPPUNIT_ASSERT_GREATER(0.0, fScale); + CPPUNIT_ASSERT_LESS(100.0, fScale); } save("Impress Office Open XML"); @@ -1843,10 +1843,10 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest2, testTextColumns_3columns) CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(300)), xColProps->getPropertyValue("AutomaticDistance")); // Scale value may be unstable; just test that the text is actually scaled - sal_Int16 nScale; - CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeScale") >>= nScale); - CPPUNIT_ASSERT_GREATER(sal_Int16(0), nScale); - CPPUNIT_ASSERT_LESS(sal_Int16(100), nScale); + double fScale; + CPPUNIT_ASSERT(xProps->getPropertyValue("TextFitToSizeScale") >>= fScale); + CPPUNIT_ASSERT_GREATER(0.0, fScale); + CPPUNIT_ASSERT_LESS(100.0, fScale); } xmlDocUniquePtr pXmlDocRels = parseExport("ppt/slides/slide1.xml"); diff --git a/sd/qa/unit/export-tests-ooxml3.cxx b/sd/qa/unit/export-tests-ooxml3.cxx index ccbfc6e35335..3931c53b912b 100644 --- a/sd/qa/unit/export-tests-ooxml3.cxx +++ b/sd/qa/unit/export-tests-ooxml3.cxx @@ -233,7 +233,7 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testFontScale) // Rounding errors possible, approximate value (+/- 1%) OUString sScale = getXPath( pXmlDocContent, "/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:bodyPr/a:normAutofit", "fontScale"); - CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(76000), sScale.toInt32(), 1000); + CPPUNIT_ASSERT_DOUBLES_EQUAL(sal_Int32(81111), sScale.toInt32(), 1000); } CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testShapeAutofitPPTX) @@ -1914,15 +1914,12 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testAutofittedTextboxIndent) save("Impress Office Open XML"); - // Without the accompanying fix in place, these tests would have failed with: - // - Expected: 691200 - // - Actual : 1080000 - // i.e. paragraph indent wasn't scaled proportionally to autofitted textbox - // font scale on export + // Check that the indent hasn't changed and wasn't scaled when exporting + // (the behaviour changed). xmlDocUniquePtr pXmlDocContent1 = parseExport("ppt/slides/slide1.xml"); assertXPath(pXmlDocContent1, "/p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p[1]/a:pPr", "marL", - "712800"); + "1080000"); } CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, testTdf151622_oleIcon) diff --git a/sd/qa/unit/import-tests-smartart.cxx b/sd/qa/unit/import-tests-smartart.cxx index 895ca7f03211..049a64eb0193 100644 --- a/sd/qa/unit/import-tests-smartart.cxx +++ b/sd/qa/unit/import-tests-smartart.cxx @@ -1528,13 +1528,13 @@ CPPUNIT_TEST_FIXTURE(SdImportTestSmartArt, testAutofitSync) uno::Reference<drawing::XShape> xMiddle = getChildShape(xDiagram, 2); uno::Reference<beans::XPropertySet> xFirstInner(getChildShape(getChildShape(xMiddle, 0), 0), uno::UNO_QUERY); - sal_Int16 nFirstScale = 0; + double nFirstScale = 0; CPPUNIT_ASSERT(xFirstInner->getPropertyValue("TextFitToSizeScale") >>= nFirstScale); - CPPUNIT_ASSERT_GREATER(static_cast<sal_Int16>(0), nFirstScale); - CPPUNIT_ASSERT_LESS(static_cast<sal_Int16>(100), nFirstScale); + CPPUNIT_ASSERT_GREATER(0.0, nFirstScale); + CPPUNIT_ASSERT_LESS(100.0, nFirstScale); uno::Reference<beans::XPropertySet> xSecondInner(getChildShape(getChildShape(xMiddle, 2), 0), uno::UNO_QUERY); - sal_Int16 nSecondScale = 0; + double nSecondScale = 0; CPPUNIT_ASSERT(xSecondInner->getPropertyValue("TextFitToSizeScale") >>= nSecondScale); // Without the accompanying fix in place, this test would have failed with: diff --git a/sd/qa/unit/import-tests2.cxx b/sd/qa/unit/import-tests2.cxx index 9d44f11552d8..e585673e3ad8 100644 --- a/sd/qa/unit/import-tests2.cxx +++ b/sd/qa/unit/import-tests2.cxx @@ -1343,8 +1343,10 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf120028) double fCharHeight = 0; xPropSet->getPropertyValue("CharHeight") >>= fCharHeight; CPPUNIT_ASSERT_DOUBLES_EQUAL(13.5, fCharHeight, 1E-12); - // 13.5 * 90% is approx. 12.1 (the correct scaled font size) - CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int16(90)), xShape->getPropertyValue("TextFitToSizeScale")); + + double fTextSclale = 0.0; + xShape->getPropertyValue("TextFitToSizeScale") >>= fTextSclale; + CPPUNIT_ASSERT_DOUBLES_EQUAL(92.0, fTextSclale, 1E1); } CPPUNIT_TEST_FIXTURE(SdImportTest2, testDescriptionImport) @@ -1845,11 +1847,9 @@ CPPUNIT_TEST_FIXTURE(SdImportTest2, testTdf149961AutofitIndentation) const SvxNumBulletItem* pNumFmt = aEdit.GetParaAttribs(0).GetItem(EE_PARA_NUMBULLET); CPPUNIT_ASSERT(pNumFmt); - // Without the accompanying fix in place, this test would have failed with: - // - Expected: 12700 - // - Actual : 3175 - CPPUNIT_ASSERT_EQUAL(sal_Int32(12700), pNumFmt->GetNumRule().GetLevel(0).GetAbsLSpace()); - CPPUNIT_ASSERT_EQUAL(sal_Int32(-12700), + // Spacing doesn't change when it is scaled + CPPUNIT_ASSERT_EQUAL(sal_Int32(3175), pNumFmt->GetNumRule().GetLevel(0).GetAbsLSpace()); + CPPUNIT_ASSERT_EQUAL(sal_Int32(-3175), pNumFmt->GetNumRule().GetLevel(0).GetFirstLineOffset()); } } diff --git a/sd/source/ui/view/drtxtob.cxx b/sd/source/ui/view/drtxtob.cxx index d8503d0412f7..a7204b992ed8 100644 --- a/sd/source/ui/view/drtxtob.cxx +++ b/sd/source/ui/view/drtxtob.cxx @@ -46,6 +46,7 @@ #include <editeng/writingmodeitem.hxx> #include <editeng/frmdiritem.hxx> #include <editeng/fhgtitem.hxx> +#include <o3tl/temporary.hxx> #include <sfx2/objface.hxx> @@ -165,7 +166,7 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet ) case SID_ATTR_CHAR_STRIKEOUT: case SID_ATTR_CHAR_CASEMAP: { - double stretchX = 100.0; + double stretchY = 100.0; SvxScriptSetItem aSetItem( nSlotId, GetPool() ); aSetItem.GetItemSet().Put( aAttrSet, false ); @@ -183,9 +184,8 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet ) if (OutlineView* pOView = dynamic_cast<OutlineView*>(mpView)) pOLV = pOView->GetViewByWindow(mpViewShell->GetActiveWindow()); - double stretchY = 100.0; - if( pOutliner ) - pOutliner->GetGlobalCharStretching(stretchX, stretchY); + if (pOutliner) + pOutliner->getGlobalScale(o3tl::temporary(double()), stretchY, o3tl::temporary(double()), o3tl::temporary(double())); if(pOLV && !pOLV->GetSelection().HasRange()) { @@ -204,7 +204,7 @@ void TextObjectBar::GetAttrState( SfxItemSet& rSet ) if( nSlotId == SID_ATTR_CHAR_FONTHEIGHT ) { SvxFontHeightItem aFontItem = dynamic_cast<const SvxFontHeightItem&>(*pI); - aFontItem.SetHeight(aFontItem.GetHeight(), stretchX, aFontItem.GetPropUnit()); + aFontItem.SetHeight(aFontItem.GetHeight() * (stretchY / 100.0), 100, aFontItem.GetPropUnit()); aFontItem.SetWhich(nWhich); aAttrSet.Put( aFontItem ); } diff --git a/svx/source/svdraw/svdotext.cxx b/svx/source/svdraw/svdotext.cxx index 20e54ca976ac..65f1dab7db65 100644 --- a/svx/source/svdraw/svdotext.cxx +++ b/svx/source/svdraw/svdotext.cxx @@ -43,6 +43,7 @@ #include <svx/sdtfsitm.hxx> #include <svx/sdtmfitm.hxx> #include <svx/xtextit0.hxx> +#include <svx/compatflags.hxx> #include <sdr/properties/textproperties.hxx> #include <sdr/contact/viewcontactoftextobj.hxx> #include <basegfx/tuple/b2dtuple.hxx> @@ -51,8 +52,11 @@ #include <vcl/virdev.hxx> #include <basegfx/matrix/b2dhommatrixtools.hxx> #include <sal/log.hxx> +#include <o3tl/unit_conversion.hxx> #include <o3tl/temporary.hxx> #include <unotools/configmgr.hxx> +#include <editeng/eeitem.hxx> +#include <editeng/fhgtitem.hxx> using namespace com::sun::star; @@ -908,6 +912,9 @@ void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextS } #endif } + + rOutliner.setRoundFontSizeToPt(false); + unsigned nLoopCount=0; bool bNoMoreLoop = false; tools::Long nXDiff0=0x7FFFFFFF; @@ -982,7 +989,7 @@ void SdrTextObj::ImpSetCharStretching(SdrOutliner& rOutliner, const Size& rTextS nY = nX; bNoMoreLoop = true; } - rOutliner.SetGlobalCharStretching(nX, nY); + rOutliner.setGlobalScale(nX, nY); nLoopCount++; Size aSiz(rOutliner.CalcTextSize()); tools::Long nXDiff = aSiz.Width() - nWantWdt; @@ -1172,7 +1179,8 @@ void SdrTextObj::ImpInitDrawOutliner( SdrOutliner& rOutl ) const nOutlinerMode = OutlinerMode::TextObject; rOutl.Init( nOutlinerMode ); - rOutl.SetGlobalCharStretching(100.0, 100.0); + rOutl.setGlobalScale(100.0, 100.0, 100.0, 100.0); + EEControlBits nStat=rOutl.GetControlWord(); nStat &= ~EEControlBits(EEControlBits::STRETCHING|EEControlBits::AUTOPAGESIZE); rOutl.SetControlWord(nStat); @@ -1230,15 +1238,26 @@ void SdrTextObj::ImpSetupDrawOutlinerForPaint( bool bContourFrame, } } -sal_uInt16 SdrTextObj::GetFontScaleY() const +double SdrTextObj::GetFontScale() const { SdrOutliner& rOutliner = ImpGetDrawOutliner(); // This eventually calls ImpAutoFitText UpdateOutlinerFormatting(rOutliner, o3tl::temporary(tools::Rectangle())); - double nStretchY; - rOutliner.GetGlobalCharStretching(o3tl::temporary(double()), nStretchY); - return nStretchY; + double fScaleY; + rOutliner.getGlobalScale(o3tl::temporary(double()), fScaleY, o3tl::temporary(double()), o3tl::temporary(double())); + return fScaleY; +} + +double SdrTextObj::GetSpacingScale() const +{ + SdrOutliner& rOutliner = ImpGetDrawOutliner(); + // This eventually calls ImpAutoFitText + UpdateOutlinerFormatting(rOutliner, o3tl::temporary(tools::Rectangle())); + + double fSpacingScaleY; + rOutliner.getGlobalScale(o3tl::temporary(double()), o3tl::temporary(double()), o3tl::temporary(double()), fSpacingScaleY); + return fSpacingScaleY; } void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const @@ -1253,6 +1272,12 @@ void SdrTextObj::ImpAutoFitText( SdrOutliner& rOutliner ) const void SdrTextObj::ImpAutoFitText(SdrOutliner& rOutliner, const Size& rTextSize, bool bIsVerticalWriting) const { + if (!bIsVerticalWriting) + { + autoFitTextForCompatibility(rOutliner, rTextSize); + return; + } + // EditEngine formatting is unstable enough for // line-breaking text that we need some more samples @@ -1260,6 +1285,7 @@ void SdrTextObj::ImpAutoFitText(SdrOutliner& rOutliner, const Size& rTextSize, double nMinStretchX = 0.0; double nMinStretchY = 0.0; std::array<sal_Int32, 10> aOldStretchXVals = {0,0,0,0,0,0,0,0,0,0}; + rOutliner.setRoundFontSizeToPt(false); for (size_t i = 0; i < aOldStretchXVals.size(); ++i) { const Size aCurrTextSize = rOutliner.CalcTextSizeNTP(); @@ -1283,7 +1309,7 @@ void SdrTextObj::ImpAutoFitText(SdrOutliner& rOutliner, const Size& rTextSize, fFactor = std::sqrt(fFactor); double nCurrStretchX, nCurrStretchY; - rOutliner.GetGlobalCharStretching(nCurrStretchX, nCurrStretchY); + rOutliner.getGlobalScale(nCurrStretchX, nCurrStretchY, o3tl::temporary(double()), o3tl::temporary(double())); if (fFactor >= 0.98) { @@ -1302,20 +1328,107 @@ void SdrTextObj::ImpAutoFitText(SdrOutliner& rOutliner, const Size& rTextSize, nCurrStretchX = double(basegfx::fround(nCurrStretchX * fFactor * 100.0)) / 100.00; nCurrStretchY = double(basegfx::fround(nCurrStretchY * fFactor * 100.0)) / 100.00; - rOutliner.SetGlobalCharStretching(std::min(100.0, nCurrStretchX), std::min(100.0, nCurrStretchY)); + double nStretchX = std::min(100.0, nCurrStretchX); + double nStretchY = std::min(100.0, nCurrStretchY); + + rOutliner.setGlobalScale(nStretchX, nStretchY, nStretchX, nStretchY); SAL_INFO("svx", "zoom is " << nCurrStretchX); } } const SdrTextFitToSizeTypeItem& rItem = GetObjectItem(SDRATTR_TEXT_FITTOSIZE); - if (rItem.GetMaxScale() > 0) + if (rItem.GetMaxScale() > 0.0) { - nMinStretchX = std::min<sal_uInt16>(rItem.GetMaxScale(), nMinStretchX); - nMinStretchY = std::min<sal_uInt16>(rItem.GetMaxScale(), nMinStretchY); + nMinStretchX = std::min(rItem.GetMaxScale(), nMinStretchX); + nMinStretchY = std::min(rItem.GetMaxScale(), nMinStretchY); } SAL_INFO("svx", "final zoom is " << nMinStretchX); - rOutliner.SetGlobalCharStretching(std::min(100.0, nMinStretchX), std::min(100.0, nMinStretchY)); + + nMinStretchX = std::min(100.0, nMinStretchX); + nMinStretchY = std::min(100.0, nMinStretchY); + + rOutliner.setGlobalScale(nMinStretchX, nMinStretchY, nMinStretchX, nMinStretchY); +} + +void SdrTextObj::autoFitTextForCompatibility(SdrOutliner& rOutliner, const Size& rTextBoxSize) const +{ + rOutliner.setRoundFontSizeToPt(true); + + const SdrTextFitToSizeTypeItem& rItem = GetObjectItem(SDRATTR_TEXT_FITTOSIZE); + double fMaxScale = rItem.GetMaxScale(); + if (fMaxScale > 0.0) + { + rOutliner.setGlobalScale(fMaxScale, fMaxScale, 100.0, 100.0); + } + else + { + fMaxScale = 100.0; + } + + Size aCurrentTextBoxSize = rOutliner.CalcTextSizeNTP(); + tools::Long nExtendTextBoxBy = -50; + aCurrentTextBoxSize.extendBy(0, nExtendTextBoxBy); + double fCurrentFitFactor = double(rTextBoxSize.Height()) / aCurrentTextBoxSize.Height(); + + if (fCurrentFitFactor >= 1.0) + return; + + sal_Int32 nFontHeight = GetObjectItemSet().Get(EE_CHAR_FONTHEIGHT).GetHeight(); + + double fFontHeightPt = o3tl::convert(double(nFontHeight), o3tl::Length::mm100, o3tl::Length::pt); + double fMinY = 0.0; + double fMaxY = fMaxScale; + + double fBestFontScale = 0.0; + double fBestSpacing = fMaxScale; + double fBestFitFactor = fCurrentFitFactor; + + double fInTheMidle = 0.5; + + int iteration = 0; + double fFitFactorTarget = 1.00; + + while (iteration < 10) + { + iteration++; + double fScaleY = fMinY + (fMaxY - fMinY) * fInTheMidle; + + double fScaledFontHeight = fFontHeightPt * (fScaleY / 100.0); + double fRoundedScaledFontHeight = std::floor(fScaledFontHeight * 10.0) / 10.0; + double fCurrentFontScale = (fRoundedScaledFontHeight / fFontHeightPt) * 100.0; + + fCurrentFitFactor = 0.0; // reset fit factor; + + for (double fCurrentSpacing : {100.0, 90.0, 80.0}) + { + if (fCurrentFitFactor >= fFitFactorTarget) + continue; + + rOutliner.setGlobalScale(fCurrentFontScale, fCurrentFontScale, 100.0, fCurrentSpacing); + + aCurrentTextBoxSize = rOutliner.CalcTextSizeNTP(); + aCurrentTextBoxSize.extendBy(0, nExtendTextBoxBy); + fCurrentFitFactor = double(rTextBoxSize.Height()) / aCurrentTextBoxSize.Height(); + + if (fCurrentSpacing == 100.0) + { + if (fCurrentFitFactor > fFitFactorTarget) + fMinY = fCurrentFontScale; + else + fMaxY = fCurrentFontScale; + } + + if ((fBestFitFactor < fFitFactorTarget && fCurrentFitFactor > fBestFitFactor) + || (fCurrentFitFactor >= fFitFactorTarget && fCurrentFitFactor < fBestFitFactor)) + { + fBestFontScale = fCurrentFontScale; + fBestSpacing = fCurrentSpacing; + fBestFitFactor = fCurrentFitFactor; + } + } + } + rOutliner.setGlobalScale(fBestFontScale, fBestFontScale, 100.0, fBestSpacing); } void SdrTextObj::SetupOutlinerFormatting( SdrOutliner& rOutl, tools::Rectangle& rPaintRect ) const diff --git a/svx/source/svdraw/svdotextdecomposition.cxx b/svx/source/svdraw/svdotextdecomposition.cxx index ad6edb104e01..ddbc6bfe540a 100644 --- a/svx/source/svdraw/svdotextdecomposition.cxx +++ b/svx/source/svdraw/svdotextdecomposition.cxx @@ -1226,7 +1226,7 @@ void SdrTextObj::impDecomposeStretchTextPrimitive( // to layout without mirroring const double fScaleX(fabs(aScale.getX()) / aOutlinerScale.getX()); const double fScaleY(fabs(aScale.getY()) / aOutlinerScale.getY()); - rOutliner.SetGlobalCharStretching(fScaleX * 100.0, fScaleY * 100.0); + rOutliner.setGlobalScale(fScaleX * 100.0, fScaleY * 100.0, 100.0, 100.0); // When mirroring in X and Y, // move the null point which was top left to bottom right. diff --git a/svx/source/svdraw/svdoutl.cxx b/svx/source/svdraw/svdoutl.cxx index 5e89f5d42874..94f73bfbf206 100644 --- a/svx/source/svdraw/svdoutl.cxx +++ b/svx/source/svdraw/svdoutl.cxx @@ -50,7 +50,7 @@ void SdrOutliner::SetTextObj( const SdrTextObj* pObj ) nOutlinerMode2 = OutlinerMode::TextObject; Init( nOutlinerMode2 ); - SetGlobalCharStretching(); + setGlobalScale(100.0, 100.0, 100.0, 100.0); EEControlBits nStat = GetControlWord(); nStat &= ~EEControlBits( EEControlBits::STRETCHING | EEControlBits::AUTOPAGESIZE ); diff --git a/svx/source/unodraw/unoshape.cxx b/svx/source/unodraw/unoshape.cxx index 4ee178c5e58a..85cd6045a234 100644 --- a/svx/source/unodraw/unoshape.cxx +++ b/svx/source/unodraw/unoshape.cxx @@ -173,7 +173,7 @@ protected: }; /// Calculates what scaling factor will be used for autofit text scaling of this shape. -sal_Int16 GetTextFitToSizeScale(SdrObject* pObject) +double GetTextFitToSizeScale(SdrObject* pObject) { SdrTextObj* pTextObj = DynCastSdrTextObj(pObject); if (!pTextObj) @@ -188,7 +188,7 @@ sal_Int16 GetTextFitToSizeScale(SdrObject* pObject) return 0; } - return pTextObj->GetFontScaleY(); + return pTextObj->GetFontScale(); } } @@ -2361,7 +2361,7 @@ bool SvxShape::setPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn case OWN_ATTR_TEXTFITTOSIZESCALE: { - sal_Int16 nMaxScale = 0; + double nMaxScale = 0.0; if (rValue >>= nMaxScale) { SdrTextFitToSizeTypeItem aItem(pSdrObject->GetMergedItem(SDRATTR_TEXT_FITTOSIZE)); @@ -2871,7 +2871,8 @@ bool SvxShape::getPropertyValueImpl( const OUString&, const SfxItemPropertyMapEn case OWN_ATTR_TEXTFITTOSIZESCALE: { - rValue <<= GetTextFitToSizeScale(GetSdrObject()); + double nScale = GetTextFitToSizeScale(GetSdrObject()); + rValue <<= nScale; break; } |