• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 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 #include <cmath>
16 #include <string>
17 #include "napi/native_api.h"
18 #include <bits/alltypes.h>
19 #include <multimedia/image_framework/image_mdk_common.h>
20 #include <multimedia/image_framework/image_pixel_map_mdk.h>
21 #include <native_window/external_window.h>
22 #include <native_drawing/drawing_bitmap.h>
23 #include <native_drawing/drawing_color.h>
24 #include <native_drawing/drawing_color_filter.h>
25 #include <native_drawing/drawing_canvas.h>
26 #include <native_drawing/drawing_pen.h>
27 #include <native_drawing/drawing_pixel_map.h>
28 #include <native_drawing/drawing_brush.h>
29 #include <native_drawing/drawing_path.h>
30 #include <native_drawing/drawing_rect.h>
31 #include <native_drawing/drawing_register_font.h>
32 #include <native_drawing/drawing_filter.h>
33 #include <native_drawing/drawing_font.h>
34 #include <native_drawing/drawing_font_collection.h>
35 #include <native_drawing/drawing_sampling_options.h>
36 #include <native_drawing/drawing_text_blob.h>
37 #include <native_drawing/drawing_text_declaration.h>
38 #include <native_drawing/drawing_text_typography.h>
39 #include <native_drawing/drawing_types.h>
40 #include <native_drawing/drawing_typeface.h>
41 #include "common/log_common.h"
42 
43 enum DrawType {
44     NONE,
45     PATH,
46     TEXT,
47     IMAGE
48 };
49 
50 const int FONT_COUNT = 2;
51 const char *TEXT_DEMO = "Hello, OpenHarmony! 你好,鸿蒙!";
52 const char *g_paths[FONT_COUNT] = {"system/fonts/NotoSansBengaliUI-Bold.ttf",
53     "system/fonts/NotoSansDevanagariUI-Regular.ttf"};
54 
NativeOnDrawPath(OH_Drawing_Canvas * canvas,int32_t width,int32_t height)55 static void NativeOnDrawPath(OH_Drawing_Canvas *canvas, int32_t width, int32_t height)
56 {
57     // native node draw function
58     int len = height / 4;
59     float aX = width / 2;
60     float aY = height / 6;
61     float dX = aX - len * std::sin(18.0f);
62     float dY = aY + len * std::cos(18.0f);
63     float cX = aX + len * std::sin(18.0f);
64     float cY = dY;
65     float bX = aX + (len / 2.0);
66     float bY = aY + std::sqrt((cX - dX) * (cX - dX) + (len / 2.0) * (len / 2.0));
67     float eX = aX - (len / 2.0);
68     float eY = bY;
69     // 创建一个path对象,然后使用接口连接成一个五角星形状
70     OH_Drawing_Path *cPath = OH_Drawing_PathCreate();
71     // 指定path的起始位置
72     OH_Drawing_PathMoveTo(cPath, aX, aY);
73     // 用直线连接到目标点
74     OH_Drawing_PathLineTo(cPath, bX, bY);
75     OH_Drawing_PathLineTo(cPath, cX, cY);
76     OH_Drawing_PathLineTo(cPath, dX, dY);
77     OH_Drawing_PathLineTo(cPath, eX, eY);
78     // 闭合形状,path绘制完毕
79     OH_Drawing_PathClose(cPath);
80 
81     constexpr float penWidth = 10.0f; // pen width 10
82     // 创建一个画笔Pen对象,Pen对象用于形状的边框线绘制
83     OH_Drawing_Pen *cPen = OH_Drawing_PenCreate();
84     OH_Drawing_PenSetAntiAlias(cPen, true);
85     OH_Drawing_PenSetColor(cPen, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0x00, 0x00));
86     OH_Drawing_PenSetWidth(cPen, penWidth);
87     OH_Drawing_PenSetJoin(cPen, LINE_ROUND_JOIN);
88     // 将Pen画笔设置到canvas中
89     OH_Drawing_CanvasAttachPen(canvas, cPen);
90 
91     // 创建一个画刷Brush对象,Brush对象用于形状的填充
92     OH_Drawing_Brush *cBrush = OH_Drawing_BrushCreate();
93     OH_Drawing_BrushSetColor(cBrush, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0xFF, 0x00));
94 
95     // 将Brush画刷设置到canvas中
96     OH_Drawing_CanvasAttachBrush(canvas, cBrush);
97 
98     // 在画布上画path的形状,五角星的边框样式为pen设置,颜色填充为Brush设置
99     OH_Drawing_CanvasDrawPath(canvas, cPath);
100 
101     // 绘制完成后将画笔和画刷从画布上清空并销毁
102     OH_Drawing_CanvasDetachPen(canvas);
103     OH_Drawing_CanvasDetachBrush(canvas);
104     OH_Drawing_PenDestroy(cPen);
105     OH_Drawing_BrushDestroy(cBrush);
106     OH_Drawing_PathDestroy(cPath);
107 }
108 
109 // 字体引擎提供的文字绘制能力,可指定字体,自带排版,支持字体退化
NativeOnDrawText(OH_Drawing_Canvas * canvas,int32_t width,int32_t height)110 static void NativeOnDrawText(OH_Drawing_Canvas *canvas, int32_t width, int32_t height)
111 {
112     // 选择从左到右/左对齐等排版属性
113     OH_Drawing_TypographyStyle *typoStyle = OH_Drawing_CreateTypographyStyle();
114     OH_Drawing_SetTypographyTextDirection(typoStyle, TEXT_DIRECTION_LTR);
115     OH_Drawing_SetTypographyTextAlign(typoStyle, TEXT_ALIGN_JUSTIFY);
116 
117     // TEXT_ALIGN_JUSTIFY
118     // 设置文字颜色,例如黑色
119     OH_Drawing_TextStyle *txtStyle = OH_Drawing_CreateTextStyle();
120     OH_Drawing_SetTextStyleColor(txtStyle, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
121     // 设置文字大小、字重等属性
122     double fontSize = width / 16;
123     OH_Drawing_SetTextStyleFontSize(txtStyle, fontSize);
124     OH_Drawing_SetTextStyleFontWeight(txtStyle, FONT_WEIGHT_400);
125     OH_Drawing_SetTextStyleBaseLine(txtStyle, TEXT_BASELINE_ALPHABETIC);
126     OH_Drawing_SetTextStyleFontHeight(txtStyle, 1);
127     // 设置字体类型等
128     for (int i = 0; i < FONT_COUNT; ++i) {
129         OH_Drawing_FontCollection *fontCollection = OH_Drawing_CreateFontCollection();
130         const char *fontFamily = "myFamilyName";
131         const char *fontPath = g_paths[i];
132         OH_Drawing_RegisterFont(fontCollection, fontFamily, fontPath);
133         const char *myFontFamilies[] = {"myFamilyName"};
134         OH_Drawing_SetTextStyleFontFamilies(txtStyle, 1, myFontFamilies);
135         OH_Drawing_SetTextStyleFontStyle(txtStyle, FONT_STYLE_NORMAL);
136         OH_Drawing_SetTextStyleLocale(txtStyle, "en");
137         OH_Drawing_TypographyCreate *handler =
138             OH_Drawing_CreateTypographyHandler(typoStyle, fontCollection);
139         OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyle);
140         // 设置文字内容
141         OH_Drawing_TypographyHandlerAddText(handler, TEXT_DEMO);
142         OH_Drawing_TypographyHandlerPopTextStyle(handler);
143         OH_Drawing_Typography *typography = OH_Drawing_CreateTypography(handler);
144         // 设置页面最大宽度
145         double maxWidth = width - 100;
146         OH_Drawing_TypographyLayout(typography, maxWidth);
147         // 设置文本在画布上绘制的起始位置
148         double position[2] = {width / 10.0, height / 5.0 + fontSize * i * 2};
149         // 将文本绘制到画布上
150         OH_Drawing_TypographyPaint(typography, canvas, position[0], position[1]);
151         // 销毁创建的资源
152         OH_Drawing_DestroyTypography(typography);
153         OH_Drawing_DestroyTypographyHandler(handler);
154         OH_Drawing_DestroyFontCollection(fontCollection);
155     }
156     OH_Drawing_DestroyTypographyStyle(typoStyle);
157     OH_Drawing_DestroyTextStyle(txtStyle);
158 }
159 
NativeOnDrawTextBlob(OH_Drawing_Canvas * canvas,int32_t width,int32_t height)160 static void NativeOnDrawTextBlob(OH_Drawing_Canvas *canvas, int32_t width, int32_t height)
161 {
162     OH_Drawing_Brush *brush = OH_Drawing_BrushCreate();
163     OH_Drawing_BrushSetColor(brush, OH_Drawing_ColorSetArgb(0xff, 0xff, 0x00, 0x00));
164     OH_Drawing_CanvasAttachBrush(canvas, brush);
165     float textSize = width / 16;
166     for (int i = 0; i < FONT_COUNT; ++i) {
167         OH_Drawing_TextBlobBuilder *builder = OH_Drawing_TextBlobBuilderCreate();
168         OH_Drawing_Font *font = OH_Drawing_FontCreate();
169         OH_Drawing_Typeface *typeface = OH_Drawing_TypefaceCreateFromFile(g_paths[i], 0);
170         OH_Drawing_FontSetTypeface(font, typeface);
171         OH_Drawing_FontSetTextSize(font, textSize);
172         int textCount = OH_Drawing_FontCountText(font, TEXT_DEMO, strlen(TEXT_DEMO), TEXT_ENCODING_UTF8);
173         uint16_t glyphs[textCount];
174         // 获取文本对应的glyphsID
175         uint32_t glyphsCount =
176             OH_Drawing_FontTextToGlyphs(font, TEXT_DEMO, strlen(TEXT_DEMO), TEXT_ENCODING_UTF8, glyphs, textCount);
177         float textWidth[glyphsCount];
178         // 获取文本中每个字符的宽度,以此来确定排版横坐标
179         OH_Drawing_FontGetWidths(font, glyphs, glyphsCount, textWidth);
180         OH_Drawing_Font_Metrics metrics;
181         OH_Drawing_FontGetMetrics(font, &metrics);
182         // 计算字体高度用于换行
183         const float textHeight = metrics.descent - metrics.ascent;
184         const OH_Drawing_RunBuffer *runBuffer =
185             OH_Drawing_TextBlobBuilderAllocRunPos(builder, font, glyphsCount, nullptr);
186         // 以下为计算每个字的坐标设置的数据,无具体含义
187         const float posX = width / 10.0;
188         const float posY = height / 2.0;
189         const float enlargeY = 1.2;
190         const int numberTwo = 2;
191         float bufferPosX = posX;
192         float bufferPosY = posY + enlargeY * textSize * i * numberTwo;
193         for (int j = 0; j < glyphsCount; ++j) {
194             runBuffer->glyphs[j] = glyphs[j];
195             // 自定义字体排版中的横坐标
196             runBuffer->pos[j * numberTwo] = bufferPosX;
197             // 自定义字体排版中的纵坐标
198             runBuffer->pos[j * numberTwo + 1] = bufferPosY;
199             bufferPosX += textWidth[j];
200             if (bufferPosX >= width) {
201                 bufferPosX = posX;
202                 bufferPosY += textHeight;
203             }
204         }
205         OH_Drawing_TextBlob *textBlob = OH_Drawing_TextBlobBuilderMake(builder);
206         OH_Drawing_CanvasDrawTextBlob(canvas, textBlob, 0, 0);
207 
208         // 第二种textBlob创建方式,通过字符串创建,带有基础的排版,且不支持字体退化
209         const float tempY = 1.3;
210         OH_Drawing_TextBlob *stringTextBlob =
211             OH_Drawing_TextBlobCreateFromString(TEXT_DEMO, font, TEXT_ENCODING_UTF8);
212         OH_Drawing_CanvasDrawTextBlob(canvas, stringTextBlob, posX, height / tempY + textSize * i);
213 
214         OH_Drawing_TextBlobDestroy(textBlob);
215         OH_Drawing_TextBlobBuilderDestroy(builder);
216         OH_Drawing_TextBlobDestroy(stringTextBlob);
217         OH_Drawing_TypefaceDestroy(typeface);
218         OH_Drawing_FontDestroy(font);
219     }
220     OH_Drawing_CanvasDetachBrush(canvas);
221     OH_Drawing_BrushDestroy(brush);
222 }
223 
NativeOnDrawPixelMap(OH_Drawing_Canvas * canvas,NativePixelMap * native)224 static void NativeOnDrawPixelMap(OH_Drawing_Canvas *canvas, NativePixelMap *native)
225 {
226     OH_Drawing_CanvasSave(canvas);
227     OH_Drawing_PixelMap *pixelMap = OH_Drawing_PixelMapGetFromNativePixelMap(native);
228     OH_Drawing_SamplingOptions *sampling = OH_Drawing_SamplingOptionsCreate(FILTER_MODE_NEAREST, MIPMAP_MODE_NONE);
229     OH_Drawing_Rect *src = OH_Drawing_RectCreate(0, 0, 550, 564);
230     OH_Drawing_Rect *dst = OH_Drawing_RectCreate(25, 300, 300, 582);
231     OH_Drawing_Brush *brush = OH_Drawing_BrushCreate();
232     OH_Drawing_CanvasAttachBrush(canvas, brush);
233     OH_Drawing_CanvasDrawPixelMapRect(canvas, pixelMap, src, dst, sampling);
234     OH_Drawing_CanvasDetachBrush(canvas);
235 
236     // 设置样式,绘制时生效
237     const float array[] = {
238         1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, -1, 0, 0, 1, 0,
239     };
240     OH_Drawing_ColorFilter *colorFilter = OH_Drawing_ColorFilterCreateMatrix(array);
241     OH_Drawing_Filter *filter = OH_Drawing_FilterCreate();
242     OH_Drawing_FilterSetColorFilter(filter, colorFilter);
243     OH_Drawing_BrushSetFilter(brush, filter);
244     OH_Drawing_CanvasAttachBrush(canvas, brush);
245     OH_Drawing_CanvasTranslate(canvas, 300.f, 0.f);
246     OH_Drawing_CanvasDrawPixelMapRect(canvas, pixelMap, src, dst, sampling);
247     OH_Drawing_CanvasDetachBrush(canvas);
248 
249     OH_Drawing_PixelMapDissolve(pixelMap);
250     OH_Drawing_BrushDestroy(brush);
251     OH_Drawing_CanvasRestore(canvas);
252     OH_Drawing_FilterDestroy(filter);
253     OH_Drawing_ColorFilterDestroy(colorFilter);
254     OH_Drawing_SamplingOptionsDestroy(sampling);
255     OH_Drawing_RectDestroy(src);
256     OH_Drawing_RectDestroy(dst);
257 }
258 
259 // 开发者提供的native方法,入参有且仅有如下两个,开发者不需进行变更。
260 // napi_env 为当前运行的上下文
261 // napi_callback_info 记录了一些信息,包括从ArkTS侧传递过来参数等。
OnDraw(napi_env env,napi_callback_info info)262 static napi_value OnDraw(napi_env env, napi_callback_info info)
263 {
264     size_t argc = 6;
265     napi_value args[6] = {nullptr};
266     napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
267 
268     int32_t id;
269     napi_get_value_int32(env, args[0], &id);
270     void *temp = nullptr;
271     napi_unwrap(env, args[1], &temp);
272 
273     OH_Drawing_Canvas *canvas = reinterpret_cast<OH_Drawing_Canvas *>(temp);
274     int32_t width;
275     napi_get_value_int32(env, args[2], &width); // 2 means the second argument
276     int32_t height;
277     napi_get_value_int32(env, args[3], &height); // 3 means the third argument
278     int32_t drawOption;
279     napi_get_value_int32(env, args[4], &drawOption); // 4 means the forth argument
280     NativePixelMap *nativePixelMap = OH_PixelMap_InitNativePixelMap(env, args[5]); // 5 means the forth argument
281 
282     if (drawOption == PATH) {
283         NativeOnDrawPath(canvas, width, height);
284     } else if (drawOption == TEXT) {
285         NativeOnDrawText(canvas, width, height);
286         NativeOnDrawTextBlob(canvas, width, height);
287     } else if (drawOption == IMAGE) {
288         NativeOnDrawPixelMap(canvas, nativePixelMap);
289     }
290     return nullptr;
291 }
292 
GetNodeDescriptors(napi_env env,napi_callback_info info)293 static napi_value GetNodeDescriptors(napi_env env, napi_callback_info info) { return nullptr; }
294 
295 EXTERN_C_START
296 // Init将在exports上挂上Add/NativeCallArkTS这些native方法,此处的exports就是开发者import之后获取到的ArkTS对象。
Init(napi_env env,napi_value exports)297 static napi_value Init(napi_env env, napi_value exports)
298 {
299     napi_property_descriptor desc[] = {
300         {"nativeGetNodeDescriptors", nullptr, GetNodeDescriptors, nullptr, nullptr, nullptr, napi_default, nullptr},
301         {"nativeOnDraw", nullptr, OnDraw, nullptr, nullptr, nullptr, napi_default, nullptr},
302     };
303     // 在exports这个ArkTs对象上,挂载native方法
304     napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
305     return exports;
306 }
307 EXTERN_C_END
308 
309 static napi_module demoModule = {
310     .nm_version = 1,
311     .nm_flags = 0,
312     .nm_filename = nullptr,
313     .nm_register_func = Init,
314     .nm_modname = "entry",
315     .nm_priv = ((void *)0),
316     .reserved = {0},
317 };
318 
RegisterEntryModule(void)319 extern "C" __attribute__((constructor)) void RegisterEntryModule(void) { napi_module_register(&demoModule); }
320