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