1/*
2 * Copyright (C) 2014-2016 Apple Inc. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
14 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23 * THE POSSIBILITY OF SUCH DAMAGE.
24 */
25
26#include "config.h"
27
28#include <WebCore/FloatRect.h>
29#include <WebCore/IntPoint.h>
30#include <WebCore/IntRect.h>
31#include <WebCore/IntSize.h>
32
33#if USE(CG)
34#include <CoreGraphics/CoreGraphics.h>
35#endif
36
37#if PLATFORM(WIN)
38#include <d2d1.h>
39#endif
40
41namespace TestWebKitAPI {
42
43static void testGetAndSet(WebCore::IntRect rect)
44{
45 rect.setX(1);
46 EXPECT_EQ(1, rect.x());
47 rect.setY(2);
48 EXPECT_EQ(2, rect.y());
49 rect.setWidth(203);
50 EXPECT_EQ(203, rect.width());
51 rect.setHeight(73);
52 EXPECT_EQ(73, rect.height());
53}
54
55static void testEmptyRect(const WebCore::IntRect& rect)
56{
57 EXPECT_EQ(0, rect.x());
58 EXPECT_EQ(0, rect.y());
59 EXPECT_EQ(0, rect.width());
60 EXPECT_EQ(0, rect.height());
61 EXPECT_EQ(0, rect.maxX());
62 EXPECT_EQ(0, rect.maxY());
63 EXPECT_TRUE(rect.isEmpty());
64}
65
66TEST(IntRect, DefaultConstruction)
67{
68 WebCore::IntRect test;
69
70 testEmptyRect(test);
71
72 testGetAndSet(test);
73
74 auto location = test.location();
75 EXPECT_EQ(0, location.x());
76 EXPECT_EQ(0, location.y());
77
78 auto size = test.size();
79 EXPECT_EQ(0, size.width());
80 EXPECT_EQ(0, size.height());
81}
82
83TEST(IntRect, ValueConstruction)
84{
85 WebCore::IntRect test(10, 20, 100, 50);
86
87 EXPECT_EQ(10, test.x());
88 EXPECT_EQ(20, test.y());
89 EXPECT_EQ(100, test.width());
90 EXPECT_EQ(50, test.height());
91 EXPECT_EQ(110, test.maxX());
92 EXPECT_EQ(70, test.maxY());
93 EXPECT_FALSE(test.isEmpty());
94
95 auto location = test.location();
96 EXPECT_EQ(10, location.x());
97 EXPECT_EQ(20, location.y());
98
99 auto size = test.size();
100 EXPECT_EQ(100, size.width());
101 EXPECT_EQ(50, size.height());
102}
103
104TEST(IntRect, PointSizeConstruction)
105{
106 WebCore::IntPoint location(20, 30);
107 WebCore::IntSize size(100, 50);
108
109 WebCore::IntRect test(location, size);
110
111 EXPECT_EQ(20, test.x());
112 EXPECT_EQ(30, test.y());
113 EXPECT_EQ(100, test.width());
114 EXPECT_EQ(50, test.height());
115 EXPECT_EQ(120, test.maxX());
116 EXPECT_EQ(80, test.maxY());
117 EXPECT_FALSE(test.isEmpty());
118
119 auto location2 = test.location();
120 EXPECT_EQ(20, location2.x());
121 EXPECT_EQ(30, location2.y());
122
123 auto size2 = test.size();
124 EXPECT_EQ(100, size2.width());
125 EXPECT_EQ(50, size2.height());
126}
127
128TEST(IntRect, FloatRectConstruction)
129{
130 WebCore::FloatRect rect(20.0f, 30.0f, 150.0f, 300.0f);
131
132 WebCore::IntRect test(rect);
133
134 EXPECT_EQ(20, test.x());
135 EXPECT_EQ(30, test.y());
136 EXPECT_EQ(150, test.width());
137 EXPECT_EQ(300, test.height());
138 EXPECT_EQ(170, test.maxX());
139 EXPECT_EQ(330, test.maxY());
140 EXPECT_FALSE(test.isEmpty());
141
142 auto location = test.location();
143 EXPECT_EQ(20, location.x());
144 EXPECT_EQ(30, location.y());
145
146 auto size = test.size();
147 EXPECT_EQ(150, size.width());
148 EXPECT_EQ(300, size.height());
149}
150
151TEST(IntRect, SetLocationAndSize)
152{
153 WebCore::IntRect rect;
154
155 testEmptyRect(rect);
156
157 WebCore::IntPoint location(10, 20);
158
159 rect.setLocation(location);
160
161 EXPECT_EQ(10, rect.x());
162 EXPECT_EQ(20, rect.y());
163 EXPECT_EQ(0, rect.width());
164 EXPECT_EQ(0, rect.height());
165 EXPECT_EQ(10, rect.maxX());
166 EXPECT_EQ(20, rect.maxY());
167 EXPECT_TRUE(rect.isEmpty());
168
169 WebCore::IntSize size(100, 200);
170
171 rect.setSize(size);
172
173 EXPECT_EQ(10, rect.x());
174 EXPECT_EQ(20, rect.y());
175 EXPECT_EQ(100, rect.width());
176 EXPECT_EQ(200, rect.height());
177 EXPECT_EQ(110, rect.maxX());
178 EXPECT_EQ(220, rect.maxY());
179 EXPECT_FALSE(rect.isEmpty());
180}
181
182TEST(IntRect, Center)
183{
184 WebCore::IntRect rect(20, 40, 100, 200);
185
186 auto center = rect.center();
187
188 EXPECT_EQ(70, center.x());
189 EXPECT_EQ(140, center.y());
190}
191
192TEST(IntRect, Move)
193{
194 WebCore::IntRect rect(20, 30, 100, 200);
195
196 WebCore::IntSize delta(10, 20);
197
198 rect.move(delta);
199
200 EXPECT_EQ(30, rect.x());
201 EXPECT_EQ(50, rect.y());
202
203 WebCore::IntPoint deltaPoint(-20, -40);
204
205 rect.moveBy(deltaPoint);
206
207 EXPECT_EQ(10, rect.x());
208 EXPECT_EQ(10, rect.y());
209
210 rect.move(-10, 22);
211
212 EXPECT_EQ(0, rect.x());
213 EXPECT_EQ(32, rect.y());
214}
215
216TEST(IntRect, Expand)
217{
218 WebCore::IntRect rect(20, 30, 100, 200);
219
220 WebCore::IntSize size(100, 100);
221
222 rect.expand(size);
223
224 EXPECT_EQ(200, rect.width());
225 EXPECT_EQ(300, rect.height());
226
227 rect.expand(55, 22);
228
229 EXPECT_EQ(255, rect.width());
230 EXPECT_EQ(322, rect.height());
231
232 WebCore::IntSize size2(-10, -20);
233
234 rect.expand(size2);
235
236 EXPECT_EQ(245, rect.width());
237 EXPECT_EQ(302, rect.height());
238
239 rect.expand(-5, -2);
240
241 EXPECT_EQ(240, rect.width());
242 EXPECT_EQ(300, rect.height());
243}
244
245TEST(IntRect, Contract)
246{
247 WebCore::IntRect rect(20, 30, 100, 200);
248
249 WebCore::IntSize size(50, 100);
250
251 rect.contract(size);
252
253 EXPECT_EQ(50, rect.width());
254 EXPECT_EQ(100, rect.height());
255
256 rect.contract(25, 22);
257
258 EXPECT_EQ(25, rect.width());
259 EXPECT_EQ(78, rect.height());
260
261 WebCore::IntSize size2(-10, -20);
262
263 rect.contract(size2);
264
265 EXPECT_EQ(35, rect.width());
266 EXPECT_EQ(98, rect.height());
267
268 rect.contract(-5, -2);
269
270 EXPECT_EQ(40, rect.width());
271 EXPECT_EQ(100, rect.height());
272}
273
274TEST(IntRect, ShiftXEdge)
275{
276 WebCore::IntRect rect(20, 30, 100, 200);
277
278 rect.shiftXEdgeTo(77);
279
280 EXPECT_EQ(77, rect.x());
281 EXPECT_EQ(120, rect.maxX());
282 EXPECT_EQ(30, rect.y());
283 EXPECT_EQ(230, rect.maxY());
284 EXPECT_EQ(43, rect.width());
285 EXPECT_EQ(200, rect.height());
286
287 rect.shiftMaxXEdgeTo(200);
288
289 EXPECT_EQ(77, rect.x());
290 EXPECT_EQ(200, rect.maxX());
291 EXPECT_EQ(30, rect.y());
292 EXPECT_EQ(230, rect.maxY());
293 EXPECT_EQ(123, rect.width());
294 EXPECT_EQ(200, rect.height());
295}
296
297TEST(IntRect, ShiftYEdge)
298{
299 WebCore::IntRect rect(20, 30, 100, 200);
300
301 rect.shiftYEdgeTo(59.0f);
302
303 EXPECT_EQ(20, rect.x());
304 EXPECT_EQ(120, rect.maxX());
305 EXPECT_EQ(59, rect.y());
306 EXPECT_EQ(230, rect.maxY());
307 EXPECT_EQ(100, rect.width());
308 EXPECT_EQ(171, rect.height());
309
310 rect.shiftMaxYEdgeTo(270.0f);
311
312 EXPECT_EQ(20, rect.x());
313 EXPECT_EQ(120, rect.maxX());
314 EXPECT_EQ(59, rect.y());
315 EXPECT_EQ(270, rect.maxY());
316 EXPECT_EQ(100, rect.width());
317 EXPECT_EQ(211, rect.height());
318}
319
320TEST(IntRect, Inflate)
321{
322 WebCore::IntRect rect(20, 30, 100, 200);
323
324 rect.inflateX(5);
325
326 EXPECT_EQ(15, rect.x());
327 EXPECT_EQ(125, rect.maxX());
328
329 rect.inflateY(4);
330
331 EXPECT_EQ(26, rect.y());
332 EXPECT_EQ(234, rect.maxY());
333
334 rect.inflate(10);
335
336 EXPECT_EQ(5, rect.x());
337 EXPECT_EQ(135, rect.maxX());
338 EXPECT_EQ(16, rect.y());
339 EXPECT_EQ(244, rect.maxY());
340}
341
342TEST(IntRect, Corners)
343{
344 WebCore::IntRect rect(20, 30, 100, 200);
345
346 WebCore::FloatPoint topLeft = rect.minXMinYCorner();
347 EXPECT_EQ(20, topLeft.x());
348 EXPECT_EQ(30, topLeft.y());
349
350 WebCore::FloatPoint topRight = rect.maxXMinYCorner();
351 EXPECT_EQ(120, topRight.x());
352 EXPECT_EQ(30, topRight.y());
353
354 WebCore::FloatPoint bottomLeft = rect.minXMaxYCorner();
355 EXPECT_EQ(20, bottomLeft.x());
356 EXPECT_EQ(230, bottomLeft.y());
357
358 WebCore::FloatPoint bottomRight = rect.maxXMaxYCorner();
359 EXPECT_EQ(120, bottomRight.x());
360 EXPECT_EQ(230, bottomRight.y());
361}
362
363TEST(IntRect, Contains)
364{
365 WebCore::IntRect rect(20, 30, 100, 200);
366
367 WebCore::IntRect contained(30, 40, 50, 100);
368
369 ASSERT_TRUE(rect.contains(contained));
370
371 WebCore::IntRect outside(120, 230, 50, 100);
372
373 ASSERT_FALSE(rect.contains(outside));
374
375 WebCore::IntRect intersects(10, 20, 90, 180);
376
377 ASSERT_FALSE(rect.contains(intersects));
378
379 WebCore::IntPoint pointInside(60, 70);
380
381 ASSERT_TRUE(rect.contains(pointInside));
382
383 WebCore::IntPoint pointOutside(160, 270);
384
385 ASSERT_FALSE(rect.contains(pointOutside));
386
387 WebCore::IntPoint pointOnLine(20, 30);
388
389 ASSERT_TRUE(rect.contains(pointOnLine));
390
391 ASSERT_TRUE(rect.contains(60, 70));
392 ASSERT_FALSE(rect.contains(160, 270));
393}
394
395TEST(IntRect, Intersects)
396{
397 WebCore::IntRect rect(20, 30, 100, 200);
398
399 WebCore::IntRect contained(30, 40, 50, 100);
400
401 ASSERT_TRUE(rect.intersects(contained));
402
403 WebCore::IntRect outside(120, 230, 50, 100);
404
405 ASSERT_FALSE(rect.intersects(outside));
406
407 WebCore::IntRect intersects(10, 20, 90, 180);
408
409 ASSERT_TRUE(rect.intersects(intersects));
410}
411
412static void testIntersectResult(const WebCore::IntRect& rect)
413{
414 EXPECT_EQ(70, rect.x());
415 EXPECT_EQ(120, rect.maxX());
416 EXPECT_EQ(80, rect.y());
417 EXPECT_EQ(230, rect.maxY());
418}
419
420TEST(IntRect, Intersect)
421{
422 WebCore::IntRect rectA(20, 30, 100, 200);
423 WebCore::IntRect rectB(70, 80, 100, 200);
424
425 rectA.intersect(rectB);
426
427 testIntersectResult(rectA);
428
429 WebCore::IntRect rectC(20, 30, 100, 200);
430
431 auto intersected = WebCore::intersection(rectC, rectB);
432
433 testIntersectResult(intersected);
434}
435
436static void testUnitedRects(const WebCore::IntRect& united)
437{
438 EXPECT_EQ(20, united.x());
439 EXPECT_EQ(170, united.maxX());
440 EXPECT_EQ(30, united.y());
441 EXPECT_EQ(280, united.maxY());
442}
443
444TEST(IntRect, Unite)
445{
446 WebCore::IntRect rectA(20, 30, 100, 200);
447 WebCore::IntRect rectB(70, 80, 100, 200);
448
449 rectA.unite(rectB);
450
451 testUnitedRects(rectA);
452
453 WebCore::IntRect rectC(20, 30, 100, 200);
454
455 auto united = WebCore::unionRect(rectC, rectB);
456
457 testUnitedRects(united);
458}
459
460TEST(IntRect, Scale)
461{
462 WebCore::IntRect rect(20, 30, 100, 200);
463
464 rect.scale(2.0f);
465
466 EXPECT_EQ(40, rect.x());
467 EXPECT_EQ(240, rect.maxX());
468 EXPECT_EQ(60, rect.y());
469 EXPECT_EQ(460, rect.maxY());
470}
471
472TEST(IntRect, Transpose)
473{
474 WebCore::IntRect rect(20, 30, 100, 200);
475
476 auto transposed = rect.transposedRect();
477
478 EXPECT_EQ(30, transposed.x());
479 EXPECT_EQ(230, transposed.maxX());
480 EXPECT_EQ(20, transposed.y());
481 EXPECT_EQ(120, transposed.maxY());
482}
483
484#if USE(CG) || PLATFORM(WIN)
485static void checkCastRect(const WebCore::IntRect& rect)
486{
487 EXPECT_EQ(10, rect.x());
488 EXPECT_EQ(40, rect.maxX());
489 EXPECT_EQ(20, rect.y());
490 EXPECT_EQ(60, rect.maxY());
491 EXPECT_EQ(30, rect.width());
492 EXPECT_EQ(40, rect.height());
493}
494#endif
495
496TEST(IntRect, Casting)
497{
498 WebCore::IntRect rect(10, 20, 30, 40);
499
500#if USE(CG)
501 CGRect cgRect = CGRectMake(10.0, 20.0, 30.0, 40.0);
502
503 WebCore::IntRect rectFromCGRect(cgRect);
504
505 checkCastRect(rectFromCGRect);
506#endif
507
508#if PLATFORM(WIN)
509 RECT gdiRect = rect;
510
511 EXPECT_EQ(10, gdiRect.left);
512 EXPECT_EQ(20, gdiRect.top);
513 EXPECT_EQ(40, gdiRect.right);
514 EXPECT_EQ(60, gdiRect.bottom);
515
516 WebCore::IntRect rectFromGDIRect(gdiRect);
517
518 checkCastRect(rectFromGDIRect);
519
520 D2D1_RECT_U d2dRectU = rect;
521
522 EXPECT_EQ(10, d2dRectU.left);
523 EXPECT_EQ(20, d2dRectU.top);
524 EXPECT_EQ(40, d2dRectU.right);
525 EXPECT_EQ(60, d2dRectU.bottom);
526
527 WebCore::IntRect rectFromD2DRectU(d2dRectU);
528
529 checkCastRect(rectFromD2DRectU);
530
531 D2D1_RECT_F d2dRectF = rect;
532
533 EXPECT_FLOAT_EQ(10.0f, d2dRectF.left);
534 EXPECT_FLOAT_EQ(20.0f, d2dRectF.top);
535 EXPECT_FLOAT_EQ(40.0f, d2dRectF.right);
536 EXPECT_FLOAT_EQ(60.0f, d2dRectF.bottom);
537
538 WebCore::IntRect rectFromD2DRectF(d2dRectF);
539
540 checkCastRect(rectFromD2DRectF);
541#endif
542}
543
544static void checkSubtractionResult1(const WebCore::IntRect& rect)
545{
546 EXPECT_EQ(-10, rect.x());
547 EXPECT_EQ(90, rect.maxX());
548 EXPECT_EQ(-10, rect.y());
549 EXPECT_EQ(90, rect.maxY());
550 EXPECT_EQ(100, rect.width());
551 EXPECT_EQ(100, rect.height());
552}
553
554static void checkSubtractionResult2(const WebCore::IntRect& rect)
555{
556 EXPECT_EQ(-40, rect.x());
557 EXPECT_EQ(60, rect.maxX());
558 EXPECT_EQ(-50, rect.y());
559 EXPECT_EQ(50, rect.maxY());
560 EXPECT_EQ(100, rect.width());
561 EXPECT_EQ(100, rect.height());
562}
563
564TEST(IntRect, Subtraction)
565{
566 WebCore::IntRect rect(10, 20, 100, 100);
567 WebCore::IntPoint rightSide(20, 30);
568
569 rect -= rightSide;
570
571 checkSubtractionResult1(rect);
572
573 auto rect2 = rect - WebCore::IntPoint(30, 40);
574 checkSubtractionResult2(rect2);
575}
576
577TEST(IntRect, Equality)
578{
579 WebCore::IntRect rect(10, 20, 100, 100);
580 WebCore::IntRect rect2(10, 20, 100, 100);
581 WebCore::IntRect rightSide(110, 20, 20, 100);
582
583 ASSERT_TRUE(rect == rect2);
584 ASSERT_FALSE(rect != rect2);
585 ASSERT_TRUE(rect != rightSide);
586 ASSERT_FALSE(rect == rightSide);
587}
588
589#if USE(CG)
590static void checkEnclosingIntRect(const WebCore::IntRect& rect)
591{
592 EXPECT_EQ(10, rect.x());
593 EXPECT_EQ(41, rect.maxX());
594 EXPECT_EQ(21, rect.y());
595 EXPECT_EQ(62, rect.maxY());
596 EXPECT_EQ(31, rect.width());
597 EXPECT_EQ(41, rect.height());
598}
599#endif
600
601TEST(IntRect, EnclosingIntRect)
602{
603#if USE(CG)
604 CGRect cgRect = CGRectMake(10.5, 21.3, 30.1, 40.0);
605
606 WebCore::IntRect enclosingCG = WebCore::enclosingIntRect(cgRect);
607
608 checkEnclosingIntRect(enclosingCG);
609#endif
610}
611
612TEST(IntRect, AreaAndDistances)
613{
614 WebCore::IntRect rect(10, 20, 100, 100);
615
616 EXPECT_EQ(10000U, rect.area().unsafeGet());
617}
618
619}
620