1
2 /*
3 * 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.
7 */
8
9
10
11 #include "SkCanvas.h"
12 #include "SkData.h"
13 #include "SkDevice.h"
14 #include "SkPaint.h"
15 #include "SkGPipe.h"
16 #include "SkGPipePriv.h"
17 #include "SkStream.h"
18 #include "SkTSearch.h"
19 #include "SkTypeface.h"
20 #include "SkWriter32.h"
21 #include "SkColorFilter.h"
22 #include "SkDrawLooper.h"
23 #include "SkMaskFilter.h"
24 #include "SkRasterizer.h"
25 #include "SkShader.h"
26
get_paintflat(const SkPaint & paint,unsigned paintFlat)27 static SkFlattenable* get_paintflat(const SkPaint& paint, unsigned paintFlat) {
28 SkASSERT(paintFlat < kCount_PaintFlats);
29 switch (paintFlat) {
30 case kColorFilter_PaintFlat: return paint.getColorFilter();
31 case kDrawLooper_PaintFlat: return paint.getLooper();
32 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 }
38 SkDEBUGFAIL("never gets here");
39 return NULL;
40 }
41
estimateFlattenSize(const SkPath & path)42 static 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
writeTypeface(SkWriter32 * writer,SkTypeface * typeface)58 static 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);
65 SkAutoDataUnref data(stream.copyToData());
66 writer->write(data.data(), size);
67 }
68 return 4 + size;
69 }
70
71 ///////////////////////////////////////////////////////////////////////////////
72
73 class SkGPipeCanvas : public SkCanvas {
74 public:
75 SkGPipeCanvas(SkGPipeController*, SkWriter32*, SkFactorySet*);
76 virtual ~SkGPipeCanvas();
77
finish()78 void finish() {
79 if (!fDone) {
80 if (this->needOpBytes()) {
81 this->writeOp(kDone_DrawOp);
82 this->doNotify();
83 }
84 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);
125 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
132 private:
133 SkFactorySet* fFactorySet; // optional, only used if cross-process
134 SkGPipeController* fController;
135 SkWriter32& fWriter;
136 size_t fBlockSize; // amount allocated for writer
137 size_t fBytesNotified;
138 bool fDone;
139
140 SkRefCntSet fTypefaceSet;
141
142 uint32_t getTypefaceID(SkTypeface*);
143
writeOp(DrawOps op,unsigned flags,unsigned data)144 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
145 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
146 }
147
writeOp(DrawOps op)148 inline void writeOp(DrawOps op) {
149 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
150 }
151
152 bool needOpBytes(size_t size = 0);
153
doNotify()154 inline void doNotify() {
155 if (!fDone) {
156 size_t bytes = fWriter.size() - fBytesNotified;
157 fController->notifyWritten(bytes);
158 fBytesNotified += bytes;
159 }
160 }
161
162 struct FlatData {
163 uint32_t fIndex; // always > 0
164 uint32_t fSize;
165
dataSkGPipeCanvas::FlatData166 void* data() { return (char*)this + sizeof(*this); }
167
CompareSkGPipeCanvas::FlatData168 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
176 SkPaint fPaint;
177 void writePaint(const SkPaint&);
178
179 class AutoPipeNotify {
180 public:
AutoPipeNotify(SkGPipeCanvas * canvas)181 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
~AutoPipeNotify()182 ~AutoPipeNotify() { fCanvas->doNotify(); }
183 private:
184 SkGPipeCanvas* fCanvas;
185 };
186 friend class AutoPipeNotify;
187
188 typedef SkCanvas INHERITED;
189 };
190
191 // return 0 for NULL (or unflattenable obj), or index-base-1
flattenToIndex(SkFlattenable * obj,PaintFlats paintflat)192 int SkGPipeCanvas::flattenToIndex(SkFlattenable* obj, PaintFlats paintflat) {
193 if (NULL == obj) {
194 return 0;
195 }
196
197 SkFlattenableWriteBuffer tmpWriter(1024);
198 tmpWriter.setFlags(SkFlattenableWriteBuffer::kInlineFactoryNames_Flag);
199 tmpWriter.setFactoryRecorder(fFactorySet);
200
201 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)) {
223 this->writeOp(kDef_Flattenable_DrawOp, paintflat, copy->fIndex);
224 fWriter.write(copy->data(), len);
225 }
226 }
227 return fFlatArray[index]->fIndex;
228 }
229
230 ///////////////////////////////////////////////////////////////////////////////
231
232 #define MIN_BLOCK_SIZE (16 * 1024)
233
SkGPipeCanvas(SkGPipeController * controller,SkWriter32 * writer,SkFactorySet * fset)234 SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
235 SkWriter32* writer, SkFactorySet* fset)
236 : fWriter(*writer) {
237 fFactorySet = fset;
238 fController = controller;
239 fDone = false;
240 fBlockSize = 0; // need first block from controller
241 sk_bzero(fCurrFlatIndex, sizeof(fCurrFlatIndex));
242
243 // we need a device to limit our clip
244 // should the caller give us the bounds?
245 // We don't allocate pixels for the bitmap
246 SkBitmap bitmap;
247 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
248 SkDevice* device = SkNEW_ARGS(SkDevice, (bitmap));
249 this->setDevice(device)->unref();
250 }
251
~SkGPipeCanvas()252 SkGPipeCanvas::~SkGPipeCanvas() {
253 this->finish();
254
255 fFlatArray.freeAll();
256 }
257
needOpBytes(size_t needed)258 bool 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
getTypefaceID(SkTypeface * face)276 uint32_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)) {
284 this->writeOp(kDef_Typeface_DrawOp);
285 writeTypeface(&fWriter, face);
286 }
287 }
288 }
289 return id;
290 }
291
292 ///////////////////////////////////////////////////////////////////////////////
293
294 #define NOTIFY_SETUP(canvas) \
295 AutoPipeNotify apn(canvas)
296
save(SaveFlags flags)297 int SkGPipeCanvas::save(SaveFlags flags) {
298 NOTIFY_SETUP(this);
299 if (this->needOpBytes()) {
300 this->writeOp(kSave_DrawOp, 0, flags);
301 }
302 return this->INHERITED::save(flags);
303 }
304
saveLayer(const SkRect * bounds,const SkPaint * paint,SaveFlags saveFlags)305 int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
306 SaveFlags saveFlags) {
307 NOTIFY_SETUP(this);
308 size_t size = 0;
309 unsigned opFlags = 0;
310
311 if (bounds) {
312 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
313 size += sizeof(SkRect);
314 }
315 if (paint) {
316 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
317 this->writePaint(*paint);
318 }
319
320 if (this->needOpBytes(size)) {
321 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
322 if (bounds) {
323 fWriter.writeRect(*bounds);
324 }
325 }
326
327 // we just pass on the save, so we don't create a layer
328 return this->INHERITED::save(saveFlags);
329 }
330
restore()331 void SkGPipeCanvas::restore() {
332 NOTIFY_SETUP(this);
333 if (this->needOpBytes()) {
334 this->writeOp(kRestore_DrawOp);
335 }
336 this->INHERITED::restore();
337 }
338
translate(SkScalar dx,SkScalar dy)339 bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
340 if (dx || dy) {
341 NOTIFY_SETUP(this);
342 if (this->needOpBytes(2 * sizeof(SkScalar))) {
343 this->writeOp(kTranslate_DrawOp);
344 fWriter.writeScalar(dx);
345 fWriter.writeScalar(dy);
346 }
347 }
348 return this->INHERITED::translate(dx, dy);
349 }
350
scale(SkScalar sx,SkScalar sy)351 bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
352 if (sx || sy) {
353 NOTIFY_SETUP(this);
354 if (this->needOpBytes(2 * sizeof(SkScalar))) {
355 this->writeOp(kScale_DrawOp);
356 fWriter.writeScalar(sx);
357 fWriter.writeScalar(sy);
358 }
359 }
360 return this->INHERITED::scale(sx, sy);
361 }
362
rotate(SkScalar degrees)363 bool SkGPipeCanvas::rotate(SkScalar degrees) {
364 if (degrees) {
365 NOTIFY_SETUP(this);
366 if (this->needOpBytes(sizeof(SkScalar))) {
367 this->writeOp(kRotate_DrawOp);
368 fWriter.writeScalar(degrees);
369 }
370 }
371 return this->INHERITED::rotate(degrees);
372 }
373
skew(SkScalar sx,SkScalar sy)374 bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
375 if (sx || sy) {
376 NOTIFY_SETUP(this);
377 if (this->needOpBytes(2 * sizeof(SkScalar))) {
378 this->writeOp(kSkew_DrawOp);
379 fWriter.writeScalar(sx);
380 fWriter.writeScalar(sy);
381 }
382 }
383 return this->INHERITED::skew(sx, sy);
384 }
385
concat(const SkMatrix & matrix)386 bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
387 if (!matrix.isIdentity()) {
388 NOTIFY_SETUP(this);
389 if (this->needOpBytes(matrix.flatten(NULL))) {
390 this->writeOp(kConcat_DrawOp);
391 SkWriteMatrix(&fWriter, matrix);
392 }
393 }
394 return this->INHERITED::concat(matrix);
395 }
396
setMatrix(const SkMatrix & matrix)397 void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
398 NOTIFY_SETUP(this);
399 if (this->needOpBytes(matrix.flatten(NULL))) {
400 this->writeOp(kSetMatrix_DrawOp);
401 SkWriteMatrix(&fWriter, matrix);
402 }
403 this->INHERITED::setMatrix(matrix);
404 }
405
clipRect(const SkRect & rect,SkRegion::Op rgnOp)406 bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
407 NOTIFY_SETUP(this);
408 if (this->needOpBytes(sizeof(SkRect))) {
409 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
410 fWriter.writeRect(rect);
411 }
412 return this->INHERITED::clipRect(rect, rgnOp);
413 }
414
clipPath(const SkPath & path,SkRegion::Op rgnOp)415 bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
416 NOTIFY_SETUP(this);
417 if (this->needOpBytes(estimateFlattenSize(path))) {
418 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
419 path.flatten(fWriter);
420 }
421 // we just pass on the bounds of the path
422 return this->INHERITED::clipRect(path.getBounds(), rgnOp);
423 }
424
clipRegion(const SkRegion & region,SkRegion::Op rgnOp)425 bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
426 NOTIFY_SETUP(this);
427 if (this->needOpBytes(region.flatten(NULL))) {
428 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
429 SkWriteRegion(&fWriter, region);
430 }
431 return this->INHERITED::clipRegion(region, rgnOp);
432 }
433
434 ///////////////////////////////////////////////////////////////////////////////
435
clear(SkColor color)436 void SkGPipeCanvas::clear(SkColor color) {
437 NOTIFY_SETUP(this);
438 unsigned flags = 0;
439 if (color) {
440 flags |= kClear_HasColor_DrawOpFlag;
441 }
442 if (this->needOpBytes(sizeof(SkColor))) {
443 this->writeOp(kDrawClear_DrawOp, flags, 0);
444 if (color) {
445 fWriter.write32(color);
446 }
447 }
448 }
449
drawPaint(const SkPaint & paint)450 void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
451 NOTIFY_SETUP(this);
452 this->writePaint(paint);
453 if (this->needOpBytes()) {
454 this->writeOp(kDrawPaint_DrawOp);
455 }
456 }
457
drawPoints(PointMode mode,size_t count,const SkPoint pts[],const SkPaint & paint)458 void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
459 const SkPoint pts[], const SkPaint& paint) {
460 if (count) {
461 NOTIFY_SETUP(this);
462 this->writePaint(paint);
463 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
464 this->writeOp(kDrawPoints_DrawOp, mode, 0);
465 fWriter.write32(count);
466 fWriter.write(pts, count * sizeof(SkPoint));
467 }
468 }
469 }
470
drawRect(const SkRect & rect,const SkPaint & paint)471 void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
472 NOTIFY_SETUP(this);
473 this->writePaint(paint);
474 if (this->needOpBytes(sizeof(SkRect))) {
475 this->writeOp(kDrawRect_DrawOp);
476 fWriter.writeRect(rect);
477 }
478 }
479
drawPath(const SkPath & path,const SkPaint & paint)480 void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
481 NOTIFY_SETUP(this);
482 this->writePaint(paint);
483 if (this->needOpBytes(estimateFlattenSize(path))) {
484 this->writeOp(kDrawPath_DrawOp);
485 path.flatten(fWriter);
486 }
487 }
488
drawBitmap(const SkBitmap &,SkScalar left,SkScalar top,const SkPaint *)489 void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
490 const SkPaint*) {
491 UNIMPLEMENTED
492 }
493
drawBitmapRect(const SkBitmap &,const SkIRect * src,const SkRect & dst,const SkPaint *)494 void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
495 const SkRect& dst, const SkPaint*) {
496 UNIMPLEMENTED
497 }
498
drawBitmapMatrix(const SkBitmap &,const SkMatrix &,const SkPaint *)499 void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
500 const SkPaint*) {
501 UNIMPLEMENTED
502 }
503
drawSprite(const SkBitmap &,int left,int top,const SkPaint *)504 void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
505 const SkPaint*) {
506 UNIMPLEMENTED
507 }
508
drawText(const void * text,size_t byteLength,SkScalar x,SkScalar y,const SkPaint & paint)509 void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
510 SkScalar y, const SkPaint& paint) {
511 if (byteLength) {
512 NOTIFY_SETUP(this);
513 this->writePaint(paint);
514 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
515 this->writeOp(kDrawText_DrawOp);
516 fWriter.write32(byteLength);
517 fWriter.writePad(text, byteLength);
518 fWriter.writeScalar(x);
519 fWriter.writeScalar(y);
520 }
521 }
522 }
523
drawPosText(const void * text,size_t byteLength,const SkPoint pos[],const SkPaint & paint)524 void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
525 const SkPoint pos[], const SkPaint& paint) {
526 if (byteLength) {
527 NOTIFY_SETUP(this);
528 this->writePaint(paint);
529 int count = paint.textToGlyphs(text, byteLength, NULL);
530 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
531 this->writeOp(kDrawPosText_DrawOp);
532 fWriter.write32(byteLength);
533 fWriter.writePad(text, byteLength);
534 fWriter.write32(count);
535 fWriter.write(pos, count * sizeof(SkPoint));
536 }
537 }
538 }
539
drawPosTextH(const void * text,size_t byteLength,const SkScalar xpos[],SkScalar constY,const SkPaint & paint)540 void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
541 const SkScalar xpos[], SkScalar constY,
542 const SkPaint& paint) {
543 if (byteLength) {
544 NOTIFY_SETUP(this);
545 this->writePaint(paint);
546 int count = paint.textToGlyphs(text, byteLength, NULL);
547 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
548 this->writeOp(kDrawPosTextH_DrawOp);
549 fWriter.write32(byteLength);
550 fWriter.writePad(text, byteLength);
551 fWriter.write32(count);
552 fWriter.write(xpos, count * sizeof(SkScalar));
553 fWriter.writeScalar(constY);
554 }
555 }
556 }
557
drawTextOnPath(const void * text,size_t byteLength,const SkPath & path,const SkMatrix * matrix,const SkPaint & paint)558 void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
559 const SkPath& path, const SkMatrix* matrix,
560 const SkPaint& paint) {
561 if (byteLength) {
562 NOTIFY_SETUP(this);
563 unsigned flags = 0;
564 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
565 if (matrix) {
566 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
567 size += matrix->flatten(NULL);
568 }
569 this->writePaint(paint);
570 if (this->needOpBytes(size)) {
571 this->writeOp(kDrawTextOnPath_DrawOp, flags, 0);
572
573 fWriter.write32(byteLength);
574 fWriter.writePad(text, byteLength);
575
576 path.flatten(fWriter);
577 if (matrix) {
578 SkWriteMatrix(&fWriter, *matrix);
579 }
580 }
581 }
582 }
583
drawPicture(SkPicture & picture)584 void SkGPipeCanvas::drawPicture(SkPicture& picture) {
585 // we want to playback the picture into individual draw calls
586 this->INHERITED::drawPicture(picture);
587 }
588
drawVertices(VertexMode mode,int vertexCount,const SkPoint vertices[],const SkPoint texs[],const SkColor colors[],SkXfermode *,const uint16_t indices[],int indexCount,const SkPaint & paint)589 void 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
598 NOTIFY_SETUP(this);
599 size_t size = 4 + vertexCount * sizeof(SkPoint);
600 this->writePaint(paint);
601 unsigned flags = 0;
602 if (texs) {
603 flags |= kDrawVertices_HasTexs_DrawOpFlag;
604 size += vertexCount * sizeof(SkPoint);
605 }
606 if (colors) {
607 flags |= kDrawVertices_HasColors_DrawOpFlag;
608 size += vertexCount * sizeof(SkColor);
609 }
610 if (indices && indexCount > 0) {
611 flags |= kDrawVertices_HasIndices_DrawOpFlag;
612 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
613 }
614
615 if (this->needOpBytes(size)) {
616 this->writeOp(kDrawVertices_DrawOp, flags, 0);
617 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 }
626
627 // TODO: flatten xfermode
628
629 if (indices && indexCount > 0) {
630 fWriter.write32(indexCount);
631 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
632 }
633 }
634 }
635
drawData(const void * ptr,size_t size)636 void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
637 if (size && ptr) {
638 NOTIFY_SETUP(this);
639 unsigned data = 0;
640 if (size < (1 << DRAWOPS_DATA_BITS)) {
641 data = (unsigned)size;
642 }
643 if (this->needOpBytes(4 + SkAlign4(size))) {
644 this->writeOp(kDrawData_DrawOp, 0, data);
645 if (0 == data) {
646 fWriter.write32(size);
647 }
648 fWriter.writePad(ptr, size);
649 }
650 }
651 }
652
653 ///////////////////////////////////////////////////////////////////////////////
654
castToU32(T value)655 template <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
writePaint(const SkPaint & paint)664 void SkGPipeCanvas::writePaint(const SkPaint& paint) {
665 SkPaint& base = fPaint;
666 uint32_t storage[32];
667 uint32_t* ptr = storage;
668
669 if (base.getFlags() != paint.getFlags()) {
670 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
671 base.setFlags(paint.getFlags());
672 }
673 if (base.getColor() != paint.getColor()) {
674 *ptr++ = PaintOp_packOp(kColor_PaintOp);
675 *ptr++ = paint.getColor();
676 base.setColor(paint.getColor());
677 }
678 if (base.getStyle() != paint.getStyle()) {
679 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
680 base.setStyle(paint.getStyle());
681 }
682 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
683 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
684 base.setStrokeJoin(paint.getStrokeJoin());
685 }
686 if (base.getStrokeCap() != paint.getStrokeCap()) {
687 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
688 base.setStrokeCap(paint.getStrokeCap());
689 }
690 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
691 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
692 *ptr++ = castToU32(paint.getStrokeWidth());
693 base.setStrokeWidth(paint.getStrokeWidth());
694 }
695 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
696 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
697 *ptr++ = castToU32(paint.getStrokeMiter());
698 base.setStrokeMiter(paint.getStrokeMiter());
699 }
700 if (base.getTextEncoding() != paint.getTextEncoding()) {
701 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
702 base.setTextEncoding(paint.getTextEncoding());
703 }
704 if (base.getHinting() != paint.getHinting()) {
705 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
706 base.setHinting(paint.getHinting());
707 }
708 if (base.getTextAlign() != paint.getTextAlign()) {
709 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
710 base.setTextAlign(paint.getTextAlign());
711 }
712 if (base.getTextSize() != paint.getTextSize()) {
713 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
714 *ptr++ = castToU32(paint.getTextSize());
715 base.setTextSize(paint.getTextSize());
716 }
717 if (base.getTextScaleX() != paint.getTextScaleX()) {
718 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
719 *ptr++ = castToU32(paint.getTextScaleX());
720 base.setTextScaleX(paint.getTextScaleX());
721 }
722 if (base.getTextSkewX() != paint.getTextSkewX()) {
723 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
724 *ptr++ = castToU32(paint.getTextSkewX());
725 base.setTextSkewX(paint.getTextSkewX());
726 }
727
728 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
729 uint32_t id = this->getTypefaceID(paint.getTypeface());
730 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
731 base.setTypeface(paint.getTypeface());
732 }
733
734 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]) {
738 *ptr++ = PaintOp_packOpFlagData(kFlatIndex_PaintOp, i, index);
739 fCurrFlatIndex[i] = index;
740 }
741 }
742
743 size_t size = (char*)ptr - (char*)storage;
744 if (size && this->needOpBytes(size)) {
745 this->writeOp(kPaintOp_DrawOp, 0, size);
746 fWriter.write(storage, size);
747 for (size_t i = 0; i < size/4; i++) {
748 // SkDebugf("[%d] %08X\n", i, storage[i]);
749 }
750 }
751 }
752
753 ///////////////////////////////////////////////////////////////////////////////
754
755 #include "SkGPipe.h"
756
SkGPipeWriter()757 SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
758 fCanvas = NULL;
759 }
760
~SkGPipeWriter()761 SkGPipeWriter::~SkGPipeWriter() {
762 this->endRecording();
763 SkSafeUnref(fCanvas);
764 }
765
startRecording(SkGPipeController * controller,uint32_t flags)766 SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller,
767 uint32_t flags) {
768 if (NULL == fCanvas) {
769 fWriter.reset(NULL, 0);
770 fFactorySet.reset();
771 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter,
772 (flags & kCrossProcess_Flag) ?
773 &fFactorySet : NULL));
774 }
775 return fCanvas;
776 }
777
endRecording()778 void SkGPipeWriter::endRecording() {
779 if (fCanvas) {
780 fCanvas->finish();
781 fCanvas->unref();
782 fCanvas = NULL;
783 }
784 }
785
786