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/nine_patch_layer_impl.h" | |
6 | |
7 #include "base/strings/stringprintf.h" | |
8 #include "base/values.h" | |
9 #include "cc/base/math_util.h" | |
10 #include "cc/quads/texture_draw_quad.h" | |
11 #include "cc/trees/layer_tree_impl.h" | |
12 #include "cc/trees/occlusion.h" | |
13 #include "ui/gfx/geometry/rect_f.h" | |
14 | |
15 namespace cc { | |
16 | |
17 NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id) | |
18 : UIResourceLayerImpl(tree_impl, id), | |
19 fill_center_(false) {} | |
20 | |
21 NinePatchLayerImpl::~NinePatchLayerImpl() {} | |
22 | |
23 scoped_ptr<LayerImpl> NinePatchLayerImpl::CreateLayerImpl( | |
24 LayerTreeImpl* tree_impl) { | |
25 return NinePatchLayerImpl::Create(tree_impl, id()); | |
26 } | |
27 | |
28 void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) { | |
29 UIResourceLayerImpl::PushPropertiesTo(layer); | |
30 NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); | |
31 | |
32 layer_impl->SetLayout(image_aperture_, border_, fill_center_); | |
33 } | |
34 | |
35 static gfx::RectF NormalizedRect(float x, | |
36 float y, | |
37 float width, | |
38 float height, | |
39 float total_width, | |
40 float total_height) { | |
41 return gfx::RectF(x / total_width, | |
42 y / total_height, | |
43 width / total_width, | |
44 height / total_height); | |
45 } | |
46 | |
47 void NinePatchLayerImpl::SetLayout(const gfx::Rect& aperture, | |
48 const gfx::Rect& border, | |
49 bool fill_center) { | |
50 // This check imposes an ordering on the call sequence. An UIResource must | |
51 // exist before SetLayout can be called. | |
52 DCHECK(ui_resource_id_); | |
53 | |
54 if (image_aperture_ == aperture && | |
55 border_ == border && fill_center_ == fill_center) | |
56 return; | |
57 | |
58 image_aperture_ = aperture; | |
59 border_ = border; | |
60 fill_center_ = fill_center; | |
61 | |
62 NoteLayerPropertyChanged(); | |
63 } | |
64 | |
65 void NinePatchLayerImpl::CheckGeometryLimitations() { | |
66 // |border| is in layer space. It cannot exceed the bounds of the layer. | |
67 DCHECK_GE(bounds().width(), border_.width()); | |
68 DCHECK_GE(bounds().height(), border_.height()); | |
69 | |
70 // Sanity Check on |border| | |
71 DCHECK_LE(border_.x(), border_.width()); | |
72 DCHECK_LE(border_.y(), border_.height()); | |
73 DCHECK_GE(border_.x(), 0); | |
74 DCHECK_GE(border_.y(), 0); | |
75 | |
76 // |aperture| is in image space. It cannot exceed the bounds of the bitmap. | |
77 DCHECK(!image_aperture_.size().IsEmpty()); | |
78 DCHECK(gfx::Rect(image_bounds_).Contains(image_aperture_)) | |
79 << "image_bounds_ " << gfx::Rect(image_bounds_).ToString() | |
80 << " image_aperture_ " << image_aperture_.ToString(); | |
81 } | |
82 | |
83 void NinePatchLayerImpl::AppendQuads( | |
84 RenderPass* render_pass, | |
85 AppendQuadsData* append_quads_data) { | |
86 CheckGeometryLimitations(); | |
87 SharedQuadState* shared_quad_state = | |
88 render_pass->CreateAndAppendSharedQuadState(); | |
89 PopulateSharedQuadState(shared_quad_state); | |
90 | |
91 AppendDebugBorderQuad( | |
92 render_pass, content_bounds(), shared_quad_state, append_quads_data); | |
93 | |
94 if (!ui_resource_id_) | |
95 return; | |
96 | |
97 ResourceProvider::ResourceId resource = | |
98 layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_); | |
99 | |
100 if (!resource) | |
101 return; | |
102 | |
103 static const bool flipped = false; | |
104 static const bool nearest_neighbor = false; | |
105 static const bool premultiplied_alpha = true; | |
106 | |
107 DCHECK(!bounds().IsEmpty()); | |
108 | |
109 // NinePatch border widths in layer space. | |
110 int layer_left_width = border_.x(); | |
111 int layer_top_height = border_.y(); | |
112 int layer_right_width = border_.width() - layer_left_width; | |
113 int layer_bottom_height = border_.height() - layer_top_height; | |
114 | |
115 int layer_middle_width = bounds().width() - border_.width(); | |
116 int layer_middle_height = bounds().height() - border_.height(); | |
117 | |
118 // Patch positions in layer space | |
119 gfx::Rect layer_top_left(0, 0, layer_left_width, layer_top_height); | |
120 gfx::Rect layer_top_right(bounds().width() - layer_right_width, | |
121 0, | |
122 layer_right_width, | |
123 layer_top_height); | |
124 gfx::Rect layer_bottom_left(0, | |
125 bounds().height() - layer_bottom_height, | |
126 layer_left_width, | |
127 layer_bottom_height); | |
128 gfx::Rect layer_bottom_right(layer_top_right.x(), | |
129 layer_bottom_left.y(), | |
130 layer_right_width, | |
131 layer_bottom_height); | |
132 gfx::Rect layer_top( | |
133 layer_top_left.right(), 0, layer_middle_width, layer_top_height); | |
134 gfx::Rect layer_left( | |
135 0, layer_top_left.bottom(), layer_left_width, layer_middle_height); | |
136 gfx::Rect layer_right(layer_top_right.x(), | |
137 layer_top_right.bottom(), | |
138 layer_right_width, | |
139 layer_left.height()); | |
140 gfx::Rect layer_bottom(layer_top.x(), | |
141 layer_bottom_left.y(), | |
142 layer_top.width(), | |
143 layer_bottom_height); | |
144 gfx::Rect layer_center(layer_left_width, | |
145 layer_top_height, | |
146 layer_middle_width, | |
147 layer_middle_height); | |
148 | |
149 // Note the following values are in image (bitmap) space. | |
150 float image_width = image_bounds_.width(); | |
151 float image_height = image_bounds_.height(); | |
152 | |
153 int image_aperture_left_width = image_aperture_.x(); | |
154 int image_aperture_top_height = image_aperture_.y(); | |
155 int image_aperture_right_width = image_width - image_aperture_.right(); | |
156 int image_aperture_bottom_height = image_height - image_aperture_.bottom(); | |
157 // Patch positions in bitmap UV space (from zero to one) | |
158 gfx::RectF uv_top_left = NormalizedRect(0, | |
159 0, | |
160 image_aperture_left_width, | |
161 image_aperture_top_height, | |
162 image_width, | |
163 image_height); | |
164 gfx::RectF uv_top_right = | |
165 NormalizedRect(image_width - image_aperture_right_width, | |
166 0, | |
167 image_aperture_right_width, | |
168 image_aperture_top_height, | |
169 image_width, | |
170 image_height); | |
171 gfx::RectF uv_bottom_left = | |
172 NormalizedRect(0, | |
173 image_height - image_aperture_bottom_height, | |
174 image_aperture_left_width, | |
175 image_aperture_bottom_height, | |
176 image_width, | |
177 image_height); | |
178 gfx::RectF uv_bottom_right = | |
179 NormalizedRect(image_width - image_aperture_right_width, | |
180 image_height - image_aperture_bottom_height, | |
181 image_aperture_right_width, | |
182 image_aperture_bottom_height, | |
183 image_width, | |
184 image_height); | |
185 gfx::RectF uv_top( | |
186 uv_top_left.right(), | |
187 0, | |
188 (image_width - image_aperture_left_width - image_aperture_right_width) / | |
189 image_width, | |
190 (image_aperture_top_height) / image_height); | |
191 gfx::RectF uv_left(0, | |
192 uv_top_left.bottom(), | |
193 image_aperture_left_width / image_width, | |
194 (image_height - image_aperture_top_height - | |
195 image_aperture_bottom_height) / | |
196 image_height); | |
197 gfx::RectF uv_right(uv_top_right.x(), | |
198 uv_top_right.bottom(), | |
199 image_aperture_right_width / image_width, | |
200 uv_left.height()); | |
201 gfx::RectF uv_bottom(uv_top.x(), | |
202 uv_bottom_left.y(), | |
203 uv_top.width(), | |
204 image_aperture_bottom_height / image_height); | |
205 gfx::RectF uv_center(uv_top_left.right(), | |
206 uv_top_left.bottom(), | |
207 uv_top.width(), | |
208 uv_left.height()); | |
209 | |
210 gfx::Rect opaque_rect; | |
211 gfx::Rect visible_rect; | |
212 const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; | |
213 const bool opaque = layer_tree_impl()->IsUIResourceOpaque(ui_resource_id_); | |
214 | |
215 visible_rect = | |
216 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
217 layer_top_left); | |
218 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
219 if (!visible_rect.IsEmpty()) { | |
220 TextureDrawQuad* quad = | |
221 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
222 quad->SetNew(shared_quad_state, | |
223 layer_top_left, | |
224 opaque_rect, | |
225 visible_rect, | |
226 resource, | |
227 premultiplied_alpha, | |
228 uv_top_left.origin(), | |
229 uv_top_left.bottom_right(), | |
230 SK_ColorTRANSPARENT, | |
231 vertex_opacity, | |
232 flipped, | |
233 nearest_neighbor); | |
234 } | |
235 | |
236 visible_rect = | |
237 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
238 layer_top_right); | |
239 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
240 if (!visible_rect.IsEmpty()) { | |
241 TextureDrawQuad* quad = | |
242 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
243 quad->SetNew(shared_quad_state, | |
244 layer_top_right, | |
245 opaque_rect, | |
246 visible_rect, | |
247 resource, | |
248 premultiplied_alpha, | |
249 uv_top_right.origin(), | |
250 uv_top_right.bottom_right(), | |
251 SK_ColorTRANSPARENT, | |
252 vertex_opacity, | |
253 flipped, | |
254 nearest_neighbor); | |
255 } | |
256 | |
257 visible_rect = | |
258 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
259 layer_bottom_left); | |
260 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
261 if (!visible_rect.IsEmpty()) { | |
262 TextureDrawQuad* quad = | |
263 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
264 quad->SetNew(shared_quad_state, | |
265 layer_bottom_left, | |
266 opaque_rect, | |
267 visible_rect, | |
268 resource, | |
269 premultiplied_alpha, | |
270 uv_bottom_left.origin(), | |
271 uv_bottom_left.bottom_right(), | |
272 SK_ColorTRANSPARENT, | |
273 vertex_opacity, | |
274 flipped, | |
275 nearest_neighbor); | |
276 } | |
277 | |
278 visible_rect = | |
279 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
280 layer_bottom_right); | |
281 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
282 if (!visible_rect.IsEmpty()) { | |
283 TextureDrawQuad* quad = | |
284 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
285 quad->SetNew(shared_quad_state, | |
286 layer_bottom_right, | |
287 opaque_rect, | |
288 visible_rect, | |
289 resource, | |
290 premultiplied_alpha, | |
291 uv_bottom_right.origin(), | |
292 uv_bottom_right.bottom_right(), | |
293 SK_ColorTRANSPARENT, | |
294 vertex_opacity, | |
295 flipped, | |
296 nearest_neighbor); | |
297 } | |
298 | |
299 visible_rect = | |
300 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
301 layer_top); | |
302 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
303 if (!visible_rect.IsEmpty()) { | |
304 TextureDrawQuad* quad = | |
305 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
306 quad->SetNew(shared_quad_state, | |
307 layer_top, | |
308 opaque_rect, | |
309 visible_rect, | |
310 resource, | |
311 premultiplied_alpha, | |
312 uv_top.origin(), | |
313 uv_top.bottom_right(), | |
314 SK_ColorTRANSPARENT, | |
315 vertex_opacity, | |
316 flipped, | |
317 nearest_neighbor); | |
318 } | |
319 | |
320 visible_rect = | |
321 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
322 layer_left); | |
323 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
324 if (!visible_rect.IsEmpty()) { | |
325 TextureDrawQuad* quad = | |
326 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
327 quad->SetNew(shared_quad_state, | |
328 layer_left, | |
329 opaque_rect, | |
330 visible_rect, | |
331 resource, | |
332 premultiplied_alpha, | |
333 uv_left.origin(), | |
334 uv_left.bottom_right(), | |
335 SK_ColorTRANSPARENT, | |
336 vertex_opacity, | |
337 flipped, | |
338 nearest_neighbor); | |
339 } | |
340 | |
341 visible_rect = | |
342 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
343 layer_right); | |
344 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
345 if (!visible_rect.IsEmpty()) { | |
346 TextureDrawQuad* quad = | |
347 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
348 quad->SetNew(shared_quad_state, | |
349 layer_right, | |
350 opaque_rect, | |
351 layer_right, | |
352 resource, | |
353 premultiplied_alpha, | |
354 uv_right.origin(), | |
355 uv_right.bottom_right(), | |
356 SK_ColorTRANSPARENT, | |
357 vertex_opacity, | |
358 flipped, | |
359 nearest_neighbor); | |
360 } | |
361 | |
362 visible_rect = | |
363 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
364 layer_bottom); | |
365 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
366 if (!visible_rect.IsEmpty()) { | |
367 TextureDrawQuad* quad = | |
368 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
369 quad->SetNew(shared_quad_state, | |
370 layer_bottom, | |
371 opaque_rect, | |
372 visible_rect, | |
373 resource, | |
374 premultiplied_alpha, | |
375 uv_bottom.origin(), | |
376 uv_bottom.bottom_right(), | |
377 SK_ColorTRANSPARENT, | |
378 vertex_opacity, | |
379 flipped, | |
380 nearest_neighbor); | |
381 } | |
382 | |
383 if (fill_center_) { | |
384 visible_rect = | |
385 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
386 layer_center); | |
387 opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
388 if (!visible_rect.IsEmpty()) { | |
389 TextureDrawQuad* quad = | |
390 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
391 quad->SetNew(shared_quad_state, | |
392 layer_center, | |
393 opaque_rect, | |
394 visible_rect, | |
395 resource, | |
396 premultiplied_alpha, | |
397 uv_center.origin(), | |
398 uv_center.bottom_right(), | |
399 SK_ColorTRANSPARENT, | |
400 vertex_opacity, | |
401 flipped, | |
402 nearest_neighbor); | |
403 } | |
404 } | |
405 } | |
406 | |
407 const char* NinePatchLayerImpl::LayerTypeAsString() const { | |
408 return "cc::NinePatchLayerImpl"; | |
409 } | |
410 | |
411 base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const { | |
412 base::DictionaryValue* result = LayerImpl::LayerTreeAsJson(); | |
413 | |
414 base::ListValue* list = new base::ListValue; | |
415 list->AppendInteger(image_aperture_.origin().x()); | |
416 list->AppendInteger(image_aperture_.origin().y()); | |
417 list->AppendInteger(image_aperture_.size().width()); | |
418 list->AppendInteger(image_aperture_.size().height()); | |
419 result->Set("ImageAperture", list); | |
420 | |
421 list = new base::ListValue; | |
422 list->AppendInteger(image_bounds_.width()); | |
423 list->AppendInteger(image_bounds_.height()); | |
424 result->Set("ImageBounds", list); | |
425 | |
426 result->Set("Border", MathUtil::AsValue(border_).release()); | |
427 | |
428 result->SetBoolean("FillCenter", fill_center_); | |
429 | |
430 return result; | |
431 } | |
432 | |
433 } // namespace cc | |
OLD | NEW |