/* * Copyright 2018 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkDraw.h" #include "SkFontPriv.h" #include "SkPaintPriv.h" #include "SkRasterClip.h" #include "SkScalerContext.h" #include "SkStrike.h" #include "SkUtils.h" bool SkDraw::ShouldDrawTextAsPaths(const SkFont& font, const SkPaint& paint, const SkMatrix& ctm, SkScalar sizeLimit) { // hairline glyphs are fast enough so we don't need to cache them if (SkPaint::kStroke_Style == paint.getStyle() && 0 == paint.getStrokeWidth()) { return true; } // we don't cache perspective if (ctm.hasPerspective()) { return true; } return SkFontPriv::TooBigToUseCache(ctm, SkFontPriv::MakeTextMatrix(font), sizeLimit); } // disable warning : local variable used without having been initialized #if defined _WIN32 #pragma warning ( push ) #pragma warning ( disable : 4701 ) #endif //////////////////////////////////////////////////////////////////////////////////////////////////// void SkDraw::paintMasks(SkSpan<const SkMask> masks, const SkPaint& paint) const { // The size used for a typical blitter. SkSTArenaAlloc<3308> alloc; SkBlitter* blitter = SkBlitter::Choose(fDst, *fMatrix, paint, &alloc, false); if (fCoverage) { blitter = alloc.make<SkPairBlitter>( blitter, SkBlitter::Choose(*fCoverage, *fMatrix, SkPaint(), &alloc, true)); } SkAAClipBlitterWrapper wrapper{*fRC, blitter}; blitter = wrapper.getBlitter(); bool useRegion = fRC->isBW() && !fRC->isRect(); if (useRegion) { for (const SkMask& mask : masks) { SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds); if (!clipper.done()) { if (SkMask::kARGB32_Format == mask.fFormat) { SkBitmap bm; bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()), mask.fImage, mask.fRowBytes); this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint); } else { const SkIRect& cr = clipper.rect(); do { blitter->blitMask(mask, cr); clipper.next(); } while (!clipper.done()); } } } } else { SkIRect clipBounds = fRC->isBW() ? fRC->bwRgn().getBounds() : fRC->aaRgn().getBounds(); for (const SkMask& mask : masks) { SkIRect storage; const SkIRect* bounds = &mask.fBounds; // this extra test is worth it, assuming that most of the time it succeeds // since we can avoid writing to storage if (!clipBounds.containsNoEmptyCheck(mask.fBounds)) { if (!storage.intersectNoEmptyCheck(mask.fBounds, clipBounds)) { continue; } bounds = &storage; } if (SkMask::kARGB32_Format == mask.fFormat) { SkBitmap bm; bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()), mask.fImage, mask.fRowBytes); this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint); } else { blitter->blitMask(mask, *bounds); } } } } void SkDraw::paintPaths(SkSpan<const SkGlyphRunListPainter::PathAndPos> pathsAndPositions, SkScalar scale, const SkPaint& paint) const { for (const auto& pathAndPos : pathsAndPositions) { SkMatrix m; SkPoint position = pathAndPos.position; m.setScaleTranslate(scale, scale, position.x(), position.y()); this->drawPath(*pathAndPos.path, paint, &m, false); } } void SkDraw::drawGlyphRunList(const SkGlyphRunList& glyphRunList, SkGlyphRunListPainter* glyphPainter) const { SkDEBUGCODE(this->validate();) if (fRC->isEmpty()) { return; } glyphPainter->drawForBitmapDevice(glyphRunList, *fMatrix, this); } #if defined _WIN32 #pragma warning ( pop ) #endif