Skip to content

Commit

Permalink
Sources update
Browse files Browse the repository at this point in the history
commit_hash:1eed8ce8d0aa934f6ad22ae494bac4645dea378d
  • Loading branch information
booster committed Oct 29, 2024
1 parent acda693 commit 6353b89
Show file tree
Hide file tree
Showing 15 changed files with 414 additions and 27 deletions.
3 changes: 3 additions & 0 deletions .mapping.json
Original file line number Diff line number Diff line change
Expand Up @@ -448,6 +448,7 @@
"VGSLUI/extensions/CGPointExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/CGPointExtensions.swift",
"VGSLUI/extensions/CGRectExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/CGRectExtensions.swift",
"VGSLUI/extensions/CGSizeExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/CGSizeExtensions.swift",
"VGSLUI/extensions/CGVectorExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/CGVectorExtensions.swift",
"VGSLUI/extensions/ColorExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/ColorExtensions.swift",
"VGSLUI/extensions/EdgeInsetsExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/EdgeInsetsExtensions.swift",
"VGSLUI/extensions/ImageExtensions.swift":"mobile/vgsl/public/VGSLUI/extensions/ImageExtensions.swift",
Expand Down Expand Up @@ -504,9 +505,11 @@
"VGSLUI/typo/AttributedStringLayout.swift":"mobile/vgsl/public/VGSLUI/typo/AttributedStringLayout.swift",
"VGSLUI/typo/BackgroundAttribute.swift":"mobile/vgsl/public/VGSLUI/typo/BackgroundAttribute.swift",
"VGSLUI/typo/BorderAttribute.swift":"mobile/vgsl/public/VGSLUI/typo/BorderAttribute.swift",
"VGSLUI/typo/CloudBackgroundAttribute.swift":"mobile/vgsl/public/VGSLUI/typo/CloudBackgroundAttribute.swift",
"VGSLUI/typo/FontExtensions.swift":"mobile/vgsl/public/VGSLUI/typo/FontExtensions.swift",
"VGSLUI/typo/FontSettings.swift":"mobile/vgsl/public/VGSLUI/typo/FontSettings.swift",
"VGSLUI/typo/FontSpecifying.swift":"mobile/vgsl/public/VGSLUI/typo/FontSpecifying.swift",
"VGSLUI/typo/StringAttribute.swift":"mobile/vgsl/public/VGSLUI/typo/StringAttribute.swift",
"VGSLUI/typo/Typo.swift":"mobile/vgsl/public/VGSLUI/typo/Typo.swift",
"VGSLUI/uikit/CALayerExtensions.swift":"mobile/vgsl/public/VGSLUI/uikit/CALayerExtensions.swift",
"VGSLUI/uikit/CAMediaTimingFunction.swift":"mobile/vgsl/public/VGSLUI/uikit/CAMediaTimingFunction.swift",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import Foundation

