示例#1
0
文件: gsdevmem.c 项目: aberg001/plan9
/* 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;
}
示例#2
0
/* Open the win_pr2 driver */
static int
win_pr2_open(gx_device * dev)
{
    int code;
    int depth;
    PRINTDLG pd;
    POINT offset;
    POINT size;
    float m[4];
    FILE *pfile;
    DOCINFO docinfo;
    float ratio = 1.0;
    
    win_pr2_copy_check(wdev);

    /* get a HDC for the printer */
    if ((wdev->win32_hdevmode) &&
	(wdev->win32_hdevnames)) {
	/* The user has already had the opportunity to choose the output */
	/* file interactively. Just use the specified parameters. */
	
	LPDEVMODE devmode = (LPDEVMODE) GlobalLock(wdev->win32_hdevmode);
	LPDEVNAMES devnames = (LPDEVNAMES) GlobalLock(wdev->win32_hdevnames);
	
	const char* driver = (char*)(devnames)+(devnames->wDriverOffset);
	const char* device = (char*)(devnames)+(devnames->wDeviceOffset);
	const char* output = (char*)(devnames)+(devnames->wOutputOffset);
	
	wdev->hdcprn = CreateDC(driver, device, output, devmode);
	
	GlobalUnlock(wdev->win32_hdevmode);
	GlobalUnlock(wdev->win32_hdevnames);
	
	if (wdev->hdcprn == NULL) {
	    return gs_error_Fatal;
	}
	
    } else if (!win_pr2_getdc(wdev)) {
	/* couldn't get a printer from -sOutputFile= */
	/* Prompt with dialog box */
	
	LPDEVMODE devmode = NULL;
	memset(&pd, 0, sizeof(pd));
	
	pd.lStructSize = sizeof(pd);
	pd.hwndOwner = PARENT_WINDOW;
	pd.Flags = PD_RETURNDC;
	pd.nMinPage = wdev->doc_page_begin;
	pd.nMaxPage = wdev->doc_page_end;
	pd.nFromPage = wdev->user_page_begin;
	pd.nToPage = wdev->user_page_end;
	pd.nCopies = wdev->user_copies;
	
	if (!PrintDlg(&pd)) {
	    /* device not opened - exit ghostscript */
	    return gs_error_Fatal;	/* exit Ghostscript cleanly */
	}
	
	devmode = GlobalLock(pd.hDevMode);
	win_pr2_update_dev(wdev,devmode);
	GlobalUnlock(pd.hDevMode);
	
	if (wdev->win32_hdevmode)
	    GlobalFree(wdev->win32_hdevmode);
	if (wdev->win32_hdevnames)
	    GlobalFree(wdev->win32_hdevnames);
	
	wdev->hdcprn = pd.hDC;
	wdev->win32_hdevmode = pd.hDevMode;
	wdev->win32_hdevnames = pd.hDevNames;
	
	pd.hDevMode = NULL;
	pd.hDevNames = NULL;
    }
    if (!(GetDeviceCaps(wdev->hdcprn, RASTERCAPS) != RC_DIBTODEV)) {
	errprintf(dev->memory, "Windows printer does not have RC_DIBTODEV\n");
	DeleteDC(wdev->hdcprn);
	return gs_error_limitcheck;
    }
    /* initialise printer, install abort proc */
    wdev->lpfnAbortProc = (DLGPROC) AbortProc2;
    SetAbortProc(wdev->hdcprn, (ABORTPROC) wdev->lpfnAbortProc);

    /*
     * Some versions of the Windows headers include lpszDatatype and fwType,
     * and some don't.  Since we want to set these fields to zero anyway,
     * we just start by zeroing the whole structure.
     */
    memset(&docinfo, 0, sizeof(docinfo));
    docinfo.cbSize = sizeof(docinfo);
    docinfo.lpszDocName = wdev->doc_name;
    /*docinfo.lpszOutput = NULL;*/
    /*docinfo.lpszDatatype = NULL;*/
    /*docinfo.fwType = 0;*/

    if (docinfo.lpszDocName[0] == 0) {
	docinfo.lpszDocName = "Ghostscript output";
    }

    if (StartDoc(wdev->hdcprn, &docinfo) <= 0) {
	errprintf(dev->memory,
                  "Printer StartDoc failed (error %08x)\n", GetLastError());
	DeleteDC(wdev->hdcprn);
	return gs_error_limitcheck;
    }
    
    dev->x_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSX);
    dev->y_pixels_per_inch = (float)GetDeviceCaps(wdev->hdcprn, LOGPIXELSY);
    
    wdev->ratio = 1;
    
    if (wdev->max_dpi > 50) {
	
	float dpi_x = dev->x_pixels_per_inch;
	float dpi_y = dev->y_pixels_per_inch;
	
	while ((dev->x_pixels_per_inch > wdev->max_dpi)
	    || (dev->y_pixels_per_inch > wdev->max_dpi)) {
	    ratio += 1.0;
	    wdev->ratio ++;
	    dev->x_pixels_per_inch = dpi_x / ratio;
	    dev->y_pixels_per_inch = dpi_y / ratio;
	}
    }
    
    size.x = GetDeviceCaps(wdev->hdcprn, PHYSICALWIDTH);
    size.y = GetDeviceCaps(wdev->hdcprn, PHYSICALHEIGHT);
    gx_device_set_width_height(dev, (int)(size.x / ratio), (int)(size.y / ratio));
    offset.x = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETX);
    offset.y = GetDeviceCaps(wdev->hdcprn, PHYSICALOFFSETY);
    
    /* m[] gives margins in inches */
    m[0] /*left   */ = offset.x / dev->x_pixels_per_inch / ratio;
    m[3] /*top    */ = offset.y / dev->y_pixels_per_inch / ratio;
    m[2] /*right  */ = (size.x - offset.x - GetDeviceCaps(wdev->hdcprn, HORZRES)) / dev->x_pixels_per_inch / ratio;
    m[1] /*bottom */ = (size.y - offset.y - GetDeviceCaps(wdev->hdcprn, VERTRES)) / dev->y_pixels_per_inch / ratio;
    gx_device_set_margins(dev, m, true);
    
    depth = dev->color_info.depth;
    if (depth == 0) {
	/* Set parameters that were unknown before opening device */
	/* Find out if the device supports color */
	/* We recognize 1, 4 (but use only 3), 8 and 24 bit color devices */
	depth = GetDeviceCaps(wdev->hdcprn, PLANES) * GetDeviceCaps(wdev->hdcprn, BITSPIXEL);
    }
    win_pr2_set_bpp(dev, depth);

    /* gdev_prn_open opens a temporary file which we don't want */
    /* so we specify the name now so we can delete it later */
    wdev->fname[0] = '\0';
    pfile = gp_open_scratch_file(dev->memory,
                                 gp_scratch_file_name_prefix,
				 wdev->fname, "wb");
    fclose(pfile);
    code = gdev_prn_open(dev);
    if ((code < 0) && wdev->fname[0])
        unlink(wdev->fname);

    if (!wdev->nocancel) {
	/* inform user of progress with dialog box and allow cancel */
	wdev->lpfnCancelProc = (DLGPROC) CancelDlgProc;
	wdev->hDlgModeless = CreateDialog(phInstance, "CancelDlgBox",
				    PARENT_WINDOW, wdev->lpfnCancelProc);
	ShowWindow(wdev->hDlgModeless, SW_HIDE);
    }
    return code;
};