Skip to content

Commit

Permalink
Fixed a bug where the application crashes when the area is large.
Browse files Browse the repository at this point in the history
  • Loading branch information
shogo4405 committed Jul 24, 2024
1 parent c78257d commit e646939
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 8 deletions.
4 changes: 3 additions & 1 deletion Sources/Screen/Screen.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ protocol ScreenObserver: AnyObject {

/// An object that manages offscreen rendering a foundation.
public final class Screen: ScreenObjectContainerConvertible {
static let size = CGSize(width: 1280, height: 720)
private static let lockFrags = CVPixelBufferLockFlags(rawValue: 0)

/// The total of child counts.
Expand All @@ -42,11 +43,12 @@ public final class Screen: ScreenObjectContainerConvertible {
}

/// Specifies the video size to use when output a video.
public var size: CGSize = .init(width: 1280, height: 720) {
public var size: CGSize = Screen.size {
didSet {
guard size != oldValue else {
return
}
renderer.bounds = .init(origin: .zero, size: size)
CVPixelBufferPoolCreate(nil, nil, attributes as CFDictionary?, &pixelBufferPool)
}
}
Expand Down
36 changes: 30 additions & 6 deletions Sources/Screen/ScreenObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -153,22 +153,46 @@ public final class ImageScreenObject: ScreenObject {
guard cgImage != oldValue else {
return
}
if let cgImage {
size = cgImage.size
}
invalidateLayout()
}
}

override public func makeImage(_ renderer: some ScreenRenderer) -> CGImage? {
return cgImage
let intersection = bounds.intersection(renderer.bounds)

guard bounds != intersection else {
return cgImage
}

// Handling when the drawing area is exceeded.
let x: CGFloat
switch horizontalAlignment {
case .left:
x = bounds.origin.x
case .center:
x = bounds.origin.x / 2
case .right:
x = 0.0
}

let y: CGFloat
switch verticalAlignment {
case .top:
y = 0.0
case .middle:
y = abs(bounds.origin.y) / 2
case .bottom:
y = abs(bounds.origin.y)
}

return cgImage?.cropping(to: .init(origin: .init(x: x, y: y), size: intersection.size))
}

override public func makeBounds(_ size: CGSize) -> CGRect {
guard let cgImage else {
return super.makeBounds(self.size)
return super.makeBounds(size)
}
return super.makeBounds(cgImage.size)
return super.makeBounds(size == .zero ? cgImage.size : size)
}
}

Expand Down
7 changes: 6 additions & 1 deletion Sources/Screen/ScreenRenderer.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ public protocol ScreenRenderer: AnyObject {
var context: CIContext { get }
/// Specifies the backgroundColor for output video.
var backgroundColor: CGColor { get set }
/// The current screen bounds.
var bounds: CGRect { get }
/// Layouts a screen object.
func layout(_ screenObject: ScreenObject)
/// Draws a sceen object.
Expand All @@ -18,6 +20,8 @@ public protocol ScreenRenderer: AnyObject {
}

final class ScreenRendererByCPU: ScreenRenderer {
var bounds: CGRect = .init(origin: .zero, size: Screen.size)

lazy var context = {
guard let deive = MTLCreateSystemDefaultDevice() else {
return CIContext(options: nil)
Expand Down Expand Up @@ -142,7 +146,8 @@ final class ScreenRendererByCPU: ScreenRenderer {
}

let origin = screenObject.bounds.origin
let start = Int(origin.y) * canvas.rowBytes + Int(origin.x) * 4
let start = Int(max(0, origin.y)) * canvas.rowBytes + Int(max(0, origin.x)) * 4

var destination = vImage_Buffer(
data: canvas.data.advanced(by: start),
height: image.height,
Expand Down

0 comments on commit e646939

Please sign in to comment.