summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'base/gxhtbit.c')
-rw-r--r--base/gxhtbit.c173
1 files changed, 169 insertions, 4 deletions
diff --git a/base/gxhtbit.c b/base/gxhtbit.c
index 6cb6fdcb..243583e7 100644
--- a/base/gxhtbit.c
+++ b/base/gxhtbit.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2020 Artifex Software, Inc.
+/* Copyright (C) 2001-2021 Artifex Software, Inc.
All Rights Reserved.
This software is provided AS-IS with no warranty, either express or
@@ -25,6 +25,9 @@
#include "gxtmap.h"
#include "gxdht.h"
#include "gxdhtres.h"
+#include "gp.h"
+
+#define DUMP_TOS 0
extern_gx_device_halftone_list();
@@ -75,7 +78,6 @@ construct_ht_order_short(gx_ht_order *porder, const byte *thresholds)
for (i = 0; i < size; i++) {
uint value = max(1, thresholds[i]);
- /* Adjust the bit index to account for padding. */
bits[levels[value]++] = i + (i / width * padding);
}
}
@@ -114,10 +116,101 @@ construct_ht_order_short(gx_ht_order *porder, const byte *thresholds)
}
}
}
+#if DUMP_TOS
+/* Lets look at the bit data which is the TOS level by level if I understand what the above
+ code is supposed to be doing */
+ {
+ char file_name[50];
+ gp_file *fid;
+
+ snprintf(file_name, 50, "TOS_porder_%dx%d.raw", porder->width, porder->height);
+ fid = gp_fopen(porder->data_memory, file_name, "wb");
+ if (fid) {
+ gp_fwrite(porder->bit_data, sizeof(unsigned short), size, fid);
+ gp_fclose(fid);
+ }
+ }
+#endif
+
out:
return 0;
}
+/*
+ * Construct a uint-representation order from a threshold array.
+ * Uses porder->width, num_levels, num_bits, levels, bit_data;
+ * sets porder->levels[], bit_data[].
+ */
+static int
+construct_ht_order_uint(gx_ht_order *porder, const byte *thresholds)
+{
+ uint size = porder->num_bits;
+ uint i;
+ uint *bits = (uint *)porder->bit_data;
+ uint *levels = porder->levels;
+ uint num_levels = porder->num_levels;
+
+ memset(levels, 0, num_levels * sizeof(*levels));
+
+ /* Count the number of threshold elements with each value. */
+ for (i = 0; i < size; i++) {
+ uint value = max(1, thresholds[i]);
+
+ if (value + 1 < num_levels)
+ levels[value + 1]++;
+ }
+ for (i = 2; i < num_levels; ++i)
+ levels[i] += levels[i - 1];
+ /* Now construct the actual order. */
+ {
+ uint width = porder->width;
+ uint padding = bitmap_raster(width) * 8 - width;
+
+ for (i = 0; i < size; i++) {
+ uint value = max(1, thresholds[i]);
+
+ bits[levels[value]++] = i + (i / width * padding);
+ }
+ }
+
+ /* Check whether this is a predefined halftone. */
+ {
+ const gx_dht_proc *phtrp = gx_device_halftone_list;
+
+ for (; *phtrp; ++phtrp) {
+ const gx_device_halftone_resource_t *const *pphtr = (*phtrp)();
+ const gx_device_halftone_resource_t *phtr;
+
+ while ((phtr = *pphtr++) != 0) {
+ if (phtr->Width == porder->width &&
+ phtr->Height == porder->height &&
+ phtr->elt_size == sizeof(uint) &&
+ !memcmp(phtr->levels, levels, num_levels * sizeof(*levels)) &&
+ !memcmp(phtr->bit_data, porder->bit_data,
+ (size_t)size * phtr->elt_size)
+ ) {
+ /*
+ * This is a predefined halftone. Free the levels and
+ * bit_data arrays, replacing them with the built-in ones.
+ */
+ if (porder->data_memory) {
+ gs_free_object(porder->data_memory, porder->bit_data,
+ "construct_ht_order_uint(bit_data)");
+ gs_free_object(porder->data_memory, porder->levels,
+ "construct_ht_order_uint(levels)");
+ }
+ porder->data_memory = 0;
+ porder->levels = (uint *)phtr->levels; /* actually const */
+ porder->bit_data = (void *)phtr->bit_data; /* actually const */
+ goto out;
+ }
+ }
+ }
+ }
+out:
+ return 0;
+}
+
/* Return the bit coordinate using the standard representation. */
static int
ht_bit_index_default(const gx_ht_order *porder, uint index, gs_int_point *ppt)
@@ -145,6 +238,18 @@ ht_bit_index_short(const gx_ht_order *porder, uint index, gs_int_point *ppt)
return 0;
}
+/* Return the bit coordinate using the uint representation. */
+static int
+ht_bit_index_uint(const gx_ht_order *porder, uint index, gs_int_point *ppt)
+{
+ uint bit_index = ((const uint *)porder->bit_data)[index];
+ uint bit_raster = porder->raster * 8;
+
+ ppt->x = bit_index % bit_raster;
+ ppt->y = bit_index / bit_raster;
+ return 0;
+}
+
/* Update a halftone tile using the default order representation. */
static int
render_ht_default(gx_ht_tile *pbt, int level, const gx_ht_order *porder)
@@ -264,10 +369,70 @@ render_ht_short(gx_ht_tile *pbt, int level, const gx_ht_order *porder)
return 0;
}
+/* Update a halftone tile using the uint representation. */
+static int
+render_ht_uint(gx_ht_tile *pbt, int level, const gx_ht_order *porder)
+{
+ int old_level = pbt->level;
+ register const uint *p = (const uint *)porder->bit_data + old_level;
+ register byte *data = pbt->tiles.data;
+
+ /* Invert bits between the two levels. */
+#define INVERT_DATA(i)\
+ BEGIN\
+ uint bit_index = p[i];\
+ byte *dp = &data[bit_index >> 3];\
+ *dp ^= 0x80 >> (bit_index & 7);\
+ END
+#ifdef DEBUG
+# define INVERT(i)\
+ BEGIN\
+ if_debug3('H', "[H]invert level=%d offset=%u mask=0x%x\n",\
+ (int)(p + i - (const uint *)porder->bit_data),\
+ p[i] >> 3, 0x80 >> (p[i] & 7));\
+ INVERT_DATA(i);\
+ END
+#else
+# define INVERT(i) INVERT_DATA(i)
+#endif
+sw:switch (level - old_level) {
+default:
+ if (level > old_level) {
+ INVERT(0); INVERT(1); INVERT(2); INVERT(3);
+ p += 4; old_level += 4;
+ }
+ else {
+ INVERT(-1); INVERT(-2); INVERT(-3); INVERT(-4);
+ p -= 4; old_level -= 4;
+ }
+ goto sw;
+case 7: INVERT(6);
+case 6: INVERT(5);
+case 5: INVERT(4);
+case 4: INVERT(3);
+case 3: INVERT(2);
+case 2: INVERT(1);
+case 1: INVERT(0);
+case 0: break; /* Shouldn't happen! */
+case -7: INVERT(-7);
+case -6: INVERT(-6);
+case -5: INVERT(-5);
+case -4: INVERT(-4);
+case -3: INVERT(-3);
+case -2: INVERT(-2);
+case -1: INVERT(-1);
+}
+#undef INVERT_DATA
+#undef INVERT
+return 0;
+}
+
/* Define the procedure vectors for the order data implementations. */
-const gx_ht_order_procs_t ht_order_procs_table[2] = {
+const gx_ht_order_procs_t ht_order_procs_table[3] = {
{ sizeof(gx_ht_bit), construct_ht_order_default, ht_bit_index_default,
render_ht_default },
{ sizeof(ushort), construct_ht_order_short, ht_bit_index_short,
- render_ht_short }
+ render_ht_short },
+ { sizeof(uint), construct_ht_order_uint, ht_bit_index_uint,
+ render_ht_uint }
};