oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx   |binary
 oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx  |binary
 oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx       |binary
 oox/qa/unit/export.cxx                                  |   26 +++
 oox/qa/unit/shape.cxx                                   |  130 ++++++++++++++++
 oox/source/drawingml/shape.cxx                          |   43 +++--
 oox/source/drawingml/textcharacterpropertiescontext.cxx |    1 
 oox/source/export/drawingml.cxx                         |   12 +
 sd/qa/unit/export-tests-ooxml3.cxx                      |    5 
 9 files changed, 199 insertions(+), 18 deletions(-)

New commits:
commit 260735ff98631b94ae8737cf1cead3e20bade618
Author:     Regina Henschel <rb.hensc...@t-online.de>
AuthorDate: Sat Mar 11 18:39:06 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Tue Mar 14 07:40:00 2023 +0000

    tdf#139618 Add WordArt fill types in pptx import
    
    This fix uses a similar approach as in WpsContext::onEndElement, only
    that here moTextOutlineProperties and maFillProperties are still
    available whereas in WpsContext the properties need to be collected
    from CharInteropGrabBag.
    I have adapted unit test testTdf125573_FontworkScaleX because now the
    gradient is imported, see comment in former version of the test.
    
    Change-Id: I989ee475867c97b9f93c7e65cd25483611eec7bf
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/148687
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx 
b/oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx
new file mode 100644
index 000000000000..8fd4bcc181f0
Binary files /dev/null and 
b/oox/qa/unit/data/tdf139618_ImportWordArtGradient.pptx differ
diff --git a/oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx 
b/oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx
new file mode 100644
index 000000000000..405135783e16
Binary files /dev/null and 
b/oox/qa/unit/data/tdf139618_ThemeColorTransparency.pptx differ
diff --git a/oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx 
b/oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx
new file mode 100644
index 000000000000..5da52ceb3c15
Binary files /dev/null and b/oox/qa/unit/data/tdf139618_WordArtBitmapFill.pptx 
differ
diff --git a/oox/qa/unit/export.cxx b/oox/qa/unit/export.cxx
index 0e2a2669ee79..a98eaa5ce93f 100644
--- a/oox/qa/unit/export.cxx
+++ b/oox/qa/unit/export.cxx
@@ -1297,6 +1297,32 @@ CPPUNIT_TEST_FIXTURE(Test, testFontworkRectGradient)
     assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr/w14:lumOff", 
"val", "60000");
     assertXPath(pXmlDoc, sElement + "w14:gs[3]/w14:schemeClr/w14:alpha", 
"val", "70000");
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testThemeColorTransparency)
+{
+    // The document has first a Fontwork shape with solid fill theme color 
with transparency and
+    // outline transparency and second a textbox with character transparency.
+    // Without fix the transparency was not written to file.
+    loadFromURL(u"tdf139618_ThemeColorTransparency.pptx");
+
+    save("Impress Office Open XML");
+    xmlDocUniquePtr pXmlDoc = parseExport("ppt/slides/slide1.xml");
+
+    // Make sure a:alpha is written for line color and for fill color.
+    // Make sure fill color is a schemeClr.
+    OString sElement = 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:txBody/a:p/a:r/a:rPr/";
+    assertXPath(pXmlDoc, sElement + "a:ln/a:solidFill/a:srgbClr/a:alpha", 
"val", "25000");
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr", "val", 
"accent1");
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:lumMod", "val", 
"60000");
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:lumOff", "val", 
"40000");
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:alpha", "val", 
"35000");
+
+    // Make sure a:alpha is written for characters and fill color is a 
schemeClr.
+    sElement = "/p:sld/p:cSld/p:spTree/p:sp[2]/p:txBody/a:p/a:r/a:rPr/";
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr", "val", 
"accent4");
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:lumMod", "val", 
"75000");
+    assertXPath(pXmlDoc, sElement + "a:solidFill/a:schemeClr/a:alpha", "val", 
"20000");
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/oox/qa/unit/shape.cxx b/oox/qa/unit/shape.cxx
index b5a3fe8b1113..523003ee351a 100644
--- a/oox/qa/unit/shape.cxx
+++ b/oox/qa/unit/shape.cxx
@@ -16,7 +16,9 @@
 #include <com/sun/star/awt/FontWeight.hpp>
 #include <com/sun/star/awt/Gradient.hpp>
 #include <com/sun/star/awt/Size.hpp>
