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