From 8373bbf0e67d5fee648203438b5ea4fa827a7d15 Mon Sep 17 00:00:00 2001 From: Nigel Tao Date: Wed, 16 Oct 2013 21:39:06 +1100 Subject: [PATCH] freetype/truetype: implement compound glyph transforms. R=bsiegert CC=golang-dev https://codereview.appspot.com/14425064 --- freetype/truetype/glyph.go | 30 ++++++++++++++++++++++++++++-- freetype/truetype/truetype_test.go | 13 ++++--------- 2 files changed, 32 insertions(+), 11 deletions(-) diff --git a/freetype/truetype/glyph.go b/freetype/truetype/glyph.go index cbb3794..a3bed71 100644 --- a/freetype/truetype/glyph.go +++ b/freetype/truetype/glyph.go @@ -286,7 +286,7 @@ func (g *GlyphBuf) loadCompound(recursion int32, glyf []byte) error { for offset := loadOffset; ; { flags := u16(glyf, offset) component := Index(u16(glyf, offset+2)) - dx, dy := int32(0), int32(0) + dx, dy, transform, hasTransform := int32(0), int32(0), [4]int32{}, false if flags&flagArg1And2AreWords != 0 { dx = int32(int16(u16(glyf, offset+4))) dy = int32(int16(u16(glyf, offset+6))) @@ -300,12 +300,38 @@ func (g *GlyphBuf) loadCompound(recursion int32, glyf []byte) error { return UnsupportedError("compound glyph transform vector") } if flags&(flagWeHaveAScale|flagWeHaveAnXAndYScale|flagWeHaveATwoByTwo) != 0 { - return UnsupportedError("compound glyph scale/transform") + hasTransform = true + switch { + case flags&flagWeHaveAScale != 0: + transform[0] = int32(int16(u16(glyf, offset+0))) + transform[3] = transform[0] + offset += 2 + case flags&flagWeHaveAnXAndYScale != 0: + transform[0] = int32(int16(u16(glyf, offset+0))) + transform[3] = int32(int16(u16(glyf, offset+2))) + offset += 4 + case flags&flagWeHaveATwoByTwo != 0: + transform[0] = int32(int16(u16(glyf, offset+0))) + transform[1] = int32(int16(u16(glyf, offset+2))) + transform[2] = int32(int16(u16(glyf, offset+4))) + transform[3] = int32(int16(u16(glyf, offset+6))) + offset += 8 + } } np0 := len(g.Point) if err := g.load(recursion+1, component, flags&flagUseMyMetrics != 0); err != nil { return err } + if hasTransform { + for i := np0; i < len(g.Point); i++ { + p := &g.Point[i] + newX := int32((int64(p.X)*int64(transform[0])+1<<13)>>14) + + int32((int64(p.Y)*int64(transform[2])+1<<13)>>14) + newY := int32((int64(p.X)*int64(transform[1])+1<<13)>>14) + + int32((int64(p.Y)*int64(transform[3])+1<<13)>>14) + p.X, p.Y = newX, newY + } + } dx = g.font.scale(g.scale * dx) dy = g.font.scale(g.scale * dy) if flags&flagRoundXYToGrid != 0 { diff --git a/freetype/truetype/truetype_test.go b/freetype/truetype/truetype_test.go index 54524da..3f33e04 100644 --- a/freetype/truetype/truetype_test.go +++ b/freetype/truetype/truetype_test.go @@ -263,7 +263,6 @@ var scalingTestCases = []struct { // TODO: also test bounding boxes, not just points. func testScaling(t *testing.T, hinter *Hinter) { -loop: for _, tc := range scalingTestCases { font, testdataIsOptional, err := parseTestdataFont(tc.name) if err != nil { @@ -272,7 +271,7 @@ loop: } else { t.Error(err) } - continue loop + continue } hinting := "sans" if hinter != nil { @@ -282,7 +281,7 @@ loop: "../../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hinting)) if err != nil { t.Errorf("%s: Open: %v", tc.name, err) - continue loop + continue } defer f.Close() @@ -293,7 +292,7 @@ loop: } if err := scanner.Err(); err != nil && err != io.EOF { t.Errorf("%s: Scanner: %v", tc.name, err) - continue loop + continue } glyphBuf := NewGlyphBuf() @@ -305,12 +304,8 @@ loop: } if err = glyphBuf.Load(font, tc.size*64, Index(i), hinter); err != nil { - if ue, ok := err.(UnsupportedError); ok && ue == "compound glyph scale/transform" { - // TODO: implement compound glyph scale/transform. - continue loop - } t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err) - continue loop + continue } got := glyphBuf.Point for i := range got {