onevcat 4 лет назад
Родитель
Сommit
e815bb5c63
2 измененных файлов с 68 добавлено и 25 удалено
  1. 54 13
      Sources/Image/ImageDrawing.swift
  2. 14 12
      Sources/Image/ImageProcessor.swift

+ 54 - 13
Sources/Image/ImageDrawing.swift

@@ -101,6 +101,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
     #endif
     
     // MARK: Round Corner
+    
     /// Creates a round corner image from on `base` image.
     ///
     /// - Parameters:
@@ -112,11 +113,14 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
     ///
     /// - Note: This method only works for CG-based image. The current image scale is kept.
     ///         For any non-CG-based image, `base` itself is returned.
-    public func image(withRoundRadius radius: CGFloat,
-                      fit size: CGSize,
-                      roundingCorners corners: RectCorner = .all,
-                      backgroundColor: KFCrossPlatformColor? = nil) -> KFCrossPlatformImage
+    public func image(
+        withRadius radius: Radius,
+        fit size: CGSize,
+        roundingCorners corners: RectCorner = .all,
+        backgroundColor: KFCrossPlatformColor? = nil
+    ) -> KFCrossPlatformImage
     {
+
         guard let _ = cgImage else {
             assertionFailure("[Kingfisher] Round corner image only works for CG-based image.")
             return base
@@ -131,8 +135,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
                 rectPath.fill()
             }
             
-            let path = NSBezierPath(roundedRect: rect, byRoundingCorners: corners, radius: radius)
-            path.windingRule = .evenOdd
+            let path = pathForRoundCorner(rect: rect, radius: radius, corners: corners, refRect: rect)
             path.addClip()
             base.draw(in: rect)
             #else
@@ -147,11 +150,7 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
                 rectPath.fill()
             }
             
-            let path = UIBezierPath(
-                roundedRect: rect,
-                byRoundingCorners: corners.uiRectCorner,
-                cornerRadii: CGSize(width: radius, height: radius)
-            )
+            let path = pathForRoundCorner(rect: rect, radius: radius, corners: corners, refRect: rect)
             context.addPath(path.cgPath)
             context.clip()
             base.draw(in: rect)
@@ -160,6 +159,44 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
         }
     }
     
+    /// Creates a round corner image from on `base` image.
+    ///
+    /// - Parameters:
+    ///   - radius: The round corner radius of creating image.
+    ///   - size: The target size of creating image.
+    ///   - corners: The target corners which will be applied rounding.
+    ///   - backgroundColor: The background color for the output image
+    /// - Returns: An image with round corner of `self`.
+    ///
+    /// - Note: This method only works for CG-based image. The current image scale is kept.
+    ///         For any non-CG-based image, `base` itself is returned.
+    public func image(
+        withRoundRadius radius: CGFloat,
+        fit size: CGSize,
+        roundingCorners corners: RectCorner = .all,
+        backgroundColor: KFCrossPlatformColor? = nil
+    ) -> KFCrossPlatformImage
+    {
+        image(withRadius: .point(radius), fit: size, roundingCorners: corners, backgroundColor: backgroundColor)
+    }
+    
+    #if os(macOS)
+    func pathForRoundCorner(rect: CGRect, radius: Radius, corners: RectCorner) -> NSBezierPath {
+        let path = NSBezierPath(roundedRect: rect, byRoundingCorners: corners, radius: radius)
+        path.windingRule = .evenOdd
+        return path
+    }
+    #else
+    func pathForRoundCorner(rect: CGRect, radius: Radius, corners: RectCorner, refRect: CGRect) -> UIBezierPath {
+        let cornerRadius = radius.compute(with: rect.size)
+        return UIBezierPath(
+            roundedRect: rect,
+            byRoundingCorners: corners.uiRectCorner,
+            cornerRadii: CGSize(width: cornerRadius / (refRect.width / rect.width), height: cornerRadius / (refRect.height / rect.height))
+        )
+    }
+    #endif
+    
     #if os(iOS) || os(tvOS)
     func resize(to size: CGSize, for contentMode: UIView.ContentMode) -> KFCrossPlatformImage {
         switch contentMode {
@@ -344,9 +381,13 @@ extension KingfisherWrapper where Base: KFCrossPlatformImage {
             let strokeRect =  rect.insetBy(dx: border.lineWidth / 2, dy: border.lineWidth / 2)
             context.setStrokeColor(border.color.cgColor)
             
-            let line: UIBezierPath = .init(ovalIn: strokeRect)
+            let line = pathForRoundCorner(
+                rect: strokeRect,
+                radius: border.radius,
+                corners: border.roundingCorners,
+                refRect: rect
+            )
             line.lineWidth = border.lineWidth
-            
             line.stroke()
             
             return false

+ 14 - 12
Sources/Image/ImageProcessor.swift

@@ -324,6 +324,19 @@ public enum Radius {
             return p.description
         }
     }
+    
+    public func compute(with size: CGSize) -> CGFloat {
+        let cornerRadius: CGFloat
+        switch self {
+        case .point(let point):
+            cornerRadius = point
+        case .widthFraction(let widthFraction):
+            cornerRadius = size.width * widthFraction
+        case .heightFraction(let heightFraction):
+            cornerRadius = size.height * heightFraction
+        }
+        return cornerRadius
+    }
 }
 
 /// Processor for making round corner images. Only CG-based images are supported in macOS, 
@@ -439,20 +452,9 @@ public struct RoundCornerImageProcessor: ImageProcessor {
         switch item {
         case .image(let image):
             let size = targetSize ?? image.kf.size
-
-            let cornerRadius: CGFloat
-            switch radius {
-            case .point(let point):
-                cornerRadius = point
-            case .widthFraction(let widthFraction):
-                cornerRadius = size.width * widthFraction
-            case .heightFraction(let heightFraction):
-                cornerRadius = size.height * heightFraction
-            }
-
             return image.kf.scaled(to: options.scaleFactor)
                         .kf.image(
-                            withRoundRadius: cornerRadius,
+                            withRadius: radius,
                             fit: size,
                             roundingCorners: roundingCorners,
                             backgroundColor: backgroundColor)