add experimental canvas pipe

git-svn-id: http://skia.googlecode.com/svn/trunk@1187 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
reed@google.com 2011-04-26 17:41:56 +00:00
parent 06afe7b5a1
commit bb6992a9d6
4 changed files with 1302 additions and 0 deletions

61
include/pipe/SkGPipe.h Normal file
View File

@ -0,0 +1,61 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SkGPipe_DEFINED
#define SkGPipe_DEFINED
#include "SkWriter32.h"
class SkCanvas;
class SkGPipeReader {
public:
SkGPipeReader(SkCanvas* target);
~SkGPipeReader();
enum Status {
kDone_Status, //!< no more data expected from reader
kEOF_Status, //!< need more data from reader
kError_Status //!< encountered error
};
Status playback(const void* data, size_t length);
private:
SkCanvas* fCanvas;
class SkGPipeState* fState;
};
///////////////////////////////////////////////////////////////////////////////
class SkGPipeWriter {
public:
SkGPipeWriter();
~SkGPipeWriter();
bool isRecording() const { return NULL != fCanvas; }
SkCanvas* startRecording();
void endRecording();
size_t flatten(void* buffer);
private:
class SkGPipeCanvas* fCanvas;
SkWriter32 fWriter;
};
#endif

202
src/pipe/SkGPipePriv.h Normal file
View File

