aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-30 21:02:14 +0000
committerGravatar reed@android.com <reed@android.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2009-03-30 21:02:14 +0000
commitaefd2bc75738963b9b6579897be32bfbc8fb00af (patch)
treeaf2a10646259a721b27e84c97e13b75b50882696 /src/core
parentf459a4949d4edb179e015cf12635d26c596fd17c (diff)
Add SkChunkAlloc::unalloc() to undo the last allocation, useful if the caller wants to treat the allocats like temp memory (see PictureRecord)
Call unalloc if a paint (or other cached object) is already in our list for picture recording Use correct CompareType macro in SkCanvas::quickReject git-svn-id: http://skia.googlecode.com/svn/trunk@138 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkCanvas.cpp4
-rw-r--r--src/core/SkChunkAlloc.cpp21
-rw-r--r--src/core/SkPaint.cpp173
-rw-r--r--src/core/SkPictureRecord.cpp12
4 files changed, 163 insertions, 47 deletions
diff --git a/src/core/SkCanvas.cpp b/src/core/SkCanvas.cpp
index 00461b0de2..16c94c28c0 100644
--- a/src/core/SkCanvas.cpp
+++ b/src/core/SkCanvas.cpp
@@ -943,8 +943,8 @@ bool SkCanvas::quickRejectY(SkScalar top, SkScalar bottom, EdgeType et) const {
return true;
}
- SkScalarCompareType userT = SkScalarAs2sCompliment(top);
- SkScalarCompareType userB = SkScalarAs2sCompliment(bottom);
+ SkScalarCompareType userT = SkScalarToCompareType(top);
+ SkScalarCompareType userB = SkScalarToCompareType(bottom);
// check for invalid user Y coordinates (i.e. empty)
if (userT >= userB) {
diff --git a/src/core/SkChunkAlloc.cpp b/src/core/SkChunkAlloc.cpp
index ae37ec0839..83272c58eb 100644
--- a/src/core/SkChunkAlloc.cpp
+++ b/src/core/SkChunkAlloc.cpp
@@ -23,6 +23,10 @@ struct SkChunkAlloc::Block {
char* fFreePtr;
// data[] follows
+ char* startOfData() {
+ return reinterpret_cast<char*>(this + 1);
+ }
+
void freeChain() { // this can be null
Block* block = this;
while (block) {
@@ -89,7 +93,7 @@ SkChunkAlloc::Block* SkChunkAlloc::newBlock(size_t bytes, AllocFailType ftype) {
if (block) {
// block->fNext = fBlock;
block->fFreeSize = size;
- block->fFreePtr = (char*)block + sizeof(Block);
+ block->fFreePtr = block->startOfData();
fTotalCapacity += size;
}
@@ -118,3 +122,18 @@ void* SkChunkAlloc::alloc(size_t bytes, AllocFailType ftype) {
return ptr;
}
+size_t SkChunkAlloc::unalloc(void* ptr) {
+ size_t bytes = 0;
+ Block* block = fBlock;
+ if (block) {
+ char* cPtr = reinterpret_cast<char*>(ptr);
+ char* start = block->startOfData();
+ if (start <= cPtr && cPtr < block->fFreePtr) {
+ bytes = block->fFreePtr - cPtr;
+ block->fFreeSize += bytes;
+ block->fFreePtr = cPtr;
+ }
+ }
+ return bytes;
+}
+
diff --git a/src/core/SkPaint.cpp b/src/core/SkPaint.cpp
index 691da41980..da70c74fe5 100644
--- a/src/core/SkPaint.cpp
+++ b/src/core/SkPaint.cpp
@@ -1278,50 +1278,143 @@ SkGlyphCache* SkPaint::detachCache(const SkMatrix* deviceMatrix) const
#include "SkStream.h"
+static uintptr_t asint(const void* p) {
+ return reinterpret_cast<uintptr_t>(p);
+}
+
+union Scalar32 {
+ SkScalar fScalar;
+ uint32_t f32;
+};
+
+static uint32_t* write_scalar(uint32_t* ptr, SkScalar value) {
+ SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
+ Scalar32 tmp;
+ tmp.fScalar = value;
+ *ptr = tmp.f32;
+ return ptr + 1;
+}
+
+static SkScalar read_scalar(const uint32_t*& ptr) {
+ SkASSERT(sizeof(SkScalar) == sizeof(uint32_t));
+ Scalar32 tmp;
+ tmp.f32 = *ptr++;
+ return tmp.fScalar;
+}
+
+static uint32_t pack_4(unsigned a, unsigned b, unsigned c, unsigned d) {
+ SkASSERT(a == (uint8_t)a);
+ SkASSERT(b == (uint8_t)b);
+ SkASSERT(c == (uint8_t)c);
+ SkASSERT(d == (uint8_t)d);
+ return (a << 24) | (b << 16) | (c << 8) | d;
+}
+
+enum FlatFlags {
+ kHasTypeface_FlatFlag = 0x01,
+ kHasEffects_FlatFlag = 0x02
+};
+
+// The size of a flat paint's POD fields
+static const uint32_t kPODPaintSize = 5 * sizeof(SkScalar) +
+ 1 * sizeof(SkColor) +
+ 1 * sizeof(uint16_t) +
+ 6 * sizeof(uint8_t);
+
+/* To save space/time, we analyze the paint, and write a truncated version of
+ it if there are not tricky elements like shaders, etc.
+ */
void SkPaint::flatten(SkFlattenableWriteBuffer& buffer) const {
- buffer.writeTypeface(this->getTypeface());
- buffer.writeScalar(this->getTextSize());
- buffer.writeScalar(this->getTextScaleX());
- buffer.writeScalar(this->getTextSkewX());
- buffer.writeFlattenable(this->getPathEffect());
- buffer.writeFlattenable(this->getShader());
- buffer.writeFlattenable(this->getXfermode());
- buffer.writeFlattenable(this->getMaskFilter());
- buffer.writeFlattenable(this->getColorFilter());
- buffer.writeFlattenable(this->getRasterizer());
- buffer.writeFlattenable(this->getLooper());
- buffer.write32(this->getColor());
- buffer.writeScalar(this->getStrokeWidth());
- buffer.writeScalar(this->getStrokeMiter());
- buffer.write16(this->getFlags());
- buffer.write8(this->getTextAlign());
- buffer.write8(this->getStrokeCap());
- buffer.write8(this->getStrokeJoin());
- buffer.write8(this->getStyle());
- buffer.write8(this->getTextEncoding());
+ uint8_t flatFlags = 0;
+ if (this->getTypeface()) {
+ flatFlags |= kHasTypeface_FlatFlag;
+ }
+ if (asint(this->getPathEffect()) |
+ asint(this->getShader()) |
+ asint(this->getXfermode()) |
+ asint(this->getMaskFilter()) |
+ asint(this->getColorFilter()) |
+ asint(this->getRasterizer()) |
+ asint(this->getLooper())) {
+ flatFlags |= kHasEffects_FlatFlag;
+ }
+
+ SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
+ uint32_t* ptr = buffer.reserve(kPODPaintSize);
+
+ ptr = write_scalar(ptr, this->getTextSize());
+ ptr = write_scalar(ptr, this->getTextScaleX());
+ ptr = write_scalar(ptr, this->getTextSkewX());
+ ptr = write_scalar(ptr, this->getStrokeWidth());
+ ptr = write_scalar(ptr, this->getStrokeMiter());
+ *ptr++ = this->getColor();
+ *ptr++ = (this->getFlags() << 16) | (this->getTextAlign() << 8) | flatFlags;
+ *ptr++ = pack_4(this->getStrokeCap(), this->getStrokeJoin(),
+ this->getStyle(), this->getTextEncoding());
+
+ // now we're done with ptr and the (pre)reserved space. If we need to write
+ // additional fields, use the buffer directly
+ if (flatFlags & kHasTypeface_FlatFlag) {
+ buffer.writeTypeface(this->getTypeface());
+ }
+ if (flatFlags & kHasEffects_FlatFlag) {
+ buffer.writeFlattenable(this->getPathEffect());
+ buffer.writeFlattenable(this->getShader());
+ buffer.writeFlattenable(this->getXfermode());
+ buffer.writeFlattenable(this->getMaskFilter());
+ buffer.writeFlattenable(this->getColorFilter());
+ buffer.writeFlattenable(this->getRasterizer());
+ buffer.writeFlattenable(this->getLooper());
+ }
}
void SkPaint::unflatten(SkFlattenableReadBuffer& buffer) {
- this->setTypeface(buffer.readTypeface());
- this->setTextSize(buffer.readScalar());
- this->setTextScaleX(buffer.readScalar());
- this->setTextSkewX(buffer.readScalar());
- this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
- this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
- this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
- this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
- this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
- this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
- this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
- this->setColor(buffer.readU32());
- this->setStrokeWidth(buffer.readScalar());
- this->setStrokeMiter(buffer.readScalar());
- this->setFlags(buffer.readU16());
- this->setTextAlign((SkPaint::Align) buffer.readU8());
- this->setStrokeCap((SkPaint::Cap) buffer.readU8());
- this->setStrokeJoin((SkPaint::Join) buffer.readU8());
- this->setStyle((SkPaint::Style) buffer.readU8());
- this->setTextEncoding((SkPaint::TextEncoding) buffer.readU8());
+ SkASSERT(SkAlign4(kPODPaintSize) == kPODPaintSize);
+ const void* podData = buffer.skip(kPODPaintSize);
+ const uint32_t* pod = reinterpret_cast<const uint32_t*>(podData);
+
+ // the order we read must match the order we wrote in flatten()
+ this->setTextSize(read_scalar(pod));
+ this->setTextScaleX(read_scalar(pod));
+ this->setTextSkewX(read_scalar(pod));
+ this->setStrokeWidth(read_scalar(pod));
+ this->setStrokeMiter(read_scalar(pod));
+ this->setColor(*pod++);
+
+ uint32_t tmp = *pod++;
+ this->setFlags(tmp >> 16);
+ this->setTextAlign(static_cast<Align>((tmp >> 8) & 0xFF));
+ uint8_t flatFlags = tmp & 0xFF;
+
+ tmp = *pod++;
+ this->setStrokeCap(static_cast<Cap>((tmp >> 24) & 0xFF));
+ this->setStrokeJoin(static_cast<Join>((tmp >> 16) & 0xFF));
+ this->setStyle(static_cast<Style>((tmp >> 8) & 0xFF));
+ this->setTextEncoding(static_cast<TextEncoding>((tmp >> 0) & 0xFF));
+
+ if (flatFlags & kHasTypeface_FlatFlag) {
+ this->setTypeface(buffer.readTypeface());
+ } else {
+ this->setTypeface(NULL);
+ }
+
+ if (flatFlags & kHasEffects_FlatFlag) {
+ this->setPathEffect((SkPathEffect*) buffer.readFlattenable())->safeUnref();
+ this->setShader((SkShader*) buffer.readFlattenable())->safeUnref();
+ this->setXfermode((SkXfermode*) buffer.readFlattenable())->safeUnref();
+ this->setMaskFilter((SkMaskFilter*) buffer.readFlattenable())->safeUnref();
+ this->setColorFilter((SkColorFilter*) buffer.readFlattenable())->safeUnref();
+ this->setRasterizer((SkRasterizer*) buffer.readFlattenable())->safeUnref();
+ this->setLooper((SkDrawLooper*) buffer.readFlattenable())->safeUnref();
+ } else {
+ this->setPathEffect(NULL);
+ this->setShader(NULL);
+ this->setXfermode(NULL);
+ this->setMaskFilter(NULL);
+ this->setColorFilter(NULL);
+ this->setRasterizer(NULL);
+ this->setLooper(NULL);
+ }
}
///////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/SkPictureRecord.cpp b/src/core/SkPictureRecord.cpp
index c1fadc6c5e..ed47d64f91 100644
--- a/src/core/SkPictureRecord.cpp
+++ b/src/core/SkPictureRecord.cpp
@@ -514,8 +514,7 @@ int SkPictureRecord::find(SkTDArray<const SkFlatBitmap* >& bitmaps, const SkBitm
int index = SkTSearch<SkFlatData>((const SkFlatData**) bitmaps.begin(),
bitmaps.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
if (index >= 0) {
-// SkBitmap bitmap;
-// flat->unflatten(&bitmap); // balance ref count
+ (void)fHeap.unalloc(flat);
return bitmaps[index]->index();
}
index = ~index;
@@ -529,8 +528,10 @@ int SkPictureRecord::find(SkTDArray<const SkFlatMatrix* >& matrices, const SkMat
SkFlatMatrix* flat = SkFlatMatrix::Flatten(&fHeap, *matrix, fMatrixIndex);
int index = SkTSearch<SkFlatData>((const SkFlatData**) matrices.begin(),
matrices.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0)
+ if (index >= 0) {
+ (void)fHeap.unalloc(flat);
return matrices[index]->index();
+ }
index = ~index;
*matrices.insert(index) = flat;
return fMatrixIndex++;
@@ -546,6 +547,7 @@ int SkPictureRecord::find(SkTDArray<const SkFlatPaint* >& paints, const SkPaint*
int index = SkTSearch<SkFlatData>((const SkFlatData**) paints.begin(),
paints.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
if (index >= 0) {
+ (void)fHeap.unalloc(flat);
return paints[index]->index();
}
@@ -558,8 +560,10 @@ int SkPictureRecord::find(SkTDArray<const SkFlatRegion* >& regions, const SkRegi
SkFlatRegion* flat = SkFlatRegion::Flatten(&fHeap, region, fRegionIndex);
int index = SkTSearch<SkFlatData>((const SkFlatData**) regions.begin(),
regions.count(), (SkFlatData*) flat, sizeof(flat), &SkFlatData::Compare);
- if (index >= 0)
+ if (index >= 0) {
+ (void)fHeap.unalloc(flat);
return regions[index]->index();
+ }
index = ~index;
*regions.insert(index) = flat;
return fRegionIndex++;