+#include <com/sun/star/awt/XBitmap.hpp>
 #include <com/sun/star/beans/XPropertySet.hpp>
+#include <com/sun/star/drawing/BitmapMode.hpp>
 #include <com/sun/star/drawing/FillStyle.hpp>
 #include <com/sun/star/drawing/LineDash.hpp>
 #include <com/sun/star/drawing/LineJoint.hpp>
@@ -24,6 +26,7 @@
 #include <com/sun/star/drawing/TextHorizontalAdjust.hpp>
 #include <com/sun/star/drawing/TextVerticalAdjust.hpp>
 #include <com/sun/star/drawing/XDrawPagesSupplier.hpp>
+#include <com/sun/star/graphic/XGraphic.hpp>
 #include <com/sun/star/lang/Locale.hpp>
 #include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/text/XTextRange.hpp>
@@ -585,6 +588,133 @@ CPPUNIT_TEST_FIXTURE(OoxShapeTest, 
testWriterFontworkDarkenTransparency)
     CPPUNIT_ASSERT_EQUAL(uno::Any(Color(208, 175, 114)),
                          xShapeProps->getPropertyValue(u"FillColor"));
 }
+
+CPPUNIT_TEST_FIXTURE(OoxShapeTest, testImportWordArtGradient)
+{
+    loadFromURL(u"tdf139618_ImportWordArtGradient.pptx");
+    // Without the patch all WordArt was imported with solid color. Now 
gradient is imported.
+    // This test covers several aspects of import of gradient fill.
+
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> 
xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+                                                 uno::UNO_QUERY);
+
+    // linear gradient, MSO UI 21deg, solid transparency on outline
+    {
+        uno::Reference<beans::XPropertySet> 
xShapeProps(xDrawPage->getByIndex(0), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT),
+                             xShapeProps->getPropertyValue(u"FillStyle"));
+        awt::Gradient aGradient;
+        xShapeProps->getPropertyValue(u"FillGradient") >>= aGradient;
+        CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_LINEAR, aGradient.Style);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(690), aGradient.Angle);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(16760832), aGradient.StartColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(12582912), aGradient.EndColor);
+
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_SOLID),
+                             xShapeProps->getPropertyValue(u"LineStyle"));
+        sal_Int32 nOutlineColor;
+        xShapeProps->getPropertyValue(u"LineColor") >>= nOutlineColor;
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(7384391), nOutlineColor);
+        sal_Int16 nLineTransparence;
+        xShapeProps->getPropertyValue(u"LineTransparence") >>= 
nLineTransparence;
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(60), nLineTransparence);
+    }
+
+    // radial gradient, direct color with transparency, focus center, dotted 
outline
+    // The stop color transparency is imported as transparency gradient with 
same geometry.
+    {
+        uno::Reference<beans::XPropertySet> 
xShapeProps(xDrawPage->getByIndex(1), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT),
+                             xShapeProps->getPropertyValue(u"FillStyle"));
+        awt::Gradient aGradient;
+        xShapeProps->getPropertyValue(u"FillGradient") >>= aGradient;
+        CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(15132160), aGradient.EndColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(33760), aGradient.StartColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.XOffset);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.YOffset);
+
+        xShapeProps->getPropertyValue(u"FillTransparenceGradient") >>= 
aGradient;
+        CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RADIAL, aGradient.Style);
+        // Transparency is encoded in gray color.
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(5000268), aGradient.EndColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(6710886), aGradient.StartColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.XOffset);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(50), aGradient.YOffset);
+
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_DASH),
+                             xShapeProps->getPropertyValue(u"LineStyle"));
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineCap_ROUND),
+                             xShapeProps->getPropertyValue(u"LineCap"));
+        CPPUNIT_ASSERT_EQUAL(uno::Any(sal_Int32(7384391)),
+                             xShapeProps->getPropertyValue(u"LineColor"));
+        drawing::LineDash aLineDash;
+        xShapeProps->getPropertyValue(u"LineDash") >>= aLineDash;
+        CPPUNIT_ASSERT_EQUAL(drawing::DashStyle_ROUNDRELATIVE, 
aLineDash.Style);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(1), aLineDash.Dots);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aLineDash.Dashes);
+    }
+
+    // solid theme color accent 1, rectangular transparency gradient, focus 
top-right, no outline
+    // FillProperties::pushToPropMap imports this currently (Mar 2023) as 
color gradient.
+    // Thus no theme color is tested but direct color.
+    {
+        uno::Reference<beans::XPropertySet> 
xShapeProps(xDrawPage->getByIndex(2), uno::UNO_QUERY);
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_GRADIENT),
+                             xShapeProps->getPropertyValue(u"FillStyle"));
+        awt::Gradient aGradient;
+        xShapeProps->getPropertyValue(u"FillGradient") >>= aGradient;
+        CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RECT, aGradient.Style);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(4485828), aGradient.EndColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(4485828), aGradient.StartColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aGradient.XOffset);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aGradient.YOffset);
+
+        xShapeProps->getPropertyValue(u"FillTransparenceGradient") >>= 
aGradient;
+        CPPUNIT_ASSERT_EQUAL(awt::GradientStyle_RECT, aGradient.Style);
+        // Transparency is encoded in gray color.
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(16777215), aGradient.EndColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int32(0), aGradient.StartColor);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(100), aGradient.XOffset);
+        CPPUNIT_ASSERT_EQUAL(sal_Int16(0), aGradient.YOffset);
+
+        CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::LineStyle_NONE),
+                             xShapeProps->getPropertyValue(u"LineStyle"));
+    }
+}
+
+CPPUNIT_TEST_FIXTURE(OoxShapeTest, testWordArtBitmapFill)
+{
+    // The document has a WordArt shape with bitmap fill.
+    // Without fix it was imported as solid color fill.
+    loadFromURL(u"tdf139618_WordArtBitmapFill.pptx");
+
+    uno::Reference<drawing::XDrawPagesSupplier> 
xDrawPagesSupplier(mxComponent, uno::UNO_QUERY);
+    uno::Reference<drawing::XDrawPage> 
xDrawPage(xDrawPagesSupplier->getDrawPages()->getByIndex(0),
+                                                 uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xShapeProps(xDrawPage->getByIndex(0), 
uno::UNO_QUERY);
+    CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::FillStyle_BITMAP),
+                         xShapeProps->getPropertyValue(u"FillStyle"));
+
+    // Test some bitmap properties
+    CPPUNIT_ASSERT_EQUAL(uno::Any(drawing::BitmapMode_REPEAT),
+                         xShapeProps->getPropertyValue(u"FillBitmapMode"));
+    CPPUNIT_ASSERT_EQUAL(uno::Any(true), 
xShapeProps->getPropertyValue(u"FillBitmapTile"));
+    uno::Reference<awt::XBitmap> xBitmap;
+    xShapeProps->getPropertyValue(u"FillBitmap") >>= xBitmap;
+
+    uno::Reference<graphic::XGraphic> xGraphic;
+    xGraphic.set(xBitmap, uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xGraphicDescriptor(xGraphic, 
uno::UNO_QUERY_THROW);
+    OUString sMimeType;
+    CPPUNIT_ASSERT(xGraphicDescriptor->getPropertyValue("MimeType") >>= 
sMimeType);
+    CPPUNIT_ASSERT_EQUAL(OUString("image/jpeg"), sMimeType);
+    awt::Size aSize100thMM;
+    CPPUNIT_ASSERT(xGraphicDescriptor->getPropertyValue("Size100thMM") >>= 
aSize100thMM);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1592), aSize100thMM.Width);
+    CPPUNIT_ASSERT_EQUAL(sal_Int32(1592), aSize100thMM.Height);
+}
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index ccfd61410bd5..18e087dc2207 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -696,27 +696,38 @@ static void lcl_copyCharPropsToShape(const 
uno::Reference<drawing::XShape>& xSha
                 xSet->setPropertyValue(u"CharFontFamilyComplex", 
uno::Any(nFontFamily));
             }
 
