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 <Thorsten.Behrens@CIB.de>
This commit is contained in:
Regina Henschel 2020-07-04 15:11:03 +02:00 committed by Thorsten Behrens
parent b8ff697269
commit 005f5db47b
8 changed files with 198 additions and 97 deletions

View file

@ -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 );

View file

@ -102,7 +102,6 @@ private:
ShapeHashMap maShapeMap;
ShapeHashMap* mpShapeMap;
OUString m_presetWarp;
public:

View file

@ -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) )

View file

@ -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 );
}
}

View file

@ -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 );

Binary file not shown.

Binary file not shown.

View file

@ -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();