/* Update the strip DDA when moving to a new row. */ static void update_strip(gx_image_enum *penum) { #if 1 /* Old code. */ dda_translate(penum->dda.strip.x, penum->cur.x - penum->prev.x); dda_translate(penum->dda.strip.y, penum->cur.y - penum->prev.y); penum->dda.pixel0 = penum->dda.strip; #else /* A better precision with stromng dda_advance - doesn't work becauae gx_image1_plane_data doesn't call it at each step. */ gx_dda_fixed_point temp; temp.x.state = penum->dda.strip.x.state; temp.y.state = penum->dda.strip.y.state; temp.x.step = penum->dda.row.x.step; temp.y.step = penum->dda.row.y.step; dda_next(temp.x); dda_next(temp.y); penum->dda.strip.x.state = temp.x.state; penum->dda.strip.y.state = temp.y.state; penum->dda.pixel0 = penum->dda.strip; #endif }
/* Update the strip DDA when moving to a new row. */ static void update_strip(gx_image_enum *penum) { dda_translate(penum->dda.strip.x, penum->cur.x - penum->prev.x); dda_translate(penum->dda.strip.y, penum->cur.y - penum->prev.y); penum->dda.pixel0 = penum->dda.strip; }
/* Process the next piece of an image */ int gx_default_image_data(gx_device *dev, void *info, const byte **planes, int data_x, uint raster, int height) { gx_image_enum *penum = info; int y = penum->y; int y_end = min(y + height, penum->rect.h); int width_spp = penum->rect.w * penum->spp; int nplanes = penum->num_planes; uint bcount = /* bytes per data row */ (width_spp / penum->num_planes * penum->bps + 7) >> 3; fixed adjust = penum->adjust; gx_dda_fixed_point pixel0; ulong offset = 0; int ignore_data_x; int code; if ( height == 0 ) return 0; /* Set up the clipping and/or RasterOp device if needed. */ if ( penum->clip_dev ) { gx_device_clip *cdev = penum->clip_dev; cdev->target = dev; dev = (gx_device *)cdev; } if ( penum->rop_dev ) { gx_device_rop_texture *rtdev = penum->rop_dev; ((gx_device_forward *)rtdev)->target = dev; dev = (gx_device *)rtdev; } pixel0 = penum->dda.pixel0; /* Now render complete rows. */ for ( ; penum->y < y_end; offset += raster, penum->y++ ) { int px; /* * Normally, we unpack the data into the buffer, but if * there is only one plane and we don't need to expand the * input samples, we may use the data directly. */ int sourcex = data_x; const byte *buffer = (*penum->unpack)(penum->buffer, &sourcex, planes[0] + offset, data_x, bcount, &penum->map[0].table, penum->spread); for ( px = 1; px < nplanes; ++px ) (*penum->unpack)(penum->buffer + (px << penum->log2_xbytes), &ignore_data_x, planes[px] + offset, data_x, bcount, &penum->map[px].table, penum->spread); #ifdef DEBUG if ( gs_debug_c('B') ) { int i, n = width_spp; dputs("[B]row:"); for ( i = 0; i < n; i++ ) dprintf1(" %02x", buffer[i]); dputs("\n"); } #endif penum->cur.x = dda_current(penum->dda.row.x); dda_next(penum->dda.row.x); penum->cur.y = dda_current(penum->dda.row.y); dda_next(penum->dda.row.y); if ( !penum->interpolate ) switch ( penum->posture ) { case image_portrait: { /* Precompute integer y and height, */ /* and check for clipping. */ fixed yc = penum->cur.y, yn = dda_current(penum->dda.row.y); if ( yn < yc ) { fixed temp = yn; yn = yc; yc = temp; } yc -= adjust; if ( yc >= penum->clip_outer.q.y ) goto mt; yn += adjust; if ( yn <= penum->clip_outer.p.y ) goto mt; penum->yci = fixed2int_pixround(yc); penum->hci = fixed2int_pixround(yn) - penum->yci; if ( penum->hci == 0 ) goto mt; } break; case image_landscape: { /* Check for no pixel centers in x. */ fixed xc = penum->cur.x, xn = dda_current(penum->dda.row.x); if ( xn < xc ) { fixed temp = xn; xn = xc; xc = temp; } xc -= adjust; if ( xc >= penum->clip_outer.q.x ) goto mt; xn += adjust; if ( xn <= penum->clip_outer.p.x ) goto mt; penum->xci = fixed2int_pixround(xc); penum->wci = fixed2int_pixround(xn) - penum->xci; if ( penum->wci == 0 ) goto mt; } break; case image_skewed: ; } dda_translate(penum->dda.pixel0.x, penum->cur.x - penum->prev.x); dda_translate(penum->dda.pixel0.y, penum->cur.y - penum->prev.y); penum->prev = penum->cur; code = (*penum->render)(penum, buffer, sourcex, width_spp, 1, dev); if ( code < 0 ) goto err; mt: ; } if ( penum->y < penum->rect.h ) { code = 0; goto out; } /* End of data. Render any left-over buffered data. */ switch ( penum->posture ) { case image_portrait: { fixed yc = dda_current(penum->dda.row.y); penum->yci = fixed2int_rounded(yc - adjust); penum->hci = fixed2int_rounded(yc + adjust) - penum->yci; } break; case image_landscape: { fixed xc = dda_current(penum->dda.row.x); penum->xci = fixed2int_rounded(xc - adjust); penum->wci = fixed2int_rounded(xc + adjust) - penum->xci; } break; case image_skewed: /* pacify compilers */ ; } dda_translate(penum->dda.pixel0.x, penum->cur.x - penum->prev.x); dda_translate(penum->dda.pixel0.y, penum->cur.y - penum->prev.y); code = (*penum->render)(penum, NULL, 0, width_spp, 0, dev); if ( code < 0 ) { penum->y--; goto err; } code = 1; goto out; err: /* Error or interrupt, restore original state. */ while ( penum->y > y ) { dda_previous(penum->dda.row.x); dda_previous(penum->dda.row.y); --(penum->y); } /* Note that caller must call end_image */ /* for both error and normal termination. */ out: return code; }
/* Process the next piece of an ImageType 1 image. */ int gx_image1_plane_data(gx_image_enum_common_t * info, const gx_image_plane_t * planes, int height, int *rows_used) { gx_image_enum *penum = (gx_image_enum *) info; gx_device *dev; const int y = penum->y; int y_end = min(y + height, penum->rect.h); int width_spp = penum->rect.w * penum->spp; int num_planes = penum->num_planes; int num_components_per_plane = 1; #define BCOUNT(plane) /* bytes per data row */\ (((penum->rect.w + (plane).data_x) * penum->spp * penum->bps / num_planes\ + 7) >> 3) fixed adjust = penum->adjust; ulong offsets[GS_IMAGE_MAX_COMPONENTS]; int ignore_data_x; bool bit_planar = penum->num_planes > penum->spp; int code; if (height == 0) { *rows_used = 0; return 0; } dev = setup_image_device(penum); /* Now render complete rows. */ if (penum->used.y) { /* * Processing was interrupted by an error. Skip over rows * already processed. */ int px; for (px = 0; px < num_planes; ++px) offsets[px] = planes[px].raster * penum->used.y; penum->used.y = 0; } else memset(offsets, 0, num_planes * sizeof(offsets[0])); if (num_planes == 1 && penum->plane_depths[0] != penum->bps) { /* A single plane with multiple components. */ num_components_per_plane = penum->plane_depths[0] / penum->bps; } for (; penum->y < y_end; penum->y++) { int px; const byte *buffer; int sourcex; int x_used = penum->used.x; if (bit_planar) { /* Repack the bit planes into byte-wide samples. */ buffer = penum->buffer; sourcex = 0; for (px = 0; px < num_planes; px += penum->bps) repack_bit_planes(planes, offsets, penum->bps, penum->buffer, penum->rect.w, &penum->map[px].table, penum->spread); for (px = 0; px < num_planes; ++px) offsets[px] += planes[px].raster; } else { /* * Normally, we unpack the data into the buffer, but if * there is only one plane and we don't need to expand the * input samples, we may use the data directly. */ sourcex = planes[0].data_x; buffer = (*penum->unpack)(penum->buffer, &sourcex, planes[0].data + offsets[0], planes[0].data_x, BCOUNT(planes[0]), &penum->map[0], penum->spread, num_components_per_plane); offsets[0] += planes[0].raster; for (px = 1; px < num_planes; ++px) { (*penum->unpack)(penum->buffer + (px << penum->log2_xbytes), &ignore_data_x, planes[px].data + offsets[px], planes[px].data_x, BCOUNT(planes[px]), &penum->map[px], penum->spread, 1); offsets[px] += planes[px].raster; } } #ifdef DEBUG if (gs_debug_c('b')) dprintf1("[b]image1 y=%d\n", y); if (gs_debug_c('B')) { int i, n = width_spp; if (penum->bps > 8) n *= 2; else if (penum->bps == 1 && penum->unpack_bps == 8) n = (n + 7) / 8; dlputs("[B]row:"); for (i = 0; i < n; i++) dprintf1(" %02x", buffer[i]); dputs("\n"); } #endif penum->cur.x = dda_current(penum->dda.row.x); dda_next(penum->dda.row.x); penum->cur.y = dda_current(penum->dda.row.y); dda_next(penum->dda.row.y); if (!penum->interpolate) switch (penum->posture) { case image_portrait: { /* Precompute integer y and height, */ /* and check for clipping. */ fixed yc = penum->cur.y, yn = dda_current(penum->dda.row.y); if (yn < yc) { fixed temp = yn; yn = yc; yc = temp; } yc -= adjust; if (yc >= penum->clip_outer.q.y) goto mt; yn += adjust; if (yn <= penum->clip_outer.p.y) goto mt; penum->yci = fixed2int_pixround_perfect(yc); penum->hci = fixed2int_pixround_perfect(yn) - penum->yci; if (penum->hci == 0) goto mt; if_debug2('b', "[b]yci=%d, hci=%d\n", penum->yci, penum->hci); } break; case image_landscape: { /* Check for no pixel centers in x. */ fixed xc = penum->cur.x, xn = dda_current(penum->dda.row.x); if (xn < xc) { fixed temp = xn; xn = xc; xc = temp; } xc -= adjust; if (xc >= penum->clip_outer.q.x) goto mt; xn += adjust; if (xn <= penum->clip_outer.p.x) goto mt; penum->xci = fixed2int_pixround_perfect(xc); penum->wci = fixed2int_pixround_perfect(xn) - penum->xci; if (penum->wci == 0) goto mt; if_debug2('b', "[b]xci=%d, wci=%d\n", penum->xci, penum->wci); } break; case image_skewed: ; } update_strip(penum); if (x_used) { /* * Processing was interrupted by an error. Skip over pixels * already processed. */ dda_advance(penum->dda.pixel0.x, x_used); dda_advance(penum->dda.pixel0.y, x_used); penum->used.x = 0; } if_debug2('b', "[b]pixel0 x=%g, y=%g\n", fixed2float(dda_current(penum->dda.pixel0.x)), fixed2float(dda_current(penum->dda.pixel0.y))); code = (*penum->render)(penum, buffer, sourcex + x_used, width_spp - x_used * penum->spp, 1, dev); if (code < 0) { /* Error or interrupt, restore original state. */ penum->used.x += x_used; if (!penum->used.y) { dda_previous(penum->dda.row.x); dda_previous(penum->dda.row.y); dda_translate(penum->dda.strip.x, penum->prev.x - penum->cur.x); dda_translate(penum->dda.strip.y, penum->prev.y - penum->cur.y); } goto out; } penum->prev = penum->cur; mt:; } if (penum->y < penum->rect.h) { code = 0; } else { /* End of input data. Render any left-over buffered data. */ code = gx_image1_flush(info); if (code >= 0) code = 1; } out: /* Note that caller must call end_image */ /* for both error and normal termination. */ *rows_used = penum->y - y; return code; }