1 /*
2  * Copyright (c) 2021 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_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_SVG_PAINT_STATE_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_SVG_PAINT_STATE_H
18 
19 #include "base/memory/ace_type.h"
20 #include "core/components/common/properties/animatable_double.h"
21 #include "frameworks/core/components/common/layout/constants.h"
22 #include "frameworks/core/components/common/properties/color.h"
23 #include "frameworks/core/components/common/properties/decoration.h"
24 #include "frameworks/core/components/common/properties/paint_state.h"
25 #include "frameworks/core/components/common/properties/text_style.h"
26 
27 namespace OHOS::Ace {
28 
29 const char ATTR_NAME_FILL[] = "fill";
30 const char ATTR_NAME_STROKE[] = "stroke";
31 const char ATTR_NAME_STROKE_WIDTH[] = "stroke-width";
32 const char ATTR_NAME_MITER_LIMIT[] = "stroke-miterlimit";
33 const char ATTR_NAME_STROKE_DASH_OFFSET[] = "stroke-dashoffset";
34 const char ATTR_NAME_FONT_SIZE[] = "font-size";
35 const char ATTR_NAME_FILL_OPACITY[] = "fill-opacity";
36 const char ATTR_NAME_STROKE_OPACITY[] = "stroke-opacity";
37 const char ATTR_NAME_LETTER_SPACING[] = "letter-spacing";
38 const char ANIMATOR_TYPE_MOTION[] = "motion";
39 const char ATTR_NAME_FILL_RULE_EVENODD[] = "evenodd";
40 
41 class FillState {
42 public:
SetContextAndCallback(const WeakPtr<PipelineContext> & context,const RenderNodeAnimationCallback & callback)43     void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback)
44     {
45         color_.SetContextAndCallback(context, callback);
46         opacity_.SetContextAndCallback(context, callback);
47     }
48 
GetColor()49     const AnimatableColor& GetColor() const
50     {
51         return color_;
52     }
53 
54     /**
55      * set fill color
56      * @param color
57      * @param isSelf if false the color value inherited from the parent node, otherwise the value is setted by self
58      */
59     void SetColor(const Color& color, bool isSelf = true, const AnimationOption& option = AnimationOption())
60     {
61         color_ = AnimatableColor(color, option);
62         hasColor_ = isSelf;
63     }
64 
GetGradient()65     std::optional<Gradient>& GetGradient()
66     {
67         return gradient_;
68     }
69 
GetGradient()70     const std::optional<Gradient>& GetGradient() const
71     {
72         return gradient_;
73     }
74 
75     void SetGradient(const Gradient& gradient, bool isSelf = true)
76     {
77         gradient_ = std::make_optional(gradient);
78         hasGradient_ = isSelf;
79     }
80 
81     void SetOpacity(double opacity, bool isSelf = true, const AnimationOption& option = AnimationOption())
82     {
83         opacity_ = AnimatableDouble(opacity, option);
84         hasOpacity_ = isSelf;
85     }
86 
GetOpacity()87     AnimatableDouble GetOpacity() const
88     {
89         return opacity_;
90     }
91 
92     void SetFillRule(const std::string& fillRule, bool isSelf = true)
93     {
94         fillRule_ = fillRule;
95         hasFillRule_ = isSelf;
96     }
97 
GetFillRule()98     const std::string& GetFillRule() const
99     {
100         return fillRule_;
101     }
102 
IsEvenodd()103     bool IsEvenodd() const
104     {
105         return fillRule_ == ATTR_NAME_FILL_RULE_EVENODD;
106     }
107 
Inherit(const FillState & parent)108     void Inherit(const FillState& parent)
109     {
110         if (!hasColor_) {
111             color_ = parent.GetColor();
112         }
113         if (!hasOpacity_) {
114             opacity_ = parent.GetOpacity();
115         }
116         if (!hasFillRule_) {
117             fillRule_ = parent.GetFillRule();
118         }
119         if (!hasGradient_) {
120             gradient_ = parent.GetGradient();
121         }
122     }
123 
HasColor()124     bool HasColor() const
125     {
126         return hasColor_;
127     }
128 
HasOpacity()129     bool HasOpacity() const
130     {
131         return hasOpacity_;
132     }
133 
SetHref(const std::string & href)134     void SetHref(const std::string& href)
135     {
136         href_ = href;
137     }
138 
GetHref()139     const std::string& GetHref() const
140     {
141         return href_;
142     }
143 
144 protected:
145     AnimatableColor color_ = AnimatableColor(Color::BLACK);
146     AnimatableDouble opacity_ = AnimatableDouble(1.0);
147     std::string fillRule_;
148     std::optional<Gradient> gradient_;
149     bool hasColor_ = false;
150     bool hasOpacity_ = false;
151     bool hasFillRule_ = false;
152     bool hasGradient_ = false;
153     std::string href_;
154 };
155 
156 class StrokeState {
157 public:
SetContextAndCallback(const WeakPtr<PipelineContext> & context,const RenderNodeAnimationCallback & callback)158     void SetContextAndCallback(const WeakPtr<PipelineContext>& context, const RenderNodeAnimationCallback& callback)
159     {
160         lineWidth_.SetContextAndCallback(context, callback);
161         color_.SetContextAndCallback(context, callback);
162         opacity_.SetContextAndCallback(context, callback);
163         strokeDashOffset_.SetContextAndCallback(context, callback);
164     }
165 
GetColor()166     const AnimatableColor& GetColor() const
167     {
168         return color_;
169     }
170 
171     void SetColor(const Color& color, bool isSelf = true, const AnimationOption& option = AnimationOption())
172     {
173         color_ = AnimatableColor(color, option);
174         hasColor_ = isSelf;
175     }
176 
177     void SetOpacity(double opacity, bool isSelf = true, const AnimationOption& option = AnimationOption())
178     {
179         opacity_ = AnimatableDouble(opacity, option);
180         hasOpacity_ = isSelf;
181     }
182 
GetOpacity()183     AnimatableDouble GetOpacity() const
184     {
185         return opacity_;
186     }
187 
GetLineCap()188     LineCapStyle GetLineCap() const
189     {
190         return lineCap_;
191     }
192 
193     void SetLineCap(LineCapStyle lineCap, bool isSelf = true)
194     {
195         lineCap_ = lineCap;
196         hasLineCap_ = isSelf;
197     }
198 
GetLineJoin()199     LineJoinStyle GetLineJoin() const
200     {
201         return lineJoin_;
202     }
203 
204     void SetLineJoin(LineJoinStyle lineJoin, bool isSelf = true)
205     {
206         lineJoin_ = lineJoin;
207         hasLineJoin_ = isSelf;
208     }
209 
GetLineWidth()210     const AnimatableDimension& GetLineWidth() const
211     {
212         return lineWidth_;
213     }
214 
215     void SetLineWidth(Dimension lineWidth, bool isSelf = true, const AnimationOption& option = AnimationOption())
216     {
217         lineWidth_ = AnimatableDimension(lineWidth, option);
218         hasLineWidth_ = isSelf;
219     }
220 
GetMiterLimit()221     double GetMiterLimit() const
222     {
223         return miterLimit_;
224     }
225 
226     void SetMiterLimit(double miterLimit, bool isSelf = true)
227     {
228         miterLimit_ = miterLimit;
229         hasMiterLimit_ = isSelf;
230     }
231 
GetLineDash()232     const LineDashParam& GetLineDash() const
233     {
234         return lineDash_;
235     }
236 
237     void SetLineDash(const LineDashParam& lineDash, bool isSelf = true)
238     {
239         lineDash_ = lineDash;
240         hasLineDash_ = isSelf;
241     }
242 
243     void SetLineDashOffset(double offset, bool isSelf = true)
244     {
245         lineDash_.dashOffset = offset;
246         hasDashOffset_ = isSelf;
247     }
248 
249     void SetLineDash(const std::vector<double>& segments, bool isSelf = true)
250     {
251         lineDash_.lineDash = segments;
252         hasLineDash_ = isSelf;
253     }
254 
255     void SetStrokeDashOffset(const Dimension& offset, bool isSelf = true,
256                              const AnimationOption& option = AnimationOption())
257     {
258         strokeDashOffset_ = AnimatableDimension(offset, option);
259         hasStrokeDashOffset_ = isSelf;
260     }
261 
262     void SetStrokeDashArray(const std::vector<Dimension>& segments, bool isSelf = true)
263     {
264         strokeDashArray_ = segments;
265         hasStrokeDashArray_ = isSelf;
266     }
267 
GetStrokeDashOffset()268     const AnimatableDimension& GetStrokeDashOffset() const
269     {
270         return strokeDashOffset_;
271     }
272 
GetStrokeDashArray()273     const std::vector<Dimension>& GetStrokeDashArray() const
274     {
275         return strokeDashArray_;
276     }
277 
HasStroke()278     bool HasStroke() const
279     {
280         // The text outline is drawn only when stroke is set
281         return color_ != Color::TRANSPARENT;
282     }
283 
Inherit(const StrokeState & strokeState)284     void Inherit(const StrokeState& strokeState)
285     {
286         if (!hasColor_) {
287             color_ = strokeState.GetColor();
288         }
289         if (!hasOpacity_) {
290             opacity_ = strokeState.GetOpacity();
291         }
292         if (!hasLineCap_) {
293             lineCap_ = strokeState.GetLineCap();
294         }
295         if (!hasLineJoin_) {
296             lineJoin_ = strokeState.GetLineJoin();
297         }
298         if (!hasLineWidth_) {
299             lineWidth_ = strokeState.GetLineWidth();
300         }
301         if (!hasMiterLimit_) {
302             miterLimit_ = strokeState.GetMiterLimit();
303         }
304         if (!hasLineDash_) {
305             lineDash_.lineDash = strokeState.GetLineDash().lineDash;
306         }
307         if (!hasDashOffset_) {
308             lineDash_.dashOffset = strokeState.GetLineDash().dashOffset;
309         }
310         if (!hasStrokeDashArray_) {
311             strokeDashArray_ = strokeState.GetStrokeDashArray();
312         }
313         if (!hasStrokeDashOffset_) {
314             strokeDashOffset_ = strokeState.GetStrokeDashOffset();
315         }
316         if (!hasGradient_) {
317             gradient_ = strokeState.GetGradient();
318         }
319     }
320 
GetGradient()321     std::optional<Gradient>& GetGradient()
322     {
323         return gradient_;
324     }
325 
GetGradient()326     const std::optional<Gradient>& GetGradient() const
327     {
328         return gradient_;
329     }
330 
331     void SetGradient(const Gradient& gradient, bool isSelf = true)
332     {
333         gradient_ = std::make_optional(gradient);
334         hasGradient_ = isSelf;
335     }
336 
HasColor()337     bool HasColor() const
338     {
339         return hasColor_;
340     }
341 
HasOpacity()342     bool HasOpacity() const
343     {
344         return hasOpacity_;
345     }
346 
HasLineWidth()347     bool HasLineWidth() const
348     {
349         return hasLineWidth_;
350     }
351 
HasMiterLimit()352     bool HasMiterLimit() const
353     {
354         return hasMiterLimit_;
355     }
356 
HasDashOffset()357     bool HasDashOffset() const
358     {
359         return hasDashOffset_;
360     }
361 
SetHref(const std::string & href)362     void SetHref(const std::string& href)
363     {
364         href_ = href;
365     }
366 
GetHref()367     const std::string& GetHref() const
368     {
369         return href_;
370     }
371 
372 private:
373     AnimatableColor color_ = AnimatableColor(Color::TRANSPARENT);
374     AnimatableDouble opacity_ = AnimatableDouble(1.0);
375     LineCapStyle lineCap_ = LineCapStyle::BUTT;
376     LineJoinStyle lineJoin_ = LineJoinStyle::MITER;
377     AnimatableDimension lineWidth_ = AnimatableDimension(1.0);
378     double miterLimit_ = 4.0;
379     LineDashParam lineDash_;
380     std::vector<Dimension> strokeDashArray_;
381     AnimatableDimension strokeDashOffset_;
382     std::optional<Gradient> gradient_;
383     std::string href_;
384     bool hasColor_ = false;
385     bool hasOpacity_ = false;
386     bool hasLineCap_ = false;
387     bool hasLineJoin_ = false;
388     bool hasLineWidth_ = false;
389     bool hasMiterLimit_ = false;
390     bool hasLineDash_ = false;
391     bool hasDashOffset_ = false;
392     bool hasStrokeDashArray_ = false;
393     bool hasStrokeDashOffset_ = false;
394     bool hasGradient_ = false;
395 };
396 
397 class SvgTextStyle {
398 public:
399     void SetFontFamilies(const std::vector<std::string>& fontFamilies, bool isSelf = true)
400     {
401         hasFontFamilies_ = isSelf;
402         textStyle_.SetFontFamilies(fontFamilies);
403     }
404 
GetFontFamilies()405     const std::vector<std::string>& GetFontFamilies() const
406     {
407         return textStyle_.GetFontFamilies();
408     }
409 
410     void SetFontSize(const Dimension& fontSize, bool isSelf = true)
411     {
412         textStyle_.SetFontSize(fontSize);
413         hasFontSize_ = isSelf;
414     }
415 
GetFontSize()416     const Dimension& GetFontSize() const
417     {
418         return textStyle_.GetFontSize();
419     }
420 
421     void SetFontStyle(FontStyle fontStyle, bool isSelf = true)
422     {
423         textStyle_.SetFontStyle(fontStyle);
424         hasFontStyle_ = isSelf;
425     }
426 
GetFontStyle()427     FontStyle GetFontStyle() const
428     {
429         return textStyle_.GetFontStyle();
430     }
431 
432     void SetFontWeight(FontWeight fontWeight, bool isSelf = true)
433     {
434         textStyle_.SetFontWeight(fontWeight);
435         hasFontWeight_ = isSelf;
436     }
437 
GetFontWeight()438     FontWeight GetFontWeight() const
439     {
440         return textStyle_.GetFontWeight();
441     }
442 
443     void SetLetterSpacing(const Dimension& letterSpacing, bool isSelf = true)
444     {
445         textStyle_.SetLetterSpacing(letterSpacing);
446         hasLetterSpacing_ = isSelf;
447     }
448 
GetLetterSpacing()449     const Dimension& GetLetterSpacing() const
450     {
451         return textStyle_.GetLetterSpacing();
452     }
453 
454     void SetTextDecoration(TextDecoration textDecoration, bool isSelf = true)
455     {
456         textStyle_.SetTextDecoration(textDecoration);
457         hasTextDecoration_ = isSelf;
458     }
459 
GetTextDecoration()460     TextDecoration GetTextDecoration() const
461     {
462         return textStyle_.GetTextDecoration();
463     }
464 
GetTextStyle()465     const TextStyle& GetTextStyle() const
466     {
467         return textStyle_;
468     }
469 
Inherit(const SvgTextStyle & parent)470     void Inherit(const SvgTextStyle& parent)
471     {
472         if (!hasFontFamilies_) {
473             textStyle_.SetFontFamilies(parent.GetFontFamilies());
474         }
475         if (!hasFontSize_) {
476             textStyle_.SetFontSize(parent.GetFontSize());
477         }
478         if (!hasFontStyle_) {
479             textStyle_.SetFontStyle(parent.GetFontStyle());
480         }
481         if (!hasFontWeight_) {
482             textStyle_.SetFontWeight(parent.GetFontWeight());
483         }
484         if (!hasLetterSpacing_) {
485             textStyle_.SetLetterSpacing(parent.GetLetterSpacing());
486         }
487         if (!hasTextDecoration_) {
488             textStyle_.SetTextDecoration(parent.GetTextDecoration());
489         }
490     }
491 
HasLetterSpacing()492     bool HasLetterSpacing() const
493     {
494         return hasLetterSpacing_;
495     }
496 
HasFontSize()497     bool HasFontSize() const
498     {
499         return hasFontSize_;
500     }
501 
502 private:
503     TextStyle textStyle_;
504     bool hasFontFamilies_ = false;
505     bool hasFontSize_ = false;
506     bool hasFontStyle_ = false;
507     bool hasFontWeight_ = false;
508     bool hasLetterSpacing_ = false;
509     bool hasTextDecoration_ = false;
510 };
511 
512 class ClipState {
513 public:
514     void SetClipRule(const std::string& clipRule, bool isSelf = true)
515     {
516         clipRule_ = clipRule;
517         hasClipRule_ = isSelf;
518     }
519 
GetClipRule()520     const std::string& GetClipRule() const
521     {
522         return clipRule_;
523     }
524 
IsEvenodd()525     bool IsEvenodd() const
526     {
527         return clipRule_ == ATTR_NAME_FILL_RULE_EVENODD;
528     }
529 
530     void SetHref(const std::string& href, bool isSelf = true)
531     {
532         href_ = href;
533         hasHref_ = isSelf;
534     }
535 
GetHref()536     const std::string& GetHref() const
537     {
538         return href_;
539     }
540 
Inherit(const ClipState & clipState)541     void Inherit(const ClipState& clipState)
542     {
543         if (!hasClipRule_) {
544             clipRule_ = clipState.GetClipRule();
545         }
546         if (!hasHref_) {
547             href_ = clipState.GetHref();
548         }
549     }
550 
551 private:
552     std::string clipRule_;
553     std::string href_;
554     bool hasClipRule_ = false;
555     bool hasHref_ = false;
556 };
557 
558 } // namespace OHOS::Ace
559 
560 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_BASE_PROPERTIES_SVG_PAINT_STATE_H
561