dvi.go 2.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Copyright ©2021 The star-tex 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-STAR-TEX file.
  4. // Package dvi implements encoding and decoding DVI documents.
  5. //
  6. // More informations about the DVI standard can be found here:
  7. //
  8. // - https://ctan.crest.fr/tex-archive/dviware/driv-standard/level-0/dvistd0.pdf
  9. package dvi // import "modernc.org/knuth/dvi"
  10. import (
  11. "errors"
  12. "fmt"
  13. "image/color"
  14. "io"
  15. "modernc.org/knuth/internal/iobuf"
  16. )
  17. // Renderer defines the protocol to draw a DVI document.
  18. type Renderer interface {
  19. Init(pre *CmdPre, post *CmdPost)
  20. BOP(bop *CmdBOP)
  21. EOP()
  22. DrawGlyph(x, y int32, font Font, glyph rune, c color.Color)
  23. DrawRule(x, y, w, h int32, c color.Color)
  24. }
  25. type nopRenderer struct{}
  26. func (nopRenderer) Init(pre *CmdPre, post *CmdPost) {}
  27. func (nopRenderer) BOP(cmd *CmdBOP) {}
  28. func (nopRenderer) EOP() {}
  29. func (nopRenderer) DrawGlyph(x, y int32, font Font, glyph rune, c color.Color) {}
  30. func (nopRenderer) DrawRule(x, y, w, h int32, c color.Color) {}
  31. var (
  32. _ Renderer = (*nopRenderer)(nil)
  33. )
  34. // Dump reads r until EOF and calls f for each decoded DVI command.
  35. func Dump(r io.Reader, f func(cmd Cmd) error) error {
  36. buf, err := io.ReadAll(r)
  37. if err != nil {
  38. return fmt.Errorf("dvi: could not read DVI program: %w", err)
  39. }
  40. rr := iobuf.NewReader(buf)
  41. for {
  42. var (
  43. op = opCode(rr.PeekU8())
  44. cmd = op.cmd()
  45. )
  46. if cmd == nil {
  47. return fmt.Errorf("dvi: unknown opcode %v (v=0x%x)", op, op)
  48. }
  49. cmd.read(rr)
  50. err = f(cmd)
  51. if err != nil {
  52. return fmt.Errorf("dvi: could not call user provided function: %w", err)
  53. }
  54. if cmd.opcode() == opPostPost {
  55. break
  56. }
  57. }
  58. return nil
  59. }
  60. // Handler handles special DVI XXXn commands.
  61. // Users can customize how a DVI Machine will handle these commands.
  62. //
  63. // Special commands are usually written in DVI files with an opaque payload
  64. // of bytes, starting with a "well known" prefix.
  65. // Ex:
  66. //
  67. // color push gray 0
  68. // color pop
  69. // color push BurntOrange
  70. //
  71. // A Handler should return ErrSkipHandler if does not know how to handle a given
  72. // special command data.
  73. type Handler interface {
  74. // Handle handles a special DVI command.
  75. Handle(p []byte) error
  76. }
  77. // ErrSkipHandler is used as a return value from Handler.Handle to indicate
  78. // that the Handler should be skipped and is not suited to handle that special
  79. // command.
  80. var ErrSkipHandler = errors.New("dvi: skip handler")