• 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 #include "rosen_text/symbol_gradient.h"
17 #include "utils/text_log.h"
18 
19 namespace OHOS::Rosen {
20 
SetColors(const std::vector<Drawing::ColorQuad> & colors)21 void SymbolGradient::SetColors(const std::vector<Drawing::ColorQuad>& colors)
22 {
23     colors_ = colors;
24 }
25 
SetPositions(const std::vector<float> & positions)26 void SymbolGradient::SetPositions(const std::vector<float>& positions)
27 {
28     positions_ = positions;
29 }
30 
SetTileMode(Drawing::TileMode tileMode)31 void SymbolGradient::SetTileMode(Drawing::TileMode tileMode)
32 {
33     tileMode_ = tileMode;
34 }
35 
GetColors() const36 const std::vector<Drawing::ColorQuad>& SymbolGradient::GetColors() const
37 {
38     return colors_;
39 }
40 
GetPositions() const41 const std::vector<float>& SymbolGradient::GetPositions() const
42 {
43     return positions_;
44 }
45 
GetTileMode() const46 Drawing::TileMode SymbolGradient::GetTileMode() const
47 {
48     return tileMode_;
49 }
50 
GetGradientType() const51 GradientType SymbolGradient::GetGradientType() const
52 {
53     return gradientType_;
54 }
55 
CreateGradientBrush()56 Drawing::Brush SymbolGradient::CreateGradientBrush()
57 {
58     Drawing::Point offset;
59     return CreateGradientBrush(offset);
60 }
61 
CreateGradientPen()62 Drawing::Pen SymbolGradient::CreateGradientPen()
63 {
64     Drawing::Point offset;
65     return CreateGradientPen(offset);
66 }
67 
CreateGradientBrush(const Drawing::Point & offset)68 Drawing::Brush SymbolGradient::CreateGradientBrush(const Drawing::Point& offset)
69 {
70     Drawing::Brush brush;
71     brush.SetAntiAlias(true);
72     if (!colors_.empty()) {
73         brush.SetColor(colors_[0]);
74     }
75     return brush;
76 }
77 
CreateGradientPen(const Drawing::Point & offset)78 Drawing::Pen SymbolGradient::CreateGradientPen(const Drawing::Point& offset)
79 {
80     Drawing::Pen pen;
81     pen.SetAntiAlias(true);
82     if (!colors_.empty()) {
83         pen.SetColor(colors_[0]);
84     }
85     return pen;
86 }
87 
CreateGradientShader(const Drawing::Point & offset)88 std::shared_ptr<Drawing::ShaderEffect> SymbolGradient::CreateGradientShader(const Drawing::Point& offset)
89 {
90     return nullptr;
91 }
92 
IsNearlyEqual(const std::shared_ptr<SymbolGradient> & gradient)93 bool SymbolGradient::IsNearlyEqual(const std::shared_ptr<SymbolGradient>& gradient)
94 {
95     if (gradient == nullptr) {
96         return false;
97     }
98     bool isUnequal = gradientType_ != gradient->GetGradientType() || tileMode_ != gradient->GetTileMode() ||
99         colors_.size() != gradient->GetColors().size() || positions_.size() != gradient->GetPositions().size();
100     if (isUnequal) {
101         return false;
102     }
103 
104     auto colors = gradient->GetColors();
105     for (size_t i = 0; i < colors_.size(); i++) {
106         if (colors_[i] != colors[i]) {
107             return false;
108         }
109     }
110 
111     auto positions = gradient->GetPositions();
112     for (size_t i = 0; i < positions_.size(); i++) {
113         if (ROSEN_NE<float>(positions_[i], positions[i])) {
114             return false;
115         }
116     }
117     return true;
118 }
119 
SymbolLineGradient(float rangle)120 SymbolLineGradient::SymbolLineGradient(float rangle) : rangle_(rangle)
121 {
122     gradientType_ = GradientType::LINE_GRADIENT;
123 }
124 
SetAngle(float rangle)125 void SymbolLineGradient::SetAngle(float rangle)
126 {
127     rangle_ = rangle;
128 }
129 
GetAngle() const130 float SymbolLineGradient::GetAngle() const
131 {
132     return rangle_;
133 }
134 
Make(const Drawing::Rect & bounds)135 void SymbolLineGradient::Make(const Drawing::Rect& bounds)
136 {
137     PointsFromAngle(rangle_, bounds, startPoint_, endPoint_);
138     startPoint_.Offset(bounds.GetLeft(), bounds.GetTop());
139     endPoint_.Offset(bounds.GetLeft(), bounds.GetTop());
140 }
141 
CreateGradientBrush(const Drawing::Point & offset)142 Drawing::Brush SymbolLineGradient::CreateGradientBrush(const Drawing::Point& offset)
143 {
144     Drawing::Brush brush;
145     brush.SetAntiAlias(true);
146     auto shader = CreateGradientShader(offset);
147     if (shader == nullptr) {
148         return brush;
149     }
150     brush.SetShaderEffect(shader);
151     return brush;
152 }
153 
CreateGradientPen(const Drawing::Point & offset)154 Drawing::Pen SymbolLineGradient::CreateGradientPen(const Drawing::Point& offset)
155 {
156     Drawing::Pen pen;
157     pen.SetAntiAlias(true);
158     auto shader = CreateGradientShader(offset);
159     if (shader == nullptr) {
160         return pen;
161     }
162     pen.SetShaderEffect(shader);
163     return pen;
164 }
165 
CreateGradientShader(const Drawing::Point & offset)166 std::shared_ptr<Drawing::ShaderEffect> SymbolLineGradient::CreateGradientShader(const Drawing::Point& offset)
167 {
168     if (colors_.empty()) {
169         return nullptr;
170     }
171     auto startPoint = startPoint_;
172     auto endPoint = endPoint_;
173     startPoint.Offset(offset.GetX(), offset.GetY());
174     endPoint.Offset(offset.GetX(), offset.GetY());
175     return Drawing::ShaderEffect::CreateLinearGradient(startPoint, endPoint, colors_, positions_, tileMode_);
176 }
177 
AngleToRadian(float angle)178 static float AngleToRadian(float angle)
179 {
180     return static_cast<float>(angle * PI / 180.0f); // 180.0f is used for converting angles to radians
181 }
182 
PointsFromAngle(float angle,const Drawing::Rect & bounds,Drawing::Point & firstPoint,Drawing::Point & secondPoint)183 void SymbolLineGradient::PointsFromAngle(float angle, const Drawing::Rect& bounds,
184     Drawing::Point& firstPoint, Drawing::Point& secondPoint)
185 {
186     float width = bounds.GetWidth();
187     float height = bounds.GetHeight();
188     angle = fmod(angle, 360.0f); // 360.0f is maximum angle
189     if (ROSEN_LNE(angle, 0.0f)) {
190         angle += 360.0f;
191     }
192     firstPoint = Drawing::Point(0.0f, 0.0f);
193     secondPoint = Drawing::Point(0.0f, 0.0f);
194 
195     // 0.0f 90.0f 180.0f 270.0f is the Angle on the coordinate axis
196     if (ROSEN_EQ<float>(angle, 0.0f)) {
197         firstPoint = Drawing::Point(0.0f, height);
198         return;
199     } else if (ROSEN_EQ<float>(angle, 90.0f)) {
200         secondPoint = Drawing::Point(width, 0.0f);
201         return;
202     } else if (ROSEN_EQ<float>(angle, 180.0f)) {
203         secondPoint = Drawing::Point(0.0f, height);
204         return;
205     } else if (ROSEN_EQ<float>(angle, 270.0f)) {
206         firstPoint = Drawing::Point(width, 0.0f);
207         return;
208     }
209     // The Angle is calculated clockwise from point 0
210     float slope = tan(AngleToRadian(90.0f - angle)); // Convert to Cartesian coordinates
211     float perpendicularSlope = ROSEN_NE<float>(slope, 0.0f) ? -1 / slope : 1.0f; // the slope will not be zero
212 
213     float halfHeight = height / 2; // 2 is half
214     float halfWidth = width / 2; // 2 is half
215     Drawing::Point cornerPoint { 0.0f, 0.0f };
216     if (angle < 90.0f) { // 90.0f: the first term on the coordinate axis
217         cornerPoint = Drawing::Point(halfWidth, halfHeight);
218     } else if (angle < 180.0f) { // 180.0f: the second term on the coorinate axis
219         cornerPoint = Drawing::Point(halfWidth, -halfHeight);
220     } else if (angle < 270.0f) { // 270.0f: the third term on the coordinate axis
221         cornerPoint = Drawing::Point(-halfWidth, -halfHeight);
222     } else {
223         cornerPoint = Drawing::Point(-halfWidth, halfHeight);
224     }
225 
226     // Compute b (of y = kx + b) using the corner point.
227     float b = cornerPoint.GetY() - perpendicularSlope * cornerPoint.GetX();
228     float endX = b / (slope - perpendicularSlope);
229     float endY = perpendicularSlope * endX + b;
230 
231     secondPoint = Drawing::Point(halfWidth + endX, halfHeight - endY);
232     firstPoint = Drawing::Point(halfWidth - endX, halfHeight + endY);
233 }
234 
235 
SymbolRadialGradient(const Drawing::Point & centerPtRatio,float radiusRatio)236 SymbolRadialGradient::SymbolRadialGradient(const Drawing::Point& centerPtRatio, float radiusRatio)
237     : centerPtRatio_(centerPtRatio)
238 {
239     radiusRatio_ = std::max(radiusRatio, 0.0f);
240     gradientType_ = GradientType::RADIAL_GRADIENT;
241 }
242 
SetCenterPoint(const Drawing::Point & centerPtRatio)243 void SymbolRadialGradient::SetCenterPoint(const Drawing::Point& centerPtRatio)
244 {
245     centerPtRatio_ = centerPtRatio;
246 }
247 
SetRadiusRatio(float radiusRatio)248 void SymbolRadialGradient::SetRadiusRatio(float radiusRatio)
249 {
250     radiusRatio_ = std::max(radiusRatio, 0.0f);
251     isRadiusRatio_ = true;
252 }
253 
SetRadius(float radius)254 void SymbolRadialGradient::SetRadius(float radius)
255 {
256     radius_ = std::max(radius, 0.0f);
257     isRadiusRatio_ = false;
258 }
259 
GetCenterPoint() const260 Drawing::Point SymbolRadialGradient::GetCenterPoint() const
261 {
262     return centerPtRatio_;
263 }
264 
GetRadius() const265 float SymbolRadialGradient::GetRadius() const
266 {
267     return radius_;
268 }
269 
GetRadiusRatio() const270 float SymbolRadialGradient::GetRadiusRatio() const
271 {
272     return radiusRatio_;
273 }
274 
IsRadiusRatio() const275 bool SymbolRadialGradient::IsRadiusRatio() const
276 {
277     return isRadiusRatio_;
278 }
279 
Make(const Drawing::Rect & bounds)280 void SymbolRadialGradient::Make(const Drawing::Rect& bounds)
281 {
282     float left = bounds.GetLeft();
283     float top = bounds.GetTop();
284     float w = bounds.GetWidth();
285     float h = bounds.GetHeight();
286     float distance = std::sqrt(w * w + h * h);
287     if (isRadiusRatio_) {
288         radius_ = radiusRatio_ > 0 ? distance * radiusRatio_ : 0.0f;
289     } else {
290         radiusRatio_ = distance > 0 ? radius_ / distance : 0.0f;
291     }
292 
293     w = w * centerPtRatio_.GetX();
294     h = h * centerPtRatio_.GetY();
295     centerPt_ = { left + w, top + h};
296 }
297 
CreateGradientBrush(const Drawing::Point & offset)298 Drawing::Brush SymbolRadialGradient::CreateGradientBrush(const Drawing::Point& offset)
299 {
300     Drawing::Brush brush;
301     brush.SetAntiAlias(true);
302     auto shader = CreateGradientShader(offset);
303     if (shader == nullptr) {
304         return brush;
305     }
306     brush.SetShaderEffect(shader);
307     return brush;
308 }
309 
CreateGradientPen(const Drawing::Point & offset)310 Drawing::Pen SymbolRadialGradient::CreateGradientPen(const Drawing::Point& offset)
311 {
312     Drawing::Pen pen;
313     pen.SetAntiAlias(true);
314     auto shader = CreateGradientShader(offset);
315     if (shader == nullptr) {
316         return pen;
317     }
318     pen.SetShaderEffect(shader);
319     return pen;
320 }
321 
CreateGradientShader(const Drawing::Point & offset)322 std::shared_ptr<Drawing::ShaderEffect> SymbolRadialGradient::CreateGradientShader(const Drawing::Point& offset)
323 {
324     if (colors_.empty()) {
325         return nullptr;
326     }
327     auto centerPt = centerPt_;
328     centerPt.Offset(offset.GetX(), offset.GetY());
329     return Drawing::ShaderEffect::CreateRadialGradient(centerPt, radius_, colors_, positions_, tileMode_);
330 }
331 } // namespace OHOS::Rosen