freetype/truetype: fix rounding for negative numbers to match the C

Freetype implementation.

The spec is the "Order of rounding operations" part of
https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding
but it wasn't exactly clear to me what "the negative round value
closest to zero" was: if the phase is 1/4, was that value -1/4 or
-3/4? Anyway, the Go code now follows the C code, and code trumps
documentation.

R=bsiegert
CC=golang-dev
https://codereview.appspot.com/14092044
This commit is contained in:
Nigel Tao 2013-09-29 18:30:55 +10:00
parent c661e372c6
commit 3490800cec
3 changed files with 27 additions and 33 deletions

View file

@ -1237,27 +1237,21 @@ func dotProduct(x, y f26dot6, q [2]f2dot14) f26dot6 {
// https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding
func (h *Hinter) round(x f26dot6) f26dot6 {
if h.gs.roundPeriod == 0 {
// Rounding is off.
return x
}
neg := x < 0
x -= h.gs.roundPhase
x += h.gs.roundThreshold
if x >= 0 {
x = (x / h.gs.roundPeriod) * h.gs.roundPeriod
} else {
x -= h.gs.roundPeriod
x += 1
x = (x / h.gs.roundPeriod) * h.gs.roundPeriod
}
x += h.gs.roundPhase
if neg {
if x >= 0 {
x = h.gs.roundPhase - h.gs.roundPeriod
ret := (x - h.gs.roundPhase + h.gs.roundThreshold) & -h.gs.roundPeriod
if x != 0 && ret < 0 {
ret = 0
}
} else if x < 0 {
x = h.gs.roundPhase
return ret + h.gs.roundPhase
}
return x
ret := -((-x - h.gs.roundPhase + h.gs.roundThreshold) & -h.gs.roundPeriod)
if ret > 0 {
ret = 0
}
return ret - h.gs.roundPhase
}
func bool2int32(b bool) int32 {

View file

@ -445,33 +445,33 @@ func TestBytecode(t *testing.T) {
opPUSHW000, // [-81]
0xff,
0xaf,
opROUND00, // [-112]
opPUSHW000, // [-112, -80]
opROUND00, // [-80]
opPUSHW000, // [-80, -80]
0xff,
0xb0,
opROUND00, // [-112, -48]
opPUSHW000, // [-112, -48, -17]
opROUND00, // [-80, -80]
opPUSHW000, // [-80, -80, -17]
0xff,
0xef,
opROUND00, // [-112, -48, -48]
opPUSHW000, // [-112, -48, -48, -16]
opROUND00, // [-80, -80, -16]
opPUSHW000, // [-80, -80, -16, -16]
0xff,
0xf0,
opROUND00, // [-112, -48, -48, -48]
opPUSHB000, // [-112, -48, -48, -48, 0]
opROUND00, // [-80, -80, -16, -16]
opPUSHB000, // [-80, -80, -16, -16, 0]
0,
opROUND00, // [-112, -48, -48, -48, 16]
opPUSHB000, // [-112, -48, -48, -48, 16, 16]
opROUND00, // [-80, -80, -16, -16, 16]
opPUSHB000, // [-80, -80, -16, -16, 16, 16]
16,
opROUND00, // [-112, -48, -48, -48, 16, 16]
opPUSHB000, // [-112, -48, -48, -48, 16, 16, 47]
opROUND00, // [-80, -80, -16, -16, 16, 16]
opPUSHB000, // [-80, -80, -16, -16, 16, 16, 47]
47,
opROUND00, // [-112, -48, -48, -48, 16, 16, 16]
opPUSHB000, // [-112, -48, -48, -48, 16, 16, 16, 48]
opROUND00, // [-80, -80, -16, -16, 16, 16, 16]
opPUSHB000, // [-80, -80, -16, -16, 16, 16, 16, 48]
48,
opROUND00, // [-112, -48, -48, -48, 16, 16, 16, 80]
opROUND00, // [-80, -80, -16, -16, 16, 16, 16, 80]
},
[]int32{-112, -48, -48, -48, 16, 16, 16, 80},
[]int32{-80, -80, -16, -16, 16, 16, 16, 80},
"",
},
{

View file

@ -116,7 +116,7 @@ func testScaling(t *testing.T, filename string, hinter *Hinter) {
for i, want := range wants {
// TODO: completely implement hinting. For now, only the first N glyphs
// of luxisr.ttf are correctly hinted.
const N = 8
const N = 9
if hinter != nil && i == N {
break
}