source: trunk/src/kernel/qpixmap_pm.cpp@ 56

Last change on this file since 56 was 56, checked in by dmik, 20 years ago

Added the OS/2 specific (i.e. not portable) internal public method to create OS/2 icons/pointers from QPixmap objects.

  • Property svn:keywords set to Id
File size: 40.0 KB
Line 
1/****************************************************************************
2** $Id: qpixmap_pm.cpp 56 2006-01-19 21:09:05Z dmik $
3**
4** Implementation of QPixmap class for OS/2
5**
6** Copyright (C) 1992-2002 Trolltech AS. All rights reserved.
7** Copyright (C) 2004 Norman ASA. Initial OS/2 Port.
8** Copyright (C) 2005 netlabs.org. Further OS/2 Development.
9**
10** This file is part of the kernel module of the Qt GUI Toolkit.
11**
12** This file may be distributed under the terms of the Q Public License
13** as defined by Trolltech AS of Norway and appearing in the file
14** LICENSE.QPL included in the packaging of this file.
15**
16** This file may be distributed and/or modified under the terms of the
17** GNU General Public License version 2 as published by the Free Software
18** Foundation and appearing in the file LICENSE.GPL included in the
19** packaging of this file.
20**
21** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition
22** licenses may use this file in accordance with the Qt Commercial License
23** Agreement provided with the Software.
24**
25** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
26** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
27**
28** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for
29** information about Qt Commercial License Agreements.
30** See http://www.trolltech.com/qpl/ for QPL licensing information.
31** See http://www.trolltech.com/gpl/ for GPL licensing information.
32**
33** Contact info@trolltech.com if any conditions of this licensing are
34** not clear to you.
35**
36**********************************************************************/
37
38#include "qbitmap.h"
39#include "qimage.h"
40#include "qpaintdevicemetrics.h"
41#include "qwmatrix.h"
42#include "qapplication.h"
43#include "qapplication_p.h"
44#include "qt_os2.h"
45
46extern const uchar *qt_get_bitflip_array(); // defined in qimage.cpp
47
48static inline HPS alloc_mem_ps( int w, int h, HPS compat = 0 )
49{
50 HDC hdcCompat = 0;
51 if ( compat )
52 hdcCompat = GpiQueryDevice( compat );
53
54 static const PSZ hdcData[4] = { "Display", NULL, NULL, NULL };
55 HDC hdc = DevOpenDC( 0, OD_MEMORY, "*", 4, (PDEVOPENDATA) hdcData, hdcCompat );
56 if ( !hdc ) {
57#if defined(QT_CHECK_NULL)
58 qSystemWarning( "alloc_mem_dc: DevOpenDC failed!" );
59#endif
60 return 0;
61 }
62 SIZEL size = { w, h };
63 HPS hps = GpiCreatePS( 0, hdc, &size, PU_PELS | GPIA_ASSOC | GPIT_MICRO );
64 if ( !hps ) {
65#if defined(QT_CHECK_NULL)
66 qSystemWarning( "alloc_mem_dc: GpiCreatePS failed!" );
67#endif
68 return 0;
69 }
70 if ( QColor::hPal() ) {
71 GpiSelectPalette( hps, QColor::hPal() );
72 } else {
73 // direct RGB mode
74 GpiCreateLogColorTable( hps, 0, LCOLF_RGB, 0, 0, NULL );
75 }
76 return hps;
77}
78
79static inline void free_mem_ps( HPS hps )
80{
81 HDC hdc = GpiQueryDevice( hps );
82 GpiAssociate( hps, 0 );
83 GpiDestroyPS( hps );
84 DevCloseDC( hdc );
85}
86
87extern HPS qt_alloc_mem_ps( int w, int h, HPS compat = 0 )
88{
89 return alloc_mem_ps( w, h, compat );
90}
91
92extern void qt_free_mem_ps( HPS hps )
93{
94 free_mem_ps( hps );
95}
96
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
114
115void QPixmap::init( int w, int h, int d, bool bitmap, Optimization optim )
116{
117#if defined(QT_CHECK_STATE)
118 if ( qApp->type() == QApplication::Tty ) {
119 qWarning( "QPixmap: Cannot create a QPixmap when no GUI "
120 "is being used" );
121 }
122#endif
123
124 static int serial = 0;
125 int dd = defaultDepth();
126
127 if ( optim == DefaultOptim ) // use default optimization
128 optim = defOptim;
129
130 data = new QPixmapData;
131 Q_CHECK_PTR( data );
132
133 memset( data, 0, sizeof(QPixmapData) );
134 data->count = 1;
135 data->uninit = TRUE;
136 data->bitmap = bitmap;
137 data->ser_no = ++serial;
138 data->optim = optim;
139
140 bool make_null = w == 0 || h == 0; // create null pixmap
141 if ( d == 1 ) // monocrome pixmap
142 data->d = 1;
143 else if ( d < 0 || d == dd ) // compatible pixmap
144 data->d = dd;
145 if ( make_null || w < 0 || h < 0 || data->d == 0 ) {
146 hps = 0;
147 data->hbm = 0;
148#if defined(QT_CHECK_RANGE)
149 if ( !make_null ) // invalid parameters
150 qWarning( "QPixmap: Invalid pixmap parameters" );
151#endif
152 return;
153 }
154 data->w = w;
155 data->h = h;
156
157 hps = alloc_mem_ps( w, h );
158 BITMAPINFOHEADER2 bmh;
159 memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
160 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
161 bmh.cx = w;
162 bmh.cy = h;
163 bmh.cPlanes = 1;
164 if ( data->d == dd ) // compatible bitmap
165 bmh.cBitCount = dd;
166 else // monocrome bitmap
167 bmh.cBitCount = 1;
168 data->hbm = GpiCreateBitmap( hps, &bmh, 0, NULL, NULL );
169
170 if ( !data->hbm ) {
171 data->w = 0;
172 data->h = 0;
173 free_mem_ps( hps );
174 hps = 0;
175#if defined(QT_CHECK_NULL)
176 qSystemWarning( "QPixmap: Pixmap allocation failed" );
177#endif
178 return;
179 }
180
181 GpiSetBitmap( hps, data->hbm );
182}
183
184
185void QPixmap::deref()
186{
187 if ( data && data->deref() ) { // last reference lost
188 if ( hps )
189 GpiSetBitmap( hps, 0 );
190 if ( data->mask ) {
191 delete data->mask;
192 if ( data->maskedHbm ) {
193 GpiDeleteBitmap( data->maskedHbm );
194 data->maskedHbm = 0;
195 }
196 }
197 if ( data->hbm ) {
198 GpiDeleteBitmap( data->hbm );
199 data->hbm = 0;
200 }
201 if ( hps ) {
202 free_mem_ps( hps );
203 hps = 0;
204 }
205 delete data;
206 data = 0;
207 }
208}
209
210
211QPixmap::QPixmap( int w, int h, const uchar *bits, bool isXbitmap )
212 : QPaintDevice( QInternal::Pixmap )
213{ // for bitmaps only
214 init( 0, 0, 0, FALSE, NormalOptim );
215 if ( w <= 0 || h <= 0 ) // create null pixmap
216 return;
217
218 data->uninit = FALSE;
219 data->w = w;
220 data->h = h;
221 data->d = 1;
222
223 int bitsbpl = (w+7)/8; // original # bytes per line
224
225 int bpl = ((w + 31) / 32) * 4; // bytes per scanline,
226 // doubleword aligned
227
228 uchar *newbits = new uchar[bpl*h];
229 uchar *p = newbits + bpl*(h - 1); // last scanline
230 int x, y, pad;
231 pad = bpl - bitsbpl;
232 const uchar *f = isXbitmap ? qt_get_bitflip_array() : 0;
233
234 // flip bit order if Xbitmap and flip bitmap top to bottom
235 for ( y=0; y<h; y++ ) {
236 if ( f ) {
237 for ( x=0; x<bitsbpl; x++ )
238 *p++ = f[*bits++];
239 for ( x=0; x<pad; x++ )
240 *p++ = 0;
241 p -= bpl;
242 } else {
243 memcpy( p, bits, bitsbpl );
244 memset( p + bitsbpl, 0, pad );
245 bits += bitsbpl;
246 }
247 p -= bpl;
248 }
249
250 hps = alloc_mem_ps( w, h );
251 // allocate header + 2 palette entries
252 char *bmi_data = new char[ sizeof(BITMAPINFOHEADER2) + 4 * 2 ];
253 memset( bmi_data, 0, sizeof(BITMAPINFOHEADER2) );
254 BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2) bmi_data;
255 PULONG pal = (PULONG) (bmi_data + sizeof(BITMAPINFOHEADER2));
256 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
257 bmh.cx = w;
258 bmh.cy = h;
259 bmh.cPlanes = 1;
260 bmh.cBitCount = 1;
261 bmh.cclrUsed = 2;
262 pal[0] = 0;
263 pal[1] = 0x00FFFFFF;
264 data->hbm = GpiCreateBitmap(
265 hps, &bmh, CBM_INIT, (PBYTE) newbits, (PBITMAPINFO2) bmi_data
266 );
267
268 GpiSetBitmap( hps, data->hbm );
269
270 delete [] bmi_data;
271 delete [] newbits;
272 if ( defOptim != NormalOptim )
273 setOptimization( defOptim );
274}
275
276
277void QPixmap::detach()
278{
279 if ( data->uninit || data->count == 1 )
280 data->uninit = FALSE;
281 else
282 *this = copy();
283}
284
285
286int QPixmap::defaultDepth()
287{
288 static int dd = 0;
289 if ( dd == 0 ) {
290 LONG formats [2];
291 GpiQueryDeviceBitmapFormats( qt_display_ps(), 2, formats );
292 dd = formats [0] * formats [1];
293 }
294 return dd;
295}
296
297
298void QPixmap::setOptimization( Optimization optimization )
299{
300 if ( optimization == data->optim )
301 return;
302 detach();
303 data->optim = optimization == DefaultOptim ?
304 defOptim : optimization;
305}
306
307
308void QPixmap::fill( const QColor &fillColor )
309{
310 if ( isNull() )
311 return;
312 detach(); // detach other references
313
314 const ULONG AreaAttrs = ABB_COLOR | ABB_MIX_MODE | ABB_SET | ABB_SYMBOL;
315 AREABUNDLE oldAb;
316 GpiQueryAttrs( hps, PRIM_AREA, AreaAttrs, (PBUNDLE) &oldAb );
317 AREABUNDLE newAb;
318 newAb.lColor = fillColor.pixel();
319 newAb.usMixMode = FM_OVERPAINT;
320 newAb.usSet = LCID_DEFAULT;
321 newAb.usSymbol = PATSYM_SOLID;
322 GpiSetAttrs( hps, PRIM_AREA, AreaAttrs, 0, (PBUNDLE) &newAb );
323 POINTL ptl = { 0, 0 };
324 GpiMove( hps, &ptl );
325 ptl.x = data->w - 1;
326 ptl.y = data->h - 1;
327 GpiBox( hps, DRO_FILL, &ptl, 0, 0 );
328 GpiSetAttrs( hps, PRIM_AREA, AreaAttrs, 0, (PBUNDLE) &newAb );
329}
330
331
332int QPixmap::metric( int m ) const
333{
334 if ( m == QPaintDeviceMetrics::PdmWidth ) {
335 return width();
336 } else if ( m == QPaintDeviceMetrics::PdmHeight ) {
337 return height();
338 } else {
339 LONG val;
340 HDC hdc = GpiQueryDevice( hps );
341 switch ( m ) {
342 case QPaintDeviceMetrics::PdmDpiX:
343 DevQueryCaps( hdc, CAPS_HORIZONTAL_FONT_RES, 1, &val );
344 break;
345 case QPaintDeviceMetrics::PdmDpiY:
346 DevQueryCaps( hdc, CAPS_VERTICAL_FONT_RES, 1, &val );
347 break;
348 case QPaintDeviceMetrics::PdmWidthMM:
349 DevQueryCaps( hdc, CAPS_HORIZONTAL_RESOLUTION, 1, &val );
350 val = width() * 1000 / val;
351 break;
352 case QPaintDeviceMetrics::PdmHeightMM:
353 DevQueryCaps( hdc, CAPS_VERTICAL_RESOLUTION, 1, &val );
354 val = width() * 1000 / val;
355 break;
356 case QPaintDeviceMetrics::PdmNumColors:
357 if (depth() == 1) {
358 // it's a monochrome bitmap
359 val = 1;
360 } else {
361 DevQueryCaps( hdc, CAPS_COLORS, 1, &val );
362 }
363 break;
364 case QPaintDeviceMetrics::PdmDepth:
365 val = depth();
366 break;
367 default:
368 val = 0;
369#if defined(QT_CHECK_RANGE)
370 qWarning( "QPixmap::metric: Invalid metric command" );
371#endif
372 }
373 return val;
374 }
375}
376
377QImage QPixmap::convertToImage() const
378{
379 if ( isNull() )
380 return QImage(); // null image
381
382 int w = width();
383 int h = height();
384 const QBitmap *m = data->realAlphaBits ? 0 : mask();
385 int d = depth();
386 int ncols = 2;
387
388 if ( d > 1 && d <= 8 ) { // set to nearest valid depth
389 d = 8; // 2..7 ==> 8
390 ncols = 256;
391 } else if ( d > 8 ) {
392 d = 32; // > 8 ==> 32
393 ncols = 0;
394 }
395
396 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 }
435
436 // allocate header + ncols palette entries
437 char *bmi_data = new char[ sizeof(BITMAPINFOHEADER2) + 4 * ncols ];
438 memset( bmi_data, 0, sizeof(BITMAPINFOHEADER2) );
439 BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2) bmi_data;
440 PULONG pal = (PULONG) (bmi_data + sizeof(BITMAPINFOHEADER2));
441 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
442 bmh.cx = w;
443 bmh.cy = h;
444 bmh.cPlanes = 1;
445 bmh.cBitCount = d;
446 bmh.cclrUsed = ncols;
447 GpiQueryBitmapBits( hps, 0, h, (PBYTE) image.bits(), (PBITMAPINFO2) bmi_data );
448
449 // flip the image top to bottom
450 {
451 int bpl = image.bytesPerLine();
452 uchar *line = new uchar[bpl];
453 uchar *top = image.scanLine( 0 );
454 uchar *bottom = image.scanLine( h - 1 );
455 while( top < bottom ) {
456 memcpy( line, top, bpl );
457 memcpy( top, bottom, bpl );
458 memcpy( bottom, line, bpl );
459 top += bpl;
460 bottom -= bpl;
461 }
462 delete [] line;
463 }
464
465 if ( d == 1 ) {
466 // use a white/black palette for monochrome pixmaps (istead of
467 // black/white supplied by GPI) to make the result of possible
468 // converson to a higher depth compatible with other platforms.
469 if ( m ) {
470 image.setAlphaBuffer( TRUE );
471 image.setColor( 0, qRgba( 255, 255, 255, 0 ) );
472 image.setColor( 1, qRgba( 0, 0, 0, 255 ) );
473 } else {
474 image.setColor( 0, qRgb( 255, 255, 255 ) );
475 image.setColor( 1, qRgb( 0, 0, 0 ) );
476 }
477 } else {
478 for ( int i=0; i<ncols; i++ ) { // copy color table
479 PRGB2 r = (PRGB2) &pal[i];
480 if ( m )
481 image.setColor( i, qRgba(r->bRed,
482 r->bGreen,
483 r->bBlue,255) );
484 else
485 image.setColor( i, qRgb(r->bRed,
486 r->bGreen,
487 r->bBlue) );
488 }
489 }
490
491 delete [] bmi_data;
492
493 if ( d != 1 && m ) {
494 image.setAlphaBuffer(TRUE);
495 QImage msk = m->convertToImage();
496
497 switch ( d ) {
498 case 8: {
499 int used[256];
500 memset( used, 0, sizeof(int)*256 );
501 uchar* p = image.bits();
502 int l = image.numBytes();
503 while (l--) {
504 used[*p++]++;
505 }
506 int trans=0;
507 int bestn=INT_MAX;
508 for ( int i=0; i<256; i++ ) {
509 if ( used[i] < bestn ) {
510 bestn = used[i];
511 trans = i;
512 if ( !bestn )
513 break;
514 }
515 }
516 image.setColor( trans, image.color(trans)&0x00ffffff );
517 for ( int y=0; y<image.height(); y++ ) {
518 uchar* mb = msk.scanLine(y);
519 uchar* ib = image.scanLine(y);
520 uchar bit = 0x80;
521 int i=image.width();
522 while (i--) {
523 if ( !(*mb & bit) )
524 *ib = trans;
525 bit /= 2; if ( !bit ) mb++,bit = 0x80; // ROL
526 ib++;
527 }
528 }
529 } break;
530 case 32: {
531 for ( int y=0; y<image.height(); y++ ) {
532 uchar* mb = msk.scanLine(y);
533 QRgb* ib = (QRgb*)image.scanLine(y);
534 uchar bit = 0x80;
535 int i=image.width();
536 while (i--) {
537 if ( *mb & bit )
538 *ib |= 0xff000000;
539 else
540 *ib &= 0x00ffffff;
541 bit /= 2; if ( !bit ) mb++,bit = 0x80; // ROL
542 ib++;
543 }
544 }
545 } break;
546 }
547 }
548
549 return image;
550}
551
552
553bool QPixmap::convertFromImage( const QImage &img, int conversion_flags )
554{
555 if ( img.isNull() ) {
556#if defined(QT_CHECK_NULL)
557 qWarning( "QPixmap::convertFromImage: Cannot convert a null image" );
558#endif
559 return FALSE;
560 }
561
562 QImage image = img;
563 int d = image.depth();
564 int dd = defaultDepth();
565 bool force_mono = (dd == 1 || isQBitmap() ||
566 (conversion_flags & ColorMode_Mask)==MonoOnly );
567
568 if ( force_mono ) { // must be monochrome
569 if ( d != 1 ) { // dither
570 image = image.convertDepth( 1, conversion_flags );
571 d = 1;
572 }
573 } else { // can be both
574 bool conv8 = FALSE;
575 if ( d > 8 && dd <= 8 ) { // convert to 8 bit
576 if ( (conversion_flags & DitherMode_Mask) == AutoDither )
577 conversion_flags = (conversion_flags & ~DitherMode_Mask)
578 | PreferDither;
579 conv8 = TRUE;
580 } else if ( (conversion_flags & ColorMode_Mask) == ColorOnly ) {
581 conv8 = d == 1; // native depth wanted
582 } else if ( d == 1 ) {
583 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;
590 QRgb c0 = image.color(0); // Auto: convert to best
591 QRgb c1 = image.color(1);
592 conv8 = QMIN(c0,c1) != qRgb(0,0,0) || QMAX(c0,c1) != qRgb(255,255,255);
593 } else {
594 // eg. 1-color monochrome images (they do exist).
595 conv8 = TRUE;
596 }
597 }
598 if ( conv8 ) {
599 image = image.convertDepth( 8, conversion_flags );
600 d = 8;
601 }
602 }
603
604 if ( d == 1 ) { // 1 bit pixmap (bitmap)
605 image = image.convertBitOrder( QImage::BigEndian );
606 }
607
608 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 ) {
615 if (image.depth() == 8) {
616 const QRgb * const rgb = img.colorTable();
617 for (int i = 0, count = img.numColors(); i < count; ++i) {
618 const int alpha = qAlpha(rgb[i]);
619 if (alpha != 0 && alpha != 0xff) {
620 hasRealAlpha = true;
621 break;
622 }
623 }
624 if (hasRealAlpha) {
625//@@TODO (dmik): also need to convert? guess yes.
626// image = image.convertDepth(32, conversion_flags);
627// d = image.depth();
628 }
629 } else if (image.depth() == 32) {
630 int i = 0;
631 while ( i<image.height() && !hasRealAlpha ) {
632 uchar *p = image.scanLine(i);
633 uchar *end = p + image.bytesPerLine();
634 p += 3;
635 while ( p < end ) {
636 if ( *p!=0 && *p!=0xff ) {
637 hasRealAlpha = TRUE;
638 break;
639 }
640 p += 4;
641 }
642 ++i;
643 }
644 }
645 }
646
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 int w = image.width();
654 int h = image.height();
655
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 }
676 } else {
677 // different size or depth, make a new pixmap
678 QPixmap pm(w, h, d == 1 ? 1 : -1, data->bitmap, data->optim);
679 *this = pm;
680 }
681
682 int ncols = image.numColors();
683
684 // allocate header + ncols palette entries
685 char *bmi_data = new char[ sizeof(BITMAPINFOHEADER2) + 4 * ncols ];
686 memset( bmi_data, 0, sizeof(BITMAPINFOHEADER2) );
687 BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2) bmi_data;
688 PULONG pal = (PULONG) (bmi_data + sizeof(BITMAPINFOHEADER2));
689 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
690 bmh.cx = w;
691 bmh.cy = h;
692 bmh.cPlanes = 1;
693 bmh.cBitCount = d;
694 bmh.cclrUsed = ncols;
695 bool doAlloc = ( QApplication::colorSpec() == QApplication::CustomColor
696 && QColor::hPal() );
697
698 if ( d == 1 ) {
699 // always use the black/white palette for monochrome pixmaps;
700 // otherwise GPI can swap 0s and 1s when creating a bitmap.
701 pal [0] = 0;
702 pal [1] = 0x00FFFFFF;
703 } else {
704 for ( int i=0; i<ncols; i++ ) { // copy color table
705 PRGB2 r = (PRGB2) &pal[i];
706 QRgb c = image.color(i);
707 r->bBlue = qBlue( c );
708 r->bGreen = qGreen( c );
709 r->bRed = qRed( c);
710 r->fcOptions = 0;
711 if ( doAlloc ) {
712 QColor cl( c );
713 cl.alloc();
714 }
715 }
716 }
717
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 }
769
770 if ( img.hasAlphaBuffer() ) {
771 QBitmap m;
772 m = img.createAlphaMask( conversion_flags );
773 setMask( m );
774 }
775
776 delete [] bmi_data;
777 data->uninit = FALSE;
778
779 return TRUE;
780}
781
782
783QPixmap QPixmap::grabWindow( WId window, int x, int y, int w, int h )
784{
785 RECTL rcl;
786 WinQueryWindowRect( window, &rcl );
787 if ( w <= 0 || h <= 0 ) {
788 if ( w == 0 || h == 0 ) {
789 QPixmap nullPixmap;
790 return nullPixmap;
791 }
792 if ( w < 0 )
793 w = rcl.xRight;
794 if ( h < 0 )
795 h = rcl.yTop;
796 }
797 // flip y coordinate
798 y = rcl.yTop - (y + h);
799 QPixmap pm( w, h );
800 HPS hps = WinGetPS( window );
801 POINTL pnts[] = { {0, 0}, {w, h}, {x, y} };
802 GpiBitBlt( pm.hps, hps, 3, pnts, ROP_SRCCOPY, BBO_IGNORE );
803 WinReleasePS( hps );
804 return pm;
805}
806
807#ifndef QT_NO_PIXMAP_TRANSFORMATION
808QPixmap QPixmap::xForm( const QWMatrix &matrix ) const
809{
810 int w, h; // size of target pixmap
811 int ws, hs; // size of source pixmap
812 uchar *dptr; // data in target pixmap
813 int dbpl, dbytes; // bytes per line/bytes total
814 uchar *sptr; // data in original pixmap
815 int sbpl; // bytes per line in original
816 int bpp; // bits per pixel
817 bool depth1 = depth() == 1;
818
819 if ( isNull() ) // this is a null pixmap
820 return copy();
821
822 ws = width();
823 hs = height();
824
825 QWMatrix mat( matrix.m11(), matrix.m12(), matrix.m21(), matrix.m22(), 0., 0. );
826
827 if ( matrix.m12() == 0.0F && matrix.m21() == 0.0F &&
828 matrix.m11() >= 0.0F && matrix.m22() >= 0.0F ) {
829 if ( mat.m11() == 1.0F && mat.m22() == 1.0F )
830 return *this; // identity matrix
831
832 h = qRound( mat.m22()*hs );
833 w = qRound( mat.m11()*ws );
834 h = QABS( h );
835 w = QABS( w );
836 if ( data->realAlphaBits == 0 ) {
837 QPixmap pm( w, h, depth(), optimization() );
838 POINTL ptls[] = {
839 { 0, 0 }, { w, h },
840 { 0, 0 }, { ws, hs }
841 };
842 GpiBitBlt( pm.hps, hps, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
843 if ( data->mask ) {
844 QBitmap bm =
845 data->selfmask ? *((QBitmap*)(&pm)) :
846 data->mask->xForm( matrix );
847 pm.setMask( bm );
848 }
849 return pm;
850 }
851 } else {
852 // rotation or shearing
853 QPointArray a( QRect(0,0,ws+1,hs+1) );
854 a = mat.map( a );
855 QRect r = a.boundingRect().normalize();
856 w = r.width()-1;
857 h = r.height()-1;
858 }
859
860 mat = trueMatrix( mat, ws, hs ); // true matrix
861
862 bool invertible;
863 mat = mat.invert( &invertible ); // invert matrix
864
865 if ( h == 0 || w == 0 || !invertible ) { // error, return null pixmap
866 QPixmap pm;
867 pm.data->bitmap = data->bitmap;
868 return pm;
869 }
870
871 if ( data->realAlphaBits ) {
872 bpp = 32;
873 } else {
874 bpp = depth();
875 if ( bpp > 1 && bpp < 8 )
876 bpp = 8;
877 }
878
879 sbpl = ((ws*bpp+31)/32)*4;
880 sptr = new uchar[hs*sbpl];
881 int ncols;
882 if ( bpp <= 8 ) {
883 ncols = 1 << bpp;
884 } else {
885 ncols = 0;
886 }
887
888 // allocate header + ncols palette entries
889 int bmi_data_len = sizeof(BITMAPINFOHEADER2) + 4 * ncols;
890 char *bmi_data = new char[ bmi_data_len ];
891 memset( bmi_data, 0, sizeof(BITMAPINFOHEADER2) );
892 BITMAPINFOHEADER2 &bmh = *(PBITMAPINFOHEADER2) bmi_data;
893 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
894 bmh.cx = ws;
895 bmh.cy = hs;
896 bmh.cPlanes = 1;
897 bmh.cBitCount = bpp;
898 bmh.cclrUsed = ncols;
899 if ( depth1 ) {
900 // always use the black/white palette for monochrome pixmaps;
901 // otherwise GPI can swap 0s and 1s when creating a bitmap.
902 PULONG pal = (PULONG) (bmi_data + sizeof(BITMAPINFOHEADER2));
903 pal[0] = 0;
904 pal[1] = 0x00FFFFFF;
905 }
906
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;
923
924 dptr = new uchar[ dbytes ]; // create buffer for bits
925 Q_CHECK_PTR( dptr );
926 if ( depth1 )
927 memset( dptr, 0x00, dbytes );
928 else if ( bpp == 8 )
929 memset( dptr, white.pixel(), dbytes );
930 else if ( data->realAlphaBits )
931 memset( dptr, 0x00, dbytes );
932 else
933 memset( dptr, 0xff, dbytes );
934
935 int xbpl, p_inc;
936 if ( depth1 ) {
937 xbpl = (w+7)/8;
938 p_inc = dbpl - xbpl;
939 } else {
940 xbpl = (w*bpp)/8;
941 p_inc = dbpl - xbpl;
942 }
943
944 // OS/2 stores first image row at the bottom of the pixmap data,
945 // so do xForm starting from the bottom scanline to the top one
946 if ( !qt_xForm_helper( mat, 0, QT_XFORM_TYPE_MSBFIRST, bpp,
947 dptr + dbytes - dbpl, xbpl, p_inc - dbpl * 2, h,
948 sptr + (hs*sbpl) - sbpl, -sbpl, ws, hs ) ) {
949#if defined(QT_CHECK_RANGE)
950 qWarning( "QPixmap::xForm: display not supported (bpp=%d)",bpp);
951#endif
952 QPixmap pm;
953 delete [] sptr;
954 delete [] bmi_data;
955 delete [] dptr;
956 return pm;
957 }
958
959 delete [] sptr;
960
961 QPixmap pm( w, h, depth(), data->bitmap, optimization() );
962 pm.data->uninit = FALSE;
963 bmh.cx = w;
964 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;
974 if ( data->mask ) {
975 QBitmap bm = data->selfmask ? *((QBitmap*)(&pm)) :
976 data->mask->xForm(matrix);
977 pm.setMask( bm );
978 }
979 return pm;
980}
981#endif // QT_NO_PIXMAP_TRANSFORMATION
982
983/*!
984 \fn HBITMAP QPixmap::hbm() const
985 \internal
986*/
987
988bool QPixmap::hasAlpha() const
989{
990 return data->realAlphaBits || data->mask;
991}
992
993bool QPixmap::hasAlphaChannel() const
994{
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().
1134void QPixmap::prepareForMasking( bool prepare )
1135{
1136 if ( !data->mask || data->selfmask )
1137 return;
1138 if ( prepare ) {
1139 if ( !data->maskedHbm ) {
1140 GpiSetBitmap( hps, 0 );
1141 BITMAPINFOHEADER2 bmh;
1142 memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
1143 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
1144 bmh.cx = data->w;
1145 bmh.cy = data->h;
1146 bmh.cPlanes = 1;
1147 bmh.cBitCount = data->d;
1148 data->maskedHbm = GpiCreateBitmap( hps, &bmh, 0, NULL, NULL );
1149 GpiSetBitmap( hps, data->maskedHbm );
1150 POINTL ptls[] = {
1151 // dst is inclusive
1152 { 0, 0 }, { data->w - 1, data->h - 1 },
1153 { 0, 0 }, { data->w, data->h },
1154 };
1155 GpiWCBitBlt( hps, data->hbm, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
1156 // dst is exclusive
1157 ptls[1].x++;
1158 ptls[1].y++;
1159 // make transparent pixels black
1160 const ULONG AllImageAttrs =
1161 IBB_COLOR | IBB_BACK_COLOR |
1162 IBB_MIX_MODE | IBB_BACK_MIX_MODE;
1163 IMAGEBUNDLE oldIb;
1164 GpiQueryAttrs( hps, PRIM_IMAGE, AllImageAttrs, (PBUNDLE) &oldIb );
1165 IMAGEBUNDLE newIb = {
1166 CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT
1167 };
1168 GpiSetAttrs( hps, PRIM_IMAGE, AllImageAttrs, 0, (PBUNDLE) &newIb );
1169 GpiBitBlt( hps, data->mask->hps, 3, ptls, ROP_SRCAND, BBO_IGNORE );
1170 GpiSetAttrs( hps, PRIM_IMAGE, AllImageAttrs, 0, (PBUNDLE) &oldIb );
1171 } else {
1172 GpiSetBitmap( hps, data->maskedHbm );
1173 }
1174 } else {
1175 GpiSetBitmap( hps, data->hbm );
1176 // 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 ) {
1182 GpiDeleteBitmap( data->maskedHbm );
1183 data->maskedHbm = 0;
1184 }
1185 }
1186}
1187
1188HPOINTER QPixmap::createIcon( bool pointer, int hotX, int hotY, bool mini )
1189{
1190 HPOINTER icon = NULLHANDLE;
1191
1192 if ( !isNull() ) {
1193 int w = WinQuerySysValue( HWND_DESKTOP, pointer ? SV_CXPOINTER : SV_CXICON );
1194 int h = WinQuerySysValue( HWND_DESKTOP, pointer ? SV_CYPOINTER : SV_CYICON );
1195 if ( mini ) {
1196 w /= 2;
1197 h /= 2;
1198 }
1199
1200 QPixmap pm = *this;
1201 if ( data->w != w || data->h != h ) {
1202#if !defined(QT_NO_IMAGE_SMOOTHSCALE)
1203 // do smooth resize until icon is two or more times bigger
1204 // than the pixmap
1205 if ( data->w * 2 > w || data->h * 2 > h ) {
1206 QImage i = convertToImage();
1207 pm = QPixmap( i.smoothScale( w, h ) );
1208 } else
1209#endif
1210 {
1211 pm = QPixmap( w, h );
1212 POINTL ptls[] = {
1213 { 0, 0 }, { w, h },
1214 { 0, 0 }, { data->w, data->h },
1215 };
1216 GpiBitBlt( pm.hps, hps, 4, ptls, ROP_SRCCOPY, BBO_IGNORE );
1217 }
1218 }
1219
1220 QBitmap msk( w, h * 2, TRUE );
1221 if ( pm.data->mask ) {
1222 // create AND mask (XOR mask is left zeroed -- it's ok)
1223 POINTL ptls[] = {
1224 { 0, h }, { w, h * 2 },
1225 { 0, 0 }, { w, h },
1226 };
1227 GpiBitBlt( msk.hps, pm.data->mask->hps, 4, ptls, ROP_NOTSRCCOPY, BBO_IGNORE );
1228 pm.prepareForMasking( TRUE );
1229 }
1230
1231 // unselect bitmap handles from hps
1232 GpiSetBitmap( pm.hps, 0 );
1233 GpiSetBitmap( msk.hps, 0 );
1234
1235 POINTERINFO info;
1236 info.fPointer = pointer;
1237 info.xHotspot = hotX;
1238 info.yHotspot = hotY;
1239 info.hbmPointer = msk.data->hbm;
1240 info.hbmColor = pm.data->mask ? pm.data->maskedHbm : pm.data->hbm;
1241 info.hbmMiniPointer = 0;
1242 info.hbmMiniColor = 0;
1243 icon = WinCreatePointerIndirect( HWND_DESKTOP, &info );
1244
1245 if ( pm.mask() )
1246 pm.prepareForMasking( FALSE );
1247
1248 GpiSetBitmap( msk.hps, msk.data->hbm );
1249 GpiSetBitmap( pm.hps, pm.data->hbm );
1250 }
1251
1252 return icon;
1253}
1254
1255void QPixmap::attachHandle( HBITMAP hbm )
1256{
1257 if ( paintingActive() )
1258 return;
1259
1260 BITMAPINFOHEADER bmh;
1261 if (!GpiQueryBitmapParameters( hbm, &bmh ))
1262 return;
1263
1264 if ( !data->uninit && !isNull() ) { // has existing pixmap
1265 deref();
1266 init( 0, 0, 0, FALSE, defOptim );
1267 }
1268
1269 data->uninit = FALSE;
1270 data->w = bmh.cx;
1271 data->h = bmh.cy;
1272 data->d = bmh.cPlanes * bmh.cBitCount;
1273
1274 hps = alloc_mem_ps( bmh.cx, bmh.cy );
1275 data->hbm = hbm;
1276
1277 GpiSetBitmap( hps, data->hbm );
1278}
1279
1280HBITMAP QPixmap::detachHandle()
1281{
1282 if ( paintingActive() )
1283 return 0;
1284
1285 HBITMAP hbm = data->hbm;
1286
1287 // do what deref() will not do after data->hbm is set to 0
1288 if ( hps )
1289 GpiSetBitmap( hps, 0 );
1290
1291 data->hbm = 0;
1292 deref();
1293
1294 return hbm;
1295}
1296
1297/*!
1298 \internal
1299
1300 Creates an OS/2 icon or pointer from two given pixmaps.
1301
1302 \param pointer true to create a pointer, false to create an icon
1303 \param hotX X coordinate of the action point within the pointer/icon
1304 \param hotY Y coordinate of the action point within the pointer/icon
1305 \param normal pixmap for a normal-sized pointer/icon
1306 \param mini pixmap for a mini-sized pointer/icon
1307
1308 \note Due to a bug in WinCreatePointerIndirect, you can specify either
1309 \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.
1311*/
1312// static
1313HPOINTER QPixmap::createIcon( bool pointer, int hotX, int hotY,
1314 const QPixmap *normal, const QPixmap *mini )
1315{
1316 // Due to a bug in WinCreatePointerIndirect (it always ignores
1317 // 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.
1322
1323 if ( normal && !normal->isNull() ) {
1324#ifdef QT_CHECK_RANGE
1325 if ( mini && !mini->isNull() )
1326 qWarning( "QPixmap::createIcon(): due to a bug in WinCreatePointerIndirect "
1327 "either a normal or a mini pixmap should be specified, "
1328 "but not both. Will use a normal pixmap." );
1329#endif
1330 return const_cast <QPixmap *> (normal)->createIcon( pointer, hotX, hotY, false );
1331 }
1332
1333 if ( mini && !mini->isNull() )
1334 return const_cast <QPixmap *> (mini)->createIcon( pointer, hotX, hotY, true );
1335
1336 return 0;
1337}
1338
1339Q_EXPORT void copyBlt( QPixmap *dst, int dx, int dy,
1340 const QPixmap *src, int sx, int sy, int sw, int sh )
1341{
1342 if ( ! dst || ! src || sw == 0 || sh == 0 || dst->depth() != src->depth() ) {
1343#ifdef QT_CHECK_NULL
1344 Q_ASSERT( dst != 0 );
1345 Q_ASSERT( src != 0 );
1346#endif
1347 return;
1348 }
1349
1350 // copy mask data
1351 if ( src->data->mask ) {
1352 if ( ! dst->data->mask ) {
1353 dst->data->mask = new QBitmap( dst->width(), dst->height() );
1354
1355 // new masks are fully opaque by default
1356 dst->data->mask->fill( Qt::color1 );
1357 } else if ( dst->data->maskedHbm ) {
1358 // reset the precomposed masked pixmap
1359 GpiDeleteBitmap( dst->data->maskedHbm );
1360 dst->data->maskedHbm = 0;
1361 }
1362
1363 bitBlt( dst->data->mask, dx, dy,
1364 src->data->mask, sx, sy, sw, sh, Qt::CopyROP, TRUE );
1365 }
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}
Note: See TracBrowser for help on using the repository browser.