/* * Copyright 2014 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef GrRecordReplaceDraw_DEFINED #define GrRecordReplaceDraw_DEFINED #include "SkChecksum.h" #include "SkDrawPictureCallback.h" #include "SkImage.h" #include "SkRect.h" #include "SkTDynamicHash.h" class SkBBoxHierarchy; class SkBitmap; class SkCanvas; class SkImage; class SkMatrix; class SkPaint; class SkPicture; class SkRecord; // GrReplacements collects op ranges that can be replaced with // a single drawBitmap call (using a precomputed bitmap). class GrReplacements { public: // All the operations between fStart and fStop (inclusive) will be replaced with // a single drawBitmap call using fPos, fImage and fPaint. class ReplacementInfo { public: struct Key { Key(uint32_t pictureID, unsigned start, const SkMatrix& ctm) : fPictureID(pictureID) , fStart(start) , fCTM(ctm) { fCTM.getType(); // force initialization of type so hashes match // Key needs to be tightly packed. GR_STATIC_ASSERT(sizeof(Key) == sizeof(uint32_t) + // picture ID sizeof(int) + // start 9 * sizeof(SkScalar) // 3x3 from CTM +sizeof(uint32_t)); // matrix's type } bool operator==(const Key& other) const { return fPictureID == other.fPictureID && fStart == other.fStart && fCTM.cheapEqualTo(other.fCTM); // TODO: should be fuzzy } uint32_t pictureID() const { return fPictureID; } unsigned int start() const { return fStart; } private: const uint32_t fPictureID; const unsigned fStart; const SkMatrix fCTM; }; static const Key& GetKey(const ReplacementInfo& layer) { return layer.fKey; } static uint32_t Hash(const Key& key) { return SkChecksum::Murmur3(reinterpret_cast(&key), sizeof(Key)); } ReplacementInfo(uint32_t pictureID, unsigned int start, const SkMatrix& ctm) : fKey(pictureID, start, ctm) , fImage(NULL) , fPaint(NULL) { } ~ReplacementInfo() { fImage->unref(); SkDELETE(fPaint); } unsigned int start() const { return fKey.start(); } const Key fKey; unsigned fStop; SkIPoint fPos; SkImage* fImage; // Owns a ref const SkPaint* fPaint; // Owned by this object SkIRect fSrcRect; }; ~GrReplacements() { this->freeAll(); } // Add a new replacement range. ReplacementInfo* newReplacement(uint32_t pictureID, unsigned start, const SkMatrix& ctm); // look up a replacement range by its pictureID, start offset and the CTM // TODO: also need to add clip to lookup const ReplacementInfo* lookupByStart(uint32_t pictureID, unsigned start, const SkMatrix& ctm) const; private: SkTDynamicHash fReplacementHash; void freeAll(); }; // Draw an SkPicture into an SkCanvas replacing saveLayer/restore blocks with // drawBitmap calls. A convenience wrapper around SkRecords::Draw. // It returns the number of saveLayer/restore blocks replaced with drawBitmap calls. int GrRecordReplaceDraw(const SkPicture*, SkCanvas*, const GrReplacements*, const SkMatrix& initialMatrix, SkDrawPictureCallback*); #endif // GrRecordReplaceDraw_DEFINED