1 /*
2 * Copyright (c) 2021-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 "core/components/common/painter/rosen_scroll_bar_painter.h"
17
18 #ifndef USE_ROSEN_DRAWING
19 #include "include/core/SkCanvas.h"
20 #include "include/core/SkPaint.h"
21 #else
22 #include "core/components_ng/render/drawing.h"
23 #endif
24
25 namespace OHOS::Ace {
26 namespace {
27
28 constexpr double FULL_ALPHA = 255.0;
29 #ifdef USE_ROSEN_DRAWING
30 constexpr float FLOAT_HALF = 0.5f;
31 #endif
32
33 } // namespace
34
35 #ifndef USE_ROSEN_DRAWING
PaintBar(SkCanvas * canvas,const Offset & offset,const Rect & paintRect,const RefPtr<ScrollBar> & scrollBar,const Offset & globalOffset,int32_t alpha)36 void RosenScrollBarPainter::PaintBar(SkCanvas* canvas, const Offset& offset, const Rect& paintRect,
37 const RefPtr<ScrollBar>& scrollBar, const Offset& globalOffset, int32_t alpha)
38 #else
39 void RosenScrollBarPainter::PaintBar(RSCanvas* canvas, const Offset& offset,
40 const Rect& paintRect, const RefPtr<ScrollBar>& scrollBar, const Offset& globalOffset, int32_t alpha)
41 #endif
42 {
43 if ((canvas != nullptr) && scrollBar && scrollBar->NeedScrollBar()) {
44 if (scrollBar->GetShapeMode() == ShapeMode::RECT) {
45 PaintRectBar(canvas, offset, scrollBar, alpha);
46 } else {
47 PaintCircleBar(canvas, globalOffset, paintRect, scrollBar);
48 }
49 }
50 }
51
52 #ifndef USE_ROSEN_DRAWING
PaintCircleBar(SkCanvas * canvas,const Offset & offset,const Rect & paintRect,const RefPtr<ScrollBar> & scrollBar)53 void RosenScrollBarPainter::PaintCircleBar(
54 SkCanvas* canvas, const Offset& offset, const Rect& paintRect, const RefPtr<ScrollBar>& scrollBar)
55 {
56 if (canvas && scrollBar->GetTrickSweepAngle() > 0.0) {
57 SkPaint paint;
58 paint.setBlendMode(SkBlendMode::kSrcOver);
59 paint.setAntiAlias(true);
60 paint.setStyle(SkPaint::Style::kStroke_Style);
61 paint.setStrokeWidth(scrollBar->GetNormalWidthToPx());
62 paint.setStrokeCap(SkPaint::kRound_Cap);
63
64 auto rootSize = scrollBar->GetRootSize();
65 // do not draw scrollbar when central is out of scroll viewport
66 if (rootSize.Height() * SK_ScalarHalf < offset.GetY() ||
67 rootSize.Height() * SK_ScalarHalf > offset.GetY() + paintRect.Height()) {
68 return;
69 }
70 double scrollBarWidth = scrollBar->GetNormalWidthToPx();
71 double diameter = rootSize.Width() - scrollBarWidth;
72 SkRect arcRect =
73 SkRect::MakeXYWH(scrollBarWidth * SK_ScalarHalf, scrollBarWidth * SK_ScalarHalf, diameter, diameter);
74 // paint background
75 double deltaAngle = scrollBar->GetBottomAngle() - scrollBar->GetTopAngle();
76 paint.setColor(scrollBar->GetBackgroundColor().GetValue());
77 if (scrollBar->GetPositionMode() == PositionMode::LEFT) {
78 canvas->drawArc(arcRect, deltaAngle * SK_ScalarHalf - STRAIGHT_ANGLE, -deltaAngle, false, paint);
79 } else {
80 canvas->drawArc(arcRect, -deltaAngle * SK_ScalarHalf, deltaAngle, false, paint);
81 }
82
83 // paint foreground
84 paint.setColor(scrollBar->GetForegroundColor().GetValue());
85 canvas->drawArc(arcRect, scrollBar->GetTrickStartAngle(), scrollBar->GetTrickSweepAngle(), false, paint);
86 }
87 }
88 #else
PaintCircleBar(RSCanvas * canvas,const Offset & offset,const Rect & paintRect,const RefPtr<ScrollBar> & scrollBar)89 void RosenScrollBarPainter::PaintCircleBar(RSCanvas* canvas, const Offset& offset,
90 const Rect& paintRect, const RefPtr<ScrollBar>& scrollBar)
91 {
92 if (canvas && scrollBar->GetTrickSweepAngle() > 0.0) {
93 RSPen pen;
94 pen.SetBlendMode(RSBlendMode::SRC_OVER);
95 pen.SetAntiAlias(true);
96 pen.SetWidth(scrollBar->GetNormalWidthToPx());
97 pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
98
99 auto rootSize = scrollBar->GetRootSize();
100 // do not draw scrollbar when central is out of scroll viewport
101 if (rootSize.Height() * FLOAT_HALF < offset.GetY() ||
102 rootSize.Height() * FLOAT_HALF > offset.GetY() + paintRect.Height()) {
103 return;
104 }
105 double scrollBarWidth = scrollBar->GetNormalWidthToPx();
106 double diameter = rootSize.Width() - scrollBarWidth;
107 RSRect arcRect = RSRect(
108 scrollBarWidth * FLOAT_HALF,
109 scrollBarWidth * FLOAT_HALF,
110 diameter + scrollBarWidth * FLOAT_HALF,
111 diameter + scrollBarWidth * FLOAT_HALF);
112 // paint background
113 double deltaAngle = scrollBar->GetBottomAngle() - scrollBar->GetTopAngle();
114 pen.SetColor(scrollBar->GetBackgroundColor().GetValue());
115 canvas->AttachPen(pen);
116 if (scrollBar->GetPositionMode() == PositionMode::LEFT) {
117 canvas->DrawArc(arcRect, deltaAngle * FLOAT_HALF - STRAIGHT_ANGLE, -deltaAngle);
118 } else {
119 canvas->DrawArc(arcRect, -deltaAngle * FLOAT_HALF, deltaAngle);
120 }
121 canvas->DetachPen();
122
123 // paint foreground
124 pen.SetColor(scrollBar->GetForegroundColor().GetValue());
125 canvas->AttachPen(pen);
126 canvas->DrawArc(arcRect, scrollBar->GetTrickStartAngle(), scrollBar->GetTrickSweepAngle());
127 canvas->DetachPen();
128 }
129 }
130 #endif
131
132 #ifndef USE_ROSEN_DRAWING
PaintRectBar(SkCanvas * canvas,const Offset & offset,const RefPtr<ScrollBar> & scrollBar,int32_t alpha)133 void RosenScrollBarPainter::PaintRectBar(
134 SkCanvas* canvas, const Offset& offset, const RefPtr<ScrollBar>& scrollBar, int32_t alpha)
135 {
136 Rect activeRect = scrollBar->GetActiveRect();
137 Rect barRect = scrollBar->GetBarRect();
138 if (canvas && !NearZero(activeRect.Height()) && !NearZero(barRect.Height())) {
139 SkPaint paint;
140 paint.setBlendMode(SkBlendMode::kSrcOver);
141 paint.setAntiAlias(true);
142 paint.setStyle(SkPaint::Style::kStrokeAndFill_Style);
143 paint.setStrokeCap(SkPaint::kRound_Cap);
144
145 // paint background
146 SkRect backgroundRect = SkRect::MakeLTRB(barRect.Left(), barRect.Top(), barRect.Right(), barRect.Bottom());
147 paint.setColor(scrollBar->GetBackgroundColor().GetValue());
148 double filletRadius = backgroundRect.width() * SK_ScalarHalf;
149 canvas->drawRoundRect(backgroundRect, filletRadius, filletRadius, paint);
150
151 // paint foreground
152 paint.setColor(scrollBar->GetForegroundColor().BlendOpacity(alpha / FULL_ALPHA).GetValue());
153 SkRect foregroundRect =
154 SkRect::MakeLTRB(activeRect.Left(), activeRect.Top(), activeRect.Right(), activeRect.Bottom());
155 canvas->drawRoundRect(foregroundRect, filletRadius, filletRadius, paint);
156 RenderScrollBarBoundary(canvas, activeRect.GetOffset(), activeRect.Width(), activeRect.Height());
157 }
158 }
159 #else
PaintRectBar(RSCanvas * canvas,const Offset & offset,const RefPtr<ScrollBar> & scrollBar,int32_t alpha)160 void RosenScrollBarPainter::PaintRectBar(
161 RSCanvas* canvas, const Offset& offset, const RefPtr<ScrollBar>& scrollBar, int32_t alpha)
162 {
163 Rect activeRect = scrollBar->GetActiveRect();
164 Rect barRect = scrollBar->GetBarRect();
165 if (canvas && !NearZero(activeRect.Height()) && !NearZero(barRect.Height())) {
166 RSPen pen;
167 pen.SetBlendMode(RSBlendMode::SRC_OVER);
168 pen.SetAntiAlias(true);
169 pen.SetCapStyle(RSPen::CapStyle::ROUND_CAP);
170 RSBrush brush;
171 brush.SetBlendMode(RSBlendMode::SRC_OVER);
172 brush.SetAntiAlias(true);
173
174 // paint background
175 RSRect backgroundRect = RSRect(
176 barRect.Left(), barRect.Top(), barRect.Right(), barRect.Bottom());
177 pen.SetColor(scrollBar->GetBackgroundColor().GetValue());
178 brush.SetColor(scrollBar->GetBackgroundColor().GetValue());
179 double filletRadius = backgroundRect.GetWidth() * FLOAT_HALF;
180 canvas->AttachPen(pen);
181 canvas->AttachBrush(brush);
182 RSRoundRect backRoundRect(backgroundRect, filletRadius, filletRadius);
183 canvas->DrawRoundRect(backRoundRect);
184 canvas->DetachPen();
185 canvas->DetachBrush();
186
187 // paint foreground
188 pen.SetColor(scrollBar->GetForegroundColor().BlendOpacity(alpha / FULL_ALPHA).GetValue());
189 brush.SetColor(scrollBar->GetForegroundColor().BlendOpacity(alpha / FULL_ALPHA).GetValue());
190 RSRect foregroundRect = RSRect(
191 activeRect.Left(), activeRect.Top(), activeRect.Right(), activeRect.Bottom());
192 RSRoundRect foreRoundRect(foregroundRect, filletRadius, filletRadius);
193 canvas->AttachPen(pen);
194 canvas->AttachBrush(brush);
195 canvas->DrawRoundRect(foreRoundRect);
196 canvas->DetachPen();
197 canvas->DetachBrush();
198 RenderScrollBarBoundary(canvas, activeRect.GetOffset(), activeRect.Width(), activeRect.Height());
199 }
200 }
201 #endif
202
203 #ifndef USE_ROSEN_DRAWING
RenderScrollBarBoundary(SkCanvas * canvas,const Offset & offset,double width,double height)204 void RosenScrollBarPainter::RenderScrollBarBoundary(SkCanvas* canvas, const Offset& offset, double width, double height)
205 #else
206 void RosenScrollBarPainter::RenderScrollBarBoundary(RSCanvas* canvas, const Offset& offset,
207 double width, double height)
208 #endif
209 {
210 if (SystemProperties::GetDebugBoundaryEnabled()) {
211 if (canvas == nullptr) {
212 LOGE("Paint canvas is null.");
213 return;
214 }
215 Size layoutSize;
216 layoutSize.SetWidth(width);
217 layoutSize.SetHeight(height);
218 DebugBoundaryPainter::PaintDebugBoundary(canvas, offset, layoutSize);
219 DebugBoundaryPainter::PaintDebugCorner(canvas, offset, layoutSize);
220 }
221 }
222
223 } // namespace OHOS::Ace