mirror of
https://github.com/openharmony/ace_ace_engine.git
synced 2026-06-30 21:17:59 -04:00
update OpenHarmony 2.0 Canary
This commit is contained in:
+14
@@ -0,0 +1,14 @@
|
||||
.vs/
|
||||
.vscode/
|
||||
*.iml
|
||||
.idea/
|
||||
CMakeLists.txt
|
||||
cmake-build-debug/
|
||||
lite/appfwk/
|
||||
lite/base/
|
||||
lite/interfaces/
|
||||
lite/jsfwk/
|
||||
lite/maplejs/
|
||||
lite/tools/
|
||||
lite/ui/
|
||||
|
||||
@@ -0,0 +1,134 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
config("accessibility_library_config") {
|
||||
include_dirs = [ "../accessibility/common/" ]
|
||||
}
|
||||
|
||||
group("ace_packages") {
|
||||
deps = []
|
||||
|
||||
# core library for Ability Cross-platform Environment(ACE) JS
|
||||
deps += [
|
||||
"$ace_root/frameworks/core/components/theme:build_theme_code",
|
||||
"adapter/common/cpp:libace",
|
||||
]
|
||||
|
||||
if (is_wearable_product) {
|
||||
deps += [ "adapter/common/cpp:libace_debug" ]
|
||||
}
|
||||
|
||||
if (!is_wearable_product) {
|
||||
deps += [
|
||||
"adapter/common/cpp:libace_engine_qjs",
|
||||
"adapter/common/cpp:libace_engine_qjs_debug",
|
||||
"adapter/common/cpp:libace_engine_declarative_qjs"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
group("ace_test_packages") {
|
||||
# ohos platform
|
||||
deps = []
|
||||
}
|
||||
|
||||
source_set("third_party_cjson") {
|
||||
sources = [ "$cjson_root/cJSON.c" ]
|
||||
}
|
||||
|
||||
# Common config for Ability Cross-platform Environment(ACE) source
|
||||
config("ace_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"$ace_root",
|
||||
"$ace_root/frameworks",
|
||||
"$root_out_dir/ace/framework",
|
||||
"//third_party/zlib",
|
||||
]
|
||||
if (is_standard_system) {
|
||||
include_dirs += [
|
||||
"//base/global/resmgr_standard/frameworks/resmgr/include",
|
||||
"//base/global/resmgr_standard/interfaces/innerkits/include",
|
||||
]
|
||||
}
|
||||
defines = ace_common_defines
|
||||
|
||||
if (is_wearable_product) {
|
||||
defines += ace_wearable_defines
|
||||
}
|
||||
|
||||
if (enable_dump_drawcmd) {
|
||||
defines += [ "DUMP_DRAW_CMD" ]
|
||||
}
|
||||
|
||||
if (is_standard_system) {
|
||||
defines += [ "SK_BUILD_FOR_UNIX" ]
|
||||
}
|
||||
|
||||
cflags = [
|
||||
"-fvisibility=hidden",
|
||||
"-fdata-sections",
|
||||
"-ffunction-sections",
|
||||
"-Os",
|
||||
]
|
||||
|
||||
cflags_cc = [
|
||||
"-fvisibility-inlines-hidden",
|
||||
"-Os",
|
||||
]
|
||||
|
||||
if (use_js_debug) {
|
||||
cflags_cc += [
|
||||
"-fexceptions",
|
||||
"-fno-complete-member-pointers",
|
||||
"-Wno-implicit-fallthrough",
|
||||
]
|
||||
}
|
||||
|
||||
if (use_mingw_win) {
|
||||
cflags += [ "-std=c++17" ]
|
||||
defines += [ "_USE_MATH_DEFINES" ]
|
||||
}
|
||||
}
|
||||
|
||||
config("ace_test_config") {
|
||||
visibility = [ ":*" ]
|
||||
include_dirs = [
|
||||
"$ace_root",
|
||||
"$ace_root/frameworks",
|
||||
"$root_out_dir/ace/framework",
|
||||
]
|
||||
if (is_standard_system) {
|
||||
include_dirs += [
|
||||
"//base/global/resmgr_standard/frameworks/resmgr/include",
|
||||
"//base/global/resmgr_standard/interfaces/innerkits/include",
|
||||
]
|
||||
}
|
||||
defines = ace_common_defines
|
||||
defines += ace_ohos_defines
|
||||
|
||||
if (is_wearable_product) {
|
||||
defines += ace_wearable_defines
|
||||
}
|
||||
|
||||
cflags = [
|
||||
"-fvisibility=hidden",
|
||||
"-fdata-sections",
|
||||
"-ffunction-sections",
|
||||
]
|
||||
|
||||
cflags_cc = [ "-fvisibility-inlines-hidden" ]
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!-- Copyright (c) 2021 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.
|
||||
-->
|
||||
<!-- OAT(OSS Audit Tool) configuration guide:
|
||||
basedir: Root dir, the basedir + project path is the real source file location.
|
||||
licensefile:
|
||||
1.If the project don't have "LICENSE" in root dir, please define all the license files in this project in , OAT will check license files according to this rule.
|
||||
|
||||
tasklist(only for batch mode):
|
||||
1. task: Define oat check thread, each task will start a new thread.
|
||||
2. task name: Only an name, no practical effect.
|
||||
3. task policy: Default policy for projects under this task, this field is required and the specified policy must defined in policylist.
|
||||
4. task filter: Default filefilter for projects under this task, this field is required and the specified filefilter must defined in filefilterlist.
|
||||
5. task project: Projects to be checked, the path field define the source root dir of the project.
|
||||
|
||||
|
||||
policyList:
|
||||
1. policy: All policyitems will be merged to default OAT.xml rules, the name of policy doesn't affect OAT check process.
|
||||
2. policyitem: The fields type, name, path, desc is required, and the fields rule, group, filefilter is optional,the default value is:
|
||||
<policyitem type="" name="" path="" desc="" rule="may" group="defaultGroup" filefilter="defaultPolicyFilter"/>
|
||||
3. policyitem type:
|
||||
"compatibility" is used to check license compatibility in the specified path;
|
||||
"license" is used to check source license header in the specified path;
|
||||
"copyright" is used to check source copyright header in the specified path;
|
||||
"import" is used to check source dependency in the specified path, such as import ... ,include ...
|
||||
"filetype" is used to check file type in the specified path, supported file types: archive, binary
|
||||
"filename" is used to check whether the specified file exists in the specified path(support projectroot in default OAT.xml), supported file names: LICENSE, README, README.OpenSource
|
||||
|
||||
4. policyitem name: This field is used for define the license, copyright, "*" means match all, the "!" prefix means could not match this value. For example, "!GPL" means can not use GPL license.
|
||||
5. policyitem path: This field is used for define the source file scope to apply this policyitem, the "!" prefix means exclude the files. For example, "!.*/lib/.*" means files in lib dir will be exclude while process this policyitem.
|
||||
6. policyitem rule and group: These two fields are used together to merge policy results. "may" policyitems in the same group means any one in this group passed, the result will be passed.
|
||||
7. policyitem filefilter: Used to bind filefilter which define filter rules.
|
||||
8. filefilter: Filter rules, the type filename is used to filter file name, the type filepath is used to filter file path.
|
||||
|
||||
Note:If the text contains special characters, please escape them according to the following rules:
|
||||
" == >
|
||||
& == >
|
||||
' == >
|
||||
< == >
|
||||
> == >
|
||||
-->
|
||||
<configuration>
|
||||
<oatconfig>
|
||||
<licensefile></licensefile>
|
||||
<policylist>
|
||||
<policy name="projectPolicy" desc="">
|
||||
<policyitem type="license" name="BSD-3-Clause" path="frameworks/core/pipeline/LICENSE" desc="三方软件许可证, 与Apache兼容"/>
|
||||
</policy>
|
||||
</policylist>
|
||||
<filefilterlist>
|
||||
<filefilter name="binaryFileTypePolicyFilter" desc="二进制文件校验策略的过滤条件" >
|
||||
<filteritem type="filepath" name="frameworks/base/resource/binary/mac/.*.o" desc="来源于代码仓foundation/ace/ace_engine/frameworks/base/resource/binary下的svg编译而来。现有的objcopy工具链在mac上不能用,使用开源工具转换成.o。"/>
|
||||
</filefilter>
|
||||
<filefilter name="binaryFileTypePolicyFilter" desc="二进制文件校验策略的过滤条件" >
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imageprovider/images/broken.bmp" desc="自造的二进制图片"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imageprovider/images/broken.webp" desc="自造的二进制图片"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imageprovider/images/unbroken.bmp" desc="自研图片"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imageprovider/images/unbroken.webp" desc="自研图片"/>
|
||||
</filefilter>
|
||||
<filefilter name="copyrightPolicyFilter" desc="copyright文件头校验策略的过滤条件" >
|
||||
<filteritem type="filepath" name="frameworks/core/components/theme/theme.csv" desc="csv无法添加版权头"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/1008157312073340586" desc="自造的二进制文件无法添加版权头"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/13610839755484614436" desc="自造的二进制文件无法添加版权头"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/5841967474238710136" desc="自造的二进制文件无法添加版权头"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/748621363886323660" desc="自造的二进制文件无法添加版权头"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/8819493328252140263" desc="自造的二进制文件无法添加版权头"/>
|
||||
</filefilter>
|
||||
<filefilter name="defaultPolicyFilter" desc="根目录LICENSE文件校验策略的过滤条件xxx" >
|
||||
<filteritem type="filepath" name="frameworks/core/components/theme/theme.csv" desc="csv无法添加License"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/1008157312073340586" desc="用于测试自造的二进制文件无法添加License"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/13610839755484614436" desc="用于测试自造的二进制文件无法添加License"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/5841967474238710136" desc="用于测试自造的二进制文件无法添加License"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/748621363886323660" desc="用于测试自造的二进制文件无法添加License"/>
|
||||
<filteritem type="filepath" name="test/resource/graphicalbasicability/imagecache/images/8819493328252140263" desc="用于测试自造的二进制文件无法添加License"/>
|
||||
</filefilter>
|
||||
</filefilterlist>
|
||||
|
||||
</oatconfig>
|
||||
</configuration>
|
||||
@@ -1,36 +0,0 @@
|
||||
# ace_ace_engine
|
||||
|
||||
#### Description
|
||||
JS UI framework | JS UI开发框架
|
||||
|
||||
#### Software Architecture
|
||||
Software architecture description
|
||||
|
||||
#### Installation
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Instructions
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
|
||||
#### Contribution
|
||||
|
||||
1. Fork the repository
|
||||
2. Create Feat_xxx branch
|
||||
3. Commit your code
|
||||
4. Create Pull Request
|
||||
|
||||
|
||||
#### Gitee Feature
|
||||
|
||||
1. You can use Readme\_XXX.md to support different languages, such as Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee blog [blog.gitee.com](https://blog.gitee.com)
|
||||
3. Explore open source project [https://gitee.com/explore](https://gitee.com/explore)
|
||||
4. The most valuable open source project [GVP](https://gitee.com/gvp)
|
||||
5. The manual of Gitee [https://gitee.com/help](https://gitee.com/help)
|
||||
6. The most popular members [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
@@ -1,37 +1,102 @@
|
||||
# ace_ace_engine
|
||||
# JS UI Framework<a name="EN-US_TOPIC_0000001076213364"></a>
|
||||
|
||||
#### 介绍
|
||||
JS UI framework | JS UI开发框架
|
||||
- [Introduction](#section15701932113019)
|
||||
- [Directory Structure](#section1791423143211)
|
||||
- [When to Use](#section171384529150)
|
||||
- [Available Components](#section271831717166)
|
||||
- [Repositories Involved](#section1447164910172)
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
## Introduction<a name="section15701932113019"></a>
|
||||
|
||||
The OpenHarmony JS UI framework provides basic, container, and canvas UI components and standard CSS animation capabilities. It supports the web-development-like programming paradigm.
|
||||
|
||||
- **Web-development-like paradigm**
|
||||
|
||||
The JS UI framework supports languages that are similar to those for web development, such as HTML and CSS. You can use them to describe the page layout and style, and use JavaScript \(conforming to the ECMAScript specification\) for page behavior. This paradigm allows you to avoid code for UI state switching. The view configuration information is intuitive.
|
||||
|
||||
|
||||
#### 安装教程
|
||||
**Figure 1** Framework architecture<a name="fig2606133765017"></a>
|
||||

|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
The JS UI framework consists of the application, framework, engine, and porting layers.
|
||||
|
||||
#### 使用说明
|
||||
- **Application**
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
Contains apps with Feature Abilities \(FAs\) developed with the JS UI framework. The FA app in this document refers to the app with FAs developed using JavaScript.
|
||||
|
||||
#### 参与贡献
|
||||
- **Framework**
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
Parses UI pages and provides the Model-View-ViewModel \(MVVM\), page routing, custom components and more for front end development.
|
||||
|
||||
- **Engine**
|
||||
|
||||
Accomplishes animation parsing, Document Object Model \(DOM\) building, layout computing, rendering command building and drawing, and event management.
|
||||
|
||||
- **Porting Layer**
|
||||
|
||||
Abstracts the platform layer to provide abstract interfaces to connect to the platform. For example, event interconnection, rendering pipeline interconnection, and lifecycle interconnection.
|
||||
|
||||
|
||||
#### 特技
|
||||
## Directory Structure<a name="section1791423143211"></a>
|
||||
|
||||
The source code of the framework is stored in **/foundation/ace/ace\_engine**. The following shows the directory structure.
|
||||
|
||||
```
|
||||
/foundation/ace/ace_engine
|
||||
├── adapter # Platform adaptation code
|
||||
│ ├── common
|
||||
│ └── ohos
|
||||
├── frameworks # Framework code
|
||||
│ ├── base # Basic libraries
|
||||
│ ├── bridge # Bridging layer for frontend and backend components
|
||||
│ └── core # Core components
|
||||
```
|
||||
|
||||
## When to Use<a name="section171384529150"></a>
|
||||
|
||||
JS UI framework provides various UI components with rich functionalities and style definitions. You can use and reuse any component anywhere as needed. You can customize new components by combining existing ones to simplify development.
|
||||
|
||||
## Available Components<a name="section271831717166"></a>
|
||||
|
||||
**Table 1** Components provided by the framework
|
||||
|
||||
<a name="table2347172925617"></a>
|
||||
<table><thead align="left"><tr id="row5347429155610"><th class="cellrowborder" valign="top" width="28.64%" id="mcps1.2.3.1.1"><p id="p1347102910567"><a name="p1347102910567"></a><a name="p1347102910567"></a>Type</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="71.36%" id="mcps1.2.3.1.2"><p id="p83475294565"><a name="p83475294565"></a><a name="p83475294565"></a>Components</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row15347122918562"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p679795614335"><a name="p679795614335"></a><a name="p679795614335"></a>Basic</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p88813982011"><a name="p88813982011"></a><a name="p88813982011"></a>button, text, input, label, image, progress, rating, span, marquee, image-animator, divider, menu, chart, option, picker, picker-view, piece, qrcode, select, slider, switch, toolbar, toolbar-item, toggle</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row1973535793115"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p8735195713313"><a name="p8735195713313"></a><a name="p8735195713313"></a>Container</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p1268024618208"><a name="p1268024618208"></a><a name="p1268024618208"></a>div, list, list-item, list-item-group, stack, swiper, tabs, tab-bar, tab-content, refresh, dialog, badge, panel, popup, stepper, stepper-item</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row1792218915320"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p692289163220"><a name="p692289163220"></a><a name="p692289163220"></a>Canvas</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p199228910327"><a name="p199228910327"></a><a name="p199228910327"></a>canvas</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row837615526208"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p4377752152016"><a name="p4377752152016"></a><a name="p4377752152016"></a>Grid</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p17377185222019"><a name="p17377185222019"></a><a name="p17377185222019"></a>grid-container, grid-row, grid-col</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Repositories Involved<a name="section1447164910172"></a>
|
||||
|
||||
JS UI framework
|
||||
|
||||
**ace\_ace\_engine**
|
||||
|
||||
ace\_ace\_engine\_lite
|
||||
|
||||
ace\_napi
|
||||
|
||||
1. 使用 Readme\_XXX.md 来支持不同的语言,例如 Readme\_en.md, Readme\_zh.md
|
||||
2. Gitee 官方博客 [blog.gitee.com](https://blog.gitee.com)
|
||||
3. 你可以 [https://gitee.com/explore](https://gitee.com/explore) 这个地址来了解 Gitee 上的优秀开源项目
|
||||
4. [GVP](https://gitee.com/gvp) 全称是 Gitee 最有价值开源项目,是综合评定出的优秀开源项目
|
||||
5. Gitee 官方提供的使用手册 [https://gitee.com/help](https://gitee.com/help)
|
||||
6. Gitee 封面人物是一档用来展示 Gitee 会员风采的栏目 [https://gitee.com/gitee-stars/](https://gitee.com/gitee-stars/)
|
||||
|
||||
+102
@@ -0,0 +1,102 @@
|
||||
# JS UI框架组件<a name="ZH-CN_TOPIC_0000001076213364"></a>
|
||||
|
||||
- [简介](#section15701932113019)
|
||||
- [目录](#section1791423143211)
|
||||
- [使用场景](#section171384529150)
|
||||
- [接口说明](#section271831717166)
|
||||
- [涉及仓](#section1447164910172)
|
||||
|
||||
## 简介<a name="section15701932113019"></a>
|
||||
|
||||
JS UI框架是OpenHarmony UI开发框架,提供基础类、容器类、画布类等UI组件和标准CSS动画能力,支持类Web范式编程。
|
||||
|
||||
- **类Web范式编程**
|
||||
|
||||
JS UI框架采用类HTML和CSS Web编程语言作为页面布局和页面样式的开发语言,页面业务逻辑则支持ECMAScript规范的JavaScript语言。JS UI框架提供的类Web编程范式,可以让开发者避免编写UI状态切换的代码,视图配置信息更加直观。
|
||||
|
||||
|
||||
**图 1** JS UI框架架构<a name="fig2606133765017"></a>
|
||||

|
||||
|
||||
JS UI框架包括应用层(Application)、前端框架层(Framework)、引擎层(Engine)和平台适配层(Porting Layer)。
|
||||
|
||||
- **Application**
|
||||
|
||||
应用层表示开发者使用JS UI框架开发的FA应用,这里的FA应用特指JS FA应用。
|
||||
|
||||
- **Framework**
|
||||
|
||||
前端框架层主要完成前端页面解析,以及提供MVVM(Model-View-ViewModel)开发模式、页面路由机制和自定义组件等能力。
|
||||
|
||||
- **Engine**
|
||||
|
||||
引擎层主要提供动画解析、DOM(Document Object Model)树构建、布局计算、渲染命令构建与绘制、事件管理等能力。
|
||||
|
||||
- **Porting Layer**
|
||||
|
||||
适配层主要完成对平台层进行抽象,提供抽象接口,可以对接到系统平台。比如:事件对接、渲染管线对接和系统生命周期对接等。
|
||||
|
||||
|
||||
## 目录<a name="section1791423143211"></a>
|
||||
|
||||
JS UI开发框架源代码在/foundation/ace/ace\_engine下,目录结构如下图所示:
|
||||
|
||||
```
|
||||
/foundation/ace/ace_engine
|
||||
├── adapter # 平台适配目录
|
||||
│ ├── common
|
||||
│ └── ohos
|
||||
├── frameworks # 框架代码
|
||||
│ ├── base # 基础库
|
||||
│ ├── bridge # 前后端组件对接层
|
||||
│ └── core # 核心组件目录
|
||||
```
|
||||
|
||||
## 使用场景<a name="section171384529150"></a>
|
||||
|
||||
JS UI框架提供了丰富的、功能强大的UI组件、样式定义,组件之间相互独立,随取随用,也可以在需求相同的地方重复使用。开发者还可以通过组件间合理的搭配定义满足业务需求的新组件,减少开发量。
|
||||
|
||||
## 接口说明<a name="section271831717166"></a>
|
||||
|
||||
**表 1** 组件介绍
|
||||
|
||||
<a name="table2347172925617"></a>
|
||||
<table><thead align="left"><tr id="row5347429155610"><th class="cellrowborder" valign="top" width="28.64%" id="mcps1.2.3.1.1"><p id="p1347102910567"><a name="p1347102910567"></a><a name="p1347102910567"></a>组件类型</p>
|
||||
</th>
|
||||
<th class="cellrowborder" valign="top" width="71.36%" id="mcps1.2.3.1.2"><p id="p83475294565"><a name="p83475294565"></a><a name="p83475294565"></a>主要组件</p>
|
||||
</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr id="row15347122918562"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p679795614335"><a name="p679795614335"></a><a name="p679795614335"></a>基础组件</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p88813982011"><a name="p88813982011"></a><a name="p88813982011"></a>button、text、input、label、image、progress、rating、span、marquee、image-animator、divider、menu、chart、option、picker、picker-view、piece、qrcode、select、slider、switch、toolbar、toolbar-item、toggle</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row1973535793115"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p8735195713313"><a name="p8735195713313"></a><a name="p8735195713313"></a>容器组件</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p1268024618208"><a name="p1268024618208"></a><a name="p1268024618208"></a>div、list、list-item、list-item-group、stack、swiper、tabs、tab-bar、tab-content、refresh、dialog、badge、panel、popup、stepper、stepper-item</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row1792218915320"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p692289163220"><a name="p692289163220"></a><a name="p692289163220"></a>画布组件</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p199228910327"><a name="p199228910327"></a><a name="p199228910327"></a>canvas</p>
|
||||
</td>
|
||||
</tr>
|
||||
<tr id="row837615526208"><td class="cellrowborder" valign="top" width="28.64%" headers="mcps1.2.3.1.1 "><p id="p4377752152016"><a name="p4377752152016"></a><a name="p4377752152016"></a>栅格组件</p>
|
||||
</td>
|
||||
<td class="cellrowborder" valign="top" width="71.36%" headers="mcps1.2.3.1.2 "><p id="p17377185222019"><a name="p17377185222019"></a><a name="p17377185222019"></a>grid-container、grid-row、grid-col</p>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 涉及仓<a name="section1447164910172"></a>
|
||||
|
||||
JS UI框架子系统
|
||||
|
||||
**ace\_ace\_engine**
|
||||
|
||||
ace\_ace\_engine\_lite
|
||||
|
||||
ace\_napi
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
# Copyright (c) 2021 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("//third_party/flutter/flutter_ace_config.gni")
|
||||
|
||||
ace_root = "//foundation/ace/ace_engine"
|
||||
|
||||
ace_test_output_root = "ace_engine_standard"
|
||||
|
||||
objcopy_aarch64 = "//prebuilts/gcc/linux-x86/arm/gcc-linaro-7.5.0-arm-linux-gnueabi/arm-linux-gnueabi/bin/objcopy"
|
||||
objcopy_x86_64 = ""
|
||||
ark_tools_root = "//prebuilts/ace-toolkit/ace-loader/panda"
|
||||
node_js_path = "//prebuilts/ace-toolkit/nodejs/node-v12.18.4-linux-x64/bin/"
|
||||
cjson_root = "//third_party/cJSON"
|
||||
|
||||
use_js_debug = false
|
||||
@@ -0,0 +1,179 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
# build static
|
||||
template("ace_base_platform_source_set") {
|
||||
# get is_ohos_platform
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_source_set(target_name) {
|
||||
defines += invoker.defines
|
||||
configs = [
|
||||
"$ace_root:ace_config",
|
||||
"$flutter_root:flutter_config",
|
||||
"$flutter_root:icu_config_$platform",
|
||||
]
|
||||
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
|
||||
sources = [
|
||||
"ace_res_config.cpp",
|
||||
"ace_res_key_parser.cpp",
|
||||
"ace_trace.cpp",
|
||||
"file_asset_provider.cpp",
|
||||
"flutter_task_executor.cpp",
|
||||
"localization.cpp",
|
||||
"thread_util.cpp",
|
||||
]
|
||||
if (is_standard_system) {
|
||||
sources += [ "$ace_root/adapter/common/cpp/flutter_window.cpp" ]
|
||||
external_deps = [
|
||||
"appexecfwk_standard:libeventhandler",
|
||||
"ipc:ipc_core",
|
||||
]
|
||||
}
|
||||
|
||||
if (is_ohos_platform) {
|
||||
deps = [ "//third_party/zlib:libz" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ace_base_platform_source_set("ace_base_common_ohos") {
|
||||
defines = ace_ohos_defines
|
||||
is_ohos_platform = true
|
||||
platform = "ohos"
|
||||
}
|
||||
|
||||
# Build libace shared library
|
||||
template("libace_shared_library") {
|
||||
# get is_ohos_platform
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_shared_library(target_name) {
|
||||
deps = [
|
||||
"$ace_root/frameworks/base:ace_base_$platform",
|
||||
"$ace_root/frameworks/base/resource:ace_resource",
|
||||
"$ace_root/frameworks/bridge:js_framework_$platform",
|
||||
"$ace_root/frameworks/core:ace_core_$platform",
|
||||
"$ace_root/frameworks/core/accessibility:ace_accessibility_$platform",
|
||||
]
|
||||
|
||||
if (link_qjs_engine) {
|
||||
if (use_js_debug) {
|
||||
deps += [ "$ace_root/frameworks/bridge:js_engine_debug_$platform" ]
|
||||
} else {
|
||||
deps += [
|
||||
"$ace_root/frameworks/bridge:js_engine_$platform",
|
||||
"$ace_root/frameworks/bridge:declarative_js_engine_qjs_$platform",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ohos_platform) {
|
||||
subsystem_name = "ace"
|
||||
}
|
||||
|
||||
if (is_standard_system) {
|
||||
part_name = "ace_engine_standard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libace_shared_library("libace") {
|
||||
is_ohos_platform = true
|
||||
if (is_standard_system) {
|
||||
platform = "ohos"
|
||||
}
|
||||
if (is_wearable_product) {
|
||||
link_qjs_engine = true
|
||||
use_js_debug = false
|
||||
} else {
|
||||
link_qjs_engine = false
|
||||
}
|
||||
}
|
||||
|
||||
libace_shared_library("libace_debug") {
|
||||
is_ohos_platform = true
|
||||
if (is_standard_system) {
|
||||
platform = "ohos"
|
||||
}
|
||||
if (is_wearable_product) {
|
||||
link_qjs_engine = true
|
||||
use_js_debug = true
|
||||
} else {
|
||||
link_qjs_engine = false
|
||||
}
|
||||
}
|
||||
|
||||
# build platform engine sources
|
||||
template("ace_platform_engine") {
|
||||
# get is_ohos_platform, use_quickjs_engine
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_shared_library(target_name) {
|
||||
deps = []
|
||||
|
||||
if (is_ohos_platform) {
|
||||
deps += [ "$ace_root/adapter/common/cpp:libace" ]
|
||||
}
|
||||
|
||||
if (use_quickjs_engine) {
|
||||
if (use_js_debug) {
|
||||
deps += [ "$ace_root/frameworks/bridge:js_engine_debug_$platform" ]
|
||||
} else if (is_declarative) {
|
||||
deps += [ "$ace_root/frameworks/bridge:declarative_js_engine_qjs_$platform" ]
|
||||
} else {
|
||||
deps += [ "$ace_root/frameworks/bridge:js_engine_$platform"]
|
||||
}
|
||||
}
|
||||
|
||||
if (is_ohos_platform) {
|
||||
subsystem_name = "ace"
|
||||
}
|
||||
|
||||
if (is_standard_system) {
|
||||
part_name = "ace_engine_standard"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ace_platform_engine("libace_engine_qjs") {
|
||||
is_ohos_platform = true
|
||||
use_quickjs_engine = true
|
||||
if (is_standard_system) {
|
||||
platform = "ohos"
|
||||
}
|
||||
is_declarative = false
|
||||
}
|
||||
|
||||
ace_platform_engine("libace_engine_declarative_qjs") {
|
||||
is_ohos_platform = true
|
||||
use_quickjs_engine = true
|
||||
if (is_standard_system) {
|
||||
platform = "ohos"
|
||||
}
|
||||
is_declarative = true
|
||||
}
|
||||
|
||||
ace_platform_engine("libace_engine_qjs_debug") {
|
||||
is_ohos_platform = true
|
||||
use_quickjs_engine = true
|
||||
use_js_debug = true
|
||||
if (is_standard_system) {
|
||||
platform = "ohos"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,720 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/common/cpp/ace_res_config.h"
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include "unicode/locid.h"
|
||||
|
||||
#include "adapter/common/cpp/ace_res_key_parser.h"
|
||||
#include "base/json/json_util.h"
|
||||
#include "frameworks/bridge/common/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
const std::unordered_map<std::string, std::string> LOCALE_PARENTS {
|
||||
{ "ar-DZ", "ar-015" },
|
||||
{ "ar-EH", "ar-015" },
|
||||
{ "ar-LY", "ar-015" },
|
||||
{ "ar-MA", "ar-015" },
|
||||
{ "ar-TN", "ar-015" },
|
||||
{ "zh-MO", "zh-HK" },
|
||||
{ "en-150", "en-001" },
|
||||
{ "en-AG", "en-001" },
|
||||
{ "en-AI", "en-001" },
|
||||
{ "en-AU", "en-001" },
|
||||
{ "en-BB", "en-001" },
|
||||
{ "en-BE", "en-001" },
|
||||
{ "en-BM", "en-001" },
|
||||
{ "en-BS", "en-001" },
|
||||
{ "en-BZ", "en-001" },
|
||||
{ "en-CC", "en-001" },
|
||||
{ "en-CK", "en-001" },
|
||||
{ "en-CX", "en-001" },
|
||||
{ "en-DG", "en-001" },
|
||||
{ "en-ER", "en-001" },
|
||||
{ "en-FK", "en-001" },
|
||||
{ "en-FM", "en-001" },
|
||||
{ "en-GB", "en-001" },
|
||||
{ "en-GD", "en-001" },
|
||||
{ "en-GG", "en-001" },
|
||||
{ "en-GI", "en-001" },
|
||||
{ "en-GY", "en-001" },
|
||||
{ "en-HK", "en-001" },
|
||||
{ "en-IE", "en-001" },
|
||||
{ "en-IM", "en-001" },
|
||||
{ "en-IN", "en-001" },
|
||||
{ "en-IO", "en-001" },
|
||||
{ "en-JE", "en-001" },
|
||||
{ "en-KI", "en-001" },
|
||||
{ "en-KN", "en-001" },
|
||||
{ "en-KY", "en-001" },
|
||||
{ "en-LC", "en-001" },
|
||||
{ "en-LR", "en-001" },
|
||||
{ "en-LS", "en-001" },
|
||||
{ "en-MM", "en-001" },
|
||||
{ "en-MO", "en-001" },
|
||||
{ "en-MS", "en-001" },
|
||||
{ "en-MT", "en-001" },
|
||||
{ "en-MY", "en-001" },
|
||||
{ "en-NF", "en-001" },
|
||||
{ "en-NR", "en-001" },
|
||||
{ "en-NU", "en-001" },
|
||||
{ "en-NZ", "en-001" },
|
||||
{ "en-PG", "en-001" },
|
||||
{ "en-PK", "en-001" },
|
||||
{ "en-PN", "en-001" },
|
||||
{ "en-PW", "en-001" },
|
||||
{ "en-SB", "en-001" },
|
||||
{ "en-SC", "en-001" },
|
||||
{ "en-SD", "en-001" },
|
||||
{ "en-SG", "en-001" },
|
||||
{ "en-SH", "en-001" },
|
||||
{ "en-SL", "en-001" },
|
||||
{ "en-SS", "en-001" },
|
||||
{ "en-SX", "en-001" },
|
||||
{ "en-SZ", "en-001" },
|
||||
{ "en-TC", "en-001" },
|
||||
{ "en-TK", "en-001" },
|
||||
{ "en-TT", "en-001" },
|
||||
{ "en-TV", "en-001" },
|
||||
{ "en-VC", "en-001" },
|
||||
{ "en-VG", "en-001" },
|
||||
{ "en-WS", "en-001" },
|
||||
{ "en-ZG", "en-001" },
|
||||
{ "es-AR", "es-419" },
|
||||
{ "es-BO", "es-419" },
|
||||
{ "es-BR", "es-419" },
|
||||
{ "es-BZ", "es-419" },
|
||||
{ "es-CL", "es-419" },
|
||||
{ "es-CO", "es-419" },
|
||||
{ "es-CR", "es-419" },
|
||||
{ "es-CU", "es-419" },
|
||||
{ "es-DO", "es-419" },
|
||||
{ "es-EC", "es-419" },
|
||||
{ "es-GT", "es-419" },
|
||||
{ "es-HN", "es-419" },
|
||||
{ "es-MX", "es-419" },
|
||||
{ "es-NI", "es-419" },
|
||||
{ "es-PA", "es-419" },
|
||||
{ "es-PE", "es-419" },
|
||||
{ "es-PR", "es-419" },
|
||||
{ "es-PY", "es-419" },
|
||||
{ "es-SV", "es-419" },
|
||||
{ "es-US", "es-419" },
|
||||
{ "es-UY", "es-419" },
|
||||
{ "es-VE", "es-419" },
|
||||
{ "pt-AO", "pt-PT" },
|
||||
{ "pt-CH", "pt-PT" },
|
||||
{ "pt-CV", "pt-PT" },
|
||||
{ "pt-GQ", "pt-PT" },
|
||||
{ "pt-GW", "pt-PT" },
|
||||
{ "pt-LU", "pt-PT" },
|
||||
{ "pt-MO", "pt-PT" },
|
||||
{ "pt-MZ", "pt-PT" },
|
||||
{ "pt-ST", "pt-PT" },
|
||||
{ "pt-TL", "pt-PT" },
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, std::string> DEFAULT_LANG {
|
||||
{ "es-419", "es-US" },
|
||||
{ "en-Qaag", "en-GB" },
|
||||
{ "en-001", "en-GB" },
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, std::string> LANGUAGE_CODE_MAP {
|
||||
{ "iw", "he" },
|
||||
{ "tl", "fil" },
|
||||
{ "in", "id" },
|
||||
};
|
||||
|
||||
std::string ComputeScript(const AceResConfig& resConfig)
|
||||
{
|
||||
icu::Locale locale(resConfig.language_.c_str(), resConfig.region_.c_str());
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
locale.addLikelySubtags(status);
|
||||
if (status != U_ZERO_ERROR) {
|
||||
return std::string();
|
||||
}
|
||||
return locale.getScript();
|
||||
}
|
||||
|
||||
AceResConfig ConvertLocaleTagToConfig(const std::string& localeTag)
|
||||
{
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(localeTag), status);
|
||||
if (status != U_ZERO_ERROR) {
|
||||
LOGE("This localeTag is not valid.");
|
||||
return AceResConfig("", "", "");
|
||||
}
|
||||
return AceResConfig(locale.getLanguage(), locale.getScript(), locale.getCountry());
|
||||
}
|
||||
|
||||
std::string ConvertLocaleConfigToTag(const AceResConfig& localeConfig)
|
||||
{
|
||||
std::string localeTag = localeConfig.language_;
|
||||
if (!localeConfig.script_.empty()) {
|
||||
localeTag += ('-' + localeConfig.script_);
|
||||
}
|
||||
if (!localeConfig.region_.empty()) {
|
||||
localeTag += ('-' + localeConfig.region_);
|
||||
}
|
||||
return localeTag;
|
||||
}
|
||||
|
||||
bool IsPseudoLocale(const AceResConfig& resConfig)
|
||||
{
|
||||
return (resConfig.language_ == "en" && resConfig.region_ == "XA") ||
|
||||
(resConfig.language_ == "ar" && resConfig.region_ == "XB");
|
||||
}
|
||||
|
||||
void MatchLocaleConfig(const std::vector<AceResConfig>& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
|
||||
std::vector<AceResConfig>& matchedLocaleConfigs)
|
||||
{
|
||||
std::string deviceLanguage = deviceLocaleConfig.language_;
|
||||
std::string deviceScript = deviceLocaleConfig.script_;
|
||||
auto iter = LANGUAGE_CODE_MAP.find(deviceLanguage);
|
||||
if (iter != LANGUAGE_CODE_MAP.end()) {
|
||||
deviceLanguage = iter->second;
|
||||
}
|
||||
for (auto& candidate : candidatesLocaleConfig) {
|
||||
std::string candidateLanguage = candidate.language_;
|
||||
// Languages codes need to be specially handled.
|
||||
auto candidateIter = LANGUAGE_CODE_MAP.find(candidateLanguage);
|
||||
if (candidateIter != LANGUAGE_CODE_MAP.end()) {
|
||||
candidateLanguage = candidateIter->second;
|
||||
}
|
||||
if (candidateLanguage != deviceLanguage) {
|
||||
continue;
|
||||
}
|
||||
if (IsPseudoLocale(candidate)) {
|
||||
if (IsPseudoLocale(deviceLocaleConfig)) {
|
||||
matchedLocaleConfigs.emplace_back(candidate);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (deviceLanguage == "en" && deviceScript == "Qaag") {
|
||||
deviceScript = "Latn";
|
||||
}
|
||||
// Compute Script when it is not provided.
|
||||
std::string candidateScript = candidate.script_.empty() ? ComputeScript(candidate) : candidate.script_;
|
||||
if (deviceScript != candidateScript) {
|
||||
continue;
|
||||
}
|
||||
matchedLocaleConfigs.emplace_back(candidate);
|
||||
}
|
||||
}
|
||||
|
||||
void FindBacktrackPath(
|
||||
const AceResConfig& localeConfig, std::vector<std::string>& backtrackPath, const std::string& localeTag)
|
||||
{
|
||||
if (LOCALE_PARENTS.find(localeTag) != LOCALE_PARENTS.end()) {
|
||||
std::string curTag = LOCALE_PARENTS.find(localeTag)->second;
|
||||
backtrackPath.emplace_back(curTag);
|
||||
FindBacktrackPath(localeConfig, backtrackPath, curTag);
|
||||
} else {
|
||||
backtrackPath.emplace_back(localeConfig.language_);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOnBacktrackingPath(const std::string& bestConfigTag, const std::string& candidateConfigTag,
|
||||
const AceResConfig& bestLocaleConfig, const AceResConfig& candidateLocaleConfig,
|
||||
std::vector<std::string> backtrackPath)
|
||||
{
|
||||
std::vector<std::string> bestConfigBacktrackPaths;
|
||||
FindBacktrackPath(bestLocaleConfig, bestConfigBacktrackPaths, bestConfigTag);
|
||||
std::vector<std::string> candidateConfigBacktrackPaths;
|
||||
FindBacktrackPath(candidateLocaleConfig, candidateConfigBacktrackPaths, candidateConfigTag);
|
||||
int32_t bestConfigIndex = -1;
|
||||
int32_t candidateConfigIndex = -1;
|
||||
for (std::size_t i = 0; i < backtrackPath.size(); i++) {
|
||||
for (const auto& bestConfigPath : bestConfigBacktrackPaths) {
|
||||
if (bestConfigPath == backtrackPath[i] && bestConfigIndex == -1) {
|
||||
bestConfigIndex = i;
|
||||
}
|
||||
}
|
||||
for (const auto& candidateConfigPath : candidateConfigBacktrackPaths) {
|
||||
if (candidateConfigPath == backtrackPath[i] && candidateConfigIndex == -1) {
|
||||
candidateConfigIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bestConfigIndex < candidateConfigIndex) {
|
||||
return (bestConfigIndex == -1);
|
||||
} else if (candidateConfigIndex < bestConfigIndex) {
|
||||
return (candidateConfigIndex != -1);
|
||||
}
|
||||
// Check if candidate and best are on the default area of device's backtracking path.
|
||||
for (auto& path : backtrackPath) {
|
||||
if (DEFAULT_LANG.find(path) != DEFAULT_LANG.end()) {
|
||||
std::string curTag = DEFAULT_LANG.find(path)->second;
|
||||
if (bestConfigTag == curTag) {
|
||||
return false;
|
||||
} else if (candidateConfigTag == curTag) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Compute the default region code through the device language code.
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
icu::Locale locale = icu::Locale::forLanguageTag(icu::StringPiece(backtrackPath[backtrackPath.size() - 1]), status);
|
||||
locale.addLikelySubtags(status);
|
||||
if (status == U_ZERO_ERROR) {
|
||||
if (bestLocaleConfig.region_ == locale.getCountry()) {
|
||||
return false;
|
||||
}
|
||||
if (candidateLocaleConfig.region_ == locale.getCountry()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// If configs did not meet all the conditions above, sort the config region with dictionary order.
|
||||
return strcmp(bestLocaleConfig.region_.c_str(), candidateLocaleConfig.region_.c_str()) >= 0;
|
||||
}
|
||||
|
||||
bool IsLocaleConfigMoreSpecified(const AceResConfig& bestLocaleConfig, const AceResConfig& deviceLocaleConfig,
|
||||
const AceResConfig& candidateLocaleConfig)
|
||||
{
|
||||
// Candidates' language and script are equal with the device's after being filtered MatchLocaleConfig().
|
||||
std::string deviceRegion = deviceLocaleConfig.region_;
|
||||
if (bestLocaleConfig.region_ == deviceRegion) {
|
||||
return false;
|
||||
}
|
||||
if (candidateLocaleConfig.region_ == deviceRegion) {
|
||||
return true;
|
||||
}
|
||||
std::string deviceTag = deviceLocaleConfig.language_ + '-' + deviceLocaleConfig.region_;
|
||||
std::vector<std::string> deviceBacktrackPath;
|
||||
FindBacktrackPath(deviceLocaleConfig, deviceBacktrackPath, deviceTag);
|
||||
std::string bestConfigTag = bestLocaleConfig.language_;
|
||||
if (!bestLocaleConfig.region_.empty()) {
|
||||
bestConfigTag += '-' + bestLocaleConfig.region_;
|
||||
}
|
||||
std::string candidateConfigTag = candidateLocaleConfig.language_;
|
||||
if (!candidateLocaleConfig.region_.empty()) {
|
||||
candidateConfigTag += '-' + candidateLocaleConfig.region_;
|
||||
}
|
||||
int32_t bestConfigIndex = -1;
|
||||
int32_t candidateConfigIndex = -1;
|
||||
for (std::size_t i = 0; i < deviceBacktrackPath.size(); i++) {
|
||||
if (deviceBacktrackPath[i] == bestConfigTag) {
|
||||
bestConfigIndex = i;
|
||||
}
|
||||
if (deviceBacktrackPath[i] == candidateConfigTag) {
|
||||
candidateConfigIndex = i;
|
||||
}
|
||||
}
|
||||
if (bestConfigIndex < candidateConfigIndex) {
|
||||
return (bestConfigIndex == -1);
|
||||
} else if (candidateConfigIndex < bestConfigIndex) {
|
||||
return (candidateConfigIndex != -1);
|
||||
}
|
||||
// Neither best nor candidate on the device's backtracking path, check if they are the default locale of the device.
|
||||
if (candidateConfigIndex == bestConfigIndex && candidateConfigIndex == -1) {
|
||||
std::string deviceTagWithScript = deviceLocaleConfig.language_ + "-" + deviceLocaleConfig.script_;
|
||||
if (DEFAULT_LANG.find(deviceTagWithScript) != DEFAULT_LANG.end()) {
|
||||
std::string defaultTag = DEFAULT_LANG.find(deviceTagWithScript)->second;
|
||||
std::string defaultRegion = defaultTag.substr(defaultTag.find('-') + 1);
|
||||
if (candidateLocaleConfig.region_ == defaultRegion) {
|
||||
return true;
|
||||
}
|
||||
if (bestLocaleConfig.region_ == defaultRegion) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// If they are not on the default area, continue to check the candidates' backtacking path.
|
||||
return IsOnBacktrackingPath(
|
||||
bestConfigTag, candidateConfigTag, bestLocaleConfig, candidateLocaleConfig, deviceBacktrackPath);
|
||||
}
|
||||
// Both best and candidate on the device's backtracking path with same index.
|
||||
return false;
|
||||
}
|
||||
|
||||
void SortLocaleConfigs(std::vector<AceResConfig>& candidatesLocaleConfig, const AceResConfig& deviceLocaleConfig,
|
||||
int32_t left, int32_t right)
|
||||
{
|
||||
if (left < right) {
|
||||
AceResConfig bestLocaleConfig = candidatesLocaleConfig[left];
|
||||
int32_t i = left;
|
||||
int32_t j = right;
|
||||
while (i < j) {
|
||||
while (i < j &&
|
||||
!IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[j])) {
|
||||
j--;
|
||||
}
|
||||
candidatesLocaleConfig[i] = candidatesLocaleConfig[j];
|
||||
while (
|
||||
i < j && IsLocaleConfigMoreSpecified(bestLocaleConfig, deviceLocaleConfig, candidatesLocaleConfig[i])) {
|
||||
i++;
|
||||
}
|
||||
candidatesLocaleConfig[j] = candidatesLocaleConfig[i];
|
||||
}
|
||||
candidatesLocaleConfig[i] = bestLocaleConfig;
|
||||
SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, left, i - 1);
|
||||
SortLocaleConfigs(candidatesLocaleConfig, deviceLocaleConfig, i + 1, right);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLowerResolutionPreferred(int32_t high, int32_t low, int32_t request)
|
||||
{
|
||||
if (request <= low) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (request >= high) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return ((2 * low) - request) * high > request * request; // scaling down is 2x better than up
|
||||
}
|
||||
|
||||
bool IsCandidateResolutionPreferred(
|
||||
const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
|
||||
{
|
||||
if (bestConfig.resolution_ == candidateConfig.resolution_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const ResolutionType bestRes = bestConfig.resolution_ != ResolutionType::RESOLUTION_NONE
|
||||
? bestConfig.resolution_
|
||||
: ResolutionType::RESOLUTION_MDPI;
|
||||
const ResolutionType candidateRes = candidateConfig.resolution_ != ResolutionType::RESOLUTION_NONE
|
||||
? candidateConfig.resolution_
|
||||
: ResolutionType::RESOLUTION_MDPI;
|
||||
|
||||
if (bestRes == ResolutionType::RESOLUTION_ANY) {
|
||||
return false;
|
||||
} else if (candidateRes == ResolutionType::RESOLUTION_ANY) {
|
||||
return true;
|
||||
}
|
||||
|
||||
ResolutionType deviceRes = deviceConfig.resolution_;
|
||||
if (deviceConfig.resolution_ == ResolutionType::RESOLUTION_NONE ||
|
||||
deviceConfig.resolution_ == ResolutionType::RESOLUTION_ANY) {
|
||||
deviceRes = ResolutionType::RESOLUTION_MDPI;
|
||||
}
|
||||
|
||||
if (bestRes > candidateRes) {
|
||||
return IsLowerResolutionPreferred(
|
||||
static_cast<int32_t>(bestRes), static_cast<int32_t>(candidateRes), static_cast<int32_t>(deviceRes));
|
||||
}
|
||||
|
||||
if (bestRes < candidateRes) {
|
||||
return !IsLowerResolutionPreferred(
|
||||
static_cast<int32_t>(candidateRes), static_cast<int32_t>(bestRes), static_cast<int32_t>(deviceRes));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool IsCandidateResConfigPreferred(
|
||||
const AceResConfig& deviceConfig, const AceResConfig& bestConfig, const AceResConfig& candidateConfig)
|
||||
{
|
||||
if ((candidateConfig.mcc_ != bestConfig.mcc_) && deviceConfig.mcc_) {
|
||||
return candidateConfig.mcc_;
|
||||
}
|
||||
if ((candidateConfig.mnc_ != bestConfig.mnc_) && deviceConfig.mnc_) {
|
||||
return candidateConfig.mnc_;
|
||||
}
|
||||
|
||||
if (bestConfig.orientation_ != candidateConfig.orientation_ &&
|
||||
deviceConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
|
||||
return candidateConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED;
|
||||
}
|
||||
|
||||
if (bestConfig.deviceType_ != DeviceType::UNKNOWN || candidateConfig.deviceType_ != DeviceType::UNKNOWN) {
|
||||
if (bestConfig.deviceType_ != candidateConfig.deviceType_) {
|
||||
return candidateConfig.deviceType_ != DeviceType::UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
if (bestConfig.colorMode_ != candidateConfig.colorMode_) {
|
||||
return candidateConfig.colorMode_ == deviceConfig.colorMode_;
|
||||
}
|
||||
|
||||
return IsCandidateResolutionPreferred(deviceConfig, bestConfig, candidateConfig);
|
||||
}
|
||||
|
||||
void SortResConfigs(
|
||||
const AceResConfig& desiredConfig, std::vector<AceResConfig>& candidateConfigs, int32_t left, int32_t right)
|
||||
{
|
||||
if (left < right) {
|
||||
AceResConfig bestConfig = candidateConfigs[left];
|
||||
int32_t i = left;
|
||||
int32_t j = right;
|
||||
while (i < j) {
|
||||
while (i < j && !IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[j])) {
|
||||
j--;
|
||||
}
|
||||
candidateConfigs[i] = candidateConfigs[j];
|
||||
while (i < j && IsCandidateResConfigPreferred(desiredConfig, bestConfig, candidateConfigs[i])) {
|
||||
i++;
|
||||
}
|
||||
candidateConfigs[j] = candidateConfigs[i];
|
||||
}
|
||||
candidateConfigs[i] = bestConfig;
|
||||
SortResConfigs(desiredConfig, candidateConfigs, left, i - 1);
|
||||
SortResConfigs(desiredConfig, candidateConfigs, i + 1, right);
|
||||
}
|
||||
}
|
||||
|
||||
bool IsOrientationMatch(const AceResConfig& desired, const AceResConfig& supported)
|
||||
{
|
||||
return supported.orientation_ == DeviceOrientation::ORIENTATION_UNDEFINED ||
|
||||
supported.orientation_ == desired.orientation_;
|
||||
}
|
||||
|
||||
bool IsDeviceTypeMatch(const AceResConfig& desired, const AceResConfig& supported)
|
||||
{
|
||||
return supported.deviceType_ == DeviceType::UNKNOWN || supported.deviceType_ == desired.deviceType_;
|
||||
}
|
||||
|
||||
bool IsColorModeMatch(const AceResConfig& desired, const AceResConfig& supported)
|
||||
{
|
||||
return supported.colorMode_ == ColorMode::COLOR_MODE_UNDEFINED || supported.colorMode_ == desired.colorMode_;
|
||||
}
|
||||
|
||||
bool IsMccMncMatch(const AceResConfig& desired, const AceResConfig& supported)
|
||||
{
|
||||
if (supported.mcc_ != 0 && supported.mcc_ != desired.mcc_) {
|
||||
return false;
|
||||
}
|
||||
return !(supported.mnc_ != 0 && supported.mnc_ != desired.mnc_);
|
||||
}
|
||||
|
||||
bool IsResolutionMatch(const AceResConfig& desired, const AceResConfig& supported)
|
||||
{
|
||||
return supported.resolution_ == ResolutionType::RESOLUTION_NONE || supported.resolution_ == desired.resolution_;
|
||||
}
|
||||
|
||||
bool MatchResConfig(const AceResConfig& desired, const AceResConfig& supported)
|
||||
{
|
||||
return !(!IsOrientationMatch(desired, supported) || !IsDeviceTypeMatch(desired, supported) ||
|
||||
!IsColorModeMatch(desired, supported) || !IsMccMncMatch(desired, supported) ||
|
||||
!IsResolutionMatch(desired, supported));
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AceResConfig::operator==(const AceResConfig& other) const
|
||||
{
|
||||
return language_ == other.language_ && script_ == other.script_ && region_ == other.region_ && mcc_ == other.mcc_ &&
|
||||
mnc_ == other.mnc_ && orientation_ == other.orientation_ && colorMode_ == other.colorMode_ &&
|
||||
deviceType_ == other.deviceType_ && resolution_ == other.resolution_;
|
||||
}
|
||||
|
||||
void AceResConfig::MatchAndSortI18nConfigs(const std::vector<std::string>& candidatesFiles,
|
||||
const std::string& devicesLocaleTag, std::vector<std::string>& fileList)
|
||||
{
|
||||
std::vector<AceResConfig> candidateLocaleConfigs;
|
||||
for (auto& file : candidatesFiles) {
|
||||
AceResConfig LocaleConfig = ConvertLocaleTagToConfig(file);
|
||||
if (file == ConvertLocaleConfigToTag(LocaleConfig)) {
|
||||
candidateLocaleConfigs.emplace_back(LocaleConfig);
|
||||
}
|
||||
}
|
||||
AceResConfig deviceLocaleConfig = ConvertLocaleTagToConfig(devicesLocaleTag);
|
||||
// Compute Script when it is not provided.
|
||||
if (deviceLocaleConfig.script_.empty()) {
|
||||
deviceLocaleConfig.script_ = ComputeScript(deviceLocaleConfig);
|
||||
}
|
||||
std::vector<AceResConfig> matchedLocaleConfigs;
|
||||
MatchLocaleConfig(candidateLocaleConfigs, deviceLocaleConfig, matchedLocaleConfigs);
|
||||
int32_t left = 0;
|
||||
int32_t right = matchedLocaleConfigs.size() - 1;
|
||||
SortLocaleConfigs(matchedLocaleConfigs, deviceLocaleConfig, left, right);
|
||||
bool existDefault = false;
|
||||
for (const auto& matchedLocaleConfig : matchedLocaleConfigs) {
|
||||
std::string localeConfigTag = ConvertLocaleConfigToTag(matchedLocaleConfig);
|
||||
if (localeConfigTag == "en-US") {
|
||||
existDefault = true;
|
||||
}
|
||||
fileList.emplace_back(localeConfigTag);
|
||||
}
|
||||
|
||||
if (!existDefault) {
|
||||
fileList.emplace_back("en-US");
|
||||
}
|
||||
}
|
||||
|
||||
void AceResConfig::MatchAndSortResConfigs(const std::vector<std::string>& candidateFiles,
|
||||
const std::string& deviceResTag, std::vector<std::string>& matchedFileList)
|
||||
{
|
||||
std::vector<AceResConfig> candidateResConfigs;
|
||||
for (auto& file : candidateFiles) {
|
||||
AceResConfig ResConfig = ConvertResTagToConfig(file);
|
||||
if (file == ConvertResConfigToTag(ResConfig)) {
|
||||
candidateResConfigs.emplace_back(ResConfig);
|
||||
}
|
||||
}
|
||||
|
||||
AceResConfig deviceResConfig = ConvertResTagToConfig(deviceResTag);
|
||||
int32_t candidateConfigSize = candidateResConfigs.size();
|
||||
std::vector<AceResConfig> matchedResConfigs;
|
||||
for (auto i = 0; i < candidateConfigSize; i++) {
|
||||
if (!MatchResConfig(deviceResConfig, candidateResConfigs[i])) {
|
||||
continue;
|
||||
} else {
|
||||
matchedResConfigs.emplace_back(candidateResConfigs[i]);
|
||||
}
|
||||
}
|
||||
int32_t left = 0;
|
||||
int32_t right = matchedResConfigs.size() - 1;
|
||||
SortResConfigs(deviceResConfig, matchedResConfigs, left, right);
|
||||
for (const auto& matchedConfig : matchedResConfigs) {
|
||||
matchedFileList.emplace_back(ConvertResConfigToTag(matchedConfig));
|
||||
}
|
||||
matchedFileList.emplace_back("res-defaults");
|
||||
}
|
||||
|
||||
void AceResConfig::GetConfigString(KeyType type, int32_t value, std::string& buf)
|
||||
{
|
||||
std::string appending;
|
||||
if (!buf.empty()) {
|
||||
appending = "-";
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case KeyType::ORIENTATION:
|
||||
appending.append(
|
||||
AceResKeyParser::GetInstance().GetOrientationByType(static_cast<DeviceOrientation>(value)));
|
||||
break;
|
||||
case KeyType::DEVICETYPE:
|
||||
appending.append(AceResKeyParser::GetInstance().GetDeviceByType(static_cast<DeviceType>(value)));
|
||||
break;
|
||||
case KeyType::RESOLUTION:
|
||||
appending.append(AceResKeyParser::GetInstance().GetResolutionByType(static_cast<ResolutionType>(value)));
|
||||
break;
|
||||
case KeyType::COLOR_MODE:
|
||||
appending.append(AceResKeyParser::GetInstance().GetColorModeByType(static_cast<ColorMode>(value)));
|
||||
break;
|
||||
case KeyType::MCC:
|
||||
appending.append(AceResKeyParser::GetInstance().GetMccByValue(value));
|
||||
break;
|
||||
case KeyType::MNC_SHORT_LEN:
|
||||
appending.append(AceResKeyParser::GetInstance().GetMncShortLenByValue(value));
|
||||
break;
|
||||
case KeyType::MNC:
|
||||
appending.append(AceResKeyParser::GetInstance().GetMncByValue(value));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
buf.append(appending);
|
||||
}
|
||||
|
||||
bool AceResConfig::ParseConfig(const std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
for (auto keyParam : keyParams) {
|
||||
switch (keyParam.keyType) {
|
||||
case KeyType::RESOLUTION:
|
||||
resolution_ = static_cast<ResolutionType>(keyParam.value);
|
||||
break;
|
||||
case KeyType::ORIENTATION:
|
||||
orientation_ = static_cast<DeviceOrientation>(keyParam.value);
|
||||
break;
|
||||
case KeyType::DEVICETYPE:
|
||||
deviceType_ = static_cast<DeviceType>(keyParam.value);
|
||||
break;
|
||||
case KeyType::COLOR_MODE:
|
||||
colorMode_ = static_cast<ColorMode>(keyParam.value);
|
||||
break;
|
||||
case KeyType::MCC:
|
||||
mcc_ = keyParam.value;
|
||||
break;
|
||||
case KeyType::MNC:
|
||||
mnc_ = keyParam.value;
|
||||
break;
|
||||
case KeyType::MNC_SHORT_LEN:
|
||||
mnc_ = keyParam.value;
|
||||
mncShortLen_ = true;
|
||||
break;
|
||||
default:
|
||||
LOGE("unknown KeyType:%{public}d", keyParam.keyType);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
ResolutionType AceResConfig::GetResolutionType(double resolution)
|
||||
{
|
||||
static const LinearEnumMapNode<ResolutionType, bool (*)(double)> resolutionMap[] = {
|
||||
{ ResolutionType::RESOLUTION_LDPI,
|
||||
[](double resolution) { return GreatNotEqual(resolution, 0.0) && LessNotEqual(resolution, 0.875); } },
|
||||
{ ResolutionType::RESOLUTION_MDPI,
|
||||
[](double resolution) { return GreatOrEqual(resolution, 0.875) && LessNotEqual(resolution, 1.25); } },
|
||||
{ ResolutionType::RESOLUTION_HDPI,
|
||||
[](double resolution) { return GreatOrEqual(resolution, 1.25) && LessNotEqual(resolution, 1.75); } },
|
||||
{ ResolutionType::RESOLUTION_XHDPI,
|
||||
[](double resolution) { return GreatOrEqual(resolution, 1.75) && LessNotEqual(resolution, 2.5); } },
|
||||
{ ResolutionType::RESOLUTION_XXHDPI,
|
||||
[](double resolution) { return GreatOrEqual(resolution, 2.5) && LessNotEqual(resolution, 3.5); } },
|
||||
{ ResolutionType::RESOLUTION_XXXHDPI, [](double resolution) { return GreatOrEqual(resolution, 3.5); } },
|
||||
};
|
||||
|
||||
for (const auto& idx : resolutionMap) {
|
||||
if (idx.value(resolution)) {
|
||||
return idx.key;
|
||||
}
|
||||
}
|
||||
return ResolutionType::RESOLUTION_MDPI;
|
||||
}
|
||||
|
||||
AceResConfig AceResConfig::ConvertResTagToConfig(const std::string& deviceResConfigTag)
|
||||
{
|
||||
AceResConfig resConfig;
|
||||
std::vector<KeyParam> keyParams;
|
||||
bool parseSucceed = AceResKeyParser::GetInstance().Parse(deviceResConfigTag, keyParams);
|
||||
if (parseSucceed) {
|
||||
resConfig.ParseConfig(keyParams);
|
||||
}
|
||||
return resConfig;
|
||||
}
|
||||
|
||||
std::string AceResConfig::ConvertResConfigToTag(const AceResConfig& resConfig)
|
||||
{
|
||||
std::string resTag = "res";
|
||||
if (resConfig.mcc_ != MCC_UNDEFINED && resConfig.mnc_ != MNC_UNDEFINED) {
|
||||
GetConfigString(KeyType::MCC, resConfig.mcc_, resTag);
|
||||
if (resConfig.mncShortLen_) {
|
||||
GetConfigString(KeyType::MNC_SHORT_LEN, resConfig.mnc_, resTag);
|
||||
} else {
|
||||
GetConfigString(KeyType::MNC, resConfig.mnc_, resTag);
|
||||
}
|
||||
}
|
||||
|
||||
if (resConfig.orientation_ != DeviceOrientation::ORIENTATION_UNDEFINED) {
|
||||
GetConfigString(KeyType::ORIENTATION, static_cast<int32_t>(resConfig.orientation_), resTag);
|
||||
}
|
||||
|
||||
if (resConfig.colorMode_ != ColorMode::COLOR_MODE_UNDEFINED) {
|
||||
GetConfigString(KeyType::COLOR_MODE, static_cast<int32_t>(resConfig.colorMode_), resTag);
|
||||
}
|
||||
|
||||
if (resConfig.deviceType_ != DeviceType::UNKNOWN) {
|
||||
GetConfigString(KeyType::DEVICETYPE, static_cast<int32_t>(resConfig.deviceType_), resTag);
|
||||
}
|
||||
|
||||
if (resConfig.resolution_ != ResolutionType::RESOLUTION_NONE) {
|
||||
GetConfigString(KeyType::RESOLUTION, static_cast<int32_t>(resConfig.resolution_), resTag);
|
||||
}
|
||||
return resTag;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_CONFIG_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_CONFIG_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "adapter/common/cpp/ace_res_data_struct.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
class AceResConfig {
|
||||
public:
|
||||
AceResConfig() = default;
|
||||
~AceResConfig() = default;
|
||||
AceResConfig(const AceResConfig& config) = default;
|
||||
AceResConfig& operator=(const AceResConfig& config) = default;
|
||||
AceResConfig(const std::string& language, const std::string& script, const std::string& region)
|
||||
: language_(language), script_(script), region_(region)
|
||||
{}
|
||||
|
||||
AceResConfig(int32_t mcc, int32_t mnc, DeviceOrientation orientation, ColorMode colorMode, DeviceType deviceType,
|
||||
ResolutionType resolution)
|
||||
: mcc_(mcc), mnc_(mnc), orientation_(orientation), colorMode_(colorMode), deviceType_(deviceType),
|
||||
resolution_(resolution)
|
||||
{}
|
||||
|
||||
bool operator==(const AceResConfig& other) const;
|
||||
static void MatchAndSortI18nConfigs(const std::vector<std::string>& candidatesFiles,
|
||||
const std::string& devicesLocaleTag, std::vector<std::string>& fileList);
|
||||
static void MatchAndSortResConfigs(const std::vector<std::string>& candidateFiles,
|
||||
const std::string& deviceConfigTag, std::vector<std::string>& viableFileList);
|
||||
static void GetConfigString(KeyType type, int32_t value, std::string& buf);
|
||||
bool ParseConfig(const std::vector<KeyParam>& keyParams);
|
||||
static ResolutionType GetResolutionType(double resolution);
|
||||
static AceResConfig ConvertResTagToConfig(const std::string& deviceResConfigTag);
|
||||
static std::string ConvertResConfigToTag(const AceResConfig& resConfig);
|
||||
|
||||
std::string language_;
|
||||
std::string script_;
|
||||
std::string region_;
|
||||
int32_t mcc_ = MCC_UNDEFINED;
|
||||
int32_t mnc_ = MNC_UNDEFINED;
|
||||
bool mncShortLen_ = false;
|
||||
DeviceOrientation orientation_ = DeviceOrientation::ORIENTATION_UNDEFINED;
|
||||
ColorMode colorMode_ = ColorMode::COLOR_MODE_UNDEFINED;
|
||||
DeviceType deviceType_ = DeviceType::UNKNOWN;
|
||||
ResolutionType resolution_ = ResolutionType::RESOLUTION_NONE;
|
||||
};
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_CONFIG_H
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_DATA_STRUCT_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_DATA_STRUCT_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/utils/system_properties.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
enum class KeyType : int32_t {
|
||||
MCC = 0,
|
||||
MNC = 1,
|
||||
MNC_SHORT_LEN = 2,
|
||||
ORIENTATION = 3,
|
||||
COLOR_MODE = 4,
|
||||
DEVICETYPE = 5,
|
||||
RESOLUTION = 6,
|
||||
};
|
||||
|
||||
struct KeyParam {
|
||||
KeyType keyType;
|
||||
int32_t value;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_DATA_STRUCT_H
|
||||
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/common/cpp/ace_res_key_parser.h"
|
||||
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
#include <cstdio>
|
||||
#else
|
||||
#include "securec.h"
|
||||
#endif
|
||||
#include <regex>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/string_utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t MCC_MNC_KEYWORD_LEN = 3;
|
||||
constexpr int32_t MCC_MNC_VALUE_LEN = 3;
|
||||
constexpr int32_t MAX_MCC_MNC_LEN = 8;
|
||||
|
||||
const std::unordered_map<std::string, ResolutionType> RES_RESOLUTION = {
|
||||
{ "ldpi", ResolutionType::RESOLUTION_LDPI },
|
||||
{ "mdpi", ResolutionType::RESOLUTION_MDPI },
|
||||
{ "hdpi", ResolutionType::RESOLUTION_HDPI },
|
||||
{ "xhdpi", ResolutionType::RESOLUTION_XHDPI },
|
||||
{ "xxhdpi", ResolutionType::RESOLUTION_XXHDPI },
|
||||
{ "xxxhdpi", ResolutionType::RESOLUTION_XXXHDPI },
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, DeviceOrientation> RES_ORIENTATION = {
|
||||
{ "horizontal", DeviceOrientation::LANDSCAPE },
|
||||
{ "vertical", DeviceOrientation::PORTRAIT }
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, ColorMode> RES_COLOR_MODE = {
|
||||
{ "dark", ColorMode::DARK },
|
||||
};
|
||||
|
||||
const std::unordered_map<std::string, DeviceType> RES_DEVICE_TYPE = {
|
||||
{ "phone", DeviceType::PHONE },
|
||||
{ "tablet", DeviceType::TABLET },
|
||||
{ "tv", DeviceType::TV },
|
||||
{ "wearable", DeviceType::WATCH },
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
AceResKeyParser::AceResKeyParser() = default;
|
||||
AceResKeyParser::~AceResKeyParser() = default;
|
||||
|
||||
bool AceResKeyParser::Parse(const std::string& deviceResConfigTag, std::vector<KeyParam> &keyParams)
|
||||
{
|
||||
std::vector<std::string> keyParts;
|
||||
StringUtils::StringSpliter(deviceResConfigTag, '-', keyParts);
|
||||
|
||||
static parse_key_function functions[] = {
|
||||
ParseMcc,
|
||||
ParseMnc,
|
||||
ParseOrientation,
|
||||
ParseColorMode,
|
||||
ParseDeviceType,
|
||||
ParseResolution,
|
||||
ParseDefaults,
|
||||
};
|
||||
const int32_t FUNC_LEN = sizeof(functions) / sizeof(functions[0]);
|
||||
if (!keyParts.empty()) {
|
||||
if (!ParseMatch(keyParts, keyParams, functions, FUNC_LEN)) {
|
||||
LOGE("Invalid config:%{public}s", deviceResConfigTag.c_str());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseMatch(const std::vector<std::string>& keys, std::vector<KeyParam> &keyParams,
|
||||
parse_key_function functions[], int32_t funcLen) const
|
||||
{
|
||||
for (auto iter = keys.begin(); iter != keys.end(); iter++) {
|
||||
// currently, the first key part must be res
|
||||
if (iter == keys.begin()) {
|
||||
if (*iter == "res") {
|
||||
continue;
|
||||
} else {
|
||||
LOGE("Invalid first key part:%{private}s", iter->c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
bool parseRet = false;
|
||||
for (int32_t k = 0; k < funcLen; k++) {
|
||||
if (functions[k](*iter, keyParams)) {
|
||||
parseRet = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!parseRet) {
|
||||
LOGE("Invalid key:%{private}s", iter->c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseMcc(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
std::regex mcc("mcc(\\d{3})");
|
||||
if (regex_match(key, mcc)) {
|
||||
KeyParam keyParam;
|
||||
keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
|
||||
keyParam.keyType = KeyType::MCC;
|
||||
keyParams.emplace_back(keyParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseMnc(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
std::regex mnc("mnc(\\d{2,3})");
|
||||
if (regex_match(key, mnc)) {
|
||||
KeyParam keyParam;
|
||||
keyParam.value = StringUtils::StringToInt(key.substr(MCC_MNC_KEYWORD_LEN));
|
||||
if (key.substr(MCC_MNC_KEYWORD_LEN).length() == MCC_MNC_VALUE_LEN) {
|
||||
keyParam.keyType = KeyType::MNC;
|
||||
} else {
|
||||
keyParam.keyType = KeyType::MNC_SHORT_LEN;
|
||||
}
|
||||
keyParams.emplace_back(keyParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseOrientation(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
auto iter = RES_ORIENTATION.find(key);
|
||||
if (iter != RES_ORIENTATION.end()) {
|
||||
KeyParam keyParam;
|
||||
keyParam.keyType = KeyType::ORIENTATION;
|
||||
keyParam.value = static_cast<int32_t>(iter->second);
|
||||
keyParams.emplace_back(keyParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseColorMode(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
auto iter = RES_COLOR_MODE.find(key);
|
||||
if (iter != RES_COLOR_MODE.end()) {
|
||||
KeyParam keyParam;
|
||||
keyParam.keyType = KeyType::COLOR_MODE;
|
||||
keyParam.value = static_cast<int32_t>(iter->second);
|
||||
keyParams.emplace_back(keyParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseDeviceType(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
auto iter = RES_DEVICE_TYPE.find(key);
|
||||
if (iter != RES_DEVICE_TYPE.end()) {
|
||||
KeyParam keyParam;
|
||||
keyParam.keyType = KeyType::DEVICETYPE;
|
||||
keyParam.value = static_cast<int32_t>(iter->second);
|
||||
keyParams.emplace_back(keyParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseResolution(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
auto iter = RES_RESOLUTION.find(key);
|
||||
if (iter != RES_RESOLUTION.end()) {
|
||||
KeyParam keyParam;
|
||||
keyParam.keyType = KeyType::RESOLUTION;
|
||||
keyParam.value = static_cast<int32_t>(iter->second);
|
||||
keyParams.emplace_back(keyParam);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceResKeyParser::ParseDefaults(const std::string& key, std::vector<KeyParam>& keyParams)
|
||||
{
|
||||
return key == "defaults";
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetMccByValue(uint32_t value) const
|
||||
{
|
||||
char mccStr[MAX_MCC_MNC_LEN] = {0};
|
||||
if (sprintf_s(mccStr, MAX_MCC_MNC_LEN, "mcc%03d", value) < 0) {
|
||||
LOGE("output mcc exception");
|
||||
return "";
|
||||
}
|
||||
return std::string(mccStr);
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetMncShortLenByValue(uint32_t value) const
|
||||
{
|
||||
char mncStr[MAX_MCC_MNC_LEN] = {0};
|
||||
if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%02d", value) < 0) {
|
||||
LOGE("output mnc short len exception");
|
||||
return "";
|
||||
}
|
||||
return std::string(mncStr);
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetMncByValue(uint32_t value) const
|
||||
{
|
||||
char mncStr[MAX_MCC_MNC_LEN] = {0};
|
||||
if (sprintf_s(mncStr, MAX_MCC_MNC_LEN, "mnc%03d", value) < 0) {
|
||||
LOGE("output mnc len exception");
|
||||
return "";
|
||||
}
|
||||
return std::string(mncStr);
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetOrientationByType(DeviceOrientation type) const
|
||||
{
|
||||
auto item = find_if(RES_ORIENTATION.begin(), RES_ORIENTATION.end(),
|
||||
[type](auto iter) { return iter.second == type; });
|
||||
if (item != RES_ORIENTATION.end()) {
|
||||
return item->first;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetColorModeByType(ColorMode type) const
|
||||
{
|
||||
auto item = find_if(RES_COLOR_MODE.begin(), RES_COLOR_MODE.end(),
|
||||
[type](auto iter) { return iter.second == type; });
|
||||
if (item != RES_COLOR_MODE.end()) {
|
||||
return item->first;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetDeviceByType(DeviceType type) const
|
||||
{
|
||||
auto deviceTypeItem = find_if(RES_DEVICE_TYPE.begin(), RES_DEVICE_TYPE.end(),
|
||||
[type](auto iter) { return iter.second == type; });
|
||||
if (deviceTypeItem != RES_DEVICE_TYPE.end()) {
|
||||
return deviceTypeItem->first;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string AceResKeyParser::GetResolutionByType(ResolutionType type) const
|
||||
{
|
||||
auto resolutionItem = find_if(RES_RESOLUTION.begin(), RES_RESOLUTION.end(),
|
||||
[type](auto iter) { return iter.second == type; });
|
||||
if (resolutionItem != RES_RESOLUTION.end()) {
|
||||
return resolutionItem->first;
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_KEY_PARSER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_KEY_PARSER_H
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "adapter/common/cpp/ace_res_data_struct.h"
|
||||
#include "base/utils/singleton.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
using parse_key_function = std::function<bool(const std::string&, std::vector<KeyParam>&)>;
|
||||
|
||||
class AceResKeyParser final : public Singleton<AceResKeyParser> {
|
||||
DECLARE_SINGLETON(AceResKeyParser);
|
||||
ACE_DISALLOW_MOVE(AceResKeyParser);
|
||||
|
||||
public:
|
||||
bool Parse(const std::string& deviceResConfigTag, std::vector<KeyParam>& keyParams);
|
||||
std::string GetMccByValue(uint32_t value) const;
|
||||
std::string GetMncByValue(uint32_t value) const;
|
||||
std::string GetMncShortLenByValue(uint32_t value) const;
|
||||
std::string GetOrientationByType(DeviceOrientation type) const;
|
||||
std::string GetColorModeByType(ColorMode type) const;
|
||||
std::string GetDeviceByType(DeviceType type) const;
|
||||
std::string GetResolutionByType(ResolutionType type) const;
|
||||
|
||||
private:
|
||||
bool ParseMatch(const std::vector<std::string>& keys, std::vector<KeyParam>& keyParams,
|
||||
parse_key_function functions[], int32_t funcLen) const;
|
||||
static bool ParseMcc(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
static bool ParseMnc(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
static bool ParseOrientation(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
static bool ParseColorMode(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
static bool ParseDeviceType(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
static bool ParseResolution(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
static bool ParseDefaults(const std::string& key, std::vector<KeyParam>& keyParams);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_RES_KEY_PARSER_H
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/ace_trace.h"
|
||||
|
||||
#ifndef WINDOWS_PLATFORM
|
||||
#include "securec.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
const size_t MAX_STRING_SIZE = 128;
|
||||
|
||||
}
|
||||
|
||||
bool AceTraceBeginWithArgv(const char* format, va_list args)
|
||||
{
|
||||
char name[MAX_STRING_SIZE] = { 0 };
|
||||
if (vsnprintf_s(name, sizeof(name), sizeof(name) - 1, format, args) < 0) {
|
||||
return false;
|
||||
}
|
||||
AceTraceBegin(name);
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/common/cpp/file_asset_provider.h"
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "base/log/ace_trace.h"
|
||||
#include "base/log/log.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
FileAssetProvider::~FileAssetProvider()
|
||||
{
|
||||
}
|
||||
|
||||
bool FileAssetProvider::Initialize(const std::string& packagePath, const std::vector<std::string>& assetBasePaths)
|
||||
{
|
||||
ACE_SCOPED_TRACE("Initialize");
|
||||
if (packagePath.empty() || assetBasePaths.empty()) {
|
||||
LOGE("the packagePath or assetBasePath is empty");
|
||||
return false;
|
||||
}
|
||||
assetBasePaths_ = assetBasePaths;
|
||||
packagePath_ = packagePath;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FileAssetProvider::IsValid() const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
class FileAssetMapping : public fml::Mapping {
|
||||
public:
|
||||
FileAssetMapping(std::unique_ptr<uint8_t[]> data, size_t size) : data_(std::move(data)), size_(size) {}
|
||||
|
||||
~FileAssetMapping() override {}
|
||||
|
||||
size_t GetSize() const override
|
||||
{
|
||||
return size_;
|
||||
}
|
||||
|
||||
const uint8_t* GetMapping() const override
|
||||
{
|
||||
return data_.get();
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<uint8_t[]> data_ = nullptr;
|
||||
size_t size_ = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<fml::Mapping> FileAssetProvider::GetAsMapping(const std::string& assetName) const
|
||||
{
|
||||
ACE_SCOPED_TRACE("GetAsMapping");
|
||||
LOGD("assert name is: %{public}s", assetName.c_str());
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
|
||||
for (const auto& basePath: assetBasePaths_) {
|
||||
std::string fileName = packagePath_ + basePath + assetName;
|
||||
std::FILE* fp = std::fopen(fileName.c_str(), "r");
|
||||
if (fp == nullptr) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (std::fseek(fp, 0, SEEK_END) != 0) {
|
||||
LOGE("seek file tail error");
|
||||
std::fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
long size = std::ftell(fp);
|
||||
uint8_t* dataArray = new (std::nothrow) uint8_t[size];
|
||||
if (dataArray == nullptr) {
|
||||
LOGE("new uint8_t array failed");
|
||||
std::fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
rewind(fp);
|
||||
std::unique_ptr<uint8_t[]> data(dataArray);
|
||||
size_t result = std::fread(data.get(), 1, size, fp);
|
||||
if (result != (size_t)size) {
|
||||
LOGE("read file failed");
|
||||
std::fclose(fp);
|
||||
continue;
|
||||
}
|
||||
|
||||
fclose(fp);
|
||||
return std::make_unique<FileAssetMapping>(std::move(data), size);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
std::string FileAssetProvider::GetAssetPath(const std::string& assetName)
|
||||
{
|
||||
auto filePath = filePathMap_.find(assetName);
|
||||
if (filePath == filePathMap_.end()) {
|
||||
return "";
|
||||
}
|
||||
std::string assetPath;
|
||||
assetPath.append(packagePath_).append("!/").append(filePath->second);
|
||||
return assetPath;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_FILE_ASSET_PROVIDER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_FILE_ASSET_PROVIDER_H
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#include "contrib/minizip/unzip.h"
|
||||
#include "flutter/assets/asset_resolver.h"
|
||||
#include "flutter/fml/mapping.h"
|
||||
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class ACE_EXPORT FileAssetProvider : public flutter::AssetResolver {
|
||||
public:
|
||||
FileAssetProvider() = default;
|
||||
~FileAssetProvider() override;
|
||||
|
||||
bool Initialize(const std::string& packagePath, const std::vector<std::string>& assetBasePaths);
|
||||
|
||||
bool IsValid() const override;
|
||||
|
||||
std::unique_ptr<fml::Mapping> GetAsMapping(const std::string& assetName) const override;
|
||||
|
||||
std::string GetAssetPath(const std::string& assetName);
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, uint64_t> fileMap_;
|
||||
mutable std::mutex mutex_;
|
||||
std::unordered_map<std::string, std::string> filePathMap_;
|
||||
std::string packagePath_;
|
||||
std::vector<std::string> assetBasePaths_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_FILE_ASSET_PROVIDER_H
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_ASSET_MANAGER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_ASSET_MANAGER_H
|
||||
|
||||
#include <deque>
|
||||
|
||||
#include "flutter/assets/asset_resolver.h"
|
||||
#include "flutter/fml/mapping.h"
|
||||
|
||||
#include "base/log/event_report.h"
|
||||
#include "base/memory/ace_type.h"
|
||||
#include "base/resource/asset_manager.h"
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class FlutterAsset final : public Asset {
|
||||
public:
|
||||
explicit FlutterAsset(std::unique_ptr<fml::Mapping> mapping) : mapping_(std::move(mapping)) {}
|
||||
~FlutterAsset() override = default;
|
||||
|
||||
size_t GetSize() const override
|
||||
{
|
||||
return mapping_ ? mapping_->GetSize() : 0;
|
||||
}
|
||||
|
||||
const uint8_t* GetData() const override
|
||||
{
|
||||
return mapping_ ? mapping_->GetMapping() : nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<fml::Mapping> mapping_;
|
||||
};
|
||||
|
||||
class FlutterAssetManager final : public AssetManager {
|
||||
DECLARE_ACE_TYPE(FlutterAssetManager, AssetManager);
|
||||
|
||||
public:
|
||||
FlutterAssetManager() = default;
|
||||
~FlutterAssetManager() override = default;
|
||||
|
||||
void PushFront(std::unique_ptr<flutter::AssetResolver> provider)
|
||||
{
|
||||
if (!provider || !provider->IsValid()) {
|
||||
return;
|
||||
}
|
||||
providers_.push_front(std::move(provider));
|
||||
}
|
||||
|
||||
void PushBack(std::unique_ptr<flutter::AssetResolver> provider)
|
||||
{
|
||||
if (!provider || !provider->IsValid()) {
|
||||
return;
|
||||
}
|
||||
providers_.push_back(std::move(provider));
|
||||
}
|
||||
|
||||
RefPtr<Asset> GetAsset(const std::string& assetName) override
|
||||
{
|
||||
if (assetName.empty()) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
for (const auto& provider : providers_) {
|
||||
auto mapping = provider->GetAsMapping(assetName);
|
||||
if (mapping) {
|
||||
return AceType::MakeRefPtr<FlutterAsset>(std::move(mapping));
|
||||
}
|
||||
}
|
||||
LOGE("find asset failed, assetName = %{private}s", assetName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
std::deque<std::unique_ptr<flutter::AssetResolver>> providers_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_ASSET_MANAGER_H
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/common/cpp/flutter_task_executor.h"
|
||||
|
||||
#include <cerrno>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef FML_EMBEDDER_ONLY
|
||||
#undef FML_EMBEDDER_ONLY
|
||||
#define FML_EMBEDDER_ONLY
|
||||
#endif
|
||||
#include "flutter/fml/message_loop.h"
|
||||
#include "flutter/shell/platform/ohos/platform_task_runner_adapter.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "base/thread/background_task_executor.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t GPU_THREAD_PRIORITY = -10;
|
||||
constexpr int32_t UI_THREAD_PRIORITY = -8;
|
||||
|
||||
inline std::string GenJsThreadName()
|
||||
{
|
||||
static std::atomic<uint32_t> instanceCount { 1 };
|
||||
return std::string("jsThread-") + std::to_string(instanceCount.fetch_add(1, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
bool PostTaskToTaskRunner(const fml::RefPtr<fml::TaskRunner>& taskRunner, TaskExecutor::Task&& task, uint32_t delayTime)
|
||||
{
|
||||
if (!taskRunner || !task) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (delayTime > 0) {
|
||||
taskRunner->PostDelayedTask(std::move(task), fml::TimeDelta::FromMilliseconds(delayTime));
|
||||
} else {
|
||||
taskRunner->PostTask(std::move(task));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void SetThreadPriority(int32_t priority)
|
||||
{
|
||||
if (setpriority(PRIO_PROCESS, gettid(), priority) < 0) {
|
||||
LOGW("Failed to set thread priority, errno = %{private}d", errno);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FlutterTaskExecutor::~FlutterTaskExecutor()
|
||||
{
|
||||
// To guarantee the jsThread released in platform thread
|
||||
auto rawPtr = jsThread_.release();
|
||||
PostTaskToTaskRunner(
|
||||
platformRunner_, [rawPtr] { std::unique_ptr<fml::Thread> jsThread(rawPtr); }, 0);
|
||||
}
|
||||
|
||||
void FlutterTaskExecutor::InitPlatformThread()
|
||||
{
|
||||
platformRunner_ = flutter::PlatformTaskRunnerAdapter::CurrentTaskRunner();
|
||||
}
|
||||
|
||||
void FlutterTaskExecutor::InitJsThread(bool newThread)
|
||||
{
|
||||
if (newThread) {
|
||||
jsThread_ = std::make_unique<fml::Thread>(GenJsThreadName());
|
||||
jsRunner_ = jsThread_->GetTaskRunner();
|
||||
} else {
|
||||
jsRunner_ = uiRunner_;
|
||||
}
|
||||
}
|
||||
|
||||
void FlutterTaskExecutor::InitOtherThreads(const flutter::TaskRunners& taskRunners)
|
||||
{
|
||||
uiRunner_ = taskRunners.GetUITaskRunner();
|
||||
ioRunner_ = taskRunners.GetIOTaskRunner();
|
||||
gpuRunner_ = taskRunners.GetGPUTaskRunner();
|
||||
|
||||
PostTaskToTaskRunner(
|
||||
uiRunner_, [] { SetThreadPriority(UI_THREAD_PRIORITY); }, 0);
|
||||
PostTaskToTaskRunner(
|
||||
gpuRunner_, [] { SetThreadPriority(GPU_THREAD_PRIORITY); }, 0);
|
||||
}
|
||||
|
||||
bool FlutterTaskExecutor::OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const
|
||||
{
|
||||
switch (type) {
|
||||
case TaskType::PLATFORM:
|
||||
return PostTaskToTaskRunner(platformRunner_, std::move(task), delayTime);
|
||||
case TaskType::UI:
|
||||
return PostTaskToTaskRunner(uiRunner_, std::move(task), delayTime);
|
||||
case TaskType::IO:
|
||||
return PostTaskToTaskRunner(ioRunner_, std::move(task), delayTime);
|
||||
case TaskType::GPU:
|
||||
return PostTaskToTaskRunner(gpuRunner_, std::move(task), delayTime);
|
||||
case TaskType::JS:
|
||||
return PostTaskToTaskRunner(jsRunner_, std::move(task), delayTime);
|
||||
case TaskType::BACKGROUND:
|
||||
// Ignore delay time
|
||||
return BackgroundTaskExecutor::GetInstance().PostTask(std::move(task));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterTaskExecutor::WillRunOnCurrentThread(TaskType type) const
|
||||
{
|
||||
switch (type) {
|
||||
case TaskType::PLATFORM:
|
||||
return platformRunner_ ? platformRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::UI:
|
||||
return uiRunner_ ? uiRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::IO:
|
||||
return ioRunner_ ? ioRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::GPU:
|
||||
return gpuRunner_ ? gpuRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::JS:
|
||||
return jsRunner_ ? jsRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::BACKGROUND:
|
||||
// Always return false for background tasks.
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FlutterTaskExecutor::AddTaskObserver(Task&& callback)
|
||||
{
|
||||
fml::MessageLoop::GetCurrent().AddTaskObserver(reinterpret_cast<intptr_t>(this), std::move(callback));
|
||||
}
|
||||
|
||||
void FlutterTaskExecutor::RemoveTaskObserver()
|
||||
{
|
||||
fml::MessageLoop::GetCurrent().RemoveTaskObserver(reinterpret_cast<intptr_t>(this));
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
|
||||
#define FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
|
||||
|
||||
#include "flutter/common/task_runners.h"
|
||||
#include "flutter/fml/thread.h"
|
||||
|
||||
#include "base/thread/task_executor.h"
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class ACE_EXPORT FlutterTaskExecutor final : public TaskExecutor {
|
||||
DECLARE_ACE_TYPE(FlutterTaskExecutor, TaskExecutor);
|
||||
|
||||
public:
|
||||
~FlutterTaskExecutor() final;
|
||||
// Must call this method on platform thread
|
||||
void InitPlatformThread();
|
||||
void InitJsThread(bool newThread = true);
|
||||
void InitOtherThreads(const flutter::TaskRunners& taskRunners);
|
||||
|
||||
void AddTaskObserver(Task&& callback) override;
|
||||
void RemoveTaskObserver() override;
|
||||
bool WillRunOnCurrentThread(TaskType type) const final;
|
||||
|
||||
private:
|
||||
bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const final;
|
||||
|
||||
std::unique_ptr<fml::Thread> jsThread_;
|
||||
|
||||
fml::RefPtr<fml::TaskRunner> platformRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> uiRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> ioRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> jsRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> gpuRunner_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_CPP_FLUTTER_TASK_EXECUTOR_H
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/common/cpp/flutter_window.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "flutter/runtime/window_manager.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/pipeline/base/render_node.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
std::unique_ptr<PlatformWindow> PlatformWindow::Create(AceView* view)
|
||||
{
|
||||
if (view != nullptr) {
|
||||
return std::make_unique<Platform::FlutterWindow>(view->GetInstanceId());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Platform {
|
||||
|
||||
FlutterWindow::FlutterWindow(int32_t instanceId) : instanceId_(instanceId) {}
|
||||
|
||||
FlutterWindow::~FlutterWindow() {}
|
||||
|
||||
void FlutterWindow::RequestFrame()
|
||||
{
|
||||
auto window = flutter::WindowManager::GetWindow(instanceId_);
|
||||
if (window != nullptr) {
|
||||
window->ScheduleFrame();
|
||||
if (!window->HasBeginFrameCallback()) {
|
||||
window->SetBeginFrameCallback(std::bind(&FlutterWindow::OnVsyncCallback, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlutterWindow::RegisterVsyncCallback(AceVsyncCallback&& callback)
|
||||
{
|
||||
vsyncCallbacks_.emplace_back(std::move(callback));
|
||||
}
|
||||
|
||||
void FlutterWindow::SetRootRenderNode(const RefPtr<RenderNode>& root) {}
|
||||
|
||||
void FlutterWindow::OnVsyncCallback(uint64_t timeStampNanos)
|
||||
{
|
||||
for (const auto& vsyncCallback : vsyncCallbacks_) {
|
||||
vsyncCallback(timeStampNanos, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_FLUTTER_WINDOW_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_FLUTTER_WINDOW_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/platform_window.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class FlutterWindow final : public PlatformWindow {
|
||||
public:
|
||||
explicit FlutterWindow(int32_t instanceId);
|
||||
~FlutterWindow() override;
|
||||
|
||||
// Platform window interface
|
||||
void RequestFrame() override;
|
||||
void RegisterVsyncCallback(AceVsyncCallback&& callback) override;
|
||||
void SetRootRenderNode(const RefPtr<RenderNode>& root) override;
|
||||
|
||||
// Vsync callback
|
||||
void OnVsyncCallback(uint64_t timeStampNanos);
|
||||
|
||||
private:
|
||||
std::vector<AceVsyncCallback> vsyncCallbacks_;
|
||||
int32_t instanceId_;
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(FlutterWindow);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_FLUTTER_WINDOW_H
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/i18n/localization.h"
|
||||
|
||||
#include <cstdarg>
|
||||
|
||||
#ifndef WINDOWS_PLATFORM
|
||||
#include "securec.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
const size_t MAX_FORMAT_BUFFER = 256;
|
||||
|
||||
}
|
||||
|
||||
const std::string FormatEntry(const char* fmt, ...)
|
||||
{
|
||||
char buf[MAX_FORMAT_BUFFER] = { 0 };
|
||||
bool ret = false;
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, fmt, args) < 0) {
|
||||
ret = true;
|
||||
}
|
||||
va_end(args);
|
||||
return ret ? "" : buf;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_MULTIMODAL_FAKE_MULTIMODAL_SUBSCRIBER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_MULTIMODAL_FAKE_MULTIMODAL_SUBSCRIBER_H
|
||||
|
||||
#include "core/event/multimodal/multimodal_subscriber.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class FakeMultimodalSubscriber : public MultimodalSubscriber {
|
||||
DECLARE_ACE_TYPE(FakeMultimodalSubscriber, MultimodalSubscriber)
|
||||
|
||||
public:
|
||||
FakeMultimodalSubscriber() = default;
|
||||
~FakeMultimodalSubscriber() override = default;
|
||||
|
||||
void RegisterCallback(const std::function<void(const AceMultimodalEvent&)>& callback,
|
||||
const std::function<void()>& successCallback) override {}
|
||||
bool SubscribeVoiceEvents(const std::vector<VoiceEvent>& voiceEvents) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
void UnSubscribeVoiceEvents(const std::vector<VoiceEvent>& voiceEvents) override {}
|
||||
void UnSubscribeAllEvents() override {}
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_MULTIMODAL_FAKE_MULTIMODAL_SUBSCRIBER_H
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/thread/thread_util.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
void SetCurrentThreadName(const std::string& name)
|
||||
{
|
||||
#ifdef MAC_PLATFORM
|
||||
pthread_setname_np(name.c_str());
|
||||
#else
|
||||
pthread_setname_np(pthread_self(), name.c_str());
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,63 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
# build static
|
||||
template("ace_base_platform_source_set") {
|
||||
# get is_ohos_platform
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_source_set(target_name) {
|
||||
defines += invoker.defines
|
||||
|
||||
sources = [
|
||||
"$ace_root/adapter/ohos/cpp/ace_ability.cpp",
|
||||
"$ace_root/adapter/ohos/cpp/ace_application_info.cpp",
|
||||
"$ace_root/adapter/ohos/cpp/ace_container.cpp",
|
||||
"$ace_root/adapter/ohos/cpp/flutter_ace_view.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"$ace_root:ace_config",
|
||||
"$flutter_root:flutter_config",
|
||||
"$flutter_root:icu_config_$platform",
|
||||
]
|
||||
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
|
||||
deps = [
|
||||
"$flutter_root:ace_skia_$platform",
|
||||
"//base/global/resmgr_standard/frameworks/resmgr:global_resmgr",
|
||||
"//foundation/aafwk/standard/frameworks/kits/ability/native:abilitykit_native",
|
||||
"//foundation/graphic/standard:libwms_client",
|
||||
"//third_party/zlib:libz",
|
||||
]
|
||||
|
||||
external_deps = [
|
||||
"aafwk_standard:ability_manager",
|
||||
"aafwk_standard:want",
|
||||
"appexecfwk_standard:appexecfwk_base",
|
||||
"appexecfwk_standard:appexecfwk_core",
|
||||
"appexecfwk_standard:libeventhandler",
|
||||
"ipc:ipc_core",
|
||||
"multimodalinput_base:mmi_event",
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
ace_base_platform_source_set("ace_base_platform_ohos") {
|
||||
defines = ace_ohos_defines
|
||||
platform = "ohos"
|
||||
}
|
||||
@@ -0,0 +1,285 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/ohos/cpp/ace_ability.h"
|
||||
|
||||
#include "adapter/ohos/cpp/ace_container.h"
|
||||
#include "adapter/ohos/cpp/flutter_ace_view.h"
|
||||
#include "base/log/log.h"
|
||||
#include "core/common/ace_application_info.h"
|
||||
#include "core/common/frontend.h"
|
||||
#include "init_data.h"
|
||||
#include "touch_event.h"
|
||||
|
||||
#include "locale_info.h"
|
||||
#include "res_config.h"
|
||||
#include "resource_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
namespace Ace {
|
||||
namespace {
|
||||
FrontendType GetFrontendTypeFromManifest(const std::string& packagePathStr)
|
||||
{
|
||||
auto manifestPath = packagePathStr + std::string("assets/js/default/manifest.json");
|
||||
char realPath[PATH_MAX] = { 0x00 };
|
||||
if (realpath(manifestPath.c_str(), realPath) == nullptr) {
|
||||
LOGE("realpath fail! filePath: %{private}s, fail reason: %{public}s", manifestPath.c_str(), strerror(errno));
|
||||
LOGE("return default frontend: JS frontend.");
|
||||
return FrontendType::JS;
|
||||
}
|
||||
std::unique_ptr<FILE, decltype(&fclose)> file(fopen(realPath, "rb"), fclose);
|
||||
if (!file) {
|
||||
LOGE("open file failed, filePath: %{private}s, fail reason: %{public}s", manifestPath.c_str(), strerror(errno));
|
||||
LOGE("return default frontend: JS frontend.");
|
||||
return FrontendType::JS;
|
||||
}
|
||||
if (std::fseek(file.get(), 0, SEEK_END) != 0) {
|
||||
LOGE("seek file tail error, return default frontend: JS frontend.");
|
||||
return FrontendType::JS;
|
||||
}
|
||||
|
||||
long size = std::ftell(file.get());
|
||||
char* fileData = new (std::nothrow) char[size];
|
||||
if (fileData == nullptr) {
|
||||
LOGE("new json buff failed, return default frontend: JS frontend.");
|
||||
return FrontendType::JS;
|
||||
}
|
||||
rewind(file.get());
|
||||
std::unique_ptr<char[]> jsonStream(fileData);
|
||||
size_t result = std::fread(jsonStream.get(), 1, size, file.get());
|
||||
if (result != (size_t)size) {
|
||||
LOGE("read file failed, return default frontend: JS frontend.");
|
||||
return FrontendType::JS;
|
||||
}
|
||||
|
||||
std::string jsonString(jsonStream.get(), jsonStream.get() + size);
|
||||
auto rootJson = JsonUtil::ParseJsonString(jsonString);
|
||||
std::string frontendType = rootJson->GetString("type");
|
||||
if (frontendType == "normal") {
|
||||
return FrontendType::JS;
|
||||
} else if (frontendType == "form") {
|
||||
return FrontendType::JS_CARD;
|
||||
} else if (frontendType == "declarative") {
|
||||
return FrontendType::DECLARATIVE_JS;
|
||||
} else {
|
||||
LOGE("frontend type not supported. return default frontend: JS frontend.");
|
||||
return FrontendType::JS;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
using namespace OHOS::AAFwk;
|
||||
using namespace OHOS::AppExecFwk;
|
||||
|
||||
using AcePlatformFinish = std::function<void()>;
|
||||
class AcePlatformEventCallback final : public Platform::PlatformEventCallback {
|
||||
public:
|
||||
explicit AcePlatformEventCallback(AcePlatformFinish onFinish) : onFinish_(onFinish) {}
|
||||
|
||||
~AcePlatformEventCallback() = default;
|
||||
|
||||
virtual void OnFinish() const
|
||||
{
|
||||
LOGI("AcePlatformEventCallback OnFinish");
|
||||
if (onFinish_) {
|
||||
onFinish_();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void OnStatusBarBgColorChanged(uint32_t color)
|
||||
{
|
||||
LOGI("AcePlatformEventCallback OnStatusBarBgColorChanged");
|
||||
}
|
||||
|
||||
private:
|
||||
AcePlatformFinish onFinish_;
|
||||
};
|
||||
|
||||
int32_t AceAbility::instanceId_ = 0;
|
||||
const std::string AceAbility::START_PARAMS_KEY = "__startParams";
|
||||
const std::string AceAbility::PAGE_URI = "url";
|
||||
const std::string AceAbility::CONTINUE_PARAMS_KEY = "__remoteData";
|
||||
|
||||
REGISTER_AA(AceAbility)
|
||||
void AceAbility::OnStart(const Want& want)
|
||||
{
|
||||
Ability::OnStart(want);
|
||||
LOGI("AceAbility::OnStart called");
|
||||
|
||||
SetHwIcuDirectory();
|
||||
|
||||
std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
|
||||
auto resourceManager = GetResourceManager();
|
||||
if (resourceManager != nullptr) {
|
||||
resourceManager->GetResConfig(*resConfig);
|
||||
auto localeInfo = resConfig->GetLocaleInfo();
|
||||
AceApplicationInfo::GetInstance().SetResourceManager(resourceManager);
|
||||
if (localeInfo != nullptr) {
|
||||
auto language = localeInfo->GetLanguage();
|
||||
auto region = localeInfo->GetRegion();
|
||||
auto script = localeInfo->GetScript();
|
||||
AceApplicationInfo::GetInstance().SetLocale(
|
||||
(language == nullptr) ? "" : language,
|
||||
(region == nullptr) ? "" : region,
|
||||
(script == nullptr) ? "" : script,
|
||||
"");
|
||||
}
|
||||
}
|
||||
|
||||
auto packagePathStr = GetBundleCodePath();
|
||||
auto moduleInfo = GetHapModuleInfo();
|
||||
if (moduleInfo != nullptr) {
|
||||
packagePathStr += "/" + moduleInfo->name + "/";
|
||||
}
|
||||
FrontendType frontendType = GetFrontendTypeFromManifest(packagePathStr);
|
||||
|
||||
// create container
|
||||
Platform::AceContainer::CreateContainer(
|
||||
abilityId_, frontendType, this,
|
||||
std::make_unique<AcePlatformEventCallback>([this]() {
|
||||
TerminateAbility();
|
||||
}));
|
||||
// create view.
|
||||
auto flutterAceView = Platform::FlutterAceView::CreateView(abilityId_);
|
||||
OHOS::Window* window = Ability::GetWindow().get();
|
||||
|
||||
auto&& touchEventCallback = [aceView = flutterAceView](OHOS::TouchEvent event) -> bool {
|
||||
LOGD("RegistOnTouchCb touchEventCallback called");
|
||||
return aceView->DispatchTouchEvent(aceView, event);
|
||||
};
|
||||
window->RegistOnTouchCb(touchEventCallback);
|
||||
|
||||
Platform::FlutterAceView::SurfaceCreated(flutterAceView, window);
|
||||
|
||||
// set metrics
|
||||
BufferRequestConfig windowConfig;
|
||||
window->GetRequestConfig(windowConfig);
|
||||
LOGI("AceAbility: windowConfig: width: %{public}d, height: %{public}d", windowConfig.width, windowConfig.height);
|
||||
|
||||
flutter::ViewportMetrics metrics;
|
||||
metrics.physical_width = windowConfig.width;
|
||||
metrics.physical_height = windowConfig.height;
|
||||
Platform::FlutterAceView::SetViewportMetrics(flutterAceView, metrics);
|
||||
|
||||
// add asset path.
|
||||
auto assetBasePathStr = { std::string("assets/js/default/"), std::string("assets/js/share/") };
|
||||
Platform::AceContainer::AddAssetPath(abilityId_, packagePathStr, assetBasePathStr);
|
||||
// set view
|
||||
Platform::AceContainer::SetView(flutterAceView, density_, windowConfig.width, windowConfig.height);
|
||||
Platform::FlutterAceView::SurfaceChanged(flutterAceView, windowConfig.width, windowConfig.height, 0);
|
||||
|
||||
// get url
|
||||
std::string parsedPageUrl;
|
||||
if (!remotePageUrl_.empty()) {
|
||||
parsedPageUrl = remotePageUrl_;
|
||||
} else if (!pageUrl_.empty()) {
|
||||
parsedPageUrl = pageUrl_;
|
||||
} else if (want.HasParameter(PAGE_URI)) {
|
||||
parsedPageUrl = want.GetStringParam(PAGE_URI);
|
||||
} else {
|
||||
parsedPageUrl = "";
|
||||
}
|
||||
|
||||
// run page.
|
||||
Platform::AceContainer::RunPage(
|
||||
abilityId_, Platform::AceContainer::GetContainer(abilityId_)->GeneratePageId(),
|
||||
parsedPageUrl, want.GetStringParam(START_PARAMS_KEY));
|
||||
|
||||
Platform::AceContainer::OnRestoreData(abilityId_, remoteData_);
|
||||
LOGI("AceAbility::OnStart called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnStop()
|
||||
{
|
||||
LOGI("AceAbility::OnStop called ");
|
||||
Ability::OnStop();
|
||||
Platform::AceContainer::DestroyContainer(abilityId_);
|
||||
LOGI("AceAbility::OnStop called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnActive()
|
||||
{
|
||||
LOGI("AceAbility::OnActive called ");
|
||||
Ability::OnActive();
|
||||
Platform::AceContainer::OnActive(abilityId_);
|
||||
LOGI("AceAbility::OnActive called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnForeground(const Want& want)
|
||||
{
|
||||
LOGI("AceAbility::OnForeground called ");
|
||||
Ability::OnForeground(want);
|
||||
Platform::AceContainer::OnShow(abilityId_);
|
||||
LOGI("AceAbility::OnForeground called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnBackground()
|
||||
{
|
||||
LOGI("AceAbility::OnBackground called ");
|
||||
Ability::OnBackground();
|
||||
Platform::AceContainer::OnHide(abilityId_);
|
||||
LOGI("AceAbility::OnBackground called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnInactive()
|
||||
{
|
||||
LOGI("AceAbility::OnInactive called ");
|
||||
Ability::OnInactive();
|
||||
Platform::AceContainer::OnInactive(abilityId_);
|
||||
LOGI("AceAbility::OnInactive called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnBackPressed()
|
||||
{
|
||||
LOGI("AceAbility::OnBackPressed called ");
|
||||
if (!Platform::AceContainer::OnBackPressed(abilityId_)) {
|
||||
LOGI("AceAbility::OnBackPressed: passed to Ability to process");
|
||||
Ability::OnBackPressed();
|
||||
}
|
||||
LOGI("AceAbility::OnBackPressed called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnNewWant(const Want& want)
|
||||
{
|
||||
LOGI("AceAbility::OnNewWant called ");
|
||||
Ability::OnNewWant(want);
|
||||
std::string params = want.GetStringParam(START_PARAMS_KEY);
|
||||
Platform::AceContainer::OnNewRequest(abilityId_, params);
|
||||
LOGI("AceAbility::OnNewWant called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnRestoreAbilityState(const PacMap& inState)
|
||||
{
|
||||
LOGI("AceAbility::OnRestoreAbilityState called ");
|
||||
Ability::OnRestoreAbilityState(inState);
|
||||
LOGI("AceAbility::OnRestoreAbilityState called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnSaveAbilityState(PacMap& outState)
|
||||
{
|
||||
LOGI("AceAbility::OnSaveAbilityState called ");
|
||||
Ability::OnSaveAbilityState(outState);
|
||||
LOGI("AceAbility::OnSaveAbilityState called End");
|
||||
}
|
||||
|
||||
void AceAbility::OnConfigurationUpdated(const Configuration& configuration)
|
||||
{
|
||||
LOGI("AceAbility::OnConfigurationUpdated called ");
|
||||
Ability::OnConfigurationUpdated(configuration);
|
||||
LOGI("AceAbility::OnConfigurationUpdated called End");
|
||||
}
|
||||
|
||||
}
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
|
||||
#define FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
|
||||
|
||||
#include "ability.h"
|
||||
#include "ability_loader.h"
|
||||
#include "want.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class AceAbility final : public OHOS::AppExecFwk::Ability {
|
||||
public:
|
||||
AceAbility()
|
||||
{
|
||||
abilityId_ = instanceId_;
|
||||
instanceId_++;
|
||||
}
|
||||
virtual ~AceAbility() = default;
|
||||
|
||||
void OnStart(const OHOS::AAFwk::Want& want) override;
|
||||
void OnStop() override;
|
||||
void OnActive() override;
|
||||
void OnInactive() override;
|
||||
void OnForeground(const OHOS::AAFwk::Want& want) override;
|
||||
void OnBackground() override;
|
||||
void OnBackPressed() override;
|
||||
void OnNewWant(const OHOS::AAFwk::Want& want) override;
|
||||
void OnRestoreAbilityState(const OHOS::AppExecFwk::PacMap& inState) override;
|
||||
void OnSaveAbilityState(OHOS::AppExecFwk::PacMap& outState) override;
|
||||
void OnConfigurationUpdated(const OHOS::AppExecFwk::Configuration& configuration) override;
|
||||
|
||||
private:
|
||||
static int32_t instanceId_;
|
||||
static const std::string START_PARAMS_KEY;
|
||||
static const std::string PAGE_URI;
|
||||
static const std::string CONTINUE_PARAMS_KEY;
|
||||
|
||||
int32_t abilityId_ = 0;
|
||||
float density_ = 1.0f;
|
||||
std::string remotePageUrl_;
|
||||
std::string remoteData_;
|
||||
std::string pageUrl_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ACE_ENGINE_ADAPTER_OHOS_CPP_ACE_ABILITY_H
|
||||
Executable
+190
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/ohos/cpp/ace_application_info.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "contrib/minizip/unzip.h"
|
||||
#include "unicode/locid.h"
|
||||
|
||||
#include "adapter/common/cpp/ace_res_config.h"
|
||||
#include "adapter/common/cpp/ace_res_data_struct.h"
|
||||
#include "base/i18n/localization.h"
|
||||
#include "base/log/ace_trace.h"
|
||||
#include "base/log/log.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
|
||||
#include "init_data.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
AceApplicationInfoImpl::AceApplicationInfoImpl() {}
|
||||
|
||||
AceApplicationInfoImpl::~AceApplicationInfoImpl() = default;
|
||||
|
||||
void AceApplicationInfoImpl::SetJsEngineParam(const std::string& key, const std::string& value)
|
||||
{
|
||||
jsEngineParams_[key] = value;
|
||||
}
|
||||
|
||||
std::string AceApplicationInfoImpl::GetJsEngineParam(const std::string& key) const
|
||||
{
|
||||
std::string value;
|
||||
auto iter = jsEngineParams_.find(key);
|
||||
if (iter != jsEngineParams_.end()) {
|
||||
value = iter->second;
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
void AceApplicationInfoImpl::ChangeLocale(const std::string& language, const std::string& countryOrRegion)
|
||||
{
|
||||
std::string languageLower;
|
||||
std::transform(language.begin(), language.end(), languageLower.begin(), ::tolower);
|
||||
|
||||
std::string countryOrRegionUpper;
|
||||
std::transform(countryOrRegion.begin(), countryOrRegion.end(), countryOrRegionUpper.begin(), ::tolower);
|
||||
|
||||
std::unique_ptr<Global::Resource::ResConfig> resConfig(Global::Resource::CreateResConfig());
|
||||
resourceManager_->GetResConfig(*resConfig);
|
||||
|
||||
auto localeInfo = resConfig->GetLocaleInfo();
|
||||
if (localeInfo == nullptr) {
|
||||
LOGE("get local info failed");
|
||||
return;
|
||||
}
|
||||
|
||||
auto script = localeInfo->GetScript();
|
||||
resConfig->SetLocaleInfo(languageLower.c_str(), script, countryOrRegionUpper.c_str());
|
||||
resourceManager_->UpdateResConfig(*resConfig);
|
||||
|
||||
SetLocale(languageLower, countryOrRegionUpper, (script == nullptr) ? "" : script, "");
|
||||
}
|
||||
|
||||
std::vector<std::string> AceApplicationInfoImpl::GetLocaleFallback(const std::vector<std::string>& localeList) const
|
||||
{
|
||||
ACE_SCOPED_TRACE("GetLocaleFallback");
|
||||
std::vector<std::string> fileList;
|
||||
AceResConfig::MatchAndSortI18nConfigs(localeList, localeTag_, fileList);
|
||||
return fileList;
|
||||
}
|
||||
|
||||
void AceApplicationInfoImpl::SetLocale(
|
||||
const std::string& language,
|
||||
const std::string& countryOrRegion,
|
||||
const std::string& script,
|
||||
const std::string& keywordsAndValues)
|
||||
{
|
||||
language_ = language;
|
||||
countryOrRegion_ = countryOrRegion;
|
||||
script_ = script;
|
||||
keywordsAndValues_ = keywordsAndValues;
|
||||
|
||||
localeTag_ = language;
|
||||
if (!script_.empty()) {
|
||||
localeTag_.append("-" + script_);
|
||||
}
|
||||
localeTag_.append("-" + countryOrRegion_);
|
||||
|
||||
icu::Locale locale(language_.c_str(), countryOrRegion.c_str());
|
||||
isRightToLeft_ = locale.isRightToLeft();
|
||||
|
||||
auto languageList = Localization::GetLanguageList(language_);
|
||||
if (languageList.size() == 1) {
|
||||
Localization::SetLocale(
|
||||
language_, countryOrRegion_, script, languageList.front(), keywordsAndValues_);
|
||||
} else {
|
||||
auto selectLanguage = GetLocaleFallback(languageList);
|
||||
Localization::SetLocale(
|
||||
language_, countryOrRegion_, script, selectLanguage.front(), keywordsAndValues_);
|
||||
}
|
||||
}
|
||||
|
||||
bool AceApplicationInfoImpl::GetFiles(const std::string& filePath, std::vector<std::string>& fileList) const
|
||||
{
|
||||
const auto& packagePath = AceEngine::Get().GetPackagePath();
|
||||
const auto& assetBasePathSet = AceEngine::Get().GetAssetBasePath();
|
||||
if (packagePath.empty() || assetBasePathSet.empty()) {
|
||||
LOGE("the packagePath or assetBasePathSet is empty");
|
||||
return false;
|
||||
}
|
||||
|
||||
for (const auto& assetBasePath : assetBasePathSet) {
|
||||
std::string dirPath = packagePath + assetBasePath + filePath;
|
||||
DIR* dir = opendir(dirPath.c_str());
|
||||
if (dir == nullptr) {
|
||||
continue;
|
||||
}
|
||||
struct dirent* dirEntry = readdir(dir);
|
||||
while (dirEntry != nullptr) {
|
||||
std::string file = dirEntry->d_name;
|
||||
std::string fullPath = dirPath + file;
|
||||
dirEntry = readdir(dir);
|
||||
|
||||
struct stat st;
|
||||
if (stat(fullPath.c_str(), &st) != 0 || !S_ISREG(st.st_mode)) {
|
||||
continue;
|
||||
}
|
||||
fileList.emplace_back(file);
|
||||
}
|
||||
closedir(dir);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::vector<std::string> AceApplicationInfoImpl::SplitLocale(const std::string& desireLocales)
|
||||
{
|
||||
std::vector<std::string> ret;
|
||||
if (desireLocales.empty()) {
|
||||
ret.emplace_back("en-US");
|
||||
return ret;
|
||||
}
|
||||
|
||||
size_t rpos = -1;
|
||||
auto pos = desireLocales.find(',');
|
||||
while (pos != std::string::npos) {
|
||||
ret.emplace_back(desireLocales.substr(rpos + 1, pos - rpos - 1));
|
||||
rpos = pos;
|
||||
pos = desireLocales.find(',', rpos + 1);
|
||||
}
|
||||
ret.emplace_back(desireLocales.substr(rpos + 1, desireLocales.length() - rpos - 1));
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool AceApplicationInfoImpl::GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AceApplicationInfoImpl& AceApplicationInfoImpl::GetInstance()
|
||||
{
|
||||
static AceApplicationInfoImpl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
AceApplicationInfo& AceApplicationInfo::GetInstance()
|
||||
{
|
||||
return Platform::AceApplicationInfoImpl::GetInstance();
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
Executable
+68
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_APPLICATION_INFO_H
|
||||
#define FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_APPLICATION_INFO_H
|
||||
|
||||
#include <map>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/ace_application_info.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class AceApplicationInfoImpl : public AceApplicationInfo {
|
||||
public:
|
||||
AceApplicationInfoImpl();
|
||||
~AceApplicationInfoImpl() override;
|
||||
|
||||
static AceApplicationInfoImpl& GetInstance();
|
||||
|
||||
void SetLocale(const std::string& language, const std::string& countryOrRegion, const std::string& script,
|
||||
const std::string& keywordsAndValues) override;
|
||||
void ChangeLocale(const std::string& language, const std::string& countryOrRegion) override;
|
||||
std::vector<std::string> GetLocaleFallback(const std::vector<std::string>& localeList) const override;
|
||||
std::vector<std::string> GetResourceFallback(const std::vector<std::string>& resourceList) const override
|
||||
{
|
||||
return std::vector<std::string>();
|
||||
}
|
||||
double GetLifeTime() const override { return 0.0f; }
|
||||
std::string GetCurrentDeviceResTag() const override { return std::string(); };
|
||||
bool GetFiles(const std::string& filePath, std::vector<std::string>& fileList) const override;
|
||||
|
||||
bool GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo) override;
|
||||
|
||||
std::string GetJsEngineParam(const std::string& key) const override;
|
||||
|
||||
void SetJsEngineParam(const std::string& key, const std::string& value);
|
||||
|
||||
void SetResourceManager(std::shared_ptr<Global::Resource::ResourceManager>& resourceManager) override
|
||||
{
|
||||
resourceManager_ = resourceManager;
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<std::string> SplitLocale(const std::string& desireLocales);
|
||||
|
||||
std::map<std::string, std::string> jsEngineParams_;
|
||||
std::shared_ptr<Global::Resource::ResourceManager> resourceManager_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_COMMON_CPP_ACE_APPLICATION_INFO_H
|
||||
@@ -0,0 +1,589 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/common/cpp/file_asset_provider.h"
|
||||
#include "adapter/ohos/cpp/ace_application_info.h"
|
||||
#include "adapter/ohos/cpp/ace_container.h"
|
||||
#include "base/log/ace_trace.h"
|
||||
#include "base/log/event_report.h"
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/system_properties.h"
|
||||
#include "base/utils/utils.h"
|
||||
#include "base/watch_dog/watch_dog.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
#include "core/common/platform_window.h"
|
||||
#include "core/common/text_field_manager.h"
|
||||
#include "core/common/window.h"
|
||||
#include "core/pipeline/base/element.h"
|
||||
#include "core/pipeline/pipeline_context.h"
|
||||
#include "core/components/theme/app_theme.h"
|
||||
#include "core/components/theme/theme_constants.h"
|
||||
#include "core/components/theme/theme_manager.h"
|
||||
#include "frameworks/bridge/card_frontend/card_frontend.h"
|
||||
#include "frameworks/bridge/declarative_frontend/declarative_frontend.h"
|
||||
#include "frameworks/bridge/js_frontend/engine/common/js_engine_loader.h"
|
||||
#include "frameworks/bridge/js_frontend/js_frontend.h"
|
||||
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
|
||||
#include "adapter/common/cpp/flutter_asset_manager.h"
|
||||
#include "adapter/common/cpp/flutter_task_executor.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
AceContainer::AceContainer(int32_t instanceId, FrontendType type, AceAbility* aceAbility,
|
||||
std::unique_ptr<PlatformEventCallback> callback) : instanceId_(instanceId), type_(type), aceAbility_(aceAbility)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
auto flutterTaskExecutor = Referenced::MakeRefPtr<FlutterTaskExecutor>();
|
||||
flutterTaskExecutor->InitPlatformThread();
|
||||
flutterTaskExecutor->InitJsThread();
|
||||
taskExecutor_ = flutterTaskExecutor;
|
||||
if (type_ != FrontendType::DECLARATIVE_JS) {
|
||||
InitializeFrontend();
|
||||
}
|
||||
|
||||
platformEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void AceContainer::InitializeFrontend()
|
||||
{
|
||||
if (type_ == FrontendType::JS) {
|
||||
frontend_ = Frontend::Create();
|
||||
auto jsFrontend = AceType::DynamicCast<JsFrontend>(frontend_);
|
||||
jsFrontend->SetJsEngine(Framework::JsEngineLoader::Get().CreateJsEngine(instanceId_));
|
||||
jsFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
|
||||
jsFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
|
||||
jsFrontend->SetAbility(aceAbility_);
|
||||
} else if (type_ == FrontendType::DECLARATIVE_JS) {
|
||||
frontend_ = AceType::MakeRefPtr<DeclarativeFrontend>();
|
||||
auto declarativeFrontend = AceType::DynamicCast<DeclarativeFrontend>(frontend_);
|
||||
declarativeFrontend->SetJsEngine(Framework::JsEngineLoader::GetDeclarative().CreateJsEngine(instanceId_));
|
||||
} else {
|
||||
LOGE("Frontend type not supported");
|
||||
EventReport::SendAppStartException(AppStartExcepType::FRONTEND_TYPE_ERR);
|
||||
return;
|
||||
}
|
||||
ACE_DCHECK(frontend_);
|
||||
frontend_->Initialize(type_, taskExecutor_);
|
||||
}
|
||||
|
||||
RefPtr<AceContainer> AceContainer::GetContainer(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (container != nullptr) {
|
||||
auto aceContainer = AceType::DynamicCast<AceContainer>(container);
|
||||
return aceContainer;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool AceContainer::OnBackPressed(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
return false;
|
||||
}
|
||||
return context->CallRouterBackToPopPage();
|
||||
}
|
||||
|
||||
void AceContainer::OnShow(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->OnShow();
|
||||
}
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
#ifndef WEARABLE_PRODUCT
|
||||
context->OnShow();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AceContainer::OnHide(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->OnHide();
|
||||
auto taskExecutor = container->GetTaskExecutor();
|
||||
if (taskExecutor) {
|
||||
taskExecutor->PostTask([front]() { front->TriggerGarbageCollection(); }, TaskExecutor::TaskType::JS);
|
||||
}
|
||||
}
|
||||
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
return;
|
||||
}
|
||||
#ifndef WEARABLE_PRODUCT
|
||||
context->OnHide();
|
||||
#endif
|
||||
}
|
||||
|
||||
void AceContainer::OnActive(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->OnActive();
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::OnInactive(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->OnInactive();
|
||||
}
|
||||
}
|
||||
|
||||
std::string AceContainer::OnSaveData(int32_t instanceId)
|
||||
{
|
||||
std::string result = "false";
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (container) {
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->OnSaveData(result);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool AceContainer::OnRestoreData(int32_t instanceId, const std::string& data)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
if (!data.empty()) {
|
||||
auto result = front->OnRestoreData(data);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void AceContainer::OnNewRequest(int32_t instanceId, const std::string& data)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->OnNewRequest(data);
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::InitializeCallback()
|
||||
{
|
||||
ACE_FUNCTION_TRACE();
|
||||
|
||||
ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
|
||||
auto&& touchEventCallback = [context = pipelineContext_](const TouchPoint& event) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, event]() { context->OnTouchEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterTouchEventCallback(touchEventCallback);
|
||||
|
||||
auto&& keyEventCallback = [context = pipelineContext_](const KeyEvent& event) {
|
||||
bool result = false;
|
||||
context->GetTaskExecutor()->PostSyncTask(
|
||||
[context, event, &result]() { result = context->OnKeyEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
return result;
|
||||
};
|
||||
aceView_->RegisterKeyEventCallback(keyEventCallback);
|
||||
|
||||
auto&& mouseEventCallback = [context = pipelineContext_](const MouseEvent& event) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, event]() { context->OnMouseEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterMouseEventCallback(mouseEventCallback);
|
||||
|
||||
auto&& rotationEventCallback = [context = pipelineContext_](const RotationEvent& event) {
|
||||
bool result = false;
|
||||
context->GetTaskExecutor()->PostSyncTask(
|
||||
[context, event, &result]() { result = context->OnRotationEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
return result;
|
||||
};
|
||||
aceView_->RegisterRotationEventCallback(rotationEventCallback);
|
||||
|
||||
auto&& viewChangeCallback = [context = pipelineContext_](int32_t width, int32_t height) {
|
||||
ACE_SCOPED_TRACE("ViewChangeCallback(%d, %d)", width, height);
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, width, height]() { context->OnSurfaceChanged(width, height); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterViewChangeCallback(viewChangeCallback);
|
||||
|
||||
auto&& densityChangeCallback = [context = pipelineContext_](double density) {
|
||||
ACE_SCOPED_TRACE("DensityChangeCallback(%lf)", density);
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, density]() { context->OnSurfaceDensityChanged(density); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterDensityChangeCallback(densityChangeCallback);
|
||||
|
||||
auto&& systemBarHeightChangeCallback = [context = pipelineContext_](double statusBar, double navigationBar) {
|
||||
ACE_SCOPED_TRACE("SystemBarHeightChangeCallback(%lf, %lf)", statusBar, navigationBar);
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, statusBar, navigationBar]() { context->OnSystemBarHeightChanged(statusBar, navigationBar); },
|
||||
TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterSystemBarHeightChangeCallback(systemBarHeightChangeCallback);
|
||||
|
||||
auto&& surfaceDestroyCallback = [context = pipelineContext_]() {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context]() { context->OnSurfaceDestroyed(); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterSurfaceDestroyCallback(surfaceDestroyCallback);
|
||||
|
||||
auto&& idleCallback = [context = pipelineContext_](int64_t deadline) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, deadline]() { context->OnIdle(deadline); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterIdleCallback(idleCallback);
|
||||
|
||||
auto&& viewDestoryCallback = [context = pipelineContext_](AceView::ViewReleaseCallback&& callback) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, callback = std::move(callback)]() {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[callback = std::move(callback)]() { callback(); }, TaskExecutor::TaskType::PLATFORM);
|
||||
},
|
||||
TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterViewDestroyCallback(viewDestoryCallback);
|
||||
}
|
||||
|
||||
void AceContainer::CreateContainer(int32_t instanceId, FrontendType type, AceAbility* aceAbility,
|
||||
std::unique_ptr<PlatformEventCallback> callback)
|
||||
{
|
||||
auto aceContainer = AceType::MakeRefPtr<AceContainer>(instanceId, type, aceAbility, std::move(callback));
|
||||
AceEngine::Get().AddContainer(instanceId, aceContainer);
|
||||
auto front = aceContainer->GetFrontend();
|
||||
if (front) {
|
||||
front->UpdateState(Frontend::State::ON_CREATE);
|
||||
front->SetJsMessageDispatcher(aceContainer);
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::DestroyContainer(int32_t instanceId)
|
||||
{
|
||||
LOGI("DestroyContainer with id %{private}d", instanceId);
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
LOGE("no AceContainer with id %{private}d", instanceId);
|
||||
return;
|
||||
}
|
||||
auto context = container->GetPipelineContext();
|
||||
if (context) {
|
||||
auto taskExecutor = context->GetTaskExecutor();
|
||||
if (taskExecutor) {
|
||||
taskExecutor->PostTask([context]() { context->Destroy(); }, TaskExecutor::TaskType::UI);
|
||||
}
|
||||
}
|
||||
AceEngine::Get().RemoveContainer(instanceId);
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->UpdateState(Frontend::State::ON_DESTROY);
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::SetView(AceView* view, double density, int32_t width, int32_t height)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
auto platformWindow = PlatformWindow::Create(view);
|
||||
if (!platformWindow) {
|
||||
LOGE("Create PlatformWindow failed!");
|
||||
return;
|
||||
}
|
||||
std::unique_ptr<Window> window = std::make_unique<Window>(std::move(platformWindow));
|
||||
container->AttachView(std::move(window), view, density, width, height);
|
||||
}
|
||||
|
||||
bool AceContainer::RunPage(int32_t instanceId, int32_t pageId, const std::string& content, const std::string& params)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->RunPage(pageId, content, params);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceContainer::PushPage(int32_t instanceId, const std::string& content, const std::string& params)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->PushPage(content, params);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AceContainer::UpdatePage(int32_t instanceId, int32_t pageId, const std::string& content)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
return false;
|
||||
}
|
||||
return context->CallRouterBackToPopPage();
|
||||
}
|
||||
|
||||
void AceContainer::Dispatch(
|
||||
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
void AceContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const
|
||||
{
|
||||
auto front = GetFrontend();
|
||||
if (!front) {
|
||||
LOGE("the front is nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
taskExecutor_->PostTask(
|
||||
[front, callbackId, errorCode, errorMessage = std::move(errorMessage)]() mutable {
|
||||
front->TransferJsPluginGetError(callbackId, errorCode, std::move(errorMessage));
|
||||
},
|
||||
TaskExecutor::TaskType::BACKGROUND);
|
||||
}
|
||||
|
||||
bool AceContainer::Dump(const std::vector<std::string>& params)
|
||||
{
|
||||
if (aceView_ && aceView_->Dump(params)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pipelineContext_) {
|
||||
pipelineContext_->Dump(params);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AceContainer::AddAssetPath(
|
||||
int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths)
|
||||
{
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
AceEngine::Get().SetPackagePath(packagePath);
|
||||
for (auto path: paths) {
|
||||
AceEngine::Get().SetAssetBasePath(path);
|
||||
}
|
||||
|
||||
RefPtr<FlutterAssetManager> flutterAssetManager;
|
||||
if (container->assetManager_) {
|
||||
flutterAssetManager = AceType::DynamicCast<FlutterAssetManager>(container->assetManager_);
|
||||
} else {
|
||||
flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
|
||||
container->assetManager_ = flutterAssetManager;
|
||||
if (container->type_ != FrontendType::DECLARATIVE_JS) {
|
||||
container->frontend_->SetAssetManager(flutterAssetManager);
|
||||
}
|
||||
}
|
||||
if (flutterAssetManager && !packagePath.empty()) {
|
||||
auto assetProvider = std::make_unique<FileAssetProvider>();
|
||||
if (assetProvider->Initialize(packagePath, paths)) {
|
||||
LOGI("Push AssetProvider to queue.");
|
||||
flutterAssetManager->PushBack(std::move(assetProvider));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::AttachView(
|
||||
std::unique_ptr<Window> window, AceView* view, double density, int32_t width, int32_t height)
|
||||
{
|
||||
aceView_ = view;
|
||||
auto instanceId = aceView_->GetInstanceId();
|
||||
auto state = flutter::UIDartState::Current()->GetStateById(instanceId);
|
||||
ACE_DCHECK(state != nullptr);
|
||||
auto flutterTaskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(taskExecutor_);
|
||||
flutterTaskExecutor->InitOtherThreads(state->GetTaskRunners());
|
||||
|
||||
if (type_ == FrontendType::DECLARATIVE_JS) {
|
||||
// For DECLARATIVE_JS or UJOINT_JS frontend display UI in JS thread temporarily.
|
||||
flutterTaskExecutor->InitJsThread(false);
|
||||
InitializeFrontend();
|
||||
auto front = GetFrontend();
|
||||
if (front) {
|
||||
front->UpdateState(Frontend::State::ON_CREATE);
|
||||
front->SetJsMessageDispatcher(AceType::Claim(this));
|
||||
front->SetAssetManager(assetManager_);
|
||||
}
|
||||
}
|
||||
|
||||
resRegister_ = aceView_->GetPlatformResRegister();
|
||||
pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(std::move(window),
|
||||
taskExecutor_,
|
||||
assetManager_,
|
||||
resRegister_,
|
||||
frontend_,
|
||||
instanceId);
|
||||
pipelineContext_->SetRootSize(density, width, height);
|
||||
pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
|
||||
pipelineContext_->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
|
||||
pipelineContext_->SetWindowModal(windowModal_);
|
||||
pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate());
|
||||
InitializeCallback();
|
||||
|
||||
auto&& finishEventHandler = [weak = WeakClaim(this)] {
|
||||
auto container = weak.Upgrade();
|
||||
if (!container) {
|
||||
LOGE("FinishEventHandler container is null!");
|
||||
return;
|
||||
}
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
LOGE("FinishEventHandler context is null!");
|
||||
return;
|
||||
}
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[weak = WeakPtr<AceContainer>(container)] {
|
||||
auto container = weak.Upgrade();
|
||||
if (!container) {
|
||||
LOGE("Finish task, container is null!");
|
||||
return;
|
||||
}
|
||||
container->OnFinish();
|
||||
},
|
||||
TaskExecutor::TaskType::PLATFORM);
|
||||
};
|
||||
pipelineContext_->SetFinishEventHandler(finishEventHandler);
|
||||
|
||||
auto&& setStatusBarEventHandler = [weak = WeakClaim(this)](const Color& color) {
|
||||
auto container = weak.Upgrade();
|
||||
if (!container) {
|
||||
LOGE("StatusBarEventHandler container is null!");
|
||||
return;
|
||||
}
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
LOGE("StatusBarEventHandler context is null!");
|
||||
return;
|
||||
}
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[weak, color = color.GetValue()]() {
|
||||
auto container = weak.Upgrade();
|
||||
if (!container) {
|
||||
LOGE("StatusBarEventHandler container is null!");
|
||||
return;
|
||||
}
|
||||
if (container->platformEventCallback_) {
|
||||
container->platformEventCallback_->OnStatusBarBgColorChanged(color);
|
||||
}
|
||||
},
|
||||
TaskExecutor::TaskType::PLATFORM);
|
||||
};
|
||||
pipelineContext_->SetStatusBarEventHandler(setStatusBarEventHandler);
|
||||
|
||||
// Load custom style at UI thread before frontend attach, to make sure style can be loaded before building dom tree.
|
||||
auto themeManager = pipelineContext_->GetThemeManager();
|
||||
if (themeManager) {
|
||||
taskExecutor_->PostTask(
|
||||
[ themeManager, assetManager = assetManager_, colorScheme = colorScheme_] {
|
||||
themeManager->SetColorScheme(colorScheme);
|
||||
themeManager->LoadCustomTheme(assetManager);
|
||||
},
|
||||
TaskExecutor::TaskType::UI);
|
||||
}
|
||||
|
||||
taskExecutor_->PostTask(
|
||||
[context = pipelineContext_]() { context->SetupRootElement(); }, TaskExecutor::TaskType::UI);
|
||||
aceView_->Launch();
|
||||
frontend_->AttachPipelineContext(pipelineContext_);
|
||||
|
||||
AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_);
|
||||
}
|
||||
|
||||
void AceContainer::SetFontScale(int32_t instanceId, float fontScale)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
auto pipelineContext = container->GetPipelineContext();
|
||||
if (!pipelineContext) {
|
||||
LOGE("fail to set font style due to context is null");
|
||||
return;
|
||||
}
|
||||
pipelineContext->SetFontScale(fontScale);
|
||||
}
|
||||
|
||||
void AceContainer::SetWindowStyle(int32_t instanceId, WindowModal windowModal, ColorScheme colorScheme)
|
||||
{
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
container->SetWindowModal(windowModal);
|
||||
container->SetColorScheme(colorScheme);
|
||||
}
|
||||
} // namespace OHOS::Ace::Platform
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_OHOS_CPP_ACE_CONTAINER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_ACE_CONTAINER_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "adapter/ohos/cpp/ace_ability.h"
|
||||
#include "adapter/ohos/cpp/platform_event_callback.h"
|
||||
#include "base/resource/asset_manager.h"
|
||||
#include "base/thread/task_executor.h"
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/common/container.h"
|
||||
#include "core/common/js_message_dispatcher.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
class AceContainer : public Container, public JsMessageDispatcher {
|
||||
DECLARE_ACE_TYPE(AceContainer, Container, JsMessageDispatcher);
|
||||
|
||||
public:
|
||||
AceContainer(int32_t instanceId, FrontendType type, AceAbility* aceAbility,
|
||||
std::unique_ptr<PlatformEventCallback> callback);
|
||||
~AceContainer() override = default;
|
||||
|
||||
static bool Register();
|
||||
|
||||
int32_t GetInstanceId() const override
|
||||
{
|
||||
if (aceView_) {
|
||||
return aceView_->GetInstanceId();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
RefPtr<Frontend> GetFrontend() const override
|
||||
{
|
||||
return frontend_;
|
||||
}
|
||||
|
||||
RefPtr<TaskExecutor> GetTaskExecutor() const override
|
||||
{
|
||||
return taskExecutor_;
|
||||
}
|
||||
|
||||
RefPtr<AssetManager> GetAssetManager() const override
|
||||
{
|
||||
return assetManager_;
|
||||
}
|
||||
|
||||
RefPtr<PlatformResRegister> GetPlatformResRegister() const override
|
||||
{
|
||||
return resRegister_;
|
||||
}
|
||||
|
||||
RefPtr<PipelineContext> GetPipelineContext() const override
|
||||
{
|
||||
return pipelineContext_;
|
||||
}
|
||||
|
||||
AceView* GetAceView() const
|
||||
{
|
||||
return aceView_;
|
||||
}
|
||||
|
||||
void SetWindowModal(WindowModal windowModal)
|
||||
{
|
||||
windowModal_ = windowModal;
|
||||
}
|
||||
|
||||
void SetColorScheme(ColorScheme colorScheme)
|
||||
{
|
||||
colorScheme_ = colorScheme;
|
||||
}
|
||||
|
||||
void Dispatch(
|
||||
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const override;
|
||||
|
||||
void DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const override;
|
||||
|
||||
bool Dump(const std::vector<std::string>& params) override;
|
||||
|
||||
void OnFinish()
|
||||
{
|
||||
if (platformEventCallback_) {
|
||||
platformEventCallback_->OnFinish();
|
||||
}
|
||||
}
|
||||
|
||||
int32_t GeneratePageId()
|
||||
{
|
||||
return pageId_++;
|
||||
}
|
||||
|
||||
std::string GetHostClassName() const override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
static void CreateContainer(int32_t instanceId, FrontendType type, AceAbility* aceAbility,
|
||||
std::unique_ptr<PlatformEventCallback> callback);
|
||||
static void DestroyContainer(int32_t instanceId);
|
||||
static bool RunPage(int32_t instanceId, int32_t pageId, const std::string& content, const std::string& params);
|
||||
static bool PushPage(int32_t instanceId, const std::string& content, const std::string& params);
|
||||
static bool OnBackPressed(int32_t instanceId);
|
||||
static void OnShow(int32_t instanceId);
|
||||
static void OnHide(int32_t instanceId);
|
||||
static void OnActive(int32_t instanceId);
|
||||
static void OnInactive(int32_t instanceId);
|
||||
static std::string OnSaveData(int32_t instanceId);
|
||||
static bool OnRestoreData(int32_t instanceId, const std::string& data);
|
||||
static void OnNewRequest(int32_t instanceId, const std::string& data);
|
||||
static void AddAssetPath(int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths);
|
||||
static void SetView(AceView* view, double density, int32_t width, int32_t height);
|
||||
static void SetFontScale(int32_t instanceId, float fontScale);
|
||||
static void SetWindowStyle(int32_t instanceId, WindowModal windowModal, ColorScheme colorScheme);
|
||||
|
||||
static RefPtr<AceContainer> GetContainer(int32_t instanceId);
|
||||
static bool UpdatePage(int32_t instanceId, int32_t pageId, const std::string& content);
|
||||
|
||||
private:
|
||||
void InitializeFrontend();
|
||||
void InitializeCallback();
|
||||
|
||||
void AttachView(std::unique_ptr<Window> window, AceView* view, double density, int32_t width, int32_t height);
|
||||
int32_t instanceId_ = 0;
|
||||
AceView* aceView_ = nullptr;
|
||||
RefPtr<TaskExecutor> taskExecutor_;
|
||||
RefPtr<AssetManager> assetManager_;
|
||||
RefPtr<PlatformResRegister> resRegister_;
|
||||
RefPtr<PipelineContext> pipelineContext_;
|
||||
RefPtr<Frontend> frontend_;
|
||||
FrontendType type_ = FrontendType::JS;
|
||||
std::unique_ptr<PlatformEventCallback> platformEventCallback_;
|
||||
WindowModal windowModal_ { WindowModal::NORMAL };
|
||||
ColorScheme colorScheme_ { ColorScheme::FIRST_VALUE };
|
||||
AceAbility* aceAbility_ = nullptr;
|
||||
int32_t pageId_ = 0;
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(AceContainer);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_ACE_CONTAINER_H
|
||||
@@ -0,0 +1,476 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/ohos/cpp/flutter_ace_view.h"
|
||||
#include <fstream>
|
||||
|
||||
#include "base/log/dump_log.h"
|
||||
#include "base/log/event_report.h"
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/system_properties.h"
|
||||
#include "base/utils/utils.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
#include "core/event/mouse_event.h"
|
||||
#include "core/gestures/touch_event.h"
|
||||
#include "core/image/image_cache.h"
|
||||
#include "core/components/theme/app_theme.h"
|
||||
#include "core/components/theme/theme_manager.h"
|
||||
#include "core/pipeline/layers/flutter_scene_builder.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t ROTATION_DIVISOR = 64;
|
||||
constexpr double PERMIT_ANGLE_VALUE = 0.5;
|
||||
|
||||
TouchPoint ConvertTouchEvent(OHOS::TouchEvent& touchEvent)
|
||||
{
|
||||
int32_t id = static_cast<int32_t>(touchEvent.GetIndex());
|
||||
MmiPoint mmiPoint = touchEvent.GetPointerPosition(id);
|
||||
std::chrono::microseconds micros(touchEvent.GetOccurredTime());
|
||||
TimeStamp time(micros);
|
||||
TouchPoint point { id, mmiPoint.GetX(), mmiPoint.GetY(), TouchType::UNKNOWN, time, touchEvent.GetRadius(id) };
|
||||
switch (touchEvent.GetAction()) {
|
||||
case OHOS::TouchEvent::CANCEL:
|
||||
point.type = TouchType::CANCEL;
|
||||
break;
|
||||
case OHOS::TouchEvent::HOVER_POINTER_ENTER:
|
||||
case OHOS::TouchEvent::HOVER_POINTER_MOVE:
|
||||
case OHOS::TouchEvent::HOVER_POINTER_EXIT:
|
||||
LOGD("ConvertTouchEvent not implement type:%{public}ld", touchEvent.GetAction());
|
||||
break;
|
||||
case OHOS::TouchEvent::PRIMARY_POINT_DOWN:
|
||||
case OHOS::TouchEvent::OTHER_POINT_DOWN:
|
||||
point.type = TouchType::DOWN;
|
||||
break;
|
||||
case OHOS::TouchEvent::POINT_MOVE:
|
||||
point.type = TouchType::MOVE;
|
||||
break;
|
||||
case OHOS::TouchEvent::PRIMARY_POINT_UP:
|
||||
case OHOS::TouchEvent::OTHER_POINT_UP:
|
||||
point.type = TouchType::UP;
|
||||
break;
|
||||
default:
|
||||
LOGW("unknown type");
|
||||
break;
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
void ConvertMouseEvent(OHOS::MouseEvent& mouseEvent, MouseEvent& events)
|
||||
{
|
||||
MmiPoint mmiPoint = mouseEvent.GetCursor();
|
||||
events.x = mmiPoint.GetX();
|
||||
events.y = mmiPoint.GetY();
|
||||
events.z = mmiPoint.GetZ();
|
||||
switch (mouseEvent.GetAction()) {
|
||||
case OHOS::MouseEvent::PRESS:
|
||||
events.action = MouseAction::PRESS;
|
||||
break;
|
||||
case OHOS::MouseEvent::RELEASE:
|
||||
events.action = MouseAction::RELEASE;
|
||||
break;
|
||||
case OHOS::MouseEvent::MOVE:
|
||||
events.action = MouseAction::MOVE;
|
||||
break;
|
||||
case OHOS::MouseEvent::HOVER_ENTER:
|
||||
events.action = MouseAction::HOVER_ENTER;
|
||||
break;
|
||||
case OHOS::MouseEvent::HOVER_MOVE:
|
||||
events.action = MouseAction::HOVER_MOVE;
|
||||
break;
|
||||
case OHOS::MouseEvent::HOVER_EXIT:
|
||||
events.action = MouseAction::HOVER_EXIT;
|
||||
break;
|
||||
default:
|
||||
events.action = MouseAction::NONE;
|
||||
break;
|
||||
}
|
||||
switch (mouseEvent.GetActionButton()) {
|
||||
case OHOS::MouseEvent::LEFT_BUTTON:
|
||||
events.button = MouseButton::LEFT_BUTTON;
|
||||
break;
|
||||
case OHOS::MouseEvent::RIGHT_BUTTON:
|
||||
events.button = MouseButton::RIGHT_BUTTON;
|
||||
break;
|
||||
case OHOS::MouseEvent::MIDDLE_BUTTON:
|
||||
events.button = MouseButton::MIDDLE_BUTTON;
|
||||
break;
|
||||
case OHOS::MouseEvent::BACK_BUTTON:
|
||||
events.button = MouseButton::BACK_BUTTON;
|
||||
break;
|
||||
case OHOS::MouseEvent::FORWARD_BUTTON:
|
||||
events.button = MouseButton::FORWARD_BUTTON;
|
||||
break;
|
||||
default:
|
||||
events.button = MouseButton::NONE_BUTTON;
|
||||
break;
|
||||
}
|
||||
events.pressedButtons = static_cast<size_t>(mouseEvent.GetPressedButtons());
|
||||
std::chrono::microseconds micros(mouseEvent.GetOccurredTime());
|
||||
TimeStamp time(micros);
|
||||
events.time = time;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FlutterAceView* FlutterAceView::CreateView(int32_t instanceId)
|
||||
{
|
||||
FlutterAceView* aceSurface = new Platform::FlutterAceView(instanceId);
|
||||
flutter::Settings settings;
|
||||
settings.instanceId = instanceId;
|
||||
settings.platform = flutter::AcePlatform::ACE_PLATFORM_OHOS;
|
||||
settings.enable_software_rendering = true;
|
||||
settings.idle_notification_callback = [aceSurface](int64_t deadline) {
|
||||
if (aceSurface != nullptr) {
|
||||
aceSurface->ProcessIdleEvent(deadline);
|
||||
}
|
||||
};
|
||||
auto shell_holder = std::make_unique<flutter::OhosShellHolder>(settings, false);
|
||||
if (aceSurface != nullptr) {
|
||||
aceSurface->SetShellHolder(std::move(shell_holder));
|
||||
}
|
||||
return aceSurface;
|
||||
}
|
||||
|
||||
void FlutterAceView::SurfaceCreated(FlutterAceView* view, OHOS::Window* window)
|
||||
{
|
||||
LOGI(">>> FlutterAceView::SurfaceCreated, pWnd:%{public}p", window);
|
||||
if (window == nullptr) {
|
||||
LOGE("FlutterAceView::SurfaceCreated, window is nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
if (view == nullptr) {
|
||||
LOGE("FlutterAceView::SurfaceCreated, view is nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
auto platformView = view->GetShellHolder()->GetPlatformView();
|
||||
LOGI("FlutterAceView::SurfaceCreated, GetPlatformView");
|
||||
if (platformView) {
|
||||
LOGI("FlutterAceView::SurfaceCreated, call NotifyCreated");
|
||||
platformView->NotifyCreated(window);
|
||||
}
|
||||
LOGI("<<< FlutterAceView::SurfaceCreated, end");
|
||||
}
|
||||
|
||||
void FlutterAceView::SurfaceChanged(FlutterAceView* view, int32_t width, int32_t height, int32_t orientation)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
LOGE("FlutterAceView::SurfaceChanged, view is nullptr");
|
||||
return;
|
||||
}
|
||||
|
||||
view->NotifySurfaceChanged(width, height);
|
||||
}
|
||||
|
||||
void FlutterAceView::SetViewportMetrics(FlutterAceView* view, const flutter::ViewportMetrics& metrics)
|
||||
{
|
||||
if (view) {
|
||||
view->NotifyDensityChanged(metrics.device_pixel_ratio);
|
||||
view->NotifySystemBarHeightChanged(metrics.physical_padding_top, metrics.physical_view_inset_bottom);
|
||||
auto platformView = view->GetShellHolder()->GetPlatformView();
|
||||
if (platformView) {
|
||||
platformView->SetViewportMetrics(metrics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterAceView::DispatchTouchEvent(FlutterAceView* view, OHOS::TouchEvent& touchEvent)
|
||||
{
|
||||
if (touchEvent.GetAction() == OHOS::TouchEvent::OTHER && touchEvent.GetSourceDevice() == OHOS::TouchEvent::MOUSE) {
|
||||
// mouse event
|
||||
LOGD("DispatchTouchEvent MouseEvent");
|
||||
std::shared_ptr<MultimodalEvent> multimodalEvent = touchEvent.GetMultimodalEvent();
|
||||
OHOS::MouseEvent* mouseEvent = (OHOS::MouseEvent*)multimodalEvent.get();
|
||||
if (mouseEvent == nullptr) {
|
||||
LOGE("mouseEvent is nullptr");
|
||||
return false;
|
||||
}
|
||||
view->ProcessMouseEvent(*mouseEvent);
|
||||
} else {
|
||||
// touch event
|
||||
LOGD("DispatchTouchEvent TouchEvent");
|
||||
return view->ProcessTouchEvent(touchEvent);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlutterAceView::DispatchKeyEvent(FlutterAceView* view, int32_t keyCode, int32_t action, int32_t repeatTime,
|
||||
int64_t timeStamp, int64_t timeStampStart)
|
||||
{
|
||||
if (view != nullptr) {
|
||||
return view->ProcessKeyEvent(keyCode, action, repeatTime, timeStamp, timeStampStart);
|
||||
}
|
||||
LOGE("view is null, return false!");
|
||||
return false;
|
||||
}
|
||||
|
||||
bool FlutterAceView::DispatchRotationEvent(FlutterAceView* view, float rotationValue)
|
||||
{
|
||||
if (view) {
|
||||
return view->ProcessRotationEvent(rotationValue);
|
||||
}
|
||||
LOGE("view is null, return false!");
|
||||
return false;
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterTouchEventCallback(TouchEventCallback&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
touchEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterKeyEventCallback(KeyEventCallback&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
keyEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterMouseEventCallback(MouseEventCallback&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
mouseEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterRotationEventCallback(RotationEventCallBack&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
rotationEventCallBack_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::Launch()
|
||||
{
|
||||
LOGD("Launch shell holder.");
|
||||
if (!viewLaunched_) {
|
||||
flutter::RunConfiguration config;
|
||||
shell_holder_->Launch(std::move(config));
|
||||
viewLaunched_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void FlutterAceView::SetShellHolder(std::unique_ptr<flutter::OhosShellHolder> holder)
|
||||
{
|
||||
shell_holder_ = std::move(holder);
|
||||
}
|
||||
|
||||
bool FlutterAceView::ProcessTouchEvent(OHOS::TouchEvent& touchEvent)
|
||||
{
|
||||
TouchPoint touchPoint = ConvertTouchEvent(touchEvent);
|
||||
bool forbiddenToPlatform = false;
|
||||
if (touchPoint.type != TouchType::UNKNOWN) {
|
||||
if (touchEventCallback_) {
|
||||
touchEventCallback_(touchPoint);
|
||||
}
|
||||
} else {
|
||||
LOGW("Unknown event.");
|
||||
}
|
||||
|
||||
#ifdef WEARABLE_PRODUCT
|
||||
forbiddenToPlatform = forbiddenToPlatform || IsNeedForbidToPlatform(point);
|
||||
#endif
|
||||
|
||||
// if last page, let os know so that to quit app.
|
||||
return forbiddenToPlatform || (!IsLastPage());
|
||||
}
|
||||
|
||||
void FlutterAceView::ProcessMouseEvent(OHOS::MouseEvent& mouseEvent)
|
||||
{
|
||||
MouseEvent event;
|
||||
ConvertMouseEvent(mouseEvent, event);
|
||||
LOGD("ProcessMouseEvent event");
|
||||
|
||||
if (mouseEventCallback_) {
|
||||
mouseEventCallback_(event);
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterAceView::ProcessKeyEvent(
|
||||
int32_t keyCode, int32_t keyAction, int32_t repeatTime, int64_t timeStamp, int64_t timeStampStart)
|
||||
{
|
||||
if (!keyEventCallback_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto keyEvents = keyEventRecognizer_.GetKeyEvents(keyCode, keyAction, repeatTime, timeStamp, timeStampStart);
|
||||
// First distributes special events.
|
||||
// Because the platform receives a raw event, the identified special event processing result is ignored
|
||||
if (keyEvents.size() > 1) {
|
||||
keyEventCallback_(keyEvents.back());
|
||||
}
|
||||
return keyEventCallback_(keyEvents.front());
|
||||
}
|
||||
|
||||
void FlutterAceView::ProcessIdleEvent(int64_t deadline)
|
||||
{
|
||||
if (idleCallback_) {
|
||||
idleCallback_(deadline);
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterAceView::ProcessRotationEvent(float rotationValue)
|
||||
{
|
||||
if (!rotationEventCallBack_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
RotationEvent event { .value = rotationValue * ROTATION_DIVISOR };
|
||||
|
||||
return rotationEventCallBack_(event);
|
||||
}
|
||||
|
||||
bool FlutterAceView::Dump(const std::vector<std::string>& params)
|
||||
{
|
||||
if (params.empty() || params[0] != "-drawcmd") {
|
||||
LOGE("Unsupported parameters.");
|
||||
return false;
|
||||
}
|
||||
#ifdef DUMP_DRAW_CMD
|
||||
static int32_t count = 0;
|
||||
if (shell_holder_) {
|
||||
auto screenShot = shell_holder_->Screenshot(flutter::Rasterizer::ScreenshotType::SkiaPicture, false);
|
||||
if (screenShot.data->data() != nullptr) {
|
||||
auto byteData = screenShot.data;
|
||||
auto path = ImageCache::GetImageCacheFilePath() + "/picture_" + std::to_string(count++) + ".mskp";
|
||||
if (DumpLog::GetInstance().GetDumpFile()) {
|
||||
DumpLog::GetInstance().AddDesc("Dump draw command to path: " + path);
|
||||
DumpLog::GetInstance().Print(0, "Info:", 0);
|
||||
}
|
||||
std::ofstream outFile(path, std::fstream::out | std::fstream::binary);
|
||||
if (!outFile.is_open()) {
|
||||
LOGE("Open file %{private}s failed.", path.c_str());
|
||||
return false;
|
||||
}
|
||||
outFile.write(reinterpret_cast<const char*>(byteData->data()), byteData->size());
|
||||
outFile.close();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (DumpLog::GetInstance().GetDumpFile()) {
|
||||
DumpLog::GetInstance().AddDesc("Dump draw command not support on this version.");
|
||||
DumpLog::GetInstance().Print(0, "Info:", 0);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void FlutterAceView::InitCacheFilePath(const std::string& path)
|
||||
{
|
||||
if (!path.empty()) {
|
||||
ImageCache::SetImageCacheFilePath(path);
|
||||
ImageCache::SetCacheFileInfo();
|
||||
} else {
|
||||
LOGW("image cache path empty");
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterAceView::IsLastPage() const
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId_);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return context->IsLastPage();
|
||||
}
|
||||
|
||||
uint32_t FlutterAceView::GetBackgroundColor()
|
||||
{
|
||||
return Color::WHITE.GetValue();
|
||||
}
|
||||
|
||||
// On watch device, it's probable to quit the application unexpectedly when we slide our finger diagonally upward on the
|
||||
// screen, so we do restrictions here.
|
||||
bool FlutterAceView::IsNeedForbidToPlatform(TouchPoint point)
|
||||
{
|
||||
if (point.type == TouchType::DOWN) {
|
||||
auto result = touchPointInfoMap_.try_emplace(point.id, TouchPointInfo(point.GetOffset()));
|
||||
if (!result.second) {
|
||||
result.first->second = TouchPointInfo(point.GetOffset());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
auto iter = touchPointInfoMap_.find(point.id);
|
||||
if (iter == touchPointInfoMap_.end()) {
|
||||
return false;
|
||||
}
|
||||
if (iter->second.eventState_ == EventState::HORIZONTAL_STATE) {
|
||||
return false;
|
||||
} else if (iter->second.eventState_ == EventState::VERTICAL_STATE) {
|
||||
return true;
|
||||
}
|
||||
|
||||
Offset offset = point.GetOffset() - iter->second.offset_;
|
||||
double deltaX = offset.GetX();
|
||||
double deltaY = std::abs(offset.GetY());
|
||||
|
||||
if (point.type == TouchType::MOVE) {
|
||||
if (deltaX > 0.0) {
|
||||
if (deltaY / deltaX > PERMIT_ANGLE_VALUE) {
|
||||
iter->second.eventState_ = EventState::VERTICAL_STATE;
|
||||
return true;
|
||||
} else {
|
||||
iter->second.eventState_ = EventState::HORIZONTAL_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
touchPointInfoMap_.erase(point.id);
|
||||
return deltaX > 0.0 && deltaY / deltaX > PERMIT_ANGLE_VALUE;
|
||||
}
|
||||
|
||||
std::unique_ptr<DrawDelegate> FlutterAceView::GetDrawDelegate()
|
||||
{
|
||||
auto darwDelegate = std::make_unique<DrawDelegate>();
|
||||
|
||||
darwDelegate->SetDrawFrameCallback([this](RefPtr<Flutter::Layer>& layer, const Rect& dirty) {
|
||||
if (!layer) {
|
||||
return;
|
||||
}
|
||||
RefPtr<Flutter::FlutterSceneBuilder> flutterSceneBuilder = AceType::MakeRefPtr<Flutter::FlutterSceneBuilder>();
|
||||
layer->AddToScene(*flutterSceneBuilder, 0.0, 0.0);
|
||||
auto scene = flutterSceneBuilder->Build();
|
||||
if (!flutter::UIDartState::Current()) {
|
||||
LOGE("uiDartState is nullptr");
|
||||
return;
|
||||
}
|
||||
auto window = flutter::UIDartState::Current()->window();
|
||||
if (window != nullptr && window->client() != nullptr) {
|
||||
window->client()->Render(scene.get());
|
||||
}
|
||||
});
|
||||
|
||||
return darwDelegate;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformWindow> FlutterAceView::GetPlatformWindow()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_OHOS_CPP_FLUTTER_ACE_VIEW_H
|
||||
#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_FLUTTER_ACE_VIEW_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "flutter/common/settings.h"
|
||||
#include "flutter/lib/ui/compositing/scene.h"
|
||||
#include "flutter/lib/ui/compositing/scene_builder.h"
|
||||
#include "flutter/shell/platform/ohos/ohos_shell_holder.h"
|
||||
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/common/platform_res_register.h"
|
||||
#include "core/event/key_event_recognizer.h"
|
||||
|
||||
#include "mouse_event.h"
|
||||
#include "touch_event.h"
|
||||
#include "window_manager.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
using ReleaseCallback = std::function<void()>;
|
||||
|
||||
class FlutterAceView : public AceView, public Referenced {
|
||||
public:
|
||||
FlutterAceView() = default;
|
||||
explicit FlutterAceView(int32_t id) : instanceId_(id) {}
|
||||
~FlutterAceView() override = default;
|
||||
static FlutterAceView* CreateView(int32_t instanceId);
|
||||
static void SurfaceCreated(FlutterAceView* view, OHOS::Window* window);
|
||||
static void SurfaceChanged(FlutterAceView* view, int32_t width, int32_t height, int32_t orientation);
|
||||
static void SetViewportMetrics(FlutterAceView* view, const flutter::ViewportMetrics& metrics);
|
||||
|
||||
static bool DispatchTouchEvent(FlutterAceView* view, OHOS::TouchEvent& touchEvent);
|
||||
|
||||
static bool DispatchKeyEvent(FlutterAceView* view, int32_t keyCode, int32_t action, int32_t repeatTime,
|
||||
int64_t timeStamp, int64_t timeStampStart);
|
||||
static bool DispatchRotationEvent(FlutterAceView* view, float rotationValue);
|
||||
static void InitCacheFilePath(const std::string& path);
|
||||
static uint32_t GetBackgroundColor();
|
||||
|
||||
void RegisterTouchEventCallback(TouchEventCallback&& callback) override;
|
||||
void RegisterKeyEventCallback(KeyEventCallback&& callback) override;
|
||||
void RegisterMouseEventCallback(MouseEventCallback&& callback) override;
|
||||
void RegisterRotationEventCallback(RotationEventCallBack&& callback) override;
|
||||
void RegisterCardViewPositionCallback(CardViewPositionCallBack&& callback) override {}
|
||||
void RegisterCardViewAccessibilityParamsCallback(CardViewAccessibilityParamsCallback&& callback) override {}
|
||||
|
||||
void Launch() override;
|
||||
void SetShellHolder(std::unique_ptr<flutter::OhosShellHolder> holder);
|
||||
flutter::OhosShellHolder* GetShellHolder() const
|
||||
{
|
||||
return shell_holder_.get();
|
||||
}
|
||||
|
||||
bool ProcessTouchEvent(OHOS::TouchEvent& touchEvent);
|
||||
|
||||
void ProcessMouseEvent(OHOS::MouseEvent& mouseEvent);
|
||||
|
||||
bool ProcessKeyEvent(
|
||||
int32_t keyCode, int32_t keyAction, int32_t repeatTime, int64_t timeStamp = 0, int64_t timeStampStart = 0);
|
||||
|
||||
void ProcessIdleEvent(int64_t deadline);
|
||||
|
||||
bool ProcessRotationEvent(float rotationValue);
|
||||
|
||||
int32_t GetInstanceId() const override
|
||||
{
|
||||
return instanceId_;
|
||||
}
|
||||
|
||||
void RegisterViewChangeCallback(ViewChangeCallback&& callback) override
|
||||
{
|
||||
viewChangeCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void RegisterDensityChangeCallback(DensityChangeCallback&& callback) override
|
||||
{
|
||||
densityChangeCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void RegisterSystemBarHeightChangeCallback(SystemBarHeightChangeCallbak&& callback) override
|
||||
{
|
||||
systemBarHeightChangeCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void RegisterSurfaceDestroyCallback(SurfaceDestroyCallback&& callback) override
|
||||
{
|
||||
surfaceDestroyCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void RegisterIdleCallback(IdleCallback&& callback) override
|
||||
{
|
||||
idleCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void SetPlatformResRegister(const RefPtr<PlatformResRegister>& resRegister)
|
||||
{
|
||||
resRegister_ = resRegister;
|
||||
}
|
||||
|
||||
void RegisterViewDestroyCallback(ViewDestoryCallback&& callback) override {}
|
||||
|
||||
const RefPtr<PlatformResRegister>& GetPlatformResRegister() const override
|
||||
{
|
||||
return resRegister_;
|
||||
}
|
||||
|
||||
ViewType GetViewType() const override
|
||||
{
|
||||
return AceView::ViewType::SURFACE_VIEW;
|
||||
}
|
||||
|
||||
std::unique_ptr<DrawDelegate> GetDrawDelegate() override;
|
||||
std::unique_ptr<PlatformWindow> GetPlatformWindow() override;
|
||||
bool Dump(const std::vector<std::string>& params) override;
|
||||
|
||||
private:
|
||||
void NotifySurfaceChanged(int width, int height) const
|
||||
{
|
||||
if (viewChangeCallback_) {
|
||||
viewChangeCallback_(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyDensityChanged(double density) const
|
||||
{
|
||||
if (densityChangeCallback_) {
|
||||
densityChangeCallback_(density);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifySystemBarHeightChanged(double statusBar, double navigationBar) const
|
||||
{
|
||||
if (systemBarHeightChangeCallback_) {
|
||||
systemBarHeightChangeCallback_(statusBar, navigationBar);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifySurfaceDestroyed() const
|
||||
{
|
||||
if (surfaceDestroyCallback_) {
|
||||
surfaceDestroyCallback_();
|
||||
}
|
||||
}
|
||||
|
||||
bool IsLastPage() const;
|
||||
bool IsNeedForbidToPlatform(TouchPoint point);
|
||||
|
||||
std::unique_ptr<flutter::OhosShellHolder> shell_holder_;
|
||||
TouchEventCallback touchEventCallback_;
|
||||
MouseEventCallback mouseEventCallback_;
|
||||
RotationEventCallBack rotationEventCallBack_;
|
||||
ViewChangeCallback viewChangeCallback_;
|
||||
DensityChangeCallback densityChangeCallback_;
|
||||
SystemBarHeightChangeCallbak systemBarHeightChangeCallback_;
|
||||
SurfaceDestroyCallback surfaceDestroyCallback_;
|
||||
IdleCallback idleCallback_;
|
||||
int32_t instanceId_ = 0;
|
||||
bool viewLaunched_ = false;
|
||||
RefPtr<PlatformResRegister> resRegister_;
|
||||
KeyEventCallback keyEventCallback_;
|
||||
KeyEventRecognizer keyEventRecognizer_;
|
||||
// mark the touch event's state, HORIZONTAL_STATE: the event should send to platform, VERTICAL_STATE: should not
|
||||
enum class EventState { INITIAL_STATE, HORIZONTAL_STATE, VERTICAL_STATE };
|
||||
|
||||
struct TouchPointInfo {
|
||||
Offset offset_;
|
||||
EventState eventState_ = EventState::INITIAL_STATE;
|
||||
|
||||
TouchPointInfo() = default;
|
||||
explicit TouchPointInfo(const Offset& offset) : offset_(offset) {}
|
||||
~TouchPointInfo() = default;
|
||||
};
|
||||
std::unordered_map<int32_t, TouchPointInfo> touchPointInfoMap_;
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(FlutterAceView);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_FLUTTER_ACE_VIEW_H
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_OHOS_CPP_PLATFORM_EVENT_CALLBACK_H
|
||||
#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_PLATFORM_EVENT_CALLBACK_H
|
||||
|
||||
#include "base/utils/noncopyable.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class PlatformEventCallback {
|
||||
public:
|
||||
PlatformEventCallback() = default;
|
||||
virtual ~PlatformEventCallback() = default;
|
||||
virtual void OnFinish() const = 0;
|
||||
virtual void OnStatusBarBgColorChanged(uint32_t color) = 0;
|
||||
|
||||
private:
|
||||
ACE_DISALLOW_COPY_AND_MOVE(PlatformEventCallback);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_PLATFORM_EVENT_CALLBACK_H
|
||||
@@ -0,0 +1,59 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
# build static
|
||||
template("ace_osal_ohos_source_set") {
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_source_set(target_name) {
|
||||
defines += invoker.defines
|
||||
if (is_standard_system) {
|
||||
external_deps = [
|
||||
"bytrace_standard:bytrace_core",
|
||||
"hiviewdfx_hilog_native:libhilog",
|
||||
"startup_l2:syspara",
|
||||
]
|
||||
configs = [
|
||||
"//base/startup/syspara_lite/interfaces/innerkits/native/syspara:syspara_config",
|
||||
"$ace_root:ace_config",
|
||||
"$flutter_root:flutter_config",
|
||||
]
|
||||
}
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
|
||||
sources = [
|
||||
"$ace_root/adapter/ohos/osal/ace_trace.cpp",
|
||||
"$ace_root/adapter/ohos/osal/event_report.cpp",
|
||||
"$ace_root/adapter/ohos/osal/log_wrapper.cpp",
|
||||
"$ace_root/adapter/ohos/osal/system_properties.cpp",
|
||||
]
|
||||
external_deps += [ "hisysevent_native:libhisysevent" ]
|
||||
|
||||
deps = [
|
||||
"$ace_root/adapter/common/cpp:ace_base_common_$platform",
|
||||
"//third_party/zlib:libz",
|
||||
]
|
||||
|
||||
if (is_standard_system) {
|
||||
deps += [ "$ace_root/adapter/ohos/cpp:ace_base_platform_ohos" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ace_osal_ohos_source_set("ace_osal_ohos") {
|
||||
defines = ace_ohos_defines
|
||||
platform = "ohos"
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/ace_trace.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
#include "bytrace.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/system_properties.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
pthread_key_t g_threadLocalKey;
|
||||
|
||||
bool InitThreadLocalData()
|
||||
{
|
||||
static std::once_flag onceFlag;
|
||||
static bool initialized = false;
|
||||
std::call_once(onceFlag, []() {
|
||||
auto retVal = pthread_key_create(&g_threadLocalKey, [](void* ptr) {
|
||||
if (ptr != nullptr) {
|
||||
delete reinterpret_cast<std::vector<std::string>*>(ptr);
|
||||
}
|
||||
});
|
||||
if (retVal == 0) {
|
||||
initialized = true;
|
||||
}
|
||||
});
|
||||
return initialized;
|
||||
}
|
||||
|
||||
bool PushString(const std::string& str)
|
||||
{
|
||||
auto vector = reinterpret_cast<std::vector<std::string>*>(pthread_getspecific(g_threadLocalKey));
|
||||
if (vector == nullptr) {
|
||||
vector = new std::vector<std::string>();
|
||||
if (pthread_setspecific(g_threadLocalKey, vector) != 0) {
|
||||
delete vector;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
vector->emplace_back(str);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PopString(std::string& str)
|
||||
{
|
||||
auto vector = reinterpret_cast<std::vector<std::string>*>(pthread_getspecific(g_threadLocalKey));
|
||||
if (vector == nullptr || vector->empty()) {
|
||||
return false;
|
||||
}
|
||||
str = std::move(vector->back());
|
||||
vector->pop_back();
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
bool AceTraceEnabled()
|
||||
{
|
||||
return SystemProperties::GetTraceEnabled();
|
||||
}
|
||||
|
||||
void AceTraceBegin(const char* name)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (InitThreadLocalData()) {
|
||||
std::string nameStr(name);
|
||||
if (PushString(nameStr)) {
|
||||
StartTrace(BYTRACE_TAG_ACE, nameStr);
|
||||
} else {
|
||||
LOGW("Failed push current tag name");
|
||||
}
|
||||
} else {
|
||||
LOGW("Failed to initialized local thread data");
|
||||
}
|
||||
}
|
||||
|
||||
void AceTraceEnd()
|
||||
{
|
||||
if (InitThreadLocalData()) {
|
||||
std::string nameStr;
|
||||
if (PopString(nameStr)) {
|
||||
FinishTrace(BYTRACE_TAG_ACE, nameStr);
|
||||
} else {
|
||||
LOGW("Failed pop last tag name");
|
||||
}
|
||||
} else {
|
||||
LOGW("Failed to initialized local thread data");
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,239 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/event_report.h"
|
||||
|
||||
#include <ctime>
|
||||
#include <string>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "hisysevent.h"
|
||||
|
||||
#include "base/json/json_util.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
constexpr char EVENT_KEY_ERROR_TYPE[] = "ERROR_TYPE";
|
||||
constexpr char EVENT_KEY_UID[] = "UID";
|
||||
constexpr char EVENT_KEY_PACKAGE_NAME[] = "PACKAGE_NAME";
|
||||
constexpr char EVENT_KEY_PROCESS_NAME[] = "PROCESS_NAME";
|
||||
constexpr char EVENT_KEY_MESSAGE[] = "MESSAGE";
|
||||
constexpr char EVENT_KEY_CMD[] = "CMD";
|
||||
constexpr char EVENT_KEY_TIME[] = "TIME";
|
||||
constexpr char EVENT_KEY_JS_ERR_RAW_CODE[] = "JS_ERR_RAW_CODE";
|
||||
constexpr char EVENT_KEY_REASON[] = "REASON";
|
||||
constexpr char EVENT_KEY_SUMMARY[] = "SUMMARY";
|
||||
|
||||
constexpr int32_t MAX_PACKAGE_NAME_LENGTH = 128;
|
||||
constexpr int32_t JS_CRASH_RAW_EVENT_ID = 5002;
|
||||
constexpr int32_t JS_ERR_RAW_CODE = 3;
|
||||
constexpr int32_t UIP_WARNING_EVENT_ID = 10257;
|
||||
constexpr int32_t UIP_FREEZE_EVENT_ID = 10258;
|
||||
constexpr int32_t UIP_RECOVER_EVENT_ID = 10280;
|
||||
|
||||
constexpr char DUMP_LOG_COMMAND[] = "B";
|
||||
|
||||
void StrTrim(std::string& str)
|
||||
{
|
||||
if (str.size() > MAX_PACKAGE_NAME_LENGTH) {
|
||||
str = str.substr(0, MAX_PACKAGE_NAME_LENGTH);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void EventReport::SendEvent(const EventInfo& eventInfo)
|
||||
{
|
||||
auto packageName = AceEngine::Get().GetPackageName();
|
||||
if (packageName.size() > MAX_PACKAGE_NAME_LENGTH) {
|
||||
StrTrim(packageName);
|
||||
}
|
||||
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, std::to_string(eventInfo.eventType),
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_ERROR_TYPE, eventInfo.errorType,
|
||||
EVENT_KEY_PACKAGE_NAME, packageName);
|
||||
}
|
||||
|
||||
void EventReport::SendAppStartException(AppStartExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_FRAMEWORK_APP_START,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendPageRouterException(PageRouterExcepType type, const std::string& pageUrl)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_FRAMEWORK_PAGE_ROUTER,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
.pageUrl = pageUrl,
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendComponentException(ComponentExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_COMPONENT,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendAPIChannelException(APIChannelExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_API_CHANNEL,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendRenderException(RenderExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_RENDER,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendJsException(JsExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_JS,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendAnimationException(AnimationExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_ANIMATION,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendEventException(EventExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_EVENT,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendInternalException(InternalExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_INTERNATIONALIZATION,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendAccessibilityException(AccessibilityExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_ACCESSIBILITY,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::SendFormException(FormExcepType type)
|
||||
{
|
||||
EventInfo eventInfo = {
|
||||
.eventType = EXCEPTION_FORM,
|
||||
.errorType = static_cast<int32_t>(type),
|
||||
};
|
||||
|
||||
SendEventInner(eventInfo);
|
||||
}
|
||||
|
||||
void EventReport::JsEventReport(int32_t eventType, const std::string& jsonStr)
|
||||
{
|
||||
if (!JsonUtil::ParseJsonString(jsonStr)) {
|
||||
LOGE("jsonStr is not a JsonArray.");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void EventReport::JsErrReport(
|
||||
int32_t uid, const std::string& packageName, const std::string& reason, const std::string& summary)
|
||||
{
|
||||
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, std::to_string(JS_CRASH_RAW_EVENT_ID),
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_TIME, std::to_string((int32_t)std::time(nullptr)),
|
||||
EVENT_KEY_UID, std::to_string(uid),
|
||||
EVENT_KEY_JS_ERR_RAW_CODE, std::to_string(JS_ERR_RAW_CODE),
|
||||
EVENT_KEY_PACKAGE_NAME, packageName,
|
||||
EVENT_KEY_REASON, reason,
|
||||
EVENT_KEY_SUMMARY, summary);
|
||||
}
|
||||
|
||||
void EventReport::ANRRawReport(RawEventType type, int32_t uid, const std::string& packageName,
|
||||
const std::string& processName, const std::string& msg)
|
||||
{
|
||||
int32_t pid = getpid();
|
||||
int32_t eventId = 0;
|
||||
std::string cmd = " ";
|
||||
if (type == RawEventType::WARNING) {
|
||||
eventId = UIP_WARNING_EVENT_ID;
|
||||
cmd = "p=" + std::to_string(pid);
|
||||
} else if (type == RawEventType::FREEZE) {
|
||||
eventId = UIP_FREEZE_EVENT_ID;
|
||||
cmd = DUMP_LOG_COMMAND;
|
||||
} else {
|
||||
eventId = UIP_RECOVER_EVENT_ID;
|
||||
}
|
||||
std::string eventIdStr = std::to_string(eventId);
|
||||
std::string uidStr = std::to_string(uid);
|
||||
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, eventIdStr,
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_UID, uidStr,
|
||||
EVENT_KEY_PACKAGE_NAME, packageName,
|
||||
EVENT_KEY_PROCESS_NAME, processName,
|
||||
EVENT_KEY_MESSAGE, msg,
|
||||
EVENT_KEY_CMD, cmd);
|
||||
}
|
||||
|
||||
void EventReport::SendEventInner(const EventInfo& eventInfo)
|
||||
{
|
||||
auto packageName = AceEngine::Get().GetPackageName();
|
||||
StrTrim(packageName);
|
||||
OHOS::HiviewDFX::HiSysEvent::Write(OHOS::HiviewDFX::HiSysEvent::Domain::ACE, std::to_string(eventInfo.eventType),
|
||||
OHOS::HiviewDFX::HiSysEvent::EventType::FAULT,
|
||||
EVENT_KEY_ERROR_TYPE, eventInfo.errorType,
|
||||
EVENT_KEY_PACKAGE_NAME, packageName);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_OHOS_CPP_FAKE_ASSET_MANAGER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_FAKE_ASSET_MANAGER_H
|
||||
|
||||
#include "base/resource/asset_manager.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class FakeAsset final : public Asset {
|
||||
public:
|
||||
~FakeAsset() override = default;
|
||||
|
||||
size_t GetSize() const override
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
const uint8_t* GetData() const override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
class FakeAssetManager final : public AssetManager {
|
||||
public:
|
||||
~FakeAssetManager() override = default;
|
||||
|
||||
RefPtr<Asset> GetAsset(const std::string& assetName) override
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_FAKE_ASSET_MANAGER_H
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_OHOS_CPP_FAKE_TASK_EXECUTOR_H
|
||||
#define FOUNDATION_ACE_ADAPTER_OHOS_CPP_FAKE_TASK_EXECUTOR_H
|
||||
|
||||
#include "base/thread/background_task_executor.h"
|
||||
#include "base/thread/task_executor.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class FakeTaskExecutor final : public TaskExecutor {
|
||||
public:
|
||||
bool WillRunOnCurrentThread(TaskType type) const final
|
||||
{
|
||||
switch (type) {
|
||||
case TaskType::PLATFORM:
|
||||
case TaskType::UI:
|
||||
case TaskType::IO:
|
||||
case TaskType::GPU:
|
||||
case TaskType::JS:
|
||||
return false;
|
||||
case TaskType::BACKGROUND:
|
||||
// Always return false for background tasks.
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void AddTaskObserver(Task&& callback) {}
|
||||
void RemoveTaskObserver() {}
|
||||
|
||||
private:
|
||||
bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const final
|
||||
{
|
||||
switch (type) {
|
||||
case TaskType::PLATFORM:
|
||||
case TaskType::UI:
|
||||
case TaskType::IO:
|
||||
case TaskType::GPU:
|
||||
case TaskType::JS:
|
||||
return false;
|
||||
case TaskType::BACKGROUND:
|
||||
// Ignore delay time
|
||||
return BackgroundTaskExecutor::GetInstance().PostTask(std::move(task));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_OHOS_CPP_FAKE_TASK_EXECUTOR_H
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/log_wrapper.h"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
#include "hilog/log.h"
|
||||
|
||||
extern "C" {
|
||||
int HiLogPrintArgs(LogType type, LogLevel level, unsigned int domain, const char* tag, const char* fmt, va_list ap);
|
||||
}
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
namespace {
|
||||
|
||||
const ::LogLevel LOG_LEVELS[] = {
|
||||
LOG_DEBUG,
|
||||
LOG_INFO,
|
||||
LOG_WARN,
|
||||
LOG_ERROR,
|
||||
LOG_FATAL,
|
||||
};
|
||||
|
||||
const char* LOG_TAGS[] = {
|
||||
"Ace",
|
||||
"JSApp",
|
||||
};
|
||||
|
||||
constexpr uint32_t LOG_DOMAINS[] = {
|
||||
0xD003900,
|
||||
0xD003B00,
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
// initial static member object
|
||||
LogLevel LogWrapper::level_ = LogLevel::DEBUG;
|
||||
|
||||
char LogWrapper::GetSeparatorCharacter()
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
|
||||
void LogWrapper::PrintLog(LogDomain domain, LogLevel level, const char* fmt, va_list args)
|
||||
{
|
||||
HiLogPrintArgs(LOG_CORE, LOG_LEVELS[static_cast<uint32_t>(level)], LOG_DOMAINS[static_cast<uint32_t>(domain)],
|
||||
LOG_TAGS[static_cast<uint32_t>(domain)], fmt, args);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/utils/system_properties.h"
|
||||
#include "core/common/ace_application_info.h"
|
||||
|
||||
#include "parameters.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
const char PROPERTY_DEVICE_TYPE[] = "ro.build.characteristics";
|
||||
const char PROPERTY_DEVICE_TYPE_DEFAULT[] = "default";
|
||||
const char PROPERTY_DEVICE_TYPE_TV[] = "tv";
|
||||
const char PROPERTY_DEVICE_TYPE_WATCH[] = "watch";
|
||||
const char PROPERTY_DEVICE_TYPE_CAR[] = "car";
|
||||
|
||||
constexpr int32_t ORIENTATION_PORTRAIT = 0;
|
||||
constexpr int32_t ORIENTATION_LANDSCAPE = 1;
|
||||
|
||||
void Swap(int32_t& deviceWidth, int32_t& deviceHeight)
|
||||
{
|
||||
int32_t temp = deviceWidth;
|
||||
deviceWidth = deviceHeight;
|
||||
deviceHeight = temp;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SystemProperties::InitDeviceType(DeviceType)
|
||||
{
|
||||
// Do nothing, no need to store type here, use system property at 'GetDeviceType' instead.
|
||||
}
|
||||
|
||||
bool SystemProperties::traceEnabled_ = system::GetParameter("persist.ace.trace.enabled", "0") == "1";
|
||||
bool SystemProperties::isRound_ = false;
|
||||
int32_t SystemProperties::width_ = 0;
|
||||
int32_t SystemProperties::height_ = 0;
|
||||
int32_t SystemProperties::deviceWidth_ = 0;
|
||||
int32_t SystemProperties::deviceHeight_ = 0;
|
||||
double SystemProperties::resolution_ = 1.0;
|
||||
DeviceType SystemProperties::deviceType_ { DeviceType::UNKNOWN };
|
||||
DeviceOrientation SystemProperties::orientation_ { DeviceOrientation::PORTRAIT };
|
||||
std::string SystemProperties::brand_ = INVALID_PARAM;
|
||||
std::string SystemProperties::manufacturer_ = INVALID_PARAM;
|
||||
std::string SystemProperties::model_ = INVALID_PARAM;
|
||||
std::string SystemProperties::product_ = INVALID_PARAM;
|
||||
std::string SystemProperties::apiVersion_ = INVALID_PARAM;
|
||||
std::string SystemProperties::releaseType_ = INVALID_PARAM;
|
||||
std::string SystemProperties::paramDeviceType_ = INVALID_PARAM;
|
||||
int32_t SystemProperties::mcc_ = MCC_UNDEFINED;
|
||||
int32_t SystemProperties::mnc_ = MNC_UNDEFINED;
|
||||
ColorMode SystemProperties::colorMode_ { ColorMode::LIGHT };
|
||||
|
||||
void SystemProperties::UpdateSurfaceStatus(int32_t width, int32_t height)
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
DeviceType SystemProperties::GetDeviceType()
|
||||
{
|
||||
InitDeviceTypeBySystemProperty();
|
||||
return deviceType_;
|
||||
}
|
||||
|
||||
void SystemProperties::InitDeviceTypeBySystemProperty()
|
||||
{
|
||||
if (deviceType_ != DeviceType::UNKNOWN) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto deviceProp = system::GetParameter(PROPERTY_DEVICE_TYPE, PROPERTY_DEVICE_TYPE_DEFAULT);
|
||||
// Properties: "default", "tv", "tablet", "watch", "car"
|
||||
LOGD("GetDeviceType, deviceProp=%{private}s.", deviceProp.c_str());
|
||||
if (deviceProp == PROPERTY_DEVICE_TYPE_TV) {
|
||||
deviceType_ = DeviceType::TV;
|
||||
} else if (deviceProp == PROPERTY_DEVICE_TYPE_CAR) {
|
||||
deviceType_ = DeviceType::CAR;
|
||||
} else if (deviceProp == PROPERTY_DEVICE_TYPE_WATCH) {
|
||||
deviceType_ = DeviceType::WATCH;
|
||||
} else {
|
||||
deviceType_ = DeviceType::PHONE;
|
||||
}
|
||||
}
|
||||
|
||||
void SystemProperties::InitDeviceInfo(int32_t deviceWidth, int32_t deviceHeight, int32_t orientation,
|
||||
double resolution, bool isRound)
|
||||
{
|
||||
// SetDeviceOrientation should be eralier than deviceWidth/deviceHeight init.
|
||||
SetDeviceOrientation(orientation);
|
||||
|
||||
isRound_ = isRound;
|
||||
resolution_ = resolution;
|
||||
deviceWidth_ = deviceWidth;
|
||||
deviceHeight_ = deviceHeight;
|
||||
brand_ = system::GetParameter("ro.product.brand", INVALID_PARAM);
|
||||
manufacturer_ = system::GetParameter("ro.product.manufacturer", INVALID_PARAM);
|
||||
model_ = system::GetParameter("ro.product.model", INVALID_PARAM);
|
||||
product_ = system::GetParameter("ro.product.name", INVALID_PARAM);
|
||||
apiVersion_ = system::GetParameter("hw_sc.build.os.apiversion", INVALID_PARAM);
|
||||
releaseType_ = system::GetParameter("hw_sc.build.os.releasetype", INVALID_PARAM);
|
||||
paramDeviceType_ = system::GetParameter("hw_sc.build.os.devicetype", INVALID_PARAM);
|
||||
|
||||
InitDeviceTypeBySystemProperty();
|
||||
}
|
||||
|
||||
void SystemProperties::SetDeviceOrientation(int32_t orientation)
|
||||
{
|
||||
if (orientation == ORIENTATION_PORTRAIT && orientation_ != DeviceOrientation::PORTRAIT) {
|
||||
Swap(deviceWidth_, deviceHeight_);
|
||||
orientation_ = DeviceOrientation::PORTRAIT;
|
||||
} else if (orientation == ORIENTATION_LANDSCAPE && orientation_ != DeviceOrientation::LANDSCAPE) {
|
||||
Swap(deviceWidth_, deviceHeight_);
|
||||
orientation_ = DeviceOrientation::LANDSCAPE;
|
||||
} else {
|
||||
LOGW("SetDeviceOrientation, undefined orientation");
|
||||
}
|
||||
}
|
||||
|
||||
float SystemProperties::GetFontWeightScale()
|
||||
{
|
||||
// Default value of font weight scale is 1.0.
|
||||
std::string prop =
|
||||
"persist.sys.font_wght_scale_for_user" + std::to_string(AceApplicationInfo::GetInstance().GetUserId());
|
||||
return std::stof(system::GetParameter(prop, "1.0"));
|
||||
}
|
||||
|
||||
void SystemProperties::InitMccMnc(int32_t mcc, int32_t mnc)
|
||||
{
|
||||
mcc_ = mcc;
|
||||
mnc_ = mnc;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,70 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
template("libace_engine") {
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_shared_library(target_name) {
|
||||
defines += invoker.defines
|
||||
sources = [
|
||||
"$ace_root/adapter/common/cpp/ace_res_config.cpp",
|
||||
"$ace_root/adapter/common/cpp/ace_res_key_parser.cpp",
|
||||
"$ace_root/adapter/common/cpp/ace_trace.cpp",
|
||||
"$ace_root/adapter/common/cpp/localization.cpp",
|
||||
"$ace_root/adapter/common/cpp/thread_util.cpp",
|
||||
"$ace_root/adapter/preview/osal/download_manager.cpp",
|
||||
"ace_ability.cpp",
|
||||
"ace_application_info.cpp",
|
||||
"ace_container.cpp",
|
||||
"ace_resource_register.cpp",
|
||||
"flutter_ace_view.cpp",
|
||||
"flutter_window.cpp",
|
||||
]
|
||||
|
||||
configs = [
|
||||
"$ace_root:ace_config",
|
||||
"$flutter_root:flutter_config",
|
||||
"$flutter_root:flutter_glfw_config",
|
||||
"$flutter_root:icu_config_$platform",
|
||||
"//third_party/curl:curl_config",
|
||||
]
|
||||
|
||||
cflags = [ "-std=c++17" ]
|
||||
deps = [
|
||||
"$ace_root/frameworks/base:ace_base_$platform",
|
||||
"$ace_root/frameworks/bridge:js_engine_$platform",
|
||||
"$ace_root/frameworks/core:ace_core_$platform",
|
||||
"$flutter_root:ace_skia_$platform",
|
||||
"//third_party/curl:curl",
|
||||
]
|
||||
if (platform == "windows") {
|
||||
defines += [ "NOGDI" ]
|
||||
}
|
||||
if (platform == "mac") {
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
libace_engine("libace_engine_windows") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
}
|
||||
|
||||
libace_engine("libace_engine_mac") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
}
|
||||
@@ -0,0 +1,294 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/ace_ability.h"
|
||||
|
||||
#include <thread>
|
||||
|
||||
#include "adapter/preview/entrance/ace_application_info.h"
|
||||
#include "adapter/preview/entrance/ace_container.h"
|
||||
#include "frameworks/bridge/common/inspector/inspector_client.h"
|
||||
#include "frameworks/bridge/common/utils/utils.h"
|
||||
#include "frameworks/bridge/js_frontend/js_frontend.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
std::atomic<bool> AceAbility::loopRunning_ = true;
|
||||
|
||||
namespace {
|
||||
|
||||
// JS frontend maintain the page ID self, so it's useless to pass page ID from platform
|
||||
// layer, neither OpenHarmony or Windows.
|
||||
constexpr int32_t UNUSED_PAGE_ID = 1;
|
||||
|
||||
// Different with mobile, we don't support multi-instances in Windows, because we only want
|
||||
// preivew UI effect, it doesn't make scense to create multi ability in one process.
|
||||
constexpr int32_t ACE_INSTANCE_ID = 0;
|
||||
|
||||
constexpr char ASSET_PATH_SHARE[] = "share";
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
constexpr char DELIMITER[] = "\\";
|
||||
#else
|
||||
constexpr char DELIMITER[] = "/";
|
||||
#endif
|
||||
|
||||
#ifdef USE_GLFW_WINDOW
|
||||
// Screen Density Coefficient/Base Density = Resolution/ppi
|
||||
constexpr double SCREEN_DENSITY_COEFFICIENT_PHONE = 1080.0 * 160.0 / 480.0;
|
||||
constexpr double SCREEN_DENSITY_COEFFICIENT_WATCH = 466.0 * 160 / 320.0;
|
||||
constexpr double SCREEN_DENSITY_COEFFICIENT_TABLE = 2560.0 * 160.0 / 280.0;
|
||||
constexpr double SCREEN_DENSITY_COEFFICIENT_TV = 3840.0 * 160.0 / 640.0;
|
||||
#endif
|
||||
} // namespace
|
||||
|
||||
std::unique_ptr<AceAbility> AceAbility::CreateInstance(AceRunArgs& runArgs)
|
||||
{
|
||||
LOGI("Start create AceAbility instance");
|
||||
bool initSucceeded = FlutterDesktopInit();
|
||||
if (!initSucceeded) {
|
||||
LOGE("Could not create window; AceDesktopInit failed.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
AceApplicationInfo::GetInstance().SetLocale(runArgs.language, runArgs.region, runArgs.script, "");
|
||||
|
||||
auto controller = FlutterDesktopCreateWindow(
|
||||
runArgs.deviceWidth, runArgs.deviceHeight, runArgs.windowTitle.c_str(), runArgs.onRender);
|
||||
auto aceAbility = std::make_unique<AceAbility>(runArgs);
|
||||
aceAbility->SetGlfwWindowController(controller);
|
||||
return aceAbility;
|
||||
}
|
||||
|
||||
bool AceAbility::DispatchTouchEvent(const TouchPoint& event)
|
||||
{
|
||||
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
|
||||
if (!container) {
|
||||
LOGE("container is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
auto aceView = container->GetAceView();
|
||||
if (!aceView) {
|
||||
LOGE("aceView is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
std::promise<bool> touchPromise;
|
||||
std::future<bool> touchFuture = touchPromise.get_future();
|
||||
container->GetTaskExecutor()->PostTask(
|
||||
[aceView, event, &touchPromise]() {
|
||||
bool isHandled = aceView->HandleTouchEvent(event);
|
||||
touchPromise.set_value(isHandled);
|
||||
},
|
||||
TaskExecutor::TaskType::PLATFORM);
|
||||
return touchFuture.get();
|
||||
}
|
||||
|
||||
bool AceAbility::DispatchBackPressedEvent()
|
||||
{
|
||||
LOGI("DispatchBackPressedEvent start ");
|
||||
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto context = container->GetPipelineContext();
|
||||
if (!context) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::promise<bool> backPromise;
|
||||
std::future<bool> backFuture = backPromise.get_future();
|
||||
container->GetTaskExecutor()->PostTask(
|
||||
[container, context, &backPromise]() {
|
||||
bool canBack = false;
|
||||
if (context->IsLastPage()) {
|
||||
LOGW("Can't back because this is the last page!");
|
||||
} else {
|
||||
canBack = context->CallRouterBackToPopPage();
|
||||
}
|
||||
backPromise.set_value(canBack);
|
||||
},
|
||||
TaskExecutor::TaskType::PLATFORM);
|
||||
return backFuture.get();
|
||||
}
|
||||
|
||||
AceAbility::AceAbility(const AceRunArgs& runArgs) : runArgs_(runArgs)
|
||||
{
|
||||
SystemProperties::InitDeviceInfo(runArgs_.deviceWidth, runArgs_.deviceHeight,
|
||||
runArgs_.orientation == DeviceOrientation::PORTRAIT ? 0 : 1, runArgs_.resolution, runArgs_.isRound);
|
||||
SystemProperties::InitDeviceType(runArgs_.deviceType);
|
||||
SystemProperties::SetColorMode(runArgs_.colorMode == OHOS::Ace::Platform::ColorMode::DARK ?
|
||||
OHOS::Ace::ColorMode::DARK : OHOS::Ace::ColorMode::LIGHT);
|
||||
if (runArgs_.formsEnabled) {
|
||||
LOGI("CreateContainer with JS_CARD frontend");
|
||||
AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::JS_CARD);
|
||||
} else {
|
||||
LOGI("CreateContainer with JS frontend");
|
||||
AceContainer::CreateContainer(ACE_INSTANCE_ID, FrontendType::JS);
|
||||
}
|
||||
}
|
||||
|
||||
AceAbility::~AceAbility()
|
||||
{
|
||||
if (controller_) {
|
||||
FlutterDesktopDestroyWindow(controller_);
|
||||
}
|
||||
FlutterDesktopTerminate();
|
||||
}
|
||||
|
||||
std::string GetCustomAssetPath(std::string assetPath)
|
||||
{
|
||||
if (assetPath.empty()) {
|
||||
LOGE("AssetPath is null.");
|
||||
return std::string();
|
||||
}
|
||||
std::string customAssetPath;
|
||||
if (OHOS::Ace::Framework::EndWith(assetPath, DELIMITER)) {
|
||||
assetPath = assetPath.substr(0, assetPath.size() - 1);
|
||||
}
|
||||
customAssetPath = assetPath.substr(0, assetPath.find_last_of(DELIMITER) + 1);
|
||||
return customAssetPath;
|
||||
}
|
||||
|
||||
void AceAbility::InitEnv()
|
||||
{
|
||||
AceContainer::AddAssetPath(
|
||||
ACE_INSTANCE_ID, "", { runArgs_.assetPath, GetCustomAssetPath(runArgs_.assetPath).append(ASSET_PATH_SHARE) });
|
||||
|
||||
AceContainer::SetResourcesPathAndThemeStyle(ACE_INSTANCE_ID, runArgs_.resourcesPath,
|
||||
runArgs_.themeId, runArgs_.colorMode);
|
||||
|
||||
auto view = new FlutterAceView(ACE_INSTANCE_ID);
|
||||
AceContainer::SetView(view, runArgs_.resolution, runArgs_.deviceWidth, runArgs_.deviceHeight);
|
||||
IdleCallback idleNoticeCallback = [view](int64_t deadline) { view->ProcessIdleEvent(deadline); };
|
||||
FlutterDesktopSetIdleCallback(controller_, idleNoticeCallback);
|
||||
|
||||
// Should make it possible to update surface changes by using viewWidth and viewHeight.
|
||||
view->NotifySurfaceChanged(runArgs_.deviceWidth, runArgs_.deviceHeight);
|
||||
view->NotifyDensityChanged(runArgs_.resolution);
|
||||
}
|
||||
|
||||
void AceAbility::Start()
|
||||
{
|
||||
AceContainer::RunPage(ACE_INSTANCE_ID, UNUSED_PAGE_ID, runArgs_.url, "");
|
||||
RunEventLoop();
|
||||
}
|
||||
|
||||
void AceAbility::Stop()
|
||||
{
|
||||
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
container->GetTaskExecutor()->PostTask([]() { loopRunning_ = false; }, TaskExecutor::TaskType::PLATFORM);
|
||||
}
|
||||
|
||||
#ifdef USE_GLFW_WINDOW
|
||||
void AdaptDeviceType(AceRunArgs& runArgs)
|
||||
{
|
||||
if (runArgs.deviceType == DeviceType::PHONE) {
|
||||
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_PHONE;
|
||||
} else if (runArgs.deviceType == DeviceType::WATCH) {
|
||||
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_WATCH;
|
||||
} else if (runArgs.deviceType == DeviceType::TABLET) {
|
||||
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TABLE;
|
||||
} else if (runArgs.deviceType == DeviceType::TV) {
|
||||
runArgs.resolution = runArgs.deviceWidth / SCREEN_DENSITY_COEFFICIENT_TV;
|
||||
} else {
|
||||
LOGE("DeviceType not supported");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void AceAbility::RunEventLoop()
|
||||
{
|
||||
while (!FlutterDesktopWindowShouldClose(controller_) && loopRunning_) {
|
||||
FlutterDesktopWaitForEvents(controller_);
|
||||
#ifdef USE_GLFW_WINDOW
|
||||
auto window = FlutterDesktopGetWindow(controller_);
|
||||
int width;
|
||||
int height;
|
||||
FlutterDesktopGetFramebufferSize(window, &width, &height);
|
||||
if (width != runArgs_.deviceWidth || height != runArgs_.deviceHeight) {
|
||||
AdaptDeviceType(runArgs_);
|
||||
SurfaceChanged(runArgs_.orientation, width, height, runArgs_.resolution);
|
||||
}
|
||||
#endif
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
loopRunning_ = true;
|
||||
|
||||
// Currently exit loop is only to restart the AceContainer for real-time preivew case.
|
||||
// Previewer background thread will release the AceAbility instance and create new one,
|
||||
// then call the InitEnv() and Start() again.
|
||||
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
|
||||
if (!container) {
|
||||
LOGE("container is null");
|
||||
FlutterDesktopDestroyWindow(controller_);
|
||||
controller_ = nullptr;
|
||||
return;
|
||||
}
|
||||
auto viewPtr = container->GetAceView();
|
||||
AceContainer::DestroyContainer(ACE_INSTANCE_ID);
|
||||
|
||||
FlutterDesktopDestroyWindow(controller_);
|
||||
if (viewPtr != nullptr) {
|
||||
delete viewPtr;
|
||||
viewPtr = nullptr;
|
||||
}
|
||||
controller_ = nullptr;
|
||||
}
|
||||
|
||||
void AceAbility::SurfaceChanged(
|
||||
const DeviceOrientation& orientation, const int32_t& width, const int32_t& height, const double& resolution)
|
||||
{
|
||||
SystemProperties::InitDeviceInfo(
|
||||
width, height, orientation == DeviceOrientation::PORTRAIT ? 0 : 1, resolution, runArgs_.isRound);
|
||||
auto container = AceContainer::GetContainerInstance(ACE_INSTANCE_ID);
|
||||
if (!container) {
|
||||
LOGE("container is null, SurfaceChanged failed.");
|
||||
return;
|
||||
}
|
||||
|
||||
auto viewPtr = container->GetAceView();
|
||||
if (viewPtr == nullptr) {
|
||||
LOGE("aceView is null, SurfaceChanged failed.");
|
||||
return;
|
||||
}
|
||||
viewPtr->NotifySurfaceChanged(width, height);
|
||||
viewPtr->NotifyDensityChanged(resolution);
|
||||
runArgs_.orientation = orientation;
|
||||
runArgs_.deviceWidth = width;
|
||||
runArgs_.deviceHeight = height;
|
||||
runArgs_.resolution = resolution;
|
||||
}
|
||||
|
||||
std::string AceAbility::GetJSONTree()
|
||||
{
|
||||
std::string jsonTreeStr;
|
||||
OHOS::Ace::Framework::InspectorClient::GetInstance().AssembleJSONTreeStr(jsonTreeStr);
|
||||
return jsonTreeStr;
|
||||
}
|
||||
|
||||
std::string AceAbility::GetDefaultJSONTree()
|
||||
{
|
||||
std::string defaultJsonTreeStr;
|
||||
OHOS::Ace::Framework::InspectorClient::GetInstance().AssembleDefaultJSONTreeStr(defaultJsonTreeStr);
|
||||
return defaultJsonTreeStr;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_ABILITY_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_ABILITY_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include "flutter/shell/platform/glfw/public/flutter_glfw.h"
|
||||
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
#include "core/gestures/touch_event.h"
|
||||
|
||||
#ifndef ACE_PREVIEW_EXPORT
|
||||
#ifdef _WIN32
|
||||
#define ACE_PREVIEW_EXPORT __declspec(dllexport)
|
||||
#elif defined(__APPLE__)
|
||||
#define ACE_PREVIEW_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif // ACE_PREVIEW_EXPORT
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class ACE_PREVIEW_EXPORT AceAbility {
|
||||
|
||||
public:
|
||||
static std::unique_ptr<AceAbility> CreateInstance(AceRunArgs& runArgs);
|
||||
|
||||
// Be called in Previewer frontend thread, which is not ACE platform thread.
|
||||
static void Stop();
|
||||
static bool DispatchTouchEvent(const TouchPoint& event);
|
||||
static bool DispatchBackPressedEvent();
|
||||
|
||||
explicit AceAbility(const AceRunArgs& runArgs);
|
||||
~AceAbility();
|
||||
|
||||
void InitEnv();
|
||||
void Start();
|
||||
void SurfaceChanged(
|
||||
const DeviceOrientation& orientation, const int32_t& width, const int32_t& height, const double& resolution);
|
||||
std::string GetJSONTree();
|
||||
std::string GetDefaultJSONTree();
|
||||
|
||||
private:
|
||||
void RunEventLoop();
|
||||
|
||||
void SetGlfwWindowController(const FlutterDesktopWindowControllerRef& controller)
|
||||
{
|
||||
controller_ = controller;
|
||||
}
|
||||
|
||||
// flag indicating if the glfw message loop should be running.
|
||||
static std::atomic<bool> loopRunning_;
|
||||
|
||||
AceRunArgs runArgs_;
|
||||
FlutterDesktopWindowControllerRef controller_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_ABILITY_H
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/ace_application_info.h"
|
||||
|
||||
#include "unicode/locid.h"
|
||||
|
||||
#include "adapter/common/cpp/ace_res_config.h"
|
||||
#include "adapter/common/cpp/ace_res_data_struct.h"
|
||||
#include "base/i18n/localization.h"
|
||||
#include "base/log/ace_trace.h"
|
||||
#include "base/log/log.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dirent.h>
|
||||
#include <sys/types.h>
|
||||
#endif
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
void AceApplicationInfoImpl::ChangeLocale(const std::string& language, const std::string& countryOrRegion) {}
|
||||
|
||||
std::vector<std::string> AceApplicationInfoImpl::GetLocaleFallback(const std::vector<std::string>& localeList) const
|
||||
{
|
||||
std::vector<std::string> fileList;
|
||||
AceResConfig::MatchAndSortI18nConfigs(localeList, localeTag_, fileList);
|
||||
return fileList;
|
||||
}
|
||||
|
||||
std::vector<std::string> AceApplicationInfoImpl::GetResourceFallback(const std::vector<std::string>& resourceList) const
|
||||
{
|
||||
std::vector<std::string> fileList;
|
||||
std::string deviceConfigTag = GetCurrentDeviceResTag();
|
||||
AceResConfig::MatchAndSortResConfigs(resourceList, deviceConfigTag, fileList);
|
||||
return fileList;
|
||||
}
|
||||
|
||||
std::string AceApplicationInfoImpl::GetCurrentDeviceResTag() const
|
||||
{
|
||||
ResolutionType resolutionType = AceResConfig::GetResolutionType(SystemProperties::GetResolution());
|
||||
AceResConfig deviceResConfig = AceResConfig(SystemProperties::GetMcc(), SystemProperties::GetMnc(),
|
||||
SystemProperties::GetDevcieOrientation(), SystemProperties::GetColorMode(), SystemProperties::GetDeviceType(),
|
||||
resolutionType);
|
||||
return AceResConfig::ConvertResConfigToTag(deviceResConfig);
|
||||
}
|
||||
|
||||
void AceApplicationInfoImpl::SetLocale(const std::string& language, const std::string& countryOrRegion,
|
||||
const std::string& script, const std::string& keywordsAndValues)
|
||||
{
|
||||
language_ = language;
|
||||
countryOrRegion_ = countryOrRegion;
|
||||
script_ = script;
|
||||
keywordsAndValues_ = keywordsAndValues;
|
||||
|
||||
localeTag_ = language;
|
||||
if (!script_.empty()) {
|
||||
localeTag_.append("-" + script_);
|
||||
}
|
||||
localeTag_.append("-" + countryOrRegion_);
|
||||
|
||||
icu::Locale locale(language_.c_str(), countryOrRegion.c_str());
|
||||
isRightToLeft_ = locale.isRightToLeft();
|
||||
|
||||
auto languageList = Localization::GetLanguageList(language_);
|
||||
Localization::SetLocale(
|
||||
language_, countryOrRegion_, script, languageList.front(), keywordsAndValues_);
|
||||
}
|
||||
|
||||
bool AceApplicationInfoImpl::GetFiles(const std::string& filePath, std::vector<std::string>& fileList) const
|
||||
{
|
||||
const auto& assetBasePathSet = AceEngine::Get().GetAssetBasePath();
|
||||
if (assetBasePathSet.empty()) {
|
||||
LOGE("the assetBasePathSet is empty");
|
||||
return false;
|
||||
}
|
||||
std::vector<std::string> assetPaths;
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
for (const auto& assetBasePath : assetBasePathSet) {
|
||||
assetPaths.emplace_back(assetBasePath + "\\" + filePath);
|
||||
}
|
||||
for (const auto& path : assetPaths) {
|
||||
std::string filePath(path);
|
||||
WIN32_FIND_DATA fileInfo;
|
||||
HANDLE hFind;
|
||||
if ((hFind = FindFirstFile(filePath.append("\\*").c_str(), &fileInfo)) != INVALID_HANDLE_VALUE) {
|
||||
do {
|
||||
if (strcmp(fileInfo.cFileName, ".") != 0 && strcmp(fileInfo.cFileName, "..") != 0) {
|
||||
fileList.push_back(fileInfo.cFileName);
|
||||
}
|
||||
} while (FindNextFile(hFind, &fileInfo) != 0);
|
||||
FindClose(hFind);
|
||||
}
|
||||
}
|
||||
#elif defined(MAC_PLATFORM)
|
||||
for (const auto& assetBasePath : assetBasePathSet) {
|
||||
assetPaths.emplace_back(assetBasePath + "/" + filePath);
|
||||
}
|
||||
for (const auto& assetPath : assetPaths) {
|
||||
DIR* dp = nullptr;
|
||||
if (nullptr == (dp = opendir(assetPath.c_str()))) {
|
||||
continue;
|
||||
}
|
||||
struct dirent* dptr = nullptr;
|
||||
while ((dptr = readdir(dp)) != nullptr) {
|
||||
if (strcmp(dptr->d_name, ".") != 0 && strcmp(dptr->d_name, "..") != 0) {
|
||||
fileList.push_back(dptr->d_name);
|
||||
}
|
||||
}
|
||||
closedir(dp);
|
||||
}
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
bool AceApplicationInfoImpl::GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
double AceApplicationInfoImpl::GetLifeTime() const
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::string AceApplicationInfoImpl::GetJsEngineParam(const std::string& key) const
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
AceApplicationInfoImpl& AceApplicationInfoImpl::GetInstance()
|
||||
{
|
||||
static AceApplicationInfoImpl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
AceApplicationInfo& AceApplicationInfo::GetInstance()
|
||||
{
|
||||
return Platform::AceApplicationInfoImpl::GetInstance();
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_APPLICATION_INFO_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_APPLICATION_INFO_H
|
||||
|
||||
#include "core/common/ace_application_info.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class AceApplicationInfoImpl : public AceApplicationInfo {
|
||||
public:
|
||||
static AceApplicationInfoImpl& GetInstance();
|
||||
|
||||
void SetLocale(const std::string& language, const std::string& countryOrRegion, const std::string& script,
|
||||
const std::string& keywordsAndValues) override;
|
||||
void ChangeLocale(const std::string& language, const std::string& countryOrRegion) override;
|
||||
std::vector<std::string> GetLocaleFallback(const std::vector<std::string>& localeList) const override;
|
||||
std::vector<std::string> GetResourceFallback(const std::vector<std::string>& resourceList) const override;
|
||||
bool GetFiles(const std::string& filePath, std::vector<std::string>& fileList) const override;
|
||||
|
||||
bool GetBundleInfo(const std::string& packageName, AceBundleInfo& bundleInfo) override;
|
||||
double GetLifeTime() const override;
|
||||
|
||||
std::string GetJsEngineParam(const std::string& key) const override;
|
||||
|
||||
std::string GetCurrentDeviceResTag() const override;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // #ifndef FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_APPLICATION_INFO_H
|
||||
@@ -0,0 +1,385 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/ace_container.h"
|
||||
|
||||
#include "flutter/assets/directory_asset_bundle.h"
|
||||
#include "flutter/lib/ui/ui_dart_state.h"
|
||||
|
||||
#include "adapter/common/cpp/flutter_asset_manager.h"
|
||||
#include "adapter/preview/entrance/ace_application_info.h"
|
||||
#include "adapter/preview/entrance/flutter_task_executor.h"
|
||||
#include "base/log/ace_trace.h"
|
||||
#include "base/log/event_report.h"
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/system_properties.h"
|
||||
#include "base/utils/utils.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/common/platform_bridge.h"
|
||||
#include "core/common/platform_window.h"
|
||||
#include "core/common/text_field_manager.h"
|
||||
#include "core/common/watch_dog.h"
|
||||
#include "core/common/window.h"
|
||||
#include "core/components/theme/app_theme.h"
|
||||
#include "core/components/theme/theme_constants.h"
|
||||
#include "core/components/theme/theme_manager.h"
|
||||
#include "core/pipeline/base/element.h"
|
||||
#include "core/pipeline/pipeline_context.h"
|
||||
#include "frameworks/bridge/card_frontend/card_frontend.h"
|
||||
#include "frameworks/bridge/js_frontend/engine/common/js_engine_loader.h"
|
||||
#include "frameworks/bridge/js_frontend/js_frontend.h"
|
||||
|
||||
#ifdef USE_GLFW_WINDOW
|
||||
#include "flutter/shell/platform/embedder/embedder.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
std::once_flag AceContainer::onceFlag_;
|
||||
|
||||
AceContainer::AceContainer(int32_t instanceId, FrontendType type) : instanceId_(instanceId), type_(type)
|
||||
{
|
||||
ThemeConstants::InitDeviceType();
|
||||
|
||||
auto state = flutter::UIDartState::Current()->GetStateById(instanceId);
|
||||
taskExecutor_ = Referenced::MakeRefPtr<FlutterTaskExecutor>(state->GetTaskRunners());
|
||||
|
||||
InitializeFrontend();
|
||||
}
|
||||
|
||||
void AceContainer::InitializeFrontend()
|
||||
{
|
||||
if (type_ == FrontendType::JS) {
|
||||
frontend_ = Frontend::Create();
|
||||
auto jsFrontend = AceType::DynamicCast<JsFrontend>(frontend_);
|
||||
jsFrontend->SetJsEngine(Framework::JsEngineLoader::Get().CreateJsEngine(GetInstanceId()));
|
||||
jsFrontend->SetNeedDebugBreakPoint(AceApplicationInfo::GetInstance().IsNeedDebugBreakPoint());
|
||||
jsFrontend->SetDebugVersion(AceApplicationInfo::GetInstance().IsDebugVersion());
|
||||
} else if (type_ == FrontendType::JS_CARD) {
|
||||
AceApplicationInfo::GetInstance().SetCardType();
|
||||
frontend_ = AceType::MakeRefPtr<CardFrontend>();
|
||||
} else {
|
||||
LOGE("Frontend type not supported");
|
||||
return;
|
||||
}
|
||||
ACE_DCHECK(frontend_);
|
||||
frontend_->Initialize(type_, taskExecutor_);
|
||||
}
|
||||
|
||||
void AceContainer::InitializeCallback()
|
||||
{
|
||||
ACE_FUNCTION_TRACE();
|
||||
|
||||
ACE_DCHECK(aceView_ && taskExecutor_ && pipelineContext_);
|
||||
auto&& touchEventCallback = [context = pipelineContext_](const TouchPoint& event) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, event]() { context->OnTouchEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterTouchEventCallback(touchEventCallback);
|
||||
|
||||
auto&& keyEventCallback = [context = pipelineContext_](const KeyEvent& event) {
|
||||
bool result = false;
|
||||
context->GetTaskExecutor()->PostSyncTask(
|
||||
[context, event, &result]() { result = context->OnKeyEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
return result;
|
||||
};
|
||||
aceView_->RegisterKeyEventCallback(keyEventCallback);
|
||||
|
||||
auto&& mouseEventCallback = [context = pipelineContext_](const MouseEvent& event) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, event]() { context->OnMouseEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterMouseEventCallback(mouseEventCallback);
|
||||
|
||||
auto&& rotationEventCallback = [context = pipelineContext_](const RotationEvent& event) {
|
||||
bool result = false;
|
||||
context->GetTaskExecutor()->PostSyncTask(
|
||||
[context, event, &result]() { result = context->OnRotationEvent(event); }, TaskExecutor::TaskType::UI);
|
||||
return result;
|
||||
};
|
||||
aceView_->RegisterRotationEventCallback(rotationEventCallback);
|
||||
|
||||
auto&& cardViewPositionCallback = [context = pipelineContext_](int id, float offsetX, float offsetY) {
|
||||
context->GetTaskExecutor()->PostSyncTask(
|
||||
[context, id, offsetX, offsetY]() { context->SetCardViewPosition(id, offsetX, offsetY); },
|
||||
TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterCardViewPositionCallback(cardViewPositionCallback);
|
||||
|
||||
auto&& cardViewParamsCallback = [context = pipelineContext_](const std::string& key, bool focus) {
|
||||
context->GetTaskExecutor()->PostSyncTask(
|
||||
[context, key, focus]() { context->SetCardViewAccessibilityParams(key, focus); },
|
||||
TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterCardViewAccessibilityParamsCallback(cardViewParamsCallback);
|
||||
|
||||
auto&& viewChangeCallback = [context = pipelineContext_](int32_t width, int32_t height) {
|
||||
ACE_SCOPED_TRACE("ViewChangeCallback(%d, %d)", width, height);
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, width, height]() { context->OnSurfaceChanged(width, height); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterViewChangeCallback(viewChangeCallback);
|
||||
|
||||
auto&& densityChangeCallback = [context = pipelineContext_](double density) {
|
||||
ACE_SCOPED_TRACE("DensityChangeCallback(%lf)", density);
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, density]() { context->OnSurfaceDensityChanged(density); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterDensityChangeCallback(densityChangeCallback);
|
||||
|
||||
auto&& systemBarHeightChangeCallback = [context = pipelineContext_](double statusBar, double navigationBar) {
|
||||
ACE_SCOPED_TRACE("SystemBarHeightChangeCallback(%lf, %lf)", statusBar, navigationBar);
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, statusBar, navigationBar]() { context->OnSystemBarHeightChanged(statusBar, navigationBar); },
|
||||
TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterSystemBarHeightChangeCallback(systemBarHeightChangeCallback);
|
||||
|
||||
auto&& surfaceDestroyCallback = [context = pipelineContext_]() {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context]() { context->OnSurfaceDestroyed(); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterSurfaceDestroyCallback(surfaceDestroyCallback);
|
||||
|
||||
auto&& idleCallback = [context = pipelineContext_](int64_t deadline) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, deadline]() { context->OnIdle(deadline); }, TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterIdleCallback(idleCallback);
|
||||
|
||||
auto&& viewDestoryCallback = [context = pipelineContext_](AceView::ViewReleaseCallback&& callback) {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[context, callback = std::move(callback)]() {
|
||||
context->GetTaskExecutor()->PostTask(
|
||||
[callback = std::move(callback)]() { callback(); }, TaskExecutor::TaskType::PLATFORM);
|
||||
},
|
||||
TaskExecutor::TaskType::UI);
|
||||
};
|
||||
aceView_->RegisterViewDestroyCallback(viewDestoryCallback);
|
||||
}
|
||||
|
||||
void AceContainer::CreateContainer(int32_t instanceId, FrontendType type)
|
||||
{
|
||||
#ifdef USE_GLFW_WINDOW
|
||||
std::call_once(onceFlag_, [] {
|
||||
FlutterEngineRegisterHandleTouchEventCallback([](std::unique_ptr<flutter::PointerDataPacket>& packet) -> bool {
|
||||
auto container = AceContainer::GetContainerInstance(0);
|
||||
if (!container || !container->GetAceView()) {
|
||||
return false;
|
||||
}
|
||||
return container->GetAceView()->HandleTouchEvent(std::move(packet));
|
||||
});
|
||||
});
|
||||
#endif
|
||||
auto aceContainer = AceType::MakeRefPtr<AceContainer>(instanceId, type);
|
||||
AceEngine::Get().AddContainer(aceContainer->GetInstanceId(), aceContainer);
|
||||
auto front = aceContainer->GetFrontend();
|
||||
if (front) {
|
||||
front->UpdateState(Frontend::State::ON_CREATE);
|
||||
front->SetJsMessageDispatcher(aceContainer);
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::DestroyContainer(int32_t instanceId)
|
||||
{
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
LOGE("no AceContainer with id %{private}d in AceEngine", instanceId);
|
||||
return;
|
||||
}
|
||||
auto context = container->GetPipelineContext();
|
||||
if (context) {
|
||||
context->Destroy();
|
||||
}
|
||||
AceEngine::Get().RemoveContainer(instanceId);
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
front->UpdateState(Frontend::State::ON_DESTROY);
|
||||
}
|
||||
|
||||
auto taskExecutor = AceType::DynamicCast<FlutterTaskExecutor>(container->GetTaskExecutor());
|
||||
if (taskExecutor) {
|
||||
taskExecutor->DestroyJsThread();
|
||||
}
|
||||
|
||||
auto aceView = AceType::DynamicCast<AceContainer>(container)->GetAceView();
|
||||
if (aceView) {
|
||||
LOGI("NotifyViewDestroyed");
|
||||
aceView->NotifyViewDestroyed([aceView]() { aceView->DecRefCount(); });
|
||||
}
|
||||
}
|
||||
|
||||
bool AceContainer::RunPage(int32_t instanceId, int32_t pageId, const std::string& url, const std::string& params)
|
||||
{
|
||||
ACE_FUNCTION_TRACE();
|
||||
|
||||
auto container = AceEngine::Get().GetContainer(instanceId);
|
||||
if (!container) {
|
||||
return false;
|
||||
}
|
||||
auto front = container->GetFrontend();
|
||||
if (front) {
|
||||
auto type = front->GetType();
|
||||
if ((type == FrontendType::JS) || (type == FrontendType::JS_CARD)) {
|
||||
front->RunPage(pageId, url, params);
|
||||
return true;
|
||||
} else {
|
||||
LOGE("Frontend type not supported when runpage");
|
||||
EventReport::SendAppStartException(AppStartExcepType::FRONTEND_TYPE_ERR);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AceContainer::Dispatch(
|
||||
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const
|
||||
{}
|
||||
|
||||
void AceContainer::DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const {}
|
||||
|
||||
bool AceContainer::Dump(const std::vector<std::string>& params)
|
||||
{
|
||||
if (aceView_ && aceView_->Dump(params)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pipelineContext_) {
|
||||
pipelineContext_->Dump(params);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void AceContainer::AddAssetPath(
|
||||
int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths)
|
||||
{
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& path : paths) {
|
||||
AceEngine::Get().SetPackagePath(packagePath);
|
||||
AceEngine::Get().SetAssetBasePath(path);
|
||||
|
||||
RefPtr<FlutterAssetManager> flutterAssetManager;
|
||||
if (container->assetManager_) {
|
||||
flutterAssetManager = AceType::DynamicCast<FlutterAssetManager>(container->assetManager_);
|
||||
} else {
|
||||
flutterAssetManager = Referenced::MakeRefPtr<FlutterAssetManager>();
|
||||
container->assetManager_ = flutterAssetManager;
|
||||
container->frontend_->SetAssetManager(flutterAssetManager);
|
||||
}
|
||||
|
||||
if (flutterAssetManager) {
|
||||
LOGD("Current path is: %s", path.c_str());
|
||||
flutterAssetManager->PushBack(std::make_unique<flutter::DirectoryAssetBundle>(
|
||||
fml::OpenDirectory(path.c_str(), false, fml::FilePermission::kRead)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void AceContainer::SetResourcesPathAndThemeStyle(int32_t instanceId, const std::string& resourcesPath,
|
||||
const ThemeId& themeId, const ColorMode& colorMode)
|
||||
{
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
container->deviceResourceInfo_.deviceConfig.colorMode = static_cast<OHOS::Ace::ColorMode>(colorMode);
|
||||
container->deviceResourceInfo_.packagePath = resourcesPath;
|
||||
container->deviceResourceInfo_.themeId = static_cast<int32_t>(themeId);
|
||||
}
|
||||
|
||||
void AceContainer::SetView(FlutterAceView* view, double density, int32_t width, int32_t height)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(view->GetInstanceId()));
|
||||
if (!container) {
|
||||
return;
|
||||
}
|
||||
auto platformWindow = PlatformWindow::Create(view);
|
||||
if (!platformWindow) {
|
||||
LOGE("Create PlatformWindow failed!");
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_ptr<Window> window = std::make_unique<Window>(std::move(platformWindow));
|
||||
container->AttachView(std::move(window), view, density, width, height);
|
||||
}
|
||||
|
||||
void AceContainer::AttachView(
|
||||
std::unique_ptr<Window> window, FlutterAceView* view, double density, int32_t width, int32_t height)
|
||||
{
|
||||
aceView_ = view;
|
||||
auto instanceId = aceView_->GetInstanceId();
|
||||
|
||||
resRegister_ = aceView_->GetPlatformResRegister();
|
||||
pipelineContext_ = AceType::MakeRefPtr<PipelineContext>(
|
||||
std::move(window), taskExecutor_, assetManager_, resRegister_, frontend_, instanceId);
|
||||
pipelineContext_->SetRootSize(density, width, height);
|
||||
pipelineContext_->SetTextFieldManager(AceType::MakeRefPtr<TextFieldManager>());
|
||||
pipelineContext_->SetIsRightToLeft(AceApplicationInfo::GetInstance().IsRightToLeft());
|
||||
pipelineContext_->SetWindowModal(windowModal_);
|
||||
pipelineContext_->SetDrawDelegate(aceView_->GetDrawDelegate());
|
||||
pipelineContext_->SetIsJsCard(type_ == FrontendType::JS_CARD);
|
||||
InitializeCallback();
|
||||
|
||||
// Only init global resource here, construct theme in UI thread
|
||||
auto themeManager = pipelineContext_->GetThemeManager();
|
||||
if (themeManager) {
|
||||
// Init resource, load theme map.
|
||||
themeManager->InitResource(deviceResourceInfo_);
|
||||
themeManager->LoadSystemTheme(deviceResourceInfo_.themeId);
|
||||
// get background color from theme
|
||||
aceView_->SetBackgroundColor(themeManager->GetBackgroundColor());
|
||||
|
||||
taskExecutor_->PostTask(
|
||||
[themeManager, assetManager = assetManager_, colorScheme = colorScheme_]() {
|
||||
themeManager->ParseSystemTheme();
|
||||
themeManager->SetColorScheme(colorScheme);
|
||||
themeManager->LoadCustomTheme(assetManager);
|
||||
},
|
||||
TaskExecutor::TaskType::UI);
|
||||
}
|
||||
|
||||
taskExecutor_->PostTask(
|
||||
[context = pipelineContext_]() { context->SetupRootElement(); }, TaskExecutor::TaskType::UI);
|
||||
aceView_->Launch();
|
||||
|
||||
frontend_->AttachPipelineContext(pipelineContext_);
|
||||
auto cardFronted = AceType::DynamicCast<CardFrontend>(frontend_);
|
||||
if (cardFronted) {
|
||||
cardFronted->SetDensity(static_cast<double>(density));
|
||||
taskExecutor_->PostTask(
|
||||
[context = pipelineContext_, width, height]() { context->OnSurfaceChanged(width, height); },
|
||||
TaskExecutor::TaskType::UI);
|
||||
}
|
||||
|
||||
AceEngine::Get().RegisterToWatchDog(instanceId, taskExecutor_);
|
||||
}
|
||||
|
||||
RefPtr<AceContainer> AceContainer::GetContainerInstance(int32_t instanceId)
|
||||
{
|
||||
auto container = AceType::DynamicCast<AceContainer>(AceEngine::Get().GetContainer(instanceId));
|
||||
return container;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_CONTAINER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_CONTAINER_H
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
#include "adapter/preview/entrance/flutter_ace_view.h"
|
||||
#include "base/resource/asset_manager.h"
|
||||
#include "base/thread/task_executor.h"
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/common/container.h"
|
||||
#include "core/common/js_message_dispatcher.h"
|
||||
#include "core/common/platform_bridge.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
// AceContainer is the instance have its own pipeline and thread models, it can contains multiple pages.
|
||||
class AceContainer : public Container, public JsMessageDispatcher {
|
||||
DECLARE_ACE_TYPE(AceContainer, Container, JsMessageDispatcher);
|
||||
|
||||
public:
|
||||
static void CreateContainer(int32_t instanceId, FrontendType type);
|
||||
static void DestroyContainer(int32_t instanceId);
|
||||
|
||||
static void AddAssetPath(int32_t instanceId, const std::string& packagePath, const std::vector<std::string>& paths);
|
||||
static void SetResourcesPathAndThemeStyle(int32_t instanceId, const std::string& resourcesPath,
|
||||
const ThemeId& themeId, const ColorMode& colorMode);
|
||||
static void SetView(FlutterAceView* view, double density, int32_t width, int32_t height);
|
||||
static bool RunPage(int32_t instanceId, int32_t pageId, const std::string& url, const std::string& params);
|
||||
static RefPtr<AceContainer> GetContainerInstance(int32_t instanceId);
|
||||
|
||||
AceContainer(int32_t instanceId, FrontendType type);
|
||||
~AceContainer() override = default;
|
||||
|
||||
int32_t GetInstanceId() const override
|
||||
{
|
||||
return instanceId_;
|
||||
}
|
||||
|
||||
std::string GetHostClassName() const override
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
RefPtr<Frontend> GetFrontend() const override
|
||||
{
|
||||
return frontend_;
|
||||
}
|
||||
|
||||
RefPtr<TaskExecutor> GetTaskExecutor() const override
|
||||
{
|
||||
return taskExecutor_;
|
||||
}
|
||||
|
||||
RefPtr<AssetManager> GetAssetManager() const override
|
||||
{
|
||||
return assetManager_;
|
||||
}
|
||||
|
||||
RefPtr<PlatformResRegister> GetPlatformResRegister() const override
|
||||
{
|
||||
return resRegister_;
|
||||
}
|
||||
|
||||
RefPtr<PipelineContext> GetPipelineContext() const override
|
||||
{
|
||||
return pipelineContext_;
|
||||
}
|
||||
|
||||
FlutterAceView* GetAceView() const
|
||||
{
|
||||
return aceView_;
|
||||
}
|
||||
|
||||
void SetWindowModal(WindowModal windowModal)
|
||||
{
|
||||
windowModal_ = windowModal;
|
||||
}
|
||||
|
||||
void SetColorScheme(ColorScheme colorScheme)
|
||||
{
|
||||
colorScheme_ = colorScheme;
|
||||
}
|
||||
|
||||
void Dispatch(
|
||||
const std::string& group, std::vector<uint8_t>&& data, int32_t id, bool replyToComponent) const override;
|
||||
|
||||
void DispatchPluginError(int32_t callbackId, int32_t errorCode, std::string&& errorMessage) const override;
|
||||
|
||||
bool Dump(const std::vector<std::string>& params) override;
|
||||
|
||||
private:
|
||||
void InitializeFrontend();
|
||||
void InitializeCallback();
|
||||
|
||||
void AttachView(
|
||||
std::unique_ptr<Window> window, FlutterAceView* view, double density, int32_t width, int32_t height);
|
||||
|
||||
int32_t instanceId_;
|
||||
FlutterAceView* aceView_ = nullptr;
|
||||
RefPtr<TaskExecutor> taskExecutor_;
|
||||
RefPtr<AssetManager> assetManager_;
|
||||
RefPtr<PlatformResRegister> resRegister_;
|
||||
RefPtr<PipelineContext> pipelineContext_;
|
||||
RefPtr<Frontend> frontend_;
|
||||
FrontendType type_ { FrontendType::JSON };
|
||||
WindowModal windowModal_ { WindowModal::NORMAL };
|
||||
ColorScheme colorScheme_ { ColorScheme::SCHEME_LIGHT };
|
||||
DeviceResourceInfo deviceResourceInfo_;
|
||||
static std::once_flag onceFlag_;
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(AceContainer);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_CONTAINER_H
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/ace_resource_register.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
bool AceResourceRegister::OnMethodCall(const std::string& method, const std::string& param, std::string& result)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
int64_t AceResourceRegister::CreateResource(const std::string& resourceType, const std::string& param)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool AceResourceRegister::ReleaseResource(const std::string& resourceHash)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_RESOURCE_REGISTER_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_RESOURCE_REGISTER_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "core/common/platform_res_register.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class AceResourceRegister final : public PlatformResRegister {
|
||||
public:
|
||||
int64_t CreateResource(const std::string& resourceType, const std::string& param) override;
|
||||
bool ReleaseResource(const std::string& resourceHash) override;
|
||||
bool OnMethodCall(const std::string& method, const std::string& param, std::string& result) override;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_RESOURCE_REGISTER_H
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_RUN_OPTIONS_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_RUN_OPTIONS_H
|
||||
|
||||
#include <functional>
|
||||
#include <string>
|
||||
|
||||
#include "base/utils/device_type.h"
|
||||
|
||||
#ifndef ACE_PREVIEW_EXPORT
|
||||
#ifdef _WIN32
|
||||
#define ACE_PREVIEW_EXPORT __declspec(dllexport)
|
||||
#elif defined(__APPLE__)
|
||||
#define ACE_PREVIEW_EXPORT __attribute__((visibility("default")))
|
||||
#endif
|
||||
#endif // ACE_PREVIEW_EXPORT
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
using SendRenderDataCallback = bool (*)(const void*, size_t);
|
||||
|
||||
// Keep the same with definition in base/utils/system_properties.h
|
||||
enum class DeviceOrientation : int32_t {
|
||||
PORTRAIT,
|
||||
LANDSCAPE,
|
||||
};
|
||||
|
||||
enum class ThemeId : int32_t {
|
||||
THEME_ID_LIGHT,
|
||||
THEME_ID_DARK,
|
||||
};
|
||||
|
||||
// Keep the same with definition in base/utils/system_properties.h
|
||||
enum class ColorMode : int32_t {
|
||||
LIGHT = 0,
|
||||
DARK,
|
||||
};
|
||||
|
||||
struct ACE_PREVIEW_EXPORT AceRunArgs {
|
||||
// The absolute path end of "default".
|
||||
std::string assetPath;
|
||||
// The absolute path of system resources.
|
||||
std::string resourcesPath;
|
||||
|
||||
// Indecate light or dark theme. 0 is theme_light, 1 is theme_dark.
|
||||
ThemeId themeId = ThemeId::THEME_ID_LIGHT;
|
||||
|
||||
// Light Theme contains light mode and dark mode. The dafault is light mode of light theme.
|
||||
ColorMode colorMode = ColorMode::LIGHT;
|
||||
|
||||
// Set page path to launch directly, or launch the main page in default.
|
||||
std::string url;
|
||||
|
||||
std::string windowTitle;
|
||||
|
||||
bool isRound = false;
|
||||
int32_t viewWidth = 0;
|
||||
int32_t viewHeight = 0;
|
||||
int32_t deviceWidth = 0;
|
||||
int32_t deviceHeight = 0;
|
||||
double resolution = 1.0;
|
||||
|
||||
// Locale
|
||||
std::string language = "zh";
|
||||
std::string region = "CN";
|
||||
std::string script = "";
|
||||
|
||||
DeviceOrientation orientation = DeviceOrientation::PORTRAIT;
|
||||
DeviceType deviceType = DeviceType::PHONE;
|
||||
|
||||
bool formsEnabled = false;
|
||||
|
||||
SendRenderDataCallback onRender;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_ACE_RUN_OPTIONS_H
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/flutter_ace_view.h"
|
||||
|
||||
#include "base/log/dump_log.h"
|
||||
#include "base/log/event_report.h"
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/system_properties.h"
|
||||
#include "base/utils/utils.h"
|
||||
#include "core/common/ace_engine.h"
|
||||
#include "core/components/theme/theme_manager.h"
|
||||
#include "core/event/mouse_event.h"
|
||||
#include "core/gestures/touch_event.h"
|
||||
#include "core/image/image_cache.h"
|
||||
#include "core/pipeline/layers/flutter_scene_builder.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t DEFAULT_ACTION_ID = 0;
|
||||
|
||||
void ConvertTouchEvent(const std::vector<uint8_t>& data, std::vector<TouchPoint>& events)
|
||||
{
|
||||
const auto* origin = reinterpret_cast<const flutter::PointerData*>(data.data());
|
||||
size_t size = data.size() / sizeof(flutter::PointerData);
|
||||
auto current = const_cast<flutter::PointerData*>(origin);
|
||||
auto end = current + size;
|
||||
|
||||
while (current < end) {
|
||||
std::chrono::microseconds micros(current->time_stamp);
|
||||
TimeStamp time(micros);
|
||||
TouchPoint point {
|
||||
static_cast<int32_t>(DEFAULT_ACTION_ID), static_cast<float>(current->physical_x),
|
||||
static_cast<float>(current->physical_y), TouchType::UNKNOWN, time, current->size,
|
||||
static_cast<float>(current->pressure), static_cast<int64_t>(current->device)
|
||||
};
|
||||
switch (current->change) {
|
||||
case flutter::PointerData::Change::kCancel:
|
||||
point.type = TouchType::CANCEL;
|
||||
events.push_back(point);
|
||||
break;
|
||||
case flutter::PointerData::Change::kAdd:
|
||||
case flutter::PointerData::Change::kRemove:
|
||||
case flutter::PointerData::Change::kHover:
|
||||
break;
|
||||
case flutter::PointerData::Change::kDown:
|
||||
point.type = TouchType::DOWN;
|
||||
events.push_back(point);
|
||||
break;
|
||||
case flutter::PointerData::Change::kMove:
|
||||
point.type = TouchType::MOVE;
|
||||
events.push_back(point);
|
||||
break;
|
||||
case flutter::PointerData::Change::kUp:
|
||||
point.type = TouchType::UP;
|
||||
events.push_back(point);
|
||||
break;
|
||||
}
|
||||
current++;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterTouchEventCallback(TouchEventCallback&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
touchEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterKeyEventCallback(KeyEventCallback&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
keyEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterMouseEventCallback(MouseEventCallback&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
mouseEventCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::RegisterRotationEventCallback(RotationEventCallBack&& callback)
|
||||
{
|
||||
ACE_DCHECK(callback);
|
||||
rotationEventCallBack_ = std::move(callback);
|
||||
}
|
||||
|
||||
void FlutterAceView::Launch()
|
||||
{
|
||||
}
|
||||
|
||||
bool FlutterAceView::Dump(const std::vector<std::string>& params)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void FlutterAceView::ProcessIdleEvent(int64_t deadline)
|
||||
{
|
||||
if (idleCallback_) {
|
||||
idleCallback_(deadline);
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterAceView::HandleTouchEvent(std::unique_ptr<flutter::PointerDataPacket> packet)
|
||||
{
|
||||
if (packet == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::vector<TouchPoint> touchEvents;
|
||||
ConvertTouchEvent(packet->data(), touchEvents);
|
||||
for (const auto& point : touchEvents) {
|
||||
LOGD("HandleTouchEvent point.x: %lf, point.y: %lf, point.size: %lf", point.x, point.y, point.size);
|
||||
if (point.type == TouchType::UNKNOWN) {
|
||||
LOGW("Unknown event.");
|
||||
continue;
|
||||
}
|
||||
if (touchEventCallback_) {
|
||||
touchEventCallback_(point);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FlutterAceView::HandleTouchEvent(const TouchPoint& touchEvent)
|
||||
{
|
||||
if (touchEvent.type == TouchType::UNKNOWN) {
|
||||
LOGW("Unknown event.");
|
||||
return false;
|
||||
}
|
||||
|
||||
LOGD("HandleTouchEvent touchEvent.x: %lf, touchEvent.y: %lf, touchEvent.size: %lf",
|
||||
touchEvent.x, touchEvent.y, touchEvent.size);
|
||||
if (touchEventCallback_) {
|
||||
touchEventCallback_(touchEvent);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<DrawDelegate> FlutterAceView::GetDrawDelegate()
|
||||
{
|
||||
auto darwDelegate = std::make_unique<DrawDelegate>();
|
||||
|
||||
darwDelegate->SetDrawFrameCallback([this](RefPtr<Flutter::Layer>& layer, const Rect& dirty) {
|
||||
if (!layer) {
|
||||
return;
|
||||
}
|
||||
RefPtr<Flutter::FlutterSceneBuilder> flutterSceneBuilder = AceType::MakeRefPtr<Flutter::FlutterSceneBuilder>();
|
||||
layer->AddToScene(*flutterSceneBuilder, 0.0, 0.0);
|
||||
auto scene_ = flutterSceneBuilder->Build();
|
||||
if (!flutter::UIDartState::Current()) {
|
||||
LOGE("uiDartState is nullptr");
|
||||
return;
|
||||
}
|
||||
auto window = flutter::UIDartState::Current()->window();
|
||||
if (window != nullptr && window->client() != nullptr) {
|
||||
window->client()->Render(scene_.get());
|
||||
}
|
||||
});
|
||||
|
||||
return darwDelegate;
|
||||
}
|
||||
|
||||
std::unique_ptr<PlatformWindow> FlutterAceView::GetPlatformWindow()
|
||||
{
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_ACE_VIEW_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_ACE_VIEW_H
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "adapter/preview/entrance/ace_resource_register.h"
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/event/key_event_recognizer.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
using ReleaseCallback = std::function<void()>;
|
||||
|
||||
class FlutterAceView : public AceView, public Referenced {
|
||||
public:
|
||||
explicit FlutterAceView(int32_t instanceId) : instanceId_(instanceId) {}
|
||||
~FlutterAceView() override = default;
|
||||
|
||||
void RegisterTouchEventCallback(TouchEventCallback&& callback) override;
|
||||
void RegisterKeyEventCallback(KeyEventCallback&& callback) override;
|
||||
void RegisterMouseEventCallback(MouseEventCallback&& callback) override;
|
||||
void RegisterRotationEventCallback(RotationEventCallBack&& callback) override;
|
||||
|
||||
void Launch() override;
|
||||
|
||||
int32_t GetInstanceId() const override
|
||||
{
|
||||
return instanceId_;
|
||||
}
|
||||
|
||||
void RegisterCardViewPositionCallback(CardViewPositionCallBack&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
cardViewPositionCallBack_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterCardViewAccessibilityParamsCallback(CardViewAccessibilityParamsCallback&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
cardViewAccessibilityParamsCallback_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterViewChangeCallback(ViewChangeCallback&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
viewChangeCallback_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterDensityChangeCallback(DensityChangeCallback&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
densityChangeCallback_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterSystemBarHeightChangeCallback(SystemBarHeightChangeCallbak&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
systemBarHeightChangeCallbak_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterSurfaceDestroyCallback(SurfaceDestroyCallback&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
surfaceDestroyCallback_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterIdleCallback(IdleCallback&& callback) override
|
||||
{
|
||||
if (callback) {
|
||||
idleCallback_ = std::move(callback);
|
||||
}
|
||||
}
|
||||
|
||||
const RefPtr<PlatformResRegister>& GetPlatformResRegister() const override
|
||||
{
|
||||
return resRegister_;
|
||||
}
|
||||
|
||||
bool Dump(const std::vector<std::string>& params) override;
|
||||
|
||||
void ProcessIdleEvent(int64_t deadline);
|
||||
|
||||
void NotifySurfaceChanged(int32_t width, int32_t height) const
|
||||
{
|
||||
if (viewChangeCallback_) {
|
||||
viewChangeCallback_(width, height);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyDensityChanged(double density) const
|
||||
{
|
||||
if (densityChangeCallback_) {
|
||||
densityChangeCallback_(density);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifySystemBarHeightChanged(double statusBar, double navigationBar) const
|
||||
{
|
||||
if (systemBarHeightChangeCallbak_) {
|
||||
systemBarHeightChangeCallbak_(statusBar, navigationBar);
|
||||
}
|
||||
}
|
||||
|
||||
void NotifySurfaceDestroyed() const
|
||||
{
|
||||
if (surfaceDestroyCallback_) {
|
||||
surfaceDestroyCallback_();
|
||||
}
|
||||
}
|
||||
|
||||
void NotifyViewDestroyed(ViewReleaseCallback&& callback)
|
||||
{
|
||||
if (viewDestoryCallback_) {
|
||||
viewDestoryCallback_(std::move(callback));
|
||||
}
|
||||
}
|
||||
|
||||
void RegisterViewDestroyCallback(ViewDestoryCallback&& callback) override
|
||||
{
|
||||
viewDestoryCallback_ = std::move(callback);
|
||||
}
|
||||
|
||||
// Use to receive event from glfw window
|
||||
bool HandleTouchEvent(std::unique_ptr<flutter::PointerDataPacket> packet) override;
|
||||
|
||||
// Use to receive event from pc previewer
|
||||
bool HandleTouchEvent(const TouchPoint& touchEvent) override;
|
||||
|
||||
ViewType GetViewType() const override
|
||||
{
|
||||
return AceView::ViewType::SURFACE_VIEW;
|
||||
}
|
||||
|
||||
std::unique_ptr<DrawDelegate> GetDrawDelegate() override;
|
||||
std::unique_ptr<PlatformWindow> GetPlatformWindow() override;
|
||||
|
||||
private:
|
||||
int32_t instanceId_ = 0;
|
||||
RefPtr<PlatformResRegister> resRegister_ = Referenced::MakeRefPtr<AceResourceRegister>();
|
||||
|
||||
TouchEventCallback touchEventCallback_;
|
||||
MouseEventCallback mouseEventCallback_;
|
||||
RotationEventCallBack rotationEventCallBack_;
|
||||
CardViewPositionCallBack cardViewPositionCallBack_;
|
||||
CardViewAccessibilityParamsCallback cardViewAccessibilityParamsCallback_;
|
||||
ViewChangeCallback viewChangeCallback_;
|
||||
DensityChangeCallback densityChangeCallback_;
|
||||
SystemBarHeightChangeCallbak systemBarHeightChangeCallbak_;
|
||||
SurfaceDestroyCallback surfaceDestroyCallback_;
|
||||
IdleCallback idleCallback_;
|
||||
KeyEventCallback keyEventCallback_;
|
||||
KeyEventRecognizer keyEventRecognizer_;
|
||||
ViewDestoryCallback viewDestoryCallback_;
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(FlutterAceView);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_ACE_VIEW_H
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/flutter_task_executor.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "base/thread/background_task_executor.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
inline std::string GenJsThreadName()
|
||||
{
|
||||
static std::atomic<uint32_t> instanceCount { 1 };
|
||||
return std::string("jsThread-") + std::to_string(instanceCount.fetch_add(1, std::memory_order_relaxed));
|
||||
}
|
||||
|
||||
bool PostTaskToTaskRunner(const fml::RefPtr<fml::TaskRunner>& taskRunner, TaskExecutor::Task&& task, uint32_t delayTime)
|
||||
{
|
||||
if (!taskRunner || !task) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (delayTime > 0) {
|
||||
taskRunner->PostDelayedTask(std::move(task), fml::TimeDelta::FromMilliseconds(delayTime));
|
||||
} else {
|
||||
taskRunner->PostTask(std::move(task));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
FlutterTaskExecutor::FlutterTaskExecutor(const flutter::TaskRunners& taskRunners)
|
||||
{
|
||||
jsThread_ = std::make_unique<fml::Thread>(GenJsThreadName());
|
||||
jsRunner_ = jsThread_->GetTaskRunner();
|
||||
|
||||
platformRunner_ = taskRunners.GetPlatformTaskRunner();
|
||||
uiRunner_ = taskRunners.GetUITaskRunner();
|
||||
ioRunner_ = taskRunners.GetIOTaskRunner();
|
||||
gpuRunner_ = taskRunners.GetGPUTaskRunner();
|
||||
}
|
||||
|
||||
bool FlutterTaskExecutor::OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const
|
||||
{
|
||||
switch (type) {
|
||||
case TaskType::PLATFORM:
|
||||
return PostTaskToTaskRunner(platformRunner_, std::move(task), delayTime);
|
||||
case TaskType::UI:
|
||||
return PostTaskToTaskRunner(uiRunner_, std::move(task), delayTime);
|
||||
case TaskType::IO:
|
||||
return PostTaskToTaskRunner(ioRunner_, std::move(task), delayTime);
|
||||
case TaskType::GPU:
|
||||
return PostTaskToTaskRunner(gpuRunner_, std::move(task), delayTime);
|
||||
case TaskType::JS:
|
||||
return PostTaskToTaskRunner(jsRunner_, std::move(task), delayTime);
|
||||
case TaskType::BACKGROUND:
|
||||
// Ignore delay time
|
||||
return BackgroundTaskExecutor::GetInstance().PostTask(std::move(task));
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool FlutterTaskExecutor::WillRunOnCurrentThread(TaskType type) const
|
||||
{
|
||||
switch (type) {
|
||||
case TaskType::PLATFORM:
|
||||
return platformRunner_ ? platformRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::UI:
|
||||
return uiRunner_ ? uiRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::IO:
|
||||
return ioRunner_ ? ioRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::GPU:
|
||||
return gpuRunner_ ? gpuRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::JS:
|
||||
return jsRunner_ ? jsRunner_->RunsTasksOnCurrentThread() : false;
|
||||
case TaskType::BACKGROUND:
|
||||
// Always return false for background tasks.
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void FlutterTaskExecutor::DestroyJsThread()
|
||||
{
|
||||
jsThread_.reset();
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_TASK_EXECUTOR_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_TASK_EXECUTOR_H
|
||||
|
||||
#include "flutter/common/task_runners.h"
|
||||
#include "flutter/fml/thread.h"
|
||||
|
||||
#include "base/thread/task_executor.h"
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class ACE_EXPORT FlutterTaskExecutor final : public TaskExecutor {
|
||||
DECLARE_ACE_TYPE(FlutterTaskExecutor, TaskExecutor);
|
||||
|
||||
public:
|
||||
explicit FlutterTaskExecutor(const flutter::TaskRunners& taskRunners);
|
||||
~FlutterTaskExecutor() override = default;
|
||||
|
||||
void DestroyJsThread();
|
||||
bool WillRunOnCurrentThread(TaskType type) const final;
|
||||
|
||||
private:
|
||||
bool OnPostTask(Task&& task, TaskType type, uint32_t delayTime) const final;
|
||||
|
||||
std::unique_ptr<fml::Thread> jsThread_;
|
||||
|
||||
fml::RefPtr<fml::TaskRunner> platformRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> uiRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> ioRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> jsRunner_;
|
||||
fml::RefPtr<fml::TaskRunner> gpuRunner_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_TASK_EXECUTOR_H
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "adapter/preview/entrance/flutter_window.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
#include "flutter/runtime/window_manager.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "core/common/ace_view.h"
|
||||
#include "core/pipeline/base/render_node.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
std::unique_ptr<PlatformWindow> PlatformWindow::Create(AceView* view)
|
||||
{
|
||||
if (view != nullptr) {
|
||||
return std::make_unique<Platform::FlutterWindow>(view->GetInstanceId());
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
namespace Platform {
|
||||
|
||||
FlutterWindow::FlutterWindow(int32_t instanceId) : instanceId_(instanceId) {}
|
||||
|
||||
FlutterWindow::~FlutterWindow() {}
|
||||
|
||||
void FlutterWindow::RequestFrame()
|
||||
{
|
||||
auto window = flutter::WindowManager::GetWindow(instanceId_);
|
||||
if (window != nullptr) {
|
||||
window->ScheduleFrame();
|
||||
if (!window->HasBeginFrameCallback()) {
|
||||
window->SetBeginFrameCallback(std::bind(&FlutterWindow::OnVsyncCallback, this, std::placeholders::_1));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FlutterWindow::RegisterVsyncCallback(AceVsyncCallback&& callback)
|
||||
{
|
||||
vsyncCallbacks_.emplace_back(std::move(callback));
|
||||
}
|
||||
|
||||
void FlutterWindow::SetRootRenderNode(const RefPtr<RenderNode>& root) {}
|
||||
|
||||
void FlutterWindow::OnVsyncCallback(uint64_t timeStampNanos)
|
||||
{
|
||||
for (const auto& vsyncCallback : vsyncCallbacks_) {
|
||||
vsyncCallback(timeStampNanos, 0);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Platform
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_WINDOW_H
|
||||
#define FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_WINDOW_H
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "core/common/platform_window.h"
|
||||
|
||||
namespace OHOS::Ace::Platform {
|
||||
|
||||
class FlutterWindow final : public PlatformWindow {
|
||||
public:
|
||||
explicit FlutterWindow(int32_t instanceId);
|
||||
~FlutterWindow() override;
|
||||
|
||||
// Platform window interface
|
||||
void RequestFrame() override;
|
||||
void RegisterVsyncCallback(AceVsyncCallback&& callback) override;
|
||||
void SetRootRenderNode(const RefPtr<RenderNode>& root) override;
|
||||
|
||||
// Vsync callback
|
||||
void OnVsyncCallback(uint64_t timeStampNanos);
|
||||
|
||||
private:
|
||||
std::vector<AceVsyncCallback> vsyncCallbacks_;
|
||||
int32_t instanceId_;
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(FlutterWindow);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace::Platform
|
||||
|
||||
#endif // FOUNDATION_ACE_ADAPTER_PREVIEW_FLUTTER_WINDOW_H
|
||||
@@ -0,0 +1,110 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
config("ace_pc_preview_config") {
|
||||
cflags = [ "-std=c++17" ]
|
||||
include_dirs = [
|
||||
"$ace_root",
|
||||
"$ace_root/frameworks",
|
||||
"$flutter_root/engine",
|
||||
"$flutter_root/engine/flutter/shell/platform/common/cpp/public",
|
||||
"$flutter_root/engine/ace_adapter/flutter/shell/platform/glfw/public",
|
||||
]
|
||||
}
|
||||
|
||||
template("ace_test") {
|
||||
forward_variables_from(invoker, "*")
|
||||
ohos_executable(target_name) {
|
||||
defines += invoker.defines
|
||||
if (device == "phone") {
|
||||
sources = [ "ace_phone_test.cpp" ]
|
||||
} else if (device == "wearable") {
|
||||
sources = [ "ace_watch_test.cpp" ]
|
||||
} else if (device == "tv") {
|
||||
sources = [ "ace_tv_test.cpp" ]
|
||||
} else if (device == "tablet") {
|
||||
sources = [ "ace_tablet_test.cpp" ]
|
||||
} else if (device == "card") {
|
||||
sources = [ "ace_card_test.cpp" ]
|
||||
}
|
||||
|
||||
configs = [ ":ace_pc_preview_config" ]
|
||||
deps = [ "$ace_root/adapter/preview/entrance:libace_engine_$platform(${current_toolchain})" ]
|
||||
if (platform == "windows") {
|
||||
libs = [ "pthread" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ace_test("ace_test_windows_phone") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
device = "phone"
|
||||
}
|
||||
|
||||
ace_test("ace_test_windows_tv") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
device = "tv"
|
||||
}
|
||||
|
||||
ace_test("ace_test_windows_wearable") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
device = "wearable"
|
||||
}
|
||||
|
||||
ace_test("ace_test_windows_tablet") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
device = "tablet"
|
||||
}
|
||||
|
||||
ace_test("ace_test_windows_card") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
device = "card"
|
||||
}
|
||||
|
||||
ace_test("ace_test_mac_phone") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
device = "phone"
|
||||
}
|
||||
|
||||
ace_test("ace_test_mac_tv") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
device = "tv"
|
||||
}
|
||||
|
||||
ace_test("ace_test_mac_wearable") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
device = "wearable"
|
||||
}
|
||||
|
||||
ace_test("ace_test_mac_tablet") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
device = "tablet"
|
||||
}
|
||||
|
||||
ace_test("ace_test_mac_card") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
device = "card"
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "adapter/preview/entrance/ace_ability.h"
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
|
||||
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
|
||||
constexpr char FILE_NAME[] = "InspectorTree.txt";
|
||||
// card default width and height:
|
||||
// 2*1 (150*54)
|
||||
// 2*2 (150*150)
|
||||
// 4*2 (320*150)
|
||||
// 4*4 (320*344)
|
||||
constexpr int32_t CARD_DEFAULT_WIDTH = 320;
|
||||
constexpr int32_t CARD_DEFAULT_HEIGHT = 344;
|
||||
|
||||
} // namespace
|
||||
|
||||
int main()
|
||||
{
|
||||
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool { return true; };
|
||||
|
||||
#ifdef MAC_PLATFORM
|
||||
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default_card";
|
||||
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
|
||||
constexpr double resolution = 2;
|
||||
#else
|
||||
std::string assetPath = "D:\\Workspace\\preview\\js\\default_card";
|
||||
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
|
||||
constexpr double resolution = 1;
|
||||
#endif
|
||||
|
||||
OHOS::Ace::Platform::AceRunArgs args = {
|
||||
.assetPath = assetPath,
|
||||
.resourcesPath = resourcesPath,
|
||||
.deviceWidth = CARD_DEFAULT_WIDTH,
|
||||
.deviceHeight = CARD_DEFAULT_HEIGHT,
|
||||
.windowTitle = "ACE card",
|
||||
.resolution = resolution,
|
||||
.formsEnabled = true,
|
||||
.onRender = std::move(renderCallback),
|
||||
};
|
||||
|
||||
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
|
||||
if (!ability) {
|
||||
std::cerr << "Could not create AceAbility!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::thread timer([&ability]() {
|
||||
int32_t getJSONTreeTimes = GET_INSPECTOR_TREE_TIMES;
|
||||
while (getJSONTreeTimes--) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(GET_INSPECTOR_TREE_INTERVAL));
|
||||
std::string jsonTreeStr = ability->GetJSONTree();
|
||||
// clear all information
|
||||
std::ofstream fileCleaner(FILE_NAME, std::ios_base::out);
|
||||
std::ofstream fileWriter(FILE_NAME, std::ofstream::app);
|
||||
fileWriter << jsonTreeStr;
|
||||
fileWriter << std::endl;
|
||||
fileWriter.close();
|
||||
}
|
||||
});
|
||||
ability->InitEnv();
|
||||
std::cout << "Ace initialize done. run loop now" << std::endl;
|
||||
ability->Start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "adapter/preview/entrance/ace_ability.h"
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
|
||||
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
|
||||
constexpr char FILE_NAME[] = "InspectorTree.txt";
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifdef MAC_PLATFORM
|
||||
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
|
||||
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
|
||||
constexpr double resolution = 2;
|
||||
#else
|
||||
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
|
||||
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
|
||||
constexpr double resolution = 1;
|
||||
#endif
|
||||
|
||||
OHOS::Ace::Platform::AceRunArgs args = {
|
||||
.assetPath = assetPath,
|
||||
.resourcesPath = resourcesPath,
|
||||
.deviceWidth = 360,
|
||||
.deviceHeight = 750,
|
||||
.windowTitle = "ACE phone",
|
||||
.resolution = resolution,
|
||||
.onRender = std::move(renderCallback),
|
||||
};
|
||||
|
||||
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
|
||||
if (!ability) {
|
||||
std::cerr << "Could not create AceAbility!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::thread timer([&ability]() {
|
||||
int32_t getJSONTreeTimes = GET_INSPECTOR_TREE_TIMES;
|
||||
while (getJSONTreeTimes--) {
|
||||
std::string jsonTreeStr = ability->GetJSONTree();
|
||||
// clear all information
|
||||
std::ofstream fileCleaner(FILE_NAME, std::ios_base::out);
|
||||
std::ofstream fileWriter(FILE_NAME, std::ofstream::app);
|
||||
fileWriter << jsonTreeStr;
|
||||
fileWriter << std::endl;
|
||||
fileWriter.close();
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(GET_INSPECTOR_TREE_INTERVAL));
|
||||
}
|
||||
});
|
||||
ability->InitEnv();
|
||||
std::cout << "Ace initialize done. run loop now" << std::endl;
|
||||
ability->Start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "adapter/preview/entrance/ace_ability.h"
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
|
||||
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
|
||||
constexpr char FILE_NAME[] = "InspectorTree.txt";
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifdef MAC_PLATFORM
|
||||
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
|
||||
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
|
||||
#else
|
||||
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
|
||||
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
|
||||
#endif
|
||||
|
||||
OHOS::Ace::Platform::AceRunArgs args = {
|
||||
.assetPath = assetPath,
|
||||
.resourcesPath = resourcesPath,
|
||||
.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
|
||||
.deviceWidth = 1280,
|
||||
.deviceHeight = 800,
|
||||
.windowTitle = "ACE Table",
|
||||
.resolution = 1,
|
||||
.deviceType = OHOS::Ace::DeviceType::TABLET,
|
||||
.onRender = std::move(renderCallback),
|
||||
};
|
||||
|
||||
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
|
||||
if (!ability) {
|
||||
std::cerr << "Could not create AceAbility!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::thread timer([&ability]() {
|
||||
int32_t getJSONTreeTimes = GET_INSPECTOR_TREE_TIMES;
|
||||
while (getJSONTreeTimes--) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(GET_INSPECTOR_TREE_INTERVAL));
|
||||
std::string jsonTreeStr = ability->GetJSONTree();
|
||||
// clear all information
|
||||
std::ofstream fileCleaner(FILE_NAME, std::ios_base::out);
|
||||
std::ofstream fileWriter(FILE_NAME, std::ofstream::app);
|
||||
fileWriter << jsonTreeStr;
|
||||
fileWriter << std::endl;
|
||||
fileWriter.close();
|
||||
}
|
||||
});
|
||||
ability->InitEnv();
|
||||
std::cout << "Ace initialize done. run loop now" << std::endl;
|
||||
ability->Start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "adapter/preview/entrance/ace_ability.h"
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
|
||||
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
|
||||
constexpr char FILE_NAME[] = "InspectorTree.txt";
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifdef MAC_PLATFORM
|
||||
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
|
||||
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
|
||||
#else
|
||||
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
|
||||
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
|
||||
#endif
|
||||
|
||||
OHOS::Ace::Platform::AceRunArgs args = {
|
||||
.assetPath = assetPath,
|
||||
.orientation = OHOS::Ace::Platform::DeviceOrientation::LANDSCAPE,
|
||||
.deviceWidth = 960,
|
||||
.deviceHeight = 540,
|
||||
.windowTitle = "ACE TV",
|
||||
.resolution = 1,
|
||||
.deviceType = OHOS::Ace::DeviceType::TV,
|
||||
.onRender = std::move(renderCallback),
|
||||
};
|
||||
|
||||
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
|
||||
if (!ability) {
|
||||
std::cerr << "Could not create AceAbility!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::thread timer([&ability]() {
|
||||
int32_t getJSONTreeTimes = GET_INSPECTOR_TREE_TIMES;
|
||||
while (getJSONTreeTimes--) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(GET_INSPECTOR_TREE_INTERVAL));
|
||||
std::string jsonTreeStr = ability->GetJSONTree();
|
||||
// clear all information
|
||||
std::ofstream fileCleaner(FILE_NAME, std::ios_base::out);
|
||||
std::ofstream fileWriter(FILE_NAME, std::ofstream::app);
|
||||
fileWriter << jsonTreeStr;
|
||||
fileWriter << std::endl;
|
||||
fileWriter.close();
|
||||
}
|
||||
});
|
||||
ability->InitEnv();
|
||||
std::cout << "Ace initialize done. run loop now" << std::endl;
|
||||
ability->Start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 <fstream>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
#include <thread>
|
||||
|
||||
#include "adapter/preview/entrance/ace_ability.h"
|
||||
#include "adapter/preview/entrance/ace_run_args.h"
|
||||
|
||||
namespace {
|
||||
|
||||
constexpr int32_t GET_INSPECTOR_TREE_TIMES = 12;
|
||||
constexpr int32_t GET_INSPECTOR_TREE_INTERVAL = 5000;
|
||||
constexpr char FILE_NAME[] = "InspectorTree.txt";
|
||||
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
auto&& renderCallback = [](const void*, size_t bufferSize) -> bool {
|
||||
return true;
|
||||
};
|
||||
|
||||
#ifdef MAC_PLATFORM
|
||||
std::string assetPath = "/Volumes/SSD2T/daily-test/preview/js/default";
|
||||
std::string resourcesPath = "/Volumes/SSD2T/daily-test/preview/js/resources";
|
||||
#else
|
||||
std::string assetPath = "D:\\Workspace\\preview\\js\\default";
|
||||
std::string resourcesPath = "D:\\Workspace\\preview\\js\\resources";
|
||||
#endif
|
||||
|
||||
OHOS::Ace::Platform::AceRunArgs args = {
|
||||
.assetPath = assetPath,
|
||||
.deviceWidth = 466,
|
||||
.deviceHeight = 466,
|
||||
.windowTitle = "ACE wearable",
|
||||
.resolution = 2.0,
|
||||
.isRound = true,
|
||||
.deviceType = OHOS::Ace::DeviceType::WATCH,
|
||||
.onRender = std::move(renderCallback),
|
||||
};
|
||||
|
||||
auto ability = OHOS::Ace::Platform::AceAbility::CreateInstance(args);
|
||||
if (!ability) {
|
||||
std::cerr << "Could not create AceAbility!" << std::endl;
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::thread timer([&ability]() {
|
||||
int32_t getJSONTreeTimes = GET_INSPECTOR_TREE_TIMES;
|
||||
while (getJSONTreeTimes--) {
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(GET_INSPECTOR_TREE_INTERVAL));
|
||||
std::string jsonTreeStr = ability->GetJSONTree();
|
||||
// clear all information
|
||||
std::ofstream fileCleaner(FILE_NAME, std::ios_base::out);
|
||||
std::ofstream fileWriter(FILE_NAME, std::ofstream::app);
|
||||
fileWriter << jsonTreeStr;
|
||||
fileWriter << std::endl;
|
||||
fileWriter.close();
|
||||
}
|
||||
});
|
||||
ability->InitEnv();
|
||||
std::cout << "Ace initialize done. run loop now" << std::endl;
|
||||
ability->Start();
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
# build static
|
||||
template("ace_osal_preview_source_set") {
|
||||
# get is_ohos_platform
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_source_set(target_name) {
|
||||
defines += invoker.defines
|
||||
|
||||
sources = [
|
||||
"$ace_root/adapter/common/cpp/file_asset_provider.cpp",
|
||||
"$ace_root/adapter/preview/entrance/flutter_task_executor.cpp",
|
||||
"$ace_root/adapter/preview/osal/ace_trace.cpp",
|
||||
"$ace_root/adapter/preview/osal/event_report.cpp",
|
||||
"$ace_root/adapter/preview/osal/log_wrapper.cpp",
|
||||
"$ace_root/adapter/preview/osal/system_properties.cpp",
|
||||
]
|
||||
|
||||
cflags_cc = [ "-DNAME_MAX=128" ]
|
||||
|
||||
if (platform == "mac") {
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
}
|
||||
|
||||
configs = [
|
||||
"$ace_root:ace_config",
|
||||
"$flutter_root:flutter_config",
|
||||
]
|
||||
|
||||
deps = [ "//third_party/zlib:libz" ]
|
||||
}
|
||||
}
|
||||
|
||||
ace_osal_preview_source_set("ace_osal_windows") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
}
|
||||
|
||||
ace_osal_preview_source_set("ace_osal_mac") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/ace_trace.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
bool AceTraceEnabled()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void AceTraceBegin(const char* name)
|
||||
{
|
||||
}
|
||||
|
||||
void AceTraceEnd()
|
||||
{
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/network/download_manager.h"
|
||||
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
|
||||
#include "curl/curl.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "base/utils/singleton.h"
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
#define ACE_CURL_EASY_SET_OPTION(handle, opt, data) \
|
||||
do { \
|
||||
CURLcode result = curl_easy_setopt(handle, opt, data); \
|
||||
if (result != CURLE_OK) { \
|
||||
LOGE("Failed to set option: %{public}s, %{public}s", #opt, curl_easy_strerror(result)); \
|
||||
return false; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
class DownloadManagerImpl final : public DownloadManager, public Singleton<DownloadManagerImpl> {
|
||||
DECLARE_SINGLETON(DownloadManagerImpl);
|
||||
ACE_DISALLOW_MOVE(DownloadManagerImpl);
|
||||
|
||||
public:
|
||||
bool Download(const std::string& url, std::vector<uint8_t>& dataOut) override
|
||||
{
|
||||
if (!Initialize()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
std::unique_ptr<CURL, decltype(&curl_easy_cleanup)> handle(curl_easy_init(), &curl_easy_cleanup);
|
||||
if (!handle) {
|
||||
LOGE("Failed to create download task");
|
||||
return false;
|
||||
}
|
||||
|
||||
dataOut.clear();
|
||||
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_URL, url.c_str());
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_WRITEFUNCTION, OnWritingMemory);
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_WRITEDATA, &dataOut);
|
||||
// Some servers don't like requests that are made without a user-agent field, so we provide one
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_URL, url.c_str());
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_SSL_VERIFYPEER, 0L);
|
||||
ACE_CURL_EASY_SET_OPTION(handle.get(), CURLOPT_SSL_VERIFYHOST, 0L);
|
||||
#endif
|
||||
|
||||
CURLcode result = curl_easy_perform(handle.get());
|
||||
if (result != CURLE_OK) {
|
||||
LOGE("Failed to download, url: %{private}s, %{public}s", url.c_str(), curl_easy_strerror(result));
|
||||
dataOut.clear();
|
||||
return false;
|
||||
}
|
||||
dataOut.shrink_to_fit();
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
static size_t OnWritingMemory(void* data, size_t size, size_t memBytes, void* userData)
|
||||
{
|
||||
// size is always 1, for more details see https://curl.haxx.se/libcurl/c/CURLOPT_WRITEFUNCTION.html
|
||||
auto& dataOut = *static_cast<std::vector<uint8_t>*>(userData);
|
||||
auto chunkData = static_cast<uint8_t*>(data);
|
||||
dataOut.insert(dataOut.end(), chunkData, chunkData + memBytes);
|
||||
return memBytes;
|
||||
}
|
||||
|
||||
bool Initialize()
|
||||
{
|
||||
if (initialized_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (initialized_) {
|
||||
return true;
|
||||
}
|
||||
if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
|
||||
LOGE("Failed to initialize 'curl'");
|
||||
return false;
|
||||
}
|
||||
initialized_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
std::mutex mutex_;
|
||||
bool initialized_ = false;
|
||||
};
|
||||
|
||||
DownloadManagerImpl::DownloadManagerImpl() = default;
|
||||
|
||||
DownloadManagerImpl::~DownloadManagerImpl()
|
||||
{
|
||||
curl_global_cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
DownloadManager& DownloadManager::GetInstance()
|
||||
{
|
||||
return Singleton<DownloadManagerImpl>::GetInstance();
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/event_report.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
void EventReport::SendEvent(const EventInfo& eventInfo) {}
|
||||
|
||||
void EventReport::SendAppStartException(AppStartExcepType type) {}
|
||||
|
||||
void EventReport::SendPageRouterException(PageRouterExcepType type, const std::string& pageUrl) {}
|
||||
|
||||
void EventReport::SendComponentException(ComponentExcepType type) {}
|
||||
|
||||
void EventReport::SendAPIChannelException(APIChannelExcepType type) {}
|
||||
|
||||
void EventReport::SendRenderException(RenderExcepType type) {}
|
||||
|
||||
void EventReport::SendJsException(JsExcepType type) {}
|
||||
|
||||
void EventReport::SendAnimationException(AnimationExcepType type) {}
|
||||
|
||||
void EventReport::SendEventException(EventExcepType type) {}
|
||||
|
||||
void EventReport::SendInternalException(InternalExcepType type) {}
|
||||
|
||||
void EventReport::SendAccessibilityException(AccessibilityExcepType type) {}
|
||||
|
||||
void EventReport::SendFormException(FormExcepType type) {}
|
||||
|
||||
void EventReport::JsEventReport(int32_t eventType, const std::string& jsonStr) {}
|
||||
|
||||
void EventReport::JsErrReport(int32_t uid, const std::string& packageName,
|
||||
const std::string& reason, const std::string& summary) {}
|
||||
|
||||
void EventReport::ANRRawReport(RawEventType type, int32_t uid, const std::string& packageName,
|
||||
const std::string& processName, const std::string& msg) {}
|
||||
|
||||
void EventReport::SendEventInner(const EventInfo& eventInfo) {}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/log_wrapper.h"
|
||||
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
#include <cstdio>
|
||||
#else
|
||||
#include "securec.h"
|
||||
#endif
|
||||
#include <thread>
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
constexpr uint32_t MAX_BUFFER_SIZE = 512;
|
||||
constexpr uint32_t MAX_TIME_SIZE = 32;
|
||||
const char* const LOGLEVELNAME[] = { "DEBUG", "INFO", "WARNING", "ERROR", "FATAL" };
|
||||
|
||||
const char* LOG_TAGS[] = {
|
||||
"Ace",
|
||||
"Console",
|
||||
};
|
||||
|
||||
} // namespace
|
||||
|
||||
// initial static member object
|
||||
LogLevel LogWrapper::level_ = LogLevel::DEBUG;
|
||||
|
||||
const char* GetNameForLogLevel(LogLevel level)
|
||||
{
|
||||
if (level <= LogLevel::FATAL) {
|
||||
return LOGLEVELNAME[static_cast<int>(level)];
|
||||
}
|
||||
return "UNKNOWN";
|
||||
}
|
||||
|
||||
char LogWrapper::GetSeparatorCharacter()
|
||||
{
|
||||
return '/';
|
||||
}
|
||||
|
||||
std::string GetTimeStamp()
|
||||
{
|
||||
time_t tt = time(nullptr);
|
||||
tm* t = localtime(&tt);
|
||||
char time[MAX_TIME_SIZE];
|
||||
|
||||
if (sprintf_s(time, MAX_TIME_SIZE, " %02d/%02d %02d:%02d:%02d", t->tm_mon + 1, t->tm_mday, t->tm_hour, t->tm_min,
|
||||
t->tm_sec) < 0) {
|
||||
return std::string();
|
||||
}
|
||||
return std::string(time);
|
||||
}
|
||||
|
||||
void LogWrapper::PrintLog(LogDomain domain, LogLevel level, const char* fmt, va_list args)
|
||||
{
|
||||
std::string newFmt(fmt);
|
||||
StripFormatString("{public}", newFmt);
|
||||
StripFormatString("{private}", newFmt);
|
||||
|
||||
char buf[MAX_BUFFER_SIZE];
|
||||
if (vsnprintf_s(buf, sizeof(buf), sizeof(buf) - 1, newFmt.c_str(), args) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string newTimeFmt("%s %-6d [%-7s %7s]");
|
||||
char timeBuf[MAX_BUFFER_SIZE];
|
||||
#ifdef WINDOWS_PLATFORM
|
||||
if (_snprintf_s(timeBuf, sizeof(timeBuf), sizeof(timeBuf) - 1, newTimeFmt.c_str(), GetTimeStamp().c_str(),
|
||||
std::this_thread::get_id(), LOG_TAGS[static_cast<uint32_t>(domain)], GetNameForLogLevel(level)) < 0) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
if (snprintf_s(timeBuf, sizeof(timeBuf), sizeof(timeBuf) - 1, newTimeFmt.c_str(), GetTimeStamp().c_str(),
|
||||
std::this_thread::get_id(), LOG_TAGS[static_cast<uint32_t>(domain)], GetNameForLogLevel(level)) < 0) {
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
printf("%s %s\r\n", timeBuf, buf);
|
||||
fflush(stdout);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
Executable
+138
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/utils/system_properties.h"
|
||||
|
||||
#include "base/log/log.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t ORIENTATION_PORTRAIT = 0;
|
||||
constexpr int32_t ORIENTATION_LANDSCAPE = 1;
|
||||
const char PROPERTY_DEVICE_TYPE_PHONE[] = "phone";
|
||||
const char PROPERTY_DEVICE_TYPE_TV[] = "tv";
|
||||
const char PROPERTY_DEVICE_TYPE_TABLET[] = "tablet";
|
||||
const char PROPERTY_DEVICE_TYPE_WEARABLE[] = "wearable";
|
||||
const char PROPERTY_DEVICE_TYPE_CAR[] = "car";
|
||||
|
||||
static constexpr char UNDEFINED_PARAM[] = "undefined parameter";
|
||||
|
||||
void Swap(int32_t& deviceWidth, int32_t& deviceHeight)
|
||||
{
|
||||
int32_t temp = deviceWidth;
|
||||
deviceWidth = deviceHeight;
|
||||
deviceHeight = temp;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
void SystemProperties::InitDeviceType(DeviceType type)
|
||||
{
|
||||
// Properties: "phone", "tv", "tablet", "watch", "car"
|
||||
if (type == DeviceType::TV) {
|
||||
deviceType_ = DeviceType::TV;
|
||||
paramDeviceType_ = PROPERTY_DEVICE_TYPE_TV;
|
||||
} else if (type == DeviceType::WATCH) {
|
||||
deviceType_ = DeviceType::WATCH;
|
||||
paramDeviceType_ = PROPERTY_DEVICE_TYPE_WEARABLE;
|
||||
} else if (type == DeviceType::CAR) {
|
||||
deviceType_ = DeviceType::CAR;
|
||||
paramDeviceType_ = PROPERTY_DEVICE_TYPE_CAR;
|
||||
} else if (type == DeviceType::TABLET) {
|
||||
deviceType_ = DeviceType::PHONE;
|
||||
paramDeviceType_ = PROPERTY_DEVICE_TYPE_TABLET;
|
||||
} else {
|
||||
deviceType_ = DeviceType::PHONE;
|
||||
paramDeviceType_ = PROPERTY_DEVICE_TYPE_PHONE;
|
||||
}
|
||||
}
|
||||
|
||||
bool SystemProperties::traceEnabled_ = false;
|
||||
bool SystemProperties::isRound_ = false;
|
||||
int32_t SystemProperties::width_ = 0;
|
||||
int32_t SystemProperties::height_ = 0;
|
||||
int32_t SystemProperties::deviceWidth_ = 0;
|
||||
int32_t SystemProperties::deviceHeight_ = 0;
|
||||
double SystemProperties::resolution_ = 1.0;
|
||||
DeviceType SystemProperties::deviceType_ { DeviceType::PHONE };
|
||||
DeviceOrientation SystemProperties::orientation_ { DeviceOrientation::PORTRAIT };
|
||||
std::string SystemProperties::brand_ = UNDEFINED_PARAM;
|
||||
std::string SystemProperties::manufacturer_ = UNDEFINED_PARAM;
|
||||
std::string SystemProperties::model_ = UNDEFINED_PARAM;
|
||||
std::string SystemProperties::product_ = UNDEFINED_PARAM;
|
||||
std::string SystemProperties::apiVersion_ = UNDEFINED_PARAM;
|
||||
std::string SystemProperties::releaseType_ = UNDEFINED_PARAM;
|
||||
std::string SystemProperties::paramDeviceType_ = UNDEFINED_PARAM;
|
||||
int32_t SystemProperties::mcc_ = MCC_UNDEFINED;
|
||||
int32_t SystemProperties::mnc_ = MNC_UNDEFINED;
|
||||
ColorMode SystemProperties::colorMode_ = ColorMode::LIGHT;
|
||||
|
||||
void SystemProperties::UpdateSurfaceStatus(int32_t width, int32_t height)
|
||||
{
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
DeviceType SystemProperties::GetDeviceType()
|
||||
{
|
||||
return deviceType_;
|
||||
}
|
||||
|
||||
void SystemProperties::InitDeviceTypeBySystemProperty()
|
||||
{
|
||||
deviceType_ = DeviceType::PHONE;
|
||||
}
|
||||
|
||||
void SystemProperties::InitDeviceInfo(int32_t deviceWidth, int32_t deviceHeight, int32_t orientation,
|
||||
double resolution, bool isRound)
|
||||
{
|
||||
// SetDeviceOrientation should be eralier than deviceWidth/deviceHeight init.
|
||||
SetDeviceOrientation(orientation);
|
||||
|
||||
isRound_ = isRound;
|
||||
resolution_ = resolution;
|
||||
deviceWidth_ = deviceWidth;
|
||||
deviceHeight_ = deviceHeight;
|
||||
// To avoid the deviceinfor api failure due to surface width and height equal 0 in previewer.
|
||||
width_ = deviceWidth_;
|
||||
height_ = deviceHeight_;
|
||||
}
|
||||
|
||||
void SystemProperties::SetDeviceOrientation(int32_t orientation)
|
||||
{
|
||||
if (orientation == ORIENTATION_PORTRAIT && orientation_ != DeviceOrientation::PORTRAIT) {
|
||||
Swap(deviceWidth_, deviceHeight_);
|
||||
orientation_ = DeviceOrientation::PORTRAIT;
|
||||
} else if (orientation == ORIENTATION_LANDSCAPE && orientation_ != DeviceOrientation::LANDSCAPE) {
|
||||
Swap(deviceWidth_, deviceHeight_);
|
||||
orientation_ = DeviceOrientation::LANDSCAPE;
|
||||
} else {
|
||||
LOGW("SetDeviceOrientation, undefined orientation");
|
||||
}
|
||||
}
|
||||
|
||||
float SystemProperties::GetFontWeightScale()
|
||||
{
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
void SystemProperties::InitMccMnc(int32_t mcc, int32_t mnc)
|
||||
{
|
||||
mcc_ = mcc;
|
||||
mnc_ = mnc;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 35 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 122 KiB |
@@ -0,0 +1,114 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
config("ace_base_config") {
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
}
|
||||
|
||||
template("ace_base_source_set") {
|
||||
# get is_ohos_platform
|
||||
forward_variables_from(invoker, "*")
|
||||
|
||||
ohos_source_set(target_name) {
|
||||
defines += invoker.defines
|
||||
deps = [
|
||||
"$ace_root:third_party_cjson",
|
||||
"i18n:ace_base_i18n_$platform",
|
||||
"resource:ace_resource",
|
||||
]
|
||||
|
||||
if (is_ohos_platform) {
|
||||
deps += [ "$ace_root/adapter/ohos/osal:ace_osal_$platform" ]
|
||||
} else if (use_mingw_win || use_mac) {
|
||||
deps += [ "$ace_root/adapter/preview/osal:ace_osal_$platform" ]
|
||||
}
|
||||
|
||||
configs = [
|
||||
":ace_base_config",
|
||||
"$ace_root:ace_config",
|
||||
"//third_party/cJSON:cJSON_config",
|
||||
]
|
||||
|
||||
# add base source file here
|
||||
sources = [
|
||||
"geometry/matrix4.cpp",
|
||||
"json/json_util.cpp",
|
||||
"log/ace_trace.cpp",
|
||||
"log/dump_log.cpp",
|
||||
"memory/memory_monitor.cpp",
|
||||
"thread/background_task_executor.cpp",
|
||||
"utils/base_id.cpp",
|
||||
"utils/date_util.cpp",
|
||||
"utils/string_utils.cpp",
|
||||
"utils/time_util.cpp",
|
||||
]
|
||||
|
||||
if (is_standard_system) {
|
||||
configs += [ "//third_party/curl:curl_config" ]
|
||||
deps += [ "//third_party/curl:curl" ]
|
||||
sources += [ "network/download_manager.cpp" ]
|
||||
}
|
||||
|
||||
if (use_mingw_win) {
|
||||
defines += [ "_USE_MATH_DEFINES" ]
|
||||
|
||||
cflags = [ "-std=c++17" ]
|
||||
} else {
|
||||
# add secure c API
|
||||
sources += [
|
||||
"//utils/native/base/src/securec/memset_s.c",
|
||||
"//utils/native/base/src/securec/securecutil.c",
|
||||
"//utils/native/base/src/securec/secureprintoutput_a.c",
|
||||
"//utils/native/base/src/securec/sprintf_s.c",
|
||||
"//utils/native/base/src/securec/strcat_s.c",
|
||||
"//utils/native/base/src/securec/strcpy_s.c",
|
||||
"//utils/native/base/src/securec/vsnprintf_s.c",
|
||||
"//utils/native/base/src/securec/vsprintf_s.c",
|
||||
]
|
||||
|
||||
if (!use_mac) {
|
||||
# add ashmem API
|
||||
sources += [
|
||||
"//utils/native/base/src/ashmem.cpp",
|
||||
"//utils/native/base/src/refbase.cpp",
|
||||
]
|
||||
} else {
|
||||
sources += [
|
||||
# This is used only when logs are printed on the MAC platform.
|
||||
"//utils/native/base/src/securec/snprintf_s.c",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ace_base_source_set("ace_base_ohos") {
|
||||
defines = ace_ohos_defines
|
||||
is_ohos_platform = true
|
||||
platform = "ohos"
|
||||
}
|
||||
|
||||
ace_base_source_set("ace_base_windows") {
|
||||
defines = ace_windows_defines
|
||||
is_ohos_platform = false
|
||||
platform = "windows"
|
||||
}
|
||||
|
||||
ace_base_source_set("ace_base_mac") {
|
||||
defines = ace_mac_defines
|
||||
is_ohos_platform = false
|
||||
platform = "mac"
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ARC_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ARC_H
|
||||
|
||||
#include "base/geometry/point.h"
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class Arc {
|
||||
public:
|
||||
Arc() = default;
|
||||
~Arc() = default;
|
||||
|
||||
const Point& GetCenterPoint() const
|
||||
{
|
||||
return centerPoint_;
|
||||
}
|
||||
|
||||
void SetCenterPoint(const Point& point)
|
||||
{
|
||||
centerPoint_ = point;
|
||||
}
|
||||
|
||||
double GetRadius() const
|
||||
{
|
||||
return radius_;
|
||||
}
|
||||
|
||||
void SetRadius(double radius)
|
||||
{
|
||||
radius_ = radius;
|
||||
}
|
||||
|
||||
double GetStartAngle() const
|
||||
{
|
||||
return startAngle_;
|
||||
}
|
||||
|
||||
void SetStartAngle(double angle)
|
||||
{
|
||||
startAngle_ = angle;
|
||||
}
|
||||
|
||||
double GetEndAngle() const
|
||||
{
|
||||
return endAngle_;
|
||||
}
|
||||
|
||||
void SetEndAngle(double angle)
|
||||
{
|
||||
endAngle_ = angle;
|
||||
}
|
||||
|
||||
double GetSweepAngle() const
|
||||
{
|
||||
return endAngle_ - startAngle_;
|
||||
}
|
||||
|
||||
void Rotate(const Point& point, double angle)
|
||||
{
|
||||
centerPoint_.Rotate(point, angle);
|
||||
startAngle_ += angle;
|
||||
endAngle_ += angle;
|
||||
}
|
||||
|
||||
void Move(double xOffset, double yOffset)
|
||||
{
|
||||
centerPoint_.SetX(centerPoint_.GetX() + xOffset);
|
||||
centerPoint_.SetY(centerPoint_.GetY() + yOffset);
|
||||
}
|
||||
|
||||
void GetPointByAngle(double angle, Point& out) const
|
||||
{
|
||||
out.SetX(centerPoint_.GetX() + radius_);
|
||||
out.SetY(centerPoint_.GetY());
|
||||
out.Rotate(centerPoint_, angle);
|
||||
}
|
||||
|
||||
void GetStartPoint(Point& out) const
|
||||
{
|
||||
GetPointByAngle(startAngle_, out);
|
||||
}
|
||||
|
||||
void GetEndPoint(Point& out) const
|
||||
{
|
||||
GetPointByAngle(endAngle_, out);
|
||||
}
|
||||
|
||||
Point GetStartPoint() const
|
||||
{
|
||||
Point startPoint;
|
||||
GetStartPoint(startPoint);
|
||||
return startPoint;
|
||||
}
|
||||
|
||||
Point GetEndPoint() const
|
||||
{
|
||||
Point endPoint;
|
||||
GetEndPoint(endPoint);
|
||||
return endPoint;
|
||||
}
|
||||
|
||||
double GetLeft() const
|
||||
{
|
||||
return centerPoint_.GetX() - radius_;
|
||||
}
|
||||
|
||||
double GetRight() const
|
||||
{
|
||||
return centerPoint_.GetX() + radius_;
|
||||
}
|
||||
|
||||
double GetTop() const
|
||||
{
|
||||
return centerPoint_.GetY() - radius_;
|
||||
}
|
||||
|
||||
double GetBottom() const
|
||||
{
|
||||
return centerPoint_.GetY() + radius_;
|
||||
}
|
||||
|
||||
private:
|
||||
Point centerPoint_;
|
||||
double radius_ = 0.0;
|
||||
double startAngle_ = 0.0;
|
||||
double endAngle_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_ARC_H
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_AXIS_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_AXIS_H
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
enum class Axis {
|
||||
VERTICAL = 0,
|
||||
HORIZONTAL,
|
||||
FREE,
|
||||
};
|
||||
|
||||
enum class RotateAxis {
|
||||
AXIS_X,
|
||||
AXIS_Y,
|
||||
AXIS_Z,
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_AXIS_H
|
||||
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H
|
||||
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
enum class DimensionUnit {
|
||||
/*
|
||||
* Logical pixel used in Ace. It's based on frontend design width.
|
||||
* For example, when a frontend with 750px design width running on a
|
||||
* device with 1080 pixels width, 1px represents 1.44 pixels.
|
||||
*/
|
||||
PX = 0,
|
||||
/*
|
||||
* Density independent pixels, one vp is one pixel on a 160 dpi screen.
|
||||
*/
|
||||
VP,
|
||||
/*
|
||||
* scale independent pixels, this is like VP but will be scaled by
|
||||
* user's font size preference.
|
||||
*/
|
||||
FP,
|
||||
/*
|
||||
* The percentage of either a value from the element's parent or from
|
||||
* another property of the element itself.
|
||||
*/
|
||||
PERCENT,
|
||||
};
|
||||
|
||||
/*
|
||||
* Dimension contains a value and an unit to represent different
|
||||
* scales in one class.
|
||||
*/
|
||||
class Dimension {
|
||||
public:
|
||||
constexpr Dimension() = default;
|
||||
~Dimension() = default;
|
||||
constexpr explicit Dimension(double value, DimensionUnit unit = DimensionUnit::PX) : value_(value), unit_(unit) {}
|
||||
|
||||
double Value() const
|
||||
{
|
||||
return value_;
|
||||
}
|
||||
|
||||
void SetValue(double value)
|
||||
{
|
||||
value_ = value;
|
||||
}
|
||||
|
||||
DimensionUnit Unit() const
|
||||
{
|
||||
return unit_;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return (value_ > 0.0) && (!NearZero(value_));
|
||||
}
|
||||
|
||||
double ConvertToPx(double dipScale) const
|
||||
{
|
||||
if (unit_ == DimensionUnit::VP || unit_ == DimensionUnit::FP) {
|
||||
return value_ * dipScale;
|
||||
} else {
|
||||
return value_;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr Dimension operator*(double value) const
|
||||
{
|
||||
return Dimension(value_ * value, unit_);
|
||||
}
|
||||
|
||||
constexpr Dimension operator/(double value) const
|
||||
{
|
||||
// NearZero cannot be used in a constant expression
|
||||
if (value > 0.0 ? value - 0.0 <= 0.000001f : 0.0 - value <= 0.000001f) {
|
||||
return Dimension();
|
||||
}
|
||||
return Dimension(value_ / value, unit_);
|
||||
}
|
||||
|
||||
bool operator==(const Dimension& dimension) const
|
||||
{
|
||||
return (unit_ == dimension.unit_) && NearEqual(value_, dimension.value_);
|
||||
}
|
||||
|
||||
bool operator!=(const Dimension& dimension) const
|
||||
{
|
||||
return !operator==(dimension);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add two dimensions using the same unit.
|
||||
*/
|
||||
constexpr Dimension operator+(const Dimension& dimension) const
|
||||
{
|
||||
ACE_DCHECK(unit_ == dimension.unit_);
|
||||
return Dimension(value_ + dimension.value_, unit_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Add a new dimension to itself using same unit.
|
||||
*/
|
||||
Dimension& operator+=(const Dimension& dimension)
|
||||
{
|
||||
ACE_DCHECK(unit_ == dimension.unit_);
|
||||
value_ += dimension.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
/*
|
||||
* Minus a dimension using the same unit.
|
||||
*/
|
||||
constexpr Dimension operator-(const Dimension& dimension) const
|
||||
{
|
||||
ACE_DCHECK(unit_ == dimension.unit_);
|
||||
return Dimension(value_ - dimension.value_, unit_);
|
||||
}
|
||||
|
||||
/*
|
||||
* The opposite of dimension.
|
||||
*/
|
||||
constexpr Dimension operator-() const
|
||||
{
|
||||
return Dimension(-value_, unit_);
|
||||
}
|
||||
|
||||
/*
|
||||
* Minus a dimension to itself using the same unit.
|
||||
*/
|
||||
Dimension& operator-=(const Dimension& dimension)
|
||||
{
|
||||
ACE_DCHECK(unit_ == dimension.unit_);
|
||||
value_ -= dimension.value_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator>(const Dimension& dimension) const
|
||||
{
|
||||
ACE_DCHECK(unit_ == dimension.unit_);
|
||||
return (value_ > dimension.value_);
|
||||
}
|
||||
|
||||
bool operator<(const Dimension& dimension) const
|
||||
{
|
||||
ACE_DCHECK(unit_ == dimension.unit_);
|
||||
return (value_ < dimension.value_);
|
||||
}
|
||||
|
||||
private:
|
||||
double value_ = 0.0;
|
||||
DimensionUnit unit_ = DimensionUnit::PX;
|
||||
};
|
||||
|
||||
// literal operators for dimension
|
||||
inline constexpr Dimension operator""_vp(long double value)
|
||||
{
|
||||
return Dimension(static_cast<double>(value), DimensionUnit::VP);
|
||||
}
|
||||
|
||||
inline constexpr Dimension operator""_px(long double value)
|
||||
{
|
||||
return Dimension(static_cast<double>(value), DimensionUnit::PX);
|
||||
}
|
||||
|
||||
inline constexpr Dimension operator""_fp(long double value)
|
||||
{
|
||||
return Dimension(static_cast<double>(value), DimensionUnit::FP);
|
||||
}
|
||||
|
||||
inline constexpr Dimension operator""_pct(long double value)
|
||||
{
|
||||
return Dimension(static_cast<double>(value), DimensionUnit::PERCENT);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_H
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_OFFSET_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_OFFSET_H
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "base/geometry/dimension.h"
|
||||
#include "base/geometry/offset.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class DimensionOffset {
|
||||
public:
|
||||
DimensionOffset() = default;
|
||||
~DimensionOffset() = default;
|
||||
DimensionOffset(Dimension deltaX, Dimension deltaY) : deltaX_(deltaX), deltaY_(deltaY) {}
|
||||
DimensionOffset(Offset offset) : deltaX_(Dimension(offset.GetX(), DimensionUnit::PX)),
|
||||
deltaY_(Dimension(offset.GetY(), DimensionUnit::PX)) {}
|
||||
|
||||
const Dimension& GetX() const
|
||||
{
|
||||
return deltaX_;
|
||||
}
|
||||
|
||||
const Dimension& GetY() const
|
||||
{
|
||||
return deltaY_;
|
||||
}
|
||||
|
||||
void SetX(Dimension& x)
|
||||
{
|
||||
deltaX_ = x;
|
||||
}
|
||||
|
||||
void SetY(Dimension& y)
|
||||
{
|
||||
deltaY_ = y;
|
||||
}
|
||||
|
||||
DimensionOffset operator+(const DimensionOffset& dimensionOffset) const
|
||||
{
|
||||
return DimensionOffset(deltaX_ + dimensionOffset.deltaX_, deltaY_ + dimensionOffset.deltaY_);
|
||||
}
|
||||
|
||||
DimensionOffset operator-(const DimensionOffset& dimensionOffset) const
|
||||
{
|
||||
return DimensionOffset(deltaX_ - dimensionOffset.deltaX_, deltaY_ - dimensionOffset.deltaY_);
|
||||
}
|
||||
|
||||
DimensionOffset operator*(double value) const
|
||||
{
|
||||
return DimensionOffset(deltaX_ * value, deltaY_ * value);
|
||||
}
|
||||
|
||||
private:
|
||||
Dimension deltaX_;
|
||||
Dimension deltaY_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_DIMENSION_OFFSET_H
|
||||
@@ -0,0 +1,308 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/geometry/matrix4.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
namespace {
|
||||
|
||||
constexpr int32_t MATRIX_LENGTH = Matrix4::DIMENSION * Matrix4::DIMENSION;
|
||||
|
||||
inline bool IsEqual(const float& left, const float& right)
|
||||
{
|
||||
return NearEqual(left, right);
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
Matrix4 Matrix4::CreateIdentity()
|
||||
{
|
||||
return Matrix4(
|
||||
1.0f, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, 1.0f, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, 1.0f, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::CreateTranslate(float x, float y, float z)
|
||||
{
|
||||
return Matrix4(
|
||||
1.0f, 0.0f, 0.0f, x,
|
||||
0.0f, 1.0f, 0.0f, y,
|
||||
0.0f, 0.0f, 1.0f, z,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::CreateScale(float x, float y, float z)
|
||||
{
|
||||
return Matrix4(
|
||||
x, 0.0f, 0.0f, 0.0f,
|
||||
0.0f, y, 0.0f, 0.0f,
|
||||
0.0f, 0.0f, z, 0.0f,
|
||||
0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::CreateRotate(float angle, float dx, float dy, float dz)
|
||||
{
|
||||
// (x,y,z) need normalize
|
||||
float sum = dx * dx + dy * dy + dz * dz;
|
||||
if (NearZero(sum)) {
|
||||
return Matrix4::CreateIdentity();
|
||||
}
|
||||
|
||||
float x = dx / sqrt(sum);
|
||||
float y = dy / sqrt(sum);
|
||||
float z = dz / sqrt(sum);
|
||||
float redian = static_cast<float>(angle * (M_PI / 180.0f));
|
||||
float cosValue = cosf(redian);
|
||||
float sinValue = sinf(redian);
|
||||
|
||||
return Matrix4(cosValue + (x * x * (1.0f - cosValue)), (x * y * (1.0f - cosValue)) - (z * sinValue),
|
||||
(x * z * (1.0f - cosValue)) + (y * sinValue), 0.0f, (y * x * (1.0f - cosValue)) + (z * sinValue),
|
||||
cosValue + (y * y * (1.0f - cosValue)), (y * z * (1.0f - cosValue)) - (x * sinValue), 0.0f,
|
||||
(z * x * (1.0f - cosValue)) - (y * sinValue), (z * y * (1.0f - cosValue)) + (x * sinValue),
|
||||
cosValue + (z * z * (1.0f - cosValue)), 0.0f, 0.0f, 0.0f, 0.0f, 1.0f);
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::Invert(const Matrix4& matrix)
|
||||
{
|
||||
Matrix4 inverted = CreateInvert(matrix);
|
||||
float determinant = matrix(0, 0) * inverted(0, 0) +
|
||||
matrix(0, 1) * inverted(1, 0) +
|
||||
matrix(0, 2) * inverted(2, 0) +
|
||||
matrix(0, 3) * inverted(3, 0);
|
||||
|
||||
if (!NearZero(determinant)) {
|
||||
inverted = inverted * (1.0f / determinant);
|
||||
} else {
|
||||
inverted = CreateIdentity();
|
||||
}
|
||||
|
||||
return inverted;
|
||||
}
|
||||
|
||||
Matrix4::Matrix4()
|
||||
: Matrix4(1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f)
|
||||
{}
|
||||
|
||||
Matrix4::Matrix4(const Matrix4& matrix)
|
||||
{
|
||||
std::copy_n(&matrix.matrix4x4_[0][0], MATRIX_LENGTH, &matrix4x4_[0][0]);
|
||||
}
|
||||
|
||||
Matrix4::Matrix4(float m00, float m01, float m02, float m03, float m10, float m11, float m12, float m13, float m20,
|
||||
float m21, float m22, float m23, float m30, float m31, float m32, float m33)
|
||||
{
|
||||
matrix4x4_[0][0] = m00;
|
||||
matrix4x4_[1][0] = m01;
|
||||
matrix4x4_[2][0] = m02;
|
||||
matrix4x4_[3][0] = m03;
|
||||
matrix4x4_[0][1] = m10;
|
||||
matrix4x4_[1][1] = m11;
|
||||
matrix4x4_[2][1] = m12;
|
||||
matrix4x4_[3][1] = m13;
|
||||
matrix4x4_[0][2] = m20;
|
||||
matrix4x4_[1][2] = m21;
|
||||
matrix4x4_[2][2] = m22;
|
||||
matrix4x4_[3][2] = m23;
|
||||
matrix4x4_[0][3] = m30;
|
||||
matrix4x4_[1][3] = m31;
|
||||
matrix4x4_[2][3] = m32;
|
||||
matrix4x4_[3][3] = m33;
|
||||
}
|
||||
|
||||
void Matrix4::SetScale(float x, float y, float z)
|
||||
{
|
||||
// The 4X4 matrix scale index is [0][0], [1][1], [2][2], [3][3].
|
||||
matrix4x4_[0][0] = x;
|
||||
matrix4x4_[1][1] = y;
|
||||
matrix4x4_[2][2] = z;
|
||||
matrix4x4_[3][3] = 1.0f;
|
||||
}
|
||||
|
||||
float Matrix4::GetScaleX() const
|
||||
{
|
||||
return matrix4x4_[0][0];
|
||||
}
|
||||
|
||||
float Matrix4::GetScaleY() const
|
||||
{
|
||||
return matrix4x4_[1][1];
|
||||
}
|
||||
|
||||
void Matrix4::SetEntry(int32_t row, int32_t col, float value)
|
||||
{
|
||||
if ((row < 0 || row >= DIMENSION) || (col < 0 || col >= DIMENSION)) {
|
||||
return;
|
||||
}
|
||||
matrix4x4_[row][col] = value;
|
||||
}
|
||||
|
||||
bool Matrix4::IsIdentityMatrix() const
|
||||
{
|
||||
return *this == CreateIdentity();
|
||||
}
|
||||
|
||||
void Matrix4::Rotate(float angle, float dx, float dy, float dz)
|
||||
{
|
||||
Matrix4 transform = *this;
|
||||
*this = transform * CreateRotate(angle, dx, dy, dz);
|
||||
}
|
||||
|
||||
int32_t Matrix4::Count() const
|
||||
{
|
||||
return MATRIX_LENGTH;
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::CreateInvert(const Matrix4& matrix)
|
||||
{
|
||||
return Matrix4(
|
||||
matrix(1, 1) * matrix(2, 2) * matrix(3, 3) - matrix(1, 1) * matrix(2, 3) * matrix(3, 2) -
|
||||
matrix(2, 1) * matrix(1, 2) * matrix(3, 3) + matrix(2, 1) * matrix(1, 3) * matrix(3, 2) +
|
||||
matrix(3, 1) * matrix(1, 2) * matrix(2, 3) - matrix(3, 1) * matrix(1, 3) * matrix(2, 2),
|
||||
-matrix(1, 0) * matrix(2, 2) * matrix(3, 3) + matrix(1, 0) * matrix(2, 3) * matrix(3, 2) +
|
||||
matrix(2, 0) * matrix(1, 2) * matrix(3, 3) - matrix(2, 0) * matrix(1, 3) * matrix(3, 2) -
|
||||
matrix(3, 0) * matrix(1, 2) * matrix(2, 3) + matrix(3, 0) * matrix(1, 3) * matrix(2, 2),
|
||||
matrix(1, 0) * matrix(2, 1) * matrix(3, 3) - matrix(1, 0) * matrix(2, 3) * matrix(3, 1) -
|
||||
matrix(2, 0) * matrix(1, 1) * matrix(3, 3) + matrix(2, 0) * matrix(1, 3) * matrix(3, 1) +
|
||||
matrix(3, 0) * matrix(1, 1) * matrix(2, 3) - matrix(3, 0) * matrix(1, 3) * matrix(2, 1),
|
||||
-matrix(1, 0) * matrix(2, 1) * matrix(3, 2) + matrix(1, 0) * matrix(2, 2) * matrix(3, 1) +
|
||||
matrix(2, 0) * matrix(1, 1) * matrix(3, 2) - matrix(2, 0) * matrix(1, 2) * matrix(3, 1) -
|
||||
matrix(3, 0) * matrix(1, 1) * matrix(2, 2) + matrix(3, 0) * matrix(1, 2) * matrix(2, 1),
|
||||
-matrix(0, 1) * matrix(2, 2) * matrix(3, 3) + matrix(0, 1) * matrix(2, 3) * matrix(3, 2) +
|
||||
matrix(2, 1) * matrix(0, 2) * matrix(3, 3) - matrix(2, 1) * matrix(0, 3) * matrix(3, 2) -
|
||||
matrix(3, 1) * matrix(0, 2) * matrix(2, 3) + matrix(3, 1) * matrix(0, 3) * matrix(2, 2),
|
||||
matrix(0, 0) * matrix(2, 2) * matrix(3, 3) - matrix(0, 0) * matrix(2, 3) * matrix(3, 2) -
|
||||
matrix(2, 0) * matrix(0, 2) * matrix(3, 3) + matrix(2, 0) * matrix(0, 3) * matrix(3, 2) +
|
||||
matrix(3, 0) * matrix(0, 2) * matrix(2, 3) - matrix(3, 0) * matrix(0, 3) * matrix(2, 2),
|
||||
-matrix(0, 0) * matrix(2, 1) * matrix(3, 3) + matrix(0, 0) * matrix(2, 3) * matrix(3, 1) +
|
||||
matrix(2, 0) * matrix(0, 1) * matrix(3, 3) - matrix(2, 0) * matrix(0, 3) * matrix(3, 1) -
|
||||
matrix(3, 0) * matrix(0, 1) * matrix(2, 3) + matrix(3, 0) * matrix(0, 3) * matrix(2, 1),
|
||||
matrix(0, 0) * matrix(2, 1) * matrix(3, 2) - matrix(0, 0) * matrix(2, 2) * matrix(3, 1) -
|
||||
matrix(2, 0) * matrix(0, 1) * matrix(3, 2) + matrix(2, 0) * matrix(0, 2) * matrix(3, 1) +
|
||||
matrix(3, 0) * matrix(0, 1) * matrix(2, 2) - matrix(3, 0) * matrix(0, 2) * matrix(2, 1),
|
||||
matrix(0, 1) * matrix(1, 2) * matrix(3, 3) - matrix(0, 1) * matrix(1, 3) * matrix(3, 2) -
|
||||
matrix(1, 1) * matrix(0, 2) * matrix(3, 3) + matrix(1, 1) * matrix(0, 3) * matrix(3, 2) +
|
||||
matrix(3, 1) * matrix(0, 2) * matrix(1, 3) - matrix(3, 1) * matrix(0, 3) * matrix(1, 2),
|
||||
-matrix(0, 0) * matrix(1, 2) * matrix(3, 3) + matrix(0, 0) * matrix(1, 3) * matrix(3, 2) +
|
||||
matrix(1, 0) * matrix(0, 2) * matrix(3, 3) - matrix(1, 0) * matrix(0, 3) * matrix(3, 2) -
|
||||
matrix(3, 0) * matrix(0, 2) * matrix(1, 3) + matrix(3, 0) * matrix(0, 3) * matrix(1, 2),
|
||||
matrix(0, 0) * matrix(1, 1) * matrix(3, 3) - matrix(0, 0) * matrix(1, 3) * matrix(3, 1) -
|
||||
matrix(1, 0) * matrix(0, 1) * matrix(3, 3) + matrix(1, 0) * matrix(0, 3) * matrix(3, 1) +
|
||||
matrix(3, 0) * matrix(0, 1) * matrix(1, 3) - matrix(3, 0) * matrix(0, 3) * matrix(1, 1),
|
||||
-matrix(0, 0) * matrix(1, 1) * matrix(3, 2) + matrix(0, 0) * matrix(1, 2) * matrix(3, 1) +
|
||||
matrix(1, 0) * matrix(0, 1) * matrix(3, 2) - matrix(1, 0) * matrix(0, 2) * matrix(3, 1) -
|
||||
matrix(3, 0) * matrix(0, 1) * matrix(1, 2) + matrix(3, 0) * matrix(0, 2) * matrix(1, 1),
|
||||
-matrix(0, 1) * matrix(1, 2) * matrix(2, 3) + matrix(0, 1) * matrix(1, 3) * matrix(2, 2) +
|
||||
matrix(1, 1) * matrix(0, 2) * matrix(2, 3) - matrix(1, 1) * matrix(0, 3) * matrix(2, 2) -
|
||||
matrix(2, 1) * matrix(0, 2) * matrix(1, 3) + matrix(2, 1) * matrix(0, 3) * matrix(1, 2),
|
||||
matrix(0, 0) * matrix(1, 2) * matrix(2, 3) - matrix(0, 0) * matrix(1, 3) * matrix(2, 2) -
|
||||
matrix(1, 0) * matrix(0, 2) * matrix(2, 3) + matrix(1, 0) * matrix(0, 3) * matrix(2, 2) +
|
||||
matrix(2, 0) * matrix(0, 2) * matrix(1, 3) - matrix(2, 0) * matrix(0, 3) * matrix(1, 2),
|
||||
-matrix(0, 0) * matrix(1, 1) * matrix(2, 3) + matrix(0, 0) * matrix(1, 3) * matrix(2, 1) +
|
||||
matrix(1, 0) * matrix(0, 1) * matrix(2, 3) - matrix(1, 0) * matrix(0, 3) * matrix(2, 1) -
|
||||
matrix(2, 0) * matrix(0, 1) * matrix(1, 3) + matrix(2, 0) * matrix(0, 3) * matrix(1, 1),
|
||||
matrix(0, 0) * matrix(1, 1) * matrix(2, 2) - matrix(0, 0) * matrix(1, 2) * matrix(2, 1) -
|
||||
matrix(1, 0) * matrix(0, 1) * matrix(2, 2) + matrix(1, 0) * matrix(0, 2) * matrix(2, 1) +
|
||||
matrix(2, 0) * matrix(0, 1) * matrix(1, 2) - matrix(2, 0) * matrix(0, 2) * matrix(1, 1));
|
||||
}
|
||||
|
||||
bool Matrix4::operator==(const Matrix4& matrix) const
|
||||
{
|
||||
return std::equal(&matrix4x4_[0][0], &matrix4x4_[0][0] + MATRIX_LENGTH, &matrix.matrix4x4_[0][0], IsEqual);
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::operator*(float num)
|
||||
{
|
||||
Matrix4 ret(*this);
|
||||
std::for_each_n(&ret.matrix4x4_[0][0], MATRIX_LENGTH, [num](float& v) { v *= num; });
|
||||
return ret;
|
||||
}
|
||||
|
||||
Matrix4 Matrix4::operator*(const Matrix4& matrix)
|
||||
{
|
||||
return Matrix4(
|
||||
matrix4x4_[0][0] * matrix(0, 0) + matrix4x4_[1][0] * matrix(0, 1) + matrix4x4_[2][0] * matrix(0, 2) +
|
||||
matrix4x4_[3][0] * matrix(0, 3),
|
||||
matrix4x4_[0][0] * matrix(1, 0) + matrix4x4_[1][0] * matrix(1, 1) + matrix4x4_[2][0] * matrix(1, 2) +
|
||||
matrix4x4_[3][0] * matrix(1, 3),
|
||||
matrix4x4_[0][0] * matrix(2, 0) + matrix4x4_[1][0] * matrix(2, 1) + matrix4x4_[2][0] * matrix(2, 2) +
|
||||
matrix4x4_[3][0] * matrix(2, 3),
|
||||
matrix4x4_[0][0] * matrix(3, 0) + matrix4x4_[1][0] * matrix(3, 1) + matrix4x4_[2][0] * matrix(3, 2) +
|
||||
matrix4x4_[3][0] * matrix(3, 3),
|
||||
matrix4x4_[0][1] * matrix(0, 0) + matrix4x4_[1][1] * matrix(0, 1) + matrix4x4_[2][1] * matrix(0, 2) +
|
||||
matrix4x4_[3][1] * matrix(0, 3),
|
||||
matrix4x4_[0][1] * matrix(1, 0) + matrix4x4_[1][1] * matrix(1, 1) + matrix4x4_[2][1] * matrix(1, 2) +
|
||||
matrix4x4_[3][1] * matrix(1, 3),
|
||||
matrix4x4_[0][1] * matrix(2, 0) + matrix4x4_[1][1] * matrix(2, 1) + matrix4x4_[2][1] * matrix(2, 2) +
|
||||
matrix4x4_[3][1] * matrix(2, 3),
|
||||
matrix4x4_[0][1] * matrix(3, 0) + matrix4x4_[1][1] * matrix(3, 1) + matrix4x4_[2][1] * matrix(3, 2) +
|
||||
matrix4x4_[3][1] * matrix(3, 3),
|
||||
matrix4x4_[0][2] * matrix(0, 0) + matrix4x4_[1][2] * matrix(0, 1) + matrix4x4_[2][2] * matrix(0, 2) +
|
||||
matrix4x4_[3][2] * matrix(0, 3),
|
||||
matrix4x4_[0][2] * matrix(1, 0) + matrix4x4_[1][2] * matrix(1, 1) + matrix4x4_[2][2] * matrix(1, 2) +
|
||||
matrix4x4_[3][2] * matrix(1, 3),
|
||||
matrix4x4_[0][2] * matrix(2, 0) + matrix4x4_[1][2] * matrix(2, 1) + matrix4x4_[2][2] * matrix(2, 2) +
|
||||
matrix4x4_[3][2] * matrix(2, 3),
|
||||
matrix4x4_[0][2] * matrix(3, 0) + matrix4x4_[1][2] * matrix(3, 1) + matrix4x4_[2][2] * matrix(3, 2) +
|
||||
matrix4x4_[3][2] * matrix(3, 3),
|
||||
matrix4x4_[0][3] * matrix(0, 0) + matrix4x4_[1][3] * matrix(0, 1) + matrix4x4_[2][3] * matrix(0, 2) +
|
||||
matrix4x4_[3][3] * matrix(0, 3),
|
||||
matrix4x4_[0][3] * matrix(1, 0) + matrix4x4_[1][3] * matrix(1, 1) + matrix4x4_[2][3] * matrix(1, 2) +
|
||||
matrix4x4_[3][3] * matrix(1, 3),
|
||||
matrix4x4_[0][3] * matrix(2, 0) + matrix4x4_[1][3] * matrix(2, 1) + matrix4x4_[2][3] * matrix(2, 2) +
|
||||
matrix4x4_[3][3] * matrix(2, 3),
|
||||
matrix4x4_[0][3] * matrix(3, 0) + matrix4x4_[1][3] * matrix(3, 1) + matrix4x4_[2][3] * matrix(3, 2) +
|
||||
matrix4x4_[3][3] * matrix(3, 3));
|
||||
}
|
||||
|
||||
Point Matrix4::operator*(const Point& point)
|
||||
{
|
||||
double x = point.GetX();
|
||||
double y = point.GetY();
|
||||
return Point(matrix4x4_[0][0] * x + matrix4x4_[1][0] * y + matrix4x4_[3][0],
|
||||
matrix4x4_[0][1] * x + matrix4x4_[1][1] * y + matrix4x4_[3][1]);
|
||||
}
|
||||
|
||||
Matrix4& Matrix4::operator=(const Matrix4& matrix)
|
||||
{
|
||||
if (this == &matrix) {
|
||||
return *this;
|
||||
}
|
||||
std::copy_n(&matrix.matrix4x4_[0][0], MATRIX_LENGTH, &matrix4x4_[0][0]);
|
||||
return *this;
|
||||
}
|
||||
|
||||
float Matrix4::operator[](int32_t index) const
|
||||
{
|
||||
if (index < 0 || index >= MATRIX_LENGTH) {
|
||||
return 0.0f;
|
||||
}
|
||||
int32_t row = index / DIMENSION;
|
||||
int32_t col = index % DIMENSION;
|
||||
return matrix4x4_[row][col];
|
||||
}
|
||||
|
||||
float Matrix4::operator()(int32_t row, int32_t col) const
|
||||
{
|
||||
// Caller guarantee row and col in range of [0, 3].
|
||||
return matrix4x4_[row][col];
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_MATRIX4_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_MATRIX4_H
|
||||
|
||||
#include "base/geometry/point.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class ACE_EXPORT Matrix4 final {
|
||||
public:
|
||||
// Matrix dimension is 4X4.
|
||||
static constexpr int32_t DIMENSION = 4;
|
||||
// Crate an identity matrix.
|
||||
static Matrix4 CreateIdentity();
|
||||
// Multiplies this matrix by another that translates coordinates by the vector (x, y, z).
|
||||
static Matrix4 CreateTranslate(float x, float y, float z);
|
||||
// Multiplies this matrix by another that scales coordinates by the vector (x, y, z).
|
||||
static Matrix4 CreateScale(float x, float y, float z);
|
||||
// Multiplies this matrix by another that rotates coordinates through angle degrees about the vector (dx, dy, dz).
|
||||
static Matrix4 CreateRotate(float angle, float dx, float dy, float dz);
|
||||
// Returns the inverse of this matrix. Returns the identity if this matrix cannot be inverted;
|
||||
static Matrix4 Invert(const Matrix4& matrix);
|
||||
|
||||
Matrix4();
|
||||
Matrix4(const Matrix4& matrix);
|
||||
Matrix4(
|
||||
float m00, float m01, float m02, float m03,
|
||||
float m10, float m11, float m12, float m13,
|
||||
float m20, float m21, float m22, float m23,
|
||||
float m30, float m31, float m32, float m33);
|
||||
~Matrix4() = default;
|
||||
void SetScale(float x, float y, float z);
|
||||
float GetScaleX() const;
|
||||
float GetScaleY() const;
|
||||
void Rotate(float angle, float dx, float dy, float dz);
|
||||
void SetEntry(int32_t row, int32_t col, float value);
|
||||
bool IsIdentityMatrix() const;
|
||||
int32_t Count() const;
|
||||
|
||||
bool operator==(const Matrix4& matrix) const;
|
||||
Matrix4 operator*(float num);
|
||||
Matrix4 operator*(const Matrix4& matrix);
|
||||
// Transform point by the matrix
|
||||
Point operator*(const Point& point);
|
||||
Matrix4& operator=(const Matrix4& matrix);
|
||||
float operator[](int32_t index) const;
|
||||
|
||||
private:
|
||||
static Matrix4 CreateInvert(const Matrix4& matrix);
|
||||
float operator()(int32_t row, int32_t col) const;
|
||||
|
||||
float matrix4x4_[DIMENSION][DIMENSION] = {
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
{ 0.0f, 0.0f, 0.0f, 0.0f },
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_MATRIX4_H
|
||||
@@ -0,0 +1,150 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_OFFSET_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_OFFSET_H
|
||||
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#include "base/geometry/size.h"
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class Offset {
|
||||
public:
|
||||
Offset() = default;
|
||||
~Offset() = default;
|
||||
Offset(double deltaX, double deltaY) : deltaX_(deltaX), deltaY_(deltaY) {}
|
||||
|
||||
void Reset()
|
||||
{
|
||||
deltaX_ = 0.0;
|
||||
deltaY_ = 0.0;
|
||||
}
|
||||
|
||||
static Offset Zero()
|
||||
{
|
||||
return Offset();
|
||||
}
|
||||
|
||||
static Offset ErrorOffset()
|
||||
{
|
||||
return Offset((std::numeric_limits<double>::max)(), (std::numeric_limits<double>::max)());
|
||||
}
|
||||
|
||||
bool IsZero() const
|
||||
{
|
||||
return operator==(Offset());
|
||||
}
|
||||
|
||||
bool IsErrorOffset() const
|
||||
{
|
||||
return operator==(ErrorOffset());
|
||||
}
|
||||
|
||||
double GetX() const
|
||||
{
|
||||
return deltaX_;
|
||||
}
|
||||
|
||||
double GetY() const
|
||||
{
|
||||
return deltaY_;
|
||||
}
|
||||
|
||||
void SetX(double x)
|
||||
{
|
||||
deltaX_ = x;
|
||||
}
|
||||
|
||||
void SetY(double y)
|
||||
{
|
||||
deltaY_ = y;
|
||||
}
|
||||
|
||||
double GetDistance() const
|
||||
{
|
||||
return std::sqrt((deltaX_ * deltaX_) + (deltaY_ * deltaY_));
|
||||
}
|
||||
|
||||
Offset operator+(const Offset& offset) const
|
||||
{
|
||||
return Offset(deltaX_ + offset.deltaX_, deltaY_ + offset.deltaY_);
|
||||
}
|
||||
|
||||
Offset operator+(const Size& size) const
|
||||
{
|
||||
return Offset(deltaX_ + size.Width(), deltaY_ + size.Height());
|
||||
}
|
||||
|
||||
Offset operator-(const Offset& offset) const
|
||||
{
|
||||
return Offset(deltaX_ - offset.deltaX_, deltaY_ - offset.deltaY_);
|
||||
}
|
||||
|
||||
Offset operator*(double value) const
|
||||
{
|
||||
return Offset(deltaX_ * value, deltaY_ * value);
|
||||
}
|
||||
|
||||
Offset operator/(double value) const
|
||||
{
|
||||
if (NearZero(value)) {
|
||||
return ErrorOffset();
|
||||
}
|
||||
return Offset(deltaX_ / value, deltaY_ / value);
|
||||
}
|
||||
|
||||
Offset& operator+=(const Offset& offset)
|
||||
{
|
||||
deltaX_ += offset.deltaX_;
|
||||
deltaY_ += offset.deltaY_;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool operator==(const Offset& offset) const
|
||||
{
|
||||
return NearEqual(deltaX_, offset.deltaX_) && NearEqual(deltaY_, offset.deltaY_);
|
||||
}
|
||||
|
||||
bool operator!=(const Offset& offset) const
|
||||
{
|
||||
return !operator==(offset);
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return std::string("Offset (")
|
||||
.append(std::to_string(deltaX_))
|
||||
.append(", ")
|
||||
.append(std::to_string(deltaY_))
|
||||
.append(")");
|
||||
}
|
||||
|
||||
bool IsPositiveOffset() const
|
||||
{
|
||||
return deltaX_ >= 0 && deltaY_ >= 0;
|
||||
}
|
||||
|
||||
private:
|
||||
double deltaX_ = 0.0;
|
||||
double deltaY_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_OFFSET_H
|
||||
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_POINT_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_POINT_H
|
||||
|
||||
#include "base/geometry/offset.h"
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class ACE_EXPORT Point {
|
||||
public:
|
||||
Point() = default;
|
||||
~Point() = default;
|
||||
Point(double x, double y) : x_(x), y_(y) {}
|
||||
|
||||
double GetX() const
|
||||
{
|
||||
return x_;
|
||||
}
|
||||
|
||||
double GetY() const
|
||||
{
|
||||
return y_;
|
||||
}
|
||||
|
||||
void SetX(double x)
|
||||
{
|
||||
x_ = x;
|
||||
}
|
||||
|
||||
void SetY(double y)
|
||||
{
|
||||
y_ = y;
|
||||
}
|
||||
|
||||
void Rotate(const Point& center, double angle)
|
||||
{
|
||||
double x = (x_ - center.GetX()) * std::cos(angle) - (y_ - center.GetY()) * std::sin(angle) + center.GetX();
|
||||
double y = (x_ - center.GetX()) * std::sin(angle) + (y_ - center.GetY()) * std::cos(angle) + center.GetY();
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
}
|
||||
|
||||
Point operator-(const Offset& offset) const
|
||||
{
|
||||
return Point(x_ - offset.GetX(), y_ - offset.GetY());
|
||||
}
|
||||
|
||||
Point operator+(const Offset& offset) const
|
||||
{
|
||||
return Point(x_ + offset.GetX(), y_ + offset.GetY());
|
||||
}
|
||||
|
||||
Offset operator-(const Point& point) const
|
||||
{
|
||||
return Offset(x_ - point.x_, y_ - point.y_);
|
||||
}
|
||||
|
||||
bool operator==(const Point& point) const
|
||||
{
|
||||
return NearEqual(x_, point.x_) && NearEqual(y_, point.y_);
|
||||
}
|
||||
|
||||
bool operator!=(const Point& point) const
|
||||
{
|
||||
return !operator==(point);
|
||||
}
|
||||
|
||||
private:
|
||||
double x_ = 0.0;
|
||||
double y_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_POINT_H
|
||||
@@ -0,0 +1,389 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RECT_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RECT_H
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
#include "base/geometry/offset.h"
|
||||
#include "base/geometry/point.h"
|
||||
#include "base/geometry/size.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class Rect {
|
||||
public:
|
||||
Rect() = default;
|
||||
~Rect() = default;
|
||||
|
||||
Rect(double x, double y, double width, double height)
|
||||
{
|
||||
SetRect(x, y, width, height);
|
||||
}
|
||||
|
||||
Rect(const Offset& offset, const Size& size)
|
||||
{
|
||||
SetOffset(offset);
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void SetRect(double x, double y, double width, double height)
|
||||
{
|
||||
x_ = x;
|
||||
y_ = y;
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
void SetRect(const Offset& offset, const Size& size)
|
||||
{
|
||||
SetOffset(offset);
|
||||
SetSize(size);
|
||||
}
|
||||
|
||||
void ApplyScale(double scale)
|
||||
{
|
||||
x_ *= scale;
|
||||
y_ *= scale;
|
||||
width_ *= scale;
|
||||
height_ *= scale;
|
||||
}
|
||||
|
||||
void ApplyScaleAndRound(const Size& scale)
|
||||
{
|
||||
x_ = round(x_ * scale.Width());
|
||||
y_ = round(y_ * scale.Height());
|
||||
width_ = round(width_ * scale.Width());
|
||||
height_ = round(height_ * scale.Height());
|
||||
}
|
||||
|
||||
double Left() const
|
||||
{
|
||||
return width_ > 0.0 ? x_ : x_ + width_;
|
||||
}
|
||||
|
||||
double Top() const
|
||||
{
|
||||
return height_ > 0.0 ? y_ : y_ + height_;
|
||||
}
|
||||
|
||||
double Right() const
|
||||
{
|
||||
return width_ > 0.0 ? x_ + width_ : x_;
|
||||
}
|
||||
|
||||
double Bottom() const
|
||||
{
|
||||
return height_ > 0.0 ? y_ + height_ : y_;
|
||||
}
|
||||
|
||||
double Width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
double Height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
void SetSize(const Size& size)
|
||||
{
|
||||
width_ = size.Width();
|
||||
height_ = size.Height();
|
||||
}
|
||||
|
||||
Size GetSize() const
|
||||
{
|
||||
return Size(width_, height_);
|
||||
}
|
||||
|
||||
void SetOffset(const Offset& offset)
|
||||
{
|
||||
x_ = offset.GetX();
|
||||
y_ = offset.GetY();
|
||||
}
|
||||
|
||||
Offset GetOffset() const
|
||||
{
|
||||
return Offset(x_, y_);
|
||||
}
|
||||
|
||||
void SetLeft(double left)
|
||||
{
|
||||
x_ = left;
|
||||
}
|
||||
|
||||
void SetTop(double top)
|
||||
{
|
||||
y_ = top;
|
||||
}
|
||||
|
||||
void SetWidth(double width)
|
||||
{
|
||||
width_ = width;
|
||||
}
|
||||
|
||||
void SetHeight(double height)
|
||||
{
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
bool IsInRegion(const Point& point) const
|
||||
{
|
||||
return (point.GetX() > x_) && (point.GetX() < (x_ + width_)) && (point.GetY() > y_) &&
|
||||
(point.GetY() < (y_ + height_));
|
||||
}
|
||||
|
||||
bool IsWrappedBy(const Rect& other) const
|
||||
{
|
||||
return (Left() >= other.Left()) && (Right() <= other.Right()) && (Top() >= other.Top()) &&
|
||||
(Bottom() <= other.Bottom());
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return width_ > 0.0 && height_ > 0.0;
|
||||
}
|
||||
|
||||
Rect Constrain(const Rect& other)
|
||||
{
|
||||
double right = Right();
|
||||
double bottom = Bottom();
|
||||
double left = std::clamp(x_, other.Left(), other.Right());
|
||||
double top = std::clamp(y_, other.Top(), other.Bottom());
|
||||
right = std::clamp(right, other.Left(), other.Right()) - left;
|
||||
bottom = std::clamp(bottom, other.Top(), other.Bottom()) - top;
|
||||
return Rect(left, top, right, bottom);
|
||||
}
|
||||
|
||||
Rect& operator+=(const Offset& offset)
|
||||
{
|
||||
x_ += offset.GetX();
|
||||
y_ += offset.GetY();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rect& operator-=(const Offset& offset)
|
||||
{
|
||||
x_ -= offset.GetX();
|
||||
y_ -= offset.GetY();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rect& operator+=(const Size& size)
|
||||
{
|
||||
width_ += size.Width();
|
||||
height_ += size.Height();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rect& operator-=(const Size& size)
|
||||
{
|
||||
width_ -= size.Width();
|
||||
height_ -= size.Height();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Rect operator+(const Offset& offset) const
|
||||
{
|
||||
return Rect(x_ + offset.GetX(), y_ + offset.GetY(), width_, height_);
|
||||
}
|
||||
|
||||
Rect operator-(const Offset& offset) const
|
||||
{
|
||||
return Rect(x_ - offset.GetX(), y_ - offset.GetY(), width_, height_);
|
||||
}
|
||||
|
||||
Rect operator+(const Size& size) const
|
||||
{
|
||||
return Rect(x_, y_, width_ + size.Width(), height_ + size.Height());
|
||||
}
|
||||
|
||||
Rect operator-(const Size& size) const
|
||||
{
|
||||
return Rect(x_, y_, width_ - size.Width(), height_ - size.Height());
|
||||
}
|
||||
|
||||
Rect operator*(double scale) const
|
||||
{
|
||||
return Rect(x_ * scale, y_ * scale, width_ * scale, height_ * scale);
|
||||
}
|
||||
|
||||
bool operator==(const Rect& rect) const
|
||||
{
|
||||
return (GetOffset() == rect.GetOffset()) && (GetSize() == rect.GetSize());
|
||||
}
|
||||
|
||||
bool operator!=(const Rect& rect) const
|
||||
{
|
||||
return !operator==(rect);
|
||||
}
|
||||
|
||||
bool IsIntersectWith(const Rect& other) const
|
||||
{
|
||||
return !(other.Right() < Left() || other.Left() > Right() || other.Bottom() < Top() || other.Top() > Bottom());
|
||||
}
|
||||
|
||||
Rect IntersectRect(const Rect& other) const
|
||||
{
|
||||
double left = std::max(Left(), other.Left());
|
||||
double right = std::min(Right(), other.Right());
|
||||
double top = std::max(Top(), other.Top());
|
||||
double bottom = std::min(Bottom(), other.Bottom());
|
||||
return Rect(left, top, right - left, bottom - top);
|
||||
}
|
||||
|
||||
Rect CombineRect(const Rect& other) const
|
||||
{
|
||||
double left = std::min(Left(), other.Left());
|
||||
double right = std::max(Right(), other.Right());
|
||||
double top = std::min(Top(), other.Top());
|
||||
double bottom = std::max(Bottom(), other.Bottom());
|
||||
return Rect(left, top, right - left, bottom - top);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Magnetically attracted to a "magnetic" rect.
|
||||
*
|
||||
* Let's show some cases to illustrate how this method works:
|
||||
*
|
||||
* Case 1 : Inside. Rect won't be move because it is already attracted by magnet.
|
||||
* Result: Offset(0, 0)
|
||||
*
|
||||
* +-----------------------------+
|
||||
* | |
|
||||
* | Magnetical Rect |
|
||||
* | |
|
||||
* | +-------+ |
|
||||
* | | R | |
|
||||
* | | | |
|
||||
* | +-------+ |
|
||||
* +-----------------------------+
|
||||
*
|
||||
* Case 2: Outside. R will be attracted to position R'
|
||||
* Result: Offset(-12, -3)
|
||||
*
|
||||
* +-----------------------+
|
||||
* | |
|
||||
* | Magnetical Rect +--+
|
||||
* | | |
|
||||
* | |R'| +--+
|
||||
* +-----------------------+ |R |
|
||||
* | |
|
||||
* +--+
|
||||
*
|
||||
* Case 3: Half Inside. R will be moved totally into magnet.
|
||||
* Result: Offset(-8, 0)
|
||||
*
|
||||
* +-----------------------------+ +-----------------------------+
|
||||
* | | | |
|
||||
* | Magnetical Rect | +----------> | Magnetical Rect |
|
||||
* | | | |
|
||||
* | +----------+ | +----------+
|
||||
* | | | R | | | R' |
|
||||
* | +----------+ | +----------+
|
||||
* | | | |
|
||||
* +-----------------------------+ +-----------------------------+
|
||||
*
|
||||
* Case 4: Outside or Half Outside but space not enough. R will be moved into magnet as more as possible.
|
||||
* Result: Offset(0, 1)
|
||||
*
|
||||
* +--+
|
||||
* | | +--+
|
||||
* |R | | |
|
||||
* | | |R'|
|
||||
* +---------------------------+ +---------------------------+
|
||||
* | | | | | | | |
|
||||
* | Magnetical Rect | | | +-----> | Magnetical Rect | | |
|
||||
* | +--+ | | | | |
|
||||
* +---------------------------+ +------------------+--+-----+
|
||||
*
|
||||
* Case 5: Totally Across magnet. Nothing should happen.
|
||||
* Result: Offset(0, 0)
|
||||
*
|
||||
* +--+
|
||||
* | |
|
||||
* |R |
|
||||
* | |
|
||||
* +---------------------------+
|
||||
* | | | |
|
||||
* | Magnetical Rect | | |
|
||||
* | | | |
|
||||
* +---------------------------+
|
||||
* | |
|
||||
* +--+
|
||||
*
|
||||
* @param[in] magnet The magnetical rectangle.
|
||||
*
|
||||
* @return The offset that this rect need to moving into magnet.
|
||||
*/
|
||||
Offset MagneticAttractedBy(const Rect& magnet)
|
||||
{
|
||||
Offset offset = Offset::Zero();
|
||||
if (IsWrappedBy(magnet)) {
|
||||
return Offset::Zero();
|
||||
}
|
||||
|
||||
if (Left() < magnet.Left()) {
|
||||
offset.SetX(std::max(0.0, std::min(magnet.Left() - Left(), magnet.Right() - Right())));
|
||||
} else if (Right() > magnet.Right()) {
|
||||
offset.SetX(std::min(0.0, std::max(magnet.Left() - Left(), magnet.Right() - Right())));
|
||||
} else {
|
||||
// No need to offset.
|
||||
}
|
||||
|
||||
if (Top() < magnet.Top()) {
|
||||
offset.SetY(std::max(0.0, std::min(magnet.Top() - Top(), magnet.Bottom() - Bottom())));
|
||||
} else if (Bottom() > magnet.Bottom()) {
|
||||
offset.SetY(std::min(0.0, std::max(magnet.Top() - Top(), magnet.Bottom() - Bottom())));
|
||||
} else {
|
||||
// No need to offset.
|
||||
}
|
||||
|
||||
*this += offset;
|
||||
|
||||
return offset;
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return std::string("Rect (")
|
||||
.append(std::to_string(x_))
|
||||
.append(", ")
|
||||
.append(std::to_string(y_))
|
||||
.append(") - [")
|
||||
.append(NearEqual(width_, Size::INFINITE_SIZE) ? "INFINITE" : std::to_string(width_))
|
||||
.append(" x ")
|
||||
.append(NearEqual(height_, Size::INFINITE_SIZE) ? "INFINITE" : std::to_string(height_))
|
||||
.append("]");
|
||||
}
|
||||
|
||||
Offset Center() const
|
||||
{
|
||||
return Offset(width_ / 2.0 + x_, height_ / 2.0 + y_);
|
||||
}
|
||||
|
||||
private:
|
||||
double x_ = 0.0;
|
||||
double y_ = 0.0;
|
||||
double width_ = 0.0;
|
||||
double height_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RECT_H
|
||||
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RRECT_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RRECT_H
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
#include "base/geometry/rect.h"
|
||||
#include "core/components/common/properties/radius.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
struct Corner {
|
||||
Radius topLeftRadius;
|
||||
Radius topRightRadius;
|
||||
Radius bottomRightRadius;
|
||||
Radius bottomLeftRadius;
|
||||
};
|
||||
|
||||
class RRect final {
|
||||
public:
|
||||
RRect() = default;
|
||||
~RRect() = default;
|
||||
|
||||
explicit RRect(const Rect& rect) : rect_(rect) {}
|
||||
RRect(double x, double y, double width, double height)
|
||||
{
|
||||
rect_.SetRect(x, y, width, height);
|
||||
}
|
||||
|
||||
static RRect MakeRect(const Rect& rect)
|
||||
{
|
||||
RRect rrect;
|
||||
rrect.SetRect(rect);
|
||||
return rrect;
|
||||
}
|
||||
|
||||
static RRect MakeRRect(const Rect& rect, const Radius& radius)
|
||||
{
|
||||
RRect rrect;
|
||||
rrect.SetRectWithSimpleRadius(rect, radius.GetX().Value(), radius.GetY().Value());
|
||||
return rrect;
|
||||
}
|
||||
|
||||
static RRect MakeRRect(const Rect& rect, double x, double y)
|
||||
{
|
||||
RRect rrect;
|
||||
rrect.SetRectWithSimpleRadius(rect, x, y);
|
||||
return rrect;
|
||||
}
|
||||
|
||||
static RRect MakeOval(const Rect& rect)
|
||||
{
|
||||
RRect rrect;
|
||||
rrect.SetOval(rect);
|
||||
return rrect;
|
||||
}
|
||||
|
||||
const Rect& GetRect() const
|
||||
{
|
||||
return rect_;
|
||||
}
|
||||
|
||||
const Corner& GetCorner() const
|
||||
{
|
||||
return corner_;
|
||||
}
|
||||
|
||||
void SetRect(const Rect& rect)
|
||||
{
|
||||
rect_ = rect;
|
||||
}
|
||||
|
||||
void SetCorner(const Corner& corner)
|
||||
{
|
||||
corner_ = corner;
|
||||
}
|
||||
|
||||
void SetRectWithSimpleRadius(const Rect& rect, double xRadius, double yRadius)
|
||||
{
|
||||
rect_ = rect;
|
||||
if (xRadius <= 0 || yRadius <= 0) {
|
||||
return;
|
||||
}
|
||||
if (rect_.Width() < (xRadius + xRadius) || rect.Height() < (yRadius + yRadius)) {
|
||||
double scale = std::min(rect.Width() / (xRadius + xRadius), rect.Height() / (yRadius + yRadius));
|
||||
xRadius *= scale;
|
||||
yRadius *= scale;
|
||||
}
|
||||
auto radius = Radius(xRadius, yRadius);
|
||||
corner_ = { radius, radius, radius, radius };
|
||||
}
|
||||
|
||||
void ApplyScaleAndRound(float scale)
|
||||
{
|
||||
rect_.ApplyScaleAndRound(Size(scale, scale));
|
||||
corner_.topLeftRadius.ApplyScaleAndRound(scale);
|
||||
corner_.topRightRadius.ApplyScaleAndRound(scale);
|
||||
corner_.bottomRightRadius.ApplyScaleAndRound(scale);
|
||||
corner_.bottomLeftRadius.ApplyScaleAndRound(scale);
|
||||
}
|
||||
|
||||
void SetOval(const Rect& rect)
|
||||
{
|
||||
rect_ = rect;
|
||||
double xRadius = rect.Width() / 2;
|
||||
double yRadius = rect.Height() / 2;
|
||||
auto radius = Radius(xRadius, yRadius);
|
||||
corner_ = { radius, radius, radius, radius };
|
||||
}
|
||||
|
||||
double Width() const
|
||||
{
|
||||
return rect_.Width();
|
||||
}
|
||||
|
||||
double Height() const
|
||||
{
|
||||
return rect_.Height();
|
||||
}
|
||||
|
||||
bool NearEqual(const RRect& rrect) const
|
||||
{
|
||||
return rrect.GetCorner().bottomLeftRadius == corner_.bottomLeftRadius &&
|
||||
rrect.GetCorner().bottomRightRadius == corner_.bottomRightRadius &&
|
||||
rrect.GetCorner().topLeftRadius == corner_.topLeftRadius &&
|
||||
rrect.GetCorner().topRightRadius == corner_.topRightRadius && rrect.GetRect() == rect_;
|
||||
}
|
||||
|
||||
bool operator==(const RRect& rrect) const
|
||||
{
|
||||
return rrect.GetCorner().bottomLeftRadius == corner_.bottomLeftRadius &&
|
||||
rrect.GetCorner().bottomRightRadius == corner_.bottomRightRadius &&
|
||||
rrect.GetCorner().topLeftRadius == corner_.topLeftRadius &&
|
||||
rrect.GetCorner().topRightRadius == corner_.topRightRadius && rrect.Height() == rect_.Height() &&
|
||||
rrect.Width() == rect_.Width();
|
||||
}
|
||||
|
||||
RRect& operator+=(const Offset& offset)
|
||||
{
|
||||
rect_ += offset;
|
||||
return *this;
|
||||
}
|
||||
|
||||
private:
|
||||
Corner corner_ { { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 }, { 0.0, 0.0 } };
|
||||
Rect rect_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_RRECT_H
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_SIZE_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_SIZE_H
|
||||
|
||||
#include <limits>
|
||||
#include <string>
|
||||
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class Size {
|
||||
public:
|
||||
static constexpr double INFINITE_SIZE = std::numeric_limits<double>::max();
|
||||
Size() = default;
|
||||
~Size() = default;
|
||||
Size(double width, double height) : width_(width), height_(height) {}
|
||||
|
||||
double Width() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
double Height() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
void SetWidth(double width)
|
||||
{
|
||||
width_ = width;
|
||||
}
|
||||
|
||||
void SetHeight(double height)
|
||||
{
|
||||
height_ = height;
|
||||
}
|
||||
|
||||
bool IsWidthInfinite() const
|
||||
{
|
||||
return NearEqual(width_, INFINITE_SIZE);
|
||||
}
|
||||
|
||||
bool IsHeightInfinite() const
|
||||
{
|
||||
return NearEqual(height_, INFINITE_SIZE);
|
||||
}
|
||||
|
||||
bool IsInfinite() const
|
||||
{
|
||||
return NearEqual(width_, INFINITE_SIZE) || NearEqual(height_, INFINITE_SIZE);
|
||||
}
|
||||
|
||||
bool IsEmpty() const
|
||||
{
|
||||
return NearEqual(width_, 0.0) || NearEqual(height_, 0.0);
|
||||
}
|
||||
|
||||
Size& AddHeight(double height)
|
||||
{
|
||||
height_ += height;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Size& AddWidth(double value)
|
||||
{
|
||||
width_ += value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
Size& MinusHeight(double height)
|
||||
{
|
||||
height_ -= height;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool IsValid() const
|
||||
{
|
||||
return width_ > 0.0 && height_ > 0.0;
|
||||
}
|
||||
|
||||
Size operator*(double value) const
|
||||
{
|
||||
return Size(width_ * value, height_ * value);
|
||||
}
|
||||
|
||||
bool operator==(const Size& size) const
|
||||
{
|
||||
return NearEqual(width_, size.width_) && NearEqual(height_, size.height_);
|
||||
}
|
||||
|
||||
bool operator!=(const Size& size) const
|
||||
{
|
||||
return !operator==(size);
|
||||
}
|
||||
|
||||
Size operator+(const Size& size) const
|
||||
{
|
||||
return Size(width_ + size.Width(), height_ + size.Height());
|
||||
}
|
||||
|
||||
Size operator+=(const Size& size)
|
||||
{
|
||||
width_ += size.Width();
|
||||
height_ += size.Height();
|
||||
return *this;
|
||||
}
|
||||
|
||||
Size operator-(const Size& size) const
|
||||
{
|
||||
return Size(width_ - size.Width(), height_ - size.Height());
|
||||
}
|
||||
|
||||
Size operator-=(const Size& size)
|
||||
{
|
||||
width_ -= size.Width();
|
||||
height_ -= size.Height();
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ApplyScale(double scale)
|
||||
{
|
||||
width_ *= scale;
|
||||
height_ *= scale;
|
||||
}
|
||||
|
||||
/*
|
||||
* Please make sure that two sizes are both valid.
|
||||
* You can use IsValid() to see if a size is valid.
|
||||
*/
|
||||
bool operator>(const Size& size) const
|
||||
{
|
||||
if (IsValid() && size.IsValid()) {
|
||||
return GreatOrEqual(width_, size.width_) && GreatOrEqual(height_, size.height_);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Please make sure that two sizes are both valid.
|
||||
* You can use IsValid() to see if a size is valid.
|
||||
*/
|
||||
bool operator<(const Size& size) const
|
||||
{
|
||||
if (IsValid() && size.IsValid()) {
|
||||
return LessOrEqual(width_, size.width_) && LessOrEqual(height_, size.height_);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T>
|
||||
static double CalcRatio(const T& rectangle)
|
||||
{
|
||||
if (NearZero(static_cast<double>(rectangle.Height()))) {
|
||||
return INFINITE_SIZE;
|
||||
}
|
||||
return static_cast<double>(rectangle.Width()) / static_cast<double>(rectangle.Height());
|
||||
}
|
||||
|
||||
std::string ToString() const
|
||||
{
|
||||
return std::string(std::string("["))
|
||||
.append(NearEqual(width_, INFINITE_SIZE) ? std::string("INFINITE") : std::to_string(width_))
|
||||
.append(" x ")
|
||||
.append(NearEqual(height_, INFINITE_SIZE) ? std::string("INFINITE") : std::to_string(height_))
|
||||
.append("]");
|
||||
}
|
||||
|
||||
private:
|
||||
double width_ = 0.0;
|
||||
double height_ = 0.0;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_SIZE_H
|
||||
@@ -0,0 +1,65 @@
|
||||
# Copyright (c) 2021 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("//build/ohos.gni")
|
||||
import("//foundation/ace/ace_engine/ace_config.gni")
|
||||
|
||||
config("ace_base_i18n_config") {
|
||||
defines = [ "ACEL10N" ]
|
||||
|
||||
include_dirs = [ "//utils/native/base/include" ]
|
||||
}
|
||||
|
||||
template("ace_base_i18n") {
|
||||
forward_variables_from(invoker, "*")
|
||||
source_set(target_name) {
|
||||
defines += invoker.defines
|
||||
deps = [
|
||||
"$ace_root/frameworks/base/resource:ace_resource",
|
||||
"$flutter_root:ace_libicu_$platform",
|
||||
]
|
||||
|
||||
configs += [
|
||||
":ace_base_i18n_config",
|
||||
"$ace_root:ace_config",
|
||||
"$flutter_root:icu_config_$platform",
|
||||
]
|
||||
|
||||
# add base source file here
|
||||
sources = [ "localization.cpp" ]
|
||||
|
||||
if (use_mingw_win) {
|
||||
cflags = [
|
||||
"-std=c++17",
|
||||
|
||||
# Notice: this flag actually apply to icu source code.
|
||||
"-Wno-ignored-attributes",
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ace_base_i18n("ace_base_i18n_ohos") {
|
||||
defines = ace_ohos_defines
|
||||
platform = "ohos"
|
||||
}
|
||||
|
||||
ace_base_i18n("ace_base_i18n_windows") {
|
||||
defines = ace_windows_defines
|
||||
platform = "windows"
|
||||
}
|
||||
|
||||
ace_base_i18n("ace_base_i18n_mac") {
|
||||
defines = ace_mac_defines
|
||||
platform = "mac"
|
||||
}
|
||||
@@ -0,0 +1,906 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/i18n/localization.h"
|
||||
|
||||
#include <map>
|
||||
#include <unordered_map>
|
||||
|
||||
#include "chnsecal.h"
|
||||
#include "unicode/calendar.h"
|
||||
#include "unicode/datefmt.h"
|
||||
#include "unicode/dtfmtsym.h"
|
||||
#include "unicode/dtptngen.h"
|
||||
#include "unicode/locid.h"
|
||||
#include "unicode/measfmt.h"
|
||||
#include "unicode/measure.h"
|
||||
#include "unicode/numberformatter.h"
|
||||
#include "unicode/plurrule.h"
|
||||
#include "unicode/reldatefmt.h"
|
||||
#include "unicode/smpdtfmt.h"
|
||||
#include "unicode/uclean.h"
|
||||
#include "unicode/udata.h"
|
||||
|
||||
#include "base/json/json_util.h"
|
||||
#include "base/log/log.h"
|
||||
#include "base/resource/internal_resource.h"
|
||||
#include "base/utils/linear_map.h"
|
||||
#include "base/utils/string_utils.h"
|
||||
#include "base/utils/utils.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
using namespace icu;
|
||||
|
||||
struct LocaleProxy final {
|
||||
LocaleProxy(const char* language, const char* countryOrRegion, const char* variant, const char* keywordsAndValues)
|
||||
: instance(language, countryOrRegion, variant, keywordsAndValues)
|
||||
{}
|
||||
~LocaleProxy() = default;
|
||||
|
||||
Locale instance;
|
||||
};
|
||||
|
||||
namespace {
|
||||
|
||||
#define CHECK_RETURN(status, ret) \
|
||||
do { \
|
||||
if (status > U_ZERO_ERROR) { \
|
||||
LOGE("status = %{public}d", static_cast<int32_t>(status)); \
|
||||
return ret; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define CHECK_NO_RETURN(status) \
|
||||
do { \
|
||||
if (status > U_ZERO_ERROR) { \
|
||||
LOGE("status = %{public}d", static_cast<int32_t>(status)); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
const char JSON_PATH_CARVE = '.';
|
||||
const char DEFAULT_LANGUAGE[] = "en-US";
|
||||
constexpr uint32_t SEXAGENARY_CYCLE_SIZE = 60;
|
||||
constexpr uint32_t GUIHAI_YEAR_RECENT = 3;
|
||||
|
||||
const char CHINESE_LEAP[] = u8"\u95f0";
|
||||
const char CHINESE_FIRST[] = u8"\u521d";
|
||||
const char CHINESE_TEN[] = u8"\u5341";
|
||||
const char CHINESE_TWENTY[] = u8"\u5eff";
|
||||
const char* g_chineseOneToNine[] = {
|
||||
u8"\u4e00", u8"\u4e8c", u8"\u4e09", u8"\u56db", u8"\u4e94", u8"\u516d", u8"\u4e03", u8"\u516b", u8"\u4e5d"
|
||||
};
|
||||
const std::unordered_map<std::string, std::string> LANGUAGE_CODE_MAP {
|
||||
{ "he", "iw" },
|
||||
{ "fil", "tl" },
|
||||
{ "id", "in" },
|
||||
};
|
||||
|
||||
inline void UnicodeString2String(const UnicodeString& source, std::string& result)
|
||||
{
|
||||
source.toUTF8String(result);
|
||||
}
|
||||
|
||||
DateFormat::EStyle DateTimeStyle2EStyle(DateTimeStyle dateTimeStyle)
|
||||
{
|
||||
switch (dateTimeStyle) {
|
||||
case DateTimeStyle::NONE:
|
||||
return DateFormat::EStyle::kNone;
|
||||
case DateTimeStyle::FULL:
|
||||
return DateFormat::EStyle::kFull;
|
||||
case DateTimeStyle::LONG:
|
||||
return DateFormat::EStyle::kLong;
|
||||
case DateTimeStyle::MEDIUM:
|
||||
return DateFormat::EStyle::kMedium;
|
||||
case DateTimeStyle::SHORT:
|
||||
return DateFormat::EStyle::kShort;
|
||||
default:
|
||||
return DateFormat::EStyle::kNone;
|
||||
}
|
||||
}
|
||||
|
||||
UMeasureFormatWidth GetMeasureFormatWidth(MeasureFormatStyle formatStyle)
|
||||
{
|
||||
switch (formatStyle) {
|
||||
case MeasureFormatStyle::WIDTH_WIDE:
|
||||
return UMeasureFormatWidth::UMEASFMT_WIDTH_WIDE;
|
||||
case MeasureFormatStyle::WIDTH_SHORT:
|
||||
return UMeasureFormatWidth::UMEASFMT_WIDTH_SHORT;
|
||||
case MeasureFormatStyle::WIDTH_NARROW:
|
||||
return UMeasureFormatWidth::UMEASFMT_WIDTH_NARROW;
|
||||
case MeasureFormatStyle::WIDTH_NUMERIC:
|
||||
return UMeasureFormatWidth::UMEASFMT_WIDTH_NUMERIC;
|
||||
case MeasureFormatStyle::WIDTH_COUNT:
|
||||
return UMeasureFormatWidth::UMEASFMT_WIDTH_COUNT;
|
||||
default:
|
||||
return UMeasureFormatWidth::UMEASFMT_WIDTH_WIDE;
|
||||
}
|
||||
}
|
||||
|
||||
MeasureUnit* GetMeasureUnit(TimeUnitStyle timeUnitStyle, UErrorCode& status)
|
||||
{
|
||||
switch (timeUnitStyle) {
|
||||
case TimeUnitStyle::YEAR:
|
||||
return MeasureUnit::createYear(status);
|
||||
case TimeUnitStyle::MONTH:
|
||||
return MeasureUnit::createMonth(status);
|
||||
case TimeUnitStyle::DAY:
|
||||
return MeasureUnit::createDay(status);
|
||||
case TimeUnitStyle::HOUR:
|
||||
return MeasureUnit::createHour(status);
|
||||
case TimeUnitStyle::MINUTE:
|
||||
return MeasureUnit::createMinute(status);
|
||||
case TimeUnitStyle::SECOND:
|
||||
return MeasureUnit::createSecond(status);
|
||||
case TimeUnitStyle::MILLISECOND:
|
||||
return MeasureUnit::createMillisecond(status);
|
||||
default:
|
||||
return MeasureUnit::createYear(status);
|
||||
}
|
||||
}
|
||||
|
||||
void GetLocalJsonObject(InternalResource::ResourceId id, std::string language, std::unique_ptr<JsonValue>& indexJson,
|
||||
std::unique_ptr<JsonValue>& json)
|
||||
{
|
||||
if (indexJson == nullptr) {
|
||||
size_t size = 0;
|
||||
const uint8_t* buf = InternalResource::GetInstance().GetResource(id, size);
|
||||
if (buf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::string jsonStr(reinterpret_cast<const char*>(buf), size);
|
||||
const char* endMsg = nullptr;
|
||||
indexJson = JsonUtil::ParseJsonString(jsonStr, &endMsg);
|
||||
if (indexJson == nullptr) {
|
||||
LOGE("read indexletter json failed. reason: %{private}s.", endMsg);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (indexJson->Contains(language) && indexJson->GetValue(language)->IsObject()) {
|
||||
json = indexJson->GetValue(language);
|
||||
} else if (indexJson->Contains(DEFAULT_LANGUAGE) && indexJson->GetValue(DEFAULT_LANGUAGE)->IsObject()) {
|
||||
json = indexJson->GetValue(DEFAULT_LANGUAGE);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
||||
// for entry.json
|
||||
static std::unique_ptr<JsonValue> g_indexJsonEntry = nullptr;
|
||||
static std::unique_ptr<JsonValue> g_indexJsonError = nullptr;
|
||||
|
||||
void Localization::SetLocaleImpl(const std::string& language, const std::string& countryOrRegion,
|
||||
const std::string& script, const std::string& selectLanguage, const std::string& keywordsAndValues)
|
||||
{
|
||||
locale_ = std::make_unique<LocaleProxy>(language.c_str(), countryOrRegion.c_str(), "", keywordsAndValues.c_str());
|
||||
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
std::vector<std::string> keyValuePairs;
|
||||
StringUtils::StringSpliter(keywordsAndValues, ';', keyValuePairs);
|
||||
for (const auto& pair : keyValuePairs) {
|
||||
// [pair] is like "nu=arab" or "nu=" for most occasions, but may be "=" under extreme scenarios
|
||||
std::vector<std::string> res;
|
||||
StringUtils::StringSpliter(pair, '=', res);
|
||||
if (res.size() == 0) {
|
||||
continue;
|
||||
}
|
||||
auto value = (res.size() == 2) ? res[1] : "";
|
||||
locale_->instance.setUnicodeKeywordValue(res[0], value, status);
|
||||
CHECK_NO_RETURN(status);
|
||||
}
|
||||
|
||||
languageTag_ = language;
|
||||
if (!script.empty()) {
|
||||
languageTag_.append("-").append(script);
|
||||
}
|
||||
languageTag_.append("-").append(countryOrRegion);
|
||||
fontLocale_ = languageTag_;
|
||||
// Smiple chinese
|
||||
if (languageTag_ == "zh-Hans-CN") {
|
||||
languageTag_ = "zh-CN";
|
||||
fontLocale_ = "";
|
||||
}
|
||||
|
||||
selectLanguage_ = selectLanguage;
|
||||
// match json of latin
|
||||
if (selectLanguage_ == "jv-Latn") {
|
||||
selectLanguage_ = "b+jv+Latn";
|
||||
} else if (selectLanguage_ == "sr-Latn") {
|
||||
selectLanguage_ = "b+sr+Latn";
|
||||
}
|
||||
|
||||
LOGI("SetLocale language tag: %{public}s, select language: %{public}s", languageTag_.c_str(),
|
||||
selectLanguage_.c_str());
|
||||
if (!isPromiseUsed_) {
|
||||
promise_.set_value(true);
|
||||
isPromiseUsed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
std::string Localization::GetLanguage()
|
||||
{
|
||||
WaitingForInit();
|
||||
if (locale_) {
|
||||
return locale_->instance.getLanguage();
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Localization::GetLanguageTag()
|
||||
{
|
||||
WaitingForInit();
|
||||
return languageTag_;
|
||||
}
|
||||
|
||||
std::string Localization::GetFontLocale()
|
||||
{
|
||||
WaitingForInit();
|
||||
return fontLocale_;
|
||||
}
|
||||
|
||||
const std::string Localization::FormatDuration(uint32_t duration, bool needShowHour)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
// duration greater than 1 hour, use hh:mm:ss;
|
||||
if (!needShowHour && duration > 3600) {
|
||||
needShowHour = true;
|
||||
}
|
||||
const char* engTimeFormat = needShowHour ? "hh:mm:ss" : "mm:ss";
|
||||
auto simpleDateFormat = std::make_unique<SimpleDateFormat>(UnicodeString(engTimeFormat), locale_->instance, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
UnicodeString simpleStr;
|
||||
simpleDateFormat->format(1000.0 * duration, simpleStr, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(simpleStr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
const std::string Localization::FormatDateTime(DateTime dateTime, const std::string& format)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
auto cal = Calendar::createInstance(locale_->instance, status);
|
||||
CHECK_RETURN(status, "");
|
||||
cal->set(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute, dateTime.second);
|
||||
|
||||
UDate date = cal->getTime(status);
|
||||
delete cal;
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
auto patternGenerator = DateTimePatternGenerator::createInstance(locale_->instance, status);
|
||||
CHECK_RETURN(status, "");
|
||||
UnicodeString pattern = patternGenerator->getBestPattern(UnicodeString(format.c_str()), status);
|
||||
delete patternGenerator;
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
auto dateFormat = std::make_unique<SimpleDateFormat>(pattern, locale_->instance, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
UnicodeString dateTimeStr;
|
||||
dateFormat->format(date, dateTimeStr, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(dateTimeStr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool Localization::GetDateColumnFormatOrder(std::vector<std::string>& outOrder)
|
||||
{
|
||||
outOrder.clear();
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
auto patternGenerator = DateTimePatternGenerator::createInstance(locale_->instance, status);
|
||||
CHECK_RETURN(status, false);
|
||||
std::string format = "yyyyMMdd";
|
||||
UnicodeString pattern = patternGenerator->getBestPattern(UnicodeString(format.c_str()), status);
|
||||
delete patternGenerator;
|
||||
CHECK_RETURN(status, false);
|
||||
|
||||
std::string result;
|
||||
UnicodeString2String(pattern, result);
|
||||
LOGD("order of date format is %{public}s", result.c_str());
|
||||
|
||||
std::map<std::size_t, std::string> order;
|
||||
std::size_t position = result.find("yyyy");
|
||||
if (position == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
order[position] = "year";
|
||||
|
||||
position = result.find("MM");
|
||||
if (position == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
order[position] = "month";
|
||||
|
||||
position = result.find("dd");
|
||||
if (position == std::string::npos) {
|
||||
return false;
|
||||
}
|
||||
order[position] = "day";
|
||||
|
||||
for (auto it = order.begin(); it != order.end(); ++it) {
|
||||
outOrder.emplace_back(it->second);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Localization::Contain(const std::string& str, const std::string& tag)
|
||||
{
|
||||
auto pos = str.find(tag);
|
||||
return (pos != std::string::npos);
|
||||
}
|
||||
|
||||
bool Localization::GetHourFormat(bool& isAmPm, bool& hasZero)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
auto patternGenerator = DateTimePatternGenerator::createInstance(locale_->instance, status);
|
||||
CHECK_RETURN(status, false);
|
||||
std::string format = "J:mm";
|
||||
UnicodeString pattern = patternGenerator->getBestPattern(UnicodeString(format.c_str()), status);
|
||||
delete patternGenerator;
|
||||
CHECK_RETURN(status, false);
|
||||
|
||||
std::string result;
|
||||
UnicodeString2String(pattern, result);
|
||||
LOGI("hour format is %{public}s", result.c_str());
|
||||
|
||||
if (Contain(result, "hh") || Contain(result, "KK")) {
|
||||
isAmPm = true;
|
||||
hasZero = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Contain(result, "h") || Contain(result, "K")) {
|
||||
isAmPm = true;
|
||||
hasZero = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Contain(result, "HH") || Contain(result, "kk")) {
|
||||
isAmPm = false;
|
||||
hasZero = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Contain(result, "H") || Contain(result, "k")) {
|
||||
isAmPm = false;
|
||||
hasZero = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
LOGE("hour format is unknow[%{public}s]", result.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
const std::string Localization::FormatDateTime(DateTime dateTime, DateTimeStyle dateStyle, DateTimeStyle timeStyle)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
auto cal = Calendar::createInstance(locale_->instance, status);
|
||||
CHECK_RETURN(status, "");
|
||||
cal->set(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute, dateTime.second);
|
||||
|
||||
UDate date = cal->getTime(status);
|
||||
delete cal;
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
auto dateFormat = DateFormat::createDateTimeInstance(
|
||||
DateTimeStyle2EStyle(dateStyle), DateTimeStyle2EStyle(timeStyle), locale_->instance);
|
||||
if (dateFormat == nullptr) {
|
||||
return "";
|
||||
}
|
||||
|
||||
UnicodeString dateTimeStr;
|
||||
dateFormat->format(date, dateTimeStr, status);
|
||||
delete dateFormat;
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(dateTimeStr, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::string> Localization::GetMonths(bool isShortType, const std::string& calendarType)
|
||||
{
|
||||
WaitingForInit();
|
||||
std::vector<std::string> months;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DateFormatSymbols dateformat(locale_->instance, calendarType.c_str(), status);
|
||||
CHECK_RETURN(status, months);
|
||||
|
||||
int32_t count = 0;
|
||||
|
||||
auto monthsUniStr = dateformat.getMonths(count, DateFormatSymbols::DtContextType::STANDALONE,
|
||||
isShortType ? DateFormatSymbols::DtWidthType::SHORT : DateFormatSymbols::DtWidthType::WIDE);
|
||||
if (count > 0) {
|
||||
std::string month;
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
month.clear();
|
||||
UnicodeString2String(monthsUniStr[i], month);
|
||||
months.push_back(month);
|
||||
}
|
||||
}
|
||||
return months;
|
||||
}
|
||||
|
||||
std::vector<std::string> Localization::GetWeekdays(bool isShortType)
|
||||
{
|
||||
WaitingForInit();
|
||||
std::vector<std::string> weekdays;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DateFormatSymbols dateformat(locale_->instance, status);
|
||||
CHECK_RETURN(status, weekdays);
|
||||
|
||||
int32_t count = 0;
|
||||
|
||||
auto language = locale_->instance.getLanguage();
|
||||
auto widthType = isShortType ? (strcmp(language, "zh") == 0 || strcmp(language, "bo") == 0)
|
||||
? DateFormatSymbols::DtWidthType::NARROW
|
||||
: DateFormatSymbols::DtWidthType::ABBREVIATED
|
||||
: DateFormatSymbols::DtWidthType::WIDE;
|
||||
auto weekdaysUniStr = dateformat.getWeekdays(count, DateFormatSymbols::DtContextType::STANDALONE, widthType);
|
||||
if (count > 0) {
|
||||
std::string weekday;
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
weekday.clear();
|
||||
UnicodeString2String(weekdaysUniStr[i], weekday);
|
||||
if (!weekday.empty()) {
|
||||
weekdays.push_back(weekday);
|
||||
}
|
||||
}
|
||||
}
|
||||
return weekdays;
|
||||
}
|
||||
|
||||
std::vector<std::string> Localization::GetAmPmStrings()
|
||||
{
|
||||
WaitingForInit();
|
||||
std::vector<std::string> amPms;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
DateFormatSymbols dateformat(locale_->instance, status);
|
||||
CHECK_RETURN(status, amPms);
|
||||
|
||||
int32_t count = 0;
|
||||
|
||||
auto amPmUniStr = dateformat.getAmPmStrings(count);
|
||||
if (count > 0) {
|
||||
std::string amPm;
|
||||
for (int32_t i = 0; i < count; i++) {
|
||||
amPm.clear();
|
||||
UnicodeString2String(amPmUniStr[i], amPm);
|
||||
amPms.push_back(amPm);
|
||||
}
|
||||
}
|
||||
return amPms;
|
||||
}
|
||||
|
||||
std::string Localization::GetRelativeDateTime(double offset)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
RelativeDateTimeFormatter relativeDateformat(locale_->instance, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
UnicodeString relativeDate;
|
||||
relativeDateformat.format(offset, URelativeDateTimeUnit::UDAT_REL_UNIT_DAY, relativeDate, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(relativeDate, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
LunarDate Localization::GetLunarDate(Date date)
|
||||
{
|
||||
WaitingForInit();
|
||||
LunarDate dateRet;
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
Locale locale("zh", "CN");
|
||||
auto cal = Calendar::createInstance(locale, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
// 0 means January, 1 means February, so month - 1
|
||||
cal->set(date.year, date.month - 1, date.day);
|
||||
|
||||
UDate udate = cal->getTime(status);
|
||||
delete cal;
|
||||
CHECK_RETURN(status, dateRet);
|
||||
|
||||
ChineseCalendar chineseCalendar(locale, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
|
||||
chineseCalendar.setTime(udate, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
|
||||
int32_t lunarYear = chineseCalendar.get(UCalendarDateFields::UCAL_YEAR, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
int32_t lunarMonth = chineseCalendar.get(UCalendarDateFields::UCAL_MONTH, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
int32_t lunarDate = chineseCalendar.get(UCalendarDateFields::UCAL_DATE, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
int32_t isLeapMonth = chineseCalendar.get(UCalendarDateFields::UCAL_IS_LEAP_MONTH, status);
|
||||
CHECK_RETURN(status, dateRet);
|
||||
|
||||
// Sexagenary cycle years convert to Western years
|
||||
dateRet.year = lunarYear + GUIHAI_YEAR_RECENT;
|
||||
dateRet.year += ((date.year - GUIHAI_YEAR_RECENT) / SEXAGENARY_CYCLE_SIZE) * SEXAGENARY_CYCLE_SIZE;
|
||||
// 0 means January, 1 means February, so month + 1
|
||||
dateRet.month = lunarMonth + 1;
|
||||
dateRet.day = lunarDate;
|
||||
dateRet.isLeapMonth = isLeapMonth == 0 ? false : true;
|
||||
return dateRet;
|
||||
}
|
||||
|
||||
std::string Localization::GetLunarMonth(uint32_t month, bool isLeapMonth)
|
||||
{
|
||||
WaitingForInit();
|
||||
std::vector<std::string> months = Localization::GetInstance()->GetMonths(false, "chinese");
|
||||
if (month <= months.size() && month > 0) {
|
||||
std::string leap;
|
||||
if (isLeapMonth) {
|
||||
leap += std::string(CHINESE_LEAP);
|
||||
}
|
||||
return leap + months[month - 1];
|
||||
} else {
|
||||
LOGE("month parameter is illegal:%{public}d", month);
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
std::string Localization::GetLunarDay(uint32_t dayOfMonth)
|
||||
{
|
||||
WaitingForInit();
|
||||
if (dayOfMonth > 30 || dayOfMonth == 0) {
|
||||
LOGE("dayOfMonth parameter is illegal");
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string ret;
|
||||
if (dayOfMonth < 10) {
|
||||
ret = std::string(CHINESE_FIRST) + std::string(g_chineseOneToNine[dayOfMonth - 1]);
|
||||
} else if (dayOfMonth == 10) {
|
||||
ret = std::string(CHINESE_FIRST) + std::string(CHINESE_TEN);
|
||||
} else if (dayOfMonth < 20) {
|
||||
ret = std::string(CHINESE_TEN) + std::string(g_chineseOneToNine[dayOfMonth - 11]);
|
||||
} else if (dayOfMonth == 20) {
|
||||
ret = std::string(CHINESE_TWENTY) + std::string(CHINESE_TEN);
|
||||
} else if (dayOfMonth == 30) {
|
||||
ret = g_chineseOneToNine[2] + std::string(CHINESE_TEN);
|
||||
} else {
|
||||
ret = std::string(CHINESE_TWENTY) + std::string(g_chineseOneToNine[dayOfMonth - 21]);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Localization::TimeUnitFormat(double timeValue, TimeUnitStyle timeStyle, MeasureFormatStyle formatStyle)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
MeasureFormat measureFormat(locale_->instance, GetMeasureFormatWidth(formatStyle), status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
MeasureUnit* minuteUnit = GetMeasureUnit(timeStyle, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
Formattable formattable(timeValue);
|
||||
Measure measure(formattable, minuteUnit, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
UnicodeString timeUnit;
|
||||
FieldPosition fieldPosition;
|
||||
measureFormat.formatMeasures(&measure, 1, timeUnit, fieldPosition, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(timeUnit, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Localization::PluralRulesFormat(double number, bool isCardinal)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
UPluralType pluralType = isCardinal ? UPluralType::UPLURAL_TYPE_CARDINAL : UPluralType::UPLURAL_TYPE_ORDINAL;
|
||||
PluralRules* pluralRules = PluralRules::forLocale(locale_->instance, pluralType, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
UnicodeString numberFormat = pluralRules->select(number);
|
||||
delete pluralRules;
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(numberFormat, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::string Localization::NumberFormat(double number)
|
||||
{
|
||||
WaitingForInit();
|
||||
UErrorCode status = U_ZERO_ERROR;
|
||||
|
||||
icu::number::LocalizedNumberFormatter formatter = icu::number::NumberFormatter::withLocale(locale_->instance);
|
||||
icu::number::FormattedNumber formattedNumber = formatter.formatDouble(number, status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
UnicodeString numberFormat = formattedNumber.toString(status);
|
||||
CHECK_RETURN(status, "");
|
||||
|
||||
std::string ret;
|
||||
UnicodeString2String(numberFormat, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
std::vector<std::u16string> Localization::GetLetters(bool alphabet)
|
||||
{
|
||||
WaitingForInit();
|
||||
std::vector<std::u16string> letters;
|
||||
size_t size = 0;
|
||||
const uint8_t* buf =
|
||||
InternalResource::GetInstance().GetResource(InternalResource::ResourceId::INDEXLETTER_BAR_JSON, size);
|
||||
if (buf == nullptr) {
|
||||
return letters;
|
||||
}
|
||||
|
||||
std::string jsonStr(reinterpret_cast<const char*>(buf), size);
|
||||
const char* endMsg = nullptr;
|
||||
auto indexLetterJson = JsonUtil::ParseJsonString(jsonStr, &endMsg);
|
||||
if (indexLetterJson == nullptr) {
|
||||
LOGE("read indexletter json failed. reason: %{private}s.", endMsg);
|
||||
return letters;
|
||||
}
|
||||
|
||||
std::string language = locale_->instance.getLanguage();
|
||||
if (language == "zh") {
|
||||
language = language + "-" + std::string(locale_->instance.getCountry());
|
||||
}
|
||||
auto iter = LANGUAGE_CODE_MAP.find(language);
|
||||
if (iter != LANGUAGE_CODE_MAP.end()) {
|
||||
language = iter->second;
|
||||
}
|
||||
LOGI("[alphabet] Localization::GetLetters. language: %{private}s", language.c_str());
|
||||
std::unique_ptr<JsonValue> lettersSet;
|
||||
if (!indexLetterJson->Contains(language) || !indexLetterJson->GetValue(language)->IsObject()) {
|
||||
lettersSet = indexLetterJson->GetValue("default");
|
||||
} else {
|
||||
lettersSet = indexLetterJson->GetValue(language);
|
||||
}
|
||||
|
||||
std::string letterType = alphabet ? "alphabet" : "index";
|
||||
std::unique_ptr<JsonValue> lettersArray;
|
||||
if (!lettersSet->Contains(letterType) || !lettersSet->GetValue(letterType)->IsArray()) {
|
||||
LOGE("read letter array failed. Invalid type. %s", letterType.c_str());
|
||||
return letters;
|
||||
} else {
|
||||
lettersArray = lettersSet->GetValue(letterType)->GetChild();
|
||||
}
|
||||
|
||||
while (lettersArray->IsValid()) {
|
||||
letters.push_back(StringUtils::Str8ToStr16(lettersArray->GetString()));
|
||||
lettersArray = lettersArray->GetNext();
|
||||
}
|
||||
return letters;
|
||||
}
|
||||
|
||||
std::vector<std::u16string> Localization::GetIndexLetter()
|
||||
{
|
||||
return GetLetters(false);
|
||||
}
|
||||
|
||||
std::vector<std::u16string> Localization::GetIndexAlphabet()
|
||||
{
|
||||
return GetLetters(true);
|
||||
}
|
||||
|
||||
std::string Localization::GetEntryLetters(const std::string& lettersIndex)
|
||||
{
|
||||
WaitingForInit();
|
||||
if (lettersIndex.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> localJsonEntry;
|
||||
auto language = selectLanguage_;
|
||||
auto iter = LANGUAGE_CODE_MAP.find(language);
|
||||
if (iter != LANGUAGE_CODE_MAP.end()) {
|
||||
language = iter->second;
|
||||
}
|
||||
GetLocalJsonObject(InternalResource::ResourceId::ENTRY_JSON, language, g_indexJsonEntry, localJsonEntry);
|
||||
if (localJsonEntry == nullptr) {
|
||||
LOGE("read JsonObject fail. language: %{public}s.", selectLanguage_.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<std::string> jsonLetterIndex;
|
||||
StringUtils::StringSpliter(lettersIndex, JSON_PATH_CARVE, jsonLetterIndex);
|
||||
|
||||
for (const auto& letter : jsonLetterIndex) {
|
||||
if (localJsonEntry && localJsonEntry->Contains(letter)) {
|
||||
localJsonEntry = localJsonEntry->GetValue(letter);
|
||||
} else {
|
||||
LOGE("read entry json failed.");
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
if (localJsonEntry->IsString()) {
|
||||
return localJsonEntry->GetString();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::string Localization::GetErrorDescription(const std::string& errorIndex)
|
||||
{
|
||||
WaitingForInit();
|
||||
if (errorIndex.empty()) {
|
||||
return "";
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> localJsonError;
|
||||
auto language = selectLanguage_;
|
||||
auto iter = LANGUAGE_CODE_MAP.find(language);
|
||||
if (iter != LANGUAGE_CODE_MAP.end()) {
|
||||
language = iter->second;
|
||||
}
|
||||
GetLocalJsonObject(InternalResource::ResourceId::ERRORINFO_JSON, language, g_indexJsonError, localJsonError);
|
||||
if (localJsonError == nullptr) {
|
||||
LOGE("read JsonObject fail. language: %{public}s.", selectLanguage_.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
if (localJsonError && localJsonError->Contains(errorIndex)) {
|
||||
localJsonError = localJsonError->GetValue(errorIndex);
|
||||
} else {
|
||||
LOGE("read error json failed. error path: %{private}s.", errorIndex.c_str());
|
||||
return "";
|
||||
}
|
||||
|
||||
if (localJsonError->IsString()) {
|
||||
return localJsonError->GetString();
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
const std::vector<std::string>& Localization::GetLanguageList(const std::string& language)
|
||||
{
|
||||
static const LinearMapNode<std::vector<std::string>> mulitiLanguageMap[] = {
|
||||
{ "am", { "am" } },
|
||||
{ "ar", { "ar" } },
|
||||
{ "as", { "as" } },
|
||||
{ "az", { "az-AZ" } },
|
||||
{ "be", { "be" } },
|
||||
{ "bg", { "bg" } },
|
||||
{ "bn", { "bn" } },
|
||||
{ "bo", { "bo-CN" } },
|
||||
{ "bs", { "bs" } },
|
||||
{ "ca", { "ca" } },
|
||||
{ "cs", { "cs" } },
|
||||
{ "da", { "da" } },
|
||||
{ "de", { "de" } },
|
||||
{ "el", { "el" } },
|
||||
{ "en", { "en-US", "en-GB" } },
|
||||
{ "es", { "es,es-US" } },
|
||||
{ "et", { "et" } },
|
||||
{ "fa", { "fa" } },
|
||||
{ "fi", { "fi" } },
|
||||
{ "fil", { "fil" } },
|
||||
{ "fr", { "fr" } },
|
||||
{ "gl", { "gl-ES" } },
|
||||
{ "he", { "he" } },
|
||||
{ "hi", { "hi" } },
|
||||
{ "hr", { "hr" } },
|
||||
{ "hu", { "hu" } },
|
||||
{ "id", { "id" } },
|
||||
{ "in", { "in" } },
|
||||
{ "it", { "it" } },
|
||||
{ "iw", { "iw" } },
|
||||
{ "ja", { "ja" } },
|
||||
{ "jv", { "jv-Latn" } },
|
||||
{ "ka", { "ka-GE" } },
|
||||
{ "kk", { "kk-KZ" } },
|
||||
{ "km", { "km-KH" } },
|
||||
{ "kn", { "kn" } },
|
||||
{ "ko", { "ko" } },
|
||||
{ "lo", { "lo-LA" } },
|
||||
{ "lt", { "lt" } },
|
||||
{ "lv", { "lv" } },
|
||||
{ "mai", { "mai" } },
|
||||
{ "mi", { "mi" } },
|
||||
{ "mk", { "mk" } },
|
||||
{ "ml", { "ml" } },
|
||||
{ "mn", { "mn" } },
|
||||
{ "mr", { "mr" } },
|
||||
{ "ms", { "ms" } },
|
||||
{ "my", { "my-ZG", "my-MM" } },
|
||||
{ "nb", { "nb" } },
|
||||
{ "ne", { "ne" } },
|
||||
{ "nl", { "nl" } },
|
||||
{ "or", { "or" } },
|
||||
{ "pa", { "pa" } },
|
||||
{ "pl", { "pl" } },
|
||||
{ "pt", { "pt", "pt-PT" } },
|
||||
{ "ro", { "ro" } },
|
||||
{ "ru", { "ru" } },
|
||||
{ "si", { "si-LK" } },
|
||||
{ "sk", { "sk" } },
|
||||
{ "sl", { "sl" } },
|
||||
{ "sr", { "sr-Latn" } },
|
||||
{ "sv", { "sv" } },
|
||||
{ "sw", { "sw" } },
|
||||
{ "ta", { "ta" } },
|
||||
{ "te", { "te" } },
|
||||
{ "th", { "th" } },
|
||||
{ "tl", { "tl" } },
|
||||
{ "tr", { "tr" } },
|
||||
{ "ug", { "ug" } },
|
||||
{ "uk", { "uk" } },
|
||||
{ "ur", { "ur" } },
|
||||
{ "uz", { "uz-UZ" } },
|
||||
{ "vi", { "vi" } },
|
||||
{ "zh", { "zh-CN", "zh-HK", "zh-TW" } },
|
||||
{ "zz", { "zz-ZX" } },
|
||||
};
|
||||
int64_t list = BinarySearchFindIndex(mulitiLanguageMap, ArraySize(mulitiLanguageMap), language.c_str());
|
||||
if (list == -1) {
|
||||
static const std::vector<std::string> defaultLanguage = { "en-US" };
|
||||
return defaultLanguage;
|
||||
}
|
||||
return mulitiLanguageMap[list].value;
|
||||
}
|
||||
|
||||
std::mutex Localization::mutex_;
|
||||
std::shared_ptr<Localization> Localization::instance_;
|
||||
bool Localization::firstInstance_ = true;
|
||||
|
||||
std::shared_ptr<Localization> Localization::GetInstance()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!instance_) {
|
||||
instance_ = std::make_shared<Localization>();
|
||||
}
|
||||
return instance_;
|
||||
}
|
||||
|
||||
void Localization::SetLocale(const std::string& language, const std::string& countryOrRegion, const std::string& script,
|
||||
const std::string& selectLanguage, const std::string& keywordsAndValues)
|
||||
{
|
||||
if (instance_) {
|
||||
instance_->HandleOnChange();
|
||||
}
|
||||
std::shared_ptr<Localization> instance;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
if (!firstInstance_ || !instance_) {
|
||||
instance_ = std::make_shared<Localization>();
|
||||
}
|
||||
firstInstance_ = false;
|
||||
instance = instance_;
|
||||
}
|
||||
instance->SetLocaleImpl(language, countryOrRegion, script, selectLanguage, keywordsAndValues);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,252 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_I18N_LOCALIZATION_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_I18N_LOCALIZATION_H
|
||||
|
||||
#include <future>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "base/utils/date_util.h"
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/noncopyable.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
struct LocaleProxy;
|
||||
|
||||
struct LunarDate : Date {
|
||||
bool isLeapMonth = false;
|
||||
};
|
||||
|
||||
struct DateTime final : Date {
|
||||
uint32_t hour = 0;
|
||||
uint32_t minute = 0;
|
||||
uint32_t second = 0;
|
||||
};
|
||||
|
||||
enum DateTimeStyle { NONE, FULL, LONG, MEDIUM, SHORT };
|
||||
|
||||
enum MeasureFormatStyle { WIDTH_WIDE, WIDTH_SHORT, WIDTH_NARROW, WIDTH_NUMERIC, WIDTH_COUNT };
|
||||
|
||||
enum TimeUnitStyle { YEAR, MONTH, DAY, HOUR, MINUTE, SECOND, MILLISECOND };
|
||||
|
||||
const std::string FormatEntry(const char* fmt, ...);
|
||||
|
||||
class ACE_EXPORT Localization : public NonCopyable {
|
||||
public:
|
||||
/**
|
||||
* Get language list to select the best language.
|
||||
* @return language list which is supported
|
||||
*/
|
||||
static const std::vector<std::string>& GetLanguageList(const std::string& language);
|
||||
|
||||
static std::shared_ptr<Localization> GetInstance();
|
||||
|
||||
static void SetLocale(const std::string& language, const std::string& countryOrRegion, const std::string& script,
|
||||
const std::string& selectLanguage, const std::string& keywordsAndValues);
|
||||
|
||||
void SetOnChange(const std::function<void()>& value) {
|
||||
onChange_ = value;
|
||||
}
|
||||
|
||||
void HandleOnChange()
|
||||
{
|
||||
if (onChange_) {
|
||||
onChange_();
|
||||
}
|
||||
}
|
||||
|
||||
bool GetDateColumnFormatOrder(std::vector<std::string>& outOrder);
|
||||
|
||||
bool IsAmPmHour()
|
||||
{
|
||||
bool isAmPm = false;
|
||||
bool hasZero = true;
|
||||
GetHourFormat(isAmPm, hasZero);
|
||||
return isAmPm;
|
||||
}
|
||||
|
||||
bool HasZeroHour()
|
||||
{
|
||||
bool isAmPm = false;
|
||||
bool hasZero = true;
|
||||
GetHourFormat(isAmPm, hasZero);
|
||||
return hasZero;
|
||||
}
|
||||
|
||||
std::string GetLanguage();
|
||||
std::string GetLanguageTag();
|
||||
std::string GetFontLocale();
|
||||
|
||||
/**
|
||||
* For formatting local format duration. Cannot be formatted correctly when duration greater than 24
|
||||
* hours. For example: 10:00.
|
||||
* @param duration The value used to set the duration, the range is 0 to 90,000.
|
||||
* @return local format duration.
|
||||
*/
|
||||
const std::string FormatDuration(uint32_t duration, bool needShowHour = false);
|
||||
|
||||
/**
|
||||
* For formatting date time. For example: 2020/03/30 08:00:00.
|
||||
* @param dateTime The value of date time.
|
||||
* @param format the pattern for the format.
|
||||
* @return local format date time.
|
||||
*/
|
||||
const std::string FormatDateTime(DateTime dateTime, const std::string& format);
|
||||
|
||||
/**
|
||||
* For formatting date time.
|
||||
* @param dateTime The value of date time.
|
||||
* @param dateStyle The value of date style.
|
||||
* @param timeStyle The value of time style.
|
||||
* @return local format date time.
|
||||
*/
|
||||
const std::string FormatDateTime(DateTime dateTime, DateTimeStyle dateStyle, DateTimeStyle timeStyle);
|
||||
|
||||
/**
|
||||
* Gets month strings. For example: "January", "February", etc.
|
||||
* @param isShortType The month style.
|
||||
* @param calendarType The calendar style.
|
||||
* @return the month string vector.
|
||||
*/
|
||||
std::vector<std::string> GetMonths(bool isShortType = false, const std::string& calendarType = "");
|
||||
|
||||
/**
|
||||
* Gets weekdays strings. For example: "Monday", "Tuesday", etc.
|
||||
* @param isShortType The weekday style.
|
||||
* @return the weekday string vector.
|
||||
*/
|
||||
std::vector<std::string> GetWeekdays(bool isShortType = false);
|
||||
|
||||
/**
|
||||
* Gets AM/PM strings. For example: "AM", "PM".
|
||||
* @return the AM/PM string vector.
|
||||
*/
|
||||
std::vector<std::string> GetAmPmStrings();
|
||||
|
||||
/**
|
||||
* Gets relative date. For example: "yesterday", "today", "tomorrow", "in 2 days", etc.
|
||||
* @param offset The relative date time offset.
|
||||
* @return the relative date string.
|
||||
*/
|
||||
std::string GetRelativeDateTime(double offset);
|
||||
|
||||
/**
|
||||
* Gets lunar date.
|
||||
* @param date the western calendar date.
|
||||
* @return the lunar calendar date.
|
||||
*/
|
||||
LunarDate GetLunarDate(Date date);
|
||||
|
||||
/**
|
||||
* Gets lunar month.
|
||||
* @param month the western calendar month.
|
||||
* @param isLeapMonth is a leap month.
|
||||
* @return the lunar calendar month.
|
||||
*/
|
||||
std::string GetLunarMonth(uint32_t month, bool isLeapMonth);
|
||||
|
||||
/**
|
||||
* Gets lunar day.
|
||||
* @param dayOfMonth the western calendar day.
|
||||
* @return the lunar calendar day.
|
||||
*/
|
||||
std::string GetLunarDay(uint32_t dayOfMonth);
|
||||
|
||||
/**
|
||||
* For formatting time unit. For example: "8hours", "8min", etc .
|
||||
* @param timeValue the format time value.
|
||||
* @param timeStyle the time unit style.
|
||||
* @param formatStyle the measure format style.
|
||||
* @return local format time unit.
|
||||
*/
|
||||
std::string TimeUnitFormat(double timeValue, TimeUnitStyle timeStyle, MeasureFormatStyle formatStyle);
|
||||
|
||||
/**
|
||||
* For formatting plural rules.
|
||||
* @param number the number to be formatted.
|
||||
* @param isCardinal the plural is cardinal type.
|
||||
* @return local keyword of the plural rule.
|
||||
*/
|
||||
std::string PluralRulesFormat(double number, bool isCardinal = true);
|
||||
|
||||
/**
|
||||
* Gets Letter strings for indexer. For example: "A", "B", etc.
|
||||
* @return the letter string vector.
|
||||
*/
|
||||
std::vector<std::u16string> GetIndexLetter();
|
||||
|
||||
/**
|
||||
* For formatting number.
|
||||
* @param number the number to be formatted.
|
||||
* @return local format number.
|
||||
*/
|
||||
std::string NumberFormat(double number);
|
||||
|
||||
/**
|
||||
* Gets alphabet strings. For example: "A", "B", etc.
|
||||
* @return the alphabet string vector.
|
||||
*/
|
||||
std::vector<std::u16string> GetIndexAlphabet();
|
||||
|
||||
/**
|
||||
* Gets entry letters, read from resource/binary/entry.json.
|
||||
* @param lettersIndex letters index, like "common.ok"
|
||||
* @return letters
|
||||
*/
|
||||
std::string GetEntryLetters(const std::string& lettersIndex);
|
||||
|
||||
/**
|
||||
* Gets error description, read from resource/binary/errorcode.json.
|
||||
* @param errorIndex error index, like "error_video_000001"
|
||||
* @return error description
|
||||
*/
|
||||
std::string GetErrorDescription(const std::string& errorIndex);
|
||||
|
||||
private:
|
||||
void SetLocaleImpl(const std::string& language, const std::string& countryOrRegion, const std::string& script,
|
||||
const std::string& selectLanguage, const std::string& keywordsAndValues);
|
||||
std::vector<std::u16string> GetLetters(bool alphabet);
|
||||
bool GetHourFormat(bool& isAmPm, bool& hasZero);
|
||||
bool Contain(const std::string& str, const std::string& tag);
|
||||
|
||||
std::unique_ptr<LocaleProxy> locale_;
|
||||
std::string languageTag_;
|
||||
std::string selectLanguage_;
|
||||
std::string fontLocale_;
|
||||
|
||||
std::promise<bool> promise_;
|
||||
std::shared_future<bool> future_ = promise_.get_future();
|
||||
std::function<void()> onChange_;
|
||||
bool isPromiseUsed_ = false;
|
||||
bool isInit_ = false;
|
||||
|
||||
void WaitingForInit()
|
||||
{
|
||||
if (!isInit_) {
|
||||
isInit_ = future_.get();
|
||||
}
|
||||
}
|
||||
|
||||
static std::mutex mutex_;
|
||||
static std::shared_ptr<Localization> instance_;
|
||||
static bool firstInstance_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_I18N_LOCALIZATION_H
|
||||
@@ -0,0 +1,377 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/json/json_util.h"
|
||||
|
||||
#include "cJSON.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
JsonValue::JsonValue(JsonObject* object) : object_(object) {}
|
||||
|
||||
JsonValue::JsonValue(JsonObject* object, bool isRoot) : object_(object), isRoot_(isRoot) {}
|
||||
|
||||
JsonValue::~JsonValue()
|
||||
{
|
||||
if (object_ != nullptr && isRoot_) {
|
||||
cJSON_Delete(object_);
|
||||
}
|
||||
object_ = nullptr;
|
||||
}
|
||||
|
||||
bool JsonValue::IsBool() const
|
||||
{
|
||||
return cJSON_IsBool(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::IsNumber() const
|
||||
{
|
||||
return cJSON_IsNumber(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::IsString() const
|
||||
{
|
||||
return cJSON_IsString(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::IsArray() const
|
||||
{
|
||||
return cJSON_IsArray(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::IsObject() const
|
||||
{
|
||||
return cJSON_IsObject(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::IsValid() const
|
||||
{
|
||||
return (object_ != nullptr) && !cJSON_IsInvalid(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::IsNull() const
|
||||
{
|
||||
return (object_ == nullptr) || cJSON_IsNull(object_);
|
||||
}
|
||||
|
||||
bool JsonValue::Contains(const std::string& key) const
|
||||
{
|
||||
return cJSON_HasObjectItem(object_, key.c_str());
|
||||
}
|
||||
|
||||
bool JsonValue::GetBool() const
|
||||
{
|
||||
return cJSON_IsTrue(object_) != 0;
|
||||
}
|
||||
|
||||
bool JsonValue::GetBool(const std::string& key, bool defaultValue) const
|
||||
{
|
||||
if (Contains(key) && GetValue(key)->IsBool()) {
|
||||
return GetValue(key)->GetBool();
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
int32_t JsonValue::GetInt() const
|
||||
{
|
||||
return static_cast<int32_t>((object_ == nullptr) ? 0 : object_->valuedouble);
|
||||
}
|
||||
|
||||
uint32_t JsonValue::GetUInt() const
|
||||
{
|
||||
return static_cast<uint32_t>((object_ == nullptr) ? 0 : object_->valuedouble);
|
||||
}
|
||||
|
||||
double JsonValue::GetDouble() const
|
||||
{
|
||||
return (object_ == nullptr) ? 0.0 : object_->valuedouble;
|
||||
}
|
||||
|
||||
double JsonValue::GetDouble(const std::string& key, double defaultVal) const
|
||||
{
|
||||
auto value = GetValue(key);
|
||||
if (value && value->IsNumber()) {
|
||||
return value->GetDouble();
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
std::string JsonValue::GetString() const
|
||||
{
|
||||
return ((object_ == nullptr) || (object_->valuestring == nullptr)) ? "" : std::string(object_->valuestring);
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonValue::GetNext() const
|
||||
{
|
||||
if (object_ == nullptr) {
|
||||
return std::make_unique<JsonValue>(nullptr);
|
||||
}
|
||||
return std::make_unique<JsonValue>(object_->next);
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonValue::GetChild() const
|
||||
{
|
||||
if (object_ == nullptr) {
|
||||
return std::make_unique<JsonValue>(nullptr);
|
||||
}
|
||||
return std::make_unique<JsonValue>(object_->child);
|
||||
}
|
||||
|
||||
std::string JsonValue::GetKey() const
|
||||
{
|
||||
return ((object_ == nullptr) || (object_->string == nullptr)) ? "" : std::string(object_->string);
|
||||
}
|
||||
std::unique_ptr<JsonValue> JsonValue::GetValue(const std::string& key) const
|
||||
{
|
||||
return std::make_unique<JsonValue>(cJSON_GetObjectItem(object_, key.c_str()));
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonValue::GetObject(const std::string& key) const
|
||||
{
|
||||
if (Contains(key) && GetValue(key)->IsObject()) {
|
||||
return GetValue(key);
|
||||
}
|
||||
return std::make_unique<JsonValue>();
|
||||
}
|
||||
|
||||
int32_t JsonValue::GetArraySize() const
|
||||
{
|
||||
return cJSON_GetArraySize(object_);
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonValue::GetArrayItem(int32_t index) const
|
||||
{
|
||||
return std::make_unique<JsonValue>(cJSON_GetArrayItem(object_, index));
|
||||
}
|
||||
|
||||
bool JsonValue::Put(const char* key, const char* value)
|
||||
{
|
||||
if (!value || !key) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateString(value);
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
cJSON_AddItemToObject(object_, key, child);
|
||||
return true;
|
||||
}
|
||||
|
||||
const JsonObject* JsonValue::GetJsonObject() const
|
||||
{
|
||||
return object_;
|
||||
}
|
||||
|
||||
bool JsonValue::Put(const char* key, const std::unique_ptr<JsonValue>& value)
|
||||
{
|
||||
if (!value || !key) {
|
||||
return false;
|
||||
}
|
||||
cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
|
||||
if (jsonObject == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(object_, key, jsonObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
// add item to array
|
||||
bool JsonValue::Put(const std::unique_ptr<JsonValue>& value)
|
||||
{
|
||||
if (!value) {
|
||||
return false;
|
||||
}
|
||||
cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
|
||||
if (jsonObject == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON_AddItemToArray(object_, jsonObject);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Put(const char* key, size_t value)
|
||||
{
|
||||
if (key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
cJSON_AddItemToObject(object_, key, child);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Put(const char* key, int32_t value)
|
||||
{
|
||||
if (key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
cJSON_AddItemToObject(object_, key, child);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Put(const char* key, double value)
|
||||
{
|
||||
if (key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateNumber(value);
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
cJSON_AddItemToObject(object_, key, child);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Put(const char* key, bool value)
|
||||
{
|
||||
if (key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateBool(value);
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
cJSON_AddItemToObject(object_, key, child);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Replace(const char* key, const char* value)
|
||||
{
|
||||
if ((value == nullptr) || (key == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateString(value);
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!cJSON_ReplaceItemInObject(object_, key, child)) {
|
||||
cJSON_Delete(child);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Replace(const char* key, int32_t value)
|
||||
{
|
||||
if (key == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON* child = cJSON_CreateNumber(static_cast<double>(value));
|
||||
if (child == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (!cJSON_ReplaceItemInObject(object_, key, child)) {
|
||||
cJSON_Delete(child);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool JsonValue::Replace(const char* key, const std::unique_ptr<JsonValue>& value)
|
||||
{
|
||||
if ((value == nullptr) || (key == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
cJSON* jsonObject = cJSON_Duplicate(value->GetJsonObject(), true);
|
||||
if (jsonObject == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!cJSON_ReplaceItemInObject(object_, key, jsonObject)) {
|
||||
cJSON_Delete(jsonObject);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string JsonValue::ToString()
|
||||
{
|
||||
std::string result;
|
||||
if (!object_) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// It is null-terminated.
|
||||
char* unformatted = cJSON_PrintUnformatted(object_);
|
||||
if (unformatted != nullptr) {
|
||||
result = unformatted;
|
||||
cJSON_free(unformatted);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string JsonValue::GetString(const std::string& key, const std::string& defaultVal) const
|
||||
{
|
||||
auto value = GetValue(key);
|
||||
if (value && value->IsString()) {
|
||||
return value->GetString();
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
int32_t JsonValue::GetInt(const std::string& key, int32_t defaultVal) const
|
||||
{
|
||||
auto value = GetValue(key);
|
||||
if (value && value->IsNumber()) {
|
||||
return value->GetInt();
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
uint32_t JsonValue::GetUInt(const std::string& key, uint32_t defaultVal) const
|
||||
{
|
||||
auto value = GetValue(key);
|
||||
if (value && value->IsNumber()) {
|
||||
return value->GetUInt();
|
||||
}
|
||||
return defaultVal;
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonUtil::ParseJsonData(const char* data, const char** parseEnd)
|
||||
{
|
||||
return std::make_unique<JsonValue>(cJSON_ParseWithOpts(data, parseEnd, true), true);
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonUtil::ParseJsonString(const std::string& content, const char** parseEnd)
|
||||
{
|
||||
return ParseJsonData(content.c_str(), parseEnd);
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonUtil::Create(bool isRoot)
|
||||
{
|
||||
return std::make_unique<JsonValue>(cJSON_CreateObject(), isRoot);
|
||||
}
|
||||
|
||||
std::unique_ptr<JsonValue> JsonUtil::CreateArray(bool isRoot)
|
||||
{
|
||||
return std::make_unique<JsonValue>(cJSON_CreateArray(), isRoot);
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
struct cJSON;
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
using JsonObject = cJSON;
|
||||
|
||||
class ACE_EXPORT JsonValue final {
|
||||
public:
|
||||
JsonValue() = default;
|
||||
explicit JsonValue(JsonObject* object);
|
||||
JsonValue(JsonObject* object, bool isRoot);
|
||||
~JsonValue();
|
||||
|
||||
// check functions
|
||||
bool IsBool() const;
|
||||
bool IsNumber() const;
|
||||
bool IsString() const;
|
||||
bool IsArray() const;
|
||||
bool IsObject() const;
|
||||
bool IsValid() const;
|
||||
bool IsNull() const;
|
||||
bool Contains(const std::string& key) const;
|
||||
|
||||
// get functions
|
||||
bool GetBool() const;
|
||||
bool GetBool(const std::string& key, bool defaultValue) const;
|
||||
int32_t GetInt() const;
|
||||
int32_t GetInt(const std::string& key, int32_t defaultVal = 0) const;
|
||||
uint32_t GetUInt() const;
|
||||
uint32_t GetUInt(const std::string& key, uint32_t defaultVal = 0) const;
|
||||
double GetDouble() const;
|
||||
double GetDouble(const std::string& key, double defaultVal = 0.0) const;
|
||||
std::string GetString() const;
|
||||
std::string GetString(const std::string& key, const std::string& defaultVal = "") const;
|
||||
|
||||
std::unique_ptr<JsonValue> GetNext() const;
|
||||
std::unique_ptr<JsonValue> GetChild() const;
|
||||
std::string GetKey() const;
|
||||
std::unique_ptr<JsonValue> GetValue(const std::string& key) const;
|
||||
std::unique_ptr<JsonValue> GetObject(const std::string& key) const;
|
||||
int32_t GetArraySize() const;
|
||||
std::unique_ptr<JsonValue> GetArrayItem(int32_t index) const;
|
||||
const JsonObject* GetJsonObject() const;
|
||||
|
||||
// put functions
|
||||
bool Put(const char* key, const char* value);
|
||||
bool Put(const char* key, size_t value);
|
||||
bool Put(const char* key, int32_t value);
|
||||
bool Put(const char* key, double value);
|
||||
bool Put(const char* key, bool value);
|
||||
bool Put(const char* key, const std::unique_ptr<JsonValue>& value);
|
||||
bool Put(const std::unique_ptr<JsonValue>& value);
|
||||
|
||||
// replace functions
|
||||
bool Replace(const char* key, const char* value);
|
||||
bool Replace(const char* key, int32_t value);
|
||||
bool Replace(const char* key, const std::unique_ptr<JsonValue>& value);
|
||||
|
||||
// serialize
|
||||
std::string ToString();
|
||||
|
||||
private:
|
||||
JsonObject* object_ = nullptr;
|
||||
bool isRoot_ = false;
|
||||
};
|
||||
|
||||
class ACE_EXPORT JsonUtil final {
|
||||
public:
|
||||
JsonUtil() = delete;
|
||||
~JsonUtil() = delete;
|
||||
static std::unique_ptr<JsonValue> ParseJsonData(const char* data, const char** parseEnd = nullptr);
|
||||
static std::unique_ptr<JsonValue> ParseJsonString(const std::string& content, const char** parseEnd = nullptr);
|
||||
static std::unique_ptr<JsonValue> Create(bool isRoot);
|
||||
static std::unique_ptr<JsonValue> CreateArray(bool isRoot);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_JSON_JSON_UTIL_H
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/ace_trace.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
bool AceTraceBeginWithArgs(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
bool retVal = AceTraceBeginWithArgv(format, args);
|
||||
va_end(args);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
AceScopedTrace::AceScopedTrace(const char* format, ...) : traceEnabled_(AceTraceEnabled())
|
||||
{
|
||||
if (traceEnabled_) {
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
traceEnabled_ = AceTraceBeginWithArgv(format, args);
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
AceScopedTrace::~AceScopedTrace()
|
||||
{
|
||||
if (traceEnabled_) {
|
||||
AceTraceEnd();
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_ACE_TRACE_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_ACE_TRACE_H
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdio>
|
||||
|
||||
#include "base/utils/macros.h"
|
||||
#include "base/utils/noncopyable.h"
|
||||
|
||||
#define ACE_SCOPED_TRACE(fmt, ...) AceScopedTrace aceScopedTrace(fmt, ##__VA_ARGS__)
|
||||
#ifdef ACE_DEBUG
|
||||
#define ACE_DEBUG_SCOPED_TRACE(fmt, ...) AceScopedTrace aceScopedTrace(fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define ACE_DEBUG_SCOPED_TRACE(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define ACE_FUNCTION_TRACE() ACE_SCOPED_TRACE(__func__)
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
bool ACE_EXPORT AceTraceEnabled();
|
||||
void ACE_EXPORT AceTraceBegin(const char* name);
|
||||
bool ACE_EXPORT AceTraceBeginWithArgs(const char* format, ...) __attribute__((__format__(printf, 1, 2)));
|
||||
bool ACE_EXPORT AceTraceBeginWithArgv(const char* format, va_list args);
|
||||
void ACE_EXPORT AceTraceEnd();
|
||||
|
||||
class ACE_EXPORT AceScopedTrace final {
|
||||
public:
|
||||
explicit AceScopedTrace(const char* format, ...) __attribute__((__format__(printf, 2, 3)));
|
||||
~AceScopedTrace();
|
||||
|
||||
ACE_DISALLOW_COPY_AND_MOVE(AceScopedTrace);
|
||||
|
||||
private:
|
||||
bool traceEnabled_ { false };
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_ACE_TRACE_H
|
||||
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/log/dump_log.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
DumpLog::DumpLog() = default;
|
||||
DumpLog::~DumpLog() = default;
|
||||
|
||||
void DumpLog::Print(int32_t depth, const std::string& className, int32_t childSize)
|
||||
{
|
||||
std::string space = " ";
|
||||
for (int32_t i = 0; i < depth; ++i) {
|
||||
fwrite(space.c_str(), 1, space.length(), dumpFile_.get());
|
||||
}
|
||||
fwrite(space.c_str(), 1, space.length(), dumpFile_.get());
|
||||
std::string data = "|-> ";
|
||||
data.append(className);
|
||||
data.append(" childSize:" + std::to_string(childSize));
|
||||
data.append("\n");
|
||||
fwrite(data.c_str(), 1, data.length(), dumpFile_.get());
|
||||
|
||||
for (auto& desc : description_) {
|
||||
for (int32_t i = 0; i < depth; ++i) {
|
||||
fwrite(space.c_str(), 1, space.length(), dumpFile_.get());
|
||||
}
|
||||
std::string data = "";
|
||||
if (childSize == 0) {
|
||||
data = " ";
|
||||
} else {
|
||||
data = " | ";
|
||||
}
|
||||
data.append(desc);
|
||||
fwrite(data.c_str(), 1, data.length(), dumpFile_.get());
|
||||
}
|
||||
description_.clear();
|
||||
description_.shrink_to_fit();
|
||||
}
|
||||
|
||||
void DumpLog::Print(const std::string& content)
|
||||
{
|
||||
Print(0, content);
|
||||
}
|
||||
|
||||
void DumpLog::Print(int32_t depth, const std::string& content)
|
||||
{
|
||||
std::string space = " ";
|
||||
for (int32_t i = 0; i < depth; ++i) {
|
||||
fwrite(space.c_str(), 1, space.length(), dumpFile_.get());
|
||||
}
|
||||
|
||||
std::string data = content + "\n";
|
||||
fwrite(data.c_str(), 1, data.length(), dumpFile_.get());
|
||||
}
|
||||
|
||||
void DumpLog::Reset()
|
||||
{
|
||||
dumpFile_.reset();
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_DUMP_LOG_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_DUMP_LOG_H
|
||||
|
||||
#include <cstdio>
|
||||
#include <memory>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
|
||||
#include "base/utils/noncopyable.h"
|
||||
#include "base/utils/singleton.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class DumpLog : public Singleton<DumpLog> {
|
||||
DECLARE_SINGLETON(DumpLog);
|
||||
|
||||
public:
|
||||
using DumpFile = std::unique_ptr<FILE, decltype(&fclose)>;
|
||||
|
||||
void SetDumpFile(DumpFile&& file)
|
||||
{
|
||||
dumpFile_ = std::move(file);
|
||||
}
|
||||
const DumpFile& GetDumpFile() const
|
||||
{
|
||||
return dumpFile_;
|
||||
}
|
||||
|
||||
void Print(int32_t depth, const std::string& className, int32_t childSize);
|
||||
void Print(const std::string& content);
|
||||
void Print(int32_t depth, const std::string& content);
|
||||
void Reset();
|
||||
|
||||
template<typename T>
|
||||
void AddDesc(const T&& t)
|
||||
{
|
||||
std::stringstream paramStream;
|
||||
paramStream << t << "\n";
|
||||
description_.push_back(paramStream.str());
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void AddDesc(const T& t)
|
||||
{
|
||||
std::stringstream paramStream;
|
||||
paramStream << t << "\n";
|
||||
description_.push_back(paramStream.str());
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
void AddDesc(Args&&... args)
|
||||
{
|
||||
std::stringstream paramStream;
|
||||
BuildDesc(paramStream, args...);
|
||||
}
|
||||
|
||||
template<typename T, typename... Args>
|
||||
void BuildDesc(std::stringstream& stream, T& t, Args&&... args)
|
||||
{
|
||||
stream << t << " ";
|
||||
BuildDesc(stream, args...);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
void BuildDesc(std::stringstream& stream, T& t)
|
||||
{
|
||||
stream << t << "\n";
|
||||
description_.push_back(stream.str());
|
||||
}
|
||||
|
||||
private:
|
||||
DumpFile dumpFile_ { nullptr, &fclose };
|
||||
std::vector<std::string> description_;
|
||||
|
||||
ACE_DISALLOW_MOVE(DumpLog);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_DUMP_LOG_H
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_EVENT_REPORT_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_EVENT_REPORT_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
// eventType use int32_t type, no need enum class.
|
||||
enum {
|
||||
EXCEPTION_FRAMEWORK_APP_START = 951004000,
|
||||
EXCEPTION_FRAMEWORK_PAGE_ROUTER = 951004001,
|
||||
EXCEPTION_COMPONENT = 951004002,
|
||||
EXCEPTION_API_CHANNEL = 951004003,
|
||||
EXCEPTION_RENDER = 951004004,
|
||||
EXCEPTION_JS = 951004005,
|
||||
EXCEPTION_ANIMATION = 951004006,
|
||||
EXCEPTION_EVENT = 951004007,
|
||||
EXCEPTION_INTERNATIONALIZATION = 951004009,
|
||||
EXCEPTION_ACCESSIBILITY = 951004010,
|
||||
EXCEPTION_FORM = 951004011,
|
||||
};
|
||||
|
||||
// EXCEPTION_FRAMEWORK_APP_START
|
||||
enum class AppStartExcepType {
|
||||
CREATE_CONTAINER_ERR = 1,
|
||||
SET_VIEW_ERR,
|
||||
VIEW_TYPE_ERR,
|
||||
GET_PACKAGE_PATH_ERR,
|
||||
JNI_CLASS_ERR,
|
||||
JNI_INIT_ERR = 10,
|
||||
FRONTEND_TYPE_ERR,
|
||||
PIPELINE_CONTEXT_ERR,
|
||||
VIEW_STATE_ERR,
|
||||
RESOURCE_REGISTER_INIT_ERR,
|
||||
JS_ENGINE_CREATE_ERR,
|
||||
JAVA_EVENT_CALLBACK_INIT_ERR,
|
||||
};
|
||||
|
||||
// EXCEPTION_FRAMEWORK_PAGE_ROUTER
|
||||
enum class PageRouterExcepType {
|
||||
ROUTE_PARSE_ERR = 0,
|
||||
PAGE_STACK_OVERFLOW_ERR,
|
||||
RUN_PAGE_ERR,
|
||||
UPDATE_PAGE_ERR,
|
||||
LOAD_PAGE_ERR,
|
||||
REPLACE_PAGE_ERR,
|
||||
};
|
||||
|
||||
// EXCEPTION_COMPONENT
|
||||
enum class ComponentExcepType {
|
||||
TEXT_INPUT_CONNECTION_CLOSE_ERR = 0,
|
||||
GET_THEME_ERR,
|
||||
BUTTON_COMPONENT_ERR,
|
||||
DIALOG_EVENT_ERR,
|
||||
DOM_NODE_NOT_FOUND,
|
||||
SET_ROOT_DOM_NODE_ERR,
|
||||
IMAGE_ANIMATOR_ERR,
|
||||
LIST_COMPONENT_ERR,
|
||||
LIST_ITEM_ERR,
|
||||
MARQUEE_ERR,
|
||||
NAVIGATION_BAR_ERR,
|
||||
};
|
||||
|
||||
// EXCEPTION_API_CHANNEL
|
||||
enum class APIChannelExcepType {
|
||||
JS_BRIDGE_INIT_ERR = 0,
|
||||
SET_FUNCTION_ERR,
|
||||
};
|
||||
|
||||
// EXCEPTION_RENDER
|
||||
enum class RenderExcepType {
|
||||
VIEW_SCALE_ERR = 0,
|
||||
RENDER_ANIMATION_ERR,
|
||||
RENDER_COMPONENT_ERR,
|
||||
CLIP_ERR,
|
||||
UI_THREAD_STUCK,
|
||||
};
|
||||
|
||||
// EXCEPTION_JS
|
||||
enum class JsExcepType {
|
||||
GET_NODE_ERR = 0,
|
||||
CREATE_NODE_ERR,
|
||||
CREATE_DOM_BODY_ERR,
|
||||
REMOVE_DOM_ELEMENT_ERR,
|
||||
UPDATE_DOM_ELEMENT_ERR,
|
||||
JS_ENGINE_INIT_ERR,
|
||||
JS_RUNTIME_OBJ_ERR,
|
||||
JS_CONTEXT_INIT_ERR,
|
||||
JS_THREAD_STUCK,
|
||||
};
|
||||
|
||||
// EXCEPTION_ANIMATION
|
||||
enum class AnimationExcepType {
|
||||
ANIMATION_BRIDGE_ERR = 0,
|
||||
ANIMATION_PAGE_ERR,
|
||||
};
|
||||
|
||||
// EXCEPTION_EVENT
|
||||
enum class EventExcepType {
|
||||
FIRE_EVENT_ERR = 1,
|
||||
};
|
||||
|
||||
// EXCEPTION_INTERNATIONALIZATION
|
||||
enum class InternalExcepType {
|
||||
CHANGE_LOCALE_ERR = 0,
|
||||
};
|
||||
|
||||
// EXCEPTION_ACCESSIBILITY
|
||||
enum class AccessibilityExcepType {
|
||||
CREATE_ACCESSIBILITY_NODE_ERR = 0,
|
||||
GET_NODE_ERR,
|
||||
};
|
||||
|
||||
// EXCEPTION_FORM
|
||||
enum class FormExcepType {
|
||||
RUN_PAGE_ERR = 0,
|
||||
LOAD_PAGE_ERR,
|
||||
CREATE_NODE_ERR,
|
||||
UPDATE_PAGE_ERR,
|
||||
FIRE_FORM_EVENT_ERR,
|
||||
ACTION_EVENT_CALLBACK_ERR,
|
||||
};
|
||||
|
||||
enum class RawEventType { WARNING, FREEZE, RECOVER };
|
||||
|
||||
struct EventInfo {
|
||||
int32_t eventType = 0;
|
||||
int32_t errorType = 0;
|
||||
std::string pageUrl;
|
||||
};
|
||||
|
||||
class ACE_EXPORT EventReport {
|
||||
public:
|
||||
static void SendEvent(const EventInfo& eventInfo);
|
||||
|
||||
static void SendAppStartException(AppStartExcepType type);
|
||||
static void SendPageRouterException(PageRouterExcepType type, const std::string& pageUrl = "");
|
||||
static void SendComponentException(ComponentExcepType type);
|
||||
static void SendAPIChannelException(APIChannelExcepType type);
|
||||
static void SendRenderException(RenderExcepType type);
|
||||
static void SendJsException(JsExcepType type);
|
||||
static void SendAnimationException(AnimationExcepType type);
|
||||
static void SendEventException(EventExcepType type);
|
||||
static void SendInternalException(InternalExcepType type);
|
||||
static void SendAccessibilityException(AccessibilityExcepType type);
|
||||
static void SendFormException(FormExcepType type);
|
||||
|
||||
static void JsEventReport(int32_t eventType, const std::string& jsonStr);
|
||||
static void JsErrReport(
|
||||
int32_t uid, const std::string& packageName, const std::string& reason, const std::string& summary);
|
||||
static void ANRRawReport(RawEventType type, int32_t uid, const std::string& packageName,
|
||||
const std::string& processName, const std::string& msg = " ");
|
||||
|
||||
private:
|
||||
static void SendEventInner(const EventInfo& eventInfo);
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_EVENT_REPORT_H
|
||||
@@ -0,0 +1,21 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_LOG_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_LOG_H
|
||||
|
||||
#include "base/log/log_wrapper.h"
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_LOG_H
|
||||
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_LOG_WRAPPER_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_LOG_WRAPPER_H
|
||||
|
||||
#include <cstdarg>
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
#define PRINT_LOG(level, fmt, ...) \
|
||||
do { \
|
||||
if (OHOS::Ace::LogWrapper::JudgeLevel(OHOS::Ace::LogLevel::level)) { \
|
||||
OHOS::Ace::LogWrapper::PrintLog(OHOS::Ace::LogDomain::FRAMEWORK, OHOS::Ace::LogLevel::level, \
|
||||
"[%{private}-20s(%{private}s)] " fmt, OHOS::Ace::LogWrapper::GetBriefFileName(__FILE__), \
|
||||
__FUNCTION__, ##__VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#ifdef ACE_DEBUG
|
||||
#define LOGD(fmt, ...) PRINT_LOG(DEBUG, fmt, ##__VA_ARGS__)
|
||||
#else
|
||||
#define LOGD(fmt, ...)
|
||||
#endif
|
||||
|
||||
#define LOGI(fmt, ...) PRINT_LOG(INFO, fmt, ##__VA_ARGS__)
|
||||
#define LOGW(fmt, ...) PRINT_LOG(WARN, fmt, ##__VA_ARGS__)
|
||||
#define LOGE(fmt, ...) PRINT_LOG(ERROR, fmt, ##__VA_ARGS__)
|
||||
#define LOGF(fmt, ...) PRINT_LOG(FATAL, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define PRINT_APP_LOG(level, fmt, ...) \
|
||||
OHOS::Ace::LogWrapper::PrintLog(OHOS::Ace::LogDomain::JS_APP, OHOS::Ace::LogLevel::level, fmt, ##__VA_ARGS__)
|
||||
|
||||
#define APP_LOGD(fmt, ...) PRINT_APP_LOG(DEBUG, fmt, ##__VA_ARGS__)
|
||||
#define APP_LOGI(fmt, ...) PRINT_APP_LOG(INFO, fmt, ##__VA_ARGS__)
|
||||
#define APP_LOGW(fmt, ...) PRINT_APP_LOG(WARN, fmt, ##__VA_ARGS__)
|
||||
#define APP_LOGE(fmt, ...) PRINT_APP_LOG(ERROR, fmt, ##__VA_ARGS__)
|
||||
#define APP_LOGF(fmt, ...) PRINT_APP_LOG(FATAL, fmt, ##__VA_ARGS__)
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
enum class LogDomain : uint32_t {
|
||||
FRAMEWORK = 0,
|
||||
JS_APP,
|
||||
};
|
||||
|
||||
enum class LogLevel : uint32_t {
|
||||
DEBUG = 0,
|
||||
INFO,
|
||||
WARN,
|
||||
ERROR,
|
||||
FATAL,
|
||||
};
|
||||
|
||||
class ACE_EXPORT LogWrapper final {
|
||||
public:
|
||||
static bool JudgeLevel(LogLevel level)
|
||||
{
|
||||
return level_ <= level;
|
||||
}
|
||||
|
||||
static void SetLogLevel(LogLevel level)
|
||||
{
|
||||
level_ = level;
|
||||
}
|
||||
|
||||
static LogLevel GetLogLevel()
|
||||
{
|
||||
return level_;
|
||||
}
|
||||
|
||||
static const char* GetBriefFileName(const char* name)
|
||||
{
|
||||
static const char separator = GetSeparatorCharacter();
|
||||
const char* p = strrchr(name, separator);
|
||||
return p != nullptr ? p + 1 : name;
|
||||
}
|
||||
|
||||
static void StripFormatString(const std::string& prefix, std::string& str)
|
||||
{
|
||||
for (auto pos = str.find(prefix, 0); pos != std::string::npos; pos = str.find(prefix, pos)) {
|
||||
str.erase(pos, prefix.size());
|
||||
}
|
||||
}
|
||||
|
||||
static void PrintLog(LogDomain domain, LogLevel level, const char* fmt, ...)
|
||||
__attribute__((__format__(os_log, 3, 4)))
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
PrintLog(domain, level, fmt, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
// MUST implement these interface on each platform.
|
||||
static char GetSeparatorCharacter();
|
||||
static void PrintLog(LogDomain domain, LogLevel level, const char* fmt, va_list args);
|
||||
|
||||
private:
|
||||
LogWrapper() = delete;
|
||||
~LogWrapper() = delete;
|
||||
|
||||
static LogLevel level_;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_LOG_LOG_WRAPPER_H
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_ACE_TYPE_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_ACE_TYPE_H
|
||||
|
||||
#include "base/log/log.h"
|
||||
#include "base/memory/referenced.h"
|
||||
#include "base/memory/type_info_base.h"
|
||||
|
||||
/**
|
||||
* Example:
|
||||
* class BaseA : public virtual AceType {
|
||||
* DECLARE_ACE_TYPE(BaseA, AceType);
|
||||
* };
|
||||
*
|
||||
* class BaseB : public virtual AceType {
|
||||
* DECLARE_ACE_TYPE(BaseB, AceType);
|
||||
* };
|
||||
*
|
||||
* class BaseC : public BaseA, public BaseB {
|
||||
* DECLARE_ACE_TYPE(BaseC, BaseA, BaseB);
|
||||
* };
|
||||
*/
|
||||
// Integrate it into class declaration to support 'DynamicCast'.
|
||||
#define DECLARE_ACE_TYPE(...) DECLARE_RELATIONSHIP_OF_CLASSES(__VA_ARGS__)
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
// Inherit 'AceType' to manager pointers using 'RefPtr', 'WeakPtr' and 'AceType::DynamicCast'.
|
||||
class AceType : public virtual TypeInfoBase, public virtual Referenced {
|
||||
DECLARE_ACE_TYPE(AceType, TypeInfoBase);
|
||||
|
||||
public:
|
||||
~AceType() override = default;
|
||||
|
||||
template<class T>
|
||||
static T* DynamicCast(AceType* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::DynamicCast<T>(rawPtr);
|
||||
}
|
||||
template<class T>
|
||||
static const T* DynamicCast(const AceType* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::DynamicCast<T>(rawPtr);
|
||||
}
|
||||
template<class T, class O>
|
||||
static RefPtr<T> DynamicCast(const RefPtr<O>& ptr)
|
||||
{
|
||||
return Claim(DynamicCast<T>(RawPtr(ptr)));
|
||||
}
|
||||
template<class T, class O>
|
||||
static WeakPtr<T> DynamicCast(const WeakPtr<O>& weak)
|
||||
{
|
||||
return WeakClaim(DynamicCast<T>(RawPtr(weak.Upgrade())));
|
||||
}
|
||||
|
||||
// Get type info by instance.
|
||||
static AceType::IdType TypeId(const AceType* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::TypeId(rawPtr);
|
||||
}
|
||||
template<class T>
|
||||
static AceType::IdType TypeId(const RefPtr<T>& ptr)
|
||||
{
|
||||
return TypeId(AceType::RawPtr(ptr));
|
||||
}
|
||||
static AceType::IdType TypeId(const AceType& instance)
|
||||
{
|
||||
return TypeInfoHelper::TypeId(instance);
|
||||
}
|
||||
static const char* TypeName(const AceType* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::TypeName(rawPtr);
|
||||
}
|
||||
template<class T>
|
||||
static const char* TypeName(const RefPtr<T>& ptr)
|
||||
{
|
||||
return TypeName(AceType::RawPtr(ptr));
|
||||
}
|
||||
static const char* TypeName(const AceType& instance)
|
||||
{
|
||||
return TypeInfoHelper::TypeName(instance);
|
||||
}
|
||||
|
||||
// Get type info by type itself.
|
||||
template<class T>
|
||||
static AceType::IdType TypeId()
|
||||
{
|
||||
return TypeInfoHelper::TypeId<T>();
|
||||
}
|
||||
template<class T>
|
||||
static const char* TypeName()
|
||||
{
|
||||
return TypeInfoHelper::TypeName<T>();
|
||||
}
|
||||
|
||||
// Check whether instance is the specified type
|
||||
template<class T>
|
||||
static bool InstanceOf(const AceType* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::InstanceOf<T>(rawPtr);
|
||||
}
|
||||
template<class T>
|
||||
static bool InstanceOf(const AceType& instance)
|
||||
{
|
||||
return TypeInfoHelper::InstanceOf<T>(&instance);
|
||||
}
|
||||
template<class T, class O>
|
||||
static bool InstanceOf(const RefPtr<O>& ptr)
|
||||
{
|
||||
return TypeInfoHelper::InstanceOf<T>(RawPtr(ptr));
|
||||
}
|
||||
|
||||
protected:
|
||||
AceType() = default;
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_ACE_TYPE_H
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 "base/memory/memory_monitor.h"
|
||||
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
|
||||
#include "base/log/dump_log.h"
|
||||
#include "base/log/log.h"
|
||||
|
||||
#ifdef ACE_MEMORY_MONITOR
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class MemoryMonitorImpl : public MemoryMonitor {
|
||||
public:
|
||||
void Add(void* ptr) final
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto result = memoryMap_.emplace(ptr, MemInfo());
|
||||
if (!result.second) {
|
||||
LOGE("Address is already in memory map");
|
||||
return;
|
||||
}
|
||||
|
||||
count_++;
|
||||
}
|
||||
|
||||
void Remove(void* ptr) final
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto it = memoryMap_.find(ptr);
|
||||
if (it == memoryMap_.end()) {
|
||||
LOGE("Address MUST be in memory map");
|
||||
return;
|
||||
}
|
||||
count_--;
|
||||
|
||||
if (it->second.size > 0) {
|
||||
total_ -= it->second.size;
|
||||
auto& info = typeMap_[it->second.typeName];
|
||||
info.count--;
|
||||
info.total -= it->second.size;
|
||||
}
|
||||
memoryMap_.erase(it);
|
||||
}
|
||||
|
||||
void Update(void* ptr, size_t size, const std::string& typeName) final
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
auto it = memoryMap_.find(ptr);
|
||||
if (it == memoryMap_.end()) {
|
||||
LOGE("Address MUST be in memory map");
|
||||
return;
|
||||
}
|
||||
|
||||
it->second.size = size;
|
||||
it->second.typeName = typeName;
|
||||
|
||||
total_ += size;
|
||||
auto& info = typeMap_[typeName];
|
||||
info.count++;
|
||||
info.total += size;
|
||||
}
|
||||
|
||||
void Dump() const final
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mutex_);
|
||||
std::string out = "total = " + std::to_string(total_) + ", count = " + std::to_string(count_);
|
||||
DumpLog::GetInstance().Print(0, out);
|
||||
for (auto&& [typeName, info] : typeMap_) {
|
||||
if (info.total == 0) {
|
||||
continue;
|
||||
}
|
||||
out = typeName + ": total = " + std::to_string(info.total) + ", count = " + std::to_string(info.count);
|
||||
DumpLog::GetInstance().Print(1, out);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
struct MemInfo {
|
||||
size_t size = 0;
|
||||
std::string typeName = "Unknown";
|
||||
};
|
||||
|
||||
struct TypeInfo {
|
||||
size_t count = 0;
|
||||
size_t total = 0;
|
||||
};
|
||||
|
||||
std::map<void*, MemInfo> memoryMap_;
|
||||
std::map<std::string, TypeInfo> typeMap_;
|
||||
size_t total_ = 0;
|
||||
size_t count_ = 0;
|
||||
|
||||
mutable std::mutex mutex_;
|
||||
};
|
||||
|
||||
MemoryMonitor& MemoryMonitor::GetInstance()
|
||||
{
|
||||
static MemoryMonitorImpl instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // ACE_MEMORY_MONITOR
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2021 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 FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_MEMORY_MONITOR_H
|
||||
#define FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_MEMORY_MONITOR_H
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/memory/memory_monitor_def.h"
|
||||
#include "base/memory/type_info_base.h"
|
||||
#include "base/utils/macros.h"
|
||||
|
||||
#ifdef ACE_MEMORY_MONITOR
|
||||
|
||||
namespace OHOS::Ace {
|
||||
|
||||
class ACE_EXPORT MemoryMonitor {
|
||||
public:
|
||||
static MemoryMonitor& GetInstance();
|
||||
|
||||
virtual ~MemoryMonitor() = default;
|
||||
|
||||
virtual void Add(void* ptr) = 0;
|
||||
virtual void Remove(void* ptr) = 0;
|
||||
virtual void Update(void* ptr, size_t size, const std::string& typeName) = 0;
|
||||
virtual void Dump() const = 0;
|
||||
|
||||
template<class T>
|
||||
void Update(T* ptr, void* refPtr)
|
||||
{
|
||||
if (ptr != nullptr && ptr->RefCount() == 0) {
|
||||
Update(refPtr, TypeInfo<T>::Size(ptr), TypeInfo<T>::Name(ptr));
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
template<class T, bool hasTypeInfo = std::is_base_of_v<TypeInfoBase, T>>
|
||||
struct TypeInfo;
|
||||
|
||||
template<class T>
|
||||
struct TypeInfo<T, false> {
|
||||
static const char* Name(T*)
|
||||
{
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
static size_t Size(T*)
|
||||
{
|
||||
return sizeof(T);
|
||||
}
|
||||
};
|
||||
|
||||
template<class T>
|
||||
struct TypeInfo<T, true> {
|
||||
static const char* Name(T* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::TypeName(rawPtr);
|
||||
}
|
||||
|
||||
static size_t Size(T* rawPtr)
|
||||
{
|
||||
return TypeInfoHelper::TypeSize(rawPtr);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
} // namespace OHOS::Ace
|
||||
|
||||
#endif // ACE_MEMORY_MONITOR
|
||||
|
||||
#endif // FOUNDATION_ACE_FRAMEWORKS_BASE_MEMORY_MEMORY_MONITOR_H
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user