Reuse location type

This commit is contained in:
Laurenz 2022-05-27 14:33:00 +02:00
parent 736289b064
commit f8009b5b59
4 changed files with 41 additions and 45 deletions

View File

@ -333,14 +333,14 @@ impl<'a> PdfExporter<'a> {
.action_type(ActionType::Uri) .action_type(ActionType::Uri)
.uri(Str(uri.as_str().as_bytes())); .uri(Str(uri.as_str().as_bytes()));
} }
Destination::Internal(page, point) => { Destination::Internal(loc) => {
let page = page - 1; let index = loc.page - 1;
let height = page_heights[page]; let height = page_heights[index];
link.action() link.action()
.action_type(ActionType::GoTo) .action_type(ActionType::GoTo)
.destination_direct() .destination_direct()
.page(page_refs[page]) .page(page_refs[index])
.xyz(point.x.to_f32(), height - point.y.to_f32(), None); .xyz(loc.pos.x.to_f32(), height - loc.pos.y.to_f32(), None);
} }
} }
} }

View File

@ -3,6 +3,7 @@
use std::fmt::{self, Debug, Formatter, Write}; use std::fmt::{self, Debug, Formatter, Write};
use std::sync::Arc; use std::sync::Arc;
use crate::eval::{Dict, Value};
use crate::font::FaceId; use crate::font::FaceId;
use crate::geom::{ use crate::geom::{
Align, Em, Length, Numeric, Paint, Point, Shape, Size, Spec, Transform, Align, Em, Length, Numeric, Paint, Point, Shape, Size, Spec, Transform,
@ -313,21 +314,30 @@ pub struct Glyph {
} }
/// A link destination. /// A link destination.
#[derive(Clone, Eq, PartialEq, Hash)] #[derive(Debug, Clone, Eq, PartialEq, Hash)]
pub enum Destination { pub enum Destination {
/// A link to a point on a page. /// A link to a point on a page.
Internal(usize, Point), Internal(Location),
/// A link to a URL. /// A link to a URL.
Url(EcoString), Url(EcoString),
} }
impl Debug for Destination { /// A physical location in a document.
fn fmt(&self, f: &mut Formatter) -> fmt::Result { #[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
match self { pub struct Location {
Self::Internal(page, point) => { /// The page, starting at 1.
write!(f, "Internal(Page {}, {:?})", page, point) pub page: usize,
} /// The exact coordinates on the page (from the top left, as usual).
Self::Url(url) => write!(f, "Url({})", url), 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()),
} }
} }
} }

View File

@ -1,6 +1,5 @@
use super::TextNode; use super::TextNode;
use crate::library::prelude::*; use crate::library::prelude::*;
use crate::util::EcoString;
/// Link text and other elements to an URL. /// Link text and other elements to an URL.
#[derive(Debug, Hash)] #[derive(Debug, Hash)]
@ -24,7 +23,7 @@ impl LinkNode {
let dest = args.expect::<Destination>("destination")?; let dest = args.expect::<Destination>("destination")?;
let body = match dest { let body = match dest {
Destination::Url(_) => args.eat()?, Destination::Url(_) => args.eat()?,
Destination::Internal(_, _) => Some(args.expect("body")?), Destination::Internal(_) => Some(args.expect("body")?),
}; };
Self { dest, body } Self { dest, body }
})) }))
@ -36,10 +35,10 @@ castable! {
Expected: "string or dictionary with `page`, `x`, and `y` keys", Expected: "string or dictionary with `page`, `x`, and `y` keys",
Value::Str(string) => Self::Url(string), Value::Str(string) => Self::Url(string),
Value::Dict(dict) => { Value::Dict(dict) => {
let page: i64 = dict.get(&EcoString::from_str("page"))?.clone().cast()?; let page: i64 = dict.get(&"page".into())?.clone().cast()?;
let x: RawLength = dict.get(&EcoString::from_str("x"))?.clone().cast()?; let x: RawLength = dict.get(&"x".into())?.clone().cast()?;
let y: RawLength = dict.get(&EcoString::from_str("y"))?.clone().cast()?; let y: RawLength = dict.get(&"y".into())?.clone().cast()?;
Self::Internal(page as usize, Point::new(x.length, y.length)) Self::Internal(Location { page: page as usize, pos: Point::new(x.length, y.length) })
}, },
} }
@ -56,11 +55,7 @@ impl Show for LinkNode {
dict! { dict! {
"url" => match &self.dest { "url" => match &self.dest {
Destination::Url(url) => Value::Str(url.clone()), Destination::Url(url) => Value::Str(url.clone()),
Destination::Internal(page, point) => Value::Dict(dict!{ Destination::Internal(loc) => Value::Dict(loc.encode()),
"page" => Value::Int(*page as i64),
"x" => Value::Length(point.x.into()),
"y" => Value::Length(point.y.into()),
}),
}, },
"body" => match &self.body { "body" => match &self.body {
Some(body) => Value::Content(body.clone()), Some(body) => Value::Content(body.clone()),
@ -79,7 +74,7 @@ impl Show for LinkNode {
let shorter = text.len() < url.len(); let shorter = text.len() < url.len();
Content::Text(if shorter { text.into() } else { url.clone() }) 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) { if match styles.get(Self::UNDERLINE) {
Smart::Auto => match &self.dest { Smart::Auto => match &self.dest {
Destination::Url(_) => true, Destination::Url(_) => true,
Destination::Internal(_, _) => false, Destination::Internal(_) => false,
}, },
Smart::Custom(underline) => underline, Smart::Custom(underline) => underline,
} { } {

View File

@ -4,7 +4,7 @@ use std::sync::Arc;
use super::Content; use super::Content;
use crate::diag::TypResult; use crate::diag::TypResult;
use crate::eval::{Args, Array, Dict, Func, Value}; 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::geom::{Point, Transform};
use crate::syntax::Spanned; use crate::syntax::Spanned;
use crate::util::EcoString; use crate::util::EcoString;
@ -296,7 +296,7 @@ fn locate_in_frame(
} }
/// A document pin. /// A document pin.
#[derive(Debug, Default, Clone, PartialEq, Hash)] #[derive(Debug, Clone, PartialEq, Hash)]
pub struct Pin { pub struct Pin {
/// The physical location of the pin in the document. /// The physical location of the pin in the document.
loc: Location, loc: Location,
@ -330,22 +330,13 @@ impl Pin {
} }
} }
/// A physical location in a document. impl Default for Pin {
#[derive(Debug, Default, Copy, Clone, PartialEq, Hash)] fn default() -> Self {
struct Location { Self {
/// The page, starting at 1. loc: Location { page: 0, pos: Point::zero() },
page: usize, flow: 0,
/// The exact coordinates on the page (from the top left, as usual). group: None,
pos: Point, value: None,
}
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()),
} }
} }
} }