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

@@ -192,7 +192,7 @@ fn blend_mode<T: SetBlendMode>(
/// The choice of equation that controls how brightness and color blends between overlapping pixels.
blend_mode: BlendMode,
) -> T {
// TODO: Find a way to make this apply once to the table's parent (i.e. its row in its parent table or TableRow<T>) rather than applying to each row in its own table, which produces the undesired result
// TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or TableRow<T>) rather than applying to each item in its own table, which produces the undesired result
content.set_blend_mode(blend_mode);
content
}
@@ -216,7 +216,7 @@ fn opacity<T: MultiplyAlpha>(
#[default(100.)]
opacity: Percentage,
) -> T {
// TODO: Find a way to make this apply once to the table's parent (i.e. its row in its parent table or TableRow<T>) rather than applying to each row in its own table, which produces the undesired result
// TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or TableRow<T>) rather than applying to each item in its own table, which produces the undesired result
content.multiply_alpha(opacity / 100.);
content
}
@@ -247,7 +247,7 @@ fn blending<T: SetBlendMode + MultiplyAlpha + MultiplyFill + SetClip>(
/// Whether the content inherits the alpha of the content beneath it.
clip: bool,
) -> T {
// TODO: Find a way to make this apply once to the table's parent (i.e. its row in its parent table or TableRow<T>) rather than applying to each row in its own table, which produces the undesired result
// TODO: Find a way to make this apply once to the table's parent (i.e. its item in its parent table or TableRow<T>) rather than applying to each item in its own table, which produces the undesired result
content.set_blend_mode(blend_mode);
content.multiply_alpha(opacity / 100.);
content.multiply_fill(fill / 100.);

View File

@@ -199,8 +199,8 @@ async fn brush(
if image.is_empty() {
image.push(TableRow::default());
}
// TODO: Find a way to handle more than one row
let table_row = image.clone_row(0).expect("Expected the one row we just pushed");
// TODO: Find a way to handle more than one item
let table_row = image.clone_row(0).expect("Expected the one item we just pushed");
let bounds = Table::new_from_row(table_row.clone()).bounding_box(DAffine2::IDENTITY, false);
let [start, end] = if let RenderBoundingBox::Rectangle(rect) = bounds { rect } else { [DVec2::ZERO, DVec2::ZERO] };
@@ -217,7 +217,7 @@ async fn brush(
let mut brush_plan = cache.compute_brush_plan(table_row, &draw_strokes);
// TODO: Find a way to handle more than one row
// TODO: Find a way to handle more than one item
let Some(mut actual_image) = extend_image_to_bounds((), Table::new_from_row(brush_plan.background), background_bounds).into_iter().next() else {
return Table::new();
};

View File

@@ -64,7 +64,7 @@ impl BrushCacheImpl {
background = std::mem::take(&mut self.blended_image);
// Check if the first non-blended stroke is an extension of the last one.
// Transform is set to ZERO (not the default IDENTITY) as a sentinel to mark this row as uninitialized.
// Transform is set to ZERO (not the default IDENTITY) as a sentinel to mark this item as uninitialized.
let mut first_stroke_texture = TableRow::new_from_element(Raster::<CPU>::default()).with_attribute("transform", glam::DAffine2::ZERO);
let mut first_stroke_point_skip = 0;
let strokes = input[num_blended_strokes..].to_vec();

View File

@@ -60,7 +60,7 @@ async fn read_position(
// TODO: Return u32, u64, or usize instead of f64 after #1621 is resolved and has allowed us to implement automatic type conversion in the node graph for nodes with generic type inputs.
// TODO: (Currently automatic type conversion only works for concrete types, via the Graphene preprocessor and not the full Graphene type system.)
/// Produces the index of the current iteration of a loop by reading from the evaluation context, which is supplied by downstream nodes such as *Instance Repeat*.
/// Produces the index of the current iteration of a loop by reading from the evaluation context, which is supplied by downstream nodes such as *Repeat*.
///
/// Nested loops can enable 2D or higher-dimensional iteration by using the *Loop Level* parameter to read the index from outer levels of loops.
#[node_macro::node(category("Context"), path(core_types::vector))]

View File

@@ -7,7 +7,7 @@ use graphic_types::{
use raster_types::{CPU, GPU, Raster};
use vector_types::GradientStops;
/// Constructs a new single artboard table with the chosen properties.
/// Constructs a new single-item `Table<Artboard>` with the chosen properties.
#[node_macro::node(category(""))]
pub async fn create_artboard<T: IntoGraphicTable + 'n>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,

View File

@@ -9,12 +9,12 @@ use graphic_types::{Artboard, Vector};
use raster_types::{CPU, GPU, Raster};
use vector_types::{GradientStop, GradientStops, ReferencePoint};
/// Returns the value at the specified index in the collection.
/// Returns the value at the specified index in the list.
/// If no value exists at that index, the type's default value is returned.
#[node_macro::node(category("General"))]
pub fn index_elements<T: graphic_types::graphic::AtIndex + Clone + Default>(
_: impl Ctx,
/// The collection of data, such as a list or table.
/// The list of data.
#[implementations(
Table<Artboard>,
Table<Graphic>,
@@ -28,8 +28,8 @@ pub fn index_elements<T: graphic_types::graphic::AtIndex + Clone + Default>(
Table<u8>,
Table<NodeId>,
)]
collection: T,
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the collection, starting from -1 for the last item.
list: T,
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the list, starting from -1 for the last item.
index: SignedInteger,
) -> T::Output
where
@@ -37,20 +37,15 @@ where
{
let index = index as i32;
if index < 0 {
collection.at_index_from_end(-index as usize)
} else {
collection.at_index(index as usize)
}
.unwrap_or_default()
if index < 0 { list.at_index_from_end(-index as usize) } else { list.at_index(index as usize) }.unwrap_or_default()
}
/// Returns the collection with the element at the specified index removed.
/// If no value exists at that index, the collection is returned unchanged.
/// Returns the list with the element at the specified index removed.
/// If no value exists at that index, the list is returned unchanged.
#[node_macro::node(category("General"))]
pub fn omit_element<T: graphic_types::graphic::OmitIndex + Clone + Default>(
_: impl Ctx,
/// The collection of data, such as a list or table.
/// The list of data.
#[implementations(
Table<String>,
Table<Artboard>,
@@ -61,26 +56,26 @@ pub fn omit_element<T: graphic_types::graphic::OmitIndex + Clone + Default>(
Table<Color>,
Table<GradientStops>,
)]
collection: T,
/// The index of the item to remove, starting from 0 for the first item. Negative indices count backwards from the end of the collection, starting from -1 for the last item.
list: T,
/// The index of the item to remove, starting from 0 for the first item. Negative indices count backwards from the end of the list, starting from -1 for the last item.
index: SignedInteger,
) -> T {
let index = index as i32;
if index < 0 {
collection.omit_index_from_end(index.unsigned_abs() as usize)
list.omit_index_from_end(index.unsigned_abs() as usize)
} else {
collection.omit_index(index as usize)
list.omit_index(index as usize)
}
}
/// Returns the bare element (without its row attributes) at the specified index in a table.
/// Use this when downstream nodes want just the inner value rather than a single-row table.
/// Returns the bare element (without the item's attributes) at the specified index in a `Table`.
/// Use this when downstream nodes want just the inner value rather than a `Table` containing a single item.
/// If no value exists at that index, the element type's default is returned.
#[node_macro::node(category("General"))]
pub fn extract_element<T: Clone + Default + Send + Sync + 'static>(
_: impl Ctx,
/// The table of data to extract from.
/// The `Table` of data to extract from.
#[implementations(
Table<String>,
Table<f64>,
@@ -94,7 +89,7 @@ pub fn extract_element<T: Clone + Default + Send + Sync + 'static>(
Table<Artboard>,
)]
table: Table<T>,
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the collection, starting from -1 for the last item.
/// The index of the item to retrieve, starting from 0 for the first item. Negative indices count backwards from the end of the list, starting from -1 for the last item.
index: SignedInteger,
) -> T {
let len = table.len();
@@ -192,14 +187,14 @@ where
let mut result_table = Table::new();
// Add original instance depending on the keep_original flag
// Add original items depending on the keep_original flag
if keep_original {
for instance in content.clone().into_iter() {
result_table.push(instance);
for item in content.clone().into_iter() {
result_table.push(item);
}
}
// Create and add mirrored instance
// Create and add mirrored items
for mut row in content.into_iter() {
let current_transform: DAffine2 = row.attribute_cloned_or_default("transform");
row.set_attribute("transform", reflected_transform * current_transform);
@@ -212,7 +207,7 @@ where
/// Returns the path identifying the subgraph (network) that contains this proto node — i.e. the input `node_path`
/// with its own trailing entry dropped. The terminating element of the returned path is the document node whose
/// encapsulated network we live in, so the path doubles as a unique reference to that node at any nesting depth.
/// Used as the value source for stamping the `editor:layer` attribute on each row of a layer's output, which lets
/// Used as the value source for stamping the `editor:layer` attribute on each item of a layer's output, which lets
/// editor tools (e.g. selection, click target routing) trace data back to its owning layer regardless of whether
/// the layer is at the root document network or nested inside a custom subgraph.
#[node_macro::node(name("Path of Subgraph"), category(""))]
@@ -221,14 +216,14 @@ pub fn path_of_subgraph(_: impl Ctx, node_path: Table<NodeId>) -> Table<NodeId>
node_path.into_iter().take(len.saturating_sub(1)).collect()
}
/// Writes a per-row attribute column on the input table. The value-producing input is evaluated once per row,
/// with the row's element index and the row itself (as a single-row table vararg) passed via context, so the
/// upstream pipeline can return a different value per row that may be derived from the row's own data.
/// If the column already exists, its values are replaced; if not, the column is created.
/// Writes a named attribute on each item of the input `Table`. The value-producing input is evaluated once per item,
/// with the item's index and the item itself (as a `Table` containing only that item, passed as a vararg) provided via
/// context, so the upstream pipeline can return a different value per item that may be derived from the item's own data.
/// If the attribute already exists, its values are replaced; if not, the attribute is added.
#[node_macro::node(category("General"))]
async fn write_attribute<T: AnyHash + Clone + Send + Sync + core_types::CacheHash, U: Clone + Send + Sync + Default + std::fmt::Debug + 'static>(
ctx: impl ExtractAll + CloneVarArgs + Ctx,
/// The table whose rows will gain or replace the named attribute column.
/// The `Table` whose items will gain or have replaced the named attribute.
#[implementations(
Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>, Table<Artboard>,
Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>, Table<Graphic>,
@@ -239,9 +234,9 @@ async fn write_attribute<T: AnyHash + Clone + Send + Sync + core_types::CacheHas
Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>, Table<GradientStops>,
)]
mut content: Table<T>,
/// The attribute name (column key) to write or replace.
/// The attribute name (key) to write or replace.
name: String,
/// The node that produces the per-row value. Called once per row with the row index in context.
/// The node that produces the attribute value for each item. Called once per item with the item's index in context.
#[implementations(
Context -> f64, Context -> u32, Context -> bool, Context -> String, Context -> Table<String>, Context -> DVec2, Context -> DAffine2, Context -> Table<NodeId>, Context -> Table<Color>, Context -> Table<GradientStops>,
Context -> f64, Context -> u32, Context -> bool, Context -> String, Context -> Table<String>, Context -> DVec2, Context -> DAffine2, Context -> Table<NodeId>, Context -> Table<Color>, Context -> Table<GradientStops>,
@@ -262,14 +257,14 @@ async fn write_attribute<T: AnyHash + Clone + Send + Sync + core_types::CacheHas
content
}
/// Joins two tables of the same type, extending the base table with the rows of the new table.
/// Joins two `Table`s of the same type, extending the base `Table` with the items from the new `Table`.
#[node_macro::node(category("General"))]
pub async fn extend<T: 'n + Send + Clone>(
_: impl Ctx,
/// The table whose rows will appear at the start of the extended table.
/// The `Table` whose items will appear at the start of the extended `Table`.
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>, Table<Color>, Table<GradientStops>)]
base: Table<T>,
/// The table whose rows will appear at the end of the extended table.
/// The `Table` whose items will appear at the end of the extended `Table`.
#[expose]
#[implementations(Table<Artboard>, Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Raster<GPU>>, Table<Color>, Table<GradientStops>)]
new: Table<T>,
@@ -327,8 +322,8 @@ pub async fn wrap_graphic<T: Into<Graphic> + 'n>(
Table::new_from_element(content.into())
}
/// Converts a table of graphical content into a graphic table by placing it into an element of a new wrapper graphic table.
/// If it is already a graphic table, it is not wrapped again. Use the 'Wrap Graphic' node if wrapping is always desired.
/// Converts a `Table` of graphical content into a `Table<Graphic>` by placing it into an element of a new wrapper `Table<Graphic>`.
/// If it is already a `Table<Graphic>`, it is not wrapped again. Use the 'Wrap Graphic' node if wrapping is always desired.
#[node_macro::node(category("General"))]
pub async fn to_graphic<T: IntoGraphicTable + 'n>(
_: impl Ctx,
@@ -345,7 +340,7 @@ pub async fn to_graphic<T: IntoGraphicTable + 'n>(
content.into_graphic_table()
}
/// Removes a level of nesting from a graphic table, or all nesting if "Fully Flatten" is enabled.
/// Removes a level of nesting from a `Table<Graphic>`, or all nesting if "Fully Flatten" is enabled.
#[node_macro::node(category("General"))]
pub async fn flatten_graphic(_: impl Ctx, content: Table<Graphic>, fully_flatten: bool) -> Table<Graphic> {
// TODO: Avoid mutable reference, instead return a new Table<Graphic>?
@@ -367,7 +362,7 @@ pub async fn flatten_graphic(_: impl Ctx, content: Table<Graphic>, fully_flatten
flatten_table(output_graphic_table, current_element, fully_flatten, recursion_depth + 1);
}
// Push any leaf Graphic elements we encounter, which can be either Graphic table elements beyond the recursion depth, or table elements other than Graphic tables
// Push any leaf elements we encounter: either `Graphic::Graphic(...)` values beyond the recursion depth, or non-`Graphic::Graphic` variants (e.g. `Graphic::Vector`, `Graphic::Raster*`, `Graphic::Color`, `Graphic::Gradient`)
_ => {
let attributes = current_graphic_table.clone_row_attributes(index);
output_graphic_table.push(TableRow::from_parts(current_element, attributes));
@@ -382,31 +377,31 @@ pub async fn flatten_graphic(_: impl Ctx, content: Table<Graphic>, fully_flatten
output
}
/// Converts a graphic table into a vector table by deeply flattening any vector content it contains, and discarding any non-vector content.
/// Converts a `Table<Graphic>` into a `Table<Vector>` by deeply flattening any vector content it contains, and discarding any non-vector content.
#[node_macro::node(category("Vector"))]
pub async fn flatten_vector<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Vector>)] content: T) -> Table<Vector> {
content.into_flattened_table()
}
/// Converts a graphic table into a raster table by deeply flattening any raster content it contains, and discarding any non-raster content.
/// Converts a `Table<Graphic>` into a `Table<Raster>` by deeply flattening any raster content it contains, and discarding any non-raster content.
#[node_macro::node(category("Raster"))]
pub async fn flatten_raster<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Raster<CPU>>)] content: T) -> Table<Raster<CPU>> {
content.into_flattened_table()
}
/// Converts a graphic table into a color table by deeply flattening any color content it contains, and discarding any non-color content.
/// Converts a `Table<Graphic>` into a `Table<Color>` by deeply flattening any color content it contains, and discarding any non-color content.
#[node_macro::node(category("General"))]
pub async fn flatten_color<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Color>)] content: T) -> Table<Color> {
content.into_flattened_table()
}
/// Converts a graphic table into a gradient table by deeply flattening any gradient content it contains, and discarding any non-gradient content.
/// Converts a `Table<Graphic>` into a `Table<GradientStops>` by deeply flattening any gradient content it contains, and discarding any non-gradient content.
#[node_macro::node(category("General"))]
pub async fn flatten_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<GradientStops>)] content: T) -> Table<GradientStops> {
content.into_flattened_table()
}
/// Constructs a gradient from a table of colors, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
/// Constructs a gradient from a `Table<Color>`, where the colors are evenly distributed as gradient stops across the range from 0 to 1.
#[node_macro::node(category("Color"))]
fn colors_to_gradient<T: IntoGraphicTable + 'n + Send + Clone>(_: impl Ctx, #[implementations(Table<Graphic>, Table<Color>)] colors: T) -> Table<GradientStops> {
let colors = colors.into_flattened_table::<Color>();

