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