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 // MARKER(update_precomp.py): autogen include statement, do not remove 25 #include "precompiled_vcl.hxx" 26 27 #include "tools/debug.hxx" 28 29 #include "basegfx/polygon/b2dpolygon.hxx" 30 #include "basegfx/polygon/b2dpolypolygon.hxx" 31 #include "basegfx/polygon/b2dpolypolygontools.hxx" 32 #include "basegfx/polygon/b2dpolygontools.hxx" 33 #include "basegfx/polygon/b2dpolygonclipper.hxx" 34 #include "basegfx/polygon/b2dlinegeometry.hxx" 35 #include "basegfx/matrix/b2dhommatrix.hxx" 36 #include "basegfx/matrix/b2dhommatrixtools.hxx" 37 #include "basegfx/polygon/b2dpolypolygoncutter.hxx" 38 #include "basegfx/polygon/b2dtrapezoid.hxx" 39 40 #include "vcl/jobdata.hxx" 41 42 #include "unx/Xproto.h" 43 #include "unx/salunx.h" 44 #include "unx/saldata.hxx" 45 #include "unx/saldisp.hxx" 46 #include "unx/salgdi.h" 47 #include "unx/salframe.h" 48 #include "unx/salvd.h" 49 50 #include "printergfx.hxx" 51 #include "xrender_peer.hxx" 52 53 #include <vector> 54 #include <queue> 55 #include <set> 56 57 // -=-= SalPolyLine =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 58 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 59 #define STATIC_POINTS 64 60 61 class SalPolyLine 62 { 63 XPoint Points_[STATIC_POINTS]; 64 XPoint *pFirst_; 65 public: 66 inline SalPolyLine( sal_uLong nPoints ); 67 inline SalPolyLine( sal_uLong nPoints, const SalPoint *p ); 68 inline ~SalPolyLine(); 69 inline XPoint &operator [] ( sal_uLong n ) const 70 { return pFirst_[n]; } 71 }; 72 73 inline SalPolyLine::SalPolyLine( sal_uLong nPoints ) 74 : pFirst_( nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_ ) 75 {} 76 77 inline SalPolyLine::SalPolyLine( sal_uLong nPoints, const SalPoint *p ) 78 : pFirst_( nPoints+1 > STATIC_POINTS ? new XPoint[nPoints+1] : Points_ ) 79 { 80 for( sal_uLong i = 0; i < nPoints; i++ ) 81 { 82 pFirst_[i].x = (short)p[i].mnX; 83 pFirst_[i].y = (short)p[i].mnY; 84 } 85 pFirst_[nPoints] = pFirst_[0]; // close polyline 86 } 87 88 inline SalPolyLine::~SalPolyLine() 89 { if( pFirst_ != Points_ ) delete [] pFirst_; } 90 91 #undef STATIC_POINTS 92 // -=-= X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 93 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 94 X11SalGraphics::X11SalGraphics() 95 { 96 m_pFrame = NULL; 97 m_pVDev = NULL; 98 m_pDeleteColormap = NULL; 99 hDrawable_ = None; 100 m_aRenderPicture = 0; 101 m_pRenderFormat = NULL; 102 103 mpClipRegion = NULL; 104 pPaintRegion_ = NULL; 105 106 pPenGC_ = NULL; 107 nPenPixel_ = 0; 108 nPenColor_ = MAKE_SALCOLOR( 0x00, 0x00, 0x00 ); // Black 109 110 pFontGC_ = NULL; 111 for( int i = 0; i < MAX_FALLBACK; ++i ) 112 mpServerFont[i] = NULL; 113 114 nTextPixel_ = 0; 115 nTextColor_ = MAKE_SALCOLOR( 0x00, 0x00, 0x00 ); // Black 116 117 #ifdef ENABLE_GRAPHITE 118 // check if graphite fonts have been disabled 119 static const char* pDisableGraphiteStr = getenv( "SAL_DISABLE_GRAPHITE" ); 120 bDisableGraphite_ = pDisableGraphiteStr ? (pDisableGraphiteStr[0]!='0') : sal_False; 121 #endif 122 123 pBrushGC_ = NULL; 124 nBrushPixel_ = 0; 125 nBrushColor_ = MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ); // White 126 hBrush_ = None; 127 128 pMonoGC_ = NULL; 129 pCopyGC_ = NULL; 130 pMaskGC_ = NULL; 131 pInvertGC_ = NULL; 132 pInvert50GC_ = NULL; 133 pStippleGC_ = NULL; 134 pTrackingGC_ = NULL; 135 136 bWindow_ = sal_False; 137 bPrinter_ = sal_False; 138 bVirDev_ = sal_False; 139 bPenGC_ = sal_False; 140 bFontGC_ = sal_False; 141 bBrushGC_ = sal_False; 142 bMonoGC_ = sal_False; 143 bCopyGC_ = sal_False; 144 bInvertGC_ = sal_False; 145 bInvert50GC_ = sal_False; 146 bStippleGC_ = sal_False; 147 bTrackingGC_ = sal_False; 148 bXORMode_ = sal_False; 149 bDitherBrush_ = sal_False; 150 } 151 152 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 153 X11SalGraphics::~X11SalGraphics() 154 { 155 ReleaseFonts(); 156 freeResources(); 157 } 158 159 // -=-= SalGraphics / X11SalGraphics =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 160 161 void X11SalGraphics::freeResources() 162 { 163 Display *pDisplay = GetXDisplay(); 164 165 DBG_ASSERT( !pPaintRegion_, "pPaintRegion_" ); 166 if( mpClipRegion ) XDestroyRegion( mpClipRegion ), mpClipRegion = None; 167 168 if( hBrush_ ) XFreePixmap( pDisplay, hBrush_ ), hBrush_ = None; 169 if( pPenGC_ ) XFreeGC( pDisplay, pPenGC_ ), pPenGC_ = None; 170 if( pFontGC_ ) XFreeGC( pDisplay, pFontGC_ ), pFontGC_ = None; 171 if( pBrushGC_ ) XFreeGC( pDisplay, pBrushGC_ ), pBrushGC_ = None; 172 if( pMonoGC_ ) XFreeGC( pDisplay, pMonoGC_ ), pMonoGC_ = None; 173 if( pCopyGC_ ) XFreeGC( pDisplay, pCopyGC_ ), pCopyGC_ = None; 174 if( pMaskGC_ ) XFreeGC( pDisplay, pMaskGC_ ), pMaskGC_ = None; 175 if( pInvertGC_ ) XFreeGC( pDisplay, pInvertGC_ ), pInvertGC_ = None; 176 if( pInvert50GC_ ) XFreeGC( pDisplay, pInvert50GC_ ), pInvert50GC_ = None; 177 if( pStippleGC_ ) XFreeGC( pDisplay, pStippleGC_ ), pStippleGC_ = None; 178 if( pTrackingGC_ ) XFreeGC( pDisplay, pTrackingGC_ ), pTrackingGC_ = None; 179 if( m_pDeleteColormap ) 180 delete m_pDeleteColormap, m_pColormap = m_pDeleteColormap = NULL; 181 182 if( m_aRenderPicture ) 183 XRenderPeer::GetInstance().FreePicture( m_aRenderPicture ), m_aRenderPicture = 0; 184 185 bPenGC_ = bFontGC_ = bBrushGC_ = bMonoGC_ = bCopyGC_ = bInvertGC_ = bInvert50GC_ = bStippleGC_ = bTrackingGC_ = false; 186 } 187 188 void X11SalGraphics::SetDrawable( Drawable aDrawable, int nScreen ) 189 { 190 // shortcut if nothing changed 191 if( hDrawable_ == aDrawable ) 192 return; 193 194 // free screen specific resources if needed 195 if( nScreen != m_nScreen ) 196 { 197 freeResources(); 198 m_pColormap = &GetX11SalData()->GetDisplay()->GetColormap( nScreen ); 199 m_nScreen = nScreen; 200 } 201 202 hDrawable_ = aDrawable; 203 SetXRenderFormat( NULL ); 204 if( m_aRenderPicture ) 205 { 206 XRenderPeer::GetInstance().FreePicture( m_aRenderPicture ); 207 m_aRenderPicture = 0; 208 } 209 210 if( hDrawable_ ) 211 { 212 nPenPixel_ = GetPixel( nPenColor_ ); 213 nTextPixel_ = GetPixel( nTextColor_ ); 214 nBrushPixel_ = GetPixel( nBrushColor_ ); 215 } 216 } 217 218 void X11SalGraphics::Init( SalFrame *pFrame, Drawable aTarget, int nScreen ) 219 { 220 #if 0 // TODO: use SetDrawable() instead 221 m_pColormap = &GetX11SalData()->GetDisplay()->GetColormap(nScreen); 222 hDrawable_ = aTarget; 223 m_nScreen = nScreen; 224 SetXRenderFormat( NULL ); 225 if( m_aRenderPicture ) 226 XRenderPeer::GetInstance().FreePicture( m_aRenderPicture ), m_aRenderPicture = 0; 227 228 nPenPixel_ = GetPixel( nPenColor_ ); 229 nTextPixel_ = GetPixel( nTextColor_ ); 230 nBrushPixel_ = GetPixel( nBrushColor_ ); 231 #else 232 m_pColormap = &GetX11SalData()->GetDisplay()->GetColormap(nScreen); 233 m_nScreen = nScreen; 234 SetDrawable( aTarget, nScreen ); 235 #endif 236 237 bWindow_ = sal_True; 238 m_pFrame = pFrame; 239 m_pVDev = NULL; 240 } 241 242 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 243 void X11SalGraphics::DeInit() 244 { 245 SetDrawable( None, m_nScreen ); 246 } 247 248 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 249 void X11SalGraphics::SetClipRegion( GC pGC, XLIB_Region pXReg ) const 250 { 251 Display *pDisplay = GetXDisplay(); 252 253 int n = 0; 254 XLIB_Region Regions[3]; 255 256 if( mpClipRegion /* && !XEmptyRegion( mpClipRegion ) */ ) 257 Regions[n++] = mpClipRegion; 258 // if( pPaintRegion_ /* && !XEmptyRegion( pPaintRegion_ ) */ ) 259 // Regions[n++] = pPaintRegion_; 260 261 if( pXReg && !XEmptyRegion( pXReg ) ) 262 Regions[n++] = pXReg; 263 264 if( 0 == n ) 265 XSetClipMask( pDisplay, pGC, None ); 266 else if( 1 == n ) 267 XSetRegion( pDisplay, pGC, Regions[0] ); 268 else 269 { 270 XLIB_Region pTmpRegion = XCreateRegion(); 271 XIntersectRegion( Regions[0], Regions[1], pTmpRegion ); 272 // if( 3 == n ) 273 // XIntersectRegion( Regions[2], pTmpRegion, pTmpRegion ); 274 XSetRegion( pDisplay, pGC, pTmpRegion ); 275 XDestroyRegion( pTmpRegion ); 276 } 277 } 278 279 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 280 GC X11SalGraphics::SelectPen() 281 { 282 Display *pDisplay = GetXDisplay(); 283 284 if( !pPenGC_ ) 285 { 286 XGCValues values; 287 values.subwindow_mode = ClipByChildren; 288 values.fill_rule = EvenOddRule; // Pict import/ Gradient 289 values.graphics_exposures = False; 290 291 pPenGC_ = XCreateGC( pDisplay, hDrawable_, 292 GCSubwindowMode | GCFillRule | GCGraphicsExposures, 293 &values ); 294 } 295 296 if( !bPenGC_ ) 297 { 298 if( nPenColor_ != SALCOLOR_NONE ) 299 XSetForeground( pDisplay, pPenGC_, nPenPixel_ ); 300 XSetFunction ( pDisplay, pPenGC_, bXORMode_ ? GXxor : GXcopy ); 301 SetClipRegion( pPenGC_ ); 302 bPenGC_ = sal_True; 303 } 304 305 return pPenGC_; 306 } 307 308 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 309 GC X11SalGraphics::SelectBrush() 310 { 311 Display *pDisplay = GetXDisplay(); 312 313 DBG_ASSERT( nBrushColor_ != SALCOLOR_NONE, "Brush Transparent" ); 314 315 if( !pBrushGC_ ) 316 { 317 XGCValues values; 318 // values.subwindow_mode = IncludeInferiors; 319 values.subwindow_mode = ClipByChildren; 320 values.fill_rule = EvenOddRule; // Pict import/ Gradient 321 values.graphics_exposures = False; 322 323 pBrushGC_ = XCreateGC( pDisplay, hDrawable_, 324 GCSubwindowMode | GCFillRule | GCGraphicsExposures, 325 &values ); 326 } 327 328 if( !bBrushGC_ ) 329 { 330 if( !bDitherBrush_ ) 331 { 332 XSetFillStyle ( pDisplay, pBrushGC_, FillSolid ); 333 XSetForeground( pDisplay, pBrushGC_, nBrushPixel_ ); 334 if( bPrinter_ ) 335 XSetTile( pDisplay, pBrushGC_, None ); 336 } 337 else 338 { 339 // Bug in Sun Solaris 2.5.1, XFillPolygon doesn't allways reflect 340 // changes of the tile. PROPERTY_BUG_Tile doesn't fix this ! 341 if (GetDisplay()->GetProperties() & PROPERTY_BUG_FillPolygon_Tile) 342 XSetFillStyle ( pDisplay, pBrushGC_, FillSolid ); 343 344 XSetFillStyle ( pDisplay, pBrushGC_, FillTiled ); 345 XSetTile ( pDisplay, pBrushGC_, hBrush_ ); 346 } 347 XSetFunction ( pDisplay, pBrushGC_, bXORMode_ ? GXxor : GXcopy ); 348 SetClipRegion( pBrushGC_ ); 349 350 bBrushGC_ = sal_True; 351 } 352 353 return pBrushGC_; 354 } 355 356 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 357 GC X11SalGraphics::GetTrackingGC() 358 { 359 const char dash_list[2] = {2, 2}; 360 361 if( !pTrackingGC_ ) 362 { 363 XGCValues values; 364 365 values.graphics_exposures = False; 366 values.foreground = m_pColormap->GetBlackPixel() 367 ^ m_pColormap->GetWhitePixel(); 368 values.function = GXxor; 369 values.line_width = 1; 370 values.line_style = LineOnOffDash; 371 372 pTrackingGC_ = XCreateGC( GetXDisplay(), GetDrawable(), 373 GCGraphicsExposures | GCForeground | GCFunction 374 | GCLineWidth | GCLineStyle, 375 &values ); 376 XSetDashes( GetXDisplay(), pTrackingGC_, 0, dash_list, 2 ); 377 } 378 379 if( !bTrackingGC_ ) 380 { 381 SetClipRegion( pTrackingGC_ ); 382 bTrackingGC_ = sal_True; 383 } 384 385 return pTrackingGC_; 386 } 387 388 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 389 void X11SalGraphics::DrawLines( sal_uLong nPoints, 390 const SalPolyLine &rPoints, 391 GC pGC, 392 bool bClose 393 ) 394 { 395 // errechne wie viele Linien XWindow auf einmal zeichnen kann 396 sal_uLong nMaxLines = (GetDisplay()->GetMaxRequestSize() - sizeof(xPolyPointReq)) 397 / sizeof(xPoint); 398 if( nMaxLines > nPoints ) nMaxLines = nPoints; 399 400 // gebe alle Linien aus, die XWindows zeichnen kann. 401 sal_uLong n; 402 for( n = 0; nPoints - n > nMaxLines; n += nMaxLines - 1 ) 403 XDrawLines( GetXDisplay(), 404 GetDrawable(), 405 pGC, 406 &rPoints[n], 407 nMaxLines, 408 CoordModeOrigin ); 409 410 if( n < nPoints ) 411 XDrawLines( GetXDisplay(), 412 GetDrawable(), 413 pGC, 414 &rPoints[n], 415 nPoints - n, 416 CoordModeOrigin ); 417 if( bClose ) 418 { 419 if( rPoints[nPoints-1].x != rPoints[0].x || rPoints[nPoints-1].y != rPoints[0].y ) 420 drawLine( rPoints[nPoints-1].x, rPoints[nPoints-1].y, rPoints[0].x, rPoints[0].y ); 421 } 422 } 423 424 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 425 // Dithern: Calculate a dither-pixmap and make a brush of it 426 #define P_DELTA 51 427 #define DMAP( v, m ) ((v % P_DELTA) > m ? (v / P_DELTA) + 1 : (v / P_DELTA)) 428 429 BOOL X11SalGraphics::GetDitherPixmap( SalColor nSalColor ) 430 { 431 static const short nOrdDither8Bit[ 8 ][ 8 ] = 432 { 433 { 0, 38, 9, 48, 2, 40, 12, 50}, 434 {25, 12, 35, 22, 28, 15, 37, 24}, 435 { 6, 44, 3, 41, 8, 47, 5, 44}, 436 {32, 19, 28, 16, 34, 21, 31, 18}, 437 { 1, 40, 11, 49, 0, 39, 10, 48}, 438 {27, 14, 36, 24, 26, 13, 36, 23}, 439 { 8, 46, 4, 43, 7, 45, 4, 42}, 440 {33, 20, 30, 17, 32, 20, 29, 16} 441 }; 442 443 // test for correct depth (8bit) 444 if( GetColormap().GetVisual().GetDepth() != 8 ) 445 return sal_False; 446 447 char pBits[64]; 448 char *pBitsPtr = pBits; 449 450 // Set the pallette-entries for the dithering tile 451 sal_uInt8 nSalColorRed = SALCOLOR_RED ( nSalColor ); 452 sal_uInt8 nSalColorGreen = SALCOLOR_GREEN ( nSalColor ); 453 sal_uInt8 nSalColorBlue = SALCOLOR_BLUE ( nSalColor ); 454 455 for( int nY = 0; nY < 8; nY++ ) 456 { 457 for( int nX = 0; nX < 8; nX++ ) 458 { 459 short nMagic = nOrdDither8Bit[nY][nX]; 460 sal_uInt8 nR = P_DELTA * DMAP( nSalColorRed, nMagic ); 461 sal_uInt8 nG = P_DELTA * DMAP( nSalColorGreen, nMagic ); 462 sal_uInt8 nB = P_DELTA * DMAP( nSalColorBlue, nMagic ); 463 464 *pBitsPtr++ = GetColormap().GetPixel( MAKE_SALCOLOR( nR, nG, nB ) ); 465 } 466 } 467 468 // create the tile as ximage and an according pixmap -> caching 469 XImage *pImage = XCreateImage( GetXDisplay(), 470 GetColormap().GetXVisual(), 471 8, 472 ZPixmap, 473 0, // offset 474 pBits, // data 475 8, 8, // width & height 476 8, // bitmap_pad 477 0 ); // (default) bytes_per_line 478 479 if ( GetDisplay()->GetProperties() & PROPERTY_BUG_Tile ) 480 { 481 if (hBrush_) 482 XFreePixmap (GetXDisplay(), hBrush_); 483 hBrush_ = XCreatePixmap( GetXDisplay(), GetDrawable(), 8, 8, 8 ); 484 } 485 else 486 if( !hBrush_ ) 487 hBrush_ = XCreatePixmap( GetXDisplay(), GetDrawable(), 8, 8, 8 ); 488 489 // put the ximage to the pixmap 490 XPutImage( GetXDisplay(), 491 hBrush_, 492 GetDisplay()->GetCopyGC( m_nScreen ), 493 pImage, 494 0, 0, // Source 495 0, 0, // Destination 496 8, 8 ); // width & height 497 498 // destroy image-frame but not palette-data 499 pImage->data = NULL; 500 XDestroyImage( pImage ); 501 502 return sal_True; 503 } 504 505 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 506 void X11SalGraphics::GetResolution( sal_Int32 &rDPIX, sal_Int32 &rDPIY ) // const 507 { 508 const SalDisplay *pDisplay = GetDisplay(); 509 510 rDPIX = pDisplay->GetResolution().A(); 511 rDPIY = pDisplay->GetResolution().B(); 512 if( !pDisplay->GetExactResolution() && rDPIY < 96 ) 513 { 514 rDPIX = Divide( rDPIX * 96, rDPIY ); 515 rDPIY = 96; 516 } 517 else if ( rDPIY > 200 ) 518 { 519 rDPIX = Divide( rDPIX * 200, rDPIY ); 520 rDPIY = 200; 521 } 522 523 // #i12705# equalize x- and y-resolution if they are close enough 524 if( rDPIX != rDPIY ) 525 { 526 // different x- and y- resolutions are usually artifacts of 527 // a wrongly calculated screen size. 528 //if( (13*rDPIX >= 10*rDPIY) && (13*rDPIY >= 10*rDPIX) ) //+-30% 529 { 530 #ifdef DEBUG 531 printf("Forcing Resolution from %" SAL_PRIdINT32 "x%" SAL_PRIdINT32 " to %" SAL_PRIdINT32 "x%" SAL_PRIdINT32 "\n", 532 rDPIX,rDPIY,rDPIY,rDPIY); 533 #endif 534 rDPIX = rDPIY; // y-resolution is more trustworthy 535 } 536 } 537 } 538 539 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 540 sal_uInt16 X11SalGraphics::GetBitCount() // const 541 { 542 return GetVisual().GetDepth(); 543 } 544 545 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 546 long X11SalGraphics::GetGraphicsWidth() const 547 { 548 if( m_pFrame ) 549 return m_pFrame->maGeometry.nWidth; 550 else if( m_pVDev ) 551 return m_pVDev->GetWidth(); 552 else 553 return 0; 554 } 555 556 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 557 long X11SalGraphics::GetGraphicsHeight() const 558 { 559 if( m_pFrame ) 560 return m_pFrame->maGeometry.nHeight; 561 else if( m_pVDev ) 562 return m_pVDev->GetHeight(); 563 else 564 return 0; 565 } 566 567 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 568 void X11SalGraphics::ResetClipRegion() 569 { 570 if( mpClipRegion ) 571 { 572 bPenGC_ = sal_False; 573 bFontGC_ = sal_False; 574 bBrushGC_ = sal_False; 575 bMonoGC_ = sal_False; 576 bCopyGC_ = sal_False; 577 bInvertGC_ = sal_False; 578 bInvert50GC_ = sal_False; 579 bStippleGC_ = sal_False; 580 bTrackingGC_ = sal_False; 581 582 XDestroyRegion( mpClipRegion ); 583 mpClipRegion = NULL; 584 } 585 } 586 587 bool X11SalGraphics::setClipRegion( const Region& i_rClip ) 588 { 589 if( mpClipRegion ) 590 XDestroyRegion( mpClipRegion ); 591 mpClipRegion = XCreateRegion(); 592 593 RectangleVector aRectangles; 594 i_rClip.GetRegionRectangles(aRectangles); 595 596 for(RectangleVector::const_iterator aRectIter(aRectangles.begin()); aRectIter != aRectangles.end(); aRectIter++) 597 { 598 const long nW(aRectIter->GetWidth()); 599 600 if(nW) 601 { 602 const long nH(aRectIter->GetHeight()); 603 604 if(nH) 605 { 606 XRectangle aRect; 607 608 aRect.x = (short)aRectIter->Left(); 609 aRect.y = (short)aRectIter->Top(); 610 aRect.width = (unsigned short)nW; 611 aRect.height = (unsigned short)nH; 612 XUnionRectWithRegion(&aRect, mpClipRegion, mpClipRegion); 613 } 614 } 615 } 616 617 //ImplRegionInfo aInfo; 618 //long nX, nY, nW, nH; 619 //bool bRegionRect = i_rClip.ImplGetFirstRect(aInfo, nX, nY, nW, nH ); 620 //while( bRegionRect ) 621 //{ 622 // if ( nW && nH ) 623 // { 624 // XRectangle aRect; 625 // aRect.x = (short)nX; 626 // aRect.y = (short)nY; 627 // aRect.width = (unsigned short)nW; 628 // aRect.height = (unsigned short)nH; 629 // 630 // XUnionRectWithRegion( &aRect, mpClipRegion, mpClipRegion ); 631 // } 632 // bRegionRect = i_rClip.ImplGetNextRect( aInfo, nX, nY, nW, nH ); 633 //} 634 635 // done, invalidate GCs 636 bPenGC_ = sal_False; 637 bFontGC_ = sal_False; 638 bBrushGC_ = sal_False; 639 bMonoGC_ = sal_False; 640 bCopyGC_ = sal_False; 641 bInvertGC_ = sal_False; 642 bInvert50GC_ = sal_False; 643 bStippleGC_ = sal_False; 644 bTrackingGC_ = sal_False; 645 646 if( XEmptyRegion( mpClipRegion ) ) 647 { 648 XDestroyRegion( mpClipRegion ); 649 mpClipRegion= NULL; 650 } 651 return true; 652 } 653 654 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 655 void X11SalGraphics::SetLineColor() 656 { 657 if( nPenColor_ != SALCOLOR_NONE ) 658 { 659 nPenColor_ = SALCOLOR_NONE; 660 bPenGC_ = sal_False; 661 } 662 } 663 664 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 665 void X11SalGraphics::SetLineColor( SalColor nSalColor ) 666 { 667 if( nPenColor_ != nSalColor ) 668 { 669 nPenColor_ = nSalColor; 670 nPenPixel_ = GetPixel( nSalColor ); 671 bPenGC_ = sal_False; 672 } 673 } 674 675 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 676 void X11SalGraphics::SetFillColor() 677 { 678 if( nBrushColor_ != SALCOLOR_NONE ) 679 { 680 bDitherBrush_ = sal_False; 681 nBrushColor_ = SALCOLOR_NONE; 682 bBrushGC_ = sal_False; 683 } 684 } 685 686 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 687 void X11SalGraphics::SetFillColor( SalColor nSalColor ) 688 { 689 if( nBrushColor_ != nSalColor ) 690 { 691 bDitherBrush_ = sal_False; 692 nBrushColor_ = nSalColor; 693 nBrushPixel_ = GetPixel( nSalColor ); 694 if( TrueColor != GetColormap().GetVisual().GetClass() 695 && GetColormap().GetColor( nBrushPixel_ ) != nBrushColor_ 696 && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x00 ) // black 697 && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0x80 ) // blue 698 && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x00 ) // green 699 && nSalColor != MAKE_SALCOLOR( 0x00, 0x80, 0x80 ) // cyan 700 && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x00 ) // red 701 && nSalColor != MAKE_SALCOLOR( 0x80, 0x00, 0x80 ) // magenta 702 && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x00 ) // brown 703 && nSalColor != MAKE_SALCOLOR( 0x80, 0x80, 0x80 ) // gray 704 && nSalColor != MAKE_SALCOLOR( 0xC0, 0xC0, 0xC0 ) // light gray 705 && nSalColor != MAKE_SALCOLOR( 0x00, 0x00, 0xFF ) // light blue 706 && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0x00 ) // light green 707 && nSalColor != MAKE_SALCOLOR( 0x00, 0xFF, 0xFF ) // light cyan 708 && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0x00 ) // light red 709 && nSalColor != MAKE_SALCOLOR( 0xFF, 0x00, 0xFF ) // light magenta 710 && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0x00 ) // light brown 711 && nSalColor != MAKE_SALCOLOR( 0xFF, 0xFF, 0xFF ) ) 712 bDitherBrush_ = GetDitherPixmap(nSalColor); 713 bBrushGC_ = sal_False; 714 } 715 } 716 717 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 718 void X11SalGraphics::SetROPLineColor( SalROPColor nROPColor ) 719 { 720 switch( nROPColor ) 721 { 722 case SAL_ROP_0 : // 0 723 nPenPixel_ = (Pixel)0; 724 break; 725 case SAL_ROP_1 : // 1 726 nPenPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; 727 break; 728 case SAL_ROP_INVERT : // 2 729 nPenPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; 730 break; 731 } 732 nPenColor_ = GetColormap().GetColor( nPenPixel_ ); 733 bPenGC_ = sal_False; 734 } 735 736 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 737 void X11SalGraphics::SetROPFillColor( SalROPColor nROPColor ) 738 { 739 switch( nROPColor ) 740 { 741 case SAL_ROP_0 : // 0 742 nBrushPixel_ = (Pixel)0; 743 break; 744 case SAL_ROP_1 : // 1 745 nBrushPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; 746 break; 747 case SAL_ROP_INVERT : // 2 748 nBrushPixel_ = (Pixel)(1 << GetVisual().GetDepth()) - 1; 749 break; 750 } 751 bDitherBrush_ = sal_False; 752 nBrushColor_ = GetColormap().GetColor( nBrushPixel_ ); 753 bBrushGC_ = sal_False; 754 } 755 756 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 757 void X11SalGraphics::SetXORMode( bool bSet, bool ) 758 { 759 if( !bXORMode_ == bSet ) 760 { 761 bXORMode_ = bSet; 762 bPenGC_ = sal_False; 763 bFontGC_ = sal_False; 764 bBrushGC_ = sal_False; 765 bMonoGC_ = sal_False; 766 bCopyGC_ = sal_False; 767 bInvertGC_ = sal_False; 768 bInvert50GC_ = sal_False; 769 bStippleGC_ = sal_False; 770 bTrackingGC_ = sal_False; 771 } 772 } 773 774 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 775 void X11SalGraphics::drawPixel( long nX, long nY ) 776 { 777 if( nPenColor_ != SALCOLOR_NONE ) 778 XDrawPoint( GetXDisplay(), GetDrawable(), SelectPen(), nX, nY ); 779 } 780 781 void X11SalGraphics::drawPixel( long nX, long nY, SalColor nSalColor ) 782 { 783 if( nSalColor != SALCOLOR_NONE ) 784 { 785 Display *pDisplay = GetXDisplay(); 786 787 if( (nPenColor_ == SALCOLOR_NONE) && !bPenGC_ ) 788 { 789 SetLineColor( nSalColor ); 790 XDrawPoint( pDisplay, GetDrawable(), SelectPen(), nX, nY ); 791 nPenColor_ = SALCOLOR_NONE; 792 bPenGC_ = False; 793 } 794 else 795 { 796 GC pGC = SelectPen(); 797 798 if( nSalColor != nPenColor_ ) 799 XSetForeground( pDisplay, pGC, GetPixel( nSalColor ) ); 800 801 XDrawPoint( pDisplay, GetDrawable(), pGC, nX, nY ); 802 803 if( nSalColor != nPenColor_ ) 804 XSetForeground( pDisplay, pGC, nPenPixel_ ); 805 } 806 } 807 } 808 809 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 810 void X11SalGraphics::drawLine( long nX1, long nY1, long nX2, long nY2 ) 811 { 812 if( nPenColor_ != SALCOLOR_NONE ) 813 { 814 if ( GetDisplay()->GetProperties() & PROPERTY_BUG_DrawLine ) 815 { 816 GC aGC = SelectPen(); 817 XDrawPoint (GetXDisplay(), GetDrawable(), aGC, (int)nX1, (int)nY1); 818 XDrawPoint (GetXDisplay(), GetDrawable(), aGC, (int)nX2, (int)nY2); 819 XDrawLine (GetXDisplay(), GetDrawable(), aGC, nX1, nY1, nX2, nY2 ); 820 } 821 else 822 XDrawLine( GetXDisplay(), GetDrawable(),SelectPen(), 823 nX1, nY1, nX2, nY2 ); 824 } 825 } 826 827 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 828 void X11SalGraphics::drawRect( long nX, long nY, long nDX, long nDY ) 829 { 830 if( nBrushColor_ != SALCOLOR_NONE ) 831 { 832 XFillRectangle( GetXDisplay(), 833 GetDrawable(), 834 SelectBrush(), 835 nX, nY, nDX, nDY ); 836 } 837 // Beschreibung DrawRect verkehrt, deshalb -1 838 if( nPenColor_ != SALCOLOR_NONE ) 839 XDrawRectangle( GetXDisplay(), 840 GetDrawable(), 841 SelectPen(), 842 nX, nY, nDX-1, nDY-1 ); 843 } 844 845 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 846 void X11SalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint *pPtAry ) 847 { 848 drawPolyLine( nPoints, pPtAry, false ); 849 } 850 851 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 852 void X11SalGraphics::drawPolyLine( sal_uLong nPoints, const SalPoint *pPtAry, bool bClose ) 853 { 854 if( nPenColor_ != SALCOLOR_NONE) 855 { 856 SalPolyLine Points( nPoints, pPtAry ); 857 858 DrawLines( nPoints, Points, SelectPen(), bClose ); 859 } 860 } 861 862 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 863 void X11SalGraphics::drawPolygon( sal_uLong nPoints, const SalPoint* pPtAry ) 864 { 865 if( nPoints == 0 ) 866 return; 867 868 if( nPoints < 3 ) 869 { 870 if( !bXORMode_ ) 871 { 872 if( 1 == nPoints ) 873 drawPixel( pPtAry[0].mnX, pPtAry[0].mnY ); 874 else 875 drawLine( pPtAry[0].mnX, pPtAry[0].mnY, 876 pPtAry[1].mnX, pPtAry[1].mnY ); 877 } 878 return; 879 } 880 881 SalPolyLine Points( nPoints, pPtAry ); 882 883 nPoints++; 884 885 /* WORKAROUND: some Xservers (Xorg, VIA chipset in this case) 886 * do not draw the visible part of a polygon 887 * if it overlaps to the left of screen 0,y. 888 * This happens to be the case in the gradient drawn in the 889 * menubar background. workaround for the special case of 890 * of a rectangle overlapping to the left. 891 */ 892 if( nPoints == 5 && 893 Points[ 0 ].x == Points[ 1 ].x && 894 Points[ 1 ].y == Points[ 2 ].y && 895 Points[ 2 ].x == Points[ 3 ].x && 896 Points[ 0 ].x == Points[ 4 ].x && Points[ 0 ].y == Points[ 4 ].y 897 ) 898 { 899 bool bLeft = false; 900 bool bRight = false; 901 for(unsigned int i = 0; i < nPoints; i++ ) 902 { 903 if( Points[i].x < 0 ) 904 bLeft = true; 905 else 906 bRight= true; 907 } 908 if( bLeft && ! bRight ) 909 return; 910 if( bLeft && bRight ) 911 { 912 for( unsigned int i = 0; i < nPoints; i++ ) 913 if( Points[i].x < 0 ) 914 Points[i].x = 0; 915 } 916 } 917 918 if( nBrushColor_ != SALCOLOR_NONE ) 919 XFillPolygon( GetXDisplay(), 920 GetDrawable(), 921 SelectBrush(), 922 &Points[0], nPoints, 923 Complex, CoordModeOrigin ); 924 925 if( nPenColor_ != SALCOLOR_NONE) 926 DrawLines( nPoints, Points, SelectPen(), true ); 927 } 928 929 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 930 void X11SalGraphics::drawPolyPolygon( sal_uInt32 nPoly, 931 const sal_uInt32 *pPoints, 932 PCONSTSALPOINT *pPtAry ) 933 { 934 if( nBrushColor_ != SALCOLOR_NONE ) 935 { 936 sal_uInt32 i, n; 937 XLIB_Region pXRegA = NULL; 938 939 for( i = 0; i < nPoly; i++ ) { 940 n = pPoints[i]; 941 SalPolyLine Points( n, pPtAry[i] ); 942 if( n > 2 ) 943 { 944 XLIB_Region pXRegB = XPolygonRegion( &Points[0], n+1, WindingRule ); 945 if( !pXRegA ) 946 pXRegA = pXRegB; 947 else 948 { 949 XXorRegion( pXRegA, pXRegB, pXRegA ); 950 XDestroyRegion( pXRegB ); 951 } 952 } 953 } 954 955 if( pXRegA ) 956 { 957 XRectangle aXRect; 958 XClipBox( pXRegA, &aXRect ); 959 960 GC pGC = SelectBrush(); 961 SetClipRegion( pGC, pXRegA ); // ??? doppelt 962 XDestroyRegion( pXRegA ); 963 bBrushGC_ = sal_False; 964 965 XFillRectangle( GetXDisplay(), 966 GetDrawable(), 967 pGC, 968 aXRect.x, aXRect.y, aXRect.width, aXRect.height ); 969 } 970 } 971 972 if( nPenColor_ != SALCOLOR_NONE ) 973 for( sal_uInt32 i = 0; i < nPoly; i++ ) 974 drawPolyLine( pPoints[i], pPtAry[i], true ); 975 } 976 977 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 978 979 sal_Bool X11SalGraphics::drawPolyLineBezier( sal_uLong, const SalPoint*, const BYTE* ) 980 { 981 return sal_False; 982 } 983 984 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 985 986 sal_Bool X11SalGraphics::drawPolygonBezier( sal_uLong, const SalPoint*, const BYTE* ) 987 { 988 return sal_False; 989 } 990 991 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 992 993 sal_Bool X11SalGraphics::drawPolyPolygonBezier( sal_uInt32, const sal_uInt32*, 994 const SalPoint* const*, const BYTE* const* ) 995 { 996 return sal_False; 997 } 998 999 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1000 1001 void X11SalGraphics::invert( sal_uLong nPoints, 1002 const SalPoint* pPtAry, 1003 SalInvert nFlags ) 1004 { 1005 SalPolyLine Points ( nPoints, pPtAry ); 1006 1007 GC pGC; 1008 if( SAL_INVERT_50 & nFlags ) 1009 pGC = GetInvert50GC(); 1010 else 1011 if ( SAL_INVERT_TRACKFRAME & nFlags ) 1012 pGC = GetTrackingGC(); 1013 else 1014 pGC = GetInvertGC(); 1015 1016 if( SAL_INVERT_TRACKFRAME & nFlags ) 1017 DrawLines ( nPoints, Points, pGC, true ); 1018 else 1019 XFillPolygon( GetXDisplay(), 1020 GetDrawable(), 1021 pGC, 1022 &Points[0], nPoints, 1023 Complex, CoordModeOrigin ); 1024 } 1025 1026 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1027 1028 BOOL X11SalGraphics::drawEPS( long,long,long,long,void*,sal_uLong ) 1029 { 1030 return sal_False; 1031 } 1032 1033 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1034 1035 XID X11SalGraphics::GetXRenderPicture() 1036 { 1037 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); 1038 1039 if( !m_aRenderPicture ) 1040 { 1041 // check xrender support for matching visual 1042 // find a XRenderPictFormat compatible with the Drawable 1043 XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat()); 1044 if( !pVisualFormat ) 1045 { 1046 Visual* pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual(); 1047 pVisualFormat = rRenderPeer.FindVisualFormat( pVisual ); 1048 if( !pVisualFormat ) 1049 return 0; 1050 // cache the XRenderPictFormat 1051 SetXRenderFormat( static_cast<void*>(pVisualFormat) ); 1052 } 1053 1054 // get the matching xrender target for drawable 1055 m_aRenderPicture = rRenderPeer.CreatePicture( hDrawable_, pVisualFormat, 0, NULL ); 1056 } 1057 1058 #if 0 1059 // setup clipping so the callers don't have to do it themselves 1060 // TODO: avoid clipping if already set correctly 1061 if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) 1062 rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion ); 1063 else 1064 #endif 1065 { 1066 // reset clip region 1067 // TODO: avoid clip reset if already done 1068 XRenderPictureAttributes aAttr; 1069 aAttr.clip_mask = None; 1070 rRenderPeer.ChangePicture( m_aRenderPicture, CPClipMask, &aAttr ); 1071 } 1072 1073 return m_aRenderPicture; 1074 } 1075 1076 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1077 1078 SystemGraphicsData X11SalGraphics::GetGraphicsData() const 1079 { 1080 SystemGraphicsData aRes; 1081 1082 aRes.nSize = sizeof(aRes); 1083 aRes.pDisplay = GetXDisplay(); 1084 aRes.hDrawable = hDrawable_; 1085 aRes.pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual(); 1086 aRes.nScreen = m_nScreen; 1087 aRes.nDepth = GetDisplay()->GetVisual( m_nScreen ).GetDepth(); 1088 aRes.aColormap = GetDisplay()->GetColormap( m_nScreen ).GetXColormap(); 1089 aRes.pRenderFormat = m_pRenderFormat; 1090 return aRes; 1091 } 1092 1093 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1094 1095 // draw a poly-polygon 1096 bool X11SalGraphics::drawPolyPolygon( const ::basegfx::B2DPolyPolygon& rOrigPolyPoly, double fTransparency ) 1097 { 1098 // nothing to do for empty polypolygons 1099 const int nOrigPolyCount = rOrigPolyPoly.count(); 1100 if( nOrigPolyCount <= 0 ) 1101 return sal_True; 1102 1103 // nothing to do if everything is transparent 1104 if( (nBrushColor_ == SALCOLOR_NONE) 1105 && (nPenColor_ == SALCOLOR_NONE) ) 1106 return sal_True; 1107 1108 // cannot handle pencolor!=brushcolor yet 1109 if( (nPenColor_ != SALCOLOR_NONE) 1110 && (nPenColor_ != nBrushColor_) ) 1111 return sal_False; 1112 1113 // TODO: remove the env-variable when no longer needed 1114 static const char* pRenderEnv = getenv( "SAL_DISABLE_RENDER_POLY" ); 1115 if( pRenderEnv ) 1116 return sal_False; 1117 1118 // snap to raster if requested 1119 basegfx::B2DPolyPolygon aPolyPoly = rOrigPolyPoly; 1120 const bool bSnapToRaster = !getAntiAliasB2DDraw(); 1121 if( bSnapToRaster ) 1122 aPolyPoly = basegfx::tools::snapPointsOfHorizontalOrVerticalEdges( aPolyPoly ); 1123 1124 // don't bother with polygons outside of visible area 1125 const basegfx::B2DRange aViewRange( 0, 0, GetGraphicsWidth(), GetGraphicsHeight() ); 1126 aPolyPoly = basegfx::tools::clipPolyPolygonOnRange( aPolyPoly, aViewRange, true, false ); 1127 if( !aPolyPoly.count() ) 1128 return true; 1129 1130 // tesselate the polypolygon into trapezoids 1131 basegfx::B2DTrapezoidVector aB2DTrapVector; 1132 basegfx::tools::trapezoidSubdivide( aB2DTrapVector, aPolyPoly ); 1133 const int nTrapCount = aB2DTrapVector.size(); 1134 if( !nTrapCount ) 1135 return true; 1136 const bool bDrawn = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency ); 1137 return bDrawn; 1138 } 1139 1140 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1141 1142 bool X11SalGraphics::drawFilledTrapezoids( const ::basegfx::B2DTrapezoid* pB2DTraps, int nTrapCount, double fTransparency ) 1143 { 1144 if( nTrapCount <= 0 ) 1145 return true; 1146 1147 Picture aDstPic = GetXRenderPicture(); 1148 // check xrender support for this drawable 1149 if( !aDstPic ) 1150 return false; 1151 1152 // convert the B2DTrapezoids into XRender-Trapezoids 1153 typedef std::vector<XTrapezoid> TrapezoidVector; 1154 TrapezoidVector aTrapVector( nTrapCount ); 1155 const basegfx::B2DTrapezoid* pB2DTrap = pB2DTraps; 1156 for( int i = 0; i < nTrapCount; ++pB2DTrap, ++i ) 1157 { 1158 XTrapezoid& rTrap = aTrapVector[ i ] ; 1159 1160 // set y-coordinates 1161 const double fY1 = pB2DTrap->getTopY(); 1162 rTrap.left.p1.y = rTrap.right.p1.y = rTrap.top = XDoubleToFixed( fY1 ); 1163 const double fY2 = pB2DTrap->getBottomY(); 1164 rTrap.left.p2.y = rTrap.right.p2.y = rTrap.bottom = XDoubleToFixed( fY2 ); 1165 1166 // set x-coordinates 1167 const double fXL1 = pB2DTrap->getTopXLeft(); 1168 rTrap.left.p1.x = XDoubleToFixed( fXL1 ); 1169 const double fXR1 = pB2DTrap->getTopXRight(); 1170 rTrap.right.p1.x = XDoubleToFixed( fXR1 ); 1171 const double fXL2 = pB2DTrap->getBottomXLeft(); 1172 rTrap.left.p2.x = XDoubleToFixed( fXL2 ); 1173 const double fXR2 = pB2DTrap->getBottomXRight(); 1174 rTrap.right.p2.x = XDoubleToFixed( fXR2 ); 1175 } 1176 1177 // get xrender Picture for polygon foreground 1178 // TODO: cache it like the target picture which uses GetXRenderPicture() 1179 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); 1180 SalDisplay::RenderEntry& rEntry = GetDisplay()->GetRenderEntries( m_nScreen )[ 32 ]; 1181 if( !rEntry.m_aPicture ) 1182 { 1183 Display* pXDisplay = GetXDisplay(); 1184 1185 rEntry.m_aPixmap = ::XCreatePixmap( pXDisplay, hDrawable_, 1, 1, 32 ); 1186 XRenderPictureAttributes aAttr; 1187 aAttr.repeat = true; 1188 1189 XRenderPictFormat* pXRPF = rRenderPeer.FindStandardFormat( PictStandardARGB32 ); 1190 rEntry.m_aPicture = rRenderPeer.CreatePicture( rEntry.m_aPixmap, pXRPF, CPRepeat, &aAttr ); 1191 } 1192 1193 // set polygon foreground color and opacity 1194 XRenderColor aRenderColor = GetXRenderColor( nBrushColor_ , fTransparency ); 1195 rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 ); 1196 1197 // set clipping 1198 // TODO: move into GetXRenderPicture? 1199 if( mpClipRegion && !XEmptyRegion( mpClipRegion ) ) 1200 rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion ); 1201 1202 // render the trapezoids 1203 const XRenderPictFormat* pMaskFormat = rRenderPeer.GetStandardFormatA8(); 1204 rRenderPeer.CompositeTrapezoids( PictOpOver, 1205 rEntry.m_aPicture, aDstPic, pMaskFormat, 0, 0, &aTrapVector[0], aTrapVector.size() ); 1206 1207 return true; 1208 } 1209 1210 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1211 1212 bool X11SalGraphics::drawPolyLine( 1213 const ::basegfx::B2DPolygon& rPolygon, 1214 double fTransparency, 1215 const ::basegfx::B2DVector& rLineWidth, 1216 basegfx::B2DLineJoin eLineJoin, 1217 com::sun::star::drawing::LineCap eLineCap) 1218 { 1219 const bool bIsHairline = (rLineWidth.getX() == rLineWidth.getY()) && (rLineWidth.getX() <= 1.2); 1220 1221 // #i101491# 1222 if( !bIsHairline && (rPolygon.count() > 1000) ) 1223 { 1224 // the used basegfx::tools::createAreaGeometry is simply too 1225 // expensive with very big polygons; fallback to caller (who 1226 // should use ImplLineConverter normally) 1227 // AW: ImplLineConverter had to be removed since it does not even 1228 // know LineJoins, so the fallback will now prepare the line geometry 1229 // the same way. 1230 return false; 1231 } 1232 1233 // temporarily adjust brush color to pen color 1234 // since the line is drawn as an area-polygon 1235 const SalColor aKeepBrushColor = nBrushColor_; 1236 nBrushColor_ = nPenColor_; 1237 1238 // #i11575#desc5#b adjust B2D tesselation result to raster positions 1239 basegfx::B2DPolygon aPolygon = rPolygon; 1240 const double fHalfWidth = 0.5 * rLineWidth.getX(); 1241 aPolygon.transform( basegfx::tools::createTranslateB2DHomMatrix(+fHalfWidth,+fHalfWidth) ); 1242 1243 // shortcut for hairline drawing to improve performance 1244 bool bDrawnOk = true; 1245 if( bIsHairline ) 1246 { 1247 // hairlines can benefit from a simplified tesselation 1248 // e.g. for hairlines the linejoin style can be ignored 1249 basegfx::B2DTrapezoidVector aB2DTrapVector; 1250 basegfx::tools::createLineTrapezoidFromB2DPolygon( aB2DTrapVector, aPolygon, rLineWidth.getX() ); 1251 1252 // draw tesselation result 1253 const int nTrapCount = aB2DTrapVector.size(); 1254 if( nTrapCount > 0 ) 1255 bDrawnOk = drawFilledTrapezoids( &aB2DTrapVector[0], nTrapCount, fTransparency ); 1256 1257 // restore the original brush GC 1258 nBrushColor_ = aKeepBrushColor; 1259 return bDrawnOk; 1260 } 1261 1262 // get the area polygon for the line polygon 1263 if( (rLineWidth.getX() != rLineWidth.getY()) 1264 && !basegfx::fTools::equalZero( rLineWidth.getY() ) ) 1265 { 1266 // prepare for createAreaGeometry() with anisotropic linewidth 1267 aPolygon.transform( basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getX() / rLineWidth.getY())); 1268 } 1269 1270 // create the area-polygon for the line 1271 const basegfx::B2DPolyPolygon aAreaPolyPoly( basegfx::tools::createAreaGeometry(aPolygon, fHalfWidth, eLineJoin, eLineCap) ); 1272 1273 if( (rLineWidth.getX() != rLineWidth.getY()) 1274 && !basegfx::fTools::equalZero( rLineWidth.getX() ) ) 1275 { 1276 // postprocess createAreaGeometry() for anisotropic linewidth 1277 aPolygon.transform(basegfx::tools::createScaleB2DHomMatrix(1.0, rLineWidth.getY() / rLineWidth.getX())); 1278 } 1279 1280 // draw each area polypolygon component individually 1281 // to emulate the polypolygon winding rule "non-zero" 1282 const int nPolyCount = aAreaPolyPoly.count(); 1283 for( int nPolyIdx = 0; nPolyIdx < nPolyCount; ++nPolyIdx ) 1284 { 1285 const ::basegfx::B2DPolyPolygon aOnePoly( aAreaPolyPoly.getB2DPolygon( nPolyIdx ) ); 1286 bDrawnOk = drawPolyPolygon( aOnePoly, fTransparency ); 1287 if( !bDrawnOk ) 1288 break; 1289 } 1290 1291 // restore the original brush GC 1292 nBrushColor_ = aKeepBrushColor; 1293 return bDrawnOk; 1294 } 1295 1296 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= 1297 1298