OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2012 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/layers/picture_scrollbar_layer.h" | |
6 | |
7 #if !USE_REGULAR_SCROLLBAR | |
8 | |
9 #include "base/auto_reset.h" | |
10 #include "base/basictypes.h" | |
11 #include "base/debug/trace_event.h" | |
12 #include "cc/layers/picture_scrollbar_layer_impl.h" | |
13 #include "cc/resources/caching_bitmap_content_layer_updater.h" | |
14 #include "cc/resources/layer_painter.h" | |
15 #include "cc/resources/resource_update_queue.h" | |
16 #include "cc/resources/ui_resource_manager.h" | |
17 #include "cc/trees/layer_tree_host.h" | |
18 #include "cc/trees/layer_tree_impl.h" | |
19 #include "skia/ext/platform_canvas.h" | |
20 #include "skia/ext/refptr.h" | |
21 #include "third_party/skia/include/core/SkSize.h" | |
22 #include "ui/gfx/rect_conversions.h" | |
23 | |
24 namespace cc { | |
25 | |
26 scoped_ptr<LayerImpl> ScrollbarLayer::CreateLayerImpl( | |
27 LayerTreeImpl* tree_impl) { | |
28 return ScrollbarLayerImpl::Create( | |
29 tree_impl, id(), scrollbar_->Orientation()).PassAs<LayerImpl>(); | |
30 } | |
31 | |
32 scoped_refptr<ScrollbarLayer> ScrollbarLayer::Create( | |
33 scoped_ptr<Scrollbar> scrollbar, | |
34 int scroll_layer_id) { | |
35 return make_scoped_refptr(new ScrollbarLayer(scrollbar.Pass(), | |
36 scroll_layer_id)); | |
37 } | |
38 | |
39 ScrollbarLayer::ScrollbarLayer( | |
40 scoped_ptr<Scrollbar> scrollbar, | |
41 int scroll_layer_id) | |
42 : scrollbar_(scrollbar.Pass()), | |
43 scroll_layer_id_(scroll_layer_id), | |
44 track_ui_resource_id_(0), | |
45 thumb_ui_resource_id_(0), | |
46 track_ui_resource_status_(UIResourceManagerClient::NOT_READY), | |
47 thumb_ui_resource_status_(UIResourceManagerClient::NOT_READY), | |
48 skip_update_(false) { | |
49 if (!scrollbar_->IsOverlay()) | |
50 SetShouldScrollOnMainThread(true); | |
51 } | |
52 | |
53 ScrollbarLayer::~ScrollbarLayer() {} | |
54 | |
55 void ScrollbarLayer::SetScrollLayerId(int id) { | |
56 if (id == scroll_layer_id_) | |
57 return; | |
58 | |
59 scroll_layer_id_ = id; | |
60 SetNeedsFullTreeSync(); | |
61 } | |
62 | |
63 bool ScrollbarLayer::OpacityCanAnimateOnImplThread() const { | |
64 return scrollbar_->IsOverlay(); | |
65 } | |
66 | |
67 ScrollbarOrientation ScrollbarLayer::Orientation() const { | |
68 return scrollbar_->Orientation(); | |
69 } | |
70 | |
71 int ScrollbarLayer::MaxTextureSize() { | |
72 DCHECK(layer_tree_host()); | |
73 return layer_tree_host()->GetRendererCapabilities().max_texture_size; | |
74 } | |
75 | |
76 float ScrollbarLayer::ClampScaleToMaxTextureSize(float scale) { | |
77 if (layer_tree_host()->settings().solid_color_scrollbars) | |
78 return scale; | |
79 | |
80 // If the scaled content_bounds() is bigger than the max texture size of the | |
81 // device, we need to clamp it by rescaling, since content_bounds() is used | |
82 // below to set the texture size. | |
83 gfx::Size scaled_bounds = ComputeContentBoundsForScale(scale, scale); | |
84 if (scaled_bounds.width() > MaxTextureSize() || | |
85 scaled_bounds.height() > MaxTextureSize()) { | |
86 if (scaled_bounds.width() > scaled_bounds.height()) | |
87 return (MaxTextureSize() - 1) / static_cast<float>(bounds().width()); | |
88 else | |
89 return (MaxTextureSize() - 1) / static_cast<float>(bounds().height()); | |
90 } | |
91 return scale; | |
92 } | |
93 | |
94 void ScrollbarLayer::CalculateContentsScale(float ideal_contents_scale, | |
95 float device_scale_factor, | |
96 float page_scale_factor, | |
97 bool animating_transform_to_screen, | |
98 float* contents_scale_x, | |
99 float* contents_scale_y, | |
100 gfx::Size* content_bounds) { | |
101 ContentsScalingLayer::CalculateContentsScale( | |
102 ClampScaleToMaxTextureSize(ideal_contents_scale), | |
103 device_scale_factor, | |
104 page_scale_factor, | |
105 animating_transform_to_screen, | |
106 contents_scale_x, | |
107 contents_scale_y, | |
108 content_bounds); | |
109 } | |
110 | |
111 void ScrollbarLayer::PushPropertiesTo(LayerImpl* layer) { | |
112 ContentsScalingLayer::PushPropertiesTo(layer); | |
113 | |
114 ScrollbarLayerImpl* scrollbar_layer = static_cast<ScrollbarLayerImpl*>(layer); | |
115 | |
116 if (layer_tree_host() && | |
117 layer_tree_host()->settings().solid_color_scrollbars) { | |
118 int thickness_override = | |
119 layer_tree_host()->settings().solid_color_scrollbar_thickness_dip; | |
120 if (thickness_override != -1) { | |
121 scrollbar_layer->set_thumb_thickness(thickness_override); | |
122 } else { | |
123 if (Orientation() == HORIZONTAL) | |
124 scrollbar_layer->set_thumb_thickness(bounds().height()); | |
125 else | |
126 scrollbar_layer->set_thumb_thickness(bounds().width()); | |
127 } | |
128 } else { | |
129 scrollbar_layer->set_thumb_thickness(thumb_thickness_); | |
130 } | |
131 scrollbar_layer->set_thumb_length(thumb_length_); | |
132 | |
133 if (Orientation() == HORIZONTAL) { | |
134 scrollbar_layer->set_track_start(track_rect_.x()); | |
135 scrollbar_layer->set_track_length(track_rect_.width()); | |
136 } else { | |
137 scrollbar_layer->set_track_start(track_rect_.y()); | |
138 scrollbar_layer->set_track_length(track_rect_.height()); | |
139 } | |
140 | |
141 if (track_ui_resource_status_ == UIResourceManagerClient::READY) { | |
142 scrollbar_layer->set_track_ui_resource_id(track_ui_resource_id_); | |
143 } else { | |
144 scrollbar_layer->set_track_ui_resource_id(0); | |
145 } | |
146 | |
147 if (thumb_ui_resource_status_ == UIResourceManagerClient::READY) { | |
148 scrollbar_layer->set_thumb_ui_resource_id(thumb_ui_resource_id_); | |
149 } else { | |
150 scrollbar_layer->set_thumb_ui_resource_id(0); | |
151 } | |
152 } | |
153 | |
154 ScrollbarLayer* ScrollbarLayer::ToScrollbarLayer() { | |
155 return this; | |
156 } | |
157 | |
158 void ScrollbarLayer::SetLayerTreeHost(LayerTreeHost* host) { | |
159 ContentsScalingLayer::SetLayerTreeHost(host); | |
160 } | |
161 | |
162 gfx::Rect ScrollbarLayer::ScrollbarLayerRectToContentRect( | |
163 gfx::Rect layer_rect) const { | |
164 // Don't intersect with the bounds as in LayerRectToContentRect() because | |
165 // layer_rect here might be in coordinates of the containing layer. | |
166 gfx::Rect expanded_rect = gfx::ScaleToEnclosingRect( | |
167 layer_rect, contents_scale_y(), contents_scale_y()); | |
168 // We should never return a rect bigger than the content_bounds(). | |
169 gfx::Size clamped_size = expanded_rect.size(); | |
170 clamped_size.SetToMin(content_bounds()); | |
171 expanded_rect.set_size(clamped_size); | |
172 return expanded_rect; | |
173 } | |
174 | |
175 void ScrollbarLayer::Update(ResourceUpdateQueue* queue, | |
176 const OcclusionTracker* occlusion) { | |
177 track_rect_ = scrollbar_->TrackRect(); | |
178 | |
179 if (layer_tree_host()->settings().solid_color_scrollbars) | |
180 return; | |
181 | |
182 base::AutoReset<bool> ignore_set_needs_commit(&ignore_set_needs_commit_, | |
183 true); | |
184 ContentsScalingLayer::Update(queue, occlusion); | |
185 | |
186 if (scrollbar_->HasThumb()) { | |
187 thumb_thickness_ = scrollbar_->ThumbThickness(); | |
188 thumb_length_ = scrollbar_->ThumbLength(); | |
189 gfx::Rect origin_thumb_rect = OriginThumbRect(); | |
190 } | |
191 | |
192 if (skip_update_) { | |
193 skip_update_ = false; | |
194 return; | |
195 } | |
196 | |
197 gfx::Rect track_rect = ScrollbarLayerRectToContentRect( | |
198 gfx::Rect(scrollbar_->Location(), bounds())); | |
199 gfx::Rect thumb_rect = OriginThumbRect(); | |
200 | |
201 { | |
202 track_bitmap_ = UIResourceBitmap::Create( | |
203 new uint8_t[track_rect.width()*track_rect.height()*4], | |
204 UIResourceBitmap::RGBA8, | |
205 track_rect.size()); | |
206 | |
207 // raster track | |
208 skia::RefPtr<SkCanvas> track_canvas = skia::AdoptRef( | |
209 skia::CreatePlatformCanvas(track_rect.width(), | |
210 track_rect.height(), | |
211 false, | |
212 reinterpret_cast<uint8_t*>( | |
213 track_bitmap_->GetPixels()), | |
214 skia::CRASH_ON_FAILURE)); | |
215 | |
216 track_canvas->save(); | |
217 track_canvas->translate(SkFloatToScalar(-track_rect.x()), | |
218 SkFloatToScalar(-track_rect.y())); | |
219 SkPaint paint; | |
220 paint.setAntiAlias(false); | |
221 paint.setXfermodeMode(SkXfermode::kClear_Mode); | |
222 SkRect layer_sk_rect = SkRect::MakeXYWH(track_rect.x(), | |
223 track_rect.y(), | |
224 track_rect.width(), | |
225 track_rect.height()); | |
226 | |
227 track_canvas->drawRect(layer_sk_rect, paint); | |
228 track_canvas->clipRect(layer_sk_rect); | |
229 scrollbar_->PaintPart(track_canvas.get(), TRACK, track_rect); | |
230 track_canvas->restore(); | |
231 | |
232 if (track_ui_resource_id_) { | |
233 layer_tree_host()->DeleteUIResource(track_ui_resource_id_); | |
234 } | |
235 track_ui_resource_id_ = layer_tree_host()->CreateUIResource(track_bitmap_, | |
236 this); | |
237 } | |
238 | |
239 if (scrollbar_->HasThumb()) { | |
240 thumb_bitmap_ = UIResourceBitmap::Create( | |
241 new uint8_t[thumb_rect.width()*thumb_rect.height()*4], | |
242 UIResourceBitmap::RGBA8, | |
243 thumb_rect.size()); | |
244 | |
245 // raster thumb | |
246 skia::RefPtr<SkCanvas> thumb_canvas = skia::AdoptRef( | |
247 skia::CreatePlatformCanvas(thumb_rect.width(), | |
248 thumb_rect.height(), | |
249 false, | |
250 reinterpret_cast<uint8_t*>( | |
251 thumb_bitmap_->GetPixels()), | |
252 skia::CRASH_ON_FAILURE)); | |
253 | |
254 scrollbar_->PaintPart(thumb_canvas.get(), | |
255 THUMB, | |
256 thumb_rect); | |
257 | |
258 if (thumb_ui_resource_id_) | |
259 layer_tree_host()->DeleteUIResource(thumb_ui_resource_id_); | |
260 thumb_ui_resource_id_ = layer_tree_host()->CreateUIResource(thumb_bitmap_, | |
261 this); | |
262 } | |
263 } | |
264 | |
265 gfx::Rect ScrollbarLayer::OriginThumbRect() const { | |
266 gfx::Size thumb_size; | |
267 if (Orientation() == HORIZONTAL) { | |
268 thumb_size = gfx::Size(scrollbar_->ThumbLength(), | |
269 scrollbar_->ThumbThickness()); | |
270 } else { | |
271 thumb_size = gfx::Size(scrollbar_->ThumbThickness(), | |
272 scrollbar_->ThumbLength()); | |
273 } | |
274 return ScrollbarLayerRectToContentRect(gfx::Rect(thumb_size)); | |
275 } | |
276 | |
277 void ScrollbarLayer::UIResourceReady(UIResourceId id) { | |
278 if (thumb_ui_resource_id_ == id) { | |
279 thumb_ui_resource_status_ = UIResourceManagerClient::READY; | |
280 // need to push the ui resource id to the impl thread. | |
281 // 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.
| |
282 SetNeedsDisplay(); | |
283 // if we do not have this flag, we will always have a | |
284 // setneedsdisplay request in the scheduler | |
285 skip_update_ = true; | |
286 } | |
287 | |
288 if (track_ui_resource_id_ == id) { | |
289 track_ui_resource_status_ = UIResourceManagerClient::READY; | |
290 SetNeedsDisplay(); | |
291 skip_update_ = true; | |
292 } | |
293 } | |
294 | |
295 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.
| |
296 if (thumb_ui_resource_id_ == id) | |
297 thumb_ui_resource_status_ = UIResourceManagerClient::LOST; | |
298 thumb_ui_resource_id_ = 0; | |
299 | |
300 if (track_ui_resource_id_ == id) | |
301 track_ui_resource_status_ = UIResourceManagerClient::LOST; | |
302 track_ui_resource_id_ = 0; | |
303 } | |
304 | |
305 } // namespace cc | |
306 | |
307 #endif | |
OLD | NEW |