blob: d2bf3afd2d7bd734efe93e35204f1723f62e78c2 [file] [log] [blame]
reed@google.combb6992a2011-04-26 17:41:56 +00001/*
2 Copyright 2011 Google Inc.
3
4 Licensed under the Apache License, Version 2.0 (the "License");
5 you may not use this file except in compliance with the License.
6 You may obtain a copy of the License at
7
8 http://www.apache.org/licenses/LICENSE-2.0
9
10 Unless required by applicable law or agreed to in writing, software
11 distributed under the License is distributed on an "AS IS" BASIS,
12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 See the License for the specific language governing permissions and
14 limitations under the License.
15 */
16
17
18#include "SkCanvas.h"
reed@google.combb6793b2011-05-05 15:18:15 +000019#include "SkDevice.h"
reed@google.combb6992a2011-04-26 17:41:56 +000020#include "SkPaint.h"
reed@google.comacd471f2011-05-03 21:26:46 +000021#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000022#include "SkGPipePriv.h"
reed@google.comf5842f72011-05-04 18:30:04 +000023#include "SkStream.h"
24#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000025#include "SkWriter32.h"
26
reed@google.comacd471f2011-05-03 21:26:46 +000027static size_t estimateFlattenSize(const SkPath& path) {
28 int n = path.countPoints();
29 size_t bytes = 3 * sizeof(int32_t);
30 bytes += n * sizeof(SkPoint);
31 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras
32
33#ifdef SK_DEBUG
34 {
35 SkWriter32 writer(1024);
36 path.flatten(writer);
37 SkASSERT(writer.size() <= bytes);
38 }
39#endif
40 return bytes;
41}
42
reed@google.combb6992a2011-04-26 17:41:56 +000043static void writeRegion(SkWriter32* writer, const SkRegion& rgn) {
44 size_t size = rgn.flatten(NULL);
45 SkASSERT(SkAlign4(size) == size);
46 rgn.flatten(writer->reserve(size));
47}
48
49static void writeMatrix(SkWriter32* writer, const SkMatrix& matrix) {
50 size_t size = matrix.flatten(NULL);
51 SkASSERT(SkAlign4(size) == size);
52 matrix.flatten(writer->reserve(size));
53}
54
reed@google.comf5842f72011-05-04 18:30:04 +000055static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
56 SkASSERT(typeface);
57 SkDynamicMemoryWStream stream;
58 typeface->serialize(&stream);
59 size_t size = stream.getOffset();
60 if (writer) {
61 writer->write32(size);
62 writer->write(stream.getStream(), size);
63 }
64 return 4 + size;
65}
66
reed@google.combb6992a2011-04-26 17:41:56 +000067///////////////////////////////////////////////////////////////////////////////
68
69class SkGPipeCanvas : public SkCanvas {
70public:
reed@google.comacd471f2011-05-03 21:26:46 +000071 SkGPipeCanvas(SkGPipeController*, SkWriter32*);
reed@google.combb6992a2011-04-26 17:41:56 +000072 virtual ~SkGPipeCanvas();
73
74 void finish() {
75 if (!fDone) {
76 this->writeOp(kDone_DrawOp);
77 fDone = true;
78 }
79 }
80
81 // overrides from SkCanvas
82 virtual int save(SaveFlags);
83 virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
84 virtual void restore();
85 virtual bool translate(SkScalar dx, SkScalar dy);
86 virtual bool scale(SkScalar sx, SkScalar sy);
87 virtual bool rotate(SkScalar degrees);
88 virtual bool skew(SkScalar sx, SkScalar sy);
89 virtual bool concat(const SkMatrix& matrix);
90 virtual void setMatrix(const SkMatrix& matrix);
91 virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
92 virtual bool clipPath(const SkPath& path, SkRegion::Op op);
93 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
94 virtual void clear(SkColor);
95 virtual void drawPaint(const SkPaint& paint);
96 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
97 const SkPaint&);
98 virtual void drawRect(const SkRect& rect, const SkPaint&);
99 virtual void drawPath(const SkPath& path, const SkPaint&);
100 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
101 const SkPaint*);
102 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
103 const SkRect& dst, const SkPaint*);
104 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
105 const SkPaint*);
106 virtual void drawSprite(const SkBitmap&, int left, int top,
107 const SkPaint*);
108 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
109 SkScalar y, const SkPaint&);
110 virtual void drawPosText(const void* text, size_t byteLength,
111 const SkPoint pos[], const SkPaint&);
112 virtual void drawPosTextH(const void* text, size_t byteLength,
113 const SkScalar xpos[], SkScalar constY, const SkPaint&);
114 virtual void drawTextOnPath(const void* text, size_t byteLength,
115 const SkPath& path, const SkMatrix* matrix,
116 const SkPaint&);
117 virtual void drawPicture(SkPicture& picture);
118 virtual void drawShape(SkShape*);
119 virtual void drawVertices(VertexMode, int vertexCount,
120 const SkPoint vertices[], const SkPoint texs[],
121 const SkColor colors[], SkXfermode*,
122 const uint16_t indices[], int indexCount,
123 const SkPaint&);
124 virtual void drawData(const void*, size_t);
125
126private:
reed@google.comacd471f2011-05-03 21:26:46 +0000127 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000128 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000129 size_t fBlockSize; // amount allocated for writer
130 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000131 bool fDone;
132
reed@google.comf5842f72011-05-04 18:30:04 +0000133 SkRefCntSet fTypefaceSet;
134
135 uint32_t getTypefaceID(SkTypeface*);
136
reed@google.comacd471f2011-05-03 21:26:46 +0000137 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000138 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
139 }
140
reed@google.comacd471f2011-05-03 21:26:46 +0000141 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000142 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
143 }
reed@google.comacd471f2011-05-03 21:26:46 +0000144
145 bool needOpBytes(size_t size = 0);
146
147 inline void doNotify() {
148 if (!fDone) {
149 size_t bytes = fWriter.size() - fBytesNotified;
150 fController->notifyWritten(bytes);
151 fBytesNotified += bytes;
152 }
153 }
reed@google.combb6992a2011-04-26 17:41:56 +0000154
155 SkTDArray<SkPaint*> fPaints;
156 unsigned writePaint(const SkPaint&);
157
reed@google.comacd471f2011-05-03 21:26:46 +0000158 class AutoPipeNotify {
159 public:
160 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
161 ~AutoPipeNotify() { fCanvas->doNotify(); }
162 private:
163 SkGPipeCanvas* fCanvas;
164 };
165 friend class AutoPipeNotify;
166
reed@google.combb6992a2011-04-26 17:41:56 +0000167 typedef SkCanvas INHERITED;
168};
169
170///////////////////////////////////////////////////////////////////////////////
171
reed@google.comacd471f2011-05-03 21:26:46 +0000172#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000173
reed@google.comacd471f2011-05-03 21:26:46 +0000174SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
175 SkWriter32* writer) : fWriter(*writer) {
176 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000177 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000178 fBlockSize = 0; // need first block from controller
179
reed@google.combb6992a2011-04-26 17:41:56 +0000180 // always begin with 1 default paint
181 *fPaints.append() = SkNEW(SkPaint);
reed@google.combb6793b2011-05-05 15:18:15 +0000182
183 // we need a device to limit our clip
184 // should the caller give us the bounds?
185 SkBitmap bitmap;
186 bitmap.setConfig(SkBitmap::kARGB_8888_Config, 32767, 32767);
187 SkDevice* device = SkNEW_ARGS(SkDevice, (this, bitmap, false));
188 this->setDevice(device)->unref();
reed@google.combb6992a2011-04-26 17:41:56 +0000189}
190
191SkGPipeCanvas::~SkGPipeCanvas() {
192 this->finish();
193
194 fPaints.deleteAll();
195}
196
reed@google.comacd471f2011-05-03 21:26:46 +0000197bool SkGPipeCanvas::needOpBytes(size_t needed) {
198 if (fDone) {
199 return false;
200 }
201
202 needed += 4; // size of DrawOp atom
203 if (fWriter.size() + needed > fBlockSize) {
204 void* block = fController->requestBlock(MIN_BLOCK_SIZE, &fBlockSize);
205 if (NULL == block) {
206 fDone = true;
207 return false;
208 }
209 fWriter.reset(block, fBlockSize);
210 fBytesNotified = 0;
211 }
212 return true;
213}
214
reed@google.comf5842f72011-05-04 18:30:04 +0000215uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
216 uint32_t id = 0; // 0 means default/null typeface
217 if (face) {
218 id = fTypefaceSet.find(face);
219 if (0 == id) {
220 id = fTypefaceSet.add(face);
221 size_t size = writeTypeface(NULL, face);
222 if (this->needOpBytes(size)) {
reed@google.combb6793b2011-05-05 15:18:15 +0000223 this->writeOp(kDef_Typeface_DrawOp);
reed@google.comf5842f72011-05-04 18:30:04 +0000224 writeTypeface(&fWriter, face);
225 }
226 }
227 }
228 return id;
229}
230
reed@google.combb6992a2011-04-26 17:41:56 +0000231///////////////////////////////////////////////////////////////////////////////
232
reed@google.comacd471f2011-05-03 21:26:46 +0000233#define NOTIFY_SETUP(canvas) \
234 AutoPipeNotify apn(canvas)
235
reed@google.combb6992a2011-04-26 17:41:56 +0000236int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000237 NOTIFY_SETUP(this);
238 if (this->needOpBytes()) {
239 this->writeOp(kSave_DrawOp, 0, flags);
240 }
reed@google.combb6992a2011-04-26 17:41:56 +0000241 return this->INHERITED::save(flags);
242}
243
244int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
245 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000246 NOTIFY_SETUP(this);
247 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000248 unsigned index = 0; // just to avoid the warning
249 unsigned opFlags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000250
reed@google.combb6992a2011-04-26 17:41:56 +0000251 if (bounds) {
252 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000253 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000254 }
255 if (paint) {
256 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
257 index = this->writePaint(*paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000258 size += 4;
reed@google.combb6992a2011-04-26 17:41:56 +0000259 }
260
reed@google.comacd471f2011-05-03 21:26:46 +0000261 if (this->needOpBytes(size)) {
262 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
263 if (bounds) {
264 fWriter.writeRect(*bounds);
265 }
266 if (paint) {
267 fWriter.write32(index);
268 }
reed@google.combb6992a2011-04-26 17:41:56 +0000269 }
270
271 // we just pass on the save, so we don't create a layer
272 return this->INHERITED::save(saveFlags);
273}
274
275void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000276 NOTIFY_SETUP(this);
277 if (this->needOpBytes()) {
278 this->writeOp(kRestore_DrawOp);
279 }
reed@google.combb6992a2011-04-26 17:41:56 +0000280 this->INHERITED::restore();
281}
282
283bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
284 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000285 NOTIFY_SETUP(this);
286 if (this->needOpBytes(2 * sizeof(SkScalar))) {
287 this->writeOp(kTranslate_DrawOp);
288 fWriter.writeScalar(dx);
289 fWriter.writeScalar(dy);
290 }
reed@google.combb6992a2011-04-26 17:41:56 +0000291 }
292 return this->INHERITED::translate(dx, dy);
293}
294
295bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
296 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000297 NOTIFY_SETUP(this);
298 if (this->needOpBytes(2 * sizeof(SkScalar))) {
299 this->writeOp(kScale_DrawOp);
300 fWriter.writeScalar(sx);
301 fWriter.writeScalar(sy);
302 }
reed@google.combb6992a2011-04-26 17:41:56 +0000303 }
304 return this->INHERITED::scale(sx, sy);
305}
306
307bool SkGPipeCanvas::rotate(SkScalar degrees) {
308 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000309 NOTIFY_SETUP(this);
310 if (this->needOpBytes(sizeof(SkScalar))) {
311 this->writeOp(kRotate_DrawOp);
312 fWriter.writeScalar(degrees);
313 }
reed@google.combb6992a2011-04-26 17:41:56 +0000314 }
315 return this->INHERITED::rotate(degrees);
316}
317
318bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
319 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000320 NOTIFY_SETUP(this);
321 if (this->needOpBytes(2 * sizeof(SkScalar))) {
322 this->writeOp(kSkew_DrawOp);
323 fWriter.writeScalar(sx);
324 fWriter.writeScalar(sy);
325 }
reed@google.combb6992a2011-04-26 17:41:56 +0000326 }
327 return this->INHERITED::skew(sx, sy);
328}
329
330bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
331 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000332 NOTIFY_SETUP(this);
333 if (this->needOpBytes(matrix.flatten(NULL))) {
334 this->writeOp(kConcat_DrawOp);
335 writeMatrix(&fWriter, matrix);
336 }
reed@google.combb6992a2011-04-26 17:41:56 +0000337 }
338 return this->INHERITED::concat(matrix);
339}
340
341void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000342 NOTIFY_SETUP(this);
343 if (this->needOpBytes(matrix.flatten(NULL))) {
344 this->writeOp(kSetMatrix_DrawOp);
345 writeMatrix(&fWriter, matrix);
346 }
reed@google.combb6992a2011-04-26 17:41:56 +0000347 this->INHERITED::setMatrix(matrix);
348}
349
350bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000351 NOTIFY_SETUP(this);
352 if (this->needOpBytes(sizeof(SkRect))) {
353 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
354 fWriter.writeRect(rect);
355 }
reed@google.combb6992a2011-04-26 17:41:56 +0000356 return this->INHERITED::clipRect(rect, rgnOp);
357}
358
359bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000360 NOTIFY_SETUP(this);
361 if (this->needOpBytes(estimateFlattenSize(path))) {
362 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
363 path.flatten(fWriter);
364 }
reed@google.combb6992a2011-04-26 17:41:56 +0000365 // we just pass on the bounds of the path
366 return this->INHERITED::clipRect(path.getBounds(), rgnOp);
367}
368
369bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000370 NOTIFY_SETUP(this);
371 if (this->needOpBytes(region.flatten(NULL))) {
372 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
373 writeRegion(&fWriter, region);
374 }
reed@google.combb6992a2011-04-26 17:41:56 +0000375 return this->INHERITED::clipRegion(region, rgnOp);
376}
377
378///////////////////////////////////////////////////////////////////////////////
379
380void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000381 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000382 unsigned flags = 0;
383 if (color) {
384 flags |= kClear_HasColor_DrawOpFlag;
385 }
reed@google.comacd471f2011-05-03 21:26:46 +0000386 if (this->needOpBytes(sizeof(SkColor))) {
387 this->writeOp(kDrawClear_DrawOp, flags, 0);
388 if (color) {
389 fWriter.write32(color);
390 }
reed@google.combb6992a2011-04-26 17:41:56 +0000391 }
392}
393
394void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000395 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000396 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000397 if (this->needOpBytes()) {
398 this->writeOp(kDrawPaint_DrawOp, 0, paintIndex);
399 }
reed@google.combb6992a2011-04-26 17:41:56 +0000400}
401
402void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
403 const SkPoint pts[], const SkPaint& paint) {
404 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000405 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000406 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000407 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
408 this->writeOp(kDrawPoints_DrawOp, mode, paintIndex);
409 fWriter.write32(count);
410 fWriter.write(pts, count * sizeof(SkPoint));
411 }
reed@google.combb6992a2011-04-26 17:41:56 +0000412 }
413}
414
415void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000416 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000417 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000418 if (this->needOpBytes(sizeof(SkRect))) {
419 this->writeOp(kDrawRect_DrawOp, 0, paintIndex);
420 fWriter.writeRect(rect);
421 }
reed@google.combb6992a2011-04-26 17:41:56 +0000422}
423
424void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000425 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000426 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000427 if (this->needOpBytes(estimateFlattenSize(path))) {
428 this->writeOp(kDrawPath_DrawOp, 0, paintIndex);
429 path.flatten(fWriter);
430 }
reed@google.combb6992a2011-04-26 17:41:56 +0000431}
432
433void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
434 const SkPaint*) {
435 UNIMPLEMENTED
436}
437
438void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
439 const SkRect& dst, const SkPaint*) {
440 UNIMPLEMENTED
441}
442
443void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
444 const SkPaint*) {
445 UNIMPLEMENTED
446}
447
448void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
449 const SkPaint*) {
450 UNIMPLEMENTED
451}
452
453void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
454 SkScalar y, const SkPaint& paint) {
455 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000456 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000457 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000458 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
459 this->writeOp(kDrawText_DrawOp, 0, paintIndex);
460 fWriter.write32(byteLength);
461 fWriter.writePad(text, byteLength);
462 fWriter.writeScalar(x);
463 fWriter.writeScalar(y);
464 }
reed@google.combb6992a2011-04-26 17:41:56 +0000465 }
466}
467
468void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
469 const SkPoint pos[], const SkPaint& paint) {
470 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000471 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000472 unsigned paintIndex = this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000473 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000474 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
475 this->writeOp(kDrawPosText_DrawOp, 0, paintIndex);
476 fWriter.write32(byteLength);
477 fWriter.writePad(text, byteLength);
478 fWriter.write32(count);
479 fWriter.write(pos, count * sizeof(SkPoint));
480 }
reed@google.combb6992a2011-04-26 17:41:56 +0000481 }
482}
483
484void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
485 const SkScalar xpos[], SkScalar constY,
486 const SkPaint& paint) {
487 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000488 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000489 unsigned paintIndex = this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000490 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000491 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
492 this->writeOp(kDrawPosTextH_DrawOp, 0, paintIndex);
493 fWriter.write32(byteLength);
494 fWriter.writePad(text, byteLength);
495 fWriter.write32(count);
496 fWriter.write(xpos, count * sizeof(SkScalar));
497 fWriter.writeScalar(constY);
498 }
reed@google.combb6992a2011-04-26 17:41:56 +0000499 }
500}
501
502void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
503 const SkPath& path, const SkMatrix* matrix,
504 const SkPaint& paint) {
505 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000506 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000507 unsigned flags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000508 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
reed@google.combb6992a2011-04-26 17:41:56 +0000509 if (matrix) {
510 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000511 size += matrix->flatten(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000512 }
513 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000514 if (this->needOpBytes(size)) {
515 this->writeOp(kDrawTextOnPath_DrawOp, flags, paintIndex);
reed@google.combb6992a2011-04-26 17:41:56 +0000516
reed@google.comacd471f2011-05-03 21:26:46 +0000517 fWriter.write32(byteLength);
518 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000519
reed@google.comacd471f2011-05-03 21:26:46 +0000520 path.flatten(fWriter);
521 if (matrix) {
522 writeMatrix(&fWriter, *matrix);
523 }
reed@google.combb6992a2011-04-26 17:41:56 +0000524 }
525 }
526}
527
528void SkGPipeCanvas::drawPicture(SkPicture& picture) {
529 UNIMPLEMENTED
530}
531
532void SkGPipeCanvas::drawShape(SkShape* shape) {
533 UNIMPLEMENTED
534}
535
536void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
537 const SkPoint vertices[], const SkPoint texs[],
538 const SkColor colors[], SkXfermode*,
539 const uint16_t indices[], int indexCount,
540 const SkPaint& paint) {
541 if (0 == vertexCount) {
542 return;
543 }
544
reed@google.comacd471f2011-05-03 21:26:46 +0000545 NOTIFY_SETUP(this);
546 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000547 unsigned paintIndex = this->writePaint(paint);
548 unsigned flags = 0;
549 if (texs) {
550 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000551 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000552 }
553 if (colors) {
554 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000555 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000556 }
557 if (indices && indexCount > 0) {
558 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000559 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000560 }
561
reed@google.comacd471f2011-05-03 21:26:46 +0000562 if (this->needOpBytes(size)) {
563 this->writeOp(kDrawVertices_DrawOp, flags, paintIndex);
564 fWriter.write32(mode);
565 fWriter.write32(vertexCount);
566 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
567 if (texs) {
568 fWriter.write(texs, vertexCount * sizeof(SkPoint));
569 }
570 if (colors) {
571 fWriter.write(colors, vertexCount * sizeof(SkColor));
572 }
reed@google.combb6992a2011-04-26 17:41:56 +0000573
reed@google.comacd471f2011-05-03 21:26:46 +0000574 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000575
reed@google.comacd471f2011-05-03 21:26:46 +0000576 if (indices && indexCount > 0) {
577 fWriter.write32(indexCount);
578 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
579 }
reed@google.combb6992a2011-04-26 17:41:56 +0000580 }
581}
582
reed@google.comacd471f2011-05-03 21:26:46 +0000583void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
584 if (size && ptr) {
585 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000586 unsigned data = 0;
587 if (size < (1 << DRAWOPS_DATA_BITS)) {
588 data = (unsigned)size;
589 }
reed@google.comacd471f2011-05-03 21:26:46 +0000590 if (this->needOpBytes(4 + SkAlign4(size))) {
591 this->writeOp(kDrawData_DrawOp, 0, data);
592 if (0 == data) {
593 fWriter.write32(size);
594 }
reed@google.combb6793b2011-05-05 15:18:15 +0000595 fWriter.writePad(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000596 }
597 }
598}
599
600///////////////////////////////////////////////////////////////////////////////
601
602template <typename T> uint32_t castToU32(T value) {
603 union {
604 T fSrc;
605 uint32_t fDst;
606 } data;
607 data.fSrc = value;
608 return data.fDst;
609}
610
611unsigned SkGPipeCanvas::writePaint(const SkPaint& paint) {
reed@google.comf5842f72011-05-04 18:30:04 +0000612 SkPaint& base = *fPaints[0];
reed@google.combb6992a2011-04-26 17:41:56 +0000613 uint32_t storage[32];
614 uint32_t* ptr = storage;
615 uint32_t* last = NULL;
616
617 if (base.getFlags() != paint.getFlags()) {
618 last = ptr;
619 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000620 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000621 }
622 if (base.getColor() != paint.getColor()) {
623 last = ptr;
624 *ptr++ = PaintOp_packOp(kColor_PaintOp);
625 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000626 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000627 }
628 if (base.getStyle() != paint.getStyle()) {
629 last = ptr;
630 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000631 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000632 }
633 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
634 last = ptr;
635 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000636 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000637 }
638 if (base.getStrokeCap() != paint.getStrokeCap()) {
639 last = ptr;
640 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000641 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000642 }
643 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
644 last = ptr;
645 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
646 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000647 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000648 }
649 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
650 last = ptr;
651 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
652 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000653 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000654 }
655 if (base.getTextEncoding() != paint.getTextEncoding()) {
656 last = ptr;
657 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000658 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000659 }
660 if (base.getHinting() != paint.getHinting()) {
661 last = ptr;
662 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000663 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000664 }
665 if (base.getTextAlign() != paint.getTextAlign()) {
666 last = ptr;
667 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000668 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000669 }
670 if (base.getTextSize() != paint.getTextSize()) {
671 last = ptr;
672 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
673 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000674 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000675 }
676 if (base.getTextScaleX() != paint.getTextScaleX()) {
677 last = ptr;
678 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
679 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000680 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000681 }
682 if (base.getTextSkewX() != paint.getTextSkewX()) {
683 last = ptr;
684 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
685 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +0000686 base.setTextSkewX(paint.getTextSkewX());
687 }
688
689 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
690 uint32_t id = this->getTypefaceID(paint.getTypeface());
691 last = ptr;
692 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
693 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +0000694 }
reed@google.combb6992a2011-04-26 17:41:56 +0000695
reed@google.comacd471f2011-05-03 21:26:46 +0000696 size_t size = (char*)ptr - (char*)storage;
697 if (size && this->needOpBytes(size)) {
reed@google.combb6992a2011-04-26 17:41:56 +0000698 this->writeOp(kPaintOp_DrawOp, 0, 0);
699 size_t size = (char*)ptr - (char*)storage;
700 *last |= kLastOp_PaintOpFlag << PAINTOPS_DATA_BITS;
701 fWriter.write(storage, (char*)ptr - (char*)storage);
702 for (size_t i = 0; i < size/4; i++) {
703 SkDebugf("[%d] %08X\n", i, storage[i]);
704 }
705 }
706 return 0;
707}
708
709///////////////////////////////////////////////////////////////////////////////
710
711#include "SkGPipe.h"
712
reed@google.comacd471f2011-05-03 21:26:46 +0000713SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +0000714 fCanvas = NULL;
715}
716
717SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +0000718 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +0000719 SkSafeUnref(fCanvas);
720}
721
reed@google.comacd471f2011-05-03 21:26:46 +0000722SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller) {
reed@google.combb6992a2011-04-26 17:41:56 +0000723 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +0000724 fWriter.reset(NULL, 0);
725 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter));
reed@google.combb6992a2011-04-26 17:41:56 +0000726 }
727 return fCanvas;
728}
729
730void SkGPipeWriter::endRecording() {
731 if (fCanvas) {
732 fCanvas->finish();
733 fCanvas->unref();
734 fCanvas = NULL;
735 }
736}
737