merge the formfield patch from ooo-build
[ooovba.git] / vcl / win / source / gdi / salgdi.cxx
blobc4ea6d7832b0a0850e65a67b8eb3b76925b84ec1
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: salgdi.cxx,v $
10 * $Revision: 1.36 $
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"
34 #include <stdio.h>
35 #include <string.h>
36 #include <tools/svwin.h>
37 #include <wincomp.hxx>
38 #include <saldata.hxx>
39 #include <salgdi.h>
40 #include <tools/debug.hxx>
41 #include <salframe.h>
42 #include <tools/poly.hxx>
43 #ifndef _RTL_STRINGBUF_HXX
44 #include <rtl/strbuf.hxx>
45 #endif
47 using namespace rtl;
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 // =======================================================================
65 struct SysColorEntry
67 DWORD nRGB;
68 SysColorEntry* pNext;
71 // =======================================================================
73 static SysColorEntry* pFirstSysColor = NULL;
74 static SysColorEntry* pActSysColor = NULL;
76 // -----------------------------------------------------------------------------
78 // Blue7
79 static PALETTEENTRY aImplExtraColor1 =
81 0, 184, 255, 0
84 // -----------------------------------------------------------------------------
86 static PALETTEENTRY aImplSalSysPalEntryAry[ DITHER_MAX_SYSCOLOR ] =
88 { 0, 0, 0, 0 },
89 { 0, 0, 0x80, 0 },
90 { 0, 0x80, 0, 0 },
91 { 0, 0x80, 0x80, 0 },
92 { 0x80, 0, 0, 0 },
93 { 0x80, 0, 0x80, 0 },
94 { 0x80, 0x80, 0, 0 },
95 { 0x80, 0x80, 0x80, 0 },
96 { 0xC0, 0xC0, 0xC0, 0 },
97 { 0, 0, 0xFF, 0 },
98 { 0, 0xFF, 0, 0 },
99 { 0, 0xFF, 0xFF, 0 },
100 { 0xFF, 0, 0, 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 )
203 bDither16 = FALSE;
205 ::SelectObject( hMemDC, hBrushOld ), ::DeleteObject( hMemBrush );
206 ::SelectObject( hMemDC, hBmpOld ), ::DeleteObject( hMemBmp );
207 ::DeleteDC( hMemDC );
209 if( bDither16 )
211 // create DIBPattern for 16Bit dithering
212 long n;
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 );
225 pBIH->biWidth = 8;
226 pBIH->biHeight = 8;
227 pBIH->biPlanes = 1;
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;
243 BYTE nR, nG, nB;
244 PALETTEENTRY* pPalEntry;
245 LOGPALETTE* pLogPal;
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;
255 // Standard colors
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;
270 pPalEntry++;
275 // insert special 'Blue' as standard drawing color
276 *pPalEntry++ = aImplExtraColor1;
278 // create palette
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;
286 long n;
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 );
300 pBIH->biWidth = 8;
301 pBIH->biHeight = 8;
302 pBIH->biPlanes = 1;
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();
322 ReleaseDC( 0, hDC );
325 // -----------------------------------------------------------------------
327 void ImplFreeSalGDI()
329 SalData* pSalData = GetSalData();
331 // destroy stock objects
332 int i;
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;
375 while( pEntry )
377 SysColorEntry* pTmp = pEntry->pNext;
378 delete pEntry;
379 pEntry = pTmp;
381 pFirstSysColor = NULL;
383 // delete icon cache
384 SalIcon* pIcon = pSalData->mpFirstIcon;
385 pSalData->mpFirstIcon = NULL;
386 while( pIcon )
388 SalIcon* pTmp = pIcon->pNext;
389 DestroyIcon( pIcon->hIcon );
390 DestroyIcon( pIcon->hSmallIcon );
391 delete pIcon;
392 pIcon = pTmp;
395 // delete temporary font list
396 ImplReleaseTempFonts( *pSalData );
399 // -----------------------------------------------------------------------
401 static int ImplIsPaletteEntry( BYTE nRed, BYTE nGreen, BYTE nBlue )
403 // dither color?
404 if ( !(nRed % DITHER_PAL_DELTA) && !(nGreen % DITHER_PAL_DELTA) && !(nBlue % DITHER_PAL_DELTA) )
405 return TRUE;
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 )
413 return TRUE;
416 // extra color?
417 if ( aImplExtraColor1.peRed == nRed &&
418 aImplExtraColor1.peGreen == nGreen &&
419 aImplExtraColor1.peBlue == nBlue )
421 return TRUE;
424 return FALSE;
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 ) );
436 while ( pEntry )
438 if ( pEntry->nRGB == nTestRGB )
439 return TRUE;
440 pEntry = pEntry->pNext;
443 return FALSE;
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;
460 else
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;
475 while( pEntry )
477 SysColorEntry* pTmp = pEntry->pNext;
478 delete pEntry;
479 pEntry = pTmp;
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 )
515 SalColor nSalColor;
516 if ( nROPColor == SAL_ROP_0 )
517 nSalColor = MAKE_SALCOLOR( 0, 0, 0 );
518 else
519 nSalColor = MAKE_SALCOLOR( 255, 255, 255 );
520 return nSalColor;
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 );
531 if ( nDPIX <= 300 )
532 pData->mnPenWidth = 0;
533 else
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 ];
562 if( !pC->mhDC )
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 );
578 ReleaseDC( 0, hDC );
581 if ( hBmp )
582 SelectObject( pC->mhDC, pC->mhActBmp = hBmp );
583 else
584 pC->mhActBmp = 0;
586 return pC->mhDC;
589 // =======================================================================
591 void ImplReleaseCachedDC( ULONG nID )
593 SalData* pSalData = GetSalData();
594 HDCCache* pC = &pSalData->mpHDCCache[ nID ];
596 if ( pC->mhActBmp )
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 ];
608 if( pC->mhDC )
610 SelectObject( pC->mhDC, pC->mhDefBmp );
612 if( pC->mhDefPal )
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,
627 ULONG nPoly,
628 const ULONG* pPoints,
629 const SalPoint* const* pPtAry,
630 const BYTE* const* pFlgAry,
631 POINT* pWinPointAry,
632 BYTE* pWinFlagAry )
634 ULONG nCurrPoly;
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 );
641 ULONG nCurrPoint;
643 if( nCurrPoints )
645 // start figure
646 *pWinPointAry++ = *pCurrPoint++;
647 *pWinFlagAry++ = PT_MOVETO;
648 ++pCurrFlag;
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 ) )
662 // control point one
663 *pWinPointAry++ = *pCurrPoint++;
664 *pWinFlagAry++ = PT_BEZIERTO;
666 // control point two
667 *pWinPointAry++ = *pCurrPoint++;
668 *pWinFlagAry++ = PT_BEZIERTO;
670 // end point
671 *pWinPointAry++ = *pCurrPoint++;
672 *pWinFlagAry++ = PT_BEZIERTO;
674 nCurrPoint += 3;
675 pCurrFlag += 3;
676 continue;
680 // regular line point
681 *pWinPointAry++ = *pCurrPoint++;
682 *pWinFlagAry++ = PT_LINETO;
683 ++pCurrFlag;
684 ++nCurrPoint;
687 // end figure?
688 if( bCloseFigures )
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 )
699 if( nPoints )
701 USHORT i;
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 );
707 ++pPtAry; ++pFlgAry;
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 )
730 mhFonts[ i ] = 0;
731 mpWinFontData[ i ] = NULL;
732 mpWinFontEntry[ i ] = NULL;
735 mfFontScale = 1.0;
737 mhDC = 0;
738 mhPen = 0;
739 mhBrush = 0;
740 mhRegion = 0;
741 mhDefPen = 0;
742 mhDefBrush = 0;
743 mhDefFont = 0;
744 mhDefPal = 0;
745 mpStdClipRgnData = NULL;
746 mpLogFont = NULL;
747 mpFontCharSets = NULL;
748 mpFontAttrCache = NULL;
749 mnFontCharSetCount = 0;
750 mpFontKernPairs = NULL;
751 mnFontKernPairCount = 0;
752 mbFontKernInit = FALSE;
753 mbXORMode = FALSE;
754 mnPenWidth = GSL_PEN_WIDTH;
757 // -----------------------------------------------------------------------
759 WinSalGraphics::~WinSalGraphics()
761 // free obsolete GDI objekts
762 ReleaseFonts();
764 if ( mhPen )
766 if ( !mbStockPen )
767 DeletePen( mhPen );
769 if ( mhBrush )
771 if ( !mbStockBrush )
772 DeleteBrush( mhBrush );
775 if ( mhRegion )
777 DeleteRegion( mhRegion );
778 mhRegion = 0;
781 // Cache-Daten zerstoeren
782 if ( mpStdClipRgnData )
783 delete [] mpStdClipRgnData;
785 if ( mpLogFont )
786 delete mpLogFont;
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 )
806 rDPIX = rDPIY = 600;
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 );
823 if( pFrame )
825 if( pFrame->maGeometry.nWidth )
826 return pFrame->maGeometry.nWidth;
827 else
829 // TODO: perhaps not needed, maGeometry should always be up-to-date
830 RECT aRect;
831 GetClientRect( mhWnd, &aRect );
832 return aRect.right;
837 return 0;
840 // -----------------------------------------------------------------------
842 void WinSalGraphics::ResetClipRegion()
844 if ( mhRegion )
846 DeleteRegion( mhRegion );
847 mhRegion = 0;
850 SelectClipRgn( mhDC, 0 );
853 // -----------------------------------------------------------------------
855 void WinSalGraphics::BeginSetClipRegion( ULONG nRectCount )
857 if ( mhRegion )
859 DeleteRegion( mhRegion );
860 mhRegion = 0;
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;
870 else
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;
901 else
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;
920 mpNextClipRect++;
922 else
924 mpClipRgnData->rdh.nCount--;
925 mpClipRgnData->rdh.nRgnSize -= sizeof( RECT );
928 return TRUE;
931 // -----------------------------------------------------------------------
933 bool WinSalGraphics::unionClipRegion( const ::basegfx::B2DPolyPolygon& )
935 // TODO: implement and advertise OutDevSupport_B2DClip support
936 return false;
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 );
950 else
952 ULONG nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER);
953 mhRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData );
955 // if ExtCreateRegion(...) is not supported
956 if( !mhRegion )
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 );
964 pRect++;
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
991 if ( mhPen )
993 if ( !mbStockPen )
994 DeletePen( mhPen );
996 else
997 mhDefPen = hOldPen;
999 // set new data
1000 mhPen = hNewPen;
1001 mbPen = FALSE;
1002 mbStockPen = TRUE;
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 ) );
1013 HPEN hNewPen = 0;
1014 BOOL bStockPen = FALSE;
1016 // search for stock pen (only screen, because printer have problems,
1017 // when we use stock objects)
1018 if ( !mbPrinter )
1020 SalData* pSalData = GetSalData();
1021 for ( USHORT i = 0; i < pSalData->mnStockPenCount; i++ )
1023 if ( nPenColor == pSalData->maStockPenColorAry[i] )
1025 hNewPen = pSalData->mhStockPenAry[i];
1026 bStockPen = TRUE;
1027 break;
1032 // create new pen
1033 if ( !hNewPen )
1035 if ( !mbPrinter )
1037 if ( GetSalData()->mhDitherPal && ImplIsSysColorEntry( nSalColor ) )
1038 nPenColor = PALRGB_TO_RGB( nPenColor );
1041 hNewPen = CreatePen( PS_SOLID, mnPenWidth, nPenColor );
1042 bStockPen = FALSE;
1045 // select new pen
1046 HPEN hOldPen = SelectPen( mhDC, hNewPen );
1048 // destory or save old pen
1049 if ( mhPen )
1051 if ( !mbStockPen )
1052 DeletePen( mhPen );
1054 else
1055 mhDefPen = hOldPen;
1057 // set new data
1058 mnPenColor = nPenColor;
1059 mhPen = hNewPen;
1060 mbPen = TRUE;
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
1073 if ( mhBrush )
1075 if ( !mbStockBrush )
1076 DeleteBrush( mhBrush );
1078 else
1079 mhDefBrush = hOldBrush;
1081 // set new data
1082 mhBrush = hNewBrush;
1083 mbBrush = FALSE;
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)
1102 if ( !mbPrinter )
1104 for ( USHORT i = 0; i < pSalData->mnStockBrushCount; i++ )
1106 if ( nBrushColor == pSalData->maStockBrushColorAry[ i ] )
1108 hNewBrush = pSalData->mhStockBrushAry[i];
1109 bStockBrush = TRUE;
1110 break;
1115 // create new brush
1116 if ( !hNewBrush )
1118 if ( mbPrinter || !pSalData->mhDitherDIB )
1119 hNewBrush = CreateSolidBrush( nBrushColor );
1120 else
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 );
1149 else
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;
1162 pTmp++;
1166 hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_PAL_COLORS );
1170 bStockBrush = FALSE;
1173 // select new brush
1174 HBRUSH hOldBrush = SelectBrush( mhDC, hNewBrush );
1176 // destory or save old brush
1177 if ( mhBrush )
1179 if ( !mbStockBrush )
1180 DeleteBrush( mhBrush );
1182 else
1183 mhDefBrush = hOldBrush;
1185 // set new data
1186 mnBrushColor = nBrushColor;
1187 mhBrush = hNewBrush;
1188 mbBrush = TRUE;
1189 mbStockBrush = bStockBrush;
1192 // -----------------------------------------------------------------------
1194 void WinSalGraphics::SetXORMode( bool bSet, bool )
1196 mbXORMode = bSet;
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 )
1218 if ( mbXORMode )
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 );
1226 else
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 ) );
1238 if ( !mbPrinter &&
1239 GetSalData()->mhDitherPal &&
1240 ImplIsSysColorEntry( nSalColor ) )
1241 nCol = PALRGB_TO_RGB( nCol );
1243 if ( mbXORMode )
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 );
1251 else
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;
1263 if ( nX1 == nX2 )
1265 bPaintEnd = FALSE;
1266 if ( nY1 <= nY2 )
1267 nY2++;
1268 else
1269 nY2--;
1271 if ( nY1 == nY2 )
1273 bPaintEnd = FALSE;
1274 if ( nX1 <= nX2 )
1275 nX2++;
1276 else
1277 nX2--;
1280 LineTo( mhDC, (int)nX2, (int)nY2 );
1282 if ( bPaintEnd && !mbPrinter )
1284 if ( mbXORMode )
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 );
1292 else
1293 SetPixel( mhDC, (int)nX2, (int)nY2, mnPenColor );
1297 // -----------------------------------------------------------------------
1299 void WinSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
1301 if ( !mbPen )
1303 if ( !mbPrinter )
1305 PatBlt( mhDC, (int)nX, (int)nY, (int)nWidth, (int)nHeight,
1306 mbXORMode ? PATINVERT : PATCOPY );
1308 else
1310 RECT aWinRect;
1311 aWinRect.left = nX;
1312 aWinRect.top = nY;
1313 aWinRect.right = nX+nWidth;
1314 aWinRect.bottom = nY+nHeight;
1315 ::FillRect( mhDC, &aWinRect, mhBrush );
1318 else
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
1332 // von Punkten
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
1347 // von Punkten
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];
1358 UINT* pWinPointAry;
1359 UINT nPolyPolyPoints = 0;
1360 UINT nPoints;
1361 UINT i;
1363 if ( nPoly <= SAL_POLYPOLYCOUNT_STACKBUF )
1364 pWinPointAry = aWinPointAry;
1365 else
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;
1379 else
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;
1385 UINT n = 0;
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];
1392 n += nPoints;
1395 if ( !WIN_PolyPolygon( mhDC, pWinPointAryAry, (int*)pWinPointAry, (UINT)nPoly ) &&
1396 (nPolyPolyPoints > MAX_64KSALPOINTS) )
1398 nPolyPolyPoints = 0;
1399 nPoly = 0;
1402 nPolyPolyPoints += pWinPointAry[(UINT)nPoly];
1403 nPoly++;
1405 while ( nPolyPolyPoints < MAX_64KSALPOINTS );
1406 nPoly--;
1407 if ( pWinPointAry[(UINT)nPoly] > MAX_64KSALPOINTS )
1408 pWinPointAry[(UINT)nPoly] = MAX_64KSALPOINTS;
1409 if ( nPoly == 1 )
1410 WIN_Polygon( mhDC, pWinPointAryAry, *pWinPointAry );
1411 else
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 );
1436 return sal_True;
1437 #else
1438 return sal_False;
1439 #endif
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;
1454 BYTE* pWinFlagAry;
1455 if( nPoints > SAL_POLY_STACKBUF )
1457 pWinPointAry = new POINT[ nPoints ];
1458 pWinFlagAry = new BYTE[ nPoints ];
1460 else
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 ) )
1477 bRet = sal_True;
1481 if( pWinPointAry != aStackAry1 )
1483 delete [] pWinPointAry;
1484 delete [] pWinFlagAry;
1487 return bRet;
1488 #else
1489 return sal_False;
1490 #endif
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;
1511 BYTE* pWinFlagAry;
1512 if( nTotalPoints > SAL_POLY_STACKBUF )
1514 pWinPointAry = new POINT[ nTotalPoints ];
1515 pWinFlagAry = new BYTE[ nTotalPoints ];
1517 else
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 ) )
1534 bRet = sal_True;
1538 if( pWinPointAry != aStackAry1 )
1540 delete [] pWinPointAry;
1541 delete [] pWinFlagAry;
1544 return bRet;
1545 #else
1546 return sal_False;
1547 #endif
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 )
1560 ULONG i;
1561 for ( i = 0; i < nSize; i++ )
1563 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
1564 break;
1566 if ( i == nSize )
1567 return pSource;
1568 pSource++;
1570 return NULL;
1573 static BOOL ImplGetBoundingBox( double* nNumb, BYTE* pSource, ULONG nSize )
1575 BOOL bRetValue = FALSE;
1576 BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 );
1577 if ( pDest )
1579 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
1580 pDest += 14;
1582 int nSizeLeft = nSize - ( pDest - pSource );
1583 if ( nSizeLeft > 100 )
1584 nSizeLeft = 100; // only 100 bytes following the bounding box will be checked
1586 int i;
1587 for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
1589 int nDivision = 1;
1590 BOOL bDivision = FALSE;
1591 BOOL bNegative = FALSE;
1592 BOOL bValid = TRUE;
1594 while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++;
1595 BYTE nByte = *pDest;
1596 while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
1598 switch ( nByte )
1600 case '.' :
1601 if ( bDivision )
1602 bValid = FALSE;
1603 else
1604 bDivision = TRUE;
1605 break;
1606 case '-' :
1607 bNegative = TRUE;
1608 break;
1609 default :
1610 if ( ( nByte < '0' ) || ( nByte > '9' ) )
1611 nSizeLeft = 1; // error parsing the bounding box values
1612 else if ( bValid )
1614 if ( bDivision )
1615 nDivision*=10;
1616 nNumb[i] *= 10;
1617 nNumb[i] += nByte - '0';
1619 break;
1621 nSizeLeft--;
1622 nByte = *(++pDest);
1624 if ( bNegative )
1625 nNumb[i] = -nNumb[i];
1626 if ( bDivision && ( nDivision != 1 ) )
1627 nNumb[i] /= nDivision;
1629 if ( i == 4 )
1630 bRetValue = TRUE;
1632 return bRetValue;
1635 BOOL WinSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize )
1637 BOOL bRetValue = FALSE;
1639 if ( mbPrinter )
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"
1670 "userdict begin\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"
1676 "{\n"
1677 " pop languagelevel\n"
1678 " 1 ne\n"
1679 " {\n"
1680 " false setstrokeadjust false setoverprint\n"
1681 " } if\n"
1682 "} if\n\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
1697 // characters!)
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 );
1707 aBuf.append( " " );
1708 aBuf.append( pRect->top );
1709 aBuf.append( " moveto\n" );
1710 aBuf.append( pRect->right );
1711 aBuf.append( " " );
1712 aBuf.append( pRect->top );
1713 aBuf.append( " lineto\n" );
1714 aBuf.append( pRect->right );
1715 aBuf.append( " " );
1716 aBuf.append( pRect->bottom );
1717 aBuf.append( " lineto\n" );
1718 aBuf.append( pRect->left );
1719 aBuf.append( " " );
1720 aBuf.append( pRect->bottom );
1721 aBuf.append( " lineto\n"
1722 "closepath\n"
1723 "clip\n"
1724 "newpath\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 );
1743 aBuf.append( ' ' );
1744 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
1745 aBuf.append( ' ' );
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;
1756 ULONG nDoNow;
1757 while ( nToDo )
1759 nDoNow = nToDo;
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 );
1767 if (!nResult )
1768 break;
1769 nToDo -= nResult;
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 );
1783 bRetValue = TRUE;
1788 return bRetValue;
1791 // -----------------------------------------------------------------------
1793 SystemGraphicsData WinSalGraphics::GetGraphicsData() const
1795 SystemGraphicsData aRes;
1796 aRes.nSize = sizeof(aRes);
1797 aRes.hDC = mhDC;
1798 return aRes;
1801 // -----------------------------------------------------------------------