Example #1
0
/* Open a printer device, conditionally setting it to be planar. */
int
gdev_prn_open_planar(gx_device *dev, bool upb)
{
    if (upb)
	gdev_prn_set_procs_planar(dev);
    return gdev_prn_open(dev);
}
Example #2
0
/* Open the render portion of a printer device in ASYNC (overlapped) mode.

 * This routine is always called by concrete device's xx_open_render_device
 * in lieu of gdev_prn_open.
 */
int
gdev_prn_async_render_open(gx_device_printer * prdev)
{
    gx_device *const pdev = (gx_device *) prdev;

    prdev->is_async_renderer = true;
    return gdev_prn_open(pdev);
}
Example #3
0
/* Open the printer, and set the margins. */
static int
md_open(gx_device *pdev)
{
	static const float md_margins[4] =
	 {	MD_SIDE_MARGIN, MD_BOTTOM_MARGIN,
		MD_SIDE_MARGIN, MD_TOP_MARGIN
	 };

	gx_device_set_margins(pdev, md_margins, true);
	return gdev_prn_open(pdev);
}
Example #4
0
/* Open the printer, adjusting the margins if necessary. */
static int
oki4w_open(gx_device *pdev)
{	/* Change the margins if necessary. */
	const float *m = 0;
	static const float m_a4[4] = { OKI4W_MARGINS_A4 };
	static const float m_letter[4] = { OKI4W_MARGINS_LETTER };
	m = (oki_paper_size(pdev) == 0x1a /*PAPER_SIZE_A4*/ ? m_a4 : m_letter);
	if ( m != 0 )
	  gx_device_set_margins(pdev, m, true);
	return gdev_prn_open(pdev);
}
Example #5
0
/* Open the printer, and set the margins. */
static int
sparc_open(gx_device *pdev)
{	/* Change the margins according to the paper size. */
        const float *m;
        static const float m_a4[4] = { SPARC_MARGINS_A4 };
        static const float m_letter[4] = { SPARC_MARGINS_LETTER };

        m = (pdev->height / pdev->y_pixels_per_inch >= 11.1 ? m_a4 : m_letter);
        gx_device_set_margins(pdev, m, true);
        return gdev_prn_open(pdev);
}
Example #6
0
static int
lp2000_open(gx_device * pdev)
{
    int xdpi = pdev->x_pixels_per_inch;
    int ydpi = pdev->y_pixels_per_inch;

    /* Resolution Check */
    if (xdpi != ydpi)
        return_error(gs_error_rangecheck);
    if (xdpi < 60 || xdpi > 300)
        return_error(gs_error_rangecheck);

    return gdev_prn_open(pdev);
}
Example #7
0
/* Open the printer, and set the margins. */
static int
npdl_open(gx_device * dev)
{
    int xdpi = dev->x_pixels_per_inch;
    int ydpi = dev->y_pixels_per_inch;

    /* Print Resolution Check */
    if (xdpi != ydpi)
        return_error(gs_error_rangecheck);
    else if (xdpi != 160 && xdpi != 200 && xdpi != 240 &&
             xdpi != 400 && xdpi != 600)
        return_error(gs_error_rangecheck);

    npdl_set_page_layout(dev);

    return gdev_prn_open(dev);
}
Example #8
0
/* delayed rasterizing. */
static int
pcx2up_open(gx_device * dev)
{
    gx_device_printer *pdev = (gx_device_printer *) dev;
    int code;
    gdev_prn_space_params save_params;

    save_params = pdev->space_params;
    pdev->space_params.MaxBitmap = 0;	/* force banding */
    pdev->space_params.band.BandWidth =
        dev->width * 2 + (int)(dev->HWResolution[0] * 2.0);
    pdev->space_params.band.BandBufferSpace = RENDER_BUFFER_SPACE;
    code = gdev_prn_open(dev);
    pdev->space_params = save_params;
    ((gx_device_2up *) dev)->have_odd_page = false;
    return code;
}
Example #9
0
static int
bj10e_open(gx_device *pdev)
{
        /* See bj200_open() */
        static const float a4_margins[4] =
         {	(float)BJ200_A4_SIDE_MARGIN, (float)BJ10E_BOTTOM_MARGIN,
                (float)BJ200_A4_SIDE_MARGIN, (float)BJ10E_TOP_MARGIN
         };
        static const float letter_margins[4] =
         {	(float)BJ200_LETTER_SIDE_MARGIN, (float)BJ10E_BOTTOM_MARGIN,
                (float)BJ200_LETTER_SIDE_MARGIN, (float)BJ10E_TOP_MARGIN
         };

        gx_device_set_margins(pdev,
                (pdev->width / pdev->x_pixels_per_inch <= 8.4 ?
                 a4_margins : letter_margins),
                true);
        return gdev_prn_open(pdev);
}
Example #10
0
static int
ml600_open(
        gx_device	*pdev)
{
        int code = gdev_prn_open(pdev);
        FILE	*prn_stream;

        /* dprintf("gdevml6: ml600_open called\n");*/

        if (code < 0)
                return code;

        code = gdev_prn_open_printer(pdev, true);
        if (code < 0)
                return code;

        prn_stream = ppdev->file;
        return ml_init(ppdev, prn_stream);
}
Example #11
0
static int
pngalpha_open(gx_device * pdev)
{
    gx_device_pngalpha *ppdev = (gx_device_pngalpha *)pdev;
    int code;
    /* We replace create_buf_device so we can replace copy_alpha 
     * for memory device, but not clist.
     */
    ppdev->printer_procs.buf_procs.create_buf_device = 
	pngalpha_create_buf_device;
    code = gdev_prn_open(pdev);
    /* We intercept fill_rectangle to translate "fill page with white"
     * into "fill page with transparent".  We then call the original
     * implementation of fill_page.
     */
    if ((ppdev->procs.fill_rectangle != pngalpha_fill_rectangle) &&
	(ppdev->procs.fill_rectangle != NULL)) {
	ppdev->orig_fill_rectangle = ppdev->procs.fill_rectangle;
        ppdev->procs.fill_rectangle = pngalpha_fill_rectangle;
    }
    return code;
}
Example #12
0
/* Open the printer, adjusting the margins if necessary. */
static int
hpjet_open(gx_device * pdev)
{				/* Change the margins if necessary. */
    gx_device_printer *const ppdev = (gx_device_printer *)pdev;
    const float *m = 0;
    bool move_origin = true;

    if (ppdev->printer_procs.print_page_copies == djet_print_page_copies ||
        ppdev->printer_procs.print_page_copies == djet500_print_page_copies
        ) {
        static const float m_a4[4] =
        {DESKJET_MARGINS_A4};
        static const float m_letter[4] =
        {DESKJET_MARGINS_LETTER};

        m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? m_a4 :
             m_letter);
    } else if (ppdev->printer_procs.print_page_copies == oce9050_print_page_copies ||
               ppdev->printer_procs.print_page_copies == lp2563_print_page_copies
        );
    else {			/* LaserJet */
        static const float m_a4[4] =
        {LASERJET_MARGINS_A4};
        static const float m_letter[4] =
        {LASERJET_MARGINS_LETTER};

        m = (gdev_pcl_paper_size(pdev) == PAPER_SIZE_A4 ? m_a4 :
             m_letter);
        move_origin = false;
    }
    if (m != 0)
        gx_device_set_margins(pdev, m, move_origin);
    /* If this is a LJIIID, enable Duplex. */
    if (ppdev->printer_procs.print_page_copies == ljet3d_print_page_copies)
        ppdev->Duplex = true, ppdev->Duplex_set = 0;
    if (ppdev->printer_procs.print_page_copies == ljet4d_print_page_copies)
        ppdev->Duplex = true, ppdev->Duplex_set = 0;
    return gdev_prn_open(pdev);
}
Example #13
0
/* Open the printer, writing the stream header. */
static int
ljet5_open(gx_device * pdev)
{
    int code = gdev_prn_open(pdev);

    if (code < 0)
	return code;
    code = gdev_prn_open_printer(pdev, true);
    if (code < 0)
	return code;
    {
	gx_device_printer *const ppdev = (gx_device_printer *)pdev;
	stream fs;
	stream *const s = &fs;
	byte buf[50];		/* arbitrary */

	s_init(s, pdev->memory);
	swrite_file(s, ppdev->file, buf, sizeof(buf));
	px_write_file_header(s, pdev);
	sflush(s);		/* don't close */
    }
    return 0;
}
Example #14
0
/* Open the printer, and set the margins. */
static int
bj200_open(gx_device *pdev)
{
        /* Change the margins according to the paper size.
           The top and bottom margins don't seem to depend on the
           page length, but on the paper handling mechanism;
           The side margins do depend on the paper width, as the
           printer centres the 8" print line on the page. */

        static const float a4_margins[4] =
         {	(float)BJ200_A4_SIDE_MARGIN, (float)BJ200_BOTTOM_MARGIN,
                (float)BJ200_A4_SIDE_MARGIN, (float)BJ200_TOP_MARGIN
         };
        static const float letter_margins[4] =
         {	(float)BJ200_LETTER_SIDE_MARGIN, (float)BJ200_BOTTOM_MARGIN,
                (float)BJ200_LETTER_SIDE_MARGIN, (float)BJ200_TOP_MARGIN
         };

        gx_device_set_margins(pdev,
                (pdev->width / pdev->x_pixels_per_inch <= 8.4 ?
                 a4_margins : letter_margins),
                true);
        return gdev_prn_open(pdev);
}
Example #15
0
/* Open the os2prn driver */
static int
os2prn_open(gx_device * dev)
{
    int code;
    PTIB pptib;
    PPIB pppib;
    DEVOPENSTRUC dop;
    ULONG cbBuf;
    ULONG cbNeeded;
    APIRET rc;
    PBYTE pbuf;
    char *p;
    SIZEL sizlPage;
    LONG caps[2];
    HCINFO hcinfo;
    LONG nforms;
    float m[4];
    int depth;
    FILE *pfile;
    int i;
    char *prefix = "\\\\spool\\";	/* 8 characters long */

    PRQINFO3 *pprq;
    gx_device_os2prn *oprn;

    oprn = opdev;

    if (DosGetInfoBlocks(&pptib, &pppib)) {
	errprintf("\nos2prn_open: Couldn't get pid\n");
	return gs_error_limitcheck;
    }
    if (pppib->pib_ultype != 3) {
	/* if caller is not PM app */
	errprintf("os2prn device can only be used from a PM application\n");
	return gs_error_limitcheck;
    }
    opdev->hab = WinQueryAnchorBlock(hwndtext);
    opdev->newframe = 0;

    if (os2prn_get_queue_list(dev->memory, &opdev->ql))
	return gs_error_limitcheck;

    if (opdev->queue_name[0] == '\0') {
	/* obtain printer name from filename */
	p = opdev->fname;
	for (i = 0; i < 8; i++) {
	    if (prefix[i] == '\\') {
		if ((*p != '\\') && (*p != '/'))
		    break;
	    } else if (tolower(*p) != prefix[i])
		break;
	    p++;
	}
	if (i == 8 && (strlen(p) != 0))
	    strcpy(opdev->queue_name, p);
    }
    pprq = NULL;
    if (opdev->queue_name[0] != '\0') {
	for (i = 0; i < opdev->ql.nqueues; i++) {
	    if (strcmp(opdev->ql.prq[i].pszName, opdev->queue_name) == 0) {
		pprq = &(opdev->ql.prq[i]);
		break;
	    }
	}
    } else {
	/* use default queue */
	pprq = &(opdev->ql.prq[opdev->ql.defqueue]);
    }
    if (pprq == (PRQINFO3 *) NULL) {
	errprintf("Invalid os2prn queue  name -sOS2QUEUE=\042%s\042\n", opdev->queue_name);
	errprintf("Valid device names are:\n");
	for (i = 0; i < opdev->ql.nqueues; i++) {
	    errprintf("  -sOS2QUEUE=\042%s\042\n", opdev->ql.prq[i].pszName);
	}
	return gs_error_rangecheck;
    }
    /* open printer device */
    memset(&dop, 0, sizeof(dop));
    dop.pszLogAddress = pprq->pszName;	/* queue name */
    p = strchr(pprq->pszDriverName, '.');
    if (p != (char *)NULL)
	*p = '\0';
    dop.pszDriverName = pprq->pszDriverName;
    dop.pszDataType = "PM_Q_STD";
    dop.pdriv = pprq->pDriverData;
    opdev->hdc = DevOpenDC(opdev->hab, OD_QUEUED, "*", 9L, (PDEVOPENDATA) & dop, (HDC) NULL);
    if (opdev->hdc == DEV_ERROR) {
	ERRORID eid = WinGetLastError(opdev->hab);

	errprintf("DevOpenDC for printer error 0x%x\n", eid);
	return gs_error_limitcheck;
    }
    os2prn_free_queue_list(dev->memory, &opdev->ql);

    /* find out resolution of printer */
    /* this is returned in pixels/metre */
    DevQueryCaps(opdev->hdc, CAPS_HORIZONTAL_RESOLUTION, 2, caps);
    dev->x_pixels_per_inch = (int)(caps[0] * 0.0254 + 0.5);
    dev->y_pixels_per_inch = (int)(caps[1] * 0.0254 + 0.5);

    /* find out page size and margins */
    /* these are returned in millimetres */
    nforms = DevQueryHardcopyCaps(opdev->hdc, 0, 0, &hcinfo);
    for (i = 0; i < nforms; i++) {
	DevQueryHardcopyCaps(opdev->hdc, i, 1, &hcinfo);
	if (hcinfo.flAttributes & HCAPS_CURRENT)
	    break;		/* this is the default page size */
    }
    /* GS size is in pixels */
    dev->width = hcinfo.cx * caps[0] / 1000;
    dev->height = hcinfo.cy * caps[1] / 1000;
    /* GS margins are in inches */
    m[0] /*left */  = hcinfo.xLeftClip / 25.4;
    m[1] /*bottom */  = hcinfo.yBottomClip / 25.4;
    m[2] /*right */  = (hcinfo.cx - hcinfo.xRightClip) / 25.4;
    m[3] /*top */  = (hcinfo.cy - hcinfo.yTopClip) / 25.4;
    gx_device_set_margins(dev, m, true);
    /* set bounding box in pixels for later drawing */
    opdev->clipbox[0] = (int)(hcinfo.xLeftClip / 25.4 * dev->x_pixels_per_inch + 1);	/* round inwards */
    opdev->clipbox[1] = (int)(hcinfo.yBottomClip / 25.4 * dev->y_pixels_per_inch + 1);
    opdev->clipbox[2] = (int)(hcinfo.xRightClip / 25.4 * dev->x_pixels_per_inch);
    opdev->clipbox[3] = (int)(hcinfo.yTopClip / 25.4 * dev->y_pixels_per_inch);

    /* get presentation space */
    sizlPage.cx = dev->width;
    sizlPage.cy = dev->height;
    opdev->hps = GpiCreatePS(opdev->hab, opdev->hdc, &sizlPage,
			 PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);

    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 bit monochrome and 24 bit color devices */
	DevQueryCaps(opdev->hdc, CAPS_COLOR_PLANES, 2, caps);
	/* caps[0] is #color planes, caps[1] is #bits per plane */
	depth = caps[0] * caps[1];
	if (depth > 1)
	    depth = 24;
    }
    os2prn_set_bpp(dev, depth);

    /* create a memory DC compatible with printer */
    opdev->hdcMem = DevOpenDC(opdev->hab, OD_MEMORY, "*", 0L, NULL, opdev->hdc);
    if (opdev->hdcMem == DEV_ERROR) {
	ERRORID eid = WinGetLastError(opdev->hab);

	errprintf("DevOpenDC for memory error 0x%x\n", eid);
	return gs_error_limitcheck;
    }
    sizlPage.cx = dev->width;
    sizlPage.cy = dev->height;
    opdev->hpsMem = GpiCreatePS(opdev->hab, opdev->hdcMem, &sizlPage,
			 PU_PELS | GPIF_DEFAULT | GPIT_NORMAL | GPIA_ASSOC);
    if (opdev->hpsMem == GPI_ERROR) {
	ERRORID eid = WinGetLastError(opdev->hab);

	errprintf("GpiCreatePS for memory error 0x%x\n", eid);
	return gs_error_limitcheck;
    }
    if (DevEscape(opdev->hdc, DEVESC_STARTDOC, (LONG) strlen(gs_product),
		  (char *)gs_product, NULL, NULL) == DEVESC_ERROR) {
	ERRORID eid = WinGetLastError(opdev->hab);

	errprintf("DEVESC_STARTDOC error 0x%x\n", eid);
	return gs_error_limitcheck;
    }
    /* gdev_prn_open opens a temporary file which we don't want */
    /* so we specify the name now so we can delete it later */
    pfile = gp_open_scratch_file(gp_scratch_file_name_prefix,
				 opdev->fname, "wb");
    fclose(pfile);
    code = gdev_prn_open(dev);

    return code;
}
Example #16
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;
};
Example #17
0
/*
 * Open this printer device in ASYNC (overlapped) mode.
 * This routine must always called by the concrete device's xx_open routine
 * in lieu of gdev_prn_open.
 */
