source: trunk/src/kernel/qpaintdevice_pm.cpp@ 65

Last change on this file since 65 was 65, checked in by dmik, 19 years ago

Fixed drawing of alpha pixmaps (drawing a part of the pixmap with the alpha channel caused erroneous alpha channel shifts and visual pixmap distortions).

  • Property svn:keywords set to Id
File size: 22.0 KB
Line 
1/****************************************************************************
2** $Id: qpaintdevice_pm.cpp 65 2006-03-12 19:33:32Z dmik $
3**
4** Implementation of QPaintDevice class for OS/2
5**
6** Copyright (C) 1992-2000 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 "qpaintdevice.h"
39#include "qpaintdevicemetrics.h"
40#include "qpainter.h"
41#include "qwidget.h"
42#include "qbitmap.h"
43#include "qapplication.h"
44#include "qapplication_p.h"
45#include "qt_os2.h"
46
47
48QPaintDevice::QPaintDevice( uint devflags )
49{
50 if ( !qApp ) { // global constructor
51#if defined(QT_CHECK_STATE)
52 qFatal( "QPaintDevice: Must construct a QApplication before a "
53 "QPaintDevice" );
54#endif
55 return;
56 }
57 devFlags = devflags;
58 hps = 0;
59 painters = 0;
60}
61
62QPaintDevice::~QPaintDevice()
63{
64#if defined(QT_CHECK_STATE)
65 if ( paintingActive() )
66 qWarning( "QPaintDevice: Cannot destroy paint device that is being "
67 "painted. Be sure to QPainter::end() painters!" );
68#endif
69}
70
71HPS QPaintDevice::handle() const
72{
73 return hps;
74}
75
76bool QPaintDevice::cmd( int, QPainter *, QPDevCmdParam * )
77{
78#if defined(QT_CHECK_STATE)
79 qWarning( "QPaintDevice::cmd: Device has no command interface" );
80#endif
81 return FALSE;
82}
83
84int QPaintDevice::metric( int ) const
85{
86#if defined(QT_CHECK_STATE)
87 qWarning( "QPaintDevice::metrics: Device has no metric information" );
88#endif
89 return 0;
90}
91
92int QPaintDevice::fontMet( QFont *, int, const char*, int ) const
93{
94 return 0;
95}
96
97int QPaintDevice::fontInf( QFont *, int ) const
98{
99 return 0;
100}
101
102// these are defined in qpixmap_pm.cpp
103extern HPS qt_alloc_mem_ps( int w, int h, HPS compat = 0 );
104extern void qt_free_mem_ps( HPS hps );
105
106// ROP translation table to convert Qt::RasterOp to ROP_ constants
107extern const LONG qt_ropCodes_2ROP[] = {
108 ROP_SRCCOPY, // CopyROP
109 ROP_SRCPAINT, // OrROP
110 ROP_SRCINVERT, // XorROP
111 0x22, // NotAndROP
112 ROP_NOTSRCCOPY, // NotCopyROP
113 ROP_MERGEPAINT, // NotOrROP
114 0x99, // NotXorROP
115 ROP_SRCAND, // AndROP
116 ROP_DSTINVERT, // NotROP
117 ROP_ZERO, // ClearROP
118 ROP_ONE, // SetROP
119 0xAA, // NopROP
120 ROP_SRCERASE, // AndNotROP
121 0xDD, // OrNotROP
122 0x77, // NandROP
123 ROP_NOTSRCERASE // NorROP
124};
125
126// draws the pixmap with a mask using the black source method
127static void drawMaskedPixmap(
128 HPS dst_ps, int dst_depth, bool grab_dest, HPS src_ps, HPS mask_ps,
129 int dx, int dy, int sx, int sy, int w, int h, Qt::RasterOp rop )
130{
131 IMAGEBUNDLE oldIb;
132
133 if ( !mask_ps ) {
134 // self-masked pixmap
135 POINTL ptls[] = { { dx, dy }, { dx + w, dy + h },
136 { sx, sy } };
137 IMAGEBUNDLE newIb;
138 GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, (PBUNDLE) &oldIb );
139 newIb.usBackMixMode = BM_SRCTRANSPARENT;
140 GpiSetAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, 0, (PBUNDLE) &newIb );
141 GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
142 GpiSetAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, 0, (PBUNDLE) &oldIb );
143 } else {
144 bool simple = (rop == Qt::CopyROP) || (rop == Qt::XorROP);
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
188 // query the destination color for 1-bpp bitmaps
189 GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_COLOR, (PBUNDLE) &oldIb );
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
221 // draw the mask: make non-transparent pixels (corresponding to
222 // ones in the mask) black. skip this step when rop = XorROP
223 // to get the XOR effect.
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
230 if ( !simple ) {
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 );
235 } else {
236 // draw masked pixmap; transparent pixels are zeroed there
237 // by prepareForMasking( TRUE )
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 );
242 }
243
244 // flush the buffer
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
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
265static void drawAlphaPixmap (
266 HPS dst_ps, int dst_w, HPS src_ps, int src_w, uchar *alpha,
267 int dx, int dy, int sx, int sy, int w, int h, int depth )
268{
269 Q_ASSERT( depth == 32 || depth == 24 );
270
271 bool grab_dest = false;
272 int dst_x = dx;
273
274 if ( dst_w == 0 ) {
275 grab_dest = true;
276 dst_w = w;
277 dst_x = 0;
278 }
279
280 int dst_bpl = ((depth * dst_w + 31) / 32) * 4;
281 int src_bpl = ((depth * src_w + 31) / 32) * 4;
282
283 uchar *dst = new uchar [dst_bpl * h];
284 uchar *src = new uchar [src_bpl * h];
285
286 BITMAPINFOHEADER2 bmh;
287 memset( &bmh, 0, sizeof(BITMAPINFOHEADER2) );
288 bmh.cbFix = sizeof(BITMAPINFOHEADER2);
289 bmh.cPlanes = 1;
290 bmh.cBitCount = depth;
291 if ( grab_dest ) {
292 bmh.cx = w;
293 bmh.cy = h;
294
295 // helper hps for dblbuf
296 HPS hpsBuf = qt_alloc_mem_ps( w, h, dst_ps );
297 // helper bitmap for dblbuf
298 HBITMAP hbmBuf = GpiCreateBitmap( hpsBuf, &bmh, 0, NULL, NULL );
299 GpiSetBitmap( hpsBuf, hbmBuf );
300
301 // grab the destination and get bits
302 POINTL ptls[] = { { 0, 0 }, { w, h }, { dx, dy } };
303 GpiBitBlt ( hpsBuf, dst_ps, 3, ptls, ROP_SRCCOPY, BBO_IGNORE );
304 GpiQueryBitmapBits( hpsBuf, 0, h, (PBYTE) dst, (PBITMAPINFO2) &bmh );
305
306 // free dblbuf
307 GpiSetBitmap( hpsBuf, 0 );
308 GpiDeleteBitmap( hbmBuf );
309 qt_free_mem_ps( hpsBuf );
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 + sy * src_w + sx : 0;
322 int dst_inc = dst_bpl - px_sz * w;
323 int src_inc = src_bpl - px_sz * w;
324 int a_inc = src_w - w;
325 int px_skip = px_sz - 3;
326
327 // use two separate code paths to increase the speed slightly by
328 // eliminating one comparison op (a_ptr != 0) inside the most nested loop
329 if ( a_ptr ) {
330 for ( int y = 0; y < h; y++ ) {
331 for ( int x = 0; x < w; x++ ) {
332 uchar a = *(a_ptr++);
333 if ( a == 0 ) {
334 dst_ptr += px_sz;
335 src_ptr += px_sz;
336 continue;
337 } else if ( a == 255 ) {
338 *(dst_ptr++) = *(src_ptr++);
339 *(dst_ptr++) = *(src_ptr++);
340 *(dst_ptr++) = *(src_ptr++);
341 } else {
342 *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
343 dst_ptr ++;
344 *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
345 dst_ptr ++;
346 *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
347 dst_ptr ++;
348 }
349 dst_ptr += px_skip;
350 src_ptr += px_skip;
351 }
352 dst_ptr += dst_inc;
353 src_ptr += src_inc;
354 a_ptr += a_inc;
355 }
356 } else {
357 for ( int y = 0; y < h; y++ ) {
358 for ( int x = 0; x < w; x++ ) {
359 uchar a = src_ptr [3];
360 if ( a == 0 ) {
361 dst_ptr += px_sz;
362 src_ptr += px_sz;
363 continue;
364 } else if ( a == 255 ) {
365 *(dst_ptr++) = *(src_ptr++);
366 *(dst_ptr++) = *(src_ptr++);
367 *(dst_ptr++) = *(src_ptr++);
368 } else {
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 *dst_ptr += (*(src_ptr++) - *dst_ptr) * a / 255;
374 dst_ptr ++;
375 }
376 dst_ptr += px_skip;
377 src_ptr += px_skip;
378 }
379 dst_ptr += dst_inc;
380 src_ptr += src_inc;
381 }
382 }
383
384 // flush the dst buffer
385 {
386 bmh.cx = dst_w;
387 bmh.cy = h;
388 POINTL ptls[] = { { dx, dy }, { dx + w - 1, dy + h - 1 },
389 { dst_x, 0 }, { dst_x + w, h } };
390 GpiDrawBits( dst_ps, (PVOID) dst, (PBITMAPINFO2) &bmh, 4, ptls,
391 ROP_SRCCOPY, BBO_IGNORE );
392 }
393
394 delete[] src;
395 delete[] dst;
396}
397
398void bitBlt( QPaintDevice *dst, int dx, int dy,
399 const QPaintDevice *src, int sx, int sy, int sw, int sh,
400 Qt::RasterOp rop, bool ignoreMask )
401{
402 if ( !src || !dst || sw == 0 || sh == 0 ) {
403#if defined(QT_CHECK_NULL)
404 Q_ASSERT( src != 0 );
405 Q_ASSERT( dst != 0 );
406#endif
407 return;
408 }
409 if ( src->isExtDev() )
410 return;
411
412 QPaintDevice *pdev = QPainter::redirect( dst );
413 if ( pdev )
414 dst = pdev;
415
416 int ts = src->devType(); // from device type
417 int td = dst->devType(); // to device type
418
419 int src_w = src->metric(QPaintDeviceMetrics::PdmWidth);
420 int src_h = src->metric(QPaintDeviceMetrics::PdmHeight);
421 int dst_w = dst->metric(QPaintDeviceMetrics::PdmWidth);
422 int dst_h = dst->metric(QPaintDeviceMetrics::PdmHeight);
423
424 if ( sw < 0 ) // special width
425 sw = src_w - sx;
426 if ( sh < 0 ) // special height
427 sh = src_h - sy;
428
429 // ensure coordinates are within borders, clip if necessary
430 if ( sx < 0 || sy < 0 || sx + sw > src_w || sy + sh > src_h ||
431 dx < 0 || dy < 0 || dx + sw > dst_w || dy + sh > dst_h )
432 {
433 int tx = dx - sx;
434 int ty = dy - sy;
435 QRect dr( 0, 0, dst_w, dst_h ); // dst rect
436 QRect sr( tx, ty, src_w, src_h ); // src rect in dst coords
437 QRect bltr( dx, dy, sw, sh ); // blit rect in dst coords
438 bltr &= (dr & sr);
439 if (bltr.isEmpty())
440 return;
441 dx = bltr.x();
442 dy = bltr.y();
443 sx = dx - tx;
444 sy = dy - ty;
445 sw = bltr.width();
446 sh = bltr.height();
447 }
448
449 if ( dst->paintingActive() && dst->isExtDev() ) {
450 QPixmap *pm; // output to picture/printer
451 bool tmp_pm = TRUE;
452 if ( ts == QInternal::Pixmap ) {
453 pm = (QPixmap*)src;
454 if ( sx != 0 || sy != 0 ||
455 sw != pm->width() || sh != pm->height() ) {
456 QPixmap *pm_new = new QPixmap( sw, sh, pm->depth() );
457 bitBlt( pm_new, 0, 0, pm, sx, sy, sw, sh );
458 pm = pm_new;
459 } else {
460 tmp_pm = FALSE;
461 }
462 } else if ( ts == QInternal::Widget ) { // bitBlt to temp pixmap
463 pm = new QPixmap( sw, sh );
464 Q_CHECK_PTR( pm );
465 bitBlt( pm, 0, 0, src, sx, sy, sw, sh );
466 } else {
467#if defined(QT_CHECK_RANGE)
468 qWarning( "bitBlt: Cannot bitBlt from device" );
469#endif
470 return;
471 }
472 QPDevCmdParam param[3];
473 QPoint p(dx,dy);
474 param[0].point = &p;
475 param[1].pixmap = pm;
476 dst->cmd( QPaintDevice::PdcDrawPixmap, 0, param );
477 if ( tmp_pm )
478 delete pm;
479 return;
480 }
481
482 switch ( ts ) {
483 case QInternal::Widget:
484 case QInternal::Pixmap:
485 case QInternal::System: // OK, can blt from these
486 break;
487 default:
488#if defined(QT_CHECK_RANGE)
489 qWarning( "bitBlt: Cannot bitBlt from device type %x", ts );
490#endif
491 return;
492 }
493 switch ( td ) {
494 case QInternal::Widget:
495 case QInternal::Pixmap:
496 case QInternal::System: // OK, can blt to these
497 break;
498 default:
499#if defined(QT_CHECK_RANGE)
500 qWarning( "bitBlt: Cannot bitBlt to device type %x", td );
501#endif
502 return;
503 }
504
505 if ( rop > Qt::LastROP ) {
506#if defined(QT_CHECK_RANGE)
507 qWarning( "bitBlt: Invalid ROP code" );
508#endif
509 return;
510 }
511
512 if ( dst->isExtDev() ) {
513#if defined(QT_CHECK_NULL)
514 qWarning( "bitBlt: Cannot bitBlt to device" );
515#endif
516 return;
517 }
518
519 if ( td == QInternal::Pixmap )
520 ((QPixmap*)dst)->detach(); // changes shared pixmap
521
522 HPS src_ps = src->hps, dst_ps = dst->hps;
523 bool src_tmp = FALSE, dst_tmp = FALSE;
524
525 QPixmap *src_pm;
526 QBitmap *mask;
527 if ( ts == QInternal::Pixmap ) {
528 src_pm = (QPixmap *)src;
529 mask = ignoreMask ? 0 : (QBitmap *)src_pm->mask();
530 } else {
531 src_pm = 0;
532 mask = 0;
533 if ( !src_ps && ts == QInternal::Widget ) {
534 src_ps = WinGetPS( ((QWidget*)src)->winId() );
535 src_tmp = TRUE;
536 }
537 }
538 if ( td != QInternal::Pixmap ) {
539 if ( !dst_ps && td == QInternal::Widget ) {
540 dst_ps = ((QWidget*)dst)->getTargetPS();
541 dst_tmp = TRUE;
542 }
543 }
544#if defined(QT_CHECK_NULL)
545 Q_ASSERT( src_ps && dst_ps );
546#endif
547
548 // flip y coordinates
549 int fsy = sy;
550 if ( ts == QInternal::Widget || ts == QInternal::Pixmap ) {
551 int devh = (ts == QInternal::Widget) ?
552 ((QWidget*)src)->height() : ((QPixmap*)src)->height();
553 fsy = devh - (fsy + sh);
554 }
555 int fdy = dy;
556 if ( td == QInternal::Widget || td == QInternal::Pixmap ) {
557 int devh = (td == QInternal::Widget) ?
558 ((QWidget*)dst)->height() : ((QPixmap*)dst)->height();
559 fdy = devh - (fdy + sh);
560 }
561 POINTL ptls[] = {
562 { dx, fdy }, { dx + sw, fdy + sh },
563 { sx, fsy },
564 };
565
566 if ( td == QInternal::Pixmap ) {
567 // Ensure the auxiliary masked bitmap created for masking is destroyed
568 // (to cause it to be recreated when the destination is blitted next
569 // time). Also ensure the alpha channel of the destination pixmap is
570 // unfolded -- any GPI call will clear the high byte that may be storing
571 // the alpha bits, so the pixmap will appear as fully transparent.
572 QPixmap *dst_pm = (QPixmap *) dst;
573 if ( dst_pm->data->mask )
574 dst_pm->prepareForMasking( FALSE, TRUE );
575 if ( dst_pm->data->hasRealAlpha )
576 dst_pm->unfoldAlphaChannel();
577 }
578
579 if ( src_pm && src_pm->data->hasRealAlpha && !ignoreMask ) {
580 int dst_w = 0; // implies grab_dest = true
581 if ( td == QInternal::Pixmap )
582 dst_w = ((QPixmap *) dst)->data->w; // implies grab_dest = false
583 drawAlphaPixmap( dst_ps, dst_w, src_ps, src_pm->data->w,
584 src_pm->data->realAlphaBits,
585 dx, fdy, sx, fsy, sw, sh, QPixmap::trueColorDepth() );
586 } else if ( mask ) {
587#if 0
588 // Unfortunately, this nice method of setting the mask as a pattern
589 // and using the corresponding ROPs to do masking in one step will
590 // not apways work on many video drivers (including SDD/SNAP) since
591 // they can spontaneously simplify the bitmap set as a pattern (for
592 // example, take only first 8 pixels of the mask width), which will
593 // produce wrong results.
594 const ULONG AllAreaAttrs =
595 ABB_COLOR | ABB_BACK_COLOR |
596 ABB_MIX_MODE | ABB_BACK_MIX_MODE |
597 ABB_SET | ABB_SYMBOL | ABB_REF_POINT;
598 AREABUNDLE oldAb;
599 GpiQueryAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, (PBUNDLE) &oldAb );
600 AREABUNDLE newAb = {
601 CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT,
602 LCID_QTMaskBitmap, 0, ptls [0]
603 };
604 GpiSetBitmap( mask->hps, 0 );
605 GpiSetBitmapId( dst_ps, mask->hbm(), LCID_QTMaskBitmap );
606 GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &newAb );
607 // we use the same rop codes for masked bitblt after setting the
608 // low half of the rop byte to 0xA, which means destination bits
609 // should be preserved where the corresponding bits in the mask
610 // are zeroes.
611 GpiBitBlt( dst_ps, src_ps, 3, ptls, (qt_ropCodes_2ROP[rop] & 0xF0) | 0x0A, BBO_IGNORE );
612 GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &oldAb );
613 GpiDeleteSetId( dst_ps, LCID_QTMaskBitmap );
614 GpiSetBitmap( mask->hps, mask->hbm() );
615#else
616 bool grab_dest = td != QInternal::Pixmap;
617 src_pm->prepareForMasking( TRUE );
618 drawMaskedPixmap(
619 dst_ps, dst->metric( QPaintDeviceMetrics::PdmDepth ), grab_dest,
620 src_ps, src_pm->data->selfmask ? 0 : mask->hps,
621 dx, fdy, sx, fsy, sw, sh, rop );
622 src_pm->prepareForMasking( FALSE );
623#endif
624 } else {
625 GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
626 }
627
628 if ( src_tmp )
629 WinReleasePS( src_ps );
630 if ( dst_tmp )
631 WinReleasePS( dst_ps );
632}
633
634
635void QPaintDevice::setResolution( int )
636{
637}
638
639int QPaintDevice::resolution() const
640{
641 return metric( QPaintDeviceMetrics::PdmDpiY );
642}
Note: See TracBrowser for help on using the repository browser.