summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de>2023-05-24 12:31:48 +0200
committerArmin Le Grand <Armin.Le.Grand@me.com>2023-05-26 10:08:52 +0200
commitc2bea1bedd2ee8bc4007fd23c6cb839a692297a7 (patch)
treecabb61287db769cae2f412e45125ddba9110249b
parent7d87770986fdfc43dd5d4b514f68026ff6ededcf (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>
-rw-r--r--basegfx/source/tools/bgradient.cxx206
-rw-r--r--basegfx/source/tools/gradienttools.cxx97
-rw-r--r--include/basegfx/utils/bgradient.hxx29
-rw-r--r--include/basegfx/utils/gradienttools.hxx11
-rw-r--r--oox/source/drawingml/fillproperties.cxx98
5 files changed, 306 insertions, 135 deletions
diff --git a/basegfx/source/tools/bgradient.cxx b/basegfx/source/tools/bgradient.cxx
index 52aa721f36a6..b7ee0780a2cc 100644
--- a/basegfx/source/tools/bgradient.cxx
+++ b/basegfx/source/tools/bgradient.cxx
@@ -563,6 +563,100 @@ void BColorStops::reverseColorStops()
candidate = BColorStop(1.0 - candidate.getStopOffset(), candidate.getStopColor());
}
+// createSpaceAtStart creates fOffset space at start by
+// translating/scaling all entries to the right
+void BColorStops::createSpaceAtStart(double fOffset)
+{
+ // nothing to do if empty
+ if (empty())
+ return;
+
+ // correct offset to [0.0 .. 1.0]
+ fOffset = std::max(std::min(1.0, fOffset), 0.0);
+
+ // nothing to do if 0.0 == offset
+ if (basegfx::fTools::equalZero(fOffset))
+ return;
+
+ BColorStops aNewStops;
+
+ for (const auto& candidate : *this)
+ {
+ aNewStops.emplace_back(fOffset + (candidate.getStopOffset() * (1.0 - fOffset)),
+ candidate.getStopColor());
+ }
+
+ *this = aNewStops;
+}
+
+// removeSpaceAtStart removes fOffset space from start by
+// translating/scaling entries more or equal to fOffset
+// to the left. Entries less than fOffset will be removed
+void BColorStops::removeSpaceAtStart(double fOffset)
+{
+ // nothing to do if empty
+ if (empty())
+ return;
+
+ // correct factor to [0.0 .. 1.0]
+ fOffset = std::max(std::min(1.0, fOffset), 0.0);
+
+ // nothing to do if fOffset == 0.0
+ if (basegfx::fTools::equalZero(fOffset))
+ return;
+
+ BColorStops aNewStops;
+ const double fMul(basegfx::fTools::equal(fOffset, 1.0) ? 1.0 : 1.0 / (1.0 - fOffset));
+
+ for (const auto& candidate : *this)
+ {
+ if (basegfx::fTools::moreOrEqual(candidate.getStopOffset(), fOffset))
+ {
+ aNewStops.emplace_back((candidate.getStopOffset() - fOffset) * fMul,
+ candidate.getStopColor());
+ }
+ }
+
+ *this = aNewStops;
+}
+
+// try to detect if an empty/no-color-change area exists
+// at the start and return offset to it. Returns 0.0 if not.
+double BColorStops::detectPossibleOffsetAtStart() const
+{
+ BColor aSingleColor;
+ const bool bSingleColor(isSingleColor(aSingleColor));
+
+ // no useful offset for single color
+ if (bSingleColor)
+ return 0.0;
+
+ // here we know that we have at least two colors, so we have a
+ // color change. Find colors left and right of that first color change
+ BColorStops::const_iterator aColorR(begin());
+ BColorStops::const_iterator aColorL(aColorR++);
+
+ // aColorR would 1st get equal to end(), so no need to also check aColorL
+ // for end(). Loop as long as same color. Since we *have* a color change
+ // not even aColorR can get equal to end() before color inequality, but
+ // keep for safety
+ while (aColorR != end() && aColorL->getStopColor() == aColorR->getStopColor())
+ {
+ aColorL++;
+ aColorR++;
+ }
+
+ // also for safety: access values at aColorL below *only*
+ // if not equal to end(), but can theoretically not happen
+ if (aColorL == end())
+ {
+ return 0.0;
+ }
+
+ // return offset (maybe 0.0 what is OK)
+ return aColorL->getStopOffset();
+}
+
std::string BGradient::GradientStyleToString(css::awt::GradientStyle eStyle)
{
switch (eStyle)
@@ -757,7 +851,24 @@ css::awt::Gradient2 BGradient::getAsGradient2() const
aRetval.StepCount = GetSteps();
// for compatibility, still set StartColor/EndColor
- // const basegfx::BColorStops& rColorStops(GetColorStops());
+ // 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.
aRetval.StartColor
= static_cast<sal_Int32>(ColorToBColorConverter(aColorStops.front().getStopColor()));
aRetval.EndColor
@@ -765,10 +876,101 @@ css::awt::Gradient2 BGradient::getAsGradient2() const
// fill ColorStops to extended Gradient2
aRetval.ColorStops = aColorStops.getAsColorStopSequence();
- // fillColorStopSequenceFromColorStops(rGradient2.ColorStops, rColorStops);
return aRetval;
}
+
+void BGradient::tryToRecreateBorder(basegfx::BColorStops* pAssociatedTransparencyStops)
+{
+ // border already set, do not try to recreate
+ if (0 != GetBorder())
+ return;
+
+ BColor aSingleColor;
+ const bool bSingleColor(GetColorStops().isSingleColor(aSingleColor));
+
+ // no need to recreate with single color
+ if (bSingleColor)
+ return;
+
+ const bool bIsAxial(css::awt::GradientStyle_AXIAL == GetGradientStyle());
+
+ if (bIsAxial)
+ {
+ // for axial due to reverse used gradient work reversed
+ aColorStops.reverseColorStops();
+ if (nullptr != pAssociatedTransparencyStops)
+ pAssociatedTransparencyStops->reverseColorStops();
+ }
+
+ // check if we have space at start of range [0.0 .. 1.0] that
+ // may be interpreted as 'border' -> same color. That may involve
+ // different scenarios, e.g. 1st index > 0.0, but also a non-zero
+ // number of same color entries, or a combination of both
+ const double fOffset(aColorStops.detectPossibleOffsetAtStart());
+
+ if (!basegfx::fTools::equalZero(fOffset))
+ {
+ // we have a border area, indeed re-create
+ aColorStops.removeSpaceAtStart(fOffset);
+ if (nullptr != pAssociatedTransparencyStops)
+ pAssociatedTransparencyStops->removeSpaceAtStart(fOffset);
+
+ // ...and create border value
+ SetBorder(static_cast<sal_uInt16>(fOffset * 100.0));
+ }
+
+ if (bIsAxial)
+ {
+ // take back reverse
+ aColorStops.reverseColorStops();
+ if (nullptr != pAssociatedTransparencyStops)
+ pAssociatedTransparencyStops->reverseColorStops();
+ }
+}
+
+void BGradient::tryToApplyBorder()
+{
+ // no border to apply, done
+ if (0 == GetBorder())
+ return;
+
+ // NOTE: no new start node is added. The new ColorStop
+ // mechanism does not need entries at 0.0 and 1.0.
+ // In case this is needed, do that in the caller
+ const double fOffset(GetBorder() * 0.01);
+
+ if (css::awt::GradientStyle_AXIAL == GetGradientStyle())
+ {
+ // for axial due to reverse used gradient work reversed
+ aColorStops.reverseColorStops();
+ aColorStops.createSpaceAtStart(fOffset);
+ aColorStops.reverseColorStops();
+ }
+ else
+ {
+ // apply border to GradientSteps
+ aColorStops.createSpaceAtStart(fOffset);
+ }
+
+ // set changed values
+ SetBorder(0);
+}
+
+void BGradient::tryToApplyStartEndIntensity()
+{
+ // already on default, nothing to apply
+ if (100 == GetStartIntens() && 100 == GetEndIntens())
+ return;
+
+ // apply 'old' blend stuff, blend against black
+ aColorStops.blendToIntensity(GetStartIntens() * 0.01, GetEndIntens() * 0.01,
+ BColor()); // COL_BLACK
+
+ // set values to default
+ SetStartIntens(100);
+ SetEndIntens(100);
+}
}
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/basegfx/source/tools/gradienttools.cxx b/basegfx/source/tools/gradienttools.cxx
index d7b1bb167613..366e0b0840b8 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -265,28 +265,15 @@ namespace basegfx
namespace utils
{
- /* Tooling method to extract data from given awt::Gradient2
+ /* Tooling method to extract data from given BGradient
to ColorStops, doing some corrections, partially based
- on given SingleColor.
- This will do quite some preparations for the gradient
- as follows:
- - It will check for single color (resetting rSingleColor when
- this is the case) and return with empty ColorStops
- - It will blend ColorStops to Intensity if StartIntensity/
- EndIntensity != 100 is set in awt::Gradient2, so applying
- that value(s) to the gradient directly
- - It will adapt to Border if Border != 0 is set at the
- given awt::Gradient2, so applying that value to the gradient
- directly
- */
+ on given SingleColor */
void prepareColorStops(
const basegfx::BGradient& rGradient,
BColorStops& rColorStops,
BColor& rSingleColor)
{
- rColorStops = rGradient.GetColorStops();
-
- if (rColorStops.isSingleColor(rSingleColor))
+ if (rGradient.GetColorStops().isSingleColor(rSingleColor))
{
// when single color, preserve value in rSingleColor
// and clear the ColorStops, done.
@@ -294,73 +281,45 @@ namespace basegfx
return;
}
- if (100 != rGradient.GetStartIntens() || 100 != rGradient.GetEndIntens())
+ const bool bAdaptStartEndIntensity(100 != rGradient.GetStartIntens() || 100 != rGradient.GetEndIntens());
+ const bool bAdaptBorder(0 != rGradient.GetBorder());
+
+ if (!bAdaptStartEndIntensity && !bAdaptBorder)
{
- // apply 'old' blend stuff, blend against black
- rColorStops.blendToIntensity(
- rGradient.GetStartIntens() * 0.01,
- rGradient.GetEndIntens() * 0.01,
- basegfx::BColor()); // COL_BLACK
-
- // can lead to single color (e.g. both zero, so all black),
- // so check again
- if (rColorStops.isSingleColor(rSingleColor))
+ // copy unchanged ColorStops & done
+ rColorStops = rGradient.GetColorStops();
+ return;
+ }
+
+ // prepare a copy to work on
+ basegfx::BGradient aWorkCopy(rGradient);
+
+ if (bAdaptStartEndIntensity)
+ {
+ aWorkCopy.tryToApplyStartEndIntensity();
+
+ // this can again lead to single color (e.g. both zero, so
+ // all black), so check again for it
+ if (aWorkCopy.GetColorStops().isSingleColor(rSingleColor))
{
rColorStops.clear();
return;
}
}
- if (0 != rGradient.GetBorder())
+ if (bAdaptBorder)
{
- // apply Border if set
- // NOTE: no new start node is added. The new ColorStop
- // mechanism does not need entries at 0.0 and 1.0.
- // In case this is needed, do that in the caller
- const double fFactor(rGradient.GetBorder() * 0.01);
- BColorStops aNewStops;
-
- for (const auto& candidate : rColorStops)
- {
- if (css::awt::GradientStyle_AXIAL == rGradient.GetGradientStyle())
- {
- // for axial add the 'gap' at the start due to reverse used gradient
- aNewStops.emplace_back((1.0 - fFactor) * candidate.getStopOffset(), candidate.getStopColor());
- }
- else
- {
- // css::awt::GradientStyle_LINEAR
- // case awt::GradientStyle_RADIAL
- // case awt::GradientStyle_ELLIPTICAL
- // case awt::GradientStyle_RECT
- // case awt::GradientStyle_SQUARE
-
- // for all others add the 'gap' at the end
- aNewStops.emplace_back(fFactor + (candidate.getStopOffset() * (1.0 - fFactor)), candidate.getStopColor());
- }
- }
-
- rColorStops = aNewStops;
+ aWorkCopy.tryToApplyBorder();
}
+
+ // extract ColorStops, that's all we need here
+ rColorStops = aWorkCopy.GetColorStops();
}
/* Tooling method to synchronize the given ColorStops.
The intention is that a color GradientStops and an
alpha/transparence GradientStops gets synchronized
- for export.
- For the corrections the single values for color and
- alpha may be used, e.g. when ColorStops is given
- and not empty, but AlphaStops is empty, it will get
- synchronized so that it will have the same number and
- offsets in AlphaStops as in ColorStops, but with
- the given SingleAlpha as value.
- At return it guarantees that both have the same
- number of entries with the same StopOffsets, so
- that synchronized pair of ColorStops can e.g. be used
- to export a Gradient with defined/adapted alpha
- being 'coupled' indirectly using the
- 'FillTransparenceGradient' method (at import time).
- */
+ for export. */
void synchronizeColorStops(
BColorStops& rColorStops,
BColorStops& rAlphaStops,
diff --git a/include/basegfx/utils/bgradient.hxx b/include/basegfx/utils/bgradient.hxx
index a0e853ec7099..fa9591cdb266 100644
--- a/include/basegfx/utils/bgradient.hxx
+++ b/include/basegfx/utils/bgradient.hxx
@@ -40,13 +40,10 @@ namespace basegfx
Offset is defined as:
- being in the range of [0.0 .. 1.0] (unit range)
- - 0.0 being reserved for StartColor
- - 1.0 being reserved for EndColor
- - in-between offsets thus being in the range of ]0.0 .. 1.0[
- - no two equal offsets are allowed
- - this is an error
- - missing 1.0 entry (EndColor) is allowed
- - it means that EndColor == StartColor
+ - offsets outside are an error
+ - lowest/1st value equivalent to StartColor
+ - highest/last value equivalent to EndColor
+ - missing 0.0/1.0 entries are allowed
- at least one value (usually 0.0, StartColor) is required
- this allows to avoid massive testing in all places where
this data has to be accessed
@@ -263,6 +260,19 @@ public:
When also mirroring offsets a valid sort keeps valid.
*/
void reverseColorStops();
+
+ // createSpaceAtStart creates fOffset space at start by
+ // translating/scaling all entries to the right
+ void createSpaceAtStart(double fOffset);
+
+ // removeSpaceAtStart removes fOffset space from start by
+ // translating/scaling entries more or equal to fOffset
+ // to the left. Entries less than fOffset will be removed
+ void removeSpaceAtStart(double fOffset);
+
+ // try to detect if an empty/no-color-change area exists
+ // at the start and return offset to it. Returns 0.0 if not.
+ double detectPossibleOffsetAtStart() const;
};
class BASEGFX_DLLPUBLIC BGradient final
@@ -323,6 +333,11 @@ public:
/// Tooling method to fill awt::Gradient2 from data contained in the given basegfx::BGradient
css::awt::Gradient2 getAsGradient2() const;
+
+ /// Tooling to handle border correction/integration and StartStopIntensity
+ void tryToRecreateBorder(basegfx::BColorStops* pAssociatedTransparencyStops);
+ void tryToApplyBorder();
+ void tryToApplyStartEndIntensity();
};
}
diff --git a/include/basegfx/utils/gradienttools.hxx b/include/basegfx/utils/gradienttools.hxx
index 9672259be64b..6fc51adc0e37 100644
--- a/include/basegfx/utils/gradienttools.hxx
+++ b/include/basegfx/utils/gradienttools.hxx
@@ -186,18 +186,23 @@ namespace basegfx
namespace utils
{
- /* Tooling method to extract data from given awt::Gradient2
+ /* Tooling method to extract data from given BGradient
to ColorStops, doing some corrections, partially based
on given SingleColor.
+ This is used for export preparations in case these exports
+ do neither support Start/EndIntensity nor Border settings,
+ both will be elliminated if possible (see below).
+ The BGradient rGradient and BColorStops& rColorStops
+ are both return parameters and may be changed.
This will do quite some preparations for the gradient
as follows:
- It will check for single color (resetting rSingleColor when
this is the case) and return with empty ColorStops
- It will blend ColorStops to Intensity if StartIntensity/
- EndIntensity != 100 is set in awt::Gradient2, so applying
+ EndIntensity != 100 is set in BGradient, so applying
that value(s) to the gradient directly
- It will adapt to Border if Border != 0 is set at the
- given awt::Gradient2, so applying that value to the gradient
+ given BGradient, so applying that value to the gradient
directly
*/
BASEGFX_DLLPUBLIC void prepareColorStops(
diff --git a/oox/source/drawingml/fillproperties.cxx b/oox/source/drawingml/fillproperties.cxx
index a42418198c12..705f2dc3b55a 100644
--- a/oox/source/drawingml/fillproperties.cxx
+++ b/oox/source/drawingml/fillproperties.cxx
@@ -458,19 +458,11 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp
// do not create gradient struct if property is not supported...
if( rPropMap.supportsProperty( ShapeProperty::FillGradient ) )
{
- // use awt::Gradient2, prepare ColorStops
- awt::Gradient2 aGradient;
- assert(aGradient.ColorStops.get() && "cid#1524676 aGradient.ColorStops._pSequence won't be null here");
+ // 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)
{
@@ -489,6 +481,20 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp
}
}
+ // 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))
{
@@ -499,77 +505,61 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp
{
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;
}
@@ -577,8 +567,8 @@ void FillProperties::pushToPropMap(ShapePropertyMap& rPropMap, const GraphicHelp
// 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;