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 }