Chromium Code Reviews| 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 |