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 "SkDraw.h" 9 #include "SkFontPriv.h" 10 #include "SkPaintPriv.h" 11 #include "SkRasterClip.h" 12 #include "SkScalerContext.h" 13 #include "SkStrike.h" 14 #include "SkUtils.h" 15 16 bool SkDraw::ShouldDrawTextAsPaths(const SkFont& font, const SkPaint& paint, 17 const SkMatrix& ctm, SkScalar sizeLimit) { 18 // hairline glyphs are fast enough so we don't need to cache them 19 if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { 20 return true; 21 } 22 23 // we don't cache perspective 24 if (ctm.hasPerspective()) { 25 return true; 26 } 27 28 return SkFontPriv::TooBigToUseCache(ctm, SkFontPriv::MakeTextMatrix(font), sizeLimit); 29 } 30 31 // disable warning : local variable used without having been initialized 32 #if defined _WIN32 33 #pragma warning ( push ) 34 #pragma warning ( disable : 4701 ) 35 #endif 36 37 //////////////////////////////////////////////////////////////////////////////////////////////////// 38 39 void SkDraw::paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const { 40 41 // The size used for a typical blitter. 42 SkSTArenaAlloc<3308> alloc; 43 SkBlitter* blitter = SkBlitter::Choose(fDst, *fMatrix, paint, &alloc, false); 44 if (fCoverage) { 45 blitter = alloc.make<SkPairBlitter>( 46 blitter, 47 SkBlitter::Choose(*fCoverage, *fMatrix, SkPaint(), &alloc, true)); 48 } 49 50 SkAAClipBlitterWrapper wrapper{*fRC, blitter}; 51 blitter = wrapper.getBlitter(); 52 53 bool useRegion = fRC->isBW() && !fRC->isRect(); 54 55 if (useRegion) { 56 for (const SkMask& mask : masks) { 57 SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds); 58 59 if (!clipper.done()) { 60 if (SkMask::kARGB32_Format == mask.fFormat) { 61 SkBitmap bm; 62 bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()), 63 mask.fImage, 64 mask.fRowBytes); 65 this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint); 66 } else { 67 const SkIRect& cr = clipper.rect(); 68 do { 69 blitter->blitMask(mask, cr); 70 clipper.next(); 71 } while (!clipper.done()); 72 } 73 } 74 } 75 } else { 76 SkIRect clipBounds = fRC->isBW() ? fRC->bwRgn().getBounds() 77 : fRC->aaRgn().getBounds(); 78 for (const SkMask& mask : masks) { 79 SkIRect storage; 80 const SkIRect* bounds = &mask.fBounds; 81 82 // this extra test is worth it, assuming that most of the time it succeeds 83 // since we can avoid writing to storage 84 if (!clipBounds.containsNoEmptyCheck(mask.fBounds)) { 85 if (!storage.intersectNoEmptyCheck(mask.fBounds, clipBounds)) { 86 continue; 87 } 88 bounds = &storage; 89 } 90 91 if (SkMask::kARGB32_Format == mask.fFormat) { 92 SkBitmap bm; 93 bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()), 94 mask.fImage, 95 mask.fRowBytes); 96 this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint); 97 } else { 98 blitter->blitMask(mask, *bounds); 99 } 100 } 101 } 102 } 103 104 void SkDraw::paintPaths(SkSpan<const SkGlyphRunListPainter::PathAndPos> pathsAndPositions, 105 SkScalar scale, 106 const SkPaint& paint) const { 107 for (const auto& pathAndPos : pathsAndPositions) { 108 SkMatrix m; 109 SkPoint position = pathAndPos.position; 110 m.setScaleTranslate(scale, scale, position.x(), position.y()); 111 this->drawPath(*pathAndPos.path, paint, &m, false); 112 } 113 } 114 115 void SkDraw::drawGlyphRunList(const SkGlyphRunList& glyphRunList, 116 SkGlyphRunListPainter* glyphPainter) const { 117 118 SkDEBUGCODE(this->validate();) 119 120 if (fRC->isEmpty()) { 121 return; 122 } 123 124 glyphPainter->drawForBitmapDevice(glyphRunList, *fMatrix, this); 125 } 126 127 #if defined _WIN32 128 #pragma warning ( pop ) 129 #endif 130 131