Adopted Span and MutableSpan for buffers across the library to adapt to Swift 6.4.

This commit is contained in:
2026-09-18 12:06:21 +02:00
parent 89c8d7a04c
commit 4cb0f8f500
18 changed files with 127 additions and 83 deletions
@@ -39,14 +39,42 @@ extension Graphics {
// MARK: Properties
/// The bitmap's dimensions, row stride, and raw storage.
/// The bitmap's dimensions and row stride.
public var data: Data {
let raw = rawData()
return Data(width: raw.width, height: raw.height, rowBytes: raw.rowBytes,
hasMask: raw.mask != nil)
}
/// Calls `body` with the bitmap's pixel data: one bit per pixel,
/// `height` rows of `rowBytes` bytes each.
public func withPixelData<Result, Failure: Error>(
_ body: (inout MutableSpan<UInt8>) throws(Failure) -> Result
) throws(Failure) -> Result {
let raw = rawData()
var span = UnsafeMutableBufferPointer(
start: raw.data, count: raw.data == nil ? 0 : raw.height * raw.rowBytes).mutableSpan
return try body(&span)
}
/// Calls `body` with the bitmap's mask data, laid out like the pixel
/// data. Returns `nil` if the bitmap has no mask.
public func withMaskData<Result, Failure: Error>(
_ body: (inout MutableSpan<UInt8>) throws(Failure) -> Result
) throws(Failure) -> Result? {
let raw = rawData()
guard let mask = raw.mask else { return nil }
var span = UnsafeMutableBufferPointer(start: mask, count: raw.height * raw.rowBytes).mutableSpan
return try body(&span)
}
private func rawData() -> (width: Int, height: Int, rowBytes: Int,
mask: UnsafeMutablePointer<UInt8>?, data: UnsafeMutablePointer<UInt8>?) {
var width: Int32 = 0, height: Int32 = 0, rowBytes: Int32 = 0
var mask: UnsafeMutablePointer<UInt8>?
var data: UnsafeMutablePointer<UInt8>?
gfx.pointee.getBitmapData.unsafelyUnwrapped(pointer, &width, &height, &rowBytes, &mask, &data)
return Data(width: Int(width), height: Int(height), rowBytes: Int(rowBytes),
mask: mask, data: data)
return (Int(width), Int(height), Int(rowBytes), mask, data)
}
/// Cached dimensions, so `width`/`height` don't pay a full
@@ -56,8 +84,8 @@ extension Graphics {
private var size: (width: Int, height: Int) {
if let cachedSize { return cachedSize }
let data = self.data
let size = (data.width, data.height)
let raw = rawData()
let size = (raw.width, raw.height)
cachedSize = size
return size
}
@@ -23,9 +23,11 @@ extension Graphics {
/// Creates a font from the contents of a .pft file already in memory.
/// The bytes are copied and retained for the font's lifetime.
public convenience init?(data: UnsafeRawBufferPointer, wide: Bool = false) {
public convenience init?(data: Span<UInt8>, wide: Bool = false) {
let copy = UnsafeMutableRawPointer.allocate(byteCount: data.count, alignment: 4)
copy.copyMemory(from: data.baseAddress.unsafelyUnwrapped, byteCount: data.count)
data.withUnsafeBytes { bytes in
copy.copyMemory(from: bytes.baseAddress.unsafelyUnwrapped, byteCount: bytes.count)
}
let fontData = OpaquePointer(copy)
guard let pointer = gfx.pointee.makeFontFromData.unsafelyUnwrapped(
fontData, wide ? 1 : 0, Int32(data.count)) else {
+16 -6
View File
@@ -279,15 +279,25 @@ extension Graphics {
// MARK: - Framebuffer
/// The current working framebuffer. Rows are `rowSize` bytes.
/// Calls `body` with the current working framebuffer: `rows` rows of
/// `rowSize` bytes each. Returns `nil` if there is no framebuffer.
/// Call `markUpdatedRows(from:to:)` after writing directly.
public static var frame: UnsafeMutablePointer<UInt8>? {
gfx.pointee.getFrame.unsafelyUnwrapped()
public static func withFrame<Result, Failure: Error>(
_ body: (inout MutableSpan<UInt8>) throws(Failure) -> Result
) throws(Failure) -> Result? {
guard let frame = gfx.pointee.getFrame.unsafelyUnwrapped() else { return nil }
var span = UnsafeMutableBufferPointer(start: frame, count: rows * rowSize).mutableSpan
return try body(&span)
}
/// The framebuffer currently shown on the display. Rows are `rowSize` bytes.
public static var displayFrame: UnsafeMutablePointer<UInt8>? {
gfx.pointee.getDisplayFrame.unsafelyUnwrapped()
/// Calls `body` with the framebuffer currently shown on the display:
/// `rows` rows of `rowSize` bytes each. Returns `nil` if there is no
/// framebuffer.
public static func withDisplayFrame<Result, Failure: Error>(
_ body: (Span<UInt8>) throws(Failure) -> Result
) throws(Failure) -> Result? {
guard let frame = gfx.pointee.getDisplayFrame.unsafelyUnwrapped() else { return nil }
return try body(UnsafeBufferPointer(start: frame, count: rows * rowSize).span)
}
/// A bitmap view of the display framebuffer. Simulator only; `nil` on device.
@@ -1,18 +1,14 @@
extension Graphics.Bitmap {
/// The bitmap's dimensions, row stride, and raw pixel/mask storage.
/// The pointers are owned by the bitmap.
public struct Data {
/// The bitmap's dimensions and row stride. Access the pixels themselves
/// with `withPixelData(_:)` and `withMaskData(_:)`.
public struct Data: Sendable {
/// The bitmap's width, in pixels.
public let width: Int
/// The bitmap's height, in pixels.
public let height: Int
/// The stride of one row of pixel data, in bytes.
/// The stride of one row of pixel (and mask) data, in bytes.
public let rowBytes: Int
/// The bitmap's mask data, or `nil` if it has no mask. One bit per
/// pixel; rows are `rowBytes` wide.
public let mask: UnsafeMutablePointer<UInt8>?
/// The bitmap's pixel data. One bit per pixel; rows are `rowBytes`
/// wide.
public let data: UnsafeMutablePointer<UInt8>?
/// Whether the bitmap has a mask.
public let hasMask: Bool
}
}