aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core/SkDraw.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/SkDraw.cpp')
-rw-r--r--src/core/SkDraw.cpp180
1 files changed, 66 insertions, 114 deletions
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index bd607553cd..c9f2e0ed2c 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -51,9 +51,7 @@ static SkPaint make_paint_with_image(
///////////////////////////////////////////////////////////////////////////////
-SkDraw::SkDraw() {
- sk_bzero(this, sizeof(*this));
-}
+SkDraw::SkDraw() {}
bool SkDraw::computeConservativeLocalClipBounds(SkRect* localBounds) const {
if (fRC->isEmpty()) {
@@ -1407,8 +1405,9 @@ public:
// this extra test is worth it, assuming that most of the time it succeeds
// since we can avoid writing to storage
if (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) {
- if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds))
+ if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds)) {
return;
+ }
bounds = &storage;
}
@@ -1556,116 +1555,72 @@ void SkDraw::drawPosText(const char text[], size_t byteLength, const SkScalar po
offset, *fMatrix, pos, scalarsPerPosition, cache.get(), drawOneGlyph);
}
-void SkDraw::drawGlyphRunAsPaths(
- SkGlyphRun* glyphRun, SkPoint origin, const SkSurfaceProps* props) const {
- // setup our std paint, in hopes of getting hits in the cache
- const SkPaint& origPaint = glyphRun->paint();
- SkPaint paint(glyphRun->paint());
- SkScalar matrixScale = paint.setupForAsPaths();
-
- SkMatrix matrix;
- matrix.setScale(matrixScale, matrixScale);
-
- // Temporarily jam in kFill, so we only ever ask for the raw outline from the cache.
- paint.setStyle(SkPaint::kFill_Style);
- paint.setPathEffect(nullptr);
-
- auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
- paint, props, this->scalerContextFlags(), nullptr);
-
- // Now restore the original settings, so we "draw" with whatever style/stroking.
- paint.setStyle(origPaint.getStyle());
- paint.setPathEffect(origPaint.refPathEffect());
+void SkDraw::blitARGB32Mask(const SkMask& mask, const SkPaint& paint) const {
+ SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
+ SkBitmap bm;
+ bm.installPixels(
+ SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
+ (SkPMColor*)mask.fImage, mask.fRowBytes);
- auto eachGlyph = [this, origin, &cache, &matrix, &paint](SkGlyphID glyphID, SkPoint position) {
- const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
- if (glyph.fWidth > 0) {
- const SkPath* path = cache->findPath(glyph);
- if (path != nullptr) {
- SkPoint loc = position + origin;
- matrix[SkMatrix::kMTransX] = loc.fX;
- matrix[SkMatrix::kMTransY] = loc.fY;
- this->drawPath(*path, paint, &matrix, false);
- }
- }
- };
- glyphRun->forEachGlyphAndPosition(eachGlyph);
+ this->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), paint);
}
-void SkDraw::drawGlyphRunAsSubpixelMask(
- SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const {
+SkGlyphRunListDrawer::PerMask SkDraw::drawOneMaskCreator(
+ const SkPaint& paint, SkArenaAlloc* alloc) const {
+ SkBlitter* blitter = SkBlitter::Choose(fDst, *fMatrix, paint, alloc, false);
+ if (fCoverage != nullptr) {
+ auto coverageBlitter = SkBlitter::Choose(*fCoverage, *fMatrix, SkPaint(), alloc, true);
+ blitter = alloc->make<SkPairBlitter>(blitter, coverageBlitter);
+ }
- SkMatrix matrix = *fMatrix;
- // Add rounding and origin.
- SkAxisAlignment axisAlignment = cache->getScalerContext()->computeAxisAlignmentForHText();
- SkPoint rounding = SkFindAndPlaceGlyph::SubpixelPositionRounding(axisAlignment);
- matrix.preTranslate(origin.x(), origin.y());
- matrix.postTranslate(rounding.x(), rounding.y());
+ auto wrapaper = alloc->make<SkAAClipBlitterWrapper>(*fRC, blitter);
+ blitter = wrapaper->getBlitter();
- glyphRun->mapPositions(matrix);
+ auto useRegion = fRC->isBW() && !fRC->isRect();
- auto paint = glyphRun->paint();
- // The Blitter Choose needs to be live while using the blitter below.
- SkAutoBlitterChoose blitterChooser(*this, nullptr, paint);
- SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
- DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
+ if (useRegion) {
+ return [this, blitter, &paint](const SkMask& mask) {
+ SkRegion::Cliperator clipper(fRC->bwRgn(), mask.fBounds);
- auto eachGlyph = [cache, &drawOneGlyph, axisAlignment](SkGlyphID glyphID, SkPoint position) {
- auto subpixelAlignment = [](SkAxisAlignment axisAlignment, SkPoint position) -> SkIPoint {
+ if (!clipper.done()) {
+ if (SkMask::kARGB32_Format == mask.fFormat) {
+ this->blitARGB32Mask(mask, 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();
+ return [this, blitter, clipBounds, &paint](const SkMask& mask) {
+ SkIRect storage;
+ const SkIRect* bounds = &mask.fBounds;
- if (!SkScalarsAreFinite(position.fX, position.fY)) {
- return {0, 0};
+ // 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)) {
+ return;
+ }
+ bounds = &storage;
}
- // Only the fractional part of position.fX and position.fY matter, because the result of
- // this function will just be passed to FixedToSub.
- switch (axisAlignment) {
- case kX_SkAxisAlignment:
- return {SkScalarToFixed(SkScalarFraction(position.fX)), 0};
- case kY_SkAxisAlignment:
- return {0, SkScalarToFixed(SkScalarFraction(position.fY))};
- case kNone_SkAxisAlignment:
- return {SkScalarToFixed(SkScalarFraction(position.fX)),
- SkScalarToFixed(SkScalarFraction(position.fY))};
+ if (SkMask::kARGB32_Format == mask.fFormat) {
+ this->blitARGB32Mask(mask, paint);
+ } else {
+ blitter->blitMask(mask, *bounds);
}
- SK_ABORT("Should not get here.");
- return {0, 0};
};
-
- SkIPoint lookupPosition = subpixelAlignment(axisAlignment, position);
- const SkGlyph& glyph = cache->getGlyphIDMetrics(
- glyphID, lookupPosition.x(), lookupPosition.y());
- if (glyph.fWidth > 0) {
- drawOneGlyph(glyph, position, SkPoint::Make(0, 0));
- }
- };
- glyphRun->forEachGlyphAndPosition(eachGlyph);
-}
-
-void SkDraw::drawGlyphRunAsFullpixelMask(
- SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const {
- SkMatrix matrix = *fMatrix;
- // Add rounding and origin.
- matrix.preTranslate(origin.x(), origin.y());
- matrix.postTranslate(SK_ScalarHalf, SK_ScalarHalf);
- glyphRun->mapPositions(matrix);
-
- auto paint = glyphRun->paint();
- // The Blitter Choose needs to be live while using the blitter below.
- SkAutoBlitterChoose blitterChooser(*this, nullptr, paint);
- SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
- DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
-
- auto eachGlyph = [cache, &drawOneGlyph](SkGlyphID glyphID, SkPoint position) {
- const SkGlyph& glyph = cache->getGlyphIDMetrics(glyphID);
- if (glyph.fWidth > 0) {
- drawOneGlyph(glyph, position, SkPoint::Make(0, 0));
- }
- };
- glyphRun->forEachGlyphAndPosition(eachGlyph);
+ }
}
-void SkDraw::drawGlyphRunList(SkGlyphRunList* glyphRunList, const SkSurfaceProps* props) const {
+void SkDraw::drawGlyphRunList(
+ SkGlyphRunList* glyphRunList, SkGlyphRunListDrawer* glyphDraw) const {
SkDEBUGCODE(this->validate();)
@@ -1673,21 +1628,18 @@ void SkDraw::drawGlyphRunList(SkGlyphRunList* glyphRunList, const SkSurfaceProps
return;
}
- SkPoint origin = glyphRunList->origin();
- for (auto& glyphRun : *glyphRunList) {
- if (ShouldDrawTextAsPaths(glyphRun.paint(), *fMatrix)) {
- this->drawGlyphRunAsPaths(&glyphRun, origin, props);
- } else {
- auto cache = SkStrikeCache::FindOrCreateStrikeExclusive(
- glyphRun.paint(), props, this->scalerContextFlags(), fMatrix);
- if (cache->isSubpixel()) {
- this->drawGlyphRunAsSubpixelMask(cache.get(), &glyphRun, origin);
- } else {
- this->drawGlyphRunAsFullpixelMask(cache.get(), &glyphRun, origin);
- }
- }
- }
+ auto perPathBuilder = [this](const SkPaint& paint, SkArenaAlloc*) {
+ auto perPath = [this, &paint](const SkPath& path, const SkMatrix& matrix) {
+ this->drawPath(path, paint, &matrix, false);
+ };
+ return perPath;
+ };
+
+ auto perMaskBuilder = [this](const SkPaint& paint, SkArenaAlloc* alloc) {
+ return this->drawOneMaskCreator(paint, alloc);
+ };
+ glyphDraw->drawForBitmap(glyphRunList, *fMatrix, perMaskBuilder, perPathBuilder);
}
#if defined _WIN32