• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "ani_common.h"
17 #include "ani_drawing_converter.h"
18 #include "ani_text_style_converter.h"
19 #include "ani_text_utils.h"
20 #include "utils/text_log.h"
21 
22 namespace OHOS::Text::ANI {
23 using namespace OHOS::Rosen;
ParseTextStyleToNative(ani_env * env,ani_object obj,TextStyle & textStyle)24 ani_status AniTextStyleConverter::ParseTextStyleToNative(ani_env* env, ani_object obj, TextStyle& textStyle)
25 {
26     ani_class cls = nullptr;
27     ani_status ret = env->FindClass(ANI_INTERFACE_TEXT_STYLE, &cls);
28     if (ret != ANI_OK) {
29         TEXT_LOGE("Failed to find class, ret %{public}d", ret);
30         return ret;
31     }
32     ani_boolean isObj = false;
33     ret = env->Object_InstanceOf(obj, cls, &isObj);
34     if (!isObj) {
35         TEXT_LOGE("Object mismatch, ret %{public}d", ret);
36         return ret;
37     }
38 
39     ParseDecorationToNative(env, obj, textStyle);
40     AniDrawingConverter::ParseDrawingColorToNative(env, obj, "color", textStyle.color);
41 
42     AniTextUtils::ReadOptionalEnumField(env, obj, "fontWeight", textStyle.fontWeight);
43     AniTextUtils::ReadOptionalEnumField(env, obj, "fontStyle", textStyle.fontStyle);
44     if (textStyle.fontStyle == FontStyle::OBLIQUE) {
45         textStyle.fontStyle = FontStyle::ITALIC;
46     }
47     AniTextUtils::ReadOptionalEnumField(env, obj, "baseline", textStyle.baseline);
48 
49     AniTextUtils::ReadOptionalArrayField<std::string>(
50         env, obj, "fontFamilies", textStyle.fontFamilies, [](ani_env* env, ani_ref ref) {
51             std::string utf8Str;
52             AniTextUtils::AniToStdStringUtf8(env, reinterpret_cast<ani_string>(ref), utf8Str);
53             return utf8Str;
54         });
55     AniTextUtils::ReadOptionalDoubleField(env, obj, "fontSize", textStyle.fontSize);
56     AniTextUtils::ReadOptionalDoubleField(env, obj, "letterSpacing", textStyle.letterSpacing);
57     AniTextUtils::ReadOptionalDoubleField(env, obj, "wordSpacing", textStyle.wordSpacing);
58     AniTextUtils::ReadOptionalDoubleField(env, obj, "heightScale", textStyle.heightScale);
59     AniTextUtils::ReadOptionalBoolField(env, obj, "halfLeading", textStyle.halfLeading);
60     AniTextUtils::ReadOptionalBoolField(env, obj, "heightOnly", textStyle.heightOnly);
61     AniTextUtils::ReadOptionalU16StringField(env, obj, "ellipsis", textStyle.ellipsis);
62     AniTextUtils::ReadOptionalEnumField(env, obj, "ellipsisMode", textStyle.ellipsisModal);
63     AniTextUtils::ReadOptionalStringField(env, obj, "locale", textStyle.locale);
64     AniTextUtils::ReadOptionalDoubleField(env, obj, "baselineShift", textStyle.baseLineShift);
65     ParseTextShadowToNative(env, obj, textStyle.shadows);
66     ParseFontFeatureToNative(env, obj, textStyle.fontFeatures);
67     ParseFontVariationToNative(env, obj, textStyle.fontVariations);
68 
69     ani_ref backgroundRectRef = nullptr;
70     if (AniTextUtils::ReadOptionalField(env, obj, "backgroundRect", backgroundRectRef) == ANI_OK
71         && backgroundRectRef != nullptr) {
72         ParseRectStyleToNative(env, reinterpret_cast<ani_object>(backgroundRectRef), textStyle.backgroundRect);
73     }
74 
75     return ANI_OK;
76 }
77 
ParseDecorationToNative(ani_env * env,ani_object obj,TextStyle & textStyle)78 void AniTextStyleConverter::ParseDecorationToNative(ani_env* env, ani_object obj, TextStyle& textStyle)
79 {
80     ani_ref decorationRef = nullptr;
81     if (AniTextUtils::ReadOptionalField(env, obj, "decoration", decorationRef) == ANI_OK && decorationRef != nullptr) {
82         AniTextUtils::ReadOptionalEnumField(
83             env, reinterpret_cast<ani_object>(decorationRef), "textDecoration", textStyle.decoration);
84         AniTextUtils::ReadOptionalEnumField(
85             env, reinterpret_cast<ani_object>(decorationRef), "decorationStyle", textStyle.decorationStyle);
86         AniTextUtils::ReadOptionalDoubleField(env, reinterpret_cast<ani_object>(decorationRef),
87             "decorationThicknessScale", textStyle.decorationThicknessScale);
88         AniDrawingConverter::ParseDrawingColorToNative(
89             env, reinterpret_cast<ani_object>(decorationRef), "color", textStyle.decorationColor);
90     }
91 }
92 
GetPointXFromJsBumber(ani_env * env,ani_object argValue,Drawing::Point & point)93 inline void GetPointXFromJsBumber(ani_env* env, ani_object argValue, Drawing::Point& point)
94 {
95     ani_double objValue{0};
96     ani_status ret = env->Object_GetPropertyByName_Double(argValue, "x", &objValue);
97     if (ret != ANI_OK) {
98         TEXT_LOGE("Param x is invalid, ret %{public}d", ret);
99         return;
100     }
101     point.SetX(objValue);
102 }
103 
GetPointYFromJsBumber(ani_env * env,ani_object argValue,Drawing::Point & point)104 inline void GetPointYFromJsBumber(ani_env* env, ani_object argValue, Drawing::Point& point)
105 {
106     ani_double objValue{0};
107     ani_status ret = env->Object_GetPropertyByName_Double(argValue, "y", &objValue);
108     if (ret != ANI_OK) {
109         TEXT_LOGE("Param y is invalid, ret %{public}d", ret);
110         return;
111     }
112     point.SetY(objValue);
113 }
114 
GetTextShadowPoint(ani_env * env,ani_object obj,Drawing::Point & point)115 inline void GetTextShadowPoint(ani_env* env, ani_object obj, Drawing::Point& point)
116 {
117     GetPointXFromJsBumber(env, obj, point);
118     GetPointYFromJsBumber(env, obj, point);
119 }
120 
ParseTextShadowToNative(ani_env * env,ani_object obj,std::vector<TextShadow> & textShadow)121 void AniTextStyleConverter::ParseTextShadowToNative(ani_env* env, ani_object obj, std::vector<TextShadow>& textShadow)
122 {
123     std::vector<std::string> array;
124     AniTextUtils::ReadOptionalArrayField<std::string>(
125         env, obj, "textShadows", array, [&textShadow](ani_env* env, ani_ref ref) {
126             ani_object shadowObj = reinterpret_cast<ani_object>(ref);
127             ani_class cls = nullptr;
128             ani_status ret = env->FindClass(ANI_INTERFACE_TEXTSHADOW, &cls);
129             if (ret != ANI_OK) {
130                 TEXT_LOGE("Failed to find class, ret %{public}d", ret);
131                 return "";
132             }
133             ani_boolean isObj = false;
134             ret = env->Object_InstanceOf(shadowObj, cls, &isObj);
135             if (!isObj) {
136                 TEXT_LOGE("Object mismatch, ret %{public}d", ret);
137                 return "";
138             }
139 
140             double runTimeRadius;
141             AniTextUtils::ReadOptionalDoubleField(env, shadowObj, "blurRadius", runTimeRadius);
142 
143             Drawing::Color colorSrc = OHOS::Rosen::Drawing::Color::COLOR_BLACK;
144             AniDrawingConverter::ParseDrawingColorToNative(env, shadowObj, "color", colorSrc);
145 
146             Drawing::Point offset(0, 0);
147             ani_ref pointValue = nullptr;
148             ret = AniTextUtils::ReadOptionalField(env, shadowObj, "point", pointValue);
149             if (ret == ANI_OK && pointValue != nullptr) {
150                 GetTextShadowPoint(env, reinterpret_cast<ani_object>(pointValue), offset);
151             }
152 
153             textShadow.emplace_back(TextShadow(colorSrc, offset, runTimeRadius));
154             return "";
155         });
156 }
157 
ParseFontFeatureToNative(ani_env * env,ani_object obj,FontFeatures & fontFeatures)158 void AniTextStyleConverter::ParseFontFeatureToNative(ani_env* env, ani_object obj, FontFeatures& fontFeatures)
159 {
160     std::vector<std::string> array;
161     AniTextUtils::ReadOptionalArrayField<std::string>(
162         env, obj, "fontFeatures", array, [&fontFeatures](ani_env* env, ani_ref ref) {
163             ani_object obj = reinterpret_cast<ani_object>(ref);
164             ani_class cls = nullptr;
165             ani_status ret = env->FindClass(ANI_INTERFACE_FONT_FEATURE, &cls);
166             if (ret != ANI_OK) {
167                 TEXT_LOGE("Failed to find class, ret %{public}d", ret);
168                 return "";
169             }
170             ani_boolean isObj = false;
171             ret = env->Object_InstanceOf(obj, cls, &isObj);
172             if (!isObj) {
173                 TEXT_LOGE("Object mismatch, ret %{public}d", ret);
174                 return "";
175             }
176             ani_ref nameRef = nullptr;
177             ret = env->Object_GetPropertyByName_Ref(obj, "name", &nameRef);
178             if (ret != ANI_OK) {
179                 TEXT_LOGE("Failed to get name, ret %{public}d", ret);
180                 return "";
181             }
182             std::string name;
183             ret = AniTextUtils::AniToStdStringUtf8(env, reinterpret_cast<ani_string>(nameRef), name);
184             if (ret != ANI_OK) {
185                 return "";
186             }
187 
188             ani_double valueDouble;
189             ret = env->Object_GetPropertyByName_Double(obj, "value", &valueDouble);
190             if (ret != ANI_OK) {
191                 TEXT_LOGE("Failed to get value, ret %{public}d", ret);
192                 return "";
193             }
194             fontFeatures.SetFeature(name, static_cast<int>(valueDouble));
195             return "";
196         });
197 }
198 
ParseFontVariationToNative(ani_env * env,ani_object obj,FontVariations & fontVariations)199 void AniTextStyleConverter::ParseFontVariationToNative(ani_env* env, ani_object obj, FontVariations& fontVariations)
200 {
201     std::vector<std::string> array;
202     AniTextUtils::ReadOptionalArrayField<std::string>(
203         env, obj, "fontVariations", array, [&fontVariations](ani_env* env, ani_ref ref) {
204             ani_object obj = reinterpret_cast<ani_object>(ref);
205             ani_class cls = nullptr;
206             ani_status ret = env->FindClass(ANI_INTERFACE_FONT_VARIATION, &cls);
207             if (ret != ANI_OK) {
208                 TEXT_LOGE("Failed to find class, ret %{public}d", ret);
209                 return "";
210             }
211             ani_boolean isObj = false;
212             ret = env->Object_InstanceOf(obj, cls, &isObj);
213             if (!isObj) {
214                 TEXT_LOGE("Object mismatch, ret %{public}d", ret);
215                 return "";
216             }
217             ani_ref axisRef = nullptr;
218             ret = env->Object_GetPropertyByName_Ref(obj, "axis", &axisRef);
219             if (ret != ANI_OK) {
220                 TEXT_LOGE("Failed to get filed axis, ret %{public}d", ret);
221                 return "";
222             }
223             std::string axis;
224             ret = AniTextUtils::AniToStdStringUtf8(env, static_cast<ani_string>(axisRef), axis);
225             if (ret != ANI_OK) {
226                 TEXT_LOGE("Failed to parse string filed axis, ret %{public}d", ret);
227                 return "";
228             }
229             ani_double valueDouble;
230             ret = env->Object_GetPropertyByName_Double(obj, "value", &valueDouble);
231             if (ret != ANI_OK) {
232                 TEXT_LOGE("Failed to get filed value, ret %{public}d", ret);
233                 return "";
234             }
235             fontVariations.SetAxisValue(axis, static_cast<int>(valueDouble));
236             return "";
237         });
238 }
239 
ParseRectStyleToNative(ani_env * env,ani_object obj,RectStyle & rectStyle)240 void AniTextStyleConverter::ParseRectStyleToNative(ani_env* env, ani_object obj, RectStyle& rectStyle)
241 {
242     ani_class cls = nullptr;
243     ani_status ret = env->FindClass(ANI_INTERFACE_RECT_STYLE, &cls);
244     if (ret != ANI_OK) {
245         TEXT_LOGE("Failed to find class, ret %{public}d", ret);
246         return;
247     }
248     ani_boolean isObj = false;
249     ret = env->Object_InstanceOf(obj, cls, &isObj);
250     if (!isObj) {
251         TEXT_LOGE("Object mismatch, ret %{public}d", ret);
252         return;
253     }
254     env->Object_GetPropertyByName_Double(obj, "leftTopRadius", &rectStyle.leftTopRadius);
255     env->Object_GetPropertyByName_Double(obj, "rightTopRadius", &rectStyle.rightTopRadius);
256     env->Object_GetPropertyByName_Double(obj, "rightBottomRadius", &rectStyle.rightBottomRadius);
257     env->Object_GetPropertyByName_Double(obj, "leftBottomRadius", &rectStyle.leftBottomRadius);
258 }
259 
ParseTextStyleToAni(ani_env * env,const TextStyle & textStyle)260 ani_object AniTextStyleConverter::ParseTextStyleToAni(ani_env* env, const TextStyle& textStyle)
261 {
262     ani_object aniObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_TEXT_STYLE, ":V");
263     env->Object_SetPropertyByName_Ref(
264         aniObj, "decoration", AniTextStyleConverter::ParseDecorationToAni(env, textStyle));
265     env->Object_SetPropertyByName_Ref(aniObj, "fontWeight",
266         AniTextUtils::CreateAniEnum(env, ANI_ENUM_FONT_WEIGHT, static_cast<int>(textStyle.fontWeight)));
267     env->Object_SetPropertyByName_Ref(aniObj, "fontStyle",
268         AniTextUtils::CreateAniEnum(env, ANI_ENUM_FONT_STYLE, static_cast<int>(textStyle.fontStyle)));
269     env->Object_SetPropertyByName_Ref(aniObj, "baseline",
270         AniTextUtils::CreateAniEnum(env, ANI_ENUM_TEXT_BASELINE, static_cast<int>(textStyle.baseline)));
271     ani_object fontFamiliesAniObj =
272         AniTextUtils::CreateAniArrayAndInitData(env, textStyle.fontFamilies, textStyle.fontFamilies.size(),
273             [](ani_env* env, const std::string& item) { return AniTextUtils::CreateAniStringObj(env, item); });
274     env->Object_SetPropertyByName_Ref(aniObj, "fontFamilies", fontFamiliesAniObj);
275     env->Object_SetPropertyByName_Ref(aniObj, "fontSize", AniTextUtils::CreateAniDoubleObj(env, textStyle.fontSize));
276     env->Object_SetPropertyByName_Ref(
277         aniObj, "letterSpacing", AniTextUtils::CreateAniDoubleObj(env, textStyle.letterSpacing));
278     env->Object_SetPropertyByName_Ref(
279         aniObj, "wordSpacing", AniTextUtils::CreateAniDoubleObj(env, textStyle.wordSpacing));
280     env->Object_SetPropertyByName_Ref(
281         aniObj, "heightScale", AniTextUtils::CreateAniDoubleObj(env, textStyle.heightScale));
282     env->Object_SetPropertyByName_Ref(
283         aniObj, "halfLeading", AniTextUtils::CreateAniBooleanObj(env, textStyle.halfLeading));
284     env->Object_SetPropertyByName_Ref(
285         aniObj, "heightOnly", AniTextUtils::CreateAniBooleanObj(env, textStyle.heightOnly));
286     env->Object_SetPropertyByName_Ref(aniObj, "ellipsis", AniTextUtils::CreateAniStringObj(env, textStyle.ellipsis));
287     env->Object_SetPropertyByName_Ref(aniObj, "ellipsisMode",
288         AniTextUtils::CreateAniEnum(env, ANI_ENUM_ELLIPSIS_MODE, static_cast<int>(textStyle.ellipsisModal)));
289     env->Object_SetPropertyByName_Ref(aniObj, "locale", AniTextUtils::CreateAniStringObj(env, textStyle.locale));
290     env->Object_SetPropertyByName_Ref(
291         aniObj, "baselineShift", AniTextUtils::CreateAniDoubleObj(env, textStyle.baseLineShift));
292     env->Object_SetPropertyByName_Ref(
293         aniObj, "backgroundRect", AniTextStyleConverter::ParseRectStyleToAni(env, textStyle.backgroundRect));
294     ani_object shadowsAniObj = AniTextUtils::CreateAniArrayAndInitData(env, textStyle.shadows, textStyle.shadows.size(),
295         [](ani_env* env, const TextShadow& item) { return AniTextStyleConverter::ParseTextShadowToAni(env, item); });
296     env->Object_SetPropertyByName_Ref(aniObj, "textShadows", shadowsAniObj);
297     env->Object_SetPropertyByName_Ref(aniObj, "fontFeatures", ParseFontFeaturesToAni(env, textStyle.fontFeatures));
298     return aniObj;
299 }
300 
ParseTextShadowToAni(ani_env * env,const TextShadow & textShadow)301 ani_object AniTextStyleConverter::ParseTextShadowToAni(ani_env* env, const TextShadow& textShadow)
302 {
303     ani_object aniObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_TEXTSHADOW, ":V");
304     env->Object_SetPropertyByName_Double(aniObj, "blurRadius", ani_double(textShadow.blurRadius));
305     return aniObj;
306 }
307 
ParseDecorationToAni(ani_env * env,const TextStyle & textStyle)308 ani_object AniTextStyleConverter::ParseDecorationToAni(ani_env* env, const TextStyle& textStyle)
309 {
310     ani_object aniObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_DECORATION, ":V");
311     env->Object_SetPropertyByName_Ref(aniObj, "textDecoration",
312         AniTextUtils::CreateAniEnum(env, ANI_ENUM_TEXT_DECORATION_TYPE, static_cast<int>(textStyle.decoration)));
313     env->Object_SetPropertyByName_Ref(aniObj, "decorationStyle",
314         AniTextUtils::CreateAniEnum(env, ANI_ENUM_TEXT_DECORATION_STYLE, static_cast<int>(textStyle.decorationStyle)));
315     env->Object_SetPropertyByName_Double(aniObj, "blurRadius", textStyle.decorationThicknessScale);
316     return aniObj;
317 }
318 
ParseRectStyleToAni(ani_env * env,const RectStyle & rectStyle)319 ani_object AniTextStyleConverter::ParseRectStyleToAni(ani_env* env, const RectStyle& rectStyle)
320 {
321     ani_object aniObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_RECT_STYLE, ":V");
322     env->Object_SetPropertyByName_Double(aniObj, "leftTopRadius", rectStyle.leftTopRadius);
323     env->Object_SetPropertyByName_Double(aniObj, "rightTopRadius", rectStyle.rightTopRadius);
324     env->Object_SetPropertyByName_Double(aniObj, "rightBottomRadius", rectStyle.rightBottomRadius);
325     env->Object_SetPropertyByName_Double(aniObj, "leftBottomRadius", rectStyle.leftBottomRadius);
326     return aniObj;
327 }
328 
ParseFontFeaturesToAni(ani_env * env,const FontFeatures & fontFeatures)329 ani_object AniTextStyleConverter::ParseFontFeaturesToAni(ani_env* env, const FontFeatures& fontFeatures)
330 {
331     const std::vector<std::pair<std::string, int>> featureSet = fontFeatures.GetFontFeatures();
332     ani_object arrayObj = AniTextUtils::CreateAniArrayAndInitData(
333         env, featureSet, featureSet.size(), [](ani_env* env, const std::pair<std::string, int>& feature) {
334             ani_object aniObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_FONT_FEATURE, ":V");
335             env->Object_SetPropertyByName_Ref(aniObj, "name", AniTextUtils::CreateAniStringObj(env, feature.first));
336             env->Object_SetPropertyByName_Double(aniObj, "value", feature.second);
337             return aniObj;
338         });
339     return arrayObj;
340 }
341 
ParseFontVariationsToAni(ani_env * env,const FontVariations & fontVariations)342 ani_object AniTextStyleConverter::ParseFontVariationsToAni(ani_env* env, const FontVariations& fontVariations)
343 {
344     ani_object aniObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_FONT_VARIATION, ":V");
345     return aniObj;
346 }
347 } // namespace OHOS::Text::ANI