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