1 /*
2  * Copyright (c) 2024 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 "knuckle_drawing_manager.h"
17 
18 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
19 #include "animation/rs_particle_params.h"
20 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
21 #include "image/bitmap.h"
22 #include "image_source.h"
23 #include "image_type.h"
24 #include "image_utils.h"
25 #ifndef USE_ROSEN_DRAWING
26 #include "pipeline/rs_recording_canvas.h"
27 #else
28 #include "ui/rs_canvas_drawing_node.h"
29 #endif // USE_ROSEN_DRAWING
30 
31 #include "define_multimodal.h"
32 #include "i_multimodal_input_connect.h"
33 #include "mmi_log.h"
34 #include "parameters.h"
35 #include "setting_datashare.h"
36 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
37 #include "timer_manager.h"
38 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
39 #include "touch_drawing_manager.h"
40 
41 #undef MMI_LOG_TAG
42 #define MMI_LOG_TAG "KnuckleDrawingManager"
43 
44 namespace OHOS {
45 namespace MMI {
46 namespace {
47 constexpr int32_t DEFAULT_VALUE { -1 };
48 constexpr int32_t MAX_POINTER_NUM { 5 };
49 constexpr int32_t MID_POINT { 2 };
50 constexpr int32_t POINT_INDEX0 { 0 };
51 constexpr int32_t POINT_INDEX1 { 1 };
52 constexpr int32_t POINT_INDEX2 { 2 };
53 constexpr int32_t POINT_INDEX3 { 3 };
54 constexpr int32_t POINT_INDEX4 { 4 };
55 constexpr int32_t PAINT_STROKE_WIDTH { 10 };
56 constexpr int32_t PAINT_PATH_RADIUS { 10 };
57 constexpr int64_t DOUBLE_CLICK_INTERVAL_TIME_SLOW { 450000 };
58 constexpr int64_t WAIT_DOUBLE_CLICK_INTERVAL_TIME { 100000 };
59 constexpr float DOUBLE_CLICK_DISTANCE_LONG_CONFIG { 96.0f };
60 constexpr float VPR_CONFIG { 3.25f };
61 constexpr int32_t POW_SQUARE { 2 };
62 constexpr int32_t ROTATION_ANGLE_0 { 0 };
63 constexpr int32_t ROTATION_ANGLE_90 { 90 };
64 constexpr int32_t ROTATION_ANGLE_180 { 180 };
65 constexpr int32_t ROTATION_ANGLE_270 { 270 };
66 constexpr uint64_t FOLD_SCREEN_MAIN_ID { 5 };
67 const int32_t ROTATE_POLICY = system::GetIntParameter("const.window.device.rotate_policy", 0);
68 const std::string FOLDABLE = system::GetParameter("const.window.foldabledevice.rotate_policy", "");
69 constexpr int32_t WINDOW_ROTATE { 0 };
70 constexpr int32_t SCREEN_ROTATE { 1 };
71 constexpr int32_t FOLDABLE_DEVICE { 2 };
72 constexpr char FOLDABLE_ROTATE  { '0' };
73 constexpr int32_t SUBSCRIPT_TWO { 2 };
74 constexpr int32_t SUBSCRIPT_ZERO { 0 };
75 constexpr std::string_view SCREEN_READING { "accessibility_screenreader_enabled" };
76 constexpr std::string_view SCREEN_READ_ENABLE { "1" };
77 constexpr int32_t POINTER_NUMBER_TO_DRAW { 10 };
78 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
79 constexpr int64_t PARTICLE_LIFE_TIME { 700 };
80 constexpr int32_t PARTICLE_COUNT { -1 };
81 constexpr int32_t DEFAULT_EMIT_RATE { 0 };
82 constexpr int32_t EMIT_RATE { 400 };
83 constexpr int32_t PATH_SIZE_EIGHT { 8 };
84 constexpr int32_t MAX_PATH_SIZE { 50 };
85 constexpr int32_t MAX_PATH_LENGTH { 500 };
86 constexpr float PARTICLE_RADIUS { 5.0f };
87 constexpr float DEFAULT_PARTICLE_POSITION_X { 0.0f };
88 constexpr float DEFAULT_PARTICLE_POSITION_Y { 0.0f };
89 constexpr float DEFAULT_EMIT_SIZE_RANGE_BEGIN { 0.0f };
90 constexpr float DEFAULT_EMIT_SIZE_RANGE_END { 0.0f };
91 constexpr float EMIT_SIZE_RANGE_BEGIN { 80.0f };
92 constexpr float EMIT_SIZE_RANGE_END { 80.0f };
93 constexpr float EMIT_VELOCITY_VALUE_RANGE_BEGIN { 50.0f };
94 constexpr float EMIT_VELOCITY_VALUE_RANGE_END { 100.0f };
95 constexpr float EMIT_VELOCITY_ANGLE_RANGE_BEGIN { -180.0f };
96 constexpr float EMIT_VELOCITY_ANGLE_RANGE_END { 180.0f };
97 constexpr float EMIT_OPACITY_RANGE_BEGIN { 0.3f };
98 constexpr float EMIT_OPACITY_RANGE_END { 1.0f };
99 constexpr float EMIT_SCALE_RANGE_BEGIN { 0.3f };
100 constexpr float EMIT_SCALE_RANGE_END { 1.0f };
101 constexpr float EMIT_SCALE_CHANGE_RANGE_BEGIN { 1.0f };
102 constexpr float EMIT_SCALE_CHANGE_RANGE_END { 0.0f };
103 constexpr float SCALE_CHANGE_VELOCITY_RANGE_BEGIN { -1.0f };
104 constexpr float SCALE_CHANGE_VELOCITY_RANGE_END { -1.0f };
105 constexpr int32_t SCALE_CHANGE_START_MILLIS { 0 };
106 constexpr int32_t SCALE_CHANGE_END_MILLIS { 700 };
107 constexpr float ALPHA_RANGE_BEGIN { 1.0f };
108 constexpr float ALPHA_RANGE_END { 0.0f };
109 constexpr float EMIT_RADIUS { 40.0f };
110 constexpr float TRACK_FILTER_SCALAR { 20.0f };
111 constexpr int32_t TRACK_PATH_LENGTH_400 { 400 };
112 constexpr int32_t TRACK_PATH_LENGTH_500 { 500 };
113 constexpr int32_t TRACK_PATH_LENGTH_900 { 900 };
114 constexpr int32_t TRACK_PATH_LENGTH_1000 { 1000 };
115 constexpr int32_t TRACK_PATH_LENGTH_1400 { 1400 };
116 constexpr int32_t TRACK_PATH_LENGTH_1500 { 1500 };
117 constexpr int32_t TRACK_PATH_LENGTH_1900 { 1900 };
118 constexpr int32_t TRACK_PATH_LENGTH_2000 { 2000 };
119 constexpr uint32_t TRACK_COLOR_BLUE { 0xFF1ED0EE };
120 constexpr uint32_t TRACK_COLOR_BLUE_R { 0x1E };
121 constexpr uint32_t TRACK_COLOR_BLUE_G { 0xD0 };
122 constexpr uint32_t TRACK_COLOR_BLUE_B { 0xEE };
123 constexpr uint32_t TRACK_COLOR_PINK { 0xFFFF42D2 };
124 constexpr uint32_t TRACK_COLOR_PINK_R { 0xFF };
125 constexpr uint32_t TRACK_COLOR_PINK_G { 0x42 };
126 constexpr uint32_t TRACK_COLOR_PINK_B { 0xD2 };
127 constexpr uint32_t TRACK_COLOR_ORANGE_RED { 0xFFFF7B47 };
128 constexpr uint32_t TRACK_COLOR_ORANGE_RED_R { 0xFF };
129 constexpr uint32_t TRACK_COLOR_ORANGE_RED_G { 0x7B };
130 constexpr uint32_t TRACK_COLOR_ORANGE_RED_B { 0x47 };
131 constexpr uint32_t TRACK_COLOR_YELLOW { 0xFFFFC628 };
132 constexpr uint32_t TRACK_COLOR_YELLOW_R { 0xFF };
133 constexpr uint32_t TRACK_COLOR_YELLOW_G { 0xC6 };
134 constexpr uint32_t TRACK_COLOR_YELLOW_B { 0x28 };
135 constexpr uint32_t ALPHA_ZERO { 0xFF };
136 constexpr float TRACK_WIDTH_TEN { 10.0f };
137 constexpr float TRACK_WIDTH_THIRTY { 30.0f };
138 constexpr float COLOR_TRANSITIONS_LENGTH { 400.0f };
139 constexpr int32_t PROTOCOL_DURATION { 200 };
140 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
141 } // namespace
142 
KnuckleDrawingManager()143 KnuckleDrawingManager::KnuckleDrawingManager()
144 {
145 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
146     paint_.SetColor(Rosen::Drawing::Color::COLOR_WHITE);
147 #else
148     paint_.SetColor(Rosen::Drawing::Color::COLOR_CYAN);
149 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
150     paint_.SetAntiAlias(true);
151     float outerCircleTransparency = 1.0f;
152     paint_.SetAlphaF(outerCircleTransparency);
153     paint_.SetWidth(PAINT_STROKE_WIDTH);
154     paint_.SetStyle(Rosen::Drawing::Paint::PaintStyle::PAINT_STROKE);
155     paint_.SetJoinStyle(Rosen::Drawing::Pen::JoinStyle::ROUND_JOIN);
156     paint_.SetCapStyle(Rosen::Drawing::Pen::CapStyle::ROUND_CAP);
157     paint_.SetPathEffect(Rosen::Drawing::PathEffect::CreateCornerPathEffect(PAINT_PATH_RADIUS));
158     displayInfo_.x = 0;
159     displayInfo_.y = 0;
160     displayInfo_.id = 0;
161     displayInfo_.dpi = 0;
162     displayInfo_.width = 0;
163     displayInfo_.height = 0;
164     displayInfo_.direction = Direction::DIRECTION0;
165     displayInfo_.displayDirection = Direction::DIRECTION0;
166 }
167 
KnuckleDrawHandler(std::shared_ptr<PointerEvent> touchEvent)168 void KnuckleDrawingManager::KnuckleDrawHandler(std::shared_ptr<PointerEvent> touchEvent)
169 {
170     CALL_DEBUG_ENTER;
171     CHKPV(touchEvent);
172     if (!IsSingleKnuckle(touchEvent)) {
173         return;
174     }
175     CreateObserver();
176     int32_t touchAction = touchEvent->GetPointerAction();
177     if (IsValidAction(touchAction) && IsSingleKnuckleDoubleClick(touchEvent)) {
178         int32_t displayId = touchEvent->GetTargetDisplayId();
179         CreateTouchWindow(displayId);
180         StartTouchDraw(touchEvent);
181     }
182 }
183 
IsSingleKnuckle(std::shared_ptr<PointerEvent> touchEvent)184 bool KnuckleDrawingManager::IsSingleKnuckle(std::shared_ptr<PointerEvent> touchEvent)
185 {
186     CALL_DEBUG_ENTER;
187     CHKPF(touchEvent);
188     int32_t id = touchEvent->GetPointerId();
189     PointerEvent::PointerItem item;
190     touchEvent->GetPointerItem(id, item);
191     if (item.GetToolType() != PointerEvent::TOOL_TYPE_KNUCKLE ||
192         touchEvent->GetPointerIds().size() != 1 || isRotate_) {
193         MMI_HILOGD("Touch tool type is:%{public}d", item.GetToolType());
194         if (!pointerInfos_.empty()) {
195             DestoryWindow();
196         } else if (isRotate_) {
197             isRotate_ = false;
198             if (item.GetToolType() == PointerEvent::TOOL_TYPE_KNUCKLE) {
199                 return true;
200             }
201         }
202         return false;
203     }
204     MMI_HILOGD("Touch tool type is single knuckle");
205     return true;
206 }
207 
IsSingleKnuckleDoubleClick(std::shared_ptr<PointerEvent> touchEvent)208 bool KnuckleDrawingManager::IsSingleKnuckleDoubleClick(std::shared_ptr<PointerEvent> touchEvent)
209 {
210     CALL_DEBUG_ENTER;
211     CHKPF(touchEvent);
212     int32_t touchAction = touchEvent->GetPointerAction();
213     if (touchAction == PointerEvent::POINTER_ACTION_DOWN) {
214         pointerNum_ = 0;
215         firstDownTime_ = touchEvent->GetActionTime();
216         int64_t intervalTime = touchEvent->GetActionTime() - lastUpTime_;
217         bool isTimeIntervalReady = intervalTime > 0 && intervalTime <= DOUBLE_CLICK_INTERVAL_TIME_SLOW;
218         int32_t id = touchEvent->GetPointerId();
219         PointerEvent::PointerItem pointerItem;
220         touchEvent->GetPointerItem(id, pointerItem);
221         auto displayXY = TOUCH_DRAWING_MGR->CalcDrawCoordinate(displayInfo_, pointerItem);
222         float downToPrevDownDistance = static_cast<float>(sqrt(pow(lastDownPointer_.x - displayXY.first, POW_SQUARE) +
223             pow(lastDownPointer_.y - displayXY.second, POW_SQUARE)));
224         bool isDistanceReady = downToPrevDownDistance < DOUBLE_CLICK_DISTANCE_LONG_CONFIG * POW_SQUARE;
225         if (isTimeIntervalReady && isDistanceReady) {
226             return false;
227         }
228         lastDownPointer_.x = displayXY.first;
229         lastDownPointer_.y = displayXY.second;
230     } else if (touchAction == PointerEvent::POINTER_ACTION_UP) {
231         lastUpTime_ = touchEvent->GetActionTime();
232     }
233     return true;
234 }
235 
IsValidAction(const int32_t action)236 bool KnuckleDrawingManager::IsValidAction(const int32_t action)
237 {
238     CALL_DEBUG_ENTER;
239     if (screenReadState_.state == SCREEN_READ_ENABLE) {
240         DestoryWindow();
241     }
242     if (action == PointerEvent::POINTER_ACTION_DOWN || action == PointerEvent::POINTER_ACTION_PULL_DOWN ||
243         (action == PointerEvent::POINTER_ACTION_MOVE && (!pointerInfos_.empty())) ||
244         (action == PointerEvent::POINTER_ACTION_PULL_MOVE && (!pointerInfos_.empty())) ||
245         action == PointerEvent::POINTER_ACTION_UP || action == PointerEvent::POINTER_ACTION_PULL_UP) {
246         return true;
247     }
248     MMI_HILOGE("Action is not down or move or up, action:%{public}d", action);
249     return false;
250 }
251 
UpdateDisplayInfo(const DisplayInfo & displayInfo)252 void KnuckleDrawingManager::UpdateDisplayInfo(const DisplayInfo& displayInfo)
253 {
254     CALL_DEBUG_ENTER;
255     if (displayInfo_.direction != displayInfo.direction) {
256         MMI_HILOGD("DisplayInfo direction change");
257         isRotate_ = true;
258     }
259     scaleW_ = displayInfo.width > displayInfo.height ? displayInfo.width : displayInfo.height;
260     scaleH_ = displayInfo.width > displayInfo.height ? displayInfo.width : displayInfo.height;
261     displayInfo_ = displayInfo;
262 }
263 
StartTouchDraw(std::shared_ptr<PointerEvent> touchEvent)264 void KnuckleDrawingManager::StartTouchDraw(std::shared_ptr<PointerEvent> touchEvent)
265 {
266     CALL_DEBUG_ENTER;
267     CHKPV(touchEvent);
268     int32_t ret = DrawGraphic(touchEvent);
269     if (ret != RET_OK) {
270         MMI_HILOGD("Can't get enough pointers to draw");
271         return;
272     }
273     Rosen::RSTransaction::FlushImplicitTransaction();
274 }
275 
RotationCanvasNode(std::shared_ptr<Rosen::RSCanvasNode> canvasNode,const DisplayInfo & displayInfo)276 void KnuckleDrawingManager::RotationCanvasNode(
277     std::shared_ptr<Rosen::RSCanvasNode> canvasNode, const DisplayInfo& displayInfo)
278 {
279     CALL_DEBUG_ENTER;
280     CHKPV(canvasNode);
281     if (displayInfo.direction == Direction::DIRECTION90) {
282         canvasNode->SetRotation(ROTATION_ANGLE_270);
283         canvasNode->SetTranslateX(0);
284     } else if (displayInfo.direction == Direction::DIRECTION270) {
285         canvasNode->SetRotation(ROTATION_ANGLE_90);
286         canvasNode->SetTranslateX(-std::fabs(displayInfo.width - displayInfo.height));
287     } else if (displayInfo.direction == Direction::DIRECTION180) {
288         canvasNode->SetRotation(ROTATION_ANGLE_180);
289         canvasNode->SetTranslateX(-std::fabs(displayInfo.width - displayInfo.height));
290     } else {
291         canvasNode->SetRotation(ROTATION_ANGLE_0);
292         canvasNode->SetTranslateX(0);
293     }
294     canvasNode->SetTranslateY(0);
295 }
296 
CheckRotatePolicy(const DisplayInfo & displayInfo)297 bool KnuckleDrawingManager::CheckRotatePolicy(const DisplayInfo& displayInfo)
298 {
299     CALL_DEBUG_ENTER;
300     bool isNeedRotate = false;
301     switch (ROTATE_POLICY) {
302         case WINDOW_ROTATE:
303             isNeedRotate = true;
304             break;
305         case SCREEN_ROTATE:
306             break;
307         case FOLDABLE_DEVICE: {
308             MMI_HILOGI("FOLDABLE:%{public}s", FOLDABLE.c_str());
309             if ((displayInfo.displayMode == DisplayMode::MAIN && FOLDABLE[SUBSCRIPT_ZERO] == FOLDABLE_ROTATE) ||
310                 (displayInfo.displayMode == DisplayMode::FULL && FOLDABLE[SUBSCRIPT_TWO] == FOLDABLE_ROTATE)) {
311                 isNeedRotate = true;
312             }
313             break;
314         }
315         default:
316             MMI_HILOGW("Unknown ROTATE_POLICY:%{public}d", ROTATE_POLICY);
317             break;
318     }
319     return isNeedRotate;
320 }
321 
322 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
InitParticleEmitter()323 void KnuckleDrawingManager::InitParticleEmitter()
324 {
325     CALL_DEBUG_ENTER;
326     Rosen::Vector2f position = {DEFAULT_PARTICLE_POSITION_X, DEFAULT_PARTICLE_POSITION_Y};
327     Rosen::Vector2f emitSize = {DEFAULT_EMIT_SIZE_RANGE_BEGIN, DEFAULT_EMIT_SIZE_RANGE_END};
328     Rosen::Range<int64_t> lifeTime = {PARTICLE_LIFE_TIME, PARTICLE_LIFE_TIME};
329     std::shared_ptr<Rosen::RSImage> image = std::make_shared<Rosen::RSImage>();
330     Rosen::EmitterConfig emitterConfig(
331         DEFAULT_EMIT_RATE, Rosen::ShapeType::CIRCLE, position, emitSize, PARTICLE_COUNT, lifeTime,
332         Rosen::ParticleType::POINTS, PARTICLE_RADIUS, image, Rosen::Vector2f());
333 
334     Rosen::Range<float> velocityValue = {EMIT_VELOCITY_VALUE_RANGE_BEGIN, EMIT_VELOCITY_VALUE_RANGE_END};
335     Rosen::Range<float> velocityAngle = {EMIT_VELOCITY_ANGLE_RANGE_BEGIN, EMIT_VELOCITY_ANGLE_RANGE_END};
336     Rosen::ParticleVelocity velocity(velocityValue, velocityAngle);
337 
338     std::vector<Rosen::Change<Rosen::RSColor>> valColorChangeOverLife;
339     Rosen::RSColor rsColorRangeBegin(Rosen::Drawing::Color::COLOR_WHITE);
340     Rosen::RSColor rsColorRangeEnd(Rosen::Drawing::Color::COLOR_WHITE);
341     Rosen::Range<Rosen::RSColor> colorVal = {rsColorRangeBegin, rsColorRangeEnd};
342     Rosen::ParticleColorParaType color(
343         colorVal, Rosen::DistributionType::UNIFORM, Rosen::ParticleUpdator::NONE, Rosen::Range<float>(),
344         Rosen::Range<float>(), Rosen::Range<float>(), Rosen::Range<float>(), valColorChangeOverLife);
345 
346     std::vector<Rosen::Change<float>> opacityChangeOverLifes;
347     Rosen::Range<float> opacityVal = {EMIT_OPACITY_RANGE_BEGIN, EMIT_OPACITY_RANGE_END};
348     Rosen::ParticleParaType<float> opacity(
349         opacityVal, Rosen::ParticleUpdator::NONE, Rosen::Range<float>(), opacityChangeOverLifes);
350 
351     Rosen::RSAnimationTimingCurve rSAnimationTimingCurve(Rosen::RSAnimationTimingCurve::LINEAR);
352     Rosen::Change<float> scaleChange
353         (EMIT_SCALE_CHANGE_RANGE_BEGIN, EMIT_SCALE_CHANGE_RANGE_END, SCALE_CHANGE_START_MILLIS, SCALE_CHANGE_END_MILLIS,
354         rSAnimationTimingCurve);
355     std::vector<Rosen::Change<float>> scaleChangeOverLifes;
356     scaleChangeOverLifes.emplace_back(scaleChange);
357     Rosen::Range<float> scaleVal = {EMIT_SCALE_RANGE_BEGIN, EMIT_SCALE_RANGE_END};
358     Rosen::Range<float> scaleChangeVelocity = {SCALE_CHANGE_VELOCITY_RANGE_BEGIN, SCALE_CHANGE_VELOCITY_RANGE_END};
359     Rosen::ParticleParaType<float> scale(
360         scaleVal, Rosen::ParticleUpdator::CURVE, scaleChangeVelocity, scaleChangeOverLifes);
361 
362     Rosen::ParticleAcceleration acceleration;
363     Rosen::ParticleParaType<float> spin;
364 
365     Rosen::ParticleParams params(emitterConfig, velocity, acceleration, color, opacity, scale, spin);
366     std::vector<Rosen::ParticleParams> particleParams;
367     particleParams.push_back(params);
368     CHKPV(brushCanvasNode_);
369     brushCanvasNode_->SetParticleParams(particleParams);
370     isNeedInitParticleEmitter_ = false;
371 }
372 
CreateTouchWindow(const int32_t displayId)373 void KnuckleDrawingManager::CreateTouchWindow(const int32_t displayId)
374 {
375     CALL_DEBUG_ENTER;
376     if (surfaceNode_ != nullptr) {
377         MMI_HILOGD("surfaceNode_ is already exist");
378         return;
379     }
380     Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
381     surfaceNodeConfig.SurfaceNodeName = "knuckle window";
382     Rosen::RSSurfaceNodeType surfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
383     surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
384 
385     CHKPV(surfaceNode_);
386     surfaceNode_->SetSkipLayer(true);
387     surfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT_FILL);
388     surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
389     surfaceNode_->SetBounds(0, 0, scaleW_, scaleH_);
390     surfaceNode_->SetFrame(0, 0, scaleW_, scaleH_);
391 
392 #ifndef USE_ROSEN_DRAWING
393     surfaceNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
394 #else
395     surfaceNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
396 #endif // USE_ROSEN_DRAWING
397 
398     screenId_ = static_cast<uint64_t>(displayId);
399     surfaceNode_->SetRotation(0);
400     CreateBrushWorkCanvasNode();
401     CreateTrackCanvasNode();
402     surfaceNode_->AddChild(trackCanvasNode_, DEFAULT_VALUE);
403     surfaceNode_->AddChild(brushCanvasNode_, DEFAULT_VALUE);
404     if (displayInfo_.displayMode == DisplayMode::MAIN) {
405         screenId_ = FOLD_SCREEN_MAIN_ID;
406     }
407     MMI_HILOGI("screenId_: %{public}" PRIu64, screenId_);
408     surfaceNode_->AttachToDisplay(screenId_);
409     if (CheckRotatePolicy(displayInfo_)) {
410         RotationCanvasNode(brushCanvasNode_, displayInfo_);
411         RotationCanvasNode(trackCanvasNode_, displayInfo_);
412     }
413     brushCanvasNode_->ResetSurface(scaleW_, scaleH_);
414     trackCanvasNode_->ResetSurface(scaleW_, scaleH_);
415     Rosen::RSTransaction::FlushImplicitTransaction();
416 }
417 #else
CreateTouchWindow(const int32_t displayId)418 void KnuckleDrawingManager::CreateTouchWindow(const int32_t displayId)
419 {
420     CALL_DEBUG_ENTER;
421     if (surfaceNode_ != nullptr) {
422         MMI_HILOGD("surfaceNode_ is already exist");
423         return;
424     }
425     Rosen::RSSurfaceNodeConfig surfaceNodeConfig;
426     surfaceNodeConfig.SurfaceNodeName = "knuckle window";
427     Rosen::RSSurfaceNodeType surfaceNodeType = Rosen::RSSurfaceNodeType::SELF_DRAWING_WINDOW_NODE;
428     surfaceNode_ = Rosen::RSSurfaceNode::Create(surfaceNodeConfig, surfaceNodeType);
429 
430     CHKPV(surfaceNode_);
431     surfaceNode_->SetSkipLayer(true);
432     surfaceNode_->SetFrameGravity(Rosen::Gravity::RESIZE_ASPECT_FILL);
433     surfaceNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
434     surfaceNode_->SetBounds(0, 0, scaleW_, scaleH_);
435     surfaceNode_->SetFrame(0, 0, scaleW_, scaleH_);
436 
437 #ifndef USE_ROSEN_DRAWING
438     surfaceNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
439 #else
440     surfaceNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
441 #endif // USE_ROSEN_DRAWING
442 
443     screenId_ = static_cast<uint64_t>(displayId);
444     surfaceNode_->SetRotation(0);
445     CreateCanvasNode();
446     surfaceNode_->AddChild(canvasNode_, DEFAULT_VALUE);
447     if (displayInfo_.displayMode == DisplayMode::MAIN) {
448         screenId_ = FOLD_SCREEN_MAIN_ID;
449     }
450     MMI_HILOGI("screenId_: %{public}" PRIu64, screenId_);
451     surfaceNode_->AttachToDisplay(screenId_);
452     if (CheckRotatePolicy(displayInfo_)) {
453         RotationCanvasNode(canvasNode_, displayInfo_);
454     }
455     canvasNode_->ResetSurface(scaleW_, scaleH_);
456     Rosen::RSTransaction::FlushImplicitTransaction();
457 }
458 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
459 
460 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
CreateBrushWorkCanvasNode()461 void KnuckleDrawingManager::CreateBrushWorkCanvasNode()
462 {
463     brushCanvasNode_ = Rosen::RSCanvasDrawingNode::Create();
464     CHKPV(brushCanvasNode_);
465     brushCanvasNode_->SetBounds(0, 0, scaleW_, scaleH_);
466     brushCanvasNode_->SetFrame(0, 0, scaleW_, scaleH_);
467 
468 #ifndef USE_ROSEN_DRAWING
469     brushCanvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
470 #else
471     brushCanvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
472 #endif // USE_ROSEN_DRAWING
473     brushCanvasNode_->SetCornerRadius(1);
474     brushCanvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
475     brushCanvasNode_->SetRotation(0);
476     brushCanvasNode_->SetAlpha(ALPHA_RANGE_BEGIN);
477 }
478 
CreateTrackCanvasNode()479 void KnuckleDrawingManager::CreateTrackCanvasNode()
480 {
481     trackCanvasNode_ = Rosen::RSCanvasDrawingNode::Create();
482     CHKPV(trackCanvasNode_);
483     trackCanvasNode_->SetBounds(0, 0, scaleW_, scaleH_);
484     trackCanvasNode_->SetFrame(0, 0, scaleW_, scaleH_);
485 
486 #ifndef USE_ROSEN_DRAWING
487     trackCanvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
488 #else
489     trackCanvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
490 #endif // USE_ROSEN_DRAWING
491     trackCanvasNode_->SetCornerRadius(1);
492     trackCanvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
493     trackCanvasNode_->SetRotation(0);
494     trackCanvasNode_->SetAlpha(ALPHA_RANGE_BEGIN);
495 }
496 #else
CreateCanvasNode()497 void KnuckleDrawingManager::CreateCanvasNode()
498 {
499     canvasNode_ = Rosen::RSCanvasDrawingNode::Create();
500     CHKPV(canvasNode_);
501     canvasNode_->SetBounds(0, 0, scaleW_, scaleH_);
502     canvasNode_->SetFrame(0, 0, scaleW_, scaleH_);
503 
504 #ifndef USE_ROSEN_DRAWING
505     canvasNode_->SetBackgroundColor(SK_ColorTRANSPARENT);
506 #else
507     canvasNode_->SetBackgroundColor(Rosen::Drawing::Color::COLOR_TRANSPARENT);
508 #endif // USE_ROSEN_DRAWING
509     canvasNode_->SetCornerRadius(1);
510     canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
511     canvasNode_->SetRotation(0);
512 }
513 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
514 
GetPointerPos(std::shared_ptr<PointerEvent> touchEvent)515 int32_t KnuckleDrawingManager::GetPointerPos(std::shared_ptr<PointerEvent> touchEvent)
516 {
517     CHKPR(touchEvent, RET_ERR);
518     if (touchEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_UP ||
519         touchEvent->GetPointerAction() == PointerEvent::POINTER_ACTION_CANCEL) {
520         isActionUp_ = true;
521         return RET_OK;
522     }
523     PointerInfo pointerInfo;
524     int32_t pointerId = touchEvent->GetPointerId();
525     PointerEvent::PointerItem pointerItem;
526     if (!touchEvent->GetPointerItem(pointerId, pointerItem)) {
527         MMI_HILOGE("Can't find pointer item, pointer:%{public}d", pointerId);
528         return RET_ERR;
529     }
530     auto displayXY = TOUCH_DRAWING_MGR->CalcDrawCoordinate(displayInfo_, pointerItem);
531     pointerInfo.x = displayXY.first;
532     pointerInfo.y = displayXY.second;
533     pointerInfos_.push_back(pointerInfo);
534     pointerNum_++;
535 
536     if (pointerInfos_.size() == MAX_POINTER_NUM) {
537         pointerInfos_[POINT_INDEX3].x = (pointerInfos_[POINT_INDEX2].x + pointerInfos_[POINT_INDEX4].x) / MID_POINT;
538         pointerInfos_[POINT_INDEX3].y = (pointerInfos_[POINT_INDEX2].y + pointerInfos_[POINT_INDEX4].y) / MID_POINT;
539     } else {
540         MMI_HILOGD("Can't get enough pointers to draw");
541         return RET_ERR;
542     }
543     return RET_OK;
544 }
545 
546 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
UpdateEmitter()547 void KnuckleDrawingManager::UpdateEmitter()
548 {
549     CALL_DEBUG_ENTER;
550     CHKPV(brushCanvasNode_);
551     std::optional<Rosen::Vector2f> position = std::nullopt;
552     position = {pointerInfos_[POINT_INDEX1].x - EMIT_RADIUS, pointerInfos_[POINT_INDEX1].y - EMIT_RADIUS};
553     std::optional<Rosen::Vector2f> emitSize = std::nullopt;
554     emitSize = {EMIT_SIZE_RANGE_BEGIN, EMIT_SIZE_RANGE_END};
555     std::optional<int32_t> emitRate = std::nullopt;
556     emitRate = EMIT_RATE;
557     auto updater = std::make_shared<Rosen::EmitterUpdater>(
558         0, position, emitSize, emitRate);
559     std::vector<std::shared_ptr<Rosen::EmitterUpdater>> paras;
560     paras.push_back(updater);
561     brushCanvasNode_->SetEmitterUpdater(paras);
562 }
563 
GetDeltaColor(uint32_t deltaSource,uint32_t deltaTarget)564 uint32_t KnuckleDrawingManager::GetDeltaColor(uint32_t deltaSource, uint32_t deltaTarget)
565 {
566     CALL_DEBUG_ENTER;
567     if (deltaTarget > deltaSource) {
568         MMI_HILOGE("Invalid deltaSource or deltaTarget");
569         return 0;
570     } else {
571         return deltaSource - deltaTarget;
572     }
573 }
574 
DrawTrackColorBlue(int32_t pathValue)575 uint32_t KnuckleDrawingManager::DrawTrackColorBlue(int32_t pathValue)
576 {
577     CALL_DEBUG_ENTER;
578     if (((static_cast<int32_t>(pathLength_) / TRACK_PATH_LENGTH_2000) != 0) &&
579         (pathValue < TRACK_PATH_LENGTH_400)) {
580         uint32_t deltaR = GetDeltaColor(TRACK_COLOR_YELLOW_R, TRACK_COLOR_BLUE_R);
581         uint32_t deltaG = GetDeltaColor(TRACK_COLOR_BLUE_G, TRACK_COLOR_YELLOW_G);
582         uint32_t deltaB = GetDeltaColor(TRACK_COLOR_BLUE_B, TRACK_COLOR_YELLOW_B);
583         float pathLength = path_.GetLength(false);
584         trackColorR_ -= deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
585         trackColorG_ += deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
586         trackColorB_ += deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
587         uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
588             ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
589         return colorQuad;
590     } else {
591         trackColorR_ = TRACK_COLOR_BLUE_R;
592         trackColorG_ = TRACK_COLOR_BLUE_G;
593         trackColorB_ = TRACK_COLOR_BLUE_B;
594         return TRACK_COLOR_BLUE;
595     }
596 }
597 
DrawTrackColorPink(int32_t pathValue)598 uint32_t KnuckleDrawingManager::DrawTrackColorPink(int32_t pathValue)
599 {
600     CALL_DEBUG_ENTER;
601     if (pathValue < TRACK_PATH_LENGTH_900) {
602         uint32_t deltaR = GetDeltaColor(TRACK_COLOR_PINK_R, TRACK_COLOR_BLUE_R);
603         uint32_t deltaG = GetDeltaColor(TRACK_COLOR_BLUE_G, TRACK_COLOR_PINK_G);
604         uint32_t deltaB = GetDeltaColor(TRACK_COLOR_BLUE_B, TRACK_COLOR_PINK_B);
605         float pathLength = path_.GetLength(false);
606         trackColorR_ += deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
607         trackColorG_ -= deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
608         trackColorB_ -= deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
609         uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
610             ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
611         return colorQuad;
612     } else {
613         trackColorR_ = TRACK_COLOR_PINK_R;
614         trackColorG_ = TRACK_COLOR_PINK_G;
615         trackColorB_ = TRACK_COLOR_PINK_B;
616         return TRACK_COLOR_PINK;
617     }
618 }
619 
DrawTrackColorOrangeRed(int32_t pathValue)620 uint32_t KnuckleDrawingManager::DrawTrackColorOrangeRed(int32_t pathValue)
621 {
622     CALL_DEBUG_ENTER;
623     if (pathValue < TRACK_PATH_LENGTH_1400) {
624         uint32_t deltaR = GetDeltaColor(TRACK_COLOR_ORANGE_RED_R, TRACK_COLOR_PINK_R);
625         uint32_t deltaG = GetDeltaColor(TRACK_COLOR_ORANGE_RED_G, TRACK_COLOR_PINK_G);
626         uint32_t deltaB = GetDeltaColor(TRACK_COLOR_PINK_B, TRACK_COLOR_ORANGE_RED_B);
627         float pathLength = path_.GetLength(false);
628         trackColorR_ += deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
629         trackColorG_ += deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
630         trackColorB_ -= deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
631         uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
632             ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
633         return colorQuad;
634     } else {
635         trackColorR_ = TRACK_COLOR_ORANGE_RED_R;
636         trackColorG_ = TRACK_COLOR_ORANGE_RED_G;
637         trackColorB_ = TRACK_COLOR_ORANGE_RED_B;
638         return TRACK_COLOR_ORANGE_RED;
639     }
640 }
641 
DrawTrackColorYellow(int32_t pathValue)642 uint32_t KnuckleDrawingManager::DrawTrackColorYellow(int32_t pathValue)
643 {
644     CALL_DEBUG_ENTER;
645     if (pathValue < TRACK_PATH_LENGTH_1900) {
646         uint32_t deltaR = GetDeltaColor(TRACK_COLOR_YELLOW_R, TRACK_COLOR_ORANGE_RED_R);
647         uint32_t deltaG = GetDeltaColor(TRACK_COLOR_YELLOW_G, TRACK_COLOR_ORANGE_RED_G);
648         uint32_t deltaB = GetDeltaColor(TRACK_COLOR_ORANGE_RED_B, TRACK_COLOR_YELLOW_B);
649         float pathLength = path_.GetLength(false);
650         trackColorR_ += deltaR * pathLength / COLOR_TRANSITIONS_LENGTH;
651         trackColorG_ += deltaG * pathLength / COLOR_TRANSITIONS_LENGTH;
652         trackColorB_ -= deltaB * pathLength / COLOR_TRANSITIONS_LENGTH;
653         uint32_t colorQuad = Rosen::Drawing::Color::ColorQuadSetARGB(
654             ALPHA_ZERO, trackColorR_, trackColorG_, trackColorB_);
655         return colorQuad;
656     } else {
657         trackColorR_ = TRACK_COLOR_YELLOW_R;
658         trackColorG_ = TRACK_COLOR_YELLOW_G;
659         trackColorB_ = TRACK_COLOR_YELLOW_B;
660         return TRACK_COLOR_YELLOW;
661     }
662 }
663 
DrawTrackCanvas()664 void KnuckleDrawingManager::DrawTrackCanvas()
665 {
666     CALL_DEBUG_ENTER;
667     CHKPV(trackCanvasNode_);
668 #ifndef USE_ROSEN_DRAWING
669     auto trackCanvas = static_cast<Rosen::RSRecordingCanvas *>(trackCanvasNode_->
670         BeginRecording(scaleW_, scaleH_));
671 #else
672     auto trackCanvas = static_cast<Rosen::Drawing::RecordingCanvas *>(trackCanvasNode_->
673         BeginRecording(scaleW_, scaleH_));
674 #endif // USE_ROSEN_DRAWING
675     CHKPV(trackCanvas);
676     pathLength_ += path_.GetLength(false);
677     int32_t pathValue = static_cast<int32_t>(pathLength_) % TRACK_PATH_LENGTH_2000;
678     Rosen::Drawing::Pen pen;
679 
680     if (pathValue < TRACK_PATH_LENGTH_500) {
681         pen.SetColor(DrawTrackColorBlue(pathValue));
682     } else if (pathValue < TRACK_PATH_LENGTH_1000) {
683         pen.SetColor(DrawTrackColorPink(pathValue));
684     } else if (pathValue < TRACK_PATH_LENGTH_1500) {
685         pen.SetColor(DrawTrackColorOrangeRed(pathValue));
686     } else {
687         pen.SetColor(DrawTrackColorYellow(pathValue));
688     }
689     pen.SetWidth(PAINT_STROKE_WIDTH);
690     Rosen::Drawing::Filter filter;
691     filter.SetMaskFilter(
692         Rosen::Drawing::MaskFilter::CreateBlurMaskFilter(Rosen::Drawing::BlurType::OUTER, TRACK_FILTER_SCALAR));
693     pen.SetFilter(filter);
694     trackCanvas->AttachPen(pen);
695     trackCanvas->DrawPath(path_);
696     trackCanvas->DetachPen();
697 
698     trackCanvas->AttachPaint(paint_);
699     trackCanvas->DrawPath(path_);
700     trackCanvas->DetachPaint();
701     trackCanvasNode_->FinishRecording();
702 }
703 
DrawBrushCanvas()704 void KnuckleDrawingManager::DrawBrushCanvas()
705 {
706     if (pathInfos_.size() >= PATH_SIZE_EIGHT) {
707         brushPathLength_ += path_.GetLength(false);
708         float pathLength = pathInfos_[0].GetLength(false);
709         if (((brushPathLength_ - pathLength) > MAX_PATH_LENGTH) || (pathInfos_.size() >= MAX_PATH_SIZE)) {
710             pathInfos_.erase(pathInfos_.begin());
711             brushPathLength_ -= pathLength;
712         }
713         pathInfos_.emplace_back(path_);
714         CHKPV(brushCanvasNode_);
715         brushCanvasNode_->ResetSurface(scaleW_, scaleH_);
716 
717 #ifndef USE_ROSEN_DRAWING
718         auto canvas = static_cast<Rosen::RSRecordingCanvas *>(brushCanvasNode_->
719             BeginRecording(scaleW_, scaleH_));
720 #else
721         auto canvas = static_cast<Rosen::Drawing::RecordingCanvas *>(brushCanvasNode_->
722             BeginRecording(scaleW_, scaleH_));
723 #endif // USE_ROSEN_DRAWING
724         CHKPV(canvas);
725         for (size_t i = 0; (i < pathInfos_.size()) && (pathInfos_.size() != 1); ++i) {
726             Rosen::Drawing::Paint paint;
727             paint.SetAntiAlias(true);
728             paint.SetStyle(Rosen::Drawing::Paint::PaintStyle::PAINT_STROKE);
729             paint.SetJoinStyle(Rosen::Drawing::Pen::JoinStyle::ROUND_JOIN);
730             paint.SetCapStyle(Rosen::Drawing::Pen::CapStyle::ROUND_CAP);
731 
732             paint.SetWidth(TRACK_WIDTH_THIRTY / (pathInfos_.size() - 1) * i + TRACK_WIDTH_TEN);
733             paint.SetColor(Rosen::Drawing::Color::COLOR_WHITE);
734             canvas->AttachPaint(paint);
735             canvas->DrawPath(pathInfos_[i]);
736             canvas->DetachPaint();
737         }
738         brushCanvasNode_->FinishRecording();
739     } else {
740         pathInfos_.emplace_back(path_);
741         brushPathLength_ += path_.GetLength(false);
742     }
743 }
744 
ActionUpAnimation()745 void KnuckleDrawingManager::ActionUpAnimation()
746 {
747     CALL_DEBUG_ENTER;
748     CHKPV(trackCanvasNode_);
749     Rosen::RSAnimationTimingProtocol protocol;
750     protocol.SetDuration(PROTOCOL_DURATION);
751     protocol.SetRepeatCount(1);
752     auto animate = Rosen::RSNode::Animate(
753         protocol,
754         Rosen::RSAnimationTimingCurve::LINEAR,
755         [this]() {
756             trackCanvasNode_->SetAlpha(ALPHA_RANGE_END);
757         });
758     Rosen::RSTransaction::FlushImplicitTransaction();
759 }
760 
ProcessUpEvent(bool isNeedUpAnimation)761 int32_t KnuckleDrawingManager::ProcessUpEvent(bool isNeedUpAnimation)
762 {
763     CALL_DEBUG_ENTER;
764     isActionUp_ = false;
765     isNeedInitParticleEmitter_ = true;
766     pathInfos_.clear();
767     pathLength_ = 0.0f;
768     brushPathLength_ = 0.0f;
769     trackColorR_ = 0x00;
770     trackColorG_ = 0x00;
771     trackColorB_ = 0x00;
772     if (ClearBrushCanvas() != RET_OK) {
773         MMI_HILOGE("ClearBrushCanvas failed");
774         return RET_ERR;
775     }
776     if (isNeedUpAnimation) {
777         ActionUpAnimation();
778         int32_t repeatTime = 1;
779         int32_t timerId = TimerMgr->AddTimer(PROTOCOL_DURATION, repeatTime, [this]() {
780             DestoryWindow();
781         });
782         if (timerId < 0) {
783             MMI_HILOGE("Add timer failed, timerId:%{public}d", timerId);
784             DestoryWindow();
785         }
786     } else {
787         DestoryWindow();
788     }
789     return RET_OK;
790 }
791 
DrawGraphic(std::shared_ptr<PointerEvent> touchEvent)792 int32_t KnuckleDrawingManager::DrawGraphic(std::shared_ptr<PointerEvent> touchEvent)
793 {
794     CALL_DEBUG_ENTER;
795     CHKPR(touchEvent, RET_ERR);
796     if (GetPointerPos(touchEvent) != RET_OK) {
797         MMI_HILOGD("GetPointerPos failed");
798         return RET_ERR;
799     }
800     bool needDrawParticle = (touchEvent->GetActionTime() - firstDownTime_) > WAIT_DOUBLE_CLICK_INTERVAL_TIME;
801     if (!isActionUp_) {
802         if (needDrawParticle) {
803             if (isNeedInitParticleEmitter_) {
804                 InitParticleEmitter();
805             } else {
806                 UpdateEmitter();
807             }
808         }
809         path_.MoveTo(pointerInfos_[POINT_INDEX0].x, pointerInfos_[POINT_INDEX0].y);
810         path_.CubicTo(pointerInfos_[POINT_INDEX1].x, pointerInfos_[POINT_INDEX1].y,
811             pointerInfos_[POINT_INDEX2].x, pointerInfos_[POINT_INDEX2].y,
812             pointerInfos_[POINT_INDEX3].x, pointerInfos_[POINT_INDEX3].y);
813         pointerInfos_.erase(pointerInfos_.begin(), pointerInfos_.begin() + POINT_INDEX3);
814         if (pointerNum_ < POINTER_NUMBER_TO_DRAW) {
815             MMI_HILOGE("Pointer number not enough to draw");
816             return RET_ERR;
817         }
818         DrawTrackCanvas();
819         DrawBrushCanvas();
820     } else {
821         MMI_HILOGE("isActionUp_ is true");
822         return ProcessUpEvent(needDrawParticle);
823     }
824     path_.Reset();
825     return RET_OK;
826 }
827 #else
DrawGraphic(std::shared_ptr<PointerEvent> touchEvent)828 int32_t KnuckleDrawingManager::DrawGraphic(std::shared_ptr<PointerEvent> touchEvent)
829 {
830     CALL_DEBUG_ENTER;
831     CHKPR(touchEvent, RET_ERR);
832     CHKPR(canvasNode_, RET_ERR);
833     if (GetPointerPos(touchEvent) != RET_OK) {
834         MMI_HILOGD("GetPointerPos failed");
835         return RET_ERR;
836     }
837     if (!isActionUp_) {
838         path_.MoveTo(pointerInfos_[POINT_INDEX0].x, pointerInfos_[POINT_INDEX0].y);
839         path_.CubicTo(pointerInfos_[POINT_INDEX1].x, pointerInfos_[POINT_INDEX1].y,
840             pointerInfos_[POINT_INDEX2].x, pointerInfos_[POINT_INDEX2].y,
841             pointerInfos_[POINT_INDEX3].x, pointerInfos_[POINT_INDEX3].y);
842         pointerInfos_.erase(pointerInfos_.begin(), pointerInfos_.begin() + POINT_INDEX3);
843         if (pointerNum_ < POINTER_NUMBER_TO_DRAW) {
844             return RET_ERR;
845         }
846 #ifndef USE_ROSEN_DRAWING
847         auto canvas = static_cast<Rosen::RSRecordingCanvas *>(canvasNode_->
848             BeginRecording(scaleW_, scaleH_));
849 #else
850         auto canvas = static_cast<Rosen::Drawing::RecordingCanvas *>(canvasNode_->
851             BeginRecording(scaleW_, scaleH_));
852 #endif // USE_ROSEN_DRAWING
853         CHKPR(canvas, RET_ERR);
854         canvas->AttachPaint(paint_);
855         canvas->DrawPath(path_);
856         canvas->DetachPaint();
857     } else {
858         MMI_HILOGD("isActionUp_ is true");
859         isActionUp_ = false;
860         return DestoryWindow();
861     }
862     path_.Reset();
863     canvasNode_->FinishRecording();
864     return RET_OK;
865 }
866 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
867 
868 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
ClearTrackCanvas()869 int32_t KnuckleDrawingManager::ClearTrackCanvas()
870 {
871     CALL_DEBUG_ENTER;
872     CHKPR(trackCanvasNode_, RET_ERR);
873 #ifndef USE_ROSEN_DRAWING
874     auto trackCanvas = static_cast<Rosen::RSRecordingCanvas *>(trackCanvasNode_->
875         BeginRecording(scaleW_, scaleH_));
876 #else
877     auto trackCanvas = static_cast<Rosen::Drawing::RecordingCanvas *>(trackCanvasNode_->
878         BeginRecording(scaleW_, scaleH_));
879 #endif // USE_ROSEN_DRAWING
880     CHKPR(trackCanvas, RET_ERR);
881     trackCanvas->Clear();
882     trackCanvasNode_->FinishRecording();
883     CHKPR(surfaceNode_, RET_ERR);
884     surfaceNode_->RemoveChild(trackCanvasNode_);
885     trackCanvasNode_->ResetSurface(scaleW_, scaleH_);
886     trackCanvasNode_.reset();
887     return RET_OK;
888 }
889 
ClearBrushCanvas()890 int32_t KnuckleDrawingManager::ClearBrushCanvas()
891 {
892     CALL_DEBUG_ENTER;
893     CHKPR(brushCanvasNode_, RET_ERR);
894 #ifndef USE_ROSEN_DRAWING
895     auto brushCanvas = static_cast<Rosen::RSRecordingCanvas *>(brushCanvasNode_->
896         BeginRecording(scaleW_, scaleH_));
897 #else
898     auto brushCanvas = static_cast<Rosen::Drawing::RecordingCanvas *>(brushCanvasNode_->
899         BeginRecording(scaleW_, scaleH_));
900 #endif // USE_ROSEN_DRAWING
901     CHKPR(brushCanvas, RET_ERR);
902     brushCanvas->Clear();
903     brushCanvasNode_->FinishRecording();
904     CHKPR(surfaceNode_, RET_ERR);
905     surfaceNode_->RemoveChild(brushCanvasNode_);
906     brushCanvasNode_->ResetSurface(scaleW_, scaleH_);
907     brushCanvasNode_.reset();
908     return RET_OK;
909 }
910 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
911 
912 #ifdef OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
DestoryWindow()913 int32_t KnuckleDrawingManager::DestoryWindow()
914 {
915     CALL_DEBUG_ENTER;
916     pointerInfos_.clear();
917     path_.Reset();
918     ClearBrushCanvas();
919     if (ClearTrackCanvas() != RET_OK) {
920         MMI_HILOGE("ClearTrackCanvas failed");
921         return RET_ERR;
922     }
923     CHKPR(surfaceNode_, RET_ERR);
924     surfaceNode_->DetachToDisplay(screenId_);
925     surfaceNode_.reset();
926     Rosen::RSTransaction::FlushImplicitTransaction();
927     return RET_OK;
928 }
929 #else
DestoryWindow()930 int32_t KnuckleDrawingManager::DestoryWindow()
931 {
932     CALL_DEBUG_ENTER;
933     pointerInfos_.clear();
934     path_.Reset();
935     CHKPR(canvasNode_, RET_ERR);
936 #ifndef USE_ROSEN_DRAWING
937     auto canvas = static_cast<Rosen::RSRecordingCanvas *>(canvasNode_->
938         BeginRecording(scaleW_, scaleH_));
939 #else
940     auto canvas = static_cast<Rosen::Drawing::RecordingCanvas *>(canvasNode_->
941         BeginRecording(scaleW_, scaleH_));
942 #endif // USE_ROSEN_DRAWING
943     CHKPR(canvas, RET_ERR);
944     canvas->Clear();
945     canvasNode_->FinishRecording();
946     CHKPR(surfaceNode_, RET_ERR);
947     surfaceNode_->DetachToDisplay(screenId_);
948     surfaceNode_->RemoveChild(canvasNode_);
949     canvasNode_->ResetSurface(scaleW_, scaleH_);
950     canvasNode_.reset();
951     surfaceNode_.reset();
952     Rosen::RSTransaction::FlushImplicitTransaction();
953     return RET_OK;
954 }
955 #endif // OHOS_BUILD_ENABLE_NEW_KNUCKLE_DYNAMIC
956 
CreateObserver()957 void KnuckleDrawingManager::CreateObserver()
958 {
959     CALL_DEBUG_ENTER;
960     if (!hasScreenReadObserver_) {
961         screenReadState_.switchName = SCREEN_READING;
962         CreateScreenReadObserver(screenReadState_);
963     }
964     MMI_HILOGD("screenReadState_.state: %{public}s", screenReadState_.state.c_str());
965 }
966 
967 template <class T>
CreateScreenReadObserver(T & item)968 void KnuckleDrawingManager::CreateScreenReadObserver(T &item)
969 {
970     CALL_DEBUG_ENTER;
971     SettingObserver::UpdateFunc updateFunc = [&item](const std::string& key) {
972         auto ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
973             .GetStringValue(key, item.state);
974         if (ret != RET_OK) {
975             MMI_HILOGE("Get value from setting date fail");
976             return;
977         }
978         MMI_HILOGI("key: %{public}s, state: %{public}s", key.c_str(), item.state.c_str());
979     };
980     sptr<SettingObserver> statusObserver = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID)
981         .CreateObserver(item.switchName, updateFunc);
982     ErrCode ret = SettingDataShare::GetInstance(MULTIMODAL_INPUT_SERVICE_ID).
983         RegisterObserver(statusObserver);
984     if (ret != ERR_OK) {
985         MMI_HILOGE("register setting observer failed, ret=%{public}d", ret);
986         statusObserver = nullptr;
987         return;
988     }
989     hasScreenReadObserver_ = true;
990 }
991 
GetScreenReadState()992 std::string KnuckleDrawingManager::GetScreenReadState()
993 {
994     return screenReadState_.state;
995 }
996 } // namespace MMI
997 } // namespace OHOS