blob: 9131ff64665dcd3a65d74e9cc6cf3a37ddb494f1 [file] [log] [blame]
joshualittae5b2c62015-08-19 08:48:41 -07001/*
2 * Copyright 2015 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef GrQuad_DEFINED
9#define GrQuad_DEFINED
10
Mike Kleinc0bd9f92019-04-23 12:05:21 -050011#include "include/core/SkMatrix.h"
12#include "include/core/SkPoint.h"
13#include "include/core/SkPoint3.h"
Michael Ludwigb3461fa2019-04-30 11:50:55 -040014#include "include/private/SkVx.h"
joshualittae5b2c62015-08-19 08:48:41 -070015
16/**
Brian Salomon57caa662017-10-18 12:21:05 +000017 * GrQuad is a collection of 4 points which can be used to represent an arbitrary quadrilateral. The
18 * points make a triangle strip with CCW triangles (top-left, bottom-left, top-right, bottom-right).
joshualittae5b2c62015-08-19 08:48:41 -070019 */
20class GrQuad {
21public:
Michael Ludwigde4c58c2019-06-04 09:12:59 -040022 // Quadrilaterals can be classified in several useful ways that assist AA tessellation and other
23 // analysis when drawing, in particular, knowing if it was originally a rectangle transformed by
24 // certain types of matrices:
25 enum class Type {
26 // The 4 points remain an axis-aligned rectangle; their logical indices may not respect
27 // TL, BL, TR, BR ordering if the transform was a 90 degre rotation or mirror.
28 kAxisAligned,
29 // The 4 points represent a rectangle subjected to a rotation, its corners are right angles.
30 kRectilinear,
31 // Arbitrary 2D quadrilateral; may have been a rectangle transformed with skew or some
32 // clipped polygon. Its w coordinates will all be 1.
33 kGeneral,
34 // Even more general-purpose than kGeneral, this allows the w coordinates to be non-unity.
35 kPerspective,
36 kLast = kPerspective
37 };
38 static const int kTypeCount = static_cast<int>(Type::kLast) + 1;
joshualitt8cce8f12015-08-26 06:23:39 -070039
Michael Ludwigde4c58c2019-06-04 09:12:59 -040040 GrQuad() = default;
Brian Salomona33b67c2018-05-17 10:42:14 -040041
42 explicit GrQuad(const SkRect& rect)
43 : fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
Michael Ludwig41f395d2019-05-23 13:59:45 -040044 , fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom}
Michael Ludwig41f395d2019-05-23 13:59:45 -040045 , fW{1.f, 1.f, 1.f, 1.f}
Michael Ludwigde4c58c2019-06-04 09:12:59 -040046 , fType(Type::kAxisAligned) {}
Michael Ludwige9c57d32019-02-13 13:39:39 -050047
Michael Ludwigde4c58c2019-06-04 09:12:59 -040048 GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, Type type)
Michael Ludwig41f395d2019-05-23 13:59:45 -040049 : fType(type) {
Michael Ludwigde4c58c2019-06-04 09:12:59 -040050 SkASSERT(type != Type::kPerspective);
Michael Ludwige9c57d32019-02-13 13:39:39 -050051 xs.store(fX);
52 ys.store(fY);
53 fW[0] = fW[1] = fW[2] = fW[3] = 1.f;
54 }
Michael Ludwig009b92e2019-02-15 16:03:53 -050055
Michael Ludwigde4c58c2019-06-04 09:12:59 -040056 GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
57 const skvx::Vec<4, float>& ws, Type type)
Michael Ludwig41f395d2019-05-23 13:59:45 -040058 : fType(type) {
Michael Ludwige9c57d32019-02-13 13:39:39 -050059 xs.store(fX);
60 ys.store(fY);
61 ws.store(fW);
62 }
63
Michael Ludwigde4c58c2019-06-04 09:12:59 -040064 // Copy 4 values from each of the arrays into the quad's components
65 GrQuad(const float xs[4], const float ys[4], const float ws[4], Type type)
66 : fType(type) {
67 memcpy(fX, xs, 4 * sizeof(float));
68 memcpy(fY, ys, 4 * sizeof(float));
69 memcpy(fW, ws, 4 * sizeof(float));
70 }
Brian Salomonbe3c1d22018-05-21 12:54:39 -040071
Michael Ludwigde4c58c2019-06-04 09:12:59 -040072 static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);
73
74 // Creates a GrQuad from the quadrilateral 'pts', transformed by the matrix. The input
Michael Ludwig009b92e2019-02-15 16:03:53 -050075 // points array is arranged as per SkRect::toQuad (top-left, top-right, bottom-right,
76 // bottom-left). The returned instance's point order will still be CCW tri-strip order.
Michael Ludwigde4c58c2019-06-04 09:12:59 -040077 static GrQuad MakeFromSkQuad(const SkPoint pts[4], const SkMatrix&);
Michael Ludwig009b92e2019-02-15 16:03:53 -050078
Michael Ludwigde4c58c2019-06-04 09:12:59 -040079 GrQuad& operator=(const GrQuad&) = default;
Brian Salomonbe3c1d22018-05-21 12:54:39 -040080
Michael Ludwigde4c58c2019-06-04 09:12:59 -040081 SkPoint3 point3(int i) const { return {fX[i], fY[i], fW[i]}; }
82
83 SkPoint point(int i) const {
84 if (fType == Type::kPerspective) {
85 return {fX[i] / fW[i], fY[i] / fW[i]};
86 } else {
87 return {fX[i], fY[i]};
88 }
89 }
Brian Salomonbe3c1d22018-05-21 12:54:39 -040090
Michael Ludwig41f395d2019-05-23 13:59:45 -040091 SkRect bounds() const {
Michael Ludwigb3461fa2019-04-30 11:50:55 -040092 auto x = this->x4f();
93 auto y = this->y4f();
Michael Ludwigde4c58c2019-06-04 09:12:59 -040094 if (fType == Type::kPerspective) {
Michael Ludwigb3461fa2019-04-30 11:50:55 -040095 auto iw = this->iw4f();
Michael Ludwigc96fc372019-01-08 15:46:15 -050096 x *= iw;
97 y *= iw;
98 }
99
Michael Ludwigb3461fa2019-04-30 11:50:55 -0400100 return {min(x), min(y), max(x), max(y)};
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400101 }
102
Michael Ludwiged71b7e2019-06-21 13:47:02 -0400103 bool isFinite() const {
104 // If any coordinate is infinity or NaN, then multiplying it with 0 will make accum NaN
105 float accum = 0;
106 for (int i = 0; i < 4; ++i) {
107 accum *= fX[i];
108 accum *= fY[i];
109 accum *= fW[i];
110 }
111 SkASSERT(0 == accum || SkScalarIsNaN(accum));
112 return !SkScalarIsNaN(accum);
113 }
114
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400115 float x(int i) const { return fX[i]; }
116 float y(int i) const { return fY[i]; }
117 float w(int i) const { return fW[i]; }
Michael Ludwigc96fc372019-01-08 15:46:15 -0500118 float iw(int i) const { return sk_ieee_float_divide(1.f, fW[i]); }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400119
Michael Ludwigb3461fa2019-04-30 11:50:55 -0400120 skvx::Vec<4, float> x4f() const { return skvx::Vec<4, float>::Load(fX); }
121 skvx::Vec<4, float> y4f() const { return skvx::Vec<4, float>::Load(fY); }
122 skvx::Vec<4, float> w4f() const { return skvx::Vec<4, float>::Load(fW); }
123 skvx::Vec<4, float> iw4f() const { return 1.f / this->w4f(); }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400124
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400125 Type quadType() const { return fType; }
Michael Ludwig41f395d2019-05-23 13:59:45 -0400126
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400127 bool hasPerspective() const { return fType == Type::kPerspective; }
Michael Ludwig1f7e4382018-10-19 09:36:57 -0400128
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400129 // True if anti-aliasing affects this quad. Only valid when quadType == kAxisAligned
Michael Ludwig1f7e4382018-10-19 09:36:57 -0400130 bool aaHasEffectOnRect() const;
131
Michael Ludwig22429f92019-06-27 10:44:48 -0400132 // True if this quad is axis-aligned and still has its top-left corner at v0. Equivalently,
133 // quad == GrQuad(quad->bounds()). Axis-aligned quads with flips and rotations may exactly
134 // fill their bounds, but their vertex order will not match TL BL TR BR anymore.
135 bool asRect(SkRect* rect) const;
136
Michael Ludwig61328202019-06-19 14:48:58 +0000137 // The non-const pointers are provided to support modifying a GrQuad in-place, but care must be
138 // taken to keep its quad type aligned with the geometric nature of the new coordinates. This is
139 // no different than using the constructors that accept a quad type.
Michael Ludwig425eb452019-06-27 10:13:27 -0400140 const float* xs() const { return fX; }
Michael Ludwig61328202019-06-19 14:48:58 +0000141 float* xs() { return fX; }
Michael Ludwig425eb452019-06-27 10:13:27 -0400142 const float* ys() const { return fY; }
Michael Ludwig61328202019-06-19 14:48:58 +0000143 float* ys() { return fY; }
Michael Ludwig425eb452019-06-27 10:13:27 -0400144 const float* ws() const { return fW; }
Michael Ludwig61328202019-06-19 14:48:58 +0000145 float* ws() { return fW; }
146
147 void setQuadType(Type newType) { fType = newType; }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400148private:
Michael Ludwigc96fc372019-01-08 15:46:15 -0500149 template<typename T>
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400150 friend class GrQuadListBase; // for access to fX, fY, fW
Michael Ludwigc96fc372019-01-08 15:46:15 -0500151
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400152 float fX[4];
153 float fY[4];
154 float fW[4];
Michael Ludwig41f395d2019-05-23 13:59:45 -0400155
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400156 Type fType;
Michael Ludwigc96fc372019-01-08 15:46:15 -0500157};
158
joshualittae5b2c62015-08-19 08:48:41 -0700159#endif