15c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)/*
25c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Copyright 2014 Google Inc.
35c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) *
45c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
5197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch * found in the LICENSE file.
65c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles) */
75c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
85c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "GrRecordReplaceDraw.h"
95c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkImage.h"
105c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)#include "SkRecordDraw.h"
115c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
125c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)GrReplacements::ReplacementInfo* GrReplacements::push() {
135c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    SkDEBUGCODE(this->validate());
145c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    return fReplacements.push();
155c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
165c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
175c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)void GrReplacements::freeAll() {
185c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    for (int i = 0; i < fReplacements.count(); ++i) {
195c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        fReplacements[i].fImage->unref();
205c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        SkDELETE(fReplacements[i].fPaint);
215c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    }
225c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    fReplacements.reset();
235c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
2453e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
2553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)#ifdef SK_DEBUG
26197021e6b966cfb06891637935ef33fff06433d1Ben Murdochvoid GrReplacements::validate() const {
27d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)    // Check that the ranges are monotonically increasing and non-overlapping
2853e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    if (fReplacements.count() > 0) {
2909380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        SkASSERT(fReplacements[0].fStart < fReplacements[0].fStop);
30e1f1df5f01594c0e62e751e4b46e779b85c2faa5Torne (Richard Coles)
3153e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)        for (int i = 1; i < fReplacements.count(); ++i) {
3209380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)            SkASSERT(fReplacements[i].fStart < fReplacements[i].fStop);
331e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)            SkASSERT(fReplacements[i - 1].fStop < fReplacements[i].fStart);
34e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        }
3553e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)    }
3653e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)}
3709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)#endif
3876c265b59aa821ccbf8c75ab2bb0d036e97d2956Torne (Richard Coles)
39197021e6b966cfb06891637935ef33fff06433d1Ben Murdochconst GrReplacements::ReplacementInfo*
40f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)GrReplacements::lookupByStart(size_t start, int* searchStart) const {
41f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    SkDEBUGCODE(this->validate());
421e202183a5dc46166763171984b285173f8585e5Torne (Richard Coles)    for (int i = *searchStart; i < fReplacements.count(); ++i) {
43e52495584422c5edb5b2944981473a2e208da323Torne (Richard Coles)        if (start == fReplacements[i].fStart) {
44a9984bf9ddc3cf73fdae3f29134a2bab379e7029Ben Murdoch            *searchStart = i + 1;
45197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch            return &fReplacements[i];
4609380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)        } else if (start < fReplacements[i].fStart) {
47f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)            return NULL;  // the ranges are monotonically increasing and non-overlapping
48521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)        }
49521d96ec04ace82590870fb04353ec4f82bb150fTorne (Richard Coles)    }
5053e740f4a82e17f3ae59772501622dc354e42336Torne (Richard Coles)
518abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)    return NULL;
52e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)}
53197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
545c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)static inline void draw_replacement_bitmap(const GrReplacements::ReplacementInfo* ri,
55c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                                           SkCanvas* canvas,
565c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                           const SkMatrix& initialMatrix) {
5709380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkRect src = SkRect::Make(ri->fSrcRect);
5809380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)    SkRect dst = SkRect::MakeXYWH(SkIntToScalar(ri->fPos.fX),
596f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                                  SkIntToScalar(ri->fPos.fY),
606f543c786fc42989f552b4daa774ca5ff32fa697Ben Murdoch                                  SkIntToScalar(ri->fSrcRect.width()),
615c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                                  SkIntToScalar(ri->fSrcRect.height()));
62197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch
63e38fbeeb576b5094e34e038ab88d9d6a5c5c2214Torne (Richard Coles)    canvas->save();
645c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    canvas->setMatrix(initialMatrix);
655c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    canvas->drawImageRect(ri->fImage, &src, dst, ri->fPaint);
6651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)    canvas->restore();
675c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)}
68c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
69c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)void GrRecordReplaceDraw(const SkRecord& record,
70c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                         SkCanvas* canvas,
71c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)                         const SkBBoxHierarchy* bbh,
725c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         const GrReplacements* replacements,
735c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                         SkDrawPictureCallback* callback) {
74c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SkAutoCanvasRestore saveRestore(canvas, true /*save now, restore at exit*/);
75c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)
76c1847b1379d12d0e05df27436bf19a9b1bf12deaTorne (Richard Coles)    SkRecords::Draw draw(canvas);
775c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    const GrReplacements::ReplacementInfo* ri = NULL;
785c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)    int searchStart = 0;
79323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)
80926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)    const SkMatrix initialMatrix = canvas->getTotalMatrix();
815c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)
82f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    if (bbh) {
8319cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        // Draw only ops that affect pixels in the canvas's current clip.
84197021e6b966cfb06891637935ef33fff06433d1Ben Murdoch        // The SkRecord and BBH were recorded in identity space.  This canvas
855c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // is not necessarily in that same space.  getClipBounds() returns us
86323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)        // this canvas' clip bounds transformed back into identity space, which
875c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        // lets us query the BBH.
8819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        SkRect query = { 0, 0, 0, 0 };
895c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        (void)canvas->getClipBounds(&query);
90f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)
9119cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)        SkTDArray<void*> ops;
92f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)        bbh->search(query, &ops);
938abfc5808a4e34d6e03867af8bc440dee641886fTorne (Richard Coles)
945c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)        for (int i = 0; i < ops.count(); i++) {
955c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            if (callback && callback->abortDrawing()) {
965c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                return;
975c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            }
985c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)            ri = replacements->lookupByStart((uintptr_t)ops[i], &searchStart);
99323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)            if (ri) {
100d6cdb82654e8f3343a693ca752d5c4cee0324e17Torne (Richard Coles)                draw_replacement_bitmap(ri, canvas, initialMatrix);
101f79f16f17ddc4f842d7b7a38603e280e94be826aTorne (Richard Coles)
102926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                while ((uintptr_t)ops[i] < ri->fStop) {
103323480423219ecd77329f8326dc5e0e3b50926d4Torne (Richard Coles)                    ++i;
1045c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                }
1055c87bf8b86a7c82ef50fb7a89697d8e02e2553beTorne (Richard Coles)                SkASSERT((uintptr_t)ops[i] == ri->fStop);
10651b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                continue;
107926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
10819cde67944066db31e633d9e386f2aa9bf9fadb3Torne (Richard Coles)
10951b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            record.visit<void>((uintptr_t)ops[i], draw);
110926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
111f6b7aed3f7ce69aca0d7a032d144cbd088b04393Torne (Richard Coles)    } else {
11251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)        for (unsigned int i = 0; i < record.count(); ++i) {
113926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (callback && callback->abortDrawing()) {
114926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                return;
115926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            }
116926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            ri = replacements->lookupByStart(i, &searchStart);
117926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            if (ri) {
11851b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)                draw_replacement_bitmap(ri, canvas, initialMatrix);
119926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)                i = ri->fStop;
12009380295ba73501a205346becac22c6978e4671dTorne (Richard Coles)                continue;
12151b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)            }
12251b2906e11752df6c18351cf520e30522d3b53a1Torne (Richard Coles)
123926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)            record.visit<void>(i, draw);
124926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)        }
125a854de003a23bf3c7f95ec0f8154ada64092ff5cTorne (Richard Coles)    }
126926b001d589ce2f10facb93dd4b87578ea35a855Torne (Richard Coles)}
127e69819bd8e388ea4ad1636a19aa6b2eed4952191Ben Murdoch