1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/accessibility/accessibility_utils.h"
17
18 namespace OHOS::Ace {
19
20 const char ACCESSIBILITY_TAG_DIV[] = "div";
21 const char ACCESSIBILITY_TAG_CALENDAR[] = "calendar";
22 const char ACCESSIBILITY_TAG_TEXT[] = "text";
23 const char ACCESSIBILITY_TAG_PICKER[] = "picker";
24 const char ACCESSIBILITY_TAG_OPTION[] = "option";
25 const char ACCESSIBILITY_TAG_POPUP[] = "popup";
26 const char ACCESSIBILITY_TAG_PROGRESS[] = "progress";
27 const char ACCESSIBILITY_TAG_SELECT[] = "select";
28 const char ACCESSIBILITY_TAG_MENU[] = "menu";
29 const char ACCESSIBILITY_TAG_SLIDER[] = "slider";
30 const char ACCESSIBILITY_TAG_SPAN[] = "span";
31 const char ACCESSIBILITY_TAG_STACK[] = "stack";
32 const char ACCESSIBILITY_TAG_SWIPER[] = "swiper";
33 const char ACCESSIBILITY_TAG_SWITCH[] = "switch";
34 const char ACCESSIBILITY_TAG_TABS[] = "tabs";
35 const char ACCESSIBILITY_TAG_TAB_BAR[] = "tab-bar";
36 const char ACCESSIBILITY_TAG_TAB_CONTENT[] = "tab-content";
37 const char ACCESSIBILITY_TAG_REFRESH[] = "refresh";
38 const char ACCESSIBILITY_TAG_IMAGE[] = "image";
39 const char ACCESSIBILITY_TAG_LIST[] = "list";
40 const char ACCESSIBILITY_TAG_LIST_ITEM[] = "list-item";
41 const char ACCESSIBILITY_TAG_LIST_ITEM_GROUP[] = "list-item-group";
42 const char ACCESSIBILITY_TAG_VIDEO[] = "video";
43 const char ACCESSIBILITY_TAG_RATING[] = "rating";
44 const char ACCESSIBILITY_TAG_MARQUEE[] = "marquee";
45 const char ACCESSIBILITY_TAG_NAVIGATION_BAR[] = "navigation-bar";
46 const char ACCESSIBILITY_TAG_NAVIGATION_MENU[] = "navigation-menu";
47 const char ACCESSIBILITY_TAG_TEXTAREA[] = "textarea";
48 const char ACCESSIBILITY_TAG_INPUT[] = "input";
49 const char ACCESSIBILITY_TAG_LABEL[] = "label";
50 const char ACCESSIBILITY_TAG_DIVIDER[] = "divider";
51 const char ACCESSIBILITY_TAG_CANVAS[] = "canvas";
52 const char ACCESSIBILITY_TAG_BUTTON[] = "button";
53 const char ACCESSIBILITY_TAG_CHART[] = "chart";
54 const char ACCESSIBILITY_TAG_CLOCK[] = "clock";
55 const char ACCESSIBILITY_TAG_DIALOG[] = "dialog";
56 const char ACCESSIBILITY_TAG_SEARCH[] = "search";
57
58 const int32_t WEIGHTED_VALUE = 13;
59 const int32_t FOCUS_DIRECTION_UP = 1;
60 const int32_t FOCUS_DIRECTION_DOWN = 1 << 1;
61 const int32_t FOCUS_DIRECTION_LEFT = 1 << 2;
62 const int32_t FOCUS_DIRECTION_RIGHT = 1 << 3;
63 const int32_t FOCUS_DIRECTION_FORWARD = 1 << 4;
64 const int32_t FOCUS_DIRECTION_BACKWARD = 1 << 5;
65
CheckRectBeam(const Rect & nodeRect,const Rect & itemRect,const int direction)66 static bool CheckRectBeam(const Rect& nodeRect, const Rect& itemRect, const int direction)
67 {
68 switch (direction) {
69 case FOCUS_DIRECTION_LEFT:
70 case FOCUS_DIRECTION_RIGHT:
71 return nodeRect.Top() < itemRect.Bottom() && itemRect.Top() < nodeRect.Bottom();
72 case FOCUS_DIRECTION_UP:
73 case FOCUS_DIRECTION_DOWN:
74 return nodeRect.Left() < itemRect.Right() && itemRect.Left() < nodeRect.Right();
75 default:
76 break;
77 }
78 return false;
79 }
80
IsToDirectionOf(const Rect & nodeRect,const Rect & itemRect,const int direction)81 static bool IsToDirectionOf(const Rect& nodeRect, const Rect& itemRect, const int direction)
82 {
83 switch (direction) {
84 case FOCUS_DIRECTION_LEFT:
85 return nodeRect.Left() >= itemRect.Right();
86 case FOCUS_DIRECTION_RIGHT:
87 return nodeRect.Right() <= itemRect.Left();
88 case FOCUS_DIRECTION_UP:
89 return nodeRect.Top() >= itemRect.Bottom();
90 case FOCUS_DIRECTION_DOWN:
91 return nodeRect.Bottom() <= itemRect.Top();
92 default:
93 break;
94 }
95 return false;
96 }
97
MajorAxisDistanceToFarEdge(const Rect & nodeRect,const Rect & itemRect,const int direction)98 static double MajorAxisDistanceToFarEdge(const Rect& nodeRect, const Rect& itemRect, const int direction)
99 {
100 double distance = 0.0;
101 switch (direction) {
102 case FOCUS_DIRECTION_LEFT:
103 distance = nodeRect.Left() - itemRect.Left();
104 break;
105 case FOCUS_DIRECTION_RIGHT:
106 distance = itemRect.Right() - nodeRect.Right();
107 break;
108 case FOCUS_DIRECTION_UP:
109 distance = nodeRect.Top() - itemRect.Top();
110 break;
111 case FOCUS_DIRECTION_DOWN:
112 distance = itemRect.Bottom() - nodeRect.Bottom();
113 break;
114 default:
115 break;
116 }
117
118 return distance > 1.0 ? distance : 1.0;
119 }
120
MajorAxisDistance(const Rect & nodeRect,const Rect & itemRect,const int direction)121 static double MajorAxisDistance(const Rect& nodeRect, const Rect& itemRect, const int direction)
122 {
123 double distance = 0.0;
124 switch (direction) {
125 case FOCUS_DIRECTION_LEFT:
126 distance = nodeRect.Left() - itemRect.Right();
127 break;
128 case FOCUS_DIRECTION_RIGHT:
129 distance = itemRect.Left() - nodeRect.Right();
130 break;
131 case FOCUS_DIRECTION_UP:
132 distance = nodeRect.Top() - itemRect.Bottom();
133 break;
134 case FOCUS_DIRECTION_DOWN:
135 distance = itemRect.Top() - nodeRect.Bottom();
136 break;
137 default:
138 break;
139 }
140
141 return distance > 0.0 ? distance : 0.0;
142 }
143
MinorAxisDistance(const Rect & nodeRect,const Rect & itemRect,const int direction)144 static double MinorAxisDistance(const Rect& nodeRect, const Rect& itemRect, const int direction)
145 {
146 double distance = 0.0;
147 switch (direction) {
148 case FOCUS_DIRECTION_LEFT:
149 case FOCUS_DIRECTION_RIGHT:
150 distance = fabs((nodeRect.Top() + nodeRect.Bottom()) / 2 - (itemRect.Top() + itemRect.Bottom()) / 2);
151 break;
152 case FOCUS_DIRECTION_UP:
153 case FOCUS_DIRECTION_DOWN:
154 distance = fabs((nodeRect.Left() + nodeRect.Right()) / 2 - (itemRect.Left() + itemRect.Right()) / 2);
155 break;
156 default:
157 break;
158 }
159
160 return distance > 0.0 ? distance : -distance;
161 }
162
GetWeightedDistanceFor(double majorAxisDistance,double minorAxisDistance)163 static double GetWeightedDistanceFor(double majorAxisDistance, double minorAxisDistance)
164 {
165 return WEIGHTED_VALUE * majorAxisDistance * majorAxisDistance + minorAxisDistance * minorAxisDistance;
166 }
167
IsCandidateRect(const Rect & nodeRect,const Rect & itemRect,const int direction)168 static bool IsCandidateRect(const Rect& nodeRect, const Rect& itemRect, const int direction)
169 {
170 switch (direction) {
171 case FOCUS_DIRECTION_LEFT:
172 return nodeRect.Left() > itemRect.Left() && nodeRect.Right() > itemRect.Right();
173 case FOCUS_DIRECTION_RIGHT:
174 return nodeRect.Left() < itemRect.Left() && nodeRect.Right() < itemRect.Right();
175 case FOCUS_DIRECTION_UP:
176 return nodeRect.Top() > itemRect.Top() && nodeRect.Bottom() > itemRect.Bottom();
177 case FOCUS_DIRECTION_DOWN:
178 return nodeRect.Top() < itemRect.Top() && nodeRect.Bottom() < itemRect.Bottom();
179 default:
180 break;
181 }
182 return false;
183 }
184
185 // Check whether rect1 is outright better than rect2.
OutrightBetter(const Rect & nodeRect,const int direction,const Rect & Rect1,const Rect & Rect2)186 static bool OutrightBetter(const Rect& nodeRect, const int direction, const Rect& Rect1, const Rect& Rect2)
187 {
188 bool rect1InSrcBeam = CheckRectBeam(nodeRect, Rect1, direction);
189 bool rect2InSrcBeam = CheckRectBeam(nodeRect, Rect2, direction);
190 if (rect2InSrcBeam || !rect1InSrcBeam) {
191 return false;
192 }
193
194 if (!IsToDirectionOf(nodeRect, Rect2, direction)) {
195 return true;
196 }
197
198 // for direction left or right
199 if (direction == FOCUS_DIRECTION_LEFT || direction == FOCUS_DIRECTION_RIGHT) {
200 return true;
201 }
202
203 return (MajorAxisDistance(nodeRect, Rect1, direction) < MajorAxisDistanceToFarEdge(nodeRect, Rect2, direction));
204 }
205
CheckBetterRect(const Rect & nodeRect,const int direction,const Rect & itemRect,const Rect & tempBest)206 bool CheckBetterRect(const Rect& nodeRect, const int direction, const Rect& itemRect, const Rect& tempBest)
207 {
208 if (!IsCandidateRect(nodeRect, itemRect, direction)) {
209 return false;
210 }
211
212 if (!IsCandidateRect(nodeRect, tempBest, direction)) {
213 return true;
214 }
215
216 // now both of item and tempBest are all at the direction of node.
217 if (OutrightBetter(nodeRect, direction, itemRect, tempBest)) {
218 return true;
219 }
220
221 if (OutrightBetter(nodeRect, direction, tempBest, itemRect)) {
222 return false;
223 }
224
225 // otherwise, do fudge-tastic comparison of the major and minor axis
226 return (GetWeightedDistanceFor(
227 MajorAxisDistance(nodeRect, itemRect, direction), MinorAxisDistance(nodeRect, itemRect, direction)) <
228 GetWeightedDistanceFor(
229 MajorAxisDistance(nodeRect, tempBest, direction), MinorAxisDistance(nodeRect, tempBest, direction)));
230 }
231
232 } // namespace OHOS::Ace