diff options
author | Herb Derby <herb@google.com> | 2018-07-20 11:48:38 -0400 |
---|---|---|
committer | Skia Commit-Bot <skia-commit-bot@chromium.org> | 2018-07-24 14:53:25 +0000 |
commit | 81ecdbb7ff36afef9091c1b524baafe67381e70d (patch) | |
tree | c9d2a2ace6fecc88bf85e1377c2eeb8d8d007a5a /src/core/SkDraw.cpp | |
parent | ab98509717e1d20b8171a631d2923f47ce26fc0e (diff) |
Clean up bitmap path
Change-Id: If149194fd86f14bea289ad68262ea99cbbc398b6
Reviewed-on: https://skia-review.googlesource.com/142817
Reviewed-by: Ben Wagner <bungeman@google.com>
Commit-Queue: Herb Derby <herb@google.com>
Diffstat (limited to 'src/core/SkDraw.cpp')
-rw-r--r-- | src/core/SkDraw.cpp | 134 |
1 files changed, 134 insertions, 0 deletions
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp index ae1a873f2b..4c9dddf1f5 100644 --- a/src/core/SkDraw.cpp +++ b/src/core/SkDraw.cpp @@ -1598,6 +1598,140 @@ 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()); + + 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); +} + +void SkDraw::drawGlyphRunAsSubpixelMask( + SkGlyphCache* cache, SkGlyphRun* glyphRun, SkPoint origin) const { + + 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()); + + 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, axisAlignment](SkGlyphID glyphID, SkPoint position) { + auto subpixelAlignment = [](SkAxisAlignment axisAlignment, SkPoint position) -> SkIPoint { + + if (!SkScalarsAreFinite(position.fX, position.fY)) { + return {0, 0}; + } + + // 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))}; + } + 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 { + + SkDEBUGCODE(this->validate();) + + if (fRC->isEmpty()) { + 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); + } + } + } + +} + #if defined _WIN32 #pragma warning ( pop ) #endif |