-            // LO uses shape fill, MS Office character fill. Currently only 
this solid fill workaround
-            // is implemented.
-            // ToDo: Consider other fill styles
-            // ToDo: Consider Color Theme
-            xSet->setPropertyValue(UNO_NAME_FILLSTYLE, 
uno::Any(drawing::FillStyle_SOLID));
-            sal_Int32 aFillColor(COL_BLACK); //default
-            if (rCharProps.maFillProperties.maFillColor.isUsed())
+            // LO uses shape properties, MS Office character properties. Copy 
them from char to shape.
+            // Outline
+            if (rCharProps.moTextOutlineProperties.has_value())
             {
-                aFillColor = static_cast<sal_Int32>(
-                    
rCharProps.maFillProperties.maFillColor.getColor(rFilter.getGraphicHelper())
-                        .GetRGBColor());
-                if (rCharProps.maFillProperties.maFillColor.hasTransparency())
+                oox::drawingml::ShapePropertyMap 
aStrokeShapeProps(rFilter.getModelObjectHelper());
+                rCharProps.moTextOutlineProperties.value().pushToPropMap(
+                    aStrokeShapeProps, rFilter.getGraphicHelper());
+                for (const auto& rProp : 
aStrokeShapeProps.makePropertyValueSequence())
                 {
-                    const sal_Int16 aTransparence
-                        = 
rCharProps.maFillProperties.maFillColor.getTransparency();
-                    xSet->setPropertyValue(UNO_NAME_FILL_TRANSPARENCE, 
uno::Any(aTransparence));
+                    xSet->setPropertyValue(rProp.Name, rProp.Value);
                 }
             }
