OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "cc/layers/nine_patch_layer_impl.h" | 5 #include "cc/layers/nine_patch_layer_impl.h" |
6 | 6 |
7 #include "base/strings/stringprintf.h" | 7 #include "base/strings/stringprintf.h" |
8 #include "base/values.h" | 8 #include "base/values.h" |
9 #include "cc/base/math_util.h" | 9 #include "cc/base/math_util.h" |
10 #include "cc/quads/texture_draw_quad.h" | 10 #include "cc/quads/texture_draw_quad.h" |
11 #include "cc/trees/layer_tree_impl.h" | 11 #include "cc/trees/layer_tree_impl.h" |
12 #include "cc/trees/occlusion.h" | 12 #include "cc/trees/occlusion.h" |
13 #include "ui/gfx/geometry/rect_conversions.h" | |
13 #include "ui/gfx/geometry/rect_f.h" | 14 #include "ui/gfx/geometry/rect_f.h" |
14 | 15 |
15 namespace cc { | 16 namespace cc { |
16 | 17 |
17 // Maximum number of patches that can be produced for one NinePatchLayer. | |
18 static const int kMaxOcclusionPatches = 12; | |
19 static const int kMaxPatches = 9; | |
20 | |
21 namespace { | |
22 | |
23 gfx::Rect ToRect(const gfx::RectF& rect) { | |
24 return gfx::Rect(rect.x(), rect.y(), rect.width(), rect.height()); | |
25 } | |
26 | |
27 } // namespace | |
28 | |
29 NinePatchLayerImpl::Patch::Patch(const gfx::RectF& image_rect, | |
30 const gfx::RectF& layer_rect) | |
31 : image_rect(image_rect), layer_rect(layer_rect) {} | |
32 | |
33 NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id) | 18 NinePatchLayerImpl::NinePatchLayerImpl(LayerTreeImpl* tree_impl, int id) |
34 : UIResourceLayerImpl(tree_impl, id), | 19 : UIResourceLayerImpl(tree_impl, id) {} |
35 fill_center_(false), | |
36 nearest_neighbor_(false) {} | |
37 | 20 |
38 NinePatchLayerImpl::~NinePatchLayerImpl() {} | 21 NinePatchLayerImpl::~NinePatchLayerImpl() {} |
39 | 22 |
40 std::unique_ptr<LayerImpl> NinePatchLayerImpl::CreateLayerImpl( | 23 std::unique_ptr<LayerImpl> NinePatchLayerImpl::CreateLayerImpl( |
41 LayerTreeImpl* tree_impl) { | 24 LayerTreeImpl* tree_impl) { |
42 return NinePatchLayerImpl::Create(tree_impl, id()); | 25 return NinePatchLayerImpl::Create(tree_impl, id()); |
43 } | 26 } |
44 | 27 |
45 void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) { | 28 void NinePatchLayerImpl::PushPropertiesTo(LayerImpl* layer) { |
46 UIResourceLayerImpl::PushPropertiesTo(layer); | 29 UIResourceLayerImpl::PushPropertiesTo(layer); |
47 NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); | 30 NinePatchLayerImpl* layer_impl = static_cast<NinePatchLayerImpl*>(layer); |
48 | 31 |
49 layer_impl->SetLayout(image_aperture_, border_, layer_occlusion_, | 32 layer_impl->quad_generator_ = this->quad_generator_; |
50 fill_center_, nearest_neighbor_); | |
51 } | |
52 | |
53 static gfx::RectF BoundsToRect(int x1, int y1, int x2, int y2) { | |
54 return gfx::RectF(x1, y1, x2 - x1, y2 - y1); | |
55 } | |
56 | |
57 static gfx::RectF NormalizedRect(const gfx::RectF& rect, | |
58 float total_width, | |
59 float total_height) { | |
60 return gfx::RectF(rect.x() / total_width, rect.y() / total_height, | |
61 rect.width() / total_width, rect.height() / total_height); | |
62 } | 33 } |
63 | 34 |
64 void NinePatchLayerImpl::SetLayout(const gfx::Rect& aperture, | 35 void NinePatchLayerImpl::SetLayout(const gfx::Rect& aperture, |
65 const gfx::Rect& border, | 36 const gfx::Rect& border, |
66 const gfx::Rect& layer_occlusion, | 37 const gfx::Rect& layer_occlusion, |
67 bool fill_center, | 38 bool fill_center, |
68 bool nearest_neighbor) { | 39 bool nearest_neighbor) { |
69 // This check imposes an ordering on the call sequence. An UIResource must | 40 // This check imposes an ordering on the call sequence. An UIResource must |
70 // exist before SetLayout can be called. | 41 // exist before SetLayout can be called. |
71 DCHECK(ui_resource_id_); | 42 DCHECK(ui_resource_id_); |
72 | 43 |
73 if (image_aperture_ == aperture && border_ == border && | 44 if (!quad_generator_.SetLayout(image_bounds_, bounds(), aperture, border, |
74 fill_center_ == fill_center && nearest_neighbor_ == nearest_neighbor && | 45 layer_occlusion, fill_center, |
75 layer_occlusion_ == layer_occlusion) | 46 nearest_neighbor)) |
76 return; | 47 return; |
77 | 48 |
78 image_aperture_ = aperture; | |
79 border_ = border; | |
80 fill_center_ = fill_center; | |
81 nearest_neighbor_ = nearest_neighbor; | |
82 layer_occlusion_ = layer_occlusion; | |
83 | |
84 NoteLayerPropertyChanged(); | 49 NoteLayerPropertyChanged(); |
85 } | 50 } |
86 | 51 |
87 void NinePatchLayerImpl::CheckGeometryLimitations() { | |
88 // |border| is in layer space. It cannot exceed the bounds of the layer. | |
89 DCHECK_GE(bounds().width(), border_.width()); | |
90 DCHECK_GE(bounds().height(), border_.height()); | |
91 | |
92 // Sanity Check on |border| | |
93 DCHECK_LE(border_.x(), border_.width()); | |
94 DCHECK_LE(border_.y(), border_.height()); | |
95 DCHECK_GE(border_.x(), 0); | |
96 DCHECK_GE(border_.y(), 0); | |
97 | |
98 // |aperture| is in image space. It cannot exceed the bounds of the bitmap. | |
99 DCHECK(!image_aperture_.size().IsEmpty()); | |
100 DCHECK(gfx::Rect(image_bounds_).Contains(image_aperture_)) | |
101 << "image_bounds_ " << gfx::Rect(image_bounds_).ToString() | |
102 << " image_aperture_ " << image_aperture_.ToString(); | |
103 | |
104 // Sanity check on |layer_occlusion_|. It should always be within the | |
105 // border. | |
106 gfx::Rect border_rect(border_.x(), border_.y(), | |
107 bounds().width() - border_.width(), | |
108 bounds().height() - border_.height()); | |
109 DCHECK(layer_occlusion_.IsEmpty() || layer_occlusion_.Contains(border_rect)) | |
110 << "border_rect " << border_rect.ToString() << " layer_occlusion_ " | |
111 << layer_occlusion_.ToString(); | |
112 } | |
113 | |
114 std::vector<NinePatchLayerImpl::Patch> | |
115 NinePatchLayerImpl::ComputeQuadsWithoutOcclusion() const { | |
116 float image_width = image_bounds_.width(); | |
117 float image_height = image_bounds_.height(); | |
118 float layer_width = bounds().width(); | |
119 float layer_height = bounds().height(); | |
120 gfx::RectF layer_aperture(border_.x(), border_.y(), | |
121 layer_width - border_.width(), | |
122 layer_height - border_.height()); | |
123 | |
124 std::vector<Patch> patches; | |
125 patches.reserve(kMaxPatches); | |
126 | |
127 // Top-left. | |
128 patches.push_back( | |
129 Patch(BoundsToRect(0, 0, image_aperture_.x(), image_aperture_.y()), | |
130 BoundsToRect(0, 0, layer_aperture.x(), layer_aperture.y()))); | |
131 | |
132 // Top-right. | |
133 patches.push_back(Patch(BoundsToRect(image_aperture_.right(), 0, image_width, | |
134 image_aperture_.y()), | |
135 BoundsToRect(layer_aperture.right(), 0, layer_width, | |
136 layer_aperture.y()))); | |
137 | |
138 // Bottom-left. | |
139 patches.push_back(Patch(BoundsToRect(0, image_aperture_.bottom(), | |
140 image_aperture_.x(), image_height), | |
141 BoundsToRect(0, layer_aperture.bottom(), | |
142 layer_aperture.x(), layer_height))); | |
143 | |
144 // Bottom-right. | |
145 patches.push_back( | |
146 Patch(BoundsToRect(image_aperture_.right(), image_aperture_.bottom(), | |
147 image_width, image_height), | |
148 BoundsToRect(layer_aperture.right(), layer_aperture.bottom(), | |
149 layer_width, layer_height))); | |
150 | |
151 // Top. | |
152 patches.push_back( | |
153 Patch(BoundsToRect(image_aperture_.x(), 0, image_aperture_.right(), | |
154 image_aperture_.y()), | |
155 BoundsToRect(layer_aperture.x(), 0, layer_aperture.right(), | |
156 layer_aperture.y()))); | |
157 | |
158 // Left. | |
159 patches.push_back( | |
160 Patch(BoundsToRect(0, image_aperture_.y(), image_aperture_.x(), | |
161 image_aperture_.bottom()), | |
162 BoundsToRect(0, layer_aperture.y(), layer_aperture.x(), | |
163 layer_aperture.bottom()))); | |
164 | |
165 // Right. | |
166 patches.push_back( | |
167 Patch(BoundsToRect(image_aperture_.right(), image_aperture_.y(), | |
168 image_width, image_aperture_.bottom()), | |
169 BoundsToRect(layer_aperture.right(), layer_aperture.y(), | |
170 layer_width, layer_aperture.bottom()))); | |
171 | |
172 // Bottom. | |
173 patches.push_back( | |
174 Patch(BoundsToRect(image_aperture_.x(), image_aperture_.bottom(), | |
175 image_aperture_.right(), image_height), | |
176 BoundsToRect(layer_aperture.x(), layer_aperture.bottom(), | |
177 layer_aperture.right(), layer_height))); | |
178 | |
179 // Center. | |
180 if (fill_center_) { | |
181 patches.push_back( | |
182 Patch(BoundsToRect(image_aperture_.x(), image_aperture_.y(), | |
183 image_aperture_.right(), image_aperture_.bottom()), | |
184 BoundsToRect(layer_aperture.x(), layer_aperture.y(), | |
185 layer_aperture.right(), layer_aperture.bottom()))); | |
186 } | |
187 | |
188 return patches; | |
189 } | |
190 | |
191 std::vector<NinePatchLayerImpl::Patch> | |
192 NinePatchLayerImpl::ComputeQuadsWithOcclusion() const { | |
193 float image_width = image_bounds_.width(), | |
194 image_height = image_bounds_.height(); | |
195 float layer_width = bounds().width(), layer_height = bounds().height(); | |
196 float layer_border_right = border_.width() - border_.x(), | |
197 layer_border_bottom = border_.height() - border_.y(); | |
198 float image_aperture_right = image_width - image_aperture_.right(), | |
199 image_aperture_bottom = image_height - image_aperture_.bottom(); | |
200 float layer_occlusion_right = layer_width - layer_occlusion_.right(), | |
201 layer_occlusion_bottom = layer_height - layer_occlusion_.bottom(); | |
202 gfx::RectF image_occlusion(BoundsToRect( | |
203 border_.x() == 0 ? 0 : (layer_occlusion_.x() * image_aperture_.x() / | |
204 border_.x()), | |
205 border_.y() == 0 ? 0 : (layer_occlusion_.y() * image_aperture_.y() / | |
206 border_.y()), | |
207 image_width - (layer_border_right == 0 ? 0 : layer_occlusion_right * | |
208 image_aperture_right / | |
209 layer_border_right), | |
210 image_height - (layer_border_bottom == 0 ? 0 : layer_occlusion_bottom * | |
211 image_aperture_bottom / | |
212 layer_border_bottom))); | |
213 gfx::RectF layer_aperture(border_.x(), border_.y(), | |
214 layer_width - border_.width(), | |
215 layer_height - border_.height()); | |
216 | |
217 std::vector<Patch> patches; | |
218 patches.reserve(kMaxOcclusionPatches); | |
219 | |
220 // Top-left-left. | |
221 patches.push_back( | |
222 Patch(BoundsToRect(0, 0, image_occlusion.x(), image_aperture_.y()), | |
223 BoundsToRect(0, 0, layer_occlusion_.x(), layer_aperture.y()))); | |
224 | |
225 // Top-left-right. | |
226 patches.push_back( | |
227 Patch(BoundsToRect(image_occlusion.x(), 0, image_aperture_.x(), | |
228 image_occlusion.y()), | |
229 BoundsToRect(layer_occlusion_.x(), 0, layer_aperture.x(), | |
230 layer_occlusion_.y()))); | |
231 | |
232 // Top-center. | |
233 patches.push_back( | |
234 Patch(BoundsToRect(image_aperture_.x(), 0, image_aperture_.right(), | |
235 image_occlusion.y()), | |
236 BoundsToRect(layer_aperture.x(), 0, layer_aperture.right(), | |
237 layer_occlusion_.y()))); | |
238 | |
239 // Top-right-left. | |
240 patches.push_back( | |
241 Patch(BoundsToRect(image_aperture_.right(), 0, image_occlusion.right(), | |
242 image_occlusion.y()), | |
243 BoundsToRect(layer_aperture.right(), 0, layer_occlusion_.right(), | |
244 layer_occlusion_.y()))); | |
245 | |
246 // Top-right-right. | |
247 patches.push_back(Patch(BoundsToRect(image_occlusion.right(), 0, image_width, | |
248 image_aperture_.y()), | |
249 BoundsToRect(layer_occlusion_.right(), 0, layer_width, | |
250 layer_aperture.y()))); | |
251 | |
252 // Left-center. | |
253 patches.push_back( | |
254 Patch(BoundsToRect(0, image_aperture_.y(), image_occlusion.x(), | |
255 image_aperture_.bottom()), | |
256 BoundsToRect(0, layer_aperture.y(), layer_occlusion_.x(), | |
257 layer_aperture.bottom()))); | |
258 | |
259 // Right-center. | |
260 patches.push_back( | |
261 Patch(BoundsToRect(image_occlusion.right(), image_aperture_.y(), | |
262 image_width, image_aperture_.bottom()), | |
263 BoundsToRect(layer_occlusion_.right(), layer_aperture.y(), | |
264 layer_width, layer_aperture.bottom()))); | |
265 | |
266 // Bottom-left-left. | |
267 patches.push_back(Patch(BoundsToRect(0, image_aperture_.bottom(), | |
268 image_occlusion.x(), image_height), | |
269 BoundsToRect(0, layer_aperture.bottom(), | |
270 layer_occlusion_.x(), layer_height))); | |
271 | |
272 // Bottom-left-right. | |
273 patches.push_back( | |
274 Patch(BoundsToRect(image_occlusion.x(), image_occlusion.bottom(), | |
275 image_aperture_.x(), image_height), | |
276 BoundsToRect(layer_occlusion_.x(), layer_occlusion_.bottom(), | |
277 layer_aperture.x(), layer_height))); | |
278 | |
279 // Bottom-center. | |
280 patches.push_back( | |
281 Patch(BoundsToRect(image_aperture_.x(), image_occlusion.bottom(), | |
282 image_aperture_.right(), image_height), | |
283 BoundsToRect(layer_aperture.x(), layer_occlusion_.bottom(), | |
284 layer_aperture.right(), layer_height))); | |
285 | |
286 // Bottom-right-left. | |
287 patches.push_back( | |
288 Patch(BoundsToRect(image_aperture_.right(), image_occlusion.bottom(), | |
289 image_occlusion.right(), image_height), | |
290 BoundsToRect(layer_aperture.right(), layer_occlusion_.bottom(), | |
291 layer_occlusion_.right(), layer_height))); | |
292 | |
293 // Bottom-right-right. | |
294 patches.push_back( | |
295 Patch(BoundsToRect(image_occlusion.right(), image_aperture_.bottom(), | |
296 image_width, image_height), | |
297 BoundsToRect(layer_occlusion_.right(), layer_aperture.bottom(), | |
298 layer_width, layer_height))); | |
299 | |
300 return patches; | |
301 } | |
302 | |
303 void NinePatchLayerImpl::AppendQuads( | 52 void NinePatchLayerImpl::AppendQuads( |
304 RenderPass* render_pass, | 53 RenderPass* render_pass, |
305 AppendQuadsData* append_quads_data) { | 54 AppendQuadsData* append_quads_data) { |
306 CheckGeometryLimitations(); | |
307 SharedQuadState* shared_quad_state = | 55 SharedQuadState* shared_quad_state = |
308 render_pass->CreateAndAppendSharedQuadState(); | 56 render_pass->CreateAndAppendSharedQuadState(); |
309 PopulateSharedQuadState(shared_quad_state); | 57 PopulateSharedQuadState(shared_quad_state); |
310 | 58 |
311 AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, | 59 AppendDebugBorderQuad(render_pass, bounds(), shared_quad_state, |
312 append_quads_data); | 60 append_quads_data); |
313 | 61 |
314 if (!ui_resource_id_) | |
315 return; | |
316 | |
317 ResourceId resource = | |
318 layer_tree_impl()->ResourceIdForUIResource(ui_resource_id_); | |
319 | |
320 if (!resource) | |
321 return; | |
322 | |
323 DCHECK(!bounds().IsEmpty()); | 62 DCHECK(!bounds().IsEmpty()); |
324 | 63 |
325 std::vector<Patch> patches; | 64 std::vector<NinePatchGenerator::Patch> patches = |
65 quad_generator_.GeneratePatches(); | |
326 | 66 |
327 if (layer_occlusion_.IsEmpty() || fill_center_) | 67 for (auto& patch : patches) |
328 patches = ComputeQuadsWithoutOcclusion(); | 68 patch.output_rect = |
329 else | 69 gfx::RectF(gfx::ToFlooredRectDeprecated(patch.output_rect)); |
Evan Stade
2017/03/01 16:45:49
seems like a function call you shouldn't be adding
bokan
2017/03/01 17:02:31
It's existing, moved from inside the loop this is
| |
330 patches = ComputeQuadsWithOcclusion(); | |
331 | 70 |
332 const float vertex_opacity[] = {1.0f, 1.0f, 1.0f, 1.0f}; | 71 quad_generator_.AppendQuads(this, ui_resource_id_, render_pass, |
333 const bool opaque = layer_tree_impl()->IsUIResourceOpaque(ui_resource_id_); | 72 shared_quad_state, patches); |
334 static const bool flipped = false; | |
335 static const bool premultiplied_alpha = true; | |
336 | |
337 for (const auto& patch : patches) { | |
338 gfx::Rect visible_rect = | |
339 draw_properties().occlusion_in_content_space.GetUnoccludedContentRect( | |
340 ToRect(patch.layer_rect)); | |
341 gfx::Rect opaque_rect = opaque ? visible_rect : gfx::Rect(); | |
342 if (!visible_rect.IsEmpty()) { | |
343 gfx::RectF image_rect(NormalizedRect( | |
344 patch.image_rect, image_bounds_.width(), image_bounds_.height())); | |
345 TextureDrawQuad* quad = | |
346 render_pass->CreateAndAppendDrawQuad<TextureDrawQuad>(); | |
347 quad->SetNew(shared_quad_state, ToRect(patch.layer_rect), opaque_rect, | |
348 visible_rect, resource, premultiplied_alpha, | |
349 image_rect.origin(), image_rect.bottom_right(), | |
350 SK_ColorTRANSPARENT, vertex_opacity, flipped, | |
351 nearest_neighbor_, false); | |
352 ValidateQuadResources(quad); | |
353 } | |
354 } | |
355 } | 73 } |
356 | 74 |
357 const char* NinePatchLayerImpl::LayerTypeAsString() const { | 75 const char* NinePatchLayerImpl::LayerTypeAsString() const { |
358 return "cc::NinePatchLayerImpl"; | 76 return "cc::NinePatchLayerImpl"; |
359 } | 77 } |
360 | 78 |
361 std::unique_ptr<base::DictionaryValue> NinePatchLayerImpl::LayerTreeAsJson() { | 79 std::unique_ptr<base::DictionaryValue> NinePatchLayerImpl::LayerTreeAsJson() { |
362 std::unique_ptr<base::DictionaryValue> result = LayerImpl::LayerTreeAsJson(); | 80 std::unique_ptr<base::DictionaryValue> result = LayerImpl::LayerTreeAsJson(); |
363 | 81 quad_generator_.AsJson(result.get()); |
364 base::ListValue* list = new base::ListValue; | |
365 list->AppendInteger(image_aperture_.origin().x()); | |
366 list->AppendInteger(image_aperture_.origin().y()); | |
367 list->AppendInteger(image_aperture_.size().width()); | |
368 list->AppendInteger(image_aperture_.size().height()); | |
369 result->Set("ImageAperture", list); | |
370 | |
371 list = new base::ListValue; | |
372 list->AppendInteger(image_bounds_.width()); | |
373 list->AppendInteger(image_bounds_.height()); | |
374 result->Set("ImageBounds", list); | |
375 | |
376 result->Set("Border", MathUtil::AsValue(border_).release()); | |
377 | |
378 result->SetBoolean("FillCenter", fill_center_); | |
379 | |
380 list = new base::ListValue; | |
381 list->AppendInteger(layer_occlusion_.x()); | |
382 list->AppendInteger(layer_occlusion_.y()); | |
383 list->AppendInteger(layer_occlusion_.width()); | |
384 list->AppendInteger(layer_occlusion_.height()); | |
385 result->Set("LayerOcclusion", list); | |
386 | |
387 return result; | 82 return result; |
388 } | 83 } |
389 | 84 |
390 } // namespace cc | 85 } // namespace cc |
OLD | NEW |