blob: 8fd2b62366991b9383420f3370d21b620e49622d [file] [log] [blame]
// 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/scrollbar_layer_impl.h"
#include "cc/layer_tree_impl.h"
#include "cc/layer_tree_settings.h"
#include "cc/quad_sink.h"
#include "cc/scrollbar_animation_controller.h"
#include "cc/solid_color_draw_quad.h"
#include "cc/texture_draw_quad.h"
#include "ui/gfx/rect_conversions.h"
using WebKit::WebRect;
using WebKit::WebScrollbar;
namespace cc {
scoped_ptr<ScrollbarLayerImpl> ScrollbarLayerImpl::Create(
LayerTreeImpl* tree_impl,
int id,
scoped_ptr<ScrollbarGeometryFixedThumb> geometry) {
return make_scoped_ptr(new ScrollbarLayerImpl(tree_impl,
id,
geometry.Pass()));
}
ScrollbarLayerImpl::ScrollbarLayerImpl(
LayerTreeImpl* tree_impl,
int id,
scoped_ptr<ScrollbarGeometryFixedThumb> geometry)
: ScrollbarLayerImplBase(tree_impl, id),
scrollbar_(this),
back_track_resource_id_(0),
fore_track_resource_id_(0),
thumb_resource_id_(0),
geometry_(geometry.Pass()),
current_pos_(0),
total_size_(0),
maximum_(0),
scroll_layer_id_(-1),
scrollbar_overlay_style_(WebScrollbar::ScrollbarOverlayStyleDefault),
orientation_(WebScrollbar::Horizontal),
control_size_(WebScrollbar::RegularScrollbar),
pressed_part_(WebScrollbar::NoPart),
hovered_part_(WebScrollbar::NoPart),
is_scrollable_area_active_(false),
is_scroll_view_scrollbar_(false),
enabled_(false),
is_custom_scrollbar_(false),
is_overlay_scrollbar_(false) {}
ScrollbarLayerImpl::~ScrollbarLayerImpl() {}
ScrollbarLayerImpl* ScrollbarLayerImpl::toScrollbarLayer() {
return this;
}
void ScrollbarLayerImpl::SetScrollbarData(WebScrollbar* scrollbar) {
scrollbar_overlay_style_ = scrollbar->scrollbarOverlayStyle();
orientation_ = scrollbar->orientation();
control_size_ = scrollbar->controlSize();
pressed_part_ = scrollbar->pressedPart();
hovered_part_ = scrollbar->hoveredPart();
is_scrollable_area_active_ = scrollbar->isScrollableAreaActive();
is_scroll_view_scrollbar_ = scrollbar->isScrollViewScrollbar();
enabled_ = scrollbar->enabled();
is_custom_scrollbar_ = scrollbar->isCustomScrollbar();
is_overlay_scrollbar_ = scrollbar->isOverlay();
scrollbar->getTickmarks(tickmarks_);
}
void ScrollbarLayerImpl::SetThumbSize(gfx::Size size) {
thumb_size_ = size;
if (!geometry_) {
// In impl-side painting, the ScrollbarLayerImpl in the pending tree
// simply holds properties that are later pushed to the active tree's
// layer, but it doesn't hold geometry or append quads.
DCHECK(layerTreeImpl()->IsPendingTree());
return;
}
geometry_->setThumbSize(size);
}
float ScrollbarLayerImpl::CurrentPos() const {
return current_pos_;
}
int ScrollbarLayerImpl::TotalSize() const {
return total_size_;
}
int ScrollbarLayerImpl::Maximum() const {
return maximum_;
}
WebKit::WebScrollbar::Orientation ScrollbarLayerImpl::Orientation() const {
return orientation_;
}
static gfx::RectF ToUVRect(gfx::Rect r, gfx::Rect bounds) {
return gfx::ScaleRect(r, 1.f / bounds.width(), 1.f / bounds.height());
}
gfx::Rect ScrollbarLayerImpl::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::RectF content_rect = gfx::ScaleRect(layer_rect,
contentsScaleX(),
contentsScaleY());
return gfx::ToEnclosingRect(content_rect);
}
scoped_ptr<LayerImpl> ScrollbarLayerImpl::createLayerImpl(
LayerTreeImpl* tree_impl) {
return ScrollbarLayerImpl::Create(tree_impl,
id(),
geometry_.Pass()).PassAs<LayerImpl>();
}
void ScrollbarLayerImpl::pushPropertiesTo(LayerImpl* layer) {
LayerImpl::pushPropertiesTo(layer);
ScrollbarLayerImpl* scrollbar_layer = static_cast<ScrollbarLayerImpl*>(layer);
scrollbar_layer->SetScrollbarData(&scrollbar_);
scrollbar_layer->SetThumbSize(thumb_size_);
scrollbar_layer->set_back_track_resource_id(back_track_resource_id_);
scrollbar_layer->set_fore_track_resource_id(fore_track_resource_id_);
scrollbar_layer->set_thumb_resource_id(thumb_resource_id_);
}
void ScrollbarLayerImpl::appendQuads(QuadSink& quad_sink,
AppendQuadsData& append_quads_data) {
bool premultipled_alpha = true;
bool flipped = false;
gfx::PointF uv_top_left(0.f, 0.f);
gfx::PointF uv_bottom_right(1.f, 1.f);
gfx::Rect boundsRect(gfx::Point(), bounds());
gfx::Rect contentBoundsRect(gfx::Point(), contentBounds());
SharedQuadState* shared_quad_state =
quad_sink.useSharedQuadState(createSharedQuadState());
appendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
WebRect thumb_rect, back_track_rect, foreTrackRect;
geometry_->splitTrack(&scrollbar_,
geometry_->trackRect(&scrollbar_),
back_track_rect,
thumb_rect,
foreTrackRect);
if (!geometry_->hasThumb(&scrollbar_))
thumb_rect = WebRect();
if (layerTreeImpl()->settings().solidColorScrollbars) {
int thickness_override =
layerTreeImpl()->settings().solidColorScrollbarThicknessDIP;
if (thickness_override != -1) {
if (scrollbar_.orientation() == WebScrollbar::Vertical)
thumb_rect.width = thickness_override;
else
thumb_rect.height = thickness_override;
}
gfx::Rect quad_rect(ScrollbarLayerRectToContentRect(thumb_rect));
scoped_ptr<SolidColorDrawQuad> quad = SolidColorDrawQuad::Create();
quad->SetNew(shared_quad_state,
quad_rect,
layerTreeImpl()->settings().solidColorScrollbarColor);
quad_sink.append(quad.PassAs<DrawQuad>(), append_quads_data);
return;
}
if (thumb_resource_id_ && !thumb_rect.isEmpty()) {
gfx::Rect quad_rect(ScrollbarLayerRectToContentRect(thumb_rect));
gfx::Rect opaque_rect;
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
quad_rect,
opaque_rect,
thumb_resource_id_,
premultipled_alpha,
uv_top_left,
uv_bottom_right,
opacity,
flipped);
quad_sink.append(quad.PassAs<DrawQuad>(), append_quads_data);
}
if (!back_track_resource_id_)
return;
// We only paint the track in two parts if we were given a texture for the
// forward track part.
if (fore_track_resource_id_ && !foreTrackRect.isEmpty()) {
gfx::Rect quad_rect(ScrollbarLayerRectToContentRect(foreTrackRect));
gfx::Rect opaque_rect(contentsOpaque() ? quad_rect : gfx::Rect());
gfx::RectF uv_rect(ToUVRect(foreTrackRect, boundsRect));
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
quad_rect,
opaque_rect,
fore_track_resource_id_,
premultipled_alpha,
uv_rect.origin(),
uv_rect.bottom_right(),
opacity,
flipped);
quad_sink.append(quad.PassAs<DrawQuad>(), append_quads_data);
}
// Order matters here: since the back track texture is being drawn to the
// entire contents rect, we must append it after the thumb and fore track
// quads. The back track texture contains (and displays) the buttons.
if (!contentBoundsRect.IsEmpty()) {
gfx::Rect quad_rect(contentBoundsRect);
gfx::Rect opaque_rect(contentsOpaque() ? quad_rect : gfx::Rect());
const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create();
quad->SetNew(shared_quad_state,
quad_rect,
opaque_rect,
back_track_resource_id_,
premultipled_alpha,
uv_top_left,
uv_bottom_right,
opacity,
flipped);
quad_sink.append(quad.PassAs<DrawQuad>(), append_quads_data);
}
}
void ScrollbarLayerImpl::didLoseOutputSurface() {
back_track_resource_id_ = 0;
fore_track_resource_id_ = 0;
thumb_resource_id_ = 0;
}
bool ScrollbarLayerImpl::Scrollbar::isOverlay() const {
return owner_->is_overlay_scrollbar_;
}
int ScrollbarLayerImpl::Scrollbar::value() const {
return owner_->CurrentPos();
}
WebKit::WebPoint ScrollbarLayerImpl::Scrollbar::location() const {
return WebKit::WebPoint();
}
WebKit::WebSize ScrollbarLayerImpl::Scrollbar::size() const {
return WebKit::WebSize(owner_->bounds().width(), owner_->bounds().height());
}
bool ScrollbarLayerImpl::Scrollbar::enabled() const {
return owner_->enabled_;
}
int ScrollbarLayerImpl::Scrollbar::maximum() const {
return owner_->Maximum();
}
int ScrollbarLayerImpl::Scrollbar::totalSize() const {
return owner_->TotalSize();
}
bool ScrollbarLayerImpl::Scrollbar::isScrollViewScrollbar() const {
return owner_->is_scroll_view_scrollbar_;
}
bool ScrollbarLayerImpl::Scrollbar::isScrollableAreaActive() const {
return owner_->is_scrollable_area_active_;
}
void ScrollbarLayerImpl::Scrollbar::getTickmarks(
WebKit::WebVector<WebRect>& tickmarks) const {
tickmarks = owner_->tickmarks_;
}
WebScrollbar::ScrollbarControlSize ScrollbarLayerImpl::Scrollbar::controlSize()
const {
return owner_->control_size_;
}
WebScrollbar::ScrollbarPart ScrollbarLayerImpl::Scrollbar::pressedPart() const {
return owner_->pressed_part_;
}
WebScrollbar::ScrollbarPart ScrollbarLayerImpl::Scrollbar::hoveredPart() const {
return owner_->hovered_part_;
}
WebScrollbar::ScrollbarOverlayStyle
ScrollbarLayerImpl::Scrollbar::scrollbarOverlayStyle() const {
return owner_->scrollbar_overlay_style_;
}
WebScrollbar::Orientation ScrollbarLayerImpl::Scrollbar::orientation() const {
return owner_->orientation_;
}
bool ScrollbarLayerImpl::Scrollbar::isCustomScrollbar() const {
return owner_->is_custom_scrollbar_;
}
const char* ScrollbarLayerImpl::layerTypeAsString() const {
return "ScrollbarLayer";
}
} // namespace cc