OLD | NEW |
(Empty) | |
| 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. |
| 4 |
| 5 #include "cc/pinch_zoom_scrollbar_layer_impl.h" |
| 6 |
| 7 #include "cc/layer_tree_host_impl.h" |
| 8 #include "cc/layer_tree_impl.h" |
| 9 #include "cc/quad_sink.h" |
| 10 #include "cc/renderer.h" |
| 11 #include "cc/texture_draw_quad.h" |
| 12 #include "skia/ext/platform_canvas.h" |
| 13 #include "ui/gfx/rect.h" |
| 14 #include "ui/gfx/rect_conversions.h" |
| 15 |
| 16 namespace cc { |
| 17 |
| 18 PinchZoomScrollbarState::PinchZoomScrollbarState( |
| 19 WebKit::WebScrollbar::Orientation orientation, PinchZoomViewport* owner) |
| 20 : owner_(owner), |
| 21 orientation_(orientation) { |
| 22 DCHECK(owner_); |
| 23 } |
| 24 |
| 25 PinchZoomScrollbarState::~PinchZoomScrollbarState() {} |
| 26 |
| 27 gfx::SizeF PinchZoomScrollbarState::layout_viewport_size() const { |
| 28 return owner_->layout_viewport_size(); |
| 29 } |
| 30 |
| 31 gfx::Vector2dF PinchZoomScrollbarState::zoomed_viewport_offset() const { |
| 32 return owner_->zoomed_viewport_offset(); |
| 33 } |
| 34 |
| 35 float PinchZoomScrollbarState::total_page_scale_factor() const { |
| 36 return owner_->total_page_scale_factor(); |
| 37 } |
| 38 |
| 39 float PinchZoomScrollbarState::device_scale_factor() const { |
| 40 return owner_->device_scale_factor(); |
| 41 } |
| 42 |
| 43 LayerImpl* PinchZoomScrollbarState::root_scroll_layer() { |
| 44 return owner_->root_scroll_layer(); |
| 45 } |
| 46 |
| 47 void PinchZoomScrollbarState::RefreshSizeAndPosition(LayerImpl* layer_impl) |
| 48 { |
| 49 gfx::SizeF size = owner_->layout_viewport_size(); |
| 50 if (orientation_ == WebKit::WebScrollbar::Vertical) { |
| 51 gfx::Size bounds = gfx::Size(kTrackWidth, size.height()); |
| 52 layer_impl->setContentBounds(bounds); |
| 53 layer_impl->setBounds(bounds); |
| 54 layer_impl->setPosition(gfx::Point(size.width() - kTrackWidth, 0)); |
| 55 } else { |
| 56 gfx::Size bounds = gfx::Size(size.width(), kTrackWidth); |
| 57 layer_impl->setContentBounds(bounds); |
| 58 layer_impl->setBounds(bounds); |
| 59 layer_impl->setPosition(gfx::Point(0, size.height() - kTrackWidth)); |
| 60 } |
| 61 } |
| 62 |
| 63 bool PinchZoomScrollbarState::ShouldDisplayPinchZoomScrollbars() { |
| 64 return owner_->total_page_scale_factor() > 1 && owner_->currently_scrolling_la
yer(); |
| 65 } |
| 66 |
| 67 scoped_ptr<PinchZoomScrollbarLayerImpl> PinchZoomScrollbarLayerImpl::create( |
| 68 LayerTreeImpl* treeImpl, |
| 69 int id, |
| 70 PinchZoomScrollbarState* state) { |
| 71 return make_scoped_ptr(new PinchZoomScrollbarLayerImpl(treeImpl, id, state)); |
| 72 } |
| 73 |
| 74 PinchZoomScrollbarLayerImpl::PinchZoomScrollbarLayerImpl( |
| 75 LayerTreeImpl* treeImpl, |
| 76 int id, PinchZoomScrollbarState* state) |
| 77 : ScrollbarLayerImplBase(treeImpl, id), |
| 78 state_(state) { |
| 79 DCHECK(state_); |
| 80 std::string debugName = "Layer for Pinch Zoom Scrollbar "; |
| 81 debugName += ((state_->orientation() == WebKit::WebScrollbar::Vertical) ? |
| 82 "(vertical)" : "(horizontal)"); |
| 83 setDebugName(debugName); |
| 84 |
| 85 state_->RefreshSizeAndPosition(this); |
| 86 } |
| 87 |
| 88 PinchZoomScrollbarLayerImpl::~PinchZoomScrollbarLayerImpl() {} |
| 89 |
| 90 float PinchZoomScrollbarLayerImpl::currentPos() const { |
| 91 return state_->thumb_position(); |
| 92 } |
| 93 |
| 94 int PinchZoomScrollbarLayerImpl::totalSize() const { |
| 95 return state_->track_length(); |
| 96 } |
| 97 |
| 98 int PinchZoomScrollbarLayerImpl::maximum() const { |
| 99 return state_->maximum_position(); |
| 100 } |
| 101 |
| 102 WebKit::WebScrollbar::Orientation PinchZoomScrollbarLayerImpl::orientation() |
| 103 const { |
| 104 return state_->orientation(); |
| 105 } |
| 106 |
| 107 void PinchZoomScrollbarLayerImpl::appendQuads( |
| 108 QuadSink& quad_sink, AppendQuadsData& append_quads_data) { |
| 109 if (!state_->ShouldDisplayPinchZoomScrollbars()) |
| 110 return; |
| 111 |
| 112 if (state_->thumb_rect().IsEmpty() || !state_->thumb_texture()->id()) |
| 113 return; |
| 114 |
| 115 bool premultipled_alpha = false; |
| 116 bool flipped = false; |
| 117 gfx::RectF uv_rect(0, 0, 1, 1); |
| 118 |
| 119 SharedQuadState* shared_quad_state = |
| 120 quad_sink.useSharedQuadState(createSharedQuadState()); |
| 121 appendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); |
| 122 |
| 123 gfx::Rect quad_rect(gfx::ToEnclosingRect( |
| 124 gfx::ScaleRect(state_->thumb_rect(), |
| 125 contentsScaleX(), contentsScaleY()))); |
| 126 |
| 127 gfx::Rect opaque_rect; |
| 128 const float opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; |
| 129 scoped_ptr<TextureDrawQuad> quad = TextureDrawQuad::Create(); |
| 130 quad->SetNew(shared_quad_state, quad_rect, opaque_rect, |
| 131 state_->thumb_texture()->id(), |
| 132 premultipled_alpha, uv_rect, opacity, flipped); |
| 133 quad_sink.append(quad.PassAs<DrawQuad>(), append_quads_data); |
| 134 } |
| 135 |
| 136 void PinchZoomScrollbarLayerImpl::willDraw( |
| 137 ResourceProvider* resource_provider) { |
| 138 LayerImpl::willDraw(resource_provider); |
| 139 |
| 140 if (!state_->ShouldDisplayPinchZoomScrollbars()) |
| 141 return; |
| 142 |
| 143 gfx::Size layout_document_size(layerTreeImpl()->ContentSize()); |
| 144 |
| 145 gfx::SizeF layout_viewport_size = state_->layout_viewport_size(); |
| 146 gfx::Vector2dF layout_viewport_position = state_->zoomed_viewport_offset(); |
| 147 float page_scale_factor = state_->total_page_scale_factor(); |
| 148 float device_scale_factor = state_->device_scale_factor(); |
| 149 |
| 150 DCHECK(!layout_document_size.IsEmpty()); |
| 151 |
| 152 gfx::Vector2d root_scroll_offset; |
| 153 gfx::Vector2d root_max_scroll_offset; |
| 154 LayerImpl* root_scroll_layer = state_->root_scroll_layer(); |
| 155 if (root_scroll_layer) { |
| 156 root_scroll_offset = root_scroll_layer->scrollOffset(); |
| 157 root_max_scroll_offset = root_scroll_layer->maxScrollOffset(); |
| 158 } |
| 159 |
| 160 gfx::Rect new_thumb_rect; |
| 161 int& track_length = state_->track_length(); |
| 162 float& thumb_position = state_->thumb_position(); |
| 163 int& maximum_position = state_->maximum_position(); |
| 164 int track_width = state_->track_width(); |
| 165 |
| 166 int thumb_length; |
| 167 if (state_->orientation() == WebKit::WebScrollbar::Vertical) { |
| 168 track_length = layout_viewport_size.height() - track_width; |
| 169 thumb_length = layout_viewport_size.height() / |
| 170 layout_document_size.height() * device_scale_factor * track_length; |
| 171 maximum_position = state_->track_length() - thumb_length; |
| 172 |
| 173 float max_offset = root_max_scroll_offset.y() + (page_scale_factor - 1) |
| 174 / page_scale_factor * layout_viewport_size.height(); |
| 175 float offset = (max_offset >= 1) ? root_scroll_offset.y() + |
| 176 layout_viewport_position.y() : 0; |
| 177 thumb_position = offset / max_offset * maximum_position; |
| 178 |
| 179 // Thumb rect position is with respect to the layer, so the x-coordinate |
| 180 // should be 0. |
| 181 new_thumb_rect = gfx::Rect(0, thumb_position, track_width, thumb_length); |
| 182 } else { |
| 183 track_length = layout_viewport_size.width() - track_width; |
| 184 thumb_length = layout_viewport_size.width() / layout_document_size.width() * |
| 185 device_scale_factor * track_length; |
| 186 maximum_position = track_length - thumb_length; |
| 187 |
| 188 float max_offset = root_max_scroll_offset.x() + (page_scale_factor - 1) |
| 189 / page_scale_factor * layout_viewport_size.width(); |
| 190 float offset = (max_offset >= 1) ? root_scroll_offset.x() + |
| 191 layout_viewport_position.x() : 0; |
| 192 thumb_position = offset / max_offset * maximum_position; |
| 193 |
| 194 // Thumb rect position is with respect to the layer, so the y-coordinate |
| 195 // should be 0. |
| 196 new_thumb_rect = gfx::Rect(thumb_position, 0, thumb_length, track_width); |
| 197 } |
| 198 |
| 199 gfx::Rect& thumb_rect = state_->thumb_rect(); |
| 200 scoped_ptr<ScopedResource>& thumb_texture = state_->thumb_texture(); |
| 201 |
| 202 bool thumb_size_not_changed = thumb_rect.size() == new_thumb_rect.size(); |
| 203 thumb_rect = new_thumb_rect; |
| 204 if (thumb_size_not_changed && thumb_texture) |
| 205 return; |
| 206 |
| 207 // Does texture exist, if not, create it. |
| 208 if (!thumb_texture) |
| 209 thumb_texture = ScopedResource::create(resource_provider); |
| 210 |
| 211 if (thumb_texture->size() != thumb_rect.size()) |
| 212 thumb_texture->Free(); |
| 213 |
| 214 if (!thumb_texture->id()) |
| 215 thumb_texture->Allocate(thumb_rect.size(), GL_RGBA, |
| 216 ResourceProvider::TextureUsageAny); |
| 217 |
| 218 // Paint canvas and upload to texture. |
| 219 scoped_ptr<SkCanvas> canvas = make_scoped_ptr( |
| 220 skia::CreateBitmapCanvas(thumb_rect.width(), thumb_rect.height(), |
| 221 false /* opaque */)); |
| 222 canvas->clear(SkColorSetARGB(0, 0, 0, 0)); |
| 223 SkPaint paint; |
| 224 // Below 255 refers to blue, not red, but we do this to avoid an |
| 225 // explicit swizzle. |
| 226 paint.setColor(SkColorSetARGB(128, 255, 0, 0)); |
| 227 SkScalar border = device_scale_factor; |
| 228 SkScalar corner_radius = device_scale_factor * (track_width / 3); |
| 229 DCHECK(corner_radius); |
| 230 SkRect rect = SkRect::MakeXYWH(border, border, |
| 231 thumb_rect.width() - 2 * border, |
| 232 thumb_rect.height() - 2 * border); |
| 233 canvas->drawRoundRect(rect, corner_radius, corner_radius, paint); |
| 234 |
| 235 const SkBitmap* bitmap = &canvas->getDevice()->accessBitmap(false); |
| 236 SkAutoLockPixels locker(*bitmap); |
| 237 gfx::Rect layer_rect(gfx::Point(), thumb_rect.size()); |
| 238 DCHECK(bitmap->config() == SkBitmap::kARGB_8888_Config); |
| 239 resource_provider->setPixels(thumb_texture->id(), static_cast<const uint8_t*>( |
| 240 bitmap->getPixels()), layer_rect, layer_rect, |
| 241 gfx::Vector2d()); |
| 242 } |
| 243 |
| 244 void PinchZoomScrollbarLayerImpl::didLoseOutputSurface() { |
| 245 state_->thumb_texture().reset(0);; |
| 246 } |
| 247 |
| 248 } // namespace cc |
OLD | NEW |