mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-02 14:47:05 -06:00
Text: stories made in a right-to-left-bound document fill their columns from the right (#100)
This commit is contained in:
@@ -171,11 +171,18 @@ impl Document {
|
||||
Ok(removed)
|
||||
}
|
||||
|
||||
/// The column direction a new story starts with: right to left in a document whose binding is
|
||||
/// right to left (Document Setup), else left to right. Stories already made keep theirs.
|
||||
pub fn new_story_direction(&self) -> crate::TextDirection {
|
||||
if self.settings.right_to_left_binding { crate::TextDirection::RightToLeft } else { crate::TextDirection::LeftToRight }
|
||||
}
|
||||
|
||||
/// Create a text frame with a new (or given) story at `rect` on spread `r`.
|
||||
pub fn add_text_frame(&mut self, r: SpreadRef, rect: Rect, layer: LayerId, text: &str, para: ParaFormat) -> Result<(ItemId, StoryId)> {
|
||||
let id = ItemId(self.alloc());
|
||||
let sid = StoryId(self.alloc());
|
||||
let mut story = Story::with_text(sid, text, para);
|
||||
story.direction = self.new_story_direction();
|
||||
story.frames.push(id);
|
||||
self.stories.insert(sid, Arc::new(story));
|
||||
let mut item = Item::new(id, layer, Shape::Rectangle, shapes::rectangle(rect));
|
||||
|
||||
@@ -759,6 +759,35 @@ mod setup_tests {
|
||||
let d = &s.doc().unwrap().doc;
|
||||
assert_eq!(d.spreads[1].pages.iter().map(|p| (p.side, p.x)).collect::<Vec<_>>(), vec![(Left, 0.0), (Right, w)]);
|
||||
}
|
||||
|
||||
/// Multi-column frames filled the left column first in a right-to-left document (#100):
|
||||
/// stories made in a right-to-left-bound document start their columns on the right.
|
||||
#[test]
|
||||
fn new_stories_follow_the_binding_direction() {
|
||||
use designcraft_doc::TextDirection::{LeftToRight, RightToLeft};
|
||||
let text = (1..=12).map(|i| format!("الفقرة {i}")).collect::<Vec<_>>().join("\n");
|
||||
for (binding, expected) in [("rightToLeft", RightToLeft), ("leftToRight", LeftToRight)] {
|
||||
let mut s = crate::Session::new();
|
||||
s.execute("file.new", &json!({"preset": "A4", "pages": 1})).unwrap();
|
||||
s.execute("layout.documentSetup", &json!({"binding": binding})).unwrap();
|
||||
let f = s.execute("frame.create", &json!({"rect": [40, 170, 555, 260], "content": "text", "text": text})).unwrap();
|
||||
s.execute("object.textFrameOptions", &json!({"ids": [f["id"]], "columns": 2, "gutter": 20})).unwrap();
|
||||
let sid = designcraft_doc::StoryId(f["story"].as_u64().unwrap());
|
||||
let st = s.doc().unwrap();
|
||||
assert_eq!(st.doc.story(sid).unwrap().direction, expected, "{binding}");
|
||||
let cs = s.cache.get(&st.doc, sid, None);
|
||||
let fr = &cs.frames[0];
|
||||
let (first, last) = (fr.lines.first().unwrap(), fr.lines.last().unwrap());
|
||||
assert!(fr.columns.len() == 2 && first.x0 != last.x0, "the text fills both columns: {:?}", fr.columns);
|
||||
assert_eq!(first.x0 > last.x0, expected == RightToLeft, "{binding}: the first line is in the first column");
|
||||
// An empty frame given text content starts a story too.
|
||||
let g = s.execute("frame.create", &json!({"rect": [40, 400, 555, 500]})).unwrap();
|
||||
s.execute("object.content", &json!({"ids": [g["id"]], "type": "text"})).unwrap();
|
||||
let d = &s.doc().unwrap().doc;
|
||||
let tf = d.item(designcraft_doc::ItemId(g["id"].as_u64().unwrap())).unwrap().text_frame().unwrap().story;
|
||||
assert_eq!(d.story(tf).unwrap().direction, expected, "{binding}: object.content");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
|
||||
@@ -1379,6 +1379,7 @@ fn content_type(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
("text", Some(Content::Unassigned | Content::Graphic(_))) => {
|
||||
let sid = StoryId(d.alloc());
|
||||
let mut st = Story::new(sid);
|
||||
st.direction = d.new_story_direction();
|
||||
st.frames.push(*id);
|
||||
d.stories.insert(sid, Arc::new(st));
|
||||
if let Some(it) = d.item_mut(*id) {
|
||||
|
||||
@@ -54,6 +54,7 @@ fn on_path(s: &mut Session, p: &Value) -> Result<Value> {
|
||||
}
|
||||
let sid = StoryId(d.alloc());
|
||||
let mut st = Story::with_text(sid, &text, Default::default());
|
||||
st.direction = d.new_story_direction();
|
||||
st.frames = vec![id];
|
||||
d.stories.insert(sid, std::sync::Arc::new(st));
|
||||
let it = d.item_mut(id).ok_or(designcraft_doc::DocError::NoItem(id))?;
|
||||
|
||||
@@ -200,6 +200,7 @@ pub(super) fn place_text(s: &mut Session, p: &Value, name: &str, bytes: &[u8]) -
|
||||
Some(_) => {
|
||||
let sid = StoryId(d.alloc());
|
||||
let mut ns = Story::new(sid);
|
||||
ns.direction = d.new_story_direction();
|
||||
ns.frames = vec![fid];
|
||||
d.stories.insert(sid, std::sync::Arc::new(ns));
|
||||
if let Some(it) = d.item_mut(fid) {
|
||||
|
||||
Reference in New Issue
Block a user