15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/geometry/quad_f.h"
85d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "ui/gfx/geometry/rect_f.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace gfx {
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, Construction) {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify constructors.
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a(1, 1);
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b(2, 1);
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c(2, 2);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d(1, 2);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF e;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q1;
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q2(e, e, e, e);
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q3(a, b, c, d);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q4(BoundingRect(a, c));
23116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q1, q2);
24116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3, q4);
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify getters.
27116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p1(), a);
28116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p2(), b);
29116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p3(), c);
30116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p4(), d);
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify setters.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q3.set_p1(b);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q3.set_p2(c);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q3.set_p3(d);
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q3.set_p4(a);
37116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p1(), b);
38116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p2(), c);
39116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p3(), d);
40116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3.p4(), a);
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify operator=(Rect)
43116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_NE(q1, q4);
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q1 = BoundingRect(a, c);
45116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q1, q4);
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Verify operator=(Quad)
48116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_NE(q1, q3);
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q1 = q3;
50116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q1, q3);
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, AddingVectors) {
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a(1, 1);
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b(2, 1);
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c(2, 2);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d(1, 2);
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Vector2dF v(3.5f, -2.5f);
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q1(a, b, c, d);
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF added = q1 + v;
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q1 += v;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF expected1(PointF(4.5f, -1.5f),
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PointF(5.5f, -1.5f),
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PointF(5.5f, -0.5f),
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PointF(4.5f, -0.5f));
67116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(expected1, added);
68116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(expected1, q1);
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q2(a, b, c, d);
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF subtracted = q2 - v;
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q2 -= v;
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF expected2(PointF(-2.5f, 3.5f),
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PointF(-1.5f, 3.5f),
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PointF(-1.5f, 4.5f),
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                  PointF(-2.5f, 4.5f));
77116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(expected2, subtracted);
78116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(expected2, q2);
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q3(a, b, c, d);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q3 += v;
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q3 -= v;
83116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(QuadF(a, b, c, d), q3);
84116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q3, (q3 + v - v));
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, IsRectilinear) {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a(1, 1);
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b(2, 1);
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c(2, 2);
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d(1, 2);
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Vector2dF v(3.5f, -2.5f);
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF().IsRectilinear());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).IsRectilinear());
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE((QuadF(a, b, c, d) + v).IsRectilinear());
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float epsilon = std::numeric_limits<float>::epsilon();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a2(1 + epsilon / 2, 1 + epsilon / 2);
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b2(2 + epsilon / 2, 1 + epsilon / 2);
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c2(2 + epsilon / 2, 2 + epsilon / 2);
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d2(1 + epsilon / 2, 2 + epsilon / 2);
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a2, b, c, d).IsRectilinear());
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE((QuadF(a2, b, c, d) + v).IsRectilinear());
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b2, c, d).IsRectilinear());
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE((QuadF(a, b2, c, d) + v).IsRectilinear());
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c2, d).IsRectilinear());
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE((QuadF(a, b, c2, d) + v).IsRectilinear());
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d2).IsRectilinear());
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE((QuadF(a, b, c, d2) + v).IsRectilinear());
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  struct {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PointF a_off, b_off, c_off, d_off;
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } tests[] = {
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1, 1.00001f),
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2, 1.00001f),
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2, 2.00001f),
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1, 2.00001f)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.00001f, 1),
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2.00001f, 1),
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2.00001f, 2),
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.00001f, 2)
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.00001f, 1.00001f),
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2.00001f, 1.00001f),
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2.00001f, 2.00001f),
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.00001f, 2.00001f)
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1, 0.99999f),
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2, 0.99999f),
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(2, 1.99999f),
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1, 1.99999f)
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(0.99999f, 1),
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.99999f, 1),
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.99999f, 2),
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(0.99999f, 2)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    },
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(0.99999f, 0.99999f),
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.99999f, 0.99999f),
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(1.99999f, 1.99999f),
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      PointF(0.99999f, 1.99999f)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  };
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ARRAYSIZE_UNSAFE(tests); ++i) {
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PointF a_off = tests[i].a_off;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PointF b_off = tests[i].b_off;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PointF c_off = tests[i].c_off;
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    PointF d_off = tests[i].d_off;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a_off, b, c, d).IsRectilinear());
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a_off, b, c, d) + v).IsRectilinear());
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a, b_off, c, d).IsRectilinear());
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a, b_off, c, d) + v).IsRectilinear());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a, b, c_off, d).IsRectilinear());
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a, b, c_off, d) + v).IsRectilinear());
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a, b, c, d_off).IsRectilinear());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a, b, c, d_off) + v).IsRectilinear());
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a_off, b, c_off, d).IsRectilinear());
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a_off, b, c_off, d) + v).IsRectilinear());
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a, b_off, c, d_off).IsRectilinear());
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a, b_off, c, d_off) + v).IsRectilinear());
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a, b_off, c_off, d_off).IsRectilinear());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a, b_off, c_off, d_off) + v).IsRectilinear());
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a_off, b, c_off, d_off).IsRectilinear());
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a_off, b, c_off, d_off) + v).IsRectilinear());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a_off, b_off, c, d_off).IsRectilinear());
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a_off, b_off, c, d_off) + v).IsRectilinear());
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE(QuadF(a_off, b_off, c_off, d).IsRectilinear());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_FALSE((QuadF(a_off, b_off, c_off, d) + v).IsRectilinear());
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE(QuadF(a_off, b_off, c_off, d_off).IsRectilinear());
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    EXPECT_TRUE((QuadF(a_off, b_off, c_off, d_off) + v).IsRectilinear());
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, IsCounterClockwise) {
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a1(1, 1);
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b1(2, 1);
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c1(2, 2);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d1(1, 2);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a1, b1, c1, d1).IsCounterClockwise());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(b1, c1, d1, a1).IsCounterClockwise());
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a1, d1, c1, b1).IsCounterClockwise());
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(c1, b1, a1, d1).IsCounterClockwise());
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Slightly more complicated quads should work just as easily.
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a2(1.3f, 1.4f);
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b2(-0.7f, 4.9f);
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c2(1.8f, 6.2f);
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d2(2.1f, 1.6f);
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a2, b2, c2, d2).IsCounterClockwise());
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(b2, c2, d2, a2).IsCounterClockwise());
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a2, d2, c2, b2).IsCounterClockwise());
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(c2, b2, a2, d2).IsCounterClockwise());
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Quads with 3 collinear points should work correctly, too.
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a3(0, 0);
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b3(1, 0);
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c3(2, 0);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d3(1, 1);
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a3, b3, c3, d3).IsCounterClockwise());
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(b3, c3, d3, a3).IsCounterClockwise());
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a3, d3, c3, b3).IsCounterClockwise());
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The next expectation in particular would fail for an implementation
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // that incorrectly uses only a cross product of the first 3 vertices.
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(c3, b3, a3, d3).IsCounterClockwise());
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Non-convex quads should work correctly, too.
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a4(0, 0);
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b4(1, 1);
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c4(2, 0);
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d4(1, 3);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a4, b4, c4, d4).IsCounterClockwise());
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(b4, c4, d4, a4).IsCounterClockwise());
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a4, d4, c4, b4).IsCounterClockwise());
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(c4, b4, a4, d4).IsCounterClockwise());
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // A quad with huge coordinates should not fail this check due to
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // single-precision overflow.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a5(1e30f, 1e30f);
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b5(1e35f, 1e30f);
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c5(1e35f, 1e35f);
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d5(1e30f, 1e35f);
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a5, b5, c5, d5).IsCounterClockwise());
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(b5, c5, d5, a5).IsCounterClockwise());
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a5, d5, c5, b5).IsCounterClockwise());
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(c5, b5, a5, d5).IsCounterClockwise());
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, BoundingBox) {
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  RectF r(3.2f, 5.4f, 7.007f, 12.01f);
240116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(r, QuadF(r).BoundingBox());
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a(1.3f, 1.4f);
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b(-0.7f, 4.9f);
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c(1.8f, 6.2f);
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d(2.1f, 1.6f);
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float left = -0.7f;
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float top = 1.4f;
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float right = 2.1f;
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  float bottom = 6.2f;
250116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(RectF(left, top, right - left, bottom - top),
251116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch            QuadF(a, b, c, d).BoundingBox());
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, ContainsPoint) {
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a(1.3f, 1.4f);
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b(-0.8f, 4.4f);
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c(1.8f, 6.1f);
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d(2.1f, 1.6f);
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Vector2dF epsilon_x(2 * std::numeric_limits<float>::epsilon(), 0);
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Vector2dF epsilon_y(0, 2 * std::numeric_limits<float>::epsilon());
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Vector2dF ac_center = c - a;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ac_center.Scale(0.5f);
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Vector2dF bd_center = d - b;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bd_center.Scale(0.5f);
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(a + ac_center));
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(b + bd_center));
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(c - ac_center));
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(d - bd_center));
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - ac_center));
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - bd_center));
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + ac_center));
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + bd_center));
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(a));
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - epsilon_x));
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(a - epsilon_y));
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(a + epsilon_x));
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(a + epsilon_y));
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(b));
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - epsilon_x));
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(b - epsilon_y));
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(b + epsilon_x));
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(b + epsilon_y));
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(c));
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(c - epsilon_x));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(c - epsilon_y));
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + epsilon_x));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(c + epsilon_y));
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(d));
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(a, b, c, d).Contains(d - epsilon_x));
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(d - epsilon_y));
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + epsilon_x));
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(a, b, c, d).Contains(d + epsilon_y));
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Test a simple square.
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF s1(-1, -1);
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF s2(1, -1);
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF s3(1, 1);
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF s4(-1, 1);
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Top edge.
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, -1.0f)));
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.0f)));
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0.0f, -1.0f)));
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.0f)));
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, -1.0f)));
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Bottom edge.
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, 1.0f)));
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.0f)));
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0.0f, 1.0f)));
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.0f)));
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, 1.0f)));
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Left edge.
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.1f)));
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, -1.0f)));
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 0.0f)));
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.0f)));
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.0f, 1.1f)));
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Right edge.
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.1f)));
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, -1.0f)));
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 0.0f)));
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.0f)));
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.0f, 1.1f)));
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Centered inside.
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(QuadF(s1, s2, s3, s4).Contains(PointF(0, 0)));
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Centered outside.
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(-1.1f, 0)));
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(1.1f, 0)));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(0, -1.1f)));
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(QuadF(s1, s2, s3, s4).Contains(PointF(0, 1.1f)));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(QuadTest, Scale) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a(1.3f, 1.4f);
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b(-0.8f, 4.4f);
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c(1.8f, 6.1f);
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d(2.1f, 1.6f);
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q1(a, b, c, d);
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q1.Scale(1.5f);
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF a_scaled = ScalePoint(a, 1.5f);
3485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF b_scaled = ScalePoint(b, 1.5f);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF c_scaled = ScalePoint(c, 1.5f);
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  PointF d_scaled = ScalePoint(d, 1.5f);
351116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q1, QuadF(a_scaled, b_scaled, c_scaled, d_scaled));
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  QuadF q2;
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  q2.Scale(1.5f);
355116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  EXPECT_EQ(q2, q2);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace gfx
359