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