[Libreoffice-commits] core.git: 4 commits - include/oox oox/source sw/qa writerfilter/CustomTarget_source.mk writerfilter/source

Jacobo Aragunde Pérez jaragunde at igalia.com
Fri May 23 01:04:40 PDT 2014


 include/oox/drawingml/fillproperties.hxx                                 |   26 
 include/oox/drawingml/fillpropertiesgroupcontext.hxx                     |   42 +
 include/oox/export/drawingml.hxx                                         |    4 
 oox/source/drawingml/fillproperties.cxx                                  |  205 ++++
 oox/source/drawingml/fillpropertiesgroupcontext.cxx                      |   82 +
 oox/source/drawingml/shape.cxx                                           |    5 
 oox/source/export/drawingml.cxx                                          |  100 ++
 oox/source/token/namespaces-strict.txt                                   |    1 
 oox/source/token/namespaces.txt                                          |    1 
 oox/source/token/tokens.txt                                              |   43 +
 sw/qa/extras/inc/swmodeltestbase.hxx                                     |    1 
 sw/qa/extras/ooxmlexport/data/picture-artistic-effects-preservation.docx |binary
 sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx                              |   99 ++
 writerfilter/CustomTarget_source.mk                                      |    1 
 writerfilter/source/dmapper/GraphicImport.cxx                            |    3 
 writerfilter/source/ooxml/model.xml                                      |  412 ++++++++++
 16 files changed, 1024 insertions(+), 1 deletion(-)

New commits:
commit b5f6a5cfc517ecd8aa6ba96471d854b07b92ebaa
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Thu May 22 16:05:23 2014 +0200

    ooxml: Do not repeat wdp files in artistic effects
    
    When two pictures apply different effects to the same picture, it is
    only saved once in the original document. Added a cache to DrawingML
    to know if the picture has already been exported, and added a test
    for it.
    
    Change-Id: Ia25f3d8f2f46d61f18aefc22fdfdbcdc72f2d916

diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 77d54b4..e97f05d 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -83,6 +83,7 @@ public:
 private:
     static int mnImageCounter;
     static int mnWdpImageCounter;
+    static std::map<OUString, OUString> maWdpCache;
 
     /// To specify where write eg. the images to (like 'ppt', or 'word' - according to the OPC).
     DocumentType meDocumentType;
@@ -178,7 +179,7 @@ public:
     void WriteShapeEffect( const OUString& sName, const css::uno::Sequence< css::beans::PropertyValue >& aEffectProps );
     void WriteShape3DEffects( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
     void WriteArtisticEffect( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
-    OString WriteWdpPicture( const ::com::sun::star::uno::Sequence< sal_Int8 >& rPictureData );
+    OString WriteWdpPicture( const OUString& rFileId, const ::com::sun::star::uno::Sequence< sal_Int8 >& rPictureData );
 
     static void ResetCounters();
 
diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx
index 7d81675..9677042 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -619,8 +619,14 @@ css::beans::PropertyValue ArtisticEffectProperties::getEffect()
 
     if( mrOleObjectInfo.maEmbeddedData.hasElements() )
     {
+        css::uno::Sequence< css::beans::PropertyValue > aGraphicSeq( 2 );
+        aGraphicSeq[0].Name = "Id";
+        aGraphicSeq[0].Value = uno::makeAny( mrOleObjectInfo.maProgId );
+        aGraphicSeq[1].Name = "Data";
+        aGraphicSeq[1].Value = uno::makeAny( mrOleObjectInfo.maEmbeddedData );
+
         aSeq[i].Name = "OriginalGraphic";
-        aSeq[i].Value = uno::makeAny( mrOleObjectInfo.maEmbeddedData );
+        aSeq[i].Value = uno::makeAny( aGraphicSeq );
     }
 
     pRet.Name = msName;
diff --git a/oox/source/drawingml/fillpropertiesgroupcontext.cxx b/oox/source/drawingml/fillpropertiesgroupcontext.cxx
index ac8f215..e60f689 100644
--- a/oox/source/drawingml/fillpropertiesgroupcontext.cxx
+++ b/oox/source/drawingml/fillpropertiesgroupcontext.cxx
@@ -339,7 +339,10 @@ ContextHandlerRef ArtisticEffectContext::onCreateContext(
         {
             OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( embed ), OUString() ) );
             if( !aFragmentPath.isEmpty() )
+            {
                 getFilter().importBinaryData( maEffect.mrOleObjectInfo.maEmbeddedData, aFragmentPath );
+                maEffect.mrOleObjectInfo.maProgId = aFragmentPath;
+            }
         }
         return new ArtisticEffectContext( *this, maEffect );
     }
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 1414554..05faa6d 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -120,11 +120,13 @@ namespace drawingml {
 // not thread safe
 int DrawingML::mnImageCounter = 1;
 int DrawingML::mnWdpImageCounter = 1;
+std::map<OUString, OUString> DrawingML::maWdpCache;
 
 void DrawingML::ResetCounters()
 {
     mnImageCounter = 1;
     mnWdpImageCounter = 1;
+    maWdpCache.clear();
 }
 
 bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
@@ -2604,9 +2606,18 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
         }
         else if( aAttrs[i].Name == "OriginalGraphic" )
         {
+            Sequence< PropertyValue > aGraphic;
+            aAttrs[i].Value >>= aGraphic;
             Sequence< sal_Int8 > aGraphicData;
-            aAttrs[i].Value >>= aGraphicData;
-            sRelId = WriteWdpPicture( aGraphicData );
+            OUString sGraphicId;
+            for( sal_Int32 j=0; j < aGraphic.getLength(); ++j )
+            {
+                if( aGraphic[j].Name == "Id" )
+                    aGraphic[j].Value >>= sGraphicId;
+                else if( aGraphic[j].Name == "Data" )
+                    aGraphic[j].Value >>= aGraphicData;
+            }
+            sRelId = WriteWdpPicture( sGraphicId, aGraphicData );
         }
     }
 
@@ -2632,8 +2643,12 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
     mpFS->endElementNS( XML_a, XML_extLst );
 }
 
-OString DrawingML::WriteWdpPicture( const Sequence< sal_Int8 >& rPictureData )
+OString DrawingML::WriteWdpPicture( const OUString& rFileId, const Sequence< sal_Int8 >& rPictureData )
 {
+    std::map<OUString, OUString>::iterator aCachedItem = maWdpCache.find( rFileId );
+    if( aCachedItem != maWdpCache.end() )
+        return OUStringToOString( aCachedItem->second, RTL_TEXTENCODING_UTF8 );
+
     OUString sFileName = "media/hdphoto" + OUString::number( mnWdpImageCounter++ ) + ".wdp";
     uno::Reference< io::XOutputStream > xOutStream =
             mpFB->openFragmentStream( "word/" + sFileName,
@@ -2646,6 +2661,7 @@ OString DrawingML::WriteWdpPicture( const Sequence< sal_Int8 >& rPictureData )
                              "http://schemas.microsoft.com/office/2007/relationships/hdphoto",
                              sFileName, false );
 
+    maWdpCache[rFileId] = sId;
     return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index 0284347..611da2b 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -1378,9 +1378,7 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
     OUString sEmbedId2 = getXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
             "embed");
-    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId2 + "']";
-    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
-    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+    CPPUNIT_ASSERT_EQUAL(sEmbedId1, sEmbedId2);
 
     // 3rd picture: pencil sketch
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
@@ -1395,9 +1393,7 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
     OUString sEmbedId3 = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
             "embed");
-    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId3 + "']";
-    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
-    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+    CPPUNIT_ASSERT_EQUAL(sEmbedId1, sEmbedId3);
 
     // 4th picture: light screen
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
@@ -1425,9 +1421,7 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
     OUString sEmbedId5 = getXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
             "embed");
-    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId5 + "']";
-    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
-    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+    CPPUNIT_ASSERT_EQUAL(sEmbedId1, sEmbedId5);
 
     // 6th picture: photocopy (no attributes)
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
@@ -1437,9 +1431,10 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
     OUString sEmbedId6 = getXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
             "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
             "embed");
