• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2025-2025 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 // LCOV_EXCL_START
17 #include "magnification_window.h"
18 #include "visibility.h"
19 
20 namespace OHOS {
21 namespace Accessibility {
22 
23 namespace {
24     const std::string WINDOW_NAME = "magnification_window";
25 }
26 
27 static MagnificationWindow instance;
28 
29 //common
GetSourceCenter()30 PointerPos MagnificationWindow::GetSourceCenter()
31 {
32     PointerPos point = {0, 0};
33     point.posX = sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_ / DIVISOR_TWO);
34     point.posY = sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_ / DIVISOR_TWO);
35     return point;
36 }
37 
ConvertCoordinates(int32_t posX,int32_t posY)38 PointerPos MagnificationWindow::ConvertCoordinates(int32_t posX, int32_t posY)
39 {
40     PointerPos sourcePoint = {0, 0};
41     if ((abs(scale_) < EPS)) {
42         return sourcePoint;
43     }
44     int32_t windowDeltaX = posX - windowRect_.posX_;
45     int32_t windowDeltaY = posY - windowRect_.posY_;
46     sourcePoint.posX = sourceRect_.posX_ + static_cast<int32_t>(windowDeltaX / scale_);
47     sourcePoint.posY = sourceRect_.posY_ + static_cast<int32_t>(windowDeltaY / scale_);
48     return sourcePoint;
49 }
50 
CreateMagnificationWindow()51 void MagnificationWindow::CreateMagnificationWindow()
52 {
53     HILOG_DEBUG();
54     sptr<Rosen::WindowOption> windowOption = new(std::nothrow) Rosen::WindowOption();
55     if (windowOption == nullptr) {
56         HILOG_ERROR("windowOption is null.");
57         return;
58     }
59     windowOption->SetWindowType(Rosen::WindowType::WINDOW_TYPE_MAGNIFICATION);
60     windowOption->SetWindowMode(Rosen::WindowMode::WINDOW_MODE_FLOATING);
61     windowOption->SetWindowRect(windowRect_);
62     windowOption->SetFocusable(false);
63     window_ = OHOS::Rosen::Window::Create(WINDOW_NAME, windowOption);
64     if (window_ == nullptr) {
65         HILOG_ERROR("window create failed.");
66         ExtUtils::RecordMagnificationUnavailableEvent("Create window failed.");
67         return;
68     }
69     window_->SetCornerRadius(CORNER_RADIUS);
70     surfaceNode_ = window_->GetSurfaceNode();
71     if (surfaceNode_ == nullptr) {
72         HILOG_ERROR("get surfaceNode_ failed.");
73         return;
74     }
75     rsUIContext_ = surfaceNode_->GetRSUIContext();
76     canvasNode_ = Rosen::RSCanvasNode::Create(false, false, rsUIContext_);
77     if (canvasNode_ == nullptr) {
78         HILOG_ERROR("canvasNode_ is nullptr.");
79         return;
80     }
81     canvasNode_->SetSkipCheckInMultiInstance(true);
82 }
83 
GetWindowParam()84 void MagnificationWindow::GetWindowParam()
85 {
86     HILOG_DEBUG();
87 #ifdef OHOS_BUILD_ENABLE_DISPLAY_MANAGER
88     screenId_ = Rosen::DisplayManager::GetInstance().GetDefaultDisplayId();
89     sptr<Rosen::Display> display = Rosen::DisplayManager::GetInstance().GetDisplayById(screenId_);
90     if (display == nullptr) {
91         HILOG_ERROR("display is nullptr.");
92         return;
93     }
94     screenWidth_ = static_cast<uint32_t>(display->GetWidth());
95     screenHeight_ = static_cast<uint32_t>(display->GetHeight());
96     screenSpan_ = hypot(screenWidth_, screenHeight_);
97     screenRect_ = {0, 0, screenWidth_, screenHeight_};
98 #else
99     HILOG_INFO("not support");
100 #endif
101 }
102 
FlushImplicitTransaction()103 void MagnificationWindow::FlushImplicitTransaction()
104 {
105     if (rsUIContext_ != nullptr) {
106         auto rsTransaction = rsUIContext_->GetRSTransaction();
107         if (rsTransaction != nullptr) {
108             rsTransaction->FlushImplicitTransaction();
109         }
110     } else {
111         Rosen::RSTransaction::FlushImplicitTransaction();
112     }
113 }
114 
GetRectCenter(Rosen::Rect rect)115 PointerPos MagnificationWindow::GetRectCenter(Rosen::Rect rect)
116 {
117     PointerPos point = {0, 0};
118     point.posX = rect.posX_ + static_cast<int32_t>(rect.width_ / DIVISOR_TWO);
119     point.posY = rect.posY_ + static_cast<int32_t>(rect.height_ / DIVISOR_TWO);
120     return point;
121 }
122 
GetSourceRectFromPointer(int32_t centerX,int32_t centerY)123 Rosen::Rect MagnificationWindow::GetSourceRectFromPointer(int32_t centerX, int32_t centerY)
124 {
125     Rosen::Rect sourceRect = {0, 0, 0, 0};
126     if ((abs(scale_) < EPS)) {
127         return sourceRect;
128     }
129     sourceRect.width_ = static_cast<uint32_t>(static_cast<float>(windowRect_.width_) / scale_);
130     sourceRect.height_ = static_cast<uint32_t>(static_cast<float>(windowRect_.height_) / scale_);
131 
132     int32_t x = centerX - static_cast<int32_t>(sourceRect.width_ / DIVISOR_TWO);
133     int32_t y = centerY - static_cast<int32_t>(sourceRect.height_ / DIVISOR_TWO);
134 
135     x = (x < 0) ? 0 : x;
136     x = (x + static_cast<int32_t>(sourceRect.width_)) > static_cast<int32_t>(
137         screenWidth_) ? static_cast<int32_t>(screenWidth_ - sourceRect.width_) : x;
138 
139     y = (y < 0) ? 0 : y;
140     y = (y + static_cast<int32_t>(sourceRect.height_)) > static_cast<int32_t>(
141         screenHeight_) ? static_cast<int32_t>(screenHeight_ - sourceRect.height_) : y;
142 
143     sourceRect.posX_ = x;
144     sourceRect.posY_ = y;
145     HILOG_WARN("sourceRect_ = %{public}s", sourceRect_.ToString().c_str());
146     return sourceRect;
147 }
148 
DisableMagnification(bool needClear)149 void MagnificationWindow::DisableMagnification(bool needClear)
150 {
151     HILOG_INFO();
152     if (needClear && surfaceNode_ != nullptr) {
153         HILOG_DEBUG("claer surfaceNode");
154         surfaceNode_->SetVisible(false);
155         surfaceNode_->ClearChildren();
156         FlushImplicitTransaction();
157     }
158 
159     if (window_ != nullptr) {
160         window_->Hide();
161         window_->Destroy();
162         window_ = nullptr;
163     }
164     surfaceNode_ = nullptr;
165     canvasNode_ = nullptr;
166     rsUIContext_ = nullptr;
167 }
168 
169 // full magnification
ConvertGesture(uint32_t type,PointerPos coordinates)170 PointerPos MagnificationWindow::ConvertGesture(uint32_t type, PointerPos coordinates)
171 {
172     int32_t posX = coordinates.posX;
173     int32_t posY = coordinates.posY;
174     PointerPos point = {posX, posY};
175 
176     if (type == BOTTOM_BACK_GESTURE) {
177         int32_t offsetY = static_cast<int32_t>(screenHeight_) -
178             (sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_));
179         point.posY = posY + offsetY;
180         return point;
181     }
182     if (type == LEFT_BACK_GESTURE) {
183         int32_t offsetX = sourceRect_.posX_;
184         point.posX = posX - offsetX;
185         return point;
186     }
187 
188     if (type == RIGHT_BACK_GESTURE) {
189         int32_t offsetX = static_cast<int32_t>(screenWidth_) -
190             (sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_));
191         point.posX = posX + offsetX;
192         return point;
193     }
194 
195     return point;
196 }
197 
CheckTapOnHotArea(int32_t posX,int32_t posY)198 uint32_t MagnificationWindow::CheckTapOnHotArea(int32_t posX, int32_t posY)
199 {
200     bool isTapOnBottom = posY <= static_cast<int32_t>(screenHeight_) &&
201         posY >= static_cast<int32_t>(screenHeight_) - GESTURE_OFFSET;
202     if (isTapOnBottom) {
203         HILOG_DEBUG("Tap On Bottom");
204         return BOTTOM_BACK_GESTURE;
205     }
206     bool isTapOnLeftSide = posX >= 0 && posX <= GESTURE_OFFSET;
207     if (isTapOnLeftSide) {
208         HILOG_DEBUG("Tap On Left Side");
209         return LEFT_BACK_GESTURE;
210     }
211     bool isTapOnRightSide = posX >= static_cast<int32_t>(screenWidth_) - GESTURE_OFFSET &&
212         posX <= static_cast<int32_t>(screenWidth_);
213     if (isTapOnRightSide) {
214         HILOG_DEBUG("Tap On Right Side");
215         return RIGHT_BACK_GESTURE;
216     }
217     return INVALID_GESTURE_TYPE;
218 }
219 
FollowFocuseElementFull(int32_t centerX,int32_t centerY)220 void MagnificationWindow::FollowFocuseElementFull(int32_t centerX, int32_t centerY)
221 {
222     HILOG_DEBUG();
223     if (window_ == nullptr) {
224         HILOG_ERROR("window_ is nullptr.");
225         return;
226     }
227     sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
228     window_->SetFrameRectForPartialZoomIn(sourceRect_);
229     DrawRuoundRectFrameFull();
230     FlushImplicitTransaction();
231     UpdateAnchor();
232 }
233 
UpdateAnchor()234 void MagnificationWindow::UpdateAnchor()
235 {
236     centerX_ = static_cast<int32_t>((sourceRect_.posX_ + sourceRect_.posX_ +
237         static_cast<int32_t>(sourceRect_.width_)) / DIVISOR_TWO);
238     centerY_ = static_cast<int32_t>((sourceRect_.posY_ + sourceRect_.posY_ +
239         static_cast<int32_t>(sourceRect_.height_)) / DIVISOR_TWO);
240 }
241 
DrawRuoundRectFrameFull()242 void MagnificationWindow::DrawRuoundRectFrameFull()
243 {
244     if (surfaceNode_ == nullptr) {
245         HILOG_ERROR("get surfaceNode_ failed.");
246         return;
247     }
248 
249     if (canvasNode_ == nullptr) {
250         HILOG_ERROR("create canvasNode_ fail");
251         return;
252     }
253     surfaceNode_->SetAbilityBGAlpha(BG_ALPHA);
254     surfaceNode_->AddChild(canvasNode_, -1);
255     canvasNode_->SetBounds(0, 0, screenWidth_, screenHeight_);
256     canvasNode_->SetFrame(0, 0, screenWidth_, screenHeight_);
257     canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
258     canvasNode_->SetRotation(0);
259 
260     auto canvas = canvasNode_->BeginRecording(screenWidth_, screenHeight_);
261     if (canvas == nullptr) {
262         HILOG_ERROR("get canvas fail");
263         return;
264     }
265     Rosen::Drawing::Pen pen;
266     pen.SetAntiAlias(true);
267     pen.SetColor(ORANGE_COLOR);
268     pen.SetWidth(PEN_WIDTH);
269     canvas->AttachPen(pen);
270     Rosen::Drawing::Path path;
271     path.AddRoundRect({ROUND_RECT_MARGIN, ROUND_RECT_MARGIN,
272         screenWidth_ - ROUND_RECT_MARGIN, screenHeight_ - ROUND_RECT_MARGIN},
273         CORNER_RADIUS, CORNER_RADIUS, Rosen::Drawing::PathDirection::CW_DIRECTION);
274     canvas->DrawPath(path);
275     canvas->DetachPen();
276     canvasNode_->FinishRecording();
277 }
278 
EnableMagnificationFull(int32_t centerX,int32_t centerY)279 void MagnificationWindow::EnableMagnificationFull(int32_t centerX, int32_t centerY)
280 {
281     HILOG_INFO("centerX = %{public}d, centerY = %{public}d.", centerX, centerY);
282     GetWindowParam();
283     if (window_ == nullptr) {
284         HILOG_DEBUG("window is null. need create.");
285         windowRect_ = {0, 0, screenWidth_, screenHeight_};
286         CreateMagnificationWindow();
287     }
288 
289     if (window_ == nullptr) {
290         HILOG_ERROR("create window failed.");
291         return;
292     }
293     sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
294     UpdateAnchor();
295     DrawRuoundRectFrameFull();
296     Rosen::WMError ret = window_->SetFrameRectForPartialZoomIn(sourceRect_);
297     if (ret != Rosen::WMError::WM_OK) {
298         HILOG_ERROR("Trigger magnification failed.");
299         ExtUtils::RecordMagnificationUnavailableEvent("Trigger magnification failed.");
300     }
301     window_->Show();
302     FlushImplicitTransaction();
303     isMagnificationShowFull_ = true;
304 }
305 
DisableMagnificationFull(bool needClear)306 void MagnificationWindow::DisableMagnificationFull(bool needClear)
307 {
308     HILOG_INFO();
309     DisableMagnification();
310     isMagnificationShowFull_ = false;
311 }
312 
SetScaleFull(float scaleSpan)313 void MagnificationWindow::SetScaleFull(float scaleSpan)
314 {
315     HILOG_DEBUG();
316     if (window_ == nullptr) {
317         HILOG_ERROR("window_ is nullptr.");
318         return;
319     }
320     if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) {
321         HILOG_ERROR("screen param invalid.");
322         return;
323     }
324 
325     float ratio = scaleSpan / screenSpan_;
326     float tmpScale = scale_ + ratio * scale_;
327 
328     if (tmpScale > MAX_SCALE) {
329         tmpScale = MAX_SCALE;
330     }
331     if (tmpScale < DEFAULT_SCALE) {
332         tmpScale = DEFAULT_SCALE;
333     }
334 
335     uint32_t newWidth = static_cast<uint32_t>(windowRect_.width_ / tmpScale);
336     uint32_t newHeight = static_cast<uint32_t>(windowRect_.height_ / tmpScale);
337     int32_t newPosX = centerX_ - static_cast<int32_t>(newWidth / DIVISOR_TWO);
338     int32_t newPosY = centerY_ - static_cast<int32_t>(newHeight / DIVISOR_TWO);
339 
340     if (newPosX < 0) {
341         centerX_ -= newPosX;
342         newPosX = 0;
343     }
344 
345     if (newPosY < 0) {
346         centerY_ -= newPosY;
347         newPosY = 0;
348     }
349 
350     if (newPosX + static_cast<int32_t>(newWidth) > static_cast<int32_t>(screenWidth_)) {
351         centerX_ -= (newPosX + static_cast<int32_t>(newWidth) - static_cast<int32_t>(screenWidth_));
352         newPosX = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(newWidth);
353     }
354 
355     if (newPosY + static_cast<int32_t>(newHeight) > static_cast<int32_t>(screenHeight_)) {
356         centerY_ -= (newPosY + static_cast<int32_t>(newHeight) - static_cast<int32_t>(screenHeight_));
357         newPosY = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(newHeight);
358     }
359 
360     sourceRect_ = {newPosX, newPosY, newWidth, newHeight};
361     scale_ = tmpScale;
362     window_->SetFrameRectForPartialZoomIn(sourceRect_);
363     DrawRuoundRectFrameFull();
364     FlushImplicitTransaction();
365     UpdateAnchor();
366 }
367 
MoveMagnificationFull(int32_t deltaX,int32_t deltaY)368 void MagnificationWindow::MoveMagnificationFull(int32_t deltaX, int32_t deltaY)
369 {
370     HILOG_DEBUG();
371     if (window_ == nullptr) {
372         HILOG_ERROR("window_ is nullptr.");
373         return;
374     }
375     int32_t sourcePosX = sourceRect_.posX_ - deltaX;
376     int32_t sourcePosY = sourceRect_.posY_ - deltaY;
377 
378     if (sourcePosX < 0) {
379         sourcePosX = 0;
380     }
381 
382     if (sourcePosY < 0) {
383         sourcePosY = 0;
384     }
385 
386     if (sourcePosX + static_cast<int32_t>(sourceRect_.width_) > static_cast<int32_t>(screenWidth_)) {
387         sourcePosX = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(sourceRect_.width_);
388     }
389 
390     if (sourcePosY + static_cast<int32_t>(sourceRect_.height_) > static_cast<int32_t>(screenHeight_)) {
391         sourcePosY = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(sourceRect_.height_);
392     }
393     sourceRect_.posX_ = sourcePosX;
394     sourceRect_.posY_ = sourcePosY;
395     window_->SetFrameRectForPartialZoomIn(sourceRect_);
396     DrawRuoundRectFrameFull();
397     FlushImplicitTransaction();
398     UpdateAnchor();
399 }
400 
ShowMagnificationFull()401 void MagnificationWindow::ShowMagnificationFull()
402 {
403     int32_t centerX = static_cast<int32_t>(screenWidth_ / DIVISOR_TWO);
404     int32_t centerY = static_cast<int32_t>(screenHeight_ / DIVISOR_TWO);
405     EnableMagnificationFull(centerX, centerY);
406 }
407 
RefreshWindowParamFull(RotationType type)408 void MagnificationWindow::RefreshWindowParamFull(RotationType type)
409 {
410     HILOG_DEBUG();
411     PointerPos center = GetRectCenter(sourceRect_);
412     if (isMagnificationShowFull_) {
413         DisableMagnificationFull(false);
414         center = TransferCenter(type, center);
415         EnableMagnificationFull(center.posX, center.posY);
416     } else {
417         GetWindowParam();
418     }
419 }
420 
IsMagnificationShowFull()421 bool MagnificationWindow::IsMagnificationShowFull()
422 {
423     return isMagnificationShowFull_;
424 }
425 
426 // window magnification
GetWindowRectFromPointer(int32_t centerX,int32_t centerY)427 Rosen::Rect MagnificationWindow::GetWindowRectFromPointer(int32_t centerX, int32_t centerY)
428 {
429     Rosen::Rect windowRect = {0, 0, windowWidth_, windowHeight_};
430     int32_t x = centerX - static_cast<int32_t>(windowWidth_ / DIVISOR_TWO);
431     int32_t y = centerY - static_cast<int32_t>(windowHeight_ / DIVISOR_TWO);
432 
433     x = (x < 0) ? 0 : x;
434     x = (x + static_cast<int32_t>(windowWidth_)) > static_cast<int32_t>(
435         screenWidth_) ? static_cast<int32_t>(screenWidth_ - windowWidth_) : x;
436 
437     y = (y < 0) ? 0 : y;
438     y = (y + static_cast<int32_t>(windowHeight_)) > static_cast<int32_t>(
439         screenHeight_) ? static_cast<int32_t>(screenHeight_ - windowHeight_) : y;
440 
441     windowRect.posX_ = x;
442     windowRect.posY_ = y;
443     return windowRect;
444 }
445 
CalculateAnchorOffset()446 void MagnificationWindow::CalculateAnchorOffset()
447 {
448     int32_t windowCenterX = windowRect_.posX_ + windowRect_.posX_ + static_cast<int32_t>(windowRect_.width_);
449     int32_t sourceCenterX = sourceRect_.posX_ + sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_);
450     anchorOffsetX_ = static_cast<int32_t>((windowCenterX - sourceCenterX) * HALF);
451 
452     int32_t windowCenterY = windowRect_.posY_ + windowRect_.posY_ + static_cast<int32_t>(windowRect_.height_);
453     int32_t sourceCenterY = sourceRect_.posY_ + sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_);
454     anchorOffsetY_ = static_cast<int32_t>((windowCenterY - sourceCenterY) * HALF);
455 }
456 
UpdateRelativeRect()457 void MagnificationWindow::UpdateRelativeRect()
458 {
459     int32_t posX = sourceRect_.posX_ - windowRect_.posX_;
460     if (posX < 0) {
461         posX = 0;
462     }
463 
464     int32_t deltaX = static_cast<int32_t>(windowRect_.width_) - static_cast<int32_t>(sourceRect_.width_);
465     if (posX > deltaX) {
466         posX = deltaX;
467     }
468     relativeRect_.posX_ = posX;
469 
470     int32_t posY = sourceRect_.posY_ - windowRect_.posY_;
471     if (posY < 0) {
472         posY = 0;
473     }
474 
475     int32_t deltaY = static_cast<int32_t>(windowRect_.height_) - static_cast<int32_t>(sourceRect_.height_);
476     if (posY > deltaY) {
477         posY = deltaY;
478     }
479     relativeRect_.posY_ = posY;
480     relativeRect_.width_ = sourceRect_.width_;
481     relativeRect_.height_ = sourceRect_.height_;
482 }
483 
AdjustMagnificationWindowPosition()484 void MagnificationWindow::AdjustMagnificationWindowPosition()
485 {
486     if (windowRect_.posX_ < 0) {
487         windowRect_.posX_ = 0;
488     }
489 
490     if (windowRect_.posY_ < 0) {
491         windowRect_.posY_ = 0;
492     }
493 
494     if (windowRect_.posX_ + static_cast<int32_t>(windowRect_.width_) > static_cast<int32_t>(screenWidth_)) {
495         windowRect_.posX_ = static_cast<int32_t>(screenWidth_) - static_cast<int32_t>(windowRect_.width_);
496     }
497 
498     if (windowRect_.posY_ + static_cast<int32_t>(windowRect_.height_) > static_cast<int32_t>(screenHeight_)) {
499         windowRect_.posY_ = static_cast<int32_t>(screenHeight_) - static_cast<int32_t>(windowRect_.height_);
500     }
501 }
502 
AdjustSourceWindowPosition()503 void MagnificationWindow::AdjustSourceWindowPosition()
504 {
505     if (sourceRect_.posX_ < windowRect_.posX_) {
506         sourceRect_.posX_ = windowRect_.posX_;
507     }
508 
509     if (sourceRect_.posY_ < windowRect_.posY_) {
510         sourceRect_.posY_ = windowRect_.posY_;
511     }
512 
513     int32_t windowX = windowRect_.posX_ + static_cast<int32_t>(windowRect_.width_);
514     if (sourceRect_.posX_ + static_cast<int32_t>(sourceRect_.width_) > windowX) {
515         sourceRect_.posX_ = windowX - static_cast<int32_t>(sourceRect_.width_);
516     }
517 
518     int32_t windowY = windowRect_.posY_ + static_cast<int32_t>(windowRect_.height_);
519     if (sourceRect_.posY_ + static_cast<int32_t>(sourceRect_.height_) > windowY) {
520         sourceRect_.posY_ = windowY - static_cast<int32_t>(sourceRect_.height_);
521     }
522 }
523 
IsTapOnHotArea(int32_t posX,int32_t posY)524 bool MagnificationWindow::IsTapOnHotArea(int32_t posX, int32_t posY)
525 {
526     if (!isMagnificationShowPart_) {
527         return false;
528     }
529     Rosen::Rect innerRect = {windowRect_.posX_ + static_cast<int32_t>(hotAreaWidth_),
530         windowRect_.posY_ + static_cast<int32_t>(hotAreaWidth_),
531         windowRect_.width_ - static_cast<uint32_t>(2 * hotAreaWidth_),
532         windowRect_.height_ - static_cast<uint32_t>(2 * hotAreaWidth_)};
533     Rosen::Rect outRect = {windowRect_.posX_ - static_cast<int32_t>(hotAreaWidth_),
534         windowRect_.posY_ - static_cast<int32_t>(hotAreaWidth_),
535         windowRect_.width_ + static_cast<uint32_t>(2 * hotAreaWidth_),
536         windowRect_.height_ + static_cast<uint32_t>(2 * hotAreaWidth_)};
537     return ExtUtils::IsInRect(posX, posY, outRect) && !(ExtUtils::IsInRect(posX, posY, innerRect));
538 }
539 
IsTapOnMagnificationWindow(int32_t posX,int32_t posY)540 bool MagnificationWindow::IsTapOnMagnificationWindow(int32_t posX, int32_t posY)
541 {
542     return ExtUtils::IsInRect(posX, posY, windowRect_);
543 }
FixSourceCenter(bool needFix)544 void MagnificationWindow::FixSourceCenter(bool needFix)
545 {
546     HILOG_DEBUG();
547     if (needFix == isFixSourceCenter_) {
548         return;
549     }
550 
551     isFixSourceCenter_ = needFix;
552     if (needFix) {
553         isFixSourceCenter_ = needFix;
554         float sourceCenterX = (sourceRect_.posX_ + sourceRect_.posX_ +
555             static_cast<int32_t>(sourceRect_.width_)) / static_cast<float>(DIVISOR_TWO);
556         float sourceCenterY = (sourceRect_.posY_ + sourceRect_.posY_ +
557             static_cast<int32_t>(sourceRect_.height_)) / static_cast<float>(DIVISOR_TWO);
558         fixedSourceCenter_ = {static_cast<int32_t>(sourceCenterX), static_cast<int32_t>(sourceCenterY)};
559     } else {
560         fixedSourceCenter_ = {0, 0};
561     }
562 }
563 
DrawRuoundRectFramePart()564 void MagnificationWindow::DrawRuoundRectFramePart()
565 {
566     if (surfaceNode_ == nullptr) {
567         HILOG_ERROR("get surfaceNode_ failed.");
568         return;
569     }
570 
571     if (canvasNode_ == nullptr) {
572         HILOG_ERROR("create canvasNode_ fail");
573         return;
574     }
575     surfaceNode_->SetAbilityBGAlpha(BG_ALPHA);
576     surfaceNode_->AddChild(canvasNode_, -1);
577     canvasNode_->SetBounds(0, 0, windowWidth_, windowHeight_);
578     canvasNode_->SetFrame(0, 0, windowWidth_, windowHeight_);
579     canvasNode_->SetPositionZ(Rosen::RSSurfaceNode::POINTER_WINDOW_POSITION_Z);
580     canvasNode_->SetRotation(0);
581 
582     auto canvas = canvasNode_->BeginRecording(windowWidth_, windowHeight_);
583     if (canvas == nullptr) {
584         HILOG_ERROR("get canvas fail");
585         return;
586     }
587     Rosen::Drawing::Pen pen;
588     pen.SetAntiAlias(true);
589     pen.SetColor(ORANGE_COLOR);
590     pen.SetWidth(PEN_WIDTH);
591     canvas->AttachPen(pen);
592     Rosen::Drawing::Path path;
593     path.AddRoundRect({ROUND_RECT_MARGIN, ROUND_RECT_MARGIN,
594         windowWidth_ - ROUND_RECT_MARGIN, windowHeight_ - ROUND_RECT_MARGIN},
595         CORNER_RADIUS, CORNER_RADIUS, Rosen::Drawing::PathDirection::CW_DIRECTION);
596     canvas->DrawPath(path);
597     canvas->DetachPen();
598 
599     Rosen::Drawing::Pen linePen;
600     linePen.SetAntiAlias(true);
601     linePen.SetColor(ORANGE_COLOR);
602     linePen.SetWidth(PEN_WIDTH);
603     canvas->AttachPen(linePen);
604     auto p1 = Rosen::Drawing::Point(BAR_START, windowHeight_ - barMargin_);
605     auto p2 = Rosen::Drawing::Point(BAR_END, windowHeight_ - barMargin_);
606     canvas->DrawLine(p1, p2);
607     canvas->DetachPen();
608 
609     Rosen::Drawing::Brush brush;
610     brush.SetAntiAlias(true);
611     brush.SetColor(ORANGE_COLOR);
612     canvas->AttachBrush(brush);
613     canvas->DrawCircle(p1, static_cast<float>(PEN_WIDTH / DIVISOR_TWO));
614     canvas->DrawCircle(p2, static_cast<float>(PEN_WIDTH / DIVISOR_TWO));
615     canvas->DetachBrush();
616     canvasNode_->FinishRecording();
617 }
618 
EnableMagnificationPart(int32_t centerX,int32_t centerY)619 void MagnificationWindow::EnableMagnificationPart(int32_t centerX, int32_t centerY)
620 {
621     HILOG_INFO("centerX = %{public}d, centerY = %{public}d.", centerX, centerY);
622     GetWindowParam();
623     if (window_ == nullptr) {
624         HILOG_DEBUG("window is null. need create.");
625         windowRect_ = GetWindowRectFromPointer(centerX, centerY);
626         CreateMagnificationWindow();
627     }
628 
629     if (window_ == nullptr) {
630         HILOG_ERROR("create window failed.");
631         return;
632     }
633     sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
634     CalculateAnchorOffset();
635     UpdateRelativeRect();
636     Rosen::WMError ret = window_->SetFrameRectForPartialZoomIn(relativeRect_);
637     if (ret != Rosen::WMError::WM_OK) {
638         HILOG_ERROR("Trigger magnification failed.");
639         ExtUtils::RecordMagnificationUnavailableEvent("Trigger magnification failed.");
640     }
641     DrawRuoundRectFramePart();
642     window_->Show();
643     FlushImplicitTransaction();
644     isMagnificationShowPart_ = true;
645 }
646 
DisableMagnificationPart(bool needClear)647 void MagnificationWindow::DisableMagnificationPart(bool needClear)
648 {
649     DisableMagnification(needClear);
650     anchorOffsetX_ = 0;
651     anchorOffsetY_ = 0;
652     isMagnificationShowPart_ = false;
653 }
654 
IsMagnificationShowPart()655 bool MagnificationWindow::IsMagnificationShowPart()
656 {
657     return isMagnificationShowPart_;
658 }
659 
SetScalePart(float scaleSpan)660 void MagnificationWindow::SetScalePart(float scaleSpan)
661 {
662     HILOG_DEBUG();
663     if (screenWidth_ == 0 || screenHeight_ == 0 || abs(screenSpan_) < EPS) {
664         HILOG_ERROR("screen param invalid.");
665         return;
666     }
667 
668     float ratio = scaleSpan / screenSpan_;
669     float tmpScale = scale_ + ratio * scale_;
670     if (tmpScale > MAX_SCALE) {
671         tmpScale = MAX_SCALE;
672     }
673     if (tmpScale < DEFAULT_SCALE) {
674         tmpScale = DEFAULT_SCALE;
675     }
676 
677     uint32_t newWidth = static_cast<uint32_t>(windowRect_.width_ / tmpScale);
678     uint32_t newHeight = static_cast<uint32_t>(windowRect_.height_ / tmpScale);
679     int32_t newPosX = fixedSourceCenter_.posX - static_cast<int32_t>(newWidth / DIVISOR_TWO);
680     int32_t newPosY = fixedSourceCenter_.posY - static_cast<int32_t>(newHeight / DIVISOR_TWO);
681 
682     Rosen::Rect tmpRect = {newPosX, newPosY, newWidth, newHeight};
683     if (!tmpRect.IsInsideOf(screenRect_)) {
684         HILOG_ERROR("sourceRect out of screenRect.");
685         return;
686     }
687 
688     if (window_ == nullptr) {
689         HILOG_ERROR("window_ is nullptr.");
690         return;
691     }
692 
693     sourceRect_ = tmpRect;
694     scale_ = tmpScale;
695     UpdateRelativeRect();
696     window_->SetFrameRectForPartialZoomIn(relativeRect_);
697     DrawRuoundRectFramePart();
698     FlushImplicitTransaction();
699     CalculateAnchorOffset();
700 }
701 
MoveMagnificationPart(int32_t deltaX,int32_t deltaY)702 void MagnificationWindow::MoveMagnificationPart(int32_t deltaX, int32_t deltaY)
703 {
704     if (window_ == nullptr) {
705         HILOG_ERROR("window is null.");
706         return;
707     }
708 
709     int32_t windowPosX = windowRect_.posX_;
710     int32_t sourcePosX = sourceRect_.posX_;
711 
712     if (abs(anchorOffsetX_) <= ANCHOR_OFFSET) {
713         windowPosX += deltaX;
714     }
715     sourcePosX += deltaX;
716 
717     int32_t windowPosY = windowRect_.posY_;
718     int32_t sourcePosY = sourceRect_.posY_;
719 
720     if (abs(anchorOffsetY_) <= ANCHOR_OFFSET) {
721         windowPosY += deltaY;
722     }
723     sourcePosY += deltaY;
724 
725     windowRect_.posX_ = windowPosX;
726     windowRect_.posY_ = windowPosY;
727     AdjustMagnificationWindowPosition();
728 
729     window_->MoveTo(windowRect_.posX_, windowRect_.posY_);
730 
731     sourceRect_.posX_ = sourcePosX;
732     sourceRect_.posY_ = sourcePosY;
733     AdjustSourceWindowPosition();
734     UpdateRelativeRect();
735     window_->SetFrameRectForPartialZoomIn(relativeRect_);
736     DrawRuoundRectFramePart();
737     FlushImplicitTransaction();
738     CalculateAnchorOffset();
739 }
740 
ShowMagnificationPart()741 void MagnificationWindow::ShowMagnificationPart()
742 {
743     int32_t centerX = static_cast<int32_t>(screenWidth_ / DIVISOR_TWO);
744     int32_t centerY = static_cast<int32_t>(screenHeight_ / DIVISOR_TWO);
745     EnableMagnificationPart(centerX, centerY);
746 }
747 
FollowFocuseElementPart(int32_t centerX,int32_t centerY)748 void MagnificationWindow::FollowFocuseElementPart(int32_t centerX, int32_t centerY)
749 {
750     HILOG_DEBUG();
751     if (window_ == nullptr) {
752         HILOG_ERROR("window_ is nullptr.");
753         return;
754     }
755     windowRect_ = GetWindowRectFromPointer(centerX, centerY);
756     sourceRect_ = GetSourceRectFromPointer(centerX, centerY);
757     window_->MoveTo(windowRect_.posX_, windowRect_.posY_);
758     UpdateRelativeRect();
759     window_->SetFrameRectForPartialZoomIn(relativeRect_);
760     DrawRuoundRectFramePart();
761     FlushImplicitTransaction();
762     CalculateAnchorOffset();
763 }
764 
RefreshWindowParamPart(RotationType type)765 void MagnificationWindow::RefreshWindowParamPart(RotationType type)
766 {
767     HILOG_DEBUG();
768     if (isMagnificationShowPart_) {
769         PointerPos center = GetRectCenter(windowRect_);
770         HILOG_INFO("need refresh window param.");
771         DisableMagnificationPart();
772         center = TransferCenter(type, center);
773         EnableMagnificationPart(center.posX, center.posY);
774     } else {
775         GetWindowParam();
776     }
777 }
778 
TransferCenter(RotationType type,PointerPos center)779 PointerPos MagnificationWindow::TransferCenter(RotationType type, PointerPos center)
780 {
781     if (type == RotationType::NO_CHANGE || type == RotationType::UNKNOWN) {
782         return center;
783     }
784     GetWindowParam();
785     if (type == RotationType::LEFT_ROTATE) {
786         return {center.posY, static_cast<int32_t>(screenHeight_) - center.posX};
787     }
788     if (type == RotationType::RIGHT_ROTATE) {
789         return {screenWidth_ - center.posY, center.posX};
790     }
791     if (type == RotationType::FLIP_VERTICAL) {
792         return {screenWidth_ - center.posX, screenHeight_ - center.posY};
793     }
794     return center;
795 }
796 
EnableMagnification(uint32_t magnificationType,int32_t posX,int32_t posY)797 extern "C" API_EXPORT void EnableMagnification(uint32_t magnificationType, int32_t posX, int32_t posY)
798 {
799     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
800         instance.EnableMagnificationFull(posX, posY);
801         return;
802     }
803     if (magnificationType == WINDOW_MAGNIFICATION) {
804         instance.EnableMagnificationPart(posX, posY);
805         return;
806     }
807     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
808 }
809 
DisableMagnification(uint32_t magnificationType,bool needClear)810 extern "C" API_EXPORT void DisableMagnification(uint32_t magnificationType, bool needClear)
811 {
812     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
813         instance.DisableMagnificationFull(needClear);
814         return;
815     }
816     if (magnificationType == WINDOW_MAGNIFICATION) {
817         instance.DisableMagnificationPart(needClear);
818         return;
819     }
820     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
821 }
822 
SetScale(uint32_t magnificationType,float scaleSpan)823 extern "C" API_EXPORT void SetScale(uint32_t magnificationType, float scaleSpan)
824 {
825     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
826         instance.SetScaleFull(scaleSpan);
827         return;
828     }
829     if (magnificationType == WINDOW_MAGNIFICATION) {
830         instance.SetScalePart(scaleSpan);
831         return;
832     }
833     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
834 }
835 
MoveMagnification(uint32_t magnificationType,int32_t deltaX,int32_t deltaY)836 extern "C" API_EXPORT void MoveMagnification(uint32_t magnificationType, int32_t deltaX, int32_t deltaY)
837 {
838     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
839         instance.MoveMagnificationFull(deltaX, deltaY);
840         return;
841     }
842     if (magnificationType == WINDOW_MAGNIFICATION) {
843         instance.MoveMagnificationPart(deltaX, deltaY);
844         return;
845     }
846     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
847 }
848 
ConvertGesture(uint32_t type,PointerPos coordinates)849 extern "C" API_EXPORT PointerPos ConvertGesture(uint32_t type, PointerPos coordinates)
850 {
851     return instance.ConvertGesture(type, coordinates);
852 }
853 
ConvertCoordinates(int32_t posX,int32_t posY)854 extern "C" API_EXPORT PointerPos ConvertCoordinates(int32_t posX, int32_t posY)
855 {
856     return instance.ConvertCoordinates(posX, posY);
857 }
858 
CheckTapOnHotArea(int32_t posX,int32_t posY)859 extern "C" API_EXPORT uint32_t CheckTapOnHotArea(int32_t posX, int32_t posY)
860 {
861     return instance.CheckTapOnHotArea(posX, posY);
862 }
863 
GetScale()864 extern "C" API_EXPORT float GetScale()
865 {
866     return instance.GetScale();
867 }
868 
IsMagnificationWindowShow(uint32_t magnificationType)869 extern "C" API_EXPORT bool IsMagnificationWindowShow(uint32_t magnificationType)
870 {
871     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
872         return instance.IsMagnificationShowFull();
873     }
874     if (magnificationType == WINDOW_MAGNIFICATION) {
875         return instance.IsMagnificationShowPart();
876     }
877     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
878     return false;
879 }
880 
FollowFocuseElement(uint32_t magnificationType,int32_t centerX,int32_t centerY)881 extern "C" API_EXPORT void FollowFocuseElement(uint32_t magnificationType, int32_t centerX, int32_t centerY)
882 {
883     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
884         instance.FollowFocuseElementFull(centerX, centerY);
885         return;
886     }
887     if (magnificationType == WINDOW_MAGNIFICATION) {
888         instance.FollowFocuseElementPart(centerX, centerY);
889         return;
890     }
891     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
892 }
893 
GetSourceCenter()894 extern "C" API_EXPORT PointerPos GetSourceCenter()
895 {
896     return instance.GetSourceCenter();
897 }
898 
ShowMagnification(uint32_t magnificationType)899 extern "C" API_EXPORT void ShowMagnification(uint32_t magnificationType)
900 {
901     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
902         instance.ShowMagnificationFull();
903         return;
904     }
905     if (magnificationType == WINDOW_MAGNIFICATION) {
906         instance.ShowMagnificationPart();
907         return;
908     }
909     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
910 }
911 
RefreshWindowParam(uint32_t magnificationType,RotationType type)912 extern "C" API_EXPORT void RefreshWindowParam(uint32_t magnificationType, RotationType type)
913 {
914     if (magnificationType == FULL_SCREEN_MAGNIFICATION) {
915         instance.RefreshWindowParamFull(type);
916         return;
917     }
918     if (magnificationType == WINDOW_MAGNIFICATION) {
919         instance.RefreshWindowParamPart(type);
920         return;
921     }
922     HILOG_DEBUG("invalid type = %{public}d", magnificationType);
923 }
924 
IsTapOnHotArea(int32_t posX,int32_t posY)925 extern "C" API_EXPORT bool IsTapOnHotArea(int32_t posX, int32_t posY)
926 {
927     return instance.IsTapOnHotArea(posX, posY);
928 }
929 
IsTapOnMagnificationWindow(int32_t posX,int32_t posY)930 extern "C" API_EXPORT bool IsTapOnMagnificationWindow(int32_t posX, int32_t posY)
931 {
932     return instance.IsTapOnMagnificationWindow(posX, posY);
933 }
934 
FixSourceCenter(bool needFix)935 extern "C" API_EXPORT void FixSourceCenter(bool needFix)
936 {
937     instance.FixSourceCenter(needFix);
938 }
939 
InitMagnificationParam(float scale)940 extern "C" API_EXPORT void InitMagnificationParam(float scale)
941 {
942     instance.InitMagnificationParam(scale);
943 }
944 }
945 }
946 // LCOV_EXCL_STOP