freetype/truetype: fix Super45 rounding.

R=bsiegert
CC=golang-dev, remyoudompheng
https://codereview.appspot.com/34790045
This commit is contained in:
Nigel Tao 2013-11-30 15:19:12 +11:00
parent 1f97ea5d8e
commit 5cb0a99dcd
2 changed files with 27 additions and 6 deletions

View File

@ -81,6 +81,7 @@ type graphicsState struct {
loop int32 loop int32
// Rounding policy. // Rounding policy.
roundPeriod, roundPhase, roundThreshold f26dot6 roundPeriod, roundPhase, roundThreshold f26dot6
roundSuper45 bool
// Auto-flip. // Auto-flip.
autoFlip bool autoFlip bool
} }
@ -97,6 +98,7 @@ var globalDefaultGS = graphicsState{
loop: 1, loop: 1,
roundPeriod: 1 << 6, // 1 as an f26dot6. roundPeriod: 1 << 6, // 1 as an f26dot6.
roundThreshold: 1 << 5, // 1/2 as an f26dot6. roundThreshold: 1 << 5, // 1/2 as an f26dot6.
roundSuper45: false,
autoFlip: true, autoFlip: true,
} }
@ -350,11 +352,13 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
h.gs.roundPeriod = 1 << 6 h.gs.roundPeriod = 1 << 6
h.gs.roundPhase = 0 h.gs.roundPhase = 0
h.gs.roundThreshold = 1 << 5 h.gs.roundThreshold = 1 << 5
h.gs.roundSuper45 = false
case opRTHG: case opRTHG:
h.gs.roundPeriod = 1 << 6 h.gs.roundPeriod = 1 << 6
h.gs.roundPhase = 1 << 5 h.gs.roundPhase = 1 << 5
h.gs.roundThreshold = 1 << 5 h.gs.roundThreshold = 1 << 5
h.gs.roundSuper45 = false
case opSMD: case opSMD:
top-- top--
@ -683,6 +687,7 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
h.gs.roundPeriod = 1 << 5 h.gs.roundPeriod = 1 << 5
h.gs.roundPhase = 0 h.gs.roundPhase = 0
h.gs.roundThreshold = 1 << 4 h.gs.roundThreshold = 1 << 4
h.gs.roundSuper45 = false
case opMIAP0, opMIAP1: case opMIAP0, opMIAP1:
top -= 2 top -= 2
@ -905,7 +910,8 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
case 2: case 2:
h.gs.roundPeriod = 1 << 7 h.gs.roundPeriod = 1 << 7
} }
if opcode == opS45ROUND { h.gs.roundSuper45 = opcode == opS45ROUND
if h.gs.roundSuper45 {
// The spec says to multiply by √2, but the C Freetype code says 1/√2. // The spec says to multiply by √2, but the C Freetype code says 1/√2.
// We go with 1/√2. // We go with 1/√2.
h.gs.roundPeriod *= 46341 h.gs.roundPeriod *= 46341
@ -936,16 +942,19 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
h.gs.roundPeriod = 0 h.gs.roundPeriod = 0
h.gs.roundPhase = 0 h.gs.roundPhase = 0
h.gs.roundThreshold = 0 h.gs.roundThreshold = 0
h.gs.roundSuper45 = false
case opRUTG: case opRUTG:
h.gs.roundPeriod = 1 << 6 h.gs.roundPeriod = 1 << 6
h.gs.roundPhase = 0 h.gs.roundPhase = 0
h.gs.roundThreshold = 1<<6 - 1 h.gs.roundThreshold = 1<<6 - 1
h.gs.roundSuper45 = false
case opRDTG: case opRDTG:
h.gs.roundPeriod = 1 << 6 h.gs.roundPeriod = 1 << 6
h.gs.roundPhase = 0 h.gs.roundPhase = 0
h.gs.roundThreshold = 0 h.gs.roundThreshold = 0
h.gs.roundSuper45 = false
case opSANGW, opAA: case opSANGW, opAA:
// These ops are "anachronistic" and no longer used. // These ops are "anachronistic" and no longer used.
@ -1686,17 +1695,29 @@ func (h *Hinter) round(x f26dot6) f26dot6 {
return x return x
} }
if x >= 0 { if x >= 0 {
ret := (x - h.gs.roundPhase + h.gs.roundThreshold) & -h.gs.roundPeriod ret := x - h.gs.roundPhase + h.gs.roundThreshold
if h.gs.roundSuper45 {
ret /= h.gs.roundPeriod
ret *= h.gs.roundPeriod
} else {
ret &= -h.gs.roundPeriod
}
if x != 0 && ret < 0 { if x != 0 && ret < 0 {
ret = 0 ret = 0
} }
return ret + h.gs.roundPhase return ret + h.gs.roundPhase
} }
ret := -((-x - h.gs.roundPhase + h.gs.roundThreshold) & -h.gs.roundPeriod) ret := -x - h.gs.roundPhase + h.gs.roundThreshold
if ret > 0 { if h.gs.roundSuper45 {
ret /= h.gs.roundPeriod
ret *= h.gs.roundPeriod
} else {
ret &= -h.gs.roundPeriod
}
if ret < 0 {
ret = 0 ret = 0
} }
return ret - h.gs.roundPhase return -ret - h.gs.roundPhase
} }
func bool2int32(b bool) int32 { func bool2int32(b bool) int32 {

View File

@ -255,7 +255,7 @@ var scalingTestCases = []struct {
hintingBrokenAt int hintingBrokenAt int
}{ }{
{"luxisr", 12, -1}, {"luxisr", 12, -1},
{"x-arial-bold", 11, 238}, {"x-arial-bold", 11, 274},
{"x-deja-vu-sans-oblique", 17, -1}, {"x-deja-vu-sans-oblique", 17, -1},
{"x-droid-sans-japanese", 9, 0}, {"x-droid-sans-japanese", 9, 0},
{"x-times-new-roman", 13, 0}, {"x-times-new-roman", 13, 0},