xref: /AOO41X/main/vcl/win/source/gdi/salgdi.cxx (revision 9f62ea84a806e17e6f2bbff75724a7257a0eb5d9)
1*9f62ea84SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3*9f62ea84SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4*9f62ea84SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5*9f62ea84SAndrew Rist  * distributed with this work for additional information
6*9f62ea84SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7*9f62ea84SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8*9f62ea84SAndrew Rist  * "License"); you may not use this file except in compliance
9*9f62ea84SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11*9f62ea84SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13*9f62ea84SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14*9f62ea84SAndrew Rist  * software distributed under the License is distributed on an
15*9f62ea84SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16*9f62ea84SAndrew Rist  * KIND, either express or implied.  See the License for the
17*9f62ea84SAndrew Rist  * specific language governing permissions and limitations
18*9f62ea84SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20*9f62ea84SAndrew Rist  *************************************************************/
21*9f62ea84SAndrew Rist 
22*9f62ea84SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <stdio.h>
28cdf0e10cSrcweir #include <string.h>
29cdf0e10cSrcweir 
30cdf0e10cSrcweir #include <rtl/strbuf.hxx>
31cdf0e10cSrcweir 
32cdf0e10cSrcweir #include <tools/svwin.h>
33cdf0e10cSrcweir #include <tools/debug.hxx>
34cdf0e10cSrcweir #include <tools/poly.hxx>
35cdf0e10cSrcweir 
36cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygon.hxx>
37cdf0e10cSrcweir #include <basegfx/polygon/b2dpolygontools.hxx>
38cdf0e10cSrcweir 
39cdf0e10cSrcweir #include <win/wincomp.hxx>
40cdf0e10cSrcweir #include <win/saldata.hxx>
41cdf0e10cSrcweir #include <win/salgdi.h>
42cdf0e10cSrcweir #include <win/salframe.h>
43cdf0e10cSrcweir 
44cdf0e10cSrcweir #include <region.h>
45cdf0e10cSrcweir 
46cdf0e10cSrcweir using namespace rtl;
47cdf0e10cSrcweir 
48cdf0e10cSrcweir // =======================================================================
49cdf0e10cSrcweir 
50cdf0e10cSrcweir // comment out to prevent use of beziers on GDI functions
51cdf0e10cSrcweir #define USE_GDI_BEZIERS
52cdf0e10cSrcweir 
53cdf0e10cSrcweir // =======================================================================
54cdf0e10cSrcweir 
55cdf0e10cSrcweir #define DITHER_PAL_DELTA				51
56cdf0e10cSrcweir #define DITHER_PAL_STEPS				6
57cdf0e10cSrcweir #define DITHER_PAL_COUNT				(DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS)
58cdf0e10cSrcweir #define DITHER_MAX_SYSCOLOR 			16
59cdf0e10cSrcweir #define DITHER_EXTRA_COLORS 			1
60cdf0e10cSrcweir #define DMAP( _def_nVal, _def_nThres )	((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal])
61cdf0e10cSrcweir 
62cdf0e10cSrcweir // =======================================================================
63cdf0e10cSrcweir 
64cdf0e10cSrcweir struct SysColorEntry
65cdf0e10cSrcweir {
66cdf0e10cSrcweir 	DWORD			nRGB;
67cdf0e10cSrcweir 	SysColorEntry*	pNext;
68cdf0e10cSrcweir };
69cdf0e10cSrcweir 
70cdf0e10cSrcweir // =======================================================================
71cdf0e10cSrcweir 
72cdf0e10cSrcweir static SysColorEntry* pFirstSysColor = NULL;
73cdf0e10cSrcweir static SysColorEntry* pActSysColor = NULL;
74cdf0e10cSrcweir 
75cdf0e10cSrcweir // -----------------------------------------------------------------------------
76cdf0e10cSrcweir 
77cdf0e10cSrcweir // Blue7
78cdf0e10cSrcweir static PALETTEENTRY aImplExtraColor1 =
79cdf0e10cSrcweir {
80cdf0e10cSrcweir 	0, 184, 255, 0
81cdf0e10cSrcweir };
82cdf0e10cSrcweir 
83cdf0e10cSrcweir // -----------------------------------------------------------------------------
84cdf0e10cSrcweir 
85cdf0e10cSrcweir static PALETTEENTRY aImplSalSysPalEntryAry[ DITHER_MAX_SYSCOLOR ] =
86cdf0e10cSrcweir {
87cdf0e10cSrcweir {	 0,    0,	 0, 0 },
88cdf0e10cSrcweir {	 0,    0, 0x80, 0 },
89cdf0e10cSrcweir {	 0, 0x80,	 0, 0 },
90cdf0e10cSrcweir {	 0, 0x80, 0x80, 0 },
91cdf0e10cSrcweir { 0x80,    0,	 0, 0 },
92cdf0e10cSrcweir { 0x80,    0, 0x80, 0 },
93cdf0e10cSrcweir { 0x80, 0x80,	 0, 0 },
94cdf0e10cSrcweir { 0x80, 0x80, 0x80, 0 },
95cdf0e10cSrcweir { 0xC0, 0xC0, 0xC0, 0 },
96cdf0e10cSrcweir {	 0,    0, 0xFF, 0 },
97cdf0e10cSrcweir {	 0, 0xFF,	 0, 0 },
98cdf0e10cSrcweir {	 0, 0xFF, 0xFF, 0 },
99cdf0e10cSrcweir { 0xFF,    0,	 0, 0 },
100cdf0e10cSrcweir { 0xFF,    0, 0xFF, 0 },
101cdf0e10cSrcweir { 0xFF, 0xFF,	 0, 0 },
102cdf0e10cSrcweir { 0xFF, 0xFF, 0xFF, 0 }
103cdf0e10cSrcweir };
104cdf0e10cSrcweir 
105cdf0e10cSrcweir // -----------------------------------------------------------------------------
106cdf0e10cSrcweir 
107cdf0e10cSrcweir static BYTE aOrdDither8Bit[8][8] =
108cdf0e10cSrcweir {
109cdf0e10cSrcweir 	 0, 38,  9, 48,  2, 40, 12, 50,
110cdf0e10cSrcweir 	25, 12, 35, 22, 28, 15, 37, 24,
111cdf0e10cSrcweir 	 6, 44,  3, 41,  8, 47,  5, 44,
112cdf0e10cSrcweir 	32, 19, 28, 16, 34, 21, 31, 18,
113cdf0e10cSrcweir 	 1, 40, 11, 49,  0, 39, 10, 48,
114cdf0e10cSrcweir 	27, 14, 36, 24, 26, 13, 36, 23,
115cdf0e10cSrcweir 	 8, 46,  4, 43,  7, 45,  4, 42,
116cdf0e10cSrcweir 	33, 20, 30, 17, 32, 20, 29, 16
117cdf0e10cSrcweir };
118cdf0e10cSrcweir 
119cdf0e10cSrcweir // -----------------------------------------------------------------------------
120cdf0e10cSrcweir 
121cdf0e10cSrcweir static BYTE aOrdDither16Bit[8][8] =
122cdf0e10cSrcweir {
123cdf0e10cSrcweir 	0, 6, 1, 7, 0, 6, 1, 7,
124cdf0e10cSrcweir 	4, 2, 5, 3, 4, 2, 5, 3,
125cdf0e10cSrcweir 	1, 7, 0, 6, 1, 7, 0, 6,
126cdf0e10cSrcweir 	5, 3, 4, 2, 5, 3, 4, 2,
127cdf0e10cSrcweir 	0, 6, 1, 7, 0, 6, 1, 7,
128cdf0e10cSrcweir 	4, 2, 5, 3, 4, 2, 5, 3,
129cdf0e10cSrcweir 	1, 7, 0, 6, 1, 7, 0, 6,
130cdf0e10cSrcweir 	5, 3, 4, 2, 5, 3, 4, 2
131cdf0e10cSrcweir };
132cdf0e10cSrcweir 
133cdf0e10cSrcweir // =======================================================================
134cdf0e10cSrcweir 
135cdf0e10cSrcweir // Pens muessen wir mit 1 Pixel-Breite erzeugen, da ansonsten die S3-Karte
136cdf0e10cSrcweir // viele Paintprobleme hat, wenn Polygone/PolyLines gezeichnet werden und
137cdf0e10cSrcweir // eine komplexe ClipRegion gesetzt ist
138cdf0e10cSrcweir #define GSL_PEN_WIDTH					1
139cdf0e10cSrcweir 
140cdf0e10cSrcweir // =======================================================================
141cdf0e10cSrcweir 
142cdf0e10cSrcweir #define SAL_POLYPOLYCOUNT_STACKBUF			8
143cdf0e10cSrcweir #define SAL_POLYPOLYPOINTS_STACKBUF 		64
144cdf0e10cSrcweir 
145cdf0e10cSrcweir // =======================================================================
146cdf0e10cSrcweir 
147cdf0e10cSrcweir void ImplInitSalGDI()
148cdf0e10cSrcweir {
149cdf0e10cSrcweir 	SalData* pSalData = GetSalData();
150cdf0e10cSrcweir 
151cdf0e10cSrcweir 	// init stock brushes
152cdf0e10cSrcweir 	pSalData->maStockPenColorAry[0] 	= PALETTERGB( 0, 0, 0 );
153cdf0e10cSrcweir 	pSalData->maStockPenColorAry[1] 	= PALETTERGB( 0xFF, 0xFF, 0xFF );
154cdf0e10cSrcweir 	pSalData->maStockPenColorAry[2] 	= PALETTERGB( 0xC0, 0xC0, 0xC0 );
155cdf0e10cSrcweir 	pSalData->maStockPenColorAry[3] 	= PALETTERGB( 0x80, 0x80, 0x80 );
156cdf0e10cSrcweir 	pSalData->mhStockPenAry[0]			= CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[0] );
157cdf0e10cSrcweir 	pSalData->mhStockPenAry[1]			= CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[1] );
158cdf0e10cSrcweir 	pSalData->mhStockPenAry[2]			= CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[2] );
159cdf0e10cSrcweir 	pSalData->mhStockPenAry[3]			= CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[3] );
160cdf0e10cSrcweir 	pSalData->mnStockPenCount = 4;
161cdf0e10cSrcweir 
162cdf0e10cSrcweir 	pSalData->maStockBrushColorAry[0]	= PALETTERGB( 0, 0, 0 );
163cdf0e10cSrcweir 	pSalData->maStockBrushColorAry[1]	= PALETTERGB( 0xFF, 0xFF, 0xFF );
164cdf0e10cSrcweir 	pSalData->maStockBrushColorAry[2]	= PALETTERGB( 0xC0, 0xC0, 0xC0 );
165cdf0e10cSrcweir 	pSalData->maStockBrushColorAry[3]	= PALETTERGB( 0x80, 0x80, 0x80 );
166cdf0e10cSrcweir 	pSalData->mhStockBrushAry[0]		= CreateSolidBrush( pSalData->maStockBrushColorAry[0] );
167cdf0e10cSrcweir 	pSalData->mhStockBrushAry[1]		= CreateSolidBrush( pSalData->maStockBrushColorAry[1] );
168cdf0e10cSrcweir 	pSalData->mhStockBrushAry[2]		= CreateSolidBrush( pSalData->maStockBrushColorAry[2] );
169cdf0e10cSrcweir 	pSalData->mhStockBrushAry[3]		= CreateSolidBrush( pSalData->maStockBrushColorAry[3] );
170cdf0e10cSrcweir 	pSalData->mnStockBrushCount = 4;
171cdf0e10cSrcweir 
172cdf0e10cSrcweir 	// initialize cache of device contexts
173cdf0e10cSrcweir 	pSalData->mpHDCCache = new HDCCache[ CACHESIZE_HDC ];
174cdf0e10cSrcweir 	memset( pSalData->mpHDCCache, 0, CACHESIZE_HDC * sizeof( HDCCache ) );
175cdf0e10cSrcweir 
176cdf0e10cSrcweir     // initialize temporary font list
177cdf0e10cSrcweir     pSalData->mpTempFontItem = NULL;
178cdf0e10cSrcweir 
179cdf0e10cSrcweir 	// support palettes for 256 color displays
180cdf0e10cSrcweir 	HDC hDC = GetDC( 0 );
181cdf0e10cSrcweir 	int nBitsPixel = GetDeviceCaps( hDC, BITSPIXEL );
182cdf0e10cSrcweir 	int nPlanes = GetDeviceCaps( hDC, PLANES );
183cdf0e10cSrcweir 	int nRasterCaps = GetDeviceCaps( hDC, RASTERCAPS );
184cdf0e10cSrcweir 	int nBitCount = nBitsPixel * nPlanes;
185cdf0e10cSrcweir 
186cdf0e10cSrcweir 	if ( (nBitCount > 8) && (nBitCount < 24) )
187cdf0e10cSrcweir 	{
188cdf0e10cSrcweir 		// test, if we have to dither
189cdf0e10cSrcweir 		HDC 		hMemDC = ::CreateCompatibleDC( hDC );
190cdf0e10cSrcweir 		HBITMAP 	hMemBmp = ::CreateCompatibleBitmap( hDC, 8, 8 );
191cdf0e10cSrcweir 		HBITMAP 	hBmpOld = (HBITMAP) ::SelectObject( hMemDC, hMemBmp );
192cdf0e10cSrcweir 		HBRUSH		hMemBrush = ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
193cdf0e10cSrcweir 		HBRUSH		hBrushOld = (HBRUSH) ::SelectObject( hMemDC, hMemBrush );
194cdf0e10cSrcweir 		sal_Bool		bDither16 = TRUE;
195cdf0e10cSrcweir 
196cdf0e10cSrcweir 		::PatBlt( hMemDC, 0, 0, 8, 8, PATCOPY );
197cdf0e10cSrcweir 		const COLORREF aCol( ::GetPixel( hMemDC, 0, 0 ) );
198cdf0e10cSrcweir 
199cdf0e10cSrcweir 		for( int nY = 0; ( nY < 8 ) && bDither16; nY++ )
200cdf0e10cSrcweir 			for( int nX = 0; ( nX < 8 ) && bDither16; nX++ )
201cdf0e10cSrcweir 				if( ::GetPixel( hMemDC, nX, nY ) != aCol )
202cdf0e10cSrcweir 					bDither16 = FALSE;
203cdf0e10cSrcweir 
204cdf0e10cSrcweir 		::SelectObject( hMemDC, hBrushOld ), ::DeleteObject( hMemBrush );
205cdf0e10cSrcweir 		::SelectObject( hMemDC, hBmpOld ), ::DeleteObject( hMemBmp );
206cdf0e10cSrcweir 		::DeleteDC( hMemDC );
207cdf0e10cSrcweir 
208cdf0e10cSrcweir 		if( bDither16 )
209cdf0e10cSrcweir 		{
210cdf0e10cSrcweir 			// create DIBPattern for 16Bit dithering
211cdf0e10cSrcweir 			long n;
212cdf0e10cSrcweir 
213cdf0e10cSrcweir 			pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, sizeof( BITMAPINFOHEADER ) + 192 );
214cdf0e10cSrcweir 			pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB );
215cdf0e10cSrcweir 			pSalData->mpDitherDiff = new long[ 256 ];
216cdf0e10cSrcweir 			pSalData->mpDitherLow = new BYTE[ 256 ];
217cdf0e10cSrcweir 			pSalData->mpDitherHigh = new BYTE[ 256 ];
218cdf0e10cSrcweir 			pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER );
219cdf0e10cSrcweir 			memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) );
220cdf0e10cSrcweir 
221cdf0e10cSrcweir 			BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB;
222cdf0e10cSrcweir 
223cdf0e10cSrcweir 			pBIH->biSize = sizeof( BITMAPINFOHEADER );
224cdf0e10cSrcweir 			pBIH->biWidth = 8;
225cdf0e10cSrcweir 			pBIH->biHeight = 8;
226cdf0e10cSrcweir 			pBIH->biPlanes = 1;
227cdf0e10cSrcweir 			pBIH->biBitCount = 24;
228cdf0e10cSrcweir 
229cdf0e10cSrcweir 			for( n = 0; n < 256L; n++ )
230cdf0e10cSrcweir 				pSalData->mpDitherDiff[ n ] = n - ( n & 248L );
231cdf0e10cSrcweir 
232cdf0e10cSrcweir 			for( n = 0; n < 256L; n++ )
233cdf0e10cSrcweir 				pSalData->mpDitherLow[ n ] = (BYTE) ( n & 248 );
234cdf0e10cSrcweir 
235cdf0e10cSrcweir 			for( n = 0; n < 256L; n++ )
236cdf0e10cSrcweir 				pSalData->mpDitherHigh[ n ] = (BYTE) Min( pSalData->mpDitherLow[ n ] + 8L, 255L );
237cdf0e10cSrcweir 		}
238cdf0e10cSrcweir 	}
239cdf0e10cSrcweir 	else if ( (nRasterCaps & RC_PALETTE) && (nBitCount == 8) )
240cdf0e10cSrcweir 	{
241cdf0e10cSrcweir 		BYTE			nRed, nGreen, nBlue;
242cdf0e10cSrcweir 		BYTE			nR, nG, nB;
243cdf0e10cSrcweir 		PALETTEENTRY*	pPalEntry;
244cdf0e10cSrcweir 		LOGPALETTE* 	pLogPal;
245cdf0e10cSrcweir 		const sal_uInt16	nDitherPalCount = DITHER_PAL_COUNT;
246cdf0e10cSrcweir 		sal_uLong			nTotalCount = DITHER_MAX_SYSCOLOR + nDitherPalCount + DITHER_EXTRA_COLORS;
247cdf0e10cSrcweir 
248cdf0e10cSrcweir 		// create logical palette
249cdf0e10cSrcweir 		pLogPal = (LOGPALETTE*) new char[ sizeof( LOGPALETTE ) + ( nTotalCount * sizeof( PALETTEENTRY ) ) ];
250cdf0e10cSrcweir 		pLogPal->palVersion = 0x0300;
251cdf0e10cSrcweir 		pLogPal->palNumEntries = (sal_uInt16) nTotalCount;
252cdf0e10cSrcweir 		pPalEntry = pLogPal->palPalEntry;
253cdf0e10cSrcweir 
254cdf0e10cSrcweir 		// Standard colors
255cdf0e10cSrcweir 		memcpy( pPalEntry, aImplSalSysPalEntryAry, DITHER_MAX_SYSCOLOR * sizeof( PALETTEENTRY ) );
256cdf0e10cSrcweir 		pPalEntry += DITHER_MAX_SYSCOLOR;
257cdf0e10cSrcweir 
258cdf0e10cSrcweir 		// own palette (6/6/6)
259cdf0e10cSrcweir 		for( nB=0, nBlue=0; nB < DITHER_PAL_STEPS; nB++, nBlue += DITHER_PAL_DELTA )
260cdf0e10cSrcweir 		{
261cdf0e10cSrcweir 			for( nG=0, nGreen=0; nG < DITHER_PAL_STEPS; nG++, nGreen += DITHER_PAL_DELTA )
262cdf0e10cSrcweir 			{
263cdf0e10cSrcweir 				for( nR=0, nRed=0; nR < DITHER_PAL_STEPS; nR++, nRed += DITHER_PAL_DELTA )
264cdf0e10cSrcweir 				{
265cdf0e10cSrcweir 					pPalEntry->peRed   = nRed;
266cdf0e10cSrcweir 					pPalEntry->peGreen = nGreen;
267cdf0e10cSrcweir 					pPalEntry->peBlue  = nBlue;
268cdf0e10cSrcweir 					pPalEntry->peFlags = 0;
269cdf0e10cSrcweir 					pPalEntry++;
270cdf0e10cSrcweir 				}
271cdf0e10cSrcweir 			}
272cdf0e10cSrcweir 		}
273cdf0e10cSrcweir 
274cdf0e10cSrcweir 		// insert special 'Blue' as standard drawing color
275cdf0e10cSrcweir 		*pPalEntry++ = aImplExtraColor1;
276cdf0e10cSrcweir 
277cdf0e10cSrcweir 		// create palette
278cdf0e10cSrcweir 		pSalData->mhDitherPal = CreatePalette( pLogPal );
279cdf0e10cSrcweir 		delete[] (char*) pLogPal;
280cdf0e10cSrcweir 
281cdf0e10cSrcweir 		if( pSalData->mhDitherPal )
282cdf0e10cSrcweir 		{
283cdf0e10cSrcweir 			// create DIBPattern for 8Bit dithering
284cdf0e10cSrcweir 			long nSize = sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ) + 64;
285cdf0e10cSrcweir 			long n;
286cdf0e10cSrcweir 
287cdf0e10cSrcweir 			pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, nSize );
288cdf0e10cSrcweir 			pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB );
289cdf0e10cSrcweir 			pSalData->mpDitherDiff = new long[ 256 ];
290cdf0e10cSrcweir 			pSalData->mpDitherLow = new BYTE[ 256 ];
291cdf0e10cSrcweir 			pSalData->mpDitherHigh = new BYTE[ 256 ];
292cdf0e10cSrcweir 			pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) );
293cdf0e10cSrcweir 			memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) );
294cdf0e10cSrcweir 
295cdf0e10cSrcweir 			BITMAPINFOHEADER*	pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB;
296cdf0e10cSrcweir 			short*				pColors = (short*) ( pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) );
297cdf0e10cSrcweir 
298cdf0e10cSrcweir 			pBIH->biSize = sizeof( BITMAPINFOHEADER );
299cdf0e10cSrcweir 			pBIH->biWidth = 8;
300cdf0e10cSrcweir 			pBIH->biHeight = 8;
301cdf0e10cSrcweir 			pBIH->biPlanes = 1;
302cdf0e10cSrcweir 			pBIH->biBitCount = 8;
303cdf0e10cSrcweir 
304cdf0e10cSrcweir 			for( n = 0; n < nDitherPalCount; n++ )
305cdf0e10cSrcweir 				pColors[ n ] = (short)( n + DITHER_MAX_SYSCOLOR );
306cdf0e10cSrcweir 
307cdf0e10cSrcweir 			for( n = 0; n < 256L; n++ )
308cdf0e10cSrcweir 				pSalData->mpDitherDiff[ n ] = n % 51L;
309cdf0e10cSrcweir 
310cdf0e10cSrcweir 			for( n = 0; n < 256L; n++ )
311cdf0e10cSrcweir 				pSalData->mpDitherLow[ n ] = (BYTE) ( n / 51L );
312cdf0e10cSrcweir 
313cdf0e10cSrcweir 			for( n = 0; n < 256L; n++ )
314cdf0e10cSrcweir 				pSalData->mpDitherHigh[ n ] = (BYTE)Min( pSalData->mpDitherLow[ n ] + 1, 5 );
315cdf0e10cSrcweir 		}
316cdf0e10cSrcweir 
317cdf0e10cSrcweir 		// get system color entries
318cdf0e10cSrcweir 		ImplUpdateSysColorEntries();
319cdf0e10cSrcweir 	}
320cdf0e10cSrcweir 
321cdf0e10cSrcweir 	ReleaseDC( 0, hDC );
322cdf0e10cSrcweir }
323cdf0e10cSrcweir 
324cdf0e10cSrcweir // -----------------------------------------------------------------------
325cdf0e10cSrcweir 
326cdf0e10cSrcweir void ImplFreeSalGDI()
327cdf0e10cSrcweir {
328cdf0e10cSrcweir 	SalData*	pSalData = GetSalData();
329cdf0e10cSrcweir 
330cdf0e10cSrcweir 	// destroy stock objects
331cdf0e10cSrcweir 	int	i;
332cdf0e10cSrcweir 	for ( i = 0; i < pSalData->mnStockPenCount; i++ )
333cdf0e10cSrcweir 		DeletePen( pSalData->mhStockPenAry[i] );
334cdf0e10cSrcweir 	for ( i = 0; i < pSalData->mnStockBrushCount; i++ )
335cdf0e10cSrcweir 		DeleteBrush( pSalData->mhStockBrushAry[i] );
336cdf0e10cSrcweir 
337cdf0e10cSrcweir 	// 50% Brush loeschen
338cdf0e10cSrcweir 	if ( pSalData->mh50Brush )
339cdf0e10cSrcweir 	{
340cdf0e10cSrcweir 		DeleteBrush( pSalData->mh50Brush );
341cdf0e10cSrcweir 		pSalData->mh50Brush = 0;
342cdf0e10cSrcweir 	}
343cdf0e10cSrcweir 
344cdf0e10cSrcweir 	// 50% Bitmap loeschen
345cdf0e10cSrcweir 	if ( pSalData->mh50Bmp )
346cdf0e10cSrcweir 	{
347cdf0e10cSrcweir 		DeleteBitmap( pSalData->mh50Bmp );
348cdf0e10cSrcweir 		pSalData->mh50Bmp = 0;
349cdf0e10cSrcweir 	}
350cdf0e10cSrcweir 
351cdf0e10cSrcweir 	ImplClearHDCCache( pSalData );
352cdf0e10cSrcweir 	delete[] pSalData->mpHDCCache;
353cdf0e10cSrcweir 
354cdf0e10cSrcweir 	// Ditherpalette loeschen, wenn vorhanden
355cdf0e10cSrcweir 	if ( pSalData->mhDitherPal )
356cdf0e10cSrcweir 	{
357cdf0e10cSrcweir 		DeleteObject( pSalData->mhDitherPal );
358cdf0e10cSrcweir 		pSalData->mhDitherPal = 0;
359cdf0e10cSrcweir 	}
360cdf0e10cSrcweir 
361cdf0e10cSrcweir 	// delete buffers for dithering DIB patterns, if neccessary
362cdf0e10cSrcweir 	if ( pSalData->mhDitherDIB )
363cdf0e10cSrcweir 	{
364cdf0e10cSrcweir 		GlobalUnlock( pSalData->mhDitherDIB );
365cdf0e10cSrcweir 		GlobalFree( pSalData->mhDitherDIB );
366cdf0e10cSrcweir 		pSalData->mhDitherDIB = 0;
367cdf0e10cSrcweir 		delete[] pSalData->mpDitherDiff;
368cdf0e10cSrcweir 		delete[] pSalData->mpDitherLow;
369cdf0e10cSrcweir 		delete[] pSalData->mpDitherHigh;
370cdf0e10cSrcweir 	}
371cdf0e10cSrcweir 
372cdf0e10cSrcweir 	// delete SysColorList
373cdf0e10cSrcweir 	SysColorEntry* pEntry = pFirstSysColor;
374cdf0e10cSrcweir 	while( pEntry )
375cdf0e10cSrcweir 	{
376cdf0e10cSrcweir 		SysColorEntry* pTmp = pEntry->pNext;
377cdf0e10cSrcweir 		delete pEntry;
378cdf0e10cSrcweir 		pEntry = pTmp;
379cdf0e10cSrcweir 	}
380cdf0e10cSrcweir 	pFirstSysColor = NULL;
381cdf0e10cSrcweir 
382cdf0e10cSrcweir     // delete icon cache
383cdf0e10cSrcweir     SalIcon* pIcon = pSalData->mpFirstIcon;
384cdf0e10cSrcweir     pSalData->mpFirstIcon = NULL;
385cdf0e10cSrcweir     while( pIcon )
386cdf0e10cSrcweir     {
387cdf0e10cSrcweir         SalIcon* pTmp = pIcon->pNext;
388cdf0e10cSrcweir         DestroyIcon( pIcon->hIcon );
389cdf0e10cSrcweir         DestroyIcon( pIcon->hSmallIcon );
390cdf0e10cSrcweir         delete pIcon;
391cdf0e10cSrcweir         pIcon = pTmp;
392cdf0e10cSrcweir     }
393cdf0e10cSrcweir 
394cdf0e10cSrcweir     // delete temporary font list
395cdf0e10cSrcweir     ImplReleaseTempFonts( *pSalData );
396cdf0e10cSrcweir }
397cdf0e10cSrcweir 
398cdf0e10cSrcweir // -----------------------------------------------------------------------
399cdf0e10cSrcweir 
400cdf0e10cSrcweir static int ImplIsPaletteEntry( BYTE nRed, BYTE nGreen, BYTE nBlue )
401cdf0e10cSrcweir {
402cdf0e10cSrcweir 	// dither color?
403cdf0e10cSrcweir 	if ( !(nRed % DITHER_PAL_DELTA) && !(nGreen % DITHER_PAL_DELTA) && !(nBlue % DITHER_PAL_DELTA) )
404cdf0e10cSrcweir 		return TRUE;
405cdf0e10cSrcweir 
406cdf0e10cSrcweir 	PALETTEENTRY* pPalEntry = aImplSalSysPalEntryAry;
407cdf0e10cSrcweir 
408cdf0e10cSrcweir 	// standard palette color?
409cdf0e10cSrcweir 	for ( sal_uInt16 i = 0; i < DITHER_MAX_SYSCOLOR; i++, pPalEntry++ )
410cdf0e10cSrcweir 	{
411cdf0e10cSrcweir 		if( pPalEntry->peRed == nRed && pPalEntry->peGreen == nGreen && pPalEntry->peBlue == nBlue )
412cdf0e10cSrcweir 			return TRUE;
413cdf0e10cSrcweir 	}
414cdf0e10cSrcweir 
415cdf0e10cSrcweir 	// extra color?
416cdf0e10cSrcweir 	if ( aImplExtraColor1.peRed == nRed &&
417cdf0e10cSrcweir 		 aImplExtraColor1.peGreen == nGreen &&
418cdf0e10cSrcweir 		 aImplExtraColor1.peBlue == nBlue )
419cdf0e10cSrcweir 	{
420cdf0e10cSrcweir 		return TRUE;
421cdf0e10cSrcweir 	}
422cdf0e10cSrcweir 
423cdf0e10cSrcweir 	return FALSE;
424cdf0e10cSrcweir }
425cdf0e10cSrcweir 
426cdf0e10cSrcweir // =======================================================================
427cdf0e10cSrcweir 
428cdf0e10cSrcweir int ImplIsSysColorEntry( SalColor nSalColor )
429cdf0e10cSrcweir {
430cdf0e10cSrcweir 	SysColorEntry*	pEntry = pFirstSysColor;
431cdf0e10cSrcweir 	const DWORD 	nTestRGB = (DWORD)RGB( SALCOLOR_RED( nSalColor ),
432cdf0e10cSrcweir 										   SALCOLOR_GREEN( nSalColor ),
433cdf0e10cSrcweir 										   SALCOLOR_BLUE( nSalColor ) );
434cdf0e10cSrcweir 
435cdf0e10cSrcweir 	while ( pEntry )
436cdf0e10cSrcweir 	{
437cdf0e10cSrcweir 		if ( pEntry->nRGB == nTestRGB )
438cdf0e10cSrcweir 			return TRUE;
439cdf0e10cSrcweir 		pEntry = pEntry->pNext;
440cdf0e10cSrcweir 	}
441cdf0e10cSrcweir 
442cdf0e10cSrcweir 	return FALSE;
443cdf0e10cSrcweir }
444cdf0e10cSrcweir 
445cdf0e10cSrcweir // =======================================================================
446cdf0e10cSrcweir 
447cdf0e10cSrcweir static void ImplInsertSysColorEntry( int nSysIndex )
448cdf0e10cSrcweir {
449cdf0e10cSrcweir 	const DWORD nRGB = GetSysColor( nSysIndex );
450cdf0e10cSrcweir 
451cdf0e10cSrcweir 	if ( !ImplIsPaletteEntry( GetRValue( nRGB ), GetGValue( nRGB ), GetBValue( nRGB ) ) )
452cdf0e10cSrcweir 	{
453cdf0e10cSrcweir 		if ( !pFirstSysColor )
454cdf0e10cSrcweir 		{
455cdf0e10cSrcweir 			pActSysColor = pFirstSysColor = new SysColorEntry;
456cdf0e10cSrcweir 			pFirstSysColor->nRGB = nRGB;
457cdf0e10cSrcweir 			pFirstSysColor->pNext = NULL;
458cdf0e10cSrcweir 		}
459cdf0e10cSrcweir 		else
460cdf0e10cSrcweir 		{
461cdf0e10cSrcweir 			pActSysColor = pActSysColor->pNext = new SysColorEntry;
462cdf0e10cSrcweir 			pActSysColor->nRGB = nRGB;
463cdf0e10cSrcweir 			pActSysColor->pNext = NULL;
464cdf0e10cSrcweir 		}
465cdf0e10cSrcweir 	}
466cdf0e10cSrcweir }
467cdf0e10cSrcweir 
468cdf0e10cSrcweir // =======================================================================
469cdf0e10cSrcweir 
470cdf0e10cSrcweir void ImplUpdateSysColorEntries()
471cdf0e10cSrcweir {
472cdf0e10cSrcweir 	// delete old SysColorList
473cdf0e10cSrcweir 	SysColorEntry* pEntry = pFirstSysColor;
474cdf0e10cSrcweir 	while( pEntry )
475cdf0e10cSrcweir 	{
476cdf0e10cSrcweir 		SysColorEntry* pTmp = pEntry->pNext;
477cdf0e10cSrcweir 		delete pEntry;
478cdf0e10cSrcweir 		pEntry = pTmp;
479cdf0e10cSrcweir 	}
480cdf0e10cSrcweir 	pActSysColor = pFirstSysColor = NULL;
481cdf0e10cSrcweir 
482cdf0e10cSrcweir 	// create new sys color list
483cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_ACTIVEBORDER );
484cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_INACTIVEBORDER );
485cdf0e10cSrcweir 	if( aSalShlData.mnVersion >= 410 )
486cdf0e10cSrcweir 	{
487cdf0e10cSrcweir 		ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION );
488cdf0e10cSrcweir 		ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION );
489cdf0e10cSrcweir 	}
490cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_3DFACE );
491cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_3DHILIGHT );
492cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_3DLIGHT );
493cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_3DSHADOW );
494cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_3DDKSHADOW );
495cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_INFOBK );
496cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_INFOTEXT );
497cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_BTNTEXT );
498cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_WINDOW );
499cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_WINDOWTEXT );
500cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_HIGHLIGHT );
501cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT );
502cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_MENU );
503cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_MENUTEXT );
504cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_ACTIVECAPTION );
505cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_CAPTIONTEXT );
506cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_INACTIVECAPTION );
507cdf0e10cSrcweir 	ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT );
508cdf0e10cSrcweir }
509cdf0e10cSrcweir 
510cdf0e10cSrcweir // -----------------------------------------------------------------------
511cdf0e10cSrcweir 
512cdf0e10cSrcweir static SalColor ImplGetROPSalColor( SalROPColor nROPColor )
513cdf0e10cSrcweir {
514cdf0e10cSrcweir 	SalColor nSalColor;
515cdf0e10cSrcweir 	if ( nROPColor == SAL_ROP_0 )
516cdf0e10cSrcweir 		nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
517cdf0e10cSrcweir 	else
518cdf0e10cSrcweir 		nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
519cdf0e10cSrcweir 	return nSalColor;
520cdf0e10cSrcweir }
521cdf0e10cSrcweir 
522cdf0e10cSrcweir // =======================================================================
523cdf0e10cSrcweir 
524cdf0e10cSrcweir void ImplSalInitGraphics( WinSalGraphics* pData )
525cdf0e10cSrcweir {
526cdf0e10cSrcweir 	// Beim Printer berechnen wir die minimale Linienstaerke
527cdf0e10cSrcweir 	if ( pData->mbPrinter )
528cdf0e10cSrcweir 	{
529cdf0e10cSrcweir 		int nDPIX = GetDeviceCaps( pData->mhDC, LOGPIXELSX );
530cdf0e10cSrcweir 		if ( nDPIX <= 300 )
531cdf0e10cSrcweir 			pData->mnPenWidth = 0;
532cdf0e10cSrcweir 		else
533cdf0e10cSrcweir 			pData->mnPenWidth = nDPIX/300;
534cdf0e10cSrcweir 	}
535cdf0e10cSrcweir 
536cdf0e10cSrcweir 	::SetTextAlign( pData->mhDC, TA_BASELINE | TA_LEFT | TA_NOUPDATECP );
537cdf0e10cSrcweir 	::SetBkMode( pData->mhDC, TRANSPARENT );
538cdf0e10cSrcweir 	::SetROP2( pData->mhDC, R2_COPYPEN );
539cdf0e10cSrcweir }
540cdf0e10cSrcweir 
541cdf0e10cSrcweir // -----------------------------------------------------------------------
542cdf0e10cSrcweir 
543cdf0e10cSrcweir void ImplSalDeInitGraphics( WinSalGraphics* pData )
544cdf0e10cSrcweir {
545cdf0e10cSrcweir     // clear clip region
546cdf0e10cSrcweir 	SelectClipRgn( pData->mhDC, 0 );
547cdf0e10cSrcweir 	// select default objects
548cdf0e10cSrcweir 	if ( pData->mhDefPen )
549cdf0e10cSrcweir 		SelectPen( pData->mhDC, pData->mhDefPen );
550cdf0e10cSrcweir 	if ( pData->mhDefBrush )
551cdf0e10cSrcweir 		SelectBrush( pData->mhDC, pData->mhDefBrush );
552cdf0e10cSrcweir 	if ( pData->mhDefFont )
553cdf0e10cSrcweir 		SelectFont( pData->mhDC, pData->mhDefFont );
554cdf0e10cSrcweir }
555cdf0e10cSrcweir 
556cdf0e10cSrcweir // =======================================================================
557cdf0e10cSrcweir 
558cdf0e10cSrcweir HDC ImplGetCachedDC( sal_uLong nID, HBITMAP hBmp )
559cdf0e10cSrcweir {
560cdf0e10cSrcweir 	SalData*	pSalData = GetSalData();
561cdf0e10cSrcweir 	HDCCache*	pC = &pSalData->mpHDCCache[ nID ];
562cdf0e10cSrcweir 
563cdf0e10cSrcweir 	if( !pC->mhDC )
564cdf0e10cSrcweir 	{
565cdf0e10cSrcweir 		HDC hDC = GetDC( 0 );
566cdf0e10cSrcweir 
567cdf0e10cSrcweir 		// neuen DC mit DefaultBitmap anlegen
568cdf0e10cSrcweir 		pC->mhDC = CreateCompatibleDC( hDC );
569cdf0e10cSrcweir 
570cdf0e10cSrcweir 		if( pSalData->mhDitherPal )
571cdf0e10cSrcweir 		{
572cdf0e10cSrcweir 			pC->mhDefPal = SelectPalette( pC->mhDC, pSalData->mhDitherPal, TRUE );
573cdf0e10cSrcweir 			RealizePalette( pC->mhDC );
574cdf0e10cSrcweir 		}
575cdf0e10cSrcweir 
576cdf0e10cSrcweir 		pC->mhSelBmp = CreateCompatibleBitmap( hDC, CACHED_HDC_DEFEXT, CACHED_HDC_DEFEXT );
577cdf0e10cSrcweir 		pC->mhDefBmp = (HBITMAP) SelectObject( pC->mhDC, pC->mhSelBmp );
578cdf0e10cSrcweir 
579cdf0e10cSrcweir 		ReleaseDC( 0, hDC );
580cdf0e10cSrcweir 	}
581cdf0e10cSrcweir 
582cdf0e10cSrcweir 	if ( hBmp )
583cdf0e10cSrcweir 		SelectObject( pC->mhDC, pC->mhActBmp = hBmp );
584cdf0e10cSrcweir 	else
585cdf0e10cSrcweir 		pC->mhActBmp = 0;
586cdf0e10cSrcweir 
587cdf0e10cSrcweir 	return pC->mhDC;
588cdf0e10cSrcweir }
589cdf0e10cSrcweir 
590cdf0e10cSrcweir // =======================================================================
591cdf0e10cSrcweir 
592cdf0e10cSrcweir void ImplReleaseCachedDC( sal_uLong nID )
593cdf0e10cSrcweir {
594cdf0e10cSrcweir 	SalData*	pSalData = GetSalData();
595cdf0e10cSrcweir 	HDCCache*	pC = &pSalData->mpHDCCache[ nID ];
596cdf0e10cSrcweir 
597cdf0e10cSrcweir 	if ( pC->mhActBmp )
598cdf0e10cSrcweir 		SelectObject( pC->mhDC, pC->mhSelBmp );
599cdf0e10cSrcweir }
600cdf0e10cSrcweir 
601cdf0e10cSrcweir // =======================================================================
602cdf0e10cSrcweir 
603cdf0e10cSrcweir void ImplClearHDCCache( SalData* pData )
604cdf0e10cSrcweir {
605cdf0e10cSrcweir 	for( sal_uLong i = 0; i < CACHESIZE_HDC; i++ )
606cdf0e10cSrcweir 	{
607cdf0e10cSrcweir 		HDCCache* pC = &pData->mpHDCCache[ i ];
608cdf0e10cSrcweir 
609cdf0e10cSrcweir 		if( pC->mhDC )
610cdf0e10cSrcweir 		{
611cdf0e10cSrcweir 			SelectObject( pC->mhDC, pC->mhDefBmp );
612cdf0e10cSrcweir 
613cdf0e10cSrcweir 			if( pC->mhDefPal )
614cdf0e10cSrcweir 				SelectPalette( pC->mhDC, pC->mhDefPal, TRUE );
615cdf0e10cSrcweir 
616cdf0e10cSrcweir 			DeleteDC( pC->mhDC );
617cdf0e10cSrcweir 			DeleteObject( pC->mhSelBmp );
618cdf0e10cSrcweir 		}
619cdf0e10cSrcweir 	}
620cdf0e10cSrcweir }
621cdf0e10cSrcweir 
622cdf0e10cSrcweir // =======================================================================
623cdf0e10cSrcweir 
624cdf0e10cSrcweir // #100127# Fill point and flag memory from array of points which
625cdf0e10cSrcweir // might also contain bezier control points for the PolyDraw() GDI method
626cdf0e10cSrcweir // Make sure pWinPointAry and pWinFlagAry are big enough
627cdf0e10cSrcweir void ImplPreparePolyDraw( bool						bCloseFigures,
628cdf0e10cSrcweir                           sal_uLong 					nPoly,
629cdf0e10cSrcweir                           const sal_uLong* 				pPoints,
630cdf0e10cSrcweir                           const SalPoint* const* 	pPtAry,
631cdf0e10cSrcweir                           const BYTE* const* 		pFlgAry,
632cdf0e10cSrcweir                           POINT* 					pWinPointAry,
633cdf0e10cSrcweir                           BYTE* 					pWinFlagAry		)
634cdf0e10cSrcweir {
635cdf0e10cSrcweir     sal_uLong nCurrPoly;
636cdf0e10cSrcweir     for( nCurrPoly=0; nCurrPoly<nPoly; ++nCurrPoly )
637cdf0e10cSrcweir     {
638cdf0e10cSrcweir         const POINT* pCurrPoint = reinterpret_cast<const POINT*>( *pPtAry++ );
639cdf0e10cSrcweir         const BYTE* pCurrFlag = *pFlgAry++;
640cdf0e10cSrcweir         const sal_uLong nCurrPoints = *pPoints++;
641cdf0e10cSrcweir         const bool bHaveFlagArray( pCurrFlag );
642cdf0e10cSrcweir         sal_uLong nCurrPoint;
643cdf0e10cSrcweir 
644cdf0e10cSrcweir         if( nCurrPoints )
645cdf0e10cSrcweir         {
646cdf0e10cSrcweir             // start figure
647cdf0e10cSrcweir             *pWinPointAry++ = *pCurrPoint++;
648cdf0e10cSrcweir             *pWinFlagAry++  = PT_MOVETO;
649cdf0e10cSrcweir             ++pCurrFlag;
650cdf0e10cSrcweir 
651cdf0e10cSrcweir             for( nCurrPoint=1; nCurrPoint<nCurrPoints; )
652cdf0e10cSrcweir             {
653cdf0e10cSrcweir                 // #102067# Check existence of flag array
654cdf0e10cSrcweir                 if( bHaveFlagArray &&
655cdf0e10cSrcweir                     ( nCurrPoint + 2 ) < nCurrPoints )
656cdf0e10cSrcweir                 {
657cdf0e10cSrcweir                     BYTE P4( pCurrFlag[ 2 ] );
658cdf0e10cSrcweir 
659cdf0e10cSrcweir                     if( ( POLY_CONTROL == pCurrFlag[ 0 ] ) &&
660cdf0e10cSrcweir                         ( POLY_CONTROL == pCurrFlag[ 1 ] ) &&
661cdf0e10cSrcweir                         ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) )
662cdf0e10cSrcweir                     {
663cdf0e10cSrcweir                         // control point one
664cdf0e10cSrcweir                         *pWinPointAry++ = *pCurrPoint++;
665cdf0e10cSrcweir                         *pWinFlagAry++  = PT_BEZIERTO;
666cdf0e10cSrcweir 
667cdf0e10cSrcweir                         // control point two
668cdf0e10cSrcweir                         *pWinPointAry++ = *pCurrPoint++;
669cdf0e10cSrcweir                         *pWinFlagAry++  = PT_BEZIERTO;
670cdf0e10cSrcweir 
671cdf0e10cSrcweir                         // end point
672cdf0e10cSrcweir                         *pWinPointAry++ = *pCurrPoint++;
673cdf0e10cSrcweir                         *pWinFlagAry++  = PT_BEZIERTO;
674cdf0e10cSrcweir 
675cdf0e10cSrcweir                         nCurrPoint += 3;
676cdf0e10cSrcweir                         pCurrFlag += 3;
677cdf0e10cSrcweir                         continue;
678cdf0e10cSrcweir                     }
679cdf0e10cSrcweir                 }
680cdf0e10cSrcweir 
681cdf0e10cSrcweir                 // regular line point
682cdf0e10cSrcweir                 *pWinPointAry++ = *pCurrPoint++;
683cdf0e10cSrcweir                 *pWinFlagAry++  = PT_LINETO;
684cdf0e10cSrcweir                 ++pCurrFlag;
685cdf0e10cSrcweir                 ++nCurrPoint;
686cdf0e10cSrcweir             }
687cdf0e10cSrcweir 
688cdf0e10cSrcweir             // end figure?
689cdf0e10cSrcweir             if( bCloseFigures )
690cdf0e10cSrcweir                 pWinFlagAry[-1] |= PT_CLOSEFIGURE;
691cdf0e10cSrcweir         }
692cdf0e10cSrcweir     }
693cdf0e10cSrcweir }
694cdf0e10cSrcweir 
695cdf0e10cSrcweir // =======================================================================
696cdf0e10cSrcweir 
697cdf0e10cSrcweir // #100127# draw an array of points which might also contain bezier control points
698cdf0e10cSrcweir void ImplRenderPath( HDC hdc, sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry )
699cdf0e10cSrcweir {
700cdf0e10cSrcweir     if( nPoints )
701cdf0e10cSrcweir     {
702cdf0e10cSrcweir         sal_uInt16 i;
703cdf0e10cSrcweir         // TODO: profile whether the following options are faster:
704cdf0e10cSrcweir         // a) look ahead and draw consecutive bezier or line segments by PolyBezierTo/PolyLineTo resp.
705cdf0e10cSrcweir         // b) convert our flag array to window's and use PolyDraw
706cdf0e10cSrcweir 
707cdf0e10cSrcweir         MoveToEx( hdc, pPtAry->mnX, pPtAry->mnY, NULL );
708cdf0e10cSrcweir         ++pPtAry; ++pFlgAry;
709cdf0e10cSrcweir 
710cdf0e10cSrcweir         for( i=1; i<nPoints; ++i, ++pPtAry, ++pFlgAry )
711cdf0e10cSrcweir         {
712cdf0e10cSrcweir             if( *pFlgAry != POLY_CONTROL )
713cdf0e10cSrcweir             {
714cdf0e10cSrcweir                 LineTo( hdc, pPtAry->mnX, pPtAry->mnY );
715cdf0e10cSrcweir             }
716cdf0e10cSrcweir             else if( nPoints - i > 2 )
717cdf0e10cSrcweir             {
718cdf0e10cSrcweir                 PolyBezierTo( hdc, reinterpret_cast<const POINT*>(pPtAry), 3 );
719cdf0e10cSrcweir                 i += 2; pPtAry += 2; pFlgAry += 2;
720cdf0e10cSrcweir             }
721cdf0e10cSrcweir         }
722cdf0e10cSrcweir     }
723cdf0e10cSrcweir }
724cdf0e10cSrcweir 
725cdf0e10cSrcweir // =======================================================================
726cdf0e10cSrcweir 
727cdf0e10cSrcweir WinSalGraphics::WinSalGraphics()
728cdf0e10cSrcweir {
729cdf0e10cSrcweir     for( int i = 0; i < MAX_FALLBACK; ++i )
730cdf0e10cSrcweir     {
731cdf0e10cSrcweir         mhFonts[ i ] = 0;
732cdf0e10cSrcweir         mpWinFontData[ i ]  = NULL;
733cdf0e10cSrcweir         mpWinFontEntry[ i ] = NULL;
734cdf0e10cSrcweir     }
735cdf0e10cSrcweir 
736cdf0e10cSrcweir     mfFontScale = 1.0;
737cdf0e10cSrcweir 
738cdf0e10cSrcweir 	mhDC 				= 0;
739cdf0e10cSrcweir 	mhPen				= 0;
740cdf0e10cSrcweir 	mhBrush				= 0;
741cdf0e10cSrcweir 	mhRegion 			= 0;
742cdf0e10cSrcweir 	mhDefPen 			= 0;
743cdf0e10cSrcweir 	mhDefBrush			= 0;
744cdf0e10cSrcweir 	mhDefFont			= 0;
745cdf0e10cSrcweir 	mhDefPal 			= 0;
746cdf0e10cSrcweir 	mpStdClipRgnData 	= NULL;
747cdf0e10cSrcweir 	mpLogFont			= NULL;
748cdf0e10cSrcweir 	mpFontCharSets		= NULL;
749cdf0e10cSrcweir 	mpFontAttrCache		= NULL;
750cdf0e10cSrcweir 	mnFontCharSetCount	= 0;
751cdf0e10cSrcweir 	mpFontKernPairs		= NULL;
752cdf0e10cSrcweir 	mnFontKernPairCount	= 0;
753cdf0e10cSrcweir 	mbFontKernInit		= FALSE;
754cdf0e10cSrcweir 	mbXORMode			= FALSE;
755cdf0e10cSrcweir 	mnPenWidth			= GSL_PEN_WIDTH;
756cdf0e10cSrcweir }
757cdf0e10cSrcweir 
758cdf0e10cSrcweir // -----------------------------------------------------------------------
759cdf0e10cSrcweir 
760cdf0e10cSrcweir WinSalGraphics::~WinSalGraphics()
761cdf0e10cSrcweir {
762cdf0e10cSrcweir 	// free obsolete GDI objekts
763cdf0e10cSrcweir         ReleaseFonts();
764cdf0e10cSrcweir 
765cdf0e10cSrcweir 	if ( mhPen )
766cdf0e10cSrcweir 	{
767cdf0e10cSrcweir 		if ( !mbStockPen )
768cdf0e10cSrcweir 			DeletePen( mhPen );
769cdf0e10cSrcweir 	}
770cdf0e10cSrcweir 	if ( mhBrush )
771cdf0e10cSrcweir 	{
772cdf0e10cSrcweir 		if ( !mbStockBrush )
773cdf0e10cSrcweir 			DeleteBrush( mhBrush );
774cdf0e10cSrcweir 	}
775cdf0e10cSrcweir 
776cdf0e10cSrcweir 	if ( mhRegion )
777cdf0e10cSrcweir 	{
778cdf0e10cSrcweir 		DeleteRegion( mhRegion );
779cdf0e10cSrcweir 		mhRegion = 0;
780cdf0e10cSrcweir 	}
781cdf0e10cSrcweir 
782cdf0e10cSrcweir 	// Cache-Daten zerstoeren
783cdf0e10cSrcweir 	if ( mpStdClipRgnData )
784cdf0e10cSrcweir 		delete [] mpStdClipRgnData;
785cdf0e10cSrcweir 
786cdf0e10cSrcweir 	if ( mpLogFont )
787cdf0e10cSrcweir 		delete mpLogFont;
788cdf0e10cSrcweir 
789cdf0e10cSrcweir 	if ( mpFontCharSets )
790cdf0e10cSrcweir 		delete mpFontCharSets;
791cdf0e10cSrcweir 
792cdf0e10cSrcweir 	if ( mpFontKernPairs )
793cdf0e10cSrcweir 		delete mpFontKernPairs;
794cdf0e10cSrcweir }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir // -----------------------------------------------------------------------
797cdf0e10cSrcweir 
798cdf0e10cSrcweir void WinSalGraphics::GetResolution( long& rDPIX, long& rDPIY )
799cdf0e10cSrcweir {
800cdf0e10cSrcweir 	rDPIX = GetDeviceCaps( mhDC, LOGPIXELSX );
801cdf0e10cSrcweir 	rDPIY = GetDeviceCaps( mhDC, LOGPIXELSY );
802cdf0e10cSrcweir 
803cdf0e10cSrcweir     // #111139# this fixes the symptom of div by zero on startup
804cdf0e10cSrcweir     // however, printing will fail most likely as communication with
805cdf0e10cSrcweir     // the printer seems not to work in this case
806cdf0e10cSrcweir     if( !rDPIX || !rDPIY )
807cdf0e10cSrcweir         rDPIX = rDPIY = 600;
808cdf0e10cSrcweir }
809cdf0e10cSrcweir 
810cdf0e10cSrcweir // -----------------------------------------------------------------------
811cdf0e10cSrcweir 
812cdf0e10cSrcweir sal_uInt16 WinSalGraphics::GetBitCount()
813cdf0e10cSrcweir {
814cdf0e10cSrcweir 	return (sal_uInt16)GetDeviceCaps( mhDC, BITSPIXEL );
815cdf0e10cSrcweir }
816cdf0e10cSrcweir 
817cdf0e10cSrcweir // -----------------------------------------------------------------------
818cdf0e10cSrcweir 
819cdf0e10cSrcweir long WinSalGraphics::GetGraphicsWidth() const
820cdf0e10cSrcweir {
821cdf0e10cSrcweir     if( mhWnd && IsWindow( mhWnd ) )
822cdf0e10cSrcweir     {
823cdf0e10cSrcweir         WinSalFrame* pFrame = GetWindowPtr( mhWnd );
824cdf0e10cSrcweir         if( pFrame )
825cdf0e10cSrcweir         {
826cdf0e10cSrcweir             if( pFrame->maGeometry.nWidth )
827cdf0e10cSrcweir                 return pFrame->maGeometry.nWidth;
828cdf0e10cSrcweir             else
829cdf0e10cSrcweir             {
830cdf0e10cSrcweir                 // TODO: perhaps not needed, maGeometry should always be up-to-date
831cdf0e10cSrcweir                 RECT aRect;
832cdf0e10cSrcweir                 GetClientRect( mhWnd, &aRect );
833cdf0e10cSrcweir                 return aRect.right;
834cdf0e10cSrcweir             }
835cdf0e10cSrcweir         }
836cdf0e10cSrcweir     }
837cdf0e10cSrcweir 
838cdf0e10cSrcweir     return 0;
839cdf0e10cSrcweir }
840cdf0e10cSrcweir 
841cdf0e10cSrcweir // -----------------------------------------------------------------------
842cdf0e10cSrcweir 
843cdf0e10cSrcweir void WinSalGraphics::ResetClipRegion()
844cdf0e10cSrcweir {
845cdf0e10cSrcweir 	if ( mhRegion )
846cdf0e10cSrcweir 	{
847cdf0e10cSrcweir 		DeleteRegion( mhRegion );
848cdf0e10cSrcweir 		mhRegion = 0;
849cdf0e10cSrcweir 	}
850cdf0e10cSrcweir 
851cdf0e10cSrcweir 	SelectClipRgn( mhDC, 0 );
852cdf0e10cSrcweir }
853cdf0e10cSrcweir 
854cdf0e10cSrcweir // -----------------------------------------------------------------------
855cdf0e10cSrcweir 
856cdf0e10cSrcweir bool WinSalGraphics::setClipRegion( const Region& i_rClip )
857cdf0e10cSrcweir {
858cdf0e10cSrcweir 	if ( mhRegion )
859cdf0e10cSrcweir 	{
860cdf0e10cSrcweir 		DeleteRegion( mhRegion );
861cdf0e10cSrcweir 		mhRegion = 0;
862cdf0e10cSrcweir 	}
863cdf0e10cSrcweir 
864cdf0e10cSrcweir 	if( i_rClip.HasPolyPolygon() )
865cdf0e10cSrcweir 	{
866cdf0e10cSrcweir 	    // TODO: ConvertToB2DPolyPolygon actually is kind of const, just it does not advertise it in the header
867cdf0e10cSrcweir 	    basegfx::B2DPolyPolygon aPolyPolygon( const_cast<Region&>(i_rClip).ConvertToB2DPolyPolygon() );
868cdf0e10cSrcweir         const sal_uInt32 nCount(aPolyPolygon.count());
869cdf0e10cSrcweir 
870cdf0e10cSrcweir         if( nCount )
871cdf0e10cSrcweir         {
872cdf0e10cSrcweir             std::vector< POINT > aPolyPoints;
873cdf0e10cSrcweir             aPolyPoints.reserve( 1024 );
874cdf0e10cSrcweir             std::vector< INT > aPolyCounts( nCount, 0 );
875cdf0e10cSrcweir             for(sal_uInt32 a(0); a < nCount; a++)
876cdf0e10cSrcweir             {
877cdf0e10cSrcweir                 basegfx::B2DPolygon aPoly( aPolyPolygon.getB2DPolygon(a) );
878cdf0e10cSrcweir                 aPoly = basegfx::tools::adaptiveSubdivideByDistance( aPoly, 1 );
879cdf0e10cSrcweir                 const sal_uInt32 nPoints = aPoly.count();
880cdf0e10cSrcweir                 aPolyCounts[a] = nPoints;
881cdf0e10cSrcweir                 for( sal_uInt32 b = 0; b < nPoints; b++ )
882cdf0e10cSrcweir                 {
883cdf0e10cSrcweir                     basegfx::B2DPoint aPt( aPoly.getB2DPoint( b ) );
884cdf0e10cSrcweir                     POINT aPOINT;
885cdf0e10cSrcweir                     aPOINT.x = (LONG)aPt.getX();
886cdf0e10cSrcweir                     aPOINT.y = (LONG)aPt.getY();
887cdf0e10cSrcweir                     aPolyPoints.push_back( aPOINT );
888cdf0e10cSrcweir                 }
889cdf0e10cSrcweir             }
890cdf0e10cSrcweir             mhRegion = CreatePolyPolygonRgn( &aPolyPoints[0], &aPolyCounts[0], nCount, ALTERNATE );
891cdf0e10cSrcweir         }
892cdf0e10cSrcweir 	}
893cdf0e10cSrcweir 	else
894cdf0e10cSrcweir 	{
895cdf0e10cSrcweir 	    ULONG nRectCount = i_rClip.GetRectCount();
896cdf0e10cSrcweir 
897cdf0e10cSrcweir 	    ULONG nRectBufSize = sizeof(RECT)*nRectCount;
898cdf0e10cSrcweir         if ( nRectCount < SAL_CLIPRECT_COUNT )
899cdf0e10cSrcweir         {
900cdf0e10cSrcweir             if ( !mpStdClipRgnData )
901cdf0e10cSrcweir                 mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))];
902cdf0e10cSrcweir             mpClipRgnData = mpStdClipRgnData;
903cdf0e10cSrcweir         }
904cdf0e10cSrcweir         else
905cdf0e10cSrcweir             mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize];
906cdf0e10cSrcweir         mpClipRgnData->rdh.dwSize	= sizeof( RGNDATAHEADER );
907cdf0e10cSrcweir         mpClipRgnData->rdh.iType 	= RDH_RECTANGLES;
908cdf0e10cSrcweir         mpClipRgnData->rdh.nCount	= nRectCount;
909cdf0e10cSrcweir         mpClipRgnData->rdh.nRgnSize	= nRectBufSize;
910cdf0e10cSrcweir         RECT*		pBoundRect = &(mpClipRgnData->rdh.rcBound);
911cdf0e10cSrcweir         SetRectEmpty( pBoundRect );
912cdf0e10cSrcweir         RECT* pNextClipRect         = (RECT*)(&(mpClipRgnData->Buffer));
913cdf0e10cSrcweir         bool bFirstClipRect         = true;
914cdf0e10cSrcweir 
915cdf0e10cSrcweir         ImplRegionInfo aInfo;
916cdf0e10cSrcweir         long nX, nY, nW, nH;
917cdf0e10cSrcweir         bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH );
918cdf0e10cSrcweir         while( bRegionRect )
919cdf0e10cSrcweir         {
920cdf0e10cSrcweir             if ( nW && nH )
921cdf0e10cSrcweir             {
922cdf0e10cSrcweir                 long		nRight = nX + nW;
923cdf0e10cSrcweir                 long		nBottom = nY + nH;
924cdf0e10cSrcweir 
925cdf0e10cSrcweir                 if ( bFirstClipRect )
926cdf0e10cSrcweir                 {
927cdf0e10cSrcweir                     pBoundRect->left	= nX;
928cdf0e10cSrcweir                     pBoundRect->top 	= nY;
929cdf0e10cSrcweir                     pBoundRect->right	= nRight;
930cdf0e10cSrcweir                     pBoundRect->bottom	= nBottom;
931cdf0e10cSrcweir                     bFirstClipRect = false;
932cdf0e10cSrcweir                 }
933cdf0e10cSrcweir                 else
934cdf0e10cSrcweir                 {
935cdf0e10cSrcweir                     if ( nX < pBoundRect->left )
936cdf0e10cSrcweir                         pBoundRect->left = (int)nX;
937cdf0e10cSrcweir 
938cdf0e10cSrcweir                     if ( nY < pBoundRect->top )
939cdf0e10cSrcweir                         pBoundRect->top = (int)nY;
940cdf0e10cSrcweir 
941cdf0e10cSrcweir                     if ( nRight > pBoundRect->right )
942cdf0e10cSrcweir                         pBoundRect->right = (int)nRight;
943cdf0e10cSrcweir 
944cdf0e10cSrcweir                     if ( nBottom > pBoundRect->bottom )
945cdf0e10cSrcweir                         pBoundRect->bottom = (int)nBottom;
946cdf0e10cSrcweir                 }
947cdf0e10cSrcweir 
948cdf0e10cSrcweir                 pNextClipRect->left 	= (int)nX;
949cdf0e10cSrcweir                 pNextClipRect->top		= (int)nY;
950cdf0e10cSrcweir                 pNextClipRect->right	= (int)nRight;
951cdf0e10cSrcweir                 pNextClipRect->bottom	= (int)nBottom;
952cdf0e10cSrcweir                 pNextClipRect++;
953cdf0e10cSrcweir             }
954cdf0e10cSrcweir             else
955cdf0e10cSrcweir             {
956cdf0e10cSrcweir                 mpClipRgnData->rdh.nCount--;
957cdf0e10cSrcweir                 mpClipRgnData->rdh.nRgnSize -= sizeof( RECT );
958cdf0e10cSrcweir             }
959cdf0e10cSrcweir             bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH );
960cdf0e10cSrcweir         }
961cdf0e10cSrcweir         // create clip region from ClipRgnData
962cdf0e10cSrcweir         if ( mpClipRgnData->rdh.nCount == 1 )
963cdf0e10cSrcweir         {
964cdf0e10cSrcweir             RECT* pRect = &(mpClipRgnData->rdh.rcBound);
965cdf0e10cSrcweir             mhRegion = CreateRectRgn( pRect->left, pRect->top,
966cdf0e10cSrcweir                                                      pRect->right, pRect->bottom );
967cdf0e10cSrcweir         }
968cdf0e10cSrcweir         else if( mpClipRgnData->rdh.nCount > 1 )
969cdf0e10cSrcweir         {
970cdf0e10cSrcweir             ULONG nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
971cdf0e10cSrcweir             mhRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
972cdf0e10cSrcweir 
973cdf0e10cSrcweir             // if ExtCreateRegion(...) is not supported
974cdf0e10cSrcweir             if( !mhRegion )
975cdf0e10cSrcweir             {
976cdf0e10cSrcweir                 RGNDATAHEADER* pHeader = (RGNDATAHEADER*) mpClipRgnData;
977cdf0e10cSrcweir 
978cdf0e10cSrcweir                 if( pHeader->nCount )
979cdf0e10cSrcweir                 {
980cdf0e10cSrcweir                     RECT* pRect = (RECT*) mpClipRgnData->Buffer;
981cdf0e10cSrcweir                     mhRegion = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom );
982cdf0e10cSrcweir                     pRect++;
983cdf0e10cSrcweir 
984cdf0e10cSrcweir                     for( ULONG n = 1; n < pHeader->nCount; n++, pRect++ )
985cdf0e10cSrcweir                     {
986cdf0e10cSrcweir                         HRGN hRgn = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom );
987cdf0e10cSrcweir                         CombineRgn( mhRegion, mhRegion, hRgn, RGN_OR );
988cdf0e10cSrcweir                         DeleteRegion( hRgn );
989cdf0e10cSrcweir                     }
990cdf0e10cSrcweir                 }
991cdf0e10cSrcweir             }
992cdf0e10cSrcweir 
993cdf0e10cSrcweir             if ( mpClipRgnData != mpStdClipRgnData )
994cdf0e10cSrcweir                 delete [] mpClipRgnData;
995cdf0e10cSrcweir         }
996cdf0e10cSrcweir 	}
997cdf0e10cSrcweir 
998cdf0e10cSrcweir 	if( mhRegion )
999cdf0e10cSrcweir 	    SelectClipRgn( mhDC, mhRegion );
1000cdf0e10cSrcweir 	return mhRegion != 0;
1001cdf0e10cSrcweir }
1002cdf0e10cSrcweir 
1003cdf0e10cSrcweir // -----------------------------------------------------------------------
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir void WinSalGraphics::SetLineColor()
1006cdf0e10cSrcweir {
1007cdf0e10cSrcweir 	// create and select new pen
1008cdf0e10cSrcweir 	HPEN hNewPen = GetStockPen( NULL_PEN );
1009cdf0e10cSrcweir 	HPEN hOldPen = SelectPen( mhDC, hNewPen );
1010cdf0e10cSrcweir 
1011cdf0e10cSrcweir 	// destory or save old pen
1012cdf0e10cSrcweir 	if ( mhPen )
1013cdf0e10cSrcweir 	{
1014cdf0e10cSrcweir 		if ( !mbStockPen )
1015cdf0e10cSrcweir 			DeletePen( mhPen );
1016cdf0e10cSrcweir 	}
1017cdf0e10cSrcweir 	else
1018cdf0e10cSrcweir 		mhDefPen = hOldPen;
1019cdf0e10cSrcweir 
1020cdf0e10cSrcweir 	// set new data
1021cdf0e10cSrcweir 	mhPen		= hNewPen;
1022cdf0e10cSrcweir 	mbPen		= FALSE;
1023cdf0e10cSrcweir 	mbStockPen	= TRUE;
1024cdf0e10cSrcweir }
1025cdf0e10cSrcweir 
1026cdf0e10cSrcweir // -----------------------------------------------------------------------
1027cdf0e10cSrcweir 
1028cdf0e10cSrcweir void WinSalGraphics::SetLineColor( SalColor nSalColor )
1029cdf0e10cSrcweir {
1030cdf0e10cSrcweir     maLineColor = nSalColor;
1031cdf0e10cSrcweir 	COLORREF	nPenColor = PALETTERGB( SALCOLOR_RED( nSalColor ),
1032cdf0e10cSrcweir 										SALCOLOR_GREEN( nSalColor ),
1033cdf0e10cSrcweir 										SALCOLOR_BLUE( nSalColor ) );
1034cdf0e10cSrcweir 	HPEN		hNewPen = 0;
1035cdf0e10cSrcweir 	sal_Bool		bStockPen = FALSE;
1036cdf0e10cSrcweir 
1037cdf0e10cSrcweir 	// search for stock pen (only screen, because printer have problems,
1038cdf0e10cSrcweir 	// when we use stock objects)
1039cdf0e10cSrcweir 	if ( !mbPrinter )
1040cdf0e10cSrcweir 	{
1041cdf0e10cSrcweir 		SalData* pSalData = GetSalData();
1042cdf0e10cSrcweir 		for ( sal_uInt16 i = 0; i < pSalData->mnStockPenCount; i++ )
1043cdf0e10cSrcweir 		{
1044cdf0e10cSrcweir 			if ( nPenColor == pSalData->maStockPenColorAry[i] )
1045cdf0e10cSrcweir 			{
1046cdf0e10cSrcweir 				hNewPen = pSalData->mhStockPenAry[i];
1047cdf0e10cSrcweir 				bStockPen = TRUE;
1048cdf0e10cSrcweir 				break;
1049cdf0e10cSrcweir 			}
1050cdf0e10cSrcweir 		}
1051cdf0e10cSrcweir 	}
1052cdf0e10cSrcweir 
1053cdf0e10cSrcweir 	// create new pen
1054cdf0e10cSrcweir 	if ( !hNewPen )
1055cdf0e10cSrcweir 	{
1056cdf0e10cSrcweir 		if ( !mbPrinter )
1057cdf0e10cSrcweir 		{
1058cdf0e10cSrcweir 			if ( GetSalData()->mhDitherPal && ImplIsSysColorEntry( nSalColor ) )
1059cdf0e10cSrcweir 				nPenColor = PALRGB_TO_RGB( nPenColor );
1060cdf0e10cSrcweir 		}
1061cdf0e10cSrcweir 
1062cdf0e10cSrcweir 		hNewPen = CreatePen( PS_SOLID, mnPenWidth, nPenColor );
1063cdf0e10cSrcweir 		bStockPen = FALSE;
1064cdf0e10cSrcweir 	}
1065cdf0e10cSrcweir 
1066cdf0e10cSrcweir 	// select new pen
1067cdf0e10cSrcweir 	HPEN hOldPen = SelectPen( mhDC, hNewPen );
1068cdf0e10cSrcweir 
1069cdf0e10cSrcweir 	// destory or save old pen
1070cdf0e10cSrcweir 	if ( mhPen )
1071cdf0e10cSrcweir 	{
1072cdf0e10cSrcweir 		if ( !mbStockPen )
1073cdf0e10cSrcweir 			DeletePen( mhPen );
1074cdf0e10cSrcweir 	}
1075cdf0e10cSrcweir 	else
1076cdf0e10cSrcweir 		mhDefPen = hOldPen;
1077cdf0e10cSrcweir 
1078cdf0e10cSrcweir 	// set new data
1079cdf0e10cSrcweir 	mnPenColor	= nPenColor;
1080cdf0e10cSrcweir 	mhPen		= hNewPen;
1081cdf0e10cSrcweir 	mbPen		= TRUE;
1082cdf0e10cSrcweir 	mbStockPen	= bStockPen;
1083cdf0e10cSrcweir }
1084cdf0e10cSrcweir 
1085cdf0e10cSrcweir // -----------------------------------------------------------------------
1086cdf0e10cSrcweir 
1087cdf0e10cSrcweir void WinSalGraphics::SetFillColor()
1088cdf0e10cSrcweir {
1089cdf0e10cSrcweir 	// create and select new brush
1090cdf0e10cSrcweir 	HBRUSH hNewBrush = GetStockBrush( NULL_BRUSH );
1091cdf0e10cSrcweir 	HBRUSH hOldBrush = SelectBrush( mhDC, hNewBrush );
1092cdf0e10cSrcweir 
1093cdf0e10cSrcweir 	// destory or save old brush
1094cdf0e10cSrcweir 	if ( mhBrush )
1095cdf0e10cSrcweir 	{
1096cdf0e10cSrcweir 		if ( !mbStockBrush )
1097cdf0e10cSrcweir 			DeleteBrush( mhBrush );
1098cdf0e10cSrcweir 	}
1099cdf0e10cSrcweir 	else
1100cdf0e10cSrcweir 		mhDefBrush = hOldBrush;
1101cdf0e10cSrcweir 
1102cdf0e10cSrcweir 	// set new data
1103cdf0e10cSrcweir 	mhBrush		= hNewBrush;
1104cdf0e10cSrcweir 	mbBrush		= FALSE;
1105cdf0e10cSrcweir 	mbStockBrush = TRUE;
1106cdf0e10cSrcweir }
1107cdf0e10cSrcweir 
1108cdf0e10cSrcweir // -----------------------------------------------------------------------
1109cdf0e10cSrcweir 
1110cdf0e10cSrcweir void WinSalGraphics::SetFillColor( SalColor nSalColor )
1111cdf0e10cSrcweir {
1112cdf0e10cSrcweir     maFillColor = nSalColor;
1113cdf0e10cSrcweir 	SalData*	pSalData	= GetSalData();
1114cdf0e10cSrcweir 	BYTE		nRed		= SALCOLOR_RED( nSalColor );
1115cdf0e10cSrcweir 	BYTE		nGreen		= SALCOLOR_GREEN( nSalColor );
1116cdf0e10cSrcweir 	BYTE		nBlue		= SALCOLOR_BLUE( nSalColor );
1117cdf0e10cSrcweir 	COLORREF	nBrushColor = PALETTERGB( nRed, nGreen, nBlue );
1118cdf0e10cSrcweir 	HBRUSH		hNewBrush	= 0;
1119cdf0e10cSrcweir 	sal_Bool		bStockBrush = FALSE;
1120cdf0e10cSrcweir 
1121cdf0e10cSrcweir 	// search for stock brush (only screen, because printer have problems,
1122cdf0e10cSrcweir 	// when we use stock objects)
1123cdf0e10cSrcweir 	if ( !mbPrinter )
1124cdf0e10cSrcweir 	{
1125cdf0e10cSrcweir 		for ( sal_uInt16 i = 0; i < pSalData->mnStockBrushCount; i++ )
1126cdf0e10cSrcweir 		{
1127cdf0e10cSrcweir 			if ( nBrushColor == pSalData->maStockBrushColorAry[ i ] )
1128cdf0e10cSrcweir 			{
1129cdf0e10cSrcweir 				hNewBrush = pSalData->mhStockBrushAry[i];
1130cdf0e10cSrcweir 				bStockBrush = TRUE;
1131cdf0e10cSrcweir 				break;
1132cdf0e10cSrcweir 			}
1133cdf0e10cSrcweir 		}
1134cdf0e10cSrcweir 	}
1135cdf0e10cSrcweir 
1136cdf0e10cSrcweir 	// create new brush
1137cdf0e10cSrcweir 	if ( !hNewBrush )
1138cdf0e10cSrcweir 	{
1139cdf0e10cSrcweir 		if ( mbPrinter || !pSalData->mhDitherDIB )
1140cdf0e10cSrcweir 			hNewBrush = CreateSolidBrush( nBrushColor );
1141cdf0e10cSrcweir 		else
1142cdf0e10cSrcweir 		{
1143cdf0e10cSrcweir 			if ( 24 == ((BITMAPINFOHEADER*)pSalData->mpDitherDIB)->biBitCount )
1144cdf0e10cSrcweir 			{
1145cdf0e10cSrcweir 				BYTE* pTmp = pSalData->mpDitherDIBData;
1146cdf0e10cSrcweir 				long* pDitherDiff = pSalData->mpDitherDiff;
1147cdf0e10cSrcweir 				BYTE* pDitherLow = pSalData->mpDitherLow;
1148cdf0e10cSrcweir 				BYTE* pDitherHigh = pSalData->mpDitherHigh;
1149cdf0e10cSrcweir 
1150cdf0e10cSrcweir 				for( long nY = 0L; nY < 8L; nY++ )
1151cdf0e10cSrcweir 				{
1152cdf0e10cSrcweir 					for( long nX = 0L; nX < 8L; nX++ )
1153cdf0e10cSrcweir 					{
1154cdf0e10cSrcweir 						const long nThres = aOrdDither16Bit[ nY ][ nX ];
1155cdf0e10cSrcweir 						*pTmp++ = DMAP( nBlue, nThres );
1156cdf0e10cSrcweir 						*pTmp++ = DMAP( nGreen, nThres );
1157cdf0e10cSrcweir 						*pTmp++ = DMAP( nRed, nThres );
1158cdf0e10cSrcweir 					}
1159cdf0e10cSrcweir 				}
1160cdf0e10cSrcweir 
1161cdf0e10cSrcweir 				hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_RGB_COLORS );
1162cdf0e10cSrcweir 			}
1163cdf0e10cSrcweir 			else if ( ImplIsSysColorEntry( nSalColor ) )
1164cdf0e10cSrcweir 			{
1165cdf0e10cSrcweir 				nBrushColor = PALRGB_TO_RGB( nBrushColor );
1166cdf0e10cSrcweir 				hNewBrush = CreateSolidBrush( nBrushColor );
1167cdf0e10cSrcweir 			}
1168cdf0e10cSrcweir 			else if ( ImplIsPaletteEntry( nRed, nGreen, nBlue ) )
1169cdf0e10cSrcweir 				hNewBrush = CreateSolidBrush( nBrushColor );
1170cdf0e10cSrcweir 			else
1171cdf0e10cSrcweir 			{
1172cdf0e10cSrcweir 				BYTE* pTmp = pSalData->mpDitherDIBData;
1173cdf0e10cSrcweir 				long* pDitherDiff = pSalData->mpDitherDiff;
1174cdf0e10cSrcweir 				BYTE* pDitherLow = pSalData->mpDitherLow;
1175cdf0e10cSrcweir 				BYTE* pDitherHigh = pSalData->mpDitherHigh;
1176cdf0e10cSrcweir 
1177cdf0e10cSrcweir 				for ( long nY = 0L; nY < 8L; nY++ )
1178cdf0e10cSrcweir 				{
1179cdf0e10cSrcweir 					for ( long nX = 0L; nX < 8L; nX++ )
1180cdf0e10cSrcweir 					{
1181cdf0e10cSrcweir 						const long nThres = aOrdDither8Bit[ nY ][ nX ];
1182cdf0e10cSrcweir 						*pTmp = DMAP( nRed, nThres ) + DMAP( nGreen, nThres ) * 6 + DMAP( nBlue, nThres ) * 36;
1183cdf0e10cSrcweir 						pTmp++;
1184cdf0e10cSrcweir 					}
1185cdf0e10cSrcweir 				}
1186cdf0e10cSrcweir 
1187cdf0e10cSrcweir 				hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_PAL_COLORS );
1188cdf0e10cSrcweir 			}
1189cdf0e10cSrcweir 		}
1190cdf0e10cSrcweir 
1191cdf0e10cSrcweir 		bStockBrush = FALSE;
1192cdf0e10cSrcweir 	}
1193cdf0e10cSrcweir 
1194cdf0e10cSrcweir 	// select new brush
1195cdf0e10cSrcweir 	HBRUSH hOldBrush = SelectBrush( mhDC, hNewBrush );
1196cdf0e10cSrcweir 
1197cdf0e10cSrcweir 	// destory or save old brush
1198cdf0e10cSrcweir 	if ( mhBrush )
1199cdf0e10cSrcweir 	{
1200cdf0e10cSrcweir 		if ( !mbStockBrush )
1201cdf0e10cSrcweir 			DeleteBrush( mhBrush );
1202cdf0e10cSrcweir 	}
1203cdf0e10cSrcweir 	else
1204cdf0e10cSrcweir 		mhDefBrush = hOldBrush;
1205cdf0e10cSrcweir 
1206cdf0e10cSrcweir 	// set new data
1207cdf0e10cSrcweir 	mnBrushColor = nBrushColor;
1208cdf0e10cSrcweir 	mhBrush		= hNewBrush;
1209cdf0e10cSrcweir 	mbBrush		= TRUE;
1210cdf0e10cSrcweir 	mbStockBrush = bStockBrush;
1211cdf0e10cSrcweir }
1212cdf0e10cSrcweir 
1213cdf0e10cSrcweir // -----------------------------------------------------------------------
1214cdf0e10cSrcweir 
1215cdf0e10cSrcweir void WinSalGraphics::SetXORMode( bool bSet, bool )
1216cdf0e10cSrcweir {
1217cdf0e10cSrcweir 	mbXORMode = bSet;
1218cdf0e10cSrcweir 	::SetROP2( mhDC, bSet ? R2_XORPEN : R2_COPYPEN );
1219cdf0e10cSrcweir }
1220cdf0e10cSrcweir 
1221cdf0e10cSrcweir // -----------------------------------------------------------------------
1222cdf0e10cSrcweir 
1223cdf0e10cSrcweir void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor )
1224cdf0e10cSrcweir {
1225cdf0e10cSrcweir 	SetLineColor( ImplGetROPSalColor( nROPColor ) );
1226cdf0e10cSrcweir }
1227cdf0e10cSrcweir 
1228cdf0e10cSrcweir // -----------------------------------------------------------------------
1229cdf0e10cSrcweir 
1230cdf0e10cSrcweir void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor )
1231cdf0e10cSrcweir {
1232cdf0e10cSrcweir 	SetFillColor( ImplGetROPSalColor( nROPColor ) );
1233cdf0e10cSrcweir }
1234cdf0e10cSrcweir 
1235cdf0e10cSrcweir // -----------------------------------------------------------------------
1236cdf0e10cSrcweir 
1237cdf0e10cSrcweir void WinSalGraphics::drawPixel( long nX, long nY )
1238cdf0e10cSrcweir {
1239cdf0e10cSrcweir 	if ( mbXORMode )
1240cdf0e10cSrcweir 	{
1241cdf0e10cSrcweir 		HBRUSH	hBrush = CreateSolidBrush( mnPenColor );
1242cdf0e10cSrcweir 		HBRUSH	hOldBrush = SelectBrush( mhDC, hBrush );
1243cdf0e10cSrcweir 		PatBlt( mhDC, (int)nX, (int)nY, (int)1, (int)1, PATINVERT );
1244cdf0e10cSrcweir 		SelectBrush( mhDC, hOldBrush );
1245cdf0e10cSrcweir 		DeleteBrush( hBrush );
1246cdf0e10cSrcweir 	}
1247cdf0e10cSrcweir 	else
1248cdf0e10cSrcweir 		SetPixel( mhDC, (int)nX, (int)nY, mnPenColor );
1249cdf0e10cSrcweir }
1250cdf0e10cSrcweir 
1251cdf0e10cSrcweir // -----------------------------------------------------------------------
1252cdf0e10cSrcweir 
1253cdf0e10cSrcweir void WinSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor )
1254cdf0e10cSrcweir {
1255cdf0e10cSrcweir 	COLORREF nCol = PALETTERGB( SALCOLOR_RED( nSalColor ),
1256cdf0e10cSrcweir 								SALCOLOR_GREEN( nSalColor ),
1257cdf0e10cSrcweir 								SALCOLOR_BLUE( nSalColor ) );
1258cdf0e10cSrcweir 
1259cdf0e10cSrcweir 	if ( !mbPrinter &&
1260cdf0e10cSrcweir 		 GetSalData()->mhDitherPal &&
1261cdf0e10cSrcweir 		 ImplIsSysColorEntry( nSalColor ) )
1262cdf0e10cSrcweir 		nCol = PALRGB_TO_RGB( nCol );
1263cdf0e10cSrcweir 
1264cdf0e10cSrcweir 	if ( mbXORMode )
1265cdf0e10cSrcweir 	{
1266cdf0e10cSrcweir 		HBRUSH	hBrush = CreateSolidBrush( nCol );
1267cdf0e10cSrcweir 		HBRUSH	hOldBrush = SelectBrush( mhDC, hBrush );
1268cdf0e10cSrcweir 		PatBlt( mhDC, (int)nX, (int)nY, (int)1, (int)1, PATINVERT );
1269cdf0e10cSrcweir 		SelectBrush( mhDC, hOldBrush );
1270cdf0e10cSrcweir 		DeleteBrush( hBrush );
1271cdf0e10cSrcweir 	}
1272cdf0e10cSrcweir 	else
1273cdf0e10cSrcweir 		::SetPixel( mhDC, (int)nX, (int)nY, nCol );
1274cdf0e10cSrcweir }
1275cdf0e10cSrcweir 
1276cdf0e10cSrcweir // -----------------------------------------------------------------------
1277cdf0e10cSrcweir 
1278cdf0e10cSrcweir void WinSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
1279cdf0e10cSrcweir {
1280cdf0e10cSrcweir 	MoveToEx( mhDC, (int)nX1, (int)nY1, NULL );
1281cdf0e10cSrcweir 
1282cdf0e10cSrcweir 	// we must paint the endpoint
1283cdf0e10cSrcweir 	int bPaintEnd = TRUE;
1284cdf0e10cSrcweir 	if ( nX1 == nX2 )
1285cdf0e10cSrcweir 	{
1286cdf0e10cSrcweir 		bPaintEnd = FALSE;
1287cdf0e10cSrcweir 		if ( nY1 <= nY2 )
1288cdf0e10cSrcweir 			nY2++;
1289cdf0e10cSrcweir 		else
1290cdf0e10cSrcweir 			nY2--;
1291cdf0e10cSrcweir 	}
1292cdf0e10cSrcweir 	if ( nY1 == nY2 )
1293cdf0e10cSrcweir 	{
1294cdf0e10cSrcweir 		bPaintEnd = FALSE;
1295cdf0e10cSrcweir 		if ( nX1 <= nX2 )
1296cdf0e10cSrcweir 			nX2++;
1297cdf0e10cSrcweir 		else
1298cdf0e10cSrcweir 			nX2--;
1299cdf0e10cSrcweir 	}
1300cdf0e10cSrcweir 
1301cdf0e10cSrcweir 	LineTo( mhDC, (int)nX2, (int)nY2 );
1302cdf0e10cSrcweir 
1303cdf0e10cSrcweir 	if ( bPaintEnd && !mbPrinter )
1304cdf0e10cSrcweir 	{
1305cdf0e10cSrcweir 		if ( mbXORMode )
1306cdf0e10cSrcweir 		{
1307cdf0e10cSrcweir 			HBRUSH	hBrush = CreateSolidBrush( mnPenColor );
1308cdf0e10cSrcweir 			HBRUSH	hOldBrush = SelectBrush( mhDC, hBrush );
1309cdf0e10cSrcweir 			PatBlt( mhDC, (int)nX2, (int)nY2, (int)1, (int)1, PATINVERT );
1310cdf0e10cSrcweir 			SelectBrush( mhDC, hOldBrush );
1311cdf0e10cSrcweir 			DeleteBrush( hBrush );
1312cdf0e10cSrcweir 		}
1313cdf0e10cSrcweir 		else
1314cdf0e10cSrcweir 			SetPixel( mhDC, (int)nX2, (int)nY2, mnPenColor );
1315cdf0e10cSrcweir 	}
1316cdf0e10cSrcweir }
1317cdf0e10cSrcweir 
1318cdf0e10cSrcweir // -----------------------------------------------------------------------
1319cdf0e10cSrcweir 
1320cdf0e10cSrcweir void WinSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
1321cdf0e10cSrcweir {
1322cdf0e10cSrcweir 	if ( !mbPen )
1323cdf0e10cSrcweir 	{
1324cdf0e10cSrcweir 		if ( !mbPrinter )
1325cdf0e10cSrcweir 		{
1326cdf0e10cSrcweir 			PatBlt( mhDC, (int)nX, (int)nY, (int)nWidth, (int)nHeight,
1327cdf0e10cSrcweir 					mbXORMode ? PATINVERT : PATCOPY );
1328cdf0e10cSrcweir 		}
1329cdf0e10cSrcweir 		else
1330cdf0e10cSrcweir 		{
1331cdf0e10cSrcweir 			RECT aWinRect;
1332cdf0e10cSrcweir 			aWinRect.left	= nX;
1333cdf0e10cSrcweir 			aWinRect.top	= nY;
1334cdf0e10cSrcweir 			aWinRect.right	= nX+nWidth;
1335cdf0e10cSrcweir 			aWinRect.bottom = nY+nHeight;
1336cdf0e10cSrcweir 			::FillRect( mhDC, &aWinRect, mhBrush );
1337cdf0e10cSrcweir 		}
1338cdf0e10cSrcweir 	}
1339cdf0e10cSrcweir 	else
1340cdf0e10cSrcweir 		WIN_Rectangle( mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) );
1341cdf0e10cSrcweir }
1342cdf0e10cSrcweir 
1343cdf0e10cSrcweir // -----------------------------------------------------------------------
1344cdf0e10cSrcweir 
1345cdf0e10cSrcweir void WinSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry )
1346cdf0e10cSrcweir {
1347cdf0e10cSrcweir 	// Unter NT koennen wir das Array direkt weiterreichen
1348cdf0e10cSrcweir 	DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
1349cdf0e10cSrcweir 				"WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
1350cdf0e10cSrcweir 
1351cdf0e10cSrcweir 	POINT* pWinPtAry = (POINT*)pPtAry;
1352cdf0e10cSrcweir 	// Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
1353cdf0e10cSrcweir 	// von Punkten
1354cdf0e10cSrcweir 	if ( !Polyline( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
1355cdf0e10cSrcweir 		Polyline( mhDC, pWinPtAry, MAX_64KSALPOINTS );
1356cdf0e10cSrcweir }
1357cdf0e10cSrcweir 
1358cdf0e10cSrcweir // -----------------------------------------------------------------------
1359cdf0e10cSrcweir 
1360cdf0e10cSrcweir void WinSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry )
1361cdf0e10cSrcweir {
1362cdf0e10cSrcweir 	// Unter NT koennen wir das Array direkt weiterreichen
1363cdf0e10cSrcweir 	DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
1364cdf0e10cSrcweir 				"WinSalGraphics::DrawPolygon(): POINT != SalPoint" );
1365cdf0e10cSrcweir 
1366cdf0e10cSrcweir 	POINT* pWinPtAry = (POINT*)pPtAry;
1367cdf0e10cSrcweir 	// Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
1368cdf0e10cSrcweir 	// von Punkten
1369cdf0e10cSrcweir 	if ( !WIN_Polygon( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) )
1370cdf0e10cSrcweir 		WIN_Polygon( mhDC, pWinPtAry, MAX_64KSALPOINTS );
1371cdf0e10cSrcweir }
1372cdf0e10cSrcweir 
1373cdf0e10cSrcweir // -----------------------------------------------------------------------
1374cdf0e10cSrcweir 
1375cdf0e10cSrcweir void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
1376cdf0e10cSrcweir 								   PCONSTSALPOINT* pPtAry )
1377cdf0e10cSrcweir {
1378cdf0e10cSrcweir 	UINT	aWinPointAry[SAL_POLYPOLYCOUNT_STACKBUF];
1379cdf0e10cSrcweir 	UINT*	pWinPointAry;
1380cdf0e10cSrcweir 	UINT	nPolyPolyPoints = 0;
1381cdf0e10cSrcweir 	UINT	nPoints;
1382cdf0e10cSrcweir 	UINT	i;
1383cdf0e10cSrcweir 
1384cdf0e10cSrcweir 	if ( nPoly <= SAL_POLYPOLYCOUNT_STACKBUF )
1385cdf0e10cSrcweir 		pWinPointAry = aWinPointAry;
1386cdf0e10cSrcweir 	else
1387cdf0e10cSrcweir 		pWinPointAry = new UINT[nPoly];
1388cdf0e10cSrcweir 
1389cdf0e10cSrcweir 	for ( i = 0; i < (UINT)nPoly; i++ )
1390cdf0e10cSrcweir 	{
1391cdf0e10cSrcweir 		nPoints = (UINT)pPoints[i]+1;
1392cdf0e10cSrcweir 		pWinPointAry[i] = nPoints;
1393cdf0e10cSrcweir 		nPolyPolyPoints += nPoints;
1394cdf0e10cSrcweir 	}
1395cdf0e10cSrcweir 
1396cdf0e10cSrcweir 	POINT  aWinPointAryAry[SAL_POLYPOLYPOINTS_STACKBUF];
1397cdf0e10cSrcweir 	POINT* pWinPointAryAry;
1398cdf0e10cSrcweir 	if ( nPolyPolyPoints <= SAL_POLYPOLYPOINTS_STACKBUF )
1399cdf0e10cSrcweir 		pWinPointAryAry = aWinPointAryAry;
1400cdf0e10cSrcweir 	else
1401cdf0e10cSrcweir 		pWinPointAryAry = new POINT[nPolyPolyPoints];
1402cdf0e10cSrcweir 	// Unter NT koennen wir das Array direkt weiterreichen
1403cdf0e10cSrcweir 	DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
1404cdf0e10cSrcweir 				"WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" );
1405cdf0e10cSrcweir 	const SalPoint* pPolyAry;
1406cdf0e10cSrcweir 	UINT			n = 0;
1407cdf0e10cSrcweir 	for ( i = 0; i < (UINT)nPoly; i++ )
1408cdf0e10cSrcweir 	{
1409cdf0e10cSrcweir 		nPoints = pWinPointAry[i];
1410cdf0e10cSrcweir 		pPolyAry = pPtAry[i];
1411cdf0e10cSrcweir 		memcpy( pWinPointAryAry+n, pPolyAry, (nPoints-1)*sizeof(POINT) );
1412cdf0e10cSrcweir 		pWinPointAryAry[n+nPoints-1] = pWinPointAryAry[n];
1413cdf0e10cSrcweir 		n += nPoints;
1414cdf0e10cSrcweir 	}
1415cdf0e10cSrcweir 
1416cdf0e10cSrcweir 	if ( !WIN_PolyPolygon( mhDC, pWinPointAryAry, (int*)pWinPointAry, (UINT)nPoly ) &&
1417cdf0e10cSrcweir 		 (nPolyPolyPoints > MAX_64KSALPOINTS) )
1418cdf0e10cSrcweir 	{
1419cdf0e10cSrcweir 		nPolyPolyPoints  = 0;
1420cdf0e10cSrcweir 		nPoly = 0;
1421cdf0e10cSrcweir 		do
1422cdf0e10cSrcweir 		{
1423cdf0e10cSrcweir 			nPolyPolyPoints += pWinPointAry[(UINT)nPoly];
1424cdf0e10cSrcweir 			nPoly++;
1425cdf0e10cSrcweir 		}
1426cdf0e10cSrcweir 		while ( nPolyPolyPoints < MAX_64KSALPOINTS );
1427cdf0e10cSrcweir 		nPoly--;
1428cdf0e10cSrcweir 		if ( pWinPointAry[(UINT)nPoly] > MAX_64KSALPOINTS )
1429cdf0e10cSrcweir 			pWinPointAry[(UINT)nPoly] = MAX_64KSALPOINTS;
1430cdf0e10cSrcweir 		if ( nPoly == 1 )
1431cdf0e10cSrcweir 			WIN_Polygon( mhDC, pWinPointAryAry, *pWinPointAry );
1432cdf0e10cSrcweir 		else
1433cdf0e10cSrcweir 			WIN_PolyPolygon( mhDC, pWinPointAryAry, (int*)pWinPointAry, nPoly );
1434cdf0e10cSrcweir 	}
1435cdf0e10cSrcweir 
1436cdf0e10cSrcweir 	if ( pWinPointAry != aWinPointAry )
1437cdf0e10cSrcweir 		delete [] pWinPointAry;
1438cdf0e10cSrcweir 	if ( pWinPointAryAry != aWinPointAryAry )
1439cdf0e10cSrcweir 		delete [] pWinPointAryAry;
1440cdf0e10cSrcweir }
1441cdf0e10cSrcweir 
1442cdf0e10cSrcweir // -----------------------------------------------------------------------
1443cdf0e10cSrcweir 
1444cdf0e10cSrcweir #define SAL_POLY_STACKBUF		32
1445cdf0e10cSrcweir 
1446cdf0e10cSrcweir // -----------------------------------------------------------------------
1447cdf0e10cSrcweir 
1448cdf0e10cSrcweir sal_Bool WinSalGraphics::drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry )
1449cdf0e10cSrcweir {
1450cdf0e10cSrcweir #ifdef USE_GDI_BEZIERS
1451cdf0e10cSrcweir 	// Unter NT koennen wir das Array direkt weiterreichen
1452cdf0e10cSrcweir 	DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
1453cdf0e10cSrcweir 				"WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" );
1454cdf0e10cSrcweir 
1455cdf0e10cSrcweir     ImplRenderPath( mhDC, nPoints, pPtAry, pFlgAry );
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir     return sal_True;
1458cdf0e10cSrcweir #else
1459cdf0e10cSrcweir     return sal_False;
1460cdf0e10cSrcweir #endif
1461cdf0e10cSrcweir }
1462cdf0e10cSrcweir 
1463cdf0e10cSrcweir // -----------------------------------------------------------------------
1464cdf0e10cSrcweir 
1465cdf0e10cSrcweir sal_Bool WinSalGraphics::drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry )
1466cdf0e10cSrcweir {
1467cdf0e10cSrcweir #ifdef USE_GDI_BEZIERS
1468cdf0e10cSrcweir 	// Unter NT koennen wir das Array direkt weiterreichen
1469cdf0e10cSrcweir 	DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
1470cdf0e10cSrcweir 				"WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" );
1471cdf0e10cSrcweir 
1472cdf0e10cSrcweir     POINT	aStackAry1[SAL_POLY_STACKBUF];
1473cdf0e10cSrcweir     BYTE	aStackAry2[SAL_POLY_STACKBUF];
1474cdf0e10cSrcweir     POINT* 	pWinPointAry;
1475cdf0e10cSrcweir     BYTE* 	pWinFlagAry;
1476cdf0e10cSrcweir     if( nPoints > SAL_POLY_STACKBUF )
1477cdf0e10cSrcweir     {
1478cdf0e10cSrcweir         pWinPointAry = new POINT[ nPoints ];
1479cdf0e10cSrcweir         pWinFlagAry = new BYTE[ nPoints ];
1480cdf0e10cSrcweir     }
1481cdf0e10cSrcweir     else
1482cdf0e10cSrcweir     {
1483cdf0e10cSrcweir         pWinPointAry = aStackAry1;
1484cdf0e10cSrcweir         pWinFlagAry = aStackAry2;
1485cdf0e10cSrcweir     }
1486cdf0e10cSrcweir 
1487cdf0e10cSrcweir     ImplPreparePolyDraw(true, 1, &nPoints, &pPtAry, &pFlgAry, pWinPointAry, pWinFlagAry);
1488cdf0e10cSrcweir 
1489cdf0e10cSrcweir     sal_Bool bRet( sal_False );
1490cdf0e10cSrcweir 
1491cdf0e10cSrcweir     if( BeginPath( mhDC ) )
1492cdf0e10cSrcweir     {
1493cdf0e10cSrcweir         PolyDraw(mhDC, pWinPointAry, pWinFlagAry, nPoints);
1494cdf0e10cSrcweir 
1495cdf0e10cSrcweir         if( EndPath( mhDC ) )
1496cdf0e10cSrcweir         {
1497cdf0e10cSrcweir             if( StrokeAndFillPath( mhDC ) )
1498cdf0e10cSrcweir                 bRet = sal_True;
1499cdf0e10cSrcweir         }
1500cdf0e10cSrcweir     }
1501cdf0e10cSrcweir 
1502cdf0e10cSrcweir     if( pWinPointAry != aStackAry1 )
1503cdf0e10cSrcweir     {
1504cdf0e10cSrcweir         delete [] pWinPointAry;
1505cdf0e10cSrcweir         delete [] pWinFlagAry;
1506cdf0e10cSrcweir     }
1507cdf0e10cSrcweir 
1508cdf0e10cSrcweir     return bRet;
1509cdf0e10cSrcweir #else
1510cdf0e10cSrcweir     return sal_False;
1511cdf0e10cSrcweir #endif
1512cdf0e10cSrcweir }
1513cdf0e10cSrcweir 
1514cdf0e10cSrcweir // -----------------------------------------------------------------------
1515cdf0e10cSrcweir 
1516cdf0e10cSrcweir sal_Bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints,
1517cdf0e10cSrcweir                                              const SalPoint* const* pPtAry, const BYTE* const* pFlgAry )
1518cdf0e10cSrcweir {
1519cdf0e10cSrcweir #ifdef USE_GDI_BEZIERS
1520cdf0e10cSrcweir 	// Unter NT koennen wir das Array direkt weiterreichen
1521cdf0e10cSrcweir 	DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ),
1522cdf0e10cSrcweir 				"WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" );
1523cdf0e10cSrcweir 
1524cdf0e10cSrcweir     sal_uLong nCurrPoly, nTotalPoints;
1525cdf0e10cSrcweir     const sal_uLong* pCurrPoints = pPoints;
1526cdf0e10cSrcweir     for( nCurrPoly=0, nTotalPoints=0; nCurrPoly<nPoly; ++nCurrPoly )
1527cdf0e10cSrcweir         nTotalPoints += *pCurrPoints++;
1528cdf0e10cSrcweir 
1529cdf0e10cSrcweir     POINT	aStackAry1[SAL_POLY_STACKBUF];
1530cdf0e10cSrcweir     BYTE	aStackAry2[SAL_POLY_STACKBUF];
1531cdf0e10cSrcweir     POINT* 	pWinPointAry;
1532cdf0e10cSrcweir     BYTE* 	pWinFlagAry;
1533cdf0e10cSrcweir     if( nTotalPoints > SAL_POLY_STACKBUF )
1534cdf0e10cSrcweir     {
1535cdf0e10cSrcweir         pWinPointAry = new POINT[ nTotalPoints ];
1536cdf0e10cSrcweir         pWinFlagAry = new BYTE[ nTotalPoints ];
1537cdf0e10cSrcweir     }
1538cdf0e10cSrcweir     else
1539cdf0e10cSrcweir     {
1540cdf0e10cSrcweir         pWinPointAry = aStackAry1;
1541cdf0e10cSrcweir         pWinFlagAry = aStackAry2;
1542cdf0e10cSrcweir     }
1543cdf0e10cSrcweir 
1544cdf0e10cSrcweir     ImplPreparePolyDraw(true, nPoly, pPoints, pPtAry, pFlgAry, pWinPointAry, pWinFlagAry);
1545cdf0e10cSrcweir 
1546cdf0e10cSrcweir     sal_Bool bRet( sal_False );
1547cdf0e10cSrcweir 
1548cdf0e10cSrcweir     if( BeginPath( mhDC ) )
1549cdf0e10cSrcweir     {
1550cdf0e10cSrcweir         PolyDraw(mhDC, pWinPointAry, pWinFlagAry, nTotalPoints);
1551cdf0e10cSrcweir 
1552cdf0e10cSrcweir         if( EndPath( mhDC ) )
1553cdf0e10cSrcweir         {
1554cdf0e10cSrcweir             if( StrokeAndFillPath( mhDC ) )
1555cdf0e10cSrcweir                 bRet = sal_True;
1556cdf0e10cSrcweir         }
1557cdf0e10cSrcweir     }
1558cdf0e10cSrcweir 
1559cdf0e10cSrcweir     if( pWinPointAry != aStackAry1 )
1560cdf0e10cSrcweir     {
1561cdf0e10cSrcweir         delete [] pWinPointAry;
1562cdf0e10cSrcweir         delete [] pWinFlagAry;
1563cdf0e10cSrcweir     }
1564cdf0e10cSrcweir 
1565cdf0e10cSrcweir     return bRet;
1566cdf0e10cSrcweir #else
1567cdf0e10cSrcweir     return sal_False;
1568cdf0e10cSrcweir #endif
1569cdf0e10cSrcweir }
1570cdf0e10cSrcweir 
1571cdf0e10cSrcweir // -----------------------------------------------------------------------
1572cdf0e10cSrcweir 
1573cdf0e10cSrcweir #define POSTSCRIPT_BUFSIZE 0x4000			// MAXIMUM BUFSIZE EQ 0xFFFF
1574cdf0e10cSrcweir #define POSTSCRIPT_BOUNDINGSEARCH 0x1000	// we only try to get the BoundingBox
1575cdf0e10cSrcweir 											// in the first 4096 bytes
1576cdf0e10cSrcweir 
1577cdf0e10cSrcweir static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, sal_uLong nComp, sal_uLong nSize )
1578cdf0e10cSrcweir {
1579cdf0e10cSrcweir 	while ( nComp-- >= nSize )
1580cdf0e10cSrcweir 	{
1581cdf0e10cSrcweir 		sal_uLong i;
1582cdf0e10cSrcweir 		for ( i = 0; i < nSize; i++ )
1583cdf0e10cSrcweir 		{
1584cdf0e10cSrcweir 			if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
1585cdf0e10cSrcweir 				break;
1586cdf0e10cSrcweir 		}
1587cdf0e10cSrcweir 		if ( i == nSize )
1588cdf0e10cSrcweir 			return pSource;
1589cdf0e10cSrcweir 		pSource++;
1590cdf0e10cSrcweir 	}
1591cdf0e10cSrcweir 	return NULL;
1592cdf0e10cSrcweir }
1593cdf0e10cSrcweir 
1594cdf0e10cSrcweir static sal_Bool ImplGetBoundingBox( double* nNumb, BYTE* pSource, sal_uLong nSize )
1595cdf0e10cSrcweir {
1596cdf0e10cSrcweir 	sal_Bool	bRetValue = FALSE;
1597cdf0e10cSrcweir 	BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 );
1598cdf0e10cSrcweir 	if ( pDest )
1599cdf0e10cSrcweir 	{
1600cdf0e10cSrcweir 		nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
1601cdf0e10cSrcweir 		pDest += 14;
1602cdf0e10cSrcweir 
1603cdf0e10cSrcweir 		int nSizeLeft = nSize - ( pDest - pSource );
1604cdf0e10cSrcweir 		if ( nSizeLeft > 100 )
1605cdf0e10cSrcweir 			nSizeLeft = 100;	// only 100 bytes following the bounding box will be checked
1606cdf0e10cSrcweir 
1607cdf0e10cSrcweir 		int i;
1608cdf0e10cSrcweir 		for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
1609cdf0e10cSrcweir 		{
1610cdf0e10cSrcweir 			int 	nDivision = 1;
1611cdf0e10cSrcweir 			sal_Bool	bDivision = FALSE;
1612cdf0e10cSrcweir 			sal_Bool	bNegative = FALSE;
1613cdf0e10cSrcweir 			sal_Bool	bValid = TRUE;
1614cdf0e10cSrcweir 
1615cdf0e10cSrcweir 			while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++;
1616cdf0e10cSrcweir 			BYTE nByte = *pDest;
1617cdf0e10cSrcweir 			while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
1618cdf0e10cSrcweir 			{
1619cdf0e10cSrcweir 				switch ( nByte )
1620cdf0e10cSrcweir 				{
1621cdf0e10cSrcweir 					case '.' :
1622cdf0e10cSrcweir 						if ( bDivision )
1623cdf0e10cSrcweir 							bValid = FALSE;
1624cdf0e10cSrcweir 						else
1625cdf0e10cSrcweir 							bDivision = TRUE;
1626cdf0e10cSrcweir 						break;
1627cdf0e10cSrcweir 					case '-' :
1628cdf0e10cSrcweir 						bNegative = TRUE;
1629cdf0e10cSrcweir 						break;
1630cdf0e10cSrcweir 					default :
1631cdf0e10cSrcweir 						if ( ( nByte < '0' ) || ( nByte > '9' ) )
1632cdf0e10cSrcweir 							nSizeLeft = 1; 	// error parsing the bounding box values
1633cdf0e10cSrcweir 						else if ( bValid )
1634cdf0e10cSrcweir 						{
1635cdf0e10cSrcweir 							if ( bDivision )
1636cdf0e10cSrcweir 								nDivision*=10;
1637cdf0e10cSrcweir 							nNumb[i] *= 10;
1638cdf0e10cSrcweir 							nNumb[i] += nByte - '0';
1639cdf0e10cSrcweir 						}
1640cdf0e10cSrcweir 						break;
1641cdf0e10cSrcweir 				}
1642cdf0e10cSrcweir 				nSizeLeft--;
1643cdf0e10cSrcweir 				nByte = *(++pDest);
1644cdf0e10cSrcweir 			}
1645cdf0e10cSrcweir 			if ( bNegative )
1646cdf0e10cSrcweir 				nNumb[i] = -nNumb[i];
1647cdf0e10cSrcweir 			if ( bDivision && ( nDivision != 1 ) )
1648cdf0e10cSrcweir 				nNumb[i] /= nDivision;
1649cdf0e10cSrcweir 		}
1650cdf0e10cSrcweir 		if ( i == 4 )
1651cdf0e10cSrcweir 			bRetValue = TRUE;
1652cdf0e10cSrcweir 	}
1653cdf0e10cSrcweir 	return bRetValue;
1654cdf0e10cSrcweir }
1655cdf0e10cSrcweir 
1656cdf0e10cSrcweir sal_Bool WinSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize )
1657cdf0e10cSrcweir {
1658cdf0e10cSrcweir 	sal_Bool bRetValue = FALSE;
1659cdf0e10cSrcweir 
1660cdf0e10cSrcweir 	if ( mbPrinter )
1661cdf0e10cSrcweir 	{
1662cdf0e10cSrcweir 		int nEscape = POSTSCRIPT_PASSTHROUGH;
1663cdf0e10cSrcweir 
1664cdf0e10cSrcweir 		if ( Escape( mhDC, QUERYESCSUPPORT, sizeof( int ), ( LPSTR )&nEscape, 0 ) )
1665cdf0e10cSrcweir 		{
1666cdf0e10cSrcweir 			double	nBoundingBox[4];
1667cdf0e10cSrcweir 
1668cdf0e10cSrcweir 			if ( ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) )
1669cdf0e10cSrcweir 			{
1670cdf0e10cSrcweir                 OStringBuffer aBuf( POSTSCRIPT_BUFSIZE );
1671cdf0e10cSrcweir 
1672cdf0e10cSrcweir                 // reserve place for a sal_uInt16
1673cdf0e10cSrcweir                 aBuf.append( "aa" );
1674cdf0e10cSrcweir 
1675cdf0e10cSrcweir                 // #107797# Write out EPS encapsulation header
1676cdf0e10cSrcweir                 // ----------------------------------------------------------------------------------
1677cdf0e10cSrcweir 
1678cdf0e10cSrcweir                 // directly taken from the PLRM 3.0, p. 726. Note:
1679cdf0e10cSrcweir                 // this will definitely cause problems when
1680cdf0e10cSrcweir                 // recursively creating and embedding PostScript files
1681cdf0e10cSrcweir                 // in OOo, since we use statically-named variables
1682cdf0e10cSrcweir                 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
1683cdf0e10cSrcweir                 // op_count_salWin). Currently, I have no idea on how to
1684cdf0e10cSrcweir                 // work around that, except from scanning and
1685cdf0e10cSrcweir                 // interpreting the EPS for unused identifiers.
1686cdf0e10cSrcweir 
1687cdf0e10cSrcweir                 // append the real text
1688cdf0e10cSrcweir                 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n"
1689cdf0e10cSrcweir                              "/dict_count_salWin countdictstack def\n"
1690cdf0e10cSrcweir                              "/op_count_salWin count 1 sub def\n"
1691cdf0e10cSrcweir                              "userdict begin\n"
1692cdf0e10cSrcweir                              "/showpage {} def\n"
1693cdf0e10cSrcweir                              "0 setgray 0 setlinecap\n"
1694cdf0e10cSrcweir                              "1 setlinewidth 0 setlinejoin\n"
1695cdf0e10cSrcweir                              "10 setmiterlimit [] 0 setdash newpath\n"
1696cdf0e10cSrcweir                              "/languagelevel where\n"
1697cdf0e10cSrcweir                              "{\n"
1698cdf0e10cSrcweir                              "  pop languagelevel\n"
1699cdf0e10cSrcweir                              "  1 ne\n"
1700cdf0e10cSrcweir                              "  {\n"
1701cdf0e10cSrcweir                              "    false setstrokeadjust false setoverprint\n"
1702cdf0e10cSrcweir                              "  } if\n"
1703cdf0e10cSrcweir                              "} if\n\n" );
1704cdf0e10cSrcweir 
1705cdf0e10cSrcweir 
1706cdf0e10cSrcweir                 // #i10737# Apply clipping manually
1707cdf0e10cSrcweir                 // ----------------------------------------------------------------------------------
1708cdf0e10cSrcweir 
1709cdf0e10cSrcweir                 // Windows seems to ignore any clipping at the HDC,
1710cdf0e10cSrcweir                 // when followed by a POSTSCRIPT_PASSTHROUGH
1711cdf0e10cSrcweir 
1712cdf0e10cSrcweir                 // Check whether we've got a clipping, consisting of
1713cdf0e10cSrcweir                 // exactly one rect (other cases should be, but aren't
1714cdf0e10cSrcweir                 // handled currently)
1715cdf0e10cSrcweir 
1716cdf0e10cSrcweir                 // TODO: Handle more than one rectangle here (take
1717cdf0e10cSrcweir                 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
1718cdf0e10cSrcweir                 // characters!)
1719cdf0e10cSrcweir                 if ( mhRegion != 0 &&
1720cdf0e10cSrcweir                      mpStdClipRgnData != NULL &&
1721cdf0e10cSrcweir                      mpClipRgnData == mpStdClipRgnData &&
1722cdf0e10cSrcweir                      mpClipRgnData->rdh.nCount == 1 )
1723cdf0e10cSrcweir                 {
1724cdf0e10cSrcweir                     RECT* pRect = &(mpClipRgnData->rdh.rcBound);
1725cdf0e10cSrcweir 
1726cdf0e10cSrcweir                     aBuf.append( "\nnewpath\n" );
1727cdf0e10cSrcweir                     aBuf.append( pRect->left );
1728cdf0e10cSrcweir                     aBuf.append( " " );
1729cdf0e10cSrcweir                     aBuf.append( pRect->top );
1730cdf0e10cSrcweir                     aBuf.append( " moveto\n" );
1731cdf0e10cSrcweir                     aBuf.append( pRect->right );
1732cdf0e10cSrcweir                     aBuf.append( " " );
1733cdf0e10cSrcweir                     aBuf.append( pRect->top );
1734cdf0e10cSrcweir                     aBuf.append( " lineto\n" );
1735cdf0e10cSrcweir                     aBuf.append( pRect->right );
1736cdf0e10cSrcweir                     aBuf.append( " " );
1737cdf0e10cSrcweir                     aBuf.append( pRect->bottom );
1738cdf0e10cSrcweir                     aBuf.append( " lineto\n" );
1739cdf0e10cSrcweir                     aBuf.append( pRect->left );
1740cdf0e10cSrcweir                     aBuf.append( " " );
1741cdf0e10cSrcweir                     aBuf.append( pRect->bottom );
1742cdf0e10cSrcweir                     aBuf.append( " lineto\n"
1743cdf0e10cSrcweir                                  "closepath\n"
1744cdf0e10cSrcweir                                  "clip\n"
1745cdf0e10cSrcweir                                  "newpath\n" );
1746cdf0e10cSrcweir                 }
1747cdf0e10cSrcweir 
1748cdf0e10cSrcweir                 // #107797# Write out buffer
1749cdf0e10cSrcweir                 // ----------------------------------------------------------------------------------
1750cdf0e10cSrcweir 				*((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 );
1751cdf0e10cSrcweir 				Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
1752cdf0e10cSrcweir 
1753cdf0e10cSrcweir 
1754cdf0e10cSrcweir                 // #107797# Write out EPS transformation code
1755cdf0e10cSrcweir                 // ----------------------------------------------------------------------------------
1756cdf0e10cSrcweir 				double	dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] );
1757cdf0e10cSrcweir 				double	dM22 = nHeight / (nBoundingBox[1] - nBoundingBox[3] );
1758cdf0e10cSrcweir                 // reserve a sal_uInt16 again
1759cdf0e10cSrcweir                 aBuf.setLength( 2 );
1760cdf0e10cSrcweir                 aBuf.append( "\n\n[" );
1761cdf0e10cSrcweir                 aBuf.append( dM11 );
1762cdf0e10cSrcweir                 aBuf.append( " 0 0 " );
1763cdf0e10cSrcweir                 aBuf.append( dM22 );
1764cdf0e10cSrcweir                 aBuf.append( ' ' );
1765cdf0e10cSrcweir                 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
1766cdf0e10cSrcweir                 aBuf.append( ' ' );
1767cdf0e10cSrcweir                 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) );
1768cdf0e10cSrcweir                 aBuf.append( "] concat\n"
1769cdf0e10cSrcweir                              "%%BeginDocument:\n" );
1770cdf0e10cSrcweir 				*((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 );
1771cdf0e10cSrcweir 				Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
1772cdf0e10cSrcweir 
1773cdf0e10cSrcweir 
1774cdf0e10cSrcweir                 // #107797# Write out actual EPS content
1775cdf0e10cSrcweir                 // ----------------------------------------------------------------------------------
1776cdf0e10cSrcweir 				sal_uLong	nToDo = nSize;
1777cdf0e10cSrcweir 				sal_uLong	nDoNow;
1778cdf0e10cSrcweir 				while ( nToDo )
1779cdf0e10cSrcweir 				{
1780cdf0e10cSrcweir 					nDoNow = nToDo;
1781cdf0e10cSrcweir 					if ( nToDo > POSTSCRIPT_BUFSIZE - 2 )
1782cdf0e10cSrcweir 						nDoNow = POSTSCRIPT_BUFSIZE - 2;
1783cdf0e10cSrcweir                     // the following is based on the string buffer allocation
1784cdf0e10cSrcweir                     // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1785cdf0e10cSrcweir 					*((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)nDoNow;
1786cdf0e10cSrcweir 					memcpy( (void*)(aBuf.getStr() + 2), (BYTE*)pPtr + nSize - nToDo, nDoNow );
1787cdf0e10cSrcweir 					sal_uLong nResult = Escape ( mhDC, nEscape, nDoNow + 2, (LPTSTR)aBuf.getStr(), 0 );
1788cdf0e10cSrcweir 					if (!nResult )
1789cdf0e10cSrcweir 						break;
1790cdf0e10cSrcweir 					nToDo -= nResult;
1791cdf0e10cSrcweir 				}
1792cdf0e10cSrcweir 
1793cdf0e10cSrcweir 
1794cdf0e10cSrcweir                 // #107797# Write out EPS encapsulation footer
1795cdf0e10cSrcweir                 // ----------------------------------------------------------------------------------
1796cdf0e10cSrcweir                 // reserve a sal_uInt16 again
1797cdf0e10cSrcweir                 aBuf.setLength( 2 );
1798cdf0e10cSrcweir                 aBuf.append( "%%EndDocument\n"
1799cdf0e10cSrcweir                              "count op_count_salWin sub {pop} repeat\n"
1800cdf0e10cSrcweir                              "countdictstack dict_count_salWin sub {end} repeat\n"
1801cdf0e10cSrcweir                              "b4_Inc_state_salWin restore\n\n" );
1802cdf0e10cSrcweir 				*((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 );
1803cdf0e10cSrcweir 				Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 );
1804cdf0e10cSrcweir 				bRetValue = TRUE;
1805cdf0e10cSrcweir 			}
1806cdf0e10cSrcweir 		}
1807cdf0e10cSrcweir 	}
1808cdf0e10cSrcweir 
1809cdf0e10cSrcweir 	return bRetValue;
1810cdf0e10cSrcweir }
1811cdf0e10cSrcweir 
1812cdf0e10cSrcweir // -----------------------------------------------------------------------
1813cdf0e10cSrcweir 
1814cdf0e10cSrcweir SystemGraphicsData WinSalGraphics::GetGraphicsData() const
1815cdf0e10cSrcweir {
1816cdf0e10cSrcweir     SystemGraphicsData aRes;
1817cdf0e10cSrcweir     aRes.nSize = sizeof(aRes);
1818cdf0e10cSrcweir     aRes.hDC = mhDC;
1819cdf0e10cSrcweir     return aRes;
1820cdf0e10cSrcweir }
1821cdf0e10cSrcweir 
1822cdf0e10cSrcweir // -----------------------------------------------------------------------
1823