diff options
author | Armin Le Grand (allotropia) <armin.le.grand.extern@allotropia.de> | 2023-05-24 12:31:48 +0200 |
---|---|---|
committer | Armin Le Grand <Armin.Le.Grand@me.com> | 2023-05-26 10:08:52 +0200 |
commit | c2bea1bedd2ee8bc4007fd23c6cb839a692297a7 (patch) | |
tree | cabb61287db769cae2f412e45125ddba9110249b | |
parent | 7d87770986fdfc43dd5d4b514f68026ff6ededcf (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.cxx | 206 | ||||
-rw-r--r-- | basegfx/source/tools/gradienttools.cxx | 97 | ||||
-rw-r--r-- | include/basegfx/utils/bgradient.hxx | 29 | ||||
-rw-r--r-- | include/basegfx/utils/gradienttools.hxx | 11 | ||||
-rw-r--r-- | oox/source/drawingml/fillproperties.cxx | 98 |
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; |