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