Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
52e36b5c5a | ||
|
|
a74a86d001 | ||
|
|
f50057d951 |
@@ -118,15 +118,18 @@ final class ScreenCapture {
|
|||||||
|
|
||||||
@available(macOS 14.0, *)
|
@available(macOS 14.0, *)
|
||||||
private func crop(_ image: CGImage, to cgRect: CGRect, display: SCDisplay) -> CGImage? {
|
private func crop(_ image: CGImage, to cgRect: CGRect, display: SCDisplay) -> CGImage? {
|
||||||
// cgRect is already in SCDisplay space (Y flipped relative to AppKit).
|
// cgRect is in SCDisplay space (bottom-left origin, Y flipped vs AppKit).
|
||||||
// Derive the pixel scale from the image we actually got, relative to
|
// The captured image has a TOP-LEFT origin. So within the display,
|
||||||
// the display's point frame.
|
// we must flip Y: pixelY = displayHeight - (cgY - displayMinY) - cgHeight.
|
||||||
let scaleX = CGFloat(image.width) / display.frame.width
|
let scaleX = CGFloat(image.width) / display.frame.width
|
||||||
let scaleY = CGFloat(image.height) / display.frame.height
|
let scaleY = CGFloat(image.height) / display.frame.height
|
||||||
guard scaleX > 0, scaleY > 0 else { return nil }
|
guard scaleX > 0, scaleY > 0 else { return nil }
|
||||||
|
let localMinX = cgRect.minX - display.frame.minX
|
||||||
|
let localMaxY = cgRect.maxY - display.frame.minY
|
||||||
|
let flippedY = display.frame.height - localMaxY
|
||||||
let pxRect = CGRect(
|
let pxRect = CGRect(
|
||||||
x: (cgRect.minX - display.frame.minX) * scaleX,
|
x: localMinX * scaleX,
|
||||||
y: (cgRect.minY - display.frame.minY) * scaleY,
|
y: flippedY * scaleY,
|
||||||
width: cgRect.width * scaleX,
|
width: cgRect.width * scaleX,
|
||||||
height: cgRect.height * scaleY
|
height: cgRect.height * scaleY
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -94,6 +94,8 @@ final class CaptureModel: ObservableObject {
|
|||||||
@Published var strokes: [[CGPoint]] = []
|
@Published var strokes: [[CGPoint]] = []
|
||||||
/// Whether the pen is active (drag draws instead of selecting)
|
/// Whether the pen is active (drag draws instead of selecting)
|
||||||
@Published var isDrawing = false
|
@Published var isDrawing = false
|
||||||
|
/// Current drawing color
|
||||||
|
@Published var drawColor: NSColor = .systemRed
|
||||||
|
|
||||||
enum CaptureMode {
|
enum CaptureMode {
|
||||||
case screenshot
|
case screenshot
|
||||||
@@ -120,7 +122,7 @@ final class CaptureModel: ObservableObject {
|
|||||||
let ctx = NSGraphicsContext.current!.cgContext
|
let ctx = NSGraphicsContext.current!.cgContext
|
||||||
// CGImage draws with a flipped Y in NSGraphicsContext
|
// CGImage draws with a flipped Y in NSGraphicsContext
|
||||||
ctx.draw(image, in: NSRect(origin: .zero, size: size))
|
ctx.draw(image, in: NSRect(origin: .zero, size: size))
|
||||||
NSColor.systemRed.setStroke()
|
drawColor.setStroke()
|
||||||
ctx.setLineWidth(3)
|
ctx.setLineWidth(3)
|
||||||
ctx.setLineCap(.round)
|
ctx.setLineCap(.round)
|
||||||
ctx.setLineJoin(.round)
|
ctx.setLineJoin(.round)
|
||||||
@@ -285,6 +287,16 @@ struct ResultView: View {
|
|||||||
.foregroundStyle(model.isDrawing ? .primary : .secondary)
|
.foregroundStyle(model.isDrawing ? .primary : .secondary)
|
||||||
.help("Toggle drawing on the screenshot")
|
.help("Toggle drawing on the screenshot")
|
||||||
|
|
||||||
|
if model.isDrawing {
|
||||||
|
ColorPicker("", selection: Binding(
|
||||||
|
get: { Color(nsColor: model.drawColor) },
|
||||||
|
set: { model.drawColor = NSColor($0) }
|
||||||
|
), supportsOpacity: false)
|
||||||
|
.labelsHidden()
|
||||||
|
.frame(width: 28)
|
||||||
|
.help("Drawing color")
|
||||||
|
}
|
||||||
|
|
||||||
if !model.strokes.isEmpty {
|
if !model.strokes.isEmpty {
|
||||||
Button {
|
Button {
|
||||||
model.clearAnnotations()
|
model.clearAnnotations()
|
||||||
@@ -429,7 +441,7 @@ struct ScreenshotPane: View {
|
|||||||
path.addLine(to: CGPoint(x: origin.x + point.x * scale, y: origin.y + point.y * scale))
|
path.addLine(to: CGPoint(x: origin.x + point.x * scale, y: origin.y + point.y * scale))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.stroke(path, with: .color(.red), lineWidth: 2.5)
|
context.stroke(path, with: .color(Color(nsColor: model.drawColor)), lineWidth: 2.5)
|
||||||
}
|
}
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
|
|
||||||
@@ -443,7 +455,7 @@ struct ScreenshotPane: View {
|
|||||||
path.addLine(to: CGPoint(x: origin.x + point.x * scale, y: origin.y + point.y * scale))
|
path.addLine(to: CGPoint(x: origin.x + point.x * scale, y: origin.y + point.y * scale))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
context.stroke(path, with: .color(.red), lineWidth: 2.5)
|
context.stroke(path, with: .color(Color(nsColor: model.drawColor)), lineWidth: 2.5)
|
||||||
}
|
}
|
||||||
.allowsHitTesting(false)
|
.allowsHitTesting(false)
|
||||||
}
|
}
|
||||||
|
|||||||
+2
-2
@@ -108,9 +108,9 @@ cat > "$APP/Contents/Info.plist" <<'PLIST'
|
|||||||
<key>CFBundleIconFile</key>
|
<key>CFBundleIconFile</key>
|
||||||
<string>Icon</string>
|
<string>Icon</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>1.3.0</string>
|
<string>1.3.3</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>30</string>
|
<string>33</string>
|
||||||
<key>LSUIElement</key>
|
<key>LSUIElement</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>NSHighResolutionCapable</key>
|
<key>NSHighResolutionCapable</key>
|
||||||
|
|||||||
Reference in New Issue
Block a user