blob: 0596c38f83b48e7ecafc74480b0cb06bc3c41478 [file] [log] [blame]
/*
* 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<size_t> fOffsets;
};
SkTDArray<OffsetArray*> fOffsetArrays;
private:
typedef SkRefCnt INHERITED;
};
#endif