1 /*
2 * Copyright (c) 2022-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 "core/components_ng/render/drawing_prop_convertor.h"
17
18 #include "core/components/common/layout/constants.h"
19 #include "core/components/common/properties/text_style.h"
20
21 namespace OHOS::Ace {
22 namespace {
23 constexpr uint8_t UINT32_LEFT_SHIFT_24 = 24;
24 constexpr uint8_t UINT32_LEFT_SHIFT_16 = 16;
25 constexpr uint8_t UINT32_LEFT_SHIFT_8 = 8;
26 } // namespace
ToRSColor(const Color & color)27 RSColor ToRSColor(const Color& color)
28 {
29 return RSColor(color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha());
30 }
31
ToRSColor(const LinearColor & color)32 RSColor ToRSColor(const LinearColor& color)
33 {
34 return RSColor(
35 (static_cast<uint32_t>(std::clamp<int16_t>(color.GetAlpha(), 0, UINT8_MAX)) << UINT32_LEFT_SHIFT_24) |
36 (static_cast<uint32_t>(std::clamp<int16_t>(color.GetRed(), 0, UINT8_MAX)) << UINT32_LEFT_SHIFT_16) |
37 (static_cast<uint32_t>(std::clamp<int16_t>(color.GetGreen(), 0, UINT8_MAX)) << UINT32_LEFT_SHIFT_8) |
38 (static_cast<uint32_t>(std::clamp<int16_t>(color.GetBlue(), 0, UINT8_MAX))));
39 }
40
ToRSRect(const NG::RectF & rect)41 RSRect ToRSRect(const NG::RectF& rect)
42 {
43 return RSRect(rect.Left(), rect.Top(), rect.Right(), rect.Bottom());
44 }
45
ToRSPoint(const NG::PointF & point)46 RSPoint ToRSPoint(const NG::PointF& point)
47 {
48 return RSPoint(point.GetX(), point.GetY());
49 }
50
ToRSCapStyle(const LineCap & lineCap)51 RSPen::CapStyle ToRSCapStyle(const LineCap& lineCap)
52 {
53 RSPen::CapStyle capStyle;
54 switch (lineCap) {
55 case LineCap::SQUARE:
56 capStyle = RSPen::CapStyle::SQUARE_CAP;
57 break;
58 case LineCap::ROUND:
59 capStyle = RSPen::CapStyle::ROUND_CAP;
60 break;
61 default:
62 capStyle = RSPen::CapStyle::FLAT_CAP;
63 break;
64 }
65 return capStyle;
66 }
67
ToRSTextDirection(const TextDirection & txtDir)68 RSTextDirection ToRSTextDirection(const TextDirection& txtDir)
69 {
70 RSTextDirection rsTxtDir = RSTextDirection::LTR;
71 if (txtDir == TextDirection::LTR) {
72 rsTxtDir = RSTextDirection::LTR;
73 } else if (txtDir == TextDirection::RTL) {
74 rsTxtDir = RSTextDirection::RTL;
75 }
76 return rsTxtDir;
77 }
78
ToRSTextAlign(const TextAlign & align)79 RSTextAlign ToRSTextAlign(const TextAlign& align)
80 {
81 // should keep enum same with rosen.
82 return static_cast<RSTextAlign>(align);
83 }
84
ToRSFontWeight(FontWeight fontWeight)85 RSFontWeight ToRSFontWeight(FontWeight fontWeight)
86 {
87 RSFontWeight rsFontWeight = RSFontWeight::W400;
88 switch (fontWeight) {
89 case FontWeight::W100:
90 case FontWeight::LIGHTER:
91 rsFontWeight = RSFontWeight::W100;
92 break;
93 case FontWeight::W200:
94 rsFontWeight = RSFontWeight::W200;
95 break;
96 case FontWeight::W300:
97 rsFontWeight = RSFontWeight::W300;
98 break;
99 case FontWeight::W400:
100 case FontWeight::NORMAL:
101 case FontWeight::REGULAR:
102 rsFontWeight = RSFontWeight::W400;
103 break;
104 case FontWeight::W500:
105 case FontWeight::MEDIUM:
106 rsFontWeight = RSFontWeight::W500;
107 break;
108 case FontWeight::W600:
109 rsFontWeight = RSFontWeight::W600;
110 break;
111 case FontWeight::W700:
112 case FontWeight::BOLD:
113 rsFontWeight = RSFontWeight::W700;
114 break;
115 case FontWeight::W800:
116 rsFontWeight = RSFontWeight::W800;
117 break;
118 case FontWeight::W900:
119 case FontWeight::BOLDER:
120 rsFontWeight = RSFontWeight::W900;
121 break;
122 default:
123 rsFontWeight = RSFontWeight::W400;
124 break;
125 }
126 return rsFontWeight;
127 }
128
ToRSWordBreakType(const WordBreak & wordBreak)129 RSWordBreakType ToRSWordBreakType(const WordBreak& wordBreak)
130 {
131 // should keep enum same with rosen.
132 return static_cast<RSWordBreakType>(wordBreak);
133 }
134
ToRSTextDecoration(TextDecoration textDecoration)135 RSTextDecoration ToRSTextDecoration(TextDecoration textDecoration)
136 {
137 RSTextDecoration rsTextDecoration = RSTextDecoration::NONE;
138 switch (textDecoration) {
139 case TextDecoration::OVERLINE:
140 rsTextDecoration = RSTextDecoration::OVERLINE;
141 break;
142 case TextDecoration::LINE_THROUGH:
143 rsTextDecoration = RSTextDecoration::LINETHROUGH;
144 break;
145 case TextDecoration::UNDERLINE:
146 rsTextDecoration = RSTextDecoration::UNDERLINE;
147 break;
148 default:
149 rsTextDecoration = RSTextDecoration::NONE;
150 break;
151 }
152 return rsTextDecoration;
153 }
154
ToRSTextStyle(const RefPtr<PipelineBase> & context,const TextStyle & textStyle)155 RSTextStyle ToRSTextStyle(const RefPtr<PipelineBase>& context, const TextStyle& textStyle)
156 {
157 RSTextStyle rsTextStyle;
158 rsTextStyle.color_ = ToRSColor(textStyle.GetTextColor());
159 rsTextStyle.decoration_ = ToRSTextDecoration(textStyle.GetTextDecoration());
160 rsTextStyle.decorationColor_ = ToRSColor(textStyle.GetTextDecorationColor());
161 // TODO: convert fontFamily and other styles.
162
163 // TODO: convert missing textBaseline
164 rsTextStyle.fontWeight_ = ToRSFontWeight(textStyle.GetFontWeight());
165 rsTextStyle.fontStyle_ = static_cast<RSFontStyle>(textStyle.GetFontStyle());
166 rsTextStyle.textBaseline_ = static_cast<RSTextBaseline>(textStyle.GetTextBaseline());
167 rsTextStyle.fontFamilies_ = textStyle.GetFontFamilies();
168 if (textStyle.GetTextOverflow() == TextOverflow::ELLIPSIS) {
169 rsTextStyle.ellipsis_ = StringUtils::Str8ToStr16(StringUtils::ELLIPSIS);
170 }
171 if (context) {
172 rsTextStyle.fontSize_ = context->NormalizeToPx(textStyle.GetFontSize());
173 if (textStyle.IsAllowScale() || textStyle.GetFontSize().Unit() == DimensionUnit::FP) {
174 rsTextStyle.fontSize_ = context->NormalizeToPx(textStyle.GetFontSize() * context->GetFontScale());
175 }
176 } else {
177 rsTextStyle.fontSize_ = textStyle.GetFontSize().Value();
178 }
179 if (context) {
180 rsTextStyle.letterSpacing_ = context->NormalizeToPx(textStyle.GetLetterSpacing());
181 }
182 if (textStyle.GetWordSpacing().Unit() == DimensionUnit::PERCENT) {
183 rsTextStyle.wordSpacing_ = textStyle.GetWordSpacing().Value() * rsTextStyle.fontSize_;
184 } else {
185 if (context) {
186 rsTextStyle.wordSpacing_ = context->NormalizeToPx(textStyle.GetWordSpacing());
187 } else {
188 rsTextStyle.wordSpacing_ = textStyle.GetWordSpacing().Value();
189 }
190 }
191
192 if (textStyle.GetLineHeight().Unit() == DimensionUnit::PERCENT) {
193 rsTextStyle.hasHeightOverride_ = true;
194 rsTextStyle.height_ = textStyle.GetLineHeight().Value();
195 } else {
196 double fontSize = rsTextStyle.fontSize_;
197 double lineHeight = textStyle.GetLineHeight().Value();
198 if (context) {
199 lineHeight = context->NormalizeToPx(textStyle.GetLineHeight());
200 }
201 rsTextStyle.hasHeightOverride_ = textStyle.HasHeightOverride();
202 if (!NearEqual(lineHeight, fontSize) && (lineHeight > 0.0) && (!NearZero(fontSize))) {
203 rsTextStyle.height_ = lineHeight / fontSize;
204 } else {
205 LOGD("use default text style height value.");
206 rsTextStyle.height_ = 1;
207 static const int32_t BEGIN_VERSION = 6;
208 auto isBeginVersion = context && context->GetMinPlatformVersion() >= BEGIN_VERSION;
209 if (NearZero(lineHeight) || (!isBeginVersion && NearEqual(lineHeight, fontSize))) {
210 rsTextStyle.hasHeightOverride_ = false;
211 }
212 }
213 }
214 return rsTextStyle;
215 }
216 } // namespace OHOS::Ace
217