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

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

Transferred Qt for OS/2 version 3.3.1-rc5 sources from the CVS

  • Property svn:keywords set to Id
File size: 17.4 KB
Line 
1/****************************************************************************
2** $Id: qpaintdevice_pm.cpp 8 2005-11-16 19:36:46Z 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
127void 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 };
138 IMAGEBUNDLE oldIb;
139
140 if ( !mask_ps ) {
141 // self-masked pixmap
142 IMAGEBUNDLE newIb;
143 GpiQueryAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, (PBUNDLE) &oldIb );
144 newIb.usBackMixMode = BM_SRCTRANSPARENT;
145 GpiSetAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, 0, (PBUNDLE) &newIb );
146 GpiBitBlt( dst_ps, src_ps, 3, ptls, qt_ropCodes_2ROP[rop], BBO_IGNORE );
147 GpiSetAttrs( dst_ps, PRIM_IMAGE, IBB_BACK_MIX_MODE, 0, (PBUNDLE) &oldIb );
148 } else {
149 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
163 // query the destination color for 1-bpp bitmaps
164 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 );
171 // draw the mask: make non-transparent pixels (corresponding to
172 // ones in the mask) black. skip this step when rop = XorROP
173 // 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
178 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 );
194 } else {
195 // draw masked pixmap; transparent pixels are zeroed there
196 // by prepareForMasking( TRUE )
197 GpiSetColor( hpsBuf, oldIb.lColor );
198 GpiBitBlt( hpsBuf, src_ps, 3, &ptls[2], ROP_SRCINVERT, BBO_IGNORE );
199 }
200
201 // flush the buffer
202 GpiBitBlt( dst_ps, hpsBuf, 3, &ptls[0], ROP_SRCCOPY, BBO_IGNORE );
203 // free resources
204 GpiSetBitmap( hpsBuf, 0 );
205 GpiDeleteBitmap( hbmBuf );
206 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//}
268
269void bitBlt( QPaintDevice *dst, int dx, int dy,
270 const QPaintDevice *src, int sx, int sy, int sw, int sh,
271 Qt::RasterOp rop, bool ignoreMask )
272{
273 if ( !src || !dst ) {
274#if defined(QT_CHECK_NULL)
275 Q_ASSERT( src != 0 );
276 Q_ASSERT( dst != 0 );
277#endif
278 return;
279 }
280 if ( src->isExtDev() )
281 return;
282
283 QPaintDevice *pdev = QPainter::redirect( dst );
284 if ( pdev )
285 dst = pdev;
286
287 int ts = src->devType(); // from device type
288 int td = dst->devType(); // to device type
289
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
303 if ( dst->paintingActive() && dst->isExtDev() ) {
304 QPixmap *pm; // output to picture/printer
305 bool tmp_pm = TRUE;
306 if ( ts == QInternal::Pixmap ) {
307 pm = (QPixmap*)src;
308 if ( sx != 0 || sy != 0 ||
309 sw != pm->width() || sh != pm->height() ) {
310 QPixmap *pm_new = new QPixmap( sw, sh, pm->depth() );
311 bitBlt( pm_new, 0, 0, pm, sx, sy, sw, sh );
312 pm = pm_new;
313 } else {
314 tmp_pm = FALSE;
315 }
316 } else if ( ts == QInternal::Widget ) { // bitBlt to temp pixmap
317 pm = new QPixmap( sw, sh );
318 Q_CHECK_PTR( pm );
319 bitBlt( pm, 0, 0, src, sx, sy, sw, sh );
320 } else {
321#if defined(QT_CHECK_RANGE)
322 qWarning( "bitBlt: Cannot bitBlt from device" );
323#endif
324 return;
325 }
326 QPDevCmdParam param[3];
327 QPoint p(dx,dy);
328 param[0].point = &p;
329 param[1].pixmap = pm;
330 dst->cmd( QPaintDevice::PdcDrawPixmap, 0, param );
331 if ( tmp_pm )
332 delete pm;
333 return;
334 }
335
336 switch ( ts ) {
337 case QInternal::Widget:
338 case QInternal::Pixmap:
339 case QInternal::System: // OK, can blt from these
340 break;
341 default:
342#if defined(QT_CHECK_RANGE)
343 qWarning( "bitBlt: Cannot bitBlt from device type %x", ts );
344#endif
345 return;
346 }
347 switch ( td ) {
348 case QInternal::Widget:
349 case QInternal::Pixmap:
350 case QInternal::System: // OK, can blt to these
351 break;
352 default:
353#if defined(QT_CHECK_RANGE)
354 qWarning( "bitBlt: Cannot bitBlt to device type %x", td );
355#endif
356 return;
357 }
358
359 if ( rop > Qt::LastROP ) {
360#if defined(QT_CHECK_RANGE)
361 qWarning( "bitBlt: Invalid ROP code" );
362#endif
363 return;
364 }
365
366 if ( dst->isExtDev() ) {
367#if defined(QT_CHECK_NULL)
368 qWarning( "bitBlt: Cannot bitBlt to device" );
369#endif
370 return;
371 }
372
373 if ( td == QInternal::Pixmap )
374 ((QPixmap*)dst)->detach(); // changes shared pixmap
375
376 HPS src_ps = src->hps, dst_ps = dst->hps;
377 bool src_tmp = FALSE, dst_tmp = FALSE;
378
379 QPixmap *src_pm;
380 QBitmap *mask;
381 if ( ts == QInternal::Pixmap ) {
382 src_pm = (QPixmap *)src;
383 mask = ignoreMask ? 0 : (QBitmap *)src_pm->mask();
384 } else {
385 src_pm = 0;
386 mask = 0;
387 if ( !src_ps && ts == QInternal::Widget ) {
388 src_ps = WinGetPS( ((QWidget*)src)->winId() );
389 src_tmp = TRUE;
390 }
391 }
392 if ( td != QInternal::Pixmap ) {
393 if ( !dst_ps && td == QInternal::Widget ) {
394 QWidget *dst_w = (QWidget*)dst;
395 if ( dst_w->testWFlags(Qt::WPaintUnclipped) ) {
396 dst_ps = WinGetClipPS( dst_w->winId(), 0, PSF_PARENTCLIP );
397 } else {
398 dst_ps = WinGetPS( dst_w->winId() );
399 }
400 dst_tmp = TRUE;
401 }
402 }
403#if defined(QT_CHECK_NULL)
404 Q_ASSERT( src_ps && dst_ps );
405#endif
406
407 // flip y coordinates
408 int fsy = sy;
409 if ( ts == QInternal::Widget || ts == QInternal::Pixmap ) {
410 int devh = (ts == QInternal::Widget) ?
411 ((QWidget*)src)->height() : ((QPixmap*)src)->height();
412 fsy = devh - (fsy + sh);
413 }
414 int fdy = dy;
415 if ( td == QInternal::Widget || td == QInternal::Pixmap ) {
416 int devh = (td == QInternal::Widget) ?
417 ((QWidget*)dst)->height() : ((QPixmap*)dst)->height();
418 fdy = devh - (fdy + sh);
419 }
420 POINTL ptls[] = {
421 { dx, fdy }, { dx + sw, fdy + sh },
422 { sx, fsy },
423 };
424
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] );
432 } else if ( mask ) {
433 if ( /*src_pm &&*/ td==QInternal::Pixmap && ((QPixmap *)dst)->data->realAlphaBits ) {
434 qWarning( "::bitBlt() for pixmaps with alpha is not yet implemented on OS/2" );
435//@@TODO (dmik): later
436// src_pm->convertToAlphaPixmap();
437// QPixmap::bitBltAlphaPixmap( (QPixmap *)dst, dx, dy, src_pm, sx, sy, sw, sh, TRUE );
438 } else {
439#if 0
440//@@TODO (dmik): unfortunately, this nice method of setting the mask as a
441// pattern and using the corresponding ROPs to do masking in one step
442// will not apways work on many video drivers (including SDD/SNAP) since
443// they can spontaneously simplify the bitmap set as a pattern (for example,
444// take only first 8 pixels of the mask width), which will produce wrong
445// results.
446 const ULONG AllAreaAttrs =
447 ABB_COLOR | ABB_BACK_COLOR |
448 ABB_MIX_MODE | ABB_BACK_MIX_MODE |
449 ABB_SET | ABB_SYMBOL | ABB_REF_POINT;
450 AREABUNDLE oldAb;
451 GpiQueryAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, (PBUNDLE) &oldAb );
452 AREABUNDLE newAb = {
453 CLR_TRUE, CLR_FALSE, FM_OVERPAINT, BM_OVERPAINT,
454 LCID_QTMaskBitmap, 0, ptls [0]
455 };
456 GpiSetBitmap( mask->hps, 0 );
457 GpiSetBitmapId( dst_ps, mask->hbm(), LCID_QTMaskBitmap );
458 GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &newAb );
459 // we use the same rop codes for masked bitblt after setting the
460 // low half of the rop byte to 0xA, which means destination bits
461 // should be preserved where the corresponding bits in the mask
462 // are zeroes.
463 GpiBitBlt( dst_ps, src_ps, 3, ptls, (qt_ropCodes_2ROP[rop] & 0xF0) | 0x0A, BBO_IGNORE );
464 GpiSetAttrs( dst_ps, PRIM_AREA, AllAreaAttrs, 0, (PBUNDLE) &oldAb );
465 GpiDeleteSetId( dst_ps, LCID_QTMaskBitmap );
466 GpiSetBitmap( mask->hps, mask->hbm() );
467#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 }
478 } 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 }
503 if ( src_tmp )
504 WinReleasePS( src_ps );
505 if ( dst_tmp )
506 WinReleasePS( dst_ps );
507}
508
509
510void QPaintDevice::setResolution( int )
511{
512}
513
514int QPaintDevice::resolution() const
515{
516 return metric( QPaintDeviceMetrics::PdmDpiY );
517}
Note: See TracBrowser for help on using the repository browser.