summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Vrhel <michael.vrhel@artifex.com>2011-06-22 09:05:28 -0700
committerMichael Vrhel <michael.vrhel@artifex.com>2011-06-22 09:08:12 -0700
commite3def0b758231cd1c5c0510945cef0dd3d938393 (patch)
treee17ba49cfbad48241b238f294fa11a02a7233bd8
parentfef629cab877b0bbf4f86777f37038d1f37de838 (diff)
downloadghostpdl-e3def0b758231cd1c5c0510945cef0dd3d938393.tar.gz
Support for fast thresholding to CMYK planar devices
Code works for various orientations for color as well as indexed (mono) images. There is an inversion (polarity) issue remaining to track down as well as one potential rendering issue during the buffer clean up with landscape images. These will be resolved shortly. For now, code is sufficiently complete to begin timing testing and optimizations. To use specify -dCOLORSCREEN -sDEVICE=plank and enable processing of color images by setting use_fast_thresh = true on line 67 in gxicolor.c
-rw-r--r--gs/base/gxht_thresh.c89
-rw-r--r--gs/base/gxht_thresh.h2
-rw-r--r--gs/base/gxicolor.c111
-rw-r--r--gs/base/gxidata.c6
-rw-r--r--gs/base/gximono.c117
-rw-r--r--gs/base/lib.mak2
6 files changed, 219 insertions, 108 deletions
diff --git a/gs/base/gxht_thresh.c b/gs/base/gxht_thresh.c
index a783407a8..279fbef4b 100644
--- a/gs/base/gxht_thresh.c
+++ b/gs/base/gxht_thresh.c
@@ -413,7 +413,7 @@ gxht_thresh_image_init(gx_image_enum *penum)
data. */
if (penum->posture == image_landscape) {
int col_length =
- fixed2int_var_rounded(any_abs(penum->x_extent.y)) * spp_out;
+ fixed2int_var_rounded(any_abs(penum->x_extent.y));
ox = dda_current(penum->dda.pixel0.x);
oy = dda_current(penum->dda.pixel0.y);
/* Line_size is col_length rounded up - why? */
@@ -423,9 +423,9 @@ gxht_thresh_image_init(gx_image_enum *penum)
penum->line_size = temp * LAND_BITS; /* The stride */
/* Now we need at most LAND_BITS of these */
penum->line = gs_alloc_bytes(penum->memory,
- LAND_BITS * penum->line_size + 16,
+ LAND_BITS * penum->line_size * spp_out + 16,
"gxht_thresh");
- /* Same with this */
+ /* Same with this. However, we only need one plane here */
penum->thresh_buffer = gs_alloc_bytes(penum->memory,
penum->line_size * LAND_BITS + 16,
"gxht_thresh");
@@ -462,7 +462,7 @@ gxht_thresh_image_init(gx_image_enum *penum)
penum->ht_offset_bits = 0; /* Will get set in call to render */
if (code >= 0) {
#if defined(DEBUG) || defined(PACIFY_VALGRIND)
- memset(penum->line, 0, LAND_BITS * penum->line_size + 16);
+ memset(penum->line, 0, LAND_BITS * penum->line_size * spp_out + 16);
memset(penum->ht_buffer, 0, penum->line_size * (LAND_BITS>>3));
memset(penum->thresh_buffer, 0, LAND_BITS * penum->line_size + 16);
#endif
@@ -502,7 +502,7 @@ gxht_thresh_image_init(gx_image_enum *penum)
max_height = (int) ceil(fixed2float(any_abs(penum->dst_height)) /
(float) penum->Height);
penum->ht_buffer = gs_alloc_bytes(penum->memory,
- penum->ht_stride * max_height * spp_out,
+ penum->ht_stride * max_height,
"gxht_thresh");
/* We want to have 128 bit alignement for our contone and
threshold strips so that we can use SSE operations
@@ -522,7 +522,7 @@ gxht_thresh_image_init(gx_image_enum *penum)
penum->line = gs_alloc_bytes(penum->memory, penum->line_size * spp_out,
"gxht_thresh");
penum->thresh_buffer = gs_alloc_bytes(penum->memory,
- penum->line_size * max_height * spp_out,
+ penum->line_size * max_height,
"gxht_thresh");
if (penum->line == NULL || penum->thresh_buffer == NULL ||
penum->ht_buffer == NULL) {
@@ -530,10 +530,8 @@ gxht_thresh_image_init(gx_image_enum *penum)
} else {
#if defined(DEBUG) || defined(PACIFY_VALGRIND)
memset(penum->line, 0, penum->line_size * spp_out);
- memset(penum->ht_buffer, 0,
- penum->ht_stride * max_height * spp_out);
- memset(penum->thresh_buffer, 0,
- penum->line_size * max_height * spp_out);
+ memset(penum->ht_buffer, 0, penum->ht_stride * max_height);
+ memset(penum->thresh_buffer, 0, penum->line_size * max_height);
#endif
}
}
@@ -567,6 +565,31 @@ fill_threshhold_buffer(byte *dest_strip, byte *src_strip, int src_width,
memset(ptr_out_temp, 0, ii);
#endif
}
+/* This only moves the data but does not do a reset of the variables. Used
+ for case where we have multiple bands of data (e.g. CMYK output) */
+static void
+move_landscape_buffer(ht_landscape_info_t *ht_landscape, byte *contone_align,
+ int data_length)
+{
+ int k;
+ int position_curr, position_new;
+
+ if (ht_landscape->index < 0) {
+ /* Moving right to left, move column to far right */
+ position_curr = ht_landscape->curr_pos + 1;
+ position_new = LAND_BITS-1;
+ } else {
+ /* Moving left to right, move column to far left */
+ position_curr = ht_landscape->curr_pos - 1;
+ position_new = 0;
+ }
+ for (k = 0; k < data_length; k++) {
+ contone_align[position_new] = contone_align[position_curr];
+ position_curr += LAND_BITS;
+ position_new += LAND_BITS;
+ }
+}
+
/* If we are in here, we had data left over. Move it to the proper position
and get ht_landscape_info_t set properly */
@@ -612,7 +635,7 @@ int
gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order,
fixed xrun, int dest_width, int dest_height,
byte *thresh_align, byte *contone_align, int contone_stride,
- gx_device * dev, int plane_number)
+ gx_device * dev, int plane_number, bool allow_reset)
{
int thresh_width, thresh_height, dx;
int left_rem_end, left_width, vdi;
@@ -632,6 +655,7 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order,
int dithered_stride = penum->ht_stride;
bool is_planar_dev = dev_proc(dev, dev_spec_op)(dev,
gxdso_is_native_planar, NULL, 0);
+ bool done = false;
/* Go ahead and fill the threshold line buffer with tiled threshold values.
First just grab the row or column that we are going to tile with and
@@ -736,9 +760,9 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order,
* partial to get us in sync with the 1 bit devices 16 bit
* positions. */
vdi = penum->wci;
- while (penum->ht_landscape.count >= LAND_BITS ||
+ while ( (penum->ht_landscape.count >= LAND_BITS ||
((penum->ht_landscape.count >= offset_bits) &&
- penum->ht_landscape.offset_set)) {
+ penum->ht_landscape.offset_set)) && !done ) {
/* Go ahead and 2D tile in the threshold buffer at this time */
/* Always work the tiling from the upper left corner of our
LAND_BITS columns */
@@ -808,7 +832,6 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order,
gx_ht_threshold_landscape(contone_align, thresh_align,
penum->ht_landscape, halftone, dest_height);
/* Perform the copy mono */
- penum->ht_landscape.offset_set = false;
if (penum->ht_landscape.index < 0) {
if (!is_planar_dev) {
(*dev_proc(dev, copy_mono)) (dev, halftone, 0, LAND_BITS>>3,
@@ -846,22 +869,34 @@ gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order,
}
/* Clean up and reset our buffer. We may have a line left
over that has to be maintained due to line replication in the
- resolution conversion */
- if (width != penum->ht_landscape.count) {
- reset_landscape_buffer(&(penum->ht_landscape), contone_align,
- dest_height, width);
+ resolution conversion. However, pay attention to the reset
+ flag which indicates we are done with our last plane */
+ if (!allow_reset) {
+ if (width != penum->ht_landscape.count) {
+ /* move the line do not reset the stuff */
+ move_landscape_buffer(&(penum->ht_landscape),
+ contone_align, dest_height);
+ }
+ done = true;
} else {
- /* Reset the whole buffer */
- penum->ht_landscape.count = 0;
- if (penum->ht_landscape.index < 0) {
- /* Going right to left */
- penum->ht_landscape.curr_pos = LAND_BITS-1;
+ penum->ht_landscape.offset_set = false;
+ if (width != penum->ht_landscape.count) {
+ reset_landscape_buffer(&(penum->ht_landscape),
+ contone_align, dest_height,
+ width);
} else {
- /* Going left to right */
- penum->ht_landscape.curr_pos = 0;
+ /* Reset the whole buffer */
+ penum->ht_landscape.count = 0;
+ if (penum->ht_landscape.index < 0) {
+ /* Going right to left */
+ penum->ht_landscape.curr_pos = LAND_BITS-1;
+ } else {
+ /* Going left to right */
+ penum->ht_landscape.curr_pos = 0;
+ }
+ penum->ht_landscape.num_contones = 0;
+ memset(&(penum->ht_landscape.widths[0]), 0, sizeof(int)*LAND_BITS);
}
- penum->ht_landscape.num_contones = 0;
- memset(&(penum->ht_landscape.widths[0]), 0, sizeof(int)*LAND_BITS);
}
}
break;
diff --git a/gs/base/gxht_thresh.h b/gs/base/gxht_thresh.h
index 88d0e1bf5..7f0f63153 100644
--- a/gs/base/gxht_thresh.h
+++ b/gs/base/gxht_thresh.h
@@ -36,5 +36,5 @@ int gxht_thresh_image_init(gx_image_enum *penum);
int gxht_thresh_plane(gx_image_enum *penum, gx_ht_order *d_order,
fixed xrun, int dest_width, int dest_height,
byte *thresh_align, byte *contone_align, int contone_stride,
- gx_device * dev, int plane_number);
+ gx_device * dev, int plane_number, bool allow_reset);
#endif /* gshtx_INCLUDED */
diff --git a/gs/base/gxicolor.c b/gs/base/gxicolor.c
index 90c5822f2..8e9f5d12b 100644
--- a/gs/base/gxicolor.c
+++ b/gs/base/gxicolor.c
@@ -405,7 +405,7 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
bool flush_buff = false;
byte *psrc_temp;
int offset_contone[GX_DEVICE_COLOR_MAX_COMPONENTS]; /* to ensure 128 bit boundary */
- int offset_threshold[GX_DEVICE_COLOR_MAX_COMPONENTS]; /* to ensure 128 bit boundary */
+ int offset_threshold; /* to ensure 128 bit boundary */
gx_dda_int_t dda_ht;
int code = 0;
int spp_cm = 0;
@@ -414,6 +414,7 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
int psrc_planestride = w/penum->spp;
gx_color_value conc;
int num_des_comp = penum->dev->color_info.num_components;
+ bool allow_reset;
if (h != 0) {
/* Get the buffer into the device color space */
@@ -455,13 +456,12 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
/* Can't do this earlier, as GC might move the buffers. */
vdi = penum->hci;
contone_stride = penum->line_size;
+ offset_threshold = (- (((long)(penum->thresh_buffer)) +
+ penum->ht_offset_bits)) & 15;
for (k = 0; k < spp_out; k ++) {
offset_contone[k] = (- (((long)(penum->line)) +
contone_stride * k +
penum->ht_offset_bits)) & 15;
- offset_threshold[k] = (- (((long)(penum->thresh_buffer)) +
- contone_stride * vdi * k +
- penum->ht_offset_bits)) & 15;
}
xrun = dda_current(penum->dda.pixel0.x);
xrun = xrun - penum->adjust + (fixed_half - fixed_epsilon);
@@ -473,7 +473,7 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
scale_factor = float2fixed_rounded((float) src_size / (float) (dest_width - 1));
#ifdef DEBUG
/* Help in spotting problems */
- memset(penum->ht_buffer,0x00, penum->ht_stride * vdi * spp_out);
+ memset(penum->ht_buffer, 0x00, penum->ht_stride * vdi);
#endif
break;
case image_landscape:
@@ -483,12 +483,11 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
Can't do this earlier as GC may move the buffers.
*/
vdi = penum->wci;
- contone_stride = penum->line_size;
+ contone_stride = penum->line_size;
+ offset_threshold = (-(long)(penum->thresh_buffer)) & 15;
for (k = 0; k < spp_out; k ++) {
offset_contone[k] = (- ((long)(penum->line) +
contone_stride * k)) & 15;
- offset_threshold[k] = (-((long)(penum->thresh_buffer) +
- contone_stride * vdi * k)) & 15;
}
dest_width = fixed2int_var_rounded(any_abs(penum->y_extent.x));
dest_height = fixed2int_var_rounded(any_abs(penum->x_extent.y));
@@ -533,14 +532,22 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
/* For now we have 3 cases. A CMYK (4 channel), gray, or other case
the latter of which is not yet implemented */
for (k = 0; k < spp_out; k++) {
- devc_contone[k] = penum->line + contone_stride * k + offset_contone[k];
+ if (posture == image_portrait) {
+ devc_contone[k] = penum->line + contone_stride * k +
+ offset_contone[k];
+ } else {
+ devc_contone[k] = penum->line + offset_contone[k] +
+ LAND_BITS * k * contone_stride;
+ }
psrc_plane[k] = psrc_cm + psrc_planestride * k;
}
switch (spp_out)
{
+ /* Monochrome output case */
case 1:
devc_contone_gray = devc_contone[0];
switch (posture) {
+ /* Monochrome portrait */
case image_portrait:
if (penum->dst_width > 0) {
if (scale_factor == fixed_1) {
@@ -567,16 +574,17 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
}
}
break;
+ /* Monochrome landscape */
case image_landscape:
/* We store the data at this point into a column. Depending
upon our landscape direction we may be going left to right
or right to left. */
if (penum->ht_landscape.flipy) {
position = penum->ht_landscape.curr_pos +
- 16 * (data_length - 1);
+ LAND_BITS * (data_length - 1);
for (k = 0; k < data_length; k++) {
devc_contone_gray[position] = psrc_cm[dda_ht.state.Q];
- position -= 16;
+ position -= LAND_BITS;
dda_next(dda_ht);
}
} else {
@@ -587,22 +595,22 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
if (scale_factor == fixed_1) {
for (k = 0; k < data_length; k++) {
devc_contone_gray[position] = psrc_cm[k];
- position += 16;
+ position += LAND_BITS;
}
} else if (scale_factor == fixed_half) {
for (k = 0; k < data_length; k+=2) {
offset = fixed2int_rounded(scale_factor * k);
devc_contone_gray[position] =
- devc_contone_gray[position + 16] =
+ devc_contone_gray[position + LAND_BITS] =
psrc_cm[offset];
- position += 32;
+ position += 2*LAND_BITS;
}
} else {
/* use dda */
for (k = 0; k < data_length; k++) {
devc_contone_gray[position] =
psrc_cm[dda_ht.state.Q];
- position += 16;
+ position += LAND_BITS;
dda_next(dda_ht);
}
}
@@ -619,8 +627,10 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
}
break;
+ /* CMYK case */
case 4:
switch (posture) {
+ /* CMYK portrait */
case image_portrait:
if (penum->dst_width > 0) {
if (scale_factor == fixed_1) {
@@ -670,18 +680,21 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
}
}
break;
+ /* CMYK landscape */
case image_landscape:
-#if 0
- /* THIS WILL NOT WORK YET */
- /* We store the data at this point into a column. Depending
- upon our landscape direction we may be going left to right
- or right to left. */
+ /* Data is already color managed. */
+ /* We store the data at this point into a columns in
+ seperate planes. Depending upon our landscape direction
+ we may be going left to right or right to left. */
if (penum->ht_landscape.flipy) {
position = penum->ht_landscape.curr_pos +
- 16 * (data_length - 1);
+ LAND_BITS * (data_length - 1);
for (k = 0; k < data_length; k++) {
- devc_contone[position] = psrc_cm[dda_ht.state.Q];
- position -= 16;
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j] + position) =
+ (psrc_plane[j])[dda_ht.state.Q];
+ }
+ position -= LAND_BITS;
dda_next(dda_ht);
}
} else {
@@ -689,23 +702,38 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
/* Code up special cases for when we have no scaling
and 2x scaling which we will run into in 300 and
600dpi devices and content */
+ /* Apply initial offset */
+ for (k = 0; k < spp_out; k++) {
+ devc_contone[k] = devc_contone[k] + position;
+ }
if (scale_factor == fixed_1) {
for (k = 0; k < data_length; k++) {
- devc_contone[position] = psrc_cm[k];
- position += 16;
+ /* Is it better to unwind this? We know it is 4 */
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j]) = (psrc_plane[j])[k];
+ devc_contone[j] += LAND_BITS;
+ }
}
} else if (scale_factor == fixed_half) {
for (k = 0; k < data_length; k+=2) {
offset = fixed2int_rounded(scale_factor * k);
- devc_contone[position] =
- devc_contone[position + 16] = psrc_cm[offset];
- position += 32;
+ /* Is it better to unwind this? We know it is 4 */
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j]) =
+ *(devc_contone[j] + LAND_BITS) =
+ (psrc_plane[j])[offset];
+ devc_contone[j] += 2 * LAND_BITS;
+ }
}
} else {
/* use dda */
for (k = 0; k < data_length; k++) {
- devc_contone[position] = psrc_cm[dda_ht.state.Q];
- position += 16;
+ /* Is it better to unwind this? We know it is 4 */
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j]) =
+ (psrc_plane[j])[dda_ht.state.Q];
+ devc_contone[j] += LAND_BITS;
+ }
dda_next(dda_ht);
}
}
@@ -715,7 +743,6 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
penum->ht_landscape.widths[penum->ht_landscape.curr_pos] = vdi;
penum->ht_landscape.curr_pos += penum->ht_landscape.index;
penum->ht_landscape.num_contones++;
-#endif
break;
default:
/* error not allowed */
@@ -729,15 +756,25 @@ image_render_color_thresh(gx_image_enum *penum_orig, const byte *buffer, int dat
/* Apply threshold array to image data. It may be neccessary to invert
depnding upon the polarity of the device */
flush:
+ thresh_align = penum->thresh_buffer + offset_threshold;
for (k = 0; k < spp_out; k++) {
d_order = &(penum->pis->dev_ht->components[k].corder);
- contone_align = penum->line + contone_stride * k +
- offset_contone[k];
- thresh_align = penum->thresh_buffer + contone_stride * vdi * k +
- offset_threshold[k];
+ if (posture == image_portrait) {
+ contone_align = penum->line + contone_stride * k +
+ offset_contone[k];
+ allow_reset = true;
+ } else {
+ contone_align = penum->line + offset_contone[k] +
+ LAND_BITS * k * contone_stride;
+ if (k == spp_out - 1) {
+ allow_reset = true;
+ } else {
+ allow_reset = false;
+ }
+ }
code = gxht_thresh_plane(penum, d_order, xrun, dest_width, dest_height,
- thresh_align, contone_align, contone_stride,
- dev, k);
+ thresh_align, contone_align,
+ contone_stride, dev, k, allow_reset);
}
return code;
}
diff --git a/gs/base/gxidata.c b/gs/base/gxidata.c
index e8b993e44..81e7c7d0c 100644
--- a/gs/base/gxidata.c
+++ b/gs/base/gxidata.c
@@ -476,12 +476,10 @@ gx_image1_end_image(gx_image_enum_common_t * info, bool draw_last)
gs_free_object(mem, penum->color_cache, "image color cache");
}
if (penum->thresh_buffer != NULL) {
- gs_free_object(mem, penum->thresh_buffer,
- "image thresh_buffer");
+ gs_free_object(mem, penum->thresh_buffer, "image thresh_buffer");
}
if (penum->ht_buffer != NULL) {
- gs_free_object(mem, penum->ht_buffer,
- "image ht_buffer");
+ gs_free_object(mem, penum->ht_buffer, "image ht_buffer");
}
if (penum->clues != NULL) {
gs_free_object(mem,penum->clues, "image clues");
diff --git a/gs/base/gximono.c b/gs/base/gximono.c
index c94bb8990..8a24a0c3f 100644
--- a/gs/base/gximono.c
+++ b/gs/base/gximono.c
@@ -40,6 +40,7 @@
#include "gscie.h"
#include "gxht_thresh.h"
#include "gxdda.h"
+#include "gxdevsop.h"
#define USE_FAST_CODE 1
#define fastfloor(x) (((int)(x)) - (((x)<0) && ((x) != (float)(int)(x))))
@@ -72,7 +73,10 @@ gs_image_class_3_mono(gx_image_enum * penum)
gsicc_rendering_param_t rendering_params;
int num_des_comps;
cmm_dev_profile_t *dev_profile;
-
+ bool dev_color_ok = false;
+ bool is_planar_dev = dev_proc(penum->dev, dev_spec_op)(penum->dev,
+ gxdso_is_native_planar, NULL, 0);
+
if (penum->spp == 1) {
/* At this point in time, only use the ht approach if our device
uses halftoning, and our source image is a reasonable size. We
@@ -82,9 +86,14 @@ gs_image_class_3_mono(gx_image_enum * penum)
to the limited precision and mismatch of the stepping space in which
the interpolations occur this can cause a minor mismatch at large
scalings */
- if (use_fast_code && penum->pcs != NULL &&
- penum->dev->color_info.num_components == 1 &&
- penum->dev->color_info.depth == 1 &&
+
+ /* Allow this for CMYK planar and mono binary halftoned devices */
+ dev_color_ok = ((penum->dev->color_info.num_components == 1 &&
+ penum->dev->color_info.depth == 1) ||
+ (penum->dev->color_info.num_components == 4 &&
+ penum->dev->color_info.depth == 4 && is_planar_dev));
+
+ if (use_fast_code && penum->pcs != NULL && dev_color_ok &&
penum->bps == 8 && (penum->posture == image_portrait
|| penum->posture == image_landscape) &&
penum->image_parent_type == gs_image_type1) {
@@ -783,16 +792,18 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
int dest_width, dest_height, data_length;
byte *color_cache;
gx_ht_order *d_order = &(penum->pis->dev_ht->components[0].corder);
- int position, k;
+ int position, k, j;
int offset_bits = penum->ht_offset_bits;
int contone_stride = 0; /* Not used in landscape case */
fixed scale_factor, offset;
int src_size;
bool flush_buff = false;
int offset_contone[GX_DEVICE_COLOR_MAX_COMPONENTS]; /* to ensure 128 bit boundary */
- int offset_threshold[GX_DEVICE_COLOR_MAX_COMPONENTS]; /* to ensure 128 bit boundary */
+ int offset_threshold; /* to ensure 128 bit boundary */
gx_dda_int_t dda_ht;
int code = 0;
+ bool allow_reset;
+ byte *dev_value;
if (h == 0) {
if (penum->ht_landscape.count == 0 || posture == image_portrait) {
@@ -820,13 +831,12 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
xrun += penum->x_extent.x;
vdi = penum->hci;
contone_stride = penum->line_size;
+ offset_threshold = (- (((long)(penum->thresh_buffer)) +
+ penum->ht_offset_bits)) & 15;
for (k = 0; k < spp_out; k ++) {
offset_contone[k] = (- (((long)(penum->line)) +
contone_stride * k +
penum->ht_offset_bits)) & 15;
- offset_threshold[k] = (- (((long)(penum->thresh_buffer)) +
- contone_stride * vdi * k +
- penum->ht_offset_bits)) & 15;
}
data_length = dest_width;
dest_height = fixed2int_var_rounded(any_abs(penum->y_extent.y));
@@ -843,15 +853,15 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
Can't do this earlier as GC may move the buffers.
*/
vdi = penum->wci;
+ contone_stride = penum->line_size;
dest_width = fixed2int_var_rounded(any_abs(penum->y_extent.x));
dest_height = fixed2int_var_rounded(any_abs(penum->x_extent.y));
data_length = dest_height;
scale_factor = float2fixed_rounded((float) src_size / (float) (dest_height - 1));
+ offset_threshold = (-(long)(penum->thresh_buffer)) & 15;
for (k = 0; k < spp_out; k ++) {
offset_contone[k] = (- ((long)(penum->line) +
contone_stride * k)) & 15;
- offset_threshold[k] = (-((long)(penum->thresh_buffer) +
- contone_stride * vdi * k)) & 15;
}
/* In the landscaped case, we want to accumulate multiple columns
of data before sending to the device. We want to have a full
@@ -886,7 +896,13 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
}
/* Get the pointers to our buffers */
for (k = 0; k < spp_out; k++) {
- devc_contone[k] = penum->line + offset_contone[k];
+ if (posture == image_portrait) {
+ devc_contone[k] = penum->line + contone_stride * k +
+ offset_contone[k];
+ } else {
+ devc_contone[k] = penum->line + offset_contone[k] +
+ LAND_BITS * k * contone_stride;
+ }
}
if (flush_buff) goto flush; /* All done */
/* Set up the dda. We could move this out but the cost is pretty small */
@@ -980,17 +996,19 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
case image_portrait:
if (penum->dst_width > 0) {
if (spp_out == 1) {
+ /* Mono case */
for (k = 0; k < data_length; k++) {
*devc_contone_gray++ = color_cache[psrc[dda_ht.state.Q]];
dda_next(dda_ht);
}
} else {
- /* CMYK planar case: NEED TO FIX */
+ /* CMYK case */
for (k = 0; k < data_length; k++) {
- /* dev_value = color_cache + psrc[dda_ht.state.Q] * spp_out;
- memcpy(devc_contone, dev_value, spp_out);
- devc_contone += spp_out;
- dda_next(dda_ht); */
+ dev_value = color_cache + psrc[dda_ht.state.Q] * spp_out;
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j])++ = dev_value[j];
+ }
+ dda_next(dda_ht);
}
}
} else {
@@ -1000,12 +1018,16 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
dda_next(dda_ht);
}
} else {
- /* CMYK planar case: NEED TO FIX */
+ /* Move to the other end and we will decrement */
+ for (j = 0; j < spp_out; j++) {
+ devc_contone[j] = devc_contone[j] + data_length - 1;
+ }
for (k = 0; k < data_length; k++) {
- /* dev_value = color_cache + psrc[dda_ht.state.Q] * spp_out;
- memcpy(&(devc_contone[(data_length - k - 1) * spp_out]),
- dev_value, spp_out);
- dda_next(dda_ht); */
+ dev_value = color_cache + psrc[dda_ht.state.Q] * spp_out;
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j])-- = dev_value[j];
+ }
+ dda_next(dda_ht);
}
}
}
@@ -1025,30 +1047,39 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
dda_next(dda_ht);
}
} else {
- /* CMYK planar case: NEED TO FIX */
for (k = 0; k < data_length; k++) {
- /* dev_value = color_cache + psrc[dda_ht.state.Q] * spp_out;
- devc_contone[position] = dev_value[0];
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j] + position) =
+ color_cache[psrc[dda_ht.state.Q] * spp_out + j];
+ }
position -= LAND_BITS;
- dda_next(dda_ht); */
+ dda_next(dda_ht);
}
}
- } else {
+ } else { /* Not flipped in Y */
position = penum->ht_landscape.curr_pos;
/* use dda */
if (spp_out == 1) {
for (k = 0; k < data_length; k++) {
- devc_contone_gray[position] = color_cache[psrc[dda_ht.state.Q]];
+ devc_contone_gray[position] =
+ color_cache[psrc[dda_ht.state.Q]];
position += LAND_BITS;
dda_next(dda_ht);
}
} else {
- /* CMYK planar case: NEED TO FIX */
+ /* CMYK case */
+ /* Apply initial offset */
+ for (k = 0; k < spp_out; k++) {
+ devc_contone[k] = devc_contone[k] + position;
+ }
for (k = 0; k < data_length; k++) {
- /* dev_value = color_cache + psrc[dda_ht.state.Q] * spp_out;
- devc_contone[position] = dev_value[0];
- position += LAND_BITS;
- dda_next(dda_ht); */
+ /* Is it better to unwind this? We know it is 4 */
+ for (j = 0; j < spp_out; j++) {
+ *(devc_contone[j]) =
+ color_cache[psrc[dda_ht.state.Q] * spp_out + j];
+ devc_contone[j] += LAND_BITS;
+ }
+ dda_next(dda_ht);
}
}
}
@@ -1065,15 +1096,25 @@ image_render_mono_ht(gx_image_enum * penum_orig, const byte * buffer, int data_x
}
/* Apply threshold array to image data */
flush:
+ thresh_align = penum->thresh_buffer + offset_threshold;
for (k = 0; k < spp_out; k++) {
d_order = &(penum->pis->dev_ht->components[k].corder);
- contone_align = penum->line + contone_stride * k +
- offset_contone[k];
- thresh_align = penum->thresh_buffer + contone_stride * vdi * k +
- offset_threshold[k];
+ if (posture == image_portrait) {
+ contone_align = penum->line + contone_stride * k +
+ offset_contone[k];
+ allow_reset = true;
+ } else {
+ contone_align = penum->line + offset_contone[k] +
+ LAND_BITS * k * contone_stride;
+ if (k == spp_out - 1) {
+ allow_reset = true;
+ } else {
+ allow_reset = false;
+ }
+ }
code = gxht_thresh_plane(penum, d_order, xrun, dest_width, dest_height,
thresh_align, contone_align, contone_stride,
- dev, k);
+ dev, k, allow_reset);
}
return code;
}
diff --git a/gs/base/lib.mak b/gs/base/lib.mak
index 317c1dbab..eefffe5fa 100644
--- a/gs/base/lib.mak
+++ b/gs/base/lib.mak
@@ -711,7 +711,7 @@ $(GLOBJ)gximono.$(OBJ) : $(GLSRC)gximono.c $(AK) $(gx_h) $(gserrors_h) $(memory_
$(gxarith_h) $(gxcmap_h) $(gxcpath_h) $(gxdcolor_h) $(gxdevice_h)\
$(gxdevmem_h) $(gxfixed_h) $(gximage_h) $(gxistate_h) $(gxmatrix_h)\
$(gzht_h) $(vdtrace_h) $(gsicc_h) $(gsicc_cache_h) $(gsicc_cms_h)\
- $(gxcie_h) $(gscie_h) $(gxht_thresh_h) $(gxdda_h)
+ $(gxcie_h) $(gscie_h) $(gxht_thresh_h) $(gxdda_h) $(gxdevsop_h)
$(GLCC) $(GLO_)gximono.$(OBJ) $(C_) $(GLSRC)gximono.c
$(GLOBJ)gximask.$(OBJ) : $(GLSRC)gximask.c $(AK) $(gx_h) $(gserrors_h)\