2 * Copyright 2014 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
8 #include "GrRecordReplaceDraw.h"
9 #include "SkCanvasPriv.h"
11 #include "SkRecordDraw.h"
12 #include "SkRecords.h"
14 GrReplacements::ReplacementInfo* GrReplacements::newReplacement(uint32_t pictureID,
16 const SkMatrix& ctm) {
17 ReplacementInfo* replacement = SkNEW_ARGS(ReplacementInfo, (pictureID, start, ctm));
18 fReplacementHash.add(replacement);
22 void GrReplacements::freeAll() {
23 SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key>::Iter iter(&fReplacementHash);
25 for (; !iter.done(); ++iter) {
26 ReplacementInfo* replacement = &(*iter);
27 SkDELETE(replacement);
30 fReplacementHash.reset();
33 const GrReplacements::ReplacementInfo* GrReplacements::lookupByStart(uint32_t pictureID,
35 const SkMatrix& ctm) const {
36 return fReplacementHash.find(ReplacementInfo::Key(pictureID, start, ctm));
39 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
41 const SkMatrix& initialMatrix) {
42 SkRect src = SkRect::Make(ri->fSrcRect);
43 SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX),
44 SkIntToScalar(ri->fPos.fY),
45 SkIntToScalar(ri->fSrcRect.width()),
46 SkIntToScalar(ri->fSrcRect.height()));
49 canvas->setMatrix(initialMatrix);
50 canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
54 // Used by GrRecordReplaceDraw. It intercepts nested drawPicture calls and
55 // also draws them with replaced layers.
56 class ReplaceDraw : public SkRecords::Draw {
58 ReplaceDraw(SkCanvas* canvas,
59 const SkPicture* picture,
60 const GrReplacements* replacements,
61 const SkMatrix& initialMatrix,
62 SkDrawPictureCallback* callback)
66 , fReplacements(replacements)
67 , fInitialMatrix(initialMatrix)
74 const SkBBoxHierarchy* bbh = fPicture->fBBH.get();
75 const SkRecord* record = fPicture->fRecord.get();
85 // Draw only ops that affect pixels in the canvas's current clip.
86 // The SkRecord and BBH were recorded in identity space. This canvas
87 // is not necessarily in that same space. getClipBounds() returns us
88 // this canvas' clip bounds transformed back into identity space, which
89 // lets us query the BBH.
90 SkRect query = { 0, 0, 0, 0 };
91 (void)fCanvas->getClipBounds(&query);
93 bbh->search(query, &fOps);
95 for (fIndex = 0; fIndex < fOps.count(); ++fIndex) {
96 if (fCallback && fCallback->abortDrawing()) {
100 record->visit<void>(fOps[fIndex], *this);
104 for (fIndex = 0; fIndex < (int) record->count(); ++fIndex) {
105 if (fCallback && fCallback->abortDrawing()) {
109 record->visit<void>(fIndex, *this);
116 // Same as Draw for all ops except DrawPicture and SaveLayer.
117 template <typename T> void operator()(const T& r) {
118 this->INHERITED::operator()(r);
120 void operator()(const SkRecords::DrawPicture& dp) {
121 SkAutoCanvasMatrixPaint acmp(fCanvas, dp.matrix, dp.paint, dp.picture->cullRect());
123 // Draw sub-pictures with the same replacement list but a different picture
124 ReplaceDraw draw(fCanvas, dp.picture, fReplacements, fInitialMatrix, fCallback);
126 fNumReplaced += draw.draw();
128 void operator()(const SkRecords::SaveLayer& sl) {
130 // For a saveLayer command, check if it can be replaced by a drawBitmap
131 // call and, if so, draw it and then update the current op index accordingly.
134 startOffset = fOps[fIndex];
136 startOffset = fIndex;
139 const SkMatrix& ctm = fCanvas->getTotalMatrix();
140 const GrReplacements::ReplacementInfo* ri = fReplacements->lookupByStart(
141 fPicture->uniqueID(),
147 draw_replacement_bitmap(ri, fCanvas, fInitialMatrix);
149 if (fPicture->fBBH.get()) {
150 while (fOps[fIndex] < ri->fStop) {
153 SkASSERT(fOps[fIndex] == ri->fStop);
160 // This is a fail for layer hoisting
161 this->INHERITED::operator()(sl);
166 const SkPicture* fPicture;
167 const GrReplacements* fReplacements;
168 const SkMatrix fInitialMatrix;
169 SkDrawPictureCallback* fCallback;
171 SkTDArray<unsigned> fOps;
175 typedef Draw INHERITED;
178 int GrRecordReplaceDraw(const SkPicture* picture,
180 const GrReplacements* replacements,
181 const SkMatrix& initialMatrix,
182 SkDrawPictureCallback* callback) {
183 SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
185 ReplaceDraw draw(canvas, picture, replacements, initialMatrix, callback);