| |
| /* |
| * Copyright 2011 Google Inc. |
| * |
| * Use of this source code is governed by a BSD-style license that can be |
| * found in the LICENSE file. |
| */ |
| #include "SkPictureFlat.h" |
| |
| #include "SkColorFilter.h" |
| #include "SkDrawLooper.h" |
| #include "SkMaskFilter.h" |
| #include "SkRasterizer.h" |
| #include "SkShader.h" |
| #include "SkTypeface.h" |
| #include "SkXfermode.h" |
| |
| SkFlatData* SkFlatData::Alloc(SkChunkAlloc* heap, int32_t size, int index) { |
| SkFlatData* result = (SkFlatData*) heap->allocThrow(size + sizeof(SkFlatData)); |
| result->fIndex = index; |
| result->fAllocSize = size + sizeof(result->fAllocSize); |
| return result; |
| } |
| |
| SkFlatBitmap* SkFlatBitmap::Flatten(SkChunkAlloc* heap, const SkBitmap& bitmap, |
| int index, SkRefCntSet* rec) { |
| SkFlattenableWriteBuffer buffer(1024); |
| buffer.setRefCntRecorder(rec); |
| |
| bitmap.flatten(buffer); |
| size_t size = buffer.size(); |
| SkFlatBitmap* result = (SkFlatBitmap*) INHERITED::Alloc(heap, size, index); |
| buffer.flatten(result->fBitmapData); |
| return result; |
| } |
| |
| SkFlatMatrix* SkFlatMatrix::Flatten(SkChunkAlloc* heap, const SkMatrix& matrix, int index) { |
| size_t size = matrix.flatten(NULL); |
| SkFlatMatrix* result = (SkFlatMatrix*) INHERITED::Alloc(heap, size, index); |
| matrix.flatten(&result->fMatrixData); |
| return result; |
| } |
| |
| #ifdef SK_DEBUG_DUMP |
| void SkFlatMatrix::dump() const { |
| const SkMatrix* matrix = (const SkMatrix*) fMatrixData; |
| char pBuffer[DUMP_BUFFER_SIZE]; |
| char* bufferPtr = pBuffer; |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "matrix: "); |
| SkScalar scaleX = matrix->getScaleX(); |
| SkMatrix defaultMatrix; |
| defaultMatrix.reset(); |
| if (scaleX != defaultMatrix.getScaleX()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "scaleX:%g ", SkScalarToFloat(scaleX)); |
| SkScalar scaleY = matrix->getScaleY(); |
| if (scaleY != defaultMatrix.getScaleY()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "scaleY:%g ", SkScalarToFloat(scaleY)); |
| SkScalar skewX = matrix->getSkewX(); |
| if (skewX != defaultMatrix.getSkewX()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "skewX:%g ", SkScalarToFloat(skewX)); |
| SkScalar skewY = matrix->getSkewY(); |
| if (skewY != defaultMatrix.getSkewY()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "skewY:%g ", SkScalarToFloat(skewY)); |
| SkScalar translateX = matrix->getTranslateX(); |
| if (translateX != defaultMatrix.getTranslateX()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "translateX:%g ", SkScalarToFloat(translateX)); |
| SkScalar translateY = matrix->getTranslateY(); |
| if (translateY != defaultMatrix.getTranslateY()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "translateY:%g ", SkScalarToFloat(translateY)); |
| SkScalar perspX = matrix->getPerspX(); |
| if (perspX != defaultMatrix.getPerspX()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "perspX:%g ", SkFractToFloat(perspX)); |
| SkScalar perspY = matrix->getPerspY(); |
| if (perspY != defaultMatrix.getPerspY()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "perspY:%g ", SkFractToFloat(perspY)); |
| SkDebugf("%s\n", pBuffer); |
| } |
| #endif |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| SkFlatPaint* SkFlatPaint::Flatten(SkChunkAlloc* heap, const SkPaint& paint, |
| int index, SkRefCntSet* rec, |
| SkRefCntSet* faceRecorder) { |
| SkFlattenableWriteBuffer buffer(2*sizeof(SkPaint)); |
| buffer.setRefCntRecorder(rec); |
| buffer.setTypefaceRecorder(faceRecorder); |
| |
| paint.flatten(buffer); |
| uint32_t size = buffer.size(); |
| SkFlatPaint* result = (SkFlatPaint*) INHERITED::Alloc(heap, size, index); |
| buffer.flatten(&result->fPaintData); |
| return result; |
| } |
| |
| void SkFlatPaint::Read(const void* storage, SkPaint* paint, |
| SkRefCntPlayback* rcp, SkTypefacePlayback* facePlayback) { |
| SkFlattenableReadBuffer buffer(storage); |
| if (rcp) { |
| rcp->setupBuffer(buffer); |
| } |
| if (facePlayback) { |
| facePlayback->setupBuffer(buffer); |
| } |
| paint->unflatten(buffer); |
| } |
| |
| #ifdef SK_DEBUG_DUMP |
| void SkFlatPaint::dump() const { |
| SkPaint defaultPaint; |
| SkFlattenableReadBuffer buffer(fPaintData); |
| SkTypeface* typeface = (SkTypeface*) buffer.readPtr(); |
| char pBuffer[DUMP_BUFFER_SIZE]; |
| char* bufferPtr = pBuffer; |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "paint: "); |
| if (typeface != defaultPaint.getTypeface()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "typeface:%p ", typeface); |
| SkScalar textSize = buffer.readScalar(); |
| if (textSize != defaultPaint.getTextSize()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "textSize:%g ", SkScalarToFloat(textSize)); |
| SkScalar textScaleX = buffer.readScalar(); |
| if (textScaleX != defaultPaint.getTextScaleX()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "textScaleX:%g ", SkScalarToFloat(textScaleX)); |
| SkScalar textSkewX = buffer.readScalar(); |
| if (textSkewX != defaultPaint.getTextSkewX()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "textSkewX:%g ", SkScalarToFloat(textSkewX)); |
| const SkPathEffect* pathEffect = (const SkPathEffect*) buffer.readFlattenable(); |
| if (pathEffect != defaultPaint.getPathEffect()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "pathEffect:%p ", pathEffect); |
| SkDELETE(pathEffect); |
| const SkShader* shader = (const SkShader*) buffer.readFlattenable(); |
| if (shader != defaultPaint.getShader()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "shader:%p ", shader); |
| SkDELETE(shader); |
| const SkXfermode* xfermode = (const SkXfermode*) buffer.readFlattenable(); |
| if (xfermode != defaultPaint.getXfermode()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "xfermode:%p ", xfermode); |
| SkDELETE(xfermode); |
| const SkMaskFilter* maskFilter = (const SkMaskFilter*) buffer.readFlattenable(); |
| if (maskFilter != defaultPaint.getMaskFilter()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "maskFilter:%p ", maskFilter); |
| SkDELETE(maskFilter); |
| const SkColorFilter* colorFilter = (const SkColorFilter*) buffer.readFlattenable(); |
| if (colorFilter != defaultPaint.getColorFilter()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "colorFilter:%p ", colorFilter); |
| SkDELETE(colorFilter); |
| const SkRasterizer* rasterizer = (const SkRasterizer*) buffer.readFlattenable(); |
| if (rasterizer != defaultPaint.getRasterizer()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "rasterizer:%p ", rasterizer); |
| SkDELETE(rasterizer); |
| const SkDrawLooper* drawLooper = (const SkDrawLooper*) buffer.readFlattenable(); |
| if (drawLooper != defaultPaint.getLooper()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "drawLooper:%p ", drawLooper); |
| SkDELETE(drawLooper); |
| unsigned color = buffer.readU32(); |
| if (color != defaultPaint.getColor()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "color:0x%x ", color); |
| SkScalar strokeWidth = buffer.readScalar(); |
| if (strokeWidth != defaultPaint.getStrokeWidth()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "strokeWidth:%g ", SkScalarToFloat(strokeWidth)); |
| SkScalar strokeMiter = buffer.readScalar(); |
| if (strokeMiter != defaultPaint.getStrokeMiter()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "strokeMiter:%g ", SkScalarToFloat(strokeMiter)); |
| unsigned flags = buffer.readU16(); |
| if (flags != defaultPaint.getFlags()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "flags:0x%x ", flags); |
| int align = buffer.readU8(); |
| if (align != defaultPaint.getTextAlign()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "align:0x%x ", align); |
| int strokeCap = buffer.readU8(); |
| if (strokeCap != defaultPaint.getStrokeCap()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "strokeCap:0x%x ", strokeCap); |
| int strokeJoin = buffer.readU8(); |
| if (strokeJoin != defaultPaint.getStrokeJoin()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "align:0x%x ", strokeJoin); |
| int style = buffer.readU8(); |
| if (style != defaultPaint.getStyle()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "style:0x%x ", style); |
| int textEncoding = buffer.readU8(); |
| if (textEncoding != defaultPaint.getTextEncoding()) |
| bufferPtr += snprintf(bufferPtr, DUMP_BUFFER_SIZE - (bufferPtr - pBuffer), |
| "textEncoding:0x%x ", textEncoding); |
| SkDebugf("%s\n", pBuffer); |
| } |
| #endif |
| |
| SkFlatRegion* SkFlatRegion::Flatten(SkChunkAlloc* heap, const SkRegion& region, int index) { |
| uint32_t size = region.flatten(NULL); |
| SkFlatRegion* result = (SkFlatRegion*) INHERITED::Alloc(heap, size, index); |
| region.flatten(&result->fRegionData); |
| return result; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| SkRefCntPlayback::SkRefCntPlayback() : fCount(0), fArray(NULL) {} |
| |
| SkRefCntPlayback::~SkRefCntPlayback() { |
| this->reset(NULL); |
| } |
| |
| void SkRefCntPlayback::reset(const SkRefCntSet* rec) { |
| for (int i = 0; i < fCount; i++) { |
| SkASSERT(fArray[i]); |
| fArray[i]->unref(); |
| } |
| SkDELETE_ARRAY(fArray); |
| |
| if (rec) { |
| fCount = rec->count(); |
| fArray = SkNEW_ARRAY(SkRefCnt*, fCount); |
| rec->copyToArray(fArray); |
| for (int i = 0; i < fCount; i++) { |
| fArray[i]->ref(); |
| } |
| } else { |
| fCount = 0; |
| fArray = NULL; |
| } |
| } |
| |
| void SkRefCntPlayback::setCount(int count) { |
| this->reset(NULL); |
| |
| fCount = count; |
| fArray = SkNEW_ARRAY(SkRefCnt*, count); |
| sk_bzero(fArray, count * sizeof(SkRefCnt*)); |
| } |
| |
| SkRefCnt* SkRefCntPlayback::set(int index, SkRefCnt* obj) { |
| SkASSERT((unsigned)index < (unsigned)fCount); |
| SkRefCnt_SafeAssign(fArray[index], obj); |
| return obj; |
| } |
| |