• 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 <codecvt>
17 #include <cstdint>
18 
19 #include "ani_common.h"
20 #include "ani_line_metrics_converter.h"
21 #include "ani_paragraph.h"
22 #include "ani_text_utils.h"
23 #include "canvas_ani/ani_canvas.h"
24 #include "font_collection.h"
25 #include "text/font_metrics.h"
26 #include "typography.h"
27 #include "typography_create.h"
28 #include "utils/text_log.h"
29 
30 namespace OHOS::Text::ANI {
31 using namespace OHOS::Rosen;
SetTypography(ani_env * env,std::unique_ptr<OHOS::Rosen::Typography> & typography)32 ani_object AniParagraph::SetTypography(ani_env* env, std::unique_ptr<OHOS::Rosen::Typography>& typography)
33 {
34     ani_object pargraphObj = AniTextUtils::CreateAniObject(env, ANI_CLASS_PARAGRAPH, ":V");
35     Typography* typographyPtr = typography.release();
36     ani_status ret =
37         env->Object_SetFieldByName_Long(pargraphObj, "nativeObj", reinterpret_cast<ani_long>(typographyPtr));
38     if (ret != ANI_OK) {
39         TEXT_LOGE("Failed to create ani Paragraph obj");
40         delete typographyPtr;
41         typographyPtr = nullptr;
42         return AniTextUtils::CreateAniUndefined(env);
43     }
44     return pargraphObj;
45 }
46 
AniInit(ani_vm * vm,uint32_t * result)47 ani_status AniParagraph::AniInit(ani_vm* vm, uint32_t* result)
48 {
49     ani_env* env;
50     ani_status ret = vm->GetEnv(ANI_VERSION_1, &env);
51     if (ret != ANI_OK) {
52         TEXT_LOGE("null env, ret %{public}d", ret);
53         return ANI_NOT_FOUND;
54     }
55 
56     ani_class cls = nullptr;
57     ret = env->FindClass(ANI_CLASS_PARAGRAPH, &cls);
58     if (ret != ANI_OK) {
59         TEXT_LOGE("Failed to find class, ret %{public}d", ret);
60         return ANI_NOT_FOUND;
61     }
62 
63     std::string paintSignature = std::string(ANI_CLASS_CANVAS) + "DD:V";
64     std::string paintOnPathSignature = std::string(ANI_CLASS_CANVAS) + std::string(ANI_CLASS_PATH) + "DD:V";
65     std::array methods = {
66         ani_native_function{"layoutSync", "D:V", reinterpret_cast<void*>(LayoutSync)},
67         ani_native_function{"paint", paintSignature.c_str(), reinterpret_cast<void*>(Paint)},
68         ani_native_function{"paintOnPath", paintOnPathSignature.c_str(), reinterpret_cast<void*>(PaintOnPath)},
69         ani_native_function{"getLongestLine", ":D", reinterpret_cast<void*>(GetLongestLine)},
70         ani_native_function{"getLineMetrics", ":Lescompat/Array;", reinterpret_cast<void*>(GetLineMetrics)},
71         ani_native_function{"nativeGetLineMetricsAt", "D:L@ohos/graphics/text/text/LineMetrics;",
72             reinterpret_cast<void*>(GetLineMetricsAt)},
73     };
74 
75     ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
76     if (ret != ANI_OK) {
77         TEXT_LOGE("Failed to bind methods, ret %{public}d", ret);
78         return ANI_NOT_FOUND;
79     }
80     return ANI_OK;
81 }
82 
LayoutSync(ani_env * env,ani_object object,ani_double width)83 void AniParagraph::LayoutSync(ani_env* env, ani_object object, ani_double width)
84 {
85     Typography* typography = AniTextUtils::GetNativeFromObj<Typography>(env, object);
86     if (typography == nullptr) {
87         TEXT_LOGE("Paragraph is null");
88         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
89         return;
90     }
91     typography->Layout(width);
92 }
93 
Paint(ani_env * env,ani_object object,ani_object canvas,ani_double x,ani_double y)94 void AniParagraph::Paint(ani_env* env, ani_object object, ani_object canvas, ani_double x, ani_double y)
95 {
96     Typography* typography = AniTextUtils::GetNativeFromObj<Typography>(env, object);
97     if (typography == nullptr) {
98         TEXT_LOGE("Paragraph is null");
99         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
100         return;
101     }
102     Drawing::AniCanvas* aniCanvas =  AniTextUtils::GetNativeFromObj<Drawing::AniCanvas>(env, canvas);
103     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
104         TEXT_LOGE("Canvas is null");
105         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "canvas unavailable.");
106         return;
107     }
108     typography->Paint(aniCanvas->GetCanvas(), x, y);
109 }
110 
PaintOnPath(ani_env * env,ani_object object,ani_object canvas,ani_object path,ani_double hOffset,ani_double vOffset)111 void AniParagraph::PaintOnPath(
112     ani_env* env, ani_object object, ani_object canvas, ani_object path, ani_double hOffset, ani_double vOffset)
113 {
114     Typography* typography = AniTextUtils::GetNativeFromObj<Typography>(env, object);
115     if (typography == nullptr) {
116         TEXT_LOGE("Paragraph is null");
117         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
118         return;
119     }
120     Drawing::AniCanvas* aniCanvas =  AniTextUtils::GetNativeFromObj<Drawing::AniCanvas>(env, canvas);
121     if (aniCanvas == nullptr || aniCanvas->GetCanvas() == nullptr) {
122         TEXT_LOGE("Canvas is null");
123         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Canvas unavailable.");
124         return;
125     }
126     Drawing::Path* pathInternal = AniTextUtils::GetNativeFromObj<Drawing::Path>(env, path);
127     if (pathInternal == nullptr) {
128         TEXT_LOGE("Path is null");
129         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Path unavailable.");
130         return;
131     }
132     typography->Paint(aniCanvas->GetCanvas(), pathInternal, hOffset, vOffset);
133 }
134 
GetLongestLine(ani_env * env,ani_object object)135 ani_double AniParagraph::GetLongestLine(ani_env* env, ani_object object)
136 {
137     Typography* typography = AniTextUtils::GetNativeFromObj<Typography>(env, object);
138     if (typography == nullptr) {
139         TEXT_LOGE("Paragraph is null");
140         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
141         return 0;
142     }
143     return typography->GetActualWidth();
144 }
145 
GetLineMetrics(ani_env * env,ani_object object)146 ani_ref AniParagraph::GetLineMetrics(ani_env* env, ani_object object)
147 {
148     ani_object arrayObj = AniTextUtils::CreateAniUndefined(env);
149     Typography* typography = AniTextUtils::GetNativeFromObj<Typography>(env, object);
150     if (typography == nullptr) {
151         TEXT_LOGE("Paragraph is null");
152         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
153         return arrayObj;
154     }
155     std::vector<LineMetrics> vectorLineMetrics = typography->GetLineMetrics();
156     arrayObj = AniTextUtils::CreateAniArray(env, vectorLineMetrics.size());
157     ani_boolean isUndefined;
158     env->Reference_IsUndefined(arrayObj, &isUndefined);
159     if (isUndefined) {
160         TEXT_LOGE("Failed to Create arrayObject");
161         return arrayObj;
162     }
163     ani_size index = 0;
164     for (const auto& lineMetrics : vectorLineMetrics) {
165         ani_object aniObj = AniLineMetricsConverter::ParseLineMetricsToAni(env, lineMetrics);
166         ani_status ret = env->Object_CallMethodByName_Void(arrayObj, "$_set", "ILstd/core/Object;:V", index, aniObj);
167         if (ret != ANI_OK) {
168             TEXT_LOGE("Failed to set lineMetrics item");
169             continue;
170         }
171         index++;
172     }
173     return arrayObj;
174 }
175 
GetLineMetricsAt(ani_env * env,ani_object object,ani_double lineNumber)176 ani_object AniParagraph::GetLineMetricsAt(ani_env* env, ani_object object, ani_double lineNumber)
177 {
178     Typography* typography = AniTextUtils::GetNativeFromObj<Typography>(env, object);
179     if (typography == nullptr) {
180         TEXT_LOGE("Paragraph is null");
181         AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
182         return AniTextUtils::CreateAniUndefined(env);
183     }
184     LineMetrics lineMetrics;
185     if (!typography->GetLineMetricsAt(lineNumber, &lineMetrics)) {
186         TEXT_LOGE("Failed to get line metrics");
187         return AniTextUtils::CreateAniUndefined(env);
188     }
189     return AniLineMetricsConverter::ParseLineMetricsToAni(env, lineMetrics);
190 }
191 } // namespace OHOS::Text::ANI