blob: 04a794b59812cc53336416c0b7b89cd9676c00ea [file] [log] [blame]
// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNK_SUBSET_H_
#define THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNK_SUBSET_H_
#include "third_party/blink/renderer/platform/graphics/paint/paint_artifact.h"
#include "third_party/blink/renderer/platform/wtf/allocator/allocator.h"
#include "third_party/blink/renderer/platform/wtf/vector.h"
namespace blink {
// Provides access to a subset of paint chunks in a PaintArtifact.
class PaintChunkSubset {
public:
// An empty subset.
PaintChunkSubset() = default;
// A subset containing a single paint chunk initially.
PaintChunkSubset(scoped_refptr<const PaintArtifact> paint_artifact,
wtf_size_t chunk_index)
: paint_artifact_(std::move(paint_artifact)) {
DCHECK(paint_artifact_);
DCHECK(UsesSubsetIndices());
subset_indices_.push_back(chunk_index);
}
// A subset containing the whole PaintArtifact.
PaintChunkSubset(scoped_refptr<const PaintArtifact> paint_artifact)
: PaintChunkSubset(paint_artifact,
0,
paint_artifact->PaintChunks().size()) {}
// A subset defined by a range of segments. |end_segment_index| is not
// inclusive.
PaintChunkSubset(scoped_refptr<const PaintArtifact> paint_artifact,
wtf_size_t begin_index,
wtf_size_t end_index)
: paint_artifact_(std::move(paint_artifact)),
begin_index_(begin_index),
end_index_(end_index) {
DCHECK(paint_artifact_);
DCHECK_LE(begin_index_, end_index_);
DCHECK(!UsesSubsetIndices());
}
class Iterator {
STACK_ALLOCATED();
public:
const PaintChunk& operator*() const { return GetChunk(); }
const PaintChunk* operator->() const { return &GetChunk(); }
bool operator==(const Iterator& other) const {
DCHECK_EQ(&subset_, &other.subset_);
return subset_or_chunk_index_ == other.subset_or_chunk_index_;
}
bool operator!=(const Iterator& other) const { return !(*this == other); }
const Iterator& operator++() {
++subset_or_chunk_index_;
return *this;
}
const Iterator& operator--() {
--subset_or_chunk_index_;
return *this;
}
Iterator operator+(wtf_size_t offset) const {
DCHECK_LE(subset_or_chunk_index_ + offset,
subset_.end().subset_or_chunk_index_);
return Iterator(subset_, subset_or_chunk_index_ + offset);
}
// Returns the index of the current PaintChunk in the PaintArtifact.
wtf_size_t IndexInPaintArtifact() const {
if (subset_.UsesSubsetIndices())
return subset_.subset_indices_[subset_or_chunk_index_];
return subset_or_chunk_index_;
}
DisplayItemRange DisplayItems() const {
auto& chunk = GetChunk();
return subset_.paint_artifact_->GetDisplayItemList().ItemsInRange(
chunk.begin_index, chunk.end_index);
}
private:
friend class PaintChunkSubset;
Iterator(const PaintChunkSubset& subset, wtf_size_t subset_or_chunk_index)
: subset_(subset), subset_or_chunk_index_(subset_or_chunk_index) {}
const PaintChunk& GetChunk() const {
DCHECK_LT(subset_or_chunk_index_, subset_.end().subset_or_chunk_index_);
return subset_.paint_artifact_->PaintChunks()[IndexInPaintArtifact()];
}
const PaintChunkSubset& subset_;
wtf_size_t subset_or_chunk_index_;
};
using value_type = PaintChunk;
using const_iterator = Iterator;
Iterator begin() const {
return Iterator(*this, UsesSubsetIndices() ? 0 : begin_index_);
}
Iterator end() const {
return Iterator(*this,
UsesSubsetIndices() ? subset_indices_.size() : end_index_);
}
bool IsEmpty() const {
return UsesSubsetIndices() ? subset_indices_.IsEmpty()
: begin_index_ == end_index_;
}
wtf_size_t size() const {
return UsesSubsetIndices() ? subset_indices_.size()
: end_index_ - begin_index_;
}
const PaintArtifact& GetPaintArtifact() const { return *paint_artifact_; }
void Merge(const PaintChunkSubset& other) {
DCHECK_EQ(paint_artifact_.get(), other.paint_artifact_.get());
DCHECK(UsesSubsetIndices());
DCHECK(other.UsesSubsetIndices());
subset_indices_.AppendVector(other.subset_indices_);
}
size_t ApproximateUnsharedMemoryUsage() const {
return sizeof(*this) + subset_indices_.CapacityInBytes();
}
private:
bool UsesSubsetIndices() const { return begin_index_ == kNotFound; }
scoped_refptr<const PaintArtifact> paint_artifact_;
// This is used when UsesSubsetIndices() is true.
Vector<wtf_size_t> subset_indices_;
// These are used when UsesSubsetIndices() is false.
wtf_size_t begin_index_ = kNotFound;
wtf_size_t end_index_ = kNotFound;
};
using PaintChunkIterator = PaintChunkSubset::Iterator;
} // namespace blink
#endif // THIRD_PARTY_BLINK_RENDERER_PLATFORM_GRAPHICS_PAINT_PAINT_CHUNK_SUBSET_H_