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