mirror of
https://github.com/typst/typst
synced 2025-05-13 20:46:23 +08:00
Move some types into better places 🧱
This commit is contained in:
parent
f683bba400
commit
db96ecae94
Binary file not shown.
202
src/doc.rs
202
src/doc.rs
@ -1,9 +1,10 @@
|
||||
//! Abstract representation of a typesetted document.
|
||||
//! Representation of typesetted documents.
|
||||
|
||||
use crate::font::Font;
|
||||
use crate::engine::Size;
|
||||
|
||||
|
||||
/// A representation of a typesetted document.
|
||||
/// A complete typesetted document, which can be exported.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Document {
|
||||
/// The pages of the document.
|
||||
@ -12,62 +13,6 @@ pub struct Document {
|
||||
pub fonts: Vec<Font>,
|
||||
}
|
||||
|
||||
/// Default styles for a document.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Style {
|
||||
/// The width of the paper.
|
||||
pub width: Size,
|
||||
/// The height of the paper.
|
||||
pub height: Size,
|
||||
|
||||
/// The left margin of the paper.
|
||||
pub margin_left: Size,
|
||||
/// The top margin of the paper.
|
||||
pub margin_top: Size,
|
||||
/// The right margin of the paper.
|
||||
pub margin_right: Size,
|
||||
/// The bottom margin of the paper.
|
||||
pub margin_bottom: Size,
|
||||
|
||||
/// A fallback list of font families to use.
|
||||
pub font_families: Vec<FontFamily>,
|
||||
/// The font size.
|
||||
pub font_size: f32,
|
||||
/// The line spacing (as a multiple of the font size).
|
||||
pub line_spacing: f32,
|
||||
}
|
||||
|
||||
/// A family of fonts (either generic or named).
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum FontFamily {
|
||||
SansSerif,
|
||||
Serif,
|
||||
Monospace,
|
||||
Named(String),
|
||||
}
|
||||
|
||||
impl Default for Style {
|
||||
fn default() -> Style {
|
||||
use FontFamily::*;
|
||||
Style {
|
||||
// A4 paper.
|
||||
width: Size::from_mm(210.0),
|
||||
height: Size::from_mm(297.0),
|
||||
|
||||
// Margins. A bit more on top and bottom.
|
||||
margin_left: Size::from_cm(2.5),
|
||||
margin_top: Size::from_cm(3.0),
|
||||
margin_right: Size::from_cm(2.5),
|
||||
margin_bottom: Size::from_cm(3.0),
|
||||
|
||||
// Default font family, font size and line spacing.
|
||||
font_families: vec![SansSerif, Serif, Monospace],
|
||||
font_size: 12.0,
|
||||
line_spacing: 1.25,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A page with text contents in a document.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Page {
|
||||
@ -96,144 +41,3 @@ pub enum TextCommand {
|
||||
/// Use the indexed font in the documents font list with a given font size.
|
||||
SetFont(usize, f32),
|
||||
}
|
||||
|
||||
/// A general distance type that can convert between units.
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct Size {
|
||||
/// The size in typographic points (1/72 inches).
|
||||
points: f32,
|
||||
}
|
||||
|
||||
impl Size {
|
||||
/// Create an zeroed size.
|
||||
#[inline]
|
||||
pub fn zero() -> Size { Size { points: 0.0 } }
|
||||
|
||||
/// Create a size from a number of points.
|
||||
#[inline]
|
||||
pub fn from_points(points: f32) -> Size { Size { points } }
|
||||
|
||||
/// Create a size from a number of inches.
|
||||
#[inline]
|
||||
pub fn from_inches(inches: f32) -> Size { Size { points: 72.0 * inches } }
|
||||
|
||||
/// Create a size from a number of millimeters.
|
||||
#[inline]
|
||||
pub fn from_mm(mm: f32) -> Size { Size { points: 2.83465 * mm } }
|
||||
|
||||
/// Create a size from a number of centimeters.
|
||||
#[inline]
|
||||
pub fn from_cm(cm: f32) -> Size { Size { points: 28.3465 * cm } }
|
||||
|
||||
/// Create a size from a number of points.
|
||||
#[inline]
|
||||
pub fn to_points(&self) -> f32 { self.points }
|
||||
|
||||
/// Create a size from a number of inches.
|
||||
#[inline]
|
||||
pub fn to_inches(&self) -> f32 { self.points * 0.0138889 }
|
||||
|
||||
/// Create a size from a number of millimeters.
|
||||
#[inline]
|
||||
pub fn to_mm(&self) -> f32 { self.points * 0.352778 }
|
||||
|
||||
/// Create a size from a number of centimeters.
|
||||
#[inline]
|
||||
pub fn to_cm(&self) -> f32 { self.points * 0.0352778 }
|
||||
}
|
||||
|
||||
mod size {
|
||||
use super::Size;
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt;
|
||||
use std::iter::Sum;
|
||||
use std::ops::*;
|
||||
|
||||
impl fmt::Display for Size {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
write!(f, "{}pt", self.points)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_reflexive {
|
||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident) => {
|
||||
impl $trait for Size {
|
||||
type Output = Size;
|
||||
|
||||
#[inline]
|
||||
fn $func(self, other: Size) -> Size {
|
||||
Size { points: $trait::$func(self.points, other.points) }
|
||||
}
|
||||
}
|
||||
|
||||
impl $assign_trait for Size {
|
||||
#[inline]
|
||||
fn $assign_func(&mut self, other: Size) {
|
||||
$assign_trait::$assign_func(&mut self.points, other.points);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_num_back {
|
||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => {
|
||||
impl $trait<$ty> for Size {
|
||||
type Output = Size;
|
||||
|
||||
#[inline]
|
||||
fn $func(self, other: $ty) -> Size {
|
||||
Size { points: $trait::$func(self.points, other as f32) }
|
||||
}
|
||||
}
|
||||
|
||||
impl $assign_trait<$ty> for Size {
|
||||
#[inline]
|
||||
fn $assign_func(&mut self, other: $ty) {
|
||||
$assign_trait::$assign_func(&mut self.points, other as f32);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_num_both {
|
||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => {
|
||||
impl_num_back!($trait, $func, $assign_trait, $assign_func, $ty);
|
||||
|
||||
impl $trait<Size> for $ty {
|
||||
type Output = Size;
|
||||
|
||||
#[inline]
|
||||
fn $func(self, other: Size) -> Size {
|
||||
Size { points: $trait::$func(self as f32, other.points) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl Neg for Size {
|
||||
type Output = Size;
|
||||
|
||||
fn neg(self) -> Size {
|
||||
Size { points: -self.points }
|
||||
}
|
||||
}
|
||||
|
||||
impl_reflexive!(Add, add, AddAssign, add_assign);
|
||||
impl_reflexive!(Sub, sub, SubAssign, sub_assign);
|
||||
impl_num_both!(Mul, mul, MulAssign, mul_assign, f32);
|
||||
impl_num_both!(Mul, mul, MulAssign, mul_assign, i32);
|
||||
impl_num_back!(Div, div, DivAssign, div_assign, f32);
|
||||
impl_num_back!(Div, div, DivAssign, div_assign, i32);
|
||||
|
||||
impl PartialOrd for Size {
|
||||
fn partial_cmp(&self, other: &Size) -> Option<Ordering> {
|
||||
self.points.partial_cmp(&other.points)
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for Size {
|
||||
fn sum<I>(iter: I) -> Size where I: Iterator<Item=Size> {
|
||||
iter.fold(Size::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,13 @@
|
||||
//! Core typesetting engine.
|
||||
|
||||
use crate::syntax::{SyntaxTree, Node};
|
||||
use crate::doc::{Document, Size, Page, Text, TextCommand};
|
||||
use crate::font::{Font, FontConfig, FontError};
|
||||
use crate::doc::{Document, Page, Text, TextCommand};
|
||||
use crate::font::{Font, FontFamily, FontConfig, FontError};
|
||||
use crate::Context;
|
||||
|
||||
mod size;
|
||||
pub use size::Size;
|
||||
|
||||
|
||||
/// The core typesetting engine, transforming an abstract syntax tree into a document.
|
||||
pub(crate) struct Engine<'a> {
|
||||
@ -138,6 +141,53 @@ impl<'a> Engine<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Default styles for a document.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct Style {
|
||||
/// The width of the paper.
|
||||
pub width: Size,
|
||||
/// The height of the paper.
|
||||
pub height: Size,
|
||||
|
||||
/// The left margin of the paper.
|
||||
pub margin_left: Size,
|
||||
/// The top margin of the paper.
|
||||
pub margin_top: Size,
|
||||
/// The right margin of the paper.
|
||||
pub margin_right: Size,
|
||||
/// The bottom margin of the paper.
|
||||
pub margin_bottom: Size,
|
||||
|
||||
/// A fallback list of font families to use.
|
||||
pub font_families: Vec<FontFamily>,
|
||||
/// The font size.
|
||||
pub font_size: f32,
|
||||
/// The line spacing (as a multiple of the font size).
|
||||
pub line_spacing: f32,
|
||||
}
|
||||
|
||||
impl Default for Style {
|
||||
fn default() -> Style {
|
||||
use FontFamily::*;
|
||||
Style {
|
||||
// A4 paper.
|
||||
width: Size::from_mm(210.0),
|
||||
height: Size::from_mm(297.0),
|
||||
|
||||
// Margins. A bit more on top and bottom.
|
||||
margin_left: Size::from_cm(2.5),
|
||||
margin_top: Size::from_cm(3.0),
|
||||
margin_right: Size::from_cm(2.5),
|
||||
margin_bottom: Size::from_cm(3.0),
|
||||
|
||||
// Default font family, font size and line spacing.
|
||||
font_families: vec![SansSerif, Serif, Monospace],
|
||||
font_size: 12.0,
|
||||
line_spacing: 1.25,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The error type for typesetting.
|
||||
pub enum TypesetError {
|
||||
/// There was no suitable font.
|
144
src/engine/size.rs
Normal file
144
src/engine/size.rs
Normal file
@ -0,0 +1,144 @@
|
||||
use std::cmp::Ordering;
|
||||
use std::fmt::{self, Display, Debug, Formatter};
|
||||
use std::iter::Sum;
|
||||
use std::ops::*;
|
||||
|
||||
|
||||
/// A general distance type that can convert between units.
|
||||
#[derive(Copy, Clone, PartialEq)]
|
||||
pub struct Size {
|
||||
/// The size in typographic points (1/72 inches).
|
||||
points: f32,
|
||||
}
|
||||
|
||||
impl Size {
|
||||
/// Create an zeroed size.
|
||||
#[inline]
|
||||
pub fn zero() -> Size { Size { points: 0.0 } }
|
||||
|
||||
/// Create a size from a number of points.
|
||||
#[inline]
|
||||
pub fn from_points(points: f32) -> Size { Size { points } }
|
||||
|
||||
/// Create a size from a number of inches.
|
||||
#[inline]
|
||||
pub fn from_inches(inches: f32) -> Size { Size { points: 72.0 * inches } }
|
||||
|
||||
/// Create a size from a number of millimeters.
|
||||
#[inline]
|
||||
pub fn from_mm(mm: f32) -> Size { Size { points: 2.83465 * mm } }
|
||||
|
||||
/// Create a size from a number of centimeters.
|
||||
#[inline]
|
||||
pub fn from_cm(cm: f32) -> Size { Size { points: 28.3465 * cm } }
|
||||
|
||||
/// Create a size from a number of points.
|
||||
#[inline]
|
||||
pub fn to_points(&self) -> f32 { self.points }
|
||||
|
||||
/// Create a size from a number of inches.
|
||||
#[inline]
|
||||
pub fn to_inches(&self) -> f32 { self.points * 0.0138889 }
|
||||
|
||||
/// Create a size from a number of millimeters.
|
||||
#[inline]
|
||||
pub fn to_mm(&self) -> f32 { self.points * 0.352778 }
|
||||
|
||||
/// Create a size from a number of centimeters.
|
||||
#[inline]
|
||||
pub fn to_cm(&self) -> f32 { self.points * 0.0352778 }
|
||||
}
|
||||
|
||||
impl Display for Size {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
write!(f, "{}pt", self.points)
|
||||
}
|
||||
}
|
||||
|
||||
impl Debug for Size {
|
||||
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
|
||||
Display::fmt(self, f)
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialOrd for Size {
|
||||
fn partial_cmp(&self, other: &Size) -> Option<Ordering> {
|
||||
self.points.partial_cmp(&other.points)
|
||||
}
|
||||
}
|
||||
|
||||
impl Neg for Size {
|
||||
type Output = Size;
|
||||
|
||||
fn neg(self) -> Size {
|
||||
Size { points: -self.points }
|
||||
}
|
||||
}
|
||||
|
||||
impl Sum for Size {
|
||||
fn sum<I>(iter: I) -> Size where I: Iterator<Item=Size> {
|
||||
iter.fold(Size::zero(), Add::add)
|
||||
}
|
||||
}
|
||||
|
||||
macro_rules! impl_reflexive {
|
||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident) => {
|
||||
impl $trait for Size {
|
||||
type Output = Size;
|
||||
|
||||
#[inline]
|
||||
fn $func(self, other: Size) -> Size {
|
||||
Size { points: $trait::$func(self.points, other.points) }
|
||||
}
|
||||
}
|
||||
|
||||
impl $assign_trait for Size {
|
||||
#[inline]
|
||||
fn $assign_func(&mut self, other: Size) {
|
||||
$assign_trait::$assign_func(&mut self.points, other.points);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_num_back {
|
||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => {
|
||||
impl $trait<$ty> for Size {
|
||||
type Output = Size;
|
||||
|
||||
#[inline]
|
||||
fn $func(self, other: $ty) -> Size {
|
||||
Size { points: $trait::$func(self.points, other as f32) }
|
||||
}
|
||||
}
|
||||
|
||||
impl $assign_trait<$ty> for Size {
|
||||
#[inline]
|
||||
fn $assign_func(&mut self, other: $ty) {
|
||||
$assign_trait::$assign_func(&mut self.points, other as f32);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
macro_rules! impl_num_both {
|
||||
($trait:ident, $func:ident, $assign_trait:ident, $assign_func:ident, $ty:ty) => {
|
||||
impl_num_back!($trait, $func, $assign_trait, $assign_func, $ty);
|
||||
|
||||
impl $trait<Size> for $ty {
|
||||
type Output = Size;
|
||||
|
||||
#[inline]
|
||||
fn $func(self, other: Size) -> Size {
|
||||
Size { points: $trait::$func(self as f32, other.points) }
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
impl_reflexive!(Add, add, AddAssign, add_assign);
|
||||
impl_reflexive!(Sub, sub, SubAssign, sub_assign);
|
||||
impl_num_both!(Mul, mul, MulAssign, mul_assign, f32);
|
||||
impl_num_both!(Mul, mul, MulAssign, mul_assign, i32);
|
||||
impl_num_back!(Div, div, DivAssign, div_assign, f32);
|
||||
impl_num_back!(Div, div, DivAssign, div_assign, i32);
|
@ -1,3 +1,5 @@
|
||||
//! Error handling.
|
||||
|
||||
/// Create an error type.
|
||||
macro_rules! error_type {
|
||||
(
|
||||
|
@ -6,8 +6,9 @@ use pdf::{PdfWriter, Ref, Rect, Version, Trailer, Content};
|
||||
use pdf::doc::{Catalog, PageTree, Page, Resource, Text};
|
||||
use pdf::font::{Type0Font, CIDFont, CIDFontType, CIDSystemInfo, FontDescriptor, FontFlags};
|
||||
use pdf::font::{GlyphUnit, CMapEncoding, WidthRecord, FontStream, EmbeddedFontType};
|
||||
use crate::doc::{Document, Size, Text as DocText, TextCommand};
|
||||
use crate::doc::{Document, Text as DocText, TextCommand};
|
||||
use crate::font::{Font, FontError};
|
||||
use crate::engine::Size;
|
||||
|
||||
|
||||
/// Exports documents into _PDFs_.
|
||||
|
26
src/font.rs
26
src/font.rs
@ -1,6 +1,4 @@
|
||||
//! Font loading, utility and subsetting.
|
||||
|
||||
#![macro_use]
|
||||
//! Font loading and transforming.
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Path, PathBuf};
|
||||
@ -9,7 +7,7 @@ use byteorder::{BE, ReadBytesExt, WriteBytesExt};
|
||||
use opentype::{Error as OpentypeError, OpenTypeReader, Outlines, TableRecord, Tag};
|
||||
use opentype::tables::{Header, Name, CharMap, MaximumProfile, HorizontalMetrics, Post, OS2};
|
||||
use opentype::global::{MacStyleFlags, NameEntry};
|
||||
use crate::doc::{Size, FontFamily};
|
||||
use crate::engine::Size;
|
||||
|
||||
|
||||
/// An font wrapper which allows to subset a font.
|
||||
@ -54,8 +52,8 @@ impl Font {
|
||||
/// Create a new font from a font program.
|
||||
pub fn new(program: Vec<u8>) -> FontResult<Font> {
|
||||
// Create opentype reader to parse font tables
|
||||
let mut readable = Cursor::new(&program);
|
||||
let mut reader = OpenTypeReader::new(&mut readable);
|
||||
let cursor = Cursor::new(&program);
|
||||
let mut reader = OpenTypeReader::new(cursor);
|
||||
|
||||
// Read the relevant tables
|
||||
// (all of these are required by the OpenType specification)
|
||||
@ -586,8 +584,6 @@ impl<T> TakeInvalid<T> for Option<T> {
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/// A type that provides fonts matching given criteria.
|
||||
pub trait FontProvider {
|
||||
/// Returns a font matching the configuration
|
||||
@ -599,8 +595,18 @@ pub trait FontProvider {
|
||||
///
|
||||
/// Automatically implemented for all types that are [`Read`] and [`Seek`].
|
||||
pub trait FontSource: Read + Seek {}
|
||||
|
||||
impl<T> FontSource for T where T: Read + Seek {}
|
||||
|
||||
/// A family of fonts (either generic or named).
|
||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||
pub enum FontFamily {
|
||||
SansSerif,
|
||||
Serif,
|
||||
Monospace,
|
||||
Named(String),
|
||||
}
|
||||
|
||||
/// Criteria to filter fonts.
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct FontConfig {
|
||||
@ -694,8 +700,8 @@ impl FileFontDescriptor<'_> {
|
||||
#[macro_export]
|
||||
macro_rules! file_font {
|
||||
($family:expr, [$($generic:ident),*], $path:expr, $bold:expr, $italic:expr) => {{
|
||||
let mut families = vec![$crate::doc::FontFamily::Named($family.to_string())];
|
||||
families.extend([$($crate::doc::FontFamily::$generic),*].iter().cloned());
|
||||
let mut families = vec![$crate::font::FontFamily::Named($family.to_string())];
|
||||
families.extend([$($crate::font::FontFamily::$generic),*].iter().cloned());
|
||||
$crate::font::FileFontDescriptor {
|
||||
path: std::path::Path::new($path),
|
||||
families,
|
||||
|
13
src/lib.rs
13
src/lib.rs
@ -33,16 +33,19 @@
|
||||
//! let document = compiler.typeset(src).unwrap();
|
||||
//!
|
||||
//! // Export the document into a PDF file.
|
||||
//! let mut file = File::create("hello-typeset.pdf").unwrap();
|
||||
//! # /*
|
||||
//! let file = File::create("hello-typeset.pdf").unwrap();
|
||||
//! # */
|
||||
//! # let file = File::create("../target/typeset-hello.pdf").unwrap();
|
||||
//! let exporter = PdfExporter::new();
|
||||
//! exporter.export(&document, &mut file).unwrap();
|
||||
//! exporter.export(&document, file).unwrap();
|
||||
//! ```
|
||||
|
||||
use crate::syntax::SyntaxTree;
|
||||
use crate::parsing::{Tokens, Parser, ParseError};
|
||||
use crate::doc::{Document, Style};
|
||||
use crate::doc::Document;
|
||||
use crate::font::FontProvider;
|
||||
use crate::engine::{Engine, TypesetError};
|
||||
use crate::engine::{Engine, Style, TypesetError};
|
||||
|
||||
#[macro_use]
|
||||
mod error;
|
||||
@ -50,6 +53,7 @@ mod utility;
|
||||
pub mod doc;
|
||||
pub mod engine;
|
||||
pub mod export;
|
||||
#[macro_use]
|
||||
pub mod font;
|
||||
pub mod parsing;
|
||||
pub mod syntax;
|
||||
@ -135,6 +139,7 @@ error_type! {
|
||||
from: (TypesetError, Error::Typeset(err)),
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod test {
|
||||
use std::fs::File;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! Parsing of source code into tokens and syntax trees.
|
||||
//! Tokenization and parsing of source code into syntax trees.
|
||||
|
||||
use std::fmt;
|
||||
use std::iter::Peekable;
|
||||
@ -475,7 +475,6 @@ mod token_tests {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[cfg(test)]
|
||||
mod parse_tests {
|
||||
use super::*;
|
||||
|
@ -1,4 +1,4 @@
|
||||
//! Token and abstract syntax tree representations.
|
||||
//! Tokenized and syntax tree representations of source code.
|
||||
|
||||
|
||||
/// A logical unit of the incoming text stream.
|
||||
|
Loading…
x
Reference in New Issue
Block a user