1 // Copyright 2014 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.
6 #include "core/paint/NinePieceImageGrid.h"
8 #include "core/css/CSSGradientValue.h"
9 #include "core/layout/LayoutTestHelper.h"
10 #include "core/style/ComputedStyle.h"
11 #include "core/style/NinePieceImage.h"
12 #include "core/style/StyleGeneratedImage.h"
13 #include <gtest/gtest.h>
18 class NinePieceImageGridTest
: public RenderingTest
{
20 NinePieceImageGridTest() { }
22 PassRefPtrWillBeRawPtr
<StyleImage
> generatedImage()
24 RefPtrWillBeRawPtr
<CSSLinearGradientValue
> gradient
= CSSLinearGradientValue::create(Repeating
);
25 return StyleGeneratedImage::create(gradient
.get());
31 RenderingTest::SetUp();
35 TEST_F(NinePieceImageGridTest
, NinePieceImagePainting_NoDrawables
)
37 NinePieceImage ninePiece
;
38 ninePiece
.setImage(generatedImage());
40 IntSize
imageSize(100, 100);
41 IntRect
borderImageArea(0, 0, 100, 100);
42 IntRectOutsets
borderWidths(0, 0, 0, 0);
44 NinePieceImageGrid grid
= NinePieceImageGrid(ninePiece
, imageSize
, borderImageArea
, borderWidths
);
45 for (NinePiece piece
= MinPiece
; piece
< MaxPiece
; ++piece
) {
46 NinePieceImageGrid::NinePieceDrawInfo drawInfo
= grid
.getNinePieceDrawInfo(piece
);
47 EXPECT_FALSE(drawInfo
.isDrawable
);
51 TEST_F(NinePieceImageGridTest
, NinePieceImagePainting_AllDrawable
)
53 NinePieceImage ninePiece
;
54 ninePiece
.setImage(generatedImage());
55 ninePiece
.setImageSlices(LengthBox(10, 10, 10, 10));
56 ninePiece
.setFill(true);
58 IntSize
imageSize(100, 100);
59 IntRect
borderImageArea(0, 0, 100, 100);
60 IntRectOutsets
borderWidths(10, 10, 10, 10);
62 NinePieceImageGrid grid
= NinePieceImageGrid(ninePiece
, imageSize
, borderImageArea
, borderWidths
);
63 for (NinePiece piece
= MinPiece
; piece
< MaxPiece
; ++piece
) {
64 NinePieceImageGrid::NinePieceDrawInfo drawInfo
= grid
.getNinePieceDrawInfo(piece
);
65 EXPECT_TRUE(drawInfo
.isDrawable
);
69 TEST_F(NinePieceImageGridTest
, NinePieceImagePainting_NoFillMiddleNotDrawable
)
71 NinePieceImage ninePiece
;
72 ninePiece
.setImage(generatedImage());
73 ninePiece
.setImageSlices(LengthBox(10, 10, 10, 10));
74 ninePiece
.setFill(false); // default
76 IntSize
imageSize(100, 100);
77 IntRect
borderImageArea(0, 0, 100, 100);
78 IntRectOutsets
borderWidths(10, 10, 10, 10);
80 NinePieceImageGrid grid
= NinePieceImageGrid(ninePiece
, imageSize
, borderImageArea
, borderWidths
);
81 for (NinePiece piece
= MinPiece
; piece
< MaxPiece
; ++piece
) {
82 NinePieceImageGrid::NinePieceDrawInfo drawInfo
= grid
.getNinePieceDrawInfo(piece
);
83 if (piece
!= MiddlePiece
)
84 EXPECT_TRUE(drawInfo
.isDrawable
);
86 EXPECT_FALSE(drawInfo
.isDrawable
);
90 TEST_F(NinePieceImageGridTest
, NinePieceImagePainting_TopLeftDrawable
)
92 NinePieceImage ninePiece
;
93 ninePiece
.setImage(generatedImage());
94 ninePiece
.setImageSlices(LengthBox(10, 10, 10, 10));
96 IntSize
imageSize(100, 100);
97 IntRect
borderImageArea(0, 0, 100, 100);
98 IntRectOutsets
borderWidths(10, 10, 10, 10);
101 IntRectOutsets borderWidths
;
102 bool expectedIsDrawable
;
104 { IntRectOutsets(0, 0, 0, 0), false },
105 { IntRectOutsets(10, 0, 0, 0), false },
106 { IntRectOutsets(0, 0, 0, 10), false },
107 { IntRectOutsets(10, 0, 0, 10), true },
110 for (const auto& testCase
: testCases
) {
111 NinePieceImageGrid grid
= NinePieceImageGrid(ninePiece
, imageSize
, borderImageArea
, testCase
.borderWidths
);
112 for (NinePiece piece
= MinPiece
; piece
< MaxPiece
; ++piece
) {
113 NinePieceImageGrid::NinePieceDrawInfo drawInfo
= grid
.getNinePieceDrawInfo(piece
);
114 if (piece
== TopLeftPiece
)
115 EXPECT_EQ(drawInfo
.isDrawable
, testCase
.expectedIsDrawable
);
120 TEST_F(NinePieceImageGridTest
, NinePieceImagePainting_ScaleDownBorder
)
122 NinePieceImage ninePiece
;
123 ninePiece
.setImage(generatedImage());
124 ninePiece
.setImageSlices(LengthBox(10, 10, 10, 10));
126 IntSize
imageSize(100, 100);
127 IntRect
borderImageArea(0, 0, 100, 100);
128 IntRectOutsets
borderWidths(10, 10, 10, 10);
130 // Set border slices wide enough so that the widths are scaled
131 // down and corner pieces cover the entire border image area.
132 ninePiece
.setBorderSlices(BorderImageLengthBox(6));
134 NinePieceImageGrid grid
= NinePieceImageGrid(ninePiece
, imageSize
, borderImageArea
, borderWidths
);
135 for (NinePiece piece
= MinPiece
; piece
< MaxPiece
; ++piece
) {
136 NinePieceImageGrid::NinePieceDrawInfo drawInfo
= grid
.getNinePieceDrawInfo(piece
);
137 if (drawInfo
.isCornerPiece
)
138 EXPECT_EQ(drawInfo
.destination
.size(), FloatSize(50, 50));
140 EXPECT_TRUE(drawInfo
.destination
.size().isEmpty());
144 TEST_F(NinePieceImageGridTest
, NinePieceImagePainting
)
148 IntRect borderImageArea
;
149 IntRectOutsets borderWidths
;
151 LengthBox imageSlices
;
152 Image::TileRule horizontalRule
;
153 Image::TileRule verticalRule
;
157 FloatRect destination
;
159 float tileScaleHorizontal
;
160 float tileScaleVertical
;
161 Image::TileRule horizontalRule
;
162 Image::TileRule verticalRule
;
166 // Empty border and slices but with fill
167 IntSize(100, 100), IntRect(0, 0, 100, 100), IntRectOutsets(0, 0, 0, 0), true,
168 LengthBox(Length(0, Fixed
), Length(0, Fixed
), Length(0, Fixed
), Length(0, Fixed
)), Image::StretchTile
, Image::StretchTile
, {
169 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
170 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
171 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
172 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
173 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
174 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
175 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
176 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
177 { true, false, FloatRect(0, 0, 100, 100), FloatRect(0, 0, 100, 100), 1, 1, Image::StretchTile
, Image::StretchTile
},
179 // Single border and fill
180 IntSize(100, 100), IntRect(0, 0, 100, 100), IntRectOutsets(0, 0, 10, 0), true,
181 LengthBox(Length(20, Percent
), Length(20, Percent
), Length(20, Percent
), Length(20, Percent
)), Image::StretchTile
, Image::StretchTile
, {
182 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
183 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
184 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
185 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
186 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
187 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
188 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
189 { true, false, FloatRect(0, 90, 100, 10), FloatRect(20, 80, 60, 20), 0.5, 0.5, Image::StretchTile
, Image::StretchTile
},
190 { true, false, FloatRect(0, 0, 100, 90), FloatRect(20, 20, 60, 60), 1.666667, 1.5, Image::StretchTile
, Image::StretchTile
},
192 // All borders, no fill
193 IntSize(100, 100), IntRect(0, 0, 100, 100), IntRectOutsets(10, 10, 10, 10), false,
194 LengthBox(Length(20, Percent
), Length(20, Percent
), Length(20, Percent
), Length(20, Percent
)), Image::StretchTile
, Image::StretchTile
, {
195 { true, true, FloatRect(0, 0, 10, 10), FloatRect(0, 0, 20, 20), 1, 1, Image::StretchTile
, Image::StretchTile
},
196 { true, true, FloatRect(0, 90, 10, 10), FloatRect(0, 80, 20, 20), 1, 1, Image::StretchTile
, Image::StretchTile
},
197 { true, false, FloatRect(0, 10, 10, 80), FloatRect(0, 20, 20, 60), 0.5, 0.5, Image::StretchTile
, Image::StretchTile
},
198 { true, true, FloatRect(90, 0, 10, 10), FloatRect(80, 0, 20, 20), 1, 1, Image::StretchTile
, Image::StretchTile
},
199 { true, true, FloatRect(90, 90, 10, 10), FloatRect(80, 80, 20, 20), 1, 1, Image::StretchTile
, Image::StretchTile
},
200 { true, false, FloatRect(90, 10, 10, 80), FloatRect(80, 20, 20, 60), 0.5, 0.5, Image::StretchTile
, Image::StretchTile
},
201 { true, false, FloatRect(10, 0, 80, 10), FloatRect(20, 0, 60, 20), 0.5, 0.5, Image::StretchTile
, Image::StretchTile
},
202 { true, false, FloatRect(10, 90, 80, 10), FloatRect(20, 80, 60, 20), 0.5, 0.5, Image::StretchTile
, Image::StretchTile
},
203 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::StretchTile
},
205 // Single border, no fill
206 IntSize(100, 100), IntRect(0, 0, 100, 100), IntRectOutsets(0, 0, 0, 10), false,
207 LengthBox(Length(20, Percent
), Length(20, Percent
), Length(20, Percent
), Length(20, Percent
)), Image::StretchTile
, Image::RoundTile
, {
208 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
209 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
210 { true, false, FloatRect(0, 0, 10, 100), FloatRect(0, 20, 20, 60), 0.5, 0.5, Image::StretchTile
, Image::RoundTile
},
211 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
212 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
213 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::RoundTile
},
214 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::RoundTile
},
215 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::RoundTile
},
216 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::RoundTile
},
218 // All borders but no slices, with fill (stretch horizontally, space vertically)
219 IntSize(100, 100), IntRect(0, 0, 100, 100), IntRectOutsets(10, 10, 10, 10), true,
220 LengthBox(Length(0, Fixed
), Length(0, Fixed
), Length(0, Fixed
), Length(0, Fixed
)), Image::StretchTile
, Image::SpaceTile
, {
221 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
222 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
223 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::SpaceTile
},
224 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
225 { false, true, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 1, 1, Image::StretchTile
, Image::StretchTile
},
226 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::SpaceTile
},
227 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::SpaceTile
},
228 { false, false, FloatRect(0, 0, 0, 0), FloatRect(0, 0, 0, 0), 0, 0, Image::StretchTile
, Image::SpaceTile
},
229 { true, false, FloatRect(10, 10, 80, 80), FloatRect(0, 0, 100, 100), 0.800000, 1, Image::StretchTile
, Image::SpaceTile
},
233 for (auto& testCase
: testCases
) {
234 NinePieceImage ninePiece
;
235 ninePiece
.setImage(generatedImage());
236 ninePiece
.setFill(testCase
.fill
);
237 ninePiece
.setImageSlices(testCase
.imageSlices
);
238 ninePiece
.setHorizontalRule((ENinePieceImageRule
)testCase
.horizontalRule
);
239 ninePiece
.setVerticalRule((ENinePieceImageRule
)testCase
.verticalRule
);
241 NinePieceImageGrid grid
= NinePieceImageGrid(ninePiece
, testCase
.imageSize
, testCase
.borderImageArea
, testCase
.borderWidths
);
242 for (NinePiece piece
= MinPiece
; piece
< MaxPiece
; ++piece
) {
243 NinePieceImageGrid::NinePieceDrawInfo drawInfo
= grid
.getNinePieceDrawInfo(piece
);
244 EXPECT_EQ(testCase
.pieces
[piece
].isDrawable
, drawInfo
.isDrawable
);
245 if (!testCase
.pieces
[piece
].isDrawable
)
248 EXPECT_EQ(testCase
.pieces
[piece
].destination
.x(), drawInfo
.destination
.x());
249 EXPECT_EQ(testCase
.pieces
[piece
].destination
.y(), drawInfo
.destination
.y());
250 EXPECT_EQ(testCase
.pieces
[piece
].destination
.width(), drawInfo
.destination
.width());
251 EXPECT_EQ(testCase
.pieces
[piece
].destination
.height(), drawInfo
.destination
.height());
252 EXPECT_EQ(testCase
.pieces
[piece
].source
.x(), drawInfo
.source
.x());
253 EXPECT_EQ(testCase
.pieces
[piece
].source
.y(), drawInfo
.source
.y());
254 EXPECT_EQ(testCase
.pieces
[piece
].source
.width(), drawInfo
.source
.width());
255 EXPECT_EQ(testCase
.pieces
[piece
].source
.height(), drawInfo
.source
.height());
257 if (testCase
.pieces
[piece
].isCornerPiece
)
260 EXPECT_FLOAT_EQ(testCase
.pieces
[piece
].tileScaleHorizontal
, drawInfo
.tileScale
.width());
261 EXPECT_FLOAT_EQ(testCase
.pieces
[piece
].tileScaleVertical
, drawInfo
.tileScale
.height());
262 EXPECT_EQ(testCase
.pieces
[piece
].horizontalRule
, drawInfo
.tileRule
.horizontal
);
263 EXPECT_EQ(testCase
.pieces
[piece
].verticalRule
, drawInfo
.tileRule
.vertical
);