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 <algorithm>
17 #include <codecvt>
18 #include <cstdint>
19
20 #include "ani_common.h"
21 #include "ani_font_collection.h"
22 #include "ani_paragraph.h"
23 #include "ani_paragraph_builder.h"
24 #include "ani_paragraph_style_converter.h"
25 #include "ani_text_style_converter.h"
26 #include "ani_text_utils.h"
27 #include "font_collection.h"
28 #include "text_style.h"
29 #include "utils/text_log.h"
30
31 namespace OHOS::Text::ANI {
32 using namespace OHOS::Rosen;
Constructor(ani_env * env,ani_object object,ani_object paragraphStyle,ani_object fontCollection)33 void AniParagraphBuilder::Constructor(
34 ani_env* env, ani_object object, ani_object paragraphStyle, ani_object fontCollection)
35 {
36 std::unique_ptr<TypographyStyle> typographyStyleNative =
37 AniParagraphStyleConverter::ParseParagraphStyleToNative(env, paragraphStyle);
38 if (typographyStyleNative == nullptr) {
39 TEXT_LOGE("Failed to parse typographyStyle");
40 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
41 return;
42 }
43
44 AniFontCollection* aniFontCollection = AniTextUtils::GetNativeFromObj<AniFontCollection>(env, fontCollection);
45 if (aniFontCollection == nullptr) {
46 TEXT_LOGE("FontCollection is null");
47 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
48 return;
49 }
50 std::shared_ptr<FontCollection> fontCollectionNative = aniFontCollection->GetFontCollection();
51 if (fontCollectionNative == nullptr) {
52 TEXT_LOGE("Failed to get font collection");
53 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
54 return;
55 }
56
57 std::unique_ptr<TypographyCreate> typographyCreateNative =
58 TypographyCreate::Create(*typographyStyleNative, fontCollectionNative);
59 if (typographyCreateNative == nullptr) {
60 TEXT_LOGE("Failed to create typography creator");
61 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "TypographyCreate create error.");
62 return;
63 }
64
65 TypographyCreate* typographyCreate = typographyCreateNative.release();
66 ani_status ret = env->Object_SetFieldByName_Long(object, NATIVE_OBJ, reinterpret_cast<ani_long>(typographyCreate));
67 if (ret != ANI_OK) {
68 TEXT_LOGE("Failed to create ani ParagraphBuilder obj");
69 delete typographyCreate;
70 typographyCreate = nullptr;
71 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "AniParagraphBuilder create error.");
72 return;
73 }
74 }
75
AniInit(ani_vm * vm,uint32_t * result)76 ani_status AniParagraphBuilder::AniInit(ani_vm* vm, uint32_t* result)
77 {
78 ani_env* env;
79 ani_status ret = vm->GetEnv(ANI_VERSION_1, &env);
80 if (ret != ANI_OK) {
81 TEXT_LOGE("null env, ret %{public}d", ret);
82 return ANI_NOT_FOUND;
83 }
84
85 ani_class cls = nullptr;
86 ret = env->FindClass(ANI_CLASS_PARAGRAPH_BUILDER, &cls);
87 if (ret != ANI_OK) {
88 TEXT_LOGE("Failed to find class, ret %{public}d", ret);
89 return ANI_NOT_FOUND;
90 }
91
92 std::string ctorSignature =
93 std::string(ANI_INTERFACE_PARAGRAPH_STYLE) + std::string(ANI_CLASS_FONT_COLLECTION) + ":V";
94 std::string pushStyleSignature = std::string(ANI_INTERFACE_TEXT_STYLE) + ":V";
95 std::string buildStyleSignature = ":" + std::string(ANI_CLASS_PARAGRAPH);
96 std::array methods = {
97 ani_native_function{"constructorNative", ctorSignature.c_str(), reinterpret_cast<void*>(Constructor)},
98 ani_native_function{"pushStyle", pushStyleSignature.c_str(), reinterpret_cast<void*>(PushStyle)},
99 ani_native_function{"popStyle", ":V", reinterpret_cast<void*>(PopStyle)},
100 ani_native_function{"addText", "Lstd/core/String;:V", reinterpret_cast<void*>(AddText)},
101 ani_native_function{"build", buildStyleSignature.c_str(), reinterpret_cast<void*>(Build)},
102 };
103
104 ret = env->Class_BindNativeMethods(cls, methods.data(), methods.size());
105 if (ret != ANI_OK) {
106 TEXT_LOGE("Failed to bind methods, ret %{public}d", ret);
107 return ANI_NOT_FOUND;
108 }
109 return ANI_OK;
110 }
111
PushStyle(ani_env * env,ani_object object,ani_object textStyle)112 void AniParagraphBuilder::PushStyle(ani_env* env, ani_object object, ani_object textStyle)
113 {
114 TypographyCreate* typographyCreate = AniTextUtils::GetNativeFromObj<TypographyCreate>(env, object);
115 if (typographyCreate == nullptr) {
116 TEXT_LOGE("ParagraphBuilder is null");
117 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
118 return;
119 }
120 TextStyle textStyleNative;
121 ani_status status = AniTextStyleConverter::ParseTextStyleToNative(env, textStyle, textStyleNative);
122 if (status == ANI_OK) {
123 typographyCreate->PushStyle(textStyleNative);
124 }
125 }
126
PopStyle(ani_env * env,ani_object object)127 void AniParagraphBuilder::PopStyle(ani_env* env, ani_object object)
128 {
129 TypographyCreate* typographyCreate = AniTextUtils::GetNativeFromObj<TypographyCreate>(env, object);
130 if (typographyCreate == nullptr) {
131 TEXT_LOGE("ParagraphBuilder is null");
132 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
133 return;
134 }
135
136 typographyCreate->PopStyle();
137 }
138
AddText(ani_env * env,ani_object object,ani_string text)139 void AniParagraphBuilder::AddText(ani_env* env, ani_object object, ani_string text)
140 {
141 std::u16string textStr;
142 ani_status status = AniTextUtils::AniToStdStringUtf16(env, text, textStr);
143 if (status != ANI_OK) {
144 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Fail get utf16.");
145 return;
146 }
147 TypographyCreate* typographyCreate = AniTextUtils::GetNativeFromObj<TypographyCreate>(env, object);
148 if (typographyCreate == nullptr) {
149 TEXT_LOGE("ParagraphBuilder is null");
150 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
151 return;
152 }
153 typographyCreate->AppendText(textStr);
154 }
155
Build(ani_env * env,ani_object object)156 ani_object AniParagraphBuilder::Build(ani_env* env, ani_object object)
157 {
158 TypographyCreate* typographyCreate = AniTextUtils::GetNativeFromObj<TypographyCreate>(env, object);
159 if (typographyCreate == nullptr) {
160 TEXT_LOGE("ParagraphBuilder is null");
161 AniTextUtils::ThrowBusinessError(env, TextErrorCode::ERROR_INVALID_PARAM, "Invalid params.");
162 return AniTextUtils::CreateAniUndefined(env);
163 }
164 std::unique_ptr<OHOS::Rosen::Typography> typography = typographyCreate->CreateTypography();
165 return AniParagraph::SetTypography(env, typography);
166 }
167 } // namespace OHOS::Text::ANI