Kaydet (Commit) 642a252c authored tarafından Jacobo Aragunde Pérez's avatar Jacobo Aragunde Pérez

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
üst 21d4cfe1
......@@ -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 );
};
......
......@@ -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
......
......@@ -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();
......
......@@ -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
......
......@@ -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
......
......@@ -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 )
......
......@@ -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 );
}
}
}
......
......@@ -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"));
}
};
......
......@@ -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");
......
......@@ -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;
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment