Image#4200
Conversation
…iteEditor#4175) chore: remove duplicate words in five comments All comment-only fixes. - desktop/src/window/win/native_handle.rs L228: "Return 0 to to tell Windows" -> "Return 0 to tell Windows" - node-graph/libraries/vector-types/src/vector/algorithms/spline.rs L24: "is the the second point" -> "is the second point" - node-graph/libraries/vector-types/src/vector/algorithms/poisson_disk.rs L153: panic message "couldn't be be mapped" -> "couldn't be mapped" - node-graph/libraries/rendering/src/renderer.rs L1800: "this is is achived" -> "this is achieved" (also fixes "achived") - editor/src/messages/tool/common_functionality/shapes/shape_utility.rs L494,523: "Check if the the cursor" -> "Check if the cursor" Co-authored-by: Matt Van Horn <455140+mvanhorn@users.noreply.github.com>
* Good start
* Impl
* allow responses.add(async { Message::NoOp });
* Fix
* Cache font blob in text node
* Refactor font handling to use Font struct direcly
* Fix fmt
* Embedd Font Resources by default
* Review
* Review
* Cache font info based on ResourceHash
* Impl NetworkMessageHandler * Repalce Frontend fetch like messages with NetworkMessage * Reimpl resource loading with NetworkMessage * Fix wasm * dedublicate resource requests * Embedd font resources created by migration * Fixup * Fix tests * Fix font catalog not loading * Cleanup * Fix layouts not updating when font catalog is loaded * Review * Review * Cleanup
There was a problem hiding this comment.
Code Review
This pull request refactors the font and resource loading system by introducing a backend-driven asynchronous resource resolution system using a new network message handler and client. Text nodes are updated to use font resources via ResourceId instead of passing Font structs directly, and support is added for importing embedded SVG images. The review feedback suggests optimizing SVG image dimension extraction by reading only the image headers instead of decoding full pixel data, and resolving already-cached resources synchronously to avoid spawning redundant asynchronous network requests.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| let decoded_image = match ::image::load_from_memory_with_format(image_data, format) { | ||
| Ok(img) => img, | ||
| Err(e) => { | ||
| log::warn!("Failed to decode SVG image data: {:?}", e); | ||
| return; | ||
| } | ||
| }; | ||
| let width = decoded_image.width(); | ||
| let height = decoded_image.height(); |
There was a problem hiding this comment.
Decoding the entire image using ::image::load_from_memory_with_format just to retrieve its dimensions is highly inefficient, especially for large embedded SVG images. Consider using ::image::Reader with into_dimensions() to parse only the image header and extract the width and height without decoding the full pixel data.
| let decoded_image = match ::image::load_from_memory_with_format(image_data, format) { | |
| Ok(img) => img, | |
| Err(e) => { | |
| log::warn!("Failed to decode SVG image data: {:?}", e); | |
| return; | |
| } | |
| }; | |
| let width = decoded_image.width(); | |
| let height = decoded_image.height(); | |
| let (width, height) = match ::image::Reader::with_format(std::io::Cursor::new(image_data), format).into_dimensions() { | |
| Ok(dim) => dim, | |
| Err(e) => { | |
| log::warn!("Failed to parse SVG image dimensions: {:?}", e); | |
| return; | |
| } | |
| }; |
| self.pending_resolves.insert(resource_id); | ||
|
|
||
| let font_catalog = fonts.font_catalog.clone(); | ||
|
|
||
| let sources = info | ||
| .sources | ||
| .iter() | ||
| .map(|source| match source { | ||
| DataSource::Font { family, style } => { | ||
| let font = match style { | ||
| Some(style) => Font::new(family.clone(), style.clone()), | ||
| None => Font::new_with_default_style(family.clone()), | ||
| }; | ||
| let hash = fonts.cached_hash(&font); | ||
| (source.clone(), hash) | ||
| } | ||
| source => (source.clone(), None), | ||
| }) | ||
| .collect::<Vec<(DataSource, Option<ResourceHash>)>>(); |
There was a problem hiding this comment.
When resolving a resource, if the resource is already cached locally (i.e., fonts.cached_hash(&font) returns Some(hash)), we can resolve it synchronously and return immediately. This avoids the overhead of spawning an asynchronous network request and dispatching a client call for already-cached resources.
let sources = info
.sources
.iter()
.map(|source| match source {
DataSource::Font { family, style } => {
let font = match style {
Some(style) => Font::new(family.clone(), style.clone()),
None => Font::new_with_default_style(family.clone()),
};
let hash = fonts.cached_hash(&font);
(source.clone(), hash)
}
source => (source.clone(), None),
})
.collect::<Vec<(DataSource, Option<ResourceHash>)>>();
if let Some((source, Some(hash))) = sources.iter().find(|(_, hash)| hash.is_some()) {
responses.add(ResourceMessage::Resolved { resource_id, source: source.clone(), hash: *hash });
return;
}
self.pending_resolves.insert(resource_id);
let font_catalog = fonts.font_catalog.clone();
No description provided.