fix(menubar): 修正预览位图缩放
This commit is contained in:
1 parent
9356f86e5d
commit
e7040dd04b
2 files changed
+18
-8
No files matched your search
@@ -294,9 +294,9 @@ enum MenuBarRenderer {
|
||||
return image
|
||||
}
|
||||
|
||||
/// 设置页预览:按指定外观绘制到不透明底色上。
|
||||
/// 设置页预览:按指定外观栅格化,透明区域由界面叠加底色。
|
||||
/// 绘制回调型图像每次布局或重绘都会重跑文字排版,因此栅格化一次,SwiftUI 之后只复用位图。
|
||||
static func preview(_ image: NSImage, dark: Bool) -> NSImage {
|
||||
static func preview(_ image: NSImage, dark: Bool, backingScale: CGFloat? = nil) -> NSImage {
|
||||
let appearance = NSAppearance(named: dark ? .darkAqua : .aqua)
|
||||
let draw = { (rect: NSRect) in
|
||||
let content = {
|
||||
@@ -308,16 +308,19 @@ enum MenuBarRenderer {
|
||||
}
|
||||
if let appearance { appearance.performAsCurrentDrawingAppearance(content) } else { content() }
|
||||
}
|
||||
let scale = NSScreen.main?.backingScaleFactor ?? 2
|
||||
let scale = backingScale ?? NSScreen.main?.backingScaleFactor ?? 2
|
||||
guard let rep = NSBitmapImageRep(bitmapDataPlanes: nil,
|
||||
pixelsWide: Int(ceil(image.size.width * scale)),
|
||||
pixelsHigh: Int(ceil(image.size.height * scale)),
|
||||
bitsPerSample: 8, samplesPerPixel: 4, hasAlpha: true, isPlanar: false,
|
||||
colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0),
|
||||
let context = NSGraphicsContext(bitmapImageRep: rep) else {
|
||||
colorSpaceName: .deviceRGB, bytesPerRow: 0, bitsPerPixel: 0) else {
|
||||
return NSImage(size: image.size, flipped: false) { draw($0); return true }
|
||||
}
|
||||
// 逻辑尺寸决定上下文的点到像素缩放,必须在创建上下文前设置。
|
||||
rep.size = image.size
|
||||
guard let context = NSGraphicsContext(bitmapImageRep: rep) else {
|
||||
return NSImage(size: image.size, flipped: false) { draw($0); return true }
|
||||
}
|
||||
NSGraphicsContext.saveGraphicsState()
|
||||
NSGraphicsContext.current = context
|
||||
draw(NSRect(origin: .zero, size: image.size))
|
||||
|
||||
@@ -202,8 +202,8 @@ private func isolatedDefaults() -> UserDefaults {
|
||||
|
||||
@MainActor
|
||||
@Suite struct SettingsTests {
|
||||
@Test(arguments: [false, true])
|
||||
func settingsPreviewRasterizesOnceAndKeepsAppearanceColors(dark: Bool) throws {
|
||||
@Test(arguments: [false, true], [CGFloat(1), CGFloat(2)])
|
||||
func settingsPreviewRasterizesOnceAndKeepsAppearanceColors(dark: Bool, scale: CGFloat) throws {
|
||||
var draws = 0
|
||||
let source = NSImage(size: NSSize(width: 40, height: 18), flipped: false) { rect in
|
||||
draws += 1
|
||||
@@ -212,7 +212,7 @@ private func isolatedDefaults() -> UserDefaults {
|
||||
return true
|
||||
}
|
||||
source.isTemplate = true
|
||||
let preview = MenuBarRenderer.preview(source, dark: dark)
|
||||
let preview = MenuBarRenderer.preview(source, dark: dark, backingScale: scale)
|
||||
let drawsAfterRender = draws
|
||||
#expect(drawsAfterRender >= 1)
|
||||
// 反复读取预览(布局、重绘)不能再触发源图的绘制回调。
|
||||
@@ -222,9 +222,16 @@ private func isolatedDefaults() -> UserDefaults {
|
||||
#expect(preview.representations.contains { $0 is NSBitmapImageRep })
|
||||
// 模板图按外观着色:浅色外观为黑,深色外观为白。
|
||||
let rep = try #require(preview.representations.compactMap { $0 as? NSBitmapImageRep }.first)
|
||||
#expect(rep.pixelsWide == Int(source.size.width * scale))
|
||||
#expect(rep.pixelsHigh == Int(source.size.height * scale))
|
||||
let center = try #require(rep.colorAt(x: rep.pixelsWide / 2, y: rep.pixelsHigh / 2)?.usingColorSpace(.deviceRGB))
|
||||
#expect(center.alphaComponent > 0.99)
|
||||
#expect((center.redComponent > 0.5) == dark)
|
||||
for (x, y) in [(0, 0), (rep.pixelsWide - 1, 0), (0, rep.pixelsHigh - 1), (rep.pixelsWide - 1, rep.pixelsHigh - 1)] {
|
||||
let corner = try #require(rep.colorAt(x: x, y: y)?.usingColorSpace(.deviceRGB))
|
||||
#expect(corner.alphaComponent > 0.99)
|
||||
#expect((corner.redComponent > 0.5) == dark)
|
||||
}
|
||||
}
|
||||
|
||||
@Test func stackedCenteredStyleRendersDifferentPlacementAtSameWidth() {
|
||||
|
||||
Reference in new issue
Block a user