include/docmodel/theme/FormatScheme.hxx                 |   67 +++++++
 oox/inc/drawingml/misccontexts.hxx                      |   25 +-
 oox/source/drawingml/graphicshapecontext.cxx            |    2 
 oox/source/drawingml/misccontexts.cxx                   |  144 +++++++++++++---
 oox/source/drawingml/textparagraphpropertiescontext.cxx |    2 
 5 files changed, 201 insertions(+), 39 deletions(-)

New commits:
commit 0ffa50031eb33500a3530ece76ea32d15864f345
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Tue Feb 28 18:09:46 2023 +0900
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Wed Apr 12 06:01:53 2023 +0200

    oox: add model::BlipFilll and import blip (graphic) fill elements
    
    Change-Id: I610b732b1fd4eebcfcc55acb6f04a8acf84f92b7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147954
    Tested-by: Jenkins
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/include/docmodel/theme/FormatScheme.hxx 
b/include/docmodel/theme/FormatScheme.hxx
index fea08ee50d1e..cd3c5491a62a 100644
--- a/include/docmodel/theme/FormatScheme.hxx
+++ b/include/docmodel/theme/FormatScheme.hxx
@@ -13,6 +13,7 @@
 #include <docmodel/dllapi.h>
 #include <tools/color.hxx>
 #include <docmodel/theme/ThemeColor.hxx>
+#include <com/sun/star/graphic/XGraphic.hpp>
 
 namespace model
 {
@@ -277,6 +278,72 @@ public:
     }
 };
 
+enum class BitmapMode
+{
+    Unused,
+    Tile,
+    Stretch,
+};
+
+enum class FlipMode
+{
+    None,
+    X,
+    Y,
+    XY
+};
+
+enum class RectangleAlignment
+{
+    TopLeft,
+    Top,
+    TopRight,
+    Left,
+    Center,
+    Right,
+    BottomLeft,
+    Bottom,
+    BottomRight
+};
+
+enum class ColorEffectType
+{
+    None,
+    BiLevel,
+    Grayscale,
+    ColorChange
+};
+
+class DOCMODEL_DLLPUBLIC BlipFill : public Fill
+{
+public:
+    bool mbRotateWithShape = false;
+    RelativeRectangle maClipRectangle;
+    RelativeRectangle maFillRectangle;
+    BitmapMode meMode = BitmapMode::Unused;
+
+    sal_Int32 mnTileOffsetX = 0;
+    sal_Int32 mnTileOffsetY = 0;
+    sal_Int32 mnTileScaleX = 0;
+    sal_Int32 mnTileScaleY = 0;
+    FlipMode meTileFlipMode = FlipMode::None;
+    RectangleAlignment meTileAlignment = RectangleAlignment::TopLeft;
+
+    css::uno::Reference<css::graphic::XGraphic> mxGraphic;
+
+    ColorEffectType meColorEffectType = ColorEffectType::None;
+
+    sal_Int32 mnBiLevelThreshold = 0;
+    ColorDefinition maColorFrom;
+    ColorDefinition maColorTo;
+    bool mbUseAlpha = false;
+
+    BlipFill()
+        : Fill(FillType::Blip)
+    {
+    }
+};
+
 // Format Scheme
 
 class DOCMODEL_DLLPUBLIC FillStyle
