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 // https://developer.apple.com/fonts/TTRefMan/RM02/Chap2.html#rounding
func (h *Hinter) round(x f26dot6) f26dot6 { func (h *Hinter) round(x f26dot6) f26dot6 {
if h.gs.roundPeriod == 0 { if h.gs.roundPeriod == 0 {
// Rounding is off.
return x return x
} }
neg := x < 0
x -= h.gs.roundPhase
x += h.gs.roundThreshold
if x >= 0 { if x >= 0 {
x = (x / h.gs.roundPeriod) * h.gs.roundPeriod ret := (x - h.gs.roundPhase + h.gs.roundThreshold) & -h.gs.roundPeriod
} else { if x != 0 && ret < 0 {
x -= h.gs.roundPeriod ret = 0
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
} }
} else if x < 0 { return ret + h.gs.roundPhase
x = 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 { func bool2int32(b bool) int32 {

View File

@ -445,33 +445,33 @@ func TestBytecode(t *testing.T) {
opPUSHW000, // [-81] opPUSHW000, // [-81]
0xff, 0xff,
0xaf, 0xaf,
opROUND00, // [-112] opROUND00, // [-80]
opPUSHW000, // [-112, -80] opPUSHW000, // [-80, -80]
0xff, 0xff,
0xb0, 0xb0,
opROUND00, // [-112, -48] opROUND00, // [-80, -80]
opPUSHW000, // [-112, -48, -17] opPUSHW000, // [-80, -80, -17]
0xff, 0xff,
0xef, 0xef,
opROUND00, // [-112, -48, -48] opROUND00, // [-80, -80, -16]
opPUSHW000, // [-112, -48, -48, -16] opPUSHW000, // [-80, -80, -16, -16]
0xff, 0xff,
0xf0, 0xf0,
opROUND00, // [-112, -48, -48, -48] opROUND00, // [-80, -80, -16, -16]
opPUSHB000, // [-112, -48, -48, -48, 0] opPUSHB000, // [-80, -80, -16, -16, 0]
0, 0,
opROUND00, // [-112, -48, -48, -48, 16] opROUND00, // [-80, -80, -16, -16, 16]
opPUSHB000, // [-112, -48, -48, -48, 16, 16] opPUSHB000, // [-80, -80, -16, -16, 16, 16]
16, 16,
opROUND00, // [-112, -48, -48, -48, 16, 16] opROUND00, // [-80, -80, -16, -16, 16, 16]
opPUSHB000, // [-112, -48, -48, -48, 16, 16, 47] opPUSHB000, // [-80, -80, -16, -16, 16, 16, 47]
47, 47,
opROUND00, // [-112, -48, -48, -48, 16, 16, 16] opROUND00, // [-80, -80, -16, -16, 16, 16, 16]
opPUSHB000, // [-112, -48, -48, -48, 16, 16, 16, 48] opPUSHB000, // [-80, -80, -16, -16, 16, 16, 16, 48]
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 { for i, want := range wants {
// TODO: completely implement hinting. For now, only the first N glyphs // TODO: completely implement hinting. For now, only the first N glyphs
// of luxisr.ttf are correctly hinted. // of luxisr.ttf are correctly hinted.
const N = 8 const N = 9
if hinter != nil && i == N { if hinter != nil && i == N {
break break
} }