• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022-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 "display_cutout_controller.h"
17 #include <screen_manager/screen_types.h>
18 #include "display_manager_service_inner.h"
19 #include "dm_common.h"
20 
21 namespace OHOS {
22 namespace Rosen {
23 namespace {
24     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_DISPLAY, "DisplayCutoutController"};
25     const uint32_t NO_WATERFALL_DISPLAY_COMPRESSION_SIZE = 0;
26 }
27 
28 bool DisplayCutoutController::isWaterfallDisplay_ = false;
29 bool DisplayCutoutController::isWaterfallAreaCompressionEnableWhenHorizontal_ = false;
30 uint32_t DisplayCutoutController::waterfallAreaCompressionSizeWhenHorizontal_ = 0;
31 
SetBuiltInDisplayCutoutSvgPath(const std::string & svgPath)32 void DisplayCutoutController::SetBuiltInDisplayCutoutSvgPath(const std::string& svgPath)
33 {
34     SetCutoutSvgPath(0, svgPath);
35 }
36 
SetIsWaterfallDisplay(bool isWaterfallDisplay)37 void DisplayCutoutController::SetIsWaterfallDisplay(bool isWaterfallDisplay)
38 {
39     WLOGFI("Set isWaterfallDisplay: %{public}u", isWaterfallDisplay);
40     isWaterfallDisplay_ = isWaterfallDisplay;
41 }
42 
IsWaterfallDisplay()43 bool DisplayCutoutController::IsWaterfallDisplay()
44 {
45     return isWaterfallDisplay_;
46 }
47 
SetCurvedScreenBoundary(std::vector<int> curvedScreenBoundary)48 void DisplayCutoutController::SetCurvedScreenBoundary(std::vector<int> curvedScreenBoundary)
49 {
50     while (curvedScreenBoundary.size() < 4) { // 4 directions.
51         curvedScreenBoundary.emplace_back(0);
52     }
53     WLOGFI("Set curvedScreenBoundary");
54     curvedScreenBoundary_ = curvedScreenBoundary;
55 }
56 
SetCutoutSvgPath(DisplayId displayId,const std::string & svgPath)57 void DisplayCutoutController::SetCutoutSvgPath(DisplayId displayId, const std::string& svgPath)
58 {
59     WLOGFI("Set SvgPath: %{public}s", svgPath.c_str());
60     if (svgPaths_.count(displayId) == 1) {
61         svgPaths_[displayId].emplace_back(svgPath);
62     } else {
63         std::vector<std::string> pathVec;
64         pathVec.emplace_back(svgPath);
65         svgPaths_[displayId] = pathVec;
66     }
67     DMRect boundingRect = CalcCutoutBoundingRect(svgPath);
68     if (boundingRects_.count(displayId) == 1) {
69         boundingRects_[displayId].emplace_back(boundingRect);
70     } else {
71         std::vector<DMRect> rectVec;
72         rectVec.emplace_back(boundingRect);
73         boundingRects_[displayId] = rectVec;
74     }
75 }
76 
GetCutoutInfo(DisplayId displayId)77 sptr<CutoutInfo> DisplayCutoutController::GetCutoutInfo(DisplayId displayId)
78 {
79     WLOGFD("Get Cutout Info");
80     std::vector<DMRect> boundingRects;
81     WaterfallDisplayAreaRects waterfallDisplayAreaRects;
82     if (boundingRects_.count(displayId) == 1) {
83         TransferBoundingRectsByRotation(displayId, boundingRects);
84     }
85     if (displayId == DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId()) {
86         CalcBuiltInDisplayWaterfallRects();
87         waterfallDisplayAreaRects = waterfallDisplayAreaRects_;
88     }
89     sptr<CutoutInfo> cutoutInfo(new CutoutInfo(boundingRects, waterfallDisplayAreaRects));
90     return cutoutInfo;
91 }
92 
CheckBoundingRectsBoundary(DisplayId displayId,std::vector<DMRect> & boundingRects)93 void DisplayCutoutController::CheckBoundingRectsBoundary(DisplayId displayId, std::vector<DMRect>& boundingRects)
94 {
95     sptr<SupportedScreenModes> modes =
96         DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(displayId);
97     if (modes == nullptr) {
98         WLOGFE("DisplayId is invalid");
99         return;
100     }
101     uint32_t displayHeight = modes->height_;
102     uint32_t displayWidth = modes->width_;
103     for (auto iter = boundingRects.begin(); iter != boundingRects.end();) {
104         DMRect boundingRect = *iter;
105         if (boundingRect.posX_ < 0 || boundingRect.posY_ < 0 ||
106             static_cast<int32_t>(boundingRect.width_) + boundingRect.posX_ > static_cast<int32_t>(displayWidth) ||
107             static_cast<int32_t>(boundingRect.height_) + boundingRect.posY_ > static_cast<int32_t>(displayHeight) ||
108             boundingRect.width_ > displayWidth || boundingRect.height_ > displayHeight ||
109             boundingRect.IsUninitializedRect()) {
110             WLOGFE("boundingRect boundary is invalid");
111             iter = boundingRects.erase(iter);
112         } else {
113             iter++;
114         }
115     }
116 }
117 
CalcCutoutBoundingRect(std::string svgPath)118 DMRect DisplayCutoutController::CalcCutoutBoundingRect(std::string svgPath)
119 {
120     DMRect emptyRect = {0, 0, 0, 0};
121     SkPath skCutoutSvgPath;
122     if (!SkParsePath::FromSVGString(svgPath.c_str(), &skCutoutSvgPath)) {
123         WLOGFE("Parse svg string path failed.");
124         return emptyRect;
125     }
126     SkRect skRect = skCutoutSvgPath.computeTightBounds();
127     if (skRect.isEmpty()) {
128         WLOGFW("Get empty skRect");
129         return emptyRect;
130     }
131     SkIRect skiRect = skRect.roundOut();
132     if (skiRect.isEmpty()) {
133         WLOGFW("Get empty skiRect");
134         return emptyRect;
135     }
136     int32_t left = static_cast<int32_t>(skiRect.left());
137     int32_t top = static_cast<int32_t>(skiRect.top());
138     uint32_t width = static_cast<uint32_t>(skiRect.width());
139     uint32_t height = static_cast<uint32_t>(skiRect.height());
140     WLOGFI("calc rect from path,[%{public}d, %{public}d, %{public}u, %{public}u]", left, top, width, height);
141     DMRect cutoutMinOuterRect = {.posX_ = left, .posY_ = top, .width_ = width, .height_ = height};
142     return cutoutMinOuterRect;
143 }
144 
CalcBuiltInDisplayWaterfallRects()145 void DisplayCutoutController::CalcBuiltInDisplayWaterfallRects()
146 {
147     WaterfallDisplayAreaRects emptyRects = {};
148     if (!isWaterfallDisplay_) {
149         WLOGFI("not waterfall display");
150         waterfallDisplayAreaRects_ = emptyRects;
151         return;
152     }
153     if (curvedScreenBoundary_.empty()) {
154         WLOGFI("curved screen boundary is empty");
155         waterfallDisplayAreaRects_ = emptyRects;
156         return;
157     }
158     uint32_t left = static_cast<uint32_t>(curvedScreenBoundary_[0]);
159     uint32_t top = static_cast<uint32_t>(curvedScreenBoundary_[1]);
160     uint32_t right = static_cast<uint32_t>(curvedScreenBoundary_[2]);
161     uint32_t bottom = static_cast<uint32_t>(curvedScreenBoundary_[3]);
162     if (left == 0 && top == 0 && right == 0 && bottom == 0) {
163         waterfallDisplayAreaRects_ = emptyRects;
164         return;
165     }
166     sptr<SupportedScreenModes> modes =
167         DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(
168             DisplayManagerServiceInner::GetInstance().GetDefaultDisplayId());
169     if (!modes) {
170         WLOGE("support screen modes get failed");
171         waterfallDisplayAreaRects_ = emptyRects;
172         return;
173     }
174     uint32_t displayHeight = modes->height_;
175     uint32_t displayWidth = modes->width_;
176 
177     if ((left > displayWidth / 2) || (right > displayWidth / 2) || // invalid if more than 1/2 width
178         (top > displayHeight / 2) || (bottom > displayHeight / 2)) { // invalid if more than 1/2 height
179         WLOGFE("Curved screen boundary data is not valid.");
180         waterfallDisplayAreaRects_ = emptyRects;
181         return;
182     }
183     CalcBuiltInDisplayWaterfallRectsByRotation(
184         DisplayManagerServiceInner::GetInstance().GetDefaultDisplay()->GetRotation(),
185         displayHeight, displayWidth);
186 }
187 
CalcBuiltInDisplayWaterfallRectsByRotation(Rotation rotation,uint32_t displayHeight,uint32_t displayWidth)188 void DisplayCutoutController::CalcBuiltInDisplayWaterfallRectsByRotation(
189     Rotation rotation, uint32_t displayHeight, uint32_t displayWidth)
190 {
191     uint32_t left = static_cast<uint32_t>(curvedScreenBoundary_[0]);
192     uint32_t top = static_cast<uint32_t>(curvedScreenBoundary_[1]);
193     uint32_t right = static_cast<uint32_t>(curvedScreenBoundary_[2]);
194     uint32_t bottom = static_cast<uint32_t>(curvedScreenBoundary_[3]);
195     switch (rotation) {
196         case Rotation::ROTATION_0: {
197             DMRect leftRect = CreateWaterfallRect(0, 0, left, displayHeight);
198             DMRect topRect = CreateWaterfallRect(0, 0, displayWidth, top);
199             DMRect rightRect = CreateWaterfallRect(displayWidth - right, 0, right, displayHeight);
200             DMRect bottomRect = CreateWaterfallRect(0, displayHeight - bottom, displayWidth, bottom);
201             waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect};
202             return;
203         }
204         case Rotation::ROTATION_90: {
205             DMRect leftRect = CreateWaterfallRect(0, 0, bottom, displayWidth);
206             DMRect topRect = CreateWaterfallRect(0, 0, displayHeight, left);
207             DMRect rightRect = CreateWaterfallRect(displayHeight - top, 0, top, displayWidth);
208             DMRect bottomRect = CreateWaterfallRect(0, displayWidth - right, displayHeight, right);
209             waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect};
210             return;
211         }
212         case Rotation::ROTATION_180: {
213             DMRect leftRect = CreateWaterfallRect(0, 0, right, displayHeight);
214             DMRect topRect = CreateWaterfallRect(0, 0, bottom, displayWidth);
215             DMRect rightRect = CreateWaterfallRect(displayWidth - left, 0, left, displayHeight);
216             DMRect bottomRect = CreateWaterfallRect(0, displayHeight - top, displayWidth, top);
217             waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect};
218             return;
219         }
220         case Rotation::ROTATION_270: {
221             DMRect leftRect = CreateWaterfallRect(0, 0, top, displayWidth);
222             DMRect topRect = CreateWaterfallRect(0, 0, displayHeight, right);
223             DMRect rightRect = CreateWaterfallRect(displayHeight - bottom, 0, bottom, displayWidth);
224             DMRect bottomRect = CreateWaterfallRect(0, displayWidth - left, displayHeight, left);
225             waterfallDisplayAreaRects_ = WaterfallDisplayAreaRects {leftRect, topRect, rightRect, bottomRect};
226             return;
227         }
228         default: {
229         }
230     }
231 }
232 
TransferBoundingRectsByRotation(DisplayId displayId,std::vector<DMRect> & boundingRects)233 void DisplayCutoutController::TransferBoundingRectsByRotation(DisplayId displayId, std::vector<DMRect>& boundingRects)
234 {
235     std::vector<DMRect> resultVec;
236     if (boundingRects_.count(displayId) == 0) {
237         boundingRects = resultVec;
238         return;
239     }
240     std::vector<DMRect> displayBoundingRects = boundingRects_[displayId];
241     if (displayBoundingRects.empty()) {
242         boundingRects = resultVec;
243         return;
244     }
245     sptr<DisplayInfo> displayInfo = DisplayManagerServiceInner::GetInstance().GetDisplayById(displayId);
246     if (!displayInfo) {
247         WLOGFE("display invaild");
248         return;
249     }
250     Rotation currentRotation = displayInfo->GetRotation();
251     CheckBoundingRectsBoundary(displayId, displayBoundingRects);
252     if (currentRotation == Rotation::ROTATION_0) {
253         boundingRects = displayBoundingRects;
254         return;
255     }
256     sptr<SupportedScreenModes> modes =
257         DisplayManagerServiceInner::GetInstance().GetScreenModesByDisplayId(displayId);
258     if (!modes) {
259         WLOGE("support screen modes get failed");
260         return;
261     }
262     uint32_t displayHeight = modes->height_;
263     uint32_t displayWidth = modes->width_;
264 
265     switch (currentRotation) {
266         case Rotation::ROTATION_90: {
267             for (DMRect rect : displayBoundingRects) {
268                 resultVec.emplace_back(DMRect {.posX_ = displayHeight - rect.posY_ - rect.height_,
269                     .posY_ = rect.posX_, .width_ = rect.height_, .height_ = rect.width_});
270             }
271             break;
272         }
273         case Rotation::ROTATION_180: {
274             for (DMRect rect : displayBoundingRects) {
275                 resultVec.emplace_back(DMRect {displayWidth - rect.posX_ - rect.width_,
276                     displayHeight - rect.posY_ - rect.height_, rect.width_, rect.height_});
277             }
278             break;
279         }
280         case Rotation::ROTATION_270: {
281             for (DMRect rect : displayBoundingRects) {
282                 resultVec.emplace_back(DMRect {rect.posY_, displayWidth - rect.posX_ - rect.width_,
283                     rect.height_, rect.width_});
284             }
285             break;
286         }
287         default: {
288         }
289     }
290     boundingRects = resultVec;
291 }
292 
CreateWaterfallRect(uint32_t left,uint32_t top,uint32_t width,uint32_t height)293 DMRect DisplayCutoutController::CreateWaterfallRect(uint32_t left, uint32_t top, uint32_t width, uint32_t height)
294 {
295     if (width == 0 || height == 0) {
296         return DMRect {0, 0, 0, 0};
297     }
298     return DMRect {left, top, width, height};
299 }
300 
SetWaterfallAreaCompressionEnableWhenHorzontal(bool isEnable)301 void DisplayCutoutController::SetWaterfallAreaCompressionEnableWhenHorzontal(bool isEnable)
302 {
303     isWaterfallAreaCompressionEnableWhenHorizontal_ = isEnable;
304 }
305 
SetWaterfallAreaCompressionSizeWhenHorizontal(uint32_t size)306 void DisplayCutoutController::SetWaterfallAreaCompressionSizeWhenHorizontal(uint32_t size)
307 {
308     waterfallAreaCompressionSizeWhenHorizontal_ = size;
309 }
310 
IsWaterfallAreaCompressionEnableWhenHorizontal()311 bool DisplayCutoutController::IsWaterfallAreaCompressionEnableWhenHorizontal()
312 {
313     return isWaterfallDisplay_ && isWaterfallAreaCompressionEnableWhenHorizontal_;
314 }
315 
GetWaterfallAreaCompressionSizeWhenHorizontal()316 uint32_t DisplayCutoutController::GetWaterfallAreaCompressionSizeWhenHorizontal()
317 {
318     if (!isWaterfallDisplay_ || !isWaterfallAreaCompressionEnableWhenHorizontal_) {
319         WLOGFW("Not waterfall display or not enable waterfall compression");
320         return NO_WATERFALL_DISPLAY_COMPRESSION_SIZE;
321     }
322     return waterfallAreaCompressionSizeWhenHorizontal_;
323 }
324 } // Rosen
325 } // OHOS
326