summaryrefslogtreecommitdiff
path: root/dviware/dvipage/sample.c
diff options
context:
space:
mode:
authorNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
committerNorbert Preining <norbert@preining.info>2019-09-02 13:46:59 +0900
commite0c6872cf40896c7be36b11dcc744620f10adf1d (patch)
tree60335e10d2f4354b0674ec22d7b53f0f8abee672 /dviware/dvipage/sample.c
Initial commit
Diffstat (limited to 'dviware/dvipage/sample.c')
-rw-r--r--dviware/dvipage/sample.c1245
1 files changed, 1245 insertions, 0 deletions
diff --git a/dviware/dvipage/sample.c b/dviware/dvipage/sample.c
new file mode 100644
index 0000000000..7262e31993
--- /dev/null
+++ b/dviware/dvipage/sample.c
@@ -0,0 +1,1245 @@
+/*
+ * dvipage: DVI Previewer Program for Suns
+ *
+ * Neil Hunt (hunt@spar.slb.com)
+ *
+ * This program is based, in part, upon the program dvisun,
+ * distributed by the UnixTeX group, extensively modified by
+ * Neil Hunt at the Schlumberger Palo Alto Research Laboratories
+ * of Schlumberger Technologies, Inc.
+ *
+ * Copyright (c) 1988 Schlumberger Technologies, Inc 1988.
+ * Anyone can use this software in any manner they choose,
+ * including modification and redistribution, provided they make
+ * no charge for it, and these conditions remain unchanged.
+ *
+ * This program is distributed as is, with all faults (if any), and
+ * without any warranty. No author or distributor accepts responsibility
+ * to anyone for the consequences of using it, or for whether it serves any
+ * particular purpose at all, or any other reason.
+ *
+ * $Log: sample.c,v $
+ * Revision 1.1 88/11/28 18:41:24 hunt
+ * Initial revision
+ *
+ * Split out of dvipage.c version 1.4.
+ */
+
+#include <stdio.h>
+#include <sys/param.h> /* For MAXPATHLEN */
+#include <suntool/sunview.h>
+#include <suntool/canvas.h>
+#include "dvipage.h"
+
+forward struct pixrect * pr_alloc();
+forward struct pixrect * pr_free();
+forward struct pixrect * pr_check();
+forward struct pixrect * pr_link();
+forward struct pixrect * pr_sample_4();
+forward struct pixrect * pr_sample_34();
+forward struct pixrect * pr_sample_3();
+forward struct pixrect * pr_sample_2();
+
+forward void pw_cover();
+forward void pr_rect();
+forward void pw_rect();
+
+/*
+ * sample_page:
+ * Filter and sample down page according to current sampling rate,
+ * and prepare for display.
+ */
+
+void
+sample_page()
+{
+
+#ifdef TIMING
+ start_time();
+#endif TIMING
+
+ switch(sampling)
+ {
+ default:
+ case 1:
+ sample_pr = pr_link(&page_mpr, &sample_mpr);
+ break;
+
+ case 2:
+ if(! (sample_pr = pr_sample_2(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+
+ case 3:
+ if(! (sample_pr = pr_sample_3(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+
+ case 4:
+ if(! (sample_pr = pr_sample_4(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+
+ case 5:
+ if(! (sample_pr = pr_sample_34(&page_mpr, &sample_mpr)))
+ message("Out of memory for resampling image");
+ break;
+ }
+
+#ifdef TIMING
+ stop_time("Sampling one page");
+#endif TIMING
+
+}
+
+/*
+ * Here follow some functions to deal with pixrects under the special case
+ * assumption that they are mem_pixrects, where the mpr_data is part
+ * of a parent structure.
+ */
+
+extern struct pixrectops mem_ops;
+
+/*
+ * pr_alloc:
+ * Allocate memory for a pixrect of size w, h, d.
+ * Returns a pointer to the pixrect structure.
+ */
+
+struct pixrect *
+pr_alloc(mpr, w, h, d)
+struct mem_pixrect *mpr;
+int w, h, d;
+{
+ int size;
+ int linebytes;
+ short *image;
+
+ /*
+ * Compute the size of memory needed, and alloc it.
+ */
+ linebytes = mpr_linebytes(w, d);
+ size = linebytes * h;
+ if(! (image = (short *)malloc(size)))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Set up the pr.
+ */
+ mpr->mpr_pr.pr_ops = &mem_ops;
+ mpr->mpr_pr.pr_width = w;
+ mpr->mpr_pr.pr_height = h;
+ mpr->mpr_pr.pr_depth = d;
+ mpr->mpr_pr.pr_data = (caddr_t)&mpr->mpr_data;
+
+ /*
+ * Set up the mpr_data
+ */
+ mpr->mpr_data.md_linebytes = linebytes;
+ mpr->mpr_data.md_image = image;
+ mpr->mpr_data.md_offset.x = 0;
+ mpr->mpr_data.md_offset.y = 0;
+ mpr->mpr_data.md_primary = TRUE;
+ mpr->mpr_data.md_flags = 0;
+
+ /*
+ * Return the pr.
+ */
+ return &mpr->mpr_pr;
+}
+
+/*
+ * pr_free:
+ * Free the memory associated with a pixrect.
+ * Returns a pointer to no pixrect structure.
+ */
+
+struct pixrect *
+pr_free(mpr)
+struct mem_pixrect *mpr;
+{
+ short *image;
+
+ if((image = mpr->mpr_data.md_image))
+ {
+ if(mpr->mpr_data.md_primary)
+ free(image);
+ mpr->mpr_data.md_image = (short *)NULL;
+ }
+ mpr->mpr_pr.pr_width = 0;
+ mpr->mpr_pr.pr_height = 0;
+
+ return (struct pixrect *)NULL;
+}
+
+/*
+ * pr_check:
+ * Check that a designated pixrect has memory allocated for an image
+ * of size w, h, d. If not, free any existing memory and allocate
+ * more memory. This is equivalent to, but much faster than, a
+ * sequence of
+ * pr_destroy(mpr);
+ * mpr = mem_create(w, h, d);
+ */
+
+struct pixrect *
+pr_check(mpr, w, h, d)
+struct mem_pixrect *mpr;
+int w, h, d;
+{
+ /*
+ * If there is an image, check that it is the correct size.
+ */
+ if(mpr->mpr_data.md_image)
+ {
+ if(mpr->mpr_pr.pr_width == w &&
+ mpr->mpr_pr.pr_height == h &&
+ mpr->mpr_pr.pr_depth == d)
+ return &mpr->mpr_pr;
+
+ (void)pr_free(mpr);
+ }
+
+ return pr_alloc(mpr, w, h, d);
+}
+
+/*
+ * pr_link:
+ * Link the memory of mpr1 to mpr2, making mpr2 a secondary pixrect.
+ */
+
+struct pixrect *
+pr_link(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ /*
+ * Free the existing memory, if any.
+ */
+ (void)pr_free(mpr2);
+
+ /*
+ * Set up the pr.
+ */
+ mpr2->mpr_pr.pr_ops = &mem_ops;
+ mpr2->mpr_pr.pr_width = mpr1->mpr_pr.pr_width;
+ mpr2->mpr_pr.pr_height = mpr1->mpr_pr.pr_height;
+ mpr2->mpr_pr.pr_depth = mpr1->mpr_pr.pr_depth;
+ mpr2->mpr_pr.pr_data = (caddr_t)&mpr2->mpr_data;
+
+ /*
+ * Set up the mpr_data
+ */
+ mpr2->mpr_data.md_linebytes = mpr1->mpr_data.md_linebytes;
+ mpr2->mpr_data.md_image = mpr1->mpr_data.md_image;
+ mpr2->mpr_data.md_offset.x = mpr1->mpr_data.md_offset.x;
+ mpr2->mpr_data.md_offset.y = mpr1->mpr_data.md_offset.y;
+ mpr2->mpr_data.md_primary = FALSE;
+ mpr2->mpr_data.md_flags = 0;
+
+ /*
+ * Return the pr.
+ */
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * Colour Map Stuff
+ * ================
+ */
+
+#define M4F 0
+#define M4T (M4F+16)
+#define M3F (M4T+1)
+#define M3T (M3F+24)
+#define M2F (M3T+1)
+#define M2T (M2F+4)
+
+uchar cmap_red[64] =
+{
+#ifdef NEVER
+ /* Cmap with GAMMA=2,2,2,20,20,20 */
+ /* 4x4 from 0 to 16 */
+ 255, 247, 239, 231, 223, 214, 205, 196, 186,
+ 175, 163, 151, 137, 121, 103, 78, 20,
+
+ /* 3x3 from 17 to 41 */
+ 255, 250, 244, 239, 234, 229, 223, 217, 211,
+ 205, 199, 192, 186, 179, 171, 163, 155,
+ 146, 137, 127, 115, 103, 87, 67, 20,
+
+ /* 2x2 from 42 to 46 */
+ 255, 223, 186, 137, 20,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+#endif NEVER
+ /* Cmap with GAMMA=1.3,1.3,1.3,0,0,0 */
+ /* 4x4 from 0 to 16 */
+ 255, 242, 230, 217, 204, 191, 177, 163, 149,
+ 135, 119, 104, 87, 70, 51, 30, 0,
+
+ /* 3x3 from 17 to 41 */
+ 255, 246, 238, 230, 221, 213, 204, 195, 186,
+ 177, 168, 159, 149, 139, 130, 119, 109,
+ 98, 87, 76, 64, 51, 37, 22, 0,
+
+ /* 2x2 from 42 to 46 */
+ 255, 204, 149, 87, 0,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+uchar cmap_green[64] =
+{
+ /* 4x4 from 0 to 16 */
+ 255, 242, 230, 217, 204, 191, 177, 163, 149,
+ 135, 119, 104, 87, 70, 51, 30, 0,
+
+ /* 3x3 from 17 to 41 */
+ 255, 246, 238, 230, 221, 213, 204, 195, 186,
+ 177, 168, 159, 149, 139, 130, 119, 109,
+ 98, 87, 76, 64, 51, 37, 22, 0,
+
+ /* 2x2 from 42 to 46 */
+ 255, 204, 149, 87, 0,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+uchar cmap_blue[64] =
+{
+ /* 4x4 from 0 to 16 */
+ 255, 242, 230, 217, 204, 191, 177, 163, 149,
+ 135, 119, 104, 87, 70, 51, 30, 0,
+
+ /* 3x3 from 17 to 41 */
+ 255, 246, 238, 230, 221, 213, 204, 195, 186,
+ 177, 168, 159, 149, 139, 130, 119, 109,
+ 98, 87, 76, 64, 51, 37, 22, 0,
+
+ /* 2x2 from 42 to 46 */
+ 255, 204, 149, 87, 0,
+
+ /* spare */
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+};
+
+double gamma_red = 2.0;
+double gamma_green = 2.0;
+double gamma_blue = 2.0;
+int min_red = 20;
+int min_green = 20;
+int min_blue = 20;
+
+forward void make_one_cmap();
+
+void
+make_cmap()
+{
+ char *e;
+
+ if((e = getenv("DVIPAGE_GAMMA")) == NULL)
+ return;
+
+ min_red = 20;
+ min_green = 20;
+ min_blue = 20;
+ gamma_red = 0.0;
+ gamma_green = 0.0;
+ gamma_blue = 0.0;
+
+ (void)sscanf(e, " %lf,%lf,%lf,%d,%d,%d ",
+ &gamma_red, &gamma_green, &gamma_blue,
+ &min_red, &min_green, &min_blue);
+
+ if(gamma_red == 0.0)
+ gamma_red = 1.3;
+ if(gamma_green == 0.0)
+ gamma_green = gamma_red;
+ if(gamma_blue == 0.0)
+ gamma_blue = gamma_red;
+
+ make_one_cmap(cmap_red, 1.0/gamma_red, min_red);
+ make_one_cmap(cmap_green, 1.0/gamma_green, min_green);
+ make_one_cmap(cmap_blue, 1.0/gamma_blue, min_blue);
+}
+
+void
+make_one_cmap(cmap, power, mn)
+uchar cmap[];
+double power;
+int mn;
+{
+ int i;
+
+ /*
+ * 4x4 cmap.
+ */
+ for(i = M4F; i <= M4T; i++)
+ cmap[i] = (uchar)(pow((double)(M4T - i) / (M4T - M4F), power)
+ * (255 - mn) + mn);
+
+ /*
+ * 3x3 cmap.
+ */
+ for(i = M3F; i <= M3T; i++)
+ cmap[i] = (uchar)(pow((double)(M3T - i) / (M3T - M3F), power)
+ * (255 - mn) + mn);
+
+ /*
+ * 2x2 cmap.
+ */
+ for(i = M2F; i <= M2T; i++)
+ cmap[i] = (uchar)(pow((double)(M2T - i) / (M2T - M2F), power)
+ * (255 - mn) + mn);
+
+ cmap[63] = mn;
+}
+
+/*
+ * Tally table used to compute the number of bits in packed words.
+ * This is used in computing the number of bits in a 4x4 region of
+ * a packed image.
+ *
+ * The packed word is used as an index into this table;
+ * The most significant 16 bits of the value obtained represent the
+ * number of bits in the upper half of the index, with each bit counted
+ * with a weight of 15.
+ * The least significant 16 bits of the value obtained represent the
+ * number of bits in the l;ower hald of the index, with each bit counted
+ * with a weight of 15.
+ *
+ * By combining the upper and lower halves in a single word, the values
+ * for the four vertically adjacent words can be combined with each other
+ * in a single addition per word, adding simultaneously both the tallies
+ * for the left and the right halves of the word.
+ */
+
+static int tally4[] =
+{
+ 0x00000000, 0x00000001, 0x00000001, 0x00000002,
+ 0x00000001, 0x00000002, 0x00000002, 0x00000003,
+ 0x00000001, 0x00000002, 0x00000002, 0x00000003,
+ 0x00000002, 0x00000003, 0x00000003, 0x00000004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010001, 0x00010002, 0x00010002, 0x00010003,
+ 0x00010002, 0x00010003, 0x00010003, 0x00010004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020001, 0x00020002, 0x00020002, 0x00020003,
+ 0x00020002, 0x00020003, 0x00020003, 0x00020004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00030000, 0x00030001, 0x00030001, 0x00030002,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030001, 0x00030002, 0x00030002, 0x00030003,
+ 0x00030002, 0x00030003, 0x00030003, 0x00030004,
+ 0x00040000, 0x00040001, 0x00040001, 0x00040002,
+ 0x00040001, 0x00040002, 0x00040002, 0x00040003,
+ 0x00040001, 0x00040002, 0x00040002, 0x00040003,
+ 0x00040002, 0x00040003, 0x00040003, 0x00040004,
+};
+
+/*
+ * Tally table used to compute the number of bits in packed words.
+ * This is used in computing the number of bits in a 3x3 region of
+ * a packed image.
+ *
+ * The packed word is used as an index into this table;
+ * Bits 23..16 of the value obtained represent the number of bits in
+ * the upper 2.67 bits of the index, with each bit counted with a weight
+ * of 15. etc. etc.
+ *
+ * By combining the three parts in a single word, the values
+ * for the three vertically adjacent words can be combined with each other
+ * in a single addition per word, adding simultaneously both the tallies
+ * for the left and the right halves of the word.
+ */
+
+static int tally3[] =
+{
+ 0x00000000, 0x00000003, 0x00000003, 0x00000006,
+ 0x00000102, 0x00000105, 0x00000105, 0x00000108,
+ 0x00000300, 0x00000303, 0x00000303, 0x00000306,
+ 0x00000402, 0x00000405, 0x00000405, 0x00000408,
+ 0x00000300, 0x00000303, 0x00000303, 0x00000306,
+ 0x00000402, 0x00000405, 0x00000405, 0x00000408,
+ 0x00000600, 0x00000603, 0x00000603, 0x00000606,
+ 0x00000702, 0x00000705, 0x00000705, 0x00000708,
+ 0x00020100, 0x00020103, 0x00020103, 0x00020106,
+ 0x00020202, 0x00020205, 0x00020205, 0x00020208,
+ 0x00020400, 0x00020403, 0x00020403, 0x00020406,
+ 0x00020502, 0x00020505, 0x00020505, 0x00020508,
+ 0x00020400, 0x00020403, 0x00020403, 0x00020406,
+ 0x00020502, 0x00020505, 0x00020505, 0x00020508,
+ 0x00020700, 0x00020703, 0x00020703, 0x00020706,
+ 0x00020802, 0x00020805, 0x00020805, 0x00020808,
+ 0x00030000, 0x00030003, 0x00030003, 0x00030006,
+ 0x00030102, 0x00030105, 0x00030105, 0x00030108,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030600, 0x00030603, 0x00030603, 0x00030606,
+ 0x00030702, 0x00030705, 0x00030705, 0x00030708,
+ 0x00050100, 0x00050103, 0x00050103, 0x00050106,
+ 0x00050202, 0x00050205, 0x00050205, 0x00050208,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050700, 0x00050703, 0x00050703, 0x00050706,
+ 0x00050802, 0x00050805, 0x00050805, 0x00050808,
+ 0x00030000, 0x00030003, 0x00030003, 0x00030006,
+ 0x00030102, 0x00030105, 0x00030105, 0x00030108,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030300, 0x00030303, 0x00030303, 0x00030306,
+ 0x00030402, 0x00030405, 0x00030405, 0x00030408,
+ 0x00030600, 0x00030603, 0x00030603, 0x00030606,
+ 0x00030702, 0x00030705, 0x00030705, 0x00030708,
+ 0x00050100, 0x00050103, 0x00050103, 0x00050106,
+ 0x00050202, 0x00050205, 0x00050205, 0x00050208,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050400, 0x00050403, 0x00050403, 0x00050406,
+ 0x00050502, 0x00050505, 0x00050505, 0x00050508,
+ 0x00050700, 0x00050703, 0x00050703, 0x00050706,
+ 0x00050802, 0x00050805, 0x00050805, 0x00050808,
+ 0x00060000, 0x00060003, 0x00060003, 0x00060006,
+ 0x00060102, 0x00060105, 0x00060105, 0x00060108,
+ 0x00060300, 0x00060303, 0x00060303, 0x00060306,
+ 0x00060402, 0x00060405, 0x00060405, 0x00060408,
+ 0x00060300, 0x00060303, 0x00060303, 0x00060306,
+ 0x00060402, 0x00060405, 0x00060405, 0x00060408,
+ 0x00060600, 0x00060603, 0x00060603, 0x00060606,
+ 0x00060702, 0x00060705, 0x00060705, 0x00060708,
+ 0x00080100, 0x00080103, 0x00080103, 0x00080106,
+ 0x00080202, 0x00080205, 0x00080205, 0x00080208,
+ 0x00080400, 0x00080403, 0x00080403, 0x00080406,
+ 0x00080502, 0x00080505, 0x00080505, 0x00080508,
+ 0x00080400, 0x00080403, 0x00080403, 0x00080406,
+ 0x00080502, 0x00080505, 0x00080505, 0x00080508,
+ 0x00080700, 0x00080703, 0x00080703, 0x00080706,
+ 0x00080802, 0x00080805, 0x00080805, 0x00080808,
+};
+
+/*
+ * Tally table used to compute the number of bits in packed words.
+ * This is used in computing the number of bits in a 2x2 region of
+ * a packed image.
+ *
+ * The packed word is used as an index into this table;
+ * The most significant 8 bits of the value obtained represent the
+ * number of bits in the upper half of the index, with each bit counted
+ * with a weight of 15.
+ * ...
+ * The least significant 8 bits of the value obtained represent the
+ * number of bits in the l;ower hald of the index, with each bit counted
+ * with a weight of 15.
+ *
+ * By combining the four pairs of tallies in a single word, the values
+ * for the two vertically adjacent words can be combined with each other
+ * in a single addition per word, adding simultaneously all four tallies
+ * for the four pairs of the word.
+ */
+
+static int tally2[] =
+{
+ 0x00000000, 0x00000001, 0x00000001, 0x00000002,
+ 0x00000100, 0x00000101, 0x00000101, 0x00000102,
+ 0x00000100, 0x00000101, 0x00000101, 0x00000102,
+ 0x00000200, 0x00000201, 0x00000201, 0x00000202,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010200, 0x00010201, 0x00010201, 0x00010202,
+ 0x00010000, 0x00010001, 0x00010001, 0x00010002,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010100, 0x00010101, 0x00010101, 0x00010102,
+ 0x00010200, 0x00010201, 0x00010201, 0x00010202,
+ 0x00020000, 0x00020001, 0x00020001, 0x00020002,
+ 0x00020100, 0x00020101, 0x00020101, 0x00020102,
+ 0x00020100, 0x00020101, 0x00020101, 0x00020102,
+ 0x00020200, 0x00020201, 0x00020201, 0x00020202,
+ 0x01000000, 0x01000001, 0x01000001, 0x01000002,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000200, 0x01000201, 0x01000201, 0x01000202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01020000, 0x01020001, 0x01020001, 0x01020002,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020200, 0x01020201, 0x01020201, 0x01020202,
+ 0x01000000, 0x01000001, 0x01000001, 0x01000002,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000100, 0x01000101, 0x01000101, 0x01000102,
+ 0x01000200, 0x01000201, 0x01000201, 0x01000202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01010000, 0x01010001, 0x01010001, 0x01010002,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010100, 0x01010101, 0x01010101, 0x01010102,
+ 0x01010200, 0x01010201, 0x01010201, 0x01010202,
+ 0x01020000, 0x01020001, 0x01020001, 0x01020002,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020100, 0x01020101, 0x01020101, 0x01020102,
+ 0x01020200, 0x01020201, 0x01020201, 0x01020202,
+ 0x02000000, 0x02000001, 0x02000001, 0x02000002,
+ 0x02000100, 0x02000101, 0x02000101, 0x02000102,
+ 0x02000100, 0x02000101, 0x02000101, 0x02000102,
+ 0x02000200, 0x02000201, 0x02000201, 0x02000202,
+ 0x02010000, 0x02010001, 0x02010001, 0x02010002,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010200, 0x02010201, 0x02010201, 0x02010202,
+ 0x02010000, 0x02010001, 0x02010001, 0x02010002,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010100, 0x02010101, 0x02010101, 0x02010102,
+ 0x02010200, 0x02010201, 0x02010201, 0x02010202,
+ 0x02020000, 0x02020001, 0x02020001, 0x02020002,
+ 0x02020100, 0x02020101, 0x02020101, 0x02020102,
+ 0x02020100, 0x02020101, 0x02020101, 0x02020102,
+ 0x02020200, 0x02020201, 0x02020201, 0x02020202,
+};
+
+/*
+ * P_row:
+ * Access macro for obtaining a pointer to the bytes of a pixrect
+ * starting at row `row'.
+ */
+
+#define P_row(mpr, row) \
+ (uchar *)((int)((mpr)->mpr_data.md_image) + \
+ (int)((short)(row) * (short)((mpr)->mpr_data.md_linebytes)));
+
+/*
+ * pr_sample_4:
+ * Filter and sample mpr1 on a 4x4 basis into mpr2.
+ */
+
+struct pixrect *
+pr_sample_4(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *p2; /* a3 */
+ register uchar *p3; /* a2 */
+ register uchar *pr;
+ register uchar *er;
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width / 4;
+ rows = mpr1->mpr_pr.pr_height / 4;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_4: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*4);
+ p1 = p0 + line_offset;
+ p2 = p1 + line_offset;
+ p3 = p2 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0 && *p2 == 0 && *p3 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally4[*p0] +
+ tally4[*p1] +
+ tally4[*p2] +
+ tally4[*p3];
+
+ /*
+ * High order 4 bits
+ */
+ *pr++ = (tallies >> 16) + M4F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Low order 4 bits
+ */
+ *pr++ = tallies + M4F;
+ }
+ p0++;
+ p1++;
+ p2++;
+ p3++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pr_sample_34:
+ * Filter and sample mpr1 on a 2.67x4 basis into mpr2.
+ * Tally count uses M3 table, and gets up to 32 pixels (weighted at 1/3)
+ * divides by two to index into the 0..16 M4 table.
+ */
+
+struct pixrect *
+pr_sample_34(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *p2; /* a3 */
+ register uchar *p3; /* a2 */
+ register uchar *pr;
+ register uchar *er;
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width * 3 / 8;
+ rows = mpr1->mpr_pr.pr_height / 4;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_34: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*4);
+ p1 = p0 + line_offset;
+ p2 = p1 + line_offset;
+ p3 = p2 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0 && *p2 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally3[*p0] +
+ tally3[*p1] +
+ tally3[*p2] +
+ tally3[*p3];
+
+ /*
+ * High order 3 bits
+ */
+ *pr++ = (tallies >> (16+1)) + M4F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> (8+1)) + M4F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Low order 3 bits
+ */
+ *pr++ = (tallies >> 1) + M4F;
+ }
+ p0++;
+ p1++;
+ p2++;
+ p3++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pr_sample_3:
+ * Filter and sample mpr1 on a 3x3 basis into mpr2.
+ * Note that the horizontal sampling is actually 3/8 rather than 1/3.
+ */
+
+struct pixrect *
+pr_sample_3(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *p2; /* a3 */
+ register uchar *pr; /* a2 */
+ register uchar *er;
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width * 3 / 8;
+ rows = mpr1->mpr_pr.pr_height / 3;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_3: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*3);
+ p1 = p0 + line_offset;
+ p2 = p1 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0 && *p2 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally3[*p0] +
+ tally3[*p1] +
+ tally3[*p2];
+
+ /*
+ * High order 3 bits
+ */
+ *pr++ = (tallies >> 16) + M3F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> 8) + M3F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Low order 3 bits
+ */
+ *pr++ = tallies + M3F;
+ }
+ p0++;
+ p1++;
+ p2++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pr_sample_2:
+ * Filter and sample mpr1 on a 2x2 basis into mpr2.
+ */
+
+struct pixrect *
+pr_sample_2(mpr1, mpr2)
+struct mem_pixrect *mpr1;
+struct mem_pixrect *mpr2;
+{
+ int cols, rows;
+ int j;
+ register uchar *p0; /* a5 */
+ register uchar *p1; /* a4 */
+ register uchar *pr; /* a3 */
+ register uchar *er; /* a2 */
+ register int tallies; /* d7 */
+ int line_offset;
+
+ cols = mpr1->mpr_pr.pr_width / 2;
+ rows = mpr1->mpr_pr.pr_height / 2;
+
+ if(verbose & DEBUG_IMSIZE)
+ fprintf(stderr, "pr_sample_2: (%d x %d) -> (%d x %d)\n",
+ mpr1->mpr_pr.pr_width, mpr1->mpr_pr.pr_height, cols, rows);
+
+ /*
+ * Allocate output image.
+ */
+ if(! pr_check(mpr2, cols, rows, 8))
+ return (struct pixrect *)NULL;
+
+ /*
+ * Do the sampling.
+ */
+ line_offset = mpr1->mpr_data.md_linebytes;
+ for(j = 0; j < rows; j++)
+ {
+ p0 = P_row(mpr1, j*2);
+ p1 = p0 + line_offset;
+
+ pr = P_row(mpr2, j);
+
+ for(er = pr + cols; pr < er; )
+ {
+ /*
+ * Test for all zero.
+ if(*p0 == 0 && *p1 == 0)
+ {
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = 0;
+ }
+ else
+ */
+ {
+ tallies =
+ tally2[*p0] +
+ tally2[*p1];
+
+ /*
+ * Highest two bits
+ */
+ *pr++ = (tallies >> 24) + M2F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> 16) + M2F;
+
+ if(pr >= er)
+ break;
+
+ *pr++ = (tallies >> 8) + M2F;
+
+ if(pr >= er)
+ break;
+
+ /*
+ * Lowest two bits
+ */
+ *pr++ = tallies + M2F;
+ }
+ p0++;
+ p1++;
+ }
+ }
+
+ return &mpr2->mpr_pr;
+}
+
+/*
+ * pw_cover:
+ * Function which writes a pixrect onto a pixwin;
+ * where there are no src pixels, it writes background colour.
+ */
+
+void
+pw_cover(dpw, dx, dy, dw, dh, op, spr, sx, sy)
+Pixwin *dpw;
+int dx, dy, dw, dh;
+int op;
+Pixrect *spr;
+int sx, sy;
+{
+ int aw, ah;
+
+ /*
+ * Handle the left margin.
+ * If the left margin is less than the width to be painted,
+ * paint a margin, else paint the whole region and return.
+ */
+ if(sx < 0)
+ {
+ if(-sx < dw)
+ {
+ pw_writebackground(dpw, dx, dy, -sx, dh, op);
+ dx -= sx;
+ sx = 0;
+ dw += sx;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Handle the top margin.
+ * If the top margin is less thatn the width to be painted,
+ * paint a margin, else paint the whole region and return.
+ */
+ if(sy < 0)
+ {
+ if(-sy < dh)
+ {
+ pw_writebackground(dpw, dx, dy, dw, -sy, op);
+ dy -= sy;
+ sy = 0;
+ dh += sy;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Handle the right margin.
+ * aw = available width of source image.
+ * If available width > 0 paint a margin of dw-aw width,
+ * otherwise paint the whole region.
+ */
+ aw = spr->pr_width-sx;
+ if(dw > aw)
+ {
+ if(aw > 0)
+ {
+ pw_writebackground(dpw, dx+aw, dy, dw-aw, dh, op);
+ dw = aw;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Handle the bottom margin.
+ * ah = available height of source image.
+ * If available height > 0 paint a margin of dh-ah height,
+ * otherwise paint the whole region.
+ */
+ ah = spr->pr_height-sy;
+ if(dh > ah)
+ {
+ if(ah > 0)
+ {
+ pw_writebackground(dpw, dx, dy+ah, dw, dh-ah, op);
+ dh = ah;
+ }
+ else
+ {
+ pw_writebackground(dpw, dx, dy, dw, dh, op);
+ return;
+ }
+ }
+
+ /*
+ * Paint the image.
+ */
+ pw_write(dpw, dx, dy, dw, dh, op, spr, sx, sy);
+}
+
+/*
+ * pr_rect:
+ * Draws a box with op and colour as specified.
+ */
+
+void
+pr_rect(pr, x, y, w, h, t, op, value)
+struct pixrect *pr;
+int x, y, w, h;
+int t;
+int op, value;
+{
+ int i;
+
+ for(i = 0; i < t; i++)
+ {
+ pr_vector(pr, x, y, x+w-1, y, op, value);
+ pr_vector(pr, x+w-1, y+1, x+w-1, y+h-2, op, value);
+ pr_vector(pr, x, y+h-1, x+w-1, y+h-1, op, value);
+ pr_vector(pr, x, y+1, x, y+h-2, op, value);
+
+ x += 1;
+ y += 1;
+ w -= 2;
+ h -= 2;
+
+ if(w <= 0 || h <= 0)
+ break;
+ }
+}
+
+/*
+ * pw_rect:
+ * Draws a box with op and colour as specified.
+ */
+
+void
+pw_rect(pw, x, y, w, h, t, op, value)
+Pixwin *pw;
+int x, y, w, h;
+int t;
+int op, value;
+{
+ int i;
+ Rect r;
+
+ r.r_left = x;
+ r.r_top = y;
+ r.r_width = w;
+ r.r_height = h;
+ pw_lock(pw, &r);
+
+ for(i = 0; i < t; i++)
+ {
+ pw_vector(pw, x, y, x+w-1, y, op, value);
+ pw_vector(pw, x+w-1, y+1, x+w-1, y+h-2, op, value);
+ pw_vector(pw, x, y+h-1, x+w-1, y+h-1, op, value);
+ pw_vector(pw, x, y+1, x, y+h-2, op, value);
+
+ x += 1;
+ y += 1;
+ w -= 2;
+ h -= 2;
+
+ if(w <= 0 || h <= 0)
+ break;
+ }
+
+ pw_unlock(pw);
+}