1cb93a386Sopenharmony_ci/*
2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc.
3cb93a386Sopenharmony_ci *
4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be
5cb93a386Sopenharmony_ci * found in the LICENSE file.
6cb93a386Sopenharmony_ci */
7cb93a386Sopenharmony_ci
8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h"
9cb93a386Sopenharmony_ci#include "src/core/SkDraw.h"
10cb93a386Sopenharmony_ci#include "src/core/SkFontPriv.h"
11cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h"
12cb93a386Sopenharmony_ci#include "src/core/SkPaintPriv.h"
13cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h"
14cb93a386Sopenharmony_ci#include "src/core/SkScalerCache.h"
15cb93a386Sopenharmony_ci#include "src/core/SkScalerContext.h"
16cb93a386Sopenharmony_ci#include "src/core/SkUtils.h"
17cb93a386Sopenharmony_ci#include <climits>
18cb93a386Sopenharmony_ci
19cb93a386Sopenharmony_ci// disable warning : local variable used without having been initialized
20cb93a386Sopenharmony_ci#if defined _WIN32
21cb93a386Sopenharmony_ci#pragma warning ( push )
22cb93a386Sopenharmony_ci#pragma warning ( disable : 4701 )
23cb93a386Sopenharmony_ci#endif
24cb93a386Sopenharmony_ci
25cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////////
26cb93a386Sopenharmony_ci
27cb93a386Sopenharmony_cistatic bool check_glyph_position(SkPoint position) {
28cb93a386Sopenharmony_ci    // Prevent glyphs from being drawn outside of or straddling the edge of device space.
29cb93a386Sopenharmony_ci    // Comparisons written a little weirdly so that NaN coordinates are treated safely.
30cb93a386Sopenharmony_ci    auto gt = [](float a, int b) { return !(a <= (float)b); };
31cb93a386Sopenharmony_ci    auto lt = [](float a, int b) { return !(a >= (float)b); };
32cb93a386Sopenharmony_ci    return !(gt(position.fX, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) ||
33cb93a386Sopenharmony_ci             lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) ||
34cb93a386Sopenharmony_ci             gt(position.fY, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) ||
35cb93a386Sopenharmony_ci             lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)));
36cb93a386Sopenharmony_ci}
37cb93a386Sopenharmony_ci
38cb93a386Sopenharmony_civoid SkDraw::paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const {
39cb93a386Sopenharmony_ci
40cb93a386Sopenharmony_ci    // The size used for a typical blitter.
41cb93a386Sopenharmony_ci    SkSTArenaAlloc<3308> alloc;
42cb93a386Sopenharmony_ci    SkBlitter* blitter =
43cb93a386Sopenharmony_ci            SkBlitter::Choose(fDst, *fMatrixProvider, paint, &alloc, false, fRC->clipShader());
44cb93a386Sopenharmony_ci    if (fCoverage) {
45cb93a386Sopenharmony_ci        blitter = alloc.make<SkPairBlitter>(
46cb93a386Sopenharmony_ci                blitter,
47cb93a386Sopenharmony_ci                SkBlitter::Choose(
48cb93a386Sopenharmony_ci                        *fCoverage, *fMatrixProvider, SkPaint(), &alloc, true, fRC->clipShader()));
49cb93a386Sopenharmony_ci    }
50cb93a386Sopenharmony_ci
51cb93a386Sopenharmony_ci    SkAAClipBlitterWrapper wrapper{*fRC, blitter};
52cb93a386Sopenharmony_ci    blitter = wrapper.getBlitter();
53cb93a386Sopenharmony_ci
54cb93a386Sopenharmony_ci    bool useRegion = fRC->isBW() && !fRC->isRect();
55cb93a386Sopenharmony_ci
56cb93a386Sopenharmony_ci    if (useRegion) {
57cb93a386Sopenharmony_ci        for (auto [variant, pos] : drawables->drawable()) {
58cb93a386Sopenharmony_ci            SkGlyph* glyph = variant.glyph();
59cb93a386Sopenharmony_ci            if (check_glyph_position(pos)) {
60cb93a386Sopenharmony_ci                SkMask mask = glyph->mask(pos);
61cb93a386Sopenharmony_ci
62cb93a386Sopenharmony_ci                SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds);
63cb93a386Sopenharmony_ci
64cb93a386Sopenharmony_ci                if (!clipper.done()) {
65cb93a386Sopenharmony_ci                    if (SkMask::kARGB32_Format == mask.fFormat) {
66cb93a386Sopenharmony_ci                        SkBitmap bm;
67cb93a386Sopenharmony_ci                        bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()),
68cb93a386Sopenharmony_ci                                         mask.fImage,
69cb93a386Sopenharmony_ci                                         mask.fRowBytes);
70cb93a386Sopenharmony_ci                        this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint);
71cb93a386Sopenharmony_ci                    } else {
72cb93a386Sopenharmony_ci                        const SkIRect& cr = clipper.rect();
73cb93a386Sopenharmony_ci                        do {
74cb93a386Sopenharmony_ci                            blitter->blitMask(mask, cr);
75cb93a386Sopenharmony_ci                            clipper.next();
76cb93a386Sopenharmony_ci                        } while (!clipper.done());
77cb93a386Sopenharmony_ci                    }
78cb93a386Sopenharmony_ci                }
79cb93a386Sopenharmony_ci            }
80cb93a386Sopenharmony_ci        }
81cb93a386Sopenharmony_ci    } else {
82cb93a386Sopenharmony_ci        SkIRect clipBounds = fRC->isBW() ? fRC->bwRgn().getBounds()
83cb93a386Sopenharmony_ci                                         : fRC->aaRgn().getBounds();
84cb93a386Sopenharmony_ci        for (auto [variant, pos] : drawables->drawable()) {
85cb93a386Sopenharmony_ci            SkGlyph* glyph = variant.glyph();
86cb93a386Sopenharmony_ci            if (check_glyph_position(pos)) {
87cb93a386Sopenharmony_ci                SkMask mask = glyph->mask(pos);
88cb93a386Sopenharmony_ci                SkIRect storage;
89cb93a386Sopenharmony_ci                const SkIRect* bounds = &mask.fBounds;
90cb93a386Sopenharmony_ci
91cb93a386Sopenharmony_ci                // this extra test is worth it, assuming that most of the time it succeeds
92cb93a386Sopenharmony_ci                // since we can avoid writing to storage
93cb93a386Sopenharmony_ci                if (!clipBounds.containsNoEmptyCheck(mask.fBounds)) {
94cb93a386Sopenharmony_ci                    if (!storage.intersect(mask.fBounds, clipBounds)) {
95cb93a386Sopenharmony_ci                        continue;
96cb93a386Sopenharmony_ci                    }
97cb93a386Sopenharmony_ci                    bounds = &storage;
98cb93a386Sopenharmony_ci                }
99cb93a386Sopenharmony_ci
100cb93a386Sopenharmony_ci                if (SkMask::kARGB32_Format == mask.fFormat) {
101cb93a386Sopenharmony_ci                    SkBitmap bm;
102cb93a386Sopenharmony_ci                    bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()),
103cb93a386Sopenharmony_ci                                     mask.fImage,
104cb93a386Sopenharmony_ci                                     mask.fRowBytes);
105cb93a386Sopenharmony_ci                    this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint);
106cb93a386Sopenharmony_ci                } else {
107cb93a386Sopenharmony_ci                    blitter->blitMask(mask, *bounds);
108cb93a386Sopenharmony_ci                }
109cb93a386Sopenharmony_ci            }
110cb93a386Sopenharmony_ci        }
111cb93a386Sopenharmony_ci    }
112cb93a386Sopenharmony_ci}
113cb93a386Sopenharmony_ci
114cb93a386Sopenharmony_civoid SkDraw::paintPaths(SkDrawableGlyphBuffer* drawables,
115cb93a386Sopenharmony_ci                        SkScalar scale,
116cb93a386Sopenharmony_ci                        SkPoint origin,
117cb93a386Sopenharmony_ci                        const SkPaint& paint) const {
118cb93a386Sopenharmony_ci    for (auto [variant, pos] : drawables->drawable()) {
119cb93a386Sopenharmony_ci        const SkPath* path = variant.path();
120cb93a386Sopenharmony_ci        SkMatrix m;
121cb93a386Sopenharmony_ci        SkPoint translate = origin + pos;
122cb93a386Sopenharmony_ci        m.setScaleTranslate(scale, scale, translate.x(), translate.y());
123cb93a386Sopenharmony_ci        this->drawPath(*path, paint, &m, false);
124cb93a386Sopenharmony_ci    }
125cb93a386Sopenharmony_ci}
126cb93a386Sopenharmony_ci
127cb93a386Sopenharmony_civoid SkDraw::drawGlyphRunList(const SkGlyphRunList& glyphRunList,
128cb93a386Sopenharmony_ci                              const SkPaint& paint,
129cb93a386Sopenharmony_ci                              SkGlyphRunListPainter* glyphPainter) const {
130cb93a386Sopenharmony_ci
131cb93a386Sopenharmony_ci    SkDEBUGCODE(this->validate();)
132cb93a386Sopenharmony_ci
133cb93a386Sopenharmony_ci    if (fRC->isEmpty()) {
134cb93a386Sopenharmony_ci        return;
135cb93a386Sopenharmony_ci    }
136cb93a386Sopenharmony_ci
137cb93a386Sopenharmony_ci    glyphPainter->drawForBitmapDevice(glyphRunList, paint, fMatrixProvider->localToDevice(), this);
138cb93a386Sopenharmony_ci}
139cb93a386Sopenharmony_ci
140cb93a386Sopenharmony_ci#if defined _WIN32
141cb93a386Sopenharmony_ci#pragma warning ( pop )
142cb93a386Sopenharmony_ci#endif
143cb93a386Sopenharmony_ci
144