diff options
author | Szymon Kłos <szymon.klos@collabora.com> | 2018-08-07 10:44:21 +0200 |
---|---|---|
committer | Andras Timar <andras.timar@collabora.com> | 2018-08-20 10:14:41 +0200 |
commit | 40b396ef207213ebd07981206674a2260256cb3c (patch) | |
tree | aed1e5334a28cfa67dbe709fd4ac4ad8edb2f358 | |
parent | 406280c62843e9ed167e7adaa005fba92a39608f (diff) |
tdf#116350 Correctly display text on arc
Change-Id: Ice8c141db20d43ccc8d6e2b56004a4a28d2b257a
Reviewed-on: https://gerrit.libreoffice.org/58729
Tested-by: Jenkins
Reviewed-by: Szymon Kłos <szymon.klos@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/58840
Reviewed-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r-- | oox/source/drawingml/shape.cxx | 11 | ||||
-rw-r--r-- | sd/qa/unit/export-tests-ooxml2.cxx | 42 | ||||
-rw-r--r-- | svx/source/customshapes/EnhancedCustomShapeFontWork.cxx | 148 |
3 files changed, 167 insertions, 34 deletions
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx index f13fa4a2f56f..5483dcc06ff1 100644 --- a/oox/source/drawingml/shape.cxx +++ b/oox/source/drawingml/shape.cxx @@ -547,13 +547,22 @@ static inline void lcl_createPresetShape( uno::Reference<drawing::XShape>& xShap lcl_resetPropertyValue( aGeomPropVec, sEquations ); lcl_resetPropertyValue( aGeomPropVec, sPath ); + // Some shapes don't need scaling + bool bScale = true; + if ( rPresetType == "textRingInside" + || rPresetType == "textRingOutside" + || rPresetType == "textCirclePour" ) + { + bScale = false; + } + // Apply geometry properties uno::Sequence<beans::PropertyValue> aPropertyValues( comphelper::InitPropertySequence( { { sTextPath, uno::makeAny( true ) }, { "TextPathMode", uno::Any( drawing::EnhancedCustomShapeTextPathMode_PATH ) }, - { "ScaleX", uno::Any( false ) } } ) ); + { "ScaleX", uno::Any( bScale ) } } ) ); lcl_setPropertyValue( aGeomPropVec, sTextPath, comphelper::makePropertyValue( sTextPath, aPropertyValues ) ); diff --git a/sd/qa/unit/export-tests-ooxml2.cxx b/sd/qa/unit/export-tests-ooxml2.cxx index 1f246fec7a90..80cd202c533c 100644 --- a/sd/qa/unit/export-tests-ooxml2.cxx +++ b/sd/qa/unit/export-tests-ooxml2.cxx @@ -1717,6 +1717,39 @@ static inline double getAdjustmentValue( uno::Reference<beans::XPropertySet>& xS return -1.0; } +static inline bool getScaleXValue(uno::Reference<beans::XPropertySet>& xSet) +{ + bool bScaleX = false; + + auto aGeomPropSeq = xSet->getPropertyValue("CustomShapeGeometry") + .get<uno::Sequence<beans::PropertyValue>>(); + auto aGeomPropVec + = comphelper::sequenceToContainer<std::vector<beans::PropertyValue>>( + aGeomPropSeq); + + const OUString sName = "TextPath"; + auto aIterator = std::find_if( + aGeomPropVec.begin(), aGeomPropVec.end(), + [sName](const beans::PropertyValue& rValue) { return rValue.Name == sName; }); + + if (aIterator != aGeomPropVec.end()) + { + uno::Sequence<beans::PropertyValue> aTextPathProperties; + aIterator->Value >>= aTextPathProperties; + const OUString sScaleX = "ScaleX"; + auto aIterator2 = std::find_if( + aTextPathProperties.begin(), aTextPathProperties.end(), + [sScaleX](const beans::PropertyValue& rValue) { return rValue.Name == sScaleX; }); + + if (aIterator2 != aTextPathProperties.end()) + { + aIterator2->Value >>= bScaleX; + } + } + + return bScaleX; +} + void SdOOXMLExportTest2::testTdf116350TextEffects() { ::sd::DrawDocShellRef xDocShRef = loadURL( m_directories.getURLFromSrc( "sd/qa/unit/data/pptx/tdf116350-texteffects.pptx" ), PPTX ); @@ -1726,16 +1759,25 @@ void SdOOXMLExportTest2::testTdf116350TextEffects() double fAdjust = getAdjustmentValue( xShape0 ); CPPUNIT_ASSERT_EQUAL( 180.0, fAdjust ); + bool bScaleX = getScaleXValue( xShape0 ); + CPPUNIT_ASSERT_EQUAL( true, bScaleX ); + // Default angle for ArchDown uno::Reference<beans::XPropertySet> xShape14( getShapeFromPage( 14, 0, xDocShRef ) ); fAdjust = getAdjustmentValue( xShape14 ); CPPUNIT_ASSERT_EQUAL( 0.0, fAdjust ); + bScaleX = getScaleXValue( xShape14 ); + CPPUNIT_ASSERT_EQUAL( true, bScaleX ); + // Angle directly set uno::Reference<beans::XPropertySet> xShape1( getShapeFromPage( 1, 0, xDocShRef ) ); fAdjust = getAdjustmentValue( xShape1 ); CPPUNIT_ASSERT_EQUAL( 213.25, fAdjust ); + bScaleX = getScaleXValue( xShape1 ); + CPPUNIT_ASSERT_EQUAL( true, bScaleX ); + // Export utl::TempFile tempFile; xDocShRef = saveAndReload( xDocShRef.get(), PPTX, &tempFile ); diff --git a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx index 9bfed5d53ab4..0419038f0fda 100644 --- a/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx +++ b/svx/source/customshapes/EnhancedCustomShapeFontWork.cxx @@ -33,6 +33,7 @@ #include <editeng/fontitem.hxx> #include <editeng/postitem.hxx> #include <editeng/wghtitem.hxx> +#include <editeng/fhgtitem.hxx> #include <editeng/charscaleitem.hxx> #include <svx/EnhancedCustomShapeTypeNames.hxx> #include <svx/svdorect.hxx> @@ -79,9 +80,11 @@ struct FWData // representing the whole text { std::vector< FWTextArea > vTextAreas; double fHorizontalTextScaling; + double fVerticalTextScaling; sal_uInt32 nMaxParagraphsPerTextArea; sal_Int32 nSingleLineHeight; bool bSingleLineMode; + bool bScaleX; }; @@ -98,6 +101,13 @@ static bool InitializeFontWorkData( else nTextAreaCount >>= 1; + const SdrCustomShapeGeometryItem& rGeometryItem( rSdrObjCustomShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY ) ); + const css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "TextPath", "ScaleX" ); + if (pAny) + *pAny >>= rFWData.bScaleX; + else + rFWData.bScaleX = false; + if ( nTextAreaCount ) { rFWData.bSingleLineMode = bSingleLineMode; @@ -157,18 +167,31 @@ void CalculateHorizontalScalingFactor( { double fScalingFactor = 1.0; bool bScalingFactorDefined = false; + rFWData.fVerticalTextScaling = 1.0; sal_uInt16 i = 0; bool bSingleLineMode = false; sal_uInt16 nOutlinesCount2d = rOutline2d.Count(); vcl::Font aFont; - const SvxFontItem& rFontItem(rSdrObjCustomShape.GetMergedItem( EE_CHAR_FONTINFO )); - aFont.SetFontHeight(rSdrObjCustomShape.GetLogicRect().GetHeight() / rFWData.nMaxParagraphsPerTextArea); + const SvxFontItem& rFontItem( rSdrObjCustomShape.GetMergedItem( EE_CHAR_FONTINFO ) ); + const SvxFontHeightItem& rFontHeight( rSdrObjCustomShape.GetMergedItem( EE_CHAR_FONTHEIGHT ) ); + sal_Int32 nFontSize = rFontHeight.GetHeight(); + + if (rFWData.bScaleX) + aFont.SetFontHeight( nFontSize ); + else + aFont.SetFontHeight( rSdrObjCustomShape.GetLogicRect().GetHeight() / rFWData.nMaxParagraphsPerTextArea ); + aFont.SetAlignment( ALIGN_TOP ); aFont.SetFamilyName( rFontItem.GetFamilyName() ); aFont.SetFamily( rFontItem.GetFamily() ); aFont.SetStyleName( rFontItem.GetStyleName() ); + const SvxPostureItem& rPostureItem = rSdrObjCustomShape.GetMergedItem( EE_CHAR_ITALIC ); + aFont.SetItalic( rPostureItem.GetPosture() ); + + const SvxWeightItem& rWeightItem = rSdrObjCustomShape.GetMergedItem( EE_CHAR_WEIGHT ); + aFont.SetWeight( rWeightItem.GetWeight() ); aFont.SetOrientation( 0 ); // initializing virtual device @@ -179,40 +202,55 @@ void CalculateHorizontalScalingFactor( if ( nOutlinesCount2d & 1 ) bSingleLineMode = true; - std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin(); - std::vector< FWTextArea >::const_iterator aTextAreaIEnd = rFWData.vTextAreas.end(); - while( aTextAreaIter != aTextAreaIEnd ) + do { - // calculating the width of the corresponding 2d text area - double fWidth = GetLength( rOutline2d.GetObject( i++ ) ); - if ( !bSingleLineMode ) - { - fWidth += GetLength( rOutline2d.GetObject( i++ ) ); - fWidth /= 2.0; - } - std::vector< FWParagraphData >::const_iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() ); - std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() ); - while( aParagraphIter != aParagraphIEnd ) + i = 0; + std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin(); + std::vector< FWTextArea >::const_iterator aTextAreaIEnd = rFWData.vTextAreas.end(); + while( aTextAreaIter != aTextAreaIEnd ) { - double fTextWidth = pVirDev->GetTextWidth( aParagraphIter->aString ); - if ( fTextWidth > 0.0 ) + // calculating the width of the corresponding 2d text area + double fWidth = GetLength( rOutline2d.GetObject( i++ ) ); + if ( !bSingleLineMode ) { - double fScale = fWidth / fTextWidth; - if ( !bScalingFactorDefined ) - { - fScalingFactor = fScale; - bScalingFactorDefined = true; - } - else + fWidth += GetLength( rOutline2d.GetObject( i++ ) ); + fWidth /= 2.0; + } + + std::vector< FWParagraphData >::const_iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() ); + std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() ); + while( aParagraphIter != aParagraphIEnd ) + { + double fTextWidth = pVirDev->GetTextWidth( aParagraphIter->aString ); + if ( fTextWidth > 0.0 ) { - if ( fScale < fScalingFactor ) + double fScale = fWidth / fTextWidth; + if ( !bScalingFactorDefined ) + { fScalingFactor = fScale; + bScalingFactorDefined = true; + } + else if ( fScale < fScalingFactor || ( rFWData.bScaleX && fScalingFactor < 1.0 ) ) + { + fScalingFactor = fScale; + } } + ++aParagraphIter; } - ++aParagraphIter; + ++aTextAreaIter; + } + + if (fScalingFactor < 1.0) + { + nFontSize--; + aFont.SetFontHeight( nFontSize ); + pVirDev->SetFont( aFont ); } - ++aTextAreaIter; } + while (rFWData.bScaleX && fScalingFactor < 1.0 && nFontSize > 1 ); + + if (nFontSize > 1) + rFWData.fVerticalTextScaling = static_cast<double>(nFontSize) / rFontHeight.GetHeight(); rFWData.fHorizontalTextScaling = fScalingFactor; } @@ -255,7 +293,9 @@ void GetTextAreaOutline( nFntItm = EE_CHAR_FONTINFO_CJK; const SvxFontItem& rFontItem = static_cast<const SvxFontItem&>(rSdrObjCustomShape.GetMergedItem( nFntItm )); vcl::Font aFont; + aFont.SetFontHeight( rFWData.nSingleLineHeight ); + aFont.SetAlignment( ALIGN_TOP ); aFont.SetFamilyName( rFontItem.GetFamilyName() ); @@ -433,18 +473,22 @@ bool GetFontWorkOutline( std::vector< FWTextArea >::iterator aTextAreaIter = rFWData.vTextAreas.begin(); std::vector< FWTextArea >::const_iterator aTextAreaIEnd = rFWData.vTextAreas.end(); - rFWData.nSingleLineHeight = static_cast<sal_Int32>( ( static_cast<double>(rSdrObjCustomShape.GetLogicRect().GetHeight()) - / rFWData.nMaxParagraphsPerTextArea ) * rFWData.fHorizontalTextScaling ); - - if (rFWData.nSingleLineHeight == SAL_MIN_INT32) - return false; - bool bSameLetterHeights = false; const SdrCustomShapeGeometryItem& rGeometryItem(rSdrObjCustomShape.GetMergedItem( SDRATTR_CUSTOMSHAPE_GEOMETRY )); const css::uno::Any* pAny = rGeometryItem.GetPropertyValueByName( "TextPath", "SameLetterHeights" ); if ( pAny ) *pAny >>= bSameLetterHeights; + const SvxFontHeightItem& rFontHeight( rSdrObjCustomShape.GetMergedItem( EE_CHAR_FONTHEIGHT ) ); + if (rFWData.bScaleX) + rFWData.nSingleLineHeight = rFWData.fVerticalTextScaling * rFontHeight.GetHeight(); + else + rFWData.nSingleLineHeight = static_cast<sal_Int32>( ( static_cast<double>( rSdrObjCustomShape.GetLogicRect().GetHeight() ) + / rFWData.nMaxParagraphsPerTextArea ) * rFWData.fHorizontalTextScaling ); + + if (rFWData.nSingleLineHeight == SAL_MIN_INT32) + return false; + while ( aTextAreaIter != aTextAreaIEnd ) { GetTextAreaOutline( @@ -484,6 +528,38 @@ bool GetFontWorkOutline( ++aParagraphIter; } } + else if (rFWData.bScaleX) + { + std::vector< FWParagraphData >::iterator aParagraphIter( aTextAreaIter->vParagraphs.begin() ); + std::vector< FWParagraphData >::const_iterator aParagraphIEnd( aTextAreaIter->vParagraphs.end() ); + while ( aParagraphIter != aParagraphIEnd ) + { + sal_Int32 nHorzDiff = 0; + if ( eHorzAdjust == SDRTEXTHORZADJUST_CENTER ) + nHorzDiff = ( rFWData.fHorizontalTextScaling * aTextAreaIter->aBoundRect.GetWidth() - aParagraphIter->aBoundRect.GetWidth() ) / 2; + else if ( eHorzAdjust == SDRTEXTHORZADJUST_RIGHT ) + nHorzDiff = ( rFWData.fHorizontalTextScaling * aTextAreaIter->aBoundRect.GetWidth() - aParagraphIter->aBoundRect.GetWidth() ); + + if (nHorzDiff) + { + std::vector< FWCharacterData >::iterator aCharacterIter( aParagraphIter->vCharacters.begin() ); + std::vector< FWCharacterData >::const_iterator aCharacterIEnd( aParagraphIter->vCharacters.end() ); + while ( aCharacterIter != aCharacterIEnd ) + { + std::vector< tools::PolyPolygon >::iterator aOutlineIter = aCharacterIter->vOutlines.begin(); + std::vector< tools::PolyPolygon >::const_iterator aOutlineIEnd = aCharacterIter->vOutlines.end(); + while( aOutlineIter != aOutlineIEnd ) + { + aOutlineIter->Move( nHorzDiff, 0 ); + ++aOutlineIter; + } + ++aCharacterIter; + } + } + + ++aParagraphIter; + } + } else { switch( eHorzAdjust ) @@ -670,6 +746,12 @@ void FitTextOutlinesToShapeOutlines( const tools::PolyPolygon& aOutlines2d, FWDa sal_Int32 nTop = rTextAreaBoundRect.Top(); sal_Int32 nWidth = rTextAreaBoundRect.GetWidth(); sal_Int32 nHeight= rTextAreaBoundRect.GetHeight(); + + if (rFWData.bScaleX) + { + nWidth *= rFWData.fHorizontalTextScaling; + } + if ( rFWData.bSingleLineMode && nHeight && nWidth ) { if ( nOutline2dIdx >= aOutlines2d.Count() ) |