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