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 .
22 #include <rtl/strbuf.hxx>
23 #include <tools/debug.hxx>
24 #include <tools/poly.hxx>
25 #include <basegfx/polygon/b2dpolygon.hxx>
26 #include <basegfx/polygon/b2dpolygontools.hxx>
27 #include <basegfx/polygon/b2dpolypolygontools.hxx>
28 #include <win/wincomp.hxx>
29 #include <win/saldata.hxx>
30 #include <win/salgdi.h>
31 #include <win/salframe.h>
32 #include <win/salvd.h>
33 #include <basegfx/matrix/b2dhommatrixtools.hxx>
35 #include "salgdiimpl.hxx"
36 #include "gdiimpl.hxx"
37 #include "opengl/win/gdiimpl.hxx"
39 #include <vcl/opengl/OpenGLHelper.hxx>
42 #define DITHER_PAL_DELTA 51
43 #define DITHER_PAL_STEPS 6
44 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS)
45 #define DITHER_MAX_SYSCOLOR 16
46 #define DITHER_EXTRA_COLORS 1
54 static SysColorEntry
* pFirstSysColor
= nullptr;
55 static SysColorEntry
* pActSysColor
= nullptr;
58 static PALETTEENTRY aImplExtraColor1
=
63 static PALETTEENTRY aImplSalSysPalEntryAry
[ DITHER_MAX_SYSCOLOR
] =
72 { 0x80, 0x80, 0x80, 0 },
73 { 0xC0, 0xC0, 0xC0, 0 },
80 { 0xFF, 0xFF, 0xFF, 0 }
83 // we must create pens with 1-pixel width; otherwise the S3-graphics card
84 // map has many paint problems when drawing polygons/polyLines and a
86 #define GSL_PEN_WIDTH 1
90 SalData
* pSalData
= GetSalData();
92 pSalData
->mbResourcesAlreadyFreed
= false;
95 pSalData
->maStockPenColorAry
[0] = PALETTERGB( 0, 0, 0 );
96 pSalData
->maStockPenColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
97 pSalData
->maStockPenColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
98 pSalData
->maStockPenColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
99 pSalData
->mhStockPenAry
[0] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[0] );
100 pSalData
->mhStockPenAry
[1] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[1] );
101 pSalData
->mhStockPenAry
[2] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[2] );
102 pSalData
->mhStockPenAry
[3] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[3] );
103 pSalData
->mnStockPenCount
= 4;
105 pSalData
->maStockBrushColorAry
[0] = PALETTERGB( 0, 0, 0 );
106 pSalData
->maStockBrushColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
107 pSalData
->maStockBrushColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
108 pSalData
->maStockBrushColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
109 pSalData
->mhStockBrushAry
[0] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[0] );
110 pSalData
->mhStockBrushAry
[1] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[1] );
111 pSalData
->mhStockBrushAry
[2] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[2] );
112 pSalData
->mhStockBrushAry
[3] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[3] );
113 pSalData
->mnStockBrushCount
= 4;
115 // initialize cache of device contexts
116 pSalData
->mpHDCCache
= new HDCCache
[ CACHESIZE_HDC
];
117 memset( pSalData
->mpHDCCache
, 0, CACHESIZE_HDC
* sizeof( HDCCache
) );
119 // initialize temporary font list
120 pSalData
->mpTempFontItem
= nullptr;
122 // support palettes for 256 color displays
123 HDC hDC
= GetDC( nullptr );
124 int nBitsPixel
= GetDeviceCaps( hDC
, BITSPIXEL
);
125 int nPlanes
= GetDeviceCaps( hDC
, PLANES
);
126 int nRasterCaps
= GetDeviceCaps( hDC
, RASTERCAPS
);
127 int nBitCount
= nBitsPixel
* nPlanes
;
129 if ( (nBitCount
> 8) && (nBitCount
< 24) )
131 // test if we have to dither
132 HDC hMemDC
= ::CreateCompatibleDC( hDC
);
133 HBITMAP hMemBmp
= ::CreateCompatibleBitmap( hDC
, 8, 8 );
134 HBITMAP hBmpOld
= static_cast<HBITMAP
>(::SelectObject( hMemDC
, hMemBmp
));
135 HBRUSH hMemBrush
= ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
136 HBRUSH hBrushOld
= static_cast<HBRUSH
>(::SelectObject( hMemDC
, hMemBrush
));
137 bool bDither16
= TRUE
;
139 ::PatBlt( hMemDC
, 0, 0, 8, 8, PATCOPY
);
140 const COLORREF
aCol( ::GetPixel( hMemDC
, 0, 0 ) );
142 for( int nY
= 0; ( nY
< 8 ) && bDither16
; nY
++ )
143 for( int nX
= 0; ( nX
< 8 ) && bDither16
; nX
++ )
144 if( ::GetPixel( hMemDC
, nX
, nY
) != aCol
)
147 ::SelectObject( hMemDC
, hBrushOld
);
148 ::DeleteObject( hMemBrush
);
149 ::SelectObject( hMemDC
, hBmpOld
);
150 ::DeleteObject( hMemBmp
);
151 ::DeleteDC( hMemDC
);
155 // create DIBPattern for 16Bit dithering
158 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, sizeof( BITMAPINFOHEADER
) + 192 );
159 pSalData
->mpDitherDIB
= static_cast<BYTE
*>(GlobalLock( pSalData
->mhDitherDIB
));
160 pSalData
->mpDitherDiff
= new long[ 256 ];
161 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
162 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
163 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
);
164 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
166 BITMAPINFOHEADER
* pBIH
= reinterpret_cast<BITMAPINFOHEADER
*>(pSalData
->mpDitherDIB
);
168 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
172 pBIH
->biBitCount
= 24;
174 for( n
= 0; n
< 256; n
++ )
175 pSalData
->mpDitherDiff
[ n
] = n
- ( n
& 248L );
177 for( n
= 0; n
< 256; n
++ )
178 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
& 248 );
180 for( n
= 0; n
< 256; n
++ )
181 pSalData
->mpDitherHigh
[ n
] = (BYTE
) std::min( pSalData
->mpDitherLow
[ n
] + 8, 255 );
184 else if ( (nRasterCaps
& RC_PALETTE
) && (nBitCount
== 8) )
186 BYTE nRed
, nGreen
, nBlue
;
188 PALETTEENTRY
* pPalEntry
;
190 const sal_uInt16 nDitherPalCount
= DITHER_PAL_COUNT
;
191 sal_uLong nTotalCount
= DITHER_MAX_SYSCOLOR
+ nDitherPalCount
+ DITHER_EXTRA_COLORS
;
193 // create logical palette
194 pLogPal
= reinterpret_cast<LOGPALETTE
*>(new char[ sizeof( LOGPALETTE
) + ( nTotalCount
* sizeof( PALETTEENTRY
) ) ]);
195 pLogPal
->palVersion
= 0x0300;
196 pLogPal
->palNumEntries
= (sal_uInt16
) nTotalCount
;
197 pPalEntry
= pLogPal
->palPalEntry
;
200 memcpy( pPalEntry
, aImplSalSysPalEntryAry
, DITHER_MAX_SYSCOLOR
* sizeof( PALETTEENTRY
) );
201 pPalEntry
+= DITHER_MAX_SYSCOLOR
;
203 // own palette (6/6/6)
204 for( nB
=0, nBlue
=0; nB
< DITHER_PAL_STEPS
; nB
++, nBlue
+= DITHER_PAL_DELTA
)
206 for( nG
=0, nGreen
=0; nG
< DITHER_PAL_STEPS
; nG
++, nGreen
+= DITHER_PAL_DELTA
)
208 for( nR
=0, nRed
=0; nR
< DITHER_PAL_STEPS
; nR
++, nRed
+= DITHER_PAL_DELTA
)
210 pPalEntry
->peRed
= nRed
;
211 pPalEntry
->peGreen
= nGreen
;
212 pPalEntry
->peBlue
= nBlue
;
213 pPalEntry
->peFlags
= 0;
219 // insert special 'Blue' as standard drawing color
220 *pPalEntry
++ = aImplExtraColor1
;
223 pSalData
->mhDitherPal
= CreatePalette( pLogPal
);
224 delete[] reinterpret_cast<char*>(pLogPal
);
226 if( pSalData
->mhDitherPal
)
228 // create DIBPattern for 8Bit dithering
229 long nSize
= sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) ) + 64;
232 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, nSize
);
233 pSalData
->mpDitherDIB
= static_cast<BYTE
*>(GlobalLock( pSalData
->mhDitherDIB
));
234 pSalData
->mpDitherDiff
= new long[ 256 ];
235 pSalData
->mpDitherLow
= new BYTE
[ 256 ];
236 pSalData
->mpDitherHigh
= new BYTE
[ 256 ];
237 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) );
238 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
240 BITMAPINFOHEADER
* pBIH
= reinterpret_cast<BITMAPINFOHEADER
*>(pSalData
->mpDitherDIB
);
241 short* pColors
= reinterpret_cast<short*>( pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) );
243 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
247 pBIH
->biBitCount
= 8;
249 for( n
= 0; n
< nDitherPalCount
; n
++ )
250 pColors
[ n
] = (short)( n
+ DITHER_MAX_SYSCOLOR
);
252 for( n
= 0; n
< 256; n
++ )
253 pSalData
->mpDitherDiff
[ n
] = n
% 51L;
255 for( n
= 0; n
< 256; n
++ )
256 pSalData
->mpDitherLow
[ n
] = (BYTE
) ( n
/ 51L );
258 for( n
= 0; n
< 256; n
++ )
259 pSalData
->mpDitherHigh
[ n
] = (BYTE
)std::min( pSalData
->mpDitherLow
[ n
] + 1, 5 );
262 // get system color entries
263 ImplUpdateSysColorEntries();
266 ReleaseDC( nullptr, hDC
);
269 void ImplFreeSalGDI()
271 SalData
* pSalData
= GetSalData();
273 if (pSalData
->mbResourcesAlreadyFreed
)
276 // destroy stock objects
278 for ( i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
279 DeletePen( pSalData
->mhStockPenAry
[i
] );
280 for ( i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
281 DeleteBrush( pSalData
->mhStockBrushAry
[i
] );
284 if ( pSalData
->mh50Brush
)
286 DeleteBrush( pSalData
->mh50Brush
);
287 pSalData
->mh50Brush
= nullptr;
291 if ( pSalData
->mh50Bmp
)
293 DeleteBitmap( pSalData
->mh50Bmp
);
294 pSalData
->mh50Bmp
= nullptr;
297 ImplClearHDCCache( pSalData
);
298 delete[] pSalData
->mpHDCCache
;
300 // delete Ditherpalette, if existing
301 if ( pSalData
->mhDitherPal
)
303 DeleteObject( pSalData
->mhDitherPal
);
304 pSalData
->mhDitherPal
= nullptr;
307 // delete buffers for dithering DIB patterns, if necessary
308 if ( pSalData
->mhDitherDIB
)
310 GlobalUnlock( pSalData
->mhDitherDIB
);
311 GlobalFree( pSalData
->mhDitherDIB
);
312 pSalData
->mhDitherDIB
= nullptr;
313 delete[] pSalData
->mpDitherDiff
;
314 delete[] pSalData
->mpDitherLow
;
315 delete[] pSalData
->mpDitherHigh
;
318 // delete SysColorList
319 SysColorEntry
* pEntry
= pFirstSysColor
;
322 SysColorEntry
* pTmp
= pEntry
->pNext
;
326 pFirstSysColor
= nullptr;
329 SalIcon
* pIcon
= pSalData
->mpFirstIcon
;
330 pSalData
->mpFirstIcon
= nullptr;
333 SalIcon
* pTmp
= pIcon
->pNext
;
334 DestroyIcon( pIcon
->hIcon
);
335 DestroyIcon( pIcon
->hSmallIcon
);
340 // delete temporary font list
341 ImplReleaseTempFonts( *pSalData
);
343 pSalData
->mbResourcesAlreadyFreed
= true;
346 int ImplIsSysColorEntry( SalColor nSalColor
)
348 SysColorEntry
* pEntry
= pFirstSysColor
;
349 const DWORD nTestRGB
= (DWORD
)RGB( SALCOLOR_RED( nSalColor
),
350 SALCOLOR_GREEN( nSalColor
),
351 SALCOLOR_BLUE( nSalColor
) );
355 if ( pEntry
->nRGB
== nTestRGB
)
357 pEntry
= pEntry
->pNext
;
363 static int ImplIsPaletteEntry( BYTE nRed
, BYTE nGreen
, BYTE nBlue
)
366 if ( !(nRed
% DITHER_PAL_DELTA
) && !(nGreen
% DITHER_PAL_DELTA
) && !(nBlue
% DITHER_PAL_DELTA
) )
369 PALETTEENTRY
* pPalEntry
= aImplSalSysPalEntryAry
;
371 // standard palette color?
372 for ( sal_uInt16 i
= 0; i
< DITHER_MAX_SYSCOLOR
; i
++, pPalEntry
++ )
374 if( pPalEntry
->peRed
== nRed
&& pPalEntry
->peGreen
== nGreen
&& pPalEntry
->peBlue
== nBlue
)
379 if ( aImplExtraColor1
.peRed
== nRed
&&
380 aImplExtraColor1
.peGreen
== nGreen
&&
381 aImplExtraColor1
.peBlue
== nBlue
)
389 static void ImplInsertSysColorEntry( int nSysIndex
)
391 const DWORD nRGB
= GetSysColor( nSysIndex
);
393 if ( !ImplIsPaletteEntry( GetRValue( nRGB
), GetGValue( nRGB
), GetBValue( nRGB
) ) )
395 if ( !pFirstSysColor
)
397 pActSysColor
= pFirstSysColor
= new SysColorEntry
;
398 pFirstSysColor
->nRGB
= nRGB
;
399 pFirstSysColor
->pNext
= nullptr;
403 pActSysColor
= pActSysColor
->pNext
= new SysColorEntry
;
404 pActSysColor
->nRGB
= nRGB
;
405 pActSysColor
->pNext
= nullptr;
410 void ImplUpdateSysColorEntries()
412 // delete old SysColorList
413 SysColorEntry
* pEntry
= pFirstSysColor
;
416 SysColorEntry
* pTmp
= pEntry
->pNext
;
420 pActSysColor
= pFirstSysColor
= nullptr;
422 // create new sys color list
423 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER
);
424 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER
);
425 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION
);
426 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION
);
427 ImplInsertSysColorEntry( COLOR_3DFACE
);
428 ImplInsertSysColorEntry( COLOR_3DHILIGHT
);
429 ImplInsertSysColorEntry( COLOR_3DLIGHT
);
430 ImplInsertSysColorEntry( COLOR_3DSHADOW
);
431 ImplInsertSysColorEntry( COLOR_3DDKSHADOW
);
432 ImplInsertSysColorEntry( COLOR_INFOBK
);
433 ImplInsertSysColorEntry( COLOR_INFOTEXT
);
434 ImplInsertSysColorEntry( COLOR_BTNTEXT
);
435 ImplInsertSysColorEntry( COLOR_WINDOW
);
436 ImplInsertSysColorEntry( COLOR_WINDOWTEXT
);
437 ImplInsertSysColorEntry( COLOR_HIGHLIGHT
);
438 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT
);
439 ImplInsertSysColorEntry( COLOR_MENU
);
440 ImplInsertSysColorEntry( COLOR_MENUTEXT
);
441 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION
);
442 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT
);
443 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION
);
444 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT
);
447 void WinSalGraphics::InitGraphics()
449 // calculate the minimal line width for the printer
452 int nDPIX
= GetDeviceCaps( getHDC(), LOGPIXELSX
);
456 mnPenWidth
= nDPIX
/300;
459 ::SetTextAlign( getHDC(), TA_BASELINE
| TA_LEFT
| TA_NOUPDATECP
);
460 ::SetBkMode( getHDC(), TRANSPARENT
);
461 ::SetROP2( getHDC(), R2_COPYPEN
);
466 void WinSalGraphics::DeInitGraphics()
469 SelectClipRgn( getHDC(), nullptr );
470 // select default objects
472 SelectPen( getHDC(), mhDefPen
);
474 SelectBrush( getHDC(), mhDefBrush
);
476 SelectFont( getHDC(), mhDefFont
);
481 HDC
ImplGetCachedDC( sal_uLong nID
, HBITMAP hBmp
)
483 SalData
* pSalData
= GetSalData();
484 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
488 HDC hDC
= GetDC( nullptr );
490 // create new DC with DefaultBitmap
491 pC
->mhDC
= CreateCompatibleDC( hDC
);
493 if( pSalData
->mhDitherPal
)
495 pC
->mhDefPal
= SelectPalette( pC
->mhDC
, pSalData
->mhDitherPal
, TRUE
);
496 RealizePalette( pC
->mhDC
);
499 pC
->mhSelBmp
= CreateCompatibleBitmap( hDC
, CACHED_HDC_DEFEXT
, CACHED_HDC_DEFEXT
);
500 pC
->mhDefBmp
= static_cast<HBITMAP
>(SelectObject( pC
->mhDC
, pC
->mhSelBmp
));
502 ReleaseDC( nullptr, hDC
);
506 SelectObject( pC
->mhDC
, pC
->mhActBmp
= hBmp
);
508 pC
->mhActBmp
= nullptr;
513 void ImplReleaseCachedDC( sal_uLong nID
)
515 SalData
* pSalData
= GetSalData();
516 HDCCache
* pC
= &pSalData
->mpHDCCache
[ nID
];
519 SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
522 void ImplClearHDCCache( SalData
* pData
)
524 for( sal_uLong i
= 0; i
< CACHESIZE_HDC
; i
++ )
526 HDCCache
* pC
= &pData
->mpHDCCache
[ i
];
530 SelectObject( pC
->mhDC
, pC
->mhDefBmp
);
533 SelectPalette( pC
->mhDC
, pC
->mhDefPal
, TRUE
);
535 DeleteDC( pC
->mhDC
);
536 DeleteObject( pC
->mhSelBmp
);
541 OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics
&rGraphics
, int x
, int y
, int width
, int height
)
544 , maRects(0, 0, width
, height
, x
, y
, width
, height
)
546 WinSalGraphics
& rWinGraphics
= static_cast<WinSalGraphics
&>(rGraphics
);
547 mpImpl
= dynamic_cast<WinOpenGLSalGraphicsImpl
*>(rWinGraphics
.mpImpl
.get());
551 // we avoid the OpenGL drawing, instead we draw directly to the DC
552 mhCompatibleDC
= rWinGraphics
.getHDC();
556 mhCompatibleDC
= CreateCompatibleDC(rWinGraphics
.getHDC());
558 // move the origin so that we always paint at 0,0 - to keep the bitmap
560 OffsetViewportOrgEx(mhCompatibleDC
, -x
, -y
, nullptr);
562 mhBitmap
= WinSalVirtualDevice::ImplCreateVirDevBitmap(mhCompatibleDC
, width
, height
, 32, reinterpret_cast<void **>(&mpData
));
564 mhOrigBitmap
= static_cast<HBITMAP
>(SelectObject(mhCompatibleDC
, mhBitmap
));
567 OpenGLCompatibleDC::~OpenGLCompatibleDC()
571 SelectObject(mhCompatibleDC
, mhOrigBitmap
);
572 DeleteObject(mhBitmap
);
573 DeleteDC(mhCompatibleDC
);
577 void OpenGLCompatibleDC::fill(sal_uInt32 color
)
582 sal_uInt32
*p
= mpData
;
583 for (int i
= maRects
.mnSrcWidth
* maRects
.mnSrcHeight
; i
> 0; --i
)
587 OpenGLTexture
* OpenGLCompatibleDC::getTexture()
592 // turn what's in the mpData into a texture
593 return new OpenGLTexture(maRects
.mnSrcWidth
, maRects
.mnSrcHeight
, GL_BGRA
, GL_UNSIGNED_BYTE
, mpData
);
596 bool OpenGLCompatibleDC::copyToTexture(OpenGLTexture
& aTexture
)
601 return aTexture
.CopyData(maRects
.mnSrcWidth
, maRects
.mnSrcHeight
, GL_BGRA
, GL_UNSIGNED_BYTE
, reinterpret_cast<sal_uInt8
*>(mpData
));
604 WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType
, bool bScreen
, HWND hWnd
, SalGeometryProvider
*pProvider
):
606 mbPrinter(eType
== WinSalGraphics::PRINTER
),
607 mbVirDev(eType
== WinSalGraphics::VIRTUAL_DEVICE
),
608 mbWindow(eType
== WinSalGraphics::WINDOW
),
611 mfCurrentFontScale(1.0),
617 mpStdClipRgnData(nullptr),
618 mbFontKernInit(false),
619 mpFontKernPairs(nullptr),
620 mnFontKernPairCount(0),
621 mnPenWidth(GSL_PEN_WIDTH
)
623 if (OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter
)
624 mpImpl
.reset(new WinOpenGLSalGraphicsImpl(*this, pProvider
));
626 mpImpl
.reset(new WinSalGraphicsImpl(*this));
628 for( int i
= 0; i
< MAX_FALLBACK
; ++i
)
630 mhFonts
[ i
] = nullptr;
631 mpWinFontData
[ i
] = nullptr;
632 mpWinFontEntry
[ i
] = nullptr;
633 mfFontScale
[ i
] = 1.0;
637 WinSalGraphics::~WinSalGraphics()
639 // free obsolete GDI objects
644 DeleteRegion( mhRegion
);
649 delete [] reinterpret_cast<BYTE
*>(mpStdClipRgnData
);
651 delete [] mpFontKernPairs
;
654 SalGraphicsImpl
* WinSalGraphics::GetImpl() const
659 bool WinSalGraphics::isPrinter() const
664 bool WinSalGraphics::isVirtualDevice() const
669 bool WinSalGraphics::isWindow() const
674 bool WinSalGraphics::isScreen() const
679 HWND
WinSalGraphics::gethWnd()
684 void WinSalGraphics::setHWND(HWND hWnd
)
689 HPALETTE
WinSalGraphics::getDefPal() const
694 void WinSalGraphics::setDefPal(HPALETTE hDefPal
)
699 HRGN
WinSalGraphics::getRegion() const
704 void WinSalGraphics::GetResolution( sal_Int32
& rDPIX
, sal_Int32
& rDPIY
)
706 rDPIX
= GetDeviceCaps( getHDC(), LOGPIXELSX
);
707 rDPIY
= GetDeviceCaps( getHDC(), LOGPIXELSY
);
709 // #111139# this fixes the symptom of div by zero on startup
710 // however, printing will fail most likely as communication with
711 // the printer seems not to work in this case
712 if( !rDPIX
|| !rDPIY
)
716 sal_uInt16
WinSalGraphics::GetBitCount() const
718 return mpImpl
->GetBitCount();
721 long WinSalGraphics::GetGraphicsWidth() const
723 return mpImpl
->GetGraphicsWidth();
726 void WinSalGraphics::ResetClipRegion()
728 mpImpl
->ResetClipRegion();
731 bool WinSalGraphics::setClipRegion( const vcl::Region
& i_rClip
)
733 return mpImpl
->setClipRegion( i_rClip
);
736 void WinSalGraphics::SetLineColor()
738 mpImpl
->SetLineColor();
741 void WinSalGraphics::SetLineColor( SalColor nSalColor
)
743 mpImpl
->SetLineColor( nSalColor
);
746 void WinSalGraphics::SetFillColor()
748 mpImpl
->SetFillColor();
751 void WinSalGraphics::SetFillColor( SalColor nSalColor
)
753 mpImpl
->SetFillColor( nSalColor
);
756 void WinSalGraphics::SetXORMode( bool bSet
)
758 mpImpl
->SetXORMode( bSet
);
761 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
763 mpImpl
->SetROPLineColor( nROPColor
);
766 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
768 mpImpl
->SetROPFillColor( nROPColor
);
771 void WinSalGraphics::drawPixel( long nX
, long nY
)
773 mpImpl
->drawPixel( nX
, nY
);
776 void WinSalGraphics::drawPixel( long nX
, long nY
, SalColor nSalColor
)
778 mpImpl
->drawPixel( nX
, nY
, nSalColor
);
781 void WinSalGraphics::drawLine( long nX1
, long nY1
, long nX2
, long nY2
)
783 mpImpl
->drawLine( nX1
, nY1
, nX2
, nY2
);
786 void WinSalGraphics::drawRect( long nX
, long nY
, long nWidth
, long nHeight
)
788 mpImpl
->drawRect( nX
, nY
, nWidth
, nHeight
);
791 void WinSalGraphics::drawPolyLine( sal_uInt32 nPoints
, SalPoint
* pPtAry
)
793 mpImpl
->drawPolyLine( nPoints
, pPtAry
);
796 void WinSalGraphics::drawPolygon( sal_uInt32 nPoints
, const SalPoint
* pPtAry
)
798 mpImpl
->drawPolygon( nPoints
, pPtAry
);
801 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
802 PCONSTSALPOINT
* pPtAry
)
804 mpImpl
->drawPolyPolygon( nPoly
, pPoints
, pPtAry
);
807 bool WinSalGraphics::drawPolyLineBezier( sal_uInt32 nPoints
, const SalPoint
* pPtAry
, const PolyFlags
* pFlgAry
)
809 return mpImpl
->drawPolyLineBezier( nPoints
, pPtAry
, pFlgAry
);
812 bool WinSalGraphics::drawPolygonBezier( sal_uInt32 nPoints
, const SalPoint
* pPtAry
, const PolyFlags
* pFlgAry
)
814 return mpImpl
->drawPolygonBezier( nPoints
, pPtAry
, pFlgAry
);
817 bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
818 const SalPoint
* const* pPtAry
, const PolyFlags
* const* pFlgAry
)
820 return mpImpl
->drawPolyPolygonBezier( nPoly
, pPoints
, pPtAry
, pFlgAry
);
823 static BYTE
* ImplSearchEntry( BYTE
* pSource
, BYTE
const * pDest
, sal_uLong nComp
, sal_uLong nSize
)
825 while ( nComp
-- >= nSize
)
828 for ( i
= 0; i
< nSize
; i
++ )
830 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
840 static bool ImplGetBoundingBox( double* nNumb
, BYTE
* pSource
, sal_uLong nSize
)
842 bool bRetValue
= FALSE
;
843 BYTE
* pDest
= ImplSearchEntry( pSource
, reinterpret_cast<BYTE
const *>("%%BoundingBox:"), nSize
, 14 );
846 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
849 int nSizeLeft
= nSize
- ( pDest
- pSource
);
850 if ( nSizeLeft
> 100 )
851 nSizeLeft
= 100; // only 100 bytes following the bounding box will be checked
854 for ( i
= 0; ( i
< 4 ) && nSizeLeft
; i
++ )
857 bool bDivision
= FALSE
;
858 bool bNegative
= FALSE
;
861 while ( ( --nSizeLeft
) && ( ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) ) pDest
++;
863 while ( nSizeLeft
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
877 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
878 nSizeLeft
= 1; // error parsing the bounding box values
884 nNumb
[i
] += nByte
- '0';
892 nNumb
[i
] = -nNumb
[i
];
893 if ( bDivision
&& ( nDivision
!= 1 ) )
894 nNumb
[i
] /= nDivision
;
902 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
904 bool WinSalGraphics::drawEPS( long nX
, long nY
, long nWidth
, long nHeight
, void* pPtr
, sal_uLong nSize
)
906 bool bRetValue
= false;
910 int nEscape
= POSTSCRIPT_PASSTHROUGH
;
912 if ( Escape( getHDC(), QUERYESCSUPPORT
, sizeof( int ), reinterpret_cast<LPSTR
>(&nEscape
), nullptr ) )
914 double nBoundingBox
[4];
916 if ( ImplGetBoundingBox( nBoundingBox
, static_cast<BYTE
*>(pPtr
), nSize
) )
918 OStringBuffer
aBuf( POSTSCRIPT_BUFSIZE
);
920 // reserve place for a sal_uInt16
923 // #107797# Write out EPS encapsulation header
925 // directly taken from the PLRM 3.0, p. 726. Note:
926 // this will definitely cause problems when
927 // recursively creating and embedding PostScript files
928 // in OOo, since we use statically-named variables
929 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
930 // op_count_salWin). Currently, I have no idea on how to
931 // work around that, except from scanning and
932 // interpreting the EPS for unused identifiers.
934 // append the real text
935 aBuf
.append( "\n\n/b4_Inc_state_salWin save def\n"
936 "/dict_count_salWin countdictstack def\n"
937 "/op_count_salWin count 1 sub def\n"
940 "0 setgray 0 setlinecap\n"
941 "1 setlinewidth 0 setlinejoin\n"
942 "10 setmiterlimit [] 0 setdash newpath\n"
943 "/languagelevel where\n"
945 " pop languagelevel\n"
948 " false setstrokeadjust false setoverprint\n"
952 // #i10737# Apply clipping manually
954 // Windows seems to ignore any clipping at the HDC,
955 // when followed by a POSTSCRIPT_PASSTHROUGH
957 // Check whether we've got a clipping, consisting of
958 // exactly one rect (other cases should be, but aren't
959 // handled currently)
961 // TODO: Handle more than one rectangle here (take
962 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
964 if ( mhRegion
!= nullptr &&
965 mpStdClipRgnData
!= nullptr &&
966 mpClipRgnData
== mpStdClipRgnData
&&
967 mpClipRgnData
->rdh
.nCount
== 1 )
969 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
971 aBuf
.append( "\nnewpath\n" );
972 aBuf
.append( pRect
->left
);
974 aBuf
.append( pRect
->top
);
975 aBuf
.append( " moveto\n" );
976 aBuf
.append( pRect
->right
);
978 aBuf
.append( pRect
->top
);
979 aBuf
.append( " lineto\n" );
980 aBuf
.append( pRect
->right
);
982 aBuf
.append( pRect
->bottom
);
983 aBuf
.append( " lineto\n" );
984 aBuf
.append( pRect
->left
);
986 aBuf
.append( pRect
->bottom
);
987 aBuf
.append( " lineto\n"
993 // #107797# Write out buffer
995 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = (sal_uInt16
)( aBuf
.getLength() - 2 );
996 Escape ( getHDC(), nEscape
, aBuf
.getLength(), aBuf
.getStr(), nullptr );
998 // #107797# Write out EPS transformation code
1000 double dM11
= nWidth
/ ( nBoundingBox
[2] - nBoundingBox
[0] );
1001 double dM22
= nHeight
/ (nBoundingBox
[1] - nBoundingBox
[3] );
1002 // reserve a sal_uInt16 again
1003 aBuf
.setLength( 2 );
1004 aBuf
.append( "\n\n[" );
1005 aBuf
.append( dM11
);
1006 aBuf
.append( " 0 0 " );
1007 aBuf
.append( dM22
);
1009 aBuf
.append( nX
- ( dM11
* nBoundingBox
[0] ) );
1011 aBuf
.append( nY
- ( dM22
* nBoundingBox
[3] ) );
1012 aBuf
.append( "] concat\n"
1013 "%%BeginDocument:\n" );
1014 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1015 Escape ( getHDC(), nEscape
, aBuf
.getLength(), aBuf
.getStr(), nullptr );
1017 // #107797# Write out actual EPS content
1019 sal_uLong nToDo
= nSize
;
1024 if ( nToDo
> POSTSCRIPT_BUFSIZE
- 2 )
1025 nDoNow
= POSTSCRIPT_BUFSIZE
- 2;
1026 // the following is based on the string buffer allocation
1027 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1028 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = (sal_uInt16
)nDoNow
;
1029 memcpy( const_cast<char *>(aBuf
.getStr() + 2), static_cast<BYTE
*>(pPtr
) + nSize
- nToDo
, nDoNow
);
1030 sal_uLong nResult
= Escape ( getHDC(), nEscape
, nDoNow
+ 2, aBuf
.getStr(), nullptr );
1036 // #107797# Write out EPS encapsulation footer
1038 // reserve a sal_uInt16 again
1039 aBuf
.setLength( 2 );
1040 aBuf
.append( "%%EndDocument\n"
1041 "count op_count_salWin sub {pop} repeat\n"
1042 "countdictstack dict_count_salWin sub {end} repeat\n"
1043 "b4_Inc_state_salWin restore\n\n" );
1044 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = (sal_uInt16
)( aBuf
.getLength() - 2 );
1045 Escape ( getHDC(), nEscape
, aBuf
.getLength(), aBuf
.getStr(), nullptr );
1054 SystemGraphicsData
WinSalGraphics::GetGraphicsData() const
1056 SystemGraphicsData aRes
;
1057 aRes
.nSize
= sizeof(aRes
);
1058 aRes
.hDC
= getHDC();
1062 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */