Reset the overlay context for each draw request and use global font cache (#3231)
This commit is contained in:
parent
84e44810d2
commit
bc66148d2b
|
|
@ -15,8 +15,6 @@ pub struct OverlaysMessageHandler {
|
||||||
canvas: Option<web_sys::HtmlCanvasElement>,
|
canvas: Option<web_sys::HtmlCanvasElement>,
|
||||||
#[cfg(target_family = "wasm")]
|
#[cfg(target_family = "wasm")]
|
||||||
context: Option<web_sys::CanvasRenderingContext2d>,
|
context: Option<web_sys::CanvasRenderingContext2d>,
|
||||||
#[cfg(all(not(target_family = "wasm"), not(test)))]
|
|
||||||
context: Option<super::utility_types::OverlayContext>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[message_handler_data]
|
#[message_handler_data]
|
||||||
|
|
@ -82,11 +80,7 @@ impl MessageHandler<OverlaysMessage, OverlaysMessageContext<'_>> for OverlaysMes
|
||||||
|
|
||||||
let size = ipp.viewport_bounds.size();
|
let size = ipp.viewport_bounds.size();
|
||||||
|
|
||||||
if self.context.is_none() {
|
let overlay_context = OverlayContext::new(size, device_pixel_ratio, visibility_settings);
|
||||||
self.context = Some(OverlayContext::new(size, device_pixel_ratio, visibility_settings));
|
|
||||||
}
|
|
||||||
|
|
||||||
let overlay_context = self.context.as_mut().unwrap();
|
|
||||||
|
|
||||||
if visibility_settings.all() {
|
if visibility_settings.all() {
|
||||||
responses.add(DocumentMessage::GridOverlays { context: overlay_context.clone() });
|
responses.add(DocumentMessage::GridOverlays { context: overlay_context.clone() });
|
||||||
|
|
@ -95,7 +89,7 @@ impl MessageHandler<OverlaysMessage, OverlaysMessageContext<'_>> for OverlaysMes
|
||||||
responses.add(provider(overlay_context.clone()));
|
responses.add(provider(overlay_context.clone()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
responses.add(FrontendMessage::RenderOverlays { context: overlay_context.clone() });
|
responses.add(FrontendMessage::RenderOverlays { context: overlay_context });
|
||||||
}
|
}
|
||||||
#[cfg(all(not(target_family = "wasm"), test))]
|
#[cfg(all(not(target_family = "wasm"), test))]
|
||||||
OverlaysMessage::Draw => {
|
OverlaysMessage::Draw => {
|
||||||
|
|
|
||||||
|
|
@ -20,10 +20,22 @@ use graphene_std::vector::{PointId, SegmentId, Vector};
|
||||||
use kurbo::{self, BezPath, ParamCurve};
|
use kurbo::{self, BezPath, ParamCurve};
|
||||||
use kurbo::{Affine, PathSeg};
|
use kurbo::{Affine, PathSeg};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::{Arc, Mutex, MutexGuard};
|
use std::sync::{Arc, LazyLock, Mutex, MutexGuard};
|
||||||
use vello::Scene;
|
use vello::Scene;
|
||||||
use vello::peniko;
|
use vello::peniko;
|
||||||
|
|
||||||
|
// Global lazy initialized font cache and text context
|
||||||
|
static GLOBAL_FONT_CACHE: LazyLock<FontCache> = LazyLock::new(|| {
|
||||||
|
let mut font_cache = FontCache::default();
|
||||||
|
// Initialize with the hardcoded font used by overlay text
|
||||||
|
const FONT_DATA: &[u8] = include_bytes!("source-sans-pro-regular.ttf");
|
||||||
|
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
||||||
|
font_cache.insert(font, String::new(), FONT_DATA.to_vec());
|
||||||
|
font_cache
|
||||||
|
});
|
||||||
|
|
||||||
|
static GLOBAL_TEXT_CONTEXT: LazyLock<Mutex<TextContext>> = LazyLock::new(|| Mutex::new(TextContext::default()));
|
||||||
|
|
||||||
pub type OverlayProvider = fn(OverlayContext) -> Message;
|
pub type OverlayProvider = fn(OverlayContext) -> Message;
|
||||||
|
|
||||||
pub fn empty_provider() -> OverlayProvider {
|
pub fn empty_provider() -> OverlayProvider {
|
||||||
|
|
@ -412,8 +424,6 @@ pub(super) struct OverlayContextInternal {
|
||||||
size: DVec2,
|
size: DVec2,
|
||||||
device_pixel_ratio: f64,
|
device_pixel_ratio: f64,
|
||||||
visibility_settings: OverlaysVisibilitySettings,
|
visibility_settings: OverlaysVisibilitySettings,
|
||||||
font_cache: FontCache,
|
|
||||||
thread_text: TextContext,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for OverlayContextInternal {
|
impl Default for OverlayContextInternal {
|
||||||
|
|
@ -424,19 +434,11 @@ impl Default for OverlayContextInternal {
|
||||||
|
|
||||||
impl OverlayContextInternal {
|
impl OverlayContextInternal {
|
||||||
pub(super) fn new(size: DVec2, device_pixel_ratio: f64, visibility_settings: OverlaysVisibilitySettings) -> Self {
|
pub(super) fn new(size: DVec2, device_pixel_ratio: f64, visibility_settings: OverlaysVisibilitySettings) -> Self {
|
||||||
let mut font_cache = FontCache::default();
|
|
||||||
// Initialize with the hardcoded font used by overlay text
|
|
||||||
const FONT_DATA: &[u8] = include_bytes!("source-sans-pro-regular.ttf");
|
|
||||||
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
|
||||||
font_cache.insert(font, String::new(), FONT_DATA.to_vec());
|
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
scene: Scene::new(),
|
scene: Scene::new(),
|
||||||
size,
|
size,
|
||||||
device_pixel_ratio,
|
device_pixel_ratio,
|
||||||
visibility_settings,
|
visibility_settings,
|
||||||
font_cache,
|
|
||||||
thread_text: TextContext::default(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1031,7 +1033,8 @@ impl OverlayContextInternal {
|
||||||
// TODO: Grab this from the node_modules folder (either with `include_bytes!` or ideally at runtime) instead of checking the font file into the repo.
|
// TODO: Grab this from the node_modules folder (either with `include_bytes!` or ideally at runtime) instead of checking the font file into the repo.
|
||||||
// TODO: And maybe use the WOFF2 version (if it's supported) for its smaller, compressed file size.
|
// TODO: And maybe use the WOFF2 version (if it's supported) for its smaller, compressed file size.
|
||||||
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
||||||
let bounds = self.thread_text.bounding_box(text, &font, &self.font_cache, typesetting, false);
|
let mut text_context = GLOBAL_TEXT_CONTEXT.lock().expect("Failed to lock global text context");
|
||||||
|
let bounds = text_context.bounding_box(text, &font, &GLOBAL_FONT_CACHE, typesetting, false);
|
||||||
bounds.x
|
bounds.x
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1056,14 +1059,15 @@ impl OverlayContextInternal {
|
||||||
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
||||||
|
|
||||||
// Get text dimensions directly from layout
|
// Get text dimensions directly from layout
|
||||||
let text_size = self.thread_text.bounding_box(text, &font, &self.font_cache, typesetting, false);
|
let mut text_context = GLOBAL_TEXT_CONTEXT.lock().expect("Failed to lock global text context");
|
||||||
|
let text_size = text_context.bounding_box(text, &font, &GLOBAL_FONT_CACHE, typesetting, false);
|
||||||
let text_width = text_size.x;
|
let text_width = text_size.x;
|
||||||
let text_height = text_size.y;
|
let text_height = text_size.y;
|
||||||
// Create a rect from the size (assuming text starts at origin)
|
// Create a rect from the size (assuming text starts at origin)
|
||||||
let text_bounds = kurbo::Rect::new(0.0, 0.0, text_width, text_height);
|
let text_bounds = kurbo::Rect::new(0.0, 0.0, text_width, text_height);
|
||||||
|
|
||||||
// Convert text to vector paths for rendering
|
// Convert text to vector paths for rendering
|
||||||
let text_table = self.thread_text.to_path(text, &font, &self.font_cache, typesetting, false);
|
let text_table = text_context.to_path(text, &font, &GLOBAL_FONT_CACHE, typesetting, false);
|
||||||
|
|
||||||
// Calculate position based on pivot
|
// Calculate position based on pivot
|
||||||
let mut position = DVec2::ZERO;
|
let mut position = DVec2::ZERO;
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue