blob: 9a080f32e26f9439e003c02bbad84abe3346d2b3 [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
103 float x(int i) const { return fX[i]; }
104 float y(int i) const { return fY[i]; }
105 float w(int i) const { return fW[i]; }
Michael Ludwigc96fc372019-01-08 15:46:15 -0500106 float iw(int i) const { return sk_ieee_float_divide(1.f, fW[i]); }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400107
Michael Ludwigb3461fa2019-04-30 11:50:55 -0400108 skvx::Vec<4, float> x4f() const { return skvx::Vec<4, float>::Load(fX); }
109 skvx::Vec<4, float> y4f() const { return skvx::Vec<4, float>::Load(fY); }
110 skvx::Vec<4, float> w4f() const { return skvx::Vec<4, float>::Load(fW); }
111 skvx::Vec<4, float> iw4f() const { return 1.f / this->w4f(); }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400112
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400113 Type quadType() const { return fType; }
Michael Ludwig41f395d2019-05-23 13:59:45 -0400114
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400115 bool hasPerspective() const { return fType == Type::kPerspective; }
Michael Ludwig1f7e4382018-10-19 09:36:57 -0400116
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400117 // True if anti-aliasing affects this quad. Only valid when quadType == kAxisAligned
Michael Ludwig1f7e4382018-10-19 09:36:57 -0400118 bool aaHasEffectOnRect() const;
119
Michael Ludwig61328202019-06-19 14:48:58 +0000120 // The non-const pointers are provided to support modifying a GrQuad in-place, but care must be
121 // taken to keep its quad type aligned with the geometric nature of the new coordinates. This is
122 // no different than using the constructors that accept a quad type.
123
124 float* xs() { return fX; }
125 float* ys() { return fY; }
126 float* ws() { return fW; }
127
128 void setQuadType(Type newType) { fType = newType; }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400129private:
Michael Ludwigc96fc372019-01-08 15:46:15 -0500130 template<typename T>
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400131 friend class GrQuadListBase; // for access to fX, fY, fW
Michael Ludwigc96fc372019-01-08 15:46:15 -0500132
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400133 float fX[4];
134 float fY[4];
135 float fW[4];
Michael Ludwig41f395d2019-05-23 13:59:45 -0400136
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400137 Type fType;
Michael Ludwigc96fc372019-01-08 15:46:15 -0500138};
139
joshualittae5b2c62015-08-19 08:48:41 -0700140#endif