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
3 // found in the LICENSE file.
5 #ifndef UI_WM_CORE_IMAGE_GRID_H_
6 #define UI_WM_CORE_IMAGE_GRID_H_
8 #include "base/basictypes.h"
9 #include "base/gtest_prod_util.h"
10 #include "base/memory/scoped_ptr.h"
11 #include "ui/compositor/layer.h"
12 #include "ui/compositor/layer_delegate.h"
13 #include "ui/gfx/geometry/rect.h"
14 #include "ui/gfx/geometry/size.h"
15 #include "ui/gfx/image/image_skia.h"
16 #include "ui/wm/wm_export.h"
24 // An ImageGrid is a 3x3 array of ui::Layers, each containing an image.
26 // As the grid is resized, its images fill the requested space:
27 // - corner images are not scaled
28 // - top and bottom images are scaled horizontally
29 // - left and right images are scaled vertically
30 // - the center image is scaled in both directions
32 // If one of the non-center images is smaller than the largest images in its
33 // row or column, it will be aligned with the outside of the grid. For
34 // example, given 4x4 top-left and top-right images and a 1x2 top images:
36 // +--------+---------------------+--------+
38 // | top- +---------------------+ top- +
40 // +----+---+ +---+----+
44 // This may seem odd at first, but it lets ImageGrid be used to draw shadows
45 // with curved corners that extend inwards beyond a window's borders. In the
46 // below example, the top-left corner image is overlaid on top of the window's
49 // +---------+-----------------------
50 // | ..xxx|XXXXXXXXXXXXXXXXXX
51 // | .xXXXXX|XXXXXXXXXXXXXXXXXX_____
52 // | .xXX | ^ window's top edge
56 // | xXX|< window's left edge
60 class WM_EXPORT ImageGrid
{
62 // Helper class for use by tests.
63 class WM_EXPORT TestAPI
{
65 TestAPI(ImageGrid
* grid
) : grid_(grid
) {}
67 gfx::Rect
top_left_clip_rect() const {
68 return grid_
->top_left_painter_
->clip_rect_
;
70 gfx::Rect
top_right_clip_rect() const {
71 return grid_
->top_right_painter_
->clip_rect_
;
73 gfx::Rect
bottom_left_clip_rect() const {
74 return grid_
->bottom_left_painter_
->clip_rect_
;
76 gfx::Rect
bottom_right_clip_rect() const {
77 return grid_
->bottom_right_painter_
->clip_rect_
;
80 // Returns |layer|'s bounds after applying the layer's current transform.
81 gfx::RectF
GetTransformedLayerBounds(const ui::Layer
& layer
);
84 ImageGrid
* grid_
; // not owned
86 DISALLOW_COPY_AND_ASSIGN(TestAPI
);
92 ui::Layer
* layer() { return layer_
.get(); }
93 int top_image_height() const { return top_image_height_
; }
94 int bottom_image_height() const { return bottom_image_height_
; }
95 int left_image_width() const { return left_image_width_
; }
96 int right_image_width() const { return right_image_width_
; }
98 // Visible to allow independent layer animations and for testing.
99 ui::Layer
* top_left_layer() const { return top_left_layer_
.get(); }
100 ui::Layer
* top_layer() const { return top_layer_
.get(); }
101 ui::Layer
* top_right_layer() const { return top_right_layer_
.get(); }
102 ui::Layer
* left_layer() const { return left_layer_
.get(); }
103 ui::Layer
* center_layer() const { return center_layer_
.get(); }
104 ui::Layer
* right_layer() const { return right_layer_
.get(); }
105 ui::Layer
* bottom_left_layer() const { return bottom_left_layer_
.get(); }
106 ui::Layer
* bottom_layer() const { return bottom_layer_
.get(); }
107 ui::Layer
* bottom_right_layer() const { return bottom_right_layer_
.get(); }
109 // Sets the grid to display the passed-in images (any of which can be NULL).
110 // Ownership of the images remains with the caller. May be called more than
111 // once to switch images.
112 void SetImages(const gfx::Image
* top_left_image
,
113 const gfx::Image
* top_image
,
114 const gfx::Image
* top_right_image
,
115 const gfx::Image
* left_image
,
116 const gfx::Image
* center_image
,
117 const gfx::Image
* right_image
,
118 const gfx::Image
* bottom_left_image
,
119 const gfx::Image
* bottom_image
,
120 const gfx::Image
* bottom_right_image
);
122 void SetSize(const gfx::Size
& size
);
124 // Sets the grid to a position and size such that the inner edges of the top,
125 // bottom, left and right images will be flush with |content_bounds_in_dip|.
126 void SetContentBounds(const gfx::Rect
& content_bounds_in_dip
);
129 // Delegate responsible for painting a specific image on a layer.
130 class ImagePainter
: public ui::LayerDelegate
{
132 ImagePainter(const gfx::ImageSkia
& image
) : image_(image
) {}
133 ~ImagePainter() override
{}
135 // Clips |layer| to |clip_rect|. Triggers a repaint if the clipping
136 // rectangle has changed. An empty rectangle disables clipping.
137 void SetClipRect(const gfx::Rect
& clip_rect
, ui::Layer
* layer
);
139 // ui::LayerDelegate implementation:
140 void OnPaintLayer(const ui::PaintContext
& context
) override
;
141 void OnDelegatedFrameDamage(const gfx::Rect
& damage_rect_in_dip
) override
;
142 void OnDeviceScaleFactorChanged(float device_scale_factor
) override
;
143 base::Closure
PrepareForLayerBoundsChange() override
;
146 friend class TestAPI
;
148 const gfx::ImageSkia image_
;
150 gfx::Rect clip_rect_
;
152 DISALLOW_COPY_AND_ASSIGN(ImagePainter
);
161 // Sets |layer_ptr| and |painter_ptr| to display |image| and adds the
162 // passed-in layer to |layer_|. If image is NULL resets |layer_ptr| and
163 // |painter_ptr| and removes any existing layer from |layer_|.
164 // If |type| is either HORIZONTAL or VERTICAL, it may resize the image to
165 // guarantee that it has minimum size in order for scaling work properly
166 // with fractional device scale factors. crbug.com/376519.
167 void SetImage(const gfx::Image
* image
,
168 scoped_ptr
<ui::Layer
>* layer_ptr
,
169 scoped_ptr
<ImagePainter
>* painter_ptr
,
172 // Layer that contains all of the image layers.
173 scoped_ptr
<ui::Layer
> layer_
;
175 // The grid's dimensions.
178 // Heights and widths of the images displayed by |top_layer_|,
179 // |bottom_layer_|, |left_layer_|, and |right_layer_|.
180 int top_image_height_
;
181 int bottom_image_height_
;
182 int left_image_width_
;
183 int right_image_width_
;
185 // Heights of the tallest images in the top and bottom rows and the widest
186 // images in the left and right columns. Note that we may have less actual
187 // space than this available if the images are large and |size_| is small.
188 int base_top_row_height_
;
189 int base_bottom_row_height_
;
190 int base_left_column_width_
;
191 int base_right_column_width_
;
193 // Layers used to display the various images. Children of |layer_|.
194 // Positions for which no images were supplied are NULL.
195 scoped_ptr
<ui::Layer
> top_left_layer_
;
196 scoped_ptr
<ui::Layer
> top_layer_
;
197 scoped_ptr
<ui::Layer
> top_right_layer_
;
198 scoped_ptr
<ui::Layer
> left_layer_
;
199 scoped_ptr
<ui::Layer
> center_layer_
;
200 scoped_ptr
<ui::Layer
> right_layer_
;
201 scoped_ptr
<ui::Layer
> bottom_left_layer_
;
202 scoped_ptr
<ui::Layer
> bottom_layer_
;
203 scoped_ptr
<ui::Layer
> bottom_right_layer_
;
205 // Delegates responsible for painting the above layers.
206 // Positions for which no images were supplied are NULL.
207 scoped_ptr
<ImagePainter
> top_left_painter_
;
208 scoped_ptr
<ImagePainter
> top_painter_
;
209 scoped_ptr
<ImagePainter
> top_right_painter_
;
210 scoped_ptr
<ImagePainter
> left_painter_
;
211 scoped_ptr
<ImagePainter
> center_painter_
;
212 scoped_ptr
<ImagePainter
> right_painter_
;
213 scoped_ptr
<ImagePainter
> bottom_left_painter_
;
214 scoped_ptr
<ImagePainter
> bottom_painter_
;
215 scoped_ptr
<ImagePainter
> bottom_right_painter_
;
217 DISALLOW_COPY_AND_ASSIGN(ImageGrid
);
222 #endif // UI_WM_CORE_IMAGE_GRID_H_