blob: 00d5d5ff8737696b4a38354e9551481403145007 [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.comacd471f2011-05-03 21:26:46 +000015#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000016#include "SkGPipePriv.h"
reed@google.comf5842f72011-05-04 18:30:04 +000017#include "SkStream.h"
reed@google.comb55d1182011-05-11 00:42:04 +000018#include "SkTSearch.h"
reed@google.comf5842f72011-05-04 18:30:04 +000019#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000020#include "SkWriter32.h"
reed@google.comb55d1182011-05-11 00:42:04 +000021#include "SkColorFilter.h"
reed@google.com0faac1e2011-05-11 05:58:58 +000022#include "SkDrawLooper.h"
reed@google.comb55d1182011-05-11 00:42:04 +000023#include "SkMaskFilter.h"
24#include "SkRasterizer.h"
25#include "SkShader.h"
26
27static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
28 SkASSERT(paintFlat < kCount_PaintFlats);
29 switch (paintFlat) {
30 case kColorFilter_PaintFlat: return paint.getColorFilter();
reed@google.com0faac1e2011-05-11 05:58:58 +000031 case kDrawLooper_PaintFlat: return paint.getLooper();
reed@google.comb55d1182011-05-11 00:42:04 +000032 case kMaskFilter_PaintFlat: return paint.getMaskFilter();
33 case kPathEffect_PaintFlat: return paint.getPathEffect();
34 case kRasterizer_PaintFlat: return paint.getRasterizer();
35 case kShader_PaintFlat: return paint.getShader();
36 case kXfermode_PaintFlat: return paint.getXfermode();
37 }
tomhudson@google.com0c00f212011-12-28 14:59:50 +000038 SkDEBUGFAIL("never gets here");
reed@google.comb55d1182011-05-11 00:42:04 +000039 return NULL;
40}
reed@google.combb6992a2011-04-26 17:41:56 +000041
reed@google.comacd471f2011-05-03 21:26:46 +000042static size_t estimateFlattenSize(const SkPath& path) {
43 int n = path.countPoints();
44 size_t bytes = 3 * sizeof(int32_t);
45 bytes += n * sizeof(SkPoint);
46 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras
47
48#ifdef SK_DEBUG
49 {
50 SkWriter32 writer(1024);
51 path.flatten(writer);
52 SkASSERT(writer.size() <= bytes);
53 }
54#endif
55 return bytes;
56}
57
reed@google.comf5842f72011-05-04 18:30:04 +000058static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
59 SkASSERT(typeface);
60 SkDynamicMemoryWStream stream;
61 typeface->serialize(&stream);
62 size_t size = stream.getOffset();
63 if (writer) {
64 writer->write32(size);
reed@google.com8a85d0c2011-06-24 19:12:12 +000065 SkAutoDataUnref data(stream.copyToData());
66 writer->write(data.data(), size);
reed@google.comf5842f72011-05-04 18:30:04 +000067 }
68 return 4 + size;
69}
70
reed@google.combb6992a2011-04-26 17:41:56 +000071///////////////////////////////////////////////////////////////////////////////
72
73class SkGPipeCanvas : public SkCanvas {
74public:
reed@google.comdde09562011-05-23 12:21:05 +000075 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*);
reed@google.combb6992a2011-04-26 17:41:56 +000076 virtual ~SkGPipeCanvas();
77
78 void finish() {
79 if (!fDone) {
reed@google.comdbccc882011-07-08 18:53:39 +000080 if (this->needOpBytes()) {
81 this->writeOp(kDone_DrawOp);
82 this->doNotify();
83 }
reed@google.combb6992a2011-04-26 17:41:56 +000084 fDone = true;
85 }
86 }
87
88 // overrides from SkCanvas
89 virtual int save(SaveFlags);
90 virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
91 virtual void restore();
92 virtual bool translate(SkScalar dx, SkScalar dy);
93 virtual bool scale(SkScalar sx, SkScalar sy);
94 virtual bool rotate(SkScalar degrees);
95 virtual bool skew(SkScalar sx, SkScalar sy);
96 virtual bool concat(const SkMatrix& matrix);
97 virtual void setMatrix(const SkMatrix& matrix);
98 virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
99 virtual bool clipPath(const SkPath& path, SkRegion::Op op);
100 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
101 virtual void clear(SkColor);
102 virtual void drawPaint(const SkPaint& paint);
103 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
104 const SkPaint&);
105 virtual void drawRect(const SkRect& rect, const SkPaint&);
106 virtual void drawPath(const SkPath& path, const SkPaint&);
107 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
108 const SkPaint*);
109 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
110 const SkRect& dst, const SkPaint*);
111 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
112 const SkPaint*);
113 virtual void drawSprite(const SkBitmap&, int left, int top,
114 const SkPaint*);
115 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
116 SkScalar y, const SkPaint&);
117 virtual void drawPosText(const void* text, size_t byteLength,
118 const SkPoint pos[], const SkPaint&);
119 virtual void drawPosTextH(const void* text, size_t byteLength,
120 const SkScalar xpos[], SkScalar constY, const SkPaint&);
121 virtual void drawTextOnPath(const void* text, size_t byteLength,
122 const SkPath& path, const SkMatrix* matrix,
123 const SkPaint&);
124 virtual void drawPicture(SkPicture& picture);
reed@google.combb6992a2011-04-26 17:41:56 +0000125 virtual void drawVertices(VertexMode, int vertexCount,
126 const SkPoint vertices[], const SkPoint texs[],
127 const SkColor colors[], SkXfermode*,
128 const uint16_t indices[], int indexCount,
129 const SkPaint&);
130 virtual void drawData(const void*, size_t);
131
132private:
reed@google.comdde09562011-05-23 12:21:05 +0000133 SkFactorySet* fFactorySet; // optional, only used if cross-process
reed@google.comacd471f2011-05-03 21:26:46 +0000134 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000135 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000136 size_t fBlockSize; // amount allocated for writer
137 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000138 bool fDone;
139
reed@google.comf5842f72011-05-04 18:30:04 +0000140 SkRefCntSet fTypefaceSet;
141
142 uint32_t getTypefaceID(SkTypeface*);
143
reed@google.comacd471f2011-05-03 21:26:46 +0000144 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000145 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
146 }
147
reed@google.comacd471f2011-05-03 21:26:46 +0000148 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000149 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
150 }
reed@google.comacd471f2011-05-03 21:26:46 +0000151
152 bool needOpBytes(size_t size = 0);
153
154 inline void doNotify() {
155 if (!fDone) {
156 size_t bytes = fWriter.size() - fBytesNotified;
157 fController->notifyWritten(bytes);
158 fBytesNotified += bytes;
159 }
160 }
reed@google.comb55d1182011-05-11 00:42:04 +0000161
162 struct FlatData {
163 uint32_t fIndex; // always > 0
164 uint32_t fSize;
165
166 void* data() { return (char*)this + sizeof(*this); }
167
168 static int Compare(const FlatData* a, const FlatData* b) {
169 return memcmp(&a->fSize, &b->fSize, a->fSize + sizeof(a->fSize));
170 }
171 };
172 SkTDArray<FlatData*> fFlatArray;
173 int fCurrFlatIndex[kCount_PaintFlats];
174 int flattenToIndex(SkFlattenable* obj, PaintFlats);
175
reed@google.com31891582011-05-12 03:03:56 +0000176 SkPaint fPaint;
177 void writePaint(const SkPaint&);
reed@google.combb6992a2011-04-26 17:41:56 +0000178
reed@google.comacd471f2011-05-03 21:26:46 +0000179 class AutoPipeNotify {
180 public:
181 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
182 ~AutoPipeNotify() { fCanvas->doNotify(); }
183 private:
184 SkGPipeCanvas* fCanvas;
185 };
186 friend class AutoPipeNotify;
187
reed@google.combb6992a2011-04-26 17:41:56 +0000188 typedef SkCanvas INHERITED;
189};
190
reed@google.comb55d1182011-05-11 00:42:04 +0000191// return 0 for NULL (or unflattenable obj), or index-base-1
192int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
193 if (NULL == obj) {
194 return 0;
195 }
reed@google.comb55d1182011-05-11 00:42:04 +0000196
197 SkFlattenableWriteBuffer tmpWriter(1024);
reed@google.com6bac9472011-06-21 19:24:00 +0000198 tmpWriter.setFlags(SkFlattenableWriteBuffer::kInlineFactoryNames_Flag);
reed@google.comdde09562011-05-23 12:21:05 +0000199 tmpWriter.setFactoryRecorder(fFactorySet);
200
reed@google.comb55d1182011-05-11 00:42:04 +0000201 tmpWriter.writeFlattenable(obj);
202 size_t len = tmpWriter.size();
203 size_t allocSize = len + sizeof(FlatData);
204
205 SkAutoSMalloc<1024> storage(allocSize);
206 FlatData* flat = (FlatData*)storage.get();
207 flat->fSize = len;
208 tmpWriter.flatten(flat->data());
209
210 int index = SkTSearch<FlatData>((const FlatData**)fFlatArray.begin(),
211 fFlatArray.count(), flat, sizeof(flat),
212 &FlatData::Compare);
213 if (index < 0) {
214 index = ~index;
215 FlatData* copy = (FlatData*)sk_malloc_throw(allocSize);
216 memcpy(copy, flat, allocSize);
217 *fFlatArray.insert(index) = copy;
218 // call this after the insert, so that count() will have been grown
219 copy->fIndex = fFlatArray.count();
220// SkDebugf("--- add flattenable[%d] size=%d index=%d\n", paintflat, len, copy->fIndex);
221
222 if (this->needOpBytes(len)) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000223 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
reed@google.comb55d1182011-05-11 00:42:04 +0000224 fWriter.write(copy->data(), len);
225 }
226 }
227 return fFlatArray[index]->fIndex;
228}
229
reed@google.combb6992a2011-04-26 17:41:56 +0000230///////////////////////////////////////////////////////////////////////////////
231
reed@google.comacd471f2011-05-03 21:26:46 +0000232#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000233
reed@google.comacd471f2011-05-03 21:26:46 +0000234SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
reed@google.comdde09562011-05-23 12:21:05 +0000235 SkWriter32* writer, SkFactorySet* fset)
reed@google.com67908f22011-06-27 14:47:50 +0000236 : fWriter(*writer) {
237 fFactorySet = fset;
reed@google.comacd471f2011-05-03 21:26:46 +0000238 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000239 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000240 fBlockSize = 0; // need first block from controller
reed@google.comb55d1182011-05-11 00:42:04 +0000241 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
reed@google.comacd471f2011-05-03 21:26:46 +0000242
reed@google.combb6793b2011-05-05 15:18:15 +0000243 // we need a device to limit our clip
244 // should the caller give us the bounds?
yangsu@google.com06b4da12011-06-17 15:04:40 +0000245 // We don't allocate pixels for the bitmap
reed@google.combb6793b2011-05-05 15:18:15 +0000246 SkBitmap bitmap;
247 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
yangsu@google.com06b4da12011-06-17 15:04:40 +0000248 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
reed@google.combb6793b2011-05-05 15:18:15 +0000249 this->setDevice(device)->unref();
reed@google.combb6992a2011-04-26 17:41:56 +0000250}
251
252SkGPipeCanvas::~SkGPipeCanvas() {
253 this->finish();
254
reed@google.comb55d1182011-05-11 00:42:04 +0000255 fFlatArray.freeAll();
reed@google.combb6992a2011-04-26 17:41:56 +0000256}
257
reed@google.comacd471f2011-05-03 21:26:46 +0000258bool SkGPipeCanvas::needOpBytes(size_t needed) {
259 if (fDone) {
260 return false;
261 }
262
263 needed += 4; // size of DrawOp atom
264 if (fWriter.size() + needed > fBlockSize) {
265 void* block = fController->requestBlock(MIN_BLOCK_SIZE, &fBlockSize);
266 if (NULL == block) {
267 fDone = true;
268 return false;
269 }
270 fWriter.reset(block, fBlockSize);
271 fBytesNotified = 0;
272 }
273 return true;
274}
275
reed@google.comf5842f72011-05-04 18:30:04 +0000276uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
277 uint32_t id = 0; // 0 means default/null typeface
278 if (face) {
279 id = fTypefaceSet.find(face);
280 if (0 == id) {
281 id = fTypefaceSet.add(face);
282 size_t size = writeTypeface(NULL, face);
283 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000284 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000285 writeTypeface(&fWriter, face);
286 }
287 }
288 }
289 return id;
290}
291
reed@google.combb6992a2011-04-26 17:41:56 +0000292///////////////////////////////////////////////////////////////////////////////
293
reed@google.comacd471f2011-05-03 21:26:46 +0000294#define NOTIFY_SETUP(canvas) \
295 AutoPipeNotify apn(canvas)
296
reed@google.combb6992a2011-04-26 17:41:56 +0000297int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000298 NOTIFY_SETUP(this);
299 if (this->needOpBytes()) {
300 this->writeOp(kSave_DrawOp, 0, flags);
301 }
reed@google.combb6992a2011-04-26 17:41:56 +0000302 return this->INHERITED::save(flags);
303}
304
305int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
306 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000307 NOTIFY_SETUP(this);
308 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000309 unsigned opFlags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000310
reed@google.combb6992a2011-04-26 17:41:56 +0000311 if (bounds) {
312 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000313 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000314 }
315 if (paint) {
316 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
reed@google.com31891582011-05-12 03:03:56 +0000317 this->writePaint(*paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000318 }
319
reed@google.comacd471f2011-05-03 21:26:46 +0000320 if (this->needOpBytes(size)) {
321 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
322 if (bounds) {
323 fWriter.writeRect(*bounds);
324 }
reed@google.combb6992a2011-04-26 17:41:56 +0000325 }
326
327 // we just pass on the save, so we don't create a layer
328 return this->INHERITED::save(saveFlags);
329}
330
331void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000332 NOTIFY_SETUP(this);
333 if (this->needOpBytes()) {
334 this->writeOp(kRestore_DrawOp);
335 }
reed@google.combb6992a2011-04-26 17:41:56 +0000336 this->INHERITED::restore();
337}
338
339bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
340 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000341 NOTIFY_SETUP(this);
342 if (this->needOpBytes(2 * sizeof(SkScalar))) {
343 this->writeOp(kTranslate_DrawOp);
344 fWriter.writeScalar(dx);
345 fWriter.writeScalar(dy);
346 }
reed@google.combb6992a2011-04-26 17:41:56 +0000347 }
348 return this->INHERITED::translate(dx, dy);
349}
350
351bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
352 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000353 NOTIFY_SETUP(this);
354 if (this->needOpBytes(2 * sizeof(SkScalar))) {
355 this->writeOp(kScale_DrawOp);
356 fWriter.writeScalar(sx);
357 fWriter.writeScalar(sy);
358 }
reed@google.combb6992a2011-04-26 17:41:56 +0000359 }
360 return this->INHERITED::scale(sx, sy);
361}
362
363bool SkGPipeCanvas::rotate(SkScalar degrees) {
364 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000365 NOTIFY_SETUP(this);
366 if (this->needOpBytes(sizeof(SkScalar))) {
367 this->writeOp(kRotate_DrawOp);
368 fWriter.writeScalar(degrees);
369 }
reed@google.combb6992a2011-04-26 17:41:56 +0000370 }
371 return this->INHERITED::rotate(degrees);
372}
373
374bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
375 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000376 NOTIFY_SETUP(this);
377 if (this->needOpBytes(2 * sizeof(SkScalar))) {
378 this->writeOp(kSkew_DrawOp);
379 fWriter.writeScalar(sx);
380 fWriter.writeScalar(sy);
381 }
reed@google.combb6992a2011-04-26 17:41:56 +0000382 }
383 return this->INHERITED::skew(sx, sy);
384}
385
386bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
387 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000388 NOTIFY_SETUP(this);
389 if (this->needOpBytes(matrix.flatten(NULL))) {
390 this->writeOp(kConcat_DrawOp);
reed@google.comb55d1182011-05-11 00:42:04 +0000391 SkWriteMatrix(&fWriter, matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000392 }
reed@google.combb6992a2011-04-26 17:41:56 +0000393 }
394 return this->INHERITED::concat(matrix);
395}
396
397void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000398 NOTIFY_SETUP(this);
399 if (this->needOpBytes(matrix.flatten(NULL))) {
400 this->writeOp(kSetMatrix_DrawOp);
reed@google.comb55d1182011-05-11 00:42:04 +0000401 SkWriteMatrix(&fWriter, matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000402 }
reed@google.combb6992a2011-04-26 17:41:56 +0000403 this->INHERITED::setMatrix(matrix);
404}
405
406bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000407 NOTIFY_SETUP(this);
408 if (this->needOpBytes(sizeof(SkRect))) {
409 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
410 fWriter.writeRect(rect);
411 }
reed@google.combb6992a2011-04-26 17:41:56 +0000412 return this->INHERITED::clipRect(rect, rgnOp);
413}
414
415bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000416 NOTIFY_SETUP(this);
417 if (this->needOpBytes(estimateFlattenSize(path))) {
418 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
419 path.flatten(fWriter);
420 }
reed@google.combb6992a2011-04-26 17:41:56 +0000421 // we just pass on the bounds of the path
422 return this->INHERITED::clipRect(path.getBounds(), rgnOp);
423}
424
425bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000426 NOTIFY_SETUP(this);
427 if (this->needOpBytes(region.flatten(NULL))) {
428 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
reed@google.comb55d1182011-05-11 00:42:04 +0000429 SkWriteRegion(&fWriter, region);
reed@google.comacd471f2011-05-03 21:26:46 +0000430 }
reed@google.combb6992a2011-04-26 17:41:56 +0000431 return this->INHERITED::clipRegion(region, rgnOp);
432}
433
434///////////////////////////////////////////////////////////////////////////////
435
436void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000437 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000438 unsigned flags = 0;
439 if (color) {
440 flags |= kClear_HasColor_DrawOpFlag;
441 }
reed@google.comacd471f2011-05-03 21:26:46 +0000442 if (this->needOpBytes(sizeof(SkColor))) {
443 this->writeOp(kDrawClear_DrawOp, flags, 0);
444 if (color) {
445 fWriter.write32(color);
446 }
reed@google.combb6992a2011-04-26 17:41:56 +0000447 }
448}
449
450void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000451 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000452 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000453 if (this->needOpBytes()) {
reed@google.com31891582011-05-12 03:03:56 +0000454 this->writeOp(kDrawPaint_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000455 }
reed@google.combb6992a2011-04-26 17:41:56 +0000456}
457
458void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
459 const SkPoint pts[], const SkPaint& paint) {
460 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000461 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000462 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000463 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000464 this->writeOp(kDrawPoints_DrawOp, mode, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000465 fWriter.write32(count);
466 fWriter.write(pts, count * sizeof(SkPoint));
467 }
reed@google.combb6992a2011-04-26 17:41:56 +0000468 }
469}
470
471void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000472 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000473 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000474 if (this->needOpBytes(sizeof(SkRect))) {
reed@google.com31891582011-05-12 03:03:56 +0000475 this->writeOp(kDrawRect_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000476 fWriter.writeRect(rect);
477 }
reed@google.combb6992a2011-04-26 17:41:56 +0000478}
479
480void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000481 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000482 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000483 if (this->needOpBytes(estimateFlattenSize(path))) {
reed@google.com31891582011-05-12 03:03:56 +0000484 this->writeOp(kDrawPath_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000485 path.flatten(fWriter);
486 }
reed@google.combb6992a2011-04-26 17:41:56 +0000487}
488
489void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
490 const SkPaint*) {
491 UNIMPLEMENTED
492}
493
494void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
495 const SkRect& dst, const SkPaint*) {
496 UNIMPLEMENTED
497}
498
499void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
500 const SkPaint*) {
501 UNIMPLEMENTED
502}
503
504void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
505 const SkPaint*) {
506 UNIMPLEMENTED
507}
508
509void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
510 SkScalar y, const SkPaint& paint) {
511 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000512 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000513 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000514 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
reed@google.com31891582011-05-12 03:03:56 +0000515 this->writeOp(kDrawText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000516 fWriter.write32(byteLength);
517 fWriter.writePad(text, byteLength);
518 fWriter.writeScalar(x);
519 fWriter.writeScalar(y);
520 }
reed@google.combb6992a2011-04-26 17:41:56 +0000521 }
522}
523
524void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
525 const SkPoint pos[], const SkPaint& paint) {
526 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000527 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000528 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000529 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000530 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
reed@google.com31891582011-05-12 03:03:56 +0000531 this->writeOp(kDrawPosText_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000532 fWriter.write32(byteLength);
533 fWriter.writePad(text, byteLength);
534 fWriter.write32(count);
535 fWriter.write(pos, count * sizeof(SkPoint));
536 }
reed@google.combb6992a2011-04-26 17:41:56 +0000537 }
538}
539
540void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
541 const SkScalar xpos[], SkScalar constY,
542 const SkPaint& paint) {
543 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000544 NOTIFY_SETUP(this);
reed@google.com31891582011-05-12 03:03:56 +0000545 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000546 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000547 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
reed@google.com31891582011-05-12 03:03:56 +0000548 this->writeOp(kDrawPosTextH_DrawOp);
reed@google.comacd471f2011-05-03 21:26:46 +0000549 fWriter.write32(byteLength);
550 fWriter.writePad(text, byteLength);
551 fWriter.write32(count);
552 fWriter.write(xpos, count * sizeof(SkScalar));
553 fWriter.writeScalar(constY);
554 }
reed@google.combb6992a2011-04-26 17:41:56 +0000555 }
556}
557
558void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
559 const SkPath& path, const SkMatrix* matrix,
560 const SkPaint& paint) {
561 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000562 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000563 unsigned flags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000564 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
reed@google.combb6992a2011-04-26 17:41:56 +0000565 if (matrix) {
566 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000567 size += matrix->flatten(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000568 }
reed@google.com31891582011-05-12 03:03:56 +0000569 this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000570 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000571 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
reed@google.combb6992a2011-04-26 17:41:56 +0000572
reed@google.comacd471f2011-05-03 21:26:46 +0000573 fWriter.write32(byteLength);
574 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000575
reed@google.comacd471f2011-05-03 21:26:46 +0000576 path.flatten(fWriter);
577 if (matrix) {
reed@google.comb55d1182011-05-11 00:42:04 +0000578 SkWriteMatrix(&fWriter, *matrix);
reed@google.comacd471f2011-05-03 21:26:46 +0000579 }
reed@google.combb6992a2011-04-26 17:41:56 +0000580 }
581 }
582}
583
584void SkGPipeCanvas::drawPicture(SkPicture& picture) {
reed@google.com0faac1e2011-05-11 05:58:58 +0000585 // we want to playback the picture into individual draw calls
586 this->INHERITED::drawPicture(picture);
reed@google.combb6992a2011-04-26 17:41:56 +0000587}
588
reed@google.combb6992a2011-04-26 17:41:56 +0000589void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
590 const SkPoint vertices[], const SkPoint texs[],
591 const SkColor colors[], SkXfermode*,
592 const uint16_t indices[], int indexCount,
593 const SkPaint& paint) {
594 if (0 == vertexCount) {
595 return;
596 }
597
reed@google.comacd471f2011-05-03 21:26:46 +0000598 NOTIFY_SETUP(this);
599 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.com31891582011-05-12 03:03:56 +0000600 this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000601 unsigned flags = 0;
602 if (texs) {
603 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000604 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000605 }
606 if (colors) {
607 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000608 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000609 }
610 if (indices && indexCount > 0) {
611 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000612 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000613 }
614
reed@google.comacd471f2011-05-03 21:26:46 +0000615 if (this->needOpBytes(size)) {
reed@google.com31891582011-05-12 03:03:56 +0000616 this->writeOp(kDrawVertices_DrawOp, flags, 0);
reed@google.comacd471f2011-05-03 21:26:46 +0000617 fWriter.write32(mode);
618 fWriter.write32(vertexCount);
619 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
620 if (texs) {
621 fWriter.write(texs, vertexCount * sizeof(SkPoint));
622 }
623 if (colors) {
624 fWriter.write(colors, vertexCount * sizeof(SkColor));
625 }
reed@google.combb6992a2011-04-26 17:41:56 +0000626
reed@google.comacd471f2011-05-03 21:26:46 +0000627 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000628
reed@google.comacd471f2011-05-03 21:26:46 +0000629 if (indices && indexCount > 0) {
630 fWriter.write32(indexCount);
631 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
632 }
reed@google.combb6992a2011-04-26 17:41:56 +0000633 }
634}
635
reed@google.comacd471f2011-05-03 21:26:46 +0000636void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
637 if (size && ptr) {
638 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000639 unsigned data = 0;
640 if (size < (1 << DRAWOPS_DATA_BITS)) {
641 data = (unsigned)size;
642 }
reed@google.comacd471f2011-05-03 21:26:46 +0000643 if (this->needOpBytes(4 + SkAlign4(size))) {
644 this->writeOp(kDrawData_DrawOp, 0, data);
645 if (0 == data) {
646 fWriter.write32(size);
647 }
reed@google.combb6793b2011-05-05 15:18:15 +0000648 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000649 }
650 }
651}
652
653///////////////////////////////////////////////////////////////////////////////
654
655template <typename T> uint32_t castToU32(T value) {
656 union {
657 T fSrc;
658 uint32_t fDst;
659 } data;
660 data.fSrc = value;
661 return data.fDst;
662}
663
reed@google.com31891582011-05-12 03:03:56 +0000664void SkGPipeCanvas::writePaint(const SkPaint& paint) {
665 SkPaint& base = fPaint;
reed@google.combb6992a2011-04-26 17:41:56 +0000666 uint32_t storage[32];
667 uint32_t* ptr = storage;
reed@google.combb6992a2011-04-26 17:41:56 +0000668
669 if (base.getFlags() != paint.getFlags()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000670 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000671 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000672 }
673 if (base.getColor() != paint.getColor()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000674 *ptr++ = PaintOp_packOp(kColor_PaintOp);
675 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000676 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000677 }
678 if (base.getStyle() != paint.getStyle()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000679 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000680 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000681 }
682 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000683 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000684 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000685 }
686 if (base.getStrokeCap() != paint.getStrokeCap()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000687 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000688 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000689 }
690 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000691 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
692 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000693 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000694 }
695 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000696 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
697 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000698 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000699 }
700 if (base.getTextEncoding() != paint.getTextEncoding()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000701 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000702 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000703 }
704 if (base.getHinting() != paint.getHinting()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000705 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000706 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000707 }
708 if (base.getTextAlign() != paint.getTextAlign()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000709 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000710 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000711 }
712 if (base.getTextSize() != paint.getTextSize()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000713 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
714 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000715 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000716 }
717 if (base.getTextScaleX() != paint.getTextScaleX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000718 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
719 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000720 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000721 }
722 if (base.getTextSkewX() != paint.getTextSkewX()) {
reed@google.combb6992a2011-04-26 17:41:56 +0000723 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
724 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +0000725 base.setTextSkewX(paint.getTextSkewX());
726 }
727
728 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
729 uint32_t id = this->getTypefaceID(paint.getTypeface());
reed@google.comf5842f72011-05-04 18:30:04 +0000730 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
731 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +0000732 }
reed@google.combb6992a2011-04-26 17:41:56 +0000733
reed@google.comb55d1182011-05-11 00:42:04 +0000734 for (int i = 0; i < kCount_PaintFlats; i++) {
735 int index = this->flattenToIndex(get_paintflat(paint, i), (PaintFlats)i);
736 SkASSERT(index >= 0 && index <= fFlatArray.count());
737 if (index != fCurrFlatIndex[i]) {
reed@google.comb55d1182011-05-11 00:42:04 +0000738 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
739 fCurrFlatIndex[i] = index;
740 }
741 }
742
reed@google.comacd471f2011-05-03 21:26:46 +0000743 size_t size = (char*)ptr - (char*)storage;
744 if (size && this->needOpBytes(size)) {
reed@google.comb55d1182011-05-11 00:42:04 +0000745 this->writeOp(kPaintOp_DrawOp, 0, size);
reed@google.comb55d1182011-05-11 00:42:04 +0000746 fWriter.write(storage, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000747 for (size_t i = 0; i < size/4; i++) {
reed@google.comb55d1182011-05-11 00:42:04 +0000748// SkDebugf("[%d] %08X\n", i, storage[i]);
reed@google.combb6992a2011-04-26 17:41:56 +0000749 }
750 }
reed@google.combb6992a2011-04-26 17:41:56 +0000751}
752
753///////////////////////////////////////////////////////////////////////////////
754
755#include "SkGPipe.h"
756
reed@google.comacd471f2011-05-03 21:26:46 +0000757SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +0000758 fCanvas = NULL;
759}
760
761SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +0000762 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +0000763 SkSafeUnref(fCanvas);
764}
765
reed@google.comdde09562011-05-23 12:21:05 +0000766SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller,
767 uint32_t flags) {
reed@google.combb6992a2011-04-26 17:41:56 +0000768 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +0000769 fWriter.reset(NULL, 0);
reed@google.comdde09562011-05-23 12:21:05 +0000770 fFactorySet.reset();
771 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
772 (flags & kCrossProcess_Flag) ?
773 &fFactorySet : NULL));
reed@google.combb6992a2011-04-26 17:41:56 +0000774 }
775 return fCanvas;
776}
777
778void SkGPipeWriter::endRecording() {
779 if (fCanvas) {
780 fCanvas->finish();
781 fCanvas->unref();
782 fCanvas = NULL;
783 }
784}
785