blob: 27d98cb4c975b978783bcf9e20faa778c1125a2b [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
Michael Ludwig6bee7762018-10-19 09:50:36 -040016enum class GrAAType : unsigned;
17enum class GrQuadAAFlags;
18
joshualittae5b2c62015-08-19 08:48:41 -070019/**
Brian Salomon57caa662017-10-18 12:21:05 +000020 * GrQuad is a collection of 4 points which can be used to represent an arbitrary quadrilateral. The
21 * points make a triangle strip with CCW triangles (top-left, bottom-left, top-right, bottom-right).
joshualittae5b2c62015-08-19 08:48:41 -070022 */
23class GrQuad {
24public:
Michael Ludwigde4c58c2019-06-04 09:12:59 -040025 // Quadrilaterals can be classified in several useful ways that assist AA tessellation and other
26 // analysis when drawing, in particular, knowing if it was originally a rectangle transformed by
27 // certain types of matrices:
28 enum class Type {
29 // The 4 points remain an axis-aligned rectangle; their logical indices may not respect
30 // TL, BL, TR, BR ordering if the transform was a 90 degre rotation or mirror.
31 kAxisAligned,
32 // The 4 points represent a rectangle subjected to a rotation, its corners are right angles.
33 kRectilinear,
34 // Arbitrary 2D quadrilateral; may have been a rectangle transformed with skew or some
35 // clipped polygon. Its w coordinates will all be 1.
36 kGeneral,
37 // Even more general-purpose than kGeneral, this allows the w coordinates to be non-unity.
38 kPerspective,
39 kLast = kPerspective
40 };
41 static const int kTypeCount = static_cast<int>(Type::kLast) + 1;
joshualitt8cce8f12015-08-26 06:23:39 -070042
Michael Ludwigde4c58c2019-06-04 09:12:59 -040043 GrQuad() = default;
Brian Salomona33b67c2018-05-17 10:42:14 -040044
45 explicit GrQuad(const SkRect& rect)
46 : fX{rect.fLeft, rect.fLeft, rect.fRight, rect.fRight}
Michael Ludwig41f395d2019-05-23 13:59:45 -040047 , fY{rect.fTop, rect.fBottom, rect.fTop, rect.fBottom}
Michael Ludwig41f395d2019-05-23 13:59:45 -040048 , fW{1.f, 1.f, 1.f, 1.f}
Michael Ludwigde4c58c2019-06-04 09:12:59 -040049 , fType(Type::kAxisAligned) {}
Michael Ludwige9c57d32019-02-13 13:39:39 -050050
Michael Ludwigde4c58c2019-06-04 09:12:59 -040051 GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys, Type type)
Michael Ludwig41f395d2019-05-23 13:59:45 -040052 : fType(type) {
Michael Ludwigde4c58c2019-06-04 09:12:59 -040053 SkASSERT(type != Type::kPerspective);
Michael Ludwige9c57d32019-02-13 13:39:39 -050054 xs.store(fX);
55 ys.store(fY);
56 fW[0] = fW[1] = fW[2] = fW[3] = 1.f;
57 }
Michael Ludwig009b92e2019-02-15 16:03:53 -050058
Michael Ludwigde4c58c2019-06-04 09:12:59 -040059 GrQuad(const skvx::Vec<4, float>& xs, const skvx::Vec<4, float>& ys,
60 const skvx::Vec<4, float>& ws, Type type)
Michael Ludwig41f395d2019-05-23 13:59:45 -040061 : fType(type) {
Michael Ludwige9c57d32019-02-13 13:39:39 -050062 xs.store(fX);
63 ys.store(fY);
64 ws.store(fW);
65 }
66
Michael Ludwigde4c58c2019-06-04 09:12:59 -040067 // Copy 4 values from each of the arrays into the quad's components
68 GrQuad(const float xs[4], const float ys[4], const float ws[4], Type type)
69 : fType(type) {
70 memcpy(fX, xs, 4 * sizeof(float));
71 memcpy(fY, ys, 4 * sizeof(float));
72 memcpy(fW, ws, 4 * sizeof(float));
73 }
Brian Salomonbe3c1d22018-05-21 12:54:39 -040074
Michael Ludwigde4c58c2019-06-04 09:12:59 -040075 static GrQuad MakeFromRect(const SkRect&, const SkMatrix&);
76
77 // Creates a GrQuad from the quadrilateral 'pts', transformed by the matrix. The input
Michael Ludwig009b92e2019-02-15 16:03:53 -050078 // points array is arranged as per SkRect::toQuad (top-left, top-right, bottom-right,
79 // bottom-left). The returned instance's point order will still be CCW tri-strip order.
Michael Ludwigde4c58c2019-06-04 09:12:59 -040080 static GrQuad MakeFromSkQuad(const SkPoint pts[4], const SkMatrix&);
Michael Ludwig009b92e2019-02-15 16:03:53 -050081
Michael Ludwigde4c58c2019-06-04 09:12:59 -040082 GrQuad& operator=(const GrQuad&) = default;
Brian Salomonbe3c1d22018-05-21 12:54:39 -040083
Michael Ludwigde4c58c2019-06-04 09:12:59 -040084 SkPoint3 point3(int i) const { return {fX[i], fY[i], fW[i]}; }
85
86 SkPoint point(int i) const {
87 if (fType == Type::kPerspective) {
88 return {fX[i] / fW[i], fY[i] / fW[i]};
89 } else {
90 return {fX[i], fY[i]};
91 }
92 }
Brian Salomonbe3c1d22018-05-21 12:54:39 -040093
Michael Ludwig41f395d2019-05-23 13:59:45 -040094 SkRect bounds() const {
Michael Ludwigb3461fa2019-04-30 11:50:55 -040095 auto x = this->x4f();
96 auto y = this->y4f();
Michael Ludwigde4c58c2019-06-04 09:12:59 -040097 if (fType == Type::kPerspective) {
Michael Ludwigb3461fa2019-04-30 11:50:55 -040098 auto iw = this->iw4f();
Michael Ludwigc96fc372019-01-08 15:46:15 -050099 x *= iw;
100 y *= iw;
101 }
102
Michael Ludwigb3461fa2019-04-30 11:50:55 -0400103 return {min(x), min(y), max(x), max(y)};
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400104 }
105
106 float x(int i) const { return fX[i]; }
107 float y(int i) const { return fY[i]; }
108 float w(int i) const { return fW[i]; }
Michael Ludwigc96fc372019-01-08 15:46:15 -0500109 float iw(int i) const { return sk_ieee_float_divide(1.f, fW[i]); }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400110
Michael Ludwigb3461fa2019-04-30 11:50:55 -0400111 skvx::Vec<4, float> x4f() const { return skvx::Vec<4, float>::Load(fX); }
112 skvx::Vec<4, float> y4f() const { return skvx::Vec<4, float>::Load(fY); }
113 skvx::Vec<4, float> w4f() const { return skvx::Vec<4, float>::Load(fW); }
114 skvx::Vec<4, float> iw4f() const { return 1.f / this->w4f(); }
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400115
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400116 Type quadType() const { return fType; }
Michael Ludwig41f395d2019-05-23 13:59:45 -0400117
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400118 bool hasPerspective() const { return fType == Type::kPerspective; }
Michael Ludwig1f7e4382018-10-19 09:36:57 -0400119
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400120 // True if anti-aliasing affects this quad. Only valid when quadType == kAxisAligned
Michael Ludwig1f7e4382018-10-19 09:36:57 -0400121 bool aaHasEffectOnRect() const;
122
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400123private:
Michael Ludwigc96fc372019-01-08 15:46:15 -0500124 template<typename T>
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400125 friend class GrQuadListBase; // for access to fX, fY, fW
Michael Ludwigc96fc372019-01-08 15:46:15 -0500126
Brian Salomonbe3c1d22018-05-21 12:54:39 -0400127 float fX[4];
128 float fY[4];
129 float fW[4];
Michael Ludwig41f395d2019-05-23 13:59:45 -0400130
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400131 Type fType;
Michael Ludwigc96fc372019-01-08 15:46:15 -0500132};
133
Michael Ludwigde4c58c2019-06-04 09:12:59 -0400134// Resolve disagreements between the overall requested AA type and the per-edge quad AA flags.
135// Both outAAType and outEdgeFlags will be updated.
136void GrResolveAATypeForQuad(GrAAType requestedAAType, GrQuadAAFlags requestedEdgeFlags,
137 const GrQuad& quad, GrAAType* outAAtype, GrQuadAAFlags* outEdgeFlags);
138
joshualittae5b2c62015-08-19 08:48:41 -0700139#endif