1 /************************************************************** 2 * 3 * Licensed to the Apache Software Foundation (ASF) under one 4 * or more contributor license agreements. See the NOTICE file 5 * distributed with this work for additional information 6 * regarding copyright ownership. The ASF licenses this file 7 * to you under the Apache License, Version 2.0 (the 8 * "License"); you may not use this file except in compliance 9 * with the License. You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, 14 * software distributed under the License is distributed on an 15 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 * KIND, either express or implied. See the License for the 17 * specific language governing permissions and limitations 18 * under the License. 19 * 20 *************************************************************/ 21 22 23 24 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include <stdio.h> 28 #include <string.h> 29 30 #include <rtl/strbuf.hxx> 31 32 #include <tools/svwin.h> 33 #include <tools/debug.hxx> 34 #include <tools/poly.hxx> 35 36 #include <basegfx/polygon/b2dpolygon.hxx> 37 #include <basegfx/polygon/b2dpolygontools.hxx> 38 39 #include <win/wincomp.hxx> 40 #include <win/saldata.hxx> 41 #include <win/salgdi.h> 42 #include <win/salframe.h> 43 44 #include <region.h> 45 46 using namespace rtl; 47 48 // ======================================================================= 49 50 // comment out to prevent use of beziers on GDI functions 51 #define USE_GDI_BEZIERS 52 53 // ======================================================================= 54 55 #define DITHER_PAL_DELTA 51 56 #define DITHER_PAL_STEPS 6 57 #define DITHER_PAL_COUNT (DITHER_PAL_STEPS*DITHER_PAL_STEPS*DITHER_PAL_STEPS) 58 #define DITHER_MAX_SYSCOLOR 16 59 #define DITHER_EXTRA_COLORS 1 60 #define DMAP( _def_nVal, _def_nThres ) ((pDitherDiff[_def_nVal]>(_def_nThres))?pDitherHigh[_def_nVal]:pDitherLow[_def_nVal]) 61 62 // ======================================================================= 63 64 struct SysColorEntry 65 { 66 DWORD nRGB; 67 SysColorEntry* pNext; 68 }; 69 70 // ======================================================================= 71 72 static SysColorEntry* pFirstSysColor = NULL; 73 static SysColorEntry* pActSysColor = NULL; 74 75 // ----------------------------------------------------------------------------- 76 77 // Blue7 78 static PALETTEENTRY aImplExtraColor1 = 79 { 80 0, 184, 255, 0 81 }; 82 83 // ----------------------------------------------------------------------------- 84 85 static PALETTEENTRY aImplSalSysPalEntryAry[ DITHER_MAX_SYSCOLOR ] = 86 { 87 { 0, 0, 0, 0 }, 88 { 0, 0, 0x80, 0 }, 89 { 0, 0x80, 0, 0 }, 90 { 0, 0x80, 0x80, 0 }, 91 { 0x80, 0, 0, 0 }, 92 { 0x80, 0, 0x80, 0 }, 93 { 0x80, 0x80, 0, 0 }, 94 { 0x80, 0x80, 0x80, 0 }, 95 { 0xC0, 0xC0, 0xC0, 0 }, 96 { 0, 0, 0xFF, 0 }, 97 { 0, 0xFF, 0, 0 }, 98 { 0, 0xFF, 0xFF, 0 }, 99 { 0xFF, 0, 0, 0 }, 100 { 0xFF, 0, 0xFF, 0 }, 101 { 0xFF, 0xFF, 0, 0 }, 102 { 0xFF, 0xFF, 0xFF, 0 } 103 }; 104 105 // ----------------------------------------------------------------------------- 106 107 static BYTE aOrdDither8Bit[8][8] = 108 { 109 0, 38, 9, 48, 2, 40, 12, 50, 110 25, 12, 35, 22, 28, 15, 37, 24, 111 6, 44, 3, 41, 8, 47, 5, 44, 112 32, 19, 28, 16, 34, 21, 31, 18, 113 1, 40, 11, 49, 0, 39, 10, 48, 114 27, 14, 36, 24, 26, 13, 36, 23, 115 8, 46, 4, 43, 7, 45, 4, 42, 116 33, 20, 30, 17, 32, 20, 29, 16 117 }; 118 119 // ----------------------------------------------------------------------------- 120 121 static BYTE aOrdDither16Bit[8][8] = 122 { 123 0, 6, 1, 7, 0, 6, 1, 7, 124 4, 2, 5, 3, 4, 2, 5, 3, 125 1, 7, 0, 6, 1, 7, 0, 6, 126 5, 3, 4, 2, 5, 3, 4, 2, 127 0, 6, 1, 7, 0, 6, 1, 7, 128 4, 2, 5, 3, 4, 2, 5, 3, 129 1, 7, 0, 6, 1, 7, 0, 6, 130 5, 3, 4, 2, 5, 3, 4, 2 131 }; 132 133 // ======================================================================= 134 135 // Pens muessen wir mit 1 Pixel-Breite erzeugen, da ansonsten die S3-Karte 136 // viele Paintprobleme hat, wenn Polygone/PolyLines gezeichnet werden und 137 // eine komplexe ClipRegion gesetzt ist 138 #define GSL_PEN_WIDTH 1 139 140 // ======================================================================= 141 142 #define SAL_POLYPOLYCOUNT_STACKBUF 8 143 #define SAL_POLYPOLYPOINTS_STACKBUF 64 144 145 // ======================================================================= 146 147 void ImplInitSalGDI() 148 { 149 SalData* pSalData = GetSalData(); 150 151 // init stock brushes 152 pSalData->maStockPenColorAry[0] = PALETTERGB( 0, 0, 0 ); 153 pSalData->maStockPenColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF ); 154 pSalData->maStockPenColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 ); 155 pSalData->maStockPenColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 ); 156 pSalData->mhStockPenAry[0] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[0] ); 157 pSalData->mhStockPenAry[1] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[1] ); 158 pSalData->mhStockPenAry[2] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[2] ); 159 pSalData->mhStockPenAry[3] = CreatePen( PS_SOLID, GSL_PEN_WIDTH, pSalData->maStockPenColorAry[3] ); 160 pSalData->mnStockPenCount = 4; 161 162 pSalData->maStockBrushColorAry[0] = PALETTERGB( 0, 0, 0 ); 163 pSalData->maStockBrushColorAry[1] = PALETTERGB( 0xFF, 0xFF, 0xFF ); 164 pSalData->maStockBrushColorAry[2] = PALETTERGB( 0xC0, 0xC0, 0xC0 ); 165 pSalData->maStockBrushColorAry[3] = PALETTERGB( 0x80, 0x80, 0x80 ); 166 pSalData->mhStockBrushAry[0] = CreateSolidBrush( pSalData->maStockBrushColorAry[0] ); 167 pSalData->mhStockBrushAry[1] = CreateSolidBrush( pSalData->maStockBrushColorAry[1] ); 168 pSalData->mhStockBrushAry[2] = CreateSolidBrush( pSalData->maStockBrushColorAry[2] ); 169 pSalData->mhStockBrushAry[3] = CreateSolidBrush( pSalData->maStockBrushColorAry[3] ); 170 pSalData->mnStockBrushCount = 4; 171 172 // initialize cache of device contexts 173 pSalData->mpHDCCache = new HDCCache[ CACHESIZE_HDC ]; 174 memset( pSalData->mpHDCCache, 0, CACHESIZE_HDC * sizeof( HDCCache ) ); 175 176 // initialize temporary font list 177 pSalData->mpTempFontItem = NULL; 178 179 // support palettes for 256 color displays 180 HDC hDC = GetDC( 0 ); 181 int nBitsPixel = GetDeviceCaps( hDC, BITSPIXEL ); 182 int nPlanes = GetDeviceCaps( hDC, PLANES ); 183 int nRasterCaps = GetDeviceCaps( hDC, RASTERCAPS ); 184 int nBitCount = nBitsPixel * nPlanes; 185 186 if ( (nBitCount > 8) && (nBitCount < 24) ) 187 { 188 // test, if we have to dither 189 HDC hMemDC = ::CreateCompatibleDC( hDC ); 190 HBITMAP hMemBmp = ::CreateCompatibleBitmap( hDC, 8, 8 ); 191 HBITMAP hBmpOld = (HBITMAP) ::SelectObject( hMemDC, hMemBmp ); 192 HBRUSH hMemBrush = ::CreateSolidBrush( PALETTERGB( 175, 171, 169 ) ); 193 HBRUSH hBrushOld = (HBRUSH) ::SelectObject( hMemDC, hMemBrush ); 194 sal_Bool bDither16 = TRUE; 195 196 ::PatBlt( hMemDC, 0, 0, 8, 8, PATCOPY ); 197 const COLORREF aCol( ::GetPixel( hMemDC, 0, 0 ) ); 198 199 for( int nY = 0; ( nY < 8 ) && bDither16; nY++ ) 200 for( int nX = 0; ( nX < 8 ) && bDither16; nX++ ) 201 if( ::GetPixel( hMemDC, nX, nY ) != aCol ) 202 bDither16 = FALSE; 203 204 ::SelectObject( hMemDC, hBrushOld ), ::DeleteObject( hMemBrush ); 205 ::SelectObject( hMemDC, hBmpOld ), ::DeleteObject( hMemBmp ); 206 ::DeleteDC( hMemDC ); 207 208 if( bDither16 ) 209 { 210 // create DIBPattern for 16Bit dithering 211 long n; 212 213 pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, sizeof( BITMAPINFOHEADER ) + 192 ); 214 pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB ); 215 pSalData->mpDitherDiff = new long[ 256 ]; 216 pSalData->mpDitherLow = new BYTE[ 256 ]; 217 pSalData->mpDitherHigh = new BYTE[ 256 ]; 218 pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ); 219 memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) ); 220 221 BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB; 222 223 pBIH->biSize = sizeof( BITMAPINFOHEADER ); 224 pBIH->biWidth = 8; 225 pBIH->biHeight = 8; 226 pBIH->biPlanes = 1; 227 pBIH->biBitCount = 24; 228 229 for( n = 0; n < 256L; n++ ) 230 pSalData->mpDitherDiff[ n ] = n - ( n & 248L ); 231 232 for( n = 0; n < 256L; n++ ) 233 pSalData->mpDitherLow[ n ] = (BYTE) ( n & 248 ); 234 235 for( n = 0; n < 256L; n++ ) 236 pSalData->mpDitherHigh[ n ] = (BYTE) Min( pSalData->mpDitherLow[ n ] + 8L, 255L ); 237 } 238 } 239 else if ( (nRasterCaps & RC_PALETTE) && (nBitCount == 8) ) 240 { 241 BYTE nRed, nGreen, nBlue; 242 BYTE nR, nG, nB; 243 PALETTEENTRY* pPalEntry; 244 LOGPALETTE* pLogPal; 245 const sal_uInt16 nDitherPalCount = DITHER_PAL_COUNT; 246 sal_uLong nTotalCount = DITHER_MAX_SYSCOLOR + nDitherPalCount + DITHER_EXTRA_COLORS; 247 248 // create logical palette 249 pLogPal = (LOGPALETTE*) new char[ sizeof( LOGPALETTE ) + ( nTotalCount * sizeof( PALETTEENTRY ) ) ]; 250 pLogPal->palVersion = 0x0300; 251 pLogPal->palNumEntries = (sal_uInt16) nTotalCount; 252 pPalEntry = pLogPal->palPalEntry; 253 254 // Standard colors 255 memcpy( pPalEntry, aImplSalSysPalEntryAry, DITHER_MAX_SYSCOLOR * sizeof( PALETTEENTRY ) ); 256 pPalEntry += DITHER_MAX_SYSCOLOR; 257 258 // own palette (6/6/6) 259 for( nB=0, nBlue=0; nB < DITHER_PAL_STEPS; nB++, nBlue += DITHER_PAL_DELTA ) 260 { 261 for( nG=0, nGreen=0; nG < DITHER_PAL_STEPS; nG++, nGreen += DITHER_PAL_DELTA ) 262 { 263 for( nR=0, nRed=0; nR < DITHER_PAL_STEPS; nR++, nRed += DITHER_PAL_DELTA ) 264 { 265 pPalEntry->peRed = nRed; 266 pPalEntry->peGreen = nGreen; 267 pPalEntry->peBlue = nBlue; 268 pPalEntry->peFlags = 0; 269 pPalEntry++; 270 } 271 } 272 } 273 274 // insert special 'Blue' as standard drawing color 275 *pPalEntry++ = aImplExtraColor1; 276 277 // create palette 278 pSalData->mhDitherPal = CreatePalette( pLogPal ); 279 delete[] (char*) pLogPal; 280 281 if( pSalData->mhDitherPal ) 282 { 283 // create DIBPattern for 8Bit dithering 284 long nSize = sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ) + 64; 285 long n; 286 287 pSalData->mhDitherDIB = GlobalAlloc( GMEM_FIXED, nSize ); 288 pSalData->mpDitherDIB = (BYTE*) GlobalLock( pSalData->mhDitherDIB ); 289 pSalData->mpDitherDiff = new long[ 256 ]; 290 pSalData->mpDitherLow = new BYTE[ 256 ]; 291 pSalData->mpDitherHigh = new BYTE[ 256 ]; 292 pSalData->mpDitherDIBData = pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) + ( 256 * sizeof( short ) ); 293 memset( pSalData->mpDitherDIB, 0, sizeof( BITMAPINFOHEADER ) ); 294 295 BITMAPINFOHEADER* pBIH = (BITMAPINFOHEADER*) pSalData->mpDitherDIB; 296 short* pColors = (short*) ( pSalData->mpDitherDIB + sizeof( BITMAPINFOHEADER ) ); 297 298 pBIH->biSize = sizeof( BITMAPINFOHEADER ); 299 pBIH->biWidth = 8; 300 pBIH->biHeight = 8; 301 pBIH->biPlanes = 1; 302 pBIH->biBitCount = 8; 303 304 for( n = 0; n < nDitherPalCount; n++ ) 305 pColors[ n ] = (short)( n + DITHER_MAX_SYSCOLOR ); 306 307 for( n = 0; n < 256L; n++ ) 308 pSalData->mpDitherDiff[ n ] = n % 51L; 309 310 for( n = 0; n < 256L; n++ ) 311 pSalData->mpDitherLow[ n ] = (BYTE) ( n / 51L ); 312 313 for( n = 0; n < 256L; n++ ) 314 pSalData->mpDitherHigh[ n ] = (BYTE)Min( pSalData->mpDitherLow[ n ] + 1, 5 ); 315 } 316 317 // get system color entries 318 ImplUpdateSysColorEntries(); 319 } 320 321 ReleaseDC( 0, hDC ); 322 } 323 324 // ----------------------------------------------------------------------- 325 326 void ImplFreeSalGDI() 327 { 328 SalData* pSalData = GetSalData(); 329 330 // destroy stock objects 331 int i; 332 for ( i = 0; i < pSalData->mnStockPenCount; i++ ) 333 DeletePen( pSalData->mhStockPenAry[i] ); 334 for ( i = 0; i < pSalData->mnStockBrushCount; i++ ) 335 DeleteBrush( pSalData->mhStockBrushAry[i] ); 336 337 // 50% Brush loeschen 338 if ( pSalData->mh50Brush ) 339 { 340 DeleteBrush( pSalData->mh50Brush ); 341 pSalData->mh50Brush = 0; 342 } 343 344 // 50% Bitmap loeschen 345 if ( pSalData->mh50Bmp ) 346 { 347 DeleteBitmap( pSalData->mh50Bmp ); 348 pSalData->mh50Bmp = 0; 349 } 350 351 ImplClearHDCCache( pSalData ); 352 delete[] pSalData->mpHDCCache; 353 354 // Ditherpalette loeschen, wenn vorhanden 355 if ( pSalData->mhDitherPal ) 356 { 357 DeleteObject( pSalData->mhDitherPal ); 358 pSalData->mhDitherPal = 0; 359 } 360 361 // delete buffers for dithering DIB patterns, if neccessary 362 if ( pSalData->mhDitherDIB ) 363 { 364 GlobalUnlock( pSalData->mhDitherDIB ); 365 GlobalFree( pSalData->mhDitherDIB ); 366 pSalData->mhDitherDIB = 0; 367 delete[] pSalData->mpDitherDiff; 368 delete[] pSalData->mpDitherLow; 369 delete[] pSalData->mpDitherHigh; 370 } 371 372 // delete SysColorList 373 SysColorEntry* pEntry = pFirstSysColor; 374 while( pEntry ) 375 { 376 SysColorEntry* pTmp = pEntry->pNext; 377 delete pEntry; 378 pEntry = pTmp; 379 } 380 pFirstSysColor = NULL; 381 382 // delete icon cache 383 SalIcon* pIcon = pSalData->mpFirstIcon; 384 pSalData->mpFirstIcon = NULL; 385 while( pIcon ) 386 { 387 SalIcon* pTmp = pIcon->pNext; 388 DestroyIcon( pIcon->hIcon ); 389 DestroyIcon( pIcon->hSmallIcon ); 390 delete pIcon; 391 pIcon = pTmp; 392 } 393 394 // delete temporary font list 395 ImplReleaseTempFonts( *pSalData ); 396 } 397 398 // ----------------------------------------------------------------------- 399 400 static int ImplIsPaletteEntry( BYTE nRed, BYTE nGreen, BYTE nBlue ) 401 { 402 // dither color? 403 if ( !(nRed % DITHER_PAL_DELTA) && !(nGreen % DITHER_PAL_DELTA) && !(nBlue % DITHER_PAL_DELTA) ) 404 return TRUE; 405 406 PALETTEENTRY* pPalEntry = aImplSalSysPalEntryAry; 407 408 // standard palette color? 409 for ( sal_uInt16 i = 0; i < DITHER_MAX_SYSCOLOR; i++, pPalEntry++ ) 410 { 411 if( pPalEntry->peRed == nRed && pPalEntry->peGreen == nGreen && pPalEntry->peBlue == nBlue ) 412 return TRUE; 413 } 414 415 // extra color? 416 if ( aImplExtraColor1.peRed == nRed && 417 aImplExtraColor1.peGreen == nGreen && 418 aImplExtraColor1.peBlue == nBlue ) 419 { 420 return TRUE; 421 } 422 423 return FALSE; 424 } 425 426 // ======================================================================= 427 428 int ImplIsSysColorEntry( SalColor nSalColor ) 429 { 430 SysColorEntry* pEntry = pFirstSysColor; 431 const DWORD nTestRGB = (DWORD)RGB( SALCOLOR_RED( nSalColor ), 432 SALCOLOR_GREEN( nSalColor ), 433 SALCOLOR_BLUE( nSalColor ) ); 434 435 while ( pEntry ) 436 { 437 if ( pEntry->nRGB == nTestRGB ) 438 return TRUE; 439 pEntry = pEntry->pNext; 440 } 441 442 return FALSE; 443 } 444 445 // ======================================================================= 446 447 static void ImplInsertSysColorEntry( int nSysIndex ) 448 { 449 const DWORD nRGB = GetSysColor( nSysIndex ); 450 451 if ( !ImplIsPaletteEntry( GetRValue( nRGB ), GetGValue( nRGB ), GetBValue( nRGB ) ) ) 452 { 453 if ( !pFirstSysColor ) 454 { 455 pActSysColor = pFirstSysColor = new SysColorEntry; 456 pFirstSysColor->nRGB = nRGB; 457 pFirstSysColor->pNext = NULL; 458 } 459 else 460 { 461 pActSysColor = pActSysColor->pNext = new SysColorEntry; 462 pActSysColor->nRGB = nRGB; 463 pActSysColor->pNext = NULL; 464 } 465 } 466 } 467 468 // ======================================================================= 469 470 void ImplUpdateSysColorEntries() 471 { 472 // delete old SysColorList 473 SysColorEntry* pEntry = pFirstSysColor; 474 while( pEntry ) 475 { 476 SysColorEntry* pTmp = pEntry->pNext; 477 delete pEntry; 478 pEntry = pTmp; 479 } 480 pActSysColor = pFirstSysColor = NULL; 481 482 // create new sys color list 483 ImplInsertSysColorEntry( COLOR_ACTIVEBORDER ); 484 ImplInsertSysColorEntry( COLOR_INACTIVEBORDER ); 485 if( aSalShlData.mnVersion >= 410 ) 486 { 487 ImplInsertSysColorEntry( COLOR_GRADIENTACTIVECAPTION ); 488 ImplInsertSysColorEntry( COLOR_GRADIENTINACTIVECAPTION ); 489 } 490 ImplInsertSysColorEntry( COLOR_3DFACE ); 491 ImplInsertSysColorEntry( COLOR_3DHILIGHT ); 492 ImplInsertSysColorEntry( COLOR_3DLIGHT ); 493 ImplInsertSysColorEntry( COLOR_3DSHADOW ); 494 ImplInsertSysColorEntry( COLOR_3DDKSHADOW ); 495 ImplInsertSysColorEntry( COLOR_INFOBK ); 496 ImplInsertSysColorEntry( COLOR_INFOTEXT ); 497 ImplInsertSysColorEntry( COLOR_BTNTEXT ); 498 ImplInsertSysColorEntry( COLOR_WINDOW ); 499 ImplInsertSysColorEntry( COLOR_WINDOWTEXT ); 500 ImplInsertSysColorEntry( COLOR_HIGHLIGHT ); 501 ImplInsertSysColorEntry( COLOR_HIGHLIGHTTEXT ); 502 ImplInsertSysColorEntry( COLOR_MENU ); 503 ImplInsertSysColorEntry( COLOR_MENUTEXT ); 504 ImplInsertSysColorEntry( COLOR_ACTIVECAPTION ); 505 ImplInsertSysColorEntry( COLOR_CAPTIONTEXT ); 506 ImplInsertSysColorEntry( COLOR_INACTIVECAPTION ); 507 ImplInsertSysColorEntry( COLOR_INACTIVECAPTIONTEXT ); 508 } 509 510 // ----------------------------------------------------------------------- 511 512 static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) 513 { 514 SalColor nSalColor; 515 if ( nROPColor == SAL_ROP_0 ) 516 nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); 517 else 518 nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); 519 return nSalColor; 520 } 521 522 // ======================================================================= 523 524 void ImplSalInitGraphics( WinSalGraphics* pData ) 525 { 526 // Beim Printer berechnen wir die minimale Linienstaerke 527 if ( pData->mbPrinter ) 528 { 529 int nDPIX = GetDeviceCaps( pData->mhDC, LOGPIXELSX ); 530 if ( nDPIX <= 300 ) 531 pData->mnPenWidth = 0; 532 else 533 pData->mnPenWidth = nDPIX/300; 534 } 535 536 ::SetTextAlign( pData->mhDC, TA_BASELINE | TA_LEFT | TA_NOUPDATECP ); 537 ::SetBkMode( pData->mhDC, TRANSPARENT ); 538 ::SetROP2( pData->mhDC, R2_COPYPEN ); 539 } 540 541 // ----------------------------------------------------------------------- 542 543 void ImplSalDeInitGraphics( WinSalGraphics* pData ) 544 { 545 // clear clip region 546 SelectClipRgn( pData->mhDC, 0 ); 547 // select default objects 548 if ( pData->mhDefPen ) 549 SelectPen( pData->mhDC, pData->mhDefPen ); 550 if ( pData->mhDefBrush ) 551 SelectBrush( pData->mhDC, pData->mhDefBrush ); 552 if ( pData->mhDefFont ) 553 SelectFont( pData->mhDC, pData->mhDefFont ); 554 } 555 556 // ======================================================================= 557 558 HDC ImplGetCachedDC( sal_uLong nID, HBITMAP hBmp ) 559 { 560 SalData* pSalData = GetSalData(); 561 HDCCache* pC = &pSalData->mpHDCCache[ nID ]; 562 563 if( !pC->mhDC ) 564 { 565 HDC hDC = GetDC( 0 ); 566 567 // neuen DC mit DefaultBitmap anlegen 568 pC->mhDC = CreateCompatibleDC( hDC ); 569 570 if( pSalData->mhDitherPal ) 571 { 572 pC->mhDefPal = SelectPalette( pC->mhDC, pSalData->mhDitherPal, TRUE ); 573 RealizePalette( pC->mhDC ); 574 } 575 576 pC->mhSelBmp = CreateCompatibleBitmap( hDC, CACHED_HDC_DEFEXT, CACHED_HDC_DEFEXT ); 577 pC->mhDefBmp = (HBITMAP) SelectObject( pC->mhDC, pC->mhSelBmp ); 578 579 ReleaseDC( 0, hDC ); 580 } 581 582 if ( hBmp ) 583 SelectObject( pC->mhDC, pC->mhActBmp = hBmp ); 584 else 585 pC->mhActBmp = 0; 586 587 return pC->mhDC; 588 } 589 590 // ======================================================================= 591 592 void ImplReleaseCachedDC( sal_uLong nID ) 593 { 594 SalData* pSalData = GetSalData(); 595 HDCCache* pC = &pSalData->mpHDCCache[ nID ]; 596 597 if ( pC->mhActBmp ) 598 SelectObject( pC->mhDC, pC->mhSelBmp ); 599 } 600 601 // ======================================================================= 602 603 void ImplClearHDCCache( SalData* pData ) 604 { 605 for( sal_uLong i = 0; i < CACHESIZE_HDC; i++ ) 606 { 607 HDCCache* pC = &pData->mpHDCCache[ i ]; 608 609 if( pC->mhDC ) 610 { 611 SelectObject( pC->mhDC, pC->mhDefBmp ); 612 613 if( pC->mhDefPal ) 614 SelectPalette( pC->mhDC, pC->mhDefPal, TRUE ); 615 616 DeleteDC( pC->mhDC ); 617 DeleteObject( pC->mhSelBmp ); 618 } 619 } 620 } 621 622 // ======================================================================= 623 624 // #100127# Fill point and flag memory from array of points which 625 // might also contain bezier control points for the PolyDraw() GDI method 626 // Make sure pWinPointAry and pWinFlagAry are big enough 627 void ImplPreparePolyDraw( bool bCloseFigures, 628 sal_uLong nPoly, 629 const sal_uLong* pPoints, 630 const SalPoint* const* pPtAry, 631 const BYTE* const* pFlgAry, 632 POINT* pWinPointAry, 633 BYTE* pWinFlagAry ) 634 { 635 sal_uLong nCurrPoly; 636 for( nCurrPoly=0; nCurrPoly<nPoly; ++nCurrPoly ) 637 { 638 const POINT* pCurrPoint = reinterpret_cast<const POINT*>( *pPtAry++ ); 639 const BYTE* pCurrFlag = *pFlgAry++; 640 const sal_uLong nCurrPoints = *pPoints++; 641 const bool bHaveFlagArray( pCurrFlag ); 642 sal_uLong nCurrPoint; 643 644 if( nCurrPoints ) 645 { 646 // start figure 647 *pWinPointAry++ = *pCurrPoint++; 648 *pWinFlagAry++ = PT_MOVETO; 649 ++pCurrFlag; 650 651 for( nCurrPoint=1; nCurrPoint<nCurrPoints; ) 652 { 653 // #102067# Check existence of flag array 654 if( bHaveFlagArray && 655 ( nCurrPoint + 2 ) < nCurrPoints ) 656 { 657 BYTE P4( pCurrFlag[ 2 ] ); 658 659 if( ( POLY_CONTROL == pCurrFlag[ 0 ] ) && 660 ( POLY_CONTROL == pCurrFlag[ 1 ] ) && 661 ( POLY_NORMAL == P4 || POLY_SMOOTH == P4 || POLY_SYMMTR == P4 ) ) 662 { 663 // control point one 664 *pWinPointAry++ = *pCurrPoint++; 665 *pWinFlagAry++ = PT_BEZIERTO; 666 667 // control point two 668 *pWinPointAry++ = *pCurrPoint++; 669 *pWinFlagAry++ = PT_BEZIERTO; 670 671 // end point 672 *pWinPointAry++ = *pCurrPoint++; 673 *pWinFlagAry++ = PT_BEZIERTO; 674 675 nCurrPoint += 3; 676 pCurrFlag += 3; 677 continue; 678 } 679 } 680 681 // regular line point 682 *pWinPointAry++ = *pCurrPoint++; 683 *pWinFlagAry++ = PT_LINETO; 684 ++pCurrFlag; 685 ++nCurrPoint; 686 } 687 688 // end figure? 689 if( bCloseFigures ) 690 pWinFlagAry[-1] |= PT_CLOSEFIGURE; 691 } 692 } 693 } 694 695 // ======================================================================= 696 697 // #100127# draw an array of points which might also contain bezier control points 698 void ImplRenderPath( HDC hdc, sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 699 { 700 if( nPoints ) 701 { 702 sal_uInt16 i; 703 // TODO: profile whether the following options are faster: 704 // a) look ahead and draw consecutive bezier or line segments by PolyBezierTo/PolyLineTo resp. 705 // b) convert our flag array to window's and use PolyDraw 706 707 MoveToEx( hdc, pPtAry->mnX, pPtAry->mnY, NULL ); 708 ++pPtAry; ++pFlgAry; 709 710 for( i=1; i<nPoints; ++i, ++pPtAry, ++pFlgAry ) 711 { 712 if( *pFlgAry != POLY_CONTROL ) 713 { 714 LineTo( hdc, pPtAry->mnX, pPtAry->mnY ); 715 } 716 else if( nPoints - i > 2 ) 717 { 718 PolyBezierTo( hdc, reinterpret_cast<const POINT*>(pPtAry), 3 ); 719 i += 2; pPtAry += 2; pFlgAry += 2; 720 } 721 } 722 } 723 } 724 725 // ======================================================================= 726 727 WinSalGraphics::WinSalGraphics() 728 { 729 for( int i = 0; i < MAX_FALLBACK; ++i ) 730 { 731 mhFonts[ i ] = 0; 732 mpWinFontData[ i ] = NULL; 733 mpWinFontEntry[ i ] = NULL; 734 } 735 736 mfFontScale = 1.0; 737 738 mhDC = 0; 739 mhPen = 0; 740 mhBrush = 0; 741 mhRegion = 0; 742 mhDefPen = 0; 743 mhDefBrush = 0; 744 mhDefFont = 0; 745 mhDefPal = 0; 746 mpStdClipRgnData = NULL; 747 mpLogFont = NULL; 748 mpFontCharSets = NULL; 749 mpFontAttrCache = NULL; 750 mnFontCharSetCount = 0; 751 mpFontKernPairs = NULL; 752 mnFontKernPairCount = 0; 753 mbFontKernInit = FALSE; 754 mbXORMode = FALSE; 755 mnPenWidth = GSL_PEN_WIDTH; 756 } 757 758 // ----------------------------------------------------------------------- 759 760 WinSalGraphics::~WinSalGraphics() 761 { 762 // free obsolete GDI objekts 763 ReleaseFonts(); 764 765 if ( mhPen ) 766 { 767 if ( !mbStockPen ) 768 DeletePen( mhPen ); 769 } 770 if ( mhBrush ) 771 { 772 if ( !mbStockBrush ) 773 DeleteBrush( mhBrush ); 774 } 775 776 if ( mhRegion ) 777 { 778 DeleteRegion( mhRegion ); 779 mhRegion = 0; 780 } 781 782 // Cache-Daten zerstoeren 783 if ( mpStdClipRgnData ) 784 delete [] mpStdClipRgnData; 785 786 if ( mpLogFont ) 787 delete mpLogFont; 788 789 if ( mpFontCharSets ) 790 delete mpFontCharSets; 791 792 if ( mpFontKernPairs ) 793 delete mpFontKernPairs; 794 } 795 796 // ----------------------------------------------------------------------- 797 798 void WinSalGraphics::GetResolution( long& rDPIX, long& rDPIY ) 799 { 800 rDPIX = GetDeviceCaps( mhDC, LOGPIXELSX ); 801 rDPIY = GetDeviceCaps( mhDC, LOGPIXELSY ); 802 803 // #111139# this fixes the symptom of div by zero on startup 804 // however, printing will fail most likely as communication with 805 // the printer seems not to work in this case 806 if( !rDPIX || !rDPIY ) 807 rDPIX = rDPIY = 600; 808 } 809 810 // ----------------------------------------------------------------------- 811 812 sal_uInt16 WinSalGraphics::GetBitCount() 813 { 814 return (sal_uInt16)GetDeviceCaps( mhDC, BITSPIXEL ); 815 } 816 817 // ----------------------------------------------------------------------- 818 819 long WinSalGraphics::GetGraphicsWidth() const 820 { 821 if( mhWnd && IsWindow( mhWnd ) ) 822 { 823 WinSalFrame* pFrame = GetWindowPtr( mhWnd ); 824 if( pFrame ) 825 { 826 if( pFrame->maGeometry.nWidth ) 827 return pFrame->maGeometry.nWidth; 828 else 829 { 830 // TODO: perhaps not needed, maGeometry should always be up-to-date 831 RECT aRect; 832 GetClientRect( mhWnd, &aRect ); 833 return aRect.right; 834 } 835 } 836 } 837 838 return 0; 839 } 840 841 // ----------------------------------------------------------------------- 842 843 void WinSalGraphics::ResetClipRegion() 844 { 845 if ( mhRegion ) 846 { 847 DeleteRegion( mhRegion ); 848 mhRegion = 0; 849 } 850 851 SelectClipRgn( mhDC, 0 ); 852 } 853 854 // ----------------------------------------------------------------------- 855 856 bool WinSalGraphics::setClipRegion( const Region& i_rClip ) 857 { 858 if ( mhRegion ) 859 { 860 DeleteRegion( mhRegion ); 861 mhRegion = 0; 862 } 863 864 if( i_rClip.HasPolyPolygon() ) 865 { 866 // TODO: ConvertToB2DPolyPolygon actually is kind of const, just it does not advertise it in the header 867 basegfx::B2DPolyPolygon aPolyPolygon( const_cast<Region&>(i_rClip).ConvertToB2DPolyPolygon() ); 868 const sal_uInt32 nCount(aPolyPolygon.count()); 869 870 if( nCount ) 871 { 872 std::vector< POINT > aPolyPoints; 873 aPolyPoints.reserve( 1024 ); 874 std::vector< INT > aPolyCounts( nCount, 0 ); 875 for(sal_uInt32 a(0); a < nCount; a++) 876 { 877 basegfx::B2DPolygon aPoly( aPolyPolygon.getB2DPolygon(a) ); 878 aPoly = basegfx::tools::adaptiveSubdivideByDistance( aPoly, 1 ); 879 const sal_uInt32 nPoints = aPoly.count(); 880 aPolyCounts[a] = nPoints; 881 for( sal_uInt32 b = 0; b < nPoints; b++ ) 882 { 883 basegfx::B2DPoint aPt( aPoly.getB2DPoint( b ) ); 884 POINT aPOINT; 885 aPOINT.x = (LONG)aPt.getX(); 886 aPOINT.y = (LONG)aPt.getY(); 887 aPolyPoints.push_back( aPOINT ); 888 } 889 } 890 mhRegion = CreatePolyPolygonRgn( &aPolyPoints[0], &aPolyCounts[0], nCount, ALTERNATE ); 891 } 892 } 893 else 894 { 895 ULONG nRectCount = i_rClip.GetRectCount(); 896 897 ULONG nRectBufSize = sizeof(RECT)*nRectCount; 898 if ( nRectCount < SAL_CLIPRECT_COUNT ) 899 { 900 if ( !mpStdClipRgnData ) 901 mpStdClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+(SAL_CLIPRECT_COUNT*sizeof(RECT))]; 902 mpClipRgnData = mpStdClipRgnData; 903 } 904 else 905 mpClipRgnData = (RGNDATA*)new BYTE[sizeof(RGNDATA)-1+nRectBufSize]; 906 mpClipRgnData->rdh.dwSize = sizeof( RGNDATAHEADER ); 907 mpClipRgnData->rdh.iType = RDH_RECTANGLES; 908 mpClipRgnData->rdh.nCount = nRectCount; 909 mpClipRgnData->rdh.nRgnSize = nRectBufSize; 910 RECT* pBoundRect = &(mpClipRgnData->rdh.rcBound); 911 SetRectEmpty( pBoundRect ); 912 RECT* pNextClipRect = (RECT*)(&(mpClipRgnData->Buffer)); 913 bool bFirstClipRect = true; 914 915 ImplRegionInfo aInfo; 916 long nX, nY, nW, nH; 917 bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH ); 918 while( bRegionRect ) 919 { 920 if ( nW && nH ) 921 { 922 long nRight = nX + nW; 923 long nBottom = nY + nH; 924 925 if ( bFirstClipRect ) 926 { 927 pBoundRect->left = nX; 928 pBoundRect->top = nY; 929 pBoundRect->right = nRight; 930 pBoundRect->bottom = nBottom; 931 bFirstClipRect = false; 932 } 933 else 934 { 935 if ( nX < pBoundRect->left ) 936 pBoundRect->left = (int)nX; 937 938 if ( nY < pBoundRect->top ) 939 pBoundRect->top = (int)nY; 940 941 if ( nRight > pBoundRect->right ) 942 pBoundRect->right = (int)nRight; 943 944 if ( nBottom > pBoundRect->bottom ) 945 pBoundRect->bottom = (int)nBottom; 946 } 947 948 pNextClipRect->left = (int)nX; 949 pNextClipRect->top = (int)nY; 950 pNextClipRect->right = (int)nRight; 951 pNextClipRect->bottom = (int)nBottom; 952 pNextClipRect++; 953 } 954 else 955 { 956 mpClipRgnData->rdh.nCount--; 957 mpClipRgnData->rdh.nRgnSize -= sizeof( RECT ); 958 } 959 bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH ); 960 } 961 // create clip region from ClipRgnData 962 if ( mpClipRgnData->rdh.nCount == 1 ) 963 { 964 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 965 mhRegion = CreateRectRgn( pRect->left, pRect->top, 966 pRect->right, pRect->bottom ); 967 } 968 else if( mpClipRgnData->rdh.nCount > 1 ) 969 { 970 ULONG nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); 971 mhRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData ); 972 973 // if ExtCreateRegion(...) is not supported 974 if( !mhRegion ) 975 { 976 RGNDATAHEADER* pHeader = (RGNDATAHEADER*) mpClipRgnData; 977 978 if( pHeader->nCount ) 979 { 980 RECT* pRect = (RECT*) mpClipRgnData->Buffer; 981 mhRegion = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); 982 pRect++; 983 984 for( ULONG n = 1; n < pHeader->nCount; n++, pRect++ ) 985 { 986 HRGN hRgn = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); 987 CombineRgn( mhRegion, mhRegion, hRgn, RGN_OR ); 988 DeleteRegion( hRgn ); 989 } 990 } 991 } 992 993 if ( mpClipRgnData != mpStdClipRgnData ) 994 delete [] mpClipRgnData; 995 } 996 } 997 998 if( mhRegion ) 999 SelectClipRgn( mhDC, mhRegion ); 1000 return mhRegion != 0; 1001 } 1002 1003 // ----------------------------------------------------------------------- 1004 1005 void WinSalGraphics::SetLineColor() 1006 { 1007 // create and select new pen 1008 HPEN hNewPen = GetStockPen( NULL_PEN ); 1009 HPEN hOldPen = SelectPen( mhDC, hNewPen ); 1010 1011 // destory or save old pen 1012 if ( mhPen ) 1013 { 1014 if ( !mbStockPen ) 1015 DeletePen( mhPen ); 1016 } 1017 else 1018 mhDefPen = hOldPen; 1019 1020 // set new data 1021 mhPen = hNewPen; 1022 mbPen = FALSE; 1023 mbStockPen = TRUE; 1024 } 1025 1026 // ----------------------------------------------------------------------- 1027 1028 void WinSalGraphics::SetLineColor( SalColor nSalColor ) 1029 { 1030 maLineColor = nSalColor; 1031 COLORREF nPenColor = PALETTERGB( SALCOLOR_RED( nSalColor ), 1032 SALCOLOR_GREEN( nSalColor ), 1033 SALCOLOR_BLUE( nSalColor ) ); 1034 HPEN hNewPen = 0; 1035 sal_Bool bStockPen = FALSE; 1036 1037 // search for stock pen (only screen, because printer have problems, 1038 // when we use stock objects) 1039 if ( !mbPrinter ) 1040 { 1041 SalData* pSalData = GetSalData(); 1042 for ( sal_uInt16 i = 0; i < pSalData->mnStockPenCount; i++ ) 1043 { 1044 if ( nPenColor == pSalData->maStockPenColorAry[i] ) 1045 { 1046 hNewPen = pSalData->mhStockPenAry[i]; 1047 bStockPen = TRUE; 1048 break; 1049 } 1050 } 1051 } 1052 1053 // create new pen 1054 if ( !hNewPen ) 1055 { 1056 if ( !mbPrinter ) 1057 { 1058 if ( GetSalData()->mhDitherPal && ImplIsSysColorEntry( nSalColor ) ) 1059 nPenColor = PALRGB_TO_RGB( nPenColor ); 1060 } 1061 1062 hNewPen = CreatePen( PS_SOLID, mnPenWidth, nPenColor ); 1063 bStockPen = FALSE; 1064 } 1065 1066 // select new pen 1067 HPEN hOldPen = SelectPen( mhDC, hNewPen ); 1068 1069 // destory or save old pen 1070 if ( mhPen ) 1071 { 1072 if ( !mbStockPen ) 1073 DeletePen( mhPen ); 1074 } 1075 else 1076 mhDefPen = hOldPen; 1077 1078 // set new data 1079 mnPenColor = nPenColor; 1080 mhPen = hNewPen; 1081 mbPen = TRUE; 1082 mbStockPen = bStockPen; 1083 } 1084 1085 // ----------------------------------------------------------------------- 1086 1087 void WinSalGraphics::SetFillColor() 1088 { 1089 // create and select new brush 1090 HBRUSH hNewBrush = GetStockBrush( NULL_BRUSH ); 1091 HBRUSH hOldBrush = SelectBrush( mhDC, hNewBrush ); 1092 1093 // destory or save old brush 1094 if ( mhBrush ) 1095 { 1096 if ( !mbStockBrush ) 1097 DeleteBrush( mhBrush ); 1098 } 1099 else 1100 mhDefBrush = hOldBrush; 1101 1102 // set new data 1103 mhBrush = hNewBrush; 1104 mbBrush = FALSE; 1105 mbStockBrush = TRUE; 1106 } 1107 1108 // ----------------------------------------------------------------------- 1109 1110 void WinSalGraphics::SetFillColor( SalColor nSalColor ) 1111 { 1112 maFillColor = nSalColor; 1113 SalData* pSalData = GetSalData(); 1114 BYTE nRed = SALCOLOR_RED( nSalColor ); 1115 BYTE nGreen = SALCOLOR_GREEN( nSalColor ); 1116 BYTE nBlue = SALCOLOR_BLUE( nSalColor ); 1117 COLORREF nBrushColor = PALETTERGB( nRed, nGreen, nBlue ); 1118 HBRUSH hNewBrush = 0; 1119 sal_Bool bStockBrush = FALSE; 1120 1121 // search for stock brush (only screen, because printer have problems, 1122 // when we use stock objects) 1123 if ( !mbPrinter ) 1124 { 1125 for ( sal_uInt16 i = 0; i < pSalData->mnStockBrushCount; i++ ) 1126 { 1127 if ( nBrushColor == pSalData->maStockBrushColorAry[ i ] ) 1128 { 1129 hNewBrush = pSalData->mhStockBrushAry[i]; 1130 bStockBrush = TRUE; 1131 break; 1132 } 1133 } 1134 } 1135 1136 // create new brush 1137 if ( !hNewBrush ) 1138 { 1139 if ( mbPrinter || !pSalData->mhDitherDIB ) 1140 hNewBrush = CreateSolidBrush( nBrushColor ); 1141 else 1142 { 1143 if ( 24 == ((BITMAPINFOHEADER*)pSalData->mpDitherDIB)->biBitCount ) 1144 { 1145 BYTE* pTmp = pSalData->mpDitherDIBData; 1146 long* pDitherDiff = pSalData->mpDitherDiff; 1147 BYTE* pDitherLow = pSalData->mpDitherLow; 1148 BYTE* pDitherHigh = pSalData->mpDitherHigh; 1149 1150 for( long nY = 0L; nY < 8L; nY++ ) 1151 { 1152 for( long nX = 0L; nX < 8L; nX++ ) 1153 { 1154 const long nThres = aOrdDither16Bit[ nY ][ nX ]; 1155 *pTmp++ = DMAP( nBlue, nThres ); 1156 *pTmp++ = DMAP( nGreen, nThres ); 1157 *pTmp++ = DMAP( nRed, nThres ); 1158 } 1159 } 1160 1161 hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_RGB_COLORS ); 1162 } 1163 else if ( ImplIsSysColorEntry( nSalColor ) ) 1164 { 1165 nBrushColor = PALRGB_TO_RGB( nBrushColor ); 1166 hNewBrush = CreateSolidBrush( nBrushColor ); 1167 } 1168 else if ( ImplIsPaletteEntry( nRed, nGreen, nBlue ) ) 1169 hNewBrush = CreateSolidBrush( nBrushColor ); 1170 else 1171 { 1172 BYTE* pTmp = pSalData->mpDitherDIBData; 1173 long* pDitherDiff = pSalData->mpDitherDiff; 1174 BYTE* pDitherLow = pSalData->mpDitherLow; 1175 BYTE* pDitherHigh = pSalData->mpDitherHigh; 1176 1177 for ( long nY = 0L; nY < 8L; nY++ ) 1178 { 1179 for ( long nX = 0L; nX < 8L; nX++ ) 1180 { 1181 const long nThres = aOrdDither8Bit[ nY ][ nX ]; 1182 *pTmp = DMAP( nRed, nThres ) + DMAP( nGreen, nThres ) * 6 + DMAP( nBlue, nThres ) * 36; 1183 pTmp++; 1184 } 1185 } 1186 1187 hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_PAL_COLORS ); 1188 } 1189 } 1190 1191 bStockBrush = FALSE; 1192 } 1193 1194 // select new brush 1195 HBRUSH hOldBrush = SelectBrush( mhDC, hNewBrush ); 1196 1197 // destory or save old brush 1198 if ( mhBrush ) 1199 { 1200 if ( !mbStockBrush ) 1201 DeleteBrush( mhBrush ); 1202 } 1203 else 1204 mhDefBrush = hOldBrush; 1205 1206 // set new data 1207 mnBrushColor = nBrushColor; 1208 mhBrush = hNewBrush; 1209 mbBrush = TRUE; 1210 mbStockBrush = bStockBrush; 1211 } 1212 1213 // ----------------------------------------------------------------------- 1214 1215 void WinSalGraphics::SetXORMode( bool bSet, bool ) 1216 { 1217 mbXORMode = bSet; 1218 ::SetROP2( mhDC, bSet ? R2_XORPEN : R2_COPYPEN ); 1219 } 1220 1221 // ----------------------------------------------------------------------- 1222 1223 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor ) 1224 { 1225 SetLineColor( ImplGetROPSalColor( nROPColor ) ); 1226 } 1227 1228 // ----------------------------------------------------------------------- 1229 1230 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor ) 1231 { 1232 SetFillColor( ImplGetROPSalColor( nROPColor ) ); 1233 } 1234 1235 // ----------------------------------------------------------------------- 1236 1237 void WinSalGraphics::drawPixel( long nX, long nY ) 1238 { 1239 if ( mbXORMode ) 1240 { 1241 HBRUSH hBrush = CreateSolidBrush( mnPenColor ); 1242 HBRUSH hOldBrush = SelectBrush( mhDC, hBrush ); 1243 PatBlt( mhDC, (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); 1244 SelectBrush( mhDC, hOldBrush ); 1245 DeleteBrush( hBrush ); 1246 } 1247 else 1248 SetPixel( mhDC, (int)nX, (int)nY, mnPenColor ); 1249 } 1250 1251 // ----------------------------------------------------------------------- 1252 1253 void WinSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) 1254 { 1255 COLORREF nCol = PALETTERGB( SALCOLOR_RED( nSalColor ), 1256 SALCOLOR_GREEN( nSalColor ), 1257 SALCOLOR_BLUE( nSalColor ) ); 1258 1259 if ( !mbPrinter && 1260 GetSalData()->mhDitherPal && 1261 ImplIsSysColorEntry( nSalColor ) ) 1262 nCol = PALRGB_TO_RGB( nCol ); 1263 1264 if ( mbXORMode ) 1265 { 1266 HBRUSH hBrush = CreateSolidBrush( nCol ); 1267 HBRUSH hOldBrush = SelectBrush( mhDC, hBrush ); 1268 PatBlt( mhDC, (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); 1269 SelectBrush( mhDC, hOldBrush ); 1270 DeleteBrush( hBrush ); 1271 } 1272 else 1273 ::SetPixel( mhDC, (int)nX, (int)nY, nCol ); 1274 } 1275 1276 // ----------------------------------------------------------------------- 1277 1278 void WinSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) 1279 { 1280 MoveToEx( mhDC, (int)nX1, (int)nY1, NULL ); 1281 1282 // we must paint the endpoint 1283 int bPaintEnd = TRUE; 1284 if ( nX1 == nX2 ) 1285 { 1286 bPaintEnd = FALSE; 1287 if ( nY1 <= nY2 ) 1288 nY2++; 1289 else 1290 nY2--; 1291 } 1292 if ( nY1 == nY2 ) 1293 { 1294 bPaintEnd = FALSE; 1295 if ( nX1 <= nX2 ) 1296 nX2++; 1297 else 1298 nX2--; 1299 } 1300 1301 LineTo( mhDC, (int)nX2, (int)nY2 ); 1302 1303 if ( bPaintEnd && !mbPrinter ) 1304 { 1305 if ( mbXORMode ) 1306 { 1307 HBRUSH hBrush = CreateSolidBrush( mnPenColor ); 1308 HBRUSH hOldBrush = SelectBrush( mhDC, hBrush ); 1309 PatBlt( mhDC, (int)nX2, (int)nY2, (int)1, (int)1, PATINVERT ); 1310 SelectBrush( mhDC, hOldBrush ); 1311 DeleteBrush( hBrush ); 1312 } 1313 else 1314 SetPixel( mhDC, (int)nX2, (int)nY2, mnPenColor ); 1315 } 1316 } 1317 1318 // ----------------------------------------------------------------------- 1319 1320 void WinSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) 1321 { 1322 if ( !mbPen ) 1323 { 1324 if ( !mbPrinter ) 1325 { 1326 PatBlt( mhDC, (int)nX, (int)nY, (int)nWidth, (int)nHeight, 1327 mbXORMode ? PATINVERT : PATCOPY ); 1328 } 1329 else 1330 { 1331 RECT aWinRect; 1332 aWinRect.left = nX; 1333 aWinRect.top = nY; 1334 aWinRect.right = nX+nWidth; 1335 aWinRect.bottom = nY+nHeight; 1336 ::FillRect( mhDC, &aWinRect, mhBrush ); 1337 } 1338 } 1339 else 1340 WIN_Rectangle( mhDC, (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); 1341 } 1342 1343 // ----------------------------------------------------------------------- 1344 1345 void WinSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry ) 1346 { 1347 // Unter NT koennen wir das Array direkt weiterreichen 1348 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1349 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" ); 1350 1351 POINT* pWinPtAry = (POINT*)pPtAry; 1352 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl 1353 // von Punkten 1354 if ( !Polyline( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 1355 Polyline( mhDC, pWinPtAry, MAX_64KSALPOINTS ); 1356 } 1357 1358 // ----------------------------------------------------------------------- 1359 1360 void WinSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry ) 1361 { 1362 // Unter NT koennen wir das Array direkt weiterreichen 1363 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1364 "WinSalGraphics::DrawPolygon(): POINT != SalPoint" ); 1365 1366 POINT* pWinPtAry = (POINT*)pPtAry; 1367 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl 1368 // von Punkten 1369 if ( !WIN_Polygon( mhDC, pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 1370 WIN_Polygon( mhDC, pWinPtAry, MAX_64KSALPOINTS ); 1371 } 1372 1373 // ----------------------------------------------------------------------- 1374 1375 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, 1376 PCONSTSALPOINT* pPtAry ) 1377 { 1378 UINT aWinPointAry[SAL_POLYPOLYCOUNT_STACKBUF]; 1379 UINT* pWinPointAry; 1380 UINT nPolyPolyPoints = 0; 1381 UINT nPoints; 1382 UINT i; 1383 1384 if ( nPoly <= SAL_POLYPOLYCOUNT_STACKBUF ) 1385 pWinPointAry = aWinPointAry; 1386 else 1387 pWinPointAry = new UINT[nPoly]; 1388 1389 for ( i = 0; i < (UINT)nPoly; i++ ) 1390 { 1391 nPoints = (UINT)pPoints[i]+1; 1392 pWinPointAry[i] = nPoints; 1393 nPolyPolyPoints += nPoints; 1394 } 1395 1396 POINT aWinPointAryAry[SAL_POLYPOLYPOINTS_STACKBUF]; 1397 POINT* pWinPointAryAry; 1398 if ( nPolyPolyPoints <= SAL_POLYPOLYPOINTS_STACKBUF ) 1399 pWinPointAryAry = aWinPointAryAry; 1400 else 1401 pWinPointAryAry = new POINT[nPolyPolyPoints]; 1402 // Unter NT koennen wir das Array direkt weiterreichen 1403 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1404 "WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" ); 1405 const SalPoint* pPolyAry; 1406 UINT n = 0; 1407 for ( i = 0; i < (UINT)nPoly; i++ ) 1408 { 1409 nPoints = pWinPointAry[i]; 1410 pPolyAry = pPtAry[i]; 1411 memcpy( pWinPointAryAry+n, pPolyAry, (nPoints-1)*sizeof(POINT) ); 1412 pWinPointAryAry[n+nPoints-1] = pWinPointAryAry[n]; 1413 n += nPoints; 1414 } 1415 1416 if ( !WIN_PolyPolygon( mhDC, pWinPointAryAry, (int*)pWinPointAry, (UINT)nPoly ) && 1417 (nPolyPolyPoints > MAX_64KSALPOINTS) ) 1418 { 1419 nPolyPolyPoints = 0; 1420 nPoly = 0; 1421 do 1422 { 1423 nPolyPolyPoints += pWinPointAry[(UINT)nPoly]; 1424 nPoly++; 1425 } 1426 while ( nPolyPolyPoints < MAX_64KSALPOINTS ); 1427 nPoly--; 1428 if ( pWinPointAry[(UINT)nPoly] > MAX_64KSALPOINTS ) 1429 pWinPointAry[(UINT)nPoly] = MAX_64KSALPOINTS; 1430 if ( nPoly == 1 ) 1431 WIN_Polygon( mhDC, pWinPointAryAry, *pWinPointAry ); 1432 else 1433 WIN_PolyPolygon( mhDC, pWinPointAryAry, (int*)pWinPointAry, nPoly ); 1434 } 1435 1436 if ( pWinPointAry != aWinPointAry ) 1437 delete [] pWinPointAry; 1438 if ( pWinPointAryAry != aWinPointAryAry ) 1439 delete [] pWinPointAryAry; 1440 } 1441 1442 // ----------------------------------------------------------------------- 1443 1444 #define SAL_POLY_STACKBUF 32 1445 1446 // ----------------------------------------------------------------------- 1447 1448 sal_Bool WinSalGraphics::drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 1449 { 1450 #ifdef USE_GDI_BEZIERS 1451 // Unter NT koennen wir das Array direkt weiterreichen 1452 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1453 "WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" ); 1454 1455 ImplRenderPath( mhDC, nPoints, pPtAry, pFlgAry ); 1456 1457 return sal_True; 1458 #else 1459 return sal_False; 1460 #endif 1461 } 1462 1463 // ----------------------------------------------------------------------- 1464 1465 sal_Bool WinSalGraphics::drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 1466 { 1467 #ifdef USE_GDI_BEZIERS 1468 // Unter NT koennen wir das Array direkt weiterreichen 1469 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1470 "WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" ); 1471 1472 POINT aStackAry1[SAL_POLY_STACKBUF]; 1473 BYTE aStackAry2[SAL_POLY_STACKBUF]; 1474 POINT* pWinPointAry; 1475 BYTE* pWinFlagAry; 1476 if( nPoints > SAL_POLY_STACKBUF ) 1477 { 1478 pWinPointAry = new POINT[ nPoints ]; 1479 pWinFlagAry = new BYTE[ nPoints ]; 1480 } 1481 else 1482 { 1483 pWinPointAry = aStackAry1; 1484 pWinFlagAry = aStackAry2; 1485 } 1486 1487 ImplPreparePolyDraw(true, 1, &nPoints, &pPtAry, &pFlgAry, pWinPointAry, pWinFlagAry); 1488 1489 sal_Bool bRet( sal_False ); 1490 1491 if( BeginPath( mhDC ) ) 1492 { 1493 PolyDraw(mhDC, pWinPointAry, pWinFlagAry, nPoints); 1494 1495 if( EndPath( mhDC ) ) 1496 { 1497 if( StrokeAndFillPath( mhDC ) ) 1498 bRet = sal_True; 1499 } 1500 } 1501 1502 if( pWinPointAry != aStackAry1 ) 1503 { 1504 delete [] pWinPointAry; 1505 delete [] pWinFlagAry; 1506 } 1507 1508 return bRet; 1509 #else 1510 return sal_False; 1511 #endif 1512 } 1513 1514 // ----------------------------------------------------------------------- 1515 1516 sal_Bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, 1517 const SalPoint* const* pPtAry, const BYTE* const* pFlgAry ) 1518 { 1519 #ifdef USE_GDI_BEZIERS 1520 // Unter NT koennen wir das Array direkt weiterreichen 1521 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1522 "WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" ); 1523 1524 sal_uLong nCurrPoly, nTotalPoints; 1525 const sal_uLong* pCurrPoints = pPoints; 1526 for( nCurrPoly=0, nTotalPoints=0; nCurrPoly<nPoly; ++nCurrPoly ) 1527 nTotalPoints += *pCurrPoints++; 1528 1529 POINT aStackAry1[SAL_POLY_STACKBUF]; 1530 BYTE aStackAry2[SAL_POLY_STACKBUF]; 1531 POINT* pWinPointAry; 1532 BYTE* pWinFlagAry; 1533 if( nTotalPoints > SAL_POLY_STACKBUF ) 1534 { 1535 pWinPointAry = new POINT[ nTotalPoints ]; 1536 pWinFlagAry = new BYTE[ nTotalPoints ]; 1537 } 1538 else 1539 { 1540 pWinPointAry = aStackAry1; 1541 pWinFlagAry = aStackAry2; 1542 } 1543 1544 ImplPreparePolyDraw(true, nPoly, pPoints, pPtAry, pFlgAry, pWinPointAry, pWinFlagAry); 1545 1546 sal_Bool bRet( sal_False ); 1547 1548 if( BeginPath( mhDC ) ) 1549 { 1550 PolyDraw(mhDC, pWinPointAry, pWinFlagAry, nTotalPoints); 1551 1552 if( EndPath( mhDC ) ) 1553 { 1554 if( StrokeAndFillPath( mhDC ) ) 1555 bRet = sal_True; 1556 } 1557 } 1558 1559 if( pWinPointAry != aStackAry1 ) 1560 { 1561 delete [] pWinPointAry; 1562 delete [] pWinFlagAry; 1563 } 1564 1565 return bRet; 1566 #else 1567 return sal_False; 1568 #endif 1569 } 1570 1571 // ----------------------------------------------------------------------- 1572 1573 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF 1574 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox 1575 // in the first 4096 bytes 1576 1577 static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, sal_uLong nComp, sal_uLong nSize ) 1578 { 1579 while ( nComp-- >= nSize ) 1580 { 1581 sal_uLong i; 1582 for ( i = 0; i < nSize; i++ ) 1583 { 1584 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) ) 1585 break; 1586 } 1587 if ( i == nSize ) 1588 return pSource; 1589 pSource++; 1590 } 1591 return NULL; 1592 } 1593 1594 static sal_Bool ImplGetBoundingBox( double* nNumb, BYTE* pSource, sal_uLong nSize ) 1595 { 1596 sal_Bool bRetValue = FALSE; 1597 BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 ); 1598 if ( pDest ) 1599 { 1600 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0; 1601 pDest += 14; 1602 1603 int nSizeLeft = nSize - ( pDest - pSource ); 1604 if ( nSizeLeft > 100 ) 1605 nSizeLeft = 100; // only 100 bytes following the bounding box will be checked 1606 1607 int i; 1608 for ( i = 0; ( i < 4 ) && nSizeLeft; i++ ) 1609 { 1610 int nDivision = 1; 1611 sal_Bool bDivision = FALSE; 1612 sal_Bool bNegative = FALSE; 1613 sal_Bool bValid = TRUE; 1614 1615 while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++; 1616 BYTE nByte = *pDest; 1617 while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) ) 1618 { 1619 switch ( nByte ) 1620 { 1621 case '.' : 1622 if ( bDivision ) 1623 bValid = FALSE; 1624 else 1625 bDivision = TRUE; 1626 break; 1627 case '-' : 1628 bNegative = TRUE; 1629 break; 1630 default : 1631 if ( ( nByte < '0' ) || ( nByte > '9' ) ) 1632 nSizeLeft = 1; // error parsing the bounding box values 1633 else if ( bValid ) 1634 { 1635 if ( bDivision ) 1636 nDivision*=10; 1637 nNumb[i] *= 10; 1638 nNumb[i] += nByte - '0'; 1639 } 1640 break; 1641 } 1642 nSizeLeft--; 1643 nByte = *(++pDest); 1644 } 1645 if ( bNegative ) 1646 nNumb[i] = -nNumb[i]; 1647 if ( bDivision && ( nDivision != 1 ) ) 1648 nNumb[i] /= nDivision; 1649 } 1650 if ( i == 4 ) 1651 bRetValue = TRUE; 1652 } 1653 return bRetValue; 1654 } 1655 1656 sal_Bool WinSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ) 1657 { 1658 sal_Bool bRetValue = FALSE; 1659 1660 if ( mbPrinter ) 1661 { 1662 int nEscape = POSTSCRIPT_PASSTHROUGH; 1663 1664 if ( Escape( mhDC, QUERYESCSUPPORT, sizeof( int ), ( LPSTR )&nEscape, 0 ) ) 1665 { 1666 double nBoundingBox[4]; 1667 1668 if ( ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) ) 1669 { 1670 OStringBuffer aBuf( POSTSCRIPT_BUFSIZE ); 1671 1672 // reserve place for a sal_uInt16 1673 aBuf.append( "aa" ); 1674 1675 // #107797# Write out EPS encapsulation header 1676 // ---------------------------------------------------------------------------------- 1677 1678 // directly taken from the PLRM 3.0, p. 726. Note: 1679 // this will definitely cause problems when 1680 // recursively creating and embedding PostScript files 1681 // in OOo, since we use statically-named variables 1682 // here (namely, b4_Inc_state_salWin, dict_count_salWin and 1683 // op_count_salWin). Currently, I have no idea on how to 1684 // work around that, except from scanning and 1685 // interpreting the EPS for unused identifiers. 1686 1687 // append the real text 1688 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n" 1689 "/dict_count_salWin countdictstack def\n" 1690 "/op_count_salWin count 1 sub def\n" 1691 "userdict begin\n" 1692 "/showpage {} def\n" 1693 "0 setgray 0 setlinecap\n" 1694 "1 setlinewidth 0 setlinejoin\n" 1695 "10 setmiterlimit [] 0 setdash newpath\n" 1696 "/languagelevel where\n" 1697 "{\n" 1698 " pop languagelevel\n" 1699 " 1 ne\n" 1700 " {\n" 1701 " false setstrokeadjust false setoverprint\n" 1702 " } if\n" 1703 "} if\n\n" ); 1704 1705 1706 // #i10737# Apply clipping manually 1707 // ---------------------------------------------------------------------------------- 1708 1709 // Windows seems to ignore any clipping at the HDC, 1710 // when followed by a POSTSCRIPT_PASSTHROUGH 1711 1712 // Check whether we've got a clipping, consisting of 1713 // exactly one rect (other cases should be, but aren't 1714 // handled currently) 1715 1716 // TODO: Handle more than one rectangle here (take 1717 // care, the buffer can handle only POSTSCRIPT_BUFSIZE 1718 // characters!) 1719 if ( mhRegion != 0 && 1720 mpStdClipRgnData != NULL && 1721 mpClipRgnData == mpStdClipRgnData && 1722 mpClipRgnData->rdh.nCount == 1 ) 1723 { 1724 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 1725 1726 aBuf.append( "\nnewpath\n" ); 1727 aBuf.append( pRect->left ); 1728 aBuf.append( " " ); 1729 aBuf.append( pRect->top ); 1730 aBuf.append( " moveto\n" ); 1731 aBuf.append( pRect->right ); 1732 aBuf.append( " " ); 1733 aBuf.append( pRect->top ); 1734 aBuf.append( " lineto\n" ); 1735 aBuf.append( pRect->right ); 1736 aBuf.append( " " ); 1737 aBuf.append( pRect->bottom ); 1738 aBuf.append( " lineto\n" ); 1739 aBuf.append( pRect->left ); 1740 aBuf.append( " " ); 1741 aBuf.append( pRect->bottom ); 1742 aBuf.append( " lineto\n" 1743 "closepath\n" 1744 "clip\n" 1745 "newpath\n" ); 1746 } 1747 1748 // #107797# Write out buffer 1749 // ---------------------------------------------------------------------------------- 1750 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); 1751 Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 1752 1753 1754 // #107797# Write out EPS transformation code 1755 // ---------------------------------------------------------------------------------- 1756 double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] ); 1757 double dM22 = nHeight / (nBoundingBox[1] - nBoundingBox[3] ); 1758 // reserve a sal_uInt16 again 1759 aBuf.setLength( 2 ); 1760 aBuf.append( "\n\n[" ); 1761 aBuf.append( dM11 ); 1762 aBuf.append( " 0 0 " ); 1763 aBuf.append( dM22 ); 1764 aBuf.append( ' ' ); 1765 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) ); 1766 aBuf.append( ' ' ); 1767 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) ); 1768 aBuf.append( "] concat\n" 1769 "%%BeginDocument:\n" ); 1770 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); 1771 Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 1772 1773 1774 // #107797# Write out actual EPS content 1775 // ---------------------------------------------------------------------------------- 1776 sal_uLong nToDo = nSize; 1777 sal_uLong nDoNow; 1778 while ( nToDo ) 1779 { 1780 nDoNow = nToDo; 1781 if ( nToDo > POSTSCRIPT_BUFSIZE - 2 ) 1782 nDoNow = POSTSCRIPT_BUFSIZE - 2; 1783 // the following is based on the string buffer allocation 1784 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf 1785 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)nDoNow; 1786 memcpy( (void*)(aBuf.getStr() + 2), (BYTE*)pPtr + nSize - nToDo, nDoNow ); 1787 sal_uLong nResult = Escape ( mhDC, nEscape, nDoNow + 2, (LPTSTR)aBuf.getStr(), 0 ); 1788 if (!nResult ) 1789 break; 1790 nToDo -= nResult; 1791 } 1792 1793 1794 // #107797# Write out EPS encapsulation footer 1795 // ---------------------------------------------------------------------------------- 1796 // reserve a sal_uInt16 again 1797 aBuf.setLength( 2 ); 1798 aBuf.append( "%%EndDocument\n" 1799 "count op_count_salWin sub {pop} repeat\n" 1800 "countdictstack dict_count_salWin sub {end} repeat\n" 1801 "b4_Inc_state_salWin restore\n\n" ); 1802 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); 1803 Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 1804 bRetValue = TRUE; 1805 } 1806 } 1807 } 1808 1809 return bRetValue; 1810 } 1811 1812 // ----------------------------------------------------------------------- 1813 1814 SystemGraphicsData WinSalGraphics::GetGraphicsData() const 1815 { 1816 SystemGraphicsData aRes; 1817 aRes.nSize = sizeof(aRes); 1818 aRes.hDC = mhDC; 1819 return aRes; 1820 } 1821 1822 // ----------------------------------------------------------------------- 1823