dvi2bitmap  dvi2bitmap1.0
DviFile.h
Go to the documentation of this file.
1 /* This file is part of dvi2bitmap; see README for copyrights and licence */
2 
3 #ifndef DVI_FILE_HEADER_READ
4 #define DVI_FILE_HEADER_READ 1
5 
6 #include <config.h>
7 
8 #ifdef HAVE_CSTD_INCLUDE
9 #include <cctype>
10 #else
11 #include <ctype.h>
12 #endif
13 
14 #include <string>
15 
16 #include <stack>
17 #include <list>
18 #include <map>
19 
20 #include <Byte.h>
21 #include <DviError.h>
22 #include <FileByteStream.h>
23 #include <PkFont.h>
24 #include <verbosity.h>
25 
26 // I think the GCC 2.8.1 stack implementation may be buggy.
27 // Setting this to 1 switches on a home-made version.
28 // This hasn't received _extensive_ testing, but seems to work OK.
29 // This is pretty crappy, though, and I intend to remove it next time
30 // I'm feeling brave. If you have to enable this to get this library
31 // to compile, therefore, tell me (norman@astro.gla.ac.uk) so that I
32 // don't discard this. If you need to enable this, then you should
33 // probably call the DviFile constructors with read_post true, so
34 // that the maximum stack size can be read from the postamble, and
35 // the homemade posstack therefore initialised to the correct length.
36 #ifndef HOMEMADE_POSSTATESTACK
37 #define HOMEMADE_POSSTATESTACK 0
38 #endif
39 
40 class DviFileEvent;
41 class DviFilePreamble;
42 
51 class DviFile {
52 public:
53  DviFile (string& s,
54  int resolution=0,
55  double magmag=1.0,
56  bool read_postamble=true,
57  bool seekable=true)
58  throw (DviError);
59  ~DviFile();
60  bool eof();
68  enum DviUnits {
136  };
137  static DviUnits unitType(string unitString);
138  static string unitString(DviUnits unit);
154  int currH(DviUnits units=unit_pixels) const
155  throw (DviError) {
156  int r;
157  switch (units) {
158  case unit_pixels:
159  r = hh_; /* device units */
160  break;
161  case unit_dvi:
162  r = h_;
163  break;
164  case unit_sp:
165  r = (netmag_ == 1.0 ? h_ : static_cast<int>(h_*netmag_));
166  break;
167  default:
168  throw DviError("Bad unit in currH");
169  }
170  return r;
171  }
176  int currV(DviUnits units=unit_pixels) const
177  throw (DviError) {
178  int r;
179  switch (units) {
180  case unit_pixels:
181  r = vv_; /* device units */
182  break;
183  case unit_dvi:
184  r = v_;
185  break;
186  case unit_sp:
187  r = (netmag_ == 1.0 ? v_ : static_cast<int>(v_*netmag_));
188  break;
189  default:
190  throw DviError("Bad unit in currV");
191  }
192  return r;
193  }
194  int hSize();
195  int vSize();
196  static double convertFromScaledPoints(int sp, DviUnits units,
197  DviFile *dvif=0)
198  throw (DviError);
199  static int convertToScaledPoints(double length, DviUnits units,
200  DviFile *dvif=0)
201  throw (DviError);
202  static double convertUnits(double length,
203  DviUnits from_units,
204  DviUnits to_units,
205  DviFile *dvif=0)
206  throw (DviError);
207  static verbosities verbosity(const verbosities level);
213  double magnification() const { return netmag_; }
221  int pt2px(double npt) const
222  {
223  return static_cast<int>
224  (npt * dviu_per_pt_ / dviu_per_px_ + 0.5);
225  }
230  const string *filename () const { return &fileName_; }
231 
232  const PkFont* getFallbackFont(const PkFont* desired);
233 
245  bool haveReadPostamble() const { return have_preread_postamble_; }
246 
247 private:
248  string fileName_;
253  int h_, v_, w_, x_, y_, z_;
257  int hh_, vv_;
259  int pending_hupdate_;
261  int pending_hhupdate_;
262  PkFont *current_font_;
263  InputByteStream *dvif_;
272  double dviu_per_pt_;
273 
281  double dviu_per_px_;
287  double dviu_per_sp_;
288 
289  double dviu_per_(DviUnits unit);
290 
296  const double extmag_;
301  double netmag_;
302 
303  // tell getEvent to skip this page
304  bool skipPage_;
305 
309  int max_drift_;
310 
316  int widest_page_;
323  int deepest_page_;
324 
325  Byte getByte();
326  signed int getSIU(int), getSIS(int);
327  unsigned int getUIU(int);
328  struct {
329  unsigned int mag, l, u, s, t;
330  } postamble_;
331  struct {
332  unsigned int i, num, den, mag;
333  string comment;
334  } preamble_;
335  void read_postamble()
336  throw (DviError);
337  bool have_preread_postamble_; /* we sought to it at beginning */
338  bool have_read_to_postamble_; /* we have read through to end */
339  void process_preamble(DviFilePreamble *);
340  void fnt_def_(double fontmag, int nbytes);
341  void check_duplicate_font(int);
342  int pixel_round(int);
343  int charWidth_ (int charno);
344  int charEscapement_ (int charno);
345  // updateH/V update the horizontal position by an amount in DVI units
346  void updateH_ (int hup, int hhup);
347  void updateV_ (int y);
348  struct PosState {
349  const int h, v, w, x, y, z, hh, vv;
350  PosState(int h, int v, int w, int x, int y, int z, int hh, int vv)
351  : h(h),v(v),w(w),x(x),y(y),z(z),hh(hh),vv(vv) { }
352  };
353 #if HOMEMADE_POSSTATESTACK
354  class PosStateStack {
355  // It seems wrong to implement a stack rather than using the standard
356  // one, but either I'm doing something wrong the way
357  // I use the STL stack, or else it's (horrors!) buggy. In any case,
358  // it's reasonable to use a non-extendable stack, since the DVI
359  // postamble specifies the maximum stack size required.
360  public:
361  PosStateStack(int size);
362  void push(const PosState *p);
363  const PosState *pop();
364  bool empty() const { return i == 0; }
365  void clear();
366  private:
367  unsigned int size, i;
368  const PosState **s;
369  };
370  PosStateStack *posStack_;
371 #else
372  STD::stack<PosState> posStack_;
373 #endif
374  static verbosities verbosity_;
375 
376  public:
380  class FontSet {
381  private:
382  FontSet();
383  ~FontSet();
384  void add(int fnt_num, PkFont* newfont);
385  PkFont* get(int fnt_num);
386  friend class DviFile;
387  typedef STD::map<int,PkFont*> FontMap;
388  FontMap fontMap_;
389  public:
394  bool empty() const { return fontMap_.empty(); }
399  size_t size() const { return fontMap_.size(); }
404  friend class DviFile::FontSet::const_iterator; /* so it sees FontMap */
406  public:
407  const PkFont* operator*() const throw (DviError);
409  bool operator==(const const_iterator& it) const;
410  bool operator!=(const const_iterator& it) const;
411  ~const_iterator();
412  private:
413  const_iterator();
414  const_iterator(FontMap m);
415  STD::list<PkFont*> fontlist_;
416  friend class DviFile::FontSet;
417  };
418  const_iterator begin() const;
419  const_iterator end() const;
420  private:
421  mutable const_iterator* myIter_;
422  };
423  private:
424  FontSet fontSet_;
425  public:
435  const FontSet* getFontSet() const { return &fontSet_; }
436  // Why can't I have 'FontSet& getFontSet() const { return fontSet_; };'?
437 
438 #if 0
439  public:
440  class const_iterator {
441  public:
442  const PkFont* operator*() const throw (DviBug);
443  const_iterator& operator++();
444  bool operator==(const const_iterator& it) const;
445  bool operator!=(const const_iterator& it) const;
446 #if 0
447  bool operator==(const const_iterator& it) const
448  { return finished_ == it.finished_; }
449  bool operator!=(const const_iterator& it) const
450  { return finished_ != it.finished_; }
451 #endif
452  private:
453  /* These should be implementable more compactly, since we're
454  just using map's iterator, but there's some visibility
455  subtlety that escapes me... */
456  const_iterator(FontMap::const_iterator m,
457  FontMap::const_iterator me) {
458  mapiter_ = m;
459  endmapiter_ = me;
460  finished_ = false;
461  };
462  const_iterator() : finished_(true) { }
463  FontMap::const_iterator mapiter_;
464  FontMap::const_iterator endmapiter_;
465  bool finished_;
466  friend class DviFile;
467  };
475  const_iterator begin() {
476  return const_iterator(fontMap_.begin(), fontMap_.end());
477  }
484  const_iterator end() const { return const_iterator(); };
485  friend class const_iterator;
486 #endif
487 };
488 
489 
490 /* DviFileEvent is what is returned to the client from the DVI reading class.
491  * Declare one derived class for each type of event.
492  *
493  * This is rather bad design - these classes should be subclasses of DviFile
494  * above.
495  * DviFileEvent is a virtual class, so these derived classes should have
496  * non-virtual destructors.
497  * XXX these shouldn't be subclasses of DviFile, I don't think, but
498  * they should have DviFile as a friend (correct?), so that only
499  * DviFile can create instances
500  */
518  public:
524  virtual void debug() const;
525 
534  eventTypes type() const { return type_; }
535 
540  const unsigned char opcode() const { return opcode_; }
541 
542  void release();
543 
544  static verbosities verbosity(const verbosities level);
545 
546  protected:
547  DviFileEvent(unsigned char opcode, eventTypes t, DviFile *dp=0);
549 
550  private:
551  const unsigned char opcode_;
552  DviFile *dviFile_;
553  const eventTypes type_;
554 
555  static void releaseEvent(DviFileEvent *e);
556 };
557 
559 class DviFileSetChar : public DviFileEvent {
560  public:
566  DviFileSetChar(int charno, DviFile *dptr);
567  DviFileSetChar(int opcode, int charno, DviFile *dptr);
568  void debug() const;
573  const int charno() const { return charno_; }
574  private:
575  const int charno_;
576 };
577 
580  public:
585  const int h;
590  const int w;
591  DviFileSetRule(unsigned char opcode, DviFile *dptr, int h, int w)
592  : DviFileEvent(opcode, setrule, dptr), h(h), w(w) { }
593  void debug() const;
594 };
595 
598  public:
599  DviFileFontChange(unsigned char opcode, PkFont *f)
600  : DviFileEvent(opcode, fontchange), font(f) { }
601  void debug() const;
603  const PkFont *font;
604 };
605 
607 class DviFileSpecial : public DviFileEvent {
608  public:
609  DviFileSpecial(unsigned char opcode, string str)
610  : DviFileEvent(opcode, special), specialString(str) { }
612  const string specialString;
613  void debug() const;
614 };
615 
617 class DviFilePage : public DviFileEvent {
618  public:
619  DviFilePage(unsigned char opcode, bool isStart)
620  : DviFileEvent(opcode, page), isStart(isStart) { }
621  void debug() const;
628  const bool isStart;
633  signed int count[10];
639  signed int previous;
640 };
641 
644  public:
646  : DviFileEvent(247, preamble) { }
647  void debug() const;
652  unsigned int dviType;
656  unsigned int num;
660  unsigned int den;
665  unsigned int mag;
669  string comment;
670 };
671 
674  public:
676  : DviFileEvent(248, postamble) { }
677 };
678 
679 #endif //#ifndef DVI_FILE_HEADER_READ