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