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