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 .
23 #include <rtl/strbuf.hxx>
24 #include <tools/debug.hxx>
25 #include <tools/poly.hxx>
26 #include <basegfx/polygon/b2dpolygon.hxx>
27 #include <basegfx/polygon/b2dpolygontools.hxx>
28 #include <basegfx/polygon/b2dpolypolygontools.hxx>
29 #include <win/wincomp.hxx>
30 #include <win/saldata.hxx>
31 #include <win/salgdi.h>
32 #include <win/salframe.h>
33 #include <win/salvd.h>
34 #include <basegfx/matrix/b2dhommatrixtools.hxx>
36 #include "salgdiimpl.hxx"
37 #include "gdiimpl.hxx"
38 #include "opengl/win/gdiimpl.hxx"
39 #include <config_cairo_canvas.h>
40 #if ENABLE_CAIRO_CANVAS
41 #include "cairo_win32_cairo.cxx"
44 #include <vcl/opengl/OpenGLHelper.hxx>
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])
60 static SysColorEntry
* pFirstSysColor
= NULL
;
61 static SysColorEntry
* pActSysColor
= NULL
;
64 static PALETTEENTRY aImplExtraColor1
=
69 static PALETTEENTRY aImplSalSysPalEntryAry
[ DITHER_MAX_SYSCOLOR
] =
78 { 0x80, 0x80, 0x80, 0 },
79 { 0xC0, 0xC0, 0xC0, 0 },
86 { 0xFF, 0xFF, 0xFF, 0 }
89 static BYTE aOrdDither8Bit
[8][8] =
91 { 0, 38, 9, 48, 2, 40, 12, 50 },
92 { 25, 12, 35, 22, 28, 15, 37, 24 },
93 { 6, 44, 3, 41, 8, 47, 5, 44 },
94 { 32, 19, 28, 16, 34, 21, 31, 18 },
95 { 1, 40, 11, 49, 0, 39, 10, 48 },
96 { 27, 14, 36, 24, 26, 13, 36, 23 },
97 { 8, 46, 4, 43, 7, 45, 4, 42 },
98 { 33, 20, 30, 17, 32, 20, 29, 16 }
101 static BYTE aOrdDither16Bit
[8][8] =
103 { 0, 6, 1, 7, 0, 6, 1, 7 },
104 { 4, 2, 5, 3, 4, 2, 5, 3 },
105 { 1, 7, 0, 6, 1, 7, 0, 6 },
106 { 5, 3, 4, 2, 5, 3, 4, 2 },
107 { 0, 6, 1, 7, 0, 6, 1, 7 },
108 { 4, 2, 5, 3, 4, 2, 5, 3 },
109 { 1, 7, 0, 6, 1, 7, 0, 6 },
110 { 5, 3, 4, 2, 5, 3, 4, 2 }
113 // we must create pens with 1-pixel width; otherwise the S3-graphics card
114 // map has many paint problems when drawing polygons/polyLines and a
116 #define GSL_PEN_WIDTH 1
118 void ImplInitSalGDI()
120 SalData
* pSalData
= GetSalData();
122 pSalData
->mbResourcesAlreadyFreed
= false;
124 // init stock brushes
125 pSalData
->maStockPenColorAry
[0] = PALETTERGB( 0, 0, 0 );
126 pSalData
->maStockPenColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
127 pSalData
->maStockPenColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
128 pSalData
->maStockPenColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
129 pSalData
->mhStockPenAry
[0] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[0] );
130 pSalData
->mhStockPenAry
[1] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[1] );
131 pSalData
->mhStockPenAry
[2] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[2] );
132 pSalData
->mhStockPenAry
[3] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[3] );
133 pSalData
->mnStockPenCount
= 4;
135 pSalData
->maStockBrushColorAry
[0] = PALETTERGB( 0, 0, 0 );
136 pSalData
->maStockBrushColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
137 pSalData
->maStockBrushColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
138 pSalData
->maStockBrushColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
139 pSalData
->mhStockBrushAry
[0] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[0] );
140 pSalData
->mhStockBrushAry
[1] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[1] );
141 pSalData
->mhStockBrushAry
[2] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[2] );
142 pSalData
->mhStockBrushAry
[3] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[3] );
143 pSalData
->mnStockBrushCount
= 4;
145 // initialize cache of device contexts
146 pSalData
->mpHDCCache
= new HDCCache
[ CACHESIZE_HDC
];
147 memset( pSalData
->mpHDCCache
, 0, CACHESIZE_HDC
* sizeof( HDCCache
) );
149 // initialize temporary font list
150 pSalData
->mpTempFontItem
= NULL
;
152 // support palettes for 256 color displays
153 HDC hDC
= GetDC( 0 );
154 int nBitsPixel
= GetDeviceCaps( hDC
, BITSPIXEL
);
155 int nPlanes
= GetDeviceCaps( hDC
, PLANES
);
156 int nRasterCaps
= GetDeviceCaps( hDC
, RASTERCAPS
);
157 int nBitCount
= nBitsPixel
* nPlanes
;
159 if ( (nBitCount
> 8) && (nBitCount
< 24) )
161 // test if we have to dither
162 HDC hMemDC
= ::CreateCompatibleDC( hDC
);
163 HBITMAP hMemBmp
= ::CreateCompatibleBitmap( hDC
, 8, 8 );
164 HBITMAP hBmpOld
= (HBITMAP
) ::SelectObject( hMemDC
, hMemBmp
);
165 HBRUSH hMemBrush
= ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
166 HBRUSH hBrushOld
= (HBRUSH
) ::SelectObject( hMemDC
, hMemBrush
);
167 bool bDither16
= TRUE
;
169 ::PatBlt( hMemDC
, 0, 0, 8, 8, PATCOPY
);
170 const COLORREF
aCol( ::GetPixel( hMemDC
, 0, 0 ) );
172 for( int nY
= 0; ( nY
< 8 ) && bDither16
; nY
++ )
173 for( int nX
= 0; ( nX
< 8 ) && bDither16
; nX
++ )
174 if( ::GetPixel( hMemDC
, nX
, nY
) != aCol
)
177 ::SelectObject( hMemDC
, hBrushOld
), ::DeleteObject( hMemBrush
);
178 ::SelectObject( hMemDC
, hBmpOld
), ::DeleteObject( hMemBmp
);
179 ::DeleteDC( hMemDC
);
183 // create DIBPattern for 16Bit dithering
186 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, sizeof( BITMAPINFOHEADER
) + 192 );
187 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
188 pSalData
->mpDitherDiff
= new long[ 256 ];
189 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
190 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
191 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
);
192 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
194 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
196 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
200 pBIH
->biBitCount
= 24;
202 for( n
= 0; n
< 256L; n
++ )
203 pSalData
->mpDitherDiff
[ n
] = n
- ( n
& 248L );
205 for( n
= 0; n
< 256L; n
++ )
206 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
& 248 );
208 for( n
= 0; n
< 256L; n
++ )
209 pSalData
->mpDitherHigh
[ n
] = (BYTE
) std::min( pSalData
->mpDitherLow
[ n
] + 8L, 255L );
212 else if ( (nRasterCaps
& RC_PALETTE
) && (nBitCount
== 8) )
214 BYTE nRed
, nGreen
, nBlue
;
216 PALETTEENTRY
* pPalEntry
;
218 const sal_uInt16 nDitherPalCount
= DITHER_PAL_COUNT
;
219 sal_uLong nTotalCount
= DITHER_MAX_SYSCOLOR
+ nDitherPalCount
+ DITHER_EXTRA_COLORS
;
221 // create logical palette
222 pLogPal
= (LOGPALETTE
*) new char[ sizeof( LOGPALETTE
) + ( nTotalCount
* sizeof( PALETTEENTRY
) ) ];
223 pLogPal
->palVersion
= 0x0300;
224 pLogPal
->palNumEntries
= (sal_uInt16
) nTotalCount
;
225 pPalEntry
= pLogPal
->palPalEntry
;
228 memcpy( pPalEntry
, aImplSalSysPalEntryAry
, DITHER_MAX_SYSCOLOR
* sizeof( PALETTEENTRY
) );
229 pPalEntry
+= DITHER_MAX_SYSCOLOR
;
231 // own palette (6/6/6)
232 for( nB
=0, nBlue
=0; nB
< DITHER_PAL_STEPS
; nB
++, nBlue
+= DITHER_PAL_DELTA
)
234 for( nG
=0, nGreen
=0; nG
< DITHER_PAL_STEPS
; nG
++, nGreen
+= DITHER_PAL_DELTA
)
236 for( nR
=0, nRed
=0; nR
< DITHER_PAL_STEPS
; nR
++, nRed
+= DITHER_PAL_DELTA
)
238 pPalEntry
->peRed
= nRed
;
239 pPalEntry
->peGreen
= nGreen
;
240 pPalEntry
->peBlue
= nBlue
;
241 pPalEntry
->peFlags
= 0;
247 // insert special 'Blue' as standard drawing color
248 *pPalEntry
++ = aImplExtraColor1
;
251 pSalData
->mhDitherPal
= CreatePalette( pLogPal
);
252 delete[] (char*) pLogPal
;
254 if( pSalData
->mhDitherPal
)
256 // create DIBPattern for 8Bit dithering
257 long nSize
= sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) ) + 64;
260 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, nSize
);
261 pSalData
->mpDitherDIB
= (BYTE
*) GlobalLock( pSalData
->mhDitherDIB
);
262 pSalData
->mpDitherDiff
= new long[ 256 ];
263 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
264 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
265 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) );
266 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
268 BITMAPINFOHEADER
* pBIH
= (BITMAPINFOHEADER
*) pSalData
->mpDitherDIB
;
269 short* pColors
= (short*) ( pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) );
271 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
275 pBIH
->biBitCount
= 8;
277 for( n
= 0; n
< nDitherPalCount
; n
++ )
278 pColors
[ n
] = (short)( n
+ DITHER_MAX_SYSCOLOR
);
280 for( n
= 0; n
< 256L; n
++ )
281 pSalData
->mpDitherDiff
[ n
] = n
% 51L;
283 for( n
= 0; n
< 256L; n
++ )
284 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
/ 51L );
286 for( n
= 0; n
< 256L; n
++ )
287 pSalData
->mpDitherHigh
[ n
] = (BYTE
)std::min( pSalData
->mpDitherLow
[ n
] + 1, 5 );
290 // get system color entries
291 ImplUpdateSysColorEntries();
297 void ImplFreeSalGDI()
299 SalData
* pSalData
= GetSalData();
301 if (pSalData
->mbResourcesAlreadyFreed
)
304 // destroy stock objects
306 for ( i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
307 DeletePen( pSalData
->mhStockPenAry
[i
] );
308 for ( i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
309 DeleteBrush( pSalData
->mhStockBrushAry
[i
] );
312 if ( pSalData
->mh50Brush
)
314 DeleteBrush( pSalData
->mh50Brush
);
315 pSalData
->mh50Brush
= 0;
319 if ( pSalData
->mh50Bmp
)
321 DeleteBitmap( pSalData
->mh50Bmp
);
322 pSalData
->mh50Bmp
= 0;
325 ImplClearHDCCache( pSalData
);
326 delete[] pSalData
->mpHDCCache
;
328 // delete Ditherpalette, if existing
329 if ( pSalData
->mhDitherPal
)
331 DeleteObject( pSalData
->mhDitherPal
);
332 pSalData
->mhDitherPal
= 0;
335 // delete buffers for dithering DIB patterns, if necessary
336 if ( pSalData
->mhDitherDIB
)
338 GlobalUnlock( pSalData
->mhDitherDIB
);
339 GlobalFree( pSalData
->mhDitherDIB
);
340 pSalData
->mhDitherDIB
= 0;
341 delete[] pSalData
->mpDitherDiff
;
342 delete[] pSalData
->mpDitherLow
;
343 delete[] pSalData
->mpDitherHigh
;
346 // delete SysColorList
347 SysColorEntry
* pEntry
= pFirstSysColor
;
350 SysColorEntry
* pTmp
= pEntry
->pNext
;
354 pFirstSysColor
= NULL
;
357 SalIcon
* pIcon
= pSalData
->mpFirstIcon
;
358 pSalData
->mpFirstIcon
= NULL
;
361 SalIcon
* pTmp
= pIcon
->pNext
;
362 DestroyIcon( pIcon
->hIcon
);
363 DestroyIcon( pIcon
->hSmallIcon
);
368 // delete temporary font list
369 ImplReleaseTempFonts( *pSalData
);
371 pSalData
->mbResourcesAlreadyFreed
= true;
374 int ImplIsSysColorEntry( SalColor nSalColor
)
376 SysColorEntry
* pEntry
= pFirstSysColor
;
377 const DWORD nTestRGB
= (DWORD
)RGB( SALCOLOR_RED( nSalColor
),
378 SALCOLOR_GREEN( nSalColor
),
379 SALCOLOR_BLUE( nSalColor
) );
383 if ( pEntry
->nRGB
== nTestRGB
)
385 pEntry
= pEntry
->pNext
;
391 static int ImplIsPaletteEntry( BYTE nRed
, BYTE nGreen
, BYTE nBlue
)
394 if ( !(nRed
% DITHER_PAL_DELTA
) && !(nGreen
% DITHER_PAL_DELTA
) && !(nBlue
% DITHER_PAL_DELTA
) )
397 PALETTEENTRY
* pPalEntry
= aImplSalSysPalEntryAry
;
399 // standard palette color?
400 for ( sal_uInt16 i
= 0; i
< DITHER_MAX_SYSCOLOR
; i
++, pPalEntry
++ )
402 if( pPalEntry
->peRed
== nRed
&& pPalEntry
->peGreen
== nGreen
&& pPalEntry
->peBlue
== nBlue
)
407 if ( aImplExtraColor1
.peRed
== nRed
&&
408 aImplExtraColor1
.peGreen
== nGreen
&&
409 aImplExtraColor1
.peBlue
== nBlue
)
417 static void ImplInsertSysColorEntry( int nSysIndex
)
419 const DWORD nRGB
= GetSysColor( nSysIndex
);
421 if ( !ImplIsPaletteEntry( GetRValue( nRGB
), GetGValue( nRGB
), GetBValue( nRGB
) ) )
423 if ( !pFirstSysColor
)
425 pActSysColor
= pFirstSysColor
= new SysColorEntry
;
426 pFirstSysColor
->nRGB
= nRGB
;
427 pFirstSysColor
->pNext
= NULL
;
431 pActSysColor
= pActSysColor
->pNext
= new SysColorEntry
;
432 pActSysColor
->nRGB
= nRGB
;
433 pActSysColor
->pNext
= NULL
;
438 void ImplUpdateSysColorEntries()
440 // delete old SysColorList
441 SysColorEntry
* pEntry
= pFirstSysColor
;
444 SysColorEntry
* pTmp
= pEntry
->pNext
;
448 pActSysColor
= pFirstSysColor
= NULL
;
450 // create new sys color list
451 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER
);
452 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER
);
453 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION
);
454 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION
);
455 ImplInsertSysColorEntry( COLOR_3DFACE
);
456 ImplInsertSysColorEntry( COLOR_3DHILIGHT
);
457 ImplInsertSysColorEntry( COLOR_3DLIGHT
);
458 ImplInsertSysColorEntry( COLOR_3DSHADOW
);
459 ImplInsertSysColorEntry( COLOR_3DDKSHADOW
);
460 ImplInsertSysColorEntry( COLOR_INFOBK
);
461 ImplInsertSysColorEntry( COLOR_INFOTEXT
);
462 ImplInsertSysColorEntry( COLOR_BTNTEXT
);
463 ImplInsertSysColorEntry( COLOR_WINDOW
);
464 ImplInsertSysColorEntry( COLOR_WINDOWTEXT
);
465 ImplInsertSysColorEntry( COLOR_HIGHLIGHT
);
466 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT
);
467 ImplInsertSysColorEntry( COLOR_MENU
);
468 ImplInsertSysColorEntry( COLOR_MENUTEXT
);
469 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION
);
470 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT
);
471 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION
);
472 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT
);
475 void WinSalGraphics::InitGraphics()
477 // calculate the minimal line width for the printer
480 int nDPIX
= GetDeviceCaps( getHDC(), LOGPIXELSX
);
484 mnPenWidth
= nDPIX
/300;
487 ::SetTextAlign( getHDC(), TA_BASELINE
| TA_LEFT
| TA_NOUPDATECP
);
488 ::SetBkMode( getHDC(), TRANSPARENT
);
489 ::SetROP2( getHDC(), R2_COPYPEN
);
494 void WinSalGraphics::DeInitGraphics()
497 SelectClipRgn( getHDC(), 0 );
498 // select default objects
500 SelectPen( getHDC(), mhDefPen
);
502 SelectBrush( getHDC(), mhDefBrush
);
504 SelectFont( getHDC(), mhDefFont
);
509 HDC
ImplGetCachedDC( sal_uLong nID
, HBITMAP hBmp
)
511 SalData
* pSalData
= GetSalData();
512 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
516 HDC hDC
= GetDC( 0 );
518 // create new DC with DefaultBitmap
519 pC
->mhDC
= CreateCompatibleDC( hDC
);
521 if( pSalData
->mhDitherPal
)
523 pC
->mhDefPal
= SelectPalette( pC
->mhDC
, pSalData
->mhDitherPal
, TRUE
);
524 RealizePalette( pC
->mhDC
);
527 pC
->mhSelBmp
= CreateCompatibleBitmap( hDC
, CACHED_HDC_DEFEXT
, CACHED_HDC_DEFEXT
);
528 pC
->mhDefBmp
= (HBITMAP
) SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
534 SelectObject( pC
->mhDC
, pC
->mhActBmp
= hBmp
);
541 void ImplReleaseCachedDC( sal_uLong nID
)
543 SalData
* pSalData
= GetSalData();
544 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
547 SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
550 void ImplClearHDCCache( SalData
* pData
)
552 for( sal_uLong i
= 0; i
< CACHESIZE_HDC
; i
++ )
554 HDCCache
* pC
= &pData
->mpHDCCache
[ i
];
558 SelectObject( pC
->mhDC
, pC
->mhDefBmp
);
561 SelectPalette( pC
->mhDC
, pC
->mhDefPal
, TRUE
);
563 DeleteDC( pC
->mhDC
);
564 DeleteObject( pC
->mhSelBmp
);
569 OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics
&rGraphics
, int x
, int y
, int width
, int height
)
572 , maRects(0, 0, width
, height
, x
, y
, width
, height
)
574 WinSalGraphics
& rWinGraphics
= static_cast<WinSalGraphics
&>(rGraphics
);
575 mpImpl
= dynamic_cast<WinOpenGLSalGraphicsImpl
*>(rWinGraphics
.mpImpl
.get());
579 // we avoid the OpenGL drawing, instead we draw directly to the DC
580 mhCompatibleDC
= rWinGraphics
.getHDC();
584 mhCompatibleDC
= CreateCompatibleDC(rWinGraphics
.getHDC());
586 // move the origin so that we always paint at 0,0 - to keep the bitmap
588 OffsetViewportOrgEx(mhCompatibleDC
, -x
, -y
, NULL
);
590 mhBitmap
= WinSalVirtualDevice::ImplCreateVirDevBitmap(mhCompatibleDC
, width
, height
, 32, reinterpret_cast<void **>(&mpData
));
592 mhOrigBitmap
= (HBITMAP
) SelectObject(mhCompatibleDC
, mhBitmap
);
595 OpenGLCompatibleDC::~OpenGLCompatibleDC()
599 SelectObject(mhCompatibleDC
, mhOrigBitmap
);
600 DeleteObject(mhBitmap
);
601 DeleteDC(mhCompatibleDC
);
605 void OpenGLCompatibleDC::fill(sal_uInt32 color
)
610 sal_uInt32
*p
= mpData
;
611 for (int i
= maRects
.mnSrcWidth
* maRects
.mnSrcHeight
; i
> 0; --i
)
615 OpenGLTexture
* OpenGLCompatibleDC::getTexture()
620 // turn what's in the mpData into a texture
621 return new OpenGLTexture(maRects
.mnSrcWidth
, maRects
.mnSrcHeight
, GL_BGRA
, GL_UNSIGNED_BYTE
, reinterpret_cast<sal_uInt8
*>(mpData
));
624 WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType
, bool bScreen
, HWND hWnd
, SalGeometryProvider
*pProvider
):
626 mbPrinter(eType
== WinSalGraphics::PRINTER
),
627 mbVirDev(eType
== WinSalGraphics::VIRTUAL_DEVICE
),
628 mbWindow(eType
== WinSalGraphics::WINDOW
),
631 mfCurrentFontScale(1.0),
637 mpStdClipRgnData(NULL
),
638 mpFontAttrCache(NULL
),
639 mnPenWidth(GSL_PEN_WIDTH
)
641 if (OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter
)
642 mpImpl
.reset(new WinOpenGLSalGraphicsImpl(*this, pProvider
));
644 mpImpl
.reset(new WinSalGraphicsImpl(*this));
646 for( int i
= 0; i
< MAX_FALLBACK
; ++i
)
649 mpWinFontData
[ i
] = NULL
;
650 mpWinFontEntry
[ i
] = NULL
;
651 mfFontScale
[ i
] = 1.0;
655 WinSalGraphics::~WinSalGraphics()
657 // free obsolete GDI objects
662 DeleteRegion( mhRegion
);
667 delete [] mpStdClipRgnData
;
670 SalGraphicsImpl
* WinSalGraphics::GetImpl() const
675 bool WinSalGraphics::isPrinter() const
680 bool WinSalGraphics::isVirtualDevice() const
685 bool WinSalGraphics::isWindow() const
690 bool WinSalGraphics::isScreen() const
695 HWND
WinSalGraphics::gethWnd()
700 void WinSalGraphics::setHWND(HWND hWnd
)
705 HPALETTE
WinSalGraphics::getDefPal() const
710 void WinSalGraphics::setDefPal(HPALETTE hDefPal
)
715 HRGN
WinSalGraphics::getRegion() const
720 void WinSalGraphics::GetResolution( sal_Int32
& rDPIX
, sal_Int32
& rDPIY
)
722 rDPIX
= GetDeviceCaps( getHDC(), LOGPIXELSX
);
723 rDPIY
= GetDeviceCaps( getHDC(), LOGPIXELSY
);
725 // #111139# this fixes the symptom of div by zero on startup
726 // however, printing will fail most likely as communication with
727 // the printer seems not to work in this case
728 if( !rDPIX
|| !rDPIY
)
732 sal_uInt16
WinSalGraphics::GetBitCount() const
734 return mpImpl
->GetBitCount();
737 long WinSalGraphics::GetGraphicsWidth() const
739 return mpImpl
->GetGraphicsWidth();
742 void WinSalGraphics::ResetClipRegion()
744 mpImpl
->ResetClipRegion();
747 bool WinSalGraphics::setClipRegion( const vcl::Region
& i_rClip
)
749 return mpImpl
->setClipRegion( i_rClip
);
752 void WinSalGraphics::SetLineColor()
754 mpImpl
->SetLineColor();
757 void WinSalGraphics::SetLineColor( SalColor nSalColor
)
759 mpImpl
->SetLineColor( nSalColor
);
762 void WinSalGraphics::SetFillColor()
764 mpImpl
->SetFillColor();
767 void WinSalGraphics::SetFillColor( SalColor nSalColor
)
769 mpImpl
->SetFillColor( nSalColor
);
772 void WinSalGraphics::SetXORMode( bool bSet
, bool bInvertOnly
)
774 mpImpl
->SetXORMode( bSet
, bInvertOnly
);
777 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
779 mpImpl
->SetROPLineColor( nROPColor
);
782 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
784 mpImpl
->SetROPFillColor( nROPColor
);
787 void WinSalGraphics::drawPixel( long nX
, long nY
)
789 mpImpl
->drawPixel( nX
, nY
);
792 void WinSalGraphics::drawPixel( long nX
, long nY
, SalColor nSalColor
)
794 mpImpl
->drawPixel( nX
, nY
, nSalColor
);
797 void WinSalGraphics::drawLine( long nX1
, long nY1
, long nX2
, long nY2
)
799 mpImpl
->drawLine( nX1
, nY1
, nX2
, nY2
);
802 void WinSalGraphics::drawRect( long nX
, long nY
, long nWidth
, long nHeight
)
804 mpImpl
->drawRect( nX
, nY
, nWidth
, nHeight
);
807 void WinSalGraphics::drawPolyLine( sal_uInt32 nPoints
, const SalPoint
* pPtAry
)
809 mpImpl
->drawPolyLine( nPoints
, pPtAry
);
812 void WinSalGraphics::drawPolygon( sal_uInt32 nPoints
, const SalPoint
* pPtAry
)
814 mpImpl
->drawPolygon( nPoints
, pPtAry
);
817 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
818 PCONSTSALPOINT
* pPtAry
)
820 mpImpl
->drawPolyPolygon( nPoly
, pPoints
, pPtAry
);
823 bool WinSalGraphics::drawPolyLineBezier( sal_uInt32 nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
825 return mpImpl
->drawPolyLineBezier( nPoints
, pPtAry
, pFlgAry
);
828 bool WinSalGraphics::drawPolygonBezier( sal_uInt32 nPoints
, const SalPoint
* pPtAry
, const BYTE
* pFlgAry
)
830 return mpImpl
->drawPolygonBezier( nPoints
, pPtAry
, pFlgAry
);
833 bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
834 const SalPoint
* const* pPtAry
, const BYTE
* const* pFlgAry
)
836 return mpImpl
->drawPolyPolygonBezier( nPoly
, pPoints
, pPtAry
, pFlgAry
);
839 static BYTE
* ImplSearchEntry( BYTE
* pSource
, BYTE
* pDest
, sal_uLong nComp
, sal_uLong nSize
)
841 while ( nComp
-- >= nSize
)
844 for ( i
= 0; i
< nSize
; i
++ )
846 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
856 static bool ImplGetBoundingBox( double* nNumb
, BYTE
* pSource
, sal_uLong nSize
)
858 bool bRetValue
= FALSE
;
859 BYTE
* pDest
= ImplSearchEntry( pSource
, (BYTE
*)"%%BoundingBox:", nSize
, 14 );
862 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
865 int nSizeLeft
= nSize
- ( pDest
- pSource
);
866 if ( nSizeLeft
> 100 )
867 nSizeLeft
= 100; // only 100 bytes following the bounding box will be checked
870 for ( i
= 0; ( i
< 4 ) && nSizeLeft
; i
++ )
873 bool bDivision
= FALSE
;
874 bool bNegative
= FALSE
;
877 while ( ( --nSizeLeft
) && ( ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) ) pDest
++;
879 while ( nSizeLeft
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
893 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
894 nSizeLeft
= 1; // error parsing the bounding box values
900 nNumb
[i
] += nByte
- '0';
908 nNumb
[i
] = -nNumb
[i
];
909 if ( bDivision
&& ( nDivision
!= 1 ) )
910 nNumb
[i
] /= nDivision
;
918 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
920 bool WinSalGraphics::drawEPS( long nX
, long nY
, long nWidth
, long nHeight
, void* pPtr
, sal_uLong nSize
)
922 bool bRetValue
= false;
926 int nEscape
= POSTSCRIPT_PASSTHROUGH
;
928 if ( Escape( getHDC(), QUERYESCSUPPORT
, sizeof( int ), ( LPSTR
)&nEscape
, 0 ) )
930 double nBoundingBox
[4];
932 if ( ImplGetBoundingBox( nBoundingBox
, (BYTE
*)pPtr
, nSize
) )
934 OStringBuffer
aBuf( POSTSCRIPT_BUFSIZE
);
936 // reserve place for a sal_uInt16
939 // #107797# Write out EPS encapsulation header
941 // directly taken from the PLRM 3.0, p. 726. Note:
942 // this will definitely cause problems when
943 // recursively creating and embedding PostScript files
944 // in OOo, since we use statically-named variables
945 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
946 // op_count_salWin). Currently, I have no idea on how to
947 // work around that, except from scanning and
948 // interpreting the EPS for unused identifiers.
950 // append the real text
951 aBuf
.append( "\n\n/b4_Inc_state_salWin save def\n"
952 "/dict_count_salWin countdictstack def\n"
953 "/op_count_salWin count 1 sub def\n"
956 "0 setgray 0 setlinecap\n"
957 "1 setlinewidth 0 setlinejoin\n"
958 "10 setmiterlimit [] 0 setdash newpath\n"
959 "/languagelevel where\n"
961 " pop languagelevel\n"
964 " false setstrokeadjust false setoverprint\n"
968 // #i10737# Apply clipping manually
970 // Windows seems to ignore any clipping at the HDC,
971 // when followed by a POSTSCRIPT_PASSTHROUGH
973 // Check whether we've got a clipping, consisting of
974 // exactly one rect (other cases should be, but aren't
975 // handled currently)
977 // TODO: Handle more than one rectangle here (take
978 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
980 if ( mhRegion
!= 0 &&
981 mpStdClipRgnData
!= NULL
&&
982 mpClipRgnData
== mpStdClipRgnData
&&
983 mpClipRgnData
->rdh
.nCount
== 1 )
985 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
987 aBuf
.append( "\nnewpath\n" );
988 aBuf
.append( pRect
->left
);
990 aBuf
.append( pRect
->top
);
991 aBuf
.append( " moveto\n" );
992 aBuf
.append( pRect
->right
);
994 aBuf
.append( pRect
->top
);
995 aBuf
.append( " lineto\n" );
996 aBuf
.append( pRect
->right
);
998 aBuf
.append( pRect
->bottom
);
999 aBuf
.append( " lineto\n" );
1000 aBuf
.append( pRect
->left
);
1002 aBuf
.append( pRect
->bottom
);
1003 aBuf
.append( " lineto\n"
1009 // #107797# Write out buffer
1011 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1012 Escape ( getHDC(), nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1014 // #107797# Write out EPS transformation code
1016 double dM11
= nWidth
/ ( nBoundingBox
[2] - nBoundingBox
[0] );
1017 double dM22
= nHeight
/ (nBoundingBox
[1] - nBoundingBox
[3] );
1018 // reserve a sal_uInt16 again
1019 aBuf
.setLength( 2 );
1020 aBuf
.append( "\n\n[" );
1021 aBuf
.append( dM11
);
1022 aBuf
.append( " 0 0 " );
1023 aBuf
.append( dM22
);
1025 aBuf
.append( nX
- ( dM11
* nBoundingBox
[0] ) );
1027 aBuf
.append( nY
- ( dM22
* nBoundingBox
[3] ) );
1028 aBuf
.append( "] concat\n"
1029 "%%BeginDocument:\n" );
1030 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1031 Escape ( getHDC(), nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1033 // #107797# Write out actual EPS content
1035 sal_uLong nToDo
= nSize
;
1040 if ( nToDo
> POSTSCRIPT_BUFSIZE
- 2 )
1041 nDoNow
= POSTSCRIPT_BUFSIZE
- 2;
1042 // the following is based on the string buffer allocation
1043 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1044 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)nDoNow
;
1045 memcpy( (void*)(aBuf
.getStr() + 2), (BYTE
*)pPtr
+ nSize
- nToDo
, nDoNow
);
1046 sal_uLong nResult
= Escape ( getHDC(), nEscape
, nDoNow
+ 2, (LPTSTR
)aBuf
.getStr(), 0 );
1052 // #107797# Write out EPS encapsulation footer
1054 // reserve a sal_uInt16 again
1055 aBuf
.setLength( 2 );
1056 aBuf
.append( "%%EndDocument\n"
1057 "count op_count_salWin sub {pop} repeat\n"
1058 "countdictstack dict_count_salWin sub {end} repeat\n"
1059 "b4_Inc_state_salWin restore\n\n" );
1060 *((sal_uInt16
*)aBuf
.getStr()) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1061 Escape ( getHDC(), nEscape
, aBuf
.getLength(), (LPTSTR
)aBuf
.getStr(), 0 );
1070 SystemGraphicsData
WinSalGraphics::GetGraphicsData() const
1072 SystemGraphicsData aRes
;
1073 aRes
.nSize
= sizeof(aRes
);
1074 aRes
.hDC
= const_cast< WinSalGraphics
* >(this)->getHDC();
1078 bool WinSalGraphics::SupportsCairo() const
1080 #if ENABLE_CAIRO_CANVAS
1088 * cairo::createSurface: Create generic Canvas surface using given Cairo Surface
1090 * @param rSurface Cairo Surface
1092 * @return new Surface
1094 cairo::SurfaceSharedPtr
WinSalGraphics::CreateSurface(const cairo::CairoSurfaceSharedPtr
& rSurface
) const
1096 #if ENABLE_CAIRO_CANVAS
1097 return cairo::SurfaceSharedPtr(new cairo::Win32Surface(rSurface
));
1100 return cairo::SurfaceSharedPtr();
1105 * cairo::createSurface: Create Canvas surface using given VCL Window or Virtualdevice
1107 * @param rSurface Cairo Surface
1109 * For VCL Window, use platform native system environment data (struct SystemEnvData in vcl/inc/sysdata.hxx)
1110 * For VCL Virtualdevice, use platform native system graphics data (struct SystemGraphicsData in vcl/inc/sysdata.hxx)
1112 * @return new Surface
1114 cairo::SurfaceSharedPtr
WinSalGraphics::CreateSurface( const OutputDevice
& rRefDevice
,
1115 int x
, int y
, int /* width */, int /* height */) const
1117 cairo::SurfaceSharedPtr surf
;
1119 #if ENABLE_CAIRO_CANVAS
1120 if( rRefDevice
.GetOutDevType() == OUTDEV_WINDOW
)
1122 const vcl::Window
&rWindow
= (const vcl::Window
&) rRefDevice
;
1123 const SystemEnvData
* pSysData
= GetSysData(&rWindow
);
1124 if (pSysData
&& pSysData
->hWnd
)
1125 surf
= cairo::SurfaceSharedPtr(new cairo::Win32Surface(GetDC((HWND
) pSysData
->hWnd
), x
, y
));
1127 else if( rRefDevice
.GetOutDevType() == OUTDEV_VIRDEV
)
1129 SystemGraphicsData aSysData
= ((const VirtualDevice
&) rRefDevice
).GetSystemGfxData();
1131 surf
= cairo::SurfaceSharedPtr(new cairo::Win32Surface((HDC
) aSysData
.hDC
, x
, y
));
1143 * cairo::createBitmapSurface: Create platform native Canvas surface from BitmapSystemData
1144 * @param OutputDevice (not used)
1145 * @param rData Platform native image data (struct BitmapSystemData in vcl/inc/bitmap.hxx)
1146 * @param rSize width and height of the new surface
1148 * Create a surface based on image data on rData
1150 * @return new surface or empty surface
1152 cairo::SurfaceSharedPtr
WinSalGraphics::CreateBitmapSurface( const OutputDevice
& /* rRefDevice */,
1153 const BitmapSystemData
& rData
,
1154 const Size
& rSize
) const
1156 OSL_TRACE( "requested size: %d x %d available size: %d x %d",
1157 rSize
.Width(), rSize
.Height(), rData
.mnWidth
, rData
.mnHeight
);
1159 #if ENABLE_CAIRO_CANVAS
1160 if ( rData
.mnWidth
== rSize
.Width() && rData
.mnHeight
== rSize
.Height() )
1161 return cairo::SurfaceSharedPtr(new cairo::Win32Surface( rData
));
1166 return cairo::SurfaceSharedPtr();
1169 #if ENABLE_CAIRO_CANVAS
1172 HBITMAP
surface2HBitmap( const SurfaceSharedPtr
& rSurface
, const basegfx::B2ISize
& rSize
)
1174 // can't seem to retrieve HBITMAP from cairo. copy content then
1175 HDC hScreenDC
=GetDC(NULL
);
1176 HBITMAP hBmpBitmap
= CreateCompatibleBitmap( hScreenDC
,
1180 HDC hBmpDC
= CreateCompatibleDC( 0 );
1181 HBITMAP hBmpOld
= (HBITMAP
) SelectObject( hBmpDC
, hBmpBitmap
);
1183 BitBlt( hBmpDC
, 0, 0, rSize
.getX(), rSize
.getX(),
1184 cairo_win32_surface_get_dc(rSurface
->getCairoSurface().get()),
1187 SelectObject( hBmpDC
, hBmpOld
);
1195 css::uno::Any
WinSalGraphics::GetNativeSurfaceHandle(cairo::SurfaceSharedPtr
& rSurface
, const ::basegfx::B2ISize
& rSize
) const
1197 // TODO(F2): check whether under all circumstances,
1198 // the alpha channel is ignored here.
1199 css::uno::Sequence
< css::uno::Any
> args( 1 );
1201 #if ENABLE_CAIRO_CANVAS
1202 nHandle
= sal_Int64(surface2HBitmap(rSurface
, rSize
));
1208 args
[1] = css::uno::Any(nHandle
);
1209 // caller frees the bitmap
1210 return css::uno::Any( args
);
1213 OpenGLContext
*WinSalGraphics::BeginPaint()
1215 return mpImpl
->beginPaint();
1218 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */