Chromium Code Reviews| Index: cc/layers/picture_scrollbar_layer.cc |
| =================================================================== |
| --- cc/layers/picture_scrollbar_layer.cc (revision 0) |
| +++ cc/layers/picture_scrollbar_layer.cc (revision 0) |
| @@ -0,0 +1,307 @@ |
| +// Copyright 2012 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/layers/picture_scrollbar_layer.h" |
| + |
| +#if !USE_REGULAR_SCROLLBAR |
| + |
| +#include "base/auto_reset.h" |
| +#include "base/basictypes.h" |
| +#include "base/debug/trace_event.h" |
| +#include "cc/layers/picture_scrollbar_layer_impl.h" |
| +#include "cc/resources/caching_bitmap_content_layer_updater.h" |
| +#include "cc/resources/layer_painter.h" |
| +#include "cc/resources/resource_update_queue.h" |
| +#include "cc/resources/ui_resource_manager.h" |
| +#include "cc/trees/layer_tree_host.h" |
| +#include "cc/trees/layer_tree_impl.h" |
| +#include "skia/ext/platform_canvas.h" |
| +#include "skia/ext/refptr.h" |
| +#include "third_party/skia/include/core/SkSize.h" |
| +#include "ui/gfx/rect_conversions.h" |
| + |
| +namespace cc { |
| + |
| +scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( |
| + LayerTreeImpl* tree_impl) { |
| + return ScrollbarLayerImpl::Create( |
| + tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); |
| +} |
| + |
| +scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( |
| + scoped_ptr<Scrollbar> scrollbar, |
| + int scroll_layer_id) { |
| + return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), |
| + scroll_layer_id)); |
| +} |
| + |
| +ScrollbarLayer::ScrollbarLayer( |
| + scoped_ptr<Scrollbar> scrollbar, |
| + int scroll_layer_id) |
| + : scrollbar_(scrollbar.Pass()), |
| + scroll_layer_id_(scroll_layer_id), |
| + track_ui_resource_id_(0), |
| + thumb_ui_resource_id_(0), |
| + track_ui_resource_status_(UIResourceManagerClient::NOT_READY), |
| + thumb_ui_resource_status_(UIResourceManagerClient::NOT_READY), |
| + skip_update_(false) { |
| + if (!scrollbar_->IsOverlay()) |
| + SetShouldScrollOnMainThread(true); |
| +} |
| + |
| +ScrollbarLayer::~ScrollbarLayer() {} |
| + |
| +void ScrollbarLayer::SetScrollLayerId(int id) { |
| + if (id == scroll_layer_id_) |
| + return; |
| + |
| + scroll_layer_id_ = id; |
| + SetNeedsFullTreeSync(); |
| +} |
| + |
| +bool ScrollbarLayer::OpacityCanAnimateOnImplThread() const { |
| + return scrollbar_->IsOverlay(); |
| +} |
| + |
| +ScrollbarOrientation ScrollbarLayer::Orientation() const { |
| + return scrollbar_->Orientation(); |
| +} |
| + |
| +int ScrollbarLayer::MaxTextureSize() { |
| + DCHECK(layer_tree_host()); |
| + return layer_tree_host()->GetRendererCapabilities().max_texture_size; |
| +} |
| + |
| +float ScrollbarLayer::ClampScaleToMaxTextureSize(float scale) { |
| + if (layer_tree_host()->settings().solid_color_scrollbars) |
| + return scale; |
| + |
| + // If the scaled content_bounds() is bigger than the max texture size of the |
| + // device, we need to clamp it by rescaling, since content_bounds() is used |
| + // below to set the texture size. |
| + gfx::Size scaled_bounds = ComputeContentBoundsForScale(scale, scale); |
| + if (scaled_bounds.width() > MaxTextureSize() || |
| + scaled_bounds.height() > MaxTextureSize()) { |
| + if (scaled_bounds.width() > scaled_bounds.height()) |
| + return (MaxTextureSize() - 1) / static_cast<float>(bounds().width()); |
| + else |
| + return (MaxTextureSize() - 1) / static_cast<float>(bounds().height()); |
| + } |
| + return scale; |
| +} |
| + |
| +void ScrollbarLayer::CalculateContentsScale(float ideal_contents_scale, |
| + float device_scale_factor, |
| + float page_scale_factor, |
| + bool animating_transform_to_screen, |
| + float* contents_scale_x, |
| + float* contents_scale_y, |
| + gfx::Size* content_bounds) { |
| + ContentsScalingLayer::CalculateContentsScale( |
| + ClampScaleToMaxTextureSize(ideal_contents_scale), |
| + device_scale_factor, |
| + page_scale_factor, |
| + animating_transform_to_screen, |
| + contents_scale_x, |
| + contents_scale_y, |
| + content_bounds); |
| +} |
| + |
| +void ScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { |
| + ContentsScalingLayer::PushPropertiesTo(layer); |
| + |
| + ScrollbarLayerImpl* scrollbar_layer = static_cast<ScrollbarLayerImpl*>(layer); |
| + |
| + if (layer_tree_host() && |
| + layer_tree_host()->settings().solid_color_scrollbars) { |
| + int thickness_override = |
| + layer_tree_host()->settings().solid_color_scrollbar_thickness_dip; |
| + if (thickness_override != -1) { |
| + scrollbar_layer->set_thumb_thickness(thickness_override); |
| + } else { |
| + if (Orientation() == HORIZONTAL) |
| + scrollbar_layer->set_thumb_thickness(bounds().height()); |
| + else |
| + scrollbar_layer->set_thumb_thickness(bounds().width()); |
| + } |
| + } else { |
| + scrollbar_layer->set_thumb_thickness(thumb_thickness_); |
| + } |
| + scrollbar_layer->set_thumb_length(thumb_length_); |
| + |
| + if (Orientation() == HORIZONTAL) { |
| + scrollbar_layer->set_track_start(track_rect_.x()); |
| + scrollbar_layer->set_track_length(track_rect_.width()); |
| + } else { |
| + scrollbar_layer->set_track_start(track_rect_.y()); |
| + scrollbar_layer->set_track_length(track_rect_.height()); |
| + } |
| + |
| + if (track_ui_resource_status_ == UIResourceManagerClient::READY) { |
| + scrollbar_layer->set_track_ui_resource_id(track_ui_resource_id_); |
| + } else { |
| + scrollbar_layer->set_track_ui_resource_id(0); |
| + } |
| + |
| + if (thumb_ui_resource_status_ == UIResourceManagerClient::READY) { |
| + scrollbar_layer->set_thumb_ui_resource_id(thumb_ui_resource_id_); |
| + } else { |
| + scrollbar_layer->set_thumb_ui_resource_id(0); |
| + } |
| +} |
| + |
| +ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { |
| + return this; |
| +} |
| + |
| +void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { |
| + ContentsScalingLayer::SetLayerTreeHost(host); |
| +} |
| + |
| +gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( |
| + gfx::Rect layer_rect) const { |
| + // Don't intersect with the bounds as in LayerRectToContentRect() because |
| + // layer_rect here might be in coordinates of the containing layer. |
| + gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( |
| + layer_rect, contents_scale_y(), contents_scale_y()); |
| + // We should never return a rect bigger than the content_bounds(). |
| + gfx::Size clamped_size = expanded_rect.size(); |
| + clamped_size.SetToMin(content_bounds()); |
| + expanded_rect.set_size(clamped_size); |
| + return expanded_rect; |
| +} |
| + |
| +void ScrollbarLayer::Update(ResourceUpdateQueue* queue, |
| + const OcclusionTracker* occlusion) { |
| + track_rect_ = scrollbar_->TrackRect(); |
| + |
| + if (layer_tree_host()->settings().solid_color_scrollbars) |
| + return; |
| + |
| + base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, |
| + true); |
| + ContentsScalingLayer::Update(queue, occlusion); |
| + |
| + if (scrollbar_->HasThumb()) { |
| + thumb_thickness_ = scrollbar_->ThumbThickness(); |
| + thumb_length_ = scrollbar_->ThumbLength(); |
| + gfx::Rect origin_thumb_rect = OriginThumbRect(); |
| + } |
| + |
| + if (skip_update_) { |
| + skip_update_ = false; |
| + return; |
| + } |
| + |
| + gfx::Rect track_rect = ScrollbarLayerRectToContentRect( |
| + gfx::Rect(scrollbar_->Location(), bounds())); |
| + gfx::Rect thumb_rect = OriginThumbRect(); |
| + |
| + { |
| + track_bitmap_ = UIResourceBitmap::Create( |
| + new uint8_t[track_rect.width()*track_rect.height()*4], |
| + UIResourceBitmap::RGBA8, |
| + track_rect.size()); |
| + |
| + // raster track |
| + skia::RefPtr<SkCanvas> track_canvas = skia::AdoptRef( |
| + skia::CreatePlatformCanvas(track_rect.width(), |
| + track_rect.height(), |
| + false, |
| + reinterpret_cast<uint8_t*>( |
| + track_bitmap_->GetPixels()), |
| + skia::CRASH_ON_FAILURE)); |
| + |
| + track_canvas->save(); |
| + track_canvas->translate(SkFloatToScalar(-track_rect.x()), |
| + SkFloatToScalar(-track_rect.y())); |
| + SkPaint paint; |
| + paint.setAntiAlias(false); |
| + paint.setXfermodeMode(SkXfermode::kClear_Mode); |
| + SkRect layer_sk_rect = SkRect::MakeXYWH(track_rect.x(), |
| + track_rect.y(), |
| + track_rect.width(), |
| + track_rect.height()); |
| + |
| + track_canvas->drawRect(layer_sk_rect, paint); |
| + track_canvas->clipRect(layer_sk_rect); |
| + scrollbar_->PaintPart(track_canvas.get(), TRACK, track_rect); |
| + track_canvas->restore(); |
| + |
| + if (track_ui_resource_id_) { |
| + layer_tree_host()->DeleteUIResource(track_ui_resource_id_); |
| + } |
| + track_ui_resource_id_ = layer_tree_host()->CreateUIResource(track_bitmap_, |
| + this); |
| + } |
| + |
| + if (scrollbar_->HasThumb()) { |
| + thumb_bitmap_ = UIResourceBitmap::Create( |
| + new uint8_t[thumb_rect.width()*thumb_rect.height()*4], |
| + UIResourceBitmap::RGBA8, |
| + thumb_rect.size()); |
| + |
| + // raster thumb |
| + skia::RefPtr<SkCanvas> thumb_canvas = skia::AdoptRef( |
| + skia::CreatePlatformCanvas(thumb_rect.width(), |
| + thumb_rect.height(), |
| + false, |
| + reinterpret_cast<uint8_t*>( |
| + thumb_bitmap_->GetPixels()), |
| + skia::CRASH_ON_FAILURE)); |
| + |
| + scrollbar_->PaintPart(thumb_canvas.get(), |
| + THUMB, |
| + thumb_rect); |
| + |
| + if (thumb_ui_resource_id_) |
| + layer_tree_host()->DeleteUIResource(thumb_ui_resource_id_); |
| + thumb_ui_resource_id_ = layer_tree_host()->CreateUIResource(thumb_bitmap_, |
| + this); |
| + } |
| +} |
| + |
| +gfx::Rect ScrollbarLayer::OriginThumbRect() const { |
| + gfx::Size thumb_size; |
| + if (Orientation() == HORIZONTAL) { |
| + thumb_size = gfx::Size(scrollbar_->ThumbLength(), |
| + scrollbar_->ThumbThickness()); |
| + } else { |
| + thumb_size = gfx::Size(scrollbar_->ThumbThickness(), |
| + scrollbar_->ThumbLength()); |
| + } |
| + return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); |
| +} |
| + |
| +void ScrollbarLayer::UIResourceReady(UIResourceId id) { |
| + if (thumb_ui_resource_id_ == id) { |
| + thumb_ui_resource_status_ = UIResourceManagerClient::READY; |
| + // need to push the ui resource id to the impl thread. |
| + // Is this the only way? |
|
enne (OOO)
2013/07/09 17:57:48
I think you're looking for SetNeedsCommit.
powei
2013/07/10 17:47:21
Done.
|
| + SetNeedsDisplay(); |
| + // if we do not have this flag, we will always have a |
| + // setneedsdisplay request in the scheduler |
| + skip_update_ = true; |
| + } |
| + |
| + if (track_ui_resource_id_ == id) { |
| + track_ui_resource_status_ = UIResourceManagerClient::READY; |
| + SetNeedsDisplay(); |
| + skip_update_ = true; |
| + } |
| +} |
| + |
| +void ScrollbarLayer::UIResourceLost(UIResourceId id) { |
|
enne (OOO)
2013/07/09 17:57:48
As I mentioned in the doc about this, I would real
aelias_OOO_until_Jul13
2013/07/09 20:22:19
OK, after discussing it with dtrainor@, we agree.
|
| + if (thumb_ui_resource_id_ == id) |
| + thumb_ui_resource_status_ = UIResourceManagerClient::LOST; |
| + thumb_ui_resource_id_ = 0; |
| + |
| + if (track_ui_resource_id_ == id) |
| + track_ui_resource_status_ = UIResourceManagerClient::LOST; |
| + track_ui_resource_id_ = 0; |
| +} |
| + |
| +} // namespace cc |
| + |
| +#endif |