• 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 #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