webapps: fix theme color on status bar for Galaxy devices
[chromium-blink-merge.git] / cc / playback / discardable_image_map.cc
blobe11527773bab1a7a4e04e6ab99cd0672cbbb75b8
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "cc/playback/discardable_image_map.h"
7 #include <algorithm>
8 #include <limits>
10 #include "cc/base/math_util.h"
11 #include "cc/playback/display_item_list.h"
12 #include "cc/playback/picture.h"
13 #include "skia/ext/discardable_image_utils.h"
14 #include "ui/gfx/geometry/rect_conversions.h"
16 namespace cc {
18 DiscardableImageMap::DiscardableImageMap(const gfx::Size& cell_size)
19 : cell_size_(cell_size) {
20 DCHECK(!cell_size.IsEmpty());
23 DiscardableImageMap::~DiscardableImageMap() {}
25 void DiscardableImageMap::GatherImagesFromPicture(SkPicture* picture,
26 const gfx::Rect& layer_rect) {
27 DCHECK(picture);
29 int min_x = std::numeric_limits<int>::max();
30 int min_y = std::numeric_limits<int>::max();
31 int max_x = 0;
32 int max_y = 0;
34 skia::DiscardableImageList images;
35 skia::DiscardableImageUtils::GatherDiscardableImages(picture, &images);
36 for (skia::DiscardableImageList::const_iterator it = images.begin();
37 it != images.end(); ++it) {
38 // The image rect is in space relative to the picture, but it can extend far
39 // beyond the picture itself (since it represents the rect of actual image
40 // contained within the picture, not clipped to picture bounds). We only
41 // care about image queries that intersect the picture, so insert only into
42 // the intersection of the two rects.
43 gfx::Rect rect_clipped_to_picture = gfx::IntersectRects(
44 gfx::ToEnclosingRect(gfx::SkRectToRectF(it->image_rect)),
45 gfx::Rect(layer_rect.size()));
47 gfx::Point min(MathUtil::UncheckedRoundDown(rect_clipped_to_picture.x(),
48 cell_size_.width()),
49 MathUtil::UncheckedRoundDown(rect_clipped_to_picture.y(),
50 cell_size_.height()));
51 gfx::Point max(MathUtil::UncheckedRoundDown(rect_clipped_to_picture.right(),
52 cell_size_.width()),
53 MathUtil::UncheckedRoundDown(
54 rect_clipped_to_picture.bottom(), cell_size_.height()));
56 // We recorded the picture as if it was at (0, 0) by translating by layer
57 // rect origin. Add the rect origin back here. It really doesn't make much
58 // of a difference, since the query for pixel refs doesn't use this
59 // information. However, since picture pile / display list also returns this
60 // information, it would be nice to express it relative to the layer, not
61 // relative to the particular implementation of the raster source.
62 skia::PositionImage position_image = *it;
63 position_image.image_rect.offset(layer_rect.x(), layer_rect.y());
65 for (int y = min.y(); y <= max.y(); y += cell_size_.height()) {
66 for (int x = min.x(); x <= max.x(); x += cell_size_.width()) {
67 ImageMapKey key(x, y);
68 data_hash_map_[key].push_back(position_image);
72 min_x = std::min(min_x, min.x());
73 min_y = std::min(min_y, min.y());
74 max_x = std::max(max_x, max.x());
75 max_y = std::max(max_y, max.y());
78 min_pixel_cell_ = gfx::Point(min_x, min_y);
79 max_pixel_cell_ = gfx::Point(max_x, max_y);
82 base::LazyInstance<Images> DiscardableImageMap::Iterator::empty_images_;
84 DiscardableImageMap::Iterator::Iterator()
85 : target_image_map_(NULL),
86 current_images_(empty_images_.Pointer()),
87 current_index_(0),
88 min_point_(-1, -1),
89 max_point_(-1, -1),
90 current_x_(0),
91 current_y_(0) {}
93 DiscardableImageMap::Iterator::Iterator(const gfx::Rect& rect,
94 const Picture* picture)
95 : target_image_map_(&(picture->images_)),
96 current_images_(empty_images_.Pointer()),
97 current_index_(0) {
98 map_layer_rect_ = picture->layer_rect_;
99 PointToFirstImage(rect);
102 DiscardableImageMap::Iterator::Iterator(const gfx::Rect& rect,
103 const DisplayItemList* display_list)
104 : target_image_map_(display_list->images_.get()),
105 current_images_(empty_images_.Pointer()),
106 current_index_(0) {
107 map_layer_rect_ = display_list->layer_rect_;
108 PointToFirstImage(rect);
111 DiscardableImageMap::Iterator::~Iterator() {}
113 DiscardableImageMap::Iterator& DiscardableImageMap::Iterator::operator++() {
114 ++current_index_;
115 // If we're not at the end of the list, then we have the next item.
116 if (current_index_ < current_images_->size())
117 return *this;
119 DCHECK(current_y_ <= max_point_.y());
120 while (true) {
121 gfx::Size cell_size = target_image_map_->cell_size_;
123 // Advance the current grid cell.
124 current_x_ += cell_size.width();
125 if (current_x_ > max_point_.x()) {
126 current_y_ += cell_size.height();
127 current_x_ = min_point_.x();
128 if (current_y_ > max_point_.y()) {
129 current_images_ = empty_images_.Pointer();
130 current_index_ = 0;
131 break;
135 // If there are no pixel refs at this grid cell, keep incrementing.
136 ImageMapKey key(current_x_, current_y_);
137 ImageHashmap::const_iterator iter =
138 target_image_map_->data_hash_map_.find(key);
139 if (iter == target_image_map_->data_hash_map_.end())
140 continue;
142 // We found a non-empty list: store it and get the first pixel ref.
143 current_images_ = &iter->second;
144 current_index_ = 0;
145 break;
147 return *this;
150 void DiscardableImageMap::Iterator::PointToFirstImage(const gfx::Rect& rect) {
151 gfx::Rect query_rect(rect);
152 // Early out if the query rect doesn't intersect this picture.
153 if (!query_rect.Intersects(map_layer_rect_) || !target_image_map_) {
154 min_point_ = gfx::Point(0, 0);
155 max_point_ = gfx::Point(0, 0);
156 current_x_ = 1;
157 current_y_ = 1;
158 return;
161 // First, subtract the layer origin as cells are stored in layer space.
162 query_rect.Offset(-map_layer_rect_.OffsetFromOrigin());
164 DCHECK(!target_image_map_->cell_size_.IsEmpty());
165 gfx::Size cell_size(target_image_map_->cell_size_);
166 // We have to find a cell_size aligned point that corresponds to
167 // query_rect. Point is a multiple of cell_size.
168 min_point_ = gfx::Point(
169 MathUtil::UncheckedRoundDown(query_rect.x(), cell_size.width()),
170 MathUtil::UncheckedRoundDown(query_rect.y(), cell_size.height()));
171 max_point_ = gfx::Point(
172 MathUtil::UncheckedRoundDown(query_rect.right() - 1, cell_size.width()),
173 MathUtil::UncheckedRoundDown(query_rect.bottom() - 1,
174 cell_size.height()));
176 // Limit the points to known pixel ref boundaries.
177 min_point_ = gfx::Point(
178 std::max(min_point_.x(), target_image_map_->min_pixel_cell_.x()),
179 std::max(min_point_.y(), target_image_map_->min_pixel_cell_.y()));
180 max_point_ = gfx::Point(
181 std::min(max_point_.x(), target_image_map_->max_pixel_cell_.x()),
182 std::min(max_point_.y(), target_image_map_->max_pixel_cell_.y()));
184 // Make the current x be cell_size.width() less than min point, so that
185 // the first increment will point at min_point_.
186 current_x_ = min_point_.x() - cell_size.width();
187 current_y_ = min_point_.y();
188 if (current_y_ <= max_point_.y())
189 ++(*this);
192 } // namespace cc