mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-19 02:48:12 +08:00
Replace deprecated row/cell/instance terminology with "item" and "value" terms (#4075)
This commit is contained in:
@@ -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.);
|
||||
|
||||
@@ -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();
|
||||
};
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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))]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>();
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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(
|
||||
|
||||
Reference in New Issue
Block a user