Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(53)

Side by Side Diff: cc/quads/nine_patch_generator.cc

Issue 2591863003: Use nine-patch resource for drawing Aura overlay scrollbar thumb. (Closed)
Patch Set: Finish Plumbing Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(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"
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 return true;
70 }
71
72 void NinePatchGenerator::CheckGeometryLimitations() {
73 // |border| is in layer space. It cannot exceed the bounds of the layer.
74 DCHECK_GE(output_bounds_.width(), border_.width());
75 DCHECK_GE(output_bounds_.height(), border_.height());
76
77 // Sanity Check on |border|
78 DCHECK_LE(border_.x(), border_.width());
79 DCHECK_LE(border_.y(), border_.height());
80 DCHECK_GE(border_.x(), 0);
81 DCHECK_GE(border_.y(), 0);
82
83 // |aperture| is in image space. It cannot exceed the bounds of the bitmap.
84 DCHECK(!image_aperture_.size().IsEmpty());
85 DCHECK(gfx::Rect(image_bounds_).Contains(image_aperture_))
86 << "image_bounds_ " << gfx::Rect(image_bounds_).ToString()
87 << " image_aperture_ " << image_aperture_.ToString();
88
89 // Sanity check on |output_occlusion_|. It should always be within the
90 // border.
91 gfx::Rect border_rect(border_.x(), border_.y(),
92 output_bounds_.width() - border_.width(),
93 output_bounds_.height() - border_.height());
94 DCHECK(output_occlusion_.IsEmpty() || output_occlusion_.Contains(border_rect))
95 << "border_rect " << border_rect.ToString() << " output_occlusion_ "
96 << output_occlusion_.ToString();
97 }
98
99 std::vector<NinePatchGenerator::Patch>
100 NinePatchGenerator::ComputeQuadsWithoutOcclusion() const {
101 float image_width = image_bounds_.width();
102 float image_height = image_bounds_.height();
103 float output_width = output_bounds_.width();
104 float output_height = output_bounds_.height();
105 gfx::RectF output_aperture(border_.x(), border_.y(),
106 output_width - border_.width(),
107 output_height - border_.height());
108
109 std::vector<Patch> patches;
110 patches.reserve(kMaxPatches);
111
112 // Top-left.
113 patches.push_back(
114 Patch(BoundsToRect(0, 0, image_aperture_.x(), image_aperture_.y()),
115 image_bounds_,
116 BoundsToRect(0, 0, output_aperture.x(), output_aperture.y())));
117
118 // Top-right.
119 patches.push_back(Patch(BoundsToRect(image_aperture_.right(), 0, image_width,
120 image_aperture_.y()),
121 image_bounds_,
122 BoundsToRect(output_aperture.right(), 0, output_width,
123 output_aperture.y())));
124
125 // Bottom-left.
126 patches.push_back(Patch(BoundsToRect(0, image_aperture_.bottom(),
127 image_aperture_.x(), image_height),
128 image_bounds_,
129 BoundsToRect(0, output_aperture.bottom(),
130 output_aperture.x(), output_height)));
131
132 // Bottom-right.
133 patches.push_back(
134 Patch(BoundsToRect(image_aperture_.right(), image_aperture_.bottom(),
135 image_width, image_height),
136 image_bounds_,
137 BoundsToRect(output_aperture.right(), output_aperture.bottom(),
138 output_width, output_height)));
139
140 // Top.
141 patches.push_back(
142 Patch(BoundsToRect(image_aperture_.x(), 0, image_aperture_.right(),
143 image_aperture_.y()),
144 image_bounds_,
145 BoundsToRect(output_aperture.x(), 0, output_aperture.right(),
146 output_aperture.y())));
147
148 // Left.
149 patches.push_back(Patch(
150 BoundsToRect(0, image_aperture_.y(), image_aperture_.x(),
151 image_aperture_.bottom()),
152 image_bounds_, BoundsToRect(0, output_aperture.y(), output_aperture.x(),
153 output_aperture.bottom())));
154
155 // Right.
156 patches.push_back(Patch(
157 BoundsToRect(image_aperture_.right(), image_aperture_.y(), image_width,
158 image_aperture_.bottom()),
159 image_bounds_, BoundsToRect(output_aperture.right(), output_aperture.y(),
160 output_width, output_aperture.bottom())));
161
162 // Bottom.
163 patches.push_back(Patch(
164 BoundsToRect(image_aperture_.x(), image_aperture_.bottom(),
165 image_aperture_.right(), image_height),
166 image_bounds_, BoundsToRect(output_aperture.x(), output_aperture.bottom(),
167 output_aperture.right(), output_height)));
168
169 // Center.
170 if (fill_center_) {
171 patches.push_back(
172 Patch(BoundsToRect(image_aperture_.x(), image_aperture_.y(),
173 image_aperture_.right(), image_aperture_.bottom()),
174 image_bounds_,
175 BoundsToRect(output_aperture.x(), output_aperture.y(),
176 output_aperture.right(), output_aperture.bottom())));
177 }
178
179 return patches;
180 }
181
182 std::vector<NinePatchGenerator::Patch>
183 NinePatchGenerator::ComputeQuadsWithOcclusion() const {
184 float image_width = image_bounds_.width();
185 float image_height = image_bounds_.height();
186
187 float output_width = output_bounds_.width();
188 float output_height = output_bounds_.height();
189
190 float layer_border_right = border_.width() - border_.x();
191 float layer_border_bottom = border_.height() - border_.y();
192
193 float image_aperture_right = image_width - image_aperture_.right();
194 float image_aperture_bottom = image_height - image_aperture_.bottom();
195
196 float output_occlusion_right = output_width - output_occlusion_.right();
197 float output_occlusion_bottom = output_height - output_occlusion_.bottom();
198
199 gfx::RectF image_occlusion(BoundsToRect(
200 border_.x() == 0 ? 0 : (output_occlusion_.x() * image_aperture_.x() /
201 border_.x()),
202 border_.y() == 0 ? 0 : (output_occlusion_.y() * image_aperture_.y() /
203 border_.y()),
204 image_width - (layer_border_right == 0
205 ? 0
206 : output_occlusion_right * image_aperture_right /
207 layer_border_right),
208 image_height - (layer_border_bottom == 0
209 ? 0
210 : output_occlusion_bottom * image_aperture_bottom /
211 layer_border_bottom)));
212 gfx::RectF output_aperture(border_.x(), border_.y(),
213 output_width - border_.width(),
214 output_height - border_.height());
215
216 std::vector<Patch> patches;
217 patches.reserve(kMaxOcclusionPatches);
218
219 // Top-left-left.
220 patches.push_back(
221 Patch(BoundsToRect(0, 0, image_occlusion.x(), image_aperture_.y()),
222 image_bounds_,
223 BoundsToRect(0, 0, output_occlusion_.x(), output_aperture.y())));
224
225 // Top-left-right.
226 patches.push_back(Patch(
227 BoundsToRect(image_occlusion.x(), 0, image_aperture_.x(),
228 image_occlusion.y()),
229 image_bounds_, BoundsToRect(output_occlusion_.x(), 0, output_aperture.x(),
230 output_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 image_bounds_,
237 BoundsToRect(output_aperture.x(), 0, output_aperture.right(),
238 output_occlusion_.y())));
239
240 // Top-right-left.
241 patches.push_back(
242 Patch(BoundsToRect(image_aperture_.right(), 0, image_occlusion.right(),
243 image_occlusion.y()),
244 image_bounds_,
245 BoundsToRect(output_aperture.right(), 0, output_occlusion_.right(),
246 output_occlusion_.y())));
247
248 // Top-right-right.
249 patches.push_back(Patch(BoundsToRect(image_occlusion.right(), 0, image_width,
250 image_aperture_.y()),
251 image_bounds_,
252 BoundsToRect(output_occlusion_.right(), 0,
253 output_width, output_aperture.y())));
254
255 // Left-center.
256 patches.push_back(Patch(
257 BoundsToRect(0, image_aperture_.y(), image_occlusion.x(),
258 image_aperture_.bottom()),
259 image_bounds_, BoundsToRect(0, output_aperture.y(), output_occlusion_.x(),
260 output_aperture.bottom())));
261
262 // Right-center.
263 patches.push_back(
264 Patch(BoundsToRect(image_occlusion.right(), image_aperture_.y(),
265 image_width, image_aperture_.bottom()),
266 image_bounds_,
267 BoundsToRect(output_occlusion_.right(), output_aperture.y(),
268 output_width, output_aperture.bottom())));
269
270 // Bottom-left-left.
271 patches.push_back(Patch(BoundsToRect(0, image_aperture_.bottom(),
272 image_occlusion.x(), image_height),
273 image_bounds_,
274 BoundsToRect(0, output_aperture.bottom(),
275 output_occlusion_.x(), output_height)));
276
277 // Bottom-left-right.
278 patches.push_back(
279 Patch(BoundsToRect(image_occlusion.x(), image_occlusion.bottom(),
280 image_aperture_.x(), image_height),
281 image_bounds_,
282 BoundsToRect(output_occlusion_.x(), output_occlusion_.bottom(),
283 output_aperture.x(), output_height)));
284
285 // Bottom-center.
286 patches.push_back(
287 Patch(BoundsToRect(image_aperture_.x(), image_occlusion.bottom(),
288 image_aperture_.right(), image_height),
289 image_bounds_,
290 BoundsToRect(output_aperture.x(), output_occlusion_.bottom(),
291 output_aperture.right(), output_height)));
292
293 // Bottom-right-left.
294 patches.push_back(
295 Patch(BoundsToRect(image_aperture_.right(), image_occlusion.bottom(),
296 image_occlusion.right(), image_height),
297 image_bounds_,
298 BoundsToRect(output_aperture.right(), output_occlusion_.bottom(),
299 output_occlusion_.right(), output_height)));
300
301 // Bottom-right-right.
302 patches.push_back(
303 Patch(BoundsToRect(image_occlusion.right(), image_aperture_.bottom(),
304 image_width, image_height),
305 image_bounds_,
306 BoundsToRect(output_occlusion_.right(), output_aperture.bottom(),
307 output_width, output_height)));
308
309 return patches;
310 }
311
312 std::vector<NinePatchGenerator::Patch> NinePatchGenerator::GeneratePatches()
313 const {
314 DCHECK(!output_bounds_.IsEmpty());
315
316 std::vector<Patch> patches;
317
318 if (output_occlusion_.IsEmpty() || fill_center_)
319 patches = ComputeQuadsWithoutOcclusion();
320 else
321 patches = ComputeQuadsWithOcclusion();
322
323 return patches;
324 }
325
326 void NinePatchGenerator::AsJson(base::DictionaryValue* dictionary) const {
327 base::ListValue* list = new base::ListValue;
328 list->AppendInteger(image_aperture_.origin().x());
329 list->AppendInteger(image_aperture_.origin().y());
330 list->AppendInteger(image_aperture_.size().width());
331 list->AppendInteger(image_aperture_.size().height());
332 dictionary->Set("ImageAperture", list);
333
334 list = new base::ListValue;
335 list->AppendInteger(image_bounds_.width());
336 list->AppendInteger(image_bounds_.height());
337 dictionary->Set("ImageBounds", list);
338
339 dictionary->Set("Border", MathUtil::AsValue(border_).release());
340
341 dictionary->SetBoolean("FillCenter", fill_center_);
342
343 list = new base::ListValue;
344 list->AppendInteger(output_occlusion_.x());
345 list->AppendInteger(output_occlusion_.y());
346 list->AppendInteger(output_occlusion_.width());
347 list->AppendInteger(output_occlusion_.height());
348 dictionary->Set("OutputOcclusion", list);
349 }
350
351 } // namespace cc
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698