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 }