/* 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; }
/* 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; }
/* 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); } }