extension Graphics { /// An 8×8 two-color pattern: 8 rows of image data followed by 8 rows of mask. public struct Pattern: Sendable { /// The pattern's 8 rows of image data followed by 8 rows of mask, /// one byte per row. public var bytes: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) /// Creates a pattern from 8 rows of image data and 8 rows of mask. public init(bytes: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)) { self.bytes = bytes } /// Creates an opaque pattern from 8 rows of image data. public init(rows r: (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8)) { bytes = (r.0, r.1, r.2, r.3, r.4, r.5, r.6, r.7, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff) } } } // InlineArray needs macOS 26 on the host, so these conveniences are gated // there while the tuple API keeps working on older systems. The device and // Linux have no such restriction. Both representations are 16 contiguous // bytes, so converting between them is a reinterpretation, not a copy. @available(macOS 26, *) extension Graphics.Pattern { /// Creates a pattern from 8 rows of image data and 8 rows of mask. public init(bytes: [16 of UInt8]) { self.init(bytes: unsafeBitCast(bytes, to: Bytes.self)) } /// Creates an opaque pattern from 8 rows of image data. public init(rows: [8 of UInt8]) { self.init(bytes: [16 of UInt8] { $0 < 8 ? rows[$0] : 0xff }) } /// The pattern's bytes as an inline array: 8 rows of image data /// followed by 8 rows of mask. public var inlineBytes: [16 of UInt8] { get { unsafeBitCast(bytes, to: [16 of UInt8].self) } set { bytes = unsafeBitCast(newValue, to: Bytes.self) } } } extension Graphics.Pattern { typealias Bytes = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) }