@objc(YXAsyncOperation)
open class AsyncOperation: Operation {
open class AsyncOperation: Operation, @unchecked Sendable {
private var _isExecuting = false
private var _isFinished = false
private lazy var lock = NSRecursiveLock()
Expand Down
3 changes: 2 additions & 1 deletion VGSLFundamentals/concurrency/operations/OperationQueue.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ extension OperationQueue: OperationQueueType {
}
}

private final class SerialOperationQueueImpl: OperationQueue, SerialOperationQueue {
private final class SerialOperationQueueImpl: OperationQueue, SerialOperationQueue,
@unchecked Sendable {
override init() {
super.init()
maxConcurrentOperationCount = 1
Expand Down
4 changes: 4 additions & 0 deletions VGSLFundamentals/extensions/EncodableExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,8 @@ extension Encodable {
let data = try JSONEncoder().encode(self)
return String(data: data, encoding: .utf8)!
}

public func jsonData() throws -> Data {
try JSONEncoder().encode(self)
}
}
2 changes: 1 addition & 1 deletion VGSLNetworking/NetworkActivityOperation.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ public enum NetworkActivityOperationErrorCode: Int {
case failedToCreateResource
}

public final class NetworkActivityOperation<Response>: AsyncOperation {
public final class NetworkActivityOperation<Response>: AsyncOperation, @unchecked Sendable {
public typealias ResourceFactory = Variable<Resource<Response>?>
public typealias Request = (
URL,
Expand Down
2 changes: 1 addition & 1 deletion VGSLNetworking/URLRequestPerforming.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ public protocol NetworkTask: AnyObject, Cancellable {
func resume()
}

extension URLSessionTask: NetworkTask {}
extension Foundation.URLSessionTask: VGSLNetworking.NetworkTask {}

public typealias URLRequestCompletionHandler = (Result<(Data, HTTPURLResponse), NSError>) -> Void

Expand Down
112 changes: 112 additions & 0 deletions VGSLUI/extensions/CGContextExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,116 @@ extension CGContext {
block()
restoreGState()
}

/// Draws a non-convex polygon with rounded corners and fills it with a specified color.
///
/// This method takes a series of points defining a non-convex polygon and renders it onto the
/// current graphics context
/// with rounded corners. The corners are rounded with the specified radius, and the entire shape
/// is filled with the provided color.
///
/// - Parameters:
/// - points: An array of `CGPoint` representing the vertices of the non-convex polygon. The
/// points should be ordered in a
/// way that consecutive points define the edges of the polygon. The polygon is
/// automatically closed from the
/// last point back to the first.
/// - cornerRadius: A `CGFloat` indicating the radius for rounding the corners of the polygon.
/// The radius should not exceed
/// half the length of the shortest edge to avoid overlapping arcs.
/// - backgroundColor: A `Color` to use for filling the polygon. This color will be applied to
/// the entire interior
/// of the shape, following the rounding of the corners.
public func drawCloud(
points: [CGPoint],
cornerRadius: CGFloat,
backgroundColor: Color
) {
guard points.count >= 3 else { return }

let path = BezierPath()

for i in 0..<(points.count) {
let currentPoint = points[i]
let nextPoint = points[(i + 1) % (points.count)]
let afterNextPoint = points[(i + 2) % (points.count)]

guard !arePointsCollinear(p1: currentPoint, p2: nextPoint, p3: afterNextPoint) else {
continue
}
// In the code below, we make a rounded line from a right angle. To do this, we find the
// maximum possible radius, the point lying on the angle bisector, and the angles for the
// corresponding rounding.
let vector1 = CGVector(currentPoint, nextPoint)
let vector2 = CGVector(nextPoint, afterNextPoint)

let cornerRadius: CGFloat = min(cornerRadius, vector1.length / 2, vector2.length / 2)
let lineEnd = CGPoint(
x: nextPoint.x - vector1.normalized.dx * cornerRadius,
y: nextPoint.y - vector1.normalized.dy * cornerRadius
)
path.addLine(to: lineEnd)
let cornerCenter = calculatePointOnBisector(
vertex: nextPoint,
pointOnLine1: currentPoint,
pointOnLine2: afterNextPoint,
dx: cornerRadius,
dy: cornerRadius
)

let clockwise = vector1.isClockwised(vector2)
let startAngle =
if vector1.dy.isApproximatelyEqualTo(0, withAccuracy: 1e-3) {
if cornerCenter.y > currentPoint.y {
-Double.pi / 2
} else {
Double.pi / 2
}
} else {
if cornerCenter.x > currentPoint.x {
-Double.pi
} else {
0.0
}
}
var endAngle: Double = (startAngle + Double.pi * 2 + (clockwise ? .pi / 2 : -.pi / 2))
.truncatingRemainder(dividingBy: Double.pi * 2)
endAngle = endAngle > .pi ? endAngle - 2 * .pi : endAngle

#if os(iOS)
path.addArc(
withCenter: cornerCenter,
radius: cornerRadius,
startAngle: startAngle,
endAngle: endAngle,
clockwise: clockwise
)
#endif
}
addPath(path.cgPath)
setFillColor(backgroundColor.cgColor)
fillPath()
}
}

func calculatePointOnBisector(
vertex: CGPoint,
pointOnLine1: CGPoint,
pointOnLine2: CGPoint,
dx: CGFloat,
dy: CGFloat
) -> CGPoint {
let vector1 = CGVector(vertex, pointOnLine1).normalized
let vector2 = CGVector(vertex, pointOnLine2).normalized

return CGPoint(
x: vertex.x + vector1.dx * dx + vector2.dx * dy,
y: vertex.y + vector1.dy * dx + vector2.dy * dy
)
}

func arePointsCollinear(p1: CGPoint, p2: CGPoint, p3: CGPoint) -> Bool {
let vector1 = CGVector(p1, p2)
let vector2 = CGVector(p2, p3)
return vector1.crossProductMagnitude(vector2).isApproximatelyEqualTo(0)
}
2 changes: 1 addition & 1 deletion VGSLUI/extensions/CGPointExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ public func -(lhs: CGPoint, rhs: CGFloat) -> CGPoint {
CGPoint(x: lhs.x - rhs, y: lhs.y - rhs)
}

extension CGPoint: Hashable {
extension CoreFoundation.CGPoint: Swift.Hashable {
public func hash(into hasher: inout Hasher) {
x.hash(into: &hasher)
y.hash(into: &hasher)
Expand Down
2 changes: 1 addition & 1 deletion VGSLUI/extensions/CGSizeExtensions.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import Foundation

import VGSLFundamentals

extension CGSize: Hashable {
extension CoreFoundation.CGSize: Swift.Hashable {
public static var infinite: CGSize {
CGSize(width: CGFloat.infinity, height: CGFloat.infinity)
}
Expand Down
35 changes: 35 additions & 0 deletions VGSLUI/extensions/CGVectorExtensions.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright 2024 Yandex LLC. All rights reserved.
import Foundation

import VGSLFundamentals

extension CGVector {
public init(_ point: CGPoint) {
self.init(dx: point.x, dy: point.y)
}

public init(_ point1: CGPoint, _ point2: CGPoint) {
self.init(dx: point2.x - point1.x, dy: point2.y - point1.y)
}

public func crossProductMagnitude(_ vector2: CGVector) -> CGFloat {
dx * vector2.dy - dy * vector2.dx
}

public func dotProduct(_ vector2: CGVector) -> CGFloat {
dx * vector2.dx + dy * vector2.dy
}

public var length: CGFloat {
sqrt(dotProduct(self))
}

public var normalized: CGVector {
let length = self.length
return CGVector(CGPoint(x: dx / length, y: dy / length))
}

public func isClockwised(_ vector2: CGVector) -> Bool {
crossProductMagnitude(vector2) > 0
}
}
Loading

0 comments on commit 6353b89

Please sign in to comment.