mirror of
https://github.com/GraphiteEditor/Graphite.git
synced 2026-09-15 22:28:10 +08:00
Migrate test sources and assertions onto the safe record builders
This commit is contained in:
@@ -2456,21 +2456,15 @@ mod tests {
|
||||
use crate::lane::LaneSource;
|
||||
use glam::DAffine2;
|
||||
|
||||
let layout = Layout::default().with_writes(0, element_write::<f64>(), &[FieldWrite::of::<Transform>(0), FieldWrite::of::<Opacity>(0)]);
|
||||
let stride = layout.lane_stride();
|
||||
let arena = crate::arena::Arena::new(4096).unwrap();
|
||||
let transform = DAffine2::from_translation((5., 6.).into());
|
||||
let mut bytes = vec![0u8; stride * 2];
|
||||
let mut builder = RunBuilder::new(&arena, element_write::<f64>(), &[FieldWrite::of::<Transform>(0), FieldWrite::of::<Opacity>(0)], 2).unwrap();
|
||||
for lane in 0..2 {
|
||||
// SAFETY: `bytes` is `stride` per lane, and the offsets come from `layout`.
|
||||
unsafe {
|
||||
let base = bytes.as_mut_ptr().add(lane * stride);
|
||||
base.cast::<f64>().write(lane as f64);
|
||||
base.add(layout.offset_of(Transform::NAME, 0).unwrap()).cast::<DAffine2>().write(transform);
|
||||
base.add(layout.offset_of(Opacity::NAME, 0).unwrap()).cast::<f64>().write(0.25);
|
||||
}
|
||||
let lane = builder.push(lane as f64).unwrap();
|
||||
builder.attr::<Transform>(lane, transform);
|
||||
builder.attr::<Opacity>(lane, 0.25);
|
||||
}
|
||||
// SAFETY: `bytes` holds two lanes of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(crate::node::RecordBatch::new(bytes.as_ptr(), 2, &layout)) };
|
||||
let item = builder.finish();
|
||||
let run = RunView::<f64>::new(&item).expect("the run holds f64 elements");
|
||||
|
||||
let mut list = crate::list::List::new_from_element(0f64);
|
||||
@@ -2493,10 +2487,10 @@ mod tests {
|
||||
use crate::attribute::Opacity;
|
||||
use crate::lane::LaneSource;
|
||||
|
||||
let layout = Layout::default().with_writes(0, element_write::<f64>(), &[]);
|
||||
let bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(crate::node::RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let arena = crate::arena::Arena::new(1024).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write::<f64>(), &[], 1).unwrap();
|
||||
builder.push(0f64).unwrap();
|
||||
let item = builder.finish();
|
||||
let run = RunView::<f64>::new(&item).expect("the run holds f64 elements");
|
||||
|
||||
assert_eq!(run.attr::<Opacity>(0), 1.);
|
||||
@@ -2708,6 +2702,8 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn a_run_builds_from_a_legacy_list_and_serves_its_rows() {
|
||||
use crate::lane::LaneSource;
|
||||
|
||||
let mut list = crate::list::List::new_from_element(String::from("row 0"));
|
||||
list.push(crate::list::Item::new_from_element(String::from("row 1")));
|
||||
let transform = glam::DAffine2::from_translation(glam::DVec2::new(3., 4.));
|
||||
@@ -2719,29 +2715,25 @@ mod tests {
|
||||
let arena = crate::arena::Arena::new(1 << 16).unwrap();
|
||||
let item = GroupItem::from_list(list, &arena).unwrap();
|
||||
assert_eq!(item.len(), 2);
|
||||
let layout = item.layout().clone();
|
||||
let lanes = item.lanes();
|
||||
let run = RunView::<String>::new(&item).expect("the run holds string elements");
|
||||
|
||||
let rec = lanes.get(0).rec();
|
||||
assert_eq!(unsafe { read_element::<String>(rec) }, "row 0");
|
||||
assert_eq!(unsafe { rec.read::<glam::DAffine2>(layout.offset_of(crate::ATTR_TRANSFORM, 0).unwrap()) }, transform);
|
||||
assert_eq!(unsafe { rec.read::<&str>(layout.offset_of("name", 0).unwrap()) }, "first");
|
||||
assert!(unsafe { rec.read::<&[crate::uuid::NodeId]>(layout.offset_of(crate::ATTR_EDITOR_LAYER_PATH, 0).unwrap()) }.is_empty());
|
||||
assert_eq!(run.element(0).map(String::as_str), Some("row 0"));
|
||||
assert_eq!(run.attr::<crate::attribute::Transform>(0), transform);
|
||||
assert_eq!(run.attr::<crate::attribute::Name>(0), "first");
|
||||
assert!(run.attr::<crate::attribute::EditorLayerPath>(0).is_empty());
|
||||
|
||||
let rec = lanes.get(1).rec();
|
||||
assert_eq!(unsafe { read_element::<String>(rec) }, "row 1");
|
||||
assert_eq!(run.element(1).map(String::as_str), Some("row 1"));
|
||||
// A lane without the value reads the census default, not garbage.
|
||||
assert_eq!(unsafe { rec.read::<glam::DAffine2>(layout.offset_of(crate::ATTR_TRANSFORM, 0).unwrap()) }, glam::DAffine2::IDENTITY);
|
||||
assert_eq!(unsafe { rec.read::<&str>(layout.offset_of("name", 0).unwrap()) }, "");
|
||||
assert_eq!(
|
||||
unsafe { rec.read::<&[crate::uuid::NodeId]>(layout.offset_of(crate::ATTR_EDITOR_LAYER_PATH, 0).unwrap()) },
|
||||
&[crate::uuid::NodeId(7), crate::uuid::NodeId(9)]
|
||||
);
|
||||
assert_eq!(unsafe { rec.read::<Option<f64>>(layout.offset_of("max_width", 0).unwrap()) }, Some(12.5));
|
||||
assert_eq!(run.attr::<crate::attribute::Transform>(1), glam::DAffine2::IDENTITY);
|
||||
assert_eq!(run.attr::<crate::attribute::Name>(1), "");
|
||||
assert_eq!(run.attr::<crate::attribute::EditorLayerPath>(1), &[crate::uuid::NodeId(7), crate::uuid::NodeId(9)]);
|
||||
assert_eq!(run.attr::<crate::attribute::MaxWidth>(1), Some(12.5));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_built_run_replays_after_the_source_dies() {
|
||||
use crate::lane::LaneSource;
|
||||
|
||||
let owned = {
|
||||
let arena = crate::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut list = crate::list::List::new_from_element(String::from("element"));
|
||||
@@ -2752,25 +2744,25 @@ mod tests {
|
||||
|
||||
let arena = crate::arena::Arena::new(1 << 16).unwrap();
|
||||
let replayed = owned.replay(&arena).unwrap();
|
||||
let layout = replayed.layout().clone();
|
||||
let rec = replayed.lanes().get(0).rec();
|
||||
assert_eq!(unsafe { read_element::<String>(rec) }, "element");
|
||||
assert_eq!(unsafe { rec.read::<&str>(layout.offset_of("name", 0).unwrap()) }, "label");
|
||||
assert_eq!(unsafe { rec.read::<&[crate::uuid::NodeId]>(layout.offset_of(crate::ATTR_EDITOR_LAYER_PATH, 0).unwrap()) }, &[crate::uuid::NodeId(3)]);
|
||||
let run = RunView::<String>::new(&replayed).expect("the run holds string elements");
|
||||
assert_eq!(run.element(0).map(String::as_str), Some("element"));
|
||||
assert_eq!(run.attr::<crate::attribute::Name>(0), "label");
|
||||
assert_eq!(run.attr::<crate::attribute::EditorLayerPath>(0), &[crate::uuid::NodeId(3)]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_wrong_typed_or_undeclared_column_leaves_the_default() {
|
||||
use crate::lane::LaneSource;
|
||||
|
||||
let mut list = crate::list::List::new_from_element(String::from("element"));
|
||||
list.set_attribute(crate::ATTR_OPACITY, 0, String::from("not an f64"));
|
||||
list.set_attribute("never_declared", 0, 5u32);
|
||||
|
||||
let arena = crate::arena::Arena::new(1 << 16).unwrap();
|
||||
let item = GroupItem::from_list(list, &arena).unwrap();
|
||||
let layout = item.layout().clone();
|
||||
assert!(layout.offset_of("never_declared", 0).is_none(), "an undeclared key has no field form");
|
||||
let rec = item.lanes().get(0).rec();
|
||||
assert_eq!(unsafe { rec.read::<f64>(layout.offset_of(crate::ATTR_OPACITY, 0).unwrap()) }, 1., "the wrong-typed value reads as absent");
|
||||
assert!(item.layout().offset_of("never_declared", 0).is_none(), "an undeclared key has no field form");
|
||||
let run = RunView::<String>::new(&item).expect("the run holds string elements");
|
||||
assert_eq!(run.attr::<crate::attribute::Opacity>(0), 1., "the wrong-typed value reads as absent");
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
@@ -1494,8 +1494,7 @@ mod run_tests {
|
||||
use core_types::attribute::Attribute;
|
||||
use core_types::bounds::BoundingBox;
|
||||
use core_types::lane::LaneSource;
|
||||
use core_types::node::RecordBatch;
|
||||
use core_types::record::{FieldWrite, GroupItem, Layout, RunView, element_write_hashed};
|
||||
use core_types::record::{FieldWrite, RunBuilder, RunView, element_write_hashed};
|
||||
use glam::{DAffine2, DVec2};
|
||||
use vector_types::subpath::Subpath;
|
||||
use vector_types::vector::PointId;
|
||||
@@ -1509,17 +1508,11 @@ mod run_tests {
|
||||
let paint = List::new_from_element(Graphic::Color(Color::BLACK));
|
||||
let vector = unit_square_at(DVec2::ZERO);
|
||||
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
let mut bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: `bytes` is one lane of `layout`; a parked element stores its
|
||||
// reference, and the fill field stores the marker's value form.
|
||||
unsafe {
|
||||
let base = bytes.as_mut_ptr();
|
||||
base.cast::<&Vector>().write(&vector);
|
||||
base.add(layout.offset_of(Fill::NAME, 0).unwrap()).cast::<Option<&List<Graphic>>>().write(Some(&paint));
|
||||
}
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(vector.clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let item = builder.finish();
|
||||
let run = RunView::<Vector>::new(&item).expect("the run holds vector elements");
|
||||
|
||||
assert_eq!(run.attr::<Fill>(0), Some(&paint));
|
||||
@@ -1535,26 +1528,17 @@ mod run_tests {
|
||||
let paint = List::new_from_element(Graphic::Color(Color::BLACK));
|
||||
let vector = unit_square_at(DVec2::ZERO);
|
||||
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
let mut bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: `bytes` is one lane of `layout`; a parked element stores its
|
||||
// reference, and the fill field stores the marker's value form.
|
||||
unsafe {
|
||||
let base = bytes.as_mut_ptr();
|
||||
base.cast::<&Vector>().write(&vector);
|
||||
base.add(layout.offset_of(Fill::NAME, 0).unwrap()).cast::<Option<&List<Graphic>>>().write(Some(&paint));
|
||||
}
|
||||
let (owned, expected) = {
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let group = core_types::record::Group {
|
||||
row: None,
|
||||
content: item,
|
||||
};
|
||||
let expected = group_to_legacy_list(&group);
|
||||
(map_groups_to_owned(&Graphic::Group(group)), expected)
|
||||
let source = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&source, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(vector.clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let group = core_types::record::Group {
|
||||
row: None,
|
||||
content: builder.finish(),
|
||||
};
|
||||
bytes.fill(u8::MAX);
|
||||
let expected = group_to_legacy_list(&group);
|
||||
let owned = map_groups_to_owned(&Graphic::Group(group));
|
||||
drop(source);
|
||||
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let resident = map_groups_to_resident(&owned, &arena).expect("the arena holds the replay");
|
||||
@@ -1565,35 +1549,23 @@ mod run_tests {
|
||||
#[test]
|
||||
fn an_owned_group_replays_nested_groups_through_the_element_glue() {
|
||||
let vector = unit_square_at(DVec2::ZERO);
|
||||
let inner_layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[]);
|
||||
let mut inner_bytes = vec![0u8; inner_layout.lane_stride()];
|
||||
// SAFETY: `inner_bytes` is one lane of `inner_layout`; a parked element
|
||||
// stores its reference.
|
||||
unsafe { inner_bytes.as_mut_ptr().cast::<&Vector>().write(&vector) };
|
||||
// SAFETY: `inner_bytes` holds one lane of `inner_layout` at its stride.
|
||||
let inner_item = unsafe { GroupItem::from_resident(RecordBatch::new(inner_bytes.as_ptr(), 1, &inner_layout)) };
|
||||
let source = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&source, element_write_hashed::<Vector>(), &[], 1).unwrap();
|
||||
builder.push(vector.clone()).unwrap();
|
||||
let nested = Graphic::Group(core_types::record::Group {
|
||||
row: None,
|
||||
content: inner_item,
|
||||
content: builder.finish(),
|
||||
});
|
||||
|
||||
let outer_layout = Layout::default().with_writes(0, element_write_hashed::<Graphic>(), &[]);
|
||||
let mut outer_bytes = vec![0u8; outer_layout.lane_stride()];
|
||||
// SAFETY: `outer_bytes` is one lane of `outer_layout`; a parked element
|
||||
// stores its reference.
|
||||
unsafe { outer_bytes.as_mut_ptr().cast::<&Graphic>().write(&nested) };
|
||||
let (owned, expected) = {
|
||||
// SAFETY: `outer_bytes` holds one lane of `outer_layout` at its stride.
|
||||
let outer_item = unsafe { GroupItem::from_resident(RecordBatch::new(outer_bytes.as_ptr(), 1, &outer_layout)) };
|
||||
let group = core_types::record::Group {
|
||||
row: None,
|
||||
content: outer_item,
|
||||
};
|
||||
let expected = group_to_legacy_list(&group);
|
||||
(map_groups_to_owned(&Graphic::Group(group)), expected)
|
||||
let mut builder = RunBuilder::new(&source, element_write_hashed::<Graphic>(), &[], 1).unwrap();
|
||||
builder.push(nested).unwrap();
|
||||
let group = core_types::record::Group {
|
||||
row: None,
|
||||
content: builder.finish(),
|
||||
};
|
||||
outer_bytes.fill(u8::MAX);
|
||||
inner_bytes.fill(u8::MAX);
|
||||
let expected = group_to_legacy_list(&group);
|
||||
let owned = map_groups_to_owned(&Graphic::Group(group));
|
||||
drop(source);
|
||||
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let resident = map_groups_to_resident(&owned, &arena).expect("the arena holds the replay");
|
||||
@@ -1601,42 +1573,31 @@ mod run_tests {
|
||||
assert_eq!(group_to_legacy_list(group), expected);
|
||||
}
|
||||
|
||||
fn native_group_paint(vector: &Vector, inner_layout: &Layout, inner_bytes: &mut Vec<u8>) -> List<Graphic> {
|
||||
// SAFETY: `inner_bytes` is one lane of `inner_layout`; a parked element
|
||||
// stores its reference.
|
||||
unsafe { inner_bytes.as_mut_ptr().cast::<&Vector>().write(vector) };
|
||||
// SAFETY: `inner_bytes` holds one lane of `inner_layout` at its stride.
|
||||
let inner_item = unsafe { GroupItem::from_resident(RecordBatch::new(inner_bytes.as_ptr(), 1, inner_layout)) };
|
||||
fn native_group_paint(vector: &Vector, arena: &core_types::arena::Arena) -> List<Graphic> {
|
||||
let mut builder = RunBuilder::new(arena, element_write_hashed::<Vector>(), &[], 1).unwrap();
|
||||
builder.push(vector.clone()).unwrap();
|
||||
List::new_from_element(Graphic::Group(core_types::record::Group {
|
||||
row: None,
|
||||
content: inner_item,
|
||||
content: builder.finish(),
|
||||
}))
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn an_owned_run_deep_copies_graphic_list_fields() {
|
||||
let inner_vector = unit_square_at(DVec2::ZERO);
|
||||
let inner_layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[]);
|
||||
let mut inner_bytes = vec![0u8; inner_layout.lane_stride()];
|
||||
let paint = native_group_paint(&inner_vector, &inner_layout, &mut inner_bytes);
|
||||
let source = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let paint = native_group_paint(&inner_vector, &source);
|
||||
|
||||
let vector = unit_square_at(DVec2::new(4., 4.));
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
let mut bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: `bytes` is one lane of `layout`; a parked element stores its
|
||||
// reference, and the fill field stores the marker's value form.
|
||||
unsafe {
|
||||
bytes.as_mut_ptr().cast::<&Vector>().write(&vector);
|
||||
bytes.as_mut_ptr().add(layout.offset_of(Fill::NAME, 0).unwrap()).cast::<Option<&List<Graphic>>>().write(Some(&paint));
|
||||
}
|
||||
let (owned, expected) = {
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
(item.copy_out(), map_groups_to_legacy(paint.element(0).unwrap()))
|
||||
};
|
||||
bytes.fill(u8::MAX);
|
||||
inner_bytes.fill(u8::MAX);
|
||||
let mut builder = RunBuilder::new(&source, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(vector.clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let item = builder.finish();
|
||||
let owned = item.copy_out();
|
||||
let expected = map_groups_to_legacy(paint.element(0).unwrap());
|
||||
drop(item);
|
||||
drop(paint);
|
||||
drop(source);
|
||||
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let replayed = owned.replay(&arena).expect("the arena holds the replay");
|
||||
@@ -1648,25 +1609,22 @@ mod run_tests {
|
||||
#[test]
|
||||
fn an_owned_record_deep_copies_graphic_list_fields() {
|
||||
let inner_vector = unit_square_at(DVec2::ZERO);
|
||||
let inner_layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[]);
|
||||
let mut inner_bytes = vec![0u8; inner_layout.lane_stride()];
|
||||
let paint = native_group_paint(&inner_vector, &inner_layout, &mut inner_bytes);
|
||||
let source = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let paint = native_group_paint(&inner_vector, &source);
|
||||
|
||||
let vector = unit_square_at(DVec2::new(4., 4.));
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
let mut builder = RunBuilder::new(&source, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(vector.clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let item = builder.finish();
|
||||
let layout = item.layout().clone();
|
||||
let offset = layout.offset_of(Fill::NAME, 0).unwrap();
|
||||
let mut bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: as in the run test above.
|
||||
unsafe {
|
||||
bytes.as_mut_ptr().cast::<&Vector>().write(&vector);
|
||||
bytes.as_mut_ptr().add(offset).cast::<Option<&List<Graphic>>>().write(Some(&paint));
|
||||
}
|
||||
// SAFETY: `bytes` is a live record of `layout`.
|
||||
let owned = unsafe { core_types::record::OwnedRecord::copy_out(&layout, core_types::record::Rec::new(bytes.as_ptr())) };
|
||||
// SAFETY: the item's lane is a live record of `layout`.
|
||||
let owned = unsafe { core_types::record::OwnedRecord::copy_out(&layout, item.lanes().get(0).rec()) };
|
||||
let expected = map_groups_to_legacy(paint.element(0).unwrap());
|
||||
bytes.fill(u8::MAX);
|
||||
inner_bytes.fill(u8::MAX);
|
||||
drop(item);
|
||||
drop(paint);
|
||||
drop(source);
|
||||
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
core_types::record::stack::reserve(layout.frame_bytes());
|
||||
@@ -1679,28 +1637,19 @@ mod run_tests {
|
||||
#[test]
|
||||
fn a_legacy_list_owns_its_paint_attr_content() {
|
||||
let inner_vector = unit_square_at(DVec2::ZERO);
|
||||
let inner_layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[]);
|
||||
let mut inner_bytes = vec![0u8; inner_layout.lane_stride()];
|
||||
let paint = native_group_paint(&inner_vector, &inner_layout, &mut inner_bytes);
|
||||
let source = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let paint = native_group_paint(&inner_vector, &source);
|
||||
|
||||
let vector = unit_square_at(DVec2::new(4., 4.));
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
let mut bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: `bytes` is one lane of `layout`; a parked element stores its
|
||||
// reference, and the fill field stores the marker's value form.
|
||||
unsafe {
|
||||
bytes.as_mut_ptr().cast::<&Vector>().write(&vector);
|
||||
bytes.as_mut_ptr().add(layout.offset_of(Fill::NAME, 0).unwrap()).cast::<Option<&List<Graphic>>>().write(Some(&paint));
|
||||
}
|
||||
let (legacy, expected) = {
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let legacy = run_to_legacy_list::<Vector>(&item).expect("the run lowers to a legacy vector list");
|
||||
(legacy, map_groups_to_legacy(paint.element(0).unwrap()))
|
||||
};
|
||||
bytes.fill(u8::MAX);
|
||||
inner_bytes.fill(u8::MAX);
|
||||
let mut builder = RunBuilder::new(&source, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(vector.clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let item = builder.finish();
|
||||
let legacy = run_to_legacy_list::<Vector>(&item).expect("the run lowers to a legacy vector list");
|
||||
let expected = map_groups_to_legacy(paint.element(0).unwrap());
|
||||
drop(item);
|
||||
drop(paint);
|
||||
drop(source);
|
||||
|
||||
let served = legacy.attribute::<Option<List<Graphic>>>(Fill::NAME, 0).expect("the fill attribute rides the list");
|
||||
let served = served.as_ref().expect("the fill is present");
|
||||
@@ -1710,18 +1659,13 @@ mod run_tests {
|
||||
#[test]
|
||||
fn a_run_list_keeps_native_group_elements() {
|
||||
let inner_vector = unit_square_at(DVec2::ZERO);
|
||||
let inner_layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[]);
|
||||
let mut inner_bytes = vec![0u8; inner_layout.lane_stride()];
|
||||
let content = native_group_paint(&inner_vector, &inner_layout, &mut inner_bytes);
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let content = native_group_paint(&inner_vector, &arena);
|
||||
let element = content.element(0).unwrap();
|
||||
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Graphic>(), &[]);
|
||||
let mut bytes = vec![0u8; layout.lane_stride()];
|
||||
// SAFETY: `bytes` is one lane of `layout`; a parked element stores its
|
||||
// reference.
|
||||
unsafe { bytes.as_mut_ptr().cast::<&Graphic>().write(element) };
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Graphic>(), &[], 1).unwrap();
|
||||
builder.push(element.clone()).unwrap();
|
||||
let item = builder.finish();
|
||||
let list = run_to_list::<Graphic>(&item).expect("the run holds graphic lanes");
|
||||
assert!(matches!(list.element(0), Some(Graphic::Group(_))), "the list keeps the native group form");
|
||||
}
|
||||
@@ -1729,13 +1673,10 @@ mod run_tests {
|
||||
#[test]
|
||||
fn the_vector_row_walk_matches_the_legacy_flatten() {
|
||||
let inner_vector = unit_square_at(DVec2::ZERO);
|
||||
let inner_layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[]);
|
||||
let mut inner_bytes = vec![0u8; inner_layout.lane_stride()];
|
||||
// SAFETY: `inner_bytes` is one lane of `inner_layout`; a parked element
|
||||
// stores its reference.
|
||||
unsafe { inner_bytes.as_mut_ptr().cast::<&Vector>().write(&inner_vector) };
|
||||
// SAFETY: `inner_bytes` holds one lane of `inner_layout` at its stride.
|
||||
let inner_item = unsafe { GroupItem::from_resident(RecordBatch::new(inner_bytes.as_ptr(), 1, &inner_layout)) };
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Vector>(), &[], 1).unwrap();
|
||||
builder.push(inner_vector.clone()).unwrap();
|
||||
let inner_item = builder.finish();
|
||||
|
||||
let mut painted = List::new();
|
||||
painted.push(Item::new_from_element(Graphic::Vector(unit_square_at(DVec2::ZERO))));
|
||||
@@ -1793,19 +1734,13 @@ mod run_tests {
|
||||
let vectors = [unit_square_at(DVec2::ZERO), unit_square_at(DVec2::new(4., 4.))];
|
||||
let transforms = [DAffine2::from_translation(DVec2::new(1., 2.)), DAffine2::from_scale(DVec2::splat(3.))];
|
||||
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<core_types::attribute::Transform>(0)]);
|
||||
let stride = layout.lane_stride();
|
||||
let mut bytes = vec![0u8; stride * 2];
|
||||
// SAFETY: `bytes` is `stride` per lane, and the offsets come from `layout`.
|
||||
unsafe {
|
||||
for lane in 0..2 {
|
||||
let base = bytes.as_mut_ptr().add(lane * stride);
|
||||
base.cast::<&Vector>().write(&vectors[lane]);
|
||||
base.add(layout.offset_of(core_types::ATTR_TRANSFORM, 0).unwrap()).cast::<DAffine2>().write(transforms[lane]);
|
||||
}
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Vector>(), &[FieldWrite::of::<core_types::attribute::Transform>(0)], 2).unwrap();
|
||||
for lane in 0..2 {
|
||||
let lane = builder.push(vectors[lane].clone()).unwrap();
|
||||
builder.attr::<core_types::attribute::Transform>(lane, transforms[lane]);
|
||||
}
|
||||
// SAFETY: `bytes` holds two lanes of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 2, &layout)) };
|
||||
let item = builder.finish();
|
||||
let run = RunView::<Vector>::new(&item).expect("the run holds vector elements");
|
||||
let legacy = run_to_legacy_list::<Vector>(&item).expect("the run lowers to a legacy vector list");
|
||||
|
||||
|
||||
@@ -3025,9 +3025,7 @@ impl SvgRenderAttrs<'_> {
|
||||
#[cfg(test)]
|
||||
mod group_walk_tests {
|
||||
use super::*;
|
||||
use core_types::attribute::Attribute;
|
||||
use core_types::node::RecordBatch;
|
||||
use core_types::record::{FieldWrite, GroupItem, Layout, element_write_hashed};
|
||||
use core_types::record::{FieldWrite, RunBuilder, element_write_hashed};
|
||||
use graphic_types::markers::Fill;
|
||||
use graphic_types::vector_types::vector::PointId;
|
||||
|
||||
@@ -3046,31 +3044,16 @@ mod group_walk_tests {
|
||||
(output.svg, output.svg_defs)
|
||||
}
|
||||
|
||||
/// One run lane per element of `elements`, each with a fill field, under the given layout writes.
|
||||
unsafe fn write_lanes<T>(layout: &Layout, elements: &[&T], fill: &[Option<&List<Graphic>>]) -> Vec<u8> {
|
||||
let stride = layout.lane_stride();
|
||||
let mut bytes = vec![0u8; stride * elements.len()];
|
||||
for lane in 0..elements.len() {
|
||||
// SAFETY: `bytes` is `stride` per lane; a parked element stores its
|
||||
// reference, and the fill field stores the marker's value form.
|
||||
unsafe {
|
||||
let base = bytes.as_mut_ptr().add(lane * stride);
|
||||
base.cast::<&T>().write(elements[lane]);
|
||||
base.add(layout.offset_of(Fill::NAME, 0).unwrap()).cast::<Option<&List<Graphic>>>().write(fill[lane]);
|
||||
}
|
||||
}
|
||||
bytes
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn a_vector_run_group_renders_its_rows_without_layer_wrappers() {
|
||||
let paint = color_paint();
|
||||
let vectors = [unit_square_at(DVec2::ZERO), unit_square_at(DVec2::new(3., 1.))];
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
// SAFETY: the layout carries a parked vector element and the fill field.
|
||||
let bytes = unsafe { write_lanes::<Vector>(&layout, &[&vectors[0], &vectors[1]], &[Some(&paint), None]) };
|
||||
// SAFETY: `bytes` holds two lanes of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 2, &layout)) };
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 2).unwrap();
|
||||
let lane = builder.push(vectors[0].clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
builder.push(vectors[1].clone()).unwrap();
|
||||
let item = builder.finish();
|
||||
let group = Group { row: None, content: item };
|
||||
|
||||
let params = RenderParams::default();
|
||||
@@ -3084,11 +3067,11 @@ mod group_walk_tests {
|
||||
fn lane_paint_on_a_graphic_run_reaches_vector_interiors() {
|
||||
let paint = color_paint();
|
||||
let inner = Graphic::Vector(unit_square_at(DVec2::ZERO));
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Graphic>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
// SAFETY: the layout carries a parked graphic element and the fill field.
|
||||
let bytes = unsafe { write_lanes::<Graphic>(&layout, &[&inner], &[Some(&paint)]) };
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Graphic>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(inner.clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let item = builder.finish();
|
||||
let group = Group { row: None, content: item };
|
||||
|
||||
let params = RenderParams::default();
|
||||
@@ -3103,11 +3086,11 @@ mod group_walk_tests {
|
||||
fn a_group_collects_its_lane_metadata_for_the_caller() {
|
||||
let paint = color_paint();
|
||||
let vectors = [unit_square_at(DVec2::ZERO)];
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
// SAFETY: the layout carries a parked vector element and the fill field.
|
||||
let bytes = unsafe { write_lanes::<Vector>(&layout, &[&vectors[0]], &[Some(&paint)]) };
|
||||
// SAFETY: `bytes` holds one lane of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 1, &layout)) };
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 1).unwrap();
|
||||
let lane = builder.push(vectors[0].clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
let item = builder.finish();
|
||||
let group = Group { row: None, content: item };
|
||||
|
||||
let footprint = Footprint::default();
|
||||
@@ -3128,11 +3111,12 @@ mod group_walk_tests {
|
||||
fn a_group_serves_its_legacy_lowerings_click_targets() {
|
||||
let paint = color_paint();
|
||||
let vectors = [unit_square_at(DVec2::ZERO), unit_square_at(DVec2::new(2., 2.))];
|
||||
let layout = Layout::default().with_writes(0, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)]);
|
||||
// SAFETY: the layout carries a parked vector element and the fill field.
|
||||
let bytes = unsafe { write_lanes::<Vector>(&layout, &[&vectors[0], &vectors[1]], &[Some(&paint), None]) };
|
||||
// SAFETY: `bytes` holds two lanes of `layout` at its stride.
|
||||
let item = unsafe { GroupItem::from_resident(RecordBatch::new(bytes.as_ptr(), 2, &layout)) };
|
||||
let arena = core_types::arena::Arena::new(1 << 16).unwrap();
|
||||
let mut builder = RunBuilder::new(&arena, element_write_hashed::<Vector>(), &[FieldWrite::of::<Fill>(0)], 2).unwrap();
|
||||
let lane = builder.push(vectors[0].clone()).unwrap();
|
||||
builder.attr::<Fill>(lane, Some(&paint));
|
||||
builder.push(vectors[1].clone()).unwrap();
|
||||
let item = builder.finish();
|
||||
let group = Group { row: None, content: item };
|
||||
|
||||
let mut native = Vec::new();
|
||||
|
||||
Reference in New Issue
Block a user