• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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