mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-17 15:28:04 +08:00
Split 'To Graphic' and 'Wrap Graphic' into the 'As Graphic' type assertion and 'Into Group' reducer nodes (#4441)
This commit is contained in:
committed by
Dennis Kobert
parent
f09eb73c08
commit
a41fdb3d75
2
demo-artwork/changing-seasons.graphite
generated
2
demo-artwork/changing-seasons.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/isometric-fountain.graphite
generated
2
demo-artwork/isometric-fountain.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/marbled-mandelbrot.graphite
generated
2
demo-artwork/marbled-mandelbrot.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/painted-dreams.graphite
generated
2
demo-artwork/painted-dreams.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/parametric-dunescape.graphite
generated
2
demo-artwork/parametric-dunescape.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/procedural-string-lights.graphite
generated
2
demo-artwork/procedural-string-lights.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/red-dress.graphite
generated
2
demo-artwork/red-dress.graphite
generated
File diff suppressed because one or more lines are too long
2
demo-artwork/valley-of-spires.graphite
generated
2
demo-artwork/valley-of-spires.graphite
generated
File diff suppressed because one or more lines are too long
@@ -155,15 +155,15 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
// Primary (bottom) input type coercion
|
||||
NodeTemplate {
|
||||
inputs: vec![NodeInput::import(generic!(T), 0)],
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::to_graphic::IDENTIFIER),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, -3)),
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::as_graphic::IDENTIFIER),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, -2)),
|
||||
..Default::default()
|
||||
},
|
||||
// Collection of the content into the layer's group; the wrap keeps
|
||||
// Collection of the content into the layer's group; the group keeps
|
||||
// the content level's element type for the legacy boundary.
|
||||
NodeTemplate {
|
||||
inputs: vec![NodeInput::import(generic!(T), 1)],
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::wrap_graphic::IDENTIFIER),
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::into_group::IDENTIFIER),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, -1)),
|
||||
..Default::default()
|
||||
},
|
||||
@@ -171,7 +171,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
NodeTemplate {
|
||||
inputs: vec![NodeInput::Reflection(graph_craft::document::DocumentNodeMetadata::DocumentNodePath)],
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::path_of_subgraph::IDENTIFIER),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, 1)),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-21, 0)),
|
||||
..Default::default()
|
||||
},
|
||||
// Stamp each item of the content with the parent layer's NodeId via the `editor:layer_path` attribute,
|
||||
@@ -194,7 +194,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
call_argument: generic!(T),
|
||||
inputs: vec![NodeInput::node(NodeId(0), 0), NodeInput::node(NodeId(4), 0)],
|
||||
implementation: NodeTemplateImplementation::ProtoNode(list::extend::IDENTIFIER),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, -3)),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(0, -2)),
|
||||
..Default::default()
|
||||
},
|
||||
]
|
||||
@@ -269,7 +269,7 @@ fn document_node_definitions() -> HashMap<DefinitionIdentifier, DocumentNodeDefi
|
||||
// Content coercion into a graphic level, evaluated within the artboard's footprint
|
||||
NodeTemplate {
|
||||
inputs: vec![NodeInput::import(generic!(T), 1)],
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::to_graphic::IDENTIFIER),
|
||||
implementation: NodeTemplateImplementation::ProtoNode(graphic::as_graphic::IDENTIFIER),
|
||||
node_type_metadata: NodeTypePersistentMetadata::node(IVec2::new(-35, -3)),
|
||||
..Default::default()
|
||||
},
|
||||
|
||||
@@ -24,7 +24,9 @@ pub fn load_demo(file_name: &str) -> DocumentMessageHandler {
|
||||
#[test]
|
||||
#[ignore = "dev tool: set DEMO_OUT and run explicitly"]
|
||||
fn migrate_demo_artwork_into_demo_out() {
|
||||
use crate::messages::portfolio::document_migration::{document_migration_reset_node_definition, document_migration_string_preprocessing, document_migration_upgrades};
|
||||
use crate::messages::portfolio::document_migration::{
|
||||
document_migration_reset_layer_definitions, document_migration_reset_node_definition, document_migration_string_preprocessing, document_migration_upgrades,
|
||||
};
|
||||
let out_dir = std::env::var("DEMO_OUT").expect("set DEMO_OUT to the output directory");
|
||||
for entry in std::fs::read_dir("../demo-artwork").unwrap() {
|
||||
let path = entry.unwrap().path();
|
||||
@@ -34,8 +36,9 @@ fn migrate_demo_artwork_into_demo_out() {
|
||||
let content = std::fs::read_to_string(&path).unwrap();
|
||||
let content = document_migration_string_preprocessing(content);
|
||||
let reset = document_migration_reset_node_definition(&content);
|
||||
let reset_layers = document_migration_reset_layer_definitions(&content);
|
||||
let mut document = DocumentMessageHandler::deserialize_document(&content).unwrap_or_else(|e| panic!("Failed to deserialize {}: {e:?}", path.display()));
|
||||
document_migration_upgrades(&mut document, reset);
|
||||
document_migration_upgrades(&mut document, reset, reset_layers);
|
||||
let out = format!("{out_dir}/{}", path.file_name().unwrap().to_string_lossy());
|
||||
std::fs::write(out, document.serialize_document()).unwrap();
|
||||
}
|
||||
|
||||
@@ -45,6 +45,14 @@ pub struct NodeReplacement<'a> {
|
||||
aliases: &'a [&'a str],
|
||||
}
|
||||
|
||||
/// Every name the Merge layer network's two type-coercion nodes have gone by, which is every alias of the node they both converged on.
|
||||
fn into_group_aliases() -> impl Iterator<Item = &'static &'static str> {
|
||||
NODE_REPLACEMENTS
|
||||
.iter()
|
||||
.filter(|replacement| replacement.node == graphene_std::graphic::into_group::IDENTIFIER)
|
||||
.flat_map(|replacement| replacement.aliases)
|
||||
}
|
||||
|
||||
const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
// ================================
|
||||
// blending
|
||||
@@ -200,22 +208,20 @@ const NODE_REPLACEMENTS: &[NodeReplacement<'static>] = &[
|
||||
],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::graphic::to_graphic::IDENTIFIER,
|
||||
node: graphene_std::graphic::into_group::IDENTIFIER,
|
||||
aliases: &[
|
||||
"graphene_core::ToGraphicGroupNode",
|
||||
"graphene_core::graphic_element::ToGroupNode",
|
||||
"graphene_core::graphic_types::ToGroupNode",
|
||||
"graphene_core::graphic::ToGraphicNode",
|
||||
],
|
||||
},
|
||||
NodeReplacement {
|
||||
node: graphene_std::graphic::wrap_graphic::IDENTIFIER,
|
||||
aliases: &[
|
||||
// Converted from "To Element"
|
||||
// Converted from "To Element", then "Wrap Graphic"
|
||||
"graphene_core::ToGraphicElementNode",
|
||||
"graphene_core::graphic_element::ToElementNode",
|
||||
"graphene_core::graphic_types::ToElementNode",
|
||||
"graphene_core::graphic::WrapGraphicNode",
|
||||
"graphic_nodes::graphic::WrapGraphicNode",
|
||||
// Converted from "To Graphic", whose grouping of non-graphical content this node now carries alone
|
||||
"graphene_core::ToGraphicGroupNode",
|
||||
"graphene_core::graphic_element::ToGroupNode",
|
||||
"graphene_core::graphic_types::ToGroupNode",
|
||||
"graphene_core::graphic::ToGraphicNode",
|
||||
"graphic_nodes::graphic::ToGraphicNode",
|
||||
],
|
||||
},
|
||||
// ================================
|
||||
@@ -1085,6 +1091,21 @@ pub fn document_migration_reset_node_definition(document_serialized_content: &st
|
||||
false
|
||||
}
|
||||
|
||||
/// Whether the layer networks built from the coercion nodes that became "As Graphic" and "Into Group" need their definitions reset.
|
||||
///
|
||||
/// A document still naming either node by an alias stores the pre-split plumbing, which the alias migration alone would mangle:
|
||||
/// it maps both names onto the reducer, leaving a reducer where the layer wants the assertion. Resetting those two layer
|
||||
/// definitions installs the current plumbing instead. This stays narrower than a full
|
||||
/// [`document_migration_reset_node_definition`], whose one-shot input reorderings would re-apply to documents already carrying them.
|
||||
pub fn document_migration_reset_layer_definitions(document_serialized_content: &str) -> bool {
|
||||
into_group_aliases().any(|alias| document_serialized_content.contains(alias))
|
||||
}
|
||||
|
||||
/// The layer networks whose definitions [`document_migration_reset_layer_definitions`] resets.
|
||||
fn is_coercion_layer_definition(reference: &DefinitionIdentifier) -> bool {
|
||||
matches!(reference, DefinitionIdentifier::Network(name) if name == "Merge" || name == "Artboard")
|
||||
}
|
||||
|
||||
pub fn document_migration_replace_resources_referenced_by_hash(document_serialized_content: String) -> (String, HashMap<ResourceHash, ResourceId>) {
|
||||
fn collect_resources_referenced_by_hash(s: &str) -> HashMap<ResourceHash, Vec<Range<usize>>> {
|
||||
let mut out: HashMap<ResourceHash, Vec<Range<usize>>> = HashMap::new();
|
||||
@@ -1156,7 +1177,7 @@ pub fn document_migration_replace_resources_referenced_by_hash(document_serializ
|
||||
(out, hash_to_id)
|
||||
}
|
||||
|
||||
pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_node_definitions_on_open: bool) {
|
||||
pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_node_definitions_on_open: bool, reset_layer_definitions: bool) {
|
||||
document.network_interface.migrate_path_modify_node();
|
||||
|
||||
let network = document.network_interface.document_network().clone();
|
||||
@@ -1323,7 +1344,7 @@ pub fn document_migration_upgrades(document: &mut DocumentMessageHandler, reset_
|
||||
.map(|(node_id, node, path)| (*node_id, node.clone(), path))
|
||||
.collect::<Vec<(NodeId, graph_craft::document::DocumentNode, Vec<NodeId>)>>();
|
||||
for (node_id, node, network_path) in &nodes {
|
||||
migrate_node(node_id, node, network_path, document, reset_node_definitions_on_open);
|
||||
migrate_node(node_id, node, network_path, document, reset_node_definitions_on_open, reset_layer_definitions);
|
||||
}
|
||||
|
||||
// The old geometry-producing "Text" node was split into the current "Text" (`String[]`) -> converter pair, which reuses the same proto
|
||||
@@ -1441,12 +1462,21 @@ fn fold_gradient_spread_into_ramp_input(input: &NodeInput, gradient_spread: Grad
|
||||
}
|
||||
}
|
||||
|
||||
fn migrate_node(node_id: &NodeId, node: &DocumentNode, network_path: &[NodeId], document: &mut DocumentMessageHandler, reset_node_definitions_on_open: bool) -> Option<()> {
|
||||
fn migrate_node(
|
||||
node_id: &NodeId,
|
||||
node: &DocumentNode,
|
||||
network_path: &[NodeId],
|
||||
document: &mut DocumentMessageHandler,
|
||||
reset_node_definitions_on_open: bool,
|
||||
reset_layer_definitions: bool,
|
||||
) -> Option<()> {
|
||||
// Must run before the reset block below: a node referencing a removed catalog entry would otherwise abort
|
||||
// `migrate_node` via the `?` on `resolve_document_node_type`, preventing subsequent migration blocks from running.
|
||||
migrate_removed_catalog_definitions(node_id, node, network_path, document);
|
||||
|
||||
if reset_node_definitions_on_open && let Some(reference) = document.network_interface.reference(node_id, network_path) {
|
||||
if let Some(reference) = document.network_interface.reference(node_id, network_path)
|
||||
&& (reset_node_definitions_on_open || (reset_layer_definitions && is_coercion_layer_definition(&reference)))
|
||||
{
|
||||
let node_definition = resolve_document_node_type(&reference)?;
|
||||
document.network_interface.replace_implementation(node_id, network_path, &mut node_definition.default_node_template());
|
||||
|
||||
@@ -2986,6 +3016,25 @@ mod tests {
|
||||
));
|
||||
}
|
||||
|
||||
// Migrating a Merge network's coercion nodes by alias would leave a reducer in the primary slot, so every alias must reset instead
|
||||
#[test]
|
||||
fn every_into_group_alias_resets_the_merge_definition() {
|
||||
let aliases = into_group_aliases().collect::<Vec<_>>();
|
||||
assert!(!aliases.is_empty(), "the reset is driven by these aliases, so losing them all would disable it unnoticed");
|
||||
|
||||
for alias in aliases {
|
||||
let document = format!(r#""implementation":{{"ProtoNode":"{alias}"}}"#);
|
||||
assert!(
|
||||
document_migration_reset_layer_definitions(&document),
|
||||
"a document referencing `{alias}` should reset its layer definitions"
|
||||
);
|
||||
assert!(
|
||||
!document_migration_reset_node_definition(&document),
|
||||
"`{alias}` alone must not reset every definition, which would re-apply the one-shot input reorderings"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_no_duplicate_node_replacements() {
|
||||
let mut hashmap = HashMap::<ProtoNodeIdentifier, u32>::new();
|
||||
|
||||
@@ -828,6 +828,8 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||
} => {
|
||||
// Upgrade the document being opened to use fresh copies of all nodes
|
||||
let reset_node_definitions_on_open = reset_node_definitions_on_open || document_migration_reset_node_definition(&document_serialized_content);
|
||||
// Reinstall just the layer networks whose coercion nodes were split into "As Graphic" and "Into Group"
|
||||
let reset_layer_definitions = document_migration_reset_layer_definitions(&document_serialized_content);
|
||||
// Upgrade the document being opened with string replacements on the original JSON
|
||||
let document_serialized_content = document_migration_string_preprocessing(document_serialized_content);
|
||||
// Upgrade resources from being referend by hash to beeing referened by ID
|
||||
@@ -878,7 +880,7 @@ impl MessageHandler<PortfolioMessage, PortfolioMessageContext<'_>> for Portfolio
|
||||
};
|
||||
|
||||
// Upgrade the document's nodes to be compatible with the latest version
|
||||
document_migration_upgrades(&mut document, reset_node_definitions_on_open);
|
||||
document_migration_upgrades(&mut document, reset_node_definitions_on_open, reset_layer_definitions);
|
||||
|
||||
// Load the document's embedded resources into the resource storage
|
||||
std::mem::take(&mut document.resources.embedded).into_iter().for_each(|(hash, resource)| {
|
||||
|
||||
@@ -83,17 +83,11 @@ fn node_registry() -> HashMap<ProtoNodeIdentifier, Vec<RegistryEntry>> {
|
||||
.into_iter()
|
||||
.map(|entry| (ProtoNodeIdentifier::new("graphene_core::ops::IntoNode<Graphic>"), entry)),
|
||||
);
|
||||
// The typed-level collapse rows of To Graphic, served under its identifier.
|
||||
// The unit row of As Graphic: an unconnected content input renders as nothing.
|
||||
node_types.extend(
|
||||
graphene_std::graphic::to_graphic_typed_entries()
|
||||
graphene_std::graphic::as_graphic_unit_entries()
|
||||
.into_iter()
|
||||
.map(|entry| (graphene_std::graphic::to_graphic::IDENTIFIER.clone(), entry)),
|
||||
);
|
||||
// The unit row of To Graphic: an unconnected content input renders as nothing.
|
||||
node_types.extend(
|
||||
graphene_std::graphic::to_graphic_unit_entries()
|
||||
.into_iter()
|
||||
.map(|entry| (graphene_std::graphic::to_graphic::IDENTIFIER.clone(), entry)),
|
||||
.map(|entry| (graphene_std::graphic::as_graphic::IDENTIFIER.clone(), entry)),
|
||||
);
|
||||
// =============
|
||||
// CONVERT NODES
|
||||
|
||||
@@ -374,6 +374,14 @@ impl From<DVec2> for Graphic<'_> {
|
||||
Graphic::Vector(Vector::from_anchor_position(position))
|
||||
}
|
||||
}
|
||||
|
||||
/// A coordinate becomes the vector holding it as a lone anchor, so a level of
|
||||
/// coordinates coerces lane-for-lane into a level of single-point vectors.
|
||||
impl IntoGraphicElement for DVec2 {
|
||||
fn into_graphic_element(self, _arena: &core_types::arena::Arena) -> Option<Graphic<'_>> {
|
||||
Some(Graphic::Vector(Vector::from_anchor_position(self)))
|
||||
}
|
||||
}
|
||||
// Note: List conversions handled by blanket impl in gcore
|
||||
|
||||
impl<'e> Graphic<'e> {
|
||||
|
||||
@@ -265,12 +265,12 @@ attribute_reads! {
|
||||
read_gradient_hue_direction_attribute: GradientHueDirection => GradientHueDirection;
|
||||
}
|
||||
|
||||
/// Nests the input graphical content in a wrapper graphic. This essentially "groups" the input.
|
||||
/// The wrapped run keeps the level's element type, so the legacy boundary can
|
||||
/// lower a wrapped vector level to the bare typed graphic the pre-flip wrap made.
|
||||
/// Nests the input graphical content in a wrapper graphic, collecting it all into a single group.
|
||||
/// The collected run keeps the level's element type, so the legacy boundary can
|
||||
/// lower a grouped vector level to the bare typed graphic the pre-flip wrap made.
|
||||
/// The inverse of this node is 'Flatten Graphic'.
|
||||
#[node_macro::node(category("General"), extent(wrap_graphic_extent))]
|
||||
pub fn wrap_graphic<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
||||
#[node_macro::node(category("General"), extent(into_group_extent))]
|
||||
pub fn into_group<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
||||
_: impl Ctx,
|
||||
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String)] content: IList<T>,
|
||||
) -> Result<IList<Graphic<'e>>, Interrupt> {
|
||||
@@ -279,15 +279,14 @@ pub fn wrap_graphic<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static
|
||||
}
|
||||
|
||||
/// The collected group is the level's single lane.
|
||||
fn wrap_graphic_extent<T>(_content: ListIn<'_, T>, _level: LevelIn) -> GPoll<Extent> {
|
||||
fn into_group_extent<T>(_content: ListIn<'_, T>, _level: LevelIn) -> GPoll<Extent> {
|
||||
GPoll::Final(Extent::Exactly(1))
|
||||
}
|
||||
|
||||
/// Converts graphical content into a `Graphic` level. A `Graphic` level passes through
|
||||
/// unchanged; a typed level nests as one graphic lane, keeping the pre-flip list
|
||||
/// collapse (`to_graphic_typed` serves those rows).
|
||||
/// Type-asserts a value to be graphical content, converting each lane of other content types into its matching form.
|
||||
/// Use the 'Into Group' node instead to collect the content into a single group.
|
||||
#[node_macro::node(category("General"))]
|
||||
pub fn to_graphic<'e, T: graphic_types::graphic::IntoGraphicElement>(ctx: impl Ctx + ExtractArena<'e>, #[implementations(Graphic)] content: T) -> Result<Graphic<'e>, Interrupt> {
|
||||
pub fn as_graphic<'e, T: graphic_types::graphic::IntoGraphicElement>(ctx: impl Ctx + ExtractArena<'e>, #[implementations(Graphic)] content: T) -> Result<Graphic<'e>, Interrupt> {
|
||||
content.into_graphic_element(ctx.arena()).ok_or_else(|| GraphError::new("the arena is exhausted").into())
|
||||
}
|
||||
|
||||
@@ -297,37 +296,24 @@ pub fn to_graphic<'e, T: graphic_types::graphic::IntoGraphicElement>(ctx: impl C
|
||||
#[node_macro::node(category(""))]
|
||||
pub fn to_graphic_element<'e, T: graphic_types::graphic::IntoGraphicElement>(
|
||||
ctx: impl Ctx + ExtractArena<'e>,
|
||||
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String)] content: T,
|
||||
#[implementations(Graphic, Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String, DVec2)] content: T,
|
||||
) -> Result<Graphic<'e>, Interrupt> {
|
||||
content.into_graphic_element(ctx.arena()).ok_or_else(|| GraphError::new("the arena is exhausted").into())
|
||||
}
|
||||
|
||||
/// The typed-level conversion: the whole level nests as one graphic lane, as
|
||||
/// the pre-flip `Into<Graphic>` list collapse did. Registered under the to
|
||||
/// graphic identifier.
|
||||
#[node_macro::node(category(""), extent(wrap_graphic_extent))]
|
||||
pub fn to_graphic_typed<'e, T: Clone + Send + Sync + core_types::CacheHash + 'static>(
|
||||
_: impl Ctx,
|
||||
#[implementations(Vector, Raster<CPU>, Raster<GPU>, Color, Gradient, String)] content: IList<T>,
|
||||
) -> Result<IList<Graphic<'e>>, Interrupt> {
|
||||
let item = content.as_group_item();
|
||||
Ok(Graphic::Group(core_types::record::Group { row: None, content: item }))
|
||||
}
|
||||
|
||||
/// An unconnected content input carries the unit, which renders as nothing like
|
||||
/// the pre-flip empty list. Registered under the to graphic identifier.
|
||||
#[node_macro::node(category(""), extent(to_graphic_unit_extent))]
|
||||
pub fn to_graphic_unit(_: impl Ctx, _content: ()) -> Result<IList<Graphic<'static>>, Interrupt> {
|
||||
/// the pre-flip empty list. Registered under the as graphic identifier.
|
||||
#[node_macro::node(category(""), extent(as_graphic_unit_extent))]
|
||||
pub fn as_graphic_unit(_: impl Ctx, _content: ()) -> Result<IList<Graphic<'static>>, Interrupt> {
|
||||
Err(core_types::gpoll::GraphError::past_end().into())
|
||||
}
|
||||
|
||||
fn to_graphic_unit_extent(_content: core_types::extent::ValueIn<'_, ()>, _level: LevelIn) -> GPoll<Extent> {
|
||||
fn as_graphic_unit_extent(_content: core_types::extent::ValueIn<'_, ()>, _level: LevelIn) -> GPoll<Extent> {
|
||||
GPoll::Final(Extent::Exactly(0))
|
||||
}
|
||||
|
||||
pub use _as_graphic_unit_mod::as_graphic_unit_entries;
|
||||
pub use _to_graphic_element_mod::to_graphic_element_entries;
|
||||
pub use _to_graphic_typed_mod::to_graphic_typed_entries;
|
||||
pub use _to_graphic_unit_mod::to_graphic_unit_entries;
|
||||
|
||||
/// Removes a level of nesting from a `Graphic[]`, or all nesting if "Fully Flatten" is enabled.
|
||||
///
|
||||
|
||||
@@ -224,8 +224,8 @@ fn flatten_levels_extent(content: ExtentIn<'_>, level: LevelIn) -> GPoll<Extent>
|
||||
mod tests {
|
||||
use super::*;
|
||||
use crate::graphic::{
|
||||
ColorsToGradientNode, FlattenColorNode, FlattenGraphicNode, GradientToColorsNode, WrapGraphicNode, flatten_color_layout_meta, flatten_graphic_layout_meta, gradient_to_colors_layout_meta,
|
||||
wrap_graphic_layout_meta,
|
||||
ColorsToGradientNode, FlattenColorNode, FlattenGraphicNode, GradientToColorsNode, IntoGroupNode, flatten_color_layout_meta, flatten_graphic_layout_meta, gradient_to_colors_layout_meta,
|
||||
into_group_layout_meta,
|
||||
};
|
||||
use core_types::arena::Arena;
|
||||
use core_types::attribute::Attribute as AttributeMarker;
|
||||
@@ -670,8 +670,8 @@ mod tests {
|
||||
let layout = graphic_layout();
|
||||
let rows = vec![(text("a"), translation(1.)), (text("b"), translation(2.))];
|
||||
let node = install(
|
||||
WrapGraphicNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
wrap_graphic_layout_meta(),
|
||||
IntoGroupNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
into_group_layout_meta(),
|
||||
&[Some(&layout)],
|
||||
);
|
||||
let out = Node::<ContextImpl>::layout(&node).clone();
|
||||
@@ -708,8 +708,8 @@ mod tests {
|
||||
let layout = graphic_layout();
|
||||
let rows = vec![(text("a"), translation(1.)), (text("b"), translation(2.))];
|
||||
let node = install(
|
||||
WrapGraphicNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
wrap_graphic_layout_meta(),
|
||||
IntoGroupNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
into_group_layout_meta(),
|
||||
&[Some(&layout)],
|
||||
);
|
||||
let out = Node::<ContextImpl>::layout(&node).clone();
|
||||
@@ -858,8 +858,8 @@ mod tests {
|
||||
let layout = graphic_layout();
|
||||
let rows = vec![(text("a"), translation(1.)), (text("b"), translation(2.))];
|
||||
let node = install(
|
||||
WrapGraphicNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
wrap_graphic_layout_meta(),
|
||||
IntoGroupNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
into_group_layout_meta(),
|
||||
&[Some(&layout)],
|
||||
);
|
||||
let out = Node::<ContextImpl>::layout(&node).clone();
|
||||
@@ -890,8 +890,8 @@ mod tests {
|
||||
let layout = graphic_layout();
|
||||
let rows = vec![(text("a"), translation(1.)), (text("b"), translation(2.))];
|
||||
let wrapped = install(
|
||||
WrapGraphicNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
wrap_graphic_layout_meta(),
|
||||
IntoGroupNode::<_, Graphic>::new(RecordSource::new(GraphicSource { layout: layout.clone(), rows }, &layout, &layout), &layout),
|
||||
into_group_layout_meta(),
|
||||
&[Some(&layout)],
|
||||
);
|
||||
let wrap_out = Node::<ContextImpl>::layout(&wrapped).clone();
|
||||
|
||||
Reference in New Issue
Block a user