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