123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302 |
- /* Copyright (C) 1992, 1993, 1994, 1996, 1997, 1998, 1999, 2000 Aladdin Enterprises. All rights reserved.
-
- This software is provided AS-IS with no warranty, either express or
- implied.
-
- This software is distributed under license and may not be copied,
- modified or distributed except as expressly authorized under the terms
- of the license contained in the file LICENSE in this distribution.
-
- For more information about licensing, please refer to
- http://www.ghostscript.com/licensing/. For information on
- commercial licensing, go to http://www.artifex.com/licensing/ or
- contact Artifex Software, Inc., 101 Lucas Valley Road #110,
- San Rafael, CA 94903, U.S.A., +1(415)492-9861.
- */
- /* $Id: gdevpm.c,v 1.10 2004/09/20 22:14:59 dan Exp $ */
- /*
- * OS/2 Presentation manager driver
- *
- * By Russell Lang (based on gdevmswn.c and gdevwdib.c)
- *
- * If Ghostscript is a PM application, stdin/stdout are not
- * provided and so no text window is available.
- * If Ghostscript is a windowed text application, a message queue
- * can't be created so a PM window for graphics can't be created.
- * The solution used here is to have two programs - gsos2.exe is a
- * text application and the outboard PM driver is gspmdrv.exe.
- * Another solution may be to make Ghostscript a PM application
- * and use VIO calls to provide a text window.
- *
- * If PM GSview starts Ghostscript, PM GSview displays the
- * bitmap instead of the PM driver (gspmdrv.exe).
- *
- * Since Ghostscript is not a PM application, this driver creates a
- * BMP bitmap in a named shared memory block and a second process
- * gspmdrv.exe reads this memory block and provides the PM window.
- * Communication to gspmdrv.exe is via the shared memory block
- * and semaphores.
- */
- #define INCL_DOS
- #define INCL_DOSERRORS
- #define INCL_WINWINDOWMGR
- #define INCL_DEV
- #define INCL_GPIBITMAPS
- #include <os2.h>
- #include "string_.h"
- #include <stdlib.h>
- #include "gx.h"
- #include "gserrors.h"
- #include "gxdevice.h"
- #include "gp.h"
- #include "gpcheck.h"
- #include "gsparam.h"
- #include "gdevpccm.h"
- #include "gxdevmem.h"
- #include "gdevpm.h"
- #ifdef __DLL__
- #include "gsdll.h"
- #include "gsdllos2.h"
- #endif
- #define MIN_COMMIT 4096 /* memory is committed in these size chunks */
- #define ID_NAME "GSPMDRV_%u_%u"
- /* Initial values for width and height */
- #define INITIAL_RESOLUTION 96
- #define INITIAL_WIDTH ((INITIAL_RESOLUTION * 85 + 5) / 10)
- #define INITIAL_HEIGHT ((INITIAL_RESOLUTION * 110 + 5) / 10)
- /* A macro for casting the device argument */
- #define pmdev ((gx_device_pm *)dev)
- #define pm_gsview_sizeof 80
- typedef struct gx_device_pm_s gx_device_pm;
- #define gx_device_pm_common\
- int BitsPerPixel;\
- int UpdateInterval;\
- char GSVIEW[pm_gsview_sizeof];\
- BOOL dll;\
- int nColors;\
- BOOL updating;\
- HTIMER update_timer;\
- HEV sync_event;\
- HEV next_event;\
- HMTX bmp_mutex;\
- HQUEUE drv_queue;\
- HQUEUE term_queue;\
- ULONG session_id;\
- PID process_id;\
- PID gspid;\
- unsigned char *bitmap;\
- ULONG committed;\
- PBITMAPINFO2 bmi
- /* The device descriptor */
- struct gx_device_pm_s {
- gx_device_common;
- gx_device_pm_common;
- gx_device_memory mdev;
- };
- /* Device procedures */
- /* See gxdevice.h for the definitions of the procedures. */
- private dev_proc_open_device(pm_open);
- private dev_proc_get_initial_matrix(pm_get_initial_matrix);
- private dev_proc_sync_output(pm_sync_output);
- private dev_proc_output_page(pm_output_page);
- private dev_proc_close_device(pm_close);
- private dev_proc_map_rgb_color(pm_map_rgb_color);
- private dev_proc_map_color_rgb(pm_map_color_rgb);
- private dev_proc_fill_rectangle(pm_fill_rectangle);
- private dev_proc_copy_mono(pm_copy_mono);
- private dev_proc_copy_color(pm_copy_color);
- private dev_proc_get_bits(pm_get_bits);
- private dev_proc_get_params(pm_get_params);
- private dev_proc_put_params(pm_put_params);
- private gx_device_procs pm_procs =
- {
- pm_open,
- pm_get_initial_matrix,
- pm_sync_output,
- pm_output_page,
- pm_close,
- pm_map_rgb_color,
- pm_map_color_rgb,
- pm_fill_rectangle,
- NULL, /* tile rectangle */
- pm_copy_mono,
- pm_copy_color,
- NULL, /* draw line */
- pm_get_bits,
- pm_get_params,
- pm_put_params,
- NULL, /* map_cmyk_color */
- gx_default_get_xfont_procs,
- NULL, /* get_xfont_device */
- NULL, /* map_rgb_alpha_color */
- gx_page_device_get_page_device
- };
- #ifdef __DLL__
- gx_device_pm far_data gs_os2dll_device =
- {
- std_device_std_body(gx_device_pm, &pm_procs, "os2dll",
- INITIAL_WIDTH, INITIAL_HEIGHT,
- INITIAL_RESOLUTION, INITIAL_RESOLUTION),
- {0}, /* std_procs */
- 24, /* BitsPerPixel */
- 5000, /* UpdateInterval */
- "\0", /* GSVIEW */
- 1 /* is DLL device */
- };
- #endif
- gx_device_pm far_data gs_os2pm_device =
- {
- std_device_std_body(gx_device_pm, &pm_procs, "os2pm",
- INITIAL_WIDTH, INITIAL_HEIGHT,
- INITIAL_RESOLUTION, INITIAL_RESOLUTION),
- {0}, /* std_procs */
- 24, /* BitsPerPixel */
- 5000, /* UpdateInterval */
- "\0", /* GSVIEW */
- 0 /* is not DLL device */
- };
- /* Compress a gx_color_value into an 8-bit PM color value, */
- /* using only the high order 5 bits. */
- #define pm_color_value(z)\
- ((((z) >> (gx_color_value_bits - 5)) << 3) +\
- ((z) >> (gx_color_value_bits - 3)))
- /* prototypes for internal procedures */
- private void pm_makepalette(gx_device_pm *);
- private void pm_update(gx_device_pm *);
- private uint pm_set_bits_per_pixel(gx_device_pm *, int);
- private uint pm_palette_size(gx_device_pm *);
- private int pm_alloc_bitmap(gx_device_pm *, gx_device *);
- private int pm_run_gspmdrv(gx_device_pm *);
- private void pm_write_bmp(gx_device_pm *);
- /* Open the pm driver */
- int
- pm_open(gx_device * dev)
- {
- int ccode;
- CHAR id[128];
- CHAR name[128];
- PTIB pptib;
- PPIB pppib;
- if (!pmdev->dll && (_osmode == DOS_MODE)) {
- eprintf("os2pm driver can't be used under DOS\n");
- return gs_error_limitcheck;
- }
- if (DosGetInfoBlocks(&pptib, &pppib)) {
- eprintf("\npm_open: Couldn't get pid\n");
- return gs_error_limitcheck;
- }
- #ifdef __DLL__
- if (pppib->pib_ultype == 3) /* if caller is PM app */
- pmdev->gspid = pppib->pib_ulpid; /* use caller pid */
- else
- #endif
- pmdev->gspid = pppib->pib_ulppid; /* use parent (CMD.EXE) pid */
- sprintf(id, ID_NAME, pmdev->gspid, (ULONG) dev);
- /* Allocate, but don't commit, enough memory for the largest */
- /* possible bitmap (13Mbytes = A3 x 150dpi x 24bits) */
- #ifdef __DLL__
- if (pmdev->dll) {
- /* We don't need to use shared memory for the DLL */
- if (DosAllocMem((PPVOID) & pmdev->bitmap,
- 13 * 1024 * 1024, PAG_READ | PAG_WRITE)) {
- eprintf("pm_open: failed allocating BMP memory\n");
- return gs_error_limitcheck;
- }
- } else
- #endif
- {
- /* Shared memory is common to all processes so we don't want to allocate too much */
- sprintf(name, SHARED_NAME, *pmdev->GSVIEW ? pmdev->GSVIEW : id);
- if (DosAllocSharedMem((PPVOID) & pmdev->bitmap, name,
- 13 * 1024 * 1024, PAG_READ | PAG_WRITE)) {
- eprintf1("pm_open: failed allocating shared BMP memory %s\n", name);
- return gs_error_limitcheck;
- }
- }
- /* commit one page so there is enough storage for a */
- /* bitmap header and palette */
- if (DosSetMem(pmdev->bitmap, MIN_COMMIT, PAG_COMMIT | PAG_DEFAULT)) {
- DosFreeMem(pmdev->bitmap);
- eprintf("pm_open: failed committing BMP memory\n");
- return gs_error_limitcheck;
- }
- pmdev->committed = MIN_COMMIT;
- if (pmdev->dll) {
- /* Create mutex - used for preventing another thread from accessing */
- /* bitmap while we are changing the bitmap size. Initially unowned. */
- sprintf(name, MUTEX_NAME, id);
- if (DosCreateMutexSem(name, &(pmdev->bmp_mutex), 0, FALSE)) {
- DosFreeMem(pmdev->bitmap);
- DosCloseEventSem(pmdev->sync_event);
- DosCloseQueue(pmdev->drv_queue);
- eprintf1("pm_open: failed to create mutex semaphore %s\n", name);
- return gs_error_limitcheck;
- }
- } else {
- if (*pmdev->GSVIEW) {
- APIRET rc;
- /* GSview has already created the necessary objects */
- /* so we use Open instead of Create */
- rc = 0;
- if (!rc) {
- sprintf(name, NEXT_NAME, pmdev->GSVIEW);
- rc = DosOpenEventSem(name, &pmdev->next_event);
- }
- if (!rc) {
- sprintf(name, MUTEX_NAME, pmdev->GSVIEW);
- rc = DosOpenMutexSem(name, &pmdev->bmp_mutex);
- }
- if (!rc) {
- PID owner_pid;
- sprintf(name, QUEUE_NAME, pmdev->GSVIEW);
- rc = DosOpenQueue(&owner_pid, &pmdev->drv_queue, name);
- }
- if (rc) {
- DosFreeMem(pmdev->bitmap);
- DosCloseEventSem(pmdev->next_event);
- eprintf2("pm_open: failed to open %s, rc = %u\n", name, rc);
- return gs_error_limitcheck;
- }
- } else { /* not GSVIEW */
- /* Create update event semaphore */
- sprintf(name, SYNC_NAME, id);
- if (DosCreateEventSem(name, &(pmdev->sync_event), 0, FALSE)) {
- DosFreeMem(pmdev->bitmap);
- eprintf1("pm_open: failed to create event semaphore %s\n", name);
- return gs_error_limitcheck;
- }
- /* Create mutex - used for preventing gspmdrv from accessing */
- /* bitmap while we are changing the bitmap size. Initially unowned. */
- sprintf(name, MUTEX_NAME, id);
- if (DosCreateMutexSem(name, &(pmdev->bmp_mutex), 0, FALSE)) {
- DosFreeMem(pmdev->bitmap);
- DosCloseEventSem(pmdev->sync_event);
- DosCloseQueue(pmdev->drv_queue);
- eprintf1("pm_open: failed to create mutex semaphore %s\n", name);
- return gs_error_limitcheck;
- }
- }
- }
- if ((pm_set_bits_per_pixel(pmdev, pmdev->BitsPerPixel) < 0) ||
- (gdev_mem_device_for_bits(dev->color_info.depth) == 0)) {
- if (!pmdev->dll) {
- if (*pmdev->GSVIEW) {
- DosCloseQueue(pmdev->drv_queue);
- DosCloseEventSem(pmdev->next_event);
- } else
- DosCloseEventSem(pmdev->sync_event);
- }
- DosCloseMutexSem(pmdev->bmp_mutex);
- DosFreeMem(pmdev->bitmap);
- return gs_error_limitcheck;
- }
- /* initialise bitmap header */
- pmdev->bmi = (PBITMAPINFO2) pmdev->bitmap;
- pmdev->bmi->cbFix = 40; /* OS/2 2.0 and Windows 3.0 compatible */
- pmdev->bmi->cx = dev->width;
- pmdev->bmi->cy = dev->height;
- pmdev->bmi->cPlanes = 1;
- pmdev->bmi->cBitCount = dev->color_info.depth;
- pmdev->bmi->ulCompression = BCA_UNCOMP;
- pmdev->bmi->cbImage = 0;
- pmdev->bmi->cxResolution = (ULONG) (dev->x_pixels_per_inch / 25.4 * 1000);
- pmdev->bmi->cyResolution = (ULONG) (dev->y_pixels_per_inch / 25.4 * 1000);
- if (pmdev->BitsPerPixel <= 8) {
- pmdev->bmi->cclrUsed = 1 << (pmdev->BitsPerPixel);
- pmdev->bmi->cclrImportant = pmdev->nColors;
- } else {
- pmdev->bmi->cclrUsed = 0;
- pmdev->bmi->cclrImportant = 0;
- }
- pm_makepalette(pmdev);
- /* commit pages */
- ccode = pm_alloc_bitmap((gx_device_pm *) dev, dev);
- if (ccode < 0) {
- if (!pmdev->dll) {
- if (*pmdev->GSVIEW) {
- DosCloseQueue(pmdev->drv_queue);
- DosCloseEventSem(pmdev->next_event);
- } else
- DosCloseEventSem(pmdev->sync_event);
- }
- DosCloseMutexSem(pmdev->bmp_mutex);
- DosFreeMem(pmdev->bitmap);
- return ccode;
- }
- if (*pmdev->GSVIEW)
- return 0; /* GSview will handle displaying */
- #ifdef __DLL__
- if (pmdev->dll && pgsdll_callback) {
- /* notify caller about new device */
- (*pgsdll_callback) (GSDLL_DEVICE, (unsigned char *)pmdev, 1);
- return 0; /* caller will handle displaying */
- }
- #endif
- ccode = pm_run_gspmdrv(pmdev);
- if (ccode < 0) {
- DosFreeMem(pmdev->bitmap);
- DosCloseEventSem(pmdev->sync_event);
- DosCloseMutexSem(pmdev->bmp_mutex);
- }
- return ccode;
- }
- /* Get the initial matrix. BMPs, unlike most displays, */
- /* put (0,0) in the lower left corner. */
- private void
- pm_get_initial_matrix(gx_device * dev, gs_matrix * pmat)
- {
- pmat->xx = dev->x_pixels_per_inch / 72.0;
- pmat->xy = 0;
- pmat->yx = 0;
- pmat->yy = dev->y_pixels_per_inch / 72.0;
- pmat->tx = 0;
- pmat->ty = 0;
- if (*pmdev->GSVIEW)
- pm_update((gx_device_pm *) dev); /* let GSVIEW know we are drawing */
- }
- /* Make the output appear on the screen. */
- int
- pm_sync_output(gx_device * dev)
- {
- #ifdef __DLL__
- if (pmdev->dll && pgsdll_callback) {
- (*pgsdll_callback) (GSDLL_SYNC, (unsigned char *)dev, 0);
- return 0;
- }
- #endif
- /* tell gspmdrv or GSview process to update display */
- if (*pmdev->GSVIEW) {
- APIRET rc;
- rc = DosWriteQueue(pmdev->drv_queue, GS_SYNC, 0, NULL, 0);
- if (rc)
- eprintf1("pm_sync_output: DosWriteQueue error %d\n", rc);
- } else {
- if (pmdev->updating)
- DosStopTimer(pmdev->update_timer);
- DosPostEventSem(pmdev->sync_event);
- }
- pmdev->updating = FALSE;
- return (0);
- }
- /* Make the output appear on the screen */
- /* and bring image window to foreground. */
- private int
- pm_do_output_page(gx_device * dev, int copies, int flush)
- {
- int code;
- APIRET rc;
- #ifdef DEBUG
- pm_write_bmp(pmdev);
- #endif
- #ifdef __DLL__
- if (pmdev->dll && pgsdll_callback) {
- (*pgsdll_callback) (GSDLL_PAGE, (unsigned char *)dev, 0);
- return 0;
- }
- #endif
- if (*pmdev->GSVIEW) {
- if (copies == -2) {
- rc = DosWriteQueue(pmdev->drv_queue, GS_END, 0, NULL, 0);
- if (rc)
- eprintf1("pm_output_page: DosWriteQueue error %d\n", rc);
- } else if (copies == -1) {
- rc = DosWriteQueue(pmdev->drv_queue, GS_BEGIN, 0, NULL, 0);
- if (rc)
- eprintf1("pm_output_page: DosWriteQueue error %d\n", rc);
- } else {
- ULONG count;
- pmdev->updating = FALSE;
- /* signal GSview that another page is ready */
- rc = DosWriteQueue(pmdev->drv_queue, GS_PAGE, 0, NULL, 0);
- if (rc)
- eprintf1("pm_output_page: DosWriteQueue error %d\n", rc);
- /* wait for GSview to signal we can move on to next page */
- DosWaitEventSem(pmdev->next_event, SEM_INDEFINITE_WAIT);
- DosResetEventSem(pmdev->next_event, &count);
- }
- code = 0;
- } else {
- code = pm_sync_output(dev);
- rc = DosSelectSession(pmdev->session_id);
- if (rc) {
- DosSleep(2000); /* give gspmdrv.exe a chance to run */
- rc = DosSelectSession(pmdev->session_id);
- if (rc == ERROR_SMG_NO_TARGET_WINDOW) {
- DosSleep(5000); /* give gspmdrv.exe a chance to run */
- rc = DosSelectSession(pmdev->session_id); /* try yet again */
- }
- if ((rc == ERROR_SMG_SESSION_NOT_FOUND) ||
- (rc == ERROR_SMG_INVALID_SESSION_ID)) {
- /* someone has killed the session */
- REQUESTDATA Request;
- ULONG DataLength;
- PVOID DataAddress;
- PULONG QueueEntry;
- BYTE ElemPriority;
- /* Close gspmdrv driver */
- DosStopSession(STOP_SESSION_SPECIFIED, pmdev->session_id);
- Request.pid = pmdev->gspid;
- Request.ulData = 0;
- /* wait for termination queue, queue is then closed by session manager */
- DosReadQueue(pmdev->term_queue, &Request, &DataLength,
- &DataAddress, 0, DCWW_WAIT, &ElemPriority, (HEV) NULL);
- DosCloseQueue(pmdev->term_queue);
- pmdev->term_queue = (HQUEUE) 0;
- /* restart it */
- pm_run_gspmdrv(pmdev);
- DosSleep(2000); /* give gspmdrv.exe a chance to run */
- rc = DosSelectSession(pmdev->session_id);
- }
- if (rc == ERROR_SMG_SESSION_NOT_FOREGRND)
- DosBeep(400, 50);
- else if (rc)
- eprintf1("pm_output_page: Select Session error code %u\n", rc);
- }
- }
- return code;
- }
- int
- pm_output_page(gx_device * dev, int copies, int flush)
- {
- int code = pm_do_output_page(dev, copies, flush);
- if (code >= 0)
- code = gx_finish_output_page(dev, copies, flush);
- return code;
- }
- /* Close the pm driver */
- int
- pm_close(gx_device * dev)
- {
- APIRET rc;
- #ifdef __DLL__
- if (pmdev->dll) {
- DosRequestMutexSem(pmdev->bmp_mutex, 60000);
- if (pgsdll_callback)
- (*pgsdll_callback) (GSDLL_DEVICE, (unsigned char *)dev, 0);
- DosReleaseMutexSem(pmdev->bmp_mutex);
- } else
- #endif
- {
- if (*pmdev->GSVIEW) {
- rc = DosWriteQueue(pmdev->drv_queue, GS_CLOSE, 0, NULL, 0);
- if (rc)
- eprintf1("pm_close: DosWriteQueue error %d\n", rc);
- } else {
- REQUESTDATA Request;
- ULONG DataLength;
- PVOID DataAddress;
- PULONG QueueEntry;
- BYTE ElemPriority;
- /* Close gspmdrv driver */
- DosStopSession(STOP_SESSION_SPECIFIED, pmdev->session_id);
- Request.pid = pmdev->gspid;
- Request.ulData = 0;
- /* wait for termination queue, queue is then closed by session manager */
- DosReadQueue(pmdev->term_queue, &Request, &DataLength,
- &DataAddress, 0, DCWW_WAIT, &ElemPriority, (HEV) NULL);
- /* queue needs to be closed by us */
- DosCloseQueue(pmdev->term_queue);
- }
- }
- /* release memory */
- DosFreeMem(pmdev->bitmap);
- pmdev->bitmap = (unsigned char *)NULL;
- pmdev->committed = 0;
- if (!pmdev->dll) {
- /* close objects */
- if (*pmdev->GSVIEW) {
- DosCloseQueue(pmdev->drv_queue);
- DosCloseEventSem(pmdev->next_event);
- } else {
- DosCloseEventSem(pmdev->sync_event);
- /* stop update timer */
- if (pmdev->updating)
- DosStopTimer(pmdev->update_timer);
- pmdev->updating = FALSE;
- }
- }
- DosCloseMutexSem(pmdev->bmp_mutex);
- return (0);
- }
- /* Map a r-g-b color to the colors available under PM */
- gx_color_index
- pm_map_rgb_color(gx_device * dev, const gx_color_value cv[])
- {
- gx_color_value r = cv[0];
- gx_color_value g = cv[1];
- gx_color_value b = cv[2];
- switch (dev->color_info.depth) {
- case 24:
- return ((b >> (gx_color_value_bits - 8)) << 16) +
- ((g >> (gx_color_value_bits - 8)) << 8) +
- ((r >> (gx_color_value_bits - 8)));
- case 8:{
- int i;
- RGB2 *prgb;
- byte cr, cg, cb;
- /* map colors to 0->255 in 32 steps */
- cr = pm_color_value(r);
- cg = pm_color_value(g);
- cb = pm_color_value(b);
- prgb = (RGB2 *) ((PBYTE) pmdev->bmi + pmdev->bmi->cbFix);
- /* search in palette */
- for (i = 0; i < pmdev->nColors; i++, prgb++) {
- if (!((cr ^ prgb->bRed) & 0xf8) &&
- !((cg ^ prgb->bGreen) & 0xf8) &&
- !((cb ^ prgb->bBlue) & 0xf8)
- )
- return ((gx_color_index) i); /* found it */
- }
- /* next try adding it to palette */
- if (i < 230) { /* allow 26 for PM and other apps */
- prgb->bRed = cr;
- prgb->bGreen = cg;
- prgb->bBlue = cb;
- prgb->fcOptions = 0;
- pmdev->nColors = i + 1;
- pmdev->bmi->cclrImportant = pmdev->nColors;
- if (*pmdev->GSVIEW) {
- APIRET rc;
- rc = DosWriteQueue(pmdev->drv_queue, GS_PALCHANGE, 0, NULL, 0);
- if (rc)
- eprintf1("pm_sync_output: DosWriteQueue error %d\n", rc);
- }
- return ((gx_color_index) i); /* return new palette index */
- }
- return (gx_no_color_index); /* not found - dither instead */
- }
- case 4:
- return pc_4bit_map_rgb_color(dev, cv);
- }
- return (gx_default_map_rgb_color(dev, cv));
- }
- /* Map a color code to r-g-b. */
- int
- pm_map_color_rgb(gx_device * dev, gx_color_index color,
- gx_color_value prgb[3])
- {
- gx_color_value one;
- switch (dev->color_info.depth) {
- case 24:
- one = (gx_color_value) (gx_max_color_value / 255);
- prgb[0] = ((color) & 255) * one;
- prgb[1] = ((color >> 8) & 255) * one;
- prgb[2] = ((color >> 16) & 255) * one;
- break;
- case 8:
- if (!dev->is_open)
- return -1;
- {
- RGB2 *argb = (RGB2 *) ((PBYTE) pmdev->bmi + pmdev->bmi->cbFix);
- one = (gx_color_value) (gx_max_color_value / 255);
- prgb[0] = argb[(int)color].bRed * one;
- prgb[1] = argb[(int)color].bGreen * one;
- prgb[2] = argb[(int)color].bBlue * one;
- }
- break;
- case 4:
- pc_4bit_map_color_rgb(dev, color, prgb);
- break;
- default:
- prgb[0] = prgb[1] = prgb[2] =
- (int)color ? gx_max_color_value : 0;
- }
- return 0;
- }
- #define pmmdev ((gx_device *)&pmdev->mdev)
- #define pmmproc(proc) (*dev_proc(&pmdev->mdev, proc))
- /* Fill a rectangle. */
- private int
- pm_fill_rectangle(gx_device * dev, int x, int y, int w, int h,
- gx_color_index color)
- {
- pmmproc(fill_rectangle) (pmmdev, x, y, w, h, color);
- pm_update((gx_device_pm *) dev);
- return 0;
- }
- /* Copy a monochrome bitmap. The colors are given explicitly. */
- /* Color = gx_no_color_index means transparent (no effect on the image). */
- private int
- pm_copy_mono(gx_device * dev,
- const byte * base, int sourcex, int raster, gx_bitmap_id id,
- int x, int y, int w, int h,
- gx_color_index zero, gx_color_index one)
- {
- pmmproc(copy_mono) (pmmdev, base, sourcex, raster, id,
- x, y, w, h, zero, one);
- pm_update((gx_device_pm *) dev);
- return 0;
- }
- /* Copy a color pixel map. This is just like a bitmap, except that */
- /* each pixel takes 8 or 4 bits instead of 1 when device driver has color. */
- private int
- pm_copy_color(gx_device * dev,
- const byte * base, int sourcex, int raster, gx_bitmap_id id,
- int x, int y, int w, int h)
- {
- pmmproc(copy_color) (pmmdev, base, sourcex, raster, id,
- x, y, w, h);
- pm_update((gx_device_pm *) dev);
- return 0;
- }
- int
- pm_get_bits(gx_device * dev, int y, byte * str, byte ** actual_data)
- {
- return pmmproc(get_bits) (pmmdev, y, str, actual_data);
- }
- /* Get PM parameters */
- int
- pm_get_params(gx_device * dev, gs_param_list * plist)
- {
- int code = gx_default_get_params(dev, plist);
- gs_param_string gvs;
- gvs.data = pmdev->GSVIEW, gvs.size = strlen(gvs.data),
- gvs.persistent = false;
- code < 0 ||
- (code = param_write_int(plist, "UpdateInterval", &pmdev->UpdateInterval)) < 0 ||
- (code = param_write_string(plist, "GSVIEW", &gvs)) < 0;
- return code;
- }
- /* Put parameters. */
- /* Set PM parameters -- size and resolution. */
- /* We implement this ourselves so that we can do it without */
- /* closing and opening the device. */
- /* Also set BitsPerPixel and GSVIEW if device not open */
- int
- pm_put_params(gx_device * dev, gs_param_list * plist)
- {
- int ecode = 0, code;
- bool reopen = false;
- bool is_open = dev->is_open;
- int width = dev->width;
- int height = dev->height;
- int old_bpp = dev->color_info.depth;
- int bpp = old_bpp;
- int uii = pmdev->UpdateInterval;
- gs_param_string gsvs;
- /* Handle extra parameters */
- switch (code = param_read_string(plist, "GSVIEW", &gsvs)) {
- case 0:
- if (gsvs.size == strlen(pmdev->GSVIEW) &&
- !memcmp(pmdev->GSVIEW, gsvs.data, gsvs.size)
- ) {
- gsvs.data = 0;
- break;
- }
- if (dev->is_open)
- ecode = gs_error_rangecheck;
- else if (gsvs.size >= pm_gsview_sizeof)
- ecode = gs_error_limitcheck;
- else
- break;
- goto gsve;
- default:
- ecode = code;
- gsve:param_signal_error(plist, "GSVIEW", ecode);
- case 1:
- gsvs.data = 0;
- break;
- }
- switch (code = param_read_int(plist, "UpdateInterval", &uii)) {
- case 0:
- if (uii < 0)
- ecode = gs_error_rangecheck;
- else
- break;
- goto uie;
- default:
- ecode = code;
- uie:param_signal_error(plist, "UpdateInterval", ecode);
- case 1:
- break;
- }
- switch (code = param_read_int(plist, "BitsPerPixel", &bpp)) {
- case 0:
- if (dev->is_open && bpp != old_bpp)
- ecode = gs_error_rangecheck;
- else {
- code = pm_set_bits_per_pixel(pmdev, bpp);
- if (code < 0)
- ecode = code;
- else
- break;
- }
- goto bppe;
- default:
- ecode = code;
- bppe:param_signal_error(plist, "BitsPerPixel", ecode);
- case 1:
- break;
- }
- if (ecode >= 0) { /* Prevent gx_default_put_params from closing the device. */
- dev->is_open = false;
- ecode = gx_default_put_params(dev, plist);
- dev->is_open = is_open;
- }
- if (ecode < 0) {
- if (bpp != old_bpp)
- pm_set_bits_per_pixel(pmdev, old_bpp);
- return ecode;
- }
- /* Hand off the change to the implementation. */
- /* obtain mutex - to prevent gspmdrv from using bitmap */
- /* while we change its size */
- if (DosRequestMutexSem(pmdev->bmp_mutex, 20000) == ERROR_TIMEOUT)
- eprintf("pm_put_params: mutex timeout\n");
- if (is_open && (old_bpp != bpp ||
- dev->width != width || dev->height != height)
- ) {
- int ccode;
- ccode = pm_alloc_bitmap(pmdev, dev);
- if (ccode < 0) { /* Bad news! Some of the other device parameters */
- /* may have changed. We don't handle this. */
- /* This is ****** WRONG ******. */
- dev->width = width;
- dev->height = height;
- pm_set_bits_per_pixel(pmdev, old_bpp);
- pm_alloc_bitmap(pmdev, dev);
- DosReleaseMutexSem(pmdev->bmp_mutex);
- return ccode;
- }
- reopen = true;
- }
- pmdev->UpdateInterval = uii;
- if (gsvs.data != 0) {
- memcpy(pmdev->GSVIEW, gsvs.data, gsvs.size);
- pmdev->GSVIEW[gsvs.size] = 0;
- }
- if (dev->is_open && reopen) {
- /* need to update bitmap info header also */
- pmdev->bmi->cx = dev->width;
- pmdev->bmi->cy = dev->height;
- /* update bit count and palette */
- pmdev->bmi->cBitCount = dev->color_info.depth;
- pmdev->bmi->cclrUsed = 1 << (pmdev->BitsPerPixel);
- pmdev->bmi->cclrImportant = pmdev->nColors;
- pm_makepalette(pmdev);
- /* erase bitmap - before window gets redrawn */
- {
- int i;
- gx_color_value cv[GX_DEVICE_COLOR_MAX_COMPONENTS];
- for (i=0; i<GX_DEVICE_COLOR_MAX_COMPONENTS; i++)
- cv[i] = (pmdev->color_info.polarity == GX_CINFO_POLARITY_ADDITIVE)
- ? gx_max_color_value : 0;
- dev_proc(pmdev, fill_rectangle)((gx_device *)pmdev,
- 0, 0, pmdev->width, pmdev->height,
- pmdev->procs.encode_color((gx_device *)pmdev, cv));
- }
- /* cause scroll bars to be redrawn */
- /* need to signal gspmdrv that bitmap size has changed */
- /* or perhaps gspmdrv can check if the bitmap size has */
- /* before each use */
- #ifdef __DLL__
- if (pmdev->dll && pgsdll_callback)
- (*pgsdll_callback) (GSDLL_SIZE, (unsigned char *)dev,
- (dev->width & 0xffff) + ((dev->height & 0xffff) << 16));
- #endif
- }
- /* release bmp mutex */
- DosReleaseMutexSem(pmdev->bmp_mutex);
- return 0;
- }
- #ifdef __DLL__
- /* ------ DLL routines ------ */
- /* store at pbitmap the address of the bitmap */
- /* device is a pointer to Ghostscript device from GSDLL_DEVICE message */
- unsigned long GSDLLAPI
- gsdll_get_bitmap(unsigned char *device, unsigned char **pbitmap)
- {
- gx_device *dev = (gx_device *) device;
- *pbitmap = (unsigned char *)(pmdev->bmi);
- return 0;
- }
- /* Lock the device (so it's size cannot be changed) if flag = TRUE */
- /* or unlock the device if flag = FALSE */
- /* device is a pointer to Ghostscript device from GSDLL_DEVICE message */
- int GSDLLAPI
- gsdll_lock_device(unsigned char *device, int flag)
- {
- gx_device *dev = (gx_device *) device;
- APIRET rc;
- if (flag)
- rc = DosRequestMutexSem(pmdev->bmp_mutex, 60000);
- else
- rc = DosReleaseMutexSem(pmdev->bmp_mutex);
- return rc;
- }
- #endif /* __DLL__ */
- /* ------ Internal routines ------ */
- #undef pmdev
- /* start gspmdrv.exe */
- private int
- pm_run_gspmdrv(gx_device_pm * pmdev)
- {
- int ccode;
- PCHAR pdrvname = "gspmdrv.exe";
- CHAR error_message[256];
- CHAR term_queue_name[128];
- CHAR id[128];
- CHAR arg[1024];
- STARTDATA sdata;
- APIRET rc;
- PTIB pptib;
- PPIB pppib;
- CHAR progname[256];
- PCHAR tail;
- sprintf(id, ID_NAME, pmdev->gspid, (ULONG) pmdev);
- /* Create termination queue - used to find out when gspmdrv terminates */
- sprintf(term_queue_name, "\\QUEUES\\TERMQ_%s", id);
- if (DosCreateQueue(&(pmdev->term_queue), QUE_FIFO, term_queue_name)) {
- eprintf("pm_run_gspmdrv: failed to create termination queue\n");
- return gs_error_limitcheck;
- }
- /* get full path to gsos2.exe and hence path to gspmdrv.exe */
- if ((rc = DosGetInfoBlocks(&pptib, &pppib)) != 0) {
- eprintf1("pm_run_gspmdrv: Couldn't get module handle, rc = %d\n", rc);
- return gs_error_limitcheck;
- }
- if ((rc = DosQueryModuleName(pppib->pib_hmte, sizeof(progname) - 1, progname)) != 0) {
- eprintf1("pm_run_gspmdrv: Couldn't get module name, rc = %d\n", rc);
- return gs_error_limitcheck;
- }
- if ((tail = strrchr(progname, '\\')) != (PCHAR) NULL) {
- tail++;
- *tail = '\0';
- } else
- tail = progname;
- strcat(progname, pdrvname);
- /* Open the PM driver session gspmdrv.exe */
- /* arguments are: */
- /* (1) -d (display) option */
- /* (2) id string */
- sprintf(arg, "-d %s", id);
- /* because gspmdrv.exe is a different EXE type to gs.exe,
- * we must use start session not DosExecPgm() */
- sdata.Length = sizeof(sdata);
- sdata.Related = SSF_RELATED_CHILD; /* to be a child */
- sdata.FgBg = SSF_FGBG_BACK; /* start in background */
- sdata.TraceOpt = 0;
- sdata.PgmTitle = "Ghostscript PM driver session";
- sdata.PgmName = progname;
- sdata.PgmInputs = arg;
- sdata.TermQ = term_queue_name;
- sdata.Environment = pppib->pib_pchenv; /* use Parent's environment */
- sdata.InheritOpt = 0; /* Can't inherit from parent because different sesison type */
- sdata.SessionType = SSF_TYPE_DEFAULT; /* default is PM */
- sdata.IconFile = NULL;
- sdata.PgmHandle = 0;
- sdata.PgmControl = 0;
- sdata.InitXPos = 0;
- sdata.InitYPos = 0;
- sdata.InitXSize = 0;
- sdata.InitYSize = 0;
- sdata.ObjectBuffer = error_message;
- sdata.ObjectBuffLen = sizeof(error_message);
- rc = DosStartSession(&sdata, &pmdev->session_id, &pmdev->process_id);
- if (rc == ERROR_FILE_NOT_FOUND) {
- sdata.PgmName = pdrvname;
- rc = DosStartSession(&sdata, &pmdev->session_id, &pmdev->process_id);
- }
- if (rc) {
- eprintf2("pm_run_gspmdrv: failed to run %s, rc = %d\n", sdata.PgmName, rc);
- eprintf1("pm_run_gspmdrv: error_message: %s\n", error_message);
- return gs_error_limitcheck;
- }
- return 0;
- }
- /* Allocate the backing bitmap. */
- private int
- pm_alloc_bitmap(gx_device_pm * pmdev, gx_device * param_dev)
- {
- gx_device_memory mdev;
- byte *base;
- ulong data_size;
- uint ptr_size;
- uint pal_size;
- uint raster;
- ULONG rc;
- ULONG needed;
- /* Finish initializing the bitmap. */
- gs_make_mem_device(&mdev, gdev_mem_device_for_bits(pmdev->color_info.depth), 0, 0, (gx_device *) pmdev);
- mdev.width = param_dev->width;
- mdev.height = param_dev->height;
- /* BMP files need width rounded up so that a scan line is */
- /* a multiple of 4 bytes. */
- /* This is currently done by gdev_mem_raster(). */
- /* It may be better to do it here explicitly in case */
- /* gdev_mem_raster changes. */
- raster = gdev_mem_raster(&mdev);
- data_size = (ulong) raster *mdev.height;
- ptr_size = sizeof(byte **) * mdev.height;
- pal_size = pm_palette_size(pmdev);
- needed = pmdev->bmi->cbFix + pal_size + data_size + ptr_size;
- /* round up to page boundary */
- needed = (needed + MIN_COMMIT - 1) & (~(MIN_COMMIT - 1));
- if (needed > pmdev->committed) {
- /* commit more memory */
- if (rc = DosSetMem(pmdev->bitmap + pmdev->committed,
- needed - pmdev->committed,
- PAG_COMMIT | PAG_DEFAULT)) {
- eprintf1("No memory in pm_alloc_bitmap, rc = %d\n", rc);
- return gs_error_limitcheck;
- }
- pmdev->committed = needed;
- }
- /* Shared memory can't be decommitted */
- #ifdef __DLL__
- if (pmdev->dll && (needed < pmdev->committed)) {
- /* decommit memory */
- if (rc = DosSetMem(pmdev->bitmap + needed,
- pmdev->committed - needed,
- PAG_DECOMMIT)) {
- eprintf1("Failed to decommit memory in pm_alloc_bitmap, rc = %d\n", rc);
- return gs_error_limitcheck;
- }
- pmdev->committed = needed;
- }
- #endif
- /* Nothing can go wrong now.... */
- base = pmdev->bitmap + pmdev->bmi->cbFix + pm_palette_size(pmdev);
- pmdev->mdev = mdev;
- pmdev->mdev.base = (byte *) base;
- pmmproc(open_device) ((gx_device *) & pmdev->mdev);
- pmdev->bmi->cbImage = data_size;
- return 0;
- }
- private void
- pm_makepalette(gx_device_pm * pmdev)
- {
- int i, val;
- RGB2 *argb = (RGB2 *) ((PBYTE) pmdev->bmi + pmdev->bmi->cbFix);
- if (pmdev->BitsPerPixel > 8)
- return; /* these don't use a palette */
- for (i = 0; i < pmdev->nColors; i++) {
- switch (pmdev->nColors) {
- case 64:
- /* colors are rrggbb */
- argb[i].bRed = ((i & 0x30) >> 4) * 85;
- argb[i].bGreen = ((i & 0xC) >> 2) * 85;
- argb[i].bBlue = (i & 3) * 85;
- argb[i].fcOptions = 0;
- /* zero unused entries */
- argb[i + 64].bRed = argb[i + 64].bGreen = argb[i + 64].bBlue = 0;
- argb[i + 64].fcOptions = 0;
- argb[i + 128].bRed = argb[i + 128].bGreen = argb[i + 128].bBlue = 0;
- argb[i + 128].fcOptions = 0;
- argb[i + 192].bRed = argb[i + 192].bGreen = argb[i + 192].bBlue = 0;
- argb[i + 192].fcOptions = 0;
- break;
- case 16:
- /* colors are irgb */
- val = (i & 8 ? 255 : 128);
- argb[i].bRed = i & 4 ? val : 0;
- argb[i].bGreen = i & 2 ? val : 0;
- argb[i].bBlue = i & 1 ? val : 0;
- if (i == 8) { /* light gray */
- argb[i].bRed =
- argb[i].bGreen =
- argb[i].bBlue = 192;
- argb[i].fcOptions = 0;
- }
- break;
- case 2:
- argb[i].bRed =
- argb[i].bGreen =
- argb[i].bBlue = (i ? 255 : 0);
- argb[i].fcOptions = 0;
- break;
- }
- }
- }
- /* Cause display to be updated periodically */
- private void
- pm_update(gx_device_pm * pmdev)
- {
- if (pmdev->updating)
- return;
- if (!pmdev->UpdateInterval)
- return;
- if (*pmdev->GSVIEW) {
- APIRET rc;
- rc = DosWriteQueue(pmdev->drv_queue, GS_UPDATING, 0, NULL, 0);
- if (rc)
- eprintf1("pm_update: DosWriteQueue error %d\n", rc);
- } else {
- DosStartTimer(pmdev->UpdateInterval, (HSEM) pmdev->sync_event,
- &pmdev->update_timer);
- }
- pmdev->updating = TRUE;
- }
- /*
- * This is a utility routine to build the display device's color_info
- * structure (except for the anti alias info).
- */
- private void
- set_color_info(gx_device_color_info * pdci, int nc, int depth, int maxgray, int maxcolor)
- {
- pdci->num_components = pdci->max_components = nc;
- pdci->depth = depth;
- pdci->gray_index = 0;
- pdci->max_gray = maxgray;
- pdci->max_color = maxcolor;
- pdci->dither_grays = maxgray + 1;
- pdci->dither_colors = maxcolor + 1;
- pdci->separable_and_linear = GX_CINFO_UNKNOWN_SEP_LIN;
- switch (nc) {
- case 1:
- pdci->polarity = GX_CINFO_POLARITY_ADDITIVE;
- pdci->cm_name = "DeviceGray";
- break;
- case 3:
- pdci->polarity = GX_CINFO_POLARITY_ADDITIVE;
- pdci->cm_name = "DeviceRGB";
- break;
- case 4:
- pdci->polarity = GX_CINFO_POLARITY_SUBTRACTIVE;
- pdci->cm_name = "DeviceCMYK";
- break;
- default:
- break;
- }
- }
- /*
- * This is an utility routine to set up the color procs for the display
- * device. The display device can change its setup.
- */
- private void
- set_color_procs(gx_device * pdev,
- dev_t_proc_encode_color((*encode_color), gx_device),
- dev_t_proc_decode_color((*decode_color), gx_device),
- dev_t_proc_get_color_mapping_procs((*get_color_mapping_procs), gx_device),
- dev_t_proc_get_color_comp_index((*get_color_comp_index), gx_device))
- {
- #if 0 /* These procs are no longer used */
- pdev->procs.map_rgb_color = encode_color;
- pdev->procs.map_color_rgb = decode_color;
- #endif
- pdev->procs.get_color_mapping_procs = get_color_mapping_procs;
- pdev->procs.get_color_comp_index = get_color_comp_index;
- pdev->procs.encode_color = encode_color;
- pdev->procs.decode_color = decode_color;
- }
- /*
- * This is an utility routine to set up the color procs for the display
- * device. This routine is used when the display device is Gray.
- */
- private void
- set_gray_color_procs(gx_device * pdev,
- dev_t_proc_encode_color((*encode_color), gx_device),
- dev_t_proc_decode_color((*decode_color), gx_device))
- {
- set_color_procs(pdev, encode_color, decode_color,
- gx_default_DevGray_get_color_mapping_procs,
- gx_default_DevGray_get_color_comp_index);
- }
- /*
- * This is an utility routine to set up the color procs for the display
- * device. This routine is used when the display device is RGB.
- */
- private void
- set_rgb_color_procs(gx_device * pdev,
- dev_t_proc_encode_color((*encode_color), gx_device),
- dev_t_proc_decode_color((*decode_color), gx_device))
- {
- set_color_procs(pdev, encode_color, decode_color,
- gx_default_DevRGB_get_color_mapping_procs,
- gx_default_DevRGB_get_color_comp_index);
- }
- private uint
- pm_set_bits_per_pixel(gx_device_pm * pmdev, int bpp)
- {
- gx_device * pdev = (gx_device *) pmdev;
- gx_device_color_info dci = pmdev->color_info;
- switch (bpp) {
- case 24:
- set_color_info(&dci, 3, bpp, 255, 255);
- set_rgb_color_procs(pdev, pm_map_rgb_color, pm_map_color_rgb);
- pmdev->nColors = (1 << 24);
- break;
- case 8:
- /* use 64 static colors and 166 dynamic colors from 8 planes */
- set_color_info(&dci, 3, 8, 7, 31);
- set_rgb_color_procs(pdev, pm_map_rgb_color, pm_map_color_rgb);
- pmdev->nColors = 64;
- break;
- case 4:
- set_color_info(&dci, 3, 4, 1, 1);
- set_rgb_color_procs(pdev, pm_map_rgb_color, pm_map_color_rgb);
- pmdev->nColors = 16;
- break;
- case 1:
- set_color_info(&dci, 1, 1, 1, 0);
- set_gray_color_procs(pdev, gx_default_gray_encode,
- gx_default_w_b_map_color_rgb);
- pmdev->nColors = 2;
- break;
- default:
- return (gs_error_rangecheck);
- }
- pmdev->BitsPerPixel = bpp;
- /* restore old anti_alias info */
- dci.anti_alias = pmdev->color_info.anti_alias;
- pmdev->color_info = dci;
- /* Set the mask bits, etc. even though we are setting linear: unknown */
- set_linear_color_bits_mask_shift(pdev);
- return 0;
- }
- /* return length of BMP palette in bytes */
- private uint
- pm_palette_size(gx_device_pm * pmdev)
- {
- switch (pmdev->color_info.depth) {
- case 24:
- return 0;
- case 8:
- return 256 * sizeof(RGB2);
- case 4:
- return 16 * sizeof(RGB2);
- }
- /* must be two color */
- return 2 * sizeof(RGB2);
- }
- /* This is used for testing */
- /* Write out a BMP file to "out.bmp" */
- private void
- pm_write_bmp(gx_device_pm * pmdev)
- {
- BITMAPFILEHEADER2 bmfh;
- uint bmfh_length = sizeof(BITMAPFILEHEADER2) - sizeof(BITMAPINFOHEADER2);
- uint length; /* bitmap length */
- ULONG fh; /* file handle */
- ULONG action;
- ULONG count;
- bmfh.usType = 0x4d42; /* "BM" */
- length = pmdev->bmi->cbFix + pm_palette_size(pmdev)
- + ((gdev_mem_raster(&pmdev->mdev) * pmdev->mdev.height));
- bmfh.cbSize = bmfh_length + length;
- bmfh.xHotspot = bmfh.yHotspot = 0;
- bmfh.offBits = bmfh_length + pmdev->bmi->cbFix + pm_palette_size(pmdev);
- if (DosOpen("out.bmp", /* filename */
- &fh, /* pointer to handle */
- &action, /* pointer to result */
- 0, /* initial length */
- FILE_NORMAL, /* normal file */
- OPEN_ACTION_CREATE_IF_NEW | OPEN_ACTION_REPLACE_IF_EXISTS,
- OPEN_ACCESS_WRITEONLY | OPEN_SHARE_DENYREADWRITE,
- 0)) {
- eprintf("error opening out.bmp\n");
- return;
- }
- if (DosWrite(fh, (PBYTE) & bmfh, bmfh_length, &count))
- eprintf("error writing header for out.bmp\n");
- if (DosWrite(fh, pmdev->bitmap, length, &count))
- eprintf("error writing out.bmp\n");
- if (DosClose(fh))
- eprintf("error closing out.bmp\n");
- }
|