mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-31 21:56:50 -06:00
IDML: a left-aligned anchored object's X offset reads in the layout's direction (#555)
This commit is contained in:
@@ -2055,7 +2055,8 @@ impl<'a> Ex<'a> {
|
||||
.attr("VerticalReferencePoint", names::anchor_rel_out(*y_relative, true))
|
||||
.attr("HorizontalAlignment", ["LeftAlign", "CenterAlign", "RightAlign"][(*ref_point % 3) as usize])
|
||||
.attr("VerticalAlignment", ["TopAlign", "CenterAlign", "BottomAlign"][(*ref_point / 3).min(2) as usize])
|
||||
.attr("AnchorXoffset", num(*x_offset))
|
||||
// IDML measures a left-aligned object's X offset leftwards.
|
||||
.attr("AnchorXoffset", num(if *ref_point % 3 == 0 { 0.0 - *x_offset } else { *x_offset }))
|
||||
.attr("AnchorYoffset", num(*y_offset))
|
||||
.attr("PinPosition", bool_s(*keep_within_column)),
|
||||
};
|
||||
|
||||
@@ -1876,7 +1876,8 @@ impl<'r> Importer<'r> {
|
||||
designcraft_doc::AnchorPosition::Custom {
|
||||
x_relative: names::anchor_rel_in(s("HorizontalReferencePoint")),
|
||||
y_relative: names::anchor_rel_in(s("VerticalReferencePoint")),
|
||||
x_offset: get("AnchorXoffset"),
|
||||
// IDML measures a left-aligned object's X offset leftwards.
|
||||
x_offset: if col == 0 { 0.0 - get("AnchorXoffset") } else { get("AnchorXoffset") },
|
||||
y_offset: get("AnchorYoffset"),
|
||||
object_point: names::anchor_in(s("AnchorPoint")),
|
||||
ref_point: row * 3 + col,
|
||||
|
||||
@@ -822,13 +822,65 @@ fn anchored_objects_take_unset_settings_from_object_styles() {
|
||||
assert_eq!(
|
||||
positions,
|
||||
[
|
||||
custom(R::TextFrame, R::Anchor, 5.0, -3.0, 8, true),
|
||||
custom(R::TextFrame, R::Anchor, -5.0, -3.0, 8, true),
|
||||
custom(R::TextFrame, R::PageEdge, 0.0, 0.0, 0, true),
|
||||
custom(R::PageMargin, R::Anchor, 2.0, 0.0, 8, false),
|
||||
custom(R::PageMargin, R::Anchor, -2.0, 0.0, 8, false),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
/// IDML measures a left-aligned anchored object's X offset leftwards; the document model and
|
||||
/// composition measure every X offset rightwards.
|
||||
#[test]
|
||||
fn left_aligned_anchored_x_offsets_flip_at_the_idml_boundary() {
|
||||
use designcraft_doc::AnchorPosition;
|
||||
let rect = |id: &str, align: &str, x: &str| {
|
||||
format!(
|
||||
r#"<Rectangle Self="{id}" ItemTransform="1 0 0 1 0 0">
|
||||
<Properties><PathGeometry><GeometryPathType PathOpen="false"><PathPointArray>
|
||||
<PathPointType Anchor="0 0"/><PathPointType Anchor="0 10"/><PathPointType Anchor="10 10"/><PathPointType Anchor="10 0"/>
|
||||
</PathPointArray></GeometryPathType></PathGeometry></Properties>
|
||||
<AnchoredObjectSetting AnchoredPosition="Anchored" AnchorPoint="TopLeftAnchor" HorizontalReferencePoint="TextFrame"
|
||||
HorizontalAlignment="{align}" VerticalAlignment="TopAlign" VerticalReferencePoint="PageEdge" AnchorXoffset="{x}" AnchorYoffset="0"/>
|
||||
</Rectangle>"#
|
||||
)
|
||||
};
|
||||
let story = format!(
|
||||
r#"<idPkg:Story xmlns:idPkg="http://ns.adobe.com/AdobeInDesign/idml/1.0/packaging"><Story Self="s1">
|
||||
<ParagraphStyleRange><CharacterStyleRange><Content>a</Content>{}{}{}</CharacterStyleRange></ParagraphStyleRange>
|
||||
</Story></idPkg:Story>"#,
|
||||
rect("left", "LeftAlign", "-108"),
|
||||
rect("zero", "LeftAlign", "0"),
|
||||
rect("center", "CenterAlign", "116"),
|
||||
);
|
||||
let d = import_idml(&fixture_with_story(&story)).unwrap();
|
||||
let x_offsets = |d: &Document| -> Vec<f64> {
|
||||
let s = d.stories.values().find(|s| !s.objects.is_empty()).unwrap();
|
||||
s.objects.iter().map(|o| if let AnchorPosition::Custom { x_offset, .. } = o.position { x_offset } else { f64::NAN }).collect()
|
||||
};
|
||||
assert_eq!(x_offsets(&d), [108.0, 0.0, 116.0]);
|
||||
// The left-aligned object lands 108 pt right of the reference point.
|
||||
let sid = d.stories.iter().find(|(_, s)| !s.objects.is_empty()).map(|(id, _)| *id).unwrap();
|
||||
let cs = designcraft_compose::compose_story(&d, sid, &Default::default());
|
||||
let placed: Vec<_> = cs.frames.iter().flat_map(|f| &f.objects).collect();
|
||||
let x = |i: usize| placed.iter().find(|o| o.index == i).unwrap().origin.x;
|
||||
assert!((x(0) - x(1) - 108.0).abs() < 1e-6, "{} {}", x(0), x(1));
|
||||
// Export writes the original IDML values back.
|
||||
let bytes = export_idml(&d);
|
||||
let mut zip = zip::ZipArchive::new(std::io::Cursor::new(bytes)).unwrap();
|
||||
let mut stories = String::new();
|
||||
for i in 0..zip.len() {
|
||||
let mut f = zip.by_index(i).unwrap();
|
||||
if f.name().starts_with("Stories/") {
|
||||
std::io::Read::read_to_string(&mut f, &mut stories).unwrap();
|
||||
}
|
||||
}
|
||||
for v in [r#"AnchorXoffset="-108""#, r#"AnchorXoffset="0""#, r#"AnchorXoffset="116""#] {
|
||||
assert!(stories.contains(v), "{v} missing");
|
||||
}
|
||||
assert_eq!(x_offsets(&import_idml(&export_idml(&d)).unwrap()), [108.0, 0.0, 116.0]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn round_trips_frames_with_pasted_in_items() {
|
||||
let mut d = Document::new(&NewDocument::default());
|
||||
|
||||
Reference in New Issue
Block a user