1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2000, 2010 Oracle and/or its affiliates.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * This file is part of OpenOffice.org.
11 * OpenOffice.org is free software: you can redistribute it and/or modify
12 * it under the terms of the GNU Lesser General Public License version 3
13 * only, as published by the Free Software Foundation.
15 * OpenOffice.org is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU Lesser General Public License version 3 for more details
19 * (a copy is included in the LICENSE file that accompanied this code).
21 * You should have received a copy of the GNU Lesser General Public License
22 * version 3 along with OpenOffice.org. If not, see
23 * <http://www.openoffice.org/license.html>
24 * for a copy of the LGPLv3 License.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
33 #include <tools/svwin.h>
34 #include <wincomp.hxx>
35 #include <saldata.hxx>
37 #include <tools/debug.hxx>
39 #include <tools/poly.hxx>
40 #include <basegfx/polygon/b2dpolygon.hxx>
41 #include <basegfx/polygon/b2dpolygontools.hxx>
42 #include <rtl/strbuf.hxx>
43 #include <vcl/region.h>
47 // =======================================================================
49 // comment out to prevent use of beziers on GDI functions
50 #define USE_GDI_BEZIERS
52 // =======================================================================
54 #define DITHER_PAL_DELTA 51
55 #define DITHER_PAL_STEPS 6
56 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS)
57 #define DITHER_MAX_SYSCOLOR 16
58 #define DITHER_EXTRA_COLORS 1
59 #define DMAP( _def_nVal, _def_nThres ) ((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal])
61 // =======================================================================
69 // =======================================================================
71 static SysColorEntry
* pFirstSysColor
= NULL
;
72 static SysColorEntry
* pActSysColor
= NULL
;
74 // -----------------------------------------------------------------------------
77 static PALETTEENTRY aImplExtraColor1
=
82 // -----------------------------------------------------------------------------
84 static PALETTEENTRY aImplSalSysPalEntryAry
[ DITHER_MAX_SYSCOLOR
] =
93 { 0x80, 0x80, 0x80, 0 },
94 { 0xC0, 0xC0, 0xC0, 0 },
100 { 0xFF, 0xFF, 0, 0 },
101 { 0xFF, 0xFF, 0xFF, 0 }
104 // -----------------------------------------------------------------------------
106 static BYTE aOrdDither8Bit
[8][8] =
108 0, 38, 9, 48, 2, 40, 12, 50,
109 25, 12, 35, 22, 28, 15, 37, 24,
110 6, 44, 3, 41, 8, 47, 5, 44,
111 32, 19, 28, 16, 34, 21, 31, 18,
112 1, 40, 11, 49, 0, 39, 10, 48,
113 27, 14, 36, 24, 26, 13, 36, 23,
114 8, 46, 4, 43, 7, 45, 4, 42,
115 33, 20, 30, 17, 32, 20, 29, 16
118 // -----------------------------------------------------------------------------
120 static BYTE aOrdDither16Bit
[8][8] =
122 0, 6, 1, 7, 0, 6, 1, 7,
123 4, 2, 5, 3, 4, 2, 5, 3,
124 1, 7, 0, 6, 1, 7, 0, 6,
125 5, 3, 4, 2, 5, 3, 4, 2,
126 0, 6, 1, 7, 0, 6, 1, 7,
127 4, 2, 5, 3, 4, 2, 5, 3,
128 1, 7, 0, 6, 1, 7, 0, 6,
129 5, 3, 4, 2, 5, 3, 4, 2
132 // =======================================================================
134 // Pens muessen wir mit 1 Pixel-Breite erzeugen, da ansonsten die S3-Karte
135 // viele Paintprobleme hat, wenn Polygone/PolyLines gezeichnet werden und
136 // eine komplexe ClipRegion gesetzt ist
137 #define GSL_PEN_WIDTH 1
139 // =======================================================================
141 #define SAL_POLYPOLYCOUNT_STACKBUF 8
142 #define SAL_POLYPOLYPOINTS_STACKBUF 64
144 // =======================================================================
146 void ImplInitSalGDI()
148 SalData
* pSalData
= GetSalData();
150 // init stock brushes
151 pSalData
->maStockPenColorAry
[0] = PALETTERGB( 0, 0, 0 );
152 pSalData
->maStockPenColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
153 pSalData
->maStockPenColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
154 pSalData
->maStockPenColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
155 pSalData
->mhStockPenAry
[0] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[0] );
156 pSalData
->mhStockPenAry
[1] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[1] );
157 pSalData
->mhStockPenAry
[2] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[2] );
158 pSalData
->mhStockPenAry
[3] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[3] );
159 pSalData
->mnStockPenCount
= 4;
161 pSalData
->maStockBrushColorAry
[0] = PALETTERGB( 0, 0, 0 );
162 pSalData
->maStockBrushColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
163 pSalData
->maStockBrushColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
164 pSalData
->maStockBrushColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
165 pSalData
->mhStockBrushAry
[0] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[0] );
166 pSalData
->mhStockBrushAry
[1] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[1] );
167 pSalData
->mhStockBrushAry
[2] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[2] );
168 pSalData
->mhStockBrushAry
[3] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[3] );
169 pSalData
->mnStockBrushCount
= 4;
171 // initialize cache of device contexts
172 pSalData
->mpHDCCache
= new HDCCache
[ CACHESIZE_HDC
];
173 memset( pSalData
->mpHDCCache
, 0, CACHESIZE_HDC
* sizeof( HDCCache
) );
175 // initialize temporary font list
176 pSalData
->mpTempFontItem
= NULL
;
178 // support palettes for 256 color displays
179 HDC hDC
= GetDC( 0 );
180 int nBitsPixel
= GetDeviceCaps( hDC
, BITSPIXEL
);
181 int nPlanes
= GetDeviceCaps( hDC
, PLANES
);
182 int nRasterCaps
= GetDeviceCaps( hDC
, RASTERCAPS
);
183 int nBitCount
= nBitsPixel
* nPlanes
;
185 if ( (nBitCount
> 8) && (nBitCount
< 24) )
187 // test, if we have to dither
188 HDC hMemDC
= ::CreateCompatibleDC( hDC
);
189 HBITMAP hMemBmp
= ::CreateCompatibleBitmap( hDC
, 8, 8 );
190 HBITMAP hBmpOld
= (HBITMAP
) ::SelectObject( hMemDC
, hMemBmp
);
191 HBRUSH hMemBrush
= ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
192 HBRUSH hBrushOld
= (HBRUSH
) ::SelectObject( hMemDC
, hMemBrush
);
193 sal_Bool bDither16
= TRUE
;
195 ::PatBlt( hMemDC
, 0, 0, 8, 8, PATCOPY
);
196 const COLORREF
aCol( ::GetPixel( hMemDC
, 0, 0 ) );
198 for( int nY
= 0; ( nY
< 8 ) && bDither16
; nY
++ )
199 for( int nX
= 0; ( nX
< 8 ) && bDither16
; nX
++ )
200 if( ::GetPixel( hMemDC
, nX
, nY
) != aCol
)
203 ::SelectObject( hMemDC
, hBrushOld
), ::DeleteObject( hMemBrush
);
204 ::SelectObject( hMemDC
, hBmpOld
), ::DeleteObject( hMemBmp
);
205 ::DeleteDC( hMemDC
);
209 // create DIBPattern for 16Bit dithering
212 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, sizeof( BITMAPINFOHEADER
) + 192 );
213 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
214 pSalData
->mpDitherDiff
= new long[ 256 ];
215 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
216 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
217 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
);
218 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
220 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
222 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
226 pBIH
->biBitCount
= 24;
228 for( n
= 0; n
< 256L; n
++ )
229 pSalData
->mpDitherDiff
[ n
] = n
- ( n
& 248L );
231 for( n
= 0; n
< 256L; n
++ )
232 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
& 248 );
234 for( n
= 0; n
< 256L; n
++ )
235 pSalData
->mpDitherHigh
[ n
] = (BYTE
) Min( pSalData
->mpDitherLow
[ n
] + 8L, 255L );
238 else if ( (nRasterCaps
& RC_PALETTE
) && (nBitCount
== 8) )
240 BYTE nRed
, nGreen
, nBlue
;
242 PALETTEENTRY
* pPalEntry
;
244 const sal_uInt16 nDitherPalCount
= DITHER_PAL_COUNT
;
245 sal_uLong nTotalCount
= DITHER_MAX_SYSCOLOR
+ nDitherPalCount
+ DITHER_EXTRA_COLORS
;
247 // create logical palette
248 pLogPal
= (LOGPALETTE
*) new char[ sizeof( LOGPALETTE
) + ( nTotalCount
* sizeof( PALETTEENTRY
) ) ];
249 pLogPal
->palVersion
= 0x0300;
250 pLogPal
->palNumEntries
= (sal_uInt16
) nTotalCount
;
251 pPalEntry
= pLogPal
->palPalEntry
;
254 memcpy( pPalEntry
, aImplSalSysPalEntryAry
, DITHER_MAX_SYSCOLOR
* sizeof( PALETTEENTRY
) );
255 pPalEntry
+= DITHER_MAX_SYSCOLOR
;
257 // own palette (6/6/6)
258 for( nB
=0, nBlue
=0; nB
< DITHER_PAL_STEPS
; nB
++, nBlue
+= DITHER_PAL_DELTA
)
260 for( nG
=0, nGreen
=0; nG
< DITHER_PAL_STEPS
; nG
++, nGreen
+= DITHER_PAL_DELTA
)
262 for( nR
=0, nRed
=0; nR
< DITHER_PAL_STEPS
; nR
++, nRed
+= DITHER_PAL_DELTA
)
264 pPalEntry
->peRed
= nRed
;
265 pPalEntry
->peGreen
= nGreen
;
266 pPalEntry
->peBlue
= nBlue
;
267 pPalEntry
->peFlags
= 0;
273 // insert special 'Blue' as standard drawing color
274 *pPalEntry
++ = aImplExtraColor1
;
277 pSalData
->mhDitherPal
= CreatePalette( pLogPal
);
278 delete[] (char*) pLogPal
;
280 if( pSalData
->mhDitherPal
)
282 // create DIBPattern for 8Bit dithering
283 long nSize
= sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) ) + 64;
286 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, nSize
);
287 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
288 pSalData
->mpDitherDiff
= new long[ 256 ];
289 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
290 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
291 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) );
292 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
294 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
295 short* pColors
= (short*) ( pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) );
297 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
301 pBIH
->biBitCount
= 8;
303 for( n
= 0; n
< nDitherPalCount
; n
++ )
304 pColors
[ n
] = (short)( n
+ DITHER_MAX_SYSCOLOR
);
306 for( n
= 0; n
< 256L; n
++ )
307 pSalData
->mpDitherDiff
[ n
] = n
% 51L;
309 for( n
= 0; n
< 256L; n
++ )
310 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
/ 51L );
312 for( n
= 0; n
< 256L; n
++ )
313 pSalData
->mpDitherHigh
[ n
] = (BYTE
)Min( pSalData
->mpDitherLow
[ n
] + 1, 5 );
316 // get system color entries
317 ImplUpdateSysColorEntries();
323 // -----------------------------------------------------------------------
325 void ImplFreeSalGDI()
327 SalData
* pSalData
= GetSalData();
329 // destroy stock objects
331 for ( i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
332 DeletePen( pSalData
->mhStockPenAry
[i
] );
333 for ( i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
334 DeleteBrush( pSalData
->mhStockBrushAry
[i
] );
336 // 50% Brush loeschen
337 if ( pSalData
->mh50Brush
)
339 DeleteBrush( pSalData
->mh50Brush
);
340 pSalData
->mh50Brush
= 0;
343 // 50% Bitmap loeschen
344 if ( pSalData
->mh50Bmp
)
346 DeleteBitmap( pSalData
->mh50Bmp
);
347 pSalData
->mh50Bmp
= 0;
350 ImplClearHDCCache( pSalData
);
351 delete[] pSalData
->mpHDCCache
;
353 // Ditherpalette loeschen, wenn vorhanden
354 if ( pSalData
->mhDitherPal
)
356 DeleteObject( pSalData
->mhDitherPal
);
357 pSalData
->mhDitherPal
= 0;
360 // delete buffers for dithering DIB patterns, if neccessary
361 if ( pSalData
->mhDitherDIB
)
363 GlobalUnlock( pSalData
->mhDitherDIB
);
364 GlobalFree( pSalData
->mhDitherDIB
);
365 pSalData
->mhDitherDIB
= 0;
366 delete[] pSalData
->mpDitherDiff
;
367 delete[] pSalData
->mpDitherLow
;
368 delete[] pSalData
->mpDitherHigh
;
371 // delete SysColorList
372 SysColorEntry
* pEntry
= pFirstSysColor
;
375 SysColorEntry
* pTmp
= pEntry
->pNext
;
379 pFirstSysColor
= NULL
;
382 SalIcon
* pIcon
= pSalData
->mpFirstIcon
;
383 pSalData
->mpFirstIcon
= NULL
;
386 SalIcon
* pTmp
= pIcon
->pNext
;
387 DestroyIcon( pIcon
->hIcon
);
388 DestroyIcon( pIcon
->hSmallIcon
);
393 // delete temporary font list
394 ImplReleaseTempFonts( *pSalData
);
397 // -----------------------------------------------------------------------
399 static int ImplIsPaletteEntry( BYTE nRed
, BYTE nGreen
, BYTE nBlue
)
402 if ( !(nRed
% DITHER_PAL_DELTA
) && !(nGreen
% DITHER_PAL_DELTA
) && !(nBlue
% DITHER_PAL_DELTA
) )
405 PALETTEENTRY
* pPalEntry
= aImplSalSysPalEntryAry
;
407 // standard palette color?
408 for ( sal_uInt16 i
= 0; i
< DITHER_MAX_SYSCOLOR
; i
++, pPalEntry
++ )
410 if( pPalEntry
->peRed
== nRed
&& pPalEntry
->peGreen
== nGreen
&& pPalEntry
->peBlue
== nBlue
)
415 if ( aImplExtraColor1
.peRed
== nRed
&&
416 aImplExtraColor1
.peGreen
== nGreen
&&
417 aImplExtraColor1
.peBlue
== nBlue
)
425 // =======================================================================
427 int ImplIsSysColorEntry( SalColor nSalColor
)
429 SysColorEntry
* pEntry
= pFirstSysColor
;
430 const DWORD nTestRGB
= (DWORD
)RGB( SALCOLOR_RED( nSalColor
),
431 SALCOLOR_GREEN( nSalColor
),
432 SALCOLOR_BLUE( nSalColor
) );
436 if ( pEntry
->nRGB
== nTestRGB
)
438 pEntry
= pEntry
->pNext
;
444 // =======================================================================
446 static void ImplInsertSysColorEntry( int nSysIndex
)
448 const DWORD nRGB
= GetSysColor( nSysIndex
);
450 if ( !ImplIsPaletteEntry( GetRValue( nRGB
), GetGValue( nRGB
), GetBValue( nRGB
) ) )
452 if ( !pFirstSysColor
)
454 pActSysColor
= pFirstSysColor
= new SysColorEntry
;
455 pFirstSysColor
->nRGB
= nRGB
;
456 pFirstSysColor
->pNext
= NULL
;
460 pActSysColor
= pActSysColor
->pNext
= new SysColorEntry
;
461 pActSysColor
->nRGB
= nRGB
;
462 pActSysColor
->pNext
= NULL
;
467 // =======================================================================
469 void ImplUpdateSysColorEntries()
471 // delete old SysColorList
472 SysColorEntry
* pEntry
= pFirstSysColor
;
475 SysColorEntry
* pTmp
= pEntry
->pNext
;
479 pActSysColor
= pFirstSysColor
= NULL
;
481 // create new sys color list
482 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER
);
483 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER
);
484 if( aSalShlData
.mnVersion
>= 410 )
486 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION
);
487 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION
);
489 ImplInsertSysColorEntry( COLOR_3DFACE
);
490 ImplInsertSysColorEntry( COLOR_3DHILIGHT
);
491 ImplInsertSysColorEntry( COLOR_3DLIGHT
);
492 ImplInsertSysColorEntry( COLOR_3DSHADOW
);
493 ImplInsertSysColorEntry( COLOR_3DDKSHADOW
);
494 ImplInsertSysColorEntry( COLOR_INFOBK
);
495 ImplInsertSysColorEntry( COLOR_INFOTEXT
);
496 ImplInsertSysColorEntry( COLOR_BTNTEXT
);
497 ImplInsertSysColorEntry( COLOR_WINDOW
);
498 ImplInsertSysColorEntry( COLOR_WINDOWTEXT
);
499 ImplInsertSysColorEntry( COLOR_HIGHLIGHT
);
500 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT
);
501 ImplInsertSysColorEntry( COLOR_MENU
);
502 ImplInsertSysColorEntry( COLOR_MENUTEXT
);
503 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION
);
504 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT
);
505 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION
);
506 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT
);
509 // -----------------------------------------------------------------------
511 static SalColor
ImplGetROPSalColor( SalROPColor nROPColor
)
514 if ( nROPColor
== SAL_ROP_0
)
515 nSalColor
= MAKE_SALCOLOR( 0, 0, 0 );
517 nSalColor
= MAKE_SALCOLOR( 255, 255, 255 );
521 // =======================================================================
523 void ImplSalInitGraphics( WinSalGraphics
* pData
)
525 // Beim Printer berechnen wir die minimale Linienstaerke
526 if ( pData
->mbPrinter
)
528 int nDPIX
= GetDeviceCaps( pData
->mhDC
, LOGPIXELSX
);
530 pData
->mnPenWidth
= 0;
532 pData
->mnPenWidth
= nDPIX
/300;
535 ::SetTextAlign( pData
->mhDC
, TA_BASELINE
| TA_LEFT
| TA_NOUPDATECP
);
536 ::SetBkMode( pData
->mhDC
, TRANSPARENT
);
537 ::SetROP2( pData
->mhDC
, R2_COPYPEN
);
540 // -----------------------------------------------------------------------
542 void ImplSalDeInitGraphics( WinSalGraphics
* pData
)
545 SelectClipRgn( pData
->mhDC
, 0 );
546 // select default objects
547 if ( pData
->mhDefPen
)
548 SelectPen( pData
->mhDC
, pData
->mhDefPen
);
549 if ( pData
->mhDefBrush
)
550 SelectBrush( pData
->mhDC
, pData
->mhDefBrush
);
551 if ( pData
->mhDefFont
)
552 SelectFont( pData
->mhDC
, pData
->mhDefFont
);
555 // =======================================================================
557 HDC
ImplGetCachedDC( sal_uLong nID
, HBITMAP hBmp
)
559 SalData
* pSalData
= GetSalData();
560 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
564 HDC hDC
= GetDC( 0 );
566 // neuen DC mit DefaultBitmap anlegen
567 pC
->mhDC
= CreateCompatibleDC( hDC
);
569 if( pSalData
->mhDitherPal
)
571 pC
->mhDefPal
= SelectPalette( pC
->mhDC
, pSalData
->mhDitherPal
, TRUE
);
572 RealizePalette( pC
->mhDC
);
575 pC
->mhSelBmp
= CreateCompatibleBitmap( hDC
, CACHED_HDC_DEFEXT
, CACHED_HDC_DEFEXT
);
576 pC
->mhDefBmp
= (HBITMAP
) SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
582 SelectObject( pC
->mhDC
, pC
->mhActBmp
= hBmp
);
589 // =======================================================================
591 void ImplReleaseCachedDC( sal_uLong nID
)
593 SalData
* pSalData
= GetSalData();
594 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
597 SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
600 // =======================================================================
602 void ImplClearHDCCache( SalData
* pData
)
604 for( sal_uLong i
= 0; i
< CACHESIZE_HDC
; i
++ )
606 HDCCache
* pC
= &pData
->mpHDCCache
[ i
];
610 SelectObject( pC
->mhDC
, pC
->mhDefBmp
);
613 SelectPalette( pC
->mhDC
, pC
->mhDefPal
, TRUE
);
615 DeleteDC( pC
->mhDC
);
616 DeleteObject( pC
->mhSelBmp
);
621 // =======================================================================
623 // #100127# Fill point and flag memory from array of points which
624 // might also contain bezier control points for the PolyDraw() GDI method
625 // Make sure pWinPointAry and pWinFlagAry are big enough
626 void ImplPreparePolyDraw( bool bCloseFigures
,
628 const sal_uLong
* pPoints
,
629 const SalPoint
* const* pPtAry
,
630 const BYTE
* const* pFlgAry
,
635 for( nCurrPoly
=0; nCurrPoly
<nPoly
; ++nCurrPoly
)
637 const POINT
* pCurrPoint
= reinterpret_cast<const POINT
*>( *pPtAry
++ );
638 const BYTE
* pCurrFlag
= *pFlgAry
++;
639 const sal_uLong nCurrPoints
= *pPoints
++;
640 const bool bHaveFlagArray( pCurrFlag
);
641 sal_uLong nCurrPoint
;
646 *pWinPointAry
++ = *pCurrPoint
++;
647 *pWinFlagAry
++ = PT_MOVETO
;
650 for( nCurrPoint
=1; nCurrPoint
<nCurrPoints
; )
652 // #102067# Check existence of flag array
653 if( bHaveFlagArray
&&
654 ( nCurrPoint
+ 2 ) < nCurrPoints
)
656 BYTE
P4( pCurrFlag
[ 2 ] );
658 if( ( POLY_CONTROL
== pCurrFlag
[ 0 ] ) &&
659 ( POLY_CONTROL
== pCurrFlag
[ 1 ] ) &&
660 ( POLY_NORMAL
== P4
|| POLY_SMOOTH
== P4
|| POLY_SYMMTR
== P4
) )
663 *pWinPointAry
++ = *pCurrPoint
++;
664 *pWinFlagAry
++ = PT_BEZIERTO
;
667 *pWinPointAry
++ = *pCurrPoint
++;
668 *pWinFlagAry
++ = PT_BEZIERTO
;
671 *pWinPointAry
++ = *pCurrPoint
++;
672 *pWinFlagAry
++ = PT_BEZIERTO
;
680 // regular line point
681 *pWinPointAry
++ = *pCurrPoint
++;
682 *pWinFlagAry
++ = PT_LINETO
;
689 pWinFlagAry
[-1] |= PT_CLOSEFIGURE
;
694 // =======================================================================
696 // #100127# draw an array of points which might also contain bezier control points
697 void ImplRenderPath( HDC hdc
, sal_uLong nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
702 // TODO: profile whether the following options are faster:
703 // a) look ahead and draw consecutive bezier or line segments by PolyBezierTo/PolyLineTo resp.
704 // b) convert our flag array to window's and use PolyDraw
706 MoveToEx( hdc
, pPtAry
->mnX
, pPtAry
->mnY
, NULL
);
709 for( i
=1; i
<nPoints
; ++i
, ++pPtAry
, ++pFlgAry
)
711 if( *pFlgAry
!= POLY_CONTROL
)
713 LineTo( hdc
, pPtAry
->mnX
, pPtAry
->mnY
);
715 else if( nPoints
- i
> 2 )
717 PolyBezierTo( hdc
, reinterpret_cast<const POINT
*>(pPtAry
), 3 );
718 i
+= 2; pPtAry
+= 2; pFlgAry
+= 2;
724 // =======================================================================
726 WinSalGraphics::WinSalGraphics()
728 for( int i
= 0; i
< MAX_FALLBACK
; ++i
)
731 mpWinFontData
[ i
] = NULL
;
732 mpWinFontEntry
[ i
] = NULL
;
745 mpStdClipRgnData
= NULL
;
747 mpFontCharSets
= NULL
;
748 mpFontAttrCache
= NULL
;
749 mnFontCharSetCount
= 0;
750 mpFontKernPairs
= NULL
;
751 mnFontKernPairCount
= 0;
752 mbFontKernInit
= FALSE
;
754 mnPenWidth
= GSL_PEN_WIDTH
;
757 // -----------------------------------------------------------------------
759 WinSalGraphics::~WinSalGraphics()
761 // free obsolete GDI objekts
772 DeleteBrush( mhBrush
);
777 DeleteRegion( mhRegion
);
781 // Cache-Daten zerstoeren
782 if ( mpStdClipRgnData
)
783 delete [] mpStdClipRgnData
;
788 if ( mpFontCharSets
)
789 delete mpFontCharSets
;
791 if ( mpFontKernPairs
)
792 delete mpFontKernPairs
;
795 // -----------------------------------------------------------------------
797 void WinSalGraphics::GetResolution( long& rDPIX
, long& rDPIY
)
799 rDPIX
= GetDeviceCaps( mhDC
, LOGPIXELSX
);
800 rDPIY
= GetDeviceCaps( mhDC
, LOGPIXELSY
);
802 // #111139# this fixes the symptom of div by zero on startup
803 // however, printing will fail most likely as communication with
804 // the printer seems not to work in this case
805 if( !rDPIX
|| !rDPIY
)
809 // -----------------------------------------------------------------------
811 sal_uInt16
WinSalGraphics::GetBitCount()
813 return (sal_uInt16
)GetDeviceCaps( mhDC
, BITSPIXEL
);
816 // -----------------------------------------------------------------------
818 long WinSalGraphics::GetGraphicsWidth() const
820 if( mhWnd
&& IsWindow( mhWnd
) )
822 WinSalFrame
* pFrame
= GetWindowPtr( mhWnd
);
825 if( pFrame
->maGeometry
.nWidth
)
826 return pFrame
->maGeometry
.nWidth
;
829 // TODO: perhaps not needed, maGeometry should always be up-to-date
831 GetClientRect( mhWnd
, &aRect
);
840 // -----------------------------------------------------------------------
842 void WinSalGraphics::ResetClipRegion()
846 DeleteRegion( mhRegion
);
850 SelectClipRgn( mhDC
, 0 );
853 // -----------------------------------------------------------------------
855 bool WinSalGraphics::setClipRegion( const Region
& i_rClip
)
859 DeleteRegion( mhRegion
);
863 if( i_rClip
.HasPolyPolygon() )
865 // TODO: ConvertToB2DPolyPolygon actually is kind of const, just it does not advertise it in the header
866 basegfx::B2DPolyPolygon
aPolyPolygon( const_cast<Region
&>(i_rClip
).ConvertToB2DPolyPolygon() );
867 const sal_uInt32
nCount(aPolyPolygon
.count());
871 std::vector
< POINT
> aPolyPoints
;
872 aPolyPoints
.reserve( 1024 );
873 std::vector
< INT
> aPolyCounts( nCount
, 0 );
874 for(sal_uInt32
a(0); a
< nCount
; a
++)
876 basegfx::B2DPolygon
aPoly( aPolyPolygon
.getB2DPolygon(a
) );
877 aPoly
= basegfx::tools::adaptiveSubdivideByDistance( aPoly
, 1 );
878 const sal_uInt32 nPoints
= aPoly
.count();
879 aPolyCounts
[a
] = nPoints
;
880 for( sal_uInt32 b
= 0; b
< nPoints
; b
++ )
882 basegfx::B2DPoint
aPt( aPoly
.getB2DPoint( b
) );
884 aPOINT
.x
= (LONG
)aPt
.getX();
885 aPOINT
.y
= (LONG
)aPt
.getY();
886 aPolyPoints
.push_back( aPOINT
);
889 mhRegion
= CreatePolyPolygonRgn( &aPolyPoints
[0], &aPolyCounts
[0], nCount
, ALTERNATE
);
894 ULONG nRectCount
= i_rClip
.GetRectCount();
896 ULONG nRectBufSize
= sizeof(RECT
)*nRectCount
;
897 if ( nRectCount
< SAL_CLIPRECT_COUNT
)
899 if ( !mpStdClipRgnData
)
900 mpStdClipRgnData
= (RGNDATA
*)new BYTE
[sizeof(RGNDATA
)-1+(SAL_CLIPRECT_COUNT
*sizeof(RECT
))];
901 mpClipRgnData
= mpStdClipRgnData
;
904 mpClipRgnData
= (RGNDATA
*)new BYTE
[sizeof(RGNDATA
)-1+nRectBufSize
];
905 mpClipRgnData
->rdh
.dwSize
= sizeof( RGNDATAHEADER
);
906 mpClipRgnData
->rdh
.iType
= RDH_RECTANGLES
;
907 mpClipRgnData
->rdh
.nCount
= nRectCount
;
908 mpClipRgnData
->rdh
.nRgnSize
= nRectBufSize
;
909 RECT
* pBoundRect
= &(mpClipRgnData
->rdh
.rcBound
);
910 SetRectEmpty( pBoundRect
);
911 RECT
* pNextClipRect
= (RECT
*)(&(mpClipRgnData
->Buffer
));
912 bool bFirstClipRect
= true;
914 ImplRegionInfo aInfo
;
916 bool bRegionRect
= i_rClip
.ImplGetFirstRect(aInfo
, nX
, nY
, nW
, nH
);
921 long nRight
= nX
+ nW
;
922 long nBottom
= nY
+ nH
;
924 if ( bFirstClipRect
)
926 pBoundRect
->left
= nX
;
927 pBoundRect
->top
= nY
;
928 pBoundRect
->right
= nRight
;
929 pBoundRect
->bottom
= nBottom
;
930 bFirstClipRect
= false;
934 if ( nX
< pBoundRect
->left
)
935 pBoundRect
->left
= (int)nX
;
937 if ( nY
< pBoundRect
->top
)
938 pBoundRect
->top
= (int)nY
;
940 if ( nRight
> pBoundRect
->right
)
941 pBoundRect
->right
= (int)nRight
;
943 if ( nBottom
> pBoundRect
->bottom
)
944 pBoundRect
->bottom
= (int)nBottom
;
947 pNextClipRect
->left
= (int)nX
;
948 pNextClipRect
->top
= (int)nY
;
949 pNextClipRect
->right
= (int)nRight
;
950 pNextClipRect
->bottom
= (int)nBottom
;
955 mpClipRgnData
->rdh
.nCount
--;
956 mpClipRgnData
->rdh
.nRgnSize
-= sizeof( RECT
);
958 bRegionRect
= i_rClip
.ImplGetNextRect( aInfo
, nX
, nY
, nW
, nH
);
960 // create clip region from ClipRgnData
961 if ( mpClipRgnData
->rdh
.nCount
== 1 )
963 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
964 mhRegion
= CreateRectRgn( pRect
->left
, pRect
->top
,
965 pRect
->right
, pRect
->bottom
);
967 else if( mpClipRgnData
->rdh
.nCount
> 1 )
969 ULONG nSize
= mpClipRgnData
->rdh
.nRgnSize
+sizeof(RGNDATAHEADER
);
970 mhRegion
= ExtCreateRegion( NULL
, nSize
, mpClipRgnData
);
972 // if ExtCreateRegion(...) is not supported
975 RGNDATAHEADER
* pHeader
= (RGNDATAHEADER
*) mpClipRgnData
;
977 if( pHeader
->nCount
)
979 RECT
* pRect
= (RECT
*) mpClipRgnData
->Buffer
;
980 mhRegion
= CreateRectRgn( pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
983 for( ULONG n
= 1; n
< pHeader
->nCount
; n
++, pRect
++ )
985 HRGN hRgn
= CreateRectRgn( pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
986 CombineRgn( mhRegion
, mhRegion
, hRgn
, RGN_OR
);
987 DeleteRegion( hRgn
);
992 if ( mpClipRgnData
!= mpStdClipRgnData
)
993 delete [] mpClipRgnData
;
998 SelectClipRgn( mhDC
, mhRegion
);
999 return mhRegion
!= 0;
1002 // -----------------------------------------------------------------------
1004 void WinSalGraphics::SetLineColor()
1006 // create and select new pen
1007 HPEN hNewPen
= GetStockPen( NULL_PEN
);
1008 HPEN hOldPen
= SelectPen( mhDC
, hNewPen
);
1010 // destory or save old pen
1025 // -----------------------------------------------------------------------
1027 void WinSalGraphics::SetLineColor( SalColor nSalColor
)
1029 maLineColor
= nSalColor
;
1030 COLORREF nPenColor
= PALETTERGB( SALCOLOR_RED( nSalColor
),
1031 SALCOLOR_GREEN( nSalColor
),
1032 SALCOLOR_BLUE( nSalColor
) );
1034 sal_Bool bStockPen
= FALSE
;
1036 // search for stock pen (only screen, because printer have problems,
1037 // when we use stock objects)
1040 SalData
* pSalData
= GetSalData();
1041 for ( sal_uInt16 i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
1043 if ( nPenColor
== pSalData
->maStockPenColorAry
[i
] )
1045 hNewPen
= pSalData
->mhStockPenAry
[i
];
1057 if ( GetSalData()->mhDitherPal
&& ImplIsSysColorEntry( nSalColor
) )
1058 nPenColor
= PALRGB_TO_RGB( nPenColor
);
1061 hNewPen
= CreatePen( PS_SOLID
, mnPenWidth
, nPenColor
);
1066 HPEN hOldPen
= SelectPen( mhDC
, hNewPen
);
1068 // destory or save old pen
1078 mnPenColor
= nPenColor
;
1081 mbStockPen
= bStockPen
;
1084 // -----------------------------------------------------------------------
1086 void WinSalGraphics::SetFillColor()
1088 // create and select new brush
1089 HBRUSH hNewBrush
= GetStockBrush( NULL_BRUSH
);
1090 HBRUSH hOldBrush
= SelectBrush( mhDC
, hNewBrush
);
1092 // destory or save old brush
1095 if ( !mbStockBrush
)
1096 DeleteBrush( mhBrush
);
1099 mhDefBrush
= hOldBrush
;
1102 mhBrush
= hNewBrush
;
1104 mbStockBrush
= TRUE
;
1107 // -----------------------------------------------------------------------
1109 void WinSalGraphics::SetFillColor( SalColor nSalColor
)
1111 maFillColor
= nSalColor
;
1112 SalData
* pSalData
= GetSalData();
1113 BYTE nRed
= SALCOLOR_RED( nSalColor
);
1114 BYTE nGreen
= SALCOLOR_GREEN( nSalColor
);
1115 BYTE nBlue
= SALCOLOR_BLUE( nSalColor
);
1116 COLORREF nBrushColor
= PALETTERGB( nRed
, nGreen
, nBlue
);
1117 HBRUSH hNewBrush
= 0;
1118 sal_Bool bStockBrush
= FALSE
;
1120 // search for stock brush (only screen, because printer have problems,
1121 // when we use stock objects)
1124 for ( sal_uInt16 i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
1126 if ( nBrushColor
== pSalData
->maStockBrushColorAry
[ i
] )
1128 hNewBrush
= pSalData
->mhStockBrushAry
[i
];
1138 if ( mbPrinter
|| !pSalData
->mhDitherDIB
)
1139 hNewBrush
= CreateSolidBrush( nBrushColor
);
1142 if ( 24 == ((BITMAPINFOHEADER
*)pSalData
->mpDitherDIB
)->biBitCount
)
1144 BYTE
* pTmp
= pSalData
->mpDitherDIBData
;
1145 long* pDitherDiff
= pSalData
->mpDitherDiff
;
1146 BYTE
* pDitherLow
= pSalData
->mpDitherLow
;
1147 BYTE
* pDitherHigh
= pSalData
->mpDitherHigh
;
1149 for( long nY
= 0L; nY
< 8L; nY
++ )
1151 for( long nX
= 0L; nX
< 8L; nX
++ )
1153 const long nThres
= aOrdDither16Bit
[ nY
][ nX
];
1154 *pTmp
++ = DMAP( nBlue
, nThres
);
1155 *pTmp
++ = DMAP( nGreen
, nThres
);
1156 *pTmp
++ = DMAP( nRed
, nThres
);
1160 hNewBrush
= CreateDIBPatternBrush( pSalData
->mhDitherDIB
, DIB_RGB_COLORS
);
1162 else if ( ImplIsSysColorEntry( nSalColor
) )
1164 nBrushColor
= PALRGB_TO_RGB( nBrushColor
);
1165 hNewBrush
= CreateSolidBrush( nBrushColor
);
1167 else if ( ImplIsPaletteEntry( nRed
, nGreen
, nBlue
) )
1168 hNewBrush
= CreateSolidBrush( nBrushColor
);
1171 BYTE
* pTmp
= pSalData
->mpDitherDIBData
;
1172 long* pDitherDiff
= pSalData
->mpDitherDiff
;
1173 BYTE
* pDitherLow
= pSalData
->mpDitherLow
;
1174 BYTE
* pDitherHigh
= pSalData
->mpDitherHigh
;
1176 for ( long nY
= 0L; nY
< 8L; nY
++ )
1178 for ( long nX
= 0L; nX
< 8L; nX
++ )
1180 const long nThres
= aOrdDither8Bit
[ nY
][ nX
];
1181 *pTmp
= DMAP( nRed
, nThres
) + DMAP( nGreen
, nThres
) * 6 + DMAP( nBlue
, nThres
) * 36;
1186 hNewBrush
= CreateDIBPatternBrush( pSalData
->mhDitherDIB
, DIB_PAL_COLORS
);
1190 bStockBrush
= FALSE
;
1194 HBRUSH hOldBrush
= SelectBrush( mhDC
, hNewBrush
);
1196 // destory or save old brush
1199 if ( !mbStockBrush
)
1200 DeleteBrush( mhBrush
);
1203 mhDefBrush
= hOldBrush
;
1206 mnBrushColor
= nBrushColor
;
1207 mhBrush
= hNewBrush
;
1209 mbStockBrush
= bStockBrush
;
1212 // -----------------------------------------------------------------------
1214 void WinSalGraphics::SetXORMode( bool bSet
, bool )
1217 ::SetROP2( mhDC
, bSet
? R2_XORPEN
: R2_COPYPEN
);
1220 // -----------------------------------------------------------------------
1222 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
1224 SetLineColor( ImplGetROPSalColor( nROPColor
) );
1227 // -----------------------------------------------------------------------
1229 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
1231 SetFillColor( ImplGetROPSalColor( nROPColor
) );
1234 // -----------------------------------------------------------------------
1236 void WinSalGraphics::drawPixel( long nX
, long nY
)
1240 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1241 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1242 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)1, (int)1, PATINVERT
);
1243 SelectBrush( mhDC
, hOldBrush
);
1244 DeleteBrush( hBrush
);
1247 SetPixel( mhDC
, (int)nX
, (int)nY
, mnPenColor
);
1250 // -----------------------------------------------------------------------
1252 void WinSalGraphics::drawPixel( long nX
, long nY
, SalColor nSalColor
)
1254 COLORREF nCol
= PALETTERGB( SALCOLOR_RED( nSalColor
),
1255 SALCOLOR_GREEN( nSalColor
),
1256 SALCOLOR_BLUE( nSalColor
) );
1259 GetSalData()->mhDitherPal
&&
1260 ImplIsSysColorEntry( nSalColor
) )
1261 nCol
= PALRGB_TO_RGB( nCol
);
1265 HBRUSH hBrush
= CreateSolidBrush( nCol
);
1266 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1267 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)1, (int)1, PATINVERT
);
1268 SelectBrush( mhDC
, hOldBrush
);
1269 DeleteBrush( hBrush
);
1272 ::SetPixel( mhDC
, (int)nX
, (int)nY
, nCol
);
1275 // -----------------------------------------------------------------------
1277 void WinSalGraphics::drawLine( long nX1
, long nY1
, long nX2
, long nY2
)
1279 MoveToEx( mhDC
, (int)nX1
, (int)nY1
, NULL
);
1281 // we must paint the endpoint
1282 int bPaintEnd
= TRUE
;
1300 LineTo( mhDC
, (int)nX2
, (int)nY2
);
1302 if ( bPaintEnd
&& !mbPrinter
)
1306 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1307 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1308 PatBlt( mhDC
, (int)nX2
, (int)nY2
, (int)1, (int)1, PATINVERT
);
1309 SelectBrush( mhDC
, hOldBrush
);
1310 DeleteBrush( hBrush
);
1313 SetPixel( mhDC
, (int)nX2
, (int)nY2
, mnPenColor
);
1317 // -----------------------------------------------------------------------
1319 void WinSalGraphics::drawRect( long nX
, long nY
, long nWidth
, long nHeight
)
1325 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)nWidth
, (int)nHeight
,
1326 mbXORMode
? PATINVERT
: PATCOPY
);
1333 aWinRect
.right
= nX
+nWidth
;
1334 aWinRect
.bottom
= nY
+nHeight
;
1335 ::FillRect( mhDC
, &aWinRect
, mhBrush
);
1339 WIN_Rectangle( mhDC
, (int)nX
, (int)nY
, (int)(nX
+nWidth
), (int)(nY
+nHeight
) );
1342 // -----------------------------------------------------------------------
1344 void WinSalGraphics::drawPolyLine( sal_uLong nPoints
, const SalPoint
* pPtAry
)
1346 // Unter NT koennen wir das Array direkt weiterreichen
1347 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1348 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
1350 POINT
* pWinPtAry
= (POINT
*)pPtAry
;
1351 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
1353 if ( !Polyline( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
1354 Polyline( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
1357 // -----------------------------------------------------------------------
1359 void WinSalGraphics::drawPolygon( sal_uLong nPoints
, const SalPoint
* pPtAry
)
1361 // Unter NT koennen wir das Array direkt weiterreichen
1362 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1363 "WinSalGraphics::DrawPolygon(): POINT != SalPoint" );
1365 POINT
* pWinPtAry
= (POINT
*)pPtAry
;
1366 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
1368 if ( !WIN_Polygon( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
1369 WIN_Polygon( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
1372 // -----------------------------------------------------------------------
1374 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
1375 PCONSTSALPOINT
* pPtAry
)
1377 UINT aWinPointAry
[SAL_POLYPOLYCOUNT_STACKBUF
];
1379 UINT nPolyPolyPoints
= 0;
1383 if ( nPoly
<= SAL_POLYPOLYCOUNT_STACKBUF
)
1384 pWinPointAry
= aWinPointAry
;
1386 pWinPointAry
= new UINT
[nPoly
];
1388 for ( i
= 0; i
< (UINT
)nPoly
; i
++ )
1390 nPoints
= (UINT
)pPoints
[i
]+1;
1391 pWinPointAry
[i
] = nPoints
;
1392 nPolyPolyPoints
+= nPoints
;
1395 POINT aWinPointAryAry
[SAL_POLYPOLYPOINTS_STACKBUF
];
1396 POINT
* pWinPointAryAry
;
1397 if ( nPolyPolyPoints
<= SAL_POLYPOLYPOINTS_STACKBUF
)
1398 pWinPointAryAry
= aWinPointAryAry
;
1400 pWinPointAryAry
= new POINT
[nPolyPolyPoints
];
1401 // Unter NT koennen wir das Array direkt weiterreichen
1402 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1403 "WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" );
1404 const SalPoint
* pPolyAry
;
1406 for ( i
= 0; i
< (UINT
)nPoly
; i
++ )
1408 nPoints
= pWinPointAry
[i
];
1409 pPolyAry
= pPtAry
[i
];
1410 memcpy( pWinPointAryAry
+n
, pPolyAry
, (nPoints
-1)*sizeof(POINT
) );
1411 pWinPointAryAry
[n
+nPoints
-1] = pWinPointAryAry
[n
];
1415 if ( !WIN_PolyPolygon( mhDC
, pWinPointAryAry
, (int*)pWinPointAry
, (UINT
)nPoly
) &&
1416 (nPolyPolyPoints
> MAX_64KSALPOINTS
) )
1418 nPolyPolyPoints
= 0;
1422 nPolyPolyPoints
+= pWinPointAry
[(UINT
)nPoly
];
1425 while ( nPolyPolyPoints
< MAX_64KSALPOINTS
);
1427 if ( pWinPointAry
[(UINT
)nPoly
] > MAX_64KSALPOINTS
)
1428 pWinPointAry
[(UINT
)nPoly
] = MAX_64KSALPOINTS
;
1430 WIN_Polygon( mhDC
, pWinPointAryAry
, *pWinPointAry
);
1432 WIN_PolyPolygon( mhDC
, pWinPointAryAry
, (int*)pWinPointAry
, nPoly
);
1435 if ( pWinPointAry
!= aWinPointAry
)
1436 delete [] pWinPointAry
;
1437 if ( pWinPointAryAry
!= aWinPointAryAry
)
1438 delete [] pWinPointAryAry
;
1441 // -----------------------------------------------------------------------
1443 #define SAL_POLY_STACKBUF 32
1445 // -----------------------------------------------------------------------
1447 sal_Bool
WinSalGraphics::drawPolyLineBezier( sal_uLong nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
1449 #ifdef USE_GDI_BEZIERS
1450 // Unter NT koennen wir das Array direkt weiterreichen
1451 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1452 "WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" );
1454 ImplRenderPath( mhDC
, nPoints
, pPtAry
, pFlgAry
);
1462 // -----------------------------------------------------------------------
1464 sal_Bool
WinSalGraphics::drawPolygonBezier( sal_uLong nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
1466 #ifdef USE_GDI_BEZIERS
1467 // Unter NT koennen wir das Array direkt weiterreichen
1468 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1469 "WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" );
1471 POINT aStackAry1
[SAL_POLY_STACKBUF
];
1472 BYTE aStackAry2
[SAL_POLY_STACKBUF
];
1473 POINT
* pWinPointAry
;
1475 if( nPoints
> SAL_POLY_STACKBUF
)
1477 pWinPointAry
= new POINT
[ nPoints
];
1478 pWinFlagAry
= new BYTE
[ nPoints
];
1482 pWinPointAry
= aStackAry1
;
1483 pWinFlagAry
= aStackAry2
;
1486 ImplPreparePolyDraw(true, 1, &nPoints
, &pPtAry
, &pFlgAry
, pWinPointAry
, pWinFlagAry
);
1488 sal_Bool
bRet( sal_False
);
1490 if( BeginPath( mhDC
) )
1492 PolyDraw(mhDC
, pWinPointAry
, pWinFlagAry
, nPoints
);
1494 if( EndPath( mhDC
) )
1496 if( StrokeAndFillPath( mhDC
) )
1501 if( pWinPointAry
!= aStackAry1
)
1503 delete [] pWinPointAry
;
1504 delete [] pWinFlagAry
;
1513 // -----------------------------------------------------------------------
1515 sal_Bool
WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
1516 const SalPoint
* const* pPtAry
, const BYTE
* const* pFlgAry
)
1518 #ifdef USE_GDI_BEZIERS
1519 // Unter NT koennen wir das Array direkt weiterreichen
1520 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1521 "WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" );
1523 sal_uLong nCurrPoly
, nTotalPoints
;
1524 const sal_uLong
* pCurrPoints
= pPoints
;
1525 for( nCurrPoly
=0, nTotalPoints
=0; nCurrPoly
<nPoly
; ++nCurrPoly
)
1526 nTotalPoints
+= *pCurrPoints
++;
1528 POINT aStackAry1
[SAL_POLY_STACKBUF
];
1529 BYTE aStackAry2
[SAL_POLY_STACKBUF
];
1530 POINT
* pWinPointAry
;
1532 if( nTotalPoints
> SAL_POLY_STACKBUF
)
1534 pWinPointAry
= new POINT
[ nTotalPoints
];
1535 pWinFlagAry
= new BYTE
[ nTotalPoints
];
1539 pWinPointAry
= aStackAry1
;
1540 pWinFlagAry
= aStackAry2
;
1543 ImplPreparePolyDraw(true, nPoly
, pPoints
, pPtAry
, pFlgAry
, pWinPointAry
, pWinFlagAry
);
1545 sal_Bool
bRet( sal_False
);
1547 if( BeginPath( mhDC
) )
1549 PolyDraw(mhDC
, pWinPointAry
, pWinFlagAry
, nTotalPoints
);
1551 if( EndPath( mhDC
) )
1553 if( StrokeAndFillPath( mhDC
) )
1558 if( pWinPointAry
!= aStackAry1
)
1560 delete [] pWinPointAry
;
1561 delete [] pWinFlagAry
;
1570 // -----------------------------------------------------------------------
1572 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
1573 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox
1574 // in the first 4096 bytes
1576 static BYTE
* ImplSearchEntry( BYTE
* pSource
, BYTE
* pDest
, sal_uLong nComp
, sal_uLong nSize
)
1578 while ( nComp
-- >= nSize
)
1581 for ( i
= 0; i
< nSize
; i
++ )
1583 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
1593 static sal_Bool
ImplGetBoundingBox( double* nNumb
, BYTE
* pSource
, sal_uLong nSize
)
1595 sal_Bool bRetValue
= FALSE
;
1596 BYTE
* pDest
= ImplSearchEntry( pSource
, (BYTE
*)"%%BoundingBox:", nSize
, 14 );
1599 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
1602 int nSizeLeft
= nSize
- ( pDest
- pSource
);
1603 if ( nSizeLeft
> 100 )
1604 nSizeLeft
= 100; // only 100 bytes following the bounding box will be checked
1607 for ( i
= 0; ( i
< 4 ) && nSizeLeft
; i
++ )
1610 sal_Bool bDivision
= FALSE
;
1611 sal_Bool bNegative
= FALSE
;
1612 sal_Bool bValid
= TRUE
;
1614 while ( ( --nSizeLeft
) && ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) pDest
++;
1615 BYTE nByte
= *pDest
;
1616 while ( nSizeLeft
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
1630 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
1631 nSizeLeft
= 1; // error parsing the bounding box values
1637 nNumb
[i
] += nByte
- '0';
1645 nNumb
[i
] = -nNumb
[i
];
1646 if ( bDivision
&& ( nDivision
!= 1 ) )
1647 nNumb
[i
] /= nDivision
;
1655 sal_Bool
WinSalGraphics::drawEPS( long nX
, long nY
, long nWidth
, long nHeight
, void* pPtr
, sal_uLong nSize
)
1657 sal_Bool bRetValue
= FALSE
;
1661 int nEscape
= POSTSCRIPT_PASSTHROUGH
;
1663 if ( Escape( mhDC
, QUERYESCSUPPORT
, sizeof( int ), ( LPSTR
)&nEscape
, 0 ) )
1665 double nBoundingBox
[4];
1667 if ( ImplGetBoundingBox( nBoundingBox
, (BYTE
*)pPtr
, nSize
) )
1669 OStringBuffer
aBuf( POSTSCRIPT_BUFSIZE
);
1671 // reserve place for a sal_uInt16
1672 aBuf
.append( "aa" );
1674 // #107797# Write out EPS encapsulation header
1675 // ----------------------------------------------------------------------------------
1677 // directly taken from the PLRM 3.0, p. 726. Note:
1678 // this will definitely cause problems when
1679 // recursively creating and embedding PostScript files
1680 // in OOo, since we use statically-named variables
1681 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
1682 // op_count_salWin). Currently, I have no idea on how to
1683 // work around that, except from scanning and
1684 // interpreting the EPS for unused identifiers.
1686 // append the real text
1687 aBuf
.append( "\n\n/b4_Inc_state_salWin save def\n"
1688 "/dict_count_salWin countdictstack def\n"
1689 "/op_count_salWin count 1 sub def\n"
1691 "/showpage {} def\n"
1692 "0 setgray 0 setlinecap\n"
1693 "1 setlinewidth 0 setlinejoin\n"
1694 "10 setmiterlimit [] 0 setdash newpath\n"
1695 "/languagelevel where\n"
1697 " pop languagelevel\n"
1700 " false setstrokeadjust false setoverprint\n"
1705 // #i10737# Apply clipping manually
1706 // ----------------------------------------------------------------------------------
1708 // Windows seems to ignore any clipping at the HDC,
1709 // when followed by a POSTSCRIPT_PASSTHROUGH
1711 // Check whether we've got a clipping, consisting of
1712 // exactly one rect (other cases should be, but aren't
1713 // handled currently)
1715 // TODO: Handle more than one rectangle here (take
1716 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
1718 if ( mhRegion
!= 0 &&
1719 mpStdClipRgnData
!= NULL
&&
1720 mpClipRgnData
== mpStdClipRgnData
&&
1721 mpClipRgnData
->rdh
.nCount
== 1 )
1723 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
1725 aBuf
.append( "\nnewpath\n" );
1726 aBuf
.append( pRect
->left
);
1728 aBuf
.append( pRect
->top
);
1729 aBuf
.append( " moveto\n" );
1730 aBuf
.append( pRect
->right
);
1732 aBuf
.append( pRect
->top
);
1733 aBuf
.append( " lineto\n" );
1734 aBuf
.append( pRect
->right
);
1736 aBuf
.append( pRect
->bottom
);
1737 aBuf
.append( " lineto\n" );
1738 aBuf
.append( pRect
->left
);
1740 aBuf
.append( pRect
->bottom
);
1741 aBuf
.append( " lineto\n"
1747 // #107797# Write out buffer
1748 // ----------------------------------------------------------------------------------
1749 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1750 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1753 // #107797# Write out EPS transformation code
1754 // ----------------------------------------------------------------------------------
1755 double dM11
= nWidth
/ ( nBoundingBox
[2] - nBoundingBox
[0] );
1756 double dM22
= nHeight
/ (nBoundingBox
[1] - nBoundingBox
[3] );
1757 // reserve a sal_uInt16 again
1758 aBuf
.setLength( 2 );
1759 aBuf
.append( "\n\n[" );
1760 aBuf
.append( dM11
);
1761 aBuf
.append( " 0 0 " );
1762 aBuf
.append( dM22
);
1764 aBuf
.append( nX
- ( dM11
* nBoundingBox
[0] ) );
1766 aBuf
.append( nY
- ( dM22
* nBoundingBox
[3] ) );
1767 aBuf
.append( "] concat\n"
1768 "%%BeginDocument:\n" );
1769 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1770 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1773 // #107797# Write out actual EPS content
1774 // ----------------------------------------------------------------------------------
1775 sal_uLong nToDo
= nSize
;
1780 if ( nToDo
> POSTSCRIPT_BUFSIZE
- 2 )
1781 nDoNow
= POSTSCRIPT_BUFSIZE
- 2;
1782 // the following is based on the string buffer allocation
1783 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1784 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)nDoNow
;
1785 memcpy( (void*)(aBuf
.getStr() + 2), (BYTE
*)pPtr
+ nSize
- nToDo
, nDoNow
);
1786 sal_uLong nResult
= Escape ( mhDC
, nEscape
, nDoNow
+ 2, (LPTSTR
)aBuf
.getStr(), 0 );
1793 // #107797# Write out EPS encapsulation footer
1794 // ----------------------------------------------------------------------------------
1795 // reserve a sal_uInt16 again
1796 aBuf
.setLength( 2 );
1797 aBuf
.append( "%%EndDocument\n"
1798 "count op_count_salWin sub {pop} repeat\n"
1799 "countdictstack dict_count_salWin sub {end} repeat\n"
1800 "b4_Inc_state_salWin restore\n\n" );
1801 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1802 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1811 // -----------------------------------------------------------------------
1813 SystemGraphicsData
WinSalGraphics::GetGraphicsData() const
1815 SystemGraphicsData aRes
;
1816 aRes
.nSize
= sizeof(aRes
);
1821 // -----------------------------------------------------------------------