Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / cc / layers / nine_patch_layer_impl.cc
blobb31382f65809b6fe50f00b07defbc8cd2a3eac7a
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.
5 #include "cc/layers/nine_patch_layer_impl.h"
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"
15 namespace cc {
17 NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id)
18 : UIResourceLayerImpl(tree_impl, id),
19 fill_center_(false) {}
21 NinePatchLayerImpl::~NinePatchLayerImpl() {}
23 scoped_ptr<LayerImpl> NinePatchLayerImpl::CreateLayerImpl(
24 LayerTreeImpl* tree_impl) {
25 return NinePatchLayerImpl::Create(tree_impl, id());
28 void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) {
29 UIResourceLayerImpl::PushPropertiesTo(layer);
30 NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer);
32 layer_impl->SetLayout(image_aperture_, border_, fill_center_);
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);
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_);
54 if (image_aperture_ == aperture &&
55 border_ == border && fill_center_ == fill_center)
56 return;
58 image_aperture_ = aperture;
59 border_ = border;
60 fill_center_ = fill_center;
62 NoteLayerPropertyChanged();
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());
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);
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();
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);
91 AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state,
92 append_quads_data);
94 if (!ui_resource_id_)
95 return;
97 ResourceId resource =
98 layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_);
100 if (!resource)
101 return;
103 static const bool flipped = false;
104 static const bool nearest_neighbor = false;
105 static const bool premultiplied_alpha = true;
107 DCHECK(!bounds().IsEmpty());
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;
115 int layer_middle_width = bounds().width() - border_.width();
116 int layer_middle_height = bounds().height() - border_.height();
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,
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);
149 // Note the following values are in image (bitmap) space.
150 float image_width = image_bounds_.width();
151 float image_height = image_bounds_.height();
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,
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,
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(),
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());
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_);
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 ValidateQuadResources(quad);
237 visible_rect =
238 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
239 layer_top_right);
240 opaque_rect = opaque ? visible_rect : gfx::Rect();
241 if (!visible_rect.IsEmpty()) {
242 TextureDrawQuad* quad =
243 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
244 quad->SetNew(shared_quad_state,
245 layer_top_right,
246 opaque_rect,
247 visible_rect,
248 resource,
249 premultiplied_alpha,
250 uv_top_right.origin(),
251 uv_top_right.bottom_right(),
252 SK_ColorTRANSPARENT,
253 vertex_opacity,
254 flipped,
255 nearest_neighbor);
256 ValidateQuadResources(quad);
259 visible_rect =
260 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
261 layer_bottom_left);
262 opaque_rect = opaque ? visible_rect : gfx::Rect();
263 if (!visible_rect.IsEmpty()) {
264 TextureDrawQuad* quad =
265 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
266 quad->SetNew(shared_quad_state,
267 layer_bottom_left,
268 opaque_rect,
269 visible_rect,
270 resource,
271 premultiplied_alpha,
272 uv_bottom_left.origin(),
273 uv_bottom_left.bottom_right(),
274 SK_ColorTRANSPARENT,
275 vertex_opacity,
276 flipped,
277 nearest_neighbor);
278 ValidateQuadResources(quad);
281 visible_rect =
282 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
283 layer_bottom_right);
284 opaque_rect = opaque ? visible_rect : gfx::Rect();
285 if (!visible_rect.IsEmpty()) {
286 TextureDrawQuad* quad =
287 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
288 quad->SetNew(shared_quad_state,
289 layer_bottom_right,
290 opaque_rect,
291 visible_rect,
292 resource,
293 premultiplied_alpha,
294 uv_bottom_right.origin(),
295 uv_bottom_right.bottom_right(),
296 SK_ColorTRANSPARENT,
297 vertex_opacity,
298 flipped,
299 nearest_neighbor);
300 ValidateQuadResources(quad);
303 visible_rect =
304 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
305 layer_top);
306 opaque_rect = opaque ? visible_rect : gfx::Rect();
307 if (!visible_rect.IsEmpty()) {
308 TextureDrawQuad* quad =
309 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
310 quad->SetNew(shared_quad_state,
311 layer_top,
312 opaque_rect,
313 visible_rect,
314 resource,
315 premultiplied_alpha,
316 uv_top.origin(),
317 uv_top.bottom_right(),
318 SK_ColorTRANSPARENT,
319 vertex_opacity,
320 flipped,
321 nearest_neighbor);
322 ValidateQuadResources(quad);
325 visible_rect =
326 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
327 layer_left);
328 opaque_rect = opaque ? visible_rect : gfx::Rect();
329 if (!visible_rect.IsEmpty()) {
330 TextureDrawQuad* quad =
331 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
332 quad->SetNew(shared_quad_state,
333 layer_left,
334 opaque_rect,
335 visible_rect,
336 resource,
337 premultiplied_alpha,
338 uv_left.origin(),
339 uv_left.bottom_right(),
340 SK_ColorTRANSPARENT,
341 vertex_opacity,
342 flipped,
343 nearest_neighbor);
344 ValidateQuadResources(quad);
347 visible_rect =
348 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
349 layer_right);
350 opaque_rect = opaque ? visible_rect : gfx::Rect();
351 if (!visible_rect.IsEmpty()) {
352 TextureDrawQuad* quad =
353 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
354 quad->SetNew(shared_quad_state,
355 layer_right,
356 opaque_rect,
357 layer_right,
358 resource,
359 premultiplied_alpha,
360 uv_right.origin(),
361 uv_right.bottom_right(),
362 SK_ColorTRANSPARENT,
363 vertex_opacity,
364 flipped,
365 nearest_neighbor);
366 ValidateQuadResources(quad);
369 visible_rect =
370 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
371 layer_bottom);
372 opaque_rect = opaque ? visible_rect : gfx::Rect();
373 if (!visible_rect.IsEmpty()) {
374 TextureDrawQuad* quad =
375 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
376 quad->SetNew(shared_quad_state,
377 layer_bottom,
378 opaque_rect,
379 visible_rect,
380 resource,
381 premultiplied_alpha,
382 uv_bottom.origin(),
383 uv_bottom.bottom_right(),
384 SK_ColorTRANSPARENT,
385 vertex_opacity,
386 flipped,
387 nearest_neighbor);
388 ValidateQuadResources(quad);
391 if (fill_center_) {
392 visible_rect =
393 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
394 layer_center);
395 opaque_rect = opaque ? visible_rect : gfx::Rect();
396 if (!visible_rect.IsEmpty()) {
397 TextureDrawQuad* quad =
398 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
399 quad->SetNew(shared_quad_state,
400 layer_center,
401 opaque_rect,
402 visible_rect,
403 resource,
404 premultiplied_alpha,
405 uv_center.origin(),
406 uv_center.bottom_right(),
407 SK_ColorTRANSPARENT,
408 vertex_opacity,
409 flipped,
410 nearest_neighbor);
411 ValidateQuadResources(quad);
416 const char* NinePatchLayerImpl::LayerTypeAsString() const {
417 return "cc::NinePatchLayerImpl";
420 base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const {
421 base::DictionaryValue* result = LayerImpl::LayerTreeAsJson();
423 base::ListValue* list = new base::ListValue;
424 list->AppendInteger(image_aperture_.origin().x());
425 list->AppendInteger(image_aperture_.origin().y());
426 list->AppendInteger(image_aperture_.size().width());
427 list->AppendInteger(image_aperture_.size().height());
428 result->Set("ImageAperture", list);
430 list = new base::ListValue;
431 list->AppendInteger(image_bounds_.width());
432 list->AppendInteger(image_bounds_.height());
433 result->Set("ImageBounds", list);
435 result->Set("Border", MathUtil::AsValue(border_).release());
437 result->SetBoolean("FillCenter", fill_center_);
439 return result;
442 } // namespace cc