1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 #include <string.h> 29 #include <svpm.h> 30 31 #define _SV_SALGDI_CXX 32 #include <tools/debug.hxx> 33 #include <saldata.hxx> 34 #include <salgdi.h> 35 #include <tools/debug.hxx> 36 #include <salframe.h> 37 #include <tools/poly.hxx> 38 #ifndef _RTL_STRINGBUF_HXX 39 #include <rtl/strbuf.hxx> 40 #endif 41 #include "vcl/region.h" 42 43 #ifndef __H_FT2LIB 44 #include <wingdi.h> 45 #include <ft2lib.h> 46 #endif 47 48 // ----------- 49 // - Defines - 50 // ----------- 51 52 // ClipRegions funktionieren immer noch nicht auf allen getesteten Druckern 53 #define SAL_PRINTER_CLIPPATH 1 54 // #define SAL_PRINTER_POLYPATH 1 55 56 // ======================================================================= 57 58 void ImplInitSalGDI() 59 { 60 } 61 62 // ----------------------------------------------------------------------- 63 64 void ImplFreeSalGDI() 65 { 66 SalData* pSalData = GetSalData(); 67 68 // delete icon cache 69 SalIcon* pIcon = pSalData->mpFirstIcon; 70 while( pIcon ) 71 { 72 SalIcon* pTmp = pIcon->pNext; 73 WinDestroyPointer( pIcon->hIcon ); 74 delete pIcon; 75 pIcon = pTmp; 76 } 77 78 } 79 80 // ======================================================================= 81 82 void ImplSalInitGraphics( Os2SalGraphics* pData ) 83 { 84 GpiCreateLogColorTable( pData->mhPS, LCOL_RESET, LCOLF_RGB, 0, 0, NULL ); 85 } 86 87 // ----------------------------------------------------------------------- 88 89 void ImplSalDeInitGraphics( Os2SalGraphics* pData ) 90 { 91 } 92 93 // ======================================================================= 94 95 Os2SalGraphics::Os2SalGraphics() 96 { 97 for( int i = 0; i < MAX_FALLBACK; ++i ) 98 { 99 mhFonts[ i ] = 0; 100 mpOs2FontData[ i ] = NULL; 101 mpOs2FontEntry[ i ] = NULL; 102 } 103 104 mfFontScale = 1.0; 105 106 mhPS = 0; 107 mhDC = 0; 108 mbLine = FALSE; 109 mbFill = FALSE; 110 mbXORMode = FALSE; 111 mnFontMetricCount = 0; 112 mpFontMetrics = NULL; 113 mpClipRectlAry = NULL; 114 115 mhDefFont = 0; 116 mpFontKernPairs = NULL; 117 mnFontKernPairCount = 0; 118 mbFontKernInit = FALSE; 119 120 } 121 122 // ----------------------------------------------------------------------- 123 124 Os2SalGraphics::~Os2SalGraphics() 125 { 126 Ft2DeleteSetId( mhPS, LCID_BASE); 127 128 if ( mpFontMetrics ) 129 delete mpFontMetrics; 130 131 if ( mpFontKernPairs ) 132 delete mpFontKernPairs; 133 134 } 135 136 // ----------------------------------------------------------------------- 137 138 static SalColor ImplGetROPSalColor( SalROPColor nROPColor ) 139 { 140 SalColor nSalColor; 141 142 switch( nROPColor ) 143 { 144 case SAL_ROP_0: 145 nSalColor = MAKE_SALCOLOR( 0, 0, 0 ); 146 break; 147 148 case SAL_ROP_1: 149 case SAL_ROP_INVERT: 150 nSalColor = MAKE_SALCOLOR( 255, 255, 255 ); 151 break; 152 } 153 154 return nSalColor; 155 } 156 157 // ----------------------------------------------------------------------- 158 159 void Os2SalGraphics::GetResolution( long& rDPIX, long& rDPIY ) 160 { 161 // since OOo asks for DPI, I will query FONT_RES, which seems to be 162 // more correct than _RESOLUTION fields (on my wide screen lcd) 163 // and does not require conversion 164 DevQueryCaps( mhDC, CAPS_HORIZONTAL_FONT_RES, 1, &rDPIX ); 165 DevQueryCaps( mhDC, CAPS_VERTICAL_FONT_RES, 1, &rDPIY ); 166 } 167 168 // ----------------------------------------------------------------------- 169 170 USHORT Os2SalGraphics::GetBitCount() 171 { 172 LONG nBitCount; 173 DevQueryCaps( mhDC, CAPS_COLOR_BITCOUNT, 1, &nBitCount ); 174 return (USHORT)nBitCount; 175 } 176 177 // ----------------------------------------------------------------------- 178 179 long Os2SalGraphics::GetGraphicsWidth() const 180 { 181 if( mhWnd ) 182 { 183 Os2SalFrame* pFrame = (Os2SalFrame*)GetWindowPtr( mhWnd ); 184 if( pFrame ) 185 { 186 if( pFrame->maGeometry.nWidth ) 187 return pFrame->maGeometry.nWidth; 188 else 189 { 190 // TODO: perhaps not needed, maGeometry should always be up-to-date 191 RECTL aRect; 192 WinQueryWindowRect( mhWnd, &aRect ); 193 return aRect.xRight; 194 } 195 } 196 } 197 198 return 0; 199 } 200 201 // ----------------------------------------------------------------------- 202 203 void Os2SalGraphics::ResetClipRegion() 204 { 205 #ifdef SAL_PRINTER_CLIPPATH 206 if ( mbPrinter ) 207 GpiSetClipPath( mhPS, 0, SCP_RESET ); 208 else 209 #endif 210 { 211 HRGN hOldRegion; 212 213 GpiSetClipRegion( mhPS, NULL, &hOldRegion ); 214 if ( hOldRegion ) 215 GpiDestroyRegion( mhPS, hOldRegion ); 216 } 217 } 218 219 // ----------------------------------------------------------------------- 220 221 bool Os2SalGraphics::setClipRegion( const Region& i_rClip ) 222 { 223 ULONG nCount = i_rClip.GetRectCount(); 224 225 mpClipRectlAry = new RECTL[ nCount ]; 226 mnClipElementCount = 0; 227 228 ImplRegionInfo aInfo; 229 long nX, nY, nW, nH; 230 bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH ); 231 while( bRegionRect ) 232 { 233 if ( nW && nH ) 234 { 235 RECTL* pClipRect = &mpClipRectlAry[ mnClipElementCount ]; 236 pClipRect->xLeft = nX; 237 pClipRect->yTop = mnHeight - nY; 238 pClipRect->xRight = nX + nW; 239 pClipRect->yBottom = mnHeight - (nY + nH); 240 mnClipElementCount++; 241 } 242 bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH ); 243 } 244 #ifdef SAL_PRINTER_CLIPPATH 245 if ( mbPrinter ) 246 { 247 GpiSetClipPath( mhPS, 0, SCP_RESET ); 248 GpiBeginPath( mhPS, 1L ); 249 250 for( int i = 0; i < mnClipElementCount; i++ ) 251 { 252 POINTL aPt; 253 RECTL* pClipRect = &mpClipRectlAry[ i ]; 254 255 aPt.x = pClipRect->xLeft; 256 aPt.y = pClipRect->yTop-1; 257 Ft2Move( mhPS, &aPt ); 258 259 aPt.x = pClipRect->xRight-1; 260 aPt.y = pClipRect->yBottom; 261 262 Ft2Box( mhPS, DRO_OUTLINE, &aPt, 0, 0 ); 263 } 264 265 GpiEndPath( mhPS ); 266 GpiSetClipPath( mhPS, 1L, SCP_ALTERNATE | SCP_AND ); 267 } 268 else 269 #endif 270 { 271 HRGN hClipRegion = GpiCreateRegion( mhPS, 272 mnClipElementCount, 273 mpClipRectlAry ); 274 HRGN hOldRegion; 275 276 GpiSetClipRegion( mhPS, hClipRegion, &hOldRegion ); 277 if( hOldRegion ) 278 GpiDestroyRegion( mhPS, hOldRegion ); 279 } 280 281 delete [] mpClipRectlAry; 282 283 return true; 284 } 285 286 // ----------------------------------------------------------------------- 287 288 void Os2SalGraphics::SetLineColor() 289 { 290 // don't draw line! 291 mbLine = FALSE; 292 } 293 294 // ----------------------------------------------------------------------- 295 296 void Os2SalGraphics::SetLineColor( SalColor nSalColor ) 297 { 298 LINEBUNDLE lb; 299 300 // set color 301 lb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), 302 SALCOLOR_GREEN( nSalColor ), 303 SALCOLOR_BLUE( nSalColor ) ); 304 305 Ft2SetAttrs( mhPS, 306 PRIM_LINE, 307 LBB_COLOR, 308 0, 309 &lb ); 310 311 // draw line! 312 mbLine = TRUE; 313 } 314 315 // ----------------------------------------------------------------------- 316 317 void Os2SalGraphics::SetFillColor() 318 { 319 // don't fill area! 320 mbFill = FALSE; 321 } 322 323 // ----------------------------------------------------------------------- 324 325 void Os2SalGraphics::SetFillColor( SalColor nSalColor ) 326 { 327 AREABUNDLE ab; 328 329 // set color 330 ab.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), 331 SALCOLOR_GREEN( nSalColor ), 332 SALCOLOR_BLUE( nSalColor ) ); 333 334 Ft2SetAttrs( mhPS, 335 PRIM_AREA, 336 ABB_COLOR, 337 0, 338 &ab ); 339 340 // fill area! 341 mbFill = TRUE; 342 } 343 344 // ----------------------------------------------------------------------- 345 346 void Os2SalGraphics::SetXORMode( bool bSet, bool ) 347 { 348 mbXORMode = bSet; 349 LONG nMixMode = bSet ? FM_XOR : FM_OVERPAINT; 350 351 // set mix mode for lines 352 LINEBUNDLE lb; 353 lb.usMixMode = nMixMode; 354 Ft2SetAttrs( mhPS, 355 PRIM_LINE, 356 LBB_MIX_MODE, 357 0, 358 &lb ); 359 360 // set mix mode for areas 361 AREABUNDLE ab; 362 ab.usMixMode = nMixMode; 363 Ft2SetAttrs( mhPS, 364 PRIM_AREA, 365 ABB_MIX_MODE, 366 0, 367 &ab ); 368 369 // set mix mode for text 370 CHARBUNDLE cb; 371 cb.usMixMode = nMixMode; 372 Ft2SetAttrs( mhPS, 373 PRIM_CHAR, 374 CBB_MIX_MODE, 375 0, 376 &cb ); 377 } 378 379 // ----------------------------------------------------------------------- 380 381 void Os2SalGraphics::SetROPLineColor( SalROPColor nROPColor ) 382 { 383 SetLineColor( ImplGetROPSalColor( nROPColor ) ); 384 } 385 386 // ----------------------------------------------------------------------- 387 388 void Os2SalGraphics::SetROPFillColor( SalROPColor nROPColor ) 389 { 390 SetFillColor( ImplGetROPSalColor( nROPColor ) ); 391 } 392 393 // ----------------------------------------------------------------------- 394 395 void Os2SalGraphics::drawPixel( long nX, long nY ) 396 { 397 POINTL aPt; 398 399 aPt.x = nX; 400 aPt.y = TY( nY ); 401 402 // set color 403 Ft2SetPel( mhPS, &aPt ); 404 } 405 406 // ----------------------------------------------------------------------- 407 408 void Os2SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) 409 { 410 // save old color 411 LINEBUNDLE oldLb; 412 GpiQueryAttrs( mhPS, 413 PRIM_LINE, 414 LBB_COLOR, 415 &oldLb ); 416 417 // set new color 418 LINEBUNDLE lb; 419 lb.lColor = RGBCOLOR( SALCOLOR_RED( nSalColor ), 420 SALCOLOR_GREEN( nSalColor ), 421 SALCOLOR_BLUE( nSalColor ) ); 422 Ft2SetAttrs( mhPS, 423 PRIM_LINE, 424 LBB_COLOR, 425 0, 426 &lb ); 427 428 // set color of pixel 429 POINTL aPt; 430 aPt.x = nX; 431 aPt.y = TY( nY ); 432 Ft2SetPel( mhPS, &aPt ); 433 434 // restore old color 435 Ft2SetAttrs( mhPS, 436 PRIM_LINE, 437 LBB_COLOR, 438 0, 439 &oldLb ); 440 } 441 442 // ----------------------------------------------------------------------- 443 444 void Os2SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) 445 { 446 // OS2 zeichnet den Endpunkt mit 447 POINTL aPt; 448 aPt.x = nX1; 449 aPt.y = TY( nY1 ); 450 Ft2Move( mhPS, &aPt ); 451 aPt.x = nX2; 452 aPt.y = TY( nY2 ); 453 GpiLine( mhPS, &aPt ); 454 } 455 456 // ----------------------------------------------------------------------- 457 458 void Os2SalGraphics::drawRect( long nX, long nY, long nWidth, long nHeight ) 459 { 460 POINTL aPt; 461 long lControl; 462 463 if ( mbFill ) 464 { 465 if ( mbLine ) 466 lControl = DRO_OUTLINEFILL; 467 else 468 lControl = DRO_FILL; 469 } 470 else 471 { 472 if ( mbLine ) 473 lControl = DRO_OUTLINE; 474 else 475 return; 476 } 477 478 aPt.x = nX; 479 aPt.y = TY( nY ); 480 Ft2Move( mhPS, &aPt ); 481 aPt.x = nX + nWidth - 1; 482 aPt.y = TY( nY + nHeight - 1 ); 483 Ft2Box( mhPS, lControl, &aPt, 0, 0 ); 484 } 485 486 // ----------------------------------------------------------------------- 487 488 void Os2SalGraphics::drawPolyLine( ULONG nPoints, const SalPoint* pPtAry ) 489 { 490 // convert all points to sys orientation 491 POINTL* pOS2PtAry = new POINTL[ nPoints ]; 492 POINTL* pTempOS2PtAry = pOS2PtAry; 493 const SalPoint* pTempPtAry = pPtAry; 494 ULONG nTempPoints = nPoints; 495 long nHeight = mnHeight - 1; 496 497 while( nTempPoints-- ) 498 { 499 (*pTempOS2PtAry).x = (*pTempPtAry).mnX; 500 (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY; 501 pTempOS2PtAry++; 502 pTempPtAry++; 503 } 504 505 Ft2Move( mhPS, pOS2PtAry ); 506 GpiPolyLine( mhPS, nPoints, pOS2PtAry ); 507 delete [] pOS2PtAry; 508 } 509 510 // ----------------------------------------------------------------------- 511 512 void Os2SalGraphics::drawPolygon( ULONG nPoints, const SalPoint* pPtAry ) 513 { 514 PM_POLYGON aPolygon; 515 516 // create polygon 517 aPolygon.aPointl = new POINTL[ nPoints ]; 518 aPolygon.ulPoints = nPoints; 519 520 // convert all points to sys orientation 521 POINTL* pTempOS2PtAry = aPolygon.aPointl; 522 const SalPoint* pTempPtAry = pPtAry; 523 ULONG nTempPoints = nPoints; 524 long nHeight = mnHeight - 1; 525 526 while( nTempPoints-- ) 527 { 528 (*pTempOS2PtAry).x = (*pTempPtAry).mnX; 529 (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY; 530 pTempOS2PtAry++; 531 pTempPtAry++; 532 } 533 534 // Innenleben zeichnen 535 if ( mbFill ) 536 { 537 #ifdef SAL_PRINTER_POLYPATH 538 if ( mbPrinter ) 539 { 540 Ft2BeginPath( mhPS, 1 ); 541 Ft2Move( mhPS, aPolygon.aPointl ); 542 Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl ); 543 Ft2EndPath( mhPS ); 544 Ft2FillPath( mhPS, 1, 0 ); 545 546 if ( mbLine ) 547 { 548 Ft2Move( mhPS, aPolygon.aPointl ); 549 Ft2PolyLine( mhPS, aPolygon.ulPoints, aPolygon.aPointl ); 550 } 551 } 552 else 553 #endif 554 { 555 ULONG nOptions = POLYGON_ALTERNATE; 556 557 if ( mbLine ) 558 nOptions |= POLYGON_BOUNDARY; 559 else 560 nOptions |= POLYGON_NOBOUNDARY; 561 562 Ft2Move( mhPS, aPolygon.aPointl ); 563 GpiPolygons( mhPS, 1, &aPolygon, nOptions, POLYGON_EXCL ); 564 } 565 } 566 else 567 { 568 if ( mbLine ) 569 { 570 Ft2Move( mhPS, aPolygon.aPointl ); 571 GpiPolyLine( mhPS, nPoints, aPolygon.aPointl ); 572 } 573 } 574 575 delete [] aPolygon.aPointl; 576 } 577 578 // ----------------------------------------------------------------------- 579 580 void Os2SalGraphics::drawPolyPolygon( ULONG nPoly, const ULONG* pPoints, 581 PCONSTSALPOINT* pPtAry ) 582 { 583 ULONG i; 584 long nHeight = mnHeight - 1; 585 PM_POLYGON* aPolygonAry = new PM_POLYGON[ nPoly ]; 586 587 for( i = 0; i < nPoly; i++ ) 588 { 589 const SalPoint * pTempPtAry = (const SalPoint*)pPtAry[ i ]; 590 591 // create polygon 592 ULONG nTempPoints = pPoints[ i ]; 593 POINTL * pTempOS2PtAry = new POINTL[ nTempPoints ]; 594 595 // convert all points to sys orientation 596 aPolygonAry[ i ].ulPoints = nTempPoints; 597 aPolygonAry[ i ].aPointl = pTempOS2PtAry; 598 599 while( nTempPoints-- ) 600 { 601 (*pTempOS2PtAry).x = (*pTempPtAry).mnX; 602 (*pTempOS2PtAry).y = nHeight - (*pTempPtAry).mnY; 603 pTempOS2PtAry++; 604 pTempPtAry++; 605 } 606 } 607 608 // Innenleben zeichnen 609 if ( mbFill ) 610 { 611 #ifdef SAL_PRINTER_POLYPATH 612 if ( mbPrinter ) 613 { 614 Ft2BeginPath( mhPS, 1 ); 615 for ( i = 0; i < nPoly; i++ ) 616 { 617 Ft2Move( mhPS, aPolygonAry[i].aPointl ); 618 Ft2PolyLine( mhPS, aPolygonAry[i].ulPoints, aPolygonAry[i].aPointl ); 619 } 620 Ft2EndPath( mhPS ); 621 Ft2FillPath( mhPS, 1, 0 ); 622 } 623 else 624 #endif 625 { 626 ULONG nOptions = POLYGON_ALTERNATE; 627 628 if ( mbLine ) 629 nOptions |= POLYGON_BOUNDARY; 630 else 631 nOptions |= POLYGON_NOBOUNDARY; 632 633 Ft2Move( mhPS, aPolygonAry[ 0 ].aPointl ); 634 GpiPolygons( mhPS, nPoly, aPolygonAry, nOptions, POLYGON_EXCL ); 635 } 636 } 637 else 638 { 639 if ( mbLine ) 640 { 641 for( i = 0; i < nPoly; i++ ) 642 { 643 Ft2Move( mhPS, aPolygonAry[ i ].aPointl ); 644 GpiPolyLine( mhPS, aPolygonAry[ i ].ulPoints, aPolygonAry[ i ].aPointl ); 645 } 646 } 647 } 648 649 // cleanup 650 for( i = 0; i < nPoly; i++ ) 651 delete [] aPolygonAry[ i ].aPointl; 652 delete [] aPolygonAry; 653 } 654 655 // ----------------------------------------------------------------------- 656 657 bool Os2SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon&, double /*fTransparency*/ ) 658 { 659 // TODO: implement and advertise OutDevSupport_B2DDraw support 660 return false; 661 } 662 663 // ----------------------------------------------------------------------- 664 665 bool Os2SalGraphics::drawPolyLine( 666 const basegfx::B2DPolygon& /*rPolygon*/, 667 double /*fTransparency*/, 668 const basegfx::B2DVector& /*rLineWidths*/, 669 basegfx::B2DLineJoin /*eLineJoin*/) 670 { 671 // TODO: implement 672 return false; 673 } 674 675 // ----------------------------------------------------------------------- 676 677 sal_Bool Os2SalGraphics::drawPolyLineBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 678 { 679 return sal_False; 680 } 681 682 // ----------------------------------------------------------------------- 683 684 sal_Bool Os2SalGraphics::drawPolygonBezier( ULONG nPoints, const SalPoint* pPtAry, const BYTE* pFlgAry ) 685 { 686 return sal_False; 687 } 688 689 // ----------------------------------------------------------------------- 690 691 sal_Bool Os2SalGraphics::drawPolyPolygonBezier( ULONG nPoly, const ULONG* pPoints, 692 const SalPoint* const* pPtAry, const BYTE* const* pFlgAry ) 693 { 694 return sal_False; 695 } 696 697 // ======================================================================= 698 699 // MAXIMUM BUFSIZE EQ 0xFFFF 700 #define POSTSCRIPT_BUFSIZE 0x4000 701 // we only try to get the BoundingBox in the first 4096 bytes 702 #define POSTSCRIPT_BOUNDINGSEARCH 0x1000 703 704 static BYTE* ImplSearchEntry( BYTE* pSource, BYTE* pDest, ULONG nComp, ULONG nSize ) 705 { 706 while ( nComp-- >= nSize ) 707 { 708 ULONG i; 709 for ( i = 0; i < nSize; i++ ) 710 { 711 if ( ( pSource[i]&~0x20 ) != ( pDest[i]&~0x20 ) ) 712 break; 713 } 714 if ( i == nSize ) 715 return pSource; 716 pSource++; 717 } 718 return NULL; 719 } 720 721 722 static BOOL ImplGetBoundingBox( double* nNumb, BYTE* pSource, ULONG nSize ) 723 { 724 BOOL bRetValue = FALSE; 725 BYTE* pDest = ImplSearchEntry( pSource, (BYTE*)"%%BoundingBox:", nSize, 14 ); 726 if ( pDest ) 727 { 728 nNumb[0] = nNumb[1] = nNumb[2] = nNumb[3] = 0; 729 pDest += 14; 730 731 int nSizeLeft = nSize - ( pDest - pSource ); 732 if ( nSizeLeft > 100 ) 733 nSizeLeft = 100; // only 100 bytes following the bounding box will be checked 734 735 int i; 736 for ( i = 0; ( i < 4 ) && nSizeLeft; i++ ) 737 { 738 int nDivision = 1; 739 BOOL bDivision = FALSE; 740 BOOL bNegative = FALSE; 741 BOOL bValid = TRUE; 742 743 while ( ( --nSizeLeft ) && ( *pDest == ' ' ) || ( *pDest == 0x9 ) ) pDest++; 744 BYTE nByte = *pDest; 745 while ( nSizeLeft && ( nByte != ' ' ) && ( nByte != 0x9 ) && ( nByte != 0xd ) && ( nByte != 0xa ) ) 746 { 747 switch ( nByte ) 748 { 749 case '.' : 750 if ( bDivision ) 751 bValid = FALSE; 752 else 753 bDivision = TRUE; 754 break; 755 case '-' : 756 bNegative = TRUE; 757 break; 758 default : 759 if ( ( nByte < '0' ) || ( nByte > '9' ) ) 760 nSizeLeft = 1; // error parsing the bounding box values 761 else if ( bValid ) 762 { 763 if ( bDivision ) 764 nDivision*=10; 765 nNumb[i] *= 10; 766 nNumb[i] += nByte - '0'; 767 } 768 break; 769 } 770 nSizeLeft--; 771 nByte = *(++pDest); 772 } 773 if ( bNegative ) 774 nNumb[i] = -nNumb[i]; 775 if ( bDivision && ( nDivision != 1 ) ) 776 nNumb[i] /= nDivision; 777 } 778 if ( i == 4 ) 779 bRetValue = TRUE; 780 } 781 return bRetValue; 782 } 783 784 #if 0 785 static void ImplWriteDouble( BYTE** pBuf, double nNumber ) 786 { 787 // *pBuf += sprintf( (char*)*pBuf, "%f", nNumber ); 788 789 if ( nNumber < 0 ) 790 { 791 *(*pBuf)++ = (BYTE)'-'; 792 nNumber = -nNumber; 793 } 794 ULONG nTemp = (ULONG)nNumber; 795 const String aNumber1( nTemp ); 796 ULONG nLen = aNumber1.Len(); 797 798 for ( USHORT n = 0; n < nLen; n++ ) 799 *(*pBuf)++ = aNumber1[ n ]; 800 801 nTemp = (ULONG)( ( nNumber - nTemp ) * 100000 ); 802 if ( nTemp ) 803 { 804 *(*pBuf)++ = (BYTE)'.'; 805 const String aNumber2( nTemp ); 806 807 ULONG nLen = aNumber2.Len(); 808 if ( nLen < 8 ) 809 { 810 for ( n = 0; n < ( 5 - nLen ); n++ ) 811 { 812 *(*pBuf)++ = (BYTE)'0'; 813 } 814 } 815 for ( USHORT n = 0; n < nLen; n++ ) 816 { 817 *(*pBuf)++ = aNumber2[ n ]; 818 } 819 } 820 *(*pBuf)++ = ' '; 821 } 822 #endif 823 824 inline void ImplWriteString( BYTE** pBuf, const char* sString ) 825 { 826 strcpy( (char*)*pBuf, sString ); 827 *pBuf += strlen( sString ); 828 } 829 830 BOOL Os2SalGraphics::drawEPS( long nX, long nY, long nWidth, long nHeight, void* pPtr, ULONG nSize ) 831 { 832 if ( !mbPrinter ) 833 return FALSE; 834 835 BOOL bRet = FALSE; 836 LONG nLong = 0; 837 if ( !(DevQueryCaps( mhDC, CAPS_TECHNOLOGY, 1, &nLong ) && 838 (CAPS_TECH_POSTSCRIPT == nLong)) ) 839 return FALSE; 840 841 BYTE* pBuf = new BYTE[ POSTSCRIPT_BUFSIZE ]; 842 double nBoundingBox[4]; 843 844 if ( pBuf && ImplGetBoundingBox( nBoundingBox, (BYTE*)pPtr, nSize ) ) 845 { 846 LONG pOS2DXAry[4]; // hack -> print always 2 white space 847 POINTL aPt; 848 aPt.x = 0; 849 aPt.y = 0; 850 PCH pStr = (PCH) " "; 851 for( long i = 0; i < 4; i++ ) 852 pOS2DXAry[i] = i; 853 Ft2CharStringPosAt( mhPS, &aPt, NULL, 0, 2, (PCH)pStr,(PLONG)&pOS2DXAry[0] ); 854 855 OStringBuffer aBuf( POSTSCRIPT_BUFSIZE ); 856 857 // reserve place for a USHORT 858 aBuf.append( "aa" ); 859 860 // #107797# Write out EPS encapsulation header 861 // ---------------------------------------------------------------------------------- 862 863 // directly taken from the PLRM 3.0, p. 726. Note: 864 // this will definitely cause problems when 865 // recursively creating and embedding PostScript files 866 // in OOo, since we use statically-named variables 867 // here (namely, b4_Inc_state_salWin, dict_count_salWin and 868 // op_count_salWin). Currently, I have no idea on how to 869 // work around that, except from scanning and 870 // interpreting the EPS for unused identifiers. 871 872 // append the real text 873 aBuf.append( "\n\n/b4_Inc_state_salWin save def\n" 874 "/dict_count_salWin countdictstack def\n" 875 "/op_count_salWin count 1 sub def\n" 876 "userdict begin\n" 877 "/showpage {} def\n" 878 "0 setgray 0 setlinecap\n" 879 "1 setlinewidth 0 setlinejoin\n" 880 "10 setmiterlimit [] 0 setdash newpath\n" 881 "/languagelevel where\n" 882 "{\n" 883 " pop languagelevel\n" 884 " 1 ne\n" 885 " {\n" 886 " false setstrokeadjust false setoverprint\n" 887 " } if\n" 888 "} if\n\n" ); 889 890 #if 0 891 // #i10737# Apply clipping manually 892 // ---------------------------------------------------------------------------------- 893 894 // Windows seems to ignore any clipping at the HDC, 895 // when followed by a POSTSCRIPT_PASSTHROUGH 896 897 // Check whether we've got a clipping, consisting of 898 // exactly one rect (other cases should be, but aren't 899 // handled currently) 900 901 // TODO: Handle more than one rectangle here (take 902 // care, the buffer can handle only POSTSCRIPT_BUFSIZE 903 // characters!) 904 if ( mhRegion != 0 && 905 mpStdClipRgnData != NULL && 906 mpClipRgnData == mpStdClipRgnData && 907 mpClipRgnData->rdh.nCount == 1 ) 908 { 909 RECT* pRect = &(mpClipRgnData->rdh.rcBound); 910 911 aBuf.append( "\nnewpath\n" ); 912 aBuf.append( pRect->left ); 913 aBuf.append( " " ); 914 aBuf.append( pRect->top ); 915 aBuf.append( " moveto\n" ); 916 aBuf.append( pRect->right ); 917 aBuf.append( " " ); 918 aBuf.append( pRect->top ); 919 aBuf.append( " lineto\n" ); 920 aBuf.append( pRect->right ); 921 aBuf.append( " " ); 922 aBuf.append( pRect->bottom ); 923 aBuf.append( " lineto\n" ); 924 aBuf.append( pRect->left ); 925 aBuf.append( " " ); 926 aBuf.append( pRect->bottom ); 927 aBuf.append( " lineto\n" 928 "closepath\n" 929 "clip\n" 930 "newpath\n" ); 931 } 932 #endif 933 934 // #107797# Write out buffer 935 // ---------------------------------------------------------------------------------- 936 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 ); 937 //Escape ( mhDC, nEscape, aBuf.getLength(), (LPTSTR)aBuf.getStr(), 0 ); 938 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(), 939 (PBYTE)aBuf.getStr(), 0, NULL ); 940 941 double dM11 = nWidth / ( nBoundingBox[2] - nBoundingBox[0] ); 942 double dM22 = - ( nHeight / (nBoundingBox[1] - nBoundingBox[3] ) ); 943 944 // reserve a USHORT again 945 aBuf.setLength( 2 ); 946 aBuf.append( "\n\n[" ); 947 aBuf.append( dM11 ); 948 aBuf.append( " 0 0 " ); 949 aBuf.append( dM22 ); 950 aBuf.append( ' ' ); 951 aBuf.append( nX - ( dM11 * nBoundingBox[0] ) ); 952 aBuf.append( ' ' ); 953 aBuf.append( nY - ( dM22 * nBoundingBox[3] ) ); 954 aBuf.append( "] concat\n" 955 "%%BeginDocument:\n" ); 956 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 ); 957 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(), 958 (PBYTE)aBuf.getStr(), 0, NULL ); 959 #if 0 960 BYTE* pTemp = pBuf; 961 ImplWriteString( &pTemp, "save\n[ " ); 962 ImplWriteDouble( &pTemp, dM11 ); 963 ImplWriteDouble( &pTemp, 0 ); 964 ImplWriteDouble( &pTemp, 0 ); 965 ImplWriteDouble( &pTemp, dM22 ); 966 ImplWriteDouble( &pTemp, nX - ( dM11 * nBoundingBox[0] ) ); 967 ImplWriteDouble( &pTemp, mnHeight - nY - ( dM22 * nBoundingBox[3] ) ); 968 ImplWriteString( &pTemp, "] concat /showpage {} def\n" ); 969 970 if ( DevEscape( mhDC, DEVESC_RAWDATA, pTemp - pBuf, 971 (PBYTE)pBuf, 0, NULL ) == DEV_OK ) 972 #endif // 973 { 974 UINT32 nToDo = nSize; 975 UINT32 nDoNow; 976 bRet = TRUE; 977 while( nToDo && bRet ) 978 { 979 nDoNow = 0x4000; 980 if ( nToDo < nDoNow ) 981 nDoNow = nToDo; 982 983 if ( DevEscape( mhDC, DEVESC_RAWDATA, nDoNow, (PBYTE)pPtr + nSize - nToDo, 984 0, NULL ) == -1 ) 985 bRet = FALSE; 986 nToDo -= nDoNow; 987 } 988 989 if ( bRet ) 990 { 991 strcpy ( (char*)pBuf, "\nrestore\n" ); 992 if ( DevEscape( mhDC, DEVESC_RAWDATA, 9, (PBYTE)pBuf, 993 0, NULL ) == DEV_OK ) bRet = TRUE; 994 } 995 996 // #107797# Write out EPS encapsulation footer 997 // ---------------------------------------------------------------------------------- 998 // reserve a USHORT again 999 aBuf.setLength( 2 ); 1000 aBuf.append( "%%EndDocument\n" 1001 "count op_count_salWin sub {pop} repeat\n" 1002 "countdictstack dict_count_salWin sub {end} repeat\n" 1003 "b4_Inc_state_salWin restore\n\n" ); 1004 *((USHORT*)aBuf.getStr()) = (USHORT)( aBuf.getLength() - 2 ); 1005 DevEscape( mhDC, DEVESC_RAWDATA, aBuf.getLength(), 1006 (PBYTE)aBuf.getStr(), 0, NULL ); 1007 bRet = TRUE; 1008 1009 } 1010 } 1011 delete [] pBuf; 1012 return bRet; 1013 } 1014 1015 /* 1016 * IsNativeControlSupported() 1017 * 1018 * Returns TRUE if the platform supports native 1019 * drawing of the control defined by nPart 1020 */ 1021 BOOL Os2SalGraphics::IsNativeControlSupported( ControlType nType, ControlPart nPart ) 1022 { 1023 return( FALSE ); 1024 } 1025 1026 // ----------------------------------------------------------------------- 1027 1028 SystemGraphicsData Os2SalGraphics::GetGraphicsData() const 1029 { 1030 SystemGraphicsData aRes; 1031 aRes.nSize = sizeof(aRes); 1032 #if 0 1033 aRes.hDC = mhDC; 1034 #endif 1035 return aRes; 1036 } 1037 1038 // ----------------------------------------------------------------------- 1039