@ -0,0 +1,202 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#ifndef SkGPipePriv_DEFINED
#define SkGPipePriv_DEFINED
#include "SkTypes.h"
#define UNIMPLEMENTED
enum DrawOps {
// these match Canvas apis
kClipPath_DrawOp,
kClipRegion_DrawOp,
kClipRect_DrawOp,
kConcat_DrawOp,
kDrawBitmap_DrawOp,
kDrawBitmapMatrix_DrawOp,
kDrawBitmapRect_DrawOp,
kDrawClear_DrawOp,
kDrawData_DrawOp,
kDrawPaint_DrawOp,
kDrawPath_DrawOp,
kDrawPicture_DrawOp,
kDrawPoints_DrawOp,
kDrawPosText_DrawOp,
kDrawPosTextH_DrawOp,
kDrawRect_DrawOp,
kDrawShape_DrawOp,
kDrawSprite_DrawOp,
kDrawText_DrawOp,
kDrawTextOnPath_DrawOp,
kDrawVertices_DrawOp,
kRestore_DrawOp,
kRotate_DrawOp,
kSave_DrawOp,
kSaveLayer_DrawOp,
kScale_DrawOp,
kSetMatrix_DrawOp,
kSkew_DrawOp,
kTranslate_DrawOp,
// these edit paints
kPaintOp_DrawOp,
// these are signals to playback, not drawing verbs
kDone_DrawOp,
};
/**
* DrawOp packs into a 32bit int as follows
*
* DrawOp:8 - Flags:4 - Data:20
*
* Flags and Data are called out separately, so we can reuse Data between
* different Ops that might have different Flags. e.g. Data might be a Paint
* index for both drawRect (no flags) and saveLayer (does have flags).
*
* All Ops that take a SkPaint use their Data field to store the index to
* the paint (previously defined with kPaintOp_DrawOp).
*/
#define DRAWOPS_OP_BITS 8
#define DRAWOPS_FLAG_BITS 4
#define DRAWOPS_DATA_BITS 20
#define DRAWOPS_OP_MASK ((1 << DRAWOPS_OP_BITS) - 1)
#define DRAWOPS_FLAG_MASK ((1 << DRAWOPS_FLAG_BITS) - 1)
#define DRAWOPS_DATA_MASK ((1 << DRAWOPS_DATA_BITS) - 1)
static unsigned DrawOp_unpackOp(uint32_t op32) {
return (op32 >> (DRAWOPS_FLAG_BITS + DRAWOPS_DATA_BITS));
}
static unsigned DrawOp_unpackFlags(uint32_t op32) {
return (op32 >> DRAWOPS_DATA_BITS) & DRAWOPS_FLAG_MASK;
}
static unsigned DrawOp_unpackData(uint32_t op32) {
return op32 & DRAWOPS_DATA_MASK;
}
static uint32_t DrawOp_packOpFlagData(DrawOps op, unsigned flags, unsigned data) {
SkASSERT(0 == (op & ~DRAWOPS_OP_MASK));
SkASSERT(0 == (flags & ~DRAWOPS_FLAG_MASK));
SkASSERT(0 == (data & ~DRAWOPS_DATA_MASK));
return (op << DRAWOPS_FLAG_BITS + DRAWOPS_DATA_BITS) |
(flags << DRAWOPS_DATA_BITS) |
data;
}
/** DrawOp specific flag bits
*/
enum {
kSaveLayer_HasBounds_DrawOpFlag = 1 << 0,
kSaveLayer_HasPaint_DrawOpFlag = 1 << 1,
};
enum {
kClear_HasColor_DrawOpFlag = 1 << 0
};
enum {
kDrawTextOnPath_HasMatrix_DrawOpFlag = 1 << 0
};
enum {
kDrawVertices_HasTexs_DrawOpFlag = 1 << 0,
kDrawVertices_HasColors_DrawOpFlag = 1 << 1,
kDrawVertices_HasIndices_DrawOpFlag = 1 << 2,
};
///////////////////////////////////////////////////////////////////////////////
enum PaintOps {
kReset_PaintOp, // no arg
kFlags_PaintOp, // arg inline
kColor_PaintOp, // arg 32
kStyle_PaintOp, // arg inline
kJoin_PaintOp, // arg inline
kCap_PaintOp, // arg inline
kWidth_PaintOp, // arg scalar
kMiter_PaintOp,// arg scalar
kEncoding_PaintOp, // arg inline - text
kHinting_PaintOp, // arg inline - text
kAlign_PaintOp, // arg inline - text
kTextSize_PaintOp, // arg scalar - text
kTextScaleX_PaintOp,// arg scalar - text
kTextSkewX_PaintOp, // arg scalar - text
kPathEffect_PaintOp, // arg inline
kShader_PaintOp,
kXfermode_PaintOp,
kMaskFilter_PaintOp,
kColorFilter_PaintOp,
kRasterizer_PaintOp,
kDrawLooper_PaintOp,
};
#define PAINTOPS_OP_BITS 8
#define PAINTOPS_FLAG_BITS 4
#define PAINTOPS_DATA_BITS 20
#define PAINTOPS_OP_MASK ((1 << PAINTOPS_OP_BITS) - 1)
#define PAINTOPS_FLAG_MASK ((1 << PAINTOPS_FLAG_BITS) - 1)
#define PAINTOPS_DATA_MASK ((1 << PAINTOPS_DATA_BITS) - 1)
static unsigned PaintOp_unpackOp(uint32_t op32) {
return (op32 >> (PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS));
}
static unsigned PaintOp_unpackFlags(uint32_t op32) {
return (op32 >> PAINTOPS_DATA_BITS) & PAINTOPS_FLAG_MASK;
}
static unsigned PaintOp_unpackData(uint32_t op32) {
return op32 & PAINTOPS_DATA_MASK;
}
static uint32_t PaintOp_packOp(PaintOps op) {
SkASSERT(0 == (op & ~PAINTOPS_OP_MASK));
return (op << PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS);
}
static uint32_t PaintOp_packOpData(PaintOps op, unsigned data) {
SkASSERT(0 == (op & ~PAINTOPS_OP_MASK));
SkASSERT(0 == (data & ~PAINTOPS_DATA_MASK));
return (op << PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS) | data;
}
static uint32_t PaintOp_packOpFlagData(PaintOps op, unsigned flags, unsigned data) {
SkASSERT(0 == (op & ~PAINTOPS_OP_MASK));
SkASSERT(0 == (flags & ~PAINTOPS_FLAG_MASK));
SkASSERT(0 == (data & ~PAINTOPS_DATA_MASK));
return (op << PAINTOPS_FLAG_BITS + PAINTOPS_DATA_BITS) |
(flags << PAINTOPS_DATA_BITS) |
data;
}
enum {
kLastOp_PaintOpFlag = 1 << 0
};
#endif

500
src/pipe/SkGPipeRead.cpp Normal file
View File