-    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId6 + "']";
-    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
-    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+    CPPUNIT_ASSERT_EQUAL(sEmbedId1, sEmbedId6);
+
+    // no redundant wdp files saved
+    CPPUNIT_ASSERT_EQUAL(false, bool(xNameAccess->hasByName("word/media/hdphoto3.wdp")));
 }
 
 DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
commit 2e68a1468c035fc3bb4d02ad0b3187872fe1e67b
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Thu May 22 13:54:42 2014 +0200

    ooxml: Preserve the original picture in artistic effects
    
    When Word applies an artistic effect, it creates two embedded files;
    one contains the bitmap with the effect and the other one contains the
    original bitmap to be able to undo the effect.
    
    This patch reads the original bitmap, stores it in the shape grab bag
    and saves it back to the docx file. Added unit tests too.
    
    TODO: right now, if two effects point to the same original bitmap it
    is stored twice, we should improve this.
    
    Change-Id: Ia72034a257739abe4ffafa0f42b2a912e4bf9436

diff --git a/include/oox/drawingml/fillproperties.hxx b/include/oox/drawingml/fillproperties.hxx
index c588dee..dcf3afb 100644
--- a/include/oox/drawingml/fillproperties.hxx
+++ b/include/oox/drawingml/fillproperties.hxx
@@ -26,6 +26,7 @@
 #include <oox/drawingml/color.hxx>
 #include <oox/helper/helper.hxx>
 #include <oox/drawingml/embeddedwavaudiofile.hxx>
+#include <oox/ole/oleobjecthelper.hxx>
 
 namespace oox {
     class GraphicHelper;
@@ -70,6 +71,7 @@ struct ArtisticEffectProperties
     OUString            msName;
     std::map< OUString, css::uno::Any >
                         maAttribs;
+    ::oox::ole::OleObjectInfo mrOleObjectInfo;  /// The original graphic as embedded object.
 
     bool                isEmpty() const;
 
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 98cc0df..77d54b4 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -82,6 +82,7 @@ public:
 
 private:
     static int mnImageCounter;
+    static int mnWdpImageCounter;
 
     /// To specify where write eg. the images to (like 'ppt', or 'word' - according to the OPC).
     DocumentType meDocumentType;
@@ -177,6 +178,7 @@ public:
     void WriteShapeEffect( const OUString& sName, const css::uno::Sequence< css::beans::PropertyValue >& aEffectProps );
     void WriteShape3DEffects( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
     void WriteArtisticEffect( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
+    OString WriteWdpPicture( const ::com::sun::star::uno::Sequence< sal_Int8 >& rPictureData );
 
     static void ResetCounters();
 
diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx
index a9ca0db..7d81675 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -608,7 +608,7 @@ css::beans::PropertyValue ArtisticEffectProperties::getEffect()
     if( msName.isEmpty() )
         return pRet;
 
-    css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() );
+    css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() + 1 );
     sal_uInt32 i = 0;
     for( std::map< OUString, css::uno::Any >::iterator it = maAttribs.begin(); it != maAttribs.end(); ++it )
     {
@@ -617,6 +617,12 @@ css::beans::PropertyValue ArtisticEffectProperties::getEffect()
         i++;
     }
 
+    if( mrOleObjectInfo.maEmbeddedData.hasElements() )
+    {
+        aSeq[i].Name = "OriginalGraphic";
+        aSeq[i].Value = uno::makeAny( mrOleObjectInfo.maEmbeddedData );
+    }
+
     pRet.Name = msName;
     pRet.Value = css::uno::Any( aSeq );
 
diff --git a/oox/source/drawingml/fillpropertiesgroupcontext.cxx b/oox/source/drawingml/fillpropertiesgroupcontext.cxx
index e7e4142..ac8f215 100644
--- a/oox/source/drawingml/fillpropertiesgroupcontext.cxx
+++ b/oox/source/drawingml/fillpropertiesgroupcontext.cxx
@@ -333,9 +333,18 @@ ContextHandlerRef ArtisticEffectContext::onCreateContext(
         sal_Int32 nElement, const AttributeList& rAttribs )
 {
     // containers
-    if( nElement == OOX_TOKEN( a14, imgLayer ) || nElement == OOX_TOKEN( a14, imgEffect ) )
+    if( nElement == OOX_TOKEN( a14, imgLayer ) )
+    {
+        if( rAttribs.hasAttribute( R_TOKEN( embed ) ) )
+        {
+            OUString aFragmentPath = getFragmentPathFromRelId( rAttribs.getString( R_TOKEN( embed ), OUString() ) );
+            if( !aFragmentPath.isEmpty() )
+                getFilter().importBinaryData( maEffect.mrOleObjectInfo.maEmbeddedData, aFragmentPath );
+        }
+        return new ArtisticEffectContext( *this, maEffect );
+    }
+    if( nElement == OOX_TOKEN( a14, imgEffect ) )
         return new ArtisticEffectContext( *this, maEffect );
-        // TODO: manage r:embed attribute in a14:imgLayer
 
     // effects
     maEffect.msName = ArtisticEffectProperties::getEffectString( nElement );
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 0364764..1414554 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -119,10 +119,12 @@ namespace drawingml {
 
 // not thread safe
 int DrawingML::mnImageCounter = 1;
+int DrawingML::mnWdpImageCounter = 1;
 
 void DrawingML::ResetCounters()
 {
     mnImageCounter = 1;
+    mnWdpImageCounter = 1;
 }
 
 bool DrawingML::GetProperty( Reference< XPropertySet > rXPropSet, const OUString& aName )
@@ -2590,6 +2592,7 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
     Sequence< PropertyValue > aAttrs;
     aEffect.Value >>= aAttrs;
     sax_fastparser::FastAttributeList *aAttrList = mpFS->createAttrList();
+    OString sRelId;
     for( sal_Int32 i=0; i < aAttrs.getLength(); ++i )
     {
         sal_Int32 nToken = ArtisticEffectProperties::getEffectToken( aAttrs[i].Name );
@@ -2599,6 +2602,12 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
             aAttrs[i].Value >>= nVal;
             aAttrList->add( nToken, OString::number( nVal ).getStr() );
         }
+        else if( aAttrs[i].Name == "OriginalGraphic" )
+        {
+            Sequence< sal_Int8 > aGraphicData;
+            aAttrs[i].Value >>= aGraphicData;
+            sRelId = WriteWdpPicture( aGraphicData );
+        }
     }
 
     mpFS->startElementNS( XML_a, XML_extLst, FSEND );
@@ -2608,7 +2617,9 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
     mpFS->startElementNS( XML_a14, XML_imgProps,
                           FSNS( XML_xmlns, XML_a14 ), "http://schemas.microsoft.com/office/drawing/2010/main",
                           FSEND );
-    mpFS->startElementNS( XML_a14, XML_imgLayer, FSEND );
+    mpFS->startElementNS( XML_a14, XML_imgLayer,
+                          FSNS( XML_r, XML_embed), sRelId.getStr(),
+                          FSEND );
     mpFS->startElementNS( XML_a14, XML_imgEffect, FSEND );
 
     sax_fastparser::XFastAttributeListRef xAttrList( aAttrList );
@@ -2621,6 +2632,23 @@ void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
     mpFS->endElementNS( XML_a, XML_extLst );
 }
 
+OString DrawingML::WriteWdpPicture( const Sequence< sal_Int8 >& rPictureData )
+{
+    OUString sFileName = "media/hdphoto" + OUString::number( mnWdpImageCounter++ ) + ".wdp";
+    uno::Reference< io::XOutputStream > xOutStream =
+            mpFB->openFragmentStream( "word/" + sFileName,
+                                      "image/vnd.ms-photo" );
+    OUString sId;
+    xOutStream->writeBytes( rPictureData );
+    xOutStream->closeOutput();
+
+    sId = mpFB->addRelation( mpFS->getOutputStream(),
+                             "http://schemas.microsoft.com/office/2007/relationships/hdphoto",
+                             sFileName, false );
+
+    return OUStringToOString( sId, RTL_TEXTENCODING_UTF8 );
+}
+
 }
 }
 
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index 43f5b6e..0284347 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -1341,9 +1341,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureEffectPreservation, "picture-effects-preserv
 DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artistic-effects-preservation.docx")
 {
     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
-    if (!pXmlDoc)
+    xmlDocPtr pRelsDoc = parseExport("word/_rels/document.xml.rels");
+    if (!pXmlDoc || !pRelsDoc)
        return;
 
+    uno::Reference<packages::zip::XZipFileAccess2> xNameAccess = packages::zip::ZipFileAccess::createWithURL(
+            comphelper::getComponentContext(m_xSFactory), maTempFile.GetURL());
+
     // 1st picture: marker effect
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
             "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
@@ -1354,6 +1358,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
             "a14:artisticMarker",
             "size", "80");
 
