func Measure(r io.RuneReader, f font.Face) (size fixed.Point26_6, err error) { var char rune var prev rune w := fixed.Int26_6(0) m := f.Metrics() size.Y = m.Height + m.Descent for { if char, _, err = r.ReadRune(); err != nil { if err == io.EOF { err = nil } size.X = maxInt26_6(size.X, w) return } if char == '\n' { size.X = maxInt26_6(size.X, w) size.Y += m.Height w, prev = 0, 0 continue } if prev != 0 { w += f.Kern(prev, char) } w += advance(f, char) prev = char } }
func advance(face font.Face, char rune) (x fixed.Int26_6) { if x, ok := face.GlyphAdvance(char); ok { return x } else { x, _ = face.GlyphAdvance(utf8.RuneError) return x } }
func glyph(face font.Face, char rune, dot fixed.Point26_6) (dr image.Rectangle, mask image.Image, maskp image.Point) { var ok bool if dr, mask, maskp, _, ok = face.Glyph(dot, char); !ok { dr, mask, maskp, _, _ = face.Glyph(dot, utf8.RuneError) } return }
func fromString(s string, fc font.Face) []*glyph { var gs []*glyph for _, r := range s { if b, a, ok := fc.GlyphBounds(r); ok { gs = append(gs, &glyph{r: r, b: b, a: a}) } } return gs }
// enumerate returns all glyphs with a valid index. func enumerate(f *truetype.Font, fc font.Face) []*glyph { var gs []*glyph for r := rune(1); r < (1<<16)-1; r++ { if r == '\uFEFF' { continue // ignore BOM } if f.Index(r) != 0 { b, a, _ := fc.GlyphBounds(r) gs = append(gs, &glyph{r: r, b: b, a: a}) } } return gs }
func (self rightToLeft) Advance(face font.Face, origin fixed.Point26_6, dot fixed.Point26_6, prev rune, char rune) (begin fixed.Point26_6, end fixed.Point26_6) { if char == '\n' { dot.X = origin.X dot.Y += face.Metrics().Height return dot, dot } if prev != 0 { dot.X -= face.Kern(prev, char) } dot.X -= advance(face, char) return dot, dot }
func newGlyphPage(face fnt.Face, r rune) *glyphPage { // Start the page big enough to hold the initial rune. b, _, _ := face.GlyphBounds(r) bounds := rectangle26_6toRect(b) size := math.Size{W: glyphPageWidth, H: glyphPageHeight}.Max(bounds.Size()) size.W = align(size.W, glyphSizeAlignment) size.H = align(size.H, glyphSizeAlignment) page := &glyphPage{ image: image.NewAlpha(image.Rect(0, 0, size.W, size.H)), size: size, entries: make(map[rune]glyphEntry), rowHeight: 0, } page.add(face, r) return page }
func (p *glyphPage) add(face fnt.Face, r rune) bool { if _, found := p.entries[r]; found { panic("Glyph already added to glyph page") } b, mask, maskp, _, _ := face.Glyph(fixed.Point26_6{}, r) bounds := math.CreateRect(b.Min.X, b.Min.Y, b.Max.X, b.Max.Y) w, h := bounds.Size().WH() x, y := p.nextPoint.X, p.nextPoint.Y if x+w > p.size.W { // Row full, start new line x = 0 y += p.rowHeight + glyphPadding p.rowHeight = 0 } if y+h > p.size.H { return false // Page full } draw.Draw(p.image, image.Rect(x, y, x+w, y+h), mask, maskp, draw.Src) p.entries[r] = glyphEntry{ offset: math.Point{X: x, Y: y}.Sub(bounds.Min), bounds: bounds, } p.nextPoint = math.Point{X: x + w + glyphPadding, Y: y} if h > p.rowHeight { p.rowHeight = h } p.tex = nil return true }
func (self rightToLeft) Origin(face font.Face, bounds fixed.Rectangle26_6) fixed.Point26_6 { return fixed.Point26_6{ X: bounds.Max.X, Y: bounds.Min.Y + face.Metrics().Ascent, } }
// MeasureString returns the rendered width and height of the specified text // given the current font face. func MeasureString(ff font.Face, s string) (w float64, h float64) { d := &font.Drawer{Face: ff} return float64(d.MeasureString(s) >> 6), float64(ff.Metrics().Height>>6) * 96.0 / 72.0 }