From 4c33bd09f5bece0cbc1e5f8c763e161e03202b02 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Wed, 4 Dec 2013 10:04:19 +1100 Subject: [PATCH] freetype/truetype: implement SCFS, FLIPPT, FLIPRGON, FLIPRGOFF opcodes. R=bsiegert CC=golang-dev, remyoudompheng https://codereview.appspot.com/36300043 --- freetype/truetype/hint.go | 48 ++++++++++++++++++++++++++++++ freetype/truetype/opcodes.go | 12 ++++---- freetype/truetype/truetype_test.go | 4 +-- 3 files changed, 56 insertions(+), 8 deletions(-) diff --git a/freetype/truetype/hint.go b/freetype/truetype/hint.go index 53ef444..193c157 100644 --- a/freetype/truetype/hint.go +++ b/freetype/truetype/hint.go @@ -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-- diff --git a/freetype/truetype/opcodes.go b/freetype/truetype/opcodes.go index cfe3b32..d5e9bdc 100644 --- a/freetype/truetype/opcodes.go +++ b/freetype/truetype/opcodes.go @@ -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 diff --git a/freetype/truetype/truetype_test.go b/freetype/truetype/truetype_test.go index 4f07eba..9e425ae 100644 --- a/freetype/truetype/truetype_test.go +++ b/freetype/truetype/truetype_test.go @@ -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.