home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / gbmos2pm.zip / gbmv2 / bmputils.c next >
C/C++ Source or Header  |  1996-11-16  |  12KB  |  470 lines

  1. /*
  2.  
  3. bmputils.c - PM Bitmap Utilities
  4.  
  5. */
  6.  
  7. /*...sincludes:0:*/
  8. #define    INCL_DOS
  9. #define    INCL_WIN
  10. #define    INCL_GPI
  11. #define    INCL_DEV
  12. #define    INCL_SPL
  13. #define    INCL_SPLDOSPRINT
  14. #define    INCL_BITMAPFILEFORMAT
  15. #include <os2.h>
  16. #include <stdio.h>
  17. #include <ctype.h>
  18. #include <stdlib.h>
  19. #include <string.h>
  20. #include <malloc.h>
  21. #include <memory.h>
  22. #define    _BMPUTILS_
  23. #include "bmputils.h"
  24.  
  25. /*...vbmputils\46\h:0:*/
  26. /*...e*/
  27.  
  28. /*...sBmpBlitter          \45\ blit one part of one bitmap to part of another:0:*/
  29. BMP_ERR BmpBlitter(
  30.     HAB hab,
  31.     HBITMAP hbmSrc, RECTL rclSrc,
  32.     HBITMAP hbmDst, RECTL rclDst
  33.     )
  34.     {
  35.     HDC hdcSrc, hdcDst;
  36.     HPS hpsSrc, hpsDst;
  37.     BITMAPINFOHEADER2 bmp;
  38.     SIZEL sizl;
  39.     POINTL aptl[4];
  40.  
  41.     if ( (hdcSrc = DevOpenDC(hab, OD_MEMORY, "*", 0L, (PDEVOPENDATA) NULL, (HDC) NULL)) == (HDC) NULL )
  42.         return BMP_ERR_RES;
  43.  
  44.     bmp.cbFix = sizeof(BITMAPINFOHEADER2);
  45.     GpiQueryBitmapInfoHeader(hbmSrc, &bmp);
  46.     sizl.cx = bmp.cx; sizl.cy = bmp.cy;
  47.     if ( (hpsSrc = GpiCreatePS(hab, hdcSrc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL )
  48.         {
  49.         DevCloseDC(hdcSrc);
  50.         return BMP_ERR_RES;
  51.         }
  52.  
  53.     if ( (hdcDst = DevOpenDC(hab, OD_MEMORY, "*", 0L, (PDEVOPENDATA) NULL, (HDC) NULL)) == (HDC) NULL )
  54.         {
  55.         GpiDestroyPS(hpsSrc); DevCloseDC(hdcSrc);
  56.         return BMP_ERR_RES;
  57.         }
  58.  
  59.     bmp.cbFix = sizeof(BITMAPINFOHEADER2);
  60.     GpiQueryBitmapInfoHeader(hbmDst, &bmp);
  61.     sizl.cx = bmp.cx; sizl.cy = bmp.cy;
  62.     if ( (hpsDst = GpiCreatePS(hab, hdcDst, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL )
  63.         {
  64.         DevCloseDC(hdcDst);
  65.         GpiDestroyPS(hpsSrc); DevCloseDC(hdcSrc);
  66.         return BMP_ERR_RES;
  67.         }
  68.  
  69.     GpiSetBitmap(hpsSrc, hbmSrc);
  70.     GpiSetBitmap(hpsDst, hbmDst);
  71.  
  72.     aptl[0].x = rclDst.xLeft;
  73.     aptl[0].y = rclDst.yBottom;
  74.     aptl[1].x = rclDst.xRight;
  75.     aptl[1].y = rclDst.yTop;
  76.     aptl[2].x = rclSrc.xLeft;
  77.     aptl[2].y = rclSrc.yBottom;
  78.     aptl[3].x = rclSrc.xRight;
  79.     aptl[3].y = rclSrc.yTop;
  80.  
  81.     if ( aptl[1].x - aptl[0].x == aptl[3].x - aptl[2].x &&
  82.          aptl[1].y - aptl[0].y == aptl[3].y - aptl[2].y )
  83.         GpiBitBlt(hpsDst, hpsSrc, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  84.     else
  85.         GpiBitBlt(hpsDst, hpsSrc, 4L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  86.  
  87.     GpiSetBitmap(hpsDst, (HBITMAP) NULL); GpiDestroyPS(hpsDst); DevCloseDC(hdcDst);
  88.     GpiSetBitmap(hpsSrc, (HBITMAP) NULL); GpiDestroyPS(hpsSrc); DevCloseDC(hdcSrc);
  89.  
  90.     return BMP_ERR_OK;
  91.     }
  92. /*...e*/
  93. /*...sBmpCopySubrectangle \45\ make a new bitmap from a bit of the first:0:*/
  94. BMP_ERR BmpCopySubrectangle(HAB hab, HBITMAP hbmSrc, RECTL rclSrc, HBITMAP *phbmDst)
  95.     {
  96.     BITMAPINFOHEADER2 bmp;
  97.     HBITMAP hbmDst;
  98.     RECTL rclDst;
  99.     SIZEL sizl;
  100.     USHORT rc;
  101.     HDC hdc;
  102.     HPS hps;
  103.  
  104.     bmp.cbFix = sizeof(BITMAPINFOHEADER2);
  105.     GpiQueryBitmapInfoHeader(hbmSrc, &bmp);
  106.  
  107.     bmp.cx = (USHORT) (rclSrc.xRight - rclSrc.xLeft);
  108.     bmp.cy = (USHORT) (rclSrc.yTop - rclSrc.yBottom);
  109.  
  110.     if ( (hdc = DevOpenDC(hab, OD_MEMORY, "*", 0L, (PDEVOPENDATA) NULL, (HDC) NULL)) == (HDC) NULL )
  111.         return BMP_ERR_RES;
  112.  
  113.     sizl.cx = bmp.cx; sizl.cy = bmp.cy;
  114.     if ( (hps = GpiCreatePS(hab, hdc, &sizl, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL )
  115.         {
  116.         DevCloseDC(hdc);
  117.         return BMP_ERR_RES;
  118.         }
  119.  
  120.     if ( (hbmDst = GpiCreateBitmap(hps, &bmp, 0L, NULL, NULL)) == (HBITMAP) NULL )
  121.         {
  122.         GpiDestroyPS(hps);
  123.         DevCloseDC(hdc);
  124.         return BMP_ERR_MEM;
  125.         }
  126.  
  127.     GpiDestroyPS(hps);
  128.     DevCloseDC(hdc);
  129.  
  130.     rclDst.xLeft = 0; rclDst.xRight = bmp.cx;
  131.     rclDst.yBottom = 0; rclDst.yTop = bmp.cy;
  132.  
  133.     if ( (rc = BmpBlitter(hab, hbmSrc, rclSrc, hbmDst, rclDst)) != BMP_ERR_OK )
  134.         {
  135.         GpiDeleteBitmap(hbmDst);
  136.         return rc;
  137.         }
  138.  
  139.     *phbmDst = hbmDst;
  140.  
  141.     return BMP_ERR_OK;
  142.     }
  143. /*...e*/
  144. /*...sBmpCopy             \45\ make a new bitmap from all of the first:0:*/
  145. BMP_ERR BmpCopy(HAB hab, HBITMAP hbmSrc, HBITMAP *phbmDst)
  146.     {
  147.     BITMAPINFOHEADER2 bmp;
  148.     RECTL rclSrc;
  149.  
  150.     bmp.cbFix = sizeof(BITMAPINFOHEADER2);
  151.     GpiQueryBitmapInfoHeader(hbmSrc, &bmp);
  152.  
  153.     rclSrc.xLeft = 0; rclSrc.xRight = bmp.cx;
  154.     rclSrc.yBottom = 0; rclSrc.yTop = bmp.cy;
  155.  
  156.     return BmpCopySubrectangle(hab, hbmSrc, rclSrc, phbmDst);
  157.     }
  158. /*...e*/
  159. /*...sBmpPrint            \45\ print a bitmap:0:*/
  160. /*...sEnquireQueueDetails:0:*/
  161. static BOOL EnquireQueueDetails(
  162.     CHAR *szQueue,
  163.     CHAR *szLogAddress,
  164.     CHAR *szDriverName,
  165.     CHAR *szNameWPS,
  166.     DRIVDATA **ppdriv
  167.     )
  168.     {
  169.     ULONG cb; PRQINFO3 *ppq3;
  170.  
  171.     SplQueryQueue(NULL, szQueue, 3, NULL, 0, &cb);
  172.     if ( cb < sizeof(PRQINFO3) )
  173.         return FALSE;
  174.     if ( (ppq3 = (PRQINFO3 *) malloc(cb)) == (PRQINFO3 *) NULL )
  175.         return FALSE;
  176.     SplQueryQueue(NULL, szQueue, 3, ppq3, cb, &cb);
  177.     strcpy(szNameWPS, ppq3 -> pszComment);
  178.     strcpy(szLogAddress, szQueue);
  179.     sscanf(ppq3 -> pszDriverName, "%[^.,;]", szDriverName);
  180.     *ppdriv = ppq3 -> pDriverData;
  181.     free(ppq3);
  182.     return TRUE;
  183.     }
  184. /*...e*/
  185. /*...sPrinterInfo:0:*/
  186. static BOOL PrinterInfo(HPS hpsPrinter, const CHAR *szNameWPS)
  187.     {
  188.     HDC hdcPrinter = GpiQueryDevice(hpsPrinter);
  189.     LONG lBitCount, lPlanes, lColors, lPhysColors;
  190.     SIZEL sizlPrinter;
  191.     CHAR sz[100+1];
  192.  
  193.     GpiQueryPS(hpsPrinter, &sizlPrinter);
  194.  
  195.     DevQueryCaps(hdcPrinter, CAPS_COLOR_BITCOUNT, 1L, &lBitCount  );
  196.     DevQueryCaps(hdcPrinter, CAPS_COLOR_PLANES  , 1L, &lPlanes    );
  197.     DevQueryCaps(hdcPrinter, CAPS_COLORS        , 1L, &lColors    );
  198.     DevQueryCaps(hdcPrinter, CAPS_PHYS_COLORS   , 1L, &lPhysColors);
  199.  
  200.     sprintf(sz, "%s: %ldx%ld, %ld bits, %ld planes, %ld colors, %ld physical colors?",
  201.         szNameWPS, sizlPrinter.cx, sizlPrinter.cy, lBitCount, lPlanes, lColors, lPhysColors);
  202.  
  203.     return WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, sz, "GbmV2 - Confirm Printer", 0, MB_OKCANCEL | MB_QUERY | MB_MOVEABLE) == MBID_OK;
  204.     }
  205. /*...e*/
  206. /*...sTransferBitmapData:0:*/
  207. /*
  208. Put the largest possible copy of the bitmap onto the printer presentation
  209. space. Preserve aspect ratio and correct for printer aspect ratio.
  210. */
  211.  
  212. /*...sMonoPrint:0:*/
  213. static BOOL MonoPrint(HPS hpsPrinter)
  214.     {
  215.     HDC hdcPrinter = GpiQueryDevice(hpsPrinter);
  216.     LONG lBitCount, lPlanes;
  217.  
  218.     DevQueryCaps(hdcPrinter, CAPS_COLOR_BITCOUNT, 1L, &lBitCount);
  219.     DevQueryCaps(hdcPrinter, CAPS_COLOR_PLANES  , 1L, &lPlanes  );
  220.  
  221.     return lBitCount == 1 && lPlanes == 1;
  222.     }
  223. /*...e*/
  224.  
  225. static BMP_ERR TransferBitmapData(
  226.     HAB hab,
  227.     HBITMAP hbm, LONG lColorFg, LONG lColorBg,
  228.     HDC hdcPrinter, HPS hpsPrinter
  229.     )
  230.     {
  231.     SIZEL sizlMemory, sizlPrinter, sizlImage;
  232.     SIZEL sizlMmPrinter, sizlMmImage; /* Sizes in mm */
  233.     HDC hdcMemory;
  234.     HPS hpsMemory;
  235.     POINTL aptl[4];
  236.     BITMAPINFOHEADER2 bmp;
  237.     LONG xRes, yRes, xCentre, yCentre;
  238.  
  239.     /* Query printer size */
  240.  
  241.     GpiQueryPS(hpsPrinter, &sizlPrinter);
  242.  
  243.     /* Query bitmap size */
  244.  
  245.     bmp.cbFix = sizeof(BITMAPINFOHEADER2);
  246.     GpiQueryBitmapInfoHeader(hbm, &bmp);
  247.     sizlMemory.cx = (LONG) bmp.cx;
  248.     sizlMemory.cy = (LONG) bmp.cy;
  249.  
  250.     /* Make a memory device context for the bitmap */
  251.  
  252.     if ( (hdcMemory = DevOpenDC(hab, OD_MEMORY, "*", 0L, NULL, hdcPrinter)) == (HPS) NULL )
  253.         return BMP_ERR_RES;
  254.  
  255.     if ( (hpsMemory = GpiCreatePS(hab, hdcMemory, &sizlMemory, PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)) == (HPS) NULL )
  256.         {
  257.         DevCloseDC(hdcMemory);
  258.         return BMP_ERR_RES;
  259.         }
  260.  
  261.     GpiSetBitmap(hpsMemory, hbm);
  262.  
  263.     /* Set colours ready for blitting into printer ps */
  264.  
  265.     if ( bmp.cBitCount == 1 )
  266.         {
  267.         GpiSetBackColor(hpsPrinter, GpiQueryColorIndex(hpsPrinter, 0, lColorBg));
  268.         GpiSetColor    (hpsPrinter, GpiQueryColorIndex(hpsPrinter, 0, lColorFg));
  269.         }
  270.  
  271. /*...sscale to fit page:8:*/
  272. /* Query printer aspect ratio */
  273.  
  274. DevQueryCaps(hdcPrinter, CAPS_HORIZONTAL_RESOLUTION, 1L, &xRes);
  275. DevQueryCaps(hdcPrinter, CAPS_VERTICAL_RESOLUTION  , 1L, &yRes);
  276.  
  277. /* Get size of page in mm */
  278.  
  279. sizlMmPrinter.cx = (1000L * sizlPrinter.cx) / xRes;
  280. sizlMmPrinter.cy = (1000L * sizlPrinter.cy) / yRes;
  281.  
  282. /* Get largest image size in mm */
  283.  
  284. if ( sizlMemory.cx * sizlMmPrinter.cy > sizlMemory.cy * sizlMmPrinter.cx )
  285.     /* Stretch to fill width */
  286.     {
  287.     sizlMmImage.cx = sizlMmPrinter.cx;
  288.     sizlMmImage.cy = (sizlMmImage.cx * sizlMemory.cy) / sizlMemory.cx;
  289.     }
  290. else
  291.     /* Stretch to fill height */
  292.     {
  293.     sizlMmImage.cy = sizlMmPrinter.cy;
  294.     sizlMmImage.cx = (sizlMmImage.cy * sizlMemory.cx) / sizlMemory.cy;
  295.     }
  296.  
  297. sizlImage.cx = (xRes * sizlMmImage.cx) / 1000L;
  298. sizlImage.cy = (yRes * sizlMmImage.cy) / 1000L;
  299.  
  300. xCentre = ((sizlPrinter.cx - sizlImage.cx) >> 1);
  301. yCentre = ((sizlPrinter.cy - sizlImage.cy) >> 1);
  302.  
  303. aptl[0].x = xCentre;
  304. aptl[0].y = yCentre;
  305. aptl[1].x = xCentre + sizlImage.cx;
  306. aptl[1].y = yCentre + sizlImage.cy;
  307. aptl[2].x = 0;
  308. aptl[2].y = 0;
  309. aptl[3].x = sizlMemory.cx;
  310. aptl[3].y = sizlMemory.cy;
  311.  
  312. GpiBitBlt(hpsPrinter, hpsMemory, 4L, aptl, ROP_SRCCOPY, 
  313.     MonoPrint(hpsPrinter) ? BBO_AND : BBO_IGNORE);
  314. /*...e*/
  315. #if 0
  316. /*...sposition in the middle if room:8:*/
  317. if ( sizlMemory.cx < sizlPrinter.cx &&
  318.      sizlMemory.cy < sizlPrinter.cy )
  319.     { 
  320.     xCentre = ((sizlPrinter.cx - sizlMemory.cx) >> 1);
  321.     yCentre = ((sizlPrinter.cy - sizlMemory.cy) >> 1);
  322.  
  323.     aptl[0].x = xCentre;
  324.     aptl[0].y = yCentre;
  325.     aptl[1].x = xCentre + sizlMemory.cx;
  326.     aptl[1].y = yCentre + sizlMemory.cy;
  327.     aptl[2].x = 0;
  328.     aptl[2].y = 0;
  329.  
  330.     GpiBitBlt(hpsPrinter, hpsMemory, 3L, aptl, ROP_SRCCOPY, BBO_IGNORE);
  331.     }
  332. /*...e*/
  333. #endif
  334.  
  335.     GpiSetBitmap(hpsMemory, (HBITMAP) NULL);
  336.     GpiDestroyPS(hpsMemory);
  337.     DevCloseDC(hdcMemory);
  338.  
  339.     return BMP_ERR_OK;
  340.     }
  341. /*...e*/
  342.  
  343. BMP_ERR BmpPrint(
  344.     HAB hab,
  345.     HBITMAP hbm, LONG lColorFg, LONG lColorBg,
  346.     const CHAR *szDocName,
  347.     const CHAR *szComment,
  348.     CHAR *szQueueToUse
  349.     )
  350.     {
  351.     static SIZEL sizl = { 0, 0 };
  352.     HDC hdcPrinter;
  353.     HPS hpsPrinter;
  354.     CHAR szLogAddress[256];
  355.     CHAR szDriverName[256];
  356.     CHAR szNameWPS[256];
  357.     DEVOPENSTRUC dop;
  358.     USHORT cb, usJobId;
  359.     CHAR szQueue[256];
  360.     BMP_ERR rc;
  361.     LONG lOutCount;
  362.     BOOL fQueried = FALSE;
  363.  
  364.     /* Set defaults, in case can't query information about printer */
  365.  
  366.     dop.pszLogAddress      = szLogAddress;
  367.     dop.pszDriverName      = szDriverName;
  368.     dop.pdriv              = NULL;
  369.     dop.pszDataType        = "PM_Q_STD";
  370.     dop.pszComment         = (PSZ) szComment;
  371.     dop.pszQueueProcName   = NULL;
  372.     dop.pszQueueProcParams = NULL;
  373.     dop.pszSpoolerParams   = NULL;
  374.     dop.pszNetworkParams   = NULL;
  375.  
  376.     if ( szQueueToUse != NULL )
  377.         /* Use the queue we have been told to use */
  378.         fQueried = EnquireQueueDetails(szQueueToUse, szLogAddress, szDriverName, szNameWPS, &dop.pdriv);
  379.     else if ( (cb = (USHORT) PrfQueryProfileString(HINI_PROFILE, "PM_SPOOLER",
  380.          "QUEUE", NULL, szQueue, (LONG) sizeof(szQueue))) > 0 )
  381.         /* Use application default queue */
  382.         {
  383.         szQueue[cb - 2] = '\0'; /* Remove semicolon at end */
  384.         fQueried = EnquireQueueDetails(szQueue, szLogAddress, szDriverName, szNameWPS, &dop.pdriv);
  385.         }
  386.  
  387.     if ( !fQueried )
  388.         return BMP_ERR_QUERY;
  389.  
  390.     /* Try to create printer device context */
  391.  
  392.     if ( (hdcPrinter = DevOpenDC(hab, OD_QUEUED, "*", 5L, (PDEVOPENDATA) &dop, (HDC) NULL)) == (HDC) NULL )
  393.         /* Failed to open printer device context */
  394.         return BMP_ERR_PRINTER;
  395.  
  396.     /* Create a presentation space of default size (size of page) */
  397.  
  398.     if ( (hpsPrinter = GpiCreatePS(hab, hdcPrinter, &sizl, PU_PELS | GPIF_DEFAULT | GPIA_ASSOC)) == (HPS) NULL )
  399.         /* Could not make presentation space */
  400.         {
  401.         DevCloseDC(hdcPrinter);
  402.         return BMP_ERR_PRINTER;
  403.         }
  404.  
  405.     /* Tell user about printer, and give chance to abort job */
  406.  
  407.     if ( !PrinterInfo(hpsPrinter, szNameWPS) )
  408.         {
  409.         GpiAssociate(hpsPrinter, (HDC) NULL);
  410.         GpiDestroyPS(hpsPrinter);
  411.         DevCloseDC(hdcPrinter);
  412.         return BMP_ERR_OK;
  413.         }
  414.  
  415.     /* Indicate a new print job is starting */
  416.  
  417.     if ( !DevEscape(hdcPrinter, DEVESC_STARTDOC, (LONG) strlen(szDocName),
  418.           (BYTE *) szDocName, &lOutCount, (BYTE *) NULL) )
  419.         {
  420.         GpiAssociate(hpsPrinter, (HDC) NULL);
  421.         GpiDestroyPS(hpsPrinter);
  422.         DevCloseDC(hdcPrinter);
  423.         return BMP_ERR_PRINT;
  424.         }
  425.  
  426.     GpiErase(hpsPrinter); /* Blank the page to CLR_BACKGROUND */
  427.  
  428.     if ( (rc = TransferBitmapData(hab, hbm, lColorFg, lColorBg, hdcPrinter, hpsPrinter)) != BMP_ERR_OK )
  429.         {
  430.         DevEscape(hdcPrinter, DEVESC_ABORTDOC, 0L, NULL, 0L, NULL);
  431.         GpiAssociate(hpsPrinter, (HDC) NULL);
  432.         GpiDestroyPS(hpsPrinter);
  433.         DevCloseDC(hdcPrinter);
  434.         return rc;
  435.         }
  436.  
  437.     /* Indicate the job is done */
  438.  
  439.     if ( !DevEscape(hdcPrinter, DEVESC_ENDDOC, 0L, (BYTE *) NULL, &lOutCount, (BYTE *) &usJobId) )
  440.         {
  441.         GpiAssociate(hpsPrinter, (HDC) NULL);
  442.         GpiDestroyPS(hpsPrinter);
  443.         DevCloseDC(hdcPrinter);
  444.         return BMP_ERR_PRINT;
  445.         }
  446.  
  447.     GpiAssociate(hpsPrinter, (HDC) NULL);
  448.     GpiDestroyPS(hpsPrinter);
  449.     DevCloseDC(hdcPrinter);
  450.  
  451.     return BMP_ERR_OK;
  452.     }
  453. /*...e*/
  454. /*...sBmpErrorMessage     \45\ get error message from error return code:0:*/
  455. CHAR *BmpErrorMessage(BMP_ERR rc, CHAR *sz)
  456.     {
  457.     static CHAR *aszBitmapErrors[] =
  458.         {
  459.         "",
  460.         "out of memory",
  461.         "out of resources",
  462.         "can't query printer/queue details",
  463.         "can't locate printer/queue",
  464.         "error sending data to printer/queue",
  465.         };
  466.  
  467.     return strcpy(sz, aszBitmapErrors[rc]);
  468.     }
  469. /*...e*/
  470.