diff options
author | Bo Liu <boliu@google.com> | 2014-05-01 10:38:38 -0700 |
---|---|---|
committer | Bo Liu <boliu@google.com> | 2014-05-01 10:38:38 -0700 |
commit | 27ab20dffff01006f5d20fdb2b3f4ea503d69114 (patch) | |
tree | f8a42f1186f835772ed0c20a7f9095392e124b04 /core | |
parent | 51512eaae8128a677f92e2689d8df720dca13d32 (diff) | |
parent | 2e8705638185600b128f867809b6cd034225451c (diff) | |
download | src-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')
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, ©Info)); + 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>(©Info.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, ©Info)); 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'; |