Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/dvi/dvilib/dl-pkfont.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dvi/dvilib/dl-pkfont.cc')
-rwxr-xr-xdvi/dvilib/dl-pkfont.cc379
1 files changed, 379 insertions, 0 deletions
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;
+}