/* 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; }
/* Fill a rectangle. */ static int win_ddb_fill_rectangle(gx_device * dev, int x, int y, int w, int h, gx_color_index color) { fit_fill(dev, x, y, w, h); /* Use PatBlt for filling. Special-case black. */ if (color == 0) PatBlt(wdev->hdcbit, x, y, w, h, rop_write_0s); else { select_brush((int)color); PatBlt(wdev->hdcbit, x, y, w, h, rop_write_pattern); } win_update((gx_device_win *) dev); return 0; }
int mem_gray8_rgb24_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id, const gx_color_index * scolors, const gx_strip_bitmap * textures, const gx_color_index * tcolors, int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop) { gx_device_memory *mdev = (gx_device_memory *) dev; gs_rop3_t rop = lop_rop(lop); gx_color_index const_source = gx_no_color_index; gx_color_index const_texture = gx_no_color_index; uint draster = mdev->raster; int line_count; byte *drow, *base; int depth = dev->color_info.depth; int bpp = depth >> 3; /* bytes per pixel, 1 or 3 */ gx_color_index all_ones = ((gx_color_index) 1 << depth) - 1; gx_color_index strans = (lop & lop_S_transparent ? all_ones : gx_no_color_index); gx_color_index ttrans = (lop & lop_T_transparent ? all_ones : gx_no_color_index); #ifdef USE_RUN_ROP rop_run_op ropper; #ifdef COMPARE_AND_CONTRAST static byte testbuffer[4096]; static byte *start; static int bytelen; #endif #endif /* Check for constant source. */ if (!rop3_uses_S(rop)) const_source = 0; /* arbitrary */ else if (scolors != 0 && scolors[0] == scolors[1]) { /* Constant source */ const_source = scolors[0]; if (const_source == gx_device_black(dev)) rop = rop3_know_S_0(rop); else if (const_source == gx_device_white(dev)) rop = rop3_know_S_1(rop); } /* Check for constant texture. */ if (!rop3_uses_T(rop)) const_texture = 0; /* arbitrary */ else if (tcolors != 0 && tcolors[0] == tcolors[1]) { /* Constant texture */ const_texture = tcolors[0]; if (const_texture == gx_device_black(dev)) rop = rop3_know_T_0(rop); else if (const_texture == gx_device_white(dev)) rop = rop3_know_T_1(rop); } if (bpp == 1 && (gx_device_has_color(dev) || (gx_device_black(dev) != 0 || gx_device_white(dev) != all_ones)) ) { /* * This is an 8-bit device but not gray-scale. Except in a few * simple cases, we have to use the slow algorithm that converts * values to and from RGB. */ gx_color_index bw_pixel; switch (rop) { case rop3_0: bw_pixel = gx_device_black(dev); goto bw; case rop3_1: bw_pixel = gx_device_white(dev); bw: if (bw_pixel == 0x00) rop = rop3_0; else if (bw_pixel == 0xff) rop = rop3_1; else goto df; break; case rop3_D: break; case rop3_S: if (lop & lop_S_transparent) goto df; break; case rop3_T: if (lop & lop_T_transparent) goto df; break; default: df: return mem_default_strip_copy_rop(dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, phase_x, phase_y, lop); } } /* Adjust coordinates to be in bounds. */ if (const_source == gx_no_color_index) { fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height); } else { fit_fill(dev, x, y, width, height); } /* Set up transfer parameters. */ line_count = height; base = scan_line_base(mdev, y); drow = base + x * bpp; /* * There are 18 cases depending on whether each of the source and * texture is constant, 1-bit, or multi-bit, and on whether the * depth is 8 or 24 bits. We divide first according to constant * vs. non-constant, and then according to 1- vs. multi-bit, and * finally according to pixel depth. This minimizes source code, * but not necessarily time, since we do some of the divisions * within 1 or 2 levels of loop. */ #ifdef USE_RUN_ROP #define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7))) /* 8-bit */ #define cbit8(base, i, colors)\ (dbit(base, i) ? (byte)colors[1] : (byte)colors[0]) #define rop_body_8(s_pixel, t_pixel)\ if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\ (t_pixel) == ttrans /* Po = 0, p_tr = 1 */\ )\ continue;\ *dptr = (*rop_proc_table[rop])(*dptr, s_pixel, t_pixel) /* 24-bit */ #define get24(ptr)\ (((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2]) #define put24(ptr, pixel)\ (ptr)[0] = (byte)((pixel) >> 16),\ (ptr)[1] = (byte)((uint)(pixel) >> 8),\ (ptr)[2] = (byte)(pixel) #define cbit24(base, i, colors)\ (dbit(base, i) ? colors[1] : colors[0]) #define rop_body_24(s_pixel, t_pixel)\ if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\ (t_pixel) == ttrans /* Po = 0, p_tr = 1 */\ )\ continue;\ { gx_color_index d_pixel = get24(dptr);\ d_pixel = (*rop_proc_table[rop])(d_pixel, s_pixel, t_pixel);\ put24(dptr, d_pixel);\ } if (const_texture != gx_no_color_index) { /**** Constant texture ****/ if (const_source != gx_no_color_index) { /**** Constant source & texture ****/ rop_get_run_op(&ropper, lop, depth, rop_s_constant | rop_t_constant); rop_set_s_constant(&ropper, const_source); rop_set_t_constant(&ropper, const_texture); for (; line_count-- > 0; drow += draster) { #ifdef COMPARE_AND_CONTRAST byte *dptr = drow; int left = width; bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); rop_run(&ropper, testbuffer, left); if (bpp == 1) /**** 8-bit destination ****/ for (; left > 0; ++dptr, --left) { vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), const_texture); rop_body_8((byte)const_source, (byte)const_texture); } else /**** 24-bit destination ****/ for (; left > 0; dptr += 3, --left) { vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), const_texture); rop_body_24(const_source, const_texture); } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else rop_run(&ropper, drow, width); #endif } rop_release_run_op(&ropper); } else { /**** Data source, const texture ****/ if (scolors) { const byte *srow = sdata; rop_get_run_op(&ropper, lop, depth, rop_t_constant | rop_s_1bit); rop_set_t_constant(&ropper, const_texture); rop_set_s_colors(&ropper, scolors); for (; line_count-- > 0; drow += draster, srow += sraster) { #ifdef COMPARE_AND_CONTRAST byte *dptr = drow; int left = width; /**** 1-bit source ****/ int sx = sourcex; rop_set_s_bitmap_subbyte(&ropper, srow, sourcex); bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); rop_run(&ropper, testbuffer, width); if (bpp == 1) /**** 8-bit destination ****/ for (; left > 0; ++dptr, ++sx, --left) { byte s_pixel = cbit8(srow, sx, scolors); vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), const_texture); rop_body_8(s_pixel, (byte)const_texture); } else /**** 24-bit destination ****/ for (; left > 0; dptr += 3, ++sx, --left) { bits32 s_pixel = cbit24(srow, sx, scolors); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), const_texture); rop_body_24(s_pixel, const_texture); } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else /**** 1-bit source ****/ /**** 8-bit destination ****/ /**** 24-bit destination ****/ rop_set_s_bitmap_subbyte(&ropper, srow, sourcex); rop_run(&ropper, drow, width); #endif } rop_release_run_op(&ropper); } else { const byte *srow = sdata; rop_get_run_op(&ropper, lop, depth, rop_t_constant); rop_set_t_constant(&ropper, const_texture); for (; line_count-- > 0; drow += draster, srow += sraster) { #ifdef COMPARE_AND_CONTRAST byte *dptr = drow; int left = width; bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); rop_set_s_bitmap(&ropper, srow + sourcex * bpp); rop_run(&ropper, testbuffer, left); /**** 8-bit source & dest ****/ if (bpp == 1) { const byte *sptr = srow + sourcex; for (; left > 0; ++dptr, ++sptr, --left) { byte s_pixel = *sptr; vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), const_texture); rop_body_8(s_pixel, (byte)const_texture); } } else { /**** 24-bit source & dest ****/ const byte *sptr = srow + sourcex * 3; bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); for (; left > 0; dptr += 3, sptr += 3, --left) { bits32 s_pixel = get24(sptr); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), const_texture); rop_body_24(s_pixel, const_texture); } } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else /**** 8-bit source & dest ****/ /**** 24-bit source & dest ****/ rop_set_s_bitmap(&ropper, srow + sourcex * bpp); rop_run(&ropper, drow, width); #endif } rop_release_run_op(&ropper); } } } else if (const_source != gx_no_color_index) { /**** Const source, data texture ****/ if (tcolors) { uint traster = textures->raster; int ty = y + phase_y; rop_get_run_op(&ropper, lop, depth, rop_s_constant | rop_t_1bit); rop_set_s_constant(&ropper, const_source); for (; line_count-- > 0; drow += draster, ++ty) { /* Loop over copies of the tile. */ int dx = x, w = width, nw; byte *dptr = drow; const byte *trow = textures->data + (ty % textures->size.y) * traster; int xoff = x_offset(phase_x, ty, textures); for (; w > 0; dx += nw, w -= nw) { int tx = (dx + xoff) % textures->rep_width; int left = nw = min(w, textures->size.x - tx); const byte *tptr = trow; rop_set_t_bitmap_subbyte(&ropper, trow, tx); #ifdef COMPARE_AND_CONTRAST bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); rop_run(&ropper, testbuffer, left); /**** 1-bit texture ****/ if (bpp == 1) /**** 8-bit dest ****/ for (; left > 0; ++dptr, ++tx, --left) { byte t_pixel = cbit8(tptr, tx, tcolors); vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_8((byte)const_source, t_pixel); } else /**** 24-bit dest ****/ for (; left > 0; dptr += 3, ++tx, --left) { bits32 t_pixel = cbit24(tptr, tx, tcolors); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_24(const_source, t_pixel); } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else rop_run(&ropper, dptr, left); dptr += left; #endif } } } else { uint traster = textures->raster; int ty = y + phase_y; rop_get_run_op(&ropper, lop, depth, rop_s_constant); rop_set_s_constant(&ropper, const_source); for (; line_count-- > 0; drow += draster, ++ty) { /* Loop over copies of the tile. */ int dx = x, w = width, nw; byte *dptr = drow; const byte *trow = textures->data + (ty % textures->size.y) * traster; int xoff = x_offset(phase_x, ty, textures); for (; w > 0; dx += nw, w -= nw) { int tx = (dx + xoff) % textures->rep_width; int left = nw = min(w, textures->size.x - tx); const byte *tptr = trow + tx*bpp; rop_set_t_bitmap(&ropper, tptr); #ifdef COMPARE_AND_CONTRAST bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); rop_run(&ropper, testbuffer, left); /**** 8-bit T & D ****/ if (bpp == 1) { for (; left > 0; ++dptr, ++tptr, --left) { byte t_pixel = *tptr; vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_8((byte)const_source, t_pixel); } } else { /**** 24-bit T & D ****/ for (; left > 0; dptr += 3, tptr += 3, --left) { bits32 t_pixel = get24(tptr); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_24(const_source, t_pixel); } } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else /**** 8-bit T & D ****/ /**** 24-bit T & D ****/ rop_run(&ropper, dptr, left); dptr += left * bpp; #endif } } rop_release_run_op(&ropper); } } else { /**** Data source & texture ****/ if (scolors != NULL | tcolors != NULL) { uint traster = textures->raster; int ty = y + phase_y; const byte *srow = sdata; rop_get_run_op(&ropper, lop, depth, ((scolors == NULL ? 0 : rop_s_1bit) | (tcolors == NULL ? 0 : rop_t_1bit))); /* Loop over scan lines. */ for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) { /* Loop over copies of the tile. */ int sx = sourcex; int dx = x; int w = width; int nw; byte *dptr = drow; const byte *trow = textures->data + (ty % textures->size.y) * traster; int xoff = x_offset(phase_x, ty, textures); for (; w > 0; dx += nw, w -= nw) { /* Loop over individual pixels. */ int tx = (dx + xoff) % textures->rep_width; int left = nw = min(w, textures->size.x - tx); const byte *sptr = srow + sx*bpp; const byte *tptr = trow + tx*bpp; /* * For maximum speed, we should split this loop * into 7 cases depending on source & texture * depth: (1,1), (1,8), (1,24), (8,1), (8,8), * (24,1), (24,24). But since we expect these * cases to be relatively uncommon, we just * divide on the destination depth. */ if (scolors) rop_set_s_bitmap_subbyte(&ropper, srow, sx); else rop_set_s_bitmap(&ropper, sptr); if (tcolors) rop_set_t_bitmap_subbyte(&ropper, trow, tx); else rop_set_t_bitmap(&ropper, tptr); #ifdef COMPARE_AND_CONTRAST bytelen = left*bpp; start = dptr; memcpy(testbuffer, dptr, bytelen); rop_run(&ropper, testbuffer, left); if (bpp == 1) { /**** 8-bit destination ****/ for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) { byte s_pixel = (scolors ? cbit8(srow, sx, scolors) : *sptr); byte t_pixel = (tcolors ? cbit8(trow, tx, tcolors) : *tptr); vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_8(s_pixel, t_pixel); } } else { /**** 24-bit destination ****/ for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) { bits32 s_pixel = (scolors ? cbit24(srow, sx, scolors) : get24(sptr)); bits32 t_pixel = (tcolors ? cbit24(tptr, tx, tcolors) : get24(tptr)); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_24(s_pixel, t_pixel); } } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else rop_run(&ropper, dptr, left); #endif } } } else { uint traster = textures->raster; int ty = y + phase_y; const byte *srow = sdata; /* Loop over scan lines. */ rop_get_run_op(&ropper, rop, depth, 0); for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) { /* Loop over copies of the tile. */ int sx = sourcex; int dx = x; int w = width; int nw; byte *dptr = drow; const byte *trow = textures->data + (ty % textures->size.y) * traster; int xoff = x_offset(phase_x, ty, textures); for (; w > 0; dx += nw, w -= nw) { /* Loop over individual pixels. */ int tx = (dx + xoff) % textures->rep_width; int left = nw = min(w, textures->size.x - tx); const byte *tptr = trow + tx * bpp; const byte *sptr = srow + sx * bpp; rop_set_s_bitmap(&ropper, sptr); rop_set_t_bitmap(&ropper, tptr); #ifdef COMPARE_AND_CONTRAST if (bpp == 1) { rop_run(&ropper, testbuffer, left); /**** 8-bit destination ****/ for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) { rop_body_8(*sptr, *tptr); } } else { /**** 24-bit destination ****/ for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) { bits32 s_pixel = get24(sptr); bits32 t_pixel = get24(tptr); rop_body_24(s_pixel, t_pixel); } } if (memcmp(testbuffer, start, bytelen) != 0) { eprintf("Failed!\n"); } #else /**** 8-bit destination ****/ /**** 24-bit destination ****/ rop_run(&ropper, dptr, left); #endif } } rop_release_run_op(&ropper); } } #undef rop_body_8 #undef rop_body_24 #undef dbit #undef cbit8 #undef cbit24 #else #define dbit(base, i) ((base)[(i) >> 3] & (0x80 >> ((i) & 7))) /* 8-bit */ #define cbit8(base, i, colors)\ (dbit(base, i) ? (byte)colors[1] : (byte)colors[0]) #define rop_body_8(s_pixel, t_pixel)\ if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\ (t_pixel) == ttrans /* Po = 0, p_tr = 1 */\ )\ continue;\ *dptr = (*rop_proc_table[rop])(*dptr, s_pixel, t_pixel) /* 24-bit */ #define get24(ptr)\ (((gx_color_index)(ptr)[0] << 16) | ((gx_color_index)(ptr)[1] << 8) | (ptr)[2]) #define put24(ptr, pixel)\ (ptr)[0] = (byte)((pixel) >> 16),\ (ptr)[1] = (byte)((uint)(pixel) >> 8),\ (ptr)[2] = (byte)(pixel) #define cbit24(base, i, colors)\ (dbit(base, i) ? colors[1] : colors[0]) #define rop_body_24(s_pixel, t_pixel)\ if ( (s_pixel) == strans || /* So = 0, s_tr = 1 */\ (t_pixel) == ttrans /* Po = 0, p_tr = 1 */\ )\ continue;\ { gx_color_index d_pixel = get24(dptr);\ d_pixel = (*rop_proc_table[rop])(d_pixel, s_pixel, t_pixel);\ put24(dptr, d_pixel);\ } if (const_texture != gx_no_color_index) { /**** Constant texture ****/ if (const_source != gx_no_color_index) { /**** Constant source & texture ****/ for (; line_count-- > 0; drow += draster) { byte *dptr = drow; int left = width; if (bpp == 1) /**** 8-bit destination ****/ for (; left > 0; ++dptr, --left) { vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), const_texture); rop_body_8((byte)const_source, (byte)const_texture); } else /**** 24-bit destination ****/ for (; left > 0; dptr += 3, --left) { vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), const_texture); rop_body_24(const_source, const_texture); } } } else { /**** Data source, const texture ****/ const byte *srow = sdata; for (; line_count-- > 0; drow += draster, srow += sraster) { byte *dptr = drow; int left = width; if (scolors) { /**** 1-bit source ****/ int sx = sourcex; if (bpp == 1) /**** 8-bit destination ****/ for (; left > 0; ++dptr, ++sx, --left) { byte s_pixel = cbit8(srow, sx, scolors); vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), const_texture); rop_body_8(s_pixel, (byte)const_texture); } else /**** 24-bit destination ****/ for (; left > 0; dptr += 3, ++sx, --left) { bits32 s_pixel = cbit24(srow, sx, scolors); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), const_texture); rop_body_24(s_pixel, const_texture); } } else if (bpp == 1) { /**** 8-bit source & dest ****/ const byte *sptr = srow + sourcex; for (; left > 0; ++dptr, ++sptr, --left) { byte s_pixel = *sptr; vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), const_texture); rop_body_8(s_pixel, (byte)const_texture); } } else { /**** 24-bit source & dest ****/ const byte *sptr = srow + sourcex * 3; for (; left > 0; dptr += 3, sptr += 3, --left) { bits32 s_pixel = get24(sptr); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), const_texture); rop_body_24(s_pixel, const_texture); } } } } } else if (const_source != gx_no_color_index) { /**** Const source, data texture ****/ uint traster = textures->raster; int ty = y + phase_y; for (; line_count-- > 0; drow += draster, ++ty) { /* Loop over copies of the tile. */ int dx = x, w = width, nw; byte *dptr = drow; const byte *trow = textures->data + (ty % textures->size.y) * traster; int xoff = x_offset(phase_x, ty, textures); for (; w > 0; dx += nw, w -= nw) { int tx = (dx + xoff) % textures->rep_width; int left = nw = min(w, textures->size.x - tx); const byte *tptr = trow; if (tcolors) { /**** 1-bit texture ****/ if (bpp == 1) /**** 8-bit dest ****/ for (; left > 0; ++dptr, ++tx, --left) { byte t_pixel = cbit8(tptr, tx, tcolors); vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_8((byte)const_source, t_pixel); } else /**** 24-bit dest ****/ for (; left > 0; dptr += 3, ++tx, --left) { bits32 t_pixel = cbit24(tptr, tx, tcolors); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_24(const_source, t_pixel); } } else if (bpp == 1) { /**** 8-bit T & D ****/ tptr += tx; for (; left > 0; ++dptr, ++tptr, --left) { byte t_pixel = *tptr; vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_8((byte)const_source, t_pixel); } } else { /**** 24-bit T & D ****/ tptr += tx * 3; for (; left > 0; dptr += 3, tptr += 3, --left) { bits32 t_pixel = get24(tptr); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_24(const_source, t_pixel); } } } } } else { /**** Data source & texture ****/ uint traster = textures->raster; int ty = y + phase_y; const byte *srow = sdata; /* Loop over scan lines. */ for (; line_count-- > 0; drow += draster, srow += sraster, ++ty) { /* Loop over copies of the tile. */ int sx = sourcex; int dx = x; int w = width; int nw; byte *dptr = drow; const byte *trow = textures->data + (ty % textures->size.y) * traster; int xoff = x_offset(phase_x, ty, textures); for (; w > 0; dx += nw, w -= nw) { /* Loop over individual pixels. */ int tx = (dx + xoff) % textures->rep_width; int left = nw = min(w, textures->size.x - tx); const byte *tptr = trow; /* * For maximum speed, we should split this loop * into 7 cases depending on source & texture * depth: (1,1), (1,8), (1,24), (8,1), (8,8), * (24,1), (24,24). But since we expect these * cases to be relatively uncommon, we just * divide on the destination depth. */ if (bpp == 1) { /**** 8-bit destination ****/ const byte *sptr = srow + sx; tptr += tx; for (; left > 0; ++dptr, ++sptr, ++tptr, ++sx, ++tx, --left) { byte s_pixel = (scolors ? cbit8(srow, sx, scolors) : *sptr); byte t_pixel = (tcolors ? cbit8(tptr, tx, tcolors) : *tptr); vd_pixel(int2fixed((dptr - base) % draster), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_8(s_pixel, t_pixel); } } else { /**** 24-bit destination ****/ const byte *sptr = srow + sx * 3; tptr += tx * 3; for (; left > 0; dptr += 3, sptr += 3, tptr += 3, ++sx, ++tx, --left) { bits32 s_pixel = (scolors ? cbit24(srow, sx, scolors) : get24(sptr)); bits32 t_pixel = (tcolors ? cbit24(tptr, tx, tcolors) : get24(tptr)); vd_pixel(int2fixed((dptr - base) % draster / 3), int2fixed((dptr - base) / draster + y), t_pixel); rop_body_24(s_pixel, t_pixel); } } } } } #undef rop_body_8 #undef rop_body_24 #undef dbit #undef cbit8 #undef cbit24 #endif return 0; }
/* Note that this also does the right thing for colored tiles. */ static int win_ddb_tile_rectangle(gx_device * dev, const gx_tile_bitmap * tile, int x, int y, int w, int h, gx_color_index czero, gx_color_index cone, int px, int py) { fit_fill(dev, x, y, w, h); if (czero != gx_no_color_index && cone != gx_no_color_index) { fill_rect(x, y, w, h, czero); czero = gx_no_color_index; } if (tile->raster == bmWidthBytes && tile->size.y <= bmHeight && (px | py) == 0 && cone != gx_no_color_index ) { /* We can do this much more efficiently */ /* by using the internal algorithms of copy_mono */ /* and gx_default_tile_rectangle. */ int width = tile->size.x; int height = tile->size.y; int rwidth = tile->rep_width; int irx = ((rwidth & (rwidth - 1)) == 0 ? /* power of 2 */ x & (rwidth - 1) : x % rwidth); int ry = y % tile->rep_height; int icw = width - irx; int ch = height - ry; int ex = x + w, ey = y + h; int fex = ex - width, fey = ey - height; int cx, cy; select_brush((int)cone); if (tile->id != wdev->bm_id || tile->id == gx_no_bitmap_id) { wdev->bm_id = tile->id; SetBitmapBits(wdev->hbmmono, (DWORD) (bmWidthBytes * tile->size.y), (BYTE *) tile->data); } #define copy_tile(srcx, srcy, tx, ty, tw, th)\ BitBlt(wdev->hdcbit, tx, ty, tw, th, wdev->hdcmono, srcx, srcy, rop_write_at_1s) if (ch > h) ch = h; for (cy = y;;) { if (w <= icw) copy_tile(irx, ry, x, cy, w, ch); else { copy_tile(irx, ry, x, cy, icw, ch); cx = x + icw; while (cx <= fex) { copy_tile(0, ry, cx, cy, width, ch); cx += width; } if (cx < ex) { copy_tile(0, ry, cx, cy, ex - cx, ch); } } if ((cy += ch) >= ey) break; ch = (cy > fey ? ey - cy : height); ry = 0; } win_update((gx_device_win *) dev); return 0; } return gx_default_tile_rectangle(dev, tile, x, y, w, h, czero, cone, px, py); }
/* 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); } }
/* * The default implementation for non-memory devices uses get_bits_rectangle * to read out the pixels, the memory device implementation to do the * operation, and copy_color to write the pixels back. */ int gx_default_strip_copy_rop(gx_device * dev, const byte * sdata, int sourcex, uint sraster, gx_bitmap_id id, const gx_color_index * scolors, const gx_strip_bitmap * textures, const gx_color_index * tcolors, int x, int y, int width, int height, int phase_x, int phase_y, gs_logical_operation_t lop) { int depth = dev->color_info.depth; gs_memory_t *mem = dev->memory; const gx_device_memory *mdproto = gdev_mem_device_for_bits(depth); gx_device_memory mdev; uint draster; byte *row = 0; gs_int_rect rect; int max_height; int block_height; int code; int py; #ifdef DEBUG if (gs_debug_c('b')) trace_copy_rop("gx_default_strip_copy_rop", dev, sdata, sourcex, sraster, id, scolors, textures, tcolors, x, y, width, height, phase_x, phase_y, lop); #endif if (mdproto == 0) return_error(gs_error_rangecheck); if (sdata == 0) { fit_fill(dev, x, y, width, height); } else { fit_copy(dev, sdata, sourcex, sraster, id, x, y, width, height); } draster = bitmap_raster(width * depth); max_height = max_rop_bitmap / draster; if (max_height == 0) max_height = 1; block_height = min(height, max_height); gs_make_mem_device(&mdev, mdproto, mem, -1, dev); gx_device_retain((gx_device *)&mdev, true); /* prevent freeing */ mdev.width = width; mdev.height = block_height; mdev.bitmap_memory = mem; mdev.color_info = dev->color_info; code = (*dev_proc(&mdev, open_device))((gx_device *)&mdev); if (code < 0) return code; if (rop3_uses_D(gs_transparent_rop(lop))) { row = gs_alloc_bytes(mem, draster * block_height, "copy_rop row"); if (row == 0) { code = gs_note_error(gs_error_VMerror); goto out; } } rect.p.x = x; rect.q.x = x + width; for (py = y; py < y + height; py += block_height) { if (block_height > y + height - py) block_height = y + height - py; rect.p.y = py; rect.q.y = py + block_height; if (row /*uses_d*/) { gs_get_bits_params_t bit_params; bit_params.options = GB_COLORS_NATIVE | GB_ALPHA_NONE | GB_DEPTH_ALL | GB_PACKING_CHUNKY | GB_RETURN_ALL | GB_ALIGN_STANDARD | GB_OFFSET_0 | GB_OFFSET_ANY | GB_RASTER_STANDARD; bit_params.data[0] = row; bit_params.x_offset = 0; code = (*dev_proc(dev, get_bits_rectangle)) (dev, &rect, &bit_params, NULL); if (code < 0) break; code = (*dev_proc(&mdev, copy_color)) ((gx_device *)&mdev, bit_params.data[0], bit_params.x_offset, draster, gx_no_bitmap_id, 0, 0, width, block_height); if (code < 0) return code; } code = (*dev_proc(&mdev, strip_copy_rop)) ((gx_device *)&mdev, sdata + (py - y) * sraster, sourcex, sraster, gx_no_bitmap_id, scolors, textures, tcolors, 0, 0, width, block_height, phase_x + x, phase_y + py, lop); if (code < 0) break; code = (*dev_proc(dev, copy_color)) (dev, scan_line_base(&mdev, 0), 0, draster, gx_no_bitmap_id, x, py, width, block_height); if (code < 0) break; } out: gs_free_object(mem, row, "copy_rop row"); (*dev_proc(&mdev, close_device))((gx_device *)&mdev); return code; }