mirror of
https://github.com/openharmony/graphic_ui.git
synced 2026-06-30 23:17:56 -04:00
update openharmony 1.0.1
This commit is contained in:
+160
@@ -0,0 +1,160 @@
|
||||
Language: Cpp
|
||||
# BasedOnStyle: LLVM
|
||||
# 访问说明符(public、private等)的偏移
|
||||
AccessModifierOffset: -4
|
||||
# 开括号(开圆括号、开尖括号、开方括号)后的对齐
|
||||
AlignAfterOpenBracket: Align
|
||||
# 连续赋值时,等号对齐
|
||||
AlignConsecutiveAssignments: false
|
||||
# 连续赋值时,变量名对齐
|
||||
AlignConsecutiveDeclarations: false
|
||||
# 左对齐逃脱换行(使用反斜杠换行)的反斜杠
|
||||
AlignEscapedNewlinesLeft: true
|
||||
# 水平对齐二元和三元表达式的操作数
|
||||
AlignOperands: true
|
||||
# 对齐连续的尾随的注释
|
||||
AlignTrailingComments: true
|
||||
# 允许函数声明的所有参数在放在下一行
|
||||
AllowAllParametersOfDeclarationOnNextLine: false
|
||||
# 允许短的块放在同一行
|
||||
AllowShortBlocksOnASingleLine: false
|
||||
# 允许短的case标签放在同一行
|
||||
AllowShortCaseLabelsOnASingleLine: false
|
||||
# 允许短的函数放在同一行: None, InlineOnly(定义在类中), Empty(空函数), Inline(定义在类中,空函数), All
|
||||
AllowShortFunctionsOnASingleLine: Empty
|
||||
# 允许短的if语句保持在同一行
|
||||
AllowShortIfStatementsOnASingleLine: false
|
||||
# 允许短的循环保持在同一行
|
||||
AllowShortLoopsOnASingleLine: false
|
||||
# 总是在定义返回类型后换行(deprecated)
|
||||
AlwaysBreakAfterDefinitionReturnType: None
|
||||
# 总是在返回类型后换行: None, All, TopLevel(顶级函数,不包括在类中的函数),
|
||||
# AllDefinitions(所有的定义,不包括声明), TopLevelDefinitions(所有的顶级函数的定义)
|
||||
AlwaysBreakAfterReturnType: None
|
||||
# 总是在多行string字面量前换行
|
||||
AlwaysBreakBeforeMultilineStrings: true
|
||||
# 总是在template声明后换行
|
||||
AlwaysBreakTemplateDeclarations: false
|
||||
# false表示函数实参要么都在同一行,要么都各自一行
|
||||
BinPackArguments: true
|
||||
# false表示所有形参要么都在同一行,要么都各自一行
|
||||
BinPackParameters: false
|
||||
# 大括号换行,只有当BreakBeforeBraces设置为Custom时才有效
|
||||
BraceWrapping:
|
||||
AfterClass: false
|
||||
AfterControlStatement: false
|
||||
AfterEnum: false
|
||||
AfterFunction: true
|
||||
AfterNamespace: false
|
||||
AfterObjCDeclaration: false
|
||||
AfterStruct: false
|
||||
AfterUnion: false
|
||||
BeforeCatch: false
|
||||
BeforeElse: false
|
||||
IndentBraces: false
|
||||
# 在二元运算符前换行: None(在操作符后换行), NonAssignment(在非赋值的操作符前换行), All(在操作符前换行)
|
||||
BreakBeforeBinaryOperators: None
|
||||
# 在大括号前换行: Attach(始终将大括号附加到周围的上下文), Linux(除函数、命名空间和类定义,与Attach类似),
|
||||
# Mozilla(除枚举、函数、记录定义,与Attach类似), Stroustrup(除函数定义、catch、else,与Attach类似),
|
||||
# Allman(总是在大括号前换行), GNU(总是在大括号前换行,并对于控制语句的大括号增加额外的缩进), WebKit(在函数前换行), Custom
|
||||
# 注:这里认为语句块也属于函数
|
||||
BreakBeforeBraces: Custom
|
||||
# 在三元运算符前换行
|
||||
BreakBeforeTernaryOperators: false
|
||||
# 在构造函数的初始化列表的逗号前换行
|
||||
BreakConstructorInitializersBeforeComma: false
|
||||
# 每行字符的限制,0表示没有限制
|
||||
ColumnLimit: 120
|
||||
# 描述具有特殊意义的注释的正则表达式,它不应该被分割为多行或以其它方式改变
|
||||
CommentPragmas: "^ IWYU pragma:"
|
||||
# 构造函数的初始化列表要么都在同一行,要么都各自一行
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: true
|
||||
# 构造函数的初始化列表的缩进宽度
|
||||
ConstructorInitializerIndentWidth: 4
|
||||
# 延续的行的缩进宽度
|
||||
ContinuationIndentWidth: 4
|
||||
# 去除C++11的列表初始化的大括号{后和}前的空格
|
||||
Cpp11BracedListStyle: true
|
||||
# 继承最常用的指针和引用的对齐方式
|
||||
DerivePointerAlignment: false
|
||||
# 关闭格式化
|
||||
DisableFormat: false
|
||||
# 自动检测函数的调用和定义是否被格式为每行一个参数(Experimental)
|
||||
ExperimentalAutoDetectBinPacking: false
|
||||
# 需要被解读为foreach循环而不是函数调用的宏
|
||||
ForEachMacros: [foreach, Q_FOREACH, BOOST_FOREACH]
|
||||
# 对#include进行排序,匹配了某正则表达式的#include拥有对应的优先级,匹配不到的则默认优先级为INT_MAX(优先级越小排序越靠前),
|
||||
# 可以定义负数优先级从而保证某些#include永远在最前面
|
||||
IncludeCategories:
|
||||
- Regex: '^"(llvm|llvm-c|clang|clang-c)/'
|
||||
Priority: 2
|
||||
- Regex: '^(<|"(gtest|isl|json)/)'
|
||||
Priority: 3
|
||||
- Regex: ".*"
|
||||
Priority: 1
|
||||
# 缩进case标签
|
||||
IndentCaseLabels: true
|
||||
# 缩进宽度
|
||||
IndentWidth: 4
|
||||
# 函数返回类型换行时,缩进函数声明或函数定义的函数名
|
||||
IndentWrappedFunctionNames: true
|
||||
# 保留在块开始处的空行
|
||||
KeepEmptyLinesAtTheStartOfBlocks: true
|
||||
# 开始一个块的宏的正则表达式
|
||||
MacroBlockBegin: ""
|
||||
# 结束一个块的宏的正则表达式
|
||||
MacroBlockEnd: ""
|
||||
# 连续空行的最大数量
|
||||
MaxEmptyLinesToKeep: 1
|
||||
# 命名空间的缩进: None, Inner(缩进嵌套的命名空间中的内容), All
|
||||
NamespaceIndentation: None
|
||||
# 使用ObjC块时缩进宽度
|
||||
ObjCBlockIndentWidth: 4
|
||||
# 在ObjC的@property后添加一个空格
|
||||
ObjCSpaceAfterProperty: false
|
||||
# 在ObjC的protocol列表前添加一个空格
|
||||
ObjCSpaceBeforeProtocolList: true
|
||||
# 在call(后对函数调用换行的penalty
|
||||
PenaltyBreakBeforeFirstCallParameter: 19
|
||||
# 在一个注释中引入换行的penalty
|
||||
PenaltyBreakComment: 300
|
||||
# 第一次在<<前换行的penalty
|
||||
PenaltyBreakFirstLessLess: 120
|
||||
# 在一个字符串字面量中引入换行的penalty
|
||||
PenaltyBreakString: 1000
|
||||
# 对于每个在行字符数限制之外的字符的penalt
|
||||
PenaltyExcessCharacter: 1000000
|
||||
# 将函数的返回类型放到它自己的行的penalty
|
||||
PenaltyReturnTypeOnItsOwnLine: 60
|
||||
# 指针和引用的对齐: Left, Right, Middle
|
||||
PointerAlignment: Left
|
||||
# 允许重新排版注释
|
||||
ReflowComments: true
|
||||
# 允许排序#include
|
||||
SortIncludes: true
|
||||
# 在C风格类型转换后添加空格
|
||||
SpaceAfterCStyleCast: false
|
||||
# 在赋值运算符之前添加空格
|
||||
SpaceBeforeAssignmentOperators: true
|
||||
# 开圆括号之前添加一个空格: Never, ControlStatements, Always
|
||||
SpaceBeforeParens: ControlStatements
|
||||
# 在空的圆括号中添加空格
|
||||
SpaceInEmptyParentheses: false
|
||||
# 在尾随的评论前添加的空格数(只适用于//)
|
||||
SpacesBeforeTrailingComments: 1
|
||||
# 在尖括号的<后和>前添加空格
|
||||
SpacesInAngles: false
|
||||
# 在容器(ObjC和JavaScript的数组和字典等)字面量中添加空格
|
||||
SpacesInContainerLiterals: true
|
||||
# 在C风格类型转换的括号中添加空格
|
||||
SpacesInCStyleCastParentheses: false
|
||||
# 在圆括号的(后和)前添加空格
|
||||
SpacesInParentheses: false
|
||||
# 在方括号的[后和]前添加空格,lamda表达式和未指明大小的数组的声明不受影响
|
||||
SpacesInSquareBrackets: false
|
||||
# 标准: Cpp03, Cpp11, Auto
|
||||
Standard: Cpp11
|
||||
# tab宽度
|
||||
TabWidth: 4
|
||||
# 使用tab字符: Never, ForIndentation, ForContinuationAndIndentation, Always
|
||||
UseTab: Never
|
||||
@@ -0,0 +1 @@
|
||||
/huawei_proprietary
|
||||
@@ -0,0 +1,170 @@
|
||||
# Copyright (c) 2020-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/lite/config/component/lite_component.gni")
|
||||
import("//build/lite/config/subsystem/graphic/config.gni")
|
||||
import("//build/lite/ndk/ndk.gni")
|
||||
|
||||
lite_component("lite_ui") {
|
||||
features = [ ":ui" ]
|
||||
public_deps = features
|
||||
}
|
||||
|
||||
ndk_lib("lite_ui_ndk") {
|
||||
lib_extension = ".so"
|
||||
deps = [ ":ui" ]
|
||||
head_files = [ "interfaces/kits" ]
|
||||
}
|
||||
|
||||
config("graphic_define_config") {
|
||||
include_dirs = [
|
||||
"interfaces/kits",
|
||||
"interfaces/innerkits",
|
||||
]
|
||||
|
||||
defines = [
|
||||
"ENABLE_VECTOR_FONT=1",
|
||||
"ENABLE_SHAPING=0",
|
||||
"ENABLE_ICU=0",
|
||||
"ENABLE_MULTI_FONT=0",
|
||||
]
|
||||
|
||||
if (ohos_kernel_type == "linux") {
|
||||
defines += [ "RESOURCE_DIR=\"/storage/data/\"" ]
|
||||
} else {
|
||||
defines += [ "RESOURCE_DIR=\"/user/data/\"" ]
|
||||
}
|
||||
}
|
||||
|
||||
if (enable_graphic_font) {
|
||||
copy("utils_config") {
|
||||
sources = [ "tools/qt/simulator/font/SourceHanSansSC-Regular.otf" ]
|
||||
outputs = [ "$root_out_dir/data/SourceHanSansSC-Regular.otf" ]
|
||||
}
|
||||
}
|
||||
|
||||
shared_library("ui") {
|
||||
sources = [
|
||||
"frameworks/animator/animator.cpp",
|
||||
"frameworks/animator/easing_equation.cpp",
|
||||
"frameworks/animator/interpolation.cpp",
|
||||
"frameworks/common/graphic_startup.cpp",
|
||||
"frameworks/common/image.cpp",
|
||||
"frameworks/common/input_device_manager.cpp",
|
||||
"frameworks/common/screen.cpp",
|
||||
"frameworks/common/screen_device_proxy.cpp",
|
||||
"frameworks/common/task.cpp",
|
||||
"frameworks/common/text.cpp",
|
||||
"frameworks/common/typed_text.cpp",
|
||||
"frameworks/common/ui_font_header.cpp",
|
||||
"frameworks/components/root_view.cpp",
|
||||
"frameworks/components/text_adapter.cpp",
|
||||
"frameworks/components/ui_abstract_clock.cpp",
|
||||
"frameworks/components/ui_abstract_progress.cpp",
|
||||
"frameworks/components/ui_abstract_scroll.cpp",
|
||||
"frameworks/components/ui_analog_clock.cpp",
|
||||
"frameworks/components/ui_arc_label.cpp",
|
||||
"frameworks/components/ui_axis.cpp",
|
||||
"frameworks/components/ui_box_progress.cpp",
|
||||
"frameworks/components/ui_button.cpp",
|
||||
"frameworks/components/ui_canvas.cpp",
|
||||
"frameworks/components/ui_chart.cpp",
|
||||
"frameworks/components/ui_checkbox.cpp",
|
||||
"frameworks/components/ui_circle_progress.cpp",
|
||||
"frameworks/components/ui_dialog.cpp",
|
||||
"frameworks/components/ui_digital_clock.cpp",
|
||||
"frameworks/components/ui_image_animator.cpp",
|
||||
"frameworks/components/ui_image_view.cpp",
|
||||
"frameworks/components/ui_label.cpp",
|
||||
"frameworks/components/ui_label_button.cpp",
|
||||
"frameworks/components/ui_list.cpp",
|
||||
"frameworks/components/ui_picker.cpp",
|
||||
"frameworks/components/ui_qrcode.cpp",
|
||||
"frameworks/components/ui_radio_button.cpp",
|
||||
"frameworks/components/ui_repeat_button.cpp",
|
||||
"frameworks/components/ui_scroll_view.cpp",
|
||||
"frameworks/components/ui_slider.cpp",
|
||||
"frameworks/components/ui_surface_view.cpp",
|
||||
"frameworks/components/ui_swipe_view.cpp",
|
||||
"frameworks/components/ui_texture_mapper.cpp",
|
||||
"frameworks/components/ui_time_picker.cpp",
|
||||
"frameworks/components/ui_toggle_button.cpp",
|
||||
"frameworks/components/ui_video.cpp",
|
||||
"frameworks/components/ui_view.cpp",
|
||||
"frameworks/components/ui_view_group.cpp",
|
||||
"frameworks/core/render_manager.cpp",
|
||||
"frameworks/core/task_manager.cpp",
|
||||
"frameworks/default_resource/check_box_res.cpp",
|
||||
"frameworks/dfx/event_injector.cpp",
|
||||
"frameworks/dfx/key_event_injector.cpp",
|
||||
"frameworks/dfx/point_event_injector.cpp",
|
||||
"frameworks/dfx/ui_dump_dom_tree.cpp",
|
||||
"frameworks/dfx/ui_screenshot.cpp",
|
||||
"frameworks/dock/input_device.cpp",
|
||||
"frameworks/dock/key_input_device.cpp",
|
||||
"frameworks/dock/ohos/ohos_input_device.cpp",
|
||||
"frameworks/dock/pointer_input_device.cpp",
|
||||
"frameworks/dock/rotate_input_device.cpp",
|
||||
"frameworks/dock/virtual_input_device.cpp",
|
||||
"frameworks/draw/draw_arc.cpp",
|
||||
"frameworks/draw/draw_curve.cpp",
|
||||
"frameworks/draw/draw_image.cpp",
|
||||
"frameworks/draw/draw_label.cpp",
|
||||
"frameworks/draw/draw_line.cpp",
|
||||
"frameworks/draw/draw_rect.cpp",
|
||||
"frameworks/draw/draw_triangle.cpp",
|
||||
"frameworks/draw/draw_utils.cpp",
|
||||
"frameworks/events/event.cpp",
|
||||
"frameworks/font/base_font.cpp",
|
||||
"frameworks/font/glyphs_manager.cpp",
|
||||
"frameworks/font/ui_font.cpp",
|
||||
"frameworks/font/ui_font_adaptor.cpp",
|
||||
"frameworks/font/ui_font_allocator.cpp",
|
||||
"frameworks/font/ui_font_cache.cpp",
|
||||
"frameworks/font/ui_font_vector.cpp",
|
||||
"frameworks/font/ui_line_break.cpp",
|
||||
"frameworks/font/ui_multi_font_manager.cpp",
|
||||
"frameworks/font/ui_text_shaping.cpp",
|
||||
"frameworks/imgdecode/cache_manager.cpp",
|
||||
"frameworks/imgdecode/file_img_decoder.cpp",
|
||||
"frameworks/imgdecode/image_load.cpp",
|
||||
"frameworks/layout/flex_layout.cpp",
|
||||
"frameworks/layout/grid_layout.cpp",
|
||||
"frameworks/layout/list_layout.cpp",
|
||||
"frameworks/themes/theme.cpp",
|
||||
"frameworks/themes/theme_manager.cpp",
|
||||
"frameworks/window/window.cpp",
|
||||
"frameworks/window/window_impl.cpp",
|
||||
]
|
||||
include_dirs = [ "//foundation/graphic/ui/frameworks" ]
|
||||
deps = [
|
||||
"//build/lite/config/component/cJSON:cjson_shared",
|
||||
"//foundation/graphic/surface:lite_surface",
|
||||
"//foundation/graphic/utils:lite_graphic_hals",
|
||||
"//foundation/graphic/wms:lite_wms",
|
||||
"//foundation/multimedia/media_lite/frameworks/player_lite:player_lite",
|
||||
"//third_party/bounds_checking_function:libsec_shared",
|
||||
"//third_party/freetype:freetype",
|
||||
"//third_party/giflib:libgif",
|
||||
"//third_party/libjpeg:libjpeg",
|
||||
"//third_party/libpng:libpng",
|
||||
"//third_party/qrcodegen:qrcodegen",
|
||||
]
|
||||
|
||||
public_deps = [ "//foundation/graphic/utils:lite_graphic_utils" ]
|
||||
public_configs = [ ":graphic_define_config" ]
|
||||
cflags = [
|
||||
"-Wall",
|
||||
"-fno-exceptions",
|
||||
]
|
||||
cflags_cc = cflags
|
||||
ldflags = [ "-Wl,-rpath-link=$ohos_root_path/$root_out_dir" ]
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,36 +0,0 @@
|
||||
# graphic_ui
|
||||
|
||||
#### Description
|
||||
{**When you're done, you can delete the content in this README and update the file with details for others getting started with your repository**}
|
||||
|
||||
#### 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,39 +1,124 @@
|
||||
# graphic_ui
|
||||
# UI<a name="EN-US_TOPIC_0000001123180295"></a>
|
||||
|
||||
#### 介绍
|
||||
{**以下是 Gitee 平台说明,您可以替换此简介**
|
||||
Gitee 是 OSCHINA 推出的基于 Git 的代码托管平台(同时支持 SVN)。专为开发者提供稳定、高效、安全的云端软件开发协作平台
|
||||
无论是个人、团队、或是企业,都能够用 Gitee 实现代码托管、项目管理、协作开发。企业项目请看 [https://gitee.com/enterprises](https://gitee.com/enterprises)}
|
||||
- [Introduction](#section11660541593)
|
||||
- [Directory Structure](#section161941989596)
|
||||
- [Constraints](#section119744591305)
|
||||
- [Compilation and Building](#section137768191623)
|
||||
- [Description](#section1312121216216)
|
||||
- [Component Description](#section66002422015)
|
||||
- [Usage](#section129654513264)
|
||||
|
||||
#### 软件架构
|
||||
软件架构说明
|
||||
- [Repositories Involved](#section1371113476307)
|
||||
|
||||
## Introduction<a name="section11660541593"></a>
|
||||
|
||||
The graphics UI module implements a system-level graphics engine.
|
||||
|
||||
This module provides the UIKit APIs for application development. You can use the APIs to add animations, manage layouts, transform images, process events, and operates on rich UI components.
|
||||
|
||||
The graphics UI directly calls the HAL API or uses the client provided by the Window Manager Service \(WMS\) to interact with the hardware to complete operations such as event response and image drawing.
|
||||
|
||||
**Figure 1** Graphics subsystem architecture<a name="fig1358754417214"></a>
|
||||

|
||||
|
||||
## Directory Structure<a name="section161941989596"></a>
|
||||
|
||||
```
|
||||
/foundation/graphic/ui
|
||||
├── frameworks # Framework code
|
||||
│ ├── animator # Animator module
|
||||
│ ├── common # Common module
|
||||
│ ├── components # Components
|
||||
│ ├── core # UI main processes (such as rendering and task management)
|
||||
│ ├── default_resource
|
||||
│ ├── dfx # Maintenance and test
|
||||
│ ├── dock # Driver adaptation layer
|
||||
│ │ └── ohos # OHOS platform adaptation
|
||||
│ ├── draw # Drawing logic
|
||||
│ ├── engines # Drawing engines
|
||||
│ │ ├── dfb
|
||||
│ │ ├── general
|
||||
│ │ ├── gpu_vglite
|
||||
│ │ └── software_zlite
|
||||
│ ├── events # Events
|
||||
│ ├── font # Fonts
|
||||
│ ├── imgdecode # Image management
|
||||
│ ├── layout # Page layout
|
||||
│ ├── themes # Theme management
|
||||
│ ├── window # Window management adaptation layer
|
||||
│ └── window_manager
|
||||
│ └── dfb
|
||||
├── interfaces # APIs
|
||||
│ ├── innerkits # APIs between modules
|
||||
│ │ └── xxx # Sub-module APIs
|
||||
│ └── kits # Externel APIs
|
||||
│ │ └── xxx # Sub-module APIs
|
||||
├── test # Test code
|
||||
│ ├── framework
|
||||
│ │ ├── include # Header files for the test framework
|
||||
│ │ └── src # Source code for the test framework
|
||||
│ ├── uitest # Display effect test (The executable program is in foundation/graphic/wms/test:sample_ui.)
|
||||
│ │ └── test_xxx # Specific UI effect test
|
||||
│ └── unittest # Unit testing
|
||||
│ └── xxx # Unit testing for a specific UI component
|
||||
└── tools # Test and simulation tools (simulator projects and resource files)
|
||||
└── qt # Qt project
|
||||
```
|
||||
|
||||
## Constraints<a name="section119744591305"></a>
|
||||
|
||||
Platform Constraints
|
||||
|
||||
- The Windows platform supports only Qt and OHOS IDE.
|
||||
- For the support of other platforms, see the **graphic** tag in **vender/hisilicon/\[product\_name\]/config.json**. If the **graphic** tag does not exist, it indicates that the product does not have the graphics subsystem.
|
||||
|
||||
## Compilation and Building<a name="section137768191623"></a>
|
||||
|
||||
```
|
||||
# Generate the libui.so file in the out directory of the product folder through GN compilation.
|
||||
hb build lite_ui
|
||||
|
||||
# To compile the Qt library, see the Qt simulator project at graphic/ui/tools/qt/simulator/simulator.pro.
|
||||
```
|
||||
|
||||
## Description<a name="section1312121216216"></a>
|
||||
|
||||
### Component Description<a name="section66002422015"></a>
|
||||
|
||||
Components are classified into basic components and container components.
|
||||
|
||||
- Basic components: Implement only a single function, such as **Text**, **Button**, **Image**, and **List**.
|
||||
- Container components: Hold and combine child components to implement complex functions.
|
||||
|
||||
**Figure 2** Graphics subsystem components<a name="fig1594213196218"></a>
|
||||

|
||||
|
||||
### Usage<a name="section129654513264"></a>
|
||||
|
||||
For details about how to use components and APIs of graphics, see the examples provided in **foundation/graphic/ui/test/uitest**.
|
||||
|
||||
- The Qt project can be debugged in the Windows environment.
|
||||
|
||||
Project file path:
|
||||
|
||||
```
|
||||
graphic/ui/tools/qt/simulator/simulator.pro
|
||||
```
|
||||
|
||||
- For other debugging environments, you can run **foundation/graphic/wms/test:sample\_ui**.
|
||||
|
||||
```
|
||||
hb build lite_wms -b debug
|
||||
```
|
||||
|
||||
After the building is successful, the executable program **out/\[product\_name\]/dev\_tools/bin/sample\_ui** is obtained. You can run the program in an environment to view the display effect of a specific component.
|
||||
|
||||
|
||||
#### 安装教程
|
||||
## Repositories Involved<a name="section1371113476307"></a>
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
/hmf/graphic/surface
|
||||
|
||||
#### 使用说明
|
||||
/hmf/graphic/wms
|
||||
|
||||
1. xxxx
|
||||
2. xxxx
|
||||
3. xxxx
|
||||
/hmf/graphic/utils
|
||||
|
||||
#### 参与贡献
|
||||
|
||||
1. Fork 本仓库
|
||||
2. 新建 Feat_xxx 分支
|
||||
3. 提交代码
|
||||
4. 新建 Pull Request
|
||||
|
||||
|
||||
#### 特技
|
||||
|
||||
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/)
|
||||
|
||||
+124
@@ -0,0 +1,124 @@
|
||||
# 图形UI组件<a name="ZH-CN_TOPIC_0000001123180295"></a>
|
||||
|
||||
- [简介](#section11660541593)
|
||||
- [目录](#section161941989596)
|
||||
- [约束](#section119744591305)
|
||||
- [编译构建](#section137768191623)
|
||||
- [说明](#section1312121216216)
|
||||
- [组件说明](#section66002422015)
|
||||
- [使用说明](#section129654513264)
|
||||
|
||||
- [相关仓](#section1371113476307)
|
||||
|
||||
## 简介<a name="section11660541593"></a>
|
||||
|
||||
图形UI组件实现了一套系统级的图形引擎。
|
||||
|
||||
该组件为应用开发提供UIKit接口,包括了动画、布局、图形转换、事件处理,以及丰富的UI组件。
|
||||
|
||||
组件内部直接调用HAL接口,或者使用WMS\(Window Manager Service\)提供的客户端与硬件交互,以完成事件响应、图像绘制等操作。
|
||||
|
||||
**图 1** 图形子系统架构图<a name="fig1358754417214"></a>
|
||||

|
||||
|
||||
## 目录<a name="section161941989596"></a>
|
||||
|
||||
```
|
||||
/foundation/graphic/ui
|
||||
├── frameworks # 框架代码
|
||||
│ ├── animator # 动画模块
|
||||
│ ├── common # 公共模块
|
||||
│ ├── components # 组件
|
||||
│ ├── core # ui主流程(渲染、任务管理等)
|
||||
│ ├── default_resource
|
||||
│ ├── dfx # 维测功能
|
||||
│ ├── dock # 驱动适配层
|
||||
│ │ └── ohos # ohos平台适配
|
||||
│ ├── draw # 绘制逻辑
|
||||
│ ├── engines # 绘制引擎
|
||||
│ │ ├── dfb
|
||||
│ │ ├── general
|
||||
│ │ ├── gpu_vglite
|
||||
│ │ └── software_zlite
|
||||
│ ├── events # 事件
|
||||
│ ├── font # 字体
|
||||
│ ├── imgdecode # 图片管理
|
||||
│ ├── layout # 页面布局
|
||||
│ ├── themes # 主题管理
|
||||
│ ├── window # 窗口管理适配层
|
||||
│ └── window_manager
|
||||
│ └── dfb
|
||||
├── interfaces # 接口
|
||||
│ ├── innerkits # 模块间接口
|
||||
│ │ └── xxx # 子模块的接口
|
||||
│ └── kits # 对外接口
|
||||
│ └── xxx # 子模块的接口
|
||||
├── test # 测试代码
|
||||
│ ├── framework
|
||||
│ │ ├── include # 测试框架头文件
|
||||
│ │ └── src # 测试框架源码
|
||||
│ ├── uitest # 显示效果测试(可执行程序在foundation/graphic/wms/test:sample_ui)
|
||||
│ │ └── test_xxx # 具体UI组件效果测试
|
||||
│ └── unittest # 单元测试
|
||||
│ └── xxx # 具体UI组件单元测试
|
||||
└── tools # 测试和模拟器工具(模拟器工程、资源文件)
|
||||
└── qt # QT工程
|
||||
```
|
||||
|
||||
## 约束<a name="section119744591305"></a>
|
||||
|
||||
平台约束
|
||||
|
||||
- Windows平台仅支持QT和OHOS IDE。
|
||||
- 其他平台支持情况参考vender/hisilicon/\[product\_name\]/config.json中的graphic标签(不存在graphic标签即该产品不存在图形子系统)。
|
||||
|
||||
## 编译构建<a name="section137768191623"></a>
|
||||
|
||||
```
|
||||
# 通过gn编译,在out目录下对应产品的文件夹中生成libui.so
|
||||
hb build lite_ui
|
||||
|
||||
# 编译qt库可直接参考qt模拟器工程:graphic/ui/tools/qt/simulator/simulator.pro
|
||||
```
|
||||
|
||||
## 说明<a name="section1312121216216"></a>
|
||||
|
||||
### 组件说明<a name="section66002422015"></a>
|
||||
|
||||
组件分为基础组件和容器组件
|
||||
|
||||
- 基础组件:仅实现组件自身单一功能,比如按钮、文字、图片等;
|
||||
- 容器组件:可将其他组件作为自己的子组件,通过组合实现复杂功能。
|
||||
|
||||
**图 2** 图形组件一览<a name="fig1594213196218"></a>
|
||||

|
||||
|
||||
### 使用说明<a name="section129654513264"></a>
|
||||
|
||||
foundation/graphic/ui/test/uitest中提供了图形所有组件和功能接口的使用范例。
|
||||
|
||||
- Windows环境可运行QT工程调试
|
||||
|
||||
工程文件路径:
|
||||
|
||||
```
|
||||
graphic/ui/tools/qt/simulator/simulator.pro
|
||||
```
|
||||
|
||||
- 其他调试环境可以编译运行foundation/graphic/wms/test:sample\_ui
|
||||
|
||||
```
|
||||
hb build lite_wms -b debug
|
||||
```
|
||||
|
||||
编译成功后得到可执行程序out/\[product\_name\]/dev\_tools/bin/sample\_ui,在实际环境上运行即可观察对应组件显示效果。
|
||||
|
||||
|
||||
## 相关仓<a name="section1371113476307"></a>
|
||||
|
||||
/hmf/graphic/surface
|
||||
|
||||
/hmf/graphic/wms
|
||||
|
||||
/hmf/graphic/utils
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 41 KiB |
Binary file not shown.
|
After Width: | Height: | Size: 39 KiB |
Executable
+110
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "animator/animator.h"
|
||||
|
||||
#include "common/task_manager.h"
|
||||
#include "hal_tick.h"
|
||||
|
||||
namespace OHOS {
|
||||
void Animator::Start()
|
||||
{
|
||||
SetState(START);
|
||||
runTime_ = 0;
|
||||
lastRunTime_ = 0;
|
||||
}
|
||||
|
||||
void Animator::Stop()
|
||||
{
|
||||
SetState(STOP);
|
||||
if (callback_ != nullptr) {
|
||||
callback_->OnStop(*view_);
|
||||
}
|
||||
}
|
||||
|
||||
void Animator::Pause()
|
||||
{
|
||||
SetState(PAUSE);
|
||||
}
|
||||
|
||||
void Animator::Resume()
|
||||
{
|
||||
SetState(START);
|
||||
lastRunTime_ = HALTick::GetInstance().GetTime();
|
||||
}
|
||||
|
||||
void Animator::Run()
|
||||
{
|
||||
if (lastRunTime_ == 0) {
|
||||
lastRunTime_ = HALTick::GetInstance().GetTime();
|
||||
}
|
||||
|
||||
uint32_t elepse = HALTick::GetInstance().GetElapseTime(lastRunTime_);
|
||||
|
||||
runTime_ = (UINT32_MAX - elepse > runTime_) ? (runTime_ + elepse) : time_;
|
||||
lastRunTime_ = HALTick::GetInstance().GetTime();
|
||||
if (callback_ != nullptr) {
|
||||
callback_->Callback(view_);
|
||||
}
|
||||
}
|
||||
|
||||
void AnimatorManager::Init()
|
||||
{
|
||||
Task::Init();
|
||||
}
|
||||
|
||||
void AnimatorManager::Add(Animator* animator)
|
||||
{
|
||||
if (animator == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_.PushBack(animator);
|
||||
}
|
||||
|
||||
void AnimatorManager::Remove(const Animator* animator)
|
||||
{
|
||||
if (animator == nullptr) {
|
||||
return;
|
||||
}
|
||||
ListNode<Animator*>* pos = list_.Begin();
|
||||
while (pos != list_.End()) {
|
||||
if (pos->data_ == animator) {
|
||||
list_.Remove(pos);
|
||||
return;
|
||||
}
|
||||
pos = pos->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void AnimatorManager::AnimatorTask()
|
||||
{
|
||||
ListNode<Animator*>* pos = list_.Begin();
|
||||
Animator* animator = nullptr;
|
||||
|
||||
while (pos != list_.End()) {
|
||||
animator = pos->data_;
|
||||
if (animator->GetState() == Animator::START) {
|
||||
if (animator->IsRepeat() || (animator->GetRunTime() <= animator->GetTime())) {
|
||||
animator->Run();
|
||||
} else {
|
||||
animator->Stop();
|
||||
}
|
||||
}
|
||||
|
||||
pos = pos->next_;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+254
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "animator/easing_equation.h"
|
||||
#include "graphic_math.h"
|
||||
|
||||
namespace OHOS {
|
||||
double EasingEquation::overshoot_ = 1.7; // The empirical value commonly used in easing equation
|
||||
|
||||
void EasingEquation::SetBackOvershoot(double overshoot)
|
||||
{
|
||||
if ((overshoot >= OVERSHOOT_MIN) && (overshoot <= OVERSHOOT_MAX)) {
|
||||
overshoot_ = overshoot;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t EasingEquation::BackEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
double t = -(static_cast<double>(curTime) / durationTime);
|
||||
double x = -t * t * ((overshoot_ + 1) * t + overshoot_);
|
||||
return static_cast<int16_t>((x * (static_cast<int32_t>(endPos) - startPos)) + startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::BackEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
double t = static_cast<double>(curTime) / durationTime;
|
||||
t -= 1.0;
|
||||
double x = t * t * ((overshoot_ + 1) * t + overshoot_) + 1;
|
||||
return static_cast<int16_t>((x * (static_cast<int32_t>(endPos) - startPos)) + startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::BackEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
uint16_t halfTime = durationTime >> 1;
|
||||
int16_t halfStep = (endPos >> 1) + (startPos >> 1);
|
||||
if (curTime < halfTime) {
|
||||
return BackEaseIn(startPos, halfStep, curTime, halfTime);
|
||||
}
|
||||
return BackEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
|
||||
}
|
||||
|
||||
/* 1 - sqrt(1 - t^2) */
|
||||
int16_t EasingEquation::CircEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
uint32_t x = INTERPOLATION_RANGE - Sqrt(INTERPOLATION_RANGE_SQUARE - t * t);
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
/* sqrt(1 - (1 - t)^2) */
|
||||
int16_t EasingEquation::CircEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = INTERPOLATION_RANGE - (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
uint32_t x = static_cast<uint32_t>(Sqrt(INTERPOLATION_RANGE_SQUARE - t * t));
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::CircEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
uint16_t halfTime = durationTime >> 1;
|
||||
int16_t halfStep = (endPos >> 1) + (startPos >> 1);
|
||||
if (curTime < halfTime) {
|
||||
return CircEaseIn(startPos, halfStep, curTime, halfTime);
|
||||
}
|
||||
return CircEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
|
||||
}
|
||||
|
||||
/* t^3 */
|
||||
int16_t EasingEquation::CubicEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
int16_t x = (t * t * t) >> (INTERPOLATION_RANGE_OFFSET << 1);
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
/* 1 - (1 - t)^3 */
|
||||
int16_t EasingEquation::CubicEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
t = INTERPOLATION_RANGE - t;
|
||||
int16_t x = INTERPOLATION_RANGE - ((t * t * t) >> (INTERPOLATION_RANGE_OFFSET << 1));
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::CubicEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
uint16_t halfTime = durationTime >> 1;
|
||||
int16_t halfStep = (endPos >> 1) + (startPos >> 1);
|
||||
if (curTime < halfTime) {
|
||||
return CubicEaseIn(startPos, halfStep, curTime, halfTime);
|
||||
}
|
||||
return CubicEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
|
||||
}
|
||||
|
||||
int16_t EasingEquation::LinearEaseNone(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
return static_cast<int16_t>(((t * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
/* t^2 */
|
||||
int16_t EasingEquation::QuadEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
int16_t x = (t * t) >> INTERPOLATION_RANGE_OFFSET;
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
/* 1 - (1 - t)^2 */
|
||||
int16_t EasingEquation::QuadEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int32_t t = INTERPOLATION_RANGE - (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
int16_t x = INTERPOLATION_RANGE - ((t * t) >> INTERPOLATION_RANGE_OFFSET);
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::QuadEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
uint16_t halfTime = durationTime >> 1;
|
||||
int16_t halfStep = (endPos >> 1) + (startPos >> 1);
|
||||
if (curTime < halfTime) {
|
||||
return QuadEaseIn(startPos, halfStep, curTime, halfTime);
|
||||
}
|
||||
return QuadEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
|
||||
}
|
||||
|
||||
/* t^5 */
|
||||
int16_t EasingEquation::QuintEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int64_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
|
||||
/* 4: the fourth power of t */
|
||||
int16_t x = (t * t * t * t * t) >> (INTERPOLATION_RANGE_OFFSET * 4);
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
/* 1 - (1 - t)^5 */
|
||||
int16_t EasingEquation::QuintEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int64_t t = (curTime << INTERPOLATION_RANGE_OFFSET) / durationTime;
|
||||
t = INTERPOLATION_RANGE - t;
|
||||
|
||||
/* 4: the fourth power of t */
|
||||
int16_t x = INTERPOLATION_RANGE - ((t * t * t * t * t) >> (INTERPOLATION_RANGE_OFFSET * 4));
|
||||
return static_cast<int16_t>(((x * (static_cast<int32_t>(endPos) - startPos)) >> INTERPOLATION_RANGE_OFFSET) +
|
||||
startPos);
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::QuintEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
uint16_t halfTime = durationTime >> 1;
|
||||
int16_t halfStep = (endPos >> 1) + (startPos >> 1);
|
||||
if (curTime < halfTime) {
|
||||
return QuintEaseIn(startPos, halfStep, curTime, halfTime);
|
||||
}
|
||||
return QuintEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
|
||||
}
|
||||
|
||||
int16_t EasingEquation::SineEaseIn(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int16_t t = (curTime * QUARTER_IN_DEGREE) / durationTime - QUARTER_IN_DEGREE;
|
||||
float x = Sin(t) + 1;
|
||||
return static_cast<int16_t>(x * (endPos - startPos)) + startPos;
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::SineEaseOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
if (curTime < durationTime) {
|
||||
int16_t t = (curTime * QUARTER_IN_DEGREE) / durationTime;
|
||||
float x = Sin(t);
|
||||
return static_cast<int16_t>(x * (endPos - startPos)) + startPos;
|
||||
}
|
||||
|
||||
return endPos;
|
||||
}
|
||||
|
||||
int16_t EasingEquation::SineEaseInOut(int16_t startPos, int16_t endPos, uint16_t curTime, uint16_t durationTime)
|
||||
{
|
||||
uint16_t halfTime = durationTime >> 1;
|
||||
int16_t halfStep = (endPos >> 1) + (startPos >> 1);
|
||||
if (curTime < halfTime) {
|
||||
return SineEaseIn(startPos, halfStep, curTime, halfTime);
|
||||
}
|
||||
return SineEaseOut(halfStep, endPos, curTime - halfTime, halfTime);
|
||||
}
|
||||
}
|
||||
Executable
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "animator/interpolation.h"
|
||||
|
||||
namespace OHOS {
|
||||
/* B(t) = P0*(1-t)^3 + 3*P1*t*(1-t)^2 + 3*P2*t^2*(1-t) + P3*t^3 */
|
||||
int16_t Interpolation::GetBezierInterpolation(int16_t t, int16_t u0, int16_t u1, int16_t u2, int16_t u3)
|
||||
{
|
||||
int64_t invT = INTERPOLATION_RANGE - t;
|
||||
int64_t invT2 = invT * invT;
|
||||
int64_t invT3 = invT2 * invT;
|
||||
int64_t t2 = t * t;
|
||||
int64_t t3 = t2 * t;
|
||||
|
||||
int64_t ret = invT3 * u0;
|
||||
ret += BESSEL_COEFFICIENT * invT2 * t * u1;
|
||||
ret += BESSEL_COEFFICIENT * invT * t2 * u2;
|
||||
ret += t3 * u3;
|
||||
ret = ret >> CUBIC_BEZIER_CALCULATE_OFFSET;
|
||||
return static_cast<int16_t>(ret);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/graphic_startup.h"
|
||||
#include "animator/animator.h"
|
||||
#include "common/input_device_manager.h"
|
||||
#include "common/task_manager.h"
|
||||
#include "core/render_manager.h"
|
||||
#include "dfx/performance_task.h"
|
||||
#include "file.h"
|
||||
#include "font/ui_font.h"
|
||||
#if ENABLE_SHAPING
|
||||
#include "font/ui_text_shaping.h"
|
||||
#endif
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#ifdef VERSION_STANDARD
|
||||
#include "dock/ohos/ohos_input_device.h"
|
||||
#endif
|
||||
#if ENABLE_WINDOW
|
||||
#include "iwindows_manager.h"
|
||||
#endif
|
||||
#if ENABLE_GFX_ENGINES
|
||||
#include "hals/gfx_engines.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
void GraphicStartUp::InitFontEngine(uintptr_t psramAddr, uint32_t psramLen, const char* dPath, const char* ttfName)
|
||||
{
|
||||
#if ENABLE_VECTOR_FONT
|
||||
UIFont* fontEngine = UIFont::GetInstance();
|
||||
if (fontEngine == nullptr) {
|
||||
GRAPHIC_LOGE("Get UIFont error");
|
||||
return;
|
||||
}
|
||||
fontEngine->SetPsramMemory(psramAddr, psramLen);
|
||||
// font and glyph path
|
||||
int8_t ret = fontEngine->SetFontPath(const_cast<char*>(dPath), nullptr);
|
||||
if (ret == INVALID_RET_VALUE) {
|
||||
GRAPHIC_LOGW("SetFontPath failed");
|
||||
}
|
||||
if (ttfName != nullptr) {
|
||||
uint8_t ret2 = fontEngine->RegisterFontInfo(ttfName);
|
||||
if (ret2 == INVALID_UCHAR_ID) {
|
||||
GRAPHIC_LOGW("SetTtfName failed");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GraphicStartUp::Init()
|
||||
{
|
||||
TaskManager::GetInstance()->SetTaskRun(true);
|
||||
DEBUG_PERFORMANCE_TASK_INIT();
|
||||
|
||||
if (INDEV_READ_PERIOD > 0) {
|
||||
InputDeviceManager::GetInstance()->Init();
|
||||
}
|
||||
AnimatorManager::GetInstance()->Init();
|
||||
|
||||
StyleDefault::Init();
|
||||
RenderManager::GetInstance().Init();
|
||||
|
||||
CacheManager::GetInstance().Init(IMG_CACHE_SIZE);
|
||||
#ifdef VERSION_STANDARD
|
||||
OHOSInputDevice* input = new OHOSInputDevice();
|
||||
if (input == nullptr) {
|
||||
GRAPHIC_LOGE("new OHOSInputDevice fail");
|
||||
return;
|
||||
}
|
||||
InputDeviceManager::GetInstance()->Add(input);
|
||||
#endif
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
IWindowsManager::GetInstance()->Init();
|
||||
#endif
|
||||
#if ENABLE_GFX_ENGINES
|
||||
GfxEngines::GetInstance()->InitDriver();
|
||||
#endif
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+449
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/image.h"
|
||||
#include "common/image_decode_ability.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "file.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#if ENABLE_JPEG_AND_PNG
|
||||
#include "jpeglib.h"
|
||||
#include "png.h"
|
||||
#endif
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
Image::Image() : imageInfo_(nullptr), path_(nullptr), srcType_(IMG_SRC_UNKNOWN), mallocFlag_(false) {}
|
||||
|
||||
Image::~Image()
|
||||
{
|
||||
if (srcType_ == IMG_SRC_FILE) {
|
||||
CacheManager::GetInstance().Close(path_);
|
||||
}
|
||||
if (imageInfo_ != nullptr) {
|
||||
if (mallocFlag_) {
|
||||
if (imageInfo_->data != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(imageInfo_->data)));
|
||||
}
|
||||
mallocFlag_ = false;
|
||||
}
|
||||
UIFree(reinterpret_cast<void*>(const_cast<ImageInfo*>(imageInfo_)));
|
||||
imageInfo_ = nullptr;
|
||||
}
|
||||
if (path_ != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<char*>(path_)));
|
||||
path_ = nullptr;
|
||||
}
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
}
|
||||
|
||||
void Image::GetHeader(ImageHeader& header) const
|
||||
{
|
||||
if ((srcType_ == IMG_SRC_VARIABLE) && (imageInfo_ != nullptr)) {
|
||||
header = imageInfo_->header;
|
||||
} else if ((srcType_ == IMG_SRC_FILE) && (path_ != nullptr)) {
|
||||
CacheManager::GetInstance().GetImageHeader(path_, header);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_JPEG_AND_PNG
|
||||
Image::ImageType Image::CheckImgType(const char* src)
|
||||
{
|
||||
char buf[IMG_BYTES_TO_CHECK] = {0};
|
||||
#ifdef _WIN32
|
||||
int32_t fd = open(src, O_RDONLY | O_BINARY);
|
||||
#else
|
||||
int32_t fd = open(src, O_RDONLY);
|
||||
#endif
|
||||
if (fd < 0) {
|
||||
GRAPHIC_LOGE("can't open %s\n", src);
|
||||
return IMG_UNKNOWN;
|
||||
}
|
||||
if (read(fd, buf, IMG_BYTES_TO_CHECK) != IMG_BYTES_TO_CHECK) {
|
||||
close(fd);
|
||||
return IMG_UNKNOWN;
|
||||
}
|
||||
close(fd);
|
||||
if (!png_sig_cmp(reinterpret_cast<png_const_bytep>(buf), 0, IMG_BYTES_TO_CHECK)) {
|
||||
return IMG_PNG;
|
||||
// 0xFF 0xD8: JPEG file's header
|
||||
} else if ((static_cast<uint8_t>(buf[0]) == 0xFF) && (static_cast<uint8_t>(buf[1]) == 0xD8)) {
|
||||
return IMG_JPEG;
|
||||
}
|
||||
return IMG_UNKNOWN;
|
||||
}
|
||||
#endif
|
||||
|
||||
bool Image::SetStandardSrc(const char* src)
|
||||
{
|
||||
if (src == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const char* ptr = strrchr(src, '.');
|
||||
if (ptr == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_JPEG_AND_PNG
|
||||
ImageType imageType = CheckImgType(src);
|
||||
if (imageType == IMG_PNG) {
|
||||
return SetPNGSrc(src);
|
||||
} else if (imageType == IMG_JPEG) {
|
||||
return SetJPEGSrc(src);
|
||||
}
|
||||
#endif
|
||||
|
||||
size_t strLen = strlen(src) + 1;
|
||||
char* imagePath = static_cast<char*>(UIMalloc(static_cast<uint32_t>(strLen)));
|
||||
if (imagePath == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (strcpy_s(imagePath, strLen, src) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(imagePath));
|
||||
imagePath = nullptr;
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
path_ = imagePath;
|
||||
srcType_ = IMG_SRC_FILE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::SetLiteSrc(const char* src)
|
||||
{
|
||||
if (src == nullptr) {
|
||||
return false;
|
||||
}
|
||||
const char* ptr = strrchr(src, '.');
|
||||
if (ptr == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t strLen = strlen(src) + 1;
|
||||
char* imagePath = static_cast<char*>(UIMalloc(static_cast<uint32_t>(strLen)));
|
||||
if (imagePath == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
if (IsImgValid(ptr)) {
|
||||
const char* suffixName = "bin";
|
||||
if (memcpy_s(imagePath, strLen, src, strLen) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(imagePath));
|
||||
imagePath = nullptr;
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
(ptr - src + imagePath)[1] = '\0'; // remove suffix
|
||||
if (strcat_s(imagePath, strLen, suffixName) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(imagePath));
|
||||
imagePath = nullptr;
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (memcpy_s(imagePath, strLen, src, strLen) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(imagePath));
|
||||
imagePath = nullptr;
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
path_ = imagePath;
|
||||
srcType_ = IMG_SRC_FILE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::SetSrc(const char* src)
|
||||
{
|
||||
if (path_ != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<char*>(path_)));
|
||||
path_ = nullptr;
|
||||
}
|
||||
|
||||
if (src != nullptr) {
|
||||
uint32_t imageType = ImageDecodeAbility::GetInstance().GetImageDecodeAbility();
|
||||
if (((imageType & IMG_SUPPORT_JPEG) == IMG_SUPPORT_JPEG) ||
|
||||
((imageType & IMG_SUPPORT_PNG) == IMG_SUPPORT_PNG)) {
|
||||
return SetStandardSrc(src);
|
||||
}
|
||||
return SetLiteSrc(src);
|
||||
} else {
|
||||
path_ = src;
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::SetSrc(const ImageInfo* src)
|
||||
{
|
||||
if (imageInfo_ != nullptr) {
|
||||
if (mallocFlag_) {
|
||||
if (imageInfo_->data != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(imageInfo_->data)));
|
||||
}
|
||||
mallocFlag_ = false;
|
||||
}
|
||||
UIFree(reinterpret_cast<void*>(const_cast<ImageInfo*>(imageInfo_)));
|
||||
imageInfo_ = nullptr;
|
||||
}
|
||||
|
||||
if (src != nullptr) {
|
||||
imageInfo_ = static_cast<ImageInfo*>(UIMalloc(static_cast<uint32_t>(sizeof(ImageInfo))));
|
||||
if (imageInfo_ == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcpy_s(const_cast<ImageInfo*>(imageInfo_), sizeof(ImageInfo), src, sizeof(ImageInfo)) != EOK) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
|
||||
srcType_ = IMG_SRC_VARIABLE;
|
||||
} else {
|
||||
imageInfo_ = src;
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void Image::DrawImage(const Rect& coords, const Rect& mask, const Style& style, uint8_t opaScale) const
|
||||
{
|
||||
if (srcType_ == IMG_SRC_VARIABLE) {
|
||||
DrawImage::DrawCommon(coords, mask, imageInfo_, style, opaScale);
|
||||
} else if (srcType_ == IMG_SRC_FILE) {
|
||||
DrawImage::DrawCommon(coords, mask, path_, style, opaScale);
|
||||
} else {
|
||||
GRAPHIC_LOGE("Image::DrawImage:: failed with error srctype!\n");
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_JPEG_AND_PNG
|
||||
bool Image::SetPNGSrc(const char* src)
|
||||
{
|
||||
FILE* infile = nullptr;
|
||||
png_bytep* rowPointer = nullptr;
|
||||
png_structp png = png_create_read_struct(PNG_LIBPNG_VER_STRING, nullptr, nullptr, nullptr);
|
||||
if (png == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
png_infop info = png_create_info_struct(png);
|
||||
if (info == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
if ((infile = fopen(src, "rb")) == nullptr) {
|
||||
GRAPHIC_LOGE("can't open %s\n", src);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
png_init_io(png, infile);
|
||||
png_read_info(png, info);
|
||||
|
||||
uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(ARGB8888) >> 3; // 3: Shift right 3 bits
|
||||
uint16_t width = png_get_image_width(png, info);
|
||||
uint16_t height = png_get_image_height(png, info);
|
||||
uint8_t colorType = png_get_color_type(png, info);
|
||||
uint8_t bitDepth = png_get_bit_depth(png, info);
|
||||
uint32_t dataSize = height * width * pixelByteSize;
|
||||
|
||||
if ((colorType == PNG_COLOR_TYPE_GRAY) && (bitDepth < 8)) { // 8: Expand grayscale images to the full 8 bits
|
||||
png_set_expand_gray_1_2_4_to_8(png);
|
||||
}
|
||||
if ((colorType == PNG_COLOR_TYPE_GRAY) || (colorType == PNG_COLOR_TYPE_GRAY_ALPHA)) {
|
||||
png_set_gray_to_rgb(png);
|
||||
}
|
||||
if (colorType == PNG_COLOR_TYPE_PALETTE) {
|
||||
png_set_palette_to_rgb(png);
|
||||
}
|
||||
if (bitDepth == 16) { // 16: Chop 16-bit depth images to 8-bit depth
|
||||
png_set_strip_16(png);
|
||||
}
|
||||
if (png_get_valid(png, info, PNG_INFO_tRNS)) {
|
||||
png_set_tRNS_to_alpha(png);
|
||||
}
|
||||
if (!(colorType & PNG_COLOR_MASK_ALPHA)) {
|
||||
png_set_add_alpha(png, 0xFF, PNG_FILLER_AFTER);
|
||||
}
|
||||
png_set_interlace_handling(png);
|
||||
png_read_update_info(png, info);
|
||||
|
||||
rowPointer = static_cast<png_bytep*>(UIMalloc(sizeof(png_bytep) * height));
|
||||
if (rowPointer == nullptr) {
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
fclose(infile);
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
for (uint16_t y = 0; y < height; y++) {
|
||||
rowPointer[y] = static_cast<png_byte*>(UIMalloc(png_get_rowbytes(png, info)));
|
||||
if (rowPointer[y] == nullptr) {
|
||||
for (uint16_t i = 0; i < y; i++) {
|
||||
UIFree(rowPointer[i]);
|
||||
rowPointer[i] = nullptr;
|
||||
}
|
||||
fclose(infile);
|
||||
UIFree(rowPointer);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
png_read_image(png, rowPointer);
|
||||
fclose(infile);
|
||||
png_destroy_read_struct(&png, &info, nullptr);
|
||||
ImageInfo* imgInfo = static_cast<ImageInfo*>(UIMalloc(sizeof(ImageInfo)));
|
||||
if (imgInfo == nullptr) {
|
||||
for (uint16_t i = 0; i < height; i++) {
|
||||
UIFree(rowPointer[i]);
|
||||
rowPointer[i] = nullptr;
|
||||
}
|
||||
UIFree(rowPointer);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
uint8_t* srcData = static_cast<uint8_t*>(UIMalloc(dataSize));
|
||||
if (srcData == nullptr) {
|
||||
for (uint16_t i = 0; i < height; i++) {
|
||||
UIFree(rowPointer[i]);
|
||||
rowPointer[i] = nullptr;
|
||||
}
|
||||
UIFree(rowPointer);
|
||||
UIFree(imgInfo);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
uint32_t n = 0;
|
||||
for (uint16_t y = 0; y < height; y++) {
|
||||
png_bytep row = rowPointer[y];
|
||||
for (uint16_t x = 0; x < width * pixelByteSize; x += pixelByteSize) {
|
||||
srcData[n++] = row[x + 2]; // 2: B channel
|
||||
srcData[n++] = row[x + 1]; // 1: G channel
|
||||
srcData[n++] = row[x + 0]; // 0: R channel
|
||||
srcData[n++] = row[x + 3]; // 3: Alpha channel
|
||||
}
|
||||
UIFree(row);
|
||||
row = nullptr;
|
||||
}
|
||||
UIFree(rowPointer);
|
||||
|
||||
imgInfo->header.width = width;
|
||||
imgInfo->header.height = height;
|
||||
imgInfo->header.colorMode = ARGB8888;
|
||||
imgInfo->dataSize = dataSize;
|
||||
imgInfo->data = srcData;
|
||||
|
||||
if (imageInfo_ != nullptr) {
|
||||
if (mallocFlag_) {
|
||||
if (imageInfo_->data != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(imageInfo_->data)));
|
||||
}
|
||||
mallocFlag_ = false;
|
||||
}
|
||||
UIFree(reinterpret_cast<void*>(const_cast<ImageInfo*>(imageInfo_)));
|
||||
imageInfo_ = nullptr;
|
||||
}
|
||||
imageInfo_ = imgInfo;
|
||||
mallocFlag_ = true;
|
||||
srcType_ = IMG_SRC_VARIABLE;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Image::SetJPEGSrc(const char* src)
|
||||
{
|
||||
struct jpeg_decompress_struct cinfo;
|
||||
struct jpeg_error_mgr jerr;
|
||||
FILE* infile = nullptr;
|
||||
|
||||
if ((infile = fopen(src, "rb")) == nullptr) {
|
||||
GRAPHIC_LOGE("can't open %s\n", src);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
cinfo.err = jpeg_std_error(&jerr);
|
||||
jpeg_create_decompress(&cinfo);
|
||||
jpeg_stdio_src(&cinfo, infile);
|
||||
jpeg_read_header(&cinfo, TRUE);
|
||||
jpeg_start_decompress(&cinfo);
|
||||
|
||||
uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(ARGB8888) >> 3; // 3: Shift right 3 bits
|
||||
uint16_t width = cinfo.output_width;
|
||||
uint16_t height = cinfo.output_height;
|
||||
uint32_t dataSize = width * height * pixelByteSize;
|
||||
uint16_t rowStride = cinfo.output_width * pixelByteSize;
|
||||
JSAMPARRAY buffer = (*cinfo.mem->alloc_sarray)(reinterpret_cast<j_common_ptr>(&cinfo), JPOOL_IMAGE, rowStride,
|
||||
1); // 1: one-row-high array
|
||||
ImageInfo* imgInfo = static_cast<ImageInfo*>(UIMalloc(sizeof(ImageInfo)));
|
||||
if (imgInfo == nullptr) {
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(infile);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
uint8_t* srcData = static_cast<uint8_t*>(UIMalloc(dataSize));
|
||||
if (srcData == nullptr) {
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(infile);
|
||||
UIFree(imgInfo);
|
||||
srcType_ = IMG_SRC_UNKNOWN;
|
||||
return false;
|
||||
}
|
||||
uint32_t n = 0;
|
||||
while (cinfo.output_scanline < cinfo.output_height) {
|
||||
jpeg_read_scanlines(&cinfo, buffer, 1); // 1: read one line each time
|
||||
for (uint16_t x = 0; x < width * 3; x += 3) { // 3: color components per pixel
|
||||
srcData[n++] = buffer[0][x + 2]; // 2: B channel
|
||||
srcData[n++] = buffer[0][x + 1]; // 1: G channel
|
||||
srcData[n++] = buffer[0][x + 0]; // 0: R channel
|
||||
srcData[n++] = 255; // 255: set alpha channel
|
||||
}
|
||||
}
|
||||
jpeg_finish_decompress(&cinfo);
|
||||
jpeg_destroy_decompress(&cinfo);
|
||||
fclose(infile);
|
||||
|
||||
imgInfo->header.width = width;
|
||||
imgInfo->header.height = height;
|
||||
imgInfo->header.colorMode = ARGB8888;
|
||||
imgInfo->dataSize = dataSize;
|
||||
imgInfo->data = srcData;
|
||||
|
||||
if (imageInfo_ != nullptr) {
|
||||
if (mallocFlag_) {
|
||||
if (imageInfo_->data != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(imageInfo_->data)));
|
||||
}
|
||||
mallocFlag_ = false;
|
||||
}
|
||||
UIFree(reinterpret_cast<void*>(const_cast<ImageInfo*>(imageInfo_)));
|
||||
imageInfo_ = nullptr;
|
||||
}
|
||||
imageInfo_ = imgInfo;
|
||||
mallocFlag_ = true;
|
||||
srcType_ = IMG_SRC_VARIABLE;
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
} // namespace OHOS
|
||||
Executable
+66
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/input_device_manager.h"
|
||||
#include "common/task_manager.h"
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
void InputDeviceManager::Init()
|
||||
{
|
||||
if (INDEV_READ_PERIOD > 0) {
|
||||
SetPeriod(INDEV_READ_PERIOD);
|
||||
TaskManager::GetInstance()->Add(this);
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::Add(InputDevice* device)
|
||||
{
|
||||
if (device == nullptr) {
|
||||
GRAPHIC_LOGE("InputDeviceManager::Add invalid param\n");
|
||||
return;
|
||||
}
|
||||
deviceList_.PushBack(device);
|
||||
}
|
||||
|
||||
void InputDeviceManager::Remove(InputDevice* device)
|
||||
{
|
||||
if (device == nullptr) {
|
||||
return;
|
||||
}
|
||||
ListNode<InputDevice*>* node = deviceList_.Begin();
|
||||
while (node != deviceList_.End()) {
|
||||
if (node->data_ == device) {
|
||||
deviceList_.Remove(node);
|
||||
return;
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::Callback()
|
||||
{
|
||||
ListNode<InputDevice*>* node = deviceList_.Begin();
|
||||
while (node != deviceList_.End()) {
|
||||
node->data_->ProcessEvent();
|
||||
node = node->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void InputDeviceManager::Clear()
|
||||
{
|
||||
deviceList_.Clear();
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/screen.h"
|
||||
#include "dock/screen_device_proxy.h"
|
||||
|
||||
namespace OHOS {
|
||||
uint16_t Screen::GetWidth()
|
||||
{
|
||||
return ScreenDeviceProxy::GetInstance()->GetScreenWidth();
|
||||
}
|
||||
|
||||
uint16_t Screen::GetHeight()
|
||||
{
|
||||
return ScreenDeviceProxy::GetInstance()->GetScreenHeight();
|
||||
}
|
||||
} // namespace OHOS
|
||||
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/screen_device_proxy.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "graphic_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
#if ENABLE_FRAME_BUFFER
|
||||
void ScreenDeviceProxy::Flush() {}
|
||||
#else
|
||||
void ScreenDeviceProxy::Flush()
|
||||
{
|
||||
flush_.Flushing();
|
||||
|
||||
if (device_ != nullptr) {
|
||||
#if ENABLE_WINDOW
|
||||
device_->Flush(bufferRect_.GetLeft(), bufferRect_.GetTop(), bufferRect_.GetRight(), bufferRect_.GetBottom(),
|
||||
gfxAlloc_.virAddr, ARGB8888);
|
||||
#else
|
||||
device_->Flush(bufferRect_.GetLeft(), bufferRect_.GetTop(), bufferRect_.GetRight(), bufferRect_.GetBottom(),
|
||||
buffer_, ARGB8888);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void ScreenDeviceProxy::OnFlushReady()
|
||||
{
|
||||
flush_.Notify();
|
||||
}
|
||||
|
||||
void ScreenDeviceProxy::OnRenderFinish()
|
||||
{
|
||||
if (device_ != nullptr) {
|
||||
device_->RenderFinish();
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenDeviceProxy::DrawAnimatorBuffer(const Rect& invalidatedArea)
|
||||
{
|
||||
Rect invalidRect = curViewRect_;
|
||||
transMap_.SetTransMapRect(curViewRect_);
|
||||
invalidRect.Join(invalidRect, transMap_.GetBoxRect());
|
||||
|
||||
if (invalidRect.Intersect(invalidRect, invalidatedArea)) {
|
||||
uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(animatorImageInfo_.header.colorMode);
|
||||
TransformDataInfo imageTranDataInfo = {animatorImageInfo_.header, animatorImageInfo_.data, pxSize, LEVEL0,
|
||||
BILINEAR};
|
||||
DrawUtils::GetInstance()->DrawTransform(invalidRect, {0, 0}, Color::Black(), OPA_OPAQUE, transMap_,
|
||||
imageTranDataInfo);
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenDeviceProxy::SetAnimatorRect(const Rect& rect)
|
||||
{
|
||||
curViewRect_ = rect;
|
||||
uint16_t bufferWidth = (width_ > curViewRect_.GetWidth()) ? curViewRect_.GetWidth() : width_;
|
||||
uint16_t bufferHeight = (height_ > curViewRect_.GetHeight()) ? curViewRect_.GetHeight() : height_;
|
||||
|
||||
animatorImageInfo_.header.colorMode = animatorBufferMode_;
|
||||
animatorImageInfo_.dataSize = bufferWidth * bufferHeight * DrawUtils::GetByteSizeByColorMode(animatorBufferMode_);
|
||||
animatorImageInfo_.header.width = bufferWidth;
|
||||
animatorImageInfo_.header.height = bufferHeight;
|
||||
animatorImageInfo_.header.reserved = 0;
|
||||
animatorImageInfo_.data = reinterpret_cast<uint8_t*>(GetBuffer());
|
||||
if (animatorImageInfo_.data == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetAnimatorbufferWidth(bufferWidth);
|
||||
if (memset_s(reinterpret_cast<void*>(const_cast<uint8_t*>(animatorImageInfo_.data)), animatorImageInfo_.dataSize, 0,
|
||||
animatorImageInfo_.dataSize) != EOK) {
|
||||
GRAPHIC_LOGE("animator buffer memset failed.");
|
||||
}
|
||||
}
|
||||
|
||||
void ScreenDeviceProxy::SetScreenSize(uint16_t width, uint16_t height)
|
||||
{
|
||||
if ((width == 0) || (height == 0)) {
|
||||
GRAPHIC_LOGE("screen size can not be zero.");
|
||||
return;
|
||||
}
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
#if !ENABLE_WINDOW && !ENABLE_FRAME_BUFFER
|
||||
if (buffer_ != nullptr) {
|
||||
UIFree(buffer_);
|
||||
}
|
||||
uint32_t bufSize = width * height * DrawUtils::GetByteSizeByColorMode(ARGB8888);
|
||||
buffer_ = static_cast<uint8_t*>(UIMalloc(bufSize));
|
||||
if (buffer_ == nullptr) {
|
||||
GRAPHIC_LOGE("screen buffer malloc failed.");
|
||||
return;
|
||||
}
|
||||
if (memset_s(buffer_, bufSize, 0, bufSize) != EOK) {
|
||||
GRAPHIC_LOGE("screen buffer memset failed.");
|
||||
UIFree(reinterpret_cast<void*>(buffer_));
|
||||
buffer_ = nullptr;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
uint8_t* ScreenDeviceProxy::GetBuffer()
|
||||
{
|
||||
flush_.Wait();
|
||||
if (useAnimatorBuff_) {
|
||||
if (animatorBufferAddr_ == nullptr) {
|
||||
GRAPHIC_LOGE("Invalid param animatorBufferAddr_.");
|
||||
return nullptr;
|
||||
}
|
||||
int32_t offset = bufferRect_.GetTop() * animatorBufferWidth_ + bufferRect_.GetLeft();
|
||||
offset *= DrawUtils::GetByteSizeByColorMode(animatorBufferMode_);
|
||||
return animatorBufferAddr_ + offset;
|
||||
}
|
||||
#if ENABLE_FRAME_BUFFER
|
||||
if (frameBufferAddr_ == nullptr) {
|
||||
GRAPHIC_LOGE("Invalid param frameBufferAddr_.");
|
||||
return nullptr;
|
||||
}
|
||||
int32_t offset = bufferRect_.GetTop() * frameBufferWidth_ + bufferRect_.GetLeft();
|
||||
offset *= DrawUtils::GetByteSizeByColorMode(frameBufferMode_);
|
||||
return frameBufferAddr_ + offset;
|
||||
#elif ENABLE_WINDOW
|
||||
return gfxAlloc_.virAddr;
|
||||
#else
|
||||
return buffer_;
|
||||
#endif
|
||||
}
|
||||
|
||||
ColorMode ScreenDeviceProxy::GetBufferMode()
|
||||
{
|
||||
if (useAnimatorBuff_) {
|
||||
return animatorBufferMode_;
|
||||
}
|
||||
#if ENABLE_FRAME_BUFFER
|
||||
return frameBufferMode_;
|
||||
#else
|
||||
return ARGB8888;
|
||||
#endif
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/task.h"
|
||||
#include "common/task_manager.h"
|
||||
#include "hal_tick.h"
|
||||
|
||||
namespace OHOS {
|
||||
void Task::TaskExecute()
|
||||
{
|
||||
uint32_t elp = HALTick::GetInstance().GetElapseTime(lastRun_);
|
||||
if (elp >= period_) {
|
||||
lastRun_ = HALTick::GetInstance().GetTime();
|
||||
Callback();
|
||||
}
|
||||
}
|
||||
|
||||
void Task::Init()
|
||||
{
|
||||
SetPeriod(period_);
|
||||
TaskManager::GetInstance()->Add(this);
|
||||
}
|
||||
}
|
||||
Executable
+368
@@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/text.h"
|
||||
#include "common/typed_text.h"
|
||||
#include "draw/draw_label.h"
|
||||
#include "font/ui_font.h"
|
||||
#include "graphic_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
Text::TextLine Text::textLine_[MAX_LINE_COUNT] = {{0}};
|
||||
|
||||
Text::Text()
|
||||
: text_(nullptr),
|
||||
fontId_(0),
|
||||
fontSize_(0),
|
||||
textSize_({0, 0}),
|
||||
needRefresh_(false),
|
||||
expandWidth_(false),
|
||||
expandHeight_(false),
|
||||
direct_(TEXT_DIRECT_LTR),
|
||||
horizontalAlign_(TEXT_ALIGNMENT_LEFT),
|
||||
verticalAlign_(TEXT_ALIGNMENT_TOP)
|
||||
{
|
||||
SetFont(DEFAULT_VECTOR_FONT_FILENAME, DEFAULT_VECTOR_FONT_SIZE);
|
||||
}
|
||||
|
||||
Text::~Text()
|
||||
{
|
||||
if (text_ != nullptr) {
|
||||
UIFree(text_);
|
||||
text_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetText(const char* text)
|
||||
{
|
||||
if (text == nullptr) {
|
||||
return;
|
||||
}
|
||||
uint32_t textLen = static_cast<uint32_t>(strlen(text));
|
||||
if (textLen > MAX_TEXT_LENGTH) {
|
||||
return;
|
||||
}
|
||||
if (text_ != nullptr) {
|
||||
if (strcmp(text, text_) == 0) {
|
||||
return;
|
||||
}
|
||||
UIFree(text_);
|
||||
text_ = nullptr;
|
||||
}
|
||||
text_ = static_cast<char*>(UIMalloc(++textLen));
|
||||
if (text_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (memcpy_s(text_, textLen, text, textLen) != EOK) {
|
||||
UIFree(text_);
|
||||
text_ = nullptr;
|
||||
return;
|
||||
}
|
||||
needRefresh_ = true;
|
||||
}
|
||||
|
||||
void Text::SetFont(const char* name, uint8_t size)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (UIFont::GetInstance()->IsVectorFont()) {
|
||||
uint8_t fontId = UIFont::GetInstance()->GetFontId(name);
|
||||
if ((fontId != GetTotalFontId()) && ((fontId_ != fontId) || (fontSize_ != size))) {
|
||||
fontId_ = fontId;
|
||||
fontSize_ = size;
|
||||
needRefresh_ = true;
|
||||
}
|
||||
} else {
|
||||
uint8_t fontId = UIFont::GetInstance()->GetFontId(name, size);
|
||||
SetFontId(fontId);
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetFont(const char* name, uint8_t size, char*& destName, uint8_t& destSize)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
return;
|
||||
}
|
||||
uint32_t nameLen = static_cast<uint32_t>(strlen(name));
|
||||
if (nameLen > MAX_TEXT_LENGTH) {
|
||||
return;
|
||||
}
|
||||
if (destName != nullptr) {
|
||||
if (strcmp(destName, name) == 0) {
|
||||
destSize = size;
|
||||
return;
|
||||
}
|
||||
UIFree(destName);
|
||||
destName = nullptr;
|
||||
}
|
||||
if (nameLen != 0) {
|
||||
/* one more to store '\0' */
|
||||
destName = static_cast<char*>(UIMalloc(++nameLen));
|
||||
if (destName == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (memcpy_s(destName, nameLen, name, nameLen) != EOK) {
|
||||
UIFree(destName);
|
||||
destName = nullptr;
|
||||
return;
|
||||
}
|
||||
destSize = size;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::SetFontId(uint8_t fontId)
|
||||
{
|
||||
if ((fontId >= GetTotalFontId()) || (fontId_ == fontId)) {
|
||||
GRAPHIC_LOGE("Text::SetFontId invalid fontId(%d)", fontId);
|
||||
return;
|
||||
}
|
||||
UITextLanguageFontParam* fontParam = GetTextLangFontsTable(fontId);
|
||||
if (fontParam == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (UIFont::GetInstance()->IsVectorFont()) {
|
||||
uint8_t fontId = UIFont::GetInstance()->GetFontId(fontParam->ttfName);
|
||||
if ((fontId != GetTotalFontId()) && ((fontId_ != fontId) || (fontSize_ != fontParam->size))) {
|
||||
fontId_ = fontId;
|
||||
fontSize_ = fontParam->size;
|
||||
needRefresh_ = true;
|
||||
}
|
||||
} else {
|
||||
fontId_ = fontId;
|
||||
fontSize_ = fontParam->size;
|
||||
needRefresh_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::ReMeasureTextSize(const Rect& textRect, const Style& style)
|
||||
{
|
||||
if (fontSize_ == 0) {
|
||||
return;
|
||||
}
|
||||
UIFont::GetInstance()->SetCurrentFontId(fontId_, fontSize_);
|
||||
int16_t maxWidth = (expandWidth_ ? COORD_MAX : textRect.GetWidth());
|
||||
if (maxWidth > 0) {
|
||||
textSize_ = TypedText::GetTextSize(text_, style.letterSpace_, style.lineSpace_, maxWidth);
|
||||
FontHeader head;
|
||||
if (UIFont::GetInstance()->GetCurrentFontHeader(head) != 0) {
|
||||
return;
|
||||
}
|
||||
textSize_.y += fontSize_ - head.ascender;
|
||||
}
|
||||
}
|
||||
|
||||
void Text::OnDraw(const Rect& invalidatedArea,
|
||||
const Rect& viewOrigRect,
|
||||
const Rect& textRect,
|
||||
int16_t offsetX,
|
||||
const Style& style,
|
||||
uint16_t ellipsisIndex,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
if ((text_ == nullptr) || (strlen(text_) == 0) || (fontSize_ == 0)) {
|
||||
return;
|
||||
}
|
||||
UIFont::GetInstance()->SetCurrentFontId(fontId_, fontSize_);
|
||||
Rect mask = invalidatedArea;
|
||||
|
||||
if (mask.Intersect(mask, textRect)) {
|
||||
Draw(mask, textRect, style, offsetX, ellipsisIndex, opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void Text::Draw(const Rect& mask,
|
||||
const Rect& coords,
|
||||
const Style& style,
|
||||
int16_t offsetX,
|
||||
uint16_t ellipsisIndex,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
Point offset = {offsetX, 0};
|
||||
int16_t lineMaxWidth = expandWidth_ ? textSize_.x : coords.GetWidth();
|
||||
int16_t lineHeight = UIFont::GetInstance()->GetHeight() + style.lineSpace_;
|
||||
uint16_t lineBegin = 0;
|
||||
uint32_t maxLineBytes = 0;
|
||||
uint16_t lineCount = GetLine(lineMaxWidth, style.letterSpace_, ellipsisIndex, maxLineBytes);
|
||||
Point pos;
|
||||
pos.y = TextPositionY(coords, (lineCount * lineHeight - style.lineSpace_));
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.textOpa_);
|
||||
for (int i = 0; i < lineCount; i++) {
|
||||
if (pos.y > mask.GetBottom()) {
|
||||
return;
|
||||
}
|
||||
int16_t nextLine = pos.y + lineHeight;
|
||||
if (nextLine >= mask.GetTop()) {
|
||||
pos.x = LineStartPos(coords, textLine_[i].linePixelWidth);
|
||||
LabelLineInfo labelLine{pos,
|
||||
offset,
|
||||
mask,
|
||||
lineHeight,
|
||||
textLine_[i].lineBytes,
|
||||
0,
|
||||
opa,
|
||||
style,
|
||||
&text_[lineBegin],
|
||||
textLine_[i].lineBytes,
|
||||
lineBegin,
|
||||
fontId_,
|
||||
fontSize_,
|
||||
0,
|
||||
static_cast<UITextLanguageDirect>(direct_),
|
||||
nullptr};
|
||||
DrawLabel::DrawTextOneLine(labelLine);
|
||||
if ((i == (lineCount - 1)) && (ellipsisIndex != TEXT_ELLIPSIS_END_INV)) {
|
||||
labelLine.offset.x = 0;
|
||||
labelLine.text = TEXT_ELLIPSIS;
|
||||
labelLine.lineLength = TEXT_ELLIPSIS_DOT_NUM;
|
||||
labelLine.length = TEXT_ELLIPSIS_DOT_NUM;
|
||||
DrawLabel::DrawTextOneLine(labelLine);
|
||||
}
|
||||
}
|
||||
lineBegin += textLine_[i].lineBytes;
|
||||
pos.y = nextLine;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t Text::TextPositionY(const Rect& textRect, int16_t textHeight)
|
||||
{
|
||||
int16_t yOffset = 0;
|
||||
if (!expandHeight_ && (verticalAlign_ != TEXT_ALIGNMENT_TOP) && (textRect.GetHeight() > textHeight)) {
|
||||
if (verticalAlign_ == TEXT_ALIGNMENT_CENTER) {
|
||||
yOffset = (textRect.GetHeight() - textHeight) >> 1;
|
||||
} else if (verticalAlign_ == TEXT_ALIGNMENT_BOTTOM) {
|
||||
yOffset = textRect.GetHeight() - textHeight;
|
||||
}
|
||||
}
|
||||
return textRect.GetY() + yOffset;
|
||||
}
|
||||
|
||||
int16_t Text::LineStartPos(const Rect& textRect, uint16_t lineWidth)
|
||||
{
|
||||
int16_t xOffset = 0;
|
||||
int16_t rectWidth = textRect.GetWidth();
|
||||
if (horizontalAlign_ == TEXT_ALIGNMENT_CENTER) {
|
||||
xOffset = (direct_ == TEXT_DIRECT_RTL) ? ((rectWidth + lineWidth + 1) >> 1) : ((rectWidth - lineWidth) >> 1);
|
||||
} else if (horizontalAlign_ == TEXT_ALIGNMENT_RIGHT) {
|
||||
xOffset = (direct_ == TEXT_DIRECT_RTL) ? rectWidth : (rectWidth - lineWidth);
|
||||
} else {
|
||||
xOffset = (direct_ == TEXT_DIRECT_RTL) ? lineWidth : 0;
|
||||
}
|
||||
return textRect.GetX() + xOffset;
|
||||
}
|
||||
|
||||
uint16_t Text::GetLine(int16_t width, uint8_t letterSpace, uint16_t ellipsisIndex, uint32_t& maxLineBytes)
|
||||
{
|
||||
if (text_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
uint16_t lineNum = 0;
|
||||
uint32_t textLen = GetTextStrLen();
|
||||
if ((ellipsisIndex != TEXT_ELLIPSIS_END_INV) && (ellipsisIndex < textLen)) {
|
||||
textLen = ellipsisIndex;
|
||||
}
|
||||
uint32_t begin = 0;
|
||||
while ((begin < textLen) && (text_[begin] != '\0') && (lineNum < MAX_LINE_COUNT)) {
|
||||
begin += GetTextLine(begin, textLen, width, lineNum, letterSpace);
|
||||
if (maxLineBytes < textLine_[lineNum].lineBytes) {
|
||||
maxLineBytes = textLine_[lineNum].lineBytes;
|
||||
}
|
||||
lineNum++;
|
||||
}
|
||||
if ((lineNum != 0) && (ellipsisIndex != TEXT_ELLIPSIS_END_INV)) {
|
||||
uint16_t ellipsisWidth = UIFont::GetInstance()->GetWidth('.', 0) + letterSpace;
|
||||
textLine_[lineNum - 1].linePixelWidth += ellipsisWidth * TEXT_ELLIPSIS_DOT_NUM;
|
||||
}
|
||||
return lineNum;
|
||||
}
|
||||
|
||||
uint32_t Text::GetTextStrLen()
|
||||
{
|
||||
return strlen(text_);
|
||||
}
|
||||
|
||||
uint32_t Text::GetTextLine(uint32_t begin, uint32_t textLen, int16_t width, uint16_t lineNum, uint8_t letterSpace)
|
||||
{
|
||||
uint16_t nextLineBytes = TypedText::GetNextLine(&text_[begin], letterSpace, width);
|
||||
if (nextLineBytes + begin > textLen) {
|
||||
nextLineBytes = textLen - begin;
|
||||
}
|
||||
textLine_[lineNum].lineBytes = nextLineBytes;
|
||||
textLine_[lineNum].linePixelWidth =
|
||||
static_cast<uint16_t>(TypedText::GetTextWidth(&text_[begin], nextLineBytes, letterSpace));
|
||||
return nextLineBytes;
|
||||
}
|
||||
|
||||
uint16_t Text::GetEllipsisIndex(const Rect& textRect, const Style& style)
|
||||
{
|
||||
if ((textSize_.y <= textRect.GetHeight()) || (TypedText::GetUTF8CharacterSize(text_) <= TEXT_ELLIPSIS_DOT_NUM)) {
|
||||
return TEXT_ELLIPSIS_END_INV;
|
||||
}
|
||||
UIFont* fontEngine = UIFont::GetInstance();
|
||||
fontEngine->SetCurrentFontId(fontId_, fontSize_);
|
||||
int16_t letterWidth = fontEngine->GetWidth('.', 0) + style.letterSpace_;
|
||||
Point p;
|
||||
p.x = textRect.GetWidth() - letterWidth * TEXT_ELLIPSIS_DOT_NUM;
|
||||
p.y = textRect.GetHeight();
|
||||
int16_t height = fontEngine->GetHeight() + style.lineSpace_;
|
||||
if (height) {
|
||||
p.y -= p.y % height;
|
||||
}
|
||||
|
||||
p.y -= style.lineSpace_;
|
||||
return GetLetterIndexByPosition(textRect, style, p);
|
||||
}
|
||||
|
||||
uint16_t Text::GetLetterIndexByPosition(const Rect& textRect, const Style& style, const Point& pos)
|
||||
{
|
||||
if (text_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
uint32_t lineStart = 0;
|
||||
uint32_t nextLineStart = 0;
|
||||
|
||||
uint16_t lineHeight = UIFont::GetInstance()->GetHeight();
|
||||
int16_t y = 0;
|
||||
uint32_t textLen = static_cast<uint32_t>(strlen(text_));
|
||||
while ((lineStart < textLen) && (text_[lineStart] != '\0')) {
|
||||
nextLineStart += TypedText::GetNextLine(&text_[lineStart], style.letterSpace_, textRect.GetWidth());
|
||||
if (pos.y <= y + lineHeight) {
|
||||
break;
|
||||
}
|
||||
y += lineHeight + style.lineSpace_;
|
||||
lineStart = nextLineStart;
|
||||
}
|
||||
/* Calculate the x coordinate */
|
||||
int16_t x = 0;
|
||||
uint32_t i = lineStart;
|
||||
uint32_t pre = i;
|
||||
while (i < nextLineStart - 1) {
|
||||
uint32_t letter = TypedText::GetUTF8Next(text_, i, i);
|
||||
x += UIFont::GetInstance()->GetWidth(letter, 0);
|
||||
if (pos.x < x) {
|
||||
i = pre;
|
||||
break;
|
||||
}
|
||||
x += style.letterSpace_;
|
||||
pre = i;
|
||||
}
|
||||
if (i >= (GetTextStrLen() - TEXT_ELLIPSIS_DOT_NUM)) {
|
||||
return TEXT_ELLIPSIS_END_INV;
|
||||
} else {
|
||||
return static_cast<uint16_t>(i);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+384
@@ -0,0 +1,384 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/typed_text.h"
|
||||
#include "font/ui_font.h"
|
||||
#include "font/ui_font_adaptor.h"
|
||||
#include "graphic_log.h"
|
||||
#include "mem_api.h"
|
||||
#include "transform.h"
|
||||
|
||||
namespace OHOS {
|
||||
#ifndef _FONT_TOOL
|
||||
Point TypedText::GetTextSize(const char* text, int16_t letterSpace, int16_t lineSpace, int16_t maxWidth)
|
||||
{
|
||||
Point size{0, 0};
|
||||
|
||||
if (text == nullptr) {
|
||||
GRAPHIC_LOGE("TypedText::GetTextSize invalid parameter");
|
||||
return size;
|
||||
}
|
||||
|
||||
uint32_t lineBegin = 0;
|
||||
uint32_t newLineBegin = 0;
|
||||
uint16_t letterHeight = UIFont::GetInstance()->GetHeight();
|
||||
|
||||
while (text[lineBegin] != '\0') {
|
||||
int16_t lineWidth = maxWidth;
|
||||
newLineBegin += UIFontAdaptor::GetNextLineAndWidth(&text[lineBegin], letterSpace, lineWidth);
|
||||
if (newLineBegin == lineBegin) {
|
||||
break;
|
||||
}
|
||||
size.y += letterHeight + lineSpace;
|
||||
size.x = MATH_MAX(lineWidth, size.x);
|
||||
lineBegin = newLineBegin;
|
||||
}
|
||||
|
||||
if ((lineBegin != 0) && ((text[lineBegin - 1] == '\n') || (text[lineBegin - 1] == '\r'))) {
|
||||
size.y += letterHeight + lineSpace;
|
||||
}
|
||||
|
||||
if (size.y == 0) {
|
||||
size.y = letterHeight;
|
||||
} else {
|
||||
size.y -= lineSpace;
|
||||
}
|
||||
return size;
|
||||
}
|
||||
|
||||
Rect TypedText::GetArcTextRect(const char* text,
|
||||
const Point& arcCenter,
|
||||
int16_t letterSpace,
|
||||
UIArcLabel::TextOrientation orientation,
|
||||
const UIArcLabel::ArcTextInfo& arcTextInfo)
|
||||
{
|
||||
if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) {
|
||||
GRAPHIC_LOGE("TypedText::GetArcTextRect invalid parameter\n");
|
||||
return Rect();
|
||||
}
|
||||
|
||||
uint16_t letterHeight = UIFont::GetInstance()->GetHeight();
|
||||
bool xorFlag = (orientation == UIArcLabel::TextOrientation::INSIDE) ^ (arcTextInfo.direct == TEXT_DIRECT_LTR);
|
||||
float posX = 0;
|
||||
float posY = 0;
|
||||
uint32_t i = arcTextInfo.lineStart;
|
||||
float angle = arcTextInfo.startAngle;
|
||||
Rect rect;
|
||||
Rect rectLetter;
|
||||
TransformMap transform;
|
||||
while (i < arcTextInfo.lineEnd) {
|
||||
uint32_t tmp = i;
|
||||
uint32_t letter = GetUTF8Next(text, tmp, i);
|
||||
if (letter == 0) {
|
||||
continue;
|
||||
}
|
||||
if ((letter == '\r') || (letter == '\n')) {
|
||||
break;
|
||||
}
|
||||
uint16_t letterWidth = UIFont::GetInstance()->GetWidth(letter, 0);
|
||||
if (tmp == arcTextInfo.lineStart) {
|
||||
angle += xorFlag ? GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius,
|
||||
arcTextInfo.direct, orientation)
|
||||
: 0;
|
||||
GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
|
||||
rect.SetPosition(MATH_ROUND(posX), MATH_ROUND(posY));
|
||||
}
|
||||
rectLetter.SetPosition(MATH_ROUND(posX), MATH_ROUND(posY));
|
||||
rectLetter.Resize(letterWidth, letterHeight);
|
||||
transform.SetTransMapRect(rectLetter);
|
||||
|
||||
uint16_t arcLen = letterWidth + letterSpace;
|
||||
if (arcLen == 0) {
|
||||
continue;
|
||||
}
|
||||
float incrementAngle = GetAngleForArcLen(static_cast<float>(arcLen), letterHeight, arcTextInfo.radius,
|
||||
arcTextInfo.direct, orientation);
|
||||
float rotateAngle =
|
||||
(orientation == UIArcLabel::TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE);
|
||||
// 2: letterWidth's half
|
||||
float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (2 * arcLen));
|
||||
rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle);
|
||||
|
||||
transform.Rotate(MATH_ROUND(rotateAngle), Vector2<float>(0, 0));
|
||||
rect.Join(rect, transform.GetBoxRect());
|
||||
|
||||
angle += incrementAngle;
|
||||
GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
float TypedText::GetAngleForArcLen(float len,
|
||||
uint16_t height,
|
||||
uint16_t radius,
|
||||
UITextLanguageDirect direct,
|
||||
UIArcLabel::TextOrientation orientation)
|
||||
{
|
||||
float realRadius =
|
||||
static_cast<float>((orientation == UIArcLabel::TextOrientation::OUTSIDE) ? (radius + height) : radius);
|
||||
float angle = static_cast<float>(len * SEMICIRCLE_IN_DEGREE) / (UI_PI * realRadius);
|
||||
return (direct == TEXT_DIRECT_LTR) ? angle : -angle;
|
||||
}
|
||||
|
||||
void TypedText::GetArcLetterPos(const Point& arcCenter, uint16_t radius, float angle, float& posX, float& posY)
|
||||
{
|
||||
posX = arcCenter.x + (static_cast<float>(radius) * Sin(MATH_ROUND(angle)));
|
||||
posY = arcCenter.y - (static_cast<float>(radius) * Sin(MATH_ROUND(angle + QUARTER_IN_DEGREE)));
|
||||
}
|
||||
|
||||
uint32_t TypedText::GetNextLine(const char* text, int16_t letterSpace, int16_t maxWidth)
|
||||
{
|
||||
uint32_t lastBreakPos = 0;
|
||||
int16_t curW;
|
||||
uint32_t index = 0;
|
||||
uint32_t tmp = 0;
|
||||
if (GetWrapPoint(text, index)) {
|
||||
return index;
|
||||
}
|
||||
while (true) {
|
||||
curW = TypedText::GetTextWidth(text, index, letterSpace);
|
||||
if (curW > maxWidth) {
|
||||
index = lastBreakPos;
|
||||
if (lastBreakPos == 0) {
|
||||
curW = 0;
|
||||
uint32_t i = 0;
|
||||
uint32_t letter;
|
||||
uint16_t letterWidth;
|
||||
while (text[i] != '\0') {
|
||||
tmp = i;
|
||||
letter = TypedText::GetUTF8Next(text, tmp, i);
|
||||
letterWidth = UIFont::GetInstance()->GetWidth(letter, 0);
|
||||
curW += letterWidth;
|
||||
if (letterWidth > 0) {
|
||||
curW += letterSpace;
|
||||
}
|
||||
if (curW > maxWidth) {
|
||||
index = lastBreakPos;
|
||||
return index;
|
||||
}
|
||||
lastBreakPos = i;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if ((index > 0) && (index < strlen(text)) && ((text[index - 1] == '\r') || (text[index - 1] == '\n'))) {
|
||||
break;
|
||||
}
|
||||
lastBreakPos = index;
|
||||
if (text[index] == '\0') {
|
||||
break;
|
||||
}
|
||||
if (GetWrapPoint(text + index, tmp)) {
|
||||
return index + tmp;
|
||||
}
|
||||
index += tmp;
|
||||
if (lastBreakPos == index) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return index;
|
||||
}
|
||||
|
||||
bool TypedText::GetWrapPoint(const char* text, uint32_t& breakPoint)
|
||||
{
|
||||
breakPoint = 0;
|
||||
uint32_t j = 0;
|
||||
uint32_t letter = 0;
|
||||
if (text == nullptr) {
|
||||
return true;
|
||||
}
|
||||
|
||||
while (text[breakPoint] != '\0') {
|
||||
letter = GetUTF8Next(text, breakPoint, j);
|
||||
breakPoint = j;
|
||||
if ((letter == ' ') || (letter == '.') || (letter == ',') || (letter == '!') || (letter == '=')
|
||||
|| (letter == '?')) {
|
||||
return false;
|
||||
}
|
||||
if (letter == '\n') {
|
||||
return true;
|
||||
}
|
||||
if ((letter == '\r') && (GetUTF8Next(text, breakPoint, j) == '\n')) {
|
||||
breakPoint = j;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
int16_t TypedText::GetTextWidth(const char* text, uint16_t length, int16_t letterSpace)
|
||||
{
|
||||
if ((text == nullptr) || (length == 0) || (length > strlen(text))) {
|
||||
GRAPHIC_LOGE("TypedText::GetTextWidth invalid parameter\n");
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t i = 0;
|
||||
uint16_t width = 0;
|
||||
uint32_t letter;
|
||||
|
||||
while (i < length) {
|
||||
letter = GetUTF8Next(text, i, i);
|
||||
if ((letter == 0) || (letter == '\n') || (letter == '\r')) {
|
||||
continue;
|
||||
}
|
||||
uint16_t charWidth = UIFont::GetInstance()->GetWidth(letter, 0);
|
||||
width += charWidth + letterSpace;
|
||||
}
|
||||
if (width > 0) {
|
||||
width -= letterSpace;
|
||||
}
|
||||
return width;
|
||||
}
|
||||
#endif // _FONT_TOOL
|
||||
|
||||
uint8_t TypedText::GetUTF8OneCharacterSize(const char* str)
|
||||
{
|
||||
if ((str[0] & 0x80) == 0) {
|
||||
return 1;
|
||||
} else if ((str[0] & 0xE0) == 0xC0) {
|
||||
return 2; // 2: 2 bytes
|
||||
} else if ((str[0] & 0xF0) == 0xE0) {
|
||||
return 3; // 3: 3 bytes
|
||||
} else if ((str[0] & 0xF8) == 0xF0) {
|
||||
return 4; // 4: 4 bytes
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t TypedText::GetUTF8Next(const char* text, uint32_t i, uint32_t& j)
|
||||
{
|
||||
uint32_t unicode = 0;
|
||||
if (text == nullptr) {
|
||||
GRAPHIC_LOGE("text invalid parameter");
|
||||
return 0;
|
||||
}
|
||||
|
||||
j = i;
|
||||
uint8_t lettetSize = GetUTF8OneCharacterSize(text + i);
|
||||
switch (lettetSize) {
|
||||
case 1:
|
||||
unicode = text[j];
|
||||
break;
|
||||
case 2: // 2: letter size
|
||||
unicode = static_cast<uint32_t>(text[j] & 0x1F) << UTF8_TO_UNICODE_SHIFT1;
|
||||
j++;
|
||||
if ((text[j] & 0xC0) != 0x80) {
|
||||
return 0;
|
||||
}
|
||||
unicode += (text[j] & 0x3F);
|
||||
break;
|
||||
case 3: // 3: letter size
|
||||
unicode = static_cast<uint32_t>(text[j] & 0x0F) << UTF8_TO_UNICODE_SHIFT2;
|
||||
unicode += static_cast<uint32_t>(text[++j] & 0x3F) << UTF8_TO_UNICODE_SHIFT1;
|
||||
unicode += (text[++j] & 0x3F);
|
||||
break;
|
||||
case 4: // 4: letter size
|
||||
unicode = static_cast<uint32_t>(text[j] & 0x07) << UTF8_TO_UNICODE_SHIFT3;
|
||||
unicode += static_cast<uint32_t>(text[++j] & 0x3F) << UTF8_TO_UNICODE_SHIFT2;
|
||||
unicode += static_cast<uint32_t>(text[++j] & 0x3F) << UTF8_TO_UNICODE_SHIFT1;
|
||||
unicode += text[++j] & 0x3F;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
j++;
|
||||
return unicode;
|
||||
}
|
||||
|
||||
uint32_t TypedText::GetByteIndexFromUTF8Id(const char* text, uint32_t utf8Id)
|
||||
{
|
||||
if (text == nullptr) {
|
||||
GRAPHIC_LOGE("TypedText::GetByteIndexFromUTF8Id text invalid parameter\n");
|
||||
return 0;
|
||||
}
|
||||
uint32_t byteIndex = 0;
|
||||
for (uint32_t i = 0; i < utf8Id; i++) {
|
||||
byteIndex += GetUTF8OneCharacterSize(&text[byteIndex]);
|
||||
}
|
||||
|
||||
return byteIndex;
|
||||
}
|
||||
|
||||
uint32_t TypedText::GetUTF8CharacterSize(const char* text, uint32_t byteIndex)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint32_t size = 0;
|
||||
|
||||
if (text == nullptr) {
|
||||
GRAPHIC_LOGE("TypedText::GetUTF8CharacterSize text invalid parameter\n");
|
||||
return 0;
|
||||
}
|
||||
while ((text[i] != '\0') && (i < byteIndex)) {
|
||||
GetUTF8Next(text, i, i);
|
||||
size++;
|
||||
}
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
void TypedText::Utf8ToUtf16(const char* utf8Str, uint16_t* utf16Str, uint32_t len)
|
||||
{
|
||||
if ((utf8Str == nullptr) || (utf16Str == nullptr)) {
|
||||
GRAPHIC_LOGE("utf8Str or u16Str is null");
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t cnt = 0;
|
||||
while (utf8Str[i] != '\0') {
|
||||
uint32_t unicode = GetUTF8Next(utf8Str, i, i);
|
||||
if (cnt < len) {
|
||||
if (unicode <= MAX_UINT16_LOW_SCOPE) {
|
||||
utf16Str[cnt] = (unicode & MAX_UINT16_LOW_SCOPE);
|
||||
} else if (unicode <= MAX_UINT16_HIGH_SCOPE) {
|
||||
if (cnt + 1 < len) {
|
||||
utf16Str[cnt] = static_cast<uint16_t>(UTF16_LOW_PARAM + (unicode & UTF16_LOW_MASK)); // low
|
||||
cnt++;
|
||||
utf16Str[cnt] = static_cast<uint16_t>(UTF16_HIGH_PARAM1 + (unicode >> UTF16_HIGH_SHIFT) -
|
||||
UTF16_HIGH_PARAM2); // high
|
||||
}
|
||||
} else {
|
||||
GRAPHIC_LOGE("Invalid unicode");
|
||||
return;
|
||||
}
|
||||
cnt++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t TypedText::GetUtf16Cnt(const char* utf8Str)
|
||||
{
|
||||
if (utf8Str == nullptr) {
|
||||
GRAPHIC_LOGE("text invalid parameter");
|
||||
return 0;
|
||||
}
|
||||
uint32_t len = 0;
|
||||
uint32_t i = 0;
|
||||
|
||||
while (utf8Str[i] != '\0') {
|
||||
uint32_t unicode = GetUTF8Next(utf8Str, i, i);
|
||||
if (unicode <= MAX_UINT16_LOW_SCOPE) {
|
||||
len++;
|
||||
} else if (unicode <= MAX_UINT16_HIGH_SCOPE) {
|
||||
len += 2; // 2: low and high, two uint16_t numbers
|
||||
} else {
|
||||
GRAPHIC_LOGE("Invalid unicode");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return len;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+83
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_TYPE_TEXT_H
|
||||
#define GRAPHIC_LITE_TYPE_TEXT_H
|
||||
#include "common/text.h"
|
||||
#include "graphic_config.h"
|
||||
#ifndef _FONT_TOOL
|
||||
#include "components/ui_arc_label.h"
|
||||
#include "font/ui_font_header.h"
|
||||
#include "geometry2d.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
#ifndef _FONT_TOOL
|
||||
class TypedText : public HeapBase {
|
||||
public:
|
||||
static constexpr uint32_t MAX_UINT16_LOW_SCOPE = 0xFFFF;
|
||||
static constexpr uint32_t MAX_UINT16_HIGH_SCOPE = 0xEFFFF;
|
||||
static constexpr uint32_t UTF16_LOW_MASK = 0x03FF;
|
||||
static constexpr uint32_t UTF16_LOW_PARAM = 56320;
|
||||
static constexpr uint32_t UTF16_HIGH_PARAM1 = 55296;
|
||||
static constexpr uint8_t UTF16_HIGH_PARAM2 = 64;
|
||||
static constexpr uint8_t UTF16_HIGH_SHIFT = 10;
|
||||
static constexpr uint8_t UTF8_TO_UNICODE_SHIFT1 = 6;
|
||||
static constexpr uint8_t UTF8_TO_UNICODE_SHIFT2 = 12;
|
||||
static constexpr uint8_t UTF8_TO_UNICODE_SHIFT3 = 18;
|
||||
|
||||
static Point GetTextSize(const char* text,
|
||||
int16_t letterSpace,
|
||||
int16_t lineSpace,
|
||||
int16_t maxWidth);
|
||||
|
||||
static uint32_t GetNextLine(const char* text,
|
||||
int16_t letterSpace,
|
||||
int16_t maxWidth);
|
||||
|
||||
static int16_t GetTextWidth(const char* text,
|
||||
uint16_t length,
|
||||
int16_t letterSpace);
|
||||
|
||||
static Rect GetArcTextRect(const char* text,
|
||||
const Point& arcCenter,
|
||||
int16_t letterSpace,
|
||||
UIArcLabel::TextOrientation orientation,
|
||||
const UIArcLabel::ArcTextInfo& arcTextInfo);
|
||||
|
||||
static float GetAngleForArcLen(float len,
|
||||
uint16_t height,
|
||||
uint16_t radius,
|
||||
UITextLanguageDirect direct,
|
||||
UIArcLabel::TextOrientation orientation);
|
||||
|
||||
static void GetArcLetterPos(const Point& arcCenter, uint16_t radius, float angle, float& posX, float& posY);
|
||||
|
||||
#else // _FONT_TOOL
|
||||
class TypedText {
|
||||
public:
|
||||
#endif // _FONT_TOOL
|
||||
static uint32_t GetUTF8Next(const char* text, uint32_t i, uint32_t& j);
|
||||
static uint8_t GetUTF8OneCharacterSize(const char* str);
|
||||
static uint32_t GetByteIndexFromUTF8Id(const char* text, uint32_t utf8Id);
|
||||
static uint32_t GetUTF8CharacterSize(const char* text, uint32_t byteIndex = UINT32_MAX);
|
||||
static void Utf8ToUtf16(const char* utf8Str, uint16_t* utf16Str, uint32_t len);
|
||||
static uint32_t GetUtf16Cnt(const char* utf8Str);
|
||||
|
||||
private:
|
||||
static bool GetWrapPoint(const char* text, uint32_t& breakPoint);
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_TYPE_TEXT_H
|
||||
Executable
+55
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "font/ui_font.h"
|
||||
#include "font/ui_font_header.h"
|
||||
|
||||
namespace OHOS {
|
||||
UITextLanguageFontParam* GetTextLangFontsTable(uint8_t langFontId)
|
||||
{
|
||||
// Need to be implemented
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint8_t GetTotalLangId()
|
||||
{
|
||||
// Need to be implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t GetBitmapFontIdMax()
|
||||
{
|
||||
// Need to be implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t GetTotalFontId()
|
||||
{
|
||||
// Need to be implemented
|
||||
return 0xFF;
|
||||
}
|
||||
|
||||
uint16_t GetTotalTextId()
|
||||
{
|
||||
// Need to be implemented
|
||||
return 0;
|
||||
}
|
||||
|
||||
LangTextParam* GetLangTextDefaultParamTable()
|
||||
{
|
||||
// Need to be implemented
|
||||
return nullptr;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+633
@@ -0,0 +1,633 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/root_view.h"
|
||||
|
||||
#include "common/screen.h"
|
||||
#include "core/render_manager.h"
|
||||
#include "dock/screen_device_proxy.h"
|
||||
#include "graphic_log.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "window/window_impl.h"
|
||||
#endif
|
||||
namespace OHOS {
|
||||
namespace {
|
||||
#if LOCAL_RENDER
|
||||
const constexpr uint8_t MAX_SPLIT_NUM = 32; // split at most 32 parts
|
||||
// view along with its parents and siblings are at most 128
|
||||
const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH * 2;
|
||||
#else
|
||||
const constexpr uint8_t VIEW_STACK_DEPTH = COMPONENT_NESTING_DEPTH;
|
||||
#endif
|
||||
static Rect g_maskStack[COMPONENT_NESTING_DEPTH];
|
||||
static UIView* g_viewStack[VIEW_STACK_DEPTH];
|
||||
} // namespace
|
||||
RootView::RootView()
|
||||
{
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_init(&lock_, nullptr);
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
Window* RootView::GetBoundWindow() const
|
||||
{
|
||||
return boundWindow_;
|
||||
}
|
||||
#endif
|
||||
|
||||
inline bool RootView::IntersectScreenRect(Rect& rect)
|
||||
{
|
||||
#if ENABLE_WINDOW
|
||||
Rect screenRect = GetRect();
|
||||
#else
|
||||
Rect screenRect(0, 0, Screen::GetInstance().GetWidth() - 1, Screen::GetInstance().GetHeight() - 1);
|
||||
#endif
|
||||
return rect.Intersect(rect, screenRect);
|
||||
}
|
||||
|
||||
#if LOCAL_RENDER
|
||||
static void DivideInvalidateRect(const Rect& originRect, Rect& leftoverRect, Vector<Rect>& splitRects)
|
||||
{
|
||||
Rect mask;
|
||||
if (!mask.Intersect(originRect, leftoverRect)) {
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* +---+---+---+
|
||||
* | | A | | originRect :A+B
|
||||
* | +---+ | leftoverRect :A->0
|
||||
* | B | mask :A
|
||||
* +-----------+
|
||||
*/
|
||||
if (originRect.IsContains(leftoverRect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t reserveCnt = MAX_SPLIT_NUM - splitRects.Size();
|
||||
if (reserveCnt <= 0) {
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mask.GetWidth() == leftoverRect.GetWidth()) {
|
||||
/*
|
||||
* +---+
|
||||
* | A | originRect :B+C
|
||||
* +-----------+ leftoverRect :A+B->A
|
||||
* | | B | | mask :B
|
||||
* | +---+ |
|
||||
* | C |
|
||||
* +-----------+
|
||||
*/
|
||||
if (mask.GetBottom() == leftoverRect.GetBottom()) {
|
||||
leftoverRect.SetBottom(mask.GetTop() - 1);
|
||||
} else if (mask.GetTop() == leftoverRect.GetTop()) {
|
||||
leftoverRect.SetTop(mask.GetBottom() + 1);
|
||||
} else {
|
||||
splitRects.PushBack(leftoverRect);
|
||||
splitRects.Back().SetBottom(mask.GetTop() - 1);
|
||||
leftoverRect.SetTop(mask.GetBottom() + 1);
|
||||
}
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
if (mask.GetHeight() == leftoverRect.GetHeight()) {
|
||||
/*
|
||||
* +---------+ originRect :B+C
|
||||
* +-------+ | leftoverRect :A+B->A
|
||||
* | A | B | C | mask :B
|
||||
* +-------+ |
|
||||
* +---------+
|
||||
*/
|
||||
if (mask.GetLeft() == leftoverRect.GetLeft()) {
|
||||
leftoverRect.SetLeft(mask.GetRight() + 1);
|
||||
} else if (mask.GetRight() == leftoverRect.GetRight()) {
|
||||
leftoverRect.SetRight(mask.GetLeft() - 1);
|
||||
} else {
|
||||
splitRects.PushBack(leftoverRect);
|
||||
splitRects.Back().SetRight(mask.GetLeft() - 1);
|
||||
leftoverRect.SetLeft(mask.GetRight() + 1);
|
||||
}
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
|
||||
Vector<Rect> copyRect(splitRects);
|
||||
if (mask.GetLeft() != leftoverRect.GetLeft()) {
|
||||
/*
|
||||
* |
|
||||
* +-------+
|
||||
* | +---+ mask :A
|
||||
* | B | A | leftoverRect :A+B
|
||||
* | +---+
|
||||
* +-------+
|
||||
* |
|
||||
*/
|
||||
if (reserveCnt-- <= 0) {
|
||||
splitRects.Swap(copyRect);
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
splitRects.PushBack(leftoverRect);
|
||||
splitRects.Back().SetRight(mask.GetLeft() - 1);
|
||||
leftoverRect.SetLeft(mask.GetLeft());
|
||||
}
|
||||
|
||||
if (mask.GetTop() != leftoverRect.GetTop()) {
|
||||
/*
|
||||
* +-------+
|
||||
* | B | mask :A
|
||||
* ---+---+--- leftoverRect :A+B
|
||||
* | | A | |
|
||||
* +-+---+-+
|
||||
*/
|
||||
if (reserveCnt-- <= 0) {
|
||||
splitRects.Swap(copyRect);
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
splitRects.PushBack(leftoverRect);
|
||||
splitRects.Back().SetBottom(mask.GetTop() - 1);
|
||||
leftoverRect.SetTop(mask.GetTop());
|
||||
}
|
||||
|
||||
if (mask.GetRight() != leftoverRect.GetRight()) {
|
||||
/*
|
||||
* |
|
||||
* +-------+
|
||||
* +---+ | mask :A
|
||||
* | A | B | leftoverRect :A+B
|
||||
* +---+ |
|
||||
* +-------+
|
||||
* |
|
||||
*/
|
||||
if (reserveCnt-- <= 0) {
|
||||
splitRects.Swap(copyRect);
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
splitRects.PushBack(leftoverRect);
|
||||
splitRects.Back().SetLeft(mask.GetRight() + 1);
|
||||
leftoverRect.SetRight(mask.GetRight());
|
||||
}
|
||||
|
||||
if (mask.GetBottom() != leftoverRect.GetBottom()) {
|
||||
/*
|
||||
* +-+---+-+
|
||||
* | | A | | mask :A
|
||||
* ---+---+--- leftoverRect :A+B
|
||||
* | B |
|
||||
* +-------+
|
||||
*/
|
||||
if (reserveCnt-- <= 0) {
|
||||
splitRects.Swap(copyRect);
|
||||
splitRects.PushBack(leftoverRect);
|
||||
return;
|
||||
}
|
||||
splitRects.PushBack(leftoverRect);
|
||||
splitRects.Back().SetTop(mask.GetBottom() + 1);
|
||||
leftoverRect.SetBottom(mask.GetBottom());
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
static void AddRenderedRects(Rect& rect, List<Rect>& renderedRects, ListNode<Rect>* iter)
|
||||
{
|
||||
/* Elements at front have larger area and more relevance */
|
||||
for (; iter != renderedRects.End(); iter = iter->next_) {
|
||||
Rect& curRect = iter->data_;
|
||||
if (!curRect.IsIntersect(rect)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (curRect.IsContains(rect)) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Merge two rects */
|
||||
if (rect.IsContains(curRect)) {
|
||||
} else if (((curRect.GetLeft() == rect.GetLeft()) && (curRect.GetRight() == rect.GetRight())) ||
|
||||
((curRect.GetTop() == rect.GetTop()) && (curRect.GetBottom() == rect.GetBottom()))) {
|
||||
rect.Join(curRect, rect);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
iter = renderedRects.Remove(iter)->prev_;
|
||||
break;
|
||||
}
|
||||
if (iter == renderedRects.End()) { // No merge rises
|
||||
if (renderedRects.Size() == 128) { // record 128 rendered rects at most
|
||||
renderedRects.PopBack();
|
||||
}
|
||||
renderedRects.PushFront(rect);
|
||||
} else { // merge rises, go over the rest nodes
|
||||
AddRenderedRects(rect, renderedRects, iter);
|
||||
}
|
||||
}
|
||||
|
||||
void RootView::RemoveViewFromInvalidMap(UIView* view)
|
||||
{
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_lock(&lock_);
|
||||
#endif
|
||||
|
||||
int16_t stackCount = 0;
|
||||
do {
|
||||
while (view != nullptr) {
|
||||
/* delete node itself */
|
||||
auto entry = invalidateMap_.find(view);
|
||||
if (entry != invalidateMap_.end()) {
|
||||
invalidateMap_.erase(entry);
|
||||
}
|
||||
/* delete node's children */
|
||||
if (view->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
|
||||
g_viewStack[stackCount++] = view;
|
||||
view = static_cast<UIViewGroup*>(view)->GetChildrenHead();
|
||||
continue;
|
||||
}
|
||||
/* only go to child's sibling */
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
if (--stackCount >= 0) {
|
||||
view = g_viewStack[stackCount]->GetNextSibling();
|
||||
}
|
||||
} while (stackCount >= 0);
|
||||
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_unlock(&lock_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RootView::OptimizeInvalidView(UIView* curview, UIView* background, List<Rect>& renderedRects)
|
||||
{
|
||||
if (curview == nullptr) {
|
||||
return;
|
||||
}
|
||||
auto mapEntry = invalidateMap_.find(curview);
|
||||
if (mapEntry == invalidateMap_.end()) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect& invalidRect = mapEntry->second.Front();
|
||||
/* Transparent views should draw from background */
|
||||
if (((curview->GetStyleConst().bgOpa_ != OPA_OPAQUE) || (curview->GetOpaScale() != OPA_OPAQUE) ||
|
||||
(!curview->IsTransInvalid())) &&
|
||||
(curview != this)) {
|
||||
AddInvalidateRect(invalidRect, background);
|
||||
invalidateMap_.erase(mapEntry);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Remove the rendered parts and split the origin rect into splitInvalidRects
|
||||
* For performance reason, split numbers are strictly restrained.
|
||||
*/
|
||||
Vector<Rect> splitInvalidRects(MAX_SPLIT_NUM << 1);
|
||||
Rect invalidRectCopy(invalidRect);
|
||||
/* Using forward order because entries at the front are closer to the current view and have larger Size */
|
||||
for (auto iter = renderedRects.Begin(); iter != renderedRects.End(); iter = iter->next_) {
|
||||
for (int8_t i = 0; i < mapEntry->second.Size(); i++) {
|
||||
DivideInvalidateRect(iter->data_, mapEntry->second[i], splitInvalidRects);
|
||||
}
|
||||
mapEntry->second.Swap(splitInvalidRects);
|
||||
splitInvalidRects.Clear();
|
||||
}
|
||||
|
||||
/* Add new opaque rects */
|
||||
Rect preDrawRect(invalidRectCopy);
|
||||
if (!curview->OnPreDraw(preDrawRect)) {
|
||||
AddInvalidateRect(invalidRectCopy, background);
|
||||
}
|
||||
AddRenderedRects(preDrawRect, renderedRects, renderedRects.Begin());
|
||||
}
|
||||
|
||||
void RootView::OptimizeInvalidMap()
|
||||
{
|
||||
UIView* curview = this;
|
||||
int16_t stackCount = 0;
|
||||
int16_t opaStackCount = 0;
|
||||
UIView* background[VIEW_STACK_DEPTH];
|
||||
bool flags[VIEW_STACK_DEPTH]; // indicate whether stack go back from child
|
||||
List<Rect> renderedRects; // Record rendered areas to avoid rerendering
|
||||
|
||||
do {
|
||||
/* push stack */
|
||||
if (curview != nullptr) {
|
||||
if (stackCount >= VIEW_STACK_DEPTH) {
|
||||
return;
|
||||
}
|
||||
g_viewStack[stackCount] = curview;
|
||||
flags[stackCount++] = false;
|
||||
curview = curview->GetNextSibling();
|
||||
continue;
|
||||
}
|
||||
|
||||
curview = g_viewStack[--stackCount];
|
||||
Rect rect(curview->GetRect());
|
||||
if (!curview->IsVisible() || !IntersectScreenRect(rect)) {
|
||||
curview = nullptr;
|
||||
continue;
|
||||
}
|
||||
if (!flags[stackCount]) { // Back from sibling
|
||||
if (curview->IsViewGroup()) {
|
||||
/* Set background/topview */
|
||||
if (((curview->GetStyleConst().bgOpa_ == OPA_OPAQUE) && (curview->GetOpaScale() == OPA_OPAQUE) &&
|
||||
curview->IsTransInvalid()) ||
|
||||
(curview == this)) {
|
||||
background[opaStackCount] = curview;
|
||||
} else {
|
||||
background[opaStackCount] = background[opaStackCount - 1];
|
||||
}
|
||||
++opaStackCount;
|
||||
if (opaStackCount >= VIEW_STACK_DEPTH) {
|
||||
return;
|
||||
}
|
||||
flags[stackCount++] = true;
|
||||
curview = static_cast<UIViewGroup*>(curview)->GetChildrenHead();
|
||||
continue;
|
||||
}
|
||||
} else { // Back from child
|
||||
opaStackCount--;
|
||||
}
|
||||
OptimizeInvalidView(curview, background[opaStackCount - 1], renderedRects);
|
||||
curview = nullptr;
|
||||
} while (stackCount > 0);
|
||||
}
|
||||
|
||||
void RootView::DrawInvalidMap(const Rect& buffRect)
|
||||
{
|
||||
OptimizeInvalidMap();
|
||||
Rect rect;
|
||||
for (auto& viewEntry : invalidateMap_) {
|
||||
Vector<Rect>& viewRenderRect = viewEntry.second;
|
||||
for (uint16_t i = 0; i < viewRenderRect.Size(); i++) {
|
||||
rect.Intersect(viewRenderRect[i], buffRect);
|
||||
DrawTop(viewEntry.first, rect);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void RootView::AddInvalidateRect(Rect& rect, UIView* view)
|
||||
{
|
||||
Rect commonRect(rect);
|
||||
if (IntersectScreenRect(commonRect)) {
|
||||
#if LOCAL_RENDER
|
||||
Vector<Rect>& invalidRects = invalidateMap_[view];
|
||||
if (invalidRects.IsEmpty()) {
|
||||
invalidRects.PushBack(commonRect);
|
||||
} else {
|
||||
invalidRects[0].Join(invalidRects[0], commonRect);
|
||||
}
|
||||
#else
|
||||
invalidRect_.Join(invalidRect_, commonRect);
|
||||
renderFlag_ = true;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void RootView::AddInvalidateRectWithLock(Rect& rect, UIView* view)
|
||||
{
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_lock(&lock_);
|
||||
#endif
|
||||
|
||||
AddInvalidateRect(rect, view);
|
||||
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_unlock(&lock_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RootView::Measure()
|
||||
{
|
||||
#if LOCAL_RENDER
|
||||
if (!invalidateMap_.empty()) {
|
||||
MeasureView(childrenHead_);
|
||||
}
|
||||
#else
|
||||
if (renderFlag_) {
|
||||
MeasureView(childrenHead_);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void RootView::MeasureView(UIView* view)
|
||||
{
|
||||
int16_t stackCount = 0;
|
||||
UIView* curView = view;
|
||||
while (stackCount >= 0) {
|
||||
while (curView != nullptr) {
|
||||
if (curView->IsVisible()) {
|
||||
curView->ReMeasure();
|
||||
if (curView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
|
||||
g_viewStack[stackCount++] = curView;
|
||||
curView = static_cast<UIViewGroup*>(curView)->GetChildrenHead();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
curView = curView->GetNextSibling();
|
||||
}
|
||||
if (--stackCount >= 0) {
|
||||
curView = (g_viewStack[stackCount])->GetNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RootView::Render()
|
||||
{
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_lock(&lock_);
|
||||
#endif
|
||||
|
||||
#if LOCAL_RENDER
|
||||
if (!invalidateMap_.empty()) {
|
||||
RenderManager::RenderRect(GetRect(), this);
|
||||
invalidateMap_.clear();
|
||||
#else
|
||||
if (renderFlag_) {
|
||||
RenderManager::RenderRect(invalidRect_, this);
|
||||
invalidRect_ = {0, 0, 0, 0};
|
||||
renderFlag_ = false;
|
||||
#endif
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
if (boundWindow_) {
|
||||
boundWindow_->Flush();
|
||||
boundWindow_->Update();
|
||||
}
|
||||
#endif
|
||||
ScreenDeviceProxy::GetInstance()->OnRenderFinish();
|
||||
}
|
||||
|
||||
#if defined __linux__ || defined __LITEOS__ || defined __APPLE__
|
||||
pthread_mutex_unlock(&lock_);
|
||||
#endif
|
||||
}
|
||||
|
||||
void RootView::DrawTop(UIView* view, const Rect& rect)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t stackCount = 0;
|
||||
UIView* par = view->GetParent();
|
||||
if (par == nullptr) {
|
||||
par = view;
|
||||
}
|
||||
UIView* curView = view;
|
||||
UIView* transViewGroup = nullptr;
|
||||
Rect curViewRect;
|
||||
Rect mask = rect;
|
||||
Rect OrigRect;
|
||||
Rect RelativeRect;
|
||||
while (par != nullptr) {
|
||||
if (curView != nullptr) {
|
||||
if (curView->IsVisible()) {
|
||||
curViewRect = curView->GetMaskedRect();
|
||||
if (curViewRect.Intersect(curViewRect, mask) || enableAnimator_) {
|
||||
if ((curView->GetViewType() != UI_IMAGE_VIEW) && (curView->GetViewType() != UI_TEXTURE_MAPPER) &&
|
||||
!curView->IsTransInvalid() && !enableAnimator_) {
|
||||
OrigRect = curView->GetOrigRect();
|
||||
RelativeRect = curView->GetRelativeRect();
|
||||
curView->GetTransformMap().SetInvalid(true);
|
||||
curView->SetPosition(RelativeRect.GetX() - OrigRect.GetX(),
|
||||
RelativeRect.GetY() - OrigRect.GetY());
|
||||
ScreenDeviceProxy::GetInstance()->EnableAnimatorBuffer(true);
|
||||
ScreenDeviceProxy::GetInstance()->SetAnimatorRect(OrigRect);
|
||||
ScreenDeviceProxy::GetInstance()->SetAnimatorTransMap(curView->GetTransformMap());
|
||||
enableAnimator_ = true;
|
||||
}
|
||||
if (enableAnimator_) {
|
||||
Rect invalidatedArea;
|
||||
invalidatedArea.SetWidth(ScreenDeviceProxy::GetInstance()->GetScreenWidth());
|
||||
invalidatedArea.SetHeight(ScreenDeviceProxy::GetInstance()->GetScreenHeight());
|
||||
curView->OnDraw(invalidatedArea);
|
||||
} else {
|
||||
curView->OnDraw(curViewRect);
|
||||
}
|
||||
|
||||
if ((curView->IsViewGroup()) && (stackCount < COMPONENT_NESTING_DEPTH)) {
|
||||
if (enableAnimator_ && (transViewGroup == nullptr)) {
|
||||
transViewGroup = curView;
|
||||
}
|
||||
par = curView;
|
||||
g_viewStack[stackCount] = curView;
|
||||
g_maskStack[stackCount] = mask;
|
||||
stackCount++;
|
||||
curView = static_cast<UIViewGroup*>(curView)->GetChildrenHead();
|
||||
mask = par->GetContentRect();
|
||||
mask.Intersect(mask, curViewRect);
|
||||
continue;
|
||||
}
|
||||
curView->OnPostDraw(curViewRect);
|
||||
if (enableAnimator_ && (transViewGroup == nullptr)) {
|
||||
ScreenDeviceProxy::GetInstance()->EnableAnimatorBuffer(false);
|
||||
ScreenDeviceProxy::GetInstance()->DrawAnimatorBuffer(mask);
|
||||
curView->GetTransformMap().SetInvalid(false);
|
||||
enableAnimator_ = false;
|
||||
curView->SetPosition(RelativeRect.GetX(), RelativeRect.GetY());
|
||||
}
|
||||
}
|
||||
}
|
||||
curView = curView->GetNextSibling();
|
||||
continue;
|
||||
}
|
||||
if (--stackCount >= 0) {
|
||||
curViewRect = par->GetMaskedRect();
|
||||
mask = g_maskStack[stackCount];
|
||||
if (curViewRect.Intersect(curViewRect, g_maskStack[stackCount])) {
|
||||
par->OnPostDraw(curViewRect);
|
||||
}
|
||||
if (enableAnimator_ && transViewGroup == g_viewStack[stackCount]) {
|
||||
ScreenDeviceProxy::GetInstance()->EnableAnimatorBuffer(false);
|
||||
ScreenDeviceProxy::GetInstance()->DrawAnimatorBuffer(mask);
|
||||
transViewGroup->GetTransformMap().SetInvalid(false);
|
||||
enableAnimator_ = false;
|
||||
transViewGroup->SetPosition(RelativeRect.GetX(), RelativeRect.GetY());
|
||||
transViewGroup = nullptr;
|
||||
}
|
||||
curView = g_viewStack[stackCount]->GetNextSibling();
|
||||
par = par->GetParent();
|
||||
continue;
|
||||
}
|
||||
stackCount = 0;
|
||||
curView = par->GetNextSibling();
|
||||
par = par->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
UIView* RootView::GetTopUIView(const Rect& rect)
|
||||
{
|
||||
int16_t stackCount = 0;
|
||||
UIView* currentView = this;
|
||||
UIView* topView = currentView;
|
||||
Rect copyRect(rect);
|
||||
while (stackCount >= 0) {
|
||||
while (currentView != nullptr) {
|
||||
if (currentView->GetOrigRect().IsContains(rect) && currentView->IsVisible()) {
|
||||
if (currentView->GetStyleConst().bgOpa_ == OPA_OPAQUE && currentView->OnPreDraw(copyRect) &&
|
||||
currentView->GetOpaScale() == OPA_OPAQUE) {
|
||||
topView = currentView;
|
||||
}
|
||||
if (currentView->IsViewGroup() && stackCount < COMPONENT_NESTING_DEPTH) {
|
||||
g_viewStack[stackCount++] = currentView;
|
||||
currentView = static_cast<UIViewGroup*>(currentView)->GetChildrenHead();
|
||||
continue;
|
||||
}
|
||||
}
|
||||
currentView = currentView->GetNextSibling();
|
||||
}
|
||||
if (--stackCount >= 0) {
|
||||
currentView = (g_viewStack[stackCount])->GetNextSibling();
|
||||
}
|
||||
}
|
||||
return topView;
|
||||
}
|
||||
|
||||
bool RootView::FindSubView(const UIView& parentView, const UIView* subView)
|
||||
{
|
||||
const UIView* root = &parentView;
|
||||
if (root == subView) {
|
||||
return true;
|
||||
} else if (!root->IsViewGroup() || (subView == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
UIView* currentView = static_cast<const UIViewGroup*>(root)->GetChildrenHead();
|
||||
const UIView* parent = root;
|
||||
int8_t deep = 1;
|
||||
while (deep > 0) {
|
||||
if (currentView == subView) {
|
||||
return true;
|
||||
}
|
||||
if (currentView == nullptr) {
|
||||
currentView = parent->GetNextSibling();
|
||||
parent = parent->GetParent();
|
||||
deep--;
|
||||
} else if (currentView->IsViewGroup()) {
|
||||
parent = currentView;
|
||||
currentView = static_cast<UIViewGroup*>(currentView)->GetChildrenHead();
|
||||
deep++;
|
||||
} else {
|
||||
currentView = currentView->GetNextSibling();
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+229
@@ -0,0 +1,229 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/text_adapter.h"
|
||||
#include <cstdio>
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
bool TextFormatter::Format(int16_t value, char* outText, uint16_t textLen)
|
||||
{
|
||||
if (sprintf_s(outText, textLen, "%d", value) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
TextAdapter::TextAdapter()
|
||||
: dataMode_(DYNAMIC_TEXT_MODE),
|
||||
fontName_(nullptr),
|
||||
fontSize_(0),
|
||||
width_(0),
|
||||
height_(0),
|
||||
direct_(UITextLanguageDirect::TEXT_DIRECT_LTR),
|
||||
lineBreakMode_(UILabel::LINE_BREAK_ADAPT),
|
||||
integerTextStart_(0),
|
||||
integerTextEnd_(0),
|
||||
clickListener_(nullptr),
|
||||
formatter_(nullptr)
|
||||
{
|
||||
style_ = StyleDefault::GetBackgroundTransparentStyle();
|
||||
fontId_ = style_.font_;
|
||||
}
|
||||
|
||||
TextAdapter::~TextAdapter()
|
||||
{
|
||||
ClearDynamicText();
|
||||
if (fontName_ != nullptr) {
|
||||
UIFree(fontName_);
|
||||
fontName_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void TextAdapter::SetFont(const char* name, uint8_t size)
|
||||
{
|
||||
Text::SetFont(name, size, fontName_, fontSize_);
|
||||
}
|
||||
|
||||
UIView* TextAdapter::GetView(UIView* inView, int16_t index)
|
||||
{
|
||||
UILabel* newView = GetTextView(inView, index);
|
||||
if (newView == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
newView->SetLineBreakMode(lineBreakMode_);
|
||||
newView->SetAlign(TEXT_ALIGNMENT_CENTER, TEXT_ALIGNMENT_CENTER);
|
||||
if (width_) {
|
||||
newView->SetWidth(width_);
|
||||
}
|
||||
if (height_) {
|
||||
newView->SetHeight(height_);
|
||||
}
|
||||
newView->SetViewIndex(index);
|
||||
newView->UIView::SetStyle(style_);
|
||||
newView->GetHeight();
|
||||
if (clickListener_) {
|
||||
newView->SetOnClickListener(clickListener_);
|
||||
newView->SetTouchable(true);
|
||||
}
|
||||
return newView;
|
||||
}
|
||||
|
||||
UILabel* TextAdapter::GetTextView(UIView* inView, int16_t index)
|
||||
{
|
||||
switch (dataMode_) {
|
||||
case DYNAMIC_TEXT_MODE:
|
||||
return GetDynamicText(inView, index);
|
||||
case CONTINUOUS_INTEGER_MODE:
|
||||
return GetIntegerText(inView, index);
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
UILabel* TextAdapter::GetDynamicText(UIView* inView, int16_t index)
|
||||
{
|
||||
if (dynamicText_.IsEmpty() || (index > dynamicText_.Size() - 1) || (index < 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ListNode<const char*>* node = dynamicText_.Begin();
|
||||
for (int16_t i = 0; i < index; i++) {
|
||||
node = node->next_;
|
||||
}
|
||||
UILabel* newView = nullptr;
|
||||
if (inView == nullptr) {
|
||||
newView = new UILabel();
|
||||
} else {
|
||||
newView = static_cast<UILabel*>(inView);
|
||||
}
|
||||
|
||||
if (newView != nullptr) {
|
||||
newView->SetText(node->data_);
|
||||
if (fontName_ == nullptr) {
|
||||
newView->SetFontId(fontId_);
|
||||
} else {
|
||||
newView->SetFont(fontName_, fontSize_);
|
||||
}
|
||||
newView->SetDirect(direct_);
|
||||
}
|
||||
return newView;
|
||||
}
|
||||
|
||||
UILabel* TextAdapter::GetIntegerText(UIView* inView, int16_t index)
|
||||
{
|
||||
if ((index < 0) || ((integerTextEnd_ - integerTextStart_) < index)) {
|
||||
return nullptr;
|
||||
}
|
||||
UILabel* newView = nullptr;
|
||||
if (inView == nullptr) {
|
||||
newView = new UILabel();
|
||||
} else {
|
||||
newView = static_cast<UILabel*>(inView);
|
||||
}
|
||||
|
||||
if (newView != nullptr) {
|
||||
char buf[BUF_LEN] = {0};
|
||||
if (formatter_ != nullptr) {
|
||||
if (!formatter_->Format(integerTextStart_ + index, buf, BUF_LEN)) {
|
||||
if (inView == nullptr) {
|
||||
delete newView;
|
||||
newView = nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
} else {
|
||||
if (sprintf_s(buf, sizeof(buf), "%02d", integerTextStart_ + index) < 0) {
|
||||
if (inView == nullptr) {
|
||||
delete newView;
|
||||
newView = nullptr;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
buf[BUF_LEN - 1] = '\0';
|
||||
newView->SetText(buf);
|
||||
if (fontName_ == nullptr) {
|
||||
newView->SetFontId(fontId_);
|
||||
} else {
|
||||
newView->SetFont(fontName_, fontSize_);
|
||||
}
|
||||
newView->SetDirect(direct_);
|
||||
}
|
||||
return newView;
|
||||
}
|
||||
|
||||
void TextAdapter::ClearDynamicText()
|
||||
{
|
||||
ListNode<const char*>* node = dynamicText_.Begin();
|
||||
while (node != dynamicText_.End()) {
|
||||
if (node->data_) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<char*>(node->data_)));
|
||||
node->data_ = nullptr;
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
dynamicText_.Clear();
|
||||
}
|
||||
|
||||
void TextAdapter::SetData(List<const char*>* data)
|
||||
{
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (!dynamicText_.IsEmpty()) {
|
||||
ClearDynamicText();
|
||||
}
|
||||
ListNode<const char*>* node = data->Begin();
|
||||
while (node != data->End()) {
|
||||
uint32_t len = strlen(node->data_);
|
||||
char* stringData = static_cast<char*>(UIMalloc(len + 1));
|
||||
if (stringData == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (memcpy_s(stringData, len + 1, node->data_, len) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(stringData));
|
||||
stringData = nullptr;
|
||||
return;
|
||||
}
|
||||
stringData[len] = '\0';
|
||||
dynamicText_.PushBack(stringData);
|
||||
node = node->next_;
|
||||
}
|
||||
dataMode_ = DYNAMIC_TEXT_MODE;
|
||||
}
|
||||
|
||||
void TextAdapter::SetData(int16_t start, int16_t end)
|
||||
{
|
||||
if (start <= end) {
|
||||
integerTextStart_ = start;
|
||||
integerTextEnd_ = end;
|
||||
dataMode_ = CONTINUOUS_INTEGER_MODE;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t TextAdapter::GetCount()
|
||||
{
|
||||
switch (dataMode_) {
|
||||
case DYNAMIC_TEXT_MODE:
|
||||
return dynamicText_.Size();
|
||||
case CONTINUOUS_INTEGER_MODE:
|
||||
return (integerTextStart_ <= integerTextEnd_) ? (integerTextEnd_ - integerTextStart_ + 1) : 0;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+57
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_abstract_clock.h"
|
||||
|
||||
namespace OHOS {
|
||||
void UIAbstractClock::SetTime24Hour(uint8_t hour, uint8_t minute, uint8_t second)
|
||||
{
|
||||
currentHour_ = hour % ONE_DAY_IN_HOUR;
|
||||
currentMinute_ = minute % ONE_HOUR_IN_MINUTE;
|
||||
currentSecond_ = second % ONE_MINUTE_IN_SECOND;
|
||||
UpdateClock(false);
|
||||
}
|
||||
|
||||
void UIAbstractClock::SetTime12Hour(uint8_t hour, uint8_t minute, uint8_t second, bool am)
|
||||
{
|
||||
SetTime24Hour((hour % HALF_DAY_IN_HOUR) + (am ? 0 : HALF_DAY_IN_HOUR), minute, second);
|
||||
}
|
||||
|
||||
void UIAbstractClock::IncOneSecond()
|
||||
{
|
||||
currentSecond_++;
|
||||
currentMinute_ += currentSecond_ / ONE_MINUTE_IN_SECOND;
|
||||
currentSecond_ = currentSecond_ % ONE_MINUTE_IN_SECOND;
|
||||
|
||||
currentHour_ += currentMinute_ / ONE_HOUR_IN_MINUTE;
|
||||
currentMinute_ = currentMinute_ % ONE_HOUR_IN_MINUTE;
|
||||
currentHour_ = currentHour_ % ONE_DAY_IN_HOUR;
|
||||
|
||||
UpdateClock(false);
|
||||
}
|
||||
|
||||
void UIAbstractClock::SetWorkMode(WorkMode newMode)
|
||||
{
|
||||
if (mode_ != newMode) {
|
||||
mode_ = newMode;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractClock::UpdateClock(bool clockInit)
|
||||
{
|
||||
Invalidate();
|
||||
}
|
||||
} // namespace OHOS
|
||||
+230
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_abstract_progress.h"
|
||||
#include "common/image.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIAbstractProgress::UIAbstractProgress()
|
||||
: enableBackground_(true),
|
||||
backgroundStyleAllocFlag_(false),
|
||||
foregroundStyleAllocFlag_(false),
|
||||
backgroundImage_(nullptr),
|
||||
foregroundImage_(nullptr),
|
||||
rangeMax_(MAX_PERCENT_VALUE),
|
||||
rangeMin_(MIN_PERCENT_VALUE),
|
||||
curValue_(0),
|
||||
step_(1),
|
||||
lastValue_(0)
|
||||
{
|
||||
style_ = &(StyleDefault::GetBackgroundTransparentStyle());
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
if (theme != nullptr) {
|
||||
backgroundStyle_ = &(theme->GetProgressBackgroundStyle());
|
||||
foregroundStyle_ = &(theme->GetProgressForegroundStyle());
|
||||
} else {
|
||||
backgroundStyle_ = &(StyleDefault::GetProgressBackgroundStyle());
|
||||
foregroundStyle_ = &(StyleDefault::GetProgressForegroundStyle());
|
||||
}
|
||||
}
|
||||
|
||||
UIAbstractProgress::~UIAbstractProgress()
|
||||
{
|
||||
if (backgroundImage_ != nullptr) {
|
||||
delete backgroundImage_;
|
||||
backgroundImage_ = nullptr;
|
||||
}
|
||||
|
||||
if (foregroundImage_ != nullptr) {
|
||||
delete foregroundImage_;
|
||||
foregroundImage_ = nullptr;
|
||||
}
|
||||
|
||||
if (backgroundStyleAllocFlag_) {
|
||||
delete backgroundStyle_;
|
||||
backgroundStyle_ = nullptr;
|
||||
backgroundStyleAllocFlag_ = false;
|
||||
}
|
||||
|
||||
if (foregroundStyleAllocFlag_) {
|
||||
delete foregroundStyle_;
|
||||
foregroundStyle_ = nullptr;
|
||||
foregroundStyleAllocFlag_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetRange(int32_t rangeMax, int32_t rangeMin)
|
||||
{
|
||||
if ((rangeMax_ == rangeMax) && (rangeMin_ == rangeMin)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (rangeMax >= rangeMin) {
|
||||
rangeMax_ = rangeMax;
|
||||
rangeMin_ = rangeMin;
|
||||
lastValue_ = rangeMin;
|
||||
SetValue(curValue_);
|
||||
} else {
|
||||
GRAPHIC_LOGW("UIAbstractProgress::SetRange rangeMax less than rangeMin !\n");
|
||||
}
|
||||
};
|
||||
|
||||
void UIAbstractProgress::SetValue(int32_t value)
|
||||
{
|
||||
if (value < rangeMin_) {
|
||||
curValue_ = rangeMin_;
|
||||
} else if (value > rangeMax_) {
|
||||
curValue_ = rangeMax_;
|
||||
} else {
|
||||
curValue_ = value;
|
||||
}
|
||||
|
||||
if ((curValue_ != lastValue_) &&
|
||||
((curValue_ == rangeMin_) || (curValue_ == rangeMax_) ||
|
||||
(MATH_ABS(curValue_ - lastValue_) >= static_cast<int32_t>(step_)))) {
|
||||
Invalidate();
|
||||
lastValue_ = curValue_;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t UIAbstractProgress::GetCurrentPos(int16_t distance) const
|
||||
{
|
||||
uint32_t delta = lastValue_ - rangeMin_;
|
||||
uint32_t rangeSize = GetRangeSize();
|
||||
if (rangeSize == 0) {
|
||||
return distance;
|
||||
}
|
||||
int16_t result = static_cast<int64_t>(distance) * delta / rangeSize;
|
||||
return result;
|
||||
}
|
||||
|
||||
uint32_t UIAbstractProgress::GetRangeSize() const
|
||||
{
|
||||
return (rangeMax_ < rangeMin_) ? 0 : (rangeMax_ - rangeMin_);
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetImage(const char* foregroundImage, const char* backgroundImage)
|
||||
{
|
||||
if (!InitImage()) {
|
||||
return;
|
||||
}
|
||||
backgroundImage_->SetSrc(backgroundImage);
|
||||
foregroundImage_->SetSrc(foregroundImage);
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetImage(const ImageInfo* foregroundImage, const ImageInfo* backgroundImage)
|
||||
{
|
||||
if (!InitImage()) {
|
||||
return;
|
||||
}
|
||||
backgroundImage_->SetSrc(backgroundImage);
|
||||
foregroundImage_->SetSrc(foregroundImage);
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetBackgroundStyle(const Style& style)
|
||||
{
|
||||
if (!backgroundStyleAllocFlag_) {
|
||||
backgroundStyle_ = new Style();
|
||||
if (backgroundStyle_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style1 fail");
|
||||
return;
|
||||
}
|
||||
backgroundStyleAllocFlag_ = true;
|
||||
}
|
||||
*backgroundStyle_ = style;
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetBackgroundStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
if (!backgroundStyleAllocFlag_) {
|
||||
backgroundStyle_ = new Style(*backgroundStyle_);
|
||||
if (backgroundStyle_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style1 fail");
|
||||
return;
|
||||
}
|
||||
backgroundStyleAllocFlag_ = true;
|
||||
}
|
||||
backgroundStyle_->SetStyle(key, value);
|
||||
}
|
||||
|
||||
const Style& UIAbstractProgress::GetBackgroundStyle() const
|
||||
{
|
||||
return *backgroundStyle_;
|
||||
}
|
||||
|
||||
int64_t UIAbstractProgress::GetBackgroundStyle(uint8_t key) const
|
||||
{
|
||||
return backgroundStyle_->GetStyle(key);
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetForegroundStyle(const Style& style)
|
||||
{
|
||||
if (!foregroundStyleAllocFlag_) {
|
||||
foregroundStyle_ = new Style();
|
||||
if (foregroundStyle_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style1 fail");
|
||||
return;
|
||||
}
|
||||
foregroundStyleAllocFlag_ = true;
|
||||
}
|
||||
*foregroundStyle_ = style;
|
||||
}
|
||||
|
||||
void UIAbstractProgress::SetForegroundStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
if (!foregroundStyleAllocFlag_) {
|
||||
foregroundStyle_ = new Style(*foregroundStyle_);
|
||||
if (foregroundStyle_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style1 fail");
|
||||
return;
|
||||
}
|
||||
foregroundStyleAllocFlag_ = true;
|
||||
}
|
||||
foregroundStyle_->SetStyle(key, value);
|
||||
}
|
||||
|
||||
const Style& UIAbstractProgress::GetForegroundStyle() const
|
||||
{
|
||||
return *foregroundStyle_;
|
||||
}
|
||||
|
||||
int64_t UIAbstractProgress::GetForegroundStyle(uint8_t key) const
|
||||
{
|
||||
return foregroundStyle_->GetStyle(key);
|
||||
}
|
||||
|
||||
bool UIAbstractProgress::InitImage()
|
||||
{
|
||||
if (backgroundImage_ == nullptr) {
|
||||
backgroundImage_ = new Image();
|
||||
if (backgroundImage_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Image fail");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (foregroundImage_ == nullptr) {
|
||||
foregroundImage_ = new Image();
|
||||
if (foregroundImage_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Image fail");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+182
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_abstract_scroll.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIAbstractScroll::UIAbstractScroll()
|
||||
: scrollBlankSize_(0),
|
||||
reboundSize_(0),
|
||||
maxScrollDistance_(0),
|
||||
lastDeltaY_{0},
|
||||
dragAccCoefficient_(DRAG_ACC_FACTOR),
|
||||
swipeAccCoefficient_(0),
|
||||
direction_(VERTICAL),
|
||||
deltaYIndex_(0),
|
||||
reserve_(0),
|
||||
throwDrag_(false),
|
||||
easingFunc_(EasingEquation::CubicEaseOut),
|
||||
scrollAnimator_(&animatorCallback_, this, 0, true)
|
||||
{
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
rotateFactor_ = 1;
|
||||
rotateThreshold_ = 1;
|
||||
#endif
|
||||
isViewGroup_ = true;
|
||||
touchable_ = true;
|
||||
draggable_ = true;
|
||||
dragParentInstead_ = false;
|
||||
AnimatorManager::GetInstance()->Add(&scrollAnimator_);
|
||||
}
|
||||
|
||||
UIAbstractScroll::~UIAbstractScroll()
|
||||
{
|
||||
scrollAnimator_.Stop();
|
||||
AnimatorManager::GetInstance()->Remove(&scrollAnimator_);
|
||||
}
|
||||
|
||||
void UIAbstractScroll::MoveChildByOffset(int16_t offsetX, int16_t offsetY)
|
||||
{
|
||||
if ((offsetX == 0) && (offsetY == 0)) {
|
||||
return;
|
||||
}
|
||||
UIView* view = GetChildrenHead();
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
while (view != nullptr) {
|
||||
x = view->GetX() + offsetX;
|
||||
y = view->GetY() + offsetY;
|
||||
view->SetPosition(x, y);
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
int16_t UIAbstractScroll::GetMaxDeltaY() const
|
||||
{
|
||||
int16_t result = 0;
|
||||
for (int16_t i = 0; i < MAX_DELTA_Y_SIZE; i++) {
|
||||
if (result < MATH_ABS(lastDeltaY_[i])) {
|
||||
result = MATH_ABS(lastDeltaY_[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void UIAbstractScroll::StopAnimator()
|
||||
{
|
||||
scrollAnimator_.Stop();
|
||||
animatorCallback_.RsetCallback();
|
||||
isDragging_ = false;
|
||||
}
|
||||
|
||||
bool UIAbstractScroll::DragThrowAnimator(Point currentPos, Point lastPos)
|
||||
{
|
||||
if (!throwDrag_ && (reboundSize_ == 0)) {
|
||||
return false;
|
||||
}
|
||||
int16_t dragDistanceX = 0;
|
||||
int16_t dragDistanceY = 0;
|
||||
if (throwDrag_) {
|
||||
CalculateDragDistance(currentPos, lastPos, dragDistanceX, dragDistanceY);
|
||||
}
|
||||
if (reboundSize_ != 0) {
|
||||
CalculateReboundDistance(dragDistanceX, dragDistanceY);
|
||||
}
|
||||
StartAnimator(dragDistanceX, dragDistanceY);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIAbstractScroll::StartAnimator(int16_t dragDistanceX, int16_t dragDistanceY)
|
||||
{
|
||||
int16_t dragTimes = MATH_MAX(MATH_ABS(dragDistanceX), MATH_ABS(dragDistanceY)) / DRAG_TIMES_COEFFICIENT;
|
||||
if (dragTimes < MIN_DRAG_TIMES) {
|
||||
dragTimes = MIN_DRAG_TIMES;
|
||||
}
|
||||
animatorCallback_.SetDragStartValue(0, 0);
|
||||
animatorCallback_.SetDragEndValue(dragDistanceX, dragDistanceY);
|
||||
animatorCallback_.SetDragTimes(dragTimes * DRAG_ACC_FACTOR / GetDragACCLevel());
|
||||
scrollAnimator_.Start();
|
||||
}
|
||||
|
||||
void UIAbstractScroll::CalculateDragDistance(Point currentPos,
|
||||
Point lastPos,
|
||||
int16_t& dragDistanceX,
|
||||
int16_t& dragDistanceY)
|
||||
{
|
||||
if ((direction_ == VERTICAL) || (direction_ == HORIZONTAL_AND_VERTICAL)) {
|
||||
dragDistanceY = (currentPos.y - lastPos.y) * DRAG_DISTANCE_COEFFICIENT;
|
||||
if (dragDistanceY > 0) {
|
||||
dragDistanceY += GetMaxDeltaY() * GetSwipeACCLevel() / DRAG_ACC_FACTOR;
|
||||
} else {
|
||||
dragDistanceY -= GetMaxDeltaY() * GetSwipeACCLevel() / DRAG_ACC_FACTOR;
|
||||
}
|
||||
}
|
||||
|
||||
if ((direction_ == HORIZONTAL) || (direction_ == HORIZONTAL_AND_VERTICAL)) {
|
||||
dragDistanceX = (currentPos.x - lastPos.x) * DRAG_DISTANCE_COEFFICIENT;
|
||||
}
|
||||
|
||||
if (maxScrollDistance_ != 0) {
|
||||
if (MATH_ABS(dragDistanceY) > maxScrollDistance_) {
|
||||
int16_t calculatedValue = (dragDistanceY > 0) ? 1 : -1;
|
||||
dragDistanceY = calculatedValue * maxScrollDistance_;
|
||||
}
|
||||
if (MATH_ABS(dragDistanceX) > maxScrollDistance_) {
|
||||
int16_t calculatedValue = (dragDistanceX > 0) ? 1 : -1;
|
||||
dragDistanceX = calculatedValue * maxScrollDistance_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIAbstractScroll::ListAnimatorCallback::Callback(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
curtTime_++;
|
||||
|
||||
UIAbstractScroll* scrollView = static_cast<UIAbstractScroll*>(view);
|
||||
scrollView->isDragging_ = true;
|
||||
|
||||
if (curtTime_ <= dragTimes_) {
|
||||
bool needStopX = false;
|
||||
bool needStopY = false;
|
||||
if (startValueY_ != endValueY_) {
|
||||
int16_t actY = scrollView->easingFunc_(startValueY_, endValueY_, curtTime_, dragTimes_);
|
||||
if (!scrollView->DragYInner(actY - previousValueY_)) {
|
||||
needStopY = true;
|
||||
}
|
||||
previousValueY_ = actY;
|
||||
} else {
|
||||
needStopY = true;
|
||||
}
|
||||
if (startValueX_ != endValueX_) {
|
||||
int16_t actX = scrollView->easingFunc_(startValueX_, endValueX_, curtTime_, dragTimes_);
|
||||
if (!scrollView->DragXInner(actX - previousValueX_)) {
|
||||
needStopX = true;
|
||||
}
|
||||
previousValueX_ = actX;
|
||||
} else {
|
||||
needStopX = true;
|
||||
}
|
||||
if (needStopX && needStopY) {
|
||||
scrollView->StopAnimator();
|
||||
}
|
||||
} else {
|
||||
scrollView->StopAnimator();
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+336
@@ -0,0 +1,336 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_analog_clock.h"
|
||||
#include "components/ui_image_view.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_line.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "style.h"
|
||||
#include "themes/theme.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIAnalogClock::UIAnalogClock()
|
||||
{
|
||||
touchable_ = true;
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetHandImage(HandType type, const UIImageView& img, Point position, Point center)
|
||||
{
|
||||
Hand *hand = nullptr;
|
||||
if (type == HandType::HOUR_HAND) {
|
||||
hand = &hourHand_;
|
||||
} else if (type == HandType::MINUTE_HAND) {
|
||||
hand = &minuteHand_;
|
||||
} else {
|
||||
hand = &secondHand_;
|
||||
}
|
||||
|
||||
hand->center_ = center;
|
||||
hand->position_ = position;
|
||||
hand->initAngle_ = 0;
|
||||
hand->preAngle_ = 0;
|
||||
hand->nextAngle_ = 0;
|
||||
hand->drawtype_ = DrawType::DRAW_IMAGE;
|
||||
|
||||
if (img.GetSrcType() == IMG_SRC_FILE) {
|
||||
CacheEntry entry;
|
||||
RetCode ret = CacheManager::GetInstance().Open(img.GetPath(), *style_, entry);
|
||||
if (ret != RetCode::OK) {
|
||||
return;
|
||||
}
|
||||
hand->imageInfo_ = entry.GetImageInfo();
|
||||
} else {
|
||||
hand->imageInfo_ = *(img.GetImageInfo());
|
||||
}
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetHandLine(HandType type, Point position, Point center, ColorType color,
|
||||
uint16_t width, uint16_t height, OpacityType opacity)
|
||||
{
|
||||
Hand* hand = nullptr;
|
||||
if (type == HandType::HOUR_HAND) {
|
||||
hand = &hourHand_;
|
||||
} else if (type == HandType::MINUTE_HAND) {
|
||||
hand = &minuteHand_;
|
||||
} else {
|
||||
hand = &secondHand_;
|
||||
}
|
||||
|
||||
hand->color_ = color;
|
||||
hand->height_ = height;
|
||||
hand->width_ = width;
|
||||
hand->position_ = position;
|
||||
hand->center_ = center;
|
||||
hand->opacity_ = opacity;
|
||||
hand->initAngle_ = 0;
|
||||
hand->preAngle_ = 0;
|
||||
hand->nextAngle_ = 0;
|
||||
hand->drawtype_ = DrawType::DRAW_LINE;
|
||||
}
|
||||
|
||||
Point UIAnalogClock::GetHandRotateCenter(HandType type) const
|
||||
{
|
||||
if (type == HandType::HOUR_HAND) {
|
||||
return hourHand_.center_;
|
||||
} else if (type == HandType::MINUTE_HAND) {
|
||||
return minuteHand_.center_;
|
||||
} else {
|
||||
return secondHand_.center_;
|
||||
}
|
||||
}
|
||||
|
||||
Point UIAnalogClock::GetHandPosition(HandType type) const
|
||||
{
|
||||
if (type == HandType::HOUR_HAND) {
|
||||
return hourHand_.position_;
|
||||
} else if (type == HandType::MINUTE_HAND) {
|
||||
return minuteHand_.position_;
|
||||
} else {
|
||||
return secondHand_.position_;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t UIAnalogClock::GetHandInitAngle(HandType type) const
|
||||
{
|
||||
if (type == HandType::HOUR_HAND) {
|
||||
return hourHand_.initAngle_;
|
||||
} else if (type == HandType::MINUTE_HAND) {
|
||||
return minuteHand_.initAngle_;
|
||||
} else {
|
||||
return secondHand_.initAngle_;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t UIAnalogClock::GetHandCurrentAngle(HandType type) const
|
||||
{
|
||||
if (type == HandType::HOUR_HAND) {
|
||||
return hourHand_.nextAngle_;
|
||||
} else if (type == HandType::MINUTE_HAND) {
|
||||
return minuteHand_.nextAngle_;
|
||||
} else {
|
||||
return secondHand_.nextAngle_;
|
||||
}
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetInitTime24Hour(uint8_t hour, uint8_t minute, uint8_t second)
|
||||
{
|
||||
currentHour_ = hour % ONE_DAY_IN_HOUR;
|
||||
currentMinute_ = minute % ONE_HOUR_IN_MINUTE;
|
||||
currentSecond_ = second % ONE_MINUTE_IN_SECOND;
|
||||
|
||||
hourHand_.initAngle_ = ConvertHandValueToAngle(currentHour_,
|
||||
HALF_DAY_IN_HOUR, currentMinute_, ONE_HOUR_IN_MINUTE);
|
||||
hourHand_.preAngle_ = hourHand_.initAngle_;
|
||||
hourHand_.nextAngle_ = hourHand_.initAngle_;
|
||||
|
||||
minuteHand_.initAngle_ = ConvertHandValueToAngle(currentMinute_,
|
||||
ONE_HOUR_IN_MINUTE, currentSecond_, ONE_MINUTE_IN_SECOND);
|
||||
minuteHand_.preAngle_ = minuteHand_.initAngle_;
|
||||
minuteHand_.nextAngle_ = minuteHand_.initAngle_;
|
||||
|
||||
secondHand_.initAngle_ = ConvertHandValueToAngle(currentSecond_, ONE_MINUTE_IN_SECOND);
|
||||
secondHand_.preAngle_ = secondHand_.initAngle_;
|
||||
secondHand_.nextAngle_ = secondHand_.initAngle_;
|
||||
|
||||
UpdateClock(true);
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetInitTime12Hour(uint8_t hour, uint8_t minute, uint8_t second, bool am)
|
||||
{
|
||||
SetInitTime24Hour((hour % HALF_DAY_IN_HOUR) + (am ? 0 : HALF_DAY_IN_HOUR), minute, second);
|
||||
}
|
||||
|
||||
uint16_t UIAnalogClock::ConvertHandValueToAngle(uint8_t handValue, uint8_t range,
|
||||
uint8_t secondHandValue, uint8_t ratio) const
|
||||
{
|
||||
if ((range == 0) || (ratio == 0)) {
|
||||
GRAPHIC_LOGW("UIAnalogClock::ConvertHandValueToAngle Invalid range or ratio\n");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Example: calculate the angle of hour hand
|
||||
* Assume that the time is 5: 30, then range is 12, radio is 60
|
||||
* angle is [(5 * 60 + 30) / (12 * 60)] * 360
|
||||
*/
|
||||
uint32_t degree = (static_cast<uint16_t>(handValue) * ratio + secondHandValue);
|
||||
degree = static_cast<uint32_t>(CIRCLE_IN_DEGREE * degree / (static_cast<uint16_t>(range) * ratio));
|
||||
|
||||
return static_cast<uint16_t>(degree % CIRCLE_IN_DEGREE);
|
||||
}
|
||||
|
||||
uint16_t UIAnalogClock::ConvertHandValueToAngle(uint8_t handValue, uint8_t range) const
|
||||
{
|
||||
if (range == 0) {
|
||||
GRAPHIC_LOGW("UIAnalogClock::ConvertHandValueToAngle Invalid range or ratio\n");
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Example: calculate the angle of second hand without millisecond handle
|
||||
* Assume that the time is 5:30:30, then range is 60
|
||||
* angle is (30 / 60) * 360
|
||||
*/
|
||||
return (static_cast<uint16_t>(handValue) * CIRCLE_IN_DEGREE / range);
|
||||
}
|
||||
|
||||
void UIAnalogClock::UpdateClock(bool clockInit)
|
||||
{
|
||||
Invalidate();
|
||||
hourHand_.nextAngle_ = ConvertHandValueToAngle(currentHour_,
|
||||
HALF_DAY_IN_HOUR, currentMinute_, ONE_HOUR_IN_MINUTE);
|
||||
|
||||
minuteHand_.nextAngle_ = ConvertHandValueToAngle(currentMinute_,
|
||||
ONE_HOUR_IN_MINUTE, currentSecond_, ONE_MINUTE_IN_SECOND);
|
||||
|
||||
secondHand_.nextAngle_ = ConvertHandValueToAngle(currentSecond_, ONE_MINUTE_IN_SECOND);
|
||||
|
||||
Rect rect = GetRect();
|
||||
CalculateRedrawArea(rect, hourHand_, clockInit);
|
||||
CalculateRedrawArea(rect, minuteHand_, clockInit);
|
||||
if (GetWorkMode() == WorkMode::NORMAL) {
|
||||
CalculateRedrawArea(rect, secondHand_, clockInit);
|
||||
}
|
||||
}
|
||||
|
||||
void UIAnalogClock::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
DrawRect::Draw(GetRect(), invalidatedArea, *style_, opaScale_);
|
||||
}
|
||||
|
||||
void UIAnalogClock::OnPostDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
Rect current = GetOrigRect();
|
||||
DrawHand(current, invalidatedArea, hourHand_);
|
||||
DrawHand(current, invalidatedArea, minuteHand_);
|
||||
if (GetWorkMode() == WorkMode::NORMAL) {
|
||||
DrawHand(current, invalidatedArea, secondHand_);
|
||||
}
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetPosition(int16_t x, int16_t y)
|
||||
{
|
||||
UIViewGroup::SetPosition(x, y);
|
||||
UpdateClock(true);
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetPosition(int16_t x, int16_t y, int16_t width, int16_t height)
|
||||
{
|
||||
UIViewGroup::SetPosition(x, y, width, height);
|
||||
UpdateClock(true);
|
||||
}
|
||||
|
||||
void UIAnalogClock::CalculateRedrawArea(const Rect& current, Hand& hand, bool clockInit)
|
||||
{
|
||||
/*
|
||||
* Use the current image as an independent rectangular area
|
||||
* to calculate the coordinate conversion coefficient.
|
||||
*/
|
||||
int16_t imgWidth = hand.imageInfo_.header.width;
|
||||
int16_t imgHeight = hand.imageInfo_.header.height;
|
||||
|
||||
int16_t left = hand.position_.x + current.GetLeft();
|
||||
int16_t right = left + imgWidth;
|
||||
int16_t top = hand.position_.y + current.GetTop();
|
||||
int16_t bottom = top + imgHeight;
|
||||
Rect imgRect(left, top, right, bottom);
|
||||
TransformMap backwardMap(imgRect);
|
||||
Vector2<float> pivot;
|
||||
pivot.x_ = hand.center_.x;
|
||||
pivot.y_ = hand.center_.y;
|
||||
|
||||
/* Rotate the specified angle, */
|
||||
backwardMap.Rotate(hand.nextAngle_ - hand.initAngle_, pivot);
|
||||
Rect redraw = hand.target_;
|
||||
hand.target_ = backwardMap.GetBoxRect();
|
||||
hand.trans_ = backwardMap;
|
||||
hand.preAngle_ = hand.nextAngle_;
|
||||
if (!clockInit) {
|
||||
/* Prevent old images from being residued */
|
||||
redraw.Join(redraw, hand.target_);
|
||||
InvalidateRect(redraw);
|
||||
}
|
||||
}
|
||||
|
||||
void UIAnalogClock::DrawHand(const Rect& current, const Rect& invalidatedArea, Hand& hand)
|
||||
{
|
||||
if (hand.drawtype_ == DrawType::DRAW_IMAGE) {
|
||||
DrawHandImage(current, invalidatedArea, hand);
|
||||
} else {
|
||||
DrawHandLine(invalidatedArea, hand);
|
||||
}
|
||||
}
|
||||
|
||||
void UIAnalogClock::DrawHandImage(const Rect& current, const Rect& invalidatedArea, Hand& hand)
|
||||
{
|
||||
uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(hand.imageInfo_.header.colorMode);
|
||||
TransformDataInfo imageTranDataInfo = {
|
||||
hand.imageInfo_.header, hand.imageInfo_.data, pxSize,
|
||||
BlurLevel::LEVEL0, TransformAlgorithm::BILINEAR
|
||||
};
|
||||
DrawUtils::GetInstance()->DrawTransform(invalidatedArea, { 0, 0 },
|
||||
Color::Black(), opaScale_, hand.trans_, imageTranDataInfo);
|
||||
}
|
||||
|
||||
void UIAnalogClock::DrawHandLine(const Rect& invalidatedArea, Hand& hand)
|
||||
{
|
||||
float sinma = Sin(hand.nextAngle_);
|
||||
float cosma = Sin(hand.nextAngle_ + THREE_QUARTER_IN_DEGREE);
|
||||
int32_t handLength = hand.height_;
|
||||
Rect rect = GetRect();
|
||||
Point start;
|
||||
Point end;
|
||||
Point curCenter;
|
||||
curCenter.x = hand.position_.x + hand.center_.x + rect.GetLeft();
|
||||
curCenter.y = hand.position_.y + hand.center_.y + rect.GetTop();
|
||||
|
||||
int32_t startToCenterLength = hand.center_.y;
|
||||
|
||||
int32_t xPointLength = static_cast<int32_t>(startToCenterLength * sinma);
|
||||
int32_t yPointLength = static_cast<int32_t>(startToCenterLength * cosma);
|
||||
|
||||
start.x = xPointLength + curCenter.x;
|
||||
start.y = yPointLength + curCenter.y;
|
||||
|
||||
/*
|
||||
* @ startToCenterLength: means the length between StartPoint and CenterPoint.
|
||||
* @ handlength: means the hand height.
|
||||
* @ xlength: means X-axis length relative to the center point
|
||||
* @ ylength: means Y-axis length relative to the center point
|
||||
*/
|
||||
int32_t xlength = static_cast<int32_t>((startToCenterLength - handLength) * sinma);
|
||||
int32_t ylength = static_cast<int32_t>((startToCenterLength - handLength) * cosma);
|
||||
end.x = xlength + curCenter.x;
|
||||
end.y = ylength + curCenter.y;
|
||||
|
||||
DrawLine::Draw(start, end, invalidatedArea, hand.width_, hand.color_, hand.opacity_);
|
||||
}
|
||||
|
||||
void UIAnalogClock::SetWorkMode(WorkMode newMode)
|
||||
{
|
||||
WorkMode oldMode = mode_;
|
||||
|
||||
if (oldMode != newMode) {
|
||||
/*
|
||||
* After entering the alwayson mode, all child controls are no longer drawn,
|
||||
* making the simplest analog clock.
|
||||
*/
|
||||
isViewGroup_ = (newMode == ALWAYS_ON) ? false : true;
|
||||
mode_ = newMode;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+219
@@ -0,0 +1,219 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_arc_label.h"
|
||||
#include "common/typed_text.h"
|
||||
#include "draw/draw_label.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "font/ui_font.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIArcLabel::UIArcLabel()
|
||||
: arcLabelText_(nullptr),
|
||||
needRefresh_(false),
|
||||
textSize_({0, 0}),
|
||||
radius_(0),
|
||||
startAngle_(0),
|
||||
endAngle_(0),
|
||||
arcCenter_({0, 0}),
|
||||
orientation_(TextOrientation::INSIDE),
|
||||
arcTextInfo_{0}
|
||||
{
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
style_ = (theme != nullptr) ? &(theme->GetLabelStyle()) : &(StyleDefault::GetLabelStyle());
|
||||
}
|
||||
|
||||
UIArcLabel::~UIArcLabel()
|
||||
{
|
||||
if (arcLabelText_ != nullptr) {
|
||||
delete arcLabelText_;
|
||||
arcLabelText_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UIArcLabel::SetStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
UIView::SetStyle(key, value);
|
||||
RefreshArcLabel();
|
||||
}
|
||||
|
||||
void UIArcLabel::SetText(const char* text)
|
||||
{
|
||||
if (text == nullptr) {
|
||||
return;
|
||||
}
|
||||
InitArcLabelText();
|
||||
arcLabelText_->SetText(text);
|
||||
if (arcLabelText_->IsNeedRefresh()) {
|
||||
RefreshArcLabel();
|
||||
}
|
||||
}
|
||||
|
||||
const char* UIArcLabel::GetText() const
|
||||
{
|
||||
return (arcLabelText_ == nullptr) ? nullptr : arcLabelText_->GetText();
|
||||
}
|
||||
|
||||
void UIArcLabel::SetAlign(UITextLanguageAlignment horizontalAlign)
|
||||
{
|
||||
InitArcLabelText();
|
||||
arcLabelText_->SetAlign(horizontalAlign, TEXT_ALIGNMENT_TOP);
|
||||
if (arcLabelText_->IsNeedRefresh()) {
|
||||
RefreshArcLabel();
|
||||
}
|
||||
}
|
||||
|
||||
UITextLanguageAlignment UIArcLabel::GetHorAlign()
|
||||
{
|
||||
InitArcLabelText();
|
||||
return arcLabelText_->GetHorAlign();
|
||||
}
|
||||
|
||||
UITextLanguageDirect UIArcLabel::GetDirect()
|
||||
{
|
||||
InitArcLabelText();
|
||||
return arcLabelText_->GetDirect();
|
||||
}
|
||||
|
||||
void UIArcLabel::SetFontId(uint8_t fontId)
|
||||
{
|
||||
InitArcLabelText();
|
||||
arcLabelText_->SetFontId(fontId);
|
||||
if (arcLabelText_->IsNeedRefresh()) {
|
||||
RefreshArcLabel();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t UIArcLabel::GetFontId()
|
||||
{
|
||||
InitArcLabelText();
|
||||
return arcLabelText_->GetFontId();
|
||||
}
|
||||
|
||||
void UIArcLabel::SetFont(const char* name, uint8_t size)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
return;
|
||||
}
|
||||
InitArcLabelText();
|
||||
arcLabelText_->SetFont(name, size);
|
||||
if (arcLabelText_->IsNeedRefresh()) {
|
||||
RefreshArcLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void UIArcLabel::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
InitArcLabelText();
|
||||
const char* text = arcLabelText_->GetText();
|
||||
if ((text == nullptr) || (radius_ == 0)) {
|
||||
return;
|
||||
}
|
||||
Rect trunc = invalidatedArea;
|
||||
OpacityType opa = GetMixOpaScale();
|
||||
DrawRect::Draw(GetRect(), trunc, *style_, opa);
|
||||
|
||||
Rect coords = GetContentRect();
|
||||
if (trunc.Intersect(trunc, coords)) {
|
||||
DrawArcText(trunc, opa);
|
||||
}
|
||||
}
|
||||
|
||||
void UIArcLabel::DrawArcText(const Rect& mask, OpacityType opaScale)
|
||||
{
|
||||
Point center;
|
||||
center.x = arcTextInfo_.arcCenter.x + GetRect().GetX();
|
||||
center.y = arcTextInfo_.arcCenter.y + GetRect().GetY();
|
||||
InitArcLabelText();
|
||||
UIFont::GetInstance()->SetCurrentFontId(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize());
|
||||
DrawLabel::DrawArcText(mask, arcLabelText_->GetText(), center, arcLabelText_->GetFontId(),
|
||||
arcTextInfo_, orientation_, *style_, opaScale);
|
||||
}
|
||||
|
||||
void UIArcLabel::RefreshArcLabel()
|
||||
{
|
||||
Invalidate();
|
||||
if (!needRefresh_) {
|
||||
needRefresh_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void UIArcLabel::ReMeasure()
|
||||
{
|
||||
if (!needRefresh_) {
|
||||
return;
|
||||
}
|
||||
needRefresh_ = false;
|
||||
InitArcLabelText();
|
||||
UIFont::GetInstance()->SetCurrentFontId(arcLabelText_->GetFontId(), arcLabelText_->GetFontSize());
|
||||
|
||||
MeasureArcTextInfo();
|
||||
Rect textRect = TypedText::GetArcTextRect(arcLabelText_->GetText(),
|
||||
arcCenter_,
|
||||
style_->letterSpace_,
|
||||
orientation_,
|
||||
arcTextInfo_);
|
||||
int16_t arcTextWidth = textRect.GetWidth();
|
||||
int16_t arcTextHeight = textRect.GetHeight();
|
||||
|
||||
SetPosition(textRect.GetX(), textRect.GetY());
|
||||
Resize(arcTextWidth, arcTextHeight);
|
||||
arcTextInfo_.arcCenter.x = arcCenter_.x - GetX();
|
||||
arcTextInfo_.arcCenter.y = arcCenter_.y - GetY();
|
||||
textSize_.x = arcTextWidth;
|
||||
textSize_.y = arcTextHeight;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UIArcLabel::MeasureArcTextInfo()
|
||||
{
|
||||
const char* text = arcLabelText_->GetText();
|
||||
if (text == nullptr) {
|
||||
return;
|
||||
}
|
||||
uint16_t letterHeight = UIFont::GetInstance()->GetHeight();
|
||||
arcTextInfo_.radius = ((orientation_ == TextOrientation::INSIDE) ? radius_ : (radius_ - letterHeight));
|
||||
if (arcTextInfo_.radius == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint16_t arcAngle;
|
||||
if (startAngle_ < endAngle_) {
|
||||
arcAngle = endAngle_ - startAngle_;
|
||||
arcTextInfo_.direct = TEXT_DIRECT_LTR; // Clockwise
|
||||
arcLabelText_->SetDirect(TEXT_DIRECT_LTR);
|
||||
} else {
|
||||
arcAngle = startAngle_ - endAngle_;
|
||||
arcTextInfo_.direct = TEXT_DIRECT_RTL; // Counterclockwise
|
||||
arcLabelText_->SetDirect(TEXT_DIRECT_RTL);
|
||||
}
|
||||
// calculate max arc length
|
||||
float maxLength = static_cast<float>((UI_PI * radius_ * arcAngle) / SEMICIRCLE_IN_DEGREE);
|
||||
arcTextInfo_.lineStart = 0;
|
||||
arcTextInfo_.lineEnd = TypedText::GetNextLine(&text[arcTextInfo_.lineStart], style_->letterSpace_, maxLength);
|
||||
arcTextInfo_.startAngle = startAngle_ % CIRCLE_IN_DEGREE;
|
||||
int16_t actLength = TypedText::GetTextWidth(&text[arcTextInfo_.lineStart],
|
||||
arcTextInfo_.lineEnd - arcTextInfo_.lineStart, style_->letterSpace_);
|
||||
if ((arcLabelText_->GetHorAlign() != TEXT_ALIGNMENT_LEFT) && (actLength < maxLength)) {
|
||||
float gapLength = maxLength - actLength;
|
||||
if (arcLabelText_->GetHorAlign() == TEXT_ALIGNMENT_CENTER) {
|
||||
gapLength = gapLength / 2; // 2: half
|
||||
}
|
||||
arcTextInfo_.startAngle += TypedText::GetAngleForArcLen(gapLength, letterHeight, arcTextInfo_.radius,
|
||||
arcTextInfo_.direct, orientation_);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+197
@@ -0,0 +1,197 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_axis.h"
|
||||
#include "common/screen.h"
|
||||
#include "draw/draw_line.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIAxis::UIAxis()
|
||||
: maxRange_(0),
|
||||
minRange_(0),
|
||||
start_({0, 0}),
|
||||
end_({0, 0}),
|
||||
markInterval_(0),
|
||||
dataPerMark_(0),
|
||||
dataInterval_(0),
|
||||
markDataCount_(AXIS_DEFAULT_MARK_INTERVAL),
|
||||
enableReverse_(false)
|
||||
{
|
||||
SetStyle(STYLE_LINE_WIDTH, 1);
|
||||
SetStyle(STYLE_LINE_COLOR, Color::White().full);
|
||||
}
|
||||
|
||||
void UIAxis::SetLineColor(const ColorType& color)
|
||||
{
|
||||
SetStyle(STYLE_LINE_COLOR, color.full);
|
||||
}
|
||||
|
||||
void UIXAxis::SetMarkNum(uint16_t count)
|
||||
{
|
||||
if ((count == 0) || (count > Screen::GetInstance().GetWidth())) {
|
||||
return;
|
||||
}
|
||||
markDataCount_ = count;
|
||||
UpdateAxis();
|
||||
}
|
||||
|
||||
bool UIXAxis::SetDataRange(uint16_t min, uint16_t max)
|
||||
{
|
||||
if (max <= min) {
|
||||
return false;
|
||||
}
|
||||
maxRange_ = max;
|
||||
minRange_ = min;
|
||||
return UpdateAxis();
|
||||
}
|
||||
|
||||
void UIXAxis::UpdateAxisPoints()
|
||||
{
|
||||
Rect current = GetContentRect();
|
||||
start_.x = current.GetLeft();
|
||||
end_.x = current.GetRight();
|
||||
start_.y = enableReverse_ ? current.GetTop() : current.GetBottom();
|
||||
end_.y = start_.y;
|
||||
}
|
||||
|
||||
bool UIXAxis::UpdateAxis()
|
||||
{
|
||||
UpdateAxisPoints();
|
||||
int16_t xAxisLength = end_.x - start_.x + 1;
|
||||
if (xAxisLength <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (markDataCount_ != 0) {
|
||||
dataInterval_ = static_cast<float>((maxRange_ - minRange_) / markDataCount_);
|
||||
markInterval_ = static_cast<float>(xAxisLength) / markDataCount_;
|
||||
if (maxRange_ > minRange_) {
|
||||
dataPerMark_ = markInterval_ / dataInterval_;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIXAxis::TranslateToPixel(int16_t& value)
|
||||
{
|
||||
float minXStep = dataPerMark_ ? dataPerMark_ : markInterval_;
|
||||
value = start_.x + static_cast<int16_t>((value - minRange_) * minXStep);
|
||||
}
|
||||
|
||||
void UIAxis::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
DrawLine::Draw(start_, end_, invalidatedArea, style_->lineWidth_, style_->lineColor_, style_->lineOpa_);
|
||||
DrawAxisMark(invalidatedArea);
|
||||
}
|
||||
|
||||
void UIXAxis::DrawAxisMark(const Rect& invalidatedArea)
|
||||
{
|
||||
Point start;
|
||||
Point end;
|
||||
uint16_t index = 1;
|
||||
while (index <= markDataCount_) {
|
||||
start.y = start_.y;
|
||||
start.x = start_.x + static_cast<int16_t>(index * markInterval_);
|
||||
end.y = enableReverse_ ? (start.y + AXIS_DEFAULT_MARK_LENGTH) : (start.y - AXIS_DEFAULT_MARK_LENGTH);
|
||||
end.x = start.x;
|
||||
|
||||
DrawLine::Draw(start, end, invalidatedArea, style_->lineWidth_, style_->lineColor_, style_->lineOpa_);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
void UIYAxis::SetMarkNum(uint16_t count)
|
||||
{
|
||||
if ((count == 0) || (count > Screen::GetInstance().GetHeight())) {
|
||||
return;
|
||||
}
|
||||
markDataCount_ = count;
|
||||
dataInterval_ = static_cast<float>((maxRange_ - minRange_) / markDataCount_);
|
||||
}
|
||||
|
||||
bool UIYAxis::SetDataRange(uint16_t min, uint16_t max)
|
||||
{
|
||||
if (max <= min) {
|
||||
return false;
|
||||
}
|
||||
|
||||
maxRange_ = max;
|
||||
minRange_ = min;
|
||||
return UpdateAxis();
|
||||
}
|
||||
|
||||
void UIYAxis::UpdateAxisPoints()
|
||||
{
|
||||
Rect current = GetContentRect();
|
||||
int16_t top = current.GetTop();
|
||||
int16_t bottom = current.GetBottom();
|
||||
|
||||
start_.x = current.GetLeft();
|
||||
end_.x = start_.x;
|
||||
if (enableReverse_) {
|
||||
start_.y = top;
|
||||
end_.y = bottom;
|
||||
} else {
|
||||
start_.y = bottom;
|
||||
end_.y = top;
|
||||
}
|
||||
}
|
||||
|
||||
void UIYAxis::TranslateToPixel(int16_t& value)
|
||||
{
|
||||
float minYStep = dataPerMark_ ? dataPerMark_ : markInterval_;
|
||||
if (enableReverse_) {
|
||||
value = start_.y + static_cast<int16_t>((maxRange_ - value + minRange_) * minYStep);
|
||||
} else {
|
||||
value = start_.y - static_cast<int16_t>((value - minRange_) * minYStep);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIYAxis::UpdateAxis()
|
||||
{
|
||||
UpdateAxisPoints();
|
||||
int16_t yAxisLength = enableReverse_ ? (end_.y - start_.y + 1) : (start_.y - end_.y + 1);
|
||||
if (yAxisLength <= 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (markDataCount_ != 0) {
|
||||
dataInterval_ = static_cast<float>((maxRange_ - minRange_) / markDataCount_);
|
||||
markInterval_ = static_cast<float>(yAxisLength) / markDataCount_;
|
||||
if (dataInterval_ != 0) {
|
||||
dataPerMark_ = markInterval_ / dataInterval_;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIYAxis::DrawAxisMark(const Rect& invalidatedArea)
|
||||
{
|
||||
uint16_t index = 1;
|
||||
while (index <= markDataCount_) {
|
||||
Point start;
|
||||
Point end;
|
||||
start.x = start_.x;
|
||||
start.y = enableReverse_ ? (start_.y + static_cast<int16_t>(index * markInterval_))
|
||||
: (start_.y - static_cast<int16_t>(index * markInterval_));
|
||||
end.x = start.x + AXIS_DEFAULT_MARK_LENGTH;
|
||||
end.y = start.y;
|
||||
|
||||
DrawLine::Draw(start, end, invalidatedArea, style_->lineWidth_, style_->lineColor_, style_->lineOpa_);
|
||||
index++;
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+237
@@ -0,0 +1,237 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_box_progress.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIBoxProgress::UIBoxProgress()
|
||||
: progressWidth_(0), progressHeight_(0), isValidWidthSet_(false), isValidHeightSet_(false)
|
||||
{
|
||||
SetDirection(Direction::DIR_LEFT_TO_RIGHT);
|
||||
}
|
||||
|
||||
void UIBoxProgress::DrawValidRect(const Image* image, const Rect& rect, const Rect& invalidatedArea,
|
||||
const Style& style, uint16_t radius)
|
||||
{
|
||||
Rect cordsTmp;
|
||||
if ((image != nullptr) && (image->GetSrcType() != IMG_SRC_UNKNOWN)) {
|
||||
ImageHeader header = {0};
|
||||
image->GetHeader(header);
|
||||
|
||||
Rect area(rect);
|
||||
switch (direction_) {
|
||||
case Direction::DIR_LEFT_TO_RIGHT:
|
||||
cordsTmp.SetPosition(area.GetLeft() - radius, area.GetTop());
|
||||
break;
|
||||
case Direction::DIR_TOP_TO_BOTTOM:
|
||||
cordsTmp.SetPosition(area.GetLeft(), area.GetTop() - radius);
|
||||
break;
|
||||
case Direction::DIR_RIGHT_TO_LEFT:
|
||||
cordsTmp.SetPosition(area.GetRight() + radius - header.width, area.GetTop());
|
||||
break;
|
||||
case Direction::DIR_BOTTOM_TO_TOP:
|
||||
cordsTmp.SetPosition(area.GetLeft(), area.GetBottom() + radius - header.height);
|
||||
break;
|
||||
default:
|
||||
GRAPHIC_LOGE("UIBoxProgress: DrawValidRect direction Err!\n");
|
||||
break;
|
||||
}
|
||||
cordsTmp.SetHeight(header.height);
|
||||
cordsTmp.SetWidth(header.width);
|
||||
if (area.Intersect(area, invalidatedArea)) {
|
||||
image->DrawImage(cordsTmp, area, style, opaScale_);
|
||||
}
|
||||
} else {
|
||||
DrawRect::Draw(rect, invalidatedArea, style, opaScale_);
|
||||
}
|
||||
|
||||
if (style.lineCap_ == CapType::CAP_ROUND) {
|
||||
DrawRoundCap(image, {cordsTmp.GetX(), cordsTmp.GetY()}, rect, invalidatedArea, radius, style);
|
||||
}
|
||||
}
|
||||
|
||||
void UIBoxProgress::DrawRoundCap(const Image* image, const Point& imgPos, const Rect& rect,
|
||||
const Rect& invalidatedArea, uint16_t radius, const Style& style)
|
||||
{
|
||||
Point leftTop;
|
||||
Point leftBottom;
|
||||
Point rightTop;
|
||||
Point rightBottom;
|
||||
|
||||
switch (direction_) {
|
||||
case Direction::DIR_LEFT_TO_RIGHT:
|
||||
case Direction::DIR_RIGHT_TO_LEFT: {
|
||||
leftTop.x = rect.GetLeft() - 1;
|
||||
leftTop.y = rect.GetTop() + radius - 1;
|
||||
leftBottom.x = leftTop.x;
|
||||
leftBottom.y = rect.GetBottom() - radius + 1;
|
||||
rightTop.x = rect.GetRight() + 1;
|
||||
rightTop.y = leftTop.y;
|
||||
rightBottom.x = rightTop.x;
|
||||
rightBottom.y = leftBottom.y;
|
||||
break;
|
||||
}
|
||||
|
||||
case Direction::DIR_TOP_TO_BOTTOM:
|
||||
case Direction::DIR_BOTTOM_TO_TOP: {
|
||||
leftTop.x = rect.GetLeft() + radius - 1;
|
||||
leftTop.y = rect.GetTop() - 1;
|
||||
rightTop.x = rect.GetRight() - radius + 1;
|
||||
rightTop.y = leftTop.y;
|
||||
leftBottom.x = leftTop.x;
|
||||
leftBottom.y = rect.GetBottom() + 1;
|
||||
rightBottom.x = rightTop.x;
|
||||
rightBottom.y = leftBottom.y;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
GRAPHIC_LOGE("UIBoxProgress: DrawRoundCap direction Err!\n");
|
||||
break;
|
||||
}
|
||||
|
||||
Style capStyle = style;
|
||||
capStyle.lineWidth_ = radius;
|
||||
capStyle.lineColor_ = style.bgColor_;
|
||||
capStyle.lineOpa_ = style.bgOpa_;
|
||||
ArcInfo arcInfo = {{0}};
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = imgPos;
|
||||
arcInfo.imgSrc = image;
|
||||
|
||||
arcInfo.center = leftTop;
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = 0;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, capStyle, opaScale_, CapType::CAP_NONE);
|
||||
|
||||
arcInfo.center = leftBottom;
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, capStyle, opaScale_, CapType::CAP_NONE);
|
||||
|
||||
arcInfo.center = rightTop;
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, capStyle, opaScale_, CapType::CAP_NONE);
|
||||
|
||||
arcInfo.center = rightBottom;
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, capStyle, opaScale_, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void UIBoxProgress::GetBackgroundParam(Point& startPoint, int16_t& width, int16_t& height, uint16_t& radius,
|
||||
const Style& style)
|
||||
{
|
||||
Rect rect = GetOrigRect();
|
||||
startPoint.x = rect.GetLeft() + style_->borderWidth_ + style_->paddingLeft_;
|
||||
startPoint.y = rect.GetTop() + style_->borderWidth_ + style_->paddingTop_;
|
||||
|
||||
radius = 0;
|
||||
width = progressWidth_;
|
||||
height = progressHeight_;
|
||||
if (style.lineCap_ == CapType::CAP_ROUND) {
|
||||
switch (direction_) {
|
||||
case Direction::DIR_LEFT_TO_RIGHT:
|
||||
case Direction::DIR_RIGHT_TO_LEFT:
|
||||
radius = (progressHeight_ + 1) >> 1;
|
||||
width -= radius << 1;
|
||||
startPoint.x += radius;
|
||||
break;
|
||||
case Direction::DIR_TOP_TO_BOTTOM:
|
||||
case Direction::DIR_BOTTOM_TO_TOP:
|
||||
radius = (progressWidth_ + 1) >> 1;
|
||||
height -= radius << 1;
|
||||
startPoint.y += radius;
|
||||
break;
|
||||
default:
|
||||
GRAPHIC_LOGE("UIBoxProgress: GetBackgroundParam direction Err!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIBoxProgress::DrawBackground(const Rect& invalidatedArea)
|
||||
{
|
||||
Point startPoint;
|
||||
int16_t progressWidth;
|
||||
int16_t progressHeight;
|
||||
uint16_t radius;
|
||||
GetBackgroundParam(startPoint, progressWidth, progressHeight, radius, *backgroundStyle_);
|
||||
|
||||
Rect coords(startPoint.x, startPoint.y, startPoint.x + progressWidth - 1, startPoint.y + progressHeight - 1);
|
||||
|
||||
DrawValidRect(backgroundImage_, coords, invalidatedArea, *backgroundStyle_, radius);
|
||||
}
|
||||
|
||||
void UIBoxProgress::DrawForeground(const Rect& invalidatedArea, Rect& coords)
|
||||
{
|
||||
Point startPoint;
|
||||
int16_t progressWidth;
|
||||
int16_t progressHeight;
|
||||
uint16_t radius;
|
||||
GetBackgroundParam(startPoint, progressWidth, progressHeight, radius, *foregroundStyle_);
|
||||
int16_t length;
|
||||
|
||||
switch (direction_) {
|
||||
case Direction::DIR_LEFT_TO_RIGHT: {
|
||||
length = GetCurrentPos(progressWidth - 1);
|
||||
coords.SetRect(startPoint.x, startPoint.y, startPoint.x + length, startPoint.y + progressHeight - 1);
|
||||
break;
|
||||
}
|
||||
case Direction::DIR_RIGHT_TO_LEFT: {
|
||||
length = GetCurrentPos(progressWidth - 1);
|
||||
coords.SetRect(startPoint.x + progressWidth - 1 - length,
|
||||
startPoint.y, startPoint.x + progressWidth - 1, startPoint.y + progressHeight - 1);
|
||||
break;
|
||||
}
|
||||
case Direction::DIR_TOP_TO_BOTTOM: {
|
||||
length = GetCurrentPos(progressHeight - 1);
|
||||
coords.SetRect(startPoint.x, startPoint.y, startPoint.x + progressWidth - 1, startPoint.y + length);
|
||||
break;
|
||||
}
|
||||
case Direction::DIR_BOTTOM_TO_TOP: {
|
||||
length = GetCurrentPos(progressHeight - 1);
|
||||
coords.SetRect(startPoint.x, startPoint.y + progressHeight - 1 - length,
|
||||
startPoint.x + progressWidth - 1, startPoint.y + progressHeight - 1);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
GRAPHIC_LOGE("UIBoxProgress: DrawForeground direction Err!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
DrawValidRect(foregroundImage_, coords, invalidatedArea, *foregroundStyle_, radius);
|
||||
}
|
||||
|
||||
void UIBoxProgress::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
DrawRect::Draw(GetOrigRect(), invalidatedArea, *style_, opaScale_);
|
||||
Rect trunc(invalidatedArea);
|
||||
if (trunc.Intersect(trunc, GetOrigRect())) {
|
||||
if (enableBackground_) {
|
||||
DrawBackground(trunc);
|
||||
}
|
||||
|
||||
if ((lastValue_ - rangeMin_ != 0) || (foregroundStyle_->lineCap_ == CapType::CAP_ROUND)) {
|
||||
Rect coords;
|
||||
DrawForeground(trunc, coords);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+278
@@ -0,0 +1,278 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_button.h"
|
||||
#include "common/image.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "style.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIButton::UIButton()
|
||||
: defaultImgSrc_(nullptr),
|
||||
triggeredImgSrc_(nullptr),
|
||||
currentImgSrc_(ButtonImageSrc::BTN_IMAGE_DEFAULT),
|
||||
imgX_(0),
|
||||
imgY_(0),
|
||||
contentWidth_(0),
|
||||
contentHeight_(0),
|
||||
state_(RELEASED),
|
||||
styleState_(RELEASED),
|
||||
buttonStyleAllocFlag_(false)
|
||||
{
|
||||
touchable_ = true;
|
||||
SetupThemeStyles();
|
||||
}
|
||||
|
||||
UIButton::~UIButton()
|
||||
{
|
||||
if (defaultImgSrc_ != nullptr) {
|
||||
delete defaultImgSrc_;
|
||||
defaultImgSrc_ = nullptr;
|
||||
}
|
||||
|
||||
if (triggeredImgSrc_ != nullptr) {
|
||||
delete triggeredImgSrc_;
|
||||
triggeredImgSrc_ = nullptr;
|
||||
}
|
||||
|
||||
if (buttonStyleAllocFlag_) {
|
||||
for (uint8_t i = 0; i < BTN_STATE_NUM; i++) {
|
||||
delete buttonStyles_[i];
|
||||
buttonStyles_[i] = nullptr;
|
||||
}
|
||||
buttonStyleAllocFlag_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UIButton::DrawImg(const Rect& invalidatedArea, OpacityType opaScale)
|
||||
{
|
||||
const Image* image = GetCurImageSrc();
|
||||
if (image == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageHeader header = {0};
|
||||
image->GetHeader(header);
|
||||
Rect coords;
|
||||
Rect viewRect = GetContentRect();
|
||||
coords.SetLeft(viewRect.GetLeft() + GetImageX());
|
||||
coords.SetTop(viewRect.GetTop() + GetImageY());
|
||||
coords.SetWidth(header.width);
|
||||
coords.SetHeight(header.height);
|
||||
|
||||
Rect trunc(invalidatedArea);
|
||||
if (trunc.Intersect(trunc, viewRect)) {
|
||||
image->DrawImage(coords, trunc, *buttonStyles_[state_], opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void UIButton::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
OpacityType opa = GetMixOpaScale();
|
||||
DrawRect::Draw(GetOrigRect(), invalidatedArea, *buttonStyles_[state_], opa);
|
||||
DrawImg(invalidatedArea, opa);
|
||||
}
|
||||
|
||||
void UIButton::SetupThemeStyles()
|
||||
{
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
|
||||
if (theme == nullptr) {
|
||||
buttonStyles_[RELEASED] = &(StyleDefault::GetButtonReleasedStyle());
|
||||
buttonStyles_[PRESSED] = &(StyleDefault::GetButtonPressedStyle());
|
||||
buttonStyles_[INACTIVE] = &(StyleDefault::GetButtonInactiveStyle());
|
||||
} else {
|
||||
buttonStyles_[RELEASED] = &(theme->GetButtonStyle().released);
|
||||
buttonStyles_[PRESSED] = &(theme->GetButtonStyle().pressed);
|
||||
buttonStyles_[INACTIVE] = &(theme->GetButtonStyle().inactive);
|
||||
}
|
||||
}
|
||||
|
||||
int64_t UIButton::GetStyle(uint8_t key) const
|
||||
{
|
||||
return GetStyleForState(key, styleState_);
|
||||
}
|
||||
|
||||
void UIButton::SetStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
SetStyleForState(key, value, styleState_);
|
||||
}
|
||||
|
||||
int64_t UIButton::GetStyleForState(uint8_t key, ButtonState state) const
|
||||
{
|
||||
if (state < BTN_STATE_NUM) {
|
||||
return (buttonStyles_[state])->GetStyle(key);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void UIButton::SetStyleForState(uint8_t key, int64_t value, ButtonState state)
|
||||
{
|
||||
if (state < BTN_STATE_NUM) {
|
||||
if (!buttonStyleAllocFlag_) {
|
||||
for (uint8_t i = 0; i < BTN_STATE_NUM; i++) {
|
||||
Style styleSaved = *buttonStyles_[i];
|
||||
buttonStyles_[i] = new Style;
|
||||
if (buttonStyles_[i] == nullptr) {
|
||||
GRAPHIC_LOGE("new Style fail");
|
||||
return;
|
||||
}
|
||||
*(buttonStyles_[i]) = styleSaved;
|
||||
}
|
||||
buttonStyleAllocFlag_ = true;
|
||||
}
|
||||
int16_t width = GetWidth();
|
||||
int16_t height = GetHeight();
|
||||
buttonStyles_[state]->SetStyle(key, value);
|
||||
switch (key) {
|
||||
case STYLE_BORDER_WIDTH: {
|
||||
SetWidth(width);
|
||||
SetHeight(height);
|
||||
break;
|
||||
}
|
||||
case STYLE_PADDING_LEFT:
|
||||
case STYLE_PADDING_RIGHT: {
|
||||
SetWidth(width);
|
||||
break;
|
||||
}
|
||||
case STYLE_PADDING_TOP:
|
||||
case STYLE_PADDING_BOTTOM: {
|
||||
SetHeight(height);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UIButton::OnPressEvent(const PressEvent& event)
|
||||
{
|
||||
currentImgSrc_ = ButtonImageSrc::BTN_IMAGE_TRIGGERED;
|
||||
SetState(PRESSED);
|
||||
Resize(contentWidth_, contentHeight_);
|
||||
Invalidate();
|
||||
return UIView::OnPressEvent(event);
|
||||
}
|
||||
|
||||
bool UIButton::OnReleaseEvent(const ReleaseEvent& event)
|
||||
{
|
||||
currentImgSrc_ = ButtonImageSrc::BTN_IMAGE_DEFAULT;
|
||||
SetState(RELEASED);
|
||||
Resize(contentWidth_, contentHeight_);
|
||||
Invalidate();
|
||||
return UIView::OnReleaseEvent(event);
|
||||
}
|
||||
|
||||
bool UIButton::OnCancelEvent(const CancelEvent& event)
|
||||
{
|
||||
currentImgSrc_ = ButtonImageSrc::BTN_IMAGE_DEFAULT;
|
||||
SetState(RELEASED);
|
||||
Resize(contentWidth_, contentHeight_);
|
||||
Invalidate();
|
||||
return UIView::OnCancelEvent(event);
|
||||
}
|
||||
|
||||
const Image* UIButton::GetCurImageSrc() const
|
||||
{
|
||||
if (currentImgSrc_ == ButtonImageSrc::BTN_IMAGE_DEFAULT) {
|
||||
return defaultImgSrc_;
|
||||
} else if (currentImgSrc_ == ButtonImageSrc::BTN_IMAGE_TRIGGERED) {
|
||||
return triggeredImgSrc_;
|
||||
} else {
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UIButton::SetImageSrc(const char* defaultImgSrc, const char* triggeredImgSrc)
|
||||
{
|
||||
if (!InitImage()) {
|
||||
return;
|
||||
}
|
||||
defaultImgSrc_->SetSrc(defaultImgSrc);
|
||||
triggeredImgSrc_->SetSrc(triggeredImgSrc);
|
||||
}
|
||||
|
||||
void UIButton::SetImageSrc(const ImageInfo* defaultImgSrc, const ImageInfo* triggeredImgSrc)
|
||||
{
|
||||
if (!InitImage()) {
|
||||
return;
|
||||
}
|
||||
defaultImgSrc_->SetSrc(defaultImgSrc);
|
||||
triggeredImgSrc_->SetSrc(triggeredImgSrc);
|
||||
}
|
||||
|
||||
void UIButton::Disable()
|
||||
{
|
||||
SetState(INACTIVE);
|
||||
touchable_ = false;
|
||||
}
|
||||
|
||||
void UIButton::Enable()
|
||||
{
|
||||
SetState(RELEASED);
|
||||
touchable_ = true;
|
||||
}
|
||||
|
||||
void UIButton::SetState(ButtonState state)
|
||||
{
|
||||
state_ = state;
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
bool UIButton::InitImage()
|
||||
{
|
||||
if (defaultImgSrc_ == nullptr) {
|
||||
defaultImgSrc_ = new Image();
|
||||
if (defaultImgSrc_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Image fail");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (triggeredImgSrc_ == nullptr) {
|
||||
triggeredImgSrc_ = new Image();
|
||||
if (triggeredImgSrc_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Image fail");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIButton::OnPreDraw(Rect& invalidatedArea) const
|
||||
{
|
||||
Rect rect(GetRect());
|
||||
int16_t r = buttonStyles_[styleState_]->borderRadius_;
|
||||
if (r == COORD_MAX) {
|
||||
return true;
|
||||
}
|
||||
if (r != 0) {
|
||||
r = ((r & 0x1) == 0) ? (r >> 1) : ((r + 1) >> 1);
|
||||
rect.SetLeft(rect.GetX() + r);
|
||||
rect.SetWidth(rect.GetWidth() - r);
|
||||
rect.SetTop(rect.GetY() + r);
|
||||
rect.SetHeight(rect.GetHeight() - r);
|
||||
}
|
||||
if (rect.IsContains(invalidatedArea)) {
|
||||
return true;
|
||||
}
|
||||
invalidatedArea.Intersect(invalidatedArea, rect);
|
||||
return false;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+807
@@ -0,0 +1,807 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_canvas.h"
|
||||
#include "common/image.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_curve.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_line.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
UICanvas::UICanvasPath::~UICanvasPath()
|
||||
{
|
||||
points_.Clear();
|
||||
cmd_.Clear();
|
||||
arcParam_.Clear();
|
||||
}
|
||||
|
||||
void UICanvas::BeginPath()
|
||||
{
|
||||
/* If the previous path is not added to the drawing linked list, it should be destroyed directly. */
|
||||
if (path_ != nullptr && path_->strokeCount_ == 0) {
|
||||
delete path_;
|
||||
path_ = nullptr;
|
||||
}
|
||||
|
||||
path_ = new UICanvasPath();
|
||||
if (path_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UICanvasPath fail");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::MoveTo(const Point& point)
|
||||
{
|
||||
if (path_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
path_->startPos_ = point;
|
||||
/* If the previous command is also CMD_MOVE_TO, the previous command is overwritten. */
|
||||
if ((path_->cmd_.Size() != 0) && (path_->cmd_.Tail()->data_ == CMD_MOVE_TO)) {
|
||||
path_->points_.Tail()->data_ = point;
|
||||
return;
|
||||
}
|
||||
path_->points_.PushBack(point);
|
||||
path_->cmd_.PushBack(CMD_MOVE_TO);
|
||||
}
|
||||
|
||||
void UICanvas::LineTo(const Point& point)
|
||||
{
|
||||
if (path_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
path_->points_.PushBack(point);
|
||||
if (path_->cmd_.Size() == 0) {
|
||||
path_->startPos_ = point;
|
||||
path_->cmd_.PushBack(CMD_MOVE_TO);
|
||||
} else {
|
||||
path_->cmd_.PushBack(CMD_LINE_TO);
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::ArcTo(const Point& center, uint16_t radius, int16_t startAngle, int16_t endAngle)
|
||||
{
|
||||
if (path_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is no command before CMD_ARC, only the arc is drawn. If there is a command in front of
|
||||
* CMD_ARC, the start point of arc must be connected to the end point of the path.
|
||||
*/
|
||||
float sinma = radius * Sin(startAngle);
|
||||
float cosma = radius * Sin(QUARTER_IN_DEGREE - startAngle);
|
||||
if (path_->cmd_.Size() != 0) {
|
||||
path_->points_.PushBack({MATH_ROUND(center.x + sinma), MATH_ROUND(center.y - cosma)});
|
||||
path_->cmd_.PushBack(CMD_LINE_TO);
|
||||
} else {
|
||||
path_->startPos_ = {MATH_ROUND(center.x + sinma), MATH_ROUND(center.y - cosma)};
|
||||
}
|
||||
|
||||
/* If the ARC scan range exceeds 360 degrees, the end point of the path is the position of the start angle. */
|
||||
if (MATH_ABS(startAngle - endAngle) < CIRCLE_IN_DEGREE) {
|
||||
sinma = radius * Sin(endAngle);
|
||||
cosma = radius * Sin(QUARTER_IN_DEGREE - endAngle);
|
||||
}
|
||||
path_->points_.PushBack({MATH_ROUND(center.x + sinma), MATH_ROUND(center.y - cosma)});
|
||||
path_->cmd_.PushBack(CMD_ARC);
|
||||
|
||||
int16_t start;
|
||||
int16_t end;
|
||||
if (startAngle > endAngle) {
|
||||
start = endAngle;
|
||||
end = startAngle;
|
||||
} else {
|
||||
start = startAngle;
|
||||
end = endAngle;
|
||||
}
|
||||
|
||||
DrawArc::GetInstance()->GetDrawRange(start, end);
|
||||
ArcParam param;
|
||||
param.center = center;
|
||||
param.radius = radius;
|
||||
param.startAngle = start;
|
||||
param.endAngle = end;
|
||||
path_->arcParam_.PushBack(param);
|
||||
}
|
||||
|
||||
void UICanvas::AddRect(const Point& point, int16_t height, int16_t width)
|
||||
{
|
||||
if (path_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
MoveTo(point);
|
||||
LineTo({static_cast<int16_t>(point.x + width), point.y});
|
||||
LineTo({static_cast<int16_t>(point.x + width), static_cast<int16_t>(point.y + height)});
|
||||
LineTo({point.x, static_cast<int16_t>(point.y + height)});
|
||||
ClosePath();
|
||||
}
|
||||
|
||||
void UICanvas::ClosePath()
|
||||
{
|
||||
if ((path_ == nullptr) || (path_->cmd_.Size() == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
path_->points_.PushBack(path_->startPos_);
|
||||
path_->cmd_.PushBack(CMD_CLOSE);
|
||||
}
|
||||
|
||||
UICanvas::~UICanvas()
|
||||
{
|
||||
if ((path_ != nullptr) && (path_->strokeCount_ == 0)) {
|
||||
delete path_;
|
||||
path_ = nullptr;
|
||||
}
|
||||
|
||||
void* param = nullptr;
|
||||
ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
|
||||
for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
|
||||
param = curDraw->data_.param;
|
||||
curDraw->data_.DeleteParam(param);
|
||||
curDraw->data_.param = nullptr;
|
||||
}
|
||||
drawCmdList_.Clear();
|
||||
}
|
||||
|
||||
void UICanvas::Clear()
|
||||
{
|
||||
if ((path_ != nullptr) && (path_->strokeCount_ == 0)) {
|
||||
delete path_;
|
||||
path_ = nullptr;
|
||||
}
|
||||
|
||||
void* param = nullptr;
|
||||
ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
|
||||
for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
|
||||
param = curDraw->data_.param;
|
||||
curDraw->data_.DeleteParam(param);
|
||||
curDraw->data_.param = nullptr;
|
||||
}
|
||||
drawCmdList_.Clear();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UICanvas::DrawLine(const Point& endPoint, const Paint& paint)
|
||||
{
|
||||
DrawLine(startPoint_, endPoint, paint);
|
||||
}
|
||||
|
||||
void UICanvas::DrawLine(const Point& startPoint, const Point& endPoint, const Paint& paint)
|
||||
{
|
||||
LineParam* lineParam = new LineParam;
|
||||
if (lineParam == nullptr) {
|
||||
GRAPHIC_LOGE("new LineParam fail");
|
||||
return;
|
||||
}
|
||||
lineParam->start = startPoint;
|
||||
lineParam->end = endPoint;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = lineParam;
|
||||
cmd.DeleteParam = DeleteLineParam;
|
||||
cmd.DrawGraphics = DoDrawLine;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
|
||||
Invalidate();
|
||||
SetStartPosition(endPoint);
|
||||
}
|
||||
|
||||
void UICanvas::DrawCurve(const Point& control1, const Point& control2, const Point& endPoint, const Paint& paint)
|
||||
{
|
||||
DrawCurve(startPoint_, control1, control2, endPoint, paint);
|
||||
}
|
||||
|
||||
void UICanvas::DrawCurve(const Point& startPoint,
|
||||
const Point& control1,
|
||||
const Point& control2,
|
||||
const Point& endPoint,
|
||||
const Paint& paint)
|
||||
{
|
||||
CurveParam* curveParam = new CurveParam;
|
||||
if (curveParam == nullptr) {
|
||||
GRAPHIC_LOGE("new CurveParam fail");
|
||||
return;
|
||||
}
|
||||
curveParam->start = startPoint;
|
||||
curveParam->control1 = control1;
|
||||
curveParam->control2 = control2;
|
||||
curveParam->end = endPoint;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
if (paint.GetStrokeWidth() > MAX_CURVE_WIDTH) {
|
||||
cmd.paint.SetStrokeWidth(MAX_CURVE_WIDTH);
|
||||
}
|
||||
cmd.param = curveParam;
|
||||
cmd.DeleteParam = DeleteCurveParam;
|
||||
cmd.DrawGraphics = DoDrawCurve;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
|
||||
Invalidate();
|
||||
SetStartPosition(endPoint);
|
||||
}
|
||||
|
||||
void UICanvas::DrawRect(const Point& startPoint, int16_t height, int16_t width, const Paint& paint)
|
||||
{
|
||||
if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
|
||||
RectParam* rectParam = new RectParam;
|
||||
if (rectParam == nullptr) {
|
||||
GRAPHIC_LOGE("new RectParam fail");
|
||||
return;
|
||||
}
|
||||
rectParam->start = startPoint;
|
||||
rectParam->height = height;
|
||||
rectParam->width = width;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = rectParam;
|
||||
cmd.DeleteParam = DeleteRectParam;
|
||||
cmd.DrawGraphics = DoDrawRect;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
}
|
||||
|
||||
if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
|
||||
RectParam* rectParam = new RectParam;
|
||||
if (rectParam == nullptr) {
|
||||
GRAPHIC_LOGE("new RectParam fail");
|
||||
return;
|
||||
}
|
||||
rectParam->start = startPoint;
|
||||
rectParam->height = height;
|
||||
rectParam->width = width;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = rectParam;
|
||||
cmd.DeleteParam = DeleteRectParam;
|
||||
cmd.DrawGraphics = DoFillRect;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UICanvas::DrawCircle(const Point& center, uint16_t radius, const Paint& paint)
|
||||
{
|
||||
CircleParam* circleParam = new CircleParam;
|
||||
if (circleParam == nullptr) {
|
||||
GRAPHIC_LOGE("new CircleParam fail");
|
||||
return;
|
||||
}
|
||||
circleParam->center = center;
|
||||
circleParam->radius = radius;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = circleParam;
|
||||
cmd.DeleteParam = DeleteCircleParam;
|
||||
cmd.DrawGraphics = DoDrawCircle;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UICanvas::DrawSector(const Point& center,
|
||||
uint16_t radius,
|
||||
int16_t startAngle,
|
||||
int16_t endAngle,
|
||||
const Paint& paint)
|
||||
{
|
||||
if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
|
||||
Paint innerPaint = paint;
|
||||
innerPaint.SetStyle(Paint::PaintStyle::STROKE_STYLE);
|
||||
innerPaint.SetStrokeWidth(radius);
|
||||
innerPaint.SetStrokeColor(paint.GetFillColor());
|
||||
radius >>= 1;
|
||||
DrawArc(center, radius, startAngle, endAngle, innerPaint);
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::DrawArc(const Point& center, uint16_t radius, int16_t startAngle, int16_t endAngle, const Paint& paint)
|
||||
{
|
||||
if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE) {
|
||||
ArcParam* arcParam = new ArcParam;
|
||||
if (arcParam == nullptr) {
|
||||
GRAPHIC_LOGE("new ArcParam fail");
|
||||
return;
|
||||
}
|
||||
arcParam->center = center;
|
||||
arcParam->radius = radius;
|
||||
|
||||
int16_t start;
|
||||
int16_t end;
|
||||
if (startAngle > endAngle) {
|
||||
start = endAngle;
|
||||
end = startAngle;
|
||||
} else {
|
||||
start = startAngle;
|
||||
end = endAngle;
|
||||
}
|
||||
|
||||
DrawArc::GetInstance()->GetDrawRange(start, end);
|
||||
arcParam->startAngle = start;
|
||||
arcParam->endAngle = end;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = arcParam;
|
||||
cmd.DeleteParam = DeleteArcParam;
|
||||
cmd.DrawGraphics = DoDrawArc;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::DrawLabel(const Point& startPoint,
|
||||
const char* text,
|
||||
uint16_t maxWidth,
|
||||
const FontStyle& fontStyle,
|
||||
const Paint& paint)
|
||||
{
|
||||
if (text == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
|
||||
UILabel* label = new UILabel();
|
||||
if (label == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
label->SetLineBreakMode(UILabel::LINE_BREAK_CLIP);
|
||||
label->SetPosition(startPoint.x, startPoint.y);
|
||||
label->SetWidth(maxWidth);
|
||||
label->SetHeight(GetHeight());
|
||||
label->SetText(text);
|
||||
label->SetFont(fontStyle.fontName, fontStyle.fontSize);
|
||||
label->SetAlign(fontStyle.align);
|
||||
label->SetDirect(fontStyle.direct);
|
||||
label->SetStyle(STYLE_LETTER_SPACE, fontStyle.letterSpace);
|
||||
label->SetStyle(STYLE_TEXT_COLOR, paint.GetFillColor().full);
|
||||
label->SetStyle(STYLE_TEXT_OPA, paint.GetOpacity());
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.param = label;
|
||||
cmd.DeleteParam = DeleteLabel;
|
||||
cmd.DrawGraphics = DoDrawLabel;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::DrawImage(const Point& startPoint, const char* image, const Paint& paint)
|
||||
{
|
||||
if (image == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageParam* imageParam = new ImageParam;
|
||||
if (imageParam == nullptr) {
|
||||
GRAPHIC_LOGE("new ImageParam fail");
|
||||
return;
|
||||
}
|
||||
imageParam->image = new Image();
|
||||
if (imageParam->image == nullptr) {
|
||||
delete imageParam;
|
||||
imageParam = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
imageParam->image->SetSrc(image);
|
||||
ImageHeader header = {0};
|
||||
imageParam->image->GetHeader(header);
|
||||
imageParam->start = startPoint;
|
||||
imageParam->height = header.height;
|
||||
imageParam->width = header.width;
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = imageParam;
|
||||
cmd.DeleteParam = DeleteImageParam;
|
||||
cmd.DrawGraphics = DoDrawImage;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UICanvas::DrawPath(const Paint& paint)
|
||||
{
|
||||
if ((path_ == nullptr) || (path_->cmd_.Size() == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
path_->strokeCount_++;
|
||||
PathParam* param = new PathParam;
|
||||
if (param == nullptr) {
|
||||
GRAPHIC_LOGE("new PathParam fail");
|
||||
return;
|
||||
}
|
||||
param->path = path_;
|
||||
param->count = path_->cmd_.Size();
|
||||
|
||||
DrawCmd cmd;
|
||||
cmd.paint = paint;
|
||||
cmd.param = param;
|
||||
cmd.DeleteParam = DeletePathParam;
|
||||
cmd.DrawGraphics = DoDrawPath;
|
||||
drawCmdList_.PushBack(cmd);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UICanvas::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
Rect rect = GetOrigRect();
|
||||
DrawRect::Draw(rect, invalidatedArea, *style_, opaScale_);
|
||||
|
||||
void* param = nullptr;
|
||||
ListNode<DrawCmd>* curDraw = drawCmdList_.Begin();
|
||||
Rect coords = GetOrigRect();
|
||||
Rect trunc = invalidatedArea;
|
||||
if (trunc.Intersect(trunc, coords)) {
|
||||
for (; curDraw != drawCmdList_.End(); curDraw = curDraw->next_) {
|
||||
param = curDraw->data_.param;
|
||||
curDraw->data_.DrawGraphics(param, curDraw->data_.paint, rect, trunc, *style_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::GetAbsolutePosition(const Point& prePoint, const Rect& rect, const Style& style, Point& point)
|
||||
{
|
||||
point.x = prePoint.x + rect.GetLeft() + style.paddingLeft_ + style.borderWidth_;
|
||||
point.y = prePoint.y + rect.GetTop() + style.paddingTop_ + style.borderWidth_;
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawLine(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
LineParam* lineParam = static_cast<LineParam*>(param);
|
||||
Point start;
|
||||
Point end;
|
||||
GetAbsolutePosition(lineParam->start, rect, style, start);
|
||||
GetAbsolutePosition(lineParam->end, rect, style, end);
|
||||
|
||||
DrawLine::Draw(start, end, invalidatedArea, paint.GetStrokeWidth(), paint.GetStrokeColor(), paint.GetOpacity());
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawCurve(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
CurveParam* curveParam = static_cast<CurveParam*>(param);
|
||||
Point start;
|
||||
Point end;
|
||||
Point control1;
|
||||
Point control2;
|
||||
GetAbsolutePosition(curveParam->start, rect, style, start);
|
||||
GetAbsolutePosition(curveParam->end, rect, style, end);
|
||||
GetAbsolutePosition(curveParam->control1, rect, style, control1);
|
||||
GetAbsolutePosition(curveParam->control2, rect, style, control2);
|
||||
|
||||
DrawCurve::DrawCubicBezier(start, control1, control2, end, invalidatedArea, paint.GetStrokeWidth(),
|
||||
paint.GetStrokeColor(), paint.GetOpacity());
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawRect(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
RectParam* rectParam = static_cast<RectParam*>(param);
|
||||
Style drawStyle = StyleDefault::GetDefaultStyle();
|
||||
drawStyle.bgColor_ = paint.GetStrokeColor();
|
||||
drawStyle.bgOpa_ = paint.GetOpacity();
|
||||
drawStyle.borderRadius_ = 0;
|
||||
|
||||
int16_t lineWidth = static_cast<int16_t>(paint.GetStrokeWidth());
|
||||
Point start;
|
||||
GetAbsolutePosition(rectParam->start, rect, style, start);
|
||||
|
||||
int16_t x = start.x - lineWidth / 2; // 2: half
|
||||
int16_t y = start.y - lineWidth / 2; // 2: half
|
||||
Rect coords;
|
||||
if ((rectParam->height <= lineWidth) || (rectParam->width <= lineWidth)) {
|
||||
coords.SetPosition(x, y);
|
||||
coords.SetHeight(rectParam->height + lineWidth);
|
||||
coords.SetWidth(rectParam->width + lineWidth);
|
||||
DrawRect::Draw(coords, invalidatedArea, drawStyle, OPA_OPAQUE);
|
||||
return;
|
||||
}
|
||||
|
||||
coords.SetPosition(x, y);
|
||||
coords.SetHeight(lineWidth);
|
||||
coords.SetWidth(rectParam->width);
|
||||
DrawRect::Draw(coords, invalidatedArea, drawStyle, OPA_OPAQUE);
|
||||
|
||||
coords.SetPosition(x + rectParam->width, y);
|
||||
coords.SetHeight(rectParam->height);
|
||||
coords.SetWidth(lineWidth);
|
||||
DrawRect::Draw(coords, invalidatedArea, drawStyle, OPA_OPAQUE);
|
||||
|
||||
coords.SetPosition(x, y + lineWidth);
|
||||
coords.SetHeight(rectParam->height);
|
||||
coords.SetWidth(lineWidth);
|
||||
DrawRect::Draw(coords, invalidatedArea, drawStyle, OPA_OPAQUE);
|
||||
|
||||
coords.SetPosition(x + lineWidth, y + rectParam->height);
|
||||
coords.SetHeight(lineWidth);
|
||||
coords.SetWidth(rectParam->width);
|
||||
DrawRect::Draw(coords, invalidatedArea, drawStyle, OPA_OPAQUE);
|
||||
}
|
||||
|
||||
void UICanvas::DoFillRect(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
RectParam* rectParam = static_cast<RectParam*>(param);
|
||||
uint8_t enableStroke = static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE;
|
||||
int16_t lineWidth = enableStroke ? paint.GetStrokeWidth() : 0;
|
||||
if ((rectParam->height <= lineWidth) || (rectParam->width <= lineWidth)) {
|
||||
return;
|
||||
}
|
||||
Point start;
|
||||
GetAbsolutePosition(rectParam->start, rect, style, start);
|
||||
|
||||
Rect coords;
|
||||
coords.SetPosition(start.x + (lineWidth + 1) / 2, start.y + (lineWidth + 1) / 2); // 2: half
|
||||
coords.SetHeight(rectParam->height - lineWidth);
|
||||
coords.SetWidth(rectParam->width - lineWidth);
|
||||
|
||||
Style drawStyle = StyleDefault::GetDefaultStyle();
|
||||
drawStyle.bgColor_ = paint.GetFillColor();
|
||||
drawStyle.bgOpa_ = paint.GetOpacity();
|
||||
drawStyle.borderRadius_ = 0;
|
||||
DrawRect::Draw(coords, invalidatedArea, drawStyle, OPA_OPAQUE);
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawCircle(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
CircleParam* circleParam = static_cast<CircleParam*>(param);
|
||||
|
||||
Style drawStyle = StyleDefault::GetDefaultStyle();
|
||||
drawStyle.lineOpa_ = paint.GetOpacity();
|
||||
|
||||
ArcInfo arcInfo = {{0}};
|
||||
arcInfo.imgPos = Point{0, 0};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
GetAbsolutePosition(circleParam->center, rect, style, arcInfo.center);
|
||||
uint8_t enableStroke = static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::STROKE_STYLE;
|
||||
uint16_t halfLineWidth = enableStroke ? (paint.GetStrokeWidth() >> 1) : 0;
|
||||
if (static_cast<uint8_t>(paint.GetStyle()) & Paint::PaintStyle::FILL_STYLE) {
|
||||
arcInfo.radius = circleParam->radius - halfLineWidth;
|
||||
drawStyle.lineWidth_ = arcInfo.radius;
|
||||
drawStyle.lineColor_ = paint.GetFillColor();
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
if (enableStroke) {
|
||||
arcInfo.radius = circleParam->radius + halfLineWidth - 1;
|
||||
drawStyle.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
|
||||
drawStyle.lineColor_ = paint.GetStrokeColor();
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawArc(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
ArcParam* arcParam = static_cast<ArcParam*>(param);
|
||||
|
||||
ArcInfo arcInfo = {{0}};
|
||||
arcInfo.imgPos = Point{0, 0};
|
||||
arcInfo.startAngle = arcParam->startAngle;
|
||||
arcInfo.endAngle = arcParam->endAngle;
|
||||
Style drawStyle = StyleDefault::GetDefaultStyle();
|
||||
drawStyle.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
|
||||
drawStyle.lineColor_ = paint.GetStrokeColor();
|
||||
drawStyle.lineOpa_ = paint.GetOpacity();
|
||||
arcInfo.radius = arcParam->radius + ((paint.GetStrokeWidth() + 1) >> 1);
|
||||
|
||||
GetAbsolutePosition(arcParam->center, rect, style, arcInfo.center);
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawImage(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
ImageParam* imageParam = static_cast<ImageParam*>(param);
|
||||
|
||||
if (imageParam->image == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point start;
|
||||
GetAbsolutePosition(imageParam->start, rect, style, start);
|
||||
|
||||
Rect cordsTmp;
|
||||
cordsTmp.SetPosition(start.x, start.y);
|
||||
cordsTmp.SetHeight(imageParam->height);
|
||||
cordsTmp.SetWidth(imageParam->width);
|
||||
DrawImage::DrawCommon(cordsTmp, invalidatedArea, imageParam->image->GetPath(), style, paint.GetOpacity());
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawLabel(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
UILabel* label = static_cast<UILabel*>(param);
|
||||
Point startPos = {label->GetX(), label->GetY()};
|
||||
Point start;
|
||||
GetAbsolutePosition({startPos.x, startPos.y}, rect, style, start);
|
||||
label->SetPosition(start.x, start.y);
|
||||
label->OnDraw(invalidatedArea);
|
||||
label->SetPosition(startPos.x, startPos.y);
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawLineJoin(const Point& center, const Rect& invalidatedArea, const Paint& paint)
|
||||
{
|
||||
ArcInfo arcinfo = {{0}};
|
||||
arcinfo.center = center;
|
||||
arcinfo.imgPos = Point{0, 0};
|
||||
arcinfo.radius = (paint.GetStrokeWidth() + 1) >> 1;
|
||||
arcinfo.startAngle = 0;
|
||||
arcinfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
|
||||
Style style;
|
||||
style.lineColor_ = paint.GetStrokeColor();
|
||||
style.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
|
||||
style.lineOpa_ = OPA_OPAQUE;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, invalidatedArea, style, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void UICanvas::DoDrawPath(void* param,
|
||||
const Paint& paint,
|
||||
const Rect& rect,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style)
|
||||
{
|
||||
if (param == nullptr) {
|
||||
return;
|
||||
}
|
||||
PathParam* pathParam = static_cast<PathParam*>(param);
|
||||
const UICanvasPath* path = pathParam->path;
|
||||
if (path == nullptr) {
|
||||
return;
|
||||
}
|
||||
Point pathEnd = {COORD_MIN, COORD_MIN};
|
||||
|
||||
ListNode<Point>* pointIter = path->points_.Begin();
|
||||
ListNode<ArcParam>* arcIter = path->arcParam_.Begin();
|
||||
ListNode<PathCmd>* iter = path->cmd_.Begin();
|
||||
for (uint16_t i = 0; (i < pathParam->count) && (iter != path->cmd_.End()); i++, iter = iter->next_) {
|
||||
switch (iter->data_) {
|
||||
case CMD_MOVE_TO: {
|
||||
pointIter = pointIter->next_;
|
||||
break;
|
||||
}
|
||||
case CMD_LINE_TO: {
|
||||
Point start = pointIter->prev_->data_;
|
||||
Point end = pointIter->data_;
|
||||
pointIter = pointIter->next_;
|
||||
if ((start.x == end.x) && (start.y == end.y)) {
|
||||
break;
|
||||
}
|
||||
|
||||
GetAbsolutePosition(start, rect, style, start);
|
||||
GetAbsolutePosition(end, rect, style, end);
|
||||
DrawLine::Draw(start, end, invalidatedArea, paint.GetStrokeWidth(), paint.GetStrokeColor(), OPA_OPAQUE);
|
||||
if ((pathEnd.x == start.x) && (pathEnd.y == start.y)) {
|
||||
DoDrawLineJoin(start, invalidatedArea, paint);
|
||||
}
|
||||
pathEnd = end;
|
||||
break;
|
||||
}
|
||||
case CMD_ARC: {
|
||||
ArcInfo arcInfo = {{0}};
|
||||
arcInfo.imgPos = Point{0, 0};
|
||||
arcInfo.startAngle = arcIter->data_.startAngle;
|
||||
arcInfo.endAngle = arcIter->data_.endAngle;
|
||||
Style drawStyle = StyleDefault::GetDefaultStyle();
|
||||
drawStyle.lineWidth_ = static_cast<int16_t>(paint.GetStrokeWidth());
|
||||
drawStyle.lineColor_ = paint.GetStrokeColor();
|
||||
drawStyle.lineOpa_ = OPA_OPAQUE;
|
||||
arcInfo.radius = arcIter->data_.radius + ((paint.GetStrokeWidth() + 1) >> 1);
|
||||
|
||||
GetAbsolutePosition(arcIter->data_.center, rect, style, arcInfo.center);
|
||||
DrawArc::GetInstance()->Draw(arcInfo, invalidatedArea, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
if (pointIter != path->points_.Begin()) {
|
||||
DoDrawLineJoin(pathEnd, invalidatedArea, paint);
|
||||
}
|
||||
|
||||
GetAbsolutePosition(pointIter->data_, rect, style, pathEnd);
|
||||
pointIter = pointIter->next_;
|
||||
arcIter = arcIter->next_;
|
||||
break;
|
||||
}
|
||||
case CMD_CLOSE: {
|
||||
Point start = pointIter->prev_->data_;
|
||||
Point end = pointIter->data_;
|
||||
GetAbsolutePosition(start, rect, style, start);
|
||||
GetAbsolutePosition(end, rect, style, end);
|
||||
if ((start.x != end.x) || (start.y != end.y)) {
|
||||
DrawLine::Draw(start, end, invalidatedArea, paint.GetStrokeWidth(), paint.GetStrokeColor(),
|
||||
OPA_OPAQUE);
|
||||
if ((pathEnd.x == start.x) && (pathEnd.y == start.y)) {
|
||||
DoDrawLineJoin(start, invalidatedArea, paint);
|
||||
}
|
||||
pathEnd = end;
|
||||
}
|
||||
|
||||
if ((pathEnd.x == end.x) && (pathEnd.y == end.y)) {
|
||||
DoDrawLineJoin(end, invalidatedArea, paint);
|
||||
}
|
||||
pointIter = pointIter->next_;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+832
@@ -0,0 +1,832 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_chart.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_line.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIChart::~UIChart()
|
||||
{
|
||||
if (mixData_ != nullptr) {
|
||||
UIFree(mixData_);
|
||||
mixData_ = nullptr;
|
||||
}
|
||||
ClearDataSerial();
|
||||
Remove(&xAxis_);
|
||||
Remove(&yAxis_);
|
||||
}
|
||||
|
||||
void UIChart::SetHeight(int16_t height)
|
||||
{
|
||||
if (GetHeight() == height) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (height > 0) {
|
||||
needRefresh_ = true;
|
||||
}
|
||||
|
||||
UIViewGroup::SetHeight(height);
|
||||
xAxis_.SetHeight(height);
|
||||
xAxis_.UpdateAxis();
|
||||
yAxis_.SetHeight(height);
|
||||
yAxis_.UpdateAxis();
|
||||
}
|
||||
|
||||
void UIChart::SetWidth(int16_t width)
|
||||
{
|
||||
UIViewGroup::SetWidth(width);
|
||||
xAxis_.SetWidth(width);
|
||||
yAxis_.SetWidth(width);
|
||||
xAxis_.UpdateAxis();
|
||||
yAxis_.UpdateAxis();
|
||||
}
|
||||
|
||||
void UIChart::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
UIViewGroup::OnDraw(invalidatedArea);
|
||||
Rect rect = GetContentRect();
|
||||
if (rect.Intersect(rect, invalidatedArea)) {
|
||||
DrawDataSerials(rect);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIChart::AddDataSerial(UIChartDataSerial* dataSerial)
|
||||
{
|
||||
if (dataSerial == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ListNode<UIChartDataSerial*>* serialNode = list_.Head();
|
||||
while (serialNode != list_.End()) {
|
||||
if (serialNode->data_ == dataSerial) {
|
||||
return false;
|
||||
}
|
||||
serialNode = serialNode->next_;
|
||||
}
|
||||
list_.PushBack(dataSerial);
|
||||
dataSerial->BindToChart(this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIChart::DeleteDataSerial(UIChartDataSerial* dataSerial)
|
||||
{
|
||||
if ((dataSerial == nullptr) || list_.IsEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool findSerial = false;
|
||||
ListNode<UIChartDataSerial*>* serialNode = list_.Head();
|
||||
while (serialNode != list_.End()) {
|
||||
if (serialNode->data_ == dataSerial) {
|
||||
dataSerial->BindToChart(nullptr);
|
||||
list_.Remove(serialNode);
|
||||
findSerial = true;
|
||||
break;
|
||||
}
|
||||
serialNode = serialNode->next_;
|
||||
}
|
||||
|
||||
return findSerial;
|
||||
}
|
||||
|
||||
void UIChart::ClearDataSerial()
|
||||
{
|
||||
if (list_.IsEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
ListNode<UIChartDataSerial*>* serialNode = list_.Head();
|
||||
while (serialNode != list_.End()) {
|
||||
serialNode->data_->BindToChart(nullptr);
|
||||
ListNode<UIChartDataSerial*>* tempNode = serialNode;
|
||||
serialNode = serialNode->next_;
|
||||
list_.Remove(tempNode);
|
||||
}
|
||||
list_.Clear();
|
||||
}
|
||||
|
||||
UIChartDataSerial::UIChartDataSerial()
|
||||
: maxCount_(0),
|
||||
pointArray_(nullptr),
|
||||
serialColor_(Color::White()),
|
||||
fillColor_(Color::White()),
|
||||
dataCount_(0),
|
||||
peakPointIndex_(0),
|
||||
peakData_(0),
|
||||
valleyData_(0),
|
||||
valleyPointIndex_(0),
|
||||
lastPointIndex_(0),
|
||||
latestIndex_(0),
|
||||
hideIndex_(0),
|
||||
hideCount_(0),
|
||||
smooth_(false),
|
||||
enableGradient_(false),
|
||||
enableHeadPoint_(false),
|
||||
enableTopPoint_(false),
|
||||
enableBottomPoint_(false),
|
||||
chart_(nullptr),
|
||||
invalidateRect_(0, 0, 0, 0)
|
||||
{
|
||||
PointStyle style;
|
||||
style.radius = DEFAULT_POINT_RADIUS;
|
||||
style.strokeWidth = 1;
|
||||
style.fillColor = Color::White();
|
||||
style.strokeColor = Color::White();
|
||||
topPointStyle_ = style;
|
||||
bottomPointStyle_ = style;
|
||||
headPointStyle_ = style;
|
||||
}
|
||||
|
||||
bool UIChartDataSerial::SetMaxDataCount(uint16_t maxCount)
|
||||
{
|
||||
if (maxCount > MAX_POINTS_COUNT) {
|
||||
maxCount = MAX_POINTS_COUNT;
|
||||
}
|
||||
|
||||
if (maxCount == maxCount_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pointArray_ != nullptr) {
|
||||
UIFree(pointArray_);
|
||||
pointArray_ = nullptr;
|
||||
}
|
||||
|
||||
maxCount_ = maxCount;
|
||||
if (maxCount_ == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
pointArray_ = static_cast<Point*>(UIMalloc(sizeof(Point) * maxCount_));
|
||||
if (pointArray_ == nullptr) {
|
||||
maxCount_ = 0;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIChartDataSerial::ModifyPoint(uint16_t index, const Point& point)
|
||||
{
|
||||
if ((index >= maxCount_) || (pointArray_ == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pointArray_[index].x = point.x;
|
||||
pointArray_[index].y = point.y;
|
||||
if (point.y > peakData_) {
|
||||
if (enableTopPoint_) {
|
||||
RefreshInvalidateRect(peakPointIndex_, topPointStyle_);
|
||||
}
|
||||
peakPointIndex_ = index;
|
||||
peakData_ = point.y;
|
||||
} else if (point.y < valleyData_) {
|
||||
if (enableBottomPoint_) {
|
||||
RefreshInvalidateRect(valleyPointIndex_, bottomPointStyle_);
|
||||
}
|
||||
valleyPointIndex_ = index;
|
||||
valleyData_ = point.y;
|
||||
} else if ((index == peakPointIndex_) || (index == valleyPointIndex_)) {
|
||||
UpdatePeakAndValley(0, dataCount_);
|
||||
}
|
||||
|
||||
latestIndex_ = index;
|
||||
uint16_t startIndex = (index == 0) ? index : (index - 1);
|
||||
RefreshInvalidateRect(startIndex, index + 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIChartDataSerial::GetPoint(uint16_t index, Point& point)
|
||||
{
|
||||
if ((index >= dataCount_) || (pointArray_ == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
point = pointArray_[index];
|
||||
if (chart_ != nullptr) {
|
||||
chart_->GetXAxis().TranslateToPixel(point.x);
|
||||
chart_->GetYAxis().TranslateToPixel(point.y);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIChartDataSerial::HidePoint(uint16_t index, uint16_t count)
|
||||
{
|
||||
hideIndex_ = index;
|
||||
hideCount_ = count;
|
||||
RefreshInvalidateRect(hideIndex_, hideIndex_ + hideCount_);
|
||||
}
|
||||
|
||||
void UIChartDataSerial::RefreshInvalidateRect(uint16_t pointIndex, const PointStyle& style)
|
||||
{
|
||||
Point point;
|
||||
if (GetPoint(pointIndex, point)) {
|
||||
uint16_t width = style.radius + style.strokeWidth;
|
||||
Rect refresh(point.x - width, 0, point.x + width, 0);
|
||||
if ((invalidateRect_.GetLeft() == 0) && (invalidateRect_.GetRight() == 0)) {
|
||||
invalidateRect_ = refresh;
|
||||
} else {
|
||||
invalidateRect_.Join(invalidateRect_, refresh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartDataSerial::RefreshInvalidateRect(uint16_t startIndex, uint16_t endIndex)
|
||||
{
|
||||
Point start;
|
||||
GetPoint(startIndex, start);
|
||||
Point end;
|
||||
endIndex = (endIndex >= dataCount_) ? (dataCount_ - 1) : endIndex;
|
||||
GetPoint(endIndex, end);
|
||||
int16_t xMin = MATH_MIN(start.x, end.x);
|
||||
int16_t xMax = MATH_MAX(start.x, end.x);
|
||||
Rect refresh(xMin, 0, xMax, 0);
|
||||
if ((invalidateRect_.GetLeft() == 0) && (invalidateRect_.GetRight() == 0)) {
|
||||
invalidateRect_ = refresh;
|
||||
return;
|
||||
}
|
||||
invalidateRect_.Join(invalidateRect_, refresh);
|
||||
}
|
||||
|
||||
bool UIChartDataSerial::UpdatePeakAndValley(uint16_t startPos, uint16_t endPos)
|
||||
{
|
||||
if ((startPos >= endPos) || (endPos > dataCount_) || (pointArray_ == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (startPos == 0) {
|
||||
peakData_ = pointArray_[startPos].y;
|
||||
valleyData_ = pointArray_[startPos].y;
|
||||
}
|
||||
|
||||
for (uint16_t i = startPos; i < endPos; i++) {
|
||||
if (pointArray_[i].y > peakData_) {
|
||||
if (enableTopPoint_) {
|
||||
RefreshInvalidateRect(peakPointIndex_, topPointStyle_);
|
||||
RefreshInvalidateRect(i, topPointStyle_);
|
||||
}
|
||||
peakPointIndex_ = i;
|
||||
peakData_ = pointArray_[i].y;
|
||||
}
|
||||
|
||||
if (pointArray_[i].y < valleyData_) {
|
||||
if (enableBottomPoint_) {
|
||||
RefreshInvalidateRect(valleyPointIndex_, bottomPointStyle_);
|
||||
RefreshInvalidateRect(i, bottomPointStyle_);
|
||||
}
|
||||
valleyPointIndex_ = i;
|
||||
valleyData_ = pointArray_[i].y;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIChartDataSerial::AddPoints(const Point* data, uint16_t count)
|
||||
{
|
||||
if ((maxCount_ <= dataCount_) || (count == 0) || (pointArray_ == nullptr) || (data == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (count > (maxCount_ - dataCount_)) {
|
||||
count = maxCount_ - dataCount_;
|
||||
}
|
||||
|
||||
Point* current = pointArray_ + dataCount_;
|
||||
if (memcpy_s(current, (maxCount_ - dataCount_) * sizeof(Point), data, count * sizeof(Point)) != EOK) {
|
||||
return false;
|
||||
}
|
||||
uint16_t i = dataCount_;
|
||||
dataCount_ += count;
|
||||
UpdatePeakAndValley(i, dataCount_);
|
||||
latestIndex_ = dataCount_ - 1;
|
||||
uint16_t startIndex = (i == 0) ? i : (i - 1);
|
||||
RefreshInvalidateRect(startIndex, latestIndex_);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIChartDataSerial::ClearData()
|
||||
{
|
||||
RefreshInvalidateRect(0, dataCount_ - 1);
|
||||
if (pointArray_ != nullptr) {
|
||||
if (memset_s(pointArray_, maxCount_ * sizeof(Point), 0, maxCount_ * sizeof(Point)) != EOK) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
dataCount_ = 0;
|
||||
valleyPointIndex_ = 0;
|
||||
peakPointIndex_ = 0;
|
||||
latestIndex_ = 0;
|
||||
}
|
||||
|
||||
void UIChartDataSerial::DoDrawPoint(const Point& center, const PointStyle& style, const Rect& mask)
|
||||
{
|
||||
Style drawStyle = StyleDefault::GetDefaultStyle();
|
||||
drawStyle.lineOpa_ = OPA_OPAQUE;
|
||||
drawStyle.lineColor_ = style.fillColor;
|
||||
|
||||
ArcInfo arcinfo = {{0}};
|
||||
arcinfo.center = center;
|
||||
arcinfo.imgPos = Point{0, 0};
|
||||
arcinfo.radius = style.radius + style.strokeWidth;
|
||||
arcinfo.startAngle = 0;
|
||||
arcinfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
|
||||
if (style.fillColor.full == style.strokeColor.full) {
|
||||
drawStyle.lineWidth_ = style.radius + style.strokeWidth;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, mask, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
return;
|
||||
}
|
||||
drawStyle.lineWidth_ = style.radius;
|
||||
arcinfo.radius = style.radius;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, mask, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
|
||||
drawStyle.lineWidth_ = style.strokeWidth;
|
||||
drawStyle.lineColor_ = style.strokeColor;
|
||||
arcinfo.radius = style.radius + style.strokeWidth;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, mask, drawStyle, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void UIChartDataSerial::DrawPoint(const Rect& mask)
|
||||
{
|
||||
Point center;
|
||||
if (enableTopPoint_) {
|
||||
if (GetPoint(peakPointIndex_, center)) {
|
||||
DoDrawPoint(center, topPointStyle_, mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (enableBottomPoint_) {
|
||||
if (GetPoint(valleyPointIndex_, center)) {
|
||||
DoDrawPoint(center, bottomPointStyle_, mask);
|
||||
}
|
||||
}
|
||||
|
||||
if (enableHeadPoint_) {
|
||||
if (GetPoint(latestIndex_, center)) {
|
||||
DoDrawPoint(center, headPointStyle_, mask);
|
||||
lastPointIndex_ = latestIndex_;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartDataSerial::Refresh()
|
||||
{
|
||||
if (chart_ != nullptr) {
|
||||
Rect refresh = chart_->GetContentRect();
|
||||
refresh.SetLeft(invalidateRect_.GetLeft() - headPointStyle_.radius - headPointStyle_.strokeWidth);
|
||||
refresh.SetRight(invalidateRect_.GetRight() + headPointStyle_.radius + headPointStyle_.strokeWidth);
|
||||
invalidateRect_.SetRect(0, 0, 0, 0);
|
||||
chart_->InvalidateRect(refresh);
|
||||
|
||||
if (enableHeadPoint_ && (lastPointIndex_ != latestIndex_)) {
|
||||
RefreshInvalidateRect(lastPointIndex_, headPointStyle_);
|
||||
refresh.SetLeft(invalidateRect_.GetLeft());
|
||||
refresh.SetRight(invalidateRect_.GetRight());
|
||||
chart_->InvalidateRect(refresh);
|
||||
invalidateRect_.SetRect(0, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPillar::RefreshChart()
|
||||
{
|
||||
ListNode<UIChartDataSerial*>* iter = list_.Begin();
|
||||
Rect rect = GetContentRect();
|
||||
for (; iter != list_.End(); iter = iter->next_) {
|
||||
UIChartDataSerial* data = iter->data_;
|
||||
if (data == nullptr) {
|
||||
break;
|
||||
}
|
||||
uint16_t dataCount = data->GetDataCount();
|
||||
if (dataCount <= 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
uint16_t index = data->GetLastPointIndex();
|
||||
if (index >= dataCount) {
|
||||
break;
|
||||
}
|
||||
|
||||
Point current;
|
||||
data->GetPoint(index, current);
|
||||
Point last;
|
||||
data->GetPoint(dataCount - 1, last);
|
||||
Rect refresh(current.x, rect.GetTop(), last.x, rect.GetBottom());
|
||||
InvalidateRect(refresh);
|
||||
data->SetLastPointIndex(dataCount - 1);
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPillar::DrawDataSerials(const Rect& invalidatedArea)
|
||||
{
|
||||
xAxis_.UpdateAxisPoints();
|
||||
yAxis_.UpdateAxisPoints();
|
||||
uint16_t minXStep = static_cast<uint16_t>(xAxis_.GetMarkInterval());
|
||||
Point xStart = xAxis_.GetStartPoint();
|
||||
uint16_t dataSerialCount = list_.Size();
|
||||
if (dataSerialCount == 0) {
|
||||
return;
|
||||
}
|
||||
uint16_t width = minXStep / dataSerialCount;
|
||||
uint8_t dataSerialIndex = 0;
|
||||
uint16_t barWidth = static_cast<uint16_t>(width - DEFAULT_MARK_PERCENTAGE * (width << 1));
|
||||
|
||||
for (ListNode<UIChartDataSerial*>* iter = list_.Begin(); iter != list_.End(); iter = iter->next_) {
|
||||
UIChartDataSerial* data = iter->data_;
|
||||
uint16_t dataSerialWidth = width * dataSerialIndex;
|
||||
int16_t x = dataSerialWidth + (width >> 1);
|
||||
for (uint16_t index = 0; index < data->GetDataCount(); index++) {
|
||||
Point current;
|
||||
data->GetPoint(index, current);
|
||||
if (current.y == xStart.y) {
|
||||
continue;
|
||||
}
|
||||
current.x += x;
|
||||
xStart.x = current.x;
|
||||
DrawLine::Draw(current, xStart, invalidatedArea, barWidth, data->GetFillColor(), style_->lineOpa_);
|
||||
}
|
||||
dataSerialIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::RefreshChart()
|
||||
{
|
||||
ListNode<UIChartDataSerial*>* iter = list_.Begin();
|
||||
for (; iter != list_.End(); iter = iter->next_) {
|
||||
UIChartDataSerial* data = iter->data_;
|
||||
uint16_t dataCount = data->GetDataCount();
|
||||
if (dataCount == 1) {
|
||||
break;
|
||||
}
|
||||
data->Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::ReMeasure()
|
||||
{
|
||||
if (!needRefresh_) {
|
||||
return;
|
||||
}
|
||||
needRefresh_ = false;
|
||||
int16_t height = GetHeight();
|
||||
if (mixData_ != nullptr) {
|
||||
UIFree(mixData_);
|
||||
mixData_ = nullptr;
|
||||
}
|
||||
if (height <= 0) {
|
||||
return;
|
||||
}
|
||||
if (height > COORD_MAX) {
|
||||
height = COORD_MAX;
|
||||
}
|
||||
mixData_ = static_cast<uint8_t*>(UIMalloc(height));
|
||||
if (mixData_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
int16_t opa = maxOpa_ - minOpa_;
|
||||
for (int16_t y = 0; y < height; y++) {
|
||||
mixData_[y] = static_cast<uint8_t>(y * opa / height + minOpa_);
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::DrawDataSerials(const Rect& invalidatedArea)
|
||||
{
|
||||
xAxis_.UpdateAxisPoints();
|
||||
yAxis_.UpdateAxisPoints();
|
||||
ListNode<UIChartDataSerial*>* iter = list_.Begin();
|
||||
for (; iter != list_.End(); iter = iter->next_) {
|
||||
UIChartDataSerial* data = iter->data_;
|
||||
uint16_t dataCount = data->GetDataCount();
|
||||
if (dataCount <= 1) {
|
||||
continue;
|
||||
}
|
||||
if (data->IsGradient()) {
|
||||
GradientColor(invalidatedArea, data);
|
||||
}
|
||||
if (data->GetHideCount() != 0) {
|
||||
uint16_t hideIndex = data->GetHideIndex();
|
||||
DrawPolyLine(0, hideIndex, invalidatedArea, data);
|
||||
DrawPolyLine(hideIndex + data->GetHideCount(), dataCount - 1, invalidatedArea, data);
|
||||
} else {
|
||||
DrawPolyLine(0, dataCount - 1, invalidatedArea, data);
|
||||
}
|
||||
|
||||
data->DrawPoint(invalidatedArea);
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::DrawSmoothPolyLine(uint16_t startIndex,
|
||||
uint16_t endIndex,
|
||||
const Rect& invalidatedArea,
|
||||
UIChartDataSerial* data)
|
||||
{
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
Point start;
|
||||
Point end;
|
||||
ColorType color = data->GetLineColor();
|
||||
Style style = *style_;
|
||||
style.lineColor_ = color;
|
||||
style.lineOpa_ = OPA_OPAQUE;
|
||||
|
||||
uint16_t slope;
|
||||
data->GetPoint(startIndex, start);
|
||||
data->GetPoint(startIndex + 1, end);
|
||||
uint16_t preSlope = (start.x == end.x) ? QUARTER_IN_DEGREE : FastAtan2(end.x - start.x, end.y - start.y);
|
||||
Point current;
|
||||
for (uint16_t i = startIndex; i < endIndex; i++) {
|
||||
data->GetPoint(i + 1, current);
|
||||
if (((end.y - start.y <= 0) && (current.y - end.y <= 0)) ||
|
||||
((end.y - start.y >= 0) && (current.y - end.y >= 0))) {
|
||||
slope = (current.x == start.x) ? QUARTER_IN_DEGREE : FastAtan2(current.x - start.x, current.y - start.y);
|
||||
if (MATH_ABS(slope - preSlope) < SMOOTH_SLOPE_ANGLE) {
|
||||
end = current;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
preSlope = (current.x == end.x) ? QUARTER_IN_DEGREE : FastAtan2(current.x - end.x, current.y - end.y);
|
||||
Rect rect;
|
||||
rect.SetLeft(MATH_MIN(start.x, end.x) - style_->lineWidth_);
|
||||
rect.SetRight(MATH_MAX(start.x, end.x) + style_->lineWidth_);
|
||||
rect.SetTop(MATH_MIN(start.y, end.y) - style_->lineWidth_);
|
||||
rect.SetBottom(MATH_MAX(start.y, end.y) + style_->lineWidth_);
|
||||
if (!invalidatedArea.IsIntersect(rect)) {
|
||||
start = end;
|
||||
end = current;
|
||||
continue;
|
||||
}
|
||||
|
||||
DrawLine::Draw(start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
|
||||
ArcInfo arcinfo = {{0}};
|
||||
arcinfo.center = end;
|
||||
arcinfo.imgPos = Point{0, 0};
|
||||
arcinfo.radius = (style_->lineWidth_ + 1) >> 1;
|
||||
arcinfo.startAngle = 0;
|
||||
arcinfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
|
||||
DrawArc::GetInstance()->Draw(arcinfo, invalidatedArea, style, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
|
||||
start = end;
|
||||
end = current;
|
||||
}
|
||||
DrawLine::Draw(start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
|
||||
}
|
||||
|
||||
void UIChartPolyline::DrawPolyLine(uint16_t startIndex,
|
||||
uint16_t endIndex,
|
||||
const Rect& invalidatedArea,
|
||||
UIChartDataSerial* data)
|
||||
{
|
||||
if ((startIndex >= endIndex) || (data == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (data->IsSmooth()) {
|
||||
DrawSmoothPolyLine(startIndex, endIndex, invalidatedArea, data);
|
||||
return;
|
||||
}
|
||||
Point start;
|
||||
Point end;
|
||||
ColorType color = data->GetLineColor();
|
||||
Style style = *style_;
|
||||
style.lineColor_ = color;
|
||||
style.lineOpa_ = OPA_OPAQUE;
|
||||
ArcInfo arcinfo = {{0}};
|
||||
arcinfo.imgPos = Point{0, 0};
|
||||
arcinfo.radius = (style_->lineWidth_ + 1) >> 1;
|
||||
arcinfo.startAngle = 0;
|
||||
arcinfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
for (uint16_t i = startIndex; i < endIndex - 1; i++) {
|
||||
data->GetPoint(i, start);
|
||||
data->GetPoint(i + 1, end);
|
||||
Rect rect;
|
||||
rect.SetLeft(MATH_MIN(start.x, end.x) - style_->lineWidth_);
|
||||
rect.SetRight(MATH_MAX(start.x, end.x) + style_->lineWidth_);
|
||||
rect.SetTop(MATH_MIN(start.y, end.y) - style_->lineWidth_);
|
||||
rect.SetBottom(MATH_MAX(start.y, end.y) + style_->lineWidth_);
|
||||
if (!invalidatedArea.IsIntersect(rect)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
DrawLine::Draw(start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
|
||||
if (style_->lineWidth_ >= LINE_JOIN_WIDTH) {
|
||||
arcinfo.center = end;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, invalidatedArea, style, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
}
|
||||
data->GetPoint(endIndex - 1, start);
|
||||
data->GetPoint(endIndex, end);
|
||||
DrawLine::Draw(start, end, invalidatedArea, style_->lineWidth_, color, OPA_OPAQUE);
|
||||
}
|
||||
|
||||
bool UIChartPolyline::GetLineCrossPoint(const Point& p1,
|
||||
const Point& p2,
|
||||
const Point& p3,
|
||||
const Point& p4,
|
||||
Point& cross)
|
||||
{
|
||||
/* Rectangular ranges of line segments must intersect. */
|
||||
if ((MATH_MIN(p1.x, p2.x) <= MATH_MAX(p3.x, p4.x)) && (MATH_MIN(p3.x, p4.x) <= MATH_MAX(p1.x, p2.x)) &&
|
||||
(MATH_MIN(p1.y, p2.y) <= MATH_MAX(p3.y, p4.y)) && (MATH_MIN(p3.y, p4.y) <= MATH_MAX(p1.y, p2.y))) {
|
||||
/* Check whether the lines are parallel. If the lines are collinear, there is no intersection point. */
|
||||
if ((p4.y - p3.y) * (p2.x - p1.x) - (p4.x - p3.x) * (p2.y - p1.y) != 0) {
|
||||
/*
|
||||
* (y1 - y2)x + (x2 - x1)y = x2y1 - x1y2 -> ax + by = c
|
||||
* (y3 - y4)x + (x4 - x3)y = x4y3 - x3y4 -> dx + ey = f
|
||||
*/
|
||||
int64_t a = p1.y - p2.y;
|
||||
int64_t b = p2.x - p1.x;
|
||||
int64_t c = p2.x * p1.y - p1.x * p2.y;
|
||||
int64_t d = p3.y - p4.y;
|
||||
int64_t e = p4.x - p3.x;
|
||||
int64_t f = p4.x * p3.y - p3.x * p4.y;
|
||||
int64_t left = a * e - b * d;
|
||||
int64_t right = c * e - b * f;
|
||||
if (left == 0) {
|
||||
return false;
|
||||
}
|
||||
cross.x = static_cast<int16_t>(right / left);
|
||||
left = b * d - a * e;
|
||||
right = c * d - a * f;
|
||||
if (left == 0) {
|
||||
return false;
|
||||
}
|
||||
cross.y = static_cast<int16_t>(right / left);
|
||||
if ((cross.x >= MATH_MIN(p1.x, p2.x)) && (cross.x <= MATH_MAX(p1.x, p2.x)) &&
|
||||
(cross.x >= MATH_MIN(p3.x, p4.x)) && (cross.x <= MATH_MAX(p3.x, p4.x))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIChartPolyline::FindCrossPoints(const ChartLine& line, const ChartLine& polyLine, CrossPointSet& cross)
|
||||
{
|
||||
if (GetLineCrossPoint(line.start, line.end, polyLine.start, polyLine.end, cross.nextFirst)) {
|
||||
if (!cross.firstFind) {
|
||||
/* first corss must on the line like "/" */
|
||||
if (polyLine.start.y < polyLine.end.y) {
|
||||
cross.first = cross.nextFirst;
|
||||
cross.firstFind = true;
|
||||
}
|
||||
} else if (!cross.secondFind) {
|
||||
/* second corss can't be same with first cross. */
|
||||
if ((cross.first.x != cross.nextFirst.x) || (cross.first.y != cross.nextFirst.y)) {
|
||||
cross.second = cross.nextFirst;
|
||||
cross.secondFind = true;
|
||||
return;
|
||||
}
|
||||
/* second corss must on the line like "\", otherwise skip those crosss. */
|
||||
if (polyLine.start.y > polyLine.end.y) {
|
||||
cross.firstFind = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::DrawGradientColor(const Rect& invalidatedArea,
|
||||
UIChartDataSerial* data,
|
||||
const ChartLine& linePoints,
|
||||
const ChartLine& limitPoints,
|
||||
int16_t startY)
|
||||
{
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
Rect currentRect = GetContentRect();
|
||||
CrossPointSet cross = {{0}};
|
||||
ChartLine polyLine = {{0}};
|
||||
uint16_t pointCount = data->GetDataCount() - 1;
|
||||
int16_t y = enableReverse_ ? (linePoints.start.y + startY) : (startY - linePoints.start.y);
|
||||
int16_t mixScale = !enableReverse_ ? (currentRect.GetBottom() - y) : (y - currentRect.GetTop());
|
||||
if ((mixScale < 0) || (mixScale >= currentRect.GetHeight())) {
|
||||
return;
|
||||
}
|
||||
bool onVerticalLine = enableReverse_ ? (y <= limitPoints.start.y) : (y >= limitPoints.start.y);
|
||||
if (onVerticalLine) {
|
||||
cross.first.x = limitPoints.start.x;
|
||||
cross.first.y = enableReverse_ ? (y - startY) : (startY - y);
|
||||
cross.firstFind = true;
|
||||
}
|
||||
|
||||
Point start;
|
||||
Point end;
|
||||
for (uint16_t i = 0; i < pointCount; i++) {
|
||||
data->GetPoint(i, start);
|
||||
data->GetPoint(i + 1, end);
|
||||
if (start.y == end.y) {
|
||||
int16_t tmpY = enableReverse_ ? (start.y + startY) : (startY - start.y);
|
||||
if (tmpY == linePoints.start.y) {
|
||||
cross.firstFind = false;
|
||||
cross.secondFind = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
start.y = enableReverse_ ? (start.y - startY) : (startY - start.y);
|
||||
end.y = enableReverse_ ? (end.y - startY) : (startY - end.y);
|
||||
polyLine.start = start;
|
||||
polyLine.end = end;
|
||||
FindCrossPoints(linePoints, polyLine, cross);
|
||||
if (cross.firstFind && cross.secondFind) {
|
||||
cross.first.y = enableReverse_ ? (cross.first.y + startY) : (startY - cross.first.y);
|
||||
cross.second.y = enableReverse_ ? (cross.second.y + startY) : (startY - cross.second.y);
|
||||
DrawLine::Draw(cross.first, cross.second, invalidatedArea, 1, data->GetFillColor(), mixData_[mixScale]);
|
||||
cross.firstFind = false;
|
||||
cross.secondFind = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (cross.firstFind && !cross.secondFind) {
|
||||
cross.second.x = limitPoints.end.x;
|
||||
cross.second.y = y;
|
||||
cross.first.y = y;
|
||||
DrawLine::Draw(cross.first, cross.second, invalidatedArea, 1, data->GetFillColor(), mixData_[mixScale]);
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::CalcVerticalInfo(int16_t top,
|
||||
int16_t bottom,
|
||||
int16_t start,
|
||||
int16_t end,
|
||||
int16_t& y,
|
||||
int16_t& yHeight)
|
||||
{
|
||||
if ((top < start) && (bottom > start)) {
|
||||
y = start;
|
||||
yHeight = top;
|
||||
} else if ((bottom <= start) && (top >= end)) {
|
||||
y = bottom;
|
||||
yHeight = top;
|
||||
} else if ((top < end) && (bottom > end)) {
|
||||
y = bottom;
|
||||
yHeight = end;
|
||||
}
|
||||
}
|
||||
|
||||
void UIChartPolyline::GradientColor(const Rect& invalidatedArea, UIChartDataSerial* data)
|
||||
{
|
||||
if (data == nullptr) {
|
||||
return;
|
||||
}
|
||||
int16_t bottom = invalidatedArea.GetBottom();
|
||||
int16_t top = invalidatedArea.GetTop();
|
||||
Point yStart = yAxis_.GetStartPoint();
|
||||
yStart.y = enableReverse_ ? (yStart.y + gradientBottom_) : (yStart.y - gradientBottom_);
|
||||
int16_t topY = enableReverse_ ? data->GetValleyData() : data->GetPeakData();
|
||||
int16_t bottomY = enableReverse_ ? data->GetPeakData() : data->GetValleyData();
|
||||
yAxis_.TranslateToPixel(topY);
|
||||
yAxis_.TranslateToPixel(bottomY);
|
||||
int16_t valleyY = enableReverse_ ? topY : bottomY;
|
||||
int16_t startY = enableReverse_ ? topY : yStart.y;
|
||||
int16_t endY = enableReverse_ ? yStart.y : topY;
|
||||
if ((bottom < endY) || (top > startY)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t y = 0;
|
||||
int16_t yHeight = 0;
|
||||
CalcVerticalInfo(top, bottom, startY, endY, y, yHeight);
|
||||
|
||||
ChartLine limitPoints = {{0}};
|
||||
data->GetPoint(0, limitPoints.start);
|
||||
data->GetPoint(data->GetDataCount() - 1, limitPoints.end);
|
||||
ChartLine linePoints = {{0}};
|
||||
linePoints.start.x = limitPoints.start.x;
|
||||
linePoints.end.x = limitPoints.end.x;
|
||||
Rect currentRect = GetContentRect();
|
||||
while (y >= yHeight) {
|
||||
linePoints.start.y = enableReverse_ ? (y - endY) : (startY - y);
|
||||
linePoints.end.y = linePoints.start.y;
|
||||
if (y <= valleyY) {
|
||||
int16_t baseY = enableReverse_ ? endY : startY;
|
||||
DrawGradientColor(invalidatedArea, data, linePoints, limitPoints, baseY);
|
||||
} else {
|
||||
int16_t mixScale = enableReverse_ ? (linePoints.start.y + endY - currentRect.GetTop()) :
|
||||
(currentRect.GetBottom() - (startY - linePoints.start.y));
|
||||
if ((mixScale < 0) || (mixScale >= currentRect.GetHeight())) {
|
||||
y--;
|
||||
continue;
|
||||
}
|
||||
Point start = {limitPoints.start.x, y};
|
||||
Point end = {limitPoints.end.x, y};
|
||||
DrawLine::Draw(start, end, invalidatedArea, 1, data->GetFillColor(), mixData_[mixScale]);
|
||||
}
|
||||
y--;
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/image.h"
|
||||
#include "components/ui_checkbox.h"
|
||||
#include "default_resource/check_box_res.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UICheckBox::UICheckBox()
|
||||
: state_(UNSELECTED), onStateChangeListener_(nullptr)
|
||||
{
|
||||
touchable_ = true;
|
||||
style_ = &(StyleDefault::GetBackgroundTransparentStyle());
|
||||
image_[UNSELECTED].SetSrc(GetCheckBoxOffInfo());
|
||||
image_[SELECTED].SetSrc(GetCheckBoxOnInfo());
|
||||
ImageHeader header = { 0 };
|
||||
image_[UNSELECTED].GetHeader(header);
|
||||
Resize(header.width, header.height);
|
||||
}
|
||||
|
||||
UICheckBox::~UICheckBox()
|
||||
{
|
||||
}
|
||||
|
||||
void UICheckBox::SetState(UICheckBoxState state)
|
||||
{
|
||||
if (state != state_) {
|
||||
state_ = state;
|
||||
if (onStateChangeListener_ != nullptr) {
|
||||
onStateChangeListener_->OnChange(state);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UICheckBox::ReverseState()
|
||||
{
|
||||
state_ = (state_ == SELECTED) ? UNSELECTED : SELECTED;
|
||||
}
|
||||
|
||||
bool UICheckBox::OnClickEvent(const ClickEvent& event)
|
||||
{
|
||||
ReverseState();
|
||||
Invalidate();
|
||||
return UIView::OnClickEvent(event);
|
||||
}
|
||||
|
||||
void UICheckBox::SetImages(const char* selectedImageSrc, const char* unselectedImageSrc)
|
||||
{
|
||||
image_[SELECTED].SetSrc(selectedImageSrc);
|
||||
image_[UNSELECTED].SetSrc(unselectedImageSrc);
|
||||
}
|
||||
|
||||
void UICheckBox::SetImages(const ImageInfo* selectedImageSrc, const ImageInfo* unselectedImageSrc)
|
||||
{
|
||||
image_[SELECTED].SetSrc(selectedImageSrc);
|
||||
image_[UNSELECTED].SetSrc(unselectedImageSrc);
|
||||
}
|
||||
|
||||
void UICheckBox::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
ImageHeader header = {0};
|
||||
image_[state_].GetHeader(header);
|
||||
int16_t imgWidth = header.width;
|
||||
int16_t imgHeight = header.height;
|
||||
Rect coords = GetContentRect();
|
||||
coords.SetWidth(imgWidth);
|
||||
coords.SetHeight(imgHeight);
|
||||
DrawRect::Draw(GetRect(), invalidatedArea, *style_, opaScale_);
|
||||
|
||||
int16_t offsetLeft = (GetWidth() - imgWidth) / 2; // 2 : half
|
||||
int16_t offsetTop = (GetHeight() - imgHeight) / 2; // 2 : half
|
||||
coords.SetX(coords.GetX() + offsetLeft);
|
||||
coords.SetY(coords.GetY() + offsetTop);
|
||||
Rect trunc = invalidatedArea;
|
||||
if (trunc.Intersect(trunc, coords)) {
|
||||
image_[state_].DrawImage(coords, trunc, *style_, opaScale_);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+134
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_circle_progress.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_line.h"
|
||||
#include "draw/draw_rect.h"
|
||||
|
||||
namespace OHOS {
|
||||
UICircleProgress::UICircleProgress()
|
||||
: center_({0, 0}),
|
||||
backgroundImagePos_({0, 0}),
|
||||
progressImagePos_({0, 0}),
|
||||
radius_(0),
|
||||
startAngle_(MIN_ANGLE_VALUE),
|
||||
endAngle_(MAX_ANGLE_VALUE)
|
||||
{
|
||||
}
|
||||
|
||||
void UICircleProgress::SetCenterPosition(int16_t x, int16_t y)
|
||||
{
|
||||
center_.x = x;
|
||||
center_.y = y;
|
||||
}
|
||||
|
||||
void UICircleProgress::SetStartAngle(int16_t startAngle)
|
||||
{
|
||||
startAngle_ = startAngle;
|
||||
}
|
||||
|
||||
void UICircleProgress::SetEndAngle(int16_t endAngle)
|
||||
{
|
||||
endAngle_ = endAngle;
|
||||
}
|
||||
|
||||
void UICircleProgress::GetStartEndAngle(int16_t& start, int16_t& end) const
|
||||
{
|
||||
if (startAngle_ > endAngle_) {
|
||||
start = endAngle_;
|
||||
end = startAngle_;
|
||||
} else {
|
||||
start = startAngle_;
|
||||
end = endAngle_;
|
||||
}
|
||||
}
|
||||
|
||||
void UICircleProgress::GetAngleRange(int16_t& start, int16_t& end) const
|
||||
{
|
||||
GetStartEndAngle(start, end);
|
||||
DrawArc::GetInstance()->GetDrawRange(start, end);
|
||||
}
|
||||
|
||||
void UICircleProgress::GetRedrawAngle(int16_t& start, int16_t& end) const
|
||||
{
|
||||
GetStartEndAngle(start, end);
|
||||
|
||||
if (startAngle_ == endAngle_) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t angleRange = end - start;
|
||||
angleRange = (angleRange > CIRCLE_IN_DEGREE) ? CIRCLE_IN_DEGREE : angleRange;
|
||||
|
||||
int16_t angle = GetCurrentPos(angleRange);
|
||||
if (startAngle_ > endAngle_) {
|
||||
start = end - angle;
|
||||
} else {
|
||||
end = angle + start;
|
||||
}
|
||||
DrawArc::GetInstance()->GetDrawRange(start, end);
|
||||
}
|
||||
|
||||
void UICircleProgress::DrawCommonCircle(const Rect& invalidatedArea)
|
||||
{
|
||||
ArcInfo arcinfo = {{0}};
|
||||
arcinfo.radius = radius_;
|
||||
int16_t endAngle;
|
||||
int16_t startAngle;
|
||||
GetRedrawAngle(startAngle, endAngle);
|
||||
|
||||
int16_t start;
|
||||
int16_t end;
|
||||
GetAngleRange(start, end);
|
||||
Rect rect = GetOrigRect();
|
||||
arcinfo.center.x = center_.x + rect.GetLeft() + style_->paddingLeft_ + style_->borderWidth_;
|
||||
arcinfo.center.y = center_.y + rect.GetTop() + style_->paddingTop_ + style_->borderWidth_;
|
||||
|
||||
if (enableBackground_ && ((start != end) || (backgroundStyle_->lineCap_ == CapType::CAP_ROUND))) {
|
||||
arcinfo.imgPos.x = backgroundImagePos_.x + rect.GetLeft();
|
||||
arcinfo.imgPos.y = backgroundImagePos_.y + rect.GetTop();
|
||||
arcinfo.startAngle = start;
|
||||
arcinfo.endAngle = end;
|
||||
arcinfo.imgSrc = backgroundImage_;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, invalidatedArea, *backgroundStyle_, opaScale_,
|
||||
backgroundStyle_->lineCap_);
|
||||
}
|
||||
|
||||
if ((startAngle != endAngle) || (foregroundStyle_->lineCap_ == CapType::CAP_ROUND)) {
|
||||
arcinfo.imgPos.x = progressImagePos_.x + rect.GetLeft();
|
||||
arcinfo.imgPos.y = progressImagePos_.y + rect.GetTop();
|
||||
arcinfo.startAngle = startAngle;
|
||||
arcinfo.endAngle = endAngle;
|
||||
arcinfo.imgSrc = foregroundImage_;
|
||||
DrawArc::GetInstance()->Draw(arcinfo, invalidatedArea, *foregroundStyle_, opaScale_,
|
||||
foregroundStyle_->lineCap_);
|
||||
}
|
||||
}
|
||||
|
||||
void UICircleProgress::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
if (GetRangeSize() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
DrawRect::Draw(GetOrigRect(), invalidatedArea, *style_, opaScale_);
|
||||
|
||||
Rect trunc(invalidatedArea);
|
||||
if (trunc.Intersect(trunc, GetOrigRect())) {
|
||||
DrawCommonCircle(trunc);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+694
@@ -0,0 +1,694 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_dialog.h"
|
||||
#include "common/screen.h"
|
||||
#include "common/typed_text.h"
|
||||
#if ENABLE_DEBUG
|
||||
#include "graphic_assert.h"
|
||||
#endif
|
||||
#include "graphic_log.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "window/window.h"
|
||||
#endif
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
namespace OHOS {
|
||||
class UIDialogLabelButton : public UILabelButton {
|
||||
public:
|
||||
UIDialogLabelButton(UIDialog* dialog)
|
||||
{
|
||||
dialog_ = dialog;
|
||||
}
|
||||
virtual ~UIDialogLabelButton() {}
|
||||
virtual bool OnClickEvent(const ClickEvent& event)
|
||||
{
|
||||
bool ret = true;
|
||||
if (dialog_ != nullptr) {
|
||||
dialog_->DestoryWindow();
|
||||
dialog_->isShowing_ = false;
|
||||
}
|
||||
if (onClickListener_ != nullptr) {
|
||||
ret = onClickListener_->OnClick(*this, event);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
UIDialog* dialog_;
|
||||
};
|
||||
|
||||
class UIDialogClickListener : public UIView::OnClickListener {
|
||||
public:
|
||||
UIDialogClickListener(UIDialog* dialog)
|
||||
{
|
||||
dialog_ = dialog;
|
||||
}
|
||||
virtual ~UIDialogClickListener() {}
|
||||
bool OnClick(UIView& view, const ClickEvent& event) override
|
||||
{
|
||||
bool ret = true;
|
||||
if ((dialog_ != nullptr) && (dialog_->dialogLayer_ != nullptr) &&
|
||||
!dialog_->dialogLayer_->GetRect().IsContains(event.GetCurrentPos())) {
|
||||
if (dialog_->enableAutoCancel_) {
|
||||
dialog_->DestoryWindow();
|
||||
dialog_->isShowing_ = false;
|
||||
}
|
||||
if (dialog_->onCancelListener_ != nullptr) {
|
||||
ret = dialog_->onCancelListener_->OnClick(view, event);
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
private:
|
||||
UIDialog* dialog_;
|
||||
};
|
||||
|
||||
UIDialog::UIDialog()
|
||||
: isShowing_(false),
|
||||
enableAutoCancel_(false),
|
||||
buttonNum_(0),
|
||||
title_(nullptr),
|
||||
text_(nullptr),
|
||||
button1_(nullptr),
|
||||
button2_(nullptr),
|
||||
button3_(nullptr),
|
||||
dialogLayer_(nullptr),
|
||||
windowRootView_(nullptr),
|
||||
onCancelListener_(nullptr),
|
||||
dialogClickListener_(nullptr),
|
||||
window_(nullptr),
|
||||
line1_(nullptr),
|
||||
line2_(nullptr),
|
||||
titleText_(nullptr),
|
||||
textText_(nullptr)
|
||||
{
|
||||
uint16_t screenWidth = Screen::GetInstance().GetWidth();
|
||||
uint16_t screenHeight = Screen::GetInstance().GetHeight();
|
||||
// 100: calculate percentage
|
||||
widthMax_ = screenWidth * MAX_WIDTH_PERCENT / 100;
|
||||
// 100: calculate percentage
|
||||
heightMax_ = screenHeight * MAX_HEIGHT_PERCENT / 100;
|
||||
colorType1_ = Color::White();
|
||||
colorType2_ = Color::White();
|
||||
colorType3_ = Color::White();
|
||||
}
|
||||
|
||||
UIDialog::~UIDialog()
|
||||
{
|
||||
onCancelListener_ = nullptr;
|
||||
if (dialogLayer_ != nullptr) {
|
||||
dialogLayer_->RemoveAll();
|
||||
delete dialogLayer_;
|
||||
dialogLayer_ = nullptr;
|
||||
}
|
||||
if (title_ != nullptr) {
|
||||
delete title_;
|
||||
title_ = nullptr;
|
||||
}
|
||||
if (text_ != nullptr) {
|
||||
delete text_;
|
||||
text_ = nullptr;
|
||||
}
|
||||
if (button1_ != nullptr) {
|
||||
delete button1_;
|
||||
button1_ = nullptr;
|
||||
}
|
||||
if (button2_ != nullptr) {
|
||||
delete button2_;
|
||||
button2_ = nullptr;
|
||||
}
|
||||
if (button3_ != nullptr) {
|
||||
delete button3_;
|
||||
button3_ = nullptr;
|
||||
}
|
||||
if (line1_ != nullptr) {
|
||||
delete line1_;
|
||||
line1_ = nullptr;
|
||||
}
|
||||
if (line2_ != nullptr) {
|
||||
delete line2_;
|
||||
line2_ = nullptr;
|
||||
}
|
||||
if ((windowRootView_ != nullptr) && !RootView::DestoryWindowRootView(windowRootView_)) {
|
||||
windowRootView_ = nullptr;
|
||||
}
|
||||
if (dialogClickListener_ != nullptr) {
|
||||
delete dialogClickListener_;
|
||||
dialogClickListener_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::SetTitle(const char* title)
|
||||
{
|
||||
if (title == nullptr) {
|
||||
return;
|
||||
}
|
||||
titleText_ = title;
|
||||
}
|
||||
|
||||
void UIDialog::SetText(const char* text)
|
||||
{
|
||||
if (text == nullptr) {
|
||||
return;
|
||||
}
|
||||
textText_ = text;
|
||||
}
|
||||
|
||||
void UIDialog::SetButton(DialogButtonType buttonType, const char* text, UIView::OnClickListener* listener)
|
||||
{
|
||||
switch (buttonType) {
|
||||
case DialogButtonType::BUTTON_LEFT:
|
||||
if (button1_ == nullptr) {
|
||||
button1_ = new UIDialogLabelButton(this);
|
||||
if (button1_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIDialogLabelButton fail");
|
||||
return;
|
||||
}
|
||||
button1_->SetViewId(BUTTON1_ID);
|
||||
AddButton(buttonType, button1_, text, listener);
|
||||
} else {
|
||||
button1_->SetText(text);
|
||||
button1_->SetOnClickListener(listener);
|
||||
}
|
||||
break;
|
||||
case DialogButtonType::BUTTON_MID:
|
||||
if (button2_ == nullptr) {
|
||||
button2_ = new UIDialogLabelButton(this);
|
||||
if (button2_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIDialogLabelButton fail");
|
||||
return;
|
||||
}
|
||||
button2_->SetViewId(BUTTON2_ID);
|
||||
AddButton(buttonType, button2_, text, listener);
|
||||
} else {
|
||||
button2_->SetText(text);
|
||||
button2_->SetOnClickListener(listener);
|
||||
}
|
||||
break;
|
||||
case DialogButtonType::BUTTON_RIGHT:
|
||||
if (button3_ == nullptr) {
|
||||
button3_ = new UIDialogLabelButton(this);
|
||||
if (button3_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIDialogLabelButton fail");
|
||||
return;
|
||||
}
|
||||
AddButton(buttonType, button3_, text, listener);
|
||||
} else {
|
||||
button3_->SetText(text);
|
||||
button3_->SetOnClickListener(listener);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::AddButton(DialogButtonType buttonType,
|
||||
UILabelButton* button,
|
||||
const char* text,
|
||||
UIView::OnClickListener* listener)
|
||||
{
|
||||
buttonNum_++;
|
||||
button->SetText(text);
|
||||
button->SetOnClickListener(listener);
|
||||
button->SetFont(DEFAULT_VECTOR_FONT_FILENAME, BUTTON_FONT_SIZE);
|
||||
button->SetTextColor(Color::Blue());
|
||||
button->SetStyleForState(STYLE_BACKGROUND_COLOR, Color::White().full, UIButton::ButtonState::RELEASED);
|
||||
button->SetStyleForState(STYLE_BACKGROUND_COLOR, Color::Black().full, UIButton::ButtonState::PRESSED);
|
||||
button->SetStyleForState(STYLE_BACKGROUND_OPA, BUTTON_PRESS_OPA, UIButton::ButtonState::PRESSED);
|
||||
button->SetStyleForState(STYLE_BORDER_WIDTH, 0, UIButton::ButtonState::RELEASED);
|
||||
button->SetStyleForState(STYLE_BORDER_WIDTH, 0, UIButton::ButtonState::PRESSED);
|
||||
button->SetHeight(BUTTON_HEIGHT);
|
||||
}
|
||||
|
||||
void UIDialog::Show()
|
||||
{
|
||||
if (isShowing_) {
|
||||
return;
|
||||
}
|
||||
SetTitleLabel();
|
||||
SetTextLabel();
|
||||
InitDialog();
|
||||
AddComponents();
|
||||
MeasureSize();
|
||||
Layout();
|
||||
CreateDialogWindow();
|
||||
window_->Show();
|
||||
isShowing_ = true;
|
||||
}
|
||||
|
||||
void UIDialog::SetTitleLabel()
|
||||
{
|
||||
if (titleText_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (title_ == nullptr) {
|
||||
title_ = new UILabel();
|
||||
if (title_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
title_->SetViewId(TITLE_ID);
|
||||
title_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, TITLE_FONT_SIZE);
|
||||
title_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT);
|
||||
title_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
|
||||
title_->SetStyle(STYLE_TEXT_OPA, TITLE_TEXT_OPA);
|
||||
title_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
|
||||
}
|
||||
title_->SetText(titleText_);
|
||||
}
|
||||
|
||||
void UIDialog::SetTextLabel()
|
||||
{
|
||||
if (textText_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (text_ == nullptr) {
|
||||
text_ = new UILabel();
|
||||
if (text_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
text_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, TEXT_FONT_SIZE);
|
||||
text_->SetStyle(STYLE_TEXT_COLOR, Color::Black().full);
|
||||
text_->SetStyle(STYLE_TEXT_OPA, TITLE_TEXT_OPA);
|
||||
text_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
|
||||
}
|
||||
text_->SetText(textText_);
|
||||
}
|
||||
|
||||
void UIDialog::InitDialog()
|
||||
{
|
||||
if (dialogLayer_ == nullptr) {
|
||||
dialogLayer_ = new UIViewGroup();
|
||||
if (dialogLayer_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIViewGroup fail");
|
||||
return;
|
||||
}
|
||||
dialogLayer_->SetStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
|
||||
}
|
||||
if (windowRootView_ == nullptr) {
|
||||
windowRootView_ = RootView::GetWindowRootView();
|
||||
windowRootView_->SetWidth(Screen::GetInstance().GetWidth());
|
||||
windowRootView_->SetHeight(Screen::GetInstance().GetHeight());
|
||||
windowRootView_->SetTouchable(true);
|
||||
windowRootView_->Add(dialogLayer_);
|
||||
}
|
||||
if (dialogClickListener_ == nullptr) {
|
||||
dialogClickListener_ = new UIDialogClickListener(this);
|
||||
if (dialogClickListener_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIDialogClickListener fail");
|
||||
return;
|
||||
}
|
||||
windowRootView_->SetOnClickListener(dialogClickListener_);
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::AddComponents()
|
||||
{
|
||||
if (title_ != nullptr) {
|
||||
dialogLayer_->Add(title_);
|
||||
}
|
||||
if (text_ != nullptr) {
|
||||
dialogLayer_->Add(text_);
|
||||
}
|
||||
if (button1_ != nullptr) {
|
||||
dialogLayer_->Add(button1_);
|
||||
}
|
||||
if (button2_ != nullptr) {
|
||||
dialogLayer_->Add(button2_);
|
||||
}
|
||||
if (button3_ != nullptr) {
|
||||
dialogLayer_->Add(button3_);
|
||||
}
|
||||
if (buttonNum_ > 1) {
|
||||
line1_ = new UIView();
|
||||
if (line1_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIView fail");
|
||||
return;
|
||||
}
|
||||
line1_->SetHeight(LINE_HEIGHT);
|
||||
line1_->SetWidth(LINE_WIDTH);
|
||||
line1_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
|
||||
line1_->SetStyle(STYLE_BACKGROUND_OPA, LINE_OPA);
|
||||
dialogLayer_->Add(line1_);
|
||||
}
|
||||
if (buttonNum_ == 3) { // 3: three buttons
|
||||
line2_ = new UIView();
|
||||
if (line2_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIView fail");
|
||||
return;
|
||||
}
|
||||
line2_->SetHeight(LINE_HEIGHT);
|
||||
line2_->SetWidth(LINE_WIDTH);
|
||||
line2_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Black().full);
|
||||
line2_->SetStyle(STYLE_BACKGROUND_OPA, LINE_OPA);
|
||||
dialogLayer_->Add(line2_);
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::MeasureSize()
|
||||
{
|
||||
uint16_t width = MeasureMaxWidth();
|
||||
uint16_t height = 0;
|
||||
|
||||
if (buttonNum_ > 0) {
|
||||
// 2: there are 2 paddings horizontally
|
||||
uint16_t buttonWidth = (width - 2 * BUTTON_PADDING - (buttonNum_ - 1) * BUTTON_MID_PADDING) / buttonNum_;
|
||||
// 2: there are 2 paddings horizontally
|
||||
width = static_cast<uint32_t>(buttonWidth) * buttonNum_ + (buttonNum_ - 1) * BUTTON_MID_PADDING +
|
||||
2 * BUTTON_PADDING;
|
||||
height += BUTTON_TOTAL_HEIGHT;
|
||||
height += TEXT_BUTTON_PADDING;
|
||||
if (button1_ != nullptr) {
|
||||
button1_->SetWidth(buttonWidth);
|
||||
}
|
||||
if (button2_ != nullptr) {
|
||||
button2_->SetWidth(buttonWidth);
|
||||
}
|
||||
if (button3_ != nullptr) {
|
||||
button3_->SetWidth(buttonWidth);
|
||||
}
|
||||
} else {
|
||||
height += PADDING;
|
||||
}
|
||||
|
||||
if (title_ != nullptr) {
|
||||
title_->SetWidth(width - 2 * PADDING); // 2: there are 2 paddings horizontally
|
||||
height += TITLE_TOTAL_HEIGHT;
|
||||
} else {
|
||||
height += PADDING;
|
||||
}
|
||||
|
||||
if (text_ != nullptr) {
|
||||
text_->SetWidth(width - 2 * PADDING); // 2: there are 2 paddings horizontally
|
||||
uint16_t textHightMax = heightMax_ - height;
|
||||
if (text_->GetTextHeight() < textHightMax) {
|
||||
text_->SetHeight(text_->GetTextHeight());
|
||||
} else {
|
||||
text_->SetHeight(textHightMax);
|
||||
text_->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS);
|
||||
}
|
||||
height += text_->GetHeight();
|
||||
}
|
||||
|
||||
uint16_t dialogHeight = height;
|
||||
dialogLayer_->SetHeight(dialogHeight);
|
||||
dialogLayer_->SetWidth(width);
|
||||
}
|
||||
|
||||
uint16_t UIDialog::MeasureMaxWidth()
|
||||
{
|
||||
uint16_t titleWidth = 0;
|
||||
uint16_t textWidth = 0;
|
||||
uint16_t buttonTotalWidth = 0;
|
||||
|
||||
if (title_ != nullptr) {
|
||||
titleWidth = MeasureTitleWidth();
|
||||
titleWidth += 2 * PADDING; // 2: there are 2 paddings horizontally
|
||||
}
|
||||
if (text_ != nullptr) {
|
||||
textWidth = MeasureTextWidth();
|
||||
textWidth += 2 * PADDING; // 2: there are 2 paddings horizontally
|
||||
}
|
||||
if (buttonNum_ > 0) {
|
||||
buttonTotalWidth =
|
||||
static_cast<uint32_t>(MeasureButtonWidth()) * buttonNum_ + (buttonNum_ - 1) * BUTTON_MID_PADDING;
|
||||
buttonTotalWidth += 2 * BUTTON_PADDING; // 2: there are 2 paddings horizontally
|
||||
}
|
||||
return MATH_MAX(titleWidth, MATH_MAX(textWidth, buttonTotalWidth));
|
||||
}
|
||||
|
||||
uint16_t UIDialog::MeasureTitleWidth()
|
||||
{
|
||||
uint16_t titleWidth = 0;
|
||||
uint16_t widthMaxNoPadding = widthMax_ - 2 * PADDING; // 2: there are 2 paddings horizontally
|
||||
title_->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
|
||||
if (title_->GetTextWidth() > widthMaxNoPadding) {
|
||||
titleWidth = widthMaxNoPadding;
|
||||
title_->SetLineBreakMode(UILabel::LINE_BREAK_ELLIPSIS);
|
||||
} else {
|
||||
titleWidth = title_->GetTextWidth();
|
||||
}
|
||||
title_->SetHeight(title_->GetTextHeight());
|
||||
return titleWidth;
|
||||
}
|
||||
|
||||
uint16_t UIDialog::MeasureTextWidth()
|
||||
{
|
||||
uint16_t textWidth = 0;
|
||||
uint16_t widthMaxNoPadding = widthMax_ - 2 * PADDING; // 2: there are 2 paddings horizontally
|
||||
if (title_ != nullptr) {
|
||||
text_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT);
|
||||
} else {
|
||||
text_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
|
||||
}
|
||||
text_->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
|
||||
textWidth = text_->GetTextWidth();
|
||||
if (text_->GetTextWidth() > widthMaxNoPadding) {
|
||||
text_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT);
|
||||
textWidth = widthMaxNoPadding;
|
||||
text_->SetLineBreakMode(UILabel::LINE_BREAK_WRAP);
|
||||
}
|
||||
return textWidth;
|
||||
}
|
||||
|
||||
uint16_t UIDialog::MeasureButtonWidth()
|
||||
{
|
||||
if (buttonNum_ == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint16_t buttonTextWidth = 0;
|
||||
// 2: there are 2 paddings horizontally
|
||||
uint16_t buttonMaxWidth = (widthMax_ - 2 * BUTTON_PADDING - (buttonNum_ - 1) * BUTTON_MID_PADDING) / buttonNum_;
|
||||
|
||||
if (button1_ != nullptr) {
|
||||
const char* text1 = button1_->GetText();
|
||||
buttonTextWidth = MATH_MAX(buttonTextWidth, TypedText::GetTextSize(text1,
|
||||
button1_->GetStyleConst().letterSpace_, button1_->GetStyleConst().lineSpace_, widthMax_).x);
|
||||
}
|
||||
if (button2_ != nullptr) {
|
||||
const char* text2 = button2_->GetText();
|
||||
buttonTextWidth = MATH_MAX(buttonTextWidth, TypedText::GetTextSize(text2,
|
||||
button2_->GetStyleConst().letterSpace_, button2_->GetStyleConst().lineSpace_, widthMax_).x);
|
||||
}
|
||||
if (button3_ != nullptr) {
|
||||
const char* text3 = button3_->GetText();
|
||||
buttonTextWidth = MATH_MAX(buttonTextWidth, TypedText::GetTextSize(text3,
|
||||
button3_->GetStyleConst().letterSpace_, button3_->GetStyleConst().lineSpace_, widthMax_).x);
|
||||
}
|
||||
return (buttonTextWidth + BUTTON_HEIGHT) > buttonMaxWidth ? buttonMaxWidth : (buttonTextWidth + BUTTON_HEIGHT);
|
||||
}
|
||||
|
||||
void UIDialog::Layout()
|
||||
{
|
||||
if (title_ != nullptr) {
|
||||
// 2: there are 2 paddings vertically
|
||||
uint8_t padding = (TITLE_TOTAL_HEIGHT - title_->GetHeight()) / 2;
|
||||
title_->LayoutLeftOfParent(PADDING);
|
||||
title_->LayoutTopOfParent(padding);
|
||||
if (text_ != nullptr) {
|
||||
text_->LayoutLeftOfParent(PADDING);
|
||||
text_->LayoutBottomToSibling(TITLE_ID, padding);
|
||||
}
|
||||
} else {
|
||||
if (text_ != nullptr) {
|
||||
text_->LayoutLeftOfParent(PADDING);
|
||||
text_->LayoutTopOfParent(PADDING);
|
||||
}
|
||||
}
|
||||
LayoutButton();
|
||||
}
|
||||
|
||||
void UIDialog::LayoutButton()
|
||||
{
|
||||
if (button1_ != nullptr) {
|
||||
button1_->LayoutLeftOfParent(BUTTON_PADDING);
|
||||
button1_->LayoutBottomOfParent(BUTTON_PADDING);
|
||||
if (button2_ != nullptr) {
|
||||
button2_->LayoutRightToSibling(BUTTON1_ID, BUTTON_MID_PADDING);
|
||||
button2_->LayoutBottomOfParent(BUTTON_PADDING);
|
||||
}
|
||||
} else if (button2_ != nullptr) {
|
||||
button2_->LayoutLeftOfParent(BUTTON_PADDING);
|
||||
button2_->LayoutBottomOfParent(BUTTON_PADDING);
|
||||
}
|
||||
if (button3_ != nullptr) {
|
||||
button3_->LayoutRightOfParent(BUTTON_PADDING);
|
||||
button3_->LayoutBottomOfParent(BUTTON_PADDING);
|
||||
}
|
||||
|
||||
if (buttonNum_ == 3) { // 3: three buttons
|
||||
line1_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
|
||||
line1_->LayoutRightToSibling(BUTTON1_ID, LINE_BUTTON_PADDING);
|
||||
line2_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
|
||||
line2_->LayoutRightToSibling(BUTTON2_ID, LINE_BUTTON_PADDING);
|
||||
} else if (buttonNum_ == 2) { // 2: two buttons
|
||||
if (button1_ != nullptr) {
|
||||
line1_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
|
||||
line1_->LayoutRightToSibling(BUTTON1_ID, LINE_BUTTON_PADDING);
|
||||
} else {
|
||||
line1_->LayoutBottomOfParent(LINE_BOTTOM_PADDING);
|
||||
line1_->LayoutRightToSibling(BUTTON2_ID, LINE_BUTTON_PADDING);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::CreateDialogWindow()
|
||||
{
|
||||
dialogLayer_->LayoutCenterOfParent();
|
||||
Rect rect = dialogLayer_->GetRect();
|
||||
int16_t offset_x = dialogLayer_->GetX();
|
||||
int16_t offset_y = dialogLayer_->GetY();
|
||||
|
||||
windowRootView_->SetPosition(-offset_x, -offset_y);
|
||||
windowRootView_->Invalidate();
|
||||
|
||||
WindowConfig config = {};
|
||||
config.rect = rect;
|
||||
config.rect.SetPosition(offset_x, offset_y);
|
||||
config.isModal = true;
|
||||
window_ = Window::CreateWindow(config);
|
||||
if (window_ != nullptr) {
|
||||
window_->BindRootView(windowRootView_);
|
||||
} else {
|
||||
GRAPHIC_LOGE("Create window false!");
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::SetButtonColor(DialogButtonType buttonType, ColorType color)
|
||||
{
|
||||
switch (buttonType) {
|
||||
case DialogButtonType::BUTTON_LEFT:
|
||||
if (button1_ != nullptr) {
|
||||
button1_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.full, UIButton::ButtonState::RELEASED);
|
||||
button1_->SetStyleForState(STYLE_BACKGROUND_OPA, color.alpha, UIButton::ButtonState::RELEASED);
|
||||
colorType1_ = color;
|
||||
}
|
||||
break;
|
||||
case DialogButtonType::BUTTON_MID:
|
||||
if (button2_ != nullptr) {
|
||||
button2_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.full, UIButton::ButtonState::RELEASED);
|
||||
button2_->SetStyleForState(STYLE_BACKGROUND_OPA, color.alpha, UIButton::ButtonState::RELEASED);
|
||||
colorType2_ = color;
|
||||
}
|
||||
break;
|
||||
case DialogButtonType::BUTTON_RIGHT:
|
||||
if (button3_ != nullptr) {
|
||||
button3_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.full, UIButton::ButtonState::RELEASED);
|
||||
button3_->SetStyleForState(STYLE_BACKGROUND_COLOR, color.alpha, UIButton::ButtonState::RELEASED);
|
||||
colorType3_ = color;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UIDialog::SetOnCancelListener(UIView::OnClickListener* onCancelListener)
|
||||
{
|
||||
if (onCancelListener == nullptr) {
|
||||
return;
|
||||
}
|
||||
onCancelListener_ = onCancelListener;
|
||||
}
|
||||
|
||||
void UIDialog::EnableAutoCancel(bool enable)
|
||||
{
|
||||
enableAutoCancel_ = enable;
|
||||
}
|
||||
|
||||
void UIDialog::DestoryWindow()
|
||||
{
|
||||
if (window_ != nullptr) {
|
||||
Window::DestoryWindow(window_);
|
||||
window_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef ENABLE_DEBUG
|
||||
const char* UIDialog::GetButtonText(DialogButtonType buttonType) const
|
||||
{
|
||||
switch (buttonType) {
|
||||
case DialogButtonType::BUTTON_LEFT:
|
||||
if (button1_ != nullptr) {
|
||||
return button1_->GetText();
|
||||
}
|
||||
return nullptr;
|
||||
case DialogButtonType::BUTTON_MID:
|
||||
if (button2_ != nullptr) {
|
||||
return button2_->GetText();
|
||||
}
|
||||
return nullptr;
|
||||
case DialogButtonType::BUTTON_RIGHT:
|
||||
if (button3_ != nullptr) {
|
||||
return button3_->GetText();
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
UIView::OnClickListener* UIDialog::GetButtonListener(DialogButtonType buttonType) const
|
||||
{
|
||||
switch (buttonType) {
|
||||
case DialogButtonType::BUTTON_LEFT:
|
||||
if (button1_ != nullptr) {
|
||||
return button1_->GetOnClickListener();
|
||||
}
|
||||
return nullptr;
|
||||
case DialogButtonType::BUTTON_MID:
|
||||
if (button2_ != nullptr) {
|
||||
return button2_->GetOnClickListener();
|
||||
}
|
||||
return nullptr;
|
||||
case DialogButtonType::BUTTON_RIGHT:
|
||||
if (button3_ != nullptr) {
|
||||
return button3_->GetOnClickListener();
|
||||
}
|
||||
return nullptr;
|
||||
default:
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
ColorType UIDialog::GetButtonColor(DialogButtonType buttonType) const
|
||||
{
|
||||
switch (buttonType) {
|
||||
case DialogButtonType::BUTTON_LEFT:
|
||||
if (button1_ != nullptr) {
|
||||
return colorType1_;
|
||||
}
|
||||
break;
|
||||
case DialogButtonType::BUTTON_MID:
|
||||
if (button2_ != nullptr) {
|
||||
return colorType2_;
|
||||
}
|
||||
break;
|
||||
case DialogButtonType::BUTTON_RIGHT:
|
||||
if (button3_ != nullptr) {
|
||||
return colorType3_;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
ASSERT(0);
|
||||
}
|
||||
#endif // ENABLE_DEBUG
|
||||
} // namespace OHOS
|
||||
#endif // ENABLE_WINDOW
|
||||
Executable
+249
@@ -0,0 +1,249 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_digital_clock.h"
|
||||
#include <cstdio>
|
||||
#include "components/ui_view_group.h"
|
||||
#include "font/ui_font.h"
|
||||
#include "graphic_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIDigitalClock::UIDigitalClock()
|
||||
: timeLabels_{0},
|
||||
displayMode_(DISPLAY_24_HOUR),
|
||||
leadingZero_(true),
|
||||
color_(Color::White()),
|
||||
prevHour_(0),
|
||||
prevMinute_(0),
|
||||
prevSecond_(0),
|
||||
verticalShow_(false)
|
||||
{
|
||||
style_ = &(StyleDefault::GetBackgroundTransparentStyle());
|
||||
}
|
||||
|
||||
void UIDigitalClock::InitTimeLabels()
|
||||
{
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
if (timeLabels_[i] == nullptr) {
|
||||
timeLabels_[i] = new UILabel;
|
||||
if (timeLabels_[i] == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
timeLabels_[i]->SetLineBreakMode(UILabel::LINE_BREAK_ADAPT);
|
||||
timeLabels_[i]->SetStyle(STYLE_BACKGROUND_OPA, OPA_TRANSPARENT);
|
||||
Add(timeLabels_[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIDigitalClock::DisplayLeadingZero(bool displayLeadingZero)
|
||||
{
|
||||
leadingZero_ = displayLeadingZero;
|
||||
UpdateClock(false);
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetOpacity(uint8_t opacity)
|
||||
{
|
||||
opaScale_ = opacity;
|
||||
InitTimeLabels();
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetStyle(STYLE_TEXT_OPA, opacity);
|
||||
}
|
||||
RefreshTime();
|
||||
}
|
||||
|
||||
uint8_t UIDigitalClock::GetOpacity() const
|
||||
{
|
||||
return opaScale_;
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetFontId(uint8_t fontId)
|
||||
{
|
||||
SetStyle(STYLE_TEXT_FONT, fontId);
|
||||
InitTimeLabels();
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetFontId(fontId);
|
||||
}
|
||||
UpdateClock(false);
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetFont(const char* name, uint8_t size)
|
||||
{
|
||||
InitTimeLabels();
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetFont(name, size);
|
||||
}
|
||||
UpdateClock(false);
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetColor(ColorType color)
|
||||
{
|
||||
color_ = color;
|
||||
InitTimeLabels();
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetStyle(STYLE_TEXT_COLOR, color.full);
|
||||
}
|
||||
RefreshTime();
|
||||
}
|
||||
|
||||
void UIDigitalClock::TimeElementRefresh()
|
||||
{
|
||||
InitTimeLabels();
|
||||
if (currentHour_ != prevHour_) {
|
||||
prevHour_ = currentHour_;
|
||||
timeLabels_[HOUR_ELEMENT]->Invalidate();
|
||||
}
|
||||
|
||||
if (currentMinute_ != prevMinute_) {
|
||||
prevMinute_ = currentMinute_;
|
||||
timeLabels_[MINUTE_ELEMENT]->Invalidate();
|
||||
}
|
||||
|
||||
if (currentSecond_ != prevSecond_) {
|
||||
prevSecond_ = currentSecond_;
|
||||
timeLabels_[SECOND_ELEMENT]->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UIDigitalClock::RefreshTime()
|
||||
{
|
||||
InitTimeLabels();
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UIDigitalClock::UpdateClock(bool clockInit)
|
||||
{
|
||||
char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE] = {{0}};
|
||||
const char* formatWithColon = leadingZero_ ? "%02d:" : "%d:";
|
||||
const char* formatWithoutColon = leadingZero_ ? "%02d" : "%d";
|
||||
const char* format = verticalShow_ ? formatWithoutColon : formatWithColon;
|
||||
const char* formatForMinute = verticalShow_ ? "%02d" : "%02d:";
|
||||
switch (displayMode_) {
|
||||
case DISPLAY_24_HOUR_NO_SECONDS: {
|
||||
if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_) < 0) {
|
||||
return;
|
||||
}
|
||||
if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, "%02d", currentMinute_) < 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DISPLAY_12_HOUR_NO_SECONDS: {
|
||||
if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_ % HALF_DAY_IN_HOUR) < 0) {
|
||||
return;
|
||||
}
|
||||
if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, "%02d", currentMinute_) < 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DISPLAY_12_HOUR: {
|
||||
if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_ % HALF_DAY_IN_HOUR) < 0) {
|
||||
return;
|
||||
}
|
||||
if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, formatForMinute, currentMinute_) < 0) {
|
||||
return;
|
||||
}
|
||||
if (sprintf_s(buf[SECOND_ELEMENT], BUFFER_SIZE, "%02d", currentSecond_) < 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DISPLAY_24_HOUR: {
|
||||
if (sprintf_s(buf[HOUR_ELEMENT], BUFFER_SIZE, format, currentHour_) < 0) {
|
||||
return;
|
||||
}
|
||||
if (sprintf_s(buf[MINUTE_ELEMENT], BUFFER_SIZE, formatForMinute, currentMinute_) < 0) {
|
||||
return;
|
||||
}
|
||||
if (sprintf_s(buf[SECOND_ELEMENT], BUFFER_SIZE, "%02d", currentSecond_) < 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
break;
|
||||
}
|
||||
}
|
||||
SetTimeLabels(buf);
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetTimeLabels(const char buf[TIME_ELEMENT_COUNT][BUFFER_SIZE])
|
||||
{
|
||||
InitTimeLabels();
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetText(buf[i]);
|
||||
}
|
||||
|
||||
SetTimeLabelsPosition();
|
||||
TimeElementRefresh();
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetHorizontal()
|
||||
{
|
||||
InitTimeLabels();
|
||||
uint16_t totalWidth = timeLabels_[HOUR_ELEMENT]->GetWidth() + timeLabels_[MINUTE_ELEMENT]->GetWidth() +
|
||||
timeLabels_[SECOND_ELEMENT]->GetWidth();
|
||||
UITextLanguageAlignment align = timeLabels_[HOUR_ELEMENT]->GetHorAlign();
|
||||
int16_t x = 0;
|
||||
Rect rect = GetContentRect();
|
||||
if (align == TEXT_ALIGNMENT_CENTER) {
|
||||
x = (rect.GetWidth() >> 1) - (totalWidth >> 1);
|
||||
} else if (align == TEXT_ALIGNMENT_RIGHT) {
|
||||
x = rect.GetRight() - totalWidth;
|
||||
}
|
||||
timeLabels_[HOUR_ELEMENT]->SetPosition(x, 0);
|
||||
int16_t width = timeLabels_[HOUR_ELEMENT]->GetWidth();
|
||||
for (uint8_t i = 1; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetPosition(x + width, 0);
|
||||
width += timeLabels_[i]->GetWidth();
|
||||
}
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetTimeLabelsPosition()
|
||||
{
|
||||
if (verticalShow_) {
|
||||
SetVertical();
|
||||
} else {
|
||||
SetHorizontal();
|
||||
}
|
||||
}
|
||||
|
||||
void UIDigitalClock::SetVertical()
|
||||
{
|
||||
InitTimeLabels();
|
||||
int16_t fontHeight = timeLabels_[HOUR_ELEMENT]->GetHeight();
|
||||
timeLabels_[HOUR_ELEMENT]->SetPosition(0, 0);
|
||||
int16_t y = fontHeight;
|
||||
for (uint8_t i = 1; i < TIME_ELEMENT_COUNT; i++) {
|
||||
timeLabels_[i]->SetPosition(0, y);
|
||||
y += fontHeight;
|
||||
}
|
||||
}
|
||||
|
||||
UIDigitalClock::~UIDigitalClock()
|
||||
{
|
||||
for (uint8_t i = 0; i < TIME_ELEMENT_COUNT; i++) {
|
||||
if (timeLabels_[i] != nullptr) {
|
||||
delete timeLabels_[i];
|
||||
timeLabels_[i] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+204
@@ -0,0 +1,204 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_image_animator.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIImageAnimatorView::UIImageAnimatorView()
|
||||
: imageSrc_(nullptr), imageNum_(0), tickOfUpdate_(1), timeOfUpdate_(DEFAULT_TASK_PERIOD),
|
||||
timeOfPause_(0), tickOfPause_(0), repeatTimes_(1), imageAnimator_(&imageAnimatorCallback_, this, 0, true),
|
||||
listener_(nullptr), reverse_(false), repeat_(true), sizeFixed_(false), fillMode_(true)
|
||||
{
|
||||
AnimatorManager::GetInstance()->Add(&imageAnimator_);
|
||||
}
|
||||
|
||||
UIImageAnimatorView::~UIImageAnimatorView()
|
||||
{
|
||||
AnimatorManager::GetInstance()->Remove(&imageAnimator_);
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::ImageAnimatorCallback::Callback(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIImageAnimatorView* imageAnimatorView = static_cast<UIImageAnimatorView*>(view);
|
||||
|
||||
imageSrc_ = imageAnimatorView->GetImageAnimatorSrc();
|
||||
imageNum_ = imageAnimatorView->GetImageAnimatorImageNum();
|
||||
if ((imageSrc_ == nullptr) || (imageNum_ == 0) || (imageAnimatorView->tickOfUpdate_ == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!imageAnimatorView->IsRepeat() && (repeat_ == imageAnimatorView->GetRepeatTimes())) {
|
||||
imageAnimatorView->Stop();
|
||||
return;
|
||||
}
|
||||
|
||||
tickNum_++;
|
||||
|
||||
if (loop_ != imageNum_) {
|
||||
if (tickNum_ < imageAnimatorView->tickOfUpdate_) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (imageAnimatorView->tickOfPause_ != 0) {
|
||||
if (tickNum_ < imageAnimatorView->tickOfPause_) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (tickNum_ < imageAnimatorView->tickOfUpdate_) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
repeat_++;
|
||||
loop_ = 0;
|
||||
if (!imageAnimatorView->IsRepeat() && (repeat_ == imageAnimatorView->GetRepeatTimes())) {
|
||||
imageAnimatorView->Stop();
|
||||
return;
|
||||
}
|
||||
}
|
||||
imageAnimatorView->UpdateImage(drawingImage_, loop_);
|
||||
tickNum_ = 0;
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::UpdateImage(uint8_t& drawingImage, uint8_t& loop)
|
||||
{
|
||||
Invalidate();
|
||||
drawingImage = reverse_ ? (imageNum_ - loop - 1) : loop;
|
||||
if (drawingImage >= imageNum_) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageAnimatorInfo* imageAnimatorInfo = &(imageSrc_[drawingImage]);
|
||||
if (imageAnimatorInfo->imageType == IMG_SRC_FILE_PATH) {
|
||||
SetSrc(imageAnimatorInfo->imagePath);
|
||||
} else if (imageAnimatorInfo->imageType == IMG_SRC_IMAGE_INFO) {
|
||||
SetSrc(imageAnimatorInfo->imageInfo);
|
||||
}
|
||||
if (!sizeFixed_) {
|
||||
SetPosition(imageAnimatorInfo->pos.x, imageAnimatorInfo->pos.y);
|
||||
SetWidth(imageAnimatorInfo->width);
|
||||
SetHeight(imageAnimatorInfo->height);
|
||||
}
|
||||
Invalidate();
|
||||
loop++;
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::SetImageAnimatorSrc(const ImageAnimatorInfo imageAnimatorInfoSrc[], uint8_t imageNum)
|
||||
{
|
||||
SetImageAnimatorSrc(imageAnimatorInfoSrc, imageNum, timeOfUpdate_);
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::SetImageAnimatorSrc(const ImageAnimatorInfo imageAnimatorInfoSrc[],
|
||||
uint8_t imageNum, uint16_t timeOfUpdate)
|
||||
{
|
||||
imageSrc_ = const_cast<ImageAnimatorInfo*>(imageAnimatorInfoSrc);
|
||||
imageNum_ = imageNum;
|
||||
timeOfUpdate_ = timeOfUpdate;
|
||||
tickOfUpdate_ = GetTickByTime(timeOfUpdate);
|
||||
return;
|
||||
}
|
||||
|
||||
const ImageAnimatorInfo* UIImageAnimatorView::GetImageAnimatorSrc() const
|
||||
{
|
||||
return imageSrc_;
|
||||
}
|
||||
|
||||
uint8_t UIImageAnimatorView::GetImageAnimatorImageNum() const
|
||||
{
|
||||
return imageNum_;
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::SetTimeOfUpdate(uint16_t timeOfUpdate)
|
||||
{
|
||||
timeOfUpdate_ = timeOfUpdate;
|
||||
tickOfUpdate_ = GetTickByTime(timeOfUpdate);
|
||||
}
|
||||
|
||||
uint16_t UIImageAnimatorView::GetTimeOfUpdate() const
|
||||
{
|
||||
return timeOfUpdate_;
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::SetTimeOfPause(uint16_t timeOfPause)
|
||||
{
|
||||
timeOfPause_ = timeOfPause;
|
||||
tickOfPause_ = GetTickByTime(timeOfPause);
|
||||
}
|
||||
|
||||
uint16_t UIImageAnimatorView::GetTimeOfPause() const
|
||||
{
|
||||
return timeOfPause_;
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::Start()
|
||||
{
|
||||
Reset(false);
|
||||
imageAnimator_.SetState(Animator::START);
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::Reset(bool fillMode)
|
||||
{
|
||||
if ((imageSrc_ == nullptr) || (imageNum_ == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Invalidate();
|
||||
uint8_t drawingImage;
|
||||
if (fillMode) {
|
||||
drawingImage = reverse_ ? 0 : (imageNum_ - 1);
|
||||
} else {
|
||||
drawingImage = reverse_ ? (imageNum_ - 1) : 0;
|
||||
}
|
||||
ImageAnimatorInfo* imageAnimatorInfo = &(imageSrc_[drawingImage]);
|
||||
if (imageAnimatorInfo->imageType == IMG_SRC_FILE_PATH) {
|
||||
SetSrc(imageAnimatorInfo->imagePath);
|
||||
} else if (imageAnimatorInfo->imageType == IMG_SRC_IMAGE_INFO) {
|
||||
SetSrc(imageAnimatorInfo->imageInfo);
|
||||
}
|
||||
if (!sizeFixed_) {
|
||||
SetPosition(imageAnimatorInfo->pos.x, imageAnimatorInfo->pos.y);
|
||||
SetWidth(imageAnimatorInfo->width);
|
||||
SetHeight(imageAnimatorInfo->height);
|
||||
}
|
||||
Invalidate();
|
||||
imageAnimatorCallback_.Reset();
|
||||
}
|
||||
|
||||
void UIImageAnimatorView::Stop()
|
||||
{
|
||||
if (imageAnimator_.GetState() == Animator::STOP) {
|
||||
return;
|
||||
}
|
||||
|
||||
imageAnimator_.SetState(Animator::STOP);
|
||||
Reset(fillMode_);
|
||||
if (listener_ != nullptr) {
|
||||
listener_->OnAnimatorStop(*this);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t UIImageAnimatorView::GetTickByTime(uint16_t time) const
|
||||
{
|
||||
uint8_t tick;
|
||||
if ((time > 0) && (time <= DEFAULT_TASK_PERIOD)) {
|
||||
tick = 1;
|
||||
} else {
|
||||
tick = time / DEFAULT_TASK_PERIOD;
|
||||
}
|
||||
return tick;
|
||||
}
|
||||
}
|
||||
Executable
+424
@@ -0,0 +1,424 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_image_view.h"
|
||||
#include "common/image.h"
|
||||
#include "common/typed_text.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_label.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "file.h"
|
||||
#include "image_info.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "mem_api.h"
|
||||
#ifndef VERSION_LITE
|
||||
#include "gif_lib.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
#ifndef VERSION_LITE
|
||||
class GifImageAnimator : public Animator, public AnimatorCallback {
|
||||
public:
|
||||
GifImageAnimator(UIView* view, const char* src)
|
||||
: Animator(this, view, 0, true),
|
||||
gifFileType_(nullptr),
|
||||
imageIndex_(0),
|
||||
delayTime_(0),
|
||||
lastRunTime_(0),
|
||||
deltaTime_(0),
|
||||
gifDataSize_(0),
|
||||
src_(src)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~GifImageAnimator()
|
||||
{
|
||||
CloseGifFile();
|
||||
}
|
||||
|
||||
void Callback(UIView* view) override;
|
||||
|
||||
void SetGifFileType(GifFileType* gifFileType)
|
||||
{
|
||||
gifFileType_ = gifFileType;
|
||||
}
|
||||
|
||||
uint32_t SetGifFrame(GifFileType* gifFileType, int32_t imageIndex, UIImageView* imageView) const;
|
||||
void DealGifImageData(const GifFileType* gifFileType,
|
||||
const GifImageDesc* gifImageDesc,
|
||||
const SavedImage* savedImage,
|
||||
GraphicsControlBlock gcb,
|
||||
const ColorMapObject* colorMap) const;
|
||||
const void OpenGifFile(const char* src);
|
||||
void CloseGifFile();
|
||||
|
||||
private:
|
||||
GifFileType* GetGifFileType()
|
||||
{
|
||||
if (gifFileType_ == nullptr) {
|
||||
OpenGifFile(src_);
|
||||
}
|
||||
return gifFileType_;
|
||||
}
|
||||
|
||||
GifFileType* gifFileType_;
|
||||
int32_t imageIndex_;
|
||||
uint32_t delayTime_;
|
||||
uint32_t lastRunTime_;
|
||||
uint32_t deltaTime_;
|
||||
uint32_t gifDataSize_;
|
||||
uint8_t* gifImageData_ = nullptr;
|
||||
const char* src_;
|
||||
};
|
||||
|
||||
const void GifImageAnimator::OpenGifFile(const char* src)
|
||||
{
|
||||
int32_t error = D_GIF_SUCCEEDED;
|
||||
GifFileType* gifFileType = DGifOpenFileName(src, &error);
|
||||
if (error != D_GIF_SUCCEEDED) {
|
||||
return;
|
||||
}
|
||||
DGifSlurp(gifFileType);
|
||||
/* 3 : when change single pixel to byte, the buffer should divided by 8, equal to shift right 3 bits. */
|
||||
uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(ARGB8888) >> 3;
|
||||
gifDataSize_ = gifFileType->SWidth * gifFileType->SHeight * pixelByteSize;
|
||||
gifImageData_ = static_cast<uint8_t*>(UIMalloc(gifDataSize_));
|
||||
if (gifImageData_ == nullptr) {
|
||||
CloseGifFile();
|
||||
return;
|
||||
}
|
||||
SetGifFileType(gifFileType);
|
||||
}
|
||||
|
||||
void GifImageAnimator::CloseGifFile()
|
||||
{
|
||||
GifFileType* gifFileType = GetGifFileType();
|
||||
if (gifFileType != nullptr) {
|
||||
DGifCloseFile(gifFileType, nullptr);
|
||||
}
|
||||
if (gifImageData_ != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(const_cast<uint8_t*>(gifImageData_)));
|
||||
gifImageData_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void GifImageAnimator::Callback(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIImageView* imageView = static_cast<UIImageView*>(view);
|
||||
uint32_t curTime = GetRunTime();
|
||||
if (curTime != 0) {
|
||||
if (curTime + deltaTime_ - lastRunTime_ >= delayTime_) {
|
||||
deltaTime_ = curTime + deltaTime_ - lastRunTime_ - delayTime_;
|
||||
lastRunTime_ = curTime;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
GifFileType* gifFileType = GetGifFileType();
|
||||
if (gifFileType != nullptr) {
|
||||
delayTime_ = SetGifFrame(gifFileType, imageIndex_, imageView);
|
||||
imageIndex_ = (imageIndex_ < gifFileType->ImageCount - 1) ? (imageIndex_ + 1) : 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t GifImageAnimator::SetGifFrame(GifFileType* gifFileType, int32_t imageIndex, UIImageView* imageView) const
|
||||
{
|
||||
SavedImage* savedImage = &(gifFileType->SavedImages[imageIndex]);
|
||||
if (savedImage == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
GifImageDesc* gifImageDesc = &(savedImage->ImageDesc);
|
||||
if (gifImageDesc == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
GraphicsControlBlock gcb;
|
||||
int32_t ret = DGifSavedExtensionToGCB(gifFileType, imageIndex, &gcb);
|
||||
if (ret != GIF_OK) {
|
||||
return 0;
|
||||
}
|
||||
ColorMapObject* colorMap = nullptr;
|
||||
if (gifImageDesc->ColorMap != nullptr) {
|
||||
colorMap = gifImageDesc->ColorMap;
|
||||
} else {
|
||||
colorMap = gifFileType->SColorMap;
|
||||
}
|
||||
|
||||
DealGifImageData(gifFileType, gifImageDesc, savedImage, gcb, colorMap);
|
||||
if (gifImageData_ == nullptr) {
|
||||
return 0;
|
||||
}
|
||||
imageView->gifFrameFlag_ = true;
|
||||
ImageInfo gifFrame;
|
||||
gifFrame.header.width = gifFileType->SWidth;
|
||||
gifFrame.header.height = gifFileType->SHeight;
|
||||
gifFrame.header.colorMode = ARGB8888;
|
||||
gifFrame.dataSize = gifDataSize_;
|
||||
gifFrame.data = gifImageData_;
|
||||
imageView->SetSrc(&gifFrame);
|
||||
|
||||
if (gcb.DelayTime >= 0) {
|
||||
return static_cast<uint32_t>(gcb.DelayTime) * 10; // 10: change hundredths (1/100) of a second to millisecond
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
void GifImageAnimator::DealGifImageData(const GifFileType* gifFileType,
|
||||
const GifImageDesc* gifImageDesc,
|
||||
const SavedImage* savedImage,
|
||||
GraphicsControlBlock gcb,
|
||||
const ColorMapObject* colorMap) const
|
||||
{
|
||||
if ((gifFileType == nullptr) || (gifImageDesc == nullptr) || (savedImage == nullptr) ||
|
||||
(savedImage->RasterBits == nullptr) || (colorMap == nullptr) || (colorMap->Colors == nullptr)) {
|
||||
return;
|
||||
}
|
||||
uint8_t colorIndex = 0;
|
||||
GifColorType* gifColorType = nullptr;
|
||||
uint32_t index = 0;
|
||||
bool transparentColor = true;
|
||||
int32_t loc = 0;
|
||||
for (int32_t x = 0; x < gifFileType->SHeight; x++) {
|
||||
for (int32_t y = 0; y < gifFileType->SWidth; y++) {
|
||||
transparentColor = true;
|
||||
if ((x >= gifImageDesc->Top) && (x < gifImageDesc->Top + gifImageDesc->Height) &&
|
||||
(y >= gifImageDesc->Left) && (y < gifImageDesc->Left + gifImageDesc->Width)) {
|
||||
loc = (x - gifImageDesc->Top) * gifImageDesc->Width + (y - gifImageDesc->Left);
|
||||
colorIndex = savedImage->RasterBits[loc];
|
||||
|
||||
if ((gcb.DisposalMode != DISPOSE_DO_NOT) || (gcb.TransparentColor == NO_TRANSPARENT_COLOR) ||
|
||||
(colorIndex != gcb.TransparentColor)) {
|
||||
transparentColor = false;
|
||||
}
|
||||
}
|
||||
if (transparentColor) {
|
||||
index += 4; // 4: skip color index, keep last frame color
|
||||
} else {
|
||||
gifColorType = &colorMap->Colors[colorIndex];
|
||||
gifImageData_[index++] = gifColorType->Blue;
|
||||
gifImageData_[index++] = gifColorType->Green;
|
||||
gifImageData_[index++] = gifColorType->Red;
|
||||
gifImageData_[index++] = OPA_OPAQUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
UIImageView::UIImageView()
|
||||
: imageWidth_(0),
|
||||
imageHeight_(0),
|
||||
autoEnable_(true),
|
||||
needRefresh_(false),
|
||||
colorFormat_(UNKNOW),
|
||||
blurLevel_(BlurLevel::LEVEL0),
|
||||
algorithm_(TransformAlgorithm::BILINEAR),
|
||||
reserve_(0)
|
||||
{
|
||||
style_ = &(StyleDefault::GetBackgroundTransparentStyle());
|
||||
#ifndef VERSION_LITE
|
||||
gifImageAnimator_ = nullptr;
|
||||
gifFrameFlag_ = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
UIImageView::~UIImageView()
|
||||
{
|
||||
#ifndef VERSION_LITE
|
||||
RemoveAndStopGifAnimator();
|
||||
#endif
|
||||
}
|
||||
|
||||
bool UIImageView::OnPreDraw(Rect& invalidatedArea) const
|
||||
{
|
||||
if ((image_.GetSrcType() == IMG_SRC_UNKNOWN)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((colorFormat_ == RGB565) || (colorFormat_ == RGB888)) {
|
||||
if (GetRect().IsContains(invalidatedArea)) {
|
||||
return true;
|
||||
}
|
||||
invalidatedArea.Intersect(invalidatedArea, GetRect());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIImageView::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
OpacityType opa = GetMixOpaScale();
|
||||
DrawRect::Draw(GetRect(), invalidatedArea, *style_, opa);
|
||||
if ((imageHeight_ == 0) || (imageWidth_ == 0)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect viewRect = GetContentRect();
|
||||
Rect trunc(invalidatedArea);
|
||||
if (trunc.Intersect(trunc, viewRect)) {
|
||||
uint8_t srcType = image_.GetSrcType();
|
||||
if ((srcType == IMG_SRC_FILE) || (srcType == IMG_SRC_VARIABLE)) {
|
||||
Rect cordsTmp;
|
||||
cordsTmp.SetTop(viewRect.GetY());
|
||||
cordsTmp.SetBottom(viewRect.GetY() + imageHeight_ - 1);
|
||||
|
||||
if ((transMap_ == nullptr) || transMap_->IsInvalid()) {
|
||||
while (cordsTmp.GetTop() <= viewRect.GetBottom()) {
|
||||
cordsTmp.SetLeft(viewRect.GetX());
|
||||
cordsTmp.SetRight(viewRect.GetX() + imageWidth_ - 1);
|
||||
while (cordsTmp.GetLeft() <= viewRect.GetRight()) {
|
||||
image_.DrawImage(cordsTmp, trunc, *style_, opa);
|
||||
cordsTmp.SetLeft(cordsTmp.GetLeft() + imageWidth_);
|
||||
cordsTmp.SetRight(cordsTmp.GetRight() + imageWidth_);
|
||||
}
|
||||
cordsTmp.SetTop(cordsTmp.GetTop() + imageHeight_);
|
||||
cordsTmp.SetBottom(cordsTmp.GetBottom() + imageHeight_);
|
||||
}
|
||||
} else if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
|
||||
ImageInfo imgInfo;
|
||||
if (srcType == IMG_SRC_FILE) {
|
||||
CacheEntry entry;
|
||||
RetCode ret = CacheManager::GetInstance().Open(GetPath(), *style_, entry);
|
||||
if (ret != RetCode::OK) {
|
||||
return;
|
||||
}
|
||||
imgInfo = entry.GetImageInfo();
|
||||
} else {
|
||||
imgInfo = *(GetImageInfo());
|
||||
}
|
||||
uint8_t pxSize = DrawUtils::GetPxSizeByColorMode(imgInfo.header.colorMode);
|
||||
TransformDataInfo imageTranDataInfo = {imgInfo.header, imgInfo.data, pxSize,
|
||||
static_cast<BlurLevel>(blurLevel_),
|
||||
static_cast<TransformAlgorithm>(algorithm_)};
|
||||
|
||||
Rect origRect = GetOrigRect();
|
||||
transMap_->SetTransMapRect(origRect);
|
||||
OpacityType opaScale = DrawUtils::GetMixOpacity(opa, style_->imageOpa_);
|
||||
DrawUtils::GetInstance()->DrawTransform(invalidatedArea, {0, 0}, Color::Black(), opaScale, *transMap_,
|
||||
imageTranDataInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIImageView::SetSrc(const char* src)
|
||||
{
|
||||
#ifndef VERSION_LITE
|
||||
if (src == nullptr) {
|
||||
return;
|
||||
}
|
||||
const static uint8_t IMG_BYTES_TO_CHECK = 4; // 4: check 4 bytes of image file
|
||||
char buf[IMG_BYTES_TO_CHECK] = {0};
|
||||
int32_t fd = open(src, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
return;
|
||||
}
|
||||
if (read(fd, buf, IMG_BYTES_TO_CHECK) != IMG_BYTES_TO_CHECK) {
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
close(fd);
|
||||
bool updated = false;
|
||||
RemoveAndStopGifAnimator();
|
||||
// 0x47 0x49 0x46: GIF file's header
|
||||
if ((static_cast<uint8_t>(buf[0]) == 0x47) && (static_cast<uint8_t>(buf[1]) == 0x49) &&
|
||||
(static_cast<uint8_t>(buf[2]) == 0x46)) { // 2: array index of GIF file's header
|
||||
if (gifImageAnimator_ == nullptr) {
|
||||
gifImageAnimator_ = new GifImageAnimator(this, src);
|
||||
if (gifImageAnimator_ == nullptr) {
|
||||
GRAPHIC_LOGE("new GifImageAnimator fail");
|
||||
return;
|
||||
}
|
||||
}
|
||||
AddAndStartGifAnimator();
|
||||
updated = true;
|
||||
} else {
|
||||
updated = image_.SetSrc(src);
|
||||
}
|
||||
#else
|
||||
bool updated = image_.SetSrc(src);
|
||||
#endif
|
||||
if (!updated) {
|
||||
return;
|
||||
}
|
||||
needRefresh_ = true;
|
||||
if (autoEnable_) {
|
||||
UIImageView::ReMeasure();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UIImageView::ReMeasure()
|
||||
{
|
||||
if (!needRefresh_) {
|
||||
return;
|
||||
}
|
||||
needRefresh_ = false;
|
||||
|
||||
ImageHeader header = {0};
|
||||
image_.GetHeader(header);
|
||||
|
||||
imageWidth_ = header.width;
|
||||
imageHeight_ = header.height;
|
||||
colorFormat_ = header.colorMode;
|
||||
|
||||
if (autoEnable_) {
|
||||
Resize(imageWidth_, imageHeight_);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UIImageView::SetSrc(const ImageInfo* src)
|
||||
{
|
||||
#ifndef VERSION_LITE
|
||||
if (!gifFrameFlag_ && (gifImageAnimator_ != nullptr)) {
|
||||
RemoveAndStopGifAnimator();
|
||||
}
|
||||
gifFrameFlag_ = false;
|
||||
#endif
|
||||
bool updated = image_.SetSrc(src);
|
||||
if (!updated) {
|
||||
return;
|
||||
}
|
||||
needRefresh_ = true;
|
||||
if (autoEnable_) {
|
||||
UIImageView::ReMeasure();
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
#ifndef VERSION_LITE
|
||||
void UIImageView::AddAndStartGifAnimator()
|
||||
{
|
||||
if (gifImageAnimator_ != nullptr) {
|
||||
AnimatorManager::GetInstance()->Add(gifImageAnimator_);
|
||||
gifImageAnimator_->Start();
|
||||
}
|
||||
}
|
||||
|
||||
void UIImageView::RemoveAndStopGifAnimator()
|
||||
{
|
||||
if (gifImageAnimator_ != nullptr) {
|
||||
gifImageAnimator_->Stop();
|
||||
AnimatorManager::GetInstance()->Remove(gifImageAnimator_);
|
||||
delete gifImageAnimator_;
|
||||
gifImageAnimator_ = nullptr;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace OHOS
|
||||
@@ -0,0 +1,365 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_label.h"
|
||||
#include "font/ui_font.h"
|
||||
#include "graphic_log.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
class LabelAnimator : public Animator, public AnimatorCallback {
|
||||
public:
|
||||
LabelAnimator(uint16_t textX, uint16_t labelX, int16_t startPos, UIView* view)
|
||||
: Animator(this, view, 0, true),
|
||||
startPos_(startPos),
|
||||
textX_(textX),
|
||||
labelX_(labelX),
|
||||
offsetX_(startPos),
|
||||
waitCount_(ANIM_WAIT_COUNT),
|
||||
speed_(0),
|
||||
preRunTime_(0),
|
||||
decimal_(0)
|
||||
{
|
||||
AnimatorManager::GetInstance()->Add(this);
|
||||
}
|
||||
|
||||
virtual ~LabelAnimator()
|
||||
{
|
||||
AnimatorManager::GetInstance()->Remove(this);
|
||||
}
|
||||
|
||||
int16_t GetStartPos() const
|
||||
{
|
||||
return startPos_;
|
||||
}
|
||||
|
||||
void SetStartPos(int16_t pos)
|
||||
{
|
||||
startPos_ = pos;
|
||||
}
|
||||
|
||||
void UpdateWidth(uint16_t textWidth, uint16_t labelWidth)
|
||||
{
|
||||
textX_ = textWidth;
|
||||
labelX_ = labelWidth;
|
||||
waitCount_ = ANIM_WAIT_COUNT;
|
||||
preRunTime_ = 0;
|
||||
decimal_ = 0;
|
||||
offsetX_ = startPos_;
|
||||
static_cast<UILabel*>(view_)->offsetX_ = offsetX_;
|
||||
view_->Invalidate();
|
||||
}
|
||||
|
||||
void Callback(UIView* view) override
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t curTime = GetRunTime();
|
||||
if (waitCount_ > 0) {
|
||||
waitCount_--;
|
||||
preRunTime_ = curTime;
|
||||
return;
|
||||
}
|
||||
uint32_t time = (curTime > preRunTime_) ? (curTime - preRunTime_) : (UINT32_MAX - preRunTime_ + curTime);
|
||||
// 1000: 1000 milliseconds is 1 second
|
||||
float floatStep = (static_cast<float>(time * speed_) / 1000) + decimal_;
|
||||
uint16_t integerStep = static_cast<uint16_t>(floatStep);
|
||||
decimal_ = floatStep - integerStep;
|
||||
preRunTime_ = curTime;
|
||||
|
||||
if (integerStep != 0) {
|
||||
offsetX_ -= integerStep;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
offsetX_ = ((offsetX_ - labelX_) % (textX_ + labelX_)) + labelX_;
|
||||
static_cast<UILabel*>(view)->offsetX_ = offsetX_;
|
||||
view->Invalidate();
|
||||
}
|
||||
|
||||
void SetAnimatorSpeed(uint16_t animSpeed)
|
||||
{
|
||||
speed_ = animSpeed;
|
||||
decimal_ = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint8_t ANIM_WAIT_COUNT = 50;
|
||||
int16_t startPos_;
|
||||
uint16_t textX_;
|
||||
uint16_t labelX_;
|
||||
int16_t offsetX_;
|
||||
uint16_t waitCount_;
|
||||
uint16_t speed_;
|
||||
uint32_t preRunTime_;
|
||||
float decimal_;
|
||||
};
|
||||
|
||||
UILabel::UILabel()
|
||||
: labelText_(nullptr),
|
||||
needRefresh_(false),
|
||||
useTextColor_(false),
|
||||
hasAnimator_(false),
|
||||
lineBreakMode_(LINE_BREAK_ELLIPSIS),
|
||||
ellipsisIndex_(Text::TEXT_ELLIPSIS_END_INV),
|
||||
offsetX_(0),
|
||||
textColor_(Color::White()),
|
||||
animator_{nullptr}
|
||||
{
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
Style& style = (theme != nullptr) ? (theme->GetLabelStyle()) : (StyleDefault::GetLabelStyle());
|
||||
UIView::SetStyle(style);
|
||||
animator_.speed = DEFAULT_ANIMATOR_SPEED;
|
||||
}
|
||||
|
||||
UILabel::~UILabel()
|
||||
{
|
||||
if (hasAnimator_) {
|
||||
animator_.animator->Stop();
|
||||
delete animator_.animator;
|
||||
hasAnimator_ = false;
|
||||
}
|
||||
if (labelText_ != nullptr) {
|
||||
delete labelText_;
|
||||
labelText_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t UILabel::GetWidth()
|
||||
{
|
||||
InitLabelText();
|
||||
if (needRefresh_ && labelText_->IsExpandWidth()) {
|
||||
ReMeasure();
|
||||
}
|
||||
return UIView::GetWidth();
|
||||
}
|
||||
|
||||
int16_t UILabel::GetHeight()
|
||||
{
|
||||
InitLabelText();
|
||||
if (needRefresh_ && labelText_->IsExpandHeight()) {
|
||||
ReMeasure();
|
||||
}
|
||||
return UIView::GetHeight();
|
||||
}
|
||||
|
||||
void UILabel::SetStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
UIView::SetStyle(key, value);
|
||||
RefreshLabel();
|
||||
}
|
||||
|
||||
void UILabel::SetText(const char* text)
|
||||
{
|
||||
InitLabelText();
|
||||
labelText_->SetText(text);
|
||||
if (labelText_->IsNeedRefresh()) {
|
||||
RefreshLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::SetLineBreakMode(const uint8_t lineBreakMode)
|
||||
{
|
||||
InitLabelText();
|
||||
if ((lineBreakMode >= LINE_BREAK_MAX) || (lineBreakMode_ == lineBreakMode)) {
|
||||
return;
|
||||
}
|
||||
lineBreakMode_ = lineBreakMode;
|
||||
if ((lineBreakMode_ == LINE_BREAK_ADAPT) || (lineBreakMode_ == LINE_BREAK_STRETCH) ||
|
||||
(lineBreakMode_ == LINE_BREAK_MARQUEE)) {
|
||||
labelText_->SetExpandWidth(true);
|
||||
} else {
|
||||
labelText_->SetExpandWidth(false);
|
||||
}
|
||||
if ((lineBreakMode_ == LINE_BREAK_ADAPT) || (lineBreakMode_ == LINE_BREAK_WRAP)) {
|
||||
labelText_->SetExpandHeight(true);
|
||||
} else {
|
||||
labelText_->SetExpandHeight(false);
|
||||
}
|
||||
RefreshLabel();
|
||||
}
|
||||
|
||||
void UILabel::SetAlign(UITextLanguageAlignment horizontalAlign, UITextLanguageAlignment verticalAlign)
|
||||
{
|
||||
InitLabelText();
|
||||
labelText_->SetAlign(horizontalAlign, verticalAlign);
|
||||
if (labelText_->IsNeedRefresh()) {
|
||||
RefreshLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::SetFontId(uint8_t fontId)
|
||||
{
|
||||
InitLabelText();
|
||||
labelText_->SetFontId(fontId);
|
||||
if (labelText_->IsNeedRefresh()) {
|
||||
RefreshLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::SetFont(const char* name, uint8_t size)
|
||||
{
|
||||
InitLabelText();
|
||||
labelText_->SetFont(name, size);
|
||||
if (labelText_->IsNeedRefresh()) {
|
||||
RefreshLabel();
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t UILabel::GetTextWidth()
|
||||
{
|
||||
InitLabelText();
|
||||
if (labelText_->IsNeedRefresh()) {
|
||||
Style style = GetStyleConst();
|
||||
style.textColor_ = GetTextColor();
|
||||
labelText_->ReMeasureTextSize(GetContentRect(), style);
|
||||
}
|
||||
return labelText_->GetTextSize().x;
|
||||
}
|
||||
|
||||
uint16_t UILabel::GetTextHeight()
|
||||
{
|
||||
InitLabelText();
|
||||
if (labelText_->IsNeedRefresh()) {
|
||||
Style style = GetStyleConst();
|
||||
style.textColor_ = GetTextColor();
|
||||
labelText_->ReMeasureTextSize(GetContentRect(), style);
|
||||
}
|
||||
return labelText_->GetTextSize().y;
|
||||
}
|
||||
|
||||
void UILabel::SetWidth(int16_t width)
|
||||
{
|
||||
if (GetWidth() != width) {
|
||||
UIView::SetWidth(width);
|
||||
RefreshLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::SetHeight(int16_t height)
|
||||
{
|
||||
if (GetHeight() != height) {
|
||||
UIView::SetHeight(height);
|
||||
RefreshLabel();
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::RefreshLabel()
|
||||
{
|
||||
Invalidate();
|
||||
ellipsisIndex_ = Text::TEXT_ELLIPSIS_END_INV;
|
||||
if (!needRefresh_) {
|
||||
needRefresh_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::ReMeasure()
|
||||
{
|
||||
if (!needRefresh_) {
|
||||
return;
|
||||
}
|
||||
needRefresh_ = false;
|
||||
InitLabelText();
|
||||
Style style = GetStyleConst();
|
||||
style.textColor_ = GetTextColor();
|
||||
labelText_->ReMeasureTextSize(GetContentRect(), style);
|
||||
Point textSize = labelText_->GetTextSize();
|
||||
switch (lineBreakMode_) {
|
||||
case LINE_BREAK_ADAPT:
|
||||
Resize(textSize.x, textSize.y);
|
||||
break;
|
||||
case LINE_BREAK_STRETCH:
|
||||
SetWidth(textSize.x);
|
||||
break;
|
||||
case LINE_BREAK_WRAP:
|
||||
SetHeight(textSize.y);
|
||||
break;
|
||||
case LINE_BREAK_ELLIPSIS:
|
||||
ellipsisIndex_ = labelText_->GetEllipsisIndex(GetContentRect(), style);
|
||||
break;
|
||||
case LINE_BREAK_MARQUEE:
|
||||
RemeasureForMarquee(textSize.x);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::RemeasureForMarquee(int16_t textWidth)
|
||||
{
|
||||
int16_t rectWidth = GetWidth();
|
||||
if (textWidth > rectWidth) {
|
||||
offsetX_ = GetRollStartPos();
|
||||
if (labelText_->GetDirect() == TEXT_DIRECT_RTL) {
|
||||
labelText_->SetAlign(TEXT_ALIGNMENT_RIGHT);
|
||||
} else {
|
||||
labelText_->SetAlign(TEXT_ALIGNMENT_LEFT);
|
||||
}
|
||||
if (hasAnimator_) {
|
||||
static_cast<LabelAnimator*>(animator_.animator)->UpdateWidth(textWidth, rectWidth);
|
||||
} else {
|
||||
LabelAnimator* animator = new LabelAnimator(textWidth, rectWidth, offsetX_, this);
|
||||
if (animator == nullptr) {
|
||||
GRAPHIC_LOGE("new LabelAnimator fail");
|
||||
return;
|
||||
}
|
||||
animator->SetAnimatorSpeed(animator_.speed);
|
||||
animator_.animator = animator;
|
||||
hasAnimator_ = true;
|
||||
}
|
||||
animator_.animator->Start();
|
||||
} else {
|
||||
offsetX_ = 0;
|
||||
if (hasAnimator_) {
|
||||
animator_.animator->Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::SetRollStartPos(int16_t pos)
|
||||
{
|
||||
if (hasAnimator_) {
|
||||
static_cast<LabelAnimator*>(animator_.animator)->SetStartPos(pos);
|
||||
} else {
|
||||
animator_.pos = pos;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t UILabel::GetRollStartPos() const
|
||||
{
|
||||
return hasAnimator_ ? static_cast<LabelAnimator*>(animator_.animator)->GetStartPos() : animator_.pos;
|
||||
}
|
||||
|
||||
void UILabel::SetRollSpeed(uint16_t speed)
|
||||
{
|
||||
if (hasAnimator_) {
|
||||
static_cast<LabelAnimator*>(animator_.animator)->SetAnimatorSpeed(speed);
|
||||
} else {
|
||||
animator_.speed = speed;
|
||||
}
|
||||
}
|
||||
|
||||
void UILabel::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
InitLabelText();
|
||||
UIView::OnDraw(invalidatedArea);
|
||||
Style style = GetStyleConst();
|
||||
style.textColor_ = GetTextColor();
|
||||
OpacityType opa = GetMixOpaScale();
|
||||
labelText_->OnDraw(invalidatedArea, GetOrigRect(), GetContentRect(), offsetX_, style, ellipsisIndex_, opa);
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_label_button.h"
|
||||
#include "common/typed_text.h"
|
||||
#include "draw/draw_label.h"
|
||||
#include "font/ui_font.h"
|
||||
|
||||
namespace OHOS {
|
||||
UILabelButton::UILabelButton() : labelButtonText_(nullptr), offset_({ 0, 0 })
|
||||
{
|
||||
labelStyle_ = StyleDefault::GetDefaultStyle();
|
||||
}
|
||||
|
||||
void UILabelButton::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
UIButton::OnDraw(invalidatedArea);
|
||||
|
||||
Rect textRect = GetContentRect();
|
||||
textRect.SetLeft(textRect.GetLeft() + offset_.x);
|
||||
textRect.SetTop(textRect.GetTop() + offset_.y);
|
||||
InitLabelButtonText();
|
||||
labelButtonText_->ReMeasureTextSize(textRect, labelStyle_);
|
||||
OpacityType opa = GetMixOpaScale();
|
||||
uint16_t ellipsisIndex = labelButtonText_->GetEllipsisIndex(textRect, labelStyle_);
|
||||
labelButtonText_->OnDraw(invalidatedArea, GetOrigRect(), textRect, 0, labelStyle_, ellipsisIndex, opa);
|
||||
}
|
||||
|
||||
UILabelButton::~UILabelButton()
|
||||
{
|
||||
if (labelButtonText_ != nullptr) {
|
||||
delete labelButtonText_;
|
||||
labelButtonText_ = nullptr;
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+763
@@ -0,0 +1,763 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_list.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIList::Recycle::~Recycle()
|
||||
{
|
||||
ListNode<UIView*>* node = scrapView_.Begin();
|
||||
while (node != scrapView_.End()) {
|
||||
if (node->data_) {
|
||||
UIView* deleteView = node->data_;
|
||||
if (deleteView != nullptr) {
|
||||
delete deleteView;
|
||||
deleteView = nullptr;
|
||||
node->data_ = nullptr;
|
||||
}
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
scrapView_.Clear();
|
||||
}
|
||||
|
||||
void UIList::Recycle::InitRecycle()
|
||||
{
|
||||
if ((adapter_ == nullptr) || (listView_ == nullptr)) {
|
||||
return;
|
||||
}
|
||||
FillActiveView();
|
||||
listView_->Invalidate();
|
||||
}
|
||||
|
||||
UIView* UIList::Recycle::GetView(int16_t index)
|
||||
{
|
||||
if (adapter_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
UIView* inView = nullptr;
|
||||
UIView* retView = nullptr;
|
||||
|
||||
if (scrapView_.Size() != 0) {
|
||||
inView = scrapView_.Back();
|
||||
}
|
||||
|
||||
retView = adapter_->GetView(inView, index);
|
||||
if (retView != nullptr) {
|
||||
retView->SetViewIndex(index);
|
||||
scrapView_.PopBack();
|
||||
}
|
||||
return retView;
|
||||
}
|
||||
|
||||
void UIList::Recycle::FillActiveView()
|
||||
{
|
||||
if ((adapter_ == nullptr) || (listView_ == nullptr)) {
|
||||
return;
|
||||
}
|
||||
uint16_t index = listView_->GetStartIndex();
|
||||
if (listView_->GetDirection() == UIList::VERTICAL) {
|
||||
int16_t childBottom = 0;
|
||||
while ((index < adapter_->GetCount()) && (childBottom < listView_->GetHeight())) {
|
||||
UIView* view = GetView(index);
|
||||
if (view == nullptr) {
|
||||
break;
|
||||
}
|
||||
listView_->PushBack(view);
|
||||
if (listView_->childrenTail_) {
|
||||
childBottom =
|
||||
listView_->childrenTail_->GetY() + listView_->childrenTail_->GetRelativeRect().GetHeight();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
} else {
|
||||
int16_t childRight = 0;
|
||||
while ((index < adapter_->GetCount()) && (childRight < listView_->GetWidth())) {
|
||||
UIView* view = GetView(index);
|
||||
listView_->PushBack(view);
|
||||
if (listView_->childrenTail_) {
|
||||
childRight = listView_->childrenTail_->GetX() + listView_->childrenTail_->GetRelativeRect().GetWidth();
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
UIList::UIList()
|
||||
: onSelectedView_(nullptr),
|
||||
isLoopList_(false),
|
||||
isReCalculateDragEnd_(true),
|
||||
autoAlign_(false),
|
||||
startIndex_(0),
|
||||
topIndex_(0),
|
||||
bottomIndex_(0),
|
||||
selectPosition_(0),
|
||||
onSelectedIndex_(0),
|
||||
recycle_(this),
|
||||
scrollListener_(nullptr)
|
||||
{
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
rotateFactor_ = 1;
|
||||
rotateThreshold_ = 4; // 4: which means 25% of half view size
|
||||
#endif
|
||||
#if ENABLE_MOTOR
|
||||
motorType_ = MotorType::MOTOR_TYPE_ONE;
|
||||
#endif
|
||||
direction_ = VERTICAL;
|
||||
touchable_ = true;
|
||||
draggable_ = true;
|
||||
dragParentInstead_ = false;
|
||||
}
|
||||
|
||||
UIList::UIList(uint8_t direction)
|
||||
: onSelectedView_(nullptr),
|
||||
isLoopList_(false),
|
||||
isReCalculateDragEnd_(true),
|
||||
autoAlign_(false),
|
||||
startIndex_(0),
|
||||
topIndex_(0),
|
||||
bottomIndex_(0),
|
||||
selectPosition_(0),
|
||||
onSelectedIndex_(0),
|
||||
recycle_(this),
|
||||
scrollListener_(nullptr)
|
||||
{
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
rotateFactor_ = 1;
|
||||
rotateThreshold_ = 4; // 4: which means 25% of half view size
|
||||
#endif
|
||||
#if ENABLE_MOTOR
|
||||
motorType_ = MotorType::MOTOR_TYPE_ONE;
|
||||
#endif
|
||||
direction_ = direction;
|
||||
touchable_ = true;
|
||||
draggable_ = true;
|
||||
dragParentInstead_ = false;
|
||||
}
|
||||
|
||||
UIList::~UIList()
|
||||
{
|
||||
UIView* view = GetChildrenHead();
|
||||
while (view != nullptr) {
|
||||
UIView* tmp = view->GetNextSibling();
|
||||
delete view;
|
||||
view = tmp;
|
||||
}
|
||||
}
|
||||
|
||||
bool UIList::OnDragEvent(const DragEvent& event)
|
||||
{
|
||||
if (scrollAnimator_.GetState() != Animator::STOP) {
|
||||
UIAbstractScroll::StopAnimator();
|
||||
}
|
||||
int16_t xDistance = event.GetDeltaX();
|
||||
int16_t yDistance = event.GetDeltaY();
|
||||
isReCalculateDragEnd_ = true;
|
||||
if (direction_ == VERTICAL) {
|
||||
RefreshDeltaY(yDistance);
|
||||
DragYInner(yDistance);
|
||||
} else {
|
||||
DragXInner(xDistance);
|
||||
}
|
||||
return UIView::OnDragEvent(event);
|
||||
}
|
||||
|
||||
bool UIList::OnDragEndEvent(const DragEvent& event)
|
||||
{
|
||||
Point last = event.GetPreLastPoint();
|
||||
Point current = event.GetLastPoint();
|
||||
if ((last.x == current.x) && (last.y == current.y)) {
|
||||
last = current;
|
||||
current = event.GetCurrentPos();
|
||||
}
|
||||
isReCalculateDragEnd_ = false;
|
||||
if (!DragThrowAnimator(current, last)) {
|
||||
if (scrollListener_ && (scrollListener_->GetScrollState() == ListScrollListener::SCROLL_STATE_MOVE)) {
|
||||
scrollListener_->SetScrollState(ListScrollListener::SCROLL_STATE_STOP);
|
||||
scrollListener_->OnScrollEnd(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
}
|
||||
return UIView::OnDragEndEvent(event);
|
||||
}
|
||||
|
||||
bool UIList::OnPressEvent(const PressEvent& event)
|
||||
{
|
||||
StopAnimator();
|
||||
return UIView::OnPressEvent(event);
|
||||
}
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
bool UIList::OnRotateEvent(const RotateEvent& event)
|
||||
{
|
||||
int16_t tmpRotateLen = static_cast<int16_t>(event.GetRotate() * rotateFactor_);
|
||||
int16_t midPointX = static_cast<int16_t>(GetWidth() / 2); // 2 : Get the middle point X coord of the view
|
||||
int16_t midPointY = static_cast<int16_t>(GetHeight() / 2); // 2 : Get the middle point Y coord of the view
|
||||
Point last, current;
|
||||
#if ENABLE_MOTOR
|
||||
MotorFunc motorFunc = FocusManager::GetInstance()->GetMotorFunc();
|
||||
#endif
|
||||
|
||||
if (!throwDrag_ || ((MATH_ABS(tmpRotateLen) < (midPointX / rotateThreshold_)) &&
|
||||
(MATH_ABS(tmpRotateLen) < (midPointY / rotateThreshold_)))) {
|
||||
ScrollBy(tmpRotateLen);
|
||||
if (event.GetRotate() == 0) {
|
||||
isReCalculateDragEnd_ = false;
|
||||
DragThrowAnimator(Point{0, 0}, Point{0, 0});
|
||||
}
|
||||
} else {
|
||||
tmpRotateLen += tmpRotateLen;
|
||||
last = Point{midPointX, midPointY};
|
||||
if (direction_ == VERTICAL) {
|
||||
current = Point{midPointX, static_cast<int16_t>(midPointY + tmpRotateLen)};
|
||||
} else {
|
||||
current = Point{static_cast<int16_t>(midPointX + tmpRotateLen), midPointY};
|
||||
}
|
||||
isReCalculateDragEnd_ = false;
|
||||
DragThrowAnimator(current, last);
|
||||
#if ENABLE_MOTOR
|
||||
if (motorFunc != nullptr && motorType_ == MotorType::MOTOR_TYPE_TWO) {
|
||||
motorFunc(MotorType::MOTOR_TYPE_TWO);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_MOTOR
|
||||
if (motorFunc != nullptr && motorType_ == MotorType::MOTOR_TYPE_ONE) {
|
||||
motorFunc(MotorType::MOTOR_TYPE_ONE);
|
||||
}
|
||||
#endif
|
||||
|
||||
return UIView::OnRotateEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIList::ScrollBy(int16_t distance)
|
||||
{
|
||||
if (direction_ == VERTICAL) {
|
||||
DragYInner(distance);
|
||||
} else {
|
||||
DragXInner(distance);
|
||||
}
|
||||
if (scrollListener_ && (scrollListener_->GetScrollState() == ListScrollListener::SCROLL_STATE_MOVE)) {
|
||||
scrollListener_->SetScrollState(ListScrollListener::SCROLL_STATE_STOP);
|
||||
scrollListener_->OnScrollEnd(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIList::DragXInner(int16_t distance)
|
||||
{
|
||||
if (IsNeedReCalculateDragEnd()) {
|
||||
return false;
|
||||
}
|
||||
int16_t listWidth = GetWidth();
|
||||
if (distance == 0) {
|
||||
return true;
|
||||
}
|
||||
int16_t reboundSize = reboundSize_;
|
||||
if (isLoopList_ || (scrollAnimator_.GetState() != Animator::STOP)) {
|
||||
reboundSize = 0;
|
||||
}
|
||||
bool ret = 0;
|
||||
do {
|
||||
ret = MoveChildStep(distance);
|
||||
} while (ret);
|
||||
|
||||
if (isLoopList_) {
|
||||
return MoveOffset(distance);
|
||||
}
|
||||
if (distance > 0) {
|
||||
if (childrenHead_ && (childrenHead_->GetX() + distance > scrollBlankSize_ + reboundSize)) {
|
||||
distance = scrollBlankSize_ + reboundSize - childrenHead_->GetX();
|
||||
}
|
||||
} else {
|
||||
if (childrenTail_) {
|
||||
if (childrenTail_->GetRelativeRect().GetRight() <= listWidth - scrollBlankSize_ - reboundSize) {
|
||||
distance = 0;
|
||||
} else if (listWidth - (childrenTail_->GetX() + childrenTail_->GetRelativeRect().GetWidth() + distance) >
|
||||
scrollBlankSize_ + reboundSize) {
|
||||
distance = listWidth - scrollBlankSize_ - reboundSize - childrenTail_->GetX() -
|
||||
childrenTail_->GetRelativeRect().GetWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
return MoveOffset(distance);
|
||||
}
|
||||
|
||||
bool UIList::DragYInner(int16_t distance)
|
||||
{
|
||||
if (IsNeedReCalculateDragEnd()) {
|
||||
return false;
|
||||
}
|
||||
int16_t listHeigh = GetHeight();
|
||||
if (distance == 0) {
|
||||
return true;
|
||||
}
|
||||
int16_t reboundSize = reboundSize_;
|
||||
if (isLoopList_ || (scrollAnimator_.GetState() != Animator::STOP)) {
|
||||
reboundSize = 0;
|
||||
}
|
||||
bool ret = 0;
|
||||
do {
|
||||
ret = MoveChildStep(distance);
|
||||
} while (ret);
|
||||
|
||||
if (isLoopList_) {
|
||||
return MoveOffset(distance);
|
||||
}
|
||||
if (distance > 0) {
|
||||
if (childrenHead_ && (childrenHead_->GetY() + distance > scrollBlankSize_ + reboundSize)) {
|
||||
distance = scrollBlankSize_ + reboundSize - childrenHead_->GetY();
|
||||
}
|
||||
} else {
|
||||
if (childrenTail_) {
|
||||
if (childrenTail_->GetRelativeRect().GetBottom() <= listHeigh - scrollBlankSize_ - reboundSize) {
|
||||
distance = 0;
|
||||
} else if (listHeigh - (childrenTail_->GetY() + childrenTail_->GetRelativeRect().GetHeight() + distance) >
|
||||
scrollBlankSize_ + reboundSize) {
|
||||
distance = listHeigh - scrollBlankSize_ - reboundSize - childrenTail_->GetY() -
|
||||
childrenTail_->GetRelativeRect().GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
return MoveOffset(distance);
|
||||
}
|
||||
|
||||
bool UIList::MoveOffset(int16_t offset)
|
||||
{
|
||||
if (offset == 0) {
|
||||
return false;
|
||||
}
|
||||
if (direction_ == VERTICAL) {
|
||||
MoveChildByOffset(0, offset);
|
||||
} else {
|
||||
MoveChildByOffset(offset, 0);
|
||||
}
|
||||
Invalidate();
|
||||
if (scrollListener_ && (scrollListener_->GetScrollState() == ListScrollListener::SCROLL_STATE_STOP)) {
|
||||
scrollListener_->SetScrollState(ListScrollListener::SCROLL_STATE_MOVE);
|
||||
scrollListener_->OnScrollStart(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIList::IsNeedReCalculateDragEnd()
|
||||
{
|
||||
if (!autoAlign_ || isReCalculateDragEnd_ || (onSelectedView_ == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
int16_t animationLess = 0;
|
||||
if (direction_ == VERTICAL) {
|
||||
animationLess = animatorCallback_.endValueY_ - animatorCallback_.previousValueY_;
|
||||
} else {
|
||||
animationLess = animatorCallback_.endValueX_ - animatorCallback_.previousValueX_;
|
||||
}
|
||||
if (!isDragging_ || (MATH_ABS(animationLess) > RECALCULATE_DRAG_DISTANCE)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool UIList::ReCalculateDragEnd()
|
||||
{
|
||||
if ((onSelectedView_ == nullptr) || isReCalculateDragEnd_ || !autoAlign_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int16_t offsetX = 0;
|
||||
int16_t offsetY = 0;
|
||||
if (direction_ == VERTICAL) {
|
||||
// 2: half
|
||||
offsetY = selectPosition_ - (onSelectedView_->GetY() + (onSelectedView_->GetRelativeRect().GetHeight() / 2));
|
||||
} else {
|
||||
// 2: half
|
||||
offsetX = selectPosition_ - (onSelectedView_->GetX() + (onSelectedView_->GetRelativeRect().GetWidth() / 2));
|
||||
}
|
||||
animatorCallback_.SetDragStartValue(0, 0);
|
||||
animatorCallback_.SetDragEndValue(offsetX, offsetY);
|
||||
animatorCallback_.SetDragTimes(RECALCULATE_DRAG_TIMES * DRAG_ACC_FACTOR / GetDragACCLevel());
|
||||
scrollAnimator_.Start();
|
||||
isReCalculateDragEnd_ = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIList::MoveChildStepInner(int16_t distance,
|
||||
int16_t (UIView::*pfnGetXOrY)() const,
|
||||
int16_t (Rect::*pfnGetWidthOrHeight)() const)
|
||||
{
|
||||
bool popRet = false;
|
||||
bool pushRet = false;
|
||||
if (distance > 0) {
|
||||
if ((childrenHead_ == nullptr) || ((childrenHead_->*pfnGetXOrY)() + distance > 0)) {
|
||||
uint16_t index = GetIndexDec(topIndex_);
|
||||
if (index == topIndex_) {
|
||||
return false;
|
||||
}
|
||||
UIView* newView = recycle_.GetView(index);
|
||||
if (newView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
PushFront(newView);
|
||||
pushRet = true;
|
||||
}
|
||||
if (childrenTail_ != nullptr &&
|
||||
((childrenTail_->*pfnGetXOrY)() + distance > (this->GetRelativeRect().*pfnGetWidthOrHeight)())) {
|
||||
PopItem(childrenTail_);
|
||||
popRet = true;
|
||||
}
|
||||
} else {
|
||||
if ((childrenTail_ == nullptr) ||
|
||||
((childrenTail_->*pfnGetXOrY)() + (childrenTail_->GetRelativeRect().*pfnGetWidthOrHeight)() + distance <
|
||||
(this->GetRelativeRect().*pfnGetWidthOrHeight)())) {
|
||||
UIView* newView = recycle_.GetView(GetIndexInc(bottomIndex_));
|
||||
if (newView == nullptr) {
|
||||
return false;
|
||||
}
|
||||
PushBack(newView);
|
||||
pushRet = true;
|
||||
}
|
||||
if (childrenHead_ &&
|
||||
(childrenHead_->*pfnGetXOrY)() + distance + (childrenHead_->GetRelativeRect().*pfnGetWidthOrHeight)() < 0) {
|
||||
PopItem(childrenHead_);
|
||||
popRet = true;
|
||||
}
|
||||
}
|
||||
return (popRet || pushRet);
|
||||
}
|
||||
|
||||
bool UIList::MoveChildStep(int16_t distance)
|
||||
{
|
||||
if (direction_ == VERTICAL) {
|
||||
return MoveChildStepInner(distance, &UIView::GetY, &Rect::GetHeight);
|
||||
} else {
|
||||
return MoveChildStepInner(distance, &UIView::GetX, &Rect::GetWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void UIList::SetAdapter(AbstractAdapter* adapter)
|
||||
{
|
||||
recycle_.SetAdapter(adapter);
|
||||
recycle_.InitRecycle();
|
||||
}
|
||||
|
||||
UIView* UIList::GetSelectView()
|
||||
{
|
||||
if (onSelectedView_ != nullptr) {
|
||||
return onSelectedView_;
|
||||
}
|
||||
if ((childrenHead_ == nullptr) || (selectPosition_ == 0)) {
|
||||
return nullptr;
|
||||
}
|
||||
UIView* child = childrenHead_;
|
||||
while (child != nullptr) {
|
||||
if (direction_ == VERTICAL) {
|
||||
if ((child->GetY() <= selectPosition_) &&
|
||||
(child->GetY() + child->GetRelativeRect().GetHeight() >= selectPosition_)) {
|
||||
if (scrollListener_ != nullptr) {
|
||||
scrollListener_->OnItemSelected(child->GetViewIndex(), child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
} else {
|
||||
if ((child->GetX() <= selectPosition_) &&
|
||||
(child->GetX() + child->GetRelativeRect().GetWidth() >= selectPosition_)) {
|
||||
if (scrollListener_ != nullptr) {
|
||||
scrollListener_->OnItemSelected(child->GetViewIndex(), child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
}
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UIList::PushBack(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (childrenTail_ == nullptr) {
|
||||
SetHead(view);
|
||||
} else {
|
||||
if (direction_ == VERTICAL) {
|
||||
view->SetPosition(0, childrenTail_->GetY() + childrenTail_->GetRelativeRect().GetHeight());
|
||||
} else {
|
||||
view->SetPosition(childrenTail_->GetX() + childrenTail_->GetRelativeRect().GetWidth(), 0);
|
||||
}
|
||||
bottomIndex_ = GetIndexInc(bottomIndex_);
|
||||
}
|
||||
|
||||
view->SetDragParentInstead(true);
|
||||
UIViewGroup::Add(view);
|
||||
}
|
||||
|
||||
void UIList::PushFront(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (GetChildrenHead() == nullptr) {
|
||||
SetHead(view);
|
||||
} else {
|
||||
if (direction_ == VERTICAL) {
|
||||
view->SetPosition(0, GetChildrenHead()->GetY() - view->GetRelativeRect().GetHeight());
|
||||
} else {
|
||||
view->SetPosition(GetChildrenHead()->GetX() - view->GetRelativeRect().GetWidth(), 0);
|
||||
}
|
||||
topIndex_ = GetIndexDec(topIndex_);
|
||||
}
|
||||
view->SetDragParentInstead(true);
|
||||
UIViewGroup::Insert(nullptr, view);
|
||||
}
|
||||
|
||||
void UIList::PopItem(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
recycle_.AddScrapView(view);
|
||||
if (view == GetChildrenHead()) {
|
||||
topIndex_ = GetIndexInc(topIndex_);
|
||||
}
|
||||
|
||||
if (view == childrenTail_) {
|
||||
bottomIndex_ = GetIndexDec(bottomIndex_);
|
||||
}
|
||||
UIViewGroup::Remove(view);
|
||||
}
|
||||
|
||||
void UIList::SetHead(UIView* view)
|
||||
{
|
||||
if (view != nullptr) {
|
||||
view->SetPosition(0, 0);
|
||||
topIndex_ = startIndex_;
|
||||
bottomIndex_ = startIndex_;
|
||||
}
|
||||
}
|
||||
|
||||
void UIList::MoveChildByOffset(int16_t xOffset, int16_t yOffset)
|
||||
{
|
||||
UIView* view = GetChildrenHead();
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
int16_t height;
|
||||
int16_t width;
|
||||
|
||||
if ((onSelectedIndex_ != NULL_SELECT_INDEX) && (selectPosition_ != 0)) {
|
||||
if (direction_ == VERTICAL) {
|
||||
height = view->GetRelativeRect().GetHeight();
|
||||
if ((GetChildrenHead()->GetY() + yOffset > selectPosition_) ||
|
||||
(childrenTail_->GetY() + height + yOffset < selectPosition_)) {
|
||||
onSelectedIndex_ = NULL_SELECT_INDEX;
|
||||
onSelectedView_ = nullptr;
|
||||
if (scrollListener_ != nullptr) {
|
||||
scrollListener_->OnItemSelected(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
width = view->GetRelativeRect().GetWidth();
|
||||
if ((GetChildrenHead()->GetX() + xOffset > selectPosition_) ||
|
||||
(childrenTail_->GetX() + width < selectPosition_)) {
|
||||
onSelectedIndex_ = NULL_SELECT_INDEX;
|
||||
onSelectedView_ = nullptr;
|
||||
if (scrollListener_ != nullptr) {
|
||||
scrollListener_->OnItemSelected(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool isSelectViewFind = false;
|
||||
while (view != nullptr) {
|
||||
x = view->GetX() + xOffset;
|
||||
y = view->GetY() + yOffset;
|
||||
view->SetPosition(x, y);
|
||||
if ((selectPosition_ != 0) && !isSelectViewFind) {
|
||||
if (direction_ == VERTICAL) {
|
||||
height = view->GetRelativeRect().GetHeight();
|
||||
/* Views may be the same but have different indexes because of view recycling. */
|
||||
if ((y <= selectPosition_) && (y + height >= selectPosition_) &&
|
||||
((onSelectedView_ != view) || (onSelectedIndex_ != view->GetViewIndex()))) {
|
||||
onSelectedIndex_ = view->GetViewIndex();
|
||||
onSelectedView_ = view;
|
||||
if (scrollListener_ != nullptr) {
|
||||
scrollListener_->OnItemSelected(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
isSelectViewFind = true;
|
||||
}
|
||||
} else {
|
||||
width = view->GetRelativeRect().GetWidth();
|
||||
if ((x <= selectPosition_) && (x + width >= selectPosition_) &&
|
||||
((onSelectedView_ != view) || (onSelectedIndex_ != view->GetViewIndex()))) {
|
||||
onSelectedIndex_ = view->GetViewIndex();
|
||||
onSelectedView_ = view;
|
||||
if (scrollListener_ != nullptr) {
|
||||
scrollListener_->OnItemSelected(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
isSelectViewFind = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
void UIList::StopAnimator()
|
||||
{
|
||||
UIAbstractScroll::StopAnimator();
|
||||
if (!ReCalculateDragEnd()) {
|
||||
if ((scrollListener_ != nullptr) &&
|
||||
(scrollListener_->GetScrollState() == ListScrollListener::SCROLL_STATE_MOVE)) {
|
||||
scrollListener_->SetScrollState(ListScrollListener::SCROLL_STATE_STOP);
|
||||
scrollListener_->OnScrollEnd(onSelectedIndex_, onSelectedView_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t UIList::GetIndexInc(uint16_t index)
|
||||
{
|
||||
uint16_t ret = index + 1;
|
||||
if (isLoopList_ && (recycle_.GetAdapterItemCount() != 0)) {
|
||||
ret = ret % recycle_.GetAdapterItemCount();
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
uint16_t UIList::GetIndexDec(uint16_t index)
|
||||
{
|
||||
if (index == 0) {
|
||||
if (isLoopList_) {
|
||||
return recycle_.GetAdapterItemCount() - 1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
return index - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void UIList::ScrollTo(uint16_t index)
|
||||
{
|
||||
UIView* child = GetChildrenHead();
|
||||
UIView* tmp = nullptr;
|
||||
while (child != nullptr) {
|
||||
tmp = child;
|
||||
child = child->GetNextSibling();
|
||||
PopItem(tmp);
|
||||
}
|
||||
onSelectedView_ = nullptr;
|
||||
SetStartIndex(index);
|
||||
recycle_.InitRecycle();
|
||||
}
|
||||
|
||||
void UIList::RefreshList()
|
||||
{
|
||||
int16_t topIndex = topIndex_;
|
||||
UIView* child = GetChildrenHead();
|
||||
UIView* tmp = nullptr;
|
||||
int16_t offset = 0;
|
||||
if (child != nullptr) {
|
||||
if (direction_ == VERTICAL) {
|
||||
offset = child->GetY();
|
||||
} else {
|
||||
offset = child->GetX();
|
||||
}
|
||||
}
|
||||
|
||||
while (child != nullptr) {
|
||||
tmp = child;
|
||||
child = child->GetNextSibling();
|
||||
PopItem(tmp);
|
||||
}
|
||||
onSelectedView_ = nullptr;
|
||||
|
||||
uint16_t tmpStartIndex = startIndex_;
|
||||
if (topIndex > recycle_.GetAdapterItemCount() - 1) {
|
||||
startIndex_ = 0;
|
||||
offset = 0;
|
||||
} else {
|
||||
startIndex_ = topIndex;
|
||||
}
|
||||
recycle_.InitRecycle();
|
||||
startIndex_ = tmpStartIndex;
|
||||
|
||||
if (direction_ == VERTICAL) {
|
||||
DragYInner(offset);
|
||||
} else {
|
||||
DragXInner(offset);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UIList::RemoveAll()
|
||||
{
|
||||
UIViewGroup::RemoveAll();
|
||||
recycle_.ClearScrapView();
|
||||
}
|
||||
|
||||
void UIList::CalculateReboundDistance(int16_t& dragDistanceX, int16_t& dragDistanceY)
|
||||
{
|
||||
if (isLoopList_) {
|
||||
return;
|
||||
}
|
||||
Rect rect = GetAllChildRelativeRect();
|
||||
int16_t top = rect.GetTop();
|
||||
int16_t bottom = rect.GetBottom();
|
||||
int16_t scrollHeight = GetHeight();
|
||||
int16_t left = rect.GetLeft();
|
||||
int16_t right = rect.GetRight();
|
||||
int16_t scrollWidth = GetWidth();
|
||||
if ((direction_ == VERTICAL) || (direction_ == HORIZONTAL_AND_VERTICAL)) {
|
||||
if (top > scrollBlankSize_) {
|
||||
if ((dragDistanceY + top) > (scrollBlankSize_ + reboundSize_)) {
|
||||
dragDistanceY = 0;
|
||||
}
|
||||
dragDistanceY += scrollBlankSize_ - (top + dragDistanceY);
|
||||
}
|
||||
if (bottom < (scrollHeight - scrollBlankSize_ - 1)) {
|
||||
if ((dragDistanceY + bottom) < (scrollHeight - scrollBlankSize_ - reboundSize_ - 1)) {
|
||||
dragDistanceY = 0;
|
||||
}
|
||||
dragDistanceY += scrollHeight - scrollBlankSize_ - 1 - (bottom + dragDistanceY);
|
||||
}
|
||||
} else {
|
||||
if (left > scrollBlankSize_) {
|
||||
if ((dragDistanceX + left) > (scrollBlankSize_ + reboundSize_)) {
|
||||
dragDistanceX = 0;
|
||||
}
|
||||
dragDistanceX += scrollBlankSize_ - (left + dragDistanceX);
|
||||
}
|
||||
if (right < (scrollWidth - scrollBlankSize_ - 1)) {
|
||||
if ((dragDistanceX + right) < (scrollWidth - scrollBlankSize_ - reboundSize_ - 1)) {
|
||||
dragDistanceX = 0;
|
||||
}
|
||||
dragDistanceX += scrollWidth - scrollBlankSize_ - 1 - (right + dragDistanceX);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_MOTOR
|
||||
void UIList::SetMotorType(MotorType motorType)
|
||||
{
|
||||
motorType_ = motorType;
|
||||
}
|
||||
#endif
|
||||
} // namespace OHOS
|
||||
Executable
+462
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_picker.h"
|
||||
#include "draw/draw_line.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
class PickerListScrollListener : public ListScrollListener {
|
||||
public:
|
||||
PickerListScrollListener(UIPicker* picker, UIList* list)
|
||||
: listView_(list), pickerView_(picker), selectView_(nullptr), lastSelectView_(nullptr),
|
||||
selectIndex_(0), isInitted_(false){}
|
||||
|
||||
virtual ~PickerListScrollListener() {}
|
||||
|
||||
void OnItemSelected(int16_t index, UIView* view) override
|
||||
{
|
||||
if (!isInitted_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((lastSelectView_ != nullptr) && (listView_ != nullptr) && (pickerView_ != nullptr) && (view != nullptr)) {
|
||||
lastSelectView_->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetBackgroundTextColor().full);
|
||||
if (pickerView_->backgroundFontName_ == nullptr) {
|
||||
static_cast<UILabel*>(lastSelectView_)->SetFontId(pickerView_->backgroundFontId_);
|
||||
} else {
|
||||
static_cast<UILabel*>(lastSelectView_)
|
||||
->SetFont(pickerView_->backgroundFontName_, pickerView_->backgroundFontSize_);
|
||||
}
|
||||
view->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetHighlightTextColor().full);
|
||||
if (pickerView_->highlightFontName_ == nullptr) {
|
||||
static_cast<UILabel*>(view)->SetFontId(pickerView_->highlightFontId_);
|
||||
} else {
|
||||
static_cast<UILabel*>(view)
|
||||
->SetFont(pickerView_->highlightFontName_, pickerView_->highlightFontSize_);
|
||||
}
|
||||
lastSelectView_ = view;
|
||||
selectIndex_ = index;
|
||||
listView_->Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void OnScrollEnd(int16_t index, UIView* view) override
|
||||
{
|
||||
if ((view == nullptr) || (listView_ == nullptr) || (pickerView_ == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (lastSelectView_ != nullptr) {
|
||||
lastSelectView_->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetBackgroundTextColor().full);
|
||||
if (pickerView_->backgroundFontName_ == nullptr) {
|
||||
static_cast<UILabel*>(lastSelectView_)->SetFontId(pickerView_->backgroundFontId_);
|
||||
} else {
|
||||
static_cast<UILabel*>(lastSelectView_)
|
||||
->SetFont(pickerView_->backgroundFontName_, pickerView_->backgroundFontSize_);
|
||||
}
|
||||
lastSelectView_ = view;
|
||||
}
|
||||
|
||||
view->SetStyle(STYLE_TEXT_COLOR, pickerView_->GetHighlightTextColor().full);
|
||||
if (pickerView_->highlightFontName_ == nullptr) {
|
||||
static_cast<UILabel*>(view)->SetFontId(pickerView_->highlightFontId_);
|
||||
} else {
|
||||
static_cast<UILabel*>(view)
|
||||
->SetFont(pickerView_->highlightFontName_, pickerView_->highlightFontSize_);
|
||||
}
|
||||
|
||||
listView_->Invalidate();
|
||||
selectView_ = view;
|
||||
selectIndex_ = index;
|
||||
|
||||
if (pickerView_->pickerListener_) {
|
||||
pickerView_->pickerListener_->OnPickerStoped(*pickerView_);
|
||||
}
|
||||
}
|
||||
|
||||
void SetSelectView(UIView* view)
|
||||
{
|
||||
selectView_ = view;
|
||||
lastSelectView_ = view;
|
||||
}
|
||||
|
||||
const UIView* GetSelectView() const
|
||||
{
|
||||
return selectView_;
|
||||
}
|
||||
|
||||
void SetSelectIndex(uint16_t index)
|
||||
{
|
||||
selectIndex_ = index;
|
||||
}
|
||||
|
||||
uint16_t GetSelectIndex() const
|
||||
{
|
||||
return selectIndex_;
|
||||
}
|
||||
|
||||
void SetInitStatus(bool status)
|
||||
{
|
||||
isInitted_ = status;
|
||||
}
|
||||
|
||||
private:
|
||||
UIList* listView_;
|
||||
UIPicker* pickerView_;
|
||||
UIView* selectView_;
|
||||
UIView* lastSelectView_;
|
||||
uint16_t selectIndex_;
|
||||
bool isInitted_;
|
||||
};
|
||||
|
||||
UIPicker::UIPicker()
|
||||
: isWidthSet_(false),
|
||||
isHeightSet_(false),
|
||||
textAdapter_(nullptr),
|
||||
maxCount_(0),
|
||||
setSelectedIndex_(0),
|
||||
backgroundFontSize_(0),
|
||||
highlightFontSize_(0),
|
||||
backgroundFontName_(nullptr),
|
||||
highlightFontName_(nullptr),
|
||||
itemsWidth_(0),
|
||||
itemsHeight_(0),
|
||||
rangeValue_(nullptr),
|
||||
rangeValueCount_(0),
|
||||
startValue_(0),
|
||||
endValue_(0),
|
||||
isSetAdaptered_(false),
|
||||
pickerListener_(nullptr)
|
||||
{
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
if (theme != nullptr) {
|
||||
style_ = &(theme->GetPickerBackgroundStyle());
|
||||
} else {
|
||||
style_ = &(StyleDefault::GetPickerBackgroundStyle());
|
||||
}
|
||||
backgroundFontId_ = style_->font_;
|
||||
backgroundColor_ = style_->textColor_;
|
||||
direct_ = UITextLanguageDirect::TEXT_DIRECT_LTR;
|
||||
|
||||
if (theme != nullptr) {
|
||||
style_ = &(theme->GetPickerHighlightStyle());
|
||||
} else {
|
||||
style_ = &(StyleDefault::GetPickerHighlightStyle());
|
||||
}
|
||||
highlightFontId_ = style_->font_;
|
||||
highlightColor_ = style_->textColor_;
|
||||
|
||||
list_.SetThrowDrag(true);
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
list_.rotateFactor_ = 5; // 5: need to fit device to change
|
||||
list_.rotateThreshold_ = 20; // 20: which means 20% of half view size
|
||||
#endif
|
||||
#if ENABLE_MOTOR
|
||||
list_.SetMotorType(MotorType::MOTOR_TYPE_TWO);
|
||||
#endif
|
||||
list_.SetLoopState(false);
|
||||
list_.EnableAutoAlign(true);
|
||||
list_.SetIntercept(false);
|
||||
PickerListScrollListener* listener = new PickerListScrollListener(this, &list_);
|
||||
list_.SetScrollStateListener(listener);
|
||||
listListener_ = static_cast<void*>(listener);
|
||||
Add(&list_);
|
||||
}
|
||||
|
||||
UIPicker::~UIPicker()
|
||||
{
|
||||
ClearValues();
|
||||
Remove(&list_);
|
||||
if (listListener_ != nullptr) {
|
||||
delete static_cast<PickerListScrollListener *>(listListener_);
|
||||
listListener_ = nullptr;
|
||||
}
|
||||
|
||||
if (backgroundFontName_ != nullptr) {
|
||||
UIFree(backgroundFontName_);
|
||||
backgroundFontName_ = nullptr;
|
||||
}
|
||||
|
||||
if (highlightFontName_ != nullptr) {
|
||||
UIFree(highlightFontName_);
|
||||
highlightFontName_ = nullptr;
|
||||
}
|
||||
|
||||
if (textAdapter_ != nullptr) {
|
||||
delete textAdapter_;
|
||||
textAdapter_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool UIPicker::SetValues(int16_t start, int16_t end)
|
||||
{
|
||||
if (start > end) {
|
||||
return false;
|
||||
}
|
||||
|
||||
startValue_ = start;
|
||||
endValue_ = end;
|
||||
return RefreshValues(start, end);
|
||||
}
|
||||
|
||||
bool UIPicker::SetValues(const char* value[], uint16_t count)
|
||||
{
|
||||
if (value == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
rangeValue_ = value;
|
||||
rangeValueCount_ = count;
|
||||
return RefreshValues(value, count);
|
||||
}
|
||||
|
||||
void UIPicker::Refresh()
|
||||
{
|
||||
if (rangeValue_) {
|
||||
RefreshValues(rangeValue_, rangeValueCount_);
|
||||
} else if ((startValue_ != 0) || (endValue_ != 0)) {
|
||||
RefreshValues(startValue_, endValue_);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIPicker::RefreshValues(int16_t start, int16_t end)
|
||||
{
|
||||
if (!isWidthSet_ || !isHeightSet_ || !itemsHeight_ || ((start == 0) && (end == 0))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClearList();
|
||||
InitTextAdapter();
|
||||
textAdapter_->SetData(start, end);
|
||||
maxCount_ = end - start + 1;
|
||||
RefreshList();
|
||||
if (setSelectedIndex_) {
|
||||
RefreshSelected(setSelectedIndex_);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIPicker::RefreshValues(const char* value[], uint16_t count)
|
||||
{
|
||||
if (value == nullptr || !isWidthSet_ || !isHeightSet_ || !itemsHeight_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ClearList();
|
||||
for (uint16_t i = 0; i < count; i++) {
|
||||
dataList_.PushBack(value[i]);
|
||||
}
|
||||
InitTextAdapter();
|
||||
textAdapter_->SetData(&dataList_);
|
||||
maxCount_ = count;
|
||||
RefreshList();
|
||||
if (setSelectedIndex_) {
|
||||
RefreshSelected(setSelectedIndex_);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIPicker::RefreshList()
|
||||
{
|
||||
int16_t height = GetHeight();
|
||||
itemsWidth_ = GetWidth();
|
||||
textAdapter_->SetWidth(itemsWidth_);
|
||||
textAdapter_->SetHeight(itemsHeight_);
|
||||
textAdapter_->SetLineBreakMode(UILabel::LINE_BREAK_CLIP);
|
||||
if (backgroundFontName_ == nullptr) {
|
||||
textAdapter_->SetFontId(backgroundFontId_);
|
||||
} else {
|
||||
textAdapter_->SetFont(backgroundFontName_, backgroundFontSize_);
|
||||
}
|
||||
textAdapter_->GetStyle().textColor_ = backgroundColor_;
|
||||
textAdapter_->SetDirect(direct_);
|
||||
list_.SetHeight(height);
|
||||
list_.SetWidth(itemsWidth_);
|
||||
list_.SetPosition(GetWidth() / 2 - list_.GetWidth() / 2, 0); // 2: half
|
||||
list_.SetScrollBlankSize((height - itemsHeight_) / 2); // 2: half
|
||||
list_.SetSelectPosition(height / 2); // 2: half
|
||||
list_.SetStyle(*style_);
|
||||
list_.SetStyle(STYLE_BORDER_WIDTH, 0);
|
||||
list_.SetStyle(STYLE_BACKGROUND_OPA, 0);
|
||||
if (!isSetAdaptered_) {
|
||||
list_.SetAdapter(textAdapter_);
|
||||
isSetAdaptered_ = true;
|
||||
}
|
||||
|
||||
list_.RefreshList();
|
||||
RefreshSelected(0);
|
||||
}
|
||||
|
||||
void UIPicker::ClearValues()
|
||||
{
|
||||
rangeValue_ = nullptr;
|
||||
rangeValueCount_ = 0;
|
||||
setSelectedIndex_ = 0;
|
||||
ClearList();
|
||||
}
|
||||
|
||||
void UIPicker::ClearList()
|
||||
{
|
||||
maxCount_ = 0;
|
||||
itemsWidth_ = 0;
|
||||
if (listListener_) {
|
||||
PickerListScrollListener* listListener = static_cast<PickerListScrollListener*>(listListener_);
|
||||
listListener->SetSelectView(nullptr);
|
||||
listListener->SetSelectIndex(0);
|
||||
listListener->SetInitStatus(false);
|
||||
}
|
||||
dataList_.Clear();
|
||||
}
|
||||
|
||||
bool UIPicker::SetSelected(uint16_t index)
|
||||
{
|
||||
setSelectedIndex_ = index;
|
||||
return RefreshSelected(index);
|
||||
}
|
||||
|
||||
bool UIPicker::RefreshSelected(uint16_t index)
|
||||
{
|
||||
if (itemsHeight_ && (maxCount_ > index) && (list_.GetChildrenHead() != nullptr) && isWidthSet_ && isHeightSet_) {
|
||||
PickerListScrollListener* listListener = static_cast<PickerListScrollListener*>(listListener_);
|
||||
listListener->SetInitStatus(false);
|
||||
// 2: half
|
||||
int16_t yOffset = (list_.GetHeight() - itemsHeight_) / 2 -
|
||||
itemsHeight_ * (index - list_.GetChildrenHead()->GetViewIndex());
|
||||
list_.SetScrollStateListener(nullptr);
|
||||
list_.ScrollBy(yOffset - list_.GetChildrenHead()->GetY());
|
||||
list_.SetScrollStateListener(listListener);
|
||||
listListener->SetScrollState(ListScrollListener::SCROLL_STATE_STOP);
|
||||
UIView* childView = static_cast<UIView*>(list_.GetChildrenHead());
|
||||
uint16_t lastSelectIndex = listListener->GetSelectIndex();
|
||||
|
||||
int16_t viewIndex;
|
||||
while (childView != nullptr) {
|
||||
viewIndex = childView->GetViewIndex();
|
||||
if (viewIndex == lastSelectIndex) {
|
||||
childView->SetStyle(STYLE_TEXT_COLOR, GetBackgroundTextColor().full);
|
||||
if (backgroundFontName_ == nullptr) {
|
||||
static_cast<UILabel*>(childView)->SetFontId(backgroundFontId_);
|
||||
} else {
|
||||
static_cast<UILabel*>(childView)->SetFont(backgroundFontName_, backgroundFontSize_);
|
||||
}
|
||||
}
|
||||
if (viewIndex == index) {
|
||||
childView->SetStyle(STYLE_TEXT_COLOR, GetHighlightTextColor().full);
|
||||
if (highlightFontName_ == nullptr) {
|
||||
static_cast<UILabel*>(childView)->SetFontId(highlightFontId_);
|
||||
} else {
|
||||
static_cast<UILabel*>(childView)->SetFont(highlightFontName_, highlightFontSize_);
|
||||
}
|
||||
listListener->SetSelectView(childView);
|
||||
listListener->SetSelectIndex(index);
|
||||
listListener->SetInitStatus(true);
|
||||
}
|
||||
childView = childView->GetNextSibling();
|
||||
}
|
||||
list_.Invalidate();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t UIPicker::GetSelected() const
|
||||
{
|
||||
PickerListScrollListener* listListener = static_cast<PickerListScrollListener*>(listListener_);
|
||||
return listListener->GetSelectIndex();
|
||||
}
|
||||
|
||||
void UIPicker::SetFontId(uint8_t backgroundFontId, uint8_t highlightFontId)
|
||||
{
|
||||
backgroundFontId_ = backgroundFontId;
|
||||
if (backgroundFontName_ != nullptr) {
|
||||
UIFree(backgroundFontName_);
|
||||
backgroundFontName_ = nullptr;
|
||||
}
|
||||
|
||||
highlightFontId_ = highlightFontId;
|
||||
if (highlightFontName_ != nullptr) {
|
||||
UIFree(highlightFontName_);
|
||||
highlightFontName_ = nullptr;
|
||||
}
|
||||
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void UIPicker::SetBackgroundFont(const char* name, uint8_t size)
|
||||
{
|
||||
Text::SetFont(name, size, backgroundFontName_, backgroundFontSize_);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void UIPicker::SetHighlightFont(const char* name, uint8_t size)
|
||||
{
|
||||
Text::SetFont(name, size, highlightFontName_, highlightFontSize_);
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void UIPicker::SetTextColor(ColorType backgroundColor, ColorType highlightColor)
|
||||
{
|
||||
backgroundColor_ = backgroundColor;
|
||||
highlightColor_ = highlightColor;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void UIPicker::SetItemHeight(int16_t height)
|
||||
{
|
||||
if (height > 0) {
|
||||
itemsHeight_ = height;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void UIPicker::SetWidth(int16_t width)
|
||||
{
|
||||
if (width > 0) {
|
||||
UIView::SetWidth(width);
|
||||
isWidthSet_ = true;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void UIPicker::SetHeight(int16_t height)
|
||||
{
|
||||
if (height > 0) {
|
||||
UIView::SetHeight(height);
|
||||
isHeightSet_ = true;
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
|
||||
void UIPicker::SetLoopState(bool state)
|
||||
{
|
||||
list_.SetLoopState(state);
|
||||
}
|
||||
|
||||
void UIPicker::SetDirect(UITextLanguageDirect direct)
|
||||
{
|
||||
direct_ = direct;
|
||||
Refresh();
|
||||
}
|
||||
|
||||
void UIPicker::SetTextFormatter(TextFormatter* formatter)
|
||||
{
|
||||
InitTextAdapter();
|
||||
textAdapter_->SetTextFormatter(formatter);
|
||||
Refresh();
|
||||
}
|
||||
}
|
||||
Executable
+215
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_qrcode.h"
|
||||
#include "QrCode.hpp"
|
||||
#include "graphic_log.h"
|
||||
#include "securec.h"
|
||||
|
||||
using qrcodegen::QrCode;
|
||||
namespace OHOS {
|
||||
UIQrcode::UIQrcode()
|
||||
: width_(0), needDraw_(false), backgroundColor_(Color::White()), qrColor_(Color::Black()), qrcodeVal_(nullptr)
|
||||
{
|
||||
style_ = &(StyleDefault::GetBackgroundTransparentStyle());
|
||||
imageInfo_ = {{0}};
|
||||
}
|
||||
|
||||
UIQrcode::~UIQrcode()
|
||||
{
|
||||
if (qrcodeVal_ != nullptr) {
|
||||
UIFree(qrcodeVal_);
|
||||
qrcodeVal_ = nullptr;
|
||||
}
|
||||
|
||||
if (imageInfo_.data != nullptr) {
|
||||
ImageCacheFree(imageInfo_);
|
||||
imageInfo_.data = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::SetQrcodeInfo(const char* val, ColorType backgroundColor, ColorType qrColor)
|
||||
{
|
||||
if (val == nullptr) {
|
||||
GRAPHIC_LOGE("UIQrcode::SetQrcodeInfo val is null!\n");
|
||||
return;
|
||||
}
|
||||
uint32_t length = static_cast<uint32_t>(strlen(val));
|
||||
if ((length > QRCODE_VAL_MAX) || (length == 0)) {
|
||||
GRAPHIC_LOGE("UIQrcode::SetQrcodeInfo val length is equal 0 or greater than QRCODE_VAL_MAX!\n");
|
||||
return;
|
||||
}
|
||||
backgroundColor_ = backgroundColor;
|
||||
qrColor_ = qrColor;
|
||||
SetQrcodeVal(val, length);
|
||||
RefreshQrcode();
|
||||
}
|
||||
|
||||
void UIQrcode::RefreshQrcode()
|
||||
{
|
||||
Invalidate();
|
||||
if (!needDraw_) {
|
||||
needDraw_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::SetWidth(int16_t width)
|
||||
{
|
||||
if (GetWidth() != width) {
|
||||
UIView::SetWidth(width);
|
||||
RefreshQrcode();
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::SetHeight(int16_t height)
|
||||
{
|
||||
if (GetHeight() != height) {
|
||||
UIView::SetHeight(height);
|
||||
RefreshQrcode();
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::ReMeasure()
|
||||
{
|
||||
if (!needDraw_) {
|
||||
return;
|
||||
}
|
||||
needDraw_ = false;
|
||||
if (qrcodeVal_ == nullptr) {
|
||||
GRAPHIC_LOGE("UIQrcode::ReMeasure qrcodeVal_ is null!\n");
|
||||
return;
|
||||
}
|
||||
QrCode qr = QrCode::encodeText(qrcodeVal_, QrCode::Ecc::LOW);
|
||||
SetImageInfo(qr);
|
||||
SetSrc(&imageInfo_);
|
||||
}
|
||||
|
||||
void UIQrcode::SetQrcodeVal(const char* qrcodeVal, uint32_t length)
|
||||
{
|
||||
if (qrcodeVal_ != nullptr) {
|
||||
UIFree(qrcodeVal_);
|
||||
qrcodeVal_ = nullptr;
|
||||
}
|
||||
|
||||
uint32_t len = static_cast<uint32_t>(length + 1);
|
||||
qrcodeVal_ = static_cast<char*>(UIMalloc(len));
|
||||
if (qrcodeVal_ != nullptr) {
|
||||
if (memcpy_s(qrcodeVal_, len, qrcodeVal, len) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(qrcodeVal_));
|
||||
qrcodeVal_ = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::SetImageInfo(qrcodegen::QrCode& qrcode)
|
||||
{
|
||||
int16_t width = GetWidth();
|
||||
int16_t height = GetHeight();
|
||||
width_ = (width >= height) ? height : width;
|
||||
if (width_ < qrcode.getSize()) {
|
||||
GRAPHIC_LOGE("UIQrcode::SetImageInfo width is less than the minimum qrcode width!\n");
|
||||
return;
|
||||
}
|
||||
imageInfo_.header.width = width;
|
||||
imageInfo_.header.height = height;
|
||||
imageInfo_.header.colorMode = ARGB8888;
|
||||
imageInfo_.dataSize = imageInfo_.header.width * imageInfo_.header.height * QRCODE_FACTOR_NUM;
|
||||
if (imageInfo_.data != nullptr) {
|
||||
ImageCacheFree(imageInfo_);
|
||||
imageInfo_.data = nullptr;
|
||||
}
|
||||
imageInfo_.data = reinterpret_cast<uint8_t*>(ImageCacheMalloc(imageInfo_));
|
||||
if (imageInfo_.data == nullptr) {
|
||||
GRAPHIC_LOGE("UIQrcode::SetImageInfo imageInfo_.data is null!\n");
|
||||
return;
|
||||
}
|
||||
GenerateQrCode(qrcode);
|
||||
}
|
||||
|
||||
void UIQrcode::GenerateQrCode(qrcodegen::QrCode& qrcode)
|
||||
{
|
||||
FillQrCodeBackgroundColor();
|
||||
|
||||
FillQrCodeColor(qrcode);
|
||||
}
|
||||
|
||||
void UIQrcode::FillQrCodeColor(qrcodegen::QrCode& qrcode)
|
||||
{
|
||||
int32_t qrWidth = qrcode.getSize();
|
||||
if (qrWidth <= 0) {
|
||||
GRAPHIC_LOGE("UIQrcode::FillQrCodeColor generated qrcode size is less or equal 0!\n");
|
||||
return;
|
||||
}
|
||||
int16_t width = imageInfo_.header.width;
|
||||
int16_t height = imageInfo_.header.height;
|
||||
uint16_t outFilePixelPrescaler = width_ / qrWidth;
|
||||
int32_t offsetX = (width - outFilePixelPrescaler * qrWidth) / 2; // 2: half
|
||||
int32_t offsetY = (height - outFilePixelPrescaler * qrWidth) / 2; // 2: half
|
||||
|
||||
uint8_t* destData = nullptr;
|
||||
int64_t oneLinePixel = width * QRCODE_FACTOR_NUM * outFilePixelPrescaler;
|
||||
int64_t oneLineOffsetPixel = (offsetY * width * QRCODE_FACTOR_NUM) + (offsetX * QRCODE_FACTOR_NUM);
|
||||
for (int32_t y = 0; y < qrWidth; ++y) {
|
||||
destData = const_cast<uint8_t*>(imageInfo_.data) + (oneLinePixel * y) + oneLineOffsetPixel;
|
||||
for (int32_t x = 0; x < qrWidth; ++x) {
|
||||
if (qrcode.getModule(x, y)) {
|
||||
GetDestData(destData, outFilePixelPrescaler);
|
||||
}
|
||||
destData += QRCODE_FACTOR_NUM * outFilePixelPrescaler;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::FillQrCodeBackgroundColor()
|
||||
{
|
||||
uint8_t* initColorData = const_cast<uint8_t*>(imageInfo_.data);
|
||||
*(initColorData + 0) = backgroundColor_.blue; // 0: B channel
|
||||
*(initColorData + 1) = backgroundColor_.green; // 1: G channel
|
||||
*(initColorData + 2) = backgroundColor_.red; // 2: R channel
|
||||
*(initColorData + 3) = OPA_OPAQUE; // 3: Alpha channel
|
||||
|
||||
uint8_t* tempColorData = initColorData;
|
||||
for (int16_t col = 1; col < imageInfo_.header.width; ++col) {
|
||||
initColorData += QRCODE_FACTOR_NUM;
|
||||
if (memcpy_s(initColorData, QRCODE_FACTOR_NUM, tempColorData, QRCODE_FACTOR_NUM) != EOK) {
|
||||
GRAPHIC_LOGE("UIQrcode::FillQrCodeBackgroundColor memcpy_s failed!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
initColorData = tempColorData;
|
||||
int32_t deltaWidth = QRCODE_FACTOR_NUM * imageInfo_.header.width;
|
||||
for (int16_t row = 1; row < imageInfo_.header.height; ++row) {
|
||||
initColorData += deltaWidth;
|
||||
if (memcpy_s(initColorData, deltaWidth, tempColorData, deltaWidth) != EOK) {
|
||||
GRAPHIC_LOGE("UIQrcode::FillQrCodeBackgroundColor memcpy_s failed!\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIQrcode::GetDestData(uint8_t* destData, int32_t outFilePixelPrescaler)
|
||||
{
|
||||
for (int32_t x = 0; x < outFilePixelPrescaler; ++x) {
|
||||
uint8_t* tempData = destData + imageInfo_.header.width * QRCODE_FACTOR_NUM * x;
|
||||
for (int32_t y = 0; y < outFilePixelPrescaler; ++y) {
|
||||
*(tempData + 0) = qrColor_.blue; // 0: B channel
|
||||
*(tempData + 1) = qrColor_.green; // 1: G channel
|
||||
*(tempData + 2) = qrColor_.red; // 2: R channel
|
||||
*(tempData + 3) = OPA_OPAQUE; // 3: Alpha channel
|
||||
tempData += QRCODE_FACTOR_NUM;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+166
@@ -0,0 +1,166 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_radio_button.h"
|
||||
#include "common/image.h"
|
||||
#include "components/root_view.h"
|
||||
#include "components/ui_view_group.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIRadioButton::UIRadioButton() : name_(nullptr), width_(DEFAULT_HOT_WIDTH), height_(DEFAULT_HOT_HEIGHT),
|
||||
radiusBig_(DEFAULT_RADIUS_BIG), radiusSmall_(DEFAULT_RADIUS_SMALL),
|
||||
lineWidth_(DEFAULT_LINE_WIDTH)
|
||||
{
|
||||
image_[UNSELECTED].SetSrc("");
|
||||
image_[SELECTED].SetSrc("");
|
||||
Resize(width_, height_);
|
||||
}
|
||||
|
||||
UIRadioButton::UIRadioButton(const char* name) : name_(nullptr), width_(DEFAULT_HOT_WIDTH),
|
||||
height_(DEFAULT_HOT_HEIGHT), radiusBig_(DEFAULT_RADIUS_BIG),
|
||||
radiusSmall_(DEFAULT_RADIUS_SMALL), lineWidth_(DEFAULT_LINE_WIDTH)
|
||||
{
|
||||
SetName(name);
|
||||
image_[UNSELECTED].SetSrc("");
|
||||
image_[SELECTED].SetSrc("");
|
||||
Resize(width_, height_);
|
||||
}
|
||||
|
||||
bool UIRadioButton::OnClickEvent(const ClickEvent& event)
|
||||
{
|
||||
SetState(SELECTED);
|
||||
Invalidate();
|
||||
UIView* view = this;
|
||||
while ((view != nullptr) && (view->GetParent() != nullptr)) {
|
||||
view = view->GetParent();
|
||||
}
|
||||
FindRadioButtonAndChangeState(view);
|
||||
return UIView::OnClickEvent(event);
|
||||
}
|
||||
|
||||
void UIRadioButton::CalculateSize()
|
||||
{
|
||||
int16_t width = GetWidth();
|
||||
int16_t height = GetHeight();
|
||||
if ((width_ == width) && (height_ == height)) {
|
||||
return;
|
||||
}
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
int16_t minValue = (width_ > height_) ? height_ : width_;
|
||||
radiusBig_ = DEFAULT_RADIUS_BIG * minValue / DEFAULT_HOT_WIDTH;
|
||||
radiusSmall_ = DEFAULT_RADIUS_SMALL * minValue / DEFAULT_HOT_WIDTH;
|
||||
if (minValue >= DEFAULT_HOT_WIDTH) {
|
||||
lineWidth_ = DEFAULT_LINE_WIDTH * minValue / DEFAULT_HOT_WIDTH;
|
||||
}
|
||||
}
|
||||
|
||||
void UIRadioButton::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) {
|
||||
UICheckBox::OnDraw(invalidatedArea);
|
||||
} else {
|
||||
CalculateSize();
|
||||
DrawRect::Draw(GetRect(), invalidatedArea, *style_, opaScale_);
|
||||
Rect contentRect = GetContentRect();
|
||||
int16_t dx = width_ >> 1;
|
||||
int16_t dy = height_ >> 1;
|
||||
int16_t x = contentRect.GetX() + dx;
|
||||
int16_t y = contentRect.GetY() + dy;
|
||||
ArcInfo arcInfoBig = { { x, y }, { 0 }, radiusBig_, 0, CIRCLE_IN_DEGREE, nullptr };
|
||||
ArcInfo arcInfoSmall = { { x, y }, { 0 }, radiusSmall_, 0, CIRCLE_IN_DEGREE, nullptr };
|
||||
Rect trunc = invalidatedArea;
|
||||
bool isIntersect = trunc.Intersect(trunc, contentRect);
|
||||
switch (state_) {
|
||||
case SELECTED: {
|
||||
Style styleSelect = StyleDefault::GetBackgroundTransparentStyle();
|
||||
styleSelect.lineWidth_ = arcInfoBig.radius;
|
||||
styleSelect.lineColor_ = Color::GetColorFromRGB(0x1F, 0x71, 0xFF);
|
||||
if (isIntersect) {
|
||||
DrawArc::GetInstance()->Draw(arcInfoBig, trunc, styleSelect, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
styleSelect.lineWidth_ = arcInfoSmall.radius;
|
||||
styleSelect.lineColor_ = Color::White();
|
||||
if (isIntersect) {
|
||||
DrawArc::GetInstance()->Draw(arcInfoSmall, trunc, styleSelect, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UNSELECTED: {
|
||||
Style styleUnSelect = StyleDefault::GetBackgroundTransparentStyle();
|
||||
styleUnSelect.lineColor_ = Color::White();
|
||||
styleUnSelect.lineWidth_ = lineWidth_;
|
||||
if (isIntersect) {
|
||||
// 0xa8 : opacity of drawing unselected button arc edge.
|
||||
DrawArc::GetInstance()->Draw(arcInfoBig, trunc, styleUnSelect, 0xa8, CapType::CAP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIRadioButton::SetName(const char* name)
|
||||
{
|
||||
if (name == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (name_ != nullptr) {
|
||||
UIFree(name_);
|
||||
name_ = nullptr;
|
||||
}
|
||||
uint32_t nameLen = static_cast<uint32_t>(strlen(name) + 1);
|
||||
if (nameLen > MAX_TEXT_LENGTH) {
|
||||
return;
|
||||
}
|
||||
name_ = static_cast<char*>(UIMalloc(nameLen));
|
||||
if (name_ != nullptr) {
|
||||
if (memcpy_s(name_, nameLen, name, nameLen) != EOK) {
|
||||
UIFree(name_);
|
||||
name_ = nullptr;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIRadioButton::FindRadioButtonAndChangeState(UIView* view)
|
||||
{
|
||||
if ((view == nullptr) || (name_ == nullptr)) {
|
||||
return;
|
||||
}
|
||||
if (view->IsViewGroup()) {
|
||||
UIView* childView = static_cast<UIViewGroup*>(view)->GetChildrenHead();
|
||||
while (childView != nullptr) {
|
||||
FindRadioButtonAndChangeState(childView);
|
||||
childView = childView->GetNextSibling();
|
||||
}
|
||||
}
|
||||
if ((view == this) || (view->GetViewType() != UI_RADIO_BUTTON)) {
|
||||
return;
|
||||
}
|
||||
UIRadioButton* uiRadioButtonInfo = static_cast<UIRadioButton*>(view);
|
||||
if ((uiRadioButtonInfo->GetName() != nullptr) && (strcmp(uiRadioButtonInfo->GetName(), name_) == 0)) {
|
||||
uiRadioButtonInfo->SetState(UNSELECTED);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+63
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_repeat_button.h"
|
||||
#include "components/ui_button.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIRepeatButton* UIRepeatButton::repeatButton_ = nullptr;
|
||||
|
||||
/** default tick interval 200ms. */
|
||||
UIRepeatButton::UIRepeatButton() : ticksInterval_(200), event_({ 0, 0 }),
|
||||
longPressed_(false), timerRepeatID_(0) {}
|
||||
|
||||
UIRepeatButton::~UIRepeatButton() {}
|
||||
|
||||
void UIRepeatButton::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
UIButton::OnDraw(invalidatedArea);
|
||||
}
|
||||
|
||||
bool UIRepeatButton::OnReleaseEvent(const ReleaseEvent& event)
|
||||
{
|
||||
if (longPressed_ && (timerRepeatID_ != 0)) {
|
||||
longPressed_ = false;
|
||||
}
|
||||
return UIButton::OnReleaseEvent(event);
|
||||
}
|
||||
|
||||
bool UIRepeatButton::OnClickEvent(const ClickEvent& event)
|
||||
{
|
||||
SetEvent(event);
|
||||
return UIButton::OnClickEvent(event);
|
||||
}
|
||||
|
||||
void UIRepeatButton::HandleTickEvent()
|
||||
{
|
||||
UIButton::OnClickEvent(event_);
|
||||
}
|
||||
|
||||
bool UIRepeatButton::OnLongPressEvent(const LongPressEvent& event)
|
||||
{
|
||||
longPressed_ = true;
|
||||
repeatButton_ = this;
|
||||
return UIButton::OnLongPressEvent(event);
|
||||
}
|
||||
|
||||
void UIRepeatButton::SetEvent(const ClickEvent& event)
|
||||
{
|
||||
event_ = event;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+417
@@ -0,0 +1,417 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_scroll_view.h"
|
||||
#include "dock/focus_manager.h"
|
||||
#include "draw/draw_rect.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIScrollView::UIScrollView()
|
||||
: xSliderPos_({0, 0}),
|
||||
ySliderPos_({0, 0}),
|
||||
scrollBarWidth_(DEFAULT_BAR_WIDTH),
|
||||
xScrollable_(true),
|
||||
yScrollable_(true),
|
||||
minScrollBarLen_(DEFAULT_MIN_BAR_LEN),
|
||||
scrollListener_(nullptr)
|
||||
{
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
rotateFactor_ = 1;
|
||||
rotateThreshold_ = 4; // 4: which means 25% of half view size
|
||||
#endif
|
||||
direction_ = HORIZONTAL_AND_VERTICAL;
|
||||
xSlider_.SetVisible(false);
|
||||
ySlider_.SetVisible(false);
|
||||
xSlider_.SetStyle(StyleDefault::GetBrightStyle());
|
||||
ySlider_.SetStyle(StyleDefault::GetBrightStyle());
|
||||
}
|
||||
|
||||
void UIScrollView::OnPostDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
if (!xSlider_.IsVisible() && !ySlider_.IsVisible()) {
|
||||
return;
|
||||
}
|
||||
Rect scrollRect = GetRect();
|
||||
if (xSlider_.IsVisible()) {
|
||||
xSlider_.SetPosition(scrollRect.GetX() + xSliderPos_.x, scrollRect.GetY() + xSliderPos_.y);
|
||||
xSlider_.OnDraw(invalidatedArea);
|
||||
}
|
||||
if (ySlider_.IsVisible()) {
|
||||
ySlider_.SetPosition(scrollRect.GetX() + ySliderPos_.x, scrollRect.GetY() + ySliderPos_.y);
|
||||
ySlider_.OnDraw(invalidatedArea);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIScrollView::OnDragEvent(const DragEvent& event)
|
||||
{
|
||||
if (scrollAnimator_.GetState() != Animator::STOP) {
|
||||
UIAbstractScroll::StopAnimator();
|
||||
}
|
||||
Drag(event);
|
||||
return UIView::OnDragEvent(event);
|
||||
}
|
||||
|
||||
bool UIScrollView::OnDragEndEvent(const DragEvent& event)
|
||||
{
|
||||
Point last = event.GetPreLastPoint();
|
||||
Point current = event.GetLastPoint();
|
||||
if ((last.x == current.x) && (last.y == current.y)) {
|
||||
last = current;
|
||||
current = event.GetCurrentPos();
|
||||
}
|
||||
|
||||
if (!DragThrowAnimator(current, last)) {
|
||||
if (scrollListener_ && (scrollListener_->GetScrollState() == OnScrollListener::SCROLL_STATE_MOVE)) {
|
||||
scrollListener_->OnScrollEnd();
|
||||
scrollListener_->SetScrollState(OnScrollListener::SCROLL_STATE_STOP);
|
||||
}
|
||||
}
|
||||
return UIView::OnDragEndEvent(event);
|
||||
}
|
||||
|
||||
void UIScrollView::Drag(const DragEvent& event)
|
||||
{
|
||||
int16_t xDistance = event.GetDeltaX();
|
||||
int16_t yDistance = event.GetDeltaY();
|
||||
|
||||
if (xScrollable_ && xDistance != 0) {
|
||||
DragXInner(xDistance);
|
||||
}
|
||||
if (yScrollable_ && yDistance != 0) {
|
||||
DragYInner(yDistance);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIScrollView::OnPressEvent(const PressEvent& event)
|
||||
{
|
||||
StopAnimator();
|
||||
return UIView::OnPressEvent(event);
|
||||
}
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
bool UIScrollView::OnRotateEvent(const RotateEvent& event)
|
||||
{
|
||||
int16_t tmpRotateLen = static_cast<int16_t>(event.GetRotate() * rotateFactor_);
|
||||
int16_t midPointX = static_cast<int16_t>(GetWidth() / 2); // 2 : Get the middle point X coord of the view
|
||||
int16_t midPointY = static_cast<int16_t>(GetHeight() / 2); // 2 : Get the middle point Y coord of the view
|
||||
Point last, current;
|
||||
if (!throwDrag_ || ((MATH_ABS(tmpRotateLen) < (midPointX / rotateThreshold_)) &&
|
||||
(MATH_ABS(tmpRotateLen) < (midPointY / rotateThreshold_)))) {
|
||||
yScrollable_ ? ScrollBy(0, tmpRotateLen) : ScrollBy(tmpRotateLen, 0);
|
||||
if (event.GetRotate() == 0) {
|
||||
DragThrowAnimator(Point {0, 0}, Point {0, 0});
|
||||
}
|
||||
} else {
|
||||
last = Point {midPointX, midPointY};
|
||||
yScrollable_ ? (current = Point {midPointX, static_cast<int16_t>(midPointY + tmpRotateLen)})
|
||||
: (current = Point {static_cast<int16_t>(midPointX + tmpRotateLen), midPointY});
|
||||
DragThrowAnimator(current, last);
|
||||
}
|
||||
#if ENABLE_MOTOR
|
||||
MotorFunc motorFunc = FocusManager::GetInstance()->GetMotorFunc();
|
||||
if (motorFunc != nullptr) {
|
||||
motorFunc(MotorType::MOTOR_TYPE_ONE);
|
||||
}
|
||||
#endif
|
||||
return UIView::OnRotateEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIScrollView::ScrollBy(int16_t xDistance, int16_t yDistance)
|
||||
{
|
||||
if (xScrollable_ && xDistance != 0) {
|
||||
DragXInner(xDistance);
|
||||
}
|
||||
if (yScrollable_ && yDistance != 0) {
|
||||
DragYInner(yDistance);
|
||||
}
|
||||
if ((scrollListener_ != nullptr) && (scrollListener_->GetScrollState() == OnScrollListener::SCROLL_STATE_MOVE)) {
|
||||
scrollListener_->OnScrollEnd();
|
||||
scrollListener_->SetScrollState(OnScrollListener::SCROLL_STATE_STOP);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIScrollView::DragXInner(int16_t distance)
|
||||
{
|
||||
Rect childRect = GetAllChildRelativeRect();
|
||||
int16_t reboundSize = reboundSize_;
|
||||
if (scrollAnimator_.GetState() != Animator::STOP) {
|
||||
reboundSize = 0;
|
||||
}
|
||||
|
||||
if (childRect.GetWidth() <= (GetWidth() - (scrollBlankSize_ << 1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (distance > 0) {
|
||||
if (childRect.GetLeft() > scrollBlankSize_ + reboundSize) {
|
||||
distance = 0;
|
||||
} else if ((childRect.GetLeft() + distance) > scrollBlankSize_ + reboundSize) {
|
||||
distance = scrollBlankSize_ - childRect.GetLeft() + reboundSize;
|
||||
}
|
||||
} else {
|
||||
int16_t childRight = childRect.GetRight();
|
||||
int16_t scrollWidth = GetWidth();
|
||||
if (yScrollable_ && ySlider_.IsVisible()) {
|
||||
if (childRight < scrollWidth - ySlider_.GetWidth() - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = 0;
|
||||
} else if (childRight + distance < scrollWidth - ySlider_.GetWidth() - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = scrollWidth - ySlider_.GetWidth() - (scrollBlankSize_ + reboundSize) - childRight;
|
||||
}
|
||||
} else {
|
||||
if (childRight < scrollWidth - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = 0;
|
||||
} else if (childRight + distance < scrollWidth - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = scrollWidth - (scrollBlankSize_ + reboundSize) - childRight - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MoveOffset(distance, 0);
|
||||
}
|
||||
|
||||
bool UIScrollView::DragYInner(int16_t distance)
|
||||
{
|
||||
Rect childRect = GetAllChildRelativeRect();
|
||||
int16_t reboundSize = reboundSize_;
|
||||
if (scrollAnimator_.GetState() != Animator::STOP) {
|
||||
reboundSize = 0;
|
||||
}
|
||||
|
||||
if (childRect.GetHeight() <= (GetHeight() - (scrollBlankSize_ << 1))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (distance > 0) {
|
||||
if (childRect.GetTop() > scrollBlankSize_ + reboundSize) {
|
||||
distance = 0;
|
||||
} else if ((childRect.GetTop() + distance) > scrollBlankSize_ + reboundSize) {
|
||||
distance = scrollBlankSize_ - childRect.GetTop() + reboundSize;
|
||||
}
|
||||
} else {
|
||||
int16_t childBottom = childRect.GetBottom();
|
||||
int16_t scrollHeight = GetHeight();
|
||||
if (xScrollable_ && xSlider_.IsVisible()) {
|
||||
if (childBottom < scrollHeight - xSlider_.GetHeight() - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = 0;
|
||||
} else if (childBottom + distance <
|
||||
scrollHeight - xSlider_.GetHeight() - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = scrollHeight - xSlider_.GetHeight() - (scrollBlankSize_ + reboundSize) - childBottom;
|
||||
}
|
||||
} else {
|
||||
if (childBottom < scrollHeight - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = 0;
|
||||
} else if (childBottom + distance < scrollHeight - (scrollBlankSize_ + reboundSize)) {
|
||||
distance = scrollHeight - (scrollBlankSize_ + reboundSize) - childBottom - 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MoveOffset(0, distance);
|
||||
}
|
||||
|
||||
bool UIScrollView::MoveOffset(int16_t offsetX, int16_t offsetY)
|
||||
{
|
||||
if ((offsetX != 0) || (offsetY != 0)) {
|
||||
if ((scrollListener_ != nullptr) &&
|
||||
(scrollListener_->GetScrollState() == OnScrollListener::SCROLL_STATE_STOP)) {
|
||||
scrollListener_->OnScrollStart();
|
||||
scrollListener_->SetScrollState(OnScrollListener::SCROLL_STATE_MOVE);
|
||||
}
|
||||
UIAbstractScroll::MoveChildByOffset(offsetX, offsetY);
|
||||
Invalidate();
|
||||
RefreshScrollBarPosition();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIScrollView::RefreshScrollBar()
|
||||
{
|
||||
Rect childRect = GetAllChildRelativeRect();
|
||||
if (xScrollable_ && (childRect.GetWidth() <= GetWidth())) {
|
||||
xSliderPos_.y = GetHeight() - scrollBarWidth_;
|
||||
xSlider_.SetHeight(scrollBarWidth_);
|
||||
// y scroll bar is on, x scroll bar width should be group width - scroll bar width
|
||||
if (yScrollable_) {
|
||||
xSlider_.SetWidth(GetWidth() - scrollBarWidth_);
|
||||
} else {
|
||||
xSlider_.SetWidth(GetWidth());
|
||||
}
|
||||
}
|
||||
|
||||
if (yScrollable_ && (childRect.GetHeight() <= GetHeight())) {
|
||||
ySliderPos_.x = GetWidth() - scrollBarWidth_;
|
||||
ySliderPos_.y = 0;
|
||||
ySlider_.SetWidth(scrollBarWidth_);
|
||||
// x scroll bar is on, y scroll bar height should be group height - scroll bar width
|
||||
if (xScrollable_) {
|
||||
ySlider_.SetHeight(GetHeight() - scrollBarWidth_);
|
||||
} else {
|
||||
ySlider_.SetHeight(GetHeight());
|
||||
}
|
||||
}
|
||||
float multiple;
|
||||
|
||||
// child width is larger than group width, resize the x scroll bar width
|
||||
if (xScrollable_ && (childRect.GetWidth() > GetWidth()) && (childRect.GetWidth() != 0)) {
|
||||
int16_t groupWidth = GetWidth();
|
||||
int16_t xWidth;
|
||||
if (yScrollable_) {
|
||||
multiple = static_cast<float>(groupWidth - scrollBarWidth_) / childRect.GetWidth();
|
||||
xWidth = static_cast<int16_t>((groupWidth - scrollBarWidth_) * multiple);
|
||||
} else {
|
||||
multiple = static_cast<float>(groupWidth) / childRect.GetWidth();
|
||||
xWidth = static_cast<int16_t>(groupWidth * multiple);
|
||||
}
|
||||
if (xWidth < minScrollBarLen_) {
|
||||
xWidth = minScrollBarLen_;
|
||||
}
|
||||
|
||||
xSliderPos_.x = GetXScrollOffset(childRect);
|
||||
xSliderPos_.y = GetHeight() - scrollBarWidth_;
|
||||
xSlider_.SetWidth(xWidth);
|
||||
xSlider_.SetHeight(scrollBarWidth_);
|
||||
}
|
||||
|
||||
// child height is larger than group height, resize the y scroll height
|
||||
if (yScrollable_ && (childRect.GetHeight() > GetHeight()) && (childRect.GetHeight() != 0)) {
|
||||
int16_t groupHeight = GetHeight();
|
||||
int16_t yHeight;
|
||||
if (xScrollable_) {
|
||||
multiple = static_cast<float>(groupHeight - scrollBarWidth_) / childRect.GetHeight();
|
||||
yHeight = static_cast<int16_t>((groupHeight - scrollBarWidth_) * multiple);
|
||||
} else {
|
||||
multiple = static_cast<float>(groupHeight) / childRect.GetHeight();
|
||||
yHeight = static_cast<int16_t>(groupHeight * multiple);
|
||||
}
|
||||
|
||||
// scroll bar may be too small, keep it min size
|
||||
if (yHeight < minScrollBarLen_) {
|
||||
yHeight = minScrollBarLen_;
|
||||
}
|
||||
|
||||
ySliderPos_.x = GetWidth() - scrollBarWidth_;
|
||||
ySliderPos_.y = GetYScrollOffset(childRect);
|
||||
ySlider_.SetHeight(yHeight);
|
||||
ySlider_.SetWidth(scrollBarWidth_);
|
||||
}
|
||||
}
|
||||
|
||||
void UIScrollView::RefreshScrollBarPosition()
|
||||
{
|
||||
if (!xSlider_.IsVisible() && !ySlider_.IsVisible()) {
|
||||
return;
|
||||
}
|
||||
Rect childRect = GetAllChildRelativeRect();
|
||||
if ((childRect.GetWidth() == 0) || (childRect.GetHeight() == 0)) {
|
||||
return;
|
||||
}
|
||||
if (xScrollable_) {
|
||||
int16_t xOffset = GetXScrollOffset(childRect);
|
||||
xSliderPos_.x = xOffset;
|
||||
Invalidate();
|
||||
}
|
||||
if (yScrollable_) {
|
||||
int16_t yOffset = GetYScrollOffset(childRect);
|
||||
ySliderPos_.y = yOffset;
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
int16_t UIScrollView::GetXScrollOffset(const Rect& childRect)
|
||||
{
|
||||
Rect scrollRect = GetRelativeRect();
|
||||
int16_t xOffset;
|
||||
int16_t scrollBarOffset = 0;
|
||||
|
||||
if (yScrollable_) {
|
||||
scrollBarOffset = scrollBarWidth_;
|
||||
}
|
||||
|
||||
int16_t childRectLeft = childRect.GetLeft();
|
||||
int16_t childRectWidth = childRect.GetWidth();
|
||||
int16_t scrollRectWidth = scrollRect.GetWidth();
|
||||
int16_t xSliderWidth = xSlider_.GetWidth();
|
||||
if ((childRectLeft >= 0) || (childRectWidth - scrollRectWidth + scrollBarOffset == 0)) {
|
||||
xOffset = 0;
|
||||
} else {
|
||||
float multiple = static_cast<float>(scrollRectWidth - scrollBarOffset - xSliderWidth) /
|
||||
(childRectWidth - scrollRectWidth + scrollBarOffset);
|
||||
xOffset = static_cast<int16_t>(-childRectLeft * multiple);
|
||||
}
|
||||
return xOffset;
|
||||
}
|
||||
|
||||
int16_t UIScrollView::GetYScrollOffset(const Rect& childRect)
|
||||
{
|
||||
Rect scrollRect = GetRelativeRect();
|
||||
int16_t yOffset;
|
||||
int16_t scrollBarOffset = 0;
|
||||
|
||||
if (xScrollable_) {
|
||||
scrollBarOffset = scrollBarWidth_;
|
||||
}
|
||||
|
||||
int16_t childRectTop = childRect.GetTop();
|
||||
int16_t childRectHeight = childRect.GetHeight();
|
||||
int16_t scrollRectHeight = scrollRect.GetHeight();
|
||||
int16_t ySliderHeight = ySlider_.GetHeight();
|
||||
if ((childRectTop >= 0) || (childRectHeight - scrollRectHeight + scrollBarOffset == 0)) {
|
||||
yOffset = 0;
|
||||
} else {
|
||||
float multiple = static_cast<float>(scrollRectHeight - scrollBarOffset - ySliderHeight) /
|
||||
(childRectHeight - scrollRectHeight + scrollBarOffset);
|
||||
yOffset = static_cast<int16_t>(-childRectTop * multiple);
|
||||
}
|
||||
return yOffset;
|
||||
}
|
||||
|
||||
void UIScrollView::OnChildChanged()
|
||||
{
|
||||
RefreshScrollBar();
|
||||
}
|
||||
|
||||
void UIScrollView::CalculateReboundDistance(int16_t& dragDistanceX, int16_t& dragDistanceY)
|
||||
{
|
||||
Rect rect = GetAllChildRelativeRect();
|
||||
int16_t top = rect.GetTop();
|
||||
int16_t bottom = rect.GetBottom();
|
||||
int16_t scrollHeight = GetHeight();
|
||||
int16_t left = rect.GetLeft();
|
||||
int16_t right = rect.GetRight();
|
||||
int16_t scrollWidth = GetWidth();
|
||||
if (scrollBlankSize_ < top) {
|
||||
dragDistanceY = scrollBlankSize_ - top;
|
||||
} else if (bottom < scrollHeight - 1) {
|
||||
dragDistanceY = scrollHeight - scrollBlankSize_ - bottom - 1;
|
||||
}
|
||||
|
||||
if (scrollBlankSize_ < left) {
|
||||
dragDistanceX = scrollBlankSize_ - left;
|
||||
} else if (right < scrollWidth - 1) {
|
||||
dragDistanceX = scrollWidth - scrollBlankSize_ - right - 1;
|
||||
}
|
||||
}
|
||||
|
||||
void UIScrollView::StopAnimator()
|
||||
{
|
||||
if ((scrollListener_ != nullptr) && (scrollListener_->GetScrollState() == OnScrollListener::SCROLL_STATE_MOVE)) {
|
||||
scrollListener_->OnScrollEnd();
|
||||
scrollListener_->SetScrollState(OnScrollListener::SCROLL_STATE_STOP);
|
||||
}
|
||||
UIAbstractScroll::StopAnimator();
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+299
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_slider.h"
|
||||
#include "common/image.h"
|
||||
#include "dock/focus_manager.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UISlider::UISlider()
|
||||
: knobWidth_(0), knobWidthSetFlag_(false), knobStyleAllocFlag_(false), knobImage_(nullptr), listener_(nullptr)
|
||||
{
|
||||
touchable_ = true;
|
||||
draggable_ = true;
|
||||
dragParentInstead_ = false;
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
if (theme != nullptr) {
|
||||
knobStyle_ = &(theme->GetSliderKnobStyle());
|
||||
} else {
|
||||
knobStyle_ = &(StyleDefault::GetSliderKnobStyle());
|
||||
}
|
||||
}
|
||||
|
||||
UISlider::~UISlider()
|
||||
{
|
||||
if (knobImage_ != nullptr) {
|
||||
delete knobImage_;
|
||||
knobImage_ = nullptr;
|
||||
}
|
||||
|
||||
if (knobStyleAllocFlag_) {
|
||||
delete knobStyle_;
|
||||
knobStyle_ = nullptr;
|
||||
knobStyleAllocFlag_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
void UISlider::SetKnobStyle(const Style& style)
|
||||
{
|
||||
if (!knobStyleAllocFlag_) {
|
||||
knobStyle_ = new Style;
|
||||
if (knobStyle_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style fail");
|
||||
return;
|
||||
}
|
||||
knobStyleAllocFlag_ = true;
|
||||
}
|
||||
*knobStyle_ = style;
|
||||
}
|
||||
|
||||
void UISlider::SetKnobStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
if (!knobStyleAllocFlag_) {
|
||||
knobStyle_ = new Style(*knobStyle_);
|
||||
if (knobStyle_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style fail");
|
||||
return;
|
||||
}
|
||||
knobStyleAllocFlag_ = true;
|
||||
}
|
||||
knobStyle_->SetStyle(key, value);
|
||||
}
|
||||
|
||||
const Style& UISlider::GetKnobStyle() const
|
||||
{
|
||||
return *knobStyle_;
|
||||
}
|
||||
|
||||
int64_t UISlider::GetKnobStyle(uint8_t key) const
|
||||
{
|
||||
return knobStyle_->GetStyle(key);
|
||||
}
|
||||
|
||||
int32_t UISlider::CalculateCurrentValue(int16_t length, int16_t totalLength)
|
||||
{
|
||||
if (totalLength != 0) {
|
||||
return static_cast<int32_t>(rangeMin_ + (static_cast<int64_t>(rangeMax_) - rangeMin_) * length / totalLength);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int32_t UISlider::UpdateCurrentValue(const Point& knobPosition)
|
||||
{
|
||||
Point startPoint;
|
||||
Rect rect = GetOrigRect();
|
||||
startPoint.x = rect.GetLeft() + style_->borderWidth_ + style_->paddingLeft_;
|
||||
startPoint.y = rect.GetTop() + style_->borderWidth_ + style_->paddingTop_;
|
||||
|
||||
int32_t value = curValue_;
|
||||
switch (direction_) {
|
||||
case Direction::DIR_LEFT_TO_RIGHT:
|
||||
if (knobPosition.x <= startPoint.x) {
|
||||
value = rangeMin_;
|
||||
} else if (knobPosition.x >= startPoint.x + progressWidth_) {
|
||||
value = rangeMax_;
|
||||
} else {
|
||||
value = CalculateCurrentValue(knobPosition.x - startPoint.x, progressWidth_);
|
||||
}
|
||||
break;
|
||||
case Direction::DIR_RIGHT_TO_LEFT:
|
||||
if (knobPosition.x <= startPoint.x) {
|
||||
value = rangeMax_;
|
||||
} else if (knobPosition.x >= startPoint.x + progressWidth_) {
|
||||
value = rangeMin_;
|
||||
} else {
|
||||
value = CalculateCurrentValue(startPoint.x + progressWidth_ - knobPosition.x, progressWidth_);
|
||||
}
|
||||
break;
|
||||
case Direction::DIR_BOTTOM_TO_TOP:
|
||||
if (knobPosition.y <= startPoint.y) {
|
||||
value = rangeMax_;
|
||||
} else if (knobPosition.y >= startPoint.y + progressHeight_) {
|
||||
value = rangeMin_;
|
||||
} else {
|
||||
value = CalculateCurrentValue(startPoint.y + progressHeight_ - knobPosition.y, progressHeight_);
|
||||
}
|
||||
break;
|
||||
case Direction::DIR_TOP_TO_BOTTOM:
|
||||
if (knobPosition.y <= startPoint.y) {
|
||||
value = rangeMin_;
|
||||
} else if (knobPosition.y >= startPoint.y + progressHeight_) {
|
||||
value = rangeMax_;
|
||||
} else {
|
||||
value = CalculateCurrentValue(knobPosition.y - startPoint.y, progressHeight_);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
GRAPHIC_LOGW("UISlider::UpdateCurrentValue Direction error!\n");
|
||||
}
|
||||
SetValue(value);
|
||||
return value;
|
||||
}
|
||||
|
||||
bool UISlider::OnClickEvent(const ClickEvent& event)
|
||||
{
|
||||
Point knobPosition = event.GetCurrentPos();
|
||||
int32_t value = UpdateCurrentValue(knobPosition);
|
||||
if (listener_ != nullptr) {
|
||||
listener_->OnChange(value);
|
||||
}
|
||||
bool ret = UIView::OnClickEvent(event);
|
||||
Invalidate();
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool UISlider::OnDragEvent(const DragEvent& event)
|
||||
{
|
||||
Point knobPosition = event.GetCurrentPos();
|
||||
int32_t value = UpdateCurrentValue(knobPosition);
|
||||
if (listener_ != nullptr) {
|
||||
listener_->OnChange(value);
|
||||
}
|
||||
Invalidate();
|
||||
return UIView::OnDragEvent(event);
|
||||
}
|
||||
|
||||
bool UISlider::OnDragEndEvent(const DragEvent& event)
|
||||
{
|
||||
Point knobPosition = event.GetCurrentPos();
|
||||
int32_t value = UpdateCurrentValue(knobPosition);
|
||||
if (listener_ != nullptr) {
|
||||
listener_->OnChange(value);
|
||||
listener_->OnRelease(value);
|
||||
}
|
||||
Invalidate();
|
||||
return UIView::OnDragEndEvent(event);
|
||||
}
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
bool UISlider::OnRotateEvent(const RotateEvent& event)
|
||||
{
|
||||
if (event.GetRotate() == 0) {
|
||||
return false;
|
||||
}
|
||||
int32_t tmp = event.GetRotate() * rotateFactor_;
|
||||
SetValue(curValue_ + tmp);
|
||||
#if ENABLE_MOTOR
|
||||
MotorFunc motorFunc = FocusManager::GetInstance()->GetMotorFunc();
|
||||
if (motorFunc != nullptr) {
|
||||
motorFunc(MotorType::MOTOR_TYPE_TWO);
|
||||
}
|
||||
#endif
|
||||
return UIView::OnRotateEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
int16_t UISlider::GetKnobWidth()
|
||||
{
|
||||
if (!knobWidthSetFlag_) {
|
||||
if ((direction_ == Direction::DIR_LEFT_TO_RIGHT) || (direction_ == Direction::DIR_RIGHT_TO_LEFT)) {
|
||||
knobWidth_ = progressHeight_;
|
||||
} else {
|
||||
knobWidth_ = progressWidth_;
|
||||
}
|
||||
}
|
||||
return knobWidth_;
|
||||
}
|
||||
|
||||
void UISlider::SetImage(const ImageInfo* backgroundImage, const ImageInfo* foregroundImage, const ImageInfo* knobImage)
|
||||
{
|
||||
if (!InitImage()) {
|
||||
return;
|
||||
}
|
||||
backgroundImage_->SetSrc(backgroundImage);
|
||||
foregroundImage_->SetSrc(foregroundImage);
|
||||
knobImage_->SetSrc(knobImage);
|
||||
}
|
||||
|
||||
void UISlider::SetImage(const char* backgroundImage, const char* foregroundImage, const char* knobImage)
|
||||
{
|
||||
if (!InitImage()) {
|
||||
return;
|
||||
}
|
||||
backgroundImage_->SetSrc(backgroundImage);
|
||||
foregroundImage_->SetSrc(foregroundImage);
|
||||
knobImage_->SetSrc(knobImage);
|
||||
}
|
||||
|
||||
void UISlider::DrawKnob(const Rect& invalidatedArea, const Rect& foregroundRect)
|
||||
{
|
||||
int16_t halfKnobWidth = GetKnobWidth() >> 1;
|
||||
int16_t offset;
|
||||
Rect knobBar;
|
||||
switch (direction_) {
|
||||
case Direction::DIR_LEFT_TO_RIGHT: {
|
||||
offset = (knobWidth_ - progressHeight_) >> 1;
|
||||
knobBar.SetRect(foregroundRect.GetRight() - halfKnobWidth, foregroundRect.GetTop() - offset,
|
||||
foregroundRect.GetRight() + halfKnobWidth, foregroundRect.GetBottom() + offset);
|
||||
break;
|
||||
}
|
||||
case Direction::DIR_RIGHT_TO_LEFT: {
|
||||
offset = (knobWidth_ - progressHeight_) >> 1;
|
||||
knobBar.SetRect(foregroundRect.GetLeft() - halfKnobWidth, foregroundRect.GetTop() - offset,
|
||||
foregroundRect.GetLeft() + halfKnobWidth, foregroundRect.GetBottom() + offset);
|
||||
break;
|
||||
}
|
||||
case Direction::DIR_BOTTOM_TO_TOP: {
|
||||
offset = (knobWidth_ - progressWidth_) >> 1;
|
||||
knobBar.SetRect(foregroundRect.GetLeft() - offset, foregroundRect.GetTop() - halfKnobWidth,
|
||||
foregroundRect.GetRight() + offset, foregroundRect.GetTop() + halfKnobWidth);
|
||||
break;
|
||||
}
|
||||
case Direction::DIR_TOP_TO_BOTTOM: {
|
||||
offset = (knobWidth_ - progressWidth_) >> 1;
|
||||
knobBar.SetRect(foregroundRect.GetLeft() - offset, foregroundRect.GetBottom() - halfKnobWidth,
|
||||
foregroundRect.GetRight() + offset, foregroundRect.GetBottom() + halfKnobWidth);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
GRAPHIC_LOGW("UISlider::DrawKnob Direction error!\n");
|
||||
}
|
||||
}
|
||||
DrawValidRect(knobImage_, knobBar, invalidatedArea, *knobStyle_, 0);
|
||||
}
|
||||
|
||||
void UISlider::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
DrawRect::Draw(GetOrigRect(), invalidatedArea, *style_, opaScale_);
|
||||
|
||||
Rect trunc(invalidatedArea);
|
||||
if (trunc.Intersect(trunc, GetOrigRect())) {
|
||||
DrawBackground(trunc);
|
||||
Rect foregroundRect;
|
||||
DrawForeground(trunc, foregroundRect);
|
||||
DrawKnob(trunc, foregroundRect);
|
||||
}
|
||||
}
|
||||
|
||||
bool UISlider::InitImage()
|
||||
{
|
||||
if (!UIAbstractProgress::InitImage()) {
|
||||
return false;
|
||||
}
|
||||
if (knobImage_ == nullptr) {
|
||||
knobImage_ = new Image();
|
||||
if (knobImage_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Image fail");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+157
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_surface_view.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "draw/draw_rect.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "graphic_log.h"
|
||||
#include "surface_buffer.h"
|
||||
|
||||
namespace OHOS {
|
||||
UISurfaceView::UISurfaceView()
|
||||
{
|
||||
surface_ = Surface::CreateSurface();
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::UISurfaceView surface create failed\n");
|
||||
return;
|
||||
}
|
||||
surface_->SetWidthAndHeight(GetWidth(), GetHeight());
|
||||
surface_->SetQueueSize(DEFAULT_QUEUE_SIZE);
|
||||
surface_->SetFormat(IMAGE_PIXEL_FORMAT_ARGB8888);
|
||||
}
|
||||
|
||||
UISurfaceView::~UISurfaceView()
|
||||
{
|
||||
if (surface_ != nullptr) {
|
||||
delete surface_;
|
||||
surface_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UISurfaceView::SetPosition(int16_t x, int16_t y)
|
||||
{
|
||||
UIView::SetPosition(x, y);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::SetPosition surface is null\n");
|
||||
return;
|
||||
}
|
||||
x = GetRect().GetLeft();
|
||||
y = GetRect().GetTop();
|
||||
surface_->SetUserData(REGION_POSITION_X, std::to_string(x));
|
||||
surface_->SetUserData(REGION_POSITION_Y, std::to_string(y));
|
||||
}
|
||||
|
||||
void UISurfaceView::SetPosition(int16_t x, int16_t y, int16_t width, int16_t height)
|
||||
{
|
||||
UIView::SetPosition(x, y, width, height);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::SetPosition surface is null\n");
|
||||
return;
|
||||
}
|
||||
x = GetRect().GetLeft();
|
||||
y = GetRect().GetTop();
|
||||
surface_->SetUserData(REGION_POSITION_X, std::to_string(x));
|
||||
surface_->SetUserData(REGION_POSITION_Y, std::to_string(y));
|
||||
surface_->SetUserData(REGION_WIDTH, std::to_string(width));
|
||||
surface_->SetUserData(REGION_HEIGHT, std::to_string(height));
|
||||
}
|
||||
|
||||
void UISurfaceView::Resize(int16_t width, int16_t height)
|
||||
{
|
||||
UIView::Resize(width, height);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::Resize surface is null\n");
|
||||
return;
|
||||
}
|
||||
surface_->SetUserData(REGION_WIDTH, std::to_string(width));
|
||||
surface_->SetUserData(REGION_HEIGHT, std::to_string(height));
|
||||
}
|
||||
|
||||
void UISurfaceView::SetWidth(int16_t width)
|
||||
{
|
||||
UIView::SetWidth(width);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::SetWidth surface is null\n");
|
||||
return;
|
||||
}
|
||||
surface_->SetUserData(REGION_WIDTH, std::to_string(width));
|
||||
}
|
||||
|
||||
void UISurfaceView::SetHeight(int16_t height)
|
||||
{
|
||||
UIView::SetHeight(height);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::SetHeight surface is null\n");
|
||||
return;
|
||||
}
|
||||
surface_->SetUserData(REGION_HEIGHT, std::to_string(height));
|
||||
}
|
||||
|
||||
void UISurfaceView::SetX(int16_t x)
|
||||
{
|
||||
UIView::SetX(x);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::SetX surface is null\n");
|
||||
return;
|
||||
}
|
||||
x = GetRect().GetLeft();
|
||||
surface_->SetUserData(REGION_POSITION_X, std::to_string(x));
|
||||
}
|
||||
|
||||
void UISurfaceView::SetY(int16_t y)
|
||||
{
|
||||
UIView::SetY(y);
|
||||
if (surface_ == nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::SetY surface is null\n");
|
||||
return;
|
||||
}
|
||||
y = GetRect().GetTop();
|
||||
surface_->SetUserData(REGION_POSITION_Y, std::to_string(y));
|
||||
}
|
||||
|
||||
Surface* UISurfaceView::GetSurface() const
|
||||
{
|
||||
return surface_;
|
||||
}
|
||||
|
||||
bool UISurfaceView::OnPreDraw(Rect& invalidatedArea) const
|
||||
{
|
||||
// need fill transpant color
|
||||
return false;
|
||||
}
|
||||
|
||||
void UISurfaceView::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
Draw(invalidatedArea);
|
||||
}
|
||||
|
||||
void UISurfaceView::Draw(const Rect& invalidatedArea)
|
||||
{
|
||||
SurfaceBuffer* acquireBuffer = (surface_ != nullptr) ? surface_->AcquireBuffer() : nullptr;
|
||||
if (acquireBuffer != nullptr) {
|
||||
GRAPHIC_LOGE("UISurfaceView::Draw acquireBufferVirAddr=%p \n", acquireBuffer->GetVirAddr());
|
||||
// fill with buffer
|
||||
DrawUtils::GetInstance()->DrawWithBuffer(GetRect(), invalidatedArea,
|
||||
reinterpret_cast<const ColorType*>(acquireBuffer->GetVirAddr()));
|
||||
surface_->ReleaseBuffer(acquireBuffer);
|
||||
} else {
|
||||
// fill with transpant color
|
||||
DrawUtils::GetInstance()->DrawTranspantArea(GetRect(), invalidatedArea);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+480
@@ -0,0 +1,480 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_swipe_view.h"
|
||||
#include "dock/focus_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UISwipeView::UISwipeView(uint8_t direction)
|
||||
: swipeListener_(nullptr),
|
||||
curIndex_(0),
|
||||
blankSize_(DEFAULT_BLANK_SIZE),
|
||||
curView_(nullptr),
|
||||
loop_(false)
|
||||
{
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
rotateFactor_ = 1;
|
||||
#endif
|
||||
direction_ = direction;
|
||||
AnimatorManager::GetInstance()->Add(&scrollAnimator_);
|
||||
tickTime_ = ANIMATOR_TIME;
|
||||
swipeAccCoefficient_ = DRAG_ACC_FACTOR;
|
||||
}
|
||||
|
||||
UISwipeView::~UISwipeView()
|
||||
{
|
||||
AnimatorManager::GetInstance()->Remove(&scrollAnimator_);
|
||||
}
|
||||
|
||||
void UISwipeView::Add(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
view->SetDragParentInstead(true);
|
||||
UIViewGroup::Add(view);
|
||||
SortChild();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UISwipeView::Insert(UIView* prevView, UIView* insertView)
|
||||
{
|
||||
if (insertView == nullptr) {
|
||||
return;
|
||||
}
|
||||
insertView->SetDragParentInstead(true);
|
||||
UIViewGroup::Insert(prevView, insertView);
|
||||
SortChild();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UISwipeView::Remove(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIViewGroup::Remove(view);
|
||||
SortChild();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UISwipeView::SetCurrentPage(uint16_t index, bool needAnimator)
|
||||
{
|
||||
SwitchToPage(index, needAnimator);
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
bool UISwipeView::DragXInner(int16_t distance)
|
||||
{
|
||||
if (distance == 0) {
|
||||
return true;
|
||||
}
|
||||
if (!loop_) {
|
||||
if ((distance > 0) && (childrenHead_ != nullptr)) {
|
||||
if (childrenHead_->GetX() >= blankSize_) {
|
||||
distance = 0;
|
||||
} else if (childrenHead_ && (childrenHead_->GetX() + distance > blankSize_)) {
|
||||
distance = blankSize_ - childrenHead_->GetX();
|
||||
}
|
||||
} else if (childrenTail_ != nullptr) {
|
||||
int16_t width = GetWidth();
|
||||
if (childrenTail_->GetRelativeRect().GetRight() < width - blankSize_) {
|
||||
distance = 0;
|
||||
} else if (width - (childrenTail_->GetX() + childrenTail_->GetWidth() + distance) > blankSize_) {
|
||||
distance = width - blankSize_ - childrenTail_->GetX() - childrenTail_->GetWidth();
|
||||
}
|
||||
}
|
||||
}
|
||||
CalculateInvalidate();
|
||||
MoveChildByOffset(distance, 0);
|
||||
CalculateInvalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UISwipeView::DragYInner(int16_t distance)
|
||||
{
|
||||
if (distance == 0) {
|
||||
return true;
|
||||
}
|
||||
if (!loop_) {
|
||||
if ((distance > 0) && (childrenHead_ != nullptr)) {
|
||||
if (childrenHead_->GetY() >= blankSize_) {
|
||||
distance = 0;
|
||||
} else if ((childrenHead_ != nullptr) && (childrenHead_->GetY() + distance > blankSize_)) {
|
||||
distance = blankSize_ - childrenHead_->GetY();
|
||||
}
|
||||
} else if (childrenTail_ != nullptr) {
|
||||
int16_t height = GetHeight();
|
||||
if (childrenTail_->GetRelativeRect().GetBottom() < height - blankSize_) {
|
||||
distance = 0;
|
||||
} else if (height - (childrenTail_->GetY() + childrenTail_->GetHeight() + distance) > blankSize_) {
|
||||
distance = height - blankSize_ - childrenTail_->GetY() - childrenTail_->GetHeight();
|
||||
}
|
||||
}
|
||||
}
|
||||
CalculateInvalidate();
|
||||
MoveChildByOffset(0, distance);
|
||||
CalculateInvalidate();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UISwipeView::OnDragEvent(const DragEvent& event)
|
||||
{
|
||||
UIView* currentView = GetViewByIndex(curIndex_);
|
||||
if (currentView == nullptr) {
|
||||
return UIView::OnDragEvent(event);
|
||||
}
|
||||
if (scrollAnimator_.GetState() != Animator::STOP) {
|
||||
UIAbstractScroll::StopAnimator();
|
||||
}
|
||||
|
||||
if (direction_ == HORIZONTAL) {
|
||||
DragXInner(event.GetDeltaX());
|
||||
RefreshDeltaY(event.GetDeltaX());
|
||||
} else {
|
||||
DragYInner(event.GetDeltaY());
|
||||
RefreshDeltaY(event.GetDeltaY());
|
||||
}
|
||||
return UIView::OnDragEvent(event);
|
||||
}
|
||||
|
||||
bool UISwipeView::OnDragEndEvent(const DragEvent& event)
|
||||
{
|
||||
int16_t distance = 0;
|
||||
if (direction_ == HORIZONTAL) {
|
||||
distance = event.GetCurrentPos().x - event.GetPreLastPoint().x;
|
||||
} else {
|
||||
distance = event.GetCurrentPos().y - event.GetPreLastPoint().y;
|
||||
}
|
||||
RefreshCurrentView(distance);
|
||||
|
||||
if (curView_ == nullptr) {
|
||||
return UIView::OnDragEndEvent(event);
|
||||
}
|
||||
|
||||
SwitchToPage(curIndex_);
|
||||
|
||||
Invalidate();
|
||||
return UIView::OnDragEndEvent(event);
|
||||
}
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
bool UISwipeView::OnRotateEvent(const RotateEvent& event)
|
||||
{
|
||||
if (event.GetRotate() != 0) {
|
||||
// 4 : need to fit for the device
|
||||
if (MATH_ABS(event.GetRotate()) > blankSize_ / (4 * static_cast<uint16_t>(rotateFactor_))) {
|
||||
SwitchToPage(curIndex_ - event.GetRotate());
|
||||
} else {
|
||||
int16_t tmp = event.GetRotate() * rotateFactor_;
|
||||
DragXInner(tmp);
|
||||
RefreshCurrentView(tmp);
|
||||
}
|
||||
} else {
|
||||
SwitchToPage(curIndex_);
|
||||
#if ENABLE_MOTOR
|
||||
MotorFunc motorFunc = FocusManager::GetInstance()->GetMotorFunc();
|
||||
if (motorFunc != nullptr) {
|
||||
motorFunc(MotorType::MOTOR_TYPE_ONE);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
return UIView::OnRotateEvent(event);
|
||||
}
|
||||
#endif
|
||||
|
||||
UIView* UISwipeView::GetViewByIndex(uint16_t index) const
|
||||
{
|
||||
UIView* child = childrenHead_;
|
||||
while (child != nullptr) {
|
||||
if (child->GetViewIndex() == index) {
|
||||
return child;
|
||||
}
|
||||
child = child->GetNextSibling();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UISwipeView::SetAnimatorTime(uint16_t time)
|
||||
{
|
||||
tickTime_ = time / DEFAULT_TASK_PERIOD;
|
||||
if (tickTime_ == 0) {
|
||||
tickTime_ = 1;
|
||||
}
|
||||
animatorCallback_.SetDragTimes(tickTime_);
|
||||
}
|
||||
|
||||
void UISwipeView::SwitchToPage(int16_t dst, bool needAnimator)
|
||||
{
|
||||
if (isNeedLoop()) {
|
||||
dst = (dst + childrenNum_) % childrenNum_;
|
||||
} else if (dst < 0) {
|
||||
dst = 0;
|
||||
} else if (dst >= childrenNum_) {
|
||||
dst = childrenNum_ - 1;
|
||||
}
|
||||
|
||||
UIView* dstView = GetViewByIndex(dst);
|
||||
if (dstView == nullptr) {
|
||||
return;
|
||||
}
|
||||
curIndex_ = dst;
|
||||
int16_t xOffset = 0;
|
||||
int16_t yOffset = 0;
|
||||
|
||||
if (direction_ == HORIZONTAL) {
|
||||
if (alignMode_ == ALIGN_LEFT) {
|
||||
xOffset = -dstView->GetX();
|
||||
} else if (alignMode_ == ALIGN_RIGHT) {
|
||||
xOffset = GetWidth() - (dstView->GetX() + dstView->GetWidth());
|
||||
} else {
|
||||
xOffset = (GetWidth() >> 1) - (dstView->GetX() + (dstView->GetWidth() >> 1));
|
||||
}
|
||||
} else {
|
||||
yOffset = (GetHeight() >> 1) - (dstView->GetY() + (dstView->GetHeight() >> 1));
|
||||
}
|
||||
|
||||
if ((xOffset != 0) || (yOffset != 0)) {
|
||||
if (scrollAnimator_.GetState() != Animator::STOP) {
|
||||
scrollAnimator_.Stop();
|
||||
}
|
||||
if (needAnimator) {
|
||||
animatorCallback_.SetDragTimes(tickTime_);
|
||||
animatorCallback_.SetDragStartValue(0, 0);
|
||||
animatorCallback_.SetDragEndValue(xOffset, yOffset);
|
||||
scrollAnimator_.Start();
|
||||
} else {
|
||||
MoveChildByOffset(xOffset, yOffset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UISwipeView::StopAnimator()
|
||||
{
|
||||
UIAbstractScroll::StopAnimator();
|
||||
if (swipeListener_ != nullptr) {
|
||||
swipeListener_->OnSwipe(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void UISwipeView::SortChild()
|
||||
{
|
||||
if (childrenHead_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
int16_t index = 0;
|
||||
UIView* pre = childrenHead_;
|
||||
UIView* next = childrenHead_->GetNextSibling();
|
||||
if (direction_ == HORIZONTAL) {
|
||||
pre->SetX(0);
|
||||
} else {
|
||||
pre->SetY(0);
|
||||
}
|
||||
pre->SetViewIndex(index);
|
||||
index++;
|
||||
|
||||
while (next != nullptr) {
|
||||
if (direction_ == HORIZONTAL) {
|
||||
next->SetX(pre->GetX() + pre->GetWidth());
|
||||
} else {
|
||||
next->SetY(pre->GetY() + pre->GetHeight());
|
||||
}
|
||||
pre = next;
|
||||
next->SetViewIndex(index);
|
||||
next = next->GetNextSibling();
|
||||
index++;
|
||||
}
|
||||
bool tmpLoop = loop_;
|
||||
loop_ = false;
|
||||
SwitchToPage(curIndex_, false);
|
||||
loop_ = tmpLoop;
|
||||
}
|
||||
|
||||
void UISwipeView::RefreshCurrentViewInner(int16_t distance, int16_t (UIView::*pfnGetXOrY)() const,
|
||||
int16_t(UIView::*pfnGetWidthOrHeight)())
|
||||
{
|
||||
if (childrenHead_ == nullptr) {
|
||||
curIndex_ = 0;
|
||||
curView_ = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
curIndex_ = 0;
|
||||
curView_ = nullptr;
|
||||
|
||||
uint16_t swipeMid;
|
||||
if (alignMode_ == ALIGN_LEFT) {
|
||||
swipeMid = 0;
|
||||
} else if (alignMode_ == ALIGN_RIGHT) {
|
||||
swipeMid = (this->*pfnGetWidthOrHeight)();
|
||||
} else {
|
||||
swipeMid = (this->*pfnGetWidthOrHeight)() >> 1;
|
||||
}
|
||||
UIView* view = childrenHead_;
|
||||
|
||||
if ((childrenHead_->*pfnGetXOrY)() > swipeMid) {
|
||||
curIndex_ = childrenHead_->GetViewIndex();
|
||||
curView_ = childrenHead_;
|
||||
} else if ((childrenTail_->*pfnGetXOrY)() + (childrenHead_->*pfnGetWidthOrHeight)() < swipeMid) {
|
||||
curIndex_ = childrenTail_->GetViewIndex();
|
||||
curView_ = childrenTail_;
|
||||
} else {
|
||||
while (view != nullptr) {
|
||||
if ((swipeMid >= (view->*pfnGetXOrY)()) &&
|
||||
(swipeMid <= (view->*pfnGetXOrY)() + (view->*pfnGetWidthOrHeight)())) {
|
||||
curIndex_ = view->GetViewIndex();
|
||||
curView_ = view;
|
||||
break;
|
||||
}
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
}
|
||||
if (curView_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t accelerationOffset = GetMaxDeltaY() * GetSwipeACCLevel() / DRAG_ACC_FACTOR;
|
||||
if (distance < 0) {
|
||||
/*
|
||||
* 7, 10 : Check whether the current view is dragged by more than 1/5,
|
||||
* that is, the x or y coordinate plus 7/10 width or height.
|
||||
*/
|
||||
if (((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) < swipeMid) &&
|
||||
((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() * 7 / 10) -
|
||||
accelerationOffset < swipeMid)) {
|
||||
curIndex_++;
|
||||
}
|
||||
} else if (distance > 0) {
|
||||
/*
|
||||
* 3, 10 : Check whether the current view is dragged by more than 1/5,
|
||||
* that is, the x or y coordinate plus 3/10 width or height.
|
||||
*/
|
||||
if (((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) > swipeMid) &&
|
||||
((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() * 3 / 10) +
|
||||
accelerationOffset > swipeMid)) {
|
||||
curIndex_--;
|
||||
}
|
||||
} else {
|
||||
if (alignMode_ == ALIGN_LEFT) {
|
||||
if (((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) < swipeMid)) {
|
||||
curIndex_++;
|
||||
}
|
||||
} else if (alignMode_ == ALIGN_RIGHT) {
|
||||
if ((curView_->*pfnGetXOrY)() + ((curView_->*pfnGetWidthOrHeight)() >> 1) > swipeMid) {
|
||||
curIndex_--;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UISwipeView::RefreshCurrentView(int16_t distance)
|
||||
{
|
||||
if (direction_ == HORIZONTAL) {
|
||||
RefreshCurrentViewInner(distance, &UIView::GetX, &UIView::GetWidth);
|
||||
} else {
|
||||
RefreshCurrentViewInner(distance, &UIView::GetY, &UIView::GetHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void UISwipeView::MoveChildByOffset(int16_t xOffset, int16_t yOffset)
|
||||
{
|
||||
UIViewGroup::MoveChildByOffset(xOffset, yOffset);
|
||||
if (direction_ == HORIZONTAL) {
|
||||
while (isNeedLoop() && (childrenHead_->GetX() > 0)) {
|
||||
MoveLastChildToFirst();
|
||||
}
|
||||
while (isNeedLoop() && (childrenTail_->GetX() + childrenTail_->GetWidth() < GetWidth())) {
|
||||
MoveFirstChildToLast();
|
||||
}
|
||||
} else {
|
||||
while (isNeedLoop() && (childrenHead_->GetY() > 0)) {
|
||||
MoveLastChildToFirst();
|
||||
}
|
||||
while (isNeedLoop() && (childrenTail_->GetY() + childrenTail_->GetHeight() < GetHeight())) {
|
||||
MoveFirstChildToLast();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UISwipeView::isNeedLoop()
|
||||
{
|
||||
if (!loop_ || (childrenHead_ == nullptr) || (childrenTail_ == nullptr)) {
|
||||
return false;
|
||||
}
|
||||
Rect childRect = GetAllChildRelativeRect();
|
||||
if (direction_ == HORIZONTAL) {
|
||||
if ((childRect.GetWidth() - childrenHead_->GetWidth() >= GetWidth()) &&
|
||||
(childRect.GetWidth() - childrenTail_->GetWidth() >= GetWidth())) {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if ((childRect.GetHeight() - childrenHead_->GetHeight() >= GetHeight()) &&
|
||||
(childRect.GetHeight() - childrenTail_->GetHeight() >= GetHeight())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UISwipeView::MoveFirstChildToLast()
|
||||
{
|
||||
if ((childrenTail_ == nullptr) || (childrenHead_ == nullptr)) {
|
||||
return;
|
||||
}
|
||||
if (direction_ == HORIZONTAL) {
|
||||
childrenHead_->SetX(childrenTail_->GetX() + childrenTail_->GetWidth());
|
||||
} else {
|
||||
childrenHead_->SetY(childrenTail_->GetY() + childrenTail_->GetHeight());
|
||||
}
|
||||
UIView* head = childrenHead_;
|
||||
UIViewGroup::Remove(childrenHead_);
|
||||
UIViewGroup::Add(head);
|
||||
}
|
||||
|
||||
void UISwipeView::MoveLastChildToFirst()
|
||||
{
|
||||
if ((childrenTail_ == nullptr) || (childrenHead_ == nullptr)) {
|
||||
return;
|
||||
}
|
||||
if (direction_ == HORIZONTAL) {
|
||||
childrenTail_->SetX(childrenHead_->GetX() - childrenTail_->GetWidth());
|
||||
} else {
|
||||
childrenTail_->SetY(childrenHead_->GetY() - childrenTail_->GetHeight());
|
||||
}
|
||||
UIView* last = childrenTail_;
|
||||
UIViewGroup::Remove(childrenTail_);
|
||||
UIViewGroup::Insert(nullptr, last);
|
||||
}
|
||||
|
||||
void UISwipeView::CalculateInvalidate()
|
||||
{
|
||||
Rect swipeRect(0, 0, GetRelativeRect().GetWidth() - 1, GetRelativeRect().GetHeight() - 1);
|
||||
UIView* view = childrenHead_;
|
||||
bool isFound = false;
|
||||
while (view != nullptr) {
|
||||
Rect rect = view->GetRelativeRect();
|
||||
if (rect.IsIntersect(swipeRect)) {
|
||||
if (view->IsVisible() && (view->GetOpaScale() != OPA_TRANSPARENT)) {
|
||||
view->Invalidate();
|
||||
}
|
||||
isFound = true;
|
||||
} else if (isFound) {
|
||||
return;
|
||||
}
|
||||
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+95
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_texture_mapper.h"
|
||||
|
||||
namespace OHOS {
|
||||
void UITextureMapper::TextureMapperAnimatorCallback::Callback(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
UITextureMapper* mapper = static_cast<UITextureMapper*>(view);
|
||||
mapper->Callback();
|
||||
}
|
||||
|
||||
void UITextureMapper::TextureMapperAnimatorCallback::OnStop(UIView& view)
|
||||
{
|
||||
UITextureMapper& mapper = static_cast<UITextureMapper&>(view);
|
||||
if (mapper.listener_ != nullptr) {
|
||||
mapper.listener_->OnAnimatorStop(view);
|
||||
}
|
||||
}
|
||||
|
||||
UITextureMapper::UITextureMapper()
|
||||
: animator_(&animatorCallback_, this, 0, false),
|
||||
listener_(nullptr),
|
||||
pivot_(0, 0),
|
||||
rotateCur_(0),
|
||||
rotateStart_(0),
|
||||
rotateEnd_(0),
|
||||
scaleCur_(SCALE_CONVERTION),
|
||||
scaleStart_(SCALE_CONVERTION),
|
||||
scaleEnd_(SCALE_CONVERTION),
|
||||
delayTime_(0),
|
||||
easingFunc_(EasingEquation::LinearEaseNone)
|
||||
{
|
||||
AnimatorManager::GetInstance()->Add(&animator_);
|
||||
}
|
||||
|
||||
UITextureMapper::~UITextureMapper()
|
||||
{
|
||||
AnimatorManager::GetInstance()->Remove(&animator_);
|
||||
}
|
||||
|
||||
void UITextureMapper::Start()
|
||||
{
|
||||
rotateStart_ = rotateCur_;
|
||||
scaleStart_ = scaleCur_;
|
||||
animator_.Start();
|
||||
}
|
||||
|
||||
void UITextureMapper::Cancel()
|
||||
{
|
||||
animator_.Stop();
|
||||
}
|
||||
|
||||
void UITextureMapper::Reset()
|
||||
{
|
||||
Invalidate();
|
||||
ResetTransParameter();
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UITextureMapper::Callback()
|
||||
{
|
||||
uint16_t curTime = animator_.GetRunTime();
|
||||
if (curTime >= delayTime_) {
|
||||
uint16_t actualTime = curTime - delayTime_;
|
||||
uint16_t durationTime = animator_.GetTime() - delayTime_;
|
||||
|
||||
if (scaleStart_ != scaleEnd_) {
|
||||
scaleCur_ = easingFunc_(scaleStart_, scaleEnd_, actualTime, durationTime);
|
||||
}
|
||||
float scale = static_cast<float>(scaleCur_) / SCALE_CONVERTION;
|
||||
Scale(Vector2<float>(scale, scale), pivot_);
|
||||
|
||||
if (rotateStart_ != rotateEnd_) {
|
||||
rotateCur_ = easingFunc_(rotateStart_, rotateEnd_, actualTime, durationTime);
|
||||
}
|
||||
Rotate(rotateCur_, pivot_);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+291
@@ -0,0 +1,291 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_time_picker.h"
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
#include "securec.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UITimePicker::UITimePicker()
|
||||
: selectedValue_{0},
|
||||
selectedHour_{0},
|
||||
selectedMinute_{0},
|
||||
selectedSecond_{0},
|
||||
secVisible_(false),
|
||||
setSelectedTime_(nullptr),
|
||||
pickerWidth_(0),
|
||||
itemsHeight_(0),
|
||||
xPos_(0),
|
||||
backgroundFontSize_(0),
|
||||
highlightFontSize_(0),
|
||||
backgroundFontName_(nullptr),
|
||||
highlightFontName_(nullptr),
|
||||
pickerListener_(this),
|
||||
timePickerListener_(nullptr)
|
||||
{
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
if (theme != nullptr) {
|
||||
style_ = &(theme->GetPickerBackgroundStyle());
|
||||
} else {
|
||||
style_ = &(StyleDefault::GetPickerBackgroundStyle());
|
||||
}
|
||||
backgroundFontId_ = style_->font_;
|
||||
backgroundColor_ = style_->textColor_;
|
||||
if (theme != nullptr) {
|
||||
style_ = &(theme->GetPickerHighlightStyle());
|
||||
} else {
|
||||
style_ = &(StyleDefault::GetPickerHighlightStyle());
|
||||
}
|
||||
highlightFontId_ = style_->font_;
|
||||
highlightColor_ = style_->textColor_;
|
||||
|
||||
hourPicker_ = nullptr;
|
||||
minutePicker_ = nullptr;
|
||||
secondPicker_ = nullptr;
|
||||
}
|
||||
|
||||
UITimePicker::~UITimePicker()
|
||||
{
|
||||
DeInitTimePicker();
|
||||
if (backgroundFontName_ != nullptr) {
|
||||
UIFree(backgroundFontName_);
|
||||
backgroundFontName_ = nullptr;
|
||||
}
|
||||
|
||||
if (highlightFontName_ != nullptr) {
|
||||
UIFree(highlightFontName_);
|
||||
highlightFontName_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UITimePicker::InitTimePicker()
|
||||
{
|
||||
xPos_ = 0;
|
||||
if (secVisible_) {
|
||||
pickerWidth_ = GetWidth() / SEC_VISIBLE_COUNT;
|
||||
InitPicker(hourPicker_, TIME_START, HOUR_END);
|
||||
xPos_ = pickerWidth_;
|
||||
InitPicker(minutePicker_, TIME_START, MIN_END);
|
||||
xPos_ *= (SEC_VISIBLE_COUNT - 1);
|
||||
InitPicker(secondPicker_, TIME_START, SEC_END);
|
||||
} else {
|
||||
pickerWidth_ = GetWidth() / SEC_INVISIBLE_COUNT;
|
||||
InitPicker(hourPicker_, TIME_START, HOUR_END);
|
||||
xPos_ = pickerWidth_;
|
||||
InitPicker(minutePicker_, TIME_START, MIN_END);
|
||||
}
|
||||
|
||||
if (setSelectedTime_ == nullptr) {
|
||||
const char* curTime = secVisible_ ? "00:00:00" : "00:00";
|
||||
RefreshSelected(curTime);
|
||||
} else {
|
||||
RefreshSelected(setSelectedTime_);
|
||||
}
|
||||
}
|
||||
|
||||
void UITimePicker::DeInitTimePicker()
|
||||
{
|
||||
DeInitPicker(secondPicker_);
|
||||
DeInitPicker(minutePicker_);
|
||||
DeInitPicker(hourPicker_);
|
||||
}
|
||||
|
||||
void UITimePicker::RefreshTimePicker()
|
||||
{
|
||||
DeInitTimePicker();
|
||||
InitTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::InitPicker(UIPicker*& picker, int16_t start, int16_t end)
|
||||
{
|
||||
picker = new UIPicker();
|
||||
if (picker == nullptr) {
|
||||
GRAPHIC_LOGE("new UIPicker fail");
|
||||
return;
|
||||
}
|
||||
picker->SetPosition(xPos_, 0, pickerWidth_, GetHeight());
|
||||
picker->SetItemHeight(itemsHeight_);
|
||||
picker->SetFontId(backgroundFontId_, highlightFontId_);
|
||||
if ((backgroundFontName_ == nullptr) || (highlightFontName_ == nullptr)) {
|
||||
picker->SetFontId(backgroundFontId_, highlightFontId_);
|
||||
} else {
|
||||
picker->SetBackgroundFont(backgroundFontName_, backgroundFontSize_);
|
||||
picker->SetHighlightFont(highlightFontName_, highlightFontSize_);
|
||||
}
|
||||
picker->SetTextColor(backgroundColor_, highlightColor_);
|
||||
picker->SetValues(start, end);
|
||||
picker->RegisterSelectedListener(&pickerListener_);
|
||||
picker->SetIntercept(false);
|
||||
Add(picker);
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
if (end == HOUR_END) {
|
||||
picker->GetChildrenHead()->SetViewId(HOUR_LIST_NAME);
|
||||
return;
|
||||
} else if (end == MIN_END) {
|
||||
if (minutePicker_->GetChildById(MIN_LIST_NAME) == nullptr) {
|
||||
picker->GetChildrenHead()->SetViewId(MIN_LIST_NAME);
|
||||
return;
|
||||
}
|
||||
}
|
||||
picker->GetChildrenHead()->SetViewId(SEC_LIST_NAME);
|
||||
return;
|
||||
#endif
|
||||
}
|
||||
|
||||
void UITimePicker::DeInitPicker(UIPicker*& picker)
|
||||
{
|
||||
if (picker != nullptr) {
|
||||
Remove(picker);
|
||||
picker->ClearValues();
|
||||
delete picker;
|
||||
picker = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void UITimePicker::TimeSelectedCallback()
|
||||
{
|
||||
uint16_t hourSelect = hourPicker_->GetSelected();
|
||||
uint16_t minSelect = minutePicker_->GetSelected();
|
||||
GetValueByIndex(selectedHour_, BUF_SIZE, hourSelect, TIME_START, HOUR_END);
|
||||
GetValueByIndex(selectedMinute_, BUF_SIZE, minSelect, TIME_START, MIN_END);
|
||||
|
||||
if (secVisible_) {
|
||||
uint16_t secSelect = secondPicker_->GetSelected();
|
||||
GetValueByIndex(selectedSecond_, BUF_SIZE, secSelect, TIME_START, SEC_END);
|
||||
if (sprintf_s(selectedValue_, SELECTED_VALUE_SIZE, "%s:%s:%s",
|
||||
selectedHour_, selectedMinute_, selectedSecond_) < 0) {
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
if (sprintf_s(selectedValue_, SELECTED_VALUE_SIZE, "%s:%s", selectedHour_, selectedMinute_) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (timePickerListener_ != nullptr) {
|
||||
timePickerListener_->OnTimePickerStoped(*this);
|
||||
}
|
||||
}
|
||||
|
||||
void UITimePicker::GetValueByIndex(char* value, uint8_t len, uint16_t index, int16_t start, int16_t end)
|
||||
{
|
||||
if ((value != nullptr) && (index < end - start + 1)) {
|
||||
if (sprintf_s(value, len, "%02d", index) < 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool UITimePicker::SetSelected(const char* value)
|
||||
{
|
||||
setSelectedTime_ = value;
|
||||
return RefreshSelected(value);
|
||||
}
|
||||
|
||||
bool UITimePicker::RefreshSelected(const char* value)
|
||||
{
|
||||
uint32_t hourSelect;
|
||||
uint32_t minSelect;
|
||||
|
||||
if (value == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (secVisible_) {
|
||||
uint32_t secSelect;
|
||||
// 3: three variables
|
||||
if (sscanf_s(value, "%d:%d:%d", &hourSelect, &minSelect, &secSelect) < 3) {
|
||||
return false;
|
||||
}
|
||||
secondPicker_->SetSelected(secSelect);
|
||||
} else {
|
||||
if (sscanf_s(value, "%d:%d", &hourSelect, &minSelect) < 2) { // 2: two variables
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
hourPicker_->SetSelected(hourSelect);
|
||||
minutePicker_->SetSelected(minSelect);
|
||||
return true;
|
||||
}
|
||||
|
||||
void UITimePicker::SetItemHeight(int16_t height)
|
||||
{
|
||||
itemsHeight_ = height;
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::EnableSecond(bool state)
|
||||
{
|
||||
secVisible_ = state;
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::SetTextStyle(uint8_t backgroundFontId, uint8_t highlightFontId,
|
||||
ColorType backgroundColor, ColorType highlightColor)
|
||||
{
|
||||
highlightFontId_ = highlightFontId;
|
||||
if (highlightFontName_ != nullptr) {
|
||||
UIFree(highlightFontName_);
|
||||
highlightFontName_ = nullptr;
|
||||
}
|
||||
|
||||
backgroundFontId_ = backgroundFontId;
|
||||
if (backgroundFontName_ != nullptr) {
|
||||
UIFree(backgroundFontName_);
|
||||
backgroundFontName_ = nullptr;
|
||||
}
|
||||
|
||||
highlightColor_ = highlightColor;
|
||||
backgroundColor_ = backgroundColor;
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::SetTextColor(ColorType backgroundColor, ColorType highlightColor)
|
||||
{
|
||||
backgroundColor_ = backgroundColor;
|
||||
highlightColor_ = highlightColor;
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::SetBackgroundFont(const char* name, uint8_t size)
|
||||
{
|
||||
Text::SetFont(name, size, backgroundFontName_, backgroundFontSize_);
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::SetHighlightFont(const char* name, uint8_t size)
|
||||
{
|
||||
Text::SetFont(name, size, highlightFontName_, highlightFontSize_);
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::SetWidth(int16_t width)
|
||||
{
|
||||
UIView::SetWidth(width);
|
||||
RefreshTimePicker();
|
||||
}
|
||||
|
||||
void UITimePicker::SetHeight(int16_t height)
|
||||
{
|
||||
UIView::SetHeight(height);
|
||||
RefreshTimePicker();
|
||||
}
|
||||
}
|
||||
Executable
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_toggle_button.h"
|
||||
#include "common/image.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIToggleButton::UIToggleButton() : width_(DEFAULT_HOT_WIDTH), height_(DEFAULT_HOT_WIDTH),
|
||||
corner_(DEFAULT_CORNER_RADIUS), radius_(DEFAULT_CORNER_RADIUS - DEAFULT_RADIUS_DIFF),
|
||||
rectWidth_(DEFAULT_WIDTH)
|
||||
{
|
||||
image_[UNSELECTED].SetSrc("");
|
||||
image_[SELECTED].SetSrc("");
|
||||
Resize(width_, height_);
|
||||
}
|
||||
|
||||
void UIToggleButton::SetState(bool state)
|
||||
{
|
||||
if (state) {
|
||||
UICheckBox::SetState(SELECTED);
|
||||
} else {
|
||||
UICheckBox::SetState(UNSELECTED);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
|
||||
void UIToggleButton::CalculateSize()
|
||||
{
|
||||
int16_t width = GetWidth();
|
||||
int16_t height = GetHeight();
|
||||
if ((width_ == width) && (height_ == height)) {
|
||||
return;
|
||||
}
|
||||
width_ = width;
|
||||
height_ = height;
|
||||
int16_t minValue = (width_ > height_) ? height_ : width_;
|
||||
corner_ = DEFAULT_CORNER_RADIUS * minValue / DEFAULT_HOT_HEIGHT;
|
||||
int16_t radiusDiff = DEAFULT_RADIUS_DIFF * minValue / DEFAULT_HOT_WIDTH;
|
||||
radius_ = corner_ - radiusDiff;
|
||||
rectWidth_ = DEFAULT_WIDTH * minValue / DEFAULT_HOT_WIDTH;
|
||||
}
|
||||
|
||||
void UIToggleButton::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
if ((image_[SELECTED].GetSrcType() != IMG_SRC_UNKNOWN) && (image_[UNSELECTED].GetSrcType() != IMG_SRC_UNKNOWN)) {
|
||||
UICheckBox::OnDraw(invalidatedArea);
|
||||
} else {
|
||||
CalculateSize();
|
||||
DrawRect::Draw(GetRect(), invalidatedArea, *style_, opaScale_);
|
||||
Rect contentRect = GetContentRect();
|
||||
int16_t dx = (width_ - rectWidth_) >> 1;
|
||||
int16_t dy = (height_ >> 1) - corner_;
|
||||
int16_t x = contentRect.GetX() + dx;
|
||||
int16_t y = contentRect.GetY() + dy;
|
||||
Rect rectMid;
|
||||
rectMid.SetRect(x, y, x + rectWidth_, y + (corner_ << 1) + 1);
|
||||
Rect trunc = invalidatedArea;
|
||||
bool isIntersect = trunc.Intersect(trunc, contentRect);
|
||||
switch (state_) {
|
||||
case SELECTED: {
|
||||
Style styleSelect = StyleDefault::GetBackgroundTransparentStyle();
|
||||
styleSelect.borderRadius_ = corner_;
|
||||
styleSelect.bgColor_ = Color::GetColorFromRGB(DEFAULT_BG_RED, DEFAULT_BG_GREEN, DEFAULT_BG_BLUE);
|
||||
styleSelect.bgOpa_ = OPA_OPAQUE;
|
||||
if (isIntersect) {
|
||||
DrawRect::Draw(rectMid, trunc, styleSelect, opaScale_);
|
||||
}
|
||||
ArcInfo arcInfoRight = {
|
||||
{ static_cast<int16_t>(x + rectWidth_ - corner_), static_cast<int16_t>(y + corner_) }, { 0 },
|
||||
radius_, 0, CIRCLE_IN_DEGREE, nullptr
|
||||
};
|
||||
styleSelect.bgColor_ = Color::White();
|
||||
styleSelect.lineWidth_ = radius_;
|
||||
styleSelect.lineColor_ = Color::White();
|
||||
if (isIntersect) {
|
||||
DrawArc::GetInstance()->Draw(arcInfoRight, trunc, styleSelect, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case UNSELECTED: {
|
||||
Style styleUnSelect = StyleDefault::GetBackgroundTransparentStyle();
|
||||
styleUnSelect.bgColor_ = Color::White();
|
||||
styleUnSelect.bgOpa_ = DEFAULT_UNSELECTED_OPA;
|
||||
styleUnSelect.borderRadius_ = corner_;
|
||||
if (isIntersect) {
|
||||
DrawRect::Draw(rectMid, trunc, styleUnSelect, opaScale_);
|
||||
}
|
||||
ArcInfo arcInfoLeft = {
|
||||
{ static_cast<int16_t>(x + corner_), static_cast<int16_t>(y + corner_) }, { 0 }, radius_, 0,
|
||||
CIRCLE_IN_DEGREE, nullptr
|
||||
};
|
||||
styleUnSelect.lineColor_ = Color::White();
|
||||
styleUnSelect.lineWidth_ = radius_;
|
||||
if (isIntersect) {
|
||||
DrawArc::GetInstance()->Draw(arcInfoLeft, trunc, styleUnSelect, OPA_OPAQUE, CapType::CAP_NONE);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+719
@@ -0,0 +1,719 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_video.h"
|
||||
#include "securec.h"
|
||||
|
||||
#ifndef VERSION_LITE
|
||||
namespace OHOS {
|
||||
UIVideo::UIVideo()
|
||||
{
|
||||
SetTouchable(true);
|
||||
SetOnTouchListener(this);
|
||||
}
|
||||
|
||||
UIVideo::~UIVideo()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
videoPlayer_->Stop();
|
||||
videoPlayer_->Reset();
|
||||
videoPlayer_->Release();
|
||||
}
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
AnimatorManager::GetInstance()->Remove(sliderAnimator_);
|
||||
delete sliderAnimator_;
|
||||
sliderAnimator_ = nullptr;
|
||||
}
|
||||
if (surfaceView_ != nullptr) {
|
||||
delete surfaceView_;
|
||||
surfaceView_ = nullptr;
|
||||
}
|
||||
DeleteController();
|
||||
}
|
||||
|
||||
bool UIVideo::SetSrc(const char* source)
|
||||
{
|
||||
if (source == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
InitVideo();
|
||||
src_ = source;
|
||||
std::string uri(source);
|
||||
std::map<std::string, std::string> header;
|
||||
Source videoSource(uri, header);
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->SetSource(videoSource);
|
||||
if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::Prepare()
|
||||
{
|
||||
if (src_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (videoPlayer_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int32_t ret = videoPlayer_->Prepare();
|
||||
if (ret != 0) {
|
||||
return false;
|
||||
}
|
||||
SetVolume(DEFAULT_VOLUME, DEFAULT_VOLUME);
|
||||
videoPlayer_->GetDuration(duration_);
|
||||
if (totalTimeLabel_ != nullptr) {
|
||||
char timer[10] = {0}; // 10:timer length
|
||||
if (!GetTimerFromMSecond(duration_, timer, sizeof(timer))) {
|
||||
return false;
|
||||
}
|
||||
totalTimeLabel_->SetText(&timer[0]);
|
||||
}
|
||||
|
||||
if (titleLabel_ != nullptr) {
|
||||
const char* fileName = nullptr;
|
||||
fileName = strrchr(src_, '/');
|
||||
if (fileName != nullptr) {
|
||||
titleLabel_->SetText(fileName + 1);
|
||||
}
|
||||
}
|
||||
if (sliderAnimatorCallback_) {
|
||||
sliderAnimatorCallback_->SetDuration(duration_);
|
||||
}
|
||||
SetSurfaceInfo();
|
||||
|
||||
playerListener_ = std::make_shared<PlayerListener>();
|
||||
playerListener_->SetVideoPlayer(this);
|
||||
videoPlayer_->SetPlayerCallback(playerListener_);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIVideo::Play()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->Play();
|
||||
if (ret == 0) {
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
sliderAnimator_->Start();
|
||||
}
|
||||
if (pauseButton_ != nullptr) {
|
||||
pauseButton_->SetVisible(false);
|
||||
}
|
||||
if (playButton_ != nullptr) {
|
||||
playButton_->SetState(true);
|
||||
}
|
||||
if (surfaceView_ != nullptr) {
|
||||
surfaceView_->SetVisible(true);
|
||||
}
|
||||
if (videoPlayerListener_ != nullptr) {
|
||||
videoPlayerListener_->OnPlaybackPlay();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::IsPlaying()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
return videoPlayer_->IsPlaying();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::Pause()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->Pause();
|
||||
if (ret == 0) {
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
sliderAnimator_->Pause();
|
||||
}
|
||||
if (playButton_ != nullptr) {
|
||||
playButton_->SetState(false);
|
||||
}
|
||||
if (pauseButton_ != nullptr) {
|
||||
pauseButton_->SetVisible(true);
|
||||
}
|
||||
if (videoPlayerListener_ != nullptr) {
|
||||
videoPlayerListener_->OnPlaybackPause();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::Stop()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->Stop();
|
||||
if (ret == 0) {
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
sliderAnimator_->Stop();
|
||||
}
|
||||
if (playSlider_ != nullptr) {
|
||||
playSlider_->SetValue(0);
|
||||
}
|
||||
if (currentTimeLabel_ != nullptr) {
|
||||
currentTimeLabel_->SetText("00:00:00");
|
||||
}
|
||||
if (totalTimeLabel_ != nullptr) {
|
||||
totalTimeLabel_->SetText("00:00:00");
|
||||
}
|
||||
if (playButton_ != nullptr) {
|
||||
playButton_->SetState(false);
|
||||
}
|
||||
if (pauseButton_ != nullptr) {
|
||||
pauseButton_->SetVisible(true);
|
||||
}
|
||||
if (surfaceView_ != nullptr) {
|
||||
surfaceView_->SetVisible(false);
|
||||
}
|
||||
if (videoPlayerListener_ != nullptr) {
|
||||
videoPlayerListener_->OnPlaybackStop();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::Rewind(int64_t mSeconds)
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->Rewind(mSeconds, PLAYER_SEEK_PREVIOUS_SYNC);
|
||||
if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::SetVolume(float leftVolume, float rightVolume)
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->SetVolume(leftVolume * MAX_VOLUME, rightVolume * MAX_VOLUME);
|
||||
if (ret == 0) {
|
||||
leftVolumeValue_ = leftVolume;
|
||||
rightVolumeValue_ = rightVolume;
|
||||
if (volumeButton_ != nullptr) {
|
||||
if ((leftVolumeValue_ == 0) && (rightVolumeValue_ == 0)) {
|
||||
volumeButton_->SetState(true);
|
||||
} else {
|
||||
volumeButton_->SetState(false);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::IsSingleLooping()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
return videoPlayer_->IsSingleLooping();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::GetCurrentTime(int64_t& time)
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->GetCurrentTime(time);
|
||||
if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::GetDuration(int64_t& durationMs)
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->GetDuration(durationMs);
|
||||
if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIVideo::SetVideoPlayerListener(VideoPlayerListener* listener)
|
||||
{
|
||||
videoPlayerListener_ = listener;
|
||||
|
||||
if (playerListener_ != nullptr) {
|
||||
playerListener_->SetVideoPlayerListerner(videoPlayerListener_);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIVideo::Reset()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
sliderAnimator_->Stop();
|
||||
}
|
||||
if (playSlider_ != nullptr) {
|
||||
playSlider_->SetValue(0);
|
||||
}
|
||||
if (currentTimeLabel_ != nullptr) {
|
||||
currentTimeLabel_->SetText("00:00");
|
||||
}
|
||||
if (totalTimeLabel_ != nullptr) {
|
||||
totalTimeLabel_->SetText("00:00");
|
||||
}
|
||||
if (pauseButton_ != nullptr) {
|
||||
pauseButton_->SetVisible(true);
|
||||
}
|
||||
if (playButton_ != nullptr) {
|
||||
playButton_->SetState(false);
|
||||
}
|
||||
int32_t ret = videoPlayer_->Reset();
|
||||
if (ret == 0) {
|
||||
videoPlayer_->Release();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIVideo::EnableSingleLooping(bool loop)
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
int32_t ret = videoPlayer_->EnableSingleLooping(loop);
|
||||
if (ret == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIVideo::ShowController(bool show)
|
||||
{
|
||||
if (controllerGroup_ != nullptr) {
|
||||
if (controllerGroup_->IsVisible() != show) {
|
||||
controllerGroup_->SetVisible(show);
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::InitVideo()
|
||||
{
|
||||
if (videoPlayer_ == nullptr) {
|
||||
videoPlayer_ = std::make_shared<Player>();
|
||||
}
|
||||
|
||||
InitControllerLabel();
|
||||
InitControllerButton();
|
||||
InitControllerSlider();
|
||||
|
||||
if (surfaceView_ == nullptr) {
|
||||
surfaceView_ = new UISurfaceView();
|
||||
if (surfaceView_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UISurfaceView fail");
|
||||
return;
|
||||
}
|
||||
surfaceView_->SetPosition(0, 0);
|
||||
surfaceView_->SetWidth(DEFAULT_VIEW_WIDTH);
|
||||
surfaceView_->SetHeight(DEFAULT_VIEW_HEIGHT);
|
||||
Add(surfaceView_);
|
||||
}
|
||||
if (controllerGroup_ == nullptr) {
|
||||
controllerGroup_ = new UIViewGroup();
|
||||
if (controllerGroup_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIViewGroup fail");
|
||||
return;
|
||||
}
|
||||
controllerGroup_->SetPosition(0, 0, DEFAULT_VIEW_WIDTH, DEFAULT_VIEW_HEIGHT);
|
||||
controllerGroup_->SetStyle(STYLE_BACKGROUND_OPA, 0);
|
||||
controllerGroup_->Add(titleLabel_);
|
||||
controllerGroup_->Add(totalTimeLabel_);
|
||||
controllerGroup_->Add(currentTimeLabel_);
|
||||
controllerGroup_->Add(playSlider_);
|
||||
controllerGroup_->Add(volumeButton_);
|
||||
controllerGroup_->Add(playButton_);
|
||||
controllerGroup_->Add(pauseButton_);
|
||||
Add(controllerGroup_);
|
||||
}
|
||||
if (sliderAnimatorCallback_ == nullptr) {
|
||||
sliderAnimatorCallback_ = new SliderAnimatorCallback(this, playSlider_, currentTimeLabel_);
|
||||
if (sliderAnimatorCallback_ == nullptr) {
|
||||
GRAPHIC_LOGE("new SliderAnimatorCallback fail");
|
||||
return;
|
||||
}
|
||||
sliderAnimatorCallback_->SetPlayButton(playButton_);
|
||||
}
|
||||
if (sliderAnimator_ == nullptr) {
|
||||
sliderAnimator_ = new Animator(sliderAnimatorCallback_, this, 0, true);
|
||||
if (sliderAnimator_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Animator fail");
|
||||
return;
|
||||
}
|
||||
AnimatorManager::GetInstance()->Add(sliderAnimator_);
|
||||
sliderAnimatorCallback_->SetSliderAnimator(sliderAnimator_);
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::InitControllerLabel()
|
||||
{
|
||||
if (titleLabel_ == nullptr) {
|
||||
titleLabel_ = new UILabel();
|
||||
if (titleLabel_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
titleLabel_->SetPosition(322, 28, 316, 29); // 322:pos x, 28:pos y, 316:width, 29:height
|
||||
titleLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER,
|
||||
UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
|
||||
titleLabel_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, 20); // 20:font size
|
||||
titleLabel_->SetText("title title");
|
||||
titleLabel_->SetTextColor(Color::White());
|
||||
}
|
||||
|
||||
if (totalTimeLabel_ == nullptr) {
|
||||
totalTimeLabel_ = new UILabel();
|
||||
if (totalTimeLabel_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
// 580:pos x, 56:pos y offset
|
||||
totalTimeLabel_->SetPosition(580, DEFAULT_VIEW_HEIGHT - 56, TIME_LABEL_WIDTH, TIME_LABEL_HEIGHT);
|
||||
totalTimeLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_RIGHT,
|
||||
UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
|
||||
totalTimeLabel_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, FONT_DEFAULT_SIZE);
|
||||
totalTimeLabel_->SetTextColor(Color::White());
|
||||
totalTimeLabel_->SetText("00:00:00");
|
||||
}
|
||||
|
||||
if (currentTimeLabel_ == nullptr) {
|
||||
currentTimeLabel_ = new UILabel();
|
||||
if (currentTimeLabel_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UILabel fail");
|
||||
return;
|
||||
}
|
||||
// 80:pos x, 56:pos y offset
|
||||
currentTimeLabel_->SetPosition(80, DEFAULT_VIEW_HEIGHT - 56, TIME_LABEL_WIDTH, TIME_LABEL_HEIGHT);
|
||||
currentTimeLabel_->SetAlign(UITextLanguageAlignment::TEXT_ALIGNMENT_LEFT,
|
||||
UITextLanguageAlignment::TEXT_ALIGNMENT_CENTER);
|
||||
currentTimeLabel_->SetStyle(STYLE_BACKGROUND_COLOR, Color::Red().full);
|
||||
currentTimeLabel_->SetFont(DEFAULT_VECTOR_FONT_FILENAME, FONT_DEFAULT_SIZE);
|
||||
currentTimeLabel_->SetText("00:00:00");
|
||||
currentTimeLabel_->SetTextColor(Color::White());
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::InitControllerButton()
|
||||
{
|
||||
if (playButton_ == nullptr) {
|
||||
playButton_ = new UIToggleButton();
|
||||
if (playButton_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIToggleButton fail");
|
||||
return;
|
||||
}
|
||||
// 24:pox x, 88:pos y offset
|
||||
playButton_->SetPosition(24, DEFAULT_VIEW_HEIGHT - 88, TOGGLE_BUTTON_WIDTH, TOGGLE_BUTTON_HEIGHT);
|
||||
playButton_->SetImages(MEDIA_IMAGE_PAUSE, MEDIA_IMAGE_PLAY);
|
||||
playButton_->SetState(true);
|
||||
playButton_->SetOnClickListener(this);
|
||||
}
|
||||
|
||||
if (pauseButton_ == nullptr) {
|
||||
pauseButton_ = new UIToggleButton();
|
||||
if (pauseButton_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIToggleButton fail");
|
||||
return;
|
||||
}
|
||||
// 448:pox x, 208:pos y 2:double width 2:double height
|
||||
pauseButton_->SetPosition(448, 208, 2 * TOGGLE_BUTTON_WIDTH, 2 * TOGGLE_BUTTON_HEIGHT);
|
||||
pauseButton_->SetImages(MEDIA_IMAGE_PLAY_CENTER, MEDIA_IMAGE_PLAY_CENTER);
|
||||
pauseButton_->SetVisible(false);
|
||||
pauseButton_->SetOnClickListener(this);
|
||||
}
|
||||
|
||||
if (volumeButton_ == nullptr) {
|
||||
volumeButton_ = new UIToggleButton();
|
||||
if (volumeButton_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UIToggleButton fail");
|
||||
return;
|
||||
}
|
||||
// 56:pox x offset, 88:pos y offset
|
||||
volumeButton_->SetPosition(DEFAULT_VIEW_WIDTH - 56, DEFAULT_VIEW_HEIGHT - 88, TOGGLE_BUTTON_WIDTH,
|
||||
TOGGLE_BUTTON_HEIGHT);
|
||||
volumeButton_->SetImages(MEDIA_IMAGE_MUTE, MEDIA_IMAGE_VOLUME);
|
||||
volumeButton_->SetOnClickListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::OnVideoComplete()
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
videoPlayer_->Stop();
|
||||
completeFlag_ = true;
|
||||
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
sliderAnimator_->Stop();
|
||||
}
|
||||
if (playSlider_ != nullptr) {
|
||||
playSlider_->SetValue(playSlider_->GetRangeMax());
|
||||
}
|
||||
if (playButton_ != nullptr) {
|
||||
playButton_->SetState(false);
|
||||
}
|
||||
if (pauseButton_ != nullptr) {
|
||||
pauseButton_->SetVisible(true);
|
||||
}
|
||||
if (controllerGroup_ != nullptr) {
|
||||
controllerGroup_->SetVisible(true);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::InitControllerSlider()
|
||||
{
|
||||
if (playSlider_ == nullptr) {
|
||||
playSlider_ = new UISlider();
|
||||
if (playSlider_ == nullptr) {
|
||||
GRAPHIC_LOGE("new UISlider fail");
|
||||
return;
|
||||
}
|
||||
// 80:pos x, 74:width offset, 5:multiply, 6:divide, 4:height
|
||||
playSlider_->SetPosition(80, DEFAULT_VIEW_HEIGHT - 74, DEFAULT_VIEW_WIDTH * 5 / 6, 4);
|
||||
playSlider_->SetValidHeight(4); // 4:height
|
||||
playSlider_->SetValidWidth(DEFAULT_VIEW_WIDTH * 5 / 6); // 5:multiply, 6:divide
|
||||
playSlider_->SetRange(100, 0); // 100:range max
|
||||
playSlider_->SetValue(0);
|
||||
playSlider_->SetKnobWidth(KNOB_WIDTH);
|
||||
playSlider_->SetSliderRadius(5, 5, KNOB_WIDTH / 2); // 5:background radius, 5:foreground radius, 2:half
|
||||
playSlider_->SetKnobStyle(STYLE_BACKGROUND_COLOR, Color::White().full);
|
||||
playSlider_->SetBackgroundStyle(STYLE_BACKGROUND_COLOR, 0x1A888888); // 0x1A888888:slider background color
|
||||
playSlider_->SetBackgroundStyle(STYLE_BACKGROUND_OPA, 90); // 90:background opa
|
||||
playSlider_->SetDirection(UISlider::Direction::DIR_LEFT_TO_RIGHT);
|
||||
playSlider_->SetSliderEventListener(this);
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::DeleteController()
|
||||
{
|
||||
if (controllerGroup_ != nullptr) {
|
||||
controllerGroup_->RemoveAll();
|
||||
delete controllerGroup_;
|
||||
controllerGroup_ = nullptr;
|
||||
}
|
||||
if (playButton_ != nullptr) {
|
||||
delete playButton_;
|
||||
playButton_ = nullptr;
|
||||
}
|
||||
if (pauseButton_ != nullptr) {
|
||||
delete pauseButton_;
|
||||
pauseButton_ = nullptr;
|
||||
}
|
||||
if (volumeButton_ != nullptr) {
|
||||
delete volumeButton_;
|
||||
volumeButton_ = nullptr;
|
||||
}
|
||||
if (playSlider_ != nullptr) {
|
||||
delete playSlider_;
|
||||
playSlider_ = nullptr;
|
||||
}
|
||||
if (sliderAnimatorCallback_ != nullptr) {
|
||||
delete sliderAnimatorCallback_;
|
||||
sliderAnimatorCallback_ = nullptr;
|
||||
}
|
||||
if (titleLabel_ != nullptr) {
|
||||
delete titleLabel_;
|
||||
titleLabel_ = nullptr;
|
||||
}
|
||||
if (totalTimeLabel_ != nullptr) {
|
||||
delete totalTimeLabel_;
|
||||
totalTimeLabel_ = nullptr;
|
||||
}
|
||||
if (currentTimeLabel_ != nullptr) {
|
||||
delete currentTimeLabel_;
|
||||
currentTimeLabel_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool UIVideo::OnClick(UIView& view, const ClickEvent& event)
|
||||
{
|
||||
if (videoPlayer_ == nullptr) {
|
||||
return true;
|
||||
}
|
||||
if (&view == playButton_) {
|
||||
if (completeFlag_) {
|
||||
completeFlag_ = false;
|
||||
if (pauseButton_ != nullptr) {
|
||||
pauseButton_->SetVisible(true);
|
||||
}
|
||||
if (controllerGroup_ != nullptr) {
|
||||
controllerGroup_->SetVisible(true);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((sliderAnimatorCallback_ != nullptr) && (pauseButton_ != nullptr) && (playButton_ != nullptr)) {
|
||||
sliderAnimatorCallback_->ResetTickTime();
|
||||
if (playButton_->GetState()) {
|
||||
Play();
|
||||
pauseButton_->SetVisible(false);
|
||||
} else {
|
||||
Pause();
|
||||
pauseButton_->SetVisible(true);
|
||||
}
|
||||
pauseButton_->Invalidate();
|
||||
}
|
||||
} else if (&view == pauseButton_) {
|
||||
if ((pauseButton_ != nullptr) && pauseButton_->IsVisible()) {
|
||||
pauseButton_->SetVisible(false);
|
||||
Play();
|
||||
}
|
||||
} else if (&view == volumeButton_) {
|
||||
if ((volumeButton_ != nullptr) && volumeButton_->GetState()) {
|
||||
videoPlayer_->SetVolume(0, 0);
|
||||
} else {
|
||||
SetVolume(leftVolumeValue_, rightVolumeValue_);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool UIVideo::OnPress(UIView& view, const PressEvent& event)
|
||||
{
|
||||
if (sliderAnimatorCallback_ != nullptr) {
|
||||
sliderAnimatorCallback_->ResetTickTime();
|
||||
if (controllerGroup_ != nullptr) {
|
||||
controllerGroup_->SetVisible(true);
|
||||
}
|
||||
Invalidate();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIVideo::OnChange(int32_t progress)
|
||||
{
|
||||
if (videoPlayer_ != nullptr) {
|
||||
if (sliderAnimatorCallback_ != nullptr) {
|
||||
sliderAnimatorCallback_->ResetTickTime();
|
||||
}
|
||||
int64_t currentValue = progress * duration_ / 100; // 100:percent
|
||||
if (currentTimeLabel_ != nullptr) {
|
||||
char timer[10] = {0}; // 10:timer length
|
||||
if (!GetTimerFromMSecond(currentValue, timer, sizeof(timer))) {
|
||||
return;
|
||||
}
|
||||
currentTimeLabel_->SetText(&timer[0]);
|
||||
}
|
||||
videoPlayer_->Rewind(currentValue, PLAYER_SEEK_PREVIOUS_SYNC);
|
||||
}
|
||||
}
|
||||
|
||||
void UIVideo::SetSurfaceInfo()
|
||||
{
|
||||
if (videoPlayer_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
int32_t width = 0;
|
||||
int32_t height = 0;
|
||||
videoPlayer_->GetVideoWidth(width);
|
||||
videoPlayer_->GetVideoHeight(height);
|
||||
|
||||
if ((width <= 0) || (height <= 0)) {
|
||||
videoPlayer_->Reset();
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t viewWidth = GetWidth();
|
||||
int16_t viewHeight = GetHeight();
|
||||
if ((viewWidth <= 0) || (viewHeight <= 0)) {
|
||||
videoPlayer_->Reset();
|
||||
return;
|
||||
}
|
||||
float ratioX = static_cast<float>(width) / viewWidth;
|
||||
float ratioY = static_cast<float>(height) / viewHeight;
|
||||
uint16_t surfaceViewWidth;
|
||||
uint16_t surfaceViewHeight;
|
||||
uint16_t surfaceViewPositionX = 0;
|
||||
uint16_t surfaceViewPositionY = 0;
|
||||
if (ratioX > ratioY) {
|
||||
surfaceViewWidth = viewWidth;
|
||||
surfaceViewHeight = height / ratioX;
|
||||
surfaceViewPositionY = (viewHeight - surfaceViewHeight) / 2; // 2:half
|
||||
} else {
|
||||
surfaceViewWidth = width / ratioY;
|
||||
surfaceViewHeight = viewHeight;
|
||||
surfaceViewPositionX = (viewWidth - surfaceViewWidth) / 2; // 2:half
|
||||
}
|
||||
if (surfaceView_ != nullptr) {
|
||||
surfaceView_->SetPosition(surfaceViewPositionX, surfaceViewPositionY);
|
||||
surfaceView_->SetWidth(surfaceViewWidth - 1);
|
||||
surfaceView_->SetHeight(surfaceViewHeight);
|
||||
videoPlayer_->SetVideoSurface(surfaceView_->GetSurface());
|
||||
}
|
||||
}
|
||||
|
||||
bool UIVideo::GetTimerFromMSecond(int64_t currentTime, char* timer, int32_t len)
|
||||
{
|
||||
int64_t currentSecond = currentTime / 1000; // 1000:millisecond
|
||||
int32_t second = currentSecond % 60; // 60:second
|
||||
int32_t minute = (currentSecond / 60) % 60; // 60:minute 60:second
|
||||
int32_t hour = (currentSecond / 60) / 60; // 60:minute 60:second
|
||||
int32_t ret = 0;
|
||||
ret = sprintf_s(timer, len, "%02d:%02d:%02d", hour, minute, second);
|
||||
if (ret < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIVideo::SliderAnimatorCallback::Callback(UIView* view)
|
||||
{
|
||||
if (video_ != nullptr) {
|
||||
int64_t currentTime = 0;
|
||||
video_->GetCurrentTime(currentTime);
|
||||
if (timeLabel_ != nullptr) {
|
||||
char timer[10] = {0}; // 10:timer length
|
||||
if (!video_->GetTimerFromMSecond(currentTime, timer, sizeof(timer))) {
|
||||
return;
|
||||
}
|
||||
timeLabel_->SetText(&timer[0]);
|
||||
timeLabel_->Invalidate();
|
||||
}
|
||||
if (slider_ != nullptr) {
|
||||
int64_t curPosition = currentTime * slider_->GetRangeMax() / duration_;
|
||||
slider_->SetValue(curPosition);
|
||||
slider_->Invalidate();
|
||||
}
|
||||
|
||||
uint32_t runTime = 0;
|
||||
if (sliderAnimator_ != nullptr) {
|
||||
runTime = sliderAnimator_->GetRunTime();
|
||||
}
|
||||
if ((runTime > tickCount_) && (runTime - tickCount_ >= HIDE_MILLI_SECOND)) {
|
||||
video_->ShowController(false);
|
||||
tickCount_ = runTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // VERSION_LITE
|
||||
Executable
+785
@@ -0,0 +1,785 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_view.h"
|
||||
#include "components/root_view.h"
|
||||
#include "core/render_manager.h"
|
||||
#include "dock/focus_manager.h"
|
||||
#include "draw/draw_rect.h"
|
||||
#include "graphic_log.h"
|
||||
#include "themes/theme_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIView::UIView()
|
||||
: touchable_(false),
|
||||
visible_(true),
|
||||
draggable_(false),
|
||||
dragParentInstead_(true),
|
||||
isViewGroup_(false),
|
||||
needRedraw_(false),
|
||||
styleAllocFlag_(false),
|
||||
isIntercept_(true),
|
||||
opaScale_(OPA_OPAQUE),
|
||||
index_(0),
|
||||
id_(nullptr),
|
||||
parent_(nullptr),
|
||||
nextSibling_(nullptr),
|
||||
style_(nullptr),
|
||||
transMap_(nullptr),
|
||||
onClickListener_(nullptr),
|
||||
onLongPressListener_(nullptr),
|
||||
onDragListener_(nullptr),
|
||||
onTouchListener_(nullptr),
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
onRotateListener_(nullptr),
|
||||
#endif
|
||||
viewExtraMsg_(nullptr),
|
||||
rect_(0, 0, 0, 0),
|
||||
visibleRect_(nullptr)
|
||||
{
|
||||
SetupThemeStyles();
|
||||
}
|
||||
|
||||
UIView::~UIView()
|
||||
{
|
||||
if (transMap_ != nullptr) {
|
||||
delete transMap_;
|
||||
transMap_ = nullptr;
|
||||
}
|
||||
if (visibleRect_ != nullptr) {
|
||||
delete visibleRect_;
|
||||
visibleRect_ = nullptr;
|
||||
}
|
||||
if (styleAllocFlag_) {
|
||||
delete style_;
|
||||
style_ = nullptr;
|
||||
styleAllocFlag_ = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool UIView::OnPreDraw(Rect& invalidatedArea) const
|
||||
{
|
||||
Rect rect(GetRect());
|
||||
int16_t r = style_->borderRadius_;
|
||||
if (r == COORD_MAX) {
|
||||
return true;
|
||||
}
|
||||
if (r != 0) {
|
||||
r = ((r & 0x1) == 0) ? (r >> 1) : ((r + 1) >> 1);
|
||||
rect.SetLeft(rect.GetX() + r);
|
||||
rect.SetWidth(rect.GetWidth() - r);
|
||||
rect.SetTop(rect.GetY() + r);
|
||||
rect.SetHeight(rect.GetHeight() - r);
|
||||
}
|
||||
if (rect.IsContains(invalidatedArea)) {
|
||||
return true;
|
||||
}
|
||||
invalidatedArea.Intersect(invalidatedArea, rect);
|
||||
return false;
|
||||
}
|
||||
|
||||
void UIView::OnDraw(const Rect& invalidatedArea)
|
||||
{
|
||||
uint8_t opa = GetMixOpaScale();
|
||||
DrawRect::Draw(GetOrigRect(), invalidatedArea, *style_, opa);
|
||||
}
|
||||
|
||||
void UIView::SetupThemeStyles()
|
||||
{
|
||||
Theme* theme = ThemeManager::GetInstance().GetCurrent();
|
||||
if (theme != nullptr) {
|
||||
style_ = &(theme->GetMainStyle());
|
||||
} else {
|
||||
style_ = &(StyleDefault::GetDefaultStyle());
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::SetStyle(Style& style)
|
||||
{
|
||||
if (styleAllocFlag_) {
|
||||
delete style_;
|
||||
styleAllocFlag_ = false;
|
||||
}
|
||||
style_ = &style;
|
||||
}
|
||||
|
||||
void UIView::SetStyle(uint8_t key, int64_t value)
|
||||
{
|
||||
if (!styleAllocFlag_) {
|
||||
style_ = new Style(*style_);
|
||||
if (style_ == nullptr) {
|
||||
GRAPHIC_LOGE("new Style fail");
|
||||
return;
|
||||
}
|
||||
styleAllocFlag_ = true;
|
||||
}
|
||||
int16_t width = GetWidth();
|
||||
int16_t height = GetHeight();
|
||||
style_->SetStyle(key, value);
|
||||
switch (key) {
|
||||
case STYLE_BORDER_WIDTH: {
|
||||
SetWidth(width);
|
||||
SetHeight(height);
|
||||
break;
|
||||
}
|
||||
case STYLE_PADDING_LEFT:
|
||||
case STYLE_PADDING_RIGHT: {
|
||||
SetWidth(width);
|
||||
break;
|
||||
}
|
||||
case STYLE_PADDING_TOP:
|
||||
case STYLE_PADDING_BOTTOM: {
|
||||
SetHeight(height);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::Rotate(int16_t angle, const Vector2<float>& pivot)
|
||||
{
|
||||
if (transMap_ == nullptr) {
|
||||
ReMeasure();
|
||||
transMap_ = new TransformMap();
|
||||
if (transMap_ == nullptr) {
|
||||
GRAPHIC_LOGE("new TransformMap fail");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Rect joinRect = transMap_->GetBoxRect();
|
||||
transMap_->SetTransMapRect(GetOrigRect());
|
||||
transMap_->Rotate(angle, pivot);
|
||||
joinRect.Join(joinRect, transMap_->GetBoxRect());
|
||||
joinRect.Join(joinRect, GetOrigRect());
|
||||
InvalidateRect(joinRect);
|
||||
}
|
||||
|
||||
void UIView::Scale(const Vector2<float>& scale, const Vector2<float>& pivot)
|
||||
{
|
||||
if (transMap_ == nullptr) {
|
||||
ReMeasure();
|
||||
transMap_ = new TransformMap();
|
||||
if (transMap_ == nullptr) {
|
||||
GRAPHIC_LOGE("new TransformMap fail");
|
||||
return;
|
||||
}
|
||||
}
|
||||
Rect joinRect = transMap_->GetBoxRect();
|
||||
transMap_->SetTransMapRect(GetOrigRect());
|
||||
transMap_->Scale(scale, pivot);
|
||||
joinRect.Join(joinRect, transMap_->GetBoxRect());
|
||||
joinRect.Join(joinRect, GetOrigRect());
|
||||
InvalidateRect(joinRect);
|
||||
}
|
||||
|
||||
void UIView::Translate(const Vector2<int16_t>& trans)
|
||||
{
|
||||
if (transMap_ == nullptr) {
|
||||
ReMeasure();
|
||||
transMap_ = new TransformMap(GetOrigRect());
|
||||
if (transMap_ == nullptr) {
|
||||
GRAPHIC_LOGE("new TransformMap fail");
|
||||
return;
|
||||
}
|
||||
}
|
||||
transMap_->Translate(trans);
|
||||
|
||||
Rect prevRect = GetRect();
|
||||
Rect mapRect = transMap_->GetBoxRect();
|
||||
|
||||
Rect joinRect;
|
||||
joinRect.Join(prevRect, mapRect);
|
||||
InvalidateRect(joinRect);
|
||||
}
|
||||
|
||||
bool UIView::IsTransInvalid()
|
||||
{
|
||||
if (transMap_ == nullptr) {
|
||||
return true;
|
||||
}
|
||||
return transMap_->IsInvalid();
|
||||
}
|
||||
|
||||
void UIView::ResetTransParameter()
|
||||
{
|
||||
if (transMap_ != nullptr) {
|
||||
delete transMap_;
|
||||
transMap_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
void UIView::RequestFocus()
|
||||
{
|
||||
FocusManager::GetInstance()->RequestFocus(this);
|
||||
}
|
||||
|
||||
void UIView::ClearFocus()
|
||||
{
|
||||
FocusManager::GetInstance()->ClearFocus();
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIView::Invalidate()
|
||||
{
|
||||
InvalidateRect(GetOrigRect());
|
||||
}
|
||||
|
||||
void UIView::InvalidateRect(const Rect& invalidatedArea)
|
||||
{
|
||||
if (!visible_) {
|
||||
if (needRedraw_) {
|
||||
needRedraw_ = false;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Rect trunc(invalidatedArea);
|
||||
bool isIntersect = true;
|
||||
UIView* par = parent_;
|
||||
UIView* cur = this;
|
||||
|
||||
while (par != nullptr) {
|
||||
if (!par->visible_) {
|
||||
return;
|
||||
}
|
||||
|
||||
isIntersect = trunc.Intersect(par->GetContentRect(), trunc);
|
||||
if (!isIntersect) {
|
||||
break;
|
||||
}
|
||||
|
||||
cur = par;
|
||||
par = par->parent_;
|
||||
}
|
||||
|
||||
if (isIntersect && (cur->GetViewType() == UI_ROOT_VIEW)) {
|
||||
RootView* rootView = reinterpret_cast<RootView*>(cur);
|
||||
rootView->AddInvalidateRectWithLock(trunc, this);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIView::OnLongPressEvent(const LongPressEvent& event)
|
||||
{
|
||||
if (onLongPressListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onLongPressListener_->OnLongPress(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnDragStartEvent(const DragEvent& event)
|
||||
{
|
||||
if (onDragListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onDragListener_->OnDragStart(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnDragEvent(const DragEvent& event)
|
||||
{
|
||||
if (onDragListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onDragListener_->OnDrag(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnDragEndEvent(const DragEvent& event)
|
||||
{
|
||||
if (onDragListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onDragListener_->OnDragEnd(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnClickEvent(const ClickEvent& event)
|
||||
{
|
||||
if (onClickListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onClickListener_->OnClick(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnPressEvent(const PressEvent& event)
|
||||
{
|
||||
if (onTouchListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onTouchListener_->OnPress(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnReleaseEvent(const ReleaseEvent& event)
|
||||
{
|
||||
if (onTouchListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onTouchListener_->OnRelease(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool UIView::OnCancelEvent(const CancelEvent& event)
|
||||
{
|
||||
if (onTouchListener_ != nullptr) {
|
||||
/* To ensure version compatibility, the listeners of both versions are invoked. */
|
||||
bool isConsumed = onTouchListener_->OnCancel(*this, event);
|
||||
return isConsumed;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
bool UIView::OnRotateEvent(const RotateEvent& event)
|
||||
{
|
||||
if (onRotateListener_ != nullptr) {
|
||||
return onRotateListener_->OnRotate(*this, event);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
void UIView::GetTargetView(const Point& point, UIView** last)
|
||||
{
|
||||
if (last == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* par = parent_;
|
||||
Rect rect = GetRect();
|
||||
|
||||
if (par != nullptr) {
|
||||
rect.Intersect(par->GetContentRect(), rect);
|
||||
}
|
||||
|
||||
if (visible_ && touchable_ && rect.IsContains(point)) {
|
||||
*last = this;
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::GetTargetView(const Point& point, UIView** current, UIView** target)
|
||||
{
|
||||
if (current == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* par = parent_;
|
||||
Rect rect = GetRect();
|
||||
|
||||
if (par != nullptr) {
|
||||
rect.Intersect(par->GetContentRect(), rect);
|
||||
}
|
||||
|
||||
if (visible_ && rect.IsContains(point)) {
|
||||
if (touchable_) {
|
||||
*current = this;
|
||||
}
|
||||
*target = this;
|
||||
}
|
||||
}
|
||||
|
||||
Rect UIView::GetRect() const
|
||||
{
|
||||
if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
|
||||
Rect r = transMap_->GetBoxRect();
|
||||
Rect origRect = GetOrigRect();
|
||||
r.SetX(r.GetX() + origRect.GetX() - transMap_->GetTransMapRect().GetX());
|
||||
r.SetY(r.GetY() + origRect.GetY() - transMap_->GetTransMapRect().GetY());
|
||||
return r;
|
||||
}
|
||||
return GetOrigRect();
|
||||
}
|
||||
|
||||
Rect UIView::GetContentRect()
|
||||
{
|
||||
if ((transMap_ != nullptr) && !transMap_->IsInvalid()) {
|
||||
Rect r = transMap_->GetBoxRect();
|
||||
Rect origRect = GetOrigRect();
|
||||
r.SetX(r.GetX() + origRect.GetX() - transMap_->GetTransMapRect().GetX());
|
||||
r.SetY(r.GetY() + origRect.GetY() - transMap_->GetTransMapRect().GetY());
|
||||
return r;
|
||||
}
|
||||
|
||||
Rect contentRect = GetRect();
|
||||
contentRect.SetX(contentRect.GetX() + style_->paddingLeft_ + style_->borderWidth_);
|
||||
contentRect.SetY(contentRect.GetY() + style_->paddingTop_ + style_->borderWidth_);
|
||||
contentRect.SetWidth(GetWidth());
|
||||
contentRect.SetHeight(GetHeight());
|
||||
return contentRect;
|
||||
}
|
||||
|
||||
Rect UIView::GetOrigRect() const
|
||||
{
|
||||
int16_t x = rect_.GetX();
|
||||
int16_t y = rect_.GetY();
|
||||
UIView* par = parent_;
|
||||
while (par != nullptr) {
|
||||
x += par->GetX() + par->style_->paddingLeft_ + par->style_->borderWidth_;
|
||||
y += par->GetY() + par->style_->paddingTop_ + par->style_->borderWidth_;
|
||||
par = par->parent_;
|
||||
}
|
||||
return Rect(x, y, x + rect_.GetWidth() - 1, y + rect_.GetHeight() - 1);
|
||||
}
|
||||
|
||||
Rect UIView::GetMaskedRect() const
|
||||
{
|
||||
Rect mask;
|
||||
if (visibleRect_ != nullptr) {
|
||||
mask.Intersect(GetRect(), GetVisibleRect());
|
||||
} else {
|
||||
mask = GetRect();
|
||||
}
|
||||
return mask;
|
||||
}
|
||||
|
||||
Rect UIView::GetVisibleRect() const
|
||||
{
|
||||
if (visibleRect_ == nullptr) {
|
||||
return GetRect();
|
||||
}
|
||||
Rect absoluteRect;
|
||||
int16_t x = visibleRect_->GetX();
|
||||
int16_t y = visibleRect_->GetY();
|
||||
UIView* par = parent_;
|
||||
while (par != nullptr) {
|
||||
x += par->GetX();
|
||||
y += par->GetY();
|
||||
par = par->parent_;
|
||||
}
|
||||
absoluteRect.SetX(x);
|
||||
absoluteRect.SetY(y);
|
||||
absoluteRect.SetWidth(visibleRect_->GetWidth());
|
||||
absoluteRect.SetHeight(visibleRect_->GetHeight());
|
||||
return absoluteRect;
|
||||
}
|
||||
|
||||
void UIView::SetTransformMap(const TransformMap& transMap)
|
||||
{
|
||||
if (transMap.IsInvalid()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((transMap_ != nullptr) && (*transMap_ == transMap)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect prevRect = GetRect();
|
||||
Rect mapRect = transMap.GetBoxRect();
|
||||
|
||||
Rect joinRect;
|
||||
joinRect.Join(prevRect, mapRect);
|
||||
|
||||
InvalidateRect(joinRect);
|
||||
|
||||
if (transMap_ == nullptr) {
|
||||
transMap_ = new TransformMap();
|
||||
}
|
||||
|
||||
*transMap_ = transMap;
|
||||
}
|
||||
|
||||
void UIView::SetWidthPercent(float widthPercent)
|
||||
{
|
||||
if (IsInvalid(widthPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1)) {
|
||||
int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
|
||||
SetWidth(newWidth);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::SetHeightPercent(float heightPercent)
|
||||
{
|
||||
if (IsInvalid(heightPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetHeight() > 1)) {
|
||||
int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
|
||||
SetHeight(newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::ResizePercent(float widthPercent, float heightPercent)
|
||||
{
|
||||
if (IsInvalid(widthPercent) || IsInvalid(heightPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
|
||||
int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
|
||||
int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
|
||||
Resize(newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::SetXPercent(float xPercent)
|
||||
{
|
||||
if (IsInvalid(xPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1)) {
|
||||
int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
|
||||
SetX(newX);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::SetYPercent(float yPercent)
|
||||
{
|
||||
if (IsInvalid(yPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetHeight() > 1)) {
|
||||
int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
|
||||
SetY(newY);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::SetPositionPercent(float xPercent, float yPercent)
|
||||
{
|
||||
if (IsInvalid(xPercent) || IsInvalid(yPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
|
||||
int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
|
||||
int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
|
||||
SetPosition(newX, newY);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::SetPositionPercent(float xPercent, float yPercent, float widthPercent, float heightPercent)
|
||||
{
|
||||
if (IsInvalid(xPercent) || IsInvalid(yPercent) || IsInvalid(widthPercent) || IsInvalid(heightPercent)) {
|
||||
return;
|
||||
}
|
||||
if ((GetParent() != nullptr) && (GetParent()->GetWidth() > 1) && (GetParent()->GetHeight() > 1)) {
|
||||
int16_t newX = static_cast<int16_t>(GetParent()->GetWidth() * xPercent);
|
||||
int16_t newY = static_cast<int16_t>(GetParent()->GetHeight() * yPercent);
|
||||
int16_t newWidth = static_cast<int16_t>(GetParent()->GetWidth() * widthPercent);
|
||||
int16_t newHeight = static_cast<int16_t>(GetParent()->GetHeight() * heightPercent);
|
||||
SetPosition(newX, newY, newWidth, newHeight);
|
||||
}
|
||||
}
|
||||
|
||||
bool UIView::IsInvalid(float percent)
|
||||
{
|
||||
if ((percent < 1) && (percent > 0)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIView::LayoutCenterOfParent(int16_t xOffset, int16_t yOffset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t topMargin = style_->marginTop_;
|
||||
int16_t leftMargin = style_->marginLeft_;
|
||||
int16_t rightMargin = style_->marginRight_;
|
||||
int16_t bottomMargin = style_->marginBottom_;
|
||||
// 2: half
|
||||
int16_t posX = parent_->GetWidth() / 2 - (rect_.GetWidth() - leftMargin + rightMargin) / 2 + xOffset;
|
||||
int16_t posY = parent_->GetHeight() / 2 - (rect_.GetHeight() - topMargin + bottomMargin) / 2 + yOffset;
|
||||
SetPosition(posX, posY);
|
||||
}
|
||||
|
||||
void UIView::LayoutLeftOfParent(int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t leftMargin = style_->marginLeft_;
|
||||
SetPosition(leftMargin + offset, GetY());
|
||||
}
|
||||
|
||||
void UIView::LayoutRightOfParent(int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t rightMargin = style_->marginRight_;
|
||||
SetPosition(parent_->GetWidth() - offset - rect_.GetWidth() - rightMargin, GetY());
|
||||
}
|
||||
|
||||
void UIView::LayoutTopOfParent(int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t topMargin = style_->marginTop_;
|
||||
SetPosition(GetX(), topMargin + offset);
|
||||
}
|
||||
|
||||
void UIView::LayoutBottomOfParent(int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t bottomMargin = style_->marginBottom_;
|
||||
SetPosition(GetX(), parent_->GetHeight() - offset - rect_.GetHeight() - bottomMargin);
|
||||
}
|
||||
|
||||
void UIView::AlignLeftToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginLeft_ - style_->marginLeft_;
|
||||
SetPosition(sib->GetX() - margin + offset, GetY());
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::AlignRightToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginRight_ - style_->marginRight_;
|
||||
SetPosition(sib->GetX() + sib->rect_.GetWidth() - rect_.GetWidth() - offset + margin, GetY());
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::AlignTopToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginTop_ - style_->marginTop_;
|
||||
SetPosition(GetX(), sib->GetY() + offset - margin);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::AlignBottomToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginBottom_ - style_->marginBottom_;
|
||||
SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() - rect_.GetHeight() - offset + margin);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::AlignHorCenterToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin =
|
||||
(sib->style_->marginRight_ - sib->style_->marginLeft_ - style_->marginRight_ + style_->marginLeft_) /
|
||||
2; // 2 : half
|
||||
SetPosition(sib->GetX() + sib->rect_.GetWidth() / 2 - rect_.GetWidth() / 2 + margin + offset, GetY());
|
||||
}
|
||||
}
|
||||
void UIView::AlignVerCenterToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin =
|
||||
(sib->style_->marginBottom_ - sib->style_->marginTop_ - style_->marginBottom_ + style_->marginTop_) /
|
||||
2; // 2 : half
|
||||
SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() / 2 - rect_.GetHeight() / 2 + margin + offset);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::LayoutLeftToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginLeft_ + style_->marginRight_;
|
||||
SetPosition(sib->GetX() - offset - rect_.GetWidth() - margin, GetY());
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::LayoutRightToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginRight_ + style_->marginLeft_;
|
||||
SetPosition(sib->GetX() + sib->rect_.GetWidth() + offset + margin, GetY());
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::LayoutTopToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginTop_ + style_->marginBottom_;
|
||||
SetPosition(GetX(), sib->GetY() - offset - rect_.GetHeight() - margin);
|
||||
}
|
||||
}
|
||||
|
||||
void UIView::LayoutBottomToSibling(const char* id, int16_t offset)
|
||||
{
|
||||
if (parent_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
UIView* sib = parent_->GetChildById(id);
|
||||
if (sib != nullptr) {
|
||||
int16_t margin = sib->style_->marginBottom_ + style_->marginTop_;
|
||||
SetPosition(GetX(), sib->GetY() + sib->rect_.GetHeight() + offset + margin);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t UIView::GetMixOpaScale()
|
||||
{
|
||||
uint8_t opaMix = opaScale_;
|
||||
UIView* parent = parent_;
|
||||
uint8_t opaParent;
|
||||
while (parent != nullptr) {
|
||||
opaParent = parent->GetOpaScale();
|
||||
// 8: Shift right 8 bits
|
||||
opaMix = (opaParent == OPA_OPAQUE) ? opaMix : ((static_cast<uint16_t>(opaParent) * opaMix) >> 8);
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
return opaMix;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+299
@@ -0,0 +1,299 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "components/ui_view_group.h"
|
||||
|
||||
#include <cstring>
|
||||
#include "components/root_view.h"
|
||||
|
||||
namespace OHOS {
|
||||
UIViewGroup::UIViewGroup()
|
||||
: childrenHead_(nullptr), childrenTail_(nullptr), childrenNum_(0),
|
||||
isDragging_(false), disallowIntercept_(false), isAutoSize_(false)
|
||||
{
|
||||
isViewGroup_ = true;
|
||||
}
|
||||
|
||||
UIViewGroup::~UIViewGroup() {}
|
||||
|
||||
void UIViewGroup::Add(UIView* view)
|
||||
{
|
||||
if ((view == this) || (view == nullptr)) {
|
||||
return;
|
||||
}
|
||||
if (childrenHead_ == nullptr) {
|
||||
childrenHead_ = view;
|
||||
} else {
|
||||
UIView* head = childrenHead_;
|
||||
while (head != nullptr) {
|
||||
if ((view == head) ||
|
||||
((view->GetViewId() != nullptr) &&
|
||||
(head->GetViewId() != nullptr) &&
|
||||
!strcmp(view->GetViewId(), head->GetViewId()))) {
|
||||
return;
|
||||
}
|
||||
head = head->GetNextSibling();
|
||||
}
|
||||
|
||||
if (childrenTail_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
childrenTail_->SetNextSibling(view);
|
||||
}
|
||||
view->SetParent(this);
|
||||
view->SetNextSibling(nullptr);
|
||||
childrenTail_ = view;
|
||||
childrenNum_++;
|
||||
if (isAutoSize_) {
|
||||
AutoResize();
|
||||
}
|
||||
OnChildChanged();
|
||||
}
|
||||
|
||||
void UIViewGroup::Insert(UIView* prevView, UIView* insertView)
|
||||
{
|
||||
if (insertView == nullptr) {
|
||||
return;
|
||||
}
|
||||
if (childrenHead_ == nullptr) {
|
||||
Add(insertView);
|
||||
return;
|
||||
}
|
||||
UIView* head = childrenHead_;
|
||||
while (head != nullptr) {
|
||||
if ((insertView == head) ||
|
||||
((insertView->GetViewId() != nullptr) &&
|
||||
(head->GetViewId() != nullptr) &&
|
||||
!strcmp(insertView->GetViewId(), head->GetViewId()))) {
|
||||
return;
|
||||
}
|
||||
head = head->GetNextSibling();
|
||||
}
|
||||
if (prevView == nullptr) {
|
||||
insertView->SetNextSibling(childrenHead_);
|
||||
insertView->SetParent(this);
|
||||
childrenHead_ = insertView;
|
||||
} else {
|
||||
UIView* nextView = prevView->GetNextSibling();
|
||||
prevView->SetNextSibling(insertView);
|
||||
insertView->SetNextSibling(nextView);
|
||||
insertView->SetParent(this);
|
||||
}
|
||||
if (childrenTail_ == prevView) {
|
||||
childrenTail_ = insertView;
|
||||
}
|
||||
childrenNum_++;
|
||||
if (isAutoSize_) {
|
||||
AutoResize();
|
||||
}
|
||||
OnChildChanged();
|
||||
}
|
||||
|
||||
void UIViewGroup::Remove(UIView* view)
|
||||
{
|
||||
if ((childrenHead_ == nullptr) || (view == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if LOCAL_RENDER
|
||||
RootView::GetInstance()->RemoveViewFromInvalidMap(view);
|
||||
InvalidateRect(view->GetRect());
|
||||
#endif
|
||||
if (childrenHead_ == view) {
|
||||
childrenHead_ = childrenHead_->GetNextSibling();
|
||||
view->SetParent(nullptr);
|
||||
view->SetNextSibling(nullptr);
|
||||
if (childrenTail_ == view) {
|
||||
childrenTail_ = nullptr;
|
||||
}
|
||||
childrenNum_--;
|
||||
OnChildChanged();
|
||||
return;
|
||||
}
|
||||
UIView* node = childrenHead_;
|
||||
while (node->GetNextSibling() != nullptr) {
|
||||
if (node->GetNextSibling() == view) {
|
||||
node->SetNextSibling(view->GetNextSibling());
|
||||
view->SetParent(nullptr);
|
||||
view->SetNextSibling(nullptr);
|
||||
if (childrenTail_ == view) {
|
||||
childrenTail_ = node;
|
||||
}
|
||||
childrenNum_--;
|
||||
OnChildChanged();
|
||||
return;
|
||||
}
|
||||
node = node->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
void UIViewGroup::RemoveAll()
|
||||
{
|
||||
UIView* node = childrenHead_;
|
||||
childrenHead_ = nullptr;
|
||||
childrenTail_ = nullptr;
|
||||
childrenNum_ = 0;
|
||||
UIView* tmp = nullptr;
|
||||
while (node != nullptr) {
|
||||
tmp = node;
|
||||
node = node->GetNextSibling();
|
||||
tmp->SetParent(nullptr);
|
||||
tmp->SetNextSibling(nullptr);
|
||||
}
|
||||
OnChildChanged();
|
||||
}
|
||||
|
||||
void UIViewGroup::GetTargetView(const Point& point, UIView** last)
|
||||
{
|
||||
if (last == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect rect = GetRect();
|
||||
if (disallowIntercept_) {
|
||||
*last = nullptr;
|
||||
return;
|
||||
}
|
||||
if (!rect.IsContains(point)) {
|
||||
return;
|
||||
}
|
||||
if (!visible_) {
|
||||
return;
|
||||
}
|
||||
if (touchable_) {
|
||||
*last = this;
|
||||
}
|
||||
if (isDragging_) {
|
||||
return;
|
||||
}
|
||||
UIView* view = childrenHead_;
|
||||
while (view != nullptr) {
|
||||
if (!view->IsViewGroup()) {
|
||||
rect = view->GetRect();
|
||||
if (rect.IsContains(point)) {
|
||||
view->GetTargetView(point, last);
|
||||
}
|
||||
} else {
|
||||
UIViewGroup* viewGroup = static_cast<UIViewGroup*>(view);
|
||||
viewGroup->GetTargetView(point, last);
|
||||
}
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
void UIViewGroup::GetTargetView(const Point& point, UIView** current, UIView** target)
|
||||
{
|
||||
if ((current == nullptr) || (target == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect rect = GetRect();
|
||||
if (disallowIntercept_) {
|
||||
*current = nullptr;
|
||||
*target = nullptr;
|
||||
return;
|
||||
}
|
||||
if (!rect.IsContains(point)) {
|
||||
return;
|
||||
}
|
||||
if (!visible_) {
|
||||
return;
|
||||
}
|
||||
*target = this;
|
||||
if (touchable_) {
|
||||
*current = this;
|
||||
}
|
||||
if (isDragging_) {
|
||||
return;
|
||||
}
|
||||
UIView* view = childrenHead_;
|
||||
while (view != nullptr) {
|
||||
if (!view->IsViewGroup()) {
|
||||
rect = view->GetRect();
|
||||
if (rect.IsContains(point)) {
|
||||
view->GetTargetView(point, current, target);
|
||||
}
|
||||
} else {
|
||||
UIViewGroup* viewGroup = static_cast<UIViewGroup*>(view);
|
||||
viewGroup->GetTargetView(point, current, target);
|
||||
}
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
Rect UIViewGroup::GetAllChildRelativeRect() const
|
||||
{
|
||||
Rect rect;
|
||||
UIView* view = childrenHead_;
|
||||
if (view != nullptr) {
|
||||
rect = view->GetRelativeRect();
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
while (view != nullptr) {
|
||||
Rect rectChild = view->GetRelativeRect();
|
||||
rect.Join(rect, rectChild);
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
return rect;
|
||||
}
|
||||
|
||||
UIView* UIViewGroup::GetChildById(const char* id) const
|
||||
{
|
||||
if (id == nullptr || childrenHead_ == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
UIView* child = childrenHead_;
|
||||
while (child != nullptr) {
|
||||
if ((child->GetViewId() != nullptr) && !strcmp(child->GetViewId(), id)) {
|
||||
return child;
|
||||
} else if (child->IsViewGroup() && static_cast<UIViewGroup*>(child)->GetChildrenHead() != nullptr) {
|
||||
child = static_cast<UIViewGroup*>(child)->GetChildrenHead();
|
||||
continue;
|
||||
} else if (child->GetNextSibling() != nullptr) {
|
||||
child = child->GetNextSibling();
|
||||
continue;
|
||||
}
|
||||
while (child->GetParent() != this && child->GetParent()->GetNextSibling() == nullptr) {
|
||||
child = child->GetParent();
|
||||
}
|
||||
if (child->GetParent() != this) {
|
||||
child = child->GetParent()->GetNextSibling();
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void UIViewGroup::MoveChildByOffset(int16_t xOffset, int16_t yOffset)
|
||||
{
|
||||
UIView* view = childrenHead_;
|
||||
int16_t x;
|
||||
int16_t y;
|
||||
while (view != nullptr) {
|
||||
x = view->GetX() + xOffset;
|
||||
y = view->GetY() + yOffset;
|
||||
view->SetPosition(x, y);
|
||||
view = view->GetNextSibling();
|
||||
}
|
||||
}
|
||||
|
||||
void UIViewGroup::AutoResize()
|
||||
{
|
||||
Rect rect = GetAllChildRelativeRect();
|
||||
SetWidth(rect.GetWidth() + rect.GetLeft());
|
||||
SetHeight(rect.GetHeight() + rect.GetTop());
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+230
@@ -0,0 +1,230 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "core/render_manager.h"
|
||||
|
||||
#include "components/root_view.h"
|
||||
#include "dock/screen_device_proxy.h"
|
||||
#include "graphic_log.h"
|
||||
#include "hal_tick.h"
|
||||
#include "securec.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "window/window_impl.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
RenderManager::RenderManager() : fps_(0.f), needResetFPS_(true), onFPSChangedListener_(nullptr) {}
|
||||
|
||||
RenderManager::~RenderManager() {}
|
||||
|
||||
void RenderManager::Init()
|
||||
{
|
||||
Task::Init();
|
||||
}
|
||||
|
||||
void RenderManager::RenderTask()
|
||||
{
|
||||
#if ENABLE_WINDOW
|
||||
ListNode<Window*>* winNode = winList_.Begin();
|
||||
while (winNode != winList_.End()) {
|
||||
WindowImpl* windowImpl = reinterpret_cast<WindowImpl*>(winNode->data_);
|
||||
windowImpl->Render();
|
||||
winNode = winNode->next_;
|
||||
}
|
||||
#else
|
||||
RootView::GetInstance()->Measure();
|
||||
RootView::GetInstance()->Render();
|
||||
#endif
|
||||
|
||||
#if ENABLE_FPS_SUPPORT
|
||||
UpdateFPS();
|
||||
#endif
|
||||
}
|
||||
|
||||
#if ENABLE_FPS_SUPPORT
|
||||
void RenderManager::UpdateFPS()
|
||||
{
|
||||
SysInfo::FPSCalculateType type = SysInfo::FPS_CT_FIXED_TIME;
|
||||
if (onFPSChangedListener_) {
|
||||
type = onFPSChangedListener_->GetFPSCalculateType();
|
||||
}
|
||||
if (type == SysInfo::FPS_CT_FIXED_TIME) {
|
||||
UpdateFPSByFixedTimeMethod();
|
||||
} else if (type == SysInfo::FPS_CT_AVERAGE_SAMPLING) {
|
||||
UpdateFPSByAverageSamplingMethod();
|
||||
} else if (type == SysInfo::FPS_CT_PRECISE_SAMPLING) {
|
||||
UpdateFPSByPreciseSamplingMethod();
|
||||
}
|
||||
OnFPSChanged(fps_);
|
||||
}
|
||||
|
||||
void RenderManager::UpdateFPSByFixedTimeMethod()
|
||||
{
|
||||
static uint16_t frameCount = 0;
|
||||
static uint32_t lastTime = HALTick::GetInstance().GetTime();
|
||||
if (needResetFPS_) {
|
||||
frameCount = 0;
|
||||
lastTime = HALTick::GetInstance().GetTime();
|
||||
needResetFPS_ = false;
|
||||
fps_ = 0.f;
|
||||
return;
|
||||
}
|
||||
|
||||
frameCount++;
|
||||
|
||||
uint32_t curTime = HALTick::GetInstance().GetTime();
|
||||
if (curTime - lastTime > MILLISECONDS_PER_SECOND) {
|
||||
fps_ = 1.f * frameCount / (curTime - lastTime) * MILLISECONDS_PER_SECOND;
|
||||
fps_ = (fps_ > MAX_FPS) ? MAX_FPS : fps_;
|
||||
frameCount = 0;
|
||||
lastTime = curTime;
|
||||
}
|
||||
}
|
||||
|
||||
void RenderManager::UpdateFPSByAverageSamplingMethod()
|
||||
{
|
||||
static float avgDuration = 0.f;
|
||||
static float alpha = 1.f / SAMPLE_NUMBER;
|
||||
static bool firstFrame = true;
|
||||
static uint32_t lastTime = HALTick::GetInstance().GetTime();
|
||||
if (needResetFPS_) {
|
||||
avgDuration = 0.f;
|
||||
alpha = 1.f / SAMPLE_NUMBER;
|
||||
firstFrame = true;
|
||||
lastTime = HALTick::GetInstance().GetTime();
|
||||
needResetFPS_ = false;
|
||||
fps_ = 0.f;
|
||||
return;
|
||||
}
|
||||
uint32_t curTime = HALTick::GetInstance().GetTime();
|
||||
int deltaTime = curTime - lastTime;
|
||||
lastTime = curTime;
|
||||
|
||||
if (firstFrame) {
|
||||
avgDuration = static_cast<float>(deltaTime);
|
||||
firstFrame = false;
|
||||
} else {
|
||||
avgDuration = avgDuration * (1 - alpha) + deltaTime * alpha;
|
||||
}
|
||||
fps_ = 1.f / avgDuration * MILLISECONDS_PER_SECOND;
|
||||
}
|
||||
|
||||
void RenderManager::UpdateFPSByPreciseSamplingMethod()
|
||||
{
|
||||
static int deltaTimeQueue[SAMPLE_NUMBER] = {0};
|
||||
static int frameCount = 0;
|
||||
static int sumDuration = 0;
|
||||
static bool isQueueFull = false;
|
||||
static uint32_t lastTime = HALTick::GetInstance().GetTime();
|
||||
if (needResetFPS_) {
|
||||
if (memset_s(deltaTimeQueue, sizeof(deltaTimeQueue), 0, sizeof(deltaTimeQueue)) != EOK) {
|
||||
return;
|
||||
}
|
||||
frameCount = 0;
|
||||
sumDuration = 0;
|
||||
isQueueFull = false;
|
||||
lastTime = HALTick::GetInstance().GetTime();
|
||||
needResetFPS_ = false;
|
||||
fps_ = 0.f;
|
||||
return;
|
||||
}
|
||||
uint32_t curTime = HALTick::GetInstance().GetTime();
|
||||
int deltaTime = curTime - lastTime;
|
||||
lastTime = curTime;
|
||||
|
||||
if (!isQueueFull && (frameCount == SAMPLE_NUMBER)) {
|
||||
isQueueFull = true;
|
||||
}
|
||||
frameCount %= SAMPLE_NUMBER;
|
||||
sumDuration -= deltaTimeQueue[frameCount];
|
||||
sumDuration += deltaTime;
|
||||
deltaTimeQueue[frameCount++] = deltaTime;
|
||||
if (isQueueFull) {
|
||||
fps_ = 1.f * SAMPLE_NUMBER / sumDuration * MILLISECONDS_PER_SECOND;
|
||||
} else {
|
||||
fps_ = 1.f * frameCount / sumDuration * MILLISECONDS_PER_SECOND;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
void RenderManager::RenderRect(const Rect& rect, RootView* rootView)
|
||||
{
|
||||
if (rootView == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect mask = rect;
|
||||
#if ENABLE_WINDOW
|
||||
if (rootView->GetBoundWindow()) {
|
||||
Rect winRect = rootView->GetBoundWindow()->GetRect();
|
||||
winRect.SetPosition(0, 0);
|
||||
mask.Intersect(rect, winRect);
|
||||
}
|
||||
#endif
|
||||
int32_t bufferHeight = ScreenDeviceProxy::GetInstance()->GetScreenArea() / mask.GetWidth();
|
||||
if (bufferHeight > mask.GetHeight()) {
|
||||
bufferHeight = mask.GetHeight();
|
||||
}
|
||||
|
||||
Rect& bufferRect = ScreenDeviceProxy::GetInstance()->GetBufferRect();
|
||||
bufferRect.SetLeft(mask.GetLeft());
|
||||
bufferRect.SetRight(mask.GetRight());
|
||||
|
||||
int16_t bottom = mask.GetBottom();
|
||||
for (int16_t bufferTop = mask.GetTop(); bufferTop <= bottom; bufferTop += bufferHeight) {
|
||||
bufferRect.SetTop(bufferTop);
|
||||
int16_t bufferBottom = bufferTop + bufferHeight - 1;
|
||||
if (bufferBottom >= bottom) {
|
||||
bufferRect.SetBottom(bottom);
|
||||
} else {
|
||||
bufferRect.SetBottom(bufferBottom);
|
||||
}
|
||||
#if LOCAL_RENDER
|
||||
rootView->DrawInvalidMap(bufferRect);
|
||||
#else
|
||||
UIView* topView = rootView->GetTopUIView(bufferRect);
|
||||
rootView->DrawTop(topView, bufferRect);
|
||||
#endif
|
||||
#if !ENABLE_WINDOW
|
||||
ScreenDeviceProxy::GetInstance()->Flush();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
void RenderManager::AddToDisplay(Window* window)
|
||||
{
|
||||
if (window == nullptr) {
|
||||
return;
|
||||
}
|
||||
winList_.PushBack(window);
|
||||
}
|
||||
|
||||
void RenderManager::RemoveFromDisplay(Window* window)
|
||||
{
|
||||
if (window == nullptr) {
|
||||
return;
|
||||
}
|
||||
ListNode<Window*>* winNode = winList_.Begin();
|
||||
while (winNode != winList_.End()) {
|
||||
if (winNode->data_ == window) {
|
||||
winList_.Remove(winNode);
|
||||
return;
|
||||
}
|
||||
winNode = winNode->next_;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
} // namespace OHOS
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_RENDER_MANAGER_H
|
||||
#define GRAPHIC_LITE_RENDER_MANAGER_H
|
||||
|
||||
#include "components/ui_view.h"
|
||||
#include "components/root_view.h"
|
||||
#include "common/task_manager.h"
|
||||
#include "geometry2d.h"
|
||||
#include "list.h"
|
||||
#include "sys_info.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "window/window.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
static constexpr float MAX_FPS = 90.f;
|
||||
|
||||
static constexpr int16_t SAMPLE_NUMBER = 100;
|
||||
|
||||
static constexpr uint16_t MILLISECONDS_PER_SECOND = 1000;
|
||||
|
||||
class RenderManager : public Task {
|
||||
public:
|
||||
static RenderManager& GetInstance()
|
||||
{
|
||||
static RenderManager instance;
|
||||
return instance;
|
||||
}
|
||||
|
||||
virtual void Init() override;
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
Window* GetWindowById(int32_t id)
|
||||
{
|
||||
auto node = winList_.Begin();
|
||||
while (node != winList_.End()) {
|
||||
if (node->data_->GetWindowId() == id) {
|
||||
return node->data_;
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
virtual void Callback() override
|
||||
{
|
||||
RenderTask();
|
||||
}
|
||||
|
||||
float GetFPS() const
|
||||
{
|
||||
return fps_;
|
||||
}
|
||||
|
||||
void RegisterFPSChangedListener(SysInfo::OnFPSChangedListener* onFPSChangedListener)
|
||||
{
|
||||
onFPSChangedListener_ = onFPSChangedListener;
|
||||
needResetFPS_ = true;
|
||||
}
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
void AddToDisplay(Window* window);
|
||||
|
||||
void RemoveFromDisplay(Window* window);
|
||||
#endif
|
||||
|
||||
private:
|
||||
friend class RootView;
|
||||
|
||||
RenderManager();
|
||||
|
||||
~RenderManager();
|
||||
|
||||
void RenderTask();
|
||||
|
||||
static void RenderRect(const Rect& rect, RootView* rootView);
|
||||
|
||||
#if ENABLE_FPS_SUPPORT
|
||||
void UpdateFPS();
|
||||
|
||||
void UpdateFPSByFixedTimeMethod();
|
||||
|
||||
void UpdateFPSByAverageSamplingMethod();
|
||||
|
||||
void UpdateFPSByPreciseSamplingMethod();
|
||||
|
||||
void OnFPSChanged(float newFPS)
|
||||
{
|
||||
if (onFPSChangedListener_) {
|
||||
onFPSChangedListener_->OnFPSChanged(newFPS);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
float fps_;
|
||||
|
||||
bool needResetFPS_;
|
||||
|
||||
SysInfo::OnFPSChangedListener* onFPSChangedListener_;
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
List<Window*> winList_;
|
||||
#endif
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_RENDER_MANAGER_H
|
||||
Executable
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "common/task_manager.h"
|
||||
#include <cassert>
|
||||
#include "hal_tick.h"
|
||||
|
||||
namespace OHOS {
|
||||
void TaskManager::Add(Task* task)
|
||||
{
|
||||
if (task == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
list_.PushBack(task);
|
||||
}
|
||||
|
||||
void TaskManager::Remove(Task* task)
|
||||
{
|
||||
if (task == nullptr) {
|
||||
return;
|
||||
}
|
||||
ListNode<Task*>* pos = list_.Begin();
|
||||
while (pos != list_.End()) {
|
||||
if (pos->data_ == task) {
|
||||
list_.Remove(pos);
|
||||
return;
|
||||
}
|
||||
pos = pos->next_;
|
||||
}
|
||||
}
|
||||
|
||||
void TaskManager::TaskHandler()
|
||||
{
|
||||
if (!canTaskRun_) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isHandlerRunning_) {
|
||||
return;
|
||||
}
|
||||
isHandlerRunning_ = true;
|
||||
|
||||
ListNode<Task*>* node = list_.Begin();
|
||||
|
||||
while (node != list_.End()) {
|
||||
Task* currentTask = node->data_;
|
||||
currentTask->TaskExecute();
|
||||
|
||||
node = node->next_;
|
||||
}
|
||||
|
||||
isHandlerRunning_ = false;
|
||||
}
|
||||
}
|
||||
+1379
File diff suppressed because it is too large
Load Diff
Executable
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_CHECK_BOX_RES_H
|
||||
#define GRAPHIC_LITE_CHECK_BOX_RES_H
|
||||
|
||||
#include "image_info.h"
|
||||
#include "graphic_types.h"
|
||||
namespace OHOS {
|
||||
ImageInfo* GetCheckBoxOnInfo();
|
||||
ImageInfo* GetCheckBoxOffInfo();
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_CHECK_BOX_RES_H
|
||||
Executable
+269
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dfx/event_injector.h"
|
||||
#if ENABLE_DEBUG
|
||||
#include "common/input_device_manager.h"
|
||||
#include "dfx/key_event_injector.h"
|
||||
#include "dfx/point_event_injector.h"
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
EventInjector::~EventInjector()
|
||||
{
|
||||
if (pointEventInjector_ != nullptr) {
|
||||
InputDeviceManager::GetInstance()->Remove(pointEventInjector_);
|
||||
delete pointEventInjector_;
|
||||
pointEventInjector_ = nullptr;
|
||||
}
|
||||
if (keyEventInjector_ != nullptr) {
|
||||
InputDeviceManager::GetInstance()->Remove(keyEventInjector_);
|
||||
delete keyEventInjector_;
|
||||
keyEventInjector_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventInjector::RegisterEventInjector(EventDataType type)
|
||||
{
|
||||
switch (type) {
|
||||
case EventDataType::POINT_TYPE:
|
||||
if (pointEventInjector_ == nullptr) {
|
||||
pointEventInjector_ = new PointEventInjector();
|
||||
if (pointEventInjector_ == nullptr) {
|
||||
GRAPHIC_LOGE("EventInjector::RegisterEventInjector register pointEventInjector failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
InputDeviceManager::GetInstance()->Add(pointEventInjector_);
|
||||
}
|
||||
return true;
|
||||
case EventDataType::KEY_TYPE:
|
||||
if (keyEventInjector_ == nullptr) {
|
||||
keyEventInjector_ = new KeyEventInjector();
|
||||
if (keyEventInjector_ == nullptr) {
|
||||
GRAPHIC_LOGE("EventInjector::RegisterEventInjector register keyEventInjector failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
InputDeviceManager::GetInstance()->Add(keyEventInjector_);
|
||||
}
|
||||
return true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void EventInjector::UnregisterEventInjector(EventDataType type)
|
||||
{
|
||||
switch (type) {
|
||||
case EventDataType::POINT_TYPE:
|
||||
if (pointEventInjector_ != nullptr) {
|
||||
InputDeviceManager::GetInstance()->Remove(pointEventInjector_);
|
||||
delete pointEventInjector_;
|
||||
pointEventInjector_ = nullptr;
|
||||
}
|
||||
break;
|
||||
case EventDataType::KEY_TYPE:
|
||||
if (keyEventInjector_ != nullptr) {
|
||||
InputDeviceManager::GetInstance()->Remove(keyEventInjector_);
|
||||
delete keyEventInjector_;
|
||||
keyEventInjector_ = nullptr;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool EventInjector::IsEventInjectorRegistered(EventDataType type) const
|
||||
{
|
||||
switch (type) {
|
||||
case EventDataType::POINT_TYPE:
|
||||
if (pointEventInjector_ != nullptr) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
case EventDataType::KEY_TYPE:
|
||||
if (keyEventInjector_ != nullptr) {
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EventInjector::SetInjectEvent(const DeviceData* dataArray, uint16_t arrayLength, EventDataType type)
|
||||
{
|
||||
if (dataArray == nullptr) {
|
||||
return false;
|
||||
}
|
||||
switch (type) {
|
||||
case EventDataType::POINT_TYPE:
|
||||
if (pointEventInjector_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (uint16_t i = 0; i < arrayLength; i++) {
|
||||
if (!pointEventInjector_->SetPointEvent(dataArray[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case EventDataType::KEY_TYPE:
|
||||
if (keyEventInjector_ == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (uint16_t i = 0; i < arrayLength; i++) {
|
||||
if (!keyEventInjector_->SetKey(dataArray[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool EventInjector::SetClickEvent(const Point& clickPoint)
|
||||
{
|
||||
uint16_t clickArrayLen = 2; /* 2:click event point */
|
||||
if (clickArrayLen > pointEventInjector_->GetLeftSize()) {
|
||||
GRAPHIC_LOGE("front points need to be read.(left size in pointer queue is not enough)");
|
||||
return false;
|
||||
}
|
||||
bool setResult = true;
|
||||
DeviceData* dataArray = new DeviceData[clickArrayLen];
|
||||
if (dataArray == nullptr) {
|
||||
return false;
|
||||
}
|
||||
dataArray[0].point = clickPoint;
|
||||
dataArray[0].state = InputDevice::STATE_PRESS;
|
||||
dataArray[1].point = clickPoint;
|
||||
dataArray[1].state = InputDevice::STATE_RELEASE;
|
||||
if (!SetInjectEvent(dataArray, clickArrayLen, EventDataType::POINT_TYPE)) {
|
||||
setResult = false;
|
||||
}
|
||||
delete [] dataArray;
|
||||
return setResult;
|
||||
}
|
||||
|
||||
bool EventInjector::SetLongPressEvent(const Point& longPressPoint)
|
||||
{
|
||||
uint16_t pointCount = INDEV_LONG_PRESS_TIME / INDEV_READ_PERIOD + 1;
|
||||
if (pointCount > pointEventInjector_->GetLeftSize()) {
|
||||
GRAPHIC_LOGE("front points need to be read.(left size in pointer queue is not enough)");
|
||||
return false;
|
||||
}
|
||||
bool setResult = true;
|
||||
DeviceData* dataArray = new DeviceData[pointCount];
|
||||
if (dataArray == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (uint16_t i = 0; i < pointCount; i++) {
|
||||
dataArray[i].point = longPressPoint;
|
||||
dataArray[i].state = InputDevice::STATE_PRESS;
|
||||
}
|
||||
dataArray[pointCount - 1].state = InputDevice::STATE_RELEASE;
|
||||
if (!SetInjectEvent(dataArray, pointCount, EventDataType::POINT_TYPE)) {
|
||||
setResult = false;
|
||||
}
|
||||
delete [] dataArray;
|
||||
return setResult;
|
||||
}
|
||||
|
||||
bool EventInjector::SetDragEvent(const Point& startPoint, const Point& endPoint, uint32_t dragTime)
|
||||
{
|
||||
uint16_t pointCount = (dragTime / INDEV_READ_PERIOD) + 1;
|
||||
/* 3: at least 3 points in drag event */
|
||||
if (pointCount < 3) {
|
||||
GRAPHIC_LOGE("dragTime is too short.(drag event needs at least 3 points)");
|
||||
return false;
|
||||
}
|
||||
if (pointCount > pointEventInjector_->GetLeftSize()) {
|
||||
GRAPHIC_LOGE("dragTime is too long or front points need to be read.(left size in pointer queue is not enough)");
|
||||
return false;
|
||||
}
|
||||
bool setResult = true;
|
||||
int16_t negativeFlag = 1; /* 1:represent the coordinate (x, y) of endPoint is larger than startPoint. */
|
||||
DeviceData* dataArray = new DeviceData[pointCount];
|
||||
if (dataArray == nullptr) {
|
||||
return false;
|
||||
}
|
||||
if (startPoint.x == endPoint.x) {
|
||||
float pointStep = static_cast<float>(MATH_ABS(endPoint.y - startPoint.y)) / (pointCount - 1);
|
||||
if (endPoint.y < startPoint.y) {
|
||||
negativeFlag = -1; /* -1:represent the coordinate y of endPoint is smaller than startPoint. */
|
||||
}
|
||||
for (uint16_t i = 0; i < pointCount; i++) {
|
||||
dataArray[i].point.x = startPoint.x;
|
||||
dataArray[i].point.y = startPoint.y + (i * negativeFlag * pointStep);
|
||||
dataArray[i].state = InputDevice::STATE_PRESS;
|
||||
}
|
||||
} else {
|
||||
float slope = static_cast<float>(endPoint.y - startPoint.y) / (endPoint.x - startPoint.x);
|
||||
int16_t constPara = startPoint.y - (slope * startPoint.x);
|
||||
float pointStep = static_cast<float>(MATH_ABS(endPoint.x - startPoint.x)) / (pointCount - 1);
|
||||
if (endPoint.x < startPoint.x) {
|
||||
negativeFlag = -1; /* -1:represent the coordinate x of endPoint is smaller than startPoint. */
|
||||
}
|
||||
for (uint16_t i = 0; i < pointCount; i++) {
|
||||
dataArray[i].point.x = startPoint.x + (i * negativeFlag * pointStep);
|
||||
dataArray[i].point.y = slope * (dataArray[i].point.x) + constPara;
|
||||
dataArray[i].state = InputDevice::STATE_PRESS;
|
||||
}
|
||||
}
|
||||
dataArray[pointCount - 1].point = endPoint;
|
||||
dataArray[pointCount - 1].state = InputDevice::STATE_RELEASE;
|
||||
if (!SetInjectEvent(dataArray, pointCount, EventDataType::POINT_TYPE)) {
|
||||
setResult = false;
|
||||
}
|
||||
delete [] dataArray;
|
||||
return setResult;
|
||||
}
|
||||
|
||||
bool EventInjector::SetKeyEvent(uint16_t keyId, uint16_t state)
|
||||
{
|
||||
uint16_t kevArrayLen = 1;
|
||||
if (kevArrayLen > keyEventInjector_->GetLeftSize()) {
|
||||
GRAPHIC_LOGE("front key event need to be read.(left size in key event queue is not enough)");
|
||||
return false;
|
||||
}
|
||||
bool setResult = true;
|
||||
DeviceData* dataArray = new DeviceData[kevArrayLen];
|
||||
if (dataArray == nullptr) {
|
||||
return false;
|
||||
}
|
||||
for (uint16_t i = 0; i < kevArrayLen; i++) {
|
||||
dataArray[i].keyId = keyId;
|
||||
dataArray[i].state = state;
|
||||
}
|
||||
if (!SetInjectEvent(dataArray, kevArrayLen, EventDataType::KEY_TYPE)) {
|
||||
setResult = false;
|
||||
}
|
||||
delete [] dataArray;
|
||||
return setResult;
|
||||
}
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
void EventInjector::SetWindowId(uint8_t windowId)
|
||||
{
|
||||
if (pointEventInjector_ != nullptr) {
|
||||
pointEventInjector_->SetWindowId(windowId);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // ENABLE_DEBUG
|
||||
Executable
+82
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dfx/key_event_injector.h"
|
||||
#if ENABLE_DEBUG
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace {
|
||||
const uint8_t MAX_LIST_SIZE = 100;
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
KeyEventInjector::~KeyEventInjector()
|
||||
{
|
||||
ListNode<DeviceData*>* node = dataList_.Begin();
|
||||
while (node != dataList_.End()) {
|
||||
if (node->data_ != nullptr) {
|
||||
DeviceData* deleteData = node->data_;
|
||||
delete deleteData;
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
dataList_.Clear();
|
||||
}
|
||||
|
||||
bool KeyEventInjector::Read(DeviceData& data)
|
||||
{
|
||||
if (dataList_.IsEmpty()) {
|
||||
lastState_ = INVALID_KEY_STATE;
|
||||
}
|
||||
if (dataList_.Size() > 0) {
|
||||
lastKeyId_ = dataList_.Front()->keyId;
|
||||
lastState_ = dataList_.Front()->state;
|
||||
|
||||
ListNode<DeviceData*>* node = dataList_.Begin();
|
||||
if (node->data_ != nullptr) {
|
||||
DeviceData* deleteData = node->data_;
|
||||
delete deleteData;
|
||||
}
|
||||
dataList_.PopFront();
|
||||
}
|
||||
data.keyId = lastKeyId_;
|
||||
data.state = lastState_;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool KeyEventInjector::SetKey(const DeviceData& data)
|
||||
{
|
||||
if (dataList_.Size() >= MAX_LIST_SIZE) {
|
||||
GRAPHIC_LOGI("PointEventInjector::SetPointEvent data list is full.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceData* tmpData = new DeviceData;
|
||||
if (tmpData == nullptr) {
|
||||
GRAPHIC_LOGE("PointEventInjector::SetPointEvent memory allocation failed Err!");
|
||||
return false;
|
||||
}
|
||||
tmpData->keyId = data.keyId;
|
||||
tmpData->state = data.state;
|
||||
dataList_.PushBack(tmpData);
|
||||
return true;
|
||||
}
|
||||
|
||||
uint8_t KeyEventInjector::GetLeftSize() const
|
||||
{
|
||||
return MAX_LIST_SIZE - dataList_.Size();
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_DEBUG
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_KEY_EVENT_INJECTOR
|
||||
#define GRAPHIC_LITE_KEY_EVENT_INJECTOR
|
||||
|
||||
#include "graphic_config.h"
|
||||
#if ENABLE_DEBUG
|
||||
#include "dock/key_input_device.h"
|
||||
#include "events/key_event.h"
|
||||
#include "list.h"
|
||||
|
||||
namespace OHOS {
|
||||
class KeyEventInjector : public KeyInputDevice {
|
||||
public:
|
||||
KeyEventInjector() : lastKeyId_(0), lastState_(INVALID_KEY_STATE) {}
|
||||
~KeyEventInjector();
|
||||
bool Read(DeviceData& data) override;
|
||||
bool SetKey(const DeviceData& data);
|
||||
uint8_t GetLeftSize() const;
|
||||
private:
|
||||
List<DeviceData*> dataList_;
|
||||
uint16_t lastKeyId_;
|
||||
uint16_t lastState_;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ENABLE_DEBUG
|
||||
#endif // GRAPHIC_LITE_KEY_EVENT_INJECTOR
|
||||
Executable
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_PERFORMANCE_TASK_H
|
||||
#define GRAPHIC_LITE_PERFORMANCE_TASK_H
|
||||
|
||||
#include "graphic_config.h"
|
||||
#if ENABLE_DEBUG && ENABLE_DEBUG_PERFORMANCE_TRACE
|
||||
#include "common/task.h"
|
||||
#include "graphic_performance.h"
|
||||
|
||||
namespace OHOS {
|
||||
class PerformanceTask : public Task {
|
||||
public:
|
||||
static PerformanceTask* GetInstance()
|
||||
{
|
||||
static PerformanceTask instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void Init() override
|
||||
{
|
||||
Performance::GetInstance()->RegisterSIGUSR1();
|
||||
Task::Init();
|
||||
}
|
||||
|
||||
void Callback() override
|
||||
{
|
||||
Performance::GetInstance()->PrintResult();
|
||||
}
|
||||
private:
|
||||
PerformanceTask() {}
|
||||
virtual ~PerformanceTask() {}
|
||||
PerformanceTask(const PerformanceTask&) = delete;
|
||||
PerformanceTask& operator=(const PerformanceTask&) = delete;
|
||||
PerformanceTask(PerformanceTask&&) = delete;
|
||||
PerformanceTask& operator=(PerformanceTask&&) = delete;
|
||||
};
|
||||
}
|
||||
#define DEBUG_PERFORMANCE_TASK_INIT() OHOS::PerformanceTask::GetInstance()->Init()
|
||||
#else
|
||||
#define DEBUG_PERFORMANCE_TASK_INIT()
|
||||
#endif
|
||||
#endif
|
||||
Executable
+92
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dfx/point_event_injector.h"
|
||||
#if ENABLE_DEBUG
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace {
|
||||
const uint16_t MAX_LIST_SIZE = 500;
|
||||
}
|
||||
|
||||
namespace OHOS {
|
||||
PointEventInjector::~PointEventInjector()
|
||||
{
|
||||
ListNode<DeviceData*>* node = dataList_.Begin();
|
||||
while (node != dataList_.End()) {
|
||||
if (node->data_ != nullptr) {
|
||||
DeviceData* deleteData = node->data_;
|
||||
delete deleteData;
|
||||
}
|
||||
node = node->next_;
|
||||
}
|
||||
dataList_.Clear();
|
||||
}
|
||||
|
||||
bool PointEventInjector::SetPointEvent(const DeviceData& data)
|
||||
{
|
||||
if (dataList_.Size() >= MAX_LIST_SIZE) {
|
||||
GRAPHIC_LOGI("PointEventInjector::SetPointEvent data list is full.");
|
||||
return false;
|
||||
}
|
||||
|
||||
DeviceData* tmpData = new DeviceData;
|
||||
if (tmpData == nullptr) {
|
||||
GRAPHIC_LOGE("PointEventInjector::SetPointEvent memory allocation failed Err!");
|
||||
return false;
|
||||
}
|
||||
tmpData->point = data.point;
|
||||
tmpData->state = data.state;
|
||||
dataList_.PushBack(tmpData);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PointEventInjector::Read(DeviceData& data)
|
||||
{
|
||||
if (dataList_.Size() > 0) {
|
||||
lastX_ = dataList_.Front()->point.x;
|
||||
lastY_ = dataList_.Front()->point.y;
|
||||
lastState_ = dataList_.Front()->state;
|
||||
|
||||
ListNode<DeviceData*>* node = dataList_.Begin();
|
||||
if (node->data_ != nullptr) {
|
||||
DeviceData* deleteData = node->data_;
|
||||
delete deleteData;
|
||||
}
|
||||
dataList_.PopFront();
|
||||
}
|
||||
data.point = {lastX_, lastY_};
|
||||
data.state = lastState_;
|
||||
#if ENABLE_WINDOW
|
||||
if (windowId_ >= 0) {
|
||||
data.winId = windowId_;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
uint16_t PointEventInjector::GetLeftSize() const
|
||||
{
|
||||
return MAX_LIST_SIZE - dataList_.Size();
|
||||
}
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
void PointEventInjector::SetWindowId(int32_t windowId)
|
||||
{
|
||||
windowId_ = windowId;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
#endif // ENABLE_DEBUG
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_POINT_EVENT_INJECTOR_H
|
||||
#define GRAPHIC_LITE_POINT_EVENT_INJECTOR_H
|
||||
|
||||
#include "graphic_config.h"
|
||||
#if ENABLE_DEBUG
|
||||
#include "dock/pointer_input_device.h"
|
||||
#include "list.h"
|
||||
|
||||
namespace OHOS {
|
||||
class PointEventInjector : public PointerInputDevice {
|
||||
public:
|
||||
PointEventInjector() : lastX_(0), lastY_(0), lastState_(0) {}
|
||||
~PointEventInjector();
|
||||
bool SetPointEvent(const DeviceData& data);
|
||||
bool Read(DeviceData& data) override;
|
||||
uint16_t GetLeftSize() const;
|
||||
#if ENABLE_WINDOW
|
||||
void SetWindowId(int32_t windowId);
|
||||
#endif
|
||||
|
||||
private:
|
||||
List<DeviceData*> dataList_;
|
||||
int16_t lastX_;
|
||||
int16_t lastY_;
|
||||
uint16_t lastState_;
|
||||
#if ENABLE_WINDOW
|
||||
int32_t windowId_ = -1;
|
||||
#endif
|
||||
};
|
||||
}
|
||||
#endif // ENABLE_DEBUG
|
||||
#endif // GRAPHIC_LITE_POINT_EVENT_INJECTOR_H
|
||||
Executable
+386
@@ -0,0 +1,386 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dfx/ui_dump_dom_tree.h"
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
#include "components/root_view.h"
|
||||
#include "components/ui_view.h"
|
||||
#include "components/ui_label.h"
|
||||
#include "components/ui_label_button.h"
|
||||
#include "components/ui_checkbox.h"
|
||||
#include "components/ui_toggle_button.h"
|
||||
#include "components/ui_image_view.h"
|
||||
#include "components/ui_abstract_progress.h"
|
||||
#include "components/ui_scroll_view.h"
|
||||
#include "components/ui_list.h"
|
||||
#include "components/ui_abstract_clock.h"
|
||||
#include "components/ui_picker.h"
|
||||
#include "components/ui_swipe_view.h"
|
||||
#include "components/ui_time_picker.h"
|
||||
#include "draw/draw_image.h"
|
||||
#include "file.h"
|
||||
#include "graphic_log.h"
|
||||
#endif // ENABLE_DEBUG
|
||||
namespace OHOS {
|
||||
#if ENABLE_DEBUG
|
||||
void UIDumpDomTree::AddNameField(UIViewType type, cJSON* usr) const
|
||||
{
|
||||
if (usr == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (type < UI_NUMBER_MAX) {
|
||||
cJSON_AddStringToObject(usr, "name", VIEW_TYPE_STRING[type]);
|
||||
} else {
|
||||
cJSON_AddStringToObject(usr, "name", "UnknownType");
|
||||
}
|
||||
}
|
||||
|
||||
void UIDumpDomTree::AddImageViewSpecialField(const UIView* view, cJSON* usr) const
|
||||
{
|
||||
if ((view == nullptr) || (usr == nullptr)) {
|
||||
return;
|
||||
}
|
||||
const UIImageView* tmpImageView = static_cast<const UIImageView*>(view);
|
||||
ImageSrcType srcType = tmpImageView->GetSrcType();
|
||||
if (srcType == IMG_SRC_FILE) {
|
||||
cJSON_AddStringToObject(usr, "src", reinterpret_cast<const char*>(tmpImageView->GetPath()));
|
||||
} else if (srcType == IMG_SRC_VARIABLE) {
|
||||
const ImageInfo* imageInfo = reinterpret_cast<const ImageInfo*>(tmpImageView->GetImageInfo());
|
||||
if ((imageInfo == nullptr) || (imageInfo->userData == nullptr)) {
|
||||
cJSON_AddStringToObject(usr, "src", "");
|
||||
return;
|
||||
}
|
||||
uintptr_t userData = reinterpret_cast<uintptr_t>(imageInfo->userData);
|
||||
cJSON_AddNumberToObject(usr, "src", static_cast<uint32_t>(userData));
|
||||
} else {
|
||||
cJSON_AddStringToObject(usr, "src", "");
|
||||
}
|
||||
}
|
||||
|
||||
void UIDumpDomTree::AddSpecialField(const UIView* view, cJSON* usr) const
|
||||
{
|
||||
if ((view == nullptr) || (usr == nullptr)) {
|
||||
return;
|
||||
}
|
||||
switch (view->GetViewType()) {
|
||||
case UI_LABEL:
|
||||
case UI_ARC_LABEL: {
|
||||
const UILabel* tmpLabel = static_cast<const UILabel*>(view);
|
||||
cJSON_AddStringToObject(usr, "text", tmpLabel->GetText());
|
||||
tmpLabel = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_LABEL_BUTTON: {
|
||||
const UILabelButton* tmpLabelButton = static_cast<const UILabelButton*>(view);
|
||||
cJSON_AddStringToObject(usr, "text", tmpLabelButton->GetText());
|
||||
tmpLabelButton = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_CHECK_BOX:
|
||||
case UI_RADIO_BUTTON: {
|
||||
const UICheckBox* tmpCheckBox = static_cast<const UICheckBox*>(view);
|
||||
if (tmpCheckBox->GetState()) {
|
||||
cJSON_AddStringToObject(usr, "state", "UNSELECTED");
|
||||
} else {
|
||||
cJSON_AddStringToObject(usr, "state", "SELECTED");
|
||||
}
|
||||
tmpCheckBox = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_TOGGLE_BUTTON: {
|
||||
const UIToggleButton* tmpToggleButton = static_cast<const UIToggleButton*>(view);
|
||||
cJSON_AddBoolToObject(usr, "state", tmpToggleButton->GetState());
|
||||
tmpToggleButton = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_IMAGE_VIEW: {
|
||||
AddImageViewSpecialField(view, usr);
|
||||
break;
|
||||
}
|
||||
// case below are all progress, thus has same attr.
|
||||
case UI_BOX_PROGRESS:
|
||||
case UI_SLIDER:
|
||||
case UI_CIRCLE_PROGRESS: {
|
||||
const UIAbstractProgress* tmpAbstractProgress = static_cast<const UIAbstractProgress*>(view);
|
||||
cJSON_AddNumberToObject(usr, "currValue", static_cast<double>(tmpAbstractProgress->GetValue()));
|
||||
cJSON_AddNumberToObject(usr, "rangeMin", static_cast<double>(tmpAbstractProgress->GetRangeMin()));
|
||||
cJSON_AddNumberToObject(usr, "rangeMax", static_cast<double>(tmpAbstractProgress->GetRangeMax()));
|
||||
tmpAbstractProgress = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_SCROLL_VIEW: {
|
||||
const UIScrollView* tmpScrollView = static_cast<const UIScrollView*>(view);
|
||||
cJSON_AddBoolToObject(usr, "xScrollable", tmpScrollView->GetHorizontalScrollState());
|
||||
cJSON_AddBoolToObject(usr, "yScrollable", tmpScrollView->GetVerticalScrollState());
|
||||
tmpScrollView = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_LIST: {
|
||||
UIList* tmpList = static_cast<UIList*>(const_cast<UIView*>(view));
|
||||
cJSON_AddBoolToObject(usr, "isLoopList", tmpList->GetLoopState());
|
||||
UIView* selectView = tmpList->GetSelectView();
|
||||
if (selectView != nullptr) {
|
||||
cJSON_AddNumberToObject(usr, "selectedIndex", static_cast<double>(selectView->GetViewIndex()));
|
||||
selectView = nullptr;
|
||||
}
|
||||
tmpList = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_DIGITAL_CLOCK:
|
||||
case UI_ANALOG_CLOCK: {
|
||||
const UIAbstractClock* tmpAbstractClock = static_cast<const UIAbstractClock*>(view);
|
||||
cJSON_AddNumberToObject(usr, "currentHour", static_cast<double>(tmpAbstractClock->GetCurrentHour()));
|
||||
cJSON_AddNumberToObject(usr, "currentMinute", static_cast<double>(tmpAbstractClock->GetCurrentMinute()));
|
||||
cJSON_AddNumberToObject(usr, "currentSecond", static_cast<double>(tmpAbstractClock->GetCurrentSecond()));
|
||||
tmpAbstractClock = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_PICKER: {
|
||||
const UIPicker* tmpPicker = static_cast<const UIPicker*>(view);
|
||||
cJSON_AddNumberToObject(usr, "selectedIndex", static_cast<double>(tmpPicker->GetSelected()));
|
||||
tmpPicker = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_SWIPE_VIEW: {
|
||||
const UISwipeView* tmpSwipeView = static_cast<const UISwipeView*>(view);
|
||||
cJSON_AddNumberToObject(usr, "currentIndex", static_cast<double>(tmpSwipeView->GetCurrentPage()));
|
||||
cJSON_AddNumberToObject(usr, "direction", static_cast<double>(tmpSwipeView->GetDirection()));
|
||||
tmpSwipeView = nullptr;
|
||||
break;
|
||||
}
|
||||
case UI_TIME_PICKER: {
|
||||
const UITimePicker* tmpTimePicker = static_cast<const UITimePicker*>(view);
|
||||
cJSON_AddStringToObject(usr, "selectedHour", tmpTimePicker->GetSelectHour());
|
||||
cJSON_AddStringToObject(usr, "selectedMinute", tmpTimePicker->GetSelectMinute());
|
||||
cJSON_AddStringToObject(usr, "selectedSecond", tmpTimePicker->GetSelectSecond());
|
||||
tmpTimePicker = nullptr;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void UIDumpDomTree::AddCommonField(UIView* view, cJSON* usr) const
|
||||
{
|
||||
if ((view == nullptr) || (usr == nullptr)) {
|
||||
return;
|
||||
}
|
||||
cJSON_AddNumberToObject(usr, "x", static_cast<double>(view->GetOrigRect().GetX()));
|
||||
cJSON_AddNumberToObject(usr, "y", static_cast<double>(view->GetOrigRect().GetY()));
|
||||
cJSON_AddNumberToObject(usr, "width", static_cast<double>(view->GetWidth()));
|
||||
cJSON_AddNumberToObject(usr, "height", static_cast<double>(view->GetHeight()));
|
||||
cJSON_AddStringToObject(usr, "id", view->GetViewId());
|
||||
cJSON_AddBoolToObject(usr, "visible", view->IsVisible());
|
||||
cJSON_AddBoolToObject(usr, "touchable", view->IsTouchable());
|
||||
cJSON_AddBoolToObject(usr, "draggable", view->IsDraggable());
|
||||
cJSON_AddBoolToObject(usr, "onClickListener", (view->GetOnClickListener() != nullptr));
|
||||
cJSON_AddBoolToObject(usr, "onDragListener", (view->GetOnDragListener() != nullptr));
|
||||
cJSON_AddBoolToObject(usr, "onLongPressListener", (view->GetOnLongPressListener() != nullptr));
|
||||
}
|
||||
|
||||
void UIDumpDomTree::OutputDomNode(UIView* view)
|
||||
{
|
||||
if (view == nullptr) {
|
||||
return;
|
||||
}
|
||||
/* Output current view's info into cJSON structure. */
|
||||
cJSON* dumpUsr = cJSON_CreateObject();
|
||||
if (dumpUsr == nullptr) {
|
||||
GRAPHIC_LOGE("UIDumpDomTree::OutputDomNode cJSON create object failed Err!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
AddNameField(view->GetViewType(), dumpUsr);
|
||||
AddCommonField(view, dumpUsr);
|
||||
AddSpecialField(view, dumpUsr);
|
||||
|
||||
pJson_ = cJSON_Print(dumpUsr);
|
||||
cJSON_Delete(dumpUsr);
|
||||
}
|
||||
|
||||
bool UIDumpDomTree::WriteDumpFile() const
|
||||
{
|
||||
unlink(path_);
|
||||
int32_t fd = open(path_, O_CREAT | O_RDWR, DEFAULT_FILE_PERMISSION);
|
||||
if (fd < 0) {
|
||||
GRAPHIC_LOGE("UIDumpDomTree::WriteDumpFile open file failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pJson_ == nullptr) {
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t length = strlen(pJson_);
|
||||
if (static_cast<uint32_t>(write(fd, pJson_, length)) != length) {
|
||||
GRAPHIC_LOGE("UIDumpDomTree::WriteDumpFile write file failed Err!\n");
|
||||
close(fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (close(fd) < 0) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void UIDumpDomTree::OutputDomTree(UIView* view, cJSON* usr)
|
||||
{
|
||||
if (allocErrorFlag_) {
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON* dumpUsr = usr;
|
||||
if (dumpUsr != rootJson_) {
|
||||
dumpUsr = cJSON_CreateObject();
|
||||
if (dumpUsr == nullptr) {
|
||||
allocErrorFlag_ = true;
|
||||
GRAPHIC_LOGE("UIDumpDomTree::OutputDomTree cJSON create object failed Err!\n");
|
||||
return;
|
||||
}
|
||||
/* usr must be a array. */
|
||||
cJSON_AddItemToArray(usr, dumpUsr);
|
||||
}
|
||||
|
||||
AddNameField(view->GetViewType(), dumpUsr);
|
||||
AddCommonField(view, dumpUsr);
|
||||
AddSpecialField(view, dumpUsr);
|
||||
|
||||
if (view->IsViewGroup()) {
|
||||
cJSON* arrayJson = cJSON_CreateArray();
|
||||
if (arrayJson == nullptr) {
|
||||
allocErrorFlag_ = true;
|
||||
GRAPHIC_LOGE("UIDumpDomTree::OutputDomTree cJSON create object failed Err!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
cJSON_AddItemToObject(dumpUsr, "child", arrayJson);
|
||||
UIViewGroup* tmpViewGroup = static_cast<UIViewGroup*>(view);
|
||||
UIView* childView = tmpViewGroup->GetChildrenHead();
|
||||
while (childView != nullptr) {
|
||||
OutputDomTree(childView, arrayJson);
|
||||
childView = childView->GetNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UIDumpDomTree::DumpJsonById(UIView* view, const char* id, DumpMode mode)
|
||||
{
|
||||
if (searchFlag_) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Check whether current view is the view we are looking for. */
|
||||
if ((view->GetViewId() != nullptr) && !strcmp(view->GetViewId(), id)) {
|
||||
if (mode == DUMP_NODE) {
|
||||
/* Find the view with right id, output its info. */
|
||||
OutputDomNode(view);
|
||||
} else if (mode == DUMP_TREE) {
|
||||
/* Find the view with right id, output its dom tree's info. */
|
||||
OutputDomTree(view, rootJson_);
|
||||
}
|
||||
/* Set flag to stop the tranversion. */
|
||||
searchFlag_ = true;
|
||||
} else {
|
||||
/* Look through all childrens of the current viewGroup. */
|
||||
if (view->IsViewGroup()) {
|
||||
UIViewGroup* tmpViewGroup = static_cast<UIViewGroup*>(view);
|
||||
UIView* childView = tmpViewGroup->GetChildrenHead();
|
||||
while (childView != nullptr) {
|
||||
DumpJsonById(childView, id, mode);
|
||||
childView = childView->GetNextSibling();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_DEBUG
|
||||
|
||||
char* UIDumpDomTree::DumpDomNode(const char* id)
|
||||
{
|
||||
#if ENABLE_DEBUG
|
||||
if (id == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
/* Reset dump info */
|
||||
pJson_ = nullptr;
|
||||
|
||||
RootView* rootView = RootView::GetInstance();
|
||||
UIView* currView = static_cast<UIView*>(rootView);
|
||||
/* Search through all views from rootView. */
|
||||
DumpJsonById(currView, id, DUMP_NODE);
|
||||
|
||||
/* Reset the search flag and pJson for next search */
|
||||
searchFlag_ = false;
|
||||
return pJson_;
|
||||
#else
|
||||
return nullptr;
|
||||
#endif // ENABLE_DEBUG
|
||||
}
|
||||
|
||||
bool UIDumpDomTree::DumpDomTree(const char* id, const char* path)
|
||||
{
|
||||
#if ENABLE_DEBUG
|
||||
path_ = (path == nullptr) ? DEFAULT_DUMP_DOM_TREE_PATH : path;
|
||||
|
||||
RootView* rootView = RootView::GetInstance();
|
||||
UIView* currView = static_cast<UIView*>(rootView);
|
||||
rootJson_ = cJSON_CreateObject();
|
||||
if (rootJson_ == nullptr) {
|
||||
GRAPHIC_LOGE("UIDumpDomTree::DumpDomTree cJSON create object failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id == nullptr) {
|
||||
OutputDomTree(currView, rootJson_);
|
||||
} else {
|
||||
DumpJsonById(currView, id, DUMP_TREE);
|
||||
if (!searchFlag_) {
|
||||
cJSON_Delete(rootJson_);
|
||||
rootJson_ = nullptr;
|
||||
GRAPHIC_LOGI("UIDumpDomTree::DumpDomTree can not find the node \n");
|
||||
return false;
|
||||
}
|
||||
/* Reset the search flag. */
|
||||
searchFlag_ = false;
|
||||
}
|
||||
|
||||
pJson_ = cJSON_Print(rootJson_);
|
||||
cJSON_Delete(rootJson_);
|
||||
rootJson_ = nullptr;
|
||||
if (pJson_ == nullptr) {
|
||||
GRAPHIC_LOGE("UIDumpDomTree::DumpDomTree convert cJSON object to string failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!WriteDumpFile()) {
|
||||
cJSON_free(pJson_);
|
||||
pJson_ = nullptr;
|
||||
GRAPHIC_LOGE("UIDumpDomTree::DumpDomTree file operation failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
cJSON_free(pJson_);
|
||||
pJson_ = nullptr;
|
||||
allocErrorFlag_ = false;
|
||||
return true;
|
||||
#else
|
||||
return false;
|
||||
#endif // ENABLE_DEBUG
|
||||
}
|
||||
}
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dfx/ui_screenshot.h"
|
||||
|
||||
#if ENABLE_DEBUG
|
||||
#include "iwindows_manager.h"
|
||||
#include "color.h"
|
||||
#include "common/screen.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "file.h"
|
||||
#include "graphic_log.h"
|
||||
#include "image_info.h"
|
||||
#include "securec.h"
|
||||
|
||||
namespace OHOS {
|
||||
class UIScreenshotListener : public IWindowsManager::ScreenshotListener {
|
||||
public:
|
||||
UIScreenshotListener() : filePath_(nullptr) {}
|
||||
|
||||
virtual ~UIScreenshotListener()
|
||||
{
|
||||
if (filePath_ != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(filePath_));
|
||||
filePath_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
void OnScreenshotEnd(uint8_t* virAddr, uint32_t width, uint32_t height,
|
||||
ImagePixelFormat format, uint32_t stride) override
|
||||
{
|
||||
if ((virAddr == nullptr) || ((format != IMAGE_PIXEL_FORMAT_ARGB1555) &&
|
||||
(format != IMAGE_PIXEL_FORMAT_ARGB8888))) {
|
||||
return;
|
||||
}
|
||||
|
||||
ImageHeader header = {0};
|
||||
header.colorMode = ARGB8888;
|
||||
header.width = width;
|
||||
header.height = height;
|
||||
|
||||
unlink(filePath_);
|
||||
int32_t fd = open(filePath_, O_RDWR | O_CREAT, DEFAULT_FILE_PERMISSION);
|
||||
UIFree(reinterpret_cast<void*>(filePath_));
|
||||
filePath_ = nullptr;
|
||||
if (fd < 0) {
|
||||
GRAPHIC_LOGE("UIScreenshotListener::OnScreenshotEnd open file failed Err!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (write(fd, &header, sizeof(ImageHeader)) != sizeof(ImageHeader)) {
|
||||
GRAPHIC_LOGE("UIScreenshotListener::OnScreenshotEnd write image header failed Err!\n");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t row = MAX_MALLOC_SIZE / width;
|
||||
row = (row == 0) ? 1 : row;
|
||||
uint32_t size = row * width * sizeof(uint32_t);
|
||||
uint32_t* argb8888Addr = static_cast<uint32_t*>(UIMalloc(size));
|
||||
if (argb8888Addr == nullptr) {
|
||||
GRAPHIC_LOGE("UIScreenshotListener::OnScreenshotEnd memory allocation failed Err!");
|
||||
close(fd);
|
||||
return;
|
||||
}
|
||||
|
||||
while (height >= row) {
|
||||
WriteBlockToFile(fd, argb8888Addr, virAddr, row, width, format, stride);
|
||||
height -= row;
|
||||
}
|
||||
if (height != 0) {
|
||||
WriteBlockToFile(fd, argb8888Addr, virAddr, height, width, format, stride);
|
||||
}
|
||||
UIFree(reinterpret_cast<void*>(argb8888Addr));
|
||||
close(fd);
|
||||
}
|
||||
|
||||
void SetFilePath(char* path)
|
||||
{
|
||||
if (filePath_ != nullptr) {
|
||||
UIFree(reinterpret_cast<void*>(filePath_));
|
||||
}
|
||||
filePath_ = path;
|
||||
}
|
||||
|
||||
private:
|
||||
static constexpr uint8_t DEFAULT_COLOR_SIZE = 4;
|
||||
static constexpr uint16_t MAX_MALLOC_SIZE = 2048; // unit: 4 bytes
|
||||
char* filePath_;
|
||||
|
||||
bool WriteBlockToFile(int32_t fd, uint32_t* buffer, uint8_t*& startAddr, uint32_t row,
|
||||
uint32_t width, ImagePixelFormat format, uint32_t stride) const
|
||||
{
|
||||
uint32_t* argb8888Addr = buffer;
|
||||
for (uint32_t r = 0; r < row; ++r) {
|
||||
if (format == IMAGE_PIXEL_FORMAT_ARGB1555) {
|
||||
uint16_t* temp = reinterpret_cast<uint16_t*>(startAddr);
|
||||
for (uint32_t i = 0; i < width; ++i) {
|
||||
buffer[i] = PixelFormatUtils::ARGB1555ToARGB8888(*temp++);
|
||||
}
|
||||
} else if (format == IMAGE_PIXEL_FORMAT_ARGB8888) {
|
||||
if (memcpy_s(buffer, width * DEFAULT_COLOR_SIZE, startAddr, width * DEFAULT_COLOR_SIZE) != EOK) {
|
||||
GRAPHIC_LOGE("memcpy_s error!");
|
||||
}
|
||||
}
|
||||
startAddr += stride;
|
||||
buffer += width;
|
||||
}
|
||||
|
||||
uint32_t blockSize = row * width * sizeof(uint32_t);
|
||||
if (static_cast<uint32_t>(write(fd, argb8888Addr, blockSize)) != blockSize) {
|
||||
GRAPHIC_LOGE("UIScreenshotListener::WriteBlockToFile wrong amount of written data Err!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
UIScreenshot::~UIScreenshot()
|
||||
{
|
||||
if (screenshotListener_ != nullptr) {
|
||||
delete screenshotListener_;
|
||||
screenshotListener_ = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
bool UIScreenshot::ScreenshotToFile(const char* path)
|
||||
{
|
||||
if (screenshotListener_ == nullptr) {
|
||||
screenshotListener_ = new UIScreenshotListener();
|
||||
if (screenshotListener_ == nullptr) {
|
||||
GRAPHIC_LOGE("UIScreenshot::ScreenshotToFile register screenshot listener failed Err!\n");
|
||||
return false;
|
||||
}
|
||||
IWindowsManager::GetInstance()->SetScreenshotListener(screenshotListener_);
|
||||
}
|
||||
|
||||
const char* srcPath = (path == nullptr) ? DEFAULT_SCREENSHOT_PATH : path;
|
||||
uint32_t pathLength = strlen(srcPath);
|
||||
char* destPath = static_cast<char*>(UIMalloc(pathLength + 1));
|
||||
if (destPath == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (memcpy_s(destPath, pathLength + 1, srcPath, pathLength) != EOK) {
|
||||
UIFree(reinterpret_cast<void*>(destPath));
|
||||
return false;
|
||||
}
|
||||
destPath[pathLength] = '\0';
|
||||
screenshotListener_->SetFilePath(destPath);
|
||||
IWindowsManager::GetInstance()->Screenshot();
|
||||
return true;
|
||||
}
|
||||
} // namespace OHOS
|
||||
#endif // ENABLE_DEBUG
|
||||
Executable
+28
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/input_device.h"
|
||||
|
||||
namespace OHOS {
|
||||
void InputDevice::ProcessEvent()
|
||||
{
|
||||
DeviceData data;
|
||||
bool moreToRead = false;
|
||||
do {
|
||||
moreToRead = Read(data);
|
||||
DispatchEvent(data);
|
||||
} while (moreToRead);
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_INPUT_DEVICE_H
|
||||
#define GRAPHIC_LITE_INPUT_DEVICE_H
|
||||
|
||||
#include "input_event_info.h"
|
||||
#include "heap_base.h"
|
||||
|
||||
namespace OHOS {
|
||||
/**
|
||||
* @brief Input device base class.
|
||||
*/
|
||||
class InputDevice : public HeapBase {
|
||||
public:
|
||||
InputDevice() : rawDataState_(STATE_RELEASE) {}
|
||||
virtual ~InputDevice() {}
|
||||
|
||||
/**
|
||||
* @brief Process event from input device driver.
|
||||
*/
|
||||
void ProcessEvent();
|
||||
|
||||
/**
|
||||
* @brief Read data from hardware.User should override this to set data
|
||||
*
|
||||
* @param [out] input device data.
|
||||
*
|
||||
* @returns no more data to read if true.
|
||||
*/
|
||||
virtual bool Read(DeviceData& data) = 0;
|
||||
|
||||
constexpr static uint8_t STATE_RELEASE = 0;
|
||||
constexpr static uint8_t STATE_PRESS = 1;
|
||||
|
||||
protected:
|
||||
uint16_t rawDataState_;
|
||||
|
||||
/**
|
||||
* @brief Dispatch event to ui component.
|
||||
* @param [in] data data received from hardware
|
||||
*/
|
||||
virtual void DispatchEvent(const DeviceData& data) = 0;
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_INPUT_DEVICE_H
|
||||
Executable
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/key_input_device.h"
|
||||
#include "components/root_view.h"
|
||||
#include "graphic_math.h"
|
||||
#include "hal_tick.h"
|
||||
|
||||
namespace OHOS {
|
||||
void KeyInputDevice::DispatchEvent(const DeviceData& data)
|
||||
{
|
||||
if (data.state != INVALID_KEY_STATE) {
|
||||
KeyEvent event(data.keyId, data.state);
|
||||
RootView::GetInstance()->OnKeyEvent(event);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_KEY_INPUT_DEVICE_H
|
||||
#define GRAPHIC_LITE_KEY_INPUT_DEVICE_H
|
||||
|
||||
#include "dock/input_device.h"
|
||||
|
||||
namespace OHOS {
|
||||
/** @brief A key input device. */
|
||||
class KeyInputDevice : public InputDevice {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*
|
||||
* @param [in] read If non-null, the read.
|
||||
* @param [in] userData If non-null, information describing the user.
|
||||
*/
|
||||
KeyInputDevice() {}
|
||||
/** @brief Destructor */
|
||||
virtual ~KeyInputDevice() {}
|
||||
|
||||
private:
|
||||
void DispatchEvent(const DeviceData& data) override;
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // UI_INCLUDE_CORE_PHYKEY_INPUT_DEVICE_H
|
||||
Executable
+26
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/ohos/ohos_input_device.h"
|
||||
#include "input_event_info.h"
|
||||
#include "iwindows_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
bool OHOSInputDevice::Read(DeviceData& data)
|
||||
{
|
||||
IWindowsManager::GetInstance()->GetEventData(&data);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_OHOS_INPUT_DEVICE_H
|
||||
#define GRAPHIC_LITE_OHOS_INPUT_DEVICE_H
|
||||
|
||||
#include "dock/pointer_input_device.h"
|
||||
|
||||
namespace OHOS {
|
||||
class OHOSInputDevice : public PointerInputDevice {
|
||||
public:
|
||||
OHOSInputDevice() {}
|
||||
|
||||
virtual ~OHOSInputDevice() {}
|
||||
|
||||
bool Read(DeviceData& data) override;
|
||||
};
|
||||
}
|
||||
#endif
|
||||
Executable
+324
@@ -0,0 +1,324 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/pointer_input_device.h"
|
||||
|
||||
#include "components/root_view.h"
|
||||
#include "core/render_manager.h"
|
||||
#if ENABLE_AOD
|
||||
#include "events/aod_callback.h"
|
||||
#endif
|
||||
#include "graphic_log.h"
|
||||
#include "graphic_math.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "window/window.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
void PointerInputDevice::DispatchEvent(const DeviceData& data)
|
||||
{
|
||||
curPos_ = data.point;
|
||||
#if ENABLE_WINDOW
|
||||
Window* window = RenderManager::GetInstance().GetWindowById(data.winId);
|
||||
if (window == nullptr) {
|
||||
return;
|
||||
}
|
||||
curPos_.x = curPos_.x - window->GetRect().GetLeft();
|
||||
curPos_.y = curPos_.y - window->GetRect().GetTop();
|
||||
UIViewGroup* rootView = window->GetRootView();
|
||||
if (rootView == nullptr) {
|
||||
return;
|
||||
}
|
||||
#else
|
||||
UIViewGroup* rootView = RootView::GetInstance();
|
||||
#endif
|
||||
// invalid touchable and draggable view will be reset to nullptr
|
||||
if ((touchableView_ != nullptr) && !RootView::FindSubView(*rootView, touchableView_)) {
|
||||
touchableView_ = nullptr;
|
||||
lastPos_ = curPos_;
|
||||
}
|
||||
if ((draggableView_ != nullptr) && !RootView::FindSubView(*rootView, draggableView_)) {
|
||||
draggableView_ = nullptr;
|
||||
lastPos_ = curPos_;
|
||||
dragLastPos_ = curPos_;
|
||||
dragLen_ = { 0, 0 };
|
||||
dragStep_ = { 0, 0 };
|
||||
isDragging_ = false;
|
||||
}
|
||||
|
||||
if (data.state == STATE_PRESS) {
|
||||
DispatchPressEvent(rootView);
|
||||
} else {
|
||||
DispatchReleaseEvent(rootView);
|
||||
}
|
||||
dragLastPos_ = lastPos_;
|
||||
lastPos_ = curPos_;
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchPressEvent(UIViewGroup* rootView)
|
||||
{
|
||||
if (rootView == nullptr) {
|
||||
return;
|
||||
}
|
||||
// first time to press
|
||||
if (!pressState_) {
|
||||
rootView->GetTargetView(curPos_, &touchableView_, &targetView_);
|
||||
if (touchableView_ == nullptr) {
|
||||
GRAPHIC_LOGD("PointerInputDevice::DispatchPressEvent cannot find target view!\n");
|
||||
return;
|
||||
}
|
||||
draggableView_ = GetDraggableView(touchableView_);
|
||||
pressState_ = true;
|
||||
pressTimeStamp_ = HALTick::GetInstance().GetTime();
|
||||
lastPos_ = curPos_;
|
||||
dragLastPos_ = lastPos_;
|
||||
return;
|
||||
}
|
||||
uint32_t elapse = HALTick::GetInstance().GetElapseTime(pressTimeStamp_);
|
||||
DispatchDragStartEvent();
|
||||
DispatchDragEvent();
|
||||
if (!isDragging_ && (touchableView_ != nullptr) && !cancelSent_) {
|
||||
UIView* tempView = nullptr;
|
||||
rootView->GetTargetView(curPos_, &tempView, &targetView_);
|
||||
if (tempView != touchableView_) {
|
||||
DispatchCancelEvent();
|
||||
} else {
|
||||
if (!pressSent_ && (elapse > INDEV_PRESS_TIME_IN_DRAG)) {
|
||||
PressEvent evt(curPos_);
|
||||
UIView* parent = touchableView_->GetParent();
|
||||
if (!touchableView_->OnPressEvent(evt)) {
|
||||
while (parent != nullptr) {
|
||||
PressEvent evtParent(curPos_);
|
||||
if (parent->UIView::OnPressEvent(evtParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
pressSent_ = true;
|
||||
}
|
||||
DispatchLongPressEvent(elapse);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool PointerInputDevice::ProcessReleaseEvent()
|
||||
{
|
||||
UIView* parent = touchableView_->GetParent();
|
||||
// reissue press event.
|
||||
if (!pressSent_) {
|
||||
PressEvent evtPress(curPos_);
|
||||
if (!touchableView_->OnPressEvent(evtPress)) {
|
||||
while (parent != nullptr) {
|
||||
PressEvent evtPressParent(curPos_);
|
||||
if (parent->UIView::OnPressEvent(evtPressParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
pressSent_ = true;
|
||||
return false;
|
||||
} else {
|
||||
ReleaseEvent evtRelease(curPos_);
|
||||
if (!touchableView_->OnReleaseEvent(evtRelease)) {
|
||||
while (parent != nullptr) {
|
||||
ReleaseEvent evtReleaseParent(curPos_);
|
||||
if (parent->UIView::OnReleaseEvent(evtReleaseParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
|
||||
if (pressSent_ && needClick_) {
|
||||
ClickEvent evt(curPos_);
|
||||
parent = touchableView_->GetParent();
|
||||
if (!touchableView_->OnClickEvent(evt)) {
|
||||
while (parent != nullptr) {
|
||||
#if ENABLE_AOD
|
||||
OnClickEventHappen(parent);
|
||||
#endif
|
||||
ClickEvent evtParent(curPos_);
|
||||
if (parent->UIView::OnClickEvent(evtParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
#if ENABLE_AOD
|
||||
OnClickEventHappen(*touchableView_);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchReleaseEvent(UIViewGroup* rootView)
|
||||
{
|
||||
if (!pressState_ || (rootView == nullptr)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DispatchDragStartEvent();
|
||||
DispatchDragEndEvent();
|
||||
if (!isDragging_ && (touchableView_ != nullptr) && !cancelSent_) {
|
||||
UIView* tempView = nullptr;
|
||||
rootView->GetTargetView(curPos_, &tempView, &targetView_);
|
||||
if (tempView != touchableView_) {
|
||||
DispatchCancelEvent();
|
||||
} else {
|
||||
if (!ProcessReleaseEvent()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
isDragging_ = false;
|
||||
pressState_ = false;
|
||||
pressSent_ = false;
|
||||
cancelSent_ = false;
|
||||
longPressSent_ = false;
|
||||
needClick_ = true;
|
||||
touchableView_ = nullptr;
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchDragStartEvent()
|
||||
{
|
||||
if (draggableView_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
dragStep_.x = curPos_.x - lastPos_.x;
|
||||
dragStep_.y = curPos_.y - lastPos_.y;
|
||||
dragLen_.x += dragStep_.x;
|
||||
dragLen_.y += dragStep_.y;
|
||||
if (!isDragging_) {
|
||||
if ((MATH_ABS(dragLen_.x) >= INDEV_DRAG_LIMIT) || (MATH_ABS(dragLen_.y) >= INDEV_DRAG_LIMIT)) {
|
||||
if ((touchableView_ != nullptr) && !cancelSent_) {
|
||||
DispatchCancelEvent();
|
||||
}
|
||||
// Send Drag Begin Event.
|
||||
DragEvent evt(curPos_, lastPos_, dragLen_);
|
||||
UIView* parent = draggableView_->GetParent();
|
||||
if (!draggableView_->OnDragStartEvent(evt)) {
|
||||
while (parent != nullptr) {
|
||||
DragEvent evtParent(curPos_, lastPos_, dragLen_);
|
||||
if (parent->UIView::OnDragStartEvent(evtParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
dragLastPos_ = lastPos_;
|
||||
isDragging_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchDragEvent()
|
||||
{
|
||||
if ((draggableView_ == nullptr) || !isDragging_) {
|
||||
return;
|
||||
}
|
||||
if ((dragStep_.x != 0) || (dragStep_.y != 0)) {
|
||||
DragEvent evt(curPos_, lastPos_, dragLen_);
|
||||
UIView* parent = draggableView_->GetParent();
|
||||
if (!draggableView_->OnDragEvent(evt)) {
|
||||
while (parent != nullptr) {
|
||||
DragEvent evtParent(curPos_, lastPos_, dragLen_);
|
||||
if (parent->UIView::OnDragEvent(evtParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchDragEndEvent()
|
||||
{
|
||||
if (draggableView_ == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (isDragging_) {
|
||||
DragEvent evt(curPos_, lastPos_, dragLen_);
|
||||
UIView* parent = draggableView_->GetParent();
|
||||
evt.SetPreLastPoint(dragLastPos_);
|
||||
if (!draggableView_->OnDragEndEvent(evt)) {
|
||||
while (parent != nullptr) {
|
||||
DragEvent evtParent(curPos_, lastPos_, dragLen_);
|
||||
if (parent->UIView::OnDragEndEvent(evtParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
#if ENABLE_AOD
|
||||
OnDragEndEventHappen(*draggableView_);
|
||||
#endif
|
||||
}
|
||||
dragLen_ = { 0, 0 };
|
||||
dragStep_ = { 0, 0 };
|
||||
draggableView_ = nullptr;
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchLongPressEvent(uint32_t elapse)
|
||||
{
|
||||
if (!longPressSent_ && (elapse > INDEV_LONG_PRESS_TIME)) {
|
||||
longPressSent_ = true;
|
||||
LongPressEvent evt(curPos_, pressTimeStamp_);
|
||||
bool isConsumed = touchableView_->OnLongPressEvent(evt);
|
||||
if (touchableView_->GetOnLongPressListener() != nullptr) {
|
||||
needClick_ = false;
|
||||
}
|
||||
UIView* parent = touchableView_->GetParent();
|
||||
#if ENABLE_AOD
|
||||
OnLongPressEventHappen(*touchableView_);
|
||||
#endif
|
||||
if (!isConsumed) {
|
||||
while (parent != nullptr) {
|
||||
LongPressEvent evtParent(curPos_, pressTimeStamp_);
|
||||
isConsumed = parent->UIView::OnLongPressEvent(evtParent);
|
||||
if (needClick_ && (parent->GetOnLongPressListener() != nullptr)) {
|
||||
needClick_ = false;
|
||||
}
|
||||
#if ENABLE_AOD
|
||||
OnLongPressEventHappen(*parent);
|
||||
#endif
|
||||
if (isConsumed) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PointerInputDevice::DispatchCancelEvent()
|
||||
{
|
||||
CancelEvent evt(lastPos_);
|
||||
UIView* parent = touchableView_->GetParent();
|
||||
if (!touchableView_->OnCancelEvent(evt)) {
|
||||
while (parent != nullptr) {
|
||||
CancelEvent evtParent(lastPos_);
|
||||
if (parent->UIView::OnCancelEvent(evtParent)) {
|
||||
break;
|
||||
}
|
||||
parent = parent->GetParent();
|
||||
}
|
||||
}
|
||||
cancelSent_ = true;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+76
@@ -0,0 +1,76 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_POINTER_INPUT_DEVICE_H
|
||||
#define GRAPHIC_LITE_POINTER_INPUT_DEVICE_H
|
||||
|
||||
#include "hal_tick.h"
|
||||
#include "dock/input_device.h"
|
||||
#include "components/ui_view_group.h"
|
||||
|
||||
namespace OHOS {
|
||||
/** @brief A pointer input device. */
|
||||
class PointerInputDevice : public InputDevice {
|
||||
public:
|
||||
PointerInputDevice()
|
||||
: touchableView_(nullptr), draggableView_(nullptr), targetView_(nullptr), lastPos_({0, 0}),
|
||||
dragLastPos_({0, 0}), curPos_({ 0, 0 }), dragStep_({ 0, 0 }), dragLen_({ 0, 0 }), pressState_(false),
|
||||
pressSent_(false), longPressSent_(false), cancelSent_(false), isDragging_(false), needClick_(true),
|
||||
pressTimeStamp_(0)
|
||||
{}
|
||||
virtual ~PointerInputDevice() {}
|
||||
|
||||
protected:
|
||||
void DispatchEvent(const DeviceData& data) override;
|
||||
|
||||
private:
|
||||
UIView* touchableView_;
|
||||
UIView* draggableView_;
|
||||
UIView* targetView_;
|
||||
Point lastPos_;
|
||||
Point dragLastPos_;
|
||||
Point curPos_;
|
||||
Point dragStep_;
|
||||
Point dragLen_;
|
||||
bool pressState_;
|
||||
bool pressSent_;
|
||||
bool longPressSent_;
|
||||
bool cancelSent_;
|
||||
bool isDragging_;
|
||||
bool needClick_;
|
||||
uint32_t pressTimeStamp_;
|
||||
|
||||
void DispatchPressEvent(UIViewGroup* rootView);
|
||||
void DispatchReleaseEvent(UIViewGroup* rootView);
|
||||
void DispatchDragStartEvent();
|
||||
void DispatchDragEndEvent();
|
||||
void DispatchDragEvent();
|
||||
void DispatchLongPressEvent(uint32_t elapse);
|
||||
void DispatchCancelEvent();
|
||||
bool ProcessReleaseEvent();
|
||||
UIView* GetDraggableView(UIView* targetView) const
|
||||
{
|
||||
UIView* tempView = targetView;
|
||||
while ((tempView != nullptr) && tempView->IsDragParentInstead()) {
|
||||
tempView = tempView->GetParent();
|
||||
}
|
||||
if ((tempView == nullptr) || !tempView->IsDraggable()) {
|
||||
return nullptr;
|
||||
}
|
||||
return tempView;
|
||||
}
|
||||
};
|
||||
}; // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_POINTER_INPUT_DEVICE_H
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/rotate_input_device.h"
|
||||
#include "dock/focus_manager.h"
|
||||
|
||||
#if ENABLE_ROTATE_INPUT
|
||||
namespace OHOS {
|
||||
static int8_t g_rotateCtrl = INT8_MIN;
|
||||
void RotateInputDevice::DispatchEvent(const DeviceData& data)
|
||||
{
|
||||
UIView *view_ = FocusManager::GetInstance()->GetFocusedView();
|
||||
if (view_ == nullptr) {
|
||||
return;
|
||||
} else if (g_rotateCtrl == INT8_MIN) {
|
||||
g_rotateCtrl = INT8_MAX;
|
||||
return;
|
||||
} else if (data.rotate == 0 && g_rotateCtrl == NULL) {
|
||||
view_->OnRotateEvent(0);
|
||||
g_rotateCtrl = INT8_MAX;
|
||||
return;
|
||||
} else if (data.rotate == 0) {
|
||||
return;
|
||||
} else {
|
||||
g_rotateCtrl = data.rotate;
|
||||
view_->OnRotateEvent(g_rotateCtrl);
|
||||
g_rotateCtrl = NULL;
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
#endif
|
||||
Executable
+202
@@ -0,0 +1,202 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_SCREEN_DEVICE_H
|
||||
#define GRAPHIC_LITE_SCREEN_DEVICE_H
|
||||
|
||||
#include "color.h"
|
||||
#include "graphic_semaphore.h"
|
||||
#include "graphic_assert.h"
|
||||
#include "rect.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "pixel_format_utils.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
#if ENABLE_WINDOW
|
||||
struct AllocationInfo {
|
||||
uint8_t* virAddr;
|
||||
uint8_t* phyAddr;
|
||||
uint16_t width;
|
||||
uint16_t height;
|
||||
uint32_t stride;
|
||||
ImagePixelFormat pixelFormat;
|
||||
};
|
||||
#endif
|
||||
|
||||
struct TransformOption {
|
||||
TransformAlgorithm algorithm;
|
||||
};
|
||||
|
||||
/** @brief A semaphore for display buffer flushing. */
|
||||
class FlushSem : public HeapBase {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @param [in] isFlushing (Optional) True if is flushing, false if not.
|
||||
*/
|
||||
FlushSem(bool isFlushing = false) : sem_(1, 1), isFlushing_(isFlushing) {}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~FlushSem() {}
|
||||
|
||||
/** Notifies the buffer is flushing end */
|
||||
void Notify()
|
||||
{
|
||||
isFlushing_ = false;
|
||||
sem_.Notify();
|
||||
}
|
||||
|
||||
/** Waits the buffer is flushing */
|
||||
void Wait()
|
||||
{
|
||||
while (isFlushing_) {
|
||||
sem_.Wait();
|
||||
}
|
||||
}
|
||||
|
||||
/** set the flag as flashing */
|
||||
void Flushing()
|
||||
{
|
||||
isFlushing_ = true;
|
||||
}
|
||||
|
||||
private:
|
||||
GraphicSemaphore sem_;
|
||||
bool isFlushing_;
|
||||
};
|
||||
|
||||
/** @brief A display device. */
|
||||
class ScreenDevice : public HeapBase {
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
*/
|
||||
ScreenDevice() {}
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
virtual ~ScreenDevice() {}
|
||||
|
||||
virtual void Flush(int16_t x1, int16_t y1, int16_t x2, int16_t y2, const uint8_t* buffer, ColorMode mode) {}
|
||||
|
||||
virtual void Fill(int16_t x1, int16_t y1, int16_t x2, int16_t y2, const ColorType& color) {}
|
||||
|
||||
/**
|
||||
* @brief Hardware accelerated filling interface implemented by the product platform
|
||||
* @param fillArea Indicates the area to be filled
|
||||
* @param color Indicates the color to be filled
|
||||
* @param opa Indicates the transparency
|
||||
* @param dst Indicates the start address of destination memory
|
||||
* @param dstStride Indicates the number of bytes in a single row of destination memory
|
||||
* @param dstColorMode Indicates the color format of destination memory
|
||||
* @return Return true on success, false on failure
|
||||
* @since 5.0
|
||||
* @version 3.0
|
||||
*/
|
||||
virtual bool HardwareFill(const Rect& fillArea,
|
||||
uint32_t color,
|
||||
OpacityType opa,
|
||||
uint8_t* dst,
|
||||
uint32_t dstStride,
|
||||
ColorMode dstColorMode)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hardware accelerated blending interface implemented by the product platform
|
||||
* @param src Indicates the start address of source memory
|
||||
* @param srcRect Indicates the area of the source memory for color blending
|
||||
* @param srcStride Indicates the number of bytes in a single row of source memory
|
||||
* @param srcLineNumber Indicates the number of source memory rows
|
||||
* @param srcColorMode Indicates the source memory color format
|
||||
* @param color 32-bit XRGB8888 value
|
||||
* (valid when the source memory is in a format with only alph information such as A1)
|
||||
* @param opa Indicates the transparency
|
||||
* @param dst Indicates the start address of destination memory
|
||||
* @param dstStride Indicates the number of bytes in a single row of destination memory
|
||||
* @param dstColorMode Indicates the color format of destination memory
|
||||
* @param x The x coordinate of the upper left vertex of the destination memory for color blending
|
||||
* @param y The y coordinate of the upper left vertex of the destination memory for color blending
|
||||
* @return Return true on success, false on failure
|
||||
* @since 5.0
|
||||
* @version 3.0
|
||||
*/
|
||||
virtual bool HardwareBlend(const uint8_t* src,
|
||||
const Rect& srcRect,
|
||||
uint32_t srcStride,
|
||||
uint32_t srcLineNumber,
|
||||
ColorMode srcColorMode,
|
||||
uint32_t color,
|
||||
OpacityType opa,
|
||||
uint8_t* dst,
|
||||
uint32_t dstStride,
|
||||
ColorMode dstColorMode,
|
||||
uint32_t x,
|
||||
uint32_t y)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Hardware accelerated transformation interface implemented by the product platform
|
||||
* @param src Indicates the start address of the source image
|
||||
* @param srcColorMode Indicates the color format of the source image
|
||||
* @param srcRect Indicates the position of the source image in the destination memory and its width and height
|
||||
* @param transformMatrix Indicates the transformation matrix
|
||||
* @param opa Indicates the transparency
|
||||
* @param color 32-bit XRGB8888 value
|
||||
* (valid when the source memory is in a format with only alph information such as A1)
|
||||
* @param mask Indicates the masking rectangle, and the content beyond the rectangle is not drawn
|
||||
* @param dst Indicates the start address of destination memory
|
||||
* @param dstStride Indicates the number of bytes in a single row of destination memory
|
||||
* @param dstColorMode Indicates the color format of destination memory
|
||||
* @param option Indicates the optional setting items for transformation operation
|
||||
* @return Return true on success, false on failure
|
||||
* @since 5.0
|
||||
* @version 3.0
|
||||
*/
|
||||
virtual bool HardwareTransform(const uint8_t* src,
|
||||
ColorMode srcColorMode,
|
||||
const Rect& srcRect,
|
||||
const Matrix3<float>& transformMatrix,
|
||||
OpacityType opa,
|
||||
uint32_t color,
|
||||
const Rect& mask,
|
||||
uint8_t* dst,
|
||||
uint32_t dstStride,
|
||||
ColorMode dstColorMode,
|
||||
const TransformOption& option)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
virtual void SnapShot(uint32_t len,
|
||||
bool justCopy,
|
||||
uint8_t* dest,
|
||||
const Rect& rect,
|
||||
bool justRender)
|
||||
{
|
||||
}
|
||||
|
||||
virtual void RenderFinish() {}
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_SCREEN_DEVICE_H
|
||||
Executable
+232
@@ -0,0 +1,232 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_SCREEN_DEVICE_PROXY_H
|
||||
#define GRAPHIC_LITE_SCREEN_DEVICE_PROXY_H
|
||||
|
||||
#include "color.h"
|
||||
#include "dock/screen_device.h"
|
||||
#include "graphic_assert.h"
|
||||
#include "graphic_semaphore.h"
|
||||
#include "image_info.h"
|
||||
#include "rect.h"
|
||||
#include "transform.h"
|
||||
#if ENABLE_WINDOW
|
||||
#include "surface.h"
|
||||
#endif
|
||||
|
||||
namespace OHOS {
|
||||
/** @brief A display device proxy */
|
||||
class ScreenDeviceProxy : public HeapBase {
|
||||
public:
|
||||
static ScreenDeviceProxy* GetInstance()
|
||||
{
|
||||
static ScreenDeviceProxy instance;
|
||||
return &instance;
|
||||
}
|
||||
|
||||
void SetDevice(ScreenDevice* device)
|
||||
{
|
||||
device_ = device;
|
||||
}
|
||||
|
||||
void Flush();
|
||||
|
||||
void OnFlushReady();
|
||||
|
||||
void OnRenderFinish();
|
||||
|
||||
bool HardwareFill(const Rect& fillArea,
|
||||
uint32_t color,
|
||||
OpacityType opa,
|
||||
uint8_t* dst,
|
||||
uint32_t dstStride,
|
||||
ColorMode dstColorMode)
|
||||
{
|
||||
if (device_ != nullptr) {
|
||||
return device_->HardwareFill(fillArea, color, opa, dst, dstStride, dstColorMode);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HardwareBlend(const uint8_t* src,
|
||||
const Rect& srcRect,
|
||||
uint32_t srcStride,
|
||||
uint32_t srcLineNumber,
|
||||
ColorMode srcColorMode,
|
||||
uint32_t color,
|
||||
OpacityType opa,
|
||||
uint8_t* dst,
|
||||
uint32_t dstStride,
|
||||
ColorMode dstColorMode,
|
||||
uint32_t x,
|
||||
uint32_t y)
|
||||
{
|
||||
if (device_ != nullptr) {
|
||||
return device_->HardwareBlend(src, srcRect, srcStride, srcLineNumber, srcColorMode, color, opa, dst,
|
||||
dstStride, dstColorMode, x, y);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool HardwareTransform(const uint8_t* src,
|
||||
ColorMode srcColorMode,
|
||||
const Rect& srcRect,
|
||||
const Matrix3<float>& transformMatrix,
|
||||
OpacityType opa,
|
||||
uint32_t color,
|
||||
const Rect& mask,
|
||||
uint8_t* dst,
|
||||
uint32_t dstStride,
|
||||
ColorMode dstColorMode,
|
||||
const TransformOption& option)
|
||||
{
|
||||
if (device_ != nullptr) {
|
||||
return device_->HardwareTransform(src, srcColorMode, srcRect, transformMatrix, opa, color, mask, dst,
|
||||
dstStride, dstColorMode, option);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void SnapShot(uint32_t len, bool justCopy, uint8_t* dest, const Rect& rect, bool justRender)
|
||||
{
|
||||
if (device_ != nullptr) {
|
||||
device_->SnapShot(len, justCopy, dest, rect, justRender);
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_FRAME_BUFFER
|
||||
void SetFramebuffer(uint8_t* addr, ColorMode mode, uint16_t width)
|
||||
{
|
||||
frameBufferAddr_ = addr;
|
||||
frameBufferWidth_ = width;
|
||||
frameBufferMode_ = mode;
|
||||
}
|
||||
#endif
|
||||
|
||||
void SetAnimatorbuffer(uint8_t* addr, ColorMode mode, uint16_t width)
|
||||
{
|
||||
animatorBufferAddr_ = addr;
|
||||
animatorBufferWidth_ = width;
|
||||
animatorBufferMode_ = mode;
|
||||
}
|
||||
|
||||
void SetAnimatorbufferWidth(uint16_t width)
|
||||
{
|
||||
animatorBufferWidth_ = width;
|
||||
}
|
||||
|
||||
void EnableAnimatorBuffer(bool status)
|
||||
{
|
||||
useAnimatorBuff_ = status;
|
||||
}
|
||||
|
||||
void SetAnimatorRect(const Rect& rect);
|
||||
|
||||
void SetAnimatorTransMap(TransformMap& transMap)
|
||||
{
|
||||
transMap_ = transMap;
|
||||
}
|
||||
|
||||
void DrawAnimatorBuffer(const Rect& invalidatedArea);
|
||||
|
||||
bool GetAnimatorBufferStatus()
|
||||
{
|
||||
return useAnimatorBuff_;
|
||||
}
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
AllocationInfo& GetAllocationInfo()
|
||||
{
|
||||
return gfxAlloc_;
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t GetBufferWidth() const
|
||||
{
|
||||
if (useAnimatorBuff_) {
|
||||
return animatorBufferWidth_;
|
||||
}
|
||||
#if ENABLE_FRAME_BUFFER
|
||||
return frameBufferWidth_;
|
||||
#elif ENABLE_WINDOW
|
||||
return gfxAlloc_.stride / sizeof(ColorType);
|
||||
#else
|
||||
return bufferRect_.GetWidth();
|
||||
#endif
|
||||
}
|
||||
|
||||
Rect& GetBufferRect()
|
||||
{
|
||||
return bufferRect_;
|
||||
}
|
||||
|
||||
void SetScreenSize(uint16_t width, uint16_t height);
|
||||
|
||||
uint16_t GetScreenWidth() const
|
||||
{
|
||||
return width_;
|
||||
}
|
||||
|
||||
uint16_t GetScreenHeight() const
|
||||
{
|
||||
return height_;
|
||||
}
|
||||
|
||||
uint32_t GetScreenArea() const
|
||||
{
|
||||
return width_ * height_;
|
||||
}
|
||||
|
||||
uint8_t* GetBuffer();
|
||||
|
||||
ColorMode GetBufferMode();
|
||||
|
||||
private:
|
||||
ScreenDeviceProxy() {}
|
||||
virtual ~ScreenDeviceProxy() {}
|
||||
|
||||
ScreenDeviceProxy(const ScreenDeviceProxy&) = delete;
|
||||
ScreenDeviceProxy& operator=(const ScreenDeviceProxy&) = delete;
|
||||
ScreenDeviceProxy(ScreenDeviceProxy&&) = delete;
|
||||
ScreenDeviceProxy& operator=(ScreenDeviceProxy&&) = delete;
|
||||
|
||||
ScreenDevice* device_ = nullptr;
|
||||
FlushSem flush_ = FlushSem(false);
|
||||
uint16_t width_ = HORIZONTAL_RESOLUTION;
|
||||
uint16_t height_ = VERTICAL_RESOLUTION;
|
||||
uint8_t* buffer_ = nullptr;
|
||||
Rect bufferRect_;
|
||||
|
||||
#if ENABLE_FRAME_BUFFER
|
||||
uint8_t* frameBufferAddr_ = nullptr;
|
||||
uint16_t frameBufferWidth_ = 0;
|
||||
ColorMode frameBufferMode_ = ARGB8888;
|
||||
#endif
|
||||
|
||||
uint8_t* animatorBufferAddr_ = nullptr;
|
||||
uint16_t animatorBufferWidth_ = 0;
|
||||
ColorMode animatorBufferMode_ = ARGB8888;
|
||||
Rect curViewRect_;
|
||||
TransformMap transMap_;
|
||||
bool useAnimatorBuff_ = false;
|
||||
ImageInfo animatorImageInfo_ = {{0}};
|
||||
|
||||
#if ENABLE_WINDOW
|
||||
AllocationInfo gfxAlloc_ = {0};
|
||||
#endif
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_SCREEN_DEVICE_PROXY_H
|
||||
Executable
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "dock/virtual_input_device.h"
|
||||
#include "components/root_view.h"
|
||||
#include "events/virtual_device_event.h"
|
||||
|
||||
#if USE_VIRTUAL_DEVICE
|
||||
namespace OHOS {
|
||||
void VirtualInputDevice::DispatchEvent(const DeviceData& data)
|
||||
{
|
||||
if (data.state != INVALID_VIRTUAL_INPUT_STATE) {
|
||||
VirtualDeviceEvent event(data.type, data.state);
|
||||
RootView::GetInstance()->OnVirtualDeviceEvent(event);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
#endif
|
||||
Executable
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_VIRTUAL_INPUT_DEVICE_H
|
||||
#define GRAPHIC_LITE_VIRTUAL_INPUT_DEVICE_H
|
||||
|
||||
#include "dock/input_device.h"
|
||||
#include "graphic_config.h"
|
||||
|
||||
#if USE_VIRTUAL_DEVICE
|
||||
namespace OHOS {
|
||||
/** @brief virtual input device. */
|
||||
class VirtualInputDevice : public InputDevice {
|
||||
public:
|
||||
/** @brief Constructor */
|
||||
VirtualInputDevice() {}
|
||||
|
||||
/** @brief Destructor */
|
||||
virtual ~VirtualInputDevice() {}
|
||||
|
||||
private:
|
||||
void DispatchEvent(const DeviceData& data) override;
|
||||
|
||||
VirtualInputDevice(const VirtualInputDevice&) = delete;
|
||||
VirtualInputDevice& operator=(const VirtualInputDevice&) = delete;
|
||||
VirtualInputDevice(VirtualInputDevice&&) = delete;
|
||||
VirtualInputDevice& operator=(VirtualInputDevice&&) = delete;
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif
|
||||
#endif // GRAPHIC_LITE_VIRTUAL_INPUT_DEVICE_H
|
||||
Executable
+490
@@ -0,0 +1,490 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_arc.h"
|
||||
#include "common/image.h"
|
||||
#include "graphic_math.h"
|
||||
|
||||
namespace OHOS {
|
||||
#define IS_IN_DEGREERANE(d, s, e) ((s) <= (e)) ? (((d) >= (s)) && ((d) <= (e))) : (((d) >= (s)) || ((d) <= (e)))
|
||||
|
||||
void DrawArc::DrawImg(const Point& imgPos,
|
||||
Rect& area,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
const Image* image)
|
||||
{
|
||||
if (image == nullptr) {
|
||||
return;
|
||||
}
|
||||
ImageHeader header = {0};
|
||||
image->GetHeader(header);
|
||||
|
||||
Rect cordsTmp;
|
||||
cordsTmp.SetPosition(imgPos.x, imgPos.y);
|
||||
cordsTmp.SetHeight(header.height);
|
||||
cordsTmp.SetWidth(header.width);
|
||||
if (area.Intersect(area, invalidatedArea)) {
|
||||
image->DrawImage(cordsTmp, area, style, opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArc::DrawVerLine(const Point& begin,
|
||||
const Point& imgPos,
|
||||
const Rect& mask,
|
||||
int16_t len,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
const Image* image)
|
||||
{
|
||||
Rect rect(begin.x, begin.y, begin.x, begin.y + len);
|
||||
if ((image != nullptr) && (image->GetSrcType() != IMG_SRC_UNKNOWN)) {
|
||||
DrawImg(imgPos, rect, mask, style, opaScale, image);
|
||||
} else {
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, style.lineColor_, opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArc::DrawHorLine(const Point& begin,
|
||||
const Point& imgPos,
|
||||
const Rect& mask,
|
||||
int16_t len,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
const Image* image)
|
||||
{
|
||||
if ((image != nullptr) && (image->GetSrcType() != IMG_SRC_UNKNOWN)) {
|
||||
Rect rect(begin.x, begin.y, begin.x + len, begin.y);
|
||||
DrawImg(imgPos, rect, mask, style, opaScale, image);
|
||||
} else {
|
||||
if (len == 0) {
|
||||
DrawUtils::GetInstance()->DrawPixel(begin.x, begin.y, mask, style.lineColor_, opaScale);
|
||||
} else {
|
||||
Rect rect(begin.x, begin.y, begin.x + len, begin.y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, style.lineColor_, opaScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int16_t DrawArc::GetDrawAngle(int16_t angle)
|
||||
{
|
||||
if (angle < 0) {
|
||||
angle = (angle % CIRCLE_IN_DEGREE) + CIRCLE_IN_DEGREE;
|
||||
} else if (angle > CIRCLE_IN_DEGREE) {
|
||||
angle = angle % CIRCLE_IN_DEGREE;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
void DrawArc::GetDrawRange(int16_t& start, int16_t& end)
|
||||
{
|
||||
int16_t tempAngle = GetDrawAngle(start);
|
||||
if (start == end) {
|
||||
start = tempAngle;
|
||||
end = tempAngle;
|
||||
} else if (end - start >= CIRCLE_IN_DEGREE) {
|
||||
// draw circle
|
||||
start = 0;
|
||||
end = CIRCLE_IN_DEGREE;
|
||||
} else {
|
||||
start = tempAngle;
|
||||
end = GetDrawAngle(end);
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t DrawArc::CalculateTanDegree(uint16_t x, uint16_t y)
|
||||
{
|
||||
uint16_t degree = FastAtan2(x, y);
|
||||
if ((degree == QUARTER_IN_DEGREE) && (y != 0)) {
|
||||
degree--;
|
||||
}
|
||||
if ((degree == 0) && (x != 0)) {
|
||||
degree++;
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
void DrawArc::DrawCircleNoEndpoint(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opa, bool anti)
|
||||
{
|
||||
DrawAxisLine(arcInfo, mask, style, opa);
|
||||
|
||||
int16_t yStart = mask.GetTop() - arcInfo.center.y;
|
||||
int16_t yEnd = mask.GetBottom() - arcInfo.center.y;
|
||||
if ((yStart >= 0) && (yEnd >= 0)) {
|
||||
int16_t tmp = yStart;
|
||||
yStart = -yEnd;
|
||||
yEnd = -tmp;
|
||||
} else if ((yStart < 0) && (yEnd > 0)) {
|
||||
yStart = MATH_MIN(yStart, -yEnd);
|
||||
yEnd = -1;
|
||||
}
|
||||
yStart = MATH_MAX(yStart, -outRadius_) - 1;
|
||||
yEnd = MATH_MIN(yEnd, -1);
|
||||
|
||||
int16_t xi;
|
||||
int16_t xLineStart = -outRadius_;
|
||||
int16_t xLineStart2 = xLineStart - 1;
|
||||
int16_t xLineStart3 = COORD_MIN;
|
||||
|
||||
for (y_ = yEnd; y_ > yStart; y_--) {
|
||||
ySqr_ = static_cast<int32_t>(y_) * y_;
|
||||
bool isSetStartPot = false;
|
||||
for (xi = xLineStart2; xi < 0; xi++) {
|
||||
uint32_t currentSqr = static_cast<int32_t>(xi) * xi + ySqr_;
|
||||
if (currentSqr > outRadiusSqr_) {
|
||||
continue;
|
||||
}
|
||||
if (!isSetStartPot) {
|
||||
xLineStart2 = xi;
|
||||
lineStart_ = xi;
|
||||
if (xLineStart3 != COORD_MIN) {
|
||||
xi = xLineStart3;
|
||||
}
|
||||
isSetStartPot = true;
|
||||
}
|
||||
if (y_ <= -inRadius_) {
|
||||
lineEnd_ = -1;
|
||||
xi = -1;
|
||||
break;
|
||||
}
|
||||
if (currentSqr < inRadiusSqr_) {
|
||||
xLineStart3 = xi - 1;
|
||||
lineEnd_ = xi - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!isSetStartPot) {
|
||||
continue;
|
||||
}
|
||||
#if ENABLE_ANTIALIAS
|
||||
if (anti) {
|
||||
DrawLineAnti(arcInfo, mask, style, opa);
|
||||
}
|
||||
#endif
|
||||
DrawLineWithDegree(arcInfo, -lineEnd_, -lineStart_, y_, mask, style, opa, ARC_QUADRANT_ONE);
|
||||
|
||||
DrawLineWithDegree(arcInfo, -lineEnd_, -lineStart_, -y_, mask, style, opa, ARC_QUADRANT_TWO);
|
||||
|
||||
DrawLineWithDegree(arcInfo, lineStart_, lineEnd_, -y_, mask, style, opa, ARC_QUADRANT_THREE);
|
||||
|
||||
DrawLineWithDegree(arcInfo, lineStart_, lineEnd_, y_, mask, style, opa, ARC_QUADRANT_FOUR);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArc::DrawAxisLine(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opa)
|
||||
{
|
||||
int16_t lineWidth = 0;
|
||||
int16_t outRadius = outRadius_ - 1;
|
||||
int16_t inRadius = inRadius_;
|
||||
if (inRadius <= 0) {
|
||||
inRadius = 1;
|
||||
DrawHorLine(arcInfo.center, arcInfo.imgPos, mask, 0, style, opa, arcInfo.imgSrc);
|
||||
}
|
||||
lineWidth = outRadius - inRadius;
|
||||
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(THREE_QUARTER_IN_DEGREE, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
DrawHorLine(Point{static_cast<int16_t>(arcInfo.center.x - outRadius), arcInfo.center.y}, arcInfo.imgPos, mask,
|
||||
lineWidth, style, opa, arcInfo.imgSrc);
|
||||
}
|
||||
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(QUARTER_IN_DEGREE, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
DrawHorLine(Point{static_cast<int16_t>(arcInfo.center.x + inRadius), arcInfo.center.y}, arcInfo.imgPos, mask,
|
||||
lineWidth, style, opa, arcInfo.imgSrc);
|
||||
}
|
||||
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(0, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
DrawVerLine(Point{arcInfo.center.x, static_cast<int16_t>(arcInfo.center.y - outRadius)}, arcInfo.imgPos, mask,
|
||||
lineWidth, style, opa, arcInfo.imgSrc);
|
||||
}
|
||||
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(SEMICIRCLE_IN_DEGREE, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
DrawVerLine(Point{arcInfo.center.x, static_cast<int16_t>(arcInfo.center.y + inRadius)}, arcInfo.imgPos, mask,
|
||||
lineWidth, style, opa, arcInfo.imgSrc);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArc::DrawLineWithDegree(ArcInfo& arcInfo,
|
||||
int16_t start,
|
||||
int16_t end,
|
||||
int16_t y,
|
||||
const Rect& mask,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
uint8_t quadrant)
|
||||
{
|
||||
if (isCircle_) {
|
||||
DrawHorLine(Point{static_cast<int16_t>(arcInfo.center.x + start), static_cast<int16_t>(arcInfo.center.y + y)},
|
||||
arcInfo.imgPos, mask, end - start, style, opaScale, arcInfo.imgSrc);
|
||||
return;
|
||||
}
|
||||
uint16_t degreeStart = GetDegreeInQuadrant(CalculateTanDegree(MATH_ABS(start), MATH_ABS(y)), quadrant);
|
||||
uint16_t degreeEnd = GetDegreeInQuadrant(CalculateTanDegree(MATH_ABS(end), MATH_ABS(y)), quadrant);
|
||||
if (degreeStart > degreeEnd) {
|
||||
uint16_t tmp = degreeStart;
|
||||
degreeStart = degreeEnd;
|
||||
degreeEnd = tmp;
|
||||
}
|
||||
|
||||
int16_t lineDegreeRet = GetDegreeRangeIntersectState(degreeStart, degreeEnd, arcInfo.startAngle, arcInfo.endAngle);
|
||||
int16_t drawEnd = 0;
|
||||
switch (lineDegreeRet) {
|
||||
case OUT_DEGREE_RANG:
|
||||
return;
|
||||
case IN_DEGREE_RANG:
|
||||
DrawHorLine(
|
||||
Point{static_cast<int16_t>(arcInfo.center.x + start), static_cast<int16_t>(arcInfo.center.y + y)},
|
||||
arcInfo.imgPos, mask, end - start, style, opaScale, arcInfo.imgSrc);
|
||||
return;
|
||||
case INTERSECT:
|
||||
DrawLineWithDegreeInner(arcInfo, start, end, y, mask, style, opaScale, quadrant);
|
||||
return;
|
||||
case DOUBLE_INTERSECT:
|
||||
drawEnd = DrawLineWithDegreeInner(arcInfo, start, end, y, mask, style, opaScale, quadrant);
|
||||
DrawLineWithDegreeInner(arcInfo, drawEnd + 1, end, y, mask, style, opaScale, quadrant);
|
||||
return;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
int16_t DrawArc::DrawLineWithDegreeInner(ArcInfo& arcInfo,
|
||||
int16_t start,
|
||||
int16_t end,
|
||||
int16_t y,
|
||||
const Rect& mask,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
uint8_t quadrant)
|
||||
{
|
||||
int16_t drawStart = COORD_MIN;
|
||||
int16_t drawEnd = COORD_MIN;
|
||||
for (int16_t xi = start; xi <= end; xi++) {
|
||||
uint16_t degreeBase = CalculateTanDegree(MATH_ABS(xi), MATH_ABS(y));
|
||||
uint16_t degree = GetDegreeInQuadrant(degreeBase, quadrant);
|
||||
if (IS_IN_DEGREERANE(degree, arcInfo.startAngle, arcInfo.endAngle)) {
|
||||
if (drawStart == COORD_MIN) {
|
||||
drawStart = xi;
|
||||
}
|
||||
} else {
|
||||
if ((drawStart != COORD_MIN) && (drawEnd == COORD_MIN)) {
|
||||
drawEnd = xi - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (drawEnd == COORD_MIN) {
|
||||
drawEnd = end;
|
||||
}
|
||||
if ((drawStart != COORD_MIN) && (drawEnd != COORD_MIN)) {
|
||||
DrawHorLine(
|
||||
Point{static_cast<int16_t>(arcInfo.center.x + drawStart), static_cast<int16_t>(arcInfo.center.y + y)},
|
||||
arcInfo.imgPos, mask, drawEnd - drawStart, style, opaScale, arcInfo.imgSrc);
|
||||
}
|
||||
return drawEnd;
|
||||
}
|
||||
|
||||
#if ENABLE_ANTIALIAS
|
||||
void DrawArc::DrawLineAnti(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opa)
|
||||
{
|
||||
outAntiStart_ = lineStart_;
|
||||
outAntiEnd_ = lineStart_;
|
||||
inAntiStart_ = lineEnd_ + 1;
|
||||
inAntiEnd_ = COORD_MIN;
|
||||
|
||||
for (int16_t xAnti = lineStart_; xAnti <= lineEnd_; xAnti++) {
|
||||
uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
|
||||
if ((currentSqr <= antiOutRadiusSqr_) || (xAnti == lineEnd_)) {
|
||||
lineStart_ = xAnti;
|
||||
outAntiEnd_ = xAnti - 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int16_t xAnti = lineEnd_ + 1; xAnti <= -1; xAnti++) {
|
||||
uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
|
||||
if ((currentSqr <= antiInRadiusSqr_) || (xAnti == -1)) {
|
||||
inAntiEnd_ = xAnti;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int16_t xAnti = outAntiStart_; xAnti <= outAntiEnd_; xAnti++) {
|
||||
uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
|
||||
uint8_t antiOpa =
|
||||
(((static_cast<uint64_t>(outRadius_) << 1) - 1 - (currentSqr - antiOutRadiusSqr_)) * OPA_OPAQUE) /
|
||||
((outRadius_ << 1) - 1);
|
||||
antiOpa = (opa == OPA_OPAQUE) ? antiOpa : (static_cast<uint16_t>(antiOpa) * opa) >> SHIFT_8;
|
||||
DrawPointAnti(arcInfo, xAnti, mask, style, antiOpa);
|
||||
}
|
||||
|
||||
for (int16_t xAnti = inAntiStart_; xAnti <= inAntiEnd_; xAnti++) {
|
||||
uint32_t currentSqr = static_cast<int32_t>(xAnti) * xAnti + ySqr_;
|
||||
if (currentSqr <= antiInRadiusSqr_) {
|
||||
break;
|
||||
}
|
||||
uint8_t antiOpa = (static_cast<uint64_t>(currentSqr - antiInRadiusSqr_) * OPA_OPAQUE) / ((inRadius_ << 1) - 1);
|
||||
antiOpa = (opa == OPA_OPAQUE) ? antiOpa : (static_cast<uint16_t>(antiOpa) * opa) >> SHIFT_8;
|
||||
DrawPointAnti(arcInfo, xAnti, mask, style, antiOpa);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArc::DrawPointAnti(ArcInfo& arcInfo, int16_t x, const Rect& mask, const Style& style, uint8_t antiOpa)
|
||||
{
|
||||
int16_t startX;
|
||||
int16_t starty;
|
||||
uint16_t degreeBase = CalculateTanDegree(MATH_ABS(x), MATH_ABS(y_));
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(CIRCLE_IN_DEGREE - degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
startX = arcInfo.center.x + x;
|
||||
starty = arcInfo.center.y + y_;
|
||||
DrawHorLine(Point{startX, starty}, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
|
||||
}
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(SEMICIRCLE_IN_DEGREE + degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
startX = arcInfo.center.x + x;
|
||||
starty = arcInfo.center.y - y_;
|
||||
DrawHorLine(Point{startX, starty}, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
|
||||
}
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
startX = arcInfo.center.x - x;
|
||||
starty = arcInfo.center.y + y_;
|
||||
DrawHorLine(Point{startX, starty}, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
|
||||
}
|
||||
if (isCircle_ || (IS_IN_DEGREERANE(SEMICIRCLE_IN_DEGREE - degreeBase, arcInfo.startAngle, arcInfo.endAngle))) {
|
||||
startX = arcInfo.center.x - x;
|
||||
starty = arcInfo.center.y - y_;
|
||||
DrawHorLine(Point{startX, starty}, arcInfo.imgPos, mask, 0, style, antiOpa, arcInfo.imgSrc);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
uint16_t DrawArc::GetDegreeInQuadrant(uint16_t degree, uint8_t quadrant)
|
||||
{
|
||||
switch (quadrant) {
|
||||
case ARC_QUADRANT_ONE:
|
||||
return degree;
|
||||
case ARC_QUADRANT_TWO:
|
||||
return SEMICIRCLE_IN_DEGREE - degree;
|
||||
case ARC_QUADRANT_THREE:
|
||||
return SEMICIRCLE_IN_DEGREE + degree;
|
||||
case ARC_QUADRANT_FOUR:
|
||||
return CIRCLE_IN_DEGREE - degree;
|
||||
default:
|
||||
return degree;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawArc::Draw(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opaScale, uint8_t cap)
|
||||
{
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.lineOpa_);
|
||||
if ((opa == OPA_TRANSPARENT) || (style.lineWidth_ < 1) || (arcInfo.startAngle == arcInfo.endAngle)) {
|
||||
return;
|
||||
}
|
||||
|
||||
SetArcInfo(arcInfo, style);
|
||||
|
||||
if ((arcInfo.imgSrc != nullptr) && (arcInfo.imgSrc->GetSrcType() != IMG_SRC_UNKNOWN)) {
|
||||
DrawCircleNoEndpoint(arcInfo, mask, style, opa, false);
|
||||
} else {
|
||||
DrawCircleNoEndpoint(arcInfo, mask, style, opa, true);
|
||||
}
|
||||
|
||||
if (!isCircle_ && (cap == CapType::CAP_ROUND)) {
|
||||
int16_t lineWidth = style.lineWidth_;
|
||||
if (lineWidth > arcInfo.radius) {
|
||||
lineWidth = arcInfo.radius;
|
||||
}
|
||||
|
||||
ArcInfo endArcInfo = arcInfo;
|
||||
endArcInfo.startAngle = 0;
|
||||
endArcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
|
||||
int16_t outRadius = arcInfo.radius - 1;
|
||||
lineWidth--;
|
||||
/* the arc radius of the round cap should be half the line width */
|
||||
endArcInfo.radius = (static_cast<uint16_t>(lineWidth + 1) >> 1) + 1;
|
||||
|
||||
/* 0.5: round up */
|
||||
float temp = (outRadius - endArcInfo.radius + 1) * Sin(arcInfo.startAngle);
|
||||
int16_t startCapX = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
|
||||
|
||||
temp = (outRadius - endArcInfo.radius + 1) * Sin(QUARTER_IN_DEGREE - arcInfo.startAngle);
|
||||
int16_t startCapY = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
|
||||
|
||||
endArcInfo.center.x += startCapX;
|
||||
endArcInfo.center.y -= startCapY;
|
||||
SetArcInfo(endArcInfo, style);
|
||||
DrawCircleNoEndpoint(endArcInfo, mask, style, opa, true);
|
||||
|
||||
temp = (outRadius - endArcInfo.radius + 1) * Sin(arcInfo.endAngle);
|
||||
int16_t endCapX = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
|
||||
|
||||
temp = (outRadius - endArcInfo.radius + 1) * Sin(QUARTER_IN_DEGREE - arcInfo.endAngle);
|
||||
int16_t endCapY = static_cast<int16_t>((temp > 0) ? (temp + 0.5f) : (temp - 0.5f));
|
||||
|
||||
endArcInfo.center = arcInfo.center;
|
||||
endArcInfo.center.x += endCapX;
|
||||
endArcInfo.center.y -= endCapY;
|
||||
SetArcInfo(endArcInfo, style);
|
||||
DrawCircleNoEndpoint(endArcInfo, mask, style, opa, true);
|
||||
}
|
||||
}
|
||||
|
||||
int16_t DrawArc::GetDegreeRangeIntersectState(uint16_t degreeStart, uint16_t degreeEnd, uint16_t start, uint16_t end)
|
||||
{
|
||||
if (start <= end) {
|
||||
if ((degreeStart >= start) && (degreeStart <= end) && (degreeEnd >= start) && (degreeEnd <= end)) {
|
||||
return IN_DEGREE_RANG;
|
||||
} else if ((degreeEnd < start) || (degreeStart > end)) {
|
||||
return OUT_DEGREE_RANG;
|
||||
} else {
|
||||
return INTERSECT;
|
||||
}
|
||||
} else {
|
||||
if (((degreeStart >= start) && (degreeEnd >= start)) || ((degreeStart <= end) && (degreeEnd <= end))) {
|
||||
return IN_DEGREE_RANG;
|
||||
} else if ((degreeStart > end) && (degreeEnd < start)) {
|
||||
return OUT_DEGREE_RANG;
|
||||
} else if ((degreeStart <= end) && (degreeEnd >= start)) {
|
||||
return DOUBLE_INTERSECT;
|
||||
} else {
|
||||
return INTERSECT;
|
||||
}
|
||||
}
|
||||
}
|
||||
void DrawArc::SetArcInfo(ArcInfo& arcInfo, const Style& style)
|
||||
{
|
||||
outRadius_ = arcInfo.radius;
|
||||
inRadius_ = outRadius_ - style.lineWidth_;
|
||||
if (inRadius_ < 0) {
|
||||
inRadius_ = 0;
|
||||
}
|
||||
outRadiusSqr_ = outRadius_ * outRadius_;
|
||||
inRadiusSqr_ = inRadius_ * inRadius_;
|
||||
|
||||
if ((arcInfo.startAngle == 0) && (arcInfo.endAngle == CIRCLE_IN_DEGREE)) {
|
||||
isCircle_ = true;
|
||||
} else {
|
||||
isCircle_ = false;
|
||||
}
|
||||
#if ENABLE_ANTIALIAS
|
||||
antiOutRadiusSqr_ = (outRadius_ - 1) * (outRadius_ - 1);
|
||||
if (inRadius_ == 0) {
|
||||
antiInRadiusSqr_ = 0;
|
||||
} else {
|
||||
antiInRadiusSqr_ = (inRadius_ - 1) * (inRadius_ - 1);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+146
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_ARC_H
|
||||
#define GRAPHIC_LITE_DRAW_ARC_H
|
||||
#include "common/image.h"
|
||||
#include "draw_image.h"
|
||||
#include "draw_utils.h"
|
||||
#include "graphic_math.h"
|
||||
#include "heap_base.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
#include "style.h"
|
||||
|
||||
namespace OHOS {
|
||||
struct ArcInfo {
|
||||
Point center;
|
||||
Point imgPos;
|
||||
uint16_t radius;
|
||||
int16_t startAngle;
|
||||
int16_t endAngle;
|
||||
const Image* imgSrc;
|
||||
};
|
||||
|
||||
class DrawArc : public HeapBase {
|
||||
public:
|
||||
static DrawArc* GetInstance()
|
||||
{
|
||||
static DrawArc drawArc;
|
||||
return &drawArc;
|
||||
}
|
||||
|
||||
void GetDrawRange(int16_t& start, int16_t& end);
|
||||
|
||||
void Draw(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opaScale, uint8_t cap);
|
||||
|
||||
private:
|
||||
static constexpr uint8_t DRAW_ARC_QUADRANT_NUM = 4;
|
||||
static constexpr uint8_t ARC_QUADRANT_ONE = 0;
|
||||
static constexpr uint8_t ARC_QUADRANT_TWO = 1;
|
||||
static constexpr uint8_t ARC_QUADRANT_THREE = 2;
|
||||
static constexpr uint8_t ARC_QUADRANT_FOUR = 3;
|
||||
static constexpr int16_t IN_DEGREE_RANG = 0;
|
||||
static constexpr int16_t OUT_DEGREE_RANG = 1;
|
||||
static constexpr int16_t INTERSECT = 2;
|
||||
static constexpr int16_t DOUBLE_INTERSECT = 3;
|
||||
|
||||
int16_t lineStart_;
|
||||
int16_t lineEnd_;
|
||||
int16_t outAntiStart_;
|
||||
int16_t outAntiEnd_;
|
||||
int16_t inAntiStart_;
|
||||
int16_t inAntiEnd_;
|
||||
int16_t y_;
|
||||
int16_t outRadius_;
|
||||
int16_t inRadius_;
|
||||
uint32_t ySqr_;
|
||||
uint32_t outRadiusSqr_;
|
||||
uint32_t inRadiusSqr_;
|
||||
bool isCircle_;
|
||||
uint32_t antiOutRadiusSqr_;
|
||||
uint32_t antiInRadiusSqr_;
|
||||
|
||||
DrawArc()
|
||||
: lineStart_(0),
|
||||
lineEnd_(0),
|
||||
outAntiStart_(0),
|
||||
outAntiEnd_(0),
|
||||
inAntiStart_(0),
|
||||
inAntiEnd_(0),
|
||||
y_(0),
|
||||
outRadius_(0),
|
||||
inRadius_(0),
|
||||
ySqr_(0),
|
||||
outRadiusSqr_(0),
|
||||
inRadiusSqr_(0),
|
||||
isCircle_(false),
|
||||
antiOutRadiusSqr_(0),
|
||||
antiInRadiusSqr_(0)
|
||||
{
|
||||
}
|
||||
~DrawArc() {}
|
||||
void DrawVerLine(const Point& begin,
|
||||
const Point& imgPos,
|
||||
const Rect& mask,
|
||||
int16_t len,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
const Image* imgSrc);
|
||||
|
||||
void DrawHorLine(const Point& begin,
|
||||
const Point& imgPos,
|
||||
const Rect& mask,
|
||||
int16_t len,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
const Image* imgSrc);
|
||||
|
||||
void DrawImg(const Point& imgPos,
|
||||
Rect& area,
|
||||
const Rect& invalidatedArea,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
const Image* imgSrc);
|
||||
|
||||
int16_t GetDegreeRangeIntersectState(uint16_t degreeStart, uint16_t degreeEnd, uint16_t start, uint16_t end);
|
||||
uint16_t CalculateTanDegree(uint16_t x, uint16_t y);
|
||||
int16_t GetDrawAngle(int16_t angle);
|
||||
void DrawCircleNoEndpoint(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opa, bool anti);
|
||||
void DrawAxisLine(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opa);
|
||||
void DrawLineWithDegree(ArcInfo& arcInfo,
|
||||
int16_t start,
|
||||
int16_t end,
|
||||
int16_t y,
|
||||
const Rect& mask,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
uint8_t quadrant);
|
||||
int16_t DrawLineWithDegreeInner(ArcInfo& arcInfo,
|
||||
int16_t start,
|
||||
int16_t end,
|
||||
int16_t y,
|
||||
const Rect& mask,
|
||||
const Style& style,
|
||||
uint8_t opaScale,
|
||||
uint8_t quadrant);
|
||||
#if ENABLE_ANTIALIAS
|
||||
void DrawLineAnti(ArcInfo& arcInfo, const Rect& mask, const Style& style, uint8_t opa);
|
||||
void DrawPointAnti(ArcInfo& arcInfo, int16_t x, const Rect& mask, const Style& style, uint8_t antiOpa);
|
||||
#endif
|
||||
uint16_t GetDegreeInQuadrant(uint16_t degree, uint8_t quadrant);
|
||||
void SetArcInfo(ArcInfo& arcInfo, const Style& style);
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_DRAW_ARC_H
|
||||
Executable
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_curve.h"
|
||||
#include "animator/interpolation.h"
|
||||
#include "draw/draw_line.h"
|
||||
|
||||
namespace OHOS {
|
||||
void DrawCurve::DrawCubicBezier(const Point& start, const Point& control1, const Point& control2, const Point& end,
|
||||
const Rect& mask, int16_t width, const ColorType& color, OpacityType opacity)
|
||||
{
|
||||
if ((width == 0) || (opacity == OPA_TRANSPARENT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
Point prePoint = start;
|
||||
for (int16_t t = 1; t <= INTERPOLATION_RANGE; t++) {
|
||||
Point point;
|
||||
point.x = Interpolation::GetBezierInterpolation(t, start.x, control1.x, control2.x, end.x);
|
||||
point.y = Interpolation::GetBezierInterpolation(t, start.y, control1.y, control2.y, end.y);
|
||||
if ((prePoint.x == point.x) && (prePoint.y == point.y)) {
|
||||
continue;
|
||||
}
|
||||
DrawLine::Draw(prePoint, point, mask, width, color, opacity);
|
||||
prePoint = point;
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_CURVE_H
|
||||
#define GRAPHIC_LITE_DRAW_CURVE_H
|
||||
|
||||
#include "color.h"
|
||||
#include "geometry2d.h"
|
||||
|
||||
namespace OHOS {
|
||||
class DrawCurve : public HeapBase {
|
||||
public:
|
||||
static void DrawCubicBezier(const Point& start, const Point& control1, const Point& control2, const Point& end,
|
||||
const Rect& mask, int16_t width, const ColorType& color, OpacityType opacity);
|
||||
private:
|
||||
static constexpr uint16_t INTERPOLATION_RANGE = 1024;
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_DRAW_CURVE_H
|
||||
Executable
+88
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_image.h"
|
||||
|
||||
#include "color.h"
|
||||
#include "graphic_log.h"
|
||||
#include "imgdecode/cache_manager.h"
|
||||
|
||||
namespace OHOS {
|
||||
void DrawImage::DrawCommon(const Rect& coords, const Rect& mask,
|
||||
const ImageInfo* img, const Style& style, uint8_t opaScale)
|
||||
{
|
||||
if (img == nullptr) {
|
||||
return;
|
||||
}
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.imageOpa_);
|
||||
|
||||
/* 3 : when single pixel change bit to byte, the buffer should divide by 8, equal to shift right 3 bits. */
|
||||
uint8_t pxByteSize = DrawUtils::GetPxSizeByImageInfo(*img) >> 3;
|
||||
DrawUtils::GetInstance()->DrawImage(coords, mask, img->data, opa, pxByteSize);
|
||||
}
|
||||
|
||||
void DrawImage::DrawCommon(const Rect& coords, const Rect& mask,
|
||||
const char* path, const Style& style, uint8_t opaScale)
|
||||
{
|
||||
if (path == nullptr) {
|
||||
return;
|
||||
}
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.imageOpa_);
|
||||
|
||||
CacheEntry entry;
|
||||
if (CacheManager::GetInstance().Open(path, style, entry) != RetCode::OK) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* 3 : when single pixel change bit to byte, the buffer should divide by 8, equal to shift right 3 bits. */
|
||||
uint8_t pxByteSize = DrawUtils::GetPxSizeByImageInfo(entry.GetImageInfo()) >> 3;
|
||||
if (entry.InCache()) {
|
||||
DrawUtils::GetInstance()->DrawImage(coords, mask, entry.GetImgData(), opa, pxByteSize);
|
||||
} else {
|
||||
Rect valid = coords;
|
||||
if (!valid.Intersect(valid, mask)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t width = valid.GetWidth();
|
||||
if (width <= 0) {
|
||||
return;
|
||||
}
|
||||
uint8_t* buf = static_cast<uint8_t*>(UIMalloc(static_cast<uint32_t>(width) * ((COLOR_DEPTH >> SHIFT_3) + 1)));
|
||||
if (buf == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
Rect line = valid;
|
||||
line.SetHeight(1);
|
||||
Point start;
|
||||
start.x = valid.GetLeft() - coords.GetLeft();
|
||||
start.y = valid.GetTop() - coords.GetTop();
|
||||
int16_t row;
|
||||
for (row = valid.GetTop(); row <= valid.GetBottom(); row++) {
|
||||
if (entry.ReadLine(start, width, buf) != RetCode::OK) {
|
||||
CacheManager::GetInstance().Close(path);
|
||||
UIFree(buf);
|
||||
return;
|
||||
}
|
||||
DrawUtils::GetInstance()->DrawImage(line, mask, buf, opa, pxByteSize);
|
||||
line.SetTop(line.GetTop() + 1);
|
||||
line.SetBottom(line.GetBottom() + 1);
|
||||
start.y++;
|
||||
}
|
||||
UIFree(buf);
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_IMAGE_H
|
||||
#define GRAPHIC_LITE_DRAW_IMAGE_H
|
||||
|
||||
#include <cstdint>
|
||||
#include <stdio.h>
|
||||
#include "components/ui_view.h"
|
||||
#include "draw_utils.h"
|
||||
#include "geometry2d.h"
|
||||
|
||||
namespace OHOS {
|
||||
class CacheEntry;
|
||||
|
||||
class DrawImage : public HeapBase {
|
||||
public:
|
||||
DrawImage() {}
|
||||
~DrawImage() {}
|
||||
|
||||
static void DrawCommon(const Rect& coords, const Rect& mask,
|
||||
const ImageInfo* img, const Style& style, uint8_t opaScale);
|
||||
|
||||
static void DrawCommon(const Rect& coords, const Rect& mask,
|
||||
const char* path, const Style& style, uint8_t opaScale);
|
||||
};
|
||||
} // namespace OHOS
|
||||
|
||||
#endif // GRAPHIC_LITE_DRAW_IMAGE_H
|
||||
Executable
+167
@@ -0,0 +1,167 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_label.h"
|
||||
#include <cstdio>
|
||||
#include "common/typed_text.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "font/ui_font.h"
|
||||
#include "font/ui_font_header.h"
|
||||
#include "graphic_log.h"
|
||||
|
||||
namespace OHOS {
|
||||
void DrawLabel::DrawTextOneLine(const LabelLineInfo& labelLine)
|
||||
{
|
||||
UIFont* fontEngine = UIFont::GetInstance();
|
||||
if (labelLine.direct == TEXT_DIRECT_RTL) {
|
||||
labelLine.pos.x -= labelLine.offset.x;
|
||||
} else {
|
||||
labelLine.pos.x += labelLine.offset.x;
|
||||
}
|
||||
|
||||
uint32_t i = 0;
|
||||
uint32_t letter;
|
||||
uint16_t letterWidth;
|
||||
while (i < labelLine.lineLength) {
|
||||
letter = TypedText::GetUTF8Next(labelLine.text, i, i);
|
||||
|
||||
LabelLetterInfo letterInfo{labelLine.pos,
|
||||
labelLine.mask,
|
||||
labelLine.style.textColor_,
|
||||
labelLine.opaScale,
|
||||
0,
|
||||
0,
|
||||
letter,
|
||||
labelLine.direct,
|
||||
labelLine.fontId,
|
||||
0,
|
||||
labelLine.fontSize};
|
||||
DrawUtils::GetInstance()->DrawLetter(letterInfo);
|
||||
letterWidth = fontEngine->GetWidth(letter, 0);
|
||||
if (labelLine.direct == TEXT_DIRECT_RTL) {
|
||||
labelLine.pos.x -= (letterWidth + labelLine.style.letterSpace_);
|
||||
} else {
|
||||
labelLine.pos.x += (letterWidth + labelLine.style.letterSpace_);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLabel::DrawArcText(const Rect& mask,
|
||||
const char* text,
|
||||
const Point& arcCenter,
|
||||
uint8_t fontId,
|
||||
const UIArcLabel::ArcTextInfo arcTextInfo,
|
||||
UIArcLabel::TextOrientation orientation,
|
||||
const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
if ((text == nullptr) || (arcTextInfo.lineStart == arcTextInfo.lineEnd) || (arcTextInfo.radius == 0)) {
|
||||
GRAPHIC_LOGE("DrawLabel::DrawArcText invalid parameter\n");
|
||||
return;
|
||||
}
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.textOpa_);
|
||||
if (opa == OPA_TRANSPARENT) {
|
||||
return;
|
||||
}
|
||||
uint16_t letterWidth;
|
||||
uint16_t letterHeight = UIFont::GetInstance()->GetHeight();
|
||||
uint32_t i = arcTextInfo.lineStart;
|
||||
float angle = arcTextInfo.startAngle;
|
||||
float posX;
|
||||
float posY;
|
||||
float rotateAngle;
|
||||
bool xorFlag = (orientation == UIArcLabel::TextOrientation::INSIDE) ^ (arcTextInfo.direct == TEXT_DIRECT_LTR);
|
||||
|
||||
while (i < arcTextInfo.lineEnd) {
|
||||
uint32_t tmp = i;
|
||||
uint32_t letter = TypedText::GetUTF8Next(text, tmp, i);
|
||||
if (letter == 0) {
|
||||
continue;
|
||||
}
|
||||
if ((letter == '\r') || (letter == '\n')) {
|
||||
break;
|
||||
}
|
||||
letterWidth = UIFont::GetInstance()->GetWidth(letter, 0);
|
||||
if ((tmp == arcTextInfo.lineStart) && xorFlag) {
|
||||
angle += TypedText::GetAngleForArcLen(static_cast<float>(letterWidth), letterHeight, arcTextInfo.radius,
|
||||
arcTextInfo.direct, orientation);
|
||||
}
|
||||
uint16_t arcLen = letterWidth + style.letterSpace_;
|
||||
if (arcLen == 0) {
|
||||
continue;
|
||||
}
|
||||
float incrementAngle = TypedText::GetAngleForArcLen(static_cast<float>(arcLen), letterHeight,
|
||||
arcTextInfo.radius, arcTextInfo.direct, orientation);
|
||||
|
||||
rotateAngle = (orientation == UIArcLabel::TextOrientation::INSIDE) ? angle : (angle - SEMICIRCLE_IN_DEGREE);
|
||||
|
||||
// 2: half
|
||||
float fineTuningAngle = incrementAngle * (static_cast<float>(letterWidth) / (2 * arcLen));
|
||||
rotateAngle += (xorFlag ? -fineTuningAngle : fineTuningAngle);
|
||||
TypedText::GetArcLetterPos(arcCenter, arcTextInfo.radius, angle, posX, posY);
|
||||
angle += incrementAngle;
|
||||
|
||||
DrawLetterWithRotate(mask, fontId, letter, Point{MATH_ROUND(posX), MATH_ROUND(posY)},
|
||||
static_cast<int16_t>(rotateAngle), style.textColor_, opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLabel::DrawLetterWithRotate(const Rect& mask,
|
||||
uint8_t fontId,
|
||||
uint32_t letter,
|
||||
const Point& pos,
|
||||
int16_t rotateAngle,
|
||||
const ColorType& color,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
UIFont* fontEngine = UIFont::GetInstance();
|
||||
FontHeader head;
|
||||
GlyphNode node;
|
||||
if (fontEngine->GetCurrentFontHeader(head) != 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
const uint8_t* fontMap = fontEngine->GetBitmap(letter, node, 0);
|
||||
if (fontMap == nullptr) {
|
||||
return;
|
||||
}
|
||||
uint8_t fontWeight = fontEngine->GetFontWeight(fontId);
|
||||
ColorMode colorMode;
|
||||
switch (fontWeight) {
|
||||
case FONT_WEIGHT_1:
|
||||
colorMode = A1;
|
||||
break;
|
||||
case FONT_WEIGHT_2:
|
||||
colorMode = A2;
|
||||
break;
|
||||
case FONT_WEIGHT_4:
|
||||
colorMode = A4;
|
||||
break;
|
||||
case FONT_WEIGHT_8:
|
||||
colorMode = A8;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
Rect rectLetter;
|
||||
rectLetter.SetPosition(pos.x + node.left, pos.y + head.ascender - node.top);
|
||||
rectLetter.Resize(node.cols, node.rows);
|
||||
TransformMap transMap(rectLetter);
|
||||
transMap.Rotate(rotateAngle, Vector2<float>(-node.left, node.top - head.ascender));
|
||||
TransformDataInfo letterTranDataInfo = {ImageHeader{colorMode, 0, 0, 0, node.cols, node.rows}, fontMap, fontWeight,
|
||||
BlurLevel::LEVEL0};
|
||||
DrawUtils::GetInstance()->DrawTransform(mask, Point{0, 0}, color, opaScale, transMap, letterTranDataInfo);
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_LABEL_H
|
||||
#define GRAPHIC_LITE_DRAW_LABEL_H
|
||||
|
||||
#include "common/typed_text.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "geometry2d.h"
|
||||
#include "heap_base.h"
|
||||
#include "style.h"
|
||||
|
||||
namespace OHOS {
|
||||
class DrawLabel : public HeapBase {
|
||||
public:
|
||||
static void DrawTextOneLine(const LabelLineInfo& labelLine);
|
||||
|
||||
static void DrawArcText(const Rect& mask, const char* text, const Point& arcCenter, uint8_t fontId,
|
||||
const UIArcLabel::ArcTextInfo arcTextInfo, UIArcLabel::TextOrientation orientation, const Style& style,
|
||||
uint8_t opaScale);
|
||||
|
||||
static void DrawLetterWithRotate(const Rect& mask, uint8_t fontId, uint32_t letter, const Point& pos,
|
||||
int16_t rotateAngle, const ColorType& color, OpacityType opaScale);
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_DRAW_LABEL_H
|
||||
Executable
+472
@@ -0,0 +1,472 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_line.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "graphic_math.h"
|
||||
|
||||
namespace OHOS {
|
||||
#define INCREASE_ACC(acc, accTemp, adj, step, dir) \
|
||||
do { \
|
||||
(accTemp) = (acc); \
|
||||
(acc) += (adj); \
|
||||
if ((acc) <= (accTemp)) { \
|
||||
(step) += (dir); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SWAP_START_END(sx, sy, ex, ey, dx, dy, dir) \
|
||||
do { \
|
||||
if ((dy) >= (dx)) { \
|
||||
if ((sy) > (ey)) { \
|
||||
SWAP_POINTS((sx), (ex), (sy), (ey)); \
|
||||
} \
|
||||
if ((ex) < (sx)) { \
|
||||
(dir) = -1; \
|
||||
} \
|
||||
} else { \
|
||||
if ((sx) < (ex)) { \
|
||||
SWAP_POINTS((sx), (ex), (sy), (ey)); \
|
||||
} \
|
||||
if ((ey) < (sy)) { \
|
||||
(dir) = -1; \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SWAP_IF_Y_LARGER(x1, x2, y1, y2) \
|
||||
if ((y1) > (y2)) { \
|
||||
SWAP_POINTS((x1), (x2), (y1), (y2)); \
|
||||
}
|
||||
|
||||
#define SWAP_IF_X_SMALLER(x1, x2, y1, y2) \
|
||||
if ((x1) < (x2)) { \
|
||||
SWAP_POINTS((x1), (x2), (y1), (y2)); \
|
||||
}
|
||||
|
||||
void DrawLine::Draw(const Point& start,
|
||||
const Point& end,
|
||||
const Rect& mask,
|
||||
int16_t width,
|
||||
const ColorType& color,
|
||||
OpacityType opacity)
|
||||
{
|
||||
if ((width == 0) || (opacity == OPA_TRANSPARENT)) {
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t yTop;
|
||||
int16_t yBottom;
|
||||
|
||||
if (start.y < end.y) {
|
||||
yTop = start.y - width / 2; // 2: half
|
||||
yBottom = end.y + width / 2; // 2: half
|
||||
} else {
|
||||
yTop = end.y - width / 2; // 2: half
|
||||
yBottom = start.y + width / 2; // 2: half
|
||||
}
|
||||
|
||||
if ((yBottom < mask.GetTop()) || (yTop > mask.GetBottom())) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (start.y == end.y) {
|
||||
DrawHorizontalLine(start, end, mask, width, color, opacity);
|
||||
} else if (start.x == end.x) {
|
||||
DrawVerticalLine(start, end, mask, width, color, opacity);
|
||||
} else {
|
||||
DrawWuLine(start, end, mask, width, color, opacity);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLine::DrawVerticalLine(const Point& start,
|
||||
const Point& end,
|
||||
const Rect& mask,
|
||||
int16_t width,
|
||||
const ColorType& color,
|
||||
OpacityType opacity)
|
||||
{
|
||||
Rect rect;
|
||||
|
||||
if (start.y < end.y) {
|
||||
rect.SetX(start.x - width / 2); // 2: half
|
||||
rect.SetY(start.y);
|
||||
rect.SetWidth(width);
|
||||
rect.SetHeight(end.y - start.y + 1);
|
||||
} else {
|
||||
rect.SetX(end.x - width / 2); // 2: half
|
||||
rect.SetY(end.y);
|
||||
rect.SetWidth(width);
|
||||
rect.SetHeight(start.y - end.y + 1);
|
||||
}
|
||||
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
}
|
||||
|
||||
void DrawLine::DrawHorizontalLine(const Point& start,
|
||||
const Point& end,
|
||||
const Rect& mask,
|
||||
int16_t width,
|
||||
const ColorType& color,
|
||||
OpacityType opacity)
|
||||
{
|
||||
Rect rect;
|
||||
|
||||
if (start.x < end.x) {
|
||||
rect.SetX(start.x);
|
||||
rect.SetY(start.y - width / 2); // 2: half
|
||||
rect.SetWidth(end.x - start.x + 1);
|
||||
rect.SetHeight(width);
|
||||
} else {
|
||||
rect.SetX(end.x);
|
||||
rect.SetY(end.y - width / 2); // 2: half
|
||||
rect.SetWidth(start.x - end.x + 1);
|
||||
rect.SetHeight(width);
|
||||
}
|
||||
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
}
|
||||
|
||||
void DrawLine::DrawWuLine(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity)
|
||||
{
|
||||
if (width <= 2) { // 2 : thin line width
|
||||
DrawThinWuLine(start, end, mask, width, color, opacity);
|
||||
return;
|
||||
}
|
||||
|
||||
int16_t sx = start.x;
|
||||
int16_t sy = start.y;
|
||||
int16_t ex = end.x;
|
||||
int16_t ey = end.y;
|
||||
uint16_t dx = MATH_ABS(ex - sx);
|
||||
uint16_t dy = MATH_ABS(ey - sy);
|
||||
int8_t dir = 1;
|
||||
SWAP_START_END(sx, sy, ex, ey, dx, dy, dir);
|
||||
|
||||
// calculate four vertex ordered according to dy and dx
|
||||
float plot = -static_cast<float>(ex - sx) / static_cast<float>(ey - sy);
|
||||
float offset = 1 / (1 + plot * plot);
|
||||
offset = Sqrt(offset) * width / 2; // 2: half
|
||||
float x0 = sx + offset;
|
||||
float y0 = sy + (x0 - sx) * plot;
|
||||
float x1 = sx - offset;
|
||||
float y1 = sy + (x1 - sx) * plot;
|
||||
float x2 = ex + offset;
|
||||
float y2 = ey + (x2 - ex) * plot;
|
||||
float x3 = ex - offset;
|
||||
float y3 = ey + (x3 - ex) * plot;
|
||||
int16_t x0Int = MATH_ROUND(x0);
|
||||
int16_t y0Int = MATH_ROUND(y0);
|
||||
int16_t x1Int = MATH_ROUND(x1);
|
||||
int16_t y1Int = MATH_ROUND(y1);
|
||||
int16_t x2Int = MATH_ROUND(x2);
|
||||
int16_t y2Int = MATH_ROUND(y2);
|
||||
int16_t x3Int = MATH_ROUND(x3);
|
||||
int16_t y3Int = MATH_ROUND(y3);
|
||||
// width is longer than distance between start point and end point, need swap direction of line.
|
||||
if (dx * dx + dy * dy < width * width) {
|
||||
if ((dx == 1) && (dy == 1)) {
|
||||
DrawThinWuLine({ x0Int, y0Int }, { x3Int, y3Int }, mask, 2, color, opacity); // 2 : width of line
|
||||
return;
|
||||
}
|
||||
dx = MATH_ABS(x0Int - x1Int);
|
||||
dy = MATH_ABS(y0Int - y1Int);
|
||||
if (dy == dx) {
|
||||
dir = -dir;
|
||||
}
|
||||
}
|
||||
if (dy >= dx) {
|
||||
SWAP_IF_Y_LARGER(x0Int, x1Int, y0Int, y1Int);
|
||||
SWAP_IF_Y_LARGER(x1Int, x2Int, y1Int, y2Int);
|
||||
SWAP_IF_Y_LARGER(x2Int, x3Int, y2Int, y3Int);
|
||||
SWAP_IF_Y_LARGER(x0Int, x1Int, y0Int, y1Int);
|
||||
SWAP_IF_Y_LARGER(x1Int, x2Int, y1Int, y2Int);
|
||||
SWAP_IF_Y_LARGER(x0Int, x1Int, y0Int, y1Int);
|
||||
if (dir == -1) {
|
||||
SWAP_IF_X_SMALLER(x1Int, x0Int, y1Int, y0Int);
|
||||
SWAP_IF_X_SMALLER(x3Int, x2Int, y3Int, y2Int);
|
||||
} else {
|
||||
SWAP_IF_X_SMALLER(x0Int, x1Int, y0Int, y1Int);
|
||||
SWAP_IF_X_SMALLER(x2Int, x3Int, y2Int, y3Int);
|
||||
}
|
||||
} else {
|
||||
SWAP_IF_X_SMALLER(x0Int, x1Int, y0Int, y1Int);
|
||||
SWAP_IF_X_SMALLER(x1Int, x2Int, y1Int, y2Int);
|
||||
SWAP_IF_X_SMALLER(x2Int, x3Int, y2Int, y3Int);
|
||||
SWAP_IF_X_SMALLER(x0Int, x1Int, y0Int, y1Int);
|
||||
SWAP_IF_X_SMALLER(x1Int, x2Int, y1Int, y2Int);
|
||||
SWAP_IF_X_SMALLER(x0Int, x1Int, y0Int, y1Int);
|
||||
if (dir == 1) {
|
||||
SWAP_IF_Y_LARGER(x1Int, x0Int, y1Int, y0Int);
|
||||
SWAP_IF_Y_LARGER(x3Int, x2Int, y3Int, y2Int);
|
||||
} else {
|
||||
SWAP_IF_Y_LARGER(x0Int, x1Int, y0Int, y1Int);
|
||||
SWAP_IF_Y_LARGER(x2Int, x3Int, y2Int, y3Int);
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t adj0;
|
||||
uint16_t accTemp0;
|
||||
uint16_t acc0 = 0;
|
||||
uint64_t adj1;
|
||||
uint16_t accTemp1;
|
||||
uint16_t acc1 = 0;
|
||||
uint16_t accTemp2;
|
||||
uint16_t acc2 = 0;
|
||||
|
||||
int16_t endPoints0[MAX_LINE_WIDTH] = { 0 };
|
||||
int16_t endPoints1[MAX_LINE_WIDTH] = { 0 };
|
||||
int16_t temp0 = 0;
|
||||
int16_t temp1 = 0;
|
||||
int16_t edge0 = 0;
|
||||
int16_t edge1 = 0;
|
||||
Rect rect;
|
||||
|
||||
// sort points
|
||||
if (dy >= dx) {
|
||||
adj0 = static_cast<uint64_t>(dx << SHIFT_16) / static_cast<uint64_t>(dy);
|
||||
adj1 = static_cast<uint64_t>(MATH_ABS(y1Int - y0Int) << SHIFT_16) /
|
||||
static_cast<uint64_t>(MATH_ABS(x1Int - x0Int));
|
||||
if (adj1 != 0) {
|
||||
// draw top line
|
||||
dx = MATH_ABS(x1Int - x0Int);
|
||||
sx = x0Int;
|
||||
sy = y0Int;
|
||||
DrawUtils::GetInstance()->DrawPixel(x0Int, y0Int, mask, color, opacity);
|
||||
while (--dx) {
|
||||
accTemp1 = acc1;
|
||||
acc1 += adj1;
|
||||
if (acc1 <= accTemp1) {
|
||||
if (sy - y0Int < MAX_LINE_WIDTH) {
|
||||
endPoints0[sy - y0Int] = sx;
|
||||
}
|
||||
sy++;
|
||||
}
|
||||
sx -= dir;
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, sy, mask, color, opacity,
|
||||
(acc1 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
}
|
||||
if (sy - y0Int < MAX_LINE_WIDTH) {
|
||||
endPoints0[sy - y0Int] = sx - dir;
|
||||
}
|
||||
|
||||
// draw botttom line
|
||||
acc1 = 0;
|
||||
dx = MATH_ABS(x3Int - x2Int);
|
||||
sy = y3Int;
|
||||
sx = x3Int;
|
||||
DrawUtils::GetInstance()->DrawPixel(x3Int, y3Int, mask, color, opacity);
|
||||
while (--dx) {
|
||||
accTemp1 = acc1;
|
||||
acc1 += adj1;
|
||||
if (acc1 <= accTemp1) {
|
||||
if (temp1 < MAX_LINE_WIDTH) {
|
||||
endPoints1[temp1++] = sx;
|
||||
}
|
||||
sy--;
|
||||
}
|
||||
sx += dir;
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, sy, mask, color, opacity, (acc1 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
}
|
||||
if (temp1 < MAX_LINE_WIDTH) {
|
||||
endPoints1[temp1++] = sx + dir;
|
||||
}
|
||||
} else {
|
||||
/* If y0 is equal to y1, draw two horizontal lines as the top line and bottom line. */
|
||||
rect.SetRect(MATH_MIN(x0Int, x1Int), y0Int, MATH_MAX(x0Int, x1Int), y1Int);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
rect.SetRect(MATH_MIN(x2Int, x3Int), y3Int, MATH_MAX(x2Int, x3Int), y2Int);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
}
|
||||
|
||||
sx = x0Int;
|
||||
sy = y0Int + 1;
|
||||
dy = MATH_ABS(y3Int - y0Int);
|
||||
if (dy == 0) {
|
||||
return;
|
||||
}
|
||||
int16_t sxTemp = x1Int;
|
||||
while (--dy) {
|
||||
if (sy <= y1Int) {
|
||||
INCREASE_ACC(acc0, accTemp0, adj0, sx, dir);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx + dir, sy, mask, color, opacity, acc0 >> SHIFT_8);
|
||||
if (temp0 < MAX_LINE_WIDTH) {
|
||||
edge0 = endPoints0[temp0++];
|
||||
}
|
||||
edge1 = sx;
|
||||
} else if (sy < y2Int) {
|
||||
INCREASE_ACC(acc0, accTemp0, adj0, sx, dir);
|
||||
INCREASE_ACC(acc2, accTemp2, adj0, sxTemp, dir);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx + dir, sy, mask, color, opacity, acc0 >> SHIFT_8);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sxTemp, sy, mask, color, opacity,
|
||||
(acc2 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
edge0 = sxTemp + dir;
|
||||
edge1 = sx;
|
||||
} else if (sy < y3Int) {
|
||||
INCREASE_ACC(acc2, accTemp2, adj0, sxTemp, dir);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sxTemp, sy, mask, color, opacity,
|
||||
(acc2 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
edge0 = sxTemp + dir;
|
||||
if (temp1 > 0) {
|
||||
edge1 = endPoints1[--temp1];
|
||||
}
|
||||
}
|
||||
if ((dir < 0) && (edge0 > edge1)) {
|
||||
SWAP_INT16(edge0, edge1);
|
||||
}
|
||||
rect.SetRect(edge0, sy, edge1, sy);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
sy++;
|
||||
}
|
||||
} else {
|
||||
adj0 = static_cast<uint64_t>(dy << SHIFT_16) / static_cast<uint64_t>(dx);
|
||||
adj1 = static_cast<uint64_t>(MATH_ABS(x1Int - x0Int) << SHIFT_16) /
|
||||
static_cast<uint64_t>(MATH_ABS(y1Int - y0Int));
|
||||
if (adj1 != 0) {
|
||||
// draw top line
|
||||
dy = MATH_ABS(y1Int - y0Int);
|
||||
sx = x0Int;
|
||||
sy = y0Int;
|
||||
DrawUtils::GetInstance()->DrawPixel(sx, sy, mask, color, opacity);
|
||||
while (--dy) {
|
||||
accTemp1 = acc1;
|
||||
acc1 += adj1;
|
||||
if (acc1 <= accTemp1) {
|
||||
if (x0Int - sx < MAX_LINE_WIDTH) {
|
||||
endPoints0[x0Int - sx] = sy;
|
||||
}
|
||||
sx--;
|
||||
}
|
||||
sy -= dir;
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, sy, mask, color, opacity,
|
||||
(acc1 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
}
|
||||
if (x0Int - sx < MAX_LINE_WIDTH) {
|
||||
endPoints0[x0Int - sx] = sy - dir;
|
||||
}
|
||||
|
||||
// draw botttom line
|
||||
acc1 = 0;
|
||||
dy = MATH_ABS(y3Int - y2Int);
|
||||
sy = y3Int;
|
||||
sx = x3Int;
|
||||
while (--dy) {
|
||||
accTemp1 = acc1;
|
||||
acc1 += adj1;
|
||||
if (acc1 <= accTemp1) {
|
||||
if (temp1 < MAX_LINE_WIDTH) {
|
||||
endPoints1[temp1++] = sy;
|
||||
}
|
||||
sx++;
|
||||
}
|
||||
sy += dir;
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, sy, mask, color, opacity, (acc1 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
}
|
||||
DrawUtils::GetInstance()->DrawPixel(x3Int, y3Int, mask, color, opacity);
|
||||
if (temp1 < MAX_LINE_WIDTH) {
|
||||
endPoints1[temp1++] = sy + dir;
|
||||
}
|
||||
} else {
|
||||
/* If x0 is equal to x1, draw two vertical lines as the top line and bottom line. */
|
||||
rect.SetRect(x1Int, MATH_MIN(y0Int, y1Int), x0Int, MATH_MAX(y0Int, y1Int));
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
rect.SetRect(x3Int, MATH_MIN(y2Int, y3Int), x2Int, MATH_MAX(y2Int, y3Int));
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
}
|
||||
|
||||
sx = x0Int - 1;
|
||||
sy = y0Int;
|
||||
dx = MATH_ABS(x3Int - x0Int);
|
||||
int16_t syTemp = y1Int;
|
||||
if (dx == 0) {
|
||||
return;
|
||||
}
|
||||
while (--dx) {
|
||||
if (sx >= x1Int) {
|
||||
INCREASE_ACC(acc0, accTemp0, adj0, sy, dir);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, sy + dir, mask, color, opacity, acc0 >> SHIFT_8);
|
||||
if (temp0 < MAX_LINE_WIDTH) {
|
||||
edge0 = endPoints0[temp0++];
|
||||
}
|
||||
edge1 = sy;
|
||||
} else if (sx > x2Int) {
|
||||
INCREASE_ACC(acc0, accTemp0, adj0, sy, dir);
|
||||
INCREASE_ACC(acc2, accTemp2, adj0, syTemp, dir);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, sy + dir, mask, color, opacity, acc0 >> SHIFT_8);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, syTemp, mask, color, opacity,
|
||||
(acc2 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
edge0 = syTemp + dir;
|
||||
edge1 = sy;
|
||||
} else if (sx > x3Int) {
|
||||
INCREASE_ACC(acc2, accTemp2, adj0, syTemp, dir);
|
||||
DrawUtils::GetInstance()->DrawPixelInLine(sx, syTemp, mask, color, opacity,
|
||||
(acc2 >> SHIFT_8) ^ OPA_OPAQUE);
|
||||
edge0 = syTemp + dir;
|
||||
if (temp1 > 0) {
|
||||
edge1 = endPoints1[--temp1];
|
||||
}
|
||||
}
|
||||
if ((dir < 0) && (edge0 > edge1)) {
|
||||
SWAP_INT16(edge0, edge1);
|
||||
}
|
||||
rect.SetRect(sx, edge0, sx, edge1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, mask, color, opacity);
|
||||
sx--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawLine::DrawThinWuLine(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity)
|
||||
{
|
||||
int16_t sx = start.x;
|
||||
int16_t sy = start.y;
|
||||
int16_t ex = end.x;
|
||||
int16_t ey = end.y;
|
||||
uint16_t dx = MATH_ABS(ex - sx);
|
||||
uint16_t dy = MATH_ABS(ey - sy);
|
||||
uint64_t adj;
|
||||
uint16_t accTemp;
|
||||
uint16_t acc = 0;
|
||||
int8_t dir = 1;
|
||||
SWAP_START_END(sx, sy, ex, ey, dx, dy, dir);
|
||||
if (dy >= dx) {
|
||||
adj = static_cast<uint64_t>(dx << SHIFT_16) / static_cast<uint64_t>(dy);
|
||||
while (dy--) {
|
||||
INCREASE_ACC(acc, accTemp, adj, sx, dir);
|
||||
sy++;
|
||||
if (width == 1) {
|
||||
DrawUtils::GetInstance()->DrawAdjPixelInLine(sx, sy, sx + dir, sy, mask, color, opacity,
|
||||
acc >> SHIFT_8);
|
||||
} else {
|
||||
DrawUtils::GetInstance()->DrawVerPixelInLine(sx, sy, dir, mask, color, opacity, acc >> SHIFT_8);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
adj = static_cast<uint64_t>(dy << SHIFT_16) / static_cast<uint64_t>(dx);
|
||||
while (dx--) {
|
||||
INCREASE_ACC(acc, accTemp, adj, sy, dir);
|
||||
sx--;
|
||||
if (width == 1) {
|
||||
DrawUtils::GetInstance()->DrawAdjPixelInLine(sx, sy, sx, sy + dir, mask, color, opacity,
|
||||
acc >> SHIFT_8);
|
||||
} else {
|
||||
DrawUtils::GetInstance()->DrawHorPixelInLine(sx, sy, dir, mask, color, opacity, acc >> SHIFT_8);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_LINE_H
|
||||
#define GRAPHIC_LITE_DRAW_LINE_H
|
||||
|
||||
#include "color.h"
|
||||
#include "geometry2d.h"
|
||||
|
||||
namespace OHOS {
|
||||
class DrawLine : public HeapBase {
|
||||
public:
|
||||
static void Draw(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity);
|
||||
|
||||
private:
|
||||
static void DrawVerticalLine(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity);
|
||||
static void DrawHorizontalLine(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity);
|
||||
static void DrawWuLine(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity);
|
||||
static void DrawThinWuLine(const Point& start, const Point& end, const Rect& mask,
|
||||
int16_t width, const ColorType& color, OpacityType opacity);
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_DRAW_LINE_H
|
||||
Executable
+728
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_rect.h"
|
||||
#include "draw/draw_arc.h"
|
||||
#include "draw/draw_utils.h"
|
||||
#include "graphic_log.h"
|
||||
#include "graphic_math.h"
|
||||
#include "style.h"
|
||||
|
||||
namespace OHOS {
|
||||
void DrawRect::Draw(const Rect& rect, const Rect& dirtyRect, const Style& style, OpacityType opaScale)
|
||||
{
|
||||
if ((rect.GetWidth() <= 0) || (rect.GetHeight() <= 0)) {
|
||||
GRAPHIC_LOGD("DrawRect::Draw width or height is zero\n");
|
||||
return;
|
||||
}
|
||||
|
||||
/**
|
||||
* no border
|
||||
* radius = 0 (1/4)
|
||||
* radius > 0 (2/4)
|
||||
* rect width > rect height
|
||||
* radius >= rect height / 2
|
||||
* radius < rect height / 2
|
||||
* rect width <= rect height
|
||||
* radius >= rect width / 2
|
||||
* radius < rect width / 2
|
||||
* have border
|
||||
* radius = 0 (3/4)
|
||||
* radius > 0 (4/4)
|
||||
* radius < border width (4.1/4)
|
||||
* radius = border width (4.2/4)
|
||||
* radius > border width (4.3/4)
|
||||
* rect width <= rect height
|
||||
* radius >= border width + rect height / 2
|
||||
* radius < border width + rect height / 2
|
||||
* rect width > rect height
|
||||
* radius >= border width + rect height / 2
|
||||
* radius < border width + rect height / 2
|
||||
*/
|
||||
if (style.borderWidth_ == 0) {
|
||||
if (style.borderRadius_ == 0) {
|
||||
/* no border no radius (1/4) */
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rect, dirtyRect, style.bgColor_, opa);
|
||||
return;
|
||||
} else {
|
||||
/* [2/4] no border with radius (2/4) */
|
||||
DrawRectRadiusWithoutBorder(rect, dirtyRect, style, opaScale);
|
||||
}
|
||||
} else {
|
||||
if (style.borderRadius_ == 0) {
|
||||
/* [3/4] border without radius (3/4) */
|
||||
DrawRectBorderWithoutRadius(rect, dirtyRect, style, opaScale);
|
||||
} else if (style.borderRadius_ < style.borderWidth_) {
|
||||
/* [4.1/4] radius < border width */
|
||||
DrawRectRadiusSmallThanBorder(rect, dirtyRect, style, opaScale);
|
||||
} else if (style.borderRadius_ == style.borderWidth_) {
|
||||
/* [4.2/4] radius = border width */
|
||||
DrawRectRadiusEqualBorder(rect, dirtyRect, style, opaScale);
|
||||
} else {
|
||||
/* [4.3/4] radius >= border width + rect height_or_width / 2 */
|
||||
DrawRectRadiusBiggerThanBorder(rect, dirtyRect, style, opaScale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusWithoutBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
// 2 : half
|
||||
if ((rect.GetWidth() > rect.GetHeight()) && (style.borderRadius_ >= rect.GetHeight() / 2)) {
|
||||
DrawRectRadiusWithoutBorderCon1(rect, dirtyRect, style, opaScale);
|
||||
} else if ((rect.GetWidth() < rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
|
||||
DrawRectRadiusWithoutBorderCon2(rect, dirtyRect, style, opaScale);
|
||||
} else if ((rect.GetWidth() == rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
|
||||
DrawRectRadiusWithoutBorderCon3(rect, dirtyRect, style, opaScale);
|
||||
} else {
|
||||
DrawRectRadiusWithoutBorderCon4(rect, dirtyRect, style, opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusWithoutBorderCon1(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = rect.GetHeight() / 2;
|
||||
int16_t col2X = rect.GetLeft() + radius - 1;
|
||||
int16_t col3X = rect.GetRight() - radius + 1;
|
||||
|
||||
int16_t row1Y = rect.GetTop();
|
||||
int16_t row2Y = rect.GetTop() + radius - 1;
|
||||
int16_t row3Y = rect.GetBottom();
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
// draw left sector
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col2X, row2Y};
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw right sector
|
||||
arcInfo.center = {col3X, row2Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw top rectangle
|
||||
Rect topRect(col2X, row1Y, col3X - 1, row2Y - 1);
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topRect, dirtyRect, style.bgColor_, opa);
|
||||
|
||||
// draw bottom rectangle
|
||||
Rect bottomRect(col2X + 1, row2Y, col3X - 1, row3Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomRect, dirtyRect, style.bgColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusWithoutBorderCon2(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = rect.GetWidth() / 2;
|
||||
int16_t col1X = rect.GetLeft();
|
||||
int16_t col2X = rect.GetLeft() + radius - 1;
|
||||
int16_t col3X = rect.GetRight();
|
||||
|
||||
int16_t row2Y = rect.GetTop() + radius - 1;
|
||||
int16_t row3Y = rect.GetBottom() - radius + 1;
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
// draw top sector
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col2X, row2Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw bottom sector
|
||||
arcInfo.center = {col2X, row3Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw middle rectangle
|
||||
Rect middleRect(col1X, row2Y + 1, col3X, row3Y - 1);
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleRect, dirtyRect, style.bgColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusWithoutBorderCon3(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = rect.GetWidth() / 2;
|
||||
int16_t col1X = rect.GetLeft() + radius - 1;
|
||||
int16_t row1Y = rect.GetTop() + radius - 1;
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
// draw circle
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col1X, row1Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusWithoutBorderCon4(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = style.borderRadius_;
|
||||
int16_t col1X = rect.GetLeft();
|
||||
int16_t col2X = rect.GetLeft() + radius - 1;
|
||||
int16_t col3X = rect.GetRight() - radius + 1;
|
||||
int16_t col4X = rect.GetRight();
|
||||
|
||||
int16_t row1Y = rect.GetTop();
|
||||
int16_t row2Y = rect.GetTop() + radius - 1;
|
||||
int16_t row3Y = rect.GetBottom() - radius + 1;
|
||||
int16_t row4Y = rect.GetBottom();
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// draw top rectangle
|
||||
Rect topRect(col2X, row1Y, col3X - 1, row2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topRect, dirtyRect, style.bgColor_, opa);
|
||||
|
||||
// draw middle rectangle
|
||||
Rect middleRect(col1X, row2Y + 1, col4X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleRect, dirtyRect, style.bgColor_, opa);
|
||||
|
||||
// draw bottom rectangle
|
||||
Rect bottomRect(col2X + 1, row3Y, col3X - 1, row4Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomRect, dirtyRect, style.bgColor_, opa);
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
// top left sector
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col2X, row2Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// top right sector
|
||||
arcInfo.center = {col3X, row2Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// bottom left sector
|
||||
arcInfo.center = {col2X, row3Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// bottom right sector
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectBorderWithoutRadius(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t col1X = rect.GetLeft();
|
||||
int16_t col2X = rect.GetLeft() + style.borderWidth_ - 1;
|
||||
int16_t col3X = rect.GetRight() - style.borderWidth_ + 1;
|
||||
int16_t col4X = rect.GetRight();
|
||||
|
||||
int16_t row1Y = rect.GetTop();
|
||||
int16_t row2Y = rect.GetTop() + style.borderWidth_ - 1;
|
||||
int16_t row3Y = rect.GetBottom() - style.borderWidth_ + 1;
|
||||
int16_t row4Y = rect.GetBottom();
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
|
||||
// draw top border
|
||||
Rect topRect(col1X, row1Y, col4X, row2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// draw left border
|
||||
Rect leftRect(col1X, row2Y + 1, col2X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(leftRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// draw middle rectangle
|
||||
Rect middleRect(col2X + 1, row2Y + 1, col3X - 1, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// draw right border
|
||||
Rect rightRect(col3X, row2Y + 1, col4X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rightRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// draw bottom border
|
||||
Rect bottomRect(col1X, row3Y, col4X, row4Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomRect, dirtyRect, style.borderColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusEqualBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t col1X = rect.GetLeft();
|
||||
int16_t col2X = rect.GetLeft() + style.borderRadius_ - 1;
|
||||
int16_t col3X = rect.GetRight() - style.borderRadius_ + 1;
|
||||
int16_t col4X = rect.GetRight();
|
||||
|
||||
int16_t row1Y = rect.GetTop();
|
||||
int16_t row2Y = rect.GetTop() + style.borderRadius_ - 1;
|
||||
int16_t row3Y = rect.GetBottom() - style.borderRadius_ + 1;
|
||||
int16_t row4Y = rect.GetBottom();
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = style.borderWidth_;
|
||||
arcStyle.lineColor_ = style.borderColor_;
|
||||
arcStyle.lineOpa_ = style.borderOpa_;
|
||||
// draw top left sector in border
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col2X, row2Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = style.borderRadius_;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw top right sector in border
|
||||
arcInfo.center = {col3X, row2Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw bottom left sector in border
|
||||
arcInfo.center = {col2X, row3Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw bottom right sector in border
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
|
||||
// draw top rectangle in border
|
||||
Rect topRect(col2X, row1Y, col3X - 1, row2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// draw left rectangle in border
|
||||
Rect leftRect(col1X, row2Y + 1, col2X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(leftRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// draw middle rectangle
|
||||
Rect middleRect(col2X + 1, row2Y + 1, col3X - 1, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// draw right rectangle in border
|
||||
Rect rightRect(col3X, row2Y + 1, col4X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rightRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// draw bottom rectangle in border
|
||||
Rect bottomRect(col2X + 1, row3Y, col3X - 1, row4Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomRect, dirtyRect, style.borderColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusSmallThanBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radiusCol1X = rect.GetLeft();
|
||||
int16_t radiusCol2X = rect.GetLeft() + style.borderRadius_ - 1;
|
||||
int16_t radiusCol3X = rect.GetRight() - style.borderRadius_ + 1;
|
||||
int16_t radiusCol4X = rect.GetRight();
|
||||
|
||||
int16_t radiusRow1Y = rect.GetTop();
|
||||
int16_t radiusRow2Y = rect.GetTop() + style.borderRadius_ - 1;
|
||||
int16_t radiusRow3Y = rect.GetBottom() - style.borderRadius_ + 1;
|
||||
int16_t radiusRow4Y = rect.GetBottom();
|
||||
|
||||
int16_t rectCol1X = radiusCol1X;
|
||||
int16_t rectCol2X = rect.GetLeft() + style.borderWidth_ - 1;
|
||||
int16_t rectCol3X = rect.GetRight() - style.borderWidth_ + 1;
|
||||
int16_t rectCol4X = radiusCol4X;
|
||||
|
||||
int16_t rectRow1Y = radiusRow2Y;
|
||||
int16_t rectRow2Y = rect.GetTop() + style.borderWidth_ - 1;
|
||||
int16_t rectRow3Y = rect.GetBottom() - style.borderWidth_ + 1;
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = style.borderWidth_;
|
||||
arcStyle.lineColor_ = style.borderColor_;
|
||||
arcStyle.lineOpa_ = style.borderOpa_;
|
||||
// draw top left sector in border
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {radiusCol2X, radiusRow2Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = style.borderRadius_;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw top right sector in border
|
||||
arcInfo.center = {radiusCol3X, radiusRow2Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw bottom left sector in border
|
||||
arcInfo.center = {radiusCol2X, radiusRow3Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
// draw bottom right sector in border
|
||||
arcInfo.center = {radiusCol3X, radiusRow3Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
|
||||
// draw top rectangle in border
|
||||
Rect topRect(radiusCol2X, radiusRow1Y, radiusCol3X - 1, radiusRow2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topRect, dirtyRect, style.borderColor_, opa);
|
||||
Rect topRect2(rectCol1X, rectRow1Y + 1, rectCol4X, rectRow2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topRect2, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// draw left rectangle in border
|
||||
Rect leftRect(rectCol1X, rectRow2Y + 1, rectCol2X, rectRow3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(leftRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// draw middle rectangle
|
||||
Rect middleRect(rectCol2X + 1, rectRow2Y + 1, rectCol3X - 1, rectRow3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// draw right rectangle in border
|
||||
Rect rightRect(rectCol3X, rectRow2Y + 1, rectCol4X, rectRow3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rightRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// draw bottom rectangle in border
|
||||
Rect bottomRect(radiusCol2X + 1, radiusRow3Y, radiusCol3X - 1, radiusRow4Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomRect, dirtyRect, style.borderColor_, opa);
|
||||
Rect bottomRect2(rectCol1X, rectRow3Y, rectCol4X, radiusRow3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomRect2, dirtyRect, style.borderColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusBiggerThanBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
// 2 : half
|
||||
if ((rect.GetWidth() > rect.GetHeight()) && (style.borderRadius_ >= rect.GetHeight() / 2)) {
|
||||
DrawRectRadiusBiggerThanBorderCon1(rect, dirtyRect, style, opaScale);
|
||||
} else if ((rect.GetWidth() < rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
|
||||
DrawRectRadiusBiggerThanBorderCon2(rect, dirtyRect, style, opaScale);
|
||||
} else if ((rect.GetWidth() == rect.GetHeight()) && (style.borderRadius_ >= rect.GetWidth() / 2)) {
|
||||
DrawRectRadiusBiggerThanBorderCon3(rect, dirtyRect, style, opaScale);
|
||||
} else {
|
||||
DrawRectRadiusBiggerThanBorderCon4(rect, dirtyRect, style, opaScale);
|
||||
}
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusBiggerThanBorderCon1(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = rect.GetHeight() / 2;
|
||||
int16_t borderWidth = style.borderWidth_;
|
||||
int16_t col2X = rect.GetLeft() + radius - 1;
|
||||
int16_t col3X = rect.GetRight() - radius + 1;
|
||||
|
||||
int16_t row1Y = rect.GetTop();
|
||||
int16_t row2Y = rect.GetTop() + borderWidth - 1;
|
||||
int16_t row3Y = rect.GetTop() + radius - 1;
|
||||
int16_t row4Y = rect.GetBottom() - borderWidth + 1;
|
||||
int16_t row5Y = rect.GetBottom();
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = borderWidth;
|
||||
arcStyle.lineColor_ = style.borderColor_;
|
||||
arcStyle.lineOpa_ = style.borderOpa_;
|
||||
// draw left arc in border
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col2X, row3Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw right arc in border
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
radius = radius - borderWidth;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
|
||||
// draw left sector in rectangle
|
||||
arcInfo.center = {col2X, row3Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw right sector in rectangle
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
|
||||
// top rectangle in border
|
||||
Rect topBorderRect(col2X, row1Y, col3X - 1, row2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// middle rectangle inner
|
||||
Rect middleInnerRect(col2X, row2Y + 1, col3X - 1, row3Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleInnerRect, dirtyRect, style.bgColor_, opaBg);
|
||||
Rect middleInnerRect2(col2X + 1, row3Y + 1, col3X - 1, row4Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleInnerRect2, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// bottom rectangle in border
|
||||
Rect bottomBorderRect(col2X + 1, row4Y, col3X - 1, row5Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusBiggerThanBorderCon2(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = rect.GetWidth() / 2;
|
||||
int16_t borderWidth = style.borderWidth_;
|
||||
int16_t col1X = rect.GetLeft();
|
||||
int16_t col2X = rect.GetLeft() + borderWidth - 1;
|
||||
int16_t col3X = rect.GetLeft() + radius - 1;
|
||||
int16_t col4X = rect.GetRight() - borderWidth + 1;
|
||||
int16_t col5X = rect.GetRight();
|
||||
|
||||
int16_t row2Y = rect.GetTop() + radius - 1;
|
||||
int16_t row3Y = rect.GetBottom() - radius + 1;
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = borderWidth;
|
||||
arcStyle.lineColor_ = style.borderColor_;
|
||||
arcStyle.lineOpa_ = style.borderOpa_;
|
||||
// draw top arc in border
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col3X, row2Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw bottom arc in border
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
radius = radius - borderWidth;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
|
||||
// draw top sector in rectangle
|
||||
arcInfo.center = {col3X, row2Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw bottom sector in rectangle
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
|
||||
// left rectangle in border
|
||||
Rect topBorderRect(col1X, row2Y + 1, col2X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// middle rectangle inner
|
||||
Rect middleInnerRect(col2X + 1, row2Y + 1, col4X - 1, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleInnerRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// right rectangle in border
|
||||
Rect bottomBorderRect(col4X, row2Y + 1, col5X, row3Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusBiggerThanBorderCon3(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = rect.GetWidth() / 2;
|
||||
int16_t borderWidth = style.borderWidth_;
|
||||
int16_t col2X = rect.GetLeft() + radius - 1;
|
||||
int16_t row2Y = rect.GetTop() + radius - 1;
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = borderWidth;
|
||||
arcStyle.lineColor_ = style.borderColor_;
|
||||
arcStyle.lineOpa_ = style.borderOpa_;
|
||||
// draw circle in border
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col2X, row2Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
radius = radius - borderWidth;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
|
||||
// draw circle in rectangle
|
||||
arcInfo.center = {col2X, row2Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
}
|
||||
|
||||
void DrawRect::DrawRectRadiusBiggerThanBorderCon4(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale)
|
||||
{
|
||||
int16_t radius = style.borderRadius_;
|
||||
int16_t borderWidth = style.borderWidth_;
|
||||
int16_t col1X = rect.GetLeft();
|
||||
int16_t col2X = rect.GetLeft() + borderWidth - 1;
|
||||
int16_t col3X = rect.GetLeft() + radius - 1;
|
||||
int16_t col4X = rect.GetRight() - radius + 1;
|
||||
int16_t col5X = rect.GetRight() - borderWidth + 1;
|
||||
int16_t col6X = rect.GetRight();
|
||||
|
||||
int16_t row1Y = rect.GetTop();
|
||||
int16_t row2Y = rect.GetTop() + borderWidth - 1;
|
||||
int16_t row3Y = rect.GetTop() + radius - 1;
|
||||
int16_t row4Y = rect.GetBottom() - radius + 1;
|
||||
int16_t row5Y = rect.GetBottom() - borderWidth + 1;
|
||||
int16_t row6Y = rect.GetBottom();
|
||||
|
||||
Style arcStyle = style;
|
||||
arcStyle.lineWidth_ = borderWidth;
|
||||
arcStyle.lineColor_ = style.borderColor_;
|
||||
arcStyle.lineOpa_ = style.borderOpa_;
|
||||
|
||||
// draw top left arc in border
|
||||
ArcInfo arcInfo;
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
arcInfo.imgPos = {0, 0};
|
||||
arcInfo.imgSrc = nullptr;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw top right arc in border
|
||||
arcInfo.center = {col4X, row3Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw bottom left arc in border
|
||||
arcInfo.center = {col3X, row4Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw bottom right arc in border
|
||||
arcInfo.center = {col4X, row4Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
radius = radius - borderWidth;
|
||||
arcStyle.lineWidth_ = radius;
|
||||
arcStyle.lineColor_ = style.bgColor_;
|
||||
arcStyle.lineOpa_ = style.bgOpa_;
|
||||
|
||||
// draw top left sector in rectangle
|
||||
arcInfo.center = {col3X, row3Y};
|
||||
arcInfo.startAngle = THREE_QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = CIRCLE_IN_DEGREE;
|
||||
arcInfo.radius = radius;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw top right sector in rectangle
|
||||
arcInfo.center = {col4X, row3Y};
|
||||
arcInfo.startAngle = 0;
|
||||
arcInfo.endAngle = QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw bottom left sector in rectangle
|
||||
arcInfo.center = {col3X, row4Y};
|
||||
arcInfo.startAngle = SEMICIRCLE_IN_DEGREE;
|
||||
arcInfo.endAngle = THREE_QUARTER_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
// draw bottom right sector in rectangle
|
||||
arcInfo.center = {col4X, row4Y};
|
||||
arcInfo.startAngle = QUARTER_IN_DEGREE;
|
||||
arcInfo.endAngle = SEMICIRCLE_IN_DEGREE;
|
||||
DrawArc::GetInstance()->Draw(arcInfo, dirtyRect, arcStyle, opaScale, CapType::CAP_NONE);
|
||||
|
||||
OpacityType opa = DrawUtils::GetMixOpacity(opaScale, style.borderOpa_);
|
||||
// top rectangle in border
|
||||
Rect topBorderRect(col3X, row1Y, col4X - 1, row2Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
OpacityType opaBg = DrawUtils::GetMixOpacity(opaScale, style.bgOpa_);
|
||||
// top rectangle inner
|
||||
Rect topInnerRect(col3X, row2Y + 1, col4X - 1, row3Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(topInnerRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// left rectangle in border
|
||||
Rect leftBorderRect(col1X, row3Y + 1, col2X, row4Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(leftBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// middle rectangle inner
|
||||
Rect middleInnerRect(col2X + 1, row3Y + 1, col5X - 1, row4Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(middleInnerRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// right rectangle in border
|
||||
Rect rightBorderRect(col5X, row3Y + 1, col6X, row4Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(rightBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
|
||||
// bottom rectangle inner
|
||||
Rect bottomInnerRect(col3X + 1, row4Y, col4X - 1, row5Y - 1);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomInnerRect, dirtyRect, style.bgColor_, opaBg);
|
||||
|
||||
// bottom rectangle in border
|
||||
Rect bottomBorderRect(col3X + 1, row5Y, col4X - 1, row6Y);
|
||||
DrawUtils::GetInstance()->DrawColorArea(bottomBorderRect, dirtyRect, style.borderColor_, opa);
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+61
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_RECT_H
|
||||
#define GRAPHIC_LITE_DRAW_RECT_H
|
||||
|
||||
#include "components/ui_view.h"
|
||||
|
||||
namespace OHOS {
|
||||
/** @brief Class for drawing rectangle. */
|
||||
class DrawRect : public HeapBase {
|
||||
public:
|
||||
DrawRect() {};
|
||||
~DrawRect() {};
|
||||
|
||||
static void Draw(const Rect& rect, const Rect& dirtyRect, const Style& style, OpacityType opaScale);
|
||||
|
||||
private:
|
||||
static void DrawRectRadiusWithoutBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectBorderWithoutRadius(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusEqualBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusSmallThanBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusBiggerThanBorder(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
|
||||
static void DrawRectRadiusWithoutBorderCon1(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusWithoutBorderCon2(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusWithoutBorderCon3(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusWithoutBorderCon4(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
|
||||
static void DrawRectRadiusBiggerThanBorderCon1(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusBiggerThanBorderCon2(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusBiggerThanBorderCon3(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
static void DrawRectRadiusBiggerThanBorderCon4(const Rect& rect, const Rect& dirtyRect, const Style& style,
|
||||
OpacityType opaScale);
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_DRAW_RECT_H
|
||||
Executable
+121
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 "draw/draw_triangle.h"
|
||||
#include "draw/draw_utils.h"
|
||||
|
||||
namespace OHOS {
|
||||
void DrawTriangle::Draw(const Point* points, uint8_t count, const Rect& mask, const ColorType& color, OpacityType opa)
|
||||
{
|
||||
if ((points == nullptr) || (count != VERTEX_NUM)) {
|
||||
return;
|
||||
}
|
||||
// sort vertex according to y axis
|
||||
Point p1 = points[0]; // 0: point index
|
||||
Point p2 = points[1]; // 1: point index
|
||||
Point p3 = points[2]; // 2: point index
|
||||
// return if vertexs are invalid.
|
||||
if ((p1.x == p2.x) && ((p1.y == p2.y) || (p1.x == p3.x))) {
|
||||
return;
|
||||
}
|
||||
if ((p2.x == p3.x) && (p2.y == p3.y)) {
|
||||
return;
|
||||
}
|
||||
if (((p1.x == p3.x) || (p1.y == p2.y)) && (p1.y == p3.y)) {
|
||||
return;
|
||||
}
|
||||
SortVertexs(p1, p2, p3);
|
||||
Edge edge1 = InitEdge(p1, p2);
|
||||
Edge edge2 = InitEdge(p1, p3);
|
||||
Rect area;
|
||||
int16_t lastY = p1.y;
|
||||
|
||||
while (edge1.curPoint.y <= p3.y) {
|
||||
// change edge1 from p1-p2 to p2-p3
|
||||
if (edge1.curPoint.y == p2.y) {
|
||||
edge1 = InitEdge(p2, p3);
|
||||
if (edge1.dPoint.y == 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
area.SetLeft(MATH_MIN(edge1.curPoint.x, edge2.curPoint.x));
|
||||
area.SetRight(MATH_MAX(edge1.curPoint.x, edge2.curPoint.x));
|
||||
area.SetTop(MATH_MIN(edge1.curPoint.y, edge2.curPoint.y));
|
||||
area.SetBottom(MATH_MAX(edge1.curPoint.y, edge2.curPoint.y));
|
||||
DrawUtils::GetInstance()->DrawColorArea(area, mask, color, opa);
|
||||
|
||||
while (edge1.curPoint.y == lastY) {
|
||||
// use Bresenham algorithm to get next point on edge1
|
||||
StepToNextPointOnEdge(edge1);
|
||||
}
|
||||
while (edge2.curPoint.y == lastY) {
|
||||
// use Bresenham algorithm to get next point on edge2
|
||||
StepToNextPointOnEdge(edge2);
|
||||
}
|
||||
lastY = edge1.curPoint.y;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTriangle::SortVertexs(Point& p1, Point& p2, Point& p3)
|
||||
{
|
||||
SortPoint(p1, p2);
|
||||
SortPoint(p2, p3);
|
||||
SortPoint(p1, p2);
|
||||
}
|
||||
|
||||
void DrawTriangle::SortPoint(Point& p1, Point& p2)
|
||||
{
|
||||
Point temp;
|
||||
if (p1.y > p2.y) {
|
||||
temp = p1;
|
||||
p1 = p2;
|
||||
p2 = temp;
|
||||
}
|
||||
}
|
||||
|
||||
void DrawTriangle::StepToNextPointOnEdge(Edge& edge)
|
||||
{
|
||||
if (edge.dPoint.x > edge.dPoint.y) {
|
||||
edge.curPoint.x += edge.uPoint.x;
|
||||
edge.eps += edge.dPoint.y;
|
||||
if ((edge.eps << 1) >= edge.dPoint.x) {
|
||||
edge.curPoint.y += edge.uPoint.y;
|
||||
edge.eps -= edge.dPoint.x;
|
||||
}
|
||||
} else {
|
||||
edge.curPoint.y += edge.uPoint.y;
|
||||
edge.eps += edge.dPoint.x;
|
||||
if ((edge.eps << 1) >= edge.dPoint.y) {
|
||||
edge.curPoint.x += edge.uPoint.x;
|
||||
edge.eps -= edge.dPoint.y;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DrawTriangle::Edge DrawTriangle::InitEdge(const Point& startP, const Point& endP)
|
||||
{
|
||||
Edge edge = { {0, 0}, {0, 0}, {0, 0}, 0 };
|
||||
edge.curPoint = startP;
|
||||
edge.dPoint.x = startP.x - endP.x;
|
||||
edge.dPoint.y = startP.y - endP.y;
|
||||
edge.uPoint.x = (edge.dPoint.x < 0) ? 1 : -1;
|
||||
edge.uPoint.y = (edge.dPoint.y < 0) ? 1 : -1;
|
||||
edge.eps = 0;
|
||||
edge.dPoint.x = MATH_ABS(edge.dPoint.x);
|
||||
edge.dPoint.y = MATH_ABS(edge.dPoint.y);
|
||||
return edge;
|
||||
}
|
||||
} // namespace OHOS
|
||||
Executable
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Copyright (c) 2020-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 GRAPHIC_LITE_DRAW_TRIANGLE_H
|
||||
#define GRAPHIC_LITE_DRAW_TRIANGLE_H
|
||||
|
||||
#include "color.h"
|
||||
#include "geometry2d.h"
|
||||
|
||||
namespace OHOS {
|
||||
class DrawTriangle : public HeapBase {
|
||||
public:
|
||||
static void Draw(const Point* points, uint8_t count, const Rect& mask, const ColorType& color, OpacityType opa);
|
||||
|
||||
struct Edge {
|
||||
Point curPoint;
|
||||
Point dPoint;
|
||||
Point uPoint;
|
||||
int16_t eps;
|
||||
};
|
||||
|
||||
static void SortVertexs(Point& p1, Point& p2, Point& p3);
|
||||
|
||||
static void SortPoint(Point& p1, Point& p2);
|
||||
|
||||
static void StepToNextPointOnEdge(Edge& edge);
|
||||
|
||||
static Edge InitEdge(const Point& startP, const Point& endP);
|
||||
private:
|
||||
static constexpr uint8_t VERTEX_NUM = 3;
|
||||
};
|
||||
} // namespace OHOS
|
||||
#endif // GRAPHIC_LITE_DRAW_TRIANGLE_H
|
||||
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user