func (f *Face) Glyph(dot fixed.Point26_6, r rune) ( dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) { loop: for _, rr := range [2]rune{r, '\ufffd'} { for _, rng := range f.Ranges { if rr < rng.Low || rng.High <= rr { continue } maskp.Y = (int(rr-rng.Low) + rng.Offset) * f.Height ok = true break loop } } if !ok { return image.Rectangle{}, nil, image.Point{}, 0, false } minX := int(dot.X+32) >> 6 minY := int(dot.Y+32)>>6 - f.Ascent dr = image.Rectangle{ Min: image.Point{ X: minX, Y: minY, }, Max: image.Point{ X: minX + f.Width, Y: minY + f.Height, }, } return dr, f.Mask, maskp, fixed.I(f.Advance), true }
func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { return fixed.R(0, -f.Ascent, f.Width, -f.Ascent+f.Height), fixed.I(f.Advance), true }
func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { return fixed.I(f.Advance), true }
func testScaling(t *testing.T, h font.Hinting) { for _, tc := range scalingTestCases { f, testdataIsOptional, err := parseTestdataFont(tc.name) if err != nil { if testdataIsOptional { t.Log(err) } else { t.Error(err) } continue } hintingStr := "sans" if h != font.HintingNone { hintingStr = "with" } testFile, err := os.Open(fmt.Sprintf( "../testdata/%s-%dpt-%s-hinting.txt", tc.name, tc.size, hintingStr)) if err != nil { t.Errorf("%s: Open: %v", tc.name, err) continue } defer testFile.Close() wants := []scalingTestData{} scanner := bufio.NewScanner(testFile) if scanner.Scan() { major, minor, patch := 0, 0, 0 _, err := fmt.Sscanf(scanner.Text(), "freetype version %d.%d.%d", &major, &minor, &patch) if err != nil { t.Errorf("%s: version information: %v", tc.name, err) } if (major < 2) || (major == 2 && minor < 5) || (major == 2 && minor == 5 && patch < 1) { t.Errorf("%s: need freetype version >= 2.5.1.\n"+ "Try setting LD_LIBRARY_PATH=/path/to/freetype_built_from_src/objs/.libs/\n"+ "and re-running testdata/make-other-hinting-txts.sh", tc.name) continue } } else { t.Errorf("%s: no version information", tc.name) continue } for scanner.Scan() { wants = append(wants, scalingTestParse(scanner.Text())) } if err := scanner.Err(); err != nil && err != io.EOF { t.Errorf("%s: Scanner: %v", tc.name, err) continue } glyphBuf := &GlyphBuf{} for i, want := range wants { if err = glyphBuf.Load(f, fixed.I(tc.size), Index(i), h); err != nil { t.Errorf("%s: glyph #%d: Load: %v", tc.name, i, err) continue } got := scalingTestData{ advanceWidth: glyphBuf.AdvanceWidth, bounds: glyphBuf.Bounds, points: glyphBuf.Points, } if got.advanceWidth != want.advanceWidth { t.Errorf("%s: glyph #%d advance width:\ngot %v\nwant %v", tc.name, i, got.advanceWidth, want.advanceWidth) continue } if got.bounds != want.bounds { t.Errorf("%s: glyph #%d bounds:\ngot %v\nwant %v", tc.name, i, got.bounds, want.bounds) continue } for i := range got.points { got.points[i].Flags &= 0x01 } if len(got.points) != len(want.points) { t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\ndifferent slice lengths: %d versus %d", tc.name, i, got.points, want.points, len(got.points), len(want.points)) continue } if j, equals := scalingTestEquals(got.points, want.points); !equals { t.Errorf("%s: glyph #%d:\ngot %v\nwant %v\nat index %d: %v versus %v", tc.name, i, got.points, want.points, j, got.points[j], want.points[j]) continue } } } }