mirror of
https://github.com/storytold/designcraft.git
synced 2026-11-09 03:51:38 +00:00
Integration: #787 refuses bitmap-only fonts for embedding, and styles name the face's numeric weight
This commit is contained in:
1 parent
11e4a7f60e
commit
8f54d1cce4
3 files changed
+41
-10
No files matched your search
@@ -156,7 +156,7 @@ fn embedded_fonts(d: &designcraft_doc::Document, warnings: &mut Vec<String>) ->
|
|||||||
let face = db.face(&family, &style);
|
let face = db.face(&family, &style);
|
||||||
if !face.family.eq_ignore_ascii_case(&family) {
|
if !face.family.eq_ignore_ascii_case(&family) {
|
||||||
warnings.push(format!("font `{family} {style}` is not available; not embedded"));
|
warnings.push(format!("font `{family} {style}` is not available; not embedded"));
|
||||||
} else if face.restricted_licence() {
|
} else if face.restricted_licence() || face.bitmap_only() {
|
||||||
warnings.push(format!("font `{family} {style}`: its licence doesn't allow embedding; not embedded"));
|
warnings.push(format!("font `{family} {style}`: its licence doesn't allow embedding; not embedded"));
|
||||||
} else if face.data().starts_with(b"ttcf") {
|
} else if face.data().starts_with(b"ttcf") {
|
||||||
warnings.push(format!("font `{family} {style}` is part of a font collection; not embedded"));
|
warnings.push(format!("font `{family} {style}` is part of a font collection; not embedded"));
|
||||||
@@ -811,6 +811,36 @@ mod text_tests {
|
|||||||
assert!(html.contains("\"Source Sans 3\", sans-serif;"));
|
assert!(html.contains("\"Source Sans 3\", sans-serif;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A font whose licence allows embedding bitmaps only (fsType bit 9) is not packaged whole,
|
||||||
|
/// and a Semibold style asks for the Semibold face's weight, not Bold's.
|
||||||
|
#[test]
|
||||||
|
fn epub_embedding_follows_bitmap_only_licences_and_weights() {
|
||||||
|
use designcraft_fonts::testing::{font_with, with_fs_type};
|
||||||
|
const BITMAP: &str = "DocFont Epub Bitmap Only";
|
||||||
|
for fs_type in [0x0200, 0x0208] {
|
||||||
|
designcraft_fonts::FontDb::global()
|
||||||
|
.add_font(with_fs_type(font_with(&format!("{BITMAP} {fs_type:04x}"), &['W']).unwrap(), fs_type).unwrap());
|
||||||
|
}
|
||||||
|
let mut s = Session::new();
|
||||||
|
s.execute("file.new", &json!({"pages": 1})).unwrap();
|
||||||
|
for fs_type in [0x0200, 0x0208] {
|
||||||
|
let family = format!("{BITMAP} {fs_type:04x}");
|
||||||
|
s.execute("style.paragraph.create", &json!({"name": family, "chars": {"fontFamily": family, "fontStyle": "Regular"}})).unwrap();
|
||||||
|
}
|
||||||
|
s.execute("style.paragraph.create", &json!({"name": "Semi", "chars": {"fontFamily": "Source Sans 3", "fontStyle": "Semibold"}})).unwrap();
|
||||||
|
s.execute("frame.create", &json!({"rect": [72, 72, 400, 200], "content": "text", "text": "Words", "caret": false})).unwrap();
|
||||||
|
let r = s.execute("file.exportEpub", &json!({"embedFonts": true})).unwrap();
|
||||||
|
let mut z = unzip(r["base64"].as_str().unwrap());
|
||||||
|
let css = read(&mut z, "OEBPS/style.css");
|
||||||
|
assert!(!css.contains(&format!("@font-face {{ font-family: \"{BITMAP}")), "{css}");
|
||||||
|
let warnings = r["warnings"].to_string();
|
||||||
|
for fs_type in [0x0200, 0x0208] {
|
||||||
|
assert!(warnings.contains(&format!("{BITMAP} {fs_type:04x} Regular`: its licence doesn't allow embedding")), "{warnings}");
|
||||||
|
}
|
||||||
|
let semi = css.lines().find(|l| l.contains(".semi {")).unwrap_or_default();
|
||||||
|
assert!(semi.contains("font-weight: 600;"), "{css}");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn flattener_rasterises_spreads_with_transparency() {
|
fn flattener_rasterises_spreads_with_transparency() {
|
||||||
let mut s = Session::new();
|
let mut s = Session::new();
|
||||||
|
|||||||
@@ -349,15 +349,9 @@ fn hex(doc: &Document, swatch: &str, tint: f32) -> Option<String> {
|
|||||||
|
|
||||||
fn char_css(doc: &Document, c: &CharProps, base_size: f64, generics: &BTreeMap<String, String>, out: &mut String) {
|
fn char_css(doc: &Document, c: &CharProps, base_size: f64, generics: &BTreeMap<String, String>, out: &mut String) {
|
||||||
let _ = write!(out, "font-family: \"{}\", {}; ", css_string(&c.font_family), generic_family(&c.font_family, generics));
|
let _ = write!(out, "font-family: \"{}\", {}; ", css_string(&c.font_family), generic_family(&c.font_family, generics));
|
||||||
let st = c.font_style.to_lowercase();
|
// The face's own weight, so an embedded Semibold or Light face is the one chosen.
|
||||||
if st.contains("bold") {
|
let (weight, style) = css_weight_style(&c.font_style);
|
||||||
out.push_str("font-weight: bold; ");
|
let _ = write!(out, "font-weight: {weight}; font-style: {style}; ");
|
||||||
} else if st.contains("semibold") {
|
|
||||||
out.push_str("font-weight: 600; ");
|
|
||||||
}
|
|
||||||
if st.contains("italic") {
|
|
||||||
out.push_str("font-style: italic; ");
|
|
||||||
}
|
|
||||||
let _ = write!(out, "font-size: {:.3}em; ", c.size / base_size);
|
let _ = write!(out, "font-size: {:.3}em; ", c.size / base_size);
|
||||||
if c.tracking != 0.0 {
|
if c.tracking != 0.0 {
|
||||||
let _ = write!(out, "letter-spacing: {:.3}em; ", c.tracking / 1000.0);
|
let _ = write!(out, "letter-spacing: {:.3}em; ", c.tracking / 1000.0);
|
||||||
|
|||||||
@@ -358,6 +358,13 @@ impl FontFace {
|
|||||||
let fs_type = self.skrifa().and_then(|f| f.os2().ok()).map_or(0, |t| t.fs_type());
|
let fs_type = self.skrifa().and_then(|f| f.os2().ok()).map_or(0, |t| t.fs_type());
|
||||||
fs_type & 0x0002 != 0 && fs_type & 0x000C == 0
|
fs_type & 0x0002 != 0 && fs_type & 0x000C == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Does the font's licence allow embedding bitmaps only? OS/2 `fsType` bit 9: the outlines
|
||||||
|
/// may not be passed on, so the font file can't be packaged whole.
|
||||||
|
pub fn bitmap_only(&self) -> bool {
|
||||||
|
use skrifa::raw::TableProvider;
|
||||||
|
self.skrifa().and_then(|f| f.os2().ok()).is_some_and(|t| t.fs_type() & 0x0200 != 0)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(not(target_arch = "wasm32"))]
|
#[cfg(not(target_arch = "wasm32"))]
|
||||||
|
|||||||
Reference in new issue
Block a user