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
X11GlyphPeer()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
~X11GlyphPeer()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
InitAntialiasing()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
PrepareForMultiscreen(ExtGlyphData & rEGD) const157 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
GetRenderGlyph(const GlyphData & rGD) const191 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
SetRenderGlyph(GlyphData & rGD,Glyph aGlyphId) const204 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
GetRawBitmap(const GlyphData & rGD) const229 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
SetRawBitmap(GlyphData & rGD,const RawBitmap * pRawBitmap) const242 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
GetPixmap(const GlyphData & rGD,int nScreen) const268 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
SetPixmap(GlyphData & rGD,Pixmap aPixmap,int nScreen) const281 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
RemovingFont(ServerFont & rServerFont)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
RemovingGlyph(ServerFont &,GlyphData & rGlyphData,sal_GlyphId)330 void X11GlyphPeer::RemovingGlyph( ServerFont& /*rServerFont*/, GlyphData& rGlyphData, sal_GlyphId /*aGlyphId*/ )
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 // XRenderGlyph nXRGlyph = (XRenderGlyph)rGlyphData.GetExtPointer();
368 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nXRGlyph );
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 // XRenderGlyph nXRGlyph = (XRenderGlyph)rGlyphData.GetExtPointer();
388 // XRenderPeer::GetInstance().FreeGlyph( aGlyphSet, &nXRGlyph );
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
ForcedAntialiasing(const ServerFont & rServerFont,int nScreen) const402 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
GetGlyphSet(ServerFont & rServerFont,int nScreen)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
GetPixmap(ServerFont & rServerFont,sal_GlyphId aGlyphId,int nReqScreen)452 Pixmap X11GlyphPeer::GetPixmap( ServerFont& rServerFont, sal_GlyphId aGlyphId, int nReqScreen )
453 {
454 if( rServerFont.IsGlyphInvisible( aGlyphId ) )
455 return None;
456
457 GlyphData& rGlyphData = rServerFont.GetGlyphData( aGlyphId );
458 Pixmap aPixmap = GetPixmap( rGlyphData, nReqScreen );
459 if( aPixmap == NO_PIXMAP )
460 {
461 aPixmap = None;
462 if( rServerFont.GetGlyphBitmap1( aGlyphId, 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( aGlyphId != 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
GetRawBitmap(ServerFont & rServerFont,sal_GlyphId aGlyphId)557 const RawBitmap* X11GlyphPeer::GetRawBitmap( ServerFont& rServerFont, sal_GlyphId aGlyphId )
558 {
559 if( rServerFont.IsGlyphInvisible( aGlyphId ) )
560 return NO_RAWBMP;
561
562 GlyphData& rGlyphData = rServerFont.GetGlyphData( aGlyphId );
563
564 const RawBitmap* pRawBitmap = GetRawBitmap( rGlyphData );
565 if( pRawBitmap == NO_RAWBMP )
566 {
567 RawBitmap* pNewBitmap = new RawBitmap;
568 if( rServerFont.GetGlyphBitmap8( aGlyphId, *pNewBitmap ) )
569 {
570 pRawBitmap = pNewBitmap;
571 mnBytesUsed += pNewBitmap->mnScanlineSize * pNewBitmap->mnHeight;
572 mnBytesUsed += sizeof(pNewBitmap);
573 }
574 else
575 {
576 delete pNewBitmap;
577 // fall back to .notdef glyph
578 if( aGlyphId != 0 ) // recurse only once
579 pRawBitmap = GetRawBitmap( rServerFont, 0 );
580 }
581
582 SetRawBitmap( rGlyphData, pRawBitmap );
583 }
584
585 return pRawBitmap;
586 }
587
588 // ---------------------------------------------------------------------------
589
GetXRGlyph(ServerFont & rServerFont,sal_GlyphId aGlyphId)590 XRenderGlyph X11GlyphPeer::GetXRGlyph( ServerFont& rServerFont, sal_GlyphId aGlyphId )
591 {
592 if( rServerFont.IsGlyphInvisible( aGlyphId ) )
593 return NO_GLYPHID;
594
595 GlyphData& rGlyphData = rServerFont.GetGlyphData( aGlyphId );
596
597 XRenderGlyph nXRGlyph = GetRenderGlyph( rGlyphData );
598 if( nXRGlyph == NO_GLYPHID )
599 {
600 // prepare GlyphInfo and Bitmap
601 if( rServerFont.GetGlyphBitmap8( aGlyphId, maRawBitmap ) )
602 {
603 XGlyphInfo aGlyphInfo;
604 aGlyphInfo.width = maRawBitmap.mnWidth;
605 aGlyphInfo.height = maRawBitmap.mnHeight;
606 aGlyphInfo.x = -maRawBitmap.mnXOffset;
607 aGlyphInfo.y = -maRawBitmap.mnYOffset;
608
609 rGlyphData.SetSize( Size( maRawBitmap.mnWidth, maRawBitmap.mnHeight ) );
610 rGlyphData.SetOffset( +maRawBitmap.mnXOffset, +maRawBitmap.mnYOffset );
611
612 const GlyphMetric& rGM = rGlyphData.GetMetric();
613 aGlyphInfo.xOff = +rGM.GetDelta().X();
614 aGlyphInfo.yOff = +rGM.GetDelta().Y();
615
616 // upload glyph bitmap to server
617 GlyphSet aGlyphSet = GetGlyphSet( rServerFont, -1 );
618
619 nXRGlyph = aGlyphId & 0x00FFFFFF;
620 const sal_uLong nBytes = maRawBitmap.mnScanlineSize * maRawBitmap.mnHeight;
621 XRenderPeer::GetInstance().AddGlyph( aGlyphSet, nXRGlyph,
622 aGlyphInfo, (char*)maRawBitmap.mpBits, nBytes );
623 mnBytesUsed += nBytes;
624 }
625 else
626 {
627 // fall back to .notdef glyph
628 if( nXRGlyph != 0 ) // recurse only once
629 nXRGlyph = GetXRGlyph( rServerFont, 0 );
630 }
631
632 SetRenderGlyph( rGlyphData, nXRGlyph );
633 }
634
635 return nXRGlyph;
636 }
637
638 // ===========================================================================
639
X11GlyphCache(X11GlyphPeer & rPeer)640 X11GlyphCache::X11GlyphCache( X11GlyphPeer& rPeer )
641 : GlyphCache( rPeer )
642 {
643 }
644
645 // ---------------------------------------------------------------------------
646
647 static X11GlyphPeer* pX11GlyphPeer = NULL;
648 static X11GlyphCache* pX11GlyphCache = NULL;
649
GetInstance()650 X11GlyphCache& X11GlyphCache::GetInstance()
651 {
652 if( !pX11GlyphCache )
653 {
654 pX11GlyphPeer = new X11GlyphPeer();
655 pX11GlyphCache = new X11GlyphCache( *pX11GlyphPeer );
656 }
657 return *pX11GlyphCache;
658 }
659
660 // ---------------------------------------------------------------------------
661
KillInstance()662 void X11GlyphCache::KillInstance()
663 {
664 delete pX11GlyphCache;
665 delete pX11GlyphPeer;
666 pX11GlyphCache = NULL;
667 pX11GlyphPeer = NULL;
668 }
669
670 // ===========================================================================
671
releaseGlyphPeer()672 void X11SalGraphics::releaseGlyphPeer()
673 {
674 X11GlyphCache::KillInstance();
675 }
676
677 // ===========================================================================
678
679