blob: 15adea8935805d887abe53dd1b43d51d43e8663f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@google.combb6992a2011-04-26 17:41:56 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@google.combb6992a2011-04-26 17:41:56 +00007 */
8
9
epoger@google.comec3ed6a2011-07-28 14:26:00 +000010
reed@google.combb6992a2011-04-26 17:41:56 +000011#include "SkCanvas.h"
reed@google.com8a85d0c2011-06-24 19:12:12 +000012#include "SkData.h"
reed@google.combb6793b2011-05-05 15:18:15 +000013#include "SkDevice.h"
reed@google.combb6992a2011-04-26 17:41:56 +000014#include "SkPaint.h"
reed@google.com75a09722012-05-10 12:56:16 +000015#include "SkPathEffect.h"
reed@google.comacd471f2011-05-03 21:26:46 +000016#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000017#include "SkGPipePriv.h"
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000018#include "SkImageFilter.h"
reed@google.comf5842f72011-05-04 18:30:04 +000019#include "SkStream.h"
reed@google.comb55d1182011-05-11 00:42:04 +000020#include "SkTSearch.h"
reed@google.comf5842f72011-05-04 18:30:04 +000021#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000022#include "SkWriter32.h"
reed@google.comb55d1182011-05-11 00:42:04 +000023#include "SkColorFilter.h"
reed@google.com0faac1e2011-05-11 05:58:58 +000024#include "SkDrawLooper.h"
reed@google.comb55d1182011-05-11 00:42:04 +000025#include "SkMaskFilter.h"
26#include "SkRasterizer.h"
27#include "SkShader.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000028#include "SkOrderedWriteBuffer.h"
reed@google.comb55d1182011-05-11 00:42:04 +000029
30static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
31 SkASSERT(paintFlat < kCount_PaintFlats);
32 switch (paintFlat) {
33 case kColorFilter_PaintFlat: return paint.getColorFilter();
reed@google.com0faac1e2011-05-11 05:58:58 +000034 case kDrawLooper_PaintFlat: return paint.getLooper();
reed@google.comb55d1182011-05-11 00:42:04 +000035 case kMaskFilter_PaintFlat: return paint.getMaskFilter();
36 case kPathEffect_PaintFlat: return paint.getPathEffect();
37 case kRasterizer_PaintFlat: return paint.getRasterizer();
38 case kShader_PaintFlat: return paint.getShader();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +000039 case kImageFilter_PaintFlat: return paint.getImageFilter();
reed@google.comb55d1182011-05-11 00:42:04 +000040 case kXfermode_PaintFlat: return paint.getXfermode();
41 }
tomhudson@google.com0c00f212011-12-28 14:59:50 +000042 SkDEBUGFAIL("never gets here");
reed@google.comb55d1182011-05-11 00:42:04 +000043 return NULL;
44}
reed@google.combb6992a2011-04-26 17:41:56 +000045
reed@google.comf5842f72011-05-04 18:30:04 +000046static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
47 SkASSERT(typeface);
48 SkDynamicMemoryWStream stream;
49 typeface->serialize(&stream);
50 size_t size = stream.getOffset();
51 if (writer) {
52 writer->write32(size);
reed@google.com8a85d0c2011-06-24 19:12:12 +000053 SkAutoDataUnref data(stream.copyToData());
scroggo@google.com5af9b202012-06-04 17:17:36 +000054 writer->writePad(data.data(), size);
reed@google.comf5842f72011-05-04 18:30:04 +000055 }
scroggo@google.com5af9b202012-06-04 17:17:36 +000056 return 4 + SkAlign4(size);
reed@google.comf5842f72011-05-04 18:30:04 +000057}
58
reed@google.combb6992a2011-04-26 17:41:56 +000059///////////////////////////////////////////////////////////////////////////////
60
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000061/*
62 * Shared heap for storing large things that can be shared, for a stream
63 * used by multiple readers.
64 * TODO: Make the allocations all come from cross process safe address space
65 * TODO: Store paths (others?)
66 * TODO: Allow reclaiming of memory. Will require us to know when all readers
67 * have used the object.
68 */
69class Heap {
70public:
scroggo@google.com565254b2012-06-28 15:41:32 +000071 Heap(bool shallow) : fCanDoShallowCopies(shallow) {}
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +000072 ~Heap() {
73 for (int i = 0; i < fBitmaps.count(); i++) {
74 delete fBitmaps[i].fBitmap;
75 }
76 }
77
78 /*
79 * Add a copy of a bitmap to the heap.
80 * @param bm The SkBitmap to be copied and placed in the heap.
81 * @return void* Pointer to the heap's copy of the bitmap. If NULL,
82 * the bitmap could not be copied.
83 */
84 const SkBitmap* addBitmap(const SkBitmap& bm) {
85 const uint32_t genID = bm.getGenerationID();
86 for (int i = fBitmaps.count() - 1; i >= 0; i--) {
87 if (genID == fBitmaps[i].fGenID) {
88 return fBitmaps[i].fBitmap;
89 }
90 }
scroggo@google.com565254b2012-06-28 15:41:32 +000091 SkBitmap* copy;
92 // If the bitmap is mutable, we still need to do a deep copy, since the
93 // caller may modify it afterwards. That said, if the bitmap is mutable,
94 // but has no pixelRef, the copy constructor actually does a deep copy.
95 if (fCanDoShallowCopies && (bm.isImmutable() || !bm.pixelRef())) {
96 copy = new SkBitmap(bm);
97 } else {
98 copy = new SkBitmap();
99 if (!bm.copyTo(copy, bm.getConfig())) {
100 delete copy;
101 return NULL;
102 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000103 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000104 BitmapInfo* info = fBitmaps.append();
105 info->fBitmap = copy;
106 info->fGenID = genID;
107 return copy;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000108 }
109private:
110 struct BitmapInfo {
111 SkBitmap* fBitmap;
112 // Store the generation ID of the original bitmap, since copying does
113 // not copy this field, so fBitmap's generation ID will not be useful
114 // for comparing.
115 uint32_t fGenID;
116 };
scroggo@google.com565254b2012-06-28 15:41:32 +0000117 SkTDArray<BitmapInfo> fBitmaps;
118 const bool fCanDoShallowCopies;
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000119};
120
121///////////////////////////////////////////////////////////////////////////////
122
reed@google.combb6992a2011-04-26 17:41:56 +0000123class SkGPipeCanvas : public SkCanvas {
124public:
scroggo@google.com565254b2012-06-28 15:41:32 +0000125 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*, uint32_t flags);
reed@google.combb6992a2011-04-26 17:41:56 +0000126 virtual ~SkGPipeCanvas();
127
128 void finish() {
129 if (!fDone) {
reed@google.comdbccc882011-07-08 18:53:39 +0000130 if (this->needOpBytes()) {
131 this->writeOp(kDone_DrawOp);
132 this->doNotify();
133 }
reed@google.combb6992a2011-04-26 17:41:56 +0000134 fDone = true;
135 }
136 }
137
138 // overrides from SkCanvas
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000139 virtual int save(SaveFlags) SK_OVERRIDE;
140 virtual int saveLayer(const SkRect* bounds, const SkPaint*,
141 SaveFlags) SK_OVERRIDE;
142 virtual void restore() SK_OVERRIDE;
143 virtual bool translate(SkScalar dx, SkScalar dy) SK_OVERRIDE;
144 virtual bool scale(SkScalar sx, SkScalar sy) SK_OVERRIDE;
145 virtual bool rotate(SkScalar degrees) SK_OVERRIDE;
146 virtual bool skew(SkScalar sx, SkScalar sy) SK_OVERRIDE;
147 virtual bool concat(const SkMatrix& matrix) SK_OVERRIDE;
148 virtual void setMatrix(const SkMatrix& matrix) SK_OVERRIDE;
149 virtual bool clipRect(const SkRect& rect, SkRegion::Op op,
150 bool doAntiAlias = false) SK_OVERRIDE;
151 virtual bool clipPath(const SkPath& path, SkRegion::Op op,
152 bool doAntiAlias = false) SK_OVERRIDE;
153 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op) SK_OVERRIDE;
154 virtual void clear(SkColor) SK_OVERRIDE;
155 virtual void drawPaint(const SkPaint& paint) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000156 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000157 const SkPaint&) SK_OVERRIDE;
158 virtual void drawRect(const SkRect& rect, const SkPaint&) SK_OVERRIDE;
159 virtual void drawPath(const SkPath& path, const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000160 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000161 const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000162 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000163 const SkRect& dst, const SkPaint*) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000164 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000165 const SkPaint*) SK_OVERRIDE;
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000166 virtual void drawBitmapNine(const SkBitmap& bitmap, const SkIRect& center,
167 const SkRect& dst, const SkPaint* paint = NULL) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000168 virtual void drawSprite(const SkBitmap&, int left, int top,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000169 const SkPaint*) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000170 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000171 SkScalar y, const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000172 virtual void drawPosText(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000173 const SkPoint pos[], const SkPaint&) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000174 virtual void drawPosTextH(const void* text, size_t byteLength,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000175 const SkScalar xpos[], SkScalar constY,
176 const SkPaint&) SK_OVERRIDE;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000177 virtual void drawTextOnPath(const void* text, size_t byteLength,
178 const SkPath& path, const SkMatrix* matrix,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000179 const SkPaint&) SK_OVERRIDE;
180 virtual void drawPicture(SkPicture& picture) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000181 virtual void drawVertices(VertexMode, int vertexCount,
182 const SkPoint vertices[], const SkPoint texs[],
183 const SkColor colors[], SkXfermode*,
184 const uint16_t indices[], int indexCount,
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000185 const SkPaint&) SK_OVERRIDE;
186 virtual void drawData(const void*, size_t) SK_OVERRIDE;
reed@google.combb6992a2011-04-26 17:41:56 +0000187
188private:
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000189 Heap fHeap;
reed@google.comdde09562011-05-23 12:21:05 +0000190 SkFactorySet* fFactorySet; // optional, only used if cross-process
reed@google.comacd471f2011-05-03 21:26:46 +0000191 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000192 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000193 size_t fBlockSize; // amount allocated for writer
194 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000195 bool fDone;
scroggo@google.com565254b2012-06-28 15:41:32 +0000196 uint32_t fFlags;
reed@google.combb6992a2011-04-26 17:41:56 +0000197
reed@google.comf5842f72011-05-04 18:30:04 +0000198 SkRefCntSet fTypefaceSet;
199
200 uint32_t getTypefaceID(SkTypeface*);
201
reed@google.comacd471f2011-05-03 21:26:46 +0000202 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000203 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
204 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000205
reed@google.comacd471f2011-05-03 21:26:46 +0000206 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000207 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
208 }
reed@google.comacd471f2011-05-03 21:26:46 +0000209
210 bool needOpBytes(size_t size = 0);
211
212 inline void doNotify() {
213 if (!fDone) {
214 size_t bytes = fWriter.size() - fBytesNotified;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000215 if (bytes > 0) {
216 fController->notifyWritten(bytes);
217 fBytesNotified += bytes;
218 }
reed@google.comacd471f2011-05-03 21:26:46 +0000219 }
220 }
reed@google.comb55d1182011-05-11 00:42:04 +0000221
222 struct FlatData {
223 uint32_t fIndex; // always > 0
224 uint32_t fSize;
225
226 void* data() { return (char*)this + sizeof(*this); }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000227
reed@google.comb55d1182011-05-11 00:42:04 +0000228 static int Compare(const FlatData* a, const FlatData* b) {
229 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
230 }
231 };
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000232
233 SkTDArray<FlatData*> fBitmapArray;
234 int flattenToIndex(const SkBitmap&);
235
reed@google.comb55d1182011-05-11 00:42:04 +0000236 SkTDArray<FlatData*> fFlatArray;
237 int fCurrFlatIndex[kCount_PaintFlats];
238 int flattenToIndex(SkFlattenable* obj, PaintFlats);
239
reed@google.com31891582011-05-12 03:03:56 +0000240 SkPaint fPaint;
241 void writePaint(const SkPaint&);
reed@google.combb6992a2011-04-26 17:41:56 +0000242
reed@google.comacd471f2011-05-03 21:26:46 +0000243 class AutoPipeNotify {
244 public:
245 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
246 ~AutoPipeNotify() { fCanvas->doNotify(); }
247 private:
248 SkGPipeCanvas* fCanvas;
249 };
250 friend class AutoPipeNotify;
251
reed@google.combb6992a2011-04-26 17:41:56 +0000252 typedef SkCanvas INHERITED;
253};
254
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000255int SkGPipeCanvas::flattenToIndex(const SkBitmap & bitmap) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000256 SkASSERT(shouldFlattenBitmaps(fFlags));
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000257 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com565254b2012-06-28 15:41:32 +0000258 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
259 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
260 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
261 tmpWriter.setFactoryRecorder(fFactorySet);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000262 bitmap.flatten(tmpWriter);
263
264 size_t len = tmpWriter.size();
265 size_t allocSize = len + sizeof(FlatData);
266
267 SkAutoSMalloc<1024> storage(allocSize);
268 FlatData* flat = (FlatData*)storage.get();
269 flat->fSize = len;
270 tmpWriter.flatten(flat->data());
271
272 int index = SkTSearch<FlatData>((const FlatData**)fBitmapArray.begin(),
273 fBitmapArray.count(), flat, sizeof(flat),
274 &FlatData::Compare);
275 if (index < 0) {
276 index = ~index;
277 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
278 memcpy(copy, flat, allocSize);
279 // For bitmaps, we can use zero based indices, since we will never ask
280 // for a NULL bitmap (unlike with paint flattenables).
281 copy->fIndex = fBitmapArray.count();
282 *fBitmapArray.insert(index) = copy;
scroggo@google.com565254b2012-06-28 15:41:32 +0000283 if (this->needOpBytes(len)) {
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000284 this->writeOp(kDef_Bitmap_DrawOp, 0, copy->fIndex);
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000285 fWriter.write(copy->data(), len);
286 }
287 }
288 return fBitmapArray[index]->fIndex;
289}
290
reed@google.comb55d1182011-05-11 00:42:04 +0000291// return 0 for NULL (or unflattenable obj), or index-base-1
292int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
293 if (NULL == obj) {
294 return 0;
295 }
reed@google.comb55d1182011-05-11 00:42:04 +0000296
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000297 SkOrderedWriteBuffer tmpWriter(1024);
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000298
scroggo@google.com565254b2012-06-28 15:41:32 +0000299 if (fFlags & SkGPipeWriter::kCrossProcess_Flag) {
300 tmpWriter.setFlags((SkFlattenableWriteBuffer::Flags)
301 (SkFlattenableWriteBuffer::kInlineFactoryNames_Flag
302 | SkFlattenableWriteBuffer::kCrossProcess_Flag));
303 tmpWriter.setFactoryRecorder(fFactorySet);
304 } else {
305 // Needed for bitmap shaders.
306 tmpWriter.setFlags(SkFlattenableWriteBuffer::kForceFlattenBitmapPixels_Flag);
307 }
reed@google.comdde09562011-05-23 12:21:05 +0000308
reed@google.comb55d1182011-05-11 00:42:04 +0000309 tmpWriter.writeFlattenable(obj);
310 size_t len = tmpWriter.size();
311 size_t allocSize = len + sizeof(FlatData);
312
313 SkAutoSMalloc<1024> storage(allocSize);
314 FlatData* flat = (FlatData*)storage.get();
315 flat->fSize = len;
316 tmpWriter.flatten(flat->data());
317
318 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(),
319 fFlatArray.count(), flat, sizeof(flat),
320 &FlatData::Compare);
321 if (index < 0) {
322 index = ~index;
323 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
324 memcpy(copy, flat, allocSize);
325 *fFlatArray.insert(index) = copy;
326 // call this after the insert, so that count() will have been grown
327 copy->fIndex = fFlatArray.count();
328// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex);
329
330 if (this->needOpBytes(len)) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000331 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
reed@google.comb55d1182011-05-11 00:42:04 +0000332 fWriter.write(copy->data(), len);
333 }
334 }
335 return fFlatArray[index]->fIndex;
336}
337
reed@google.combb6992a2011-04-26 17:41:56 +0000338///////////////////////////////////////////////////////////////////////////////
339
reed@google.comacd471f2011-05-03 21:26:46 +0000340#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000341
reed@google.comacd471f2011-05-03 21:26:46 +0000342SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
scroggo@google.com565254b2012-06-28 15:41:32 +0000343 SkWriter32* writer, SkFactorySet* fset, uint32_t flags)
344: fWriter(*writer), fFlags(flags), fHeap(!(flags & SkGPipeWriter::kCrossProcess_Flag)) {
reed@google.com67908f22011-06-27 14:47:50 +0000345 fFactorySet = fset;
reed@google.comacd471f2011-05-03 21:26:46 +0000346 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000347 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000348 fBlockSize = 0; // need first block from controller
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000349 fBytesNotified = 0;
reed@google.comb55d1182011-05-11 00:42:04 +0000350 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
reed@google.comacd471f2011-05-03 21:26:46 +0000351
reed@google.combb6793b2011-05-05 15:18:15 +0000352 // we need a device to limit our clip
353 // should the caller give us the bounds?
yangsu@google.com06b4da162011-06-17 15:04:40 +0000354 // We don't allocate pixels for the bitmap
reed@google.combb6793b2011-05-05 15:18:15 +0000355 SkBitmap bitmap;
356 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
yangsu@google.com06b4da162011-06-17 15:04:40 +0000357 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
reed@google.combb6793b2011-05-05 15:18:15 +0000358 this->setDevice(device)->unref();
scroggo@google.com565254b2012-06-28 15:41:32 +0000359 // Tell the reader the appropriate flags to use.
360 if (this->needOpBytes()) {
361 this->writeOp(kReportFlags_DrawOp, fFlags, 0);
362 }
reed@google.combb6992a2011-04-26 17:41:56 +0000363}
364
365SkGPipeCanvas::~SkGPipeCanvas() {
366 this->finish();
367
reed@google.comb55d1182011-05-11 00:42:04 +0000368 fFlatArray.freeAll();
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000369 fBitmapArray.freeAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000370}
371
reed@google.comacd471f2011-05-03 21:26:46 +0000372bool SkGPipeCanvas::needOpBytes(size_t needed) {
373 if (fDone) {
374 return false;
375 }
376
377 needed += 4; // size of DrawOp atom
378 if (fWriter.size() + needed > fBlockSize) {
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000379 // Before we wipe out any data that has already been written, read it
380 // out.
381 this->doNotify();
382 size_t blockSize = SkMax32(MIN_BLOCK_SIZE, needed);
383 void* block = fController->requestBlock(blockSize, &fBlockSize);
reed@google.comacd471f2011-05-03 21:26:46 +0000384 if (NULL == block) {
385 fDone = true;
386 return false;
387 }
388 fWriter.reset(block, fBlockSize);
389 fBytesNotified = 0;
390 }
391 return true;
392}
393
reed@google.comf5842f72011-05-04 18:30:04 +0000394uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
395 uint32_t id = 0; // 0 means default/null typeface
396 if (face) {
397 id = fTypefaceSet.find(face);
398 if (0 == id) {
399 id = fTypefaceSet.add(face);
400 size_t size = writeTypeface(NULL, face);
401 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000402 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000403 writeTypeface(&fWriter, face);
404 }
405 }
406 }
407 return id;
408}
409
reed@google.combb6992a2011-04-26 17:41:56 +0000410///////////////////////////////////////////////////////////////////////////////
411
reed@google.comacd471f2011-05-03 21:26:46 +0000412#define NOTIFY_SETUP(canvas) \
413 AutoPipeNotify apn(canvas)
414
reed@google.combb6992a2011-04-26 17:41:56 +0000415int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000416 NOTIFY_SETUP(this);
417 if (this->needOpBytes()) {
418 this->writeOp(kSave_DrawOp, 0, flags);
419 }
reed@google.combb6992a2011-04-26 17:41:56 +0000420 return this->INHERITED::save(flags);
421}
422
423int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
424 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000425 NOTIFY_SETUP(this);
426 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000427 unsigned opFlags = 0;
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000428
reed@google.combb6992a2011-04-26 17:41:56 +0000429 if (bounds) {
430 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000431 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000432 }
433 if (paint) {
434 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
reed@google.com31891582011-05-12 03:03:56 +0000435 this->writePaint(*paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000436 }
437
reed@google.comacd471f2011-05-03 21:26:46 +0000438 if (this->needOpBytes(size)) {
439 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
440 if (bounds) {
441 fWriter.writeRect(*bounds);
442 }
reed@google.combb6992a2011-04-26 17:41:56 +0000443 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000444
reed@google.combb6992a2011-04-26 17:41:56 +0000445 // we just pass on the save, so we don't create a layer
446 return this->INHERITED::save(saveFlags);
447}
448
449void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000450 NOTIFY_SETUP(this);
451 if (this->needOpBytes()) {
452 this->writeOp(kRestore_DrawOp);
453 }
reed@google.combb6992a2011-04-26 17:41:56 +0000454 this->INHERITED::restore();
455}
456
457bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
458 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000459 NOTIFY_SETUP(this);
460 if (this->needOpBytes(2 * sizeof(SkScalar))) {
461 this->writeOp(kTranslate_DrawOp);
462 fWriter.writeScalar(dx);
463 fWriter.writeScalar(dy);
464 }
reed@google.combb6992a2011-04-26 17:41:56 +0000465 }
466 return this->INHERITED::translate(dx, dy);
467}
468
469bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
470 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000471 NOTIFY_SETUP(this);
472 if (this->needOpBytes(2 * sizeof(SkScalar))) {
473 this->writeOp(kScale_DrawOp);
474 fWriter.writeScalar(sx);
475 fWriter.writeScalar(sy);
476 }
reed@google.combb6992a2011-04-26 17:41:56 +0000477 }
478 return this->INHERITED::scale(sx, sy);
479}
480
481bool SkGPipeCanvas::rotate(SkScalar degrees) {
482 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000483 NOTIFY_SETUP(this);
484 if (this->needOpBytes(sizeof(SkScalar))) {
485 this->writeOp(kRotate_DrawOp);
486 fWriter.writeScalar(degrees);
487 }
reed@google.combb6992a2011-04-26 17:41:56 +0000488 }
489 return this->INHERITED::rotate(degrees);
490}
491
492bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
493 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000494 NOTIFY_SETUP(this);
495 if (this->needOpBytes(2 * sizeof(SkScalar))) {
496 this->writeOp(kSkew_DrawOp);
497 fWriter.writeScalar(sx);
498 fWriter.writeScalar(sy);
499 }
reed@google.combb6992a2011-04-26 17:41:56 +0000500 }
501 return this->INHERITED::skew(sx, sy);
502}
503
504bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
505 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000506 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000507 if (this->needOpBytes(matrix.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000508 this->writeOp(kConcat_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000509 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000510 }
reed@google.combb6992a2011-04-26 17:41:56 +0000511 }
512 return this->INHERITED::concat(matrix);
513}
514
515void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000516 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000517 if (this->needOpBytes(matrix.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000518 this->writeOp(kSetMatrix_DrawOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000519 fWriter.writeMatrix(matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000520 }
reed@google.combb6992a2011-04-26 17:41:56 +0000521 this->INHERITED::setMatrix(matrix);
522}
523
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000524bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp,
525 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000526 NOTIFY_SETUP(this);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000527 if (this->needOpBytes(sizeof(SkRect)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000528 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
529 fWriter.writeRect(rect);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000530 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000531 }
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000532 return this->INHERITED::clipRect(rect, rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000533}
534
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000535bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp,
536 bool doAntiAlias) {
reed@google.comacd471f2011-05-03 21:26:46 +0000537 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000538 if (this->needOpBytes(path.writeToMemory(NULL)) + sizeof(bool)) {
reed@google.comacd471f2011-05-03 21:26:46 +0000539 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000540 fWriter.writePath(path);
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000541 fWriter.writeBool(doAntiAlias);
reed@google.comacd471f2011-05-03 21:26:46 +0000542 }
reed@google.combb6992a2011-04-26 17:41:56 +0000543 // we just pass on the bounds of the path
scroggo@google.com3b45cd52012-04-18 13:57:47 +0000544 return this->INHERITED::clipRect(path.getBounds(), rgnOp, doAntiAlias);
reed@google.combb6992a2011-04-26 17:41:56 +0000545}
546
547bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000548 NOTIFY_SETUP(this);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000549 if (this->needOpBytes(region.writeToMemory(NULL))) {
reed@google.comacd471f2011-05-03 21:26:46 +0000550 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000551 fWriter.writeRegion(region);
reed@google.comacd471f2011-05-03 21:26:46 +0000552 }
reed@google.combb6992a2011-04-26 17:41:56 +0000553 return this->INHERITED::clipRegion(region, rgnOp);
554}
555
556///////////////////////////////////////////////////////////////////////////////
557
558void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000559 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000560 unsigned flags = 0;
561 if (color) {
562 flags |= kClear_HasColor_DrawOpFlag;
563 }
reed@google.comacd471f2011-05-03 21:26:46 +0000564 if (this->needOpBytes(sizeof(SkColor))) {
565 this->writeOp(kDrawClear_DrawOp, flags, 0);
566 if (color) {
567 fWriter.write32(color);
568 }
reed@google.combb6992a2011-04-26 17:41:56 +0000569 }
570}
571
572void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000573 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000574 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000575 if (this->needOpBytes()) {
reed@google.com31891582011-05-12 03:03:56 +0000576 this->writeOp(kDrawPaint_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000577 }
reed@google.combb6992a2011-04-26 17:41:56 +0000578}
579
580void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
581 const SkPoint pts[], const SkPaint& paint) {
582 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000583 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000584 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000585 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000586 this->writeOp(kDrawPoints_DrawOp, mode, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000587 fWriter.write32(count);
588 fWriter.write(pts, count * sizeof(SkPoint));
589 }
reed@google.combb6992a2011-04-26 17:41:56 +0000590 }
591}
592
593void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000594 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000595 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000596 if (this->needOpBytes(sizeof(SkRect))) {
reed@google.com31891582011-05-12 03:03:56 +0000597 this->writeOp(kDrawRect_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000598 fWriter.writeRect(rect);
599 }
reed@google.combb6992a2011-04-26 17:41:56 +0000600}
601
602void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000603 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000604 this->writePaint(paint);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000605 if (this->needOpBytes(path.writeToMemory(NULL))) {
reed@google.com31891582011-05-12 03:03:56 +0000606 this->writeOp(kDrawPath_DrawOp);
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000607 fWriter.writePath(path);
reed@google.comacd471f2011-05-03 21:26:46 +0000608 }
reed@google.combb6992a2011-04-26 17:41:56 +0000609}
610
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000611void SkGPipeCanvas::drawBitmap(const SkBitmap& bm, SkScalar left, SkScalar top,
612 const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000613 bool flatten = shouldFlattenBitmaps(fFlags);
614 const void* ptr = 0;
615 int bitmapIndex = 0;
616 if (flatten) {
617 bitmapIndex = this->flattenToIndex(bm);
618 } else {
619 ptr = fHeap.addBitmap(bm);
620 if (NULL == ptr) {
621 return;
622 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000623 }
624
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000625 NOTIFY_SETUP(this);
626 if (paint) {
627 this->writePaint(*paint);
628 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000629
scroggo@google.com565254b2012-06-28 15:41:32 +0000630 size_t opBytesNeeded = sizeof(SkScalar) * 2 + sizeof(bool);
631 if (!flatten) {
632 opBytesNeeded += sizeof(void*);
633 }
634 if (this->needOpBytes(opBytesNeeded)) {
635 this->writeOp(kDrawBitmap_DrawOp, 0, bitmapIndex);
636 if (!flatten) {
637 fWriter.writePtr(const_cast<void*>(ptr));
638 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000639 fWriter.writeBool(paint != NULL);
640 fWriter.writeScalar(left);
641 fWriter.writeScalar(top);
642 }
reed@google.combb6992a2011-04-26 17:41:56 +0000643}
644
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000645void SkGPipeCanvas::drawBitmapRect(const SkBitmap& bm, const SkIRect* src,
646 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000647 bool flatten = shouldFlattenBitmaps(fFlags);
648 const void* ptr = 0;
649 int bitmapIndex = 0;
650 if (flatten) {
651 bitmapIndex = this->flattenToIndex(bm);
652 } else {
653 ptr = fHeap.addBitmap(bm);
654 if (NULL == ptr) {
655 return;
656 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000657 }
658
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000659 NOTIFY_SETUP(this);
660 if (paint) {
661 this->writePaint(*paint);
662 }
663
scroggo@google.com565254b2012-06-28 15:41:32 +0000664 size_t opBytesNeeded = sizeof(SkRect) + sizeof(bool) * 2;
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000665 bool hasSrc = src != NULL;
666 if (hasSrc) {
667 opBytesNeeded += sizeof(int32_t) * 4;
668 }
scroggo@google.com565254b2012-06-28 15:41:32 +0000669 if (!flatten) {
670 opBytesNeeded += sizeof(void*);
671 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000672 if (this->needOpBytes(opBytesNeeded)) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000673 this->writeOp(kDrawBitmapRect_DrawOp, 0, bitmapIndex);
674 if (!flatten) {
675 fWriter.writePtr(const_cast<void*>(ptr));
676 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000677 fWriter.writeBool(paint != NULL);
678 fWriter.writeBool(hasSrc);
679 if (hasSrc) {
680 fWriter.write32(src->fLeft);
681 fWriter.write32(src->fTop);
682 fWriter.write32(src->fRight);
683 fWriter.write32(src->fBottom);
684 }
685 fWriter.writeRect(dst);
686 }
reed@google.combb6992a2011-04-26 17:41:56 +0000687}
688
689void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
690 const SkPaint*) {
691 UNIMPLEMENTED
692}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000693
694void SkGPipeCanvas::drawBitmapNine(const SkBitmap& bm, const SkIRect& center,
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000695 const SkRect& dst, const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000696 bool flatten = shouldFlattenBitmaps(fFlags);
697 const void* ptr = 0;
698 int bitmapIndex = 0;
699 if (flatten) {
700 bitmapIndex = this->flattenToIndex(bm);
701 } else {
702 ptr = fHeap.addBitmap(bm);
703 if (NULL == ptr) {
704 return;
705 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000706 }
707
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000708 NOTIFY_SETUP(this);
709 if (paint) {
710 this->writePaint(*paint);
711 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000712
scroggo@google.com565254b2012-06-28 15:41:32 +0000713 size_t opBytesNeeded = sizeof(int32_t) * 4 + sizeof(bool) + sizeof(SkRect);
714 if (!flatten) {
715 opBytesNeeded += sizeof(void*);
716 }
717 if (this->needOpBytes(opBytesNeeded)) {
718 this->writeOp(kDrawBitmapNine_DrawOp, 0, bitmapIndex);
719 if (!flatten) {
720 fWriter.writePtr(const_cast<void*>(ptr));
721 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000722 fWriter.writeBool(paint != NULL);
723 fWriter.write32(center.fLeft);
724 fWriter.write32(center.fTop);
725 fWriter.write32(center.fRight);
726 fWriter.write32(center.fBottom);
727 fWriter.writeRect(dst);
728 }
scroggo@google.com5a2e8792012-04-20 17:39:51 +0000729}
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000730
731void SkGPipeCanvas::drawSprite(const SkBitmap& bm, int left, int top,
732 const SkPaint* paint) {
scroggo@google.com565254b2012-06-28 15:41:32 +0000733 bool flatten = shouldFlattenBitmaps(fFlags);
734 const void* ptr = 0;
735 int bitmapIndex = 0;
736 if (flatten) {
737 bitmapIndex = this->flattenToIndex(bm);
738 } else {
739 ptr = fHeap.addBitmap(bm);
740 if (NULL == ptr) {
741 return;
742 }
scroggo@google.com8ae3c7f2012-06-13 17:47:52 +0000743 }
744
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000745 NOTIFY_SETUP(this);
746 if (paint) {
747 this->writePaint(*paint);
748 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000749
scroggo@google.com565254b2012-06-28 15:41:32 +0000750 size_t opBytesNeeded = sizeof(int32_t) * 2 + sizeof(bool);
751 if (!flatten) {
752 opBytesNeeded += sizeof(void*);
753 }
754 if (this->needOpBytes(opBytesNeeded)) {
755 this->writeOp(kDrawSprite_DrawOp, 0, bitmapIndex);
756 if (!flatten) {
757 fWriter.writePtr(const_cast<void*>(ptr));
758 }
scroggo@google.com16d1d0b2012-05-02 19:09:40 +0000759 fWriter.writeBool(paint != NULL);
760 fWriter.write32(left);
761 fWriter.write32(top);
762 }
reed@google.combb6992a2011-04-26 17:41:56 +0000763}
764
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000765void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
reed@google.combb6992a2011-04-26 17:41:56 +0000766 SkScalar y, const SkPaint& paint) {
767 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000768 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000769 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000770 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
reed@google.com31891582011-05-12 03:03:56 +0000771 this->writeOp(kDrawText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000772 fWriter.write32(byteLength);
773 fWriter.writePad(text, byteLength);
774 fWriter.writeScalar(x);
775 fWriter.writeScalar(y);
776 }
reed@google.combb6992a2011-04-26 17:41:56 +0000777 }
778}
779
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000780void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
reed@google.combb6992a2011-04-26 17:41:56 +0000781 const SkPoint pos[], const SkPaint& paint) {
782 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000783 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000784 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000785 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000786 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000787 this->writeOp(kDrawPosText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000788 fWriter.write32(byteLength);
789 fWriter.writePad(text, byteLength);
790 fWriter.write32(count);
791 fWriter.write(pos, count * sizeof(SkPoint));
792 }
reed@google.combb6992a2011-04-26 17:41:56 +0000793 }
794}
795
796void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
797 const SkScalar xpos[], SkScalar constY,
798 const SkPaint& paint) {
799 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000800 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000801 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000802 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000803 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
reed@google.com31891582011-05-12 03:03:56 +0000804 this->writeOp(kDrawPosTextH_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000805 fWriter.write32(byteLength);
806 fWriter.writePad(text, byteLength);
807 fWriter.write32(count);
808 fWriter.write(xpos, count * sizeof(SkScalar));
809 fWriter.writeScalar(constY);
810 }
reed@google.combb6992a2011-04-26 17:41:56 +0000811 }
812}
813
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000814void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
815 const SkPath& path, const SkMatrix* matrix,
reed@google.combb6992a2011-04-26 17:41:56 +0000816 const SkPaint& paint) {
817 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000818 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000819 unsigned flags = 0;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000820 size_t size = 4 + SkAlign4(byteLength) + path.writeToMemory(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000821 if (matrix) {
822 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000823 size += matrix->writeToMemory(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000824 }
reed@google.com31891582011-05-12 03:03:56 +0000825 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000826 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000827 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
reed@google.combb6992a2011-04-26 17:41:56 +0000828
reed@google.comacd471f2011-05-03 21:26:46 +0000829 fWriter.write32(byteLength);
830 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000831
djsollen@google.com94e75ee2012-06-08 18:30:46 +0000832 fWriter.writePath(path);
reed@google.comacd471f2011-05-03 21:26:46 +0000833 if (matrix) {
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000834 fWriter.writeMatrix(*matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000835 }
reed@google.combb6992a2011-04-26 17:41:56 +0000836 }
837 }
838}
839
840void SkGPipeCanvas::drawPicture(SkPicture& picture) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000841 // we want to playback the picture into individual draw calls
842 this->INHERITED::drawPicture(picture);
reed@google.combb6992a2011-04-26 17:41:56 +0000843}
844
reed@google.combb6992a2011-04-26 17:41:56 +0000845void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
846 const SkPoint vertices[], const SkPoint texs[],
847 const SkColor colors[], SkXfermode*,
848 const uint16_t indices[], int indexCount,
849 const SkPaint& paint) {
850 if (0 == vertexCount) {
851 return;
852 }
853
reed@google.comacd471f2011-05-03 21:26:46 +0000854 NOTIFY_SETUP(this);
855 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.com31891582011-05-12 03:03:56 +0000856 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000857 unsigned flags = 0;
858 if (texs) {
859 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000860 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000861 }
862 if (colors) {
863 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000864 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000865 }
866 if (indices && indexCount > 0) {
867 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000868 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000869 }
vandebo@chromium.org74b46192012-01-28 01:45:11 +0000870
reed@google.comacd471f2011-05-03 21:26:46 +0000871 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000872 this->writeOp(kDrawVertices_DrawOp, flags, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000873 fWriter.write32(mode);
874 fWriter.write32(vertexCount);
875 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
876 if (texs) {
877 fWriter.write(texs, vertexCount * sizeof(SkPoint));
878 }
879 if (colors) {
880 fWriter.write(colors, vertexCount * sizeof(SkColor));
881 }
reed@google.combb6992a2011-04-26 17:41:56 +0000882
reed@google.comacd471f2011-05-03 21:26:46 +0000883 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000884
reed@google.comacd471f2011-05-03 21:26:46 +0000885 if (indices && indexCount > 0) {
886 fWriter.write32(indexCount);
887 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
888 }
reed@google.combb6992a2011-04-26 17:41:56 +0000889 }
890}
891
reed@google.comacd471f2011-05-03 21:26:46 +0000892void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
893 if (size && ptr) {
894 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000895 unsigned data = 0;
896 if (size < (1 << DRAWOPS_DATA_BITS)) {
897 data = (unsigned)size;
898 }
reed@google.comacd471f2011-05-03 21:26:46 +0000899 if (this->needOpBytes(4 + SkAlign4(size))) {
900 this->writeOp(kDrawData_DrawOp, 0, data);
901 if (0 == data) {
902 fWriter.write32(size);
903 }
reed@google.combb6793b2011-05-05 15:18:15 +0000904 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000905 }
906 }
907}
908
909///////////////////////////////////////////////////////////////////////////////
910
911template <typename T> uint32_t castToU32(T value) {
912 union {
913 T fSrc;
914 uint32_t fDst;
915 } data;
916 data.fSrc = value;
917 return data.fDst;
918}
919
reed@google.com31891582011-05-12 03:03:56 +0000920void SkGPipeCanvas::writePaint(const SkPaint& paint) {
921 SkPaint& base = fPaint;
reed@google.combb6992a2011-04-26 17:41:56 +0000922 uint32_t storage[32];
923 uint32_t* ptr = storage;
reed@google.combb6992a2011-04-26 17:41:56 +0000924
925 if (base.getFlags() != paint.getFlags()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000926 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000927 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000928 }
929 if (base.getColor() != paint.getColor()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000930 *ptr++ = PaintOp_packOp(kColor_PaintOp);
931 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000932 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000933 }
934 if (base.getStyle() != paint.getStyle()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000935 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000936 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000937 }
938 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000939 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000940 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000941 }
942 if (base.getStrokeCap() != paint.getStrokeCap()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000943 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000944 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000945 }
946 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000947 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
948 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000949 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000950 }
951 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000952 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
953 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000954 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000955 }
956 if (base.getTextEncoding() != paint.getTextEncoding()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000957 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000958 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000959 }
960 if (base.getHinting() != paint.getHinting()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000961 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000962 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000963 }
964 if (base.getTextAlign() != paint.getTextAlign()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000965 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000966 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000967 }
968 if (base.getTextSize() != paint.getTextSize()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000969 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
970 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000971 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000972 }
973 if (base.getTextScaleX() != paint.getTextScaleX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000974 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
975 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000976 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000977 }
978 if (base.getTextSkewX() != paint.getTextSkewX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000979 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
980 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +0000981 base.setTextSkewX(paint.getTextSkewX());
982 }
983
984 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
985 uint32_t id = this->getTypefaceID(paint.getTypeface());
reed@google.comf5842f72011-05-04 18:30:04 +0000986 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
987 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +0000988 }
reed@google.combb6992a2011-04-26 17:41:56 +0000989
reed@google.comb55d1182011-05-11 00:42:04 +0000990 for (int i = 0; i < kCount_PaintFlats; i++) {
991 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
992 SkASSERT(index >= 0 && index <= fFlatArray.count());
993 if (index != fCurrFlatIndex[i]) {
reed@google.comb55d1182011-05-11 00:42:04 +0000994 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
995 fCurrFlatIndex[i] = index;
996 }
997 }
998
reed@google.comacd471f2011-05-03 21:26:46 +0000999 size_t size = (char*)ptr - (char*)storage;
1000 if (size && this->needOpBytes(size)) {
reed@google.comb55d1182011-05-11 00:42:04 +00001001 this->writeOp(kPaintOp_DrawOp, 0, size);
reed@google.comb55d1182011-05-11 00:42:04 +00001002 fWriter.write(storage, size);
reed@google.combb6992a2011-04-26 17:41:56 +00001003 for (size_t i = 0; i < size/4; i++) {
reed@google.comb55d1182011-05-11 00:42:04 +00001004// SkDebugf("[%d] %08X\n", i, storage[i]);
reed@google.combb6992a2011-04-26 17:41:56 +00001005 }
1006 }
reed@google.combb6992a2011-04-26 17:41:56 +00001007}
1008
1009///////////////////////////////////////////////////////////////////////////////
1010
1011#include "SkGPipe.h"
1012
reed@google.comacd471f2011-05-03 21:26:46 +00001013SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +00001014 fCanvas = NULL;
1015}
1016
1017SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +00001018 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +00001019 SkSafeUnref(fCanvas);
1020}
1021
scroggo@google.com565254b2012-06-28 15:41:32 +00001022SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller, uint32_t flags) {
reed@google.combb6992a2011-04-26 17:41:56 +00001023 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +00001024 fWriter.reset(NULL, 0);
reed@google.comdde09562011-05-23 12:21:05 +00001025 fFactorySet.reset();
1026 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
1027 (flags & kCrossProcess_Flag) ?
scroggo@google.com565254b2012-06-28 15:41:32 +00001028 &fFactorySet : NULL, flags));
reed@google.combb6992a2011-04-26 17:41:56 +00001029 }
1030 return fCanvas;
1031}
1032
1033void SkGPipeWriter::endRecording() {
1034 if (fCanvas) {
1035 fCanvas->finish();
1036 fCanvas->unref();
1037 fCanvas = NULL;
1038 }
1039}
1040