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:
parent
b8ff697269
commit
005f5db47b
8 changed files with 198 additions and 97 deletions
|
@ -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 );
|
||||
|
|
|
@ -102,7 +102,6 @@ private:
|
|||
|
||||
ShapeHashMap maShapeMap;
|
||||
ShapeHashMap* mpShapeMap;
|
||||
OUString m_presetWarp;
|
||||
|
||||
public:
|
||||
|
||||
|
|
|
@ -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) )
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
BIN
sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp
Normal file
BIN
sd/qa/unit/data/odp/tdf100348_FontworkBitmapFill.odp
Normal file
Binary file not shown.
BIN
sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp
Normal file
BIN
sd/qa/unit/data/odp/tdf100348_FontworkGradientGlow.odp
Normal file
Binary file not shown.
|
@ -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();
|
||||
|
|
Loading…
Reference in a new issue