Main Page | Namespace List | Class Hierarchy | Class List | File List | Namespace Members | Class Members | File Members

DviFile.h

Go to the documentation of this file.
00001 // This file is part of dvi2bitmap. 00002 // Copyright 1999--2002, Council for the Central Laboratory of the Research Councils 00003 // 00004 // This program is part of the Starlink Software Distribution: see 00005 // http://www.starlink.ac.uk 00006 // 00007 // dvi2bitmap is free software; you can redistribute it and/or modify 00008 // it under the terms of the GNU General Public License as published by 00009 // the Free Software Foundation; either version 2 of the License, or 00010 // (at your option) any later version. 00011 // 00012 // dvi2bitmap is distributed in the hope that it will be useful, 00013 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 // GNU General Public License for more details. 00016 // 00017 // You should have received a copy of the GNU General Public License 00018 // along with dvi2bitmap; if not, write to the Free Software 00019 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 00020 // 00021 // The General Public License is distributed along with this 00022 // program in the file LICENCE. 00023 // 00024 // Author: Norman Gray <norman@astro.gla.ac.uk> 00025 // $Id: DviFile.h,v 1.61 2004/10/19 20:39:23 nxg Exp $ 00026 00027 00028 #ifndef DVI_FILE_HEADER_READ 00029 #define DVI_FILE_HEADER_READ 1 00030 00031 #include <config.h> 00032 00033 #ifdef HAVE_CSTD_INCLUDE 00034 #include <cctype> 00035 #else 00036 #include <ctype.h> 00037 #endif 00038 00039 #include <string> 00040 00041 #include <stack> 00042 #include <list> 00043 #include <map> 00044 00045 #include <Byte.h> 00046 #include <DviError.h> 00047 #include <FileByteStream.h> 00048 #include <PkFont.h> 00049 #include <verbosity.h> 00050 00051 // I think the GCC 2.8.1 stack implementation may be buggy. 00052 // Setting this to 1 switches on a home-made version. 00053 // This hasn't received _extensive_ testing, but seems to work OK. 00054 // This is pretty crappy, though, and I intend to remove it next time 00055 // I'm feeling brave. If you have to enable this to get this library 00056 // to compile, therefore, tell me (norman@astro.gla.ac.uk) so that I 00057 // don't discard this. If you need to enable this, then you should 00058 // probably call the DviFile constructors with read_post true, so 00059 // that the maximum stack size can be read from the postamble, and 00060 // the homemade posstack therefore initialised to the correct length. 00061 #ifndef HOMEMADE_POSSTATESTACK 00062 #define HOMEMADE_POSSTATESTACK 0 00063 #endif 00064 00065 class DviFileEvent; 00066 class DviFilePreamble; 00067 00076 class DviFile { 00077 public: 00078 DviFile (string& s, 00079 int resolution=0, 00080 double magmag=1.0, 00081 bool read_postamble=true, 00082 bool seekable=true) 00083 throw (DviError); 00084 ~DviFile(); 00085 bool eof(); 00086 DviFileEvent *getEvent(); 00087 DviFileEvent *getEndOfPage(); 00093 enum DviUnits { 00097 unit_BAD, 00101 unit_pt, 00105 unit_pc, 00109 unit_in, 00114 unit_bp, 00118 unit_cm, 00125 unit_mm, 00129 unit_dd, 00133 unit_cc, 00144 unit_sp, 00149 unit_pixels, 00160 unit_dvi 00161 }; 00162 static DviUnits unitType(string unitString); 00163 static string unitString(DviUnits unit); 00179 int currH(DviUnits units=unit_pixels) const 00180 throw (DviError) { 00181 int r; 00182 switch (units) { 00183 case unit_pixels: 00184 r = hh_; /* device units */ 00185 break; 00186 case unit_dvi: 00187 r = h_; 00188 break; 00189 case unit_sp: 00190 r = (netmag_ == 1.0 ? h_ : static_cast<int>(h_*netmag_)); 00191 break; 00192 default: 00193 throw DviError("Bad unit in currH"); 00194 } 00195 return r; 00196 } 00201 int currV(DviUnits units=unit_pixels) const 00202 throw (DviError) { 00203 int r; 00204 switch (units) { 00205 case unit_pixels: 00206 r = vv_; /* device units */ 00207 break; 00208 case unit_dvi: 00209 r = v_; 00210 break; 00211 case unit_sp: 00212 r = (netmag_ == 1.0 ? v_ : static_cast<int>(v_*netmag_)); 00213 break; 00214 default: 00215 throw DviError("Bad unit in currV"); 00216 } 00217 return r; 00218 } 00219 int hSize(); 00220 int vSize(); 00221 static double convertFromScaledPoints(int sp, DviUnits units, 00222 DviFile *dvif=0) 00223 throw (DviError); 00224 static double convertToScaledPoints(double length, DviUnits units, 00225 DviFile *dvif=0) 00226 throw (DviError); 00227 static double convertUnits(double length, 00228 DviUnits from_units, 00229 DviUnits to_units, 00230 DviFile *dvif=0) 00231 throw (DviError); 00232 static verbosities verbosity(const verbosities level); 00238 double magnification() const { return netmag_; } 00246 int pt2px(double npt) const 00247 { 00248 return static_cast<int> 00249 (npt * dviu_per_pt_ / dviu_per_px_ + 0.5); 00250 } 00255 const string *filename () const { return &fileName_; } 00256 00257 const PkFont* getFallbackFont(const PkFont* desired); 00258 00270 bool haveReadPostamble() const { return have_preread_postamble_; } 00271 00272 private: 00273 string fileName_; 00278 int h_, v_, w_, x_, y_, z_; 00282 int hh_, vv_; 00284 int pending_hupdate_; 00286 int pending_hhupdate_; 00287 PkFont *current_font_; 00288 InputByteStream *dvif_; 00297 double dviu_per_pt_; 00298 00306 double dviu_per_px_; 00312 double dviu_per_sp_; 00313 00314 double dviu_per_(DviUnits unit); 00315 00321 const double extmag_; 00326 double netmag_; 00327 00328 // tell getEvent to skip this page 00329 bool skipPage_; 00330 00334 int max_drift_; 00335 00341 int widest_page_; 00348 int deepest_page_; 00349 00350 Byte getByte(); 00351 signed int getSIU(int), getSIS(int); 00352 unsigned int getUIU(int); 00353 struct { 00354 unsigned int mag, l, u, s, t; 00355 } postamble_; 00356 struct { 00357 unsigned int i, num, den, mag; 00358 string comment; 00359 } preamble_; 00360 void read_postamble() 00361 throw (DviError); 00362 bool have_preread_postamble_; /* we sought to it at beginning */ 00363 bool have_read_to_postamble_; /* we have read through to end */ 00364 void process_preamble(DviFilePreamble *); 00365 void fnt_def_(double fontmag, int nbytes); 00366 void check_duplicate_font(int); 00367 int pixel_round(int); 00368 int charWidth_ (int charno); 00369 int charEscapement_ (int charno); 00370 // updateH/V update the horizontal position by an amount in DVI units 00371 void updateH_ (int hup, int hhup); 00372 void updateV_ (int y); 00373 struct PosState { 00374 const int h, v, w, x, y, z, hh, vv; 00375 PosState(int h, int v, int w, int x, int y, int z, int hh, int vv) 00376 : h(h),v(v),w(w),x(x),y(y),z(z),hh(hh),vv(vv) { } 00377 }; 00378 #if HOMEMADE_POSSTATESTACK 00379 class PosStateStack { 00380 // It seems wrong to implement a stack rather than using the standard 00381 // one, but either I'm doing something wrong the way 00382 // I use the STL stack, or else it's (horrors!) buggy. In any case, 00383 // it's reasonable to use a non-extendable stack, since the DVI 00384 // postamble specifies the maximum stack size required. 00385 public: 00386 PosStateStack(int size); 00387 void push(const PosState *p); 00388 const PosState *pop(); 00389 bool empty() const { return i == 0; } 00390 void clear(); 00391 private: 00392 unsigned int size, i; 00393 const PosState **s; 00394 }; 00395 PosStateStack *posStack_; 00396 #else 00397 STD::stack<PosState> posStack_; 00398 #endif 00399 static verbosities verbosity_; 00400 00401 public: 00405 class FontSet { 00406 private: 00407 FontSet(); 00408 ~FontSet(); 00409 void add(int fnt_num, PkFont* newfont); 00410 PkFont* get(int fnt_num); 00411 friend class DviFile; 00412 typedef STD::map<int,PkFont*> FontMap; 00413 FontMap fontMap_; 00414 public: 00419 bool empty() const { return fontMap_.empty(); } 00424 size_t size() const { return fontMap_.size(); } 00428 class const_iterator; 00429 friend class DviFile::FontSet::const_iterator; /* so it sees FontMap */ 00430 class const_iterator { 00431 public: 00432 const PkFont* operator*() const throw (DviError); 00433 const_iterator& operator++() throw (DviError); 00434 bool operator==(const const_iterator& it) const; 00435 bool operator!=(const const_iterator& it) const; 00436 ~const_iterator(); 00437 private: 00438 const_iterator(); 00439 const_iterator(FontMap m); 00440 STD::list<PkFont*> fontlist_; 00441 friend class DviFile::FontSet; 00442 }; 00443 const_iterator begin() const; 00444 const_iterator end() const; 00445 private: 00446 mutable const_iterator* myIter_; 00447 }; 00448 private: 00449 FontSet fontSet_; 00450 public: 00460 const FontSet* getFontSet() const { return &fontSet_; } 00461 // Why can't I have 'FontSet& getFontSet() const { return fontSet_; };'? 00462 00463 #if 0 00464 public: 00465 class const_iterator { 00466 public: 00467 const PkFont* operator*() const throw (DviBug); 00468 const_iterator& operator++(); 00469 bool operator==(const const_iterator& it) const; 00470 bool operator!=(const const_iterator& it) const; 00471 #if 0 00472 bool operator==(const const_iterator& it) const 00473 { return finished_ == it.finished_; } 00474 bool operator!=(const const_iterator& it) const 00475 { return finished_ != it.finished_; } 00476 #endif 00477 private: 00478 /* These should be implementable more compactly, since we're 00479 just using map's iterator, but there's some visibility 00480 subtlety that escapes me... */ 00481 const_iterator(FontMap::const_iterator m, 00482 FontMap::const_iterator me) { 00483 mapiter_ = m; 00484 endmapiter_ = me; 00485 finished_ = false; 00486 }; 00487 const_iterator() : finished_(true) { } 00488 FontMap::const_iterator mapiter_; 00489 FontMap::const_iterator endmapiter_; 00490 bool finished_; 00491 friend class DviFile; 00492 }; 00500 const_iterator begin() { 00501 return const_iterator(fontMap_.begin(), fontMap_.end()); 00502 } 00509 const_iterator end() const { return const_iterator(); }; 00510 friend class const_iterator; 00511 #endif 00512 }; 00513 00514 00515 /* DviFileEvent is what is returned to the client from the DVI reading class. 00516 * Declare one derived class for each type of event. 00517 * 00518 * This is rather bad design - these classes should be subclasses of DviFile 00519 * above. 00520 * DviFileEvent is a virtual class, so these derived classes should have 00521 * non-virtual destructors. 00522 * XXX these shouldn't be subclasses of DviFile, I don't think, but 00523 * they should have DviFile as a friend (correct?), so that only 00524 * DviFile can create instances 00525 */ 00542 class DviFileEvent { 00543 public: 00544 enum eventTypes { setchar, setrule, fontchange, special, 00545 page, preamble, postamble }; 00549 virtual void debug() const; 00550 00559 eventTypes type() const { return type_; } 00560 00565 const unsigned char opcode() const { return opcode_; } 00566 00567 void release(); 00568 00569 static verbosities verbosity(const verbosities level); 00570 00571 protected: 00572 DviFileEvent(unsigned char opcode, eventTypes t, DviFile *dp=0); 00573 static verbosities verbosity_; 00574 00575 private: 00576 const unsigned char opcode_; 00577 DviFile *dviFile_; 00578 const eventTypes type_; 00579 00580 static void releaseEvent(DviFileEvent *e); 00581 }; 00582 class DviFileSetChar : public DviFileEvent { 00583 public: 00589 DviFileSetChar(int charno, DviFile *dptr); 00590 DviFileSetChar(int opcode, int charno, DviFile *dptr); 00591 void debug() const; 00596 const int charno() const { return charno_; } 00597 private: 00598 const int charno_; 00599 }; 00600 class DviFileSetRule: public DviFileEvent { 00601 public: 00606 const int h; 00611 const int w; 00612 DviFileSetRule(unsigned char opcode, DviFile *dptr, int h, int w) 00613 : DviFileEvent(opcode, setrule, dptr), h(h), w(w) { } 00614 void debug() const; 00615 }; 00616 class DviFileFontChange : public DviFileEvent { 00617 public: 00618 DviFileFontChange(unsigned char opcode, PkFont *f) 00619 : DviFileEvent(opcode, fontchange), font(f) { } 00620 void debug() const; 00622 const PkFont *font; 00623 }; 00624 class DviFileSpecial : public DviFileEvent { 00625 public: 00626 DviFileSpecial(unsigned char opcode, string str) 00627 : DviFileEvent(opcode, special), specialString(str) { } 00629 const string specialString; 00630 void debug() const; 00631 }; 00632 class DviFilePage : public DviFileEvent { 00633 public: 00634 DviFilePage(unsigned char opcode, bool isStart) 00635 : DviFileEvent(opcode, page), isStart(isStart) { } 00636 void debug() const; 00643 const bool isStart; 00648 signed int count[10]; 00654 signed int previous; 00655 }; 00656 class DviFilePreamble : public DviFileEvent { 00657 public: 00658 DviFilePreamble() 00659 : DviFileEvent(247, preamble) { } 00660 void debug() const; 00665 unsigned int dviType; 00669 unsigned int num; 00673 unsigned int den; 00678 unsigned int mag; 00682 string comment; 00683 }; 00684 class DviFilePostamble : public DviFileEvent { 00685 public: 00686 DviFilePostamble() 00687 : DviFileEvent(248, postamble) { } 00688 }; 00689 00690 #endif //#ifndef DVI_FILE_HEADER_READ

Generated on Sun Aug 21 18:21:02 2005 for dvi2bitmap by doxygen 1.3.8