• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "constants_converter.h"
17 #include <cstdint>
18 
19 #include "rosen_text/hm_symbol_txt.h"
20 #include "rosen_text/typography_create.h"
21 #include "rosen_text/typography_style.h"
22 
23 #include "base/i18n/localization.h"
24 #include "core/components_ng/render/drawing.h"
25 #include "core/components_ng/render/adapter/drawing_decoration_painter.h"
26 #include "base/geometry/ng/rect_t.h"
27 #include "draw/color.h"
28 
29 namespace OHOS::Ace::Constants {
30 namespace {
31 const std::string FONTWEIGHT = "wght";
32 constexpr float DEFAULT_MULTIPLE = 100.0f;
33 constexpr float MIN_FONT_WEIGHT = 100.0f;
34 constexpr float DEFAULT_FONT_WEIGHT = 400.0f;
35 constexpr float MAX_FONT_WEIGHT = 900.0f;
36 constexpr int32_t SCALE_EFFECT = 2;
37 constexpr int32_t NONE_EFFECT = 0;
38 constexpr float ORIGINAL_LINE_HEIGHT_SCALE = 1.0f;
39 constexpr float DEFAULT_STROKE_WIDTH = 0.0f;
40 const std::string DEFAULT_SYMBOL_FONTFAMILY = "HM Symbol";
41 struct LineSpaceAndHeightInfo {
42     double lineHeightScale = 0.0;
43     double lineSpacingScale = 0.0;
44     bool lineHeightOnly = false;
45     bool lineSpacingOnly = false;
46 };
47 } // namespace
48 
ConvertTxtFontWeight(FontWeight fontWeight)49 Rosen::FontWeight ConvertTxtFontWeight(FontWeight fontWeight)
50 {
51     Rosen::FontWeight convertValue;
52     switch (fontWeight) {
53         case FontWeight::W100:
54         case FontWeight::LIGHTER:
55             convertValue = Rosen::FontWeight::W100;
56             break;
57         case FontWeight::W200:
58             convertValue = Rosen::FontWeight::W200;
59             break;
60         case FontWeight::W300:
61             convertValue = Rosen::FontWeight::W300;
62             break;
63         case FontWeight::W400:
64         case FontWeight::NORMAL:
65         case FontWeight::REGULAR:
66             convertValue = Rosen::FontWeight::W400;
67             break;
68         case FontWeight::W500:
69         case FontWeight::MEDIUM:
70             convertValue = Rosen::FontWeight::W500;
71             break;
72         case FontWeight::W600:
73             convertValue = Rosen::FontWeight::W600;
74             break;
75         case FontWeight::W700:
76         case FontWeight::BOLD:
77             convertValue = Rosen::FontWeight::W700;
78             break;
79         case FontWeight::W800:
80             convertValue = Rosen::FontWeight::W800;
81             break;
82         case FontWeight::W900:
83         case FontWeight::BOLDER:
84             convertValue = Rosen::FontWeight::W900;
85             break;
86         default:
87             TAG_LOGW(AceLogTag::ACE_FONT, "FontWeight setting error! Now using default FontWeight.");
88             convertValue = Rosen::FontWeight::W400;
89             break;
90     }
91     return convertValue;
92 }
93 
ConvertTxtSymbolType(SymbolType symbolType)94 Rosen::SymbolType ConvertTxtSymbolType(SymbolType symbolType)
95 {
96     Rosen::SymbolType txtSymbolType;
97     switch (symbolType) {
98         case SymbolType::SYSTEM:
99             txtSymbolType = Rosen::SymbolType::SYSTEM;
100             break;
101         case SymbolType::CUSTOM:
102             txtSymbolType = Rosen::SymbolType::CUSTOM;
103             break;
104         default:
105             LOGE("SymbolType setting error! Now using default SymbolType.");
106             txtSymbolType = Rosen::SymbolType::SYSTEM;
107             break;
108     }
109     return txtSymbolType;
110 }
111 
ConvertTxtFontStyle(FontStyle fontStyle)112 Rosen::FontStyle ConvertTxtFontStyle(FontStyle fontStyle)
113 {
114     Rosen::FontStyle convertValue;
115     switch (fontStyle) {
116         case FontStyle::NORMAL:
117             convertValue = Rosen::FontStyle::NORMAL;
118             break;
119         case FontStyle::ITALIC:
120             convertValue = Rosen::FontStyle::ITALIC;
121             break;
122         default:
123             TAG_LOGW(AceLogTag::ACE_FONT, "FontStyle setting error! Now using default FontStyle");
124             convertValue = Rosen::FontStyle::NORMAL;
125             break;
126     }
127     return convertValue;
128 }
129 
ConvertTxtBadgeType(SuperscriptStyle superscript)130 Rosen::TextBadgeType ConvertTxtBadgeType(SuperscriptStyle superscript)
131 {
132     Rosen::TextBadgeType convertValue;
133     switch (superscript) {
134         case SuperscriptStyle::NORMAL:
135             convertValue = Rosen::TextBadgeType::BADGE_NONE;
136             break;
137         case SuperscriptStyle::SUPERSCRIPT:
138             convertValue = Rosen::TextBadgeType::SUPERSCRIPT;
139             break;
140         case SuperscriptStyle::SUBSCRIPT:
141             convertValue = Rosen::TextBadgeType::SUBSCRIPT;
142             break;
143         default:
144             TAG_LOGW(AceLogTag::ACE_FONT, "TextBadgeType setting error! Now using default TextBadgeType");
145             convertValue = Rosen::TextBadgeType::BADGE_NONE;
146             break;
147     }
148     return convertValue;
149 }
150 
ConvertTxtTextBaseline(TextBaseline textBaseline)151 Rosen::TextBaseline ConvertTxtTextBaseline(TextBaseline textBaseline)
152 {
153     Rosen::TextBaseline convertValue;
154     switch (textBaseline) {
155         case TextBaseline::ALPHABETIC:
156             convertValue = Rosen::TextBaseline::ALPHABETIC;
157             break;
158         case TextBaseline::IDEOGRAPHIC:
159             convertValue = Rosen::TextBaseline::IDEOGRAPHIC;
160             break;
161         default:
162             convertValue = Rosen::TextBaseline::ALPHABETIC;
163             break;
164     }
165     return convertValue;
166 }
167 
ConvertTxtTextAlign(TextAlign textAlign)168 Rosen::TextAlign ConvertTxtTextAlign(TextAlign textAlign)
169 {
170     Rosen::TextAlign convertValue;
171     switch (textAlign) {
172         case TextAlign::LEFT:
173             convertValue = Rosen::TextAlign::LEFT;
174             break;
175         case TextAlign::RIGHT:
176             convertValue = Rosen::TextAlign::RIGHT;
177             break;
178         case TextAlign::CENTER:
179             convertValue = Rosen::TextAlign::CENTER;
180             break;
181         case TextAlign::JUSTIFY:
182             convertValue = Rosen::TextAlign::JUSTIFY;
183             break;
184         case TextAlign::START:
185             convertValue = Rosen::TextAlign::START;
186             break;
187         case TextAlign::END:
188             convertValue = Rosen::TextAlign::END;
189             break;
190         default:
191             TAG_LOGW(AceLogTag::ACE_FONT, "TextAlign setting error! Now using default TextAlign");
192             convertValue = Rosen::TextAlign::START;
193             break;
194     }
195     return convertValue;
196 }
197 
ConvertTxtTextVerticalAlign(TextVerticalAlign textVerticalAlign)198 Rosen::TextVerticalAlign ConvertTxtTextVerticalAlign(TextVerticalAlign textVerticalAlign)
199 {
200     Rosen::TextVerticalAlign convertValue;
201     switch (textVerticalAlign) {
202         case TextVerticalAlign::BASELINE:
203             convertValue = Rosen::TextVerticalAlign::BASELINE;
204             break;
205         case TextVerticalAlign::BOTTOM:
206             convertValue = Rosen::TextVerticalAlign::BOTTOM;
207             break;
208         case TextVerticalAlign::CENTER:
209             convertValue = Rosen::TextVerticalAlign::CENTER;
210             break;
211         case TextVerticalAlign::TOP:
212             convertValue = Rosen::TextVerticalAlign::TOP;
213             break;
214         default:
215             TAG_LOGW(AceLogTag::ACE_FONT,
216                 "TextVerticalAlign setting error! Now using default TextVerticalAlign");
217             convertValue = Rosen::TextVerticalAlign::BASELINE;
218             break;
219     }
220     return convertValue;
221 }
222 
ConvertTxtRectHeightStyle(RectHeightStyle heightStyle)223 Rosen::TextRectHeightStyle ConvertTxtRectHeightStyle(RectHeightStyle heightStyle)
224 {
225     switch (heightStyle) {
226         case RectHeightStyle::TIGHT:
227             return Rosen::TextRectHeightStyle::TIGHT;
228         case RectHeightStyle::MAX:
229             return Rosen::TextRectHeightStyle::COVER_TOP_AND_BOTTOM;
230         case RectHeightStyle::INCLUDE_LINE_SPACE_MIDDLE:
231             return Rosen::TextRectHeightStyle::COVER_HALF_TOP_AND_BOTTOM;
232         case RectHeightStyle::INCLUDE_LINE_SPACE_TOP:
233             return Rosen::TextRectHeightStyle::COVER_TOP;
234         case RectHeightStyle::INCLUDE_LINE_SPACE_BOTTOM:
235             return Rosen::TextRectHeightStyle::COVER_BOTTOM;
236         case RectHeightStyle::STRUT:
237             return Rosen::TextRectHeightStyle::FOLLOW_BY_STRUT;
238         default:
239             return Rosen::TextRectHeightStyle::TIGHT;
240     }
241 }
242 
ConvertTxtRectWidthStyle(RectWidthStyle widthStyle)243 Rosen::TextRectWidthStyle ConvertTxtRectWidthStyle(RectWidthStyle widthStyle)
244 {
245     switch (widthStyle) {
246         case RectWidthStyle::TIGHT:
247             return Rosen::TextRectWidthStyle::TIGHT;
248         case RectWidthStyle::MAX:
249             return Rosen::TextRectWidthStyle::MAX;
250         default:
251             return Rosen::TextRectWidthStyle::TIGHT;
252     }
253 }
254 
ConvertTxtTextDirection(TextDirection textDirection)255 Rosen::TextDirection ConvertTxtTextDirection(TextDirection textDirection)
256 {
257     Rosen::TextDirection convertValue;
258     switch (textDirection) {
259         case TextDirection::RTL:
260             convertValue = Rosen::TextDirection::RTL;
261             break;
262         case TextDirection::LTR:
263             convertValue = Rosen::TextDirection::LTR;
264             break;
265         default:
266             TAG_LOGW(AceLogTag::ACE_FONT, "TextDirection setting error! Now using default TextDirection");
267             convertValue = Rosen::TextDirection::LTR;
268             break;
269     }
270     return convertValue;
271 }
272 
ConvertSkColor(Color color)273 SkColor ConvertSkColor(Color color)
274 {
275     return color.GetValue();
276 }
277 
ConvertTxtTextDecoration(const std::vector<TextDecoration> & textDecorations)278 Rosen::TextDecoration ConvertTxtTextDecoration(const std::vector<TextDecoration>& textDecorations)
279 {
280     Rosen::TextDecoration convertValue = Rosen::TextDecoration::NONE;
281     for (TextDecoration textDecoration : textDecorations) {
282         switch (textDecoration) {
283             case TextDecoration::NONE:
284                 convertValue = static_cast<Rosen::TextDecoration>(
285                     static_cast<uint32_t>(convertValue) | static_cast<uint32_t>(Rosen::TextDecoration::NONE));
286                 break;
287             case TextDecoration::UNDERLINE:
288                 convertValue = static_cast<Rosen::TextDecoration>(
289                     static_cast<uint32_t>(convertValue) | static_cast<uint32_t>(Rosen::TextDecoration::UNDERLINE));
290                 break;
291             case TextDecoration::OVERLINE:
292                 convertValue = static_cast<Rosen::TextDecoration>(
293                     static_cast<uint32_t>(convertValue) | static_cast<uint32_t>(Rosen::TextDecoration::OVERLINE));
294                 break;
295             case TextDecoration::LINE_THROUGH:
296                 convertValue = static_cast<Rosen::TextDecoration>(
297                     static_cast<uint32_t>(convertValue) | static_cast<uint32_t>(Rosen::TextDecoration::LINE_THROUGH));
298                 break;
299             default:
300                 TAG_LOGW(AceLogTag::ACE_FONT, "TextDecoration setting error! Now using default TextDecoration");
301                 break;
302         }
303     }
304     return convertValue;
305 }
ConvertTxtTextDecorationStyle(TextDecorationStyle textDecorationStyle)306 Rosen::TextDecorationStyle ConvertTxtTextDecorationStyle(TextDecorationStyle textDecorationStyle)
307 {
308     Rosen::TextDecorationStyle convertValue = Rosen::TextDecorationStyle::SOLID;
309     switch (textDecorationStyle) {
310         case TextDecorationStyle::SOLID:
311             convertValue = Rosen::TextDecorationStyle::SOLID;
312             break;
313         case TextDecorationStyle::DOUBLE:
314             convertValue = Rosen::TextDecorationStyle::DOUBLE;
315             break;
316         case TextDecorationStyle::DOTTED:
317             convertValue = Rosen::TextDecorationStyle::DOTTED;
318             break;
319         case TextDecorationStyle::DASHED:
320             convertValue = Rosen::TextDecorationStyle::DASHED;
321             break;
322         case TextDecorationStyle::WAVY:
323             convertValue = Rosen::TextDecorationStyle::WAVY;
324             break;
325         default:
326             TAG_LOGW(AceLogTag::ACE_FONT, "TextDecorationStyle setting error! Now using default TextDecorationStyle");
327             break;
328     }
329     return convertValue;
330 }
331 
NormalizeToPx(const Dimension & dimension)332 double NormalizeToPx(const Dimension& dimension)
333 {
334     if ((dimension.Unit() == DimensionUnit::VP) || (dimension.Unit() == DimensionUnit::FP)) {
335         return (dimension.Value() * SystemProperties::GetResolution());
336     }
337     return dimension.Value();
338 }
339 
ConvertTxtStyle(const TextStyle & textStyle,Rosen::TextStyle & txtStyle)340 void ConvertTxtStyle(const TextStyle& textStyle, Rosen::TextStyle& txtStyle)
341 {
342     txtStyle.color = ConvertSkColor(textStyle.GetTextColor());
343     txtStyle.fontWeight = ConvertTxtFontWeight(textStyle.GetFontWeight());
344 
345     txtStyle.fontSize = NormalizeToPx(textStyle.GetFontSize());
346 
347     txtStyle.fontStyle = ConvertTxtFontStyle(textStyle.GetFontStyle());
348 
349     if (textStyle.GetWordSpacing().Unit() == DimensionUnit::PERCENT) {
350         txtStyle.wordSpacing = textStyle.GetWordSpacing().Value() * txtStyle.fontSize;
351     } else {
352         txtStyle.wordSpacing = NormalizeToPx(textStyle.GetWordSpacing());
353     }
354 
355     txtStyle.letterSpacing = NormalizeToPx(textStyle.GetLetterSpacing());
356     txtStyle.baseLineShift = -NormalizeToPx(textStyle.GetBaselineOffset());
357     txtStyle.fontFamilies = textStyle.GetFontFamilies();
358     ConvertSymbolTxtStyle(textStyle, txtStyle);
359     txtStyle.baseline = ConvertTxtTextBaseline(textStyle.GetTextBaseline());
360     txtStyle.decoration = ConvertTxtTextDecoration(textStyle.GetTextDecoration());
361     txtStyle.decorationColor = ConvertSkColor(textStyle.GetTextDecorationColor());
362     txtStyle.decorationStyle = ConvertTxtTextDecorationStyle(textStyle.GetTextDecorationStyle());
363     txtStyle.locale = Localization::GetInstance()->GetFontLocale();
364     txtStyle.halfLeading = textStyle.GetHalfLeading();
365 
366     for (auto& spanShadow : textStyle.GetTextShadows()) {
367         Rosen::TextShadow txtShadow;
368         txtShadow.color = spanShadow.GetColor().GetValue();
369         txtShadow.offset.SetX(spanShadow.GetOffset().GetX());
370         txtShadow.offset.SetY(spanShadow.GetOffset().GetY());
371         txtShadow.blurRadius = spanShadow.GetBlurRadius();
372         txtStyle.shadows.emplace_back(txtShadow);
373     }
374 
375     if (textStyle.GetLineHeight().Unit() == DimensionUnit::PERCENT) {
376         txtStyle.heightOnly = true;
377         txtStyle.heightScale = textStyle.GetLineHeight().Value();
378     } else {
379         double fontSize = txtStyle.fontSize;
380         double lineHeight = textStyle.GetLineHeight().Value();
381 
382         lineHeight = NormalizeToPx(textStyle.GetLineHeight());
383 
384         txtStyle.heightOnly = textStyle.HasHeightOverride();
385         if (!NearEqual(lineHeight, fontSize) && (lineHeight > 0.0) && (!NearZero(fontSize))) {
386             txtStyle.heightScale = lineHeight / fontSize;
387         } else {
388             txtStyle.heightScale = 1;
389             if (NearZero(lineHeight) || NearEqual(lineHeight, fontSize)) {
390                 txtStyle.heightOnly = false;
391             }
392         }
393     }
394 
395     // set font variant
396     auto fontFeatures = textStyle.GetFontFeatures();
397     if (!fontFeatures.empty()) {
398         Rosen::FontFeatures features;
399         for (auto iter = fontFeatures.begin(); iter != fontFeatures.end(); ++iter) {
400             features.SetFeature(iter->first, iter->second);
401         }
402         txtStyle.fontFeatures = features;
403     }
404     auto textBackgroundStyle = textStyle.GetTextBackgroundStyle();
405     CHECK_NULL_VOID(textBackgroundStyle.has_value());
406     txtStyle.styleId = textBackgroundStyle->groupId;
407     if (textBackgroundStyle->backgroundColor.has_value()) {
408         txtStyle.backgroundRect.color = textBackgroundStyle->backgroundColor.value().GetValue();
409     }
410     auto radius = textBackgroundStyle->backgroundRadius;
411     CHECK_NULL_VOID(radius.has_value());
412     auto radiusConverter = [](const std::optional<Dimension>& radius) -> double {
413         CHECK_NULL_RETURN(radius.has_value(), 0);
414         return NormalizeToPx(radius.value());
415     };
416     txtStyle.backgroundRect.leftTopRadius = radiusConverter(radius->radiusTopLeft);
417     txtStyle.backgroundRect.rightTopRadius = radiusConverter(radius->radiusTopRight);
418     txtStyle.backgroundRect.leftBottomRadius = radiusConverter(radius->radiusBottomLeft);
419     txtStyle.backgroundRect.rightBottomRadius = radiusConverter(radius->radiusBottomRight);
420 }
421 
422 // ConvertTxtStyle helper for LineSpacing and LineHeight etc
ConvertSpacingAndHeigh(const TextStyle & textStyle,const WeakPtr<PipelineBase> & context,Rosen::TextStyle & txtStyle,LineSpaceAndHeightInfo & info)423 void ConvertSpacingAndHeigh(
424     const TextStyle& textStyle, const WeakPtr<PipelineBase>& context, Rosen::TextStyle& txtStyle,
425     LineSpaceAndHeightInfo& info)
426 {
427     auto pipelineContext = context.Upgrade();
428     if (textStyle.GetLineHeight().Unit() == DimensionUnit::PERCENT) {
429         info.lineHeightOnly = true;
430         info.lineHeightScale = textStyle.GetLineHeight().Value();
431     } else {
432         double fontSize = txtStyle.fontSize;
433         double lineHeight = textStyle.GetLineHeight().Value();
434         if (pipelineContext) {
435             lineHeight = textStyle.GetLineHeight().ConvertToPxDistribute(
436                 textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
437         }
438         info.lineHeightOnly = textStyle.HasHeightOverride();
439         if (!NearEqual(lineHeight, fontSize) && (lineHeight > 0.0) && (!NearZero(fontSize))) {
440             info.lineHeightScale = lineHeight / fontSize;
441         } else {
442             info.lineHeightScale = 1;
443             static const int32_t beginVersion = 6;
444             auto isBeginVersion = pipelineContext && pipelineContext->GetMinPlatformVersion() >= beginVersion;
445             if (NearZero(lineHeight) || (!isBeginVersion && NearEqual(lineHeight, fontSize))) {
446                 info.lineHeightOnly = false;
447             }
448         }
449     }
450     if (textStyle.GetLineSpacing().Unit() == DimensionUnit::PERCENT) {
451         info.lineSpacingOnly = true;
452         info.lineSpacingScale = textStyle.GetLineSpacing().Value();
453     } else {
454         double fontSize = txtStyle.fontSize;
455         double lineSpacing = textStyle.GetLineSpacing().Value();
456         if (pipelineContext) {
457             lineSpacing = textStyle.GetLineSpacing().ConvertToPxDistribute(
458                 textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
459         }
460         info.lineSpacingOnly = true;
461         if (!NearEqual(lineSpacing, fontSize) && (lineSpacing > 0.0) && (!NearZero(fontSize))) {
462             info.lineSpacingScale = lineSpacing / fontSize;
463         } else {
464             info.lineSpacingScale = 1;
465             if (NearZero(lineSpacing)) {
466                 info.lineSpacingOnly = false;
467             }
468         }
469     }
470 }
471 
ConvertGradiantColor(const TextStyle & textStyle,const WeakPtr<PipelineBase> & context,Rosen::TextStyle & txtStyle,OHOS::Ace::FontForegroudGradiantColor & gradiantColor)472 void ConvertGradiantColor(
473     const TextStyle& textStyle, const WeakPtr<PipelineBase>& context, Rosen::TextStyle& txtStyle,
474     OHOS::Ace::FontForegroudGradiantColor & gradiantColor)
475 {
476     RSBrush brush;
477     std::vector<Rosen::Drawing::PointF> points = {
478         Rosen::Drawing::PointF(gradiantColor.points[0].GetX(), gradiantColor.points[0].GetY()),
479         Rosen::Drawing::PointF(gradiantColor.points[1].GetX(), gradiantColor.points[1].GetY())
480     };
481     std::vector<RSColorQuad> colors;
482     std::vector<RSScalar> pos;
483     for (size_t i = 0; i < gradiantColor.colors.size(); i++) {
484         colors.push_back(ConvertSkColor(gradiantColor.colors[i]));
485         // IsValid ensures colors and scalars are same size
486         pos.push_back(gradiantColor.scalars[i]);
487     }
488     brush.SetShaderEffect(
489         RSShaderEffect::CreateLinearGradient(points.at(0), points.at(1), colors, pos, RSTileMode::CLAMP));
490     if (txtStyle.foregroundBrush) {
491         txtStyle.foregroundBrush->SetShaderEffect(
492             RSShaderEffect::CreateLinearGradient(points.at(0), points.at(1), colors, pos, RSTileMode::CLAMP));
493     } else {
494         txtStyle.foregroundBrush = brush;
495     }
496 }
497 
ConvertTxtStyle(const TextStyle & textStyle,const WeakPtr<PipelineBase> & context,Rosen::TextStyle & txtStyle)498 void ConvertTxtStyle(const TextStyle& textStyle, const WeakPtr<PipelineBase>& context, Rosen::TextStyle& txtStyle)
499 {
500     txtStyle.relayoutChangeBitmap = textStyle.GetReLayoutTextStyleBitmap();
501     txtStyle.textStyleUid  = static_cast<unsigned long>(textStyle.GetTextStyleUid());
502     txtStyle.color = ConvertSkColor(textStyle.GetTextColor());
503     txtStyle.fontWeight = ConvertTxtFontWeight(textStyle.GetFontWeight());
504     txtStyle.symbol.SetSymbolType(ConvertTxtSymbolType(textStyle.GetSymbolType()));
505     auto fontWeightValue = (static_cast<int32_t>(
506             ConvertTxtFontWeight(textStyle.GetFontWeight())) + 1) * DEFAULT_MULTIPLE;
507     auto pipelineContext = context.Upgrade();
508     if (pipelineContext) {
509         fontWeightValue = fontWeightValue * pipelineContext->GetFontWeightScale();
510     }
511     if (textStyle.GetEnableVariableFontWeight()) {
512         fontWeightValue = textStyle.GetVariableFontWeight();
513         if (LessNotEqual(fontWeightValue, MIN_FONT_WEIGHT) || GreatNotEqual(fontWeightValue, MAX_FONT_WEIGHT)) {
514             fontWeightValue = DEFAULT_FONT_WEIGHT;
515         }
516     }
517     txtStyle.fontVariations.SetAxisValue(FONTWEIGHT, fontWeightValue);
518     // Font size must be px when transferring to Rosen::TextStyle
519     txtStyle.fontSize = textStyle.GetFontSize().ConvertToPxDistribute(
520         textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
521     txtStyle.fontStyle = ConvertTxtFontStyle(textStyle.GetFontStyle());
522     txtStyle.badgeType = ConvertTxtBadgeType(textStyle.GetSuperscript());
523 
524     if (textStyle.GetWordSpacing().Unit() == DimensionUnit::PERCENT) {
525         txtStyle.wordSpacing = textStyle.GetWordSpacing().Value() * txtStyle.fontSize;
526     } else {
527         if (pipelineContext) {
528             txtStyle.wordSpacing = textStyle.GetWordSpacing().ConvertToPxDistribute(
529                 textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
530         } else {
531             txtStyle.wordSpacing = textStyle.GetWordSpacing().Value();
532         }
533     }
534     if (pipelineContext) {
535         txtStyle.letterSpacing = textStyle.GetLetterSpacing().ConvertToPxDistribute(
536             textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
537         txtStyle.baseLineShift = -textStyle.GetBaselineOffset().ConvertToPxDistribute(
538             textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
539     }
540 
541     txtStyle.fontFamilies = textStyle.GetFontFamilies();
542     ConvertSymbolTxtStyle(textStyle, txtStyle);
543     txtStyle.baseline = ConvertTxtTextBaseline(textStyle.GetTextBaseline());
544     txtStyle.decoration = ConvertTxtTextDecoration(textStyle.GetTextDecoration());
545     txtStyle.decorationColor = ConvertSkColor(textStyle.GetTextDecorationColor());
546     txtStyle.decorationStyle = ConvertTxtTextDecorationStyle(textStyle.GetTextDecorationStyle());
547     txtStyle.decorationThicknessScale = static_cast<double>(textStyle.GetLineThicknessScale());
548     txtStyle.locale = Localization::GetInstance()->GetFontLocale();
549     txtStyle.halfLeading = textStyle.GetHalfLeading();
550 
551     if (textStyle.GetStrokeWidth().Value() != DEFAULT_STROKE_WIDTH) {
552         RSPen pen;
553         pen.SetWidth(std::abs(textStyle.GetStrokeWidth().ConvertToPxDistribute(
554             textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale())));
555         pen.SetColor(textStyle.GetStrokeColor().GetValue());
556         txtStyle.foregroundPen = pen;
557     }
558     if (textStyle.GetStrokeWidth().Value() < DEFAULT_STROKE_WIDTH) {
559         RSBrush brush;
560         brush.SetColor(textStyle.GetTextColor().GetValue());
561         txtStyle.foregroundBrush = brush;
562     }
563     if (textStyle.GetColorShaderStyle().has_value() && textStyle.GetStrokeWidth().Value() == DEFAULT_STROKE_WIDTH) {
564         RSBrush brush;
565         auto shaderEffect =
566             RSRecordingShaderEffect::CreateColorShader(textStyle.GetColorShaderStyle().value().GetValue());
567         brush.SetShaderEffect(shaderEffect);
568         txtStyle.foregroundBrush = brush;
569     }
570     for (auto& spanShadow : textStyle.GetTextShadows()) {
571         Rosen::TextShadow txtShadow;
572         txtShadow.color = spanShadow.GetColor().GetValue();
573         txtShadow.offset.SetX(spanShadow.GetOffset().GetX());
574         txtShadow.offset.SetY(spanShadow.GetOffset().GetY());
575         txtShadow.blurRadius = spanShadow.GetBlurRadius();
576         txtStyle.shadows.emplace_back(txtShadow);
577     }
578 
579     LineSpaceAndHeightInfo info;
580     ConvertSpacingAndHeigh(textStyle, context, txtStyle, info);
581     txtStyle.heightOnly = info.lineHeightOnly || info.lineSpacingOnly;
582     if (info.lineHeightOnly && info.lineSpacingOnly) {
583         txtStyle.heightScale = info.lineHeightScale + info.lineSpacingScale;
584     } else if (info.lineHeightOnly && !info.lineSpacingOnly) {
585         txtStyle.heightScale = info.lineHeightScale;
586     } else if (!info.lineHeightOnly && info.lineSpacingOnly) {
587         txtStyle.heightScale = ORIGINAL_LINE_HEIGHT_SCALE + info.lineSpacingScale;
588     } else {
589         txtStyle.heightScale = 1;
590     }
591 
592     // set font variant
593     auto fontFeatures = textStyle.GetFontFeatures();
594     if (!fontFeatures.empty()) {
595         Rosen::FontFeatures features;
596         for (auto iter = fontFeatures.begin(); iter != fontFeatures.end(); ++iter) {
597             features.SetFeature(iter->first, iter->second);
598         }
599         txtStyle.fontFeatures = features;
600     }
601 
602     auto gradiantColor = textStyle.GetFontForegroudGradiantColor().value_or(FontForegroudGradiantColor());
603     if (gradiantColor.IsValid()) {
604         ConvertGradiantColor(textStyle, context, txtStyle, gradiantColor);
605     }
606 
607     auto textBackgroundStyle = textStyle.GetTextBackgroundStyle();
608     CHECK_NULL_VOID(textBackgroundStyle.has_value());
609     txtStyle.styleId = textBackgroundStyle->groupId;
610     if (textBackgroundStyle->backgroundColor.has_value()) {
611         txtStyle.backgroundRect.color = textBackgroundStyle->backgroundColor.value().GetValue();
612     }
613     auto radius = textBackgroundStyle->backgroundRadius;
614     CHECK_NULL_VOID(radius.has_value());
615     auto radiusConverter = [context = pipelineContext, textStyle](const std::optional<Dimension>& radius) -> double {
616         CHECK_NULL_RETURN(radius.has_value(), 0);
617         CHECK_NULL_RETURN(context, radius->Value());
618         return radius.value().ConvertToPxDistribute(
619             textStyle.GetMinFontScale(), textStyle.GetMaxFontScale(), textStyle.IsAllowScale());
620     };
621     txtStyle.backgroundRect.leftTopRadius = radiusConverter(radius->radiusTopLeft);
622     txtStyle.backgroundRect.rightTopRadius = radiusConverter(radius->radiusTopRight);
623     txtStyle.backgroundRect.leftBottomRadius = radiusConverter(radius->radiusBottomLeft);
624     txtStyle.backgroundRect.rightBottomRadius = radiusConverter(radius->radiusBottomRight);
625 }
626 
ToGradient(const Gradient & gradient)627 NG::Gradient ToGradient(const Gradient& gradient)
628 {
629     NG::Gradient retGradient;
630     retGradient.CreateGradientWithType(static_cast<NG::GradientType>(gradient.GetType()));
631     if (gradient.GetType() == GradientType::LINEAR) {
632         auto angle = gradient.GetLinearGradient().angle;
633         if (angle.has_value()) {
634             retGradient.GetLinearGradient()->angle = CalcDimension(angle.value());
635         }
636         auto linearX = gradient.GetLinearGradient().linearX;
637         if (linearX.has_value()) {
638             retGradient.GetLinearGradient()->linearX = static_cast<NG::GradientDirection>(linearX.value());
639         }
640         auto linearY = gradient.GetLinearGradient().linearY;
641         if (linearY.has_value()) {
642             retGradient.GetLinearGradient()->linearY = static_cast<NG::GradientDirection>(linearY.value());
643         }
644     }
645     if (gradient.GetType() == GradientType::RADIAL) {
646         auto radialCenterX = gradient.GetRadialGradient().radialCenterX;
647         if (radialCenterX.has_value()) {
648             retGradient.GetRadialGradient()->radialCenterX = CalcDimension(radialCenterX.value());
649         }
650         auto radialCenterY = gradient.GetRadialGradient().radialCenterY;
651         if (radialCenterY.has_value()) {
652             retGradient.GetRadialGradient()->radialCenterY = CalcDimension(radialCenterY.value());
653         }
654         auto radialVerticalSize = gradient.GetRadialGradient().radialVerticalSize;
655         if (radialVerticalSize.has_value()) {
656             retGradient.GetRadialGradient()->radialVerticalSize = CalcDimension(radialVerticalSize.value());
657         }
658         auto radialHorizontalSize = gradient.GetRadialGradient().radialHorizontalSize;
659         if (radialHorizontalSize.has_value()) {
660             retGradient.GetRadialGradient()->radialHorizontalSize = CalcDimension(radialHorizontalSize.value());
661         }
662     }
663     retGradient.SetRepeat(gradient.GetRepeat());
664     const auto& colorStops = gradient.GetColors();
665     for (const auto& item : colorStops) {
666         NG::GradientColor gradientColor;
667         gradientColor.SetColor(item.GetColor());
668         gradientColor.SetHasValue(item.GetHasValue());
669         gradientColor.SetDimension(item.GetDimension());
670         retGradient.AddColor(gradientColor);
671     }
672     return retGradient;
673 }
674 
ConvertForegroundPaint(const TextStyle & textStyle,double width,double height,Rosen::TextStyle & txtStyle)675 void ConvertForegroundPaint(const TextStyle& textStyle, double width, double height, Rosen::TextStyle& txtStyle)
676 {
677     if (!textStyle.GetGradient().has_value() || textStyle.GetStrokeWidth().Value() != DEFAULT_STROKE_WIDTH) {
678         return;
679     }
680     txtStyle.textStyleUid = static_cast<unsigned long>(textStyle.GetTextStyleUid());
681     txtStyle.relayoutChangeBitmap = textStyle.GetReLayoutTextStyleBitmap();
682     auto gradient = textStyle.GetGradient().value();
683     GradientType type = gradient.GetType();
684     if (type != GradientType::LINEAR && type != GradientType::RADIAL) {
685         return;
686     }
687     RSBrush brush;
688     auto shaderEffect =
689         NG::DrawingDecorationPainter::CreateGradientShader(ToGradient(gradient), NG::SizeF(width, height));
690     brush.SetShaderEffect(shaderEffect);
691     txtStyle.foregroundBrush = brush;
692 }
693 
ConvertToNativeSymbolColor(const std::vector<SymbolGradient> & intermediate)694 Rosen::SymbolColor ConvertToNativeSymbolColor(const std::vector<SymbolGradient>& intermediate)
695 {
696     Rosen::SymbolColor symbolColor;
697     for (const auto& grad : intermediate) {
698         auto nativeGradient = CreateNativeGradient(grad);
699         symbolColor.colorType = static_cast<Rosen::SymbolColorType>(grad.gradientType);
700         symbolColor.gradients.push_back(nativeGradient);
701     }
702 
703     return symbolColor;
704 }
705 
ConvertSymbolTxtStyle(const TextStyle & textStyle,Rosen::TextStyle & txtStyle)706 void ConvertSymbolTxtStyle(const TextStyle& textStyle, Rosen::TextStyle& txtStyle)
707 {
708     if (!textStyle.isSymbolGlyph_) {
709         return;
710     }
711 
712     txtStyle.isSymbolGlyph = true;
713     txtStyle.symbol.SetRenderMode(textStyle.GetRenderStrategy());
714     const std::vector<Color>& symbolColor = textStyle.GetSymbolColorList();
715     std::vector<Rosen::Drawing::Color> symbolColors;
716     for (size_t i = 0; i < symbolColor.size(); i++) {
717         symbolColors.emplace_back(ConvertSkColor(symbolColor[i]));
718     }
719     txtStyle.symbol.SetRenderColor(symbolColors);
720 
721     if (auto intermediateStyle = textStyle.GetShaderStyle(); !intermediateStyle.empty()) {
722         txtStyle.symbol.SetSymbolColor(ConvertToNativeSymbolColor(intermediateStyle));
723     }
724 
725     txtStyle.symbol.SetSymbolShadow(ConvertToNativeSymbolShadow(textStyle.GetSymbolShadow()));
726 
727     if (textStyle.GetSymbolEffectOptions().has_value()) {
728         auto options = textStyle.GetSymbolEffectOptions().value();
729         auto effectType = options.GetEffectType();
730         txtStyle.symbol.SetSymbolEffect(static_cast<uint32_t>(effectType));
731         txtStyle.symbol.SetAnimationStart(options.GetIsTxtActive());
732         if (options.GetCommonSubType().has_value()) {
733             auto commonType = static_cast<uint16_t>(options.GetCommonSubType().value());
734             txtStyle.symbol.SetCommonSubType(commonType == 1 ? Rosen::Drawing::DrawingCommonSubType::UP
735                                                              : Rosen::Drawing::DrawingCommonSubType::DOWN);
736         }
737         if (effectType == SymbolEffectType::HIERARCHICAL && options.GetFillStyle().has_value()) {
738             txtStyle.symbol.SetAnimationMode(static_cast<uint16_t>(options.GetFillStyle().value()));
739         } else {
740             if (options.GetScopeType().has_value()) {
741                 txtStyle.symbol.SetAnimationMode(static_cast<uint16_t>(options.GetScopeType().value()));
742             }
743         }
744     } else {
745         auto effectStrategyValue = textStyle.GetEffectStrategy();
746         if (effectStrategyValue < NONE_EFFECT || effectStrategyValue > SCALE_EFFECT) {
747             effectStrategyValue = NONE_EFFECT;
748         }
749         txtStyle.symbol.SetSymbolEffect(effectStrategyValue);
750         txtStyle.symbol.SetAnimationStart(true);
751     }
752     if (txtStyle.symbol.GetSymbolType() != Rosen::SymbolType::CUSTOM) {
753         txtStyle.fontFamilies.push_back(DEFAULT_SYMBOL_FONTFAMILY);
754     }
755     txtStyle.symbol.SetSymbolBitmap(textStyle.GetReLayoutSymbolStyleBitmap());
756     txtStyle.symbol.SetSymbolUid(textStyle.GetSymbolUid());
757 }
758 
ConvertSkRect(const Rosen::Drawing::RectF & skRect)759 Rect ConvertSkRect(const Rosen::Drawing::RectF& skRect)
760 {
761     Rect result;
762     result.SetLeft(skRect.GetLeft());
763     result.SetTop(skRect.GetTop());
764     result.SetWidth(skRect.GetWidth());
765     result.SetHeight(skRect.GetHeight());
766     return result;
767 }
768 
ConvertPlaceholderAlignment(PlaceholderAlignment textDecoration)769 Rosen::PlaceholderVerticalAlignment ConvertPlaceholderAlignment(PlaceholderAlignment textDecoration)
770 {
771     Rosen::PlaceholderVerticalAlignment convertValue = Rosen::PlaceholderVerticalAlignment::OFFSET_AT_BASELINE;
772     switch (textDecoration) {
773         case PlaceholderAlignment::BASELINE:
774             convertValue = Rosen::PlaceholderVerticalAlignment::OFFSET_AT_BASELINE;
775             break;
776         case PlaceholderAlignment::ABOVEBASELINE:
777             convertValue = Rosen::PlaceholderVerticalAlignment::ABOVE_BASELINE;
778             break;
779         case PlaceholderAlignment::BELOWBASELINE:
780             convertValue = Rosen::PlaceholderVerticalAlignment::BELOW_BASELINE;
781             break;
782         case PlaceholderAlignment::TOP:
783             convertValue = Rosen::PlaceholderVerticalAlignment::TOP_OF_ROW_BOX;
784             break;
785         case PlaceholderAlignment::BOTTOM:
786             convertValue = Rosen::PlaceholderVerticalAlignment::BOTTOM_OF_ROW_BOX;
787             break;
788         case PlaceholderAlignment::MIDDLE:
789             convertValue = Rosen::PlaceholderVerticalAlignment::CENTER_OF_ROW_BOX;
790             break;
791         case PlaceholderAlignment::FOLLOW_PARAGRAPH:
792             convertValue = Rosen::PlaceholderVerticalAlignment::FOLLOW_PARAGRAPH;
793             break;
794         default:
795             TAG_LOGW(AceLogTag::ACE_FONT, "PlaceholderAlignment setting error! Now using default PlaceholderAlignment");
796             break;
797     }
798     return convertValue;
799 }
800 
ConvertPlaceholderRun(const PlaceholderRun & span,Rosen::PlaceholderSpan & txtSpan)801 void ConvertPlaceholderRun(const PlaceholderRun& span, Rosen::PlaceholderSpan& txtSpan)
802 {
803     txtSpan.width = span.width;
804     txtSpan.height = span.height;
805     txtSpan.alignment = ConvertPlaceholderAlignment(span.alignment);
806     txtSpan.baseline = ConvertTxtTextBaseline(span.baseline);
807     txtSpan.baselineOffset = span.baseline_offset;
808 }
809 
GetVariableFontWeight(FontWeight fontWeight)810 float GetVariableFontWeight(FontWeight fontWeight)
811 {
812     return (static_cast<int32_t>(ConvertTxtFontWeight(fontWeight)) + 1) * DEFAULT_MULTIPLE;
813 }
814 
ConvertToNativeSymbolShadow(const SymbolShadow & shadow)815 std::optional<Rosen::SymbolShadow> ConvertToNativeSymbolShadow(const SymbolShadow& shadow)
816 {
817     if (shadow.IsDefault()) {
818         return std::nullopt;
819     }
820     Rosen::SymbolShadow rosenShadow;
821 
822     rosenShadow.color = ConvertSkColor(shadow.color);
823 
824     rosenShadow.offset = Rosen::Drawing::Point(
825         shadow.offset.first,
826         shadow.offset.second);
827 
828     rosenShadow.blurRadius = shadow.radius;
829 
830     return rosenShadow;
831 }
832 
CreateNativeGradient(const SymbolGradient & grad)833 std::shared_ptr<Rosen::SymbolGradient> CreateNativeGradient(const SymbolGradient& grad)
834 {
835     switch (grad.type) {
836         case SymbolGradientType::COLOR_SHADER: {
837             auto gradient = std::make_shared<Rosen::SymbolGradient>();
838             gradient->SetColors(ConvertColors(grad.symbolColor));
839             return gradient;
840         }
841         case SymbolGradientType::LINEAR_GRADIENT: {
842             auto gradient = std::make_shared<Rosen::SymbolLineGradient>(grad.angle.value_or(0.0f));
843             gradient->SetColors(ConvertColors(grad.symbolColor));
844             gradient->SetPositions(grad.symbolOpacities);
845             gradient->SetTileMode(grad.repeating ?
846                 Rosen::Drawing::TileMode::REPEAT : Rosen::Drawing::TileMode::CLAMP);
847             return gradient;
848         }
849         case SymbolGradientType::RADIAL_GRADIENT: {
850             auto getCoord = [](const std::optional<Dimension>& dim) {
851                 if (!dim) return Dimension(0.0).ConvertToPx();
852                 return dim->Unit() == DimensionUnit::PERCENT ? dim->Value() : dim->ConvertToPx();
853             };
854             Rosen::Drawing::Point centerPt(
855                 static_cast<float>(getCoord(grad.radialCenterX)),
856                 static_cast<float>(getCoord(grad.radialCenterY))
857             );
858             auto gradient = std::make_shared<Rosen::SymbolRadialGradient>
859                             (centerPt, grad.radius.value_or(Dimension(0.0)).Value());
860             if (grad.radius.has_value() && grad.radius.value().Unit() != DimensionUnit::PERCENT) {
861                 gradient->SetRadius(static_cast<float>(grad.radius.value().ConvertToPx()));
862             }
863             gradient->SetColors(ConvertColors(grad.symbolColor));
864             gradient->SetPositions(grad.symbolOpacities);
865             gradient->SetTileMode(grad.repeating ?
866                 Rosen::Drawing::TileMode::REPEAT : Rosen::Drawing::TileMode::CLAMP);
867             return gradient;
868         }
869         default:
870             return nullptr;
871     }
872 }
873 
ConvertColors(const std::vector<Color> & colors)874 std::vector<Rosen::Drawing::ColorQuad> ConvertColors(const std::vector<Color>& colors)
875 {
876     std::vector<Rosen::Drawing::ColorQuad> symbolColors;
877     for (const auto& color : colors) {
878         symbolColors.emplace_back(ConvertSkColor(color));
879     }
880     return symbolColors;
881 }
882 } // namespace OHOS::Ace::Constants
883