From 20ce6ab4df55c94eb11404089945af058d8df558 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Wed, 11 Jul 2012 21:49:03 +1000 Subject: [PATCH] freetype/truetype: variable sized bytecode interpreter stack/store. R=bsiegert CC=golang-dev http://codereview.appspot.com/6343091 --- freetype/truetype/hint.go | 19 ++++++++++++++----- freetype/truetype/hint_test.go | 4 ++++ freetype/truetype/truetype.go | 6 ++++++ 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/freetype/truetype/hint.go b/freetype/truetype/hint.go index 6b128dd..4098ee0 100644 --- a/freetype/truetype/hint.go +++ b/freetype/truetype/hint.go @@ -13,11 +13,7 @@ import ( ) type hinter struct { - // TODO: variable sized stack and store slices based on the maxp section? - // Should the arrays for the stack and store be combined? For now, fixed - // maximum sizes seem to work in practice. - stack [800]int32 - store [128]int32 + stack, store []int32 // The fields below constitue the graphics state, which is described at // https://developer.apple.com/fonts/TTRefMan/RM04/Chap4.html @@ -32,6 +28,19 @@ type hinter struct { roundPeriod, roundPhase, roundThreshold f26dot6 } +func (h *hinter) init(f *Font) { + if x := int(f.maxStackElements); x > len(h.stack) { + x += 255 + x &^= 255 + h.stack = make([]int32, x) + } + if x := int(f.maxStorage); x > len(h.store) { + x += 15 + x &^= 15 + h.store = make([]int32, x) + } +} + func (h *hinter) run(program []byte) error { // The default vectors are along the X axis. h.pv = [2]f2dot14{0x4000, 0} diff --git a/freetype/truetype/hint_test.go b/freetype/truetype/hint_test.go index 3c66be3..b8c9d14 100644 --- a/freetype/truetype/hint_test.go +++ b/freetype/truetype/hint_test.go @@ -489,6 +489,10 @@ func TestBytecode(t *testing.T) { for _, tc := range testCases { h := &hinter{} + h.init(&Font{ + maxStorage: 32, + maxStackElements: 100, + }) err, errStr := h.run(tc.prog), "" if err != nil { errStr = err.Error() diff --git a/freetype/truetype/truetype.go b/freetype/truetype/truetype.go index 7e2e564..03dd54c 100644 --- a/freetype/truetype/truetype.go +++ b/freetype/truetype/truetype.go @@ -98,6 +98,8 @@ type Font struct { nGlyph, nHMetric, nKern int unitsPerEm int bounds Bounds + // Values from the maxp section. + maxTwilightPoints, maxStorage, maxFunctionDefs, maxStackElements uint16 } func (f *Font) parseCmap() error { @@ -254,6 +256,10 @@ func (f *Font) parseMaxp() error { return FormatError(fmt.Sprintf("bad maxp length: %d", len(f.maxp))) } f.nGlyph = int(u16(f.maxp, 4)) + f.maxTwilightPoints = u16(f.maxp, 16) + f.maxStorage = u16(f.maxp, 18) + f.maxFunctionDefs = u16(f.maxp, 20) + f.maxStackElements = u16(f.maxp, 24) return nil }