Пример #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
/* Copy a monochrome bitmap. */
static int
x_copy_mono(gx_device * dev,
            const byte * base, int sourcex, int raster, gx_bitmap_id id,
            int x, int y, int w, int h,
            gx_color_index zero, gx_color_index one)
/*
 * X doesn't directly support the simple operation of writing a color
 * through a mask specified by an image.  The plot is the following:
 *  If neither color is gx_no_color_index ("transparent"),
 *      use XPutImage with the "copy" function as usual.
 *  If the color either bitwise-includes or is bitwise-included-in
 *      every color written to date
 *      (a special optimization for writing black/white on color displays),
 *      use XPutImage with an appropriate Boolean function.
 *  Otherwise, do the following complicated stuff:
 *      Create pixmap of depth 1 if necessary.
 *      If foreground color is "transparent" then
 *        invert the raster data.
 *      Use XPutImage to copy the raster image to the newly
 *        created Pixmap.
 *      Install the Pixmap as the clip_mask in the X GC and
 *        tweak the clip origin.
 *      Do an XFillRectangle, fill style=solid, specifying a
 *        rectangle the same size as the original raster data.
 *      De-install the clip_mask.
 */
{
    gx_device_X *xdev = (gx_device_X *) dev;
    int function = GXcopy;
    unsigned long
        lzero = zero,
        lone = one;
    x_pixel
        bc = lzero,
        fc = lone;

    fit_copy(dev, base, sourcex, raster, id, x, y, w, h);
    flush_text(xdev);

    xdev->image.width = sourcex + w;
    xdev->image.height = h;
    xdev->image.data = (char *)base;
    xdev->image.bytes_per_line = raster;
    X_SET_FILL_STYLE(xdev, FillSolid);

    /* Check for null, easy 1-color, hard 1-color, and 2-color cases. */
    if (zero != gx_no_color_index) {
        if (one != gx_no_color_index) {
            /* 2-color case. */
            /* Simply replace existing bits with what's in the image. */
        } else if (!(~xdev->colors_and & bc)) {
            function = GXand;
            fc = ~(x_pixel) 0;
        } else if (!(~bc & xdev->colors_or)) {
            function = GXor;
            fc = 0;
        } else {
            goto hard;
        }
    } else {
        if (one == gx_no_color_index) {		/* no-op */
            return 0;
        } else if (!(~xdev->colors_and & fc)) {
            function = GXand;
            bc = ~(x_pixel) 0;
        } else if (!(~fc & xdev->colors_or)) {
            function = GXor;
            bc = 0;
        } else {
            goto hard;
        }
    }
    xdev->image.format = XYBitmap;
    X_SET_FUNCTION(xdev, function);
    if (bc != xdev->back_color) {
        XSetBackground(xdev->dpy, xdev->gc, (xdev->back_color = bc));
    }
    if (fc != xdev->fore_color) {
        XSetForeground(xdev->dpy, xdev->gc, (xdev->fore_color = fc));
    }
    if (zero != gx_no_color_index)
        NOTE_COLOR(xdev, lzero);
    if (one != gx_no_color_index)
        NOTE_COLOR(xdev, lone);
    put_image(xdev->dpy, xdev->dest, xdev->gc, &xdev->image,
              sourcex, 0, x, y, w, h);

    goto out;

  hard:			/* Handle the hard 1-color case. */
    if (raster > xdev->cp.raster || h > xdev->cp.height) {
        /* Must allocate a new pixmap and GC. */
        /* Release the old ones first. */
        free_cp(dev);

        /* Create the clipping pixmap, depth must be 1. */
        xdev->cp.pixmap =
            XCreatePixmap(xdev->dpy, xdev->win, raster << 3, h, 1);
        if (xdev->cp.pixmap == (Pixmap) 0) {
            lprintf("x_copy_mono: can't allocate pixmap\n");
            return_error(gs_error_VMerror);
        }
        xdev->cp.gc = XCreateGC(xdev->dpy, xdev->cp.pixmap, 0, 0);
        if (xdev->cp.gc == (GC) 0) {
            lprintf("x_copy_mono: can't allocate GC\n");
            return_error(gs_error_VMerror);
        }
        xdev->cp.raster = raster;
        xdev->cp.height = h;
    }
    /* Initialize static mask image params */
    xdev->image.format = XYBitmap;
    X_SET_FUNCTION(xdev, GXcopy);

    /* Select polarity based on fg/bg transparency. */
    if (one == gx_no_color_index) {	/* invert */
        XSetBackground(xdev->dpy, xdev->cp.gc, (x_pixel) 1);
        XSetForeground(xdev->dpy, xdev->cp.gc, (x_pixel) 0);
        X_SET_FORE_COLOR(xdev, lzero);
    } else {
        XSetBackground(xdev->dpy, xdev->cp.gc, (x_pixel) 0);
        XSetForeground(xdev->dpy, xdev->cp.gc, (x_pixel) 1);
        X_SET_FORE_COLOR(xdev, lone);
    }
    put_image(xdev->dpy, xdev->cp.pixmap, xdev->cp.gc,
              &xdev->image, sourcex, 0, 0, 0, w, h);

    /* Install as clipmask. */
    XSetClipMask(xdev->dpy, xdev->gc, xdev->cp.pixmap);
    XSetClipOrigin(xdev->dpy, xdev->gc, x, y);

    /*
     * Draw a solid rectangle through the raster clip mask.
     * Note fill style is guaranteed to be solid from above.
     */
    XFillRectangle(xdev->dpy, xdev->dest, xdev->gc, x, y, w, h);

    /* Tidy up.  Free the pixmap if it's big. */
    XSetClipMask(xdev->dpy, xdev->gc, None);
    if (raster * h > xdev->MaxTempPixmap)
        free_cp(dev);

  out:if (xdev->bpixmap != (Pixmap) 0) {
        /* We wrote to the pixmap, so update the display now. */
        x_update_add(xdev, x, y, w, h);
    }
    return 0;
}
Пример #3
0
/* Render a character. */
static int
x_render_char(gx_xfont * xf, gx_xglyph xg, gx_device * dev,
	      int xo, int yo, gx_color_index color, int required)
{
    x_xfont *xxf = (x_xfont *) xf;
    char chr = (char)xg;
    gs_point wxy;
    gs_int_rect bbox;
    int x, y, w, h;
    int code;

    if (dev->dname == gs_x11_device.dname && !((gx_device_X *)dev)->is_buffered) {
	gx_device_X *xdev = (gx_device_X *)dev;

	code = (*xf->common.procs->char_metrics) (xf, xg, 0, &wxy, &bbox);
	if (code < 0)
	    return code;
	/* Buffer text for more efficient X interaction. */
	if (xdev->text.item_count == MAX_TEXT_ITEMS ||
	    xdev->text.char_count == MAX_TEXT_CHARS ||
	    (IN_TEXT(xdev) &&
	     (yo != xdev->text.origin.y || color != xdev->fore_color ||
	      xxf->font->fid != xdev->fid))
	    ) {
	    DRAW_TEXT(xdev);
	    xdev->text.item_count = xdev->text.char_count = 0;
	}
	if (xdev->text.item_count == 0) {
	    X_SET_FILL_STYLE(xdev, FillSolid);
	    X_SET_FORE_COLOR(xdev, color);
	    X_SET_FUNCTION(xdev, GXcopy);
	    xdev->text.origin.x = xdev->text.x = xo;
	    xdev->text.origin.y = yo;
	    xdev->text.items[0].font = xdev->fid = xxf->font->fid;
	}
	/*
	 * The following is wrong for rotated text, but it doesn't matter,
	 * because the next call of x_render_char will have a different Y.
	 */
	{
	    int index = xdev->text.item_count;
	    XTextItem *item = &xdev->text.items[index];
	    char *pchar = &xdev->text.chars[xdev->text.char_count++];
	    int delta = xo - xdev->text.x;

	    *pchar = chr;
	    if (index > 0 && delta == 0) {
		/* Continue the same item. */
		item[-1].nchars++;
	    } else {
		/* Start a new item. */
		item->chars = pchar;
		item->nchars = 1;
		item->delta = delta;
		if (index > 0)
		    item->font = None;
		xdev->text.item_count++;
	    }
	    xdev->text.x = xo + wxy.x;
	}
	if (xdev->bpixmap != (Pixmap) 0) {
	    x = xo + bbox.p.x;
	    y = yo + bbox.p.y;
	    w = bbox.q.x - bbox.p.x;
	    h = bbox.q.y - bbox.p.y;
	    fit_fill(dev, x, y, w, h);
	    x_update_add(xdev, x, y, w, h);
	}
	return 0;
    } else if (!required)
	return -1;		/* too hard */
    else {
	/* Display on an intermediate bitmap, then copy the bits. */
	gx_device_X *xdev = xxf->xdev;
	int wbm, raster;
	int i;
	XImage *xim;
	Pixmap xpm;
	GC fgc;
	byte *bits;

	dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono);

	code = (*xf->common.procs->char_metrics) (xf, xg, 0, &wxy, &bbox);
	if (code < 0)
	    return code;
	w = bbox.q.x - bbox.p.x;
	h = bbox.q.y - bbox.p.y;
	wbm = ROUND_UP(w, align_bitmap_mod * 8);
	raster = wbm >> 3;
	bits = (byte *) gs_malloc(xdev->memory, h, raster, "x_render_char");
	if (bits == 0)
	    return gs_error_limitcheck;
	xpm = XCreatePixmap(xdev->dpy, xdev->win, w, h, 1);
	fgc = XCreateGC(xdev->dpy, xpm, None, NULL);
	XSetForeground(xdev->dpy, fgc, 0);
	XFillRectangle(xdev->dpy, xpm, fgc, 0, 0, w, h);
	XSetForeground(xdev->dpy, fgc, 1);
	XSetFont(xdev->dpy, fgc, xxf->font->fid);
	XDrawString(xdev->dpy, xpm, fgc, -bbox.p.x, -bbox.p.y, &chr, 1);
	xim = XGetImage(xdev->dpy, xpm, 0, 0, w, h, 1, ZPixmap);
	i = 0;
	for (y = 0; y < h; y++) {
	    char b = 0;

	    for (x = 0; x < wbm; x++) {
		b = b << 1;
		if (x < w)
		    b += XGetPixel(xim, x, y);
		if ((x & 7) == 7)
		    bits[i++] = b;
	    }
	}
	code = (*copy_mono) (dev, bits, 0, raster, gx_no_bitmap_id,
			     xo + bbox.p.x, yo + bbox.p.y, w, h,
			     gx_no_color_index, color);
	gs_free(xdev->memory, (char *)bits, h, raster, "x_render_char");
	XFreePixmap(xdev->dpy, xpm);
	XFreeGC(xdev->dpy, fgc);
	XDestroyImage(xim);
	return (code < 0 ? code : 0);
    }
}