#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);
+ }
}
///////////////////////////////////////////////////////////////////////////////
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;
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++;
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();
}
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++;
008C4D980F77DAEE0056981C /* SampleHairline.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 008C4D970F77DAEE0056981C /* SampleHairline.cpp */; };
009CC9190F65918A002185BE /* SampleFontScalerTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */; };
00A41E4B0EFC312F00C9CBEB /* SampleArc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00A41E4A0EFC312F00C9CBEB /* SampleArc.cpp */; };
+ 00FACE3C0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */; };
+ 00FACE680F7D23DD00F8A7FF /* SkWriter32_largeBlock.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */; };
0156F80407C56A3000C6122B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0156F80307C56A3000C6122B /* Foundation.framework */; };
01FC44D507BD3BB800D228F4 /* Quartz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 01FC44D407BD3BB800D228F4 /* Quartz.framework */; };
8D0C4E8D0486CD37000505A6 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 0867D6AAFE840B52C02AAC07 /* InfoPlist.strings */; };
009CC9180F65918A002185BE /* SampleFontScalerTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFontScalerTest.cpp; path = ../../samplecode/SampleFontScalerTest.cpp; sourceTree = SOURCE_ROOT; };
00A41E4A0EFC312F00C9CBEB /* SampleArc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleArc.cpp; path = ../../samplecode/SampleArc.cpp; sourceTree = SOURCE_ROOT; };
00D6B5CB0F72DC4300C466B9 /* SampleFuzz.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SampleFuzz.cpp; path = ../../samplecode/SampleFuzz.cpp; sourceTree = SOURCE_ROOT; };
+ 00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLargeBlock_malloc.cpp; path = ../../src/utils/SkLargeBlock_malloc.cpp; sourceTree = SOURCE_ROOT; };
+ 00FACE3F0F7D167400F8A7FF /* SkLargeBlock_remap.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkLargeBlock_remap.cpp; path = ../../src/utils/SkLargeBlock_remap.cpp; sourceTree = SOURCE_ROOT; };
+ 00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkWriter32_largeBlock.cpp; path = ../../src/utils/SkWriter32_largeBlock.cpp; sourceTree = SOURCE_ROOT; };
+ 00FACE600F7D22CF00F8A7FF /* SkWriter32_noLargeBlock.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SkWriter32_noLargeBlock.cpp; path = ../../src/utils/SkWriter32_noLargeBlock.cpp; sourceTree = SOURCE_ROOT; };
0156F80307C56A3000C6122B /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = /System/Library/Frameworks/Foundation.framework; sourceTree = "<absolute>"; };
01FC44D407BD3BB800D228F4 /* Quartz.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Quartz.framework; path = /System/Library/Frameworks/Quartz.framework; sourceTree = "<absolute>"; };
0867D6ABFE840B52C02AAC07 /* English */ = {isa = PBXFileReference; fileEncoding = 10; lastKnownFileType = text.plist.strings; name = English; path = English.lproj/InfoPlist.strings; sourceTree = "<group>"; };
002884490EFAA35C0083E387 /* core.xcodeproj */,
002884B40EFAB69F0083E387 /* maccore.xcodeproj */,
00003C8C0EFC230E000FF73A /* effects.xcodeproj */,
+ 00FACE3B0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp */,
+ 00FACE3F0F7D167400F8A7FF /* SkLargeBlock_remap.cpp */,
+ 00FACE5C0F7D209700F8A7FF /* SkWriter32_largeBlock.cpp */,
+ 00FACE600F7D22CF00F8A7FF /* SkWriter32_noLargeBlock.cpp */,
);
name = CICarbonSample;
sourceTree = "<group>";
007A7CB30F01658C00A2D6EE /* SamplePicture.cpp in Sources */,
0041CE440F00A12400695E8C /* SampleLines.cpp in Sources */,
008C4D980F77DAEE0056981C /* SampleHairline.cpp in Sources */,
+ 00FACE3C0F7D0E6600F8A7FF /* SkLargeBlock_malloc.cpp in Sources */,
+ 00FACE680F7D23DD00F8A7FF /* SkWriter32_largeBlock.cpp in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};