Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions crates/shift-store/src/font.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
use crate::{ShiftStore, StoreError};

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct FontInfo {
pub family_name: Option<String>,
pub copyright: Option<String>,
pub trademark: Option<String>,
pub description: Option<String>,
pub sample_text: Option<String>,
pub designer: Option<String>,
pub designer_url: Option<String>,
pub manufacturer: Option<String>,
pub manufacturer_url: Option<String>,
pub license_description: Option<String>,
pub license_info_url: Option<String>,
pub vendor_id: Option<String>,
pub version_major: Option<i64>,
pub version_minor: Option<i64>,
pub units_per_em: i64,
}

impl ShiftStore {
pub fn set_font_info(&mut self, font_info: FontInfo) -> Result<(), StoreError> {
self.conn.execute(
"
INSERT INTO font_info (
id,
family_name,
copyright,
trademark,
description,
sample_text,
designer,
designer_url,
manufacturer,
manufacturer_url,
license_description,
license_info_url,
vendor_id,
version_major,
version_minor,
units_per_em
)
VALUES (1, ?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8, ?9, ?10, ?11, ?12, ?13, ?14, ?15)
ON CONFLICT(id) DO UPDATE SET
family_name = excluded.family_name,
copyright = excluded.copyright,
trademark = excluded.trademark,
description = excluded.description,
sample_text = excluded.sample_text,
designer = excluded.designer,
designer_url = excluded.designer_url,
manufacturer = excluded.manufacturer,
manufacturer_url = excluded.manufacturer_url,
license_description = excluded.license_description,
license_info_url = excluded.license_info_url,
vendor_id = excluded.vendor_id,
version_major = excluded.version_major,
version_minor = excluded.version_minor,
units_per_em = excluded.units_per_em
",
rusqlite::params![
font_info.family_name,
font_info.copyright,
font_info.trademark,
font_info.description,
font_info.sample_text,
font_info.designer,
font_info.designer_url,
font_info.manufacturer,
font_info.manufacturer_url,
font_info.license_description,
font_info.license_info_url,
font_info.vendor_id,
font_info.version_major,
font_info.version_minor,
font_info.units_per_em,
],
)?;

Ok(())
}

pub fn get_font_info(&self) -> Result<Option<FontInfo>, StoreError> {
let mut stmt = self.conn.prepare(
"
SELECT
family_name,
copyright,
trademark,
description,
sample_text,
designer,
designer_url,
manufacturer,
manufacturer_url,
license_description,
license_info_url,
vendor_id,
version_major,
version_minor,
units_per_em
FROM font_info
WHERE id = 1
",
)?;

match stmt.query_row([], map_font_info_row) {
Ok(font_info) => Ok(Some(font_info)),
Err(rusqlite::Error::QueryReturnedNoRows) => Ok(None),
Err(err) => Err(err.into()),
}
}
}

fn map_font_info_row(row: &rusqlite::Row<'_>) -> rusqlite::Result<FontInfo> {
Ok(FontInfo {
family_name: row.get(0)?,
copyright: row.get(1)?,
trademark: row.get(2)?,
description: row.get(3)?,
sample_text: row.get(4)?,
designer: row.get(5)?,
designer_url: row.get(6)?,
manufacturer: row.get(7)?,
manufacturer_url: row.get(8)?,
license_description: row.get(9)?,
license_info_url: row.get(10)?,
vendor_id: row.get(11)?,
version_major: row.get(12)?,
version_minor: row.get(13)?,
units_per_em: row.get(14)?,
})
}
2 changes: 2 additions & 0 deletions crates/shift-store/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod component;
mod connection;
mod error;
mod font;
mod glyph;
mod layer;
mod schema;
Expand All @@ -10,6 +11,7 @@ mod types;

pub use component::{GlyphComponentRecord, NewGlyphComponent};
pub use error::StoreError;
pub use font::FontInfo;
pub use glyph::{GlyphRecord, NewGlyph};
pub use layer::{GlyphLayerRecord, NewGlyphLayer};
pub use source::{AxisRecord, NewAxis, NewSource, SourceAxisLocation, SourceKind, SourceRecord};
Expand Down
19 changes: 19 additions & 0 deletions crates/shift-store/src/schema.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,25 @@
use crate::StoreError;

