mirror of
https://github.com/typst/typst
synced 2025-05-14 04:56:26 +08:00
Reuse location type
This commit is contained in:
parent
736289b064
commit
f8009b5b59
@ -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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
28
src/frame.rs
28
src/frame.rs
@ -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()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
} {
|
} {
|
||||||
|
@ -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()),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user