blob: 03a0251471a4b8709c974edf96f31b2864ad3595 [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.combb6992a2011-04-26 17:41:56 +000022#include "SkWriter32.h"
23
reed@google.comacd471f2011-05-03 21:26:46 +000024static size_t estimateFlattenSize(const SkPath& path) {
25 int n = path.countPoints();
26 size_t bytes = 3 * sizeof(int32_t);
27 bytes += n * sizeof(SkPoint);
28 bytes += SkAlign4(n + 2); // verbs: add 2 for move/close extras
29
30#ifdef SK_DEBUG
31 {
32 SkWriter32 writer(1024);
33 path.flatten(writer);
34 SkASSERT(writer.size() <= bytes);
35 }
36#endif
37 return bytes;
38}
39
reed@google.combb6992a2011-04-26 17:41:56 +000040static void writeRegion(SkWriter32* writer, const SkRegion& rgn) {
41 size_t size = rgn.flatten(NULL);
42 SkASSERT(SkAlign4(size) == size);
43 rgn.flatten(writer->reserve(size));
44}
45
46static void writeMatrix(SkWriter32* writer, const SkMatrix& matrix) {
47 size_t size = matrix.flatten(NULL);
48 SkASSERT(SkAlign4(size) == size);
49 matrix.flatten(writer->reserve(size));
50}
51
52///////////////////////////////////////////////////////////////////////////////
53
54class SkGPipeCanvas : public SkCanvas {
55public:
reed@google.comacd471f2011-05-03 21:26:46 +000056 SkGPipeCanvas(SkGPipeController*, SkWriter32*);
reed@google.combb6992a2011-04-26 17:41:56 +000057 virtual ~SkGPipeCanvas();
58
59 void finish() {
60 if (!fDone) {
61 this->writeOp(kDone_DrawOp);
62 fDone = true;
63 }
64 }
65
66 // overrides from SkCanvas
67 virtual int save(SaveFlags);
68 virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
69 virtual void restore();
70 virtual bool translate(SkScalar dx, SkScalar dy);
71 virtual bool scale(SkScalar sx, SkScalar sy);
72 virtual bool rotate(SkScalar degrees);
73 virtual bool skew(SkScalar sx, SkScalar sy);
74 virtual bool concat(const SkMatrix& matrix);
75 virtual void setMatrix(const SkMatrix& matrix);
76 virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
77 virtual bool clipPath(const SkPath& path, SkRegion::Op op);
78 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
79 virtual void clear(SkColor);
80 virtual void drawPaint(const SkPaint& paint);
81 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
82 const SkPaint&);
83 virtual void drawRect(const SkRect& rect, const SkPaint&);
84 virtual void drawPath(const SkPath& path, const SkPaint&);
85 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
86 const SkPaint*);
87 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
88 const SkRect& dst, const SkPaint*);
89 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
90 const SkPaint*);
91 virtual void drawSprite(const SkBitmap&, int left, int top,
92 const SkPaint*);
93 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
94 SkScalar y, const SkPaint&);
95 virtual void drawPosText(const void* text, size_t byteLength,
96 const SkPoint pos[], const SkPaint&);
97 virtual void drawPosTextH(const void* text, size_t byteLength,
98 const SkScalar xpos[], SkScalar constY, const SkPaint&);
99 virtual void drawTextOnPath(const void* text, size_t byteLength,
100 const SkPath& path, const SkMatrix* matrix,
101 const SkPaint&);
102 virtual void drawPicture(SkPicture& picture);
103 virtual void drawShape(SkShape*);
104 virtual void drawVertices(VertexMode, int vertexCount,
105 const SkPoint vertices[], const SkPoint texs[],
106 const SkColor colors[], SkXfermode*,
107 const uint16_t indices[], int indexCount,
108 const SkPaint&);
109 virtual void drawData(const void*, size_t);
110
111private:
reed@google.comacd471f2011-05-03 21:26:46 +0000112 SkGPipeController* fController;
reed@google.combb6992a2011-04-26 17:41:56 +0000113 SkWriter32& fWriter;
reed@google.comacd471f2011-05-03 21:26:46 +0000114 size_t fBlockSize; // amount allocated for writer
115 size_t fBytesNotified;
reed@google.combb6992a2011-04-26 17:41:56 +0000116 bool fDone;
117
reed@google.comacd471f2011-05-03 21:26:46 +0000118 inline void writeOp(DrawOps op, unsigned flags, unsigned data) {
reed@google.combb6992a2011-04-26 17:41:56 +0000119 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
120 }
121
reed@google.comacd471f2011-05-03 21:26:46 +0000122 inline void writeOp(DrawOps op) {
reed@google.combb6992a2011-04-26 17:41:56 +0000123 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
124 }
reed@google.comacd471f2011-05-03 21:26:46 +0000125
126 bool needOpBytes(size_t size = 0);
127
128 inline void doNotify() {
129 if (!fDone) {
130 size_t bytes = fWriter.size() - fBytesNotified;
131 fController->notifyWritten(bytes);
132 fBytesNotified += bytes;
133 }
134 }
reed@google.combb6992a2011-04-26 17:41:56 +0000135
136 SkTDArray<SkPaint*> fPaints;
137 unsigned writePaint(const SkPaint&);
138
reed@google.comacd471f2011-05-03 21:26:46 +0000139 class AutoPipeNotify {
140 public:
141 AutoPipeNotify(SkGPipeCanvas* canvas) : fCanvas(canvas) {}
142 ~AutoPipeNotify() { fCanvas->doNotify(); }
143 private:
144 SkGPipeCanvas* fCanvas;
145 };
146 friend class AutoPipeNotify;
147
reed@google.combb6992a2011-04-26 17:41:56 +0000148 typedef SkCanvas INHERITED;
149};
150
151///////////////////////////////////////////////////////////////////////////////
152
reed@google.comacd471f2011-05-03 21:26:46 +0000153#define MIN_BLOCK_SIZE (16 * 1024)
reed@google.combb6992a2011-04-26 17:41:56 +0000154
reed@google.comacd471f2011-05-03 21:26:46 +0000155SkGPipeCanvas::SkGPipeCanvas(SkGPipeController* controller,
156 SkWriter32* writer) : fWriter(*writer) {
157 fController = controller;
reed@google.combb6992a2011-04-26 17:41:56 +0000158 fDone = false;
reed@google.comacd471f2011-05-03 21:26:46 +0000159 fBlockSize = 0; // need first block from controller
160
reed@google.combb6992a2011-04-26 17:41:56 +0000161 // always begin with 1 default paint
162 *fPaints.append() = SkNEW(SkPaint);
163}
164
165SkGPipeCanvas::~SkGPipeCanvas() {
166 this->finish();
167
168 fPaints.deleteAll();
169}
170
reed@google.comacd471f2011-05-03 21:26:46 +0000171bool SkGPipeCanvas::needOpBytes(size_t needed) {
172 if (fDone) {
173 return false;
174 }
175
176 needed += 4; // size of DrawOp atom
177 if (fWriter.size() + needed > fBlockSize) {
178 void* block = fController->requestBlock(MIN_BLOCK_SIZE, &fBlockSize);
179 if (NULL == block) {
180 fDone = true;
181 return false;
182 }
183 fWriter.reset(block, fBlockSize);
184 fBytesNotified = 0;
185 }
186 return true;
187}
188
reed@google.combb6992a2011-04-26 17:41:56 +0000189///////////////////////////////////////////////////////////////////////////////
190
reed@google.comacd471f2011-05-03 21:26:46 +0000191#define NOTIFY_SETUP(canvas) \
192 AutoPipeNotify apn(canvas)
193
reed@google.combb6992a2011-04-26 17:41:56 +0000194int SkGPipeCanvas::save(SaveFlags flags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000195 NOTIFY_SETUP(this);
196 if (this->needOpBytes()) {
197 this->writeOp(kSave_DrawOp, 0, flags);
198 }
reed@google.combb6992a2011-04-26 17:41:56 +0000199 return this->INHERITED::save(flags);
200}
201
202int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
203 SaveFlags saveFlags) {
reed@google.comacd471f2011-05-03 21:26:46 +0000204 NOTIFY_SETUP(this);
205 size_t size = 0;
reed@google.combb6992a2011-04-26 17:41:56 +0000206 unsigned index = 0; // just to avoid the warning
207 unsigned opFlags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000208
reed@google.combb6992a2011-04-26 17:41:56 +0000209 if (bounds) {
210 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000211 size += sizeof(SkRect);
reed@google.combb6992a2011-04-26 17:41:56 +0000212 }
213 if (paint) {
214 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
215 index = this->writePaint(*paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000216 size += 4;
reed@google.combb6992a2011-04-26 17:41:56 +0000217 }
218
reed@google.comacd471f2011-05-03 21:26:46 +0000219 if (this->needOpBytes(size)) {
220 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
221 if (bounds) {
222 fWriter.writeRect(*bounds);
223 }
224 if (paint) {
225 fWriter.write32(index);
226 }
reed@google.combb6992a2011-04-26 17:41:56 +0000227 }
228
229 // we just pass on the save, so we don't create a layer
230 return this->INHERITED::save(saveFlags);
231}
232
233void SkGPipeCanvas::restore() {
reed@google.comacd471f2011-05-03 21:26:46 +0000234 NOTIFY_SETUP(this);
235 if (this->needOpBytes()) {
236 this->writeOp(kRestore_DrawOp);
237 }
reed@google.combb6992a2011-04-26 17:41:56 +0000238 this->INHERITED::restore();
239}
240
241bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
242 if (dx || dy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000243 NOTIFY_SETUP(this);
244 if (this->needOpBytes(2 * sizeof(SkScalar))) {
245 this->writeOp(kTranslate_DrawOp);
246 fWriter.writeScalar(dx);
247 fWriter.writeScalar(dy);
248 }
reed@google.combb6992a2011-04-26 17:41:56 +0000249 }
250 return this->INHERITED::translate(dx, dy);
251}
252
253bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
254 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000255 NOTIFY_SETUP(this);
256 if (this->needOpBytes(2 * sizeof(SkScalar))) {
257 this->writeOp(kScale_DrawOp);
258 fWriter.writeScalar(sx);
259 fWriter.writeScalar(sy);
260 }
reed@google.combb6992a2011-04-26 17:41:56 +0000261 }
262 return this->INHERITED::scale(sx, sy);
263}
264
265bool SkGPipeCanvas::rotate(SkScalar degrees) {
266 if (degrees) {
reed@google.comacd471f2011-05-03 21:26:46 +0000267 NOTIFY_SETUP(this);
268 if (this->needOpBytes(sizeof(SkScalar))) {
269 this->writeOp(kRotate_DrawOp);
270 fWriter.writeScalar(degrees);
271 }
reed@google.combb6992a2011-04-26 17:41:56 +0000272 }
273 return this->INHERITED::rotate(degrees);
274}
275
276bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
277 if (sx || sy) {
reed@google.comacd471f2011-05-03 21:26:46 +0000278 NOTIFY_SETUP(this);
279 if (this->needOpBytes(2 * sizeof(SkScalar))) {
280 this->writeOp(kSkew_DrawOp);
281 fWriter.writeScalar(sx);
282 fWriter.writeScalar(sy);
283 }
reed@google.combb6992a2011-04-26 17:41:56 +0000284 }
285 return this->INHERITED::skew(sx, sy);
286}
287
288bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
289 if (!matrix.isIdentity()) {
reed@google.comacd471f2011-05-03 21:26:46 +0000290 NOTIFY_SETUP(this);
291 if (this->needOpBytes(matrix.flatten(NULL))) {
292 this->writeOp(kConcat_DrawOp);
293 writeMatrix(&fWriter, matrix);
294 }
reed@google.combb6992a2011-04-26 17:41:56 +0000295 }
296 return this->INHERITED::concat(matrix);
297}
298
299void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
reed@google.comacd471f2011-05-03 21:26:46 +0000300 NOTIFY_SETUP(this);
301 if (this->needOpBytes(matrix.flatten(NULL))) {
302 this->writeOp(kSetMatrix_DrawOp);
303 writeMatrix(&fWriter, matrix);
304 }
reed@google.combb6992a2011-04-26 17:41:56 +0000305 this->INHERITED::setMatrix(matrix);
306}
307
308bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000309 NOTIFY_SETUP(this);
310 if (this->needOpBytes(sizeof(SkRect))) {
311 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
312 fWriter.writeRect(rect);
313 }
reed@google.combb6992a2011-04-26 17:41:56 +0000314 return this->INHERITED::clipRect(rect, rgnOp);
315}
316
317bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000318 NOTIFY_SETUP(this);
319 if (this->needOpBytes(estimateFlattenSize(path))) {
320 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
321 path.flatten(fWriter);
322 }
reed@google.combb6992a2011-04-26 17:41:56 +0000323 // we just pass on the bounds of the path
324 return this->INHERITED::clipRect(path.getBounds(), rgnOp);
325}
326
327bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
reed@google.comacd471f2011-05-03 21:26:46 +0000328 NOTIFY_SETUP(this);
329 if (this->needOpBytes(region.flatten(NULL))) {
330 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
331 writeRegion(&fWriter, region);
332 }
reed@google.combb6992a2011-04-26 17:41:56 +0000333 return this->INHERITED::clipRegion(region, rgnOp);
334}
335
336///////////////////////////////////////////////////////////////////////////////
337
338void SkGPipeCanvas::clear(SkColor color) {
reed@google.comacd471f2011-05-03 21:26:46 +0000339 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000340 unsigned flags = 0;
341 if (color) {
342 flags |= kClear_HasColor_DrawOpFlag;
343 }
reed@google.comacd471f2011-05-03 21:26:46 +0000344 if (this->needOpBytes(sizeof(SkColor))) {
345 this->writeOp(kDrawClear_DrawOp, flags, 0);
346 if (color) {
347 fWriter.write32(color);
348 }
reed@google.combb6992a2011-04-26 17:41:56 +0000349 }
350}
351
352void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000353 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000354 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000355 if (this->needOpBytes()) {
356 this->writeOp(kDrawPaint_DrawOp, 0, paintIndex);
357 }
reed@google.combb6992a2011-04-26 17:41:56 +0000358}
359
360void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
361 const SkPoint pts[], const SkPaint& paint) {
362 if (count) {
reed@google.comacd471f2011-05-03 21:26:46 +0000363 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000364 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000365 if (this->needOpBytes(4 + count * sizeof(SkPoint))) {
366 this->writeOp(kDrawPoints_DrawOp, mode, paintIndex);
367 fWriter.write32(count);
368 fWriter.write(pts, count * sizeof(SkPoint));
369 }
reed@google.combb6992a2011-04-26 17:41:56 +0000370 }
371}
372
373void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000374 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000375 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000376 if (this->needOpBytes(sizeof(SkRect))) {
377 this->writeOp(kDrawRect_DrawOp, 0, paintIndex);
378 fWriter.writeRect(rect);
379 }
reed@google.combb6992a2011-04-26 17:41:56 +0000380}
381
382void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
reed@google.comacd471f2011-05-03 21:26:46 +0000383 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000384 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000385 if (this->needOpBytes(estimateFlattenSize(path))) {
386 this->writeOp(kDrawPath_DrawOp, 0, paintIndex);
387 path.flatten(fWriter);
388 }
reed@google.combb6992a2011-04-26 17:41:56 +0000389}
390
391void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
392 const SkPaint*) {
393 UNIMPLEMENTED
394}
395
396void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
397 const SkRect& dst, const SkPaint*) {
398 UNIMPLEMENTED
399}
400
401void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
402 const SkPaint*) {
403 UNIMPLEMENTED
404}
405
406void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
407 const SkPaint*) {
408 UNIMPLEMENTED
409}
410
411void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
412 SkScalar y, const SkPaint& paint) {
413 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000414 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000415 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000416 if (this->needOpBytes(4 + SkAlign4(byteLength) + 2 * sizeof(SkScalar))) {
417 this->writeOp(kDrawText_DrawOp, 0, paintIndex);
418 fWriter.write32(byteLength);
419 fWriter.writePad(text, byteLength);
420 fWriter.writeScalar(x);
421 fWriter.writeScalar(y);
422 }
reed@google.combb6992a2011-04-26 17:41:56 +0000423 }
424}
425
426void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
427 const SkPoint pos[], const SkPaint& paint) {
428 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000429 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000430 unsigned paintIndex = this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000431 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000432 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkPoint))) {
433 this->writeOp(kDrawPosText_DrawOp, 0, paintIndex);
434 fWriter.write32(byteLength);
435 fWriter.writePad(text, byteLength);
436 fWriter.write32(count);
437 fWriter.write(pos, count * sizeof(SkPoint));
438 }
reed@google.combb6992a2011-04-26 17:41:56 +0000439 }
440}
441
442void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
443 const SkScalar xpos[], SkScalar constY,
444 const SkPaint& paint) {
445 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000446 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000447 unsigned paintIndex = this->writePaint(paint);
reed@google.combb6992a2011-04-26 17:41:56 +0000448 int count = paint.textToGlyphs(text, byteLength, NULL);
reed@google.comacd471f2011-05-03 21:26:46 +0000449 if (this->needOpBytes(4 + SkAlign4(byteLength) + 4 + count * sizeof(SkScalar) + 4)) {
450 this->writeOp(kDrawPosTextH_DrawOp, 0, paintIndex);
451 fWriter.write32(byteLength);
452 fWriter.writePad(text, byteLength);
453 fWriter.write32(count);
454 fWriter.write(xpos, count * sizeof(SkScalar));
455 fWriter.writeScalar(constY);
456 }
reed@google.combb6992a2011-04-26 17:41:56 +0000457 }
458}
459
460void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
461 const SkPath& path, const SkMatrix* matrix,
462 const SkPaint& paint) {
463 if (byteLength) {
reed@google.comacd471f2011-05-03 21:26:46 +0000464 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000465 unsigned flags = 0;
reed@google.comacd471f2011-05-03 21:26:46 +0000466 size_t size = 4 + SkAlign4(byteLength) + estimateFlattenSize(path);
reed@google.combb6992a2011-04-26 17:41:56 +0000467 if (matrix) {
468 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000469 size += matrix->flatten(NULL);
reed@google.combb6992a2011-04-26 17:41:56 +0000470 }
471 unsigned paintIndex = this->writePaint(paint);
reed@google.comacd471f2011-05-03 21:26:46 +0000472 if (this->needOpBytes(size)) {
473 this->writeOp(kDrawTextOnPath_DrawOp, flags, paintIndex);
reed@google.combb6992a2011-04-26 17:41:56 +0000474
reed@google.comacd471f2011-05-03 21:26:46 +0000475 fWriter.write32(byteLength);
476 fWriter.writePad(text, byteLength);
reed@google.combb6992a2011-04-26 17:41:56 +0000477
reed@google.comacd471f2011-05-03 21:26:46 +0000478 path.flatten(fWriter);
479 if (matrix) {
480 writeMatrix(&fWriter, *matrix);
481 }
reed@google.combb6992a2011-04-26 17:41:56 +0000482 }
483 }
484}
485
486void SkGPipeCanvas::drawPicture(SkPicture& picture) {
487 UNIMPLEMENTED
488}
489
490void SkGPipeCanvas::drawShape(SkShape* shape) {
491 UNIMPLEMENTED
492}
493
494void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
495 const SkPoint vertices[], const SkPoint texs[],
496 const SkColor colors[], SkXfermode*,
497 const uint16_t indices[], int indexCount,
498 const SkPaint& paint) {
499 if (0 == vertexCount) {
500 return;
501 }
502
reed@google.comacd471f2011-05-03 21:26:46 +0000503 NOTIFY_SETUP(this);
504 size_t size = 4 + vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000505 unsigned paintIndex = this->writePaint(paint);
506 unsigned flags = 0;
507 if (texs) {
508 flags |= kDrawVertices_HasTexs_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000509 size += vertexCount * sizeof(SkPoint);
reed@google.combb6992a2011-04-26 17:41:56 +0000510 }
511 if (colors) {
512 flags |= kDrawVertices_HasColors_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000513 size += vertexCount * sizeof(SkColor);
reed@google.combb6992a2011-04-26 17:41:56 +0000514 }
515 if (indices && indexCount > 0) {
516 flags |= kDrawVertices_HasIndices_DrawOpFlag;
reed@google.comacd471f2011-05-03 21:26:46 +0000517 size += 4 + SkAlign4(indexCount * sizeof(uint16_t));
reed@google.combb6992a2011-04-26 17:41:56 +0000518 }
519
reed@google.comacd471f2011-05-03 21:26:46 +0000520 if (this->needOpBytes(size)) {
521 this->writeOp(kDrawVertices_DrawOp, flags, paintIndex);
522 fWriter.write32(mode);
523 fWriter.write32(vertexCount);
524 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
525 if (texs) {
526 fWriter.write(texs, vertexCount * sizeof(SkPoint));
527 }
528 if (colors) {
529 fWriter.write(colors, vertexCount * sizeof(SkColor));
530 }
reed@google.combb6992a2011-04-26 17:41:56 +0000531
reed@google.comacd471f2011-05-03 21:26:46 +0000532 // TODO: flatten xfermode
reed@google.combb6992a2011-04-26 17:41:56 +0000533
reed@google.comacd471f2011-05-03 21:26:46 +0000534 if (indices && indexCount > 0) {
535 fWriter.write32(indexCount);
536 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
537 }
reed@google.combb6992a2011-04-26 17:41:56 +0000538 }
539}
540
reed@google.comacd471f2011-05-03 21:26:46 +0000541void SkGPipeCanvas::drawData(const void* ptr, size_t size) {
542 if (size && ptr) {
543 NOTIFY_SETUP(this);
reed@google.combb6992a2011-04-26 17:41:56 +0000544 unsigned data = 0;
545 if (size < (1 << DRAWOPS_DATA_BITS)) {
546 data = (unsigned)size;
547 }
reed@google.comacd471f2011-05-03 21:26:46 +0000548 if (this->needOpBytes(4 + SkAlign4(size))) {
549 this->writeOp(kDrawData_DrawOp, 0, data);
550 if (0 == data) {
551 fWriter.write32(size);
552 }
553 fWriter.write(ptr, size);
reed@google.combb6992a2011-04-26 17:41:56 +0000554 }
555 }
556}
557
558///////////////////////////////////////////////////////////////////////////////
559
560template <typename T> uint32_t castToU32(T value) {
561 union {
562 T fSrc;
563 uint32_t fDst;
564 } data;
565 data.fSrc = value;
566 return data.fDst;
567}
568
569unsigned SkGPipeCanvas::writePaint(const SkPaint& paint) {
570 const SkPaint& base = *fPaints[0];
571 uint32_t storage[32];
572 uint32_t* ptr = storage;
573 uint32_t* last = NULL;
574
575 if (base.getFlags() != paint.getFlags()) {
576 last = ptr;
577 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
578 }
579 if (base.getColor() != paint.getColor()) {
580 last = ptr;
581 *ptr++ = PaintOp_packOp(kColor_PaintOp);
582 *ptr++ = paint.getColor();
583 }
584 if (base.getStyle() != paint.getStyle()) {
585 last = ptr;
586 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
587 }
588 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
589 last = ptr;
590 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
591 }
592 if (base.getStrokeCap() != paint.getStrokeCap()) {
593 last = ptr;
594 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
595 }
596 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
597 last = ptr;
598 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
599 *ptr++ = castToU32(paint.getStrokeWidth());
600 }
601 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
602 last = ptr;
603 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
604 *ptr++ = castToU32(paint.getStrokeMiter());
605 }
606 if (base.getTextEncoding() != paint.getTextEncoding()) {
607 last = ptr;
608 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
609 }
610 if (base.getHinting() != paint.getHinting()) {
611 last = ptr;
612 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
613 }
614 if (base.getTextAlign() != paint.getTextAlign()) {
615 last = ptr;
616 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
617 }
618 if (base.getTextSize() != paint.getTextSize()) {
619 last = ptr;
620 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
621 *ptr++ = castToU32(paint.getTextSize());
622 }
623 if (base.getTextScaleX() != paint.getTextScaleX()) {
624 last = ptr;
625 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
626 *ptr++ = castToU32(paint.getTextScaleX());
627 }
628 if (base.getTextSkewX() != paint.getTextSkewX()) {
629 last = ptr;
630 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
631 *ptr++ = castToU32(paint.getTextSkewX());
632 }
reed@google.combb6992a2011-04-26 17:41:56 +0000633
reed@google.comacd471f2011-05-03 21:26:46 +0000634 size_t size = (char*)ptr - (char*)storage;
635 if (size && this->needOpBytes(size)) {
636 *fPaints[0] = paint;
637
reed@google.combb6992a2011-04-26 17:41:56 +0000638 this->writeOp(kPaintOp_DrawOp, 0, 0);
639 size_t size = (char*)ptr - (char*)storage;
640 *last |= kLastOp_PaintOpFlag << PAINTOPS_DATA_BITS;
641 fWriter.write(storage, (char*)ptr - (char*)storage);
642 for (size_t i = 0; i < size/4; i++) {
643 SkDebugf("[%d] %08X\n", i, storage[i]);
644 }
645 }
646 return 0;
647}
648
649///////////////////////////////////////////////////////////////////////////////
650
651#include "SkGPipe.h"
652
reed@google.comacd471f2011-05-03 21:26:46 +0000653SkGPipeWriter::SkGPipeWriter() : fWriter(0) {
reed@google.combb6992a2011-04-26 17:41:56 +0000654 fCanvas = NULL;
655}
656
657SkGPipeWriter::~SkGPipeWriter() {
reed@google.comacd471f2011-05-03 21:26:46 +0000658 this->endRecording();
reed@google.combb6992a2011-04-26 17:41:56 +0000659 SkSafeUnref(fCanvas);
660}
661
reed@google.comacd471f2011-05-03 21:26:46 +0000662SkCanvas* SkGPipeWriter::startRecording(SkGPipeController* controller) {
reed@google.combb6992a2011-04-26 17:41:56 +0000663 if (NULL == fCanvas) {
reed@google.comacd471f2011-05-03 21:26:46 +0000664 fWriter.reset(NULL, 0);
665 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (controller, &fWriter));
reed@google.combb6992a2011-04-26 17:41:56 +0000666 }
667 return fCanvas;
668}
669
670void SkGPipeWriter::endRecording() {
671 if (fCanvas) {
672 fCanvas->finish();
673 fCanvas->unref();
674 fCanvas = NULL;
675 }
676}
677