-            xSet->setPropertyValue(UNO_NAME_FILLCOLOR, uno::Any(aFillColor));
+            else
+            {
+                xSet->setPropertyValue(UNO_NAME_LINESTYLE, 
uno::Any(drawing::LineStyle_NONE));
+            }
+
+            // Fill
+            // ToDo: Replace flip and rotate constants in parameters with 
actual values.
+            oox::drawingml::ShapePropertyMap 
aFillShapeProps(rFilter.getModelObjectHelper());
+            rCharProps.maFillProperties.pushToPropMap(aFillShapeProps, 
rFilter.getGraphicHelper(),
+                                                      /*nShapeRotation*/ 0,
+                                                      /*nPhClr*/ 
API_RGB_TRANSPARENT,
+                                                      /*nPhClrTheme*/ -1,
+                                                      /*bFlipH*/ false, 
/*bFlipV*/ false,
+                                                      /*bIsCustomShape*/ true);
+            for (const auto& rProp : 
aFillShapeProps.makePropertyValueSequence())
+            {
+                xSet->setPropertyValue(rProp.Name, rProp.Value);
+            }
 
-            // ToDo: copy character outline to shape stroke.
+            // ToDo: Import WordArt glow and simple shadow effects. They are 
available in LO.
         }
 
         // LO does not evaluate paragraph alignment in text path mode. Use 
