1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salgdi.cxx,v $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
36 #include <tools/svwin.h>
37 #include <wincomp.hxx>
38 #include <saldata.hxx>
40 #include <tools/debug.hxx>
42 #include <tools/poly.hxx>
43 #ifndef _RTL_STRINGBUF_HXX
44 #include <rtl/strbuf.hxx>
49 // =======================================================================
51 // comment out to prevent use of beziers on GDI functions
52 #define USE_GDI_BEZIERS
54 // =======================================================================
56 #define DITHER_PAL_DELTA 51
57 #define DITHER_PAL_STEPS 6
58 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS)
59 #define DITHER_MAX_SYSCOLOR 16
60 #define DITHER_EXTRA_COLORS 1
61 #define DMAP( _def_nVal, _def_nThres ) ((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal])
63 // =======================================================================
71 // =======================================================================
73 static SysColorEntry
* pFirstSysColor
= NULL
;
74 static SysColorEntry
* pActSysColor
= NULL
;
76 // -----------------------------------------------------------------------------
79 static PALETTEENTRY aImplExtraColor1
=
84 // -----------------------------------------------------------------------------
86 static PALETTEENTRY aImplSalSysPalEntryAry
[ DITHER_MAX_SYSCOLOR
] =
95 { 0x80, 0x80, 0x80, 0 },
96 { 0xC0, 0xC0, 0xC0, 0 },
101 { 0xFF, 0, 0xFF, 0 },
102 { 0xFF, 0xFF, 0, 0 },
103 { 0xFF, 0xFF, 0xFF, 0 }
106 // -----------------------------------------------------------------------------
108 static BYTE aOrdDither8Bit
[8][8] =
110 0, 38, 9, 48, 2, 40, 12, 50,
111 25, 12, 35, 22, 28, 15, 37, 24,
112 6, 44, 3, 41, 8, 47, 5, 44,
113 32, 19, 28, 16, 34, 21, 31, 18,
114 1, 40, 11, 49, 0, 39, 10, 48,
115 27, 14, 36, 24, 26, 13, 36, 23,
116 8, 46, 4, 43, 7, 45, 4, 42,
117 33, 20, 30, 17, 32, 20, 29, 16
120 // -----------------------------------------------------------------------------
122 static BYTE aOrdDither16Bit
[8][8] =
124 0, 6, 1, 7, 0, 6, 1, 7,
125 4, 2, 5, 3, 4, 2, 5, 3,
126 1, 7, 0, 6, 1, 7, 0, 6,
127 5, 3, 4, 2, 5, 3, 4, 2,
128 0, 6, 1, 7, 0, 6, 1, 7,
129 4, 2, 5, 3, 4, 2, 5, 3,
130 1, 7, 0, 6, 1, 7, 0, 6,
131 5, 3, 4, 2, 5, 3, 4, 2
134 // =======================================================================
136 // Pens muessen wir mit 1 Pixel-Breite erzeugen, da ansonsten die S3-Karte
137 // viele Paintprobleme hat, wenn Polygone/PolyLines gezeichnet werden und
138 // eine komplexe ClipRegion gesetzt ist
139 #define GSL_PEN_WIDTH 1
141 // =======================================================================
143 #define SAL_POLYPOLYCOUNT_STACKBUF 8
144 #define SAL_POLYPOLYPOINTS_STACKBUF 64
146 // =======================================================================
148 void ImplInitSalGDI()
150 SalData
* pSalData
= GetSalData();
152 // init stock brushes
153 pSalData
->maStockPenColorAry
[0] = PALETTERGB( 0, 0, 0 );
154 pSalData
->maStockPenColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
155 pSalData
->maStockPenColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
156 pSalData
->maStockPenColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
157 pSalData
->mhStockPenAry
[0] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[0] );
158 pSalData
->mhStockPenAry
[1] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[1] );
159 pSalData
->mhStockPenAry
[2] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[2] );
160 pSalData
->mhStockPenAry
[3] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[3] );
161 pSalData
->mnStockPenCount
= 4;
163 pSalData
->maStockBrushColorAry
[0] = PALETTERGB( 0, 0, 0 );
164 pSalData
->maStockBrushColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
165 pSalData
->maStockBrushColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
166 pSalData
->maStockBrushColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
167 pSalData
->mhStockBrushAry
[0] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[0] );
168 pSalData
->mhStockBrushAry
[1] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[1] );
169 pSalData
->mhStockBrushAry
[2] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[2] );
170 pSalData
->mhStockBrushAry
[3] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[3] );
171 pSalData
->mnStockBrushCount
= 4;
173 // initialize cache of device contexts
174 pSalData
->mpHDCCache
= new HDCCache
[ CACHESIZE_HDC
];
175 memset( pSalData
->mpHDCCache
, 0, CACHESIZE_HDC
* sizeof( HDCCache
) );
177 // initialize temporary font list
178 pSalData
->mpTempFontItem
= NULL
;
180 // support palettes for 256 color displays
181 HDC hDC
= GetDC( 0 );
182 int nBitsPixel
= GetDeviceCaps( hDC
, BITSPIXEL
);
183 int nPlanes
= GetDeviceCaps( hDC
, PLANES
);
184 int nRasterCaps
= GetDeviceCaps( hDC
, RASTERCAPS
);
185 int nBitCount
= nBitsPixel
* nPlanes
;
187 if ( (nBitCount
> 8) && (nBitCount
< 24) )
189 // test, if we have to dither
190 HDC hMemDC
= ::CreateCompatibleDC( hDC
);
191 HBITMAP hMemBmp
= ::CreateCompatibleBitmap( hDC
, 8, 8 );
192 HBITMAP hBmpOld
= (HBITMAP
) ::SelectObject( hMemDC
, hMemBmp
);
193 HBRUSH hMemBrush
= ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
194 HBRUSH hBrushOld
= (HBRUSH
) ::SelectObject( hMemDC
, hMemBrush
);
195 BOOL bDither16
= TRUE
;
197 ::PatBlt( hMemDC
, 0, 0, 8, 8, PATCOPY
);
198 const COLORREF
aCol( ::GetPixel( hMemDC
, 0, 0 ) );
200 for( int nY
= 0; ( nY
< 8 ) && bDither16
; nY
++ )
201 for( int nX
= 0; ( nX
< 8 ) && bDither16
; nX
++ )
202 if( ::GetPixel( hMemDC
, nX
, nY
) != aCol
)
205 ::SelectObject( hMemDC
, hBrushOld
), ::DeleteObject( hMemBrush
);
206 ::SelectObject( hMemDC
, hBmpOld
), ::DeleteObject( hMemBmp
);
207 ::DeleteDC( hMemDC
);
211 // create DIBPattern for 16Bit dithering
214 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, sizeof( BITMAPINFOHEADER
) + 192 );
215 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
216 pSalData
->mpDitherDiff
= new long[ 256 ];
217 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
218 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
219 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
);
220 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
222 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
224 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
228 pBIH
->biBitCount
= 24;
230 for( n
= 0; n
< 256L; n
++ )
231 pSalData
->mpDitherDiff
[ n
] = n
- ( n
& 248L );
233 for( n
= 0; n
< 256L; n
++ )
234 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
& 248 );
236 for( n
= 0; n
< 256L; n
++ )
237 pSalData
->mpDitherHigh
[ n
] = (BYTE
) Min( pSalData
->mpDitherLow
[ n
] + 8L, 255L );
240 else if ( (nRasterCaps
& RC_PALETTE
) && (nBitCount
== 8) )
242 BYTE nRed
, nGreen
, nBlue
;
244 PALETTEENTRY
* pPalEntry
;
246 const USHORT nDitherPalCount
= DITHER_PAL_COUNT
;
247 ULONG nTotalCount
= DITHER_MAX_SYSCOLOR
+ nDitherPalCount
+ DITHER_EXTRA_COLORS
;
249 // create logical palette
250 pLogPal
= (LOGPALETTE
*) new char[ sizeof( LOGPALETTE
) + ( nTotalCount
* sizeof( PALETTEENTRY
) ) ];
251 pLogPal
->palVersion
= 0x0300;
252 pLogPal
->palNumEntries
= (USHORT
) nTotalCount
;
253 pPalEntry
= pLogPal
->palPalEntry
;
256 memcpy( pPalEntry
, aImplSalSysPalEntryAry
, DITHER_MAX_SYSCOLOR
* sizeof( PALETTEENTRY
) );
257 pPalEntry
+= DITHER_MAX_SYSCOLOR
;
259 // own palette (6/6/6)
260 for( nB
=0, nBlue
=0; nB
< DITHER_PAL_STEPS
; nB
++, nBlue
+= DITHER_PAL_DELTA
)
262 for( nG
=0, nGreen
=0; nG
< DITHER_PAL_STEPS
; nG
++, nGreen
+= DITHER_PAL_DELTA
)
264 for( nR
=0, nRed
=0; nR
< DITHER_PAL_STEPS
; nR
++, nRed
+= DITHER_PAL_DELTA
)
266 pPalEntry
->peRed
= nRed
;
267 pPalEntry
->peGreen
= nGreen
;
268 pPalEntry
->peBlue
= nBlue
;
269 pPalEntry
->peFlags
= 0;
275 // insert special 'Blue' as standard drawing color
276 *pPalEntry
++ = aImplExtraColor1
;
279 pSalData
->mhDitherPal
= CreatePalette( pLogPal
);
280 delete[] (char*) pLogPal
;
282 if( pSalData
->mhDitherPal
)
284 // create DIBPattern for 8Bit dithering
285 long nSize
= sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) ) + 64;
288 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, nSize
);
289 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
290 pSalData
->mpDitherDiff
= new long[ 256 ];
291 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
292 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
293 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) );
294 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
296 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
297 short* pColors
= (short*) ( pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) );
299 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
303 pBIH
->biBitCount
= 8;
305 for( n
= 0; n
< nDitherPalCount
; n
++ )
306 pColors
[ n
] = (short)( n
+ DITHER_MAX_SYSCOLOR
);
308 for( n
= 0; n
< 256L; n
++ )
309 pSalData
->mpDitherDiff
[ n
] = n
% 51L;
311 for( n
= 0; n
< 256L; n
++ )
312 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
/ 51L );
314 for( n
= 0; n
< 256L; n
++ )
315 pSalData
->mpDitherHigh
[ n
] = (BYTE
)Min( pSalData
->mpDitherLow
[ n
] + 1, 5 );
318 // get system color entries
319 ImplUpdateSysColorEntries();
325 // -----------------------------------------------------------------------
327 void ImplFreeSalGDI()
329 SalData
* pSalData
= GetSalData();
331 // destroy stock objects
333 for ( i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
334 DeletePen( pSalData
->mhStockPenAry
[i
] );
335 for ( i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
336 DeleteBrush( pSalData
->mhStockBrushAry
[i
] );
338 // 50% Brush loeschen
339 if ( pSalData
->mh50Brush
)
341 DeleteBrush( pSalData
->mh50Brush
);
342 pSalData
->mh50Brush
= 0;
345 // 50% Bitmap loeschen
346 if ( pSalData
->mh50Bmp
)
348 DeleteBitmap( pSalData
->mh50Bmp
);
349 pSalData
->mh50Bmp
= 0;
352 ImplClearHDCCache( pSalData
);
353 delete[] pSalData
->mpHDCCache
;
355 // Ditherpalette loeschen, wenn vorhanden
356 if ( pSalData
->mhDitherPal
)
358 DeleteObject( pSalData
->mhDitherPal
);
359 pSalData
->mhDitherPal
= 0;
362 // delete buffers for dithering DIB patterns, if neccessary
363 if ( pSalData
->mhDitherDIB
)
365 GlobalUnlock( pSalData
->mhDitherDIB
);
366 GlobalFree( pSalData
->mhDitherDIB
);
367 pSalData
->mhDitherDIB
= 0;
368 delete[] pSalData
->mpDitherDiff
;
369 delete[] pSalData
->mpDitherLow
;
370 delete[] pSalData
->mpDitherHigh
;
373 // delete SysColorList
374 SysColorEntry
* pEntry
= pFirstSysColor
;
377 SysColorEntry
* pTmp
= pEntry
->pNext
;
381 pFirstSysColor
= NULL
;
384 SalIcon
* pIcon
= pSalData
->mpFirstIcon
;
385 pSalData
->mpFirstIcon
= NULL
;
388 SalIcon
* pTmp
= pIcon
->pNext
;
389 DestroyIcon( pIcon
->hIcon
);
390 DestroyIcon( pIcon
->hSmallIcon
);
395 // delete temporary font list
396 ImplReleaseTempFonts( *pSalData
);
399 // -----------------------------------------------------------------------
401 static int ImplIsPaletteEntry( BYTE nRed
, BYTE nGreen
, BYTE nBlue
)
404 if ( !(nRed
% DITHER_PAL_DELTA
) && !(nGreen
% DITHER_PAL_DELTA
) && !(nBlue
% DITHER_PAL_DELTA
) )
407 PALETTEENTRY
* pPalEntry
= aImplSalSysPalEntryAry
;
409 // standard palette color?
410 for ( USHORT i
= 0; i
< DITHER_MAX_SYSCOLOR
; i
++, pPalEntry
++ )
412 if( pPalEntry
->peRed
== nRed
&& pPalEntry
->peGreen
== nGreen
&& pPalEntry
->peBlue
== nBlue
)
417 if ( aImplExtraColor1
.peRed
== nRed
&&
418 aImplExtraColor1
.peGreen
== nGreen
&&
419 aImplExtraColor1
.peBlue
== nBlue
)
427 // =======================================================================
429 int ImplIsSysColorEntry( SalColor nSalColor
)
431 SysColorEntry
* pEntry
= pFirstSysColor
;
432 const DWORD nTestRGB
= (DWORD
)RGB( SALCOLOR_RED( nSalColor
),
433 SALCOLOR_GREEN( nSalColor
),
434 SALCOLOR_BLUE( nSalColor
) );
438 if ( pEntry
->nRGB
== nTestRGB
)
440 pEntry
= pEntry
->pNext
;
446 // =======================================================================
448 static void ImplInsertSysColorEntry( int nSysIndex
)
450 const DWORD nRGB
= GetSysColor( nSysIndex
);
452 if ( !ImplIsPaletteEntry( GetRValue( nRGB
), GetGValue( nRGB
), GetBValue( nRGB
) ) )
454 if ( !pFirstSysColor
)
456 pActSysColor
= pFirstSysColor
= new SysColorEntry
;
457 pFirstSysColor
->nRGB
= nRGB
;
458 pFirstSysColor
->pNext
= NULL
;
462 pActSysColor
= pActSysColor
->pNext
= new SysColorEntry
;
463 pActSysColor
->nRGB
= nRGB
;
464 pActSysColor
->pNext
= NULL
;
469 // =======================================================================
471 void ImplUpdateSysColorEntries()
473 // delete old SysColorList
474 SysColorEntry
* pEntry
= pFirstSysColor
;
477 SysColorEntry
* pTmp
= pEntry
->pNext
;
481 pActSysColor
= pFirstSysColor
= NULL
;
483 // create new sys color list
484 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER
);
485 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER
);
486 if( aSalShlData
.mnVersion
>= 410 )
488 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION
);
489 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION
);
491 ImplInsertSysColorEntry( COLOR_3DFACE
);
492 ImplInsertSysColorEntry( COLOR_3DHILIGHT
);
493 ImplInsertSysColorEntry( COLOR_3DLIGHT
);
494 ImplInsertSysColorEntry( COLOR_3DSHADOW
);
495 ImplInsertSysColorEntry( COLOR_3DDKSHADOW
);
496 ImplInsertSysColorEntry( COLOR_INFOBK
);
497 ImplInsertSysColorEntry( COLOR_INFOTEXT
);
498 ImplInsertSysColorEntry( COLOR_BTNTEXT
);
499 ImplInsertSysColorEntry( COLOR_WINDOW
);
500 ImplInsertSysColorEntry( COLOR_WINDOWTEXT
);
501 ImplInsertSysColorEntry( COLOR_HIGHLIGHT
);
502 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT
);
503 ImplInsertSysColorEntry( COLOR_MENU
);
504 ImplInsertSysColorEntry( COLOR_MENUTEXT
);
505 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION
);
506 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT
);
507 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION
);
508 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT
);
511 // -----------------------------------------------------------------------
513 static SalColor
ImplGetROPSalColor( SalROPColor nROPColor
)
516 if ( nROPColor
== SAL_ROP_0
)
517 nSalColor
= MAKE_SALCOLOR( 0, 0, 0 );
519 nSalColor
= MAKE_SALCOLOR( 255, 255, 255 );
523 // =======================================================================
525 void ImplSalInitGraphics( WinSalGraphics
* pData
)
527 // Beim Printer berechnen wir die minimale Linienstaerke
528 if ( pData
->mbPrinter
)
530 int nDPIX
= GetDeviceCaps( pData
->mhDC
, LOGPIXELSX
);
532 pData
->mnPenWidth
= 0;
534 pData
->mnPenWidth
= nDPIX
/300;
537 ::SetTextAlign( pData
->mhDC
, TA_BASELINE
| TA_LEFT
| TA_NOUPDATECP
);
538 ::SetBkMode( pData
->mhDC
, TRANSPARENT
);
539 ::SetROP2( pData
->mhDC
, R2_COPYPEN
);
542 // -----------------------------------------------------------------------
544 void ImplSalDeInitGraphics( WinSalGraphics
* pData
)
546 // Default Objekte selektieren
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( 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( 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( 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 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 ULONG nCurrPoints
= *pPoints
++;
640 const bool bHaveFlagArray( pCurrFlag
);
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
, 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 USHORT
WinSalGraphics::GetBitCount()
813 return (USHORT
)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 void WinSalGraphics::BeginSetClipRegion( ULONG nRectCount
)
859 DeleteRegion( mhRegion
);
863 ULONG nRectBufSize
= sizeof(RECT
)*nRectCount
;
864 if ( nRectCount
< SAL_CLIPRECT_COUNT
)
866 if ( !mpStdClipRgnData
)
867 mpStdClipRgnData
= (RGNDATA
*)new BYTE
[sizeof(RGNDATA
)-1+(SAL_CLIPRECT_COUNT
*sizeof(RECT
))];
868 mpClipRgnData
= mpStdClipRgnData
;
871 mpClipRgnData
= (RGNDATA
*)new BYTE
[sizeof(RGNDATA
)-1+nRectBufSize
];
872 mpClipRgnData
->rdh
.dwSize
= sizeof( RGNDATAHEADER
);
873 mpClipRgnData
->rdh
.iType
= RDH_RECTANGLES
;
874 mpClipRgnData
->rdh
.nCount
= nRectCount
;
875 mpClipRgnData
->rdh
.nRgnSize
= nRectBufSize
;
876 SetRectEmpty( &(mpClipRgnData
->rdh
.rcBound
) );
877 mpNextClipRect
= (RECT
*)(&(mpClipRgnData
->Buffer
));
878 mbFirstClipRect
= TRUE
;
882 // -----------------------------------------------------------------------
884 BOOL
WinSalGraphics::unionClipRegion( long nX
, long nY
, long nWidth
, long nHeight
)
886 if ( nWidth
&& nHeight
)
888 RECT
* pRect
= mpNextClipRect
;
889 RECT
* pBoundRect
= &(mpClipRgnData
->rdh
.rcBound
);
890 long nRight
= nX
+ nWidth
;
891 long nBottom
= nY
+ nHeight
;
893 if ( mbFirstClipRect
)
895 pBoundRect
->left
= nX
;
896 pBoundRect
->top
= nY
;
897 pBoundRect
->right
= nRight
;
898 pBoundRect
->bottom
= nBottom
;
899 mbFirstClipRect
= FALSE
;
903 if ( nX
< pBoundRect
->left
)
904 pBoundRect
->left
= (int)nX
;
906 if ( nY
< pBoundRect
->top
)
907 pBoundRect
->top
= (int)nY
;
909 if ( nRight
> pBoundRect
->right
)
910 pBoundRect
->right
= (int)nRight
;
912 if ( nBottom
> pBoundRect
->bottom
)
913 pBoundRect
->bottom
= (int)nBottom
;
916 pRect
->left
= (int)nX
;
917 pRect
->top
= (int)nY
;
918 pRect
->right
= (int)nRight
;
919 pRect
->bottom
= (int)nBottom
;
924 mpClipRgnData
->rdh
.nCount
--;
925 mpClipRgnData
->rdh
.nRgnSize
-= sizeof( RECT
);
931 // -----------------------------------------------------------------------
933 bool WinSalGraphics::unionClipRegion( const ::basegfx::B2DPolyPolygon
& )
935 // TODO: implement and advertise OutDevSupport_B2DClip support
939 // -----------------------------------------------------------------------
941 void WinSalGraphics::EndSetClipRegion()
943 // create clip region from ClipRgnData
944 if ( mpClipRgnData
->rdh
.nCount
== 1 )
946 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
947 mhRegion
= CreateRectRgn( pRect
->left
, pRect
->top
,
948 pRect
->right
, pRect
->bottom
);
952 ULONG nSize
= mpClipRgnData
->rdh
.nRgnSize
+sizeof(RGNDATAHEADER
);
953 mhRegion
= ExtCreateRegion( NULL
, nSize
, mpClipRgnData
);
955 // if ExtCreateRegion(...) is not supported
958 RGNDATAHEADER
* pHeader
= (RGNDATAHEADER
*) mpClipRgnData
;
960 if( pHeader
->nCount
)
962 RECT
* pRect
= (RECT
*) mpClipRgnData
->Buffer
;
963 mhRegion
= CreateRectRgn( pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
966 for( ULONG n
= 1; n
< pHeader
->nCount
; n
++, pRect
++ )
968 HRGN hRgn
= CreateRectRgn( pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
969 CombineRgn( mhRegion
, mhRegion
, hRgn
, RGN_OR
);
970 DeleteRegion( hRgn
);
975 if ( mpClipRgnData
!= mpStdClipRgnData
)
976 delete [] mpClipRgnData
;
979 SelectClipRgn( mhDC
, mhRegion
);
982 // -----------------------------------------------------------------------
984 void WinSalGraphics::SetLineColor()
986 // create and select new pen
987 HPEN hNewPen
= GetStockPen( NULL_PEN
);
988 HPEN hOldPen
= SelectPen( mhDC
, hNewPen
);
990 // destory or save old pen
1005 // -----------------------------------------------------------------------
1007 void WinSalGraphics::SetLineColor( SalColor nSalColor
)
1009 maLineColor
= nSalColor
;
1010 COLORREF nPenColor
= PALETTERGB( SALCOLOR_RED( nSalColor
),
1011 SALCOLOR_GREEN( nSalColor
),
1012 SALCOLOR_BLUE( nSalColor
) );
1014 BOOL bStockPen
= FALSE
;
1016 // search for stock pen (only screen, because printer have problems,
1017 // when we use stock objects)
1020 SalData
* pSalData
= GetSalData();
1021 for ( USHORT i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
1023 if ( nPenColor
== pSalData
->maStockPenColorAry
[i
] )
1025 hNewPen
= pSalData
->mhStockPenAry
[i
];
1037 if ( GetSalData()->mhDitherPal
&& ImplIsSysColorEntry( nSalColor
) )
1038 nPenColor
= PALRGB_TO_RGB( nPenColor
);
1041 hNewPen
= CreatePen( PS_SOLID
, mnPenWidth
, nPenColor
);
1046 HPEN hOldPen
= SelectPen( mhDC
, hNewPen
);
1048 // destory or save old pen
1058 mnPenColor
= nPenColor
;
1061 mbStockPen
= bStockPen
;
1064 // -----------------------------------------------------------------------
1066 void WinSalGraphics::SetFillColor()
1068 // create and select new brush
1069 HBRUSH hNewBrush
= GetStockBrush( NULL_BRUSH
);
1070 HBRUSH hOldBrush
= SelectBrush( mhDC
, hNewBrush
);
1072 // destory or save old brush
1075 if ( !mbStockBrush
)
1076 DeleteBrush( mhBrush
);
1079 mhDefBrush
= hOldBrush
;
1082 mhBrush
= hNewBrush
;
1084 mbStockBrush
= TRUE
;
1087 // -----------------------------------------------------------------------
1089 void WinSalGraphics::SetFillColor( SalColor nSalColor
)
1091 maFillColor
= nSalColor
;
1092 SalData
* pSalData
= GetSalData();
1093 BYTE nRed
= SALCOLOR_RED( nSalColor
);
1094 BYTE nGreen
= SALCOLOR_GREEN( nSalColor
);
1095 BYTE nBlue
= SALCOLOR_BLUE( nSalColor
);
1096 COLORREF nBrushColor
= PALETTERGB( nRed
, nGreen
, nBlue
);
1097 HBRUSH hNewBrush
= 0;
1098 BOOL bStockBrush
= FALSE
;
1100 // search for stock brush (only screen, because printer have problems,
1101 // when we use stock objects)
1104 for ( USHORT i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
1106 if ( nBrushColor
== pSalData
->maStockBrushColorAry
[ i
] )
1108 hNewBrush
= pSalData
->mhStockBrushAry
[i
];
1118 if ( mbPrinter
|| !pSalData
->mhDitherDIB
)
1119 hNewBrush
= CreateSolidBrush( nBrushColor
);
1122 if ( 24 == ((BITMAPINFOHEADER
*)pSalData
->mpDitherDIB
)->biBitCount
)
1124 BYTE
* pTmp
= pSalData
->mpDitherDIBData
;
1125 long* pDitherDiff
= pSalData
->mpDitherDiff
;
1126 BYTE
* pDitherLow
= pSalData
->mpDitherLow
;
1127 BYTE
* pDitherHigh
= pSalData
->mpDitherHigh
;
1129 for( long nY
= 0L; nY
< 8L; nY
++ )
1131 for( long nX
= 0L; nX
< 8L; nX
++ )
1133 const long nThres
= aOrdDither16Bit
[ nY
][ nX
];
1134 *pTmp
++ = DMAP( nBlue
, nThres
);
1135 *pTmp
++ = DMAP( nGreen
, nThres
);
1136 *pTmp
++ = DMAP( nRed
, nThres
);
1140 hNewBrush
= CreateDIBPatternBrush( pSalData
->mhDitherDIB
, DIB_RGB_COLORS
);
1142 else if ( ImplIsSysColorEntry( nSalColor
) )
1144 nBrushColor
= PALRGB_TO_RGB( nBrushColor
);
1145 hNewBrush
= CreateSolidBrush( nBrushColor
);
1147 else if ( ImplIsPaletteEntry( nRed
, nGreen
, nBlue
) )
1148 hNewBrush
= CreateSolidBrush( nBrushColor
);
1151 BYTE
* pTmp
= pSalData
->mpDitherDIBData
;
1152 long* pDitherDiff
= pSalData
->mpDitherDiff
;
1153 BYTE
* pDitherLow
= pSalData
->mpDitherLow
;
1154 BYTE
* pDitherHigh
= pSalData
->mpDitherHigh
;
1156 for ( long nY
= 0L; nY
< 8L; nY
++ )
1158 for ( long nX
= 0L; nX
< 8L; nX
++ )
1160 const long nThres
= aOrdDither8Bit
[ nY
][ nX
];
1161 *pTmp
= DMAP( nRed
, nThres
) + DMAP( nGreen
, nThres
) * 6 + DMAP( nBlue
, nThres
) * 36;
1166 hNewBrush
= CreateDIBPatternBrush( pSalData
->mhDitherDIB
, DIB_PAL_COLORS
);
1170 bStockBrush
= FALSE
;
1174 HBRUSH hOldBrush
= SelectBrush( mhDC
, hNewBrush
);
1176 // destory or save old brush
1179 if ( !mbStockBrush
)
1180 DeleteBrush( mhBrush
);
1183 mhDefBrush
= hOldBrush
;
1186 mnBrushColor
= nBrushColor
;
1187 mhBrush
= hNewBrush
;
1189 mbStockBrush
= bStockBrush
;
1192 // -----------------------------------------------------------------------
1194 void WinSalGraphics::SetXORMode( bool bSet
, bool )
1197 ::SetROP2( mhDC
, bSet
? R2_XORPEN
: R2_COPYPEN
);
1200 // -----------------------------------------------------------------------
1202 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
1204 SetLineColor( ImplGetROPSalColor( nROPColor
) );
1207 // -----------------------------------------------------------------------
1209 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
1211 SetFillColor( ImplGetROPSalColor( nROPColor
) );
1214 // -----------------------------------------------------------------------
1216 void WinSalGraphics::drawPixel( long nX
, long nY
)
1220 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1221 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1222 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)1, (int)1, PATINVERT
);
1223 SelectBrush( mhDC
, hOldBrush
);
1224 DeleteBrush( hBrush
);
1227 SetPixel( mhDC
, (int)nX
, (int)nY
, mnPenColor
);
1230 // -----------------------------------------------------------------------
1232 void WinSalGraphics::drawPixel( long nX
, long nY
, SalColor nSalColor
)
1234 COLORREF nCol
= PALETTERGB( SALCOLOR_RED( nSalColor
),
1235 SALCOLOR_GREEN( nSalColor
),
1236 SALCOLOR_BLUE( nSalColor
) );
1239 GetSalData()->mhDitherPal
&&
1240 ImplIsSysColorEntry( nSalColor
) )
1241 nCol
= PALRGB_TO_RGB( nCol
);
1245 HBRUSH hBrush
= CreateSolidBrush( nCol
);
1246 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1247 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)1, (int)1, PATINVERT
);
1248 SelectBrush( mhDC
, hOldBrush
);
1249 DeleteBrush( hBrush
);
1252 ::SetPixel( mhDC
, (int)nX
, (int)nY
, nCol
);
1255 // -----------------------------------------------------------------------
1257 void WinSalGraphics::drawLine( long nX1
, long nY1
, long nX2
, long nY2
)
1259 MoveToEx( mhDC
, (int)nX1
, (int)nY1
, NULL
);
1261 // we must paint the endpoint
1262 int bPaintEnd
= TRUE
;
1280 LineTo( mhDC
, (int)nX2
, (int)nY2
);
1282 if ( bPaintEnd
&& !mbPrinter
)
1286 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1287 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1288 PatBlt( mhDC
, (int)nX2
, (int)nY2
, (int)1, (int)1, PATINVERT
);
1289 SelectBrush( mhDC
, hOldBrush
);
1290 DeleteBrush( hBrush
);
1293 SetPixel( mhDC
, (int)nX2
, (int)nY2
, mnPenColor
);
1297 // -----------------------------------------------------------------------
1299 void WinSalGraphics::drawRect( long nX
, long nY
, long nWidth
, long nHeight
)
1305 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)nWidth
, (int)nHeight
,
1306 mbXORMode
? PATINVERT
: PATCOPY
);
1313 aWinRect
.right
= nX
+nWidth
;
1314 aWinRect
.bottom
= nY
+nHeight
;
1315 ::FillRect( mhDC
, &aWinRect
, mhBrush
);
1319 WIN_Rectangle( mhDC
, (int)nX
, (int)nY
, (int)(nX
+nWidth
), (int)(nY
+nHeight
) );
1322 // -----------------------------------------------------------------------
1324 void WinSalGraphics::drawPolyLine( ULONG nPoints
, const SalPoint
* pPtAry
)
1326 // Unter NT koennen wir das Array direkt weiterreichen
1327 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1328 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
1330 POINT
* pWinPtAry
= (POINT
*)pPtAry
;
1331 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
1333 if ( !Polyline( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
1334 Polyline( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
1337 // -----------------------------------------------------------------------
1339 void WinSalGraphics::drawPolygon( ULONG nPoints
, const SalPoint
* pPtAry
)
1341 // Unter NT koennen wir das Array direkt weiterreichen
1342 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1343 "WinSalGraphics::DrawPolygon(): POINT != SalPoint" );
1345 POINT
* pWinPtAry
= (POINT
*)pPtAry
;
1346 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl
1348 if ( !WIN_Polygon( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
1349 WIN_Polygon( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
1352 // -----------------------------------------------------------------------
1354 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
1355 PCONSTSALPOINT
* pPtAry
)
1357 UINT aWinPointAry
[SAL_POLYPOLYCOUNT_STACKBUF
];
1359 UINT nPolyPolyPoints
= 0;
1363 if ( nPoly
<= SAL_POLYPOLYCOUNT_STACKBUF
)
1364 pWinPointAry
= aWinPointAry
;
1366 pWinPointAry
= new UINT
[nPoly
];
1368 for ( i
= 0; i
< (UINT
)nPoly
; i
++ )
1370 nPoints
= (UINT
)pPoints
[i
]+1;
1371 pWinPointAry
[i
] = nPoints
;
1372 nPolyPolyPoints
+= nPoints
;
1375 POINT aWinPointAryAry
[SAL_POLYPOLYPOINTS_STACKBUF
];
1376 POINT
* pWinPointAryAry
;
1377 if ( nPolyPolyPoints
<= SAL_POLYPOLYPOINTS_STACKBUF
)
1378 pWinPointAryAry
= aWinPointAryAry
;
1380 pWinPointAryAry
= new POINT
[nPolyPolyPoints
];
1381 // Unter NT koennen wir das Array direkt weiterreichen
1382 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1383 "WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" );
1384 const SalPoint
* pPolyAry
;
1386 for ( i
= 0; i
< (UINT
)nPoly
; i
++ )
1388 nPoints
= pWinPointAry
[i
];
1389 pPolyAry
= pPtAry
[i
];
1390 memcpy( pWinPointAryAry
+n
, pPolyAry
, (nPoints
-1)*sizeof(POINT
) );
1391 pWinPointAryAry
[n
+nPoints
-1] = pWinPointAryAry
[n
];
1395 if ( !WIN_PolyPolygon( mhDC
, pWinPointAryAry
, (int*)pWinPointAry
, (UINT
)nPoly
) &&
1396 (nPolyPolyPoints
> MAX_64KSALPOINTS
) )
1398 nPolyPolyPoints
= 0;
1402 nPolyPolyPoints
+= pWinPointAry
[(UINT
)nPoly
];
1405 while ( nPolyPolyPoints
< MAX_64KSALPOINTS
);
1407 if ( pWinPointAry
[(UINT
)nPoly
] > MAX_64KSALPOINTS
)
1408 pWinPointAry
[(UINT
)nPoly
] = MAX_64KSALPOINTS
;
1410 WIN_Polygon( mhDC
, pWinPointAryAry
, *pWinPointAry
);
1412 WIN_PolyPolygon( mhDC
, pWinPointAryAry
, (int*)pWinPointAry
, nPoly
);
1415 if ( pWinPointAry
!= aWinPointAry
)
1416 delete [] pWinPointAry
;
1417 if ( pWinPointAryAry
!= aWinPointAryAry
)
1418 delete [] pWinPointAryAry
;
1421 // -----------------------------------------------------------------------
1423 #define SAL_POLY_STACKBUF 32
1425 // -----------------------------------------------------------------------
1427 sal_Bool
WinSalGraphics::drawPolyLineBezier( ULONG nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
1429 #ifdef USE_GDI_BEZIERS
1430 // Unter NT koennen wir das Array direkt weiterreichen
1431 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1432 "WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" );
1434 ImplRenderPath( mhDC
, nPoints
, pPtAry
, pFlgAry
);
1442 // -----------------------------------------------------------------------
1444 sal_Bool
WinSalGraphics::drawPolygonBezier( ULONG nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
1446 #ifdef USE_GDI_BEZIERS
1447 // Unter NT koennen wir das Array direkt weiterreichen
1448 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1449 "WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" );
1451 POINT aStackAry1
[SAL_POLY_STACKBUF
];
1452 BYTE aStackAry2
[SAL_POLY_STACKBUF
];
1453 POINT
* pWinPointAry
;
1455 if( nPoints
> SAL_POLY_STACKBUF
)
1457 pWinPointAry
= new POINT
[ nPoints
];
1458 pWinFlagAry
= new BYTE
[ nPoints
];
1462 pWinPointAry
= aStackAry1
;
1463 pWinFlagAry
= aStackAry2
;
1466 ImplPreparePolyDraw(true, 1, &nPoints
, &pPtAry
, &pFlgAry
, pWinPointAry
, pWinFlagAry
);
1468 sal_Bool
bRet( sal_False
);
1470 if( BeginPath( mhDC
) )
1472 PolyDraw(mhDC
, pWinPointAry
, pWinFlagAry
, nPoints
);
1474 if( EndPath( mhDC
) )
1476 if( StrokeAndFillPath( mhDC
) )
1481 if( pWinPointAry
!= aStackAry1
)
1483 delete [] pWinPointAry
;
1484 delete [] pWinFlagAry
;
1493 // -----------------------------------------------------------------------
1495 sal_Bool
WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
1496 const SalPoint
* const* pPtAry
, const BYTE
* const* pFlgAry
)
1498 #ifdef USE_GDI_BEZIERS
1499 // Unter NT koennen wir das Array direkt weiterreichen
1500 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1501 "WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" );
1503 ULONG nCurrPoly
, nTotalPoints
;
1504 const ULONG
* pCurrPoints
= pPoints
;
1505 for( nCurrPoly
=0, nTotalPoints
=0; nCurrPoly
<nPoly
; ++nCurrPoly
)
1506 nTotalPoints
+= *pCurrPoints
++;
1508 POINT aStackAry1
[SAL_POLY_STACKBUF
];
1509 BYTE aStackAry2
[SAL_POLY_STACKBUF
];
1510 POINT
* pWinPointAry
;
1512 if( nTotalPoints
> SAL_POLY_STACKBUF
)
1514 pWinPointAry
= new POINT
[ nTotalPoints
];
1515 pWinFlagAry
= new BYTE
[ nTotalPoints
];
1519 pWinPointAry
= aStackAry1
;
1520 pWinFlagAry
= aStackAry2
;
1523 ImplPreparePolyDraw(true, nPoly
, pPoints
, pPtAry
, pFlgAry
, pWinPointAry
, pWinFlagAry
);
1525 sal_Bool
bRet( sal_False
);
1527 if( BeginPath( mhDC
) )
1529 PolyDraw(mhDC
, pWinPointAry
, pWinFlagAry
, nTotalPoints
);
1531 if( EndPath( mhDC
) )
1533 if( StrokeAndFillPath( mhDC
) )
1538 if( pWinPointAry
!= aStackAry1
)
1540 delete [] pWinPointAry
;
1541 delete [] pWinFlagAry
;
1550 // -----------------------------------------------------------------------
1552 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
1553 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox
1554 // in the first 4096 bytes
1556 static BYTE
* ImplSearchEntry( BYTE
* pSource
, BYTE
* pDest
, ULONG nComp
, ULONG nSize
)
1558 while ( nComp
-- >= nSize
)
1561 for ( i
= 0; i
< nSize
; i
++ )
1563 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
1573 static BOOL
ImplGetBoundingBox( double* nNumb
, BYTE
* pSource
, ULONG nSize
)
1575 BOOL bRetValue
= FALSE
;
1576 BYTE
* pDest
= ImplSearchEntry( pSource
, (BYTE
*)"%%BoundingBox:", nSize
, 14 );
1579 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
1582 int nSizeLeft
= nSize
- ( pDest
- pSource
);
1583 if ( nSizeLeft
> 100 )
1584 nSizeLeft
= 100; // only 100 bytes following the bounding box will be checked
1587 for ( i
= 0; ( i
< 4 ) && nSizeLeft
; i
++ )
1590 BOOL bDivision
= FALSE
;
1591 BOOL bNegative
= FALSE
;
1594 while ( ( --nSizeLeft
) && ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) pDest
++;
1595 BYTE nByte
= *pDest
;
1596 while ( nSizeLeft
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
1610 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
1611 nSizeLeft
= 1; // error parsing the bounding box values
1617 nNumb
[i
] += nByte
- '0';
1625 nNumb
[i
] = -nNumb
[i
];
1626 if ( bDivision
&& ( nDivision
!= 1 ) )
1627 nNumb
[i
] /= nDivision
;
1635 BOOL
WinSalGraphics::drawEPS( long nX
, long nY
, long nWidth
, long nHeight
, void* pPtr
, ULONG nSize
)
1637 BOOL bRetValue
= FALSE
;
1641 int nEscape
= POSTSCRIPT_PASSTHROUGH
;
1643 if ( Escape( mhDC
, QUERYESCSUPPORT
, sizeof( int ), ( LPSTR
)&nEscape
, 0 ) )
1645 double nBoundingBox
[4];
1647 if ( ImplGetBoundingBox( nBoundingBox
, (BYTE
*)pPtr
, nSize
) )
1649 OStringBuffer
aBuf( POSTSCRIPT_BUFSIZE
);
1651 // reserve place for a USHORT
1652 aBuf
.append( "aa" );
1654 // #107797# Write out EPS encapsulation header
1655 // ----------------------------------------------------------------------------------
1657 // directly taken from the PLRM 3.0, p. 726. Note:
1658 // this will definitely cause problems when
1659 // recursively creating and embedding PostScript files
1660 // in OOo, since we use statically-named variables
1661 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
1662 // op_count_salWin). Currently, I have no idea on how to
1663 // work around that, except from scanning and
1664 // interpreting the EPS for unused identifiers.
1666 // append the real text
1667 aBuf
.append( "\n\n/b4_Inc_state_salWin save def\n"
1668 "/dict_count_salWin countdictstack def\n"
1669 "/op_count_salWin count 1 sub def\n"
1671 "/showpage {} def\n"
1672 "0 setgray 0 setlinecap\n"
1673 "1 setlinewidth 0 setlinejoin\n"
1674 "10 setmiterlimit [] 0 setdash newpath\n"
1675 "/languagelevel where\n"
1677 " pop languagelevel\n"
1680 " false setstrokeadjust false setoverprint\n"
1685 // #i10737# Apply clipping manually
1686 // ----------------------------------------------------------------------------------
1688 // Windows seems to ignore any clipping at the HDC,
1689 // when followed by a POSTSCRIPT_PASSTHROUGH
1691 // Check whether we've got a clipping, consisting of
1692 // exactly one rect (other cases should be, but aren't
1693 // handled currently)
1695 // TODO: Handle more than one rectangle here (take
1696 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
1698 if ( mhRegion
!= 0 &&
1699 mpStdClipRgnData
!= NULL
&&
1700 mpClipRgnData
== mpStdClipRgnData
&&
1701 mpClipRgnData
->rdh
.nCount
== 1 )
1703 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
1705 aBuf
.append( "\nnewpath\n" );
1706 aBuf
.append( pRect
->left
);
1708 aBuf
.append( pRect
->top
);
1709 aBuf
.append( " moveto\n" );
1710 aBuf
.append( pRect
->right
);
1712 aBuf
.append( pRect
->top
);
1713 aBuf
.append( " lineto\n" );
1714 aBuf
.append( pRect
->right
);
1716 aBuf
.append( pRect
->bottom
);
1717 aBuf
.append( " lineto\n" );
1718 aBuf
.append( pRect
->left
);
1720 aBuf
.append( pRect
->bottom
);
1721 aBuf
.append( " lineto\n"
1727 // #107797# Write out buffer
1728 // ----------------------------------------------------------------------------------
1729 *((USHORT
*)aBuf
.getStr()) = (USHORT
)( aBuf
.getLength() - 2 );
1730 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1733 // #107797# Write out EPS transformation code
1734 // ----------------------------------------------------------------------------------
1735 double dM11
= nWidth
/ ( nBoundingBox
[2] - nBoundingBox
[0] );
1736 double dM22
= nHeight
/ (nBoundingBox
[1] - nBoundingBox
[3] );
1737 // reserve a USHORT again
1738 aBuf
.setLength( 2 );
1739 aBuf
.append( "\n\n[" );
1740 aBuf
.append( dM11
);
1741 aBuf
.append( " 0 0 " );
1742 aBuf
.append( dM22
);
1744 aBuf
.append( nX
- ( dM11
* nBoundingBox
[0] ) );
1746 aBuf
.append( nY
- ( dM22
* nBoundingBox
[3] ) );
1747 aBuf
.append( "] concat\n"
1748 "%%BeginDocument:\n" );
1749 *((USHORT
*)aBuf
.getStr()) = (USHORT
)( aBuf
.getLength() - 2 );
1750 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1753 // #107797# Write out actual EPS content
1754 // ----------------------------------------------------------------------------------
1755 ULONG nToDo
= nSize
;
1760 if ( nToDo
> POSTSCRIPT_BUFSIZE
- 2 )
1761 nDoNow
= POSTSCRIPT_BUFSIZE
- 2;
1762 // the following is based on the string buffer allocation
1763 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1764 *((USHORT
*)aBuf
.getStr()) = (USHORT
)nDoNow
;
1765 memcpy( (void*)(aBuf
.getStr() + 2), (BYTE
*)pPtr
+ nSize
- nToDo
, nDoNow
);
1766 ULONG nResult
= Escape ( mhDC
, nEscape
, nDoNow
+ 2, (LPTSTR
)aBuf
.getStr(), 0 );
1773 // #107797# Write out EPS encapsulation footer
1774 // ----------------------------------------------------------------------------------
1775 // reserve a USHORT again
1776 aBuf
.setLength( 2 );
1777 aBuf
.append( "%%EndDocument\n"
1778 "count op_count_salWin sub {pop} repeat\n"
1779 "countdictstack dict_count_salWin sub {end} repeat\n"
1780 "b4_Inc_state_salWin restore\n\n" );
1781 *((USHORT
*)aBuf
.getStr()) = (USHORT
)( aBuf
.getLength() - 2 );
1782 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1791 // -----------------------------------------------------------------------
1793 SystemGraphicsData
WinSalGraphics::GetGraphicsData() const
1795 SystemGraphicsData aRes
;
1796 aRes
.nSize
= sizeof(aRes
);
1801 // -----------------------------------------------------------------------