xref: /trunk/main/vcl/os2/source/gdi/salgdi2.cxx (revision 9f62ea84)
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