From 005f5db47b8e1bbd7ebddee92009be072e835fd5 Mon Sep 17 00:00:00 2001 From: Regina Henschel Date: Sat, 4 Jul 2020 15:11:03 +0200 Subject: [PATCH] tdf#100348 add fill to fontwork in export to pptx This patch adds fill to the characters in a Fontwork shape in export to pptx. It does not contain export to docx and not import. Change-Id: Ie7c8a35380a845f513516636c4f60ee307eacd50 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/98187 Tested-by: Jenkins Reviewed-by: Thorsten Behrens --- include/oox/export/drawingml.hxx | 13 +- include/oox/export/shapes.hxx | 1 - .../drawingml/customshapeproperties.cxx | 3 + oox/source/export/drawingml.cxx | 188 +++++++++++++----- oox/source/export/shapes.cxx | 53 ++--- .../data/odp/tdf100348_FontworkBitmapFill.odp | Bin 0 -> 17886 bytes .../odp/tdf100348_FontworkGradientGlow.odp | Bin 0 -> 20381 bytes sd/qa/unit/export-tests-ooxml1.cxx | 37 ++++ 8 files changed, 198 insertions(+), 97 deletions(-) create mode 100644 sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp create mode 100644 sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx index 439d817d0449..2760d2fe64a0 100644 --- a/include/oox/export/drawingml.hxx +++ b/include/oox/export/drawingml.hxx @@ -143,6 +143,7 @@ private: /// Parent exporter, used for text callback. DMLTextExport* mpTextExport; + protected: css::uno::Any mAny; ::sax_fastparser::FSHelperPtr mpFS; @@ -166,6 +167,7 @@ protected: const char* GetRelationCompPrefix() const; static bool EqualGradients( css::awt::Gradient aGradient1, css::awt::Gradient aGradient2 ); + bool IsFontworkShape(const css::uno::Reference< css::beans::XPropertySet >& rXShapePropSet); void WriteGlowEffect(const css::uno::Reference& rXPropSet); void WriteSoftEdgeEffect(const css::uno::Reference& rXPropSet); @@ -244,17 +246,20 @@ public: void WriteTransformation(const tools::Rectangle& rRectangle, sal_Int32 nXmlNamespace, bool bFlipH = false, bool bFlipV = false, sal_Int32 nRotation = 0, bool bIsGroupShape = false); - void WriteText( const css::uno::Reference< css::uno::XInterface >& rXIface, const OUString& presetWarp, bool bBodyPr, bool bText = true, sal_Int32 nXmlNamespace = 0); + void WriteText( const css::uno::Reference< css::uno::XInterface >& rXIface, bool bBodyPr, bool bText = true, sal_Int32 nXmlNamespace = 0); void WriteParagraph( const css::uno::Reference< css::text::XTextContent >& rParagraph, - bool& rbOverridingCharHeight, sal_Int32& rnCharHeight ); + bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, const css::uno::Reference< css::beans::XPropertySet >& rXShapePropSet); void WriteParagraphProperties(const css::uno::Reference< css::text::XTextContent >& rParagraph, float fFirstCharHeight); void WriteParagraphNumbering(const css::uno::Reference< css::beans::XPropertySet >& rXPropSet, float fFirstCharHeight, sal_Int16 nLevel ); void WriteParagraphTabStops(const css::uno::Reference& rXPropSet); void WriteRun( const css::uno::Reference< css::text::XTextRange >& rRun, - bool& rbOverridingCharHeight, sal_Int32& rnCharHeight ); + bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, + const css::uno::Reference< css::beans::XPropertySet >& rXShapePropSet); void WriteRunProperties( const css::uno::Reference< css::beans::XPropertySet >& rRun, bool bIsField, sal_Int32 nElement, bool bCheckDirect, - bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, sal_Int16 nScriptType = css::i18n::ScriptType::LATIN); + bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, + sal_Int16 nScriptType = css::i18n::ScriptType::LATIN, + const css::uno::Reference< css::beans::XPropertySet >& rXShapePropSet = {}); void WritePresetShape( const char* pShape , std::vector< std::pair> & rAvList ); void WritePresetShape( const char* pShape ); diff --git a/include/oox/export/shapes.hxx b/include/oox/export/shapes.hxx index 53d505f168a2..e95af1eff83e 100644 --- a/include/oox/export/shapes.hxx +++ b/include/oox/export/shapes.hxx @@ -102,7 +102,6 @@ private: ShapeHashMap maShapeMap; ShapeHashMap* mpShapeMap; - OUString m_presetWarp; public: diff --git a/oox/source/drawingml/customshapeproperties.cxx b/oox/source/drawingml/customshapeproperties.cxx index 00ecf33368ae..1b4d6b4a59f6 100644 --- a/oox/source/drawingml/customshapeproperties.cxx +++ b/oox/source/drawingml/customshapeproperties.cxx @@ -157,6 +157,9 @@ void CustomShapeProperties::pushToPropSet( uno::Any aGeoPropSet = xPropSet->getPropertyValue( sCustomShapeGeometry ); uno::Sequence< beans::PropertyValue > aGeoPropSeq; + // ToDo: Using sAdjustmentValues in this "if" looks nonsense. + // It was introduced in revision acd2c909, which introduced the property "PresetTextWarp" + // for interoperability with Word. if (aGeoPropSet >>= aGeoPropSeq) { for ( const auto& rGeoProp : std::as_const(aGeoPropSeq) ) diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx index 052ea8f93090..847bee54ab97 100644 --- a/oox/source/export/drawingml.cxx +++ b/oox/source/export/drawingml.cxx @@ -115,6 +115,7 @@ #include #include #include +#include using namespace ::css; using namespace ::css::beans; @@ -1694,8 +1695,9 @@ void DrawingML::WriteShapeTransformation( const Reference< XShape >& rXShape, sa bFlipHWrite, bFlipVWrite, ExportRotateClockwisify(nRotation), IsGroupShape( rXShape )); } -void DrawingML::WriteRunProperties( const Reference< XPropertySet >& rRun, bool bIsField, sal_Int32 nElement, bool bCheckDirect, - bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, sal_Int16 nScriptType ) +void DrawingML::WriteRunProperties( const Reference< XPropertySet >& rRun, bool bIsField, sal_Int32 nElement, + bool bCheckDirect,bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, + sal_Int16 nScriptType, const Reference< XPropertySet >& rXShapePropSet) { Reference< XPropertySet > rXPropSet = rRun; Reference< XPropertyState > rXPropState( rRun, UNO_QUERY ); @@ -1899,31 +1901,42 @@ void DrawingML::WriteRunProperties( const Reference< XPropertySet >& rRun, bool XML_baseline, sax_fastparser::UseIf(OString::number(nCharEscapement*1000), nCharEscapement != 0), XML_cap, cap ); - // mso doesn't like text color to be placed after typeface - if ((bCheckDirect && GetPropertyAndState(rXPropSet, rXPropState, "CharColor", eState) - && eState == beans::PropertyState_DIRECT_VALUE) - || GetProperty(rXPropSet, "CharColor")) + // Fontwork-shapes in LO have text outline and fill from shape stroke and shape fill + // PowerPoint has this as run properties + if (IsFontworkShape(rXShapePropSet)) { - ::Color color( *o3tl::doAccess(mAny) ); - SAL_INFO("oox.shape", "run color: " << sal_uInt32(color) << " auto: " << sal_uInt32(COL_AUTO)); - - // WriteSolidFill() handles MAX_PERCENT as "no transparency". - sal_Int32 nTransparency = MAX_PERCENT; - if (rXPropSet->getPropertySetInfo()->hasPropertyByName("CharTransparence")) + WriteOutline(rXShapePropSet); + WriteBlipOrNormalFill(rXShapePropSet, "Graphic"); + WriteShapeEffects(rXShapePropSet); + } + else + { + // mso doesn't like text color to be placed after typeface + if ((bCheckDirect && GetPropertyAndState(rXPropSet, rXPropState, "CharColor", eState) + && eState == beans::PropertyState_DIRECT_VALUE) + || GetProperty(rXPropSet, "CharColor")) { - rXPropSet->getPropertyValue("CharTransparence") >>= nTransparency; - // UNO scale is 0..100, OOXML scale is 0..100000; also UNO tracks transparency, OOXML - // tracks opacity. - nTransparency = MAX_PERCENT - (nTransparency * PER_PERCENT); - } + ::Color color( *o3tl::doAccess(mAny) ); + SAL_INFO("oox.shape", "run color: " << sal_uInt32(color) << " auto: " << sal_uInt32(COL_AUTO)); - // tdf#104219 In LibreOffice and MS Office, there are two types of colors: - // Automatic and Fixed. OOXML is setting automatic color, by not providing color. - if( color != COL_AUTO ) - { - color.SetTransparency(0); - // TODO: special handle embossed/engraved - WriteSolidFill(color, nTransparency); + // WriteSolidFill() handles MAX_PERCENT as "no transparency". + sal_Int32 nTransparency = MAX_PERCENT; + if (rXPropSet->getPropertySetInfo()->hasPropertyByName("CharTransparence")) + { + rXPropSet->getPropertyValue("CharTransparence") >>= nTransparency; + // UNO scale is 0..100, OOXML scale is 0..100000; also UNO tracks transparency, OOXML + // tracks opacity. + nTransparency = MAX_PERCENT - (nTransparency * PER_PERCENT); + } + + // tdf#104219 In LibreOffice and MS Office, there are two types of colors: + // Automatic and Fixed. OOXML is setting automatic color, by not providing color. + if( color != COL_AUTO ) + { + color.SetTransparency(0); + // TODO: special handle embossed/engraved + WriteSolidFill(color, nTransparency); + } } } @@ -2136,7 +2149,8 @@ OUString DrawingML::GetFieldValue( const css::uno::Reference< css::text::XTextRa } void DrawingML::WriteRun( const Reference< XTextRange >& rRun, - bool& rbOverridingCharHeight, sal_Int32& rnCharHeight) + bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, + const css::uno::Reference< css::beans::XPropertySet >& rXShapePropSet) { Reference< XPropertySet > rXPropSet( rRun, UNO_QUERY ); sal_Int16 nLevel = -1; @@ -2197,7 +2211,7 @@ void DrawingML::WriteRun( const Reference< XTextRange >& rRun, Reference< XPropertySet > xPropSet( rRun, uno::UNO_QUERY ); - WriteRunProperties( xPropSet, bIsURLField, XML_rPr, true, rbOverridingCharHeight, rnCharHeight, GetScriptType(sText) ); + WriteRunProperties( xPropSet, bIsURLField, XML_rPr, true, rbOverridingCharHeight, rnCharHeight, GetScriptType(sText), rXShapePropSet); mpFS->startElementNS(XML_a, XML_t); mpFS->writeEscaped( sText ); mpFS->endElementNS( XML_a, XML_t ); @@ -2669,7 +2683,8 @@ void DrawingML::WriteParagraphProperties( const Reference< XTextContent >& rPara } void DrawingML::WriteParagraph( const Reference< XTextContent >& rParagraph, - bool& rbOverridingCharHeight, sal_Int32& rnCharHeight ) + bool& rbOverridingCharHeight, sal_Int32& rnCharHeight, + const css::uno::Reference< css::beans::XPropertySet >& rXShapePropSet) { Reference< XEnumerationAccess > access( rParagraph, UNO_QUERY ); if( !access.is() ) @@ -2699,26 +2714,60 @@ void DrawingML::WriteParagraph( const Reference< XTextContent >& rParagraph, WriteParagraphProperties( rParagraph, fFirstCharHeight ); bPropertiesWritten = true; } - WriteRun( run, rbOverridingCharHeight, rnCharHeight ); + WriteRun( run, rbOverridingCharHeight, rnCharHeight, rXShapePropSet); } } Reference< XPropertySet > rXPropSet( rParagraph, UNO_QUERY ); - WriteRunProperties( rXPropSet, false, XML_endParaRPr, false, rbOverridingCharHeight, rnCharHeight ); + sal_Int16 nDummy = -1; + WriteRunProperties(rXPropSet, false, XML_endParaRPr, false, rbOverridingCharHeight, + rnCharHeight, nDummy, rXShapePropSet); mpFS->endElementNS( XML_a, XML_p ); } -void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUString& presetWarp, bool bBodyPr, bool bText, sal_Int32 nXmlNamespace ) +bool DrawingML::IsFontworkShape(const css::uno::Reference& rXShapePropSet) { - Reference< XText > xXText( rXIface, UNO_QUERY ); - Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY ); + bool bResult(false); + if (rXShapePropSet.is()) + { + Sequence aCustomShapeGeometryProps; + if (GetProperty(rXShapePropSet, "CustomShapeGeometry")) + { + mAny >>= aCustomShapeGeometryProps; + uno::Sequence aTextPathSeq; + for (const auto& rProp : std::as_const(aCustomShapeGeometryProps)) + { + if (rProp.Name == "TextPath") + { + rProp.Value >>= aTextPathSeq; + for (const auto& rTextPathItem : std::as_const(aTextPathSeq)) + { + if (rTextPathItem.Name == "TextPath") + { + rTextPathItem.Value >>= bResult; + break; + } + } + break; + } + } + } + } + return bResult; +} +void DrawingML::WriteText(const Reference& rXIface, bool bBodyPr, bool bText, + sal_Int32 nXmlNamespace) +{ + // ToDo: Fontwork in DOCX + Reference< XText > xXText( rXIface, UNO_QUERY ); if( !xXText.is() ) return; + Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY ); + sal_Int32 nTextPreRotateAngle = 0; double nTextRotateAngle = 0; - bool bIsFontworkShape(presetWarp.startsWith("text") && (presetWarp != "textNoShape")); #define DEFLRINS 254 #define DEFTBINS 127 @@ -2757,9 +2806,13 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin } } + bool bIsFontworkShape(IsFontworkShape(rXPropSet)); Sequence aAdjustmentSeq; uno::Sequence aTextPathSeq; bool bScaleX(false); + OUString sShapeType("non-primitive"); + // ToDo move to InteropGrabBag + OUString sMSWordPresetTextWarp; if (GetProperty(rXPropSet, "CustomShapeGeometry")) { @@ -2780,29 +2833,35 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin sWritingMode = "vert270"; bVertical = true; } - if (!bIsFontworkShape) - break; } else if (rProp.Name == "AdjustmentValues") rProp.Value >>= aAdjustmentSeq; else if( rProp.Name == "TextRotateAngle" ) rProp.Value >>= nTextRotateAngle; + else if (rProp.Name == "Type") + rProp.Value >>= sShapeType; else if (rProp.Name == "TextPath") { rProp.Value >>= aTextPathSeq; - for (const auto& rTextPath : std::as_const(aTextPathSeq)) + for (const auto& rTextPathItem : std::as_const(aTextPathSeq)) { - if (rTextPath.Name == "ScaleX") - rTextPath.Value >>= bScaleX; + if (rTextPathItem.Name == "ScaleX") + rTextPathItem.Value >>= bScaleX; } } + else if (rProp.Name == "PresetTextWarp") + rProp.Value >>= sMSWordPresetTextWarp; } } } + OUString sPresetWarp(PresetGeometryTypeNames::GetMsoName(sShapeType)); + // ODF may have user defined TextPath, use "textPlain" as ersatz. + if (sPresetWarp.isEmpty()) + sPresetWarp = bIsFontworkShape ? OUStringLiteral("textPlain") : OUStringLiteral("textNoShape"); bool bFromWordArt = !bScaleX - && ( presetWarp == "textArchDown" || presetWarp == "textArchUp" - || presetWarp == "textButton" || presetWarp == "textCircle"); + && ( sPresetWarp == "textArchDown" || sPresetWarp == "textArchUp" + || sPresetWarp == "textButton" || sPresetWarp == "textCircle"); TextHorizontalAdjust eHorizontalAlignment( TextHorizontalAdjust_CENTER ); bool bHorizontalCenter = false; @@ -2824,7 +2883,7 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin if (bBodyPr) { - const char* pWrap = bHasWrap && !bWrap ? "none" : nullptr; + const char* pWrap = (bHasWrap && !bWrap) || bIsFontworkShape ? "none" : nullptr; if (GetDocumentType() == DOCUMENT_DOCX) { // In case of DOCX, if we want to have the same effect as @@ -2849,11 +2908,16 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin { if (aAdjustmentSeq.hasElements()) { - mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp); + mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, sPresetWarp); mpFS->startElementNS(XML_a, XML_avLst); + bool bHasTwoHandles( + sPresetWarp == "textArchDownPour" || sPresetWarp == "textArchUpPour" + || sPresetWarp == "textButtonPour" || sPresetWarp == "textCirclePour" + || sPresetWarp == "textDoubleWave1" || sPresetWarp == "textWave1" + || sPresetWarp == "textWave2" || sPresetWarp == "textWave4"); for (sal_Int32 i = 0, nElems = aAdjustmentSeq.getLength(); i < nElems; ++i ) { - OString sName = "adj" + (( nElems > 1 ) ? OString::number(i + 1) : OString()); + OString sName = "adj" + (bHasTwoHandles ? OString::number(i + 1) : OString()); double fValue(0.0); if (aAdjustmentSeq[i].Value.getValueTypeClass() == TypeClass_DOUBLE) aAdjustmentSeq[i].Value >>= fValue; @@ -2866,20 +2930,27 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin // Convert from binary coordinate system with viewBox "0 0 21600 21600" and simple degree // to DrawingML with coordinate range 0..100000 and angle in 1/60000 degree. // Reverse to conversion in lcl_createPresetShape in drawingml/shape.cxx on import. - if (presetWarp == "textArchDown" || presetWarp == "textArchUp" - || presetWarp == "textButton" || presetWarp == "textCircle" - || ((i == 0) && (presetWarp == "textArchDownPour" || presetWarp == "textArchUpPour" - || presetWarp == "textButtonPour" || presetWarp == "textCirclePour"))) + if (sPresetWarp == "textArchDown" || sPresetWarp == "textArchUp" + || sPresetWarp == "textButton" || sPresetWarp == "textCircle" + || ((i == 0) + && (sPresetWarp == "textArchDownPour" || sPresetWarp == "textArchUpPour" + || sPresetWarp == "textButtonPour" || sPresetWarp == "textCirclePour"))) { fValue *= 60000.0; + if (fValue < 0) + fValue += 21600000; } - else if ((i == 1) && (presetWarp == "textDoubleWave1" || presetWarp == "textWave1" - || presetWarp == "textWave2" || presetWarp == "textWave4")) + else if ((i == 1) + && (sPresetWarp == "textDoubleWave1" || sPresetWarp == "textWave1" + || sPresetWarp == "textWave2" || sPresetWarp == "textWave4")) { fValue = fValue / 0.216 - 50000.0; } - else if ((i == 1) && (presetWarp == "textArchDownPour" || presetWarp == "textArchUpPour" - || presetWarp == "textButtonPour" || presetWarp == "textCirclePour")) + else if ((i == 1) + && (sPresetWarp == "textArchDownPour" + || sPresetWarp == "textArchUpPour" + || sPresetWarp == "textButtonPour" + || sPresetWarp == "textCirclePour")) { fValue /= 0.108; } @@ -2889,15 +2960,24 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin } OString sFmla = "val " + OString::number(std::lround(fValue)); mpFS->singleElementNS(XML_a, XML_gd, XML_name, sName, XML_fmla, sFmla); + // There exists faulty Favorite shapes with one handle but two adjustment values. + if (!bHasTwoHandles) + break; } - mpFS->endElementNS( XML_a, XML_avLst ); + mpFS->endElementNS(XML_a, XML_avLst); mpFS->endElementNS(XML_a, XML_prstTxWarp); } else { - mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp); + mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, sPresetWarp); } } + else if (GetDocumentType() == DOCUMENT_DOCX) + { + // interim solution for fdo#80897, roundtrip DOCX > LO > DOCX + if (!sMSWordPresetTextWarp.isEmpty()) + mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, sMSWordPresetTextWarp); + } if (GetDocumentType() == DOCUMENT_DOCX || GetDocumentType() == DOCUMENT_XLSX) { @@ -2995,7 +3075,7 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin Any any ( enumeration->nextElement() ); if( any >>= paragraph) - WriteParagraph( paragraph, bOverridingCharHeight, nCharHeight ); + WriteParagraph( paragraph, bOverridingCharHeight, nCharHeight, rXPropSet ); } } diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx index 5729c9d27a66..c1982961537b 100644 --- a/oox/source/export/shapes.cxx +++ b/oox/source/export/shapes.cxx @@ -686,11 +686,16 @@ static sal_Int32 lcl_CircleAngle2CustomShapeEllipseAngleOOX(const sal_Int32 nInt ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) { - // First check, if this is a Fontwork-shape. For DrawingML, such a shape is a - // TextBox shape with body property prstTxWarp. SAL_INFO("oox.shape", "write custom shape"); Reference< XPropertySet > rXPropSet( xShape, UNO_QUERY ); - bool bIsFontworkShape(false); + // First check, if this is a Fontwork-shape. For DrawingML, such a shape is a + // TextBox shape with body property prstTxWarp. + if (IsFontworkShape(rXPropSet)) + { + ShapeExport::WriteTextShape(xShape); // qualifier to prevent PowerPointShapeExport + return *this; + } + bool bHasGeometrySeq(false); Sequence< PropertyValue > aGeometrySeq; OUString sShapeType; @@ -704,32 +709,11 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) for (const PropertyValue& rProp : std::as_const(aGeometrySeq)) { SAL_INFO("oox.shape", "geometry property: " << rProp.Name); - if (rProp.Name == "TextPath") - { - uno::Sequence aTextPathSeq; - rProp.Value >>= aTextPathSeq; - for (const PropertyValue& rTextProp : std::as_const(aTextPathSeq)) - { - if (rTextProp.Name == "TextPath") - { - rTextProp.Value >>= bIsFontworkShape; - } - } - } - else if (rProp.Name == "Type") + if (rProp.Name == "Type") rProp.Value >>= sShapeType; } } } - if (bIsFontworkShape) - { - // write the correct type to m_presetWarp, WriteTextShape() needs it - // to set TextWarp. - m_presetWarp = PresetGeometryTypeNames::GetMsoName(sShapeType); - ShapeExport::WriteTextShape(xShape); // qualifier to prevent PowerPointShapeExport - return *this; - } - bool bPredefinedHandlesUsed = true; bool bHasHandles = false; @@ -752,9 +736,6 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) bool bFlipH = false; bool bFlipV = false; - // Avoid interference of preset type to the next shape - m_presetWarp = ""; - if (bHasGeometrySeq) { for (int i = 0; i < aGeometrySeq.getLength(); i++) @@ -778,10 +759,6 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape ) bPredefinedHandlesUsed = false; // TODO: update nAdjustmentsWhichNeedsToBeConverted here } - else if ( rProp.Name == "PresetTextWarp" ) - { - rProp.Value >>= m_presetWarp; - } else if ( rProp.Name == "ViewBox" ) rProp.Value >>= aViewBox; } @@ -1556,7 +1533,7 @@ ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, s if (xPropertySetInfo->hasPropertyByName("TextBox") && xPropertySet->getPropertyValue("TextBox").get()) { GetTextExport()->WriteTextBox(uno::Reference(xIface, uno::UNO_QUERY_THROW)); - WriteText( xIface, m_presetWarp, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace ); + WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace ); return *this; } } @@ -1569,10 +1546,10 @@ ShapeExport& ShapeExport::WriteTextBox( const Reference< XInterface >& xIface, s pFS->startElementNS(nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_txBody : XML_txbx)); - WriteText( xIface, m_presetWarp, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX) ); + WriteText( xIface, /*bBodyPr=*/(GetDocumentType() != DOCUMENT_DOCX) ); pFS->endElementNS( nXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_txBody : XML_txbx) ); if (GetDocumentType() == DOCUMENT_DOCX) - WriteText( xIface, m_presetWarp, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace ); + WriteText( xIface, /*bBodyPr=*/true, /*bText=*/false, /*nXmlNamespace=*/nXmlNamespace ); } else if (GetDocumentType() == DOCUMENT_DOCX) mpFS->singleElementNS(nXmlNamespace, XML_bodyPr); @@ -1859,9 +1836,9 @@ ShapeExport& ShapeExport::WriteTableShape( const Reference< XShape >& xShape ) ShapeExport& ShapeExport::WriteTextShape( const Reference< XShape >& xShape ) { - bool bIsFontworkShape(m_presetWarp.startsWith("text") && m_presetWarp != "textNoShape"); FSHelperPtr pFS = GetFS(); Reference xShapeProps(xShape, UNO_QUERY); + pFS->startElementNS(mnXmlNamespace, (GetDocumentType() != DOCUMENT_DOCX ? XML_sp : XML_wsp)); // non visual shape properties @@ -1898,12 +1875,12 @@ ShapeExport& ShapeExport::WriteTextShape( const Reference< XShape >& xShape ) WriteShapeTransformation( xShape, XML_a ); WritePresetShape( "rect" ); uno::Reference xPropertySet(xShape, UNO_QUERY); - if (!bIsFontworkShape) // Fontwork needs fill and outline on char instead. + if (!IsFontworkShape(xShapeProps)) // Fontwork needs fill and outline in run properties instead. { WriteBlipOrNormalFill(xPropertySet, "Graphic"); WriteOutline(xPropertySet); + WriteShapeEffects(xPropertySet); } - WriteShapeEffects(xPropertySet); pFS->endElementNS( mnXmlNamespace, XML_spPr ); WriteTextBox( xShape, mnXmlNamespace ); diff --git a/sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp b/sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp new file mode 100644 index 0000000000000000000000000000000000000000..be3d17c21c1210d9f8f6b50347b39bc85a418931 GIT binary patch literal 17886 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 t<9ZLT@~BjU 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±fhjrzL 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 + + // Make sure the fontwork shape has a blip bitmap fill and a colored outline. + // Without the patch, fill and outline were black. + xmlDocUniquePtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml"); + const OString sPathStart("//p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr"); + assertXPath(pXmlDoc, sPathStart + "/a:blipFill/a:blip", 1); + assertXPath(pXmlDoc, sPathStart + "/a:ln/a:solidFill/a:srgbClr", "val", "ffbf00"); +} + +void SdOOXMLExportTest1::testTdf100348FontworkGradientGlow() +{ + ::sd::DrawDocShellRef xDocShRef + = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp"), ODP); + utl::TempFile tempFile; + xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile); + xDocShRef->DoClose(); + + // Make sure the fontwork shape has a gradient fill and a colored glow. + // Without the patch, fill was black and no glow applied. + xmlDocUniquePtr pXmlDoc = parseExport(tempFile, "ppt/slides/slide1.xml"); + const OString sPathStart("//p:sld/p:cSld/p:spTree/p:sp/p:txBody/a:p/a:r/a:rPr"); + assertXPath(pXmlDoc, sPathStart + "/a:gradFill/a:gsLst/a:gs[1]/a:srgbClr", "val", "8d281e"); + assertXPath(pXmlDoc, sPathStart + "/a:effectLst/a:glow", "rad", "63360"); + assertXPath(pXmlDoc, sPathStart + "/a:effectLst/a:glow/a:srgbClr", "val", "ff4500"); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdOOXMLExportTest1); CPPUNIT_PLUGIN_IMPLEMENT();