Replace deprecated row/cell/instance terminology with "item" and "value" terms (#4075)

This commit is contained in:
Keavon Chambers
2026-04-28 19:12:59 -07:00
committed by GitHub
parent f6c73d1c20
commit 5774ec215d
49 changed files with 347 additions and 354 deletions

View File

@@ -1,4 +1,4 @@
//! A collection of utilities for working with HTML canvases.
//! Utilities for working with HTML canvases.
//! This library is designed to be used in a WebAssembly context.
//! It doesn't expose any functionality when compiled for non-WebAssembly targets

View File

@@ -109,7 +109,7 @@ trait AttributeColumn: std::any::Any + Send + Sync {
fn display_at(&self, index: usize) -> Option<String>;
/// Clones a single value from this column into a boxed scalar attribute value.
fn clone_cell(&self, index: usize) -> Option<Box<dyn AttributeValue>>;
fn clone_value(&self, index: usize) -> Option<Box<dyn AttributeValue>>;
/// Drains all values out of this column into a Vec of scalar attribute values.
fn drain(self: Box<Self>) -> Vec<Box<dyn AttributeValue>>;
@@ -191,7 +191,7 @@ impl<T: Clone + Send + Sync + Default + Debug + 'static> AttributeColumn for Col
}
/// Clones the value at the given index into a boxed scalar attribute value.
fn clone_cell(&self, index: usize) -> Option<Box<dyn AttributeValue>> {
fn clone_value(&self, index: usize) -> Option<Box<dyn AttributeValue>> {
self.0.get(index).map(|v| Box::new(v.clone()) as Box<dyn AttributeValue>)
}
@@ -346,8 +346,8 @@ impl AttributeColumns {
// Push values into existing columns, or a default if the row lacks that attribute
for (column_key, column) in &mut self.columns {
if let Some(position) = row_entries.iter().position(|(k, _)| k == column_key) {
let (_, cell_value) = row_entries.swap_remove(position);
column.push(cell_value);
let (_, value) = row_entries.swap_remove(position);
column.push(value);
} else {
column.push_default();
}
@@ -389,8 +389,8 @@ impl AttributeColumns {
self.len += other_len;
}
/// Gets a reference to a cell value at the given index from the column for the given key.
fn get_cell<T: 'static>(&self, key: &str, index: usize) -> Option<&T> {
/// Gets a reference to the value at the given index from the column for the given key.
fn get_value<T: 'static>(&self, key: &str, index: usize) -> Option<&T> {
self.columns.iter().find_map(|(k, column)| if k == key { column.get_any(index)?.downcast_ref::<T>() } else { None })
}
@@ -415,28 +415,28 @@ impl AttributeColumns {
}
}
/// Gets a mutable reference to a cell value at the given index, creating the column if it doesn't exist or has the wrong type.
fn get_or_insert_default_cell<T: Clone + Send + Sync + Default + Debug + 'static>(&mut self, key: &str, index: usize) -> &mut T {
/// Gets a mutable reference to the value at the given index, creating the column if it doesn't exist or has the wrong type.
fn get_or_insert_default_value<T: Clone + Send + Sync + Default + Debug + 'static>(&mut self, key: &str, index: usize) -> &mut T {
let column_position = self.find_or_create_column::<T>(key);
let column = (*self.columns[column_position].1).as_any_mut().downcast_mut::<Column<T>>().unwrap();
&mut column.0[index]
}
/// Sets a cell value at the given index in the column for the given key.
/// Sets the value at the given index in the column for the given key.
/// Creates the column with defaults if it doesn't exist.
fn set_cell<T: Clone + Send + Sync + Default + Debug + 'static>(&mut self, key: impl Into<String>, index: usize, value: T) {
fn set_value<T: Clone + Send + Sync + Default + Debug + 'static>(&mut self, key: impl Into<String>, index: usize, value: T) {
let key = key.into();
let column_position = self.find_or_create_column::<T>(&key);
let column = (*self.columns[column_position].1).as_any_mut().downcast_mut::<Column<T>>().unwrap();
column.0[index] = value;
}
/// Returns a debug-formatted string for a cell at the given index in the column for the given key.
fn display_cell_value(&self, key: &str, index: usize, overrides: fn(&dyn std::any::Any) -> Option<String>) -> Option<String> {
/// Returns a debug-formatted string for the value at the given index in the column for the given key.
fn display_value(&self, key: &str, index: usize, overrides: fn(&dyn std::any::Any) -> Option<String>) -> Option<String> {
self.columns.iter().find_map(|(k, column)| {
if k == key {
if let Some(cell) = column.get_any(index)
&& let Some(text) = overrides(cell)
if let Some(value) = column.get_any(index)
&& let Some(text) = overrides(value)
{
return Some(text);
}
@@ -447,8 +447,8 @@ impl AttributeColumns {
})
}
/// Returns a type-erased reference to the cell value at the given index in the column for the given key.
fn get_any_cell(&self, key: &str, index: usize) -> Option<&dyn std::any::Any> {
/// Returns a type-erased reference to the value at the given index in the column for the given key.
fn get_any_value(&self, key: &str, index: usize) -> Option<&dyn std::any::Any> {
self.columns.iter().find_map(|(k, column)| if k == key { column.get_any(index) } else { None })
}
@@ -487,8 +487,8 @@ impl AttributeColumns {
let mut attributes = AttributeValues::new();
for (key, column) in &self.columns {
if let Some(cell) = column.clone_cell(index) {
attributes.0.push((key.clone(), cell));
if let Some(value) = column.clone_value(index) {
attributes.0.push((key.clone(), value));
}
}
@@ -500,8 +500,8 @@ impl AttributeColumns {
let mut rows: Vec<AttributeValues> = (0..self.len).map(|_| AttributeValues::new()).collect();
for (key, column) in self.columns {
for (i, cell) in column.drain().into_iter().enumerate() {
rows[i].0.push((key.clone(), cell));
for (i, value) in column.drain().into_iter().enumerate() {
rows[i].0.push((key.clone(), value));
}
}
@@ -640,38 +640,38 @@ impl<T> Table<T> {
/// Returns a shared reference to the attribute value at the given row index and key, if it exists and can be downcast to the requested type.
pub fn attribute<U: 'static>(&self, key: &str, index: usize) -> Option<&U> {
self.attributes.get_cell(key, index)
self.attributes.get_value(key, index)
}
/// Returns a clone of the attribute value at the given row index and key, or `U::default()` if absent or of a different type.
pub fn attribute_cloned_or_default<U: Clone + Default + 'static>(&self, key: &str, index: usize) -> U {
self.attributes.get_cell::<U>(key, index).cloned().unwrap_or_default()
self.attributes.get_value::<U>(key, index).cloned().unwrap_or_default()
}
/// Returns a clone of the attribute value at the given row index and key, or the provided default if absent or of a different type.
pub fn attribute_cloned_or<U: Clone + 'static>(&self, key: &str, index: usize, default: U) -> U {
self.attributes.get_cell::<U>(key, index).cloned().unwrap_or(default)
self.attributes.get_value::<U>(key, index).cloned().unwrap_or(default)
}
/// Sets the attribute value at the given row index and key, creating the column with defaults if it doesn't exist.
pub fn set_attribute<U: Clone + Send + Sync + Default + Debug + 'static>(&mut self, key: impl Into<String>, index: usize, value: U) {
self.attributes.set_cell(key, index, value);
self.attributes.set_value(key, index, value);
}
/// Runs the given closure on a mutable reference to the attribute value at the given row index,
/// creating the column with defaults if it doesn't exist, and returns the closure's result.
pub fn with_attribute_mut_or_default<U: Clone + Send + Sync + Default + Debug + 'static, R, F: FnOnce(&mut U) -> R>(&mut self, key: &str, index: usize, f: F) -> R {
f(self.attributes.get_or_insert_default_cell::<U>(key, index))
f(self.attributes.get_or_insert_default_value::<U>(key, index))
}
/// Returns a debug-formatted display string for the attribute at the given row index and key.
pub fn attribute_display_value(&self, key: &str, index: usize, overrides: fn(&dyn std::any::Any) -> Option<String>) -> Option<String> {
self.attributes.display_cell_value(key, index, overrides)
self.attributes.display_value(key, index, overrides)
}
/// Returns a type-erased reference to the attribute value at the given row index and key, or `None` if absent.
pub fn attribute_any(&self, key: &str, index: usize) -> Option<&dyn std::any::Any> {
self.attributes.get_any_cell(key, index)
self.attributes.get_any_value(key, index)
}
// =====================

View File

@@ -114,7 +114,7 @@ pub fn migrate_artboard<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Re
}
// Attributes (transform, alpha_blending, editor:layer) are not serialized, so migration only needs
// to recover the elements. Per-row attribute values are populated at runtime by the node graph.
// to recover the elements. Per-item attribute values are populated at runtime by the node graph.
Ok(match ArtboardFormat::deserialize(deserializer)? {
ArtboardFormat::ArtboardGroup(artboard_group) => artboard_group.artboards.into_iter().map(|(artboard, _)| TableRow::new_from_element(artboard)).collect(),
ArtboardFormat::OldArtboardTable(old_table) => old_table.element.into_iter().map(TableRow::new_from_element).collect(),

View File

@@ -127,8 +127,8 @@ impl From<Table<GradientStops>> for Graphic {
}
}
/// Deeply flattens a graphic table, collecting only elements matching a specific variant (extracted by `extract_variant`)
/// and discarding all other non-matching content. Recursion through `Graphic::Graphic` sub-tables composes transforms and opacity.
/// Deeply flattens a `Table<Graphic>`, collecting only elements matching a specific variant (extracted by `extract_variant`)
/// and discarding all other non-matching content. Recursion through `Graphic::Graphic` sub-`Table`s composes transforms and opacity.
fn flatten_graphic_table<T>(content: Table<Graphic>, extract_variant: fn(Graphic) -> Option<Table<T>>) -> Table<T> {
fn compose_alpha_blending(parent: AlphaBlending, child: AlphaBlending) -> AlphaBlending {
AlphaBlending {
@@ -146,7 +146,7 @@ fn flatten_graphic_table<T>(content: Table<Graphic>, extract_variant: fn(Graphic
let current_alpha_blending: AlphaBlending = current_graphic_row.attribute_cloned_or_default("alpha_blending");
match current_graphic_row.into_element() {
// Recurse into nested graphic tables, composing the parent's transform onto each child
// Recurse into nested `Table<Graphic>` items, composing the parent's transform onto each child
Graphic::Graphic(mut sub_table) => {
for index in 0..sub_table.len() {
let child_transform: DAffine2 = sub_table.attribute_cloned_or_default("transform", index);
@@ -158,7 +158,7 @@ fn flatten_graphic_table<T>(content: Table<Graphic>, extract_variant: fn(Graphic
flatten_recursive(output, sub_table, extract_variant);
}
// Try to extract the target variant; if it matches, push its rows with composed transform and opacity
// Try to extract the target variant; if it matches, push its items with composed transform and opacity
other => {
if let Some(typed_table) = extract_variant(other) {
for row in typed_table.into_iter() {
@@ -184,7 +184,7 @@ fn flatten_graphic_table<T>(content: Table<Graphic>, extract_variant: fn(Graphic
}
/// Maps from a concrete element type to its corresponding `Graphic` enum variant,
/// enabling type-directed casting of typed tables from a `Graphic` value.
/// enabling type-directed casting of typed `Table`s from a `Graphic` value.
pub trait TryFromGraphic: Clone + Sized {
fn try_from_graphic(graphic: Graphic) -> Option<Table<Self>>;
}
@@ -217,7 +217,7 @@ impl TryFromGraphic for GradientStops {
pub trait IntoGraphicTable {
fn into_graphic_table(self) -> Table<Graphic>;
/// Deeply flattens any content of type `T` within a graphic table, discarding all other content, and returning a flat table of only `T` elements.
/// Deeply flattens any content of type `T` within a `Table<Graphic>`, discarding all other content, and returning a flat `Table<T>`.
fn into_flattened_table<T: TryFromGraphic>(self) -> Table<T>
where
Self: std::marker::Sized,
@@ -505,7 +505,7 @@ pub fn migrate_graphic<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Res
}
// Attributes (transform, alpha_blending, editor:layer) are not serialized, so migration only needs
// to recover the elements. Per-row attribute values are populated at runtime by the node graph.
// to recover the elements. Per-item attribute values are populated at runtime by the node graph.
Ok(match GraphicFormat::deserialize(deserializer)? {
GraphicFormat::OldGraphicGroup(old) => old.elements.into_iter().map(|(graphic, _)| TableRow::new_from_element(graphic)).collect(),
GraphicFormat::OlderTableOldGraphicGroup(old) => old
@@ -524,7 +524,7 @@ pub fn migrate_graphic<'de, D: serde::Deserializer<'de>>(deserializer: D) -> Res
.flat_map(|element| element.elements.into_iter().map(|(graphic, _)| TableRow::new_from_element(graphic)))
.collect(),
GraphicFormat::Table(value) => {
// Try to deserialize as either table format
// Try to deserialize as either `Table` format
if let Ok(old_table) = serde_json::from_value::<Table<GraphicGroup>>(value.clone()) {
let mut graphic_table = Table::new();
for index in 0..old_table.len() {

View File

@@ -73,7 +73,7 @@ pub mod migrations {
Ok(match VectorFormat::deserialize(deserializer)? {
VectorFormat::Vector(vector) => Table::new_from_element(vector),
// Attributes (transform, alpha_blending, editor:layer) are not serialized, so migration only needs
// to recover the elements. Per-row attribute values are populated at runtime by the node graph.
// to recover the elements. Per-item attribute values are populated at runtime by the node graph.
VectorFormat::OldVectorData(old) => Table::new_from_element(Vector {
style: old.style,
colinear_manipulators: old.colinear_manipulators,

View File

@@ -320,7 +320,7 @@ pub fn migrate_image_frame<'de, D: serde::Deserializer<'de>>(deserializer: D) ->
}
// Attributes (transform, alpha_blending, editor:layer) are not serialized, so migration only needs
// to recover the elements. Per-row attribute values are populated at runtime by the node graph.
// to recover the elements. Per-item attribute values are populated at runtime by the node graph.
fn old_table_to_new_table<T>(old_table: OldTable<T>) -> Table<T> {
old_table.element.into_iter().map(TableRow::new_from_element).collect()
}
@@ -431,7 +431,7 @@ pub fn migrate_image_frame_row<'de, D: serde::Deserializer<'de>>(deserializer: D
}
// Attributes (transform, alpha_blending, editor:layer) are not serialized, so migration only needs
// to recover the element. Per-row attribute values are populated at runtime by the node graph.
// to recover the element. Per-item attribute values are populated at runtime by the node graph.
Ok(match FormatVersions::deserialize(deserializer)? {
FormatVersions::Image(image) => TableRow::new_from_element(Raster::new_cpu(image)),
FormatVersions::OldImageFrame(old) => TableRow::new_from_element(Raster::new_cpu(old.image)),

View File

@@ -410,7 +410,7 @@ impl Render for Graphic {
}
Graphic::Vector(table) => {
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than the first row
// TODO: Find a way to handle more than the first item
if !table.is_empty() {
let layer_path: Table<NodeId> = table.attribute_cloned_or_default("editor:layer", 0);
let layer = layer_path.iter_element_values().next_back().copied();
@@ -423,7 +423,7 @@ impl Render for Graphic {
Graphic::RasterCPU(table) => {
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than the first row
// TODO: Find a way to handle more than the first item
if !table.is_empty() {
metadata.local_transforms.insert(element_id, table.attribute_cloned_or_default("transform", 0));
}
@@ -431,7 +431,7 @@ impl Render for Graphic {
Graphic::RasterGPU(table) => {
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than the first row
// TODO: Find a way to handle more than the first item
if !table.is_empty() {
metadata.local_transforms.insert(element_id, table.attribute_cloned_or_default("transform", 0));
}
@@ -439,7 +439,7 @@ impl Render for Graphic {
Graphic::Color(table) => {
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than the first row
// TODO: Find a way to handle more than the first item
if !table.is_empty() {
metadata.local_transforms.insert(element_id, table.attribute_cloned_or_default("transform", 0));
}
@@ -447,7 +447,7 @@ impl Render for Graphic {
Graphic::Gradient(table) => {
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than the first row
// TODO: Find a way to handle more than the first item
if !table.is_empty() {
metadata.local_transforms.insert(element_id, table.attribute_cloned_or_default("transform", 0));
}
@@ -817,7 +817,7 @@ impl Render for Table<Graphic> {
if let Some(element_id) = layer {
element.collect_metadata(metadata, footprint, Some(element_id));
} else {
// Recurse through anonymous wrapper rows to reach nested content with editor:layer tags
// Recurse through anonymous wrapper items to reach nested content with editor:layer tags
element.collect_metadata(metadata, footprint, None);
}
}
@@ -1334,7 +1334,7 @@ impl Render for Table<Vector> {
let layer = layer_path.iter_element_values().next_back().copied();
if let Some(element_id) = caller_element_id.or(layer) {
// When recovering element_id from the row's editor:layer tag (because the caller
// When recovering element_id from the item's editor:layer tag (because the caller
// passed None), also store the transform metadata that Graphic::collect_metadata
// normally provides but skipped due to the None element_id.
if caller_element_id.is_none() {
@@ -1375,7 +1375,7 @@ impl Render for Table<Vector> {
metadata.vector_data.entry(element_id).or_insert_with(|| Arc::new(vector.clone()));
}
// If this row carries a snapshot of upstream graphic content (e.g. it was produced by Boolean Operation,
// If this item carries a snapshot of upstream graphic content (e.g. it was produced by Boolean Operation,
// Flatten Path, Morph, or any other destructive merge), recurse into that snapshot so the editor can
// surface the original child layers' click targets.
let upstream_nested_layers = self.attribute_cloned_or_default::<Table<Graphic>>("editor:merged_layers", index);
@@ -1575,7 +1575,7 @@ impl Render for Table<Raster<CPU>> {
metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.).into()]);
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than one row of the raster table
// TODO: Find a way to handle more than one item of the `Table<Raster<...>>`
if !self.is_empty() {
let transform: DAffine2 = self.attribute_cloned_or_default("transform", 0);
metadata.local_transforms.insert(element_id, transform);
@@ -1665,7 +1665,7 @@ impl Render for Table<Raster<GPU>> {
metadata.click_targets.insert(element_id, vec![ClickTarget::new_with_subpath(subpath, 0.).into()]);
metadata.upstream_footprints.insert(element_id, footprint);
// TODO: Find a way to handle more than one row of the raster table
// TODO: Find a way to handle more than one item of the `Table<Raster<...>>`
if !self.is_empty() {
let transform: DAffine2 = self.attribute_cloned_or_default("transform", 0);
metadata.local_transforms.insert(element_id, transform);

View File

@@ -18,7 +18,7 @@ impl<PointId: Identifier> Subpath<PointId> {
let mut intersections_vec = Vec::new();
let err = accuracy.unwrap_or(MAX_ABSOLUTE_DIFFERENCE);
let num_curves = self.len();
// TODO: optimization opportunity - this for-loop currently compares all intersections with all curve-segments in the subpath collection
// TODO: optimization opportunity - this for-loop currently compares all intersections with all curve-segments in the subpath list
self.iter_closed().enumerate().for_each(|(i, other)| {
intersections_vec.extend(pathseg_self_intersections(other, accuracy, minimum_separation).iter().flat_map(|value| [(i, value.0), (i, value.1)]));
self.iter_closed().enumerate().skip(i + 1).for_each(|(j, curve)| {

View File

@@ -137,14 +137,14 @@ impl RasterGpuToRasterCpuConverter {
}
}
/// Passthrough conversion for GPU tables - no conversion needed
/// Passthrough conversion for GPU `Table`s - no conversion needed
impl<'i> Convert<Table<Raster<GPU>>, &'i WgpuExecutor> for Table<Raster<GPU>> {
async fn convert(self, _: Footprint, _converter: &'i WgpuExecutor) -> Table<Raster<GPU>> {
self
}
}
/// Converts CPU raster table to GPU by uploading each image to a texture
/// Converts a `Table<Raster<CPU>>` to `Table<Raster<GPU>>` by uploading each image to a texture
impl<'i> Convert<Table<Raster<GPU>>, &'i WgpuExecutor> for Table<Raster<CPU>> {
async fn convert(self, _: Footprint, executor: &'i WgpuExecutor) -> Table<Raster<GPU>> {
let device = &executor.context.device;
@@ -176,16 +176,14 @@ impl<'i> Convert<Raster<GPU>, &'i WgpuExecutor> for Raster<CPU> {
}
}
/// Passthrough conversion for CPU tables - no conversion needed
/// Passthrough conversion for CPU `Table`s - no conversion needed
impl<'i> Convert<Table<Raster<CPU>>, &'i WgpuExecutor> for Table<Raster<CPU>> {
async fn convert(self, _: Footprint, _converter: &'i WgpuExecutor) -> Table<Raster<CPU>> {
self
}
}
/// Converts GPU raster table to CPU by downloading texture data in one go
///
/// then asynchronously maps all buffers and processes the results.
/// Converts a `Table<Raster<GPU>>` to `Table<Raster<CPU>>` by downloading texture data in one go then asynchronously maps all buffers and processes the results.
impl<'i> Convert<Table<Raster<CPU>>, &'i WgpuExecutor> for Table<Raster<GPU>> {
async fn convert(self, _: Footprint, executor: &'i WgpuExecutor) -> Table<Raster<CPU>> {
let device = &executor.context.device;
@@ -218,7 +216,7 @@ impl<'i> Convert<Table<Raster<CPU>>, &'i WgpuExecutor> for Table<Raster<GPU>> {
map_results
.into_iter()
.zip(rows_meta.into_iter())
.zip(rows_meta)
.map(|(element, row)| {
let (_, attributes) = row.into_parts();
TableRow::from_parts(element, attributes)
@@ -247,7 +245,7 @@ impl<'i> Convert<Raster<CPU>, &'i WgpuExecutor> for Raster<GPU> {
/// Uploads an raster texture from the CPU to the GPU. This is now deprecated and the Convert node should be used in the future.
///
/// Accepts either individual raster data or a table of raster elements and converts it to the GPU format using the WgpuExecutor's device and queue.
/// Accepts either individual raster data or a `Table` of raster elements and converts it to the GPU format using the WgpuExecutor's device and queue.
#[node_macro::node(category(""))]
pub async fn upload_texture<'a: 'n, T: Convert<Table<Raster<GPU>>, &'a WgpuExecutor>>(
_: impl Ctx,