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