1 /*************************************************************************
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5 * Copyright 2008 by Sun Microsystems, Inc.
7 * OpenOffice.org - a multi-platform office productivity suite
9 * $RCSfile: gcach_xpeer.cxx,v $
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>
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
;
53 Pixmap maPixmaps
[1]; // [mnMaxScreens]
56 // ===========================================================================
58 X11GlyphPeer::X11GlyphPeer()
59 : mpDisplay( GetX11SalData()->GetDisplay()->GetDisplay() )
66 maRawBitmap
.mnAllocated
= 0;
67 maRawBitmap
.mpBits
= NULL
;
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();
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
);
106 // ---------------------------------------------------------------------------
108 void X11GlyphPeer::InitAntialiasing()
110 int nEnvAntiAlias
= 0;
111 const char* pEnvAntiAlias
= getenv( "SAL_ANTIALIAS_DISABLE" );
114 nEnvAntiAlias
= atoi( pEnvAntiAlias
);
115 if( nEnvAntiAlias
== 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 )
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
;
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
;
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
;
208 // ---------------------------------------------------------------------------
210 void X11GlyphPeer::SetRenderGlyph( GlyphData
& rGD
, Glyph aGlyphId
) const
212 ExtGlyphData
& rEGD
= rGD
.ExtDataRef();
213 switch( rEGD
.meInfo
)
216 rEGD
.meInfo
= INFO_XRENDER
;
219 rEGD
.mpData
= reinterpret_cast<void*>(aGlyphId
);
223 PrepareForMultiscreen( rEGD
);
225 case INFO_MULTISCREEN
:
226 reinterpret_cast<MultiScreenGlyph
*>(rEGD
.mpData
)->maXRGlyphId
= aGlyphId
;
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
;
246 // ---------------------------------------------------------------------------
248 void X11GlyphPeer::SetRawBitmap( GlyphData
& rGD
, const RawBitmap
* pRawBitmap
) const
250 ExtGlyphData
& rEGD
= rGD
.ExtDataRef();
251 switch( rEGD
.meInfo
)
254 rEGD
.meInfo
= INFO_RAWBMP
;
257 rEGD
.mpData
= (void*)pRawBitmap
;
261 PrepareForMultiscreen( rEGD
);
263 case INFO_MULTISCREEN
:
264 reinterpret_cast<MultiScreenGlyph
*>(rEGD
.mpData
)->mpRawBitmap
= pRawBitmap
;
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
]);
285 // ---------------------------------------------------------------------------
287 void X11GlyphPeer::SetPixmap( GlyphData
& rGD
, Pixmap aPixmap
, int nScreen
) const
289 if( aPixmap
== NO_PIXMAP
)
292 ExtGlyphData
& rEGD
= rGD
.ExtDataRef();
293 if( (rEGD
.meInfo
== INFO_EMPTY
) && (nScreen
== mnDefaultScreen
) )
295 rEGD
.meInfo
= INFO_PIXMAP
;
296 rEGD
.mpData
= (void*)aPixmap
;
300 MultiScreenGlyph
* pMSGlyph
;
301 if( rEGD
.meInfo
== INFO_MULTISCREEN
)
302 pMSGlyph
= reinterpret_cast<MultiScreenGlyph
*>(rEGD
.mpData
);
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() )
321 case INFO_MULTISCREEN
:
326 XRenderPeer::GetInstance().FreeGlyphSet( (GlyphSet
)pFontExt
);
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
)
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
)
351 Pixmap aPixmap
= (Pixmap
)pGlyphExt
;
352 if( aPixmap
!= None
)
354 XFreePixmap( mpDisplay
, aPixmap
);
355 mnBytesUsed
-= nHeight
* ((nWidth
+ 7) >> 3);
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
)
367 if( pMSGlyph
->maPixmaps
[i
] == None
)
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[]
381 RawBitmap
* pRawBitmap
= (RawBitmap
*)pGlyphExt
;
382 if( pRawBitmap
!= NULL
)
384 mnBytesUsed
-= pRawBitmap
->mnScanlineSize
* pRawBitmap
->mnHeight
;
385 mnBytesUsed
-= sizeof(RawBitmap
);
393 // Glyph nGlyphId = (Glyph)rGlyphData.GetExtPointer();
394 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nGlyphId );
395 mnBytesUsed
-= nHeight
* ((nWidth
+ 3) & ~3);
400 if( mnBytesUsed
< 0 ) // TODO: eliminate nBytesUsed calc mismatch
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 )
425 switch( rServerFont
.GetExtInfo() )
428 aGlyphSet
= (GlyphSet
)rServerFont
.GetExtPointer();
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
);
456 // ---------------------------------------------------------------------------
458 Pixmap
X11GlyphPeer::GetPixmap( ServerFont
& rServerFont
, int nGlyphIndex
, int nReqScreen
)
460 if( rServerFont
.IsGlyphInvisible( nGlyphIndex
) )
463 GlyphData
& rGlyphData
= rServerFont
.GetGlyphData( nGlyphIndex
);
464 Pixmap aPixmap
= GetPixmap( rGlyphData
, nReqScreen
);
465 if( aPixmap
== NO_PIXMAP
)
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
;
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
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
)
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
;
549 // fall back to .notdef glyph
550 if( nGlyphIndex
!= 0 ) // recurse only once
551 aPixmap
= GetPixmap( rServerFont
, 0, nReqScreen
);
553 if( aPixmap
== NO_PIXMAP
)
561 // ---------------------------------------------------------------------------
563 const RawBitmap
* X11GlyphPeer::GetRawBitmap( ServerFont
& rServerFont
,
566 if( rServerFont
.IsGlyphInvisible( nGlyphIndex
) )
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
);
584 // fall back to .notdef glyph
585 if( nGlyphIndex
!= 0 ) // recurse only once
586 pRawBitmap
= GetRawBitmap( rServerFont
, 0 );
589 SetRawBitmap( rGlyphData
, pRawBitmap
);
595 // ---------------------------------------------------------------------------
597 Glyph
X11GlyphPeer::GetGlyphId( ServerFont
& rServerFont
, int nGlyphIndex
)
599 if( rServerFont
.IsGlyphInvisible( nGlyphIndex
) )
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
;
634 // fall back to .notdef glyph
635 if( nGlyphIndex
!= 0 ) // recurse only once
636 aGlyphId
= GetGlyphId( rServerFont
, 0 );
639 SetRenderGlyph( rGlyphData
, 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 // ===========================================================================