@ -0,0 +1,500 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkGPipePriv.h"
#include "SkReader32.h"
class SkGPipeState {
public:
SkGPipeState();
~SkGPipeState();
const SkPaint& getPaint(uint32_t drawOp32) const;
// Extracts index from DrawOp_unpackData().
// Returns the specified paint from our list, or creates a new paint if
// index == count. If index > count, return NULL
SkPaint* editPaint(uint32_t drawOp32);
private:
SkTDArray<SkPaint*> fPaints;
};
///////////////////////////////////////////////////////////////////////////////
template <typename T> const T* skip(SkReader32* reader, int count = 1) {
SkASSERT(count >= 0);
size_t size = sizeof(T) * count;
SkASSERT(SkAlign4(size) == size);
return reinterpret_cast<const T*>(reader->skip(size));
}
template <typename T> const T* skipAlign(SkReader32* reader, int count = 1) {
SkASSERT(count >= 0);
size_t size = SkAlign4(sizeof(T) * count);
return reinterpret_cast<const T*>(reader->skip(size));
}
static void readRegion(SkReader32* reader, SkRegion* rgn) {
size_t size = rgn->unflatten(reader->peek());
SkASSERT(SkAlign4(size) == size);
(void)reader->skip(size);
}
static void readMatrix(SkReader32* reader, SkMatrix* matrix) {
size_t size = matrix->unflatten(reader->peek());
SkASSERT(SkAlign4(size) == size);
(void)reader->skip(size);
}
const SkPaint& SkGPipeState::getPaint(uint32_t op32) const {
unsigned index = DrawOp_unpackData(op32);
if (index >= fPaints.count()) {
SkASSERT(!"paint index out of range");
index = 0; // we always have at least 1 paint
}
return *fPaints[index];
}
SkPaint* SkGPipeState::editPaint(uint32_t op32) {
unsigned index = DrawOp_unpackData(op32);
if (index > fPaints.count()) {
SkASSERT(!"paint index out of range");
return NULL;
}
if (index == fPaints.count()) {
*fPaints.append() = SkNEW(SkPaint);
}
return fPaints[index];
}
///////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
static void clipPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkPath path;
path.unflatten(*reader);
canvas->clipPath(path, (SkRegion::Op)DrawOp_unpackData(op32));
}
static void clipRegion_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkRegion rgn;
readRegion(reader, &rgn);
canvas->clipRegion(rgn, (SkRegion::Op)DrawOp_unpackData(op32));
}
static void clipRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
canvas->clipRect(*skip<SkRect>(reader), (SkRegion::Op)DrawOp_unpackData(op32));
}
///////////////////////////////////////////////////////////////////////////////
static void setMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkMatrix matrix;
readMatrix(reader, &matrix);
canvas->setMatrix(matrix);
}
static void concat_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkMatrix matrix;
readMatrix(reader, &matrix);
canvas->concat(matrix);
}
static void scale_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
const SkScalar* param = skip<SkScalar>(reader, 2);
canvas->scale(param[0], param[1]);
}
static void skew_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
const SkScalar* param = skip<SkScalar>(reader, 2);
canvas->skew(param[0], param[1]);
}
static void rotate_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
canvas->rotate(reader->readScalar());
}
static void translate_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
const SkScalar* param = skip<SkScalar>(reader, 2);
canvas->translate(param[0], param[1]);
}
///////////////////////////////////////////////////////////////////////////////
static void save_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
canvas->save((SkCanvas::SaveFlags)DrawOp_unpackData(op32));
}
static void saveLayer_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
unsigned flags = DrawOp_unpackData(op32);
const SkRect* bounds = NULL;
if (flags & kSaveLayer_HasBounds_DrawOpFlag) {
bounds = skip<SkRect>(reader);
}
const SkPaint* paint = NULL;
if (flags & kSaveLayer_HasPaint_DrawOpFlag) {
paint = &state->getPaint(reader->readU32());
}
canvas->saveLayer(bounds, paint,
(SkCanvas::SaveFlags)DrawOp_unpackFlags(op32));
}
static void restore_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
canvas->restore();
}
///////////////////////////////////////////////////////////////////////////////
static void drawClear_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkColor color = 0;
if (DrawOp_unpackFlags(op32) & kClear_HasColor_DrawOpFlag) {
color = reader->readU32();
}
canvas->clear(color);
}
static void drawPaint_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
canvas->drawPaint(state->getPaint(op32));
}
static void drawPoints_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkCanvas::PointMode mode = (SkCanvas::PointMode)DrawOp_unpackFlags(op32);
size_t count = reader->readU32();
const SkPoint* pts = skip<SkPoint>(reader, count);
canvas->drawPoints(mode, count, pts, state->getPaint(op32));
}
static void drawRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
canvas->drawRect(*skip<SkRect>(reader), state->getPaint(op32));
}
static void drawPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkPath path;
path.unflatten(*reader);
canvas->drawPath(path, state->getPaint(op32));
}
static void drawVertices_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
unsigned flags = DrawOp_unpackFlags(op32);
SkCanvas::VertexMode mode = (SkCanvas::VertexMode)reader->readU32();
int vertexCount = reader->readU32();
const SkPoint* verts = skip<SkPoint>(reader, vertexCount);
const SkPoint* texs = NULL;
if (flags & kDrawVertices_HasTexs_DrawOpFlag) {
texs = skip<SkPoint>(reader, vertexCount);
}
const SkColor* colors = NULL;
if (flags & kDrawVertices_HasColors_DrawOpFlag) {
colors = skip<SkColor>(reader, vertexCount);
}
// TODO: flatten/unflatten xfermodes
SkXfermode* xfer = NULL;
int indexCount = 0;
const uint16_t* indices = NULL;
if (flags & kDrawVertices_HasIndices_DrawOpFlag) {
indexCount = reader->readU32();
indices = skipAlign<uint16_t>(reader, indexCount);
}
canvas->drawVertices(mode, vertexCount, verts, texs, colors, xfer,
indices, indexCount, state->getPaint(op32));
}
///////////////////////////////////////////////////////////////////////////////
static void drawText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
size_t len = reader->readU32();
const void* text = reader->skip(SkAlign4(len));
const SkScalar* xy = skip<SkScalar>(reader, 2);
canvas->drawText(text, len, xy[0], xy[1], state->getPaint(op32));
}
static void drawPosText_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
size_t len = reader->readU32();
const void* text = reader->skip(SkAlign4(len));
size_t posCount = reader->readU32(); // compute by our writer
const SkPoint* pos = skip<SkPoint>(reader, posCount);
canvas->drawPosText(text, len, pos, state->getPaint(op32));
}
static void drawPosTextH_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
size_t len = reader->readU32();
const void* text = reader->skip(SkAlign4(len));
size_t posCount = reader->readU32(); // compute by our writer
const SkScalar* xpos = skip<SkScalar>(reader, posCount);
SkScalar constY = reader->readScalar();
canvas->drawPosTextH(text, len, xpos, constY, state->getPaint(op32));
}
static void drawTextOnPath_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
size_t len = reader->readU32();
const void* text = reader->skip(SkAlign4(len));
SkPath path;
path.unflatten(*reader);
SkMatrix matrixStorage;
const SkMatrix* matrix = NULL;
if (DrawOp_unpackFlags(op32) & kDrawTextOnPath_HasMatrix_DrawOpFlag) {
readMatrix(reader, &matrixStorage);
matrix = &matrixStorage;
}
canvas->drawTextOnPath(text, len, path, matrix, state->getPaint(op32));
}
///////////////////////////////////////////////////////////////////////////////
static void drawBitmap_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
UNIMPLEMENTED
}
static void drawBitmapMatrix_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
UNIMPLEMENTED
}
static void drawBitmapRect_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
UNIMPLEMENTED
}
static void drawSprite_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
UNIMPLEMENTED
}
///////////////////////////////////////////////////////////////////////////////
static void drawData_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
// since we don't have a paint, we can use data for our (small) sizes
size_t size = DrawOp_unpackData(op32);
if (0 == size) {
size = reader->readU32();
}
const void* data = reader->skip(SkAlign4(size));
canvas->drawData(data, size);
}
static void drawShape_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
UNIMPLEMENTED
}
static void drawPicture_rp(SkCanvas* canvas, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
UNIMPLEMENTED
}
///////////////////////////////////////////////////////////////////////////////
static void inflate_patheffect(SkReader32* reader, SkPaint* paint) {
}
static void inflate_shader(SkReader32* reader, SkPaint* paint) {
}
static void inflate_xfermode(SkReader32* reader, SkPaint* paint) {
}
static void inflate_maskfilter(SkReader32* reader, SkPaint* paint) {
}
static void inflate_colorfilter(SkReader32* reader, SkPaint* paint) {
}
static void inflate_rasterizer(SkReader32* reader, SkPaint* paint) {
}
static void inflate_drawlooper(SkReader32* reader, SkPaint* paint) {
}
static void paintOp_rp(SkCanvas*, SkReader32* reader, uint32_t op32,
SkGPipeState* state) {
SkPaint* p = state->editPaint(op32);
int done;
do {
uint32_t p32 = reader->readU32();
unsigned op = PaintOp_unpackOp(p32);
unsigned data = PaintOp_unpackData(p32);
done = PaintOp_unpackFlags(p32) & kLastOp_PaintOpFlag;
SkDebugf(" read %08X op=%d flags=%d data=%d\n", p32, op, done, data);
switch (op) {
case kReset_PaintOp: p->reset(); break;
case kFlags_PaintOp: p->setFlags(data); break;
case kColor_PaintOp: p->setColor(reader->readU32()); break;
case kStyle_PaintOp: p->setStyle((SkPaint::Style)data); break;
case kJoin_PaintOp: p->setStrokeJoin((SkPaint::Join)data); break;
case kCap_PaintOp: p->setStrokeCap((SkPaint::Cap)data); break;
case kWidth_PaintOp: p->setStrokeWidth(reader->readScalar()); break;
case kMiter_PaintOp: p->setStrokeMiter(reader->readScalar()); break;
case kEncoding_PaintOp:
p->setTextEncoding((SkPaint::TextEncoding)data);
break;
case kHinting_PaintOp: p->setHinting((SkPaint::Hinting)data); break;
case kAlign_PaintOp: p->setTextAlign((SkPaint::Align)data); break;
case kTextSize_PaintOp: p->setTextSize(reader->readScalar()); break;
case kTextScaleX_PaintOp: p->setTextScaleX(reader->readScalar()); break;
case kTextSkewX_PaintOp: p->setTextSkewX(reader->readScalar()); break;
// flag to reference a cached index instead of inflating?
case kPathEffect_PaintOp: inflate_patheffect(reader, p); break;
case kShader_PaintOp: inflate_shader(reader, p); break;
case kXfermode_PaintOp: inflate_xfermode(reader, p); break;
case kMaskFilter_PaintOp: inflate_maskfilter(reader, p); break;
case kColorFilter_PaintOp: inflate_colorfilter(reader, p); break;
case kRasterizer_PaintOp: inflate_rasterizer(reader, p); break;
case kDrawLooper_PaintOp: inflate_drawlooper(reader, p); break;
default: SkASSERT(!"bad paintop"); return;
}
} while (!done);
}
///////////////////////////////////////////////////////////////////////////////
static void done_rp(SkCanvas*, SkReader32*, uint32_t, SkGPipeState*) {}
typedef void (*ReadProc)(SkCanvas*, SkReader32*, uint32_t op32, SkGPipeState*);
static const ReadProc gReadTable[] = {
clipPath_rp,
clipRegion_rp,
clipRect_rp,
concat_rp,
drawBitmap_rp,
drawBitmapMatrix_rp,
drawBitmapRect_rp,
drawClear_rp,
drawData_rp,
drawPaint_rp,
drawPath_rp,
drawPicture_rp,
drawPoints_rp,
drawPosText_rp,
drawPosTextH_rp,
drawRect_rp,
drawShape_rp,
drawSprite_rp,
drawText_rp,
drawTextOnPath_rp,
drawVertices_rp,
restore_rp,
rotate_rp,
save_rp,
saveLayer_rp,
scale_rp,
setMatrix_rp,
skew_rp,
translate_rp,
paintOp_rp,
done_rp
};
///////////////////////////////////////////////////////////////////////////////
SkGPipeState::SkGPipeState() {
// start out with one paint in default state
*fPaints.append() = SkNEW(SkPaint);
}
SkGPipeState::~SkGPipeState() {
fPaints.deleteAll();
}
///////////////////////////////////////////////////////////////////////////////
#include "SkGPipe.h"
SkGPipeReader::SkGPipeReader(SkCanvas* target) {
SkSafeRef(target);
fCanvas = target;
fState = NULL;
}
SkGPipeReader::~SkGPipeReader() {
SkSafeUnref(fCanvas);
delete fState;
}
SkGPipeReader::Status SkGPipeReader::playback(const void* data, size_t length) {
if (NULL == fCanvas) {
return kError_Status;
}
if (NULL == fState) {
fState = new SkGPipeState;
}
const ReadProc* table = gReadTable;
SkReader32 reader(data, length);
SkCanvas* canvas = fCanvas;
while (!reader.eof()) {
uint32_t op32 = reader.readU32();
unsigned op = DrawOp_unpackOp(op32);
if (op >= SK_ARRAY_COUNT(gReadTable)) {
SkDebugf("---- bad op during GPipeState::playback\n");
return kError_Status;
}
if (kDone_DrawOp == op) {
return kDone_Status;
}
table[op](canvas, &reader, op32, fState);
}
return kEOF_Status;
}

