Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/dvi
diff options
context:
space:
mode:
Diffstat (limited to 'dvi')
-rw-r--r--dvi/Makefile38
-rw-r--r--dvi/dvilib/TODO2
-rwxr-xr-xdvi/dvilib/dl-dvi-file.cc50
-rwxr-xr-xdvi/dvilib/dl-dvi-file.hh99
-rwxr-xr-xdvi/dvilib/dl-dvi-fontdefinition.cc3
-rwxr-xr-xdvi/dvilib/dl-dvi-fontdefinition.hh22
-rwxr-xr-xdvi/dvilib/dl-dvi-parser.cc581
-rwxr-xr-xdvi/dvilib/dl-dvi-parser.hh35
-rwxr-xr-xdvi/dvilib/dl-dvi-program.cc30
-rwxr-xr-xdvi/dvilib/dl-dvi-program.hh272
-rwxr-xr-xdvi/dvilib/dl-dvi-runtime.cc2
-rwxr-xr-xdvi/dvilib/dl-dvi-runtime.hh45
-rwxr-xr-xdvi/dvilib/dl-font.hh27
-rwxr-xr-xdvi/dvilib/dl-loader.cc196
-rwxr-xr-xdvi/dvilib/dl-loader.hh59
-rwxr-xr-xdvi/dvilib/dl-pkfont.cc379
-rwxr-xr-xdvi/dvilib/dl-pkfont.hh104
-rwxr-xr-xdvi/dvilib/dl-refcounted.hh37
-rwxr-xr-xdvi/dvilib/dl-vffont.cc16
-rwxr-xr-xdvi/dvilib/dl-vffont.hh55
-rw-r--r--dvi/fest.tex23
-rwxr-xr-xdvi/font.cc169
-rwxr-xr-xdvi/font.hh23
-rwxr-xr-xdvi/main.cc31
-rwxr-xr-xdvi/model.cc23
-rwxr-xr-xdvi/model.hh61
-rwxr-xr-xdvi/observer.hh15
-rwxr-xr-xdvi/painter.cc334
-rwxr-xr-xdvi/painter.hh94
-rwxr-xr-xdvi/view.cc113
-rwxr-xr-xdvi/view.hh37
31 files changed, 2975 insertions, 0 deletions
diff --git a/dvi/Makefile b/dvi/Makefile
new file mode 100644
index 0000000..3ba3611
--- /dev/null
+++ b/dvi/Makefile
@@ -0,0 +1,38 @@
+binary = dviviewer
+
+sources = \
+ main.cc \
+ \
+ painter.cc \
+ font.cc \
+ view.cc \
+ model.cc \
+ \
+ dvilib/dl-dvi-file.cc \
+ dvilib/dl-dvi-fontdefinition.cc \
+ dvilib/dl-dvi-parser.cc \
+ dvilib/dl-dvi-program.cc \
+ dvilib/dl-dvi-runtime.cc \
+ dvilib/dl-loader.cc \
+ dvilib/dl-pkfont.cc \
+ dvilib/dl-vffont.cc
+
+headers = \
+ painter.hh \
+ font.hh \
+ view.hh \
+ model.hh \
+ \
+ dvilib/dl-dvi-file.hh \
+ dvilib/dl-dvi-fontdefinition.hh \
+ dvilib/dl-dvi-parser.hh \
+ dvilib/dl-dvi-runtime.hh \
+ dvilib/dl-font.hh \
+ dvilib/dl-loader.hh \
+ dvilib/dl-pkfont.hh \
+ dvilib/dl-vffont.hh
+
+CFLAGS = -Idvilib -Wall -W -ansi -pedantic -g -O0 `pkg-config --cflags gtk+-2.0`
+
+$(binary): $(sources) $(headers)
+ c++ $(CFLAGS) $(sources) -o$(binary) -lfl `pkg-config --libs gtk+-2.0`
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 <map>
+#include <list>
+#include <algorithm>
+#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<N_PAGE_COUNTERS; ++i)
+ count[i] = c[i];
+ }
+ DviPage (DviPageHeader& h, DviProgram& p) :
+ program (p)
+ {
+ for (uint i=0; i<N_PAGE_COUNTERS; ++i)
+ count[i] = h.count[i];
+ }
+ virtual void execute (DviRuntime& runtime)
+ {
+ program.execute (runtime);
+ }
+ int get_page_count (int i) { return count[i]; }
+ };
+
+ enum DviType {
+ NORMAL_DVI = 2, // FIXME: this should be 2
+ TEX_XET_DVI = 2 // FIXME: is this correct?
+ };
+
+ class DviFilePreamble : public RefCounted {
+ public:
+ // preamble
+ DviType type;
+ uint magnification;
+ uint numerator;
+ uint denominator;
+ string comment;
+ };
+
+ class DviFilePostamble : public RefCounted {
+ public:
+ // postamble
+ DviType type;
+ uint magnification;
+ uint numerator;
+ uint denominator;
+
+ uint last_page_address;
+ uint max_height;
+ uint max_width;
+ uint stack_height;
+ map <uint, DviFontdefinition *> fontdefinitions;
+ };
+
+ class DviFile : public RefCounted {
+ AbstractLoader &loader;
+
+ DviFilePreamble *preamble;
+ DviFilePostamble *postamble;
+
+ uint n_pages;
+ map <uint, DviPageHeader *> page_headers;
+ map <uint, DviPage *> 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 <string>
+
+#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; i<N_PAGE_COUNTERS; ++i)
+ header->count[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; i<dirlength; ++i)
+ fontdef->directory += loader.get_uint8();
+ for (uint i=0; i<namelength; ++i)
+ fontdef->name += 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 <algorithm>
+
+using namespace DviLib;
+
+typedef vector<DviCommand *>::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 <string>
+#include <vector>
+
+#include <iostream>
+
+#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 <DviCommand *> 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 <string>
+#include <map>
+
+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<int, DviFontdefinition *> 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 <vector>
+#include <map>
+
+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 <errno.h>
+#include <iostream>
+
+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 <string>
+#include <cstdio>
+#include <vector>
+
+#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 <algorithm>
+#include <iostream>
+
+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 <vector>
+#include <map>
+
+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 <uint, PkChar *> 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 <DviFontdefinition *> fontdefinitions;
+ };
+
+ class VfFont : public AbstractFont {
+ VfFontPreamble *preamble;
+ map <int, VfChar *> 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__ */
diff --git a/dvi/fest.tex b/dvi/fest.tex
new file mode 100644
index 0000000..1ae5083
--- /dev/null
+++ b/dvi/fest.tex
@@ -0,0 +1,23 @@
+\documentclass[a4paper, danish]{article}
+
+\usepackage{times}
+\usepackage[T1]{fontenc}
+\usepackage{babel}
+
+\begin{document}
+
+\section{Title}
+
+{\large Hej verden\par}
+
+{\large Bl\aa b\ae rgr\o d\par}
+
+\subsection {Subtitle}
+
+Math: $\sum_{i=0}^\infty \frac{1}{i^2} = \frac{\pi^2}{6}$
+
+{\large\bf Big, bold\par}
+
+{\Huge\bf Huge, bold\par}
+
+\end{document}
diff --git a/dvi/font.cc b/dvi/font.cc
new file mode 100755
index 0000000..512370e
--- /dev/null
+++ b/dvi/font.cc
@@ -0,0 +1,169 @@
+#include "font.hh"
+
+#include "painter.hh"
+#include "dl-pkfont.hh"
+#include "dl-vffont.hh"
+
+using DviLib::FileLoader;
+using DviLib::AbstractFont;
+using DviLib::VfChar;
+using DviLib::PkChar;
+using DviLib::PkFont;
+using DviLib::VfFont;
+
+static char *
+do_run_program (const char *program,
+ GList *args,
+ GError **err)
+{
+ char **argv = g_new (char *, g_list_length (args) + 2);
+ GList *l;
+ int i;
+ char *result;
+
+ i = 0;
+ argv[i++] = g_strdup (program);
+ for (l = args; l; l = l->next)
+ argv[i++] = g_strdup ((char *)l->data);
+ argv[i++] = NULL;
+
+ g_list_free (args);
+
+
+ /* run it */
+ g_spawn_sync (NULL, /* working directory */
+ argv, /* arguments */
+ NULL, /* environment */
+ G_SPAWN_SEARCH_PATH, /* flags */
+ NULL, /* child setup */
+ NULL, /* user data for child setup */
+ &result, /* stdout */
+ NULL, /* stderr */
+ NULL, /* exit status */
+ err /* GError */);
+
+ g_strfreev (argv);
+
+ return result;
+}
+
+
+static char *
+run_program (const char *program,
+ GError **err,
+ const char *arg1,
+ ...)
+{
+ va_list arg_list;
+ GList *arguments = NULL;
+ char *s;
+
+ va_start (arg_list, arg1);
+
+ arguments = g_list_append (arguments, (gpointer)arg1);
+
+ s = va_arg (arg_list, gchar*);
+ while (s)
+ {
+ arguments = g_list_append (arguments, s);
+ s = va_arg (arg_list, gchar*);
+ }
+
+ va_end (arg_list);
+
+ return do_run_program (program, arguments, err);
+}
+
+static char *
+run_kpsewhich (int dpi,
+ string format,
+ string name)
+{
+ char *dpistr = g_strdup_printf ("--dpi=%d", dpi);
+ char *formatstr = g_strdup_printf ("--format=%s", format.c_str());
+ char *namestr = g_strdup (name.c_str());
+ GError *err = NULL;
+ char *result;
+
+ result = run_program ("kpsewhich", &err, dpistr, formatstr, namestr, NULL);
+
+ if (!result)
+ {
+ cout << err->message << endl;
+ }
+ else
+ {
+ g_strstrip (result);
+
+ if (*result == '\0')
+ {
+ /* Nothing useful returned */
+ g_free (result);
+ result = NULL;
+ }
+ }
+
+ cout << "kpsewhich " << dpistr << " " << formatstr << " " << namestr << " " << endl;
+
+ g_free (dpistr);
+ g_free (formatstr);
+ g_free (namestr);
+
+ return result;
+}
+
+static void
+run_mktexpk (int dpi, string name)
+{
+ char *dpistr = g_strdup_printf ("--bdpi=%d", dpi);
+ char *bdpistr = g_strdup_printf ("--dpi=%d", dpi);
+ char *namestr = g_strdup (name.c_str());
+ char *result;
+
+ result = run_program ("mktexpk", NULL, bdpistr, dpistr, namestr, NULL);
+ if (result)
+ g_free (result);
+
+ g_free (dpistr);
+ g_free (bdpistr);
+ g_free (namestr);
+}
+
+AbstractFont *
+FontFactory::create_font (std::string name,
+ int dpi,
+ int at_size)
+{
+ char *filename;
+
+ /* Find VF */
+ filename = run_kpsewhich (dpi, "vf", name);
+
+ if (filename)
+ return new VfFont (*new FileLoader (filename), at_size);
+
+ /* Try PK */
+
+ filename = run_kpsewhich (dpi, "pk", name);
+
+ if (filename)
+ return new PkFont (*new FileLoader (filename), at_size);
+
+ /* Generate PK */
+
+ run_mktexpk (dpi, name);
+
+ cout << "birnan" << endl;
+
+ /* Try PK again */
+ filename = run_kpsewhich (dpi, "pk", name);
+
+ if (filename)
+ return new PkFont (*new FileLoader (filename), at_size);
+
+ cout << "no luck" << endl;
+
+ throw (string ("bad font"));
+
+ return NULL;
+}
diff --git a/dvi/font.hh b/dvi/font.hh
new file mode 100755
index 0000000..5f34c07
--- /dev/null
+++ b/dvi/font.hh
@@ -0,0 +1,23 @@
+#ifndef FONT_HH
+#define FONT_HH
+
+#include "dl-dvi-program.hh"
+#include "dl-font.hh"
+
+// Font factories
+
+class AbstractFontFactory : public DviLib::RefCounted {
+public:
+ virtual DviLib::AbstractFont *create_font (std::string name,
+ int dpi,
+ int at_size) = 0;
+};
+
+class FontFactory : public AbstractFontFactory {
+public:
+ virtual DviLib::AbstractFont *create_font (std::string name,
+ int dpi,
+ int at_size);
+};
+
+#endif
diff --git a/dvi/main.cc b/dvi/main.cc
new file mode 100755
index 0000000..1037256
--- /dev/null
+++ b/dvi/main.cc
@@ -0,0 +1,31 @@
+#include <gtk/gtk.h>
+
+#include "model.hh"
+#include "view.hh"
+#include "painter.hh"
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window, *scrwin;
+
+ gtk_init (&argc, &argv);
+
+ Model *model = new Model ("fest.dvi");
+ View *view = new View (model);
+
+
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ scrwin = gtk_scrolled_window_new (NULL, NULL);
+
+ gtk_container_add (GTK_CONTAINER (window), scrwin);
+
+ gtk_scrolled_window_add_with_viewport (GTK_SCROLLED_WINDOW (scrwin), view->get_widget());
+
+ gtk_widget_show_all (GTK_WIDGET (window));
+
+ gtk_main ();
+
+ return 0;
+}
diff --git a/dvi/model.cc b/dvi/model.cc
new file mode 100755
index 0000000..154352e
--- /dev/null
+++ b/dvi/model.cc
@@ -0,0 +1,23 @@
+#include "model.hh"
+
+Model::Model (string file_name)
+{
+ try {
+ FileLoader *fl = new FileLoader (file_name);
+ dvi_file = new DviFile (*fl);
+ state = HAS_FILE;
+ }
+ catch (string e) {
+ dvi_file = 0;
+ state = ERROR;
+ err_msg = e;
+ cout << "error" << endl;
+ }
+}
+
+Model::Model (void)
+{
+ state = NO_FILE;
+ dvi_file = 0;
+}
+
diff --git a/dvi/model.hh b/dvi/model.hh
new file mode 100755
index 0000000..749c640
--- /dev/null
+++ b/dvi/model.hh
@@ -0,0 +1,61 @@
+#ifndef MODEL_HH
+#define MODEL_HH
+
+#include "dl-refcounted.hh"
+#include "dl-dvi-file.hh"
+#include "observer.hh"
+#include <list>
+
+enum ModelState {
+ HAS_FILE,
+ NO_FILE,
+ ERROR
+};
+
+using DviLib::FileLoader;
+using DviLib::DviFile;
+using DviLib::RefCounted;
+using std::string;
+
+class Model : public RefCounted {
+ ModelState state;
+ DviFile *dvi_file;
+ string file_name;
+ string err_msg;
+ vector <Observer *> observers;
+
+public:
+ Model (string file_name);
+ Model (void);
+ void add_observer (Observer& o)
+ {
+ observers.push_back (&o);
+ }
+ void notify (void)
+ {
+ typedef vector <Observer *>::const_iterator It;
+ for (It i = observers.begin(); i != observers.end(); ++i)
+ (*i)->notify ();
+ }
+ ModelState get_state (void) { return state; }
+ string get_error (void) {
+ if (state == ERROR)
+ return err_msg;
+ else
+ return "";
+ };
+ DviFile *get_dvi_file (void) {
+ if (state == HAS_FILE)
+ return dvi_file;
+ else
+ return 0;
+ };
+ string get_file_name (void) {
+ if (state == HAS_FILE)
+ return file_name;
+ else
+ return "";
+ };
+};
+
+#endif
diff --git a/dvi/observer.hh b/dvi/observer.hh
new file mode 100755
index 0000000..488fc52
--- /dev/null
+++ b/dvi/observer.hh
@@ -0,0 +1,15 @@
+#ifndef OBSERVER_HH
+#define OBSERVER_HH
+
+#include <dl-refcounted.hh>
+
+using DviLib::RefCounted;
+
+class Observer : public RefCounted {
+public:
+ virtual void notify (void) const = 0;
+ virtual ~Observer() {}
+};
+
+
+#endif /* OBSERVER_HH */
diff --git a/dvi/painter.cc b/dvi/painter.cc
new file mode 100755
index 0000000..a1bb758
--- /dev/null
+++ b/dvi/painter.cc
@@ -0,0 +1,334 @@
+#include "painter.hh"
+#include "dl-dvi-fontdefinition.hh"
+
+using DviLib::DviFontdefinition;
+using DviLib::AbstractCharacter;
+
+// paint a bitmap
+void
+DviPainter::paint_bitmap (const unsigned char *data,
+ uint width, uint height,
+ int hoffset, int voffset)
+{
+ GdkPixbuf *pixbuf =
+ gdk_pixbuf_new_from_data (data,
+ GDK_COLORSPACE_RGB,
+ TRUE, // has_alpha,
+ 8,
+ width,
+ height,
+ width * 4, // rowstride
+ NULL, // destroy_fn
+ NULL); // destroy_fn_data
+
+ uint x = dvi_to_pixels (current_frame->h);
+ uint y = dvi_to_pixels (current_frame->v);
+
+ gdk_pixbuf_render_to_drawable (pixbuf,
+ pixmap,
+ gc,
+ 0, 0,
+ x-hoffset,
+ y-voffset,
+ //y+(height - voffset),
+ width,
+ height,
+ GDK_RGB_DITHER_NONE,
+ 0, 0);
+}
+
+// typeset ch, move w
+void
+DviPainter::set_char (int ch)
+{
+ g_assert (current_font);
+
+ AbstractCharacter *character = current_font->get_char (ch);
+ character->paint (* this);
+
+ int tfm_width = character->get_tfm_width ();
+ int at_size = current_font->get_at_size ();
+ int dvi_width = tfm_to_dvi (tfm_width, at_size);
+
+ current_frame->h += dvi_width;
+}
+
+// typeset ch, don't move
+void
+DviPainter::put_char (int ch)
+{
+ AbstractCharacter *character = current_font->get_char (ch);
+ character->paint (* this);
+}
+
+void
+// rule, move (height, width)
+DviPainter::set_rule (int height,
+ int width)
+{
+ int width_p = dvi_to_pixels_no_offset (width);
+ int height_p = dvi_to_pixels_no_offset (height);
+ int x = dvi_to_pixels (current_frame->h);
+ int y = dvi_to_pixels (current_frame->v);
+
+ cout << "BIRNAN\n" << endl;
+
+ gdk_draw_rectangle (pixmap, gc, TRUE,
+ x, y,
+ width_p + 1, height_p + 1);
+
+ current_frame->h += width;
+}
+
+// rule, don't move
+void
+DviPainter::put_rule (int height,
+ int width)
+{
+ cout << "w h " << width << " " << height << " " << endl;
+
+ int width_p = dvi_to_pixels_no_offset (width);
+ int height_p = dvi_to_pixels_no_offset (height);
+ int x = dvi_to_pixels (current_frame->h);
+ int y = dvi_to_pixels (current_frame->v);
+
+ cout << "EMFLE\n" << endl;
+
+ cout << "x y h w " << x << " " << y << " " << height_p << " "
+ << width_p << endl;
+
+ gdk_draw_rectangle (pixmap, gc, TRUE,
+ x, y,
+ width_p + 1, height_p + 1);
+}
+
+// push current context
+DviFrame *
+DviFrame::copy (void)
+{
+ DviFrame *frame = new DviFrame ();
+
+ frame->h = this->h;
+ frame->v = this->v;
+ frame->w = this->w;
+ frame->x = this->x;
+ frame->y = this->y;
+ frame->z = this->z;
+
+ return frame;
+}
+
+void
+DviPainter::push (void)
+{
+ DviFrame *new_frame = current_frame->copy();
+ new_frame->next = current_frame;
+ current_frame = new_frame;
+}
+
+// pop ccontext
+void
+DviPainter::pop (void)
+{
+ DviFrame *old_frame = current_frame;
+
+ current_frame = current_frame->next;
+
+ old_frame->unref();
+}
+
+// move right len
+void
+DviPainter::right (int len)
+{
+ current_frame->h += len;
+}
+
+// move right len, set w = len
+void
+DviPainter::w (int len)
+{
+ right (len);
+ current_frame->w = len;
+}
+
+// move right w
+void
+DviPainter::w_rep ()
+{
+ right (current_frame->w);
+}
+
+// move right len, set x = len
+void
+DviPainter::x (int len)
+{
+ right (len);
+ current_frame->x = len;
+}
+
+// move right x
+void
+DviPainter::x_rep ()
+{
+ right (current_frame->x);
+}
+
+// move down len
+void
+DviPainter::down (int len)
+{
+ current_frame->v += len;
+}
+
+// move down len, set y = len
+void
+DviPainter::y (int len)
+{
+ down (len);
+ current_frame->y = len;
+}
+
+// move down y
+void
+DviPainter::y_rep ()
+{
+ down (current_frame->y);
+}
+
+// move down len, set z = len
+void
+DviPainter::z (int len)
+{
+ down (len);
+ current_frame->z = len;
+}
+
+// move down z
+void
+DviPainter::z_rep ()
+{
+ down (current_frame->z);
+}
+
+// f = font_num
+void
+DviPainter::font_num (int font_num)
+{
+ cout << "get fno " << font_num << endl;
+ DviFontdefinition *fd = dvi_file->get_fontdefinition (font_num);
+
+ g_assert (fd);
+ if (fd)
+ {
+ // gtkdvi:
+ int dpi = (int)floor( 0.5 + 1.0 * base_dpi *
+ dvi_file->get_magnification() * fd->at_size /
+ ( 1000.0 * fd->design_size));
+ cout << "fno: " << fd->fontnum << endl;
+ cout << fd->name << endl;
+ current_font =
+ font_factory->create_font (fd->name, dpi, fd->at_size);
+ }
+}
+
+// do something special
+void
+DviPainter::special (string spc)
+{
+ cout << "warning: special " << spc << " " << "not handled" << endl;
+}
+
+int
+DviPainter::tfm_to_dvi (uint tfm, int at_size)
+{
+ // this is from gtkdvi:
+ int alpha, z, beta, b0, b1, b2, b3, r;
+
+ alpha = 16;
+ z = at_size;
+ while (z >= (1<<23))
+ {
+ z >>= 1;
+ alpha <<= 1;
+ }
+ beta = 256/alpha;
+ alpha *= z;
+
+#if 0
+ b0 = tfm & (0xFF << 24);
+ b1 = tfm & (0xFF << 16);
+ b2 = tfm & (0xFF << 8);
+ b3 = tfm & (0xFF << 0);
+#endif
+
+ b0 = tfm >> 24;
+ b1 = (tfm >> 16) & 255;
+ b2 = (tfm >> 8) & 255;
+ b3 = tfm & 255;
+
+#if 0
+ r = (((((b3 * z) / 256) + (b2 * z)) / 256) + (b1 * z))/beta;
+#endif
+
+ b1 *= z;
+ b2 *= z;
+ b3 *= z;
+
+ r = (((b3 / 256 + b2) / 256) + b1) / beta;
+
+ if (b0 > 0)
+ {
+ if ((b0 > 0) != (tfm > 0))
+ cout << "b0: " << b0 << "tfm: " << tfm << endl;
+ r -= alpha;
+ }
+
+ return r;
+}
+
+DviPainter::DviPainter (GdkPixmap *pixmap_arg,
+ GdkGC *gc_arg,
+ DviLib::DviFile *dvi_file_arg,
+ uint base_dpi_arg,
+ AbstractFontFactory *font_factory_arg)
+{
+ pixmap = (GdkPixmap *)g_object_ref (pixmap_arg);
+ gc = (GdkGC *)g_object_ref (gc_arg);
+ dvi_file = dvi_file_arg;
+ base_dpi = base_dpi_arg;
+ font_factory = font_factory_arg;
+
+ dvi_file->ref();
+ font_factory->ref();
+
+ current_font = 0;
+
+ current_frame = new DviFrame;
+ current_frame->h = 0;
+ current_frame->v = 0;
+ current_frame->w = 0;
+ current_frame->x = 0;
+ current_frame->y = 0;
+ current_frame->z = 0;
+
+ // from gtkdvi:
+ scale = dvi_file->get_numerator() / 254000.0;
+ scale *= 1.0 * base_dpi / dvi_file->get_denominator ();
+ scale *= dvi_file->get_magnification () / 1000.0;
+}
+
+DviPainter::~DviPainter ()
+{
+ g_object_unref (pixmap);
+ g_object_unref (gc);
+ dvi_file->unref();
+ font_factory->unref();
+ while (current_frame)
+ pop();
+}
+
+void
+DviPainter::push_fontmap (std::map<int, DviFontdefinition *> fontmap)
+{
+}
diff --git a/dvi/painter.hh b/dvi/painter.hh
new file mode 100755
index 0000000..cbb968b
--- /dev/null
+++ b/dvi/painter.hh
@@ -0,0 +1,94 @@
+#ifndef PAINTER_HH
+#define PAINTER_HH
+
+#include "dl-dvi-program.hh"
+#include "dl-dvi-file.hh"
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include "font.hh"
+#include <gdk/gdk.h>
+#include <cmath>
+#include <list>
+
+class AbstractDviPainter : public DviLib::DviRuntime
+{
+public:
+ virtual void paint_bitmap (const unsigned char *data,
+ uint width,
+ uint height,
+ int hoffset,
+ int voffseth) = 0;
+ virtual ~AbstractDviPainter () {}
+};
+
+class DviFrame : public DviLib::RefCounted
+{
+public:
+ int h, v, w, x, y, z; // in dvi units
+ DviFrame *next;
+ DviFrame *copy ();
+};
+
+class DviPainter : public AbstractDviPainter
+{
+public:
+ virtual void set_char (int ch); // typeset ch, move w
+ virtual void put_char (int ch); // typeset ch, don't move
+ virtual void set_rule (int height,
+ int width); // rule, move (height, width)
+ virtual void put_rule (int height,
+ int width); // rule, don't move
+ virtual void push (void); // push current context
+ virtual void pop (void); // pop ccontext
+ virtual void right (int len); // move right len
+ virtual void w (int len); // move right len, set w = len
+ virtual void w_rep (); // move right w
+ virtual void x (int len); // move right len, set x = len
+ virtual void x_rep (); // move right x
+ virtual void down (int len); // move down len
+ virtual void y (int len); // move down len, set y = len
+ virtual void y_rep (); // move down y
+ virtual void z (int len); // move down len, set z = len
+ virtual void z_rep (); // move down z
+ virtual void push_fontmap (std::map<int, DviLib::DviFontdefinition *> fontmap);
+ virtual void font_num (int font_num); // current_font = fd
+ virtual void special (string spc); // do something special
+ virtual void paint_bitmap (const unsigned char *data,
+ uint width,
+ uint height,
+ int voffset,
+ int hoffset);
+private:
+ GdkPixmap *pixmap;
+ GdkGC *gc;
+ DviLib::DviFile *dvi_file;
+ uint base_dpi;
+ AbstractFontFactory *font_factory;
+
+ // runtime
+ DviLib::AbstractFont *current_font;
+ DviFrame *current_frame; // stack of DVI frames
+
+ double scale; // convert dvi units to pixels
+ int dvi_to_pixels (int du)
+ {
+ // We add base_dpi horizontally and vertically. This
+ // has the effect of adding an inch horizontally and
+ // vertically. This is just how .dvi files work ...
+ return (int)floor (0.5 + scale * du) + base_dpi;
+ }
+ int dvi_to_pixels_no_offset (int du)
+ {
+ return (int)floor (0.5 + scale * du);
+ }
+ int tfm_to_dvi (uint tfm, int at_size);
+
+public:
+ DviPainter (GdkPixmap *pixmap_arg,
+ GdkGC *gc_arg,
+ DviLib::DviFile *dvi_file_arg,
+ uint base_dpi_arg,
+ AbstractFontFactory *font_factory_arg);
+ virtual ~DviPainter ();
+};
+
+#endif
diff --git a/dvi/view.cc b/dvi/view.cc
new file mode 100755
index 0000000..0f2f4b5
--- /dev/null
+++ b/dvi/view.cc
@@ -0,0 +1,113 @@
+#include "view.hh"
+#include "dl-dvi-fontdefinition.hh"
+
+using DviLib::DviPage;
+using DviLib::DviFontdefinition;
+
+View::View (Model *model_arg)
+{
+ model = model_arg;
+
+ model->add_observer (*this);
+
+ drawing_area = gtk_drawing_area_new ();
+ gtk_widget_show (drawing_area);
+ gtk_drawing_area_size (GTK_DRAWING_AREA (drawing_area),
+ BASE_DPI * PAPER_WIDTH,
+ BASE_DPI * PAPER_HEIGHT);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "realize",
+ (GtkSignalFunc) on_da_realize, this);
+ gtk_signal_connect (GTK_OBJECT (drawing_area), "expose_event",
+ (GtkSignalFunc) on_da_expose, this);
+}
+
+void
+View::create_pixmap (void)
+{
+ pixmap = gdk_pixmap_new(drawing_area->window,
+ BASE_DPI * PAPER_WIDTH,
+ BASE_DPI * PAPER_HEIGHT,
+ -1);
+}
+
+void
+View::expose (GdkEventExpose *event)
+{
+ gdk_draw_pixmap (
+ drawing_area->window,
+ drawing_area->style->fg_gc[GTK_WIDGET_STATE (drawing_area)],
+ pixmap,
+ event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+}
+
+void
+View::redraw (void) const
+{
+ // clear page
+ gdk_draw_rectangle (pixmap,
+ drawing_area->style->white_gc,
+ TRUE, 0, 0,
+ BASE_DPI * PAPER_WIDTH,
+ BASE_DPI * PAPER_HEIGHT);
+
+ cout << "width " << BASE_DPI * PAPER_WIDTH << endl;
+ cout << "height " << BASE_DPI * PAPER_HEIGHT << endl;
+
+ // create a painter
+ DviPainter *painter =
+ new DviPainter (pixmap,
+ drawing_area->style->fg_gc[GTK_WIDGET_STATE
+ (drawing_area)],
+ model->get_dvi_file (),
+ BASE_DPI,
+ new FontFactory());
+ // get page
+ DviPage *page;
+ try
+ {
+ page = model->get_dvi_file ()->get_page (0);
+ }
+ catch (string s)
+ {
+ cout << s;
+ abort ();
+ }
+
+ // draw it with the painter
+ page->execute (* painter);
+
+}
+
+void
+View::notify (void) const
+{
+ ModelState state = model->get_state ();
+
+ switch (state) {
+ case HAS_FILE:
+ redraw ();
+ break;
+
+ case NO_FILE:
+ break;
+
+ case ERROR:
+ break;
+ }
+}
+
+void
+on_da_realize (GtkDrawingArea *da, View *v)
+{
+ v->create_pixmap ();
+ v->notify ();
+}
+
+gint
+on_da_expose (GtkWidget *widget, GdkEventExpose *event, View *v)
+{
+ v->expose (event);
+ return FALSE;
+}
diff --git a/dvi/view.hh b/dvi/view.hh
new file mode 100755
index 0000000..bdab6df
--- /dev/null
+++ b/dvi/view.hh
@@ -0,0 +1,37 @@
+// notes:
+/*
+ * hold en gdkpixbuf ved lige, og tegn den på en gtkdrawingarea
+ * ved passende lejligheder
+ */
+
+#include "model.hh"
+#include <gtk/gtk.h>
+#include "painter.hh"
+
+enum {
+ BASE_DPI = 300,
+ PAPER_WIDTH = 7, // inches
+ PAPER_HEIGHT = 17 // inches
+};
+
+class View : public Observer {
+private:
+ Model *model;
+ GtkWidget *drawing_area;
+ GdkPixmap *pixmap;
+public:
+ View (Model *model_arg);
+
+ GtkWidget *get_widget (void) { return drawing_area; }
+
+ void create_pixmap (void);
+ void expose (GdkEventExpose *event);
+ void notify (void) const;
+ void redraw (void) const;
+};
+
+void on_da_realize (GtkDrawingArea *da,
+ View *v);
+int on_da_expose (GtkWidget *widget,
+ GdkEventExpose *event,
+ View *v);