1 /*
2 * Copyright (C) 2023 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 "accessibility_circle_drawing_manager.h"
17 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
18 #include "accessibility_display_manager.h"
19 #endif
20 #include "hilog_wrapper.h"
21 #include "pipeline/rs_recording_canvas.h"
22 #include "recording/recording_canvas.h"
23
24 namespace OHOS {
25 namespace Accessibility {
26
27 constexpr int32_t DEFAULT_VALUE = -1;
28
29 constexpr int32_t OUT_CIRCLE_RADIUS = 49; // outer circle
30 constexpr int32_t PROGRESS_RADIUS = 46; // progress circle background
31 constexpr int32_t CENTER_CIRCLE_RADIUS = 6; // center circle
32 constexpr int32_t PROGRESS_STROKE_WIDTH = 2; // progress stroke
33
34 constexpr int32_t OUT_CIRCLE_BACKGROUND_ALPHA = 64;
35 constexpr int32_t PROGRESS_BACKGROUND_ALPHA = 153;
36 constexpr int32_t CENTER_CIRCLE_BACKGROUND_ALPHA = 230;
37 constexpr int32_t PROGRESS_BAR_BACKGROUND_ALPHA = 230;
38
39 const std::string PROGRESS_BACKGROUND_COLOR_TYPE = "#0A59F7"; // progress circle background
40 const std::string PROGRESS_COLOR_TYPE = "#FFFFFF"; // center circle
41 const std::string OUT_CIRCLE_BACKGROUND_COLOR_TYPE = "#1756C4"; // outer circle
42
43 constexpr int32_t DEFAULT_WIDTH = 500;
44 constexpr int32_t DEFAULT_HEIGHT = 500;
45 constexpr int32_t DEFAULT_HALF = 2;
46
47 constexpr int32_t DEFAULT_PIXEL_DENSITY = 160;
48
49 constexpr int32_t HEXADECIMAL = 16;
50 constexpr int32_t DECIMAL = 10;
51 constexpr char CHAR_0 = '0';
52 constexpr char CHAR_9 = '9';
53 constexpr char CHAR_A = 'A';
54 constexpr char CHAR_B = 'B';
55 constexpr char CHAR_C = 'C';
56 constexpr char CHAR_D = 'D';
57 constexpr char CHAR_E = 'E';
58 constexpr char CHAR_F = 'F';
59
60 constexpr int32_t COLOR_STRING_LENGTH = 2;
61 constexpr int32_t RED_START_INDEX = 1;
62 constexpr int32_t GREEN_START_INDEX = 3;
63 constexpr int32_t BLUE_START_INDEX = 5;
64
65 constexpr int32_t NUMBER_0 = 0;
66 constexpr int32_t NUMBER_1 = 1;
67 constexpr int32_t NUMBER_2 = 2;
68
69 constexpr int32_t START_ANGLE = -90; // start angle
70 constexpr int32_t INVALID_NODE_ID = -1;
71
72 std::shared_ptr<AccessibilityCircleDrawingManager> AccessibilityCircleDrawingManager::pointDrawMgr_ = nullptr;
73
GetInstance()74 std::shared_ptr<AccessibilityCircleDrawingManager> AccessibilityCircleDrawingManager::GetInstance()
75 {
76 HILOG_DEBUG();
77 if (pointDrawMgr_ == nullptr) {
78 pointDrawMgr_ = std::make_shared<AccessibilityCircleDrawingManager>();
79 }
80 return pointDrawMgr_;
81 }
82
DeleteInstance()83 void AccessibilityCircleDrawingManager::DeleteInstance()
84 {
85 HILOG_DEBUG();
86 if (pointDrawMgr_ == nullptr) {
87 HILOG_ERROR("surfaceNode_ is nullptr");
88 return;
89 }
90 pointDrawMgr_ = nullptr;
91 }
92
AccessibilityCircleDrawingManager()93 AccessibilityCircleDrawingManager::AccessibilityCircleDrawingManager()
94 {
95 HILOG_DEBUG();
96 imageWidth_ = DEFAULT_WIDTH;
97 imageHeight_ = DEFAULT_HEIGHT;
98 half_ = DEFAULT_WIDTH / DEFAULT_HALF;
99
100 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
101 AccessibilityDisplayManager &displayMgr = Singleton<AccessibilityDisplayManager>::GetInstance();
102 screenId_ = displayMgr.GetDefaultDisplayId(); // default screenId 0
103 auto dpi = displayMgr.GetDefaultDisplayDpi();
104 dispalyDensity_ = static_cast<float>(dpi) / DEFAULT_PIXEL_DENSITY;
105 #else
106 HILOG_DEBUG("not support display manager");
107 screenId_ = 0;
108 dispalyDensity_ = 1;
109 #endif
110 }
111
~AccessibilityCircleDrawingManager()112 AccessibilityCircleDrawingManager::~AccessibilityCircleDrawingManager()
113 {
114 HILOG_DEBUG();
115 if (surfaceNode_ == nullptr) {
116 HILOG_ERROR("surfaceNode_ is nullptr");
117 return;
118 }
119
120 surfaceNode_->ClearChildren();
121 surfaceNode_->DetachToDisplay(screenId_);
122 surfaceNode_ = nullptr;
123 canvasNode_ = nullptr;
124 if (rsUiDirector_ != nullptr) {
125 rsUiDirector_->SetRoot(INVALID_NODE_ID);
126 }
127
128 rootNode_ = nullptr;
129 rsUiDirector_ = nullptr;
130 Rosen::RSTransaction::FlushImplicitTransaction();
131 }
132
UpdatePointerVisible(bool state)133 void AccessibilityCircleDrawingManager::UpdatePointerVisible(bool state)
134 {
135 HILOG_DEBUG("state %{public}s", state ? "true" : "false");
136 if (surfaceNode_ == nullptr) {
137 HILOG_ERROR("surfaceNode_ is nullptr");
138 return;
139 }
140
141 surfaceNode_->SetVisible(state);
142 Rosen::RSTransaction::FlushImplicitTransaction();
143 }
144
CreatePointerWindow(int32_t physicalX,int32_t physicalY,uint64_t screenId)145 void AccessibilityCircleDrawingManager::CreatePointerWindow(int32_t physicalX, int32_t physicalY, uint64_t screenId)
146 {
147 rsUiDirector_ = Rosen::RSUIDirector::Create();
148 if (rsUiDirector_ == nullptr) {
149 return;
150 }
151 Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
152 surfaceNodeConfig.SurfaceNodeName = "screen touch progress";
153 Rosen::RSSurfaceNodeType surfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
154 surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
155 if (surfaceNode_ == nullptr) {
156 HILOG_ERROR("create surfaceNode_ fail");
157 return;
158 }
159
160 rsUiDirector_->Init();
161 surfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT_FILL);
162 surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
163 surfaceNode_->SetBounds(physicalX - half_, physicalY - half_, imageWidth_, imageHeight_);
164 surfaceNode_->SetBackgroundColor(SK_ColorTRANSPARENT); // USE_ROSEN_DRAWING
165 screenId_ = screenId;
166 surfaceNode_->AttachToDisplay(screenId);
167 surfaceNode_->SetRotation(0);
168 std::shared_ptr<Rosen::RectF> drawRect = std::make_shared<Rosen::RectF>(physicalX - half_, physicalY - half_,
169 imageWidth_, imageHeight_);
170 surfaceNode_->SetDrawRegion(drawRect);
171
172 rootNode_ = Rosen::RSRootNode::Create();
173 if (rootNode_ == nullptr) {
174 return;
175 }
176
177 rootNode_->SetBounds(0, 0, imageWidth_, imageHeight_);
178 rootNode_->SetFrame(0, 0, imageWidth_, imageHeight_);
179 rootNode_->SetBackgroundColor(SK_ColorTRANSPARENT); // USE_ROSEN_DRAWING
180 rootNode_->SetCornerRadius(1);
181 rootNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
182 rootNode_->SetRotation(0);
183
184 canvasNode_ = Rosen::RSCanvasNode::Create();
185 if (canvasNode_ == nullptr) {
186 HILOG_ERROR("create canvasNode_ fail");
187 return;
188 }
189
190 rootNode_->AddChild(canvasNode_, DEFAULT_VALUE);
191 canvasNode_->SetBounds(0, 0, imageWidth_, imageHeight_);
192 canvasNode_->SetFrame(0, 0, imageWidth_, imageHeight_);
193 canvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT); // USE_ROSEN_DRAWING
194 canvasNode_->SetCornerRadius(1);
195 canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
196 canvasNode_->SetRotation(0);
197
198 rsUiDirector_->SetRSSurfaceNode(surfaceNode_);
199 rsUiDirector_->SetRoot(rootNode_->GetId());
200 Rosen::RSTransaction::FlushImplicitTransaction();
201 }
202
203 #ifndef USE_ROSEN_DRAWING
DrawingProgressByOpenSource(int32_t physicalX,int32_t physicalY,int32_t angle)204 void AccessibilityCircleDrawingManager::DrawingProgressByOpenSource(int32_t physicalX, int32_t physicalY, int32_t angle)
205 {
206 HILOG_DEBUG();
207 auto canvas = static_cast<Rosen::RSRecordingCanvas *>(canvasNode_->BeginRecording(imageWidth_, imageHeight_));
208
209 // outer circle
210 SkPaint outCirclePaint;
211 outCirclePaint.setAntiAlias(true);
212 outCirclePaint.setAlphaf(OUT_CIRCLE_BACKGROUND_ALPHA);
213
214 std::vector<int32_t> outCircleColor = ParseColorString(OUT_CIRCLE_BACKGROUND_COLOR_TYPE);
215 outCirclePaint.setARGB(OUT_CIRCLE_BACKGROUND_ALPHA, outCircleColor[NUMBER_0], outCircleColor[NUMBER_1],
216 outCircleColor[NUMBER_2]);
217 outCirclePaint.setStyle(SkPaint::kFill_Style);
218 canvas->drawCircle(half_, half_, dispalyDensity_ * OUT_CIRCLE_RADIUS, outCirclePaint);
219
220 // center circle
221 SkPaint centerCirclePaint;
222 centerCirclePaint.setAntiAlias(true);
223 centerCirclePaint.setAlphaf(CENTER_CIRCLE_BACKGROUND_ALPHA);
224 std::vector<int32_t> centerCircleColor = ParseColorString(PROGRESS_COLOR_TYPE);
225 centerCirclePaint.setARGB(CENTER_CIRCLE_BACKGROUND_ALPHA, centerCircleColor[NUMBER_0],
226 centerCircleColor[NUMBER_1], centerCircleColor[NUMBER_2]);
227 centerCirclePaint.setStyle(SkPaint::kFill_Style);
228 canvas->drawCircle(half_, half_, dispalyDensity_ * CENTER_CIRCLE_RADIUS, centerCirclePaint);
229
230 // progress circle
231 SkPaint progressCirclePaint;
232 progressCirclePaint.setAntiAlias(true);
233 progressCirclePaint.setAlphaf(PROGRESS_BACKGROUND_ALPHA);
234 std::vector<int32_t> progressCircleColor = ParseColorString(PROGRESS_BACKGROUND_COLOR_TYPE);
235 progressCirclePaint.setARGB(PROGRESS_BACKGROUND_ALPHA, progressCircleColor[NUMBER_0],
236 progressCircleColor[NUMBER_1], progressCircleColor[NUMBER_2]);
237 progressCirclePaint.setStrokeWidth(PROGRESS_STROKE_WIDTH * dispalyDensity_);
238 progressCirclePaint.setStyle(SkPaint::kStroke_Style);
239 canvas->drawCircle(half_, half_, dispalyDensity_ * PROGRESS_RADIUS, progressCirclePaint);
240
241 // progress arc
242 SkPaint progressArcPaint;
243 progressArcPaint.setAntiAlias(true);
244 progressArcPaint.setAlphaf(PROGRESS_BAR_BACKGROUND_ALPHA);
245 std::vector<int32_t> progressArcColor = ParseColorString(PROGRESS_COLOR_TYPE);
246 progressArcPaint.setARGB(PROGRESS_BAR_BACKGROUND_ALPHA, progressArcColor[NUMBER_0],
247 progressArcColor[NUMBER_1], progressArcColor[NUMBER_2]);
248 progressArcPaint.setStrokeWidth(PROGRESS_STROKE_WIDTH * dispalyDensity_);
249 progressArcPaint.setStyle(SkPaint::kStroke_Style);
250
251 SkRect arcRect = SkRect::MakeLTRB(half_ - dispalyDensity_ * PROGRESS_RADIUS,
252 half_ - dispalyDensity_ * PROGRESS_RADIUS,
253 half_ + dispalyDensity_ * PROGRESS_RADIUS,
254 half_ + dispalyDensity_ * PROGRESS_RADIUS);
255 canvas->drawArc(arcRect, START_ANGLE, angle, false, progressArcPaint);
256
257 canvasNode_->FinishRecording();
258 Rosen::RSTransaction::FlushImplicitTransaction();
259 }
260 #else
DrawingProgressByRosenDrawing(int32_t physicalX,int32_t physicalY,int32_t angle)261 void AccessibilityCircleDrawingManager::DrawingProgressByRosenDrawing(int32_t physicalX, int32_t physicalY,
262 int32_t angle)
263 {
264 HILOG_DEBUG();
265 auto canvas = canvasNode_->BeginRecording(imageWidth_, imageHeight_);
266
267 // outer circle
268 Rosen::Drawing::Brush outCircleBrush;
269 outCircleBrush.SetAntiAlias(true);
270 outCircleBrush.SetAlphaF(OUT_CIRCLE_BACKGROUND_ALPHA);
271 std::vector<int32_t> outCircleColor = ParseColorString(OUT_CIRCLE_BACKGROUND_COLOR_TYPE);
272 outCircleBrush.SetARGB(OUT_CIRCLE_BACKGROUND_ALPHA, outCircleColor[NUMBER_0], outCircleColor[NUMBER_1],
273 outCircleColor[NUMBER_2]);
274
275 canvas->AttachBrush(outCircleBrush);
276 canvas->DrawCircle(Rosen::Drawing::Point(half_, half_), dispalyDensity_ * OUT_CIRCLE_RADIUS);
277 canvas->DetachBrush();
278
279 // center circle
280 Rosen::Drawing::Brush centerCircleBrush;
281 centerCircleBrush.SetAntiAlias(true);
282 centerCircleBrush.SetAlphaF(CENTER_CIRCLE_BACKGROUND_ALPHA);
283 std::vector<int32_t> centerCircleColor = ParseColorString(PROGRESS_COLOR_TYPE);
284 centerCircleBrush.SetARGB(CENTER_CIRCLE_BACKGROUND_ALPHA, centerCircleColor[NUMBER_0],
285 centerCircleColor[NUMBER_1], centerCircleColor[NUMBER_2]);
286
287 canvas->AttachBrush(centerCircleBrush);
288 canvas->DrawCircle(Rosen::Drawing::Point(half_, half_), dispalyDensity_ * CENTER_CIRCLE_RADIUS);
289 canvas->DetachBrush();
290
291 // progress circle
292 Rosen::Drawing::Pen progressPen;
293 progressPen.SetAntiAlias(true);
294 progressPen.SetAlphaF(PROGRESS_BACKGROUND_ALPHA);
295 std::vector<int32_t> progressCircleColor = ParseColorString(PROGRESS_BACKGROUND_COLOR_TYPE);
296 progressPen.SetARGB(PROGRESS_BACKGROUND_ALPHA, progressCircleColor[NUMBER_0],
297 progressCircleColor[NUMBER_1], progressCircleColor[NUMBER_2]);
298 progressPen.SetWidth(PROGRESS_STROKE_WIDTH * dispalyDensity_);
299
300 canvas->AttachPen(progressPen);
301 canvas->DrawCircle(Rosen::Drawing::Point(half_, half_), dispalyDensity_ * PROGRESS_RADIUS);
302 canvas->DetachPen();
303
304 // progress arc
305 Rosen::Drawing::Pen progressArcPen;
306 progressArcPen.SetAntiAlias(true);
307 progressArcPen.SetAlphaF(PROGRESS_BAR_BACKGROUND_ALPHA);
308 std::vector<int32_t> progressArcColor = ParseColorString(PROGRESS_COLOR_TYPE);
309 progressArcPen.SetARGB(PROGRESS_BAR_BACKGROUND_ALPHA, progressArcColor[NUMBER_0],
310 progressArcColor[NUMBER_1], progressArcColor[NUMBER_2]);
311 progressArcPen.SetWidth(PROGRESS_STROKE_WIDTH * dispalyDensity_);
312
313 Rosen::Drawing::Rect rect(half_ - dispalyDensity_ * PROGRESS_RADIUS,
314 half_ - dispalyDensity_ * PROGRESS_RADIUS,
315 half_ + dispalyDensity_ * PROGRESS_RADIUS,
316 half_ + dispalyDensity_ * PROGRESS_RADIUS);
317 canvas->AttachPen(progressArcPen);
318 canvas->DrawArc(rect, START_ANGLE, angle);
319 canvas->DetachPen();
320
321 canvasNode_->FinishRecording();
322 Rosen::RSTransaction::FlushImplicitTransaction();
323 }
324 #endif
325
DrawingProgress(int32_t physicalX,int32_t physicalY,int32_t angle)326 void AccessibilityCircleDrawingManager::DrawingProgress(int32_t physicalX, int32_t physicalY, int32_t angle)
327 {
328 #ifndef USE_ROSEN_DRAWING
329 DrawingProgressByOpenSource(physicalX, physicalY, angle);
330 #else
331 DrawingProgressByRosenDrawing(physicalX, physicalY, angle);
332 #endif
333 }
334
SetPointerLocation(int32_t physicalX,int32_t physicalY,uint64_t screenId)335 void AccessibilityCircleDrawingManager::SetPointerLocation(int32_t physicalX, int32_t physicalY, uint64_t screenId)
336 {
337 HILOG_DEBUG("Pointer window move, x:%{public}d, y:%{public}d", physicalX, physicalY);
338 if (surfaceNode_ != nullptr) {
339 surfaceNode_->SetBounds(physicalX - half_,
340 physicalY - half_,
341 surfaceNode_->GetStagingProperties().GetBounds().z_,
342 surfaceNode_->GetStagingProperties().GetBounds().w_);
343 screenId_ = screenId;
344 surfaceNode_->AttachToDisplay(screenId);
345 Rosen::RSTransaction::FlushImplicitTransaction();
346 }
347 }
348
DrawPointer(int32_t physicalX,int32_t physicalY,int32_t angle,uint64_t screenId)349 void AccessibilityCircleDrawingManager::DrawPointer(int32_t physicalX, int32_t physicalY, int32_t angle,
350 uint64_t screenId)
351 {
352 HILOG_DEBUG();
353 if (surfaceNode_ != nullptr) {
354 SetPointerLocation(physicalX, physicalY, screenId);
355 DrawingProgress(physicalX, physicalY, angle);
356 UpdatePointerVisible(true);
357 HILOG_DEBUG("surfaceNode_ is existed");
358 return;
359 }
360
361 CreatePointerWindow(physicalX, physicalY, screenId);
362 if (surfaceNode_ == nullptr) {
363 HILOG_ERROR("surfaceNode_ is nullptr");
364 return;
365 }
366
367 DrawingProgress(physicalX, physicalY, angle);
368 UpdatePointerVisible(true);
369 }
370
ParseStringToInteger(const std::string & color)371 int32_t AccessibilityCircleDrawingManager::ParseStringToInteger(const std::string& color)
372 {
373 int32_t val = 0;
374 int32_t base = 1;
375 for (int32_t index = static_cast<int32_t>(color.size() - 1); index >= 0; index--) {
376 if (color[index] >= CHAR_0 && color[index] <= CHAR_9) {
377 val += base * static_cast<int32_t>(color[index] - CHAR_0);
378 }
379
380 if (color[index] == CHAR_A) {
381 val += base * static_cast<int32_t>(color[index] - CHAR_A + DECIMAL);
382 }
383
384 if (color[index] == CHAR_B) {
385 val += base * static_cast<int32_t>(color[index] - CHAR_A + DECIMAL);
386 }
387
388 if (color[index] == CHAR_C) {
389 val += base * static_cast<int32_t>(color[index] - CHAR_A + DECIMAL);
390 }
391
392 if (color[index] == CHAR_D) {
393 val += base * static_cast<int32_t>(color[index] - CHAR_A + DECIMAL);
394 }
395
396 if (color[index] == CHAR_E) {
397 val += base * static_cast<int32_t>(color[index] - CHAR_A + DECIMAL);
398 }
399
400 if (color[index] == CHAR_F) {
401 val += base * static_cast<int32_t>(color[index] - CHAR_A + DECIMAL);
402 }
403
404 base = base * HEXADECIMAL;
405 }
406
407 return val;
408 }
409
ParseColorString(const std::string & color)410 std::vector<int32_t> AccessibilityCircleDrawingManager::ParseColorString(const std::string& color)
411 {
412 std::string r = color.substr(RED_START_INDEX, COLOR_STRING_LENGTH);
413 std::string g = color.substr(GREEN_START_INDEX, COLOR_STRING_LENGTH);
414 std::string b = color.substr(BLUE_START_INDEX, COLOR_STRING_LENGTH);
415
416 int32_t rValue = ParseStringToInteger(r);
417 int32_t gValue = ParseStringToInteger(g);
418 int32_t bValue = ParseStringToInteger(b);
419
420 std::vector<int32_t> rgbValue = {rValue, gValue, bValue};
421 return rgbValue;
422 }
423 } // namespace Accessibility
424 } // namespace OHOS