summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTorne (Richard Coles) <torne@google.com>2013-09-05 16:25:26 +0100
committerTorne (Richard Coles) <torne@google.com>2013-09-05 16:25:26 +0100
commit8d45e2ee426c8ec7e7262d20e9a55d5462afa720 (patch)
treec1be11925c5726f2ccfb9b6f3a34b85ef8e0de5a
parent754def2f35d1fb9b3b4000fb71399a9b64f7f336 (diff)
parentb761984a9fdb89ac1b588a92f3b37b50eb3d6a9f (diff)
downloadsrc-8d45e2ee426c8ec7e7262d20e9a55d5462afa720.tar.gz
Merge third_party/skia/src from https://chromium.googlesource.com/a/external/skia/src.git at b761984a9fdb89ac1b588a92f3b37b50eb3d6a9f
This commit was generated by merge_from_chromium.py. Change-Id: I518d7882062c7679bf22e1e9a03c538b2d3a4c44
-rw-r--r--core/SkDeviceLooper.cpp114
-rw-r--r--core/SkDeviceLooper.h96
-rw-r--r--core/SkDraw.cpp91
3 files changed, 260 insertions, 41 deletions
diff --git a/core/SkDeviceLooper.cpp b/core/SkDeviceLooper.cpp
new file mode 100644
index 00000000..4122fd7a
--- /dev/null
+++ b/core/SkDeviceLooper.cpp
@@ -0,0 +1,114 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#include "SkDeviceLooper.h"
+
+SkDeviceLooper::SkDeviceLooper(const SkBitmap& base,
+ const SkRasterClip& rc,
+ const SkIRect& bounds, bool aa)
+: fBaseBitmap(base)
+, fBaseRC(rc)
+, fDelta(aa ? kAA_Delta : kBW_Delta)
+{
+ // sentinels that next() has not yet been called, and so our mapper functions
+ // should not be called either.
+ fCurrBitmap = NULL;
+ fCurrRC = NULL;
+
+ SkIRect bitmapBounds = SkIRect::MakeWH(base.width(), base.height());
+ if (!fClippedBounds.intersect(bounds, bitmapBounds)) {
+ fState = kDone_State;
+ } else if (this->fitsInDelta(bounds)) {
+ fState = kSimple_State;
+ } else {
+ // back up by 1 DX, so that next() will put us in a correct starting
+ // position.
+ fCurrOffset.set(fClippedBounds.left() - fDelta,
+ fClippedBounds.top());
+ fState = kComplex_State;
+ }
+}
+
+SkDeviceLooper::~SkDeviceLooper() {
+}
+
+void SkDeviceLooper::mapRect(SkRect* dst, const SkRect& src) const {
+ SkASSERT(kDone_State != fState);
+ SkASSERT(fCurrBitmap);
+ SkASSERT(fCurrRC);
+
+ *dst = src;
+ dst->offset(SkIntToScalar(-fCurrOffset.fX),
+ SkIntToScalar(-fCurrOffset.fY));
+}
+
+void SkDeviceLooper::mapMatrix(SkMatrix* dst, const SkMatrix& src) const {
+ SkASSERT(kDone_State != fState);
+ SkASSERT(fCurrBitmap);
+ SkASSERT(fCurrRC);
+
+ *dst = src;
+ dst->postTranslate(SkIntToScalar(-fCurrOffset.fX),
+ SkIntToScalar(-fCurrOffset.fY));
+}
+
+bool SkDeviceLooper::computeCurrBitmapAndClip() {
+ SkASSERT(kComplex_State == fState);
+
+ SkIRect r = SkIRect::MakeXYWH(fCurrOffset.x(), fCurrOffset.y(),
+ fDelta, fDelta);
+ if (!fBaseBitmap.extractSubset(&fSubsetBitmap, r)) {
+ fState = kDone_State;
+ return false;
+ }
+ fSubsetBitmap.lockPixels();
+
+ fBaseRC.translate(-r.left(), -r.top(), &fSubsetRC);
+ (void)fSubsetRC.op(SkIRect::MakeWH(fDelta, fDelta), SkRegion::kIntersect_Op);
+
+ fCurrBitmap = &fSubsetBitmap;
+ fCurrRC = &fSubsetRC;
+ return true;
+}
+
+bool SkDeviceLooper::next() {
+ switch (fState) {
+ case kDone_State:
+ // in theory, we should not get called here, since we must have
+ // previously returned false, but we check anyway.
+ break;
+
+ case kSimple_State:
+ // first time for simple
+ if (NULL == fCurrBitmap) {
+ fCurrBitmap = &fBaseBitmap;
+ fCurrRC = &fBaseRC;
+ fCurrOffset.set(0, 0);
+ return true;
+ }
+ // 2nd time for simple, we are done
+ break;
+
+ case kComplex_State:
+ // need to propogate fCurrOffset through clippedbounds
+ // left to right, until we wrap around and move down
+
+ if (fCurrOffset.x() + fDelta < fClippedBounds.right()) {
+ fCurrOffset.fX += fDelta;
+ return this->computeCurrBitmapAndClip();
+ }
+ fCurrOffset.fX = fClippedBounds.left();
+ if (fCurrOffset.y() + fDelta < fClippedBounds.bottom()) {
+ fCurrOffset.fY += fDelta;
+ return this->computeCurrBitmapAndClip();
+ }
+ break;
+ }
+
+ fState = kDone_State;
+ return false;
+}
diff --git a/core/SkDeviceLooper.h b/core/SkDeviceLooper.h
new file mode 100644
index 00000000..405173dd
--- /dev/null
+++ b/core/SkDeviceLooper.h
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2013 Google Inc.
+ *
+ * Use of this source code is governed by a BSD-style license that can be
+ * found in the LICENSE file.
+ */
+
+#ifndef SkDeviceLooper_DEFINED
+#define SkDeviceLooper_DEFINED
+
+#include "SkBitmap.h"
+#include "SkMatrix.h"
+#include "SkRasterClip.h"
+
+/**
+ * Helper class to manage "tiling" a large coordinate space into managable
+ * chunks, where managable means areas that are <= some max critical coordinate
+ * size.
+ *
+ * The constructor takes an antialiasing bool, which affects what this maximum
+ * allowable size is: If we're drawing BW, then we need coordinates to stay
+ * safely within fixed-point range (we use +- 16K, to give ourselves room to
+ * add/subtract two fixed values and still be in range. If we're drawing AA,
+ * then we reduce that size by the amount that the supersampler scan converter
+ * needs (at the moment, that is 4X, so the "safe" range is +- 4K).
+ *
+ * For performance reasons, the class first checks to see if any help is needed
+ * at all, and if not (i.e. the specified bounds and base bitmap area already
+ * in the safe-zone, then the class does nothing (effectively).
+ */
+class SkDeviceLooper {
+public:
+ SkDeviceLooper(const SkBitmap& base, const SkRasterClip&,
+ const SkIRect& bounds, bool aa);
+ ~SkDeviceLooper();
+
+ const SkBitmap& getBitmap() const {
+ SkASSERT(kDone_State != fState);
+ SkASSERT(fCurrBitmap);
+ return *fCurrBitmap;
+ }
+
+ const SkRasterClip& getRC() const {
+ SkASSERT(kDone_State != fState);
+ SkASSERT(fCurrRC);
+ return *fCurrRC;
+ }
+
+ void mapRect(SkRect* dst, const SkRect& src) const;
+ void mapMatrix(SkMatrix* dst, const SkMatrix& src) const;
+
+ /**
+ * Call next to setup the looper to return a valid coordinate chunk.
+ * Each time this returns true, it is safe to call mapRect() and
+ * mapMatrix(), to convert from "global" coordinate values to ones that
+ * are local to this chunk.
+ *
+ * When next() returns false, the list of chunks is done, and mapRect()
+ * and mapMatrix() should no longer be called.
+ */
+ bool next();
+
+private:
+ const SkBitmap& fBaseBitmap;
+ const SkRasterClip& fBaseRC;
+
+ enum State {
+ kDone_State, // iteration is complete, getters will assert
+ kSimple_State, // no translate/clip mods needed
+ kComplex_State
+ };
+
+ // storage for our tiled versions. Perhaps could use SkTLazy
+ SkBitmap fSubsetBitmap;
+ SkRasterClip fSubsetRC;
+
+ const SkBitmap* fCurrBitmap;
+ const SkRasterClip* fCurrRC;
+ SkIRect fClippedBounds;
+ SkIPoint fCurrOffset;
+ int fDelta;
+ State fState;
+
+ enum Delta {
+ kBW_Delta = 1 << 14, // 16K, gives room to spare for fixedpoint
+ kAA_Delta = kBW_Delta >> 2 // supersample 4x
+ };
+
+ bool fitsInDelta(const SkIRect& r) const {
+ return r.right() < fDelta && r.bottom() < fDelta;
+ }
+
+ bool computeCurrBitmapAndClip();
+};
+
+#endif
diff --git a/core/SkDraw.cpp b/core/SkDraw.cpp
index 671da49d..a9d5fbb0 100644
--- a/core/SkDraw.cpp
+++ b/core/SkDraw.cpp
@@ -5,13 +5,13 @@
* found in the LICENSE file.
*/
-
#include "SkDraw.h"
#include "SkBlitter.h"
#include "SkBounder.h"
#include "SkCanvas.h"
#include "SkColorPriv.h"
#include "SkDevice.h"
+#include "SkDeviceLooper.h"
#include "SkFixed.h"
#include "SkMaskFilter.h"
#include "SkPaint.h"
@@ -873,48 +873,56 @@ void SkDraw::drawRect(const SkRect& rect, const SkPaint& paint) const {
}
// look for the quick exit, before we build a blitter
- if (true) {
- SkIRect ir;
- devRect.roundOut(&ir);
- if (paint.getStyle() != SkPaint::kFill_Style) {
- // extra space for hairlines
- ir.inset(-1, -1);
- }
- if (fRC->quickReject(ir))
- return;
+ SkIRect ir;
+ devRect.roundOut(&ir);
+ if (paint.getStyle() != SkPaint::kFill_Style) {
+ // extra space for hairlines
+ ir.inset(-1, -1);
+ }
+ if (fRC->quickReject(ir)) {
+ return;
}
- SkAutoBlitterChoose blitterStorage(*fBitmap, matrix, paint);
- const SkRasterClip& clip = *fRC;
- SkBlitter* blitter = blitterStorage.get();
-
- // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
- // case we are also hairline (if we've gotten to here), which devolves to
- // effectively just kFill
- switch (rtype) {
- case kFill_RectType:
- if (paint.isAntiAlias()) {
- SkScan::AntiFillRect(devRect, clip, blitter);
- } else {
- SkScan::FillRect(devRect, clip, blitter);
- }
- break;
- case kStroke_RectType:
- if (paint.isAntiAlias()) {
- SkScan::AntiFrameRect(devRect, strokeSize, clip, blitter);
- } else {
- SkScan::FrameRect(devRect, strokeSize, clip, blitter);
- }
- break;
- case kHair_RectType:
- if (paint.isAntiAlias()) {
- SkScan::AntiHairRect(devRect, clip, blitter);
- } else {
- SkScan::HairRect(devRect, clip, blitter);
- }
- break;
- default:
- SkDEBUGFAIL("bad rtype");
+ SkDeviceLooper looper(*fBitmap, *fRC, ir, paint.isAntiAlias());
+ while (looper.next()) {
+ SkRect localDevRect;
+ looper.mapRect(&localDevRect, devRect);
+ SkMatrix localMatrix;
+ looper.mapMatrix(&localMatrix, matrix);
+
+ SkAutoBlitterChoose blitterStorage(looper.getBitmap(), localMatrix,
+ paint);
+ const SkRasterClip& clip = looper.getRC();
+ SkBlitter* blitter = blitterStorage.get();
+
+ // we want to "fill" if we are kFill or kStrokeAndFill, since in the latter
+ // case we are also hairline (if we've gotten to here), which devolves to
+ // effectively just kFill
+ switch (rtype) {
+ case kFill_RectType:
+ if (paint.isAntiAlias()) {
+ SkScan::AntiFillRect(localDevRect, clip, blitter);
+ } else {
+ SkScan::FillRect(localDevRect, clip, blitter);
+ }
+ break;
+ case kStroke_RectType:
+ if (paint.isAntiAlias()) {
+ SkScan::AntiFrameRect(localDevRect, strokeSize, clip, blitter);
+ } else {
+ SkScan::FrameRect(localDevRect, strokeSize, clip, blitter);
+ }
+ break;
+ case kHair_RectType:
+ if (paint.isAntiAlias()) {
+ SkScan::AntiHairRect(localDevRect, clip, blitter);
+ } else {
+ SkScan::HairRect(localDevRect, clip, blitter);
+ }
+ break;
+ default:
+ SkDEBUGFAIL("bad rtype");
+ }
}
}
@@ -2825,3 +2833,4 @@ bool SkDraw::DrawToMask(const SkPath& devPath, const SkIRect* clipBounds,
return true;
}
+