summaryrefslogtreecommitdiffstats
path: root/skia/picture
diff options
context:
space:
mode:
authorbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-12 21:01:41 +0000
committerbrettw@google.com <brettw@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-12-12 21:01:41 +0000
commit52e935d04c59135739c3a68fb6e19d313dc6d5ad (patch)
tree95f7ab178b045bef4456cbf92c6aa7e476becd99 /skia/picture
parent30fab79877b4bb067944b74d98346ac9bb6bfc7e (diff)
downloadchromium_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.cpp55
-rw-r--r--skia/picture/SkPathHeap.h37
-rw-r--r--skia/picture/SkPicture.cpp246
-rw-r--r--skia/picture/SkPictureFlat.cpp9
-rw-r--r--skia/picture/SkPictureFlat.h27
-rw-r--r--skia/picture/SkPicturePlayback.cpp130
-rw-r--r--skia/picture/SkPicturePlayback.h12
-rw-r--r--skia/picture/SkPictureRecord.cpp74
-rw-r--r--skia/picture/SkPictureRecord.h8
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