+    OUString sEmbedId1 = getXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
+            "embed");
+    OUString sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId1 + "']";
+    OUString sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
+    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+
     // 2nd picture: pencil grayscale
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
             "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
@@ -1364,6 +1375,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
             "a14:artisticPencilGrayscale",
             "pencilSize", "66");
 
+    OUString sEmbedId2 = getXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
+            "embed");
+    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId2 + "']";
+    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
+    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+
     // 3rd picture: pencil sketch
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
             "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
@@ -1374,6 +1392,13 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
             "a14:artisticPencilSketch",
             "pressure", "17");
 
+    OUString sEmbedId3 = getXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
+            "embed");
+    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId3 + "']";
+    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
+    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+
     // 4th picture: light screen
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
             "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
@@ -1384,16 +1409,37 @@ DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artisti
             "a14:artisticLightScreen",
             "gridSize", "1");
 
+    OUString sEmbedId4 = getXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
+            "embed");
+    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId4 + "']";
+    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
+    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+
     // 5th picture: watercolor sponge
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
             "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
             "a14:artisticWatercolorSponge",
             "brushSize", "4");
 
+    OUString sEmbedId5 = getXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
+            "embed");
+    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId5 + "']";
+    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
+    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
+
     // 6th picture: photocopy (no attributes)
     assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
             "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
             "a14:artisticPhotocopy", 1);
+
+    OUString sEmbedId6 = getXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/"
+            "wp:inline/a:graphic/a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer",
+            "embed");
+    sXmlPath = "/rels:Relationships/rels:Relationship[@Id='" + sEmbedId6 + "']";
+    sFile = getXPath(pRelsDoc, OUStringToOString( sXmlPath, RTL_TEXTENCODING_UTF8 ), "Target");
+    CPPUNIT_ASSERT_EQUAL(true, bool(xNameAccess->hasByName("word/" + sFile)));
 }
 
 DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
commit 642a252cf1a2f1d08c4bbfcae15527bb82c7664d
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue May 20 21:05:10 2014 +0200

    ooxml: preserve artistic effects on shapes.
    
    Bitmaps can define artistic effects like in the following example:
    
      <a:blip r:embed="rId5">
        <a:extLst>
          <a:ext uri="{BEBA8EAE-BF5A-486C-A8C5-ECC9F3942E4B}">
            <a14:imgProps
             xmlns:a14="http://schemas.microsoft.com/office/drawing/2010/main">
              <a14:imgLayer r:embed="rId6">
                <a14:imgEffect>
                  <a14:artisticMarker trans="14000" size="80" />
                </a14:imgEffect>
              </a14:imgLayer>
            </a14:imgProps>
          </a:ext>
        </a:extLst>
      </a:blip>
    
    LO core doesn't support them, but I'm preserving them using the shape
    grab bag. Bitmaps must not be transformed to a SwXTextGraphicObject
    so the grab bag of the XShape is not discarded.
    
    Added several Context and Properties objects on the import side to
    traverse and save the relevant tags, and added the corresponding code
    on the export side to extract the grab bag and output the effect back.
    
    Also added a unit test for a selection of artistic effects.
    
    TODO: Word saves the original bitmap as an embedded wdp file so the
    effect can be undone. We must preserve it too and add the reference to
    the a14:imgLayer tag.
    
    Change-Id: I61d427f83e4c8f353eb073da0114cd73ba50ba4b

diff --git a/include/oox/drawingml/fillproperties.hxx b/include/oox/drawingml/fillproperties.hxx
index 447cba2..c588dee 100644
--- a/include/oox/drawingml/fillproperties.hxx
+++ b/include/oox/drawingml/fillproperties.hxx
@@ -65,6 +65,28 @@ struct PatternFillProperties
     void                assignUsed( const PatternFillProperties& rSourceProps );
 };
 
+struct ArtisticEffectProperties
+{
+    OUString            msName;
+    std::map< OUString, css::uno::Any >
+                        maAttribs;
+
+    bool                isEmpty() const;
+
+    /** Returns the struct as a PropertyValue with Name = msName and
+     *  Value = maAttribs as a Sequence< PropertyValue >. */
+    css::beans::PropertyValue getEffect();
+
+    /** Overwrites all members that are explicitly set in rSourceProps. */
+    void                assignUsed( const ArtisticEffectProperties& rSourceProps );
+
+    /** Translate effect tokens to strings. */
+    static OUString     getEffectString( sal_Int32 nToken );
+
+    /** Translate effect strings to tokens. */
+    static sal_Int32    getEffectToken( OUString sName );
+};
+
 struct BlipFillProperties
 {
     ::com::sun::star::uno::Reference< ::com::sun::star::graphic::XGraphic >
@@ -89,6 +111,8 @@ struct BlipFillProperties
     Color               maColorChangeTo;        /// Destination color of color transformation.
     Color               maDuotoneColors[2];     /// Duotone Colors
 
+    ArtisticEffectProperties maEffect;          /// Artistic effect, not supported by core.
+
     /** Overwrites all members that are explicitly set in rSourceProps. */
     void                assignUsed( const BlipFillProperties& rSourceProps );
 };
diff --git a/include/oox/drawingml/fillpropertiesgroupcontext.hxx b/include/oox/drawingml/fillpropertiesgroupcontext.hxx
index bbeed08..aae88df 100644
--- a/include/oox/drawingml/fillpropertiesgroupcontext.hxx
+++ b/include/oox/drawingml/fillpropertiesgroupcontext.hxx
@@ -78,6 +78,48 @@ private:
 
 
 
+/** Context handler that imports a14:imgProps, a14:imgLayer, a14:imgEffect containers
+    and the a14:artistic* effect tags defined in the MS-ODRAWXML extension. */
+class ArtisticEffectContext : public ::oox::core::ContextHandler2
+{
+public:
+    explicit            ArtisticEffectContext(
+                            ::oox::core::ContextHandler2Helper& rParent,
+                            ArtisticEffectProperties& rEffect );
+    virtual             ~ArtisticEffectContext();
+
+    virtual ::oox::core::ContextHandlerRef
+                        onCreateContext(
+                            sal_Int32 nElement,
+                            const ::oox::AttributeList& rAttribs ) SAL_OVERRIDE;
+
+private:
+    ArtisticEffectProperties& maEffect;
+};
+
+
+
+/** Context handler that imports the a:extLst element inside a:blip and its
+    children a:ext, which can contain transformations to the bitmap. */
+class BlipExtensionContext : public ::oox::core::ContextHandler2
+{
+public:
+    explicit            BlipExtensionContext(
+                            ::oox::core::ContextHandler2Helper& rParent,
+                            BlipFillProperties& rBlipProps );
+    virtual             ~BlipExtensionContext();
+
+    virtual ::oox::core::ContextHandlerRef
+                        onCreateContext(
+                            sal_Int32 nElement,
+                            const ::oox::AttributeList& rAttribs ) SAL_OVERRIDE;
+
+private:
+    BlipFillProperties& mrBlipProps;
+};
+
+
+
 /** Context handler that imports the a:duotone element containing the colors
     of a bitmap duotone transformation. */
 class DuotoneContext : public ::oox::core::ContextHandler2
