git.lucas.co / go_mono
git clone https://git.lucas.co/go_mono.git

font/basicfont/basicfont.go (3.7K)

  1 // Copyright 2015 The Go Authors. All rights reserved.
  2 // Use of this source code is governed by a BSD-style
  3 // license that can be found in the LICENSE file.
  4 
  5 //go:generate go run gen.go
  6 
  7 // Package basicfont provides fixed-size font faces.
  8 package basicfont // import "golang.org/x/image/font/basicfont"
  9 
 10 import (
 11 	"image"
 12 
 13 	"golang.org/x/image/font"
 14 	"golang.org/x/image/math/fixed"
 15 )
 16 
 17 // Range maps a contiguous range of runes to vertically adjacent sub-images of
 18 // a Face's Mask image. The rune range is inclusive on the low end and
 19 // exclusive on the high end.
 20 //
 21 // If Low <= r && r < High, then the rune r is mapped to the sub-image of
 22 // Face.Mask whose bounds are image.Rect(0, y*h, Face.Width, (y+1)*h),
 23 // where y = (int(r-Low) + Offset) and h = (Face.Ascent + Face.Descent).
 24 type Range struct {
 25 	Low, High rune
 26 	Offset    int
 27 }
 28 
 29 // Face7x13 is a Face derived from the public domain X11 misc-fixed font files.
 30 //
 31 // At the moment, it holds the printable characters in ASCII starting with
 32 // space, and the Unicode replacement character U+FFFD.
 33 //
 34 // Its data is entirely self-contained and does not require loading from
 35 // separate files.
 36 var Face7x13 = &Face{
 37 	Advance: 7,
 38 	Width:   6,
 39 	Height:  13,
 40 	Ascent:  11,
 41 	Descent: 2,
 42 	Mask:    mask7x13,
 43 	Ranges: []Range{
 44 		{'\u0020', '\u007f', 0},
 45 		{'\ufffd', '\ufffe', 95},
 46 	},
 47 }
 48 
 49 // Face is a basic font face whose glyphs all have the same metrics.
 50 //
 51 // It is safe to use concurrently.
 52 type Face struct {
 53 	// Advance is the glyph advance, in pixels.
 54 	Advance int
 55 	// Width is the glyph width, in pixels.
 56 	Width int
 57 	// Height is the inter-line height, in pixels.
 58 	Height int
 59 	// Ascent is the glyph ascent, in pixels.
 60 	Ascent int
 61 	// Descent is the glyph descent, in pixels.
 62 	Descent int
 63 	// Left is the left side bearing, in pixels. A positive value means that
 64 	// all of a glyph is to the right of the dot.
 65 	Left int
 66 
 67 	// Mask contains all of the glyph masks. Its width is typically the Face's
 68 	// Width, and its height a multiple of the Face's Height.
 69 	Mask image.Image
 70 	// Ranges map runes to sub-images of Mask. The rune ranges must not
 71 	// overlap, and must be in increasing rune order.
 72 	Ranges []Range
 73 }
 74 
 75 func (f *Face) Close() error                   { return nil }
 76 func (f *Face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
 77 
 78 func (f *Face) Metrics() font.Metrics {
 79 	return font.Metrics{
 80 		Height:     fixed.I(f.Height),
 81 		Ascent:     fixed.I(f.Ascent),
 82 		Descent:    fixed.I(f.Descent),
 83 		XHeight:    fixed.I(f.Ascent),
 84 		CapHeight:  fixed.I(f.Ascent),
 85 		CaretSlope: image.Point{X: 0, Y: 1},
 86 	}
 87 }
 88 
 89 func (f *Face) Glyph(dot fixed.Point26_6, r rune) (
 90 	dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
 91 
 92 	if found, rng := f.find(r); rng != nil {
 93 		maskp.Y = (int(found-rng.Low) + rng.Offset) * (f.Ascent + f.Descent)
 94 		x := int(dot.X+32)>>6 + f.Left
 95 		y := int(dot.Y+32) >> 6
 96 		dr = image.Rectangle{
 97 			Min: image.Point{
 98 				X: x,
 99 				Y: y - f.Ascent,
100 			},
101 			Max: image.Point{
102 				X: x + f.Width,
103 				Y: y + f.Descent,
104 			},
105 		}
106 
107 		return dr, f.Mask, maskp, fixed.I(f.Advance), r == found
108 	}
109 	return image.Rectangle{}, nil, image.Point{}, 0, false
110 }
111 
112 func (f *Face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
113 	if found, rng := f.find(r); rng != nil {
114 		return fixed.R(0, -f.Ascent, f.Width, +f.Descent), fixed.I(f.Advance), r == found
115 	}
116 	return fixed.Rectangle26_6{}, 0, false
117 }
118 
119 func (f *Face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
120 	if found, rng := f.find(r); rng != nil {
121 		return fixed.I(f.Advance), r == found
122 	}
123 	return 0, false
124 }
125 
126 func (f *Face) find(r rune) (rune, *Range) {
127 	for {
128 		for i, rng := range f.Ranges {
129 			if (rng.Low <= r) && (r < rng.High) {
130 				return r, &f.Ranges[i]
131 			}
132 		}
133 		if r == '\ufffd' {
134 			return 0, nil
135 		}
136 		r = '\ufffd'
137 	}
138 }