1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2018 Google Inc. 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#include "include/core/SkBitmap.h" 9cb93a386Sopenharmony_ci#include "src/core/SkDraw.h" 10cb93a386Sopenharmony_ci#include "src/core/SkFontPriv.h" 11cb93a386Sopenharmony_ci#include "src/core/SkMatrixProvider.h" 12cb93a386Sopenharmony_ci#include "src/core/SkPaintPriv.h" 13cb93a386Sopenharmony_ci#include "src/core/SkRasterClip.h" 14cb93a386Sopenharmony_ci#include "src/core/SkScalerCache.h" 15cb93a386Sopenharmony_ci#include "src/core/SkScalerContext.h" 16cb93a386Sopenharmony_ci#include "src/core/SkUtils.h" 17cb93a386Sopenharmony_ci#include <climits> 18cb93a386Sopenharmony_ci 19cb93a386Sopenharmony_ci// disable warning : local variable used without having been initialized 20cb93a386Sopenharmony_ci#if defined _WIN32 21cb93a386Sopenharmony_ci#pragma warning ( push ) 22cb93a386Sopenharmony_ci#pragma warning ( disable : 4701 ) 23cb93a386Sopenharmony_ci#endif 24cb93a386Sopenharmony_ci 25cb93a386Sopenharmony_ci//////////////////////////////////////////////////////////////////////////////////////////////////// 26cb93a386Sopenharmony_ci 27cb93a386Sopenharmony_cistatic bool check_glyph_position(SkPoint position) { 28cb93a386Sopenharmony_ci // Prevent glyphs from being drawn outside of or straddling the edge of device space. 29cb93a386Sopenharmony_ci // Comparisons written a little weirdly so that NaN coordinates are treated safely. 30cb93a386Sopenharmony_ci auto gt = [](float a, int b) { return !(a <= (float)b); }; 31cb93a386Sopenharmony_ci auto lt = [](float a, int b) { return !(a >= (float)b); }; 32cb93a386Sopenharmony_ci return !(gt(position.fX, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) || 33cb93a386Sopenharmony_ci lt(position.fX, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) || 34cb93a386Sopenharmony_ci gt(position.fY, INT_MAX - (INT16_MAX + SkTo<int>(UINT16_MAX))) || 35cb93a386Sopenharmony_ci lt(position.fY, INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))); 36cb93a386Sopenharmony_ci} 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_civoid SkDraw::paintMasks(SkDrawableGlyphBuffer* drawables, const SkPaint& paint) const { 39cb93a386Sopenharmony_ci 40cb93a386Sopenharmony_ci // The size used for a typical blitter. 41cb93a386Sopenharmony_ci SkSTArenaAlloc<3308> alloc; 42cb93a386Sopenharmony_ci SkBlitter* blitter = 43cb93a386Sopenharmony_ci SkBlitter::Choose(fDst, *fMatrixProvider, paint, &alloc, false, fRC->clipShader()); 44cb93a386Sopenharmony_ci if (fCoverage) { 45cb93a386Sopenharmony_ci blitter = alloc.make<SkPairBlitter>( 46cb93a386Sopenharmony_ci blitter, 47cb93a386Sopenharmony_ci SkBlitter::Choose( 48cb93a386Sopenharmony_ci *fCoverage, *fMatrixProvider, SkPaint(), &alloc, true, fRC->clipShader())); 49cb93a386Sopenharmony_ci } 50cb93a386Sopenharmony_ci 51cb93a386Sopenharmony_ci SkAAClipBlitterWrapper wrapper{*fRC, blitter}; 52cb93a386Sopenharmony_ci blitter = wrapper.getBlitter(); 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci bool useRegion = fRC->isBW() && !fRC->isRect(); 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci if (useRegion) { 57cb93a386Sopenharmony_ci for (auto [variant, pos] : drawables->drawable()) { 58cb93a386Sopenharmony_ci SkGlyph* glyph = variant.glyph(); 59cb93a386Sopenharmony_ci if (check_glyph_position(pos)) { 60cb93a386Sopenharmony_ci SkMask mask = glyph->mask(pos); 61cb93a386Sopenharmony_ci 62cb93a386Sopenharmony_ci SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds); 63cb93a386Sopenharmony_ci 64cb93a386Sopenharmony_ci if (!clipper.done()) { 65cb93a386Sopenharmony_ci if (SkMask::kARGB32_Format == mask.fFormat) { 66cb93a386Sopenharmony_ci SkBitmap bm; 67cb93a386Sopenharmony_ci bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()), 68cb93a386Sopenharmony_ci mask.fImage, 69cb93a386Sopenharmony_ci mask.fRowBytes); 70cb93a386Sopenharmony_ci this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint); 71cb93a386Sopenharmony_ci } else { 72cb93a386Sopenharmony_ci const SkIRect& cr = clipper.rect(); 73cb93a386Sopenharmony_ci do { 74cb93a386Sopenharmony_ci blitter->blitMask(mask, cr); 75cb93a386Sopenharmony_ci clipper.next(); 76cb93a386Sopenharmony_ci } while (!clipper.done()); 77cb93a386Sopenharmony_ci } 78cb93a386Sopenharmony_ci } 79cb93a386Sopenharmony_ci } 80cb93a386Sopenharmony_ci } 81cb93a386Sopenharmony_ci } else { 82cb93a386Sopenharmony_ci SkIRect clipBounds = fRC->isBW() ? fRC->bwRgn().getBounds() 83cb93a386Sopenharmony_ci : fRC->aaRgn().getBounds(); 84cb93a386Sopenharmony_ci for (auto [variant, pos] : drawables->drawable()) { 85cb93a386Sopenharmony_ci SkGlyph* glyph = variant.glyph(); 86cb93a386Sopenharmony_ci if (check_glyph_position(pos)) { 87cb93a386Sopenharmony_ci SkMask mask = glyph->mask(pos); 88cb93a386Sopenharmony_ci SkIRect storage; 89cb93a386Sopenharmony_ci const SkIRect* bounds = &mask.fBounds; 90cb93a386Sopenharmony_ci 91cb93a386Sopenharmony_ci // this extra test is worth it, assuming that most of the time it succeeds 92cb93a386Sopenharmony_ci // since we can avoid writing to storage 93cb93a386Sopenharmony_ci if (!clipBounds.containsNoEmptyCheck(mask.fBounds)) { 94cb93a386Sopenharmony_ci if (!storage.intersect(mask.fBounds, clipBounds)) { 95cb93a386Sopenharmony_ci continue; 96cb93a386Sopenharmony_ci } 97cb93a386Sopenharmony_ci bounds = &storage; 98cb93a386Sopenharmony_ci } 99cb93a386Sopenharmony_ci 100cb93a386Sopenharmony_ci if (SkMask::kARGB32_Format == mask.fFormat) { 101cb93a386Sopenharmony_ci SkBitmap bm; 102cb93a386Sopenharmony_ci bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.size()), 103cb93a386Sopenharmony_ci mask.fImage, 104cb93a386Sopenharmony_ci mask.fRowBytes); 105cb93a386Sopenharmony_ci this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint); 106cb93a386Sopenharmony_ci } else { 107cb93a386Sopenharmony_ci blitter->blitMask(mask, *bounds); 108cb93a386Sopenharmony_ci } 109cb93a386Sopenharmony_ci } 110cb93a386Sopenharmony_ci } 111cb93a386Sopenharmony_ci } 112cb93a386Sopenharmony_ci} 113cb93a386Sopenharmony_ci 114cb93a386Sopenharmony_civoid SkDraw::paintPaths(SkDrawableGlyphBuffer* drawables, 115cb93a386Sopenharmony_ci SkScalar scale, 116cb93a386Sopenharmony_ci SkPoint origin, 117cb93a386Sopenharmony_ci const SkPaint& paint) const { 118cb93a386Sopenharmony_ci for (auto [variant, pos] : drawables->drawable()) { 119cb93a386Sopenharmony_ci const SkPath* path = variant.path(); 120cb93a386Sopenharmony_ci SkMatrix m; 121cb93a386Sopenharmony_ci SkPoint translate = origin + pos; 122cb93a386Sopenharmony_ci m.setScaleTranslate(scale, scale, translate.x(), translate.y()); 123cb93a386Sopenharmony_ci this->drawPath(*path, paint, &m, false); 124cb93a386Sopenharmony_ci } 125cb93a386Sopenharmony_ci} 126cb93a386Sopenharmony_ci 127cb93a386Sopenharmony_civoid SkDraw::drawGlyphRunList(const SkGlyphRunList& glyphRunList, 128cb93a386Sopenharmony_ci const SkPaint& paint, 129cb93a386Sopenharmony_ci SkGlyphRunListPainter* glyphPainter) const { 130cb93a386Sopenharmony_ci 131cb93a386Sopenharmony_ci SkDEBUGCODE(this->validate();) 132cb93a386Sopenharmony_ci 133cb93a386Sopenharmony_ci if (fRC->isEmpty()) { 134cb93a386Sopenharmony_ci return; 135cb93a386Sopenharmony_ci } 136cb93a386Sopenharmony_ci 137cb93a386Sopenharmony_ci glyphPainter->drawForBitmapDevice(glyphRunList, paint, fMatrixProvider->localToDevice(), this); 138cb93a386Sopenharmony_ci} 139cb93a386Sopenharmony_ci 140cb93a386Sopenharmony_ci#if defined _WIN32 141cb93a386Sopenharmony_ci#pragma warning ( pop ) 142cb93a386Sopenharmony_ci#endif 143cb93a386Sopenharmony_ci 144