• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google LLC
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 skgpu_graphite_geom_EdgeAAQuad_DEFINED
9 #define skgpu_graphite_geom_EdgeAAQuad_DEFINED
10 
11 #include "include/core/SkRect.h"
12 #include "src/base/SkVx.h"
13 #include "src/core/SkEnumBitMask.h"
14 #include "src/gpu/graphite/geom/Rect.h"
15 
16 namespace skgpu::graphite {
17 
18 /**
19  * EdgeAAQuad contains (x,y) coordinates for the four corners of a quadrilateral, assumed to be
20  * convex and in a consistent winding (CW vs. CCW is fine). Locally, the vertices are ordered
21  * "top-left", "top-right", "bottom-right", "bottom-left". The edges are in order left (p0-p3),
22  * top (p1-p0), right (p2-p1), and bottom (p3-p2).
23  */
24 class EdgeAAQuad {
25 public:
26     // SkEnumBitMask<Flags> is a typesafe equivalent to SkCanvas::QuadAAFlags.
27     enum class Flags : uint8_t {
28         kLeft   = 0b0001,
29         kTop    = 0b0010,
30         kRight  = 0b0100,
31         kBottom = 0b1000,
32 
33         kNone   = 0b0000,
34         kAll    = 0b1111,
35     };
36 
37     EdgeAAQuad() = delete;
38 
EdgeAAQuad(const SkRect & rect,SkEnumBitMask<Flags> edgeFlags)39     EdgeAAQuad(const SkRect& rect, SkEnumBitMask<Flags> edgeFlags)
40             : fXs{rect.fLeft, rect.fRight, rect.fRight, rect.fLeft}
41             , fYs{rect.fTop, rect.fTop, rect.fBottom, rect.fBottom}
42             , fEdgeFlags(edgeFlags)
43             , fIsRect(true) {}
EdgeAAQuad(const Rect & rect,SkEnumBitMask<Flags> edgeFlags)44     EdgeAAQuad(const Rect& rect, SkEnumBitMask<Flags> edgeFlags)
45             : fXs{skvx::shuffle<0,2,2,0>(rect.ltrb())}
46             , fYs{skvx::shuffle<1,1,3,3>(rect.ltrb())}
47             , fEdgeFlags(edgeFlags)
48             , fIsRect(true) {}
EdgeAAQuad(const SkPoint points[4],SkEnumBitMask<Flags> edgeFlags)49     EdgeAAQuad(const SkPoint points[4], SkEnumBitMask<Flags> edgeFlags)
50             : fXs{points[0].fX, points[1].fX, points[2].fX, points[3].fX}
51             , fYs{points[0].fY, points[1].fY, points[2].fY, points[3].fY}
52             , fEdgeFlags(edgeFlags)
53             , fIsRect(false) {}
EdgeAAQuad(const skvx::float4 & xs,const skvx::float4 & ys,SkEnumBitMask<Flags> edgeFlags)54     EdgeAAQuad(const skvx::float4& xs, const skvx::float4& ys, SkEnumBitMask<Flags> edgeFlags)
55             : fXs(xs)
56             , fYs(ys)
57             , fEdgeFlags(edgeFlags)
58             , fIsRect(false) {}
59 
60     // The bounding box of the quadrilateral (not counting any outsetting for anti-aliasing).
bounds()61     Rect bounds() const {
62         if (fIsRect) {
63             return Rect({fXs[0], fYs[0]}, {fXs[2], fYs[2]});
64         }
65 
66         Rect p0p1 = Rect::LTRB(skvx::shuffle<0,2,1,3>(skvx::float4(fXs.lo, fYs.lo))).makeSorted();
67         Rect p2p3 = Rect::LTRB(skvx::shuffle<0,2,1,3>(skvx::float4(fXs.hi, fYs.hi))).makeSorted();
68         return p0p1.makeJoin(p2p3);
69     }
70 
71     // Access the individual elements of the quad data.
xs()72     const skvx::float4& xs() const { return fXs; }
ys()73     const skvx::float4& ys() const { return fYs; }
edgeFlags()74     SkEnumBitMask<Flags> edgeFlags() const { return fEdgeFlags; }
75 
isRect()76     bool isRect() const { return fIsRect; }
77 
78 private:
79     skvx::float4 fXs;
80     skvx::float4 fYs;
81     SkEnumBitMask<Flags> fEdgeFlags;
82     bool fIsRect;
83 };
84 
85 SK_MAKE_BITMASK_OPS(EdgeAAQuad::Flags)
86 
87 } // namespace skgpu::graphite
88 
89 #endif // skgpu_graphite_geom_EdgeAAQuad_DEFINED
90