-
Notifications
You must be signed in to change notification settings - Fork 105
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add tests that will match rendered words/paragraphs against reference images. Use env var `GENERATE_IMAGES` to write the initial reference images to the repository.
- Loading branch information
Showing
8 changed files
with
318 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
This package is distributed under the terms of GNU General Public License | ||
version 2 (see file GNU-GPL). | ||
--------------------------------------------------------------------- | ||
|
||
Shofar font family is Copyright 2011-2012 by Yoram Gnat ([email protected]) | ||
Latin glyphs and punctuation Copyright (URW)++,Copyright 1999 by (URW)++ Design | ||
& Development; | ||
Hebrew Cantillation marks GSUB and GPOS OpenType positioning rules copyright | ||
(c) 2010 by Yoram Gnat ([email protected]) | ||
Inspired by the Hebrew OpenType Layout logic copyright (c) 2003 & 2007, | ||
Ralph Hancock & John Hudson published under the MIT License. | ||
As a special exception, if you create a document which uses this font, and | ||
embed this font or unaltered portions of this font into the document, this | ||
font does not by itself cause the resulting document to be covered by the | ||
GNU General Public License. This exception does not however invalidate any | ||
other reasons why the document might be covered by the GNU General Public | ||
License. If you modify this font, you may extend this exception to your | ||
version of the font, but you are not obligated to do so. If you do not wish | ||
to do so, delete this exception statement from your version. | ||
|
||
Keter YG font family is Copyright 2009 by Yoram Gnat ([email protected]) | ||
Hebrew OpenType Layout logic copyright (c) 2003 & 2007, Ralph Hancock & | ||
John Hudson. This layout logic for Biblical Hebrew is open source software | ||
under the MIT License; for details contact copyright holders | ||
at <[email protected]>. | ||
As a special exception, if you create a document which uses this font, and | ||
embed this font or unaltered portions of this font into the document, this | ||
font does not by itself cause the resulting document to be covered by the | ||
GNU General Public License. This exception does not however invalidate any | ||
other reasons why the document might be covered by the GNU General Public | ||
License. If you modify this font, you may extend this exception to your | ||
version of the font, but you are not obligated to do so. If you do not wish | ||
to do so, delete this exception statement from your version. | ||
|
||
Hadasim font family is copyright 2010 by Yoram Gnat ([email protected]). | ||
Latin and parts of general punctuation marks based on modified forms from | ||
the LiberationSerif font, created by Digitized data 2007 Ascender | ||
Corporation. All rights reserved. | ||
As a special exception, if you create a document which uses this font, and | ||
embed this font or unaltered portions of this font into the document, this | ||
font does not by itself cause the resulting document to be covered by the | ||
GNU General Public License. This exception does not however invalidate any | ||
other reasons why the document might be covered by the GNU General Public | ||
License. If you modify this font, you may extend this exception to your | ||
version of the font, but you are not obligated to do so. If you do not wish | ||
to do so, delete this exception statement from your version. | ||
|
||
Simple font family is copyright 2007-2010 by Yoram Gnat | ||
([email protected]). Latin glyphs, digits and punctuation copyright 1999 | ||
by (URW)++ Design & Development. All rights reserved. | ||
Hebrew vowel marks positioning algorithms Copyright 2010 by Yoram Gnat 2010. | ||
([email protected]. | ||
As a special exception, if you create a document which uses this font, and | ||
embed this font or unaltered portions of this font into the document, this | ||
font does not by itself cause the resulting document to be covered by the | ||
GNU General Public License. This exception does not however invalidate any | ||
other reasons why the document might be covered by the GNU General Public | ||
License. If you modify this font, you may extend this exception to your | ||
version of the font, but you are not obligated to do so. If you do not wish | ||
to do so, delete this exception statement from your version. | ||
|
||
Stam Ashkenaz font is copyright 2007-2010 by Yoram Gnat ([email protected]). | ||
As a special exception, if you create a document which uses this font, and | ||
embed this font or unaltered portions of this font into the document, this | ||
font does not by itself cause the resulting document to be covered by the | ||
GNU General Public License. This exception does not however invalidate any | ||
other reasons why the document might be covered by the GNU General Public | ||
License. If you modify this font, you may extend this exception to your | ||
version of the font, but you are not obligated to do so. If you do not wish | ||
to do so, delete this exception statement from your version. | ||
|
||
Stam Sefarad font is copyright 2008-2010 by Yoram Gnat ([email protected]). | ||
As a special exception, if you create a document which uses this font, and | ||
embed this font or unaltered portions of this font into the document, this | ||
font does not by itself cause the resulting document to be covered by the | ||
GNU General Public License. This exception does not however invalidate any | ||
other reasons why the document might be covered by the GNU General Public | ||
License. If you modify this font, you may extend this exception to your | ||
version of the font, but you are not obligated to do so. If you do not wish | ||
to do so, delete this exception statement from your version. | ||
|
||
Miriam font family is copyright 2004-2010 by Maxim Iorsh | ||
([email protected]). All rights reserved. | ||
|
||
Yehuda font family is copyright 2004 by Maxim Iorsh | ||
([email protected]). All rights reserved. | ||
|
||
Drugulin font family (Hebrew glyphs) is copyright 2003,2004 by Maxim Iorsh | ||
([email protected]). Latin glyphs, digits and punctuation | ||
contained in the Drugulin font family are part of Nimbus Roman No9 L font | ||
family and are copyright 1999 by (URW)++ Design & Development. | ||
All rights reserved. | ||
|
||
Ellinia font family is copyright 2003,2004 by Maxim Iorsh | ||
([email protected]). All rights reserved. | ||
|
||
Caladings collection is copyright 2003,2004 by Maxim Iorsh | ||
([email protected]). All rights reserved. | ||
|
||
Digital version of Aharoni font family (Hebrew glyphs, numerals and part | ||
of punctuation) is copyright 2002-2004 by Maxim Iorsh | ||
([email protected]). Latin glyphs, digits and part of punctuation | ||
contained in the Aharoni font family are part of URW Gothic L font family | ||
and are copyright 1999 by (URW)++ Design & Development. | ||
All rights reserved. | ||
|
||
Digital version of David font family (Hebrew glyphs, numerals and part of | ||
punctuation) is copyright 2002-2017 by Maxim Iorsh | ||
([email protected]). Latin glyphs and part of punctuation | ||
contained in the David font family are part of Bitstream Charter font | ||
family and are copyright 1990 as an unpublished work by Bitstream Inc. All | ||
rights reserved. See also file LICENSE-BITSTREAM. | ||
|
||
Frank-Ruehl font family (Hebrew glyphs) is copyright 2002-2011 by Maxim | ||
Iorsh ([email protected]). Latin glyphs, digits and punctuation | ||
contained in the Frank-Ruehl font family are part of Century Schoolbook L | ||
font family and are copyright 1999 by (URW)++ Design & Development. All | ||
rights reserved. | ||
|
||
Nachlieli font family (Hebrew glyphs) is copyright 2002-2017 by Maxim | ||
Iorsh ([email protected]). Latin glyphs, digits and punctuation | ||
contained in the Nachlieli font family are part of Nimbus Sans L font | ||
family and are copyright 1999 by (URW)++ Design & Development. All | ||
rights reserved. | ||
|
||
Miriam Mono font family (Hebrew glyphs) is copyright 2002-2004 by Maxim | ||
Iorsh ([email protected]). Hebrew vowel marks positioning algorithms | ||
implementation by Yoram Gnat ([email protected]), 2010. | ||
Latin glyphs, digits and punctuation contained in the Miriam Mono font | ||
family are part of Nimbus Mono L font family and are copyright 1999 by | ||
(URW)++ Design & Development. All rights reserved. |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,144 @@ | ||
use std::path::PathBuf; | ||
|
||
use cosmic_text::{ | ||
fontdb::Database, Attrs, Buffer, Color, Family, FontSystem, Metrics, Shaping, SwashCache, | ||
}; | ||
use tiny_skia::{Paint, Pixmap, Rect, Transform}; | ||
|
||
/// The test configuration. | ||
/// The text in the test will be rendered as image using the font specified. The font will be | ||
/// loaded from the `fonts` directory in this repository. | ||
/// The image will then be compared to an image with the name `name` under the `tests/images` | ||
/// directory in this repository. | ||
/// If the images do not match the test will fail. | ||
/// NOTE: if an environment file `GENERATE_IMAGES` is set, the test will create and save | ||
/// the images instead. | ||
#[derive(Debug)] | ||
pub struct DrawTestCfg { | ||
/// The name of the test. | ||
/// Will be used for the image name under the `tests/images` directory in this repository. | ||
name: String, | ||
/// The name of the font file to be used. | ||
/// Expected to be found under the `fonts` directory in this repository. | ||
font_file_name: String, | ||
text: String, | ||
font_size: f32, | ||
line_height: f32, | ||
canvas_width: u32, | ||
canvas_height: u32, | ||
} | ||
|
||
impl Default for DrawTestCfg { | ||
fn default() -> Self { | ||
Self { | ||
name: "default".into(), | ||
font_file_name: "FiraMono-Medium.ttf".into(), | ||
text: "".into(), | ||
font_size: 16.0, | ||
line_height: 20.0, | ||
canvas_width: 300, | ||
canvas_height: 300, | ||
} | ||
} | ||
} | ||
|
||
impl DrawTestCfg { | ||
pub fn new( | ||
name: impl Into<String>, | ||
font_file_name: impl Into<String>, | ||
text: impl Into<String>, | ||
) -> Self { | ||
Self { | ||
name: name.into(), | ||
font_file_name: font_file_name.into(), | ||
text: text.into(), | ||
..Default::default() | ||
} | ||
} | ||
|
||
pub fn font_size(mut self, font_size: f32, line_height: f32) -> Self { | ||
self.font_size = font_size; | ||
self.line_height = line_height; | ||
self | ||
} | ||
|
||
pub fn canvas(mut self, width: u32, height: u32) -> Self { | ||
self.canvas_width = width; | ||
self.canvas_height = height; | ||
self | ||
} | ||
|
||
pub fn validate_text_rendering(self) { | ||
let repo_dir = std::env::var("CARGO_MANIFEST_DIR").unwrap(); | ||
// Create a db with just this font to make sure we either test it or fail | ||
let font_path = PathBuf::from(&repo_dir) | ||
.join("fonts") | ||
.join(&self.font_file_name); | ||
let mut font_db = Database::new(); | ||
font_db.load_font_file(font_path).unwrap(); | ||
// Get the font config so we can choose it later for the buffer | ||
let font_face = font_db.faces().next().unwrap(); | ||
let (family, lang) = font_face.families[0].clone(); | ||
let attrs = Attrs::new() | ||
.family(Family::Name(&family)) | ||
.weight(font_face.weight) | ||
.style(font_face.style) | ||
.stretch(font_face.stretch); | ||
let mut font_system = FontSystem::new_with_locale_and_db(lang.to_string(), font_db); | ||
|
||
let mut swash_cache = SwashCache::new(); | ||
let metrics = Metrics::new(self.font_size, self.line_height); | ||
let mut buffer = Buffer::new(&mut font_system, metrics); | ||
let mut buffer = buffer.borrow_with(&mut font_system); | ||
let margins = 5; | ||
buffer.set_size( | ||
(self.canvas_width - margins * 2) as f32, | ||
(self.canvas_height - margins * 2) as f32, | ||
); | ||
buffer.set_text(&self.text, attrs, Shaping::Advanced); | ||
buffer.shape_until_scroll(); | ||
|
||
// Black | ||
let text_color = Color::rgb(0x00, 0x00, 0x00); | ||
|
||
let mut pixmap = Pixmap::new(self.canvas_width, self.canvas_height).unwrap(); | ||
pixmap.fill(tiny_skia::Color::WHITE); | ||
|
||
buffer.draw(&mut swash_cache, text_color, |x, y, w, h, color| { | ||
let mut paint = Paint::default(); | ||
paint.set_color_rgba8(color.r(), color.g(), color.b(), color.a()); | ||
let rect = Rect::from_xywh( | ||
(x + margins as i32) as f32, | ||
(y + margins as i32) as f32, | ||
w as f32, | ||
h as f32, | ||
) | ||
.unwrap(); | ||
pixmap.fill_rect(rect, &paint, Transform::identity(), None); | ||
}); | ||
|
||
let image_name = format!("{}.png", self.name); | ||
let reference_image_path = PathBuf::from(&repo_dir) | ||
.join("tests") | ||
.join("images") | ||
.join(image_name); | ||
|
||
let generate_images = std::env::var("GENERATE_IMAGES") | ||
.map(|v| { | ||
let val = v.trim().to_ascii_lowercase(); | ||
["t", "true", "1"].iter().any(|&v| v == val) | ||
}) | ||
.unwrap_or_default(); | ||
|
||
if generate_images { | ||
pixmap.save_png(reference_image_path).unwrap(); | ||
} else { | ||
let reference_image_data = std::fs::read(reference_image_path).unwrap(); | ||
let image_data = pixmap.encode_png().unwrap(); | ||
assert_eq!( | ||
reference_image_data, image_data, | ||
"rendering failed of {self:?}" | ||
) | ||
} | ||
} | ||
} |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
use common::DrawTestCfg; | ||
|
||
mod common; | ||
|
||
#[test] | ||
fn test_hebrew_word_rendering() { | ||
DrawTestCfg::new("a_hebrew_word", "FrankRuehlCLM-Medium.ttf", "בדיקה") | ||
.font_size(24., 26.) | ||
.canvas(70, 40) | ||
.validate_text_rendering(); | ||
} | ||
|
||
#[test] | ||
fn test_hebrew_paragraph_rendering() { | ||
let paragraph = "השועל החום המהיר קופץ מעל הכלב העצלן"; | ||
DrawTestCfg::new("a_hebrew_paragraph", "FrankRuehlCLM-Medium.ttf", paragraph) | ||
.font_size(36., 40.) | ||
.canvas(400, 110) | ||
.validate_text_rendering(); | ||
} | ||
|
||
#[test] | ||
fn test_english_mixed_with_hebrew_paragraph_rendering() { | ||
let paragraph = "Many computer programs fail to display bidirectional text correctly. For example, this page is mostly LTR English script, and here is the RTL Hebrew name Sarah: שרה, spelled sin (ש) on the right, resh (ר) in the middle, and heh (ה) on the left."; | ||
DrawTestCfg::new( | ||
"some_english_mixed_with_hebrew", | ||
"FrankRuehlCLM-Medium.ttf", | ||
paragraph, | ||
) | ||
.font_size(16., 20.) | ||
.canvas(400, 120) | ||
.validate_text_rendering(); | ||
} |