Пример #1
0
/* Fill a rectangle with a color. */
static int
x_fill_rectangle(gx_device * dev,
                 int x, int y, int w, int h, gx_color_index gscolor)
{
    gx_device_X *xdev = (gx_device_X *) dev;
    unsigned long color = (unsigned long) gscolor;

    fit_fill(dev, x, y, w, h);
    flush_text(xdev);
    X_SET_FILL_STYLE(xdev, FillSolid);
    X_SET_FORE_COLOR(xdev, color);
    X_SET_FUNCTION(xdev, GXcopy);
    XFillRectangle(xdev->dpy, xdev->dest, xdev->gc, x, y, w, h);
    /* If we are filling the entire screen, reset */
    /* colors_or and colors_and.  It's wasteful to test this */
    /* on every operation, but there's no separate driver routine */
    /* for erasepage (yet). */
    if (x == 0 && y == 0 && w == xdev->width && h == xdev->height) {
        if (color == xdev->foreground || color == xdev->background)
            gdev_x_free_dynamic_colors(xdev);
        xdev->colors_or = xdev->colors_and = color;
    }
    if (xdev->bpixmap != (Pixmap) 0) {
        x_update_add(xdev, x, y, w, h);
    }
    if_debug5('F', "[F] fill (%d,%d):(%d,%d) %ld\n",
              x, y, w, h, (long)color);
    return 0;
}
Пример #2
0
static void
cie_lookup_map3(cie_cached_vector3 * pvec,
                const gx_cie_vector_cache3_t * pc, const char *cname)
{
    if_debug5('c', "[c]lookup %s 0x%lx [%g %g %g]\n",
              (const char *)cname, (ulong) pc,
              cie_cached2float(pvec->u), cie_cached2float(pvec->v),
              cie_cached2float(pvec->w));
    cie_lookup_mult3(pvec, pc);
    if_debug3('c', "        =[%g %g %g]\n",
              cie_cached2float(pvec->u), cie_cached2float(pvec->v),
              cie_cached2float(pvec->w));
}
Пример #3
0
/* Tracing printout */
static void
print_save(const char *str, uint spacen, const alloc_save_t *sav)
{
  if_debug5('u', "[u]%s space %u 0x%lx: cdata = 0x%lx, id = %lu\n",\
            str, spacen, (ulong)sav, (ulong)sav->client_data, (ulong)sav->id);
}
Пример #4
0
int
gs_image_next_planes(gs_image_enum * penum,
		     gs_const_string *plane_data /*[num_planes]*/,
		     uint *used /*[num_planes]*/)
{
    const int num_planes = penum->num_planes;
    int i;
    int code = 0;

#ifdef DEBUG
    vd_get_dc('i');
    vd_set_shift(0, 0);
    vd_set_scale(0.01);
    vd_set_origin(0, 0);
    if (gs_debug_c('b')) {
	int pi;

	for (pi = 0; pi < num_planes; ++pi)
	    dprintf6("[b]plane %d source=0x%lx,%u pos=%u data=0x%lx,%u\n",
		     pi, (ulong)penum->planes[pi].source.data,
		     penum->planes[pi].source.size, penum->planes[pi].pos,
		     (ulong)plane_data[pi].data, plane_data[pi].size);
    }
#endif
    for (i = 0; i < num_planes; ++i) {
        used[i] = 0;
	if (penum->wanted[i] && plane_data[i].size != 0) {
	    penum->planes[i].source.size = plane_data[i].size;
	    penum->planes[i].source.data = plane_data[i].data;
	}
    }
    for (;;) {
	/* If wanted can vary, only transfer 1 row at a time. */
	int h = (penum->wanted_varies ? 1 : max_int);

	/* Move partial rows from source[] to row[]. */
	for (i = 0; i < num_planes; ++i) {
	    int pos, size;
	    uint raster;

	    if (!penum->wanted[i])
		continue;	/* skip unwanted planes */
	    pos = penum->planes[i].pos;
	    size = penum->planes[i].source.size;
	    raster = penum->image_planes[i].raster;
	    if (size > 0) {
		if (pos < raster && (pos != 0 || size < raster)) {
		    /* Buffer a partial row. */
		    int copy = min(size, raster - pos);
		    uint old_size = penum->planes[i].row.size;

		    /* Make sure the row buffer is fully allocated. */
		    if (raster > old_size) {
			gs_memory_t *mem = gs_image_row_memory(penum);
			byte *old_data = penum->planes[i].row.data;
			byte *row =
			    (old_data == 0 ?
			     gs_alloc_string(mem, raster,
					     "gs_image_next(row)") :
			     gs_resize_string(mem, old_data, old_size, raster,
					      "gs_image_next(row)"));

			if_debug5('b', "[b]plane %d row (0x%lx,%u) => (0x%lx,%u)\n",
				  i, (ulong)old_data, old_size,
				  (ulong)row, raster);
			if (row == 0) {
			    code = gs_note_error(gs_error_VMerror);
			    free_row_buffers(penum, i, "gs_image_next(row)");
			    break;
			}
			penum->planes[i].row.data = row;
			penum->planes[i].row.size = raster;
		    }
		    memcpy(penum->planes[i].row.data + pos,
			   penum->planes[i].source.data, copy);
		    penum->planes[i].source.data += copy;
		    penum->planes[i].source.size = size -= copy;
		    penum->planes[i].pos = pos += copy;
		    used[i] += copy;
		}
	    }
	    if (h == 0)
		continue;	/* can't transfer any data this cycle */
	    if (pos == raster) {
		/*
		 * This plane will be transferred from the row buffer,
		 * so we can only transfer one row.
		 */
		h = min(h, 1);
		penum->image_planes[i].data = penum->planes[i].row.data;
	    } else if (pos == 0 && size >= raster) {
		/* We can transfer 1 or more planes from the source. */
		h = min(h, size / raster);
		penum->image_planes[i].data = penum->planes[i].source.data;
	    } else
		h = 0;		/* not enough data in this plane */
	}
	if (h == 0 || code != 0)
	    break;
	/* Pass rows to the device. */
	if (penum->dev == 0) {
	    /*
	     * ****** NOTE: THE FOLLOWING IS NOT CORRECT FOR ImageType 3
	     * ****** InterleaveType 2, SINCE MASK HEIGHT AND IMAGE HEIGHT
	     * ****** MAY DIFFER (BY AN INTEGER FACTOR).  ALSO, plane_depths[0]
	     * ****** AND plane_widths[0] ARE NOT UPDATED.
	 */
	    if (penum->y + h < penum->height)
		code = 0;
	    else
		h = penum->height - penum->y, code = 1;
	} else {
	    code = gx_image_plane_data_rows(penum->info, penum->image_planes,
					    h, &h);
	    if_debug2('b', "[b]used %d, code=%d\n", h, code);
	    penum->error = code < 0;
	}
	penum->y += h;
	/* Update positions and sizes. */
	if (h == 0)
	    break;
	for (i = 0; i < num_planes; ++i) {
	    int count;

	    if (!penum->wanted[i])
		continue;
	    count = penum->image_planes[i].raster * h;
	    if (penum->planes[i].pos) {
		/* We transferred the row from the row buffer. */
		penum->planes[i].pos = 0;
	    } else {
		/* We transferred the row(s) from the source. */
		penum->planes[i].source.data += count;
		penum->planes[i].source.size -= count;
		used[i] += count;
	    }
	}
	cache_planes(penum);
	if (code > 0)
	    break;
    }
    /* Return the retained data pointers. */
    for (i = 0; i < num_planes; ++i)
	plane_data[i] = penum->planes[i].source;
    vd_release_dc;
    return code;
}
Пример #5
0
/* the routine sets ph->actual_frequency and ph->actual_angle. */
static int
pick_cell_size(gs_screen_halftone * ph, const gs_matrix * pmat, ulong max_size,
               uint min_levels, bool accurate, gx_ht_cell_params_t * phcp)
{
    const bool landscape = (pmat->xy != 0.0 || pmat->yx != 0.0);

    /* Account for a possibly reflected coordinate system. */
    /* See gxstroke.c for the algorithm. */
    const bool reflected = pmat->xy * pmat->yx > pmat->xx * pmat->yy;
    const int reflection = (reflected ? -1 : 1);
    const int rotation =
    (landscape ? (pmat->yx < 0 ? 90 : -90) : pmat->xx < 0 ? 180 : 0);
    const double f0 = ph->frequency, a0 = ph->angle;
    const double T =
    fabs((landscape ? pmat->yx / pmat->xy : pmat->xx / pmat->yy));
    gs_point uv0;

#define u0 uv0.x
#define v0 uv0.y
    int rt = 1;
    double f = 0, a = 0;
    double e_best = 1000;
    bool better;

    /*
     * We need to find a vector in device space whose length is
     * 1 inch / ph->frequency and whose angle is ph->angle.
     * Because device pixels may not be square, we can't simply
     * map the length to device space and then rotate it;
     * instead, since we know that user space is uniform in X and Y,
     * we calculate the correct angle in user space before rotation.
     */

    /* Compute trial values of u and v. */

    {
        gs_matrix rmat;

        gs_make_rotation(a0 * reflection + rotation, &rmat);
        gs_distance_transform(72.0 / f0, 0.0, &rmat, &uv0);
        gs_distance_transform(u0, v0, pmat, &uv0);
        if_debug10('h', "[h]Requested: f=%g a=%g mat=[%g %g %g %g] max_size=%lu min_levels=%u =>\n     u=%g v=%g\n",
                   ph->frequency, ph->angle,
                   pmat->xx, pmat->xy, pmat->yx, pmat->yy,
                   max_size, min_levels, u0, v0);
    }

    /* Adjust u and v to reasonable values. */

    if (u0 == 0 && v0 == 0)
        return_error(gs_error_rangecheck);
    while ((fabs(u0) + fabs(v0)) * rt < 4)
        ++rt;
  try_size:
    better = false;
    {
        double fm0 = u0 * rt;
        double fn0 = v0 * rt;
        int m0 = (int)floor(u0 * rt + 0.0001);
        int n0 = (int)floor(v0 * rt + 0.0001);
        gx_ht_cell_params_t p;

        p.R = p.R1 = rt;
        for (p.M = m0 + 1; p.M >= m0; p.M--)
            for (p.N = n0 + 1; p.N >= n0; p.N--) {
                long raster, wt, wt_size;
                double fr, ar, ft, at, f_diff, a_diff, f_err, a_err;

                p.M1 = (int)floor(p.M / T + 0.5);
                p.N1 = (int)floor(p.N * T + 0.5);
                gx_compute_cell_values(&p);
                if_debug3('h', "[h]trying m=%d, n=%d, r=%d\n", p.M, p.N, rt);
                wt = p.W;
                if (wt >= max_short)
                    continue;
                /* Check the strip size, not the full tile size, */
                /* against max_size. */
                raster = bitmap_raster(wt);
                if (raster > max_size / p.D || raster > max_long / wt)
                    continue;
                wt_size = raster * wt;

                /* Compute the corresponding values of F and A. */

                if (landscape)
                    ar = atan2(p.M * pmat->xy, p.N * pmat->yx),
                        fr = 72.0 * (p.M == 0 ? pmat->xy / p.N * cos(ar) :
                                     pmat->yx / p.M * sin(ar));
                else
                    ar = atan2(p.N * pmat->xx, p.M * pmat->yy),
                        fr = 72.0 * (p.M == 0 ? pmat->yy / p.N * sin(ar) :
                                     pmat->xx / p.M * cos(ar));
                ft = fabs(fr) * rt;
                /* Normalize the angle to the requested quadrant. */
                at = (ar * radians_to_degrees - rotation) * reflection;
                at -= floor(at / 180.0) * 180.0;
                at += floor(a0 / 180.0) * 180.0;
                f_diff = fabs(ft - f0);
                a_diff = fabs(at - a0);
                f_err = f_diff / fabs(f0);
                /*
                 * We used to compute the percentage difference here:
                 *      a_err = (a0 == 0 ? a_diff : a_diff / fabs(a0));
                 * but using the angle difference makes more sense:
                 */
                a_err = a_diff;

                if_debug5('h', " ==> d=%d, wt=%ld, wt_size=%ld, f=%g, a=%g\n",
                          p.D, wt, bitmap_raster(wt) * wt, ft, at);

                {
                    /*
                     * Compute the error in position between ideal location.
                     * and the current integer location.
                     */

                    double error =
                        (fn0 - p.N) * (fn0 - p.N) + (fm0 - p.M) * (fm0 - p.M);
                    /*
                     * Adjust the error by the length of the vector.  This gives
                     * a slight bias toward larger cell sizzes.
                     */
                    error /= p.N * p.N + p.M * p.M;
                    error = sqrt(error); /* The previous calcs. gave value squared */
                    if (error > e_best)
                        continue;
                    e_best = error;
                }
                *phcp = p;
                f = ft, a = at;
                better = true;
                if_debug3('h', "*** best wt_size=%ld, f_diff=%g, a_diff=%g\n",
                          wt_size, f_diff, a_diff);
                /*
                 * We want a maximum relative frequency error of 1% and a
                 * maximum angle error of 1% (of 90 degrees).
                 */
                if (f_err <= 0.01 && a_err <= 0.9 /*degrees*/)
                    goto done;
            }
    }
    if (phcp->C < min_levels) { /* We don't have enough levels yet.  Keep going. */
        ++rt;
        goto try_size;
    }
    if (better) {               /* If we want accurate screens, continue till we fail. */
        if (accurate) {
            ++rt;
            goto try_size;
        }
    } else {                    /*
                                 * We couldn't find an acceptable M and N.  If R > 1,
                                 * take what we've got; if R = 1, give up.
                                 */
        if (rt == 1)
            return_error(gs_error_rangecheck);
    }

    /* Deliver the results. */
  done:
    if_debug5('h', "[h]Chosen: f=%g a=%g M=%d N=%d R=%d\n",
              f, a, phcp->M, phcp->N, phcp->R);
    ph->actual_frequency = f;
    ph->actual_angle = a;
    return 0;
#undef u0
#undef v0
}
Пример #6
0
/* TODO: consider using source.position and source.count (and possibly also phase) */
static int
read_mode10_bitmap_data(byte ** pdata, px_args_t * par, px_state_t * pxs,
			bool mode9031)
{
    px_vendor_state_t *v_state = pxs->vendor_state;
    mode10_state_t *mode10_state = &v_state->mode10_state;
    uint avail = min(par->source.available,
		     (v_state->tag.bytes_expected -
		      v_state->tag.bytes_so_far));
    const byte *pin = par->source.data;
    byte *pout;
    bool end_of_row = false;
    uint32_t pixel;
    int i;

    update_pout(pout);

    if ((v_state->state == vu_body)
	&& v_state->rowwritten == v_state->BlockHeight) {
	int code = pl_end_image(pxs->pgs, v_state->info, true);

	if (code < 0)
	    return code;

	v_state->state = vu_blank;
	v_state->rowwritten = 0;
	return 0;
    }

    /* initialize at begin of image */
    if (v_state->state == vu_tagged) {
	int code = vu_begin_image(pxs);

	if (code < 0)
	    return code;

	mode10_state->state = next_is_cmd;
	mode10_state->cursor = 0;
	v_state->rowwritten = 0;
	v_state->state = vu_body;
    }

    /* one byte at a time until end of input or end of row */
    while ((avail || mode10_state->state == process_rle)	/* process_rle does not consume */
	   &&(!end_of_row)) {
	switch (mode10_state->state) {
	    case next_is_cmd:{
		    mode10_state->cmd = *pin++;
		    --avail;
		    if_debug4('w',
			      "command:%02X row written:%d cursor:%d cached=%08X\n",
			      mode10_state->cmd,
			      v_state->rowwritten,
			      mode10_state->cursor,
			      mode10_state->cached_pixel);
		    mode10_state->offset = (mode10_state->cmd >> 3) & 0x03;
		    mode10_state->count = mode10_state->cmd & 0x07;
		    mode10_state->cursor += mode10_state->offset;	/* may be partial */
		    if ((mode10_state->offset < 3)
			&& (mode10_state->count < 7)
			&& (!srcNEW(mode10_state->cmd))
			) {
			/* completed command */
			if (mode10_state->cmd & eRLE) {
			    mode10_state->state = process_rle;
			} else {
			    /* literal, non-new */
			    update_pout(pout);
			    pixel =
				get_pixel(pout, &mode10_state->cached_pixel,
					  mode10_state->cmd,
					  v_state->color_space);

			    copy_pixel(pout, pixel);
			    mode10_state->cursor += 1;
			    if (mode10_state->count > 0) {
				mode10_state->count--;
				mode10_state->state = next_is_pixel;
			    } else
				mode10_state->state = next_is_cmd;
			}
		    } else if (mode10_state->offset == 3)
			mode10_state->state = partial_offset;
		    else if (srcNEW(mode10_state->cmd)) {
			if ((mode10_state->cmd & eRLE)
			    && (mode10_state->cursor >= v_state->SourceWidth)) {
			    /* special case */
			    if_debug0('w', "special\n");
			    mode10_state->cursor = 0;
			    end_of_row = 1;
			    mode10_state->state = next_is_cmd;
			} else
			    mode10_state->state = next_is_pixel;
		    } else if (mode10_state->count == 7)
			mode10_state->state = partial_count;
		    else
			mode10_state->state = next_is_cmd;	/* does not happen */
		    break;
		}

	    case partial_offset:{
		    uint offset = *pin++;

		    avail--;
		    mode10_state->offset += offset;
		    mode10_state->cursor += offset;
		    if (offset == 0xff)
			mode10_state->state = partial_offset;
		    else {
			/* completed offset */
			if_debug5('w',
				  "%02X row=%d offset=%d cursor=%d/%d\n",
				  mode10_state->cmd,
				  v_state->rowwritten,
				  mode10_state->offset, mode10_state->cursor,
				  v_state->SourceWidth);
			if (srcNEW(mode10_state->cmd)) {
			    if ((mode10_state->cmd & eRLE)
				&& (mode10_state->cursor >=
				    v_state->SourceWidth)) {
				/* special case */
				if_debug0('w', "special\n");
				mode10_state->cursor = 0;
				end_of_row = 1;
				mode10_state->state = next_is_cmd;
			    } else
				mode10_state->state = next_is_pixel;
			} else if (mode10_state->count == 7) {
			    mode10_state->state = partial_count;
			} else {
			    /* not new pixels, counts under 7, so we need to process there */
			    if (mode10_state->cmd & eRLE) {
				mode10_state->state = process_rle;
			    } else {
				/* literal non-new */
				update_pout(pout);
				pixel = get_pixel(pout,
						  &mode10_state->cached_pixel,
						  mode10_state->cmd,
						  v_state->color_space);
				copy_pixel(pout, pixel);
				mode10_state->cursor += 1;
				if (mode10_state->count > 0) {
				    mode10_state->count--;
				    mode10_state->state = next_is_pixel;
				} else
				    mode10_state->state = next_is_cmd;
			    }
			}
		    }
		    break;
		}

	    case partial_count:{
		    uint count = *pin++;

		    avail--;
		    mode10_state->count += count;
		    if (count == 0xff)
			mode10_state->state = partial_count;
		    else {
			/* finished count - partial count only happens on RLE */
			if_debug1('w', "count=%d\n", mode10_state->count);
			mode10_state->state = process_rle;
		    }
		    break;
		}

	    case next_is_pixel:{
		    if (!mode9031 && (avail < 3)) {
			/* get to outer loop to get more data */
			avail = 0;
			break;
		    }
		    if_debug3('w', "pixel:%02X%02X%02X\n", pin[0], pin[1],
			      pin[2]);
		    if (v_state->color_space == eGraySub) {
			/* bug in recent hpijs */
			mode10_state->cached_pixel =
			    (pin[0] << 16 | pin[0] << 8 | pin[0]) ^
			    0x00ffffff;
		    } else if (mode9031) {
			mode10_state->cached_pixel =
			    (pin[0] << 16 | pin[0] << 8 | pin[0]);
		    } else
			mode10_state->cached_pixel =
			    (pin[0] << 16 | pin[1] << 8 | pin[2]);
		    update_pout(pout);
		    update_advance_pixel(pout, pin, mode9031);
		    if (mode9031) {
			pin += 1;
			avail -= 1;
		    } else {
			pin += 3;
			avail -= 3;
		    }
		    mode10_state->cursor++;
		    if ((mode10_state->cmd & eRLE)
			&& (mode10_state->count == 7))
			mode10_state->state = partial_count;
		    else if (mode10_state->cmd & eRLE) {
			mode10_state->state = process_rle;
		    } else if (mode10_state->count > 0) {
			/* literal */
			mode10_state->count--;
			mode10_state->state = next_is_pixel;
		    } else
			mode10_state->state = next_is_cmd;
		    break;
		}

	    case process_rle:{
		    update_pout(pout);
		    pixel =
			get_pixel(pout, &mode10_state->cached_pixel,
				  mode10_state->cmd, v_state->color_space);

		    mode10_state->cursor += mode10_state->count + 2;
		    i = mode10_state->count + 2;

		    if (srcNEW(mode10_state->cmd)) {
			i--;	/* already moved cursor in the case of new pixel */
			mode10_state->cursor--;
		    }
		    while (i > 0) {
			copy_pixel(pout, pixel);
			i--;
		    }
		    mode10_state->state = next_is_cmd;
		    break;
		}

	}			/* end switch */

	/* conditional on state may not be necessary */
	if ((mode10_state->state == next_is_cmd) &&
	    (mode10_state->cursor >= v_state->SourceWidth)) {
	    mode10_state->cursor = 0;
	    end_of_row = 1;
	}
    }				/* end of while */

    par->source.available -= pin - par->source.data;	/* subtract compressed data used */
    par->source.position += pin - par->source.data;
    par->source.data = pin;	/* new compressed data position */

    if (end_of_row) {
	v_state->rowwritten++;
	return 1;
    }
    return pxNeedData;		/* not end of row so request more data */
}