pub(crate) const SCHEMA_V1: &str = r#"
CREATE TABLE IF NOT EXISTS font_info (
id INTEGER PRIMARY KEY CHECK (id = 1),
family_name TEXT,
copyright TEXT,
trademark TEXT,
description TEXT,
sample_text TEXT,
designer TEXT,
designer_url TEXT,
manufacturer TEXT,
manufacturer_url TEXT,
license_description TEXT,
license_info_url TEXT,
vendor_id TEXT,
version_major INTEGER CHECK (version_major IS NULL OR version_major >= 0),
version_minor INTEGER CHECK (version_minor IS NULL OR version_minor >= 0),
units_per_em INTEGER NOT NULL CHECK (units_per_em > 0)
);

CREATE TABLE IF NOT EXISTS axes (
id TEXT PRIMARY KEY,
tag TEXT NOT NULL,
Expand Down
108 changes: 106 additions & 2 deletions crates/shift-store/tests/store_test.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,68 @@
use shift_store::{
AxisId, ComponentId, GlyphId, LayerId, NewAxis, NewGlyph, NewGlyphComponent, NewGlyphLayer,
NewSource, ShiftStore, SourceId, SourceKind,
AxisId, ComponentId, FontInfo, GlyphId, LayerId, NewAxis, NewGlyph, NewGlyphComponent,
NewGlyphLayer, NewSource, ShiftStore, SourceId, SourceKind,
};

#[test]
fn opens_memory_store() {
ShiftStore::open_memory_for_test().expect("memory store should open");
}

#[test]
fn writes_and_reads_font_info() {
let mut store = ShiftStore::open_memory_for_test().expect("memory store should open");
let font_info = open_sans_font_info();

store
.set_font_info(font_info.clone())
.expect("font info should be written");

let loaded = store
.get_font_info()
.expect("font info query should succeed")
.expect("font info should exist");

assert_eq!(loaded, font_info);
}

#[test]
fn overwrites_font_info() {
let mut store = ShiftStore::open_memory_for_test().expect("memory store should open");

store
.set_font_info(open_sans_font_info())
.expect("font info should be written");

store
.set_font_info(FontInfo {
family_name: Some("Shift Sans".to_string()),
units_per_em: 1000,
..empty_font_info()
})
.expect("font info should be overwritten");

let loaded = store
.get_font_info()
.expect("font info query should succeed")
.expect("font info should exist");

assert_eq!(loaded.family_name.as_deref(), Some("Shift Sans"));
assert_eq!(loaded.units_per_em, 1000);
assert_eq!(loaded.copyright, None);
}

#[test]
fn font_info_requires_positive_units_per_em() {
let mut store = ShiftStore::open_memory_for_test().expect("memory store should open");

let result = store.set_font_info(FontInfo {
units_per_em: 0,
..empty_font_info()
});

assert!(result.is_err());
}

#[test]
fn creates_and_reads_glyph() {
let mut store = ShiftStore::open_memory_for_test().expect("memory store should open");
Expand Down Expand Up @@ -215,6 +270,55 @@ fn create_glyph_a(store: &mut ShiftStore) -> GlyphId {
glyph_id
}

fn open_sans_font_info() -> FontInfo {
FontInfo {
family_name: Some("Open Sans".to_string()),
copyright: Some(
"Copyright 2020 The Open Sans Project Authors (https://github.com/googlefonts/opensans)"
.to_string(),
),
trademark: Some(
"Open Sans is a trademark of Google and may be registered in certain jurisdictions."
.to_string(),
),
description: Some("Designed by Monotype design team.".to_string()),
sample_text: None,
designer: Some("Monotype Design Team".to_string()),
designer_url: Some("http://www.monotype.com/studio".to_string()),
manufacturer: Some("Monotype Imaging Inc.".to_string()),
manufacturer_url: Some("http://www.google.com/get/noto/".to_string()),
license_description: Some(
"This Font Software is licensed under the SIL Open Font License, Version 1.1."
.to_string(),
),
license_info_url: Some("http://scripts.sil.org/OFL".to_string()),
vendor_id: None,
version_major: Some(3),
version_minor: Some(3),
units_per_em: 2048,
}
}

fn empty_font_info() -> FontInfo {
FontInfo {
family_name: None,
copyright: None,
trademark: None,
description: None,
sample_text: None,
designer: None,
designer_url: None,
manufacturer: None,
manufacturer_url: None,
license_description: None,
license_info_url: None,
vendor_id: None,
version_major: None,
version_minor: None,
units_per_em: 1000,
}
}

fn create_glyph_b(store: &mut ShiftStore) -> GlyphId {
let glyph_id = GlyphId::new("glyph-B");

Expand Down
Loading