[Do not revert] Roll-back V8 to version 4.4.63.
[chromium-blink-merge.git] / cc / layers / painted_scrollbar_layer.cc
blobd82ef9895890313040ed09f11ecc8250e5a363c8
1 // Copyright 2013 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/layers/painted_scrollbar_layer.h"
7 #include <algorithm>
9 #include "base/auto_reset.h"
10 #include "base/basictypes.h"
11 #include "base/trace_event/trace_event.h"
12 #include "cc/base/math_util.h"
13 #include "cc/layers/painted_scrollbar_layer_impl.h"
14 #include "cc/resources/ui_resource_bitmap.h"
15 #include "cc/trees/draw_property_utils.h"
16 #include "cc/trees/layer_tree_host.h"
17 #include "cc/trees/layer_tree_impl.h"
18 #include "skia/ext/platform_canvas.h"
19 #include "skia/ext/refptr.h"
20 #include "third_party/skia/include/core/SkBitmap.h"
21 #include "third_party/skia/include/core/SkCanvas.h"
22 #include "third_party/skia/include/core/SkSize.h"
23 #include "ui/gfx/geometry/size_conversions.h"
24 #include "ui/gfx/skia_util.h"
26 namespace cc {
28 scoped_ptr<LayerImpl> PaintedScrollbarLayer::CreateLayerImpl(
29 LayerTreeImpl* tree_impl) {
30 return PaintedScrollbarLayerImpl::Create(
31 tree_impl, id(), scrollbar_->Orientation());
34 scoped_refptr<PaintedScrollbarLayer> PaintedScrollbarLayer::Create(
35 scoped_ptr<Scrollbar> scrollbar,
36 int scroll_layer_id) {
37 return make_scoped_refptr(
38 new PaintedScrollbarLayer(scrollbar.Pass(), scroll_layer_id));
41 PaintedScrollbarLayer::PaintedScrollbarLayer(scoped_ptr<Scrollbar> scrollbar,
42 int scroll_layer_id)
43 : scrollbar_(scrollbar.Pass()),
44 scroll_layer_id_(scroll_layer_id),
45 clip_layer_id_(Layer::INVALID_ID),
46 internal_contents_scale_(0.f),
47 thumb_thickness_(scrollbar_->ThumbThickness()),
48 thumb_length_(scrollbar_->ThumbLength()),
49 is_overlay_(scrollbar_->IsOverlay()),
50 has_thumb_(scrollbar_->HasThumb()) {
51 if (!scrollbar_->IsOverlay())
52 SetShouldScrollOnMainThread(true);
55 PaintedScrollbarLayer::~PaintedScrollbarLayer() {}
57 int PaintedScrollbarLayer::ScrollLayerId() const {
58 return scroll_layer_id_;
61 void PaintedScrollbarLayer::SetScrollLayer(int layer_id) {
62 if (layer_id == scroll_layer_id_)
63 return;
65 scroll_layer_id_ = layer_id;
66 SetNeedsFullTreeSync();
69 void PaintedScrollbarLayer::SetClipLayer(int layer_id) {
70 if (layer_id == clip_layer_id_)
71 return;
73 clip_layer_id_ = layer_id;
74 SetNeedsFullTreeSync();
77 bool PaintedScrollbarLayer::OpacityCanAnimateOnImplThread() const {
78 return scrollbar_->IsOverlay();
81 ScrollbarOrientation PaintedScrollbarLayer::orientation() const {
82 return scrollbar_->Orientation();
85 int PaintedScrollbarLayer::MaxTextureSize() {
86 DCHECK(layer_tree_host());
87 return layer_tree_host()->GetRendererCapabilities().max_texture_size;
90 float PaintedScrollbarLayer::ClampScaleToMaxTextureSize(float scale) {
91 // If the scaled bounds() is bigger than the max texture size of the
92 // device, we need to clamp it by rescaling, since this is used
93 // below to set the texture size.
94 gfx::Size scaled_bounds = gfx::ToCeiledSize(gfx::ScaleSize(bounds(), scale));
95 if (scaled_bounds.width() > MaxTextureSize() ||
96 scaled_bounds.height() > MaxTextureSize()) {
97 if (scaled_bounds.width() > scaled_bounds.height())
98 return (MaxTextureSize() - 1) / static_cast<float>(bounds().width());
99 else
100 return (MaxTextureSize() - 1) / static_cast<float>(bounds().height());
102 return scale;
105 void PaintedScrollbarLayer::PushPropertiesTo(LayerImpl* layer) {
106 Layer::PushPropertiesTo(layer);
108 PushScrollClipPropertiesTo(layer);
110 PaintedScrollbarLayerImpl* scrollbar_layer =
111 static_cast<PaintedScrollbarLayerImpl*>(layer);
113 scrollbar_layer->set_internal_contents_scale_and_bounds(
114 internal_contents_scale_, internal_content_bounds_);
116 scrollbar_layer->SetThumbThickness(thumb_thickness_);
117 scrollbar_layer->SetThumbLength(thumb_length_);
118 if (orientation() == HORIZONTAL) {
119 scrollbar_layer->SetTrackStart(
120 track_rect_.x() - location_.x());
121 scrollbar_layer->SetTrackLength(track_rect_.width());
122 } else {
123 scrollbar_layer->SetTrackStart(
124 track_rect_.y() - location_.y());
125 scrollbar_layer->SetTrackLength(track_rect_.height());
128 if (track_resource_.get())
129 scrollbar_layer->set_track_ui_resource_id(track_resource_->id());
130 else
131 scrollbar_layer->set_track_ui_resource_id(0);
132 if (thumb_resource_.get())
133 scrollbar_layer->set_thumb_ui_resource_id(thumb_resource_->id());
134 else
135 scrollbar_layer->set_thumb_ui_resource_id(0);
137 scrollbar_layer->set_is_overlay_scrollbar(is_overlay_);
140 ScrollbarLayerInterface* PaintedScrollbarLayer::ToScrollbarLayer() {
141 return this;
144 void PaintedScrollbarLayer::PushScrollClipPropertiesTo(LayerImpl* layer) {
145 PaintedScrollbarLayerImpl* scrollbar_layer =
146 static_cast<PaintedScrollbarLayerImpl*>(layer);
148 scrollbar_layer->SetScrollLayerAndClipLayerByIds(scroll_layer_id_,
149 clip_layer_id_);
152 void PaintedScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) {
153 // When the LTH is set to null or has changed, then this layer should remove
154 // all of its associated resources.
155 if (!host || host != layer_tree_host()) {
156 track_resource_ = nullptr;
157 thumb_resource_ = nullptr;
160 Layer::SetLayerTreeHost(host);
163 gfx::Rect PaintedScrollbarLayer::ScrollbarLayerRectToContentRect(
164 const gfx::Rect& layer_rect) const {
165 // Don't intersect with the bounds as in LayerRectToContentRect() because
166 // layer_rect here might be in coordinates of the containing layer.
167 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect(
168 layer_rect, internal_contents_scale_, internal_contents_scale_);
169 // We should never return a rect bigger than the content bounds.
170 gfx::Size clamped_size = expanded_rect.size();
171 clamped_size.SetToMin(internal_content_bounds_);
172 expanded_rect.set_size(clamped_size);
173 return expanded_rect;
176 gfx::Rect PaintedScrollbarLayer::OriginThumbRect() const {
177 gfx::Size thumb_size;
178 if (orientation() == HORIZONTAL) {
179 thumb_size =
180 gfx::Size(scrollbar_->ThumbLength(), scrollbar_->ThumbThickness());
181 } else {
182 thumb_size =
183 gfx::Size(scrollbar_->ThumbThickness(), scrollbar_->ThumbLength());
185 return gfx::Rect(thumb_size);
188 void PaintedScrollbarLayer::UpdateThumbAndTrackGeometry() {
189 UpdateProperty(scrollbar_->TrackRect(), &track_rect_);
190 UpdateProperty(scrollbar_->Location(), &location_);
191 UpdateProperty(scrollbar_->IsOverlay(), &is_overlay_);
192 UpdateProperty(scrollbar_->HasThumb(), &has_thumb_);
193 if (has_thumb_) {
194 UpdateProperty(scrollbar_->ThumbThickness(), &thumb_thickness_);
195 UpdateProperty(scrollbar_->ThumbLength(), &thumb_length_);
196 } else {
197 UpdateProperty(0, &thumb_thickness_);
198 UpdateProperty(0, &thumb_length_);
202 void PaintedScrollbarLayer::UpdateInternalContentScale() {
203 float scale = layer_tree_host()->device_scale_factor();
204 if (layer_tree_host()
205 ->settings()
206 .layer_transforms_should_scale_layer_contents) {
207 gfx::Transform transform;
208 if (layer_tree_host()->using_only_property_trees()) {
209 transform = DrawTransformFromPropertyTrees(
210 this, layer_tree_host()->property_trees()->transform_tree);
211 } else {
212 transform = draw_transform();
215 gfx::Vector2dF transform_scales =
216 MathUtil::ComputeTransform2dScaleComponents(transform, scale);
217 scale = std::max(transform_scales.x(), transform_scales.y());
219 bool changed = false;
220 changed |= UpdateProperty(ClampScaleToMaxTextureSize(scale),
221 &internal_contents_scale_);
222 changed |= UpdateProperty(
223 gfx::ToCeiledSize(gfx::ScaleSize(bounds(), internal_contents_scale_)),
224 &internal_content_bounds_);
225 if (changed) {
226 // If the content scale or bounds change, repaint.
227 SetNeedsDisplay();
231 bool PaintedScrollbarLayer::Update(ResourceUpdateQueue* queue,
232 const OcclusionTracker<Layer>* occlusion) {
234 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_,
235 true);
236 Layer::Update(queue, occlusion);
237 UpdateInternalContentScale();
240 UpdateThumbAndTrackGeometry();
242 gfx::Rect track_layer_rect = gfx::Rect(location_, bounds());
243 gfx::Rect scaled_track_rect = ScrollbarLayerRectToContentRect(
244 track_layer_rect);
246 bool updated = false;
248 if (track_rect_.IsEmpty() || scaled_track_rect.IsEmpty()) {
249 if (track_resource_) {
250 track_resource_ = nullptr;
251 thumb_resource_ = nullptr;
252 SetNeedsPushProperties();
253 updated = true;
255 return updated;
258 if (!has_thumb_ && thumb_resource_) {
259 thumb_resource_ = nullptr;
260 SetNeedsPushProperties();
261 updated = true;
264 if (update_rect_.IsEmpty() && track_resource_)
265 return updated;
267 track_resource_ = ScopedUIResource::Create(
268 layer_tree_host(),
269 RasterizeScrollbarPart(track_layer_rect, scaled_track_rect, TRACK));
271 gfx::Rect thumb_layer_rect = OriginThumbRect();
272 gfx::Rect scaled_thumb_rect =
273 ScrollbarLayerRectToContentRect(thumb_layer_rect);
274 if (has_thumb_ && !scaled_thumb_rect.IsEmpty()) {
275 thumb_resource_ = ScopedUIResource::Create(
276 layer_tree_host(),
277 RasterizeScrollbarPart(thumb_layer_rect, scaled_thumb_rect, THUMB));
280 // UI resources changed so push properties is needed.
281 SetNeedsPushProperties();
282 updated = true;
283 return updated;
286 UIResourceBitmap PaintedScrollbarLayer::RasterizeScrollbarPart(
287 const gfx::Rect& layer_rect,
288 const gfx::Rect& content_rect,
289 ScrollbarPart part) {
290 DCHECK(!content_rect.size().IsEmpty());
291 DCHECK(!layer_rect.size().IsEmpty());
293 SkBitmap skbitmap;
294 skbitmap.allocN32Pixels(content_rect.width(), content_rect.height());
295 SkCanvas skcanvas(skbitmap);
297 float scale_x =
298 content_rect.width() / static_cast<float>(layer_rect.width());
299 float scale_y =
300 content_rect.height() / static_cast<float>(layer_rect.height());
302 skcanvas.scale(SkFloatToScalar(scale_x),
303 SkFloatToScalar(scale_y));
304 skcanvas.translate(SkFloatToScalar(-layer_rect.x()),
305 SkFloatToScalar(-layer_rect.y()));
307 SkRect layer_skrect = RectToSkRect(layer_rect);
308 SkPaint paint;
309 paint.setAntiAlias(false);
310 paint.setXfermodeMode(SkXfermode::kClear_Mode);
311 skcanvas.drawRect(layer_skrect, paint);
312 skcanvas.clipRect(layer_skrect);
314 scrollbar_->PaintPart(&skcanvas, part, layer_rect);
315 // Make sure that the pixels are no longer mutable to unavoid unnecessary
316 // allocation and copying.
317 skbitmap.setImmutable();
319 return UIResourceBitmap(skbitmap);
322 } // namespace cc