1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
9 * This file incorporates work covered by the following license notice:
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
25 #include <rtl/strbuf.hxx>
27 #include <tools/debug.hxx>
28 #include <tools/poly.hxx>
30 #include <basegfx/polygon/b2dpolygon.hxx>
31 #include <basegfx/polygon/b2dpolygontools.hxx>
33 #include <win/wincomp.hxx>
34 #include <win/saldata.hxx>
35 #include <win/salgdi.h>
36 #include <win/salframe.h>
40 // =======================================================================
42 // comment out to prevent use of beziers on GDI functions
43 #define USE_GDI_BEZIERS
45 // =======================================================================
47 #define DITHER_PAL_DELTA 51
48 #define DITHER_PAL_STEPS 6
49 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS)
50 #define DITHER_MAX_SYSCOLOR 16
51 #define DITHER_EXTRA_COLORS 1
52 #define DMAP( _def_nVal, _def_nThres ) ((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal])
54 // =======================================================================
62 // =======================================================================
64 static SysColorEntry
* pFirstSysColor
= NULL
;
65 static SysColorEntry
* pActSysColor
= NULL
;
67 // -----------------------------------------------------------------------------
70 static PALETTEENTRY aImplExtraColor1
=
75 // -----------------------------------------------------------------------------
77 static PALETTEENTRY aImplSalSysPalEntryAry
[ DITHER_MAX_SYSCOLOR
] =
86 { 0x80, 0x80, 0x80, 0 },
87 { 0xC0, 0xC0, 0xC0, 0 },
94 { 0xFF, 0xFF, 0xFF, 0 }
97 // -----------------------------------------------------------------------------
99 static BYTE aOrdDither8Bit
[8][8] =
101 { 0, 38, 9, 48, 2, 40, 12, 50 },
102 { 25, 12, 35, 22, 28, 15, 37, 24 },
103 { 6, 44, 3, 41, 8, 47, 5, 44 },
104 { 32, 19, 28, 16, 34, 21, 31, 18 },
105 { 1, 40, 11, 49, 0, 39, 10, 48 },
106 { 27, 14, 36, 24, 26, 13, 36, 23 },
107 { 8, 46, 4, 43, 7, 45, 4, 42 },
108 { 33, 20, 30, 17, 32, 20, 29, 16 }
111 // -----------------------------------------------------------------------------
113 static BYTE aOrdDither16Bit
[8][8] =
115 { 0, 6, 1, 7, 0, 6, 1, 7 },
116 { 4, 2, 5, 3, 4, 2, 5, 3 },
117 { 1, 7, 0, 6, 1, 7, 0, 6 },
118 { 5, 3, 4, 2, 5, 3, 4, 2 },
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 }
125 // =======================================================================
127 // we must create pens with 1-pixel width; otherwise the S3-graphics card
128 // map has many paint problems when drawing polygons/polyLines and a
130 #define GSL_PEN_WIDTH 1
132 // =======================================================================
134 #define SAL_POLYPOLYCOUNT_STACKBUF 8
135 #define SAL_POLYPOLYPOINTS_STACKBUF 64
137 // =======================================================================
139 void ImplInitSalGDI()
141 SalData
* pSalData
= GetSalData();
143 // init stock brushes
144 pSalData
->maStockPenColorAry
[0] = PALETTERGB( 0, 0, 0 );
145 pSalData
->maStockPenColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
146 pSalData
->maStockPenColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
147 pSalData
->maStockPenColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
148 pSalData
->mhStockPenAry
[0] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[0] );
149 pSalData
->mhStockPenAry
[1] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[1] );
150 pSalData
->mhStockPenAry
[2] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[2] );
151 pSalData
->mhStockPenAry
[3] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[3] );
152 pSalData
->mnStockPenCount
= 4;
154 pSalData
->maStockBrushColorAry
[0] = PALETTERGB( 0, 0, 0 );
155 pSalData
->maStockBrushColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
156 pSalData
->maStockBrushColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
157 pSalData
->maStockBrushColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
158 pSalData
->mhStockBrushAry
[0] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[0] );
159 pSalData
->mhStockBrushAry
[1] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[1] );
160 pSalData
->mhStockBrushAry
[2] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[2] );
161 pSalData
->mhStockBrushAry
[3] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[3] );
162 pSalData
->mnStockBrushCount
= 4;
164 // initialize cache of device contexts
165 pSalData
->mpHDCCache
= new HDCCache
[ CACHESIZE_HDC
];
166 memset( pSalData
->mpHDCCache
, 0, CACHESIZE_HDC
* sizeof( HDCCache
) );
168 // initialize temporary font list
169 pSalData
->mpTempFontItem
= NULL
;
171 // support palettes for 256 color displays
172 HDC hDC
= GetDC( 0 );
173 int nBitsPixel
= GetDeviceCaps( hDC
, BITSPIXEL
);
174 int nPlanes
= GetDeviceCaps( hDC
, PLANES
);
175 int nRasterCaps
= GetDeviceCaps( hDC
, RASTERCAPS
);
176 int nBitCount
= nBitsPixel
* nPlanes
;
178 if ( (nBitCount
> 8) && (nBitCount
< 24) )
180 // test, if we have to dither
181 HDC hMemDC
= ::CreateCompatibleDC( hDC
);
182 HBITMAP hMemBmp
= ::CreateCompatibleBitmap( hDC
, 8, 8 );
183 HBITMAP hBmpOld
= (HBITMAP
) ::SelectObject( hMemDC
, hMemBmp
);
184 HBRUSH hMemBrush
= ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
185 HBRUSH hBrushOld
= (HBRUSH
) ::SelectObject( hMemDC
, hMemBrush
);
186 sal_Bool bDither16
= TRUE
;
188 ::PatBlt( hMemDC
, 0, 0, 8, 8, PATCOPY
);
189 const COLORREF
aCol( ::GetPixel( hMemDC
, 0, 0 ) );
191 for( int nY
= 0; ( nY
< 8 ) && bDither16
; nY
++ )
192 for( int nX
= 0; ( nX
< 8 ) && bDither16
; nX
++ )
193 if( ::GetPixel( hMemDC
, nX
, nY
) != aCol
)
196 ::SelectObject( hMemDC
, hBrushOld
), ::DeleteObject( hMemBrush
);
197 ::SelectObject( hMemDC
, hBmpOld
), ::DeleteObject( hMemBmp
);
198 ::DeleteDC( hMemDC
);
202 // create DIBPattern for 16Bit dithering
205 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, sizeof( BITMAPINFOHEADER
) + 192 );
206 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
207 pSalData
->mpDitherDiff
= new long[ 256 ];
208 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
209 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
210 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
);
211 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
213 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
215 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
219 pBIH
->biBitCount
= 24;
221 for( n
= 0; n
< 256L; n
++ )
222 pSalData
->mpDitherDiff
[ n
] = n
- ( n
& 248L );
224 for( n
= 0; n
< 256L; n
++ )
225 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
& 248 );
227 for( n
= 0; n
< 256L; n
++ )
228 pSalData
->mpDitherHigh
[ n
] = (BYTE
) std::min( pSalData
->mpDitherLow
[ n
] + 8L, 255L );
231 else if ( (nRasterCaps
& RC_PALETTE
) && (nBitCount
== 8) )
233 BYTE nRed
, nGreen
, nBlue
;
235 PALETTEENTRY
* pPalEntry
;
237 const sal_uInt16 nDitherPalCount
= DITHER_PAL_COUNT
;
238 sal_uLong nTotalCount
= DITHER_MAX_SYSCOLOR
+ nDitherPalCount
+ DITHER_EXTRA_COLORS
;
240 // create logical palette
241 pLogPal
= (LOGPALETTE
*) new char[ sizeof( LOGPALETTE
) + ( nTotalCount
* sizeof( PALETTEENTRY
) ) ];
242 pLogPal
->palVersion
= 0x0300;
243 pLogPal
->palNumEntries
= (sal_uInt16
) nTotalCount
;
244 pPalEntry
= pLogPal
->palPalEntry
;
247 memcpy( pPalEntry
, aImplSalSysPalEntryAry
, DITHER_MAX_SYSCOLOR
* sizeof( PALETTEENTRY
) );
248 pPalEntry
+= DITHER_MAX_SYSCOLOR
;
250 // own palette (6/6/6)
251 for( nB
=0, nBlue
=0; nB
< DITHER_PAL_STEPS
; nB
++, nBlue
+= DITHER_PAL_DELTA
)
253 for( nG
=0, nGreen
=0; nG
< DITHER_PAL_STEPS
; nG
++, nGreen
+= DITHER_PAL_DELTA
)
255 for( nR
=0, nRed
=0; nR
< DITHER_PAL_STEPS
; nR
++, nRed
+= DITHER_PAL_DELTA
)
257 pPalEntry
->peRed
= nRed
;
258 pPalEntry
->peGreen
= nGreen
;
259 pPalEntry
->peBlue
= nBlue
;
260 pPalEntry
->peFlags
= 0;
266 // insert special 'Blue' as standard drawing color
267 *pPalEntry
++ = aImplExtraColor1
;
270 pSalData
->mhDitherPal
= CreatePalette( pLogPal
);
271 delete[] (char*) pLogPal
;
273 if( pSalData
->mhDitherPal
)
275 // create DIBPattern for 8Bit dithering
276 long nSize
= sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) ) + 64;
279 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, nSize
);
280 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
281 pSalData
->mpDitherDiff
= new long[ 256 ];
282 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
283 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
284 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) );
285 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
287 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
288 short* pColors
= (short*) ( pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) );
290 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
294 pBIH
->biBitCount
= 8;
296 for( n
= 0; n
< nDitherPalCount
; n
++ )
297 pColors
[ n
] = (short)( n
+ DITHER_MAX_SYSCOLOR
);
299 for( n
= 0; n
< 256L; n
++ )
300 pSalData
->mpDitherDiff
[ n
] = n
% 51L;
302 for( n
= 0; n
< 256L; n
++ )
303 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
/ 51L );
305 for( n
= 0; n
< 256L; n
++ )
306 pSalData
->mpDitherHigh
[ n
] = (BYTE
)std::min( pSalData
->mpDitherLow
[ n
] + 1, 5 );
309 // get system color entries
310 ImplUpdateSysColorEntries();
316 // -----------------------------------------------------------------------
318 void ImplFreeSalGDI()
320 SalData
* pSalData
= GetSalData();
322 // destroy stock objects
324 for ( i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
325 DeletePen( pSalData
->mhStockPenAry
[i
] );
326 for ( i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
327 DeleteBrush( pSalData
->mhStockBrushAry
[i
] );
330 if ( pSalData
->mh50Brush
)
332 DeleteBrush( pSalData
->mh50Brush
);
333 pSalData
->mh50Brush
= 0;
337 if ( pSalData
->mh50Bmp
)
339 DeleteBitmap( pSalData
->mh50Bmp
);
340 pSalData
->mh50Bmp
= 0;
343 ImplClearHDCCache( pSalData
);
344 delete[] pSalData
->mpHDCCache
;
346 // delete Ditherpalette, if existing
347 if ( pSalData
->mhDitherPal
)
349 DeleteObject( pSalData
->mhDitherPal
);
350 pSalData
->mhDitherPal
= 0;
353 // delete buffers for dithering DIB patterns, if necessary
354 if ( pSalData
->mhDitherDIB
)
356 GlobalUnlock( pSalData
->mhDitherDIB
);
357 GlobalFree( pSalData
->mhDitherDIB
);
358 pSalData
->mhDitherDIB
= 0;
359 delete[] pSalData
->mpDitherDiff
;
360 delete[] pSalData
->mpDitherLow
;
361 delete[] pSalData
->mpDitherHigh
;
364 // delete SysColorList
365 SysColorEntry
* pEntry
= pFirstSysColor
;
368 SysColorEntry
* pTmp
= pEntry
->pNext
;
372 pFirstSysColor
= NULL
;
375 SalIcon
* pIcon
= pSalData
->mpFirstIcon
;
376 pSalData
->mpFirstIcon
= NULL
;
379 SalIcon
* pTmp
= pIcon
->pNext
;
380 DestroyIcon( pIcon
->hIcon
);
381 DestroyIcon( pIcon
->hSmallIcon
);
386 // delete temporary font list
387 ImplReleaseTempFonts( *pSalData
);
390 // -----------------------------------------------------------------------
392 static int ImplIsPaletteEntry( BYTE nRed
, BYTE nGreen
, BYTE nBlue
)
395 if ( !(nRed
% DITHER_PAL_DELTA
) && !(nGreen
% DITHER_PAL_DELTA
) && !(nBlue
% DITHER_PAL_DELTA
) )
398 PALETTEENTRY
* pPalEntry
= aImplSalSysPalEntryAry
;
400 // standard palette color?
401 for ( sal_uInt16 i
= 0; i
< DITHER_MAX_SYSCOLOR
; i
++, pPalEntry
++ )
403 if( pPalEntry
->peRed
== nRed
&& pPalEntry
->peGreen
== nGreen
&& pPalEntry
->peBlue
== nBlue
)
408 if ( aImplExtraColor1
.peRed
== nRed
&&
409 aImplExtraColor1
.peGreen
== nGreen
&&
410 aImplExtraColor1
.peBlue
== nBlue
)
418 // =======================================================================
420 int ImplIsSysColorEntry( SalColor nSalColor
)
422 SysColorEntry
* pEntry
= pFirstSysColor
;
423 const DWORD nTestRGB
= (DWORD
)RGB( SALCOLOR_RED( nSalColor
),
424 SALCOLOR_GREEN( nSalColor
),
425 SALCOLOR_BLUE( nSalColor
) );
429 if ( pEntry
->nRGB
== nTestRGB
)
431 pEntry
= pEntry
->pNext
;
437 // =======================================================================
439 static void ImplInsertSysColorEntry( int nSysIndex
)
441 const DWORD nRGB
= GetSysColor( nSysIndex
);
443 if ( !ImplIsPaletteEntry( GetRValue( nRGB
), GetGValue( nRGB
), GetBValue( nRGB
) ) )
445 if ( !pFirstSysColor
)
447 pActSysColor
= pFirstSysColor
= new SysColorEntry
;
448 pFirstSysColor
->nRGB
= nRGB
;
449 pFirstSysColor
->pNext
= NULL
;
453 pActSysColor
= pActSysColor
->pNext
= new SysColorEntry
;
454 pActSysColor
->nRGB
= nRGB
;
455 pActSysColor
->pNext
= NULL
;
460 // =======================================================================
462 void ImplUpdateSysColorEntries()
464 // delete old SysColorList
465 SysColorEntry
* pEntry
= pFirstSysColor
;
468 SysColorEntry
* pTmp
= pEntry
->pNext
;
472 pActSysColor
= pFirstSysColor
= NULL
;
474 // create new sys color list
475 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER
);
476 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER
);
477 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION
);
478 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION
);
479 ImplInsertSysColorEntry( COLOR_3DFACE
);
480 ImplInsertSysColorEntry( COLOR_3DHILIGHT
);
481 ImplInsertSysColorEntry( COLOR_3DLIGHT
);
482 ImplInsertSysColorEntry( COLOR_3DSHADOW
);
483 ImplInsertSysColorEntry( COLOR_3DDKSHADOW
);
484 ImplInsertSysColorEntry( COLOR_INFOBK
);
485 ImplInsertSysColorEntry( COLOR_INFOTEXT
);
486 ImplInsertSysColorEntry( COLOR_BTNTEXT
);
487 ImplInsertSysColorEntry( COLOR_WINDOW
);
488 ImplInsertSysColorEntry( COLOR_WINDOWTEXT
);
489 ImplInsertSysColorEntry( COLOR_HIGHLIGHT
);
490 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT
);
491 ImplInsertSysColorEntry( COLOR_MENU
);
492 ImplInsertSysColorEntry( COLOR_MENUTEXT
);
493 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION
);
494 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT
);
495 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION
);
496 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT
);
499 // -----------------------------------------------------------------------
501 static SalColor
ImplGetROPSalColor( SalROPColor nROPColor
)
504 if ( nROPColor
== SAL_ROP_0
)
505 nSalColor
= MAKE_SALCOLOR( 0, 0, 0 );
507 nSalColor
= MAKE_SALCOLOR( 255, 255, 255 );
511 // =======================================================================
513 void ImplSalInitGraphics( WinSalGraphics
* pData
)
515 // calculate the minimal line width for the printer
516 if ( pData
->mbPrinter
)
518 int nDPIX
= GetDeviceCaps( pData
->mhDC
, LOGPIXELSX
);
520 pData
->mnPenWidth
= 0;
522 pData
->mnPenWidth
= nDPIX
/300;
525 ::SetTextAlign( pData
->mhDC
, TA_BASELINE
| TA_LEFT
| TA_NOUPDATECP
);
526 ::SetBkMode( pData
->mhDC
, TRANSPARENT
);
527 ::SetROP2( pData
->mhDC
, R2_COPYPEN
);
530 // -----------------------------------------------------------------------
532 void ImplSalDeInitGraphics( WinSalGraphics
* pData
)
535 SelectClipRgn( pData
->mhDC
, 0 );
536 // select default objects
537 if ( pData
->mhDefPen
)
538 SelectPen( pData
->mhDC
, pData
->mhDefPen
);
539 if ( pData
->mhDefBrush
)
540 SelectBrush( pData
->mhDC
, pData
->mhDefBrush
);
541 if ( pData
->mhDefFont
)
542 SelectFont( pData
->mhDC
, pData
->mhDefFont
);
545 // =======================================================================
547 HDC
ImplGetCachedDC( sal_uLong nID
, HBITMAP hBmp
)
549 SalData
* pSalData
= GetSalData();
550 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
554 HDC hDC
= GetDC( 0 );
556 // create new DC sith DefaultBitmap
557 pC
->mhDC
= CreateCompatibleDC( hDC
);
559 if( pSalData
->mhDitherPal
)
561 pC
->mhDefPal
= SelectPalette( pC
->mhDC
, pSalData
->mhDitherPal
, TRUE
);
562 RealizePalette( pC
->mhDC
);
565 pC
->mhSelBmp
= CreateCompatibleBitmap( hDC
, CACHED_HDC_DEFEXT
, CACHED_HDC_DEFEXT
);
566 pC
->mhDefBmp
= (HBITMAP
) SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
572 SelectObject( pC
->mhDC
, pC
->mhActBmp
= hBmp
);
579 // =======================================================================
581 void ImplReleaseCachedDC( sal_uLong nID
)
583 SalData
* pSalData
= GetSalData();
584 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
587 SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
590 // =======================================================================
592 void ImplClearHDCCache( SalData
* pData
)
594 for( sal_uLong i
= 0; i
< CACHESIZE_HDC
; i
++ )
596 HDCCache
* pC
= &pData
->mpHDCCache
[ i
];
600 SelectObject( pC
->mhDC
, pC
->mhDefBmp
);
603 SelectPalette( pC
->mhDC
, pC
->mhDefPal
, TRUE
);
605 DeleteDC( pC
->mhDC
);
606 DeleteObject( pC
->mhSelBmp
);
611 // =======================================================================
613 // #100127# Fill point and flag memory from array of points which
614 // might also contain bezier control points for the PolyDraw() GDI method
615 // Make sure pWinPointAry and pWinFlagAry are big enough
616 void ImplPreparePolyDraw( bool bCloseFigures
,
618 const sal_uInt32
* pPoints
,
619 const SalPoint
* const* pPtAry
,
620 const BYTE
* const* pFlgAry
,
625 for( nCurrPoly
=0; nCurrPoly
<nPoly
; ++nCurrPoly
)
627 const POINT
* pCurrPoint
= reinterpret_cast<const POINT
*>( *pPtAry
++ );
628 const BYTE
* pCurrFlag
= *pFlgAry
++;
629 const sal_uInt32 nCurrPoints
= *pPoints
++;
630 const bool bHaveFlagArray( pCurrFlag
);
631 sal_uLong nCurrPoint
;
636 *pWinPointAry
++ = *pCurrPoint
++;
637 *pWinFlagAry
++ = PT_MOVETO
;
640 for( nCurrPoint
=1; nCurrPoint
<nCurrPoints
; )
642 // #102067# Check existence of flag array
643 if( bHaveFlagArray
&&
644 ( nCurrPoint
+ 2 ) < nCurrPoints
)
646 BYTE
P4( pCurrFlag
[ 2 ] );
648 if( ( POLY_CONTROL
== pCurrFlag
[ 0 ] ) &&
649 ( POLY_CONTROL
== pCurrFlag
[ 1 ] ) &&
650 ( POLY_NORMAL
== P4
|| POLY_SMOOTH
== P4
|| POLY_SYMMTR
== P4
) )
653 *pWinPointAry
++ = *pCurrPoint
++;
654 *pWinFlagAry
++ = PT_BEZIERTO
;
657 *pWinPointAry
++ = *pCurrPoint
++;
658 *pWinFlagAry
++ = PT_BEZIERTO
;
661 *pWinPointAry
++ = *pCurrPoint
++;
662 *pWinFlagAry
++ = PT_BEZIERTO
;
670 // regular line point
671 *pWinPointAry
++ = *pCurrPoint
++;
672 *pWinFlagAry
++ = PT_LINETO
;
679 pWinFlagAry
[-1] |= PT_CLOSEFIGURE
;
684 // =======================================================================
686 // #100127# draw an array of points which might also contain bezier control points
687 void ImplRenderPath( HDC hdc
, sal_uLong nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
692 // TODO: profile whether the following options are faster:
693 // a) look ahead and draw consecutive bezier or line segments by PolyBezierTo/PolyLineTo resp.
694 // b) convert our flag array to window's and use PolyDraw
696 MoveToEx( hdc
, pPtAry
->mnX
, pPtAry
->mnY
, NULL
);
699 for( i
=1; i
<nPoints
; ++i
, ++pPtAry
, ++pFlgAry
)
701 if( *pFlgAry
!= POLY_CONTROL
)
703 LineTo( hdc
, pPtAry
->mnX
, pPtAry
->mnY
);
705 else if( nPoints
- i
> 2 )
707 PolyBezierTo( hdc
, reinterpret_cast<const POINT
*>(pPtAry
), 3 );
708 i
+= 2; pPtAry
+= 2; pFlgAry
+= 2;
714 // =======================================================================
716 WinSalGraphics::WinSalGraphics()
718 for( int i
= 0; i
< MAX_FALLBACK
; ++i
)
721 mpWinFontData
[ i
] = NULL
;
722 mpWinFontEntry
[ i
] = NULL
;
723 mfFontScale
[ i
] = 1.0;
726 mfCurrentFontScale
= 1.0;
736 mpStdClipRgnData
= NULL
;
738 mpFontCharSets
= NULL
;
739 mpFontAttrCache
= NULL
;
740 mnFontCharSetCount
= 0;
741 mpFontKernPairs
= NULL
;
742 mnFontKernPairCount
= 0;
743 mbFontKernInit
= FALSE
;
745 mnPenWidth
= GSL_PEN_WIDTH
;
748 // -----------------------------------------------------------------------
750 WinSalGraphics::~WinSalGraphics()
752 // free obsolete GDI objects
763 DeleteBrush( mhBrush
);
768 DeleteRegion( mhRegion
);
773 if ( mpStdClipRgnData
)
774 delete [] mpStdClipRgnData
;
778 delete mpFontCharSets
;
780 delete mpFontKernPairs
;
783 // -----------------------------------------------------------------------
785 void WinSalGraphics::GetResolution( long& rDPIX
, long& rDPIY
)
787 rDPIX
= GetDeviceCaps( mhDC
, LOGPIXELSX
);
788 rDPIY
= GetDeviceCaps( mhDC
, LOGPIXELSY
);
790 // #111139# this fixes the symptom of div by zero on startup
791 // however, printing will fail most likely as communication with
792 // the printer seems not to work in this case
793 if( !rDPIX
|| !rDPIY
)
797 // -----------------------------------------------------------------------
799 sal_uInt16
WinSalGraphics::GetBitCount() const
801 return (sal_uInt16
)GetDeviceCaps( mhDC
, BITSPIXEL
);
804 // -----------------------------------------------------------------------
806 long WinSalGraphics::GetGraphicsWidth() const
808 if( mhWnd
&& IsWindow( mhWnd
) )
810 WinSalFrame
* pFrame
= GetWindowPtr( mhWnd
);
813 if( pFrame
->maGeometry
.nWidth
)
814 return pFrame
->maGeometry
.nWidth
;
817 // TODO: perhaps not needed, maGeometry should always be up-to-date
819 GetClientRect( mhWnd
, &aRect
);
828 // -----------------------------------------------------------------------
830 void WinSalGraphics::ResetClipRegion()
834 DeleteRegion( mhRegion
);
838 SelectClipRgn( mhDC
, 0 );
841 // -----------------------------------------------------------------------
843 bool WinSalGraphics::setClipRegion( const Region
& i_rClip
)
847 DeleteRegion( mhRegion
);
851 if( i_rClip
.HasPolyPolygon() )
853 // TODO: ConvertToB2DPolyPolygon actually is kind of const, just it does not advertise it in the header
854 basegfx::B2DPolyPolygon
aPolyPolygon( const_cast<Region
&>(i_rClip
).ConvertToB2DPolyPolygon() );
855 const sal_uInt32
nCount(aPolyPolygon
.count());
859 std::vector
< POINT
> aPolyPoints
;
860 aPolyPoints
.reserve( 1024 );
861 std::vector
< INT
> aPolyCounts( nCount
, 0 );
862 for(sal_uInt32
a(0); a
< nCount
; a
++)
864 basegfx::B2DPolygon
aPoly( aPolyPolygon
.getB2DPolygon(a
) );
865 aPoly
= basegfx::tools::adaptiveSubdivideByDistance( aPoly
, 1 );
866 const sal_uInt32 nPoints
= aPoly
.count();
867 aPolyCounts
[a
] = nPoints
;
868 for( sal_uInt32 b
= 0; b
< nPoints
; b
++ )
870 basegfx::B2DPoint
aPt( aPoly
.getB2DPoint( b
) );
872 aPOINT
.x
= (LONG
)aPt
.getX();
873 aPOINT
.y
= (LONG
)aPt
.getY();
874 aPolyPoints
.push_back( aPOINT
);
877 mhRegion
= CreatePolyPolygonRgn( &aPolyPoints
[0], &aPolyCounts
[0], nCount
, ALTERNATE
);
882 sal_uLong nRectCount
= i_rClip
.GetRectCount();
884 sal_uLong nRectBufSize
= sizeof(RECT
)*nRectCount
;
885 if ( nRectCount
< SAL_CLIPRECT_COUNT
)
887 if ( !mpStdClipRgnData
)
888 mpStdClipRgnData
= (RGNDATA
*)new BYTE
[sizeof(RGNDATA
)-1+(SAL_CLIPRECT_COUNT
*sizeof(RECT
))];
889 mpClipRgnData
= mpStdClipRgnData
;
892 mpClipRgnData
= (RGNDATA
*)new BYTE
[sizeof(RGNDATA
)-1+nRectBufSize
];
893 mpClipRgnData
->rdh
.dwSize
= sizeof( RGNDATAHEADER
);
894 mpClipRgnData
->rdh
.iType
= RDH_RECTANGLES
;
895 mpClipRgnData
->rdh
.nCount
= nRectCount
;
896 mpClipRgnData
->rdh
.nRgnSize
= nRectBufSize
;
897 RECT
* pBoundRect
= &(mpClipRgnData
->rdh
.rcBound
);
898 SetRectEmpty( pBoundRect
);
899 RECT
* pNextClipRect
= (RECT
*)(&(mpClipRgnData
->Buffer
));
900 bool bFirstClipRect
= true;
902 ImplRegionInfo aInfo
;
904 bool bRegionRect
= i_rClip
.ImplGetFirstRect(aInfo
, nX
, nY
, nW
, nH
);
909 long nRight
= nX
+ nW
;
910 long nBottom
= nY
+ nH
;
912 if ( bFirstClipRect
)
914 pBoundRect
->left
= nX
;
915 pBoundRect
->top
= nY
;
916 pBoundRect
->right
= nRight
;
917 pBoundRect
->bottom
= nBottom
;
918 bFirstClipRect
= false;
922 if ( nX
< pBoundRect
->left
)
923 pBoundRect
->left
= (int)nX
;
925 if ( nY
< pBoundRect
->top
)
926 pBoundRect
->top
= (int)nY
;
928 if ( nRight
> pBoundRect
->right
)
929 pBoundRect
->right
= (int)nRight
;
931 if ( nBottom
> pBoundRect
->bottom
)
932 pBoundRect
->bottom
= (int)nBottom
;
935 pNextClipRect
->left
= (int)nX
;
936 pNextClipRect
->top
= (int)nY
;
937 pNextClipRect
->right
= (int)nRight
;
938 pNextClipRect
->bottom
= (int)nBottom
;
943 mpClipRgnData
->rdh
.nCount
--;
944 mpClipRgnData
->rdh
.nRgnSize
-= sizeof( RECT
);
946 bRegionRect
= i_rClip
.ImplGetNextRect( aInfo
, nX
, nY
, nW
, nH
);
948 // create clip region from ClipRgnData
949 if ( mpClipRgnData
->rdh
.nCount
== 1 )
951 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
952 mhRegion
= CreateRectRgn( pRect
->left
, pRect
->top
,
953 pRect
->right
, pRect
->bottom
);
955 else if( mpClipRgnData
->rdh
.nCount
> 1 )
957 sal_uLong nSize
= mpClipRgnData
->rdh
.nRgnSize
+sizeof(RGNDATAHEADER
);
958 mhRegion
= ExtCreateRegion( NULL
, nSize
, mpClipRgnData
);
960 // if ExtCreateRegion(...) is not supported
963 RGNDATAHEADER
* pHeader
= (RGNDATAHEADER
*) mpClipRgnData
;
965 if( pHeader
->nCount
)
967 RECT
* pRect
= (RECT
*) mpClipRgnData
->Buffer
;
968 mhRegion
= CreateRectRgn( pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
971 for( sal_uLong n
= 1; n
< pHeader
->nCount
; n
++, pRect
++ )
973 HRGN hRgn
= CreateRectRgn( pRect
->left
, pRect
->top
, pRect
->right
, pRect
->bottom
);
974 CombineRgn( mhRegion
, mhRegion
, hRgn
, RGN_OR
);
975 DeleteRegion( hRgn
);
980 if ( mpClipRgnData
!= mpStdClipRgnData
)
981 delete [] mpClipRgnData
;
986 SelectClipRgn( mhDC
, mhRegion
);
987 return mhRegion
!= 0;
990 // -----------------------------------------------------------------------
992 void WinSalGraphics::SetLineColor()
994 // create and select new pen
995 HPEN hNewPen
= GetStockPen( NULL_PEN
);
996 HPEN hOldPen
= SelectPen( mhDC
, hNewPen
);
998 // destroy or save old pen
1013 // -----------------------------------------------------------------------
1015 void WinSalGraphics::SetLineColor( SalColor nSalColor
)
1017 maLineColor
= nSalColor
;
1018 COLORREF nPenColor
= PALETTERGB( SALCOLOR_RED( nSalColor
),
1019 SALCOLOR_GREEN( nSalColor
),
1020 SALCOLOR_BLUE( nSalColor
) );
1022 sal_Bool bStockPen
= FALSE
;
1024 // search for stock pen (only screen, because printer have problems,
1025 // when we use stock objects)
1028 SalData
* pSalData
= GetSalData();
1029 for ( sal_uInt16 i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
1031 if ( nPenColor
== pSalData
->maStockPenColorAry
[i
] )
1033 hNewPen
= pSalData
->mhStockPenAry
[i
];
1045 if ( GetSalData()->mhDitherPal
&& ImplIsSysColorEntry( nSalColor
) )
1046 nPenColor
= PALRGB_TO_RGB( nPenColor
);
1049 hNewPen
= CreatePen( PS_SOLID
, mnPenWidth
, nPenColor
);
1054 HPEN hOldPen
= SelectPen( mhDC
, hNewPen
);
1056 // destroy or save old pen
1066 mnPenColor
= nPenColor
;
1069 mbStockPen
= bStockPen
;
1072 // -----------------------------------------------------------------------
1074 void WinSalGraphics::SetFillColor()
1076 // create and select new brush
1077 HBRUSH hNewBrush
= GetStockBrush( NULL_BRUSH
);
1078 HBRUSH hOldBrush
= SelectBrush( mhDC
, hNewBrush
);
1080 // destroy or save old brush
1083 if ( !mbStockBrush
)
1084 DeleteBrush( mhBrush
);
1087 mhDefBrush
= hOldBrush
;
1090 mhBrush
= hNewBrush
;
1092 mbStockBrush
= TRUE
;
1095 // -----------------------------------------------------------------------
1097 void WinSalGraphics::SetFillColor( SalColor nSalColor
)
1099 maFillColor
= nSalColor
;
1100 SalData
* pSalData
= GetSalData();
1101 BYTE nRed
= SALCOLOR_RED( nSalColor
);
1102 BYTE nGreen
= SALCOLOR_GREEN( nSalColor
);
1103 BYTE nBlue
= SALCOLOR_BLUE( nSalColor
);
1104 COLORREF nBrushColor
= PALETTERGB( nRed
, nGreen
, nBlue
);
1105 HBRUSH hNewBrush
= 0;
1106 sal_Bool bStockBrush
= FALSE
;
1108 // search for stock brush (only screen, because printer have problems,
1109 // when we use stock objects)
1112 for ( sal_uInt16 i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
1114 if ( nBrushColor
== pSalData
->maStockBrushColorAry
[ i
] )
1116 hNewBrush
= pSalData
->mhStockBrushAry
[i
];
1126 if ( mbPrinter
|| !pSalData
->mhDitherDIB
)
1127 hNewBrush
= CreateSolidBrush( nBrushColor
);
1130 if ( 24 == ((BITMAPINFOHEADER
*)pSalData
->mpDitherDIB
)->biBitCount
)
1132 BYTE
* pTmp
= pSalData
->mpDitherDIBData
;
1133 long* pDitherDiff
= pSalData
->mpDitherDiff
;
1134 BYTE
* pDitherLow
= pSalData
->mpDitherLow
;
1135 BYTE
* pDitherHigh
= pSalData
->mpDitherHigh
;
1137 for( long nY
= 0L; nY
< 8L; nY
++ )
1139 for( long nX
= 0L; nX
< 8L; nX
++ )
1141 const long nThres
= aOrdDither16Bit
[ nY
][ nX
];
1142 *pTmp
++ = DMAP( nBlue
, nThres
);
1143 *pTmp
++ = DMAP( nGreen
, nThres
);
1144 *pTmp
++ = DMAP( nRed
, nThres
);
1148 hNewBrush
= CreateDIBPatternBrush( pSalData
->mhDitherDIB
, DIB_RGB_COLORS
);
1150 else if ( ImplIsSysColorEntry( nSalColor
) )
1152 nBrushColor
= PALRGB_TO_RGB( nBrushColor
);
1153 hNewBrush
= CreateSolidBrush( nBrushColor
);
1155 else if ( ImplIsPaletteEntry( nRed
, nGreen
, nBlue
) )
1156 hNewBrush
= CreateSolidBrush( nBrushColor
);
1159 BYTE
* pTmp
= pSalData
->mpDitherDIBData
;
1160 long* pDitherDiff
= pSalData
->mpDitherDiff
;
1161 BYTE
* pDitherLow
= pSalData
->mpDitherLow
;
1162 BYTE
* pDitherHigh
= pSalData
->mpDitherHigh
;
1164 for ( long nY
= 0L; nY
< 8L; nY
++ )
1166 for ( long nX
= 0L; nX
< 8L; nX
++ )
1168 const long nThres
= aOrdDither8Bit
[ nY
][ nX
];
1169 *pTmp
= DMAP( nRed
, nThres
) + DMAP( nGreen
, nThres
) * 6 + DMAP( nBlue
, nThres
) * 36;
1174 hNewBrush
= CreateDIBPatternBrush( pSalData
->mhDitherDIB
, DIB_PAL_COLORS
);
1178 bStockBrush
= FALSE
;
1182 HBRUSH hOldBrush
= SelectBrush( mhDC
, hNewBrush
);
1184 // destroy or save old brush
1187 if ( !mbStockBrush
)
1188 DeleteBrush( mhBrush
);
1191 mhDefBrush
= hOldBrush
;
1194 mnBrushColor
= nBrushColor
;
1195 mhBrush
= hNewBrush
;
1197 mbStockBrush
= bStockBrush
;
1200 // -----------------------------------------------------------------------
1202 void WinSalGraphics::SetXORMode( bool bSet
, bool )
1205 ::SetROP2( mhDC
, bSet
? R2_XORPEN
: R2_COPYPEN
);
1208 // -----------------------------------------------------------------------
1210 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
1212 SetLineColor( ImplGetROPSalColor( nROPColor
) );
1215 // -----------------------------------------------------------------------
1217 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
1219 SetFillColor( ImplGetROPSalColor( nROPColor
) );
1222 // -----------------------------------------------------------------------
1224 void WinSalGraphics::drawPixel( long nX
, long nY
)
1228 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1229 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1230 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)1, (int)1, PATINVERT
);
1231 SelectBrush( mhDC
, hOldBrush
);
1232 DeleteBrush( hBrush
);
1235 SetPixel( mhDC
, (int)nX
, (int)nY
, mnPenColor
);
1238 // -----------------------------------------------------------------------
1240 void WinSalGraphics::drawPixel( long nX
, long nY
, SalColor nSalColor
)
1242 COLORREF nCol
= PALETTERGB( SALCOLOR_RED( nSalColor
),
1243 SALCOLOR_GREEN( nSalColor
),
1244 SALCOLOR_BLUE( nSalColor
) );
1247 GetSalData()->mhDitherPal
&&
1248 ImplIsSysColorEntry( nSalColor
) )
1249 nCol
= PALRGB_TO_RGB( nCol
);
1253 HBRUSH hBrush
= CreateSolidBrush( nCol
);
1254 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1255 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)1, (int)1, PATINVERT
);
1256 SelectBrush( mhDC
, hOldBrush
);
1257 DeleteBrush( hBrush
);
1260 ::SetPixel( mhDC
, (int)nX
, (int)nY
, nCol
);
1263 // -----------------------------------------------------------------------
1265 void WinSalGraphics::drawLine( long nX1
, long nY1
, long nX2
, long nY2
)
1267 MoveToEx( mhDC
, (int)nX1
, (int)nY1
, NULL
);
1269 // we must paint the endpoint
1270 int bPaintEnd
= TRUE
;
1288 LineTo( mhDC
, (int)nX2
, (int)nY2
);
1290 if ( bPaintEnd
&& !mbPrinter
)
1294 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1295 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1296 PatBlt( mhDC
, (int)nX2
, (int)nY2
, (int)1, (int)1, PATINVERT
);
1297 SelectBrush( mhDC
, hOldBrush
);
1298 DeleteBrush( hBrush
);
1301 SetPixel( mhDC
, (int)nX2
, (int)nY2
, mnPenColor
);
1305 // -----------------------------------------------------------------------
1307 void WinSalGraphics::drawRect( long nX
, long nY
, long nWidth
, long nHeight
)
1313 PatBlt( mhDC
, (int)nX
, (int)nY
, (int)nWidth
, (int)nHeight
,
1314 mbXORMode
? PATINVERT
: PATCOPY
);
1321 aWinRect
.right
= nX
+nWidth
;
1322 aWinRect
.bottom
= nY
+nHeight
;
1323 ::FillRect( mhDC
, &aWinRect
, mhBrush
);
1327 WIN_Rectangle( mhDC
, (int)nX
, (int)nY
, (int)(nX
+nWidth
), (int)(nY
+nHeight
) );
1330 // -----------------------------------------------------------------------
1332 void WinSalGraphics::drawPolyLine( sal_uLong nPoints
, const SalPoint
* pPtAry
)
1334 // for NT, we can handover the array directly
1335 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1336 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" );
1338 POINT
* pWinPtAry
= (POINT
*)pPtAry
;
1340 // we assume there are at least 2 points (Polyline requres at least 2 point, see MSDN)
1341 // we must paint the endpoint for last line
1342 BOOL bPaintEnd
= TRUE
;
1343 if ( pWinPtAry
[nPoints
-2].x
== pWinPtAry
[nPoints
-1].x
)
1346 if ( pWinPtAry
[nPoints
-2].y
<= pWinPtAry
[nPoints
-1].y
)
1347 pWinPtAry
[nPoints
-1].y
++;
1349 pWinPtAry
[nPoints
-1].y
--;
1351 if ( pWinPtAry
[nPoints
-2].y
== pWinPtAry
[nPoints
-1].y
)
1354 if ( pWinPtAry
[nPoints
-2].x
<= pWinPtAry
[nPoints
-1].x
)
1355 pWinPtAry
[nPoints
-1].x
++;
1357 pWinPtAry
[nPoints
-1].x
--;
1360 // for Windows 95 and its maximum number of points
1361 if ( !Polyline( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
1362 Polyline( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
1364 if ( bPaintEnd
&& !mbPrinter
)
1368 HBRUSH hBrush
= CreateSolidBrush( mnPenColor
);
1369 HBRUSH hOldBrush
= SelectBrush( mhDC
, hBrush
);
1370 PatBlt( mhDC
, (int)(pWinPtAry
[nPoints
-1].x
), (int)(pWinPtAry
[nPoints
-1].y
), (int)1, (int)1, PATINVERT
);
1371 SelectBrush( mhDC
, hOldBrush
);
1372 DeleteBrush( hBrush
);
1375 SetPixel( mhDC
, (int)(pWinPtAry
[nPoints
-1].x
), (int)(pWinPtAry
[nPoints
-1].y
), mnPenColor
);
1379 // -----------------------------------------------------------------------
1381 void WinSalGraphics::drawPolygon( sal_uLong nPoints
, const SalPoint
* pPtAry
)
1383 // for NT, we can handover the array directly
1384 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1385 "WinSalGraphics::DrawPolygon(): POINT != SalPoint" );
1387 POINT
* pWinPtAry
= (POINT
*)pPtAry
;
1388 // for Windows 95 and its maximum number of points
1389 if ( !WIN_Polygon( mhDC
, pWinPtAry
, (int)nPoints
) && (nPoints
> MAX_64KSALPOINTS
) )
1390 WIN_Polygon( mhDC
, pWinPtAry
, MAX_64KSALPOINTS
);
1393 // -----------------------------------------------------------------------
1395 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
1396 PCONSTSALPOINT
* pPtAry
)
1398 UINT aWinPointAry
[SAL_POLYPOLYCOUNT_STACKBUF
];
1400 UINT nPolyPolyPoints
= 0;
1404 if ( nPoly
<= SAL_POLYPOLYCOUNT_STACKBUF
)
1405 pWinPointAry
= aWinPointAry
;
1407 pWinPointAry
= new UINT
[nPoly
];
1409 for ( i
= 0; i
< (UINT
)nPoly
; i
++ )
1411 nPoints
= (UINT
)pPoints
[i
]+1;
1412 pWinPointAry
[i
] = nPoints
;
1413 nPolyPolyPoints
+= nPoints
;
1416 POINT aWinPointAryAry
[SAL_POLYPOLYPOINTS_STACKBUF
];
1417 POINT
* pWinPointAryAry
;
1418 if ( nPolyPolyPoints
<= SAL_POLYPOLYPOINTS_STACKBUF
)
1419 pWinPointAryAry
= aWinPointAryAry
;
1421 pWinPointAryAry
= new POINT
[nPolyPolyPoints
];
1422 // for NT, we can handover the array directly
1423 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1424 "WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" );
1425 const SalPoint
* pPolyAry
;
1427 for ( i
= 0; i
< (UINT
)nPoly
; i
++ )
1429 nPoints
= pWinPointAry
[i
];
1430 pPolyAry
= pPtAry
[i
];
1431 memcpy( pWinPointAryAry
+n
, pPolyAry
, (nPoints
-1)*sizeof(POINT
) );
1432 pWinPointAryAry
[n
+nPoints
-1] = pWinPointAryAry
[n
];
1436 if ( !WIN_PolyPolygon( mhDC
, pWinPointAryAry
, (int*)pWinPointAry
, (UINT
)nPoly
) &&
1437 (nPolyPolyPoints
> MAX_64KSALPOINTS
) )
1439 nPolyPolyPoints
= 0;
1443 nPolyPolyPoints
+= pWinPointAry
[(UINT
)nPoly
];
1446 while ( nPolyPolyPoints
< MAX_64KSALPOINTS
);
1448 if ( pWinPointAry
[(UINT
)nPoly
] > MAX_64KSALPOINTS
)
1449 pWinPointAry
[(UINT
)nPoly
] = MAX_64KSALPOINTS
;
1451 WIN_Polygon( mhDC
, pWinPointAryAry
, *pWinPointAry
);
1453 WIN_PolyPolygon( mhDC
, pWinPointAryAry
, (int*)pWinPointAry
, nPoly
);
1456 if ( pWinPointAry
!= aWinPointAry
)
1457 delete [] pWinPointAry
;
1458 if ( pWinPointAryAry
!= aWinPointAryAry
)
1459 delete [] pWinPointAryAry
;
1462 // -----------------------------------------------------------------------
1464 #define SAL_POLY_STACKBUF 32
1466 // -----------------------------------------------------------------------
1468 sal_Bool
WinSalGraphics::drawPolyLineBezier( sal_uLong nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
1470 #ifdef USE_GDI_BEZIERS
1471 // for NT, we can handover the array directly
1472 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1473 "WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" );
1475 ImplRenderPath( mhDC
, nPoints
, pPtAry
, pFlgAry
);
1483 // -----------------------------------------------------------------------
1485 sal_Bool
WinSalGraphics::drawPolygonBezier( sal_uLong nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
1487 #ifdef USE_GDI_BEZIERS
1488 // for NT, we can handover the array directly
1489 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1490 "WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" );
1492 POINT aStackAry1
[SAL_POLY_STACKBUF
];
1493 BYTE aStackAry2
[SAL_POLY_STACKBUF
];
1494 POINT
* pWinPointAry
;
1496 if( nPoints
> SAL_POLY_STACKBUF
)
1498 pWinPointAry
= new POINT
[ nPoints
];
1499 pWinFlagAry
= new BYTE
[ nPoints
];
1503 pWinPointAry
= aStackAry1
;
1504 pWinFlagAry
= aStackAry2
;
1507 sal_uInt32
nPoints_i32(nPoints
);
1508 ImplPreparePolyDraw(true, 1, &nPoints_i32
, &pPtAry
, &pFlgAry
, pWinPointAry
, pWinFlagAry
);
1510 sal_Bool
bRet( sal_False
);
1512 if( BeginPath( mhDC
) )
1514 PolyDraw(mhDC
, pWinPointAry
, pWinFlagAry
, nPoints
);
1516 if( EndPath( mhDC
) )
1518 if( StrokeAndFillPath( mhDC
) )
1523 if( pWinPointAry
!= aStackAry1
)
1525 delete [] pWinPointAry
;
1526 delete [] pWinFlagAry
;
1535 // -----------------------------------------------------------------------
1537 sal_Bool
WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
1538 const SalPoint
* const* pPtAry
, const BYTE
* const* pFlgAry
)
1540 #ifdef USE_GDI_BEZIERS
1541 // for NT, we can handover the array directly
1542 DBG_ASSERT( sizeof( POINT
) == sizeof( SalPoint
),
1543 "WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" );
1545 sal_uLong nCurrPoly
, nTotalPoints
;
1546 const sal_uInt32
* pCurrPoints
= pPoints
;
1547 for( nCurrPoly
=0, nTotalPoints
=0; nCurrPoly
<nPoly
; ++nCurrPoly
)
1548 nTotalPoints
+= *pCurrPoints
++;
1550 POINT aStackAry1
[SAL_POLY_STACKBUF
];
1551 BYTE aStackAry2
[SAL_POLY_STACKBUF
];
1552 POINT
* pWinPointAry
;
1554 if( nTotalPoints
> SAL_POLY_STACKBUF
)
1556 pWinPointAry
= new POINT
[ nTotalPoints
];
1557 pWinFlagAry
= new BYTE
[ nTotalPoints
];
1561 pWinPointAry
= aStackAry1
;
1562 pWinFlagAry
= aStackAry2
;
1565 ImplPreparePolyDraw(true, nPoly
, pPoints
, pPtAry
, pFlgAry
, pWinPointAry
, pWinFlagAry
);
1567 sal_Bool
bRet( sal_False
);
1569 if( BeginPath( mhDC
) )
1571 PolyDraw(mhDC
, pWinPointAry
, pWinFlagAry
, nTotalPoints
);
1573 if( EndPath( mhDC
) )
1575 if( StrokeAndFillPath( mhDC
) )
1580 if( pWinPointAry
!= aStackAry1
)
1582 delete [] pWinPointAry
;
1583 delete [] pWinFlagAry
;
1592 // -----------------------------------------------------------------------
1594 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
1596 static BYTE
* ImplSearchEntry( BYTE
* pSource
, BYTE
* pDest
, sal_uLong nComp
, sal_uLong nSize
)
1598 while ( nComp
-- >= nSize
)
1601 for ( i
= 0; i
< nSize
; i
++ )
1603 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
1613 static sal_Bool
ImplGetBoundingBox( double* nNumb
, BYTE
* pSource
, sal_uLong nSize
)
1615 sal_Bool bRetValue
= FALSE
;
1616 BYTE
* pDest
= ImplSearchEntry( pSource
, (BYTE
*)"%%BoundingBox:", nSize
, 14 );
1619 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
1622 int nSizeLeft
= nSize
- ( pDest
- pSource
);
1623 if ( nSizeLeft
> 100 )
1624 nSizeLeft
= 100; // only 100 bytes following the bounding box will be checked
1627 for ( i
= 0; ( i
< 4 ) && nSizeLeft
; i
++ )
1630 sal_Bool bDivision
= FALSE
;
1631 sal_Bool bNegative
= FALSE
;
1632 sal_Bool bValid
= TRUE
;
1634 while ( ( --nSizeLeft
) && ( ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) ) pDest
++;
1635 BYTE nByte
= *pDest
;
1636 while ( nSizeLeft
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
1650 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
1651 nSizeLeft
= 1; // error parsing the bounding box values
1657 nNumb
[i
] += nByte
- '0';
1665 nNumb
[i
] = -nNumb
[i
];
1666 if ( bDivision
&& ( nDivision
!= 1 ) )
1667 nNumb
[i
] /= nDivision
;
1675 sal_Bool
WinSalGraphics::drawEPS( long nX
, long nY
, long nWidth
, long nHeight
, void* pPtr
, sal_uLong nSize
)
1677 sal_Bool bRetValue
= FALSE
;
1681 int nEscape
= POSTSCRIPT_PASSTHROUGH
;
1683 if ( Escape( mhDC
, QUERYESCSUPPORT
, sizeof( int ), ( LPSTR
)&nEscape
, 0 ) )
1685 double nBoundingBox
[4];
1687 if ( ImplGetBoundingBox( nBoundingBox
, (BYTE
*)pPtr
, nSize
) )
1689 OStringBuffer
aBuf( POSTSCRIPT_BUFSIZE
);
1691 // reserve place for a sal_uInt16
1692 aBuf
.append( "aa" );
1694 // #107797# Write out EPS encapsulation header
1695 // ----------------------------------------------------------------------------------
1697 // directly taken from the PLRM 3.0, p. 726. Note:
1698 // this will definitely cause problems when
1699 // recursively creating and embedding PostScript files
1700 // in OOo, since we use statically-named variables
1701 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
1702 // op_count_salWin). Currently, I have no idea on how to
1703 // work around that, except from scanning and
1704 // interpreting the EPS for unused identifiers.
1706 // append the real text
1707 aBuf
.append( "\n\n/b4_Inc_state_salWin save def\n"
1708 "/dict_count_salWin countdictstack def\n"
1709 "/op_count_salWin count 1 sub def\n"
1711 "/showpage {} def\n"
1712 "0 setgray 0 setlinecap\n"
1713 "1 setlinewidth 0 setlinejoin\n"
1714 "10 setmiterlimit [] 0 setdash newpath\n"
1715 "/languagelevel where\n"
1717 " pop languagelevel\n"
1720 " false setstrokeadjust false setoverprint\n"
1725 // #i10737# Apply clipping manually
1726 // ----------------------------------------------------------------------------------
1728 // Windows seems to ignore any clipping at the HDC,
1729 // when followed by a POSTSCRIPT_PASSTHROUGH
1731 // Check whether we've got a clipping, consisting of
1732 // exactly one rect (other cases should be, but aren't
1733 // handled currently)
1735 // TODO: Handle more than one rectangle here (take
1736 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
1738 if ( mhRegion
!= 0 &&
1739 mpStdClipRgnData
!= NULL
&&
1740 mpClipRgnData
== mpStdClipRgnData
&&
1741 mpClipRgnData
->rdh
.nCount
== 1 )
1743 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
1745 aBuf
.append( "\nnewpath\n" );
1746 aBuf
.append( pRect
->left
);
1748 aBuf
.append( pRect
->top
);
1749 aBuf
.append( " moveto\n" );
1750 aBuf
.append( pRect
->right
);
1752 aBuf
.append( pRect
->top
);
1753 aBuf
.append( " lineto\n" );
1754 aBuf
.append( pRect
->right
);
1756 aBuf
.append( pRect
->bottom
);
1757 aBuf
.append( " lineto\n" );
1758 aBuf
.append( pRect
->left
);
1760 aBuf
.append( pRect
->bottom
);
1761 aBuf
.append( " lineto\n"
1767 // #107797# Write out buffer
1768 // ----------------------------------------------------------------------------------
1769 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1770 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1773 // #107797# Write out EPS transformation code
1774 // ----------------------------------------------------------------------------------
1775 double dM11
= nWidth
/ ( nBoundingBox
[2] - nBoundingBox
[0] );
1776 double dM22
= nHeight
/ (nBoundingBox
[1] - nBoundingBox
[3] );
1777 // reserve a sal_uInt16 again
1778 aBuf
.setLength( 2 );
1779 aBuf
.append( "\n\n[" );
1780 aBuf
.append( dM11
);
1781 aBuf
.append( " 0 0 " );
1782 aBuf
.append( dM22
);
1784 aBuf
.append( nX
- ( dM11
* nBoundingBox
[0] ) );
1786 aBuf
.append( nY
- ( dM22
* nBoundingBox
[3] ) );
1787 aBuf
.append( "] concat\n"
1788 "%%BeginDocument:\n" );
1789 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1790 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1793 // #107797# Write out actual EPS content
1794 // ----------------------------------------------------------------------------------
1795 sal_uLong nToDo
= nSize
;
1800 if ( nToDo
> POSTSCRIPT_BUFSIZE
- 2 )
1801 nDoNow
= POSTSCRIPT_BUFSIZE
- 2;
1802 // the following is based on the string buffer allocation
1803 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1804 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)nDoNow
;
1805 memcpy( (void*)(aBuf
.getStr() + 2), (BYTE
*)pPtr
+ nSize
- nToDo
, nDoNow
);
1806 sal_uLong nResult
= Escape ( mhDC
, nEscape
, nDoNow
+ 2, (LPTSTR
)aBuf
.getStr(), 0 );
1813 // #107797# Write out EPS encapsulation footer
1814 // ----------------------------------------------------------------------------------
1815 // reserve a sal_uInt16 again
1816 aBuf
.setLength( 2 );
1817 aBuf
.append( "%%EndDocument\n"
1818 "count op_count_salWin sub {pop} repeat\n"
1819 "countdictstack dict_count_salWin sub {end} repeat\n"
1820 "b4_Inc_state_salWin restore\n\n" );
1821 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1822 Escape ( mhDC
, nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1831 // -----------------------------------------------------------------------
1833 SystemGraphicsData
WinSalGraphics::GetGraphicsData() const
1835 SystemGraphicsData aRes
;
1836 aRes
.nSize
= sizeof(aRes
);
1841 // -----------------------------------------------------------------------
1843 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */