Avoid potential negative array index access to cached text.
[LibreOffice.git] / docmodel / source / uno / UnoGradientTools.cxx
blob0f05e398de7891bf792296f8a936a85896d50888
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 */
11 #include <docmodel/uno/UnoGradientTools.hxx>
12 #include <com/sun/star/awt/Gradient.hpp>
13 #include <com/sun/star/awt/Gradient2.hpp>
14 #include <com/sun/star/rendering/RGBColor.hpp>
15 #include <basegfx/utils/bgradient.hxx>
16 #include <tools/color.hxx>
18 using namespace css;
20 namespace model::gradient
22 css::awt::ColorStopSequence createColorStopSequence(basegfx::BColorStops const& rColorStops)
24 // Fill color stops
25 css::awt::ColorStopSequence aSequence(rColorStops.size());
26 css::awt::ColorStop* pSequence(aSequence.getArray());
28 for (const auto& rStop : rColorStops)
30 auto rBColor = rStop.getStopColor();
31 pSequence->StopOffset = rStop.getStopOffset();
32 pSequence->StopColor
33 = css::rendering::RGBColor(rBColor.getRed(), rBColor.getGreen(), rBColor.getBlue());
34 pSequence++;
37 return aSequence;
40 css::awt::Gradient2 createUnoGradient2(basegfx::BGradient const& rGradient)
42 css::awt::Gradient2 aGradient2;
44 // standard values
45 aGradient2.Style = rGradient.GetGradientStyle();
46 aGradient2.Angle = static_cast<short>(rGradient.GetAngle());
47 aGradient2.Border = rGradient.GetBorder();
48 aGradient2.XOffset = rGradient.GetXOffset();
49 aGradient2.YOffset = rGradient.GetYOffset();
50 aGradient2.StartIntensity = rGradient.GetStartIntens();
51 aGradient2.EndIntensity = rGradient.GetEndIntens();
52 aGradient2.StepCount = rGradient.GetSteps();
54 // for compatibility, still set StartColor/EndColor
55 // NOTE: All code after adapting to multi color gradients works
56 // using the ColorSteps, so in principle Start/EndColor might
57 // be either
58 // (a) ignored consequently everywhere or
59 // (b) be set/added consequently everywhere
60 // since this is - in principle - redundant data.
61 // Be aware that e.g. cases like DrawingML::EqualGradients
62 // and others would have to be identified and adapted (!)
63 // Since awt::Gradient2 is UNO API data there might
64 // be cases where just awt::Gradient is transferred, so (b)
65 // is far better backwards compatible and thus more safe, so
66 // all changes will make use of additionally using/setting
67 // these additionally, but will only make use of the given
68 // ColorSteps if these are not empty, assuming that these
69 // already contain Start/EndColor.
70 // In principle that redundancy and that it is conflict-free
71 // could even be checked and asserted, but consequently using
72 // (b) methodically should be safe.
73 const basegfx::BColorStops& rColorStops = rGradient.GetColorStops();
74 aGradient2.StartColor = static_cast<sal_Int32>(::Color(rColorStops.front().getStopColor()));
75 aGradient2.EndColor = static_cast<sal_Int32>(::Color(rColorStops.back().getStopColor()));
77 aGradient2.ColorStops = createColorStopSequence(rColorStops);
79 return aGradient2;
82 namespace
84 void fillFromColorStopSequence(basegfx::BColorStops& rColorStops,
85 css::awt::ColorStopSequence const& rUnoColorStopSequence)
87 const auto nLength = rUnoColorStopSequence.getLength();
88 if (0 != nLength)
90 rColorStops.clear();
91 rColorStops.reserve(nLength);
93 for (css::awt::ColorStop const& rSourceStop : rUnoColorStopSequence)
95 rColorStops.emplace_back(rSourceStop.StopOffset,
96 basegfx::BColor(rSourceStop.StopColor.Red,
97 rSourceStop.StopColor.Green,
98 rSourceStop.StopColor.Blue));
103 void fillFromGradient2(basegfx::BGradient& rBGradient, css::awt::Gradient2 const& rGradient2)
105 rBGradient.SetGradientStyle(rGradient2.Style);
106 rBGradient.SetAngle(Degree10(rGradient2.Angle));
107 rBGradient.SetBorder(rGradient2.Border);
108 rBGradient.SetXOffset(rGradient2.XOffset);
109 rBGradient.SetYOffset(rGradient2.YOffset);
110 rBGradient.SetStartIntens(rGradient2.StartIntensity);
111 rBGradient.SetEndIntens(rGradient2.EndIntensity);
112 rBGradient.SetSteps(rGradient2.StepCount);
114 // set ColorStops
115 if (rGradient2.ColorStops.hasElements())
117 basegfx::BColorStops aColorStops;
118 fillFromColorStopSequence(aColorStops, rGradient2.ColorStops);
119 rBGradient.SetColorStops(aColorStops);
121 else
123 // if not, for compatibility, use StartColor/EndColor
124 basegfx::BColorStops aColorStops{
125 basegfx::BColorStop(0.0, ::Color(ColorTransparency, rGradient2.StartColor).getBColor()),
126 basegfx::BColorStop(1.0, ::Color(ColorTransparency, rGradient2.EndColor).getBColor())
128 rBGradient.SetColorStops(aColorStops);
132 } // end anonymous
134 basegfx::BColorStops getColorStopsFromUno(css::awt::ColorStopSequence const& rColorStopSequence)
136 basegfx::BColorStops aColorStops;
137 fillFromColorStopSequence(aColorStops, rColorStopSequence);
138 return aColorStops;
141 basegfx::BColorStops getColorStopsFromAny(css::uno::Any const& rAny)
143 basegfx::BColorStops aColorStops;
144 if (!rAny.has<css::awt::ColorStopSequence>())
145 return aColorStops;
147 auto aSequence = rAny.get<css::awt::ColorStopSequence>();
148 fillFromColorStopSequence(aColorStops, aSequence);
149 return aColorStops;
152 basegfx::BGradient getFromUnoGradient2(css::awt::Gradient2 const& rGradient2)
154 basegfx::BGradient aBGradient;
155 fillFromGradient2(aBGradient, rGradient2);
156 return aBGradient;
159 basegfx::BGradient getFromAny(css::uno::Any const& rAny)
161 basegfx::BGradient aBGradient;
163 if (rAny.has<css::awt::Gradient2>())
165 // we can use awt::Gradient2 directly
166 css::awt::Gradient2 aGradient2;
167 rAny >>= aGradient2;
169 fillFromGradient2(aBGradient, aGradient2);
171 else if (rAny.has<css::awt::Gradient>())
173 // use awt::Gradient
174 css::awt::Gradient aGradient;
175 rAny >>= aGradient;
177 // set values
178 aBGradient.SetGradientStyle(aGradient.Style);
179 aBGradient.SetAngle(Degree10(aGradient.Angle));
180 aBGradient.SetBorder(aGradient.Border);
181 aBGradient.SetXOffset(aGradient.XOffset);
182 aBGradient.SetYOffset(aGradient.YOffset);
183 aBGradient.SetStartIntens(aGradient.StartIntensity);
184 aBGradient.SetEndIntens(aGradient.EndIntensity);
185 aBGradient.SetSteps(aGradient.StepCount);
187 basegfx::BColorStops aColorStops{
188 basegfx::BColorStop(0.0, ::Color(ColorTransparency, aGradient.StartColor).getBColor()),
189 basegfx::BColorStop(1.0, ::Color(ColorTransparency, aGradient.EndColor).getBColor())
192 aBGradient.SetColorStops(aColorStops);
195 return aBGradient;
198 } // end model::gradient
200 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */