Add the macOS client spike and record its SwiftUI gap results
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
import AppKit
|
||||
import CoreText
|
||||
import SwiftUI
|
||||
|
||||
func runFonts(_ font: CTFont, _ text: String) -> String {
|
||||
let line = CTLineCreateWithAttributedString(NSAttributedString(string: text, attributes: [.font: font as NSFont]))
|
||||
return (CTLineGetGlyphRuns(line) as! [CTRun]).map { run in
|
||||
let f = (CTRunGetAttributes(run) as NSDictionary)[kCTFontAttributeName] as! CTFont
|
||||
let file = (CTFontCopyAttribute(f, kCTFontURLAttribute) as? URL)?.lastPathComponent ?? "system"
|
||||
let r = CTRunGetStringRange(run)
|
||||
let part = (text as NSString).substring(with: NSRange(location: r.location, length: r.length))
|
||||
return "\(part) → \(CTFontCopyPostScriptName(f)) (\(file))"
|
||||
}.joined(separator: "\n")
|
||||
}
|
||||
|
||||
struct FontSpike: View {
|
||||
private let sample = "The quick brown fox jumps — 0O 1lI {}[] őŁżę → │"
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 12) {
|
||||
ForEach(Array([(400.0, false), (700.0, false), (400.0, true), (700.0, true)].enumerated()), id: \.offset) { _, style in
|
||||
let (w, italic) = style
|
||||
VStack(alignment: .leading) {
|
||||
Text("weight \(Int(w))\(italic ? " italic" : "")")
|
||||
.foregroundStyle(.secondary)
|
||||
Text(sample)
|
||||
.font(Fonts.font(16, weight: w, italic: italic))
|
||||
Text(runFonts(Fonts.ct(16, weight: w, italic: italic), sample))
|
||||
.foregroundStyle(.secondary)
|
||||
}
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text("Fonts.font(16) with SwiftUI .bold() and .italic()")
|
||||
.foregroundStyle(.secondary)
|
||||
Text(sample)
|
||||
.font(Fonts.font(16))
|
||||
.bold()
|
||||
.italic()
|
||||
}
|
||||
VStack(alignment: .leading) {
|
||||
Text("System font, for comparison")
|
||||
.foregroundStyle(.secondary)
|
||||
Text(sample)
|
||||
.font(.system(size: 16))
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity, alignment: .leading)
|
||||
.padding(8)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct SVGSpike: View {
|
||||
@Environment(Server.self) private var server
|
||||
@ViewState private var path = "web/favicon.svg"
|
||||
@ViewState private var image: NSImage?
|
||||
@ViewState private var failure = ""
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading) {
|
||||
HStack {
|
||||
TextField("Worktree path", text: $path)
|
||||
.frame(width: 320)
|
||||
Button("Load") {
|
||||
Task {
|
||||
await load()
|
||||
}
|
||||
}
|
||||
}
|
||||
if let image {
|
||||
Text(verbatim: "NSImage size \(Int(image.size.width))×\(Int(image.size.height)), reps \(image.representations.map { String(describing: type(of: $0)) })")
|
||||
.foregroundStyle(.secondary)
|
||||
HStack(alignment: .top, spacing: 16) {
|
||||
Image(nsImage: image)
|
||||
Image(nsImage: image)
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 256, height: 256)
|
||||
}
|
||||
}
|
||||
if !failure.isEmpty {
|
||||
Text(failure)
|
||||
}
|
||||
Spacer()
|
||||
}
|
||||
.task {
|
||||
await load()
|
||||
}
|
||||
}
|
||||
|
||||
private func load() async {
|
||||
image = nil
|
||||
failure = ""
|
||||
guard !server.taskId.isEmpty else {
|
||||
return
|
||||
}
|
||||
do {
|
||||
let data = try await server.data(URLRequest(url: try server.url("/api/tasks/\(server.taskId)/image", [URLQueryItem(name: "path", value: path)])))
|
||||
guard let img = NSImage(data: data) else {
|
||||
failure = "image not available: \(path)"
|
||||
return
|
||||
}
|
||||
image = img
|
||||
} catch {
|
||||
failure = "image not available: \(path) (\(error))"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user