freetype/truetype: fix Super45 rounding.
R=bsiegert CC=golang-dev, remyoudompheng https://codereview.appspot.com/34790045
This commit is contained in:
parent
1f97ea5d8e
commit
5cb0a99dcd
|
@ -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 {
|
||||||
|
|
|
@ -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},
|
||||||
|
|
Loading…
Reference in New Issue