int
gdev_prn_async_write_open(gx_device_printer * pwdev, int max_raster,
                          int min_band_height, int max_src_image_row)
{
    gx_device *const pdev = (gx_device *) pwdev;
    int code;
    bool writer_is_open = false;
    gx_device_clist_writer *const pcwdev =
        &((gx_device_clist *) pwdev)->writer;
    gx_device_clist_reader *pcrdev = 0;
    gx_device_printer *prdev = 0;
    gs_memory_t *render_memory = 0;	/* renderer's mem allocator */

    pwdev->page_queue = 0;
    pwdev->bandlist_memory = 0;
    pwdev->async_renderer = 0;

    /* allocate & init render memory */
    /* The big memory consumers are: */
    /* - the buffer used to read images from the command list */
    /* - buffer used by gx_real_default_strip_copy_rop() */
    /* - line pointer tables for memory devices used in plane extraction */
    /* - the halftone cache */
    /* - the band rendering buffer */
    /* The * 2's in the next statement are a ****** HACK ****** to deal with */
    /* sandbars in the memory manager. */
    if ((code = alloc_render_memory(&render_memory,
            pwdev->memory->non_gc_memory, RendererAllocationOverheadBytes + max_raster
                                    /* the first * 2 is not a hack */
                   + (max_raster + sizeof(void *) * 2) * min_band_height
                   + max_src_image_row + gx_ht_cache_default_bits_size() * 2)) < 0)
             goto open_err;

    /* Alloc & init bandlist allocators */
    /* Bandlist mem is threadsafe & common to rdr/wtr, so it's used */
    /* for page queue & cmd list buffers. */
    if ((code = alloc_bandlist_memory
         (&pwdev->bandlist_memory, pwdev->memory->non_gc_memory)) < 0)
        goto open_err;

    /* Dictate banding parameters for both renderer & writer */
    /* Protect from user change, since user changing these won't be */
    /* detected, ergo the necessary close/reallocate/open wouldn't happen. */
    pwdev->space_params.banding_type = BandingAlways;
    pwdev->space_params.params_are_read_only = true;

    /* Make a copy of device for use as rendering device b4 opening writer */
    code = gs_copydevice((gx_device **) & prdev, pdev, render_memory);
    pcrdev = &((gx_device_clist *) prdev)->reader;
    if (code < 0)
        goto open_err;

    /* -------------- Open cmd list WRITER instance of device ------- */
    /* --------------------------------------------------------------- */
    /* This is wrong, because it causes the same thing in the renderer */
    pwdev->OpenOutputFile = 0;	/* Don't open output file in writer */

    /* Hack: set this vector to tell gdev_prn_open to allocate for async rendering */
    pwdev->free_up_bandlist_memory = &gdev_prn_async_write_free_up_bandlist_memory;

    /* prevent clist writer from queuing path graphics & force it to split images */
    pwdev->clist_disable_mask |= clist_disable_fill_path |
        clist_disable_stroke_path | clist_disable_complex_clip |
        clist_disable_nonrect_hl_image | clist_disable_pass_thru_params;

    if ((code = gdev_prn_open(pdev)) >= 0) {
        writer_is_open = true;

        /* set up constant async-specific fields in device */
        reinit_printer_into_printera(pwdev);

        /* keep ptr to renderer device */
        pwdev->async_renderer = prdev;

        /* Allocate the page queue, then initialize it */
        /* Use bandlist memory since it's shared between rdr & wtr */
        if ((pwdev->page_queue = gx_page_queue_alloc(pwdev->bandlist_memory)) == 0)
            code = gs_note_error(gs_error_VMerror);
        else
            /* Allocate from clist allocator since it is thread-safe */
            code = gx_page_queue_init(pwdev->page_queue, pwdev->bandlist_memory);
    }
    /* ------------ Open cmd list RENDERER instance of device ------- */
    /* --------------------------------------------------------------- */
    if (code >= 0) {
        gx_semaphore_t *open_semaphore;

        /* Force writer's actual band params into reader's requested params */
        prdev->space_params.band = pcwdev->page_info.band_params;

        /* copydevice has already set up prdev->memory = render_memory */
        /* prdev->bandlist_memory = pwdev->bandlist_memory; */
        prdev->buffer_memory = prdev->memory;

        /* enable renderer to accept changes to params computed by writer */
        prdev->space_params.params_are_read_only = false;

        /* page queue is common to both devices */
        prdev->page_queue = pwdev->page_queue;

        /* Start renderer thread & wait for its successful open of device */
        if (!(open_semaphore = gx_semaphore_alloc(prdev->memory)))
            code = gs_note_error(gs_error_VMerror);
        else {
            gdev_prn_start_render_params thread_params;

            thread_params.writer_device = pwdev;
            thread_params.open_semaphore = open_semaphore;
            thread_params.open_code = 0;
            code = (*pwdev->printer_procs.start_render_thread)
                (&thread_params);
            if (code >= 0)
                gx_semaphore_wait(open_semaphore);
            code = thread_params.open_code;
            gx_semaphore_free(open_semaphore);
        }
    }
    /* ----- Set the recovery procedure for the mem allocator ----- */
    if (code >= 0) {
        gs_memory_retrying_set_recover(
                (gs_memory_retrying_t *)pwdev->memory->non_gc_memory,
                prna_mem_recover,
                (void *)pcwdev
            );
    }
    /* --------------------- Wrap up --------------------------------- */
    /* --------------------------------------------------------------- */
    if (code < 0) {
open_err:
        /* error mop-up */
        if (render_memory && !prdev)
            free_render_memory(render_memory);

        gdev_prn_dealloc(pwdev);
        if (writer_is_open) {
            gdev_prn_close(pdev);
            pwdev->free_up_bandlist_memory = 0;
        }
    }
    return code;
}
Example #18
0
int eprn_set_page_layout(eprn_Device *dev)
{
  bool
    no_match = true,
     /* Are the requested flags supported for some size? */
    landscape = dev->MediaSize[0] > dev->MediaSize[1];
     /* It's not documented, but 'MediaSize' is the requested "PageSize" page
        device parameter value and hence is to be interpreted in default (not
        default default!) user space. */
  const char *epref = dev->eprn.CUPS_messages? CUPS_ERRPREF: "";
  const eprn_CustomPageDescription
    *best_cmatch = NULL;        /* best custom page size match */
  eprn_Eprn
    *eprn = &dev->eprn;
  const eprn_PageDescription
    *best_cdmatch = NULL,     /* best custom page size match in discrete list*/
    *best_dmatch = NULL,        /* best discrete match */
    *pd;                        /* loop variable */
  float
    /* Page width and height in bp with w <= h (in a moment): */
    w = dev->MediaSize[0],
    h = dev->MediaSize[1],
    /* pixmap device space margins in bp (canonical order): */
    margins[4];
  int
    quarters;
  ms_MediaCode
    desired = eprn->desired_flags;

#ifdef EPRN_TRACE
  if_debug3(EPRN_TRACE_CHAR,
    "! eprn_set_page_layout(): PageSize = [%.0f %.0f], "
      "desired_flags = 0x%04X.\n",
    dev->MediaSize[0], dev->MediaSize[1], (unsigned int)desired);
#endif

  /* Ensure w <= h */
  if (w > h) {
    float temp;
    temp = w; w = h; h = temp;
    /* This has effectively split 'MediaSize[]' into 'w', 'h' and 'landscape'.
     */
  }

  /* Initialization of primary return value */
  eprn->code = ms_none;

  /* Put the LeadingEdge value into the desired flag pattern if it's set */
  if (eprn->leading_edge_set) {
    if (eprn->default_orientation % 2 == 0)     /* true on short edge first */
      desired &= ~MS_TRANSVERSE_FLAG;
    else
      desired |= MS_TRANSVERSE_FLAG;
  }

  /* Find best match in discrete sizes */
  if (eprn->media_overrides == NULL) pd = eprn->cap->sizes;
  else pd = eprn->media_overrides;
  while (pd->code != ms_none) {
    const ms_SizeDescription *ms = ms_find_size_from_code(pd->code);
    if (ms->dimen[0] > 0.0 /* ignore variable sizes */ &&
        fabs(w - ms->dimen[0])  <= 5.0 &&
        fabs(h - ms->dimen[1]) <= 5.0) {
       /* The size does match at 5 bp tolerance. This value has been chosen
          arbitrarily to be equal to PostScript's PageSize matching tolerance
          during media selection. The tolerance should really be that at which
          the printer in question distinguishes between sizes or smaller than
          that in order to at least prevent printing on unsupported sizes.
        */
      if (best_dmatch == NULL ||
          better_flag_match(desired, eprn->optional_flags, best_dmatch->code,
            pd->code))
        best_dmatch = pd;
      if (flag_match(desired, eprn->optional_flags, pd->code))
        no_match = false;
    }
    pd++;
  }

  /* Next find the best match among the custom size descriptions */
  if (eprn->cap->custom != NULL) {
    const eprn_CustomPageDescription *cp = eprn->cap->custom;

    /* First check whether the size is in the supported range */
    while (cp->width_max > 0.0) {
      if (cp->width_min  <= w && w <= cp->width_max &&
          cp->height_min <= h && h <= cp->height_max) {
        /* The size does match. */
        if (best_cmatch == NULL ||
            better_flag_match(desired, eprn->optional_flags, best_cmatch->code,
              cp->code))
          best_cmatch = cp;
        if (eprn->media_overrides == NULL &&
            flag_match(desired, eprn->optional_flags, cp->code))
          no_match = false;
      }
      cp++;
    }

    /* If we have read a media configuration file, the flags to be matched
       must be sought in 'media_overrides'. */
    if (best_cmatch != NULL && eprn->media_overrides != NULL) {
      for (pd = eprn->media_overrides; pd->code != ms_none; pd++) {
        if (ms_without_flags(pd->code) == ms_CustomPageSize) {
          if (best_cdmatch == NULL ||
              better_flag_match(desired, eprn->optional_flags,
                best_cdmatch->code, pd->code))
            best_cdmatch = pd;
          if (flag_match(desired, eprn->optional_flags, pd->code))
            no_match = false;
        }
      }
    }
  }

  /*  Now the 'best_*match' variables indicate for each of the categories of
      page descriptions to which extent the size is supported at all (non-NULL
      value) and what the best flag match in the category is. Here we now check
      for NULL values, i.e., size matches. */
  if (best_dmatch == NULL) {
    /* No discrete match */
    if (best_cmatch == NULL) {
      /* No match at all. */
      eprintf3("%s" ERRPREF
        "This document requests a page size of %.0f x %.0f bp.\n",
           epref, dev->MediaSize[0], dev->MediaSize[1]);
      if (eprn->cap->custom == NULL) {
        /* The printer does not support custom page sizes */
        if (eprn->media_overrides != NULL)
          eprintf1(
            "%s  The media configuration file does not contain an entry for "
              " this size.\n", epref);
        else
          eprintf2("%s  This size is not supported by the %s.\n",
            epref, eprn->cap->name);
      }
      else
        eprintf3(
          "%s  This size is not supported as a discrete size and it exceeds "
            "the\n"
          "%s  custom page size limits for the %s.\n",
          epref, epref, eprn->cap->name);
      return -1;
    }
    if (eprn->media_overrides != NULL && best_cdmatch == NULL) {
      eprintf6("%s" ERRPREF
        "This document requests a page size of %.0f x %.0f bp\n"
        "%s  but there is no entry for this size in the "
          "media configuration file\n"
        "%s  %s.\n",
        epref, dev->MediaSize[0], dev->MediaSize[1], epref, epref,
        eprn->media_file);
      return -1;
    }
  }
  /* Now we have: best_dmatch != NULL || best_cmatch != NULL &&
     (eprn->media_overrides == NULL || best_cdmatch != NULL). */

  /* Find a flag match among the size matches found so far */
  {
    ms_MediaCode custom_code = ms_none;
      /* best custom page size match (either from cmatch or dcmatch) */
    if (best_cmatch != NULL &&
        (eprn->media_overrides == NULL || best_cdmatch != NULL))
      custom_code = (eprn->media_overrides == NULL?
        best_cmatch->code: best_cdmatch->code);

    if (best_dmatch == NULL ||
        best_cmatch != NULL &&
          better_flag_match(desired, eprn->optional_flags, best_dmatch->code,
            custom_code)) {
      if (flag_match(desired, eprn->optional_flags, custom_code)) {
        if (eprn->media_overrides == NULL) {
          eprn->code = best_cmatch->code;
          margins[0] = best_cmatch->left;
          margins[1] = best_cmatch->bottom;
          margins[2] = best_cmatch->right;
          margins[3] = best_cmatch->top;
        }
        else {
          eprn->code = best_cdmatch->code;
          margins[0] = best_cdmatch->left;
          margins[1] = best_cdmatch->bottom;
          margins[2] = best_cdmatch->right;
          margins[3] = best_cdmatch->top;
        }
      }
    }
    else {
      if (flag_match(desired, eprn->optional_flags, best_dmatch->code)) {
        eprn->code = best_dmatch->code;
        margins[0] = best_dmatch->left;
        margins[1] = best_dmatch->bottom;
        margins[2] = best_dmatch->right;
        margins[3] = best_dmatch->top;
      }
    }
  }
  /* If we've found a match, 'code' is no longer 'ms_none'. */
  if (eprn->code == ms_none) {
    eprn_flag_mismatch(eprn, no_match);
    return -1;
  }

  /* Adapt the orientation of default default user space if not prescribed */
  if (!eprn->leading_edge_set) {
    if (eprn->code & MS_TRANSVERSE_FLAG) eprn->default_orientation = 3;
     /* This leads to 0 if landscape orientation is requested. */
    else eprn->default_orientation = 0;
  }

  /*
    Now 'eprn->default_orientation % 2' describes the sheet's orientation in
    pixmap device space. If this does not agree with the width and height
    values in the device instance, we'll have to adapt them.
    This is only necessary if there is a significant difference between width
    and height.
   */
  if (fabs(w - h) > 1 /* arbitrary */ &&
    (eprn->default_orientation % 2 == 0) !=
        (dev->width/dev->HWResolution[0] <= dev->height/dev->HWResolution[1])) {
    bool reallocate = false;

#ifdef EPRN_TRACE
    if_debug0(EPRN_TRACE_CHAR,
      "! eprn_set_page_layout(): width-height change is necessary.\n");
#endif

    /* Free old storage if the device is open */
    if (dev->is_open) {
#ifdef EPRN_TRACE
      if_debug0(EPRN_TRACE_CHAR, "! eprn_set_page_layout(): Device is open.\n");
#endif
      reallocate = true;
       /* One could try and call the allocation/reallocation routines of the
          prn device directly, but they are not available in older ghostscript
          versions and this method is safer anyway because it relies on a
          documented API. */
      gdev_prn_close((gx_device *)dev);         /* ignore the result */
    }

    /*  Now set width and height via gx_device_set_media_size(). This function
        sets 'MediaSize[]', 'width', and 'height' based on the assumption that
        default user space has a y axis which is vertical in pixmap device
        space. This may be wrong and we have to fix it. Because fixing
        'MediaSize[]' is simpler, gx_device_set_media_size() is called such
        that it gives the correct values for 'width' and 'height'. */
    if (eprn->default_orientation % 2 == 0) {
      /* portrait orientation of the sheet in pixmap device space */
      gx_device_set_media_size((gx_device *)dev, w, h);
      if (landscape) {
        dev->MediaSize[0] = h;
        dev->MediaSize[1] = w;
      }
    }
    else {
      /* landscape orientation in pixmap device space (transverse) */
      gx_device_set_media_size((gx_device *)dev, h, w);
      if (!landscape) {
        dev->MediaSize[0] = w;
        dev->MediaSize[1] = h;
      }
    }

    /* If the device is/was open, reallocate storage */
    if (reallocate) {
      int rc;

      rc = gdev_prn_open((gx_device *)dev);
      if (rc < 0) {
        eprintf2("%s" ERRPREF
          "Failure of gdev_prn_open(), code is %d.\n",
          epref, rc);
        return rc;
      }
    }
  }

  /* Increase the bottom margin for coloured modes except if it is exactly
     zero */
  if (eprn->colour_model != eprn_DeviceGray && margins[1] != 0.0)
    margins[1] += eprn->cap->bottom_increment;

  /* Number of +90-degree rotations needed for default user space: */
  quarters = eprn->default_orientation;
  if (landscape) quarters = (quarters + 1)%4;

  /* Store the top and left margins in the device structure for use by
     eprn_get_initial_matrix() and set the margins of the printable area if
     we may.
     gx_device_set_margins() (see gsdevice.c) copies the margins[] array to
     HWMargins[] which is presumably to be interpreted in default user space
     (see gs_initclip() in gspath.c), and if its second argument is true it
     also modifies the offset variable Margins[]. The first property means
     that gx_device_set_margins() can only be used if default user space and
     pixmap device space have the same "up" direction, and the second
     appropriates a parameter which is intended for the user.
  */
  if (eprn->keep_margins) {
    eprn->down_shift  = dev->HWMargins[3 - quarters];
    eprn->right_shift = dev->HWMargins[(4 - quarters)%4];
  }
  else {
    int j;

    eprn->down_shift  = margins[3];
    eprn->right_shift = margins[0];

    if (quarters != 0) {
       /* The "canonical margin order" for ghostscript is left, bottom, right,
          top. Hence for, e.g., a +90-degree rotation ('quarters' is 1) of
          default user space with respect to pixmap device space the left
          margin (index 0) in default user space is actually the bottom margin
          (index 1) in pixmap device space, the bottom margin is the right one,
          etc.
        */
      for (j = 0; j < 4; j++) dev->HWMargins[j] = margins[(j+quarters)%4];
      /* 'HWMargins[]' is in bp (see gxdevcli.h) */
    }
    else {
      /* Convert to inches */
      for (j = 0; j < 4; j++) margins[j] /= BP_PER_IN;

      gx_device_set_margins((gx_device *)dev, margins, false);
       /* Of course, I could set HWMargins[] directly also in this case. This
          way is however less prone to break on possible future incompatible
          changes to ghostscript and it covers the most frequent case (portrait
          and short edge first). */
    }
  }

  return 0;
}
Example #19
0
int eprn_open_device(gx_device *device)
{
  eprn_Eprn *eprn = &((eprn_Device *)device)->eprn;
  const char *epref = eprn->CUPS_messages? CUPS_ERRPREF: "";
  int rc;

#ifdef EPRN_TRACE
  if_debug0(EPRN_TRACE_CHAR, "! eprn_open_device()...\n");
#endif

  /* Checks on page size and determination of derived values */
  if (eprn_set_page_layout((eprn_Device *)device) != 0)
    return_error(gs_error_rangecheck);

  /* Check the rendering parameters */
  if (eprn_check_colour_info(eprn->cap->colour_info, &eprn->colour_model,
      &device->HWResolution[0], &device->HWResolution[1],
      &eprn->black_levels, &eprn->non_black_levels) != 0) {
    gs_param_string str;

    eprintf1("%s" ERRPREF "The requested combination of colour model (",
      epref);
    str.size = 0;
    if (eprn_get_string(eprn->colour_model, eprn_colour_model_list, &str) != 0)
      assert(0); /* Bug. No harm on NDEBUG because I've just set the size. */
    errwrite(device->memory, (const char *)str.data, str.size * sizeof(str.data[0]));
    eprintf7("),\n"
      "%s  resolution (%gx%g ppi) and intensity levels (%d, %d) is\n"
      "%s  not supported by the %s.\n",
      epref, device->HWResolution[0], device->HWResolution[1],
      eprn->black_levels, eprn->non_black_levels, epref, eprn->cap->name);
    return_error(gs_error_rangecheck);
  }

  /* Initialization for colour rendering */
  if (device->color_info.num_components == 4) {
    /* Native colour space is 'DeviceCMYK' */
    set_dev_proc(device, map_rgb_color, NULL);

    if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
      set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color_max);
    else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1)
      set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color_flex);
    else
      set_dev_proc(device, map_cmyk_color, &eprn_map_cmyk_color);

    if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
      set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_max);
    else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1)
      set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_flex);
    else
      set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K);

  }
  else {
    set_dev_proc(device, map_cmyk_color, NULL);

    if (eprn->colour_model == eprn_DeviceRGB) {
      if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB_max);
      else if (device->color_info.max_color > 1)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB_flex);
      else
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_RGB);
    } else {
      if (eprn->intensity_rendering == eprn_IR_FloydSteinberg)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_max);
      else if (device->color_info.max_gray > 1 || device->color_info.max_color > 1)
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K_flex);
      else
        set_dev_proc(device, map_rgb_color, &eprn_map_rgb_color_for_CMY_or_K);
    }
  }
  eprn->output_planes = eprn_bits_for_levels(eprn->black_levels) +
    3 * eprn_bits_for_levels(eprn->non_black_levels);

