summaryrefslogtreecommitdiff
path: root/oox
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2023-05-24 12:31:48 +0200
committerAndras Timar <andras.timar@collabora.com>2023-06-04 16:34:11 +0200
commit10f8cdb5ba93953d9efcc3959c8b886f993ddbbb (patch)
tree52842dee822ed09a9702d9addaed1b65412208c7 /oox
parentc6b90b83ad6bfaf1e95ca600ef4c5559a2a864fe (diff)
MCGR: Border restoration support
Due to tdf#155362 I added code to be able in case we would need it to convert a BGradient using added tooling from having offsets in the GradientSteps and no border to adapted GradientSteps and border. This is preferrable due to our GradientStyle_RECT (and GradientStyle_ELLIPTICAL too) use that 'non- linear' paint aka move-two-pixels-inside, someone else called it 'frame-paint'. This does not bode well with the border being applied 'linear' at the same time (argh). Thus - while in principle all is correct when re-importing a GradientStyle_RECT with a border after export to pptx, it looks slightly better ('correcter') wen doing so. That is because when being able to and restoring a border at least that border part *is* applied linearly. I took the chance to further apply tooling, move it to classes involved and instead of awt::Gradient2 use more basegfx::BGradient since it can and does host tooling. This is also a preparation to be able to adapt (restore) border in case of turn- around in ODF where the importing instance is before MCGR existance and has to handle Start/EndColor. Needed to take more care with using BGradient instead of awt::Gradient2 for initialization, also better dividing/organization of tooling, already preparation to use for other purposes. Change-Id: I2d3a4240a5ac6fff9211b46642ee80366dc09e3d Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152194 Tested-by: Jenkins Reviewed-by: Armin Le Grand <Armin.Le.Grand@me.com>
Diffstat (limited to 'oox')
-rw-r--r--oox/source/drawingml/fillproperties.cxx97
1 files changed, 44 insertions, 53 deletions
diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx
index d8cfc19beff3..fe00d12cf078 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -457,18 +457,11 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
// do not create gradient struct if property is not supported...
if( rPropMap.supportsProperty( ShapeProperty::FillGradient ) )
{
- // use awt::Gradient2, prepare ColorStops
- awt::Gradient2 aGradient;
+ // prepare ColorStops
basegfx::BColorStops aColorStops;
basegfx::BColorStops aTransparencyStops;
bool bContainsTransparency(false);
- // set defaults
- aGradient.Angle = 900;
- aGradient.StartIntensity = 100;
- aGradient.EndIntensity = 100;
- aGradient.Style = awt::GradientStyle_LINEAR;
-
// convert to BColorStops, check for contained transparency
for (const auto& rCandidate : maGradientProps.maGradientStops)
{
@@ -487,6 +480,20 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
}
}
+ // prepare BGradient with some defaults
+ // CAUTION: This used awt::Gradient2 before who's empty constructor
+ // (see workdir/UnoApiHeadersTarget/offapi/normal/com/sun/
+ // star/awt/Gradient.hpp) initializes all to zeros, so reflect
+ // this here. OTOH set all that were set, e.g. Start/EndIntens
+ // were set to 100, so just use default of BGradient constructor
+ basegfx::BGradient aGradient(
+ aColorStops,
+ awt::GradientStyle_LINEAR,
+ Degree10(900),
+ 0, // border
+ 0, // OfsX -> 0, not 50 (!)
+ 0); // OfsY -> 0, not 50 (!)
+
// "rotate with shape" set to false -> do not rotate
if (!maGradientProps.moRotateWithShape.value_or(true))
{
@@ -497,77 +504,61 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
{
IntegerRectangle2D aFillToRect = maGradientProps.moFillToRect.value_or( IntegerRectangle2D( 0, 0, MAX_PERCENT, MAX_PERCENT ) );
sal_Int32 nCenterX = (MAX_PERCENT + aFillToRect.X1 - aFillToRect.X2) / 2;
- aGradient.XOffset = getLimitedValue<sal_Int16, sal_Int32>(
- nCenterX / PER_PERCENT, 0, 100);
+ aGradient.SetXOffset(getLimitedValue<sal_Int16, sal_Int32>(
+ nCenterX / PER_PERCENT, 0, 100));
sal_Int32 nCenterY = (MAX_PERCENT + aFillToRect.Y1 - aFillToRect.Y2) / 2;
- aGradient.YOffset = getLimitedValue<sal_Int16, sal_Int32>(
- nCenterY / PER_PERCENT, 0, 100);
+ aGradient.SetYOffset(getLimitedValue<sal_Int16, sal_Int32>(
+ nCenterY / PER_PERCENT, 0, 100));
if( maGradientProps.moGradientPath.value() == XML_circle )
{
// Style should be radial at least when the horizontal center is at 50%.
// Otherwise import as a linear gradient, because it is the most similar to the MSO radial style.
- // aGradient.Style = awt::GradientStyle_LINEAR;
- if( aGradient.XOffset == 100 && aGradient.YOffset == 100 )
- aGradient.Angle = 450;
- else if( aGradient.XOffset == 0 && aGradient.YOffset == 100 )
- aGradient.Angle = 3150;
- else if( aGradient.XOffset == 100 && aGradient.YOffset == 0 )
- aGradient.Angle = 1350;
- else if( aGradient.XOffset == 0 && aGradient.YOffset == 0 )
- aGradient.Angle = 2250;
+ // aGradient.SetGradientStyle(awt::GradientStyle_LINEAR);
+ if( 100 == aGradient.GetXOffset() && 100 == aGradient.GetYOffset() )
+ aGradient.SetAngle( Degree10(450) );
+ else if( 0 == aGradient.GetXOffset() && 100 == aGradient.GetYOffset() )
+ aGradient.SetAngle( Degree10(3150) );
+ else if( 100 == aGradient.GetXOffset() && 0 == aGradient.GetYOffset() )
+ aGradient.SetAngle( Degree10(1350) );
+ else if( 0 == aGradient.GetXOffset() && 0 == aGradient.GetYOffset() )
+ aGradient.SetAngle( Degree10(2250) );
else
- aGradient.Style = awt::GradientStyle_RADIAL;
+ aGradient.SetGradientStyle(awt::GradientStyle_RADIAL);
}
else
{
- aGradient.Style = awt::GradientStyle_RECT;
+ aGradient.SetGradientStyle(awt::GradientStyle_RECT);
}
aColorStops.reverseColorStops();
+ aGradient.SetColorStops(aColorStops);
aTransparencyStops.reverseColorStops();
}
else if (!maGradientProps.maGradientStops.empty())
{
- // aGradient.Style = awt::GradientStyle_LINEAR;
- sal_Int32 nShadeAngle = maGradientProps.moShadeAngle.value_or( 0 );
+ // aGradient.SetGradientStyle(awt::GradientStyle_LINEAR);
+ sal_Int32 nShadeAngle(maGradientProps.moShadeAngle.value_or( 0 ));
// Adjust for flips
if ( bFlipH )
nShadeAngle = 180*60000 - nShadeAngle;
if ( bFlipV )
nShadeAngle = -nShadeAngle;
const sal_Int32 nDmlAngle = nShadeAngle + nShapeRotation;
+
// convert DrawingML angle (in 1/60000 degrees) to API angle (in 1/10 degrees)
- aGradient.Angle = static_cast< sal_Int16 >( (8100 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 );
+ aGradient.SetAngle(Degree10(static_cast< sal_Int16 >( (8100 - (nDmlAngle / (PER_DEGREE / 10))) % 3600 )));
}
- // set BColorStops using UNO API
- aGradient.ColorStops = aColorStops.getAsColorStopSequence();
-
- // for compatibility, still set StartColor/EndColor
- // NOTE: All code after adapting to multi color gradients works
- // using the ColorSteps, so in principle Start/EndColor might
- // be either
- // (a) ignored consequently everywhere or
- // (b) be set/added consequently everywhere
- // since this is - in principle - redundant data.
- // Be aware that e.g. cases like DrawingML::EqualGradients
- // and others would have to be identified and adapted (!)
- // Since awt::Gradient2 is UNO API data there might
- // be cases where just awt::Gradient is transferred, so (b)
- // is far better backwards compatible and thus more safe, so
- // all changes will make use of additionally using/setting
- // these additionally, but will only make use of the given
- // ColorSteps if these are not empty, assuming that these
- // already contain Start/EndColor.
- // In principle that redundancy and that it is conflict-free
- // could even be checked and asserted, but consequently using
- // (b) methodically should be safe.
- aGradient.StartColor = static_cast<sal_Int32>(::Color(aColorStops.front().getStopColor()));
- aGradient.EndColor = static_cast<sal_Int32>(::Color(aColorStops.back().getStopColor()));
+ if (awt::GradientStyle_RECT == aGradient.GetGradientStyle())
+ {
+ // MCGR: tdf#155362: better support border
+ // CAUTION: Need to handle TransparencyStops if used
+ aGradient.tryToRecreateBorder(aTransparencyStops.empty() ? nullptr : &aTransparencyStops);
+ }
// push gradient or named gradient to property map
- if (rPropMap.setProperty(ShapeProperty::FillGradient, aGradient))
+ if (rPropMap.setProperty(ShapeProperty::FillGradient, aGradient.getAsGradient2()))
{
eFillStyle = FillStyle_GRADIENT;
}
@@ -575,8 +566,8 @@ void FillProperties::pushToPropMap( ShapePropertyMap& rPropMap,
// push gradient transparency to property map if it exists
if (!aTransparencyStops.empty())
{
- aGradient.ColorStops = aTransparencyStops.getAsColorStopSequence();
- rPropMap.setProperty(ShapeProperty::GradientTransparency, aGradient);
+ aGradient.SetColorStops(aTransparencyStops);
+ rPropMap.setProperty(ShapeProperty::GradientTransparency, aGradient.getAsGradient2());
}
}
break;