Home | History | Annotate | Download | only in core
      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 SkPathPos> 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