summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipsk/unpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipsk/unpack.c')
-rw-r--r--Build/source/texk/dvipsk/unpack.c181
1 files changed, 181 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/unpack.c b/Build/source/texk/dvipsk/unpack.c
new file mode 100644
index 00000000000..493d6d7cb99
--- /dev/null
+++ b/Build/source/texk/dvipsk/unpack.c
@@ -0,0 +1,181 @@
+/*
+ * Unpacks the raster data from the packed buffer. This code was
+ * translated from pktopx.web using an automatic translator, then
+ * converted for this purpose. This little routine can be very useful
+ * in other drivers as well.
+ */
+#include "dvips.h" /* The copyright notice in that file is included too! */
+
+/*
+ * The external declarations:
+ */
+#include "protos.h"
+
+/*
+ * Some statics for use here.
+ */
+static halfword bitweight;
+static halfword dynf;
+static halfword gpower[17] = { 0 , 1 , 3 , 7 , 15 , 31 , 63 , 127 ,
+ 255 , 511 , 1023 , 2047 , 4095 , 8191 , 16383 , 32767 , 65535 };
+static long repeatcount;
+static quarterword *p;
+
+/*
+ * We need procedures to get a nybble, bit, and packed word from the
+ * packed data structure.
+ */
+
+static shalfword
+getnyb(void)
+{
+ if ( bitweight == 0 )
+ { bitweight = 16;
+ return(*p++ & 15);
+ } else {
+ bitweight = 0;
+ return(*p >> 4);
+ }
+}
+
+static Boolean
+getbit(void)
+{
+ bitweight >>= 1;
+ if ( bitweight == 0 )
+ { p++;
+ bitweight = 128;
+ }
+ return(*p & bitweight);
+}
+
+static long
+pkpackednum(void) {
+ register halfword i;
+ register long j;
+ i = getnyb ();
+ if ( i == 0 ) {
+ do { j = getnyb ();
+ i++;
+ } while ( j == 0 );
+ while ( i != 0 ) {
+ j = j * 16 + ((long) getnyb ());
+ i--;
+ }
+ return ( j - 15 + ( 13 - dynf ) * 16 + dynf );
+ }
+ else if ( i <= dynf ) return ( i );
+ else if ( i < 14 ) return ( ( i - dynf - 1 )*16 + getnyb() + dynf + 1 );
+ else {
+ if (repeatcount != 0)
+ error("! recursive repeat count in pk file");
+ repeatcount = 1;
+ if ( i == 14 ) repeatcount = pkpackednum ();
+ return ( pkpackednum() );
+ }
+}
+
+static void
+flip(register char *s, register long howmany)
+{
+ register char t;
+
+ while (howmany > 0) {
+ t = *s;
+ *s = s[1];
+ s[1] = t;
+ howmany--;
+ s += 2;
+ }
+}
+/*
+ * And now we have our main routine.
+ */
+static halfword bftest = 1;
+long
+unpack(quarterword *pack, halfword *raster,
+ halfword cwidth, halfword cheight, halfword cmd)
+{
+ register integer i, j;
+ shalfword wordwidth;
+ register halfword word, wordweight;
+ shalfword rowsleft;
+ Boolean turnon;
+ shalfword hbit, ww;
+ long count;
+ halfword *oraster;
+
+ oraster = raster;
+ p = pack;
+ dynf = cmd / 16;
+ turnon = cmd & 8;
+ wordwidth = (cwidth + 15)/16;
+ if ( dynf == 14 )
+ { bitweight = 256;
+ for ( i = 1; i <= cheight; i ++ )
+ { word = 0;
+ wordweight = 32768;
+ for ( j = 1; j <= cwidth; j ++ )
+ { if ( getbit () ) word += wordweight;
+ wordweight >>= 1;
+ if ( wordweight == 0 )
+ { *raster++ = word;
+ word = 0;
+ wordweight = 32768;
+ }
+ }
+ if ( wordweight != 32768 )
+ *raster++ = word;
+ }
+ } else {
+ rowsleft = cheight;
+ hbit = cwidth;
+ repeatcount = 0;
+ ww = 16;
+ word = 0;
+ bitweight = 16;
+ while ( rowsleft > 0 )
+ { count = pkpackednum();
+ while ( count != 0 )
+ { if ( ( count <= ww ) && ( count < hbit ) )
+ { if ( turnon ) word += gpower [ ww ] - gpower
+ [ ww - count ];
+ hbit -= count;
+ ww -= count;
+ count = 0;
+ }
+ else if ( ( count >= hbit ) && ( hbit <= ww ) )
+ { if ( turnon )
+ word += gpower[ww] - gpower[ww-hbit];
+ *raster++ = word;
+ for ( i = 1; i <= repeatcount; i ++ ) {
+ for ( j = 1; j <= wordwidth; j ++ ) {
+ *raster = *(raster - wordwidth);
+ raster++;
+ }
+ }
+ rowsleft -= repeatcount + 1;
+ repeatcount = 0;
+ word = 0;
+ ww = 16;
+ count -= hbit;
+ hbit = cwidth;
+ }
+ else
+ { if ( turnon ) word += gpower [ ww ];
+ *raster++ = word;
+ word = 0;
+ count -= ww;
+ hbit -= ww;
+ ww = 16;
+ }
+ }
+ turnon = ! turnon;
+ }
+ if ( ( rowsleft != 0 ) || ( (unsigned)hbit != cwidth ) )
+ error ( "! error while unpacking; more bits than required" );
+ }
+ if (*(char *)&bftest) /* is the hardware LittleEndian? */
+ flip((char *)oraster, ((cwidth + 15) >> 4) * (long)cheight);
+ return(p-pack);
+}