Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / third_party / skia / src / gpu / GrRecordReplaceDraw.cpp
1 /*
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
8 #include "GrRecordReplaceDraw.h"
9 #include "SkCanvasPriv.h"
10 #include "SkImage.h"
11 #include "SkRecordDraw.h"
12 #include "SkRecords.h"
13
14 GrReplacements::ReplacementInfo* GrReplacements::newReplacement(uint32_t pictureID,
15                                                                 unsigned int start,
16                                                                 const SkMatrix& ctm) {
17     ReplacementInfo* replacement = SkNEW_ARGS(ReplacementInfo, (pictureID, start, ctm));
18     fReplacementHash.add(replacement);
19     return replacement;
20 }
21
22 void GrReplacements::freeAll() {
23     SkTDynamicHash<ReplacementInfo, ReplacementInfo::Key>::Iter iter(&fReplacementHash);
24
25     for (; !iter.done(); ++iter) {
26         ReplacementInfo* replacement = &(*iter);
27         SkDELETE(replacement);
28     }
29
30     fReplacementHash.reset();
31 }
32
33 const GrReplacements::ReplacementInfo* GrReplacements::lookupByStart(uint32_t pictureID,
34                                                                      size_t start,
35                                                                      const SkMatrix& ctm) const {
36     return fReplacementHash.find(ReplacementInfo::Key(pictureID, start, ctm));
37 }
38
39 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
40                                            SkCanvas* canvas,
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()));
47
48     canvas->save();
49     canvas->setMatrix(initialMatrix);
50     canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
51     canvas->restore();
52 }
53
54 // Used by GrRecordReplaceDraw. It intercepts nested drawPicture calls and
55 // also draws them with replaced layers.
56 class ReplaceDraw : public SkRecords::Draw {
57 public:
58     ReplaceDraw(SkCanvas* canvas,
59                 const SkPicture* picture,
60                 const GrReplacements* replacements,
61                 const SkMatrix& initialMatrix,
62                 SkDrawPictureCallback* callback)
63         : INHERITED(canvas)
64         , fCanvas(canvas)
65         , fPicture(picture)
66         , fReplacements(replacements)
67         , fInitialMatrix(initialMatrix)
68         , fCallback(callback)
69         , fIndex(0)
70         , fNumReplaced(0) {
71     }
72
73     int draw() {
74         const SkBBoxHierarchy* bbh = fPicture->fBBH.get();
75         const SkRecord* record = fPicture->fRecord.get();
76         if (NULL == record) {
77             return 0;
78         }
79
80         fNumReplaced = 0;
81
82         fOps.rewind();
83
84         if (bbh) {
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);
92
93             bbh->search(query, &fOps);
94
95             for (fIndex = 0; fIndex < fOps.count(); ++fIndex) {
96                 if (fCallback && fCallback->abortDrawing()) {
97                     return fNumReplaced;
98                 }
99
100                 record->visit<void>(fOps[fIndex], *this);
101             }
102
103         } else {
104             for (fIndex = 0; fIndex < (int) record->count(); ++fIndex) {
105                 if (fCallback && fCallback->abortDrawing()) {
106                     return fNumReplaced;
107                 }
108
109                 record->visit<void>(fIndex, *this);
110             }
111         }
112
113         return fNumReplaced;
114     }
115
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);
119     }
120     void operator()(const SkRecords::DrawPicture& dp) {
121         SkAutoCanvasMatrixPaint acmp(fCanvas, dp.matrix, dp.paint, dp.picture->cullRect());
122
123         // Draw sub-pictures with the same replacement list but a different picture
124         ReplaceDraw draw(fCanvas, dp.picture, fReplacements, fInitialMatrix, fCallback);
125
126         fNumReplaced += draw.draw();
127     }
128     void operator()(const SkRecords::SaveLayer& sl) {
129
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.
132         size_t startOffset;
133         if (fOps.count()) {
134             startOffset = fOps[fIndex];
135         } else {
136             startOffset = fIndex;
137         }
138
139         const SkMatrix& ctm = fCanvas->getTotalMatrix();
140         const GrReplacements::ReplacementInfo* ri = fReplacements->lookupByStart(
141                                                             fPicture->uniqueID(),
142                                                             startOffset,
143                                                             ctm);
144
145         if (ri) {
146             fNumReplaced++;
147             draw_replacement_bitmap(ri, fCanvas, fInitialMatrix);
148
149             if (fPicture->fBBH.get()) {
150                 while (fOps[fIndex] < ri->fStop) {
151                     ++fIndex;
152                 }
153                 SkASSERT(fOps[fIndex] == ri->fStop);
154             } else {
155                 fIndex = ri->fStop;
156             }
157             return;
158         }
159
160         // This is a fail for layer hoisting
161         this->INHERITED::operator()(sl);
162     }
163
164 private:
165     SkCanvas*              fCanvas;
166     const SkPicture*       fPicture;
167     const GrReplacements*  fReplacements;
168     const SkMatrix         fInitialMatrix;
169     SkDrawPictureCallback* fCallback;
170
171     SkTDArray<unsigned>    fOps;
172     int                    fIndex;
173     int                    fNumReplaced;
174
175     typedef Draw INHERITED;
176 };
177
178 int GrRecordReplaceDraw(const SkPicture* picture,
179                         SkCanvas* canvas,
180                         const GrReplacements* replacements,
181                         const SkMatrix& initialMatrix,
182                         SkDrawPictureCallback* callback) {
183     SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
184
185     ReplaceDraw draw(canvas, picture, replacements, initialMatrix, callback);
186
187     return draw.draw();
188 }