View File

@@ -14,14 +14,14 @@ use vector_types::kurbo::{Affine, BezPath, CubicBez, Line, ParamCurve, PathSeg,
pub use vector_types::vector::misc::BooleanOperation;
// TODO: Fix boolean ops to work by removing .transform() and .one_instance_*() calls,
// TODO: since before we used a Vec of single-row tables and now we use a single table
// TODO: with multiple rows while still assuming a single row for the boolean operations.
// TODO: since before we used a Vec of single-item `Table`s and now we use a single `Table`
// TODO: with multiple items while still assuming a single item for the boolean operations.
/// Combines the geometric forms of one or more closed paths into a new vector path that results from cutting or joining the paths by the chosen method.
#[node_macro::node(category("Vector: Modifier"), memoize)]
async fn boolean_operation<I: graphic_types::IntoGraphicTable + 'n + Send + Clone>(
_: impl Ctx,
/// The table of vector paths to perform the boolean operation on. Nested tables are automatically flattened.
/// The `Table` of vector paths to perform the boolean operation on. Nested `Table`s are automatically flattened.
#[implementations(Table<Graphic>, Table<Vector>)]
content: I,
/// Which boolean operation to perform on the paths.
@@ -47,7 +47,7 @@ async fn boolean_operation<I: graphic_types::IntoGraphicTable + 'n + Send + Clon
Vector::transform(result_vector, transform);
result_vector.style.set_stroke_transform(DAffine2::IDENTITY);
// Snapshot the input layers as the `editor:merged_layers` row attribute so the renderer can recurse into them
// Snapshot the input layers as the `editor:merged_layers` attribute so the renderer can recurse into them
// for editor click-target preservation.
result_vector_table.set_attribute("editor:merged_layers", 0, content.clone());
@@ -125,7 +125,7 @@ fn boolean_operation_on_vector_table(vector: &Table<Vector>, boolean_operation:
};
let mut row = if let Some(index) = copy_from_index {
let mut attributes = vector.clone_row_attributes(index);
// The boolean op bakes input transforms into the output geometry, so the result row carries no transform of its own
// The boolean op bakes input transforms into the output geometry, so the result item carries no transform of its own
attributes.insert("transform", DAffine2::IDENTITY);
let copy_from = vector.element(index).unwrap();
let element = Vector {
@@ -166,7 +166,7 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
let graphic = graphic_table.element(index).unwrap();
match graphic.clone() {
Graphic::Vector(vector) => {
// Apply the parent graphic's transform to each element of the vector table
// Apply the parent graphic's transform to each element of the `Table<Vector>`
let parent_transform: DAffine2 = graphic_table.attribute_cloned_or_default("transform", index);
vector
.into_iter()
@@ -191,7 +191,7 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
.with_attribute("editor:layer", layer)
};
// Apply the parent graphic's transform to each raster element, preserving each row's layer
// Apply the parent graphic's transform to each raster element, preserving each item's layer
// and alpha_blending so the boolean op downstream can route clicks (and inherit blending state)
// back to the originating raster layer
(0..image.len())
@@ -217,7 +217,7 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
.with_attribute("editor:layer", layer)
};
// Apply the parent graphic's transform to each raster element, preserving each row's layer
// Apply the parent graphic's transform to each raster element, preserving each item's layer
// and alpha_blending so the boolean op downstream can route clicks (and inherit blending state)
// back to the originating raster layer
(0..image.len())
@@ -231,12 +231,12 @@ fn flatten_vector(graphic_table: &Table<Graphic>) -> Table<Vector> {
}
Graphic::Graphic(mut graphic) => {
let parent_transform: DAffine2 = graphic_table.attribute_cloned_or_default("transform", index);
// Apply the parent graphic's transform to each element of inner table
// Apply the parent graphic's transform to each element of the inner `Table`
for transform in graphic.iter_attribute_values_mut_or_default::<DAffine2>("transform") {
*transform = parent_transform * *transform;
}
// Recursively flatten the inner table into the output vector table
// Recursively flatten the inner `Table` into the output `Table<Vector>`
let flattened = flatten_vector(&graphic);
let unioned = boolean_operation_on_vector_table(&flattened, BooleanOperation::Union);

View File

@@ -112,13 +112,13 @@ pub fn combine_channels(
.zip(blue)
.zip(alpha)
.filter_map(|(((red, green), blue), alpha)| {
// Turn any default zero-sized image rows into None
// Turn any default zero-sized image items into None
let red = red.filter(|i| i.element().width > 0 && i.element().height > 0);
let green = green.filter(|i| i.element().width > 0 && i.element().height > 0);
let blue = blue.filter(|i| i.element().width > 0 && i.element().height > 0);
let alpha = alpha.filter(|i| i.element().width > 0 && i.element().height > 0);
// Get this row's transform and alpha blending mode from the first non-empty channel
// Get this item's transform and alpha blending mode from the first non-empty channel
let attributes = [&red, &green, &blue, &alpha].iter().find_map(|i| i.as_ref()).map(|i| i.attributes().clone())?;
// Get the common width and height of the channels, which must have equal dimensions
@@ -183,7 +183,7 @@ pub fn mask(
#[expose]
stencil: Table<Raster<CPU>>,
) -> Table<Raster<CPU>> {
// TODO: Figure out what it means to support multiple stencil rows?
// TODO: Figure out what it means to support multiple stencil items?
let Some(stencil) = stencil.into_iter().next() else {
// No stencil provided so we return the original image
return image;
@@ -285,7 +285,7 @@ pub fn empty_image(_: impl Ctx, transform: DAffine2, color: Table<Color>) -> Tab
result_table.set_attribute("transform", 0, transform);
result_table.set_attribute("alpha_blending", 0, AlphaBlending::default());
// Callers of empty_image can safely unwrap on returned table
// Callers of empty_image can safely unwrap on returned `Table`
result_table
}

View File

@@ -18,7 +18,7 @@ async fn repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> Table<Color>,
Context -> Table<GradientStops>,
)]
instance: impl Node<'n, Context<'static>, Output = Table<T>>,
content: impl Node<'n, Context<'static>, Output = Table<T>>,
#[default(1)]
#[hard_min(1)]
count: u32,
@@ -34,9 +34,9 @@ async fn repeat<T: Into<Graphic> + Default + Send + Clone + 'static>(
let index = if reverse { count - index - 1 } else { index };
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index);
let generated_instance = instance.eval(new_ctx.into_context()).await;
let generated_content = content.eval(new_ctx.into_context()).await;
for generated_row in generated_instance.into_iter() {
for generated_row in generated_content.into_iter() {
result_table.push(generated_row);
}
}
@@ -54,7 +54,7 @@ pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> Table<Color>,
Context -> Table<GradientStops>,
)]
instance: impl Node<'n, Context<'static>, Output = Table<T>>,
content: impl Node<'n, Context<'static>, Output = Table<T>>,
#[default(100., 100.)]
// TODO: When using a custom Properties panel layout in document_node_definitions.rs and this default is set, the widget weirdly doesn't show up in the Properties panel. Investigation is needed.
direction: PixelSize,
@@ -75,10 +75,10 @@ pub async fn repeat_array<T: Into<Graphic> + Default + Send + Clone + 'static>(
let transform = DAffine2::from_angle(angle) * DAffine2::from_translation(translation);
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index as usize);
let generated_instance = instance.eval(new_ctx.into_context()).await;
let generated_content = content.eval(new_ctx.into_context()).await;
for row_index in 0..generated_instance.len() {
let Some(mut row) = generated_instance.clone_row(row_index) else { continue };
for row_index in 0..generated_content.len() {
let Some(mut row) = generated_content.clone_row(row_index) else { continue };
let local_transform: DAffine2 = row.attribute_cloned_or_default("transform");
let local_translation = DAffine2::from_translation(local_transform.translation);
@@ -102,7 +102,7 @@ async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> Table<Color>,
Context -> Table<GradientStops>,
)]
instance: impl Node<'n, Context<'static>, Output = Table<T>>,
content: impl Node<'n, Context<'static>, Output = Table<T>>,
start_angle: Angle,
#[unit(" px")]
#[default(5)]
@@ -121,10 +121,10 @@ async fn repeat_radial<T: Into<Graphic> + Default + Send + Clone + 'static>(
let transform = angle * translation;
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index as usize);
let generated_instance = instance.eval(new_ctx.into_context()).await;
let generated_content = content.eval(new_ctx.into_context()).await;
for row_index in 0..generated_instance.len() {
let Some(mut row) = generated_instance.clone_row(row_index) else { continue };
for row_index in 0..generated_content.len() {
let Some(mut row) = generated_content.clone_row(row_index) else { continue };
let local_transform: DAffine2 = row.attribute_cloned_or_default("transform");
let local_translation = DAffine2::from_translation(local_transform.translation);
@@ -149,7 +149,7 @@ async fn repeat_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
Context -> Table<Color>,
Context -> Table<GradientStops>,
)]
instance: impl Node<'n, Context<'static>, Output = Table<T>>,
content: impl Node<'n, Context<'static>, Output = Table<T>>,
reverse: bool,
) -> Table<T> {
let mut result_table = Table::new();
@@ -162,9 +162,9 @@ async fn repeat_on_points<T: Into<Graphic> + Default + Send + Clone + 'static>(
let transformed_point = transform.transform_point2(point);
let new_ctx = OwnedContextImpl::from(ctx.clone()).with_index(index).with_position(transformed_point);
let generated_instance = instance.eval(new_ctx.into_context()).await;
let generated_content = content.eval(new_ctx.into_context()).await;
for mut generated_row in generated_instance.into_iter() {
for mut generated_row in generated_content.into_iter() {
generated_row.attribute_mut_or_insert_default::<DAffine2>("transform").translation = transformed_point;
result_table.push(generated_row);
}

View File

@@ -215,7 +215,7 @@ fn query_json(
/// Extracts every matched value from a JSON string using a path expression (see that parameter's description for its syntax). A list of zero or more resultant strings is produced. The `[]` path accessor is used to read more than one value.
///
/// Each row carries a `type` attribute holding the matched value's JSON type (`"string"`, `"number"`, `"bool"`, `"null"`, `"object"`, or `"array"`).
/// Each item carries a `type` attribute holding the matched value's JSON type (`"string"`, `"number"`, `"bool"`, `"null"`, `"object"`, or `"array"`).
///
/// This is useful in conjunction with the nodes:
/// • **Index Elements**: access the `N`th query result.

View File

@@ -19,11 +19,11 @@ pub struct PathBuilder {
}
impl PathBuilder {
pub fn new(per_glyph_instances: bool, scale: f64) -> Self {
pub fn new(per_glyph_items: bool, scale: f64) -> Self {
Self {
current_subpath: Subpath::new(Vec::new(), false),
glyph_subpaths: Vec::new(),
vector_table: if per_glyph_instances { Table::new() } else { Table::new_from_element(Vector::default()) },
vector_table: if per_glyph_items { Table::new() } else { Table::new_from_element(Vector::default()) },
scale,
id: PointId::ZERO,
origin: DVec2::default(),
@@ -35,7 +35,7 @@ impl PathBuilder {
}
#[allow(clippy::too_many_arguments)]
fn draw_glyph(&mut self, glyph: &OutlineGlyph<'_>, size: f32, normalized_coords: &[NormalizedCoord], glyph_offset: DVec2, style_skew: Option<DAffine2>, skew: DAffine2, per_glyph_instances: bool) {
fn draw_glyph(&mut self, glyph: &OutlineGlyph<'_>, size: f32, normalized_coords: &[NormalizedCoord], glyph_offset: DVec2, style_skew: Option<DAffine2>, skew: DAffine2, per_glyph_items: bool) {
let location_ref = LocationRef::new(normalized_coords);
let settings = DrawSettings::unhinted(Size::new(size), location_ref);
glyph.draw(settings, self).unwrap();
@@ -50,18 +50,18 @@ impl PathBuilder {
glyph_subpath.apply_transform(skew);
}
if per_glyph_instances {
if per_glyph_items {
self.vector_table
.push(TableRow::new_from_element(Vector::from_subpaths(core::mem::take(&mut self.glyph_subpaths), false)).with_attribute("transform", DAffine2::from_translation(glyph_offset)));
} else {
for subpath in self.glyph_subpaths.drain(..) {
// Unwrapping here is ok because `self.vector_table` is initialized with a single `Vector` table element
// Unwrapping here is ok because `self.vector_table` is initialized with a single `Table<Vector>` item
self.vector_table.element_mut(0).unwrap().append_subpath(subpath, false);
}
}
}
pub fn render_glyph_run(&mut self, glyph_run: &GlyphRun<'_, ()>, tilt: f64, per_glyph_instances: bool) {
pub fn render_glyph_run(&mut self, glyph_run: &GlyphRun<'_, ()>, tilt: f64, per_glyph_items: bool) {
let mut run_x = glyph_run.offset();
let run_y = glyph_run.baseline();
@@ -69,7 +69,7 @@ impl PathBuilder {
// User-requested tilt applied around baseline to avoid vertical displacement
// Translation ensures rotation point is at the baseline, not origin
let skew = if per_glyph_instances {
let skew = if per_glyph_items {
DAffine2::from_cols_array(&[1., 0., -tilt.to_radians().tan(), 1., 0., 0.])
} else {
DAffine2::from_translation(DVec2::new(0., run_y as f64))
@@ -82,7 +82,7 @@ impl PathBuilder {
// Font synthesis (e.g., synthetic italic) applied separately from user transforms
// This preserves the distinction between font styling and user transformations
let style_skew = synthesis.skew().map(|angle| {
if per_glyph_instances {
if per_glyph_items {
DAffine2::from_cols_array(&[1., 0., -angle.to_radians().tan() as f64, 1., 0., 0.])
} else {
DAffine2::from_translation(DVec2::new(0., run_y as f64))
@@ -107,10 +107,10 @@ impl PathBuilder {
let glyph_id = GlyphId::from(glyph.id);
if let Some(glyph_outline) = outlines.get(glyph_id) {
if !per_glyph_instances {
if !per_glyph_items {
self.origin = glyph_offset;
}
self.draw_glyph(&glyph_outline, font_size, &normalized_coords, glyph_offset, style_skew, skew, per_glyph_instances);
self.draw_glyph(&glyph_outline, font_size, &normalized_coords, glyph_offset, style_skew, skew, per_glyph_items);
}
}
}

View File

@@ -77,11 +77,11 @@ fn regex_replace(
}
}
/// Finds a regex match in the string and returns its components. The result is a list where the first element is the whole match (`$0`) and subsequent elements are the capture groups (`$1`, `$2`, etc., if any).
/// Finds a regex match in the string and returns its components. The result is a list where the first item is the whole match (`$0`) and subsequent items are the capture groups (`$1`, `$2`, etc., if any).
///
/// The match index selects which non-overlapping occurrence to return (0 for the first match). Returns an empty list if no match is found at the given index.
///
/// Each row carries `start` and `end` byte-offset attributes pointing into the original string, plus a `name` attribute holding
/// Each item carries `start` and `end` byte-offset attributes pointing into the original string, plus a `name` attribute holding
/// the capture group's name (empty for unnamed groups, and for index 0 which is the whole match).
#[node_macro::node(category(""))]
fn regex_find(
@@ -150,7 +150,7 @@ fn regex_find(
/// Finds all non-overlapping matches of a regular expression pattern in the string, returning a list of the matched substrings.
///
/// Each row carries `start` and `end` byte-offset attributes pointing into the original string.
/// Each item carries `start` and `end` byte-offset attributes pointing into the original string.
#[node_macro::node(category("Text: Regex"))]
fn regex_find_all(
_: impl Ctx,

View File

@@ -87,19 +87,19 @@ impl TextContext {
}
/// Convert text to vector paths using the specified font and typesetting configuration
pub fn to_path(&mut self, text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, per_glyph_instances: bool) -> Table<Vector> {
pub fn to_path(&mut self, text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, per_glyph_items: bool) -> Table<Vector> {
let Some(layout) = self.layout_text(text, font, font_cache, typesetting) else {
return Table::new_from_element(Vector::default());
};
let mut path_builder = PathBuilder::new(per_glyph_instances, layout.scale() as f64);
let mut path_builder = PathBuilder::new(per_glyph_items, layout.scale() as f64);
for line in layout.lines() {
for item in line.items() {
if let PositionedLayoutItem::GlyphRun(glyph_run) = item
&& typesetting.max_height.filter(|&max_height| glyph_run.baseline() > max_height as f32).is_none()
{
path_builder.render_glyph_run(&glyph_run, typesetting.tilt, per_glyph_instances);
path_builder.render_glyph_run(&glyph_run, typesetting.tilt, per_glyph_items);
}
}
}

View File

@@ -6,8 +6,8 @@ use parley::fontique::Blob;
use std::sync::Arc;
use vector_types::Vector;
pub fn to_path(text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, per_glyph_instances: bool) -> Table<Vector> {
TextContext::with_thread_local(|ctx| ctx.to_path(text, font, font_cache, typesetting, per_glyph_instances))
pub fn to_path(text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, per_glyph_items: bool) -> Table<Vector> {
TextContext::with_thread_local(|ctx| ctx.to_path(text, font, font_cache, typesetting, per_glyph_items))
}
pub fn bounding_box(text: &str, font: &Font, font_cache: &FontCache, typesetting: TypesettingConfig, for_clipping_test: bool) -> DVec2 {

View File

@@ -87,7 +87,7 @@ fn reset_transform<T>(
content
}
/// Overwrites the transform of each element in the input table with the specified transform.
/// Overwrites the transform of each item in the input `Table` with the specified transform.
#[node_macro::node(category("Math: Transform"))]
fn replace_transform<T>(
_: impl Ctx + InjectFootprint,
@@ -109,7 +109,7 @@ fn replace_transform<T>(
}
// TODO: Figure out how this node should behave once #2982 is implemented.
/// Obtains the transform of the first element in the input table, if present.
/// Obtains the transform of the first item in the input `Table`, if present.
#[node_macro::node(category("Math: Transform"), path(core_types::vector))]
async fn extract_transform<T>(
_: impl Ctx,

View File

@@ -25,7 +25,7 @@ async fn path_modify(_ctx: impl Ctx, mut vector: Table<Vector>, modification: Bo
vector.set_attribute("editor:layer", 0, if existing.is_empty() { subgraph_path } else { existing });
if vector.len() > 1 {
warn!("The path modify ran on {} vector rows. Only the first can be modified.", vector.len());
warn!("The path modify ran on {} vector items. Only the first can be modified.", vector.len());
}
vector
}

View File

@@ -29,7 +29,7 @@ use vector_types::vector::misc::{
use vector_types::vector::style::{Fill, Gradient, GradientStops, PaintOrder, Stroke, StrokeAlign, StrokeCap, StrokeJoin};
use vector_types::vector::{FillId, PointId, RegionId, SegmentDomain, SegmentId, StrokeId, VectorExt};
/// Implemented for types that contain vector rows reachable via mutable access.
/// Implemented for types that contain vector items reachable via mutable access.
/// Used for the fill and stroke nodes so they can apply to either `Table<Graphic>` or `Table<Vector>`.
trait VectorTableIterMut {
fn for_each_vector_mut(&mut self, f: impl FnMut(&mut Vector, DAffine2));
@@ -255,13 +255,13 @@ async fn copy_to_points<I: 'n + Send + Clone>(
/// Artwork to be copied and placed at each point.
#[expose]
#[implementations(Table<Graphic>, Table<Vector>, Table<Raster<CPU>>, Table<Color>, Table<GradientStops>)]
instance: Table<I>,
/// Minimum range of randomized sizes given to each instance.
content: Table<I>,
/// Minimum range of randomized sizes given to each placed copy.
#[default(1)]
#[range((0., 2.))]
#[unit("x")]
random_scale_min: Multiplier,
/// Maximum range of randomized sizes given to each instance.
/// Maximum range of randomized sizes given to each placed copy.
#[default(1)]
#[range((0., 2.))]
#[unit("x")]
@@ -269,12 +269,12 @@ async fn copy_to_points<I: 'n + Send + Clone>(
/// Bias for the probability distribution of randomized sizes (0 is uniform, negatives favor more of small sizes, positives favor more of large sizes).
#[range((-50., 50.))]
random_scale_bias: f64,
/// Seed to determine unique variations on all the randomized instance sizes.
/// Seed to determine unique variations on all the randomized copy sizes.
random_scale_seed: SeedValue,
/// Range of randomized angles given to each instance, in degrees ranging from furthest clockwise to counterclockwise.
/// Range of randomized angles given to each placed copy, in degrees ranging from furthest clockwise to counterclockwise.
#[range((0., 360.))]
random_rotation: Angle,
/// Seed to determine unique variations on all the randomized instance angles.
/// Seed to determine unique variations on all the randomized copy angles.
random_rotation_seed: SeedValue,
) -> Table<I> {
let mut result_table = Table::new();
@@ -315,8 +315,8 @@ async fn copy_to_points<I: 'n + Send + Clone>(
let transform = DAffine2::from_scale_angle_translation(DVec2::splat(scale), rotation, translation);
for row_index in 0..instance.len() {
let Some(mut row) = instance.clone_row(row_index) else { continue };
for row_index in 0..content.len() {
let Some(mut row) = content.clone_row(row_index) else { continue };
let row_transform: DAffine2 = row.attribute_cloned_or_default("transform");
row.set_attribute("transform", transform * row_transform);
@@ -741,7 +741,7 @@ async fn box_warp(_: impl Ctx, content: Table<Vector>, #[expose] rectangle: Tabl
result.style.set_stroke_transform(DAffine2::IDENTITY);
// Add this to the table and reset the transform since we've applied it directly to the points
// Add this to the `Table` and reset the transform since we've applied it directly to the points
*row.element_mut() = result;
row.set_attribute("transform", DAffine2::IDENTITY);
row
@@ -797,7 +797,7 @@ where
let mut items: Vec<(f64, f64, DVec2, TableRow<T>)> = elements
.into_iter()
.map(|row| {
// Single-element table to query its bounding box
// Single-item `Table` to query its bounding box
let single = Table::new_from_row(row.clone());
let (w, h, top_left) = match single.bounding_box(DAffine2::IDENTITY, false) {
RenderBoundingBox::Rectangle([min, max]) => {
@@ -1210,7 +1210,7 @@ async fn solidify_stroke(_: impl Ctx, content: Table<Vector>) -> Table<Vector> {
solidified_stroke.style.set_fill(Fill::solid_or_none(stroke.color));
}
// If the original vector has a fill, preserve it as a separate row with the stroke cleared.
// If the original vector has a fill, preserve it as a separate item with the stroke cleared.
let has_fill = !vector.style.fill().is_none();
let fill_row = has_fill.then(|| {
vector.style.clear_stroke();
@@ -1219,7 +1219,7 @@ async fn solidify_stroke(_: impl Ctx, content: Table<Vector>) -> Table<Vector> {
let stroke_row = TableRow::from_parts(solidified_stroke, attributes);
// Ordering based on the paint order. The first row in the table is rendered below the second.
// Ordering based on the paint order. The first item in the `Table` is rendered below the second.
match paint_order {
PaintOrder::StrokeAbove => fill_row.into_iter().chain(std::iter::once(stroke_row)).collect::<Vec<_>>(),
PaintOrder::StrokeBelow => std::iter::once(stroke_row).chain(fill_row).collect::<Vec<_>>(),
@@ -1289,7 +1289,7 @@ pub async fn flatten_path<T: IntoGraphicTable + 'n + Send>(_: impl Ctx, #[implem
let graphic_table = content.into_graphic_table();
let flattened = graphic_table.clone().into_flattened_table::<Vector>();
// Create a table with one empty `Vector` element, then get a mutable reference to it which we append flattened subpaths to
// Create a `Table` with one empty `Vector` element, then get a mutable reference to it which we append flattened subpaths to
let mut output_table = Table::new_from_element(Vector::default());
let output = output_table.element_mut(0).unwrap();
@@ -1310,12 +1310,12 @@ pub async fn flatten_path<T: IntoGraphicTable + 'n + Send>(_: impl Ctx, #[implem
output.style = element.style.clone();
}
// Preserve a reference to the original upstream graphic table so the renderer can recurse into it
// Preserve a reference to the original upstream `Table<Graphic>` so the renderer can recurse into it
// when collecting metadata, exposing the original child layers' click targets to editor tools.
// This is the same mechanism Boolean Operation uses to keep its inputs editable after the merge.
output_table.set_attribute("editor:merged_layers", 0, graphic_table);
// Adopt the last input row's layer so the editor can also bucket clicks under a contributing child layer
// Adopt the last input item's layer so the editor can also bucket clicks under a contributing child layer
if !flattened.is_empty() {
let primary = flattened.len() - 1;
let layer_path: Table<NodeId> = flattened.attribute_cloned_or_default("editor:layer", primary);
@@ -2130,7 +2130,7 @@ async fn morph<I: IntoGraphicTable + 'n + Send + Clone>(
}
}
// Preserve original graphic table as upstream data so this group layer's nested layers can be edited by the tools.
// Preserve original `Table<Graphic>` as upstream data so this group layer's nested layers can be edited by the tools.
let mut graphic_table_content = content.clone().into_graphic_table();
// If the input isn't a Table<Vector>, we convert it into one by flattening any Table<Graphic> content.
@@ -2191,7 +2191,7 @@ async fn morph<I: IntoGraphicTable + 'n + Send + Clone>(
let control_bezpath = &control_bezpaths[subpath_index];
let segment_count = control_bezpath.segments().count();
// If the control path has no segments, return the first element
// If the control path has no segments, return the first item
if segment_count == 0 {
return content.into_iter().next().into_iter().collect();
}
@@ -2352,7 +2352,7 @@ async fn morph<I: IntoGraphicTable + 'n + Send + Clone>(
};
// Pre-compensate merged_layers transforms so that when collect_metadata applies
// the row transform (which will be group_transform * lerped_transform after the
// the item transform (which will be group_transform * lerped_transform after the
// pipeline's Transform node runs), the lerped_transform cancels out and children
// get the correct footprint: parent * group_transform * child_transform.
// Only pre-compensate if the lerped transform is invertible (non-zero determinant).
@@ -2878,7 +2878,7 @@ async fn count_points(_: impl Ctx, content: Table<Vector>) -> f64 {
content.iter_element_values().map(|vector| vector.point_domain.positions().len() as f64).sum()
}
/// Retrieves the vec2 position (in local space) of the anchor point at the specified index in table of vector elements.
/// Retrieves the vec2 position (in local space) of the anchor point at the specified index in a `Table` of vector elements.
/// If no value exists at that index, the position (0, 0) is returned.
#[node_macro::node(category("Vector: Measure"), path(graphene_core::vector))]
async fn index_points(