diff --git a/include/oox/export/drawingml.hxx b/include/oox/export/drawingml.hxx
index 86e3d07..98cc0df 100644
--- a/include/oox/export/drawingml.hxx
+++ b/include/oox/export/drawingml.hxx
@@ -176,6 +176,7 @@ public:
     void WriteShapeEffects( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
     void WriteShapeEffect( const OUString& sName, const css::uno::Sequence< css::beans::PropertyValue >& aEffectProps );
     void WriteShape3DEffects( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
+    void WriteArtisticEffect( ::com::sun::star::uno::Reference< ::com::sun::star::beans::XPropertySet > rXPropSet );
 
     static void ResetCounters();
 
diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx
index 6ae078a..a9ca0db 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -205,6 +205,7 @@ void BlipFillProperties::assignUsed( const BlipFillProperties& rSourceProps )
     maColorChangeTo.assignIfUsed( rSourceProps.maColorChangeTo );
     maDuotoneColors[0].assignIfUsed( rSourceProps.maDuotoneColors[0] );
     maDuotoneColors[1].assignIfUsed( rSourceProps.maDuotoneColors[1] );
+    maEffect.assignUsed( rSourceProps.maEffect );
 }
 
 
@@ -596,6 +597,198 @@ void GraphicProperties::pushToPropMap( PropertyMap& rPropMap, const GraphicHelpe
         rPropMap.setProperty(PROP_MediaURL, maAudio.msEmbed);
 }
 
+bool ArtisticEffectProperties::isEmpty() const
+{
+    return msName.isEmpty();
+}
+
+css::beans::PropertyValue ArtisticEffectProperties::getEffect()
+{
+    css::beans::PropertyValue pRet;
+    if( msName.isEmpty() )
+        return pRet;
+
+    css::uno::Sequence< css::beans::PropertyValue > aSeq( maAttribs.size() );
+    sal_uInt32 i = 0;
+    for( std::map< OUString, css::uno::Any >::iterator it = maAttribs.begin(); it != maAttribs.end(); ++it )
+    {
+        aSeq[i].Name = it->first;
+        aSeq[i].Value = it->second;
+        i++;
+    }
+
+    pRet.Name = msName;
+    pRet.Value = css::uno::Any( aSeq );
+
+    return pRet;
+}
+
+void ArtisticEffectProperties::assignUsed( const ArtisticEffectProperties& rSourceProps )
+{
+    if( !rSourceProps.isEmpty() )
+    {
+        msName = rSourceProps.msName;
+        maAttribs = rSourceProps.maAttribs;
+    }
+}
+
+OUString ArtisticEffectProperties::getEffectString( sal_Int32 nToken )
+{
+    switch( nToken )
+    {
+        // effects
+        case OOX_TOKEN( a14, artisticBlur ):                return OUString( "artisticBlur" );
+        case OOX_TOKEN( a14, artisticCement ):              return OUString( "artisticCement" );
+        case OOX_TOKEN( a14, artisticChalkSketch ):         return OUString( "artisticChalkSketch" );
+        case OOX_TOKEN( a14, artisticCrisscrossEtching ):   return OUString( "artisticCrisscrossEtching" );
+        case OOX_TOKEN( a14, artisticCutout ):              return OUString( "artisticCutout" );
+        case OOX_TOKEN( a14, artisticFilmGrain ):           return OUString( "artisticFilmGrain" );
+        case OOX_TOKEN( a14, artisticGlass ):               return OUString( "artisticGlass" );
+        case OOX_TOKEN( a14, artisticGlowDiffused ):        return OUString( "artisticGlowDiffused" );
+        case OOX_TOKEN( a14, artisticGlowEdges ):           return OUString( "artisticGlowEdges" );
+        case OOX_TOKEN( a14, artisticLightScreen ):         return OUString( "artisticLightScreen" );
+        case OOX_TOKEN( a14, artisticLineDrawing ):         return OUString( "artisticLineDrawing" );
+        case OOX_TOKEN( a14, artisticMarker ):              return OUString( "artisticMarker" );
+        case OOX_TOKEN( a14, artisticMosiaicBubbles ):      return OUString( "artisticMosiaicBubbles" );
+        case OOX_TOKEN( a14, artisticPaintStrokes ):        return OUString( "artisticPaintStrokes" );
+        case OOX_TOKEN( a14, artisticPaintBrush ):          return OUString( "artisticPaintBrush" );
+        case OOX_TOKEN( a14, artisticPastelsSmooth ):       return OUString( "artisticPastelsSmooth" );
+        case OOX_TOKEN( a14, artisticPencilGrayscale ):     return OUString( "artisticPencilGrayscale" );
+        case OOX_TOKEN( a14, artisticPencilSketch ):        return OUString( "artisticPencilSketch" );
+        case OOX_TOKEN( a14, artisticPhotocopy ):           return OUString( "artisticPhotocopy" );
+        case OOX_TOKEN( a14, artisticPlasticWrap ):         return OUString( "artisticPlasticWrap" );
+        case OOX_TOKEN( a14, artisticTexturizer ):          return OUString( "artisticTexturizer" );
+        case OOX_TOKEN( a14, artisticWatercolorSponge ):    return OUString( "artisticWatercolorSponge" );
+        case OOX_TOKEN( a14, artisticBrightnessContrast ):  return OUString( "artisticBrightnessContrast" );
+        case OOX_TOKEN( a14, artisticColorTemperature ):    return OUString( "artisticColorTemperature" );
+        case OOX_TOKEN( a14, artisticSaturation ):          return OUString( "artisticSaturation" );
+        case OOX_TOKEN( a14, artisticSharpenSoften ):       return OUString( "artisticSharpenSoften" );
+
+        // attributes
+        case XML_visible:           return OUString( "visible" );
+        case XML_trans:             return OUString( "trans" );
+        case XML_crackSpacing:      return OUString( "crackSpacing" );
+        case XML_pressure:          return OUString( "pressure" );
+        case XML_numberOfShades:    return OUString( "numberOfShades" );
+        case XML_grainSize:         return OUString( "grainSize" );
+        case XML_intensity:         return OUString( "intensity" );
+        case XML_smoothness:        return OUString( "smoothness" );
+        case XML_gridSize:          return OUString( "gridSize" );
+        case XML_pencilSize:        return OUString( "pencilSize" );
+        case XML_size:              return OUString( "size" );
+        case XML_brushSize:         return OUString( "brushSize" );
+        case XML_scaling:           return OUString( "scaling" );
+        case XML_detail:            return OUString( "detail" );
+        case XML_bright:            return OUString( "bright" );
+        case XML_contrast:          return OUString( "contrast" );
+        case XML_colorTemp:         return OUString( "colorTemp" );
+        case XML_sat:               return OUString( "sat" );
+        case XML_amount:            return OUString( "amount" );
+    }
+    SAL_WARN( "oox.drawingml", "ArtisticEffectProperties::getEffectString - unexpected token" );
+    return OUString();
+}
+
+sal_Int32 ArtisticEffectProperties::getEffectToken( OUString sName )
+{
+    // effects
+    if( sName == "artisticBlur" )
+        return XML_artisticBlur;
+    else if( sName == "artisticCement" )
+        return XML_artisticCement;
+    else if( sName == "artisticChalkSketch" )
+        return XML_artisticChalkSketch;
+    else if( sName == "artisticCrisscrossEtching" )
+        return XML_artisticCrisscrossEtching;
+    else if( sName == "artisticCutout" )
+        return XML_artisticCutout;
+    else if( sName == "artisticFilmGrain" )
+        return XML_artisticFilmGrain;
+    else if( sName == "artisticGlass" )
+        return XML_artisticGlass;
+    else if( sName == "artisticGlowDiffused" )
+        return XML_artisticGlowDiffused;
+    else if( sName == "artisticGlowEdges" )
+        return XML_artisticGlowEdges;
+    else if( sName == "artisticLightScreen" )
+        return XML_artisticLightScreen;
+    else if( sName == "artisticLineDrawing" )
+        return XML_artisticLineDrawing;
+    else if( sName == "artisticMarker" )
+        return XML_artisticMarker;
+    else if( sName == "artisticMosiaicBubbles" )
+        return XML_artisticMosiaicBubbles;
+    else if( sName == "artisticPaintStrokes" )
+        return XML_artisticPaintStrokes;
+    else if( sName == "artisticPaintBrush" )
+        return XML_artisticPaintBrush;
+    else if( sName == "artisticPastelsSmooth" )
+        return XML_artisticPastelsSmooth;
+    else if( sName == "artisticPencilGrayscale" )
+        return XML_artisticPencilGrayscale;
+    else if( sName == "artisticPencilSketch" )
+        return XML_artisticPencilSketch;
+    else if( sName == "artisticPhotocopy" )
+        return XML_artisticPhotocopy;
+    else if( sName == "artisticPlasticWrap" )
+        return XML_artisticPlasticWrap;
+    else if( sName == "artisticTexturizer" )
+        return XML_artisticTexturizer;
+    else if( sName == "artisticWatercolorSponge" )
+        return XML_artisticWatercolorSponge;
+    else if( sName == "artisticBrightnessContrast" )
+        return XML_artisticBrightnessContrast;
+    else if( sName == "artisticColorTemperature" )
+        return XML_artisticColorTemperature;
+    else if( sName == "artisticSaturation" )
+        return XML_artisticSaturation;
+    else if( sName == "artisticSharpenSoften" )
+        return XML_artisticSharpenSoften;
+
+    // attributes
+    else if( sName == "visible" )
+        return XML_visible;
+    else if( sName == "trans" )
+        return XML_trans;
+    else if( sName == "crackSpacing" )
+        return XML_crackSpacing;
+    else if( sName == "pressure" )
+        return XML_pressure;
+    else if( sName == "numberOfShades" )
+        return XML_numberOfShades;
+    else if( sName == "grainSize" )
+        return XML_grainSize;
+    else if( sName == "intensity" )
+        return XML_intensity;
+    else if( sName == "smoothness" )
+        return XML_smoothness;
+    else if( sName == "gridSize" )
+        return XML_gridSize;
+    else if( sName == "pencilSize" )
+        return XML_pencilSize;
+    else if( sName == "size" )
+        return XML_size;
+    else if( sName == "brushSize" )
+        return XML_brushSize;
+    else if( sName == "scaling" )
+        return XML_scaling;
+    else if( sName == "detail" )
+        return XML_detail;
+    else if( sName == "bright" )
+        return XML_bright;
+    else if( sName == "contrast" )
+        return XML_contrast;
+    else if( sName == "colorTemp" )
+        return XML_colorTemp;
+    else if( sName == "sat" )
+        return XML_sat;
+    else if( sName == "amount" )
+        return XML_amount;
+
+    SAL_WARN( "oox.drawingml", "ArtisticEffectProperties::getEffectToken - unexpected token name" );
+    return XML_none;
+}
+
 
 
 } // namespace drawingml
