oox/inc/drawingml/presetgeometrynames.hxx    |    1 
 oox/source/drawingml/presetgeometrynames.cxx |   21 +++++++
 oox/source/export/drawingml.cxx              |   62 +++++++++++++++++++++-
 oox/source/export/shapes.cxx                 |   73 +++++++++++++++++++++------
 4 files changed, 139 insertions(+), 18 deletions(-)

New commits:
commit 2be2c914ed48823304c2e95a836ee93a08853628
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Fri Jun 14 19:10:36 2019 +0200
Commit:     Regina Henschel <rb.hensc...@t-online.de>
CommitDate: Mon Jun 17 18:48:14 2019 +0200

    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.behr...@cib.de>
    Reviewed-by: Regina Henschel <rb.hensc...@t-online.de>

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 );
 
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to