blob: a330713771302bb879e06f94e58fe6189c445444 [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"
20#include "SkGPipePriv.h"
21#include "SkGPipeState.h"
22#include "SkWriter32.h"
23
24static void writeRegion(SkWriter32* writer, const SkRegion& rgn) {
25 size_t size = rgn.flatten(NULL);
26 SkASSERT(SkAlign4(size) == size);
27 rgn.flatten(writer->reserve(size));
28}
29
30static void writeMatrix(SkWriter32* writer, const SkMatrix& matrix) {
31 size_t size = matrix.flatten(NULL);
32 SkASSERT(SkAlign4(size) == size);
33 matrix.flatten(writer->reserve(size));
34}
35
36///////////////////////////////////////////////////////////////////////////////
37
38class SkGPipeCanvas : public SkCanvas {
39public:
40 SkGPipeCanvas(SkWriter32* writer);
41 virtual ~SkGPipeCanvas();
42
43 void finish() {
44 if (!fDone) {
45 this->writeOp(kDone_DrawOp);
46 fDone = true;
47 }
48 }
49
50 // overrides from SkCanvas
51 virtual int save(SaveFlags);
52 virtual int saveLayer(const SkRect* bounds, const SkPaint*, SaveFlags);
53 virtual void restore();
54 virtual bool translate(SkScalar dx, SkScalar dy);
55 virtual bool scale(SkScalar sx, SkScalar sy);
56 virtual bool rotate(SkScalar degrees);
57 virtual bool skew(SkScalar sx, SkScalar sy);
58 virtual bool concat(const SkMatrix& matrix);
59 virtual void setMatrix(const SkMatrix& matrix);
60 virtual bool clipRect(const SkRect& rect, SkRegion::Op op);
61 virtual bool clipPath(const SkPath& path, SkRegion::Op op);
62 virtual bool clipRegion(const SkRegion& region, SkRegion::Op op);
63 virtual void clear(SkColor);
64 virtual void drawPaint(const SkPaint& paint);
65 virtual void drawPoints(PointMode, size_t count, const SkPoint pts[],
66 const SkPaint&);
67 virtual void drawRect(const SkRect& rect, const SkPaint&);
68 virtual void drawPath(const SkPath& path, const SkPaint&);
69 virtual void drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
70 const SkPaint*);
71 virtual void drawBitmapRect(const SkBitmap&, const SkIRect* src,
72 const SkRect& dst, const SkPaint*);
73 virtual void drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
74 const SkPaint*);
75 virtual void drawSprite(const SkBitmap&, int left, int top,
76 const SkPaint*);
77 virtual void drawText(const void* text, size_t byteLength, SkScalar x,
78 SkScalar y, const SkPaint&);
79 virtual void drawPosText(const void* text, size_t byteLength,
80 const SkPoint pos[], const SkPaint&);
81 virtual void drawPosTextH(const void* text, size_t byteLength,
82 const SkScalar xpos[], SkScalar constY, const SkPaint&);
83 virtual void drawTextOnPath(const void* text, size_t byteLength,
84 const SkPath& path, const SkMatrix* matrix,
85 const SkPaint&);
86 virtual void drawPicture(SkPicture& picture);
87 virtual void drawShape(SkShape*);
88 virtual void drawVertices(VertexMode, int vertexCount,
89 const SkPoint vertices[], const SkPoint texs[],
90 const SkColor colors[], SkXfermode*,
91 const uint16_t indices[], int indexCount,
92 const SkPaint&);
93 virtual void drawData(const void*, size_t);
94
95private:
96 SkWriter32& fWriter;
97 bool fDone;
98
99 void writeOp(DrawOps op, unsigned flags, unsigned data) {
100 fWriter.write32(DrawOp_packOpFlagData(op, flags, data));
101 }
102
103 void writeOp(DrawOps op) {
104 fWriter.write32(DrawOp_packOpFlagData(op, 0, 0));
105 }
106
107 SkTDArray<SkPaint*> fPaints;
108 unsigned writePaint(const SkPaint&);
109
110 typedef SkCanvas INHERITED;
111};
112
113///////////////////////////////////////////////////////////////////////////////
114
115
116SkGPipeCanvas::SkGPipeCanvas(SkWriter32* writer) : fWriter(*writer) {
117 fDone = false;
118 // always begin with 1 default paint
119 *fPaints.append() = SkNEW(SkPaint);
120}
121
122SkGPipeCanvas::~SkGPipeCanvas() {
123 this->finish();
124
125 fPaints.deleteAll();
126}
127
128///////////////////////////////////////////////////////////////////////////////
129
130int SkGPipeCanvas::save(SaveFlags flags) {
131 this->writeOp(kSave_DrawOp, 0, flags);
132 return this->INHERITED::save(flags);
133}
134
135int SkGPipeCanvas::saveLayer(const SkRect* bounds, const SkPaint* paint,
136 SaveFlags saveFlags) {
137 unsigned index = 0; // just to avoid the warning
138 unsigned opFlags = 0;
139
140 if (bounds) {
141 opFlags |= kSaveLayer_HasBounds_DrawOpFlag;
142 }
143 if (paint) {
144 opFlags |= kSaveLayer_HasPaint_DrawOpFlag;
145 index = this->writePaint(*paint);
146 }
147
148 this->writeOp(kSaveLayer_DrawOp, opFlags, saveFlags);
149 if (bounds) {
150 fWriter.writeRect(*bounds);
151 }
152 if (paint) {
153 fWriter.write32(index);
154 }
155
156 // we just pass on the save, so we don't create a layer
157 return this->INHERITED::save(saveFlags);
158}
159
160void SkGPipeCanvas::restore() {
161 this->writeOp(kRestore_DrawOp);
162 this->INHERITED::restore();
163}
164
165bool SkGPipeCanvas::translate(SkScalar dx, SkScalar dy) {
166 if (dx || dy) {
167 this->writeOp(kTranslate_DrawOp);
168 fWriter.writeScalar(dx);
169 fWriter.writeScalar(dy);
170 }
171 return this->INHERITED::translate(dx, dy);
172}
173
174bool SkGPipeCanvas::scale(SkScalar sx, SkScalar sy) {
175 if (sx || sy) {
176 this->writeOp(kScale_DrawOp);
177 fWriter.writeScalar(sx);
178 fWriter.writeScalar(sy);
179 }
180 return this->INHERITED::scale(sx, sy);
181}
182
183bool SkGPipeCanvas::rotate(SkScalar degrees) {
184 if (degrees) {
185 this->writeOp(kRotate_DrawOp);
186 fWriter.writeScalar(degrees);
187 }
188 return this->INHERITED::rotate(degrees);
189}
190
191bool SkGPipeCanvas::skew(SkScalar sx, SkScalar sy) {
192 if (sx || sy) {
193 this->writeOp(kSkew_DrawOp);
194 fWriter.writeScalar(sx);
195 fWriter.writeScalar(sy);
196 }
197 return this->INHERITED::skew(sx, sy);
198}
199
200bool SkGPipeCanvas::concat(const SkMatrix& matrix) {
201 if (!matrix.isIdentity()) {
202 this->writeOp(kConcat_DrawOp);
203 writeMatrix(&fWriter, matrix);
204 }
205 return this->INHERITED::concat(matrix);
206}
207
208void SkGPipeCanvas::setMatrix(const SkMatrix& matrix) {
209 this->writeOp(kSetMatrix_DrawOp);
210 writeMatrix(&fWriter, matrix);
211 this->INHERITED::setMatrix(matrix);
212}
213
214bool SkGPipeCanvas::clipRect(const SkRect& rect, SkRegion::Op rgnOp) {
215 this->writeOp(kClipRect_DrawOp, 0, rgnOp);
216 fWriter.writeRect(rect);
217 return this->INHERITED::clipRect(rect, rgnOp);
218}
219
220bool SkGPipeCanvas::clipPath(const SkPath& path, SkRegion::Op rgnOp) {
221 this->writeOp(kClipPath_DrawOp, 0, rgnOp);
222 path.flatten(fWriter);
223 // we just pass on the bounds of the path
224 return this->INHERITED::clipRect(path.getBounds(), rgnOp);
225}
226
227bool SkGPipeCanvas::clipRegion(const SkRegion& region, SkRegion::Op rgnOp) {
228 this->writeOp(kClipRegion_DrawOp, 0, rgnOp);
229 writeRegion(&fWriter, region);
230 return this->INHERITED::clipRegion(region, rgnOp);
231}
232
233///////////////////////////////////////////////////////////////////////////////
234
235void SkGPipeCanvas::clear(SkColor color) {
236 unsigned flags = 0;
237 if (color) {
238 flags |= kClear_HasColor_DrawOpFlag;
239 }
240 this->writeOp(kDrawClear_DrawOp, flags, 0);
241 if (color) {
242 fWriter.write32(color);
243 }
244}
245
246void SkGPipeCanvas::drawPaint(const SkPaint& paint) {
247 unsigned paintIndex = this->writePaint(paint);
248 this->writeOp(kDrawPaint_DrawOp, 0, paintIndex);
249}
250
251void SkGPipeCanvas::drawPoints(PointMode mode, size_t count,
252 const SkPoint pts[], const SkPaint& paint) {
253 if (count) {
254 unsigned paintIndex = this->writePaint(paint);
255 this->writeOp(kDrawPoints_DrawOp, mode, paintIndex);
256 fWriter.write32(count);
257 fWriter.write(pts, count * sizeof(SkPoint));
258 }
259}
260
261void SkGPipeCanvas::drawRect(const SkRect& rect, const SkPaint& paint) {
262 unsigned paintIndex = this->writePaint(paint);
263 this->writeOp(kDrawRect_DrawOp, 0, paintIndex);
264 fWriter.writeRect(rect);
265}
266
267void SkGPipeCanvas::drawPath(const SkPath& path, const SkPaint& paint) {
268 unsigned paintIndex = this->writePaint(paint);
269 this->writeOp(kDrawPath_DrawOp, 0, paintIndex);
270 path.flatten(fWriter);
271}
272
273void SkGPipeCanvas::drawBitmap(const SkBitmap&, SkScalar left, SkScalar top,
274 const SkPaint*) {
275 UNIMPLEMENTED
276}
277
278void SkGPipeCanvas::drawBitmapRect(const SkBitmap&, const SkIRect* src,
279 const SkRect& dst, const SkPaint*) {
280 UNIMPLEMENTED
281}
282
283void SkGPipeCanvas::drawBitmapMatrix(const SkBitmap&, const SkMatrix&,
284 const SkPaint*) {
285 UNIMPLEMENTED
286}
287
288void SkGPipeCanvas::drawSprite(const SkBitmap&, int left, int top,
289 const SkPaint*) {
290 UNIMPLEMENTED
291}
292
293void SkGPipeCanvas::drawText(const void* text, size_t byteLength, SkScalar x,
294 SkScalar y, const SkPaint& paint) {
295 if (byteLength) {
296 unsigned paintIndex = this->writePaint(paint);
297 this->writeOp(kDrawText_DrawOp, 0, paintIndex);
298 fWriter.write32(byteLength);
299 fWriter.writePad(text, byteLength);
300 fWriter.writeScalar(x);
301 fWriter.writeScalar(y);
302 }
303}
304
305void SkGPipeCanvas::drawPosText(const void* text, size_t byteLength,
306 const SkPoint pos[], const SkPaint& paint) {
307 if (byteLength) {
308 unsigned paintIndex = this->writePaint(paint);
309 this->writeOp(kDrawPosText_DrawOp, 0, paintIndex);
310 fWriter.write32(byteLength);
311 fWriter.writePad(text, byteLength);
312 int count = paint.textToGlyphs(text, byteLength, NULL);
313 fWriter.write32(count);
314 fWriter.write(pos, count * sizeof(SkPoint));
315 }
316}
317
318void SkGPipeCanvas::drawPosTextH(const void* text, size_t byteLength,
319 const SkScalar xpos[], SkScalar constY,
320 const SkPaint& paint) {
321 if (byteLength) {
322 unsigned paintIndex = this->writePaint(paint);
323 this->writeOp(kDrawPosTextH_DrawOp, 0, paintIndex);
324 fWriter.write32(byteLength);
325 fWriter.writePad(text, byteLength);
326 int count = paint.textToGlyphs(text, byteLength, NULL);
327 fWriter.write32(count);
328 fWriter.write(xpos, count * sizeof(SkScalar));
329 fWriter.writeScalar(constY);
330 }
331}
332
333void SkGPipeCanvas::drawTextOnPath(const void* text, size_t byteLength,
334 const SkPath& path, const SkMatrix* matrix,
335 const SkPaint& paint) {
336 if (byteLength) {
337 unsigned flags = 0;
338 if (matrix) {
339 flags |= kDrawTextOnPath_HasMatrix_DrawOpFlag;
340 }
341 unsigned paintIndex = this->writePaint(paint);
342 this->writeOp(kDrawTextOnPath_DrawOp, flags, paintIndex);
343
344 fWriter.write32(byteLength);
345 fWriter.writePad(text, byteLength);
346
347 path.flatten(fWriter);
348 if (matrix) {
349 writeMatrix(&fWriter, *matrix);
350 }
351 }
352}
353
354void SkGPipeCanvas::drawPicture(SkPicture& picture) {
355 UNIMPLEMENTED
356}
357
358void SkGPipeCanvas::drawShape(SkShape* shape) {
359 UNIMPLEMENTED
360}
361
362void SkGPipeCanvas::drawVertices(VertexMode mode, int vertexCount,
363 const SkPoint vertices[], const SkPoint texs[],
364 const SkColor colors[], SkXfermode*,
365 const uint16_t indices[], int indexCount,
366 const SkPaint& paint) {
367 if (0 == vertexCount) {
368 return;
369 }
370
371 unsigned paintIndex = this->writePaint(paint);
372 unsigned flags = 0;
373 if (texs) {
374 flags |= kDrawVertices_HasTexs_DrawOpFlag;
375 }
376 if (colors) {
377 flags |= kDrawVertices_HasColors_DrawOpFlag;
378 }
379 if (indices && indexCount > 0) {
380 flags |= kDrawVertices_HasIndices_DrawOpFlag;
381 }
382
383 this->writeOp(kDrawVertices_DrawOp, flags, paintIndex);
384 fWriter.write32(mode);
385 fWriter.write32(vertexCount);
386 fWriter.write(vertices, vertexCount * sizeof(SkPoint));
387 if (texs) {
388 fWriter.write(texs, vertexCount * sizeof(SkPoint));
389 }
390 if (colors) {
391 fWriter.write(colors, vertexCount * sizeof(SkColor));
392 }
393
394 // TODO: flatten xfermode
395
396 if (indices && indexCount > 0) {
397 fWriter.write32(indexCount);
398 fWriter.writePad(indices, indexCount * sizeof(uint16_t));
399 }
400}
401
402void SkGPipeCanvas::drawData(const void* data, size_t size) {
403 if (size) {
404 unsigned data = 0;
405 if (size < (1 << DRAWOPS_DATA_BITS)) {
406 data = (unsigned)size;
407 }
408 this->writeOp(kDrawData_DrawOp, 0, data);
409 if (0 == data) {
410 fWriter.write32(size);
411 }
412 }
413}
414
415///////////////////////////////////////////////////////////////////////////////
416
417template <typename T> uint32_t castToU32(T value) {
418 union {
419 T fSrc;
420 uint32_t fDst;
421 } data;
422 data.fSrc = value;
423 return data.fDst;
424}
425
426unsigned SkGPipeCanvas::writePaint(const SkPaint& paint) {
427 const SkPaint& base = *fPaints[0];
428 uint32_t storage[32];
429 uint32_t* ptr = storage;
430 uint32_t* last = NULL;
431
432 if (base.getFlags() != paint.getFlags()) {
433 last = ptr;
434 *ptr++ = PaintOp_packOpData(kFlags_PaintOp, paint.getFlags());
435 }
436 if (base.getColor() != paint.getColor()) {
437 last = ptr;
438 *ptr++ = PaintOp_packOp(kColor_PaintOp);
439 *ptr++ = paint.getColor();
440 }
441 if (base.getStyle() != paint.getStyle()) {
442 last = ptr;
443 *ptr++ = PaintOp_packOpData(kStyle_PaintOp, paint.getStyle());
444 }
445 if (base.getStrokeJoin() != paint.getStrokeJoin()) {
446 last = ptr;
447 *ptr++ = PaintOp_packOpData(kJoin_PaintOp, paint.getStrokeJoin());
448 }
449 if (base.getStrokeCap() != paint.getStrokeCap()) {
450 last = ptr;
451 *ptr++ = PaintOp_packOpData(kCap_PaintOp, paint.getStrokeCap());
452 }
453 if (base.getStrokeWidth() != paint.getStrokeWidth()) {
454 last = ptr;
455 *ptr++ = PaintOp_packOp(kWidth_PaintOp);
456 *ptr++ = castToU32(paint.getStrokeWidth());
457 }
458 if (base.getStrokeMiter() != paint.getStrokeMiter()) {
459 last = ptr;
460 *ptr++ = PaintOp_packOp(kMiter_PaintOp);
461 *ptr++ = castToU32(paint.getStrokeMiter());
462 }
463 if (base.getTextEncoding() != paint.getTextEncoding()) {
464 last = ptr;
465 *ptr++ = PaintOp_packOpData(kEncoding_PaintOp, paint.getTextEncoding());
466 }
467 if (base.getHinting() != paint.getHinting()) {
468 last = ptr;
469 *ptr++ = PaintOp_packOpData(kHinting_PaintOp, paint.getHinting());
470 }
471 if (base.getTextAlign() != paint.getTextAlign()) {
472 last = ptr;
473 *ptr++ = PaintOp_packOpData(kAlign_PaintOp, paint.getTextAlign());
474 }
475 if (base.getTextSize() != paint.getTextSize()) {
476 last = ptr;
477 *ptr++ = PaintOp_packOp(kTextSize_PaintOp);
478 *ptr++ = castToU32(paint.getTextSize());
479 }
480 if (base.getTextScaleX() != paint.getTextScaleX()) {
481 last = ptr;
482 *ptr++ = PaintOp_packOp(kTextScaleX_PaintOp);
483 *ptr++ = castToU32(paint.getTextScaleX());
484 }
485 if (base.getTextSkewX() != paint.getTextSkewX()) {
486 last = ptr;
487 *ptr++ = PaintOp_packOp(kTextSkewX_PaintOp);
488 *ptr++ = castToU32(paint.getTextSkewX());
489 }
490 *fPaints[0] = paint;
491
492 if (ptr > storage) {
493 this->writeOp(kPaintOp_DrawOp, 0, 0);
494 size_t size = (char*)ptr - (char*)storage;
495 *last |= kLastOp_PaintOpFlag << PAINTOPS_DATA_BITS;
496 fWriter.write(storage, (char*)ptr - (char*)storage);
497 for (size_t i = 0; i < size/4; i++) {
498 SkDebugf("[%d] %08X\n", i, storage[i]);
499 }
500 }
501 return 0;
502}
503
504///////////////////////////////////////////////////////////////////////////////
505
506#include "SkGPipe.h"
507
508#define MIN_WRITE_BLOCK_SIZE (4 * 1024)
509
510SkGPipeWriter::SkGPipeWriter() : fWriter(MIN_WRITE_BLOCK_SIZE) {
511 fCanvas = NULL;
512}
513
514SkGPipeWriter::~SkGPipeWriter() {
515 SkSafeUnref(fCanvas);
516}
517
518SkCanvas* SkGPipeWriter::startRecording() {
519 if (NULL == fCanvas) {
520 fCanvas = SkNEW_ARGS(SkGPipeCanvas, (&fWriter));
521 }
522 return fCanvas;
523}
524
525void SkGPipeWriter::endRecording() {
526 if (fCanvas) {
527 fCanvas->finish();
528 fCanvas->unref();
529 fCanvas = NULL;
530 }
531}
532
533size_t SkGPipeWriter::flatten(void* buffer) {
534 if (buffer) {
535 fWriter.flatten(buffer);
536 }
537 return fWriter.size();
538}
539