freetype: add script to create more hinting tests.

R=bsiegert, r
CC=golang-dev
https://codereview.appspot.com/14414044
This commit is contained in:
Nigel Tao 2013-10-09 20:07:32 +11:00
parent b968fb0953
commit b76427be47
4 changed files with 146 additions and 52 deletions

View File

@ -1,27 +1,47 @@
/*
gcc main.c -I/usr/include/freetype2 -lfreetype && ./a.out
gcc main.c -I/usr/include/freetype2 -lfreetype && ./a.out 12 ../../testdata/luxisr.ttf with_hinting
*/
#include <stdio.h>
#include <ft2build.h>
#include FT_FREETYPE_H
static int font_size = 12;
static int no_hinting = 0;
void usage(char** argv) {
printf("usage: %s font_size font_file [with_hinting|sans_hinting]\n", argv[0]);
}
int main(int argc, char** argv) {
FT_Error error;
FT_Library library;
FT_Face face;
FT_Outline* o;
int i, j;
int i, j, font_size, no_hinting;
if (argc != 4) {
usage(argv);
return 1;
}
font_size = atoi(argv[1]);
if (font_size <= 0) {
printf("invalid font_size\n");
usage(argv);
return 1;
}
if (!strcmp(argv[3], "with_hinting")) {
no_hinting = 0;
} else if (!strcmp(argv[3], "sans_hinting")) {
no_hinting = 1;
} else {
printf("neither \"with_hinting\" nor \"sans_hinting\"\n");
usage(argv);
return 1;
};
error = FT_Init_FreeType(&library);
if (error) {
printf("FT_Init_FreeType: error #%d\n", error);
return 1;
}
error = FT_New_Face(library, "../../testdata/luxisr.ttf", 0, &face);
error = FT_New_Face(library, argv[2], 0, &face);
if (error) {
printf("FT_New_Face: error #%d\n", error);
return 1;
@ -50,4 +70,5 @@ int main(int argc, char** argv) {
}
printf("\n");
}
return 0;
}

View File

