• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_UI_PROPERTIES_GRADIENT_PROPERTY_H
17 #define FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_UI_PROPERTIES_GRADIENT_PROPERTY_H
18 
19 #include <array>
20 #include <memory>
21 #include <optional>
22 #include <regex>
23 #include <vector>
24 #include <map>
25 #include <functional>
26 
27 #include "ui/base/geometry/dimension.h"
28 #include "ui/base/geometry/ng/offset_t.h"
29 #include "ui/base/ace_type.h"
30 #include "ui/base/macros.h"
31 #include "ui/base/utils/utils.h"
32 #include "ui/properties/color.h"
33 #include "ui/properties/linear_color.h"
34 #include "ui/resource/resource_object.h"
35 
36 namespace OHOS::Ace::NG {
37 
38 constexpr float BOX_END_SIZE = 100.0f;
39 
40 enum class GradientDirection {
41     LEFT = 0,
42     TOP,
43     RIGHT,
44     BOTTOM,
45     LEFT_TOP,
46     LEFT_BOTTOM,
47     RIGHT_TOP,
48     RIGHT_BOTTOM,
49     NONE,
50     START_TO_END,
51     END_TO_START,
52 };
53 
54 enum class GradientType {
55     LINEAR,
56     RADIAL,
57     SWEEP,
58     CONIC,
59 };
60 
61 enum class RadialSizeType {
62     CLOSEST_SIDE,
63     CLOSEST_CORNER,
64     FARTHEST_SIDE,
65     FARTHEST_CORNER,
66     NONE,
67 };
68 
69 enum class RadialShapeType {
70     CIRCLE,
71     ELLIPSE,
72     NONE,
73 };
74 
75 enum class SpreadMethod {
76     PAD,
77     REFLECT,
78     REPEAT,
79 };
80 
81 struct LinearGradientInfo {
82     float x1 = 0.0f;
83     float x2 = 0.0f;
84     float y1 = 0.0f;
85     float y2 = 0.0f;
86     bool operator==(const LinearGradientInfo& other) const
87     {
88         return (
89             NearEqual(x1, other.x1) && NearEqual(x2, other.x2) && NearEqual(y1, other.y1) && NearEqual(y2, other.y2));
90     }
91 };
92 
93 struct RadialGradientInfo {
94     float r = 0.0f;
95     float cx = 0.0f;
96     float cy = 0.0f;
97     float fx = 0.0f;
98     float fy = 0.0f;
99     bool operator==(const RadialGradientInfo& other) const
100     {
101         return (NearEqual(r, other.r) && NearEqual(cx, other.cx) && NearEqual(cy, other.cy) &&
102                 NearEqual(fx, other.fx) && NearEqual(fy, other.fy));
103     }
104 };
105 
106 class GradientColor final {
107 public:
108     GradientColor() = default;
109     ~GradientColor() = default;
110 
GradientColor(const Color & color)111     explicit GradientColor(const Color& color)
112     {
113         color_ = color;
114     }
115 
116     void SetDimension(double value, DimensionUnit unit = DimensionUnit::PERCENT)
117     {
118         if (value < 0.0) {
119             return;
120         }
121         if (unit == DimensionUnit::PERCENT && value > BOX_END_SIZE) {
122             return;
123         }
124         dimension_ = Dimension(value, unit);
125     }
126 
SetDimension(const Dimension & dimension)127     void SetDimension(const Dimension& dimension)
128     {
129         if (dimension.Value() < 0.0) {
130             return;
131         }
132         if (dimension.Unit() == DimensionUnit::PERCENT && dimension.Value() > BOX_END_SIZE) {
133             return;
134         }
135         dimension_ = dimension;
136     }
137 
SetHasValue(bool hasValue)138     void SetHasValue(bool hasValue)
139     {
140         hasValue_ = hasValue;
141     }
142 
SetColor(const Color & color)143     void SetColor(const Color& color)
144     {
145         color_ = color;
146     }
147 
GetColor()148     const Color& GetColor() const
149     {
150         return color_;
151     }
152 
SetLinearColor(const LinearColor & linearColor)153     void SetLinearColor(const LinearColor& linearColor)
154     {
155         linearColor_ = linearColor;
156     }
157 
GetLinearColor()158     const LinearColor& GetLinearColor() const
159     {
160         return linearColor_;
161     }
162 
GetDimension()163     const Dimension& GetDimension() const
164     {
165         return dimension_;
166     }
167 
GetHasValue()168     bool GetHasValue() const
169     {
170         return hasValue_;
171     }
172 
SetOpacity(double opacity)173     void SetOpacity(double opacity)
174     {
175         opacity_ = opacity;
176     }
177 
GetOpacity()178     double GetOpacity() const
179     {
180         return opacity_;
181     }
182 
183     bool operator==(const GradientColor& other) const
184     {
185         return (hasValue_ == other.GetHasValue() && color_ == other.GetColor() && dimension_ == other.GetDimension() &&
186                 opacity_ == other.GetOpacity() && linearColor_ == other.GetLinearColor());
187     }
188 
189 private:
190     bool hasValue_ = true;
191     Color color_ { Color::TRANSPARENT };
192     LinearColor linearColor_ { LinearColor::TRANSPARENT };
193     Dimension dimension_ { BOX_END_SIZE, DimensionUnit::PERCENT };
194     float opacity_ = 1.0f;
195 };
196 
197 struct ACE_EXPORT RadialGradient {
198     // size type
199     std::optional<RadialSizeType> radialSizeType;
200     // shape circle or ellipse
201     std::optional<RadialShapeType> radialShape;
202     // size in x-axis
203     std::optional<Dimension> radialHorizontalSize;
204     // size in y-axis
205     std::optional<Dimension> radialVerticalSize;
206     // center of shape
207     std::optional<Dimension> radialCenterX;
208     std::optional<Dimension> radialCenterY;
209 
210     std::optional<Dimension> fRadialCenterX;
211     std::optional<Dimension> fRadialCenterY;
212 
213     bool operator==(const RadialGradient& other) const
214     {
215         return (radialSizeType == other.radialSizeType && radialShape == other.radialShape &&
216                 radialHorizontalSize == other.radialHorizontalSize && radialVerticalSize == other.radialVerticalSize &&
217                 radialCenterX == other.radialCenterX && radialCenterY == other.radialCenterY &&
218                 fRadialCenterX == other.fRadialCenterX && fRadialCenterY == other.fRadialCenterY);
219     }
220 };
221 
222 struct ACE_EXPORT LinearGradient {
223     // direction in x-axis
224     std::optional<GradientDirection> linearX;
225     // direction in y-axis
226     std::optional<GradientDirection> linearY;
227     // angle of gradient line in bearing angle
228     std::optional<Dimension> angle;
229 
230     std::optional<Dimension> x1;
231     std::optional<Dimension> y1;
232     std::optional<Dimension> x2;
233     std::optional<Dimension> y2;
234 
235     // is direction in x-axis
IsXAxisLinearGradient236     static bool IsXAxis(GradientDirection direction)
237     {
238         return (direction == GradientDirection::LEFT || direction == GradientDirection::RIGHT ||
239                 direction == GradientDirection::START_TO_END || direction == GradientDirection::END_TO_START);
240     }
241 
242     bool operator==(const LinearGradient& other) const
243     {
244         return (x1 == other.x1 && y1 == other.y1 && x2 == other.x2 && y2 == other.y2 && linearX == other.linearX &&
245                 linearY == other.linearY && angle == other.angle);
246     }
247 };
248 
249 struct ACE_EXPORT SweepGradient {
250     // center of x-axis
251     std::optional<Dimension> centerX;
252     // center of y-axis
253     std::optional<Dimension> centerY;
254     // startAngle in degree
255     std::optional<Dimension> startAngle;
256     // endAngle in degree
257     std::optional<Dimension> endAngle;
258     // rotation in degree
259     std::optional<Dimension> rotation;
260 
261     bool operator==(const OHOS::Ace::NG::SweepGradient& other) const
262     {
263         return (centerX == other.centerX && centerY == other.centerY && startAngle == other.startAngle &&
264                 endAngle == other.endAngle && rotation == other.rotation);
265     }
266 };
267 
268 class ACE_FORCE_EXPORT Gradient final {
269 public:
270     ACE_FORCE_EXPORT void AddColor(const GradientColor& color);
271 
272     void ClearColors();
273 
IsSweepGradientValid()274     bool IsSweepGradientValid() const
275     {
276         if (sweepGradient_->startAngle.has_value() && sweepGradient_->endAngle.has_value()) {
277             return LessOrEqual(sweepGradient_->startAngle.value().Value(), sweepGradient_->endAngle.value().Value());
278         }
279         if (sweepGradient_->startAngle.has_value() && !sweepGradient_->endAngle.has_value()) {
280             return LessOrEqual(sweepGradient_->startAngle.value().Value(), 0.0);
281         }
282         if (!sweepGradient_->startAngle.has_value() && sweepGradient_->endAngle.has_value()) {
283             return LessOrEqual(0.0, sweepGradient_->endAngle.value().Value());
284         }
285         return true;
286     }
287 
IsValid()288     bool IsValid() const
289     {
290         if (GetType() == GradientType::SWEEP) {
291             return IsSweepGradientValid() && colors_.size() > 1;
292         }
293         return colors_.size() > 1;
294     }
295 
SetRepeat(bool repeat)296     void SetRepeat(bool repeat)
297     {
298         repeat_ = repeat;
299     }
300 
GetRepeat()301     bool GetRepeat() const
302     {
303         return repeat_;
304     }
305 
GetColors()306     const std::vector<GradientColor>& GetColors() const
307     {
308         return colors_;
309     }
310 
GetBeginOffset()311     const std::shared_ptr<OffsetF>& GetBeginOffset() const
312     {
313         return beginOffset_;
314     }
315 
SetBeginOffset(const OffsetF & beginOffset)316     void SetBeginOffset(const OffsetF& beginOffset)
317     {
318         beginOffset_ = std::make_shared<OffsetF>(beginOffset);
319     }
320 
GetEndOffset()321     const std::shared_ptr<OffsetF>& GetEndOffset() const
322     {
323         return endOffset_;
324     }
325 
SetEndOffset(const OffsetF & endOffset)326     void SetEndOffset(const OffsetF& endOffset)
327     {
328         endOffset_ = std::make_shared<OffsetF>(endOffset);
329     }
330 
GetInnerRadius()331     double GetInnerRadius() const
332     {
333         return innerRadius_;
334     }
335 
SetInnerRadius(double innerRadius)336     void SetInnerRadius(double innerRadius)
337     {
338         innerRadius_ = innerRadius;
339     }
340 
GetOuterRadius()341     double GetOuterRadius() const
342     {
343         return outerRadius_;
344     }
345 
SetOuterRadius(double outerRadius)346     void SetOuterRadius(double outerRadius)
347     {
348         outerRadius_ = outerRadius;
349     }
350 
GetType()351     GradientType GetType() const
352     {
353         return type_;
354     }
355 
356     void CreateGradientWithType(GradientType type);
357 
ToString()358     std::string ToString() const
359     {
360         return std::string("Gradient (")
361             .append(beginOffset_->ToString())
362             .append(",")
363             .append(std::to_string(innerRadius_))
364             .append(" --- ")
365             .append(endOffset_->ToString())
366             .append(",")
367             .append(std::to_string(outerRadius_))
368             .append(")");
369     }
370 
GetSweepGradient()371     std::shared_ptr<SweepGradient> GetSweepGradient()
372     {
373         return sweepGradient_;
374     }
375 
GetSweepGradient()376     const std::shared_ptr<SweepGradient> GetSweepGradient() const
377     {
378         return sweepGradient_;
379     }
380 
SetSweepGradient(const SweepGradient & sweepGradient)381     void SetSweepGradient(const SweepGradient& sweepGradient)
382     {
383         sweepGradient_ = std::make_shared<SweepGradient>(sweepGradient);
384     }
385 
GetRadialGradient()386     std::shared_ptr<RadialGradient>& GetRadialGradient()
387     {
388         return radialGradient_;
389     }
390 
GetRadialGradient()391     const std::shared_ptr<RadialGradient>& GetRadialGradient() const
392     {
393         return radialGradient_;
394     }
395 
SetRadialGradient(const RadialGradient & radialGradient)396     void SetRadialGradient(const RadialGradient& radialGradient)
397     {
398         radialGradient_ = std::make_shared<RadialGradient>(radialGradient);
399     }
400 
GetLinearGradient()401     std::shared_ptr<LinearGradient>& GetLinearGradient()
402     {
403         return linearGradient_;
404     }
405 
GetLinearGradient()406     const std::shared_ptr<LinearGradient>& GetLinearGradient() const
407     {
408         return linearGradient_;
409     }
410 
SetLinearGradient(const LinearGradient & linearGradient)411     void SetLinearGradient(const LinearGradient& linearGradient)
412     {
413         linearGradient_ = std::make_shared<LinearGradient>(linearGradient);
414     }
415 
SetDirection(const GradientDirection & direction)416     void SetDirection(const GradientDirection& direction)
417     {
418         if (LinearGradient::IsXAxis(direction)) {
419             linearGradient_->linearX = direction;
420         } else {
421             linearGradient_->linearY = direction;
422         }
423     }
424 
SetSpreadMethod(SpreadMethod spreadMethod)425     void SetSpreadMethod(SpreadMethod spreadMethod)
426     {
427         spreadMethod_ = spreadMethod;
428     }
429 
SetGradientTransform(const std::string & gradientTransform)430     void SetGradientTransform(const std::string& gradientTransform)
431     {
432         gradientTransform_ = gradientTransform;
433     }
434 
GetSpreadMethod()435     SpreadMethod GetSpreadMethod() const
436     {
437         return spreadMethod_;
438     }
439 
GetGradientTransform()440     const std::string& GetGradientTransform() const
441     {
442         return gradientTransform_;
443     }
444 
GetRadialGradientInfo()445     const std::shared_ptr<RadialGradientInfo>& GetRadialGradientInfo() const
446     {
447         return radialGradientInfo_;
448     }
449 
SetRadialGradientInfo(const RadialGradientInfo & radialGradientInfo)450     void SetRadialGradientInfo(const RadialGradientInfo& radialGradientInfo)
451     {
452         radialGradientInfo_ = std::make_shared<RadialGradientInfo>(radialGradientInfo);
453     }
454 
GetLinearGradientInfo()455     const std::shared_ptr<LinearGradientInfo> GetLinearGradientInfo() const
456     {
457         return linearGradientInfo_;
458     }
459 
SetLinearGradientInfo(const LinearGradientInfo & linearGradientInfo)460     void SetLinearGradientInfo(const LinearGradientInfo& linearGradientInfo)
461     {
462         linearGradientInfo_ = std::make_shared<LinearGradientInfo>(linearGradientInfo);
463     }
464 
465     template<class T>
CmpSharedPtr(const std::shared_ptr<T> & a,const std::shared_ptr<T> & b)466     static bool CmpSharedPtr(const std::shared_ptr<T>& a, const std::shared_ptr<T>& b)
467     {
468         if (a == b) {
469             return true;
470         }
471         if (a && b) {
472             return *a == *b;
473         }
474         return false;
475     }
476 
477     bool operator==(const Gradient& other) const
478     {
479         return (type_ == other.GetType() && repeat_ == other.GetRepeat() && colors_ == other.GetColors() &&
480                 CmpSharedPtr(radialGradient_, other.GetRadialGradient()) &&
481                 CmpSharedPtr(linearGradient_, other.GetLinearGradient()) &&
482                 CmpSharedPtr(sweepGradient_, other.GetSweepGradient()) &&
483                 beginOffset_ == other.GetBeginOffset() &&
484                 endOffset_ == other.GetEndOffset() && spreadMethod_ == other.GetSpreadMethod() &&
485                 gradientTransform_ == other.GetGradientTransform() &&
486                 linearGradientInfo_ == other.GetLinearGradientInfo() &&
487                 radialGradientInfo_ == other.GetRadialGradientInfo());
488     }
489 
490     bool operator!=(const Gradient& other) const
491     {
492         return !(*this == other);
493     }
494     struct resourceUpdater {
495         RefPtr<ResourceObject> resObj;
496         std::function<void(const RefPtr<ResourceObject>&, NG::Gradient&)> updateFunc;
497     };
498     std::map<std::string, resourceUpdater> resMap_;
499 
AddResource(const std::string & key,const RefPtr<ResourceObject> & resObj,std::function<void (const RefPtr<ResourceObject> &,NG::Gradient &)> && updateFunc)500     void AddResource(
501         const std::string& key,
502         const RefPtr<ResourceObject>& resObj,
503         std::function<void(const RefPtr<ResourceObject>&, NG::Gradient&)>&& updateFunc)
504     {
505         if (resObj == nullptr || !updateFunc) {
506             return;
507         }
508         resMap_[key] = {resObj, std::move(updateFunc)};
509     }
510 
ReloadResources()511     void ReloadResources()
512     {
513         for (const auto& [key, resourceUpdater] : resMap_) {
514             resourceUpdater.updateFunc(resourceUpdater.resObj, *this);
515         }
516     }
517 
518 private:
519     GradientType type_ = GradientType::LINEAR;
520     bool repeat_ = false;
521     std::vector<GradientColor> colors_;
522     // for RadialGradient
523     std::shared_ptr<RadialGradient> radialGradient_;
524     // for LinearGradient
525     std::shared_ptr<LinearGradient> linearGradient_;
526     // for SweepGradient
527     std::shared_ptr<SweepGradient> sweepGradient_;
528     // used for CanvasLinearGradient
529     std::shared_ptr<OffsetF> beginOffset_;
530     std::shared_ptr<OffsetF> endOffset_;
531     // used for CanvasRadialGradient
532     float innerRadius_ = 0.0f;
533     float outerRadius_ = 0.0;
534     SpreadMethod spreadMethod_ = SpreadMethod::PAD;
535     std::string gradientTransform_;
536     std::shared_ptr<LinearGradientInfo> linearGradientInfo_;
537     std::shared_ptr<RadialGradientInfo> radialGradientInfo_;
538 };
539 
540 
541 class LinearGradientBlurPara final {
542 public:
543     Dimension blurRadius_;
544     std::vector<std::pair<float, float>> fractionStops_;
545     GradientDirection direction_;
546 
LinearGradientBlurPara(const Dimension blurRadius,const std::vector<std::pair<float,float>> fractionStops,const GradientDirection direction)547     LinearGradientBlurPara(const Dimension blurRadius,
548         const std::vector<std::pair<float, float>>fractionStops, const GradientDirection direction)
549         : blurRadius_(blurRadius), fractionStops_(fractionStops), direction_(direction) {}
550     bool operator==(const LinearGradientBlurPara& other) const
551     {
552         return NearEqual(blurRadius_, other.blurRadius_) && NearEqual(fractionStops_, other.fractionStops_) &&
553                                                             NearEqual(direction_, other.direction_);
554     }
555 
556     ~LinearGradientBlurPara() = default;
557 };
558 
559 class MagnifierParams final {
560 public:
561     float factor_ = 0.f;
562     float width_ = 0.f;
563     float height_ = 0.f;
564     float borderWidth_ = 0.f;
565     float cornerRadius_ = 0.f;
566     float offsetX_ = 0.f;
567     float offsetY_ = 0.f;
568 
569     float shadowOffsetX_ = 0.f;
570     float shadowOffsetY_ = 0.f;
571     float shadowSize_ = 0.f;
572     float shadowStrength_ = 0.f;
573 
574     bool changed_ = false;
575 
576     // rgba
577     uint32_t gradientMaskColor1_ = 0x00000000;
578     uint32_t gradientMaskColor2_ = 0x00000000;
579     uint32_t outerContourColor1_ = 0x00000000;
580     uint32_t outerContourColor2_ = 0x00000000;
581 
582     bool operator==(const MagnifierParams& other) const
583     {
584         return NearEqual(factor_, other.factor_) && NearEqual(width_, other.width_) &&
585                NearEqual(height_, other.height_) && NearEqual(borderWidth_, other.borderWidth_) &&
586                NearEqual(cornerRadius_, other.cornerRadius_) && NearEqual(offsetX_, other.offsetX_) &&
587                NearEqual(offsetY_, other.offsetY_) && NearEqual(shadowOffsetX_, other.shadowOffsetX_) &&
588                NearEqual(shadowOffsetY_, other.shadowOffsetY_) && NearEqual(shadowSize_, other.shadowSize_) &&
589                NearEqual(shadowStrength_, other.shadowStrength_) &&
590                NearEqual(gradientMaskColor1_, other.gradientMaskColor1_) &&
591                NearEqual(gradientMaskColor2_, other.gradientMaskColor2_) &&
592                NearEqual(outerContourColor1_, other.outerContourColor1_) &&
593                NearEqual(outerContourColor2_, other.outerContourColor2_) &&
594                changed_ == other.changed_;
595     }
596     MagnifierParams() = default;
597     ~MagnifierParams() = default;
598 };
599 
600 } // namespace OHOS::Ace::NG
601 
602 #endif // FOUNDATION_ACE_INTERFACES_INNER_API_ACE_KIT_INCLUDE_UI_PROPERTIES_GRADIENT_PROPERTY_H
603