From 4296951e94a43c723e9522b588cab178eb66d144 Mon Sep 17 00:00:00 2001 From: Søren Sandmann Date: Tue, 21 Dec 2004 23:57:26 +0000 Subject: New directory with the beginning of a .dvi backend. Tue Dec 21 18:55:06 2004 Søren Sandmann * dvi/*: New directory with the beginning of a .dvi backend. --- (limited to 'dvi/dvilib') diff --git a/dvi/dvilib/TODO b/dvi/dvilib/TODO new file mode 100644 index 0000000..fb58cb3 --- /dev/null +++ b/dvi/dvilib/TODO @@ -0,0 +1,2 @@ +- Add a cache so we don't call kpsewhich for each font +- possibly make cache persistent so we don't have to call kpsewhich on startup diff --git a/dvi/dvilib/dl-dvi-file.cc b/dvi/dvilib/dl-dvi-file.cc new file mode 100755 index 0000000..1739be9 --- /dev/null +++ b/dvi/dvilib/dl-dvi-file.cc @@ -0,0 +1,50 @@ +#include "dl-dvi-file.hh" +#include "dl-dvi-parser.hh" + +using namespace DviLib; + +DviFile::DviFile (AbstractLoader& l) : + loader (l) +{ + DviParser parser (loader); + + preamble = parser.parse_preamble (); + postamble = parser.parse_postamble (); + + n_pages = 0; + uint page_pointer = postamble->last_page_address; + + cout << page_pointer << endl; + + while (page_pointer != (uint)-1) + { + loader.goto_from_start (page_pointer); + + page_headers[n_pages++] = + parser.parse_page_header (&page_pointer); + } +} + +DviPage * +DviFile::get_page (uint n) +{ + DviPage *page = pages[n]; + + if (n > get_n_pages()) + return 0; + + if (page == 0) + { + DviParser parser (loader); + DviPageHeader *header; + DviProgram *program; + + header = page_headers[n]; + loader.goto_from_start (header->address + 45); + program = parser.parse_program (); + + page = new DviPage (*header, *program); + } + + return page; +} diff --git a/dvi/dvilib/dl-dvi-file.hh b/dvi/dvilib/dl-dvi-file.hh new file mode 100755 index 0000000..d6c0201 --- /dev/null +++ b/dvi/dvilib/dl-dvi-file.hh @@ -0,0 +1,99 @@ +#ifndef DL_DVI_FILE_HH +#define DL_DVI_FILE_HH + +#include "dl-dvi-program.hh" +#include +#include +#include +#include "dl-dvi-fontdefinition.hh" +#include "dl-loader.hh" + +namespace DviLib { + const uint N_PAGE_COUNTERS = 10; // \count0 ... \count9 + + class DviPageHeader : public RefCounted { + public: + int count[N_PAGE_COUNTERS]; + uint address; // address of this page, not the preceding + }; + + class DviPage : public AbstractDviProgram { + DviProgram& program; + int count[N_PAGE_COUNTERS]; // \count0 ... \count9 + public: + DviPage (DviProgram& p, int c[N_PAGE_COUNTERS]) : + program (p) + { + for (uint i=0; i fontdefinitions; + }; + + class DviFile : public RefCounted { + AbstractLoader &loader; + + DviFilePreamble *preamble; + DviFilePostamble *postamble; + + uint n_pages; + map page_headers; + map pages; + + public: + DviFile (AbstractLoader& l); + DviPage *get_page (uint n); /* unref it when done */ + ~DviFile (void) {} + uint get_n_pages () { return n_pages; } + DviFontdefinition *get_fontdefinition (uint n) + { + return postamble->fontdefinitions[n]; + } + uint get_numerator () { return postamble->numerator; } + uint get_denominator () { return postamble->denominator; } + uint get_magnification () { return postamble->magnification; } + }; + +} +#endif // DL_DVI_FILE_HH + diff --git a/dvi/dvilib/dl-dvi-fontdefinition.cc b/dvi/dvilib/dl-dvi-fontdefinition.cc new file mode 100755 index 0000000..553ea28 --- /dev/null +++ b/dvi/dvilib/dl-dvi-fontdefinition.cc @@ -0,0 +1,3 @@ +#include "dl-dvi-fontdefinition.hh" + +using namespace DviLib; diff --git a/dvi/dvilib/dl-dvi-fontdefinition.hh b/dvi/dvilib/dl-dvi-fontdefinition.hh new file mode 100755 index 0000000..e6bb0d6 --- /dev/null +++ b/dvi/dvilib/dl-dvi-fontdefinition.hh @@ -0,0 +1,22 @@ +#ifndef DL_FONT_DEFINITION_HH__ +#define DL_FONT_DEFINITION_HH__ + +#include + +#include "dl-refcounted.hh" + +namespace DviLib { + + class DviFontdefinition : public RefCounted { + public: + uint fontnum; + uint checksum; + uint at_size; /* if 300 dpi base, + * load at at_size * 300 / 1000 */ + uint design_size; + string directory; + string name; + }; + +} +#endif // DL_FONT_DEFINITION_HH__ diff --git a/dvi/dvilib/dl-dvi-parser.cc b/dvi/dvilib/dl-dvi-parser.cc new file mode 100755 index 0000000..7caac02 --- /dev/null +++ b/dvi/dvilib/dl-dvi-parser.cc @@ -0,0 +1,581 @@ +#include "dl-dvi-parser.hh" + +using namespace DviLib; + +enum DviOpcode { + DVI_SETCHAR0 = 0, /* 128 of these */ + DVI_SETCHAR127 = 127, + DVI_SET1, + DVI_SET2, + DVI_SET3, + DVI_SET4, + DVI_SETRULE, + DVI_PUT1, + DVI_PUT2, + DVI_PUT3, + DVI_PUT4, + DVI_PUTRULE, + DVI_NOP, + DVI_BOP, + DVI_EOP, + DVI_PUSH, + DVI_POP, + DVI_RIGHT1, + DVI_RIGHT2, + DVI_RIGHT3, + DVI_RIGHT4, + DVI_W0, + DVI_W1, + DVI_W2, + DVI_W3, + DVI_W4, + DVI_X0, + DVI_X1, + DVI_X2, + DVI_X3, + DVI_X4, + DVI_DOWN1, + DVI_DOWN2, + DVI_DOWN3, + DVI_DOWN4, + DVI_Y0, + DVI_Y1, + DVI_Y2, + DVI_Y3, + DVI_Y4, + DVI_Z0, + DVI_Z1, + DVI_Z2, + DVI_Z3, + DVI_Z4, + DVI_FONTNUM0 = 171, /* 64 of these */ + DVI_FONTNUM63 = 234, + DVI_FNT1, + DVI_FNT2, + DVI_FNT3, + DVI_FNT4, + DVI_XXX1, + DVI_XXX2, + DVI_XXX3, + DVI_XXX4, + DVI_FNTDEF1, + DVI_FNTDEF2, + DVI_FNTDEF3, + DVI_FNTDEF4, + DVI_PRE, + DVI_POST, + DVI_POSTPOST = 249 +}; + +static void +skip_font_definition (AbstractLoader& l, uint *count) +{ + *count += 12; + l.skip_n (12); + + *count += 2; + uint dl = l.get_uint8(); + uint nl = l.get_uint8(); + + *count += dl+nl; + l.skip_n (dl+nl); +} + +static DviCommand * +parse_command (AbstractLoader &l, uint *count, DviOpcode *opcode) +{ + int h, w; + string error; + string s; + + *opcode = (DviOpcode)l.get_uint8 (); + *count += 1; + + if (DVI_SETCHAR0 <= *opcode && *opcode <= DVI_SETCHAR127) + return new DviSetCharCommand (*opcode); + else if (DVI_FONTNUM0 <= *opcode && *opcode <= DVI_FONTNUM63) + return new DviFontNumCommand (*opcode - DVI_FONTNUM0); + else switch (*opcode) { + case DVI_SET1: + *count += 1; + return new DviSetCharCommand (l.get_uint8()); + break; + case DVI_SET2: + *count += 2; + return new DviSetCharCommand (l.get_uint16()); + break; + case DVI_SET3: + *count += 3; + return new DviSetCharCommand (l.get_uint24()); + break; + case DVI_SET4: + *count += 4; + return new DviSetCharCommand (l.get_uint32()); + break; + case DVI_SETRULE: + *count += 8; + h = l.get_int32 (); + w = l.get_int32 (); + return new DviSetRuleCommand (h, w); + break; + case DVI_PUT1: + *count += 1; + return new DviPutCharCommand (l.get_uint8()); + break; + case DVI_PUT2: + *count += 2; + return new DviPutCharCommand (l.get_uint16()); + break; + case DVI_PUT3: + *count += 3; + return new DviPutCharCommand (l.get_uint24()); + break; + case DVI_PUT4: + *count += 4; + return new DviPutCharCommand (l.get_uint32()); + break; + case DVI_PUTRULE: + *count += 8; + h = l.get_int32(); + w = l.get_int32(); + return new DviPutRuleCommand (h, w); + break; + case DVI_PUSH: + return new DviPushCommand(); + break; + case DVI_POP: + return new DviPopCommand(); + break; + case DVI_RIGHT1: + *count += 1; + return new DviRightCommand (l.get_int8()); + break; + case DVI_RIGHT2: + *count += 2; + return new DviRightCommand (l.get_int16()); + break; + case DVI_RIGHT3: + *count += 3; + return new DviRightCommand (l.get_int24()); + break; + case DVI_RIGHT4: + *count += 4; + return new DviRightCommand (l.get_int32()); + break; + case DVI_W0: + return new DviWRepCommand (); + break; + case DVI_W1: + *count += 1; + return new DviWCommand (l.get_int8()); + break; + case DVI_W2: + *count += 2; + return new DviWCommand (l.get_int16()); + break; + case DVI_W3: + *count += 3; + return new DviWCommand (l.get_int24()); + break; + case DVI_W4: + *count += 4; + return new DviWCommand (l.get_int32()); + break; + case DVI_X0: + return new DviXRepCommand (); + break; + case DVI_X1: + *count += 1; + return new DviXCommand (l.get_int8()); + break; + case DVI_X2: + *count += 2; + return new DviXCommand (l.get_int16()); + break; + case DVI_X3: + *count += 3; + return new DviXCommand (l.get_int24()); + break; + case DVI_X4: + *count += 4; + return new DviXCommand (l.get_int32()); + break; + case DVI_DOWN1: + *count += 1; + return new DviDownCommand (l.get_int8()); + break; + case DVI_DOWN2: + *count += 2; + return new DviDownCommand (l.get_int16()); + break; + case DVI_DOWN3: + *count += 3; + return new DviDownCommand (l.get_int24()); + break; + case DVI_DOWN4: + *count += 4; + return new DviDownCommand (l.get_int32()); + break; + case DVI_Y0: + return new DviYRepCommand (); + break; + case DVI_Y1: + *count += 1; + return new DviYCommand (l.get_int8()); + break; + case DVI_Y2: + *count += 2; + return new DviYCommand (l.get_int16()); + break; + case DVI_Y3: + *count += 3; + return new DviYCommand (l.get_int24()); + break; + case DVI_Y4: + *count += 4; + return new DviYCommand (l.get_int32()); + break; + case DVI_Z0: + return new DviZRepCommand (); + break; + case DVI_Z1: + *count += 1; + return new DviZCommand (l.get_int8()); + break; + case DVI_Z2: + *count += 2; + return new DviZCommand (l.get_int16()); + break; + case DVI_Z3: + *count += 3; + return new DviZCommand (l.get_int24()); + break; + case DVI_Z4: + *count += 4; + return new DviZCommand (l.get_int32()); + break; + case DVI_FNT1: + *count += 1; + return new DviFontNumCommand (l.get_uint8()); + break; + case DVI_FNT2: + *count += 2; + return new DviFontNumCommand (l.get_uint16()); + break; + case DVI_FNT3: + *count += 3; + return new DviFontNumCommand (l.get_uint24()); + break; + case DVI_FNT4: + *count += 4; + return new DviFontNumCommand (l.get_uint32()); + break; + case DVI_XXX1: + s = l.get_string8(); + *count += s.length() + 1; + return new DviSpecialCommand (s); + break; + case DVI_XXX2: + s = l.get_string16(); + *count += s.length() + 2; + return new DviSpecialCommand (s); + break; + case DVI_XXX3: + s = l.get_string24(); + *count += s.length() + 3; + return new DviSpecialCommand (s); + break; + case DVI_XXX4: + s = l.get_string32(); + *count += s.length() + 4; + return new DviSpecialCommand (s); + break; + case DVI_FNTDEF1: + l.get_uint8 (); + skip_font_definition (l, count); + break; + case DVI_FNTDEF2: + l.get_uint16 (); + skip_font_definition (l, count); + break; + case DVI_FNTDEF3: + l.get_uint24 (); + skip_font_definition (l, count); + break; + case DVI_FNTDEF4: + l.get_uint32 (); + skip_font_definition (l, count); + break; + case DVI_BOP: // BOP and EOP are not considered commands + case DVI_EOP: + case DVI_NOP: // NOP is ignored + case DVI_PRE: // PRE, POST and POSTPOST are not supposed to happen + case DVI_POST: + case DVI_POSTPOST: + break; + default: + printf ("%u\n", *opcode); + throw string ("Unknown command"); + break; + } + return 0; +} + +DviProgram * +DviParser::parse_program (void) +{ + DviProgram *program = new DviProgram (); + DviOpcode opcode; + + do + { + DviCommand *cmd; + uint dummy; + + cmd = parse_command (loader, &dummy, &opcode); + if (cmd) + { + program->add_command (cmd); + cmd->unref(); + } + + } while (opcode != DVI_EOP); + + return program; +} + +DviProgram * +DviParser::parse_program (uint n_bytes) +{ + DviProgram *program = new DviProgram (); + uint count = 0; + + while (count < n_bytes) + { + DviOpcode opcode; + DviCommand *cmd; + + cmd = parse_command (loader, &count, &opcode); + if (cmd) + { + cout << opcode << endl; + program->add_command (cmd); + cmd->unref(); + } + } + + return program; +} + +DviPageHeader * +DviParser::parse_page_header (uint *page_pointer) +{ + DviOpcode c; + + DviPageHeader *header = new DviPageHeader(); + + header->address = *page_pointer; + + c = (DviOpcode)loader.get_uint8(); + if (c != DVI_BOP) + throw string ("Expected BOP not found"); + for (uint i=0; icount[i] = loader.get_uint32 (); + + *page_pointer = loader.get_uint32 (); + + return header; +} + +DviFontdefinition * +DviParser::parse_fontdefinition (void) +{ + DviFontdefinition *fontdef = new DviFontdefinition; + DviOpcode c = (DviOpcode)loader.get_uint8 (); + + switch (c) { + case DVI_FNTDEF1: + fontdef->fontnum = loader.get_uint8 (); + break; + case DVI_FNTDEF2: + fontdef->fontnum = loader.get_uint16 (); + break; + case DVI_FNTDEF3: + fontdef->fontnum = loader.get_uint24 (); + break; + case DVI_FNTDEF4: + fontdef->fontnum = loader.get_uint32 (); + break; + default: + throw string ("DVI_FNTDEF? expected"); + break; + } + fontdef->checksum = loader.get_uint32 (); + fontdef->at_size = loader.get_uint32 (); + fontdef->design_size = loader.get_uint32 (); + + uint dirlength = loader.get_uint8 (); + uint namelength = loader.get_uint8 (); + + fontdef->directory = ""; + fontdef->name = ""; + + for (uint i=0; idirectory += loader.get_uint8(); + for (uint i=0; iname += loader.get_uint8(); + + cout << "parsed fd: " << fontdef->name << " " << fontdef->fontnum << endl; + + return fontdef; +} + +DviFilePreamble * +DviParser::parse_preamble (void) +{ + DviFilePreamble *preamble = new DviFilePreamble; + + DviOpcode c = (DviOpcode)loader.get_uint8 (); + if (c != DVI_PRE) + { + string asdf ("asdf"); + throw string ("Corrupt .dvi file - first byte is not DVI_PRE" + asdf); + } + + preamble->type = (DviType)loader.get_uint8 (); + if (preamble->type != NORMAL_DVI) + { + string asdf ("asdf"); + cout << asdf; + throw string ("Unknown .dvi format" + asdf); + } + + preamble->numerator = loader.get_uint32 (); + preamble->denominator = loader.get_uint32 (); + preamble->magnification = loader.get_uint32 (); + preamble->comment = loader.get_string8 (); + + return preamble; +} + +DviFilePostamble * +DviParser::parse_postamble (void) +{ + DviFilePostamble *postamble = new DviFilePostamble; + + loader.goto_from_end (-5); + + int i; + do { + i = loader.get_uint8 (); + loader.goto_from_current (-2); + } while (i == 223); + + postamble->type = (DviType)i; + + loader.goto_from_current (-3); + loader.goto_from_start (loader.get_uint32() + 1); + + postamble->last_page_address = loader.get_uint32(); + postamble->numerator = loader.get_uint32(); + postamble->denominator = loader.get_uint32(); + postamble->magnification = loader.get_uint32(); + postamble->max_height = loader.get_uint32(); + postamble->max_width = loader.get_uint32(); + postamble->stack_height = loader.get_uint16(); + + loader.get_uint16 (); // skip number of pages (we count them instead) + + while (true) + { + DviOpcode c = (DviOpcode)loader.get_uint8 (); + + if (c == DVI_NOP) + continue; + else if (DVI_FNTDEF1 <= c && c <= DVI_FNTDEF4) + { + loader.goto_from_current (-1); + DviFontdefinition *fd = parse_fontdefinition (); + + postamble->fontdefinitions[fd->fontnum] = fd; + cout << fd->name << endl; + cout << postamble->fontdefinitions[fd->fontnum]->name; + } + else + { + loader.goto_from_current (-1); + break; + } + } + return postamble; +} + +VfFontPreamble * +DviParser::parse_vf_font_preamble (void) +{ + DviOpcode c; + VfFontPreamble *preamble = new VfFontPreamble; + + c = (DviOpcode)loader.get_uint8 (); + if (c != DVI_PRE) + throw string ("Not a .vf file"); + c = (DviOpcode)loader.get_uint8 (); + if (c != 202) + throw string ("Not a .vf file"); + + preamble->comment = loader.get_string8 (); + preamble->checksum = loader.get_uint32 (); + preamble->design_size = loader.get_uint32 (); + + while (true) + { + DviOpcode c = (DviOpcode)loader.get_uint8 (); + + if (DVI_FNTDEF1 <= c && c <= DVI_FNTDEF4) + { + loader.goto_from_current (-1); + DviFontdefinition *fd = parse_fontdefinition (); + + preamble->fontdefinitions.push_back (fd); + } + else + { + loader.goto_from_current (-1); + break; + } + } + return preamble; +} + +VfChar * +DviParser::parse_vf_char (void) +{ + DviOpcode c; + + c = (DviOpcode)loader.get_uint8 (); + + VfChar *ch = new VfChar; + + if (c == DVI_POST) + return 0; + else if (c > 242) + throw string ("Corrupt .vf file"); + else + { + uint packet_length; + if (c == 242) + { + packet_length = loader.get_uint32 (); + ch->character_code = loader.get_uint32 (); + ch->tfm_width = loader.get_uint32 (); + } + else + { + packet_length = c; + ch->character_code = loader.get_uint8 (); + ch->tfm_width = loader.get_uint24 (); + } + ch->program = parse_program (packet_length); + } + return ch; +} diff --git a/dvi/dvilib/dl-dvi-parser.hh b/dvi/dvilib/dl-dvi-parser.hh new file mode 100755 index 0000000..32e065f --- /dev/null +++ b/dvi/dvilib/dl-dvi-parser.hh @@ -0,0 +1,35 @@ +#ifndef DL_DVI_PARSER_HH +#define DL_DVI_PARSER_HH + +#include "dl-loader.hh" +#include "dl-refcounted.hh" +#include "dl-dvi-program.hh" +#include "dl-dvi-fontdefinition.hh" +#include "dl-dvi-file.hh" +#include "dl-vffont.hh" + +namespace DviLib { + + class DviParser : public RefCounted { + AbstractLoader& loader; + public: + DviParser (AbstractLoader& l) : loader (l) + { + }; + + DviFontdefinition * parse_fontdefinition (void); + DviProgram * parse_program (void); + DviProgram * parse_program (uint max); + DviPageHeader * parse_page_header (uint *prev_page); + DviFilePreamble * parse_preamble (void); + DviFilePostamble * parse_postamble (void); + VfFontPreamble * parse_vf_font_preamble (void); + VfChar * parse_vf_char (void); + + ~DviParser (void) + { + }; + }; +} + +#endif diff --git a/dvi/dvilib/dl-dvi-program.cc b/dvi/dvilib/dl-dvi-program.cc new file mode 100755 index 0000000..cb1f07f --- /dev/null +++ b/dvi/dvilib/dl-dvi-program.cc @@ -0,0 +1,30 @@ +#include "dl-dvi-program.hh" +#include + +using namespace DviLib; + +typedef vector::iterator It; + +void +DviProgram::execute (DviRuntime& runtime) +{ + for (It i = commands.begin(); i != commands.end(); ++i) + { + (*i)->execute (runtime); + } +} + +void +DviProgram::add_command (DviCommand *cmd) +{ + cmd->ref(); + commands.push_back (cmd); +} + +DviProgram::~DviProgram (void) +{ + for (It i = commands.begin(); i != commands.end(); ++i) + { + (*i)->unref (); + } +} diff --git a/dvi/dvilib/dl-dvi-program.hh b/dvi/dvilib/dl-dvi-program.hh new file mode 100755 index 0000000..afe5fdb --- /dev/null +++ b/dvi/dvilib/dl-dvi-program.hh @@ -0,0 +1,272 @@ +#ifndef DL_DVI_PROGRAM_HH__ +#define DL_DVI_PROGRAM_HH__ + +using namespace std; + +#include +#include + +#include + +#include "dl-refcounted.hh" +#include "dl-dvi-runtime.hh" + +namespace DviLib +{ + class DviCommand : public RefCounted + { + public: + virtual void execute (DviRuntime& runtime) = 0; + virtual ~DviCommand() {}; + }; + + class AbstractDviProgram : public RefCounted + { + public: + virtual void execute (DviRuntime &runtime) = 0; + virtual ~AbstractDviProgram (void) {}; + }; + + class DviProgram : public AbstractDviProgram + { + public: + vector commands; + void add_command (DviCommand *cmd); + virtual void execute (DviRuntime& runtime); + virtual ~DviProgram (void); + }; + + class DviCharCommand : public DviCommand + { + private: + uint c; + + public: + DviCharCommand (uint c_arg) + { + c = c_arg; + } + uint get_c (void) const { return c; } + }; + + class DviPutCharCommand : public DviCharCommand + { + public: + DviPutCharCommand (uint ch) : DviCharCommand (ch) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.put_char (get_c()); + } + }; + + class DviSetCharCommand : public DviCharCommand + { + public: + DviSetCharCommand (uint ch) : DviCharCommand (ch) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.set_char (get_c()); + } + }; + + class DviRuleCommand : public DviCommand + { + private: + int h, w; + + public: + DviRuleCommand (int h_arg, int w_arg) : h(h_arg), w(w_arg) + { + std::cout << "rule cmd " << h << " " << w << std::endl; + } + int get_h (void) const { return h; } + int get_w (void) const { return w; } + }; + + class DviPutRuleCommand : public DviRuleCommand + { + public: + DviPutRuleCommand (int h, int w) : DviRuleCommand (h, w) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.put_rule (get_h(), get_w()); + } + }; + + class DviSetRuleCommand : public DviRuleCommand + { + public: + DviSetRuleCommand (int h, int w) : DviRuleCommand (h, w) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.set_rule (get_h(), get_w()); + } + }; + + class DviPushCommand : public DviCommand + { + public: + DviPushCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.push (); + } + }; + + class DviPopCommand : public DviCommand + { + public: + DviPopCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.pop (); + } + }; + + class DviMoveCommand : public DviCommand + { + private: + int len; + + public: + DviMoveCommand (int len_arg) : len (len_arg) {}; + int get_len (void) { return len; } + }; + + class DviRightCommand : public DviMoveCommand + { + public: + DviRightCommand (int len) : DviMoveCommand (len) + { +#if 0 + cout << "right command " << get_len() << endl; +#endif + }; + virtual void execute (DviRuntime& runtime) + { + runtime.right (get_len()); + } + }; + + class DviWCommand : public DviMoveCommand + { + public: + DviWCommand (int len) : DviMoveCommand (len) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.w (get_len()); + } + }; + + class DviXCommand : public DviMoveCommand + { + public: + DviXCommand (int len) : DviMoveCommand (len) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.x (get_len()); + } + }; + + class DviDownCommand : public DviMoveCommand + { + public: + DviDownCommand (int len) : DviMoveCommand (len) + { +#if 0 + cout << "down command " << get_len() << endl; +#endif + }; + virtual void execute (DviRuntime& runtime) + { + runtime.down (get_len()); + } + }; + + class DviYCommand : public DviMoveCommand + { + public: + DviYCommand (int len) : DviMoveCommand (len) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.y (get_len()); + } + }; + + class DviZCommand : public DviMoveCommand + { + public: + DviZCommand (int len) : DviMoveCommand (len) {}; + virtual void execute (DviRuntime& runtime) + { + runtime.z (get_len()); + } + }; + + class DviFontNumCommand : public DviCommand + { + private: + int num; + + public: + DviFontNumCommand (int num_arg) : num (num_arg) {} + virtual void execute (DviRuntime& runtime) + { + runtime.font_num (num); + } + }; + + class DviSpecialCommand : public DviCommand + { + string spc; + public: + DviSpecialCommand (string s) : spc (s) {}; + virtual ~DviSpecialCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.special (spc); + } + }; + + class DviWRepCommand : public DviCommand + { + public: + DviWRepCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.w_rep (); + } + }; + + class DviXRepCommand : public DviCommand + { + public: + DviXRepCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.x_rep (); + } + }; + + class DviYRepCommand : public DviCommand + { + public: + DviYRepCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.y_rep (); + } + }; + + class DviZRepCommand : public DviCommand + { + public: + DviZRepCommand () {}; + virtual void execute (DviRuntime& runtime) + { + runtime.z_rep (); + } + }; + +} +#endif // DL_DVI_PROGRAM_HH__ diff --git a/dvi/dvilib/dl-dvi-runtime.cc b/dvi/dvilib/dl-dvi-runtime.cc new file mode 100755 index 0000000..52b2620 --- /dev/null +++ b/dvi/dvilib/dl-dvi-runtime.cc @@ -0,0 +1,2 @@ +#include "dl-dvi-runtime.hh" + diff --git a/dvi/dvilib/dl-dvi-runtime.hh b/dvi/dvilib/dl-dvi-runtime.hh new file mode 100755 index 0000000..abb8c71 --- /dev/null +++ b/dvi/dvilib/dl-dvi-runtime.hh @@ -0,0 +1,45 @@ +#ifndef DL_DVI_STACK_HH +#define DL_DVI_STACK_HH + +#include "dl-refcounted.hh" +#include "dl-dvi-fontdefinition.hh" +#include +#include + +namespace DviLib { + class DviRuntime : public RefCounted + { + public: + virtual void set_char (int ch) = 0; // typeset ch, move w + virtual void put_char (int ch) = 0; // typeset ch, don't move + virtual void set_rule (int height, + int width) = 0; // rule, move (height, width) + virtual void put_rule (int height, + int width) = 0; // rule, don't move + virtual void push (void) = 0; // push current context + virtual void pop (void) = 0; // pop ccontext + virtual void right (int len) = 0; // move right len + virtual void w (int len) = 0; // move right len, set w = len + virtual void w_rep () = 0; // move right w + virtual void x (int len) = 0; // move right len, set x = len + virtual void x_rep () = 0; // move right x + virtual void down (int len) = 0; // move down len + virtual void y (int len) = 0; // move down len, set y = len + virtual void y_rep () = 0; // move down y + virtual void z (int len) = 0; // move down len, set z = len + virtual void z_rep () = 0; // move down z + virtual void push_fontmap (std::map fontmap) = 0; + virtual void font_num (int num) = 0; // f = num + virtual void special (std::string spc) = 0; // do something special + + virtual void paint_bitmap (const unsigned char *data, + uint width, + uint height, + int hoffset, + int voffseth) = 0; + + virtual ~DviRuntime () {}; + }; +} + +#endif diff --git a/dvi/dvilib/dl-font.hh b/dvi/dvilib/dl-font.hh new file mode 100755 index 0000000..855ab73 --- /dev/null +++ b/dvi/dvilib/dl-font.hh @@ -0,0 +1,27 @@ +#ifndef DL_FONT_HH__ +#define DL_FONT_HH__ + +#include "dl-loader.hh" +#include "dl-refcounted.hh" +#include "dl-dvi-runtime.hh" + +#include +#include + +namespace DviLib { + + class AbstractCharacter : public RefCounted { + public: + virtual void paint (DviRuntime &runtime) = 0; + virtual int get_tfm_width () = 0; + }; + + class AbstractFont : public RefCounted { + public: + virtual int get_at_size () = 0; + virtual int get_design_size () = 0; + virtual AbstractCharacter *get_char (int ccode) = 0; + }; +} + +#endif /* DL_PKFONT_HH__ */ diff --git a/dvi/dvilib/dl-loader.cc b/dvi/dvilib/dl-loader.cc new file mode 100755 index 0000000..ce29a43 --- /dev/null +++ b/dvi/dvilib/dl-loader.cc @@ -0,0 +1,196 @@ +#include "dl-loader.hh" +#include +#include + +using namespace DviLib; + +/* Abstract loader */ +/* =============== */ + +/* unsigned integers */ +int +AbstractLoader::get_uint16 () +{ + return (get_uint8() << 8) | get_uint8(); +} + +int +AbstractLoader::get_uint24 () +{ + return (get_uint16() << 8) | get_uint8(); +} +int +AbstractLoader::get_uint32 () +{ + return (get_uint16() << 16) | get_uint16(); +} + +/* signed integers */ +int +AbstractLoader::get_int16 () +{ + return (get_int8() << 8) | get_uint8(); +} + +int +AbstractLoader::get_int24 () +{ + return (get_int16() << 8) | get_uint8(); +} + +int +AbstractLoader::get_int32 () +{ + return (get_int16() << 16) | get_uint16(); +} + +/* (Pascal) strings */ +string +AbstractLoader::get_string8 () +{ + return get_n (get_uint8()); +} + +string +AbstractLoader::get_string16 () +{ + return get_n (get_uint16()); +} + +string +AbstractLoader::get_string24 () +{ + return get_n (get_uint24()); +} + +string +AbstractLoader::get_string32 () +{ + return get_n (get_uint32()); +} + +void +AbstractLoader::skip_string8 () +{ + get_string8(); +} + +void +AbstractLoader::skip_string16 () +{ + get_string16(); +} + +void +AbstractLoader::skip_string24 () +{ + get_string24(); +} + +void +AbstractLoader::skip_string32 () +{ + get_string32(); +} + + +/* "n" */ +void +AbstractLoader::skip_n (int n) +{ + get_n(n); +} + +string +AbstractLoader::get_n (int n) +{ + string r; + + while (n--) + r += get_uint8 (); + + return r; +} + +void +AbstractLoader::get_n (int n, unsigned char *v) +{ + while (n--) + *v++ = (unsigned char)get_uint8 (); +} + +/* File loader */ + +/* FIXME + * + * do not use C style files (?) + * what exceptions should we throw? + */ + +FileLoader::FileLoader (const string &name) +{ + filename = name; + f = fopen (filename.c_str(), "r"); + if (!f) + { + string s (strerror (errno)); + throw string ("Could not open " + filename + ": " + s); + } +} + +FileLoader::~FileLoader () +{ + std::cout << "hej" << std::endl; + if (fclose (f) == EOF) + throw string ("Error closing " + filename); +} + +int +FileLoader::get_int8 () +{ + int c; + + if ((c = fgetc (f)) == EOF) + throw string ("Unexpected end of file"); + else + return (signed char)c; +} + +int +FileLoader::get_uint8 () +{ + return (unsigned char)get_int8(); +} + +void +FileLoader::goto_from_start (int n) +{ + if (fseek (f, n, SEEK_SET) < 0) + { + string error = "fseek failed: "; + error += strerror (errno); + throw error; + } +} + +void +FileLoader::goto_from_current (int n) +{ + if (fseek (f, n, SEEK_CUR) < 0) + { + string error = "fseek failed: "; + error += strerror (errno); + throw error; + } +} + +void +FileLoader::goto_from_end (int n) +{ + if (fseek (f, n, SEEK_END) < 0) + { + string error = "fseek failed: "; + error += strerror (errno); + throw error; + } +} diff --git a/dvi/dvilib/dl-loader.hh b/dvi/dvilib/dl-loader.hh new file mode 100755 index 0000000..f0ac956 --- /dev/null +++ b/dvi/dvilib/dl-loader.hh @@ -0,0 +1,59 @@ +#ifndef DL_LOADER_HH +#define DL_LOADER_HH + +#include +#include +#include + +#include "dl-refcounted.hh" + +namespace DviLib { + + class AbstractLoader : public RefCounted { + public: + virtual int get_uint8 () = 0; + virtual int get_uint16 (); + virtual int get_uint24 (); + virtual int get_uint32 (); + + virtual int get_int8 () = 0; + virtual int get_int16 (); + virtual int get_int24 (); + virtual int get_int32 (); + + virtual string get_string8 (); + virtual string get_string16 (); + virtual string get_string24 (); + virtual string get_string32 (); + + virtual void skip_string8 (); + virtual void skip_string16 (); + virtual void skip_string24 (); + virtual void skip_string32 (); + + virtual void goto_from_start (int i) = 0; + virtual void goto_from_end (int i) = 0; + virtual void goto_from_current (int i) = 0; + + virtual void skip_n (int n); + virtual string get_n (int n); + virtual void get_n (int n, unsigned char *v); + + virtual ~AbstractLoader() {}; + }; + + class FileLoader : public AbstractLoader { + FILE *f; + string filename; + public: + FileLoader (const string &name); + virtual int get_int8 (); + virtual int get_uint8 (); + virtual void goto_from_start (int i); + virtual void goto_from_end (int i); + virtual void goto_from_current (int i); + + virtual ~FileLoader (); + }; +} +#endif // DL_LOADER_HH diff --git a/dvi/dvilib/dl-pkfont.cc b/dvi/dvilib/dl-pkfont.cc new file mode 100755 index 0000000..2544e35 --- /dev/null +++ b/dvi/dvilib/dl-pkfont.cc @@ -0,0 +1,379 @@ +#include "dl-pkfont.hh" +#include +#include + +using namespace DviLib; + +enum PkOpcode { + DL_PK_FIRST_COMMAND = 240, + DL_PK_XXX1 = 240, + DL_PK_XXX2, + DL_PK_XXX3, + DL_PK_XXX4, + DL_PK_YYY, + DL_PK_POST, + DL_PK_NOP, + DL_PK_PRE +}; + +enum Color { + BLACK, + WHITE +}; + +class Bitmap { + uint *data; + uint width; +public: + Bitmap (uint width_arg, uint height) + { + width = width_arg; + data = new uint [width * height]; + std::fill (data, data + width * height, 0x00000000); + } + uchar *steal_pixels (void) + { + uchar *r = (uchar *)data; + data = 0; + return r; + } + ~Bitmap () + { + } + void fill_black (uint index, uint len) + { +#if 0 + cout << "filling: " << len << endl; +#endif + std::fill (data + index, + data + index + len, + 0xff000000); + } + void copy (uint src_index, uint len, uint dest_index) + { + std::copy (data + src_index, + data + (src_index + len), + data + dest_index); + } + uint x (uint index) + { + return index % width; + } +#if 0 + uint y (uint index) + { + return (index * 4) / (width * 4); + } +#endif + bool pixel (uint index) { + return *(data + index) == 0xff000000; + } +}; + +class DviLib::RleContext { + uchar *data; + bool first; + uchar nyb0 (uchar x) { return x >> 4; }; + uchar nyb1 (uchar x) { return x & 15; }; + Bitmap& bitmap; +public: + uint index; + Color color; + RleContext (uchar *data_arg, + Color color_arg, + Bitmap &bitmap_arg) : + data (data_arg), + first (true), + bitmap (bitmap_arg), + + index (0), + color (color_arg) + { } + uchar get_nybble (void) + { + if (first) + { + first = false; + return nyb0 (*data); + } + else + { + first = true; + return nyb1 (*data++); + } + } + Bitmap& get_bitmap () { return bitmap; } +}; + +inline CountType +PkChar::get_count (RleContext& nr, uint *count) +{ + CountType result = RUN_COUNT; + uint i; + + i = nr.get_nybble(); + if (i == 15) + { + *count = 1; + return REPEAT_COUNT; + } + else if (i == 14) + { + result = REPEAT_COUNT; + i = nr.get_nybble(); + } + switch (i) { + case 15: case 14: + throw string ("Duplicated repeat count"); + break; + case 0: + for (i = 1; (*count = nr.get_nybble()) == 0; ++i) + ; + while (i-- > 0) + *count = (*count << 4) + nr.get_nybble(); + *count = *count - 15 + (13 - dyn_f)*16 + dyn_f; + break; + default: + if (i <= dyn_f) + *count = i; + else + *count = (i - dyn_f - 1)*16 + nr.get_nybble() + dyn_f + 1; + break; + } + return result; +} + +void +PkChar::unpack_rle (RleContext& nr) +{ + uint count; + + while (nr.index < height * width) + { + CountType count_type = get_count (nr, &count); + Bitmap& bm = nr.get_bitmap (); + + switch (count_type) { + case RUN_COUNT: + if (nr.color == BLACK) + { + bm.fill_black (nr.index, count); + nr.color = WHITE; + } + else + nr.color = BLACK; + nr.index += count; + break; + case REPEAT_COUNT: + uint temp = nr.index; + + nr.index += count * width; + unpack_rle (nr); + + uint x = bm.x(temp); + + if (bm.pixel (temp - x)) + bm.fill_black (temp + count * width - x, x); + + for (uint i = 0; i < count; ++i) + bm.copy (temp + count * width - x, width, + temp - x + i * width); + return; + break; + } + } +} + +void +PkChar::unpack_bitmap (void) +{ + uint i, weight; + + uchar *bitmap + = new uchar [4 * width * height]; + fill (bitmap, bitmap + 4 * width * height, 0xFF); + + weight = 128; + + for (i=0; i < height * width; i+=4) + { + if ((*data.packed & weight) != 0) + bitmap[i] = bitmap[i+1] = + bitmap[i+2] = bitmap[i+3] = 0x00; + weight = (weight == 1)? + (data.packed++, 128) : weight >> 1; + } + data.bitmap = bitmap; +} + +void +PkChar::unpack (void) +{ + if (unpacked) + return; + + if (dyn_f == 14) + unpack_bitmap(); + else + { + Bitmap bitmap (width, height); + + RleContext nr (data.packed, + first_is_black? BLACK : WHITE, + bitmap); + unpack_rle (nr); + unpacked = true; + data.bitmap = bitmap.steal_pixels (); + } +} + +PkChar::PkChar (AbstractLoader &loader) +{ + uint flag_byte = loader.get_uint8 (); + + dyn_f = flag_byte >> 4; + if (dyn_f == 15) + throw string ("Corrupt .pk file"); + + first_is_black = (flag_byte & 8)? true : false; + + uint length = 0; // to quiet gcc + + switch (flag_byte & 7) + { + case 0: case 1: case 2: case 3: + /* short preamble */ + length = loader.get_uint8 () + ((flag_byte & 3) << 8) - 8; + character_code = loader.get_uint8 (); + tfm_width = loader.get_uint24 (); + dx = loader.get_uint8 () << 16; + dy = 0; + width = loader.get_uint8 (); + height = loader.get_uint8 (); + hoffset = loader.get_int8 (); + voffset = loader.get_int8 (); + break; + + case 4: case 5: case 6: + /* extended short preamble */ + length = loader.get_uint16 () + ((flag_byte & 3) << 16) - 13; + cout << length; + character_code = loader.get_uint8 (); + cout << ',' << character_code; + tfm_width = loader.get_uint24 (); + dx = loader.get_uint16 () << 16; + dy = 0; + width = loader.get_uint16 (); + height = loader.get_uint16 (); + hoffset = loader.get_int16 (); + voffset = loader.get_int16 (); + break; + + case 7: + /* long preamble */ + length = loader.get_int32 () - 28; + character_code = loader.get_int32 (); + tfm_width = loader.get_int32 (); + dx = loader.get_int32 (); + dy = loader.get_int32 (); + width = loader.get_int32 (); + height = loader.get_int32 (); + hoffset = loader.get_int32 (); + voffset = loader.get_int32 (); + break; + + default: + /* should not be reached */ + break; + } + unpacked = false; + data.packed = new uchar[length]; + loader.get_n (length, data.packed); +} + +void +PkChar::paint (DviRuntime &runtime) +{ + const unsigned char *bitmap; + bitmap = get_bitmap (); + runtime.paint_bitmap (bitmap, + get_width(), get_height(), + get_hoffset(), get_voffset()); + +} +void +PkFont::load (void) +{ + PkOpcode c; + + c = (PkOpcode) loader.get_uint8 (); + if (c != DL_PK_PRE) + throw string ("Not a .pk file (no pre)"); + + id = loader.get_uint8 (); + if (id != 89) + throw string ("Not a .pk file (incorrect id)"); + + comment = loader.get_string8 (); + design_size = loader.get_uint32 (); + checksum = loader.get_uint32 (); + hppp = loader.get_uint32 (); + vppp = loader.get_uint32 (); + + do + { + c = (PkOpcode)loader.get_uint8 (); + switch (c) + { + case DL_PK_XXX1: + loader.skip_string8 (); + break; + case DL_PK_XXX2: + loader.skip_string16 (); + break; + case DL_PK_XXX3: + loader.skip_string24 (); + break; + case DL_PK_XXX4: + loader.skip_string32 (); + break; + case DL_PK_YYY: + loader.get_uint32 (); + break; + case DL_PK_POST: + break; + case DL_PK_NOP: + break; + case DL_PK_PRE: + throw string ("Unexpected PRE"); + break; + default: + loader.goto_from_current (-1); + if (c <= DL_PK_FIRST_COMMAND) + { + PkChar *pkc = new PkChar (loader); + chars[pkc->get_character_code()] = pkc; +#if 0 + cout << '[' << pkc->get_character_code() << ']'; +#endif + } + else + throw string ("Undefined PK command"); + break; + } + } while (c != DL_PK_POST); +} + +PkFont::PkFont (AbstractLoader& l, int at_size_arg) : + loader (l), + at_size (at_size_arg) +{ + load (); +} + +PkFont::PkFont (AbstractLoader& l) : + loader (l) +{ + load (); + at_size = design_size; +} diff --git a/dvi/dvilib/dl-pkfont.hh b/dvi/dvilib/dl-pkfont.hh new file mode 100755 index 0000000..66cd69b --- /dev/null +++ b/dvi/dvilib/dl-pkfont.hh @@ -0,0 +1,104 @@ +#ifndef DL_PKFONT_HH__ +#define DL_PKFONT_HH__ + +#include "dl-loader.hh" +#include "dl-refcounted.hh" +#include "dl-font.hh" + +#include +#include + +namespace DviLib { + + class RleContext; + + enum CountType { + RUN_COUNT, + REPEAT_COUNT + }; + + class PkChar : public AbstractCharacter { + uint dyn_f; + bool first_is_black; // if first run count is black or white + int character_code; + int tfm_width; // in what units? FIXME + uint dx; // escapement - what is this? FIXME + uint dy; + uint width; // in pixels + uint height; // in pixels + int hoffset; + int voffset; + + bool unpacked; + union { + unsigned char *bitmap; // 32 bit/pixel ARGB format + unsigned char *packed; + } data; + + CountType get_count (RleContext& nr, uint *count); + void unpack_rle (RleContext& nr); + void unpack_bitmap (void); + void unpack (void); + public: + PkChar (AbstractLoader &l); + virtual void paint (DviRuntime &runtime); + const unsigned char *get_bitmap (void) + { + if (!unpacked) + unpack (); + return data.bitmap; + } + uint get_width (void) + { + return width; + } + uint get_height (void) + { + return height; + } + virtual int get_tfm_width (void) + { + return tfm_width; + } + int get_hoffset (void) + { + return hoffset; + } + int get_voffset (void) + { + return voffset; + } + int get_character_code (void) { return character_code; } + }; + + class PkFont : public AbstractFont { + AbstractLoader& loader; + uint id; + string comment; + uint design_size; + uint checksum; + uint hppp; /* horizontal pixels per point */ + uint vppp; /* vertical pixels per point */ + map chars; + int at_size; + void load (void); + public: + PkFont (AbstractLoader& l); + PkFont (AbstractLoader& l, int at_size); + virtual PkChar *get_char (int ccode) + { + return chars[ccode]; + } + virtual int get_design_size (void) + { + return design_size; + } + virtual int get_at_size (void) + { + return at_size; + } + virtual ~PkFont () {} + }; +} + +#endif /* DL_PKFONT_HH__ */ diff --git a/dvi/dvilib/dl-refcounted.hh b/dvi/dvilib/dl-refcounted.hh new file mode 100755 index 0000000..068ac2e --- /dev/null +++ b/dvi/dvilib/dl-refcounted.hh @@ -0,0 +1,37 @@ +#ifndef DL_REFCOUNTED_HH +#define DL_REFCOUNTED_HH + +using namespace std; + +typedef unsigned int uint; +typedef unsigned char uchar; + +namespace DviLib { + + class RefCounted + { + int refcount; + + public: + + RefCounted (void) + { + refcount = 1; + } + + RefCounted *ref (void) + { + refcount++; + return this; + } + + void unref (void) + { + refcount--; + if (!refcount) + delete this; + } + }; +} + +#endif // DL_REFCOUNTED_HH diff --git a/dvi/dvilib/dl-vffont.cc b/dvi/dvilib/dl-vffont.cc new file mode 100755 index 0000000..91109d8 --- /dev/null +++ b/dvi/dvilib/dl-vffont.cc @@ -0,0 +1,16 @@ +#include "dl-vffont.hh" +#include "dl-dvi-parser.hh" + +using namespace DviLib; + +VfFont::VfFont (AbstractLoader &l, int at_size_arg) : + at_size (at_size_arg) +{ + DviParser parser (l); + preamble = parser.parse_vf_font_preamble (); + + VfChar *ch; + while ((ch = parser.parse_vf_char ()) != NULL) + chars[ch->character_code] = ch; +} + diff --git a/dvi/dvilib/dl-vffont.hh b/dvi/dvilib/dl-vffont.hh new file mode 100755 index 0000000..185e4a9 --- /dev/null +++ b/dvi/dvilib/dl-vffont.hh @@ -0,0 +1,55 @@ +#ifndef DL_VFFONT_HH__ +#define DL_VFFONT_HH__ + +#include "dl-dvi-file.hh" +#include "dl-dvi-fontdefinition.hh" +#include "dl-font.hh" + +namespace DviLib { + + class VfChar : public AbstractCharacter { + public: + int tfm_width; + DviProgram *program; + int character_code; + + virtual void paint (DviRuntime& runtime) + { + runtime.push(); + program->execute (runtime); // FIXME push, pop, etc. + runtime.pop(); + } + virtual int get_tfm_width () { return tfm_width; } + }; + + class VfFontPreamble : public RefCounted { + public: + string comment; + uint checksum; + uint design_size; + vector fontdefinitions; + }; + + class VfFont : public AbstractFont { + VfFontPreamble *preamble; + map chars; + int at_size; + public: + VfFont (AbstractLoader& l, int at_size); + virtual VfChar *get_char (int ccode) + { + return chars[ccode]; + }; + int get_design_size () + { + return preamble->design_size; + } + virtual int get_at_size () + { + /* FIXME (what is the correct thing to do here?) */ + return at_size; + } + virtual ~VfFont () {} + }; +} +#endif /* DL_VFFONT_HH__ */ -- cgit v0.9.1