github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/image/font/plan9font/plan9font.go (about)

     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  // Package plan9font implements font faces for the Plan 9 font and subfont file
     6  // formats. These formats are described at
     7  // http://plan9.bell-labs.com/magic/man2html/6/font
     8  package plan9font // import "golang.org/x/image/font/plan9font"
     9  
    10  // TODO: have a subface use an *image.Alpha instead of plan9Image implementing
    11  // the image.Image interface? The image/draw code has a fast path for
    12  // *image.Alpha masks.
    13  
    14  import (
    15  	"bytes"
    16  	"errors"
    17  	"fmt"
    18  	"image"
    19  	"image/color"
    20  	"log"
    21  	"strconv"
    22  	"strings"
    23  
    24  	"golang.org/x/image/font"
    25  	"golang.org/x/image/math/fixed"
    26  )
    27  
    28  // fontchar describes one character glyph in a subfont.
    29  //
    30  // For more detail, look for "struct Fontchar" in
    31  // http://plan9.bell-labs.com/magic/man2html/2/cachechars
    32  type fontchar struct {
    33  	x      uint32 // X position in the image holding the glyphs.
    34  	top    uint8  // First non-zero scan line.
    35  	bottom uint8  // Last non-zero scan line.
    36  	left   int8   // Offset of baseline.
    37  	width  uint8  // Width of baseline.
    38  }
    39  
    40  func parseFontchars(p []byte) []fontchar {
    41  	fc := make([]fontchar, len(p)/6)
    42  	for i := range fc {
    43  		fc[i] = fontchar{
    44  			x:      uint32(p[0]) | uint32(p[1])<<8,
    45  			top:    uint8(p[2]),
    46  			bottom: uint8(p[3]),
    47  			left:   int8(p[4]),
    48  			width:  uint8(p[5]),
    49  		}
    50  		p = p[6:]
    51  	}
    52  	return fc
    53  }
    54  
    55  // subface implements font.Face for a Plan 9 subfont.
    56  type subface struct {
    57  	firstRune rune        // First rune in the subfont.
    58  	n         int         // Number of characters in the subfont.
    59  	height    int         // Inter-line spacing.
    60  	ascent    int         // Height above the baseline.
    61  	fontchars []fontchar  // Character descriptions.
    62  	img       *plan9Image // Image holding the glyphs.
    63  }
    64  
    65  func (f *subface) Close() error                   { return nil }
    66  func (f *subface) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
    67  
    68  func (f *subface) Glyph(dot fixed.Point26_6, r rune) (
    69  	dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
    70  
    71  	r -= f.firstRune
    72  	if r < 0 || f.n <= int(r) {
    73  		return image.Rectangle{}, nil, image.Point{}, 0, false
    74  	}
    75  	i := &f.fontchars[r+0]
    76  	j := &f.fontchars[r+1]
    77  
    78  	minX := int(dot.X+32)>>6 + int(i.left)
    79  	minY := int(dot.Y+32)>>6 + int(i.top) - f.ascent
    80  	dr = image.Rectangle{
    81  		Min: image.Point{
    82  			X: minX,
    83  			Y: minY,
    84  		},
    85  		Max: image.Point{
    86  			X: minX + int(j.x-i.x),
    87  			Y: minY + int(i.bottom) - int(i.top),
    88  		},
    89  	}
    90  	return dr, f.img, image.Point{int(i.x), int(i.top)}, fixed.Int26_6(i.width) << 6, true
    91  }
    92  
    93  func (f *subface) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
    94  	r -= f.firstRune
    95  	if r < 0 || f.n <= int(r) {
    96  		return fixed.Rectangle26_6{}, 0, false
    97  	}
    98  	i := &f.fontchars[r+0]
    99  	j := &f.fontchars[r+1]
   100  
   101  	bounds = fixed.R(
   102  		int(i.left),
   103  		int(i.top)-f.ascent,
   104  		int(i.left)+int(j.x-i.x),
   105  		int(i.bottom)-f.ascent,
   106  	)
   107  	return bounds, fixed.Int26_6(i.width) << 6, true
   108  }
   109  
   110  func (f *subface) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
   111  	r -= f.firstRune
   112  	if r < 0 || f.n <= int(r) {
   113  		return 0, false
   114  	}
   115  	return fixed.Int26_6(f.fontchars[r].width) << 6, true
   116  }
   117  
   118  // runeRange maps a single rune range [lo, hi] to a lazily loaded subface. Both
   119  // ends of the range are inclusive.
   120  type runeRange struct {
   121  	lo, hi      rune
   122  	offset      rune // subfont index that the lo rune maps to.
   123  	relFilename string
   124  	subface     *subface
   125  	bad         bool
   126  }
   127  
   128  // face implements font.Face for a Plan 9 font.
   129  //
   130  // It maps multiple rune ranges to *subface values. Rune ranges may overlap;
   131  // the first match wins.
   132  type face struct {
   133  	height     int
   134  	ascent     int
   135  	readFile   func(relFilename string) ([]byte, error)
   136  	runeRanges []runeRange
   137  }
   138  
   139  func (f *face) Close() error                   { return nil }
   140  func (f *face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 }
   141  
   142  func (f *face) Glyph(dot fixed.Point26_6, r rune) (
   143  	dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) {
   144  
   145  	if s, rr := f.subface(r); s != nil {
   146  		return s.Glyph(dot, rr)
   147  	}
   148  	return image.Rectangle{}, nil, image.Point{}, 0, false
   149  }
   150  
   151  func (f *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) {
   152  	if s, rr := f.subface(r); s != nil {
   153  		return s.GlyphBounds(rr)
   154  	}
   155  	return fixed.Rectangle26_6{}, 0, false
   156  }
   157  
   158  func (f *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) {
   159  	if s, rr := f.subface(r); s != nil {
   160  		return s.GlyphAdvance(rr)
   161  	}
   162  	return 0, false
   163  }
   164  
   165  func (f *face) subface(r rune) (*subface, rune) {
   166  	// Fall back on U+FFFD if we can't find r.
   167  	for _, rr := range [2]rune{r, '\ufffd'} {
   168  		// We have to do linear, not binary search. plan9port's
   169  		// lucsans/unicode.8.font says:
   170  		//	0x2591  0x2593  ../luc/Altshades.7.0
   171  		//	0x2500  0x25ee  ../luc/FormBlock.7.0
   172  		// and the rune ranges overlap.
   173  		for i := range f.runeRanges {
   174  			x := &f.runeRanges[i]
   175  			if rr < x.lo || x.hi < rr || x.bad {
   176  				continue
   177  			}
   178  			if x.subface == nil {
   179  				data, err := f.readFile(x.relFilename)
   180  				if err != nil {
   181  					log.Printf("plan9font: couldn't read subfont %q: %v", x.relFilename, err)
   182  					x.bad = true
   183  					continue
   184  				}
   185  				sub, err := ParseSubfont(data, x.lo-x.offset)
   186  				if err != nil {
   187  					log.Printf("plan9font: couldn't parse subfont %q: %v", x.relFilename, err)
   188  					x.bad = true
   189  					continue
   190  				}
   191  				x.subface = sub.(*subface)
   192  			}
   193  			return x.subface, rr
   194  		}
   195  	}
   196  	return nil, 0
   197  }
   198  
   199  // ParseFont parses a Plan 9 font file. data is the contents of that font file,
   200  // which gives relative filenames for subfont files. readFile returns the
   201  // contents of those subfont files. It is similar to io/ioutil's ReadFile
   202  // function, except that it takes a relative filename instead of an absolute
   203  // one.
   204  func ParseFont(data []byte, readFile func(relFilename string) ([]byte, error)) (font.Face, error) {
   205  	f := &face{
   206  		readFile: readFile,
   207  	}
   208  	// TODO: don't use strconv, to avoid the conversions from []byte to string?
   209  	for first := true; len(data) > 0; first = false {
   210  		i := bytes.IndexByte(data, '\n')
   211  		if i < 0 {
   212  			return nil, errors.New("plan9font: invalid font: no final newline")
   213  		}
   214  		row := string(data[:i])
   215  		data = data[i+1:]
   216  		if first {
   217  			height, s, ok := nextInt32(row)
   218  			if !ok {
   219  				return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row)
   220  			}
   221  			ascent, s, ok := nextInt32(s)
   222  			if !ok {
   223  				return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row)
   224  			}
   225  			if height < 0 || 0xffff < height || ascent < 0 || 0xffff < ascent {
   226  				return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row)
   227  			}
   228  			f.height, f.ascent = int(height), int(ascent)
   229  			continue
   230  		}
   231  		lo, s, ok := nextInt32(row)
   232  		if !ok {
   233  			return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row)
   234  		}
   235  		hi, s, ok := nextInt32(s)
   236  		if !ok {
   237  			return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row)
   238  		}
   239  		offset, s, _ := nextInt32(s)
   240  
   241  		f.runeRanges = append(f.runeRanges, runeRange{
   242  			lo:          lo,
   243  			hi:          hi,
   244  			offset:      offset,
   245  			relFilename: s,
   246  		})
   247  	}
   248  	return f, nil
   249  }
   250  
   251  func nextInt32(s string) (ret int32, remaining string, ok bool) {
   252  	i := 0
   253  	for ; i < len(s) && s[i] <= ' '; i++ {
   254  	}
   255  	j := i
   256  	for ; j < len(s) && s[j] > ' '; j++ {
   257  	}
   258  	n, err := strconv.ParseInt(s[i:j], 0, 32)
   259  	if err != nil {
   260  		return 0, s, false
   261  	}
   262  	for ; j < len(s) && s[j] <= ' '; j++ {
   263  	}
   264  	return int32(n), s[j:], true
   265  }
   266  
   267  // ParseSubfont parses a Plan 9 subfont file.
   268  //
   269  // firstRune is the first rune in the subfont file. For example, the
   270  // Phonetic.6.0 subfont, containing glyphs in the range U+0250 to U+02E9, would
   271  // set firstRune to '\u0250'.
   272  func ParseSubfont(data []byte, firstRune rune) (font.Face, error) {
   273  	data, m, err := parseImage(data)
   274  	if err != nil {
   275  		return nil, err
   276  	}
   277  	if len(data) < 3*12 {
   278  		return nil, errors.New("plan9font: invalid subfont: header too short")
   279  	}
   280  	n := atoi(data[0*12:])
   281  	height := atoi(data[1*12:])
   282  	ascent := atoi(data[2*12:])
   283  	data = data[3*12:]
   284  	if len(data) != 6*(n+1) {
   285  		return nil, errors.New("plan9font: invalid subfont: data length mismatch")
   286  	}
   287  	return &subface{
   288  		firstRune: firstRune,
   289  		n:         n,
   290  		height:    height,
   291  		ascent:    ascent,
   292  		fontchars: parseFontchars(data),
   293  		img:       m,
   294  	}, nil
   295  }
   296  
   297  // plan9Image implements that subset of the Plan 9 image feature set that is
   298  // used by this font file format.
   299  //
   300  // Some features, such as the repl bit and a clip rectangle, are omitted for
   301  // simplicity.
   302  type plan9Image struct {
   303  	depth int             // Depth of the pixels in bits.
   304  	width int             // Width in bytes of a single scan line.
   305  	rect  image.Rectangle // Extent of the image.
   306  	pix   []byte          // Pixel bits.
   307  }
   308  
   309  func (m *plan9Image) byteoffset(x, y int) int {
   310  	a := y * m.width
   311  	if m.depth < 8 {
   312  		// We need to always round down, but Go rounds toward zero.
   313  		np := 8 / m.depth
   314  		if x < 0 {
   315  			return a + (x-np+1)/np
   316  		}
   317  		return a + x/np
   318  	}
   319  	return a + x*(m.depth/8)
   320  }
   321  
   322  func (m *plan9Image) Bounds() image.Rectangle { return m.rect }
   323  func (m *plan9Image) ColorModel() color.Model { return color.AlphaModel }
   324  
   325  func (m *plan9Image) At(x, y int) color.Color {
   326  	if (image.Point{x, y}).In(m.rect) {
   327  		b := m.pix[m.byteoffset(x, y)]
   328  		switch m.depth {
   329  		case 1:
   330  			// CGrey, 1.
   331  			mask := uint8(1 << uint8(7-x&7))
   332  			if (b & mask) != 0 {
   333  				return color.Alpha{0xff}
   334  			}
   335  			return color.Alpha{0x00}
   336  		case 2:
   337  			// CGrey, 2.
   338  			shift := uint(x&3) << 1
   339  			// Place pixel at top of word.
   340  			y := b << shift
   341  			y &= 0xc0
   342  			// Replicate throughout.
   343  			y |= y >> 2
   344  			y |= y >> 4
   345  			return color.Alpha{y}
   346  		}
   347  	}
   348  	return color.Alpha{0x00}
   349  }
   350  
   351  var compressed = []byte("compressed\n")
   352  
   353  func parseImage(data []byte) (remainingData []byte, m *plan9Image, retErr error) {
   354  	if !bytes.HasPrefix(data, compressed) {
   355  		return nil, nil, errors.New("plan9font: unsupported uncompressed format")
   356  	}
   357  	data = data[len(compressed):]
   358  
   359  	const hdrSize = 5 * 12
   360  	if len(data) < hdrSize {
   361  		return nil, nil, errors.New("plan9font: invalid image: header too short")
   362  	}
   363  	hdr, data := data[:hdrSize], data[hdrSize:]
   364  
   365  	// Distinguish new channel descriptor from old ldepth. Channel descriptors
   366  	// have letters as well as numbers, while ldepths are a single digit
   367  	// formatted as %-11d.
   368  	new := false
   369  	for m := 0; m < 10; m++ {
   370  		if hdr[m] != ' ' {
   371  			new = true
   372  			break
   373  		}
   374  	}
   375  	if hdr[11] != ' ' {
   376  		return nil, nil, errors.New("plan9font: invalid image: bad header")
   377  	}
   378  	if !new {
   379  		return nil, nil, errors.New("plan9font: unsupported ldepth format")
   380  	}
   381  
   382  	depth := 0
   383  	switch s := strings.TrimSpace(string(hdr[:1*12])); s {
   384  	default:
   385  		return nil, nil, fmt.Errorf("plan9font: unsupported pixel format %q", s)
   386  	case "k1":
   387  		depth = 1
   388  	case "k2":
   389  		depth = 2
   390  	}
   391  	r := ator(hdr[1*12:])
   392  	if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y {
   393  		return nil, nil, errors.New("plan9font: invalid image: bad rectangle")
   394  	}
   395  
   396  	width := bytesPerLine(r, depth)
   397  	m = &plan9Image{
   398  		depth: depth,
   399  		width: width,
   400  		rect:  r,
   401  		pix:   make([]byte, width*r.Dy()),
   402  	}
   403  
   404  	miny := r.Min.Y
   405  	for miny != r.Max.Y {
   406  		if len(data) < 2*12 {
   407  			return nil, nil, errors.New("plan9font: invalid image: data band too short")
   408  		}
   409  		maxy := atoi(data[0*12:])
   410  		nb := atoi(data[1*12:])
   411  		data = data[2*12:]
   412  
   413  		if len(data) < nb {
   414  			return nil, nil, errors.New("plan9font: invalid image: data band length mismatch")
   415  		}
   416  		buf := data[:nb]
   417  		data = data[nb:]
   418  
   419  		if maxy <= miny || r.Max.Y < maxy {
   420  			return nil, nil, fmt.Errorf("plan9font: bad maxy %d", maxy)
   421  		}
   422  		// An old-format image would flip the bits here, but we don't support
   423  		// the old format.
   424  		rr := r
   425  		rr.Min.Y = miny
   426  		rr.Max.Y = maxy
   427  		if err := decompress(m, rr, buf); err != nil {
   428  			return nil, nil, err
   429  		}
   430  		miny = maxy
   431  	}
   432  	return data, m, nil
   433  }
   434  
   435  // Compressed data are sequences of byte codes. If the first byte b has the
   436  // 0x80 bit set, the next (b^0x80)+1 bytes are data. Otherwise, these two bytes
   437  // specify a previous string to repeat.
   438  const (
   439  	compShortestMatch = 3    // shortest match possible.
   440  	compWindowSize    = 1024 // window size.
   441  )
   442  
   443  var (
   444  	errDecompressBufferTooSmall = errors.New("plan9font: decompress: buffer too small")
   445  	errDecompressPhaseError     = errors.New("plan9font: decompress: phase error")
   446  )
   447  
   448  func decompress(m *plan9Image, r image.Rectangle, data []byte) error {
   449  	if !r.In(m.rect) {
   450  		return errors.New("plan9font: decompress: bad rectangle")
   451  	}
   452  	bpl := bytesPerLine(r, m.depth)
   453  	mem := make([]byte, compWindowSize)
   454  	memi := 0
   455  	omemi := -1
   456  	y := r.Min.Y
   457  	linei := m.byteoffset(r.Min.X, y)
   458  	eline := linei + bpl
   459  	datai := 0
   460  	for {
   461  		if linei == eline {
   462  			y++
   463  			if y == r.Max.Y {
   464  				break
   465  			}
   466  			linei = m.byteoffset(r.Min.X, y)
   467  			eline = linei + bpl
   468  		}
   469  		if datai == len(data) {
   470  			return errDecompressBufferTooSmall
   471  		}
   472  		c := data[datai]
   473  		datai++
   474  		if c >= 128 {
   475  			for cnt := c - 128 + 1; cnt != 0; cnt-- {
   476  				if datai == len(data) {
   477  					return errDecompressBufferTooSmall
   478  				}
   479  				if linei == eline {
   480  					return errDecompressPhaseError
   481  				}
   482  				m.pix[linei] = data[datai]
   483  				linei++
   484  				mem[memi] = data[datai]
   485  				memi++
   486  				datai++
   487  				if memi == len(mem) {
   488  					memi = 0
   489  				}
   490  			}
   491  		} else {
   492  			if datai == len(data) {
   493  				return errDecompressBufferTooSmall
   494  			}
   495  			offs := int(data[datai]) + ((int(c) & 3) << 8) + 1
   496  			datai++
   497  			if memi < offs {
   498  				omemi = memi + (compWindowSize - offs)
   499  			} else {
   500  				omemi = memi - offs
   501  			}
   502  			for cnt := (c >> 2) + compShortestMatch; cnt != 0; cnt-- {
   503  				if linei == eline {
   504  					return errDecompressPhaseError
   505  				}
   506  				m.pix[linei] = mem[omemi]
   507  				linei++
   508  				mem[memi] = mem[omemi]
   509  				memi++
   510  				omemi++
   511  				if omemi == len(mem) {
   512  					omemi = 0
   513  				}
   514  				if memi == len(mem) {
   515  					memi = 0
   516  				}
   517  			}
   518  		}
   519  	}
   520  	return nil
   521  }
   522  
   523  func ator(b []byte) image.Rectangle {
   524  	return image.Rectangle{atop(b), atop(b[2*12:])}
   525  }
   526  
   527  func atop(b []byte) image.Point {
   528  	return image.Pt(atoi(b), atoi(b[12:]))
   529  }
   530  
   531  func atoi(b []byte) int {
   532  	i := 0
   533  	for ; i < len(b) && b[i] == ' '; i++ {
   534  	}
   535  	n := 0
   536  	for ; i < len(b) && '0' <= b[i] && b[i] <= '9'; i++ {
   537  		n = n*10 + int(b[i]) - '0'
   538  	}
   539  	return n
   540  }
   541  
   542  func bytesPerLine(r image.Rectangle, depth int) int {
   543  	if depth <= 0 || 32 < depth {
   544  		panic("invalid depth")
   545  	}
   546  	var l int
   547  	if r.Min.X >= 0 {
   548  		l = (r.Max.X*depth + 7) / 8
   549  		l -= (r.Min.X * depth) / 8
   550  	} else {
   551  		// Make positive before divide.
   552  		t := (-r.Min.X*depth + 7) / 8
   553  		l = t + (r.Max.X*depth+7)/8
   554  	}
   555  	return l
   556  }