Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
273c319152 |
@@ -27,10 +27,8 @@ final class TargetPageCanvasView: NSView {
|
|||||||
fatalError("TargetPageCanvasView is code-only")
|
fatalError("TargetPageCanvasView is code-only")
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bottom-up CoreGraphics space: `CGContext.draw(_:in:)` renders
|
/// Flipped: the CoreGraphics coordinate space is correctly oriented
|
||||||
/// the raster upright — a flipped view prints mirrored (#211).
|
/// top-down, so page 1 is the TOP rect.
|
||||||
/// Page 1 is the BOTTOM band of the frame, the non-flipped
|
|
||||||
/// pagination convention.
|
|
||||||
override var isFlipped: Bool { false }
|
override var isFlipped: Bool { false }
|
||||||
override var isOpaque: Bool { true }
|
override var isOpaque: Bool { true }
|
||||||
|
|
||||||
@@ -39,7 +37,7 @@ final class TargetPageCanvasView: NSView {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 1-based page → its paper-sized rect, stacked bottom-up.
|
/// 1-based page → its paper-sized rect, stacked top-down.
|
||||||
override func rectForPage(_ page: Int) -> NSRect {
|
override func rectForPage(_ page: Int) -> NSRect {
|
||||||
NSRect(x: 0,
|
NSRect(x: 0,
|
||||||
y: CGFloat(page - 1) * paperSize.height,
|
y: CGFloat(page - 1) * paperSize.height,
|
||||||
@@ -55,7 +53,7 @@ final class TargetPageCanvasView: NSView {
|
|||||||
let pageRect = rectForPage(page)
|
let pageRect = rectForPage(page)
|
||||||
let size = pages[page - 1].pointSize
|
let size = pages[page - 1].pointSize
|
||||||
return NSRect(x: Self.snap(pageRect.minX),
|
return NSRect(x: Self.snap(pageRect.minX),
|
||||||
y: Self.snap(pageRect.maxY - size.height),
|
y: Self.snap(pageRect.minY),
|
||||||
width: size.width,
|
width: size.width,
|
||||||
height: size.height)
|
height: size.height)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -40,8 +40,21 @@ final class NativeSpoolPDFTests: XCTestCase {
|
|||||||
pixelBytes: patchBytes, in: tempRoot)
|
pixelBytes: patchBytes, in: tempRoot)
|
||||||
let raster = try TargetRasterLoader.load(tiff: tiff)
|
let raster = try TargetRasterLoader.load(tiff: tiff)
|
||||||
|
|
||||||
|
let info = NSPrintInfo()
|
||||||
|
info.paperSize = paperSize
|
||||||
|
info.orientation = .portrait
|
||||||
|
info.topMargin = 0
|
||||||
|
info.bottomMargin = 0
|
||||||
|
info.leftMargin = 0
|
||||||
|
info.rightMargin = 0
|
||||||
|
info.horizontalPagination = .clip
|
||||||
|
info.verticalPagination = .clip
|
||||||
|
info.scalingFactor = 1.0
|
||||||
|
info.isHorizontallyCentered = false
|
||||||
|
info.isVerticallyCentered = false
|
||||||
|
info.jobDisposition = .save
|
||||||
let pdfURL = tempRoot.appendingPathComponent("spool.pdf")
|
let pdfURL = tempRoot.appendingPathComponent("spool.pdf")
|
||||||
let info = makeSaveInfo(pdfURL: pdfURL)
|
info.dictionary()[NSPrintInfo.AttributeKey.jobSavingURL] = pdfURL
|
||||||
|
|
||||||
let canvas = TargetPageCanvasView(
|
let canvas = TargetPageCanvasView(
|
||||||
pages: [raster, raster], paperSize: paperSize)
|
pages: [raster, raster], paperSize: paperSize)
|
||||||
@@ -75,7 +88,29 @@ final class NativeSpoolPDFTests: XCTestCase {
|
|||||||
) throws {
|
) throws {
|
||||||
let width = Int(ceil(mediaBox.width))
|
let width = Int(ceil(mediaBox.width))
|
||||||
let height = Int(ceil(mediaBox.height))
|
let height = Int(ceil(mediaBox.height))
|
||||||
let rep = try renderPageToBitmap(page, mediaBox: mediaBox)
|
let rep = try XCTUnwrap(NSBitmapImageRep(
|
||||||
|
bitmapDataPlanes: nil,
|
||||||
|
pixelsWide: width,
|
||||||
|
pixelsHigh: height,
|
||||||
|
bitsPerSample: 8,
|
||||||
|
samplesPerPixel: 4,
|
||||||
|
hasAlpha: true,
|
||||||
|
isPlanar: false,
|
||||||
|
colorSpaceName: .deviceRGB,
|
||||||
|
bytesPerRow: 0,
|
||||||
|
bitsPerPixel: 0))
|
||||||
|
let context = try XCTUnwrap(
|
||||||
|
NSGraphicsContext(bitmapImageRep: rep))
|
||||||
|
let cg = context.cgContext
|
||||||
|
let transform = page.getDrawingTransform(
|
||||||
|
.mediaBox,
|
||||||
|
rect: CGRect(x: 0, y: 0, width: width, height: height),
|
||||||
|
rotate: 0, preserveAspectRatio: true)
|
||||||
|
NSGraphicsContext.saveGraphicsState()
|
||||||
|
NSGraphicsContext.current = context
|
||||||
|
cg.concatenate(transform)
|
||||||
|
cg.drawPDFPage(page)
|
||||||
|
NSGraphicsContext.restoreGraphicsState()
|
||||||
|
|
||||||
func pixel(_ x: Int, _ y: Int) throws -> (Double, Double, Double) {
|
func pixel(_ x: Int, _ y: Int) throws -> (Double, Double, Double) {
|
||||||
let color = try XCTUnwrap(
|
let color = try XCTUnwrap(
|
||||||
@@ -126,144 +161,4 @@ final class NativeSpoolPDFTests: XCTestCase {
|
|||||||
XCTAssertEqual(outside.1, 1, accuracy: 0.04)
|
XCTAssertEqual(outside.1, 1, accuracy: 0.04)
|
||||||
XCTAssertEqual(outside.2, 1, accuracy: 0.04)
|
XCTAssertEqual(outside.2, 1, accuracy: 0.04)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// #211 — a top/bottom banded block proves the page is drawn
|
|
||||||
/// upright AND anchored at the paper's top edge: a mirrored draw
|
|
||||||
/// swaps the bands; a bottom-anchored draw leaves white above the
|
|
||||||
/// block instead of below.
|
|
||||||
func testSavePDFDrawsPageUprightTopAnchored() throws {
|
|
||||||
try XCTSkipIf(
|
|
||||||
ProcessInfo.processInfo.environment["ICCERY_SKIP_PRINT_PDF"]
|
|
||||||
== "1",
|
|
||||||
"ICCERY_SKIP_PRINT_PDF=1 — print system unavailable")
|
|
||||||
|
|
||||||
// 144×144 px @ 72 dpi → a 144×144 pt block, top half red,
|
|
||||||
// bottom half blue.
|
|
||||||
let topBytes: [UInt8] = [230, 40, 50]
|
|
||||||
let bottomBytes: [UInt8] = [40, 50, 230]
|
|
||||||
let tiff = try TargetTestFixtures.makeTIFF(
|
|
||||||
px: CGSize(width: 144, height: 144), dpi: 72,
|
|
||||||
components: 3, bitsPerComponent: 8,
|
|
||||||
pixelBytes: topBytes,
|
|
||||||
bottomHalfPixelBytes: bottomBytes, in: tempRoot)
|
|
||||||
let raster = try TargetRasterLoader.load(tiff: tiff)
|
|
||||||
|
|
||||||
let pdfURL = tempRoot.appendingPathComponent("bands.pdf")
|
|
||||||
let info = makeSaveInfo(pdfURL: pdfURL)
|
|
||||||
let canvas = TargetPageCanvasView(
|
|
||||||
pages: [raster], paperSize: paperSize)
|
|
||||||
let operation = NSPrintOperation(view: canvas, printInfo: info)
|
|
||||||
operation.showsPrintPanel = false
|
|
||||||
operation.showsProgressPanel = false
|
|
||||||
operation.canSpawnSeparateThread = false
|
|
||||||
XCTAssertTrue(operation.run(),
|
|
||||||
"NSPrintOperation.save failed")
|
|
||||||
|
|
||||||
let document = try XCTUnwrap(
|
|
||||||
CGPDFDocument(pdfURL as CFURL))
|
|
||||||
let page = try XCTUnwrap(document.page(at: 1))
|
|
||||||
let mediaBox = page.getBoxRect(.mediaBox)
|
|
||||||
let rep = try renderPageToBitmap(page, mediaBox: mediaBox)
|
|
||||||
|
|
||||||
func pixel(_ x: Int, _ y: Int) throws -> (Double, Double, Double) {
|
|
||||||
let color = try XCTUnwrap(
|
|
||||||
rep.colorAt(x: x, y: y)?.usingColorSpace(.deviceRGB))
|
|
||||||
return (color.redComponent,
|
|
||||||
color.greenComponent,
|
|
||||||
color.blueComponent)
|
|
||||||
}
|
|
||||||
func matches(
|
|
||||||
_ p: (Double, Double, Double), _ rgb: [UInt8]
|
|
||||||
) -> Bool {
|
|
||||||
abs(p.0 - Double(rgb[0]) / 255) < 0.04
|
|
||||||
&& abs(p.1 - Double(rgb[1]) / 255) < 0.04
|
|
||||||
&& abs(p.2 - Double(rgb[2]) / 255) < 0.04
|
|
||||||
}
|
|
||||||
|
|
||||||
// Painted region = the page fill inset by the queue's
|
|
||||||
// unprintable margin (R10); minimum opaque y is its top edge
|
|
||||||
// in the rendered bitmap (same convention as the 1:1 test).
|
|
||||||
let width = Int(ceil(mediaBox.width))
|
|
||||||
let height = Int(ceil(mediaBox.height))
|
|
||||||
var topX = width, topY = height
|
|
||||||
for y in 0..<height {
|
|
||||||
for x in 0..<width
|
|
||||||
where (rep.colorAt(x: x, y: y)?.alphaComponent ?? 0) > 0.5 {
|
|
||||||
topX = min(topX, x)
|
|
||||||
topY = min(topY, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
XCTAssertLessThan(topY, height, "PDF page rendered empty")
|
|
||||||
|
|
||||||
// The 144 pt block hangs from the page's top edge: top-band
|
|
||||||
// colour for the first 72 pt, bottom-band colour for the
|
|
||||||
// next 72 pt, then the white page fill.
|
|
||||||
XCTAssertTrue(
|
|
||||||
try matches(pixel(topX + 10, topY + 10), topBytes),
|
|
||||||
"block top is not the top-band colour — mirrored draw?")
|
|
||||||
XCTAssertTrue(
|
|
||||||
try matches(pixel(topX + 10, topY + 82), bottomBytes),
|
|
||||||
"block bottom is not the bottom-band colour — mirrored draw?")
|
|
||||||
XCTAssertTrue(
|
|
||||||
try matches(pixel(topX + 10, topY + 134), bottomBytes),
|
|
||||||
"block does not reach 144 pt below the painted top edge")
|
|
||||||
let below = try pixel(topX + 10, topY + 160)
|
|
||||||
XCTAssertEqual(below.0, 1, accuracy: 0.04)
|
|
||||||
XCTAssertEqual(below.1, 1, accuracy: 0.04)
|
|
||||||
XCTAssertEqual(below.2, 1, accuracy: 0.04)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Print settings shared by the save-PDF harness tests: A4, zero
|
|
||||||
/// margins, `.clip` pagination, 1:1, no centring, `.save` to
|
|
||||||
/// `pdfURL`.
|
|
||||||
private func makeSaveInfo(pdfURL: URL) -> NSPrintInfo {
|
|
||||||
let info = NSPrintInfo()
|
|
||||||
info.paperSize = paperSize
|
|
||||||
info.orientation = .portrait
|
|
||||||
info.topMargin = 0
|
|
||||||
info.bottomMargin = 0
|
|
||||||
info.leftMargin = 0
|
|
||||||
info.rightMargin = 0
|
|
||||||
info.horizontalPagination = .clip
|
|
||||||
info.verticalPagination = .clip
|
|
||||||
info.scalingFactor = 1.0
|
|
||||||
info.isHorizontallyCentered = false
|
|
||||||
info.isVerticallyCentered = false
|
|
||||||
info.jobDisposition = .save
|
|
||||||
info.dictionary()[
|
|
||||||
NSPrintInfo.AttributeKey.jobSavingURL] = pdfURL
|
|
||||||
return info
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Render a saved-PDF page into a bitmap at 1 px/pt.
|
|
||||||
private func renderPageToBitmap(
|
|
||||||
_ page: CGPDFPage, mediaBox: CGRect
|
|
||||||
) throws -> NSBitmapImageRep {
|
|
||||||
let width = Int(ceil(mediaBox.width))
|
|
||||||
let height = Int(ceil(mediaBox.height))
|
|
||||||
let rep = try XCTUnwrap(NSBitmapImageRep(
|
|
||||||
bitmapDataPlanes: nil,
|
|
||||||
pixelsWide: width,
|
|
||||||
pixelsHigh: height,
|
|
||||||
bitsPerSample: 8,
|
|
||||||
samplesPerPixel: 4,
|
|
||||||
hasAlpha: true,
|
|
||||||
isPlanar: false,
|
|
||||||
colorSpaceName: .deviceRGB,
|
|
||||||
bytesPerRow: 0,
|
|
||||||
bitsPerPixel: 0))
|
|
||||||
let context = try XCTUnwrap(
|
|
||||||
NSGraphicsContext(bitmapImageRep: rep))
|
|
||||||
let cg = context.cgContext
|
|
||||||
let transform = page.getDrawingTransform(
|
|
||||||
.mediaBox,
|
|
||||||
rect: CGRect(x: 0, y: 0, width: width, height: height),
|
|
||||||
rotate: 0, preserveAspectRatio: true)
|
|
||||||
NSGraphicsContext.saveGraphicsState()
|
|
||||||
NSGraphicsContext.current = context
|
|
||||||
cg.concatenate(transform)
|
|
||||||
cg.drawPDFPage(page)
|
|
||||||
NSGraphicsContext.restoreGraphicsState()
|
|
||||||
return rep
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ import Foundation
|
|||||||
import XCTest
|
import XCTest
|
||||||
@testable import ICCery
|
@testable import ICCery
|
||||||
|
|
||||||
/// Issue #201 Phase 3 — `TargetPageCanvasView` bottom-up page stacking,
|
/// Issue #201 Phase 3 — `TargetPageCanvasView` top-down page stacking,
|
||||||
/// snapped top-left anchoring, and the draw-time interpolation /
|
/// snapped top-left anchoring, and the draw-time interpolation /
|
||||||
/// antialias contract asserted via `drawProbe`.
|
/// antialias contract asserted via `drawProbe`.
|
||||||
@MainActor
|
@MainActor
|
||||||
@@ -35,9 +35,7 @@ final class TargetCanvasGeometryTests: XCTestCase {
|
|||||||
|
|
||||||
// MARK: - Page stacking
|
// MARK: - Page stacking
|
||||||
|
|
||||||
/// Bottom-up space: page 1 is the BOTTOM band of the frame — the
|
func testRectForPageStacksTopDown() {
|
||||||
/// non-flipped pagination convention (#211).
|
|
||||||
func testRectForPageStacksBottomUp() {
|
|
||||||
let view = TargetPageCanvasView(
|
let view = TargetPageCanvasView(
|
||||||
pages: [raster(), raster(), raster()],
|
pages: [raster(), raster(), raster()],
|
||||||
paperSize: paperSize)
|
paperSize: paperSize)
|
||||||
@@ -70,33 +68,18 @@ final class TargetCanvasGeometryTests: XCTestCase {
|
|||||||
pages: [raster(), raster()],
|
pages: [raster(), raster()],
|
||||||
paperSize: paperSize)
|
paperSize: paperSize)
|
||||||
|
|
||||||
// Near-full-page raster: in bottom-up space the page's top
|
|
||||||
// edge is `maxY`, so the top-anchored origin is ~0.03 pt
|
|
||||||
// negative — the overflow clips at the BOTTOM of the sheet.
|
|
||||||
let first = view.destinationRect(forPage: 1)
|
let first = view.destinationRect(forPage: 1)
|
||||||
XCTAssertEqual(first.origin.x, 0, accuracy: 0.001)
|
XCTAssertEqual(first.origin.x, 0, accuracy: 0.001)
|
||||||
XCTAssertEqual(first.origin.y, -0.03, accuracy: 0.001)
|
XCTAssertEqual(first.origin.y, 0, accuracy: 0.001)
|
||||||
XCTAssertEqual(first.width, 595.2, accuracy: 0.01)
|
XCTAssertEqual(first.width, 595.2, accuracy: 0.01)
|
||||||
XCTAssertEqual(first.height, 841.92, accuracy: 0.01)
|
XCTAssertEqual(first.height, 841.92, accuracy: 0.01)
|
||||||
|
|
||||||
let second = view.destinationRect(forPage: 2)
|
let second = view.destinationRect(forPage: 2)
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
second.origin.y,
|
second.origin.y, paperSize.height, accuracy: 0.001)
|
||||||
2 * paperSize.height - first.height, accuracy: 0.001)
|
|
||||||
XCTAssertEqual(second.size, first.size)
|
XCTAssertEqual(second.size, first.size)
|
||||||
|
|
||||||
// A raster smaller than the paper hangs from the page's TOP
|
for rect in [first, second] {
|
||||||
// edge — minY would anchor it at the bottom (#211 follow-up).
|
|
||||||
let small = TargetPageCanvasView(
|
|
||||||
pages: [raster(pixelWidth: 72, pixelHeight: 72, dpi: 72)],
|
|
||||||
paperSize: paperSize)
|
|
||||||
let smallRect = small.destinationRect(forPage: 1)
|
|
||||||
XCTAssertEqual(smallRect.origin.x, 0, accuracy: 0.001)
|
|
||||||
XCTAssertEqual(
|
|
||||||
smallRect.origin.y, paperSize.height - 72, accuracy: 0.001)
|
|
||||||
XCTAssertEqual(smallRect.size, CGSize(width: 72, height: 72))
|
|
||||||
|
|
||||||
for rect in [first, second, smallRect] {
|
|
||||||
XCTAssertEqual(
|
XCTAssertEqual(
|
||||||
rect.origin.x * 1000,
|
rect.origin.x * 1000,
|
||||||
(rect.origin.x * 1000).rounded(),
|
(rect.origin.x * 1000).rounded(),
|
||||||
|
|||||||
@@ -27,16 +27,12 @@ enum TargetTestFixtures {
|
|||||||
/// colour space for 1/3/4 components at 8 or 16 bpc. `alpha: true`
|
/// colour space for 1/3/4 components at 8 or 16 bpc. `alpha: true`
|
||||||
/// appends one alpha sample per pixel (`last`). `pixelBytes` is the
|
/// appends one alpha sample per pixel (`last`). `pixelBytes` is the
|
||||||
/// repeating per-pixel pattern (big-endian for 16 bpc).
|
/// repeating per-pixel pattern (big-endian for 16 bpc).
|
||||||
/// `bottomHalfPixelBytes`, when set, is the pattern for the bottom
|
|
||||||
/// half of the rows — a vertical asymmetry that lets tests catch a
|
|
||||||
/// mirrored draw (#211).
|
|
||||||
static func makeImage(
|
static func makeImage(
|
||||||
px: CGSize,
|
px: CGSize,
|
||||||
components: Int,
|
components: Int,
|
||||||
bitsPerComponent: Int,
|
bitsPerComponent: Int,
|
||||||
alpha: Bool = false,
|
alpha: Bool = false,
|
||||||
pixelBytes: [UInt8]? = nil,
|
pixelBytes: [UInt8]? = nil
|
||||||
bottomHalfPixelBytes: [UInt8]? = nil
|
|
||||||
) -> CGImage? {
|
) -> CGImage? {
|
||||||
let width = Int(px.width)
|
let width = Int(px.width)
|
||||||
let height = Int(px.height)
|
let height = Int(px.height)
|
||||||
@@ -44,31 +40,19 @@ enum TargetTestFixtures {
|
|||||||
let samples = components + (alpha ? 1 : 0)
|
let samples = components + (alpha ? 1 : 0)
|
||||||
let bytesPerPixel = samples * bytesPerComponent
|
let bytesPerPixel = samples * bytesPerComponent
|
||||||
let bytesPerRow = width * bytesPerPixel
|
let bytesPerRow = width * bytesPerPixel
|
||||||
func buildRow(_ pattern: [UInt8]) -> [UInt8] {
|
let pattern = pixelBytes
|
||||||
var row = [UInt8](repeating: 0, count: bytesPerRow)
|
?? Array(0..<bytesPerPixel).map { UInt8(($0 * 37 + 11) & 0xff) }
|
||||||
for offset in stride(
|
var row = [UInt8](repeating: 0, count: bytesPerRow)
|
||||||
from: 0, to: bytesPerRow, by: pattern.count) {
|
for offset in stride(from: 0, to: bytesPerRow, by: pattern.count) {
|
||||||
for (index, byte) in pattern.enumerated()
|
for (index, byte) in pattern.enumerated()
|
||||||
where offset + index < bytesPerRow {
|
where offset + index < bytesPerRow {
|
||||||
row[offset + index] = byte
|
row[offset + index] = byte
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return row
|
|
||||||
}
|
}
|
||||||
let topRow = buildRow(
|
|
||||||
pixelBytes
|
|
||||||
?? Array(0..<bytesPerPixel).map {
|
|
||||||
UInt8(($0 * 37 + 11) & 0xff)
|
|
||||||
})
|
|
||||||
let bottomRow = buildRow(bottomHalfPixelBytes ?? pixelBytes
|
|
||||||
?? Array(0..<bytesPerPixel).map {
|
|
||||||
UInt8(($0 * 37 + 11) & 0xff)
|
|
||||||
})
|
|
||||||
var bytes = [UInt8]()
|
var bytes = [UInt8]()
|
||||||
bytes.reserveCapacity(bytesPerRow * height)
|
bytes.reserveCapacity(bytesPerRow * height)
|
||||||
for rowIndex in 0..<height {
|
for _ in 0..<height {
|
||||||
bytes.append(
|
bytes.append(contentsOf: row)
|
||||||
contentsOf: rowIndex < height / 2 ? topRow : bottomRow)
|
|
||||||
}
|
}
|
||||||
let data = Data(bytes)
|
let data = Data(bytes)
|
||||||
|
|
||||||
@@ -104,7 +88,6 @@ enum TargetTestFixtures {
|
|||||||
|
|
||||||
/// Writes `makeImage` output to a single-page TIFF. `dpi` nil
|
/// Writes `makeImage` output to a single-page TIFF. `dpi` nil
|
||||||
/// produces a TIFF with no resolution tags (the 72-fallback path).
|
/// produces a TIFF with no resolution tags (the 72-fallback path).
|
||||||
/// `bottomHalfPixelBytes` passes through to `makeImage` (#211).
|
|
||||||
static func makeTIFF(
|
static func makeTIFF(
|
||||||
px: CGSize,
|
px: CGSize,
|
||||||
dpi: Double?,
|
dpi: Double?,
|
||||||
@@ -112,14 +95,12 @@ enum TargetTestFixtures {
|
|||||||
bitsPerComponent: Int = 8,
|
bitsPerComponent: Int = 8,
|
||||||
alpha: Bool = false,
|
alpha: Bool = false,
|
||||||
pixelBytes: [UInt8]? = nil,
|
pixelBytes: [UInt8]? = nil,
|
||||||
bottomHalfPixelBytes: [UInt8]? = nil,
|
|
||||||
in directory: URL
|
in directory: URL
|
||||||
) throws -> URL {
|
) throws -> URL {
|
||||||
guard let image = makeImage(
|
guard let image = makeImage(
|
||||||
px: px, components: components,
|
px: px, components: components,
|
||||||
bitsPerComponent: bitsPerComponent,
|
bitsPerComponent: bitsPerComponent,
|
||||||
alpha: alpha, pixelBytes: pixelBytes,
|
alpha: alpha, pixelBytes: pixelBytes)
|
||||||
bottomHalfPixelBytes: bottomHalfPixelBytes)
|
|
||||||
else { throw FixtureError.imageNotCreated }
|
else { throw FixtureError.imageNotCreated }
|
||||||
let url = directory.appendingPathComponent(
|
let url = directory.appendingPathComponent(
|
||||||
"fixture-\(UUID().uuidString).tiff")
|
"fixture-\(UUID().uuidString).tiff")
|
||||||
|
|||||||
Reference in New Issue
Block a user