Changeset 61


Ignore:
Timestamp:
Feb 6, 2006, 10:43:39 PM (20 years ago)
Author:
dmik
Message:

Implemented QRegion(..., QRegion::Eclipse) and QRegion(QPointArray &,...) constructors.
Improved Qt<->GPI region coordinates translation (it's now implicit), QRegion::handle() takes a height of the target devise as an argument (defaults to 0).

Location:
trunk
Files:
10 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/qpainter.h

    r8 r61  
    410410    uint        pixmapBrush : 1;
    411411    int         devh;
    412     QRegion     repaintRgn;
     412    QRegion     def_crgn;
     413    QRegion     cur_crgn;
    413414#elif defined(Q_WS_X11)
    414415    friend class QFontEngineXLFD;
  • trunk/include/qregion.h

    r8 r61  
    9494                        { return !(operator==(r)); }
    9595
    96 #if defined(Q_WS_WIN) || defined(Q_WS_PM)
    97     HRGN    handle() const { if (! data->rgn ) update(); return data->rgn; }
     96#if defined(Q_WS_WIN)
     97    HRGN    handle() const { return data->rgn; }
     98#elif defined(Q_WS_PM)   
     99    HRGN handle( int target_height = 0 ) const {
     100        if ( !data->rgn || data->hgt != target_height )
     101            updateHandle( target_height );
     102        return data->rgn;
     103    }
    98104#elif defined(Q_WS_X11)
    99105    Region handle() const { if(!data->rgn) updateX11Region(); return data->rgn; }
     
    116122    QRegion winCombine( const QRegion &, int ) const;
    117123#elif defined(Q_WS_PM)
     124    QRegion( HRGN hrgn, int target_height );
    118125    QRegion pmCombine( const QRegion &, int ) const;
    119     void update() const;
     126    void updateHandle( int target_height ) const;
    120127#elif defined(Q_WS_X11)
    121128    void updateX11Region() const;
     
    125132    void    exec( const QByteArray &, int ver = 0 );
    126133    struct QRegionData : public QShared {
    127 #if defined(Q_WS_WIN) || defined(Q_WS_PM)
     134#if defined(Q_WS_WIN)
    128135        HRGN   rgn;
     136#elif defined(Q_WS_PM)
     137        HRGN rgn;
     138        int hgt;
    129139#elif defined(Q_WS_X11)
    130140        Region rgn;
     
    150160    friend class QETWidget;
    151161    friend class QPainter;
    152     friend void qt_set_paintevent_clipping( QPaintDevice*, const QRegion& );
    153162#endif
    154163
  • trunk/include/qwidget.h

    r57 r61  
    598598    friend bool qt_window_rgn(WId, short, RgnHandle, bool);
    599599    friend class QDragManager;
     600#elif defined (Q_WS_PM)
     601    enum ClipMode { Unclipped, ClipAll, ClipSiblings };
     602    HPS getTargetPS( ClipMode m = ClipAll );   
     603    friend Q_EXPORT void bitBlt( QPaintDevice *, int, int,
     604                                 const QPaintDevice *,
     605                                 int, int, int, int, RasterOp, bool );
    600606#endif
    601607
  • trunk/include/qwindowdefs_pm.h

    r8 r61  
    5656#include <os2.h>
    5757
     58// Innotek GCC lacks some API functions in its version of OS/2 Toolkit headers
     59
     60#define QCRGN_ERROR                 0
     61#define QCRGN_OK                    1
     62#define QCRGN_NO_CLIP_REGION        2
     63
     64LONG APIENTRY WinQueryClipRegion( HWND hwnd, HRGN hrgnClip );
     65BOOL APIENTRY WinSetClipRegion( HWND hwnd, HRGN hrgnClip );
     66
    5867#else
    5968
     
    7180typedef HWND WId;
    7281
    73 //@@TODO (dmik): remove
    74 //Q_EXPORT HINSTANCE qWinAppInst();
    75 //Q_EXPORT HINSTANCE qWinAppPrevInst();
    76 //Q_EXPORT int     qWinAppCmdShow();
    7782Q_EXPORT HPS       qt_display_ps();
    7883
  • trunk/src/kernel/qapplication_pm.cpp

    r52 r61  
    4343
    4444#include "qapplication.h"
    45 //@@TODO (dmik): need?
    46 //#if defined(QT_NON_COMMERCIAL)
    47 //#include "qnc_win.h"
    48 //#endif
    4945#include "private/qapplication_p.h"
    5046#include "qwidget.h"
     
    606602}
    607603
    608 //@@TODO (dmik): later (guess remove)
    609 //Q_EXPORT HINSTANCE qWinAppInst()              // get Windows app handle
    610 //{
    611 //    return appInst;
    612 //}
    613 //
    614 //Q_EXPORT HINSTANCE qWinAppPrevInst()          // get Windows prev app handle
    615 //{
    616 //    return appPrevInst;
    617 //}
    618 //
    619 //Q_EXPORT int qWinAppCmdShow()                 // get main window show command
    620 //{
    621 //    return appCmdShow;
    622 //}
    623 
    624604Q_EXPORT HPS qt_display_ps()                    // get display PS
    625605{
     
    10541034//    }
    10551035//    */
    1056 
    1057 //@@TODO (dmik): need?
    1058 //#if defined(QT_NON_COMMERCIAL)
    1059 //    QT_NC_WNDPROC
    1060 //#endif
    10611036
    10621037    if ( qt_pmEventFilter( &qmsg, rc ) )        // send through app filter
     
    13921367            bool window_state_change = FALSE;
    13931368            PSWP pswp = (PSWP) mp1;
    1394 //@@TODO (dmik): need?
    1395 //#if defined(QT_NON_COMMERCIAL)
    1396 //              QT_NC_SYSCOMMAND
    1397 //#endif
    13981369            if ( pswp->fl & SWP_MAXIMIZE ) {
    13991370                window_state_change = TRUE;
     
    14321403        }
    14331404
    1434 //@@TODO (dmik): remove, we processed these in the message above.
    1435 //@@TODO (dmik): what to do with QWhatsThis?..
    1436 //      case WM_SYSCOMMAND: {
    1437 //#ifndef Q_OS_TEMP
    1438 //          bool window_state_change = FALSE;
    1439 //          switch( wParam ) {
    1440 //          case SC_CONTEXTHELP:
    1441 //#ifndef QT_NO_WHATSTHIS
    1442 //              QWhatsThis::enterWhatsThisMode();
    1443 //#endif
    1444 //              QT_WA( {
    1445 //                  DefWindowProc( hwnd, WM_NCPAINT, 1, 0 );
    1446 //              } , {
    1447 //                  DefWindowProcA( hwnd, WM_NCPAINT, 1, 0 );
    1448 //              } );
    1449 //              break;
    1450 //#if defined(QT_NON_COMMERCIAL)
    1451 //              QT_NC_SYSCOMMAND
    1452 //#endif
    1453 //          case SC_MAXIMIZE:
    1454 //              window_state_change = TRUE;
    1455 //              widget->clearWState(Qt::WState_Minimized);
    1456 //              widget->setWState(Qt::WState_Maximized);
    1457 //              result = FALSE;
    1458 //              break;
    1459 //          case SC_MINIMIZE:
    1460 //              window_state_change = TRUE;
    1461 //              widget->setWState(Qt::WState_Minimized);
    1462 //              if ( widget->isVisible() ) {
    1463 //                  QHideEvent e;
    1464 //                  qt_sendSpontaneousEvent( widget, &e );
    1465 //                  widget->hideChildren( TRUE );
    1466 //              }
    1467 //              result = FALSE;
    1468 //              break;
    1469 //          case SC_RESTORE:
    1470 //              window_state_change = TRUE;
    1471 //              if (widget->isMinimized()) {
    1472 //                  widget->clearWState(Qt::WState_Minimized);
    1473 //                  widget->showChildren( TRUE );
    1474 //                  QShowEvent e;
    1475 //                  qt_sendSpontaneousEvent( widget, &e );
    1476 //              } else {
    1477 //                  widget->clearWState(Qt::WState_Maximized);
    1478 //              }
    1479 //              result = FALSE;
    1480 //              break;
    1481 //          default:
    1482 //              result = FALSE;
    1483 //              break;
    1484 //          }
    1485 //
    1486 //          if (window_state_change) {
    1487 //              QEvent e(QEvent::WindowStateChange);
    1488 //              qt_sendSpontaneousEvent(widget, &e);
    1489 //          }
    1490 //#endif
    1491 //
    1492 //          break;
    1493 //      }
    1494 
    1495 //@@TODO (dmik): later
     1405/// @todo (dmik) later
    14961406//      case WM_SETTINGCHANGE:
    14971407//          if ( !msg.wParam ) {
     
    15521462
    15531463        case WM_ACTIVATE:
    1554 //@@TODO (dmik): remove
    1555 //qDebug("WM_ACTIVATE: [%s] %d", widget->name(), SHORT1FROMMP(mp1) );
     1464#if 0
     1465            qDebug( "WM_ACTIVATE: [%s] %d", widget->name(), SHORT1FROMMP(mp1) );
     1466#endif           
    15561467            qApp->pmFocus( widget, SHORT1FROMMP(mp1) );
    15571468            break;
    15581469
    15591470        case WM_SETFOCUS:
    1560 //@@TODO (dmik): remove
    1561 //qDebug("WM_SETFOCUS: [%s] %s [%s]", widget->name(),
    1562 //        SHORT1FROMMP(mp2) ? "<=" : "=>",
    1563 //        QWidget::find( (HWND)mp1 ) ? QWidget::find( (HWND)mp1 )->name() : "{foreign}"
    1564 //);
     1471#if 0           
     1472            qDebug( "WM_SETFOCUS: [%s] %s [%s]", widget->name(),
     1473                    SHORT1FROMMP(mp2) ? "<=" : "=>",
     1474                    QWidget::find( (HWND)mp1 ) ? QWidget::find( (HWND)mp1 )->name()
     1475                                               : "{foreign}" );
     1476#endif           
    15651477            result = FALSE;
    15661478            if ( !SHORT1FROMMP(mp2) ) {
     
    15891501            break;
    15901502
    1591 //@@TODO (dmik): remove, handled in OS/2 version of WM_SETFOCUS above
    1592 //      case WM_ACTIVATE:
    1593 //          if ( QApplication::activePopupWidget() && LOWORD(wParam) == WA_INACTIVE &&
    1594 //              QWidget::find((HWND)lParam) == 0 ) {
    1595 //              // Another application was activated while our popups are open,
    1596 //              // then close all popups.  In case some popup refuses to close,
    1597 //              // we give up after 1024 attempts (to avoid an infinite loop).
    1598 //              int maxiter = 1024;
    1599 //              QWidget *popup;
    1600 //              while ( (popup=QApplication::activePopupWidget()) && maxiter-- )
    1601 //                  popup->close();
    1602 //          }
    1603 //          qApp->winFocus( widget, LOWORD(wParam) == WA_INACTIVE ? 0 : 1 );
    1604 //          break;
    1605 
    1606 //@@TODO (dmik): later
     1503/// @todo (dmik) remove?
    16071504//#ifndef Q_OS_TEMP
    16081505//          case WM_MOUSEACTIVATE:
     
    16231520            result = FALSE;
    16241521            break;
    1625 //@@TODO (dmik): remove later
     1522/// @todo (dmik) remove later
    16261523//          case WM_SHOWWINDOW:
    16271524//#ifndef Q_OS_TEMP
     
    16561553            RETURN(0);                          // always handled
    16571554
    1658 //@@TODO (dmik): it seems we don't need this
     1555/// @todo (dmik) it seems we don't need this
    16591556//      case WM_DESTROY:                        // destroy window
    16601557//          if ( hwnd == curWin ) {
     
    33643261#endif
    33653262
    3366     // convert region y coordinates from GPI to Qt (see qregion_pm.cpp)
    3367     POINTL ptl = { 0, -height() };
    3368     GpiOffsetRegion( hps, hrgn, &ptl );
    3369     // create a non-null region
    3370     QRegion rgn( FALSE );
    3371     // destructor will delete rgn
    3372     rgn.data->rgn = hrgn;
    3373 
    3374     QPaintEvent e(
    3375         rgn,
    3376         QRect( rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop ),
    3377         erase
    3378     );
     3263    // create a region that will take ownership of hrgn
     3264    QRegion rgn( hrgn, height() );
     3265
     3266    QPaintEvent e( rgn, QRect( rcl.xLeft, rcl.yBottom, rcl.xRight, rcl.yTop ),
     3267                   erase );
    33793268    QApplication::sendSpontaneousEvent( this, (QEvent*) &e );
    33803269
     
    34553344        }
    34563345        QPoint newCPos( swp.x, swp.y );
    3457 //@@TODO (dmik): should it apply to OS/2?
    3458 //      // Ignore silly Windows move event to wild pos after iconify.
    3459 //      if ( !isMinimized() && newCPos != oldPos ) {
    34603346        if ( newCPos != oldPos ) {
    34613347            cr.moveTopLeft( newCPos );
  • trunk/src/kernel/qcolor_pm.cpp

    r8 r61  
    248248
    249249/*! \internal */
    250 //@@TODO (dmik): this seems not to be used anywhere
     250/// @todo (dmik) this seems not to be used anywhere, remove?
    251251//uint QColor::realizePal( QWidget *widget )
    252252//{
  • trunk/src/kernel/qpaintdevice_pm.cpp

    r59 r61  
    536536    if ( td != QInternal::Pixmap ) {
    537537        if ( !dst_ps && td == QInternal::Widget ) {
    538             QWidget *dst_w = (QWidget*)dst;
    539             if ( dst_w->testWFlags(Qt::WPaintUnclipped) ) {
    540                 dst_ps = WinGetClipPS( dst_w->winId(), 0, PSF_PARENTCLIP );
    541             } else {
    542                 dst_ps = WinGetPS( dst_w->winId() );
    543             }
     538            dst_ps = ((QWidget*)dst)->getTargetPS();
    544539            dst_tmp = TRUE;
    545540        }
  • trunk/src/kernel/qpainter_pm.cpp

    r59 r61  
    4242#include "qpixmapcache.h"
    4343#include "qptrlist.h"
    44 //@@TODO (dmik): later
     44/// @todo (dmik) later
    4545//#include "qprinter.h"
    4646#include <stdlib.h>
     
    5353#include "qfontengine_p.h"
    5454
    55 //@@TODO (dmik): does OS/2 have this bug?
    56 ///*
    57 //  Workaround for win32 bug. When GM_ADVANCED graphicsmode is used with a non identity
    58 //  matrix, subsequent calls to Ellipse, Chord and Pie will be inclusive. Also after
    59 //  graphics mode is reset to GM_COMPATIBLE. This causes ellipses to grow in size
    60 //  after a call to drawText when the painter is transformated.
    61 //
    62 //  To work around this we register if a non identity transform is set in
    63 //  QPainter::nativeXForm() and reduce the size by one if native xform has been used.
    64 //
    65 //  Testcase for confirmation is checked in in:
    66 //  //depot/manualtests/platformbugs/win32/ellipseafteradvgrmode.cpp
    67 //*/
    68 
    6955// QRgb has the same RGB format (0xaarrggbb) as OS/2 uses (ignoring the
    7056// highest alpha byte) so we just mask alpha to get the valid OS/2 color.
    7157#define COLOR_VALUE(c) ((flags & RGBColor) ? (c.rgb() & RGB_MASK) : c.pixel())
    7258
    73 //@@TODO (dmik): Innotek GCC 3.2.2 beta 4 CSD1 lacks this function in
    74 //  its version of the toolkit header. This should be fixed soon.
     59// Innotek GCC lacks some API functions in its version of OS/2 Toolkit headers
    7560#if defined(Q_CC_GNU) && !defined(USE_OS2_TOOLKIT_HEADERS)
    7661extern "C" LONG  APIENTRY GpiQueryNearestPaletteIndex(HPAL hpal, ULONG color);
     
    10085    rc &= GpiSetAttrs( hps, PRIM_LINE, LBB_BACK_MIX_MODE, 0, (PBUNDLE) &lb );
    10186    return rc;
    102 }
    103 
    104 // helper function to select clip regions to the hps
    105 void qt_GpiSetClipRegion( HPS hps, HRGN hrgn, int devh, HRGN *hrgnOldRet )
    106 {
    107     if ( hrgn ) {
    108         // convert region y coordinates from Qt to GPI (see qregion_pm.cpp)
    109         if ( devh ) {
    110             POINTL ptl = { 0, devh };
    111             GpiOffsetRegion( hps, hrgn, &ptl );
    112         }
    113     }
    114     HRGN hrgnOld;
    115     GpiSetClipRegion( hps, hrgn, &hrgnOld );
    116     if ( hrgnOldRet )
    117         *hrgnOldRet = hrgnOld;
    118     else
    119         GpiDestroyRegion( hps, hrgnOld );
    12087}
    12188
     
    183150    }
    184151    if ( bg_pixmap ) {
    185 //@@TODO (dmik): don't realize why the windows code doesn't do it...
    186152        // normalize pixmap offsets according to x and y
    187153        // to ensure that the offsets are always relative to
     
    224190{
    225191    d = 0;
    226 //@@TODO (dmik): later
    227 //    hasUsedNativeXForm = FALSE;
    228 //    usingNativeXForm = FALSE;
    229192    flags = IsStartingUp;
    230193    pdev = 0;
     
    240203    wm_stack = 0;
    241204    hps = 0;
    242 //@@TODO (dmik): remove?
    243 //    hpen = 0;
    244 //    hbrush = 0;
    245 //    hfont = 0;
    246205    holdpal = 0;
    247     holdrgn = 0;
     206    holdrgn = HRGN_ERROR;
    248207    hbrushbm = 0;
    249208    pixmapBrush = nocolBrush = FALSE;
     
    407366    }
    408367
    409     //@@TODO (dmik): possibly pixmapBrush is not needed, hbrushbm and
     368    /// @todo (dmik) possibly pixmapBrush is not needed, hbrushbm and
    410369    //  CustomPattern can substitute it.
    411370    pixmapBrush = nocolBrush = FALSE;
     
    521480    hps = 0;
    522481    holdpal = 0;
    523     holdrgn = 0;
     482    holdrgn = HRGN_ERROR;
    524483    devh = 0;
    525484
    526     QRegion *pRepaintRgn = 0;
     485    QRegion *repaintRgn = 0;
    527486
    528487    if ( testf(ExtDev) ) {                      // external device
     
    574533        devh = wh;                              // for final y coord. flipping
    575534        if ( !w->isDesktop() )
    576             pRepaintRgn =                       // clip rgn passed from repaint()
     535            repaintRgn =                        // clip rgn passed from repaint()
    577536                (QRegion *) WinQueryWindowULong( w->winId(), QWL_QTCLIPRGN );
    578537        if ( w->testWState(Qt::WState_InPaintEvent) ) {
    579538            hps = w->hps;                       // during paint event
    580539        } else {
    581             if ( w->isDesktop() ) {
    582                 hps = WinGetScreenPS( HWND_DESKTOP );
    583             } else {
    584                 if ( unclipped || w->testWFlags( WPaintUnclipped ) ) {
    585                     hps = WinGetClipPS( w->winId(), 0, PSF_PARENTCLIP );
    586                 } else {
    587                     hps = WinGetPS( w->winId() );
    588                 }
    589             }
     540            hps = w->getTargetPS ( unclipped ? QWidget::Unclipped :
     541                                               QWidget::ClipAll );
    590542            w->hps = hps;
    591543        }
     
    608560            cpen.setColor( color1 );
    609561        }
    610 //@@TODO (dmik): later
     562/// @todo (dmik) later
    611563//    } else if ( dt == QInternal::Printer ) {  // device is a printer
    612564//      if ( pdev->handle() )
     
    634586        cpen = QPen( copyFrom->foregroundColor() );
    635587        bg_col = copyFrom->backgroundColor();
    636         pRepaintRgn =
     588        repaintRgn =
    637589            (QRegion *) WinQueryWindowULong( copyFrom->winId(), QWL_QTCLIPRGN );
    638590    }
     
    658610    setBrushOrigin( 0, 0 );
    659611    if ( hps ) {
    660         HRGN hrgn = 0;
    661         if ( pRepaintRgn ) {
    662             // make a shallow copy (for the case if the QWL_QTCLIPRGN pointer
    663             // will become invalid -- it should not ever happen though)
    664             repaintRgn = *pRepaintRgn;
    665             QRegion rgn = repaintRgn;
    666             // clip region in OS/2 cannot be used for anything else, make a deep copy
    667             rgn.detach();
    668             hrgn = rgn.handle();
    669             // prevent QRegion's destructor from destroying the region handle
    670             // (qt_GpiSetClipRegion does the job)
    671             rgn.data->rgn = 0;
     612        holdrgn = GpiQueryClipRegion( hps );
     613        if ( repaintRgn ) {
     614            // ensure that def_crgn is not null after assignment in any case
     615            def_crgn = repaintRgn->isNull() ? QRegion( FALSE ) : *repaintRgn;
    672616        }
    673         qt_GpiSetClipRegion( hps, hrgn, devh, &holdrgn );
     617        // clip region in GPI cannot be used for anything else, so detach it
     618        def_crgn.detach();
     619        if ( holdrgn ) {
     620            // intersect the original clip region and the region from repaint()
     621            if ( def_crgn.isNull() )
     622                def_crgn = QRegion( 0, 0, ww, wh );
     623            GpiSetClipRegion( hps, 0, NULL ); // deselect holdrgn
     624            HRGN hrgn = def_crgn.handle( devh );
     625            GpiCombineRegion( hps, hrgn, hrgn, holdrgn, CRGN_AND ); 
     626        }
     627        cur_crgn = def_crgn;
     628        if ( !cur_crgn.isNull() )
     629            GpiSetClipRegion( hps, cur_crgn.handle( devh ), NULL );
    674630    } else {
    675631        holdrgn = HRGN_ERROR;
     
    695651        GpiSetPatternSet( hps, LCID_DEFAULT );
    696652        GpiDeleteSetId( hps, LCID_QTPixmapBrush );
    697     }
    698 //@@TODO (dmik): remove or set the LCID_DEFAULT font here?
    699 //    if ( hfont ) {
    700 //      SelectObject( hdc, stock_sysfont );
    701 //      hfont = 0;
    702 //    }
    703     if ( holdrgn != HRGN_ERROR )
    704         qt_GpiSetClipRegion( hps, holdrgn, 0, NULL );
    705     if ( holdpal )
     653        hbrushbm = 0;
     654    }
     655    if ( holdrgn != HRGN_ERROR ) {
     656        GpiSetClipRegion( hps, holdrgn, NULL );
     657        holdrgn = HRGN_ERROR;
     658    }
     659    if ( holdpal ) {
    706660        GpiSelectPalette( hps, holdpal );
     661        holdpal = 0;
     662    }
    707663    if ( !pdev )
    708664        return FALSE;
     
    719675    }
    720676
     677    if ( !def_crgn.isNull() )
     678        def_crgn = QRegion();
     679    cur_crgn = def_crgn;
     680   
    721681    if ( pfont ) {
    722682        delete pfont;
     
    741701void QPainter::flush()
    742702{
    743 //@@TODO (dmik): need something here?
    744 //    GdiFlush();
    745703}
    746704
     
    945903    }
    946904
    947     HRGN hrgn = 0;
    948     QRegion rgn;
     905    // the current clip region is stored in cur_crgn, so deselect the handle
     906    // to let us operate on it. Note that the assignment op below will destroy
     907    // the handle if it is no more referred, so there is no need to do it
     908    // explicitly.
     909    GpiSetClipRegion( hps, 0, NULL );
    949910
    950911    if ( enable ) {
    951         if ( !repaintRgn.isNull() )
    952             rgn = crgn.intersect( repaintRgn );
     912        if ( !def_crgn.isNull() )
     913            cur_crgn = crgn.intersect( def_crgn );
    953914        else
    954             rgn = crgn;
     915            cur_crgn = crgn.isNull() ? QRegion( FALSE ) : crgn;
    955916#ifndef QT_NO_PRINTER
    956 //@@TODO (dmik): later
     917/// @todo (dmik) later
    957918//      if ( pdev->devType() == QInternal::Printer ) {
    958919//          double xscale = ((float)pdev->metric( QPaintDeviceMetrics::PdmPhysicalDpiX )) /
     
    971932#endif
    972933    } else {
    973         if ( !repaintRgn.isNull() )
    974             rgn = repaintRgn;
    975     }
    976 
    977     if ( !rgn.isNull() ) {
    978         // clip region in OS/2 cannot be used for anything else, make a deep copy
    979         rgn.detach();
    980         hrgn = rgn.handle();
    981         // prevent QRegion's destructor from destroying the region handle
    982         // (qt_GpiSetClipRegion does the job)
    983         rgn.data->rgn = 0;
    984     }
    985     qt_GpiSetClipRegion( hps, hrgn, devh, NULL );
     934        cur_crgn = def_crgn;
     935    }
     936
     937    // clip region in GPI cannot be used for anything else, so detach it
     938    cur_crgn.detach();
     939   
     940    if ( !cur_crgn.isNull() )
     941        GpiSetClipRegion( hps, cur_crgn.handle( devh ), NULL );
    986942}
    987943
     
    13151271        qt_end_geom_line( hps, &gh );
    13161272    }
    1317 //@@TODO (dmik): does OS/2 PM have the same bug?
    1318 //    if ( (cpen.width() == 0) && (cpen.style() == SolidLine) )
    1319 //      SetPixelV( hdc, x, y, COLOR_VALUE(cpen.color()) );
    13201273}
    13211274
     
    18241777#endif // QT_NO_BEZIER
    18251778
    1826 //@@TODO (dmik): remove?
    1827 //extern uint qt_bitblt_foreground;             // in qpaintdevice_pm.cpp
    1828 
    18291779void QPainter::drawPixmap( int x, int y, const QPixmap &pixmap,
    18301780                           int sx, int sy, int sw, int sh )
     
    18871837
    18881838    if ( txop <= TxTranslate ) {                // use optimized bitBlt
    1889 //@@TODO (dmik): remove?
    1890 //      if ( pixmap.depth() == 1 )
    1891 //          qt_bitblt_foreground = COLOR_VALUE(cpen.color());
    18921839        bitBlt( pdev, x, y, &pixmap, sx, sy, sw, sh, (RasterOp)rop );
    18931840        return;
     
    20041951    */
    20051952    QBitmap *mask = (QBitmap *)pixmap.mask();
    2006 //@@TODO (dmik): is OS/2 buggy too?
    2007 //#if 0 // Windows is too buggy, so we just use our own code (which is faster).
    20081953    if ( !testf(ExtDev) && txop <= TxTranslate && mask == 0 ) {
    20091954        if ( txop == TxTranslate )
     
    20121957        return;
    20131958    }
    2014 //#endif
    20151959    if ( sw*sh < 8192 && sw*sh < 16*w*h ) {
    20161960        int tw = sw, th = sh;
     
    20321976}
    20331977
    2034 //@@TODO (dmik): need this at all?
    20351978#if 0
    20361979//
     
    21572100        int ypos = y + si->y - ascent;
    21582101
    2159 //@@TODO (dmik): remove
    2160 //#ifndef Q_OS_TEMP
    2161 //      if ( rop != CopyROP ) {
    2162 //          // Doesn't work for non-TrueType fonts, but we dealt with those
    2163 //          // with the bitmap above.
    2164 //          BeginPath(hdc);
    2165 //      }
    2166 //#endif
    2167 
    2168 //@@TODO (dmik): do we really need this? we already have painter->handle()
     2102/// @todo (dmik) do we really need this? we already have painter->handle()
    21692103//  inside QFontEngine::draw(), and the font should have been selected into
    21702104//  hps by updateFont()
     
    21792113
    21802114        fe->draw( this, xpos, ypos, engine, si, textFlags );
    2181 //@@TODO (dmik): need?
     2115/// @todo (dmik) need?
    21822116//        fe->hps = oldPs;
    2183 
    2184 //@@TODO (dmik): remove
    2185 //      if ( rop != CopyROP ) {
    2186 //#ifndef Q_OS_TEMP
    2187 //          EndPath(hdc);
    2188 //#endif
    2189 //          uint pix = COLOR_VALUE(cpen.data->color);
    2190 //          HBRUSH tbrush = CreateSolidBrush( pix );
    2191 //          SelectObject( hdc, tbrush );
    2192 //#ifndef Q_OS_TEMP
    2193 //          FillPath(hdc);
    2194 //#endif
    2195 //          SelectObject( hdc, hbrush );
    2196 //          DeleteObject( tbrush );
    2197 //      }
    21982117    }
    21992118}
     
    22232142    y += si->y;
    22242143
    2225 //@@TODO (dmik): do we really need this? we already have painter->handle()
     2144/// @todo (dmik) do we really need this? we already have painter->handle()
    22262145//  inside QFontEngine::draw(), and the font should have been selected into
    22272146//  hps by updateFont()
     
    22312150
    22322151    fe->draw( this, x,  y, engine, si, textFlags );
    2233 //@@TODO (dmik): need?
     2152/// @todo (dmik) need?
    22342153//    fe->hps = oldPs;
    22352154}
  • trunk/src/kernel/qregion_pm.cpp

    r8 r61  
    4343#include "qt_os2.h"
    4444
    45 // We always create a GPI resuorce for a region with top and bottom corner
    46 // points made negative and swapped. This gives us no-cost top to bottom
    47 // flipping but requires to call GpiOffsetRegion() to offset the region up by
    48 // the height of the presentation space viewport before it is actually used on
    49 // that presentation space (usually for clipping) and, on the contrary, offset
    50 // the region got from GPI down before it is stored in QRegion.
     45//  To compensate the difference between Qt (where y axis goes downwards) and
     46//  GPI (where y axis goes upwards) coordinate spaces when dealing with regions
     47//  we use the following technique: when a GPI resource is allocated for a Qt
     48//  region, we simply change the sign of all y coordinates to quickly flip it
     49//  top to bottom in a manner that doesn't depend on the target device height.
     50//  All we have to do to apply the created GPI region to a particular GPI device
     51//  is to align its y axis to the top of the device (i.e. offset the region
     52//  up by the height of the device), and unalign it afterwards to bring it back
     53//  to the coordinate space of other device-independent (unaligned) regions.
     54//  To optimize this, we remember (in data->hgt) the last height value used to
     55//  align the region, and align it again only if the target device height
     56//  changes. Zero height indicates a device-independent target (such as other
     57//  unaligned Qt region).
     58//
     59//  The handle() function, used for external access to the region, takes an
     60//  argument that must be always set to the height of the target device to
     61//  guarantee the correct coordinate space alignment.
     62
     63#if defined(Q_CC_GNU) && !defined(USE_OS2_TOOLKIT_HEADERS)
     64
     65// Innotek GCC lacks some API functions in its version of OS/2 Toolkit headers
     66
     67extern "C" HRGN APIENTRY GpiCreateEllipticRegion( HPS hps,
     68                                                  PRECTL prclRect );
     69
     70extern "C" HRGN APIENTRY GpiCreatePolygonRegion( HPS hps,
     71                                                 ULONG ulCount,
     72                                                 PPOLYGON paplgn,
     73                                                 ULONG flOptions );
     74#endif
    5175
    5276QRegion::QRegion()
     
    5579    Q_CHECK_PTR( data );
    5680    data->rgn = 0;
     81    data->hgt = 0;
    5782    data->is_null = TRUE;
    5883}
     
    6388    Q_CHECK_PTR( data );
    6489    data->rgn = 0;
     90    data->hgt = 0;
    6591    data->is_null = is_null;
    6692}
    6793
    68 QRegion::QRegion( const QRect &r, RegionType t )
     94QRegion::QRegion( HRGN hrgn, int target_height )
    6995{
    7096    data = new QRegionData;
    7197    Q_CHECK_PTR( data );
     98    data->rgn = hrgn;
     99    data->hgt = target_height;
     100    data->is_null = FALSE;
     101}
     102
     103QRegion::QRegion( const QRect &r, RegionType t )
     104{
     105    data = new QRegionData;
     106    Q_CHECK_PTR( data );
     107    data->hgt = 0;
    72108    data->is_null = FALSE;
    73109    if ( r.isEmpty() ) {
     
    79115            data->rgn = GpiCreateRegion( hps, 1, &rcl );
    80116        } else if ( t == Ellipse ) {            // elliptic region
    81 //@@TODO (dmik): create elliptic regions using GpiCreateEllipticRegion() later.
    82 //  now simply create it as rectangular.
    83             RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
    84             data->rgn = GpiCreateRegion( hps, 1, &rcl );
     117            // if the width or height of the ellipse is odd, GPI always
     118            // converts it to a nearest even value, which is obviously stupid
     119            // (see also QPainter::drawArcInternal()). So, we don't use
     120            // GpiCreateEllipticRegion(), but create an array of points to
     121            // call GpiCreatePolygonRegion() instead.
     122            QPointArray a;
     123            a.makeArc( r.x(), r.y(), r.width(), r.height(), 0, 360 * 16 );
     124            for ( uint i = 0; i < a.size(); ++ i )
     125                a[i].ry() = -(a[i].y() + 1);
     126            // GpiCreatePolygonRegion() is bogus and always starts a poligon from
     127            // the current position. Make the last point the current one and reduce
     128            // the number of points by one.
     129            GpiMove( hps, (PPOINTL) &a[ a.size() - 1 ] );
     130            POLYGON poly = { a.size() - 1, (PPOINTL) a.data() };
     131            data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, POLYGON_ALTERNATE );
    85132        }
    86133    }
     
    91138    data = new QRegionData;
    92139    Q_CHECK_PTR( data );
     140    data->hgt = 0;
    93141    data->is_null = FALSE;
    94142    QRect r = a.boundingRect();
     
    96144        data->rgn = 0;
    97145    } else {
    98 //@@TODO (dmik): create poligonal regions using GpiCreatePolygonRegion() later.
    99 //  now simply create as bounding rectangle.
    100         RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
    101         data->rgn = GpiCreateRegion( qt_display_ps(), 1, &rcl );
     146        HPS hps = qt_display_ps();
     147        POINTL *pts = new POINTL[ a.size() ];
     148        for ( uint i = 0; i < a.size(); ++ i ) {
     149            pts[i].x = a[i].x();
     150            pts[i].y = - (a[i].y() + 1);
     151        }
     152        // GpiCreatePolygonRegion() is bogus and always starts a poligon from
     153        // the current position. Make the last point the current one and reduce
     154        // the number of points by one.
     155        GpiMove( hps, &pts[ a.size() - 1 ] );
     156        POLYGON poly = { a.size() - 1, pts };
     157        ULONG opts = winding ? POLYGON_WINDING : POLYGON_ALTERNATE;
     158        data->rgn = GpiCreatePolygonRegion( hps, 1, &poly, opts );
     159        delete[] pts;
    102160    }
    103161}
     
    192250    data = new QRegionData;
    193251    Q_CHECK_PTR( data );
     252    data->hgt = 0;
    194253    data->is_null = FALSE;
    195254    if ( bm.isNull() )
     
    225284{
    226285    QRegion r ( data->is_null );
     286    r.data->hgt = 0;
    227287    if ( !data->is_null && data->rgn ) {
    228288        HPS hps = qt_display_ps();
    229289        r.data->rgn = GpiCreateRegion( hps, 0, NULL );
    230290        GpiCombineRegion( hps, r.data->rgn, data->rgn, NULL, CRGN_COPY );
     291        r.data->hgt = data->hgt;
    231292    }
    232293    return r;
     
    252313    LONG rc = PRGN_OUTSIDE;
    253314    if ( data->rgn ) {
    254         POINTL ptl = { p.x(), -(p.y()+1) };
     315        POINTL ptl = { p.x(), data->hgt - (p.y() + 1) };
    255316        rc = GpiPtInRegion( qt_display_ps(), data->rgn, &ptl );
    256317    }
     
    262323    LONG rc = PRGN_OUTSIDE;
    263324    if ( data->rgn ) {
    264         RECTL rcl = { r.left(), -(r.bottom()+1), r.right()+1, -r.top() };
     325        RECTL rcl = { r.left(), data->hgt - (r.bottom() + 1),
     326                      r.right() + 1, data->hgt - r.top() };
    265327        rc = GpiRectInRegion( qt_display_ps(), data->rgn, &rcl );
    266328    }
     
    318380    HPS hps = qt_display_ps();
    319381    result.data->rgn = GpiCreateRegion( hps, 0, NULL );
    320     if ( data->rgn && r.data->rgn )
    321         GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both );
    322     else if ( data->rgn && left != CRGN_NOP )
    323         GpiCombineRegion( hps, result.data->rgn, data->rgn, NULL, left );
    324     else if ( r.data->rgn && right != CRGN_NOP )
    325         GpiCombineRegion( hps, result.data->rgn, r.data->rgn, NULL, right );
     382    LONG rc = RGN_NULL;
     383    if ( data->rgn && r.data->rgn ) {
     384        updateHandle( r.data->hgt ); // bring to the same coordinate space
     385        rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, r.data->rgn, both );
     386        result.data->hgt = r.data->hgt;
     387    } else if ( data->rgn && left != CRGN_NOP ) {
     388        rc = GpiCombineRegion( hps, result.data->rgn, data->rgn, 0, left );
     389        result.data->hgt = data->hgt;
     390    } else if ( r.data->rgn && right != CRGN_NOP ) {
     391        rc = GpiCombineRegion( hps, result.data->rgn, r.data->rgn, 0, right );
     392        result.data->hgt = r.data->hgt;
     393    }
     394    if ( rc == RGN_NULL || rc == RGN_ERROR ) {
     395        GpiDestroyRegion( hps, result.data->rgn );
     396        result.data->rgn = result.data->hgt = 0;
     397    }
    326398    return result;
    327399}
     
    354426    if ( data->rgn )
    355427        rc = GpiQueryRegionBox( qt_display_ps(), data->rgn, &rcl );
    356     if ( rc == RGN_NULL )
     428    if ( rc == RGN_NULL || rc == RGN_ERROR )
    357429        return QRect(0,0,0,0);
    358430    else
    359         return QRect(rcl.xLeft, -rcl.yTop, rcl.xRight-rcl.xLeft, rcl.yTop-rcl.yBottom );
     431        return QRect( rcl.xLeft, data->hgt - rcl.yTop,
     432                      rcl.xRight - rcl.xLeft, rcl.yTop - rcl.yBottom );
    360433}
    361434
     
    382455    PRECTL r = rcls;
    383456    for ( int i=0; i<(int)a.size(); i++ ) {
    384         a[i].setRect( r->xLeft, -r->yTop, r->xRight-r->xLeft, r->yTop-r->yBottom );
     457        a[i].setRect( r->xLeft, data->hgt - r->yTop,
     458                      r->xRight - r->xLeft, r->yTop - r->yBottom );
    385459        r++;
    386460    }
     
    407481    if ( (is_empty ^ r_is_empty ) )             // one is empty, not both
    408482        return FALSE;
    409     return is_empty ?
    410         TRUE :                                  // both empty
    411         GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL;
    412 }
    413 
    414 void QRegion::update() const
    415 {
    416     // lazy initialization. this method should be called only from handle()
    417     data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL );
    418 }
     483    if ( is_empty )                             // both empty
     484        return TRUE;
     485    updateHandle( r.data->hgt ); // bring to the same coordinate space
     486    return
     487        GpiEqualRegion( qt_display_ps(), data->rgn, r.data->rgn ) == EQRGN_EQUAL;
     488}
     489
     490/*!
     491 *  \internal
     492 *  Updates the region handle so that it is suitable for selection to
     493 *  a device with the given \a height.
     494 */
     495void QRegion::updateHandle( int target_height ) const
     496{
     497    QRegion *that = const_cast< QRegion *>( this ); // we're const here
     498    if ( !data->rgn ) {
     499        // a handle of a null region is requested, allocate an empty region
     500        that->data->rgn = GpiCreateRegion( qt_display_ps(), 0, NULL );
     501        that->data->hgt = target_height;
     502    } else if ( data->hgt != target_height ) {
     503        // align region y axis to the top of the device
     504        POINTL ptl = { 0, target_height - data->hgt };
     505        GpiOffsetRegion( qt_display_ps(), data->rgn, &ptl );
     506        that->data->hgt = target_height;
     507    }
     508}
  • trunk/src/kernel/qwidget_pm.cpp

    r57 r61  
    973973        WinValidateRect( winId(), &rcl, FALSE );
    974974
    975         QRegion *pcrgn = 0;
     975        Q_ASSERT( !WinQueryWindowULong( winId(), QWL_QTCLIPRGN ) );
     976        QRegion reg;
    976977        if ( r != rect() ) {
    977             pcrgn = new QRegion( r );
    978             WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) pcrgn );
     978            reg = QRegion( r );
     979            WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) &reg );
    979980        }
    980981
     
    984985        QApplication::sendEvent( this, &e );
    985986
    986         if ( pcrgn ) {
    987             WinSetWindowULong( winId(), QWL_QTCLIPRGN, 0 );
    988             delete pcrgn;
    989         }
     987        WinSetWindowULong( winId(), QWL_QTCLIPRGN, 0 );
    990988    }
    991989}
     
    1000998#endif
    1001999        // convert region y coordinates from Qt to GPI (see qregion_pm.cpp)
    1002         POINTL ptl = { 0, height() };
    1003         GpiOffsetRegion( qt_display_ps(), reg.handle(), &ptl );
    1004         WinValidateRegion( winId(), reg.handle(), FALSE );
    1005         // convert region y coordinates back from GPI to Qt
    1006         ptl.y = -ptl.y;
    1007         GpiOffsetRegion( qt_display_ps(), reg.handle(), &ptl );
    1008 
    1009         QRegion *pcrgn = new QRegion( reg );
    1010         WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) pcrgn );
     1000        WinValidateRegion( winId(), reg.handle( height() ), FALSE );
     1001
     1002        Q_ASSERT( !WinQueryWindowULong( winId(), QWL_QTCLIPRGN ) );
     1003        WinSetWindowULong( winId(), QWL_QTCLIPRGN, (ULONG) &reg );
    10111004
    10121005        QPaintEvent e( reg, erase );
     
    10161009
    10171010        WinSetWindowULong( winId(), QWL_QTCLIPRGN, 0 );
    1018         delete pcrgn;
    10191011    }
    10201012}
     
    14131405    } else if ( !hps ) {
    14141406        tmphps = TRUE;
    1415         lhps = WinGetPS( winId() );
     1407        lhps = getTargetPS();
    14161408    } else {
    14171409        tmphps = FALSE;
     
    14281420    );
    14291421
    1430     if ( tmphps ) {
     1422    if ( tmphps )
    14311423        WinReleasePS( lhps );
    1432         hps = 0;
    1433     }
    14341424}
    14351425
     
    14501440    } else if ( !hps ) {
    14511441        tmphps = TRUE;
    1452         lhps = WinGetPS( winId() );
     1442        lhps = getTargetPS();
    14531443    } else {
    14541444        tmphps = FALSE;
    14551445        lhps = hps;
    14561446    }
    1457 
    1458     // convert region y coordinates from Qt to GPI (see qregion_pm.cpp)
    1459     POINTL ptl = { 0, height() };
    1460     GpiOffsetRegion( lhps, rgn.handle(), &ptl );
    14611447
    14621448    HRGN oldRegion = GpiQueryClipRegion( lhps );
     
    14651451        GpiSetClipRegion( lhps, 0, NULL );
    14661452        newRegion = GpiCreateRegion( lhps, 0, NULL );
    1467         GpiCombineRegion( lhps, newRegion, oldRegion, rgn.handle(), CRGN_AND );
     1453        GpiCombineRegion( lhps, newRegion, oldRegion, rgn.handle( height() ),
     1454                          CRGN_AND );
    14681455    } else {
    1469         newRegion = rgn.handle();
     1456        newRegion = rgn.handle( height() );
    14701457    }
    14711458    GpiSetClipRegion( lhps, newRegion, &oldRegion );
     
    14821469    GpiSetClipRegion( lhps, oldRegion, NULL );
    14831470
    1484     // convert region y coordinates back from GPI to Qt
    1485     ptl.y = -ptl.y;
    1486     GpiOffsetRegion( lhps, rgn.handle(), &ptl );
    1487 
    14881471    if ( oldRegion )
    14891472        GpiDestroyRegion( lhps, newRegion );
    1490     if ( tmphps ) {
     1473    if ( tmphps )
    14911474        WinReleasePS( lhps );
    1492         hps = 0;
    1493     }
    14941475}
    14951476
     
    18821863}
    18831864
     1865/*!
     1866 *  \internal
     1867 *
     1868 *  Obtains a presentaiton space to draw on this widget, set up according
     1869 *  to widget flags. If \a m != Unclipped and WPaintUnclipped flag is not
     1870 *  set, a clip region is set on the returned PS according to \a m.
     1871 *
     1872 *  The returned handle must be freed using WinReleasePS() after usage.
     1873 */
     1874HPS QWidget::getTargetPS( ClipMode m /* = ClipAll */ )
     1875{
     1876    HPS widgetPS = 0;
     1877   
     1878    if ( isDesktop() ) {
     1879        widgetPS = WinGetScreenPS( HWND_DESKTOP );
     1880    } else {
     1881        if ( m == Unclipped || testWFlags( WPaintUnclipped ) ) {
     1882            widgetPS = WinGetClipPS( winId(), 0, PSF_PARENTCLIP );
     1883        } else {
     1884            widgetPS = WinGetPS( winId() );
     1885        }
     1886    }
     1887
     1888    return widgetPS;
     1889}
     1890
Note: See TracChangeset for help on using the changeset viewer.