| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420 |
- // Copyright ©2021 The star-tex Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style
- // license that can be found in the LICENSE-STAR-TEX file.
- package pkf
- import (
- "fmt"
- "image"
- "modernc.org/knuth/internal/iobuf"
- )
- // Glyph represents a glyph contained in a PK font file.
- type Glyph struct {
- flag uint8
- code uint32 // character code
- wtfm uint32 // TFM width
- dx uint32 // horizontal escapement
- dy uint32 // vertical escapement
- width uint32 // width in pixels of the minimum bounding box
- height uint32 // height in pixels of the minimum bounding box
- xoff int32 // horizontal offset from the upper left pixel
- yoff int32 // vertical offset from the upper left pixel
- data []byte
- mask []byte
- }
- func (g *Glyph) unpack() {
- if g.mask != nil {
- return
- }
- gr := glyphReader{
- r: iobuf.NewReader(g.data),
- g: g,
- }
- g.mask = gr.unpack()
- }
- func (g *Glyph) Mask() image.Alpha {
- g.unpack()
- h := int(g.height)
- w := int(g.width)
- pix := make([]byte, 0, h*w)
- var i int
- for row := 0; row < h; row++ {
- for col := 0; col < w; col += 8 {
- v := g.mask[i]
- n := clip(w-col, 8)
- bit := uint8(1 << 7)
- for ; n > 0; n-- {
- switch {
- case v&bit != 0:
- pix = append(pix, 0xff)
- default:
- pix = append(pix, 0x00)
- }
- bit >>= 1
- }
- i++
- }
- }
- return image.Alpha{
- Stride: w,
- Pix: pix,
- Rect: image.Rect(0, 0, w, h),
- }
- }
- func (g *Glyph) Bounds() image.Rectangle {
- h := int(g.height)
- w := int(g.width)
- return image.Rect(0, 0, w, h)
- }
- func readGlyph(r *iobuf.Reader) (g Glyph, err error) {
- var (
- pos = r.Pos()
- raster uint32
- )
- g.flag = r.ReadU8()
- switch g.flag & 7 {
- case 0, 1, 2, 3:
- // 'short' character description.
- // flag[1] pl[1] cc[1] tfm[3] dm[1] w[1] h[1] hoff[+1] voff[+1]
- raster = uint32(g.flag&7)*(2<<7) + uint32(r.ReadU8()) - 4
- g.code = uint32(r.ReadU8())
- g.wtfm = r.ReadU24()
- g.dx = uint32(r.ReadU8()) * 65536
- g.dy = 0
- g.width = uint32(r.ReadU8())
- g.height = uint32(r.ReadU8())
- g.xoff = int32(r.ReadI8())
- g.yoff = int32(r.ReadI8())
- raster -= 4
- case 4, 5, 6:
- // 'extended short' character description.
- // flag[1] pl[2] cc[1] tfm[3] dm[2] w[2] h[2] hoff[+2] voff[+2].
- raster = uint32(g.flag&3)*(2<<15) + uint32(r.ReadU16()) - 5
- g.code = uint32(r.ReadU8())
- g.wtfm = r.ReadU24()
- g.dx = uint32(r.ReadU16()) * 65536
- g.dy = 0
- g.width = uint32(r.ReadU16())
- g.height = uint32(r.ReadU16())
- g.xoff = int32(r.ReadI16())
- g.yoff = int32(r.ReadI16())
- raster -= 4 * 2
- case 7:
- // 'long' character description.
- // flag[1] pl[4] cc[4] tfm[4] dx[4] dy[4] w[4] h[4] hoff[4] voff[4]
- raster = r.ReadU32() - 12
- g.code = r.ReadU32()
- g.wtfm = r.ReadU32()
- g.dx = r.ReadU32()
- g.dy = r.ReadU32()
- g.width = r.ReadU32()
- g.height = r.ReadU32()
- g.xoff = int32(r.ReadU32())
- g.yoff = int32(r.ReadU32())
- raster -= 4 * 4
- }
- g.data = r.ReadBuf(int(raster))
- g.mask = nil
- if false {
- dynf := g.flag / 16
- fmt.Printf(
- "%d: Flag byte = %d Character = %d Packet length = %d\n"+
- " Dynamic packing variable = %d\n"+
- " TFM width = %d dx = %d%s\n"+
- " Height = %d Width = %d X-offset = %d Y-offset = %d\n",
- pos, g.flag, g.code, raster,
- dynf,
- g.wtfm, g.dx, func() string {
- switch g.dy {
- case 0:
- return " "
- default:
- return fmt.Sprintf(" dy = %d", g.dy)
- }
- }(),
- g.height, g.width, g.xoff, g.yoff,
- )
- }
- return g, err
- }
- type glyphReader struct {
- r *iobuf.Reader
- g *Glyph
- inputbyte uint16
- bitweight uint16
- dynf uint32
- repeat uint32
- remainder int32
- read func() uint32
- }
- func (gr *glyphReader) init() {
- gr.r.SetPos(0)
- gr.repeat = 0
- gr.inputbyte = 0
- gr.bitweight = 0
- gr.dynf = uint32(gr.g.flag / 16)
- gr.read = gr.pknum
- }
- var gpower = [17]uint16{
- 0, 1, 3, 7, 15, 31, 63, 127,
- 255, 511, 1023, 2047, 4095, 8191, 16383, 32767, 65535,
- }
- func (gr *glyphReader) unpack() []byte {
- var (
- wordwidth = int16((gr.g.width + 15) / 16)
- word uint16
- wordweight uint16
- rowsleft int16
- turnon = gr.g.flag&8 != 0
- hbit int16
- count uint16
- mask []uint8
- )
- gr.init()
- sz := 2 * gr.g.height * uint32(wordwidth)
- if sz <= 0 {
- sz = 2
- }
- var (
- idx int
- sli = make([]uint16, sz/2+1) // divide by 2: sz is in bytes
- raster = sli[1:]
- )
- switch gr.dynf {
- case 14:
- gr.bitweight = 0
- for i := 0; i < int(gr.g.height); i++ {
- word = 0
- wordweight = 32768
- for j := 0; j < int(gr.g.width); j++ {
- if gr.getbit() {
- word += wordweight
- }
- wordweight >>= 1
- if wordweight == 0 {
- raster[idx] = word
- idx++
- word = 0
- wordweight = 32768
- }
- }
- if wordweight != 32768 {
- raster[idx] = word
- idx++
- }
- }
- default:
- rowsleft = int16(gr.g.height)
- hbit = int16(gr.g.width)
- wordweight = 16
- word = 0
- for rowsleft > 0 {
- count = uint16(gr.read())
- for count != 0 {
- switch {
- case count < wordweight && count < uint16(hbit):
- if turnon {
- word += gpower[wordweight] - gpower[wordweight-count]
- }
- hbit -= int16(count)
- wordweight -= count
- count = 0
- case count >= uint16(hbit) && uint16(hbit) <= wordweight:
- if turnon {
- word += gpower[wordweight] - gpower[wordweight-uint16(hbit)]
- }
- raster[idx] = word
- idx++
- for i := 0; i < int(gr.repeat); i++ {
- for j := 0; j < int(wordwidth); j++ {
- raster[idx] = raster[idx-int(wordwidth)]
- idx++
- }
- }
- rowsleft -= int16(gr.repeat) + 1
- gr.repeat = 0
- word = 0
- wordweight = 16
- count -= uint16(hbit)
- hbit = int16(gr.g.width)
- default:
- if turnon {
- word += gpower[wordweight]
- }
- raster[idx] = word
- idx++
- word = 0
- count -= wordweight
- hbit -= int16(wordweight)
- wordweight = 16
- }
- }
- turnon = !turnon
- }
- if rowsleft != 0 || hbit != int16(gr.g.width) {
- panic(fmt.Errorf("error while unpacking: more bits than required: rowsleft=%d hbit=%d width=%d",
- rowsleft, hbit, gr.g.width,
- ))
- }
- }
- {
- // build raster data
- var (
- widx = 0
- word = sli
- )
- for row := 0; row < int(gr.g.height); row++ {
- var (
- bitsleft uint8
- nextword uint16
- nextbyte uint8
- )
- for col := 0; col < int(gr.g.width); col += 8 {
- switch {
- case bitsleft >= 8:
- nextbyte = uint8(nextword >> (bitsleft - 8) & 0xff)
- bitsleft -= 8
- mask = append(mask, nextbyte)
- default:
- nextbyte = uint8(nextword << (8 - bitsleft) & 0xff)
- widx++
- nextword = word[widx]
- nextbyte = nextbyte | uint8(nextword>>(16-(8-bitsleft))&0xff)
- bitsleft = 16 - (8 - bitsleft)
- mask = append(mask, nextbyte)
- }
- }
- }
- }
- return mask
- }
- func (gr *glyphReader) pkbyte() uint16 {
- return uint16(gr.r.ReadU8())
- }
- func (gr *glyphReader) pknum() uint32 {
- var (
- i, j uint16
- dynf = uint16(gr.dynf)
- )
- i = uint16(gr.nyb())
- switch {
- case i == 0:
- for {
- j = uint16(gr.nyb())
- i++
- if j != 0 {
- break
- }
- }
- switch {
- case i > 3:
- return gr.huge(i, j)
- default:
- for i > 0 {
- j = j*16 + uint16(gr.nyb())
- i--
- }
- return uint32(j - 15 + (13-dynf)*16 + dynf)
- }
- case i <= dynf:
- return uint32(i)
- case i < 14:
- v := dynf + 1
- return uint32((i-v)*16 + uint16(gr.nyb()) + v)
- default:
- switch i {
- case 14:
- gr.repeat = gr.pknum()
- default:
- gr.repeat = 1
- }
- return gr.read()
- }
- }
- func (gr *glyphReader) rest() uint32 {
- switch {
- case gr.remainder < 0:
- gr.remainder = -gr.remainder
- return 0
- case gr.remainder > 0:
- switch {
- case gr.remainder > 4000:
- gr.remainder = 4000 - gr.remainder
- return 4000
- default:
- i := uint32(gr.remainder)
- gr.remainder = 0
- gr.read = gr.pknum
- return i
- }
- }
- panic("impossible")
- }
- func (gr *glyphReader) huge(i, k uint16) uint32 {
- var (
- j = k
- dynf = int32(gr.dynf)
- )
- for i != 0 {
- j = (j << 4) + uint16(gr.nyb())
- i--
- }
- gr.remainder = int32(j) - 15 + (13-dynf)*16 + dynf
- gr.read = gr.rest
- return gr.rest()
- }
- func (gr *glyphReader) nyb() int16 {
- var v uint16
- switch gr.bitweight {
- case 0:
- gr.bitweight = 16
- gr.inputbyte = gr.pkbyte()
- v = gr.inputbyte >> 4
- default:
- gr.bitweight = 0
- v = gr.inputbyte & 15
- }
- return int16(v)
- }
- func (gr *glyphReader) getbit() bool {
- gr.bitweight >>= 1
- if gr.bitweight == 0 {
- gr.inputbyte = gr.pkbyte()
- gr.bitweight = 128
- }
- return gr.inputbyte&gr.bitweight != 0
- }
|