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 "rtl/ustring.hxx" 32 #include "osl/module.h" 33 #include "osl/thread.h" 34 35 #include "unx/saldisp.hxx" 36 #include "unx/saldata.hxx" 37 #include "unx/salgdi.h" 38 39 #include "gcach_xpeer.hxx" 40 #include "xrender_peer.hxx" 41 42 // =========================================================================== 43 44 // all glyph specific data needed by the XGlyphPeer is quite trivial 45 // with one exception: if multiple screens are involved and non-antialiased 46 // glyph rendering is active, then we need screen specific pixmaps 47 struct MultiScreenGlyph 48 { 49 const RawBitmap* mpRawBitmap; 50 Glyph maXRGlyphId; 51 Pixmap maPixmaps[1]; // [mnMaxScreens] 52 }; 53 54 // =========================================================================== 55 56 X11GlyphPeer::X11GlyphPeer() 57 : mpDisplay( GetX11SalData()->GetDisplay()->GetDisplay() ) 58 , mnMaxScreens(0) 59 , mnDefaultScreen(0) 60 , mnExtByteCount(0) 61 , mnForcedAA(0) 62 , mnUsingXRender(0) 63 { 64 maRawBitmap.mnAllocated = 0; 65 maRawBitmap.mpBits = NULL; 66 if( !mpDisplay ) 67 return; 68 69 SalDisplay& rSalDisplay = *GetX11SalData()->GetDisplay(); 70 mpDisplay = rSalDisplay.GetDisplay(); 71 mnMaxScreens = rSalDisplay.GetScreenCount(); 72 if( mnMaxScreens > MAX_GCACH_SCREENS ) 73 mnMaxScreens = MAX_GCACH_SCREENS; 74 // if specific glyph data has to be kept for many screens 75 // then prepare the allocation of MultiScreenGlyph objects 76 if( mnMaxScreens > 1 ) 77 mnExtByteCount = sizeof(MultiScreenGlyph) + sizeof(Pixmap) * (mnMaxScreens - 1); 78 mnDefaultScreen = rSalDisplay.GetDefaultScreenNumber(); 79 80 InitAntialiasing(); 81 } 82 83 // --------------------------------------------------------------------------- 84 85 X11GlyphPeer::~X11GlyphPeer() 86 { 87 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay(); 88 Display* const pX11Disp = pSalDisp->GetDisplay(); 89 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance(); 90 for( int i = 0; i < mnMaxScreens; i++ ) 91 { 92 SalDisplay::RenderEntryMap& rMap = pSalDisp->GetRenderEntries( i ); 93 for( SalDisplay::RenderEntryMap::iterator it = rMap.begin(); it != rMap.end(); ++it ) 94 { 95 if( it->second.m_aPixmap ) 96 ::XFreePixmap( pX11Disp, it->second.m_aPixmap ); 97 if( it->second.m_aPicture ) 98 rRenderPeer.FreePicture( it->second.m_aPicture ); 99 } 100 rMap.clear(); 101 } 102 } 103 104 // --------------------------------------------------------------------------- 105 106 void X11GlyphPeer::InitAntialiasing() 107 { 108 int nEnvAntiAlias = 0; 109 const char* pEnvAntiAlias = getenv( "SAL_ANTIALIAS_DISABLE" ); 110 if( pEnvAntiAlias ) 111 { 112 nEnvAntiAlias = atoi( pEnvAntiAlias ); 113 if( nEnvAntiAlias == 0 ) 114 return; 115 } 116 117 mnUsingXRender = 0; 118 mnForcedAA = 0; 119 120 // enable XRENDER accelerated aliasing on screens that support it 121 // unless it explicitly disabled by an environment variable 122 if( (nEnvAntiAlias & 2) == 0 ) 123 mnUsingXRender = XRenderPeer::GetInstance().InitRenderText(); 124 125 // else enable client side antialiasing for these screens 126 // unless it is explicitly disabled by an environment variable 127 if( (nEnvAntiAlias & 1) != 0 ) 128 return; 129 130 // enable client side antialiasing for screen visuals that are suitable 131 // mnForcedAA is a bitmask of screens enabled for client side antialiasing 132 mnForcedAA = (~(~0U << mnMaxScreens)) ^ mnUsingXRender; 133 SalDisplay& rSalDisplay = *GetX11SalData()->GetDisplay(); 134 for( int nScreen = 0; nScreen < mnMaxScreens; ++nScreen) 135 { 136 Visual* pVisual = rSalDisplay.GetVisual( nScreen ).GetVisual(); 137 XVisualInfo aXVisualInfo; 138 aXVisualInfo.visualid = pVisual->visualid; 139 int nVisuals = 0; 140 XVisualInfo* pXVisualInfo = XGetVisualInfo( mpDisplay, VisualIDMask, &aXVisualInfo, &nVisuals ); 141 for( int i = nVisuals; --i >= 0; ) 142 { 143 if( ((pXVisualInfo[i].c_class==PseudoColor) || (pXVisualInfo[i].depth<24)) 144 && ((pXVisualInfo[i].c_class>GrayScale) || (pXVisualInfo[i].depth!=8) ) ) 145 mnForcedAA &= ~(1U << nScreen); 146 } 147 if( pXVisualInfo != NULL ) 148 XFree( pXVisualInfo ); 149 } 150 } 151 152 // =========================================================================== 153 154 enum { INFO_EMPTY=0, INFO_PIXMAP, INFO_XRENDER, INFO_RAWBMP, INFO_MULTISCREEN }; 155 static const Glyph NO_GLYPHID = 0; 156 static RawBitmap* const NO_RAWBMP = NULL; 157 static const Pixmap NO_PIXMAP = ~0; 158 159 // --------------------------------------------------------------------------- 160 161 MultiScreenGlyph* X11GlyphPeer::PrepareForMultiscreen( ExtGlyphData& rEGD ) const 162 { 163 // prepare to store screen specific pixmaps 164 MultiScreenGlyph* pMSGlyph = (MultiScreenGlyph*)new char[ mnExtByteCount ]; 165 166 // init the glyph formats 167 pMSGlyph->mpRawBitmap = NO_RAWBMP; 168 pMSGlyph->maXRGlyphId = NO_GLYPHID; 169 for( int i = 0; i < mnMaxScreens; ++i ) 170 pMSGlyph->maPixmaps[i] = NO_PIXMAP; 171 // reuse already available glyph formats 172 if( rEGD.meInfo == INFO_XRENDER ) 173 pMSGlyph->maXRGlyphId = reinterpret_cast<Glyph>(rEGD.mpData); 174 else if( rEGD.meInfo == INFO_RAWBMP ) 175 pMSGlyph->mpRawBitmap = reinterpret_cast<RawBitmap*>(rEGD.mpData); 176 else if( rEGD.meInfo == INFO_PIXMAP ) 177 { 178 Pixmap aPixmap = reinterpret_cast<Pixmap>(rEGD.mpData); 179 if( aPixmap != None ) 180 // pixmap for the default screen is available 181 pMSGlyph->maPixmaps[ mnDefaultScreen ] = aPixmap; 182 else // empty pixmap for all screens is available 183 for( int i = 0; i < mnMaxScreens; ++i ) 184 pMSGlyph->maPixmaps[ i ] = None; 185 } 186 // enable use of multiscreen glyph 187 rEGD.mpData = (void*)pMSGlyph; 188 rEGD.meInfo = INFO_MULTISCREEN; 189 190 return pMSGlyph; 191 } 192 193 // --------------------------------------------------------------------------- 194 195 Glyph X11GlyphPeer::GetRenderGlyph( const GlyphData& rGD ) const 196 { 197 Glyph aGlyphId = NO_GLYPHID; 198 const ExtGlyphData& rEGD = rGD.ExtDataRef(); 199 if( rEGD.meInfo == INFO_XRENDER ) 200 aGlyphId = reinterpret_cast<Glyph>(rEGD.mpData); 201 else if( rEGD.meInfo == INFO_MULTISCREEN ) 202 aGlyphId = reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->maXRGlyphId; 203 return aGlyphId; 204 } 205 206 // --------------------------------------------------------------------------- 207 208 void X11GlyphPeer::SetRenderGlyph( GlyphData& rGD, Glyph aGlyphId ) const 209 { 210 ExtGlyphData& rEGD = rGD.ExtDataRef(); 211 switch( rEGD.meInfo ) 212 { 213 case INFO_EMPTY: 214 rEGD.meInfo = INFO_XRENDER; 215 // fall through 216 case INFO_XRENDER: 217 rEGD.mpData = reinterpret_cast<void*>(aGlyphId); 218 break; 219 case INFO_PIXMAP: 220 case INFO_RAWBMP: 221 PrepareForMultiscreen( rEGD ); 222 // fall through 223 case INFO_MULTISCREEN: 224 reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->maXRGlyphId = aGlyphId; 225 break; 226 default: 227 break; // cannot happen... 228 } 229 } 230 231 // --------------------------------------------------------------------------- 232 233 const RawBitmap* X11GlyphPeer::GetRawBitmap( const GlyphData& rGD ) const 234 { 235 const RawBitmap* pRawBitmap = NO_RAWBMP; 236 const ExtGlyphData& rEGD = rGD.ExtDataRef(); 237 if( rEGD.meInfo == INFO_RAWBMP ) 238 pRawBitmap = reinterpret_cast<RawBitmap*>(rEGD.mpData); 239 else if( rEGD.meInfo == INFO_MULTISCREEN ) 240 pRawBitmap = reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->mpRawBitmap; 241 return pRawBitmap; 242 } 243 244 // --------------------------------------------------------------------------- 245 246 void X11GlyphPeer::SetRawBitmap( GlyphData& rGD, const RawBitmap* pRawBitmap ) const 247 { 248 ExtGlyphData& rEGD = rGD.ExtDataRef(); 249 switch( rEGD.meInfo ) 250 { 251 case INFO_EMPTY: 252 rEGD.meInfo = INFO_RAWBMP; 253 // fall through 254 case INFO_RAWBMP: 255 rEGD.mpData = (void*)pRawBitmap; 256 break; 257 case INFO_PIXMAP: 258 case INFO_XRENDER: 259 PrepareForMultiscreen( rEGD ); 260 // fall through 261 case INFO_MULTISCREEN: 262 reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->mpRawBitmap = pRawBitmap; 263 break; 264 default: 265 // cannot happen... 266 break; 267 } 268 } 269 270 // --------------------------------------------------------------------------- 271 272 Pixmap X11GlyphPeer::GetPixmap( const GlyphData& rGD, int nScreen ) const 273 { 274 Pixmap aPixmap = NO_PIXMAP; 275 const ExtGlyphData& rEGD = rGD.ExtDataRef(); 276 if( (rEGD.meInfo == INFO_PIXMAP) && (nScreen == mnDefaultScreen) ) 277 aPixmap = (Pixmap)rEGD.mpData; 278 else if( rEGD.meInfo == INFO_MULTISCREEN ) 279 aPixmap = (Pixmap)(reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->maPixmaps[nScreen]); 280 return aPixmap; 281 } 282 283 // --------------------------------------------------------------------------- 284 285 void X11GlyphPeer::SetPixmap( GlyphData& rGD, Pixmap aPixmap, int nScreen ) const 286 { 287 if( aPixmap == NO_PIXMAP ) 288 aPixmap = None; 289 290 ExtGlyphData& rEGD = rGD.ExtDataRef(); 291 if( (rEGD.meInfo == INFO_EMPTY) && (nScreen == mnDefaultScreen) ) 292 { 293 rEGD.meInfo = INFO_PIXMAP; 294 rEGD.mpData = (void*)aPixmap; 295 } 296 else 297 { 298 MultiScreenGlyph* pMSGlyph; 299 if( rEGD.meInfo == INFO_MULTISCREEN ) 300 pMSGlyph = reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData); 301 else 302 pMSGlyph = PrepareForMultiscreen( rEGD ); 303 304 pMSGlyph->maPixmaps[ nScreen ] = aPixmap; 305 } 306 } 307 308 // --------------------------------------------------------------------------- 309 310 void X11GlyphPeer::RemovingFont( ServerFont& rServerFont ) 311 { 312 void* pFontExt = rServerFont.GetExtPointer(); 313 switch( rServerFont.GetExtInfo() ) 314 { 315 case INFO_PIXMAP: 316 case INFO_RAWBMP: 317 // nothing to do 318 break; 319 case INFO_MULTISCREEN: 320 // cannot happen... 321 break; 322 323 case INFO_XRENDER: 324 XRenderPeer::GetInstance().FreeGlyphSet( (GlyphSet)pFontExt ); 325 break; 326 } 327 328 rServerFont.SetExtended( INFO_EMPTY, NULL ); 329 } 330 331 // --------------------------------------------------------------------------- 332 333 // notification to clean up GlyphPeer resources for this glyph 334 void X11GlyphPeer::RemovingGlyph( ServerFont& /*rServerFont*/, GlyphData& rGlyphData, int /*nGlyphIndex*/ ) 335 { 336 // nothing to do if the GlyphPeer hasn't allocated resources for the glyph 337 if( rGlyphData.ExtDataRef().meInfo == INFO_EMPTY ) 338 return; 339 340 const GlyphMetric& rGM = rGlyphData.GetMetric(); 341 const int nWidth = rGM.GetSize().Width(); 342 const int nHeight = rGM.GetSize().Height(); 343 344 void* pGlyphExt = rGlyphData.ExtDataRef().mpData; 345 switch( rGlyphData.ExtDataRef().meInfo ) 346 { 347 case INFO_PIXMAP: 348 { 349 Pixmap aPixmap = (Pixmap)pGlyphExt; 350 if( aPixmap != None ) 351 { 352 XFreePixmap( mpDisplay, aPixmap ); 353 mnBytesUsed -= nHeight * ((nWidth + 7) >> 3); 354 } 355 } 356 break; 357 358 case INFO_MULTISCREEN: 359 { 360 MultiScreenGlyph* pMSGlyph = reinterpret_cast<MultiScreenGlyph*>(pGlyphExt); 361 for( int i = 0; i < mnMaxScreens; ++i) 362 { 363 if( pMSGlyph->maPixmaps[i] == NO_PIXMAP ) 364 continue; 365 if( pMSGlyph->maPixmaps[i] == None ) 366 continue; 367 XFreePixmap( mpDisplay, pMSGlyph->maPixmaps[i] ); 368 mnBytesUsed -= nHeight * ((nWidth + 7) >> 3); 369 } 370 delete pMSGlyph->mpRawBitmap; 371 // Glyph nGlyphId = (Glyph)rGlyphData.GetExtPointer(); 372 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nGlyphId ); 373 delete[] pMSGlyph; // it was allocated with new char[] 374 } 375 break; 376 377 case INFO_RAWBMP: 378 { 379 RawBitmap* pRawBitmap = (RawBitmap*)pGlyphExt; 380 if( pRawBitmap != NULL ) 381 { 382 mnBytesUsed -= pRawBitmap->mnScanlineSize * pRawBitmap->mnHeight; 383 mnBytesUsed -= sizeof(RawBitmap); 384 delete pRawBitmap; 385 } 386 } 387 break; 388 389 case INFO_XRENDER: 390 { 391 // Glyph nGlyphId = (Glyph)rGlyphData.GetExtPointer(); 392 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nGlyphId ); 393 mnBytesUsed -= nHeight * ((nWidth + 3) & ~3); 394 } 395 break; 396 } 397 398 if( mnBytesUsed < 0 ) // TODO: eliminate nBytesUsed calc mismatch 399 mnBytesUsed = 0; 400 401 rGlyphData.ExtDataRef() = ExtGlyphData(); 402 } 403 404 // --------------------------------------------------------------------------- 405 406 bool X11GlyphPeer::ForcedAntialiasing( const ServerFont& rServerFont, int nScreen ) const 407 { 408 bool bForceOk = rServerFont.GetAntialiasAdvice(); 409 // maximum size for antialiasing is 250 pixels 410 bForceOk &= (rServerFont.GetFontSelData().mnHeight < 250); 411 return (bForceOk && ((mnForcedAA >> nScreen) & 1)); 412 } 413 414 // --------------------------------------------------------------------------- 415 416 GlyphSet X11GlyphPeer::GetGlyphSet( ServerFont& rServerFont, int nScreen ) 417 { 418 if( (nScreen >= 0) && ((mnUsingXRender >> nScreen) & 1) == 0 ) 419 return 0; 420 421 GlyphSet aGlyphSet; 422 423 switch( rServerFont.GetExtInfo() ) 424 { 425 case INFO_XRENDER: 426 aGlyphSet = (GlyphSet)rServerFont.GetExtPointer(); 427 break; 428 429 case INFO_EMPTY: 430 { 431 // antialiasing for reasonable font heights only 432 // => prevents crashes caused by X11 requests >= 256k 433 // => prefer readablity of hinted glyphs at small sizes 434 // => prefer "grey clouds" to "black clouds" at very small sizes 435 int nHeight = rServerFont.GetFontSelData().mnHeight; 436 if( nHeight<250 && rServerFont.GetAntialiasAdvice() ) 437 { 438 aGlyphSet = XRenderPeer::GetInstance().CreateGlyphSet(); 439 rServerFont.SetExtended( INFO_XRENDER, (void*)aGlyphSet ); 440 } 441 else 442 aGlyphSet = 0; 443 } 444 break; 445 446 default: 447 aGlyphSet = 0; 448 break; 449 } 450 451 return aGlyphSet; 452 } 453 454 // --------------------------------------------------------------------------- 455 456 Pixmap X11GlyphPeer::GetPixmap( ServerFont& rServerFont, int nGlyphIndex, int nReqScreen ) 457 { 458 if( rServerFont.IsGlyphInvisible( nGlyphIndex ) ) 459 return None; 460 461 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex ); 462 Pixmap aPixmap = GetPixmap( rGlyphData, nReqScreen ); 463 if( aPixmap == NO_PIXMAP ) 464 { 465 aPixmap = None; 466 if( rServerFont.GetGlyphBitmap1( nGlyphIndex, maRawBitmap ) ) 467 { 468 // #94666# circumvent bug in some X11 systems, e.g. XF410.LynxEM.v163 469 sal_uLong nPixmapWidth = 8 * maRawBitmap.mnScanlineSize - 1; 470 nPixmapWidth = Max( nPixmapWidth, maRawBitmap.mnWidth ); 471 472 rGlyphData.SetSize( Size( nPixmapWidth, maRawBitmap.mnHeight ) ); 473 rGlyphData.SetOffset( +maRawBitmap.mnXOffset, +maRawBitmap.mnYOffset ); 474 475 const sal_uLong nBytes = maRawBitmap.mnHeight * maRawBitmap.mnScanlineSize; 476 if( nBytes > 0 ) 477 { 478 // conversion table LSB<->MSB (for XCreatePixmapFromData) 479 static const unsigned char lsb2msb[256] = 480 { 481 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0, 482 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0, 483 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8, 484 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8, 485 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4, 486 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4, 487 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC, 488 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC, 489 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2, 490 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2, 491 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA, 492 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA, 493 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6, 494 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6, 495 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE, 496 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE, 497 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1, 498 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1, 499 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9, 500 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9, 501 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5, 502 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5, 503 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED, 504 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD, 505 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3, 506 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3, 507 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB, 508 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB, 509 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7, 510 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7, 511 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF, 512 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF 513 }; 514 515 unsigned char* pTemp = maRawBitmap.mpBits; 516 for( int i = nBytes; --i >= 0; ++pTemp ) 517 *pTemp = lsb2msb[ *pTemp ]; 518 519 // often a glyph pixmap is only needed on the default screen 520 // => optimize for this common case 521 int nMinScreen = 0; 522 int nEndScreen = mnMaxScreens; 523 if( nReqScreen == mnDefaultScreen ) { 524 nMinScreen = mnDefaultScreen; 525 nEndScreen = mnDefaultScreen + 1; 526 } 527 // prepare glyph pixmaps for the different screens 528 for( int i = nMinScreen; i < nEndScreen; ++i ) 529 { 530 // don't bother if the pixmap is already there 531 if( GetPixmap( rGlyphData, i ) != NO_PIXMAP ) 532 continue; 533 // create the glyph pixmap 534 Pixmap aScreenPixmap = XCreatePixmapFromBitmapData( mpDisplay, 535 RootWindow( mpDisplay, i ), (char*)maRawBitmap.mpBits, 536 nPixmapWidth, maRawBitmap.mnHeight, 1, 0, 1 ); 537 // and cache it as glyph specific data 538 SetPixmap( rGlyphData, aScreenPixmap, i ); 539 mnBytesUsed += nBytes; 540 if( i == nReqScreen ) 541 aPixmap = aScreenPixmap; 542 } 543 } 544 } 545 else 546 { 547 // fall back to .notdef glyph 548 if( nGlyphIndex != 0 ) // recurse only once 549 aPixmap = GetPixmap( rServerFont, 0, nReqScreen ); 550 551 if( aPixmap == NO_PIXMAP ) 552 aPixmap = None; 553 } 554 } 555 556 return aPixmap; 557 } 558 559 // --------------------------------------------------------------------------- 560 561 const RawBitmap* X11GlyphPeer::GetRawBitmap( ServerFont& rServerFont, 562 int nGlyphIndex ) 563 { 564 if( rServerFont.IsGlyphInvisible( nGlyphIndex ) ) 565 return NO_RAWBMP; 566 567 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex ); 568 569 const RawBitmap* pRawBitmap = GetRawBitmap( rGlyphData ); 570 if( pRawBitmap == NO_RAWBMP ) 571 { 572 RawBitmap* pNewBitmap = new RawBitmap; 573 if( rServerFont.GetGlyphBitmap8( nGlyphIndex, *pNewBitmap ) ) 574 { 575 pRawBitmap = pNewBitmap; 576 mnBytesUsed += pNewBitmap->mnScanlineSize * pNewBitmap->mnHeight; 577 mnBytesUsed += sizeof(pNewBitmap); 578 } 579 else 580 { 581 delete pNewBitmap; 582 // fall back to .notdef glyph 583 if( nGlyphIndex != 0 ) // recurse only once 584 pRawBitmap = GetRawBitmap( rServerFont, 0 ); 585 } 586 587 SetRawBitmap( rGlyphData, pRawBitmap ); 588 } 589 590 return pRawBitmap; 591 } 592 593 // --------------------------------------------------------------------------- 594 595 Glyph X11GlyphPeer::GetGlyphId( ServerFont& rServerFont, int nGlyphIndex ) 596 { 597 if( rServerFont.IsGlyphInvisible( nGlyphIndex ) ) 598 return NO_GLYPHID; 599 600 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex ); 601 602 Glyph aGlyphId = GetRenderGlyph( rGlyphData ); 603 if( aGlyphId == NO_GLYPHID ) 604 { 605 // prepare GlyphInfo and Bitmap 606 if( rServerFont.GetGlyphBitmap8( nGlyphIndex, maRawBitmap ) ) 607 { 608 XGlyphInfo aGlyphInfo; 609 aGlyphInfo.width = maRawBitmap.mnWidth; 610 aGlyphInfo.height = maRawBitmap.mnHeight; 611 aGlyphInfo.x = -maRawBitmap.mnXOffset; 612 aGlyphInfo.y = -maRawBitmap.mnYOffset; 613 614 rGlyphData.SetSize( Size( maRawBitmap.mnWidth, maRawBitmap.mnHeight ) ); 615 rGlyphData.SetOffset( +maRawBitmap.mnXOffset, +maRawBitmap.mnYOffset ); 616 617 const GlyphMetric& rGM = rGlyphData.GetMetric(); 618 aGlyphInfo.xOff = +rGM.GetDelta().X(); 619 aGlyphInfo.yOff = +rGM.GetDelta().Y(); 620 621 // upload glyph bitmap to server 622 GlyphSet aGlyphSet = GetGlyphSet( rServerFont, -1 ); 623 624 aGlyphId = nGlyphIndex & 0x00FFFFFF; 625 const sal_uLong nBytes = maRawBitmap.mnScanlineSize * maRawBitmap.mnHeight; 626 XRenderPeer::GetInstance().AddGlyph( aGlyphSet, aGlyphId, 627 aGlyphInfo, (char*)maRawBitmap.mpBits, nBytes ); 628 mnBytesUsed += nBytes; 629 } 630 else 631 { 632 // fall back to .notdef glyph 633 if( nGlyphIndex != 0 ) // recurse only once 634 aGlyphId = GetGlyphId( rServerFont, 0 ); 635 } 636 637 SetRenderGlyph( rGlyphData, aGlyphId ); 638 } 639 640 return aGlyphId; 641 } 642 643 // =========================================================================== 644 645 X11GlyphCache::X11GlyphCache( X11GlyphPeer& rPeer ) 646 : GlyphCache( rPeer ) 647 { 648 } 649 650 // --------------------------------------------------------------------------- 651 652 static X11GlyphPeer* pX11GlyphPeer = NULL; 653 static X11GlyphCache* pX11GlyphCache = NULL; 654 655 X11GlyphCache& X11GlyphCache::GetInstance() 656 { 657 if( !pX11GlyphCache ) 658 { 659 pX11GlyphPeer = new X11GlyphPeer(); 660 pX11GlyphCache = new X11GlyphCache( *pX11GlyphPeer ); 661 } 662 return *pX11GlyphCache; 663 } 664 665 // --------------------------------------------------------------------------- 666 667 void X11GlyphCache::KillInstance() 668 { 669 delete pX11GlyphCache; 670 delete pX11GlyphPeer; 671 pX11GlyphCache = NULL; 672 pX11GlyphPeer = NULL; 673 } 674 675 // =========================================================================== 676 677 void X11SalGraphics::releaseGlyphPeer() 678 { 679 X11GlyphCache::KillInstance(); 680 } 681 682 // =========================================================================== 683 684