diff --git a/freetype/truetype/hint.go b/freetype/truetype/hint.go index 2afaab0..86647c3 100644 --- a/freetype/truetype/hint.go +++ b/freetype/truetype/hint.go @@ -627,6 +627,33 @@ func (h *Hinter) run(program []byte, pCurrent, pUnhinted, pInFontUnits []Point, case opRCVT: h.stack[top-1] = int32(h.getScaledCVT(h.stack[top-1])) + case opGC0, opGC1: + i := h.stack[top-1] + if opcode == opGC0 { + p := h.point(2, current, i) + h.stack[top-1] = int32(dotProduct(f26dot6(p.X), f26dot6(p.Y), h.gs.pv)) + } else { + p := h.point(2, unhinted, i) + // Using dv as per C Freetype. + h.stack[top-1] = int32(dotProduct(f26dot6(p.X), f26dot6(p.Y), h.gs.dv)) + } + + 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)) + } 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)) + } + case opMPPEM, opMPS: if top >= len(h.stack) { return errors.New("truetype: hinting: stack overflow") diff --git a/freetype/truetype/opcodes.go b/freetype/truetype/opcodes.go index e6b9e70..94b5220 100644 --- a/freetype/truetype/opcodes.go +++ b/freetype/truetype/opcodes.go @@ -80,11 +80,11 @@ const ( opRS = 0x43 // Read Store opWCVTP = 0x44 // Write Control Value Table in Pixel units opRCVT = 0x45 // Read Control Value Table entry - opGC0 = 0x46 - opGC1 = 0x47 + opGC0 = 0x46 // Get Coordinate projected onto the projection vector + opGC1 = 0x47 // . opSCFS = 0x48 - opMD0 = 0x49 - opMD1 = 0x4a + opMD0 = 0x49 // Measure Distance + opMD1 = 0x4a // . opMPPEM = 0x4b // Measure Pixels Per EM opMPS = 0x4c // Measure Point Size opFLIPON = 0x4d // set the auto FLIP Boolean to ON @@ -275,7 +275,7 @@ 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, q, q, q, q, 1, 1, 1, 0, q, q, 0, 0, 2, 2, // 0x30 - 0x3f - 0, 0, 2, 1, 2, 1, q, q, q, q, q, 0, 0, 0, 0, 0, // 0x40 - 0x4f + 0, 0, 2, 1, 2, 1, 1, 1, q, 2, 2, 0, 0, 0, 0, 0, // 0x40 - 0x4f 2, 2, 2, 2, 2, 2, 1, 1, 1, 0, 2, 2, 1, q, 1, 1, // 0x50 - 0x5f 2, 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0x60 - 0x6f q, q, q, q, q, q, 1, 1, 2, 2, 0, q, 0, 0, 1, 1, // 0x70 - 0x7f