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 <quikee@gmail.com>
This commit is contained in:
Tomaž Vajngerl
2023-04-12 06:01:53 +02:00
committed by Tomaž Vajngerl
parent 17167dbede
commit 0ffa50031e
5 changed files with 201 additions and 39 deletions
+67
View File
@@ -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
+11 -14
View File
@@ -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;
};
+1 -1
View File
@@ -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));
+121 -23
View File
@@ -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 ):
{
@@ -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 );