Changeset 59
- Timestamp:
- Jan 29, 2006, 8:56:21 PM (20 years ago)
- Location:
- trunk
- Files:
-
- 5 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/qpixmap.h
r56 r59 217 217 HBITMAP hbm; 218 218 HBITMAP maskedHbm; // pixmap precomposed for masking 219 //@@TODO (dmik): need this? 219 bool hasRealAlpha; 220 220 uchar *realAlphaBits; 221 221 #elif defined(Q_WS_X11) … … 254 254 int sw, int sh, bool useDstAlpha ); 255 255 #elif defined(Q_WS_PM) 256 void prepareForMasking( bool prepare );256 void prepareForMasking( bool prepare, bool force = FALSE ); 257 257 HPOINTER createIcon( bool pointer, int hotX, int hotY, bool mini ); 258 258 void attachHandle( HBITMAP hbm ); 259 259 HBITMAP detachHandle(); 260 void unfoldAlphaChannel(); 261 void convertToAlpha(); 262 static int trueColorDepth(); 260 263 friend class QPMMimeImage; 261 264 #endif -
trunk/src/kernel/qpaintdevice_pm.cpp
r8 r59 125 125 126 126 // 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 }; 127 static 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 { 138 131 IMAGEBUNDLE oldIb; 139 132 140 133 if ( !mask_ps ) { 141 134 // self-masked pixmap 135 POINTL ptls[] = { { dx, dy }, { dx + w, dy + h }, 136 { sx, sy } }; 142 137 IMAGEBUNDLE newIb; 143 138 GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, (PBUNDLE) &oldIb ); … … 148 143 } else { 149 144 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 163 188 // query the destination color for 1-bpp bitmaps 164 189 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 171 221 // draw the mask: make non-transparent pixels (corresponding to 172 222 // ones in the mask) black. skip this step when rop = XorROP 173 223 // 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 178 230 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 ); 194 235 } else { 195 236 // draw masked pixmap; transparent pixels are zeroed there 196 237 // 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 ); 199 242 } 200 243 201 244 // 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 203 251 // 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 265 static 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 204 307 GpiSetBitmap( hpsBuf, 0 ); 205 308 GpiDeleteBitmap( hbmBuf ); 206 309 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 } 268 395 269 396 void bitBlt( QPaintDevice *dst, int dx, int dy, … … 271 398 Qt::RasterOp rop, bool ignoreMask ) 272 399 { 273 if ( !src || !dst ) {400 if ( !src || !dst || sw == 0 || sh == 0 ) { 274 401 #if defined(QT_CHECK_NULL) 275 402 Q_ASSERT( src != 0 ); … … 288 415 int td = dst->devType(); // to device type 289 416 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 303 447 if ( dst->paintingActive() && dst->isExtDev() ) { 304 448 QPixmap *pm; // output to picture/printer … … 423 567 }; 424 568 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() ); 432 589 } 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): later436 // src_pm->convertToAlphaPixmap();437 // QPixmap::bitBltAlphaPixmap( (QPixmap *)dst, dx, dy, src_pm, sx, sy, sw, sh, TRUE );438 } else {439 590 #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 // willnot apways work on many video drivers (including SDD/SNAP) since443 // 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 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 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() ); 467 618 #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 478 627 } 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 503 631 if ( src_tmp ) 504 632 WinReleasePS( src_ps ); -
trunk/src/kernel/qpainter_pm.cpp
r8 r59 505 505 if ( (pdev->devFlags & QInternal::CompatibilityMode) != 0 ) 506 506 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 } 509 520 510 521 hps = 0; … … 802 813 } 803 814 804 /*805 This function adjusts the raster operations for painting into a QBitmap on806 Windows.807 808 //@@TODO (dmik): think of it. should it be the same on OS/2? see also809 // 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 we812 have to use adjusted ROPs in this case to get the same effect as on Unix.813 */814 //@@TODO (dmik): possibly remove815 //Qt::RasterOp qt_map_rop_for_bitmaps( Qt::RasterOp r )816 //{817 // static const Qt::RasterOp ropCodes[] = {818 // Qt::CopyROP, // CopyROP819 // Qt::AndROP, // OrROP820 // Qt::NotXorROP, // XorROP821 // Qt::NotOrROP, // NotAndROP822 // Qt::NotCopyROP, // NotCopyROP823 // Qt::NotAndROP, // NotOrROP824 // Qt::XorROP, // NotXorROP825 // Qt::OrROP, // AndROP826 // Qt::NotROP, // NotROP827 // Qt::SetROP, // ClearROP828 // Qt::ClearROP, // SetROP829 // Qt::NopROP, // NopROP830 // Qt::OrNotROP, // AndNotROP831 // Qt::AndNotROP, // OrNotROP832 // Qt::NorROP, // NandROP833 // Qt::NandROP // NorROP834 // };835 // return ropCodes[r];836 //}837 838 815 void QPainter::setRasterOp( RasterOp r ) 839 816 { … … 861 838 if ( bg_mode != TransparentMode ) 862 839 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 // else868 // SetROP2( hdc, ropCodes[r] );869 840 } 870 841 -
trunk/src/kernel/qpixmap.cpp
r8 r59 746 746 #endif 747 747 } 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 748 758 return; 749 759 } … … 766 776 767 777 #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 } 768 785 if ( data->maskedHbm ) { 769 786 GpiDeleteBitmap( data->maskedHbm ); -
trunk/src/kernel/qpixmap_pm.cpp
r56 r59 95 95 } 96 96 97 //@@TODO (dmik): later98 //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 114 97 115 98 void QPixmap::init( int w, int h, int d, bool bitmap, Optimization optim ) … … 123 106 124 107 static int serial = 0; 125 int dd = defaultDepth();108 const int dd = defaultDepth(); 126 109 127 110 if ( optim == DefaultOptim ) // use default optimization … … 162 145 bmh.cy = h; 163 146 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 165 150 bmh.cBitCount = dd; 166 else // monocrome bitmap167 bmh.cBitCount = 1;168 151 data->hbm = GpiCreateBitmap( hps, &bmh, 0, NULL, NULL ); 169 152 … … 188 171 if ( hps ) 189 172 GpiSetBitmap( hps, 0 ); 173 if ( data->hasRealAlpha && data->realAlphaBits ) { 174 delete[] data->realAlphaBits; 175 data->realAlphaBits = 0; 176 } 190 177 if ( data->mask ) { 191 178 delete data->mask; … … 221 208 data->d = 1; 222 209 223 int bitsbpl = (w +7)/8; // original # bytes per line210 int bitsbpl = (w + 7) / 8; // original # bytes per line 224 211 225 212 int bpl = ((w + 31) / 32) * 4; // bytes per scanline, … … 288 275 static int dd = 0; 289 276 if ( dd == 0 ) { 290 LONG formats [2];277 LONG formats[ 2 ]; 291 278 GpiQueryDeviceBitmapFormats( qt_display_ps(), 2, formats ); 292 dd = formats [0] * formats [1];279 dd = formats[ 0 ] * formats[ 1 ]; 293 280 } 294 281 return dd; … … 382 369 int w = width(); 383 370 int h = height(); 384 const QBitmap *m = data-> realAlphaBits? 0 : mask();371 const QBitmap *m = data->hasRealAlpha ? 0 : mask(); 385 372 int d = depth(); 386 373 int ncols = 2; … … 392 379 d = 32; // > 8 ==> 32 393 380 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 394 388 } 395 389 396 390 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): later400 //#ifndef Q_OS_TEMP401 // GdiFlush();402 //#endif403 // memcpy( image.bits(), data->realAlphaBits, image.numBytes() );404 // image.setAlphaBuffer( TRUE );405 //406 // // Windows has premultiplied alpha, so revert it407 // 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 }435 391 436 392 // allocate header + ncols palette entries … … 447 403 GpiQueryBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data ); 448 404 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 449 424 // flip the image top to bottom 450 425 { … … 550 525 } 551 526 552 553 527 bool QPixmap::convertFromImage( const QImage &img, int conversion_flags ) 554 528 { … … 582 556 } else if ( d == 1 ) { 583 557 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). 590 569 QRgb c0 = image.color(0); // Auto: convert to best 591 570 QRgb c1 = image.color(1); … … 607 586 608 587 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() ) { 615 589 if (image.depth() == 8) { 616 590 const QRgb * const rgb = img.colorTable(); … … 623 597 } 624 598 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(); 628 601 } 629 602 } else if (image.depth() == 32) { … … 645 618 } 646 619 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 653 620 int w = image.width(); 654 621 int h = image.height(); 655 622 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 } 676 634 } else { 677 635 // 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 ); 679 637 *this = pm; 680 638 } 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 681 647 682 648 int ncols = image.numColors(); … … 707 673 r->bBlue = qBlue( c ); 708 674 r->bGreen = qGreen( c ); 709 r->bRed = qRed( c );675 r->bRed = qRed( c ); 710 676 r->fcOptions = 0; 711 677 if ( doAlloc ) { … … 716 682 } 717 683 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 ); 769 729 770 730 if ( img.hasAlphaBuffer() ) { 771 731 QBitmap m; 772 732 m = img.createAlphaMask( conversion_flags ); 773 setMask( m ); 733 data->mask = new QBitmap( m ); 774 734 } 775 735 … … 834 794 h = QABS( h ); 835 795 w = QABS( w ); 836 if ( data->realAlphaBits == 0) {796 if ( !data->hasRealAlpha ) { 837 797 QPixmap pm( w, h, depth(), optimization() ); 838 798 POINTL ptls[] = { … … 869 829 } 870 830 871 if ( data-> realAlphaBits) {831 if ( data->hasRealAlpha ) { 872 832 bpp = 32; 873 833 } else { … … 877 837 } 878 838 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 ]; 881 841 int ncols; 882 842 if ( bpp <= 8 ) { … … 886 846 } 887 847 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 888 856 // allocate header + ncols palette entries 889 857 int bmi_data_len = sizeof(BITMAPINFOHEADER2) + 4 * ncols; … … 905 873 } 906 874 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; 923 895 924 896 dptr = new uchar[ dbytes ]; // create buffer for bits … … 928 900 else if ( bpp == 8 ) 929 901 memset( dptr, white.pixel(), dbytes ); 930 else if ( data-> realAlphaBits)902 else if ( data->hasRealAlpha ) 931 903 memset( dptr, 0x00, dbytes ); 932 904 else … … 935 907 int xbpl, p_inc; 936 908 if ( depth1 ) { 937 xbpl = (w +7)/8;909 xbpl = (w + 7) / 8; 938 910 p_inc = dbpl - xbpl; 939 911 } else { 940 xbpl = (w *bpp)/8;912 xbpl = (w * bpp) / 8; 941 913 p_inc = dbpl - xbpl; 942 914 } … … 963 935 bmh.cx = w; 964 936 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 974 939 if ( data->mask ) { 975 940 QBitmap bm = data->selfmask ? *((QBitmap*)(&pm)) : … … 977 942 pm.setMask( bm ); 978 943 } 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 979 967 return pm; 980 968 } … … 988 976 bool QPixmap::hasAlpha() const 989 977 { 990 return data-> realAlphaBits|| data->mask;978 return data->hasRealAlpha || data->mask; 991 979 } 992 980 993 981 bool QPixmap::hasAlphaChannel() const 994 982 { 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 */ 996 void QPixmap::prepareForMasking( bool prepare, bool force /* = FALSE */ ) 1135 997 { 1136 998 if ( !data->mask || data->selfmask ) … … 1175 1037 GpiSetBitmap( hps, data->hbm ); 1176 1038 // 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)) ) { 1182 1042 GpiDeleteBitmap( data->maskedHbm ); 1183 1043 data->maskedHbm = 0; … … 1295 1155 } 1296 1156 1157 void 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 */ 1204 void 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 1264 int 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 1297 1288 /*! 1298 1289 \internal … … 1306 1297 \param mini pixmap for a mini-sized pointer/icon 1307 1298 1299 \return PM handle of the created pointer or 0 in case of any error 1300 1308 1301 \note Due to a bug in WinCreatePointerIndirect, you can specify either 1309 1302 \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. 1311 1307 */ 1312 1308 // static … … 1316 1312 // Due to a bug in WinCreatePointerIndirect (it always ignores 1317 1313 // 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. 1322 1317 1323 1318 if ( normal && !normal->isNull() ) { … … 1347 1342 return; 1348 1343 } 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 1350 1372 // copy mask data 1351 1373 if ( src->data->mask ) { 1352 if ( ! 1374 if ( !dst->data->mask ) { 1353 1375 dst->data->mask = new QBitmap( dst->width(), dst->height() ); 1354 1355 1376 // new masks are fully opaque by default 1356 1377 dst->data->mask->fill( Qt::color1 ); 1357 1378 } else if ( dst->data->maskedHbm ) { 1358 1379 // reset the precomposed masked pixmap 1359 GpiDeleteBitmap( dst->data->maskedHbm ); 1360 dst->data->maskedHbm = 0; 1380 dst->prepareForMasking( FALSE, TRUE ); 1361 1381 } 1362 1382 … … 1364 1384 src->data->mask, sx, sy, sw, sh, Qt::CopyROP, TRUE ); 1365 1385 } 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.