summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorRegina Henschel <rb.henschel@t-online.de>2019-06-14 19:10:36 +0200
committerRegina Henschel <rb.henschel@t-online.de>2019-06-17 18:48:14 +0200
commit2be2c914ed48823304c2e95a836ee93a08853628 (patch)
tree310fb25c47b2cf6bc07b640cfc54b199cb34b845 /oox
parent04d37a2151cdab801fff7229c2624a8e21be8c4b (diff)
tdf#51195, tdf#100348 Convert Fontwork to TextWarp on export
LibreOffice has Fontwork as property text-path in enhanced-custom- geometry. OOXML has the similar TextWarp as property of a textbox. The patch converts the custom shape to a textbox and sets the attribute prstTxWarp. Fill and outline of the Fontwork is lost. The import and export of fill and outline is tracked in tdf#119221 and still needs to be fixed. Change-Id: I8ea7b305d7d0a8367d61c1789f22b56d274a311d Reviewed-on: https://gerrit.libreoffice.org/74057 Tested-by: Jenkins Reviewed-by: Thorsten Behrens <Thorsten.Behrens@CIB.de> Reviewed-by: Regina Henschel <rb.henschel@t-online.de>
Diffstat (limited to 'oox')
-rw-r--r--oox/inc/drawingml/presetgeometrynames.hxx1
-rw-r--r--oox/source/drawingml/presetgeometrynames.cxx21
-rw-r--r--oox/source/export/drawingml.cxx62
-rw-r--r--oox/source/export/shapes.cxx73
4 files changed, 139 insertions, 18 deletions
diff --git a/oox/inc/drawingml/presetgeometrynames.hxx b/oox/inc/drawingml/presetgeometrynames.hxx
index 51721e41febd..358fc9acefb6 100644
--- a/oox/inc/drawingml/presetgeometrynames.hxx
+++ b/oox/inc/drawingml/presetgeometrynames.hxx
@@ -16,6 +16,7 @@
namespace PresetGeometryTypeNames
{
OOX_DLLPUBLIC OUString GetFontworkType(const OUString& rMsoType);
+OOX_DLLPUBLIC OUString GetMsoName(const OUString& rFontworkType);
}
#endif
diff --git a/oox/source/drawingml/presetgeometrynames.cxx b/oox/source/drawingml/presetgeometrynames.cxx
index 272094dd7ef6..dea972dc1476 100644
--- a/oox/source/drawingml/presetgeometrynames.cxx
+++ b/oox/source/drawingml/presetgeometrynames.cxx
@@ -91,4 +91,25 @@ OUString PresetGeometryTypeNames::GetFontworkType(const OUString& rMsoType)
return OUString(pRetValue, strlen(pRetValue), RTL_TEXTENCODING_ASCII_US);
}
+OUString PresetGeometryTypeNames::GetMsoName(const OUString& rFontworkType)
+{
+ static const PresetGeometryHashMap s_HashMapInv = []() {
+ PresetGeometryHashMap aHInv;
+ for (const auto& item : pPresetGeometryNameArray)
+ aHInv[item.pFontworkType] = item.pMsoName;
+ return aHInv;
+ }();
+ const char* pRetValue = "";
+ int i, nLen = rFontworkType.getLength();
+ std::unique_ptr<char[]> pBuf(new char[nLen + 1]);
+ for (i = 0; i < nLen; i++)
+ pBuf[i] = static_cast<char>(rFontworkType[i]);
+ pBuf[i] = 0;
+ PresetGeometryHashMap::const_iterator aHashIter(s_HashMapInv.find(pBuf.get()));
+ if (aHashIter != s_HashMapInv.end())
+ pRetValue = (*aHashIter).second;
+
+ return OUString(pRetValue, strlen(pRetValue), RTL_TEXTENCODING_ASCII_US);
+}
+
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index c87cb3a1f617..575878a11171 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -2544,6 +2544,7 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin
return;
sal_Int32 nTextRotateAngle = 0;
+ bool bIsFontworkShape(presetWarp.startsWith("text") && (presetWarp != "textNoShape"));
#define DEFLRINS 254
#define DEFTBINS 127
@@ -2582,6 +2583,8 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin
}
}
+ Sequence<drawing::EnhancedCustomShapeAdjustmentValue>aAdjustmentSeq;
+
if (GetProperty(rXPropSet, "CustomShapeGeometry"))
{
Sequence< PropertyValue > aProps;
@@ -2601,8 +2604,11 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin
sWritingMode = "vert270";
bVertical = true;
}
- break;
+ if (!bIsFontworkShape)
+ break;
}
+ else if (aProps[i].Name == "AdjustmentValues")
+ aProps[i].Value >>= aAdjustmentSeq;
}
}
}
@@ -2647,10 +2653,60 @@ void DrawingML::WriteText( const Reference< XInterface >& rXIface, const OUStrin
XML_anchorCtr, bHorizontalCenter ? "1" : nullptr,
XML_vert, sWritingMode,
XML_rot, (nTextRotateAngle != 0) ? oox::drawingml::calcRotationValue( nTextRotateAngle * 100 ).getStr() : nullptr );
- if( !presetWarp.isEmpty())
+ if (bIsFontworkShape)
{
- mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp.toUtf8());
+ if (aAdjustmentSeq.getLength() > 0)
+ {
+ mpFS->startElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp.toUtf8());
+ mpFS->startElementNS(XML_a, XML_avLst);
+ for (sal_Int32 i = 0, nElems = aAdjustmentSeq.getLength(); i < nElems; ++i )
+ {
+ OString sName = OString("adj") + (( nElems > 1 ) ? OString::number(i + 1) : OString());
+ double fValue(0.0);
+ if (aAdjustmentSeq[i].Value.getValueTypeClass() == TypeClass_DOUBLE)
+ aAdjustmentSeq[i].Value >>= fValue;
+ else
+ {
+ sal_Int32 nNumber(0);
+ aAdjustmentSeq[i].Value >>= nNumber;
+ fValue = static_cast<double>(nNumber);
+ }
+ // 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")))
+ {
+ fValue *= 60000.0;
+ }
+ else if ((i == 1) && (presetWarp == "textDoubleWave1" || presetWarp == "textWave1"
+ || presetWarp == "textWave2" || presetWarp == "textWave4"))
+ {
+ fValue = fValue / 0.216 - 50000.0;
+ }
+ else if ((i == 1) && (presetWarp == "textArchDownPour" || presetWarp == "textArchUpPour"
+ || presetWarp == "textButtonPour" || presetWarp == "textCirclePour"))
+ {
+ fValue /= 0.108;
+ }
+ else
+ {
+ fValue /= 0.216;
+ }
+ OString sFmla = OString("val ") + OString::number(std::lround(fValue));
+ mpFS->singleElementNS(XML_a, XML_gd, XML_name, sName, XML_fmla, sFmla);
+ }
+ mpFS->endElementNS( XML_a, XML_avLst );
+ mpFS->endElementNS(XML_a, XML_prstTxWarp);
+ }
+ else
+ {
+ mpFS->singleElementNS(XML_a, XML_prstTxWarp, XML_prst, presetWarp.toUtf8());
+ }
}
+
if (GetDocumentType() == DOCUMENT_DOCX || GetDocumentType() == DOCUMENT_XLSX)
{
bool bTextAutoGrowHeight = false;
diff --git a/oox/source/export/shapes.cxx b/oox/source/export/shapes.cxx
index d441406ae95f..14e5b848558f 100644
--- a/oox/source/export/shapes.cxx
+++ b/oox/source/export/shapes.cxx
@@ -101,6 +101,7 @@
#include <svx/unoapi.hxx>
#include <oox/export/chartexport.hxx>
#include <oox/mathml/export.hxx>
+#include <drawingml/presetgeometrynames.hxx>
using namespace ::css;
using namespace ::css::beans;
@@ -698,13 +699,56 @@ static sal_Int32 lcl_NormalizeAngle( sal_Int32 nAngle )
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);
+ bool bHasGeometrySeq(false);
+ Sequence< PropertyValue > aGeometrySeq;
+ OUString sShapeType;
+ if (GETA(CustomShapeGeometry))
+ {
+ SAL_INFO("oox.shape", "got custom shape geometry");
+ if (mAny >>= aGeometrySeq)
+ {
+ bHasGeometrySeq = true;
+ SAL_INFO("oox.shape", "got custom shape geometry sequence");
+ for (int i = 0; i < aGeometrySeq.getLength(); i++)
+ {
+ const PropertyValue& rProp = aGeometrySeq[i];
+ SAL_INFO("oox.shape", "geometry property: " << rProp.Name);
+ if (rProp.Name == "TextPath")
+ {
+ uno::Sequence<beans::PropertyValue> aTextPathSeq;
+ rProp.Value >>= aTextPathSeq;
+ for (int k = 0; k < aTextPathSeq.getLength(); k++)
+ {
+ const PropertyValue& rTextProp = aTextPathSeq[k];
+ if (rTextProp.Name == "TextPath")
+ {
+ rTextProp.Value >>= bIsFontworkShape;
+ }
+ }
+ }
+ else 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;
- OUString sShapeType;
ShapeFlag nMirrorFlags = ShapeFlag::NONE;
MSO_SPT eShapeType = EscherPropertyContainer::GetCustomShapeType( xShape, nMirrorFlags, sShapeType );
OSL_ENSURE(nullptr != dynamic_cast< SdrObjCustomShape* >(GetSdrObjectFromXShape(xShape)), "Not a SdrObjCustomShape (!)");
@@ -715,7 +759,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
eShapeType));
const char* sPresetShape = msfilter::util::GetOOXMLPresetGeometry(sShapeType.toUtf8().getStr());
SAL_INFO("oox.shape", "custom shape type: " << sShapeType << " ==> " << sPresetShape);
- Sequence< PropertyValue > aGeometrySeq;
+
sal_Int32 nAdjustmentValuesIndex = -1;
awt::Rectangle aViewBox;
uno::Sequence<beans::PropertyValues> aHandles;
@@ -726,12 +770,10 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
// Avoid interference of preset type to the next shape
m_presetWarp = "";
- if( GETA( CustomShapeGeometry ) ) {
- SAL_INFO("oox.shape", "got custom shape geometry");
- if( mAny >>= aGeometrySeq ) {
-
- SAL_INFO("oox.shape", "got custom shape geometry sequence");
- for( int i = 0; i < aGeometrySeq.getLength(); i++ ) {
+ if (bHasGeometrySeq)
+ {
+ for (int i = 0; i < aGeometrySeq.getLength(); i++)
+ {
const PropertyValue& rProp = aGeometrySeq[ i ];
SAL_INFO("oox.shape", "geometry property: " << rProp.Name);
@@ -757,7 +799,6 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
}
else if ( rProp.Name == "ViewBox" )
rProp.Value >>= aViewBox;
- }
}
}
@@ -986,9 +1027,7 @@ ShapeExport& ShapeExport::WriteCustomShape( const Reference< XShape >& xShape )
}
if( rXPropSet.is() )
{
- // Preset shape with text has no fill
- if( m_presetWarp.isEmpty() || !m_presetWarp.startsWith( "text" ) || m_presetWarp == "textNoShape" )
- WriteFill( rXPropSet );
+ WriteFill( rXPropSet );
WriteOutline( rXPropSet );
WriteShapeEffects( rXPropSet );
WriteShape3DEffects( rXPropSet );
@@ -1793,6 +1832,7 @@ 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));
@@ -1831,8 +1871,11 @@ ShapeExport& ShapeExport::WriteTextShape( const Reference< XShape >& xShape )
WriteShapeTransformation( xShape, XML_a );
WritePresetShape( "rect" );
uno::Reference<beans::XPropertySet> xPropertySet(xShape, UNO_QUERY);
- WriteBlipOrNormalFill(xPropertySet, "Graphic");
- WriteOutline(xPropertySet);
+ if (!bIsFontworkShape) // Fontwork needs fill and outline on char instead.
+ {
+ WriteBlipOrNormalFill(xPropertySet, "Graphic");
+ WriteOutline(xPropertySet);
+ }
WriteShapeEffects(xPropertySet);
pFS->endElementNS( mnXmlNamespace, XML_spPr );