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