/* Default implementation of tile_rectangle */ int gx_default_tile_rectangle(gx_device *dev, register const gx_bitmap *tile, int x, int y, int w, int h, gx_color_index color0, gx_color_index color1, int px, int py) { /* Fill the rectangle in chunks */ int width = tile->size.x; int height = tile->size.y; int raster = tile->raster; int rwidth = tile->rep_width; int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ (x + px) & (rwidth - 1) : (x + px) % rwidth); int ry = (y + py) % tile->rep_height; int icw = width - irx; int ch = height - ry; byte *row = tile->data + ry * raster; #define d_proc_mono (dev->procs->copy_mono) dev_proc_copy_mono((*proc_mono)); #define d_proc_color (dev->procs->copy_color) dev_proc_copy_color((*proc_color)); #define d_color_halftone\ (color0 == gx_no_color_index && color1 == gx_no_color_index) int color_halftone; #define get_color_info()\ if ( (color_halftone = d_color_halftone) ) proc_color = d_proc_color;\ else proc_mono = d_proc_mono int code; #ifdef DEBUG if ( gs_debug['t'] ) { int ptx, pty; const byte *ptp = tile->data; dprintf3("[t]tile %dx%d raster=%d;", tile->size.x, tile->size.y, tile->raster); dprintf6(" x,y=%d,%d w,h=%d,%d p=%d,%d\n", x, y, w, h, px, py); for ( pty = 0; pty < tile->size.y; pty++ ) { dprintf(" "); for ( ptx = 0; ptx < tile->raster; ptx++ ) dprintf1("%3x", *ptp++); } dputc('\n'); } #endif #define real_copy_tile(srcx, tx, ty, tw, th)\ code =\ (color_halftone ?\ (*proc_color)(dev, row, srcx, raster, gx_no_bitmap_id, tx, ty, tw, th) :\ (*proc_mono)(dev, row, srcx, raster, gx_no_bitmap_id, tx, ty, tw, th, color0, color1));\ gp_check_interrupts();\ if ( code < 0 ) return_error(code) #ifdef DEBUG #define copy_tile(sx, tx, ty, tw, th)\ if ( gs_debug['t'] )\ dprintf5(" copy sx=%d x=%d y=%d w=%d h=%d\n",\ sx, tx, ty, tw, th);\ real_copy_tile(sx, tx, ty, tw, th) #else #define copy_tile(sx, tx, ty, tw, th)\ real_copy_tile(sx, tx, ty, tw, th) #endif if ( icw >= w ) { /* Narrow operation */ int ey, fey, cy; if ( ch >= h ) { /* Just one (partial) tile to transfer. */ #define color_halftone d_color_halftone #define proc_color d_proc_color #define proc_mono d_proc_mono copy_tile(irx, x, y, w, h); #undef proc_mono #undef proc_color #undef color_halftone return 0; } get_color_info(); ey = y + h; fey = ey - height; copy_tile(irx, x, y, w, ch); cy = y + ch; row = tile->data; do { ch = (cy > fey ? ey - cy : height); copy_tile(irx, x, cy, w, ch); } while ( (cy += ch) < ey ); return 0; } get_color_info(); if ( ch >= h ) { /* Shallow operation */ int ex = x + w; int fex = ex - width; int cx = x + icw; copy_tile(irx, x, y, icw, h); while ( cx <= fex ) { copy_tile(0, cx, y, width, h); cx += width; } if ( cx < ex ) { copy_tile(0, cx, y, ex - cx, h); } } else { /* Full operation */ int ex = x + w, ey = y + h; int fex = ex - width, fey = ey - height; int cx, cy; for ( cy = y; ; ) { copy_tile(irx, x, cy, icw, ch); cx = x + icw; while ( cx <= fex ) { copy_tile(0, cx, cy, width, ch); cx += width; } if ( cx < ex ) { copy_tile(0, cx, cy, ex - cx, ch); } if ( (cy += ch) >= ey ) break; ch = (cy > fey ? ey - cy : height); row = tile->data; } } #undef copy_tile #undef real_copy_tile 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); } }
/* Render a character. */ int win_render_char(gx_xfont * xf, gx_xglyph xg, gx_device * dev, int xo, int yo, gx_color_index color, int required) { char chr = (char)xg; int code; #ifdef NOTUSED /* we don't own any windows so we can no longer do this */ if (dev->dname == gs_mswin_device.dname && wdev->hdctext != NULL && !wxf->invert_y ) { /* Display the character directly */ HDC hdc = wdev->hdctext; PALETTEENTRY *pal = &wdev->limgpalette->palPalEntry[color]; if ((code = win_select_font(hdc, wxf)) < 0) return code; SetTextColor(hdc, RGB(pal->peRed, pal->peGreen, pal->peBlue)); SetBkMode(hdc, TRANSPARENT); TextOut(hdc, xo, yo - wxf->y_offset, &chr, 1); } else #endif if (!required) code = -1; /* too hard */ else { /* Display on an intermediate bitmap, then copy the bits. */ gs_point wxy; gs_int_rect bbox; int w, h, wbm, raster; gx_device_win *fdev = wxf->dev; HBITMAP hbm; byte *bits; 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 = gs_malloc(dev->memory, h, raster, "win_render_char"); if (bits == 0) return gs_error_limitcheck; hbm = CreateBitmap(wbm, h, 1, 1, NULL); if (hbm == NULL) { code = gs_error_limitcheck; } else { HDC hdcwin = win_get_dc(fdev); HDC hdcbit = CreateCompatibleDC(hdcwin); dev_proc_copy_mono((*copy_mono)) = dev_proc(dev, copy_mono); int y = yo - wxf->y_offset; SetMapMode(hdcbit, GetMapMode(hdcwin)); win_select_font(hdcbit, wxf); SelectObject(hdcbit, hbm); PatBlt(hdcbit, 0, 0, wbm, h, rop_write_0s); SetTextColor(hdcbit, 0xffffffL); /* 1 */ SetBkMode(hdcbit, TRANSPARENT); TextOut(hdcbit, 0, 0, &chr, 1); GetBitmapBits(hbm, (DWORD) raster * h, bits); DeleteDC(hdcbit); win_release_dc(fdev, hdcwin); DeleteObject(hbm); if (!wxf->invert_y) code = (*copy_mono) (dev, bits, 0, raster, gx_no_bitmap_id, xo, y, w, h, gx_no_color_index, color); else { /* Copy scan lines in reverse order. */ int i; y += h - 1; for (i = 0; i < h; i++) (*copy_mono) (dev, bits + i * raster, 0, raster, gx_no_bitmap_id, xo, y - i, w, 1, gx_no_color_index, color); } } gs_free(dev->memory, bits, h, raster, "win_render_char"); } return (code < 0 ? code : 0); }