/* Open the win_dib driver */ static int win_dib_open(gx_device * dev) { int code = win_open(dev); if (code < 0) return code; #ifdef __WIN32__ if (!is_win32s) wdev->hmtx = CreateMutex(NULL, FALSE, NULL); /* unnamed mutex, initially unowned */ #endif if (gdev_mem_device_for_bits(dev->color_info.depth) == 0) { win_close(dev); return gs_error_rangecheck; } code = win_dib_alloc_bitmap((gx_device_win *) dev, dev); if (code < 0) { win_close(dev); return code; } /* notify caller about new device */ if (pgsdll_callback) { (*pgsdll_callback) (GSDLL_DEVICE, (unsigned char *)dev, 1); (*pgsdll_callback) (GSDLL_SIZE, (unsigned char *)dev, (dev->width & 0xffff) + ((ulong) (dev->height & 0xffff) << 16)); } return code; }
/* * Create an imdi memory device for page or band buffering, * possibly preceded by a plane extraction device. */ int wtsimdi_create_buf_device(gx_device **pbdev, gx_device *target, const gx_render_plane_t *render_plane, gs_memory_t *mem, bool for_band) { int plane_index = (render_plane ? render_plane->index : -1); int depth; const gx_device_memory *mdproto; gx_device_memory *mdev; if (plane_index >= 0) depth = render_plane->depth; else depth = target->color_info.depth; mdproto = gdev_mem_device_for_bits(depth); if (mdproto == 0) return_error(gs_error_rangecheck); if (mem) { mdev = gs_alloc_struct(mem, gx_device_memory, &st_device_memory, "create_buf_device"); if (mdev == 0) return_error(gs_error_VMerror); } else { mdev = (gx_device_memory *)*pbdev; } if (target == (gx_device *)mdev) { /* The following is a special hack for setting up printer devices. */ assign_dev_procs(mdev, mdproto); check_device_separable((gx_device *)mdev); gx_device_fill_in_procs((gx_device *)mdev); } else gs_make_mem_device(mdev, mdproto, mem, (for_band ? 1 : 0), (target == (gx_device *)mdev ? NULL : target)); mdev->width = target->width; /* * The matrix in the memory device is irrelevant, * because all we do with the device is call the device-level * output procedures, but we may as well set it to * something halfway reasonable. */ gs_deviceinitialmatrix(target, &mdev->initial_matrix); /****** QUESTIONABLE, BUT BETTER THAN OMITTING ******/ mdev->color_info = target->color_info; *pbdev = (gx_device *)mdev; return 0; }
/* * Set up a planar memory device, after calling gs_make_mem_device but * before opening the device. The pre-existing device provides the color * mapping procedures, but not the drawing procedures. Requires: num_planes * > 0, plane_depths[0 .. num_planes - 1] > 0, sum of plane depths = * mdev->color_info.depth. * * Note that this is the only public procedure in this file, and the only * sanctioned way to set up a planar memory device. */ int gdev_mem_set_planar(gx_device_memory * mdev, int num_planes, const gx_render_plane_t *planes /*[num_planes]*/) { int total_depth; int same_depth = planes[0].depth; gx_color_index covered = 0; int pi; const gx_device_memory *mdproto = gdev_mem_device_for_bits(mdev->color_info.depth); if (num_planes < 1 || num_planes > GX_DEVICE_COLOR_MAX_COMPONENTS) return_error(gs_error_rangecheck); for (pi = 0, total_depth = 0; pi < num_planes; ++pi) { int shift = planes[pi].shift; int plane_depth = planes[pi].depth; gx_color_index mask; if (shift < 0 || plane_depth > 16 || !gdev_mem_device_for_bits(plane_depth)) return_error(gs_error_rangecheck); mask = (((gx_color_index)1 << plane_depth) - 1) << shift; if (covered & mask) return_error(gs_error_rangecheck); covered |= mask; if (plane_depth != same_depth) same_depth = 0; total_depth += plane_depth; } if (total_depth > mdev->color_info.depth) return_error(gs_error_rangecheck); mdev->num_planes = num_planes; memcpy(mdev->planes, planes, num_planes * sizeof(planes[0])); mdev->plane_depth = same_depth; /* Change the drawing procedures. */ set_dev_proc(mdev, open_device, mem_planar_open); if (num_planes == 1) { /* For 1 plane, just use a normal device */ set_dev_proc(mdev, fill_rectangle, dev_proc(mdproto, fill_rectangle)); set_dev_proc(mdev, copy_mono, dev_proc(mdproto, copy_mono)); set_dev_proc(mdev, copy_color, dev_proc(mdproto, copy_color)); set_dev_proc(mdev, copy_alpha, dev_proc(mdproto, copy_alpha)); set_dev_proc(mdev, strip_tile_rectangle, dev_proc(mdproto, strip_tile_rectangle)); set_dev_proc(mdev, strip_copy_rop, dev_proc(mdproto, strip_copy_rop)); set_dev_proc(mdev, get_bits_rectangle, dev_proc(mdproto, get_bits_rectangle)); } else { set_dev_proc(mdev, fill_rectangle, mem_planar_fill_rectangle); set_dev_proc(mdev, copy_mono, mem_planar_copy_mono); if ((mdev->color_info.depth == 24) && (mdev->num_planes == 3) && (mdev->planes[0].depth == 8) && (mdev->planes[0].shift == 16) && (mdev->planes[1].depth == 8) && (mdev->planes[1].shift == 8) && (mdev->planes[2].depth == 8) && (mdev->planes[2].shift == 0)) set_dev_proc(mdev, copy_color, mem_planar_copy_color_24to8); else if ((mdev->color_info.depth == 4) && (mdev->num_planes == 4) && (mdev->planes[0].depth == 1) && (mdev->planes[0].shift == 3) && (mdev->planes[1].depth == 1) && (mdev->planes[1].shift == 2) && (mdev->planes[2].depth == 1) && (mdev->planes[2].shift == 1) && (mdev->planes[3].depth == 1) && (mdev->planes[3].shift == 0)) set_dev_proc(mdev, copy_color, mem_planar_copy_color_4to1); else set_dev_proc(mdev, copy_color, mem_planar_copy_color); set_dev_proc(mdev, copy_alpha, gx_default_copy_alpha); set_dev_proc(mdev, copy_plane, mem_planar_copy_plane); set_dev_proc(mdev, strip_tile_rectangle, mem_planar_strip_tile_rectangle); set_dev_proc(mdev, strip_copy_rop, mem_planar_strip_copy_rop); set_dev_proc(mdev, get_bits_rectangle, mem_planar_get_bits_rectangle); set_dev_proc(mdev, dev_spec_op, mem_planar_dev_spec_op); } return 0; }
/* We separate device allocation and initialization at customer request. */ int gs_initialize_wordimagedevice(gx_device_memory * new_dev, const gs_matrix * pmat, uint width, uint height, const byte * colors, int colors_size, bool word_oriented, bool page_device, gs_memory_t * mem) { const gx_device_memory *proto_dev; int palette_count = colors_size; int num_components = 1; int pcount; int bits_per_pixel; float x_pixels_per_unit, y_pixels_per_unit; byte palette[256 * 3]; bool has_color; switch (colors_size) { case 3 * 2: palette_count = 2; num_components = 3; case 2: bits_per_pixel = 1; break; case 3 * 4: palette_count = 4; num_components = 3; case 4: bits_per_pixel = 2; break; case 3 * 16: palette_count = 16; num_components = 3; case 16: bits_per_pixel = 4; break; case 3 * 256: palette_count = 256; num_components = 3; case 256: bits_per_pixel = 8; break; case -16: bits_per_pixel = 16; palette_count = 0; break; case -24: bits_per_pixel = 24; palette_count = 0; break; case -32: bits_per_pixel = 32; palette_count = 0; break; default: return_error(gs_error_rangecheck); } proto_dev = (word_oriented ? gdev_mem_word_device_for_bits(bits_per_pixel) : gdev_mem_device_for_bits(bits_per_pixel)); if (proto_dev == 0) /* no suitable device */ return_error(gs_error_rangecheck); pcount = palette_count * 3; /* Check to make sure the palette contains white and black, */ /* and, if it has any colors, the six primaries. */ if (bits_per_pixel <= 8) { const byte *p; byte *q; int primary_mask = 0; int i; has_color = false; for (i = 0, p = colors, q = palette; i < palette_count; i++, q += 3 ) { int mask = 1; switch (num_components) { case 1: /* gray */ q[0] = q[1] = q[2] = *p++; break; default /* case 3 */ : /* RGB */ q[0] = p[0], q[1] = p[1], q[2] = p[2]; p += 3; } #define shift_mask(b,n)\ switch ( b ) { case 0xff: mask <<= n; case 0: break; default: mask = 0; } shift_mask(q[0], 4); shift_mask(q[1], 2); shift_mask(q[2], 1); #undef shift_mask primary_mask |= mask; if (q[0] != q[1] || q[0] != q[2]) has_color = true; } switch (primary_mask) { case 129: /* just black and white */ if (has_color) /* color but no primaries */ return_error(gs_error_rangecheck); case 255: /* full color */ break; default: return_error(gs_error_rangecheck); } } else has_color = true; /* * The initial transformation matrix must map 1 user unit to * 1/72". Let W and H be the width and height in pixels, and * assume the initial matrix is of the form [A 0 0 B X Y]. * Then the size of the image in user units is (W/|A|,H/|B|), * hence the size in inches is ((W/|A|)/72,(H/|B|)/72), so * the number of pixels per inch is * (W/((W/|A|)/72),H/((H/|B|)/72)), or (|A|*72,|B|*72). * Similarly, if the initial matrix is [0 A B 0 X Y] for a 90 * or 270 degree rotation, the size of the image in user * units is (W/|B|,H/|A|), so the pixels per inch are * (|B|*72,|A|*72). We forbid non-orthogonal transformation * matrices. */ if (is_fzero2(pmat->xy, pmat->yx)) x_pixels_per_unit = pmat->xx, y_pixels_per_unit = pmat->yy; else if (is_fzero2(pmat->xx, pmat->yy)) x_pixels_per_unit = pmat->yx, y_pixels_per_unit = pmat->xy; else return_error(gs_error_undefinedresult); /* All checks done, initialize the device. */ if (bits_per_pixel == 1) { /* Determine the polarity from the palette. */ gs_make_mem_device(new_dev, proto_dev, mem, (page_device ? 1 : -1), 0); /* This is somewhat bogus, but does the right thing */ /* in the only cases we care about. */ gdev_mem_mono_set_inverted(new_dev, (palette[0] | palette[1] | palette[2]) != 0); } else { byte *dev_palette = gs_alloc_string(mem, pcount, "gs_makeimagedevice(palette)"); if (dev_palette == 0) return_error(gs_error_VMerror); gs_make_mem_device(new_dev, proto_dev, mem, (page_device ? 1 : -1), 0); new_dev->palette.size = pcount; new_dev->palette.data = dev_palette; memcpy(dev_palette, palette, pcount); if (!has_color) { new_dev->color_info.num_components = 1; new_dev->color_info.max_color = 0; new_dev->color_info.dither_colors = 0; new_dev->color_info.gray_index = 0; } } /* Memory defice is always initialised as an internal device but */ /* this is an external device */ new_dev->retained = true; rc_init(new_dev, new_dev->memory, 1); new_dev->initial_matrix = *pmat; new_dev->MarginsHWResolution[0] = new_dev->HWResolution[0] = fabs(x_pixels_per_unit) * 72; new_dev->MarginsHWResolution[1] = new_dev->HWResolution[1] = fabs(y_pixels_per_unit) * 72; gx_device_set_width_height((gx_device *) new_dev, width, height); /* Set the ImagingBBox so we get a correct clipping region. */ { gs_rect bbox; bbox.p.x = 0; bbox.p.y = 0; bbox.q.x = width; bbox.q.y = height; gs_bbox_transform_inverse(&bbox, pmat, &bbox); new_dev->ImagingBBox[0] = bbox.p.x; new_dev->ImagingBBox[1] = bbox.p.y; new_dev->ImagingBBox[2] = bbox.q.x; new_dev->ImagingBBox[3] = bbox.q.y; new_dev->ImagingBBox_set = true; } /* The bitmap will be allocated when the device is opened. */ new_dev->is_open = false; new_dev->bitmap_memory = mem; return 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; }