diff --git a/oox/source/drawingml/fillpropertiesgroupcontext.cxx b/oox/source/drawingml/fillpropertiesgroupcontext.cxx
index 89fdb26..e7e4142 100644
--- a/oox/source/drawingml/fillpropertiesgroupcontext.cxx
+++ b/oox/source/drawingml/fillpropertiesgroupcontext.cxx
@@ -182,6 +182,9 @@ ContextHandlerRef BlipContext::onCreateContext(
         case A_TOKEN( duotone ):
             return new DuotoneContext( *this, rAttribs, mrBlipProps );
 
+        case A_TOKEN( extLst ):
+            return new BlipExtensionContext( *this, mrBlipProps );
+
         case A_TOKEN( lum ):
             mrBlipProps.moBrightness = rAttribs.getInteger( XML_bright );
             mrBlipProps.moContrast = rAttribs.getInteger( XML_contrast );
@@ -292,6 +295,73 @@ SimpleFillPropertiesContext::~SimpleFillPropertiesContext()
     mrColor = getBestSolidColor();
 }
 
+BlipExtensionContext::BlipExtensionContext( ContextHandler2Helper& rParent, BlipFillProperties& rBlipProps ) :
+    ContextHandler2( rParent ),
+    mrBlipProps( rBlipProps )
+{
+}
+
+BlipExtensionContext::~BlipExtensionContext()
+{
+}
+
+ContextHandlerRef BlipExtensionContext::onCreateContext(
+        sal_Int32 nElement, const AttributeList& )
+{
+    switch( nElement )
+    {
+        case A_TOKEN( ext ):
+            return new BlipExtensionContext( *this, mrBlipProps );
+
+        case OOX_TOKEN( a14, imgProps ):
+            return new ArtisticEffectContext( *this, mrBlipProps.maEffect );
+    }
+    return 0;
+}
+
+ArtisticEffectContext::ArtisticEffectContext( ContextHandler2Helper& rParent, ArtisticEffectProperties& rEffect ) :
+    ContextHandler2( rParent ),
+    maEffect( rEffect )
+{
+}
+
+ArtisticEffectContext::~ArtisticEffectContext()
+{
+}
+
+ContextHandlerRef ArtisticEffectContext::onCreateContext(
+        sal_Int32 nElement, const AttributeList& rAttribs )
+{
+    // containers
+    if( nElement == OOX_TOKEN( a14, imgLayer ) || nElement == OOX_TOKEN( a14, imgEffect ) )
+        return new ArtisticEffectContext( *this, maEffect );
+        // TODO: manage r:embed attribute in a14:imgLayer
+
+    // effects
+    maEffect.msName = ArtisticEffectProperties::getEffectString( nElement );
+    if( maEffect.isEmpty() )
+        return 0;
+
+    // effect attributes
+    sal_Int32 aAttribs[19] = {
+            XML_visible, XML_trans, XML_crackSpacing, XML_pressure, XML_numberOfShades,
+            XML_grainSize, XML_intensity, XML_smoothness, XML_gridSize, XML_pencilSize,
+            XML_size, XML_brushSize, XML_scaling, XML_detail, XML_bright, XML_contrast,
+            XML_colorTemp, XML_sat, XML_amount
+    };
+    for( sal_Int32 i=0; i<19; ++i )
+    {
+        if( rAttribs.hasAttribute( aAttribs[i] ) )
+        {
+            OUString sName = ArtisticEffectProperties::getEffectString( aAttribs[i] );
+            if( !sName.isEmpty() )
+                maEffect.maAttribs[sName] = uno::makeAny( rAttribs.getInteger( aAttribs[i], 0 ) );
+        }
+    }
+
+    return 0;
+}
+
 } // namespace drawingml
 } // namespace oox
 
diff --git a/oox/source/drawingml/shape.cxx b/oox/source/drawingml/shape.cxx
index ca42d4a..8c97b87 100644
--- a/oox/source/drawingml/shape.cxx
+++ b/oox/source/drawingml/shape.cxx
@@ -960,6 +960,11 @@ Reference< XShape > Shape::createAndInsert(
                 PUT_PROP( a3DEffectsGrabBag, 2, "Shape3D", Any( aShape3DEffects ) );
                 putPropertyToGrabBag( "3DEffectProperties", Any( a3DEffectsGrabBag ) );
             }
+
+            // store bitmap artistic effects in the grab bag
+            if( !mpGraphicPropertiesPtr->maBlipProps.maEffect.isEmpty() )
+                putPropertyToGrabBag( "ArtisticEffectProperties",
+                                      Any( mpGraphicPropertiesPtr->maBlipProps.maEffect.getEffect() ) );
         }
 
         else if( mbLockedCanvas )
