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/poly.hxx>
24 #include <basegfx/polygon/b2dpolygon.hxx>
25 #include <basegfx/polygon/b2dpolygontools.hxx>
26 #include <basegfx/polygon/b2dpolypolygontools.hxx>
27 #include <comphelper/windowserrorstring.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 <win/winlayout.hxx>
34 #include <basegfx/matrix/b2dhommatrixtools.hxx>
36 #include <salgdiimpl.hxx>
37 #include "gdiimpl.hxx"
39 #include <config_features.h>
40 #include <vcl/skia/SkiaHelper.hxx>
42 #include <skia/win/gdiimpl.hxx>
46 #define DITHER_PAL_DELTA 51
47 #define DITHER_PAL_STEPS 6
48 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS)
49 #define DITHER_MAX_SYSCOLOR 16
50 #define DITHER_EXTRA_COLORS 1
61 SysColorEntry
* pFirstSysColor
= nullptr;
62 SysColorEntry
* pActSysColor
= nullptr;
64 void DeleteSysColorList()
66 SysColorEntry
* pEntry
= pFirstSysColor
;
67 pActSysColor
= pFirstSysColor
= nullptr;
71 SysColorEntry
* pTmp
= pEntry
->pNext
;
80 static PALETTEENTRY aImplExtraColor1
=
85 static PALETTEENTRY aImplSalSysPalEntryAry
[ DITHER_MAX_SYSCOLOR
] =
94 { 0x80, 0x80, 0x80, 0 },
95 { 0xC0, 0xC0, 0xC0, 0 },
100 { 0xFF, 0, 0xFF, 0 },
101 { 0xFF, 0xFF, 0, 0 },
102 { 0xFF, 0xFF, 0xFF, 0 }
105 // we must create pens with 1-pixel width; otherwise the S3-graphics card
106 // map has many paint problems when drawing polygons/polyLines and a
108 #define GSL_PEN_WIDTH 1
110 void ImplInitSalGDI()
112 SalData
* pSalData
= GetSalData();
114 pSalData
->mbResourcesAlreadyFreed
= false;
116 // init stock brushes
117 pSalData
->maStockPenColorAry
[0] = PALETTERGB( 0, 0, 0 );
118 pSalData
->maStockPenColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
119 pSalData
->maStockPenColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
120 pSalData
->maStockPenColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
121 pSalData
->mhStockPenAry
[0] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[0] );
122 pSalData
->mhStockPenAry
[1] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[1] );
123 pSalData
->mhStockPenAry
[2] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[2] );
124 pSalData
->mhStockPenAry
[3] = CreatePen( PS_SOLID
, GSL_PEN_WIDTH
, pSalData
->maStockPenColorAry
[3] );
125 pSalData
->mnStockPenCount
= 4;
127 pSalData
->maStockBrushColorAry
[0] = PALETTERGB( 0, 0, 0 );
128 pSalData
->maStockBrushColorAry
[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
129 pSalData
->maStockBrushColorAry
[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
130 pSalData
->maStockBrushColorAry
[3] = PALETTERGB( 0x80, 0x80, 0x80 );
131 pSalData
->mhStockBrushAry
[0] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[0] );
132 pSalData
->mhStockBrushAry
[1] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[1] );
133 pSalData
->mhStockBrushAry
[2] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[2] );
134 pSalData
->mhStockBrushAry
[3] = CreateSolidBrush( pSalData
->maStockBrushColorAry
[3] );
135 pSalData
->mnStockBrushCount
= 4;
137 // initialize temporary font lists
138 pSalData
->mpSharedTempFontItem
= nullptr;
139 pSalData
->mpOtherTempFontItem
= nullptr;
141 // support palettes for 256 color displays
142 HDC hDC
= GetDC( nullptr );
143 int nBitsPixel
= GetDeviceCaps( hDC
, BITSPIXEL
);
144 int nPlanes
= GetDeviceCaps( hDC
, PLANES
);
145 int nRasterCaps
= GetDeviceCaps( hDC
, RASTERCAPS
);
146 int nBitCount
= nBitsPixel
* nPlanes
;
148 if ( (nBitCount
> 8) && (nBitCount
< 24) )
150 // test if we have to dither
151 HDC hMemDC
= ::CreateCompatibleDC( hDC
);
152 HBITMAP hMemBmp
= ::CreateCompatibleBitmap( hDC
, 8, 8 );
153 HBITMAP hBmpOld
= static_cast<HBITMAP
>(::SelectObject( hMemDC
, hMemBmp
));
154 HBRUSH hMemBrush
= ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) );
155 HBRUSH hBrushOld
= static_cast<HBRUSH
>(::SelectObject( hMemDC
, hMemBrush
));
156 bool bDither16
= true;
158 ::PatBlt( hMemDC
, 0, 0, 8, 8, PATCOPY
);
159 const COLORREF
aCol( ::GetPixel( hMemDC
, 0, 0 ) );
161 for( int nY
= 0; ( nY
< 8 ) && bDither16
; nY
++ )
162 for( int nX
= 0; ( nX
< 8 ) && bDither16
; nX
++ )
163 if( ::GetPixel( hMemDC
, nX
, nY
) != aCol
)
166 ::SelectObject( hMemDC
, hBrushOld
);
167 ::DeleteObject( hMemBrush
);
168 ::SelectObject( hMemDC
, hBmpOld
);
169 ::DeleteObject( hMemBmp
);
170 ::DeleteDC( hMemDC
);
174 // create DIBPattern for 16Bit dithering
177 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, sizeof( BITMAPINFOHEADER
) + 192 );
178 pSalData
->mpDitherDIB
= static_cast<BYTE
*>(GlobalLock( pSalData
->mhDitherDIB
));
179 pSalData
->mpDitherDiff
.reset(new tools::Long
[ 256 ]);
180 pSalData
->mpDitherLow
.reset(new BYTE
[ 256 ]);
181 pSalData
->mpDitherHigh
.reset(new BYTE
[ 256 ]);
182 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
);
183 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
185 BITMAPINFOHEADER
* pBIH
= reinterpret_cast<BITMAPINFOHEADER
*>(pSalData
->mpDitherDIB
);
187 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
191 pBIH
->biBitCount
= 24;
193 for( n
= 0; n
< 256; n
++ )
194 pSalData
->mpDitherDiff
[ n
] = n
- ( n
& 248L );
196 for( n
= 0; n
< 256; n
++ )
197 pSalData
->mpDitherLow
[ n
] = static_cast<BYTE
>( n
& 248 );
199 for( n
= 0; n
< 256; n
++ )
200 pSalData
->mpDitherHigh
[ n
] = static_cast<BYTE
>(std::min( pSalData
->mpDitherLow
[ n
] + 8, 255 ));
203 else if ( (nRasterCaps
& RC_PALETTE
) && (nBitCount
== 8) )
205 BYTE nRed
, nGreen
, nBlue
;
207 PALETTEENTRY
* pPalEntry
;
209 const sal_uInt16 nDitherPalCount
= DITHER_PAL_COUNT
;
210 sal_uLong nTotalCount
= DITHER_MAX_SYSCOLOR
+ nDitherPalCount
+ DITHER_EXTRA_COLORS
;
212 // create logical palette
213 pLogPal
= reinterpret_cast<LOGPALETTE
*>(new char[ sizeof( LOGPALETTE
) + ( nTotalCount
* sizeof( PALETTEENTRY
) ) ]);
214 pLogPal
->palVersion
= 0x0300;
215 pLogPal
->palNumEntries
= static_cast<sal_uInt16
>(nTotalCount
);
216 pPalEntry
= pLogPal
->palPalEntry
;
219 memcpy( pPalEntry
, aImplSalSysPalEntryAry
, DITHER_MAX_SYSCOLOR
* sizeof( PALETTEENTRY
) );
220 pPalEntry
+= DITHER_MAX_SYSCOLOR
;
222 // own palette (6/6/6)
223 for( nB
=0, nBlue
=0; nB
< DITHER_PAL_STEPS
; nB
++, nBlue
+= DITHER_PAL_DELTA
)
225 for( nG
=0, nGreen
=0; nG
< DITHER_PAL_STEPS
; nG
++, nGreen
+= DITHER_PAL_DELTA
)
227 for( nR
=0, nRed
=0; nR
< DITHER_PAL_STEPS
; nR
++, nRed
+= DITHER_PAL_DELTA
)
229 pPalEntry
->peRed
= nRed
;
230 pPalEntry
->peGreen
= nGreen
;
231 pPalEntry
->peBlue
= nBlue
;
232 pPalEntry
->peFlags
= 0;
238 // insert special 'Blue' as standard drawing color
239 *pPalEntry
++ = aImplExtraColor1
;
242 pSalData
->mhDitherPal
= CreatePalette( pLogPal
);
243 delete[] reinterpret_cast<char*>(pLogPal
);
245 if( pSalData
->mhDitherPal
)
247 // create DIBPattern for 8Bit dithering
248 tools::Long
const nSize
= sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) ) + 64;
251 pSalData
->mhDitherDIB
= GlobalAlloc( GMEM_FIXED
, nSize
);
252 pSalData
->mpDitherDIB
= static_cast<BYTE
*>(GlobalLock( pSalData
->mhDitherDIB
));
253 pSalData
->mpDitherDiff
.reset(new tools::Long
[ 256 ]);
254 pSalData
->mpDitherLow
.reset(new BYTE
[ 256 ]);
255 pSalData
->mpDitherHigh
.reset(new BYTE
[ 256 ]);
256 pSalData
->mpDitherDIBData
= pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) + ( 256 * sizeof( short ) );
257 memset( pSalData
->mpDitherDIB
, 0, sizeof( BITMAPINFOHEADER
) );
259 BITMAPINFOHEADER
* pBIH
= reinterpret_cast<BITMAPINFOHEADER
*>(pSalData
->mpDitherDIB
);
260 short* pColors
= reinterpret_cast<short*>( pSalData
->mpDitherDIB
+ sizeof( BITMAPINFOHEADER
) );
262 pBIH
->biSize
= sizeof( BITMAPINFOHEADER
);
266 pBIH
->biBitCount
= 8;
268 for( n
= 0; n
< nDitherPalCount
; n
++ )
269 pColors
[ n
] = static_cast<short>( n
+ DITHER_MAX_SYSCOLOR
);
271 for( n
= 0; n
< 256; n
++ )
272 pSalData
->mpDitherDiff
[ n
] = n
% 51;
274 for( n
= 0; n
< 256; n
++ )
275 pSalData
->mpDitherLow
[ n
] = static_cast<BYTE
>( n
/ 51 );
277 for( n
= 0; n
< 256; n
++ )
278 pSalData
->mpDitherHigh
[ n
] = static_cast<BYTE
>(std::min( pSalData
->mpDitherLow
[ n
] + 1, 5 ));
281 // get system color entries
282 ImplUpdateSysColorEntries();
285 ReleaseDC( nullptr, hDC
);
288 void ImplFreeSalGDI()
290 SalData
* pSalData
= GetSalData();
292 if (pSalData
->mbResourcesAlreadyFreed
)
295 // destroy stock objects
297 for ( i
= 0; i
< pSalData
->mnStockPenCount
; i
++ )
298 DeletePen( pSalData
->mhStockPenAry
[i
] );
299 for ( i
= 0; i
< pSalData
->mnStockBrushCount
; i
++ )
300 DeleteBrush( pSalData
->mhStockBrushAry
[i
] );
303 if ( pSalData
->mh50Brush
)
305 DeleteBrush( pSalData
->mh50Brush
);
306 pSalData
->mh50Brush
= nullptr;
310 if ( pSalData
->mh50Bmp
)
312 DeleteBitmap( pSalData
->mh50Bmp
);
313 pSalData
->mh50Bmp
= nullptr;
316 ImplClearHDCCache( pSalData
);
318 // delete Ditherpalette, if existing
319 if ( pSalData
->mhDitherPal
)
321 DeleteObject( pSalData
->mhDitherPal
);
322 pSalData
->mhDitherPal
= nullptr;
325 // delete buffers for dithering DIB patterns, if necessary
326 if ( pSalData
->mhDitherDIB
)
328 GlobalUnlock( pSalData
->mhDitherDIB
);
329 GlobalFree( pSalData
->mhDitherDIB
);
330 pSalData
->mhDitherDIB
= nullptr;
331 pSalData
->mpDitherDiff
.reset();
332 pSalData
->mpDitherLow
.reset();
333 pSalData
->mpDitherHigh
.reset();
336 DeleteSysColorList();
339 SalIcon
* pIcon
= pSalData
->mpFirstIcon
;
340 pSalData
->mpFirstIcon
= nullptr;
343 SalIcon
* pTmp
= pIcon
->pNext
;
344 DestroyIcon( pIcon
->hIcon
);
345 DestroyIcon( pIcon
->hSmallIcon
);
350 // delete temporary font list
351 ImplReleaseTempFonts(*pSalData
, true);
353 pSalData
->mbResourcesAlreadyFreed
= true;
356 int ImplIsSysColorEntry( Color nColor
)
358 SysColorEntry
* pEntry
= pFirstSysColor
;
359 const DWORD nTestRGB
= static_cast<DWORD
>(RGB( nColor
.GetRed(),
365 if ( pEntry
->nRGB
== nTestRGB
)
367 pEntry
= pEntry
->pNext
;
373 static int ImplIsPaletteEntry( BYTE nRed
, BYTE nGreen
, BYTE nBlue
)
376 if ( !(nRed
% DITHER_PAL_DELTA
) && !(nGreen
% DITHER_PAL_DELTA
) && !(nBlue
% DITHER_PAL_DELTA
) )
379 PALETTEENTRY
* pPalEntry
= aImplSalSysPalEntryAry
;
381 // standard palette color?
382 for ( sal_uInt16 i
= 0; i
< DITHER_MAX_SYSCOLOR
; i
++, pPalEntry
++ )
384 if( pPalEntry
->peRed
== nRed
&& pPalEntry
->peGreen
== nGreen
&& pPalEntry
->peBlue
== nBlue
)
389 if ( aImplExtraColor1
.peRed
== nRed
&&
390 aImplExtraColor1
.peGreen
== nGreen
&&
391 aImplExtraColor1
.peBlue
== nBlue
)
399 static void ImplInsertSysColorEntry( int nSysIndex
)
401 const DWORD nRGB
= GetSysColor( nSysIndex
);
403 if ( !ImplIsPaletteEntry( GetRValue( nRGB
), GetGValue( nRGB
), GetBValue( nRGB
) ) )
405 if ( !pFirstSysColor
)
407 pActSysColor
= pFirstSysColor
= new SysColorEntry
;
408 pFirstSysColor
->nRGB
= nRGB
;
409 pFirstSysColor
->pNext
= nullptr;
413 pActSysColor
= pActSysColor
->pNext
= new SysColorEntry
;
414 pActSysColor
->nRGB
= nRGB
;
415 pActSysColor
->pNext
= nullptr;
420 void ImplUpdateSysColorEntries()
422 DeleteSysColorList();
424 // create new sys color list
425 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER
);
426 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER
);
427 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION
);
428 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION
);
429 ImplInsertSysColorEntry( COLOR_3DFACE
);
430 ImplInsertSysColorEntry( COLOR_3DHILIGHT
);
431 ImplInsertSysColorEntry( COLOR_3DLIGHT
);
432 ImplInsertSysColorEntry( COLOR_3DSHADOW
);
433 ImplInsertSysColorEntry( COLOR_3DDKSHADOW
);
434 ImplInsertSysColorEntry( COLOR_INFOBK
);
435 ImplInsertSysColorEntry( COLOR_INFOTEXT
);
436 ImplInsertSysColorEntry( COLOR_BTNTEXT
);
437 ImplInsertSysColorEntry( COLOR_WINDOW
);
438 ImplInsertSysColorEntry( COLOR_WINDOWTEXT
);
439 ImplInsertSysColorEntry( COLOR_HIGHLIGHT
);
440 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT
);
441 ImplInsertSysColorEntry( COLOR_MENU
);
442 ImplInsertSysColorEntry( COLOR_MENUTEXT
);
443 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION
);
444 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT
);
445 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION
);
446 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT
);
449 void WinSalGraphics::InitGraphics()
454 // calculate the minimal line width for the printer
457 int nDPIX
= GetDeviceCaps( getHDC(), LOGPIXELSX
);
461 mnPenWidth
= nDPIX
/300;
464 ::SetTextAlign( getHDC(), TA_BASELINE
| TA_LEFT
| TA_NOUPDATECP
);
465 ::SetBkMode( getHDC(), TRANSPARENT
);
466 ::SetROP2( getHDC(), R2_COPYPEN
);
469 void WinSalGraphics::DeInitGraphics()
475 SelectClipRgn( getHDC(), nullptr );
476 // select default objects
479 SelectPen( getHDC(), mhDefPen
);
484 SelectBrush( getHDC(), mhDefBrush
);
485 mhDefBrush
= nullptr;
489 SelectFont( getHDC(), mhDefFont
);
497 void WinSalGraphics::setHDC(HDC aNew
)
504 HDC
ImplGetCachedDC( sal_uLong nID
, HBITMAP hBmp
)
506 SalData
* pSalData
= GetSalData();
507 HDCCache
* pC
= &pSalData
->maHDCCache
[ nID
];
511 HDC hDC
= GetDC( nullptr );
513 // create new DC with DefaultBitmap
514 pC
->mhDC
= CreateCompatibleDC( hDC
);
516 if( pSalData
->mhDitherPal
)
518 pC
->mhDefPal
= SelectPalette( pC
->mhDC
, pSalData
->mhDitherPal
, TRUE
);
519 RealizePalette( pC
->mhDC
);
522 pC
->mhSelBmp
= CreateCompatibleBitmap( hDC
, CACHED_HDC_DEFEXT
, CACHED_HDC_DEFEXT
);
523 pC
->mhDefBmp
= static_cast<HBITMAP
>(SelectObject( pC
->mhDC
, pC
->mhSelBmp
));
525 ReleaseDC( nullptr, hDC
);
529 SelectObject( pC
->mhDC
, pC
->mhActBmp
= hBmp
);
531 pC
->mhActBmp
= nullptr;
536 void ImplReleaseCachedDC( sal_uLong nID
)
538 SalData
* pSalData
= GetSalData();
539 HDCCache
* pC
= &pSalData
->maHDCCache
[ nID
];
542 SelectObject( pC
->mhDC
, pC
->mhSelBmp
);
545 void ImplClearHDCCache( SalData
* pData
)
547 for( sal_uLong i
= 0; i
< CACHESIZE_HDC
; i
++ )
549 HDCCache
* pC
= &pData
->maHDCCache
[ i
];
553 SelectObject( pC
->mhDC
, pC
->mhDefBmp
);
556 SelectPalette( pC
->mhDC
, pC
->mhDefPal
, TRUE
);
558 DeleteDC( pC
->mhDC
);
559 DeleteObject( pC
->mhSelBmp
);
564 std::unique_ptr
< CompatibleDC
> CompatibleDC::create(SalGraphics
&rGraphics
, int x
, int y
, int width
, int height
)
566 #if HAVE_FEATURE_SKIA
567 if (SkiaHelper::isVCLSkiaEnabled())
568 return std::make_unique
< SkiaCompatibleDC
>( rGraphics
, x
, y
, width
, height
);
570 return std::unique_ptr
< CompatibleDC
>( new CompatibleDC( rGraphics
, x
, y
, width
, height
));
573 CompatibleDC::CompatibleDC(SalGraphics
&rGraphics
, int x
, int y
, int width
, int height
, bool disable
)
576 , maRects(0, 0, width
, height
, x
, y
, width
, height
)
579 WinSalGraphics
& rWinGraphics
= static_cast<WinSalGraphics
&>(rGraphics
);
583 // we avoid the OpenGL drawing, instead we draw directly to the DC
584 mhCompatibleDC
= rWinGraphics
.getHDC();
588 mpImpl
= rWinGraphics
.getWinSalGraphicsImplBase();
589 mhCompatibleDC
= CreateCompatibleDC(rWinGraphics
.getHDC());
591 // move the origin so that we always paint at 0,0 - to keep the bitmap
593 OffsetViewportOrgEx(mhCompatibleDC
, -x
, -y
, nullptr);
595 mhBitmap
= WinSalVirtualDevice::ImplCreateVirDevBitmap(mhCompatibleDC
, width
, height
, 32, reinterpret_cast<void **>(&mpData
));
597 mhOrigBitmap
= static_cast<HBITMAP
>(SelectObject(mhCompatibleDC
, mhBitmap
));
600 CompatibleDC::~CompatibleDC()
604 SelectObject(mhCompatibleDC
, mhOrigBitmap
);
605 DeleteObject(mhBitmap
);
606 DeleteDC(mhCompatibleDC
);
610 void CompatibleDC::fill(sal_uInt32 color
)
615 sal_uInt32
*p
= mpData
;
616 for (int i
= maRects
.mnSrcWidth
* maRects
.mnSrcHeight
; i
> 0; --i
)
620 WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType
, bool bScreen
, HWND hWnd
, [[maybe_unused
]] SalGeometryProvider
*pProvider
):
622 mbPrinter(eType
== WinSalGraphics::PRINTER
),
623 mbVirDev(eType
== WinSalGraphics::VIRTUAL_DEVICE
),
624 mbWindow(eType
== WinSalGraphics::WINDOW
),
632 mpStdClipRgnData(nullptr),
633 mnPenWidth(GSL_PEN_WIDTH
)
635 #if HAVE_FEATURE_SKIA
636 if (SkiaHelper::isVCLSkiaEnabled() && !mbPrinter
)
638 auto const impl
= new WinSkiaSalGraphicsImpl(*this, pProvider
);
640 mWinSalGraphicsImplBase
= impl
;
645 auto const impl
= new WinSalGraphicsImpl(*this);
647 mWinSalGraphicsImplBase
= impl
;
651 WinSalGraphics::~WinSalGraphics()
653 // free obsolete GDI objects
658 DeleteRegion( mhRegion
);
663 delete [] reinterpret_cast<BYTE
*>(mpStdClipRgnData
);
668 SalGraphicsImpl
* WinSalGraphics::GetImpl() const
673 bool WinSalGraphics::isPrinter() const
678 bool WinSalGraphics::isVirtualDevice() const
683 bool WinSalGraphics::isWindow() const
688 bool WinSalGraphics::isScreen() const
693 HWND
WinSalGraphics::gethWnd()
698 void WinSalGraphics::setHWND(HWND hWnd
)
703 HPALETTE
WinSalGraphics::getDefPal() const
705 assert(getHDC() || !mhDefPal
);
709 UINT
WinSalGraphics::setPalette(HPALETTE hNewPal
, BOOL bForceBkgd
)
711 UINT res
= GDI_ERROR
;
721 HPALETTE hOldPal
= SelectPalette(getHDC(), hNewPal
, bForceBkgd
);
726 res
= RealizePalette(getHDC());
734 SelectPalette(getHDC(), mhDefPal
, bForceBkgd
);
742 HRGN
WinSalGraphics::getRegion() const
747 void WinSalGraphics::GetResolution( sal_Int32
& rDPIX
, sal_Int32
& rDPIY
)
749 rDPIX
= GetDeviceCaps( getHDC(), LOGPIXELSX
);
750 rDPIY
= GetDeviceCaps( getHDC(), LOGPIXELSY
);
752 // #111139# this fixes the symptom of div by zero on startup
753 // however, printing will fail most likely as communication with
754 // the printer seems not to work in this case
755 if( !rDPIX
|| !rDPIY
)
760 IDWriteFactory
* WinSalGraphics::getDWriteFactory()
762 static sal::systools::COMReference
<IDWriteFactory
> pDWriteFactory(
765 sal::systools::COMReference
<IDWriteFactory
> pResult
;
766 HRESULT hr
= DWriteCreateFactory(DWRITE_FACTORY_TYPE_SHARED
, __uuidof(IDWriteFactory
),
767 reinterpret_cast<IUnknown
**>(&pResult
));
770 SAL_WARN("vcl.fonts", "HRESULT 0x" << OUString::number(hr
, 16) << ": "
771 << WindowsErrorStringFromHRESULT(hr
));
776 return pDWriteFactory
.get();
780 IDWriteGdiInterop
* WinSalGraphics::getDWriteGdiInterop()
782 static sal::systools::COMReference
<IDWriteGdiInterop
> pDWriteGdiInterop(
785 sal::systools::COMReference
<IDWriteGdiInterop
> pResult
;
786 HRESULT hr
= getDWriteFactory()->GetGdiInterop(&pResult
);
789 SAL_WARN("vcl.fonts", "HRESULT 0x" << OUString::number(hr
, 16) << ": "
790 << WindowsErrorStringFromHRESULT(hr
));
795 return pDWriteGdiInterop
.get();
798 sal_uInt16
WinSalGraphics::GetBitCount() const
800 return mpImpl
->GetBitCount();
803 tools::Long
WinSalGraphics::GetGraphicsWidth() const
805 return mpImpl
->GetGraphicsWidth();
808 void WinSalGraphics::Flush()
810 mWinSalGraphicsImplBase
->Flush();
813 void WinSalGraphics::ResetClipRegion()
815 mpImpl
->ResetClipRegion();
818 void WinSalGraphics::setClipRegion( const vcl::Region
& i_rClip
)
820 mpImpl
->setClipRegion( i_rClip
);
823 void WinSalGraphics::SetLineColor()
825 mpImpl
->SetLineColor();
828 void WinSalGraphics::SetLineColor( Color nColor
)
830 mpImpl
->SetLineColor( nColor
);
833 void WinSalGraphics::SetFillColor()
835 mpImpl
->SetFillColor();
838 void WinSalGraphics::SetFillColor( Color nColor
)
840 mpImpl
->SetFillColor( nColor
);
843 void WinSalGraphics::SetXORMode( bool bSet
, bool bInvertOnly
)
845 mpImpl
->SetXORMode( bSet
, bInvertOnly
);
848 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor
)
850 mpImpl
->SetROPLineColor( nROPColor
);
853 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor
)
855 mpImpl
->SetROPFillColor( nROPColor
);
858 void WinSalGraphics::drawPixel( tools::Long nX
, tools::Long nY
)
860 mpImpl
->drawPixel( nX
, nY
);
863 void WinSalGraphics::drawPixel( tools::Long nX
, tools::Long nY
, Color nColor
)
865 mpImpl
->drawPixel( nX
, nY
, nColor
);
868 void WinSalGraphics::drawLine( tools::Long nX1
, tools::Long nY1
, tools::Long nX2
, tools::Long nY2
)
870 mpImpl
->drawLine( nX1
, nY1
, nX2
, nY2
);
873 void WinSalGraphics::drawRect( tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
)
875 mpImpl
->drawRect( nX
, nY
, nWidth
, nHeight
);
878 void WinSalGraphics::drawPolyLine( sal_uInt32 nPoints
, const Point
* pPtAry
)
880 mpImpl
->drawPolyLine( nPoints
, pPtAry
);
883 void WinSalGraphics::drawPolygon( sal_uInt32 nPoints
, const Point
* pPtAry
)
885 mpImpl
->drawPolygon( nPoints
, pPtAry
);
888 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
889 const Point
** pPtAry
)
891 mpImpl
->drawPolyPolygon( nPoly
, pPoints
, pPtAry
);
894 bool WinSalGraphics::drawPolyLineBezier( sal_uInt32 nPoints
, const Point
* pPtAry
, const PolyFlags
* pFlgAry
)
896 return mpImpl
->drawPolyLineBezier( nPoints
, pPtAry
, pFlgAry
);
899 bool WinSalGraphics::drawPolygonBezier( sal_uInt32 nPoints
, const Point
* pPtAry
, const PolyFlags
* pFlgAry
)
901 return mpImpl
->drawPolygonBezier( nPoints
, pPtAry
, pFlgAry
);
904 bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly
, const sal_uInt32
* pPoints
,
905 const Point
* const* pPtAry
, const PolyFlags
* const* pFlgAry
)
907 return mpImpl
->drawPolyPolygonBezier( nPoly
, pPoints
, pPtAry
, pFlgAry
);
910 bool WinSalGraphics::drawGradient(const tools::PolyPolygon
& rPoly
, const Gradient
& rGradient
)
912 return mpImpl
->drawGradient(rPoly
, rGradient
);
915 bool WinSalGraphics::implDrawGradient(basegfx::B2DPolyPolygon
const & rPolyPolygon
, SalGradient
const & rGradient
)
917 return mpImpl
->implDrawGradient(rPolyPolygon
, rGradient
);
920 static BYTE
* ImplSearchEntry( BYTE
* pSource
, BYTE
const * pDest
, sal_uLong nComp
, sal_uLong nSize
)
922 while ( nComp
-- >= nSize
)
925 for ( i
= 0; i
< nSize
; i
++ )
927 if ( ( pSource
[i
]&~0x20 ) != ( pDest
[i
]&~0x20 ) )
937 static bool ImplGetBoundingBox( double* nNumb
, BYTE
* pSource
, sal_uLong nSize
)
939 bool bRetValue
= false;
940 BYTE
* pDest
= ImplSearchEntry( pSource
, reinterpret_cast<BYTE
const *>("%%BoundingBox:"), nSize
, 14 );
943 nNumb
[0] = nNumb
[1] = nNumb
[2] = nNumb
[3] = 0;
946 int nSizeLeft
= nSize
- ( pDest
- pSource
);
947 if ( nSizeLeft
> 100 )
948 nSizeLeft
= 100; // only 100 bytes following the bounding box will be checked
951 for ( i
= 0; ( i
< 4 ) && nSizeLeft
; i
++ )
954 bool bDivision
= false;
955 bool bNegative
= false;
958 while ( ( --nSizeLeft
) && ( ( *pDest
== ' ' ) || ( *pDest
== 0x9 ) ) ) pDest
++;
960 while ( nSizeLeft
&& ( nByte
!= ' ' ) && ( nByte
!= 0x9 ) && ( nByte
!= 0xd ) && ( nByte
!= 0xa ) )
974 if ( ( nByte
< '0' ) || ( nByte
> '9' ) )
975 nSizeLeft
= 1; // error parsing the bounding box values
981 nNumb
[i
] += nByte
- '0';
989 nNumb
[i
] = -nNumb
[i
];
990 if ( bDivision
&& ( nDivision
!= 1 ) )
991 nNumb
[i
] /= nDivision
;
999 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
1001 bool WinSalGraphics::drawEPS( tools::Long nX
, tools::Long nY
, tools::Long nWidth
, tools::Long nHeight
, void* pPtr
, sal_uInt32 nSize
)
1003 bool bRetValue
= false;
1007 int nEscape
= POSTSCRIPT_PASSTHROUGH
;
1009 if ( Escape( getHDC(), QUERYESCSUPPORT
, sizeof( int ), reinterpret_cast<LPSTR
>(&nEscape
), nullptr ) )
1011 double nBoundingBox
[4];
1013 if ( ImplGetBoundingBox( nBoundingBox
, static_cast<BYTE
*>(pPtr
), nSize
) )
1015 OStringBuffer
aBuf( POSTSCRIPT_BUFSIZE
);
1017 // reserve place for a sal_uInt16
1018 aBuf
.append( "aa" );
1020 // #107797# Write out EPS encapsulation header
1022 // directly taken from the PLRM 3.0, p. 726. Note:
1023 // this will definitely cause problems when
1024 // recursively creating and embedding PostScript files
1025 // in OOo, since we use statically-named variables
1026 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
1027 // op_count_salWin). Currently, I have no idea on how to
1028 // work around that, except from scanning and
1029 // interpreting the EPS for unused identifiers.
1031 // append the real text
1032 aBuf
.append( "\n\n/b4_Inc_state_salWin save def\n"
1033 "/dict_count_salWin countdictstack def\n"
1034 "/op_count_salWin count 1 sub def\n"
1036 "/showpage {} def\n"
1037 "0 setgray 0 setlinecap\n"
1038 "1 setlinewidth 0 setlinejoin\n"
1039 "10 setmiterlimit [] 0 setdash newpath\n"
1040 "/languagelevel where\n"
1042 " pop languagelevel\n"
1045 " false setstrokeadjust false setoverprint\n"
1049 // #i10737# Apply clipping manually
1051 // Windows seems to ignore any clipping at the HDC,
1052 // when followed by a POSTSCRIPT_PASSTHROUGH
1054 // Check whether we've got a clipping, consisting of
1055 // exactly one rect (other cases should be, but aren't
1056 // handled currently)
1058 // TODO: Handle more than one rectangle here (take
1059 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
1061 if ( mhRegion
!= nullptr &&
1062 mpStdClipRgnData
!= nullptr &&
1063 mpClipRgnData
== mpStdClipRgnData
&&
1064 mpClipRgnData
->rdh
.nCount
== 1 )
1066 RECT
* pRect
= &(mpClipRgnData
->rdh
.rcBound
);
1068 aBuf
.append( "\nnewpath\n"
1069 + OString::number(pRect
->left
) + " " + OString::number(pRect
->top
)
1071 + OString::number(pRect
->right
) + " " + OString::number(pRect
->top
)
1073 + OString::number(pRect
->right
) + " "
1074 + OString::number(pRect
->bottom
) + " lineto\n"
1075 + OString::number(pRect
->left
) + " "
1076 + OString::number(pRect
->bottom
) + " lineto\n"
1082 // #107797# Write out buffer
1084 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = static_cast<sal_uInt16
>( aBuf
.getLength() - 2 );
1085 Escape ( getHDC(), nEscape
, aBuf
.getLength(), aBuf
.getStr(), nullptr );
1087 // #107797# Write out EPS transformation code
1089 double dM11
= nWidth
/ ( nBoundingBox
[2] - nBoundingBox
[0] );
1090 double dM22
= nHeight
/ (nBoundingBox
[1] - nBoundingBox
[3] );
1091 // reserve a sal_uInt16 again
1092 aBuf
.setLength( 2 );
1093 aBuf
.append( "\n\n[" + OString::number(dM11
) + " 0 0 " + OString::number(dM22
) + " "
1094 + OString::number(nX
- ( dM11
* nBoundingBox
[0] )) + " "
1095 + OString::number(nY
- ( dM22
* nBoundingBox
[3] )) + "] concat\n"
1096 "%%BeginDocument:\n" );
1097 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = static_cast<sal_uInt16
>( aBuf
.getLength() - 2 );
1098 Escape ( getHDC(), nEscape
, aBuf
.getLength(), aBuf
.getStr(), nullptr );
1100 // #107797# Write out actual EPS content
1102 sal_uLong nToDo
= nSize
;
1107 if ( nToDo
> POSTSCRIPT_BUFSIZE
- 2 )
1108 nDoNow
= POSTSCRIPT_BUFSIZE
- 2;
1109 // the following is based on the string buffer allocation
1110 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1111 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = static_cast<sal_uInt16
>(nDoNow
);
1112 memcpy( const_cast<char *>(aBuf
.getStr() + 2), static_cast<BYTE
*>(pPtr
) + nSize
- nToDo
, nDoNow
);
1113 sal_uLong nResult
= Escape ( getHDC(), nEscape
, nDoNow
+ 2, aBuf
.getStr(), nullptr );
1119 // #107797# Write out EPS encapsulation footer
1121 // reserve a sal_uInt16 again
1122 aBuf
.setLength( 2 );
1123 aBuf
.append( "%%EndDocument\n"
1124 "count op_count_salWin sub {pop} repeat\n"
1125 "countdictstack dict_count_salWin sub {end} repeat\n"
1126 "b4_Inc_state_salWin restore\n\n" );
1127 *reinterpret_cast<sal_uInt16
*>(const_cast<char *>(aBuf
.getStr())) = static_cast<sal_uInt16
>( aBuf
.getLength() - 2 );
1128 Escape ( getHDC(), nEscape
, aBuf
.getLength(), aBuf
.getStr(), nullptr );
1137 SystemGraphicsData
WinSalGraphics::GetGraphicsData() const
1139 SystemGraphicsData aRes
;
1140 aRes
.nSize
= sizeof(aRes
);
1141 aRes
.hDC
= getHDC();
1145 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */