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 <stdio.h>
#include <ft2build.h> #include <ft2build.h>
#include FT_FREETYPE_H #include FT_FREETYPE_H
static int font_size = 12; void usage(char** argv) {
static int no_hinting = 0; printf("usage: %s font_size font_file [with_hinting|sans_hinting]\n", argv[0]);
}
int main(int argc, char** argv) { int main(int argc, char** argv) {
FT_Error error; FT_Error error;
FT_Library library; FT_Library library;
FT_Face face; FT_Face face;
FT_Outline* o; 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); error = FT_Init_FreeType(&library);
if (error) { if (error) {
printf("FT_Init_FreeType: error #%d\n", error); printf("FT_Init_FreeType: error #%d\n", error);
return 1; return 1;
} }
error = FT_New_Face(library, "../../testdata/luxisr.ttf", 0, &face); error = FT_New_Face(library, argv[2], 0, &face);
if (error) { if (error) {
printf("FT_New_Face: error #%d\n", error); printf("FT_New_Face: error #%d\n", error);
return 1; return 1;
@ -50,4 +70,5 @@ int main(int argc, char** argv) {
} }
printf("\n"); printf("\n");
} }
return 0;
} }

View File

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