freetype/truetype: fix MD0/MD1 opcodes and f26dot6 multiplication

rounding.

Pass all the hinting tests. Hooray! Removing the hintingBrokenAt field
will be a follow-up CL.

R=bsiegert, remyoudompheng, jeremyjackins
CC=golang-dev
https://codereview.appspot.com/36880043
This commit is contained in:
Nigel Tao 2013-12-05 09:09:03 +11:00
parent 4c33bd09f5
commit f3eade8b5f
2 changed files with 22 additions and 13 deletions

View file

@ -775,19 +775,28 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
case opMD0, opMD1:
top--
i, j := h.stack[top-1], h.stack[top]
if opcode == opMD1 {
p := h.point(0, current, i)
q := h.point(1, current, j)
h.stack[top-1] = int32(dotProduct(f26dot6(p.X-q.X), f26dot6(p.Y-q.Y), h.gs.pv))
pt, v, scale := pointType(0), [2]f2dot14{}, false
if opcode == opMD0 {
pt = current
v = h.gs.pv
} else if h.gs.zp[0] == 0 || h.gs.zp[1] == 0 {
pt = unhinted
v = h.gs.dv
} else {
// TODO: do we need to check (h.gs.zp[0] == 0 || h.gs.zp[1] == 0)
// as C Freetype does, similar to the MDRP instructions?
p := h.point(0, unhinted, i)
q := h.point(1, unhinted, j)
// Use dv for MD0 as in C Freetype.
h.stack[top-1] = int32(dotProduct(f26dot6(p.X-q.X), f26dot6(p.Y-q.Y), h.gs.dv))
pt = inFontUnits
v = h.gs.dv
scale = true
}
p := h.point(0, pt, h.stack[top-1])
q := h.point(1, pt, h.stack[top])
if p == nil || q == nil {
return errors.New("truetype: hinting: point out of range")
}
d := int32(dotProduct(f26dot6(p.X-q.X), f26dot6(p.Y-q.Y), v))
if scale {
d = int32(int64(d*h.scale) / int64(h.font.fUnitsPerEm))
}
h.stack[top-1] = d
case opMPPEM, opMPS:
if top >= len(h.stack) {
@ -1679,7 +1688,7 @@ func (x f26dot6) div(y f26dot6) f26dot6 {
// mul returns x*y in 26.6 fixed point arithmetic.
func (x f26dot6) mul(y f26dot6) f26dot6 {
return f26dot6(int64(x) * int64(y) >> 6)
return f26dot6((int64(x)*int64(y) + 1<<5) >> 6)
}
// dotProduct returns the dot product of [x, y] and q. It is almost the same as

View file

@ -256,7 +256,7 @@ var scalingTestCases = []struct {
{"x-arial-bold", 11, -1},
{"x-deja-vu-sans-oblique", 17, -1},
{"x-droid-sans-japanese", 9, -1},
{"x-times-new-roman", 13, 8},
{"x-times-new-roman", 13, -1},
}
// TODO: also test bounding boxes, not just points.