xref: /trunk/main/vcl/os2/source/gdi/salgdi2.cxx (revision cdf0e10c4e3984b49a9502b011690b615761d4a3)
1 /*************************************************************************
2  *
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * Copyright 2000, 2010 Oracle and/or its affiliates.
6  *
7  * OpenOffice.org - a multi-platform office productivity suite
8  *
9  * This file is part of OpenOffice.org.
10  *
11  * OpenOffice.org is free software: you can redistribute it and/or modify
12  * it under the terms of the GNU Lesser General Public License version 3
13  * only, as published by the Free Software Foundation.
14  *
15  * OpenOffice.org is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU Lesser General Public License version 3 for more details
19  * (a copy is included in the LICENSE file that accompanied this code).
20  *
21  * You should have received a copy of the GNU Lesser General Public License
22  * version 3 along with OpenOffice.org.  If not, see
23  * <http://www.openoffice.org/license.html>
24  * for a copy of the LGPLv3 License.
25  *
26  ************************************************************************/
27 
28 #include <string.h>
29 #include <svpm.h>
30 
31 #define _SV_SALGDI2_CXX
32 #include <salbmp.h>
33 #include <saldata.hxx>
34 #ifndef _SV_SALIDS_HRC
35 #include <salids.hrc>
36 #endif
37 #include <salgdi.h>
38 #include <salvd.h>
39 #include <vcl/salbtype.hxx>
40 
41 #ifndef __H_FT2LIB
42 #include <wingdi.h>
43 #include <ft2lib.h>
44 #endif
45 
46 BOOL bFastTransparent = FALSE;
47 
48 // -----------
49 // - Defines -
50 // -----------
51 
52 #define RGBCOLOR( r, g, b ) ((ULONG)(((BYTE)(b)|((USHORT)(g)<<8))|(((ULONG)(BYTE)(r))<<16)))
53 #define TY( y )             (mnHeight-(y)-1)
54 
55 // ---------------
56 // - SalGraphics -
57 // ---------------
58 
59 bool Os2SalGraphics::supportsOperation( OutDevSupportType ) const
60 {
61     return false;
62 }
63 
64 
65 void Os2SalGraphics::copyBits( const SalTwoRect* pPosAry, SalGraphics* pSrcGraphics )
66 {
67     HPS     hSrcPS;
68     POINTL  thePoints[4];
69     long    nSrcHeight;
70 
71     if ( pSrcGraphics )
72     {
73         //hSrcPS = pSrcGraphics->mhPS;
74         //nSrcHeight = pSrcGraphics->mnHeight;
75         hSrcPS = static_cast<Os2SalGraphics*>(pSrcGraphics)->mhPS;
76         nSrcHeight = static_cast<Os2SalGraphics*>(pSrcGraphics)->mnHeight;
77     }
78     else
79     {
80         hSrcPS = mhPS;
81         nSrcHeight = mnHeight;
82     }
83 
84     // lower-left corner of target
85     thePoints[0].x = pPosAry->mnDestX;
86     thePoints[0].y = TY( pPosAry->mnDestY + pPosAry->mnDestHeight - 1 );
87 
88     // upper-right corner of target
89     thePoints[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth;
90     thePoints[1].y = TY( pPosAry->mnDestY - 1 );
91 
92     // lower-left corner of source
93     thePoints[2].x = pPosAry->mnSrcX;
94     thePoints[2].y = nSrcHeight - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight );
95 
96     if ( ( pPosAry->mnDestWidth != pPosAry->mnSrcWidth ) || ( pPosAry->mnDestHeight != pPosAry->mnSrcHeight ) )
97     {
98         // upper-right corner of Source
99         thePoints[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth;
100         thePoints[3].y = nSrcHeight - pPosAry->mnSrcY + pPosAry->mnSrcHeight;
101 
102         GpiBitBlt( mhPS, hSrcPS, 4, thePoints,
103                    mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE );
104     }
105     else
106     {
107         GpiBitBlt( mhPS, hSrcPS, 3, thePoints,
108                    mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE );
109     }
110 }
111 
112 // -----------------------------------------------------------------------
113 
114 void Os2SalGraphics::copyArea( long nDestX, long nDestY,
115                             long nSrcX, long nSrcY,
116                             long nSrcWidth, long nSrcHeight,
117                             USHORT nFlags )
118 {
119     POINTL thePoints[3];
120 
121     // lower-left corner of target
122     thePoints[0].x = nDestX;
123     thePoints[0].y = TY( nDestY + nSrcHeight - 1 );
124 
125     // upper-right corner of target
126     thePoints[1].x = nDestX + nSrcWidth;
127     thePoints[1].y = TY( nDestY - 1 );
128 
129     // lower-left corner of source
130     thePoints[2].x = nSrcX;
131     thePoints[2].y = TY( nSrcY + nSrcHeight - 1);
132 
133     if ( (nFlags & SAL_COPYAREA_WINDOWINVALIDATE) && mbWindow )
134     {
135         // Overlap-Bereich berechnen und invalidieren
136         Point       aVCLSrcPos( nSrcX, nSrcY );
137         Size        aVCLSrcSize( nSrcWidth, nSrcHeight );
138         Rectangle   aVCLSrcRect( aVCLSrcPos, aVCLSrcSize );
139         Rectangle   aVCLClipRect;
140         SWP         aSWP;
141 
142         WinQueryWindowPos( mhWnd, &aSWP );
143         aVCLClipRect.Right()    = aSWP.cx-1;
144         aVCLClipRect.Bottom()   = aSWP.cy-1;
145         if ( !aVCLSrcRect.Intersection( aVCLClipRect ).IsEmpty() )
146         {
147             RECTL   aSrcRect;
148             RECTL   aTempRect;
149             HRGN    hInvalidateRgn;
150             HRGN    hTempRgn;
151             HWND    hWnd;
152             long    nRgnType;
153 
154             long nVCLScrHeight  = aVCLSrcRect.GetHeight();
155             aSrcRect.xLeft      = aVCLSrcRect.Left();
156             aSrcRect.yBottom    = TY( aVCLSrcRect.Top()+nVCLScrHeight-1 );
157             aSrcRect.xRight     = aSrcRect.xLeft+aVCLSrcRect.GetWidth();
158             aSrcRect.yTop       = aSrcRect.yBottom+nVCLScrHeight;
159 
160             // Rechteck in Screen-Koordinaaten umrechnen
161             POINTL  aPt;
162             long    nScreenDX = WinQuerySysValue( HWND_DESKTOP, SV_CXSCREEN );
163             long    nScreenDY = WinQuerySysValue( HWND_DESKTOP, SV_CYSCREEN );
164             aPt.x = 0;
165             aPt.y = 0;
166             WinMapWindowPoints( mhWnd, HWND_DESKTOP, &aPt, 1 );
167             aSrcRect.xLeft   += aPt.x;
168             aSrcRect.yTop    += aPt.y;
169             aSrcRect.xRight  += aPt.x;
170             aSrcRect.yBottom += aPt.y;
171             hInvalidateRgn = 0;
172             // Bereiche ausserhalb des sichtbaren Bereiches berechnen
173             if ( aSrcRect.xLeft < 0 )
174             {
175                 if ( !hInvalidateRgn )
176                     hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
177                 aTempRect.xLeft     = -31999;
178                 aTempRect.yBottom   = 0;
179                 aTempRect.xRight    = 0;
180                 aTempRect.yTop      = 31999;
181                 hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
182                 GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
183                 GpiDestroyRegion( mhPS, hTempRgn );
184             }
185             if ( aSrcRect.yBottom < 0 )
186             {
187                 if ( !hInvalidateRgn )
188                     hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
189                 aTempRect.xLeft     = 0;
190                 aTempRect.yBottom   = -31999;
191                 aTempRect.xRight    = 31999;
192                 aTempRect.yTop      = 0;
193                 hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
194                 GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
195                 GpiDestroyRegion( mhPS, hTempRgn );
196             }
197             if ( aSrcRect.xRight > nScreenDX )
198             {
199                 if ( !hInvalidateRgn )
200                     hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
201                 aTempRect.xLeft     = nScreenDX;
202                 aTempRect.yBottom   = 0;
203                 aTempRect.xRight    = 31999;
204                 aTempRect.yTop      = 31999;
205                 hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
206                 GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
207                 GpiDestroyRegion( mhPS, hTempRgn );
208             }
209             if ( aSrcRect.yTop > nScreenDY )
210             {
211                 if ( !hInvalidateRgn )
212                     hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
213                 aTempRect.xLeft     = 0;
214                 aTempRect.yBottom   = nScreenDY;
215                 aTempRect.xRight    = 31999;
216                 aTempRect.yTop      = 31999;
217                 hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
218                 GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
219                 GpiDestroyRegion( mhPS, hTempRgn );
220             }
221 
222             // Bereiche die von anderen Fenstern ueberlagert werden berechnen
223             // Calculate areas that are overlapped by other windows
224             HWND hWndParent = WinQueryWindow( mhWnd, QW_PARENT );
225             hWnd = WinQueryWindow( HWND_DESKTOP, QW_TOP );
226             aVCLSrcRect = Rectangle( aSrcRect.xLeft, aSrcRect.yBottom, aSrcRect.xRight, aSrcRect.yTop );
227             while ( hWnd )
228             {
229                 if ( hWnd == hWndParent )
230                     break;
231                 if ( WinIsWindowVisible( hWnd ) )
232                 {
233                     WinQueryWindowPos( hWnd, &aSWP );
234                     if ( !(aSWP.fl & SWP_MINIMIZE) )
235                     {
236                         aVCLClipRect = Rectangle( Point( aSWP.x, aSWP.y ), Size( aSWP.cx, aSWP.cy ) );
237                         if ( aVCLSrcRect.IsOver( aVCLClipRect ) )
238                         {
239                             if ( !hInvalidateRgn )
240                                 hInvalidateRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
241                             aTempRect.xLeft     = aSWP.x;
242                             aTempRect.yBottom   = aSWP.y;
243                             aTempRect.xRight    = aTempRect.xLeft+aSWP.cx;
244                             aTempRect.yTop      = aTempRect.yBottom+aSWP.cy;
245                             hTempRgn = GpiCreateRegion( mhPS, 1, &aTempRect );
246                             GpiCombineRegion( mhPS, hInvalidateRgn, hInvalidateRgn, hTempRgn, CRGN_DIFF );
247                             GpiDestroyRegion( mhPS, hTempRgn );
248                         }
249                     }
250                 }
251                 hWnd = WinQueryWindow( hWnd, QW_NEXT );
252             }
253 
254             if ( hInvalidateRgn )
255             {
256                 hTempRgn = GpiCreateRegion( mhPS, 1, &aSrcRect );
257                 nRgnType = GpiCombineRegion( mhPS, hInvalidateRgn, hTempRgn, hInvalidateRgn, CRGN_DIFF );
258                 GpiDestroyRegion( mhPS, hTempRgn );
259                 if ( (nRgnType != RGN_ERROR) && (nRgnType != RGN_NULL) )
260                 {
261                     long nOffX = (nDestX-nSrcX);
262                     long nOffY = (nSrcY-nDestY);
263                     aPt.x = nOffX-aPt.x;
264                     aPt.y = nOffY-aPt.y;
265                     GpiOffsetRegion( mhPS, hInvalidateRgn, &aPt );
266                     WinInvalidateRegion( mhWnd, hInvalidateRgn, TRUE );
267                     // Hier loesen wir nur ein Update aus, wenn es der
268                     // MainThread ist, damit es beim Bearbeiten der
269                     // Paint-Message keinen Deadlock gibt, da der
270                     // SolarMutex durch diesen Thread schon gelockt ist
271                     SalData*    pSalData = GetSalData();
272                     ULONG       nCurThreadId = GetCurrentThreadId();
273                     if ( pSalData->mnAppThreadId == nCurThreadId )
274                         WinUpdateWindow( mhWnd );
275                 }
276                 GpiDestroyRegion( mhPS, hInvalidateRgn );
277             }
278         }
279     }
280 
281     GpiBitBlt( mhPS, mhPS, 3, thePoints,
282                ROP_SRCCOPY, BBO_IGNORE );
283 
284 }
285 
286 // -----------------------------------------------------------------------
287 
288 void ImplDrawBitmap( HPS hPS, long nScreenHeight,
289                      const SalTwoRect* pPosAry, const Os2SalBitmap& rSalBitmap,
290                      BOOL bPrinter, int nDrawMode )
291 {
292     if( hPS )
293     {
294         HANDLE      hDrawDIB;
295         HBITMAP     hDrawDDB = rSalBitmap.ImplGethDDB();
296         Os2SalBitmap*   pTmpSalBmp = NULL;
297         BOOL        bPrintDDB = ( bPrinter && hDrawDDB );
298         BOOL        bDrawDDB1 = ( ( rSalBitmap.GetBitCount() == 1 ) && hDrawDDB );
299 
300         if( bPrintDDB || bDrawDDB1 )
301         {
302             pTmpSalBmp = new Os2SalBitmap;
303             pTmpSalBmp->Create( rSalBitmap, rSalBitmap.GetBitCount() );
304             hDrawDIB = pTmpSalBmp->ImplGethDIB();
305         }
306         else
307             hDrawDIB = rSalBitmap.ImplGethDIB();
308 
309         if( hDrawDIB )
310         {
311             HANDLE              hSubst = rSalBitmap.ImplGethDIB1Subst();
312             POINTL              pts[ 4 ];
313             BITMAPINFO2*        pBI = (BITMAPINFO2*) hDrawDIB;
314             BITMAPINFOHEADER2*  pBIH = (BITMAPINFOHEADER2*) pBI;
315             const long          nHeight = pBIH->cy;
316             long                nInfoSize = *(ULONG*) pBI + rSalBitmap.ImplGetDIBColorCount( hDrawDIB ) * sizeof( RGB2 );
317             BYTE*               pBits = (BYTE*) pBI + nInfoSize;
318 
319             pts[0].x = pPosAry->mnDestX;
320             pts[0].y = nScreenHeight - pPosAry->mnDestY - pPosAry->mnDestHeight;
321             pts[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth - 1;
322             pts[1].y = nScreenHeight - pPosAry->mnDestY - 1;
323 
324             pts[2].x = pPosAry->mnSrcX;
325             pts[2].y = nHeight - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight );
326             pts[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth;
327             pts[3].y = nHeight - pPosAry->mnSrcY;
328 
329             // if we've got a 1Bit DIB, we create a 4Bit substitute
330             if( ( pBIH->cBitCount == 1 ) && !hSubst )
331             {
332                 // create 4Bit substitute
333                 hSubst = Os2SalBitmap::ImplCreateDIB4FromDIB1( hDrawDIB );
334 
335                 // replace substitute only, if it is no temporary SalBitmap
336                 if( !( bPrintDDB || bDrawDDB1 ) )
337                     ( (Os2SalBitmap&) rSalBitmap ).ImplReplacehDIB1Subst( hSubst );
338             }
339 
340             if( hSubst )
341             {
342                 pBI = (BITMAPINFO2*) hSubst;
343                 pBIH = (BITMAPINFOHEADER2*) pBI;
344                 nInfoSize = *(ULONG*) pBI + rSalBitmap.ImplGetDIBColorCount( hSubst ) * sizeof( RGB2 );
345                 pBits = (BYTE*) pBI + nInfoSize;
346             }
347 
348             if( bPrinter )
349             {
350                 BYTE* pDummy;
351 
352                 // expand 8Bit-DIB's to 24Bit-DIB's, because some printer drivers
353                 // have problems to print these DIB's (strange)
354                 if( pBIH->cBitCount == 8 && pBIH->ulCompression == BCA_UNCOMP )
355                 {
356                     const long          nWidth = pBIH->cx;
357                     const long          nHeight = pBIH->cy;
358                     const long          nWidthAl8 = AlignedWidth4Bytes( nWidth * 8 );
359                     const long          nWidthAl24 = AlignedWidth4Bytes( nWidth * 24 );
360                     const long          nNewImageSize = nHeight * nWidthAl24;
361                     BITMAPINFOHEADER2*  pNewInfo;
362 
363                     pDummy = new BYTE[ sizeof( BITMAPINFO2 ) + nNewImageSize ];
364                     memset( pDummy, 0, sizeof( BITMAPINFO2 ) );
365 
366                     pNewInfo = (BITMAPINFOHEADER2*) pDummy;
367                     pNewInfo->cbFix = sizeof( BITMAPINFOHEADER2 );
368                     pNewInfo->cx = nWidth;
369                     pNewInfo->cy = nHeight;
370                     pNewInfo->cPlanes = 1;
371                     pNewInfo->cBitCount = 24;
372                     pNewInfo->ulCompression = BCA_UNCOMP;
373                     pNewInfo->cbImage = nNewImageSize;
374 
375                     BYTE* pBitsSrc = (BYTE*) pBIH + nInfoSize;
376                     BYTE* pBitsDst = pDummy + sizeof( BITMAPINFO2 );
377 
378                     for( long nY = 0UL; nY < nHeight; nY++ )
379                     {
380                         BYTE* pSrcLine = pBitsSrc + nY * nWidthAl8;
381                         BYTE* pDstLine = pBitsDst + nY * nWidthAl24;
382 
383                         for( long nX = 0UL; nX < nWidth; nX++ )
384                         {
385                             const RGB2& rQuad = pBI->argbColor[ *pSrcLine++ ];
386 
387                             *pDstLine++ = rQuad.bBlue;
388                             *pDstLine++ = rQuad.bGreen;
389                             *pDstLine++ = rQuad.bRed;
390                         }
391                     }
392 
393                     nInfoSize = sizeof( BITMAPINFO2 );
394                 }
395                 else
396                 {
397                     const long nImageSize = ( pBIH->cbImage ? pBIH->cbImage : ( pBIH->cy * AlignedWidth4Bytes( pBIH->cx * pBIH->cBitCount ) ) );
398                     const long nTotalSize = nInfoSize + nImageSize;
399 
400                     pDummy = new BYTE[ nTotalSize ];
401                     memcpy( pDummy, pBI, nTotalSize );
402                 }
403 
404                 GpiDrawBits( hPS, pDummy + nInfoSize, (BITMAPINFO2*) pDummy, 4L, pts, nDrawMode, BBO_IGNORE );
405                 delete[] pDummy;
406             }
407             else
408                 GpiDrawBits( hPS, pBits, pBI, 4L, pts, nDrawMode, BBO_IGNORE );
409         }
410         else if( hDrawDDB && !bPrintDDB )
411         {
412             POINTL pts[ 4 ];
413 
414             pts[0].x = pPosAry->mnDestX;
415             pts[0].y = nScreenHeight - pPosAry->mnDestY - pPosAry->mnDestHeight;
416             pts[1].x = pPosAry->mnDestX + pPosAry->mnDestWidth - 1;
417             pts[1].y = nScreenHeight - pPosAry->mnDestY - 1;
418 
419             pts[2].x = pPosAry->mnSrcX;
420             pts[2].y = rSalBitmap.GetSize().Height() - ( pPosAry->mnSrcY + pPosAry->mnSrcHeight );
421             pts[3].x = pPosAry->mnSrcX + pPosAry->mnSrcWidth;
422             pts[3].y = rSalBitmap.GetSize().Height() - pPosAry->mnSrcY;
423 
424             GpiWCBitBlt( hPS, hDrawDDB, 4L, pts, nDrawMode, BBO_IGNORE );
425 /*
426             HPS hDrawPS = ImplGetCachedPS( CACHED_HPS_DRAW, hDrawDDB );
427             Ft2BitBlt( hPS, hDrawPS, 4, pts, nDrawMode, BBO_IGNORE );
428             ImplReleaseCachedPS( CACHED_HPS_DRAW );
429 */
430         }
431 
432         if( bPrintDDB || bDrawDDB1 )
433             delete pTmpSalBmp;
434     }
435 }
436 
437 // -----------------------------------------------------------------------
438 
439 void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
440                               const SalBitmap& rSalBitmap )
441 {
442     ImplDrawBitmap( mhPS, mnHeight,
443                     pPosAry, static_cast<const Os2SalBitmap&>(rSalBitmap),
444                     mbPrinter,
445                     mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY );
446 }
447 
448 // -----------------------------------------------------------------------
449 
450 void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
451                               const SalBitmap& rSalBitmap,
452                               SalColor nTransparentColor )
453 {
454     DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
455     //const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
456     // an FM: kann erst einmal unberuecksichtigt bleiben
457     drawBitmap( pPosAry, rSalBitmap );
458 }
459 
460 // -----------------------------------------------------------------------
461 
462 void Os2SalGraphics::drawBitmap( const SalTwoRect* pPosAry,
463                               const SalBitmap& rSSalBitmap,
464                               const SalBitmap& rSTransparentBitmap )
465 {
466     DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
467 
468     const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
469     const Os2SalBitmap& rTransparentBitmap = static_cast<const Os2SalBitmap&>(rSTransparentBitmap);
470 
471     if( bFastTransparent )
472     {
473         ImplDrawBitmap( mhPS, mnHeight, pPosAry, rTransparentBitmap, FALSE, ROP_SRCAND );
474         ImplDrawBitmap( mhPS, mnHeight, pPosAry, rSalBitmap, FALSE, ROP_SRCPAINT );
475     }
476     else
477     {
478         SalTwoRect      aPosAry = *pPosAry;
479         int             nDstX = (int) aPosAry.mnDestX;
480         int             nDstY = (int) aPosAry.mnDestY;
481         int             nDstWidth = (int) aPosAry.mnDestWidth;
482         int             nDstHeight = (int) aPosAry.mnDestHeight;
483         HAB             hAB = GetSalData()->mhAB;
484         HPS             hPS = mhPS;
485         DEVOPENSTRUC    aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
486         SIZEL           aSizeL = { nDstWidth, nDstHeight };
487         POINTL          aPtL[ 3 ];
488 
489         HDC                hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
490         HPS                hMemPS = Ft2CreatePS( hAB, hMemDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
491         HBITMAP            hMemBitmap = ImplCreateVirDevBitmap( hMemDC, hMemPS, nDstWidth, nDstHeight, 0 );
492         HBITMAP            hMemOld = (HBITMAP) Ft2SetBitmap( hMemPS, hMemBitmap );
493         HDC                hMaskDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
494         HPS                hMaskPS = Ft2CreatePS( hAB, hMaskDC, &aSizeL, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
495         HBITMAP            hMaskBitmap = ImplCreateVirDevBitmap( hMaskDC, hMaskPS, nDstWidth, nDstHeight, 0 );
496         HBITMAP            hMaskOld = (HBITMAP) Ft2SetBitmap( hMaskPS, hMaskBitmap );
497 /*
498         HPS hMemPS = ImplGetCachedPS( CACHED_HPS_1, 0 );
499         HPS hMaskPS = ImplGetCachedPS( CACHED_HPS_2, 0 );
500 */
501         aPosAry.mnDestX = aPosAry.mnDestY = 0L;
502 
503         aPtL[ 0 ].x = 0;
504         aPtL[ 0 ].y = 0;
505         aPtL[ 1 ].x = nDstWidth;
506         aPtL[ 1 ].y = nDstHeight;
507         aPtL[ 2 ].x = nDstX;
508         aPtL[ 2 ].y = TY( nDstY + nDstHeight - 1 );
509 
510         GpiBitBlt( hMemPS, hPS, 3, aPtL, ROP_SRCCOPY, BBO_IGNORE );
511         ImplDrawBitmap( hMaskPS, nDstHeight, &aPosAry, rTransparentBitmap, FALSE, ROP_SRCCOPY );
512 
513         aPtL[ 2 ].x = 0;
514         aPtL[ 2 ].y = 0;
515 
516         GpiBitBlt( hMemPS, hMaskPS, 3, aPtL, ROP_SRCAND, BBO_IGNORE );
517         ImplDrawBitmap( hMaskPS, nDstHeight, &aPosAry, rSalBitmap, FALSE, ROP_SRCERASE );
518         GpiBitBlt( hMemPS, hMaskPS, 3, aPtL, ROP_SRCPAINT, BBO_IGNORE );
519 
520         aPtL[ 0 ].x = nDstX;
521         aPtL[ 0 ].y = TY( nDstY + nDstHeight - 1 );
522         aPtL[ 1 ].x = nDstX + nDstWidth;
523         aPtL[ 1 ].y = TY( nDstY - 1 );
524 
525         GpiBitBlt( hPS, hMemPS, 3, aPtL, ROP_SRCCOPY, BBO_IGNORE );
526 
527         Ft2SetBitmap( hMaskPS, hMaskOld );
528         Ft2DestroyPS( hMaskPS );
529         DevCloseDC( hMaskDC );
530         GpiDeleteBitmap( hMaskBitmap );
531 
532         Ft2SetBitmap( hMemPS, hMemOld );
533         Ft2DestroyPS( hMemPS );
534         DevCloseDC( hMemDC );
535         GpiDeleteBitmap( hMemBitmap );
536 
537 /*
538         ImplReleaseCachedPS( CACHED_HPS_1 );
539         ImplReleaseCachedPS( CACHED_HPS_2 );
540 */
541     }
542 }
543 
544 // -----------------------------------------------------------------------
545 
546 bool Os2SalGraphics::drawAlphaBitmap( const SalTwoRect& rTR,
547                       const SalBitmap&  rSrcBitmap,
548                       const SalBitmap&  rAlphaBmp )
549 {
550     // TODO(P3) implement alpha blending
551     return false;
552 }
553 
554 // -----------------------------------------------------------------------
555 
556 bool Os2SalGraphics::drawAlphaRect( long nX, long nY, long nWidth,
557                                     long nHeight, sal_uInt8 nTransparency )
558 {
559     // TODO(P3) implement alpha blending
560     return false;
561 }
562 
563 // -----------------------------------------------------------------------
564 
565 void Os2SalGraphics::drawMask( const SalTwoRect* pPosAry,
566                             const SalBitmap& rSSalBitmap,
567                             SalColor nMaskColor )
568 {
569     DBG_ASSERT( !mbPrinter, "No transparency print possible!" );
570 
571     const Os2SalBitmap& rSalBitmap = static_cast<const Os2SalBitmap&>(rSSalBitmap);
572 
573     SalTwoRect  aPosAry = *pPosAry;
574     HPS         hPS = mhPS;
575     IMAGEBUNDLE aBundle, aOldBundle;
576     AREABUNDLE  aAreaBundle, aOldAreaBundle;
577     const ULONG    nColor = RGBCOLOR( SALCOLOR_RED( nMaskColor ),
578                                     SALCOLOR_GREEN( nMaskColor ),
579                                     SALCOLOR_BLUE( nMaskColor ) );
580 
581     GpiQueryAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, &aOldBundle );
582     aBundle.lColor = RGBCOLOR( 0, 0, 0 );
583     aBundle.lBackColor = RGBCOLOR( 0xFF, 0xFF, 0xFF );
584     Ft2SetAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &aBundle );
585 
586     GpiQueryAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL |
587                    ABB_MIX_MODE | ABB_BACK_MIX_MODE, &aOldAreaBundle );
588     aAreaBundle.lColor = nColor;
589     aAreaBundle.lBackColor = nColor;
590     aAreaBundle.usSymbol = PATSYM_SOLID;
591     aAreaBundle.usMixMode = FM_OVERPAINT;
592     aAreaBundle.usBackMixMode = BM_OVERPAINT;
593     Ft2SetAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL |
594                  ABB_MIX_MODE | ABB_BACK_MIX_MODE, 0, &aAreaBundle );
595 
596     ImplDrawBitmap( hPS, mnHeight, &aPosAry, rSalBitmap, FALSE, 0x00B8L );
597 
598     Ft2SetAttrs( hPS, PRIM_IMAGE, IBB_COLOR | IBB_BACK_COLOR, 0, &aOldBundle );
599     Ft2SetAttrs( hPS, PRIM_AREA, ABB_COLOR | ABB_BACK_COLOR | ABB_SYMBOL |
600                  ABB_MIX_MODE | ABB_BACK_MIX_MODE, 0, &aOldAreaBundle );
601 }
602 
603 // -----------------------------------------------------------------------
604 
605 SalBitmap* Os2SalGraphics::getBitmap( long nX, long nY, long nDX, long nDY )
606 {
607     HAB            hAB = GetSalData()->mhAB;
608     SIZEL        size = { nDX, nDY };
609     Os2SalBitmap*     pSalBitmap = NULL;
610 
611     // create device context (at this time allways display compatible)
612     DEVOPENSTRUC    aDevOpenStruc = { NULL, (PSZ)"DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL };
613     HDC             hMemDC = DevOpenDC( hAB, OD_MEMORY, (PSZ)"*", 5L, (PDEVOPENDATA)&aDevOpenStruc, 0 );
614     HPS             hMemPS = Ft2CreatePS( hAB, hMemDC, &size, GPIT_MICRO | GPIA_ASSOC | PU_PELS );
615     HBITMAP         hMemBmp = ImplCreateVirDevBitmap( hMemDC, hMemPS, nDX, nDY, 0 );
616     HBITMAP         hMemOld = Ft2SetBitmap( hMemPS, hMemBmp );
617 
618     // creation successfull?
619     if( hMemDC && hMemPS && hMemBmp )
620     {
621         POINTL thePoints[ 3 ];
622 
623         // lower-left corner of target
624         thePoints[ 0 ].x = 0;
625         thePoints[ 0 ].y = 0;
626 
627         // upper-right corner of target
628         thePoints[ 1 ].x = nDX;
629         thePoints[ 1 ].y = nDY;
630 
631         // lower-left corner of source
632         thePoints[ 2 ].x = nX;
633         thePoints[ 2 ].y = TY( nY + nDY - 1 );
634 
635         long lHits = GpiBitBlt( hMemPS, mhPS, 3, thePoints,
636                                 mbXORMode ? ROP_SRCINVERT : ROP_SRCCOPY, BBO_IGNORE );
637 
638         if( hMemPS )
639         {
640             Ft2SetBitmap( hMemPS, hMemOld );
641             Ft2DestroyPS( hMemPS );
642         }
643 
644         if( hMemDC )
645             DevCloseDC( hMemDC );
646 
647         if( lHits == GPI_OK )
648         {
649             pSalBitmap = new Os2SalBitmap;
650 
651             if( !pSalBitmap->Create( hMemBmp, FALSE, FALSE ) )
652             {
653                 delete pSalBitmap;
654                 pSalBitmap = NULL;
655             }
656         }
657     }
658 
659     if( !pSalBitmap )
660         GpiDeleteBitmap( hMemBmp );
661 
662     // return pointer to SAL-Bitmap
663     return pSalBitmap;
664 }
665 
666 // -----------------------------------------------------------------------
667 
668 SalColor Os2SalGraphics::getPixel( long nX, long nY )
669 {
670     POINTL    aPt = { nX, TY( nY ) };
671     LONG    nColor = Ft2QueryPel( mhPS, &aPt );
672 
673     return MAKE_SALCOLOR( (BYTE) ( nColor >> 16 ), (BYTE) ( nColor >> 8 ), (BYTE) nColor );
674 }
675 
676 // -----------------------------------------------------------------------
677 
678 void Os2SalGraphics::invert( long nX, long nY, long nWidth, long nHeight, SalInvert nFlags )
679 {
680     if( nFlags & SAL_INVERT_TRACKFRAME )
681     {
682         // save old vylues
683         LINEBUNDLE oldLb;
684         LINEBUNDLE lb;
685         GpiQueryAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, &oldLb );
686 
687         // set linetype to short dash
688         lb.lColor = RGBCOLOR( 255, 255, 255 );
689         lb.usMixMode = FM_XOR;
690         lb.usType = LINETYPE_ALTERNATE;
691         Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &lb );
692 
693         // draw inverted box
694         POINTL aPt;
695 
696         aPt.x = nX;
697         aPt.y = TY( nY );
698 
699         Ft2Move( mhPS, &aPt );
700 
701         aPt.x = nX + nWidth - 1;
702         aPt.y = TY( nY + nHeight - 1 );
703 
704         Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 );
705 
706         // restore old values
707         Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &oldLb );
708 
709     }
710     else
711     {
712         // save old values
713         AREABUNDLE oldAb;
714         AREABUNDLE ab;
715 
716         GpiQueryAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, &oldAb );
717 
718         // set fill color to black
719         ab.lColor = RGBCOLOR( 255, 255, 255 );
720         ab.usMixMode = FM_XOR;
721         ab.usSymbol = (nFlags & SAL_INVERT_50) ? PATSYM_DENSE5 : PATSYM_SOLID;
722         Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &ab );
723 
724         // draw inverted box
725         POINTL aPt;
726 
727         aPt.x = nX;
728         aPt.y = TY( nY );
729 
730         Ft2Move( mhPS, &aPt );
731 
732         aPt.x = nX + nWidth - 1;
733         aPt.y = TY( nY + nHeight - 1 );
734 
735         Ft2Box( mhPS, DRO_FILL, &aPt, 0, 0 );
736 
737         // restore old values
738         Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &oldAb );
739     }
740 }
741 
742 // -----------------------------------------------------------------------
743 
744 void Os2SalGraphics::invert( ULONG nPoints, const SalPoint* pPtAry, SalInvert nFlags )
745 {
746     if( nFlags & SAL_INVERT_TRACKFRAME )
747     {
748         // save old vylues
749         LINEBUNDLE oldLb;
750         LINEBUNDLE lb;
751         GpiQueryAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, &oldLb );
752 
753         // set linetype to short dash
754         lb.lColor = RGBCOLOR( 255, 255, 255 );
755         lb.usMixMode = FM_XOR;
756         lb.usType = LINETYPE_ALTERNATE;
757         Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &lb );
758 
759         // Draw Polyline
760         drawPolyLine( nPoints, pPtAry );
761 
762         // restore old values
763         Ft2SetAttrs( mhPS, PRIM_LINE, LBB_MIX_MODE | LBB_TYPE | LBB_COLOR, 0, &oldLb );
764     }
765     else
766     {
767         // save old values
768         AREABUNDLE oldAb;
769         AREABUNDLE ab;
770 
771         GpiQueryAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, &oldAb );
772 
773         // set fill color to black
774         ab.lColor = RGBCOLOR( 255, 255, 255 );
775         ab.usMixMode = FM_XOR;
776         ab.usSymbol = (nFlags & SAL_INVERT_50) ? PATSYM_DENSE5 : PATSYM_SOLID;
777         Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &ab );
778 
779         // Draw Polyline
780         drawPolygon( nPoints, pPtAry );
781 
782         // restore old values
783         Ft2SetAttrs( mhPS, PRIM_AREA, ABB_COLOR | ABB_MIX_MODE | ABB_SYMBOL, 0, &oldAb );
784     }
785 }
786 
787