mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-29 19:48:11 +08:00
Desktop: Remove web_sys text measuring to fix node graph layer widths (#3455)
* Remove web_sys text measuring * Improve export * Fix top of layer stack
This commit is contained in:
@@ -2,8 +2,17 @@ pub mod grid_overlays;
|
||||
mod overlays_message;
|
||||
mod overlays_message_handler;
|
||||
pub mod utility_functions;
|
||||
#[cfg_attr(not(target_family = "wasm"), path = "utility_types_vello.rs")]
|
||||
pub mod utility_types;
|
||||
// Native (non‑wasm)
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub mod utility_types_native;
|
||||
#[cfg(not(target_family = "wasm"))]
|
||||
pub use utility_types_native as utility_types;
|
||||
|
||||
// WebAssembly
|
||||
#[cfg(target_family = "wasm")]
|
||||
pub mod utility_types_web;
|
||||
#[cfg(target_family = "wasm")]
|
||||
pub use utility_types_web as utility_types;
|
||||
|
||||
#[doc(inline)]
|
||||
pub use overlays_message::{OverlaysMessage, OverlaysMessageDiscriminant};
|
||||
|
||||
@@ -6,9 +6,11 @@ use crate::messages::tool::common_functionality::shape_editor::{SelectedLayerSta
|
||||
use crate::messages::tool::tool_messages::tool_prelude::{DocumentMessageHandler, PreferencesMessageHandler};
|
||||
use glam::{DAffine2, DVec2};
|
||||
use graphene_std::subpath::{Bezier, BezierHandles};
|
||||
use graphene_std::text::{Font, FontCache, TextAlign, TextContext, TypesettingConfig};
|
||||
use graphene_std::vector::misc::ManipulatorPointId;
|
||||
use graphene_std::vector::{PointId, SegmentId, Vector};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{LazyLock, Mutex};
|
||||
use wasm_bindgen::JsCast;
|
||||
|
||||
pub fn overlay_canvas_element() -> Option<web_sys::HtmlCanvasElement> {
|
||||
@@ -218,3 +220,35 @@ pub fn path_endpoint_overlays(document: &DocumentMessageHandler, shape_editor: &
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Global lazy initialized font cache and text context
|
||||
pub 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
|
||||
});
|
||||
|
||||
pub static GLOBAL_TEXT_CONTEXT: LazyLock<Mutex<TextContext>> = LazyLock::new(|| Mutex::new(TextContext::default()));
|
||||
|
||||
pub fn text_width(text: &str, font_size: f64) -> f64 {
|
||||
let typesetting = TypesettingConfig {
|
||||
font_size,
|
||||
line_height_ratio: 1.2,
|
||||
character_spacing: 0.0,
|
||||
max_width: None,
|
||||
max_height: None,
|
||||
tilt: 0.0,
|
||||
align: TextAlign::Left,
|
||||
};
|
||||
|
||||
// Load Source Sans Pro font data
|
||||
// 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.
|
||||
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
||||
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
|
||||
}
|
||||
|
||||
+3
-42
@@ -3,6 +3,7 @@ use crate::consts::{
|
||||
COMPASS_ROSE_ARROW_SIZE, COMPASS_ROSE_HOVER_RING_DIAMETER, COMPASS_ROSE_MAIN_RING_DIAMETER, COMPASS_ROSE_RING_INNER_DIAMETER, DOWEL_PIN_RADIUS, MANIPULATOR_GROUP_MARKER_SIZE,
|
||||
PIVOT_CROSSHAIR_LENGTH, PIVOT_CROSSHAIR_THICKNESS, PIVOT_DIAMETER, RESIZE_HANDLE_SIZE, SKEW_TRIANGLE_OFFSET, SKEW_TRIANGLE_SIZE,
|
||||
};
|
||||
use crate::messages::portfolio::document::overlays::utility_functions::{GLOBAL_FONT_CACHE, GLOBAL_TEXT_CONTEXT};
|
||||
use crate::messages::portfolio::document::utility_types::document_metadata::LayerNodeIdentifier;
|
||||
use crate::messages::prelude::Message;
|
||||
use crate::messages::prelude::ViewportMessageHandler;
|
||||
@@ -13,30 +14,17 @@ use graphene_std::Color;
|
||||
use graphene_std::math::quad::Quad;
|
||||
use graphene_std::subpath::{self, Subpath};
|
||||
use graphene_std::table::Table;
|
||||
use graphene_std::text::TextContext;
|
||||
use graphene_std::text::{Font, FontCache, TextAlign, TypesettingConfig};
|
||||
use graphene_std::text::{Font, TextAlign, TypesettingConfig};
|
||||
use graphene_std::vector::click_target::ClickTargetType;
|
||||
use graphene_std::vector::misc::point_to_dvec2;
|
||||
use graphene_std::vector::{PointId, SegmentId, Vector};
|
||||
use kurbo::{self, BezPath, ParamCurve};
|
||||
use kurbo::{Affine, PathSeg};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{Arc, LazyLock, Mutex, MutexGuard};
|
||||
use std::sync::{Arc, Mutex, MutexGuard};
|
||||
use vello::Scene;
|
||||
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 fn empty_provider() -> OverlayProvider {
|
||||
@@ -393,10 +381,6 @@ impl OverlayContext {
|
||||
self.internal().fill_path_pattern(subpaths, transform, color);
|
||||
}
|
||||
|
||||
pub fn get_width(&self, text: &str) -> f64 {
|
||||
self.internal().get_width(text)
|
||||
}
|
||||
|
||||
pub fn text(&self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
|
||||
let mut internal = self.internal();
|
||||
internal.text(text, font_color, background_color, transform, padding, pivot);
|
||||
@@ -1034,29 +1018,6 @@ impl OverlayContextInternal {
|
||||
self.scene.fill(peniko::Fill::NonZero, self.get_transform(), &brush, None, &path);
|
||||
}
|
||||
|
||||
fn get_width(&mut self, text: &str) -> f64 {
|
||||
// Use the actual text-to-path system to get precise text width
|
||||
const FONT_SIZE: f64 = 12.0;
|
||||
|
||||
let typesetting = TypesettingConfig {
|
||||
font_size: FONT_SIZE,
|
||||
line_height_ratio: 1.2,
|
||||
character_spacing: 0.0,
|
||||
max_width: None,
|
||||
max_height: None,
|
||||
tilt: 0.0,
|
||||
align: TextAlign::Left,
|
||||
};
|
||||
|
||||
// Load Source Sans Pro font data
|
||||
// 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.
|
||||
let font = Font::new("Source Sans Pro".to_string(), "Regular".to_string());
|
||||
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
|
||||
}
|
||||
|
||||
fn text(&mut self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
|
||||
// Use the proper text-to-path system for accurate text rendering
|
||||
const FONT_SIZE: f64 = 12.0;
|
||||
-4
@@ -962,10 +962,6 @@ impl OverlayContext {
|
||||
self.render_context.fill();
|
||||
}
|
||||
|
||||
pub fn get_width(&self, text: &str) -> f64 {
|
||||
self.render_context.measure_text(text).expect("Failed to measure text dimensions").width()
|
||||
}
|
||||
|
||||
pub fn text(&self, text: &str, font_color: &str, background_color: Option<&str>, transform: DAffine2, padding: f64, pivot: [Pivot; 2]) {
|
||||
let metrics = self.render_context.measure_text(text).expect("Failed to measure the text dimensions");
|
||||
let x = match pivot[0] {
|
||||
Reference in New Issue
Block a user