Migrate usage of the Hash trait for cache invalidation to the dedicated CacheHash trait (#4051)

* WIP start migrating usages of hash for cache invalidadion to dedicated trait

* Finish migrating usages

* Code review

* Add comments clearifying the reasoning for using random ids in the VectorModification cach hash impl

* Fix some remaining hash violations

* Finish migration and fix compilation

* Fix import ordering

* Cleanup

* Fix code review stuff

---------

Co-authored-by: Keavon Chambers <keavon@keavon.com>
This commit is contained in:
Dennis Kobert
2026-04-27 07:18:47 +02:00
committed by GitHub
parent 7bb01c9651
commit 3d84e63ef9
64 changed files with 828 additions and 448 deletions

View File

@@ -10,6 +10,7 @@ license = "MIT OR Apache-2.0"
# Local dependencies
dyn-any = { workspace = true }
core-types = { workspace = true }
graphene-hash = { workspace = true }
# Workspace dependencies
glam = { workspace = true }

View File

@@ -1,5 +1,6 @@
use crate::render_ext::RenderExt;
use crate::to_peniko::BlendModeExt;
use core_types::CacheHash;
use core_types::blending::BlendMode;
use core_types::bounds::{BoundingBox, RenderBoundingBox};
use core_types::color::{Alpha, Color};
@@ -10,6 +11,7 @@ use core_types::transform::{Footprint, Transform};
use core_types::uuid::{NodeId, generate_uuid};
use dyn_any::DynAny;
use glam::{DAffine2, DVec2};
use graphene_hash::CacheHashWrapper;
use graphic_types::Vector;
use graphic_types::raster_types::{BitmapMut, CPU, GPU, Image, Raster};
use graphic_types::vector_types::gradient::{GradientStops, GradientType};
@@ -21,7 +23,6 @@ use kurbo::{Affine, Cap, Join, Shape};
use num_traits::Zero;
use std::collections::{HashMap, HashSet};
use std::fmt::Write;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::sync::{Arc, LazyLock};
use vector_types::gradient::GradientSpreadMethod;
@@ -95,7 +96,7 @@ pub struct SvgRender {
pub svg: Vec<SvgSegment>,
pub svg_defs: String,
pub transform: DAffine2,
pub image_data: HashMap<Image<Color>, u64>,
pub image_data: HashMap<CacheHashWrapper<Image<Color>>, u64>,
indent: usize,
}
@@ -191,7 +192,7 @@ pub struct RenderContext {
pub resource_overrides: Vec<(peniko::ImageBrush, wgpu::Texture)>,
}
#[derive(Default, Clone, Copy, Hash)]
#[derive(Default, Clone, Copy, Hash, graphene_hash::CacheHash)]
pub enum RenderOutputType {
#[default]
Svg,
@@ -199,12 +200,13 @@ pub enum RenderOutputType {
}
/// Static state used whilst rendering
#[derive(Default, Clone)]
#[derive(Default, Clone, CacheHash)]
pub struct RenderParams {
pub render_mode: RenderMode,
pub footprint: Footprint,
/// Ratio of physical pixels to logical pixels. `scale := physical_pixels / logical_pixels`
/// Ignored when rendering to SVG.
#[cache_hash(skip)]
pub scale: f64,
pub render_output_type: RenderOutputType,
pub thumbnail: bool,
@@ -223,25 +225,6 @@ pub struct RenderParams {
pub viewport_zoom: f64,
}
impl Hash for RenderParams {
fn hash<H: Hasher>(&self, state: &mut H) {
self.render_mode.hash(state);
self.footprint.hash(state);
self.render_output_type.hash(state);
self.thumbnail.hash(state);
self.hide_artboards.hash(state);
self.for_export.hash(state);
self.for_mask.hash(state);
if let Some(x) = self.alignment_parent_transform {
x.to_cols_array().iter().for_each(|x| x.to_bits().hash(state))
}
self.aligned_strokes.hash(state);
self.override_paint_order.hash(state);
self.artboard_background.hash(state);
self.viewport_zoom.to_bits().hash(state);
}
}
impl RenderParams {
pub fn for_clipper(&self) -> Self {
Self { for_mask: true, ..*self }
@@ -1426,7 +1409,7 @@ impl Render for Table<Raster<CPU>> {
if render_params.to_canvas() {
let mut image_copy = image.clone();
image_copy.data_mut().map_pixels(|p| p.to_unassociated_alpha());
let id = *render.image_data.entry(image_copy.into_data()).or_insert_with(generate_uuid);
let id = *render.image_data.entry(CacheHashWrapper(image_copy.into_data())).or_insert_with(generate_uuid);
render.parent_tag(
"foreignObject",