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

Unified Diff: src/core/SkDraw.cpp

Issue 1486723004: Revert of Simplify draw one glyph (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Created 5 years 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 2fa6273112cf0975623755f6a4b04b4a8c386b45..e1a49d39b4a582265dda15c430ffbf95578bc297 100644
--- a/src/core/SkDraw.cpp
+++ b/src/core/SkDraw.cpp
@@ -1423,120 +1423,170 @@
#endif
////////////////////////////////////////////////////////////////////////////////////////////////////
-
-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);
-
- left += glyph.fLeft;
- top += glyph.fTop;
-
- int right = left + glyph.fWidth;
- int bottom = top + glyph.fHeight;
-
- SkMask mask;
- mask.fBounds.set(left, top, right, bottom);
-
- if (fUseRegionToDraw) {
- SkRegion::Cliperator clipper(*fClip, mask.fBounds);
-
- 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;
- }
-
- if (this->getImageData(glyph, &mask)) {
- this->blitMask(mask, *bounds);
- }
- }
- }
-
-private:
- static bool UsingRegionToDraw(const SkRasterClip* rClip) {
- return rClip->isBW() && !rClip->isRect();
- }
-
- static SkIRect PickClipBounds(const SkDraw& draw) {
- const SkRasterClip& rasterClip = *draw.fRC;
-
- if (rasterClip.isBW()) {
- return rasterClip.bwRgn().getBounds();
- } else {
- return rasterClip.aaRgn().getBounds();
- }
- }
-
- 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;
- }
-
+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) {
- 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);
+ this->blitMaskAsSprite(mask);
} else {
fBlitter->blitMask(mask, clip);
}
}
- const bool fUseRegionToDraw;
- SkGlyphCache * const fGlyphCache;
- SkBlitter * const fBlitter;
- const SkRegion* const fClip;
- const SkDraw& fDraw;
- const SkPaint& fPaint;
- const SkIRect fClipBounds;
+ // 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;
+ }
+
+ 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()));
+
+ left += glyph.fLeft;
+ top += glyph.fTop;
+
+ int right = left + glyph.fWidth;
+ int bottom = top + glyph.fHeight;
+
+ SkMask mask;
+ SkIRect storage;
+ SkIRect* bounds = &mask.fBounds;
+
+ mask.fBounds.set(left, top, right, bottom);
+
+ // 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;
+ }
+
+ 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
+ }
+ }
+
+ 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;
+
+ mask.fBounds.set(left, top, left + glyph.fWidth, top + glyph.fHeight);
+ SkRegion::Cliperator clipper(*state.fClip, mask.fBounds);
+
+ if (!clipper.done()) {
+ const SkIRect& cr = clipper.rect();
+ const uint8_t* aa = (uint8_t*)state.fCache->findImage(glyph);
+ if (nullptr == aa) {
+ return;
+ }
+
+ 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;
+ }
+
+ if (draw->fRC->isBW()) {
+ fAAClip = nullptr;
+ fClip = &draw->fRC->bwRgn();
+ fClipBounds = fClip->getBounds();
+ if (fClip->isRect()) {
+ return D1G_RectClip;
+ } else {
+ return D1G_RgnClip;
+ }
+ } 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);
+}
+
+///////////////////////////////////////////////////////////////////////////////
void SkDraw::drawText(const char text[], size_t byteLength,
SkScalar x, SkScalar y, const SkPaint& paint) const {
@@ -1556,17 +1606,25 @@
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());
- DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
+
+ SkDraw1Glyph d1g;
+ SkDraw1Glyph::Proc proc = d1g.init(this, wrapper.getBlitter(), cache, paint);
SkFindAndPlaceGlyph::ProcessText(
paint.getTextEncoding(), text, byteLength,
- {x, y}, *fMatrix, paint.getTextAlign(), cache, drawOneGlyph);
+ {x, y}, *fMatrix, paint.getTextAlign(), cache,
+ [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
+ position += rounding;
+ proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
+ }
+ );
}
//////////////////////////////////////////////////////////////////////////////
@@ -1638,18 +1696,24 @@
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());
- DrawOneGlyph drawOneGlyph(*this, paint, cache, wrapper.getBlitter());
- SkPaint::Align textAlignment = paint.getTextAlign();
+
+ 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();
SkFindAndPlaceGlyph::ProcessPosText(
paint.getTextEncoding(), text, byteLength,
- offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache, drawOneGlyph);
+ offset, *fMatrix, pos, scalarsPerPosition, textAlignment, cache,
+ [&](const SkGlyph& glyph, SkPoint position, SkPoint rounding) {
+ position += rounding;
+ proc(d1g, SkScalarTo48Dot16(position.fX), SkScalarTo48Dot16(position.fY), glyph);
+ }
+ );
}
#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