blob: 5b7bbe82b88389bc35b88a215c4f7ffd8f4c1220 [file] [log] [blame]
/*
* Copyright 2023 Google LLC
*
* Use of this source code is governed by a BSD-style license that can be
* found in the LICENSE file.
*/
#ifndef skgpu_graphite_geom_EdgeAAQuad_DEFINED
#define skgpu_graphite_geom_EdgeAAQuad_DEFINED
#include "include/core/SkRect.h"
#include "src/base/SkVx.h"
#include "src/core/SkEnumBitMask.h"
#include "src/gpu/graphite/geom/Rect.h"
namespace skgpu::graphite {
/**
* EdgeAAQuad contains (x,y) coordinates for the four corners of a quadrilateral, assumed to be
* convex and in a consistent winding (CW vs. CCW is fine). Locally, the vertices are ordered
* "top-left", "top-right", "bottom-right", "bottom-left". The edges are in order left (p0-p3),
* top (p1-p0), right (p2-p1), and bottom (p3-p2).
*/
class EdgeAAQuad {
public:
// SkEnumBitMask<Flags> is a typesafe equivalent to SkCanvas::QuadAAFlags.
enum class Flags : uint8_t {
kLeft = 0b0001,
kTop = 0b0010,
kRight = 0b0100,
kBottom = 0b1000,
kNone = 0b0000,
kAll = 0b1111,
};
EdgeAAQuad() = delete;
EdgeAAQuad(const SkRect& rect, SkEnumBitMask<Flags> edgeFlags)
: fXs{rect.fLeft, rect.fRight, rect.fRight, rect.fLeft}
, fYs{rect.fTop, rect.fTop, rect.fBottom, rect.fBottom}
, fEdgeFlags(edgeFlags)
, fIsRect(true) {}
EdgeAAQuad(const Rect& rect, SkEnumBitMask<Flags> edgeFlags)
: fXs{skvx::shuffle<0,2,2,0>(rect.ltrb())}
, fYs{skvx::shuffle<1,1,3,3>(rect.ltrb())}
, fEdgeFlags(edgeFlags)
, fIsRect(true) {}
EdgeAAQuad(const SkPoint points[4], SkEnumBitMask<Flags> edgeFlags)
: fXs{points[0].fX, points[1].fX, points[2].fX, points[3].fX}
, fYs{points[0].fY, points[1].fY, points[2].fY, points[3].fY}
, fEdgeFlags(edgeFlags)
, fIsRect(false) {}
EdgeAAQuad(const skvx::float4& xs, const skvx::float4& ys, SkEnumBitMask<Flags> edgeFlags)
: fXs(xs)
, fYs(ys)
, fEdgeFlags(edgeFlags)
, fIsRect(false) {}
// The bounding box of the quadrilateral (not counting any outsetting for anti-aliasing).
Rect bounds() const {
if (fIsRect) {
return Rect({fXs[0], fYs[0]}, {fXs[2], fYs[2]});
}
Rect p0p1 = Rect::LTRB(skvx::shuffle<0,2,1,3>(skvx::float4(fXs.lo, fYs.lo))).makeSorted();
Rect p2p3 = Rect::LTRB(skvx::shuffle<0,2,1,3>(skvx::float4(fXs.hi, fYs.hi))).makeSorted();
return p0p1.makeJoin(p2p3);
}
// Access the individual elements of the quad data.
const skvx::float4& xs() const { return fXs; }
const skvx::float4& ys() const { return fYs; }
SkEnumBitMask<Flags> edgeFlags() const { return fEdgeFlags; }
bool isRect() const { return fIsRect; }
private:
skvx::float4 fXs;
skvx::float4 fYs;
SkEnumBitMask<Flags> fEdgeFlags;
bool fIsRect;
};
SK_MAKE_BITMASK_OPS(EdgeAAQuad::Flags)
} // namespace skgpu::graphite
#endif // skgpu_graphite_geom_EdgeAAQuad_DEFINED