Adding a logging class to cast.
[chromium-blink-merge.git] / cc / layers / nine_patch_layer_impl.cc
blobc3e0998c3dc6d634f2854721ad4db94f086f9df1
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/layers/quad_sink.h"
11 #include "cc/quads/texture_draw_quad.h"
12 #include "cc/trees/layer_tree_impl.h"
13 #include "ui/gfx/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()).PassAs<LayerImpl>();
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(gfx::Rect aperture,
48 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 // TODO(ccameron): the following "greater than or equal to" (GE) checks should
67 // be greater than (GT) to avoid degenerate nine-patches. The relaxed
68 // condition "equal to" is a workaround for the overhang shadow use case and
69 // should be investigated further.
71 // |border| is in layer space. It cannot exceed the bounds of the layer.
72 DCHECK(!border_.size().IsEmpty());
73 DCHECK_GE(bounds().width(), border_.width());
74 DCHECK_GE(bounds().height(), border_.height());
76 // Sanity Check on |border|
77 DCHECK_LT(border_.x(), border_.width());
78 DCHECK_LT(border_.y(), border_.height());
79 DCHECK_GE(border_.x(), 0);
80 DCHECK_GE(border_.y(), 0);
82 // |aperture| is in image space. It cannot exceed the bounds of the bitmap.
83 DCHECK(!image_aperture_.size().IsEmpty());
84 DCHECK(gfx::Rect(image_bounds_.width(), image_bounds_.height())
85 .Contains(image_aperture_));
87 // Avoid the degenerate cases where the aperture touches the edge of the
88 // image.
89 DCHECK_LT(image_aperture_.width(), image_bounds_.width() - 1);
90 DCHECK_LT(image_aperture_.height(), image_bounds_.height() - 1);
91 DCHECK_GT(image_aperture_.x(), 0);
92 DCHECK_GT(image_aperture_.y(), 0);
95 void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink,
96 AppendQuadsData* append_quads_data) {
97 CheckGeometryLimitations();
98 SharedQuadState* shared_quad_state =
99 quad_sink->UseSharedQuadState(CreateSharedQuadState());
100 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data);
102 if (!ui_resource_id_)
103 return;
105 ResourceProvider::ResourceId resource =
106 layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_);
108 if (!resource)
109 return;
111 static const bool flipped = false;
112 static const bool premultiplied_alpha = true;
114 DCHECK(!bounds().IsEmpty());
116 // NinePatch border widths in layer space.
117 int layer_left_width = border_.x();
118 int layer_top_height = border_.y();
119 int layer_right_width = border_.width() - layer_left_width;
120 int layer_bottom_height = border_.height() - layer_top_height;
122 int layer_middle_width = bounds().width() - border_.width();
123 int layer_middle_height = bounds().height() - border_.height();
125 // Patch positions in layer space
126 gfx::Rect layer_top_left(0, 0, layer_left_width, layer_top_height);
127 gfx::Rect layer_top_right(bounds().width() - layer_right_width,
129 layer_right_width,
130 layer_top_height);
131 gfx::Rect layer_bottom_left(0,
132 bounds().height() - layer_bottom_height,
133 layer_left_width,
134 layer_bottom_height);
135 gfx::Rect layer_bottom_right(layer_top_right.x(),
136 layer_bottom_left.y(),
137 layer_right_width,
138 layer_bottom_height);
139 gfx::Rect layer_top(
140 layer_top_left.right(), 0, layer_middle_width, layer_top_height);
141 gfx::Rect layer_left(
142 0, layer_top_left.bottom(), layer_left_width, layer_middle_height);
143 gfx::Rect layer_right(layer_top_right.x(),
144 layer_top_right.bottom(),
145 layer_right_width,
146 layer_left.height());
147 gfx::Rect layer_bottom(layer_top.x(),
148 layer_bottom_left.y(),
149 layer_top.width(),
150 layer_bottom_height);
151 gfx::Rect layer_center(layer_left_width,
152 layer_top_height,
153 layer_middle_width,
154 layer_middle_height);
156 // Note the following values are in image (bitmap) space.
157 float image_width = image_bounds_.width();
158 float image_height = image_bounds_.height();
160 int image_aperture_left_width = image_aperture_.x();
161 int image_aperture_top_height = image_aperture_.y();
162 int image_aperture_right_width = image_width - image_aperture_.right();
163 int image_aperture_bottom_height = image_height - image_aperture_.bottom();
164 // Patch positions in bitmap UV space (from zero to one)
165 gfx::RectF uv_top_left = NormalizedRect(0,
167 image_aperture_left_width,
168 image_aperture_top_height,
169 image_width,
170 image_height);
171 gfx::RectF uv_top_right =
172 NormalizedRect(image_width - image_aperture_right_width,
174 image_aperture_right_width,
175 image_aperture_top_height,
176 image_width,
177 image_height);
178 gfx::RectF uv_bottom_left =
179 NormalizedRect(0,
180 image_height - image_aperture_bottom_height,
181 image_aperture_left_width,
182 image_aperture_bottom_height,
183 image_width,
184 image_height);
185 gfx::RectF uv_bottom_right =
186 NormalizedRect(image_width - image_aperture_right_width,
187 image_height - image_aperture_bottom_height,
188 image_aperture_right_width,
189 image_aperture_bottom_height,
190 image_width,
191 image_height);
192 gfx::RectF uv_top(
193 uv_top_left.right(),
195 (image_width - image_aperture_left_width - image_aperture_right_width) /
196 image_width,
197 (image_aperture_top_height) / image_height);
198 gfx::RectF uv_left(0,
199 uv_top_left.bottom(),
200 image_aperture_left_width / image_width,
201 (image_height - image_aperture_top_height -
202 image_aperture_bottom_height) /
203 image_height);
204 gfx::RectF uv_right(uv_top_right.x(),
205 uv_top_right.bottom(),
206 image_aperture_right_width / image_width,
207 uv_left.height());
208 gfx::RectF uv_bottom(uv_top.x(),
209 uv_bottom_left.y(),
210 uv_top.width(),
211 image_aperture_bottom_height / image_height);
212 gfx::RectF uv_center(uv_top_left.right(),
213 uv_top_left.bottom(),
214 uv_top.width(),
215 uv_left.height());
217 // Nothing is opaque here.
218 // TODO(danakj): Should we look at the SkBitmaps to determine opaqueness?
219 gfx::Rect opaque_rect;
220 const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f};
221 scoped_ptr<TextureDrawQuad> quad;
223 quad = TextureDrawQuad::Create();
224 quad->SetNew(shared_quad_state,
225 layer_top_left,
226 opaque_rect,
227 resource,
228 premultiplied_alpha,
229 uv_top_left.origin(),
230 uv_top_left.bottom_right(),
231 SK_ColorTRANSPARENT,
232 vertex_opacity,
233 flipped);
234 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
236 quad = TextureDrawQuad::Create();
237 quad->SetNew(shared_quad_state,
238 layer_top_right,
239 opaque_rect,
240 resource,
241 premultiplied_alpha,
242 uv_top_right.origin(),
243 uv_top_right.bottom_right(),
244 SK_ColorTRANSPARENT,
245 vertex_opacity,
246 flipped);
247 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
249 quad = TextureDrawQuad::Create();
250 quad->SetNew(shared_quad_state,
251 layer_bottom_left,
252 opaque_rect,
253 resource,
254 premultiplied_alpha,
255 uv_bottom_left.origin(),
256 uv_bottom_left.bottom_right(),
257 SK_ColorTRANSPARENT,
258 vertex_opacity,
259 flipped);
260 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
262 quad = TextureDrawQuad::Create();
263 quad->SetNew(shared_quad_state,
264 layer_bottom_right,
265 opaque_rect,
266 resource,
267 premultiplied_alpha,
268 uv_bottom_right.origin(),
269 uv_bottom_right.bottom_right(),
270 SK_ColorTRANSPARENT,
271 vertex_opacity,
272 flipped);
273 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
275 quad = TextureDrawQuad::Create();
276 quad->SetNew(shared_quad_state,
277 layer_top,
278 opaque_rect,
279 resource,
280 premultiplied_alpha,
281 uv_top.origin(),
282 uv_top.bottom_right(),
283 SK_ColorTRANSPARENT,
284 vertex_opacity,
285 flipped);
286 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
288 quad = TextureDrawQuad::Create();
289 quad->SetNew(shared_quad_state,
290 layer_left,
291 opaque_rect,
292 resource,
293 premultiplied_alpha,
294 uv_left.origin(),
295 uv_left.bottom_right(),
296 SK_ColorTRANSPARENT,
297 vertex_opacity,
298 flipped);
299 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
301 quad = TextureDrawQuad::Create();
302 quad->SetNew(shared_quad_state,
303 layer_right,
304 opaque_rect,
305 resource,
306 premultiplied_alpha,
307 uv_right.origin(),
308 uv_right.bottom_right(),
309 SK_ColorTRANSPARENT,
310 vertex_opacity,
311 flipped);
312 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
314 quad = TextureDrawQuad::Create();
315 quad->SetNew(shared_quad_state,
316 layer_bottom,
317 opaque_rect,
318 resource,
319 premultiplied_alpha,
320 uv_bottom.origin(),
321 uv_bottom.bottom_right(),
322 SK_ColorTRANSPARENT,
323 vertex_opacity,
324 flipped);
325 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
327 if (fill_center_) {
328 quad = TextureDrawQuad::Create();
329 quad->SetNew(shared_quad_state,
330 layer_center,
331 opaque_rect,
332 resource,
333 premultiplied_alpha,
334 uv_center.origin(),
335 uv_center.bottom_right(),
336 SK_ColorTRANSPARENT,
337 vertex_opacity,
338 flipped);
339 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data);
343 const char* NinePatchLayerImpl::LayerTypeAsString() const {
344 return "cc::NinePatchLayerImpl";
347 base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const {
348 base::DictionaryValue* result = LayerImpl::LayerTreeAsJson();
350 base::ListValue* list = new base::ListValue;
351 list->AppendInteger(image_aperture_.origin().x());
352 list->AppendInteger(image_aperture_.origin().y());
353 list->AppendInteger(image_aperture_.size().width());
354 list->AppendInteger(image_aperture_.size().height());
355 result->Set("ImageAperture", list);
357 result->Set("ImageBounds", MathUtil::AsValue(image_bounds_).release());
358 result->Set("Border", MathUtil::AsValue(border_).release());
360 base::FundamentalValue* fill_center =
361 base::Value::CreateBooleanValue(fill_center_);
362 result->Set("FillCenter", fill_center);
364 return result;
367 } // namespace cc