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