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