text area anchor instead.
diff --git a/oox/source/drawingml/textcharacterpropertiescontext.cxx 
b/oox/source/drawingml/textcharacterpropertiescontext.cxx
index c5cf346de199..2b87aa7f1cd0 100644
--- a/oox/source/drawingml/textcharacterpropertiescontext.cxx
+++ b/oox/source/drawingml/textcharacterpropertiescontext.cxx
@@ -123,6 +123,7 @@ ContextHandlerRef 
TextCharacterPropertiesContext::onCreateContext( sal_Int32 aEl
         case A_TOKEN( solidFill ):
         case A_TOKEN( gradFill ):
         case A_TOKEN( pattFill ):
+        case A_TOKEN( blipFill ): // Fontwork uses blibFill.
             return FillPropertiesContext::createFillContext( *this, 
aElementToken, rAttribs, mrTextCharacterProperties.maFillProperties );
         // EG_EffectProperties
         case A_TOKEN( effectDag ):  // CT_EffectContainer 5.1.10.25
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 5f2e1a7b4558..8f16b1ebc95e 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -582,6 +582,18 @@ bool DrawingML::WriteSchemeColor(OUString const& 
rPropertyName, const uno::Refer
                 break;
         }
     }
+    // Alpha is actually not contained in maTransformations although possible 
(as of Mar 2023).
+    sal_Int16 nAPITransparency(0);
+    if ((rPropertyName == u"FillColorThemeReference"
+         && GetProperty(xPropertySet, "FillTransparence"))
+        || (rPropertyName == u"LineColorThemeReference"
+            && GetProperty(xPropertySet, "LineTransparence"))
+        || (rPropertyName == u"CharColorThemeReference"
+            && GetProperty(xPropertySet, "CharTransparence")))
+        mAny >>= nAPITransparency;
+    if (nAPITransparency != 0)
+        mpFS->singleElementNS(XML_a, XML_alpha, XML_val,
+                              OString::number(MAX_PERCENT - (PER_PERCENT * 
nAPITransparency)));
 
     mpFS->endElementNS(XML_a, XML_schemeClr);
     mpFS->endElementNS(XML_a, XML_solidFill);
diff --git a/sd/qa/unit/export-tests-ooxml3.cxx 
b/sd/qa/unit/export-tests-ooxml3.cxx
index 405170ffcdcf..3bec0e59d348 100644
--- a/sd/qa/unit/export-tests-ooxml3.cxx
+++ b/sd/qa/unit/export-tests-ooxml3.cxx
@@ -575,20 +575,21 @@ CPPUNIT_TEST_FIXTURE(SdOOXMLExportTest3, 
testTdf125573_FontWorkScaleX)
     assertXPath(pXmlDocContent,
                 
"/p:sld/p:cSld/p:spTree/p:sp[1]/p:txBody/a:bodyPr[@fromWordArt='1']");
 
-    // State of Nov 2022. It needs to be updated, when import of fill and 
stroke is implemented.
     // Error was, that text in legacy shapes of category "Follow Path" was not 
scaled to the path.
     uno::Reference<beans::XPropertySet> xShapeArchProps(getShapeFromPage(0, 
0));
     awt::Rectangle aBoundRectArch;
     xShapeArchProps->getPropertyValue(UNO_NAME_MISC_OBJ_BOUNDRECT) >>= 
aBoundRectArch;
     // BoundRect is DPI dependent, thus allow some range.
+    // Expected width is 13139 in 96dpi and is 13106 in 120 dpi, for example
     // (Without fix Expected less than: 85 Actual  : 10432)
-    CPPUNIT_ASSERT_LESS(sal_Int32(85), std::abs(aBoundRectArch.Width - 13038));
+    CPPUNIT_ASSERT_LESS(sal_Int32(85), std::abs(aBoundRectArch.Width - 13139));
 
     // Error was, that text in shapes of category "Warp" was not scaled to the 
path.
     uno::Reference<beans::XPropertySet> xShapeWaveProps(getShapeFromPage(0, 
1));
     awt::Rectangle aBoundRectWave;
     xShapeWaveProps->getPropertyValue(UNO_NAME_MISC_OBJ_BOUNDRECT) >>= 
aBoundRectWave;
     // BoundRect is DPI dependent, thus allow some range.
+    // Expected with is 11576 in 96dpt and is 11578 in 120dpi, for example
     CPPUNIT_ASSERT_LESS(sal_Int32(85), std::abs(aBoundRectWave.Width - 11576));
 }
 

Reply via email to