From f8009b5b59660b8252bd3ee2cedfd234a1c30cb1 Mon Sep 17 00:00:00 2001 From: Laurenz Date: Fri, 27 May 2022 14:33:00 +0200 Subject: [PATCH] Reuse location type --- src/export/pdf.rs | 10 +++++----- src/frame.rs | 28 +++++++++++++++++++--------- src/library/text/link.rs | 21 ++++++++------------- src/model/locate.rs | 27 +++++++++------------------ 4 files changed, 41 insertions(+), 45 deletions(-) diff --git a/src/export/pdf.rs b/src/export/pdf.rs index 5e8896f75..c050bfc5d 100644 --- a/src/export/pdf.rs +++ b/src/export/pdf.rs @@ -333,14 +333,14 @@ impl<'a> PdfExporter<'a> { .action_type(ActionType::Uri) .uri(Str(uri.as_str().as_bytes())); } - Destination::Internal(page, point) => { - let page = page - 1; - let height = page_heights[page]; + Destination::Internal(loc) => { + let index = loc.page - 1; + let height = page_heights[index]; link.action() .action_type(ActionType::GoTo) .destination_direct() - .page(page_refs[page]) - .xyz(point.x.to_f32(), height - point.y.to_f32(), None); + .page(page_refs[index]) + .xyz(loc.pos.x.to_f32(), height - loc.pos.y.to_f32(), None); } } } diff --git a/src/frame.rs b/src/frame.rs index 289de6dad..2ece51476 100644 --- a/src/frame.rs +++ b/src/frame.rs @@ -3,6 +3,7 @@ use std::fmt::{self, Debug, Formatter, Write}; use std::sync::Arc; +use crate::eval::{Dict, Value}; use crate::font::FaceId; use crate::geom::{ Align, Em, Length, Numeric, Paint, Point, Shape, Size, Spec, Transform, @@ -313,21 +314,30 @@ pub struct Glyph { } /// A link destination. -#[derive(Clone, Eq, PartialEq, Hash)] +#[derive(Debug, Clone, Eq, PartialEq, Hash)] pub enum Destination { /// A link to a point on a page. - Internal(usize, Point), + Internal(Location), /// A link to a URL. Url(EcoString), } -impl Debug for Destination { - fn fmt(&self, f: &mut Formatter) -> fmt::Result { - match self { - Self::Internal(page, point) => { - write!(f, "Internal(Page {}, {:?})", page, point) - } - Self::Url(url) => write!(f, "Url({})", url), +/// A physical location in a document. +#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)] +pub struct Location { + /// The page, starting at 1. + pub page: usize, + /// The exact coordinates on the page (from the top left, as usual). + pub pos: Point, +} + +impl Location { + /// Encode into a user-facing dictionary. + pub fn encode(&self) -> Dict { + dict! { + "page" => Value::Int(self.page as i64), + "x" => Value::Length(self.pos.x.into()), + "y" => Value::Length(self.pos.y.into()), } } } diff --git a/src/library/text/link.rs b/src/library/text/link.rs index 2ce7a4695..12cbaf590 100644 --- a/src/library/text/link.rs +++ b/src/library/text/link.rs @@ -1,6 +1,5 @@ use super::TextNode; use crate::library::prelude::*; -use crate::util::EcoString; /// Link text and other elements to an URL. #[derive(Debug, Hash)] @@ -24,7 +23,7 @@ impl LinkNode { let dest = args.expect::("destination")?; let body = match dest { Destination::Url(_) => args.eat()?, - Destination::Internal(_, _) => Some(args.expect("body")?), + Destination::Internal(_) => Some(args.expect("body")?), }; Self { dest, body } })) @@ -36,10 +35,10 @@ castable! { Expected: "string or dictionary with `page`, `x`, and `y` keys", Value::Str(string) => Self::Url(string), Value::Dict(dict) => { - let page: i64 = dict.get(&EcoString::from_str("page"))?.clone().cast()?; - let x: RawLength = dict.get(&EcoString::from_str("x"))?.clone().cast()?; - let y: RawLength = dict.get(&EcoString::from_str("y"))?.clone().cast()?; - Self::Internal(page as usize, Point::new(x.length, y.length)) + let page: i64 = dict.get(&"page".into())?.clone().cast()?; + let x: RawLength = dict.get(&"x".into())?.clone().cast()?; + let y: RawLength = dict.get(&"y".into())?.clone().cast()?; + Self::Internal(Location { page: page as usize, pos: Point::new(x.length, y.length) }) }, } @@ -56,11 +55,7 @@ impl Show for LinkNode { dict! { "url" => match &self.dest { Destination::Url(url) => Value::Str(url.clone()), - Destination::Internal(page, point) => Value::Dict(dict!{ - "page" => Value::Int(*page as i64), - "x" => Value::Length(point.x.into()), - "y" => Value::Length(point.y.into()), - }), + Destination::Internal(loc) => Value::Dict(loc.encode()), }, "body" => match &self.body { Some(body) => Value::Content(body.clone()), @@ -79,7 +74,7 @@ impl Show for LinkNode { let shorter = text.len() < url.len(); Content::Text(if shorter { text.into() } else { url.clone() }) } - Destination::Internal(_, _) => panic!("missing body"), + Destination::Internal(_) => Content::Empty, })) } @@ -99,7 +94,7 @@ impl Show for LinkNode { if match styles.get(Self::UNDERLINE) { Smart::Auto => match &self.dest { Destination::Url(_) => true, - Destination::Internal(_, _) => false, + Destination::Internal(_) => false, }, Smart::Custom(underline) => underline, } { diff --git a/src/model/locate.rs b/src/model/locate.rs index 05204d2ec..c61facc55 100644 --- a/src/model/locate.rs +++ b/src/model/locate.rs @@ -4,7 +4,7 @@ use std::sync::Arc; use super::Content; use crate::diag::TypResult; use crate::eval::{Args, Array, Dict, Func, Value}; -use crate::frame::{Element, Frame}; +use crate::frame::{Element, Frame, Location}; use crate::geom::{Point, Transform}; use crate::syntax::Spanned; use crate::util::EcoString; @@ -296,7 +296,7 @@ fn locate_in_frame( } /// A document pin. -#[derive(Debug, Default, Clone, PartialEq, Hash)] +#[derive(Debug, Clone, PartialEq, Hash)] pub struct Pin { /// The physical location of the pin in the document. loc: Location, @@ -330,22 +330,13 @@ impl Pin { } } -/// A physical location in a document. -#[derive(Debug, Default, Copy, Clone, PartialEq, Hash)] -struct Location { - /// The page, starting at 1. - page: usize, - /// The exact coordinates on the page (from the top left, as usual). - pos: Point, -} - -impl Location { - /// Encode into a user-facing dictionary. - fn encode(&self) -> Dict { - dict! { - "page" => Value::Int(self.page as i64), - "x" => Value::Length(self.pos.x.into()), - "y" => Value::Length(self.pos.y.into()), +impl Default for Pin { + fn default() -> Self { + Self { + loc: Location { page: 0, pos: Point::zero() }, + flow: 0, + group: None, + value: None, } } }