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