bump product version to 6.4.0.3
[LibreOffice.git] / vcl / win / gdi / salgdi.cxx
blob2d4a283bb81825f1703bbd88a63373a362d10d39
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 .
20 #include <string.h>
21 #include <svsys.h>
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 <win/wincomp.hxx>
28 #include <win/saldata.hxx>
29 #include <win/salgdi.h>
30 #include <win/salframe.h>
31 #include <win/salvd.h>
32 #include <win/winlayout.hxx>
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
48 namespace
51 struct SysColorEntry
53 DWORD nRGB;
54 SysColorEntry* pNext;
57 SysColorEntry* pFirstSysColor = nullptr;
58 SysColorEntry* pActSysColor = nullptr;
60 void DeleteSysColorList()
62 SysColorEntry* pEntry = pFirstSysColor;
63 pActSysColor = pFirstSysColor = nullptr;
65 while( pEntry )
67 SysColorEntry* pTmp = pEntry->pNext;
68 delete pEntry;
69 pEntry = pTmp;
73 } // namespace
75 // Blue7
76 static PALETTEENTRY aImplExtraColor1 =
78 0, 184, 255, 0
81 static PALETTEENTRY aImplSalSysPalEntryAry[ DITHER_MAX_SYSCOLOR ] =
83 { 0, 0, 0, 0 },
84 { 0, 0, 0x80, 0 },
85 { 0, 0x80, 0, 0 },
86 { 0, 0x80, 0x80, 0 },
87 { 0x80, 0, 0, 0 },
88 { 0x80, 0, 0x80, 0 },
89 { 0x80, 0x80, 0, 0 },
90 { 0x80, 0x80, 0x80, 0 },
91 { 0xC0, 0xC0, 0xC0, 0 },
92 { 0, 0, 0xFF, 0 },
93 { 0, 0xFF, 0, 0 },
94 { 0, 0xFF, 0xFF, 0 },
95 { 0xFF, 0, 0, 0 },
96 { 0xFF, 0, 0xFF, 0 },
97 { 0xFF, 0xFF, 0, 0 },
98 { 0xFF, 0xFF, 0xFF, 0 }
101 // we must create pens with 1-pixel width; otherwise the S3-graphics card
102 // map has many paint problems when drawing polygons/polyLines and a
103 // complex is set
104 #define GSL_PEN_WIDTH 1
106 void ImplInitSalGDI()
108 SalData* pSalData = GetSalData();
110 pSalData->mbResourcesAlreadyFreed = false;
112 // init stock brushes
113 pSalData->maStockPenColorAry[0] = PALETTERGB( 0, 0, 0 );
114 pSalData->maStockPenColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
115 pSalData->maStockPenColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
116 pSalData->maStockPenColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 );
117 pSalData->mhStockPenAry[0] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[0] );
118 pSalData->mhStockPenAry[1] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[1] );
119 pSalData->mhStockPenAry[2] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[2] );
120 pSalData->mhStockPenAry[3] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[3] );
121 pSalData->mnStockPenCount = 4;
123 pSalData->maStockBrushColorAry[0] = PALETTERGB( 0, 0, 0 );
124 pSalData->maStockBrushColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF );
125 pSalData->maStockBrushColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 );
126 pSalData->maStockBrushColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 );
127 pSalData->mhStockBrushAry[0] = CreateSolidBrush( pSalData->maStockBrushColorAry[0] );
128 pSalData->mhStockBrushAry[1] = CreateSolidBrush( pSalData->maStockBrushColorAry[1] );
129 pSalData->mhStockBrushAry[2] = CreateSolidBrush( pSalData->maStockBrushColorAry[2] );
130 pSalData->mhStockBrushAry[3] = CreateSolidBrush( pSalData->maStockBrushColorAry[3] );
131 pSalData->mnStockBrushCount = 4;
133 // initialize cache of device contexts
134 pSalData->mpHDCCache = new HDCCache[ CACHESIZE_HDC ];
135 memset( pSalData->mpHDCCache, 0, CACHESIZE_HDC * sizeof( HDCCache ) );
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 )
164 bDither16 = FALSE;
166 ::SelectObject( hMemDC, hBrushOld );
167 ::DeleteObject( hMemBrush );
168 ::SelectObject( hMemDC, hBmpOld );
169 ::DeleteObject( hMemBmp );
170 ::DeleteDC( hMemDC );
172 if( bDither16 )
174 // create DIBPattern for 16Bit dithering
175 long n;
177 pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, sizeof( BITMAPINFOHEADER ) + 192 );
178 pSalData->mpDitherDIB = static_cast<BYTE*>(GlobalLock( pSalData->mhDitherDIB ));
179 pSalData->mpDitherDiff = new long[ 256 ];
180 pSalData->mpDitherLow = new BYTE[ 256 ];
181 pSalData->mpDitherHigh = 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 );
188 pBIH->biWidth = 8;
189 pBIH->biHeight = 8;
190 pBIH->biPlanes = 1;
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;
206 BYTE nR, nG, nB;
207 PALETTEENTRY* pPalEntry;
208 LOGPALETTE* pLogPal;
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;
218 // Standard colors
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;
233 pPalEntry++;
238 // insert special 'Blue' as standard drawing color
239 *pPalEntry++ = aImplExtraColor1;
241 // create palette
242 pSalData->mhDitherPal = CreatePalette( pLogPal );
243 delete[] reinterpret_cast<char*>(pLogPal);
245 if( pSalData->mhDitherPal )
247 // create DIBPattern for 8Bit dithering
248 long const nSize = sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ) + 64;
249 long n;
251 pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, nSize );
252 pSalData->mpDitherDIB = static_cast<BYTE*>(GlobalLock( pSalData->mhDitherDIB ));
253 pSalData->mpDitherDiff = new long[ 256 ];
254 pSalData->mpDitherLow = new BYTE[ 256 ];
255 pSalData->mpDitherHigh = 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 );
263 pBIH->biWidth = 8;
264 pBIH->biHeight = 8;
265 pBIH->biPlanes = 1;
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)
293 return;
295 // destroy stock objects
296 int i;
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] );
302 // delete 50% Brush
303 if ( pSalData->mh50Brush )
305 DeleteBrush( pSalData->mh50Brush );
306 pSalData->mh50Brush = nullptr;
309 // delete 50% Bitmap
310 if ( pSalData->mh50Bmp )
312 DeleteBitmap( pSalData->mh50Bmp );
313 pSalData->mh50Bmp = nullptr;
316 ImplClearHDCCache( pSalData );
317 delete[] pSalData->mpHDCCache;
319 // delete Ditherpalette, if existing
320 if ( pSalData->mhDitherPal )
322 DeleteObject( pSalData->mhDitherPal );
323 pSalData->mhDitherPal = nullptr;
326 // delete buffers for dithering DIB patterns, if necessary
327 if ( pSalData->mhDitherDIB )
329 GlobalUnlock( pSalData->mhDitherDIB );
330 GlobalFree( pSalData->mhDitherDIB );
331 pSalData->mhDitherDIB = nullptr;
332 delete[] pSalData->mpDitherDiff;
333 delete[] pSalData->mpDitherLow;
334 delete[] pSalData->mpDitherHigh;
337 DeleteSysColorList();
339 // delete icon cache
340 SalIcon* pIcon = pSalData->mpFirstIcon;
341 pSalData->mpFirstIcon = nullptr;
342 while( pIcon )
344 SalIcon* pTmp = pIcon->pNext;
345 DestroyIcon( pIcon->hIcon );
346 DestroyIcon( pIcon->hSmallIcon );
347 delete pIcon;
348 pIcon = pTmp;
351 // delete temporary font list
352 ImplReleaseTempFonts(*pSalData, true);
354 pSalData->mbResourcesAlreadyFreed = true;
357 int ImplIsSysColorEntry( Color nColor )
359 SysColorEntry* pEntry = pFirstSysColor;
360 const DWORD nTestRGB = static_cast<DWORD>(RGB( nColor.GetRed(),
361 nColor.GetGreen(),
362 nColor.GetBlue() ));
364 while ( pEntry )
366 if ( pEntry->nRGB == nTestRGB )
367 return TRUE;
368 pEntry = pEntry->pNext;
371 return FALSE;
374 static int ImplIsPaletteEntry( BYTE nRed, BYTE nGreen, BYTE nBlue )
376 // dither color?
377 if ( !(nRed % DITHER_PAL_DELTA) && !(nGreen % DITHER_PAL_DELTA) && !(nBlue % DITHER_PAL_DELTA) )
378 return TRUE;
380 PALETTEENTRY* pPalEntry = aImplSalSysPalEntryAry;
382 // standard palette color?
383 for ( sal_uInt16 i = 0; i < DITHER_MAX_SYSCOLOR; i++, pPalEntry++ )
385 if( pPalEntry->peRed == nRed && pPalEntry->peGreen == nGreen && pPalEntry->peBlue == nBlue )
386 return TRUE;
389 // extra color?
390 if ( aImplExtraColor1.peRed == nRed &&
391 aImplExtraColor1.peGreen == nGreen &&
392 aImplExtraColor1.peBlue == nBlue )
394 return TRUE;
397 return FALSE;
400 static void ImplInsertSysColorEntry( int nSysIndex )
402 const DWORD nRGB = GetSysColor( nSysIndex );
404 if ( !ImplIsPaletteEntry( GetRValue( nRGB ), GetGValue( nRGB ), GetBValue( nRGB ) ) )
406 if ( !pFirstSysColor )
408 pActSysColor = pFirstSysColor = new SysColorEntry;
409 pFirstSysColor->nRGB = nRGB;
410 pFirstSysColor->pNext = nullptr;
412 else
414 pActSysColor = pActSysColor->pNext = new SysColorEntry;
415 pActSysColor->nRGB = nRGB;
416 pActSysColor->pNext = nullptr;
421 void ImplUpdateSysColorEntries()
423 DeleteSysColorList();
425 // create new sys color list
426 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER );
427 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER );
428 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION );
429 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION );
430 ImplInsertSysColorEntry( COLOR_3DFACE );
431 ImplInsertSysColorEntry( COLOR_3DHILIGHT );
432 ImplInsertSysColorEntry( COLOR_3DLIGHT );
433 ImplInsertSysColorEntry( COLOR_3DSHADOW );
434 ImplInsertSysColorEntry( COLOR_3DDKSHADOW );
435 ImplInsertSysColorEntry( COLOR_INFOBK );
436 ImplInsertSysColorEntry( COLOR_INFOTEXT );
437 ImplInsertSysColorEntry( COLOR_BTNTEXT );
438 ImplInsertSysColorEntry( COLOR_WINDOW );
439 ImplInsertSysColorEntry( COLOR_WINDOWTEXT );
440 ImplInsertSysColorEntry( COLOR_HIGHLIGHT );
441 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT );
442 ImplInsertSysColorEntry( COLOR_MENU );
443 ImplInsertSysColorEntry( COLOR_MENUTEXT );
444 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION );
445 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT );
446 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION );
447 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT );
450 void WinSalGraphics::InitGraphics()
452 // calculate the minimal line width for the printer
453 if ( isPrinter() )
455 int nDPIX = GetDeviceCaps( getHDC(), LOGPIXELSX );
456 if ( nDPIX <= 300 )
457 mnPenWidth = 0;
458 else
459 mnPenWidth = nDPIX/300;
462 ::SetTextAlign( getHDC(), TA_BASELINE | TA_LEFT | TA_NOUPDATECP );
463 ::SetBkMode( getHDC(), TRANSPARENT );
464 ::SetROP2( getHDC(), R2_COPYPEN );
466 mpImpl->Init();
469 void WinSalGraphics::DeInitGraphics()
471 // clear clip region
472 SelectClipRgn( getHDC(), nullptr );
473 // select default objects
474 if ( mhDefPen )
475 SelectPen( getHDC(), mhDefPen );
476 if ( mhDefBrush )
477 SelectBrush( getHDC(), mhDefBrush );
478 if ( mhDefFont )
479 SelectFont( getHDC(), mhDefFont );
481 mpImpl->DeInit();
484 HDC ImplGetCachedDC( sal_uLong nID, HBITMAP hBmp )
486 SalData* pSalData = GetSalData();
487 HDCCache* pC = &pSalData->mpHDCCache[ nID ];
489 if( !pC->mhDC )
491 HDC hDC = GetDC( nullptr );
493 // create new DC with DefaultBitmap
494 pC->mhDC = CreateCompatibleDC( hDC );
496 if( pSalData->mhDitherPal )
498 pC->mhDefPal = SelectPalette( pC->mhDC, pSalData->mhDitherPal, TRUE );
499 RealizePalette( pC->mhDC );
502 pC->mhSelBmp = CreateCompatibleBitmap( hDC, CACHED_HDC_DEFEXT, CACHED_HDC_DEFEXT );
503 pC->mhDefBmp = static_cast<HBITMAP>(SelectObject( pC->mhDC, pC->mhSelBmp ));
505 ReleaseDC( nullptr, hDC );
508 if ( hBmp )
509 SelectObject( pC->mhDC, pC->mhActBmp = hBmp );
510 else
511 pC->mhActBmp = nullptr;
513 return pC->mhDC;
516 void ImplReleaseCachedDC( sal_uLong nID )
518 SalData* pSalData = GetSalData();
519 HDCCache* pC = &pSalData->mpHDCCache[ nID ];
521 if ( pC->mhActBmp )
522 SelectObject( pC->mhDC, pC->mhSelBmp );
525 void ImplClearHDCCache( SalData* pData )
527 for( sal_uLong i = 0; i < CACHESIZE_HDC; i++ )
529 HDCCache* pC = &pData->mpHDCCache[ i ];
531 if( pC->mhDC )
533 SelectObject( pC->mhDC, pC->mhDefBmp );
535 if( pC->mhDefPal )
536 SelectPalette( pC->mhDC, pC->mhDefPal, TRUE );
538 DeleteDC( pC->mhDC );
539 DeleteObject( pC->mhSelBmp );
544 OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height)
545 : mhBitmap(nullptr)
546 , mpData(nullptr)
547 , maRects(0, 0, width, height, x, y, width, height)
549 WinSalGraphics& rWinGraphics = static_cast<WinSalGraphics&>(rGraphics);
550 mpImpl = dynamic_cast<WinOpenGLSalGraphicsImpl*>(rWinGraphics.mpImpl.get());
552 if (!mpImpl)
554 // we avoid the OpenGL drawing, instead we draw directly to the DC
555 mhCompatibleDC = rWinGraphics.getHDC();
556 return;
559 mhCompatibleDC = CreateCompatibleDC(rWinGraphics.getHDC());
561 // move the origin so that we always paint at 0,0 - to keep the bitmap
562 // small
563 OffsetViewportOrgEx(mhCompatibleDC, -x, -y, nullptr);
565 mhBitmap = WinSalVirtualDevice::ImplCreateVirDevBitmap(mhCompatibleDC, width, height, 32, reinterpret_cast<void **>(&mpData));
567 mhOrigBitmap = static_cast<HBITMAP>(SelectObject(mhCompatibleDC, mhBitmap));
570 OpenGLCompatibleDC::~OpenGLCompatibleDC()
572 if (mpImpl)
574 SelectObject(mhCompatibleDC, mhOrigBitmap);
575 DeleteObject(mhBitmap);
576 DeleteDC(mhCompatibleDC);
580 void OpenGLCompatibleDC::fill(sal_uInt32 color)
582 if (!mpData)
583 return;
585 sal_uInt32 *p = mpData;
586 for (int i = maRects.mnSrcWidth * maRects.mnSrcHeight; i > 0; --i)
587 *p++ = color;
590 OpenGLTexture* OpenGLCompatibleDC::getTexture()
592 if (!mpImpl)
593 return nullptr;
595 // turn what's in the mpData into a texture
596 return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData);
599 bool OpenGLCompatibleDC::copyToTexture(OpenGLTexture& aTexture)
601 if (!mpImpl)
602 return false;
604 return aTexture.CopyData(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, reinterpret_cast<sal_uInt8*>(mpData));
607 WinSalGraphics::WinSalGraphics(WinSalGraphics::Type eType, bool bScreen, HWND hWnd, SalGeometryProvider *pProvider):
608 mhLocalDC(nullptr),
609 mbPrinter(eType == WinSalGraphics::PRINTER),
610 mbVirDev(eType == WinSalGraphics::VIRTUAL_DEVICE),
611 mbWindow(eType == WinSalGraphics::WINDOW),
612 mbScreen(bScreen),
613 mhWnd(hWnd),
614 mhRegion(nullptr),
615 mhDefPen(nullptr),
616 mhDefBrush(nullptr),
617 mhDefFont(nullptr),
618 mhDefPal(nullptr),
619 mpStdClipRgnData(nullptr),
620 mnPenWidth(GSL_PEN_WIDTH)
622 if (OpenGLHelper::isVCLOpenGLEnabled() && !mbPrinter)
623 mpImpl.reset(new WinOpenGLSalGraphicsImpl(*this, pProvider));
624 else
625 mpImpl.reset(new WinSalGraphicsImpl(*this));
628 WinSalGraphics::~WinSalGraphics()
630 // free obsolete GDI objects
631 ReleaseFonts();
633 if ( mhRegion )
635 DeleteRegion( mhRegion );
636 mhRegion = nullptr;
639 // delete cache data
640 delete [] reinterpret_cast<BYTE*>(mpStdClipRgnData);
643 SalGraphicsImpl* WinSalGraphics::GetImpl() const
645 return mpImpl.get();
648 bool WinSalGraphics::isPrinter() const
650 return mbPrinter;
653 bool WinSalGraphics::isVirtualDevice() const
655 return mbVirDev;
658 bool WinSalGraphics::isWindow() const
660 return mbWindow;
663 bool WinSalGraphics::isScreen() const
665 return mbScreen;
668 HWND WinSalGraphics::gethWnd()
670 return mhWnd;
673 void WinSalGraphics::setHWND(HWND hWnd)
675 mhWnd = hWnd;
678 HPALETTE WinSalGraphics::getDefPal() const
680 return mhDefPal;
683 void WinSalGraphics::setDefPal(HPALETTE hDefPal)
685 mhDefPal = hDefPal;
688 HRGN WinSalGraphics::getRegion() const
690 return mhRegion;
693 void WinSalGraphics::GetResolution( sal_Int32& rDPIX, sal_Int32& rDPIY )
695 rDPIX = GetDeviceCaps( getHDC(), LOGPIXELSX );
696 rDPIY = GetDeviceCaps( getHDC(), LOGPIXELSY );
698 // #111139# this fixes the symptom of div by zero on startup
699 // however, printing will fail most likely as communication with
700 // the printer seems not to work in this case
701 if( !rDPIX || !rDPIY )
702 rDPIX = rDPIY = 600;
705 sal_uInt16 WinSalGraphics::GetBitCount() const
707 return mpImpl->GetBitCount();
710 long WinSalGraphics::GetGraphicsWidth() const
712 return mpImpl->GetGraphicsWidth();
715 void WinSalGraphics::ResetClipRegion()
717 mpImpl->ResetClipRegion();
720 bool WinSalGraphics::setClipRegion( const vcl::Region& i_rClip )
722 return mpImpl->setClipRegion( i_rClip );
725 void WinSalGraphics::SetLineColor()
727 mpImpl->SetLineColor();
730 void WinSalGraphics::SetLineColor( Color nColor )
732 mpImpl->SetLineColor( nColor );
735 void WinSalGraphics::SetFillColor()
737 mpImpl->SetFillColor();
740 void WinSalGraphics::SetFillColor( Color nColor )
742 mpImpl->SetFillColor( nColor );
745 void WinSalGraphics::SetXORMode( bool bSet, bool bInvertOnly )
747 mpImpl->SetXORMode( bSet, bInvertOnly );
750 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor )
752 mpImpl->SetROPLineColor( nROPColor );
755 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor )
757 mpImpl->SetROPFillColor( nROPColor );
760 void WinSalGraphics::drawPixel( long nX, long nY )
762 mpImpl->drawPixel( nX, nY );
765 void WinSalGraphics::drawPixel( long nX, long nY, Color nColor )
767 mpImpl->drawPixel( nX, nY, nColor );
770 void WinSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 )
772 mpImpl->drawLine( nX1, nY1, nX2, nY2 );
775 void WinSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight )
777 mpImpl->drawRect( nX, nY, nWidth, nHeight );
780 void WinSalGraphics::drawPolyLine( sal_uInt32 nPoints, const SalPoint* pPtAry )
782 mpImpl->drawPolyLine( nPoints, pPtAry );
785 void WinSalGraphics::drawPolygon( sal_uInt32 nPoints, const SalPoint* pPtAry )
787 mpImpl->drawPolygon( nPoints, pPtAry );
790 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints,
791 PCONSTSALPOINT* pPtAry )
793 mpImpl->drawPolyPolygon( nPoly, pPoints, pPtAry );
796 bool WinSalGraphics::drawPolyLineBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry )
798 return mpImpl->drawPolyLineBezier( nPoints, pPtAry, pFlgAry );
801 bool WinSalGraphics::drawPolygonBezier( sal_uInt32 nPoints, const SalPoint* pPtAry, const PolyFlags* pFlgAry )
803 return mpImpl->drawPolygonBezier( nPoints, pPtAry, pFlgAry );
806 bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints,
807 const SalPoint* const* pPtAry, const PolyFlags* const* pFlgAry )
809 return mpImpl->drawPolyPolygonBezier( nPoly, pPoints, pPtAry, pFlgAry );
812 static BYTE* ImplSearchEntry( BYTE* pSource, BYTE const * pDest, sal_uLong nComp, sal_uLong nSize )
814 while ( nComp-- >= nSize )
816 sal_uLong i;
817 for ( i = 0; i < nSize; i++ )
819 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) )
820 break;
822 if ( i == nSize )
823 return pSource;
824 pSource++;
826 return nullptr;
829 static bool ImplGetBoundingBox( double* nNumb, BYTE* pSource, sal_uLong nSize )
831 bool bRetValue = FALSE;
832 BYTE* pDest = ImplSearchEntry( pSource, reinterpret_cast<BYTE const *>("%%BoundingBox:"), nSize, 14 );
833 if ( pDest )
835 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0;
836 pDest += 14;
838 int nSizeLeft = nSize - ( pDest - pSource );
839 if ( nSizeLeft > 100 )
840 nSizeLeft = 100; // only 100 bytes following the bounding box will be checked
842 int i;
843 for ( i = 0; ( i < 4 ) && nSizeLeft; i++ )
845 int nDivision = 1;
846 bool bDivision = FALSE;
847 bool bNegative = FALSE;
848 bool bValid = TRUE;
850 while ( ( --nSizeLeft ) && ( ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) ) pDest++;
851 BYTE nByte = *pDest;
852 while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) )
854 switch ( nByte )
856 case '.' :
857 if ( bDivision )
858 bValid = FALSE;
859 else
860 bDivision = TRUE;
861 break;
862 case '-' :
863 bNegative = TRUE;
864 break;
865 default :
866 if ( ( nByte < '0' ) || ( nByte > '9' ) )
867 nSizeLeft = 1; // error parsing the bounding box values
868 else if ( bValid )
870 if ( bDivision )
871 nDivision*=10;
872 nNumb[i] *= 10;
873 nNumb[i] += nByte - '0';
875 break;
877 nSizeLeft--;
878 nByte = *(++pDest);
880 if ( bNegative )
881 nNumb[i] = -nNumb[i];
882 if ( bDivision && ( nDivision != 1 ) )
883 nNumb[i] /= nDivision;
885 if ( i == 4 )
886 bRetValue = TRUE;
888 return bRetValue;
891 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF
893 bool WinSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uInt32 nSize )
895 bool bRetValue = false;
897 if ( mbPrinter )
899 int nEscape = POSTSCRIPT_PASSTHROUGH;
901 if ( Escape( getHDC(), QUERYESCSUPPORT, sizeof( int ), reinterpret_cast<LPSTR>(&nEscape), nullptr ) )
903 double nBoundingBox[4];
905 if ( ImplGetBoundingBox( nBoundingBox, static_cast<BYTE*>(pPtr), nSize ) )
907 OStringBuffer aBuf( POSTSCRIPT_BUFSIZE );
909 // reserve place for a sal_uInt16
910 aBuf.append( "aa" );
912 // #107797# Write out EPS encapsulation header
914 // directly taken from the PLRM 3.0, p. 726. Note:
915 // this will definitely cause problems when
916 // recursively creating and embedding PostScript files
917 // in OOo, since we use statically-named variables
918 // here (namely, b4_Inc_state_salWin, dict_count_salWin and
919 // op_count_salWin). Currently, I have no idea on how to
920 // work around that, except from scanning and
921 // interpreting the EPS for unused identifiers.
923 // append the real text
924 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n"
925 "/dict_count_salWin countdictstack def\n"
926 "/op_count_salWin count 1 sub def\n"
927 "userdict begin\n"
928 "/showpage {} def\n"
929 "0 setgray 0 setlinecap\n"
930 "1 setlinewidth 0 setlinejoin\n"
931 "10 setmiterlimit [] 0 setdash newpath\n"
932 "/languagelevel where\n"
933 "{\n"
934 " pop languagelevel\n"
935 " 1 ne\n"
936 " {\n"
937 " false setstrokeadjust false setoverprint\n"
938 " } if\n"
939 "} if\n\n" );
941 // #i10737# Apply clipping manually
943 // Windows seems to ignore any clipping at the HDC,
944 // when followed by a POSTSCRIPT_PASSTHROUGH
946 // Check whether we've got a clipping, consisting of
947 // exactly one rect (other cases should be, but aren't
948 // handled currently)
950 // TODO: Handle more than one rectangle here (take
951 // care, the buffer can handle only POSTSCRIPT_BUFSIZE
952 // characters!)
953 if ( mhRegion != nullptr &&
954 mpStdClipRgnData != nullptr &&
955 mpClipRgnData == mpStdClipRgnData &&
956 mpClipRgnData->rdh.nCount == 1 )
958 RECT* pRect = &(mpClipRgnData->rdh.rcBound);
960 aBuf.append( "\nnewpath\n" );
961 aBuf.append( pRect->left );
962 aBuf.append( " " );
963 aBuf.append( pRect->top );
964 aBuf.append( " moveto\n" );
965 aBuf.append( pRect->right );
966 aBuf.append( " " );
967 aBuf.append( pRect->top );
968 aBuf.append( " lineto\n" );
969 aBuf.append( pRect->right );
970 aBuf.append( " " );
971 aBuf.append( pRect->bottom );
972 aBuf.append( " lineto\n" );
973 aBuf.append( pRect->left );
974 aBuf.append( " " );
975 aBuf.append( pRect->bottom );
976 aBuf.append( " lineto\n"
977 "closepath\n"
978 "clip\n"
979 "newpath\n" );
982 // #107797# Write out buffer
984 *reinterpret_cast<sal_uInt16*>(const_cast<char *>(aBuf.getStr())) = static_cast<sal_uInt16>( aBuf.getLength() - 2 );
985 Escape ( getHDC(), nEscape, aBuf.getLength(), aBuf.getStr(), nullptr );
987 // #107797# Write out EPS transformation code
989 double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] );
990 double dM22 = nHeight / (nBoundingBox[1] - nBoundingBox[3] );
991 // reserve a sal_uInt16 again
992 aBuf.setLength( 2 );
993 aBuf.append( "\n\n[" );
994 aBuf.append( dM11 );
995 aBuf.append( " 0 0 " );
996 aBuf.append( dM22 );
997 aBuf.append( ' ' );
998 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) );
999 aBuf.append( ' ' );
1000 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) );
1001 aBuf.append( "] concat\n"
1002 "%%BeginDocument:\n" );
1003 *reinterpret_cast<sal_uInt16*>(const_cast<char *>(aBuf.getStr())) = static_cast<sal_uInt16>( aBuf.getLength() - 2 );
1004 Escape ( getHDC(), nEscape, aBuf.getLength(), aBuf.getStr(), nullptr );
1006 // #107797# Write out actual EPS content
1008 sal_uLong nToDo = nSize;
1009 sal_uLong nDoNow;
1010 while ( nToDo )
1012 nDoNow = nToDo;
1013 if ( nToDo > POSTSCRIPT_BUFSIZE - 2 )
1014 nDoNow = POSTSCRIPT_BUFSIZE - 2;
1015 // the following is based on the string buffer allocation
1016 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf
1017 *reinterpret_cast<sal_uInt16*>(const_cast<char *>(aBuf.getStr())) = static_cast<sal_uInt16>(nDoNow);
1018 memcpy( const_cast<char *>(aBuf.getStr() + 2), static_cast<BYTE*>(pPtr) + nSize - nToDo, nDoNow );
1019 sal_uLong nResult = Escape ( getHDC(), nEscape, nDoNow + 2, aBuf.getStr(), nullptr );
1020 if (!nResult )
1021 break;
1022 nToDo -= nResult;
1025 // #107797# Write out EPS encapsulation footer
1027 // reserve a sal_uInt16 again
1028 aBuf.setLength( 2 );
1029 aBuf.append( "%%EndDocument\n"
1030 "count op_count_salWin sub {pop} repeat\n"
1031 "countdictstack dict_count_salWin sub {end} repeat\n"
1032 "b4_Inc_state_salWin restore\n\n" );
1033 *reinterpret_cast<sal_uInt16*>(const_cast<char *>(aBuf.getStr())) = static_cast<sal_uInt16>( aBuf.getLength() - 2 );
1034 Escape ( getHDC(), nEscape, aBuf.getLength(), aBuf.getStr(), nullptr );
1035 bRetValue = TRUE;
1040 return bRetValue;
1043 SystemGraphicsData WinSalGraphics::GetGraphicsData() const
1045 SystemGraphicsData aRes;
1046 aRes.nSize = sizeof(aRes);
1047 aRes.hDC = getHDC();
1048 return aRes;
1051 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */