Пример #1
0
/*
 * Convert a CIEBasedDEF color into device color.
 */
static int
client_remap_CIEBasedDEF(client_custom_color_params_t * pparams,
    const gs_client_color * pc, const gs_color_space * pcs,
    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
    gs_color_select_t select)
{
    demo_color_space_data_t * pdata =
	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
    frac rgb[3];
    int i;

    /*** Demonstrate method to convert to XYZ ***/
    if (pdata->CIEtoXYZ_pis) {
	frac xyz[3];

	cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
	/* We don't really do anything with these values, but this */
	/* is where a real client could convert to a device color  */
	if_debug6('|', "[c]client_remap CIEDEF [%g, %g, %g] -> XYZ [%g, %g, %g]\n",
		  pc->paint.values[0], pc->paint.values[1], pc->paint.values[2],
		  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
    }
    /*
     * For demo and debug purposes, make our colors a function of the
     * intensity of the given color value and the object type.  The color
     * values could represent almost anything.  However we are assuming
     * that they are RGB values.
     */
    for (i = 0; i < 3; i++)
	rgb[i] = convert2frac(pc->paint.values[i],
		       	pcs->params.def->RangeDEF.ranges[i]);
    return client_remap_DeviceRGB(pparams, rgb, pcs, pdc, pis, dev, select);
}
Пример #2
0
static void
debug_b_print_matrix(const gs_pixel_image_t *pim)
{
    if_debug6('b', "      ImageMatrix=[%g %g %g %g %g %g]\n",
	      pim->ImageMatrix.xx, pim->ImageMatrix.xy,
	      pim->ImageMatrix.yx, pim->ImageMatrix.yy,
	      pim->ImageMatrix.tx, pim->ImageMatrix.ty);
}
Пример #3
0
/*
 * Convert a ICCBased color into device color.
 */
static int
client_remap_ICCBased(client_custom_color_params_t * pparams,
    const gs_client_color * pc, const gs_color_space * pcs,
    gx_device_color * pdc, const gs_imager_state * pis, gx_device * dev,
    gs_color_select_t select)
{
    demo_color_space_data_t * pdata =
	(demo_color_space_data_t *)(pcs->pclient_color_space_data);
    frac frac_color[GS_CLIENT_COLOR_MAX_COMPONENTS];
    int i, num_values = pcs->params.icc.picc_info->num_components;

    /*** Demonstrate method to convert to XYZ ***/
    if (pdata->CIEtoXYZ_pis) {

		frac xyz[3];

		cs_concretize_color(pc, pcs, xyz, pdata->CIEtoXYZ_pis);
		/* We don't really do anything with these values, but this */
		/* is where a real client could convert to a device color  */
		if_debug6('|', "[c]client_remap ICCBased [%g, %g, %g] -> XYZ [%g, %g, %g]\n",
			  pc->paint.values[0], pc->paint.values[1], pc->paint.values[2],
			  frac2float(xyz[0]), frac2float(xyz[1]), frac2float(xyz[2]));
    }

    /*
     * For demo and debug purposes, make our colors a function of the
     * intensity of the given color value and the object type.  The color
     * values could represent almost anything.  However based upon the
     * number of color values, we are assuming that they are either
     * gray, RGB, or CMYK values.
     */
    for (i = 0; i < num_values; i++)
	frac_color[i] = convert2frac(pc->paint.values[i],
		       	pcs->params.icc.picc_info->Range.ranges[i]);
    switch (num_values) {
	case 0:
	case 2:
	    return_error(gs_error_rangecheck);
	case 1:
	    return client_remap_DeviceGray(pparams, frac_color, pcs,
			   		 pdc, pis, dev, select);
	case 3:
	    return client_remap_DeviceRGB(pparams, frac_color, pcs,
			   		 pdc, pis, dev, select);
	case 4:
	default:
	    return client_remap_DeviceCMYK(pparams, frac_color, pcs,
			   		 pdc, pis, dev, select);
    }
}
Пример #4
0
static int
tag_dispatch_90X1(px_args_t * par, px_state_t * pxs)
{
    px_vendor_state_t *v_state = pxs->vendor_state;
    int code = 0;

    for (;;) {
	uint32_t old_avail = par->source.available;

	switch (v_state->tag.tag_id) {
	    case 0x9031:
		code =
		    read_mode10_bitmap_data(&(v_state->row), par, pxs, true);
		break;
	    case 0x9011:
		code =
		    read_mode10_bitmap_data(&(v_state->row), par, pxs, false);
		break;
	    case 0x9021:
		code =
		    read_headless_jpeg_bitmap_data(&(v_state->row), par, pxs);
		break;
	}
	v_state->tag.bytes_so_far += old_avail - par->source.available;
	if_debug6('I',
		  "new src.p %lu old.avail %u new.avail %u bytes=%d/%d code %d\n",
		  par->source.position, old_avail, par->source.available,
		  v_state->tag.bytes_so_far, v_state->tag.bytes_expected,
		  code);
	if (code < 0)
	    return_error(errorIllegalDataValue);
	if ((code == pxNeedData)
	    && (v_state->tag.bytes_so_far >= v_state->tag.bytes_expected))
	    return_error(errorIllegalDataValue);	/* 3550's behavior */
	if (code != 1)		/* = 0 */
	    return code;

	code =
	    pl_image_data(pxs->pgs, v_state->info,
			  (const byte **)&(v_state->row), 0,
			  v_state->data_per_row, 1);
	if (code < 0)
	    return code;
	pxs->have_page = true;
    }
    /* unreachable */
    return code;
}
Пример #5
0
/*
 * This is somewhat a clone of the tile_by_steps function but one
 * that performs filling from and to pdf14dev (transparency) buffers.
 * At some point it may be desirable to do some optimization here.
 */
static int
tile_by_steps_trans(tile_fill_trans_state_t * ptfs, int x0, int y0, int w0, int h0,
              gx_pattern_trans_t *fill_trans_buffer, const gx_color_tile * ptile)
{
    int x1 = x0 + w0, y1 = y0 + h0;
    int i0, i1, j0, j1, i, j;
    gs_matrix step_matrix;      /* translated by phase */
    gx_pattern_trans_t *ptrans_pat = ptile->ttrans;

    ptfs->x0 = x0, ptfs->w0 = w0;
    ptfs->y0 = y0, ptfs->h0 = h0;
    step_matrix = ptile->step_matrix;
    step_matrix.tx -= ptfs->phase.x;
    step_matrix.ty -= ptfs->phase.y;
    {
        gs_rect bbox;           /* bounding box in device space */
        gs_rect ibbox;          /* bounding box in stepping space */
        double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
        double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
        double u0, v0, u1, v1;

        bbox.p.x = x0, bbox.p.y = y0;
        bbox.q.x = x1, bbox.q.y = y1;
        gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox);
        if_debug10('T',
          "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n",
                   x0, y0, w0, h0,
                   ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
                   step_matrix.tx, step_matrix.ty);
        /*
         * If the pattern is partly transparent and XStep/YStep is smaller
         * than the device space BBox, we need to ensure that we cover
         * each pixel of the rectangle being filled with *every* pattern
         * that overlaps it, not just *some* pattern copy.
         */
        u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001;
        v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001;
        u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001;
        v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001;
        if (!ptile->is_simple)
            u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh;
        i0 = (int)fastfloor(u0);
        j0 = (int)fastfloor(v0);
        i1 = (int)ceil(u1);
        j1 = (int)ceil(v1);
    }
    if_debug4('T', "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
    for (i = i0; i < i1; i++)
        for (j = j0; j < j1; j++) {
            int x = (int)fastfloor(step_matrix.xx * i +
                          step_matrix.yx * j + step_matrix.tx);
            int y = (int)fastfloor(step_matrix.xy * i +
                          step_matrix.yy * j + step_matrix.ty);
            int w = ptrans_pat->width;
            int h = ptrans_pat->height;
            int xoff, yoff;
            int px, py;

            if_debug4('T', "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y);
            if (x < x0)
                xoff = x0 - x, x = x0, w -= xoff;
            else
                xoff = 0;
            if (y < y0)
                yoff = y0 - y, y = y0, h -= yoff;
            else
                yoff = 0;
            if (x + w > x1)
                w = x1 - x;
            if (y + h > y1)
                h = y1 - y;
            if_debug6('T', "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
                      x, y, w, h, xoff, yoff);
            if (w > 0 && h > 0) {

                px = imod(xoff - x, ptile->ttrans->width);
                py = imod(yoff - y, ptile->ttrans->height);

                /* Set the offsets for colored pattern fills */
                ptfs->xoff = xoff;
                ptfs->yoff = yoff;

                /* We only go through blending during tiling, if
                   there was overlap as defined by the step matrix
                   and the bounding box */

                ptile->ttrans->pat_trans_fill(x, y, x+w, y+h, px, py, ptile,
                        fill_trans_buffer);
            }
        }
    return 0;
}
Пример #6
0
/*
 * Fill with non-standard X and Y stepping.
 * ptile is pdevc->colors.pattern.{m,p}_tile.
 * tbits_or_tmask is whichever of tbits and tmask is supplying
 * the tile size.
 * This implementation could be sped up considerably!
 */
static int
tile_by_steps(tile_fill_state_t * ptfs, int x0, int y0, int w0, int h0,
              const gx_color_tile * ptile,
              const gx_strip_bitmap * tbits_or_tmask,
              int (*fill_proc) (const tile_fill_state_t * ptfs,
                                int x, int y, int w, int h))
{
    int x1 = x0 + w0, y1 = y0 + h0;
    int i0, i1, j0, j1, i, j;
    gs_matrix step_matrix;      /* translated by phase */
    int code;

    ptfs->x0 = x0, ptfs->w0 = w0;
    ptfs->y0 = y0, ptfs->h0 = h0;
    step_matrix = ptile->step_matrix;
    step_matrix.tx -= ptfs->phase.x;
    step_matrix.ty -= ptfs->phase.y;
    {
        gs_rect bbox;           /* bounding box in device space */
        gs_rect ibbox;          /* bounding box in stepping space */
        double bbw = ptile->bbox.q.x - ptile->bbox.p.x;
        double bbh = ptile->bbox.q.y - ptile->bbox.p.y;
        double u0, v0, u1, v1;

        bbox.p.x = x0, bbox.p.y = y0;
        bbox.q.x = x1, bbox.q.y = y1;
        gs_bbox_transform_inverse(&bbox, &step_matrix, &ibbox);
        if_debug10('T',
          "[T]x,y=(%d,%d) w,h=(%d,%d) => (%g,%g),(%g,%g), offset=(%g,%g)\n",
                   x0, y0, w0, h0,
                   ibbox.p.x, ibbox.p.y, ibbox.q.x, ibbox.q.y,
                   step_matrix.tx, step_matrix.ty);
        /*
         * If the pattern is partly transparent and XStep/YStep is smaller
         * than the device space BBox, we need to ensure that we cover
         * each pixel of the rectangle being filled with *every* pattern
         * that overlaps it, not just *some* pattern copy.
         */
        u0 = ibbox.p.x - max(ptile->bbox.p.x, 0) - 0.000001;
        v0 = ibbox.p.y - max(ptile->bbox.p.y, 0) - 0.000001;
        u1 = ibbox.q.x - min(ptile->bbox.q.x, 0) + 0.000001;
        v1 = ibbox.q.y - min(ptile->bbox.q.y, 0) + 0.000001;
        if (!ptile->is_simple)
            u0 -= bbw, v0 -= bbh, u1 += bbw, v1 += bbh;
        i0 = (int)fastfloor(u0);
        j0 = (int)fastfloor(v0);
        i1 = (int)ceil(u1);
        j1 = (int)ceil(v1);
    }
    if_debug4('T', "[T]i=(%d,%d) j=(%d,%d)\n", i0, i1, j0, j1);
    for (i = i0; i < i1; i++)
        for (j = j0; j < j1; j++) {
            int x = (int)fastfloor(step_matrix.xx * i +
                          step_matrix.yx * j + step_matrix.tx);
            int y = (int)fastfloor(step_matrix.xy * i +
                          step_matrix.yy * j + step_matrix.ty);
            int w = tbits_or_tmask->size.x;
            int h = tbits_or_tmask->size.y;
            int xoff, yoff;

            if_debug4('T', "[T]i=%d j=%d x,y=(%d,%d)", i, j, x, y);
            if (x < x0)
                xoff = x0 - x, x = x0, w -= xoff;
            else
                xoff = 0;
            if (y < y0)
                yoff = y0 - y, y = y0, h -= yoff;
            else
                yoff = 0;
            if (x + w > x1)
                w = x1 - x;
            if (y + h > y1)
                h = y1 - y;
            if_debug6('T', "=>(%d,%d) w,h=(%d,%d) x/yoff=(%d,%d)\n",
                      x, y, w, h, xoff, yoff);
            if (w > 0 && h > 0) {
                if (ptfs->pcdev == (gx_device *) & ptfs->cdev)
                    tile_clip_set_phase(&ptfs->cdev,
                                imod(xoff - x, ptfs->tmask->rep_width),
                                imod(yoff - y, ptfs->tmask->rep_height));
                /* Set the offsets for colored pattern fills */
                ptfs->xoff = xoff;
                ptfs->yoff = yoff;
                code = (*fill_proc) (ptfs, x, y, w, h);
                if (code < 0)
                    return code;
            }
        }
    return 0;
}
Пример #7
0
void eprn_get_initial_matrix(gx_device *device, gs_matrix *mptr)
{
  eprn_Device *dev = (eprn_Device *)device;
  float
    /*  The following two arrays are oriented w.r.t. pixmap device space, i.e.,
        the index 0 refers to the x coordinate (horizontal) and the index 1 to
        the y coordinate (vertical) in pixmap device space. */
    extension[2],       /* media extension in pixels */
    pixels_per_bp[2];   /* resolution */
  int
    j,
    quarters;

#ifdef EPRN_TRACE
  if_debug0(EPRN_TRACE_CHAR, "! eprn_get_initial_matrix()...\n");
#endif

  /* We need 'default_orientation' and also the margins. */
  if (dev->eprn.code == ms_none) {
#ifdef EPRN_TRACE
    if_debug0(EPRN_TRACE_CHAR,
      "! eprn_get_initial_matrix(): code is still ms_none.\n");
#endif
    if (eprn_set_page_layout(dev) != 0)
      eprintf("  Processing can't be stopped at this point although this error "
        "occurred.\n");
      /* The current function has a signature without the ability to signal
         an error condition. */
  }

  quarters = dev->eprn.default_orientation +
    (dev->MediaSize[0] <= dev->MediaSize[1]? 0: 1);
     /* Number of quarter-circle rotations by +90 degrees necessary to obtain
        default user space starting with the y axis upwards in pixmap device
        space.
        It's not documented, but 'MediaSize' is the requested "PageSize" page
        device parameter value and hence is to be interpreted in default (not
        default default!) user space. The condition above therefore tests
        whether landscape orientation has been requested.
      */

  /* Soft tumble option: rotate default user space by 180 degrees on every
     second page */
  if (dev->eprn.soft_tumble && dev->ShowpageCount % 2 != 0) quarters += 2;

  /* Prepare auxiliary data */
  for (j = 0; j < 2; j++) pixels_per_bp[j] = dev->HWResolution[j]/BP_PER_IN;
  /*  'HWResolution[]' contains the standard PostScript page device parameter
      'HWResolution' which is defined in pixels per inch with respect to
       device space. */
  if (quarters % 2 == 0) {
    /* Default user space and pixmap device space agree in what is "horizontal"
       and what is "vertical". */
    extension[0] = dev->MediaSize[0];
    extension[1] = dev->MediaSize[1];
  }
  else {
    extension[0] = dev->MediaSize[1];
    extension[1] = dev->MediaSize[0];
  }
  /* Convert from bp to pixels: */
  for (j = 0; j < 2; j++) extension[j] *= pixels_per_bp[j];
   /* Note that we are using the user-specified extension of the sheet, not the
      "official" one we could obtain in most cases from 'size'. */

  switch (quarters % 4) {
  case 0:
    /*  The y axis of default user space points upwards in pixmap device space.
        The CTM is uniquely characterized by the following mappings from
        default user space to pixmap device space:
          (0, 0)                -> (0, height in pixels)
          (width in bp, 0)      -> (width in pixels, height in pixels)
          (0, height in bp)     -> (0, 0)
        'width' and 'height' refer to the sheet's extension as seen from pixmap
        device space, i.e., width in pixels == extension[0] and
        height in pixels == extension[1].

        From the PLR we find that the CTM is a PostScript matrix
        [a b c d tx ty] used for mapping user space coordinates (x, y) to
        device space coordinates (x', y') as follows:
          x' = a*x + c*y + tx
          y' = b*x + d*y + ty
        Ghostscript's matrix type 'gs_matrix' writes its structure components
        'xx' etc. in storage layout order into a PostScript matrix (see
        write_matrix() in iutil.c), hence we obtain by comparison with
        gsmatrix.h the PostScript matrix [ xx xy yx yy tx ty ].
        The correspondence can also be seen by comparison of the equations
        above with the code in gs_point_transform() in gsmatrix.c.
        It would, however, still be reassuring to have a corresponding
        statement in ghostscript's documentation.
    */
    gx_default_get_initial_matrix(device, mptr);
    /*  Of course, I could also set this directly:
          mptr->xx = pixels_per_bp[0];
          mptr->xy = 0;
          mptr->yx = 0;
          mptr->yy = -pixels_per_bp[1];
          mptr->tx = 0;
          mptr->ty = extension[1];
        Doing it in this way is, however, more stable against dramatic changes
        in ghostscript.
    */
    break;
  case 1:
    /*  The y axis of default user space points to the left in pixmap device
        space. The CTM is uniquely characterized by the following mappings from
        default user space to pixmap device space:
          (0, 0)                -> (width in pixels, height in pixels)
          (height in bp, 0)     -> (width in pixels, 0)
          (0, width in bp)      -> (0, height in pixels)
    */
    mptr->xx = 0;
    mptr->xy = -pixels_per_bp[1];
    mptr->yx = -pixels_per_bp[0];
    mptr->yy = 0;
    mptr->tx = extension[0];
    mptr->ty = extension[1];
    break;
  case 2:
    /*  The y axis of default user space points downwards in pixmap device
        space. The CTM is uniquely characterized by the following mappings from
        default user space to pixmap device space:
          (0, 0)                -> (width in pixels, 0)
          (width in bp, 0)      -> (0, 0)
          (0, height in bp)     -> (width in pixels, height in pixels)
    */
    mptr->xx = -pixels_per_bp[0];
    mptr->xy = 0;
    mptr->yx = 0;
    mptr->yy = pixels_per_bp[1];
    mptr->tx = extension[0];
    mptr->ty = 0;
    break;
  case 3:
    /*  The y axis of default user space points to the right in pixmap device
        space. The CTM is uniquely characterized by the following mappings from
        default user space to pixmap device space:
          (0, 0)                -> (0, 0)
          (height in bp, 0)     -> (0, height in pixels)
          (0, width in bp)      -> (width in pixels, 0)
    */
    mptr->xx = 0;
    mptr->xy = pixels_per_bp[1];
    mptr->yx = pixels_per_bp[0];
    mptr->yy = 0;
    mptr->tx = 0;
    mptr->ty = 0;
    break;
  }

  /*  Finally, shift the device space origin to the top-left corner of the
      printable area. I am deliberately not using the corresponding shift
      feature in gx_device_set_margins() because it achieves its effect by
      using the 'Margins' array which should remain at the user's disposal for
      correcting misadjustments. In addition, gx_device_set_margins() will not
      work correctly for quarters % 4 != 0 anyway.
  */
  {
    gs_matrix translation;

    /*  Translation of pixmap device space origin by top and left margins in
        pixmap device space */
    gs_make_translation(
      -dev->eprn.right_shift*pixels_per_bp[0],
      -dev->eprn.down_shift *pixels_per_bp[1],
      &translation);

    /* Multiply the initial matrix from the right with the translation matrix,
       i.e., in going from user to device space the translation will be applied
       last. */
    gs_matrix_multiply(mptr, &translation, mptr);
  }

#ifdef EPRN_TRACE
  if_debug6(EPRN_TRACE_CHAR, "  Returning [%g %g %g %g %g %g].\n",
    mptr->xx, mptr->xy, mptr->yx, mptr->yy, mptr->tx, mptr->ty);
#endif
  return;
}
Пример #8
0
/* this procedure is exported for the benefit of gsicc.c */
int
gx_cie_real_remap_finish(cie_cached_vector3 vec3, frac * pconc,
                         const gs_imager_state * pis,
                         const gs_color_space *pcs)
{
    const gs_cie_render *pcrd = pis->cie_render;
    const gx_cie_joint_caches *pjc = pis->cie_joint_caches;
    const gs_const_string *table = pcrd->RenderTable.lookup.table;
    int tabc[3];		/* indices for final EncodeABC lookup */

    /* Apply DecodeLMN, MatrixLMN(decode), and MatrixPQR. */
    if (!pjc->skipDecodeLMN)
        cie_lookup_map3(&vec3 /* LMN => PQR */, &pjc->DecodeLMN,
                        "Decode/MatrixLMN+MatrixPQR");

    /* Apply TransformPQR, MatrixPQR', and MatrixLMN(encode). */
    if (!pjc->skipPQR)
        cie_lookup_map3(&vec3 /* PQR => LMN */, &pjc->TransformPQR,
                        "Transform/Matrix'PQR+MatrixLMN");

    /* Apply EncodeLMN and MatrixABC(encode). */
    if (!pjc->skipEncodeLMN)
        cie_lookup_map3(&vec3 /* LMN => ABC */, &pcrd->caches.EncodeLMN,
                        "EncodeLMN+MatrixABC");

    /* MatrixABCEncode includes the scaling of the EncodeABC */
    /* cache index. */
#define SET_TABC(i, t)\
  BEGIN\
    tabc[i] = cie_cached2int(vec3 /*ABC*/.t - pcrd->EncodeABC_base[i],\
                             _cie_interpolate_bits);\
    if ((uint)tabc[i] > (gx_cie_cache_size - 1) << _cie_interpolate_bits)\
        tabc[i] = (tabc[i] < 0 ? 0 :\
                   (gx_cie_cache_size - 1) << _cie_interpolate_bits);\
  END
    SET_TABC(0, u);
    SET_TABC(1, v);
    SET_TABC(2, w);
#undef SET_TABC
    if (table == 0) {
        /*
         * No further transformation.
         * The final mapping step includes both restriction to
         * the range [0..1] and conversion to fracs.
         */
#define EABC(i)\
  cie_interpolate_fracs(pcrd->caches.EncodeABC[i].fixeds.fracs.values, tabc[i])
        pconc[0] = EABC(0);
        pconc[1] = EABC(1);
        pconc[2] = EABC(2);
#undef EABC
        return 3;
    } else {
        /*
         * Use the RenderTable.
         */
        int m = pcrd->RenderTable.lookup.m;

#define RT_LOOKUP(j, i) pcrd->caches.RenderTableT[j].fracs.values[i]
#ifdef CIE_RENDER_TABLE_INTERPOLATE

        /*
         * The final mapping step includes restriction to the
         * ranges [0..dims[c]] as ints with interpolation bits.
         */
        fixed rfix[3];
        const int s = _fixed_shift - _cie_interpolate_bits;

#define EABC(i)\
  cie_interpolate_fracs(pcrd->caches.EncodeABC[i].fixeds.ints.values, tabc[i])
#define FABC(i, s)\
  ((s) > 0) ? (EABC(i) << (s)) : (EABC(i) >> -(s))
        rfix[0] = FABC(0, s);
        rfix[1] = FABC(1, s);
        rfix[2] = FABC(2, s);
#undef FABC
#undef EABC
        if_debug6('c', "[c]ABC=%g,%g,%g => iabc=%g,%g,%g\n",
                  cie_cached2float(vec3.u), cie_cached2float(vec3.v),
                  cie_cached2float(vec3.w), fixed2float(rfix[0]),
                  fixed2float(rfix[1]), fixed2float(rfix[2]));
        gx_color_interpolate_linear(rfix, &pcrd->RenderTable.lookup,
                                    pconc);
        if_debug3('c', "[c]  interpolated => %g,%g,%g\n",
                  frac2float(pconc[0]), frac2float(pconc[1]),
                  frac2float(pconc[2]));
        if (!pcrd->caches.RenderTableT_is_identity) {
            /* Map the interpolated values. */
#define frac2cache_index(v) frac2bits(v, gx_cie_log2_cache_size)
            pconc[0] = RT_LOOKUP(0, frac2cache_index(pconc[0]));
            pconc[1] = RT_LOOKUP(1, frac2cache_index(pconc[1]));
            pconc[2] = RT_LOOKUP(2, frac2cache_index(pconc[2]));
            if (m > 3)
                pconc[3] = RT_LOOKUP(3, frac2cache_index(pconc[3]));
#undef frac2cache_index
        }

#else /* !CIE_RENDER_TABLE_INTERPOLATE */

        /*
         * The final mapping step includes restriction to the ranges
         * [0..dims[c]], plus scaling of the indices in the strings.
         */
#define RI(i)\
  pcrd->caches.EncodeABC[i].ints.values[tabc[i] >> _cie_interpolate_bits]
        int ia = RI(0);
        int ib = RI(1);		/* pre-multiplied by m * NC */
        int ic = RI(2);		/* pre-multiplied by m */
        const byte *prtc = table[ia].data + ib + ic;

        /* (*pcrd->RenderTable.T)(prtc, m, pcrd, pconc); */

        if_debug6('c', "[c]ABC=%g,%g,%g => iabc=%d,%d,%d\n",
                  cie_cached2float(vec3.u), cie_cached2float(vec3.v),
                  cie_cached2float(vec3.w), ia, ib, ic);
        if (pcrd->caches.RenderTableT_is_identity) {
            pconc[0] = byte2frac(prtc[0]);
            pconc[1] = byte2frac(prtc[1]);
            pconc[2] = byte2frac(prtc[2]);
            if (m > 3)
                pconc[3] = byte2frac(prtc[3]);
        } else {
#if gx_cie_log2_cache_size == 8
#  define byte2cache_index(b) (b)
#else
# if gx_cie_log2_cache_size > 8
#  define byte2cache_index(b)\
    ( ((b) << (gx_cie_log2_cache_size - 8)) +\
      ((b) >> (16 - gx_cie_log2_cache_size)) )
# else				/* < 8 */
#  define byte2cache_index(b) ((b) >> (8 - gx_cie_log2_cache_size))
# endif
#endif
            pconc[0] = RT_LOOKUP(0, byte2cache_index(prtc[0]));
            pconc[1] = RT_LOOKUP(1, byte2cache_index(prtc[1]));
            pconc[2] = RT_LOOKUP(2, byte2cache_index(prtc[2]));
            if (m > 3)
                pconc[3] = RT_LOOKUP(3, byte2cache_index(prtc[3]));
#undef byte2cache_index
        }

#endif /* !CIE_RENDER_TABLE_INTERPOLATE */
#undef RI
#undef RT_LOOKUP
        return m;
    }
}
Пример #9
0
/* Process a buffer */
#define LINE_LIMIT 79		/* not 80, to satisfy Genoa FTS */
static int
s_A85E_process(stream_state * st, stream_cursor_read * pr,
	       stream_cursor_write * pw, bool last)
{
    stream_A85E_state *const ss = (stream_A85E_state *) st;
    register const byte *p = pr->ptr;
    register byte *q = pw->ptr;
    byte *qn = q + (LINE_LIMIT - ss->count); /* value of q before next EOL */
    const byte *rlimit = pr->limit;
    byte *wlimit = pw->limit;
    int status = 0;
    int prev = ss->last_char;
    int count;

    if_debug3('w', "[w85]initial ss->count = %d, rcount = %d, wcount = %d\n",
	      ss->count, (int)(rlimit - p), (int)(wlimit - q));
    for (; (count = rlimit - p) >= 4; p += 4) {
	ulong word =
	    ((ulong) (((uint) p[1] << 8) + p[2]) << 16) +
	    (((uint) p[3] << 8) + p[4]);

	if (word == 0) {
	    if (q >= qn) {
		if (wlimit - q < 2) {
		    status = 1;
		    break;
		}
		*++q = prev = '\n';
		qn = q + LINE_LIMIT;
		if_debug1('w', "[w85]EOL at %d bytes written\n",
			  (int)(q - pw->ptr));
	    } else {
		if (q >= wlimit) {
		    status = 1;
		    break;
		}
	    }
	    *++q = prev = 'z';
	} else {
	    ulong v4 = word / 85;	/* max 85^4 */
	    ulong v3 = v4 / 85;	/* max 85^3 */
	    uint v2 = v3 / 85;	/* max 85^2 */
	    uint v1 = v2 / 85;	/* max 85 */

put:	    if (q + 5 > qn) {
		if (q >= wlimit) {
		    status = 1;
		    break;
		}
		*++q = prev = '\n';
		qn = q + LINE_LIMIT;
		if_debug1('w', "[w85]EOL at %d bytes written\n",
			  (int)(q - pw->ptr));
		goto put;
	    }
	    if (wlimit - q < 5) {
		status = 1;
		break;
	    }
	    q[1] = (byte) v1 + '!';
	    q[2] = (byte) (v2 - v1 * 85) + '!';
	    q[3] = (byte) ((uint) v3 - v2 * 85) + '!';
	    q[4] = (byte) ((uint) v4 - (uint) v3 * 85) + '!';
	    q[5] = (byte) ((uint) word - (uint) v4 * 85) + '!';
	    /*
	     * '%%' or '%!' at the beginning of the line will confuse some
	     * document managers: insert (an) EOL(s) if necessary to prevent
	     * this.
	     */
	    if (q[1] == '%') {
		if (prev == '%') {
		    if (qn - q == LINE_LIMIT - 1) {
			/* A line would begin with %%. */
			*++q = prev = '\n';
			qn = q + LINE_LIMIT;
			if_debug1('w',
				  "[w85]EOL for %%%% at %d bytes written\n",
				  (int)(q - pw->ptr));
			goto put;
		    }
		} else if (prev == '\n' && (q[2] == '%' || q[2] == '!')) {
		    /*
		     * We may have to insert more than one EOL if
		     * there are more than two %s in a row.
		     */
		    int extra =
			(q[2] == '!' ? 1 : /* else q[2] == '%' */
			 q[3] == '!' ? 2 :
			 q[3] != '%' ? 1 :
			 q[4] == '!' ? 3 :
			 q[4] != '%' ? 2 :
			 q[5] == '!' ? 4 :
			 q[5] != '%' ? 3 : 4);

		    if (wlimit - q < 5 + extra) {
			status = 1;
			break;
		    }
		    if_debug6('w', "[w]%c%c%c%c%c extra = %d\n",
			      q[1], q[2], q[3], q[4], q[5], extra);
		    switch (extra) {
			case 4:
			    q[9] = q[5], q[8] = '\n';
			    goto e3;
			case 3:
			    q[8] = q[5];
			  e3:q[7] = q[4], q[6] = '\n';
			    goto e2;
			case 2:
			    q[7] = q[5], q[6] = q[4];
			  e2:q[5] = q[3], q[4] = '\n';
			    goto e1;
			case 1:
			    q[6] = q[5], q[5] = q[4], q[4] = q[3];
			  e1:q[3] = q[2], q[2] = '\n';
		    }
		    if_debug1('w', "[w85]EOL at %d bytes written\n",
			      (int)(q + 2 * extra - pw->ptr));
		    qn = q + 2 * extra + LINE_LIMIT;
		    q += extra;
		}
	    } else if (q[1] == '!' && prev == '%' &&
		       qn - q == LINE_LIMIT - 1
		       ) {
		/* A line would begin with %!. */
		*++q = prev = '\n';
		qn = q + LINE_LIMIT;
		if_debug1('w', "[w85]EOL for %%! at %d bytes written\n",
			  (int)(q - pw->ptr));
		goto put;
	    }
	    prev = *(q += 5);
	}
    }
 end:
    ss->count = LINE_LIMIT - (qn - q);
    /* Check for final partial word. */
    if (last && status == 0 && count < 4) {
	char buf[5];
        int nchars = (count == 0 ? 2 : count + 3);
	ulong word = 0;
	ulong divisor = 85L * 85 * 85 * 85;
        int i, space;

	switch (count) {
	    case 3:
		word += (uint) p[3] << 8;
	    case 2:
		word += (ulong) p[2] << 16;
	    case 1:
		word += (ulong) p[1] << 24;
                for(i=0; i <= count; i++) {
		    ulong v = word / divisor;  /* actually only a byte */

		    buf[i] = (byte) v + '!';
		    word -= v * divisor;
		    divisor /= 85;
		}
		/*case 0: */
	}
        space = count && buf[0] == '%' && 
          ( (prev == '\n' && ( buf[1] == '%' || buf[1] =='!')) ||
            (prev == '%'  && qn - q == LINE_LIMIT - 1)
          );   
        if (wlimit - q < nchars+space)
	    status = 1;
	else if (q + nchars+space > qn) {
	    *++q = prev = '\n';
	    qn = q + LINE_LIMIT;
	    goto end;
	} else {
            if (count) {
                if (space)
  	          *++q = ' ';
                memcpy(q+1, buf, count+1);
                q += count+1;
	        p += count;
            }
            *++q = '~';
            *++q = '>';
        }
    }
    if_debug3('w', "[w85]final ss->count = %d, %d bytes read, %d written\n",
	      ss->count, (int)(p - pr->ptr), (int)(q - pw->ptr));
    pr->ptr = p;
    if (q > pw->ptr)
	ss->last_char = *q;
    pw->ptr = q;
    return status;
}