]> www.fi.muni.cz Git - evince.git/blob - dvi/dvilib/dl-dvi-parser.cc
7caac026676c603d209bf443c3ea4be22504b51d
[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             cout << opcode << endl;
362             program->add_command (cmd);
363             cmd->unref();
364         }
365     }
366     
367     return program;
368 }
369
370 DviPageHeader *
371 DviParser::parse_page_header (uint *page_pointer)
372 {
373     DviOpcode c;
374     
375     DviPageHeader *header = new DviPageHeader();
376     
377     header->address = *page_pointer;
378     
379     c = (DviOpcode)loader.get_uint8();
380     if (c != DVI_BOP)
381         throw string ("Expected BOP not found");
382     for (uint i=0; i<N_PAGE_COUNTERS; ++i)
383         header->count[i] = loader.get_uint32 ();
384     
385     *page_pointer = loader.get_uint32 ();
386     
387     return header;
388 }
389
390 DviFontdefinition *
391 DviParser::parse_fontdefinition (void)
392 {
393     DviFontdefinition *fontdef = new DviFontdefinition;
394     DviOpcode c = (DviOpcode)loader.get_uint8 ();
395     
396     switch (c) {
397     case DVI_FNTDEF1:
398         fontdef->fontnum = loader.get_uint8 ();
399         break;
400     case DVI_FNTDEF2:
401         fontdef->fontnum = loader.get_uint16 ();
402         break;
403     case DVI_FNTDEF3:
404         fontdef->fontnum = loader.get_uint24 ();
405         break;
406     case DVI_FNTDEF4:
407         fontdef->fontnum = loader.get_uint32 ();
408         break;
409     default:
410         throw string ("DVI_FNTDEF? expected");
411         break;
412     }
413     fontdef->checksum = loader.get_uint32 ();
414     fontdef->at_size = loader.get_uint32 ();
415     fontdef->design_size = loader.get_uint32 ();
416     
417     uint dirlength = loader.get_uint8 ();
418     uint namelength = loader.get_uint8 ();
419     
420     fontdef->directory = "";
421     fontdef->name = "";
422     
423     for (uint i=0; i<dirlength; ++i)
424         fontdef->directory += loader.get_uint8();
425     for (uint i=0; i<namelength; ++i)
426         fontdef->name += loader.get_uint8();
427     
428     cout << "parsed fd: " << fontdef->name << " " << fontdef->fontnum << endl;
429     
430     return fontdef;
431 }
432
433 DviFilePreamble *
434 DviParser::parse_preamble (void)
435 {
436     DviFilePreamble *preamble = new DviFilePreamble;
437     
438     DviOpcode c = (DviOpcode)loader.get_uint8 ();
439     if (c != DVI_PRE)
440     {
441         string asdf ("asdf");
442         throw string ("Corrupt .dvi file - first byte is not DVI_PRE" + asdf);
443     }
444     
445     preamble->type = (DviType)loader.get_uint8 ();
446     if (preamble->type != NORMAL_DVI)
447     {
448         string asdf ("asdf");
449         cout << asdf;
450         throw string ("Unknown .dvi format" + asdf);
451     }
452     
453     preamble->numerator = loader.get_uint32 ();
454     preamble->denominator = loader.get_uint32 ();
455     preamble->magnification = loader.get_uint32 ();
456     preamble->comment = loader.get_string8 ();
457     
458     return preamble;
459 }
460
461 DviFilePostamble *
462 DviParser::parse_postamble (void)
463 {
464     DviFilePostamble *postamble = new DviFilePostamble;
465     
466     loader.goto_from_end (-5);
467     
468     int i;
469     do {
470         i = loader.get_uint8 ();
471         loader.goto_from_current (-2);
472     } while (i == 223);
473     
474     postamble->type = (DviType)i;
475     
476     loader.goto_from_current (-3);
477     loader.goto_from_start (loader.get_uint32() + 1);
478     
479     postamble->last_page_address = loader.get_uint32();
480     postamble->numerator = loader.get_uint32();
481     postamble->denominator = loader.get_uint32();
482     postamble->magnification = loader.get_uint32();
483     postamble->max_height = loader.get_uint32();
484     postamble->max_width = loader.get_uint32();
485     postamble->stack_height = loader.get_uint16();
486     
487     loader.get_uint16 (); // skip number of pages (we count them instead)
488     
489     while (true)
490     {
491         DviOpcode c = (DviOpcode)loader.get_uint8 ();
492         
493         if (c == DVI_NOP)
494             continue;
495         else if (DVI_FNTDEF1 <= c  &&  c <= DVI_FNTDEF4)
496         {
497             loader.goto_from_current (-1);
498             DviFontdefinition *fd = parse_fontdefinition ();
499             
500             postamble->fontdefinitions[fd->fontnum] = fd;
501             cout << fd->name << endl;
502             cout << postamble->fontdefinitions[fd->fontnum]->name;
503         }
504         else
505         {
506             loader.goto_from_current (-1);
507             break;
508         }
509     }
510     return postamble;
511 }
512
513 VfFontPreamble *
514 DviParser::parse_vf_font_preamble (void)
515 {
516     DviOpcode c;
517     VfFontPreamble *preamble = new VfFontPreamble;
518     
519     c = (DviOpcode)loader.get_uint8 ();
520     if (c != DVI_PRE)
521         throw string ("Not a .vf file");
522     c = (DviOpcode)loader.get_uint8 ();
523     if (c != 202)
524         throw string ("Not a .vf file");
525     
526     preamble->comment = loader.get_string8 ();
527     preamble->checksum = loader.get_uint32 ();
528     preamble->design_size = loader.get_uint32 ();
529     
530     while (true)
531     {
532         DviOpcode c = (DviOpcode)loader.get_uint8 ();
533         
534         if (DVI_FNTDEF1 <= c  &&  c <= DVI_FNTDEF4)
535         {
536             loader.goto_from_current (-1);
537             DviFontdefinition *fd = parse_fontdefinition ();
538             
539             preamble->fontdefinitions.push_back (fd);
540         }
541         else
542         {
543             loader.goto_from_current (-1);
544             break;
545         }
546     }
547     return preamble;
548 }
549
550 VfChar *
551 DviParser::parse_vf_char (void)
552 {
553     DviOpcode c;
554     
555     c = (DviOpcode)loader.get_uint8 ();
556     
557     VfChar *ch = new VfChar;
558     
559     if (c == DVI_POST)
560         return 0;
561     else if (c > 242)
562         throw string ("Corrupt .vf file");
563     else 
564     {
565         uint packet_length;
566         if (c == 242)
567         {
568             packet_length = loader.get_uint32 ();
569             ch->character_code = loader.get_uint32 ();
570             ch->tfm_width = loader.get_uint32 ();
571         }
572         else
573         {
574             packet_length = c;
575             ch->character_code = loader.get_uint8 ();
576             ch->tfm_width = loader.get_uint24 ();
577         }
578         ch->program = parse_program (packet_length);
579     }
580     return ch;
581 }