Use multiline attribute to check for IA2_STATE_MULTILINE.
[chromium-blink-merge.git] / cc / layers / nine_patch_layer_impl.cc
blob898e6b5ff5415e936f6e5f2ee762912c1f62dc8c
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(
92 render_pass, content_bounds(), shared_quad_state, append_quads_data);
94 if (!ui_resource_id_)
95 return;
97 ResourceProvider::ResourceId resource =
98 layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_);
100 if (!resource)
101 return;
103 // TODO(danakj): crbug.com/455931
104 layer_tree_impl()->resource_provider()->ValidateResource(resource);
106 static const bool flipped = false;
107 static const bool nearest_neighbor = false;
108 static const bool premultiplied_alpha = true;
110 DCHECK(!bounds().IsEmpty());
112 // NinePatch border widths in layer space.
113 int layer_left_width = border_.x();
114 int layer_top_height = border_.y();
115 int layer_right_width = border_.width() - layer_left_width;
116 int layer_bottom_height = border_.height() - layer_top_height;
118 int layer_middle_width = bounds().width() - border_.width();
119 int layer_middle_height = bounds().height() - border_.height();
121 // Patch positions in layer space
122 gfx::Rect layer_top_left(0, 0, layer_left_width, layer_top_height);
123 gfx::Rect layer_top_right(bounds().width() - layer_right_width,
125 layer_right_width,
126 layer_top_height);
127 gfx::Rect layer_bottom_left(0,
128 bounds().height() - layer_bottom_height,
129 layer_left_width,
130 layer_bottom_height);
131 gfx::Rect layer_bottom_right(layer_top_right.x(),
132 layer_bottom_left.y(),
133 layer_right_width,
134 layer_bottom_height);
135 gfx::Rect layer_top(
136 layer_top_left.right(), 0, layer_middle_width, layer_top_height);
137 gfx::Rect layer_left(
138 0, layer_top_left.bottom(), layer_left_width, layer_middle_height);
139 gfx::Rect layer_right(layer_top_right.x(),
140 layer_top_right.bottom(),
141 layer_right_width,
142 layer_left.height());
143 gfx::Rect layer_bottom(layer_top.x(),
144 layer_bottom_left.y(),
145 layer_top.width(),
146 layer_bottom_height);
147 gfx::Rect layer_center(layer_left_width,
148 layer_top_height,
149 layer_middle_width,
150 layer_middle_height);
152 // Note the following values are in image (bitmap) space.
153 float image_width = image_bounds_.width();
154 float image_height = image_bounds_.height();
156 int image_aperture_left_width = image_aperture_.x();
157 int image_aperture_top_height = image_aperture_.y();
158 int image_aperture_right_width = image_width - image_aperture_.right();
159 int image_aperture_bottom_height = image_height - image_aperture_.bottom();
160 // Patch positions in bitmap UV space (from zero to one)
161 gfx::RectF uv_top_left = NormalizedRect(0,
163 image_aperture_left_width,
164 image_aperture_top_height,
165 image_width,
166 image_height);
167 gfx::RectF uv_top_right =
168 NormalizedRect(image_width - image_aperture_right_width,
170 image_aperture_right_width,
171 image_aperture_top_height,
172 image_width,
173 image_height);
174 gfx::RectF uv_bottom_left =
175 NormalizedRect(0,
176 image_height - image_aperture_bottom_height,
177 image_aperture_left_width,
178 image_aperture_bottom_height,
179 image_width,
180 image_height);
181 gfx::RectF uv_bottom_right =
182 NormalizedRect(image_width - image_aperture_right_width,
183 image_height - image_aperture_bottom_height,
184 image_aperture_right_width,
185 image_aperture_bottom_height,
186 image_width,
187 image_height);
188 gfx::RectF uv_top(
189 uv_top_left.right(),
191 (image_width - image_aperture_left_width - image_aperture_right_width) /
192 image_width,
193 (image_aperture_top_height) / image_height);
194 gfx::RectF uv_left(0,
195 uv_top_left.bottom(),
196 image_aperture_left_width / image_width,
197 (image_height - image_aperture_top_height -
198 image_aperture_bottom_height) /
199 image_height);
200 gfx::RectF uv_right(uv_top_right.x(),
201 uv_top_right.bottom(),
202 image_aperture_right_width / image_width,
203 uv_left.height());
204 gfx::RectF uv_bottom(uv_top.x(),
205 uv_bottom_left.y(),
206 uv_top.width(),
207 image_aperture_bottom_height / image_height);
208 gfx::RectF uv_center(uv_top_left.right(),
209 uv_top_left.bottom(),
210 uv_top.width(),
211 uv_left.height());
213 gfx::Rect opaque_rect;
214 gfx::Rect visible_rect;
215 const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
216 const bool opaque = layer_tree_impl()->IsUIResourceOpaque(ui_resource_id_);
218 visible_rect =
219 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
220 layer_top_left);
221 opaque_rect = opaque ? visible_rect : gfx::Rect();
222 if (!visible_rect.IsEmpty()) {
223 TextureDrawQuad* quad =
224 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
225 quad->SetNew(shared_quad_state,
226 layer_top_left,
227 opaque_rect,
228 visible_rect,
229 resource,
230 premultiplied_alpha,
231 uv_top_left.origin(),
232 uv_top_left.bottom_right(),
233 SK_ColorTRANSPARENT,
234 vertex_opacity,
235 flipped,
236 nearest_neighbor);
239 visible_rect =
240 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
241 layer_top_right);
242 opaque_rect = opaque ? visible_rect : gfx::Rect();
243 if (!visible_rect.IsEmpty()) {
244 TextureDrawQuad* quad =
245 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
246 quad->SetNew(shared_quad_state,
247 layer_top_right,
248 opaque_rect,
249 visible_rect,
250 resource,
251 premultiplied_alpha,
252 uv_top_right.origin(),
253 uv_top_right.bottom_right(),
254 SK_ColorTRANSPARENT,
255 vertex_opacity,
256 flipped,
257 nearest_neighbor);
260 visible_rect =
261 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
262 layer_bottom_left);
263 opaque_rect = opaque ? visible_rect : gfx::Rect();
264 if (!visible_rect.IsEmpty()) {
265 TextureDrawQuad* quad =
266 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
267 quad->SetNew(shared_quad_state,
268 layer_bottom_left,
269 opaque_rect,
270 visible_rect,
271 resource,
272 premultiplied_alpha,
273 uv_bottom_left.origin(),
274 uv_bottom_left.bottom_right(),
275 SK_ColorTRANSPARENT,
276 vertex_opacity,
277 flipped,
278 nearest_neighbor);
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);
302 visible_rect =
303 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
304 layer_top);
305 opaque_rect = opaque ? visible_rect : gfx::Rect();
306 if (!visible_rect.IsEmpty()) {
307 TextureDrawQuad* quad =
308 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
309 quad->SetNew(shared_quad_state,
310 layer_top,
311 opaque_rect,
312 visible_rect,
313 resource,
314 premultiplied_alpha,
315 uv_top.origin(),
316 uv_top.bottom_right(),
317 SK_ColorTRANSPARENT,
318 vertex_opacity,
319 flipped,
320 nearest_neighbor);
323 visible_rect =
324 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
325 layer_left);
326 opaque_rect = opaque ? visible_rect : gfx::Rect();
327 if (!visible_rect.IsEmpty()) {
328 TextureDrawQuad* quad =
329 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
330 quad->SetNew(shared_quad_state,
331 layer_left,
332 opaque_rect,
333 visible_rect,
334 resource,
335 premultiplied_alpha,
336 uv_left.origin(),
337 uv_left.bottom_right(),
338 SK_ColorTRANSPARENT,
339 vertex_opacity,
340 flipped,
341 nearest_neighbor);
344 visible_rect =
345 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
346 layer_right);
347 opaque_rect = opaque ? visible_rect : gfx::Rect();
348 if (!visible_rect.IsEmpty()) {
349 TextureDrawQuad* quad =
350 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
351 quad->SetNew(shared_quad_state,
352 layer_right,
353 opaque_rect,
354 layer_right,
355 resource,
356 premultiplied_alpha,
357 uv_right.origin(),
358 uv_right.bottom_right(),
359 SK_ColorTRANSPARENT,
360 vertex_opacity,
361 flipped,
362 nearest_neighbor);
365 visible_rect =
366 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
367 layer_bottom);
368 opaque_rect = opaque ? visible_rect : gfx::Rect();
369 if (!visible_rect.IsEmpty()) {
370 TextureDrawQuad* quad =
371 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
372 quad->SetNew(shared_quad_state,
373 layer_bottom,
374 opaque_rect,
375 visible_rect,
376 resource,
377 premultiplied_alpha,
378 uv_bottom.origin(),
379 uv_bottom.bottom_right(),
380 SK_ColorTRANSPARENT,
381 vertex_opacity,
382 flipped,
383 nearest_neighbor);
386 if (fill_center_) {
387 visible_rect =
388 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect(
389 layer_center);
390 opaque_rect = opaque ? visible_rect : gfx::Rect();
391 if (!visible_rect.IsEmpty()) {
392 TextureDrawQuad* quad =
393 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>();
394 quad->SetNew(shared_quad_state,
395 layer_center,
396 opaque_rect,
397 visible_rect,
398 resource,
399 premultiplied_alpha,
400 uv_center.origin(),
401 uv_center.bottom_right(),
402 SK_ColorTRANSPARENT,
403 vertex_opacity,
404 flipped,
405 nearest_neighbor);
410 const char* NinePatchLayerImpl::LayerTypeAsString() const {
411 return "cc::NinePatchLayerImpl";
414 base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const {
415 base::DictionaryValue* result = LayerImpl::LayerTreeAsJson();
417 base::ListValue* list = new base::ListValue;
418 list->AppendInteger(image_aperture_.origin().x());
419 list->AppendInteger(image_aperture_.origin().y());
420 list->AppendInteger(image_aperture_.size().width());
421 list->AppendInteger(image_aperture_.size().height());
422 result->Set("ImageAperture", list);
424 list = new base::ListValue;
425 list->AppendInteger(image_bounds_.width());
426 list->AppendInteger(image_bounds_.height());
427 result->Set("ImageBounds", list);
429 result->Set("Border", MathUtil::AsValue(border_).release());
431 result->SetBoolean("FillCenter", fill_center_);
433 return result;
436 } // namespace cc