diff mupdf-source/thirdparty/leptonica/src/leptwin.c @ 2:b50eed0cc0ef upstream

ADD: MuPDF v1.26.7: the MuPDF source as downloaded by a default build of PyMuPDF 1.26.4. The directory name has changed: no version number in the expanded directory now.
author Franz Glasner <fzglas.hg@dom66.de>
date Mon, 15 Sep 2025 11:43:07 +0200
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mupdf-source/thirdparty/leptonica/src/leptwin.c	Mon Sep 15 11:43:07 2025 +0200
@@ -0,0 +1,363 @@
+/*====================================================================*
+ -  Copyright (C) 2001 Leptonica.  All rights reserved.
+ -
+ -  Redistribution and use in source and binary forms, with or without
+ -  modification, are permitted provided that the following conditions
+ -  are met:
+ -  1. Redistributions of source code must retain the above copyright
+ -     notice, this list of conditions and the following disclaimer.
+ -  2. Redistributions in binary form must reproduce the above
+ -     copyright notice, this list of conditions and the following
+ -     disclaimer in the documentation and/or other materials
+ -     provided with the distribution.
+ -
+ -  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ -  ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ -  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ -  A PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL ANY
+ -  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ -  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ -  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ -  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ -  OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ -  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ -  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *====================================================================*/
+
+/*!
+ * \file leptwin.c
+ * <pre>
+ *
+ *    This file contains Leptonica routines needed only on Microsoft Windows
+ *
+ *    Currently it only contains one public function
+ *    (based on dibsectn.c by jmh, 03-30-98):
+ *
+ *      HBITMAP    pixGetWindowsHBITMAP(PIX *pix)
+ * </pre>
+ */
+
+#ifdef _WIN32
+#include <stdlib.h>
+#include <string.h>
+#include "allheaders.h"
+#include "leptwin.h"
+
+/* Macro to determine the number of bytes per line in the DIB bits.
+ * This accounts for DWORD alignment by adding 31 bits,
+ * then dividing by 32, then rounding up to the next highest
+ * count of 4-bytes.  Then, we multiply by 4 to get the total byte count.  */
+#define BYTESPERLINE(Width, BPP) ((l_int32)((((DWORD)(Width) * (DWORD)(BPP) + 31) >> 5)) << 2)
+
+
+/* **********************************************************************
+  DWORD DSImageBitsSize(LPBITMAPINFO pbmi)
+
+  PARAMETERS:
+    LPBITMAPINFO - pointer to a BITMAPINFO describing a DIB
+
+  RETURNS:
+    DWORD    - the size, in bytes, of the DIB's image bits
+
+  REMARKS:
+    Calculates and returns the size, in bytes, of the image bits for
+    the DIB described by the BITMAPINFO.
+********************************************************************** */
+static DWORD
+DSImageBitsSize(LPBITMAPINFO pbmi)
+{
+    switch(pbmi->bmiHeader.biCompression)
+    {
+    case BI_RLE8:  /* wrong if haven't called DSCreateDIBSection or
+                    * CreateDIBSection with this pbmi */
+    case BI_RLE4:
+        return pbmi->bmiHeader.biSizeImage;
+
+	default:  /* should not have to use "default" */
+    case BI_RGB:
+    case BI_BITFIELDS:
+        return BYTESPERLINE(pbmi->bmiHeader.biWidth, \
+                   pbmi->bmiHeader.biBitCount * pbmi->bmiHeader.biPlanes) *
+               pbmi->bmiHeader.biHeight;
+    }
+}
+
+/* **********************************************************************
+  DWORD ImageBitsSize(HBITMAP hbitmap)
+
+  PARAMETERS:
+    HBITMAP - hbitmap
+
+  RETURNS:
+    DWORD    - the size, in bytes, of the HBITMAP's image bits
+
+  REMARKS:
+    Calculates and returns the size, in bytes, of the image bits for
+    the DIB described by the HBITMAP.
+********************************************************************** */
+static DWORD
+ImageBitsSize(HBITMAP hBitmap)
+{
+    DIBSECTION  ds;
+
+    GetObject(hBitmap, sizeof(DIBSECTION), &ds);
+    switch( ds.dsBmih.biCompression )
+    {
+    case BI_RLE8:  /* wrong if haven't called DSCreateDIBSection or
+                    * CreateDIBSection with this pbmi */
+    case BI_RLE4:
+        return ds.dsBmih.biSizeImage;
+
+	default:  /* should not have to use "default" */
+    case BI_RGB:
+    case BI_BITFIELDS:
+        return BYTESPERLINE(ds.dsBmih.biWidth, \
+                            ds.dsBmih.biBitCount * ds.dsBmih.biPlanes) *
+                            ds.dsBmih.biHeight;
+    }
+}
+
+/*!
+ * \brief   setColormap(LPBITMAPINFO pbmi, PIXCMAP *cmap)
+ *
+ * \param[in]    pbmi pointer to a BITMAPINFO describing a DIB
+ * \param[in]    cmap leptonica colormap
+ * \return  number of colors in cmap
+ */
+static int
+setColormap(LPBITMAPINFO  pbmi,
+            PIXCMAP      *cmap)
+{
+l_int32  i, nColors, rval, gval, bval;
+
+    nColors = pixcmapGetCount(cmap);
+    for (i = 0; i < nColors; i++) {
+        pixcmapGetColor(cmap, i, &rval, &gval, &bval);
+        pbmi->bmiColors[i].rgbRed = rval;
+        pbmi->bmiColors[i].rgbGreen = gval;
+        pbmi->bmiColors[i].rgbBlue = bval;
+        pbmi->bmiColors[i].rgbReserved = 0;
+    }
+    pbmi->bmiHeader.biClrUsed = nColors;
+    return nColors;
+}
+
+/* **********************************************************************
+  HBITMAP DSCreateBitmapInfo(l_int32 width, l_int32 height, l_int32 depth,
+                             PIXCMAP *cmap)
+
+  PARAMETERS:
+    l_int32 width - Desired width of the DIBSection
+    l_int32 height - Desired height of the DIBSection
+    l_int32 depth - Desired bit-depth of the DIBSection
+    PIXCMAP cmap - leptonica colormap for depths < 16
+
+  RETURNS:
+    LPBITMAPINFO - a ptr to BITMAPINFO of the desired size and bit-depth
+                   NULL on failure
+
+  REMARKS:
+    Creates a BITMAPINFO based on the criteria passed in as parameters.
+
+********************************************************************** */
+static LPBITMAPINFO
+DSCreateBitmapInfo(l_int32 width,
+                   l_int32 height,
+                   l_int32 depth,
+                   PIXCMAP *cmap)
+{
+l_int32       nInfoSize;
+LPBITMAPINFO  pbmi;
+LPDWORD       pMasks;
+
+    nInfoSize = sizeof(BITMAPINFOHEADER);
+    if( depth <= 8 )
+        nInfoSize += sizeof(RGBQUAD) * (1 << depth);
+    if((depth == 16) || (depth == 32))
+        nInfoSize += (3 * sizeof(DWORD));
+
+        /* Create the header big enough to contain color table and
+         * bitmasks if needed. */
+    pbmi = (LPBITMAPINFO)malloc(nInfoSize);
+    if (!pbmi)
+        return NULL;
+
+    ZeroMemory(pbmi, nInfoSize);
+    pbmi->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
+    pbmi->bmiHeader.biWidth = width;
+    pbmi->bmiHeader.biHeight = height;
+    pbmi->bmiHeader.biPlanes = 1;
+    pbmi->bmiHeader.biBitCount = depth;
+
+        /* override below for 16 and 32 bpp */
+    pbmi->bmiHeader.biCompression = BI_RGB;
+
+        /*  ?? not sure if this is right?  */
+    pbmi->bmiHeader.biSizeImage = DSImageBitsSize(pbmi);
+
+    pbmi->bmiHeader.biXPelsPerMeter = 0;
+    pbmi->bmiHeader.biYPelsPerMeter = 0;
+    pbmi->bmiHeader.biClrUsed = 0;  /* override below */
+    pbmi->bmiHeader.biClrImportant = 0;
+
+    switch(depth)
+    {
+        case 24:
+                /* 24bpp requires no special handling */
+            break;
+        case 16:
+                /* if it's 16bpp, fill in the masks and override the
+                 * compression.  These are the default masks -- you
+                 * could change them if needed. */
+            pMasks = (LPDWORD)(pbmi->bmiColors);
+            pMasks[0] = 0x00007c00;
+            pMasks[1] = 0x000003e0;
+            pMasks[2] = 0x0000001f;
+            pbmi->bmiHeader.biCompression = BI_BITFIELDS;
+            break;
+        case 32:
+                /* if it's 32 bpp, fill in the masks and override
+                 * the compression */
+            pMasks = (LPDWORD)(pbmi->bmiColors);
+            /*pMasks[0] = 0x00ff0000; */
+            /*pMasks[1] = 0x0000ff00; */
+            /*pMasks[2] = 0x000000ff; */
+            pMasks[0] = 0xff000000;
+            pMasks[1] = 0x00ff0000;
+            pMasks[2] = 0x0000ff00;
+
+            pbmi->bmiHeader.biCompression = BI_BITFIELDS;
+            break;
+        case 8:
+        case 4:
+        case 1:
+            setColormap(pbmi, cmap);
+            break;
+    }
+    return pbmi;
+}
+
+/* **********************************************************************
+  HBITMAP DSCreateDIBSection(l_int32 width, l_int32 height, l_int32 depth,
+                             PIXCMAP *cmap)
+
+  PARAMETERS:
+    l_int32 width - Desired width of the DIBSection
+    l_int32 height - Desired height of the DIBSection
+    l_int32 depth - Desired bit-depth of the DIBSection
+    PIXCMAP cmap - leptonica colormap for depths < 16
+
+  RETURNS:
+    HBITMAP      - a DIBSection HBITMAP of the desired size and bit-depth
+                   NULL on failure
+
+  REMARKS:
+    Creates a DIBSection based on the criteria passed in as parameters.
+
+********************************************************************** */
+static HBITMAP
+DSCreateDIBSection(l_int32  width,
+                   l_int32  height,
+                   l_int32  depth,
+                   PIXCMAP  *cmap)
+{
+HBITMAP       hBitmap;
+l_int32       nInfoSize;
+LPBITMAPINFO  pbmi;
+HDC           hRefDC;
+LPBYTE        pBits;
+
+    pbmi = DSCreateBitmapInfo (width, height, depth, cmap);
+    if (!pbmi)
+        return NULL;
+
+    hRefDC = GetDC(NULL);
+    hBitmap = CreateDIBSection(hRefDC, pbmi, DIB_RGB_COLORS,
+                               (void **) &pBits, NULL, 0);
+    nInfoSize = GetLastError();
+    ReleaseDC(NULL, hRefDC);
+    free(pbmi);
+
+    return hBitmap;
+}
+
+
+/*!
+ * \brief   pixGetWindowsHBITMAP()
+ *
+ * \param[in]    pix
+ * \return  Windows hBitmap, or NULL on error
+ *
+ * <pre>
+ * Notes:
+ *      (1) It's the responsibility of the caller to destroy the
+ *          returned hBitmap with a call to DeleteObject (or with
+ *          something that eventually calls DeleteObject).
+ * </pre>
+ */
+HBITMAP
+pixGetWindowsHBITMAP(PIX  *pix)
+{
+l_int32    width, height, depth;
+l_uint32  *data;
+HBITMAP    hBitmap = NULL;
+BITMAP     bm;
+DWORD      imageBitsSize;
+PIX       *pixt = NULL;
+PIXCMAP   *cmap;
+
+    if (!pix)
+        return (HBITMAP)ERROR_PTR("pix not defined", __func__, NULL);
+
+    pixGetDimensions(pix, &width, &height, &depth);
+    cmap = pixGetColormap(pix);
+
+    if (depth == 24) depth = 32;
+    if (depth == 2) {
+        pixt = pixConvert2To8(pix, 0, 85, 170, 255, TRUE);
+        if (!pixt)
+            return (HBITMAP)ERROR_PTR("unable to convert pix from 2bpp to 8bpp",
+                    __func__, NULL);
+        depth = pixGetDepth(pixt);
+        cmap = pixGetColormap(pixt);
+    }
+
+    if (depth < 16) {
+        if (!cmap)
+            cmap = pixcmapCreateLinear(depth, 1<<depth);
+    }
+
+    hBitmap = DSCreateDIBSection(width, height, depth, cmap);
+    if (!hBitmap)
+        return (HBITMAP)ERROR_PTR("Unable to create HBITMAP", __func__, NULL);
+
+        /* By default, Windows assumes bottom up images */
+    if (pixt)
+        pixt = pixFlipTB(pixt, pixt);
+    else
+        pixt = pixFlipTB(NULL, pix);
+
+        /* "standard" color table assumes bit off=black */
+    if (depth == 1) {
+        pixInvert(pixt, pixt);
+    }
+
+        /* Don't byte swap until done manipulating pix! */
+    if (depth <= 16)
+        pixEndianByteSwap(pixt);
+
+    GetObject (hBitmap, sizeof(BITMAP), &bm);
+    imageBitsSize = ImageBitsSize(hBitmap);
+    data = pixGetData(pixt);
+    if (data) {
+        memcpy (bm.bmBits, data, imageBitsSize);
+    } else {
+        DeleteObject (hBitmap);
+        hBitmap = NULL;
+    }
+    pixDestroy(&pixt);
+
+    return hBitmap;
+}
+
+#endif   /* _WIN32 */