diff --git a/crates/gpui/src/elements/svg.rs b/crates/gpui/src/elements/svg.rs index a29b106c0e..176072f1c8 100644 --- a/crates/gpui/src/elements/svg.rs +++ b/crates/gpui/src/elements/svg.rs @@ -1,4 +1,9 @@ -use std::{fs, path::Path, sync::Arc}; +use std::{ + fs, + hash::{Hash, Hasher}, + path::Path, + sync::Arc, +}; use crate::{ App, Asset, Bounds, Element, GlobalElementId, Hitbox, InspectorElementId, InteractiveElement, @@ -13,6 +18,8 @@ pub struct Svg { transformation: Option, path: Option, external_path: Option, + data: Option>, + data_path: Option, } /// Create a new SVG element. @@ -23,6 +30,8 @@ pub fn svg() -> Svg { transformation: None, path: None, external_path: None, + data: None, + data_path: None, } } @@ -39,6 +48,19 @@ impl Svg { self } + /// Set the raw SVG data for this element. + /// The SVG will be rendered directly from the provided bytes. + pub fn data(mut self, data: &[u8]) -> Self { + // Generate a unique deterministic path based on the data hash for caching + let mut hasher = std::collections::hash_map::DefaultHasher::new(); + data.hash(&mut hasher); + let hash = hasher.finish(); + let path = SharedString::from(format!("__binary_svg__{}", hash)); + self.data = Some(Arc::from(data)); + self.data_path = Some(path); + self + } + /// Transform the SVG element with the given transformation. /// Note that this won't effect the hitbox or layout of the element, only the rendering. pub fn with_transformation(mut self, transformation: Transformation) -> Self { @@ -116,18 +138,27 @@ impl Element for Svg { window, cx, |style, window, cx| { - if let Some((path, color)) = self.path.as_ref().zip(style.text.color) { - let transformation = self - .transformation - .as_ref() - .map(|transformation| { - transformation.into_matrix(bounds.center(), window.scale_factor()) - }) - .unwrap_or_default(); + let transformation = self + .transformation + .as_ref() + .map(|transformation| { + transformation.into_matrix(bounds.center(), window.scale_factor()) + }) + .unwrap_or_default(); - window - .paint_svg(bounds, path.clone(), None, transformation, color, cx) - .log_err(); + if let Some((data, path)) = self.data.as_ref().zip(self.data_path.as_ref()) { + if let Some(color) = style.text.color { + window + .paint_svg( + bounds, + path.clone(), + Some(&**data), + transformation, + color, + cx, + ) + .log_err(); + } } else if let Some((path, color)) = self.external_path.as_ref().zip(style.text.color) { @@ -138,14 +169,6 @@ impl Element for Svg { return; }; - let transformation = self - .transformation - .as_ref() - .map(|transformation| { - transformation.into_matrix(bounds.center(), window.scale_factor()) - }) - .unwrap_or_default(); - window .paint_svg( bounds, @@ -156,6 +179,10 @@ impl Element for Svg { cx, ) .log_err(); + } else if let Some((path, color)) = self.path.as_ref().zip(style.text.color) { + window + .paint_svg(bounds, path.clone(), None, transformation, color, cx) + .log_err(); } }, )