freetype/truetype: implement SCFS, FLIPPT, FLIPRGON, FLIPRGOFF opcodes.

R=bsiegert
CC=golang-dev, remyoudompheng
https://codereview.appspot.com/36300043
This commit is contained in:
Nigel Tao 2013-12-04 10:04:19 +11:00
parent 25cb1e119f
commit 4c33bd09f5
3 changed files with 56 additions and 8 deletions

View File

@ -754,6 +754,25 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
h.stack[top-1] = int32(dotProduct(f26dot6(p.X), f26dot6(p.Y), h.gs.dv))
}
case opSCFS:
top -= 2
i := h.stack[top]
p := h.point(2, current, i)
if p == nil {
return errors.New("truetype: hinting: point out of range")
}
c := dotProduct(f26dot6(p.X), f26dot6(p.Y), h.gs.pv)
h.move(p, f26dot6(h.stack[top+1])-c, true)
if h.gs.zp[2] != 0 {
break
}
q := h.point(2, unhinted, i)
if q == nil {
return errors.New("truetype: hinting: point out of range")
}
q.X = p.X
q.Y = p.Y
case opMD0, opMD1:
top--
i, j := h.stack[top-1], h.stack[top]
@ -960,6 +979,35 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point,
// These ops are "anachronistic" and no longer used.
top--
case opFLIPPT:
if top < int(h.gs.loop) {
return errors.New("truetype: hinting: stack underflow")
}
points := h.points[glyphZone][current]
for ; h.gs.loop != 0; h.gs.loop-- {
top--
i := h.stack[top]
if i < 0 || len(points) <= int(i) {
return errors.New("truetype: hinting: point out of range")
}
points[i].Flags ^= flagOnCurve
}
h.gs.loop = 1
case opFLIPRGON, opFLIPRGOFF:
top -= 2
i, j, points := h.stack[top], h.stack[top+1], h.points[glyphZone][current]
if i < 0 || len(points) <= int(i) || j < 0 || len(points) <= int(j) {
return errors.New("truetype: hinting: point out of range")
}
for ; i <= j; i++ {
if opcode == opFLIPRGON {
points[i].Flags |= flagOnCurve
} else {
points[i].Flags &^= flagOnCurve
}
}
case opSCANCTRL:
// We do not support dropout control, as we always rasterize grayscale glyphs.
top--

View File

@ -82,7 +82,7 @@ const (
opRCVT = 0x45 // Read Control Value Table entry
opGC0 = 0x46 // Get Coordinate projected onto the projection vector
opGC1 = 0x47 // .
opSCFS = 0x48
opSCFS = 0x48 // Sets Coordinate From the Stack using projection vector and freedom vector
opMD0 = 0x49 // Measure Distance
opMD1 = 0x4a // .
opMPPEM = 0x4b // Measure Pixels Per EM
@ -138,9 +138,9 @@ const (
opRDTG = 0x7d // Round Down To Grid
opSANGW = 0x7e // Set ANGle Weight
opAA = 0x7f // Adjust Angle
opFLIPPT = 0x80
opFLIPRGON = 0x81
opFLIPRGOFF = 0x82
opFLIPPT = 0x80 // FLIP PoinT
opFLIPRGON = 0x81 // FLIP RanGe ON
opFLIPRGOFF = 0x82 // FLIP RanGe OFF
op_0x83 = 0x83
op_0x84 = 0x84
opSCANCTRL = 0x85 // SCAN conversion ConTRoL
@ -275,11 +275,11 @@ var popCount = [256]uint8{
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, // 0x10 - 0x1f
1, 1, 0, 2, 0, 1, 1, q, q, q, 2, 1, 1, 0, 1, 1, // 0x20 - 0x2f
0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 2, 2, 0, 0, 2, 2, // 0x30 - 0x3f
0, 0, 2, 1, 2, 1, 1, 1, q, 2, 2, 0, 0, 0, 0, 0, // 0x40 - 0x4f
0, 0, 2, 1, 2, 1, 1, 1, 2, 2, 2, 0, 0, 0, 0, 0, // 0x40 - 0x4f
2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 2, 2, 1, 1, 1, 1, // 0x50 - 0x5f
2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6f
2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 0, q, 0, 0, 1, 1, // 0x70 - 0x7f
q, q, q, q, q, 1, 2, 2, 1, 1, 3, 2, 2, 1, q, q, // 0x80 - 0x8f
0, 2, 2, q, q, 1, 2, 2, 1, 1, 3, 2, 2, 1, q, q, // 0x80 - 0x8f
q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, // 0x90 - 0x9f
q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, // 0xa0 - 0xaf
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0xb0 - 0xbf

View File

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