diff options
author | 2009-03-30 21:02:14 +0000 | |
---|---|---|
committer | 2009-03-30 21:02:14 +0000 | |
commit | aefd2bc75738963b9b6579897be32bfbc8fb00af (patch) | |
tree | af2a10646259a721b27e84c97e13b75b50882696 /src/core | |
parent | f459a4949d4edb179e015cf12635d26c596fd17c (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.cpp | 4 | ||||
-rw-r--r-- | src/core/SkChunkAlloc.cpp | 21 | ||||
-rw-r--r-- | src/core/SkPaint.cpp | 173 | ||||
-rw-r--r-- | src/core/SkPictureRecord.cpp | 12 |
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++; |