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 "nine_patch_layer_impl.h" | |
6 | |
7 #include "base/stringprintf.h" | |
8 #include "base/values.h" | |
9 #include "cc/quad_sink.h" | |
10 #include "cc/quads/texture_draw_quad.h" | |
11 #include "ui/gfx/rect_f.h" | |
12 | |
13 namespace cc { | |
14 | |
15 NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id) | |
16 : LayerImpl(tree_impl, id), | |
17 resource_id_(0) {} | |
18 | |
19 NinePatchLayerImpl::~NinePatchLayerImpl() {} | |
20 | |
21 ResourceProvider::ResourceId NinePatchLayerImpl::ContentsResourceId() const { | |
22 return 0; | |
23 } | |
24 | |
25 scoped_ptr<LayerImpl> NinePatchLayerImpl::CreateLayerImpl( | |
26 LayerTreeImpl* tree_impl) { | |
27 return NinePatchLayerImpl::Create(tree_impl, id()).PassAs<LayerImpl>(); | |
28 } | |
29 | |
30 void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) { | |
31 LayerImpl::PushPropertiesTo(layer); | |
32 NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); | |
33 | |
34 if (!resource_id_) | |
35 return; | |
36 | |
37 layer_impl->SetResourceId(resource_id_); | |
38 layer_impl->SetLayout(image_bounds_, image_aperture_); | |
39 } | |
40 | |
41 void NinePatchLayerImpl::WillDraw(ResourceProvider* resource_provider) {} | |
42 | |
43 static gfx::RectF NormalizedRect(float x, | |
44 float y, | |
45 float width, | |
46 float height, | |
47 float total_width, | |
48 float total_height) { | |
49 return gfx::RectF(x / total_width, | |
50 y / total_height, | |
51 width / total_width, | |
52 height / total_height); | |
53 } | |
54 | |
55 void NinePatchLayerImpl::SetLayout(gfx::Size image_bounds, gfx::Rect aperture) { | |
56 image_bounds_ = image_bounds; | |
57 image_aperture_ = aperture; | |
58 } | |
59 | |
60 void NinePatchLayerImpl::AppendQuads(QuadSink* quad_sink, | |
61 AppendQuadsData* append_quads_data) { | |
62 if (!resource_id_) | |
63 return; | |
64 | |
65 SharedQuadState* shared_quad_state = | |
66 quad_sink->UseSharedQuadState(CreateSharedQuadState()); | |
67 AppendDebugBorderQuad(quad_sink, shared_quad_state, append_quads_data); | |
68 | |
69 static const bool flipped = false; | |
70 static const bool premultiplied_alpha = true; | |
71 | |
72 DCHECK(!bounds().IsEmpty()); | |
73 | |
74 // NinePatch border widths in bitmap pixel space | |
75 int left_width = image_aperture_.x(); | |
76 int top_height = image_aperture_.y(); | |
77 int right_width = image_bounds_.width() - image_aperture_.right(); | |
78 int bottom_height = image_bounds_.height() - image_aperture_.bottom(); | |
79 | |
80 // If layer can't fit the corners, clip to show the outer edges of the | |
81 // image. | |
82 int corner_total_width = left_width + right_width; | |
83 int middle_width = bounds().width() - corner_total_width; | |
84 if (middle_width < 0) { | |
85 float left_width_proportion = | |
86 static_cast<float>(left_width) / corner_total_width; | |
87 int left_width_crop = middle_width * left_width_proportion; | |
88 left_width += left_width_crop; | |
89 right_width = bounds().width() - left_width; | |
90 middle_width = 0; | |
91 } | |
92 int corner_total_height = top_height + bottom_height; | |
93 int middle_height = bounds().height() - corner_total_height; | |
94 if (middle_height < 0) { | |
95 float top_height_proportion = | |
96 static_cast<float>(top_height) / corner_total_height; | |
97 int top_height_crop = middle_height * top_height_proportion; | |
98 top_height += top_height_crop; | |
99 bottom_height = bounds().height() - top_height; | |
100 middle_height = 0; | |
101 } | |
102 | |
103 // Patch positions in layer space | |
104 gfx::Rect top_left(0, 0, left_width, top_height); | |
105 gfx::Rect topRight( | |
106 bounds().width() - right_width, 0, right_width, top_height); | |
107 gfx::Rect bottomLeft( | |
108 0, bounds().height() - bottom_height, left_width, bottom_height); | |
109 gfx::Rect bottomRight( | |
110 topRight.x(), bottomLeft.y(), right_width, bottom_height); | |
111 gfx::Rect top(top_left.right(), 0, middle_width, top_height); | |
112 gfx::Rect left(0, top_left.bottom(), left_width, middle_height); | |
113 gfx::Rect right(topRight.x(), topRight.bottom(), right_width, left.height()); | |
114 gfx::Rect bottom(top.x(), bottomLeft.y(), top.width(), bottom_height); | |
115 | |
116 float img_width = image_bounds_.width(); | |
117 float img_height = image_bounds_.height(); | |
118 | |
119 // Patch positions in bitmap UV space (from zero to one) | |
120 gfx::RectF uv_top_left = NormalizedRect(0, | |
121 0, | |
122 left_width, | |
123 top_height, | |
124 img_width, | |
125 img_height); | |
126 gfx::RectF uv_top_right = NormalizedRect(img_width - right_width, | |
127 0, | |
128 right_width, | |
129 top_height, | |
130 img_width, | |
131 img_height); | |
132 gfx::RectF uv_bottom_left = NormalizedRect(0, | |
133 img_height - bottom_height, | |
134 left_width, | |
135 bottom_height, | |
136 img_width, | |
137 img_height); | |
138 gfx::RectF uv_bottom_right = NormalizedRect(img_width - right_width, | |
139 img_height - bottom_height, | |
140 right_width, | |
141 bottom_height, | |
142 img_width, | |
143 img_height); | |
144 gfx::RectF uvTop(uv_top_left.right(), | |
145 0, | |
146 (img_width - left_width - right_width) / img_width, | |
147 (top_height) / img_height); | |
148 gfx::RectF uvLeft(0, | |
149 uv_top_left.bottom(), | |
150 left_width / img_width, | |
151 (img_height - top_height - bottom_height) / img_height); | |
152 gfx::RectF uvRight(uv_top_right.x(), | |
153 uv_top_right.bottom(), | |
154 right_width / img_width, | |
155 uvLeft.height()); | |
156 gfx::RectF uvBottom(uvTop.x(), | |
157 uv_bottom_left.y(), | |
158 uvTop.width(), | |
159 bottom_height / img_height); | |
160 | |
161 // Nothing is opaque here. | |
162 // TODO(danakj): Should we look at the SkBitmaps to determine opaqueness? | |
163 gfx::Rect opaque_rect; | |
164 const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; | |
165 scoped_ptr<TextureDrawQuad> quad; | |
166 | |
167 quad = TextureDrawQuad::Create(); | |
168 quad->SetNew(shared_quad_state, | |
169 top_left, | |
170 opaque_rect, | |
171 resource_id_, | |
172 premultiplied_alpha, | |
173 uv_top_left.origin(), | |
174 uv_top_left.bottom_right(), | |
175 vertex_opacity, flipped); | |
176 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
177 | |
178 quad = TextureDrawQuad::Create(); | |
179 quad->SetNew(shared_quad_state, | |
180 topRight, | |
181 opaque_rect, | |
182 resource_id_, | |
183 premultiplied_alpha, | |
184 uv_top_right.origin(), | |
185 uv_top_right.bottom_right(), | |
186 vertex_opacity, flipped); | |
187 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
188 | |
189 quad = TextureDrawQuad::Create(); | |
190 quad->SetNew(shared_quad_state, | |
191 bottomLeft, | |
192 opaque_rect, | |
193 resource_id_, | |
194 premultiplied_alpha, | |
195 uv_bottom_left.origin(), | |
196 uv_bottom_left.bottom_right(), | |
197 vertex_opacity, | |
198 flipped); | |
199 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
200 | |
201 quad = TextureDrawQuad::Create(); | |
202 quad->SetNew(shared_quad_state, | |
203 bottomRight, | |
204 opaque_rect, | |
205 resource_id_, | |
206 premultiplied_alpha, | |
207 uv_bottom_right.origin(), | |
208 uv_bottom_right.bottom_right(), | |
209 vertex_opacity, | |
210 flipped); | |
211 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
212 | |
213 quad = TextureDrawQuad::Create(); | |
214 quad->SetNew(shared_quad_state, | |
215 top, | |
216 opaque_rect, | |
217 resource_id_, | |
218 premultiplied_alpha, | |
219 uvTop.origin(), | |
220 uvTop.bottom_right(), | |
221 vertex_opacity, | |
222 flipped); | |
223 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
224 | |
225 quad = TextureDrawQuad::Create(); | |
226 quad->SetNew(shared_quad_state, | |
227 left, | |
228 opaque_rect, | |
229 resource_id_, | |
230 premultiplied_alpha, | |
231 uvLeft.origin(), | |
232 uvLeft.bottom_right(), | |
233 vertex_opacity, | |
234 flipped); | |
235 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
236 | |
237 quad = TextureDrawQuad::Create(); | |
238 quad->SetNew(shared_quad_state, | |
239 right, | |
240 opaque_rect, | |
241 resource_id_, | |
242 premultiplied_alpha, | |
243 uvRight.origin(), | |
244 uvRight.bottom_right(), | |
245 vertex_opacity, | |
246 flipped); | |
247 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
248 | |
249 quad = TextureDrawQuad::Create(); | |
250 quad->SetNew(shared_quad_state, | |
251 bottom, | |
252 opaque_rect, | |
253 resource_id_, | |
254 premultiplied_alpha, | |
255 uvBottom.origin(), | |
256 uvBottom.bottom_right(), | |
257 vertex_opacity, | |
258 flipped); | |
259 quad_sink->Append(quad.PassAs<DrawQuad>(), append_quads_data); | |
260 } | |
261 | |
262 void NinePatchLayerImpl::DidDraw(ResourceProvider* resource_provider) {} | |
263 | |
264 void NinePatchLayerImpl::DidLoseOutputSurface() { | |
265 resource_id_ = 0; | |
266 } | |
267 | |
268 const char* NinePatchLayerImpl::LayerTypeAsString() const { | |
269 return "NinePatchLayer"; | |
270 } | |
271 | |
272 void NinePatchLayerImpl::DumpLayerProperties(std::string* str, int indent) | |
273 const { | |
274 str->append(IndentString(indent)); | |
275 base::StringAppendF( | |
276 str, "imageAperture: %s\n", image_aperture_.ToString().c_str()); | |
277 base::StringAppendF( | |
278 str, "image_bounds: %s\n", image_bounds_.ToString().c_str()); | |
279 LayerImpl::DumpLayerProperties(str, indent); | |
280 } | |
281 | |
282 base::DictionaryValue* NinePatchLayerImpl::LayerTreeAsJson() const { | |
283 base::DictionaryValue* result = LayerImpl::LayerTreeAsJson(); | |
284 | |
285 base::ListValue* list = new base::ListValue; | |
286 list->AppendInteger(image_aperture_.origin().x()); | |
287 list->AppendInteger(image_aperture_.origin().y()); | |
288 list->AppendInteger(image_aperture_.size().width()); | |
289 list->AppendInteger(image_aperture_.size().height()); | |
290 result->Set("ImageAperture", list); | |
291 | |
292 list = new base::ListValue; | |
293 list->AppendInteger(image_bounds_.width()); | |
294 list->AppendInteger(image_bounds_.height()); | |
295 result->Set("ImageBounds", list); | |
296 | |
297 return result; | |
298 } | |
299 | |
300 } // namespace cc | |
OLD | NEW |