oox: import gradient fill to model::FormatScheme
Change-Id: I90bc7cf4239f08efbc7239928c34ccdbec20cb2c
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147575
Tested-by: Jenkins
Reviewed-by: Tomaž Vajngerl <quikee@gmail.com>
diff --git a/include/docmodel/theme/FormatScheme.hxx b/include/docmodel/theme/FormatScheme.hxx
index a256532..39fa5d3 100644
--- a/include/docmodel/theme/FormatScheme.hxx
+++ b/include/docmodel/theme/FormatScheme.hxx
@@ -159,6 +159,52 @@ public:
}
};
class DOCMODEL_DLLPUBLIC GradientStop
{
public:
double mfPosition = 0.0; // 0.0 - 1.0
ColorDefinition maColor;
};
enum class GradientType
{
Undefined,
Linear,
Circle,
Rectangle,
Shape,
};
struct DOCMODEL_DLLPUBLIC LinearGradientProperties
{
sal_Int32 mnAngle = 0;
bool mbScaled = false;
};
struct DOCMODEL_DLLPUBLIC RelativeRectangle
{
sal_Int32 mnLeft = 0;
sal_Int32 mnTop = 0;
sal_Int32 mnRight = 0;
sal_Int32 mnBottom = 0;
};
class DOCMODEL_DLLPUBLIC GradientFill : public Fill
{
public:
bool mbRotateWithShape = false;
GradientType meGradientType = GradientType::Undefined;
std::vector<GradientStop> maGradientStops;
LinearGradientProperties maLinearGradient;
RelativeRectangle maFillToRectangle;
RelativeRectangle maTileRectangle;
GradientFill()
: Fill(FillType::Gradient)
{
}
};
// Format Scheme
class DOCMODEL_DLLPUBLIC FillStyle
diff --git a/include/oox/drawingml/drawingmltypes.hxx b/include/oox/drawingml/drawingmltypes.hxx
index 5fe86d5..8dd5dee 100644
--- a/include/oox/drawingml/drawingmltypes.hxx
+++ b/include/oox/drawingml/drawingmltypes.hxx
@@ -31,6 +31,7 @@
#include <com/sun/star/style/TabAlign.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <o3tl/unit_conversion.hxx>
#include <docmodel/theme/FormatScheme.hxx>
#include <oox/dllapi.h>
#include <rtl/ustring.hxx>
#include <sal/types.h>
@@ -100,6 +101,9 @@ css::awt::Size GetSize2D( const css::uno::Reference< css::xml::sax::XFastAttribu
/** converts the attributes from a CT_RelativeRect to an IntegerRectangle2D */
css::geometry::IntegerRectangle2D GetRelativeRect( const css::uno::Reference< css::xml::sax::XFastAttributeList >& xAttributes );
void fillRelativeRectangle(model::RelativeRectangle& rRelativeRectangle,
const css::uno::Reference<css::xml::sax::XFastAttributeList>& xAttributes);
/** converts EMUs into 1/100th mmm */
sal_Int32 GetCoordinate( sal_Int32 nValue );
diff --git a/oox/inc/drawingml/misccontexts.hxx b/oox/inc/drawingml/misccontexts.hxx
index e2e255d..6bbaa74 100644
--- a/oox/inc/drawingml/misccontexts.hxx
+++ b/oox/inc/drawingml/misccontexts.hxx
@@ -42,10 +42,9 @@ public:
class GradientFillContext final : public ::oox::core::ContextHandler2
{
public:
explicit GradientFillContext(
::oox::core::ContextHandler2Helper const & rParent,
const ::oox::AttributeList& rAttribs,
GradientFillProperties& rGradientProps );
explicit GradientFillContext(::oox::core::ContextHandler2Helper const & rParent,
const ::oox::AttributeList& rAttribs, GradientFillProperties& rGradientProps,
model::GradientFill* pGradientFill);
virtual ::oox::core::ContextHandlerRef
onCreateContext(
@@ -53,6 +52,7 @@ public:
const ::oox::AttributeList& rAttribs ) override;
private:
model::GradientFill* mpGradientFill;
GradientFillProperties& mrGradientProps;
};
diff --git a/oox/source/drawingml/drawingmltypes.cxx b/oox/source/drawingml/drawingmltypes.cxx
index fc2f28d..d0bf1bf 100644
--- a/oox/source/drawingml/drawingmltypes.cxx
+++ b/oox/source/drawingml/drawingmltypes.cxx
@@ -400,6 +400,14 @@ IntegerRectangle2D GetRelativeRect( const Reference< XFastAttributeList >& xAttr
return r;
}
void fillRelativeRectangle(model::RelativeRectangle& rRelativeRectangle, const Reference<XFastAttributeList>& xAttribs)
{
rRelativeRectangle.mnLeft = GetST_Percentage(xAttribs->getOptionalValue(XML_l));
rRelativeRectangle.mnTop = GetST_Percentage(xAttribs->getOptionalValue(XML_t));
rRelativeRectangle.mnRight = GetST_Percentage(xAttribs->getOptionalValue(XML_r));
rRelativeRectangle.mnBottom = GetST_Percentage(xAttribs->getOptionalValue(XML_b));
}
/** converts the attributes from a CT_Size2D into an awt Size with 1/100thmm */
awt::Size GetSize2D( const Reference< XFastAttributeList >& xAttribs )
{
diff --git a/oox/source/drawingml/misccontexts.cxx b/oox/source/drawingml/misccontexts.cxx
index 9a5ff0e..e72e6ea 100644
--- a/oox/source/drawingml/misccontexts.cxx
+++ b/oox/source/drawingml/misccontexts.cxx
@@ -44,13 +44,17 @@ SolidFillContext::SolidFillContext(ContextHandler2Helper const & rParent, FillPr
SolidFillContext::~SolidFillContext()
{}
GradientFillContext::GradientFillContext( ContextHandler2Helper const & rParent,
const AttributeList& rAttribs, GradientFillProperties& rGradientProps ) :
ContextHandler2( rParent ),
mrGradientProps( rGradientProps )
GradientFillContext::GradientFillContext(ContextHandler2Helper const & rParent,
const AttributeList& rAttribs, GradientFillProperties& rGradientProps, model::GradientFill* pGradientFill)
: ContextHandler2(rParent)
, mpGradientFill(pGradientFill)
, mrGradientProps(rGradientProps)
{
auto oRotateWithShape = rAttribs.getBool(XML_rotWithShape);
mrGradientProps.moShadeFlip = rAttribs.getToken( XML_flip );
mrGradientProps.moRotateWithShape = rAttribs.getBool( XML_rotWithShape );
mrGradientProps.moRotateWithShape = oRotateWithShape;
if (mpGradientFill && oRotateWithShape)
mpGradientFill->mbRotateWithShape = *oRotateWithShape;
}
ContextHandlerRef GradientFillContext::onCreateContext(
@@ -62,30 +66,73 @@ ContextHandlerRef GradientFillContext::onCreateContext(
return this; // for gs elements
case A_TOKEN( gs ):
if( rAttribs.hasAttribute( XML_pos ) )
if (rAttribs.hasAttribute(XML_pos))
{
double fPosition = getLimitedValue< double >( rAttribs.getDouble( XML_pos, 0.0 ) / 100000.0, 0.0, 1.0 );
auto aElement = mrGradientProps.maGradientStops.emplace( fPosition, Color() );
return new ColorContext( *this, aElement->second );
double fPosition = getLimitedValue<double>(rAttribs.getDouble(XML_pos, 0.0) / 100000.0, 0.0, 1.0);
auto aElement = mrGradientProps.maGradientStops.emplace(fPosition, Color());
model::ColorDefinition* pColorDefinition = nullptr;
if (mpGradientFill)
{
model::GradientStop& rStop = mpGradientFill->maGradientStops.emplace_back();
rStop.mfPosition = fPosition;
pColorDefinition = &rStop.maColor;
}
return new ColorContext(*this, aElement->second, pColorDefinition);
}
break;
case A_TOKEN( lin ):
mrGradientProps.moShadeAngle = rAttribs.getInteger( XML_ang );
mrGradientProps.moShadeScaled = rAttribs.getBool( XML_scaled );
{
mrGradientProps.moShadeAngle = rAttribs.getInteger(XML_ang);
mrGradientProps.moShadeScaled = rAttribs.getBool(XML_scaled);
if (mpGradientFill)
{
mpGradientFill->meGradientType = model::GradientType::Linear;
mpGradientFill->maLinearGradient.mnAngle = rAttribs.getInteger(XML_ang, 0);
mpGradientFill->maLinearGradient.mbScaled = rAttribs.getBool(XML_scaled, false);
}
}
break;
case A_TOKEN( path ):
{
// always set a path type, this disables linear gradient in conversion
mrGradientProps.moGradientPath = rAttribs.getToken( XML_path, XML_rect );
sal_Int32 nToken = rAttribs.getToken(XML_path, XML_rect);
mrGradientProps.moGradientPath = nToken;
if (mpGradientFill)
{
switch (nToken)
{
case XML_rect:
mpGradientFill->meGradientType = model::GradientType::Rectangle;
break;
case XML_circle:
mpGradientFill->meGradientType = model::GradientType::Circle;
break;
case XML_shape:
mpGradientFill->meGradientType = model::GradientType::Shape;
break;
default:
break;
}
}
return this; // for fillToRect element
}
case A_TOKEN( fillToRect ):
{
mrGradientProps.moFillToRect = GetRelativeRect( rAttribs.getFastAttributeList() );
if (mpGradientFill)
fillRelativeRectangle(mpGradientFill->maFillToRectangle, rAttribs.getFastAttributeList());
}
break;
case A_TOKEN( tileRect ):
mrGradientProps.moTileRect = GetRelativeRect( rAttribs.getFastAttributeList() );
mrGradientProps.moTileRect = GetRelativeRect(rAttribs.getFastAttributeList());
if (mpGradientFill)
fillRelativeRectangle(mpGradientFill->maTileRectangle, rAttribs.getFastAttributeList());
break;
}
return nullptr;
@@ -105,9 +152,9 @@ ContextHandlerRef PatternFillContext::onCreateContext(
switch( nElement )
{
case A_TOKEN( bgClr ):
return new ColorContext( *this, mrPatternProps.maPattBgColor );
return new ColorContext(*this, mrPatternProps.maPattBgColor, nullptr);
case A_TOKEN( fgClr ):
return new ColorContext( *this, mrPatternProps.maPattFgColor );
return new ColorContext(*this, mrPatternProps.maPattFgColor, nullptr);
}
return nullptr;
}
@@ -134,9 +181,9 @@ ContextHandlerRef ColorChangeContext::onCreateContext(
switch( nElement )
{
case A_TOKEN( clrFrom ):
return new ColorContext( *this, mrBlipProps.maColorChangeFrom );
return new ColorContext(*this, mrBlipProps.maColorChangeFrom, nullptr);
case A_TOKEN( clrTo ):
return new ColorContext( *this, mrBlipProps.maColorChangeTo );
return new ColorContext(*this, mrBlipProps.maColorChangeTo, nullptr);
}
return nullptr;
}
@@ -220,7 +267,7 @@ DuotoneContext::~DuotoneContext()
sal_Int32 /*nElement*/, const AttributeList& /*rAttribs*/ )
{
if( mnColorIndex < 2 )
return new ColorValueContext( *this, mrBlipProps.maDuotoneColors[mnColorIndex++] );
return new ColorValueContext(*this, mrBlipProps.maDuotoneColors[mnColorIndex++], nullptr);
return nullptr;
}
@@ -307,7 +354,13 @@ ContextHandlerRef FillPropertiesContext::createFillContext(
case A_TOKEN( gradFill ):
{
rFillProps.moFillType = getBaseToken(nElement);
return new GradientFillContext(rParent, rAttribs, rFillProps.maGradientProps);
model::GradientFill* pGradientFill = nullptr;
if (pFillStyle)
{
pFillStyle->mpFill = std::make_unique<model::GradientFill>();
pGradientFill = static_cast<model::GradientFill*>(pFillStyle->mpFill.get());
}
return new GradientFillContext(rParent, rAttribs, rFillProps.maGradientProps, pGradientFill);
}
case A_TOKEN( pattFill ):
{