diff --git a/oox/source/export/drawingml.cxx b/oox/source/export/drawingml.cxx
index 037466a..0364764 100644
--- a/oox/source/export/drawingml.cxx
+++ b/oox/source/export/drawingml.cxx
@@ -23,6 +23,7 @@
 #include "oox/export/drawingml.hxx"
 #include "oox/export/utils.hxx"
 #include <oox/drawingml/color.hxx>
+#include <oox/drawingml/fillproperties.hxx>
 #include <oox/token/tokens.hxx>
 #include <oox/drawingml/drawingmltypes.hxx>
 
@@ -836,6 +837,7 @@ OUString DrawingML::WriteBlip( Reference< XPropertySet > rXPropSet, const OUStri
                    XML_bright, nBright ? I32S( nBright*1000 ) : NULL,
                    XML_contrast, nContrast ? I32S( nContrast*1000 ) : NULL,
                    FSEND );
+    WriteArtisticEffect( rXPropSet );
 
     mpFS->endElementNS( XML_a, XML_blip );
 
@@ -2565,6 +2567,60 @@ void DrawingML::WriteShape3DEffects( Reference< XPropertySet > xPropSet )
     mpFS->endElementNS( XML_a, XML_sp3d );
 }
 
+void DrawingML::WriteArtisticEffect( Reference< XPropertySet > rXPropSet )
+{
+    if( !GetProperty( rXPropSet, "InteropGrabBag" ) )
+        return;
+
+    PropertyValue aEffect;
+    Sequence< PropertyValue > aGrabBag;
+    mAny >>= aGrabBag;
+    for( sal_Int32 i=0; i < aGrabBag.getLength(); ++i )
+    {
+        if( aGrabBag[i].Name == "ArtisticEffectProperties" )
+        {
+            aGrabBag[i].Value >>= aEffect;
+            break;
+        }
+    }
+    sal_Int32 nEffectToken = ArtisticEffectProperties::getEffectToken( aEffect.Name );
+    if( nEffectToken == XML_none )
+        return;
+
+    Sequence< PropertyValue > aAttrs;
+    aEffect.Value >>= aAttrs;
+    sax_fastparser::FastAttributeList *aAttrList = mpFS->createAttrList();
+    for( sal_Int32 i=0; i < aAttrs.getLength(); ++i )
+    {
+        sal_Int32 nToken = ArtisticEffectProperties::getEffectToken( aAttrs[i].Name );
+        if( nToken != XML_none )
+        {
+            sal_Int32 nVal = 0;
+            aAttrs[i].Value >>= nVal;
+            aAttrList->add( nToken, OString::number( nVal ).getStr() );
+        }
+    }
+
+    mpFS->startElementNS( XML_a, XML_extLst, FSEND );
+    mpFS->startElementNS( XML_a, XML_ext,
+                          XML_uri, "{BEBA8EAE-BF5A-486C-A8C5-ECC9F3942E4B}",
+                          FSEND );
+    mpFS->startElementNS( XML_a14, XML_imgProps,
+                          FSNS( XML_xmlns, XML_a14 ), "http://schemas.microsoft.com/office/drawing/2010/main",
+                          FSEND );
+    mpFS->startElementNS( XML_a14, XML_imgLayer, FSEND );
+    mpFS->startElementNS( XML_a14, XML_imgEffect, FSEND );
+
+    sax_fastparser::XFastAttributeListRef xAttrList( aAttrList );
+    mpFS->singleElementNS( XML_a14, nEffectToken, xAttrList );
+
+    mpFS->endElementNS( XML_a14, XML_imgEffect );
+    mpFS->endElementNS( XML_a14, XML_imgLayer );
+    mpFS->endElementNS( XML_a14, XML_imgProps );
+    mpFS->endElementNS( XML_a, XML_ext );
+    mpFS->endElementNS( XML_a, XML_extLst );
+}
+
 }
 }
 
diff --git a/sw/qa/extras/inc/swmodeltestbase.hxx b/sw/qa/extras/inc/swmodeltestbase.hxx
index 2c688fd..da802cf 100644
--- a/sw/qa/extras/inc/swmodeltestbase.hxx
+++ b/sw/qa/extras/inc/swmodeltestbase.hxx
@@ -613,6 +613,7 @@ protected:
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("ContentType"), BAD_CAST("http://schemas.openxmlformats.org/package/2006/content-types"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("lc"), BAD_CAST("http://schemas.openxmlformats.org/drawingml/2006/lockedCanvas"));
         xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("extended-properties"), BAD_CAST("http://schemas.openxmlformats.org/officeDocument/2006/extended-properties"));
+        xmlXPathRegisterNs(pXmlXpathCtx, BAD_CAST("a14"), BAD_CAST("http://schemas.microsoft.com/office/drawing/2010/main"));
     }
 };
 
diff --git a/sw/qa/extras/ooxmlexport/data/picture-artistic-effects-preservation.docx b/sw/qa/extras/ooxmlexport/data/picture-artistic-effects-preservation.docx
new file mode 100644
index 0000000..85f31d8
Binary files /dev/null and b/sw/qa/extras/ooxmlexport/data/picture-artistic-effects-preservation.docx differ
diff --git a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
index 9c49216..43f5b6e 100644
--- a/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
+++ b/sw/qa/extras/ooxmlexport/ooxmlsdrexport.cxx
@@ -1338,6 +1338,64 @@ DECLARE_OOXMLEXPORT_TEST(testPictureEffectPreservation, "picture-effects-preserv
             "rad", "63500");
 }
 
