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( long& rDPIX, long& 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 ( mpClipRgnData->rdh.nCount == 1 ) 1021 { 1022 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 1023 mhRegion = CreateRectRgn( pRect->left, pRect->top, 1024 pRect->right, pRect->bottom ); 1025 } 1026 else if( mpClipRgnData->rdh.nCount > 1 ) 1027 { 1028 ULONG nSize = mpClipRgnData->rdh.nRgnSize+sizeof(RGNDATAHEADER); 1029 mhRegion = ExtCreateRegion( NULL, nSize, mpClipRgnData ); 1030 1031 // if ExtCreateRegion(...) is not supported 1032 if( !mhRegion ) 1033 { 1034 RGNDATAHEADER* pHeader = (RGNDATAHEADER*) mpClipRgnData; 1035 1036 if( pHeader->nCount ) 1037 { 1038 RECT* pRect = (RECT*) mpClipRgnData->Buffer; 1039 mhRegion = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); 1040 pRect++; 1041 1042 for( ULONG n = 1; n < pHeader->nCount; n++, pRect++ ) 1043 { 1044 HRGN hRgn = CreateRectRgn( pRect->left, pRect->top, pRect->right, pRect->bottom ); 1045 CombineRgn( mhRegion, mhRegion, hRgn, RGN_OR ); 1046 DeleteRegion( hRgn ); 1047 } 1048 } 1049 } 1050 1051 if ( mpClipRgnData != mpStdClipRgnData ) 1052 delete [] mpClipRgnData; 1053 } 1054 } 1055 1056 if( mhRegion ) 1057 { 1058 SelectClipRgn( getHDC(), mhRegion ); 1059 1060 // debug code if you weant to check range of the newly applied ClipRegion 1061 //RECT aBound; 1062 //const int aRegionType = GetRgnBox(mhRegion, &aBound); 1063 // 1064 //bool bBla = true; 1065 } 1066 1067 return mhRegion != 0; 1068 } 1069 1070 // ----------------------------------------------------------------------- 1071 1072 void WinSalGraphics::SetLineColor() 1073 { 1074 // create and select new pen 1075 HPEN hNewPen = GetStockPen( NULL_PEN ); 1076 HPEN hOldPen = SelectPen( getHDC(), hNewPen ); 1077 1078 // destory or save old pen 1079 if ( mhPen ) 1080 { 1081 if ( !mbStockPen ) 1082 DeletePen( mhPen ); 1083 } 1084 else 1085 mhDefPen = hOldPen; 1086 1087 // set new data 1088 mhPen = hNewPen; 1089 mbPen = FALSE; 1090 mbStockPen = TRUE; 1091 } 1092 1093 // ----------------------------------------------------------------------- 1094 1095 void WinSalGraphics::SetLineColor( SalColor nSalColor ) 1096 { 1097 maLineColor = nSalColor; 1098 COLORREF nPenColor = PALETTERGB( SALCOLOR_RED( nSalColor ), 1099 SALCOLOR_GREEN( nSalColor ), 1100 SALCOLOR_BLUE( nSalColor ) ); 1101 HPEN hNewPen = 0; 1102 sal_Bool bStockPen = FALSE; 1103 1104 // search for stock pen (only screen, because printer have problems, 1105 // when we use stock objects) 1106 if ( !mbPrinter ) 1107 { 1108 SalData* pSalData = GetSalData(); 1109 for ( sal_uInt16 i = 0; i < pSalData->mnStockPenCount; i++ ) 1110 { 1111 if ( nPenColor == pSalData->maStockPenColorAry[i] ) 1112 { 1113 hNewPen = pSalData->mhStockPenAry[i]; 1114 bStockPen = TRUE; 1115 break; 1116 } 1117 } 1118 } 1119 1120 // create new pen 1121 if ( !hNewPen ) 1122 { 1123 if ( !mbPrinter ) 1124 { 1125 if ( GetSalData()->mhDitherPal && ImplIsSysColorEntry( nSalColor ) ) 1126 nPenColor = PALRGB_TO_RGB( nPenColor ); 1127 } 1128 1129 hNewPen = CreatePen( PS_SOLID, mnPenWidth, nPenColor ); 1130 bStockPen = FALSE; 1131 } 1132 1133 // select new pen 1134 HPEN hOldPen = SelectPen( getHDC(), hNewPen ); 1135 1136 // destory or save old pen 1137 if ( mhPen ) 1138 { 1139 if ( !mbStockPen ) 1140 DeletePen( mhPen ); 1141 } 1142 else 1143 mhDefPen = hOldPen; 1144 1145 // set new data 1146 mnPenColor = nPenColor; 1147 mhPen = hNewPen; 1148 mbPen = TRUE; 1149 mbStockPen = bStockPen; 1150 } 1151 1152 // ----------------------------------------------------------------------- 1153 1154 void WinSalGraphics::SetFillColor() 1155 { 1156 // create and select new brush 1157 HBRUSH hNewBrush = GetStockBrush( NULL_BRUSH ); 1158 HBRUSH hOldBrush = SelectBrush( getHDC(), hNewBrush ); 1159 1160 // destory or save old brush 1161 if ( mhBrush ) 1162 { 1163 if ( !mbStockBrush ) 1164 DeleteBrush( mhBrush ); 1165 } 1166 else 1167 mhDefBrush = hOldBrush; 1168 1169 // set new data 1170 mhBrush = hNewBrush; 1171 mbBrush = FALSE; 1172 mbStockBrush = TRUE; 1173 } 1174 1175 // ----------------------------------------------------------------------- 1176 1177 void WinSalGraphics::SetFillColor( SalColor nSalColor ) 1178 { 1179 maFillColor = nSalColor; 1180 SalData* pSalData = GetSalData(); 1181 BYTE nRed = SALCOLOR_RED( nSalColor ); 1182 BYTE nGreen = SALCOLOR_GREEN( nSalColor ); 1183 BYTE nBlue = SALCOLOR_BLUE( nSalColor ); 1184 COLORREF nBrushColor = PALETTERGB( nRed, nGreen, nBlue ); 1185 HBRUSH hNewBrush = 0; 1186 sal_Bool bStockBrush = FALSE; 1187 1188 // search for stock brush (only screen, because printer have problems, 1189 // when we use stock objects) 1190 if ( !mbPrinter ) 1191 { 1192 for ( sal_uInt16 i = 0; i < pSalData->mnStockBrushCount; i++ ) 1193 { 1194 if ( nBrushColor == pSalData->maStockBrushColorAry[ i ] ) 1195 { 1196 hNewBrush = pSalData->mhStockBrushAry[i]; 1197 bStockBrush = TRUE; 1198 break; 1199 } 1200 } 1201 } 1202 1203 // create new brush 1204 if ( !hNewBrush ) 1205 { 1206 if ( mbPrinter || !pSalData->mhDitherDIB ) 1207 hNewBrush = CreateSolidBrush( nBrushColor ); 1208 else 1209 { 1210 if ( 24 == ((BITMAPINFOHEADER*)pSalData->mpDitherDIB)->biBitCount ) 1211 { 1212 BYTE* pTmp = pSalData->mpDitherDIBData; 1213 long* pDitherDiff = pSalData->mpDitherDiff; 1214 BYTE* pDitherLow = pSalData->mpDitherLow; 1215 BYTE* pDitherHigh = pSalData->mpDitherHigh; 1216 1217 for( long nY = 0L; nY < 8L; nY++ ) 1218 { 1219 for( long nX = 0L; nX < 8L; nX++ ) 1220 { 1221 const long nThres = aOrdDither16Bit[ nY ][ nX ]; 1222 *pTmp++ = DMAP( nBlue, nThres ); 1223 *pTmp++ = DMAP( nGreen, nThres ); 1224 *pTmp++ = DMAP( nRed, nThres ); 1225 } 1226 } 1227 1228 hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_RGB_COLORS ); 1229 } 1230 else if ( ImplIsSysColorEntry( nSalColor ) ) 1231 { 1232 nBrushColor = PALRGB_TO_RGB( nBrushColor ); 1233 hNewBrush = CreateSolidBrush( nBrushColor ); 1234 } 1235 else if ( ImplIsPaletteEntry( nRed, nGreen, nBlue ) ) 1236 hNewBrush = CreateSolidBrush( nBrushColor ); 1237 else 1238 { 1239 BYTE* pTmp = pSalData->mpDitherDIBData; 1240 long* pDitherDiff = pSalData->mpDitherDiff; 1241 BYTE* pDitherLow = pSalData->mpDitherLow; 1242 BYTE* pDitherHigh = pSalData->mpDitherHigh; 1243 1244 for ( long nY = 0L; nY < 8L; nY++ ) 1245 { 1246 for ( long nX = 0L; nX < 8L; nX++ ) 1247 { 1248 const long nThres = aOrdDither8Bit[ nY ][ nX ]; 1249 *pTmp = DMAP( nRed, nThres ) + DMAP( nGreen, nThres ) * 6 + DMAP( nBlue, nThres ) * 36; 1250 pTmp++; 1251 } 1252 } 1253 1254 hNewBrush = CreateDIBPatternBrush( pSalData->mhDitherDIB, DIB_PAL_COLORS ); 1255 } 1256 } 1257 1258 bStockBrush = FALSE; 1259 } 1260 1261 // select new brush 1262 HBRUSH hOldBrush = SelectBrush( getHDC(), hNewBrush ); 1263 1264 // destory or save old brush 1265 if ( mhBrush ) 1266 { 1267 if ( !mbStockBrush ) 1268 DeleteBrush( mhBrush ); 1269 } 1270 else 1271 mhDefBrush = hOldBrush; 1272 1273 // set new data 1274 mnBrushColor = nBrushColor; 1275 mhBrush = hNewBrush; 1276 mbBrush = TRUE; 1277 mbStockBrush = bStockBrush; 1278 } 1279 1280 // ----------------------------------------------------------------------- 1281 1282 void WinSalGraphics::SetXORMode( bool bSet, bool ) 1283 { 1284 mbXORMode = bSet; 1285 ::SetROP2( getHDC(), bSet ? R2_XORPEN : R2_COPYPEN ); 1286 } 1287 1288 // ----------------------------------------------------------------------- 1289 1290 void WinSalGraphics::SetROPLineColor( SalROPColor nROPColor ) 1291 { 1292 SetLineColor( ImplGetROPSalColor( nROPColor ) ); 1293 } 1294 1295 // ----------------------------------------------------------------------- 1296 1297 void WinSalGraphics::SetROPFillColor( SalROPColor nROPColor ) 1298 { 1299 SetFillColor( ImplGetROPSalColor( nROPColor ) ); 1300 } 1301 1302 // ----------------------------------------------------------------------- 1303 1304 void WinSalGraphics::drawPixel( long nX, long nY ) 1305 { 1306 if ( mbXORMode ) 1307 { 1308 HBRUSH hBrush = CreateSolidBrush( mnPenColor ); 1309 HBRUSH hOldBrush = SelectBrush( getHDC(), hBrush ); 1310 PatBlt( getHDC(), (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); 1311 SelectBrush( getHDC(), hOldBrush ); 1312 DeleteBrush( hBrush ); 1313 } 1314 else 1315 SetPixel( getHDC(), (int)nX, (int)nY, mnPenColor ); 1316 } 1317 1318 // ----------------------------------------------------------------------- 1319 1320 void WinSalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) 1321 { 1322 COLORREF nCol = PALETTERGB( SALCOLOR_RED( nSalColor ), 1323 SALCOLOR_GREEN( nSalColor ), 1324 SALCOLOR_BLUE( nSalColor ) ); 1325 1326 if ( !mbPrinter && 1327 GetSalData()->mhDitherPal && 1328 ImplIsSysColorEntry( nSalColor ) ) 1329 nCol = PALRGB_TO_RGB( nCol ); 1330 1331 if ( mbXORMode ) 1332 { 1333 HBRUSH hBrush = CreateSolidBrush( nCol ); 1334 HBRUSH hOldBrush = SelectBrush( getHDC(), hBrush ); 1335 PatBlt( getHDC(), (int)nX, (int)nY, (int)1, (int)1, PATINVERT ); 1336 SelectBrush( getHDC(), hOldBrush ); 1337 DeleteBrush( hBrush ); 1338 } 1339 else 1340 ::SetPixel( getHDC(), (int)nX, (int)nY, nCol ); 1341 } 1342 1343 // ----------------------------------------------------------------------- 1344 1345 void WinSalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) 1346 { 1347 MoveToEx( getHDC(), (int)nX1, (int)nY1, NULL ); 1348 1349 // we must paint the endpoint 1350 int bPaintEnd = TRUE; 1351 if ( nX1 == nX2 ) 1352 { 1353 bPaintEnd = FALSE; 1354 if ( nY1 <= nY2 ) 1355 nY2++; 1356 else 1357 nY2--; 1358 } 1359 if ( nY1 == nY2 ) 1360 { 1361 bPaintEnd = FALSE; 1362 if ( nX1 <= nX2 ) 1363 nX2++; 1364 else 1365 nX2--; 1366 } 1367 1368 LineTo( getHDC(), (int)nX2, (int)nY2 ); 1369 1370 if ( bPaintEnd && !mbPrinter ) 1371 { 1372 if ( mbXORMode ) 1373 { 1374 HBRUSH hBrush = CreateSolidBrush( mnPenColor ); 1375 HBRUSH hOldBrush = SelectBrush( getHDC(), hBrush ); 1376 PatBlt( getHDC(), (int)nX2, (int)nY2, (int)1, (int)1, PATINVERT ); 1377 SelectBrush( getHDC(), hOldBrush ); 1378 DeleteBrush( hBrush ); 1379 } 1380 else 1381 SetPixel( getHDC(), (int)nX2, (int)nY2, mnPenColor ); 1382 } 1383 } 1384 1385 // ----------------------------------------------------------------------- 1386 1387 void WinSalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) 1388 { 1389 if ( !mbPen ) 1390 { 1391 if ( !mbPrinter ) 1392 { 1393 PatBlt( getHDC(), (int)nX, (int)nY, (int)nWidth, (int)nHeight, 1394 mbXORMode ? PATINVERT : PATCOPY ); 1395 } 1396 else 1397 { 1398 RECT aWinRect; 1399 aWinRect.left = nX; 1400 aWinRect.top = nY; 1401 aWinRect.right = nX+nWidth; 1402 aWinRect.bottom = nY+nHeight; 1403 ::FillRect( getHDC(), &aWinRect, mhBrush ); 1404 } 1405 } 1406 else 1407 WIN_Rectangle( getHDC(), (int)nX, (int)nY, (int)(nX+nWidth), (int)(nY+nHeight) ); 1408 } 1409 1410 // ----------------------------------------------------------------------- 1411 1412 void WinSalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint* pPtAry ) 1413 { 1414 // Unter NT koennen wir das Array direkt weiterreichen 1415 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1416 "WinSalGraphics::DrawPolyLine(): POINT != SalPoint" ); 1417 1418 POINT* pWinPtAry = (POINT*)pPtAry; 1419 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl 1420 // von Punkten 1421 if ( !Polyline( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 1422 Polyline( getHDC(), pWinPtAry, MAX_64KSALPOINTS ); 1423 } 1424 1425 // ----------------------------------------------------------------------- 1426 1427 void WinSalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry ) 1428 { 1429 // Unter NT koennen wir das Array direkt weiterreichen 1430 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1431 "WinSalGraphics::DrawPolygon(): POINT != SalPoint" ); 1432 1433 POINT* pWinPtAry = (POINT*)pPtAry; 1434 // Wegen Windows 95 und der Beschraenkung auf eine maximale Anzahl 1435 // von Punkten 1436 if ( !WIN_Polygon( getHDC(), pWinPtAry, (int)nPoints ) && (nPoints > MAX_64KSALPOINTS) ) 1437 WIN_Polygon( getHDC(), pWinPtAry, MAX_64KSALPOINTS ); 1438 } 1439 1440 // ----------------------------------------------------------------------- 1441 1442 void WinSalGraphics::drawPolyPolygon( sal_uInt32 nPoly, const sal_uInt32* pPoints, 1443 PCONSTSALPOINT* pPtAry ) 1444 { 1445 UINT aWinPointAry[SAL_POLYPOLYCOUNT_STACKBUF]; 1446 UINT* pWinPointAry; 1447 UINT nPolyPolyPoints = 0; 1448 UINT nPoints; 1449 UINT i; 1450 1451 if ( nPoly <= SAL_POLYPOLYCOUNT_STACKBUF ) 1452 pWinPointAry = aWinPointAry; 1453 else 1454 pWinPointAry = new UINT[nPoly]; 1455 1456 for ( i = 0; i < (UINT)nPoly; i++ ) 1457 { 1458 nPoints = (UINT)pPoints[i]+1; 1459 pWinPointAry[i] = nPoints; 1460 nPolyPolyPoints += nPoints; 1461 } 1462 1463 POINT aWinPointAryAry[SAL_POLYPOLYPOINTS_STACKBUF]; 1464 POINT* pWinPointAryAry; 1465 if ( nPolyPolyPoints <= SAL_POLYPOLYPOINTS_STACKBUF ) 1466 pWinPointAryAry = aWinPointAryAry; 1467 else 1468 pWinPointAryAry = new POINT[nPolyPolyPoints]; 1469 // Unter NT koennen wir das Array direkt weiterreichen 1470 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1471 "WinSalGraphics::DrawPolyPolygon(): POINT != SalPoint" ); 1472 const SalPoint* pPolyAry; 1473 UINT n = 0; 1474 for ( i = 0; i < (UINT)nPoly; i++ ) 1475 { 1476 nPoints = pWinPointAry[i]; 1477 pPolyAry = pPtAry[i]; 1478 memcpy( pWinPointAryAry+n, pPolyAry, (nPoints-1)*sizeof(POINT) ); 1479 pWinPointAryAry[n+nPoints-1] = pWinPointAryAry[n]; 1480 n += nPoints; 1481 } 1482 1483 if ( !WIN_PolyPolygon( getHDC(), pWinPointAryAry, (int*)pWinPointAry, (UINT)nPoly ) && 1484 (nPolyPolyPoints > MAX_64KSALPOINTS) ) 1485 { 1486 nPolyPolyPoints = 0; 1487 nPoly = 0; 1488 do 1489 { 1490 nPolyPolyPoints += pWinPointAry[(UINT)nPoly]; 1491 nPoly++; 1492 } 1493 while ( nPolyPolyPoints < MAX_64KSALPOINTS ); 1494 nPoly--; 1495 if ( pWinPointAry[(UINT)nPoly] > MAX_64KSALPOINTS ) 1496 pWinPointAry[(UINT)nPoly] = MAX_64KSALPOINTS; 1497 if ( nPoly == 1 ) 1498 WIN_Polygon( getHDC(), pWinPointAryAry, *pWinPointAry ); 1499 else 1500 WIN_PolyPolygon( getHDC(), pWinPointAryAry, (int*)pWinPointAry, nPoly ); 1501 } 1502 1503 if ( pWinPointAry != aWinPointAry ) 1504 delete [] pWinPointAry; 1505 if ( pWinPointAryAry != aWinPointAryAry ) 1506 delete [] pWinPointAryAry; 1507 } 1508 1509 // ----------------------------------------------------------------------- 1510 1511 #define SAL_POLY_STACKBUF 32 1512 1513 // ----------------------------------------------------------------------- 1514 1515 sal_Bool WinSalGraphics::drawPolyLineBezier( sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 1516 { 1517 #ifdef USE_GDI_BEZIERS 1518 // Unter NT koennen wir das Array direkt weiterreichen 1519 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1520 "WinSalGraphics::DrawPolyLineBezier(): POINT != SalPoint" ); 1521 1522 ImplRenderPath( getHDC(), nPoints, pPtAry, pFlgAry ); 1523 1524 return sal_True; 1525 #else 1526 return sal_False; 1527 #endif 1528 } 1529 1530 // ----------------------------------------------------------------------- 1531 1532 sal_Bool WinSalGraphics::drawPolygonBezier( sal_uLong nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 1533 { 1534 #ifdef USE_GDI_BEZIERS 1535 // Unter NT koennen wir das Array direkt weiterreichen 1536 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1537 "WinSalGraphics::DrawPolygonBezier(): POINT != SalPoint" ); 1538 1539 POINT aStackAry1[SAL_POLY_STACKBUF]; 1540 BYTE aStackAry2[SAL_POLY_STACKBUF]; 1541 POINT* pWinPointAry; 1542 BYTE* pWinFlagAry; 1543 if( nPoints > SAL_POLY_STACKBUF ) 1544 { 1545 pWinPointAry = new POINT[ nPoints ]; 1546 pWinFlagAry = new BYTE[ nPoints ]; 1547 } 1548 else 1549 { 1550 pWinPointAry = aStackAry1; 1551 pWinFlagAry = aStackAry2; 1552 } 1553 1554 ImplPreparePolyDraw(true, 1, &nPoints, &pPtAry, &pFlgAry, pWinPointAry, pWinFlagAry); 1555 1556 sal_Bool bRet( sal_False ); 1557 1558 if( BeginPath( getHDC() ) ) 1559 { 1560 PolyDraw(getHDC(), pWinPointAry, pWinFlagAry, nPoints); 1561 1562 if( EndPath( getHDC() ) ) 1563 { 1564 if( StrokeAndFillPath( getHDC() ) ) 1565 bRet = sal_True; 1566 } 1567 } 1568 1569 if( pWinPointAry != aStackAry1 ) 1570 { 1571 delete [] pWinPointAry; 1572 delete [] pWinFlagAry; 1573 } 1574 1575 return bRet; 1576 #else 1577 return sal_False; 1578 #endif 1579 } 1580 1581 // ----------------------------------------------------------------------- 1582 1583 sal_Bool WinSalGraphics::drawPolyPolygonBezier( sal_uInt32 nPoly, const sal_uInt32* pPoints, 1584 const SalPoint* const* pPtAry, const BYTE* const* pFlgAry ) 1585 { 1586 #ifdef USE_GDI_BEZIERS 1587 // Unter NT koennen wir das Array direkt weiterreichen 1588 DBG_ASSERT( sizeof( POINT ) == sizeof( SalPoint ), 1589 "WinSalGraphics::DrawPolyPolygonBezier(): POINT != SalPoint" ); 1590 1591 sal_uLong nCurrPoly, nTotalPoints; 1592 const sal_uLong* pCurrPoints = pPoints; 1593 for( nCurrPoly=0, nTotalPoints=0; nCurrPoly<nPoly; ++nCurrPoly ) 1594 nTotalPoints += *pCurrPoints++; 1595 1596 POINT aStackAry1[SAL_POLY_STACKBUF]; 1597 BYTE aStackAry2[SAL_POLY_STACKBUF]; 1598 POINT* pWinPointAry; 1599 BYTE* pWinFlagAry; 1600 if( nTotalPoints > SAL_POLY_STACKBUF ) 1601 { 1602 pWinPointAry = new POINT[ nTotalPoints ]; 1603 pWinFlagAry = new BYTE[ nTotalPoints ]; 1604 } 1605 else 1606 { 1607 pWinPointAry = aStackAry1; 1608 pWinFlagAry = aStackAry2; 1609 } 1610 1611 ImplPreparePolyDraw(true, nPoly, pPoints, pPtAry, pFlgAry, pWinPointAry, pWinFlagAry); 1612 1613 sal_Bool bRet( sal_False ); 1614 1615 if( BeginPath( getHDC() ) ) 1616 { 1617 PolyDraw(getHDC(), pWinPointAry, pWinFlagAry, nTotalPoints); 1618 1619 if( EndPath( getHDC() ) ) 1620 { 1621 if( StrokeAndFillPath( getHDC() ) ) 1622 bRet = sal_True; 1623 } 1624 } 1625 1626 if( pWinPointAry != aStackAry1 ) 1627 { 1628 delete [] pWinPointAry; 1629 delete [] pWinFlagAry; 1630 } 1631 1632 return bRet; 1633 #else 1634 return sal_False; 1635 #endif 1636 } 1637 1638 // ----------------------------------------------------------------------- 1639 1640 #define POSTSCRIPT_BUFSIZE 0x4000 // MAXIMUM BUFSIZE EQ 0xFFFF 1641 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 // we only try to get the BoundingBox 1642 // in the first 4096 bytes 1643 1644 static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, sal_uLong nComp, sal_uLong nSize ) 1645 { 1646 while ( nComp-- >= nSize ) 1647 { 1648 sal_uLong i; 1649 for ( i = 0; i < nSize; i++ ) 1650 { 1651 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) ) 1652 break; 1653 } 1654 if ( i == nSize ) 1655 return pSource; 1656 pSource++; 1657 } 1658 return NULL; 1659 } 1660 1661 static sal_Bool ImplGetBoundingBox( double* nNumb, BYTE* pSource, sal_uLong nSize ) 1662 { 1663 sal_Bool bRetValue = FALSE; 1664 BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 ); 1665 if ( pDest ) 1666 { 1667 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0; 1668 pDest += 14; 1669 1670 int nSizeLeft = nSize - ( pDest - pSource ); 1671 if ( nSizeLeft > 100 ) 1672 nSizeLeft = 100; // only 100 bytes following the bounding box will be checked 1673 1674 int i; 1675 for ( i = 0; ( i < 4 ) && nSizeLeft; i++ ) 1676 { 1677 int nDivision = 1; 1678 sal_Bool bDivision = FALSE; 1679 sal_Bool bNegative = FALSE; 1680 sal_Bool bValid = TRUE; 1681 1682 while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++; 1683 BYTE nByte = *pDest; 1684 while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) ) 1685 { 1686 switch ( nByte ) 1687 { 1688 case '.' : 1689 if ( bDivision ) 1690 bValid = FALSE; 1691 else 1692 bDivision = TRUE; 1693 break; 1694 case '-' : 1695 bNegative = TRUE; 1696 break; 1697 default : 1698 if ( ( nByte < '0' ) || ( nByte > '9' ) ) 1699 nSizeLeft = 1; // error parsing the bounding box values 1700 else if ( bValid ) 1701 { 1702 if ( bDivision ) 1703 nDivision*=10; 1704 nNumb[i] *= 10; 1705 nNumb[i] += nByte - '0'; 1706 } 1707 break; 1708 } 1709 nSizeLeft--; 1710 nByte = *(++pDest); 1711 } 1712 if ( bNegative ) 1713 nNumb[i] = -nNumb[i]; 1714 if ( bDivision && ( nDivision != 1 ) ) 1715 nNumb[i] /= nDivision; 1716 } 1717 if ( i == 4 ) 1718 bRetValue = TRUE; 1719 } 1720 return bRetValue; 1721 } 1722 1723 sal_Bool WinSalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, sal_uLong nSize ) 1724 { 1725 sal_Bool bRetValue = FALSE; 1726 1727 if ( mbPrinter ) 1728 { 1729 int nEscape = POSTSCRIPT_PASSTHROUGH; 1730 1731 if ( Escape( getHDC(), QUERYESCSUPPORT, sizeof( int ), ( LPSTR )&nEscape, 0 ) ) 1732 { 1733 double nBoundingBox[4]; 1734 1735 if ( ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) ) 1736 { 1737 OStringBuffer aBuf( POSTSCRIPT_BUFSIZE ); 1738 1739 // reserve place for a sal_uInt16 1740 aBuf.append( "aa" ); 1741 1742 // #107797# Write out EPS encapsulation header 1743 // ---------------------------------------------------------------------------------- 1744 1745 // directly taken from the PLRM 3.0, p. 726. Note: 1746 // this will definitely cause problems when 1747 // recursively creating and embedding PostScript files 1748 // in OOo, since we use statically-named variables 1749 // here (namely, b4_Inc_state_salWin, dict_count_salWin and 1750 // op_count_salWin). Currently, I have no idea on how to 1751 // work around that, except from scanning and 1752 // interpreting the EPS for unused identifiers. 1753 1754 // append the real text 1755 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n" 1756 "/dict_count_salWin countdictstack def\n" 1757 "/op_count_salWin count 1 sub def\n" 1758 "userdict begin\n" 1759 "/showpage {} def\n" 1760 "0 setgray 0 setlinecap\n" 1761 "1 setlinewidth 0 setlinejoin\n" 1762 "10 setmiterlimit [] 0 setdash newpath\n" 1763 "/languagelevel where\n" 1764 "{\n" 1765 " pop languagelevel\n" 1766 " 1 ne\n" 1767 " {\n" 1768 " false setstrokeadjust false setoverprint\n" 1769 " } if\n" 1770 "} if\n\n" ); 1771 1772 1773 // #i10737# Apply clipping manually 1774 // ---------------------------------------------------------------------------------- 1775 1776 // Windows seems to ignore any clipping at the HDC, 1777 // when followed by a POSTSCRIPT_PASSTHROUGH 1778 1779 // Check whether we've got a clipping, consisting of 1780 // exactly one rect (other cases should be, but aren't 1781 // handled currently) 1782 1783 // TODO: Handle more than one rectangle here (take 1784 // care, the buffer can handle only POSTSCRIPT_BUFSIZE 1785 // characters!) 1786 if ( mhRegion != 0 && 1787 mpStdClipRgnData != NULL && 1788 mpClipRgnData == mpStdClipRgnData && 1789 mpClipRgnData->rdh.nCount == 1 ) 1790 { 1791 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 1792 1793 aBuf.append( "\nnewpath\n" ); 1794 aBuf.append( pRect->left ); 1795 aBuf.append( " " ); 1796 aBuf.append( pRect->top ); 1797 aBuf.append( " moveto\n" ); 1798 aBuf.append( pRect->right ); 1799 aBuf.append( " " ); 1800 aBuf.append( pRect->top ); 1801 aBuf.append( " lineto\n" ); 1802 aBuf.append( pRect->right ); 1803 aBuf.append( " " ); 1804 aBuf.append( pRect->bottom ); 1805 aBuf.append( " lineto\n" ); 1806 aBuf.append( pRect->left ); 1807 aBuf.append( " " ); 1808 aBuf.append( pRect->bottom ); 1809 aBuf.append( " lineto\n" 1810 "closepath\n" 1811 "clip\n" 1812 "newpath\n" ); 1813 } 1814 1815 // #107797# Write out buffer 1816 // ---------------------------------------------------------------------------------- 1817 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); 1818 Escape ( getHDC(), nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 1819 1820 1821 // #107797# Write out EPS transformation code 1822 // ---------------------------------------------------------------------------------- 1823 double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] ); 1824 double dM22 = nHeight / (nBoundingBox[1] - nBoundingBox[3] ); 1825 // reserve a sal_uInt16 again 1826 aBuf.setLength( 2 ); 1827 aBuf.append( "\n\n[" ); 1828 aBuf.append( dM11 ); 1829 aBuf.append( " 0 0 " ); 1830 aBuf.append( dM22 ); 1831 aBuf.append( ' ' ); 1832 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) ); 1833 aBuf.append( ' ' ); 1834 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) ); 1835 aBuf.append( "] concat\n" 1836 "%%BeginDocument:\n" ); 1837 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); 1838 Escape ( getHDC(), nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 1839 1840 1841 // #107797# Write out actual EPS content 1842 // ---------------------------------------------------------------------------------- 1843 sal_uLong nToDo = nSize; 1844 sal_uLong nDoNow; 1845 while ( nToDo ) 1846 { 1847 nDoNow = nToDo; 1848 if ( nToDo > POSTSCRIPT_BUFSIZE - 2 ) 1849 nDoNow = POSTSCRIPT_BUFSIZE - 2; 1850 // the following is based on the string buffer allocation 1851 // of size POSTSCRIPT_BUFSIZE at construction time of aBuf 1852 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)nDoNow; 1853 memcpy( (void*)(aBuf.getStr() + 2), (BYTE*)pPtr + nSize - nToDo, nDoNow ); 1854 sal_uLong nResult = Escape ( getHDC(), nEscape, nDoNow + 2, (LPTSTR)aBuf.getStr(), 0 ); 1855 if (!nResult ) 1856 break; 1857 nToDo -= nResult; 1858 } 1859 1860 1861 // #107797# Write out EPS encapsulation footer 1862 // ---------------------------------------------------------------------------------- 1863 // reserve a sal_uInt16 again 1864 aBuf.setLength( 2 ); 1865 aBuf.append( "%%EndDocument\n" 1866 "count op_count_salWin sub {pop} repeat\n" 1867 "countdictstack dict_count_salWin sub {end} repeat\n" 1868 "b4_Inc_state_salWin restore\n\n" ); 1869 *((sal_uInt16*)aBuf.getStr()) = (sal_uInt16)( aBuf.getLength() - 2 ); 1870 Escape ( getHDC(), nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 1871 bRetValue = TRUE; 1872 } 1873 } 1874 } 1875 1876 return bRetValue; 1877 } 1878 1879 // ----------------------------------------------------------------------- 1880 1881 SystemGraphicsData WinSalGraphics::GetGraphicsData() const 1882 { 1883 SystemGraphicsData aRes; 1884 aRes.nSize = sizeof(aRes); 1885 aRes.hDC = const_cast< WinSalGraphics* >(this)->getHDC(); 1886 return aRes; 1887 } 1888 1889 // ----------------------------------------------------------------------- 1890