blob: f0238cab0ac5f106908efde2e4ce71f68db88ce8 [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"
19#include "SkPaint.h"
reed@google.comacd471f2011-05-03 21:26:46 +000020#include "SkGPipe.h"
reed@google.combb6992a2011-04-26 17:41:56 +000021#include "SkGPipePriv.h"
reed@google.comf5842f72011-05-04 18:30:04 +000022#include "SkStream.h"
23#include "SkTypeface.h"
reed@google.combb6992a2011-04-26 17:41:56 +000024#include "SkWriter32.h"
25
reed@google.comacd471f2011-05-03 21:26:46 +000026static size_t estimateFlattenSize(const SkPath& path) {
27 int n = path.countPoints();
28 size_t bytes = 3 * sizeof(int32_t);
29 bytes += n * sizeof(SkPoint);
30 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras
31
32#ifdef SK_DEBUG
33 {
34 SkWriter32 writer(1024);
35 path.flatten(writer);
36 SkASSERT(writer.size() <= bytes);
37 }
38#endif
39 return bytes;
40}
41
reed@google.combb6992a2011-04-26 17:41:56 +000042static void writeRegion(SkWriter32* writer, const SkRegion& rgn) {
43 size_t size = rgn.flatten(NULL);
44 SkASSERT(SkAlign4(size) == size);
45 rgn.flatten(writer->reserve(size));
46}
47
48static void writeMatrix(SkWriter32* writer, const SkMatrix& matrix) {
49 size_t size = matrix.flatten(NULL);
50 SkASSERT(SkAlign4(size) == size);
51 matrix.flatten(writer->reserve(size));
52}
53
reed@google.comf5842f72011-05-04 18:30:04 +000054static size_t writeTypeface(SkWriter32* writer, SkTypeface* typeface) {
55 SkASSERT(typeface);
56 SkDynamicMemoryWStream stream;
57 typeface->serialize(&stream);
58 size_t size = stream.getOffset();
59 if (writer) {
60 writer->write32(size);
61 writer->write(stream.getStream(), size);
62 }
63 return 4 + size;
64}
65
reed@google.combb6992a2011-04-26 17:41:56 +000066///////////////////////////////////////////////////////////////////////////////
67
68class SkGPipeCanvas : public SkCanvas {
69public:
reed@google.comacd471f2011-05-03 21:26:46 +000070 SkGPipeCanvas(SkGPipeController*, SkWriter32*);
reed@google.combb6992a2011-04-26 17:41:56 +000071 virtual ~SkGPipeCanvas();
72
73 void finish() {
74 if (!fDone) {
75 this->writeOp(kDone_DrawOp);
76 fDone = true;
77 }
78 }
79
80 // overrides from SkCanvas
81 virtual int save(SaveFlags);
82 virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
83 virtual void restore();
84 virtual bool translate(SkScalar dx, SkScalar dy);
85 virtual bool scale(SkScalar sx, SkScalar sy);
86 virtual bool rotate(SkScalar degrees);
87 virtual bool skew(SkScalar sx, SkScalar sy);
88 virtual bool concat(const SkMatrix& matrix);
89 virtual void setMatrix(const SkMatrix& matrix);
90 virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
91 virtual bool clipPath(const SkPath& path, SkRegion::Op op);
92 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
93 virtual void clear(SkColor);
94 virtual void drawPaint(const SkPaint& paint);
95 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
96 const SkPaint&);
97 virtual void drawRect(const SkRect& rect, const SkPaint&);
98 virtual void drawPath(const SkPath& path, const SkPaint&);
99 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
100 const SkPaint*);
101 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
102 const SkRect& dst, const SkPaint*);
103 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
104 const SkPaint*);
105 virtual void drawSprite(const SkBitmap&, int left, int top,
106 const SkPaint*);
107 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
108 SkScalar y, const SkPaint&);
109 virtual void drawPosText(const void* text, size_t byteLength,
110 const SkPoint pos[], const SkPaint&);
111 virtual void drawPosTextH(const void* text, size_t byteLength,
112 const SkScalar xpos[], SkScalar constY, const SkPaint&);
113 virtual void drawTextOnPath(const void* text, size_t byteLength,
114 const SkPath& path, const SkMatrix* matrix,
115 const SkPaint&);
116 virtual void drawPicture(SkPicture& picture);
117 virtual void drawShape(SkShape*);
118 virtual void drawVertices(VertexMode, int vertexCount,
119 const SkPoint vertices[], const SkPoint texs[],
120 const SkColor colors[], SkXfermode*,
121 const uint16_t indices[], int indexCount,
122 const SkPaint&);
123 virtual void drawData(const void*, size_t);
124
125private:
reed@google.comacd471f2011-05-03 21:26:46 +0000126 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000127 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000128 size_t fBlockSize; // amount allocated for writer
129 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000130 bool fDone;
131
reed@google.comf5842f72011-05-04 18:30:04 +0000132 SkRefCntSet fTypefaceSet;
133
134 uint32_t getTypefaceID(SkTypeface*);
135
reed@google.comacd471f2011-05-03 21:26:46 +0000136 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000137 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
138 }
139
reed@google.comacd471f2011-05-03 21:26:46 +0000140 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000141 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
142 }
reed@google.comacd471f2011-05-03 21:26:46 +0000143
144 bool needOpBytes(size_t size = 0);
145
146 inline void doNotify() {
147 if (!fDone) {
148 size_t bytes = fWriter.size() - fBytesNotified;
149 fController->notifyWritten(bytes);
150 fBytesNotified += bytes;
151 }
152 }
reed@google.combb6992a2011-04-26 17:41:56 +0000153
154 SkTDArray<SkPaint*> fPaints;
155 unsigned writePaint(const SkPaint&);
156
reed@google.comacd471f2011-05-03 21:26:46 +0000157 class AutoPipeNotify {
158 public:
159 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
160 ~AutoPipeNotify() { fCanvas->doNotify(); }
161 private:
162 SkGPipeCanvas* fCanvas;
163 };
164 friend class AutoPipeNotify;
165
reed@google.combb6992a2011-04-26 17:41:56 +0000166 typedef SkCanvas INHERITED;
167};
168
169///////////////////////////////////////////////////////////////////////////////
170
reed@google.comacd471f2011-05-03 21:26:46 +0000171#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000172
reed@google.comacd471f2011-05-03 21:26:46 +0000173SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
174 SkWriter32* writer) : fWriter(*writer) {
175 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000176 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000177 fBlockSize = 0; // need first block from controller
178
reed@google.combb6992a2011-04-26 17:41:56 +0000179 // always begin with 1 default paint
180 *fPaints.append() = SkNEW(SkPaint);
181}
182
183SkGPipeCanvas::~SkGPipeCanvas() {
184 this->finish();
185
186 fPaints.deleteAll();
187}
188
reed@google.comacd471f2011-05-03 21:26:46 +0000189bool SkGPipeCanvas::needOpBytes(size_t needed) {
190 if (fDone) {
191 return false;
192 }
193
194 needed += 4; // size of DrawOp atom
195 if (fWriter.size() + needed > fBlockSize) {
196 void* block = fController->requestBlock(MIN_BLOCK_SIZE, &fBlockSize);
197 if (NULL == block) {
198 fDone = true;
199 return false;
200 }
201 fWriter.reset(block, fBlockSize);
202 fBytesNotified = 0;
203 }
204 return true;
205}
206
reed@google.comf5842f72011-05-04 18:30:04 +0000207uint32_t SkGPipeCanvas::getTypefaceID(SkTypeface* face) {
208 uint32_t id = 0; // 0 means default/null typeface
209 if (face) {
210 id = fTypefaceSet.find(face);
211 if (0 == id) {
212 id = fTypefaceSet.add(face);
213 size_t size = writeTypeface(NULL, face);
214 if (this->needOpBytes(size)) {
215 this->writeOp(kDefineTypeface_DrawOp);
216 writeTypeface(&fWriter, face);
217 }
218 }
219 }
220 return id;
221}
222
reed@google.combb6992a2011-04-26 17:41:56 +0000223///////////////////////////////////////////////////////////////////////////////
224
reed@google.comacd471f2011-05-03 21:26:46 +0000225#define NOTIFY_SETUP(canvas) \
226 AutoPipeNotify apn(canvas)
227
reed@google.combb6992a2011-04-26 17:41:56 +0000228int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000229 NOTIFY_SETUP(this);
230 if (this->needOpBytes()) {
231 this->writeOp(kSave_DrawOp, 0, flags);
232 }
reed@google.combb6992a2011-04-26 17:41:56 +0000233 return this->INHERITED::save(flags);
234}
235
236int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
237 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000238 NOTIFY_SETUP(this);
239 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000240 unsigned index = 0; // just to avoid the warning
241 unsigned opFlags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000242
reed@google.combb6992a2011-04-26 17:41:56 +0000243 if (bounds) {
244 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000245 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000246 }
247 if (paint) {
248 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
249 index = this->writePaint(*paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000250 size += 4;
reed@google.combb6992a2011-04-26 17:41:56 +0000251 }
252
reed@google.comacd471f2011-05-03 21:26:46 +0000253 if (this->needOpBytes(size)) {
254 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
255 if (bounds) {
256 fWriter.writeRect(*bounds);
257 }
258 if (paint) {
259 fWriter.write32(index);
260 }
reed@google.combb6992a2011-04-26 17:41:56 +0000261 }
262
263 // we just pass on the save, so we don't create a layer
264 return this->INHERITED::save(saveFlags);
265}
266
267void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000268 NOTIFY_SETUP(this);
269 if (this->needOpBytes()) {
270 this->writeOp(kRestore_DrawOp);
271 }
reed@google.combb6992a2011-04-26 17:41:56 +0000272 this->INHERITED::restore();
273}
274
275bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
276 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000277 NOTIFY_SETUP(this);
278 if (this->needOpBytes(2 * sizeof(SkScalar))) {
279 this->writeOp(kTranslate_DrawOp);
280 fWriter.writeScalar(dx);
281 fWriter.writeScalar(dy);
282 }
reed@google.combb6992a2011-04-26 17:41:56 +0000283 }
284 return this->INHERITED::translate(dx, dy);
285}
286
287bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
288 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000289 NOTIFY_SETUP(this);
290 if (this->needOpBytes(2 * sizeof(SkScalar))) {
291 this->writeOp(kScale_DrawOp);
292 fWriter.writeScalar(sx);
293 fWriter.writeScalar(sy);
294 }
reed@google.combb6992a2011-04-26 17:41:56 +0000295 }
296 return this->INHERITED::scale(sx, sy);
297}
298
299bool SkGPipeCanvas::rotate(SkScalar degrees) {
300 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000301 NOTIFY_SETUP(this);
302 if (this->needOpBytes(sizeof(SkScalar))) {
303 this->writeOp(kRotate_DrawOp);
304 fWriter.writeScalar(degrees);
305 }
reed@google.combb6992a2011-04-26 17:41:56 +0000306 }
307 return this->INHERITED::rotate(degrees);
308}
309
310bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
311 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000312 NOTIFY_SETUP(this);
313 if (this->needOpBytes(2 * sizeof(SkScalar))) {
314 this->writeOp(kSkew_DrawOp);
315 fWriter.writeScalar(sx);
316 fWriter.writeScalar(sy);
317 }
reed@google.combb6992a2011-04-26 17:41:56 +0000318 }
319 return this->INHERITED::skew(sx, sy);
320}
321
322bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
323 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000324 NOTIFY_SETUP(this);
325 if (this->needOpBytes(matrix.flatten(NULL))) {
326 this->writeOp(kConcat_DrawOp);
327 writeMatrix(&fWriter, matrix);
328 }
reed@google.combb6992a2011-04-26 17:41:56 +0000329 }
330 return this->INHERITED::concat(matrix);
331}
332
333void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000334 NOTIFY_SETUP(this);
335 if (this->needOpBytes(matrix.flatten(NULL))) {
336 this->writeOp(kSetMatrix_DrawOp);
337 writeMatrix(&fWriter, matrix);
338 }
reed@google.combb6992a2011-04-26 17:41:56 +0000339 this->INHERITED::setMatrix(matrix);
340}
341
342bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000343 NOTIFY_SETUP(this);
344 if (this->needOpBytes(sizeof(SkRect))) {
345 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
346 fWriter.writeRect(rect);
347 }
reed@google.combb6992a2011-04-26 17:41:56 +0000348 return this->INHERITED::clipRect(rect, rgnOp);
349}
350
351bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000352 NOTIFY_SETUP(this);
353 if (this->needOpBytes(estimateFlattenSize(path))) {
354 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
355 path.flatten(fWriter);
356 }
reed@google.combb6992a2011-04-26 17:41:56 +0000357 // we just pass on the bounds of the path
358 return this->INHERITED::clipRect(path.getBounds(), rgnOp);
359}
360
361bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000362 NOTIFY_SETUP(this);
363 if (this->needOpBytes(region.flatten(NULL))) {
364 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
365 writeRegion(&fWriter, region);
366 }
reed@google.combb6992a2011-04-26 17:41:56 +0000367 return this->INHERITED::clipRegion(region, rgnOp);
368}
369
370///////////////////////////////////////////////////////////////////////////////
371
372void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000373 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000374 unsigned flags = 0;
375 if (color) {
376 flags |= kClear_HasColor_DrawOpFlag;
377 }
reed@google.comacd471f2011-05-03 21:26:46 +0000378 if (this->needOpBytes(sizeof(SkColor))) {
379 this->writeOp(kDrawClear_DrawOp, flags, 0);
380 if (color) {
381 fWriter.write32(color);
382 }
reed@google.combb6992a2011-04-26 17:41:56 +0000383 }
384}
385
386void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000387 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000388 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000389 if (this->needOpBytes()) {
390 this->writeOp(kDrawPaint_DrawOp, 0, paintIndex);
391 }
reed@google.combb6992a2011-04-26 17:41:56 +0000392}
393
394void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
395 const SkPoint pts[], const SkPaint& paint) {
396 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000397 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000398 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000399 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
400 this->writeOp(kDrawPoints_DrawOp, mode, paintIndex);
401 fWriter.write32(count);
402 fWriter.write(pts, count * sizeof(SkPoint));
403 }
reed@google.combb6992a2011-04-26 17:41:56 +0000404 }
405}
406
407void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000408 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000409 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000410 if (this->needOpBytes(sizeof(SkRect))) {
411 this->writeOp(kDrawRect_DrawOp, 0, paintIndex);
412 fWriter.writeRect(rect);
413 }
reed@google.combb6992a2011-04-26 17:41:56 +0000414}
415
416void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000417 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000418 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000419 if (this->needOpBytes(estimateFlattenSize(path))) {
420 this->writeOp(kDrawPath_DrawOp, 0, paintIndex);
421 path.flatten(fWriter);
422 }
reed@google.combb6992a2011-04-26 17:41:56 +0000423}
424
425void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
426 const SkPaint*) {
427 UNIMPLEMENTED
428}
429
430void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
431 const SkRect& dst, const SkPaint*) {
432 UNIMPLEMENTED
433}
434
435void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
436 const SkPaint*) {
437 UNIMPLEMENTED
438}
439
440void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
441 const SkPaint*) {
442 UNIMPLEMENTED
443}
444
445void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
446 SkScalar y, const SkPaint& paint) {
447 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000448 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000449 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000450 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
451 this->writeOp(kDrawText_DrawOp, 0, paintIndex);
452 fWriter.write32(byteLength);
453 fWriter.writePad(text, byteLength);
454 fWriter.writeScalar(x);
455 fWriter.writeScalar(y);
456 }
reed@google.combb6992a2011-04-26 17:41:56 +0000457 }
458}
459
460void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
461 const SkPoint pos[], const SkPaint& paint) {
462 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000463 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000464 unsigned paintIndex = this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000465 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000466 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
467 this->writeOp(kDrawPosText_DrawOp, 0, paintIndex);
468 fWriter.write32(byteLength);
469 fWriter.writePad(text, byteLength);
470 fWriter.write32(count);
471 fWriter.write(pos, count * sizeof(SkPoint));
472 }
reed@google.combb6992a2011-04-26 17:41:56 +0000473 }
474}
475
476void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
477 const SkScalar xpos[], SkScalar constY,
478 const SkPaint& paint) {
479 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000480 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000481 unsigned paintIndex = this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000482 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000483 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
484 this->writeOp(kDrawPosTextH_DrawOp, 0, paintIndex);
485 fWriter.write32(byteLength);
486 fWriter.writePad(text, byteLength);
487 fWriter.write32(count);
488 fWriter.write(xpos, count * sizeof(SkScalar));
489 fWriter.writeScalar(constY);
490 }
reed@google.combb6992a2011-04-26 17:41:56 +0000491 }
492}
493
494void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
495 const SkPath& path, const SkMatrix* matrix,
496 const SkPaint& paint) {
497 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000498 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000499 unsigned flags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000500 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
reed@google.combb6992a2011-04-26 17:41:56 +0000501 if (matrix) {
502 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000503 size += matrix->flatten(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000504 }
505 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000506 if (this->needOpBytes(size)) {
507 this->writeOp(kDrawTextOnPath_DrawOp, flags, paintIndex);
reed@google.combb6992a2011-04-26 17:41:56 +0000508
reed@google.comacd471f2011-05-03 21:26:46 +0000509 fWriter.write32(byteLength);
510 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000511
reed@google.comacd471f2011-05-03 21:26:46 +0000512 path.flatten(fWriter);
513 if (matrix) {
514 writeMatrix(&fWriter, *matrix);
515 }
reed@google.combb6992a2011-04-26 17:41:56 +0000516 }
517 }
518}
519
520void SkGPipeCanvas::drawPicture(SkPicture& picture) {
521 UNIMPLEMENTED
522}
523
524void SkGPipeCanvas::drawShape(SkShape* shape) {
525 UNIMPLEMENTED
526}
527
528void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
529 const SkPoint vertices[], const SkPoint texs[],
530 const SkColor colors[], SkXfermode*,
531 const uint16_t indices[], int indexCount,
532 const SkPaint& paint) {
533 if (0 == vertexCount) {
534 return;
535 }
536
reed@google.comacd471f2011-05-03 21:26:46 +0000537 NOTIFY_SETUP(this);
538 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000539 unsigned paintIndex = this->writePaint(paint);
540 unsigned flags = 0;
541 if (texs) {
542 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000543 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000544 }
545 if (colors) {
546 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000547 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000548 }
549 if (indices && indexCount > 0) {
550 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000551 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000552 }
553
reed@google.comacd471f2011-05-03 21:26:46 +0000554 if (this->needOpBytes(size)) {
555 this->writeOp(kDrawVertices_DrawOp, flags, paintIndex);
556 fWriter.write32(mode);
557 fWriter.write32(vertexCount);
558 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
559 if (texs) {
560 fWriter.write(texs, vertexCount * sizeof(SkPoint));
561 }
562 if (colors) {
563 fWriter.write(colors, vertexCount * sizeof(SkColor));
564 }
reed@google.combb6992a2011-04-26 17:41:56 +0000565
reed@google.comacd471f2011-05-03 21:26:46 +0000566 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000567
reed@google.comacd471f2011-05-03 21:26:46 +0000568 if (indices && indexCount > 0) {
569 fWriter.write32(indexCount);
570 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
571 }
reed@google.combb6992a2011-04-26 17:41:56 +0000572 }
573}
574
reed@google.comacd471f2011-05-03 21:26:46 +0000575void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
576 if (size && ptr) {
577 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000578 unsigned data = 0;
579 if (size < (1 << DRAWOPS_DATA_BITS)) {
580 data = (unsigned)size;
581 }
reed@google.comacd471f2011-05-03 21:26:46 +0000582 if (this->needOpBytes(4 + SkAlign4(size))) {
583 this->writeOp(kDrawData_DrawOp, 0, data);
584 if (0 == data) {
585 fWriter.write32(size);
586 }
587 fWriter.write(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000588 }
589 }
590}
591
592///////////////////////////////////////////////////////////////////////////////
593
594template <typename T> uint32_t castToU32(T value) {
595 union {
596 T fSrc;
597 uint32_t fDst;
598 } data;
599 data.fSrc = value;
600 return data.fDst;
601}
602
603unsigned SkGPipeCanvas::writePaint(const SkPaint& paint) {
reed@google.comf5842f72011-05-04 18:30:04 +0000604 SkPaint& base = *fPaints[0];
reed@google.combb6992a2011-04-26 17:41:56 +0000605 uint32_t storage[32];
606 uint32_t* ptr = storage;
607 uint32_t* last = NULL;
608
609 if (base.getFlags() != paint.getFlags()) {
610 last = ptr;
611 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
reed@google.comf5842f72011-05-04 18:30:04 +0000612 base.setFlags(paint.getFlags());
reed@google.combb6992a2011-04-26 17:41:56 +0000613 }
614 if (base.getColor() != paint.getColor()) {
615 last = ptr;
616 *ptr++ = PaintOp_packOp(kColor_PaintOp);
617 *ptr++ = paint.getColor();
reed@google.comf5842f72011-05-04 18:30:04 +0000618 base.setColor(paint.getColor());
reed@google.combb6992a2011-04-26 17:41:56 +0000619 }
620 if (base.getStyle() != paint.getStyle()) {
621 last = ptr;
622 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
reed@google.comf5842f72011-05-04 18:30:04 +0000623 base.setStyle(paint.getStyle());
reed@google.combb6992a2011-04-26 17:41:56 +0000624 }
625 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
626 last = ptr;
627 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
reed@google.comf5842f72011-05-04 18:30:04 +0000628 base.setStrokeJoin(paint.getStrokeJoin());
reed@google.combb6992a2011-04-26 17:41:56 +0000629 }
630 if (base.getStrokeCap() != paint.getStrokeCap()) {
631 last = ptr;
632 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
reed@google.comf5842f72011-05-04 18:30:04 +0000633 base.setStrokeCap(paint.getStrokeCap());
reed@google.combb6992a2011-04-26 17:41:56 +0000634 }
635 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
636 last = ptr;
637 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
638 *ptr++ = castToU32(paint.getStrokeWidth());
reed@google.comf5842f72011-05-04 18:30:04 +0000639 base.setStrokeWidth(paint.getStrokeWidth());
reed@google.combb6992a2011-04-26 17:41:56 +0000640 }
641 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
642 last = ptr;
643 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
644 *ptr++ = castToU32(paint.getStrokeMiter());
reed@google.comf5842f72011-05-04 18:30:04 +0000645 base.setStrokeMiter(paint.getStrokeMiter());
reed@google.combb6992a2011-04-26 17:41:56 +0000646 }
647 if (base.getTextEncoding() != paint.getTextEncoding()) {
648 last = ptr;
649 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
reed@google.comf5842f72011-05-04 18:30:04 +0000650 base.setTextEncoding(paint.getTextEncoding());
reed@google.combb6992a2011-04-26 17:41:56 +0000651 }
652 if (base.getHinting() != paint.getHinting()) {
653 last = ptr;
654 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
reed@google.comf5842f72011-05-04 18:30:04 +0000655 base.setHinting(paint.getHinting());
reed@google.combb6992a2011-04-26 17:41:56 +0000656 }
657 if (base.getTextAlign() != paint.getTextAlign()) {
658 last = ptr;
659 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
reed@google.comf5842f72011-05-04 18:30:04 +0000660 base.setTextAlign(paint.getTextAlign());
reed@google.combb6992a2011-04-26 17:41:56 +0000661 }
662 if (base.getTextSize() != paint.getTextSize()) {
663 last = ptr;
664 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
665 *ptr++ = castToU32(paint.getTextSize());
reed@google.comf5842f72011-05-04 18:30:04 +0000666 base.setTextSize(paint.getTextSize());
reed@google.combb6992a2011-04-26 17:41:56 +0000667 }
668 if (base.getTextScaleX() != paint.getTextScaleX()) {
669 last = ptr;
670 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
671 *ptr++ = castToU32(paint.getTextScaleX());
reed@google.comf5842f72011-05-04 18:30:04 +0000672 base.setTextScaleX(paint.getTextScaleX());
reed@google.combb6992a2011-04-26 17:41:56 +0000673 }
674 if (base.getTextSkewX() != paint.getTextSkewX()) {
675 last = ptr;
676 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
677 *ptr++ = castToU32(paint.getTextSkewX());
reed@google.comf5842f72011-05-04 18:30:04 +0000678 base.setTextSkewX(paint.getTextSkewX());
679 }
680
681 if (!SkTypeface::Equal(base.getTypeface(), paint.getTypeface())) {
682 uint32_t id = this->getTypefaceID(paint.getTypeface());
683 last = ptr;
684 *ptr++ = PaintOp_packOpData(kTypeface_PaintOp, id);
685 base.setTypeface(paint.getTypeface());
reed@google.combb6992a2011-04-26 17:41:56 +0000686 }
reed@google.combb6992a2011-04-26 17:41:56 +0000687
reed@google.comacd471f2011-05-03 21:26:46 +0000688 size_t size = (char*)ptr - (char*)storage;
689 if (size && this->needOpBytes(size)) {
reed@google.combb6992a2011-04-26 17:41:56 +0000690 this->writeOp(kPaintOp_DrawOp, 0, 0);
691 size_t size = (char*)ptr - (char*)storage;
692 *last |= kLastOp_PaintOpFlag << PAINTOPS_DATA_BITS;
693 fWriter.write(storage, (char*)ptr - (char*)storage);
694 for (size_t i = 0; i < size/4; i++) {
695 SkDebugf("[%d] %08X\n", i, storage[i]);
696 }
697 }
698 return 0;
699}
700
701///////////////////////////////////////////////////////////////////////////////
702
703#include "SkGPipe.h"
704
reed@google.comacd471f2011-05-03 21:26:46 +0000705SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +0000706 fCanvas = NULL;
707}
708
709SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +0000710 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +0000711 SkSafeUnref(fCanvas);
712}
713
reed@google.comacd471f2011-05-03 21:26:46 +0000714SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller) {
reed@google.combb6992a2011-04-26 17:41:56 +0000715 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +0000716 fWriter.reset(NULL, 0);
717 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter));
reed@google.combb6992a2011-04-26 17:41:56 +0000718 }
719 return fCanvas;
720}
721
722void SkGPipeWriter::endRecording() {
723 if (fCanvas) {
724 fCanvas->finish();
725 fCanvas->unref();
726 fCanvas = NULL;
727 }
728}
729