+DECLARE_OOXMLEXPORT_TEST(testPictureArtisticEffectPreservation, "picture-artistic-effects-preservation.docx")
+{
+    xmlDocPtr pXmlDoc = parseExport("word/document.xml");
+    if (!pXmlDoc)
+       return;
+
+    // 1st picture: marker effect
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticMarker",
+            "trans", "14000");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[1]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticMarker",
+            "size", "80");
+
+    // 2nd picture: pencil grayscale
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticPencilGrayscale",
+            "trans", "15000");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[2]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticPencilGrayscale",
+            "pencilSize", "66");
+
+    // 3rd picture: pencil sketch
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticPencilSketch",
+            "trans", "7000");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[3]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticPencilSketch",
+            "pressure", "17");
+
+    // 4th picture: light screen
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticLightScreen",
+            "trans", "13000");
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[4]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticLightScreen",
+            "gridSize", "1");
+
+    // 5th picture: watercolor sponge
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[5]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticWatercolorSponge",
+            "brushSize", "4");
+
+    // 6th picture: photocopy (no attributes)
+    assertXPath(pXmlDoc, "/w:document/w:body/w:p[6]/w:r/mc:AlternateContent/mc:Choice/w:drawing/wp:inline/a:graphic/"
+            "a:graphicData/pic:pic/pic:blipFill/a:blip/a:extLst/a:ext/a14:imgProps/a14:imgLayer/a14:imgEffect/"
+            "a14:artisticPhotocopy", 1);
+}
+
 DECLARE_OOXMLEXPORT_TEST(fdo77719, "fdo77719.docx")
 {
     xmlDocPtr pXmlDoc = parseExport("word/document.xml");
diff --git a/writerfilter/source/dmapper/GraphicImport.cxx b/writerfilter/source/dmapper/GraphicImport.cxx
index 1d19df0..11f5a73 100644
--- a/writerfilter/source/dmapper/GraphicImport.cxx
+++ b/writerfilter/source/dmapper/GraphicImport.cxx
@@ -650,7 +650,8 @@ void GraphicImport::lcl_attribute(Id nName, Value& rValue)
                         {
                             // if the shape contains effects in the grab bag, we should not transform it
                             // in a XTextContent so those effects can be preserved
-                            if( aGrabBag[i].Name == "EffectProperties" || aGrabBag[i].Name == "3DEffectProperties" )
+                            if( aGrabBag[i].Name == "EffectProperties" || aGrabBag[i].Name == "3DEffectProperties" ||
+                                    aGrabBag[i].Name == "ArtisticEffectProperties" )
                                 bContainsEffects = true;
                         }
 
commit 21d4cfe19e2796ebf89c408e292c4473924b2bc4
Author: Jacobo Aragunde Pérez <jaragunde at igalia.com>
Date:   Tue May 20 20:11:13 2014 +0200

    oox, writerfilter: add a14 namespace and tokens
    
    Added the artistic effects defined in the MS-ODRAWXML extension. Ref:
    http://msdn.microsoft.com/en-us/library/dd905216(v=office.12).aspx
    
    Change-Id: I24c5e5bbe569f160d300a7a7293ca047cb7a1b88.

diff --git a/oox/source/token/namespaces-strict.txt b/oox/source/token/namespaces-strict.txt
index 9549483..d49be5e 100644
--- a/oox/source/token/namespaces-strict.txt
+++ b/oox/source/token/namespaces-strict.txt
@@ -75,6 +75,7 @@ wps                     http://schemas.microsoft.com/office/word/2010/wordproces
 wpg                     http://schemas.microsoft.com/office/word/2010/wordprocessingGroup
 wp14                    http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing
 w14                     http://schemas.microsoft.com/office/word/2010/wordml
+a14                     http://schemas.microsoft.com/office/drawingml/2010/main
 
 # extlst namespaces
 
diff --git a/oox/source/token/namespaces.txt b/oox/source/token/namespaces.txt
index 6f0bee2..63c0ce6 100644
--- a/oox/source/token/namespaces.txt
+++ b/oox/source/token/namespaces.txt
@@ -75,6 +75,7 @@ wps                     http://schemas.microsoft.com/office/word/2010/wordproces
 wpg                     http://schemas.microsoft.com/office/word/2010/wordprocessingGroup
 wp14                    http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing
 w14                     http://schemas.microsoft.com/office/word/2010/wordml
+a14                     http://schemas.microsoft.com/office/drawingml/2010/main
 
 # extlst namespaces
 
diff --git a/oox/source/token/tokens.txt b/oox/source/token/tokens.txt
index bab7cf1..1bdca90 100644
--- a/oox/source/token/tokens.txt
+++ b/oox/source/token/tokens.txt
@@ -414,6 +414,7 @@ YZ
 Year
 YearAccessed
 ZX
+a14
 a
 aa
 above
@@ -560,6 +561,7 @@ always
 alwaysMergeEmptyNamespace
 alwaysShow
 alwaysShowPlaceholderText
+amount
 amt
 anchor
 anchorCtr
@@ -640,6 +642,33 @@ array
 arrow
 arrowok
 artDeco
+artisticBlur
+artisticCement
+artisticChalkSketch
+artisticCrisscrossEtching
+artisticCutout
+artisticFilmGrain
+artisticGlass
+artisticGlowDiffused
+artisticGlowEdges
+artisticLightScreen
+artisticLineDrawing
+artisticMarker
+artisticMosiaicBubbles
+artisticPaintStrokes
+artisticPaintBrush
+artisticPastelsSmooth
+artisticPencilGrayscale
+artisticPencilSketch
+artisticPhotocopy
+artisticPlasticWrap
+artisticTexturizer
+artisticWatercolorSponge
+artisticBackgroundRemoval
+artisticBrightnessContrast
+artisticColorTemperature
+artisticSaturation
+artisticSharpenSoften
 asDisplayed
 ascending
 ascendingAlpha
@@ -947,6 +976,7 @@ brkBinSub
 brown
 browse
 browser
+brushSize
 bstr
 btLr
 btnFace
@@ -1257,6 +1287,7 @@ color2
 colorFilter
 colorId
 colorScale
+colorTemp
 colormenu
 colormode
 colormru
@@ -1390,6 +1421,7 @@ cover
 coverPg
 cp
 cr
+crackSpacing
 crashSave
 crazyMaze
 created
@@ -1729,6 +1761,7 @@ destId
 destOrd
 destination
 destinationFile
+detail
 detectmouseclick
 dgm
 dgmbasetextscale
@@ -2430,6 +2463,7 @@ gradientInactiveCaption
 gradientRadial
 gradientUnscaled
 gradientshapeok
+grainSize
 gramEnd
 gramStart
 grammar
@@ -2471,6 +2505,7 @@ gridDropZones
 gridLegend
 gridLines
 gridLinesSet
+gridSize
 gridSpacing
 gridSpan
 group
@@ -2732,7 +2767,10 @@ imagedata
 imagesize
 imeMode
 img
+imgEffect
 imgH
+imgLayer
+imgProps
 imgSz
 imgW
 immersive
@@ -2795,6 +2833,7 @@ intLim
 intVal
 integer
 integrated
+intensity
 interSp
 interactiveSeq
 intercept
@@ -3568,6 +3607,7 @@ numStyleLink
 numTab
 number
 numberInDash
+numberOfShades
 numberStoredAsText
 numbering
 numberingChange
@@ -3839,6 +3879,7 @@ pctPosVOffset
 pctWidth
 peachPuff
 penClr
+pencilSize
 pencils
 pentagon
 people
@@ -4002,6 +4043,7 @@ preserveSortFilterLayout
 presetClass
 presetID
 presetSubtype
+pressure
 prev
 prevAc
 prevCondLst
@@ -4710,6 +4752,7 @@ smartTags
 smileyFace
 smooth
 smoothMarker
+smoothness
 smtClean
 smtId
 snake
diff --git a/writerfilter/CustomTarget_source.mk b/writerfilter/CustomTarget_source.mk
index 789a627..249ebca 100644
--- a/writerfilter/CustomTarget_source.mk
+++ b/writerfilter/CustomTarget_source.mk
@@ -41,6 +41,7 @@ writerfilter_OOXMLNAMESPACES= \
 	mce \
 	wp14 \
 	w14 \
+	a14 \
 	wml
 
 writerfilter_ALL = \
diff --git a/writerfilter/source/ooxml/model.xml b/writerfilter/source/ooxml/model.xml
index 6f43179..36a37f6 100644
--- a/writerfilter/source/ooxml/model.xml
+++ b/writerfilter/source/ooxml/model.xml
@@ -46,6 +46,7 @@
   <namespace-alias name="http://schemas.openxmlformats.org/markup-compatibility/2006" alias="mce" id="mce"/>
   <namespace-alias name="http://schemas.microsoft.com/office/word/2010/wordprocessingDrawing" alias="wp14" id="wp14"/>
   <namespace-alias name="http://schemas.microsoft.com/office/word/2010/wordml" alias="w14" id="w14"/>
+  <namespace-alias name="http://schemas.microsoft.com/office/drawing/2010/main" alias="a14" id="a14"/>
   <namespace-alias name="http://sprm" alias="sprm" id="sprm"/>
   <token tokenid="ooxml:shape"/>
   <token tokenid="ooxml:token"/>
@@ -6793,6 +6794,417 @@
       <element name="cntxtAlts" tokenid="ooxml:cntxtAlts_cntxtAlts"/>
     </resource>
   </namespace>
+  <namespace name="a14" file="a14.rng">
+    <grammar xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2006/xpath-functions" xmlns="http://relaxng.org/ns/structure/1.0" ns="http://schemas.microsoft.com/office/drawingml/2010/main" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
+      <!-- Simple types -->
+      <define name="ST_ArtisticEffectParam10">
+        <data type="integer">
+          <xs:documentation>Integer value (0 to 10)</xs:documentation>
+          <param name="minInclusive">0</param>
+          <param name="maxInclusive">10</param>
+        </data>
+      </define>
+      <define name="ST_ArtisticEffectParam100">
+        <data type="integer">
+          <xs:documentation>Integer value (0 to 100)</xs:documentation>
+          <param name="minInclusive">0</param>
+          <param name="maxInclusive">100</param>
+        </data>
+      </define>
+      <define name="ST_ArtisticEffectParam4">
+        <data type="integer">
+          <xs:documentation>Integer value (0 to 4)</xs:documentation>
+          <param name="minInclusive">0</param>
+          <param name="maxInclusive">4</param>
+        </data>
+      </define>
+      <define name="ST_ArtisticEffectParam6">
+        <data type="integer">
+          <xs:documentation>Integer value (0 to 6)</xs:documentation>
+          <param name="minInclusive">0</param>
+          <param name="maxInclusive">6</param>
+        </data>
+      </define>
+      <define name="ST_ColorTemperature">
+        <data type="integer">
+          <xs:documentation>Integer value (1500 to 11500)</xs:documentation>
+          <param name="minInclusive">1500</param>
+          <param name="maxInclusive">11500</param>
+        </data>
+      </define>
+      <define name="ST_LegacySpreadsheetColorIndex">
+        <data type="integer">
+          <xs:documentation>Integer value (0 to 80)</xs:documentation>
+          <param name="minInclusive">0</param>
+          <param name="maxInclusive">80</param>
+        </data>
+      </define>
+      <define name="ST_SaturationAmount">
+        <data type="integer">
+          <xs:documentation>Integer value (0 to 400000)</xs:documentation>
+          <param name="minInclusive">0</param>
+          <param name="maxInclusive">400000</param>
+        </data>
+      </define>
+
+      <!-- Complex types for effects -->
+      <define name="CT_PictureEffectBlur">
+        <optional>
+          <attribute name="visible">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectCement">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="crackSpacing">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectChalkSketch">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="pressure">
+            <ref name="ST_ArtisticEffectParam4"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectCrisscrossEtching">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="pressure">
+            <ref name="ST_ArtisticEffectParam4"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectCutout">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="numberOfShades">
+            <ref name="ST_ArtisticEffectParam6"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectFilmGrain">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="grainSize">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectGlass">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="scaling">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectGlowDiffused">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="intensity">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectGlowEdges">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="smoothness">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectLightScreen">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="gridSize">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectLineDrawing">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="pencilSize">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectMarker">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="size">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectMosiaicBubbles">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="pressure">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPaintStrokes">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="intensity">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPaintBrush">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="brushSize">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPastelsSmooth">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="scaling">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPencilGrayscale">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="pencilSize">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPencilSketch">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="pressure">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPhotocopy">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="detail">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectPlasticWrap">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="smoothness">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectTexturizer">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="scaling">
+            <ref name="ST_ArtisticEffectParam100"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectWatercolorSponge">
+        <optional>
+          <attribute name="trans">
+            <ref name="a:ST_PositiveFixedPercentage"/>
+          </attribute>
+          <attribute name="brushSize">
+            <ref name="ST_ArtisticEffectParam10"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectBrightnessContrast">
+        <optional>
+          <attribute name="bright">
+            <ref name="a:ST_FixedPercentage"/>
+          </attribute>
+          <attribute name="contrast">
+            <ref name="a:ST_FixedPercentage"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectColorTemperature">
+        <optional>
+          <attribute name="colorTemp">
+            <ref name="ST_ColorTemperature"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectSaturation">
+        <optional>
+          <attribute name="sat">
+            <ref name="ST_SaturationAmount"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureEffectSharpenSoften">
+        <optional>
+          <attribute name="amount">
+            <ref name="ST_FixedPercentage"/>
+          </attribute>
+        </optional>
+      </define>
+
+      <!-- Complex types for containers -->
+      <define name="CT_PictureEffect">
+        <choice>
+          <element name="artisticBlur">
+            <ref name="CT_PictureEffectBlur"/>
+          </element>
+          <element name="artisticCement">
+            <ref name="CT_PictureEffectCement"/>
+          </element>
+          <element name="artisticChalkSketch">
+            <ref name="CT_PictureEffectChalkSketch"/>
+          </element>
+          <element name="artisticCrisscrossEtching">
+            <ref name="CT_PictureEffectCrisscrossEtching"/>
+          </element>
+          <element name="artisticCutout">
+            <ref name="CT_PictureEffectCutout"/>
+          </element>
+          <element name="artisticFilmGrain">
+            <ref name="CT_PictureEffectFilmGrain"/>
+          </element>
+          <element name="artisticGlass">
+            <ref name="CT_PictureEffectGlass"/>
+          </element>
+          <element name="artisticGlowDiffused">
+            <ref name="CT_PictureEffectGlowDiffused"/>
+          </element>
+          <element name="artisticGlowEdges">
+            <ref name="CT_PictureEffectGlowEdges"/>
+          </element>
+          <element name="artisticLightScreen">
+            <ref name="CT_PictureEffectLightScreen"/>
+          </element>
+          <element name="artisticLineDrawing">
+            <ref name="CT_PictureEffectLineDrawing"/>
+          </element>
+          <element name="artisticMarker">
+            <ref name="CT_PictureEffectMarker"/>
+          </element>
+          <element name="artisticMosiaicBubbles">
+            <ref name="CT_PictureEffectMosiaicBubbles"/>
+          </element>
+          <element name="artisticPaintStrokes">
+            <ref name="CT_PictureEffectPaintStrokes"/>
+          </element>
+          <element name="artisticPaintBrush">
+            <ref name="CT_PictureEffectPaintBrush"/>
+          </element>
+          <element name="artisticPastelsSmooth">
+            <ref name="CT_PictureEffectPastelsSmooth"/>
+          </element>
+          <element name="artisticPencilGrayscale">
+            <ref name="CT_PictureEffectPencilGrayscale"/>
+          </element>
+          <element name="artisticPencilSketch">
+            <ref name="CT_PictureEffectPencilSketch"/>
+          </element>
+          <element name="artisticPhotocopy">
+            <ref name="CT_PictureEffectPhotocopy"/>
+          </element>
+          <element name="artisticPlasticWrap">
+            <ref name="CT_PictureEffectPlasticWrap"/>
+          </element>
+          <element name="artisticTexturizer">
+            <ref name="CT_PictureEffectTexturizer"/>
+          </element>
+          <element name="artisticWatercolorSponge">
+            <ref name="CT_PictureEffectWatercolorSponge"/>
+          </element>
+          <element name="artisticBrightnessContrast">
+            <ref name="CT_PictureEffectBrightnessContrast"/>
+          </element>
+          <element name="artisticColorTemperature">
+            <ref name="CT_PictureEffectColorTemperature"/>
+          </element>
+          <element name="artisticSaturation">
+            <ref name="CT_PictureEffectSaturation"/>
+          </element>
+          <element name="artisticSharpenSoften">
+            <ref name="CT_PictureEffectSharpenSoften"/>
+          </element>
+        </choice>
+        <optional>
+          <attribute name="visible">
+            <data type="boolean"/>
+          </attribute>
+        </optional>
+      </define>
+      <define name="CT_PictureLayer">
+        <zeroOrMore>
+          <element name="imgEffect">
+            <ref name="CT_PictureEffect"/>
+          </element>
+        </zeroOrMore>
+        <attribute name="r:embed">
+          <text/>
+          <xs:documentation>Embedded Image Relationship Target</xs:documentation>
+        </attribute>
+      </define>
+      <define name="CT_Photo">
+        <zeroOrMore>
+          <element name="imgLayer">
+            <ref name="CT_PictureLayer"/>
+          </element>
+        </zeroOrMore>
+      </define>
+    </grammar>
+  </namespace>
   <namespace name="dml-shapeGeometry" file="dml-shapeGeometry.rng" todo="ignore">
     <grammar xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:fn="http://www.w3.org/2006/xpath-functions" xmlns="http://relaxng.org/ns/structure/1.0" ns="http://schemas.openxmlformats.org/drawingml/2006/main" datatypeLibrary="http://www.w3.org/2001/XMLSchema-datatypes">
       <!-- ISO RELAX NG Schema -->


More information about the Libreoffice-commits mailing list