diff options
author | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-12 21:01:41 +0000 |
---|---|---|
committer | brettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-12-12 21:01:41 +0000 |
commit | 52e935d04c59135739c3a68fb6e19d313dc6d5ad (patch) | |
tree | 95f7ab178b045bef4456cbf92c6aa7e476becd99 /skia/picture | |
parent | 30fab79877b4bb067944b74d98346ac9bb6bfc7e (diff) | |
download | chromium_src-52e935d04c59135739c3a68fb6e19d313dc6d5ad.zip chromium_src-52e935d04c59135739c3a68fb6e19d313dc6d5ad.tar.gz chromium_src-52e935d04c59135739c3a68fb6e19d313dc6d5ad.tar.bz2 |
New drop of Skia. This is up to CL 121320.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@6925 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'skia/picture')
-rw-r--r-- | skia/picture/SkPathHeap.cpp | 55 | ||||
-rw-r--r-- | skia/picture/SkPathHeap.h | 37 | ||||
-rw-r--r-- | skia/picture/SkPicture.cpp | 246 | ||||
-rw-r--r-- | skia/picture/SkPictureFlat.cpp | 9 | ||||
-rw-r--r-- | skia/picture/SkPictureFlat.h | 27 | ||||
-rw-r--r-- | skia/picture/SkPicturePlayback.cpp | 130 | ||||
-rw-r--r-- | skia/picture/SkPicturePlayback.h | 12 | ||||
-rw-r--r-- | skia/picture/SkPictureRecord.cpp | 74 | ||||
-rw-r--r-- | skia/picture/SkPictureRecord.h | 8 |
9 files changed, 444 insertions, 154 deletions
diff --git a/skia/picture/SkPathHeap.cpp b/skia/picture/SkPathHeap.cpp new file mode 100644 index 0000000..f6dae5d --- /dev/null +++ b/skia/picture/SkPathHeap.cpp @@ -0,0 +1,55 @@ +#include "SkPathHeap.h" +#include "SkPath.h" +#include "SkStream.h" +#include "SkFlattenable.h" +#include <new> + +#define kPathCount 64 + +SkPathHeap::SkPathHeap() : fHeap(kPathCount * sizeof(SkPath)) { +} + +SkPathHeap::SkPathHeap(SkFlattenableReadBuffer& buffer) + : fHeap(kPathCount * sizeof(SkPath)) { + int count = buffer.readS32(); + + fPaths.setCount(count); + SkPath** ptr = fPaths.begin(); + SkPath* p = (SkPath*)fHeap.allocThrow(count * sizeof(SkPath)); + + for (int i = 0; i < count; i++) { + new (p) SkPath; + p->unflatten(buffer); + *ptr++ = p; // record the pointer + p++; // move to the next storage location + } +} + +SkPathHeap::~SkPathHeap() { + SkPath** iter = fPaths.begin(); + SkPath** stop = fPaths.end(); + while (iter < stop) { + (*iter)->~SkPath(); + iter++; + } +} + +int SkPathHeap::append(const SkPath& path) { + SkPath* p = (SkPath*)fHeap.allocThrow(sizeof(SkPath)); + new (p) SkPath(path); + *fPaths.append() = p; + return fPaths.count(); +} + +void SkPathHeap::flatten(SkFlattenableWriteBuffer& buffer) const { + int count = fPaths.count(); + + buffer.write32(count); + SkPath** iter = fPaths.begin(); + SkPath** stop = fPaths.end(); + while (iter < stop) { + (*iter)->flatten(buffer); + iter++; + } +} + diff --git a/skia/picture/SkPathHeap.h b/skia/picture/SkPathHeap.h new file mode 100644 index 0000000..b8f3bd3 --- /dev/null +++ b/skia/picture/SkPathHeap.h @@ -0,0 +1,37 @@ +#ifndef SkPathHeap_DEFINED +#define SkPathHeap_DEFINED + +#include "SkRefCnt.h" +#include "SkChunkAlloc.h" +#include "SkTDArray.h" + +class SkPath; +class SkFlattenableReadBuffer; +class SkFlattenableWriteBuffer; + +class SkPathHeap : public SkRefCnt { +public: + SkPathHeap(); + SkPathHeap(SkFlattenableReadBuffer&); + virtual ~SkPathHeap(); + + // called during picture-record + int append(const SkPath&); + + // called during picture-playback + int count() const { return fPaths.count(); } + const SkPath& operator[](int index) const { + return *fPaths[index]; + } + + void flatten(SkFlattenableWriteBuffer&) const; + +private: + // we store the paths in the heap (placement new) + SkChunkAlloc fHeap; + // we just store ptrs into fHeap here + SkTDArray<SkPath*> fPaths; +}; + +#endif + diff --git a/skia/picture/SkPicture.cpp b/skia/picture/SkPicture.cpp new file mode 100644 index 0000000..07cb0a6 --- /dev/null +++ b/skia/picture/SkPicture.cpp @@ -0,0 +1,246 @@ +/* +** +** Copyright 2007, The Android Open Source Project +** +** Licensed under the Apache License, Version 2.0 (the "License"); +** you may not use this file except in compliance with the License. +** You may obtain a copy of the License at +** +** http://www.apache.org/licenses/LICENSE-2.0 +** +** Unless required by applicable law or agreed to in writing, software +** distributed under the License is distributed on an "AS IS" BASIS, +** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +** See the License for the specific language governing permissions and +** limitations under the License. +*/ + +#include "SkPictureFlat.h" +#include "SkPicturePlayback.h" +#include "SkPictureRecord.h" + +#include "SkCanvas.h" +#include "SkChunkAlloc.h" +#include "SkPicture.h" +#include "SkRegion.h" +#include "SkStream.h" +#include "SkTDArray.h" +#include "SkTSearch.h" +#include "SkTime.h" + +#include "SkReader32.h" +#include "SkWriter32.h" + +#define DUMP_BUFFER_SIZE 65536 + +//#define ENABLE_TIME_DRAW // dumps milliseconds for each draw + + +#ifdef SK_DEBUG +// enable SK_DEBUG_TRACE to trace DrawType elements when +// recorded and played back +// #define SK_DEBUG_TRACE +// enable SK_DEBUG_SIZE to see the size of picture components +// #define SK_DEBUG_SIZE +// enable SK_DEBUG_DUMP to see the contents of recorded elements +// #define SK_DEBUG_DUMP +// enable SK_DEBUG_VALIDATE to check internal structures for consistency +// #define SK_DEBUG_VALIDATE +#endif + +#if defined SK_DEBUG_TRACE || defined SK_DEBUG_DUMP +const char* DrawTypeToString(DrawType drawType) { + switch (drawType) { + case UNUSED: SkDebugf("DrawType UNUSED\n"); SkASSERT(0); break; + case CLIP_PATH: return "CLIP_PATH"; + case CLIP_REGION: return "CLIP_REGION"; + case CLIP_RECT: return "CLIP_RECT"; + case CONCAT: return "CONCAT"; + case DRAW_BITMAP: return "DRAW_BITMAP"; + case DRAW_BITMAP_MATRIX: return "DRAW_BITMAP_MATRIX"; + case DRAW_BITMAP_RECT: return "DRAW_BITMAP_RECT"; + case DRAW_PAINT: return "DRAW_PAINT"; + case DRAW_PATH: return "DRAW_PATH"; + case DRAW_PICTURE: return "DRAW_PICTURE"; + case DRAW_POINTS: return "DRAW_POINTS"; + case DRAW_POS_TEXT: return "DRAW_POS_TEXT"; + case DRAW_POS_TEXT_H: return "DRAW_POS_TEXT_H"; + case DRAW_RECT_GENERAL: return "DRAW_RECT_GENERAL"; + case DRAW_RECT_SIMPLE: return "DRAW_RECT_SIMPLE"; + case DRAW_SPRITE: return "DRAW_SPRITE"; + case DRAW_TEXT: return "DRAW_TEXT"; + case DRAW_TEXT_ON_PATH: return "DRAW_TEXT_ON_PATH"; + case RESTORE: return "RESTORE"; + case ROTATE: return "ROTATE"; + case SAVE: return "SAVE"; + case SAVE_LAYER: return "SAVE_LAYER"; + case SCALE: return "SCALE"; + case SKEW: return "SKEW"; + case TRANSLATE: return "TRANSLATE"; + default: + SkDebugf("DrawType error 0x%08x\n", drawType); + SkASSERT(0); + break; + } + SkASSERT(0); + return NULL; +} +#endif + +#ifdef SK_DEBUG_VALIDATE +static void validateMatrix(const SkMatrix* matrix) { + SkScalar scaleX = matrix->getScaleX(); + SkScalar scaleY = matrix->getScaleY(); + SkScalar skewX = matrix->getSkewX(); + SkScalar skewY = matrix->getSkewY(); + SkScalar perspX = matrix->getPerspX(); + SkScalar perspY = matrix->getPerspY(); + if (scaleX != 0 && skewX != 0) + SkDebugf("scaleX != 0 && skewX != 0\n"); + SkASSERT(scaleX == 0 || skewX == 0); + SkASSERT(scaleY == 0 || skewY == 0); + SkASSERT(perspX == 0); + SkASSERT(perspY == 0); +} +#endif + + +/////////////////////////////////////////////////////////////////////////////// + +SkPicture::SkPicture() { + fRecord = NULL; + fPlayback = NULL; + fWidth = fHeight = 0; +} + +SkPicture::SkPicture(const SkPicture& src) : SkRefCnt() { + fWidth = src.fWidth; + fHeight = src.fHeight; + fRecord = NULL; + + /* 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 (src.fPlayback) { + fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fPlayback)); + } else if (src.fRecord) { + // here we do a fake src.endRecording() + fPlayback = SkNEW_ARGS(SkPicturePlayback, (*src.fRecord)); + } else { + fPlayback = NULL; + } +} + +SkPicture::~SkPicture() { + fRecord->safeUnref(); + SkDELETE(fPlayback); +} + +void SkPicture::swap(SkPicture& other) { + SkTSwap(fRecord, other.fRecord); + SkTSwap(fPlayback, other.fPlayback); + SkTSwap(fWidth, other.fWidth); + SkTSwap(fHeight, other.fHeight); +} + +/////////////////////////////////////////////////////////////////////////////// + +SkCanvas* SkPicture::beginRecording(int width, int height) { + if (fPlayback) { + SkDELETE(fPlayback); + fPlayback = NULL; + } + + if (NULL != fRecord) { + fRecord->unref(); + fRecord = NULL; + } + + fRecord = SkNEW(SkPictureRecord); + + fWidth = width; + fHeight = height; + + SkBitmap bm; + bm.setConfig(SkBitmap::kNo_Config, width, height); + fRecord->setBitmapDevice(bm); + + return fRecord; +} + +SkCanvas* SkPicture::getRecordingCanvas() const { + // will be null if we are not recording + return fRecord; +} + +void SkPicture::endRecording() { + if (NULL == fPlayback) { + if (NULL != fRecord) { + fPlayback = SkNEW_ARGS(SkPicturePlayback, (*fRecord)); + fRecord->unref(); + fRecord = NULL; + } + } + SkASSERT(NULL == fRecord); +} + +void SkPicture::draw(SkCanvas* surface) { + this->endRecording(); + if (fPlayback) { + fPlayback->draw(*surface); + } +} + +/////////////////////////////////////////////////////////////////////////////// + +#include "SkStream.h" + +#define PICTURE_VERSION 1 + +SkPicture::SkPicture(SkStream* stream) : SkRefCnt() { + if (stream->readU32() != PICTURE_VERSION) { + sk_throw(); + } + + fWidth = stream->readU32(); + fHeight = stream->readU32(); + + fRecord = NULL; + fPlayback = NULL; + + if (stream->readBool()) { + fPlayback = SkNEW_ARGS(SkPicturePlayback, (stream)); + } +} + +void SkPicture::serialize(SkWStream* stream) const { + SkPicturePlayback* playback = fPlayback; + + if (NULL == playback && fRecord) { + playback = SkNEW_ARGS(SkPicturePlayback, (*fRecord)); + } + + stream->write32(PICTURE_VERSION); + stream->write32(fWidth); + stream->write32(fHeight); + if (playback) { + stream->writeBool(true); + playback->serialize(stream); + // delete playback if it is a local version (i.e. cons'd up just now) + if (playback != fPlayback) { + SkDELETE(playback); + } + } else { + stream->writeBool(false); + } +} + +void SkPicture::abortPlayback() { + if (NULL == fPlayback) { + return; + } + fPlayback->abort(); +} + + diff --git a/skia/picture/SkPictureFlat.cpp b/skia/picture/SkPictureFlat.cpp index ba7119e..e221e55 100644 --- a/skia/picture/SkPictureFlat.cpp +++ b/skia/picture/SkPictureFlat.cpp @@ -206,15 +206,6 @@ void SkFlatPaint::dump() const { } #endif -SkFlatPath* SkFlatPath::Flatten(SkChunkAlloc* heap, const SkPath& path, int index) { - SkFlattenableWriteBuffer buffer(1024); - path.flatten(buffer); - uint32_t size = buffer.size(); - SkFlatPath* result = (SkFlatPath*) INHERITED::Alloc(heap, size, index); - buffer.flatten(&result->fPathData); - return result; -} - SkFlatRegion* SkFlatRegion::Flatten(SkChunkAlloc* heap, const SkRegion& region, int index) { uint32_t size = region.flatten(NULL); SkFlatRegion* result = (SkFlatRegion*) INHERITED::Alloc(heap, size, index); diff --git a/skia/picture/SkPictureFlat.h b/skia/picture/SkPictureFlat.h index 64a7359..9e7fc5e 100644 --- a/skia/picture/SkPictureFlat.h +++ b/skia/picture/SkPictureFlat.h @@ -24,11 +24,12 @@ enum DrawType { DRAW_POINTS, DRAW_POS_TEXT, DRAW_POS_TEXT_H, - DRAW_RECT_GENERAL, - DRAW_RECT_SIMPLE, + DRAW_POS_TEXT_H_TOP_BOTTOM, // fast variant of DRAW_POS_TEXT_H + DRAW_RECT, DRAW_SPRITE, DRAW_TEXT, DRAW_TEXT_ON_PATH, + DRAW_TEXT_TOP_BOTTOM, // fast variant of DRAW_TEXT DRAW_VERTICES, RESTORE, ROTATE, @@ -48,7 +49,7 @@ enum DrawVertexFlags { class SkRefCntPlayback { public: SkRefCntPlayback(); - virtual ~SkRefCntPlayback(); + ~SkRefCntPlayback(); int count() const { return fCount; } @@ -183,26 +184,6 @@ private: typedef SkFlatData INHERITED; }; -class SkFlatPath : public SkFlatData { -public: - static SkFlatPath* Flatten(SkChunkAlloc* heap, const SkPath& path, int index); - - void unflatten(SkPath* path) const { - SkFlattenableReadBuffer buffer(fPathData); - path->unflatten(buffer); - } - -#ifdef SK_DEBUG_VALIDATE - void validate() const { - // to be written - } -#endif - -private: - char fPathData[1]; - typedef SkFlatData INHERITED; -}; - class SkFlatRegion : public SkFlatData { public: static SkFlatRegion* Flatten(SkChunkAlloc* heap, const SkRegion& region, int index); diff --git a/skia/picture/SkPicturePlayback.cpp b/skia/picture/SkPicturePlayback.cpp index 3bf162e..64f8f1c 100644 --- a/skia/picture/SkPicturePlayback.cpp +++ b/skia/picture/SkPicturePlayback.cpp @@ -102,16 +102,8 @@ SkPicturePlayback::SkPicturePlayback(const SkPictureRecord& record) { } } - const SkTDArray<const SkFlatPath* >& paths = record.getPaths(); - fPathCount = paths.count(); - if (fPathCount > 0) { - fPaths = SkNEW_ARRAY(SkPath, fPathCount); - for (const SkFlatPath** flatPathPtr = paths.begin(); - flatPathPtr != paths.end(); flatPathPtr++) { - const SkFlatPath* flatPath = *flatPathPtr; - flatPath->unflatten(&fPaths[flatPath->index() - 1]); - } - } + fPathHeap = record.fPathHeap; + fPathHeap->safeRef(); const SkTDArray<SkPicture* >& pictures = record.getPictureRefs(); fPictureCount = pictures.count(); @@ -185,11 +177,8 @@ SkPicturePlayback::SkPicturePlayback(const SkPicturePlayback& src) { fPaints[i] = src.fPaints[i]; } - fPathCount = src.fPathCount; - fPaths = SkNEW_ARRAY(SkPath, fPathCount); - for (i = 0; i < fPathCount; i++) { - fPaths[i] = src.fPaths[i]; - } + fPathHeap = src.fPathHeap; + fPathHeap->safeRef(); fPictureCount = src.fPictureCount; fPictureRefs = SkNEW_ARRAY(SkPicture*, fPictureCount); @@ -209,10 +198,10 @@ void SkPicturePlayback::init() { fBitmaps = NULL; fMatrices = NULL; fPaints = NULL; - fPaths = NULL; + fPathHeap = NULL; fPictureRefs = NULL; fRegions = NULL; - fBitmapCount = fMatrixCount = fPaintCount = fPathCount = fPictureCount = + fBitmapCount = fMatrixCount = fPaintCount = fPictureCount = fRegionCount = 0; fFactoryPlayback = NULL; @@ -224,8 +213,9 @@ SkPicturePlayback::~SkPicturePlayback() { SkDELETE_ARRAY(fBitmaps); SkDELETE_ARRAY(fMatrices); SkDELETE_ARRAY(fPaints); - SkDELETE_ARRAY(fPaths); SkDELETE_ARRAY(fRegions); + + fPathHeap->safeUnref(); for (int i = 0; i < fPictureCount; i++) { fPictureRefs[i]->unref(); @@ -241,7 +231,7 @@ void SkPicturePlayback::dumpSize() const { fBitmapCount, fBitmapCount * sizeof(SkBitmap), fMatrixCount, fMatrixCount * sizeof(SkMatrix), fPaintCount, fPaintCount * sizeof(SkPaint), - fPathCount, + fPathHeap ? fPathHeap->count() : 0, fRegionCount); } @@ -341,9 +331,12 @@ void SkPicturePlayback::serialize(SkWStream* stream) const { fPaints[i].flatten(buffer); } - writeTagSize(buffer, PICT_PATH_TAG, fPathCount); - for (i = 0; i < fPathCount; i++) { - fPaths[i].flatten(buffer); + { + int count = fPathHeap ? fPathHeap->count() : 0; + writeTagSize(buffer, PICT_PATH_TAG, count); + if (count > 0) { + fPathHeap->flatten(buffer); + } } writeTagSize(buffer, PICT_REGION_TAG, fRegionCount); @@ -449,10 +442,11 @@ SkPicturePlayback::SkPicturePlayback(SkStream* stream) { fPaints[i].unflatten(buffer); } - fPathCount = readTagSize(buffer, PICT_PATH_TAG); - fPaths = SkNEW_ARRAY(SkPath, fPathCount); - for (i = 0; i < fPathCount; i++) { - fPaths[i].unflatten(buffer); + { + int count = readTagSize(buffer, PICT_PATH_TAG); + if (count > 0) { + fPathHeap = SkNEW_ARGS(SkPathHeap, (buffer)); + } } fRegionCount = readTagSize(buffer, PICT_REGION_TAG); @@ -474,8 +468,6 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { TextContainer text; fReader.rewind(); - bool clipBoundsDirty = true; - SkRect clipBounds; while (!fReader.eof()) { switch (fReader.readInt()) { @@ -483,12 +475,11 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { const SkPath& path = getPath(); SkRegion::Op op = (SkRegion::Op) getInt(); size_t offsetToRestore = getInt(); - // HACK (false) until I can handle op==kReplace <reed> + // HACK (false) until I can handle op==kReplace if (!canvas.clipPath(path, op) && false) { //SkDebugf("---- skip clipPath for %d bytes\n", offsetToRestore - fReader.offset()); fReader.setOffset(offsetToRestore); } - clipBoundsDirty = true; } break; case CLIP_REGION: { const SkRegion& region = getRegion(); @@ -498,7 +489,6 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { //SkDebugf("---- skip clipDeviceRgn for %d bytes\n", offsetToRestore - fReader.offset()); fReader.setOffset(offsetToRestore); } - clipBoundsDirty = true; } break; case CLIP_RECT: { const SkRect* rect = fReader.skipRect(); @@ -508,11 +498,9 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { //SkDebugf("---- skip clipRect for %d bytes\n", offsetToRestore - fReader.offset()); fReader.setOffset(offsetToRestore); } - clipBoundsDirty = true; } break; case CONCAT: canvas.concat(*getMatrix()); - clipBoundsDirty = true; break; case DRAW_BITMAP: { const SkPaint* paint = getPaint(); @@ -538,8 +526,7 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { break; case DRAW_PATH: { const SkPaint& paint = *getPaint(); - const SkPath& path = getPath(); - canvas.drawPath(path, paint); + canvas.drawPath(getPath(), paint); } break; case DRAW_PICTURE: canvas.drawPicture(getPicture()); @@ -561,43 +548,29 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { case DRAW_POS_TEXT_H: { const SkPaint& paint = *getPaint(); getText(&text); - size_t points = getInt(); - size_t byteLength = text.length(); - const SkScalar* xpos = (const SkScalar*)fReader.skip((3 + points) * sizeof(SkScalar)); + size_t xCount = getInt(); + const SkScalar constY = getScalar(); + const SkScalar* xpos = (const SkScalar*)fReader.skip(xCount * sizeof(SkScalar)); + canvas.drawPosTextH(text.text(), text.length(), xpos, constY, + paint); + } break; + case DRAW_POS_TEXT_H_TOP_BOTTOM: { + const SkPaint& paint = *getPaint(); + getText(&text); + size_t xCount = getInt(); + const SkScalar* xpos = (const SkScalar*)fReader.skip((3 + xCount) * sizeof(SkScalar)); const SkScalar top = *xpos++; const SkScalar bottom = *xpos++; const SkScalar constY = *xpos++; - // would be nice to do this before we load the other fields - // (especially the text block). To do that we'd need to record - // the number of bytes to skip... - if (clipBoundsDirty) { - if (!canvas.getClipBounds(&clipBounds)) { - clipBounds.setEmpty(); - } - clipBoundsDirty = false; - } - if (top < clipBounds.fBottom && bottom > clipBounds.fTop) { - canvas.drawPosTextH(text.text(), byteLength, xpos, constY, - paint); + if (!canvas.quickRejectY(top, bottom, SkCanvas::kAA_EdgeType)) { + canvas.drawPosTextH(text.text(), text.length(), xpos, + constY, paint); } } break; - case DRAW_RECT_GENERAL: { + case DRAW_RECT: { const SkPaint& paint = *getPaint(); canvas.drawRect(*fReader.skipRect(), paint); } break; - case DRAW_RECT_SIMPLE: { - const SkPaint& paint = *getPaint(); - const SkRect* rect = fReader.skipRect(); - if (clipBoundsDirty) { - if (!canvas.getClipBounds(&clipBounds)) { - clipBounds.setEmpty(); - } - clipBoundsDirty = false; - } - if (SkRect::Intersects(clipBounds, *rect)) { - canvas.drawRect(*rect, paint); - } - } break; case DRAW_SPRITE: { const SkPaint* paint = getPaint(); const SkBitmap& bitmap = getBitmap(); @@ -608,18 +581,20 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { case DRAW_TEXT: { const SkPaint& paint = *getPaint(); getText(&text); + SkScalar x = getScalar(); + SkScalar y = getScalar(); + canvas.drawText(text.text(), text.length(), x, y, paint); + } break; + case DRAW_TEXT_TOP_BOTTOM: { + const SkPaint& paint = *getPaint(); + getText(&text); const SkScalar* ptr = (const SkScalar*)fReader.skip(4 * sizeof(SkScalar)); // ptr[0] == x // ptr[1] == y // ptr[2] == top // ptr[3] == bottom - if (clipBoundsDirty) { - if (!canvas.getClipBounds(&clipBounds)) { - clipBounds.setEmpty(); - } - clipBoundsDirty = false; - } - if (ptr[2] < clipBounds.fBottom && ptr[3] > clipBounds.fTop) { + if (!canvas.quickRejectY(ptr[2], ptr[3], + SkCanvas::kAA_EdgeType)) { canvas.drawText(text.text(), text.length(), ptr[0], ptr[1], paint); } @@ -661,11 +636,9 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { } break; case RESTORE: canvas.restore(); - clipBoundsDirty = true; break; case ROTATE: canvas.rotate(getScalar()); - clipBoundsDirty = true; break; case SAVE: canvas.save((SkCanvas::SaveFlags) getInt()); @@ -679,19 +652,16 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { SkScalar sx = getScalar(); SkScalar sy = getScalar(); canvas.scale(sx, sy); - clipBoundsDirty = true; } break; case SKEW: { SkScalar sx = getScalar(); SkScalar sy = getScalar(); canvas.skew(sx, sy); - clipBoundsDirty = true; } break; case TRANSLATE: { SkScalar dx = getScalar(); SkScalar dy = getScalar(); canvas.translate(dx, dy); - clipBoundsDirty = true; } break; default: SkASSERT(0); @@ -701,6 +671,10 @@ void SkPicturePlayback::draw(SkCanvas& canvas) { // this->dumpSize(); } +void SkPicturePlayback::abort() { + fReader.skip(fReader.size() - fReader.offset()); +} + /////////////////////////////////////////////////////////////////////////////// #if 0 @@ -1212,8 +1186,7 @@ void SkPicturePlayback::dumpStream() { DUMP_SCALAR(constY); DUMP_POINT_ARRAY(points); } break; - case DRAW_RECT_GENERAL: - case DRAW_RECT_SIMPLE: { + case DRAW_RECT: { DUMP_PTR(SkPaint, getPaint()); DUMP_RECT(rect); } break; @@ -1363,4 +1336,3 @@ void SkPicturePlayback::dump() const { } #endif - diff --git a/skia/picture/SkPicturePlayback.h b/skia/picture/SkPicturePlayback.h index 7e99bd0..b4e69ca 100644 --- a/skia/picture/SkPicturePlayback.h +++ b/skia/picture/SkPicturePlayback.h @@ -8,6 +8,7 @@ #include "SkMatrix.h" #include "SkPaint.h" #include "SkPath.h" +#include "SkPathHeap.h" #include "SkRegion.h" #include "SkPictureFlat.h" @@ -29,6 +30,10 @@ public: void serialize(SkWStream*) const; void dumpSize() const; + + // Can be called in the middle of playback (the draw() call). WIll abort the + // drawing and return from draw() after the "current" op code is done + void abort(); private: @@ -59,9 +64,7 @@ private: } const SkPath& getPath() { - int index = getInt(); - SkASSERT(index > 0 && index <= fPathCount); - return fPaths[index - 1]; + return (*fPathHeap)[getInt() - 1]; } SkPicture& getPicture() { @@ -143,14 +146,13 @@ public: #endif private: + SkPathHeap* fPathHeap; // reference counted SkBitmap* fBitmaps; int fBitmapCount; SkMatrix* fMatrices; int fMatrixCount; SkPaint* fPaints; int fPaintCount; - SkPath* fPaths; - int fPathCount; SkRegion* fRegions; int fRegionCount; mutable SkFlattenableReadBuffer fReader; diff --git a/skia/picture/SkPictureRecord.cpp b/skia/picture/SkPictureRecord.cpp index 718526b..6e7c645 100644 --- a/skia/picture/SkPictureRecord.cpp +++ b/skia/picture/SkPictureRecord.cpp @@ -6,7 +6,7 @@ SkPictureRecord::SkPictureRecord() : fHeap(HEAP_BLOCK_SIZE), fWriter(MIN_WRITER_SIZE) { - fBitmapIndex = fMatrixIndex = fPaintIndex = fPathIndex = fRegionIndex = 1; + fBitmapIndex = fMatrixIndex = fPaintIndex = fRegionIndex = 1; #ifdef SK_DEBUG_SIZE fPointBytes = fRectBytes = fTextBytes = 0; fPointWrites = fRectWrites = fTextWrites = 0; @@ -14,6 +14,8 @@ SkPictureRecord::SkPictureRecord() : fRestoreOffsetStack.setReserve(32); fRestoreOffsetStack.push(0); + + fPathHeap = NULL; // lazy allocate } SkPictureRecord::~SkPictureRecord() { @@ -158,17 +160,8 @@ void SkPictureRecord::drawPoints(PointMode mode, size_t count, const SkPoint pts validate(); } -// return true if geometry drawn with this paint will just be filled -// i.e. its bounding rect will not be larger than the original geometry -static bool is_simple_fill(const SkPaint& paint) { - return paint.getStyle() == SkPaint::kFill_Style && - paint.getPathEffect() == NULL && - paint.getMaskFilter() == NULL && - paint.getRasterizer() == NULL; -} - void SkPictureRecord::drawRect(const SkRect& rect, const SkPaint& paint) { - addDraw(is_simple_fill(paint) ? DRAW_RECT_SIMPLE : DRAW_RECT_GENERAL); + addDraw(DRAW_RECT); addPaint(paint); addRect(rect); validate(); @@ -224,18 +217,29 @@ void SkPictureRecord::addFontMetricsTopBottom(const SkPaint& paint, SkScalar baselineY) { SkPaint::FontMetrics metrics; paint.getFontMetrics(&metrics); - addScalar(metrics.fTop + baselineY); - addScalar(metrics.fBottom + baselineY); + SkRect bounds; + // construct a rect so we can see any adjustments from the paint. + // we use 0,1 for left,right, just so the rect isn't empty + bounds.set(0, metrics.fTop + baselineY, + SK_Scalar1, metrics.fBottom + baselineY); + (void)paint.computeFastBounds(bounds, &bounds); + // now record the top and bottom + addScalar(bounds.fTop); + addScalar(bounds.fBottom); } void SkPictureRecord::drawText(const void* text, size_t byteLength, SkScalar x, SkScalar y, const SkPaint& paint) { - addDraw(DRAW_TEXT); + bool fast = paint.canComputeFastBounds(); + + addDraw(fast ? DRAW_TEXT_TOP_BOTTOM : DRAW_TEXT); addPaint(paint); addText(text, byteLength); addScalar(x); addScalar(y); - addFontMetricsTopBottom(paint, y); + if (fast) { + addFontMetricsTopBottom(paint, y); + } validate(); } @@ -257,7 +261,13 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength, } } - addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT); + bool fast = canUseDrawH && paint.canComputeFastBounds(); + + if (fast) { + addDraw(DRAW_POS_TEXT_H_TOP_BOTTOM); + } else { + addDraw(canUseDrawH ? DRAW_POS_TEXT_H : DRAW_POS_TEXT); + } addPaint(paint); addText(text, byteLength); addInt(points); @@ -266,7 +276,9 @@ void SkPictureRecord::drawPosText(const void* text, size_t byteLength, size_t start = fWriter.size(); #endif if (canUseDrawH) { - addFontMetricsTopBottom(paint, pos[0].fY); + if (fast) { + addFontMetricsTopBottom(paint, pos[0].fY); + } addScalar(pos[0].fY); SkScalar* xptr = (SkScalar*)fWriter.reserve(points * sizeof(SkScalar)); for (size_t index = 0; index < points; index++) @@ -289,7 +301,9 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, if (0 == points) return; - addDraw(DRAW_POS_TEXT_H); + bool fast = paint.canComputeFastBounds(); + + addDraw(fast ? DRAW_POS_TEXT_H_TOP_BOTTOM : DRAW_POS_TEXT_H); addPaint(paint); addText(text, byteLength); addInt(points); @@ -297,7 +311,9 @@ void SkPictureRecord::drawPosTextH(const void* text, size_t byteLength, #ifdef SK_DEBUG_SIZE size_t start = fWriter.size(); #endif - addFontMetricsTopBottom(paint, constY); + if (fast) { + addFontMetricsTopBottom(paint, constY); + } addScalar(constY); fWriter.writeMul4(xpos, points * sizeof(SkScalar)); #ifdef SK_DEBUG_SIZE @@ -361,10 +377,12 @@ void SkPictureRecord::drawVertices(VertexMode vmode, int vertexCount, /////////////////////////////////////////////////////////////////////////////// void SkPictureRecord::reset() { + fPathHeap->safeUnref(); + fPathHeap = NULL; + fBitmaps.reset(); fMatrices.reset(); fPaints.reset(); - fPaths.reset(); fPictureRefs.unrefAll(); fRegions.reset(); fWriter.reset(); @@ -398,7 +416,10 @@ void SkPictureRecord::addPaintPtr(const SkPaint* paint) { } void SkPictureRecord::addPath(const SkPath& path) { - addInt(find(fPaths, path)); + if (NULL == fPathHeap) { + fPathHeap = SkNEW(SkPathHeap); + } + addInt(fPathHeap->append(path)); } void SkPictureRecord::addPicture(SkPicture& picture) { @@ -518,17 +539,6 @@ int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* return fPaintIndex++; } -int SkPictureRecord::find(SkTDArray<const SkFlatPath* >& paths, const SkPath& path) { - SkFlatPath* flat = SkFlatPath::Flatten(&fHeap, path, fPathIndex); - int index = SkTSearch<SkFlatData>((const SkFlatData**) paths.begin(), - paths.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare); - if (index >= 0) - return paths[index]->index(); - index = ~index; - *paths.insert(index) = flat; - return fPathIndex++; -} - int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region) { SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex); int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(), diff --git a/skia/picture/SkPictureRecord.h b/skia/picture/SkPictureRecord.h index 350040e..d25d23a 100644 --- a/skia/picture/SkPictureRecord.h +++ b/skia/picture/SkPictureRecord.h @@ -3,6 +3,7 @@ #include "SkCanvas.h" #include "SkFlattenable.h" +#include "SkPathHeap.h" #include "SkPicture.h" #include "SkPictureFlat.h" #include "SkTemplates.h" @@ -65,9 +66,6 @@ public: const SkTDArray<const SkFlatPaint* >& getPaints() const { return fPaints; } - const SkTDArray<const SkFlatPath* >& getPaths() const { - return fPaths; - } const SkTDArray<SkPicture* >& getPictureRefs() const { return fPictureRefs; } @@ -117,7 +115,6 @@ private: int find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMatrix* matrix); int find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint* paint); - int find(SkTDArray<const SkFlatPath* >& paths, const SkPath& path); int find(SkTDArray<const SkFlatRegion* >& regions, const SkRegion& region); #ifdef SK_DEBUG_DUMP @@ -162,10 +159,9 @@ private: SkTDArray<const SkFlatMatrix* > fMatrices; int fPaintIndex; SkTDArray<const SkFlatPaint* > fPaints; - int fPathIndex; - SkTDArray<const SkFlatPath* > fPaths; int fRegionIndex; SkTDArray<const SkFlatRegion* > fRegions; + SkPathHeap* fPathHeap; // reference counted SkWriter32 fWriter; // we ref each item in this array |