diff options
Diffstat (limited to 'Godeps/_workspace/src/golang.org/x/image/font/plan9font')
-rw-r--r-- | Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go | 556 |
1 files changed, 0 insertions, 556 deletions
diff --git a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go b/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go deleted file mode 100644 index 9c686b776..000000000 --- a/Godeps/_workspace/src/golang.org/x/image/font/plan9font/plan9font.go +++ /dev/null @@ -1,556 +0,0 @@ -// Copyright 2015 The Go Authors. All rights reserved. -// Use of this source code is governed by a BSD-style -// license that can be found in the LICENSE file. - -// Package plan9font implements font faces for the Plan 9 font and subfont file -// formats. These formats are described at -// http://plan9.bell-labs.com/magic/man2html/6/font -package plan9font - -// TODO: have a subface use an *image.Alpha instead of plan9Image implementing -// the image.Image interface? The image/draw code has a fast path for -// *image.Alpha masks. - -import ( - "bytes" - "errors" - "fmt" - "image" - "image/color" - "log" - "strconv" - "strings" - - "golang.org/x/image/font" - "golang.org/x/image/math/fixed" -) - -// fontchar describes one character glyph in a subfont. -// -// For more detail, look for "struct Fontchar" in -// http://plan9.bell-labs.com/magic/man2html/2/cachechars -type fontchar struct { - x uint32 // X position in the image holding the glyphs. - top uint8 // First non-zero scan line. - bottom uint8 // Last non-zero scan line. - left int8 // Offset of baseline. - width uint8 // Width of baseline. -} - -func parseFontchars(p []byte) []fontchar { - fc := make([]fontchar, len(p)/6) - for i := range fc { - fc[i] = fontchar{ - x: uint32(p[0]) | uint32(p[1])<<8, - top: uint8(p[2]), - bottom: uint8(p[3]), - left: int8(p[4]), - width: uint8(p[5]), - } - p = p[6:] - } - return fc -} - -// subface implements font.Face for a Plan 9 subfont. -type subface struct { - firstRune rune // First rune in the subfont. - n int // Number of characters in the subfont. - height int // Inter-line spacing. - ascent int // Height above the baseline. - fontchars []fontchar // Character descriptions. - img *plan9Image // Image holding the glyphs. -} - -func (f *subface) Close() error { return nil } -func (f *subface) Kern(r0, r1 rune) fixed.Int26_6 { return 0 } - -func (f *subface) Glyph(dot fixed.Point26_6, r rune) ( - dr image.Rectangle, mask image.Image, maskp image.Point, advance fixed.Int26_6, ok bool) { - - r -= f.firstRune - if r < 0 || f.n <= int(r) { - return image.Rectangle{}, nil, image.Point{}, 0, false - } - i := &f.fontchars[r+0] - j := &f.fontchars[r+1] - - minX := int(dot.X+32)>>6 + int(i.left) - minY := int(dot.Y+32)>>6 + int(i.top) - f.ascent - dr = image.Rectangle{ - Min: image.Point{ - X: minX, - Y: minY, - }, - Max: image.Point{ - X: minX + int(j.x-i.x), - Y: minY + int(i.bottom) - int(i.top), - }, - } - return dr, f.img, image.Point{int(i.x), int(i.top)}, fixed.Int26_6(i.width) << 6, true -} - -func (f *subface) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { - r -= f.firstRune - if r < 0 || f.n <= int(r) { - return fixed.Rectangle26_6{}, 0, false - } - i := &f.fontchars[r+0] - j := &f.fontchars[r+1] - - bounds = fixed.R( - int(i.left), - int(i.top)-f.ascent, - int(i.left)+int(j.x-i.x), - int(i.bottom)-f.ascent, - ) - return bounds, fixed.Int26_6(i.width) << 6, true -} - -func (f *subface) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { - r -= f.firstRune - if r < 0 || f.n <= int(r) { - return 0, false - } - return fixed.Int26_6(f.fontchars[r].width) << 6, true -} - -// runeRange maps a single rune range [lo, hi] to a lazily loaded subface. Both -// ends of the range are inclusive. -type runeRange struct { - lo, hi rune - offset rune // subfont index that the lo rune maps to. - relFilename string - subface *subface - bad bool -} - -// face implements font.Face for a Plan 9 font. -// -// It maps multiple rune ranges to *subface values. Rune ranges may overlap; -// the first match wins. -type face struct { - height int - ascent int - readFile func(relFilename string) ([]byte, error) - runeRanges []runeRange -} - -func (f *face) Close() error { return nil } -func (f *face) Kern(r0, r1 rune) fixed.Int26_6 { return 0 } - -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) { - - if s, rr := f.subface(r); s != nil { - return s.Glyph(dot, rr) - } - return image.Rectangle{}, nil, image.Point{}, 0, false -} - -func (f *face) GlyphBounds(r rune) (bounds fixed.Rectangle26_6, advance fixed.Int26_6, ok bool) { - if s, rr := f.subface(r); s != nil { - return s.GlyphBounds(rr) - } - return fixed.Rectangle26_6{}, 0, false -} - -func (f *face) GlyphAdvance(r rune) (advance fixed.Int26_6, ok bool) { - if s, rr := f.subface(r); s != nil { - return s.GlyphAdvance(rr) - } - return 0, false -} - -func (f *face) subface(r rune) (*subface, rune) { - // Fall back on U+FFFD if we can't find r. - for _, rr := range [2]rune{r, '\ufffd'} { - // We have to do linear, not binary search. plan9port's - // lucsans/unicode.8.font says: - // 0x2591 0x2593 ../luc/Altshades.7.0 - // 0x2500 0x25ee ../luc/FormBlock.7.0 - // and the rune ranges overlap. - for i := range f.runeRanges { - x := &f.runeRanges[i] - if rr < x.lo || x.hi < rr || x.bad { - continue - } - if x.subface == nil { - data, err := f.readFile(x.relFilename) - if err != nil { - log.Printf("plan9font: couldn't read subfont %q: %v", x.relFilename, err) - x.bad = true - continue - } - sub, err := ParseSubfont(data, x.lo-x.offset) - if err != nil { - log.Printf("plan9font: couldn't parse subfont %q: %v", x.relFilename, err) - x.bad = true - continue - } - x.subface = sub.(*subface) - } - return x.subface, rr - } - } - return nil, 0 -} - -// ParseFont parses a Plan 9 font file. data is the contents of that font file, -// which gives relative filenames for subfont files. readFile returns the -// contents of those subfont files. It is similar to io/ioutil's ReadFile -// function, except that it takes a relative filename instead of an absolute -// one. -func ParseFont(data []byte, readFile func(relFilename string) ([]byte, error)) (font.Face, error) { - f := &face{ - readFile: readFile, - } - // TODO: don't use strconv, to avoid the conversions from []byte to string? - for first := true; len(data) > 0; first = false { - i := bytes.IndexByte(data, '\n') - if i < 0 { - return nil, errors.New("plan9font: invalid font: no final newline") - } - row := string(data[:i]) - data = data[i+1:] - if first { - height, s, ok := nextInt32(row) - if !ok { - return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row) - } - ascent, s, ok := nextInt32(s) - if !ok { - return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row) - } - if height < 0 || 0xffff < height || ascent < 0 || 0xffff < ascent { - return nil, fmt.Errorf("plan9font: invalid font: invalid header %q", row) - } - f.height, f.ascent = int(height), int(ascent) - continue - } - lo, s, ok := nextInt32(row) - if !ok { - return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row) - } - hi, s, ok := nextInt32(s) - if !ok { - return nil, fmt.Errorf("plan9font: invalid font: invalid row %q", row) - } - offset, s, _ := nextInt32(s) - - f.runeRanges = append(f.runeRanges, runeRange{ - lo: lo, - hi: hi, - offset: offset, - relFilename: s, - }) - } - return f, nil -} - -func nextInt32(s string) (ret int32, remaining string, ok bool) { - i := 0 - for ; i < len(s) && s[i] <= ' '; i++ { - } - j := i - for ; j < len(s) && s[j] > ' '; j++ { - } - n, err := strconv.ParseInt(s[i:j], 0, 32) - if err != nil { - return 0, s, false - } - for ; j < len(s) && s[j] <= ' '; j++ { - } - return int32(n), s[j:], true -} - -// ParseSubfont parses a Plan 9 subfont file. -// -// firstRune is the first rune in the subfont file. For example, the -// Phonetic.6.0 subfont, containing glyphs in the range U+0250 to U+02E9, would -// set firstRune to '\u0250'. -func ParseSubfont(data []byte, firstRune rune) (font.Face, error) { - data, m, err := parseImage(data) - if err != nil { - return nil, err - } - if len(data) < 3*12 { - return nil, errors.New("plan9font: invalid subfont: header too short") - } - n := atoi(data[0*12:]) - height := atoi(data[1*12:]) - ascent := atoi(data[2*12:]) - data = data[3*12:] - if len(data) != 6*(n+1) { - return nil, errors.New("plan9font: invalid subfont: data length mismatch") - } - return &subface{ - firstRune: firstRune, - n: n, - height: height, - ascent: ascent, - fontchars: parseFontchars(data), - img: m, - }, nil -} - -// plan9Image implements that subset of the Plan 9 image feature set that is -// used by this font file format. -// -// Some features, such as the repl bit and a clip rectangle, are omitted for -// simplicity. -type plan9Image struct { - depth int // Depth of the pixels in bits. - width int // Width in bytes of a single scan line. - rect image.Rectangle // Extent of the image. - pix []byte // Pixel bits. -} - -func (m *plan9Image) byteoffset(x, y int) int { - a := y * m.width - if m.depth < 8 { - // We need to always round down, but Go rounds toward zero. - np := 8 / m.depth - if x < 0 { - return a + (x-np+1)/np - } - return a + x/np - } - return a + x*(m.depth/8) -} - -func (m *plan9Image) Bounds() image.Rectangle { return m.rect } -func (m *plan9Image) ColorModel() color.Model { return color.AlphaModel } - -func (m *plan9Image) At(x, y int) color.Color { - if (image.Point{x, y}).In(m.rect) { - b := m.pix[m.byteoffset(x, y)] - switch m.depth { - case 1: - // CGrey, 1. - mask := uint8(1 << uint8(7-x&7)) - if (b & mask) != 0 { - return color.Alpha{0xff} - } - return color.Alpha{0x00} - case 2: - // CGrey, 2. - shift := uint(x&3) << 1 - // Place pixel at top of word. - y := b << shift - y &= 0xc0 - // Replicate throughout. - y |= y >> 2 - y |= y >> 4 - return color.Alpha{y} - } - } - return color.Alpha{0x00} -} - -var compressed = []byte("compressed\n") - -func parseImage(data []byte) (remainingData []byte, m *plan9Image, retErr error) { - if !bytes.HasPrefix(data, compressed) { - return nil, nil, errors.New("plan9font: unsupported uncompressed format") - } - data = data[len(compressed):] - - const hdrSize = 5 * 12 - if len(data) < hdrSize { - return nil, nil, errors.New("plan9font: invalid image: header too short") - } - hdr, data := data[:hdrSize], data[hdrSize:] - - // Distinguish new channel descriptor from old ldepth. Channel descriptors - // have letters as well as numbers, while ldepths are a single digit - // formatted as %-11d. - new := false - for m := 0; m < 10; m++ { - if hdr[m] != ' ' { - new = true - break - } - } - if hdr[11] != ' ' { - return nil, nil, errors.New("plan9font: invalid image: bad header") - } - if !new { - return nil, nil, errors.New("plan9font: unsupported ldepth format") - } - - depth := 0 - switch s := strings.TrimSpace(string(hdr[:1*12])); s { - default: - return nil, nil, fmt.Errorf("plan9font: unsupported pixel format %q", s) - case "k1": - depth = 1 - case "k2": - depth = 2 - } - r := ator(hdr[1*12:]) - if r.Min.X > r.Max.X || r.Min.Y > r.Max.Y { - return nil, nil, errors.New("plan9font: invalid image: bad rectangle") - } - - width := bytesPerLine(r, depth) - m = &plan9Image{ - depth: depth, - width: width, - rect: r, - pix: make([]byte, width*r.Dy()), - } - - miny := r.Min.Y - for miny != r.Max.Y { - if len(data) < 2*12 { - return nil, nil, errors.New("plan9font: invalid image: data band too short") - } - maxy := atoi(data[0*12:]) - nb := atoi(data[1*12:]) - data = data[2*12:] - - if len(data) < nb { - return nil, nil, errors.New("plan9font: invalid image: data band length mismatch") - } - buf := data[:nb] - data = data[nb:] - - if maxy <= miny || r.Max.Y < maxy { - return nil, nil, fmt.Errorf("plan9font: bad maxy %d", maxy) - } - // An old-format image would flip the bits here, but we don't support - // the old format. - rr := r - rr.Min.Y = miny - rr.Max.Y = maxy - if err := decompress(m, rr, buf); err != nil { - return nil, nil, err - } - miny = maxy - } - return data, m, nil -} - -// Compressed data are sequences of byte codes. If the first byte b has the -// 0x80 bit set, the next (b^0x80)+1 bytes are data. Otherwise, these two bytes -// specify a previous string to repeat. -const ( - compShortestMatch = 3 // shortest match possible. - compWindowSize = 1024 // window size. -) - -var ( - errDecompressBufferTooSmall = errors.New("plan9font: decompress: buffer too small") - errDecompressPhaseError = errors.New("plan9font: decompress: phase error") -) - -func decompress(m *plan9Image, r image.Rectangle, data []byte) error { - if !r.In(m.rect) { - return errors.New("plan9font: decompress: bad rectangle") - } - bpl := bytesPerLine(r, m.depth) - mem := make([]byte, compWindowSize) - memi := 0 - omemi := -1 - y := r.Min.Y - linei := m.byteoffset(r.Min.X, y) - eline := linei + bpl - datai := 0 - for { - if linei == eline { - y++ - if y == r.Max.Y { - break - } - linei = m.byteoffset(r.Min.X, y) - eline = linei + bpl - } - if datai == len(data) { - return errDecompressBufferTooSmall - } - c := data[datai] - datai++ - if c >= 128 { - for cnt := c - 128 + 1; cnt != 0; cnt-- { - if datai == len(data) { - return errDecompressBufferTooSmall - } - if linei == eline { - return errDecompressPhaseError - } - m.pix[linei] = data[datai] - linei++ - mem[memi] = data[datai] - memi++ - datai++ - if memi == len(mem) { - memi = 0 - } - } - } else { - if datai == len(data) { - return errDecompressBufferTooSmall - } - offs := int(data[datai]) + ((int(c) & 3) << 8) + 1 - datai++ - if memi < offs { - omemi = memi + (compWindowSize - offs) - } else { - omemi = memi - offs - } - for cnt := (c >> 2) + compShortestMatch; cnt != 0; cnt-- { - if linei == eline { - return errDecompressPhaseError - } - m.pix[linei] = mem[omemi] - linei++ - mem[memi] = mem[omemi] - memi++ - omemi++ - if omemi == len(mem) { - omemi = 0 - } - if memi == len(mem) { - memi = 0 - } - } - } - } - return nil -} - -func ator(b []byte) image.Rectangle { - return image.Rectangle{atop(b), atop(b[2*12:])} -} - -func atop(b []byte) image.Point { - return image.Pt(atoi(b), atoi(b[12:])) -} - -func atoi(b []byte) int { - i := 0 - for ; i < len(b) && b[i] == ' '; i++ { - } - n := 0 - for ; i < len(b) && '0' <= b[i] && b[i] <= '9'; i++ { - n = n*10 + int(b[i]) - '0' - } - return n -} - -func bytesPerLine(r image.Rectangle, depth int) int { - if depth <= 0 || 32 < depth { - panic("invalid depth") - } - var l int - if r.Min.X >= 0 { - l = (r.Max.X*depth + 7) / 8 - l -= (r.Min.X * depth) / 8 - } else { - // Make positive before divide. - t := (-r.Min.X*depth + 7) / 8 - l = t + (r.Max.X*depth+7)/8 - } - return l -} |