539
src/pipe/SkGPipeWrite.cpp Normal file
View File

@ -0,0 +1,539 @@
/*
Copyright 2011 Google Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
#include "SkCanvas.h"
#include "SkPaint.h"
#include "SkGPipePriv.h"
#include "SkGPipeState.h"
#include "SkWriter32.h"
static void writeRegion(SkWriter32* writer, const SkRegion& rgn) {
size_t size = rgn.flatten(NULL);
SkASSERT(SkAlign4(size) == size);
rgn.flatten(writer->reserve(size));
}
static void writeMatrix(SkWriter32* writer, const SkMatrix& matrix) {
size_t size = matrix.flatten(NULL);
SkASSERT(SkAlign4(size) == size);
matrix.flatten(writer->reserve(size));
}
///////////////////////////////////////////////////////////////////////////////
class SkGPipeCanvas : public SkCanvas {
public:
SkGPipeCanvas(SkWriter32* writer);
virtual ~SkGPipeCanvas();
void finish() {
if (!fDone) {
this->writeOp(kDone_DrawOp);
fDone = true;
}
}
// overrides from SkCanvas
virtual int save(SaveFlags);
virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
virtual void restore();
virtual bool translate(SkScalar dx, SkScalar dy);
virtual bool scale(SkScalar sx, SkScalar sy);
virtual bool rotate(SkScalar degrees);
virtual bool skew(SkScalar sx, SkScalar sy);
virtual bool concat(const SkMatrix& matrix);
virtual void setMatrix(const SkMatrix& matrix);
virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
virtual bool clipPath(const SkPath& path, SkRegion::Op op);
virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
virtual void clear(SkColor);
virtual void drawPaint(const SkPaint& paint);
virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
const SkPaint&);
virtual void drawRect(const SkRect& rect, const SkPaint&);
virtual void drawPath(const SkPath& path, const SkPaint&);
virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
const SkPaint*);
virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
const SkRect& dst, const SkPaint*);
virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
const SkPaint*);
virtual void drawSprite(const SkBitmap&, int left, int top,
const SkPaint*);
virtual void drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint&);
virtual void drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint&);
virtual void drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY, const SkPaint&);
virtual void drawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint&);
virtual void drawPicture(SkPicture& picture);
virtual void drawShape(SkShape*);
virtual void drawVertices(VertexMode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode*,
const uint16_t indices[], int indexCount,
const SkPaint&);
virtual void drawData(const void*, size_t);
private:
SkWriter32& fWriter;
bool fDone;
void writeOp(DrawOps op, unsigned flags, unsigned data) {
fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
}
void writeOp(DrawOps op) {
fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
}
SkTDArray<SkPaint*> fPaints;
unsigned writePaint(const SkPaint&);
typedef SkCanvas INHERITED;
};
///////////////////////////////////////////////////////////////////////////////
SkGPipeCanvas::SkGPipeCanvas(SkWriter32* writer) : fWriter(*writer) {
fDone = false;
// always begin with 1 default paint
*fPaints.append() = SkNEW(SkPaint);
}
SkGPipeCanvas::~SkGPipeCanvas() {
this->finish();
fPaints.deleteAll();
}
///////////////////////////////////////////////////////////////////////////////
int SkGPipeCanvas::save(SaveFlags flags) {
this->writeOp(kSave_DrawOp, 0, flags);
return this->INHERITED::save(flags);
}
int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
SaveFlags saveFlags) {
unsigned index = 0; // just to avoid the warning
unsigned opFlags = 0;
if (bounds) {
opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
}
if (paint) {
opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
index = this->writePaint(*paint);
}
this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
if (bounds) {
fWriter.writeRect(*bounds);
}
if (paint) {
fWriter.write32(index);
}
// we just pass on the save, so we don't create a layer
return this->INHERITED::save(saveFlags);
}
void SkGPipeCanvas::restore() {
this->writeOp(kRestore_DrawOp);
this->INHERITED::restore();
}
bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
if (dx || dy) {
this->writeOp(kTranslate_DrawOp);
fWriter.writeScalar(dx);
fWriter.writeScalar(dy);
}
return this->INHERITED::translate(dx, dy);
}
bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
if (sx || sy) {
this->writeOp(kScale_DrawOp);
fWriter.writeScalar(sx);
fWriter.writeScalar(sy);
}
return this->INHERITED::scale(sx, sy);
}
bool SkGPipeCanvas::rotate(SkScalar degrees) {
if (degrees) {
this->writeOp(kRotate_DrawOp);
fWriter.writeScalar(degrees);
}
return this->INHERITED::rotate(degrees);
}
bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
if (sx || sy) {
this->writeOp(kSkew_DrawOp);
fWriter.writeScalar(sx);
fWriter.writeScalar(sy);
}
return this->INHERITED::skew(sx, sy);
}
bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
if (!matrix.isIdentity()) {
this->writeOp(kConcat_DrawOp);
writeMatrix(&fWriter, matrix);
}
return this->INHERITED::concat(matrix);
}
void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
this->writeOp(kSetMatrix_DrawOp);
writeMatrix(&fWriter, matrix);
this->INHERITED::setMatrix(matrix);
}
bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
this->writeOp(kClipRect_DrawOp, 0, rgnOp);
fWriter.writeRect(rect);
return this->INHERITED::clipRect(rect, rgnOp);
}
bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
this->writeOp(kClipPath_DrawOp, 0, rgnOp);
path.flatten(fWriter);
// we just pass on the bounds of the path
return this->INHERITED::clipRect(path.getBounds(), rgnOp);
}
bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
writeRegion(&fWriter, region);
return this->INHERITED::clipRegion(region, rgnOp);
}
///////////////////////////////////////////////////////////////////////////////
void SkGPipeCanvas::clear(SkColor color) {
unsigned flags = 0;
if (color) {
flags |= kClear_HasColor_DrawOpFlag;
}
this->writeOp(kDrawClear_DrawOp, flags, 0);
if (color) {
fWriter.write32(color);
}
}
void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawPaint_DrawOp, 0, paintIndex);
}
void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
const SkPoint pts[], const SkPaint& paint) {
if (count) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawPoints_DrawOp, mode, paintIndex);
fWriter.write32(count);
fWriter.write(pts, count * sizeof(SkPoint));
}
}
void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawRect_DrawOp, 0, paintIndex);
fWriter.writeRect(rect);
}
void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawPath_DrawOp, 0, paintIndex);
path.flatten(fWriter);
}
void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
const SkPaint*) {
UNIMPLEMENTED
}
void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
const SkRect& dst, const SkPaint*) {
UNIMPLEMENTED
}
void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
const SkPaint*) {
UNIMPLEMENTED
}
void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
const SkPaint*) {
UNIMPLEMENTED
}
void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
SkScalar y, const SkPaint& paint) {
if (byteLength) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawText_DrawOp, 0, paintIndex);
fWriter.write32(byteLength);
fWriter.writePad(text, byteLength);
fWriter.writeScalar(x);
fWriter.writeScalar(y);
}
}
void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
const SkPoint pos[], const SkPaint& paint) {
if (byteLength) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawPosText_DrawOp, 0, paintIndex);
fWriter.write32(byteLength);
fWriter.writePad(text, byteLength);
int count = paint.textToGlyphs(text, byteLength, NULL);
fWriter.write32(count);
fWriter.write(pos, count * sizeof(SkPoint));
}
}
void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
const SkScalar xpos[], SkScalar constY,
const SkPaint& paint) {
if (byteLength) {
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawPosTextH_DrawOp, 0, paintIndex);
fWriter.write32(byteLength);
fWriter.writePad(text, byteLength);
int count = paint.textToGlyphs(text, byteLength, NULL);
fWriter.write32(count);
fWriter.write(xpos, count * sizeof(SkScalar));
fWriter.writeScalar(constY);
}
}
void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
const SkPath& path, const SkMatrix* matrix,
const SkPaint& paint) {
if (byteLength) {
unsigned flags = 0;
if (matrix) {
flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
}
unsigned paintIndex = this->writePaint(paint);
this->writeOp(kDrawTextOnPath_DrawOp, flags, paintIndex);
fWriter.write32(byteLength);
fWriter.writePad(text, byteLength);
path.flatten(fWriter);
if (matrix) {
writeMatrix(&fWriter, *matrix);
}
}
}
void SkGPipeCanvas::drawPicture(SkPicture& picture) {
UNIMPLEMENTED
}
void SkGPipeCanvas::drawShape(SkShape* shape) {
UNIMPLEMENTED
}
void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
const SkPoint vertices[], const SkPoint texs[],
const SkColor colors[], SkXfermode*,
const uint16_t indices[], int indexCount,
const SkPaint& paint) {
if (0 == vertexCount) {
return;
}
unsigned paintIndex = this->writePaint(paint);
unsigned flags = 0;
if (texs) {
flags |= kDrawVertices_HasTexs_DrawOpFlag;
}
if (colors) {
flags |= kDrawVertices_HasColors_DrawOpFlag;
}
if (indices && indexCount > 0) {
flags |= kDrawVertices_HasIndices_DrawOpFlag;
}
this->writeOp(kDrawVertices_DrawOp, flags, paintIndex);
fWriter.write32(mode);
fWriter.write32(vertexCount);
fWriter.write(vertices, vertexCount * sizeof(SkPoint));
if (texs) {
fWriter.write(texs, vertexCount * sizeof(SkPoint));
}
if (colors) {
fWriter.write(colors, vertexCount * sizeof(SkColor));
}
// TODO: flatten xfermode
if (indices && indexCount > 0) {
fWriter.write32(indexCount);
fWriter.writePad(indices, indexCount * sizeof(uint16_t));
}
}
void SkGPipeCanvas::drawData(const void* data, size_t size) {
if (size) {
unsigned data = 0;
if (size < (1 << DRAWOPS_DATA_BITS)) {
data = (unsigned)size;
}
this->writeOp(kDrawData_DrawOp, 0, data);
if (0 == data) {
fWriter.write32(size);
}
}
}
///////////////////////////////////////////////////////////////////////////////
template <typename T> uint32_t castToU32(T value) {
union {
T fSrc;
uint32_t fDst;
} data;
data.fSrc = value;
return data.fDst;
}
unsigned SkGPipeCanvas::writePaint(const SkPaint& paint) {
const SkPaint& base = *fPaints[0];
uint32_t storage[32];
uint32_t* ptr = storage;
uint32_t* last = NULL;
if (base.getFlags() != paint.getFlags()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
}
if (base.getColor() != paint.getColor()) {
last = ptr;
*ptr++ = PaintOp_packOp(kColor_PaintOp);
*ptr++ = paint.getColor();
}
if (base.getStyle() != paint.getStyle()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
}
if (base.getStrokeJoin() != paint.getStrokeJoin()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
}
if (base.getStrokeCap() != paint.getStrokeCap()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
}
if (base.getStrokeWidth() != paint.getStrokeWidth()) {
last = ptr;
*ptr++ = PaintOp_packOp(kWidth_PaintOp);
*ptr++ = castToU32(paint.getStrokeWidth());
}
if (base.getStrokeMiter() != paint.getStrokeMiter()) {
last = ptr;
*ptr++ = PaintOp_packOp(kMiter_PaintOp);
*ptr++ = castToU32(paint.getStrokeMiter());
}
if (base.getTextEncoding() != paint.getTextEncoding()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
}
if (base.getHinting() != paint.getHinting()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
}
if (base.getTextAlign() != paint.getTextAlign()) {
last = ptr;
*ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
}
if (base.getTextSize() != paint.getTextSize()) {
last = ptr;
*ptr++ = PaintOp_packOp(kTextSize_PaintOp);
*ptr++ = castToU32(paint.getTextSize());
}
if (base.getTextScaleX() != paint.getTextScaleX()) {
last = ptr;
*ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
*ptr++ = castToU32(paint.getTextScaleX());
}
if (base.getTextSkewX() != paint.getTextSkewX()) {
last = ptr;
*ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
*ptr++ = castToU32(paint.getTextSkewX());
}
*fPaints[0] = paint;
if (ptr > storage) {
this->writeOp(kPaintOp_DrawOp, 0, 0);
size_t size = (char*)ptr - (char*)storage;
*last |= kLastOp_PaintOpFlag << PAINTOPS_DATA_BITS;
fWriter.write(storage, (char*)ptr - (char*)storage);
for (size_t i = 0; i < size/4; i++) {
SkDebugf("[%d] %08X\n", i, storage[i]);
}
}
return 0;
}
///////////////////////////////////////////////////////////////////////////////
#include "SkGPipe.h"
#define MIN_WRITE_BLOCK_SIZE (4 * 1024)
SkGPipeWriter::SkGPipeWriter() : fWriter(MIN_WRITE_BLOCK_SIZE) {
fCanvas = NULL;
}
SkGPipeWriter::~SkGPipeWriter() {
SkSafeUnref(fCanvas);
}
SkCanvas* SkGPipeWriter::startRecording() {
if (NULL == fCanvas) {
fCanvas = SkNEW_ARGS(SkGPipeCanvas, (&fWriter));
}
return fCanvas;
}
void SkGPipeWriter::endRecording() {
if (fCanvas) {
fCanvas->finish();
fCanvas->unref();
fCanvas = NULL;
}
}
size_t SkGPipeWriter::flatten(void* buffer) {
if (buffer) {
fWriter.flatten(buffer);
}
return fWriter.size();
}