Changeset 59


Ignore:
Timestamp:
Jan 29, 2006, 8:56:21 PM (20 years ago)
Author:
dmik
Message:

Implemented alpha blending for pixmaps.
Improved blitting of masked pixmaps.

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/qpixmap.h

    r56 r59  
    217217        HBITMAP hbm;
    218218        HBITMAP maskedHbm;  // pixmap precomposed for masking
    219 //@@TODO (dmik): need this?       
     219        bool hasRealAlpha;
    220220        uchar *realAlphaBits;
    221221#elif defined(Q_WS_X11)
     
    254254                                   int sw, int sh, bool useDstAlpha );
    255255#elif defined(Q_WS_PM)
    256     void prepareForMasking( bool prepare );
     256    void prepareForMasking( bool prepare, bool force = FALSE );
    257257    HPOINTER createIcon( bool pointer, int hotX, int hotY, bool mini );
    258258    void attachHandle( HBITMAP hbm );
    259259    HBITMAP detachHandle();
     260    void unfoldAlphaChannel();
     261    void convertToAlpha();
     262    static int trueColorDepth();
    260263    friend class QPMMimeImage;
    261264#endif
  • trunk/src/kernel/qpaintdevice_pm.cpp

    r8 r59  
    125125
    126126// draws the pixmap with a mask using the black source method
    127 void drawMaskedPixmap(
    128     HPS dst_ps, int dst_depth, HPS src_ps, int src_w, int src_h, HPS mask_ps,
    129     int dx, int dy, int sx, int sy, int w, int h, Qt::RasterOp rop
    130 ) {
    131     // all rectangles for different operations combined together
    132     POINTL ptls[] = {
    133         { dx, dy }, { dx + w, dy + h },         // 0: src/buf => dst
    134         { sx, sy }, { sx + w, sy + h },         // 2: src <=> buf
    135         { sx, sy }, { sx + w, sy + h },         // 4: dst => buf
    136         { dx, dy }
    137     };
     127static void drawMaskedPixmap(
     128    HPS dst_ps, int dst_depth, bool grab_dest, HPS src_ps, HPS mask_ps,
     129    int dx, int dy, int sx, int sy, int w, int h, Qt::RasterOp rop )
     130{
    138131    IMAGEBUNDLE oldIb;
    139132
    140133    if ( !mask_ps ) {
    141134        // self-masked pixmap
     135        POINTL ptls[] = { { dx, dy }, { dx + w, dy + h },
     136                          { sx, sy } };
    142137        IMAGEBUNDLE newIb;
    143138        GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, (PBUNDLE) &oldIb );
     
    148143    } else {
    149144        bool simple = (rop == Qt::CopyROP) || (rop == Qt::XorROP);
    150         // helper hps for dblbuf
    151         HPS hpsBuf = qt_alloc_mem_ps( src_w, simple ? src_h : src_h * 2, dst_ps );
    152         // helper bitmap for dblbuf
    153         BITMAPINFOHEADER2 bmh;
    154         memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
    155         bmh.cbFix = sizeof(BITMAPINFOHEADER2);
    156         bmh.cx = src_w;
    157         bmh.cy = simple ? src_h : src_h * 2;
    158         bmh.cPlanes = 1;
    159         bmh.cBitCount = dst_depth;
    160         HBITMAP hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
    161         GpiSetBitmap( hpsBuf, hbmBuf );
    162 
     145        // origial helper buffer handles
     146        HPS hpsBuf = 0;
     147        HBITMAP hbmBuf = 0;
     148        // two pointers to the helper buffer
     149        HPS hpsBuf1 = dst_ps;
     150        HPS hpsBuf2 = 0;
     151        // first helper buffer's coordinates
     152        int buf1_x = dx, buf1_y = dy;
     153        // second helper buffer's coordinates
     154        int buf2_x = -1, buf2_y = -1;
     155       
     156        if ( grab_dest || !simple ) {
     157            // create the helper buffer (we need two buffers if grab_dest and
     158            // not simple -- double the height in this case)
     159            BITMAPINFOHEADER2 bmh;
     160            memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
     161            bmh.cbFix = sizeof(BITMAPINFOHEADER2);
     162            bmh.cx = w;
     163            bmh.cy = grab_dest && !simple ? h * 2 : h;
     164            bmh.cPlanes = 1;
     165            bmh.cBitCount = dst_depth;
     166            hpsBuf = qt_alloc_mem_ps( bmh.cx, bmh.cy, dst_ps );
     167            hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
     168            GpiSetBitmap( hpsBuf, hbmBuf );
     169            // setup buffer handles and coordinates
     170            if ( grab_dest && !simple ) {
     171                hpsBuf1 = hpsBuf2 = hpsBuf;
     172                buf1_x = buf1_y = 0;
     173                buf2_x = 0;
     174                buf2_y = h;
     175            } else if ( grab_dest ) {
     176                hpsBuf1 = hpsBuf;
     177                buf1_x = buf1_y = 0;
     178            } else { // i.e. !grab_dest && !simple
     179                hpsBuf2 = hpsBuf;
     180                buf2_x = buf2_y = 0;
     181            }
     182        }
     183
     184        // save current destination colors
     185        ULONG oldColor = GpiQueryColor( dst_ps );
     186        ULONG oldBackColor = GpiQueryBackColor( dst_ps );
     187       
    163188        // query the destination color for 1-bpp bitmaps
    164189        GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_COLOR, (PBUNDLE) &oldIb );
    165         // setup colors for the masking
    166         GpiSetColor( hpsBuf, CLR_TRUE );
    167         GpiSetBackColor( hpsBuf, CLR_FALSE );
    168 
    169         // grab the destination
    170         GpiBitBlt( hpsBuf, dst_ps, 3, &ptls[4], ROP_SRCCOPY, BBO_IGNORE );
     190        // setup colors for masking
     191        GpiSetColor( hpsBuf1, CLR_TRUE );
     192        GpiSetBackColor( hpsBuf1, CLR_FALSE );
     193        if ( hpsBuf2 != hpsBuf1 ) {
     194            GpiSetColor( hpsBuf2, CLR_TRUE );
     195            GpiSetBackColor( hpsBuf2, CLR_FALSE );
     196        }
     197
     198        if ( grab_dest ) {
     199            // grab the destination
     200            POINTL ptls[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
     201                              { dx, dy } };
     202            GpiBitBlt( hpsBuf1, dst_ps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
     203        }
     204       
     205        // compose a masked pixmap with a given rop into the second buffer
     206        if ( !simple ) {
     207            // grab the destination to the 2nd buffer
     208            POINTL ptDB2[] = { { buf2_x, buf2_y }, { buf2_x + w, buf2_y + h },
     209                               { dx, dy } };
     210            GpiBitBlt( hpsBuf2, dst_ps, 3, ptDB2, ROP_SRCCOPY, BBO_IGNORE );
     211            // bitblt pixmap using rop
     212            POINTL ptSB2[] = { { buf2_x, buf2_y }, { buf2_x + w, buf2_y + h },
     213                               { sx, sy } };
     214            GpiSetColor( hpsBuf2, oldIb.lColor );
     215            GpiBitBlt( hpsBuf2, src_ps, 3, ptSB2, qt_ropCodes_2ROP[rop], BBO_IGNORE );
     216            // make transparent pixels black
     217            GpiSetColor( hpsBuf2, CLR_TRUE );
     218            GpiBitBlt( hpsBuf2, mask_ps, 3, ptSB2, ROP_SRCAND, BBO_IGNORE );
     219        }
     220
    171221        // draw the mask: make non-transparent pixels (corresponding to
    172222        // ones in the mask) black. skip this step when rop = XorROP
    173223        // to get the XOR effect.
    174         if ( rop != Qt::XorROP )
    175             GpiBitBlt( hpsBuf, mask_ps, 3, &ptls[2], 0x22, BBO_IGNORE );
    176 
    177         // compose a masked pixmap with a given rop into the second buffer
     224        if ( rop != Qt::XorROP ) {
     225            POINTL ptls[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
     226                              { sx, sy } };
     227            GpiBitBlt( hpsBuf1, mask_ps, 3, ptls, 0x22, BBO_IGNORE );
     228        }
     229       
    178230        if ( !simple ) {
    179             // grab the destination to the 2nd buffer
    180             ptls[4].y += h; ptls[5].y += h;
    181             GpiBitBlt( hpsBuf, dst_ps, 3, &ptls[4], ROP_SRCCOPY, BBO_IGNORE );
    182             ptls[4].y -= h; ptls[5].y -= h;
    183             // bitblt pixmap using rop
    184             ptls[2].y += h; ptls[3].y += h;
    185             GpiSetColor( hpsBuf, oldIb.lColor );
    186             GpiBitBlt( hpsBuf, src_ps, 3, &ptls[2], qt_ropCodes_2ROP[rop], BBO_IGNORE );
    187             // make transparent pixels black
    188             GpiSetColor( hpsBuf, CLR_TRUE );
    189             GpiBitBlt( hpsBuf, mask_ps, 3, &ptls[2], ROP_SRCAND, BBO_IGNORE );
    190             // draw masked pixmap from the 2nd buffer to the 1rd
    191             ptls[2].y -= h; ptls[3].y -= h;
    192             ptls[4].y += h; ptls[5].y += h;
    193             GpiBitBlt( hpsBuf, hpsBuf, 3, &ptls[2], ROP_SRCPAINT, BBO_IGNORE );
     231            // draw masked pixmap from the 2nd buffer to the 1st
     232            POINTL ptB2B1[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
     233                                { buf2_x, buf2_y } };
     234            GpiBitBlt( hpsBuf1, hpsBuf2, 3, ptB2B1, ROP_SRCPAINT, BBO_IGNORE );
    194235        } else {
    195236            // draw masked pixmap; transparent pixels are zeroed there
    196237            // by prepareForMasking( TRUE )
    197             GpiSetColor( hpsBuf, oldIb.lColor );
    198             GpiBitBlt( hpsBuf, src_ps, 3, &ptls[2], ROP_SRCINVERT, BBO_IGNORE );
     238            POINTL ptls[] = { { buf1_x, buf1_y }, { buf1_x + w, buf1_y + h },
     239                              { sx, sy } };
     240            GpiSetColor( hpsBuf1, oldIb.lColor );
     241            GpiBitBlt( hpsBuf1, src_ps, 3, ptls, ROP_SRCINVERT, BBO_IGNORE );
    199242        }
    200243
    201244        // flush the buffer
    202         GpiBitBlt( dst_ps, hpsBuf, 3, &ptls[0], ROP_SRCCOPY, BBO_IGNORE );
     245        if ( hpsBuf1 != dst_ps ) {
     246            POINTL ptls[] = { { dx, dy }, { dx + w, dy + h },
     247                              { buf1_x, buf1_y } };
     248            GpiBitBlt( dst_ps, hpsBuf1, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
     249        }
     250       
    203251        // free resources
     252        if ( hpsBuf ) {
     253            GpiSetBitmap( hpsBuf, 0 );
     254            GpiDeleteBitmap( hbmBuf );
     255            qt_free_mem_ps( hpsBuf );
     256        }
     257       
     258        // restore current destination colors
     259        GpiSetColor( dst_ps, oldColor );
     260        GpiSetBackColor( dst_ps, oldBackColor );
     261    }
     262}
     263
     264// draws the pixmap with a mask using the black source method
     265static void drawAlphaPixmap (
     266    HPS dst_ps, int dst_w, HPS src_ps, int src_w, uchar *alpha,
     267    int dx, int dy, int sx, int sy, int w, int h, int depth )
     268{
     269    Q_ASSERT( depth == 32 || depth == 24 );
     270
     271    bool grab_dest = false;
     272    int dst_x = dx;
     273   
     274    if ( dst_w == 0 ) {
     275        grab_dest = true;
     276        dst_w = w;
     277        dst_x = 0;
     278    }
     279   
     280    int dst_bpl = ((depth * dst_w + 31) / 32) * 4;
     281    int src_bpl = ((depth * src_w + 31) / 32) * 4;
     282   
     283    uchar *dst = new uchar [dst_bpl * h];
     284    uchar *src = new uchar [src_bpl * h];
     285   
     286    BITMAPINFOHEADER2 bmh;
     287    memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
     288    bmh.cbFix = sizeof(BITMAPINFOHEADER2);
     289    bmh.cPlanes = 1;
     290    bmh.cBitCount = depth;
     291    if ( grab_dest ) {
     292        bmh.cx = w;
     293        bmh.cy = h;
     294       
     295        // helper hps for dblbuf
     296        HPS hpsBuf = qt_alloc_mem_ps( w, h, dst_ps );
     297        // helper bitmap for dblbuf
     298        HBITMAP hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
     299        GpiSetBitmap( hpsBuf, hbmBuf );
     300       
     301        // grab the destination and get bits
     302        POINTL ptls[] = { { 0, 0 }, { w, h }, { dx, dy } };
     303        GpiBitBlt ( hpsBuf, dst_ps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
     304        GpiQueryBitmapBits( hpsBuf, 0, h, (PBYTE) dst, (PBITMAPINFO2) &bmh );
     305   
     306        // free dblbuf
    204307        GpiSetBitmap( hpsBuf, 0 );
    205308        GpiDeleteBitmap( hbmBuf );
    206309        qt_free_mem_ps( hpsBuf );
    207     }
    208 }
    209 
    210 //@@TODO (dmik): later
    211 //
    212 //#ifndef Q_OS_TEMP
    213 //// For alpha blending, we must load the AlphaBlend() function at run time.
    214 //#if !defined(AC_SRC_ALPHA)
    215 //#define AC_SRC_ALPHA 0x01
    216 //#endif
    217 //typedef BOOL (WINAPI *ALPHABLEND)( HDC, int, int, int, int, HDC, int, int, int, int, BLENDFUNCTION );
    218 //static HINSTANCE msimg32Lib = 0;
    219 //static ALPHABLEND alphaBlend = 0;
    220 //static bool loadAlphaBlendFailed = FALSE;
    221 //static void cleanup_msimg32Lib()
    222 //{
    223 //    if ( msimg32Lib != 0 ) {
    224 //      FreeLibrary( msimg32Lib );
    225 //      msimg32Lib = 0;
    226 //      alphaBlend = 0;
    227 //      loadAlphaBlendFailed = FALSE;
    228 //    }
    229 //}
    230 //#endif
    231 //
    232 ///*
    233 //   Try to do an AlphaBlend(). If it fails for some reasons, use BitBlt()
    234 //   instead. The arguments are like in the BitBlt() call.
    235 //*/
    236 //void qt_AlphaBlend( HDC dst_dc, int dx, int dy, int sw, int sh, HDC src_dc, int sx, int sy, DWORD rop )
    237 //{
    238 //#ifndef Q_OS_TEMP
    239 //    BLENDFUNCTION blend = {
    240 //      AC_SRC_OVER,
    241 //      0,
    242 //      255,
    243 //      AC_SRC_ALPHA
    244 //    };
    245 //    if ( alphaBlend ) {
    246 //      alphaBlend( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, sw, sh, blend );
    247 //    } else {
    248 //      if ( !loadAlphaBlendFailed ) {
    249 //          // try to load msimg32.dll and get the function
    250 //          // AlphaBlend()
    251 //          loadAlphaBlendFailed = TRUE;
    252 //          msimg32Lib = LoadLibraryA( "msimg32" );
    253 //          if ( msimg32Lib != 0 ) {
    254 //              qAddPostRoutine( cleanup_msimg32Lib );
    255 //              alphaBlend = (ALPHABLEND) GetProcAddress( msimg32Lib, "AlphaBlend" );
    256 //              loadAlphaBlendFailed = ( alphaBlend == 0 );
    257 //          }
    258 //      }
    259 //      if ( loadAlphaBlendFailed )
    260 //          BitBlt( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, rop );
    261 //      else
    262 //          alphaBlend( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, sw, sh, blend );
    263 //    }
    264 //#else
    265 //    BitBlt( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, rop );
    266 //#endif
    267 //}
     310    } else {
     311        // get bits of the destination
     312        GpiQueryBitmapBits( dst_ps, dy, h, (PBYTE) dst, (PBITMAPINFO2) &bmh );
     313    }
     314   
     315    // get bits of the source pixmap
     316    GpiQueryBitmapBits( src_ps, sy, h, (PBYTE) src, (PBITMAPINFO2) &bmh );
     317   
     318    uchar px_sz = depth / 8;
     319    uchar *dst_ptr = dst + px_sz * dst_x;
     320    uchar *src_ptr = src + px_sz * sx;
     321    uchar *a_ptr = alpha ? alpha + sx : 0;
     322    int dst_inc = dst_bpl - px_sz * w;
     323    int src_inc = src_bpl - px_sz * w;
     324    int px_skip = px_sz - 3;
     325   
     326    // use two separate code paths to increase the speed slightly by
     327    // eliminating one comparison op (a_ptr != 0) inside the most nested loop
     328    if ( a_ptr ) {
     329        for ( int y = 0; y < h; y++ ) {
     330            for ( int x = 0; x < w; x++ ) {
     331                uchar a = *(a_ptr++);
     332                if ( a == 0 ) {
     333                    dst_ptr += px_sz;
     334                    src_ptr += px_sz;
     335                    continue;
     336                } else if ( a == 255 ) {
     337                    *(dst_ptr++) = *(src_ptr++);
     338                    *(dst_ptr++) = *(src_ptr++);
     339                    *(dst_ptr++) = *(src_ptr++);
     340                } else {
     341                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
     342                    dst_ptr ++;
     343                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
     344                    dst_ptr ++;
     345                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
     346                    dst_ptr ++;
     347                }
     348                dst_ptr += px_skip;
     349                src_ptr += px_skip;
     350            }
     351            dst_ptr += dst_inc;
     352            src_ptr += src_inc;
     353        }
     354    } else {
     355        for ( int y = 0; y < h; y++ ) {
     356            for ( int x = 0; x < w; x++ ) {
     357                uchar a = src_ptr [3];
     358                if ( a == 0 ) {
     359                    dst_ptr += px_sz;
     360                    src_ptr += px_sz;
     361                    continue;
     362                } else if ( a == 255 ) {
     363                    *(dst_ptr++) = *(src_ptr++);
     364                    *(dst_ptr++) = *(src_ptr++);
     365                    *(dst_ptr++) = *(src_ptr++);
     366                } else {
     367                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
     368                    dst_ptr ++;
     369                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
     370                    dst_ptr ++;
     371                    *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
     372                    dst_ptr ++;
     373                }
     374                dst_ptr += px_skip;
     375                src_ptr += px_skip;
     376            }
     377            dst_ptr += dst_inc;
     378            src_ptr += src_inc;
     379        }
     380    }
     381   
     382    // flush the dst buffer
     383    {
     384        bmh.cx = dst_w;
     385        bmh.cy = h;
     386        POINTL ptls[] = { { dx, dy }, { dx + w - 1, dy + h - 1 },
     387                          { dst_x, 0 }, { dst_x + w, h } };
     388        GpiDrawBits( dst_ps, (PVOID) dst, (PBITMAPINFO2) &bmh, 4, ptls,
     389                     ROP_SRCCOPY, BBO_IGNORE );
     390    }
     391
     392    delete[] src;
     393    delete[] dst;
     394}
    268395
    269396void bitBlt( QPaintDevice *dst, int dx, int dy,
     
    271398             Qt::RasterOp rop, bool ignoreMask  )
    272399{
    273     if ( !src || !dst ) {
     400    if ( !src || !dst || sw == 0 || sh == 0 ) {
    274401#if defined(QT_CHECK_NULL)
    275402        Q_ASSERT( src != 0 );
     
    288415    int td = dst->devType();                    // to device type
    289416
    290     if ( sw <= 0 ) {                            // special width
    291         if ( sw < 0 )
    292             sw = src->metric(QPaintDeviceMetrics::PdmWidth) - sx;
    293         else
    294             return;
    295     }
    296     if ( sh <= 0 ) {                            // special height
    297         if ( sh < 0 )
    298             sh = src->metric(QPaintDeviceMetrics::PdmHeight) - sy;
    299         else
    300             return;
    301     }
    302 
     417    int src_w = src->metric(QPaintDeviceMetrics::PdmWidth);
     418    int src_h = src->metric(QPaintDeviceMetrics::PdmHeight);
     419    int dst_w = dst->metric(QPaintDeviceMetrics::PdmWidth);
     420    int dst_h = dst->metric(QPaintDeviceMetrics::PdmHeight);
     421   
     422    if ( sw < 0 )                               // special width
     423        sw = src_w - sx;
     424    if ( sh < 0 )                               // special height
     425        sh = src_h - sy;
     426
     427    // ensure coordinates are within borders, clip if necessary
     428    if ( sx < 0 || sy < 0 || sx + sw > src_w || sy + sh > src_h ||
     429         dx < 0 || dy < 0 || dx + sw > dst_w || dy + sh > dst_h )
     430    {
     431        int tx = dx - sx;
     432        int ty = dy - sy;
     433        QRect dr( 0, 0, dst_w, dst_h );  // dst rect
     434        QRect sr( tx, ty, src_w, src_h ); // src rect in dst coords
     435        QRect bltr( dx, dy, sw, sh ); // blit rect in dst coords
     436        bltr &= (dr & sr);
     437        if (bltr.isEmpty())
     438            return;
     439        dx = bltr.x();
     440        dy = bltr.y();
     441        sx = dx - tx;
     442        sy = dy - ty;
     443        sw = bltr.width();
     444        sh = bltr.height();
     445    }
     446   
    303447    if ( dst->paintingActive() && dst->isExtDev() ) {
    304448        QPixmap *pm;                            // output to picture/printer
     
    423567    };
    424568
    425     if ( src_pm && src_pm->data->realAlphaBits ) {
    426         qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
    427 //@@TODO (dmik): later
    428 //      if ( td == QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits )
    429 //          QPixmap::bitBltAlphaPixmap( ((QPixmap *)dst), dx, dy, src_pm, sx, sy, sw, sh, TRUE );
    430 //      else
    431 //          qt_AlphaBlend( dst_dc, dx, dy, sw, sh, src_dc, sx, sy, ropCodes[rop] );
     569    if ( td == QInternal::Pixmap ) {
     570        // Ensure the auxiliary masked bitmap created for masking is destroyed
     571        // (to cause it to be recreated when the destination is blitted next
     572        // time). Also ensure the alpha channel of the destination pixmap is
     573        // unfolded -- any GPI call will clear the high byte that may be storing
     574        // the alpha bits, so the pixmap will appear as fully transparent.
     575        QPixmap *dst_pm = (QPixmap *) dst;
     576        if ( dst_pm->data->mask )
     577            dst_pm->prepareForMasking( FALSE, TRUE );
     578        if ( dst_pm->data->hasRealAlpha )
     579            dst_pm->unfoldAlphaChannel();
     580    }
     581
     582    if ( src_pm && src_pm->data->hasRealAlpha && !ignoreMask ) {
     583        int dst_w = 0; // implies grab_dest = true
     584        if ( td == QInternal::Pixmap )
     585            dst_w = ((QPixmap *) dst)->data->w; // implies grab_dest = false
     586        drawAlphaPixmap( dst_ps, dst_w, src_ps, src_pm->data->w,
     587                         src_pm->data->realAlphaBits,
     588                         dx, fdy, sx, fsy, sw, sh, QPixmap::trueColorDepth() );
    432589    } else if ( mask ) {
    433         if ( /*src_pm &&*/ td==QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits ) {
    434             qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
    435 //@@TODO (dmik): later
    436 //          src_pm->convertToAlphaPixmap();
    437 //          QPixmap::bitBltAlphaPixmap( (QPixmap *)dst, dx, dy, src_pm, sx, sy, sw, sh, TRUE );
    438         } else {
    439590#if 0
    440 //@@TODO (dmik): unfortunately, this nice method of setting the mask as a
    441 //  pattern and using the corresponding ROPs to do masking in one step
    442 //  will not apways work on many video drivers (including SDD/SNAP) since
    443 //  they can spontaneously simplify the bitmap set as a pattern (for example,
    444 //  take only first 8 pixels of the mask width), which will produce wrong
    445 // results.
    446             const ULONG AllAreaAttrs =
    447                 ABB_COLOR | ABB_BACK_COLOR |
    448                 ABB_MIX_MODE | ABB_BACK_MIX_MODE |
    449                 ABB_SET | ABB_SYMBOL | ABB_REF_POINT;
    450             AREABUNDLE oldAb;
    451             GpiQueryAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, (PBUNDLE) &oldAb );
    452             AREABUNDLE newAb = {
    453                 CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT,
    454                 LCID_QTMaskBitmap, 0, ptls [0]
    455             };
    456             GpiSetBitmap( mask->hps, 0 );
    457             GpiSetBitmapId( dst_ps, mask->hbm(), LCID_QTMaskBitmap );
    458             GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &newAb );
    459             // we use the same rop codes for masked bitblt after setting the
    460             // low half of the rop byte to 0xA, which means destination bits
    461             // should be preserved where the corresponding bits in the mask
    462             // are zeroes.
    463             GpiBitBlt( dst_ps, src_ps, 3, ptls, (qt_ropCodes_2ROP[rop] & 0xF0) | 0x0A, BBO_IGNORE );
    464             GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &oldAb );
    465             GpiDeleteSetId( dst_ps, LCID_QTMaskBitmap );
    466             GpiSetBitmap( mask->hps, mask->hbm() );
     591        //  Unfortunately, this nice method of setting the mask as a pattern
     592        //  and using the corresponding ROPs to do masking in one step will
     593        // not apways work on many video drivers (including SDD/SNAP) since
     594        //  they can spontaneously simplify the bitmap set as a pattern (for
     595        //  example, take only first 8 pixels of the mask width), which will
     596        //  produce wrong results.
     597        const ULONG AllAreaAttrs =
     598            ABB_COLOR | ABB_BACK_COLOR |
     599            ABB_MIX_MODE | ABB_BACK_MIX_MODE |
     600            ABB_SET | ABB_SYMBOL | ABB_REF_POINT;
     601        AREABUNDLE oldAb;
     602        GpiQueryAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, (PBUNDLE) &oldAb );
     603        AREABUNDLE newAb = {
     604            CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT,
     605            LCID_QTMaskBitmap, 0, ptls [0]
     606        };
     607        GpiSetBitmap( mask->hps, 0 );
     608        GpiSetBitmapId( dst_ps, mask->hbm(), LCID_QTMaskBitmap );
     609        GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &newAb );
     610        // we use the same rop codes for masked bitblt after setting the
     611        // low half of the rop byte to 0xA, which means destination bits
     612        // should be preserved where the corresponding bits in the mask
     613        // are zeroes.
     614        GpiBitBlt( dst_ps, src_ps, 3, ptls, (qt_ropCodes_2ROP[rop] & 0xF0) | 0x0A, BBO_IGNORE );
     615        GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &oldAb );
     616        GpiDeleteSetId( dst_ps, LCID_QTMaskBitmap );
     617        GpiSetBitmap( mask->hps, mask->hbm() );
    467618#else
    468             src_pm->prepareForMasking( TRUE );
    469             drawMaskedPixmap(
    470                 dst_ps, dst->metric( QPaintDeviceMetrics::PdmDepth ),
    471                 src_ps, src_pm->data->w, src_pm->data->h,
    472                 src_pm->data->selfmask ? 0 : mask->hps,
    473                 dx, fdy, sx, fsy, sw, sh, rop
    474             );
    475             src_pm->prepareForMasking( FALSE );
    476 #endif
    477         }
     619        bool grab_dest = td != QInternal::Pixmap;
     620        src_pm->prepareForMasking( TRUE );
     621        drawMaskedPixmap(
     622            dst_ps, dst->metric( QPaintDeviceMetrics::PdmDepth ), grab_dest,
     623            src_ps, src_pm->data->selfmask ? 0 : mask->hps,
     624            dx, fdy, sx, fsy, sw, sh, rop );
     625        src_pm->prepareForMasking( FALSE );
     626#endif
    478627    } else {
    479         if ( td==QInternal::Pixmap && ((QPixmap *)dst)->isQBitmap() ) {
    480             GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
    481         } else if ( src_pm && td==QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits ) {
    482             qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
    483 //@@TODO (dmik): later
    484 //          QPixmap *dst_pm = (QPixmap *)dst;
    485 //          if ( rop == Qt::CopyROP ) {
    486 //              src_pm->convertToAlphaPixmap();
    487 //              QPixmap::bitBltAlphaPixmap( dst_pm, dx, dy, src_pm, sx, sy, sw, sh, TRUE );
    488 //          } else {
    489 //              src_pm->convertToAlphaPixmap();
    490 //              if ( dst_pm->mask() ) {
    491 //                  int width = QMIN( dst_pm->mask()->width()-dx, sw );
    492 //                  int height = QMIN( dst_pm->mask()->height()-dy, sh );
    493 //                  MaskBlt( dst_dc, dx, dy, width, height, src_pm->hdc, sx, sy, dst_pm->mask()->hbm(),
    494 //                          dx, dy, MAKEROP4(0x00aa0000,ropCodes[rop]) );
    495 //              } else {
    496 //                  BitBlt( dst_dc, dx, dy, sw, sh, src_pm->hdc, sx, sy, ropCodes[rop] );
    497 //              }
    498 //          }
    499         } else {
    500             GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
    501         }
    502     }
     628        GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
     629    }
     630
    503631    if ( src_tmp )
    504632        WinReleasePS( src_ps );
  • trunk/src/kernel/qpainter_pm.cpp

    r8 r59  
    505505    if ( (pdev->devFlags & QInternal::CompatibilityMode) != 0 )
    506506        setf(Qt2Compat);
    507     else if ( dt == QInternal::Pixmap )         // device is a pixmap
    508         ((QPixmap*)pdev)->detach();             // will modify it
     507    else if ( dt == QInternal::Pixmap ) {       // device is a pixmap
     508        QPixmap *pm = (QPixmap*) pdev;          // will modify it
     509        pm->detach();                           
     510        // Ensure the auxiliary masked bitmap created for masking is destroyed
     511        // (to cause it to be recreated when the pixmap is blitted next time).
     512        // Also ensure the alpha channel of the pixmap is unfolded -- any GPI
     513        // call will clear the high byte that may be storing the alpha bits,
     514        // so the pixmap will appear as fully transparent.
     515        if ( pm->data->mask )
     516            pm->prepareForMasking( FALSE, TRUE );
     517        if ( pm->data->hasRealAlpha )
     518            pm->unfoldAlphaChannel();
     519    }
    509520
    510521    hps = 0;
     
    802813}
    803814
    804 /*
    805   This function adjusts the raster operations for painting into a QBitmap on
    806   Windows.
    807 
    808 //@@TODO (dmik): think of it. should it be the same on OS/2? see also
    809 //  qcolor_pm.cpp, qpixmap.cpp (qt_xForm_helper()), qpaintdevice_pm.cpp (bitBlt())
    810 
    811   For bitmaps und Windows, color0 is 0xffffff and color1 is 0x000000 -- so we
    812   have to use adjusted ROPs in this case to get the same effect as on Unix.
    813 */
    814 //@@TODO (dmik): possibly remove
    815 //Qt::RasterOp qt_map_rop_for_bitmaps( Qt::RasterOp r )
    816 //{
    817 //    static const Qt::RasterOp ropCodes[] = {
    818 //      Qt::CopyROP,    // CopyROP
    819 //      Qt::AndROP,             // OrROP
    820 //      Qt::NotXorROP,  // XorROP
    821 //      Qt::NotOrROP,   // NotAndROP
    822 //      Qt::NotCopyROP, // NotCopyROP
    823 //      Qt::NotAndROP,  // NotOrROP
    824 //      Qt::XorROP,     // NotXorROP
    825 //      Qt::OrROP,      // AndROP
    826 //      Qt::NotROP,     // NotROP
    827 //      Qt::SetROP,     // ClearROP
    828 //      Qt::ClearROP,   // SetROP
    829 //      Qt::NopROP,     // NopROP
    830 //      Qt::OrNotROP,   // AndNotROP
    831 //      Qt::AndNotROP,  // OrNotROP
    832 //      Qt::NorROP,     // NandROP
    833 //      Qt::NandROP     // NorROP
    834 //    };
    835 //    return ropCodes[r];
    836 //}
    837 
    838815void QPainter::setRasterOp( RasterOp r )
    839816{
     
    861838   if ( bg_mode != TransparentMode )
    862839       qt_GpiSetBackMix( hps, qt_ropCodes[r], cpen.style() == NoPen );
    863 
    864 //@@TODO (dmik): remove? see above todo (qt_map_rop_for_bitmaps())
    865 //    if ( pdev->devType()==QInternal::Pixmap && ((QPixmap*)pdev)->isQBitmap() )
    866 //      SetROP2( hdc, ropCodes[ qt_map_rop_for_bitmaps(r) ] );
    867 //    else
    868 //      SetROP2( hdc, ropCodes[r] );
    869840}
    870841
  • trunk/src/kernel/qpixmap.cpp

    r8 r59  
    746746#endif
    747747        }
     748#if defined (Q_WS_PM)
     749        if ( data->hasRealAlpha ) {
     750            detach();
     751            data->hasRealAlpha = FALSE;
     752            if ( data->realAlphaBits ) {
     753                delete[] data->realAlphaBits;
     754                data->realAlphaBits = 0;
     755            }
     756        }
     757#endif
    748758        return;
    749759    }
     
    766776
    767777#if defined (Q_WS_PM)
     778    if ( data->hasRealAlpha ) {
     779        data->hasRealAlpha = FALSE;
     780        if ( data->realAlphaBits ) {
     781            delete[] data->realAlphaBits;
     782            data->realAlphaBits = 0;
     783        }
     784    }
    768785    if ( data->maskedHbm ) {
    769786        GpiDeleteBitmap( data->maskedHbm );
  • trunk/src/kernel/qpixmap_pm.cpp

    r56 r59  
    9595}
    9696
    97 //@@TODO (dmik): later
    98 //void QPixmap::initAlphaPixmap( uchar *bytes, int length, BITMAPINFO *bmi )
    99 //{
    100 //    if ( data->mcp )
    101 //      freeCell( TRUE );
    102 //    if ( !hdc )
    103 //      hdc = alloc_mem_dc( 0, &data->old_hbm );
    104 //
    105 //    HBITMAP hBitmap = CreateDIBSection( hdc, bmi, DIB_RGB_COLORS, (void**)&data->realAlphaBits, NULL, 0 );
    106 //    if ( bytes )
    107 //      memcpy( data->realAlphaBits, bytes, length );
    108 //
    109 //    DeleteObject( SelectObject( hdc, data->old_hbm ) );
    110 //    data->old_hbm = (HBITMAP)SelectObject( hdc, hBitmap );
    111 //    DATA_HBM = hBitmap;
    112 //}
    113 
    11497
    11598void QPixmap::init( int w, int h, int d, bool bitmap, Optimization optim )
     
    123106
    124107    static int serial = 0;
    125     int dd = defaultDepth();
     108    const int dd = defaultDepth();
    126109
    127110    if ( optim == DefaultOptim )                // use default optimization
     
    162145    bmh.cy = h;
    163146    bmh.cPlanes = 1;
    164     if ( data->d == dd )                        // compatible bitmap
     147    if ( data->d == 1 )                         // monocrome bitmap
     148        bmh.cBitCount = 1;
     149    else                                        // compatible bitmap
    165150        bmh.cBitCount = dd;
    166     else                                        // monocrome bitmap
    167         bmh.cBitCount = 1;
    168151    data->hbm = GpiCreateBitmap( hps, &bmh, 0, NULL, NULL );
    169152
     
    188171        if ( hps )
    189172            GpiSetBitmap( hps, 0 );
     173        if ( data->hasRealAlpha && data->realAlphaBits ) {
     174            delete[] data->realAlphaBits;
     175            data->realAlphaBits = 0;
     176        }
    190177        if ( data->mask ) {
    191178            delete data->mask;
     
    221208    data->d = 1;
    222209
    223     int bitsbpl = (w+7)/8;                      // original # bytes per line
     210    int bitsbpl = (w + 7) / 8;                  // original # bytes per line
    224211
    225212    int bpl = ((w + 31) / 32) * 4;              // bytes per scanline,
     
    288275    static int dd = 0;
    289276    if ( dd == 0 ) {
    290         LONG formats [2];
     277        LONG formats[ 2 ];
    291278        GpiQueryDeviceBitmapFormats( qt_display_ps(), 2, formats );
    292         dd = formats [0] * formats [1];
     279        dd = formats[ 0 ] * formats[ 1 ];
    293280    }
    294281    return dd;
     
    382369    int w = width();
    383370    int h = height();
    384     const QBitmap *m = data->realAlphaBits ? 0 : mask();
     371    const QBitmap *m = data->hasRealAlpha ? 0 : mask();
    385372    int d = depth();
    386373    int ncols = 2;
     
    392379        d = 32;                                 //   > 8  ==> 32
    393380        ncols = 0;
     381#if defined QT_CHECK_RANGE
     382    if ( trueColorDepth() != 32 )
     383        qWarning( "QPixmap::convertToImage(): video driver doesn't seem to "
     384                  "support the 32-bpp color depth!" );
     385        // don't return since we still hope the driver can at least convert
     386        // from/to 32-bpp bitmaps
     387#endif           
    394388    }
    395389
    396390    QImage image( w, h, d, ncols, QImage::BigEndian );
    397     if ( data->realAlphaBits ) {
    398         qWarning( "QPixmap::convertToImage() for pixmaps with alpha is not yet implemented on OS/2" );
    399 //@@TODO (dmik): later
    400 //#ifndef Q_OS_TEMP
    401 //      GdiFlush();
    402 //#endif
    403 //      memcpy( image.bits(), data->realAlphaBits, image.numBytes() );
    404 //      image.setAlphaBuffer( TRUE );
    405 //
    406 //      // Windows has premultiplied alpha, so revert it
    407 //      uchar *p = image.bits();
    408 //      uchar *end = p + image.numBytes();
    409 //      uchar alphaByte;
    410 //      while ( p < end ) {
    411 //          alphaByte = *(p+3);
    412 //          if ( alphaByte == 0 ) {
    413 //              *p = 255;
    414 //              ++p;
    415 //              *p = 255;
    416 //              ++p;
    417 //              *p = 255;
    418 //              ++p;
    419 //              ++p;
    420 //          } else if ( alphaByte == 255 ) {
    421 //              p += 4;
    422 //          } else {
    423 //              uchar alphaByte2 = alphaByte / 2;
    424 //              *p = ( (int)(*p) * 255 + alphaByte2 ) / alphaByte;
    425 //              ++p;
    426 //              *p = ( (int)(*p) * 255 + alphaByte2 ) / alphaByte;
    427 //              ++p;
    428 //              *p = ( (int)(*p) * 255 + alphaByte2 ) / alphaByte;
    429 //              ++p;
    430 //              ++p;
    431 //          }
    432 //      }
    433 //      return image;
    434     }
    435391
    436392    // allocate header + ncols palette entries
     
    447403    GpiQueryBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
    448404
     405    if ( data->hasRealAlpha ) {
     406        if ( data->realAlphaBits ) {
     407            // incorporate the alpha channel to image data
     408            // (see comments in convertFromImage() for details)
     409            uchar *src = data->realAlphaBits;
     410            int y = 0;
     411            while ( y < image.height() ) {
     412                uchar *dst = image.scanLine( y++ );
     413                uchar *end = dst + image.bytesPerLine();
     414                dst += 3;
     415                while ( dst < end ) {
     416                    *dst = *(src++);
     417                    dst += 4;
     418                }
     419            }
     420        }
     421        image.setAlphaBuffer( TRUE );
     422    }   
     423   
    449424    // flip the image top to bottom
    450425    {
     
    550525}
    551526
    552 
    553527bool QPixmap::convertFromImage( const QImage &img, int conversion_flags )
    554528{
     
    582556        } else if ( d == 1 ) {
    583557            if ( image.numColors() == 2 ) {
    584 //@@TODO (dmik): the code below is necessary to prevent converting
    585 //  1-bpp images with alpha channel to 8-bpp images. it is currently
    586 //  commented out only for compatibility with Qt/Win32; Qt/OS2 is ready
    587 //  to handle such images properly.
    588 //              QRgb c0 = image.color(0) | ~RGB_MASK;   // Auto: convert to best
    589 //              QRgb c1 = image.color(1) | ~RGB_MASK;
     558                // Note: 1-bpp images other than true black-white cannot be
     559                // correctly stored as GPI bitmaps (it doesn't store the palette
     560                // for them), so the code below ensures they will be converted
     561                // to 8-bpp images first. However, black-white images with alpha
     562                // channel will be also converted, though they can be stored
     563                // as bitmaps. The correct code to prevent setting conv8 to TRUE
     564                // for black-white bitmaps both with and w/o alpha should be:
     565                //      QRgb c0 = image.color(0) | ~RGB_MASK;
     566                //      QRgb c1 = image.color(1) | ~RGB_MASK;
     567                // but it is left as is solely for compatibility with Qt/Win32
     568                // (otherwise we would get visually different pixmaps).
    590569                QRgb c0 = image.color(0);       // Auto: convert to best
    591570                QRgb c1 = image.color(1);
     
    607586
    608587    bool hasRealAlpha = FALSE;
    609     if ( img.hasAlphaBuffer()
    610 //@@TODO (dmik): remove later.
    611 //        &&
    612 //          ( QApplication::winVersion() != Qt::WV_95 &&
    613 //            QApplication::winVersion() != Qt::WV_NT )
    614     ) {
     588    if ( img.hasAlphaBuffer() ) {
    615589        if (image.depth() == 8) {
    616590            const QRgb * const rgb = img.colorTable();
     
    623597            }
    624598            if (hasRealAlpha) {
    625 //@@TODO (dmik): also need to convert? guess yes.
    626 //              image = image.convertDepth(32, conversion_flags);
    627 //              d = image.depth();
     599                image = image.convertDepth(32, conversion_flags);
     600                d = image.depth();
    628601            }
    629602        } else if (image.depth() == 32) {
     
    645618    }
    646619
    647 //@@TODO (dmik): temporary code. will be removed when alpha support is done.
    648     if ( hasRealAlpha ) {
    649         qWarning( "QPixmap::convertFromImage() for images with alpha is not yet implemented on OS/2" );
    650         hasRealAlpha = FALSE;
    651     }
    652 
    653620    int w = image.width();
    654621    int h = image.height();
    655622
    656     if ( width() == w && height() == h && ( (d == 1 && depth() == 1) ||
    657                                             (d != 1 && depth() != 1) ) ) {
    658         if ( data->realAlphaBits && !hasRealAlpha ) {
    659 //@@TODO (dmik): later
    660 //          // pixmap uses a DIB section, but image has no alpha channel, so we
    661 //          // can't reuse the old pixmap
    662 //          QPixmap pm(w, h, d == 1 ? 1 : -1, data->bitmap, data->optim);
    663 //          *this = pm;
    664         } else {
    665             // same size etc., use the existing pixmap
    666             detach();
    667             if ( data->mask ) {                 // get rid of the mask
    668                 delete data->mask;
    669                 data->mask = 0;
    670                 if ( data->maskedHbm ) {
    671                     GpiDeleteBitmap( data->maskedHbm );
    672                     data->maskedHbm = 0;
    673                 }
    674             }
    675         }
     623    if ( width() == w && height() == h &&
     624         ( (d == 1 && depth() == 1) ||
     625           (d != 1 && depth() != 1 && hasRealAlpha == hasAlphaChannel()) ) ) {
     626        // same size etc., use the existing pixmap
     627        detach();
     628        if ( data->mask ) {                     // get rid of the mask
     629            delete data->mask;
     630            data->mask = 0;
     631            if ( data->maskedHbm )
     632                prepareForMasking( FALSE, TRUE );
     633        }
    676634    } else {
    677635        // different size or depth, make a new pixmap
    678         QPixmap pm(w, h, d == 1 ? 1 : -1, data->bitmap, data->optim);
     636        QPixmap pm( w, h, d == 1 ? 1 : -1, data->bitmap, data->optim );
    679637        *this = pm;
    680638    }
     639
     640#if defined QT_CHECK_RANGE     
     641    if ( d == 32 && trueColorDepth() != 32 )
     642        qWarning( "QPixmap::convertFromImage(): video driver doesn't seem to "
     643                  "support the 32-bpp color depth!" );
     644        // don't return since we still hope the driver can at least convert
     645        // from/to 32-bpp bitmaps
     646#endif           
    681647
    682648    int   ncols    = image.numColors();
     
    707673            r->bBlue = qBlue( c );
    708674            r->bGreen = qGreen( c );
    709             r->bRed = qRed( c);
     675            r->bRed = qRed( c );
    710676            r->fcOptions = 0;
    711677            if ( doAlloc ) {
     
    716682    }
    717683
    718 //@@TODO (dmik): later
    719 //#ifndef Q_OS_TEMP
    720 //    if ( hasRealAlpha ) {
    721 //      initAlphaPixmap( image.bits(), image.numBytes(), bmi );
    722 //
    723 //      // Windows expects premultiplied alpha
    724 //      uchar *p = image.bits();
    725 //      uchar *b = data->realAlphaBits;
    726 //      uchar *end = p + image.numBytes();
    727 //      uchar alphaByte;
    728 //      while ( p < end ) {
    729 //          alphaByte = *(p+3);
    730 //          if ( alphaByte == 0 ) {
    731 //              *(b++) = 0;
    732 //              *(b++) = 0;
    733 //              *(b++) = 0;
    734 //              b++;
    735 //              p += 4;
    736 //          } else if ( alphaByte == 255 ) {
    737 //              b += 4;
    738 //              p += 4;
    739 //          } else {
    740 //              *(b++) = ( (*(p++)) * (int)alphaByte + 127 ) / 255;
    741 //              *(b++) = ( (*(p++)) * (int)alphaByte + 127 ) / 255;
    742 //              *(b++) = ( (*(p++)) * (int)alphaByte + 127 ) / 255;
    743 //              b++;
    744 //              p++;
    745 //          }
    746 //      }
    747 //    }
    748 //#else
    749     data->realAlphaBits = 0;
    750 //#endif
    751 
    752     if ( data->realAlphaBits == 0 ) {
    753         // flip the image top to bottom
    754         image.detach();
    755         int bpl = image.bytesPerLine();
    756         uchar *line = new uchar[bpl];
    757         uchar *top = image.scanLine( 0 );
    758         uchar *bottom = image.scanLine( h - 1 );
    759         while( top < bottom ) {
    760             memcpy( line, top, bpl );
    761             memcpy( top, bottom, bpl );
    762             memcpy( bottom, line, bpl );
    763             top += bpl;
    764             bottom -= bpl;
    765         }
    766         delete [] line;
    767         GpiSetBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
    768     }
     684    data->hasRealAlpha = hasRealAlpha;
     685
     686    // If we have real alpha bits and the default video driver depth is 32-bpp,
     687    // we store the alpha channel in the unused high byte of the 32-bit pixel
     688    // value to save memory and slightly optimize the performance (QImage already
     689    // contains the alpha channel there, so nothing has to be done when setting
     690    // bitmap bits). Otherwise we create a separate array to store the alpha
     691    // channel from QImage.
     692   
     693    if ( hasRealAlpha && depth() != 32 ) {
     694        if ( data->realAlphaBits == 0 ) {
     695            // alpha bits buffer doesn't exist yet, create it
     696            data->realAlphaBits = new uchar [w * h];
     697        }
     698        // store alpha bits flipping scan lines top to bottom
     699        uchar *dst = data->realAlphaBits + w * (h - 1);
     700        int y = 0;
     701        while ( y < image.height() ) {
     702            uchar *src = image.scanLine( y++ );
     703            uchar *end = src + image.bytesPerLine();
     704            src += 3;
     705            while ( src < end ) {
     706                *(dst++) = *src;
     707                src += 4;
     708            }
     709            // go to the previous row
     710            dst -= w * 2;
     711        }
     712    }
     713
     714    // flip the image top to bottom
     715    image.detach();
     716    int bpl = image.bytesPerLine();
     717    uchar *line = new uchar[bpl];
     718    uchar *top = image.scanLine( 0 );
     719    uchar *bottom = image.scanLine( h - 1 );
     720    while( top < bottom ) {
     721        memcpy( line, top, bpl );
     722        memcpy( top, bottom, bpl );
     723        memcpy( bottom, line, bpl );
     724        top += bpl;
     725        bottom -= bpl;
     726    }
     727    delete [] line;
     728    GpiSetBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
    769729
    770730    if ( img.hasAlphaBuffer() ) {
    771731        QBitmap m;
    772732        m = img.createAlphaMask( conversion_flags );
    773         setMask( m );
     733        data->mask = new QBitmap( m );
    774734    }
    775735
     
    834794        h = QABS( h );
    835795        w = QABS( w );
    836         if ( data->realAlphaBits == 0 ) {
     796        if ( !data->hasRealAlpha ) {
    837797            QPixmap pm( w, h, depth(), optimization() );
    838798            POINTL ptls[] = {
     
    869829    }
    870830
    871     if ( data->realAlphaBits ) {
     831    if ( data->hasRealAlpha ) {
    872832        bpp = 32;
    873833    } else {
     
    877837    }
    878838
    879     sbpl = ((ws*bpp+31)/32)*4;
    880     sptr = new uchar[hs*sbpl];
     839    sbpl = ((ws * bpp + 31) / 32) * 4;
     840    sptr = new uchar[ hs * sbpl ];
    881841    int ncols;
    882842    if ( bpp <= 8 ) {
     
    886846    }
    887847
     848#if defined QT_CHECK_RANGE     
     849    if ( bpp == 32 && trueColorDepth() != 32 )
     850        qWarning( "QPixmap::xForm(): video driver doesn't seem to "
     851                  "support the 32-bpp color depth!" );
     852        // don't return since we still hope the driver can at least convert
     853        // from/to 32-bpp bitmaps
     854#endif           
     855   
    888856    // allocate header + ncols palette entries
    889857    int bmi_data_len = sizeof(BITMAPINFOHEADER2) + 4 * ncols;
     
    905873    }
    906874
    907     int result;
    908     if ( data->realAlphaBits ) {
    909         memcpy( sptr, data->realAlphaBits, sbpl*hs );
    910         result = 1;
    911     } else {
    912         result = GpiQueryBitmapBits( hps, 0, hs, (PBYTE) sptr, (PBITMAPINFO2) bmi_data );
    913     }
    914 
    915     if ( !result ) {                            // error, return null pixmap
    916         delete [] sptr;
    917         delete [] bmi_data;
    918         return QPixmap( 0, 0, 0, data->bitmap, NormalOptim );
    919     }
    920 
    921     dbpl   = ((w*bpp+31)/32)*4;
    922     dbytes = dbpl*h;
     875    GpiQueryBitmapBits( hps, 0, hs, (PBYTE) sptr, (PBITMAPINFO2) bmi_data );
     876   
     877    if ( data->hasRealAlpha && data->realAlphaBits ) {
     878        // incorporate the alpha channel to image data
     879        // (see comments in convertFromImage() for details)
     880        int bpx = bpp / 8;
     881        int inc = sbpl - bpx * ws;
     882        uchar *src = data->realAlphaBits;
     883        uchar *dst = sptr + 3; // move to the alpha byte
     884        for ( int y = 0; y < hs; ++ y ) {
     885            for ( int x = 0; x < ws; ++ x ) {
     886                *dst = *(src++);
     887                dst += bpx;
     888            }
     889            dst += inc;
     890        }
     891    }
     892   
     893    dbpl   = ((w * bpp + 31) / 32) * 4;
     894    dbytes = dbpl * h;
    923895
    924896    dptr = new uchar[ dbytes ];                 // create buffer for bits
     
    928900    else if ( bpp == 8 )
    929901        memset( dptr, white.pixel(), dbytes );
    930     else if ( data->realAlphaBits )
     902    else if ( data->hasRealAlpha )
    931903        memset( dptr, 0x00, dbytes );
    932904    else
     
    935907    int   xbpl, p_inc;
    936908    if ( depth1 ) {
    937         xbpl  = (w+7)/8;
     909        xbpl  = (w + 7) / 8;
    938910        p_inc = dbpl - xbpl;
    939911    } else {
    940         xbpl  = (w*bpp)/8;
     912        xbpl  = (w * bpp) / 8;
    941913        p_inc = dbpl - xbpl;
    942914    }
     
    963935    bmh.cx = w;
    964936    bmh.cy = h;
    965     if ( data->realAlphaBits ) {
    966         qWarning( "QPixmap::xForm() for pixmaps with alpha is not yet implemented on OS/2" );
    967 /// @todo (dmik) later
    968 //      pm.initAlphaPixmap( dptr, dbytes, bmi );
    969     } else {
    970         GpiSetBitmapBits( pm.hps, 0, h, (PBYTE) dptr, (PBITMAPINFO2) bmi_data );
    971     }
    972     delete [] bmi_data;
    973     delete [] dptr;
     937    GpiSetBitmapBits( pm.hps, 0, h, (PBYTE) dptr, (PBITMAPINFO2) bmi_data );
     938   
    974939    if ( data->mask ) {
    975940        QBitmap bm = data->selfmask ? *((QBitmap*)(&pm)) :
     
    977942        pm.setMask( bm );
    978943    }
     944   
     945    if ( data->hasRealAlpha ) {
     946        pm.data->hasRealAlpha = TRUE;
     947        if ( pm.depth() != 32 ) {
     948            // we are not able to store the alpha channel in the bitmap bits,
     949            // store it separately
     950            pm.data->realAlphaBits = new uchar[ w * h ];
     951            int bpx = bpp / 8;
     952            uchar *dst = pm.data->realAlphaBits;
     953            uchar *src = dptr + 3; // move to the alpha byte
     954            for ( int y = 0; y < h; ++ y ) {
     955                for ( int x = 0; x < w; ++ x ) {
     956                    *(dst++) = *src;
     957                    src += bpx;
     958                }
     959                src += p_inc;
     960            }
     961        }
     962    }
     963   
     964    delete [] bmi_data;
     965    delete [] dptr;
     966   
    979967    return pm;
    980968}
     
    988976bool QPixmap::hasAlpha() const
    989977{
    990     return data->realAlphaBits || data->mask;
     978    return data->hasRealAlpha || data->mask;
    991979}
    992980
    993981bool QPixmap::hasAlphaChannel() const
    994982{
    995     return data->realAlphaBits != 0;
    996 }
    997 
    998 //@@TODO (dmik): later
    999 //void QPixmap::convertToAlphaPixmap( bool initAlpha )
    1000 //{
    1001 //    char bmi_data[sizeof(BITMAPINFO)];
    1002 //    memset( bmi_data, 0, sizeof(BITMAPINFO) );
    1003 //    BITMAPINFO             *bmi = (BITMAPINFO*)bmi_data;
    1004 //    BITMAPINFOHEADER *bmh = (BITMAPINFOHEADER*)bmi;
    1005 //    bmh->biSize                 = sizeof(BITMAPINFOHEADER);
    1006 //    bmh->biWidth        = width();
    1007 //    bmh->biHeight       = -height();                  // top-down bitmap
    1008 //    bmh->biPlanes       = 1;
    1009 //    bmh->biBitCount     = 32;
    1010 //    bmh->biCompression          = BI_RGB;
    1011 //    bmh->biSizeImage    = width() * height() * 4;
    1012 //    bmh->biClrUsed      = 0;
    1013 //    bmh->biClrImportant         = 0;
    1014 //
    1015 //    QPixmap pm( width(), height(), -1 );
    1016 //    pm.initAlphaPixmap( 0, 0, bmi );
    1017 //
    1018 //#ifndef Q_OS_TEMP
    1019 //    GetDIBits( qt_display_dc(), DATA_HBM, 0, height(), pm.data->realAlphaBits, bmi, DIB_RGB_COLORS );
    1020 //    if ( initAlpha ) {
    1021 //      // In bitBlt(), if the destination has an alpha channel and the source
    1022 //      // doesn't have one, we bitBlt() the source with the destination's
    1023 //      // alpha channel. In that case, there is no need to initialize the
    1024 //      // alpha values.
    1025 //      uchar *p = pm.data->realAlphaBits;
    1026 //      uchar *pe = p + bmh->biSizeImage;
    1027 //      if ( mask() ) {
    1028 //          QImage msk = mask()->convertToImage();
    1029 //          int i = 0;
    1030 //          int w = width();
    1031 //          int backgroundIndex = msk.color(0) == Qt::color0.rgb() ? 0 : 1;
    1032 //          while ( p < pe ) {
    1033 //              if ( msk.pixelIndex( i%w, i/w ) == backgroundIndex ) {
    1034 //                  *(p++) = 0x00;
    1035 //                  *(p++) = 0x00;
    1036 //                  *(p++) = 0x00;
    1037 //                  *(p++) = 0x00;
    1038 //              } else {
    1039 //                  p += 3;
    1040 //                  *(p++) = 0xff;
    1041 //              }
    1042 //              ++i;
    1043 //          }
    1044 //      } else {
    1045 //          p += 3;
    1046 //          while ( p < pe ) {
    1047 //              *p = 0xff;
    1048 //              p += 4;
    1049 //          }
    1050 //      }
    1051 //    }
    1052 //#else
    1053 //    memcpy( pm.data->ppvBits, data->ppvBits, bmh->biSizeImage );
    1054 //#endif
    1055 //    if ( mask() )
    1056 //      pm.setMask( *mask() );
    1057 //
    1058 //    *this = pm;
    1059 //}
    1060 //
    1061 //void QPixmap::bitBltAlphaPixmap( QPixmap *dst, int dx, int dy,
    1062 //                               const QPixmap *src, int sx, int sy,
    1063 //                               int sw, int sh, bool useDstAlpha )
    1064 //{
    1065 //    if ( sw < 0 )
    1066 //      sw = src->width() - sx;
    1067 //    else
    1068 //      sw = QMIN( src->width()-sx, sw );
    1069 //    sw = QMIN( dst->width()-dx, sw );
    1070 //
    1071 //    if ( sh < 0 )
    1072 //      sh = src->height() - sy ;
    1073 //    else
    1074 //      sh = QMIN( src->height()-sy, sh );
    1075 //    sh = QMIN( dst->height()-dy, sh );
    1076 //
    1077 //    if ( sw <= 0 || sh <= 0 )
    1078 //      return;
    1079 //
    1080 //#ifndef Q_OS_TEMP
    1081 //    GdiFlush();
    1082 //#endif
    1083 //    uchar *sBits = src->data->realAlphaBits + ( sy * src->width() + sx ) * 4;
    1084 //    uchar *dBits = dst->data->realAlphaBits + ( dy * dst->width() + dx ) * 4;
    1085 //    int sw4 = sw * 4;
    1086 //    int src4 = src->width() * 4;
    1087 //    int dst4 = dst->width() * 4;
    1088 //    if ( useDstAlpha ) {
    1089 //      // Copy the source pixels premultiplied with the destination's alpha
    1090 //      // channel. The alpha channel remains the destination's alpha channel.
    1091 //      uchar *sCur;
    1092 //      uchar *dCur;
    1093 //      uchar alphaByte;
    1094 //      for ( int i=0; i<sh; i++ ) {
    1095 //          sCur = sBits;
    1096 //          dCur = dBits;
    1097 //          for ( int j=0; j<sw; j++ ) {
    1098 //              alphaByte = *(dCur+3);
    1099 //              if ( alphaByte == 0 || (*(sCur+3)) == 0 ) {
    1100 //                  dCur += 4;
    1101 //                  sCur += 4;
    1102 //              } else if ( alphaByte == 255 ) {
    1103 //                  *(dCur++) = *(sCur++);
    1104 //                  *(dCur++) = *(sCur++);
    1105 //                  *(dCur++) = *(sCur++);
    1106 //                  dCur++;
    1107 //                  sCur++;
    1108 //              } else {
    1109 //                  *(dCur++) = ( (*(sCur++)) * (int)alphaByte + 127 ) / 255;
    1110 //                  *(dCur++) = ( (*(sCur++)) * (int)alphaByte + 127 ) / 255;
    1111 //                  *(dCur++) = ( (*(sCur++)) * (int)alphaByte + 127 ) / 255;
    1112 //                  dCur++;
    1113 //                  sCur++;
    1114 //              }
    1115 //          }
    1116 //          sBits += src4;
    1117 //          dBits += dst4;
    1118 //      }
    1119 //    } else {
    1120 //      // Copy the source into the destination. Use the source's alpha
    1121 //      // channel.
    1122 //      for ( int i=0; i<sh; i++ ) {
    1123 //          memcpy( dBits, sBits, sw4 );
    1124 //          sBits += src4;
    1125 //          dBits += dst4;
    1126 //      }
    1127 //    }
    1128 //}
    1129 
    1130 // Prepares for painting the masked pixmap: precomposes and selects the
    1131 // masked pixmap (with transparent pixels made black) into this pixmap's hps.
    1132 // If prepare = FALSE, it does the cleanup. Currently used in ::bitBlt()
    1133 // and in QPixmap::createIcon().
    1134 void QPixmap::prepareForMasking( bool prepare )
     983    return data->hasRealAlpha;
     984}
     985
     986/**
     987 *  \internal
     988 *  If \a prepare is TRUE, prepares for painting a pixmap with mask: precomposes
     989 *  and selects a masked bitmap (with transparent pixels made black) into this
     990 *  pixmap's hps. If \a prepare is FALSE, it does the cleanup. If \a force is
     991 *  TRUE on cleanup, the masked bitmap is destroyed regardless of the
     992 *  optimization type.
     993 *
     994 *  Currently used in ::bitBlt() and in QPixmap::createIcon().
     995 */
     996void QPixmap::prepareForMasking( bool prepare, bool force /* = FALSE */ )
    1135997{
    1136998    if ( !data->mask || data->selfmask )
     
    11751037        GpiSetBitmap( hps, data->hbm );
    11761038        // delete the precomposed masked pixmap when memory optimization
    1177         // is in force or when no precomosing was done
    1178         if (
    1179             data->maskedHbm &&
    1180             (data->optim != NormalOptim && data->optim != BestOptim)
    1181         ) {
     1039        // is in force (or force is TRUE)
     1040        if ( data->maskedHbm && (force || (data->optim != NormalOptim &&
     1041                                           data->optim != BestOptim)) ) {
    11821042            GpiDeleteBitmap( data->maskedHbm );
    11831043            data->maskedHbm = 0;
     
    12951155}
    12961156
     1157void QPixmap::unfoldAlphaChannel()
     1158{
     1159    // do nothing if there is no alpha channel or if it is already unfolded
     1160    // (i.e. stored in a separate array)
     1161    if ( !data->hasRealAlpha || data->realAlphaBits )
     1162        return;
     1163
     1164    Q_ASSERT( data->d == 32 );
     1165    if ( !data->d == 32 )
     1166        return;
     1167   
     1168    data->realAlphaBits = new uchar[ data->w * data->h ];
     1169   
     1170    // no space for palette, since the depth is 32-bpp
     1171    BITMAPINFOHEADER2 bmh;
     1172    memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
     1173    bmh.cbFix = sizeof(BITMAPINFOHEADER2);
     1174    bmh.cx = data->w;
     1175    bmh.cy = data->h;
     1176    bmh.cPlanes = 1;
     1177    bmh.cBitCount = data->d;
     1178   
     1179    int bpl = ((data->d * data->w + 31) / 32) * 4;
     1180    uchar *bits = new uchar [bpl * data->h];
     1181   
     1182    GpiQueryBitmapBits( hps, 0, data->h, (PBYTE) bits, (PBITMAPINFO2) &bmh );
     1183
     1184    int bpx = data->d / 8;
     1185    int inc = bpl - bpx * data->w;
     1186    uchar *src = bits + 3; // move to the alpha byte
     1187    uchar *dst = data->realAlphaBits;
     1188    for ( int y = 0; y < data->h; ++ y ) {
     1189        for ( int x = 0; x < data->w; ++ x ) {
     1190            *(dst++) = *src;
     1191            src += bpx;
     1192        }
     1193        src += inc;
     1194    }
     1195   
     1196    delete[] bits;
     1197}
     1198
     1199/**
     1200 *  \internal
     1201 *  Converts the pixmap (actually, the pixmap's mask, if any) to the alpha
     1202 *  channel. Implies #unfoldAlphaChannel().
     1203 */
     1204void QPixmap::convertToAlpha()
     1205{
     1206    if ( isNull() || data->hasRealAlpha )
     1207        return;
     1208   
     1209    if ( data->mask ) {
     1210        // allocate header + 2 palette entries
     1211        char *bmi_data = new char[ sizeof(BITMAPINFOHEADER2) + 8 ];
     1212        memset( bmi_data, 0, sizeof(BITMAPINFOHEADER2) );
     1213        BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2) bmi_data;
     1214        bmh.cbFix = sizeof(BITMAPINFOHEADER2);
     1215        bmh.cx = data->w;
     1216        bmh.cy = data->h;
     1217        bmh.cPlanes = 1;
     1218        bmh.cBitCount = 1;
     1219        bmh.cclrUsed = 2;
     1220       
     1221        int bpl = ((data->w + 31) / 32) * 4;
     1222        uchar *bits = new uchar [bpl * data->h];
     1223       
     1224        GpiQueryBitmapBits( data->mask->hps, 0, data->h, (PBYTE) bits,
     1225                            (PBITMAPINFO2) bmi_data );
     1226
     1227        data->realAlphaBits = new uchar[ data->w * data->h ];
     1228
     1229        int inc = bpl - data->w / 8;
     1230        uchar *src = bits;
     1231        uchar *dst = data->realAlphaBits;
     1232        uchar m = 0x80;
     1233        for ( int y = 0; y < data->h; ++ y ) {
     1234            for ( int x = 0; x < data->w; ++ x ) {
     1235                *(dst ++) = (*src) & m ? 0xFF : 0x00;
     1236                m >>= 1;
     1237                if ( !m ) {
     1238                    m = 0x80;
     1239                    ++ src;
     1240                }
     1241            }
     1242            src += inc;
     1243        }
     1244       
     1245        data->hasRealAlpha = TRUE;
     1246       
     1247        delete[] bits;
     1248        delete[] bmi_data;
     1249    } else {
     1250        data->realAlphaBits = new uchar[ data->w * data->h ];
     1251        memset( data->realAlphaBits, 0xFF, data->w * data->h );
     1252        data->hasRealAlpha = TRUE;
     1253    }
     1254}
     1255
     1256/**
     1257 *  \internal
     1258 *  This depth is used when querying and setting bitmap bits for pixmaps
     1259 *  with alpha channel, either 24 or 32 (depending on the video driver caps).
     1260 *  \note This depth is not used to create bitmaps (#defaultDepth() is always
     1261 *  in charge for that purpose).
     1262 */
     1263//static
     1264int QPixmap::trueColorDepth()
     1265{
     1266    static int tcd = 0;
     1267    if ( tcd == 0 ) {
     1268        HDC display_dc = GpiQueryDevice( qt_display_ps() );
     1269        LONG formatCnt = 0;
     1270        DevQueryCaps( display_dc, CAPS_BITMAP_FORMATS, 1, &formatCnt );
     1271        LONG *formats = new LONG[ formatCnt * 2 ];
     1272        GpiQueryDeviceBitmapFormats( qt_display_ps(), formatCnt * 2, formats );
     1273        for( int i = 0; i < formatCnt * 2; i += 2 ) {
     1274            if ( formats[ i ] == 1 && formats[ i + 1 ] == 32 ) {
     1275                tcd = 32;
     1276                break;
     1277            }
     1278        }
     1279        delete[] formats;
     1280        // if the 32-bpp format is not supported, we assume the 24-bpp
     1281        // format that must be supported by all video drivers
     1282        if ( tcd == 0 )
     1283            tcd = 24;
     1284    }
     1285    return tcd;
     1286}
     1287
    12971288/*!
    12981289    \internal
     
    13061297    \param mini pixmap for a mini-sized pointer/icon
    13071298   
     1299    \return PM handle of the created pointer or 0 in case of any error
     1300   
    13081301    \note Due to a bug in WinCreatePointerIndirect, you can specify either
    13091302    \a normal pixmap or \a mini pixmap, but not both (if both are specified,
    1310     \a normal will be used). This may be fixed later.
     1303    \a normal will be used). PM will use scaling to draw a pointer of the
     1304    other size when necessary. This bug may be fixed later.
     1305   
     1306    \warning This function is not portable.   
    13111307*/
    13121308// static
     
    13161312    // Due to a bug in WinCreatePointerIndirect (it always ignores
    13171313    // hbmMiniPointer and hbmMiniColor fields), we can specify either a normal
    1318     // icon (and get a mini icon autocreated by PM) or a mini icon (with a
    1319     // normal icon autocreated by PM), but not both. This methods still accepts
    1320     // pixmaps for both icon sizes (assuming that we will find a workaround one
    1321     // day) but uses only one of them.
     1314    // icon, but not both. This methods still accepts pixmaps for both icon
     1315    // sizes (assuming that we will find a workaround one day) but uses only
     1316    // one of them.
    13221317   
    13231318    if ( normal && !normal->isNull() ) {
     
    13471342        return;
    13481343    }
    1349 
     1344   
     1345    if ( sw < 0 )
     1346        sw = src->width() - sx;
     1347    if ( sh < 0 )
     1348        sh = src->height() - sy;
     1349   
     1350    // ensure coordinates are within borders, clip if necessary
     1351    if ( sx < 0 || sy < 0 || sx + sw > src->width() || sy + sh > src->height() ||
     1352         dx < 0 || dy < 0 || dx + sw > dst->width() || dy + sh > dst->height() )
     1353    {
     1354        int tx = dx - sx;
     1355        int ty = dy - sy;
     1356        QRect dr( 0, 0, dst->width(), dst->height() ); // dst rect
     1357        QRect sr( tx, ty, src->width(), src->height() ); // src rect in dst coords
     1358        QRect bltr( dx, dy, sw, sh ); // blit rect in dst coords
     1359        bltr &= (dr & sr);
     1360        if (bltr.isEmpty())
     1361            return;
     1362        dx = bltr.x();
     1363        dy = bltr.y();
     1364        sx = dx - tx;
     1365        sy = dy - ty;
     1366        sw = bltr.width();
     1367        sh = bltr.height();
     1368    }
     1369   
     1370    dst->detach();
     1371       
    13501372    // copy mask data
    13511373    if ( src->data->mask ) {
    1352         if ( ! dst->data->mask ) {
     1374        if ( !dst->data->mask ) {
    13531375            dst->data->mask = new QBitmap( dst->width(), dst->height() );
    1354 
    13551376            // new masks are fully opaque by default
    13561377            dst->data->mask->fill( Qt::color1 );
    13571378        } else if ( dst->data->maskedHbm ) {
    13581379            // reset the precomposed masked pixmap
    1359             GpiDeleteBitmap( dst->data->maskedHbm );
    1360             dst->data->maskedHbm = 0;
     1380            dst->prepareForMasking( FALSE, TRUE );
    13611381        }
    13621382
     
    13641384                src->data->mask, sx, sy, sw, sh, Qt::CopyROP, TRUE );
    13651385    }
    1366 
    1367     if ( src->data->realAlphaBits ) {
    1368         qWarning( "::copyBlt() for pixmaps with alpha is not yet implemented on OS/2" );
    1369 //@@TODO (dmik): later
    1370 //      if ( !dst->data->realAlphaBits )
    1371 //          dst->convertToAlphaPixmap();
    1372 //      QPixmap::bitBltAlphaPixmap( dst, dx, dy, src, sx, sy, sw, sh, FALSE );
    1373     } else {
    1374         // copy pixel data
    1375         bitBlt( dst, dx, dy, src, sx, sy, sw, sh, Qt::CopyROP, TRUE );
    1376     }
    1377 }
     1386   
     1387    // copy alpha bits
     1388    if ( src->data->hasRealAlpha ||
     1389         (src->data->mask && dst->data->hasRealAlpha) ) {
     1390        if ( src->data->hasRealAlpha )
     1391            const_cast <QPixmap *> (src)->unfoldAlphaChannel();
     1392        else
     1393            const_cast <QPixmap *> (src)->convertToAlpha();
     1394        if ( dst->data->hasRealAlpha )
     1395            dst->unfoldAlphaChannel();
     1396        else
     1397            dst->convertToAlpha();
     1398        uchar *srca = src->data->realAlphaBits + src->width() * sy + sx;
     1399        uchar *dsta = dst->data->realAlphaBits + dst->width() * dy + dx;
     1400        for ( int y = 0; y < sh; ++ y ) {
     1401            memcpy( dsta, srca, sw );
     1402            srca += src->width();
     1403            dsta += dst->width();
     1404        }
     1405    }
     1406   
     1407    // copy pixel data
     1408    bitBlt( dst, dx, dy, src, sx, sy, sw, sh, Qt::CopyROP, TRUE );
     1409}
Note: See TracChangeset for help on using the changeset viewer.