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) 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 } } } }
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 main() { flag.Parse() // Read the font data. fontBytes, err := ioutil.ReadFile(*fontfile) if err != nil { log.Println(err) return } f, err := truetype.Parse(fontBytes) if err != nil { log.Println(err) return } // Draw the background and the guidelines. fg, bg := image.Black, image.White ruler := color.RGBA{0xdd, 0xdd, 0xdd, 0xff} if *wonb { fg, bg = image.White, image.Black ruler = color.RGBA{0x22, 0x22, 0x22, 0xff} } const imgW, imgH = 640, 480 rgba := image.NewRGBA(image.Rect(0, 0, imgW, imgH)) draw.Draw(rgba, rgba.Bounds(), bg, image.ZP, draw.Src) for i := 0; i < 200; i++ { rgba.Set(10, 10+i, ruler) rgba.Set(10+i, 10, ruler) } // Draw the text. h := font.HintingNone switch *hinting { case "full": h = font.HintingFull } d := &font.Drawer{ Dst: rgba, Src: fg, Face: truetype.NewFace(f, &truetype.Options{ Size: *size, DPI: *dpi, Hinting: h, }), } y := 10 + int(math.Ceil(*size**dpi/72)) dy := int(math.Ceil(*size * *spacing * *dpi / 72)) d.Dot = fixed.Point26_6{ X: (fixed.I(imgW) - d.MeasureString(title)) / 2, Y: fixed.I(y), } d.DrawString(title) y += dy for _, s := range text { d.Dot = fixed.P(10, y) d.DrawString(s) y += dy } // Save that RGBA image to disk. outFile, err := os.Create("out.png") if err != nil { log.Println(err) os.Exit(1) } defer outFile.Close() b := bufio.NewWriter(outFile) err = png.Encode(b, rgba) if err != nil { log.Println(err) os.Exit(1) } err = b.Flush() if err != nil { log.Println(err) os.Exit(1) } fmt.Println("Wrote out.png OK.") }