• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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