Commit ca893ada authored by Alex Butler's avatar Alex Butler

Add benchmark regression tests & gitlab-ci

parent 0dc1174e
image: "rust:latest"
stages:
- build
- test
before_script:
- rustup toolchain add $toolchain
variables:
CARGO_HOME: $CI_PROJECT_DIR/cargo
cache:
paths:
- target/
- cargo/
build:stable:
stage: build
variables:
toolchain: stable
script:
- cargo +stable build -v
test:stable:
stage: test
variables:
toolchain: stable
dependencies:
- build:stable
script:
- cargo +stable test -v
build:nightly:
stage: build
variables:
toolchain: nightly
script:
- cargo +nightly build -v
test:nightly:
stage: test
variables:
toolchain: nightly
dependencies:
- build:nightly
script:
- cargo +nightly test -v
test:benches:
stage: test
variables:
toolchain: nightly
dependencies:
- build:nightly
script:
- cargo +nightly test --bench api
build:redox:
stage: build
variables:
toolchain: nightly
script:
- rustup target add x86_64-unknown-redox --toolchain nightly
- cargo +nightly build --target=x86_64-unknown-redox -v
language: rust
after_success: |
[ $TRAVIS_BRANCH = master ] &&
[ $TRAVIS_PULL_REQUEST = false ] &&
cargo doc &&
echo "<meta http-equiv=refresh content=0;url=`echo stb_truetype | cut -d '/' -f 2`/index.html>" > target/doc/index.html &&
git clone https://github.com/davisp/ghp-import &&
./ghp-import/ghp-import target/doc &&
git push -fq https://${GH_TOKEN}@github.com/${TRAVIS_REPO_SLUG}.git gh-pages
env:
global:
secure: jyWEYm20gpM7XwS1fHOD9j8AavuknXlym1omFe5cfTH2E1r1DGzRzWg2mAWOF+7SxnXlqSJYwATyik0DEOsEALaItVbHAGV1Iz8lUXKMdPWxuHQBVbDJI7sgSTUGV8VumpchbwMep/dDhFHymCSK0VfaZvmB+8I5DDMF9D2u7uZ+Kdd1svnzpIEqwbF9KOaizwIxF0Sj8MdACRXAd7h1U4jmI8wDiEtrdDHq+B8GbVh3+7iFpy4ItZDhAMczknu3Ho7arTeQT4QWY7+akHWjZHzFnDUr/mUfsDpD8sEGVtAyTeK1UXj/fImZl3ZTfsiNBYufrtYSsX7OditMZZIT4v/0dP6WrF1w70ttjAT+YHg34RnuyszkT+j9uzOxFKrLRn50x9yFwcL86O0p8QJd/noRRK03vFJSEREpoldVEE4e1wvmmcc9We/5fWC5HKxsX8Kk0P1ENbKKGJviPKyleyS1jgxtD9u2gLeQ3PUo8aJBggt0BVqjqTdE73U3SJ9SK+/BuQU7EfZgph9sJopU4l4Ky72D3aa9pPMM87BgRjIntEOHQ2ECE5n9WdwWiKhl+6q190DK9eszG0CrmP5htzm1dMmFv8ejuHHPbrDE4hL7QCx+DIm2BR7VAQ+Q/L3RrRyrOxgUSXXxoNUAEVEcGABjW4uzxiIkLMExD+J1fJU=
......@@ -8,6 +8,10 @@ repository = "https://gitlab.redox-os.org/redox-os/stb_truetype-rs"
readme = "README.md"
license = "MIT / Apache-2.0"
keywords = ["font", "truetype", "opentype", "ttf", "otf"]
exclude = ["/fonts/**"]
[dependencies]
byteorder = "1.0"
[dev-dependencies]
approx = { version = "0.3", default-features = false }
#![feature(test)]
extern crate stb_truetype;
extern crate test;
#[macro_use]
extern crate approx;
use stb_truetype::*;
/// index map format 12
static DEJA_VU_MONO: &[u8] = include_bytes!("../fonts/DejaVuSansMono.ttf");
/// index map format 4
static GUDEA: &[u8] = include_bytes!("../fonts/Gudea-Regular.ttf");
const ALPHABET_SIZE: usize = 62;
const ALPHABET: &[char; ALPHABET_SIZE] = &[
'A', 'a', 'B', 'b', 'C', 'c', 'D', 'd', 'E', 'e', 'F', 'f', 'G', 'g', 'H', 'h', 'I', 'i', 'J',
'j', 'K', 'k', 'L', 'l', 'M', 'm', 'N', 'n', 'O', 'o', 'P', 'p', 'Q', 'q', 'R', 'r', 'S', 's',
'T', 't', 'U', 'u', 'V', 'v', 'W', 'w', 'X', 'x', 'W', 'w', 'Z', 'z', '0', '1', '2', '3', '4',
'5', '6', '7', '8', '9',
];
#[bench]
fn find_glyph_index_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let mut indices = [0_u32; ALPHABET_SIZE];
b.iter(|| {
for (i, c) in ALPHABET.iter().enumerate() {
indices[i] = font.find_glyph_index(*c as u32);
}
});
assert_eq!(
indices.to_vec(),
vec![
36, 68, 37, 69, 38, 70, 39, 71, 40, 72, 41, 73, 42, 74, 43, 75, 44, 76, 45, 77, 46, 78,
47, 79, 48, 80, 49, 81, 50, 82, 51, 83, 52, 84, 53, 85, 54, 86, 55, 87, 56, 88, 57, 89,
58, 90, 59, 91, 58, 90, 61, 93, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28
]
);
}
#[bench]
fn find_glyph_index_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let mut indices = [0_u32; ALPHABET_SIZE];
b.iter(|| {
for (i, c) in ALPHABET.iter().enumerate() {
indices[i] = font.find_glyph_index(*c as u32);
}
});
assert_eq!(
indices.to_vec(),
vec![
37, 69, 38, 70, 39, 71, 40, 72, 41, 73, 42, 74, 43, 75, 44, 76, 45, 77, 46, 78, 47, 79,
48, 80, 49, 81, 50, 82, 51, 83, 52, 84, 53, 85, 54, 86, 55, 87, 56, 88, 57, 89, 58, 90,
59, 91, 60, 92, 59, 91, 62, 94, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29
]
);
}
/// (x0, x1, y0, y1)
fn rect_to_tuple<T>(r: Rect<T>) -> (T, T, T, T) {
(r.x0, r.x1, r.y0, r.y1)
}
#[bench]
fn get_glyph_box_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let mut boxes = [None; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
boxes[i] = font.get_glyph_box(*glyph_index);
}
});
assert_eq!(rect_to_tuple(boxes[11].unwrap()), (195, 1063, 0, 1556));
assert_eq!(rect_to_tuple(boxes[34].unwrap()), (143, 1233, 0, 1493));
assert_eq!(rect_to_tuple(boxes[57].unwrap()), (143, 1069, -29, 1493));
}
#[bench]
fn get_glyph_box_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let mut boxes = [None; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
boxes[i] = font.get_glyph_box(*glyph_index);
}
});
assert_eq!(rect_to_tuple(boxes[11].unwrap()), (35, 316, 0, 710));
assert_eq!(rect_to_tuple(boxes[34].unwrap()), (91, 571, 1, 701));
assert_eq!(rect_to_tuple(boxes[57].unwrap()), (63, 504, -6, 700));
}
#[bench]
fn get_glyph_bitmap_box_subpixel_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let (s_x, s_y) = (12.0, 14.5);
let scale_y = font.scale_for_pixel_height(s_y);
let scale_x = scale_y * s_x / s_y;
let mut boxes = [None; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
boxes[i] =
font.get_glyph_bitmap_box_subpixel(*glyph_index, scale_x, scale_y, 656.0, 1034.0);
}
});
assert_eq!(rect_to_tuple(boxes[11].unwrap()), (656, 662, 1024, 1034));
assert_eq!(rect_to_tuple(boxes[34].unwrap()), (656, 663, 1024, 1034));
assert_eq!(rect_to_tuple(boxes[57].unwrap()), (656, 662, 1024, 1035));
}
#[bench]
fn get_glyph_bitmap_box_subpixel_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let (s_x, s_y) = (12.0, 14.5);
let scale_y = font.scale_for_pixel_height(s_y);
let scale_x = scale_y * s_x / s_y;
let mut boxes = [None; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
boxes[i] =
font.get_glyph_bitmap_box_subpixel(*glyph_index, scale_x, scale_y, 656.0, 1034.0);
}
});
assert_eq!(rect_to_tuple(boxes[11].unwrap()), (656, 660, 1025, 1034));
assert_eq!(rect_to_tuple(boxes[34].unwrap()), (656, 662, 1025, 1034));
assert_eq!(rect_to_tuple(boxes[57].unwrap()), (656, 661, 1025, 1035));
}
/// (x, y, cx, cy, type)
fn vertex_to_tuple(vert: Vertex) -> (i16, i16, i16, i16, u8) {
(vert.x, vert.y, vert.cx, vert.cy, vert.vertex_type() as u8)
}
#[bench]
fn get_glyph_shape_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let mut shapes = vec![None; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
shapes[i] = font.get_glyph_shape(*glyph_index);
}
});
let shapes_11: Vec<_> = shapes[11]
.as_ref()
.unwrap()
.iter()
.map(|v| vertex_to_tuple(*v))
.collect();
assert_eq!(
shapes_11,
vec![
(1063, 1556, 0, 0, 1),
(1063, 1403, 0, 0, 2),
(854, 1403, 0, 0, 2),
(716, 1362, 755, 1403, 3),
(678, 1219, 678, 1322, 3),
(678, 1120, 0, 0, 2),
(1063, 1120, 0, 0, 2),
(1063, 977, 0, 0, 2),
(678, 977, 0, 0, 2),
(678, 0, 0, 0, 2),
(494, 0, 0, 0, 2),
(494, 977, 0, 0, 2),
(195, 977, 0, 0, 2),
(195, 1120, 0, 0, 2),
(494, 1120, 0, 0, 2),
(494, 1198, 0, 0, 2),
(578, 1469, 494, 1382, 3),
(842, 1556, 663, 1556, 3),
(1063, 1556, 0, 0, 2)
]
);
let shapes_47: Vec<_> = shapes[47]
.as_ref()
.unwrap()
.iter()
.map(|v| vertex_to_tuple(*v))
.collect();
assert_eq!(
shapes_47,
vec![
(1118, 1120, 0, 0, 1),
(717, 584, 0, 0, 2),
(1157, 0, 0, 0, 2),
(944, 0, 0, 0, 2),
(616, 449, 0, 0, 2),
(289, 0, 0, 0, 2),
(76, 0, 0, 0, 2),
(516, 584, 0, 0, 2),
(115, 1120, 0, 0, 2),
(319, 1120, 0, 0, 2),
(616, 715, 0, 0, 2),
(911, 1120, 0, 0, 2),
(1118, 1120, 0, 0, 2)
]
);
}
#[bench]
fn get_glyph_shape_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let mut shapes = vec![None; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
shapes[i] = font.get_glyph_shape(*glyph_index);
}
});
let shapes_11: Vec<_> = shapes[11]
.as_ref()
.unwrap()
.iter()
.map(|v| vertex_to_tuple(*v))
.collect();
assert_eq!(
shapes_11,
vec![
(113, 500, 0, 0, 1),
(113, 596, 0, 0, 2),
(150, 683, 113, 657, 3),
(231, 710, 188, 710, 3),
(316, 697, 275, 710, 3),
(305, 643, 0, 0, 2),
(256, 649, 272, 649, 3),
(187, 582, 187, 649, 3),
(187, 500, 0, 0, 2),
(289, 500, 0, 0, 2),
(289, 440, 0, 0, 2),
(187, 440, 0, 0, 2),
(187, 0, 0, 0, 2),
(112, 0, 0, 0, 2),
(112, 440, 0, 0, 2),
(35, 440, 0, 0, 2),
(35, 500, 0, 0, 2),
(113, 500, 0, 0, 2)
]
);
let shapes_47: Vec<_> = shapes[47]
.as_ref()
.unwrap()
.iter()
.map(|v| vertex_to_tuple(*v))
.collect();
assert_eq!(
shapes_47,
vec![
(113, 501, 0, 0, 1),
(218, 324, 0, 0, 2),
(323, 501, 0, 0, 2),
(406, 501, 0, 0, 2),
(259, 255, 0, 0, 2),
(412, 0, 0, 0, 2),
(329, 0, 0, 0, 2),
(218, 198, 0, 0, 2),
(107, 0, 0, 0, 2),
(24, 0, 0, 0, 2),
(177, 255, 0, 0, 2),
(30, 501, 0, 0, 2),
(113, 501, 0, 0, 2)
]
);
}
/// (advance_width, left_side_bearing)
fn h_metrics_to_tuple(h: HMetrics) -> (i32, i32) {
(h.advance_width, h.left_side_bearing)
}
#[bench]
fn get_glyph_h_metrics_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let mut h_metrics = [HMetrics {
advance_width: 0,
left_side_bearing: 0,
}; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
h_metrics[i] = font.get_glyph_h_metrics(*glyph_index);
}
});
assert_eq!(h_metrics_to_tuple(h_metrics[11]), (1233, 195));
assert_eq!(h_metrics_to_tuple(h_metrics[25]), (1233, 109));
assert_eq!(h_metrics_to_tuple(h_metrics[49]), (1233, 0));
}
#[bench]
fn get_glyph_h_metrics_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let indices: Vec<_> = ALPHABET
.iter()
.map(|c| font.find_glyph_index(*c as u32))
.collect();
let mut h_metrics = [HMetrics {
advance_width: 0,
left_side_bearing: 0,
}; ALPHABET_SIZE];
b.iter(|| {
for (i, glyph_index) in indices.iter().enumerate() {
h_metrics[i] = font.get_glyph_h_metrics(*glyph_index);
}
});
assert_eq!(h_metrics_to_tuple(h_metrics[11]), (291, 35));
assert_eq!(h_metrics_to_tuple(h_metrics[25]), (850, 91));
assert_eq!(h_metrics_to_tuple(h_metrics[49]), (679, 11));
}
#[bench]
fn scale_for_pixel_height_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let pixel_heights: [f32; 8] = [1.0, 12.0, 14.5, 25.5, 50.0, 112.2, 500.5, 657.5];
let mut scales = [0.0; 8];
b.iter(|| {
// repeat so its a similar number of calls to the other benchmarks
for _ in 0..test::black_box(8) {
for (i, pixel_height) in pixel_heights.iter().enumerate() {
scales[i] = font.scale_for_pixel_height(*pixel_height);
}
}
});
assert_relative_eq!(scales[0], 0.000_419_463_1);
assert_relative_eq!(scales[1], 0.005_033_557);
assert_relative_eq!(scales[2], 0.006_082_215);
assert_relative_eq!(scales[3], 0.010_696_309);
assert_relative_eq!(scales[4], 0.020_973_155);
assert_relative_eq!(scales[5], 0.047_063_757);
assert_relative_eq!(scales[6], 0.209_941_27);
assert_relative_eq!(scales[7], 0.275_796_98);
}
#[bench]
fn scale_for_pixel_height_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let pixel_heights: [f32; 8] = [1.0, 12.0, 14.5, 25.5, 50.0, 112.2, 500.5, 657.5];
let mut scales = [0.0; 8];
b.iter(|| {
// repeat so its a similar number of calls to the other benchmarks
for _ in 0..test::black_box(8) {
for (i, pixel_height) in pixel_heights.iter().enumerate() {
scales[i] = font.scale_for_pixel_height(*pixel_height);
}
}
});
assert_relative_eq!(scales[0], 0.000_809_061_5);
assert_relative_eq!(scales[1], 0.009_708_738);
assert_relative_eq!(scales[2], 0.011_731_392);
assert_relative_eq!(scales[3], 0.020_631_067);
assert_relative_eq!(scales[4], 0.040_453_073);
assert_relative_eq!(scales[5], 0.090_776_7);
assert_relative_eq!(scales[6], 0.404_935_27);
assert_relative_eq!(scales[7], 0.531_957_9);
}
#[bench]
fn get_v_metrics_deja_vu_mono(b: &mut test::Bencher) {
let font = FontInfo::new(&*DEJA_VU_MONO, 0).unwrap();
let mut v_metrics = VMetrics { ascent: 1, descent: 2, line_gap: 3 };
b.iter(|| {
// repeat so its a similar number of calls to the other benchmarks
for _ in 0..test::black_box(ALPHABET_SIZE) {
v_metrics = font.get_v_metrics();
}
});
let VMetrics { ascent, descent, line_gap } = v_metrics;
assert_eq!(ascent, 1901);
assert_eq!(descent, -483);
assert_eq!(line_gap, 0);
}
#[bench]
fn get_v_metrics_gudea(b: &mut test::Bencher) {
let font = FontInfo::new(&*GUDEA, 0).unwrap();
let mut v_metrics = VMetrics { ascent: 1, descent: 2, line_gap: 3 };
b.iter(|| {
// repeat so its a similar number of calls to the other benchmarks
for _ in 0..test::black_box(ALPHABET_SIZE) {
v_metrics = font.get_v_metrics();
}
});
let VMetrics { ascent, descent, line_gap } = v_metrics;
assert_eq!(ascent, 972);
assert_eq!(descent, -264);
assert_eq!(line_gap, 0);
}
......@@ -3,7 +3,7 @@ extern crate stb_truetype;
use stb_truetype::FontInfo;
use std::borrow::Cow;
fn main() {
let file = &include_bytes!("Gudea-Regular.ttf")[..];
let file = &include_bytes!("../fonts/Gudea-Regular.ttf")[..];
let font = FontInfo::new(Cow::Borrowed(file), 0).unwrap();
for info in font.get_font_name_strings() {
......
......@@ -3,7 +3,7 @@ extern crate stb_truetype;
use stb_truetype::FontInfo;
use std::borrow::Cow;
fn main() {
let file = include_bytes!("Gudea-Regular.ttf") as &[u8];
let file = include_bytes!("../fonts/Gudea-Regular.ttf") as &[u8];
let font = FontInfo::new(Cow::Borrowed(file), 0).unwrap();
let vmetrics = font.get_v_metrics();
println!("{:?}", vmetrics);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment