summaryrefslogtreecommitdiff
path: root/gs/src
diff options
context:
space:
mode:
authorRay Johnston <ray.johnston@artifex.com>1999-12-13 02:53:22 +0000
committerRay Johnston <ray.johnston@artifex.com>1999-12-13 02:53:22 +0000
commitd7d4186d964ca61a7893e9434fa8ac5c2d3ec321 (patch)
treeb53f35bd836bd9518881ee59389f6b8070150b25 /gs/src
parent83e369998390339d55e7ff613e61ce861a550cc4 (diff)
Fix ImageType 3 for file and procedures. Add new API gs_image_next_planes
needed to correctly implement ImageType 3 (masked images). git-svn-id: http://svn.ghostscript.com/ghostpcl/trunk/ghostpcl@1050 06663e23-700e-0410-b217-a244a6096597
Diffstat (limited to 'gs/src')
-rw-r--r--gs/src/gsimage.c161
-rw-r--r--gs/src/gsimage.h29
-rw-r--r--gs/src/zimage.c74
3 files changed, 161 insertions, 103 deletions
diff --git a/gs/src/gsimage.c b/gs/src/gsimage.c
index 1430bec54..0be1d4e92 100644
--- a/gs/src/gsimage.c
+++ b/gs/src/gsimage.c
@@ -23,7 +23,7 @@
typedef struct image_enum_plane_s {
/* Change dynamically */
uint pos; /* byte position within the scan line */
- gs_const_string source; /* source data, [0 .. plane_index - 1] */
+ gs_const_string source; /* source data, [0 .. num_planes - 1] */
gs_string row; /* row buffers, [0 .. num_planes - 1] */
} image_enum_plane_t;
struct gs_image_enum_s {
@@ -35,7 +35,8 @@ struct gs_image_enum_s {
int height;
bool wanted_varies;
/* The following are updated dynamically. */
- int plane_index; /* index of next plane of data */
+ int plane_index; /* index of next plane of data, */
+ /* only needed for gs_image_next */
int y;
bool error;
byte wanted[gs_image_max_planes];
@@ -188,6 +189,7 @@ gs_image_common_init(gs_image_enum * penum, gx_image_enum_common_t * pie,
penum->height = pim->Height;
for (i = 0; i < pie->num_planes; ++i) {
penum->planes[i].pos = 0;
+ penum->planes[i].source.size = 0; /* for gs_image_next_planes */
penum->planes[i].row.data = 0; /* for GC */
penum->planes[i].row.size = 0; /* ditto */
}
@@ -253,11 +255,11 @@ int
gs_image_next(gs_image_enum * penum, const byte * dbytes, uint dsize,
uint * pused)
{
- const gx_image_enum_common_t *pie = penum->info;
int px = penum->plane_index;
- gx_device *dev;
int num_planes = penum->num_planes;
- int code;
+ int i, code;
+ uint used[gs_image_max_planes];
+ gs_const_string plane_data[gs_image_max_planes];
/*
* Handle the following differences between gs_image_next and
@@ -266,52 +268,80 @@ gs_image_next(gs_image_enum * penum, const byte * dbytes, uint dsize,
* - image_data requires an array of planes; gs_image_next
* expects planes in successive calls.
*
+ * This function is now deprecated -- gs_image_next_planes does
+ * the real work of buffering.
+ */
+ for (i = 0; i < num_planes; i++)
+ plane_data[i].size = 0;
+ plane_data[px].data = dbytes;
+ plane_data[px].size = dsize;
+ penum->error = false;
+ code = gs_image_next_planes(penum, plane_data, used);
+ if (code >= 0) {
+ /* Advance px to the next plane that needs data. */
+ do {
+ if (++px == num_planes)
+ px = 0;
+ } while (!penum->wanted[px]);
+ penum->plane_index = px;
+ }
+ *pused = used[px];
+ return code;
+}
+
+int
+gs_image_next_planes(gs_image_enum * penum, gs_const_string *plane_data,
+ uint * used)
+{
+ gx_image_plane_t planes[gs_image_max_planes];
+ gx_device *dev = penum->dev;
+ int num_planes = penum->num_planes;
+ int i;
+ int code = 0;
+ bool need_planes = false;
+
+ /*
+ * Handle the following differences between gs_image_next_planes and
+ * the device image_data procedure:
+ *
+ * - image_data requires an array of planes; not all of the
+ * planes may be available on any given call.
+ *
* - image_data requires that each call pass entire rows;
- * gs_image_next allows arbitrary amounts of data.
+ * gs_image_next_planes allows arbitrary amounts of data.
*/
- if (penum->error) {
- /*
- * We were interrupted by an error. The current data are the
- * same as the data presented at the last call.
- */
- penum->error = false;
- } else {
- if (px != 0 && dsize != penum->planes[0].source.size &&
- pie->plane_depths[px] == pie->plane_depths[0] &&
- pie->plane_widths[px] == pie->plane_widths[0])
- return_error(gs_error_rangecheck);
- penum->planes[px].source.data = dbytes;
- penum->planes[px].source.size = dsize;
- while (++px < num_planes && !penum->wanted[px])
- DO_NOTHING;
- if (px < num_planes) {
- /* We need more planes. */
- penum->plane_index = px;
- return 0;
+ for (i = 0; i < num_planes; ++i) {
+ used[i] = 0;
+ if (!penum->wanted[i])
+ planes[i].data = 0;
+ else {
+ if (plane_data[i].size != 0) {
+ penum->planes[i].source.size = plane_data[i].size;
+ penum->planes[i].source.data = plane_data[i].data;
+ planes[i].data_x = 0;
+ planes[i].raster = gs_image_bytes_per_plane_row(penum, i);
+ }
+ if (penum->planes[i].source.size == 0)
+ need_planes = true; /* can't proceed until we have all planes */
}
}
- /* We have a full set of planes. */
- dev = penum->dev;
- code = 0;
- /****** HOW TO STOP IN TIME IF TOO MUCH DATA? ******/
+ if (need_planes)
+ return 0; /* exit for more data, nothing used */
while (!code) {
- gx_image_plane_t planes[gs_image_max_planes];
- int i;
int direct = max_int;
bool filled = true;
+ bool empty = false;
+ /* see if we can do some rows without buffering (i.e., direct) */
for (i = 0; i < num_planes; ++i) {
- if (!penum->wanted[i])
- planes[i].data = 0;
- else {
- planes[i].data_x = 0;
+ /* need to reset planes[].raster if wanted_varies */
+ if (penum->wanted_varies)
planes[i].raster = gs_image_bytes_per_plane_row(penum, i);
- if (penum->planes[i].pos == 0)
- direct = min(direct, penum->planes[i].source.size /
- planes[i].raster);
- else
- direct = 0;
- }
+ if (penum->planes[i].pos == 0) /* nothing buffered for this row */
+ direct = min(direct,
+ penum->planes[i].source.size / planes[i].raster);
+ else
+ direct = 0;
}
if (direct) {
/*
@@ -324,26 +354,30 @@ gs_image_next(gs_image_enum * penum, const byte * dbytes, uint dsize,
if (penum->wanted[i])
planes[i].data = penum->planes[i].source.data;
code = copy_planes(dev, penum, planes, direct, &direct);
+ if (code < 0)
+ return code; /* don't update */
for (i = 0; i < num_planes; ++i)
if (planes[i].data) {
- uint used = direct * planes[i].raster;
+ uint direct_used = direct * planes[i].raster;
- penum->planes[i].source.data += used;
- penum->planes[i].source.size -= used;
+ used[i] += direct_used;
+ penum->planes[i].source.data += direct_used;
+ penum->planes[i].source.size -= direct_used;
+ if (penum->planes[i].source.size == 0)
+ empty = true;
}
penum->y += direct;
if (code < 0)
break;
} else { /* Buffer a partial row. */
- bool empty = false;
uint count[gs_image_max_planes];
- /* Make sure the row buffers are allocated. */
- for (i = 0; i < num_planes; ++i)
- if (penum->wanted[i]) {
+ for (i = 0; i < num_planes; ++i) {
+ if (penum->planes[i].source.size != 0) {
uint raster = planes[i].raster;
uint old_size = penum->planes[i].row.size;
+ /* Make sure the row buffers are allocated. */
if (raster > old_size) {
byte *old_data = penum->planes[i].row.data;
byte *row =
@@ -362,15 +396,15 @@ gs_image_next(gs_image_enum * penum, const byte * dbytes, uint dsize,
penum->planes[i].row.data = row;
penum->planes[i].row.size = raster;
}
- count[i] = min(raster - penum->planes[i].pos,
- penum->planes[i].source.size);
- memcpy(penum->planes[i].row.data + penum->planes[i].pos,
+ if ((count[i] = min(raster - penum->planes[i].pos,
+ penum->planes[i].source.size)) > 0) {
+ memcpy(penum->planes[i].row.data + penum->planes[i].pos,
penum->planes[i].source.data, count[i]);
- if ((penum->planes[i].pos += count[i]) < raster) {
- filled = false;
- empty |= count[i] == 0;
+ if ((penum->planes[i].pos += count[i]) < raster)
+ filled = false;
}
}
+ }
if (code < 0)
break;
if (filled) {
@@ -385,26 +419,25 @@ gs_image_next(gs_image_enum * penum, const byte * dbytes, uint dsize,
penum->planes[i].pos -= count[i];
break;
}
- for (i = 0; i < num_planes; ++i)
+ for (i = 0; i < num_planes; ++i) {
penum->planes[i].pos = 0;
+ }
penum->y++;
}
- for (i = 0; i < num_planes; ++i)
+ for (i = 0; i < num_planes; ++i) {
if (penum->wanted[i]) {
+ used[i] += count[i];
penum->planes[i].source.data += count[i];
- penum->planes[i].source.size -= count[i];
+ if ((penum->planes[i].source.size -= count[i]) == 0)
+ empty = true;
}
- if (empty)
- break;
+ }
}
if (filled & !code)
begin_planes(penum);
+ if (empty)
+ break;
}
- /*
- * We only set *pused for the last plane of a group. We will have to
- * rethink this in order to handle varying-size planes.
- */
- *pused = penum->planes[penum->plane_index].source.data - dbytes;
return code;
}
diff --git a/gs/src/gsimage.h b/gs/src/gsimage.h
index dc861cf51..fc172031b 100644
--- a/gs/src/gsimage.h
+++ b/gs/src/gsimage.h
@@ -53,12 +53,10 @@ int gs_image_enum_init(P4(gs_image_enum * penum,
const gs_data_image_t * pim, gs_state *pgs));
int gs_image_init(P4(gs_image_enum * penum, const gs_image_t * pim,
bool MultipleDataSources, gs_state * pgs));
-int gs_image_next(P4(gs_image_enum * penum, const byte * dbytes,
- uint dsize, uint * pused));
/*
* Return the number of bytes of data per row
- * (per plane, if MultipleDataSources is true).
+ * (per plane, if there are multiple data sources).
*/
uint gs_image_bytes_per_plane_row(P2(const gs_image_enum * penum, int plane));
@@ -74,4 +72,29 @@ const byte *gs_image_planes_wanted(P1(const gs_image_enum *penum));
/* Clean up after processing an image. */
void gs_image_cleanup(P1(gs_image_enum * penum));
+/*
+ * Pass multiple or selected planes of data for an image.
+ * *plane_data is an array of size num_planes of gs_const_string type
+ * which contains the pointer and the length for each.
+ * *used is also of size num_planes and will be set to the number of
+ * bytes consumed for each plane.
+ * The amount of data available for planes can be 0 in order to provide
+ * data for a single plane or only some of the planes.
+ *
+ * Returns 1 if end of image, < 0 error code, otherwise 0.
+ *
+ * ****** NEEDS DOC FROM RAY ABOUT RETENTION OF SOURCE DATA ******
+ */
+int gs_image_next_planes(P3(gs_image_enum *penum,
+ gs_const_string *plane_data,
+ uint *used));
+
+/*
+ * Pass the next plane of data for an image. This procedure should no
+ * longer be used: use gs_image_next_planes instead.
+ */
+int gs_image_next(P4(gs_image_enum * penum, const byte * dbytes,
+ uint dsize, uint * pused));
+
+
#endif /* gsimage_INCLUDED */
diff --git a/gs/src/zimage.c b/gs/src/zimage.c
index 80cb7b7e1..502c5470b 100644
--- a/gs/src/zimage.c
+++ b/gs/src/zimage.c
@@ -276,8 +276,11 @@ image_proc_continue(i_ctx_t *i_ctx_p)
{
os_ptr op = osp;
gs_image_enum *penum = r_ptr(esp, gs_image_enum);
- uint size, used;
- int code;
+ int px = ETOP_PLANE_INDEX(esp)->value.intval;
+ int num_sources = ETOP_NUM_SOURCES(esp)->value.intval;
+ uint size, used[gs_image_max_planes];
+ gs_const_string plane_data[gs_image_max_planes];
+ int i, code;
if (!r_has_type_attrs(op, t_string, a_read)) {
check_op(1);
@@ -290,9 +293,14 @@ image_proc_continue(i_ctx_t *i_ctx_p)
if (size == 0)
code = 1;
else {
- code = gs_image_next(penum, op->value.bytes, size, &used);
+ for (i = 0; i < num_sources; i++)
+ plane_data[i].size = 0;
+ plane_data[px].data = op->value.bytes;
+ plane_data[px].size = size;
+ code = gs_image_next_planes(penum, plane_data, used);
if (code == e_RemapColor)
return code;
+ size -= used[px]; /* how much unused in this string */
}
if (code) { /* Stop now. */
esp = zimage_pop_estack(esp);
@@ -301,6 +309,11 @@ image_proc_continue(i_ctx_t *i_ctx_p)
return (code < 0 ? code : o_pop_estack);
}
pop(1);
+ if (size != 0) { /* need a different plane of data */
+ if (++px == num_sources)
+ px = 0;
+ ETOP_PLANE_INDEX(esp)->value.intval = px;
+ }
return image_proc_process(i_ctx_p);
}
private int
@@ -310,20 +323,17 @@ image_proc_process(i_ctx_t *i_ctx_p)
gs_image_enum *penum = r_ptr(esp, gs_image_enum);
const byte *wanted = gs_image_planes_wanted(penum);
int num_sources = ETOP_NUM_SOURCES(esp)->value.intval;
+ const ref *pp;
- for (;;) {
- const ref *pp = ETOP_SOURCE(esp, px);
- bool xmit = wanted[px];
-
+ while (!wanted[px]) {
if (++px == num_sources)
px = 0;
- if (xmit) {
- ETOP_PLANE_INDEX(esp)->value.intval = px;
- push_op_estack(image_proc_continue);
- *++esp = *pp;
- return o_push_estack;
- }
+ ETOP_PLANE_INDEX(esp)->value.intval = px;
}
+ pp = ETOP_SOURCE(esp, px);
+ push_op_estack(image_proc_continue);
+ *++esp = *pp;
+ return o_push_estack;
}
/* Continue processing data from an image with file data sources. */
private int
@@ -333,15 +343,15 @@ image_file_continue(i_ctx_t *i_ctx_p)
int num_sources = ETOP_NUM_SOURCES(esp)->value.intval;
for (;;) {
- uint size = max_uint;
+ uint min_avail = max_int;
+ gs_const_string plane_data[gs_image_max_planes];
int code;
int px;
const ref *pp;
/*
- * Do a first pass through the files to ensure that they all
- * have data available in their buffers, and compute the min
- * of the available amounts.
+ * Do a first pass through the files to ensure that at least
+ * one has data available in its buffer.
*/
for (px = 0, pp = ETOP_SOURCE(esp, 0); px < num_sources;
@@ -376,38 +386,30 @@ image_file_continue(i_ctx_t *i_ctx_p)
}
/* Note that in the EOF case, we can get here with */
/* avail < min_left. */
- if (avail >= min_left) {
+ if (avail >= min_left)
avail = (avail - min_left) / num_aliases;
- if (avail < size)
- size = avail;
- } else
- size = 0;
+ if (avail < min_avail)
+ min_avail = avail;
+ plane_data[px].data = sbufptr(s);
+ plane_data[px].size = avail;
}
- /* Now pass the min of the available buffered data to */
- /* the image processor. */
+ /* Now pass the available buffered data to the image processor. */
- if (size == 0)
+ if (min_avail == 0)
code = 1;
else {
int pi;
- uint used; /* only set for the last plane */
-
- /****** WRONG IF ALIASING ******/
- /****** CHECK wanted ******/
- for (px = 0, pp = ETOP_SOURCE(esp, 0), code = 0;
- px < num_sources && !code;
- ++px, pp -= 2
- )
- code = gs_image_next(penum, sbufptr(pp->value.pfile),
- size, &used);
+ uint used[gs_image_max_planes];
+
+ code = gs_image_next_planes(penum, plane_data, used);
if (code == e_RemapColor)
return code;
/* Now that used has been set, update the streams. */
for (pi = 0, pp = ETOP_SOURCE(esp, 0); pi < num_sources;
++pi, pp -= 2
)
- sbufskip(pp->value.pfile, used);
+ sbufskip(pp->value.pfile, used[pi]);
}
if (code) {
esp = zimage_pop_estack(esp);