summaryrefslogtreecommitdiff
path: root/core
diff options
context:
space:
mode:
authorBo Liu <boliu@google.com>2014-05-01 10:38:38 -0700
committerBo Liu <boliu@google.com>2014-05-01 10:38:38 -0700
commit27ab20dffff01006f5d20fdb2b3f4ea503d69114 (patch)
treef8a42f1186f835772ed0c20a7f9095392e124b04 /core
parent51512eaae8128a677f92e2689d8df720dca13d32 (diff)
parent2e8705638185600b128f867809b6cd034225451c (diff)
downloadsrc-27ab20dffff01006f5d20fdb2b3f4ea503d69114.tar.gz
Merge from Chromium at DEPS revision 267519idea133-weekly-release
This commit was generated by merge_to_master.py. Change-Id: Ic063600f0ecbd8d3c74d2d514eaf91c1a33c9f07
Diffstat (limited to 'core')
-rw-r--r--core/SkBBoxHierarchyRecord.cpp5
-rw-r--r--core/SkBBoxHierarchyRecord.h3
-rw-r--r--core/SkBBoxRecord.h4
-rw-r--r--core/SkBitmapDevice.cpp4
-rw-r--r--core/SkBitmapProcShader.cpp11
-rw-r--r--core/SkBitmapProcShader.h5
-rw-r--r--core/SkBlitter.cpp3
-rw-r--r--core/SkCanvas.cpp21
-rw-r--r--core/SkComposeShader.cpp4
-rw-r--r--core/SkDraw.cpp13
-rw-r--r--core/SkDrawLooper.cpp4
-rwxr-xr-xcore/SkGlyphCache.cpp11
-rw-r--r--core/SkMaskFilter.cpp4
-rw-r--r--core/SkPicture.cpp203
-rw-r--r--core/SkPicturePlayback.cpp170
-rw-r--r--core/SkPicturePlayback.h35
-rw-r--r--core/SkPictureRecord.cpp27
-rw-r--r--core/SkPictureRecord.h6
-rw-r--r--core/SkPictureShader.cpp3
-rw-r--r--core/SkPictureStateTree.cpp11
-rw-r--r--core/SkQuadTree.cpp1
-rw-r--r--core/SkReadBuffer.cpp4
-rw-r--r--core/SkRegion.cpp4
-rw-r--r--core/SkRegionPriv.h4
-rw-r--r--core/SkScalerContext.cpp5
-rw-r--r--core/SkShader.cpp60
-rw-r--r--core/SkSmallAllocator.h10
-rw-r--r--core/SkStream.cpp16
-rw-r--r--core/SkValidatingReadBuffer.cpp6
-rw-r--r--core/SkWriter32.cpp4
30 files changed, 393 insertions, 268 deletions
diff --git a/core/SkBBoxHierarchyRecord.cpp b/core/SkBBoxHierarchyRecord.cpp
index 16ade774..f0382e64 100644
--- a/core/SkBBoxHierarchyRecord.cpp
+++ b/core/SkBBoxHierarchyRecord.cpp
@@ -9,10 +9,11 @@
#include "SkBBoxHierarchyRecord.h"
#include "SkPictureStateTree.h"
-SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(const SkISize& size,
+SkBBoxHierarchyRecord::SkBBoxHierarchyRecord(SkPicture* picture,
+ const SkISize& size,
uint32_t recordFlags,
SkBBoxHierarchy* h)
- : INHERITED(size, recordFlags) {
+ : INHERITED(picture, size, recordFlags) {
fStateTree = SkNEW(SkPictureStateTree);
fBoundingHierarchy = h;
fBoundingHierarchy->ref();
diff --git a/core/SkBBoxHierarchyRecord.h b/core/SkBBoxHierarchyRecord.h
index 51fce0d8..f6fac180 100644
--- a/core/SkBBoxHierarchyRecord.h
+++ b/core/SkBBoxHierarchyRecord.h
@@ -19,7 +19,8 @@
class SkBBoxHierarchyRecord : public SkBBoxRecord, public SkBBoxHierarchyClient {
public:
/** This will take a ref of h */
- SkBBoxHierarchyRecord(const SkISize& size, uint32_t recordFlags, SkBBoxHierarchy* h);
+ SkBBoxHierarchyRecord(SkPicture* picture, const SkISize& size,
+ uint32_t recordFlags, SkBBoxHierarchy* h);
virtual void handleBBox(const SkRect& bounds) SK_OVERRIDE;
diff --git a/core/SkBBoxRecord.h b/core/SkBBoxRecord.h
index 3a0c53bf..f2e9d8d2 100644
--- a/core/SkBBoxRecord.h
+++ b/core/SkBBoxRecord.h
@@ -19,7 +19,9 @@
class SkBBoxRecord : public SkPictureRecord {
public:
- SkBBoxRecord(const SkISize& size, uint32_t recordFlags) : INHERITED(size, recordFlags) {}
+ SkBBoxRecord(SkPicture* picture, const SkISize& size, uint32_t recordFlags)
+ : INHERITED(picture, size, recordFlags) {
+ }
virtual ~SkBBoxRecord() { }
/**
diff --git a/core/SkBitmapDevice.cpp b/core/SkBitmapDevice.cpp
index c2b633e1..311e72f5 100644
--- a/core/SkBitmapDevice.cpp
+++ b/core/SkBitmapDevice.cpp
@@ -381,11 +381,11 @@ void SkBitmapDevice::drawBitmapRect(const SkDraw& draw, const SkBitmap& bitmap,
// construct a shader, so we can call drawRect with the dst
SkShader* s = SkShader::CreateBitmapShader(*bitmapPtr,
SkShader::kClamp_TileMode,
- SkShader::kClamp_TileMode);
+ SkShader::kClamp_TileMode,
+ &matrix);
if (NULL == s) {
return;
}
- s->setLocalMatrix(matrix);
SkPaint paintWithShader(paint);
paintWithShader.setStyle(SkPaint::kFill_Style);
diff --git a/core/SkBitmapProcShader.cpp b/core/SkBitmapProcShader.cpp
index 5f5eb186..44bdc6d3 100644
--- a/core/SkBitmapProcShader.cpp
+++ b/core/SkBitmapProcShader.cpp
@@ -31,8 +31,9 @@ bool SkBitmapProcShader::CanDo(const SkBitmap& bm, TileMode tx, TileMode ty) {
return false;
}
-SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src,
- TileMode tmx, TileMode tmy) {
+SkBitmapProcShader::SkBitmapProcShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix)
+ : INHERITED(localMatrix) {
fRawBitmap = src;
fTileModeX = (uint8_t)tmx;
fTileModeY = (uint8_t)tmy;
@@ -347,7 +348,7 @@ static bool bitmapIsTooBig(const SkBitmap& bm) {
}
SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
- SkShader::TileMode tmy, SkTBlitterAllocator* allocator) {
+ SkShader::TileMode tmy, const SkMatrix* localMatrix, SkTBlitterAllocator* allocator) {
SkShader* shader;
SkColor color;
if (src.isNull() || bitmapIsTooBig(src)) {
@@ -365,9 +366,9 @@ SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode tmx,
}
} else {
if (NULL == allocator) {
- shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy));
+ shader = SkNEW_ARGS(SkBitmapProcShader, (src, tmx, tmy, localMatrix));
} else {
- shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy);
+ shader = allocator->createT<SkBitmapProcShader>(src, tmx, tmy, localMatrix);
}
}
return shader;
diff --git a/core/SkBitmapProcShader.h b/core/SkBitmapProcShader.h
index e0c78b8e..78b46ce6 100644
--- a/core/SkBitmapProcShader.h
+++ b/core/SkBitmapProcShader.h
@@ -16,7 +16,8 @@
class SkBitmapProcShader : public SkShader {
public:
- SkBitmapProcShader(const SkBitmap& src, TileMode tx, TileMode ty);
+ SkBitmapProcShader(const SkBitmap& src, TileMode tx, TileMode ty,
+ const SkMatrix* localMatrix = NULL);
// overrides from SkShader
virtual bool isOpaque() const SK_OVERRIDE;
@@ -91,6 +92,6 @@ typedef SkSmallAllocator<3, sizeof(SkBitmapProcShader) +
// If alloc is non-NULL, it will be used to allocate the returned SkShader, and MUST outlive
// the SkShader.
SkShader* CreateBitmapShader(const SkBitmap& src, SkShader::TileMode, SkShader::TileMode,
- SkTBlitterAllocator* alloc);
+ const SkMatrix* localMatrix, SkTBlitterAllocator* alloc);
#endif
diff --git a/core/SkBlitter.cpp b/core/SkBlitter.cpp
index 7243f521..41f37e65 100644
--- a/core/SkBlitter.cpp
+++ b/core/SkBlitter.cpp
@@ -928,8 +928,9 @@ SkBlitter* SkBlitter::Choose(const SkBitmap& device,
if (NULL == shader) {
if (mode) {
// xfermodes (and filters) require shaders for our current blitters
- shader = SkNEW(SkColorShader);
+ shader = SkNEW_ARGS(SkColorShader, (paint->getColor()));
paint.writable()->setShader(shader)->unref();
+ paint.writable()->setAlpha(0xFF);
} else if (cf) {
// if no shader && no xfermode, we just apply the colorfilter to
// our color and move on.
diff --git a/core/SkCanvas.cpp b/core/SkCanvas.cpp
index e3451cde..6c0fc884 100644
--- a/core/SkCanvas.cpp
+++ b/core/SkCanvas.cpp
@@ -834,6 +834,11 @@ void SkCanvas::willSave(SaveFlags) {
// Do nothing. Subclasses may do something.
}
+int SkCanvas::save() {
+ this->willSave(kMatrixClip_SaveFlag);
+ return this->internalSave(kMatrixClip_SaveFlag);
+}
+
int SkCanvas::save(SaveFlags flags) {
this->willSave(flags);
// call shared impl
@@ -898,9 +903,13 @@ SkCanvas::SaveLayerStrategy SkCanvas::willSaveLayer(const SkRect*, const SkPaint
return kFullLayer_SaveLayerStrategy;
}
+int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint) {
+ SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag);
+ return this->internalSaveLayer(bounds, paint, kARGB_ClipLayer_SaveFlag, false, strategy);
+}
+
int SkCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
SaveFlags flags) {
- // Overriding classes may return false to signal that we don't need to create a layer.
SaveLayerStrategy strategy = this->willSaveLayer(bounds, paint, flags);
return this->internalSaveLayer(bounds, paint, flags, false, strategy);
}
@@ -975,6 +984,10 @@ int SkCanvas::internalSaveLayer(const SkRect* bounds, const SkPaint* paint, Save
return count;
}
+int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha) {
+ return this->saveLayerAlpha(bounds, alpha, kARGB_ClipLayer_SaveFlag);
+}
+
int SkCanvas::saveLayerAlpha(const SkRect* bounds, U8CPU alpha,
SaveFlags flags) {
if (0xFF == alpha) {
@@ -2343,7 +2356,7 @@ void SkCanvas::onDrawPosText(const void* text, size_t byteLength, const SkPoint
iter.fDevice->drawPosText(iter, text, byteLength, &pos->fX, 0, 2,
dfp.paint());
}
-
+
LOOPER_END
}
@@ -2356,7 +2369,7 @@ void SkCanvas::onDrawPosTextH(const void* text, size_t byteLength, const SkScala
iter.fDevice->drawPosText(iter, text, byteLength, xpos, constY, 1,
dfp.paint());
}
-
+
LOOPER_END
}
@@ -2368,7 +2381,7 @@ void SkCanvas::onDrawTextOnPath(const void* text, size_t byteLength, const SkPat
iter.fDevice->drawTextOnPath(iter, text, byteLength, path,
matrix, looper.paint());
}
-
+
LOOPER_END
}
diff --git a/core/SkComposeShader.cpp b/core/SkComposeShader.cpp
index 77bc46f3..2c27c9e7 100644
--- a/core/SkComposeShader.cpp
+++ b/core/SkComposeShader.cpp
@@ -30,11 +30,11 @@ SkComposeShader::SkComposeShader(SkReadBuffer& buffer) :
INHERITED(buffer) {
fShaderA = buffer.readShader();
if (NULL == fShaderA) {
- fShaderA = SkNEW_ARGS(SkColorShader, (0));
+ fShaderA = SkNEW_ARGS(SkColorShader, ((SkColor)0));
}
fShaderB = buffer.readShader();
if (NULL == fShaderB) {
- fShaderB = SkNEW_ARGS(SkColorShader, (0));
+ fShaderB = SkNEW_ARGS(SkColorShader, ((SkColor)0));
}
fMode = buffer.readXfermode();
}
diff --git a/core/SkDraw.cpp b/core/SkDraw.cpp
index 6ddd0d27..f9e06e52 100644
--- a/core/SkDraw.cpp
+++ b/core/SkDraw.cpp
@@ -72,11 +72,12 @@ private:
*/
class SkAutoBitmapShaderInstall : SkNoncopyable {
public:
- SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint)
+ SkAutoBitmapShaderInstall(const SkBitmap& src, const SkPaint& paint,
+ const SkMatrix* localMatrix = NULL)
: fPaint(paint) /* makes a copy of the paint */ {
fPaint.setShader(CreateBitmapShader(src, SkShader::kClamp_TileMode,
SkShader::kClamp_TileMode,
- &fAllocator));
+ localMatrix, &fAllocator));
// we deliberately left the shader with an owner-count of 2
SkASSERT(2 == fPaint.getShader()->getRefCnt());
}
@@ -1374,18 +1375,16 @@ void SkDraw::drawSprite(const SkBitmap& bitmap, int x, int y,
}
}
- SkAutoBitmapShaderInstall install(bitmap, paint);
- const SkPaint& shaderPaint = install.paintWithShader();
-
SkMatrix matrix;
SkRect r;
// get a scalar version of our rect
r.set(bounds);
- // tell the shader our offset
+ // create shader with offset
matrix.setTranslate(r.fLeft, r.fTop);
- shaderPaint.getShader()->setLocalMatrix(matrix);
+ SkAutoBitmapShaderInstall install(bitmap, paint, &matrix);
+ const SkPaint& shaderPaint = install.paintWithShader();
SkDraw draw(*this);
matrix.reset();
diff --git a/core/SkDrawLooper.cpp b/core/SkDrawLooper.cpp
index c620cd08..d18d1271 100644
--- a/core/SkDrawLooper.cpp
+++ b/core/SkDrawLooper.cpp
@@ -59,3 +59,7 @@ void SkDrawLooper::computeFastBounds(const SkPaint& paint, const SkRect& src,
}
}
}
+
+bool SkDrawLooper::asABlurShadow(BlurShadowRec*) const {
+ return false;
+}
diff --git a/core/SkGlyphCache.cpp b/core/SkGlyphCache.cpp
index 7b57e2f5..cb7c1b0a 100755
--- a/core/SkGlyphCache.cpp
+++ b/core/SkGlyphCache.cpp
@@ -11,6 +11,7 @@
#include "SkGlyphCache_Globals.h"
#include "SkDistanceFieldGen.h"
#include "SkGraphics.h"
+#include "SkOnce.h"
#include "SkPaint.h"
#include "SkPath.h"
#include "SkTemplates.h"
@@ -22,11 +23,17 @@
bool gSkSuppressFontCachePurgeSpew;
+static void create_globals(SkGlyphCache_Globals** globals) {
+ *globals = SkNEW_ARGS(SkGlyphCache_Globals, (SkGlyphCache_Globals::kYes_UseMutex));
+}
+
// Returns the shared globals
static SkGlyphCache_Globals& getSharedGlobals() {
// we leak this, so we don't incur any shutdown cost of the destructor
- static SkGlyphCache_Globals* gGlobals = SkNEW_ARGS(SkGlyphCache_Globals,
- (SkGlyphCache_Globals::kYes_UseMutex));
+ static SkGlyphCache_Globals* gGlobals = NULL;
+ SK_DECLARE_STATIC_ONCE(once);
+ SkOnce(&once, create_globals, &gGlobals);
+ SkASSERT(NULL != gGlobals);
return *gGlobals;
}
diff --git a/core/SkMaskFilter.cpp b/core/SkMaskFilter.cpp
index 9b023d0d..8b9792c2 100644
--- a/core/SkMaskFilter.cpp
+++ b/core/SkMaskFilter.cpp
@@ -26,6 +26,10 @@ bool SkMaskFilter::filterMask(SkMask*, const SkMask&, const SkMatrix&,
return false;
}
+bool SkMaskFilter::asABlur(BlurRec*) const {
+ return false;
+}
+
static void extractMaskSubset(const SkMask& src, SkMask* dst) {
SkASSERT(src.fBounds.contains(dst->fBounds));
diff --git a/core/SkPicture.cpp b/core/SkPicture.cpp
index 316994a2..3b04906e 100644
--- a/core/SkPicture.cpp
+++ b/core/SkPicture.cpp
@@ -31,6 +31,10 @@
#include "GrContext.h"
#endif
+template <typename T> int SafeCount(const T* obj) {
+ return obj ? obj->count() : 0;
+}
+
#define DUMP_BUFFER_SIZE 65536
//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw
@@ -118,17 +122,18 @@ static void validateMatrix(const SkMatrix* matrix) {
///////////////////////////////////////////////////////////////////////////////
-SkPicture::SkPicture() {
+SkPicture::SkPicture()
+ : fAccelData(NULL) {
this->needsNewGenID();
fRecord = NULL;
fPlayback = NULL;
fWidth = fHeight = 0;
- fAccelData = NULL;
}
SkPicture::SkPicture(const SkPicture& src)
: INHERITED()
- , fAccelData(NULL) {
+ , fAccelData(NULL)
+ , fContentInfo(src.fContentInfo) {
this->needsNewGenID();
fWidth = src.fWidth;
fHeight = src.fHeight;
@@ -139,17 +144,48 @@ SkPicture::SkPicture(const SkPicture& src)
it (since it is destructive, and we don't want to change src).
*/
if (src.fPlayback) {
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback));
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *src.fPlayback));
SkASSERT(NULL == src.fRecord);
fUniqueID = src.uniqueID(); // need to call method to ensure != 0
} else if (src.fRecord) {
SkPictInfo info;
this->createHeader(&info);
// here we do a fake src.endRecording()
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord, info));
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *src.fRecord, info));
} else {
fPlayback = NULL;
}
+
+ fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
+}
+
+const SkPath& SkPicture::getPath(int index) const {
+ return (*fPathHeap.get())[index];
+}
+
+int SkPicture::addPathToHeap(const SkPath& path) {
+ if (NULL == fPathHeap) {
+ fPathHeap.reset(SkNEW(SkPathHeap));
+ }
+#ifdef SK_DEDUP_PICTURE_PATHS
+ return fPathHeap->insert(path);
+#else
+ return fPathHeap->append(path);
+#endif
+}
+
+void SkPicture::initForPlayback() const {
+ // ensure that the paths bounds are pre-computed
+ if (NULL != fPathHeap.get()) {
+ for (int i = 0; i < fPathHeap->count(); i++) {
+ (*fPathHeap.get())[i].updateBoundsCache();
+ }
+ }
+}
+
+void SkPicture::dumpSize() const {
+ SkDebugf("--- picture size: paths=%d\n",
+ SafeCount(fPathHeap.get()));
}
SkPicture::~SkPicture() {
@@ -171,6 +207,8 @@ void SkPicture::swap(SkPicture& other) {
SkTSwap(fAccelData, other.fAccelData);
SkTSwap(fWidth, other.fWidth);
SkTSwap(fHeight, other.fHeight);
+ fPathHeap.swap(&other.fPathHeap);
+ fContentInfo.swap(&other.fContentInfo);
}
SkPicture* SkPicture::clone() const {
@@ -179,6 +217,26 @@ SkPicture* SkPicture::clone() const {
return clonedPicture;
}
+static bool needs_deep_copy(const SkPaint& paint) {
+ /*
+ * These fields are known to be immutable, and so can be shallow-copied
+ *
+ * getTypeface()
+ * getAnnotation()
+ * paint.getColorFilter()
+ * getXfermode()
+ * getPathEffect()
+ * getMaskFilter()
+ */
+
+ return paint.getShader() ||
+#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
+ paint.getRasterizer() ||
+#endif
+ paint.getLooper() || // needs to hide its addLayer...
+ paint.getImageFilter();
+}
+
void SkPicture::clone(SkPicture* pictures, int count) const {
SkPictCopyInfo copyInfo;
SkPictInfo info;
@@ -192,21 +250,66 @@ void SkPicture::clone(SkPicture* pictures, int count) const {
clone->fHeight = fHeight;
SkSafeSetNull(clone->fRecord);
SkDELETE(clone->fPlayback);
+ clone->fContentInfo.set(fContentInfo);
/* We want to copy the src's playback. However, if that hasn't been built
yet, we need to fake a call to endRecording() without actually calling
it (since it is destructive, and we don't want to change src).
*/
if (fPlayback) {
- clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fPlayback, &copyInfo));
+ if (!copyInfo.initialized) {
+ int paintCount = SafeCount(fPlayback->fPaints);
+
+ /* The alternative to doing this is to have a clone method on the paint and have it
+ * make the deep copy of its internal structures as needed. The holdup to doing
+ * that is at this point we would need to pass the SkBitmapHeap so that we don't
+ * unnecessarily flatten the pixels in a bitmap shader.
+ */
+ copyInfo.paintData.setCount(paintCount);
+
+ /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is
+ * one, use it. If this SkPicturePlayback was created from a stream, fBitmapHeap
+ * will be NULL, so create a new one.
+ */
+ if (fPlayback->fBitmapHeap.get() == NULL) {
+ // FIXME: Put this on the stack inside SkPicture::clone.
+ SkBitmapHeap* heap = SkNEW(SkBitmapHeap);
+ copyInfo.controller.setBitmapStorage(heap);
+ heap->unref();
+ } else {
+ copyInfo.controller.setBitmapStorage(fPlayback->fBitmapHeap);
+ }
+
+ SkDEBUGCODE(int heapSize = SafeCount(fPlayback->fBitmapHeap.get());)
+ for (int i = 0; i < paintCount; i++) {
+ if (needs_deep_copy(fPlayback->fPaints->at(i))) {
+ copyInfo.paintData[i] =
+ SkFlatData::Create<SkPaint::FlatteningTraits>(&copyInfo.controller,
+ fPlayback->fPaints->at(i), 0);
+
+ } else {
+ // this is our sentinel, which we use in the unflatten loop
+ copyInfo.paintData[i] = NULL;
+ }
+ }
+ SkASSERT(SafeCount(fPlayback->fBitmapHeap.get()) == heapSize);
+
+ // needed to create typeface playback
+ copyInfo.controller.setupPlaybacks();
+ copyInfo.initialized = true;
+ }
+
+ clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (clone, *fPlayback, &copyInfo));
SkASSERT(NULL == fRecord);
clone->fUniqueID = this->uniqueID(); // need to call method to ensure != 0
} else if (fRecord) {
// here we do a fake src.endRecording()
- clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info, true));
+ clone->fPlayback = SkNEW_ARGS(SkPicturePlayback, (clone, *fRecord, info, true));
} else {
clone->fPlayback = NULL;
}
+
+ clone->fPathHeap.reset(SkSafeRef(fPathHeap.get()));
}
}
@@ -233,6 +336,7 @@ SkCanvas* SkPicture::beginRecording(int width, int height,
}
SkSafeUnref(fAccelData);
SkSafeSetNull(fRecord);
+ fContentInfo.reset();
this->needsNewGenID();
@@ -245,10 +349,10 @@ SkCanvas* SkPicture::beginRecording(int width, int height,
if (recordingFlags & kOptimizeForClippedPlayback_RecordingFlag) {
SkBBoxHierarchy* tree = this->createBBoxHierarchy();
SkASSERT(NULL != tree);
- fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size, recordingFlags, tree));
+ fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (this, size, recordingFlags, tree));
tree->unref();
} else {
- fRecord = SkNEW_ARGS(SkPictureRecord, (size, recordingFlags));
+ fRecord = SkNEW_ARGS(SkPictureRecord, (this, size, recordingFlags));
}
fRecord->beginRecording();
@@ -266,6 +370,8 @@ SkCanvas* SkPicture::beginRecording(int width, int height,
}
SkSafeUnref(fAccelData);
SkSafeSetNull(fRecord);
+ SkASSERT(NULL == fPathHeap);
+ fContentInfo.reset();
this->needsNewGenID();
@@ -277,12 +383,12 @@ SkCanvas* SkPicture::beginRecording(int width, int height,
if (NULL != bbhFactory) {
SkAutoTUnref<SkBBoxHierarchy> tree((*bbhFactory)(width, height));
SkASSERT(NULL != tree);
- fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (size,
+ fRecord = SkNEW_ARGS(SkBBoxHierarchyRecord, (this, size,
recordingFlags|
kOptimizeForClippedPlayback_RecordingFlag,
tree.get()));
} else {
- fRecord = SkNEW_ARGS(SkPictureRecord, (size, recordingFlags));
+ fRecord = SkNEW_ARGS(SkPictureRecord, (this, size, recordingFlags));
}
fRecord->beginRecording();
@@ -323,7 +429,7 @@ void SkPicture::endRecording() {
fRecord->endRecording();
SkPictInfo info;
this->createHeader(&info);
- fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info));
+ fPlayback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info));
SkSafeSetNull(fRecord);
}
}
@@ -424,18 +530,20 @@ SkPicture* SkPicture::CreateFromStream(SkStream* stream, InstallPixelRefProc pro
return NULL;
}
- SkPicturePlayback* playback;
+ SkPicture* newPict = SkNEW_ARGS(SkPicture, (NULL, info.fWidth, info.fHeight));
+
// Check to see if there is a playback to recreate.
if (stream->readBool()) {
- playback = SkPicturePlayback::CreateFromStream(stream, info, proc);
+ SkPicturePlayback* playback = SkPicturePlayback::CreateFromStream(newPict, stream,
+ info, proc);
if (NULL == playback) {
+ SkDELETE(newPict);
return NULL;
}
- } else {
- playback = NULL;
+ newPict->fPlayback = playback;
}
- return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
+ return newPict;
}
SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
@@ -445,18 +553,19 @@ SkPicture* SkPicture::CreateFromBuffer(SkReadBuffer& buffer) {
return NULL;
}
- SkPicturePlayback* playback;
+ SkPicture* newPict = SkNEW_ARGS(SkPicture, (NULL, info.fWidth, info.fHeight));
+
// Check to see if there is a playback to recreate.
if (buffer.readBool()) {
- playback = SkPicturePlayback::CreateFromBuffer(buffer, info);
+ SkPicturePlayback* playback = SkPicturePlayback::CreateFromBuffer(newPict, buffer, info);
if (NULL == playback) {
+ SkDELETE(newPict);
return NULL;
}
- } else {
- playback = NULL;
+ newPict->fPlayback = playback;
}
- return SkNEW_ARGS(SkPicture, (playback, info.fWidth, info.fHeight));
+ return newPict;
}
void SkPicture::createHeader(SkPictInfo* info) const {
@@ -484,7 +593,7 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
SkPictInfo info;
this->createHeader(&info);
if (NULL == playback && fRecord) {
- playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info));
+ playback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info));
}
stream->write(&info, sizeof(info));
@@ -500,13 +609,49 @@ void SkPicture::serialize(SkWStream* stream, EncodeBitmap encoder) const {
}
}
+void SkPicture::WriteTagSize(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
+ buffer.writeUInt(tag);
+ buffer.writeUInt(SkToU32(size));
+}
+
+void SkPicture::WriteTagSize(SkWStream* stream, uint32_t tag, size_t size) {
+ stream->write32(tag);
+ stream->write32(SkToU32(size));
+}
+
+bool SkPicture::parseBufferTag(SkReadBuffer& buffer,
+ uint32_t tag,
+ uint32_t size) {
+ switch (tag) {
+ case SK_PICT_PATH_BUFFER_TAG:
+ if (size > 0) {
+ fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
+ }
+ break;
+ default:
+ // The tag was invalid.
+ return false;
+ }
+
+ return true; // success
+}
+
+void SkPicture::flattenToBuffer(SkWriteBuffer& buffer) const {
+ int n;
+
+ if ((n = SafeCount(fPathHeap.get())) > 0) {
+ WriteTagSize(buffer, SK_PICT_PATH_BUFFER_TAG, n);
+ fPathHeap->flatten(buffer);
+ }
+}
+
void SkPicture::flatten(SkWriteBuffer& buffer) const {
SkPicturePlayback* playback = fPlayback;
SkPictInfo info;
this->createHeader(&info);
if (NULL == playback && fRecord) {
- playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord, info));
+ playback = SkNEW_ARGS(SkPicturePlayback, (this, *fRecord, info));
}
buffer.writeByteArray(&info, sizeof(info));
@@ -524,8 +669,14 @@ void SkPicture::flatten(SkWriteBuffer& buffer) const {
#if SK_SUPPORT_GPU
bool SkPicture::suitableForGpuRasterization(GrContext* context) const {
- // Stub for now; never veto GPu rasterization.
- return true;
+ // TODO: the heuristic used here needs to be refined
+ static const int kNumPaintWithPathEffectUsesTol = 1;
+ static const int kNumAAConcavePaths = 5;
+
+ SkASSERT(this->numAAHairlineConcavePaths() <= this->numAAConcavePaths());
+
+ return this->numPaintWithPathEffectUses() < kNumPaintWithPathEffectUsesTol &&
+ (this->numAAConcavePaths()-this->numAAHairlineConcavePaths()) < kNumAAConcavePaths;
}
#endif
diff --git a/core/SkPicturePlayback.cpp b/core/SkPicturePlayback.cpp
index 514769db..291774b8 100644
--- a/core/SkPicturePlayback.cpp
+++ b/core/SkPicturePlayback.cpp
@@ -23,14 +23,18 @@ template <typename T> int SafeCount(const T* obj) {
*/
#define SPEW_CLIP_SKIPPINGx
-SkPicturePlayback::SkPicturePlayback(const SkPictInfo& info) : fInfo(info) {
+SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPictInfo& info)
+ : fPicture(picture)
+ , fInfo(info) {
this->init();
}
-SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record,
+SkPicturePlayback::SkPicturePlayback(const SkPicture* picture,
+ const SkPictureRecord& record,
const SkPictInfo& info,
bool deepCopy)
- : fInfo(info) {
+ : fPicture(picture)
+ , fInfo(info) {
#ifdef SK_DEBUG_SIZE
size_t overallBytes, bitmapBytes, matricesBytes,
paintBytes, pathBytes, pictureBytes, regionBytes;
@@ -95,14 +99,8 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record,
fPaints = record.fPaints.unflattenToArray();
fBitmapHeap.reset(SkSafeRef(record.fBitmapHeap));
- fPathHeap.reset(SkSafeRef(record.fPathHeap));
- // ensure that the paths bounds are pre-computed
- if (fPathHeap.get()) {
- for (int i = 0; i < fPathHeap->count(); i++) {
- (*fPathHeap)[i].updateBoundsCache();
- }
- }
+ picture->initForPlayback();
const SkTDArray<SkPicture* >& pictures = record.getPictureRefs();
fPictureCount = pictures.count();
@@ -140,32 +138,13 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record,
#endif
}
-static bool needs_deep_copy(const SkPaint& paint) {
- /*
- * These fields are known to be immutable, and so can be shallow-copied
- *
- * getTypeface()
- * getAnnotation()
- * paint.getColorFilter()
- * getXfermode()
- * getPathEffect()
- * getMaskFilter()
- */
-
- return paint.getShader() ||
-#ifdef SK_SUPPORT_LEGACY_LAYERRASTERIZER_API
- paint.getRasterizer() ||
-#endif
- paint.getLooper() || // needs to hide its addLayer...
- paint.getImageFilter();
-}
-
-SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo)
- : fInfo(src.fInfo) {
+SkPicturePlayback::SkPicturePlayback(const SkPicture* picture, const SkPicturePlayback& src,
+ SkPictCopyInfo* deepCopyInfo)
+ : fPicture(picture)
+ , fInfo(src.fInfo) {
this->init();
fBitmapHeap.reset(SkSafeRef(src.fBitmapHeap.get()));
- fPathHeap.reset(SkSafeRef(src.fPathHeap.get()));
fOpData = SkSafeRef(src.fOpData);
@@ -176,53 +155,14 @@ SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInf
SkSafeRef(fStateTree);
if (deepCopyInfo) {
+ SkASSERT(deepCopyInfo->initialized);
+
int paintCount = SafeCount(src.fPaints);
if (src.fBitmaps) {
fBitmaps = SkTRefArray<SkBitmap>::Create(src.fBitmaps->begin(), src.fBitmaps->count());
}
- if (!deepCopyInfo->initialized) {
- /* The alternative to doing this is to have a clone method on the paint and have it make
- * the deep copy of its internal structures as needed. The holdup to doing that is at
- * this point we would need to pass the SkBitmapHeap so that we don't unnecessarily
- * flatten the pixels in a bitmap shader.
- */
- deepCopyInfo->paintData.setCount(paintCount);
-
- /* Use an SkBitmapHeap to avoid flattening bitmaps in shaders. If there already is one,
- * use it. If this SkPicturePlayback was created from a stream, fBitmapHeap will be
- * NULL, so create a new one.
- */
- if (fBitmapHeap.get() == NULL) {
- // FIXME: Put this on the stack inside SkPicture::clone. Further, is it possible to
- // do the rest of this initialization in SkPicture::clone as well?
- SkBitmapHeap* heap = SkNEW(SkBitmapHeap);
- deepCopyInfo->controller.setBitmapStorage(heap);
- heap->unref();
- } else {
- deepCopyInfo->controller.setBitmapStorage(fBitmapHeap);
- }
-
- SkDEBUGCODE(int heapSize = SafeCount(fBitmapHeap.get());)
- for (int i = 0; i < paintCount; i++) {
- if (needs_deep_copy(src.fPaints->at(i))) {
- deepCopyInfo->paintData[i] =
- SkFlatData::Create<SkPaint::FlatteningTraits>(&deepCopyInfo->controller,
- src.fPaints->at(i), 0);
-
- } else {
- // this is our sentinel, which we use in the unflatten loop
- deepCopyInfo->paintData[i] = NULL;
- }
- }
- SkASSERT(SafeCount(fBitmapHeap.get()) == heapSize);
-
- // needed to create typeface playback
- deepCopyInfo->controller.setupPlaybacks();
- deepCopyInfo->initialized = true;
- }
-
fPaints = SkTRefArray<SkPaint>::Create(paintCount);
SkASSERT(deepCopyInfo->paintData.count() == paintCount);
SkBitmapHeap* bmHeap = deepCopyInfo->controller.getBitmapHeap();
@@ -286,11 +226,11 @@ SkPicturePlayback::~SkPicturePlayback() {
}
void SkPicturePlayback::dumpSize() const {
- SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d] paths=%d\n",
+ SkDebugf("--- picture size: ops=%d bitmaps=%d [%d] paints=%d [%d]\n",
fOpData->size(),
SafeCount(fBitmaps), SafeCount(fBitmaps) * sizeof(SkBitmap),
- SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint),
- SafeCount(fPathHeap.get()));
+ SafeCount(fPaints), SafeCount(fPaints) * sizeof(SkPaint));
+ fPicture->dumpSize();
}
bool SkPicturePlayback::containsBitmaps() const {
@@ -310,16 +250,6 @@ bool SkPicturePlayback::containsBitmaps() const {
#include "SkStream.h"
-static void write_tag_size(SkWriteBuffer& buffer, uint32_t tag, size_t size) {
- buffer.writeUInt(tag);
- buffer.writeUInt(SkToU32(size));
-}
-
-static void write_tag_size(SkWStream* stream, uint32_t tag, size_t size) {
- stream->write32(tag);
- stream->write32(SkToU32(size));
-}
-
static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
size_t size = 4; // for 'count'
@@ -337,7 +267,7 @@ static size_t compute_chunk_size(SkFlattenable::Factory* array, int count) {
return size;
}
-static void write_factories(SkWStream* stream, const SkFactorySet& rec) {
+void SkPicturePlayback::WriteFactories(SkWStream* stream, const SkFactorySet& rec) {
int count = rec.count();
SkAutoSTMalloc<16, SkFlattenable::Factory> storage(count);
@@ -347,7 +277,7 @@ static void write_factories(SkWStream* stream, const SkFactorySet& rec) {
size_t size = compute_chunk_size(array, count);
// TODO: write_tag_size should really take a size_t
- write_tag_size(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
+ SkPicture::WriteTagSize(stream, SK_PICT_FACTORY_TAG, (uint32_t) size);
SkDEBUGCODE(size_t start = stream->bytesWritten());
stream->write32(count);
@@ -366,10 +296,10 @@ static void write_factories(SkWStream* stream, const SkFactorySet& rec) {
SkASSERT(size == (stream->bytesWritten() - start));
}
-static void write_typefaces(SkWStream* stream, const SkRefCntSet& rec) {
+void SkPicturePlayback::WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec) {
int count = rec.count();
- write_tag_size(stream, SK_PICT_TYPEFACE_TAG, count);
+ SkPicture::WriteTagSize(stream, SK_PICT_TYPEFACE_TAG, count);
SkAutoSTMalloc<16, SkTypeface*> storage(count);
SkTypeface** array = (SkTypeface**)storage.get();
@@ -384,32 +314,29 @@ void SkPicturePlayback::flattenToBuffer(SkWriteBuffer& buffer) const {
int i, n;
if ((n = SafeCount(fBitmaps)) > 0) {
- write_tag_size(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
+ SkPicture::WriteTagSize(buffer, SK_PICT_BITMAP_BUFFER_TAG, n);
for (i = 0; i < n; i++) {
buffer.writeBitmap((*fBitmaps)[i]);
}
}
if ((n = SafeCount(fPaints)) > 0) {
- write_tag_size(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
+ SkPicture::WriteTagSize(buffer, SK_PICT_PAINT_BUFFER_TAG, n);
for (i = 0; i < n; i++) {
buffer.writePaint((*fPaints)[i]);
}
}
- if ((n = SafeCount(fPathHeap.get())) > 0) {
- write_tag_size(buffer, SK_PICT_PATH_BUFFER_TAG, n);
- fPathHeap->flatten(buffer);
- }
+ fPicture->flattenToBuffer(buffer);
}
void SkPicturePlayback::serialize(SkWStream* stream,
SkPicture::EncodeBitmap encoder) const {
- write_tag_size(stream, SK_PICT_READER_TAG, fOpData->size());
+ SkPicture::WriteTagSize(stream, SK_PICT_READER_TAG, fOpData->size());
stream->write(fOpData->bytes(), fOpData->size());
if (fPictureCount > 0) {
- write_tag_size(stream, SK_PICT_PICTURE_TAG, fPictureCount);
+ SkPicture::WriteTagSize(stream, SK_PICT_PICTURE_TAG, fPictureCount);
for (int i = 0; i < fPictureCount; i++) {
fPictureRefs[i]->serialize(stream, encoder);
}
@@ -431,10 +358,10 @@ void SkPicturePlayback::serialize(SkWStream* stream,
// We have to write these two sets into the stream *before* we write
// the buffer, since parsing that buffer will require that we already
// have these sets available to use.
- write_factories(stream, factSet);
- write_typefaces(stream, typefaceSet);
+ WriteFactories(stream, factSet);
+ WriteTypefaces(stream, typefaceSet);
- write_tag_size(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
+ SkPicture::WriteTagSize(stream, SK_PICT_BUFFER_SIZE_TAG, buffer.bytesWritten());
buffer.writeToStream(stream);
}
@@ -442,11 +369,11 @@ void SkPicturePlayback::serialize(SkWStream* stream,
}
void SkPicturePlayback::flatten(SkWriteBuffer& buffer) const {
- write_tag_size(buffer, SK_PICT_READER_TAG, fOpData->size());
+ SkPicture::WriteTagSize(buffer, SK_PICT_READER_TAG, fOpData->size());
buffer.writeByteArray(fOpData->bytes(), fOpData->size());
if (fPictureCount > 0) {
- write_tag_size(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
+ SkPicture::WriteTagSize(buffer, SK_PICT_PICTURE_TAG, fPictureCount);
for (int i = 0; i < fPictureCount; i++) {
fPictureRefs[i]->flatten(buffer);
}
@@ -482,7 +409,8 @@ static uint32_t pictInfoFlagsToReadBufferFlags(uint32_t pictInfoFlags) {
return rbMask;
}
-bool SkPicturePlayback::parseStreamTag(SkStream* stream,
+bool SkPicturePlayback::parseStreamTag(SkPicture* picture,
+ SkStream* stream,
uint32_t tag,
uint32_t size,
SkPicture::InstallPixelRefProc proc) {
@@ -584,7 +512,7 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream,
while (!buffer.eof()) {
tag = buffer.readUInt();
size = buffer.readUInt();
- if (!this->parseBufferTag(buffer, tag, size)) {
+ if (!this->parseBufferTag(picture, buffer, tag, size)) {
return false;
}
}
@@ -594,7 +522,8 @@ bool SkPicturePlayback::parseStreamTag(SkStream* stream,
return true; // success
}
-bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer,
+bool SkPicturePlayback::parseBufferTag(SkPicture* picture,
+ SkReadBuffer& buffer,
uint32_t tag, uint32_t size) {
switch (tag) {
case SK_PICT_BITMAP_BUFFER_TAG: {
@@ -614,9 +543,7 @@ bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer,
}
} break;
case SK_PICT_PATH_BUFFER_TAG:
- if (size > 0) {
- fPathHeap.reset(SkNEW_ARGS(SkPathHeap, (buffer)));
- }
+ picture->parseBufferTag(buffer, tag, size);
break;
case SK_PICT_READER_TAG: {
SkAutoMalloc storage(size);
@@ -660,29 +587,32 @@ bool SkPicturePlayback::parseBufferTag(SkReadBuffer& buffer,
return true; // success
}
-SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkStream* stream,
+SkPicturePlayback* SkPicturePlayback::CreateFromStream(SkPicture* picture,
+ SkStream* stream,
const SkPictInfo& info,
SkPicture::InstallPixelRefProc proc) {
- SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
+ SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (picture, info)));
- if (!playback->parseStream(stream, proc)) {
+ if (!playback->parseStream(picture, stream, proc)) {
return NULL;
}
return playback.detach();
}
-SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkReadBuffer& buffer,
+SkPicturePlayback* SkPicturePlayback::CreateFromBuffer(SkPicture* picture,
+ SkReadBuffer& buffer,
const SkPictInfo& info) {
- SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (info)));
+ SkAutoTDelete<SkPicturePlayback> playback(SkNEW_ARGS(SkPicturePlayback, (picture, info)));
buffer.setPictureVersion(info.fVersion);
- if (!playback->parseBuffer(buffer)) {
+ if (!playback->parseBuffer(picture, buffer)) {
return NULL;
}
return playback.detach();
}
-bool SkPicturePlayback::parseStream(SkStream* stream,
+bool SkPicturePlayback::parseStream(SkPicture* picture,
+ SkStream* stream,
SkPicture::InstallPixelRefProc proc) {
for (;;) {
uint32_t tag = stream->readU32();
@@ -691,14 +621,14 @@ bool SkPicturePlayback::parseStream(SkStream* stream,
}
uint32_t size = stream->readU32();
- if (!this->parseStreamTag(stream, tag, size, proc)) {
+ if (!this->parseStreamTag(picture, stream, tag, size, proc)) {
return false; // we're invalid
}
}
return true;
}
-bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) {
+bool SkPicturePlayback::parseBuffer(SkPicture* picture, SkReadBuffer& buffer) {
for (;;) {
uint32_t tag = buffer.readUInt();
if (SK_PICT_EOF_TAG == tag) {
@@ -706,7 +636,7 @@ bool SkPicturePlayback::parseBuffer(SkReadBuffer& buffer) {
}
uint32_t size = buffer.readUInt();
- if (!this->parseBufferTag(buffer, tag, size)) {
+ if (!this->parseBufferTag(picture, buffer, tag, size)) {
return false; // we're invalid
}
}
diff --git a/core/SkPicturePlayback.h b/core/SkPicturePlayback.h
index cae8841f..28fdd632 100644
--- a/core/SkPicturePlayback.h
+++ b/core/SkPicturePlayback.h
@@ -75,12 +75,17 @@ struct SkPictCopyInfo {
class SkPicturePlayback {
public:
- SkPicturePlayback(const SkPicturePlayback& src, SkPictCopyInfo* deepCopyInfo = NULL);
- SkPicturePlayback(const SkPictureRecord& record, const SkPictInfo&, bool deepCopy = false);
- static SkPicturePlayback* CreateFromStream(SkStream*,
+ SkPicturePlayback(const SkPicture* picture, const SkPicturePlayback& src,
+ SkPictCopyInfo* deepCopyInfo = NULL);
+ SkPicturePlayback(const SkPicture* picture, const SkPictureRecord& record, const SkPictInfo&,
+ bool deepCopy = false);
+ static SkPicturePlayback* CreateFromStream(SkPicture* picture,
+ SkStream*,
const SkPictInfo&,
SkPicture::InstallPixelRefProc);
- static SkPicturePlayback* CreateFromBuffer(SkReadBuffer&, const SkPictInfo&);
+ static SkPicturePlayback* CreateFromBuffer(SkPicture* picture,
+ SkReadBuffer&,
+ const SkPictInfo&);
virtual ~SkPicturePlayback();
@@ -105,10 +110,10 @@ public:
void resetOpID() { fCurOffset = 0; }
protected:
- explicit SkPicturePlayback(const SkPictInfo& info);
+ explicit SkPicturePlayback(const SkPicture* picture, const SkPictInfo& info);
- bool parseStream(SkStream*, SkPicture::InstallPixelRefProc);
- bool parseBuffer(SkReadBuffer& buffer);
+ bool parseStream(SkPicture* picture, SkStream*, SkPicture::InstallPixelRefProc);
+ bool parseBuffer(SkPicture* picture, SkReadBuffer& buffer);
#ifdef SK_DEVELOPER
virtual bool preDraw(int opIndex, int type);
virtual void postDraw(int opIndex);
@@ -139,7 +144,7 @@ private:
}
const SkPath& getPath(SkReader32& reader) {
- return (*fPathHeap)[reader.readInt() - 1];
+ return fPicture->getPath(reader.readInt() - 1);
}
SkPicture& getPicture(SkReader32& reader) {
@@ -215,17 +220,22 @@ public:
#endif
private: // these help us with reading/writing
- bool parseStreamTag(SkStream*, uint32_t tag, uint32_t size, SkPicture::InstallPixelRefProc);
- bool parseBufferTag(SkReadBuffer&, uint32_t tag, uint32_t size);
+ bool parseStreamTag(SkPicture* picture, SkStream*, uint32_t tag, uint32_t size,
+ SkPicture::InstallPixelRefProc);
+ bool parseBufferTag(SkPicture* picture, SkReadBuffer&, uint32_t tag, uint32_t size);
void flattenToBuffer(SkWriteBuffer&) const;
private:
+ friend class SkPicture;
+
+ // The picture that owns this SkPicturePlayback object
+ const SkPicture* fPicture;
+
// Only used by getBitmap() if the passed in index is SkBitmapHeap::INVALID_SLOT. This empty
// bitmap allows playback to draw nothing and move on.
SkBitmap fBadBitmap;
SkAutoTUnref<SkBitmapHeap> fBitmapHeap;
- SkAutoTUnref<SkPathHeap> fPathHeap;
SkTRefArray<SkBitmap>* fBitmaps;
SkTRefArray<SkPaint>* fPaints;
@@ -269,6 +279,9 @@ private:
const SkPictInfo fInfo;
+ static void WriteFactories(SkWStream* stream, const SkFactorySet& rec);
+ static void WriteTypefaces(SkWStream* stream, const SkRefCntSet& rec);
+
#ifdef SK_BUILD_FOR_ANDROID
SkMutex fDrawMutex;
bool fAbortCurrentPlayback;
diff --git a/core/SkPictureRecord.cpp b/core/SkPictureRecord.cpp
index c5e329e7..f3d108c4 100644
--- a/core/SkPictureRecord.cpp
+++ b/core/SkPictureRecord.cpp
@@ -27,7 +27,7 @@ static const uint32_t kSaveSize = 2 * kUInt32Size;
static const uint32_t kSaveLayerNoBoundsSize = 4 * kUInt32Size;
static const uint32_t kSaveLayerWithBoundsSize = 4 * kUInt32Size + sizeof(SkRect);
-SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
+SkPictureRecord::SkPictureRecord(SkPicture* picture, const SkISize& dimensions, uint32_t flags)
: INHERITED(dimensions.width(), dimensions.height())
, fBoundingHierarchy(NULL)
, fStateTree(NULL)
@@ -40,9 +40,9 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
fPointWrites = fRectWrites = fTextWrites = 0;
#endif
+ fPicture = picture;
fBitmapHeap = SkNEW(SkBitmapHeap);
fFlattenableHeap.setBitmapStorage(fBitmapHeap);
- fPathHeap = NULL; // lazy allocate
#ifndef SK_COLLAPSE_MATRIX_CLIP_STATE
fFirstSavedLayerIndex = kNoSavedLayerIndex;
@@ -57,7 +57,6 @@ SkPictureRecord::SkPictureRecord(const SkISize& dimensions, uint32_t flags)
SkPictureRecord::~SkPictureRecord() {
SkSafeUnref(fBitmapHeap);
- SkSafeUnref(fPathHeap);
SkSafeUnref(fBoundingHierarchy);
SkSafeUnref(fStateTree);
fFlattenableHeap.setBitmapStorage(NULL);
@@ -1066,6 +1065,15 @@ void SkPictureRecord::onDrawDRRect(const SkRRect& outer, const SkRRect& inner,
void SkPictureRecord::drawPath(const SkPath& path, const SkPaint& paint) {
+ if (paint.isAntiAlias() && !path.isConvex()) {
+ fPicture->incAAConcavePaths();
+
+ if (SkPaint::kStroke_Style == paint.getStyle() &&
+ 0 == paint.getStrokeWidth()) {
+ fPicture->incAAHairlineConcavePaths();
+ }
+ }
+
#ifdef SK_COLLAPSE_MATRIX_CLIP_STATE
fMCMgr.call(SkMatrixClipStateMgr::kOther_CallType);
#endif
@@ -1579,6 +1587,10 @@ const SkFlatData* SkPictureRecord::getFlatPaintData(const SkPaint& paint) {
}
const SkFlatData* SkPictureRecord::addPaintPtr(const SkPaint* paint) {
+ if (NULL != paint && NULL != paint->getPathEffect()) {
+ fPicture->incPaintWithPathEffectUses();
+ }
+
const SkFlatData* data = paint ? getFlatPaintData(*paint) : NULL;
this->addFlatPaint(data);
return data;
@@ -1590,14 +1602,7 @@ void SkPictureRecord::addFlatPaint(const SkFlatData* flatPaint) {
}
int SkPictureRecord::addPathToHeap(const SkPath& path) {
- if (NULL == fPathHeap) {
- fPathHeap = SkNEW(SkPathHeap);
- }
-#ifdef SK_DEDUP_PICTURE_PATHS
- return fPathHeap->insert(path);
-#else
- return fPathHeap->append(path);
-#endif
+ return fPicture->addPathToHeap(path);
}
void SkPictureRecord::addPath(const SkPath& path) {
diff --git a/core/SkPictureRecord.h b/core/SkPictureRecord.h
index 257bab22..0f0986fb 100644
--- a/core/SkPictureRecord.h
+++ b/core/SkPictureRecord.h
@@ -33,7 +33,7 @@ class SkPictureStateTree;
class SkPictureRecord : public SkCanvas {
public:
- SkPictureRecord(const SkISize& dimensions, uint32_t recordFlags);
+ SkPictureRecord(SkPicture* picture, const SkISize& dimensions, uint32_t recordFlags);
virtual ~SkPictureRecord();
virtual void clear(SkColor) SK_OVERRIDE;
@@ -279,6 +279,9 @@ protected:
SkBitmapHeap* fBitmapHeap;
private:
+ // The owning SkPicture
+ SkPicture* fPicture;
+
friend class MatrixClipState; // for access to *Impl methods
friend class SkMatrixClipStateMgr; // for access to *Impl methods
@@ -286,7 +289,6 @@ private:
SkPaintDictionary fPaints;
- SkPathHeap* fPathHeap; // reference counted
SkWriter32 fWriter;
// we ref each item in these arrays
diff --git a/core/SkPictureShader.cpp b/core/SkPictureShader.cpp
index dc5c90b6..466c5e12 100644
--- a/core/SkPictureShader.cpp
+++ b/core/SkPictureShader.cpp
@@ -91,13 +91,12 @@ SkShader* SkPictureShader::refBitmapShader(const SkMatrix& matrix) const {
canvas.scale(tileScale.width(), tileScale.height());
canvas.drawPicture(*fPicture);
- fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy));
fCachedTileScale = tileScale;
fCachedLocalMatrix = this->getLocalMatrix();
SkMatrix shaderMatrix = this->getLocalMatrix();
shaderMatrix.preScale(1 / tileScale.width(), 1 / tileScale.height());
- fCachedBitmapShader->setLocalMatrix(shaderMatrix);
+ fCachedBitmapShader.reset(CreateBitmapShader(bm, fTmx, fTmy, &shaderMatrix));
}
// Increment the ref counter inside the mutex to ensure the returned pointer is still valid.
diff --git a/core/SkPictureStateTree.cpp b/core/SkPictureStateTree.cpp
index 20a826aa..f6d54ffe 100644
--- a/core/SkPictureStateTree.cpp
+++ b/core/SkPictureStateTree.cpp
@@ -123,15 +123,17 @@ uint32_t SkPictureStateTree::Iterator::nextDraw() {
for (fCurrentNode = fCurrentNode->fParent; fCurrentNode;
fCurrentNode = fCurrentNode->fParent) {
- if (fCurrentNode->fFlags & (Node::kSave_Flag | Node::kSaveLayer_Flag)) {
+ // Note: we call restore() twice when both flags are set.
+ if (fCurrentNode->fFlags & Node::kSave_Flag) {
+ fCanvas->restore();
+ }
+ if (fCurrentNode->fFlags & Node::kSaveLayer_Flag) {
fCanvas->restore();
}
}
- // restore back to where we started
fCanvas->setMatrix(fPlaybackMatrix);
fCurrentMatrix = NULL;
-
return kDrawComplete;
}
@@ -174,9 +176,6 @@ uint32_t SkPictureStateTree::Iterator::nextDraw() {
fNodes.push(ancestor);
ancestor = ancestor->fParent;
}
-
- SkASSERT(NULL != tmp);
- SkASSERT(NULL != ancestor);
}
if (ancestor->fFlags & Node::kSave_Flag) {
diff --git a/core/SkQuadTree.cpp b/core/SkQuadTree.cpp
index f3436bd5..fb02e68c 100644
--- a/core/SkQuadTree.cpp
+++ b/core/SkQuadTree.cpp
@@ -8,7 +8,6 @@
#include "SkQuadTree.h"
#include "SkTSort.h"
#include <stdio.h>
-#include <vector>
static const int kSplitThreshold = 8;
diff --git a/core/SkReadBuffer.cpp b/core/SkReadBuffer.cpp
index b60dee3b..b4bc8752 100644
--- a/core/SkReadBuffer.cpp
+++ b/core/SkReadBuffer.cpp
@@ -321,10 +321,10 @@ SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
SkFlattenable* obj = NULL;
uint32_t sizeRecorded = fReader.readU32();
if (factory) {
- uint32_t offset = fReader.offset();
+ size_t offset = fReader.offset();
obj = (*factory)(*this);
// check that we read the amount we expected
- uint32_t sizeRead = fReader.offset() - offset;
+ size_t sizeRead = fReader.offset() - offset;
if (sizeRecorded != sizeRead) {
// we could try to fix up the offset...
sk_throw();
diff --git a/core/SkRegion.cpp b/core/SkRegion.cpp
index baedf2ae..98670b6b 100644
--- a/core/SkRegion.cpp
+++ b/core/SkRegion.cpp
@@ -796,7 +796,7 @@ public:
fTop = (SkRegion::RunType)(bottom); // just update our bottom
} else {
start[-2] = (SkRegion::RunType)(bottom);
- start[-1] = len >> 1;
+ start[-1] = SkToS32(len >> 1);
fPrevDst = start;
fPrevLen = len;
}
@@ -1212,7 +1212,7 @@ static void compute_bounds(const SkRegion::RunType runs[],
const SkRegion::RunType* prev = runs;
runs = skip_intervals_slow(runs);
- int intervals = (runs - prev) >> 1;
+ int intervals = SkToInt((runs - prev) >> 1);
SkASSERT(prev[-1] == intervals);
intervalCount += intervals;
diff --git a/core/SkRegionPriv.h b/core/SkRegionPriv.h
index f299f3a9..c8f000df 100644
--- a/core/SkRegionPriv.h
+++ b/core/SkRegionPriv.h
@@ -29,7 +29,7 @@ static int compute_intervalcount(const SkRegion::RunType runs[]) {
SkASSERT(curr[1] < SkRegion::kRunTypeSentinel);
curr += 2;
}
- return (curr - runs) >> 1;
+ return SkToInt((curr - runs) >> 1);
}
#endif
@@ -213,7 +213,7 @@ public:
#ifdef SK_DEBUG
// +1 to skip the last Y-sentinel
- int runCount = runs - this->writable_runs() + 1;
+ int runCount = SkToInt(runs - this->writable_runs() + 1);
SkASSERT(runCount == fRunCount);
#endif
diff --git a/core/SkScalerContext.cpp b/core/SkScalerContext.cpp
index d0d24eeb..fee1ff79 100644
--- a/core/SkScalerContext.cpp
+++ b/core/SkScalerContext.cpp
@@ -548,8 +548,9 @@ static void packA8ToA1(const SkMask& mask, const uint8_t* src, size_t srcRB) {
const int dstPad = mask.fRowBytes - SkAlign8(width)/8;
SkASSERT(dstPad >= 0);
- const int srcPad = srcRB - width;
- SkASSERT(srcPad >= 0);
+ SkASSERT(width >= 0);
+ SkASSERT(srcRB >= (size_t)width);
+ const size_t srcPad = srcRB - width;
for (int y = 0; y < height; ++y) {
for (int i = 0; i < octs; ++i) {
diff --git a/core/SkShader.cpp b/core/SkShader.cpp
index 40e52a05..4ddd2915 100644
--- a/core/SkShader.cpp
+++ b/core/SkShader.cpp
@@ -15,8 +15,12 @@
#include "SkShader.h"
#include "SkWriteBuffer.h"
-SkShader::SkShader() {
- fLocalMatrix.reset();
+SkShader::SkShader(const SkMatrix* localMatrix) {
+ if (localMatrix) {
+ fLocalMatrix = *localMatrix;
+ } else {
+ fLocalMatrix.reset();
+ }
}
SkShader::SkShader(SkReadBuffer& buffer)
@@ -180,9 +184,9 @@ GrEffectRef* SkShader::asNewEffect(GrContext*, const SkPaint&) const {
return NULL;
}
-SkShader* SkShader::CreateBitmapShader(const SkBitmap& src,
- TileMode tmx, TileMode tmy) {
- return ::CreateBitmapShader(src, tmx, tmy, NULL);
+SkShader* SkShader::CreateBitmapShader(const SkBitmap& src, TileMode tmx, TileMode tmy,
+ const SkMatrix* localMatrix) {
+ return ::CreateBitmapShader(src, tmx, tmy, localMatrix, NULL);
}
SkShader* SkShader::CreatePictureShader(SkPicture* src, TileMode tmx, TileMode tmy) {
@@ -203,37 +207,29 @@ void SkShader::toString(SkString* str) const {
#include "SkColorShader.h"
#include "SkUtils.h"
-SkColorShader::SkColorShader()
- : fColor()
- , fInheritColor(true) {
-}
-
SkColorShader::SkColorShader(SkColor c)
- : fColor(c)
- , fInheritColor(false) {
+ : fColor(c) {
}
bool SkColorShader::isOpaque() const {
- if (fInheritColor) {
- return true; // using paint's alpha
- }
return SkColorGetA(fColor) == 255;
}
SkColorShader::SkColorShader(SkReadBuffer& b) : INHERITED(b) {
- fInheritColor = b.readBool();
- if (fInheritColor) {
- return;
+ // V25_COMPATIBILITY_CODE We had a boolean to make the color shader inherit the paint's
+ // color. We don't support that any more.
+ if (b.pictureVersion() < 26 && 0 != b.pictureVersion()) {
+ if (b.readBool()) {
+ SkDEBUGFAIL("We shouldn't have pictures that recorded the inherited case.");
+ fColor = SK_ColorWHITE;
+ return;
+ }
}
fColor = b.readColor();
}
void SkColorShader::flatten(SkWriteBuffer& buffer) const {
this->INHERITED::flatten(buffer);
- buffer.writeBool(fInheritColor);
- if (fInheritColor) {
- return;
- }
buffer.writeColor(fColor);
}
@@ -260,16 +256,8 @@ SkColorShader::ColorShaderContext::ColorShaderContext(const SkColorShader& shade
const SkMatrix& matrix)
: INHERITED(shader, device, paint, matrix)
{
- unsigned a;
-
- SkColor color;
- if (shader.fInheritColor) {
- color = paint.getColor();
- a = SkColorGetA(color);
- } else {
- color = shader.fColor;
- a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha()));
- }
+ SkColor color = shader.fColor;
+ unsigned a = SkAlphaMul(SkColorGetA(color), SkAlpha255To256(paint.getAlpha()));
unsigned r = SkColorGetR(color);
unsigned g = SkColorGetG(color);
@@ -327,12 +315,8 @@ SkShader::GradientType SkColorShader::asAGradient(GradientInfo* info) const {
void SkColorShader::toString(SkString* str) const {
str->append("SkColorShader: (");
- if (fInheritColor) {
- str->append("Color: inherited from paint");
- } else {
- str->append("Color: ");
- str->appendHex(fColor);
- }
+ str->append("Color: ");
+ str->appendHex(fColor);
this->INHERITED::toString(str);
diff --git a/core/SkSmallAllocator.h b/core/SkSmallAllocator.h
index 8d4b53a7..018705f9 100644
--- a/core/SkSmallAllocator.h
+++ b/core/SkSmallAllocator.h
@@ -96,6 +96,16 @@ public:
return static_cast<T*>(buf);
}
+ template<typename T, typename A1, typename A2, typename A3, typename A4>
+ T* createT(const A1& a1, const A2& a2, const A3& a3, const A4& a4) {
+ void* buf = this->reserveT<T>();
+ if (NULL == buf) {
+ return NULL;
+ }
+ SkNEW_PLACEMENT_ARGS(buf, T, (a1, a2, a3, a4));
+ return static_cast<T*>(buf);
+ }
+
/*
* Reserve a specified amount of space (must be enough space for one T).
* The space will be in fStorage if there is room, or on the heap otherwise.
diff --git a/core/SkStream.cpp b/core/SkStream.cpp
index c60f2a73..ebaac9ab 100644
--- a/core/SkStream.cpp
+++ b/core/SkStream.cpp
@@ -161,7 +161,7 @@ bool SkWStream::writePackedUInt(size_t value) {
memcpy(&data[1], &value16, 2);
len = 3;
} else {
- uint32_t value32 = value;
+ uint32_t value32 = SkToU32(value);
data[0] = SK_BYTE_SENTINEL_FOR_U32;
memcpy(&data[1], &value32, 4);
len = 5;
@@ -189,7 +189,7 @@ bool SkWStream::writeStream(SkStream* stream, size_t length) {
bool SkWStream::writeData(const SkData* data) {
if (data) {
- this->write32(data->size());
+ this->write32(SkToU32(data->size()));
this->write(data->data(), data->size());
} else {
this->write32(0);
@@ -481,11 +481,9 @@ SkMemoryWStream::SkMemoryWStream(void* buffer, size_t size)
{
}
-bool SkMemoryWStream::write(const void* buffer, size_t size)
-{
- size = SkMin32(size, fMaxLength - fBytesWritten);
- if (size > 0)
- {
+bool SkMemoryWStream::write(const void* buffer, size_t size) {
+ size = SkTMin(size, fMaxLength - fBytesWritten);
+ if (size > 0) {
memcpy(fBuffer + fBytesWritten, buffer, size);
fBytesWritten += size;
return true;
@@ -558,7 +556,7 @@ bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
size_t size;
if (fTail != NULL && fTail->avail() > 0) {
- size = SkMin32(fTail->avail(), count);
+ size = SkTMin(fTail->avail(), count);
buffer = fTail->append(buffer, size);
SkASSERT(count >= size);
count -= size;
@@ -566,7 +564,7 @@ bool SkDynamicMemoryWStream::write(const void* buffer, size_t count)
return true;
}
- size = SkMax32(count, SkDynamicMemoryWStream_MinBlockSize);
+ size = SkTMax<size_t>(count, SkDynamicMemoryWStream_MinBlockSize);
Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size);
block->init(size);
block->append(buffer, count);
diff --git a/core/SkValidatingReadBuffer.cpp b/core/SkValidatingReadBuffer.cpp
index 8db2c68b..0112f18e 100644
--- a/core/SkValidatingReadBuffer.cpp
+++ b/core/SkValidatingReadBuffer.cpp
@@ -91,7 +91,7 @@ int32_t SkValidatingReadBuffer::read32() {
}
void SkValidatingReadBuffer::readString(SkString* string) {
- const size_t len = this->readInt();
+ const size_t len = this->readUInt();
const void* ptr = fReader.peek();
const char* cptr = (const char*)ptr;
@@ -256,10 +256,10 @@ SkFlattenable* SkValidatingReadBuffer::readFlattenable(SkFlattenable::Type type)
SkFlattenable* obj = NULL;
uint32_t sizeRecorded = this->readUInt();
if (factory) {
- uint32_t offset = fReader.offset();
+ size_t offset = fReader.offset();
obj = (*factory)(*this);
// check that we read the amount we expected
- uint32_t sizeRead = fReader.offset() - offset;
+ size_t sizeRead = fReader.offset() - offset;
this->validate(sizeRecorded == sizeRead);
if (fError) {
// we could try to fix up the offset...
diff --git a/core/SkWriter32.cpp b/core/SkWriter32.cpp
index c7bfd92d..00c46368 100644
--- a/core/SkWriter32.cpp
+++ b/core/SkWriter32.cpp
@@ -14,7 +14,7 @@
*/
const char* SkReader32::readString(size_t* outLen) {
- size_t len = this->readInt();
+ size_t len = this->readU32();
const void* ptr = this->peek();
// skip over the string + '\0' and then pad to a multiple of 4
@@ -47,7 +47,7 @@ void SkWriter32::writeString(const char str[], size_t len) {
// [ 4 byte len ] [ str ... ] [1 - 4 \0s]
uint32_t* ptr = this->reservePad(sizeof(uint32_t) + len + 1);
- *ptr = len;
+ *ptr = SkToU32(len);
char* chars = (char*)(ptr + 1);
memcpy(chars, str, len);
chars[len] = '\0';