Ignore:
Timestamp:
Oct 28, 2009, 2:20:27 AM (16 years ago)
Author:
Dmitry A. Kuminov
Message:

gui: QPixmap: Created OS/2 specific methods for converting pixmaps to HBITMAPs and HPOINTERs.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/gui/image/qpixmap_pm.cpp

    r95 r260  
    4545#include "qpixmap_raster_p.h"
    4646
     47#include "qicon.h"
     48
     49#include "qt_os2.h"
     50
    4751QT_BEGIN_NAMESPACE
     52
     53HPS qt_alloc_mem_ps(int w, int h, HPS compat = 0)
     54{
     55    HDC hdcCompat = NULLHANDLE;
     56    if (compat)
     57        hdcCompat = GpiQueryDevice(compat);
     58
     59    static const PSZ hdcData[4] = { "Display", NULL, NULL, NULL };
     60    HDC hdc = DevOpenDC(0, OD_MEMORY, "*", 4, (PDEVOPENDATA) hdcData, hdcCompat);
     61    if (!hdc) {
     62        qWarning( "alloc_mem_dc: DevOpenDC failed with %08lX!", WinGetLastError(0));
     63        return NULLHANDLE;
     64    }
     65    SIZEL size = { w, h };
     66    HPS hps = GpiCreatePS(0, hdc, &size, PU_PELS | GPIA_ASSOC | GPIT_MICRO);
     67    if (hps == NULLHANDLE) {
     68        qWarning("alloc_mem_dc: GpiCreatePS failed wit %08lX!", WinGetLastError(0));
     69        return NULLHANDLE;
     70    }
     71    // @todo later
     72//  if (QColor::hPal()) {
     73//      GpiSelectPalette(hps, QColor::hPal());
     74//  } else {
     75        // direct RGB mode
     76        GpiCreateLogColorTable(hps, 0, LCOLF_RGB, 0, 0, NULL);
     77//  }
     78    return hps;
     79}
     80
     81void qt_free_mem_ps(HPS hps)
     82{
     83    HDC hdc = GpiQueryDevice(hps);
     84    GpiAssociate(hps, NULLHANDLE);
     85    GpiDestroyPS(hps);
     86    DevCloseDC(hdc);
     87}
     88
     89/*!
     90    Creates a \c HBITMAP equivalent to the QPixmap. Returns the \c HBITMAP
     91    handle.
     92
     93    If \a mask is not NULL, the mask mode is turned. In this mode, the bitmap
     94    mask is also created from the QPixmap's mask and returned in the given
     95    variable. This bitmap mask will contain two vertically adjacent sections,
     96    the first of which is the AND mask and the second one is the XOR mask
     97    (according to WinCreatePointer() specification). Also, in mask mode, the
     98    HBITMAP returned for the pixmap itself will be prepared for masking (with
     99    transparent pixels made black). This mode is useful for creating system
     100    icons and pointers (\sa toPmHPOINTER()).
     101
     102    Note that if the pixmap does neither have a maks nor the alpha channel but
     103    \a mask is not NULL, a NULLHANDLE value will be stored there.
     104
     105    It is the caller's responsibility to free both returned \c HBITMAP handes
     106    after use.
     107
     108    \warning This function is only available on OS/2.
     109*/
     110HBITMAP QPixmap::toPmHBITMAP(HBITMAP *mask) const
     111{
     112    if (data->classId() != QPixmapData::RasterClass) {
     113        QPixmapData *data = new QRasterPixmapData(depth() == 1 ?
     114                                                  QPixmapData::BitmapType : QPixmapData::PixmapType);
     115        data->fromImage(toImage(), Qt::AutoColor);
     116        return QPixmap(data).toPmHBITMAP(mask);
     117    }
     118
     119    QRasterPixmapData* d = static_cast<QRasterPixmapData*>(data);
     120    int w = d->image.width();
     121    int h = d->image.height();
     122
     123    HPS hps = qt_alloc_mem_ps(w, h);
     124    if (hps == NULLHANDLE)
     125        return NULLHANDLE;
     126
     127    HBITMAP hbm = NULLHANDLE;
     128    HBITMAP hbmMask = NULLHANDLE;
     129
     130    QImage image = d->image.convertToFormat(QImage::Format_ARGB32).mirrored();
     131
     132    // bitmap header + 2 palette entries (for the mask)
     133    char bmi[sizeof(BITMAPINFOHEADER2) + 4 * 2];
     134    memset(bmi, 0, sizeof(bmi));
     135    BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2)bmi;
     136    bmh.cbFix = sizeof(BITMAPINFOHEADER2);
     137    PULONG pal = (PULONG)(bmi + sizeof(BITMAPINFOHEADER2));
     138
     139    // create the normal bitmap from the pixmap data
     140    bmh.cx = w;
     141    bmh.cy = h;
     142    bmh.cPlanes = 1;
     143    bmh.cBitCount = 32;
     144    hbm = GpiCreateBitmap(hps, &bmh, CBM_INIT, (PBYTE)(const uchar *)image.bits(),
     145                          (PBITMAPINFO2)&bmi);
     146
     147    if (mask && hasAlpha()) {
     148        // get the mask. We prefer QImage::createAlphaMask() over QPixmap::mask()
     149        // since the former will dither while the latter will convert any
     150        // non-zero alpha value to an opaque pixel
     151        QImage mask = image.createAlphaMask().mirrored();
     152
     153        // create the mask bitmap (AND and XOR stripes)
     154        bmh.cbFix = sizeof(BITMAPINFOHEADER2);
     155        bmh.cx = w;
     156        bmh.cy = h;
     157        bmh.cPlanes = 1;
     158        bmh.cBitCount = 1;
     159        bmh.cclrUsed = 2;
     160        pal[0] = 0;
     161        pal[1] = 0x00FFFFFF;
     162        hbmMask = GpiCreateBitmap(hps, &bmh, 0, NULL, NULL);
     163
     164        // create AND mask (XOR mask is left zeroed -- it's okay)
     165        GpiSetBitmap(hps, hbmMask);
     166
     167        POINTL ptls[] = {
     168            { 0, h }, { w - 1, h * 2 - 1 }, // dst: inclusive-inclusive
     169            { 0, 0 }, { w, h }, // src: inclusive-exclusive
     170        };
     171        GpiDrawBits(hps, (PBYTE)(const uchar *)mask.bits(), (PBITMAPINFO2)&bmi,
     172                    4, ptls, ROP_NOTSRCCOPY, BBO_IGNORE);
     173
     174        // prepare the bitmap for masking by setting transparent pixels to black
     175        GpiSetBitmap(hps, hbmMask);
     176
     177        ptls[0].y -= h;
     178        ptls[1].y -= h;
     179        enum { AllImageAttrs = IBB_COLOR | IBB_BACK_COLOR |
     180                               IBB_MIX_MODE | IBB_BACK_MIX_MODE };
     181        IMAGEBUNDLE ib = { CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT };
     182        GpiSetAttrs(hps, PRIM_IMAGE, AllImageAttrs, 0, (PBUNDLE)&ib);
     183        GpiDrawBits(hps, (PBYTE)(const uchar *)mask.bits(), (PBITMAPINFO2)&bmi,
     184                    4, ptls, ROP_SRCAND, BBO_IGNORE);
     185    }
     186
     187    qt_free_mem_ps(hps);
     188
     189    if (mask)
     190        *mask = hbmMask;
     191
     192    return hbm;
     193}
     194
     195/*!
     196    Creates a \c HPOINTER from the given QIcon. Returns the \c HPOINTER handle.
     197
     198    If \a isPointer is \c true, an icon size closest to the system pointer size
     199    is chosen, otherwise to the system icon size. \a hotX and \a hotY define the
     200    hot spot.
     201
     202    It is the caller's responsibility to free the \c HPOINTER data
     203    after use.
     204
     205    \warning This function is only available on OS/2.
     206*/
     207// static
     208HPOINTER QPixmap::toPmHPOINTER(const QIcon &icon, bool isPointer,
     209                               int hotX, int hotY)
     210{
     211    if (icon.isNull())
     212        return NULLHANDLE;
     213
     214    int w = WinQuerySysValue(HWND_DESKTOP, isPointer ? SV_CXPOINTER : SV_CXICON);
     215    int h = WinQuerySysValue(HWND_DESKTOP, isPointer ? SV_CYPOINTER : SV_CYICON);
     216    QSize size = icon.actualSize(QSize(w, h));
     217    QSize sizeMini = icon.actualSize(QSize(w / 2, h / 2));
     218
     219    QPixmap pm = icon.pixmap(size);
     220    QPixmap pmMini = icon.pixmap(sizeMini);
     221    if (pm.isNull() && pmMini.isNull())
     222        return NULLHANDLE;
     223
     224    if (pm.isNull()) {
     225        // if we only have the mini icon, use it as a normal one;
     226        // WinCreatePointerIndirect() will figure that and not scale it
     227        pm = pmMini;
     228        pmMini = QPixmap();
     229    }
     230
     231    POINTERINFO info;
     232    info.fPointer = isPointer;
     233    info.xHotspot = hotX;
     234    info.yHotspot = hotY;
     235    info.hbmColor = pm.toPmHBITMAP(&info.hbmPointer);
     236    if (!pmMini.isNull())
     237    info.hbmMiniColor = pmMini.toPmHBITMAP(&info.hbmMiniPointer);
     238
     239    HPOINTER hIcon = WinCreatePointerIndirect(HWND_DESKTOP, &info);
     240
     241    GpiDeleteBitmap(info.hbmPointer);
     242    GpiDeleteBitmap(info.hbmColor);
     243    GpiDeleteBitmap(info.hbmMiniPointer);
     244    GpiDeleteBitmap(info.hbmMiniColor);
     245
     246    return hIcon;
     247}
    48248
    49249QPixmap QPixmap::grabWindow(WId winId, int x, int y, int w, int h )
Note: See TracChangeset for help on using the changeset viewer.