OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 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 "cc/quads/nine_patch_generator.h" | |
6 | |
7 #include "base/values.h" | |
8 #include "cc/base/math_util.h" | |
9 #include "cc/layers/append_quads_data.h" | |
10 #include "cc/layers/draw_properties.h" | |
11 #include "cc/quads/render_pass.h" | |
12 #include "cc/quads/shared_quad_state.h" | |
13 #include "cc/quads/texture_draw_quad.h" | |
aelias_OOO_until_Jul13
2017/02/28 23:23:51
Some of these includes aren't used (unless you mov
bokan
2017/03/01 00:44:21
Done and pared this down to what's needed.
| |
14 #include "cc/resources/resource_provider.h" | |
15 #include "cc/trees/layer_tree_impl.h" | |
16 #include "cc/trees/occlusion.h" | |
17 #include "ui/gfx/geometry/rect_f.h" | |
18 | |
19 namespace cc { | |
20 | |
21 namespace { | |
22 | |
23 // Maximum number of patches that can be produced for one NinePatchLayer. | |
24 const int kMaxOcclusionPatches = 12; | |
25 const int kMaxPatches = 9; | |
26 | |
27 gfx::RectF BoundsToRect(int x1, int y1, int x2, int y2) { | |
28 return gfx::RectF(x1, y1, x2 - x1, y2 - y1); | |
29 } | |
30 | |
31 gfx::RectF NormalizedRect(const gfx::RectF& rect, | |
32 float total_width, | |
33 float total_height) { | |
34 return gfx::RectF(rect.x() / total_width, rect.y() / total_height, | |
35 rect.width() / total_width, rect.height() / total_height); | |
36 } | |
37 | |
38 } // namespace | |
39 | |
40 NinePatchGenerator::Patch::Patch(const gfx::RectF& image_rect, | |
41 const gfx::Size& total_image_bounds, | |
42 const gfx::RectF& output_rect) | |
43 : image_rect(image_rect), | |
44 normalized_image_rect(NormalizedRect(image_rect, | |
45 total_image_bounds.width(), | |
46 total_image_bounds.height())), | |
47 output_rect(output_rect) {} | |
48 | |
49 NinePatchGenerator::NinePatchGenerator() : fill_center_(false) {} | |
50 | |
51 bool NinePatchGenerator::SetLayout(const gfx::Size& image_bounds, | |
52 const gfx::Size& output_bounds, | |
53 const gfx::Rect& aperture, | |
54 const gfx::Rect& border, | |
55 const gfx::Rect& output_occlusion, | |
56 bool fill_center) { | |
57 if (image_bounds_ == image_bounds && output_bounds_ == output_bounds && | |
58 image_aperture_ == aperture && border_ == border && | |
59 fill_center_ == fill_center && output_occlusion_ == output_occlusion) | |
60 return false; | |
61 | |
62 image_bounds_ = image_bounds; | |
63 output_bounds_ = output_bounds; | |
64 image_aperture_ = aperture; | |
65 border_ = border; | |
66 fill_center_ = fill_center; | |
67 output_occlusion_ = output_occlusion; | |
68 | |
69 CheckGeometryLimitations(); | |
70 | |
71 return true; | |
72 } | |
73 | |
74 void NinePatchGenerator::CheckGeometryLimitations() { | |
75 // |border| is in layer space. It cannot exceed the bounds of the layer. | |
76 DCHECK_GE(output_bounds_.width(), border_.width()); | |
77 DCHECK_GE(output_bounds_.height(), border_.height()); | |
78 | |
79 // Sanity Check on |border| | |
80 DCHECK_LE(border_.x(), border_.width()); | |
81 DCHECK_LE(border_.y(), border_.height()); | |
82 DCHECK_GE(border_.x(), 0); | |
83 DCHECK_GE(border_.y(), 0); | |
84 | |
85 // |aperture| is in image space. It cannot exceed the bounds of the bitmap. | |
86 DCHECK(!image_aperture_.size().IsEmpty()); | |
87 DCHECK(gfx::Rect(image_bounds_).Contains(image_aperture_)) | |
88 << "image_bounds_ " << gfx::Rect(image_bounds_).ToString() | |
89 << " image_aperture_ " << image_aperture_.ToString(); | |
90 | |
91 // Sanity check on |output_occlusion_|. It should always be within the | |
92 // border. | |
93 gfx::Rect border_rect(border_.x(), border_.y(), | |
94 output_bounds_.width() - border_.width(), | |
95 output_bounds_.height() - border_.height()); | |
96 DCHECK(output_occlusion_.IsEmpty() || output_occlusion_.Contains(border_rect)) | |
97 << "border_rect " << border_rect.ToString() << " output_occlusion_ " | |
98 << output_occlusion_.ToString(); | |
99 } | |
100 | |
101 std::vector<NinePatchGenerator::Patch> | |
102 NinePatchGenerator::ComputeQuadsWithoutOcclusion() const { | |
103 float image_width = image_bounds_.width(); | |
104 float image_height = image_bounds_.height(); | |
105 float output_width = output_bounds_.width(); | |
106 float output_height = output_bounds_.height(); | |
107 gfx::RectF output_aperture(border_.x(), border_.y(), | |
108 output_width - border_.width(), | |
109 output_height - border_.height()); | |
110 | |
111 std::vector<Patch> patches; | |
112 patches.reserve(kMaxPatches); | |
113 | |
114 // Top-left. | |
115 patches.push_back( | |
116 Patch(BoundsToRect(0, 0, image_aperture_.x(), image_aperture_.y()), | |
117 image_bounds_, | |
118 BoundsToRect(0, 0, output_aperture.x(), output_aperture.y()))); | |
119 | |
120 // Top-right. | |
121 patches.push_back(Patch(BoundsToRect(image_aperture_.right(), 0, image_width, | |
122 image_aperture_.y()), | |
123 image_bounds_, | |
124 BoundsToRect(output_aperture.right(), 0, output_width, | |
125 output_aperture.y()))); | |
126 | |
127 // Bottom-left. | |
128 patches.push_back(Patch(BoundsToRect(0, image_aperture_.bottom(), | |
129 image_aperture_.x(), image_height), | |
130 image_bounds_, | |
131 BoundsToRect(0, output_aperture.bottom(), | |
132 output_aperture.x(), output_height))); | |
133 | |
134 // Bottom-right. | |
135 patches.push_back( | |
136 Patch(BoundsToRect(image_aperture_.right(), image_aperture_.bottom(), | |
137 image_width, image_height), | |
138 image_bounds_, | |
139 BoundsToRect(output_aperture.right(), output_aperture.bottom(), | |
140 output_width, output_height))); | |
141 | |
142 // Top. | |
143 patches.push_back( | |
144 Patch(BoundsToRect(image_aperture_.x(), 0, image_aperture_.right(), | |
145 image_aperture_.y()), | |
146 image_bounds_, | |
147 BoundsToRect(output_aperture.x(), 0, output_aperture.right(), | |
148 output_aperture.y()))); | |
149 | |
150 // Left. | |
151 patches.push_back( | |
152 Patch(BoundsToRect(0, image_aperture_.y(), image_aperture_.x(), | |
153 image_aperture_.bottom()), | |
154 image_bounds_, | |
155 BoundsToRect(0, output_aperture.y(), output_aperture.x(), | |
156 output_aperture.bottom()))); | |
157 | |
158 // Right. | |
159 patches.push_back( | |
160 Patch(BoundsToRect(image_aperture_.right(), image_aperture_.y(), | |
161 image_width, image_aperture_.bottom()), | |
162 image_bounds_, | |
163 BoundsToRect(output_aperture.right(), output_aperture.y(), | |
164 output_width, output_aperture.bottom()))); | |
165 | |
166 // Bottom. | |
167 patches.push_back( | |
168 Patch(BoundsToRect(image_aperture_.x(), image_aperture_.bottom(), | |
169 image_aperture_.right(), image_height), | |
170 image_bounds_, | |
171 BoundsToRect(output_aperture.x(), output_aperture.bottom(), | |
172 output_aperture.right(), output_height))); | |
173 | |
174 // Center. | |
175 if (fill_center_) { | |
176 patches.push_back( | |
177 Patch(BoundsToRect(image_aperture_.x(), image_aperture_.y(), | |
178 image_aperture_.right(), image_aperture_.bottom()), | |
179 image_bounds_, | |
180 BoundsToRect(output_aperture.x(), output_aperture.y(), | |
181 output_aperture.right(), output_aperture.bottom()))); | |
182 } | |
183 | |
184 return patches; | |
185 } | |
186 | |
187 std::vector<NinePatchGenerator::Patch> | |
188 NinePatchGenerator::ComputeQuadsWithOcclusion() const { | |
189 float image_width = image_bounds_.width(); | |
190 float image_height = image_bounds_.height(); | |
191 | |
192 float output_width = output_bounds_.width(); | |
193 float output_height = output_bounds_.height(); | |
194 | |
195 float layer_border_right = border_.width() - border_.x(); | |
196 float layer_border_bottom = border_.height() - border_.y(); | |
197 | |
198 float image_aperture_right = image_width - image_aperture_.right(); | |
199 float image_aperture_bottom = image_height - image_aperture_.bottom(); | |
200 | |
201 float output_occlusion_right = output_width - output_occlusion_.right(); | |
202 float output_occlusion_bottom = output_height - output_occlusion_.bottom(); | |
203 | |
204 gfx::RectF image_occlusion(BoundsToRect( | |
205 border_.x() == 0 | |
206 ? 0 | |
207 : (output_occlusion_.x() * image_aperture_.x() / border_.x()), | |
208 border_.y() == 0 | |
209 ? 0 | |
210 : (output_occlusion_.y() * image_aperture_.y() / border_.y()), | |
211 image_width - (layer_border_right == 0 | |
212 ? 0 | |
213 : output_occlusion_right * image_aperture_right / | |
214 layer_border_right), | |
215 image_height - (layer_border_bottom == 0 | |
216 ? 0 | |
217 : output_occlusion_bottom * image_aperture_bottom / | |
218 layer_border_bottom))); | |
219 gfx::RectF output_aperture(border_.x(), border_.y(), | |
220 output_width - border_.width(), | |
221 output_height - border_.height()); | |
222 | |
223 std::vector<Patch> patches; | |
224 patches.reserve(kMaxOcclusionPatches); | |
225 | |
226 // Top-left-left. | |
227 patches.push_back( | |
228 Patch(BoundsToRect(0, 0, image_occlusion.x(), image_aperture_.y()), | |
229 image_bounds_, | |
230 BoundsToRect(0, 0, output_occlusion_.x(), output_aperture.y()))); | |
231 | |
232 // Top-left-right. | |
233 patches.push_back( | |
234 Patch(BoundsToRect(image_occlusion.x(), 0, image_aperture_.x(), | |
235 image_occlusion.y()), | |
236 image_bounds_, | |
237 BoundsToRect(output_occlusion_.x(), 0, output_aperture.x(), | |
238 output_occlusion_.y()))); | |
239 | |
240 // Top-center. | |
241 patches.push_back( | |
242 Patch(BoundsToRect(image_aperture_.x(), 0, image_aperture_.right(), | |
243 image_occlusion.y()), | |
244 image_bounds_, | |
245 BoundsToRect(output_aperture.x(), 0, output_aperture.right(), | |
246 output_occlusion_.y()))); | |
247 | |
248 // Top-right-left. | |
249 patches.push_back( | |
250 Patch(BoundsToRect(image_aperture_.right(), 0, image_occlusion.right(), | |
251 image_occlusion.y()), | |
252 image_bounds_, | |
253 BoundsToRect(output_aperture.right(), 0, output_occlusion_.right(), | |
254 output_occlusion_.y()))); | |
255 | |
256 // Top-right-right. | |
257 patches.push_back(Patch(BoundsToRect(image_occlusion.right(), 0, image_width, | |
258 image_aperture_.y()), | |
259 image_bounds_, | |
260 BoundsToRect(output_occlusion_.right(), 0, | |
261 output_width, output_aperture.y()))); | |
262 | |
263 // Left-center. | |
264 patches.push_back( | |
265 Patch(BoundsToRect(0, image_aperture_.y(), image_occlusion.x(), | |
266 image_aperture_.bottom()), | |
267 image_bounds_, | |
268 BoundsToRect(0, output_aperture.y(), output_occlusion_.x(), | |
269 output_aperture.bottom()))); | |
270 | |
271 // Right-center. | |
272 patches.push_back( | |
273 Patch(BoundsToRect(image_occlusion.right(), image_aperture_.y(), | |
274 image_width, image_aperture_.bottom()), | |
275 image_bounds_, | |
276 BoundsToRect(output_occlusion_.right(), output_aperture.y(), | |
277 output_width, output_aperture.bottom()))); | |
278 | |
279 // Bottom-left-left. | |
280 patches.push_back(Patch(BoundsToRect(0, image_aperture_.bottom(), | |
281 image_occlusion.x(), image_height), | |
282 image_bounds_, | |
283 BoundsToRect(0, output_aperture.bottom(), | |
284 output_occlusion_.x(), output_height))); | |
285 | |
286 // Bottom-left-right. | |
287 patches.push_back( | |
288 Patch(BoundsToRect(image_occlusion.x(), image_occlusion.bottom(), | |
289 image_aperture_.x(), image_height), | |
290 image_bounds_, | |
291 BoundsToRect(output_occlusion_.x(), output_occlusion_.bottom(), | |
292 output_aperture.x(), output_height))); | |
293 | |
294 // Bottom-center. | |
295 patches.push_back( | |
296 Patch(BoundsToRect(image_aperture_.x(), image_occlusion.bottom(), | |
297 image_aperture_.right(), image_height), | |
298 image_bounds_, | |
299 BoundsToRect(output_aperture.x(), output_occlusion_.bottom(), | |
300 output_aperture.right(), output_height))); | |
301 | |
302 // Bottom-right-left. | |
303 patches.push_back( | |
304 Patch(BoundsToRect(image_aperture_.right(), image_occlusion.bottom(), | |
305 image_occlusion.right(), image_height), | |
306 image_bounds_, | |
307 BoundsToRect(output_aperture.right(), output_occlusion_.bottom(), | |
308 output_occlusion_.right(), output_height))); | |
309 | |
310 // Bottom-right-right. | |
311 patches.push_back( | |
312 Patch(BoundsToRect(image_occlusion.right(), image_aperture_.bottom(), | |
313 image_width, image_height), | |
314 image_bounds_, | |
315 BoundsToRect(output_occlusion_.right(), output_aperture.bottom(), | |
316 output_width, output_height))); | |
317 | |
318 return patches; | |
319 } | |
320 | |
321 std::vector<NinePatchGenerator::Patch> NinePatchGenerator::GeneratePatches() | |
322 const { | |
323 DCHECK(!output_bounds_.IsEmpty()); | |
324 | |
325 std::vector<Patch> patches; | |
326 | |
327 if (output_occlusion_.IsEmpty() || fill_center_) | |
328 patches = ComputeQuadsWithoutOcclusion(); | |
329 else | |
330 patches = ComputeQuadsWithOcclusion(); | |
331 | |
332 return patches; | |
333 } | |
334 | |
335 void NinePatchGenerator::AsJson(base::DictionaryValue* dictionary) const { | |
336 base::ListValue* list = new base::ListValue; | |
337 list->AppendInteger(image_aperture_.origin().x()); | |
338 list->AppendInteger(image_aperture_.origin().y()); | |
339 list->AppendInteger(image_aperture_.size().width()); | |
340 list->AppendInteger(image_aperture_.size().height()); | |
341 dictionary->Set("ImageAperture", list); | |
342 | |
343 list = new base::ListValue; | |
344 list->AppendInteger(image_bounds_.width()); | |
345 list->AppendInteger(image_bounds_.height()); | |
346 dictionary->Set("ImageBounds", list); | |
347 | |
348 dictionary->Set("Border", MathUtil::AsValue(border_).release()); | |
349 | |
350 dictionary->SetBoolean("FillCenter", fill_center_); | |
351 | |
352 list = new base::ListValue; | |
353 list->AppendInteger(output_occlusion_.x()); | |
354 list->AppendInteger(output_occlusion_.y()); | |
355 list->AppendInteger(output_occlusion_.width()); | |
356 list->AppendInteger(output_occlusion_.height()); | |
357 dictionary->Set("OutputOcclusion", list); | |
358 } | |
359 | |
360 } // namespace cc | |
OLD | NEW |