/* * 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 SkOffsetTable_DEFINED #define SkOffsetTable_DEFINED #include "SkRefCnt.h" #include "SkTDArray.h" // A 2D table of skp offsets. Each row is indexed by an int. This is used // to store the command offsets that reference a particular bitmap using // the bitmap's index in the bitmap heap as the 'id' here. It has to be // ref-countable so SkPicturePlayback can take ownership of it. // Note that this class assumes that the ids are densely packed. // TODO: This needs to be sped up. We could replace the offset table with // a hash table. class SkOffsetTable : public SkRefCnt { public: SkOffsetTable() {} ~SkOffsetTable() { fOffsetArrays.deleteAll(); } // Record that this 'id' is used by the command starting at this 'offset'. // Offsets for a given 'id' should always be added in increasing order. void add(int id, size_t offset) { if (id >= fOffsetArrays.count()) { int oldCount = fOffsetArrays.count(); fOffsetArrays.setCount(id+1); for (int i = oldCount; i <= id; ++i) { fOffsetArrays[i] = NULL; } } if (NULL == fOffsetArrays[id]) { fOffsetArrays[id] = SkNEW(OffsetArray); } fOffsetArrays[id]->add(offset); } int numIDs() const { return fOffsetArrays.count(); } // Do the offsets of any commands referencing this ID fall in the // range [min, max] (both inclusive) bool overlap(int id, size_t min, size_t max) { SkASSERT(id < fOffsetArrays.count()); if (NULL == fOffsetArrays[id]) { return false; } // If this id has an offset array it should have at least one use SkASSERT(fOffsetArrays[id]->count() > 0); if (max < fOffsetArrays[id]->min() || min > fOffsetArrays[id]->max()) { return false; } return true; } bool includes(int id, size_t offset) { SkASSERT(id < fOffsetArrays.count()); OffsetArray* array = fOffsetArrays[id]; for (int i = 0; i < array->fOffsets.count(); ++i) { if (array->fOffsets[i] == offset) { return true; } else if (array->fOffsets[i] > offset) { return false; } } // Calls to 'includes' should be gaurded by an overlap() call, so we // should always find something. SkASSERT(0); return false; } protected: class OffsetArray { public: void add(size_t offset) { SkASSERT(fOffsets.count() == 0 || offset > this->max()); *fOffsets.append() = offset; } size_t min() const { SkASSERT(fOffsets.count() > 0); return fOffsets[0]; } size_t max() const { SkASSERT(fOffsets.count() > 0); return fOffsets[fOffsets.count()-1]; } int count() const { return fOffsets.count(); } SkTDArray fOffsets; }; SkTDArray fOffsetArrays; private: typedef SkRefCnt INHERITED; }; #endif