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