summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/oox/export/drawingml.hxx13
-rw-r--r--include/oox/export/shapes.hxx1
-rw-r--r--oox/source/drawingml/customshapeproperties.cxx3
-rw-r--r--oox/source/export/drawingml.cxx188
-rw-r--r--oox/source/export/shapes.cxx53
-rw-r--r--sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odpbin0 -> 17886 bytes
-rw-r--r--sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odpbin0 -> 20381 bytes
-rw-r--r--sd/qa/unit/export-tests-ooxml1.cxx37
8 files changed, 198 insertions, 97 deletions
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<css::beans::XPropertySet>& rXPropSet);
void WriteSoftEdgeEffect(const css::uno::Reference<css::beans::XPropertySet>& 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<css::beans::XPropertySet>& 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<sal_Int32,sal_Int32>> & 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 <svx/unoapi.hxx>
#include <svx/unoshape.hxx>
#include <svx/EnhancedCustomShape2d.hxx>
+#include <drawingml/presetgeometrynames.hxx>
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<sal_uInt32>(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<sal_uInt32>(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<css::beans::XPropertySet>& rXShapePropSet)
{
- Reference< XText > xXText( rXIface, UNO_QUERY );
- Reference< XPropertySet > rXPropSet( rXIface, UNO_QUERY );
+ bool bResult(false);
+ if (rXShapePropSet.is())
+ {
+ Sequence<PropertyValue> aCustomShapeGeometryProps;
+ if (GetProperty(rXShapePropSet, "CustomShapeGeometry"))
+ {
+ mAny >>= aCustomShapeGeometryProps;
+ uno::Sequence<beans::PropertyValue> 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<XInterface>& 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<drawing::EnhancedCustomShapeAdjustmentValue> aAdjustmentSeq;
uno::Sequence<beans::PropertyValue> 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<beans::PropertyValue> 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<bool>())
{
GetTextExport()->WriteTextBox(uno::Reference<drawing::XShape>(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<XPropertySet> 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<beans::XPropertySet> 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 000000000000..be3d17c21c12
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp
Binary files differ
diff --git a/sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp b/sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp
new file mode 100644
index 000000000000..e2c5f1e887f9
--- /dev/null
+++ b/sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp
Binary files differ
diff --git a/sd/qa/unit/export-tests-ooxml1.cxx b/sd/qa/unit/export-tests-ooxml1.cxx
index f7cec3010dc7..57112261a4af 100644
--- a/sd/qa/unit/export-tests-ooxml1.cxx
+++ b/sd/qa/unit/export-tests-ooxml1.cxx
@@ -91,6 +91,8 @@ public:
void testRoundtripPrstDash();
void testDashOnHairline();
void testCustomshapeBitmapfillSrcrect();
+ void testTdf100348FontworkBitmapFill();
+ void testTdf100348FontworkGradientGlow();
CPPUNIT_TEST_SUITE(SdOOXMLExportTest1);
@@ -131,6 +133,8 @@ public:
CPPUNIT_TEST(testRoundtripPrstDash);
CPPUNIT_TEST(testDashOnHairline);
CPPUNIT_TEST(testCustomshapeBitmapfillSrcrect);
+ CPPUNIT_TEST(testTdf100348FontworkBitmapFill);
+ CPPUNIT_TEST(testTdf100348FontworkGradientGlow);
CPPUNIT_TEST_SUITE_END();
@@ -1095,6 +1099,39 @@ void SdOOXMLExportTest1::testCustomshapeBitmapfillSrcrect()
CPPUNIT_ASSERT_EQUAL(4.0, fRightPercent);
}
+void SdOOXMLExportTest1::testTdf100348FontworkBitmapFill()
+{
+ ::sd::DrawDocShellRef xDocShRef
+ = loadURL(m_directories.getURLFromSrc("sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp"), ODP);
+ utl::TempFile tempFile;
+ xDocShRef = saveAndReload(xDocShRef.get(), PPTX, &tempFile);
+ xDocShRef->DoClose();
+
+ // 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();