Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(849)

Unified Diff: src/core/SkDraw.cpp

Issue 1403573002: Simplify draw one glyph (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Address comments. Created 5 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/core/SkDraw.cpp
diff --git a/src/core/SkDraw.cpp b/src/core/SkDraw.cpp
index e1a49d39b4a582265dda15c430ffbf95578bc297..2fa6273112cf0975623755f6a4b04b4a8c386b45 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1423,170 +1423,120 @@ void SkDraw::drawText_asPaths(const char text[], size_t byteLength,
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
-struct SkDraw1Glyph {
- const SkDraw* fDraw;
- const SkRegion* fClip;
- const SkAAClip* fAAClip;
- SkBlitter* fBlitter;
- SkGlyphCache* fCache;
- const SkPaint* fPaint;
- SkIRect fClipBounds;
- /** Half the sampling frequency of the rasterized glyph in x. */
- SkScalar fHalfSampleX;
- /** Half the sampling frequency of the rasterized glyph in y. */
- SkScalar fHalfSampleY;
-
- /** Draws one glyph.
- *
- * The x and y are pre-biased, so implementations may just truncate them.
- * i.e. half the sampling frequency has been added.
- * e.g. 1/2 or 1/(2^(SkGlyph::kSubBits+1)) has already been added.
- * This added bias can be found in fHalfSampleX,Y.
- */
- typedef void (*Proc)(const SkDraw1Glyph&, Sk48Dot16 x, Sk48Dot16 y, const SkGlyph&);
-
- Proc init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
- const SkPaint&);
-
- // call this instead of fBlitter->blitMask() since this wrapper will handle
- // the case when the mask is ARGB32_Format
- //
- void blitMask(const SkMask& mask, const SkIRect& clip) const {
- if (SkMask::kARGB32_Format == mask.fFormat) {
- this->blitMaskAsSprite(mask);
- } else {
- fBlitter->blitMask(mask, clip);
- }
- }
-
- // mask must be kARGB32_Format
- void blitMaskAsSprite(const SkMask& mask) const;
-};
-static void D1G_RectClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy,
- const SkGlyph& glyph) {
- // Prevent glyphs from being drawn outside of or straddling the edge of device space.
- if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
- (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
- (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
- (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/))
- {
- return;
- }
+class DrawOneGlyph {
+public:
+ DrawOneGlyph(const SkDraw& draw, const SkPaint& paint, SkGlyphCache* cache, SkBlitter* blitter)
+ : fUseRegionToDraw(UsingRegionToDraw(draw.fRC))
+ , fGlyphCache(cache)
+ , fBlitter(blitter)
+ , fClip(fUseRegionToDraw ? &draw.fRC->bwRgn() : nullptr)
+ , fDraw(draw)
+ , fPaint(paint)
+ , fClipBounds(PickClipBounds(draw)) { }
+
+ void operator()(const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
+ position += rounding;
+ Sk48Dot16 fx = SkScalarTo48Dot16(position.fX);
+ Sk48Dot16 fy = SkScalarTo48Dot16(position.fY);
+ // Prevent glyphs from being drawn outside of or straddling the edge of device space.
+ if ((fx >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
+ (fx >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/) ||
+ (fy >> 16) > INT_MAX - (INT16_MAX + UINT16_MAX) ||
+ (fy >> 16) < INT_MIN - (INT16_MIN + 0 /*UINT16_MIN*/)) {
+ return;
+ }
- int left = Sk48Dot16FloorToInt(fx);
- int top = Sk48Dot16FloorToInt(fy);
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
- SkASSERT((nullptr == state.fClip && state.fAAClip) ||
- (state.fClip && nullptr == state.fAAClip && state.fClip->isRect()));
+ int left = Sk48Dot16FloorToInt(fx);
+ int top = Sk48Dot16FloorToInt(fy);
+ SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
- left += glyph.fLeft;
- top += glyph.fTop;
+ left += glyph.fLeft;
+ top += glyph.fTop;
- int right = left + glyph.fWidth;
- int bottom = top + glyph.fHeight;
+ int right = left + glyph.fWidth;
+ int bottom = top + glyph.fHeight;
- SkMask mask;
- SkIRect storage;
- SkIRect* bounds = &mask.fBounds;
+ SkMask mask;
+ mask.fBounds.set(left, top, right, bottom);
- mask.fBounds.set(left, top, right, bottom);
+ if (fUseRegionToDraw) {
+ SkRegion::Cliperator clipper(*fClip, mask.fBounds);
- // this extra test is worth it, assuming that most of the time it succeeds
- // since we can avoid writing to storage
- if (!state.fClipBounds.containsNoEmptyCheck(left, top, right, bottom)) {
- if (!storage.intersectNoEmptyCheck(mask.fBounds, state.fClipBounds))
- return;
- bounds = &storage;
- }
+ if (!clipper.done() && this->getImageData(glyph, &mask)) {
+ const SkIRect& cr = clipper.rect();
+ do {
+ this->blitMask(mask, cr);
+ clipper.next();
+ } while (!clipper.done());
+ }
+ } else {
+ SkIRect storage;
+ 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 (!fClipBounds.containsNoEmptyCheck(mask.fBounds)) {
+ if (!storage.intersectNoEmptyCheck(mask.fBounds, fClipBounds))
+ return;
+ bounds = &storage;
+ }
- uint8_t* aa = (uint8_t*)glyph.fImage;
- if (nullptr == aa) {
- aa = (uint8_t*)state.fCache->findImage(glyph);
- if (nullptr == aa) {
- return; // can't rasterize glyph
+ if (this->getImageData(glyph, &mask)) {
+ this->blitMask(mask, *bounds);
+ }
}
}
- mask.fRowBytes = glyph.rowBytes();
- mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
- mask.fImage = aa;
- state.blitMask(mask, *bounds);
-}
-
-static void D1G_RgnClip(const SkDraw1Glyph& state, Sk48Dot16 fx, Sk48Dot16 fy,
- const SkGlyph& glyph) {
- int left = Sk48Dot16FloorToInt(fx);
- int top = Sk48Dot16FloorToInt(fy);
- SkASSERT(glyph.fWidth > 0 && glyph.fHeight > 0);
- SkASSERT(!state.fClip->isRect());
-
- SkMask mask;
-
- left += glyph.fLeft;
- top += glyph.fTop;
+private:
+ static bool UsingRegionToDraw(const SkRasterClip* rClip) {
+ return rClip->isBW() && !rClip->isRect();
+ }
- mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
- SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
+ static SkIRect PickClipBounds(const SkDraw& draw) {
+ const SkRasterClip& rasterClip = *draw.fRC;
- if (!clipper.done()) {
- const SkIRect& cr = clipper.rect();
- const uint8_t* aa = (uint8_t*)state.fCache->findImage(glyph);
- if (nullptr == aa) {
- return;
+ if (rasterClip.isBW()) {
+ return rasterClip.bwRgn().getBounds();
+ } else {
+ return rasterClip.aaRgn().getBounds();
}
-
- mask.fRowBytes = glyph.rowBytes();
- mask.fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
- mask.fImage = (uint8_t*)aa;
- do {
- state.blitMask(mask, cr);
- clipper.next();
- } while (!clipper.done());
}
-}
-
-SkDraw1Glyph::Proc SkDraw1Glyph::init(const SkDraw* draw, SkBlitter* blitter, SkGlyphCache* cache,
- const SkPaint& pnt) {
- fDraw = draw;
- fBlitter = blitter;
- fCache = cache;
- fPaint = &pnt;
- if (cache->isSubpixel()) {
- fHalfSampleX = fHalfSampleY = SkFixedToScalar(SkGlyph::kSubpixelRound);
- } else {
- fHalfSampleX = fHalfSampleY = SK_ScalarHalf;
+ bool getImageData(const SkGlyph& glyph, SkMask* mask) {
+ uint8_t* bits = (uint8_t*)(fGlyphCache->findImage(glyph));
+ if (nullptr == bits) {
+ return false; // can't rasterize glyph
+ }
+ mask->fImage = bits;
+ mask->fRowBytes = glyph.rowBytes();
+ mask->fFormat = static_cast<SkMask::Format>(glyph.fMaskFormat);
+ return true;
}
- if (draw->fRC->isBW()) {
- fAAClip = nullptr;
- fClip = &draw->fRC->bwRgn();
- fClipBounds = fClip->getBounds();
- if (fClip->isRect()) {
- return D1G_RectClip;
+ void blitMask(const SkMask& mask, const SkIRect& clip) const {
+ if (SkMask::kARGB32_Format == mask.fFormat) {
+ SkBitmap bm;
+ bm.installPixels(
+ SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
+ (SkPMColor*)mask.fImage, mask.fRowBytes);
+
+ fDraw.drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), fPaint);
} else {
- return D1G_RgnClip;
+ fBlitter->blitMask(mask, clip);
}
- } else { // aaclip
- fAAClip = &draw->fRC->aaRgn();
- fClip = nullptr;
- fClipBounds = fAAClip->getBounds();
- return D1G_RectClip;
}
-}
-
-void SkDraw1Glyph::blitMaskAsSprite(const SkMask& mask) const {
- SkASSERT(SkMask::kARGB32_Format == mask.fFormat);
- SkBitmap bm;
- bm.installPixels(SkImageInfo::MakeN32Premul(mask.fBounds.width(), mask.fBounds.height()),
- (SkPMColor*)mask.fImage, mask.fRowBytes);
-
- fDraw->drawSprite(bm, mask.fBounds.x(), mask.fBounds.y(), *fPaint);
-}
+ const bool fUseRegionToDraw;
+ SkGlyphCache * const fGlyphCache;
+ SkBlitter * const fBlitter;
+ const SkRegion* const fClip;
+ const SkDraw& fDraw;
+ const SkPaint& fPaint;
+ const SkIRect fClipBounds;
+};
-///////////////////////////////////////////////////////////////////////////////
+////////////////////////////////////////////////////////////////////////////////////////////////////
void SkDraw::drawText(const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) const {
@@ -1606,25 +1556,17 @@ void SkDraw::drawText(const char text[], size_t byteLength,
return;
}
- SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
- SkGlyphCache* cache = autoCache.getCache();
-
+ SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
+ SkGlyphCache* cache = autoCache.getCache();
// The Blitter Choose needs to be live while using the blitter below.
SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
-
- SkDraw1Glyph d1g;
- SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint);
+ DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
SkFindAndPlaceGlyph::ProcessText(
paint.getTextEncoding(), text, byteLength,
- {x, y}, *fMatrix, paint.getTextAlign(), cache,
- [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
- position += rounding;
- proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
- }
- );
+ {x, y}, *fMatrix, paint.getTextAlign(), cache, drawOneGlyph);
}
//////////////////////////////////////////////////////////////////////////////
@@ -1696,24 +1638,18 @@ void SkDraw::drawPosText(const char text[], size_t byteLength,
return;
}
+ SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
+ SkGlyphCache* cache = autoCache.getCache();
+
// The Blitter Choose needs to be live while using the blitter below.
SkAutoBlitterChoose blitterChooser(fDst, *fMatrix, paint);
SkAAClipBlitterWrapper wrapper(*fRC, blitterChooser.get());
-
- SkAutoGlyphCache autoCache(paint, &fDevice->surfaceProps(), fMatrix);
- SkGlyphCache* cache = autoCache.getCache();
- SkDraw1Glyph d1g;
- SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint);
- SkPaint::Align textAlignment = paint.getTextAlign();
+ DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
+ SkPaint::Align textAlignment = paint.getTextAlign();
SkFindAndPlaceGlyph::ProcessPosText(
paint.getTextEncoding(), text, byteLength,
- offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache,
- [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
- position += rounding;
- proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
- }
- );
+ offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, drawOneGlyph);
}
#if defined _WIN32 && _MSC_VER >= 1300
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698