Compare commits

..

No commits in common. "8bd65e5904891ea3b7ee313e16fb4f19ca701728" and "06973d185ce07de2969e25f6fea2c0b3ca284bab" have entirely different histories.

2 changed files with 25 additions and 23 deletions

View File

@ -44,28 +44,35 @@ pub fn get(preferred: &[&str]) -> Option<(String, Vec<u8>)> {
#[cfg(target_os = "macos")] #[cfg(target_os = "macos")]
mod platform_impl { mod platform_impl {
use objc2::rc::Retained;
use objc2_app_kit::NSPasteboard; use objc2_app_kit::NSPasteboard;
use objc2_foundation::{NSData, NSString}; use objc2_foundation::{NSData, NSString};
pub fn set(entries: &[(&str, &[u8])]) { pub fn set(entries: &[(&str, &[u8])]) {
let pb = NSPasteboard::generalPasteboard(); // SAFETY: must be called from the main thread (same as ClipboardManager).
for &(mime, data) in entries { unsafe {
let ns_type = NSString::from_str(mime); let pb = NSPasteboard::generalPasteboard();
let ns_data = NSData::with_bytes(data); for &(mime, data) in entries {
// setData:forType: appends to the current clipboard contents let ns_type: Retained<NSString> = NSString::from_str(mime);
// (arboard already called clearContents, so no double-clear needed). let ns_data: Retained<NSData> = NSData::with_bytes(data);
pb.setData_forType(Some(&ns_data), &ns_type); // setData:forType: appends to the current clipboard contents
// (arboard already called clearContents, so no double-clear needed).
pb.setData_forType(&ns_data, &ns_type);
}
} }
} }
pub fn get(preferred: &[&str]) -> Option<(String, Vec<u8>)> { pub fn get(preferred: &[&str]) -> Option<(String, Vec<u8>)> {
let pb = NSPasteboard::generalPasteboard(); // SAFETY: must be called from the main thread.
for &mime in preferred { unsafe {
let ns_type = NSString::from_str(mime); let pb = NSPasteboard::generalPasteboard();
if let Some(ns_data) = pb.dataForType(&ns_type) { for &mime in preferred {
// NSData: Deref<Target=[u8]> — auto-deref resolves to [u8]::to_vec(). let ns_type: Retained<NSString> = NSString::from_str(mime);
let bytes = ns_data.to_vec(); if let Some(ns_data) = pb.dataForType(&ns_type) {
return Some((mime.to_string(), bytes)); // NSData implements AsRef<[u8]> in objc2-foundation.
let bytes = ns_data.as_ref().to_vec();
return Some((mime.to_string(), bytes));
}
} }
} }
None None
@ -84,7 +91,7 @@ mod platform_impl {
CloseClipboard, GetClipboardData, OpenClipboard, RegisterClipboardFormatW, SetClipboardData, CloseClipboard, GetClipboardData, OpenClipboard, RegisterClipboardFormatW, SetClipboardData,
}; };
use windows_sys::Win32::System::Memory::{ use windows_sys::Win32::System::Memory::{
GlobalAlloc, GlobalLock, GlobalSize, GlobalUnlock, GMEM_MOVEABLE, GlobalAlloc, GlobalFree, GlobalLock, GlobalSize, GlobalUnlock, GMEM_MOVEABLE,
}; };
static FORMAT_IDS: OnceLock<Mutex<HashMap<String, u32>>> = OnceLock::new(); static FORMAT_IDS: OnceLock<Mutex<HashMap<String, u32>>> = OnceLock::new();
@ -118,12 +125,7 @@ mod platform_impl {
} }
let ptr = GlobalLock(h); let ptr = GlobalLock(h);
if ptr.is_null() { if ptr.is_null() {
// Cannot free `h` here: GlobalFree was removed from windows-sys 0.60 GlobalFree(h);
// (it still exists in Kernel32.dll, so a manual extern declaration
// would work if this ever becomes an issue). The leak is bounded to
// one clipboard-payload-sized allocation and only occurs if GlobalLock
// fails on a handle we just allocated — essentially impossible in
// practice.
continue; continue;
} }
std::ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len()); std::ptr::copy_nonoverlapping(data.as_ptr(), ptr as *mut u8, data.len());

View File

@ -549,7 +549,7 @@ fn render_background(document: &Document, scene: &mut Scene, base_transform: Aff
// Draw checkerboard behind transparent backgrounds (UI-only; skip in export) // Draw checkerboard behind transparent backgrounds (UI-only; skip in export)
if draw_checkerboard && bg.a < 255 { if draw_checkerboard && bg.a < 255 {
use vello::peniko::{Blob, Extend, ImageAlphaType, ImageData, ImageQuality}; use vello::peniko::{Blob, Color, Extend, ImageAlphaType, ImageData, ImageQuality};
// 2x2 pixel checkerboard pattern: light/dark alternating // 2x2 pixel checkerboard pattern: light/dark alternating
let light: [u8; 4] = [204, 204, 204, 255]; let light: [u8; 4] = [204, 204, 204, 255];
let dark: [u8; 4] = [170, 170, 170, 255]; let dark: [u8; 4] = [170, 170, 170, 255];
@ -1091,7 +1091,7 @@ pub fn render_dcel(
// Gradient fill (takes priority over solid colour fill) // Gradient fill (takes priority over solid colour fill)
if !filled { if !filled {
if let Some(ref grad) = face.gradient_fill { if let Some(ref grad) = face.gradient_fill {
use kurbo::Rect; use kurbo::{Point, Rect};
let bbox: Rect = vello::kurbo::Shape::bounding_box(&path); let bbox: Rect = vello::kurbo::Shape::bounding_box(&path);
let (start, end) = gradient_bbox_endpoints(grad.angle, bbox); let (start, end) = gradient_bbox_endpoints(grad.angle, bbox);
let brush = grad.to_peniko_brush(start, end, opacity_f32); let brush = grad.to_peniko_brush(start, end, opacity_f32);