Skip to content

Commit

Permalink
add system fonts
Browse files Browse the repository at this point in the history
  • Loading branch information
alpaylan committed Sep 18, 2023
1 parent c61bad9 commit 61dc4c9
Show file tree
Hide file tree
Showing 15 changed files with 203 additions and 189 deletions.
4 changes: 2 additions & 2 deletions data/layout-schemas.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,10 @@
"item": "Title",
"width": "70%",
"font": {
"name": "Exo",
"name": "Baskerville",
"size": 14.0,
"weight": "Bold",
"source": "Local"
"source": "System"
}
}
},
Expand Down
Binary file modified results/output.pdf
Binary file not shown.
2 changes: 1 addition & 1 deletion src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use std::{collections::HashMap, fmt::Display};
use serde::{Deserialize, Serialize};

use crate::{
alignment::Alignment, font::{FontDict, Font}, layout::Layout, margin::Margin, resume_data::ItemContent,
alignment::Alignment, font::{Font, FontDict}, layout::Layout, margin::Margin, resume_data::ItemContent,
width::Width,
};

Expand Down
3 changes: 2 additions & 1 deletion src/data_schema.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ pub enum DocumentDataType {
}

impl DocumentDataType {
#[allow(dead_code)]
fn validate(data_type: &DocumentDataType, value: &ItemContent) -> bool {
match value {
ItemContent::None => unreachable!(),
Expand All @@ -38,7 +39,7 @@ impl DocumentDataType {
false
}
}
ItemContent::Url { url, text } => true,
ItemContent::Url { url: _, text: _ } => true,
}
}
}
Expand Down
4 changes: 0 additions & 4 deletions src/document.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,4 @@
use std::collections::HashMap;
use rusttype::{point, Font, Scale};

pub struct DocumentDefinition {
pub font_dict: HashMap<String, Font<'static>>,
pub width: f32,
pub height: f32,
}
19 changes: 9 additions & 10 deletions src/element.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
use std::{collections::HashMap, fmt::Display};
use std::fmt::Display;

use serde::{Deserialize, Serialize};

use crate::{alignment::Alignment, font::Font, margin::Margin, width::Width};
use rusttype::Font as RFont;
use crate::{alignment::Alignment, font::{Font, FontDict}, margin::Margin, width::Width};
use uuid::Uuid;

#[derive(Serialize, Deserialize, Clone, Debug)]
Expand Down Expand Up @@ -73,7 +72,7 @@ impl Element {
uid: self.uid,
}
}

