Upstream version 10.39.225.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 "SkImage.h"
10 #include "SkRecordDraw.h"
11
12 GrReplacements::ReplacementInfo* GrReplacements::push() {
13     SkDEBUGCODE(this->validate());
14     return fReplacements.push();
15 }
16
17 void GrReplacements::freeAll() {
18     for (int i = 0; i < fReplacements.count(); ++i) {
19         fReplacements[i].fImage->unref();
20         SkDELETE(fReplacements[i].fPaint);
21     }
22     fReplacements.reset();
23 }
24
25 #ifdef SK_DEBUG
26 void GrReplacements::validate() const {
27     // Check that the ranges are monotonically increasing and non-overlapping
28     if (fReplacements.count() > 0) {
29         SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop);
30
31         for (int i = 1; i < fReplacements.count(); ++i) {
32             SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop);
33             SkASSERT(fReplacements[i - 1].fStop < fReplacements[i].fStart);
34         }
35     }
36 }
37 #endif
38
39 const GrReplacements::ReplacementInfo*
40 GrReplacements::lookupByStart(size_t start, int* searchStart) const {
41     SkDEBUGCODE(this->validate());
42     for (int i = *searchStart; i < fReplacements.count(); ++i) {
43         if (start == fReplacements[i].fStart) {
44             *searchStart = i + 1;
45             return &fReplacements[i];
46         } else if (start < fReplacements[i].fStart) {
47             return NULL;  // the ranges are monotonically increasing and non-overlapping
48         }
49     }
50
51     return NULL;
52 }
53
54 static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
55                                            SkCanvas* canvas,
56                                            const SkMatrix& initialMatrix) {
57     SkRect src = SkRect::Make(ri->fSrcRect);
58     SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX),
59                                   SkIntToScalar(ri->fPos.fY),
60                                   SkIntToScalar(ri->fSrcRect.width()),
61                                   SkIntToScalar(ri->fSrcRect.height()));
62
63     canvas->save();
64     canvas->setMatrix(initialMatrix);
65     canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
66     canvas->restore();
67 }
68
69 void GrRecordReplaceDraw(const SkRecord& record,
70                          SkCanvas* canvas,
71                          const SkBBoxHierarchy* bbh,
72                          const GrReplacements* replacements,
73                          SkDrawPictureCallback* callback) {
74     SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
75
76     SkRecords::Draw draw(canvas);
77     const GrReplacements::ReplacementInfo* ri = NULL;
78     int searchStart = 0;
79
80     const SkMatrix initialMatrix = canvas->getTotalMatrix();
81
82     if (bbh) {
83         // Draw only ops that affect pixels in the canvas's current clip.
84         // The SkRecord and BBH were recorded in identity space.  This canvas
85         // is not necessarily in that same space.  getClipBounds() returns us
86         // this canvas' clip bounds transformed back into identity space, which
87         // lets us query the BBH.
88         SkRect query = { 0, 0, 0, 0 };
89         (void)canvas->getClipBounds(&query);
90
91         SkTDArray<void*> ops;
92         bbh->search(query, &ops);
93
94         for (int i = 0; i < ops.count(); i++) {
95             if (callback && callback->abortDrawing()) {
96                 return;
97             }
98             ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart);
99             if (ri) {
100                 draw_replacement_bitmap(ri, canvas, initialMatrix);
101
102                 while ((uintptr_t)ops[i] < ri->fStop) {
103                     ++i;
104                 }
105                 SkASSERT((uintptr_t)ops[i] == ri->fStop);
106                 continue;
107             }
108
109             record.visit<void>((uintptr_t)ops[i], draw);
110         }
111     } else {
112         for (unsigned int i = 0; i < record.count(); ++i) {
113             if (callback && callback->abortDrawing()) {
114                 return;
115             }
116             ri = replacements->lookupByStart(i, &searchStart);
117             if (ri) {
118                 draw_replacement_bitmap(ri, canvas, initialMatrix);
119                 i = ri->fStop;
120                 continue;
121             }
122
123             record.visit<void>(i, draw);
124         }
125     }
126 }