#if !defined(GS_REVISION) || GS_REVISION >= 600
  /*  According to my understanding, the following call should be superfluous
      (because the colour mapping functions may not be called while the device
      is closed) and I am also not aware of any situation where it does make a
      difference. It shouldn't do any harm, though, and I feel safer with it :-)
  */
  gx_device_decache_colors(device);
#endif

#ifndef EPRN_NO_PAGECOUNTFILE
  /* Read the page count value */
  if (eprn->pagecount_file != NULL) {
    unsigned long count;
    if (pcf_getcount(eprn->pagecount_file, &count) == 0)
      device->PageCount = count;
       /* unsigned to signed. The C standard permits
          an implementation to generate an overflow indication if the value is
          too large. I consider this to mean that the type of 'PageCount' is
          inappropriate :-). Note that eprn does not use 'PageCount' for
          updating the file. */
    else {
      /* pcf_getcount() has issued an error message. */
      eprintf(
        "  No further attempts will be made to access the page count file.\n");
      gs_free(device->memory->non_gc_memory, eprn->pagecount_file, strlen(eprn->pagecount_file) + 1,
        sizeof(char), "eprn_open_device");
      eprn->pagecount_file = NULL;
    }
  }
#endif  /* !EPRN_NO_PAGECOUNTFILE */

  /* Open the "prn" device part */
  if ((rc = gdev_prn_open(device)) != 0) return rc;

  /* Just in case a previous open call failed in a derived device (note that
     'octets_per_line' is still the same as then): */
  if (eprn->scan_line.str != NULL)
    gs_free(device->memory->non_gc_memory, eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet),
      "eprn_open_device");
  if (eprn->next_scan_line.str != NULL) {
    gs_free(device->memory->non_gc_memory, eprn->next_scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet),
      "eprn_open_device");
    eprn->next_scan_line.str = NULL;
  }

  /* Calls which might depend on prn having been initialized */
  eprn->octets_per_line = gdev_prn_raster((gx_device_printer *)device);
  eprn->scan_line.str = (eprn_Octet *) gs_malloc(device->memory->non_gc_memory, eprn->octets_per_line,
    sizeof(eprn_Octet), "eprn_open_device");
  if (eprn->intensity_rendering == eprn_IR_FloydSteinberg) {
    eprn->next_scan_line.str = (eprn_Octet *) gs_malloc(device->memory->non_gc_memory, eprn->octets_per_line,
      sizeof(eprn_Octet), "eprn_open_device");
    if (eprn->next_scan_line.str == NULL && eprn->scan_line.str != NULL) {
      gs_free(device->memory->non_gc_memory, eprn->scan_line.str, eprn->octets_per_line, sizeof(eprn_Octet),
        "eprn_open_device");
      eprn->scan_line.str = NULL;
    }
  }
  if (eprn->scan_line.str == NULL) {
    eprintf1("%s" ERRPREF
      "Memory allocation failure from gs_malloc() in eprn_open_device().\n",
      epref);
    return_error(gs_error_VMerror);
  }

  return rc;
}
Example #20
0
static int
npdl_set_page_layout(gx_device * dev)
{
    int code;
    float margins[4];

    /* Change the margins according to the paper size. */
    switch (npdl_get_paper_size(dev)) {
        case PAPER_SIZE_A3:
            if (dev->MediaSize[0] > dev->MediaSize[1]) {	/* Landscape */
                margins[0] = L_MARGIN_A3;
                margins[1] = B_MARGIN_A3;
                margins[2] = R_MARGIN_A3;
                margins[3] = T_MARGIN_A3;
            } else {		/* Portrait */
                margins[1] = L_MARGIN_A3;
                margins[2] = B_MARGIN_A3;
                margins[3] = R_MARGIN_A3;
                margins[0] = T_MARGIN_A3;
            }
            break;
        case PAPER_SIZE_A5:
            if (dev->MediaSize[0] > dev->MediaSize[1]) {	/* Landscape */
                margins[0] = L_MARGIN_A5;
                margins[1] = B_MARGIN_A5;
                margins[2] = R_MARGIN_A5;
                margins[3] = T_MARGIN_A5;
            } else {		/* Portrait */
                margins[1] = L_MARGIN_A5;
                margins[2] = B_MARGIN_A5;
                margins[3] = R_MARGIN_A5;
                margins[0] = T_MARGIN_A5;
            }
            break;
        case PAPER_SIZE_B5:
            if (dev->MediaSize[0] > dev->MediaSize[1]) {	/* Landscape */
                margins[1] = L_MARGIN_B5;
                margins[2] = B_MARGIN_B5;
                margins[3] = R_MARGIN_B5;
                margins[0] = T_MARGIN_B5;
            } else {		/* Portrait */
                margins[0] = L_MARGIN_B5;
                margins[1] = B_MARGIN_B5;
                margins[2] = R_MARGIN_B5;
                margins[3] = T_MARGIN_B5;
            }
            break;
        case PAPER_SIZE_LETTER:
            if (dev->MediaSize[0] > dev->MediaSize[1]) {	/* Landscape */
                margins[1] = L_MARGIN_LETTER;
                margins[2] = B_MARGIN_LETTER;
                margins[3] = R_MARGIN_LETTER;
                margins[0] = T_MARGIN_LETTER;
            } else {		/* Portrait */
                margins[0] = L_MARGIN_LETTER;
                margins[1] = B_MARGIN_LETTER;
                margins[2] = R_MARGIN_LETTER;
                margins[3] = T_MARGIN_LETTER;
            }
            break;
        case PAPER_SIZE_POSTCARD:
            if (dev->MediaSize[0] > dev->MediaSize[1]) {	/* Landscape */
                margins[1] = L_MARGIN_POSTCARD;
                margins[2] = B_MARGIN_POSTCARD;
                margins[3] = R_MARGIN_POSTCARD;
                margins[0] = T_MARGIN_POSTCARD;
            } else {		/* Portrait */
                margins[0] = L_MARGIN_POSTCARD;
                margins[1] = B_MARGIN_POSTCARD;
                margins[2] = R_MARGIN_POSTCARD;
                margins[3] = T_MARGIN_POSTCARD;
            }
            break;
        case PAPER_SIZE_ENV4:
        case PAPER_SIZE_BPOSTCARD:
                margins[1] = L_MARGIN_ENV4;
                margins[2] = B_MARGIN_ENV4;
                margins[3] = R_MARGIN_ENV4;
                margins[0] = T_MARGIN_ENV4;
            break;
        default:		/* A4 */
            if (dev->MediaSize[0] > dev->MediaSize[1]) {	/* Landscape */
                margins[1] = L_MARGIN_A4;
                margins[2] = B_MARGIN_A4;
                margins[3] = R_MARGIN_A4;
                margins[0] = T_MARGIN_A4;
            } else {		/* Portrait */
                margins[0] = L_MARGIN_A4;
                margins[1] = B_MARGIN_A4;
                margins[2] = R_MARGIN_A4;
                margins[3] = T_MARGIN_A4;
            }
            break;
    }
    gx_device_set_margins(dev, margins, true);
    if (dev->is_open) {
        gdev_prn_close(dev);
        code = gdev_prn_open(dev);
        if (code < 0)
            return code;
    }
    return 0;
}