diff --git a/oox/inc/drawingml/misccontexts.hxx 
b/oox/inc/drawingml/misccontexts.hxx
index 10977df87d99..c79816282ae7 100644
--- a/oox/inc/drawingml/misccontexts.hxx
+++ b/oox/inc/drawingml/misccontexts.hxx
@@ -141,11 +141,9 @@ private:
 class ColorChangeContext final : public ::oox::core::ContextHandler2
 {
 public:
-    explicit            ColorChangeContext(
-                            ::oox::core::ContextHandler2Helper const & rParent,
-                            const ::oox::AttributeList& rAttribs,
-                            BlipFillProperties& rBlipProps );
-    virtual             ~ColorChangeContext() override;
+    explicit ColorChangeContext(::oox::core::ContextHandler2Helper const & 
rParent, const ::oox::AttributeList& rAttribs,
+                            BlipFillProperties& rBlipProps, model::BlipFill* 
pBlipFill);
+    virtual ~ColorChangeContext() override;
 
     virtual ::oox::core::ContextHandlerRef
                         onCreateContext(
@@ -153,8 +151,9 @@ public:
                             const ::oox::AttributeList& rAttribs ) override;
 
 private:
+    model::BlipFill* mpBlipFill;
     BlipFillProperties& mrBlipProps;
-    bool                mbUseAlpha;
+    bool mbUseAlpha;
 };
 
 /** Context handler that imports the a:blip element containing the fill bitmap
@@ -162,10 +161,8 @@ private:
 class BlipContext final : public ::oox::core::ContextHandler2
 {
 public:
-    explicit            BlipContext(
-                            ::oox::core::ContextHandler2Helper const & rParent,
-                            const ::oox::AttributeList& rAttribs,
-                            BlipFillProperties& rBlipProps );
+    explicit BlipContext(::oox::core::ContextHandler2Helper const & rParent, 
const ::oox::AttributeList& rAttribs,
+                        BlipFillProperties& rBlipProps, model::BlipFill* 
pBlipFill);
 
     virtual ::oox::core::ContextHandlerRef
                         onCreateContext(
@@ -173,6 +170,7 @@ public:
                             const ::oox::AttributeList& rAttribs ) override;
 
 private:
+    model::BlipFill* mpBlipFill;
     BlipFillProperties& mrBlipProps;
 };
 
@@ -180,10 +178,8 @@ private:
 class BlipFillContext final : public ::oox::core::ContextHandler2
 {
 public:
-    explicit            BlipFillContext(
-                            ::oox::core::ContextHandler2Helper const & rParent,
-                            const ::oox::AttributeList& rAttribs,
-                            BlipFillProperties& rBlipProps );
+    explicit BlipFillContext(::oox::core::ContextHandler2Helper const & 
rParent, const ::oox::AttributeList& rAttribs,
+                            BlipFillProperties& rBlipProps, model::BlipFill* 
pBlipFill);
 
     virtual ::oox::core::ContextHandlerRef
                         onCreateContext(
@@ -191,6 +187,7 @@ public:
                             const ::oox::AttributeList& rAttribs ) override;
 
 private:
+    model::BlipFill* mpBlipFill;
     BlipFillProperties& mrBlipProps;
 };
 
diff --git a/oox/source/drawingml/graphicshapecontext.cxx 
b/oox/source/drawingml/graphicshapecontext.cxx
index 0f96d0a92d63..4fb6af74e131 100644
--- a/oox/source/drawingml/graphicshapecontext.cxx
+++ b/oox/source/drawingml/graphicshapecontext.cxx
@@ -80,7 +80,7 @@ ContextHandlerRef GraphicShapeContext::onCreateContext( 
sal_Int32 aElementToken,
     case XML_xfrm:
         return new Transform2DContext( *this, rAttribs, *mpShapePtr );
     case XML_blipFill:
-        return new BlipFillContext( *this, rAttribs, 
mpShapePtr->getGraphicProperties().maBlipProps );
+        return new BlipFillContext(*this, rAttribs, 
mpShapePtr->getGraphicProperties().maBlipProps, nullptr);
     case XML_wavAudioFile:
         {
             OUString const path(getEmbeddedWAVAudioFile(getRelations(), 
rAttribs));
diff --git a/oox/source/drawingml/misccontexts.cxx 
b/oox/source/drawingml/misccontexts.cxx
index 20cb60e953de..3005974bdf37 100644
--- a/oox/source/drawingml/misccontexts.cxx
+++ b/oox/source/drawingml/misccontexts.cxx
@@ -243,13 +243,19 @@ ContextHandlerRef PatternFillContext::onCreateContext(
 }
 
 ColorChangeContext::ColorChangeContext( ContextHandler2Helper const & rParent,
-        const AttributeList& rAttribs, BlipFillProperties& rBlipProps ) :
-    ContextHandler2( rParent ),
-    mrBlipProps( rBlipProps )
+        const AttributeList& rAttribs, BlipFillProperties& rBlipProps, 
model::BlipFill* pBlipFill)
+    : ContextHandler2(rParent)
+    , mpBlipFill(pBlipFill)
+    , mrBlipProps(rBlipProps)
 {
     mrBlipProps.maColorChangeFrom.setUnused();
     mrBlipProps.maColorChangeTo.setUnused();
     mbUseAlpha = rAttribs.getBool( XML_useA, true );
+    if (mpBlipFill)
+    {
+        mpBlipFill->meColorEffectType = model::ColorEffectType::ColorChange;
+        mpBlipFill->mbUseAlpha = mbUseAlpha;
+    }
 }
 
 ColorChangeContext::~ColorChangeContext()
@@ -261,27 +267,38 @@ ColorChangeContext::~ColorChangeContext()
 ContextHandlerRef ColorChangeContext::onCreateContext(
         sal_Int32 nElement, const AttributeList& )
 {
-    switch( nElement )
+    model::ColorDefinition* pColorDefinition = nullptr;
+    switch (nElement)
     {
-        case A_TOKEN( clrFrom ):
-            return new ColorContext(*this, mrBlipProps.maColorChangeFrom, 
nullptr);
-        case A_TOKEN( clrTo ):
-            return new ColorContext(*this, mrBlipProps.maColorChangeTo, 
nullptr);
+        case A_TOKEN(clrFrom):
+            if (mpBlipFill)
+                pColorDefinition = &mpBlipFill->maColorFrom;
+            return new ColorContext(*this, mrBlipProps.maColorChangeFrom, 
pColorDefinition);
+        case A_TOKEN(clrTo):
+            if (mpBlipFill)
+                pColorDefinition = &mpBlipFill->maColorTo;
+            return new ColorContext(*this, mrBlipProps.maColorChangeTo, 
pColorDefinition);
     }
     return nullptr;
 }
 
-BlipContext::BlipContext( ContextHandler2Helper const & rParent,
-        const AttributeList& rAttribs, BlipFillProperties& rBlipProps ) :
-    ContextHandler2( rParent ),
-    mrBlipProps( rBlipProps )
+BlipContext::BlipContext(ContextHandler2Helper const & rParent, const 
AttributeList& rAttribs,
+        BlipFillProperties& rBlipProps, model::BlipFill* pBlipFill)
+    : ContextHandler2(rParent)
+    , mpBlipFill(pBlipFill)
+    , mrBlipProps(rBlipProps)
 {
     if( rAttribs.hasAttribute( R_TOKEN( embed ) ) )
     {
         // internal picture URL
         OUString aFragmentPath = getFragmentPathFromRelId( 
rAttribs.getStringDefaulted( R_TOKEN( embed )) );
         if (!aFragmentPath.isEmpty())
-            mrBlipProps.mxFillGraphic = 
getFilter().getGraphicHelper().importEmbeddedGraphic( aFragmentPath );
+        {
+            auto xGraphic = 
getFilter().getGraphicHelper().importEmbeddedGraphic(aFragmentPath);
+            mrBlipProps.mxFillGraphic = xGraphic;
+            if (mpBlipFill)
+                mpBlipFill->mxGraphic = xGraphic;
+        }
     }
     else if( rAttribs.hasAttribute( R_TOKEN( link ) ) )
     {
@@ -294,7 +311,10 @@ BlipContext::BlipContext( ContextHandler2Helper const & 
rParent,
         OUString aTargetLink = getFilter().getAbsoluteUrl( 
getRelations().getExternalTargetFromRelId( aRelId ) );
         GraphicExternalLink aLink(aTargetLink);
         Graphic aGraphic(aLink);
-        mrBlipProps.mxFillGraphic = aGraphic.GetXGraphic();
+        auto xGraphic = aGraphic.GetXGraphic();
+        mrBlipProps.mxFillGraphic = xGraphic;
+        if (mpBlipFill)
+            mpBlipFill->mxGraphic = xGraphic;
     }
 }
 
@@ -304,17 +324,32 @@ ContextHandlerRef BlipContext::onCreateContext(
     switch( nElement )
     {
         case A_TOKEN( biLevel ):
+        {
             mrBlipProps.moBiLevelThreshold = rAttribs.getInteger( XML_thresh );
             mrBlipProps.moColorEffect = getBaseToken(nElement);
-            break;
+            if (mpBlipFill)
+            {
+                mpBlipFill->meColorEffectType = 
model::ColorEffectType::BiLevel;
+                mpBlipFill->mnBiLevelThreshold = 
rAttribs.getInteger(XML_thresh, 0);
+            }
+        }
+        break;
 
         case A_TOKEN( grayscl ):
+        {
             mrBlipProps.moColorEffect = getBaseToken( nElement );
+            if (mpBlipFill)
+            {
+                mpBlipFill->meColorEffectType = 
model::ColorEffectType::Grayscale;
+            }
+        }
         break;
 
         case A_TOKEN( clrChange ):
-            return new ColorChangeContext( *this, rAttribs, mrBlipProps );
-
+        {
+            return new ColorChangeContext(*this, rAttribs, mrBlipProps, 
mpBlipFill);
+        }
+        break;
         case A_TOKEN( duotone ):
             return new DuotoneContext( *this, mrBlipProps );
 
@@ -322,11 +357,15 @@ ContextHandlerRef BlipContext::onCreateContext(
             return new BlipExtensionContext( *this, mrBlipProps );
 
         case A_TOKEN( lum ):
+        {
             mrBlipProps.moBrightness = rAttribs.getInteger( XML_bright );
             mrBlipProps.moContrast = rAttribs.getInteger( XML_contrast );
+        }
         break;
         case A_TOKEN( alphaModFix ):
+        {
             mrBlipProps.moAlphaModFix = rAttribs.getInteger(XML_amt);
+        }
         break;
     }
     return nullptr;
@@ -354,12 +393,15 @@ DuotoneContext::~DuotoneContext()
     return nullptr;
 }
 
-BlipFillContext::BlipFillContext( ContextHandler2Helper const & rParent,
-        const AttributeList& rAttribs, BlipFillProperties& rBlipProps ) :
-    ContextHandler2( rParent ),
-    mrBlipProps( rBlipProps )
+BlipFillContext::BlipFillContext(ContextHandler2Helper const & rParent, const 
AttributeList& rAttribs,
+        BlipFillProperties& rBlipProps, model::BlipFill* pBlipFill)
+    : ContextHandler2( rParent )
+    , mpBlipFill(pBlipFill)
+    , mrBlipProps(rBlipProps)
 {
     mrBlipProps.moRotateWithShape = rAttribs.getBool( XML_rotWithShape );
+    if (mpBlipFill)
+        mpBlipFill->mbRotateWithShape = rAttribs.getBool(XML_rotWithShape, 
false);
 }
 
 ContextHandlerRef BlipFillContext::onCreateContext(
@@ -368,13 +410,19 @@ ContextHandlerRef BlipFillContext::onCreateContext(
     switch( nElement )
     {
         case A_TOKEN( blip ):
-            return new BlipContext( *this, rAttribs, mrBlipProps );
+            return new BlipContext(*this, rAttribs, mrBlipProps, mpBlipFill);
 
         case A_TOKEN( srcRect ):
+        {
             mrBlipProps.moClipRect = GetRelativeRect( 
rAttribs.getFastAttributeList() );
+
+            if (mpBlipFill)
+                fillRelativeRectangle(mpBlipFill->maClipRectangle, 
rAttribs.getFastAttributeList());
+        }
         break;
 
         case A_TOKEN( tile ):
+        {
             mrBlipProps.moBitmapMode = getBaseToken( nElement );
             mrBlipProps.moTileOffsetX = rAttribs.getInteger( XML_tx );
             mrBlipProps.moTileOffsetY = rAttribs.getInteger( XML_ty );
@@ -382,14 +430,58 @@ ContextHandlerRef BlipFillContext::onCreateContext(
             mrBlipProps.moTileScaleY = rAttribs.getInteger( XML_sy );
             mrBlipProps.moTileAlign = rAttribs.getToken( XML_algn );
             mrBlipProps.moTileFlip = rAttribs.getToken( XML_flip );
+
+            if (mpBlipFill)
+            {
+                mpBlipFill->meMode = model::BitmapMode::Tile;
+                mpBlipFill->mnTileOffsetX = rAttribs.getInteger(XML_tx, 0);
+                mpBlipFill->mnTileOffsetY = rAttribs.getInteger(XML_ty, 0);
+                mpBlipFill->mnTileScaleX = rAttribs.getInteger(XML_sx, 0);
+                mpBlipFill->mnTileScaleY = rAttribs.getInteger(XML_sy, 0);
+
+                switch (rAttribs.getToken(XML_flip, XML_none))
+                {
+                    case XML_x: mpBlipFill->meTileFlipMode = 
model::FlipMode::X; break;
+                    case XML_y: mpBlipFill->meTileFlipMode = 
model::FlipMode::Y; break;
+                    case XML_xy: mpBlipFill->meTileFlipMode = 
model::FlipMode::XY; break;
+                    default:
+                    case XML_none: mpBlipFill->meTileFlipMode = 
model::FlipMode::None; break;
+                }
+                switch (rAttribs.getToken(XML_algn, XML_tl))
+                {
+                    default:
+                    case XML_tl: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::TopLeft; break;
+                    case XML_t: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::Top; break;
+                    case XML_tr: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::TopRight; break;
+                    case XML_l: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::Left; break;
+                    case XML_ctr: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::Center; break;
+                    case XML_r: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::Right; break;
+                    case XML_bl: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::BottomLeft; break;
+                    case XML_b: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::Bottom; break;
+                    case XML_br: mpBlipFill->meTileAlignment = 
model::RectangleAlignment::BottomRight; break;
+                }
+            }
+        }
         break;
 
         case A_TOKEN( stretch ):
+        {
             mrBlipProps.moBitmapMode = getBaseToken( nElement );
+            if (mpBlipFill)
+            {
+                mpBlipFill->meMode = model::BitmapMode::Stretch;
+            }
             return this;    // for fillRect element
+        }
+        break;
 
         case A_TOKEN( fillRect ):
+        {
             mrBlipProps.moFillRect = GetRelativeRect( 
rAttribs.getFastAttributeList() );
+
+            if (mpBlipFill)
+                fillRelativeRectangle(mpBlipFill->maFillRectangle, 
rAttribs.getFastAttributeList());
+        }
         break;
     }
     return nullptr;
@@ -460,7 +552,13 @@ ContextHandlerRef FillPropertiesContext::createFillContext(
         case A_TOKEN( blipFill ):
         {
             rFillProps.moFillType = getBaseToken( nElement );
-            return new BlipFillContext( rParent, rAttribs, 
rFillProps.maBlipProps );
+            model::BlipFill* pBlipFill = nullptr;
+            if (pFillStyle)
+            {
+                pFillStyle->mpFill = std::make_unique<model::BlipFill>();
+                pBlipFill = 
static_cast<model::BlipFill*>(pFillStyle->mpFill.get());
+            }
+            return new BlipFillContext( rParent, rAttribs, 
rFillProps.maBlipProps, pBlipFill);
         }
         case A_TOKEN( grpFill ):
         {
diff --git a/oox/source/drawingml/textparagraphpropertiescontext.cxx 
b/oox/source/drawingml/textparagraphpropertiescontext.cxx
index e75d65913cd9..2146d9ed04b0 100644
--- a/oox/source/drawingml/textparagraphpropertiescontext.cxx
+++ b/oox/source/drawingml/textparagraphpropertiescontext.cxx
@@ -275,7 +275,7 @@ ContextHandlerRef 
TextParagraphPropertiesContext::onCreateContext( sal_Int32 aEl
         case A_TOKEN( buBlip ):         // CT_TextBlipBullet
             {
                 mxBlipProps = std::make_shared<BlipFillProperties>();
-                return new BlipFillContext( *this, rAttribs, *mxBlipProps );
+                return new BlipFillContext(*this, rAttribs, *mxBlipProps, 
nullptr);
             }
         case A_TOKEN( tabLst ):         // CT_TextTabStopList
             return new TextTabStopListContext( *this, maTabList );

Reply via email to