freetype/truetype: jump opcodes.
R=gri, bsiegert CC=golang-dev http://codereview.appspot.com/6344079
This commit is contained in:
parent
523d04e0a7
commit
e843d5cf7c
3 changed files with 78 additions and 20 deletions
|
@ -25,7 +25,7 @@ func (h *hinter) run(program []byte) error {
|
|||
steps, pc, top int
|
||||
opcode uint8
|
||||
)
|
||||
for int(pc) < len(program) {
|
||||
for 0 <= pc && int(pc) < len(program) {
|
||||
steps++
|
||||
if steps == 100000 {
|
||||
return errors.New("truetype: hinting: too many steps")
|
||||
|
@ -43,6 +43,11 @@ func (h *hinter) run(program []byte) error {
|
|||
opcode = 1
|
||||
goto ifelse
|
||||
|
||||
case opJMPR:
|
||||
top--
|
||||
pc += int(h.stack[top])
|
||||
continue
|
||||
|
||||
case opDUP:
|
||||
if int(top) >= len(h.stack) {
|
||||
return errors.New("truetype: hinting: stack overflow")
|
||||
|
@ -89,36 +94,36 @@ func (h *hinter) run(program []byte) error {
|
|||
// No-op.
|
||||
|
||||
case opLT:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] < h.stack[top-1])
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] < h.stack[top])
|
||||
|
||||
case opLTEQ:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] <= h.stack[top-1])
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] <= h.stack[top])
|
||||
|
||||
case opGT:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] > h.stack[top-1])
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] > h.stack[top])
|
||||
|
||||
case opGTEQ:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] >= h.stack[top-1])
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] >= h.stack[top])
|
||||
|
||||
case opEQ:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] == h.stack[top-1])
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] == h.stack[top])
|
||||
|
||||
case opNEQ:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] != h.stack[top-1])
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] != h.stack[top])
|
||||
|
||||
case opAND:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2] != 0 && h.stack[top-1] != 0)
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] != 0 && h.stack[top] != 0)
|
||||
|
||||
case opOR:
|
||||
h.stack[top-2] = bool2int32(h.stack[top-2]|h.stack[top-1] != 0)
|
||||
top--
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1]|h.stack[top] != 0)
|
||||
|
||||
case opNOT:
|
||||
h.stack[top-1] = bool2int32(h.stack[top-1] == 0)
|
||||
|
@ -134,23 +139,23 @@ func (h *hinter) run(program []byte) error {
|
|||
// No-op.
|
||||
|
||||
case opADD:
|
||||
h.stack[top-2] += h.stack[top-1]
|
||||
top--
|
||||
h.stack[top-1] += h.stack[top]
|
||||
|
||||
case opSUB:
|
||||
h.stack[top-2] -= h.stack[top-1]
|
||||
top--
|
||||
h.stack[top-1] -= h.stack[top]
|
||||
|
||||
case opDIV:
|
||||
if h.stack[top-1] == 0 {
|
||||
top--
|
||||
if h.stack[top] == 0 {
|
||||
return errors.New("truetype: hinting: division by zero")
|
||||
}
|
||||
h.stack[top-2] = int32((int64(h.stack[top-2]) << 6) / int64(h.stack[top-1]))
|
||||
top--
|
||||
h.stack[top-1] = int32((int64(h.stack[top-1]) << 6) / int64(h.stack[top]))
|
||||
|
||||
case opMUL:
|
||||
h.stack[top-2] = int32((int64(h.stack[top-2]) * int64(h.stack[top-1])) >> 6)
|
||||
top--
|
||||
h.stack[top-1] = int32((int64(h.stack[top-1]) * int64(h.stack[top])) >> 6)
|
||||
|
||||
case opABS:
|
||||
if h.stack[top-1] < 0 {
|
||||
|
@ -167,6 +172,20 @@ func (h *hinter) run(program []byte) error {
|
|||
h.stack[top-1] += 63
|
||||
h.stack[top-1] &^= 63
|
||||
|
||||
case opJROT:
|
||||
top -= 2
|
||||
if h.stack[top+1] != 0 {
|
||||
pc += int(h.stack[top])
|
||||
continue
|
||||
}
|
||||
|
||||
case opJROF:
|
||||
top -= 2
|
||||
if h.stack[top+1] == 0 {
|
||||
pc += int(h.stack[top])
|
||||
continue
|
||||
}
|
||||
|
||||
case opPUSHB000, opPUSHB001, opPUSHB010, opPUSHB011, opPUSHB100, opPUSHB101, opPUSHB110, opPUSHB111:
|
||||
opcode -= opPUSHB000 - 1
|
||||
goto push
|
||||
|
|
|
@ -26,6 +26,18 @@ func TestBytecode(t *testing.T) {
|
|||
nil,
|
||||
"underflow",
|
||||
},
|
||||
{
|
||||
"infinite loop",
|
||||
[]byte{
|
||||
opPUSHW000, // [-1]
|
||||
0xff,
|
||||
0xff,
|
||||
opDUP, // [-1, -1]
|
||||
opJMPR, // [-1]
|
||||
},
|
||||
nil,
|
||||
"too many steps",
|
||||
},
|
||||
{
|
||||
"unbalanced if/else",
|
||||
[]byte{
|
||||
|
@ -36,6 +48,33 @@ func TestBytecode(t *testing.T) {
|
|||
nil,
|
||||
"unbalanced",
|
||||
},
|
||||
{
|
||||
"jumps",
|
||||
[]byte{
|
||||
opPUSHB001, // [10, 2]
|
||||
10,
|
||||
2,
|
||||
opJMPR, // [10]
|
||||
opDUP, // not executed
|
||||
opDUP, // [10, 10]
|
||||
opPUSHB010, // [10, 10, 20, 2, 1]
|
||||
20,
|
||||
2,
|
||||
1,
|
||||
opJROT, // [10, 10, 20]
|
||||
opDUP, // not executed
|
||||
opDUP, // [10, 10, 20, 20]
|
||||
opPUSHB010, // [10, 10, 20, 20, 30, 2, 1]
|
||||
30,
|
||||
2,
|
||||
1,
|
||||
opJROF, // [10, 10, 20, 20, 30]
|
||||
opDUP, // [10, 10, 20, 20, 30, 30]
|
||||
opDUP, // [10, 10, 20, 20, 30, 30, 30]
|
||||
},
|
||||
[]int32{10, 10, 20, 20, 30, 30, 30},
|
||||
"",
|
||||
},
|
||||
{
|
||||
"stack ops",
|
||||
[]byte{
|
||||
|
|
|
@ -38,7 +38,7 @@ const (
|
|||
opRTHG = 0x19
|
||||
opSMD = 0x1a
|
||||
opELSE = 0x1b // ELSE clause
|
||||
opJMPR = 0x1c
|
||||
opJMPR = 0x1c // JuMP Relative
|
||||
opSCVTCI = 0x1d
|
||||
opSSWCI = 0x1e
|
||||
opSSW = 0x1f
|
||||
|
@ -130,8 +130,8 @@ const (
|
|||
opDELTAC3 = 0x75
|
||||
opSROUND = 0x76
|
||||
opS45ROUND = 0x77
|
||||
opJROT = 0x78
|
||||
opJROF = 0x79
|
||||
opJROT = 0x78 // Jump Relative On True
|
||||
opJROF = 0x79 // Jump Relative On False
|
||||
opROFF = 0x7a
|
||||
op_0x7b = 0x7b
|
||||
opRUTG = 0x7c
|
||||
|
@ -272,13 +272,13 @@ const (
|
|||
var popCount = [256]uint8{
|
||||
// 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f
|
||||
q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, // 0x00 - 0x0f
|
||||
q, q, q, q, q, q, q, q, q, q, q, 0, q, q, q, q, // 0x10 - 0x1f
|
||||
q, q, q, q, q, q, q, q, q, q, q, 0, 1, q, q, q, // 0x10 - 0x1f
|
||||
1, 1, 0, 2, 0, 1, 1, q, q, q, q, q, q, q, q, q, // 0x20 - 0x2f
|
||||
q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, // 0x30 - 0x3f
|
||||
0, 0, q, q, q, q, q, q, q, q, q, q, q, q, q, 0, // 0x40 - 0x4f
|
||||
2, 2, 2, 2, 2, 2, q, q, 1, 0, 2, 2, 1, q, q, q, // 0x50 - 0x5f
|
||||
2, 2, 2, 2, 1, 1, 1, 1, q, q, q, q, q, q, q, q, // 0x60 - 0x6f
|
||||
q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, q, // 0x70 - 0x7f
|
||||
q, q, q, q, q, q, q, q, 2, 2, q, q, q, q, q, q, // 0x70 - 0x7f
|
||||
q, q, q, q, q, q, q, q, q, q, q, q, q, q, 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
|
||||
|
|
Loading…
Reference in a new issue