#[allow(dead_code)]
pub fn with_margin(&self, margin: Margin) -> Element {
Element {
item: self.item.clone(),
Expand All @@ -87,7 +86,7 @@ impl Element {
uid: self.uid,
}
}

#[allow(dead_code)]
pub fn with_alignment(&self, alignment: Alignment) -> Element {
Element {
item: self.item.clone(),
Expand All @@ -101,7 +100,7 @@ impl Element {
uid: self.uid,
}
}

#[allow(dead_code)]
pub fn with_width(&self, width: Width) -> Element {
Element {
item: self.item.clone(),
Expand Down Expand Up @@ -159,7 +158,7 @@ impl Element {

}

pub fn fill_fonts(&self, fonts: &HashMap<String, RFont>) -> Element {
pub fn fill_fonts(&self, fonts: &FontDict) -> Element {
let text_width_with_font = self.font.get_width(&self.item, fonts);
if self.is_fill {
Element {
Expand Down Expand Up @@ -192,7 +191,7 @@ impl Element {

}

pub fn break_lines(&self, font_dict: &HashMap<String, RFont>) -> Vec<Element> {
pub fn break_lines(&self, font_dict: &FontDict) -> Vec<Element> {
if self.text_width.get_fixed_unchecked() <= self.width.get_fixed_unchecked() {
return vec![self.clone()];
}
Expand Down Expand Up @@ -264,10 +263,10 @@ mod tests {

#[test]
fn test_break_lines() {
let mut font_dict = HashMap::new();
let mut font_dict = FontDict::new();
let font_data = include_bytes!("../assets/Exo/static/Exo-Medium.ttf");
// This only succeeds if collection consists of one font
let _font = RFont::try_from_bytes(font_data as &[u8]).expect("Error constructing Font");
let _font = rusttype::Font::try_from_bytes(font_data as &[u8]).expect("Error constructing Font");
font_dict.insert("Arial".to_string(), _font);

let element = Element {
Expand Down
95 changes: 74 additions & 21 deletions src/font.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use std::collections::HashMap;
use std::{collections::HashMap, fs::File, io::Read};

use font_kit::properties::{Style, Weight};
use printpdf::IndirectFontRef;
use rusttype::{point, Scale};
use serde::{Deserialize, Serialize};

use rusttype::{point, Font as RFont, Scale};

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct Font {
#[serde(default = "Font::default_name")]
Expand All @@ -12,17 +13,16 @@ pub struct Font {
pub size: f32,
#[serde(default = "FontWeight::default")]
pub weight: FontWeight,
#[serde(default = "FontSlope::default")]
pub slope: FontSlope,
#[serde(default = "FontStyle::default")]
pub style: FontStyle,
#[serde(default = "FontSource::default")]
pub source: FontSource
pub source: FontSource,
}


#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum FontSource {
Local,
System
System,
}

impl Default for FontSource {
Expand Down Expand Up @@ -54,23 +54,42 @@ impl ToString for FontWeight {
}
}

impl Into<Weight> for FontWeight {
fn into(self) -> Weight {
match self {
FontWeight::Light => Weight::LIGHT,
FontWeight::Medium => Weight::MEDIUM,
FontWeight::Bold => Weight::BOLD,
}
}
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub enum FontSlope {
pub enum FontStyle {
Normal,
Italic,
}

impl Default for FontSlope {
impl Default for FontStyle {
fn default() -> Self {
FontSlope::Normal
FontStyle::Normal
}
}

impl ToString for FontSlope {
impl ToString for FontStyle {
fn to_string(&self) -> String {
match self {
FontSlope::Normal => "".to_string(),
FontSlope::Italic => "Italic".to_string(),
FontStyle::Normal => "".to_string(),
FontStyle::Italic => "Italic".to_string(),
}
}
}

impl Into<Style> for FontStyle {
fn into(self) -> Style {
match self {
FontStyle::Normal => Style::Normal,
FontStyle::Italic => Style::Italic,
}
}
}
Expand All @@ -81,8 +100,8 @@ impl Default for Font {
name: Font::default_name(),
size: Font::default_size(),
weight: FontWeight::default(),
slope: FontSlope::default(),
source: FontSource::default()
style: FontStyle::default(),
source: FontSource::default(),
}
}
}
Expand All @@ -97,17 +116,48 @@ impl Font {
}
}

pub type FontDict<'a> = HashMap<String, RFont<'a>>;
pub struct LoadedFont {
pub printpdf_font: IndirectFontRef,
pub rusttype_font: rusttype::Font<'static>,
}

pub type FontDict = HashMap<String, LoadedFont>;

pub trait FontLoader {
fn load_from_path(&mut self, doc: &printpdf::PdfDocumentReference, name: String, path: String);
}

impl FontLoader for FontDict {
fn load_from_path(&mut self, doc: &printpdf::PdfDocumentReference, name: String, path: String) {
let mut file = File::open(path).unwrap();
let mut bytes = Vec::new();
file.read_to_end(&mut bytes).unwrap();

let rusttype_font = rusttype::Font::try_from_vec(bytes.clone()).unwrap();
let printpdf_font = doc.add_external_font(bytes.as_slice()).unwrap();
self.insert(
name,
LoadedFont {
printpdf_font,
rusttype_font,
},
);
}
}

impl Font {
pub fn full_name(&self) -> String {
self.name.clone() + "-" + self.weight.to_string().as_str() + self.slope.to_string().as_str()
self.name.clone() + "-" + self.weight.to_string().as_str() + self.style.to_string().as_str()
}

pub fn get_width(&self, text: &String, font_dict: &FontDict) -> f32 {
// The font size to use
let scale = Scale::uniform(self.size);
let font = font_dict.get(&self.name).unwrap();
let font = &font_dict
.get(&self.full_name())
.unwrap_or_else(|| font_dict.get(&Font::default().full_name()).unwrap())
.rusttype_font;

// The text to render
let v_metrics = font.v_metrics(scale);

Expand All @@ -131,10 +181,13 @@ impl Font {
glyphs_width
}

pub fn get_height(&self, font_dict: &HashMap<String, RFont>) -> f32 {
pub fn get_height(&self, font_dict: &FontDict) -> f32 {
// The font size to use
let scale = Scale::uniform(self.size);
let font = font_dict.get(&self.name).unwrap();
let font = &font_dict
.get(&self.full_name())
.unwrap_or_else(|| &font_dict.get(&Font::default().full_name()).unwrap())
.rusttype_font;

// The text to render
let v_metrics = font.v_metrics(scale);
Expand Down
24 changes: 13 additions & 11 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use crate::basic_layout::BasicLayout;
use crate::container::Container;
use crate::document::DocumentDefinition;
use crate::element::Element;
use crate::font::{FontDict, Font};

use crate::font::{Font, FontDict};
use crate::margin::Margin;
use crate::point::Point;
use crate::resume_data::ItemContent;
Expand Down Expand Up @@ -77,6 +78,7 @@ impl Layout {
}

impl Layout {
#[allow(dead_code)]
pub fn type_(&self) -> String {
match self {
Layout::Stack(_) => "stack".to_string(),
Expand All @@ -95,7 +97,7 @@ impl Layout {
Layout::Text(element) | Layout::Ref(element) => element.width,
}
}

#[allow(dead_code)]
pub fn margin(&self) -> Margin {
match self {
Layout::Stack(container)
Expand All @@ -104,7 +106,7 @@ impl Layout {
Layout::Text(element) | Layout::Ref(element) => element.margin,
}
}

#[allow(dead_code)]
pub fn alignment(&self) -> Alignment {
match self {
Layout::Stack(container)
Expand All @@ -122,7 +124,7 @@ impl Layout {
Layout::Text(element) | Layout::Ref(element) => vec![element.font.clone()],
}
}

#[allow(dead_code)]
pub fn with_margin(&self, margin: Margin) -> Layout {
match self {
Layout::Stack(container) => Layout::new_stack(container.with_margin(margin)),
Expand All @@ -132,7 +134,7 @@ impl Layout {
Layout::Ref(element) => Layout::new_ref(element.with_margin(margin)),
}
}

#[allow(dead_code)]
pub fn with_alignment(&self, alignment: Alignment) -> Layout {
match self {
Layout::Stack(container) => Layout::new_stack(container.with_alignment(alignment)),
Expand Down Expand Up @@ -173,7 +175,7 @@ impl Layout {
if let Some(text) = section.get(&element.item) {
let mut element = element.with_item(text.to_string());

if let ItemContent::Url { url, text } = text {
if let ItemContent::Url { url, text: _ } = text {
element = element.with_url(url.clone())
}

Expand Down Expand Up @@ -211,7 +213,7 @@ impl Layout {
}
}

pub fn normalize(&self, document: &DocumentDefinition) -> Layout {
pub fn normalize(&self, document: &DocumentDefinition, font_dict: &FontDict) -> Layout {
log::debug!("Normalizing document, checking if {} is instantiated...", self);

if !self.is_instantiated() {
Expand All @@ -229,11 +231,11 @@ impl Layout {

log::debug!("Widths are bounded. Filling fonts...");

let font_filled_layout = bounded_layout.fill_fonts(&document.font_dict);
let font_filled_layout = bounded_layout.fill_fonts(font_dict);

log::debug!("Fonts filled. Breaking lines...");

let broken_layout = font_filled_layout.break_lines(&document.font_dict);
let broken_layout = font_filled_layout.break_lines(font_dict);

log::debug!("Lines broken.");

Expand Down Expand Up @@ -325,7 +327,7 @@ impl Layout {

fn compute_textbox_positions(
&self,
mut textbox_positions: &mut Vec<(SpatialBox, Element)>,
textbox_positions: &mut Vec<(SpatialBox, Element)>,
top_left: Point,
font_dict: &FontDict,
) -> f32 {
Expand All @@ -351,7 +353,7 @@ impl Layout {
),
Alignment::Right => (
top_left
.move_x_by((c.width.get_fixed_unchecked() - c.elements_width())),
.move_x_by(c.width.get_fixed_unchecked() - c.elements_width()),
0.0,
),
Alignment::Justified => (
Expand Down
Loading

0 comments on commit 61dc4c9

Please sign in to comment.