// Copyright 2011 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.
#include "cc/resources/layer_tiling_data.h"
#include <vector>
#include "base/logging.h"
namespace cc {
scoped_ptr<LayerTilingData> LayerTilingData::Create(gfx::Size tile_size,
BorderTexelOption border) {
return make_scoped_ptr(new LayerTilingData(tile_size, border));
}
LayerTilingData::LayerTilingData(gfx::Size tile_size, BorderTexelOption border)
: tiling_data_(tile_size, gfx::Size(), border == HAS_BORDER_TEXELS) {
SetTileSize(tile_size);
}
LayerTilingData::~LayerTilingData() {}
void LayerTilingData::SetTileSize(gfx::Size size) {
if (tile_size() == size)
return;
reset();
tiling_data_.SetMaxTextureSize(size);
}
gfx::Size LayerTilingData::tile_size() const {
return tiling_data_.max_texture_size();
}
void LayerTilingData::SetBorderTexelOption(
BorderTexelOption border_texel_option) {
bool border_texels = border_texel_option == HAS_BORDER_TEXELS;
if (has_border_texels() == border_texels)
return;
reset();
tiling_data_.SetHasBorderTexels(border_texels);
}
const LayerTilingData& LayerTilingData::operator=
(const LayerTilingData & tiler) {
tiling_data_ = tiler.tiling_data_;
return *this;
}
void LayerTilingData::AddTile(scoped_ptr<Tile> tile, int i, int j) {
DCHECK(!TileAt(i, j));
tile->move_to(i, j);
tiles_.add(std::make_pair(i, j), tile.Pass());
}
scoped_ptr<LayerTilingData::Tile> LayerTilingData::TakeTile(int i, int j) {
return tiles_.take_and_erase(std::make_pair(i, j));
}
LayerTilingData::Tile* LayerTilingData::TileAt(int i, int j) const {
return tiles_.get(std::make_pair(i, j));
}
void LayerTilingData::ContentRectToTileIndices(gfx::Rect content_rect,
int* left,
int* top,
int* right,
int* bottom) const {
// An empty rect doesn't result in an empty set of tiles, so don't pass an
// empty rect.
// TODO(enne): Possibly we should fill a vector of tiles instead, since the
// normal use of this function is to enumerate some tiles.
DCHECK(!content_rect.IsEmpty());
*left = tiling_data_.TileXIndexFromSrcCoord(content_rect.x());
*top = tiling_data_.TileYIndexFromSrcCoord(content_rect.y());
*right = tiling_data_.TileXIndexFromSrcCoord(content_rect.right() - 1);
*bottom = tiling_data_.TileYIndexFromSrcCoord(content_rect.bottom() - 1);
}
gfx::Rect LayerTilingData::TileRect(const Tile* tile) const {
gfx::Rect tile_rect = tiling_data_.TileBoundsWithBorder(tile->i(), tile->j());
tile_rect.set_size(tile_size());
return tile_rect;
}
Region LayerTilingData::OpaqueRegionInContentRect(
gfx::Rect content_rect) const {
if (content_rect.IsEmpty())
return Region();
Region opaque_region;
int left, top, right, bottom;
ContentRectToTileIndices(content_rect, &left, &top, &right, &bottom);
for (int j = top; j <= bottom; ++j) {
for (int i = left; i <= right; ++i) {
Tile* tile = TileAt(i, j);
if (!tile)
continue;
gfx::Rect tile_opaque_rect =
gfx::IntersectRects(content_rect, tile->opaque_rect());
opaque_region.Union(tile_opaque_rect);
}
}
return opaque_region;
}
void LayerTilingData::SetBounds(gfx::Size size) {
tiling_data_.SetTotalSize(size);
if (size.IsEmpty()) {
tiles_.clear();
return;
}
// Any tiles completely outside our new bounds are invalid and should be
// dropped.
int left, top, right, bottom;
ContentRectToTileIndices(
gfx::Rect(size), &left, &top, &right, &bottom);
std::vector<TileMapKey> invalid_tile_keys;
for (TileMap::const_iterator it = tiles_.begin(); it != tiles_.end(); ++it) {
if (it->first.first > right || it->first.second > bottom)
invalid_tile_keys.push_back(it->first);
}
for (size_t i = 0; i < invalid_tile_keys.size(); ++i)
tiles_.erase(invalid_tile_keys[i]);
}
} // namespace cc