From 8b5520a573a0bd5204ee9a8cc809c2da0173fa2a Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Tue, 28 Nov 2023 17:07:57 +0800 Subject: [PATCH 1/2] Added the SymbolRenderingMode support for WebImage from SwiftUI --- SDWebImageSwiftUI/Classes/WebImage.swift | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/SDWebImageSwiftUI/Classes/WebImage.swift b/SDWebImageSwiftUI/Classes/WebImage.swift index 457b6e63..892b42a5 100644 --- a/SDWebImageSwiftUI/Classes/WebImage.swift +++ b/SDWebImageSwiftUI/Classes/WebImage.swift @@ -353,6 +353,13 @@ extension WebImage { configure { $0.renderingMode(renderingMode) } } + /// Sets the rendering mode for symbol images within this view. + /// - Parameter mode: The symbol rendering mode to use + @available(iOS 15.0, OSX 12.0, tvOS 15.0, watchOS 8.0, *) + public func symbolRenderingMode(_ mode: SymbolRenderingMode?) -> WebImage { + configure { $0.symbolRenderingMode(mode) } + } + /// Configurate this view's image interpolation quality /// - Parameter interpolation: The interpolation quality public func interpolation(_ interpolation: Image.Interpolation) -> WebImage { From 60feef8c99811b09e7baf895659c10024f450078 Mon Sep 17 00:00:00 2001 From: DreamPiggy Date: Wed, 29 Nov 2023 00:05:15 +0800 Subject: [PATCH 2/2] [Temp] Added SymbolRenderingMode for AnimatedImage I don't think WebImage/AnimatedImage will support symbol image, draft --- .../SDWebImageSwiftUIDemo/ContentView.swift | 2 + SDWebImageSwiftUI/Classes/AnimatedImage.swift | 61 +++++++++++++++++-- 2 files changed, 59 insertions(+), 4 deletions(-) diff --git a/Example/SDWebImageSwiftUIDemo/ContentView.swift b/Example/SDWebImageSwiftUIDemo/ContentView.swift index ba4215da..2409fe46 100644 --- a/Example/SDWebImageSwiftUIDemo/ContentView.swift +++ b/Example/SDWebImageSwiftUIDemo/ContentView.swift @@ -118,7 +118,9 @@ struct ContentView: View { } else { WebImage(url: URL(string:url)) .resizable() + .renderingMode(.template) .indicator(.activity) + .foregroundColor(.red) .transition(.fade(duration: 0.5)) .scaledToFit() .frame(width: CGFloat(100), height: CGFloat(100), alignment: .center) diff --git a/SDWebImageSwiftUI/Classes/AnimatedImage.swift b/SDWebImageSwiftUI/Classes/AnimatedImage.swift index 4a4498ef..2614e847 100644 --- a/SDWebImageSwiftUI/Classes/AnimatedImage.swift +++ b/SDWebImageSwiftUI/Classes/AnimatedImage.swift @@ -78,6 +78,7 @@ final class AnimatedImageLayout : ObservableObject { var capInsets: EdgeInsets = EdgeInsets() var resizingMode: Image.ResizingMode? var renderingMode: Image.TemplateRenderingMode? + var symbolRenderingMode: AnimatedImage.SymbolRenderingMode? var interpolation: Image.Interpolation? var antialiased: Bool = false } @@ -101,6 +102,18 @@ final class AnimatedImageConfiguration: ObservableObject { /// A Image View type to load image from url, data or bundle. Supports animated and static image format. @available(iOS 14.0, OSX 11.0, tvOS 14.0, watchOS 7.0, *) public struct AnimatedImage : PlatformViewRepresentable { + /// A symbol rendering mode. This match `SwiftUI.SymbolRenderingMode` + public enum SymbolRenderingMode { + /// A mode that renders symbols as multiple layers, with different opacities applied to the foreground style. + case hierarchical + /// A mode that renders symbols as a single layer filled with the foreground style. + case monochrome + /// A mode that renders symbols as multiple layers with their inherit styles. + case multicolor + /// A mode that renders symbols as multiple layers, with different styles applied to the layers. + case palette + } + @ObservedObject var imageModel: AnimatedImageModel @ObservedObject var imageHandler = AnimatedImageHandler() @ObservedObject var imageLayout = AnimatedImageLayout() @@ -435,7 +448,6 @@ public struct AnimatedImage : PlatformViewRepresentable { #else image = image.resizableImage(withCapInsets: capInsets, resizingMode: .stretch) #endif - view.wrapped.image = image case .tile: #if os(macOS) image.resizingMode = .tile @@ -443,7 +455,6 @@ public struct AnimatedImage : PlatformViewRepresentable { #else image = image.resizableImage(withCapInsets: capInsets, resizingMode: .tile) #endif - view.wrapped.image = image @unknown default: // Future cases, not implements break @@ -459,19 +470,34 @@ public struct AnimatedImage : PlatformViewRepresentable { #else image = image.withRenderingMode(.alwaysTemplate) #endif - view.wrapped.image = image case .original: #if os(macOS) image.isTemplate = false #else image = image.withRenderingMode(.alwaysOriginal) #endif - view.wrapped.image = image @unknown default: // Future cases, not implements break } } + + // Symbol Configuration + if let mode = imageLayout.symbolRenderingMode { + if #available(iOS 15.0, *) { + let symbolConfiguration = createSymbolConfiguration(mode, view.tintColor, view.backgroundColor) + image = image.applyingSymbolConfiguration(symbolConfiguration) ?? image + } else { + // Fallback on earlier versions + } + } + + // Only update when needed + if image !== view.wrapped.image { + view.wrapped.image = image + } else { + print("Equal") + } } // Interpolation @@ -499,6 +525,25 @@ public struct AnimatedImage : PlatformViewRepresentable { view.invalidateIntrinsicContentSize() } + @available(iOS 15.0, *) + private func createSymbolConfiguration(_ mode: AnimatedImage.SymbolRenderingMode, _ primary: UIColor?, _ secondary: UIColor?) -> UIImage.SymbolConfiguration { + switch mode { + case .hierarchical: + return .init(hierarchicalColor: primary!) + case .monochrome: + if #available(iOS 16.0, *) { + return .preferringMonochrome() + } else { + // Fallback on earlier versions + return .init(hierarchicalColor: .black) + } + case .multicolor: + return .preferringMulticolor() + case .palette: + return .init(paletteColors: [primary!, secondary!]) + } + } + func configureView(_ view: AnimatedImageViewWrapper, context: Context) { // IncrementalLoad if let incrementalLoad = imageConfiguration.incrementalLoad { @@ -586,6 +631,14 @@ extension AnimatedImage { return self } + /// Sets the rendering mode for symbol images within this view. + /// - Parameter mode: The symbol rendering mode to use + @available(iOS 15.0, OSX 12.0, tvOS 15.0, watchOS 8.0, *) + public func symbolRenderingMode(_ mode: AnimatedImage.SymbolRenderingMode?) -> AnimatedImage { + self.imageLayout.symbolRenderingMode = mode + return self + } + /// Configurate this view's image interpolation quality /// - Parameter interpolation: The interpolation quality public func interpolation(_ interpolation: Image.Interpolation) -> AnimatedImage {