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