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