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