blob: 8be9e005f6c3846b363c23851eb4a9d93cce4e37 [file] [log] [blame]
commit-bot@chromium.orgc4b21e62014-04-11 18:33:31 +00001/*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
commit-bot@chromium.org506db0b2014-04-08 23:31:35 +00008#include "SkRecordDraw.h"
mtklein5ad6ee12014-08-11 08:08:43 -07009#include "SkTSort.h"
commit-bot@chromium.org506db0b2014-04-08 23:31:35 +000010
mtklein5ad6ee12014-08-11 08:08:43 -070011void SkRecordDraw(const SkRecord& record,
12 SkCanvas* canvas,
13 const SkBBoxHierarchy* bbh,
14 SkDrawPictureCallback* callback) {
Mike Kleinc11530e2014-06-24 11:29:06 -040015 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
mtklein5ad6ee12014-08-11 08:08:43 -070016
17 if (NULL != bbh) {
18 SkASSERT(bbh->getCount() == SkToInt(record.count()));
19
20 // Draw only ops that affect pixels in the canvas's current clip.
21 SkIRect devBounds;
22 canvas->getClipDeviceBounds(&devBounds);
23 SkTDArray<void*> ops;
24 bbh->search(devBounds, &ops);
25
26 // Until we start filling in real bounds, we should get every op back.
27 SkASSERT(ops.count() == SkToInt(record.count()));
28
29 // FIXME: QuadTree doesn't send these back in the order we inserted them. :(
mtklein03bde3e2014-08-12 07:01:25 -070030 // Also remove the sort in SkPictureData::getActiveOps()?
mtklein5ad6ee12014-08-11 08:08:43 -070031 if (ops.count() > 0) {
32 SkTQSort(ops.begin(), ops.end() - 1, SkTCompareLT<void*>());
Mike Kleinc11530e2014-06-24 11:29:06 -040033 }
mtklein5ad6ee12014-08-11 08:08:43 -070034
35 SkRecords::Draw draw(canvas);
36 for (int i = 0; i < ops.count(); i++) {
37 if (NULL != callback && callback->abortDrawing()) {
38 return;
39 }
40 record.visit<void>((uintptr_t)ops[i], draw); // See FillBounds below.
41 }
42 } else {
43 // Draw all ops.
44 for (SkRecords::Draw draw(canvas); draw.index() < record.count(); draw.next()) {
45 if (NULL != callback && callback->abortDrawing()) {
46 return;
47 }
48 record.visit<void>(draw.index(), draw);
49 }
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000050 }
commit-bot@chromium.org27f6b0d2014-05-09 14:59:29 +000051}
commit-bot@chromium.orgd9ce2be2014-04-09 23:30:28 +000052
commit-bot@chromium.org27f6b0d2014-05-09 14:59:29 +000053namespace SkRecords {
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000054
mtklein7cdc1ee2014-07-07 10:41:04 -070055// FIXME: SkBitmaps are stateful, so we need to copy them to play back in multiple threads.
56static SkBitmap shallow_copy(const SkBitmap& bitmap) {
57 return bitmap;
58}
59
commit-bot@chromium.org2e0c32a2014-04-28 16:19:45 +000060// NoOps draw nothing.
commit-bot@chromium.org27f6b0d2014-05-09 14:59:29 +000061template <> void Draw::draw(const NoOp&) {}
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000062
commit-bot@chromium.org27f6b0d2014-05-09 14:59:29 +000063#define DRAW(T, call) template <> void Draw::draw(const T& r) { fCanvas->call; }
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000064DRAW(Restore, restore());
Florin Malita5f6102d2014-06-30 10:13:28 -040065DRAW(Save, save());
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000066DRAW(SaveLayer, saveLayer(r.bounds, r.paint, r.flags));
67DRAW(PopCull, popCull());
commit-bot@chromium.org88c3e272014-04-22 16:57:20 +000068DRAW(PushCull, pushCull(r.rect));
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000069DRAW(Clear, clear(r.color));
70DRAW(Concat, concat(r.matrix));
commit-bot@chromium.org99bd7d82014-05-19 15:51:12 +000071DRAW(SetMatrix, setMatrix(SkMatrix::Concat(fInitialCTM, r.matrix)));
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000072
73DRAW(ClipPath, clipPath(r.path, r.op, r.doAA));
74DRAW(ClipRRect, clipRRect(r.rrect, r.op, r.doAA));
75DRAW(ClipRect, clipRect(r.rect, r.op, r.doAA));
76DRAW(ClipRegion, clipRegion(r.region, r.op));
77
mtklein7cdc1ee2014-07-07 10:41:04 -070078DRAW(DrawBitmap, drawBitmap(shallow_copy(r.bitmap), r.left, r.top, r.paint));
79DRAW(DrawBitmapMatrix, drawBitmapMatrix(shallow_copy(r.bitmap), r.matrix, r.paint));
80DRAW(DrawBitmapNine, drawBitmapNine(shallow_copy(r.bitmap), r.center, r.dst, r.paint));
81DRAW(DrawBitmapRectToRect,
82 drawBitmapRectToRect(shallow_copy(r.bitmap), r.src, r.dst, r.paint, r.flags));
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000083DRAW(DrawDRRect, drawDRRect(r.outer, r.inner, r.paint));
84DRAW(DrawOval, drawOval(r.oval, r.paint));
85DRAW(DrawPaint, drawPaint(r.paint));
86DRAW(DrawPath, drawPath(r.path, r.paint));
dandovb3c9d1c2014-08-12 08:34:29 -070087DRAW(DrawPatch, drawPatch(r.cubics, r.colors, r.texCoords, r.xmode.get(), r.paint));
reedd5fa1a42014-08-09 11:08:05 -070088DRAW(DrawPicture, drawPicture(r.picture, r.matrix, r.paint));
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000089DRAW(DrawPoints, drawPoints(r.mode, r.count, r.pts, r.paint));
90DRAW(DrawPosText, drawPosText(r.text, r.byteLength, r.pos, r.paint));
91DRAW(DrawPosTextH, drawPosTextH(r.text, r.byteLength, r.xpos, r.y, r.paint));
92DRAW(DrawRRect, drawRRect(r.rrect, r.paint));
93DRAW(DrawRect, drawRect(r.rect, r.paint));
mtklein7cdc1ee2014-07-07 10:41:04 -070094DRAW(DrawSprite, drawSprite(shallow_copy(r.bitmap), r.left, r.top, r.paint));
commit-bot@chromium.org73b55eb2014-04-14 20:35:12 +000095DRAW(DrawText, drawText(r.text, r.byteLength, r.x, r.y, r.paint));
96DRAW(DrawTextOnPath, drawTextOnPath(r.text, r.byteLength, r.path, r.matrix, r.paint));
97DRAW(DrawVertices, drawVertices(r.vmode, r.vertexCount, r.vertices, r.texs, r.colors,
98 r.xmode.get(), r.indices, r.indexCount, r.paint));
99#undef DRAW
100
mtklein5ad6ee12014-08-11 08:08:43 -0700101
102// This is an SkRecord visitor that fills an SkBBoxHierarchy.
103class FillBounds : SkNoncopyable {
104public:
105 explicit FillBounds(SkBBoxHierarchy* bbh) : fBBH(bbh), fIndex(0) {}
106 ~FillBounds() { fBBH->flushDeferredInserts(); }
107
108 uintptr_t index() const { return fIndex; }
109 void next() { ++fIndex; }
110
111 template <typename T> void operator()(const T& r) {
112 // MakeLargest() is a trivially safe default for ops that haven't been bounded yet.
113 this->insert(this->index(), SkIRect::MakeLargest());
114 }
115
116private:
117 void insert(uintptr_t opIndex, const SkIRect& bounds) {
118 fBBH->insert((void*)opIndex, bounds, true/*ok to defer*/);
119 }
120
121 SkBBoxHierarchy* fBBH; // Unowned. The BBH is guaranteed to be ref'd for our lifetime.
122 uintptr_t fIndex;
123};
124
commit-bot@chromium.org27f6b0d2014-05-09 14:59:29 +0000125} // namespace SkRecords
mtklein5ad6ee12014-08-11 08:08:43 -0700126
127void SkRecordFillBounds(const SkRecord& record, SkBBoxHierarchy* bbh) {
128 SkASSERT(NULL != bbh);
129 for(SkRecords::FillBounds fb(bbh); fb.index() < record.count(); fb.next()) {
130 record.visit<void>(fb.index(), fb);
131 }
132}