machine.go 26 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175
  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
  5. import (
  6. "errors"
  7. "fmt"
  8. "io"
  9. "sort"
  10. "strings"
  11. "modernc.org/knuth/font/fixed"
  12. "modernc.org/knuth/font/tfm"
  13. "modernc.org/knuth/kpath"
  14. )
  15. const (
  16. maxdrift = 2
  17. )
  18. // Machine defines a DVI machine, handling DVI registers and DVI commands.
  19. type Machine struct {
  20. rdr Renderer
  21. ktx kpath.Context
  22. state state
  23. conv float32 // converts DVI units to pixels
  24. trueConv float32 // converts unmagnified DVI units to pixels
  25. xoff int32 // width offset
  26. yoff int32 // height offset
  27. w io.Writer
  28. buf []byte // 80-col buffer of text
  29. handlers []Handler // list of registered special handlers for CmdXXXn commands.
  30. color colorHandler // special handling of colors
  31. }
  32. // NewMachine creates a new DVI machine.
  33. func NewMachine(opts ...Option) Machine {
  34. cfg := newConfig()
  35. for _, opt := range opts {
  36. err := opt(cfg)
  37. if err != nil {
  38. panic(err)
  39. }
  40. }
  41. m := Machine{
  42. ktx: cfg.ctx,
  43. rdr: cfg.rdr,
  44. state: newState(),
  45. xoff: cfg.xoff,
  46. yoff: cfg.yoff,
  47. w: cfg.out,
  48. buf: make([]byte, 0, 80-len("[]\n")),
  49. handlers: cfg.handlers,
  50. color: nilColorHandler{},
  51. }
  52. for _, h := range m.handlers {
  53. if hh, ok := h.(colorHandler); ok {
  54. m.color = hh
  55. break
  56. }
  57. }
  58. return m
  59. }
  60. // Run executes the whole DVI program on this DVI machine.
  61. func (m *Machine) Run(p Program) error {
  62. m.load(p)
  63. for i := range p.pages {
  64. err := m.run(p, i)
  65. if err != nil {
  66. return fmt.Errorf("dvi: could not process page %d: %w", i+1, err)
  67. }
  68. }
  69. return nil
  70. }
  71. func (m *Machine) load(p Program) {
  72. m.printf("numerator/denominator=%d/%d\n", p.pre.Num, p.pre.Den)
  73. res := float32(300.0)
  74. conv := float32(p.pre.Num) / 254000.0 * (res / float32(p.pre.Den))
  75. m.trueConv = conv
  76. m.conv = conv * float32(p.pre.Mag) / 1000.0
  77. m.printf("magnification=%d; %16.8f pixels per DVI unit\n", p.pre.Mag, m.conv)
  78. m.printf("'%s'\n", p.pre.Msg)
  79. m.printf("Postamble starts at byte %d.\n", p.ppost)
  80. m.printf("maxv=%d, maxh=%d, maxstackdepth=%d, totalpages=%d\n",
  81. p.post.Height, p.post.Width, p.post.MaxStack,
  82. p.post.Pages,
  83. )
  84. m.state.fonts = p.fonts
  85. fonts := make([]int, 0, len(p.fonts))
  86. for id := range p.fonts {
  87. fonts = append(fonts, id)
  88. }
  89. sort.Sort(sort.Reverse(sort.IntSlice(fonts)))
  90. for _, id := range fonts {
  91. fnt := m.state.fonts[id]
  92. m.printf(
  93. "Font %d: %s---loaded at size %d DVI units \n",
  94. id, fnt.Name, fnt.Size,
  95. )
  96. }
  97. }
  98. func (m *Machine) run(p Program, ip int) error {
  99. var (
  100. beg = int(p.pages[ip].beg)
  101. end = int(p.pages[ip].end)
  102. eop = false
  103. )
  104. m.rdr.Init(&p.pre, &p.post)
  105. p.r.SetPos(beg)
  106. op := opCode(p.r.PeekU8())
  107. if op != opBOP {
  108. return errNoBOP
  109. }
  110. bop := op.cmd().(*CmdBOP)
  111. bop.read(p.r)
  112. m.state.reset(m.xoff, m.yoff, m.pixels)
  113. m.printf(" \n%d: beginning of page %d \n", beg, bop.C0)
  114. m.rdr.BOP(bop)
  115. for p.r.Pos() < end {
  116. pos := p.r.Pos()
  117. switch op := opCode(p.r.PeekU8()); op {
  118. case opBOP, opPre, opPost, opPostPost:
  119. return fmt.Errorf("dvi: invalid opcode=%s inside a page", op.cmd().Name())
  120. case opEOP:
  121. eop = true
  122. m.flushText()
  123. m.printf("%d: eop", pos)
  124. op.cmd().read(p.r)
  125. m.rdr.EOP()
  126. lvl := len(m.state.stack) - 1
  127. if lvl != 0 {
  128. m.printf("stack not empty at end of page (level %d)!\n", lvl)
  129. }
  130. case opSetChar000, opSetChar001, opSetChar002, opSetChar003, opSetChar004,
  131. opSetChar005, opSetChar006, opSetChar007, opSetChar008, opSetChar009,
  132. opSetChar010, opSetChar011, opSetChar012, opSetChar013, opSetChar014,
  133. opSetChar015, opSetChar016, opSetChar017, opSetChar018, opSetChar019,
  134. opSetChar020, opSetChar021, opSetChar022, opSetChar023, opSetChar024,
  135. opSetChar025, opSetChar026, opSetChar027, opSetChar028, opSetChar029,
  136. opSetChar030, opSetChar031, opSetChar032, opSetChar033, opSetChar034,
  137. opSetChar035, opSetChar036, opSetChar037, opSetChar038, opSetChar039,
  138. opSetChar040, opSetChar041, opSetChar042, opSetChar043, opSetChar044,
  139. opSetChar045, opSetChar046, opSetChar047, opSetChar048, opSetChar049,
  140. opSetChar050, opSetChar051, opSetChar052, opSetChar053, opSetChar054,
  141. opSetChar055, opSetChar056, opSetChar057, opSetChar058, opSetChar059,
  142. opSetChar060, opSetChar061, opSetChar062, opSetChar063, opSetChar064,
  143. opSetChar065, opSetChar066, opSetChar067, opSetChar068, opSetChar069,
  144. opSetChar070, opSetChar071, opSetChar072, opSetChar073, opSetChar074,
  145. opSetChar075, opSetChar076, opSetChar077, opSetChar078, opSetChar079,
  146. opSetChar080, opSetChar081, opSetChar082, opSetChar083, opSetChar084,
  147. opSetChar085, opSetChar086, opSetChar087, opSetChar088, opSetChar089,
  148. opSetChar090, opSetChar091, opSetChar092, opSetChar093, opSetChar094,
  149. opSetChar095, opSetChar096, opSetChar097, opSetChar098, opSetChar099,
  150. opSetChar100, opSetChar101, opSetChar102, opSetChar103, opSetChar104,
  151. opSetChar105, opSetChar106, opSetChar107, opSetChar108, opSetChar109,
  152. opSetChar110, opSetChar111, opSetChar112, opSetChar113, opSetChar114,
  153. opSetChar115, opSetChar116, opSetChar117, opSetChar118, opSetChar119,
  154. opSetChar120, opSetChar121, opSetChar122, opSetChar123, opSetChar124,
  155. opSetChar125, opSetChar126, opSetChar127:
  156. cmd := op.cmd().(*CmdSetChar)
  157. cmd.read(p.r)
  158. switch {
  159. case cmd.Value > ' ' && cmd.Value <= '~':
  160. m.outText(cmd.Value)
  161. default:
  162. m.flushText()
  163. }
  164. m.printf("%d: %s", pos, strings.Replace(cmd.Name(), "_", "", -1))
  165. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  166. if err != nil {
  167. return fmt.Errorf("could not set char %q: %w", op, err)
  168. }
  169. case opSet1:
  170. cmd := op.cmd().(*CmdSet1)
  171. cmd.read(p.r)
  172. m.flushText()
  173. m.printf("%d: set1 %d", pos, cmd.Value)
  174. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  175. if err != nil {
  176. return fmt.Errorf("could not set1: %w", err)
  177. }
  178. case opSet2:
  179. cmd := op.cmd().(*CmdSet2)
  180. cmd.read(p.r)
  181. m.flushText()
  182. m.printf("%d: set2 %d", pos, cmd.Value)
  183. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  184. if err != nil {
  185. return fmt.Errorf("could not set2: %w", err)
  186. }
  187. case opSet3:
  188. cmd := op.cmd().(*CmdSet3)
  189. cmd.read(p.r)
  190. m.flushText()
  191. m.printf("%d: set3 %d", pos, cmd.Value)
  192. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  193. if err != nil {
  194. return fmt.Errorf("could not set3: %w", err)
  195. }
  196. case opSet4:
  197. cmd := op.cmd().(*CmdSet4)
  198. cmd.read(p.r)
  199. m.flushText()
  200. m.printf("%d: set4 %d", pos, cmd.Value)
  201. err := m.drawGlyph(cmd.opcode(), cmd.Value)
  202. if err != nil {
  203. return fmt.Errorf("could not set4: %w", err)
  204. }
  205. case opSetRule:
  206. cmd := op.cmd().(*CmdSetRule)
  207. cmd.read(p.r)
  208. m.flushText()
  209. m.printf("%d: setrule", pos)
  210. err := m.drawRule(cmd.opcode(), cmd.Height, cmd.Width)
  211. if err != nil {
  212. return fmt.Errorf("could not setrule(%d, %d): %w", cmd.Height, cmd.Width, err)
  213. }
  214. case opPut1:
  215. cmd := op.cmd().(*CmdPut1)
  216. cmd.read(p.r)
  217. m.flushText()
  218. m.printf("%d: put1 %d", pos, cmd.Value)
  219. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  220. if err != nil {
  221. return fmt.Errorf("could not put1(%d): %w", cmd.Value, err)
  222. }
  223. case opPut2:
  224. cmd := op.cmd().(*CmdPut2)
  225. cmd.read(p.r)
  226. m.flushText()
  227. m.printf("%d: put2 %d", pos, cmd.Value)
  228. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  229. if err != nil {
  230. return fmt.Errorf("could not put2(%d): %w", cmd.Value, err)
  231. }
  232. case opPut3:
  233. cmd := op.cmd().(*CmdPut3)
  234. cmd.read(p.r)
  235. m.flushText()
  236. m.printf("%d: put3 %d", pos, cmd.Value)
  237. err := m.drawGlyph(cmd.opcode(), int32(cmd.Value))
  238. if err != nil {
  239. return fmt.Errorf("could not put3(%d): %w", cmd.Value, err)
  240. }
  241. case opPut4:
  242. cmd := op.cmd().(*CmdPut4)
  243. cmd.read(p.r)
  244. m.flushText()
  245. m.printf("%d: put4 %d", pos, cmd.Value)
  246. err := m.drawGlyph(cmd.opcode(), cmd.Value)
  247. if err != nil {
  248. return fmt.Errorf("could not put4(%d): %w", cmd.Value, err)
  249. }
  250. case opPutRule:
  251. cmd := op.cmd().(*CmdPutRule)
  252. cmd.read(p.r)
  253. m.flushText()
  254. m.printf("%d: putrule", pos)
  255. err := m.drawRule(cmd.opcode(), cmd.Height, cmd.Width)
  256. if err != nil {
  257. return fmt.Errorf("could not putrule(%d, %d): %w", cmd.Height, cmd.Width, err)
  258. }
  259. case opPush:
  260. m.flushText()
  261. m.printf("%d: push \n", pos)
  262. lvl := len(m.state.stack) - 1
  263. op.cmd().(*CmdPush).read(p.r)
  264. m.state.push()
  265. cur := m.state.cur()
  266. m.printf("level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=%d,vv=%d)",
  267. lvl,
  268. cur.h, cur.v, cur.w, cur.x, cur.y, cur.z,
  269. cur.hh, cur.vv,
  270. )
  271. case opPop:
  272. m.flushText()
  273. m.printf("%d: pop \n", pos)
  274. op.cmd().(*CmdPop).read(p.r)
  275. m.state.pop()
  276. lvl := len(m.state.stack) - 1
  277. cur := m.state.cur()
  278. m.printf("level %d:(h=%d,v=%d,w=%d,x=%d,y=%d,z=%d,hh=%d,vv=%d)",
  279. lvl,
  280. cur.h, cur.v, cur.w, cur.x, cur.y, cur.z,
  281. cur.hh, cur.vv,
  282. )
  283. case opRight1:
  284. cmd := op.cmd().(*CmdRight1)
  285. cmd.read(p.r)
  286. cur := m.state.cur()
  287. cur.hh = m.outSpace(cmd.Value)
  288. m.printf("%d: right1 %d", pos, cmd.Value)
  289. err := m.moveright(cmd.Value)
  290. if err != nil {
  291. return fmt.Errorf("could not right1(%d): %w", cmd.Value, err)
  292. }
  293. case opRight2:
  294. cmd := op.cmd().(*CmdRight2)
  295. cmd.read(p.r)
  296. cur := m.state.cur()
  297. cur.hh = m.outSpace(cmd.Value)
  298. m.printf("%d: right2 %d", pos, cmd.Value)
  299. err := m.moveright(cmd.Value)
  300. if err != nil {
  301. return fmt.Errorf("could not right2(%d): %w", cmd.Value, err)
  302. }
  303. case opRight3:
  304. cmd := op.cmd().(*CmdRight3)
  305. cmd.read(p.r)
  306. cur := m.state.cur()
  307. cur.hh = m.outSpace(cmd.Value)
  308. m.printf("%d: right3 %d", pos, cmd.Value)
  309. err := m.moveright(cmd.Value)
  310. if err != nil {
  311. return fmt.Errorf("could not right3(%d): %w", cmd.Value, err)
  312. }
  313. case opRight4:
  314. cmd := op.cmd().(*CmdRight4)
  315. cmd.read(p.r)
  316. cur := m.state.cur()
  317. cur.hh = m.outSpace(cmd.Value)
  318. m.printf("%d: right4 %d", pos, cmd.Value)
  319. err := m.moveright(cmd.Value)
  320. if err != nil {
  321. return fmt.Errorf("could not right4(%d): %w", cmd.Value, err)
  322. }
  323. case opW0:
  324. cmd := op.cmd().(*CmdW0)
  325. cmd.read(p.r)
  326. cur := m.state.cur()
  327. cur.hh = m.outSpace(cur.w)
  328. m.printf("%d: w0 %d", pos, cur.w)
  329. err := m.moveright(cur.w)
  330. if err != nil {
  331. return fmt.Errorf("could not w0(%d): %w", cur.w, err)
  332. }
  333. case opW1:
  334. cmd := op.cmd().(*CmdW1)
  335. cmd.read(p.r)
  336. cur := m.state.cur()
  337. cur.w = cmd.Value
  338. cur.hh = m.outSpace(cmd.Value)
  339. m.printf("%d: w1 %d", pos, cmd.Value)
  340. err := m.moveright(cmd.Value)
  341. if err != nil {
  342. return fmt.Errorf("could not w1(%d): %w", cmd.Value, err)
  343. }
  344. case opW2:
  345. cmd := op.cmd().(*CmdW2)
  346. cmd.read(p.r)
  347. cur := m.state.cur()
  348. cur.w = cmd.Value
  349. cur.hh = m.outSpace(cmd.Value)
  350. m.printf("%d: w2 %d", pos, cmd.Value)
  351. err := m.moveright(cmd.Value)
  352. if err != nil {
  353. return fmt.Errorf("could not w2(%d): %w", cmd.Value, err)
  354. }
  355. case opW3:
  356. cmd := op.cmd().(*CmdW3)
  357. cmd.read(p.r)
  358. cur := m.state.cur()
  359. cur.w = cmd.Value
  360. cur.hh = m.outSpace(cmd.Value)
  361. m.printf("%d: w3 %d", pos, cmd.Value)
  362. err := m.moveright(cmd.Value)
  363. if err != nil {
  364. return fmt.Errorf("could not w3(%d): %w", cmd.Value, err)
  365. }
  366. case opW4:
  367. cmd := op.cmd().(*CmdW4)
  368. cmd.read(p.r)
  369. cur := m.state.cur()
  370. cur.w = cmd.Value
  371. cur.hh = m.outSpace(cmd.Value)
  372. m.printf("%d: w4 %d", pos, cmd.Value)
  373. err := m.moveright(cmd.Value)
  374. if err != nil {
  375. return fmt.Errorf("could not w4(%d): %w", cmd.Value, err)
  376. }
  377. case opX0:
  378. cmd := op.cmd().(*CmdX0)
  379. cmd.read(p.r)
  380. cur := m.state.cur()
  381. cur.hh = m.outSpace(cur.x)
  382. m.printf("%d: x0 %d", pos, cur.x)
  383. err := m.moveright(cur.x)
  384. if err != nil {
  385. return fmt.Errorf("could not x0(%d): %w", cur.x, err)
  386. }
  387. case opX1:
  388. cmd := op.cmd().(*CmdX1)
  389. cmd.read(p.r)
  390. cur := m.state.cur()
  391. cur.x = cmd.Value
  392. cur.hh = m.outSpace(cmd.Value)
  393. m.printf("%d: x1 %d", pos, cmd.Value)
  394. err := m.moveright(cmd.Value)
  395. if err != nil {
  396. return fmt.Errorf("could not x1(%d): %w", cmd.Value, err)
  397. }
  398. case opX2:
  399. cmd := op.cmd().(*CmdX2)
  400. cmd.read(p.r)
  401. cur := m.state.cur()
  402. cur.x = cmd.Value
  403. cur.hh = m.outSpace(cmd.Value)
  404. m.printf("%d: x2 %d", pos, cmd.Value)
  405. err := m.moveright(cmd.Value)
  406. if err != nil {
  407. return fmt.Errorf("could not x2(%d): %w", cmd.Value, err)
  408. }
  409. case opX3:
  410. cmd := op.cmd().(*CmdX3)
  411. cmd.read(p.r)
  412. cur := m.state.cur()
  413. cur.x = cmd.Value
  414. cur.hh = m.outSpace(cmd.Value)
  415. m.printf("%d: x3 %d", pos, cmd.Value)
  416. err := m.moveright(cmd.Value)
  417. if err != nil {
  418. return fmt.Errorf("could not x3(%d): %w", cmd.Value, err)
  419. }
  420. case opX4:
  421. cmd := op.cmd().(*CmdX4)
  422. cmd.read(p.r)
  423. cur := m.state.cur()
  424. cur.x = cmd.Value
  425. cur.hh = m.outSpace(cmd.Value)
  426. m.printf("%d: x4 %d", pos, cmd.Value)
  427. err := m.moveright(cmd.Value)
  428. if err != nil {
  429. return fmt.Errorf("could not x4(%d): %w", cmd.Value, err)
  430. }
  431. case opDown1:
  432. cmd := op.cmd().(*CmdDown1)
  433. cmd.read(p.r)
  434. cur := m.state.cur()
  435. cur.vv = m.outVMove(cmd.Value)
  436. m.flushText()
  437. m.printf("%d: down1 %d", pos, cmd.Value)
  438. err := m.movedown(cmd.Value)
  439. if err != nil {
  440. return fmt.Errorf("could not down1(%d): %w", cmd.Value, err)
  441. }
  442. case opDown2:
  443. cmd := op.cmd().(*CmdDown2)
  444. cmd.read(p.r)
  445. cur := m.state.cur()
  446. cur.vv = m.outVMove(cmd.Value)
  447. m.flushText()
  448. m.printf("%d: down2 %d", pos, cmd.Value)
  449. err := m.movedown(cmd.Value)
  450. if err != nil {
  451. return fmt.Errorf("could not down2(%d): %w", cmd.Value, err)
  452. }
  453. case opDown3:
  454. cmd := op.cmd().(*CmdDown3)
  455. cmd.read(p.r)
  456. cur := m.state.cur()
  457. cur.vv = m.outVMove(cmd.Value)
  458. m.flushText()
  459. m.printf("%d: down3 %d", pos, cmd.Value)
  460. err := m.movedown(cmd.Value)
  461. if err != nil {
  462. return fmt.Errorf("could not down3(%d): %w", cmd.Value, err)
  463. }
  464. case opDown4:
  465. cmd := op.cmd().(*CmdDown4)
  466. cmd.read(p.r)
  467. cur := m.state.cur()
  468. cur.vv = m.outVMove(cmd.Value)
  469. m.flushText()
  470. m.printf("%d: down4 %d", pos, cmd.Value)
  471. err := m.movedown(cmd.Value)
  472. if err != nil {
  473. return fmt.Errorf("could not down4(%d): %w", cmd.Value, err)
  474. }
  475. case opY0:
  476. cmd := op.cmd().(*CmdY0)
  477. cmd.read(p.r)
  478. cur := m.state.cur()
  479. cur.vv = m.outVMove(cur.y)
  480. m.flushText()
  481. m.printf("%d: y0 %d", pos, cur.y)
  482. err := m.movedown(cur.y)
  483. if err != nil {
  484. return fmt.Errorf("could not y0(%d): %w", cur.y, err)
  485. }
  486. case opY1:
  487. cmd := op.cmd().(*CmdY1)
  488. cmd.read(p.r)
  489. cur := m.state.cur()
  490. cur.y = cmd.Value
  491. cur.vv = m.outVMove(cmd.Value)
  492. m.flushText()
  493. m.printf("%d: y1 %d", pos, cmd.Value)
  494. err := m.movedown(cmd.Value)
  495. if err != nil {
  496. return fmt.Errorf("could not y1(%d): %w", cmd.Value, err)
  497. }
  498. case opY2:
  499. cmd := op.cmd().(*CmdY2)
  500. cmd.read(p.r)
  501. cur := m.state.cur()
  502. cur.y = cmd.Value
  503. cur.vv = m.outVMove(cmd.Value)
  504. m.flushText()
  505. m.printf("%d: y2 %d", pos, cmd.Value)
  506. err := m.movedown(cmd.Value)
  507. if err != nil {
  508. return fmt.Errorf("could not y2(%d): %w", cmd.Value, err)
  509. }
  510. case opY3:
  511. cmd := op.cmd().(*CmdY3)
  512. cmd.read(p.r)
  513. cur := m.state.cur()
  514. cur.y = cmd.Value
  515. cur.vv = m.outVMove(cmd.Value)
  516. m.flushText()
  517. m.printf("%d: y3 %d", pos, cmd.Value)
  518. err := m.movedown(cmd.Value)
  519. if err != nil {
  520. return fmt.Errorf("could not y3(%d): %w", cmd.Value, err)
  521. }
  522. case opY4:
  523. cmd := op.cmd().(*CmdY4)
  524. cmd.read(p.r)
  525. cur := m.state.cur()
  526. cur.y = cmd.Value
  527. cur.vv = m.outVMove(cmd.Value)
  528. m.flushText()
  529. m.printf("%d: y4 %d", pos, cmd.Value)
  530. err := m.movedown(cmd.Value)
  531. if err != nil {
  532. return fmt.Errorf("could not y4(%d): %w", cmd.Value, err)
  533. }
  534. case opZ0:
  535. cmd := op.cmd().(*CmdZ0)
  536. cmd.read(p.r)
  537. cur := m.state.cur()
  538. cur.vv = m.outVMove(cur.z)
  539. m.flushText()
  540. m.printf("%d: z0 %d", pos, cur.z)
  541. err := m.movedown(cur.z)
  542. if err != nil {
  543. return fmt.Errorf("could not z0(%d): %w", cur.z, err)
  544. }
  545. case opZ1:
  546. cmd := op.cmd().(*CmdZ1)
  547. cmd.read(p.r)
  548. cur := m.state.cur()
  549. cur.z = cmd.Value
  550. cur.vv = m.outVMove(cmd.Value)
  551. m.flushText()
  552. m.printf("%d: z1 %d", pos, cmd.Value)
  553. err := m.movedown(cmd.Value)
  554. if err != nil {
  555. return fmt.Errorf("could not z1(%d): %w", cmd.Value, err)
  556. }
  557. case opZ2:
  558. cmd := op.cmd().(*CmdZ2)
  559. cmd.read(p.r)
  560. cur := m.state.cur()
  561. cur.z = cmd.Value
  562. cur.vv = m.outVMove(cmd.Value)
  563. m.flushText()
  564. m.printf("%d: z2 %d", pos, cmd.Value)
  565. err := m.movedown(cmd.Value)
  566. if err != nil {
  567. return fmt.Errorf("could not z2(%d): %w", cmd.Value, err)
  568. }
  569. case opZ3:
  570. cmd := op.cmd().(*CmdZ3)
  571. cmd.read(p.r)
  572. cur := m.state.cur()
  573. cur.z = cmd.Value
  574. cur.vv = m.outVMove(cmd.Value)
  575. m.flushText()
  576. m.printf("%d: z3 %d", pos, cmd.Value)
  577. err := m.movedown(cmd.Value)
  578. if err != nil {
  579. return fmt.Errorf("could not z3(%d): %w", cmd.Value, err)
  580. }
  581. case opZ4:
  582. cmd := op.cmd().(*CmdZ4)
  583. cmd.read(p.r)
  584. cur := m.state.cur()
  585. cur.z = cmd.Value
  586. cur.vv = m.outVMove(cmd.Value)
  587. m.flushText()
  588. m.printf("%d: z4 %d", pos, cmd.Value)
  589. err := m.movedown(cmd.Value)
  590. if err != nil {
  591. return fmt.Errorf("could not z4(%d): %w", cmd.Value, err)
  592. }
  593. case opFntNum00, opFntNum01, opFntNum02, opFntNum03, opFntNum04,
  594. opFntNum05, opFntNum06, opFntNum07, opFntNum08, opFntNum09,
  595. opFntNum10, opFntNum11, opFntNum12, opFntNum13, opFntNum14,
  596. opFntNum15, opFntNum16, opFntNum17, opFntNum18, opFntNum19,
  597. opFntNum20, opFntNum21, opFntNum22, opFntNum23, opFntNum24,
  598. opFntNum25, opFntNum26, opFntNum27, opFntNum28, opFntNum29,
  599. opFntNum30, opFntNum31, opFntNum32, opFntNum33, opFntNum34,
  600. opFntNum35, opFntNum36, opFntNum37, opFntNum38, opFntNum39,
  601. opFntNum40, opFntNum41, opFntNum42, opFntNum43, opFntNum44,
  602. opFntNum45, opFntNum46, opFntNum47, opFntNum48, opFntNum49,
  603. opFntNum50, opFntNum51, opFntNum52, opFntNum53, opFntNum54,
  604. opFntNum55, opFntNum56, opFntNum57, opFntNum58, opFntNum59,
  605. opFntNum60, opFntNum61, opFntNum62, opFntNum63:
  606. cmd := op.cmd().(*CmdFntNum)
  607. cmd.read(p.r)
  608. m.state.f = int(cmd.ID)
  609. m.flushText()
  610. m.printf(
  611. "%d: fntnum%d current font is %s",
  612. pos, cmd.ID, m.state.fonts[m.state.f].Name,
  613. )
  614. case opFnt1:
  615. cmd := op.cmd().(*CmdFnt1)
  616. cmd.read(p.r)
  617. m.state.f = int(cmd.ID)
  618. m.flushText()
  619. m.printf(
  620. "%d: fnt1 %d current font is %s",
  621. pos, cmd.ID, m.state.fonts[m.state.f].Name,
  622. )
  623. case opFnt2:
  624. cmd := op.cmd().(*CmdFnt2)
  625. cmd.read(p.r)
  626. m.state.f = int(cmd.ID)
  627. m.flushText()
  628. m.printf(
  629. "%d: fnt2 %d current font is %s",
  630. pos, cmd.ID, m.state.fonts[m.state.f].Name,
  631. )
  632. case opFnt3:
  633. cmd := op.cmd().(*CmdFnt3)
  634. cmd.read(p.r)
  635. m.state.f = int(cmd.ID)
  636. m.flushText()
  637. m.printf(
  638. "%d: fnt3 %d current font is %s",
  639. pos, cmd.ID, m.state.fonts[m.state.f].Name,
  640. )
  641. case opFnt4:
  642. cmd := op.cmd().(*CmdFnt4)
  643. cmd.read(p.r)
  644. m.state.f = int(cmd.ID)
  645. m.flushText()
  646. m.printf(
  647. "%d: fnt4 %d current font is %s",
  648. pos, cmd.ID, m.state.fonts[m.state.f].Name,
  649. )
  650. case opXXX1:
  651. cmd := op.cmd().(*CmdXXX1)
  652. cmd.read(p.r)
  653. m.flushText()
  654. m.printf("%d: xxx '%s'", pos, cmd.Value)
  655. err := m.handleSpecial(cmd.Value)
  656. if err != nil {
  657. return fmt.Errorf("could not xxx1 %q: %w", cmd.Value, err)
  658. }
  659. case opXXX2:
  660. cmd := op.cmd().(*CmdXXX2)
  661. cmd.read(p.r)
  662. m.flushText()
  663. m.printf("%d: xxx '%s'", pos, cmd.Value)
  664. err := m.handleSpecial(cmd.Value)
  665. if err != nil {
  666. return fmt.Errorf("could not xxx2 %q: %w", cmd.Value, err)
  667. }
  668. case opXXX3:
  669. cmd := op.cmd().(*CmdXXX3)
  670. cmd.read(p.r)
  671. m.flushText()
  672. m.printf("%d: xxx '%s'", pos, cmd.Value)
  673. err := m.handleSpecial(cmd.Value)
  674. if err != nil {
  675. return fmt.Errorf("could not xxx3 %q: %w", cmd.Value, err)
  676. }
  677. case opXXX4:
  678. cmd := op.cmd().(*CmdXXX4)
  679. cmd.read(p.r)
  680. m.flushText()
  681. m.printf("%d: xxx '%s'", pos, cmd.Value)
  682. err := m.handleSpecial(cmd.Value)
  683. if err != nil {
  684. return fmt.Errorf("could not xxx4 %q: %w", cmd.Value, err)
  685. }
  686. case opFntDef1:
  687. cmd := op.cmd().(*CmdFntDef1)
  688. cmd.read(p.r)
  689. m.flushText()
  690. m.printf("%d: fntdef1 %d: %s", pos, cmd.ID, cmd.Font)
  691. err := m.defineFont(int(cmd.ID), fntdef{
  692. ID: int(cmd.ID),
  693. Checksum: cmd.Checksum,
  694. Size: cmd.Size,
  695. Design: cmd.Design,
  696. Area: cmd.Area,
  697. Name: cmd.Font,
  698. })
  699. if err != nil {
  700. return fmt.Errorf("could not fntdef1 %d: %w", cmd.ID, err)
  701. }
  702. case opFntDef2:
  703. cmd := op.cmd().(*CmdFntDef2)
  704. cmd.read(p.r)
  705. m.flushText()
  706. m.printf("%d: fntdef2 %d: %s", pos, cmd.ID, cmd.Font)
  707. err := m.defineFont(int(cmd.ID), fntdef{
  708. ID: int(cmd.ID),
  709. Checksum: cmd.Checksum,
  710. Size: cmd.Size,
  711. Design: cmd.Design,
  712. Area: cmd.Area,
  713. Name: cmd.Font,
  714. })
  715. if err != nil {
  716. return fmt.Errorf("could not fntdef2 %d: %w", cmd.ID, err)
  717. }
  718. case opFntDef3:
  719. cmd := op.cmd().(*CmdFntDef3)
  720. cmd.read(p.r)
  721. m.flushText()
  722. m.printf("%d: fntdef3 %d: %s", pos, cmd.ID, cmd.Font)
  723. err := m.defineFont(int(cmd.ID), fntdef{
  724. ID: int(cmd.ID),
  725. Checksum: cmd.Checksum,
  726. Size: cmd.Size,
  727. Design: cmd.Design,
  728. Area: cmd.Area,
  729. Name: cmd.Font,
  730. })
  731. if err != nil {
  732. return fmt.Errorf("could not fntdef3 %d: %w", cmd.ID, err)
  733. }
  734. case opFntDef4:
  735. cmd := op.cmd().(*CmdFntDef4)
  736. cmd.read(p.r)
  737. m.flushText()
  738. m.printf("%d: fntdef4 %d: %s", pos, cmd.ID, cmd.Font)
  739. err := m.defineFont(int(cmd.ID), fntdef{
  740. ID: int(cmd.ID),
  741. Checksum: cmd.Checksum,
  742. Size: cmd.Size,
  743. Design: cmd.Design,
  744. Area: cmd.Area,
  745. Name: cmd.Font,
  746. })
  747. if err != nil {
  748. return fmt.Errorf("could not fntdef4 %d: %w", cmd.ID, err)
  749. }
  750. default:
  751. cmd := op.cmd()
  752. cmd.read(p.r)
  753. panic(fmt.Errorf("invalid dvi command %q (op=%d)", op.cmd().Name(), op))
  754. }
  755. m.printf(" \n")
  756. }
  757. if !eop {
  758. return errNoEOP
  759. }
  760. return nil
  761. }
  762. // drawGlyph finishes a command that either sets or puts a character.
  763. func (m *Machine) drawGlyph(op opCode, cmd int32) error {
  764. cur := m.state.cur()
  765. fnt, err := m.loadFont(m.state.f)
  766. if err != nil {
  767. return err
  768. }
  769. m.rdr.DrawGlyph(cur.h, cur.v, *fnt, cmd, m.color.Color())
  770. adv, ok := fnt.advance(cmd)
  771. if !ok {
  772. return fmt.Errorf("dvi: font %q has no glyph %c", fnt.name, cmd)
  773. }
  774. if op >= opPut1 {
  775. return nil
  776. }
  777. cur.hh += m.pixels(int32(adv))
  778. return m.moveright(int32(adv))
  779. }
  780. // drawRule finishes a command that either sets or puts a rule.
  781. func (m *Machine) drawRule(op opCode, height, width int32) error {
  782. m.printf(" height %d, width %d", height, width)
  783. switch {
  784. case height <= 0 || width <= 0:
  785. m.printf(" (invisible) ")
  786. default:
  787. m.printf(" (%dx%d pixels)", m.rulepixels(height), m.rulepixels(width))
  788. }
  789. cur := m.state.cur()
  790. m.rdr.DrawRule(cur.h, cur.v, width, height, m.color.Color())
  791. if op == opPutRule {
  792. return nil
  793. }
  794. cur.hh += m.rulepixels(width)
  795. m.printf(" \n")
  796. return m.moveright(width)
  797. }
  798. // moveright finishes a command that sets h += q.
  799. func (m *Machine) moveright(q int32) error {
  800. cur := m.state.cur()
  801. old := cur.h
  802. hhh := m.pixels(cur.h + q)
  803. if absI32(hhh-cur.hh) > maxdrift {
  804. switch {
  805. case hhh > cur.hh:
  806. cur.hh = hhh - maxdrift
  807. default:
  808. cur.hh = hhh + maxdrift
  809. }
  810. }
  811. cur.h += q
  812. m.printf(" h:=%d%+d=%d, hh:=%d", old, q, cur.h, cur.hh)
  813. return nil
  814. }
  815. // movedown finishes a command that sets v += q.
  816. func (m *Machine) movedown(q int32) error {
  817. cur := m.state.cur()
  818. old := cur.v
  819. vvv := m.pixels(cur.v + q)
  820. if absI32(vvv-cur.vv) > maxdrift {
  821. switch {
  822. case vvv > cur.vv:
  823. cur.vv = vvv - maxdrift
  824. default:
  825. cur.vv = vvv + maxdrift
  826. }
  827. }
  828. cur.v += q
  829. m.printf(" v:=%d%+d=%d, vv:=%d", old, q, cur.v, cur.vv)
  830. return nil
  831. }
  832. func roundF32(v float32) int32 {
  833. if v > 0 {
  834. return int32(v + 0.5)
  835. }
  836. return int32(v - 0.5)
  837. }
  838. func absI32(v int32) int32 {
  839. if v < 0 {
  840. return -v
  841. }
  842. return v
  843. }
  844. func (m *Machine) pixels(v int32) int32 {
  845. x := m.conv * float32(v)
  846. return roundF32(x)
  847. }
  848. func (m *Machine) rulepixels(v int32) int32 {
  849. x := int32(m.conv * float32(v))
  850. if float32(x) < m.conv*float32(v) {
  851. return x + 1
  852. }
  853. return x
  854. }
  855. func (m *Machine) defineFont(i int, def fntdef) error {
  856. var (
  857. scale = def.Size
  858. design = def.Design
  859. mag int32
  860. )
  861. switch {
  862. case scale <= 0 || design <= 0:
  863. mag = 1000
  864. default:
  865. mag = roundF32((1000 * m.conv * float32(scale)) / (m.trueConv * float32(design)))
  866. }
  867. design = roundF32((100 * m.conv * float32(scale)) / (m.trueConv * float32(design)))
  868. def.mag = mag
  869. def.Size = scale
  870. m.state.fonts[i] = def
  871. _, err := m.loadFont(i)
  872. if err != nil {
  873. return fmt.Errorf("could not load font %q: %w", def.Name, err)
  874. }
  875. return nil
  876. }
  877. func (m *Machine) loadFont(i int) (*Font, error) {
  878. def := m.state.fonts[i]
  879. if def.font != nil {
  880. return def.font, nil
  881. }
  882. // FIXME: add support for non-TFM fonts?
  883. name, err := m.ktx.Find(def.Name + ".tfm")
  884. if err != nil {
  885. return nil, fmt.Errorf("could not find TFM font %q: %w", def.Name, err)
  886. }
  887. f, err := m.ktx.Open(name)
  888. if err != nil {
  889. return nil, fmt.Errorf("could not open TFM font %q: %w", def.Name, err)
  890. }
  891. defer f.Close()
  892. font, err := tfm.Parse(f)
  893. if err != nil {
  894. return nil, fmt.Errorf("could not parse TFM font %q: %w", def.Name, err)
  895. }
  896. def.font = &Font{
  897. name: def.Name,
  898. font: font,
  899. scale: fixed.Int12_20(def.Size),
  900. }
  901. m.state.fonts[i] = def
  902. return def.font, nil
  903. }
  904. func (m *Machine) font(i int) *Font {
  905. fnt, err := m.loadFont(i)
  906. if err != nil {
  907. panic(err)
  908. }
  909. return fnt
  910. }
  911. func (m *Machine) outText(c uint8) {
  912. if len(m.buf) == cap(m.buf) {
  913. m.printf("[%s]\n", m.buf)
  914. m.buf = m.buf[:0]
  915. }
  916. m.buf = append(m.buf, c)
  917. }
  918. func (m *Machine) flushText() {
  919. if len(m.buf) == 0 {
  920. return
  921. }
  922. m.printf("[%s]\n", m.buf)
  923. m.buf = m.buf[:0]
  924. }
  925. func (m *Machine) outSpace(v int32) int32 {
  926. def := m.state.fonts[m.state.f]
  927. space := def.Size / 6 // this is a 3-unit "thin space"
  928. cur := m.state.cur()
  929. switch {
  930. case v >= space || v <= -4*space:
  931. m.outText(' ')
  932. cur.hh = m.pixels(cur.h + v)
  933. default:
  934. cur.hh += m.pixels(v)
  935. }
  936. return cur.hh
  937. }
  938. func (m *Machine) outVMove(v int32) int32 {
  939. def := m.state.fonts[m.state.f]
  940. space := def.Size / 6 // this is a 3-unit "thin space"
  941. cur := m.state.cur()
  942. switch {
  943. case absI32(v) >= 5*space:
  944. cur.vv = m.pixels(cur.v + v)
  945. default:
  946. cur.vv += m.pixels(v)
  947. }
  948. return cur.vv
  949. }
  950. func (m *Machine) handleSpecial(p []byte) error {
  951. for _, h := range m.handlers {
  952. err := h.Handle(p)
  953. if err == nil || !errors.Is(err, ErrSkipHandler) {
  954. return err
  955. }
  956. }
  957. return nil
  958. }
  959. func (m *Machine) printf(format string, args ...interface{}) {
  960. fmt.Fprintf(m.w, format, args...)
  961. }