diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/AttachableAsIWICBitmap.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/AttachableAsIWICBitmapSource.swift similarity index 73% rename from Sources/Overlays/_Testing_WinSDK/Attachments/AttachableAsIWICBitmap.swift rename to Sources/Overlays/_Testing_WinSDK/Attachments/AttachableAsIWICBitmapSource.swift index b17b82417..b3c37d27f 100644 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/AttachableAsIWICBitmap.swift +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/AttachableAsIWICBitmapSource.swift @@ -26,32 +26,33 @@ public import WinSDK /// /// - [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps) /// - [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons) -/// - [`IWICBitmap`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmap) +/// - [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) +/// (including its subclasses declared by Windows Imaging Component) /// /// You do not generally need to add your own conformances to this protocol. If /// you have an image in another format that needs to be attached to a test, /// first convert it to an instance of one of the types above. @_spi(Experimental) -public protocol _AttachableByAddressAsIWICBitmap { - /// Create a WIC bitmap representing an instance of this type at the given - /// address. +public protocol _AttachableByAddressAsIWICBitmapSource { + /// Create a WIC bitmap source representing an instance of this type at the + /// given address. /// /// - Parameters: /// - imageAddress: The address of the instance of this type. /// - factory: A WIC imaging factory that can be used to create additional /// WIC objects. /// - /// - Returns: A pointer to a new WIC bitmap representing this image. The - /// caller is responsible for releasing this image when done with it. + /// - Returns: A pointer to a new WIC bitmap source representing this image. + /// The caller is responsible for releasing this image when done with it. /// /// - Throws: Any error that prevented the creation of the WIC bitmap. /// /// This function is not part of the public interface of the testing library. /// It may be removed in a future update. - static func _copyAttachableIWICBitmap( + static func _copyAttachableIWICBitmapSource( from imageAddress: UnsafeMutablePointer, using factory: UnsafeMutablePointer - ) throws -> UnsafeMutablePointer + ) throws -> UnsafeMutablePointer /// Make a copy of the instance of this type at the given address. /// @@ -84,7 +85,7 @@ public protocol _AttachableByAddressAsIWICBitmap { /// does not call this function. /// /// This function is not responsible for releasing the image returned from - /// `_copyAttachableIWICBitmap(from:using:)`. + /// `_copyAttachableIWICBitmapSource(from:using:)`. /// /// This function is not part of the public interface of the testing library. /// It may be removed in a future update. @@ -104,13 +105,14 @@ public protocol _AttachableByAddressAsIWICBitmap { /// /// - [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps) /// - [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons) -/// - [`IWICBitmap`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmap) +/// - [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) +/// (including its subclasses declared by Windows Imaging Component) /// /// You do not generally need to add your own conformances to this protocol. If /// you have an image in another format that needs to be attached to a test, /// first convert it to an instance of one of the types above. @_spi(Experimental) -public protocol AttachableAsIWICBitmap { +public protocol AttachableAsIWICBitmapSource { /// Create a WIC bitmap representing an instance of this type. /// /// - Parameters: @@ -124,9 +126,9 @@ public protocol AttachableAsIWICBitmap { /// /// This function is not part of the public interface of the testing library. /// It may be removed in a future update. - borrowing func _copyAttachableIWICBitmap( + borrowing func _copyAttachableIWICBitmapSource( using factory: UnsafeMutablePointer - ) throws -> UnsafeMutablePointer + ) throws -> UnsafeMutablePointer /// Make a copy of this instance. /// @@ -152,7 +154,7 @@ public protocol AttachableAsIWICBitmap { /// automatically invokes this function as needed. /// /// This function is not responsible for releasing the image returned from - /// `_copyAttachableIWICBitmap(using:)`. + /// `_copyAttachableIWICBitmapSource(using:)`. /// /// The default implementation of this function when `Self` conforms to /// `Sendable` does nothing. @@ -162,42 +164,7 @@ public protocol AttachableAsIWICBitmap { func _deinitializeAttachableValue() } -extension AttachableAsIWICBitmap { - /// Create a WIC bitmap representing an instance of this type and return it as - /// an instance of `IWICBitmapSource`. - /// - /// - Parameters: - /// - factory: A WIC imaging factory that can be used to create additional - /// WIC objects. - /// - /// - Returns: A pointer to a new WIC bitmap representing this image. The - /// caller is responsible for releasing this image when done with it. - /// - /// - Throws: Any error that prevented the creation of the WIC bitmap. - /// - /// This function is a convenience over `_copyAttachableIWICBitmap(using:)` - /// that casts the result of that function to `IWICBitmapSource` (as needed - /// by WIC when it encodes the image.) - borrowing func copyAttachableIWICBitmapSource( - using factory: UnsafeMutablePointer - ) throws -> UnsafeMutablePointer { - let bitmap = try _copyAttachableIWICBitmap(using: factory) - defer { - _ = bitmap.pointee.lpVtbl.pointee.Release(bitmap) - } - - return try withUnsafePointer(to: IID_IWICBitmapSource) { IID_IWICBitmapSource in - var bitmapSource: UnsafeMutableRawPointer? - let rQuery = bitmap.pointee.lpVtbl.pointee.QueryInterface(bitmap, IID_IWICBitmapSource, &bitmapSource) - guard rQuery == S_OK, let bitmapSource else { - throw ImageAttachmentError.queryInterfaceFailed(IWICBitmapSource.self, rQuery) - } - return bitmapSource.assumingMemoryBound(to: IWICBitmapSource.self) - } - } -} - -extension AttachableAsIWICBitmap where Self: Sendable { +extension AttachableAsIWICBitmapSource where Self: Sendable { public func _copyAttachableValue() -> Self { self } diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/Attachment+AttachableAsIWICBitmap.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/Attachment+AttachableAsIWICBitmapSource.swift similarity index 88% rename from Sources/Overlays/_Testing_WinSDK/Attachments/Attachment+AttachableAsIWICBitmap.swift rename to Sources/Overlays/_Testing_WinSDK/Attachments/Attachment+AttachableAsIWICBitmapSource.swift index b8ff6552e..5597ab1f4 100644 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/Attachment+AttachableAsIWICBitmap.swift +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/Attachment+AttachableAsIWICBitmapSource.swift @@ -27,11 +27,12 @@ extension Attachment where AttachableValue: ~Copyable { /// attachment. /// /// The following system-provided image types conform to the - /// ``AttachableAsIWICBitmap`` protocol and can be attached to a test: + /// ``AttachableAsIWICBitmapSource`` protocol and can be attached to a test: /// /// - [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps) /// - [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons) - /// - [`IWICBitmap`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmap) + /// - [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) + /// (including its subclasses declared by Windows Imaging Component) /// /// The testing library uses the image format specified by `imageFormat`. Pass /// `nil` to let the testing library decide which image format to use. If you @@ -66,11 +67,12 @@ extension Attachment where AttachableValue: ~Copyable { /// and immediately attaches it to the current test. /// /// The following system-provided image types conform to the - /// ``AttachableAsIWICBitmap`` protocol and can be attached to a test: + /// ``AttachableAsIWICBitmapSource`` protocol and can be attached to a test: /// /// - [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps) /// - [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons) - /// - [`IWICBitmap`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmap) + /// - [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) + /// (including its subclasses declared by Windows Imaging Component) /// /// The testing library uses the image format specified by `imageFormat`. Pass /// `nil` to let the testing library decide which image format to use. If you @@ -92,7 +94,7 @@ extension Attachment where AttachableValue: ~Copyable { } @_spi(Experimental) -extension Attachment where AttachableValue: AttachableWrapper, AttachableValue.Wrapped: AttachableAsIWICBitmap { +extension Attachment where AttachableValue: AttachableWrapper, AttachableValue.Wrapped: AttachableAsIWICBitmapSource { /// The image format to use when encoding the represented image. @_disfavoredOverload public var imageFormat: AttachableImageFormat? { diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/HBITMAP+AttachableAsIWICBitmap.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/HBITMAP+AttachableAsIWICBitmapSource.swift similarity index 83% rename from Sources/Overlays/_Testing_WinSDK/Attachments/HBITMAP+AttachableAsIWICBitmap.swift rename to Sources/Overlays/_Testing_WinSDK/Attachments/HBITMAP+AttachableAsIWICBitmapSource.swift index 296a971e6..0d11fd0bc 100644 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/HBITMAP+AttachableAsIWICBitmap.swift +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/HBITMAP+AttachableAsIWICBitmapSource.swift @@ -14,17 +14,17 @@ import Testing public import WinSDK @_spi(Experimental) -extension HBITMAP__: _AttachableByAddressAsIWICBitmap { - public static func _copyAttachableIWICBitmap( +extension HBITMAP__: _AttachableByAddressAsIWICBitmapSource { + public static func _copyAttachableIWICBitmapSource( from imageAddress: UnsafeMutablePointer, using factory: UnsafeMutablePointer - ) throws -> UnsafeMutablePointer { - var bitmap: UnsafeMutablePointer! + ) throws -> UnsafeMutablePointer { + var bitmap: UnsafeMutablePointer? let rCreate = factory.pointee.lpVtbl.pointee.CreateBitmapFromHBITMAP(factory, imageAddress, nil, WICBitmapUsePremultipliedAlpha, &bitmap) guard rCreate == S_OK, let bitmap else { throw ImageAttachmentError.comObjectCreationFailed(IWICBitmap.self, rCreate) } - return bitmap + return try bitmap.cast(to: IWICBitmapSource.self) } public static func _copyAttachableValue(at imageAddress: UnsafeMutablePointer) -> UnsafeMutablePointer { diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/HICON+AttachableAsIWICBitmap.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/HICON+AttachableAsIWICBitmapSource.swift similarity index 81% rename from Sources/Overlays/_Testing_WinSDK/Attachments/HICON+AttachableAsIWICBitmap.swift rename to Sources/Overlays/_Testing_WinSDK/Attachments/HICON+AttachableAsIWICBitmapSource.swift index caeb2b5f6..a25e8f371 100644 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/HICON+AttachableAsIWICBitmap.swift +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/HICON+AttachableAsIWICBitmapSource.swift @@ -14,17 +14,17 @@ import Testing public import WinSDK @_spi(Experimental) -extension HICON__: _AttachableByAddressAsIWICBitmap { - public static func _copyAttachableIWICBitmap( +extension HICON__: _AttachableByAddressAsIWICBitmapSource { + public static func _copyAttachableIWICBitmapSource( from imageAddress: UnsafeMutablePointer, using factory: UnsafeMutablePointer - ) throws -> UnsafeMutablePointer { - var bitmap: UnsafeMutablePointer! + ) throws -> UnsafeMutablePointer { + var bitmap: UnsafeMutablePointer? let rCreate = factory.pointee.lpVtbl.pointee.CreateBitmapFromHICON(factory, imageAddress, &bitmap) guard rCreate == S_OK, let bitmap else { throw ImageAttachmentError.comObjectCreationFailed(IWICBitmap.self, rCreate) } - return bitmap + return try bitmap.cast(to: IWICBitmapSource.self) } public static func _copyAttachableValue(at imageAddress: UnsafeMutablePointer) -> UnsafeMutablePointer { diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/IWICBitmap+AttachableAsIWICBitmap.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/IWICBitmap+AttachableAsIWICBitmap.swift deleted file mode 100644 index f5fcd4c26..000000000 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/IWICBitmap+AttachableAsIWICBitmap.swift +++ /dev/null @@ -1,35 +0,0 @@ -// -// This source file is part of the Swift.org open source project -// -// Copyright (c) 2024 Apple Inc. and the Swift project authors -// Licensed under Apache License v2.0 with Runtime Library Exception -// -// See https://swift.org/LICENSE.txt for license information -// See https://swift.org/CONTRIBUTORS.txt for Swift project authors -// - -#if os(Windows) -import Testing - -public import WinSDK - -@_spi(Experimental) -extension IWICBitmap: _AttachableByAddressAsIWICBitmap { - public static func _copyAttachableIWICBitmap( - from imageAddress: UnsafeMutablePointer, - using factory: UnsafeMutablePointer - ) throws -> UnsafeMutablePointer { - _ = imageAddress.pointee.lpVtbl.pointee.AddRef(imageAddress) - return imageAddress - } - - public static func _copyAttachableValue(at imageAddress: UnsafeMutablePointer) -> UnsafeMutablePointer { - _ = imageAddress.pointee.lpVtbl.pointee.AddRef(imageAddress) - return imageAddress - } - - public static func _deinitializeAttachableValue(at imageAddress: UnsafeMutablePointer) { - _ = imageAddress.pointee.lpVtbl.pointee.Release(imageAddress) - } -} -#endif diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/IWICBitmapSource+AttachableAsIWICBitmapSource.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/IWICBitmapSource+AttachableAsIWICBitmapSource.swift new file mode 100644 index 000000000..401e6f480 --- /dev/null +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/IWICBitmapSource+AttachableAsIWICBitmapSource.swift @@ -0,0 +1,131 @@ +// +// This source file is part of the Swift.org open source project +// +// Copyright (c) 2024 Apple Inc. and the Swift project authors +// Licensed under Apache License v2.0 with Runtime Library Exception +// +// See https://swift.org/LICENSE.txt for license information +// See https://swift.org/CONTRIBUTORS.txt for Swift project authors +// + +#if os(Windows) +import Testing + +public import WinSDK + +/// - Important: The casts in this file to `IUnknown` are safe insofar as we use +/// them to access fixed members of the COM vtable. The casts would become +/// unsafe if we allowed the resulting pointers to escape _and_ if any of the +/// types we use them on have multiple non-virtual inheritance to `IUnknown`. + +/// A protocol that identifies a type as a COM subclass of `IWICBitmapSource`. +/// +/// Because COM class inheritance is not visible in Swift, we must manually +/// apply conformances to this protocol to each COM type that inherits from +/// `IWICBitmapSource`. +/// +/// Because this protocol is not `public`, we must also explicitly restate +/// conformance to the public protocol `_AttachableByAddressAsIWICBitmapSource` +/// even though this protocol refines that one. This protocol refines +/// `_AttachableByAddressAsIWICBitmapSource` because otherwise the compiler will +/// not allow us to declare `public` members in its extension that provides the +/// implementation of `_AttachableByAddressAsIWICBitmapSource` below. +/// +/// This protocol is not part of the public interface of the testing library. It +/// allows us to reuse code across all subclasses of `IWICBitmapSource`. +protocol IWICBitmapSourceProtocol: _AttachableByAddressAsIWICBitmapSource {} + +@_spi(Experimental) +extension IWICBitmapSource: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICBitmap: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICBitmapClipper: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICBitmapFlipRotator: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICBitmapFrameDecode: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICBitmapScaler: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICColorTransform: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICFormatConverter: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +@_spi(Experimental) +extension IWICPlanarFormatConverter: _AttachableByAddressAsIWICBitmapSource, IWICBitmapSourceProtocol {} + +// MARK: - Upcasting conveniences + +extension UnsafeMutablePointer where Pointee: IWICBitmapSourceProtocol { + /// Upcast this WIC bitmap to a WIC bitmap source (its parent type). + /// + /// - Returns: `self`, cast to the parent type via `QueryInterface()`. The + /// caller is responsible for releasing the resulting object. + /// + /// - Throws: Any error that occurs while calling `QueryInterface()`. In + /// practice, this function is not expected to throw an error as it should + /// always be possible to cast a valid instance of `IWICBitmap` to + /// `IWICBitmapSource`. + /// + /// - Important: This function consumes a reference to `self` even if the cast + /// fails. + consuming func cast(to _: IWICBitmapSource.Type) throws -> UnsafeMutablePointer { + try self.withMemoryRebound(to: IUnknown.self, capacity: 1) { `self` in + defer { + _ = self.pointee.lpVtbl.pointee.Release(self) + } + + return try withUnsafePointer(to: IID_IWICBitmapSource) { IID_IWICBitmapSource in + var bitmapSource: UnsafeMutableRawPointer? + let rQuery = self.pointee.lpVtbl.pointee.QueryInterface(self, IID_IWICBitmapSource, &bitmapSource) + guard rQuery == S_OK, let bitmapSource else { + throw ImageAttachmentError.queryInterfaceFailed(IWICBitmapSource.self, rQuery) + } + return bitmapSource.assumingMemoryBound(to: IWICBitmapSource.self) + } + } + } +} + +// MARK: - _AttachableByAddressAsIWICBitmapSource implementation + +extension IWICBitmapSourceProtocol { + public static func _copyAttachableIWICBitmapSource( + from imageAddress: UnsafeMutablePointer, + using factory: UnsafeMutablePointer + ) throws -> UnsafeMutablePointer { + try _copyAttachableValue(at: imageAddress).cast(to: IWICBitmapSource.self) + } + + public static func _copyAttachableValue(at imageAddress: UnsafeMutablePointer) -> UnsafeMutablePointer { + imageAddress.withMemoryRebound(to: IUnknown.self, capacity: 1) { imageAddress in + _ = imageAddress.pointee.lpVtbl.pointee.AddRef(imageAddress) + } + return imageAddress + } + + public static func _deinitializeAttachableValue(at imageAddress: UnsafeMutablePointer) { + imageAddress.withMemoryRebound(to: IUnknown.self, capacity: 1) { imageAddress in + _ = imageAddress.pointee.lpVtbl.pointee.Release(imageAddress) + } + } +} + +extension IWICBitmapSource { + public static func _copyAttachableIWICBitmapSource( + from imageAddress: UnsafeMutablePointer, + using factory: UnsafeMutablePointer + ) throws -> UnsafeMutablePointer { + _ = imageAddress.pointee.lpVtbl.pointee.AddRef(imageAddress) + return imageAddress + } +} +#endif diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/UnsafeMutablePointer+AttachableAsIWICBitmap.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/UnsafeMutablePointer+AttachableAsIWICBitmapSource.swift similarity index 64% rename from Sources/Overlays/_Testing_WinSDK/Attachments/UnsafeMutablePointer+AttachableAsIWICBitmap.swift rename to Sources/Overlays/_Testing_WinSDK/Attachments/UnsafeMutablePointer+AttachableAsIWICBitmapSource.swift index c957cf40a..0bfa354f4 100644 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/UnsafeMutablePointer+AttachableAsIWICBitmap.swift +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/UnsafeMutablePointer+AttachableAsIWICBitmapSource.swift @@ -14,9 +14,9 @@ import Testing public import WinSDK @_spi(Experimental) -extension UnsafeMutablePointer: AttachableAsIWICBitmap where Pointee: _AttachableByAddressAsIWICBitmap { - public func _copyAttachableIWICBitmap(using factory: UnsafeMutablePointer) throws -> UnsafeMutablePointer { - try Pointee._copyAttachableIWICBitmap(from: self, using: factory) +extension UnsafeMutablePointer: AttachableAsIWICBitmapSource where Pointee: _AttachableByAddressAsIWICBitmapSource { + public func _copyAttachableIWICBitmapSource(using factory: UnsafeMutablePointer) throws -> UnsafeMutablePointer { + try Pointee._copyAttachableIWICBitmapSource(from: self, using: factory) } public func _copyAttachableValue() -> Self { diff --git a/Sources/Overlays/_Testing_WinSDK/Attachments/_AttachableImageWrapper.swift b/Sources/Overlays/_Testing_WinSDK/Attachments/_AttachableImageWrapper.swift index 09fe7554e..63931c378 100644 --- a/Sources/Overlays/_Testing_WinSDK/Attachments/_AttachableImageWrapper.swift +++ b/Sources/Overlays/_Testing_WinSDK/Attachments/_AttachableImageWrapper.swift @@ -18,15 +18,16 @@ internal import WinSDK /// /// You do not need to use this type directly. Instead, initialize an instance /// of ``Attachment`` using an instance of an image type that conforms to -/// ``AttachableAsIWICBitmap``. The following system-provided image types -/// conform to the ``AttachableAsIWICBitmap`` protocol and can be attached to a -/// test: +/// ``AttachableAsIWICBitmapSource``. The following system-provided image types +/// conform to the ``AttachableAsIWICBitmapSource`` protocol and can be attached +/// to a test: /// /// - [`HBITMAP`](https://learn.microsoft.com/en-us/windows/win32/gdi/bitmaps) /// - [`HICON`](https://learn.microsoft.com/en-us/windows/win32/menurc/icons) -/// - [`IWICBitmap`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmap) +/// - [`IWICBitmapSource`](https://learn.microsoft.com/en-us/windows/win32/api/wincodec/nn-wincodec-iwicbitmapsource) +/// (including its subclasses declared by Windows Imaging Component) @_spi(Experimental) -public final class _AttachableImageWrapper: Sendable where Image: AttachableAsIWICBitmap { +public final class _AttachableImageWrapper: Sendable where Image: AttachableAsIWICBitmapSource { /// The underlying image. nonisolated(unsafe) let image: Image @@ -70,7 +71,7 @@ extension _AttachableImageWrapper: AttachableWrapper { } // Create the bitmap and downcast it to an IWICBitmapSource for later use. - let bitmap = try image.copyAttachableIWICBitmapSource(using: factory) + let bitmap = try image._copyAttachableIWICBitmapSource(using: factory) defer { _ = bitmap.pointee.lpVtbl.pointee.Release(bitmap) } diff --git a/Tests/TestingTests/AttachmentTests.swift b/Tests/TestingTests/AttachmentTests.swift index 8604e05c3..e26dbe595 100644 --- a/Tests/TestingTests/AttachmentTests.swift +++ b/Tests/TestingTests/AttachmentTests.swift @@ -775,7 +775,7 @@ extension AttachmentTests { Attachment.record(loFi) } - @MainActor @Test func attachIWICBitmap() throws { + private func copyIWICBitmap() throws -> UnsafeMutablePointer { let factory = try IWICImagingFactory.create() defer { _ = factory.pointee.lpVtbl.pointee.Release(factory) @@ -791,6 +791,11 @@ extension AttachmentTests { guard rCreate == S_OK, let wicBitmap else { throw ImageAttachmentError.comObjectCreationFailed(IWICBitmap.self, rCreate) } + return wicBitmap + } + + @MainActor @Test func attachIWICBitmap() throws { + let wicBitmap = try copyIWICBitmap() defer { _ = wicBitmap.pointee.lpVtbl.pointee.Release(wicBitmap) } @@ -802,6 +807,19 @@ extension AttachmentTests { Attachment.record(attachment) } + @MainActor @Test func attachIWICBitmapSource() throws { + let wicBitmapSource = try copyIWICBitmap().cast(to: IWICBitmapSource.self) + defer { + _ = wicBitmapSource.pointee.lpVtbl.pointee.Release(wicBitmapSource) + } + + let attachment = Attachment(wicBitmapSource, named: "diamond.png") + try attachment.withUnsafeBytes { buffer in + #expect(buffer.count > 32) + } + Attachment.record(attachment) + } + @MainActor @Test func pathExtensionAndCLSID() { let pngCLSID = AttachableImageFormat.png.clsid let pngFilename = AttachableImageFormat.appendPathExtension(for: pngCLSID, to: "example")