freetype: fix MDRP/MIRP Set-RP0 bit and fix normalize rounding.
Also make phantom point delta-X adjustment. Also make print-glyph-points require Freetype version >= 2.5, which is the latest version, at the time of writing. R=bsiegert CC=golang-dev, remyoudompheng https://codereview.appspot.com/18370043
This commit is contained in:
parent
ab80f5823d
commit
e849ac9382
|
@ -7,7 +7,7 @@ gcc main.c -I/usr/include/freetype2 -lfreetype && ./a.out 12 ../../testdata/luxi
|
|||
#include FT_FREETYPE_H
|
||||
|
||||
void usage(char** argv) {
|
||||
printf("usage: %s font_size font_file [with_hinting|sans_hinting]\n", argv[0]);
|
||||
fprintf(stderr, "usage: %s font_size font_file [with_hinting|sans_hinting]\n", argv[0]);
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
@ -15,6 +15,7 @@ int main(int argc, char** argv) {
|
|||
FT_Library library;
|
||||
FT_Face face;
|
||||
FT_Outline* o;
|
||||
FT_Int major, minor, patch;
|
||||
int i, j, font_size, no_hinting;
|
||||
|
||||
if (argc != 4) {
|
||||
|
@ -23,7 +24,7 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
font_size = atoi(argv[1]);
|
||||
if (font_size <= 0) {
|
||||
printf("invalid font_size\n");
|
||||
fprintf(stderr, "invalid font_size\n");
|
||||
usage(argv);
|
||||
return 1;
|
||||
}
|
||||
|
@ -32,33 +33,40 @@ int main(int argc, char** argv) {
|
|||
} else if (!strcmp(argv[3], "sans_hinting")) {
|
||||
no_hinting = 1;
|
||||
} else {
|
||||
printf("neither \"with_hinting\" nor \"sans_hinting\"\n");
|
||||
fprintf(stderr, "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);
|
||||
fprintf(stderr, "FT_Init_FreeType: error #%d\n", error);
|
||||
return 1;
|
||||
}
|
||||
FT_Library_Version(library, &major, &minor, &patch);
|
||||
if ((major < 2) || ((major == 2) && (minor < 5))) {
|
||||
fprintf(stderr, "%s needs freetype version >= 2.5.\n"
|
||||
"Try setting LD_LIBRARY_PATH=/path/to/freetype_built_from_src/objs/.libs/\n",
|
||||
argv[0]);
|
||||
return 1;
|
||||
}
|
||||
error = FT_New_Face(library, argv[2], 0, &face);
|
||||
if (error) {
|
||||
printf("FT_New_Face: error #%d\n", error);
|
||||
fprintf(stderr, "FT_New_Face: error #%d\n", error);
|
||||
return 1;
|
||||
}
|
||||
error = FT_Set_Char_Size(face, 0, font_size*64, 0, 0);
|
||||
if (error) {
|
||||
printf("FT_Set_Char_Size: error #%d\n", error);
|
||||
fprintf(stderr, "FT_Set_Char_Size: error #%d\n", error);
|
||||
return 1;
|
||||
}
|
||||
for (i = 0; i < face->num_glyphs; i++) {
|
||||
error = FT_Load_Glyph(face, i, no_hinting ? FT_LOAD_NO_HINTING : FT_LOAD_DEFAULT);
|
||||
if (error) {
|
||||
printf("FT_Load_Glyph: glyph %d: error #%d\n", i, error);
|
||||
fprintf(stderr, "FT_Load_Glyph: glyph %d: error #%d\n", i, error);
|
||||
return 1;
|
||||
}
|
||||
if (face->glyph->format != FT_GLYPH_FORMAT_OUTLINE) {
|
||||
printf("glyph format for glyph %d is not FT_GLYPH_FORMAT_OUTLINE\n", i);
|
||||
fprintf(stderr, "glyph format for glyph %d is not FT_GLYPH_FORMAT_OUTLINE\n", i);
|
||||
return 1;
|
||||
}
|
||||
o = &face->glyph->outline;
|
||||
|
|
|
@ -171,6 +171,11 @@ func (g *GlyphBuf) load(recursion int32, i Index, useMyMetrics bool) (err error)
|
|||
if g.hinter != nil {
|
||||
g.InFontUnits = g.InFontUnits[:len(g.InFontUnits)-4]
|
||||
g.Unhinted = g.Unhinted[:len(g.Unhinted)-4]
|
||||
if dx := ((pp1x + 32) &^ 63) - pp1x; dx != 0 {
|
||||
for i := np0; i < len(g.Point); i++ {
|
||||
g.Point[i].X += dx
|
||||
}
|
||||
}
|
||||
}
|
||||
if np0 != 0 {
|
||||
// The hinting program expects the []End values to be indexed relative
|
||||
|
|
|
@ -989,11 +989,11 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
|
|||
}
|
||||
|
||||
// Set-RP0 bit.
|
||||
h.gs.rp[1] = h.gs.rp[0]
|
||||
h.gs.rp[2] = i
|
||||
if opcode&0x10 != 0 {
|
||||
h.gs.rp[0] = i
|
||||
}
|
||||
h.gs.rp[1] = h.gs.rp[0]
|
||||
h.gs.rp[2] = i
|
||||
|
||||
// Move the point.
|
||||
oldDist = dotProduct(f26dot6(p.X-ref.X), f26dot6(p.Y-ref.Y), h.gs.pv)
|
||||
|
@ -1068,11 +1068,11 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
|
|||
}
|
||||
|
||||
// Set-RP0 bit.
|
||||
h.gs.rp[1] = h.gs.rp[0]
|
||||
h.gs.rp[2] = i
|
||||
if opcode&0x10 != 0 {
|
||||
h.gs.rp[0] = i
|
||||
}
|
||||
h.gs.rp[1] = h.gs.rp[0]
|
||||
h.gs.rp[2] = i
|
||||
|
||||
// Move the point.
|
||||
h.move(p, distance-curDist, true)
|
||||
|
@ -1438,13 +1438,20 @@ type f2dot14 int16
|
|||
|
||||
func normalize(x, y f2dot14) [2]f2dot14 {
|
||||
fx, fy := float64(x), float64(y)
|
||||
l := math.Hypot(fx, fy)
|
||||
fx /= l
|
||||
fy /= l
|
||||
return [2]f2dot14{
|
||||
f2dot14(fx * 0x4000),
|
||||
f2dot14(fy * 0x4000),
|
||||
l := 0x4000 / math.Hypot(fx, fy)
|
||||
fx *= l
|
||||
if fx >= 0 {
|
||||
fx += 0.5
|
||||
} else {
|
||||
fx -= 0.5
|
||||
}
|
||||
fy *= l
|
||||
if fy >= 0 {
|
||||
fy += 0.5
|
||||
} else {
|
||||
fy -= 0.5
|
||||
}
|
||||
return [2]f2dot14{f2dot14(fx), f2dot14(fy)}
|
||||
}
|
||||
|
||||
// f26dot6 is a 26.6 fixed point number.
|
||||
|
|
|
@ -583,6 +583,8 @@ func TestBytecode(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
// TestMove tests that the Hinter.move method matches the output of the C
|
||||
// Freetype implementation.
|
||||
func TestMove(t *testing.T) {
|
||||
h, p := Hinter{}, Point{}
|
||||
testCases := []struct {
|
||||
|
@ -642,3 +644,30 @@ func TestMove(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TestNormalize tests that the normalize function matches the output of the C
|
||||
// Freetype implementation.
|
||||
func TestNormalize(t *testing.T) {
|
||||
testCases := [][2]f2dot14{
|
||||
{-15895, 3974},
|
||||
{-15543, 5181},
|
||||
{-14654, 7327},
|
||||
{-11585, 11585},
|
||||
{0, 16384},
|
||||
{11585, 11585},
|
||||
{14654, 7327},
|
||||
{15543, 5181},
|
||||
{15895, 3974},
|
||||
{16066, 3213},
|
||||
{16161, 2694},
|
||||
{16219, 2317},
|
||||
{16257, 2032},
|
||||
{16284, 1809},
|
||||
}
|
||||
for i, want := range testCases {
|
||||
got := normalize(f2dot14(i)-4, 1)
|
||||
if got != want {
|
||||
t.Errorf("i=%d: got %v, want %v", i, got, want)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -253,7 +253,7 @@ var scalingTestCases = []struct {
|
|||
}{
|
||||
{"luxisr", 12, -1},
|
||||
{"x-arial-bold", 11, 0},
|
||||
{"x-deja-vu-sans-oblique", 17, 14},
|
||||
{"x-deja-vu-sans-oblique", 17, 229},
|
||||
{"x-droid-sans-japanese", 9, 0},
|
||||
{"x-times-new-roman", 13, 0},
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user