OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 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 "ui/wm/core/shadow.h" | 5 #include "ui/wm/core/shadow.h" |
6 | 6 |
7 #include "base/lazy_instance.h" | 7 #include "base/lazy_instance.h" |
8 #include "ui/base/resource/resource_bundle.h" | 8 #include "ui/base/resource/resource_bundle.h" |
9 #include "ui/compositor/layer.h" | 9 #include "ui/compositor/layer.h" |
10 #include "ui/compositor/scoped_layer_animation_settings.h" | 10 #include "ui/compositor/scoped_layer_animation_settings.h" |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 UpdateLayerBounds(); | 123 UpdateLayerBounds(); |
124 } | 124 } |
125 | 125 |
126 void Shadow::RecreateShadowLayer() { | 126 void Shadow::RecreateShadowLayer() { |
127 shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH)); | 127 shadow_layer_.reset(new ui::Layer(ui::LAYER_NINE_PATCH)); |
128 shadow_layer_->set_name("Shadow"); | 128 shadow_layer_->set_name("Shadow"); |
129 shadow_layer_->SetVisible(true); | 129 shadow_layer_->SetVisible(true); |
130 shadow_layer_->SetFillsBoundsOpaquely(false); | 130 shadow_layer_->SetFillsBoundsOpaquely(false); |
131 layer()->Add(shadow_layer_.get()); | 131 layer()->Add(shadow_layer_.get()); |
132 | 132 |
133 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); | |
134 shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image); | |
135 UpdateLayerBounds(); | 133 UpdateLayerBounds(); |
136 } | 134 } |
137 | 135 |
138 void Shadow::UpdateLayerBounds() { | 136 void Shadow::UpdateLayerBounds() { |
139 const ShadowDetails& details = GetDetailsForElevation(ElevationForStyle()); | 137 if (content_bounds_.IsEmpty()) |
| 138 return; |
| 139 |
| 140 // The elevation depends on the style, but the ninebox assumption breaks down |
| 141 // when the window is too small. The height/width of |blur_region| will be |
| 142 // 4 * elevation (see GetDetailsForElevation), so cap elevation at the most we |
| 143 // can handle. |
| 144 const int smaller_dimension = |
| 145 std::min(content_bounds_.width(), content_bounds_.height()); |
| 146 const int size_adjusted_elevation = std::min( |
| 147 (smaller_dimension - 2 * kRoundedCornerRadius) / 4, ElevationForStyle()); |
| 148 const ShadowDetails& details = |
| 149 GetDetailsForElevation(size_adjusted_elevation); |
| 150 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) + |
| 151 gfx::Insets(kRoundedCornerRadius); |
| 152 if (size_adjusted_elevation != effective_elevation_) { |
| 153 shadow_layer_->UpdateNinePatchLayerImage(details.ninebox_image); |
| 154 // The ninebox grid is defined in terms of the image size. The shadow blurs |
| 155 // in both inward and outward directions from the edge of the contents, so |
| 156 // the aperture goes further inside the image than the shadow margins (which |
| 157 // represent exterior blur). |
| 158 gfx::Rect aperture(details.ninebox_image.size()); |
| 159 aperture.Inset(blur_region); |
| 160 shadow_layer_->UpdateNinePatchLayerAperture(aperture); |
| 161 } |
| 162 effective_elevation_ = size_adjusted_elevation; |
| 163 |
140 // Shadow margins are negative, so this expands outwards from | 164 // Shadow margins are negative, so this expands outwards from |
141 // |content_bounds_|. | 165 // |content_bounds_|. |
142 const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values); | 166 const gfx::Insets margins = gfx::ShadowValue::GetMargin(details.values); |
143 gfx::Rect new_layer_bounds = content_bounds_; | 167 gfx::Rect new_layer_bounds = content_bounds_; |
144 new_layer_bounds.Inset(margins); | 168 new_layer_bounds.Inset(margins); |
145 gfx::Rect shadow_layer_bounds(new_layer_bounds.size()); | 169 gfx::Rect shadow_layer_bounds(new_layer_bounds.size()); |
146 | 170 |
147 // When there's an old shadow fading out, the bounds of layer() have to be | 171 // When there's an old shadow fading out, the bounds of layer() have to be |
148 // big enough to encompass both shadows. | 172 // big enough to encompass both shadows. |
149 if (fading_layer_) { | 173 if (fading_layer_) { |
(...skipping 17 matching lines...) Expand all Loading... |
167 } | 191 } |
168 | 192 |
169 shadow_layer_->SetBounds(shadow_layer_bounds); | 193 shadow_layer_->SetBounds(shadow_layer_bounds); |
170 | 194 |
171 // Occlude the region inside the bounding box. Occlusion uses shadow layer | 195 // Occlude the region inside the bounding box. Occlusion uses shadow layer |
172 // space. See nine_patch_layer.h for more context on what's going on here. | 196 // space. See nine_patch_layer.h for more context on what's going on here. |
173 gfx::Rect occlusion_bounds(shadow_layer_bounds.size()); | 197 gfx::Rect occlusion_bounds(shadow_layer_bounds.size()); |
174 occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius)); | 198 occlusion_bounds.Inset(-margins + gfx::Insets(kRoundedCornerRadius)); |
175 shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds); | 199 shadow_layer_->UpdateNinePatchOcclusion(occlusion_bounds); |
176 | 200 |
177 // The border is more or less the same inset as the aperture, but can be no | 201 // The border is the same inset as the aperture. |
178 // larger than the shadow layer. When the shadow layer is too small, shrink | |
179 // the dimensions proportionally. | |
180 gfx::Insets blur_region = gfx::ShadowValue::GetBlurRegion(details.values) + | |
181 gfx::Insets(kRoundedCornerRadius); | |
182 int border_w = std::min(blur_region.width(), shadow_layer_bounds.width()); | |
183 int border_x = border_w * blur_region.left() / blur_region.width(); | |
184 int border_h = std::min(blur_region.height(), shadow_layer_bounds.height()); | |
185 int border_y = border_h * blur_region.top() / blur_region.height(); | |
186 shadow_layer_->UpdateNinePatchLayerBorder( | 202 shadow_layer_->UpdateNinePatchLayerBorder( |
187 gfx::Rect(border_x, border_y, border_w, border_h)); | 203 gfx::Rect(blur_region.left(), blur_region.top(), blur_region.width(), |
188 | 204 blur_region.height())); |
189 // The ninebox grid is defined in terms of the image size. The shadow blurs in | |
190 // both inward and outward directions from the edge of the contents, so the | |
191 // aperture goes further inside the image than the shadow margins (which | |
192 // represent exterior blur). | |
193 gfx::Rect aperture(details.ninebox_image.size()); | |
194 // The insets for the aperture are nominally |blur_region| but we need to | |
195 // resize them if the contents are too small. | |
196 // TODO(estade): by cutting out parts of ninebox, we lose the smooth | |
197 // horizontal or vertical transition. This isn't very noticeable, but we may | |
198 // need to address it by using a separate shadow layer for each ShadowValue, | |
199 // by adjusting the shadow for very small windows, or other means. | |
200 aperture.Inset(gfx::Insets(border_y, border_x, border_h - border_y, | |
201 border_w - border_x)); | |
202 shadow_layer_->UpdateNinePatchLayerAperture(aperture); | |
203 } | 205 } |
204 | 206 |
205 int Shadow::ElevationForStyle() { | 207 int Shadow::ElevationForStyle() { |
206 switch (style_) { | 208 switch (style_) { |
207 case STYLE_ACTIVE: | 209 case STYLE_ACTIVE: |
208 return 24; | 210 return 24; |
209 case STYLE_INACTIVE: | 211 case STYLE_INACTIVE: |
210 return 8; | 212 return 8; |
211 case STYLE_SMALL: | 213 case STYLE_SMALL: |
212 return 6; | 214 return 6; |
213 } | 215 } |
214 NOTREACHED(); | 216 NOTREACHED(); |
215 return 0; | 217 return 0; |
216 } | 218 } |
217 | 219 |
218 } // namespace wm | 220 } // namespace wm |
OLD | NEW |