]> www.fi.muni.cz Git - evince.git/blob - dvi/dvilib/dl-dvi-parser.cc
Auto*ify dvi and dvi/dvilib
[evince.git] / dvi / dvilib / dl-dvi-parser.cc
1 #include "dl-dvi-parser.hh"
2
3 using namespace DviLib;
4
5 enum DviOpcode {
6     DVI_SETCHAR0 = 0, /* 128 of these */
7     DVI_SETCHAR127 = 127,
8     DVI_SET1,
9     DVI_SET2, 
10     DVI_SET3, 
11     DVI_SET4,
12     DVI_SETRULE,
13     DVI_PUT1,
14     DVI_PUT2,
15     DVI_PUT3,
16     DVI_PUT4,
17     DVI_PUTRULE,
18     DVI_NOP,
19     DVI_BOP,
20     DVI_EOP,
21     DVI_PUSH,
22     DVI_POP,
23     DVI_RIGHT1,
24     DVI_RIGHT2,
25     DVI_RIGHT3,
26     DVI_RIGHT4,
27     DVI_W0,
28     DVI_W1,
29     DVI_W2,
30     DVI_W3,
31     DVI_W4,
32     DVI_X0,
33     DVI_X1,
34     DVI_X2,
35     DVI_X3,
36     DVI_X4,
37     DVI_DOWN1,
38     DVI_DOWN2,
39     DVI_DOWN3,
40     DVI_DOWN4,
41     DVI_Y0,
42     DVI_Y1,
43     DVI_Y2,
44     DVI_Y3,
45     DVI_Y4,
46     DVI_Z0,
47     DVI_Z1,
48     DVI_Z2,
49     DVI_Z3,
50     DVI_Z4, 
51     DVI_FONTNUM0 = 171, /* 64 of these */
52     DVI_FONTNUM63 = 234,
53     DVI_FNT1,
54     DVI_FNT2,
55     DVI_FNT3,
56     DVI_FNT4,
57     DVI_XXX1,
58     DVI_XXX2,
59     DVI_XXX3,
60     DVI_XXX4,
61     DVI_FNTDEF1,
62     DVI_FNTDEF2,
63     DVI_FNTDEF3,
64     DVI_FNTDEF4,
65     DVI_PRE,
66     DVI_POST,
67     DVI_POSTPOST = 249
68 };
69
70 static void 
71 skip_font_definition (AbstractLoader& l, uint *count)
72
73     *count += 12;
74     l.skip_n (12);
75     
76     *count += 2;
77     uint dl = l.get_uint8();
78     uint nl = l.get_uint8();
79     
80     *count += dl+nl;
81     l.skip_n (dl+nl);
82 }
83
84 static DviCommand *
85 parse_command (AbstractLoader &l, uint *count, DviOpcode *opcode)
86 {
87     int h, w;
88     string error;
89     string s;
90     
91     *opcode = (DviOpcode)l.get_uint8 ();
92     *count += 1;
93     
94     if (DVI_SETCHAR0 <= *opcode && *opcode <= DVI_SETCHAR127)
95         return new DviSetCharCommand (*opcode);
96     else if (DVI_FONTNUM0 <= *opcode && *opcode <= DVI_FONTNUM63)
97         return new DviFontNumCommand (*opcode - DVI_FONTNUM0);
98     else switch (*opcode) {
99     case DVI_SET1:
100         *count += 1;
101         return new DviSetCharCommand (l.get_uint8());
102         break;
103     case DVI_SET2:
104         *count += 2;
105         return new DviSetCharCommand (l.get_uint16());
106         break;
107     case DVI_SET3:
108         *count += 3;
109         return new DviSetCharCommand (l.get_uint24());
110         break;
111     case DVI_SET4:
112         *count += 4;
113         return new DviSetCharCommand (l.get_uint32());
114         break;
115     case DVI_SETRULE:
116         *count += 8;
117         h = l.get_int32 ();
118         w = l.get_int32 ();
119         return new DviSetRuleCommand (h, w);
120         break;
121     case DVI_PUT1:
122         *count += 1;
123         return new DviPutCharCommand (l.get_uint8());
124         break;
125     case DVI_PUT2:
126         *count += 2;
127         return new DviPutCharCommand (l.get_uint16());
128         break;
129     case DVI_PUT3:
130         *count += 3;
131         return new DviPutCharCommand (l.get_uint24());
132         break;
133     case DVI_PUT4:
134         *count += 4;
135         return new DviPutCharCommand (l.get_uint32());
136         break;
137     case DVI_PUTRULE:
138         *count += 8;
139         h = l.get_int32();
140         w = l.get_int32();
141         return new DviPutRuleCommand (h, w);
142         break;
143     case DVI_PUSH:
144         return new DviPushCommand();
145         break;
146     case DVI_POP:
147         return new DviPopCommand();
148         break;
149     case DVI_RIGHT1:
150         *count += 1;
151         return new DviRightCommand (l.get_int8());
152         break;
153     case DVI_RIGHT2:
154         *count += 2;
155         return new DviRightCommand (l.get_int16());
156         break;
157     case DVI_RIGHT3:
158         *count += 3;
159         return new DviRightCommand (l.get_int24());
160         break;
161     case DVI_RIGHT4:
162         *count += 4;
163         return new DviRightCommand (l.get_int32());
164         break;
165     case DVI_W0:
166         return new DviWRepCommand ();
167         break;
168     case DVI_W1:
169         *count += 1;
170         return new DviWCommand (l.get_int8());
171         break;
172     case DVI_W2:
173         *count += 2;
174         return new DviWCommand (l.get_int16());
175         break;
176     case DVI_W3:
177         *count += 3;
178         return new DviWCommand (l.get_int24());
179         break;
180     case DVI_W4:
181         *count += 4;
182         return new DviWCommand (l.get_int32());
183         break;
184     case DVI_X0:
185         return new DviXRepCommand ();
186         break;
187     case DVI_X1:
188         *count += 1;
189         return new DviXCommand (l.get_int8());
190         break;
191     case DVI_X2:
192         *count += 2;
193         return new DviXCommand (l.get_int16());
194         break;
195     case DVI_X3:
196         *count += 3;
197         return new DviXCommand (l.get_int24());
198         break;
199     case DVI_X4:
200         *count += 4;
201         return new DviXCommand (l.get_int32());
202         break;
203     case DVI_DOWN1:
204         *count += 1;
205         return new DviDownCommand (l.get_int8());
206         break;
207     case DVI_DOWN2:
208         *count += 2;
209         return new DviDownCommand (l.get_int16());
210         break;
211     case DVI_DOWN3:
212         *count += 3;
213         return new DviDownCommand (l.get_int24());
214         break;
215     case DVI_DOWN4:
216         *count += 4;
217         return new DviDownCommand (l.get_int32());
218         break;
219     case DVI_Y0:
220         return new DviYRepCommand ();
221         break;
222     case DVI_Y1:
223         *count += 1;
224         return new DviYCommand (l.get_int8());
225         break;
226     case DVI_Y2:
227         *count += 2;
228         return new DviYCommand (l.get_int16());
229         break;
230     case DVI_Y3:
231         *count += 3;
232         return new DviYCommand (l.get_int24());
233         break;
234     case DVI_Y4:
235         *count += 4;
236         return new DviYCommand (l.get_int32());
237         break;
238     case DVI_Z0:
239         return new DviZRepCommand ();
240         break;
241     case DVI_Z1:
242         *count += 1;
243         return new DviZCommand (l.get_int8());
244         break;
245     case DVI_Z2:
246         *count += 2;
247         return new DviZCommand (l.get_int16());
248         break;
249     case DVI_Z3:
250         *count += 3;
251         return new DviZCommand (l.get_int24());
252         break;
253     case DVI_Z4:
254         *count += 4;
255         return new DviZCommand (l.get_int32());
256         break;
257     case DVI_FNT1:
258         *count += 1;
259         return new DviFontNumCommand (l.get_uint8());
260         break;
261     case DVI_FNT2:
262         *count += 2;
263         return new DviFontNumCommand (l.get_uint16());
264         break;
265     case DVI_FNT3:
266         *count += 3;
267         return new DviFontNumCommand (l.get_uint24());
268         break;
269     case DVI_FNT4:
270         *count += 4;
271         return new DviFontNumCommand (l.get_uint32());
272         break;
273     case DVI_XXX1:
274         s = l.get_string8();
275         *count += s.length() + 1;
276         return new DviSpecialCommand (s);
277         break;
278     case DVI_XXX2:
279         s = l.get_string16();
280         *count += s.length() + 2;
281         return new DviSpecialCommand (s);
282         break;
283     case DVI_XXX3:
284         s = l.get_string24();
285         *count += s.length() + 3;
286         return new DviSpecialCommand (s);
287         break;
288     case DVI_XXX4:
289         s = l.get_string32();
290         *count += s.length() + 4;
291         return new DviSpecialCommand (s);
292         break;
293     case DVI_FNTDEF1:
294         l.get_uint8 ();
295         skip_font_definition (l, count);
296         break;
297     case DVI_FNTDEF2:
298         l.get_uint16 ();
299         skip_font_definition (l, count);
300         break;
301     case DVI_FNTDEF3: 
302         l.get_uint24 ();
303         skip_font_definition (l, count);
304         break;
305     case DVI_FNTDEF4:
306         l.get_uint32 ();
307         skip_font_definition (l, count);
308         break;
309     case DVI_BOP:       // BOP and EOP are not considered commands
310     case DVI_EOP:
311     case DVI_NOP:       // NOP is ignored
312     case DVI_PRE:       // PRE, POST and POSTPOST are not supposed to happen
313     case DVI_POST:
314     case DVI_POSTPOST:
315         break;
316     default:
317         printf ("%u\n", *opcode);
318         throw string ("Unknown command");
319         break;
320     }
321     return 0;
322 }
323
324 DviProgram *
325 DviParser::parse_program (void)
326 {
327     DviProgram *program = new DviProgram ();
328     DviOpcode opcode;
329     
330     do
331     { 
332         DviCommand *cmd;
333         uint dummy;
334         
335         cmd = parse_command (loader, &dummy, &opcode);
336         if (cmd)
337         {
338             program->add_command (cmd);
339             cmd->unref();
340         }
341         
342     } while (opcode != DVI_EOP);
343     
344     return program;
345 }
346
347 DviProgram *
348 DviParser::parse_program (uint n_bytes)
349 {
350     DviProgram *program = new DviProgram ();
351     uint count = 0;
352     
353     while (count < n_bytes)
354     {
355         DviOpcode opcode;
356         DviCommand *cmd;
357         
358         cmd = parse_command (loader, &count, &opcode);
359         if (cmd)
360         {
361 #if 0
362             cout << opcode << endl;
363 #endif
364             program->add_command (cmd);
365             cmd->unref();
366         }
367     }
368     
369     return program;
370 }
371
372 DviPageHeader *
373 DviParser::parse_page_header (uint *page_pointer)
374 {
375     DviOpcode c;
376     
377     DviPageHeader *header = new DviPageHeader();
378     
379     header->address = *page_pointer;
380     
381     c = (DviOpcode)loader.get_uint8();
382     if (c != DVI_BOP)
383         throw string ("Expected BOP not found");
384     for (uint i=0; i<N_PAGE_COUNTERS; ++i)
385         header->count[i] = loader.get_uint32 ();
386     
387     *page_pointer = loader.get_uint32 ();
388     
389     return header;
390 }
391
392 DviFontdefinition *
393 DviParser::parse_fontdefinition (void)
394 {
395     DviFontdefinition *fontdef = new DviFontdefinition;
396     DviOpcode c = (DviOpcode)loader.get_uint8 ();
397     
398     switch (c) {
399     case DVI_FNTDEF1:
400         fontdef->fontnum = loader.get_uint8 ();
401         break;
402     case DVI_FNTDEF2:
403         fontdef->fontnum = loader.get_uint16 ();
404         break;
405     case DVI_FNTDEF3:
406         fontdef->fontnum = loader.get_uint24 ();
407         break;
408     case DVI_FNTDEF4:
409         fontdef->fontnum = loader.get_uint32 ();
410         break;
411     default:
412         throw string ("DVI_FNTDEF? expected");
413         break;
414     }
415     fontdef->checksum = loader.get_uint32 ();
416     fontdef->at_size = loader.get_uint32 ();
417     fontdef->design_size = loader.get_uint32 ();
418     
419     uint dirlength = loader.get_uint8 ();
420     uint namelength = loader.get_uint8 ();
421     
422     fontdef->directory = "";
423     fontdef->name = "";
424     
425     for (uint i=0; i < dirlength; ++i)
426         fontdef->directory += loader.get_uint8();
427     for (uint i=0; i < namelength; ++i)
428         fontdef->name += loader.get_uint8();
429     
430 #if 0
431     cout << "parsed fd: " << fontdef->name << " " << fontdef->fontnum << endl;
432 #endif
433     
434     return fontdef;
435 }
436
437 DviFilePreamble *
438 DviParser::parse_preamble (void)
439 {
440     DviFilePreamble *preamble = new DviFilePreamble;
441     
442     DviOpcode c = (DviOpcode)loader.get_uint8 ();
443     if (c != DVI_PRE)
444     {
445         string asdf ("asdf");
446         throw string ("Corrupt .dvi file - first byte is not DVI_PRE" + asdf);
447     }
448     
449     preamble->type = (DviType)loader.get_uint8 ();
450     if (preamble->type != NORMAL_DVI)
451     {
452         string asdf ("asdf");
453         cout << asdf;
454         throw string ("Unknown .dvi format" + asdf);
455     }
456     
457     preamble->numerator = loader.get_uint32 ();
458     preamble->denominator = loader.get_uint32 ();
459     preamble->magnification = loader.get_uint32 ();
460     preamble->comment = loader.get_string8 ();
461     
462     return preamble;
463 }
464
465 DviFilePostamble *
466 DviParser::parse_postamble (void)
467 {
468     DviFilePostamble *postamble = new DviFilePostamble;
469
470     postamble->fontmap = new DviFontMap;
471     
472     loader.goto_from_end (-5);
473     
474     int i;
475     do {
476         i = loader.get_uint8 ();
477         loader.goto_from_current (-2);
478     } while (i == 223);
479     
480     postamble->type = (DviType)i;
481     
482     loader.goto_from_current (-3);
483     loader.goto_from_start (loader.get_uint32() + 1);
484     
485     postamble->last_page_address = loader.get_uint32();
486     postamble->numerator = loader.get_uint32();
487     postamble->denominator = loader.get_uint32();
488     postamble->magnification = loader.get_uint32();
489     postamble->max_height = loader.get_uint32();
490     postamble->max_width = loader.get_uint32();
491     postamble->stack_height = loader.get_uint16();
492     
493     loader.get_uint16 (); // skip number of pages (we count them instead)
494     
495     while (true)
496     {
497         DviOpcode c = (DviOpcode)loader.get_uint8 ();
498         
499         if (c == DVI_NOP)
500             continue;
501         else if (DVI_FNTDEF1 <= c  &&  c <= DVI_FNTDEF4)
502         {
503             loader.goto_from_current (-1);
504             DviFontdefinition *fd = parse_fontdefinition ();
505             
506             postamble->fontmap->set_fontdefinition (fd->fontnum, fd);
507             cout << fd->name << endl;
508             cout << postamble->fontmap->get_fontdefinition(fd->fontnum)->name;
509         }
510         else
511         {
512             loader.goto_from_current (-1);
513             break;
514         }
515     }
516     return postamble;
517 }
518
519 VfFontPreamble *
520 DviParser::parse_vf_font_preamble (void)
521 {
522     DviOpcode c;
523     VfFontPreamble *preamble = new VfFontPreamble;
524
525     preamble->fontmap = new DviFontMap;
526     
527     c = (DviOpcode)loader.get_uint8 ();
528     if (c != DVI_PRE)
529         throw string ("Not a .vf file");
530     c = (DviOpcode)loader.get_uint8 ();
531     if (c != 202)
532         throw string ("Not a .vf file");
533     
534     preamble->comment = loader.get_string8 ();
535     preamble->checksum = loader.get_uint32 ();
536     preamble->design_size = loader.get_uint32 ();
537     
538     int i = 0;
539     while (true)
540     {
541         DviOpcode c = (DviOpcode)loader.get_uint8 ();
542         
543         if (DVI_FNTDEF1 <= c  &&  c <= DVI_FNTDEF4)
544         {
545             loader.goto_from_current (-1);
546             DviFontdefinition *fd = parse_fontdefinition ();
547             
548             preamble->fontmap->set_fontdefinition (i++, fd);
549         }
550         else
551         {
552             loader.goto_from_current (-1);
553             break;
554         }
555     }
556     return preamble;
557 }
558
559 VfChar *
560 DviParser::parse_vf_char (void)
561 {
562     DviOpcode c;
563     
564     c = (DviOpcode)loader.get_uint8 ();
565     
566     VfChar *ch = new VfChar;
567     
568     if (c == DVI_POST)
569         return 0;
570     else if (c > 242)
571         throw string ("Corrupt .vf file");
572     else 
573     {
574         uint packet_length;
575         if (c == 242)
576         {
577             packet_length = loader.get_uint32 ();
578             ch->character_code = loader.get_uint32 ();
579             ch->tfm_width = loader.get_uint32 ();
580         }
581         else
582         {
583             packet_length = c;
584             ch->character_code = loader.get_uint8 ();
585             ch->tfm_width = loader.get_uint24 ();
586         }
587         ch->program = parse_program (packet_length);
588     }
589     return ch;
590 }