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