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