merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / gdi / gcach_xpeer.cxx
blobe2f1ca14da4d685b8b59503fb2a5e3799b8d30f9
1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gcach_xpeer.cxx,v $
10 * $Revision: 1.50 $
12 * This file is part of OpenOffice.org.
14 * OpenOffice.org is free software: you can redistribute it and/or modify
15 * it under the terms of the GNU Lesser General Public License version 3
16 * only, as published by the Free Software Foundation.
18 * OpenOffice.org is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU Lesser General Public License version 3 for more details
22 * (a copy is included in the LICENSE file that accompanied this code).
24 * You should have received a copy of the GNU Lesser General Public License
25 * version 3 along with OpenOffice.org. If not, see
26 * <http://www.openoffice.org/license.html>
27 * for a copy of the LGPLv3 License.
29 ************************************************************************/
31 // MARKER(update_precomp.py): autogen include statement, do not remove
32 #include "precompiled_vcl.hxx"
34 #include <rtl/ustring.hxx>
35 #include <osl/module.h>
36 #include <osl/thread.h>
38 #include <gcach_xpeer.hxx>
39 #include <xrender_peer.hxx>
40 #include <saldisp.hxx>
41 #include <saldata.hxx>
42 #include <salgdi.h>
44 // ===========================================================================
46 // all glyph specific data needed by the XGlyphPeer is quite trivial
47 // with one exception: if multiple screens are involved and non-antialiased
48 // glyph rendering is active, then we need screen specific pixmaps
49 struct MultiScreenGlyph
51 const RawBitmap* mpRawBitmap;
52 Glyph maXRGlyphId;
53 Pixmap maPixmaps[1]; // [mnMaxScreens]
56 // ===========================================================================
58 X11GlyphPeer::X11GlyphPeer()
59 : mpDisplay( GetX11SalData()->GetDisplay()->GetDisplay() )
60 , mnMaxScreens(0)
61 , mnDefaultScreen(0)
62 , mnExtByteCount(0)
63 , mnForcedAA(0)
64 , mnUsingXRender(0)
66 maRawBitmap.mnAllocated = 0;
67 maRawBitmap.mpBits = NULL;
68 if( !mpDisplay )
69 return;
71 SalDisplay& rSalDisplay = *GetX11SalData()->GetDisplay();
72 mpDisplay = rSalDisplay.GetDisplay();
73 mnMaxScreens = rSalDisplay.GetScreenCount();
74 if( mnMaxScreens > MAX_GCACH_SCREENS )
75 mnMaxScreens = MAX_GCACH_SCREENS;
76 // if specific glyph data has to be kept for many screens
77 // then prepare the allocation of MultiScreenGlyph objects
78 if( mnMaxScreens > 1 )
79 mnExtByteCount = sizeof(MultiScreenGlyph) + sizeof(Pixmap) * (mnMaxScreens - 1);
80 mnDefaultScreen = rSalDisplay.GetDefaultScreenNumber();
82 InitAntialiasing();
85 // ---------------------------------------------------------------------------
87 X11GlyphPeer::~X11GlyphPeer()
89 SalDisplay* pSalDisp = GetX11SalData()->GetDisplay();
90 Display* const pX11Disp = pSalDisp->GetDisplay();
91 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
92 for( int i = 0; i < mnMaxScreens; i++ )
94 SalDisplay::RenderEntryMap& rMap = pSalDisp->GetRenderEntries( i );
95 for( SalDisplay::RenderEntryMap::iterator it = rMap.begin(); it != rMap.end(); ++it )
97 if( it->second.m_aPixmap )
98 ::XFreePixmap( pX11Disp, it->second.m_aPixmap );
99 if( it->second.m_aPicture )
100 rRenderPeer.FreePicture( it->second.m_aPicture );
102 rMap.clear();
106 // ---------------------------------------------------------------------------
108 void X11GlyphPeer::InitAntialiasing()
110 int nEnvAntiAlias = 0;
111 const char* pEnvAntiAlias = getenv( "SAL_ANTIALIAS_DISABLE" );
112 if( pEnvAntiAlias )
114 nEnvAntiAlias = atoi( pEnvAntiAlias );
115 if( nEnvAntiAlias == 0 )
116 return;
119 mnUsingXRender = 0;
120 mnForcedAA = 0;
122 // enable XRENDER accelerated aliasing on screens that support it
123 // unless it explicitly disabled by an environment variable
124 if( (nEnvAntiAlias & 2) == 0 )
125 mnUsingXRender = XRenderPeer::GetInstance().InitRenderText( mnMaxScreens );
127 // else enable client side antialiasing for these screens
128 // unless it is explicitly disabled by an environment variable
129 if( (nEnvAntiAlias & 1) != 0 )
130 return;
132 // enable client side antialiasing for screen visuals that are suitable
133 // mnForcedAA is a bitmask of screens enabled for client side antialiasing
134 mnForcedAA = (~(~0U << mnMaxScreens)) ^ mnUsingXRender;
135 SalDisplay& rSalDisplay = *GetX11SalData()->GetDisplay();
136 for( int nScreen = 0; nScreen < mnMaxScreens; ++nScreen)
138 Visual* pVisual = rSalDisplay.GetVisual( nScreen ).GetVisual();
139 XVisualInfo aXVisualInfo;
140 aXVisualInfo.visualid = pVisual->visualid;
141 int nVisuals = 0;
142 XVisualInfo* pXVisualInfo = XGetVisualInfo( mpDisplay, VisualIDMask, &aXVisualInfo, &nVisuals );
143 for( int i = nVisuals; --i >= 0; )
145 if( ((pXVisualInfo[i].c_class==PseudoColor) || (pXVisualInfo[i].depth<24))
146 && ((pXVisualInfo[i].c_class>GrayScale) || (pXVisualInfo[i].depth!=8) ) )
147 mnForcedAA &= ~(1U << nScreen);
149 if( pXVisualInfo != NULL )
150 XFree( pXVisualInfo );
154 // ===========================================================================
156 enum { INFO_EMPTY=0, INFO_PIXMAP, INFO_XRENDER, INFO_RAWBMP, INFO_MULTISCREEN };
157 static const Glyph NO_GLYPHID = 0;
158 static RawBitmap* const NO_RAWBMP = NULL;
159 static const Pixmap NO_PIXMAP = ~0;
161 // ---------------------------------------------------------------------------
163 MultiScreenGlyph* X11GlyphPeer::PrepareForMultiscreen( ExtGlyphData& rEGD ) const
165 // prepare to store screen specific pixmaps
166 MultiScreenGlyph* pMSGlyph = (MultiScreenGlyph*)new char[ mnExtByteCount ];
168 // init the glyph formats
169 pMSGlyph->mpRawBitmap = NO_RAWBMP;
170 pMSGlyph->maXRGlyphId = NO_GLYPHID;
171 for( int i = 0; i < mnMaxScreens; ++i )
172 pMSGlyph->maPixmaps[i] = NO_PIXMAP;
173 // reuse already available glyph formats
174 if( rEGD.meInfo == INFO_XRENDER )
175 pMSGlyph->maXRGlyphId = reinterpret_cast<Glyph>(rEGD.mpData);
176 else if( rEGD.meInfo == INFO_RAWBMP )
177 pMSGlyph->mpRawBitmap = reinterpret_cast<RawBitmap*>(rEGD.mpData);
178 else if( rEGD.meInfo == INFO_PIXMAP )
180 Pixmap aPixmap = reinterpret_cast<Pixmap>(rEGD.mpData);
181 if( aPixmap != None )
182 // pixmap for the default screen is available
183 pMSGlyph->maPixmaps[ mnDefaultScreen ] = aPixmap;
184 else // empty pixmap for all screens is available
185 for( int i = 0; i < mnMaxScreens; ++i )
186 pMSGlyph->maPixmaps[ i ] = None;
188 // enable use of multiscreen glyph
189 rEGD.mpData = (void*)pMSGlyph;
190 rEGD.meInfo = INFO_MULTISCREEN;
192 return pMSGlyph;
195 // ---------------------------------------------------------------------------
197 Glyph X11GlyphPeer::GetRenderGlyph( const GlyphData& rGD ) const
199 Glyph aGlyphId = NO_GLYPHID;
200 const ExtGlyphData& rEGD = rGD.ExtDataRef();
201 if( rEGD.meInfo == INFO_XRENDER )
202 aGlyphId = reinterpret_cast<Glyph>(rEGD.mpData);
203 else if( rEGD.meInfo == INFO_MULTISCREEN )
204 aGlyphId = reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->maXRGlyphId;
205 return aGlyphId;
208 // ---------------------------------------------------------------------------
210 void X11GlyphPeer::SetRenderGlyph( GlyphData& rGD, Glyph aGlyphId ) const
212 ExtGlyphData& rEGD = rGD.ExtDataRef();
213 switch( rEGD.meInfo )
215 case INFO_EMPTY:
216 rEGD.meInfo = INFO_XRENDER;
217 // fall through
218 case INFO_XRENDER:
219 rEGD.mpData = reinterpret_cast<void*>(aGlyphId);
220 break;
221 case INFO_PIXMAP:
222 case INFO_RAWBMP:
223 PrepareForMultiscreen( rEGD );
224 // fall through
225 case INFO_MULTISCREEN:
226 reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->maXRGlyphId = aGlyphId;
227 break;
228 default:
229 break; // cannot happen...
233 // ---------------------------------------------------------------------------
235 const RawBitmap* X11GlyphPeer::GetRawBitmap( const GlyphData& rGD ) const
237 const RawBitmap* pRawBitmap = NO_RAWBMP;
238 const ExtGlyphData& rEGD = rGD.ExtDataRef();
239 if( rEGD.meInfo == INFO_RAWBMP )
240 pRawBitmap = reinterpret_cast<RawBitmap*>(rEGD.mpData);
241 else if( rEGD.meInfo == INFO_MULTISCREEN )
242 pRawBitmap = reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->mpRawBitmap;
243 return pRawBitmap;
246 // ---------------------------------------------------------------------------
248 void X11GlyphPeer::SetRawBitmap( GlyphData& rGD, const RawBitmap* pRawBitmap ) const
250 ExtGlyphData& rEGD = rGD.ExtDataRef();
251 switch( rEGD.meInfo )
253 case INFO_EMPTY:
254 rEGD.meInfo = INFO_RAWBMP;
255 // fall through
256 case INFO_RAWBMP:
257 rEGD.mpData = (void*)pRawBitmap;
258 break;
259 case INFO_PIXMAP:
260 case INFO_XRENDER:
261 PrepareForMultiscreen( rEGD );
262 // fall through
263 case INFO_MULTISCREEN:
264 reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->mpRawBitmap = pRawBitmap;
265 break;
266 default:
267 // cannot happen...
268 break;
272 // ---------------------------------------------------------------------------
274 Pixmap X11GlyphPeer::GetPixmap( const GlyphData& rGD, int nScreen ) const
276 Pixmap aPixmap = NO_PIXMAP;
277 const ExtGlyphData& rEGD = rGD.ExtDataRef();
278 if( (rEGD.meInfo == INFO_PIXMAP) && (nScreen == mnDefaultScreen) )
279 aPixmap = (Pixmap)rEGD.mpData;
280 else if( rEGD.meInfo == INFO_MULTISCREEN )
281 aPixmap = (Pixmap)(reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData)->maPixmaps[nScreen]);
282 return aPixmap;
285 // ---------------------------------------------------------------------------
287 void X11GlyphPeer::SetPixmap( GlyphData& rGD, Pixmap aPixmap, int nScreen ) const
289 if( aPixmap == NO_PIXMAP )
290 aPixmap = None;
292 ExtGlyphData& rEGD = rGD.ExtDataRef();
293 if( (rEGD.meInfo == INFO_EMPTY) && (nScreen == mnDefaultScreen) )
295 rEGD.meInfo = INFO_PIXMAP;
296 rEGD.mpData = (void*)aPixmap;
298 else
300 MultiScreenGlyph* pMSGlyph;
301 if( rEGD.meInfo == INFO_MULTISCREEN )
302 pMSGlyph = reinterpret_cast<MultiScreenGlyph*>(rEGD.mpData);
303 else
304 pMSGlyph = PrepareForMultiscreen( rEGD );
306 pMSGlyph->maPixmaps[ nScreen ] = aPixmap;
310 // ---------------------------------------------------------------------------
312 void X11GlyphPeer::RemovingFont( ServerFont& rServerFont )
314 void* pFontExt = rServerFont.GetExtPointer();
315 switch( rServerFont.GetExtInfo() )
317 case INFO_PIXMAP:
318 case INFO_RAWBMP:
319 // nothing to do
320 break;
321 case INFO_MULTISCREEN:
322 // cannot happen...
323 break;
325 case INFO_XRENDER:
326 XRenderPeer::GetInstance().FreeGlyphSet( (GlyphSet)pFontExt );
327 break;
330 rServerFont.SetExtended( INFO_EMPTY, NULL );
333 // ---------------------------------------------------------------------------
335 // notification to clean up GlyphPeer resources for this glyph
336 void X11GlyphPeer::RemovingGlyph( ServerFont& /*rServerFont*/, GlyphData& rGlyphData, int /*nGlyphIndex*/ )
338 // nothing to do if the GlyphPeer hasn't allocated resources for the glyph
339 if( rGlyphData.ExtDataRef().meInfo == INFO_EMPTY )
340 return;
342 const GlyphMetric& rGM = rGlyphData.GetMetric();
343 const int nWidth = rGM.GetSize().Width();
344 const int nHeight = rGM.GetSize().Height();
346 void* pGlyphExt = rGlyphData.ExtDataRef().mpData;
347 switch( rGlyphData.ExtDataRef().meInfo )
349 case INFO_PIXMAP:
351 Pixmap aPixmap = (Pixmap)pGlyphExt;
352 if( aPixmap != None )
354 XFreePixmap( mpDisplay, aPixmap );
355 mnBytesUsed -= nHeight * ((nWidth + 7) >> 3);
358 break;
360 case INFO_MULTISCREEN:
362 MultiScreenGlyph* pMSGlyph = reinterpret_cast<MultiScreenGlyph*>(pGlyphExt);
363 for( int i = 0; i < mnMaxScreens; ++i)
365 if( pMSGlyph->maPixmaps[i] == NO_PIXMAP )
366 continue;
367 if( pMSGlyph->maPixmaps[i] == None )
368 continue;
369 XFreePixmap( mpDisplay, pMSGlyph->maPixmaps[i] );
370 mnBytesUsed -= nHeight * ((nWidth + 7) >> 3);
372 delete pMSGlyph->mpRawBitmap;
373 // Glyph nGlyphId = (Glyph)rGlyphData.GetExtPointer();
374 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nGlyphId );
375 delete[] pMSGlyph; // it was allocated with new char[]
377 break;
379 case INFO_RAWBMP:
381 RawBitmap* pRawBitmap = (RawBitmap*)pGlyphExt;
382 if( pRawBitmap != NULL )
384 mnBytesUsed -= pRawBitmap->mnScanlineSize * pRawBitmap->mnHeight;
385 mnBytesUsed -= sizeof(RawBitmap);
386 delete pRawBitmap;
389 break;
391 case INFO_XRENDER:
393 // Glyph nGlyphId = (Glyph)rGlyphData.GetExtPointer();
394 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nGlyphId );
395 mnBytesUsed -= nHeight * ((nWidth + 3) & ~3);
397 break;
400 if( mnBytesUsed < 0 ) // TODO: eliminate nBytesUsed calc mismatch
401 mnBytesUsed = 0;
403 rGlyphData.ExtDataRef() = ExtGlyphData();
406 // ---------------------------------------------------------------------------
408 bool X11GlyphPeer::ForcedAntialiasing( const ServerFont& rServerFont, int nScreen ) const
410 bool bForceOk = rServerFont.GetAntialiasAdvice();
411 // maximum size for antialiasing is 250 pixels
412 bForceOk &= (rServerFont.GetFontSelData().mnHeight < 250);
413 return (bForceOk && ((mnForcedAA >> nScreen) & 1));
416 // ---------------------------------------------------------------------------
418 GlyphSet X11GlyphPeer::GetGlyphSet( ServerFont& rServerFont, int nScreen )
420 if( (nScreen >= 0) && ((mnUsingXRender >> nScreen) & 1) == 0 )
421 return 0;
423 GlyphSet aGlyphSet;
425 switch( rServerFont.GetExtInfo() )
427 case INFO_XRENDER:
428 aGlyphSet = (GlyphSet)rServerFont.GetExtPointer();
429 break;
431 case INFO_EMPTY:
433 // antialiasing for reasonable font heights only
434 // => prevents crashes caused by X11 requests >= 256k
435 // => prefer readablity of hinted glyphs at small sizes
436 // => prefer "grey clouds" to "black clouds" at very small sizes
437 int nHeight = rServerFont.GetFontSelData().mnHeight;
438 if( nHeight<250 && rServerFont.GetAntialiasAdvice() )
440 aGlyphSet = XRenderPeer::GetInstance().CreateGlyphSet();
441 rServerFont.SetExtended( INFO_XRENDER, (void*)aGlyphSet );
443 else
444 aGlyphSet = 0;
446 break;
448 default:
449 aGlyphSet = 0;
450 break;
453 return aGlyphSet;
456 // ---------------------------------------------------------------------------
458 Pixmap X11GlyphPeer::GetPixmap( ServerFont& rServerFont, int nGlyphIndex, int nReqScreen )
460 if( rServerFont.IsGlyphInvisible( nGlyphIndex ) )
461 return None;
463 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
464 Pixmap aPixmap = GetPixmap( rGlyphData, nReqScreen );
465 if( aPixmap == NO_PIXMAP )
467 aPixmap = None;
468 if( rServerFont.GetGlyphBitmap1( nGlyphIndex, maRawBitmap ) )
470 // #94666# circumvent bug in some X11 systems, e.g. XF410.LynxEM.v163
471 ULONG nPixmapWidth = 8 * maRawBitmap.mnScanlineSize - 1;
472 nPixmapWidth = Max( nPixmapWidth, maRawBitmap.mnWidth );
474 rGlyphData.SetSize( Size( nPixmapWidth, maRawBitmap.mnHeight ) );
475 rGlyphData.SetOffset( +maRawBitmap.mnXOffset, +maRawBitmap.mnYOffset );
477 const ULONG nBytes = maRawBitmap.mnHeight * maRawBitmap.mnScanlineSize;
478 if( nBytes > 0 )
480 // conversion table LSB<->MSB (for XCreatePixmapFromData)
481 static const unsigned char lsb2msb[256] =
483 0x00, 0x80, 0x40, 0xC0, 0x20, 0xA0, 0x60, 0xE0,
484 0x10, 0x90, 0x50, 0xD0, 0x30, 0xB0, 0x70, 0xF0,
485 0x08, 0x88, 0x48, 0xC8, 0x28, 0xA8, 0x68, 0xE8,
486 0x18, 0x98, 0x58, 0xD8, 0x38, 0xB8, 0x78, 0xF8,
487 0x04, 0x84, 0x44, 0xC4, 0x24, 0xA4, 0x64, 0xE4,
488 0x14, 0x94, 0x54, 0xD4, 0x34, 0xB4, 0x74, 0xF4,
489 0x0C, 0x8C, 0x4C, 0xCC, 0x2C, 0xAC, 0x6C, 0xEC,
490 0x1C, 0x9C, 0x5C, 0xDC, 0x3C, 0xBC, 0x7C, 0xFC,
491 0x02, 0x82, 0x42, 0xC2, 0x22, 0xA2, 0x62, 0xE2,
492 0x12, 0x92, 0x52, 0xD2, 0x32, 0xB2, 0x72, 0xF2,
493 0x0A, 0x8A, 0x4A, 0xCA, 0x2A, 0xAA, 0x6A, 0xEA,
494 0x1A, 0x9A, 0x5A, 0xDA, 0x3A, 0xBA, 0x7A, 0xFA,
495 0x06, 0x86, 0x46, 0xC6, 0x26, 0xA6, 0x66, 0xE6,
496 0x16, 0x96, 0x56, 0xD6, 0x36, 0xB6, 0x76, 0xF6,
497 0x0E, 0x8E, 0x4E, 0xCE, 0x2E, 0xAE, 0x6E, 0xEE,
498 0x1E, 0x9E, 0x5E, 0xDE, 0x3E, 0xBE, 0x7E, 0xFE,
499 0x01, 0x81, 0x41, 0xC1, 0x21, 0xA1, 0x61, 0xE1,
500 0x11, 0x91, 0x51, 0xD1, 0x31, 0xB1, 0x71, 0xF1,
501 0x09, 0x89, 0x49, 0xC9, 0x29, 0xA9, 0x69, 0xE9,
502 0x19, 0x99, 0x59, 0xD9, 0x39, 0xB9, 0x79, 0xF9,
503 0x05, 0x85, 0x45, 0xC5, 0x25, 0xA5, 0x65, 0xE5,
504 0x15, 0x95, 0x55, 0xD5, 0x35, 0xB5, 0x75, 0xF5,
505 0x0D, 0x8D, 0x4D, 0xCD, 0x2D, 0xAD, 0x6D, 0xED,
506 0x1D, 0x9D, 0x5D, 0xDD, 0x3D, 0xBD, 0x7D, 0xFD,
507 0x03, 0x83, 0x43, 0xC3, 0x23, 0xA3, 0x63, 0xE3,
508 0x13, 0x93, 0x53, 0xD3, 0x33, 0xB3, 0x73, 0xF3,
509 0x0B, 0x8B, 0x4B, 0xCB, 0x2B, 0xAB, 0x6B, 0xEB,
510 0x1B, 0x9B, 0x5B, 0xDB, 0x3B, 0xBB, 0x7B, 0xFB,
511 0x07, 0x87, 0x47, 0xC7, 0x27, 0xA7, 0x67, 0xE7,
512 0x17, 0x97, 0x57, 0xD7, 0x37, 0xB7, 0x77, 0xF7,
513 0x0F, 0x8F, 0x4F, 0xCF, 0x2F, 0xAF, 0x6F, 0xEF,
514 0x1F, 0x9F, 0x5F, 0xDF, 0x3F, 0xBF, 0x7F, 0xFF
517 unsigned char* pTemp = maRawBitmap.mpBits;
518 for( int i = nBytes; --i >= 0; ++pTemp )
519 *pTemp = lsb2msb[ *pTemp ];
521 // often a glyph pixmap is only needed on the default screen
522 // => optimize for this common case
523 int nMinScreen = 0;
524 int nEndScreen = mnMaxScreens;
525 if( nReqScreen == mnDefaultScreen ) {
526 nMinScreen = mnDefaultScreen;
527 nEndScreen = mnDefaultScreen + 1;
529 // prepare glyph pixmaps for the different screens
530 for( int i = nMinScreen; i < nEndScreen; ++i )
532 // don't bother if the pixmap is already there
533 if( GetPixmap( rGlyphData, i ) != NO_PIXMAP )
534 continue;
535 // create the glyph pixmap
536 Pixmap aScreenPixmap = XCreatePixmapFromBitmapData( mpDisplay,
537 RootWindow( mpDisplay, i ), (char*)maRawBitmap.mpBits,
538 nPixmapWidth, maRawBitmap.mnHeight, 1, 0, 1 );
539 // and cache it as glyph specific data
540 SetPixmap( rGlyphData, aScreenPixmap, i );
541 mnBytesUsed += nBytes;
542 if( i == nReqScreen )
543 aPixmap = aScreenPixmap;
547 else
549 // fall back to .notdef glyph
550 if( nGlyphIndex != 0 ) // recurse only once
551 aPixmap = GetPixmap( rServerFont, 0, nReqScreen );
553 if( aPixmap == NO_PIXMAP )
554 aPixmap = None;
558 return aPixmap;
561 // ---------------------------------------------------------------------------
563 const RawBitmap* X11GlyphPeer::GetRawBitmap( ServerFont& rServerFont,
564 int nGlyphIndex )
566 if( rServerFont.IsGlyphInvisible( nGlyphIndex ) )
567 return NO_RAWBMP;
569 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
571 const RawBitmap* pRawBitmap = GetRawBitmap( rGlyphData );
572 if( pRawBitmap == NO_RAWBMP )
574 RawBitmap* pNewBitmap = new RawBitmap;
575 if( rServerFont.GetGlyphBitmap8( nGlyphIndex, *pNewBitmap ) )
577 pRawBitmap = pNewBitmap;
578 mnBytesUsed += pNewBitmap->mnScanlineSize * pNewBitmap->mnHeight;
579 mnBytesUsed += sizeof(pNewBitmap);
581 else
583 delete pNewBitmap;
584 // fall back to .notdef glyph
585 if( nGlyphIndex != 0 ) // recurse only once
586 pRawBitmap = GetRawBitmap( rServerFont, 0 );
589 SetRawBitmap( rGlyphData, pRawBitmap );
592 return pRawBitmap;
595 // ---------------------------------------------------------------------------
597 Glyph X11GlyphPeer::GetGlyphId( ServerFont& rServerFont, int nGlyphIndex )
599 if( rServerFont.IsGlyphInvisible( nGlyphIndex ) )
600 return NO_GLYPHID;
602 GlyphData& rGlyphData = rServerFont.GetGlyphData( nGlyphIndex );
604 Glyph aGlyphId = GetRenderGlyph( rGlyphData );
605 if( aGlyphId == NO_GLYPHID )
607 // prepare GlyphInfo and Bitmap
608 if( rServerFont.GetGlyphBitmap8( nGlyphIndex, maRawBitmap ) )
610 XGlyphInfo aGlyphInfo;
611 aGlyphInfo.width = maRawBitmap.mnWidth;
612 aGlyphInfo.height = maRawBitmap.mnHeight;
613 aGlyphInfo.x = -maRawBitmap.mnXOffset;
614 aGlyphInfo.y = -maRawBitmap.mnYOffset;
616 rGlyphData.SetSize( Size( maRawBitmap.mnWidth, maRawBitmap.mnHeight ) );
617 rGlyphData.SetOffset( +maRawBitmap.mnXOffset, +maRawBitmap.mnYOffset );
619 const GlyphMetric& rGM = rGlyphData.GetMetric();
620 aGlyphInfo.xOff = +rGM.GetDelta().X();
621 aGlyphInfo.yOff = +rGM.GetDelta().Y();
623 // upload glyph bitmap to server
624 GlyphSet aGlyphSet = GetGlyphSet( rServerFont, -1 );
626 aGlyphId = nGlyphIndex & 0x00FFFFFF;
627 const ULONG nBytes = maRawBitmap.mnScanlineSize * maRawBitmap.mnHeight;
628 XRenderPeer::GetInstance().AddGlyph( aGlyphSet, aGlyphId,
629 aGlyphInfo, (char*)maRawBitmap.mpBits, nBytes );
630 mnBytesUsed += nBytes;
632 else
634 // fall back to .notdef glyph
635 if( nGlyphIndex != 0 ) // recurse only once
636 aGlyphId = GetGlyphId( rServerFont, 0 );
639 SetRenderGlyph( rGlyphData, aGlyphId );
642 return aGlyphId;
645 // ===========================================================================
647 X11GlyphCache::X11GlyphCache( X11GlyphPeer& rPeer )
648 : GlyphCache( rPeer )
652 // ---------------------------------------------------------------------------
654 static X11GlyphPeer* pX11GlyphPeer = NULL;
655 static X11GlyphCache* pX11GlyphCache = NULL;
657 X11GlyphCache& X11GlyphCache::GetInstance()
659 if( !pX11GlyphCache )
661 pX11GlyphPeer = new X11GlyphPeer();
662 pX11GlyphCache = new X11GlyphCache( *pX11GlyphPeer );
664 return *pX11GlyphCache;
667 // ---------------------------------------------------------------------------
669 void X11GlyphCache::KillInstance()
671 delete pX11GlyphCache;
672 delete pX11GlyphPeer;
673 pX11GlyphCache = NULL;
674 pX11GlyphPeer = NULL;
677 // ===========================================================================
679 void X11SalGraphics::releaseGlyphPeer()
681 X11GlyphCache::KillInstance();
684 // ===========================================================================