Updates for SkGPipe.
Keep track of SkBitmaps which have been flattened by the PipeWriter so we can reuse them. Implement other flavors of drawBitmap (except drawBitmapMatrix). Flatten SkImageFilters in SkPaints. Do not notify if no new data has been written. Review URL: https://codereview.appspot.com/6128062 git-svn-id: http://skia.googlecode.com/svn/trunk@3826 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
9c36a76102
commit
16d1d0b39a
@ -23,6 +23,7 @@ enum PaintFlats {
|
||||
kPathEffect_PaintFlat,
|
||||
kRasterizer_PaintFlat,
|
||||
kShader_PaintFlat,
|
||||
kImageFilter_PaintFlat,
|
||||
kXfermode_PaintFlat,
|
||||
|
||||
kLast_PaintFlat = kXfermode_PaintFlat
|
||||
@ -39,6 +40,7 @@ enum DrawOps {
|
||||
kConcat_DrawOp,
|
||||
kDrawBitmap_DrawOp,
|
||||
kDrawBitmapMatrix_DrawOp,
|
||||
kDrawBitmapNine_DrawOp,
|
||||
kDrawBitmapRect_DrawOp,
|
||||
kDrawClear_DrawOp,
|
||||
kDrawData_DrawOp,
|
||||
@ -66,6 +68,7 @@ enum DrawOps {
|
||||
|
||||
kDef_Typeface_DrawOp,
|
||||
kDef_Flattenable_DrawOp,
|
||||
kDef_Bitmap_DrawOp,
|
||||
|
||||
// these are signals to playback, not drawing verbs
|
||||
kDone_DrawOp,
|
||||
|
@ -46,6 +46,9 @@ static void set_paintflat(SkPaint* paint, SkFlattenable* obj, unsigned paintFlat
|
||||
case kShader_PaintFlat:
|
||||
paint->setShader((SkShader*)obj);
|
||||
break;
|
||||
case kImageFilter_PaintFlat:
|
||||
paint->setImageFilter((SkImageFilter*)obj);
|
||||
break;
|
||||
case kXfermode_PaintFlat:
|
||||
paint->setXfermode((SkXfermode*)obj);
|
||||
break;
|
||||
@ -85,6 +88,19 @@ public:
|
||||
*fFlatArray.append() = obj;
|
||||
}
|
||||
|
||||
void addBitmap(int index) {
|
||||
SkASSERT(fBitmaps.count() == index);
|
||||
SkBitmap* bm = new SkBitmap();
|
||||
size_t size = fReader->readU32();
|
||||
SkOrderedReadBuffer readBuffer(fReader->skip(size), size);
|
||||
bm->unflatten(readBuffer);
|
||||
*fBitmaps.append() = bm;
|
||||
}
|
||||
|
||||
SkBitmap* getBitmap(unsigned index) {
|
||||
return fBitmaps[index];
|
||||
}
|
||||
|
||||
void addTypeface() {
|
||||
size_t size = fReader->readU32();
|
||||
const void* data = fReader->skip(SkAlign4(size));
|
||||
@ -102,6 +118,7 @@ private:
|
||||
SkTDArray<SkFlattenable*> fFlatArray;
|
||||
SkTDArray<SkTypeface*> fTypefaces;
|
||||
SkTDArray<SkFlattenable::Factory> fFactoryArray;
|
||||
SkTDArray<SkBitmap*> fBitmaps;
|
||||
};
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -329,14 +346,12 @@ static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op3
|
||||
|
||||
static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
|
||||
SkGPipeState* state) {
|
||||
uint32_t bitmapSize = reader->readU32();
|
||||
SkOrderedReadBuffer readBuffer(reader->skip(bitmapSize), bitmapSize);
|
||||
SkBitmap bm;
|
||||
bm.unflatten(readBuffer);
|
||||
unsigned index = DrawOp_unpackData(op32);
|
||||
SkBitmap* bm = state->getBitmap(index);
|
||||
bool hasPaint = reader->readBool();
|
||||
SkScalar left = reader->readScalar();
|
||||
SkScalar top = reader->readScalar();
|
||||
canvas->drawBitmap(bm, left, top, hasPaint ? &state->paint() : NULL);
|
||||
canvas->drawBitmap(*bm, left, top, hasPaint ? &state->paint() : NULL);
|
||||
}
|
||||
|
||||
static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
|
||||
@ -344,14 +359,41 @@ static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t o
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
|
||||
static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
|
||||
SkGPipeState* state) {
|
||||
UNIMPLEMENTED
|
||||
static void drawBitmapNine_rp(SkCanvas* canvas, SkReader32* reader,
|
||||
uint32_t op32, SkGPipeState* state) {
|
||||
unsigned index = DrawOp_unpackData(op32);
|
||||
SkBitmap* bm = state->getBitmap(index);
|
||||
bool hasPaint = reader->readBool();
|
||||
SkIRect center = SkIRect::MakeLTRB(reader->readInt(), reader->readInt(),
|
||||
reader->readInt(), reader->readInt());
|
||||
const SkRect* dst = skip<SkRect>(reader);
|
||||
canvas->drawBitmapNine(*bm, center, *dst,
|
||||
hasPaint ? &state->paint() : NULL);
|
||||
}
|
||||
|
||||
static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader,
|
||||
uint32_t op32, SkGPipeState* state) {
|
||||
unsigned index = DrawOp_unpackData(op32);
|
||||
SkBitmap* bm = state->getBitmap(index);
|
||||
bool hasPaint = reader->readBool();
|
||||
bool hasSrc = reader->readBool();
|
||||
SkIRect src;
|
||||
if (hasSrc) {
|
||||
src = SkIRect::MakeLTRB(reader->readInt(), reader->readInt(),
|
||||
reader->readInt(), reader->readInt());
|
||||
}
|
||||
const SkRect* dst = skip<SkRect>(reader);
|
||||
canvas->drawBitmapRect(*bm, hasSrc ? &src : NULL, *dst,
|
||||
hasPaint ? &state->paint() : NULL);
|
||||
}
|
||||
|
||||
static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
|
||||
SkGPipeState* state) {
|
||||
UNIMPLEMENTED
|
||||
unsigned index = DrawOp_unpackData(op32);
|
||||
SkBitmap* bm = state->getBitmap(index);
|
||||
bool hasPaint = reader->readBool();
|
||||
canvas->drawSprite(*bm, reader->readInt(), reader->readInt(),
|
||||
hasPaint ? &state->paint() : NULL);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -432,6 +474,12 @@ static void def_PaintFlat_rp(SkCanvas*, SkReader32*, uint32_t op32,
|
||||
state->defFlattenable(pf, index);
|
||||
}
|
||||
|
||||
static void def_Bitmap_rp(SkCanvas*, SkReader32*, uint32_t op32,
|
||||
SkGPipeState* state) {
|
||||
unsigned index = DrawOp_unpackData(op32);
|
||||
state->addBitmap(index);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void skip_rp(SkCanvas*, SkReader32* reader, uint32_t op32, SkGPipeState*) {
|
||||
@ -451,6 +499,7 @@ static const ReadProc gReadTable[] = {
|
||||
concat_rp,
|
||||
drawBitmap_rp,
|
||||
drawBitmapMatrix_rp,
|
||||
drawBitmapNine_rp,
|
||||
drawBitmapRect_rp,
|
||||
drawClear_rp,
|
||||
drawData_rp,
|
||||
@ -477,6 +526,7 @@ static const ReadProc gReadTable[] = {
|
||||
paintOp_rp,
|
||||
def_Typeface_rp,
|
||||
def_PaintFlat_rp,
|
||||
def_Bitmap_rp,
|
||||
|
||||
done_rp
|
||||
};
|
||||
@ -488,6 +538,7 @@ SkGPipeState::SkGPipeState() {}
|
||||
SkGPipeState::~SkGPipeState() {
|
||||
fTypefaces.safeUnrefAll();
|
||||
fFlatArray.safeUnrefAll();
|
||||
fBitmaps.deleteAll();
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
@ -541,7 +592,8 @@ SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length,
|
||||
if (readAtom &&
|
||||
(table[op] != paintOp_rp &&
|
||||
table[op] != def_Typeface_rp &&
|
||||
table[op] != def_PaintFlat_rp
|
||||
table[op] != def_PaintFlat_rp &&
|
||||
table[op] != def_Bitmap_rp
|
||||
)) {
|
||||
status = kReadAtom_Status;
|
||||
break;
|
||||
|
@ -14,6 +14,7 @@
|
||||
#include "SkPaint.h"
|
||||
#include "SkGPipe.h"
|
||||
#include "SkGPipePriv.h"
|
||||
#include "SkImageFilter.h"
|
||||
#include "SkStream.h"
|
||||
#include "SkTSearch.h"
|
||||
#include "SkTypeface.h"
|
||||
@ -34,6 +35,7 @@ static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
|
||||
case kPathEffect_PaintFlat: return paint.getPathEffect();
|
||||
case kRasterizer_PaintFlat: return paint.getRasterizer();
|
||||
case kShader_PaintFlat: return paint.getShader();
|
||||
case kImageFilter_PaintFlat: return paint.getImageFilter();
|
||||
case kXfermode_PaintFlat: return paint.getXfermode();
|
||||
}
|
||||
SkDEBUGFAIL("never gets here");
|
||||
@ -161,8 +163,10 @@ private:
|
||||
inline void doNotify() {
|
||||
if (!fDone) {
|
||||
size_t bytes = fWriter.size() - fBytesNotified;
|
||||
fController->notifyWritten(bytes);
|
||||
fBytesNotified += bytes;
|
||||
if (bytes > 0) {
|
||||
fController->notifyWritten(bytes);
|
||||
fBytesNotified += bytes;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -176,6 +180,10 @@ private:
|
||||
return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
|
||||
}
|
||||
};
|
||||
|
||||
SkTDArray<FlatData*> fBitmapArray;
|
||||
int flattenToIndex(const SkBitmap&);
|
||||
|
||||
SkTDArray<FlatData*> fFlatArray;
|
||||
int fCurrFlatIndex[kCount_PaintFlats];
|
||||
int flattenToIndex(SkFlattenable* obj, PaintFlats);
|
||||
@ -195,6 +203,41 @@ private:
|
||||
typedef SkCanvas INHERITED;
|
||||
};
|
||||
|
||||
int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
|
||||
SkOrderedWriteBuffer tmpWriter(1024);
|
||||
// FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
|
||||
// so that we can store a pointer to a bitmap's pixels during flattening.
|
||||
tmpWriter.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
|
||||
bitmap.flatten(tmpWriter);
|
||||
|
||||
size_t len = tmpWriter.size();
|
||||
size_t allocSize = len + sizeof(FlatData);
|
||||
|
||||
SkAutoSMalloc<1024> storage(allocSize);
|
||||
FlatData* flat = (FlatData*)storage.get();
|
||||
flat->fSize = len;
|
||||
tmpWriter.flatten(flat->data());
|
||||
|
||||
int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
|
||||
fBitmapArray.count(), flat, sizeof(flat),
|
||||
&FlatData::Compare);
|
||||
if (index < 0) {
|
||||
index = ~index;
|
||||
FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
|
||||
memcpy(copy, flat, allocSize);
|
||||
// For bitmaps, we can use zero based indices, since we will never ask
|
||||
// for a NULL bitmap (unlike with paint flattenables).
|
||||
copy->fIndex = fBitmapArray.count();
|
||||
*fBitmapArray.insert(index) = copy;
|
||||
if (this->needOpBytes(len + sizeof(uint32_t))) {
|
||||
this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
|
||||
fWriter.write32(len);
|
||||
fWriter.write(copy->data(), len);
|
||||
}
|
||||
}
|
||||
return fBitmapArray[index]->fIndex;
|
||||
}
|
||||
|
||||
// return 0 for NULL (or unflattenable obj), or index-base-1
|
||||
int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
|
||||
if (NULL == obj) {
|
||||
@ -267,6 +310,7 @@ SkGPipeCanvas::~SkGPipeCanvas() {
|
||||
this->finish();
|
||||
|
||||
fFlatArray.freeAll();
|
||||
fBitmapArray.freeAll();
|
||||
}
|
||||
|
||||
bool SkGPipeCanvas::needOpBytes(size_t needed) {
|
||||
@ -516,42 +560,84 @@ void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
|
||||
if (paint) {
|
||||
this->writePaint(*paint);
|
||||
}
|
||||
SkOrderedWriteBuffer writeBuffer(0);
|
||||
// FIXME: Rather than forcing CrossProcess, we should create an SkRefCntSet
|
||||
// so that we can store a pointer to a bitmap's pixels during flattening.
|
||||
writeBuffer.setFlags(SkFlattenableWriteBuffer::kCrossProcess_Flag);
|
||||
bm.flatten(writeBuffer);
|
||||
int size = writeBuffer.size();
|
||||
|
||||
int bitmapIndex = this->flattenToIndex(bm);
|
||||
|
||||
if (this->needOpBytes(sizeof(uint32_t) + size + sizeof(SkScalar)*2)
|
||||
+ sizeof(bool)) {
|
||||
// Record the act of drawing the bitmap
|
||||
this->writeOp(kDrawBitmap_DrawOp);
|
||||
fWriter.writeInt(size);
|
||||
void* ptr = (void*) fWriter.reserve(size);
|
||||
writeBuffer.flatten(ptr);
|
||||
if (this->needOpBytes(sizeof(SkScalar) * 2 + sizeof(bool))) {
|
||||
this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
|
||||
fWriter.writeBool(paint != NULL);
|
||||
fWriter.writeScalar(left);
|
||||
fWriter.writeScalar(top);
|
||||
}
|
||||
}
|
||||
|
||||
void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
|
||||
const SkRect& dst, const SkPaint*) {
|
||||
UNIMPLEMENTED
|
||||
void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
|
||||
const SkRect& dst, const SkPaint* paint) {
|
||||
NOTIFY_SETUP(this);
|
||||
if (paint) {
|
||||
this->writePaint(*paint);
|
||||
}
|
||||
|
||||
int bitmapIndex = this->flattenToIndex(bm);
|
||||
|
||||
size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
|
||||
bool hasSrc = src != NULL;
|
||||
if (hasSrc) {
|
||||
opBytesNeeded += sizeof(int32_t) * 4;
|
||||
}
|
||||
if (this->needOpBytes(opBytesNeeded)) {
|
||||
this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
|
||||
fWriter.writeBool(paint != NULL);
|
||||
fWriter.writeBool(hasSrc);
|
||||
if (hasSrc) {
|
||||
fWriter.write32(src->fLeft);
|
||||
fWriter.write32(src->fTop);
|
||||
fWriter.write32(src->fRight);
|
||||
fWriter.write32(src->fBottom);
|
||||
}
|
||||
fWriter.writeRect(dst);
|
||||
}
|
||||
}
|
||||
|
||||
void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
|
||||
const SkPaint*) {
|
||||
UNIMPLEMENTED
|
||||
}
|
||||
void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
|
||||
|
||||
void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
|
||||
const SkRect& dst, const SkPaint* paint) {
|
||||
UNIMPLEMENTED
|
||||
NOTIFY_SETUP(this);
|
||||
if (paint) {
|
||||
this->writePaint(*paint);
|
||||
}
|
||||
int bitmapIndex = this->flattenToIndex(bm);
|
||||
|
||||
if (this->needOpBytes(sizeof(int32_t) * 4 + sizeof(bool)
|
||||
+ sizeof(SkRect))) {
|
||||
this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
|
||||
fWriter.writeBool(paint != NULL);
|
||||
fWriter.write32(center.fLeft);
|
||||
fWriter.write32(center.fTop);
|
||||
fWriter.write32(center.fRight);
|
||||
fWriter.write32(center.fBottom);
|
||||
fWriter.writeRect(dst);
|
||||
}
|
||||
}
|
||||
void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
|
||||
const SkPaint*) {
|
||||
UNIMPLEMENTED
|
||||
|
||||
void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
|
||||
const SkPaint* paint) {
|
||||
NOTIFY_SETUP(this);
|
||||
if (paint) {
|
||||
this->writePaint(*paint);
|
||||
}
|
||||
int bitmapIndex = this->flattenToIndex(bm);
|
||||
|
||||
if (this->needOpBytes(sizeof(int32_t) * 2 + sizeof(bool))) {
|
||||
this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
|
||||
fWriter.writeBool(paint != NULL);
|
||||
fWriter.write32(left);
|
||||
fWriter.write32(top);
|
||||
}
|
||||
}
|
||||
|
||||
void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
|
||||
|
Loading…
Reference in New Issue
Block a user