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