diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/app.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..6254db89feb0cfd1b1bbd585e9bbb51f65f6ed1a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.samples.drawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/README.md b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..981344b62f74e664ecc1b6a240538e11708b8c4c
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/README.md
@@ -0,0 +1,131 @@
+# ArkGraphics 3D
+
+## 介绍
+
+本示例通过 ArkGraphics 3D 的接口,利用轻量级的 3D 引擎和渲染管线,实现了 3D 场景创建、3D 场景资源创建和 3D 动画创建。
+
+本示例主要展现了如何利用 ArkGraphics 3D 来实现 3D 图像的渲染,其中利用 Scene、Camera 和 Light 来创建基础的场景,使用 Material、Shader、Image 和Environment 来实现场景资源,采用 Animation 的各种方法来播放 3D 动画。
+
+## 效果预览
+
+| Index | Scene | Resource | Animation |
+| :-----------------------------------------------: | :-----------------------------------------------: | :--------------------------------------------------: | :---------------------------------------------------: |
+|
|
|
|
|
+
+**使用方法:**
+
+1. 在 Index 页面点击 ` BUilding and Managing ArkGraphics 3D Scenes` 按钮,跳转至 Scene 页面;
+ - 在 Scene 页面点击 `Model Loading and Display` 按钮,页面跳转至 Model 页面,显现 3D 头盔图像。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing a Camera` 按钮,页面跳转至 Camera 页面,显现几何体图像。通过调节 `X-axis`、`Y-axis` 和 `Z-axis` 滑动条,即可分别修改相机的 X 轴,Y 轴和 Z 轴。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing Light` 按钮,页面跳转至 Light 页面,显现几何体图像。通过调节 `Red`、`Green` 和 `Blue` 滑动条,即可分别调节光线的红、绿和蓝的颜色通道。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Back` 按钮,返回至 `Index` 页面;
+2. 在 Index 页面点击 `Creating and using ArkGraphics 3D Resources` 按钮,跳转至 Resource 页面。点击 `Replace with a blank material` 按钮,几何体图像的材质被空白材质替换。点击 `Replace with a Shader material` 按钮,几何体图像的材质被着色器材质替换。点击 `Replace with a Image material`,几何体材质被图像材质替换。点击 `Add to Environment` 按钮,给几何体图像添加背景。点击 `Back` 按钮,返回至 Index 页面;
+3. 在 Index 页面点击 `Controlling and Managing ArkGraphics 3D Scene Animations` 按钮,跳转至 Animation 页面。点击 `start` 按钮,播放动画。点击 `pause` 按钮,中止动画。点击 `stop` 按钮,暂停动画。点击 `finish` 按钮,结束动画。点击 `restart` 按钮,重新播放动画。点击 `seek to 30% progress` 按钮,动画从 30% 进度开始播放。点击 `Back` 按钮,返回至 Index 页面;
+
+## 工程目录
+
+```
+|--entry/src/main
+│ |--ets // ets代码区
+│ │ |--entryability
+│ │ │ |--EntryAbility.ts // 程序入口类
+| | | |--EntryAbility.ets
+| | |--arkGraphic
+│ │ │ |--animation.ets // 动画
+| | | |--resource.ets // 场景资源
+| | | |--scene.ets // 场景搭建
+| | |--scene
+| | | |--camera.ets // 相机
+| | | |--init.ets // 模型加载
+| | | |--light.ets // 光线
+│ │ |--pages // 页面文件
+│ │ | |--Index.ets // 初始页面
+│ │ |--utils // 工具类
+| |--resources // 资源文件目录
+```
+
+## 具体实现
+
+1. 创建场景:一个 3D 场景通常由模型、相机和光源三个关键部分组成。其中先加载模型,再生成相机和光源。等 3D 图像加载完毕,可以使 Component3D 组件将渲染好的图像传递给用户。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------ | -------- |
+ | `Scene.load(): Promise` | 加载模型 |
+ | `SceneResourceFactory.createCamera(): Promise` | 创建相机 |
+ | `SceneResourceFactory.createLight(): Promise` | 创建光源 |
+
+ - | SceneOption 参数 | 描述 |
+ | -------------------- | ------------------------------------------------------------ |
+ | scene: Scene | 3D模型资源文件或场景对象,默认值为undefined。
**说明:目前仅支持GLTF格式资源。** |
+ | modelType: ModelType | 3D场景显示合成方式。
**说明:**
一般开发者可以使用默认值而无需关心此项设置。 |
+
+2. 创建场景资源:3D 场景中主要有以下常见资源:
+
+ - 材质(Material):材质是对场景中物体的光学物理性质的数学建模。在渲染计算的过程中,利用这些物理性质计算与光的相互作用,得到渲染的颜色。ArkGraphics 3D 提供的材质类型基于 PBR 渲染,支持用户参照 PBR 渲染材质类型创建材质资源,得到预期的渲染结果。
+
+ - 图片(Image): 图片本质上是上一个储存信息的二维内存块(buffer),用于储存 3D 渲染计算过程需要的相关信息,比如基础色、法线等等。ArkGraphics 3D 提供基于 PNG、JPG、KTX格式创建 Image 资源的能力,支持用户自定义需要的 Image 资源。
+
+ - 着色器(Shader): 着色器是 GPU 上可以执行的一段程序,可以控制 GPU 执行哪些并行计算操作。AGP 引擎提供的默认着色器实现了 PBR 渲染,开发者只需要指定对应的参数就可以完成不同的 PBR 渲染。ArkGraphics 3D 支持开发者创建自定义的着色器,开发者可以通过自定义着色器自定义渲染计算过程,完全控制渲染计算流程,比如控制某物体不受某光源的影响等。
+
+ - 环境(Environment): 环境是 3D 场景背景的一种描述,可以基于图片进行创建。通过将一张图片进行正方体或者球体的映射处理,将图片贴在正方体或者球体上,在 3D 场景中模拟真实的环境。ArkGraphics 3D 支持用户创建环境资源,定义 3D 场景的背景。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------------ | ---------- |
+ | `SceneResourceFactory.createMaterial(): Promise` | 创建材质 |
+ | `SceneResourceFactory.createImage(): Promise` | 创建图片 |
+ | `SceneResourceFactory.createShader(): Promise` | 创建着色器 |
+ | `SceneResourceFactory.createEnvironment(): Promise` | 创建环境 |
+
+ - 尤其需要注意:在 ArkGraphics 3D 中需要将材质(Material)给与子网格(SubMesh)才能成功替换材质。
+
+ - | SubMesh 属性 | 说明 |
+ | ---------------------- | ------------------------ |
+ | name: string | 名称,没有特殊格式要求。 |
+ | **material: Material** | 材质。 |
+ | aabb: Aabb | 轴对齐边界盒。 |
+
+3. 创建动画:动画是3D场景中重要的资源类型,用于控制场景中各种元素的运动。
+
+ - 调用 `start` 方法控制动画开启;
+
+ - 调用 `pause` 方法控制动画暂停;
+
+ - 调用 `stop` 方法控制动画停止,并将动画状态设置为开头;
+
+ - 调用`finish` 方法控制动画结束,并将动画状态设置为结尾;
+
+ - 调用 `restart` 方法控制动画从头开始;
+
+ - 调用 `seek` 方法控制动画设置到指定状态;
+
+ - `onStarted` 方法在动画开始时执行传入的回调;
+
+ - `onFinished` 方法在动画结束时执行传入的回调。
+
+## 相关权限
+
+不涉及。
+
+## 依赖
+
+不涉及。
+
+## 约束与限制
+
+1.本示例仅支持在标准系统上运行;
+
+2.本示例为 Stage 模型,已适配 API version 14 版本 SDK,SDK 版本号(API Version 14 5.0.2.57);
+
+3.本示例需要使用 DevEco Studio 版本号(5.0.5.306)及以上版本才可编译运行。
+
+## 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/graphic/Arkgraphics3D/ > .git/info/sparse-checkout
+git remote add origin https://gitee.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..a02339aff59ee239682304883818f4b74b77666a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/build-profile.json5
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ "compatibleSdkVersion": 14,
+ "runtimeOS": "OpenHarmony"
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ],
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/code-linter.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/code-linter.json5
@@ -0,0 +1,32 @@
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/build-profile.json5
@@ -0,0 +1,28 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/obfuscation-rules.txt b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..97d03750b9972469c2c2deaad3140543658a2203
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,25 @@
+import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ preFontId = "";
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(DOMAIN, 'testTag', 'onCreate');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ hilog.info(DOMAIN, 'testTag', 'onWindowStageCreate');
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load content: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Content loaded successfully.');
+ });
+ }
+
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,16 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/pages/Index.ets b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..a2b0ca3222db81e122e5739cf06ee7086565266f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,168 @@
+import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
+import { UIContext } from '@kit.ArkUI'
+import { drawing } from '@kit.ArkGraphics2D'
+import { text } from '@kit.ArkGraphics2D'
+import { common2D } from '@kit.ArkGraphics2D'
+
+// 创建一个MyRenderNode类,并绘制文本。
+class MyRenderNode extends RenderNode {
+ async draw(context: DrawContext) {
+ // 绘制代码逻辑写在这里
+ let canvas = context.canvas;
+
+ // 初始化装饰线对象
+ let decorations: text.Decoration =
+ {
+ // 装饰线类型,支持上划线、下划线、删除线
+ textDecoration: text.TextDecorationType.UNDERLINE,
+ // 装饰线颜色
+ color: {
+ alpha: 255,
+ red: 255,
+ green: 0,
+ blue: 0
+ },
+ // 装饰线样式,支持波浪,虚线,直线等
+ decorationStyle:text.TextDecorationStyle.SOLID,
+ // 装饰线的高度
+ decorationThicknessScale: 1
+ };
+
+ let myTextStyle: text.TextStyle = {
+ color: {
+ alpha: 255,
+ red: 255,
+ green: 0,
+ blue: 0
+ },
+ fontSize: 150,
+ // 设置装饰线
+ decoration: decorations,
+ // 可变字体
+ fontVariations: [{axis: 'wght', value: 555}],
+ // 文本阴影
+ textShadows: [{color: { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 }, point: {x:10,y:10}, blurRadius: 10}],
+ // 开启字体特征
+ fontFeatures: [{name: 'frac', value: 1}]
+ };
+
+ let myParagraphStyle: text.ParagraphStyle = {
+ textStyle: myTextStyle
+ };
+
+ let fontCollection = text.FontCollection.getGlobalInstance();
+ let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
+
+ // 初始化占位符对象
+ let myPlaceholderSpan: text.PlaceholderSpan = {
+ width: 150,//宽度
+ height: 150,//高度
+ align: text.PlaceholderAlignment.BOTTOM_OF_ROW_BOX, //基线对齐策略
+ baseline: text.TextBaseline.ALPHABETIC,//使用的文本基线类型
+ baselineOffset: 100//相比基线的偏移量。只有对齐策略是OFFSET_AT_BASELINE时生效
+ };
+ // 添加占位符
+ ParagraphGraphBuilder.addPlaceholder(myPlaceholderSpan)
+
+ // 更新文本样式
+ ParagraphGraphBuilder.pushStyle(myTextStyle);
+ // 添加文本
+ ParagraphGraphBuilder.addText("1/2 1/3 1/4 ");
+
+ // 生成段落
+ let paragraph = ParagraphGraphBuilder.build();
+ // 布局
+ paragraph.layoutSync(600);
+ // 绘制文本
+ paragraph.paint(canvas, 0, 0);
+
+ let placeholderRects = paragraph.getRectsForPlaceholders();//获取全部占位符的数组
+ let left = placeholderRects[0].rect.left// 获取第一个占位符的左边界
+ let top = placeholderRects[0].rect.top// 获取第一个占位符的上边界
+ let right = placeholderRects[0].rect.right// 获取第一个占位符的有边界
+ let bottom = placeholderRects[0].rect.bottom// 获取第一个占位符的下边界
+ let pen: drawing.Pen = new drawing.Pen()
+ let pen_color : common2D.Color = { alpha: 0xFF, red: 0xFF, green: 0x00, blue: 0x00 }
+ pen.setColor(pen_color)
+ canvas.attachPen(pen)
+ canvas.drawRect(left,top,right,bottom)// 使用draw方法绘制占位符矩形框
+ }
+}
+
+class MyNodeController extends NodeController {
+ private rootNode: FrameNode | null = null;
+
+ makeNode(uiContext: UIContext): FrameNode {
+ this.rootNode = new FrameNode(uiContext)
+ if (this.rootNode == null) {
+ return this.rootNode
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.frame = {
+ x: 0,
+ y: 0,
+ width: 10,
+ height: 500
+ }
+ renderNode.pivot = { x: 50, y: 50 }
+ }
+ return this.rootNode
+ }
+
+ addNode(node: RenderNode): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.appendChild(node)
+ }
+ }
+
+ clearNodes(): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.clearChildren()
+ }
+ }
+}
+
+// 创建一个MyRenderNode对象
+const textNode = new MyRenderNode();
+// 定义newNode的大小和位置
+textNode.frame = { x: 0, y: 0, width: 400, height: 600 };
+
+@Entry
+@Component
+struct RenderTest {
+ private myNodeController: MyNodeController = new MyNodeController()
+ build() {
+ Column() {
+ Row(){
+ NodeContainer(this.myNodeController)
+ .height('100%')
+ .position({x : 50, y: 25})
+ Button("Draw complex text")
+ .fontSize('16fp')
+ .fontWeight(500)
+ .margin({ bottom: 24, right: 12 })
+ .onClick(() => {
+ this.myNodeController.clearNodes()
+ this.myNodeController.addNode(textNode)
+ })
+ .width('50%')
+ .height(40)
+ .shadow(ShadowStyle.OUTER_DEFAULT_LG)
+ }
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .shadow(ShadowStyle.OUTER_DEFAULT_SM)
+ .alignItems(VerticalAlign.Bottom)
+ .layoutWeight(1)
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2cd3a6c601073f86f4789ab9db7529f84f705f3f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/module.json5
@@ -0,0 +1,51 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/float.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/dark/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d0087c39a514078f76e581229130621aa87792a9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import { describe, it, expect } from '@ohos/hypium';
+import { Driver, ON } from '@ohos.UiTest';
+
+const TAG = '[Sample_DrawingAPI]';
+
+export default function abilityTest() {
+
+ describe('ActsAbilityTest', () => {
+ /**
+ * 打开应用
+ */
+ it('StartAbility_001', 0, async (done: Function) => {
+ console.info(TAG, 'StartAbility_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw complex text'));
+ done();
+ console.info(TAG, 'StartAbility_001 end');
+ })
+
+ /**
+ * 点击按钮,绘制简单排版文本
+ */
+ it('DrawSimpleTextTEST_001', 2, async () => {
+ console.info(TAG, 'DrawSimpleTextTEST_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `DrawSimpleTextTEST_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw complex text'));
+ let drawTextBtn = await driver.findComponent(ON.text('Draw complex text'));
+ // 点击'Draw complex text'按钮
+ await drawTextBtn.click();
+ await driver.delayMs(1000);
+ console.info(TAG, 'DrawSimpleTextTEST_001 end');
+ })
+
+ })
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..794c7dc4ed66bd98fa3865e07922906e2fcef545
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..69026872775eebd0844900b225c411959ae5608b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/entry/src/ohosTest/module.json5
@@ -0,0 +1,12 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/hvigor/hvigor-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fe83c3e838abfb3629eed84f6c7092f306d818f9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/hvigor/hvigor-config.json5
@@ -0,0 +1,22 @@
+{
+ "modelVersion": "5.0.2",
+ "dependencies": {
+ },
+ "execution": {
+ // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+ // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+ },
+ "nodeOptions": {
+ // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+ // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/oh-package-lock.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf818273347b97063c0c0a151bb14770ca1c79
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/oh-package-lock.json5
@@ -0,0 +1,27 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+ "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
+ },
+ "packages": {
+ "@ohos/hamock@1.0.0": {
+ "name": "@ohos/hamock",
+ "version": "1.0.0",
+ "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+ "registryType": "ohpm"
+ },
+ "@ohos/hypium@1.0.21": {
+ "name": "@ohos/hypium",
+ "version": "1.0.21",
+ "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9c36c086ae807ea710acd9e480cb6cc1d18bd011
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "modelVersion": "5.0.2",
+ "description": "Please describe the basic information.",
+ "dependencies": {
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.21",
+ "@ohos/hamock": "1.0.0"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/ohosTest.md b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/ohosTest.md
new file mode 100644
index 0000000000000000000000000000000000000000..280dbe74c4e1e68fdc32d7d2aab71374a791f532
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/ohosTest.md
@@ -0,0 +1,26 @@
+| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
+|:-------:|:------------:|:--------------:|:---------------------:|:----:|:----:|
+| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
+| 主页展示 | 设备正常运行 | | 展示 Building and Managing ArkGraphics 3D Scenes、Creating and Using ArkGraphics 3D Resources 和 Controlling and Managing ArkGraphics 3D Scene Animations 三种按钮 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Building and Managing ArkGraphics 3D Scenes 按钮 | 跳转 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Model Loading and Display 按钮 | 跳转至 Model 页面,显现头盔 | 是 | Pass |
+| Model 页面按钮点击 | 位于 Model 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing a Camera 按钮 | 跳转至 Camera 页面,显现几何体 | 是 | Pass |
+| Camera 页面按钮点击 | 位于 Camera 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing Light 按钮 | 跳转至 Light 页面 | 是 | Pass |
+| Light 页面按钮点击 | 位于 Light 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Creating and Using ArkGraphics 3D Resources 按钮 | 跳转至 Resource 页面,显现几何体 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a blank material 按钮 | 用空白材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a image material 按钮 | 用图像材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a shader material 按钮 | 用着色器材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Add to Environment 按钮 | 添加场景 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Controlling and Managing ArkGraphics 3D Scene Animations按钮 | 跳转至 Animation 页面 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Start 按钮 | 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Pause 按钮 | 暂停播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Stop 按钮 | 停止播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Finish 按钮 | 结束播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Restart 按钮 | 重新播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 seek to 30% progress 按钮 | 从 30% 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/screenshots/ApplyPlaceholderAndSoON.jpg b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/screenshots/ApplyPlaceholderAndSoON.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..1506187d4758c45d4b912f0ac77a699777603c2a
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/screenshots/ApplyPlaceholderAndSoON.jpg differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/screenshots/NoPlaceholderDecorationAndSonON.jpg b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/screenshots/NoPlaceholderDecorationAndSonON.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..a252478e674ce7e1de00e4a7f025ca529e65a82c
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ComplexTextDrawing/screenshots/NoPlaceholderDecorationAndSonON.jpg differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/app.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..15d714197fdf5d91703199923cf6afbdf9434372
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.samples.arkdrawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/README.md b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..981344b62f74e664ecc1b6a240538e11708b8c4c
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/README.md
@@ -0,0 +1,131 @@
+# ArkGraphics 3D
+
+## 介绍
+
+本示例通过 ArkGraphics 3D 的接口,利用轻量级的 3D 引擎和渲染管线,实现了 3D 场景创建、3D 场景资源创建和 3D 动画创建。
+
+本示例主要展现了如何利用 ArkGraphics 3D 来实现 3D 图像的渲染,其中利用 Scene、Camera 和 Light 来创建基础的场景,使用 Material、Shader、Image 和Environment 来实现场景资源,采用 Animation 的各种方法来播放 3D 动画。
+
+## 效果预览
+
+| Index | Scene | Resource | Animation |
+| :-----------------------------------------------: | :-----------------------------------------------: | :--------------------------------------------------: | :---------------------------------------------------: |
+|
|
|
|
|
+
+**使用方法:**
+
+1. 在 Index 页面点击 ` BUilding and Managing ArkGraphics 3D Scenes` 按钮,跳转至 Scene 页面;
+ - 在 Scene 页面点击 `Model Loading and Display` 按钮,页面跳转至 Model 页面,显现 3D 头盔图像。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing a Camera` 按钮,页面跳转至 Camera 页面,显现几何体图像。通过调节 `X-axis`、`Y-axis` 和 `Z-axis` 滑动条,即可分别修改相机的 X 轴,Y 轴和 Z 轴。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing Light` 按钮,页面跳转至 Light 页面,显现几何体图像。通过调节 `Red`、`Green` 和 `Blue` 滑动条,即可分别调节光线的红、绿和蓝的颜色通道。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Back` 按钮,返回至 `Index` 页面;
+2. 在 Index 页面点击 `Creating and using ArkGraphics 3D Resources` 按钮,跳转至 Resource 页面。点击 `Replace with a blank material` 按钮,几何体图像的材质被空白材质替换。点击 `Replace with a Shader material` 按钮,几何体图像的材质被着色器材质替换。点击 `Replace with a Image material`,几何体材质被图像材质替换。点击 `Add to Environment` 按钮,给几何体图像添加背景。点击 `Back` 按钮,返回至 Index 页面;
+3. 在 Index 页面点击 `Controlling and Managing ArkGraphics 3D Scene Animations` 按钮,跳转至 Animation 页面。点击 `start` 按钮,播放动画。点击 `pause` 按钮,中止动画。点击 `stop` 按钮,暂停动画。点击 `finish` 按钮,结束动画。点击 `restart` 按钮,重新播放动画。点击 `seek to 30% progress` 按钮,动画从 30% 进度开始播放。点击 `Back` 按钮,返回至 Index 页面;
+
+## 工程目录
+
+```
+|--entry/src/main
+│ |--ets // ets代码区
+│ │ |--entryability
+│ │ │ |--EntryAbility.ts // 程序入口类
+| | | |--EntryAbility.ets
+| | |--arkGraphic
+│ │ │ |--animation.ets // 动画
+| | | |--resource.ets // 场景资源
+| | | |--scene.ets // 场景搭建
+| | |--scene
+| | | |--camera.ets // 相机
+| | | |--init.ets // 模型加载
+| | | |--light.ets // 光线
+│ │ |--pages // 页面文件
+│ │ | |--Index.ets // 初始页面
+│ │ |--utils // 工具类
+| |--resources // 资源文件目录
+```
+
+## 具体实现
+
+1. 创建场景:一个 3D 场景通常由模型、相机和光源三个关键部分组成。其中先加载模型,再生成相机和光源。等 3D 图像加载完毕,可以使 Component3D 组件将渲染好的图像传递给用户。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------ | -------- |
+ | `Scene.load(): Promise` | 加载模型 |
+ | `SceneResourceFactory.createCamera(): Promise` | 创建相机 |
+ | `SceneResourceFactory.createLight(): Promise` | 创建光源 |
+
+ - | SceneOption 参数 | 描述 |
+ | -------------------- | ------------------------------------------------------------ |
+ | scene: Scene | 3D模型资源文件或场景对象,默认值为undefined。
**说明:目前仅支持GLTF格式资源。** |
+ | modelType: ModelType | 3D场景显示合成方式。
**说明:**
一般开发者可以使用默认值而无需关心此项设置。 |
+
+2. 创建场景资源:3D 场景中主要有以下常见资源:
+
+ - 材质(Material):材质是对场景中物体的光学物理性质的数学建模。在渲染计算的过程中,利用这些物理性质计算与光的相互作用,得到渲染的颜色。ArkGraphics 3D 提供的材质类型基于 PBR 渲染,支持用户参照 PBR 渲染材质类型创建材质资源,得到预期的渲染结果。
+
+ - 图片(Image): 图片本质上是上一个储存信息的二维内存块(buffer),用于储存 3D 渲染计算过程需要的相关信息,比如基础色、法线等等。ArkGraphics 3D 提供基于 PNG、JPG、KTX格式创建 Image 资源的能力,支持用户自定义需要的 Image 资源。
+
+ - 着色器(Shader): 着色器是 GPU 上可以执行的一段程序,可以控制 GPU 执行哪些并行计算操作。AGP 引擎提供的默认着色器实现了 PBR 渲染,开发者只需要指定对应的参数就可以完成不同的 PBR 渲染。ArkGraphics 3D 支持开发者创建自定义的着色器,开发者可以通过自定义着色器自定义渲染计算过程,完全控制渲染计算流程,比如控制某物体不受某光源的影响等。
+
+ - 环境(Environment): 环境是 3D 场景背景的一种描述,可以基于图片进行创建。通过将一张图片进行正方体或者球体的映射处理,将图片贴在正方体或者球体上,在 3D 场景中模拟真实的环境。ArkGraphics 3D 支持用户创建环境资源,定义 3D 场景的背景。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------------ | ---------- |
+ | `SceneResourceFactory.createMaterial(): Promise` | 创建材质 |
+ | `SceneResourceFactory.createImage(): Promise` | 创建图片 |
+ | `SceneResourceFactory.createShader(): Promise` | 创建着色器 |
+ | `SceneResourceFactory.createEnvironment(): Promise` | 创建环境 |
+
+ - 尤其需要注意:在 ArkGraphics 3D 中需要将材质(Material)给与子网格(SubMesh)才能成功替换材质。
+
+ - | SubMesh 属性 | 说明 |
+ | ---------------------- | ------------------------ |
+ | name: string | 名称,没有特殊格式要求。 |
+ | **material: Material** | 材质。 |
+ | aabb: Aabb | 轴对齐边界盒。 |
+
+3. 创建动画:动画是3D场景中重要的资源类型,用于控制场景中各种元素的运动。
+
+ - 调用 `start` 方法控制动画开启;
+
+ - 调用 `pause` 方法控制动画暂停;
+
+ - 调用 `stop` 方法控制动画停止,并将动画状态设置为开头;
+
+ - 调用`finish` 方法控制动画结束,并将动画状态设置为结尾;
+
+ - 调用 `restart` 方法控制动画从头开始;
+
+ - 调用 `seek` 方法控制动画设置到指定状态;
+
+ - `onStarted` 方法在动画开始时执行传入的回调;
+
+ - `onFinished` 方法在动画结束时执行传入的回调。
+
+## 相关权限
+
+不涉及。
+
+## 依赖
+
+不涉及。
+
+## 约束与限制
+
+1.本示例仅支持在标准系统上运行;
+
+2.本示例为 Stage 模型,已适配 API version 14 版本 SDK,SDK 版本号(API Version 14 5.0.2.57);
+
+3.本示例需要使用 DevEco Studio 版本号(5.0.5.306)及以上版本才可编译运行。
+
+## 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/graphic/Arkgraphics3D/ > .git/info/sparse-checkout
+git remote add origin https://gitee.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..a02339aff59ee239682304883818f4b74b77666a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/build-profile.json5
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ "compatibleSdkVersion": 14,
+ "runtimeOS": "OpenHarmony"
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ],
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/code-linter.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/code-linter.json5
@@ -0,0 +1,32 @@
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/build-profile.json5
@@ -0,0 +1,28 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/obfuscation-rules.txt b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..97d03750b9972469c2c2deaad3140543658a2203
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,25 @@
+import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ preFontId = "";
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(DOMAIN, 'testTag', 'onCreate');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ hilog.info(DOMAIN, 'testTag', 'onWindowStageCreate');
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load content: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Content loaded successfully.');
+ });
+ }
+
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,16 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/pages/Index.ets b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..1b0219b85005077973f1203502617deaa0568627
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,114 @@
+// Index.ets
+import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
+import { UIContext } from '@kit.ArkUI'
+import { text } from '@kit.ArkGraphics2D'
+class MyRenderNode extends RenderNode {
+ async draw(context: DrawContext) {
+ // 创建画布canvas对象
+ const canvas = context.canvas
+ // 获取全局字体集实例
+ let fontCollection = text.FontCollection.getGlobalInstance() //获取Arkui全局FC
+ // 注册自定义字体
+ fontCollection.loadFontSync('myFamilyName', 'file:///system/fonts/NotoSansMalayalamUI-SemiBold.ttf')
+ // 使用自定义字体
+ let myFontFamily: Array = ["myFamilyName"] // 如果已经注册自定义字体,填入自定义字体的字体家族名
+ // 设置文本样式
+ let myTextStyle: text.TextStyle = {
+ color: { alpha: 255, red: 255, green: 0, blue: 0 },
+ fontSize: 30,
+ // 在文本样式中加入可使用的自定义字体
+ fontFamilies: myFontFamily
+ };
+ // 创建一个段落样式对象,以设置排版风格
+ let myParagraphStyle: text.ParagraphStyle = {
+ textStyle: myTextStyle,
+ align: 3,
+ wordBreak:text.WordBreak.NORMAL
+ };
+ // 创建一个段落生成器
+ let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection)
+ // 在段落生成器中设置文本样式
+ ParagraphGraphBuilder.pushStyle(myTextStyle);
+ // 在段落生成器中设置文本内容
+ ParagraphGraphBuilder.addText("Custom font test");
+ // 通过段落生成器生成段落
+ let paragraph = ParagraphGraphBuilder.build();
+ // 布局
+ paragraph.layoutSync(1000);
+ paragraph.paint(canvas, 0, 400);
+ }
+}
+
+// 创建一个MyRenderNode对象
+const newNode = new MyRenderNode();
+// 定义newNode的大小和位置
+newNode.frame = { x: 0, y: 0, width: 400, height: 600 };
+
+
+class MyNodeController extends NodeController {
+ private rootNode: FrameNode | null = null;
+ makeNode(uiContext: UIContext): FrameNode {
+ this.rootNode = new FrameNode(uiContext)
+ if (this.rootNode == null) {
+ return this.rootNode
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.frame = { x: 0, y: 0, width: 300, height: 50 }
+ renderNode.pivot = { x: 0, y: 0 }
+ }
+ return this.rootNode
+ }
+ addNode(node: RenderNode): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.appendChild(node)
+ }
+ }
+ clearNodes(): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.clearChildren()
+ }
+ }
+}
+
+@Entry
+@Component
+struct RenderTest {
+ private myNodeController: MyNodeController = new MyNodeController()
+ build() {
+ Column() {
+ Row() {
+ NodeContainer(this.myNodeController)
+ .height('100%')
+ }
+ .height('90%')
+ .backgroundColor(Color.White)
+ Row(){
+ Button("Draw Text")
+ .fontSize('16fp')
+ .fontWeight(500)
+ .margin({ bottom: 24, right: 12 })
+ .onClick(() => {
+ this.myNodeController.clearNodes()
+ this.myNodeController.addNode(newNode)
+ })
+ .width('50%')
+ .height(40)
+ .shadow(ShadowStyle.OUTER_DEFAULT_LG)
+ }
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .shadow(ShadowStyle.OUTER_DEFAULT_SM)
+ .alignItems(VerticalAlign.Bottom)
+ .layoutWeight(1)
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2cd3a6c601073f86f4789ab9db7529f84f705f3f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/module.json5
@@ -0,0 +1,51 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/float.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/dark/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..f17b64beab6dae463e1bc73f298ca24cb8a9d225
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import { describe, it, expect } from '@ohos/hypium';
+import { Driver, ON } from '@ohos.UiTest';
+
+const TAG = '[Sample_DrawingAPI]';
+
+export default function abilityTest() {
+
+ describe('ActsAbilityTest', () => {
+ /**
+ * 打开应用
+ */
+ it('StartAbility_001', 0, async (done: Function) => {
+ console.info(TAG, 'StartAbility_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.arkdrawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw Text'));
+ done();
+ console.info(TAG, 'StartAbility_001 end');
+ })
+
+ /**
+ * 点击按钮,绘制简单排版文本
+ */
+ it('DrawSimpleTextTEST_001', 2, async () => {
+ console.info(TAG, 'DrawSimpleTextTEST_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.arkdrawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `DrawSimpleTextTEST_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw Text'));
+ let drawTextBtn = await driver.findComponent(ON.text('Draw Text'));
+ // 点击'Draw simple text'按钮
+ await drawTextBtn.click();
+ await driver.delayMs(1000);
+ console.info(TAG, 'DrawSimpleTextTEST_001 end');
+ })
+
+ })
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..794c7dc4ed66bd98fa3865e07922906e2fcef545
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..69026872775eebd0844900b225c411959ae5608b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/entry/src/ohosTest/module.json5
@@ -0,0 +1,12 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/hvigor/hvigor-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fe83c3e838abfb3629eed84f6c7092f306d818f9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/hvigor/hvigor-config.json5
@@ -0,0 +1,22 @@
+{
+ "modelVersion": "5.0.2",
+ "dependencies": {
+ },
+ "execution": {
+ // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+ // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+ },
+ "nodeOptions": {
+ // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+ // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/oh-package-lock.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf818273347b97063c0c0a151bb14770ca1c79
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/oh-package-lock.json5
@@ -0,0 +1,27 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+ "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
+ },
+ "packages": {
+ "@ohos/hamock@1.0.0": {
+ "name": "@ohos/hamock",
+ "version": "1.0.0",
+ "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+ "registryType": "ohpm"
+ },
+ "@ohos/hypium@1.0.21": {
+ "name": "@ohos/hypium",
+ "version": "1.0.21",
+ "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9c36c086ae807ea710acd9e480cb6cc1d18bd011
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "modelVersion": "5.0.2",
+ "description": "Please describe the basic information.",
+ "dependencies": {
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.21",
+ "@ohos/hamock": "1.0.0"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/ohosTest.md b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/ohosTest.md
new file mode 100644
index 0000000000000000000000000000000000000000..280dbe74c4e1e68fdc32d7d2aab71374a791f532
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/ohosTest.md
@@ -0,0 +1,26 @@
+| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
+|:-------:|:------------:|:--------------:|:---------------------:|:----:|:----:|
+| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
+| 主页展示 | 设备正常运行 | | 展示 Building and Managing ArkGraphics 3D Scenes、Creating and Using ArkGraphics 3D Resources 和 Controlling and Managing ArkGraphics 3D Scene Animations 三种按钮 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Building and Managing ArkGraphics 3D Scenes 按钮 | 跳转 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Model Loading and Display 按钮 | 跳转至 Model 页面,显现头盔 | 是 | Pass |
+| Model 页面按钮点击 | 位于 Model 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing a Camera 按钮 | 跳转至 Camera 页面,显现几何体 | 是 | Pass |
+| Camera 页面按钮点击 | 位于 Camera 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing Light 按钮 | 跳转至 Light 页面 | 是 | Pass |
+| Light 页面按钮点击 | 位于 Light 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Creating and Using ArkGraphics 3D Resources 按钮 | 跳转至 Resource 页面,显现几何体 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a blank material 按钮 | 用空白材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a image material 按钮 | 用图像材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a shader material 按钮 | 用着色器材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Add to Environment 按钮 | 添加场景 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Controlling and Managing ArkGraphics 3D Scene Animations按钮 | 跳转至 Animation 页面 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Start 按钮 | 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Pause 按钮 | 暂停播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Stop 按钮 | 停止播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Finish 按钮 | 结束播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Restart 按钮 | 重新播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 seek to 30% progress 按钮 | 从 30% 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/CustomFont/screenshots/customFont.jpg b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/screenshots/customFont.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..01412f9c03f7c881ca740f05e01786e1a1931d0a
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/CustomFont/screenshots/customFont.jpg differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/app.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..15d714197fdf5d91703199923cf6afbdf9434372
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.samples.arkdrawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/README.md b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..981344b62f74e664ecc1b6a240538e11708b8c4c
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/README.md
@@ -0,0 +1,131 @@
+# ArkGraphics 3D
+
+## 介绍
+
+本示例通过 ArkGraphics 3D 的接口,利用轻量级的 3D 引擎和渲染管线,实现了 3D 场景创建、3D 场景资源创建和 3D 动画创建。
+
+本示例主要展现了如何利用 ArkGraphics 3D 来实现 3D 图像的渲染,其中利用 Scene、Camera 和 Light 来创建基础的场景,使用 Material、Shader、Image 和Environment 来实现场景资源,采用 Animation 的各种方法来播放 3D 动画。
+
+## 效果预览
+
+| Index | Scene | Resource | Animation |
+| :-----------------------------------------------: | :-----------------------------------------------: | :--------------------------------------------------: | :---------------------------------------------------: |
+|
|
|
|
|
+
+**使用方法:**
+
+1. 在 Index 页面点击 ` BUilding and Managing ArkGraphics 3D Scenes` 按钮,跳转至 Scene 页面;
+ - 在 Scene 页面点击 `Model Loading and Display` 按钮,页面跳转至 Model 页面,显现 3D 头盔图像。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing a Camera` 按钮,页面跳转至 Camera 页面,显现几何体图像。通过调节 `X-axis`、`Y-axis` 和 `Z-axis` 滑动条,即可分别修改相机的 X 轴,Y 轴和 Z 轴。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing Light` 按钮,页面跳转至 Light 页面,显现几何体图像。通过调节 `Red`、`Green` 和 `Blue` 滑动条,即可分别调节光线的红、绿和蓝的颜色通道。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Back` 按钮,返回至 `Index` 页面;
+2. 在 Index 页面点击 `Creating and using ArkGraphics 3D Resources` 按钮,跳转至 Resource 页面。点击 `Replace with a blank material` 按钮,几何体图像的材质被空白材质替换。点击 `Replace with a Shader material` 按钮,几何体图像的材质被着色器材质替换。点击 `Replace with a Image material`,几何体材质被图像材质替换。点击 `Add to Environment` 按钮,给几何体图像添加背景。点击 `Back` 按钮,返回至 Index 页面;
+3. 在 Index 页面点击 `Controlling and Managing ArkGraphics 3D Scene Animations` 按钮,跳转至 Animation 页面。点击 `start` 按钮,播放动画。点击 `pause` 按钮,中止动画。点击 `stop` 按钮,暂停动画。点击 `finish` 按钮,结束动画。点击 `restart` 按钮,重新播放动画。点击 `seek to 30% progress` 按钮,动画从 30% 进度开始播放。点击 `Back` 按钮,返回至 Index 页面;
+
+## 工程目录
+
+```
+|--entry/src/main
+│ |--ets // ets代码区
+│ │ |--entryability
+│ │ │ |--EntryAbility.ts // 程序入口类
+| | | |--EntryAbility.ets
+| | |--arkGraphic
+│ │ │ |--animation.ets // 动画
+| | | |--resource.ets // 场景资源
+| | | |--scene.ets // 场景搭建
+| | |--scene
+| | | |--camera.ets // 相机
+| | | |--init.ets // 模型加载
+| | | |--light.ets // 光线
+│ │ |--pages // 页面文件
+│ │ | |--Index.ets // 初始页面
+│ │ |--utils // 工具类
+| |--resources // 资源文件目录
+```
+
+## 具体实现
+
+1. 创建场景:一个 3D 场景通常由模型、相机和光源三个关键部分组成。其中先加载模型,再生成相机和光源。等 3D 图像加载完毕,可以使 Component3D 组件将渲染好的图像传递给用户。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------ | -------- |
+ | `Scene.load(): Promise` | 加载模型 |
+ | `SceneResourceFactory.createCamera(): Promise` | 创建相机 |
+ | `SceneResourceFactory.createLight(): Promise` | 创建光源 |
+
+ - | SceneOption 参数 | 描述 |
+ | -------------------- | ------------------------------------------------------------ |
+ | scene: Scene | 3D模型资源文件或场景对象,默认值为undefined。
**说明:目前仅支持GLTF格式资源。** |
+ | modelType: ModelType | 3D场景显示合成方式。
**说明:**
一般开发者可以使用默认值而无需关心此项设置。 |
+
+2. 创建场景资源:3D 场景中主要有以下常见资源:
+
+ - 材质(Material):材质是对场景中物体的光学物理性质的数学建模。在渲染计算的过程中,利用这些物理性质计算与光的相互作用,得到渲染的颜色。ArkGraphics 3D 提供的材质类型基于 PBR 渲染,支持用户参照 PBR 渲染材质类型创建材质资源,得到预期的渲染结果。
+
+ - 图片(Image): 图片本质上是上一个储存信息的二维内存块(buffer),用于储存 3D 渲染计算过程需要的相关信息,比如基础色、法线等等。ArkGraphics 3D 提供基于 PNG、JPG、KTX格式创建 Image 资源的能力,支持用户自定义需要的 Image 资源。
+
+ - 着色器(Shader): 着色器是 GPU 上可以执行的一段程序,可以控制 GPU 执行哪些并行计算操作。AGP 引擎提供的默认着色器实现了 PBR 渲染,开发者只需要指定对应的参数就可以完成不同的 PBR 渲染。ArkGraphics 3D 支持开发者创建自定义的着色器,开发者可以通过自定义着色器自定义渲染计算过程,完全控制渲染计算流程,比如控制某物体不受某光源的影响等。
+
+ - 环境(Environment): 环境是 3D 场景背景的一种描述,可以基于图片进行创建。通过将一张图片进行正方体或者球体的映射处理,将图片贴在正方体或者球体上,在 3D 场景中模拟真实的环境。ArkGraphics 3D 支持用户创建环境资源,定义 3D 场景的背景。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------------ | ---------- |
+ | `SceneResourceFactory.createMaterial(): Promise` | 创建材质 |
+ | `SceneResourceFactory.createImage(): Promise` | 创建图片 |
+ | `SceneResourceFactory.createShader(): Promise` | 创建着色器 |
+ | `SceneResourceFactory.createEnvironment(): Promise` | 创建环境 |
+
+ - 尤其需要注意:在 ArkGraphics 3D 中需要将材质(Material)给与子网格(SubMesh)才能成功替换材质。
+
+ - | SubMesh 属性 | 说明 |
+ | ---------------------- | ------------------------ |
+ | name: string | 名称,没有特殊格式要求。 |
+ | **material: Material** | 材质。 |
+ | aabb: Aabb | 轴对齐边界盒。 |
+
+3. 创建动画:动画是3D场景中重要的资源类型,用于控制场景中各种元素的运动。
+
+ - 调用 `start` 方法控制动画开启;
+
+ - 调用 `pause` 方法控制动画暂停;
+
+ - 调用 `stop` 方法控制动画停止,并将动画状态设置为开头;
+
+ - 调用`finish` 方法控制动画结束,并将动画状态设置为结尾;
+
+ - 调用 `restart` 方法控制动画从头开始;
+
+ - 调用 `seek` 方法控制动画设置到指定状态;
+
+ - `onStarted` 方法在动画开始时执行传入的回调;
+
+ - `onFinished` 方法在动画结束时执行传入的回调。
+
+## 相关权限
+
+不涉及。
+
+## 依赖
+
+不涉及。
+
+## 约束与限制
+
+1.本示例仅支持在标准系统上运行;
+
+2.本示例为 Stage 模型,已适配 API version 14 版本 SDK,SDK 版本号(API Version 14 5.0.2.57);
+
+3.本示例需要使用 DevEco Studio 版本号(5.0.5.306)及以上版本才可编译运行。
+
+## 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/graphic/Arkgraphics3D/ > .git/info/sparse-checkout
+git remote add origin https://gitee.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..a02339aff59ee239682304883818f4b74b77666a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/build-profile.json5
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ "compatibleSdkVersion": 14,
+ "runtimeOS": "OpenHarmony"
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ],
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/code-linter.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/code-linter.json5
@@ -0,0 +1,32 @@
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/build-profile.json5
@@ -0,0 +1,28 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/obfuscation-rules.txt b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..97d03750b9972469c2c2deaad3140543658a2203
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,25 @@
+import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ preFontId = "";
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(DOMAIN, 'testTag', 'onCreate');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ hilog.info(DOMAIN, 'testTag', 'onWindowStageCreate');
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load content: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Content loaded successfully.');
+ });
+ }
+
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,16 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/pages/Index.ets b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..2f949f3ae71fd78dcf734194f9120ad135e5927e
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,131 @@
+import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
+import { UIContext } from '@kit.ArkUI'
+import { text } from '@kit.ArkGraphics2D'
+
+// 创建一个MyRenderNode类,并绘制文本。
+class MyRenderNode extends RenderNode {
+ async draw(context: DrawContext) {
+
+ // 绘制代码逻辑写在这里
+ let canvas = context.canvas;
+
+ let myTextStyle: text.TextStyle = {
+ // 文本颜色
+ color: {
+ alpha: 255,
+ red: 255,
+ green: 0,
+ blue: 0
+ },
+ // 文本大小
+ fontSize: 100
+ };
+
+ let myParagraphStyle: text.ParagraphStyle = {
+ textStyle: myTextStyle,
+ };
+ let fontCollection = text.FontCollection.getGlobalInstance();
+ let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection);
+ // 更新文本样式
+ ParagraphGraphBuilder.pushStyle(myTextStyle);
+ // 添加文本
+ ParagraphGraphBuilder.addText("Hello World");
+
+ // 生成段落
+ let paragraph = ParagraphGraphBuilder.build();
+ // 布局
+ paragraph.layoutSync(1250);
+ // 绘制文本
+ paragraph.paint(canvas, 0, 100);
+ }
+}
+
+// 创建一个MyRenderNode对象
+const textNode = new MyRenderNode()
+// 定义newNode的像素格式
+textNode.frame = {
+ x: 0,
+ y: 100,
+ width: 1250,
+ height: 800
+}
+textNode.pivot = { x: 0.2, y: 0.8 }
+textNode.scale = { x: 1, y: 1 }
+
+class MyNodeController extends NodeController {
+ private rootNode: FrameNode | null = null;
+
+ makeNode(uiContext: UIContext): FrameNode {
+ this.rootNode = new FrameNode(uiContext)
+ if (this.rootNode == null) {
+ return this.rootNode
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.frame = {
+ x: 0,
+ y: 0,
+ width: 10,
+ height: 500
+ }
+ renderNode.pivot = { x: 50, y: 50 }
+ }
+ return this.rootNode
+ }
+
+ addNode(node: RenderNode): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.appendChild(node)
+ }
+ }
+
+ clearNodes(): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.clearChildren()
+ }
+ }
+}
+
+// 创建一个MyRenderNode对象
+const newNode = new MyRenderNode();
+// 定义newNode的大小和位置
+newNode.frame = { x: 0, y: 0, width: 400, height: 600 };
+
+@Entry
+@Component
+struct RenderTest {
+ private myNodeController: MyNodeController = new MyNodeController()
+ build() {
+ Column() {
+ Row(){
+ NodeContainer(this.myNodeController)
+ .height('100%')
+ .position({x : 50, y: 25})
+ Button("Draw simple text")
+ .fontSize('16fp')
+ .fontWeight(500)
+ .margin({ bottom: 24, right: 12 })
+ .onClick(() => {
+ this.myNodeController.clearNodes()
+ this.myNodeController.addNode(newNode)
+ })
+ .width('50%')
+ .height(40)
+ .shadow(ShadowStyle.OUTER_DEFAULT_LG)
+ }
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .shadow(ShadowStyle.OUTER_DEFAULT_SM)
+ .alignItems(VerticalAlign.Bottom)
+ .layoutWeight(1)
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2cd3a6c601073f86f4789ab9db7529f84f705f3f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/module.json5
@@ -0,0 +1,51 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/float.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/dark/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/ets/test/DrawingAbility.test.ets b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/ets/test/DrawingAbility.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8c08561bcbc279bddcc6bf837d8a3d86e9ccd204
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/ets/test/DrawingAbility.test.ets
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import { describe, it, expect } from '@ohos/hypium';
+import { Driver, ON } from '@ohos.UiTest';
+
+const TAG = '[Sample_DrawingAPI]';
+
+export default function abilityTest() {
+
+ describe('ActsAbilityTest', () => {
+ /**
+ * 打开应用
+ */
+ it('StartAbility_001', 0, async (done: Function) => {
+ console.info(TAG, 'StartAbility_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.arkdrawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw simple text'));
+ done();
+ console.info(TAG, 'StartAbility_001 end');
+ })
+
+ /**
+ * 点击按钮,绘制简单排版文本
+ */
+ it('DrawSimpleTextTEST_001', 2, async () => {
+ console.info(TAG, 'DrawSimpleTextTEST_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.arkdrawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `DrawSimpleTextTEST_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw simple text'));
+ let drawTextBtn = await driver.findComponent(ON.text('Draw simple text'));
+ // 点击'Draw simple text'按钮
+ await drawTextBtn.click();
+ await driver.delayMs(1000);
+ console.info(TAG, 'DrawSimpleTextTEST_001 end');
+ })
+
+ })
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..bd459680696508a818779ec1f5be61310577201f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './DrawingAbility.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..69026872775eebd0844900b225c411959ae5608b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/entry/src/ohosTest/module.json5
@@ -0,0 +1,12 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/hvigor/hvigor-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fe83c3e838abfb3629eed84f6c7092f306d818f9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/hvigor/hvigor-config.json5
@@ -0,0 +1,22 @@
+{
+ "modelVersion": "5.0.2",
+ "dependencies": {
+ },
+ "execution": {
+ // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+ // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+ },
+ "nodeOptions": {
+ // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+ // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/oh-package-lock.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf818273347b97063c0c0a151bb14770ca1c79
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/oh-package-lock.json5
@@ -0,0 +1,27 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+ "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
+ },
+ "packages": {
+ "@ohos/hamock@1.0.0": {
+ "name": "@ohos/hamock",
+ "version": "1.0.0",
+ "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+ "registryType": "ohpm"
+ },
+ "@ohos/hypium@1.0.21": {
+ "name": "@ohos/hypium",
+ "version": "1.0.21",
+ "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9c36c086ae807ea710acd9e480cb6cc1d18bd011
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "modelVersion": "5.0.2",
+ "description": "Please describe the basic information.",
+ "dependencies": {
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.21",
+ "@ohos/hamock": "1.0.0"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/ohosTest.md b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/ohosTest.md
new file mode 100644
index 0000000000000000000000000000000000000000..280dbe74c4e1e68fdc32d7d2aab71374a791f532
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/ohosTest.md
@@ -0,0 +1,26 @@
+| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
+|:-------:|:------------:|:--------------:|:---------------------:|:----:|:----:|
+| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
+| 主页展示 | 设备正常运行 | | 展示 Building and Managing ArkGraphics 3D Scenes、Creating and Using ArkGraphics 3D Resources 和 Controlling and Managing ArkGraphics 3D Scene Animations 三种按钮 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Building and Managing ArkGraphics 3D Scenes 按钮 | 跳转 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Model Loading and Display 按钮 | 跳转至 Model 页面,显现头盔 | 是 | Pass |
+| Model 页面按钮点击 | 位于 Model 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing a Camera 按钮 | 跳转至 Camera 页面,显现几何体 | 是 | Pass |
+| Camera 页面按钮点击 | 位于 Camera 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing Light 按钮 | 跳转至 Light 页面 | 是 | Pass |
+| Light 页面按钮点击 | 位于 Light 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Creating and Using ArkGraphics 3D Resources 按钮 | 跳转至 Resource 页面,显现几何体 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a blank material 按钮 | 用空白材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a image material 按钮 | 用图像材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a shader material 按钮 | 用着色器材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Add to Environment 按钮 | 添加场景 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Controlling and Managing ArkGraphics 3D Scene Animations按钮 | 跳转至 Animation 页面 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Start 按钮 | 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Pause 按钮 | 暂停播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Stop 按钮 | 停止播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Finish 按钮 | 结束播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Restart 按钮 | 重新播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 seek to 30% progress 按钮 | 从 30% 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/screenshots/IMG_1501838463_003.jpg b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/screenshots/IMG_1501838463_003.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..9515288487d3635a40b5537f2a25b0d0f5af65d9
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SimpleTextDrawing/screenshots/IMG_1501838463_003.jpg differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/app.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..6254db89feb0cfd1b1bbd585e9bbb51f65f6ed1a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.samples.drawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/README.md b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..981344b62f74e664ecc1b6a240538e11708b8c4c
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/README.md
@@ -0,0 +1,131 @@
+# ArkGraphics 3D
+
+## 介绍
+
+本示例通过 ArkGraphics 3D 的接口,利用轻量级的 3D 引擎和渲染管线,实现了 3D 场景创建、3D 场景资源创建和 3D 动画创建。
+
+本示例主要展现了如何利用 ArkGraphics 3D 来实现 3D 图像的渲染,其中利用 Scene、Camera 和 Light 来创建基础的场景,使用 Material、Shader、Image 和Environment 来实现场景资源,采用 Animation 的各种方法来播放 3D 动画。
+
+## 效果预览
+
+| Index | Scene | Resource | Animation |
+| :-----------------------------------------------: | :-----------------------------------------------: | :--------------------------------------------------: | :---------------------------------------------------: |
+|
|
|
|
|
+
+**使用方法:**
+
+1. 在 Index 页面点击 ` BUilding and Managing ArkGraphics 3D Scenes` 按钮,跳转至 Scene 页面;
+ - 在 Scene 页面点击 `Model Loading and Display` 按钮,页面跳转至 Model 页面,显现 3D 头盔图像。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing a Camera` 按钮,页面跳转至 Camera 页面,显现几何体图像。通过调节 `X-axis`、`Y-axis` 和 `Z-axis` 滑动条,即可分别修改相机的 X 轴,Y 轴和 Z 轴。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing Light` 按钮,页面跳转至 Light 页面,显现几何体图像。通过调节 `Red`、`Green` 和 `Blue` 滑动条,即可分别调节光线的红、绿和蓝的颜色通道。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Back` 按钮,返回至 `Index` 页面;
+2. 在 Index 页面点击 `Creating and using ArkGraphics 3D Resources` 按钮,跳转至 Resource 页面。点击 `Replace with a blank material` 按钮,几何体图像的材质被空白材质替换。点击 `Replace with a Shader material` 按钮,几何体图像的材质被着色器材质替换。点击 `Replace with a Image material`,几何体材质被图像材质替换。点击 `Add to Environment` 按钮,给几何体图像添加背景。点击 `Back` 按钮,返回至 Index 页面;
+3. 在 Index 页面点击 `Controlling and Managing ArkGraphics 3D Scene Animations` 按钮,跳转至 Animation 页面。点击 `start` 按钮,播放动画。点击 `pause` 按钮,中止动画。点击 `stop` 按钮,暂停动画。点击 `finish` 按钮,结束动画。点击 `restart` 按钮,重新播放动画。点击 `seek to 30% progress` 按钮,动画从 30% 进度开始播放。点击 `Back` 按钮,返回至 Index 页面;
+
+## 工程目录
+
+```
+|--entry/src/main
+│ |--ets // ets代码区
+│ │ |--entryability
+│ │ │ |--EntryAbility.ts // 程序入口类
+| | | |--EntryAbility.ets
+| | |--arkGraphic
+│ │ │ |--animation.ets // 动画
+| | | |--resource.ets // 场景资源
+| | | |--scene.ets // 场景搭建
+| | |--scene
+| | | |--camera.ets // 相机
+| | | |--init.ets // 模型加载
+| | | |--light.ets // 光线
+│ │ |--pages // 页面文件
+│ │ | |--Index.ets // 初始页面
+│ │ |--utils // 工具类
+| |--resources // 资源文件目录
+```
+
+## 具体实现
+
+1. 创建场景:一个 3D 场景通常由模型、相机和光源三个关键部分组成。其中先加载模型,再生成相机和光源。等 3D 图像加载完毕,可以使 Component3D 组件将渲染好的图像传递给用户。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------ | -------- |
+ | `Scene.load(): Promise` | 加载模型 |
+ | `SceneResourceFactory.createCamera(): Promise` | 创建相机 |
+ | `SceneResourceFactory.createLight(): Promise` | 创建光源 |
+
+ - | SceneOption 参数 | 描述 |
+ | -------------------- | ------------------------------------------------------------ |
+ | scene: Scene | 3D模型资源文件或场景对象,默认值为undefined。
**说明:目前仅支持GLTF格式资源。** |
+ | modelType: ModelType | 3D场景显示合成方式。
**说明:**
一般开发者可以使用默认值而无需关心此项设置。 |
+
+2. 创建场景资源:3D 场景中主要有以下常见资源:
+
+ - 材质(Material):材质是对场景中物体的光学物理性质的数学建模。在渲染计算的过程中,利用这些物理性质计算与光的相互作用,得到渲染的颜色。ArkGraphics 3D 提供的材质类型基于 PBR 渲染,支持用户参照 PBR 渲染材质类型创建材质资源,得到预期的渲染结果。
+
+ - 图片(Image): 图片本质上是上一个储存信息的二维内存块(buffer),用于储存 3D 渲染计算过程需要的相关信息,比如基础色、法线等等。ArkGraphics 3D 提供基于 PNG、JPG、KTX格式创建 Image 资源的能力,支持用户自定义需要的 Image 资源。
+
+ - 着色器(Shader): 着色器是 GPU 上可以执行的一段程序,可以控制 GPU 执行哪些并行计算操作。AGP 引擎提供的默认着色器实现了 PBR 渲染,开发者只需要指定对应的参数就可以完成不同的 PBR 渲染。ArkGraphics 3D 支持开发者创建自定义的着色器,开发者可以通过自定义着色器自定义渲染计算过程,完全控制渲染计算流程,比如控制某物体不受某光源的影响等。
+
+ - 环境(Environment): 环境是 3D 场景背景的一种描述,可以基于图片进行创建。通过将一张图片进行正方体或者球体的映射处理,将图片贴在正方体或者球体上,在 3D 场景中模拟真实的环境。ArkGraphics 3D 支持用户创建环境资源,定义 3D 场景的背景。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------------ | ---------- |
+ | `SceneResourceFactory.createMaterial(): Promise` | 创建材质 |
+ | `SceneResourceFactory.createImage(): Promise` | 创建图片 |
+ | `SceneResourceFactory.createShader(): Promise` | 创建着色器 |
+ | `SceneResourceFactory.createEnvironment(): Promise` | 创建环境 |
+
+ - 尤其需要注意:在 ArkGraphics 3D 中需要将材质(Material)给与子网格(SubMesh)才能成功替换材质。
+
+ - | SubMesh 属性 | 说明 |
+ | ---------------------- | ------------------------ |
+ | name: string | 名称,没有特殊格式要求。 |
+ | **material: Material** | 材质。 |
+ | aabb: Aabb | 轴对齐边界盒。 |
+
+3. 创建动画:动画是3D场景中重要的资源类型,用于控制场景中各种元素的运动。
+
+ - 调用 `start` 方法控制动画开启;
+
+ - 调用 `pause` 方法控制动画暂停;
+
+ - 调用 `stop` 方法控制动画停止,并将动画状态设置为开头;
+
+ - 调用`finish` 方法控制动画结束,并将动画状态设置为结尾;
+
+ - 调用 `restart` 方法控制动画从头开始;
+
+ - 调用 `seek` 方法控制动画设置到指定状态;
+
+ - `onStarted` 方法在动画开始时执行传入的回调;
+
+ - `onFinished` 方法在动画结束时执行传入的回调。
+
+## 相关权限
+
+不涉及。
+
+## 依赖
+
+不涉及。
+
+## 约束与限制
+
+1.本示例仅支持在标准系统上运行;
+
+2.本示例为 Stage 模型,已适配 API version 14 版本 SDK,SDK 版本号(API Version 14 5.0.2.57);
+
+3.本示例需要使用 DevEco Studio 版本号(5.0.5.306)及以上版本才可编译运行。
+
+## 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/graphic/Arkgraphics3D/ > .git/info/sparse-checkout
+git remote add origin https://gitee.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..a02339aff59ee239682304883818f4b74b77666a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/build-profile.json5
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ "compatibleSdkVersion": 14,
+ "runtimeOS": "OpenHarmony"
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ],
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/code-linter.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/code-linter.json5
@@ -0,0 +1,32 @@
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/build-profile.json5
@@ -0,0 +1,28 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/obfuscation-rules.txt b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..97d03750b9972469c2c2deaad3140543658a2203
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,25 @@
+import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ preFontId = "";
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(DOMAIN, 'testTag', 'onCreate');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ hilog.info(DOMAIN, 'testTag', 'onWindowStageCreate');
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load content: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Content loaded successfully.');
+ });
+ }
+
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,16 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/pages/Index.ets b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..7fe42e6a98b0174b08d01148982727b6bd07071f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,138 @@
+// Index.ets
+import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
+import { UIContext } from '@kit.ArkUI'
+import { text } from '@kit.ArkGraphics2D'
+import { font } from '@kit.ArkUI'
+
+class MyRenderNode extends RenderNode {
+ async draw(context: DrawContext) {
+ // 创建画布canvas对象
+ const canvas = context.canvas
+ // 获取全局字体集实例
+ let fontCollection = text.FontCollection.getGlobalInstance() //获取Arkui全局FC
+ // 设置文本样式
+ let textStyle1: text.TextStyle = {
+ color: { alpha: 255, red: 255, green: 0, blue: 0 },
+ fontSize: 100,
+ fontFamilies:['HarmonyOS Sans SC']
+ };
+ let textStyle2: text.TextStyle = {
+ color: { alpha: 255, red: 255, green: 0, blue: 0 },
+ fontSize: 100,
+ fontFamilies:['HarmonyOS Sans TC']
+ };
+ // 创建一个段落样式对象,以设置排版风格
+ let myParagraphStyle: text.ParagraphStyle = {
+ textStyle: textStyle1,
+ align: 3,
+ wordBreak:text.WordBreak.NORMAL
+ };
+ // 创建一个段落生成器
+ let ParagraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection)
+ // 在段落生成器中设置文本样式
+ ParagraphGraphBuilder.pushStyle(textStyle1);
+ // 在段落生成器中设置文本内容
+ ParagraphGraphBuilder.addText("模块描述\n");
+ // 将textStyle2添加到段落样式中,再添加文字
+ ParagraphGraphBuilder.pushStyle(textStyle2);
+ ParagraphGraphBuilder.addText("模块描述\n");
+ // 通过段落生成器生成段落
+ let paragraph = ParagraphGraphBuilder.build();
+ // 布局
+ paragraph.layoutSync(1000);
+ paragraph.paint(canvas, 0, 400);
+ }
+}
+
+// 创建一个MyRenderNode对象
+const textNode = new MyRenderNode();
+// 定义newNode的大小和位置
+textNode.frame = { x: 0, y: 0, width: 400, height: 600 };
+
+
+class MyNodeController extends NodeController {
+ private rootNode: FrameNode | null = null;
+ makeNode(uiContext: UIContext): FrameNode {
+ this.rootNode = new FrameNode(uiContext)
+ if (this.rootNode == null) {
+ return this.rootNode
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.frame = { x: 0, y: 0, width: 300, height: 50 }
+ renderNode.pivot = { x: 0, y: 0 }
+ }
+ return this.rootNode
+ }
+ addNode(node: RenderNode): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.appendChild(node)
+ }
+ }
+ clearNodes(): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.clearChildren()
+ }
+ }
+}
+
+@Entry
+@Component
+struct RenderTest {
+ private myNodeController: MyNodeController = new MyNodeController()
+
+ build() {
+ Column() {
+ Row() {
+ NodeContainer(this.myNodeController)
+ .height('100%')
+ }
+ .height('90%')
+ .backgroundColor(Color.White)
+
+ Row() {
+ Button("getUIFontConfig")
+ .width('60%')
+ .height('6%')
+ .margin(50)
+ .onClick(() => {
+ this.myNodeController.clearNodes()
+ this.myNodeController.addNode(textNode)
+ let fontConfig = font.getUIFontConfig();
+ console.info("sysFontMfg::font-dir -----------" + String(fontConfig.fontDir.length));
+ for (let i = 0; i < fontConfig.fontDir.length; i++) {
+ console.info(fontConfig.fontDir[i]);
+ }
+ console.info("sysFontMfg::generic-------------" + String(fontConfig.generic.length));
+ for (let i = 0; i < fontConfig.generic.length; i++) {
+ console.info("sysFontMfg::family:" + fontConfig.generic[i].family);
+ for (let j = 0; j < fontConfig.generic[i].alias.length; j++) {
+ console.info(fontConfig.generic[i].alias[j].name + " " + fontConfig.generic[i].alias[j].weight);
+ }
+ }
+ console.info("sysFontMfg::fallback------------" + String(fontConfig.fallbackGroups.length));
+ for (let i = 0; i < fontConfig.fallbackGroups.length; i++) {
+ console.info("sysFontMfg::fontSetName:" + fontConfig.fallbackGroups[i].fontSetName);
+ for (let j = 0; j < fontConfig.fallbackGroups[i].fallback.length; j++) {
+ console.info("sysFontMfg::language:" + fontConfig.fallbackGroups[i].fallback[j].language + " family:" +
+ fontConfig.fallbackGroups[i].fallback[j].family);
+ }
+ }
+ })
+ .margin({ bottom: 40 , left : 80})
+ }.width('100%')
+ }
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .shadow(ShadowStyle.OUTER_DEFAULT_SM)
+ .layoutWeight(1)
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2cd3a6c601073f86f4789ab9db7529f84f705f3f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/module.json5
@@ -0,0 +1,51 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/float.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/dark/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..33bfa76dec7b4e0572c1fc2039f7f177ae862157
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import { describe, it, expect } from '@ohos/hypium';
+import { Driver, ON } from '@ohos.UiTest';
+
+const TAG = '[Sample_DrawingAPI]';
+
+export default function abilityTest() {
+
+ describe('ActsAbilityTest', () => {
+ /**
+ * 打开应用
+ */
+ it('StartAbility_001', 0, async (done: Function) => {
+ console.info(TAG, 'StartAbility_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('getUIFontConfig'));
+ done();
+ console.info(TAG, 'StartAbility_001 end');
+ })
+
+ /**
+ * 点击按钮,绘制简单排版文本
+ */
+ it('DrawSimpleTextTEST_001', 2, async () => {
+ console.info(TAG, 'DrawSimpleTextTEST_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `DrawSimpleTextTEST_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('getUIFontConfig'));
+ let drawTextBtn = await driver.findComponent(ON.text('getUIFontConfig'));
+ // 点击'Draw simple text'按钮
+ await drawTextBtn.click();
+ await driver.delayMs(1000);
+ console.info(TAG, 'DrawSimpleTextTEST_001 end');
+ })
+
+ })
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..794c7dc4ed66bd98fa3865e07922906e2fcef545
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..69026872775eebd0844900b225c411959ae5608b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/entry/src/ohosTest/module.json5
@@ -0,0 +1,12 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/hvigor/hvigor-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fe83c3e838abfb3629eed84f6c7092f306d818f9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/hvigor/hvigor-config.json5
@@ -0,0 +1,22 @@
+{
+ "modelVersion": "5.0.2",
+ "dependencies": {
+ },
+ "execution": {
+ // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+ // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+ },
+ "nodeOptions": {
+ // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+ // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/oh-package-lock.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf818273347b97063c0c0a151bb14770ca1c79
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/oh-package-lock.json5
@@ -0,0 +1,27 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+ "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
+ },
+ "packages": {
+ "@ohos/hamock@1.0.0": {
+ "name": "@ohos/hamock",
+ "version": "1.0.0",
+ "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+ "registryType": "ohpm"
+ },
+ "@ohos/hypium@1.0.21": {
+ "name": "@ohos/hypium",
+ "version": "1.0.21",
+ "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9c36c086ae807ea710acd9e480cb6cc1d18bd011
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "modelVersion": "5.0.2",
+ "description": "Please describe the basic information.",
+ "dependencies": {
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.21",
+ "@ohos/hamock": "1.0.0"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/ohosTest.md b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/ohosTest.md
new file mode 100644
index 0000000000000000000000000000000000000000..280dbe74c4e1e68fdc32d7d2aab71374a791f532
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/ohosTest.md
@@ -0,0 +1,26 @@
+| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
+|:-------:|:------------:|:--------------:|:---------------------:|:----:|:----:|
+| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
+| 主页展示 | 设备正常运行 | | 展示 Building and Managing ArkGraphics 3D Scenes、Creating and Using ArkGraphics 3D Resources 和 Controlling and Managing ArkGraphics 3D Scene Animations 三种按钮 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Building and Managing ArkGraphics 3D Scenes 按钮 | 跳转 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Model Loading and Display 按钮 | 跳转至 Model 页面,显现头盔 | 是 | Pass |
+| Model 页面按钮点击 | 位于 Model 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing a Camera 按钮 | 跳转至 Camera 页面,显现几何体 | 是 | Pass |
+| Camera 页面按钮点击 | 位于 Camera 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing Light 按钮 | 跳转至 Light 页面 | 是 | Pass |
+| Light 页面按钮点击 | 位于 Light 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Creating and Using ArkGraphics 3D Resources 按钮 | 跳转至 Resource 页面,显现几何体 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a blank material 按钮 | 用空白材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a image material 按钮 | 用图像材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a shader material 按钮 | 用着色器材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Add to Environment 按钮 | 添加场景 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Controlling and Managing ArkGraphics 3D Scene Animations按钮 | 跳转至 Animation 页面 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Start 按钮 | 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Pause 按钮 | 暂停播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Stop 按钮 | 停止播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Finish 按钮 | 结束播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Restart 按钮 | 重新播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 seek to 30% progress 按钮 | 从 30% 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/screenshots/IMG_1501866608_001.jpg b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/screenshots/IMG_1501866608_001.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..6f42efd72b3c082b710e1ca8e2add49c1281d8d0
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/SystemFontMsgGet/screenshots/IMG_1501866608_001.jpg differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/app.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..6254db89feb0cfd1b1bbd585e9bbb51f65f6ed1a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.samples.drawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..a02339aff59ee239682304883818f4b74b77666a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/build-profile.json5
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ "compatibleSdkVersion": 14,
+ "runtimeOS": "OpenHarmony"
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ],
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/code-linter.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/code-linter.json5
@@ -0,0 +1,32 @@
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/build-profile.json5
@@ -0,0 +1,28 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/obfuscation-rules.txt b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..97d03750b9972469c2c2deaad3140543658a2203
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,25 @@
+import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ preFontId = "";
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(DOMAIN, 'testTag', 'onCreate');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ hilog.info(DOMAIN, 'testTag', 'onWindowStageCreate');
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load content: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Content loaded successfully.');
+ });
+ }
+
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,16 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/pages/Index.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..41628cddb23808960710f0be055926bb5ddb854d
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,146 @@
+// Index.ets
+import { NodeController, FrameNode, RenderNode, DrawContext } from '@kit.ArkUI'
+import { UIContext } from '@kit.ArkUI'
+import { text } from '@kit.ArkGraphics2D'
+
+class MyRenderNode extends RenderNode {
+ async draw(context: DrawContext) {
+ // 获取画布canvas对象
+ const canvas = context.canvas
+ // 设置文本样式
+ let myTextStyle: text.TextStyle = {
+ color: {
+ alpha: 255,
+ red: 255,
+ green: 0,
+ blue: 0
+ },
+ fontSize: 100
+ };
+ // 创建一个段落样式对象,以设置排版风格
+ let myParagraphStyle: text.ParagraphStyle = {
+ textStyle: myTextStyle,
+ wordBreak: text.WordBreak.NORMAL
+ }
+ // 创建一个段落生成器
+ let paragraphBuilder = new text.ParagraphBuilder(myParagraphStyle, new text.FontCollection())
+ // 在段落生成器中设置文本样式
+ paragraphBuilder.pushStyle(myTextStyle);
+ // 在段落生成器中设置文本内容
+ paragraphBuilder.addText("文本测量测试");
+ // 通过段落生成器生成段落
+ let paragraph = paragraphBuilder.build();
+ // 布局
+ paragraph.layoutSync(1000);
+ // case1: 获取排版后最长行行宽
+ let longestLineWidth = paragraph.getLongestLine();
+ console.info("longestLineWidth = " + longestLineWidth);
+
+ // case2: 获取排版后最长行行宽(包含缩进)
+ let longestLineWithIndentWidth = paragraph.getLongestLineWithIndent();
+ console.info("longestLineWithIndentWidth = " + longestLineWithIndentWidth);
+
+ // case3: 获取排版后所有行对象
+ let textLines = paragraph.getTextLines();
+ for (let index = 0; index < textLines.length; index++) {
+ const textline = textLines[index];
+ let curLineRange = textline.getTextRange();
+ let curLineGlyCnt = textline.getGlyphCount();
+ console.info("MetricsMSG: 第" + (index + 1) + "行 TextRange start: " + curLineRange.start + " TextRange end: " + curLineRange.end);
+ console.info("MetricsMSG: 第" + (index + 1) + "行字形数量为: " + curLineGlyCnt);
+ }
+
+ // case4: 获取排版后指定行对应的度量信息
+ let lineCnt = paragraph.getLineCount();
+ for (let index = 0; index < lineCnt; index++) {
+ let lineMetrics = paragraph.getLineMetrics(index);
+ if (lineMetrics) {
+ console.info("MetricsMSG: 第" + (index + 1) + "行 lineMetrics width: " + lineMetrics.width);
+ console.info("MetricsMSG: 第" + (index + 1) + "行 lineMetrics start index: " + lineMetrics.startIndex + ", end index: " +
+ lineMetrics.endIndex);
+ }
+ }
+
+ // case5: 获取排版后所有行度量信息数组
+ let allLineMetrics = paragraph.getLineMetrics();
+ paragraph.paint(canvas, 0, 800);
+ }
+}
+
+// 创建一个MyRenderNode对象
+const textNode = new MyRenderNode();
+// 定义newNode的大小和位置
+textNode.frame = { x: 0, y: 0, width: 400, height: 600 };
+
+class MyNodeController extends NodeController {
+ private rootNode: FrameNode | null = null;
+
+ makeNode(uiContext: UIContext): FrameNode {
+ this.rootNode = new FrameNode(uiContext)
+ if (this.rootNode == null) {
+ return this.rootNode
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.frame = {
+ x: 0,
+ y: 0,
+ width: 300,
+ height: 50
+ }
+ renderNode.pivot = { x: 0, y: 0 }
+ }
+ return this.rootNode
+ }
+
+ addNode(node: RenderNode): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.appendChild(node)
+ }
+ }
+
+ clearNodes(): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.clearChildren()
+ }
+ }
+}
+
+@Entry
+@Component
+struct RenderTest {
+ private myNodeController: MyNodeController = new MyNodeController()
+
+ build() {
+ Column() {
+ Row() {
+ NodeContainer(this.myNodeController)
+ .height('100%')
+ .position({x : 30, y: 25})
+
+ Button("Draw Text")
+ .fontSize('16fp')
+ .fontWeight(500)
+ .margin({ bottom: 24, right: 12 })
+ .onClick(() => {
+ this.myNodeController.clearNodes()
+ this.myNodeController.addNode(textNode)
+ })
+ .width('50%')
+ .height(40)
+ }
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .alignItems(VerticalAlign.Bottom)
+ .layoutWeight(1)
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2cd3a6c601073f86f4789ab9db7529f84f705f3f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/module.json5
@@ -0,0 +1,51 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/float.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/dark/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/mock/mock-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/mock/mock-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7a73a41bfdf76d6f793007240d80983a52f15f97
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/mock/mock-config.json5
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8117ccdfa17fa69e67a02fb3afab2db2b8c9f923
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import { describe, it, expect } from '@ohos/hypium';
+import { Driver, ON } from '@ohos.UiTest';
+
+const TAG = '[Sample_DrawingAPI]';
+
+export default function abilityTest() {
+
+ describe('ActsAbilityTest', () => {
+ /**
+ * 打开应用
+ */
+ it('StartAbility_001', 0, async (done: Function) => {
+ console.info(TAG, 'StartAbility_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw Text'));
+ done();
+ console.info(TAG, 'StartAbility_001 end');
+ })
+
+ /**
+ * 点击按钮,绘制简单排版文本
+ */
+ it('DrawSimpleTextTEST_001', 2, async () => {
+ console.info(TAG, 'DrawSimpleTextTEST_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `DrawSimpleTextTEST_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw Text'));
+ let drawTextBtn = await driver.findComponent(ON.text('Draw Text'));
+ // 点击'Draw simple text'按钮
+ await drawTextBtn.click();
+ await driver.delayMs(1000);
+ console.info(TAG, 'DrawSimpleTextTEST_001 end');
+ })
+
+ })
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..794c7dc4ed66bd98fa3865e07922906e2fcef545
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..69026872775eebd0844900b225c411959ae5608b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/ohosTest/module.json5
@@ -0,0 +1,12 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..bb5b5c3731e283dd507c847560ee59bde477bbc7
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/test/LocalUnit.test.ets b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..165fc1615ee8618b4cb6a622f144a9a707eee99f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/hvigor/hvigor-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fe83c3e838abfb3629eed84f6c7092f306d818f9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/hvigor/hvigor-config.json5
@@ -0,0 +1,22 @@
+{
+ "modelVersion": "5.0.2",
+ "dependencies": {
+ },
+ "execution": {
+ // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+ // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+ },
+ "nodeOptions": {
+ // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+ // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/oh-package-lock.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf818273347b97063c0c0a151bb14770ca1c79
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/oh-package-lock.json5
@@ -0,0 +1,27 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+ "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
+ },
+ "packages": {
+ "@ohos/hamock@1.0.0": {
+ "name": "@ohos/hamock",
+ "version": "1.0.0",
+ "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+ "registryType": "ohpm"
+ },
+ "@ohos/hypium@1.0.21": {
+ "name": "@ohos/hypium",
+ "version": "1.0.21",
+ "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9c36c086ae807ea710acd9e480cb6cc1d18bd011
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "modelVersion": "5.0.2",
+ "description": "Please describe the basic information.",
+ "dependencies": {
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.21",
+ "@ohos/hamock": "1.0.0"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/ohosTest.md b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/ohosTest.md
new file mode 100644
index 0000000000000000000000000000000000000000..280dbe74c4e1e68fdc32d7d2aab71374a791f532
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/ohosTest.md
@@ -0,0 +1,26 @@
+| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
+|:-------:|:------------:|:--------------:|:---------------------:|:----:|:----:|
+| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
+| 主页展示 | 设备正常运行 | | 展示 Building and Managing ArkGraphics 3D Scenes、Creating and Using ArkGraphics 3D Resources 和 Controlling and Managing ArkGraphics 3D Scene Animations 三种按钮 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Building and Managing ArkGraphics 3D Scenes 按钮 | 跳转 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Model Loading and Display 按钮 | 跳转至 Model 页面,显现头盔 | 是 | Pass |
+| Model 页面按钮点击 | 位于 Model 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing a Camera 按钮 | 跳转至 Camera 页面,显现几何体 | 是 | Pass |
+| Camera 页面按钮点击 | 位于 Camera 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing Light 按钮 | 跳转至 Light 页面 | 是 | Pass |
+| Light 页面按钮点击 | 位于 Light 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Creating and Using ArkGraphics 3D Resources 按钮 | 跳转至 Resource 页面,显现几何体 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a blank material 按钮 | 用空白材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a image material 按钮 | 用图像材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a shader material 按钮 | 用着色器材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Add to Environment 按钮 | 添加场景 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Controlling and Managing ArkGraphics 3D Scene Animations按钮 | 跳转至 Animation 页面 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Start 按钮 | 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Pause 按钮 | 暂停播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Stop 按钮 | 停止播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Finish 按钮 | 结束播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Restart 按钮 | 重新播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 seek to 30% progress 按钮 | 从 30% 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/screenshots/MetricsLog.png b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/screenshots/MetricsLog.png
new file mode 100644
index 0000000000000000000000000000000000000000..8125d20cf6fbe357f89772836b5633c0198936fb
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/screenshots/MetricsLog.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/screenshots/Text.jpg b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/screenshots/Text.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..7bc8f450707f973cb78c8abac7ca832fc7078f99
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/TextMetrics/screenshots/Text.jpg differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..d2ff20141ceed86d87c0ea5d99481973005bab2b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/.gitignore
@@ -0,0 +1,12 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
+/.appanalyzer
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/app.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..6254db89feb0cfd1b1bbd585e9bbb51f65f6ed1a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/app.json5
@@ -0,0 +1,10 @@
+{
+ "app": {
+ "bundleName": "com.samples.drawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:layered_image",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..1080233f01384411ec684b58955cb8808746fdd3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "MyApplication"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/AppScope/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/README.md b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..981344b62f74e664ecc1b6a240538e11708b8c4c
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/README.md
@@ -0,0 +1,131 @@
+# ArkGraphics 3D
+
+## 介绍
+
+本示例通过 ArkGraphics 3D 的接口,利用轻量级的 3D 引擎和渲染管线,实现了 3D 场景创建、3D 场景资源创建和 3D 动画创建。
+
+本示例主要展现了如何利用 ArkGraphics 3D 来实现 3D 图像的渲染,其中利用 Scene、Camera 和 Light 来创建基础的场景,使用 Material、Shader、Image 和Environment 来实现场景资源,采用 Animation 的各种方法来播放 3D 动画。
+
+## 效果预览
+
+| Index | Scene | Resource | Animation |
+| :-----------------------------------------------: | :-----------------------------------------------: | :--------------------------------------------------: | :---------------------------------------------------: |
+|
|
|
|
|
+
+**使用方法:**
+
+1. 在 Index 页面点击 ` BUilding and Managing ArkGraphics 3D Scenes` 按钮,跳转至 Scene 页面;
+ - 在 Scene 页面点击 `Model Loading and Display` 按钮,页面跳转至 Model 页面,显现 3D 头盔图像。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing a Camera` 按钮,页面跳转至 Camera 页面,显现几何体图像。通过调节 `X-axis`、`Y-axis` 和 `Z-axis` 滑动条,即可分别修改相机的 X 轴,Y 轴和 Z 轴。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Creating and Managing Light` 按钮,页面跳转至 Light 页面,显现几何体图像。通过调节 `Red`、`Green` 和 `Blue` 滑动条,即可分别调节光线的红、绿和蓝的颜色通道。点击 `Back` 按钮,返回至 Scene 页面;
+ - 在 Scene 页面点击 `Back` 按钮,返回至 `Index` 页面;
+2. 在 Index 页面点击 `Creating and using ArkGraphics 3D Resources` 按钮,跳转至 Resource 页面。点击 `Replace with a blank material` 按钮,几何体图像的材质被空白材质替换。点击 `Replace with a Shader material` 按钮,几何体图像的材质被着色器材质替换。点击 `Replace with a Image material`,几何体材质被图像材质替换。点击 `Add to Environment` 按钮,给几何体图像添加背景。点击 `Back` 按钮,返回至 Index 页面;
+3. 在 Index 页面点击 `Controlling and Managing ArkGraphics 3D Scene Animations` 按钮,跳转至 Animation 页面。点击 `start` 按钮,播放动画。点击 `pause` 按钮,中止动画。点击 `stop` 按钮,暂停动画。点击 `finish` 按钮,结束动画。点击 `restart` 按钮,重新播放动画。点击 `seek to 30% progress` 按钮,动画从 30% 进度开始播放。点击 `Back` 按钮,返回至 Index 页面;
+
+## 工程目录
+
+```
+|--entry/src/main
+│ |--ets // ets代码区
+│ │ |--entryability
+│ │ │ |--EntryAbility.ts // 程序入口类
+| | | |--EntryAbility.ets
+| | |--arkGraphic
+│ │ │ |--animation.ets // 动画
+| | | |--resource.ets // 场景资源
+| | | |--scene.ets // 场景搭建
+| | |--scene
+| | | |--camera.ets // 相机
+| | | |--init.ets // 模型加载
+| | | |--light.ets // 光线
+│ │ |--pages // 页面文件
+│ │ | |--Index.ets // 初始页面
+│ │ |--utils // 工具类
+| |--resources // 资源文件目录
+```
+
+## 具体实现
+
+1. 创建场景:一个 3D 场景通常由模型、相机和光源三个关键部分组成。其中先加载模型,再生成相机和光源。等 3D 图像加载完毕,可以使 Component3D 组件将渲染好的图像传递给用户。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------ | -------- |
+ | `Scene.load(): Promise` | 加载模型 |
+ | `SceneResourceFactory.createCamera(): Promise` | 创建相机 |
+ | `SceneResourceFactory.createLight(): Promise` | 创建光源 |
+
+ - | SceneOption 参数 | 描述 |
+ | -------------------- | ------------------------------------------------------------ |
+ | scene: Scene | 3D模型资源文件或场景对象,默认值为undefined。
**说明:目前仅支持GLTF格式资源。** |
+ | modelType: ModelType | 3D场景显示合成方式。
**说明:**
一般开发者可以使用默认值而无需关心此项设置。 |
+
+2. 创建场景资源:3D 场景中主要有以下常见资源:
+
+ - 材质(Material):材质是对场景中物体的光学物理性质的数学建模。在渲染计算的过程中,利用这些物理性质计算与光的相互作用,得到渲染的颜色。ArkGraphics 3D 提供的材质类型基于 PBR 渲染,支持用户参照 PBR 渲染材质类型创建材质资源,得到预期的渲染结果。
+
+ - 图片(Image): 图片本质上是上一个储存信息的二维内存块(buffer),用于储存 3D 渲染计算过程需要的相关信息,比如基础色、法线等等。ArkGraphics 3D 提供基于 PNG、JPG、KTX格式创建 Image 资源的能力,支持用户自定义需要的 Image 资源。
+
+ - 着色器(Shader): 着色器是 GPU 上可以执行的一段程序,可以控制 GPU 执行哪些并行计算操作。AGP 引擎提供的默认着色器实现了 PBR 渲染,开发者只需要指定对应的参数就可以完成不同的 PBR 渲染。ArkGraphics 3D 支持开发者创建自定义的着色器,开发者可以通过自定义着色器自定义渲染计算过程,完全控制渲染计算流程,比如控制某物体不受某光源的影响等。
+
+ - 环境(Environment): 环境是 3D 场景背景的一种描述,可以基于图片进行创建。通过将一张图片进行正方体或者球体的映射处理,将图片贴在正方体或者球体上,在 3D 场景中模拟真实的环境。ArkGraphics 3D 支持用户创建环境资源,定义 3D 场景的背景。
+
+ - | 接口名 | 描述 |
+ | ------------------------------------------------------------ | ---------- |
+ | `SceneResourceFactory.createMaterial(): Promise` | 创建材质 |
+ | `SceneResourceFactory.createImage(): Promise` | 创建图片 |
+ | `SceneResourceFactory.createShader(): Promise` | 创建着色器 |
+ | `SceneResourceFactory.createEnvironment(): Promise` | 创建环境 |
+
+ - 尤其需要注意:在 ArkGraphics 3D 中需要将材质(Material)给与子网格(SubMesh)才能成功替换材质。
+
+ - | SubMesh 属性 | 说明 |
+ | ---------------------- | ------------------------ |
+ | name: string | 名称,没有特殊格式要求。 |
+ | **material: Material** | 材质。 |
+ | aabb: Aabb | 轴对齐边界盒。 |
+
+3. 创建动画:动画是3D场景中重要的资源类型,用于控制场景中各种元素的运动。
+
+ - 调用 `start` 方法控制动画开启;
+
+ - 调用 `pause` 方法控制动画暂停;
+
+ - 调用 `stop` 方法控制动画停止,并将动画状态设置为开头;
+
+ - 调用`finish` 方法控制动画结束,并将动画状态设置为结尾;
+
+ - 调用 `restart` 方法控制动画从头开始;
+
+ - 调用 `seek` 方法控制动画设置到指定状态;
+
+ - `onStarted` 方法在动画开始时执行传入的回调;
+
+ - `onFinished` 方法在动画结束时执行传入的回调。
+
+## 相关权限
+
+不涉及。
+
+## 依赖
+
+不涉及。
+
+## 约束与限制
+
+1.本示例仅支持在标准系统上运行;
+
+2.本示例为 Stage 模型,已适配 API version 14 版本 SDK,SDK 版本号(API Version 14 5.0.2.57);
+
+3.本示例需要使用 DevEco Studio 版本号(5.0.5.306)及以上版本才可编译运行。
+
+## 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/graphic/Arkgraphics3D/ > .git/info/sparse-checkout
+git remote add origin https://gitee.com/openharmony/applications_app_samples.git
+git pull origin master
+```
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..a02339aff59ee239682304883818f4b74b77666a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/build-profile.json5
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ "compatibleSdkVersion": 14,
+ "runtimeOS": "OpenHarmony"
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ],
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/code-linter.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/code-linter.json5
new file mode 100644
index 0000000000000000000000000000000000000000..073990fa45394e1f8e85d85418ee60a8953f9b99
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/code-linter.json5
@@ -0,0 +1,32 @@
+{
+ "files": [
+ "**/*.ets"
+ ],
+ "ignore": [
+ "**/src/ohosTest/**/*",
+ "**/src/test/**/*",
+ "**/src/mock/**/*",
+ "**/node_modules/**/*",
+ "**/oh_modules/**/*",
+ "**/build/**/*",
+ "**/.preview/**/*"
+ ],
+ "ruleSet": [
+ "plugin:@performance/recommended",
+ "plugin:@typescript-eslint/recommended"
+ ],
+ "rules": {
+ "@security/no-unsafe-aes": "error",
+ "@security/no-unsafe-hash": "error",
+ "@security/no-unsafe-mac": "warn",
+ "@security/no-unsafe-dh": "error",
+ "@security/no-unsafe-dsa": "error",
+ "@security/no-unsafe-ecdsa": "error",
+ "@security/no-unsafe-rsa-encrypt": "error",
+ "@security/no-unsafe-rsa-sign": "error",
+ "@security/no-unsafe-rsa-key": "error",
+ "@security/no-unsafe-dsa-key": "error",
+ "@security/no-unsafe-dh-key": "error",
+ "@security/no-unsafe-3des": "error"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/.gitignore b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/build-profile.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..4d611879c7913fb0610c686e2399258ab3a6dad1
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/build-profile.json5
@@ -0,0 +1,28 @@
+{
+ "apiType": "stageMode",
+ "buildOption": {
+ },
+ "buildOptionSet": [
+ {
+ "name": "release",
+ "arkOptions": {
+ "obfuscation": {
+ "ruleOptions": {
+ "enable": false,
+ "files": [
+ "./obfuscation-rules.txt"
+ ]
+ }
+ }
+ }
+ },
+ ],
+ "targets": [
+ {
+ "name": "default"
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..c6edcd90486dd5a853cf7d34c8647f08414ca7a3
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { hapTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: hapTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/obfuscation-rules.txt b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..272efb6ca3f240859091bbbfc7c5802d52793b0b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/obfuscation-rules.txt
@@ -0,0 +1,23 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V5/source-obfuscation-V5
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
+
+-enable-property-obfuscation
+-enable-toplevel-obfuscation
+-enable-filename-obfuscation
+-enable-export-obfuscation
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..248c3b7541a589682a250f86a6d3ecf7414d2d6a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "name": "entry",
+ "version": "1.0.0",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "author": "",
+ "license": "",
+ "dependencies": {}
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/entryability/EntryAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/entryability/EntryAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..d4b3d4b237a39f39aead4506544f684231c571b5
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/entryability/EntryAbility.ets
@@ -0,0 +1,34 @@
+import { AbilityConstant, Configuration, UIAbility, Want } from '@kit.AbilityKit';
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { window } from '@kit.ArkUI';
+import { updateRenderNodeData } from '../pages/Index';
+
+const DOMAIN = 0x0000;
+
+export default class EntryAbility extends UIAbility {
+ preFontId = "";
+
+ onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
+ hilog.info(DOMAIN, 'testTag', 'onCreate');
+ }
+
+ onWindowStageCreate(windowStage: window.WindowStage): void {
+ hilog.info(DOMAIN, 'testTag', 'onWindowStageCreate');
+ windowStage.loadContent('pages/Index', (err) => {
+ if (err.code) {
+ hilog.error(DOMAIN, 'testTag', 'Failed to load content: %{public}s', JSON.stringify(err));
+ return;
+ }
+ hilog.info(DOMAIN, 'testTag', 'Content loaded successfully.');
+ });
+ }
+
+ onConfigurationUpdate(newConfig: Configuration): void {
+ let fontId = newConfig.fontId;
+ if (fontId && fontId !== this.preFontId) {
+ this.preFontId = fontId;
+ updateRenderNodeData();
+ hilog.info(DOMAIN, 'testTag', 'Font updated: ' + fontId);
+ }
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
new file mode 100644
index 0000000000000000000000000000000000000000..8e4de99282050bad799ac892eb85ac5449364a51
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/entrybackupability/EntryBackupAbility.ets
@@ -0,0 +1,16 @@
+import { hilog } from '@kit.PerformanceAnalysisKit';
+import { BackupExtensionAbility, BundleVersion } from '@kit.CoreFileKit';
+
+const DOMAIN = 0x0000;
+
+export default class EntryBackupAbility extends BackupExtensionAbility {
+ async onBackup() {
+ hilog.info(DOMAIN, 'testTag', 'onBackup ok');
+ await Promise.resolve();
+ }
+
+ async onRestore(bundleVersion: BundleVersion) {
+ hilog.info(DOMAIN, 'testTag', 'onRestore ok %{public}s', JSON.stringify(bundleVersion));
+ await Promise.resolve();
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/pages/Index.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/pages/Index.ets
new file mode 100644
index 0000000000000000000000000000000000000000..6d32bb17d02d799bb5a49af16a185831642c1c4f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/ets/pages/Index.ets
@@ -0,0 +1,129 @@
+// /pages/Index.ets
+import { NodeController, FrameNode, RenderNode, DrawContext} from '@kit.ArkUI'
+import { UIContext } from '@kit.ArkUI'
+import { text } from '@kit.ArkGraphics2D'
+
+class MyRenderNode extends RenderNode {
+ async draw(context: DrawContext) {
+ // 获取画布canvas对象
+ const canvas = context.canvas
+ // 设置文本样式
+ let myTextStyle: text.TextStyle = {
+ color: { alpha: 255, red: 255, green: 0, blue: 0 },
+ fontSize: 33
+ };
+ // 创建一个段落样式对象,以设置排版风格
+ let myParagraphStyle: text.ParagraphStyle = {
+ textStyle: myTextStyle,
+ align: 3,
+ wordBreak:text.WordBreak.NORMAL
+ };
+ // 获取字体管理器全局FontCollection实例
+ let fontCollection = text.FontCollection.getGlobalInstance() //获取Arkui全局FC
+ // 创建一个段落生成器
+ let paragraphGraphBuilder = new text.ParagraphBuilder(myParagraphStyle, fontCollection)
+ // 在段落生成器中设置文本样式
+ paragraphGraphBuilder.pushStyle(myTextStyle);
+ // 在段落生成器中设置文本内容
+ paragraphGraphBuilder.addText("Hello World. \nThis is the theme font.");
+ // 通过段落生成器生成段落
+ let paragraph = paragraphGraphBuilder.build();
+ // 布局
+ paragraph.layoutSync(2500);
+ paragraph.paint(canvas, 0, 400);
+ }
+}
+// 创建渲染节点数组
+const renderNodeMap: Array = new Array();
+// 导出渲染节点更新函数
+export function updateRenderNodeData() {
+ renderNodeMap.forEach((node) => {
+ // 主动触发节点重绘制
+ node.invalidate()
+ })
+}
+
+class MyNodeController extends NodeController {
+ private rootNode: FrameNode | null = null;
+ makeNode(uiContext: UIContext): FrameNode {
+ this.rootNode = new FrameNode(uiContext)
+ if (this.rootNode == null) {
+ return this.rootNode
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.frame = { x: 0, y: 0, width: 300, height: 50 }
+ renderNode.pivot = { x: 0, y: 0 }
+ }
+ return this.rootNode
+ }
+ addNode(node: RenderNode): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.appendChild(node)
+ // 将节点添加到渲染节点数组中
+ renderNodeMap.push(node)
+ }
+ }
+ clearNodes(): void {
+ if (this.rootNode == null) {
+ return
+ }
+ const renderNode = this.rootNode.getRenderNode()
+ if (renderNode != null) {
+ renderNode.clearChildren()
+ // 将节点从渲染节点数组中移除
+ renderNodeMap.pop()
+ }
+ }
+}
+
+// 创建一个TextRenderNode对象
+const textNode = new MyRenderNode();
+// 定义textNode的像素格式
+textNode.frame = {
+ x: 0,
+ y: 100,
+ width: 600,
+ height: 800
+}
+textNode.pivot = { x: 0.2, y: 0.8 }
+textNode.scale = { x: 1, y: 1 }
+
+@Entry
+@Component
+struct RenderTest {
+ private myNodeController: MyNodeController = new MyNodeController()
+ build() {
+ Column() {
+ Row() {
+ NodeContainer(this.myNodeController)
+ .height('100%')
+ }
+ .height('90%')
+ .backgroundColor(Color.White)
+ Row(){
+ Button("Draw Text")
+ .fontSize('16fp')
+ .fontWeight(500)
+ .margin({ bottom: 24, right: 12 })
+ .onClick(() => {
+ this.myNodeController.clearNodes()
+ this.myNodeController.addNode(textNode)
+ })
+ .width('50%')
+ .height(40)
+ .shadow(ShadowStyle.OUTER_DEFAULT_LG)
+ }
+ .width('100%')
+ .justifyContent(FlexAlign.Center)
+ .shadow(ShadowStyle.OUTER_DEFAULT_SM)
+ .alignItems(VerticalAlign.Bottom)
+ .layoutWeight(1)
+ }
+ }
+}
+
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..2cd3a6c601073f86f4789ab9db7529f84f705f3f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/module.json5
@@ -0,0 +1,51 @@
+{
+ "module": {
+ "name": "entry",
+ "type": "entry",
+ "description": "$string:module_desc",
+ "mainElement": "EntryAbility",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false,
+ "pages": "$profile:main_pages",
+ "abilities": [
+ {
+ "name": "EntryAbility",
+ "srcEntry": "./ets/entryability/EntryAbility.ets",
+ "description": "$string:EntryAbility_desc",
+ "icon": "$media:layered_image",
+ "label": "$string:EntryAbility_label",
+ "startWindowIcon": "$media:startIcon",
+ "startWindowBackground": "$color:start_window_background",
+ "exported": true,
+ "skills": [
+ {
+ "entities": [
+ "entity.system.home"
+ ],
+ "actions": [
+ "action.system.home"
+ ]
+ }
+ ]
+ }
+ ],
+ "extensionAbilities": [
+ {
+ "name": "EntryBackupAbility",
+ "srcEntry": "./ets/entrybackupability/EntryBackupAbility.ets",
+ "type": "backup",
+ "exported": false,
+ "metadata": [
+ {
+ "name": "ohos.extension.backup",
+ "resource": "$profile:backup_config"
+ }
+ ]
+ }
+ ]
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..3c712962da3c2751c2b9ddb53559afcbd2b54a02
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#FFFFFF"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/float.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/float.json
new file mode 100644
index 0000000000000000000000000000000000000000..33ea22304f9b1485b5f22d811023701b5d4e35b6
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/float.json
@@ -0,0 +1,8 @@
+{
+ "float": [
+ {
+ "name": "page_text_font_size",
+ "value": "50fp"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/string.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..f94595515a99e0c828807e243494f57f09251930
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/element/string.json
@@ -0,0 +1,16 @@
+{
+ "string": [
+ {
+ "name": "module_desc",
+ "value": "module description"
+ },
+ {
+ "name": "EntryAbility_desc",
+ "value": "description"
+ },
+ {
+ "name": "EntryAbility_label",
+ "value": "label"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/background.png b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/background.png
new file mode 100644
index 0000000000000000000000000000000000000000..923f2b3f27e915d6871871deea0420eb45ce102f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/background.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/foreground.png b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/foreground.png
new file mode 100644
index 0000000000000000000000000000000000000000..97014d3e10e5ff511409c378cd4255713aecd85f
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/foreground.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/layered_image.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/layered_image.json
new file mode 100644
index 0000000000000000000000000000000000000000..fb49920440fb4d246c82f9ada275e26123a2136a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/layered_image.json
@@ -0,0 +1,7 @@
+{
+ "layered-image":
+ {
+ "background" : "$media:background",
+ "foreground" : "$media:foreground"
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/startIcon.png b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/startIcon.png
new file mode 100644
index 0000000000000000000000000000000000000000..205ad8b5a8a42e8762fbe4899b8e5e31ce822b8b
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/media/startIcon.png differ
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/profile/backup_config.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/profile/backup_config.json
new file mode 100644
index 0000000000000000000000000000000000000000..78f40ae7c494d71e2482278f359ec790ca73471a
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/profile/backup_config.json
@@ -0,0 +1,3 @@
+{
+ "allowToBackupRestore": true
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/profile/main_pages.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/profile/main_pages.json
new file mode 100644
index 0000000000000000000000000000000000000000..1898d94f58d6128ab712be2c68acc7c98e9ab9ce
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/base/profile/main_pages.json
@@ -0,0 +1,5 @@
+{
+ "src": [
+ "pages/Index"
+ ]
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/dark/element/color.json b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/dark/element/color.json
new file mode 100644
index 0000000000000000000000000000000000000000..79b11c2747aec33e710fd3a7b2b3c94dd9965499
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/main/resources/dark/element/color.json
@@ -0,0 +1,8 @@
+{
+ "color": [
+ {
+ "name": "start_window_background",
+ "value": "#000000"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/mock/mock-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/mock/mock-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7a73a41bfdf76d6f793007240d80983a52f15f97
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/mock/mock-config.json5
@@ -0,0 +1,2 @@
+{
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/ets/test/Ability.test.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/ets/test/Ability.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..e27b3c7cd76aa87542bc7e2aeeaa090f0ba0fcec
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/ets/test/Ability.test.ets
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 2025 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import AbilityDelegatorRegistry from '@ohos.app.ability.abilityDelegatorRegistry';
+import { describe, it, expect } from '@ohos/hypium';
+import { Driver, ON } from '@ohos.UiTest';
+
+const TAG = '[Sample_DrawingAPI]';
+
+export default function abilityTest() {
+
+ describe('ActsAbilityTest', () => {
+ /**
+ * 打开应用
+ */
+ it('StartAbility_001', 0, async (done: Function) => {
+ console.info(TAG, 'StartAbility_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `StartAbility_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw Text'));
+ done();
+ console.info(TAG, 'StartAbility_001 end');
+ })
+
+ /**
+ * 点击按钮,绘制简单排版文本
+ */
+ it('DrawSimpleTextTEST_001', 2, async () => {
+ console.info(TAG, 'DrawSimpleTextTEST_001 begin');
+ let driver = Driver.create();
+ let abilityDelegator = AbilityDelegatorRegistry.getAbilityDelegator();
+ try {
+ await abilityDelegator.startAbility({
+ bundleName: 'com.samples.drawing',
+ abilityName: 'EntryAbility'
+ });
+ } catch (exception) {
+ console.info(TAG, `DrawSimpleTextTEST_001 exception = ${JSON.stringify(exception)}`);
+ expect().assertFail();
+ }
+ await driver.delayMs(1000);
+ await driver.assertComponentExist(ON.text('Draw Text'));
+ let drawTextBtn = await driver.findComponent(ON.text('Draw Text'));
+ // 点击'Draw complex text'按钮
+ await drawTextBtn.click();
+ await driver.delayMs(1000);
+ console.info(TAG, 'DrawSimpleTextTEST_001 end');
+ })
+
+ })
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/ets/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/ets/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..794c7dc4ed66bd98fa3865e07922906e2fcef545
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/ets/test/List.test.ets
@@ -0,0 +1,5 @@
+import abilityTest from './Ability.test';
+
+export default function testsuite() {
+ abilityTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/module.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/module.json5
new file mode 100644
index 0000000000000000000000000000000000000000..69026872775eebd0844900b225c411959ae5608b
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/ohosTest/module.json5
@@ -0,0 +1,12 @@
+{
+ "module": {
+ "name": "entry_test",
+ "type": "feature",
+ "deviceTypes": [
+ "default",
+ "tablet"
+ ],
+ "deliveryWithInstall": true,
+ "installationFree": false
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/test/List.test.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/test/List.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..bb5b5c3731e283dd507c847560ee59bde477bbc7
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/test/List.test.ets
@@ -0,0 +1,5 @@
+import localUnitTest from './LocalUnit.test';
+
+export default function testsuite() {
+ localUnitTest();
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/test/LocalUnit.test.ets b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/test/LocalUnit.test.ets
new file mode 100644
index 0000000000000000000000000000000000000000..165fc1615ee8618b4cb6a622f144a9a707eee99f
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/entry/src/test/LocalUnit.test.ets
@@ -0,0 +1,33 @@
+import { describe, beforeAll, beforeEach, afterEach, afterAll, it, expect } from '@ohos/hypium';
+
+export default function localUnitTest() {
+ describe('localUnitTest', () => {
+ // Defines a test suite. Two parameters are supported: test suite name and test suite function.
+ beforeAll(() => {
+ // Presets an action, which is performed only once before all test cases of the test suite start.
+ // This API supports only one parameter: preset action function.
+ });
+ beforeEach(() => {
+ // Presets an action, which is performed before each unit test case starts.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: preset action function.
+ });
+ afterEach(() => {
+ // Presets a clear action, which is performed after each unit test case ends.
+ // The number of execution times is the same as the number of test cases defined by **it**.
+ // This API supports only one parameter: clear action function.
+ });
+ afterAll(() => {
+ // Presets a clear action, which is performed after all test cases of the test suite end.
+ // This API supports only one parameter: clear action function.
+ });
+ it('assertContain', 0, () => {
+ // Defines a test case. This API supports three parameters: test case name, filter parameter, and test case function.
+ let a = 'abc';
+ let b = 'b';
+ // Defines a variety of assertion methods, which are used to declare expected boolean conditions.
+ expect(a).assertContain(b);
+ expect(a).assertEqual(a);
+ });
+ });
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/hvigor/hvigor-config.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/hvigor/hvigor-config.json5
new file mode 100644
index 0000000000000000000000000000000000000000..fe83c3e838abfb3629eed84f6c7092f306d818f9
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/hvigor/hvigor-config.json5
@@ -0,0 +1,22 @@
+{
+ "modelVersion": "5.0.2",
+ "dependencies": {
+ },
+ "execution": {
+ // "analyze": "normal", /* Define the build analyze mode. Value: [ "normal" | "advanced" | false ]. Default: "normal" */
+ // "daemon": true, /* Enable daemon compilation. Value: [ true | false ]. Default: true */
+ // "incremental": true, /* Enable incremental compilation. Value: [ true | false ]. Default: true */
+ // "parallel": true, /* Enable parallel compilation. Value: [ true | false ]. Default: true */
+ // "typeCheck": false, /* Enable typeCheck. Value: [ true | false ]. Default: false */
+ },
+ "logging": {
+ // "level": "info" /* Define the log level. Value: [ "debug" | "info" | "warn" | "error" ]. Default: "info" */
+ },
+ "debugging": {
+ // "stacktrace": false /* Disable stacktrace compilation. Value: [ true | false ]. Default: false */
+ },
+ "nodeOptions": {
+ // "maxOldSpaceSize": 8192 /* Enable nodeOptions maxOldSpaceSize compilation. Unit M. Used for the daemon process. Default: 8192*/
+ // "exposeGC": true /* Enable to trigger garbage collection explicitly. Default: true*/
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/hvigorfile.ts b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..f3cb9f1a87a81687554a76283af8df27d8bda775
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/hvigorfile.ts
@@ -0,0 +1,6 @@
+import { appTasks } from '@ohos/hvigor-ohos-plugin';
+
+export default {
+ system: appTasks, /* Built-in plugin of Hvigor. It cannot be modified. */
+ plugins:[] /* Custom plugin to extend the functionality of Hvigor. */
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/oh-package-lock.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..7fcf818273347b97063c0c0a151bb14770ca1c79
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/oh-package-lock.json5
@@ -0,0 +1,27 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
+ "@ohos/hypium@1.0.21": "@ohos/hypium@1.0.21"
+ },
+ "packages": {
+ "@ohos/hamock@1.0.0": {
+ "name": "@ohos/hamock",
+ "version": "1.0.0",
+ "integrity": "sha512-K6lDPYc6VkKe6ZBNQa9aoG+ZZMiwqfcR/7yAVFSUGIuOAhPvCJAo9+t1fZnpe0dBRBPxj2bxPPbKh69VuyAtDg==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hamock/-/hamock-1.0.0.har",
+ "registryType": "ohpm"
+ },
+ "@ohos/hypium@1.0.21": {
+ "name": "@ohos/hypium",
+ "version": "1.0.21",
+ "integrity": "sha512-iyKGMXxE+9PpCkqEwu0VykN/7hNpb+QOeIuHwkmZnxOpI+dFZt6yhPB7k89EgV1MiSK/ieV/hMjr5Z2mWwRfMQ==",
+ "resolved": "https://ohpm.openharmony.cn/ohpm/@ohos/hypium/-/hypium-1.0.21.har",
+ "registryType": "ohpm"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/oh-package.json5 b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..9c36c086ae807ea710acd9e480cb6cc1d18bd011
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/oh-package.json5
@@ -0,0 +1,10 @@
+{
+ "modelVersion": "5.0.2",
+ "description": "Please describe the basic information.",
+ "dependencies": {
+ },
+ "devDependencies": {
+ "@ohos/hypium": "1.0.21",
+ "@ohos/hamock": "1.0.0"
+ }
+}
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/ohosTest.md b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/ohosTest.md
new file mode 100644
index 0000000000000000000000000000000000000000..280dbe74c4e1e68fdc32d7d2aab71374a791f532
--- /dev/null
+++ b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/ohosTest.md
@@ -0,0 +1,26 @@
+| 测试功能 | 预置条件 | 输入 | 预期输出 | 是否自动 | 测试结果 |
+|:-------:|:------------:|:--------------:|:---------------------:|:----:|:----:|
+| 拉起应用 | 设备正常运行 | | 成功拉起应用 | 是 | Pass |
+| 主页展示 | 设备正常运行 | | 展示 Building and Managing ArkGraphics 3D Scenes、Creating and Using ArkGraphics 3D Resources 和 Controlling and Managing ArkGraphics 3D Scene Animations 三种按钮 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Building and Managing ArkGraphics 3D Scenes 按钮 | 跳转 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Model Loading and Display 按钮 | 跳转至 Model 页面,显现头盔 | 是 | Pass |
+| Model 页面按钮点击 | 位于 Model 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing a Camera 按钮 | 跳转至 Camera 页面,显现几何体 | 是 | Pass |
+| Camera 页面按钮点击 | 位于 Camera 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Creating and Managing Light 按钮 | 跳转至 Light 页面 | 是 | Pass |
+| Light 页面按钮点击 | 位于 Light 页面 | 点击 Back 按钮 | 返回 Scene 页面 | 是 | Pass |
+| Scene 页面 按钮点击 | 位于 Scene 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Creating and Using ArkGraphics 3D Resources 按钮 | 跳转至 Resource 页面,显现几何体 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a blank material 按钮 | 用空白材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a image material 按钮 | 用图像材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Replace with a shader material 按钮 | 用着色器材质替换原有的材质 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Add to Environment 按钮 | 添加场景 | 是 | Pass |
+| Resource 页面按钮点击 | 位于 Resource 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
+| 主页按钮点击 | 位于主页 | 点击 Controlling and Managing ArkGraphics 3D Scene Animations按钮 | 跳转至 Animation 页面 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Start 按钮 | 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Pause 按钮 | 暂停播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Stop 按钮 | 停止播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Finish 按钮 | 结束播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Restart 按钮 | 重新播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 seek to 30% progress 按钮 | 从 30% 开始播放动画 | 是 | Pass |
+| Animation 页面按钮点击 | 位于 Animation 页面 | 点击 Back 按钮 | 返回主页 | 是 | Pass |
\ No newline at end of file
diff --git a/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/screenshots/IMG_1501837742_002.jpg b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/screenshots/IMG_1501837742_002.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f4ddf0c2f93532bdea2c98dd3a9aa9cca23fafaa
Binary files /dev/null and b/code/DocsSample/graphic/ArkGraphics2D/ThemeFont/screenshots/IMG_1501837742_002.jpg differ
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/.gitignore b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..fbabf771011fe78f9919db0b1195ab6cadffc2b0
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/.gitignore
@@ -0,0 +1,11 @@
+/node_modules
+/oh_modules
+/local.properties
+/.idea
+**/build
+/.hvigor
+.cxx
+/.clangd
+/.clang-format
+/.clang-tidy
+**/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/app.json5 b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/app.json5
new file mode 100644
index 0000000000000000000000000000000000000000..5026dc6a1265993c9fd9fa1542f8d1b4275bec9e
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/app.json5
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "app": {
+ "bundleName": "com.samples.nativedrawing",
+ "vendor": "example",
+ "versionCode": 1000000,
+ "versionName": "1.0.0",
+ "icon": "$media:app_icon",
+ "label": "$string:app_name"
+ }
+}
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/resources/base/element/string.json b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/resources/base/element/string.json
new file mode 100644
index 0000000000000000000000000000000000000000..871f32bfd43ba98e764bbfdb11082634c3106e64
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/resources/base/element/string.json
@@ -0,0 +1,8 @@
+{
+ "string": [
+ {
+ "name": "app_name",
+ "value": "NativeDrawing"
+ }
+ ]
+}
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/resources/base/media/app_icon.png b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/resources/base/media/app_icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ce307a8827bd75456441ceb57d530e4c8d45d36c
Binary files /dev/null and b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/AppScope/resources/base/media/app_icon.png differ
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/README.md b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/README.md
new file mode 100644
index 0000000000000000000000000000000000000000..c899a9605f95d5df65a5764855935c8ddcdfdbf1
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/README.md
@@ -0,0 +1,76 @@
+# 使用Drawing实现图形绘制与显示(C++)
+
+## 介绍
+
+本工程主要实现了对以下指南文档中 https://docs.openharmony.cn/pages/v5.0/zh-cn/application-dev/graphics/drawing-guidelines.md 示例代码片段的工程化,主要目标是实现指南中示例代码需要与sample工程文件同源。
+
+## 效果预览
+
+|  |  |
+|--------------------------| ------------------------ |
+
+使用说明
+
+1. 该工程可以选择在模拟器和开发板上运行。
+2. 点击构建,即可在生成的应用中点击对应的按钮进行图案的绘制。
+3. 进入”DocsSample/Drawing/NDKDrawing/entry/src/ohosTest/ets/test/DrawingAbility.test.ets“文件,可以对本项目进行UI的自动化测试。
+
+## 工程目录
+
+```
+NDKDrawing
+├──entry/src/main
+│ ├──cpp // C++代码区
+│ │ ├──CMakeLists.txt // CMake配置文件
+│ │ ├──hello.cpp // Napi模块注册
+│ │ ├──common
+│ │ │ └──log_common.h // 日志封装定义文件
+│ │ ├──plugin // 生命周期管理模块
+│ │ │ ├──plugin_manager.cpp
+│ │ │ └──plugin_manager.h
+│ │ ├──samples // samples渲染模块
+│ │ │ ├──sample_bitmap.cpp
+│ │ │ └──sample_bitmap.h
+│ ├──ets // ets代码区
+│ │ ├──entryability
+│ │ │ ├──EntryAbility.ts // 程序入口类
+| | | └──EntryAbility.ets
+| | ├──interface
+│ │ │ └──XComponentContext.ts // XComponentContext
+│ │ └──pages // 页面文件
+│ │ └──Index.ets // 主界面
+| ├──resources // 资源文件目录
+```
+
+## 具体实现
+
+1. 利用Native XComponent来获取NativeWindow实例、获取布局/事件信息、注册事件回调并通过Drawing API实现在页面上绘制形状。功能主要包括点击按钮绘制一个五角星和“Hello World Drawing”文字。
+2. 通过在IDE中创建Native c++ 工程,在c++代码中定义对外接口为drawPattern和drawText,在js侧调用该接口可在页面上绘制出一个五角星和“Hello World Drawing”文字。
+3. 在XComponent的OnSurfaceCreated回调中获取NativeWindow实例并初始化NativeWindow环境。调用OH_NativeXComponent_GetXComponentSize接口获取XComponent的宽高,并以此为输入调用Drawing相关的绘制接口在NativeWindow上绘制出一个五角星和文字。
+
+## 相关权限
+
+无。
+
+## 依赖
+
+不涉及。
+
+## 约束和限制
+
+1. 本示例支持标准系统上运行,支持设备:RK3568。
+2. 本示例支持API14版本SDK,版本号:5.0.2.57。
+3. 本示例已支持使DevEco Studio 5.0.1 Release (构建版本:5.0.5.306,构建 2024年12月6日)编译运行。
+
+## 下载
+
+如需单独下载本工程,执行如下命令:
+
+```
+git init
+git config core.sparsecheckout true
+echo code/DocsSample/Drawing/NDKDrawing/ > .git/info/sparse-checkout
+git remote add origin https://gitee.com/openharmony/applications_app_samples.git
+git pull origin master
+```
+
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/build-profile.json5 b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..b2f9f27de719c4f565fb167c4194513b888fbd0e
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/build-profile.json5
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2024 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+{
+ "app": {
+ "products": [
+ {
+ "name": "default",
+ "signingConfig": "default",
+ "compileSdkVersion": 14,
+ //指定OpenHarmony应用/服务编译时的版本
+ "compatibleSdkVersion": 14,
+ //指定OpenHarmony应用/服务兼容的最低版本。
+ "targetSdkVersion": 14,
+ //指定OpenHarmony应用/服务目标版本。若没有设置,默认为compatibleSdkVersion
+ "runtimeOS": "OpenHarmony",
+ //指定为OpenHarmony
+ "buildOption": {
+ "externalNativeOptions": {
+ //指定ABI配置
+ "abiFilters": [
+ "arm64-v8a",
+ "x86_64",
+ "armeabi-v7a"
+ ]
+ },
+ "strictMode": {
+ "caseSensitiveCheck": true,
+ "useNormalizedOHMUrl": true
+ }
+ }
+ }
+ ],
+ "buildModeSet": [
+ {
+ "name": "debug"
+ },
+ {
+ "name": "release"
+ }
+ ],
+ },
+ "modules": [
+ {
+ "name": "entry",
+ "srcPath": "./entry",
+ "targets": [
+ {
+ "name": "default",
+ "applyToProducts": [
+ "default"
+ ]
+ }
+ ]
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/.gitignore b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..e2713a2779c5a3e0eb879efe6115455592caeea5
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/.gitignore
@@ -0,0 +1,6 @@
+/node_modules
+/oh_modules
+/.preview
+/build
+/.cxx
+/.test
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/build-profile.json5 b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/build-profile.json5
new file mode 100644
index 0000000000000000000000000000000000000000..006bebd3e4ea631a973bcd0f0c9cc6b928926e38
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/build-profile.json5
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "apiType": 'stageMode',
+ "buildOption": {
+ "externalNativeOptions": {
+ "path": "./src/main/cpp/CMakeLists.txt",
+ "arguments": "",
+ "cppFlags": "",
+ "abiFilters": ["arm64-v8a", "armeabi-v7a", "x86_64"],
+ }
+ },
+ "targets": [
+ {
+ "name": "default",
+ },
+ {
+ "name": "ohosTest",
+ }
+ ]
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/hvigorfile.ts b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/hvigorfile.ts
new file mode 100644
index 0000000000000000000000000000000000000000..80e4ec5b81689f238c34614b167a0b9e9c83e8d9
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/hvigorfile.ts
@@ -0,0 +1,2 @@
+// Script for compiling build behavior. It is built in the build plug-in and cannot be modified currently.
+export { hapTasks } from '@ohos/hvigor-ohos-plugin';
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/obfuscation-rules.txt b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/obfuscation-rules.txt
new file mode 100644
index 0000000000000000000000000000000000000000..985b2aeb7658286b17bd26eab8f217c3fe75ea8b
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/obfuscation-rules.txt
@@ -0,0 +1,18 @@
+# Define project specific obfuscation rules here.
+# You can include the obfuscation configuration files in the current module's build-profile.json5.
+#
+# For more details, see
+# https://gitee.com/openharmony/arkcompiler_ets_frontend/blob/master/arkguard/README.md
+
+# Obfuscation options:
+# -disable-obfuscation: disable all obfuscations
+# -enable-property-obfuscation: obfuscate the property names
+# -enable-toplevel-obfuscation: obfuscate the names in the global scope
+# -compact: remove unnecessary blank spaces and all line feeds
+# -remove-log: remove all console.* statements
+# -print-namecache: print the name cache that contains the mapping from the old names to new names
+# -apply-namecache: reuse the given cache file
+
+# Keep options:
+# -keep-property-name: specifies property names that you want to keep
+# -keep-global-name: specifies names that you want to keep in the global scope
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/oh-package-lock.json5 b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/oh-package-lock.json5
new file mode 100644
index 0000000000000000000000000000000000000000..36c64d7416d67905820cf70e5e4bc4840715aa29
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/oh-package-lock.json5
@@ -0,0 +1,18 @@
+{
+ "meta": {
+ "stableOrder": true
+ },
+ "lockfileVersion": 3,
+ "ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
+ "specifiers": {
+ "libentry.so@src/main/cpp/types/libentry": "libentry.so@src/main/cpp/types/libentry"
+ },
+ "packages": {
+ "libentry.so@src/main/cpp/types/libentry": {
+ "name": "libentry.so",
+ "version": "0.0.0",
+ "resolved": "src/main/cpp/types/libentry",
+ "registryType": "local"
+ }
+ }
+}
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/oh-package.json5 b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/oh-package.json5
new file mode 100644
index 0000000000000000000000000000000000000000..80991c480e269b66302b8826914bc8622d3af673
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/oh-package.json5
@@ -0,0 +1,27 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+{
+ "license": "",
+ "devDependencies": {},
+ "author": "",
+ "name": "entry",
+ "description": "Please describe the basic information.",
+ "main": "",
+ "version": "1.0.0",
+ "dependencies": {
+ "libentry.so": "file:./src/main/cpp/types/libentry"
+ }
+}
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/CMakeLists.txt b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..dab4996d9043fc9d2fad8a0a69cf182194e1c865
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,26 @@
+# the minimum version of CMake.
+cmake_minimum_required(VERSION 3.4.1)
+project(drawing_test)
+
+set(NATIVERENDER_ROOT_PATH ${CMAKE_CURRENT_SOURCE_DIR})
+
+include_directories(${NATIVERENDER_ROOT_PATH}
+ ${NATIVERENDER_ROOT_PATH}/include)
+
+add_library(entry SHARED
+ hello.cpp
+ samples/sample_bitmap.cpp
+ plugin/plugin_manager.cpp
+)
+find_library(
+ # Sets the name of the path variable.
+ hilog-lib
+ # Specifies the name of the NDK library that
+ # you want CMake to locate.
+ hilog_ndk.z
+)
+target_link_libraries(entry PUBLIC ${hilog-lib})
+target_link_libraries(entry PUBLIC libace_napi.z.so)
+target_link_libraries(entry PUBLIC libace_ndk.z.so)
+target_link_libraries(entry PUBLIC libnative_window.so)
+target_link_libraries(entry PUBLIC libnative_drawing.so)
\ No newline at end of file
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/common/log_common.h b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/common/log_common.h
new file mode 100644
index 0000000000000000000000000000000000000000..5f3b18ed767d562ca226c2c76f269464e2e86f0f
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/common/log_common.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef LOG_COMMON_H
+#define LOG_COMMON_H
+#include
+#define LOG_PRINT_DOMAIN 0xFF00
+#define APP_LOG_DOMAIN 0x0001
+constexpr const char *APP_LOG_TAG = "DrawingSample";
+#define DRAWING_LOGI(...) ((void)OH_LOG_Print(LOG_APP, LOG_INFO, LOG_DOMAIN, APP_LOG_TAG, __VA_ARGS__))
+#define DRAWING_LOGD(...) ((void)OH_LOG_Print(LOG_APP, LOG_DEBUG, LOG_DOMAIN, APP_LOG_TAG, __VA_ARGS__))
+#define DRAWING_LOGW(...) ((void)OH_LOG_Print(LOG_APP, LOG_WARN, LOG_DOMAIN, APP_LOG_TAG, __VA_ARGS__))
+#define DRAWING_LOGE(...) ((void)OH_LOG_Print(LOG_APP, LOG_ERROR, LOG_DOMAIN, APP_LOG_TAG, __VA_ARGS__))
+
+#endif // LOG_COMMON_H
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/hello.cpp b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/hello.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..e23ff720032241a9c7cb02aef0ef1acc23a6ad8b
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/hello.cpp
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include "napi/native_api.h"
+#include "common/log_common.h"
+#include "plugin/plugin_manager.h"
+
+EXTERN_C_START
+static napi_value Init(napi_env env, napi_value exports)
+{
+ DRAWING_LOGI("napi init");
+ PluginManager::GetInstance()->Export(env, exports);
+ return exports;
+}
+EXTERN_C_END
+
+static napi_module demoModule = {
+ .nm_version = 1,
+ .nm_flags = 0,
+ .nm_filename = nullptr,
+ .nm_register_func = Init,
+ .nm_modname = "entry",
+ .nm_priv = ((void *)0),
+ .reserved = {0},
+};
+
+extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
+{
+ napi_module_register(&demoModule);
+}
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/plugin/plugin_manager.cpp b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/plugin/plugin_manager.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..046f8fd7d35dab09b032245654acd29ac353747e
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/plugin/plugin_manager.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include "common/log_common.h"
+#include "plugin_manager.h"
+
+PluginManager *PluginManager::GetInstance()
+{
+ static PluginManager pluginManager;
+ return &pluginManager;
+}
+
+PluginManager::~PluginManager()
+{
+ DRAWING_LOGI("~PluginManager");
+ for (auto iter = nativeXComponentMap_.begin(); iter != nativeXComponentMap_.end(); ++iter) {
+ if (iter->second != nullptr) {
+ delete iter->second;
+ iter->second = nullptr;
+ }
+ }
+ nativeXComponentMap_.clear();
+
+ for (auto iter = pluginRenderMap_.begin(); iter != pluginRenderMap_.end(); ++iter) {
+ if (iter->second != nullptr) {
+ delete iter->second;
+ iter->second = nullptr;
+ }
+ }
+ pluginRenderMap_.clear();
+}
+
+void PluginManager::Export(napi_env env, napi_value exports)
+{
+ if ((env == nullptr) || (exports == nullptr)) {
+ DRAWING_LOGE("Export: env or exports is null");
+ return;
+ }
+
+ napi_value exportInstance = nullptr;
+ if (napi_get_named_property(env, exports, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
+ DRAWING_LOGE("Export: napi_get_named_property fail");
+ return;
+ }
+
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) {
+ DRAWING_LOGE("Export: napi_unwrap fail");
+ return;
+ }
+
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("Export: OH_NativeXComponent_GetXComponentId fail");
+ return;
+ }
+
+ std::string id(idStr);
+ auto context = PluginManager::GetInstance();
+ if ((context != nullptr) && (nativeXComponent != nullptr)) {
+ context->SetNativeXComponent(id, nativeXComponent);
+ auto render = context->GetRender(id);
+ if (render != nullptr) {
+ render->RegisterCallback(nativeXComponent);
+ render->Export(env, exports);
+ } else {
+ DRAWING_LOGE("render is nullptr");
+ }
+ }
+}
+
+void PluginManager::SetNativeXComponent(std::string &id, OH_NativeXComponent *nativeXComponent)
+{
+ DRAWING_LOGI("set native xComponent, ID = %{public}s.", id.c_str());
+ if (nativeXComponent == nullptr) {
+ DRAWING_LOGE("xcomponent null");
+ return;
+ }
+
+ if (nativeXComponentMap_.find(id) == nativeXComponentMap_.end()) {
+ nativeXComponentMap_[id] = nativeXComponent;
+ return;
+ }
+
+ if (nativeXComponentMap_[id] != nativeXComponent) {
+ OH_NativeXComponent *tmp = nativeXComponentMap_[id];
+ delete tmp;
+ tmp = nullptr;
+ nativeXComponentMap_[id] = nativeXComponent;
+ }
+}
+
+SampleBitMap *PluginManager::GetRender(std::string &id)
+{
+ if (pluginRenderMap_.find(id) == pluginRenderMap_.end()) {
+ SampleBitMap *instance = SampleBitMap::GetInstance(id);
+ pluginRenderMap_[id] = instance;
+ return instance;
+ }
+ return pluginRenderMap_[id];
+}
+
+void PluginManager::ReleaseRender(std::string &id)
+{
+ auto map = pluginRenderMap_.find(id);
+ if (map == pluginRenderMap_.end()) {
+ return;
+ }
+ pluginRenderMap_.erase(map);
+}
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/plugin/plugin_manager.h b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/plugin/plugin_manager.h
new file mode 100644
index 0000000000000000000000000000000000000000..396e34e4a66f1946d22d15c137564ec951d5a470
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/plugin/plugin_manager.h
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef PLUGIN_MANAGER_H
+#define PLUGIN_MANAGER_H
+
+#include
+#include
+#include
+#include
+#include
+#include "samples/sample_bitmap.h"
+
+class PluginManager {
+public:
+ ~PluginManager();
+
+ static PluginManager *GetInstance();
+
+ void SetNativeXComponent(std::string &id, OH_NativeXComponent *nativeXComponent);
+ SampleBitMap *GetRender(std::string &id);
+ void ReleaseRender(std::string &id);
+ void Export(napi_env env, napi_value exports);
+private:
+
+ std::unordered_map nativeXComponentMap_;
+ std::unordered_map pluginRenderMap_;
+};
+#endif // PLUGIN_MANAGER_H
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/samples/sample_bitmap.cpp b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/samples/sample_bitmap.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..2f39510559c670cb556327bf2b9c8a3856cb6bc4
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/samples/sample_bitmap.cpp
@@ -0,0 +1,733 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "common/log_common.h"
+#include "sample_bitmap.h"
+#include "plugin/plugin_manager.h"
+
+static void OnSurfaceCreatedCB(OH_NativeXComponent *component, void *window)
+{
+ DRAWING_LOGI("OnSurfaceCreatedCB");
+ if ((component == nullptr) || (window == nullptr)) {
+ DRAWING_LOGE("OnSurfaceCreatedCB: component or window is null");
+ return;
+ }
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("OnSurfaceCreatedCB: Unable to get XComponent id");
+ return;
+ }
+ std::string id(idStr);
+ auto render = SampleBitMap::GetInstance(id);
+ OHNativeWindow *nativeWindow = static_cast(window);
+ render->SetNativeWindow(nativeWindow);
+
+ uint64_t width;
+ uint64_t height;
+ int32_t xSize = OH_NativeXComponent_GetXComponentSize(component, window, &width, &height);
+ if ((xSize == OH_NATIVEXCOMPONENT_RESULT_SUCCESS) && (render != nullptr)) {
+ render->SetHeight(height);
+ render->SetWidth(width);
+ DRAWING_LOGI("xComponent width = %{public}llu, height = %{public}llu", width, height);
+ }
+}
+
+static void OnSurfaceDestroyedCB(OH_NativeXComponent *component, void *window)
+{
+ DRAWING_LOGI("OnSurfaceDestroyedCB");
+ if ((component == nullptr) || (window == nullptr)) {
+ DRAWING_LOGE("OnSurfaceDestroyedCB: component or window is null");
+ return;
+ }
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(component, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("OnSurfaceDestroyedCB: Unable to get XComponent id");
+ return;
+ }
+ std::string id(idStr);
+ SampleBitMap::Release(id);
+}
+
+static std::unordered_map g_instance;
+
+void SampleBitMap::SetWidth(uint64_t width)
+{
+ width_ = width;
+}
+
+void SampleBitMap::SetHeight(uint64_t height)
+{
+ height_ = height;
+}
+
+void SampleBitMap::SetNativeWindow(OHNativeWindow *nativeWindow)
+{
+ nativeWindow_ = nativeWindow;
+}
+
+void SampleBitMap::Prepare()
+{
+ if (nativeWindow_ == nullptr) {
+ DRAWING_LOGE("nativeWindow_ is nullptr");
+ return;
+ }
+ // 这里的nativeWindow是从上一步骤中的回调函数中获得的
+ int32_t usage = NATIVEBUFFER_USAGE_CPU_READ | NATIVEBUFFER_USAGE_CPU_WRITE | NATIVEBUFFER_USAGE_MEM_DMA;
+ int ret = OH_NativeWindow_NativeWindowHandleOpt(nativeWindow_, SET_USAGE, usage);
+ if (ret != 0) {
+ DRAWING_LOGE("failed to OH_NativeWindow_NativeWindowHandleOpt");
+ return;
+ }
+ // 通过 OH_NativeWindow_NativeWindowRequestBuffer 获取 OHNativeWindowBuffer 实例
+ ret = OH_NativeWindow_NativeWindowRequestBuffer(nativeWindow_, &buffer_, &fenceFd_);
+ DRAWING_LOGI("request buffer ret = %{public}d", ret);
+ // 通过 OH_NativeWindow_GetBufferHandleFromNative 获取 buffer 的 handle
+ bufferHandle_ = OH_NativeWindow_GetBufferHandleFromNative(buffer_);
+ // 使用系统mmap接口拿到bufferHandle的内存虚拟地址
+ mappedAddr_ = static_cast(
+ mmap(bufferHandle_->virAddr, bufferHandle_->size, PROT_READ | PROT_WRITE, MAP_SHARED, bufferHandle_->fd, 0));
+ if (mappedAddr_ == MAP_FAILED) {
+ DRAWING_LOGE("mmap failed");
+ }
+}
+
+void SampleBitMap::DisPlay()
+{
+ // 画完后获取像素地址,地址指向的内存包含画布画的像素数据
+ void *bitmapAddr = OH_Drawing_BitmapGetPixels(cBitmap_);
+ uint32_t *value = static_cast(bitmapAddr);
+
+ uint32_t *pixel = static_cast(mappedAddr_); // 使用mmap获取到的地址来访问内存
+ if (pixel == nullptr) {
+ DRAWING_LOGE("pixel is null");
+ return;
+ }
+ if (value == nullptr) {
+ DRAWING_LOGE("value is null");
+ return;
+ }
+ uint32_t width = static_cast(bufferHandle_->stride / 4);
+ for (uint32_t x = 0; x < width; x++) {
+ for (uint32_t y = 0; y < height_; y++) {
+ *pixel++ = *value++;
+ }
+ }
+ // 设置刷新区域,如果Region中的Rect为nullptr,或者rectNumber为0,则认为OHNativeWindowBuffer全部有内容更改。
+ Region region {nullptr, 0};
+ // 通过OH_NativeWindow_NativeWindowFlushBuffer 提交给消费者使用,例如:显示在屏幕上。
+ OH_NativeWindow_NativeWindowFlushBuffer(nativeWindow_, buffer_, fenceFd_, region);
+ // 内存使用完记得去掉内存映射
+ int result = munmap(mappedAddr_, bufferHandle_->size);
+ if (result == -1) {
+ DRAWING_LOGE("munmap failed!");
+ }
+}
+
+void SampleBitMap::Create()
+{
+ uint32_t width = static_cast(bufferHandle_->stride / 4);
+ // 创建一个bitmap对象
+ cBitmap_ = OH_Drawing_BitmapCreate();
+ // 定义bitmap的像素格式
+ OH_Drawing_BitmapFormat cFormat {COLOR_FORMAT_RGBA_8888, ALPHA_FORMAT_OPAQUE};
+ // 构造对应格式的bitmap
+ OH_Drawing_BitmapBuild(cBitmap_, width, height_, &cFormat);
+
+ // 创建一个canvas对象
+ cCanvas_ = OH_Drawing_CanvasCreate();
+ // 将画布与bitmap绑定,画布画的内容会输出到绑定的bitmap内存中
+ OH_Drawing_CanvasBind(cCanvas_, cBitmap_);
+ // 使用白色清除画布内容
+ OH_Drawing_CanvasClear(cCanvas_, OH_Drawing_ColorSetArgb(0xFF, 0xFF, 0xFF, 0xFF));
+}
+
+void SampleBitMap::AddFontVariation() {
+ // 创建一个 TypographyStyle 创建 Typography 时需要使用
+ OH_Drawing_TypographyStyle *typoStyle = OH_Drawing_CreateTypographyStyle();
+ // 设置文本对齐方式为居中
+ OH_Drawing_SetTypographyTextAlign(typoStyle, TEXT_ALIGN_CENTER);
+ // 设置文字内容
+ const char *text = "Hello World Drawing\n";
+
+ OH_Drawing_TextStyle *txtStyleWithVar = OH_Drawing_CreateTextStyle();
+ // 设置可变字体的字重,在字体文件支持的情况下,还可以设置"slnt", "wdth"。
+ OH_Drawing_TextStyleAddFontVariation(txtStyleWithVar, "wght", 800);
+ // 设置文字颜色、大小、字重,不设置 TextStyle 会使用 TypographyStyle 中的默认 TextStyle
+ OH_Drawing_SetTextStyleColor(txtStyleWithVar, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
+ OH_Drawing_SetTextStyleFontSize(txtStyleWithVar, 100);
+ // 此处设置字重不生效,被可变字体的字重覆盖了。
+ OH_Drawing_SetTextStyleFontWeight(txtStyleWithVar, FONT_WEIGHT_400);
+
+ // 创建一个不带可变字体的 TextStyle 用于对比
+ OH_Drawing_TextStyle *txtStyleNoVar = OH_Drawing_CreateTextStyle();
+ // 设置文字颜色、大小、字重,不设置 TextStyle 会使用 TypographyStyle 中的默认 TextStyle
+ OH_Drawing_SetTextStyleColor(txtStyleNoVar, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
+ OH_Drawing_SetTextStyleFontSize(txtStyleNoVar, 100);
+ OH_Drawing_SetTextStyleFontWeight(txtStyleNoVar, FONT_WEIGHT_400);
+
+ // 创建 FontCollection,FontCollection 用于管理字体匹配逻辑
+ OH_Drawing_FontCollection *fc = OH_Drawing_CreateSharedFontCollection();
+ // 使用 FontCollection 和 之前创建的 TypographyStyle 创建 TypographyCreate。TypographyCreate 用于创建 Typography
+ OH_Drawing_TypographyCreate *handler = OH_Drawing_CreateTypographyHandler(typoStyle, fc);
+
+ // 加入带有可变字体的文本样式
+ OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyleWithVar);
+ // 将文本添加到 handler 中
+ OH_Drawing_TypographyHandlerAddText(handler, text);
+ // 销毁之前创建的 TextStyle
+ OH_Drawing_TypographyHandlerPopTextStyle(handler);
+
+ // 后续加入的不带可变字体的文本样式
+ OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyleNoVar);
+ // 将文本添加到 handler 中
+ OH_Drawing_TypographyHandlerAddText(handler, text);
+ // 销毁之前创建的 TextStyle
+ OH_Drawing_TypographyHandlerPopTextStyle(handler);
+
+ OH_Drawing_Typography *typography = OH_Drawing_CreateTypography(handler);
+ // 设置页面最大宽度
+ double maxWidth = width_;
+ OH_Drawing_TypographyLayout(typography, maxWidth);
+ // 设置文本在画布上绘制的起始位置
+ double position[2] = {width_ / 5.0, height_ / 2.0};
+ // 将文本绘制到画布上
+ OH_Drawing_TypographyPaint(typography, cCanvas_, 0, 100);
+
+ // 释放内存
+ OH_Drawing_DestroyTypographyStyle(typoStyle);
+ OH_Drawing_DestroyTextStyle(txtStyleWithVar);
+ OH_Drawing_DestroyTextStyle(txtStyleNoVar);
+ OH_Drawing_DestroyFontCollection(fc);
+ OH_Drawing_DestroyTypographyHandler(handler);
+ OH_Drawing_DestroyTypography(typography);
+}
+
+void SampleBitMap::SetTextShadow()
+{
+ // 创建一个 TypographyStyle 创建 Typography 时需要使用
+ OH_Drawing_TypographyStyle *typoStyle = OH_Drawing_CreateTypographyStyle();
+ // 设置文本对齐方式为居中
+ OH_Drawing_SetTypographyTextAlign(typoStyle, TEXT_ALIGN_CENTER);
+ // 设置文本内容
+ const char *text = "Hello World Drawing\n";
+
+ // 设置文字颜色、大小、字重,不设置 TextStyle 会使用 TypographyStyle 中的默认 TextStyle
+ OH_Drawing_TextStyle *txtStyleWithShadow = OH_Drawing_CreateTextStyle();
+ OH_Drawing_SetTextStyleColor(txtStyleWithShadow, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
+ OH_Drawing_SetTextStyleFontSize(txtStyleWithShadow, 100);
+ OH_Drawing_SetTextStyleFontWeight(txtStyleWithShadow, FONT_WEIGHT_400);
+ // 设置阴影偏移量
+ OH_Drawing_Point *offset = OH_Drawing_PointCreate(1, 1);
+ OH_Drawing_TextShadow *shadow = OH_Drawing_CreateTextShadow();
+ // 为 TextShadow 设置样式
+ OH_Drawing_SetTextShadow(shadow, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00), offset, 10);
+ // 将 TextShadow 加入 TextStyle
+ OH_Drawing_TextStyleAddShadow(txtStyleWithShadow, shadow);
+
+ // 创建一个不带阴影的 TextStyle 用于对比
+ OH_Drawing_TextStyle *txtStyleNoShadow = OH_Drawing_CreateTextStyle();
+ // 设置文字颜色、大小、字重,不设置 TextStyle 会使用 TypographyStyle 中的默认 TextStyle
+ OH_Drawing_SetTextStyleColor(txtStyleNoShadow, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
+ OH_Drawing_SetTextStyleFontSize(txtStyleNoShadow, 100);
+ OH_Drawing_SetTextStyleFontWeight(txtStyleNoShadow, FONT_WEIGHT_400);
+
+ // 创建 FontCollection,FontCollection 用于管理字体匹配逻辑
+ OH_Drawing_FontCollection *fc = OH_Drawing_CreateSharedFontCollection();
+ // 使用 FontCollection 和 之前创建的 TypographyStyle 创建 TypographyCreate。TypographyCreate 用于创建 Typography
+ OH_Drawing_TypographyCreate *handler = OH_Drawing_CreateTypographyHandler(typoStyle, fc);
+
+ // 加入带有阴影的文本样式
+ OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyleWithShadow);
+ // 将文本添加到 handler 中
+ OH_Drawing_TypographyHandlerAddText(handler, text);
+
+ // 后续加入的不带阴影的文本样式
+ OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyleNoShadow);
+ // 将文本添加到 handler 中
+ OH_Drawing_TypographyHandlerAddText(handler, text);
+
+ OH_Drawing_Typography *typography = OH_Drawing_CreateTypography(handler);
+ // 设置页面最大宽度
+ double maxWidth = width_;
+ OH_Drawing_TypographyLayout(typography, maxWidth);
+ // 设置文本在画布上绘制的起始位置
+ double position[2] = {width_ / 5.0, height_ / 2.0};
+ // 将文本绘制到画布上
+ OH_Drawing_TypographyPaint(typography, cCanvas_, 0, 100);
+
+ // 释放内存
+ OH_Drawing_DestroyTypographyStyle(typoStyle);
+ OH_Drawing_DestroyTextStyle(txtStyleWithShadow);
+ OH_Drawing_DestroyTextShadow(shadow);
+ OH_Drawing_DestroyTextStyle(txtStyleNoShadow);
+ OH_Drawing_DestroyFontCollection(fc);
+ OH_Drawing_DestroyTypographyHandler(handler);
+ OH_Drawing_DestroyTypography(typography);
+}
+
+void SampleBitMap::DawingInterface()
+{
+ // 创建一个 TypographyStyle 创建 Typography 时需要使用
+ OH_Drawing_TypographyStyle *typoStyle = OH_Drawing_CreateTypographyStyle();
+ // 设置文本对齐方式为居中
+ OH_Drawing_SetTypographyTextAlign(typoStyle, TEXT_ALIGN_CENTER);
+
+ // 设置文字颜色、大小、字重,不设置 TextStyle 会使用 TypographyStyle 中的默认 TextStyle
+ OH_Drawing_TextStyle *txtStyle = OH_Drawing_CreateTextStyle();
+ OH_Drawing_Brush* backgroundBrush = OH_Drawing_BrushCreate();
+ //设置指定文本样式中的背景色画刷。
+ OH_Drawing_SetTextStyleBackgroundBrush(txtStyle, backgroundBrush);
+ OH_Drawing_SetTextStyleColor(txtStyle, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
+ //设置字体基线位置。
+ OH_Drawing_SetTextStyleBaseLine(txtStyle, TEXT_BASELINE_IDEOGRAPHIC);
+ //设置行高,按当前字体大小的倍数进行设置
+ OH_Drawing_SetTextStyleFontHeight(txtStyle, 2.0);
+ //设置字体风格,设置1为斜体,设置0或其它为非斜体,具体可见OH_Drawing_FontStyle枚举
+ OH_Drawing_SetTextStyleFontStyle(txtStyle, FONT_STYLE_ITALIC);
+ OH_Drawing_Brush* foregrounddBrush = OH_Drawing_BrushCreate();
+ OH_Drawing_BrushSetColor(foregrounddBrush, OH_Drawing_ColorSetArgb(255, 50, 0, 255));
+ //设置指定文本样式中的前景色画刷。
+ OH_Drawing_SetTextStyleForegroundBrush(txtStyle, foregrounddBrush);
+ OH_Drawing_Pen* foregroundPen = OH_Drawing_PenCreate();
+ //设置指定文本样式中的前景色画笔。
+ OH_Drawing_SetTextStyleForegroundPen(txtStyle, foregroundPen);
+ //设置文本为一半行间距。
+ OH_Drawing_SetTextStyleHalfLeading(txtStyle, true);
+ //设置文本的字符间距。
+ OH_Drawing_SetTextStyleLetterSpacing(txtStyle, 10.0);
+ //设置语言类型,数据类型为指向char的指针,如'en'代表英文,'zh-Hans'代表简体中文,'zh-Hant'代表繁体中文。
+ OH_Drawing_SetTextStyleLocale(txtStyle, "zh-Hans");
+ //设置文本的单词间距。
+ OH_Drawing_SetTextStyleWordSpacing(txtStyle, 5.0);
+
+ OH_Drawing_SetTextStyleFontSize(txtStyle, 60);
+ OH_Drawing_SetTextStyleFontWeight(txtStyle, FONT_WEIGHT_400);
+
+ // 创建 FontCollection,FontCollection 用于管理字体匹配逻辑
+ OH_Drawing_FontCollection *fc = OH_Drawing_CreateSharedFontCollection();
+ // 使用 FontCollection 和 之前创建的 TypographyStyle 创建 TypographyCreate。TypographyCreate 用于创建 Typography
+ OH_Drawing_TypographyCreate *handler = OH_Drawing_CreateTypographyHandler(typoStyle, fc);
+
+ // 创建一个 placeholder,并且初始化其成员变量
+ OH_Drawing_PlaceholderSpan placeholder;
+ placeholder.width = 150.0;
+ placeholder.height = 150.0;
+ placeholder.alignment = OH_Drawing_PlaceholderVerticalAlignment::ALIGNMENT_ABOVE_BASELINE; // 基线对齐策略
+ placeholder.baseline = OH_Drawing_TextBaseline::TEXT_BASELINE_ALPHABETIC; // 使用的文本基线类型
+ placeholder.baselineOffset = 0.0; // 相比基线的偏移量。只有对齐策略是 OFFSET_AT_BASELINE 时生效
+ // 将 placeholder 放在开头
+ OH_Drawing_TypographyHandlerAddPlaceholder(handler, &placeholder);
+
+ // 将之前创建的 TextStyle 加入 handler 中
+ OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyle);
+ // 设置文本内容,并将文本添加到 handler 中
+ const char *text = "Hello World Drawing\n";
+ OH_Drawing_TypographyHandlerAddText(handler, text);
+
+ OH_Drawing_Typography *typography = OH_Drawing_CreateTypography(handler);
+ // 设置页面最大宽度
+ double maxWidth = width_;
+ OH_Drawing_TypographyLayout(typography, maxWidth);
+
+ //获取排版对象中占位符的文本框,该接口需要在OH_Drawing_TypographyLayout接口调用之后调用
+ OH_Drawing_TextBox *textBox = OH_Drawing_TypographyGetRectsForPlaceholders(typography);
+ //获取文本框顶部位置 第二个参数为文本框的索引,下同。
+ float top = OH_Drawing_GetTopFromTextBox(textBox, 0);
+ float bottom = OH_Drawing_GetBottomFromTextBox(textBox, 0);
+ float left = OH_Drawing_GetLeftFromTextBox(textBox, 0);
+ float right = OH_Drawing_GetRightFromTextBox(textBox, 0);
+ size_t size = OH_Drawing_GetSizeOfTextBox(textBox);
+ DRAWING_LOGI("top = %{public}f bottom = %{public}f left = %{public}f right = %{public}f size = %{public}zu", top, bottom, left, right, size);
+
+ // 设置文本在画布上绘制的起始位置
+ double position[2] = {width_ / 5.0, height_ / 2.0};
+ // 将文本绘制到画布上
+ OH_Drawing_TypographyPaint(typography, cCanvas_, 0, 100);
+
+ // 释放内存
+ OH_Drawing_DestroyTypographyStyle(typoStyle);
+ OH_Drawing_DestroyTextStyle(txtStyle);
+ OH_Drawing_DestroyFontCollection(fc);
+ OH_Drawing_DestroyTypographyHandler(handler);
+ OH_Drawing_DestroyTypography(typography);
+}
+
+void SampleBitMap::SetTypography()
+{
+ // 创建一个 TypographyStyle 创建 Typography 时需要使用
+ OH_Drawing_TypographyStyle *typoStyle = OH_Drawing_CreateTypographyStyle();
+ //设置指定排版样式中的文本方向。详见OH_Drawing_TextDirection枚举
+ OH_Drawing_SetTypographyTextDirection(typoStyle, TEXT_DIRECTION_RTL);
+ //设置省略号样式
+ OH_Drawing_SetTypographyTextEllipsis(typoStyle, "***");
+ //设置文本的省略号样式。如中间省略,详见OH_Drawing_EllipsisModal枚举
+ OH_Drawing_SetTypographyTextEllipsisModal(typoStyle, ELLIPSIS_MODAL_MIDDLE);
+ //设置字体家族的名称。
+ OH_Drawing_SetTypographyTextFontFamily(typoStyle, "MyFamilyName");
+ //设置文本排版字号
+ OH_Drawing_SetTypographyTextFontSize(typoStyle, 10);
+ //设置字体风格,设置1为斜体,设置0或其它为非斜体,具体可见OH_Drawing_FontStyle枚举。
+ OH_Drawing_SetTypographyTextFontStyle(typoStyle, FONT_STYLE_OBLIQUE);
+ //设置文本排版字重。目前只有系统默认字体支持字重的调节,其他字体设置字重值小于semi-bold时字体粗细无变化,当设置字重值大于等于semi-bold时可能会触发伪加粗效果
+ OH_Drawing_SetTypographyTextFontWeight(typoStyle, FONT_WEIGHT_800);
+
+
+ // 设置文本对齐方式为居中
+ OH_Drawing_SetTypographyTextAlign(typoStyle, TEXT_ALIGN_CENTER);
+
+ // 设置文字颜色、大小、字重,不设置 TextStyle 会使用 TypographyStyle 中的默认 TextStyle
+ OH_Drawing_TextStyle *txtStyle = OH_Drawing_CreateTextStyle();
+ OH_Drawing_SetTextStyleColor(txtStyle, OH_Drawing_ColorSetArgb(0xFF, 0x00, 0x00, 0x00));
+ OH_Drawing_SetTextStyleFontSize(txtStyle, 60);
+ OH_Drawing_SetTextStyleFontWeight(txtStyle, FONT_WEIGHT_400);
+ //设置段落样式
+ OH_Drawing_SetTypographyTextStyle(typoStyle, txtStyle);
+ OH_Drawing_SetTypographyTextMaxLines(typoStyle, 1);
+
+ // 创建 FontCollection,FontCollection 用于管理字体匹配逻辑
+ OH_Drawing_FontCollection *fc = OH_Drawing_CreateSharedFontCollection();
+ // 使用 FontCollection 和 之前创建的 TypographyStyle 创建 TypographyCreate。TypographyCreate 用于创建 Typography
+ OH_Drawing_TypographyCreate *handler = OH_Drawing_CreateTypographyHandler(typoStyle, fc);
+
+ // 将之前创建的 TextStyle 加入 handler 中
+ OH_Drawing_TypographyHandlerPushTextStyle(handler, txtStyle);
+ // 设置文本内容,并将文本添加到 handler 中
+ const char *text = "Typograph先关属性设置参考文本\n多行文本设置了省略模式\n省略省略省略省略省略\n省略";
+ OH_Drawing_TypographyHandlerAddText(handler, text);
+
+ OH_Drawing_Typography *typography = OH_Drawing_CreateTypography(handler);
+ // 设置页面最大宽度
+ double maxWidth = width_;
+ OH_Drawing_TypographyLayout(typography, maxWidth);
+
+ //返回文本是否超过最大行,true表示超过,false表示未超过。
+ bool isExceedMaxLines = OH_Drawing_TypographyDidExceedMaxLines(typography);
+ //获取字母文字基线。
+ double alphabeticBaseline = OH_Drawing_TypographyGetAlphabeticBaseline(typography);
+ //获取排版对象整体的高度,该接口需要在OH_Drawing_TypographyLayout接口调用之后调用。
+ double height = OH_Drawing_TypographyGetHeight(typography);
+ //获取表意文字基线。
+ double ideographicBaseline = OH_Drawing_TypographyGetIdeographicBaseline(typography);
+ //获取指定行的行宽,该接口需要在OH_Drawing_TypographyLayout接口调用之后调用
+ double lineWidth = OH_Drawing_TypographyGetLineWidth(typography, 0);
+ //获取排版对象的最大固有宽度,该接口需要在OH_Drawing_TypographyLayout接口调用之后调用。
+ double maxIntrinsicWidth = OH_Drawing_TypographyGetMaxIntrinsicWidth(typography);
+ //返回指定范围内的文本框,具体可见OH_Drawing_TextBox结构体。
+ OH_Drawing_TextBox* boxes =
+ OH_Drawing_TypographyGetRectsForRange(typography, 1, 2, RECT_HEIGHT_STYLE_TIGHT, RECT_WIDTH_STYLE_TIGHT);
+ float bottom = OH_Drawing_GetBottomFromTextBox(boxes,0);
+ DRAWING_LOGI("bottom = %{public}f", bottom);
+ DRAWING_LOGI("isExceedMaxLines = %{public}zu alphabeticBaseline = %{public}f height = %{public}f ideographicBaseline = %{public}f lineWidth = %{public}f maxIntrinsicWidth = %{public}f"
+ ,isExceedMaxLines, alphabeticBaseline, height, ideographicBaseline, lineWidth, maxIntrinsicWidth);
+
+ // 将文本绘制到画布上
+ OH_Drawing_TypographyPaint(typography, cCanvas_, 0, 100);
+
+ // 释放内存
+ OH_Drawing_DestroyTypographyStyle(typoStyle);
+ OH_Drawing_DestroyTextStyle(txtStyle);
+ OH_Drawing_DestroyFontCollection(fc);
+ OH_Drawing_DestroyTypographyHandler(handler);
+ OH_Drawing_DestroyTypography(typography);
+}
+
+napi_value SampleBitMap::NapiAddFontVariation(napi_env env, napi_callback_info info)
+{
+ DRAWING_LOGI("NapiAddFontVariation");
+ if ((env == nullptr) || (info == nullptr)) {
+ DRAWING_LOGE("NapiAddFontVariation: env or info is null");
+ return nullptr;
+ }
+
+ napi_value thisArg;
+ if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
+ DRAWING_LOGE("NapiAddFontVariation: napi_get_cb_info fail");
+ return nullptr;
+ }
+
+ napi_value exportInstance;
+ if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
+ DRAWING_LOGE("NapiAddFontVariation: napi_get_named_property fail");
+ return nullptr;
+ }
+
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) {
+ DRAWING_LOGE("NapiAddFontVariation: napi_unwrap fail");
+ return nullptr;
+ }
+
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("NapiAddFontVariation: Unable to get XComponent id");
+ return nullptr;
+ }
+ DRAWING_LOGI("ID = %{public}s", idStr);
+ std::string id(idStr);
+ SampleBitMap *render = SampleBitMap().GetInstance(id);
+ if (render != nullptr) {
+ render->Prepare();
+ render->Create();
+ render->AddFontVariation();
+ render->DisPlay();
+ render->Destroy();
+ DRAWING_LOGI("AddFontVariation executed");
+ } else {
+ DRAWING_LOGE("render is nullptr");
+ }
+ return nullptr;
+}
+
+napi_value SampleBitMap::NapiSetTextShadow(napi_env env, napi_callback_info info)
+{
+ DRAWING_LOGI("NapiSetTextShadow");
+ if ((env == nullptr) || (info == nullptr)) {
+ DRAWING_LOGE("NapiSetTextShadow: env or info is null");
+ return nullptr;
+ }
+
+ napi_value thisArg;
+ if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
+ DRAWING_LOGE("NapiSetTextShadow: napi_get_cb_info fail");
+ return nullptr;
+ }
+
+ napi_value exportInstance;
+ if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
+ DRAWING_LOGE("NapiSetTextShadow: napi_get_named_property fail");
+ return nullptr;
+ }
+
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) {
+ DRAWING_LOGE("NapiSetTextShadow: napi_unwrap fail");
+ return nullptr;
+ }
+
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("NapiSetTextShadow: Unable to get XComponent id");
+ return nullptr;
+ }
+ DRAWING_LOGI("ID = %{public}s", idStr);
+ std::string id(idStr);
+ SampleBitMap *render = SampleBitMap().GetInstance(id);
+ if (render != nullptr) {
+ render->Prepare();
+ render->Create();
+ render->SetTextShadow();
+ render->DisPlay();
+ render->Destroy();
+ DRAWING_LOGI("SetTextShadow executed");
+ } else {
+ DRAWING_LOGE("render is nullptr");
+ }
+ return nullptr;
+}
+
+napi_value SampleBitMap::NapiDawingInterface(napi_env env, napi_callback_info info)
+{
+ DRAWING_LOGI("NapiDawingInterface");
+ if ((env == nullptr) || (info == nullptr)) {
+ DRAWING_LOGE("NapiDawingInterface: env or info is null");
+ return nullptr;
+ }
+
+ napi_value thisArg;
+ if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
+ DRAWING_LOGE("NapiDawingInterface: napi_get_cb_info fail");
+ return nullptr;
+ }
+
+ napi_value exportInstance;
+ if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
+ DRAWING_LOGE("NapiDawingInterface: napi_get_named_property fail");
+ return nullptr;
+ }
+
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) {
+ DRAWING_LOGE("NapiDawingInterface: napi_unwrap fail");
+ return nullptr;
+ }
+
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("NapiDawingInterface: Unable to get XComponent id");
+ return nullptr;
+ }
+ DRAWING_LOGI("ID = %{public}s", idStr);
+ std::string id(idStr);
+ SampleBitMap *render = SampleBitMap().GetInstance(id);
+ if (render != nullptr) {
+ render->Prepare();
+ render->Create();
+ render->DawingInterface();
+ render->DisPlay();
+ render->Destroy();
+ DRAWING_LOGI("DawingInterface executed");
+ } else {
+ DRAWING_LOGE("render is nullptr");
+ }
+ return nullptr;
+}
+
+napi_value SampleBitMap::NapiSetTypography(napi_env env, napi_callback_info info)
+{
+ DRAWING_LOGI("NapiSetTypography");
+ if ((env == nullptr) || (info == nullptr)) {
+ DRAWING_LOGE("NapiSetTypography: env or info is null");
+ return nullptr;
+ }
+
+ napi_value thisArg;
+ if (napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr) != napi_ok) {
+ DRAWING_LOGE("NapiSetTypography: napi_get_cb_info fail");
+ return nullptr;
+ }
+
+ napi_value exportInstance;
+ if (napi_get_named_property(env, thisArg, OH_NATIVE_XCOMPONENT_OBJ, &exportInstance) != napi_ok) {
+ DRAWING_LOGE("NapiSetTypography: napi_get_named_property fail");
+ return nullptr;
+ }
+
+ OH_NativeXComponent *nativeXComponent = nullptr;
+ if (napi_unwrap(env, exportInstance, reinterpret_cast(&nativeXComponent)) != napi_ok) {
+ DRAWING_LOGE("NapiSetTypography: napi_unwrap fail");
+ return nullptr;
+ }
+
+ char idStr[OH_XCOMPONENT_ID_LEN_MAX + 1] = {'\0'};
+ uint64_t idSize = OH_XCOMPONENT_ID_LEN_MAX + 1;
+ if (OH_NativeXComponent_GetXComponentId(nativeXComponent, idStr, &idSize) != OH_NATIVEXCOMPONENT_RESULT_SUCCESS) {
+ DRAWING_LOGE("NapiSetTypography: Unable to get XComponent id");
+ return nullptr;
+ }
+ DRAWING_LOGI("ID = %{public}s", idStr);
+ std::string id(idStr);
+ SampleBitMap *render = SampleBitMap().GetInstance(id);
+ if (render != nullptr) {
+ render->Prepare();
+ render->Create();
+ render->SetTypography();
+ render->DisPlay();
+ render->Destroy();
+ DRAWING_LOGI("SetTypography executed");
+ } else {
+ DRAWING_LOGE("render is nullptr");
+ }
+ return nullptr;
+}
+
+SampleBitMap::~SampleBitMap()
+{
+ // 销毁创建的对象
+ OH_Drawing_BrushDestroy(cBrush_);
+ cBrush_ = nullptr;
+ OH_Drawing_PenDestroy(cPen_);
+ cPen_ = nullptr;
+ OH_Drawing_PathDestroy(cPath_);
+ cPath_ = nullptr;
+ // 销毁canvas对象
+ OH_Drawing_CanvasDestroy(cCanvas_);
+ cCanvas_ = nullptr;
+ // 销毁bitmap对象
+ OH_Drawing_BitmapDestroy(cBitmap_);
+ cBitmap_ = nullptr;
+
+ buffer_ = nullptr;
+ bufferHandle_ = nullptr;
+ nativeWindow_ = nullptr;
+ mappedAddr_ = nullptr;
+}
+
+void SampleBitMap::Destroy()
+{
+ // 销毁创建的对象
+ OH_Drawing_BrushDestroy(cBrush_);
+ cBrush_ = nullptr;
+ OH_Drawing_PenDestroy(cPen_);
+ cPen_ = nullptr;
+ OH_Drawing_PathDestroy(cPath_);
+ cPath_ = nullptr;
+ // 销毁canvas对象
+ OH_Drawing_CanvasDestroy(cCanvas_);
+ cCanvas_ = nullptr;
+ // 销毁bitmap对象
+ OH_Drawing_BitmapDestroy(cBitmap_);
+}
+
+void SampleBitMap::Release(std::string &id)
+{
+ PluginManager::GetInstance()->ReleaseRender(id);
+ SampleBitMap *render = SampleBitMap::GetInstance(id);
+ if (render != nullptr) {
+ delete render;
+ render = nullptr;
+ g_instance.erase(g_instance.find(id));
+ }
+}
+
+void SampleBitMap::Export(napi_env env, napi_value exports)
+{
+ if ((env == nullptr) || (exports == nullptr)) {
+ DRAWING_LOGE("Export: env or exports is null");
+ return;
+ }
+ napi_property_descriptor desc[] = {
+ {"addFontVariation", nullptr, SampleBitMap::NapiAddFontVariation, nullptr, nullptr, nullptr, napi_default, nullptr},
+ {"dawingInterface", nullptr, SampleBitMap::NapiDawingInterface, nullptr, nullptr, nullptr, napi_default, nullptr},
+ {"setTypography", nullptr, SampleBitMap::NapiSetTypography, nullptr, nullptr, nullptr, napi_default, nullptr},
+ {"setTextShadow", nullptr, SampleBitMap::NapiSetTextShadow, nullptr, nullptr, nullptr, napi_default, nullptr}};
+ napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
+ if (napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc) != napi_ok) {
+ DRAWING_LOGE("Export: napi_define_properties failed");
+ }
+}
+
+void SampleBitMap::RegisterCallback(OH_NativeXComponent *nativeXComponent)
+{
+ DRAWING_LOGI("register callback");
+ renderCallback_.OnSurfaceCreated = OnSurfaceCreatedCB;
+ renderCallback_.OnSurfaceDestroyed = OnSurfaceDestroyedCB;
+ // Callback must be initialized
+ renderCallback_.DispatchTouchEvent = nullptr;
+ renderCallback_.OnSurfaceChanged = nullptr;
+ OH_NativeXComponent_RegisterCallback(nativeXComponent, &renderCallback_);
+}
+
+SampleBitMap *SampleBitMap::GetInstance(std::string &id)
+{
+ if (g_instance.find(id) == g_instance.end()) {
+ SampleBitMap *render = new SampleBitMap(id);
+ g_instance[id] = render;
+ return render;
+ } else {
+ return g_instance[id];
+ }
+}
diff --git a/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/samples/sample_bitmap.h b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/samples/sample_bitmap.h
new file mode 100644
index 0000000000000000000000000000000000000000..d11f40c24fbe419d6519a2cc638244dc162657ec
--- /dev/null
+++ b/code/DocsSample/graphic/NDKGraphics2D/NDKComplextext/entry/src/main/cpp/samples/sample_bitmap.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2023 Huawei Device Co., Ltd.
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef SAMPLE_BITMAP_H
+#define SAMPLE_BITMAP_H
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include