@ -74,63 +74,106 @@ func TestParse(t *testing.T) {
}
}
func testScaling(t *testing.T, filename string, hinter *Hinter) {
b, err := ioutil.ReadFile("../../testdata/luxisr.ttf")
if err != nil {
t.Fatalf("ReadFile: %v", err)
}
font, err := Parse(b)
if err != nil {
t.Fatalf("Parse: %v", err)
}
f, err := os.Open("../../testdata/" + filename)
if err != nil {
t.Fatalf("Open: %v", err)
}
defer f.Close()
var scalingTestCases = []struct {
name string
size int32
// hintingBrokenAt, if non-negative, is the glyph index n for which
// only the first n glyphs are known to be correctly hinted.
// TODO: remove this field, when hinting is completely implemented.
hintingBrokenAt int
}{
{"luxisr", 12, -1},
// TODO: uncomment the fonts below, once they get past Parse and
// GlyphBuf.Load, and the unhinted values match C Freetype.
//{"x-arial-bold", 11, 0},
//{"x-deja-vu-sans-oblique", 17, 0},
//{"x-droid-sans-japanese", 9, 0},
//{"x-inconsolata", 10, 0},
//{"x-times-new-roman", 13, 0},
}
wants := [][]Point{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
text := scanner.Text()
if text == "" {
wants = append(wants, []Point{})
continue
}
ss := strings.Split(text, ",")
points := make([]Point, len(ss))
for i, s := range ss {
p := &points[i]
if _, err := fmt.Sscanf(s, "%d %d %d", &p.X, &p.Y, &p.Flags); err != nil {
t.Fatalf("Sscanf: %v", err)
func testScaling(t *testing.T, hinter *Hinter) {
loop:
for _, tc := range scalingTestCases {
b, err := ioutil.ReadFile(fmt.Sprintf("../../testdata/%s.ttf", tc.name))
if err != nil {
// The "x-foo" fonts are optional tests, as they are not checked
// in for copyright or file size reasons.
if strings.HasPrefix(tc.name, "x-") {
t.Logf("%s: ReadFile: %v", tc.name, err)
} else {
t.Errorf("%s: ReadFile: %v", tc.name, err)
}
continue loop
}
wants = append(wants, points)
}
if err := scanner.Err(); err != nil && err != io.EOF {
t.Fatalf("Scanner: %v", err)
}
font, err := Parse(b)
if err != nil {
t.Errorf("%s: Parse: %v", tc.name, err)
continue loop
}
hinting := "sans"
if hinter != nil {
hinting = "with"
}
f, err := os.Open(fmt.Sprintf(
"../../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hinting))
if err != nil {
t.Errorf("%s: Open: %v", tc.name, err)
continue loop
}
defer f.Close()
const fontSize = 12
glyphBuf := NewGlyphBuf()
for i, want := range wants {
if err = glyphBuf.Load(font, fontSize*64, Index(i), hinter); err != nil {
t.Fatalf("Load: %v", err)
wants := [][]Point{}
scanner := bufio.NewScanner(f)
for scanner.Scan() {
text := scanner.Text()
if text == "" {
wants = append(wants, []Point{})
continue
}
ss := strings.Split(text, ",")
points := make([]Point, len(ss))
for i, s := range ss {
p := &points[i]
if _, err := fmt.Sscanf(s, "%d %d %d", &p.X, &p.Y, &p.Flags); err != nil {
t.Errorf("%s: Sscanf: %v", tc.name, err)
continue loop
}
}
wants = append(wants, points)
}
got := glyphBuf.Point
for i := range got {
got[i].Flags &= 0x01
if err := scanner.Err(); err != nil && err != io.EOF {
t.Errorf("%s: Scanner: %v", tc.name, err)
continue loop
}
if !reflect.DeepEqual(got, want) {
t.Errorf("glyph #%d:\ngot %v\nwant %v\n", i, got, want)
glyphBuf := NewGlyphBuf()
for i, want := range wants {
// TODO: completely implement hinting. For now, only the first
// tc.hintingBrokenAt glyphs of the test case's font are correctly hinted.
if hinter != nil && i == tc.hintingBrokenAt {
break
}
if err = glyphBuf.Load(font, tc.size*64, Index(i), hinter); err != nil {
t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err)
continue loop
}
got := glyphBuf.Point
for i := range got {
got[i].Flags &= 0x01
}
if !reflect.DeepEqual(got, want) {
t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\n", tc.name, i, got, want)
}
}
}
}
func TestScalingSansHinting(t *testing.T) {
testScaling(t, "luxisr-12pt-sans-hinting.txt", nil)
testScaling(t, nil)
}
func TestScalingWithHinting(t *testing.T) {
testScaling(t, "luxisr-12pt-with-hinting.txt", &Hinter{})
testScaling(t, &Hinter{})
}

4
testdata/README vendored
View File

@ -1,8 +1,8 @@
The *.ttf and COPYING files in this directory were copied from the X.org
The luxi*.ttf and COPYING files in this directory were copied from the X.org
project, specifically
http://xorg.freedesktop.org/releases/individual/font/font-bh-ttf-1.0.0.tar.bz2
There are three fonts: sans (s), serif (r) and monospaced (m). For example,
There are three Luxi fonts: sans (s), serif (r) and monospaced (m). For example,
luxisr.ttf is Luxi Sans. The 'r' here means regular, as opposed to bold.
The *.ttx files in this directory were generated from the *.ttf files

30
testdata/make-other-hinting-txts.sh vendored Executable file
View File

@ -0,0 +1,30 @@
#!/usr/bin/env bash
#
# This script creates the optional x-*-hinting.txt files from fonts that are
# not checked in for copyright or file size reasons.
#
# Run it from this directory (testdata).
#
# It has only been tested on an Ubuntu 12.04 system.
set -e
: ${FONTDIR:=/usr/share/fonts/truetype}
ln -sf $FONTDIR/droid/DroidSansJapanese.ttf x-droid-sans-japanese.ttf
ln -sf $FONTDIR/msttcorefonts/Arial_Bold.ttf x-arial-bold.ttf
ln -sf $FONTDIR/msttcorefonts/Times_New_Roman.ttf x-times-new-roman.ttf
ln -sf $FONTDIR/ttf-dejavu/DejaVuSans-Oblique.ttf x-deja-vu-sans-oblique.ttf
${CC:=gcc} ../cmd/print-glyph-points/main.c $(pkg-config --cflags --libs freetype2) -o print-glyph-points
./print-glyph-points 9 x-droid-sans-japanese.ttf sans_hinting > x-droid-sans-japanese-9pt-sans-hinting.txt
./print-glyph-points 9 x-droid-sans-japanese.ttf with_hinting > x-droid-sans-japanese-9pt-with-hinting.txt
./print-glyph-points 11 x-arial-bold.ttf sans_hinting > x-arial-bold-11pt-sans-hinting.txt
./print-glyph-points 11 x-arial-bold.ttf with_hinting > x-arial-bold-11pt-with-hinting.txt
./print-glyph-points 13 x-times-new-roman.ttf sans_hinting > x-times-new-roman-13pt-sans-hinting.txt
./print-glyph-points 13 x-times-new-roman.ttf with_hinting > x-times-new-roman-13pt-with-hinting.txt
./print-glyph-points 17 x-deja-vu-sans-oblique.ttf sans_hinting > x-deja-vu-sans-oblique-17pt-sans-hinting.txt
./print-glyph-points 17 x-deja-vu-sans-oblique.ttf with_hinting > x-deja-vu-sans-oblique-17pt-with-hinting.txt
rm print-glyph-points