1 /*
2 * Copyright (c) 2022 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 "draw/draw_canvas.h"
17 #include "common/typed_text.h"
18 #include "draw/clip_utils.h"
19 #include "gfx_utils/diagram/depiction/depict_curve.h"
20 #include "gfx_utils/diagram/spancolorfill/fill_gradient.h"
21 #include "gfx_utils/diagram/spancolorfill/fill_interpolator.h"
22
23 namespace OHOS {
24 /**
25 * Renders monochrome polygon paths and fills
26 */
RenderSolid(const Paint & paint,RasterizerScanlineAntialias & rasterizer,RenderBase & renBase,const bool & isStroke)27 void RenderSolid(const Paint& paint, RasterizerScanlineAntialias& rasterizer, RenderBase& renBase, const bool& isStroke)
28 {
29 GeometryScanline scanline;
30 Rgba8T color;
31 DrawCanvas::RenderBlendSolid(paint, color, isStroke);
32 RenderScanlinesAntiAliasSolid(rasterizer, scanline, renBase, color);
33 }
34
35 #if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
DoRender(BufferInfo & gfxDstBuffer,void * param,const Paint & paint,const Rect & rect,const Rect & invalidatedArea,const Style & style,const bool & isStroke)36 void DrawCanvas::DoRender(BufferInfo& gfxDstBuffer,
37 void* param,
38 const Paint& paint,
39 const Rect& rect,
40 const Rect& invalidatedArea,
41 const Style& style,
42 const bool& isStroke)
43 {
44 if (param == nullptr) {
45 return;
46 }
47 #if defined(GRAPHIC_ENABLE_SHADOW_EFFECT_FLAG) && GRAPHIC_ENABLE_SHADOW_EFFECT_FLAG
48 if (paint.HaveShadow()) {
49 DrawCanvas::DoDrawShadow(gfxDstBuffer, param, paint, rect, invalidatedArea, style, isStroke);
50 }
51 #endif
52 TransAffine transform;
53 RenderBuffer renderBuffer;
54 InitRenderAndTransform(gfxDstBuffer, renderBuffer, rect, transform, style, paint);
55
56 RasterizerScanlineAntialias rasterizer;
57 GeometryScanline scanline;
58
59 PathParam* pathParam = static_cast<PathParam*>(param);
60 rasterizer.ClipBox(0, 0, gfxDstBuffer.width, gfxDstBuffer.height);
61 SetRasterizer(*pathParam->vertices, paint, rasterizer, transform, isStroke);
62
63 RenderPixfmtRgbaBlend pixFormat(renderBuffer);
64 RenderBase renBase(pixFormat);
65 FillBase allocator;
66
67 renBase.ResetClipping(true);
68 renBase.ClipBox(invalidatedArea.GetLeft(), invalidatedArea.GetTop(), invalidatedArea.GetRight(),
69 invalidatedArea.GetBottom());
70
71 if (paint.GetStyle() == Paint::STROKE_STYLE || paint.GetStyle() == Paint::FILL_STYLE ||
72 paint.GetStyle() == Paint::STROKE_FILL_STYLE) {
73 RenderSolid(paint, rasterizer, renBase, isStroke);
74 }
75
76 #if defined(GRAPHIC_ENABLE_GRADIENT_FILL_FLAG) && GRAPHIC_ENABLE_GRADIENT_FILL_FLAG
77 if (paint.GetStyle() == Paint::GRADIENT) {
78 RenderGradient(paint, rasterizer, transform, renBase, renderBuffer, allocator, invalidatedArea);
79 }
80 #endif
81 #if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
82 if (paint.GetStyle() == Paint::PATTERN) {
83 RenderPattern(paint, pathParam->imageParam, rasterizer, renBase, allocator, rect);
84 }
85 #endif
86 }
87
88 #if defined(GRAPHIC_ENABLE_SHADOW_EFFECT_FLAG) && GRAPHIC_ENABLE_SHADOW_EFFECT_FLAG
DoDrawShadow(BufferInfo & gfxDstBuffer,void * param,const Paint & paint,const Rect & rect,const Rect & invalidatedArea,const Style & style,const bool & isStroke)89 void DrawCanvas::DoDrawShadow(BufferInfo& gfxDstBuffer,
90 void* param,
91 const Paint& paint,
92 const Rect& rect,
93 const Rect& invalidatedArea,
94 const Style& style,
95 const bool& isStroke)
96 {
97 if (param == nullptr) {
98 return;
99 }
100
101 TransAffine transform;
102 RenderBuffer renderBuffer;
103 DrawCanvas::InitRenderAndTransform(gfxDstBuffer, renderBuffer, rect, transform, style, paint);
104
105 transform.Translate(paint.GetShadowOffsetX(), paint.GetShadowOffsetY());
106
107 RasterizerScanlineAntialias rasterizer;
108 GeometryScanline scanline;
109 PathParam* pathParam = static_cast<PathParam*>(param);
110 rasterizer.ClipBox(0, 0, gfxDstBuffer.width, gfxDstBuffer.height);
111 DrawCanvas::SetRasterizer(*pathParam->vertices, paint, rasterizer, transform, isStroke);
112 Rect bbox(rasterizer.GetMinX(), rasterizer.GetMinY(), rasterizer.GetMaxX(), rasterizer.GetMaxY());
113
114 RenderPixfmtRgbaBlend pixFormat(renderBuffer);
115 RenderBase renBase(pixFormat);
116 FillBase allocator;
117
118 renBase.ResetClipping(true);
119 renBase.ClipBox(invalidatedArea.GetLeft(), invalidatedArea.GetTop(), invalidatedArea.GetRight(),
120 invalidatedArea.GetBottom());
121
122 Rgba8T shadowColor;
123 DrawCanvas::ChangeColor(shadowColor, paint.GetShadowColor(), paint.GetShadowColor().alpha * paint.GetGlobalAlpha());
124
125 RenderScanlinesAntiAliasSolid(rasterizer, scanline, renBase, shadowColor);
126 #if GRAPHIC_ENABLE_BLUR_EFFECT_FLAG
127 bbox.SetLeft(bbox.GetLeft() - paint.GetShadowBlur());
128 bbox.SetTop(bbox.GetTop() - paint.GetShadowBlur());
129 bbox.SetRight(bbox.GetRight() + paint.GetShadowBlur());
130 bbox.SetBottom(bbox.GetBottom() + paint.GetShadowBlur());
131 RenderBuffer shadowBuffer;
132 RenderPixfmtRgbaBlend pixf2(shadowBuffer);
133 Rect shadowRect = {int16_t(bbox.GetLeft()), int16_t(bbox.GetTop()), int16_t(bbox.GetRight()),
134 int16_t(bbox.GetBottom())};
135 shadowRect.Intersect(shadowRect, invalidatedArea);
136 pixf2.Attach(pixFormat, shadowRect.GetLeft(), shadowRect.GetTop(), shadowRect.GetRight(), shadowRect.GetBottom());
137 uint8_t pixelByteSize = DrawUtils::GetPxSizeByColorMode(gfxDstBuffer.mode) >> 3; // 3: Shift right 3 bits
138
139 paint.GetDrawBoxBlur().BoxBlur(pixf2, MATH_UROUND(paint.GetShadowBlur()), pixelByteSize, gfxDstBuffer.stride);
140
141 #endif // GRAPHIC_ENABLE_BLUR_EFFECT_FLAG
142 }
143 #endif // GRAPHIC_ENABLE_SHADOW_EFFECT_FLAG
144 #endif // ENABLE_CANVAS_EXTEND
145
InitRenderAndTransform(BufferInfo & gfxDstBuffer,RenderBuffer & renderBuffer,const Rect & rect,TransAffine & transform,const Style & style,const Paint & paint)146 void DrawCanvas::InitRenderAndTransform(BufferInfo& gfxDstBuffer,
147 RenderBuffer& renderBuffer,
148 const Rect& rect,
149 TransAffine& transform,
150 const Style& style,
151 const Paint& paint)
152 {
153 int16_t realLeft = rect.GetLeft() + style.paddingLeft_ + style.borderWidth_;
154 int16_t realTop = rect.GetTop() + style.paddingTop_ + style.borderWidth_;
155 transform.Reset();
156 transform *= paint.GetTransAffine();
157 transform.Translate(realLeft, realTop);
158 renderBuffer.Attach(static_cast<uint8_t*>(gfxDstBuffer.virAddr), gfxDstBuffer.width, gfxDstBuffer.height,
159 gfxDstBuffer.stride);
160 }
161
SetRasterizer(UICanvasVertices & vertices,const Paint & paint,RasterizerScanlineAntialias & rasterizer,TransAffine & transform,const bool & isStroke)162 void DrawCanvas::SetRasterizer(UICanvasVertices& vertices,
163 const Paint& paint,
164 RasterizerScanlineAntialias& rasterizer,
165 TransAffine& transform,
166 const bool& isStroke)
167 {
168 DepictCurve canvasPath(vertices);
169 if (isStroke) {
170 #if defined(GRAPHIC_ENABLE_DASH_GENERATE_FLAG) && GRAPHIC_ENABLE_DASH_GENERATE_FLAG
171 if (paint.IsLineDash()) {
172 using DashStyle = DepictDash;
173 using StrokeDashStyle = DepictStroke<DashStyle>;
174 using StrokeDashTransform = DepictTransform<StrokeDashStyle>;
175 DashStyle dashStyle(canvasPath);
176 LineDashStyleCalc(dashStyle, paint);
177 StrokeDashStyle strokeDashStyle(dashStyle);
178 LineStyleCalc(strokeDashStyle, paint);
179 StrokeDashTransform strokeDashTransform(strokeDashStyle, transform);
180 rasterizer.Reset();
181 rasterizer.AddPath(strokeDashTransform);
182 return;
183 }
184 #endif
185 using StrokeLineStyle = DepictStroke<DepictCurve>;
186 StrokeLineStyle strokeLineStyle(canvasPath);
187 LineStyleCalc(strokeLineStyle, paint);
188
189 DepictTransform<StrokeLineStyle> strokeTransform(strokeLineStyle, transform);
190 rasterizer.Reset();
191 rasterizer.AddPath(strokeTransform);
192 } else {
193 DepictTransform<DepictCurve> pathTransform(canvasPath, transform);
194 rasterizer.Reset();
195 rasterizer.AddPath(pathTransform);
196 }
197 }
198
199 #if defined(GRAPHIC_ENABLE_GRADIENT_FILL_FLAG) && GRAPHIC_ENABLE_GRADIENT_FILL_FLAG
RenderGradient(const Paint & paint,RasterizerScanlineAntialias & rasterizer,TransAffine & transform,RenderBase & renBase,RenderBuffer & renderBuffer,FillBase & allocator,const Rect & invalidatedArea)200 void DrawCanvas::RenderGradient(const Paint& paint,
201 RasterizerScanlineAntialias& rasterizer,
202 TransAffine& transform,
203 RenderBase& renBase,
204 RenderBuffer& renderBuffer,
205 FillBase& allocator,
206 const Rect& invalidatedArea)
207 {
208 GeometryScanline scanline;
209
210 RenderPixfmtRgbaBlend pixFormatComp(renderBuffer);
211 RenderBase m_renBaseComp(pixFormatComp);
212
213 m_renBaseComp.ResetClipping(true);
214 m_renBaseComp.ClipBox(invalidatedArea.GetLeft(), invalidatedArea.GetTop(), invalidatedArea.GetRight(),
215 invalidatedArea.GetBottom());
216 TransAffine gradientMatrix;
217 FillInterpolator interpolatorType(gradientMatrix);
218 FillGradientLut gradientColorMode;
219 BuildGradientColor(paint, gradientColorMode);
220 if (paint.GetGradient() == Paint::Linear) {
221 float distance = 0;
222 BuildLineGradientMatrix(paint, gradientMatrix, transform, distance);
223 GradientLinearCalculate gradientLinearCalculate;
224 FillGradient span(interpolatorType, gradientLinearCalculate, gradientColorMode, 0, distance);
225 RenderScanlinesAntiAlias(rasterizer, scanline, renBase, allocator, span);
226 }
227
228 if (paint.GetGradient() == Paint::Radial) {
229 Paint::RadialGradientPoint radialPoint = paint.GetRadialGradientPoint();
230 float startRadius = 0;
231 float endRadius = 0;
232 BuildRadialGradientMatrix(paint, gradientMatrix, transform, startRadius, endRadius);
233 GradientRadialCalculate gradientRadialCalculate(radialPoint.r1, radialPoint.x0 - radialPoint.x1,
234 radialPoint.y0 - radialPoint.y1);
235 FillGradient span(interpolatorType, gradientRadialCalculate, gradientColorMode, startRadius, endRadius);
236 RenderScanlinesAntiAlias(rasterizer, scanline, renBase, allocator, span);
237 }
238 }
239
BuildGradientColor(const Paint & paint,FillGradientLut & gradientColorMode)240 void DrawCanvas::BuildGradientColor(const Paint& paint, FillGradientLut& gradientColorMode)
241 {
242 gradientColorMode.RemoveAll();
243 ListNode<Paint::StopAndColor>* iter = paint.getStopAndColor().Begin();
244 uint16_t count = 0;
245 for (; count < paint.getStopAndColor().Size(); count++) {
246 ColorType stopColor = iter->data_.color;
247 Rgba8T sRgba8;
248 ChangeColor(sRgba8, stopColor, stopColor.alpha * paint.GetGlobalAlpha());
249 gradientColorMode.AddColor(iter->data_.stop, sRgba8);
250 iter = iter->next_;
251 }
252 gradientColorMode.BuildLut();
253 }
254
BuildRadialGradientMatrix(const Paint & paint,TransAffine & gradientMatrix,TransAffine & transform,float & startRadius,float & endRadius)255 void DrawCanvas::BuildRadialGradientMatrix(const Paint& paint,
256 TransAffine& gradientMatrix,
257 TransAffine& transform,
258 float& startRadius,
259 float& endRadius)
260 {
261 Paint::RadialGradientPoint radialPoint = paint.GetRadialGradientPoint();
262 gradientMatrix.Reset();
263 gradientMatrix *= TransAffine::TransAffineTranslation(radialPoint.x1, radialPoint.y1);
264 gradientMatrix *= transform;
265 gradientMatrix.Invert();
266 startRadius = radialPoint.r0;
267 endRadius = radialPoint.r1;
268 }
269 #endif // GRAPHIC_ENABLE_GRADIENT_FILL_FLAG
270
271 #if defined(GRAPHIC_ENABLE_PATTERN_FILL_FLAG) && GRAPHIC_ENABLE_PATTERN_FILL_FLAG
272 #if defined(ENABLE_CANVAS_EXTEND) && ENABLE_CANVAS_EXTEND
RenderPattern(const Paint & paint,void * param,RasterizerScanlineAntialias & rasterizer,RenderBase & renBase,FillBase & allocator,const Rect & rect)273 void DrawCanvas::RenderPattern(const Paint& paint,
274 void* param,
275 RasterizerScanlineAntialias& rasterizer,
276 RenderBase& renBase,
277 FillBase& allocator,
278 const Rect& rect)
279 {
280 if (param == nullptr) {
281 return;
282 }
283 ImageParam* imageParam = static_cast<ImageParam*>(param);
284 if (imageParam->image == nullptr) {
285 return;
286 }
287 GeometryScanline scanline;
288 FillPatternRgba spanPattern(imageParam->image->GetImageInfo(), paint.GetPatternRepeatMode(), rect.GetLeft(),
289 rect.GetTop());
290 RenderScanlinesAntiAlias(rasterizer, scanline, renBase, allocator, spanPattern);
291 }
292 #endif
293 #endif // GRAPHIC_ENABLE_PATTERN_FILL_FLAG
294
295 } // namespace OHOS
296