merge the formfield patch from ooo-build
[ooovba.git] / vcl / unx / source / gdi / salgdi3.cxx
blob1757f80a34ed726ecd928cbe87dd43d0e9ce3348
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 * This file is part of OpenOffice.org.
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.
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).
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.
26 ************************************************************************/
28 // MARKER(update_precomp.py): autogen include statement, do not remove
29 #include "precompiled_vcl.hxx"
31 #include <string.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <math.h>
35 #include <unistd.h>
36 #include <fcntl.h>
37 #include <sys/mman.h>
38 #include <sys/stat.h>
39 #include <sys/types.h>
41 #include "gcach_xpeer.hxx"
42 #include "xrender_peer.hxx"
43 #include "salunx.h"
44 #include "saldata.hxx"
45 #include "saldisp.hxx"
46 #include "salgdi.h"
47 #include "pspgraphics.h"
48 #include "salvd.h"
49 #include "xfont.hxx"
50 #include <vcl/sysdata.hxx>
51 #include "xlfd_attr.hxx"
52 #include "xlfd_smpl.hxx"
53 #include "xlfd_extd.hxx"
54 #include "salcvt.hxx"
56 #include "vcl/printergfx.hxx"
57 #include "vcl/fontmanager.hxx"
58 #include "vcl/jobdata.hxx"
59 #include "vcl/printerinfomanager.hxx"
60 #include "vcl/svapp.hxx"
61 #include "vcl/impfont.hxx"
62 #include "vcl/salframe.hxx"
63 #include "vcl/outdev.h"
65 #include "sal/alloca.h"
66 #include "sal/types.h"
68 #include "rtl/tencinfo.h"
70 #include "osl/file.hxx"
72 #include "tools/string.hxx"
73 #include "tools/debug.hxx"
74 #include "tools/stream.hxx"
76 #include "basegfx/polygon/b2dpolypolygon.hxx"
78 #include "i18npool/mslangid.hxx"
80 #include <hash_set>
82 #ifdef ENABLE_GRAPHITE
83 #include <vcl/graphite_layout.hxx>
84 #include <vcl/graphite_serverfont.hxx>
85 #endif
87 struct cairo_surface_t;
88 struct cairo_t;
89 struct cairo_font_face_t;
90 typedef void* FT_Face;
91 struct cairo_matrix_t {
92 double xx; double yx;
93 double xy; double yy;
94 double x0; double y0;
96 struct cairo_glyph_t
98 unsigned long index;
99 double x;
100 double y;
102 struct BOX
104 short x1, x2, y1, y2;
106 struct _XRegion
108 long size;
109 long numRects;
110 BOX *rects;
111 BOX extents;
113 using namespace rtl;
115 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
117 // ----------------------------------------------------------------------------
119 // manage X11 fonts and self rastered fonts
121 // ----------------------------------------------------------------------------
123 #ifndef _USE_PRINT_EXTENSION_
125 class FontLookup
127 public:
129 struct hash;
130 struct equal;
131 typedef ::std::hash_set< FontLookup,
132 FontLookup::hash,
133 FontLookup::equal > fl_hashset;
135 private:
137 rtl::OString maName;
138 FontWeight mnWeight;
139 FontItalic mnItalic;
140 sal_Bool mbDisplay;
142 public:
144 FontLookup ( ::std::list< psp::fontID >::iterator& it,
145 const psp::PrintFontManager& rMgr );
146 FontLookup (const Xlfd& rFont);
147 FontLookup (const FontLookup &rRef) :
148 maName (rRef.maName),
149 mnWeight (rRef.mnWeight),
150 mnItalic (rRef.mnItalic),
151 mbDisplay(rRef.mbDisplay)
153 ~FontLookup ()
156 static void BuildSet (fl_hashset& rSet);
157 static bool InSet (const fl_hashset& rSet, const Xlfd& rXfld);
158 bool InSet (const fl_hashset& rSet) const;
160 bool operator== (const FontLookup &rRef) const
162 return (abs(mnWeight - rRef.mnWeight) < 2)
163 && (mnItalic == rRef.mnItalic)
164 && (maName == rRef.maName)
165 && (mbDisplay== rRef.mbDisplay);
167 FontLookup& operator= (const FontLookup &rRef)
169 mnWeight = rRef.mnWeight;
170 mnItalic = rRef.mnItalic;
171 maName = rRef.maName;
172 mbDisplay= rRef.mbDisplay;
174 return *this;
176 size_t Hash() const
178 return maName.hashCode ();
181 struct equal
183 bool operator()(const FontLookup &r1, const FontLookup &r2) const
185 return r1 == r2;
188 struct hash
190 size_t operator()(const FontLookup &rArg) const
192 return rArg.Hash();
197 FontLookup::FontLookup ( ::std::list< psp::fontID >::iterator& it,
198 const psp::PrintFontManager& rMgr )
200 psp::FastPrintFontInfo aInfo;
201 if (rMgr.getFontFastInfo (*it, aInfo))
203 mnItalic = PspGraphics::ToFontItalic (aInfo.m_eItalic);
204 mnWeight = PspGraphics::ToFontWeight (aInfo.m_eWeight);
205 mbDisplay= aInfo.m_eType == psp::fonttype::Builtin
206 || aInfo.m_eType == psp::fonttype::Unknown ? False : True;
207 maName = rtl::OUStringToOString
208 ( aInfo.m_aFamilyName,
209 RTL_TEXTENCODING_ISO_8859_1).toAsciiLowerCase();
211 sal_Int32 n_length = maName.getLength();
212 const sal_Char* p_from = maName.getStr();
213 sal_Char* p_to = (sal_Char*)alloca (n_length + 1);
215 sal_Int32 i, j;
216 for (i = 0, j = 0; i < n_length; i++)
218 if ( p_from[i] != ' ' )
219 p_to[j++] = p_from[i];
221 maName = rtl::OString (p_to, j);
222 if (mnItalic == ITALIC_OBLIQUE)
223 mnItalic = ITALIC_NORMAL;
225 else
227 mnItalic = ITALIC_DONTKNOW;
228 mnWeight = WEIGHT_DONTKNOW;
229 mbDisplay= False;
233 FontLookup::FontLookup (const Xlfd& rFont)
235 AttributeProvider* pFactory = rFont.mpFactory;
236 Attribute* pAttr;
238 pAttr = pFactory->RetrieveSlant (rFont.mnSlant);
239 mnItalic = (FontItalic)pAttr->GetValue();
240 pAttr = pFactory->RetrieveWeight (rFont.mnWeight);
241 mnWeight = (FontWeight)pAttr->GetValue();
242 pAttr = pFactory->RetrieveFamily (rFont.mnFamily);
243 maName = pAttr->GetKey();
245 if (mnItalic == ITALIC_OBLIQUE)
246 mnItalic = ITALIC_NORMAL;
248 mbDisplay = True;
251 void
252 FontLookup::BuildSet (FontLookup::fl_hashset &rSet)
254 ::std::list< psp::fontID > aIdList;
256 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
257 rMgr.getFontList( aIdList, NULL, false );
259 ::std::list< psp::fontID >::iterator it;
260 for (it = aIdList.begin(); it != aIdList.end(); ++it)
262 FontLookup aItem (it, rMgr);
263 rSet.insert (aItem);
267 bool
268 FontLookup::InSet (const FontLookup::fl_hashset& rSet) const
270 fl_hashset::const_iterator it = rSet.find(*this);
271 return it == rSet.end() ? false : true;
274 bool
275 FontLookup::InSet (const FontLookup::fl_hashset& rSet, const Xlfd& rXlfd)
277 FontLookup aNeedle (rXlfd);
278 return aNeedle.InSet (rSet);
281 #endif
283 // ----------------------------------------------------------------------------
285 // SalDisplay
287 // ----------------------------------------------------------------------------
289 XlfdStorage*
290 SalDisplay::GetXlfdList() const
292 if ( mpFontList != NULL )
294 return mpFontList;
296 else
298 const_cast<SalDisplay*>(this)->mpFactory = new AttributeProvider;
299 const_cast<SalDisplay*>(this)->mpFontList = new XlfdStorage;
300 const_cast<SalDisplay*>(this)->mpFallbackFactory = new VirtualXlfd;
302 int i, nFontCount;
303 const int nMaxCount = 64 * 1024 - 1;
304 Display *pDisplay = GetDisplay();
305 char **ppFontList = XListFonts(pDisplay, "-*", nMaxCount, &nFontCount);
308 // create a list of simple Xlfd font information
311 Xlfd *pXlfdList = (Xlfd*)malloc( nFontCount * sizeof(Xlfd) );
312 int nXlfdCount = 0;
314 for ( i = 0; i < nFontCount; i++ )
316 if ( pXlfdList[ nXlfdCount ].FromString(ppFontList[i], mpFactory) )
317 ++nXlfdCount;
320 XFreeFontNames( ppFontList );
322 mpFactory->AddClassification();
323 // add some pretty print description
324 mpFactory->AddAnnotation();
325 // misc feature checking
326 mpFactory->TagFeature();
328 // sort according to font style
329 qsort( pXlfdList, nXlfdCount, sizeof(Xlfd), XlfdCompare );
331 #ifndef _USE_PRINT_EXTENSION_
332 // create a list of fonts already managed by the fontmanager
333 FontLookup::fl_hashset aSet;
334 FontLookup::BuildSet (aSet);
335 #endif
338 // create a font list with merged encoding information
341 BitmapXlfdStorage aBitmapList;
342 ScalableXlfd *pScalableFont = NULL;
344 int nFrom = 0;
345 for ( i = 0; i < nXlfdCount; i++ )
347 // exclude openlook glyph and cursor
348 Attribute *pAttr = mpFactory->RetrieveFamily(pXlfdList[i].mnFamily);
349 if ( pAttr->HasFeature( XLFD_FEATURE_OL_GLYPH
350 | XLFD_FEATURE_OL_CURSOR) )
351 continue;
352 // exclude fonts with unknown encoding
353 if ( pXlfdList[i].GetEncoding() == RTL_TEXTENCODING_DONTKNOW )
354 continue;
355 // exclude "interface system" and "interface user"
356 if (pAttr->HasFeature( XLFD_FEATURE_APPLICATION_FONT ) )
357 continue;
358 // exclude fonts already managed by fontmanager, anyway keep
359 // gui fonts: they are candidates for GetInterfaceFont ()
360 if (pXlfdList[i].Fonttype() == eTypeScalable)
361 ((VirtualXlfd*)mpFallbackFactory)->FilterInterfaceFont (pXlfdList + i);
362 #ifndef _USE_PRINT_EXTENSION_
363 if (FontLookup::InSet (aSet, pXlfdList[i]))
364 continue;
365 #endif
366 Bool bSameOutline = pXlfdList[i].SameFontoutline(pXlfdList + nFrom);
367 XlfdFonttype eType = pXlfdList[i].Fonttype();
369 // flush the old merged font list if the name doesn't match any more
370 if ( !bSameOutline )
372 mpFontList->Add( pScalableFont );
373 mpFontList->Add( &aBitmapList );
374 pScalableFont = NULL;
375 aBitmapList.Reset();
378 // merge the font or generate a new one
379 switch( eType )
381 case eTypeScalable:
382 if ( pScalableFont == NULL )
383 pScalableFont = new ScalableXlfd;
384 pScalableFont->AddEncoding(pXlfdList + i);
385 break;
387 case eTypeBitmap:
388 aBitmapList.AddBitmapFont( pXlfdList + i );
389 break;
391 case eTypeScalableBitmap:
392 // ignore scaled X11 bitmap fonts because they look too ugly
393 default:
394 break;
397 nFrom = i;
400 // flush the merged list into the global list
401 mpFontList->Add( pScalableFont );
402 mpFontList->Add( &aBitmapList );
403 if (mpFallbackFactory->NumEncodings() > 0)
404 mpFontList->Add( mpFallbackFactory );
405 // cleanup the list of simple font information
406 if ( pXlfdList != NULL )
407 free( pXlfdList );
409 return mpFontList;
413 // ---------------------------------------------------------------------------
415 ExtendedFontStruct*
416 SalDisplay::GetFont( const ExtendedXlfd *pRequestedFont,
417 const Size& rPixelSize, sal_Bool bVertical ) const
419 // TODO: either get rid of X11 fonts or get rid of the non-hashmapped cache
420 if( !m_pFontCache )
422 m_pFontCache = new SalFontCache( 64, 64, 16 ); // ???
424 else
426 ExtendedFontStruct *pItem;
427 for ( pItem = m_pFontCache->First();
428 pItem != NULL;
429 pItem = m_pFontCache->Next() )
431 if ( pItem->Match(pRequestedFont, rPixelSize, bVertical) )
433 if( m_pFontCache->GetCurPos() )
435 m_pFontCache->Remove( pItem );
436 m_pFontCache->Insert( pItem, 0UL );
438 return pItem;
443 // before we expand the cache, we look for very old and unused items
444 if( m_pFontCache->Count() >= 64 )
446 ExtendedFontStruct *pItem;
447 for ( pItem = m_pFontCache->Last();
448 pItem != NULL;
449 pItem = m_pFontCache->Prev() )
451 if( 1 == pItem->GetRefCount() )
453 m_pFontCache->Remove( pItem );
454 pItem->ReleaseRef();
455 if( m_pFontCache->Count() < 64 )
456 break;
461 ExtendedFontStruct *pItem = new ExtendedFontStruct( GetDisplay(),
462 rPixelSize, bVertical,
463 const_cast<ExtendedXlfd*>(pRequestedFont) );
464 m_pFontCache->Insert( pItem, 0UL );
465 pItem->AddRef();
467 return pItem;
470 // ---------------------------------------------------------------------------
472 void
473 SalDisplay::DestroyFontCache()
475 if( m_pFontCache )
477 ExtendedFontStruct *pItem = m_pFontCache->First();
478 while( pItem )
480 delete pItem;
481 pItem = m_pFontCache->Next();
483 delete m_pFontCache;
485 if( mpFontList )
487 mpFontList->Dispose();
488 delete mpFontList;
490 if ( mpFactory )
492 delete mpFactory;
495 m_pFontCache = (SalFontCache*)NULL;
496 mpFontList = (XlfdStorage*)NULL;
497 mpFactory = (AttributeProvider*)NULL;
500 // ===========================================================================
502 // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#)
503 class PspKernInfo : public ExtraKernInfo
505 public:
506 PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {}
507 protected:
508 virtual void Initialize() const;
511 //--------------------------------------------------------------------------
513 void PspKernInfo::Initialize() const
515 mbInitialized = true;
517 // get the kerning pairs from psprint
518 const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
519 typedef std::list< psp::KernPair > PspKernPairs;
520 const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId );
521 if( rKernPairs.empty() )
522 return;
524 // feed psprint's kerning list into a lookup-friendly container
525 maUnicodeKernPairs.resize( rKernPairs.size() );
526 PspKernPairs::const_iterator it = rKernPairs.begin();
527 for(; it != rKernPairs.end(); ++it )
529 ImplKernPairData aKernPair = { it->first, it->second, it->kern_x };
530 maUnicodeKernPairs.insert( aKernPair );
534 // ----------------------------------------------------------------------------
536 // X11SalGraphics
538 // ----------------------------------------------------------------------------
541 X11SalGraphics::SelectFont()
543 Display *pDisplay = GetXDisplay();
545 if( !pFontGC_ )
547 XGCValues values;
548 values.subwindow_mode = ClipByChildren;
549 values.fill_rule = EvenOddRule; // Pict import/ Gradient
550 values.graphics_exposures = False;
551 values.foreground = nTextPixel_;
552 #ifdef _USE_PRINT_EXTENSION_
553 values.background = xColormap_->GetWhitePixel();
554 pFontGC_ = XCreateGC( pDisplay, hDrawable_,
555 GCSubwindowMode | GCFillRule
556 | GCGraphicsExposures | GCBackground | GCForeground,
557 &values );
558 #else
559 pFontGC_ = XCreateGC( pDisplay, hDrawable_,
560 GCSubwindowMode | GCFillRule
561 | GCGraphicsExposures | GCForeground,
562 &values );
563 #endif
565 if( !bFontGC_ )
567 XSetForeground( pDisplay, pFontGC_, nTextPixel_ );
568 SetClipRegion( pFontGC_ );
569 bFontGC_ = TRUE;
572 return pFontGC_;
575 //--------------------------------------------------------------------------
577 bool X11SalGraphics::setFont( const ImplFontSelectData *pEntry, int nFallbackLevel )
579 #ifdef HDU_DEBUG
580 ByteString aReqName( "NULL" );
581 if( pEntry )
582 aReqName = ByteString( pEntry->maName, RTL_TEXTENCODING_UTF8 );
583 ByteString aUseName( "NULL" );
584 if( pEntry && pEntry->mpFontData )
585 aUseName = ByteString( pEntry->mpFontData->GetFamilyName(), RTL_TEXTENCODING_UTF8 );
586 fprintf( stderr, "SetFont(lvl=%d,\"%s\", %d*%d, naa=%d,b=%d,i=%d) => \"%s\"\n",
587 nFallbackLevel, aReqName.GetBuffer(),
588 !pEntry?-1:pEntry->mnWidth, !pEntry?-1:pEntry->mnHeight,
589 !pEntry?-1:pEntry->mbNonAntialiased,
590 !pEntry?-1:pEntry->meWeight, !pEntry?-1:pEntry->meItalic,
591 aUseName.GetBuffer() );
592 #endif
594 // release all no longer needed font resources
595 for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
597 mXFont[i] = NULL; // ->ReleaseRef()
599 if( mpServerFont[i] != NULL )
601 // old server side font is no longer referenced
602 GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] );
603 mpServerFont[i] = NULL;
607 // return early if there is no new font
608 if( !pEntry )
609 return false;
611 bFontVertical_ = pEntry->mbVertical;
613 // return early if this is not a valid font for this graphics
614 if( !pEntry->mpFontData )
615 return false;
617 // handle the request for a native X11-font
618 if( ImplX11FontData::CheckFontData( *pEntry->mpFontData ) )
620 const ImplX11FontData* pRequestedFont = static_cast<const ImplX11FontData*>( pEntry->mpFontData );
621 const ExtendedXlfd& rX11Font = pRequestedFont->GetExtendedXlfd();
623 Size aReqSize( pEntry->mnWidth, pEntry->mnHeight );
624 mXFont[ nFallbackLevel ] = GetDisplay()->GetFont( &rX11Font, aReqSize, bFontVertical_ );
625 bFontGC_ = FALSE;
626 return true;
629 // handle the request for a non-native X11-font => use the GlyphCache
630 ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry );
631 if( pServerFont != NULL )
633 if( !pServerFont->TestFont() )
635 GlyphCache::GetInstance().UncacheFont( *pServerFont );
636 return false;
638 mpServerFont[ nFallbackLevel ] = pServerFont;
639 return true;
642 return false;
645 //--------------------------------------------------------------------------
647 inline sal_Unicode SwapBytes( const sal_Unicode nIn )
649 return ((nIn >> 8) & 0x00ff) | ((nIn & 0x00ff) << 8);
652 // draw string in a specific multibyte encoding
653 static void
654 ConvertTextItem16( XTextItem16* pTextItem, rtl_TextEncoding nEncoding )
656 if ( (pTextItem == NULL) || (pTextItem->nchars <= 0) )
657 return;
659 SalConverterCache* pCvt = SalConverterCache::GetInstance();
660 // convert the string into the font encoding
661 sal_Size nSize;
662 sal_Size nBufferSize = pTextItem->nchars * 2;
663 sal_Char *pBuffer = (sal_Char*)alloca( nBufferSize );
665 nSize = pCvt->ConvertStringUTF16( (sal_Unicode*)pTextItem->chars, pTextItem->nchars,
666 pBuffer, nBufferSize, nEncoding);
668 sal_Char *pTextChars = (sal_Char*)pTextItem->chars;
669 unsigned int n = 0, m = 0;
671 if ( nEncoding == RTL_TEXTENCODING_GB_2312
672 || nEncoding == RTL_TEXTENCODING_GBT_12345
673 || nEncoding == RTL_TEXTENCODING_GBK
674 || nEncoding == RTL_TEXTENCODING_BIG5 )
676 // GB and Big5 needs special treatment since chars can be single or
677 // double byte: encoding is
678 // [ 0x00 - 0x7f ] | [ 0x81 - 0xfe ] [ 0x40 - 0x7e 0x80 - 0xfe ]
679 while ( n < nSize )
681 if ( (unsigned char)pBuffer[ n ] < 0x80 )
683 pTextChars[ m++ ] = 0x0;
684 pTextChars[ m++ ] = pBuffer[ n++ ];
686 else
688 pTextChars[ m++ ] = pBuffer[ n++ ];
689 pTextChars[ m++ ] = pBuffer[ n++ ];
692 pTextItem->nchars = m / 2;
694 else
695 if ( pCvt->IsSingleByteEncoding(nEncoding) )
697 // Single Byte encoding has to be padded
698 while ( n < nSize )
700 pTextChars[ m++ ] = 0x0;
701 pTextChars[ m++ ] = pBuffer[ n++ ];
703 pTextItem->nchars = nSize;
705 else
707 while ( n < nSize )
709 pTextChars[ m++ ] = pBuffer[ n++ ];
711 pTextItem->nchars = nSize / 2;
714 // XXX FIXME
715 if ( (nEncoding == RTL_TEXTENCODING_GB_2312)
716 || (nEncoding == RTL_TEXTENCODING_EUC_KR) )
718 for (unsigned int n_char = 0; n_char < m; n_char++ )
719 pTextChars[ n_char ] &= 0x7F;
723 //--------------------------------------------------------------------------
724 namespace {
726 class CairoWrapper
728 private:
729 oslModule mpCairoLib;
731 cairo_surface_t* (*mp_xlib_surface_create_with_xrender_format)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int );
732 void (*mp_surface_destroy)(cairo_surface_t *);
733 cairo_t* (*mp_create)(cairo_surface_t *);
734 void (*mp_destroy)(cairo_t*);
735 void (*mp_clip)(cairo_t*);
736 void (*mp_rectangle)(cairo_t*, double, double, double, double);
737 cairo_font_face_t * (*mp_ft_font_face_create_for_ft_face)(FT_Face, int);
738 void (*mp_set_font_face)(cairo_t *, cairo_font_face_t *);
739 void (*mp_font_face_destroy)(cairo_font_face_t *);
740 void (*mp_matrix_init_identity)(cairo_matrix_t *);
741 void (*mp_matrix_scale)(cairo_matrix_t *, double, double);
742 void (*mp_matrix_rotate)(cairo_matrix_t *, double);
743 void (*mp_set_font_matrix)(cairo_t *, const cairo_matrix_t *);
744 void (*mp_show_glyphs)(cairo_t *, const cairo_glyph_t *, int );
745 void (*mp_set_source_rgb)(cairo_t *, double , double , double );
747 bool canEmbolden() const { return false; }
749 CairoWrapper();
750 public:
751 static CairoWrapper& get();
752 bool isValid() const { return (mpCairoLib != NULL); }
753 bool isCairoRenderable(const ServerFont& rFont);
755 cairo_surface_t* xlib_surface_create_with_xrender_format(Display *pDisplay, Drawable drawable, Screen *pScreen, XRenderPictFormat *pFormat, int width, int height)
756 { return (*mp_xlib_surface_create_with_xrender_format)(pDisplay, drawable, pScreen, pFormat, width, height); }
757 void surface_destroy(cairo_surface_t *surface) { (*mp_surface_destroy)(surface); }
758 cairo_t* create(cairo_surface_t *surface) { return (*mp_create)(surface); }
759 void destroy(cairo_t *cr) { (*mp_destroy)(cr); }
760 void clip(cairo_t *cr) { (*mp_clip)(cr); }
761 void rectangle(cairo_t *cr, double x, double y, double width, double height)
762 { (*mp_rectangle)(cr, x, y, width, height); }
763 cairo_font_face_t* ft_font_face_create_for_ft_face(FT_Face face, int load_flags)
764 { return (*mp_ft_font_face_create_for_ft_face)(face, load_flags); }
765 void set_font_face(cairo_t *cr, cairo_font_face_t *font_face)
766 { (*mp_set_font_face)(cr, font_face); }
767 void font_face_destroy(cairo_font_face_t *font_face)
768 { (*mp_font_face_destroy)(font_face); }
769 void matrix_init_identity(cairo_matrix_t *matrix)
770 { (*mp_matrix_init_identity)(matrix); }
771 void matrix_scale(cairo_matrix_t *matrix, double sx, double sy)
772 { (*mp_matrix_scale)(matrix, sx, sy); }
773 void matrix_rotate(cairo_matrix_t *matrix, double radians)
774 { (*mp_matrix_rotate)(matrix, radians); }
775 void set_font_matrix(cairo_t *cr, const cairo_matrix_t *matrix)
776 { (*mp_set_font_matrix)(cr, matrix); }
777 void show_glyphs(cairo_t *cr, const cairo_glyph_t *glyphs, int no_glyphs)
778 { (*mp_show_glyphs)(cr, glyphs, no_glyphs); }
779 void set_source_rgb(cairo_t *cr, double red, double green, double blue)
780 { (*mp_set_source_rgb)(cr, red, green, blue); }
783 static CairoWrapper* pCairoInstance = NULL;
785 CairoWrapper& CairoWrapper::get()
787 if( ! pCairoInstance )
788 pCairoInstance = new CairoWrapper();
789 return *pCairoInstance;
792 CairoWrapper::CairoWrapper()
793 : mpCairoLib( NULL )
795 static const char* pDisableCairoText = getenv( "SAL_DISABLE_CAIROTEXT" );
796 if( pDisableCairoText && (pDisableCairoText[0] != '0') )
797 return;
799 int nDummy;
800 if( !XQueryExtension( GetX11SalData()->GetDisplay()->GetDisplay(), "RENDER", &nDummy, &nDummy, &nDummy ) )
801 return;
803 #ifdef MACOSX
804 OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( "libcairo.2.dylib" ));
805 #else
806 OUString aLibName( RTL_CONSTASCII_USTRINGPARAM( "libcairo.so.2" ));
807 #endif
808 mpCairoLib = osl_loadModule( aLibName.pData, SAL_LOADMODULE_DEFAULT );
809 if( !mpCairoLib )
810 return;
812 #ifdef DEBUG
813 // check cairo version
814 int (*p_version)();
815 p_version = (int(*)()) osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_version" );
816 const int nVersion = p_version ? (*p_version)() : 0;
817 fprintf( stderr, "CAIRO version=%d\n", nVersion );
818 #endif
820 mp_xlib_surface_create_with_xrender_format = (cairo_surface_t* (*)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int ))
821 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_xlib_surface_create_with_xrender_format" );
822 mp_surface_destroy = (void(*)(cairo_surface_t*))
823 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_surface_destroy" );
824 mp_create = (cairo_t*(*)(cairo_surface_t*))
825 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_create" );
826 mp_destroy = (void(*)(cairo_t*))
827 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_destroy" );
828 mp_clip = (void(*)(cairo_t*))
829 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_clip" );
830 mp_rectangle = (void(*)(cairo_t*, double, double, double, double))
831 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_rectangle" );
832 mp_ft_font_face_create_for_ft_face = (cairo_font_face_t * (*)(FT_Face, int))
833 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_ft_font_face_create_for_ft_face" );
834 mp_set_font_face = (void (*)(cairo_t *, cairo_font_face_t *))
835 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_face" );
836 mp_font_face_destroy = (void (*)(cairo_font_face_t *))
837 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_font_face_destroy" );
838 mp_matrix_init_identity = (void (*)(cairo_matrix_t *))
839 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_init_identity" );
840 mp_matrix_scale = (void (*)(cairo_matrix_t *, double, double))
841 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_scale" );
842 mp_matrix_rotate = (void (*)(cairo_matrix_t *, double))
843 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_rotate" );
844 mp_set_font_matrix = (void (*)(cairo_t *, const cairo_matrix_t *))
845 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_matrix" );
846 mp_show_glyphs = (void (*)(cairo_t *, const cairo_glyph_t *, int ))
847 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_show_glyphs" );
848 mp_set_source_rgb = (void (*)(cairo_t *, double , double , double ))
849 osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_source_rgb" );
851 if( !(
852 mp_xlib_surface_create_with_xrender_format &&
853 mp_surface_destroy &&
854 mp_create &&
855 mp_destroy &&
856 mp_clip &&
857 mp_rectangle &&
858 mp_ft_font_face_create_for_ft_face &&
859 mp_set_font_face &&
860 mp_font_face_destroy &&
861 mp_matrix_init_identity &&
862 mp_matrix_scale &&
863 mp_matrix_rotate &&
864 mp_set_font_matrix &&
865 mp_show_glyphs &&
866 mp_set_source_rgb
869 osl_unloadModule( mpCairoLib );
870 mpCairoLib = NULL;
871 #if OSL_DEBUG_LEVEL > 1
872 fprintf( stderr, "not all needed symbols were found\n" );
873 #endif
877 bool CairoWrapper::isCairoRenderable(const ServerFont& rFont)
879 return rFont.GetFtFace() && isValid() && rFont.GetAntialiasAdvice() &&
880 (rFont.NeedsArtificialBold() ? canEmbolden() : true);
883 } //namespace
885 CairoFontsCache::LRUFonts CairoFontsCache::maLRUFonts;
886 int CairoFontsCache::mnRefCount = 0;
888 CairoFontsCache::CairoFontsCache()
890 ++mnRefCount;
893 CairoFontsCache::~CairoFontsCache()
895 --mnRefCount;
896 if (!mnRefCount && !maLRUFonts.empty())
898 CairoWrapper &rCairo = CairoWrapper::get();
899 LRUFonts::iterator aEnd = maLRUFonts.end();
900 for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
901 rCairo.font_face_destroy((cairo_font_face_t*)aI->first);
905 void CairoFontsCache::CacheFont(void *pFont, void* pId)
907 maLRUFonts.push_front( std::pair<void*, void *>(pFont, pId) );
908 if (maLRUFonts.size() > 8)
910 CairoWrapper &rCairo = CairoWrapper::get();
911 rCairo.font_face_destroy((cairo_font_face_t*)maLRUFonts.back().first);
912 maLRUFonts.pop_back();
916 void* CairoFontsCache::FindCachedFont(void *pId)
918 LRUFonts::iterator aEnd = maLRUFonts.end();
919 for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
920 if (aI->second == pId)
921 return aI->first;
922 return NULL;
925 void X11SalGraphics::DrawCairoAAFontString( const ServerFontLayout& rLayout )
927 std::vector<cairo_glyph_t> cairo_glyphs;
928 cairo_glyphs.reserve( 256 );
930 Point aPos;
931 sal_GlyphId aGlyphId;
932 for( int nStart = 0; rLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
934 cairo_glyph_t aGlyph;
935 aGlyph.index = aGlyphId & GF_IDXMASK;
936 aGlyph.x = aPos.X();
937 aGlyph.y = aPos.Y();
938 cairo_glyphs.push_back(aGlyph);
941 if (cairo_glyphs.empty())
942 return;
944 // find a XRenderPictFormat compatible with the Drawable
945 XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat());
946 if( !pVisualFormat )
948 Visual* pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual();
949 pVisualFormat = XRenderPeer::GetInstance().FindVisualFormat( pVisual );
950 // cache the XRenderPictFormat
951 SetXRenderFormat( static_cast<void*>(pVisualFormat) );
954 DBG_ASSERT( pVisualFormat!=NULL, "no matching XRenderPictFormat for text" );
955 if( !pVisualFormat )
956 return;
958 CairoWrapper &rCairo = CairoWrapper::get();
960 Display* pDisplay = GetXDisplay();
962 cairo_surface_t *surface = rCairo.xlib_surface_create_with_xrender_format (pDisplay,
963 hDrawable_, ScreenOfDisplay(pDisplay, m_nScreen), pVisualFormat, SAL_MAX_INT16, SAL_MAX_INT16);
966 * It might be ideal to cache surface and cairo context between calls and
967 * only destroy it when the drawable changes, but to do that we need to at
968 * least change the SalFrame etc impls to dtor the SalGraphics *before* the
969 * destruction of the windows they reference
971 cairo_t *cr = rCairo.create(surface);
972 rCairo.surface_destroy(surface);
974 if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) )
976 for (long i = 0; i < pClipRegion_->numRects; ++i)
978 rCairo.rectangle(cr,
979 pClipRegion_->rects[i].x1,
980 pClipRegion_->rects[i].y1,
981 pClipRegion_->rects[i].x2 - pClipRegion_->rects[i].x1,
982 pClipRegion_->rects[i].y2 - pClipRegion_->rects[i].y1);
984 rCairo.clip(cr);
987 rCairo.set_source_rgb(cr,
988 SALCOLOR_RED(nTextColor_)/255.0,
989 SALCOLOR_GREEN(nTextColor_)/255.0,
990 SALCOLOR_BLUE(nTextColor_)/255.0);
992 ServerFont& rFont = rLayout.GetServerFont();
994 cairo_font_face_t* font_face = NULL;
996 void *pId = rFont.GetFtFace();
997 font_face = (cairo_font_face_t*)m_aCairoFontsCache.FindCachedFont(pId);
998 if (!font_face)
1000 font_face = rCairo.ft_font_face_create_for_ft_face(pId, rFont.GetLoadFlags());
1001 m_aCairoFontsCache.CacheFont(font_face, pId);
1004 rCairo.set_font_face(cr, font_face);
1006 cairo_matrix_t m;
1007 const ImplFontSelectData& rFSD = rFont.GetFontSelData();
1008 int nWidth = rFSD.mnWidth ? rFSD.mnWidth : rFSD.mnHeight;
1010 rCairo.matrix_init_identity(&m);
1012 if (rLayout.GetOrientation())
1013 rCairo.matrix_rotate(&m, (3600 - rLayout.GetOrientation()) * M_PI / 1800.0);
1015 rCairo.matrix_scale(&m, nWidth, rFSD.mnHeight);
1016 if (rFont.NeedsArtificialItalic())
1017 m.xy = -m.xx * 0x6000L / 0x10000L;
1019 rCairo.set_font_matrix(cr, &m);
1020 rCairo.show_glyphs(cr, &cairo_glyphs[0], cairo_glyphs.size());
1021 rCairo.destroy(cr);
1024 //--------------------------------------------------------------------------
1026 void X11SalGraphics::DrawServerAAFontString( const ServerFontLayout& rLayout )
1028 // get xrender target for this drawable
1029 Picture aDstPic = GetXRenderPicture();
1030 if( !aDstPic )
1031 return;
1033 // get a XRenderPicture for the font foreground
1034 // TODO: move into own method
1035 XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
1036 XRenderPictFormat* pVisualFormat = (XRenderPictFormat*)GetXRenderFormat();
1037 DBG_ASSERT( pVisualFormat, "we already have a render picture, but XRenderPictFormat==NULL???");
1038 const int nVisualDepth = pVisualFormat->depth;
1039 SalDisplay::RenderEntry& rEntry = GetDisplay()->GetRenderEntries( m_nScreen )[ nVisualDepth ];
1040 if( !rEntry.m_aPicture )
1042 // create and cache XRenderPicture for the font foreground
1043 Display* pDisplay = GetXDisplay();
1044 #ifdef DEBUG
1045 int iDummy;
1046 unsigned uDummy;
1047 XLIB_Window wDummy;
1048 unsigned int nDrawDepth;
1049 ::XGetGeometry( pDisplay, hDrawable_, &wDummy, &iDummy, &iDummy,
1050 &uDummy, &uDummy, &uDummy, &nDrawDepth );
1051 DBG_ASSERT( static_cast<unsigned>(nVisualDepth) == nDrawDepth, "depth messed up for XRender" );
1052 #endif
1054 rEntry.m_aPixmap = ::XCreatePixmap( pDisplay, hDrawable_, 1, 1, nVisualDepth );
1056 XRenderPictureAttributes aAttr;
1057 aAttr.repeat = true;
1058 rEntry.m_aPicture = rRenderPeer.CreatePicture ( rEntry.m_aPixmap, pVisualFormat, CPRepeat, &aAttr );
1061 // set font foreground color and opacity
1062 XRenderColor aRenderColor = GetXRenderColor( nTextPixel_ );
1063 rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 );
1065 // set clipping
1066 // TODO: move into GetXRenderPicture()?
1067 if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) )
1068 rRenderPeer.SetPictureClipRegion( aDstPic, pClipRegion_ );
1070 ServerFont& rFont = rLayout.GetServerFont();
1071 X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
1072 GlyphSet aGlyphSet = rGlyphPeer.GetGlyphSet( rFont, m_nScreen );
1074 Point aPos;
1075 static const int MAXGLYPHS = 160;
1076 sal_GlyphId aGlyphAry[ MAXGLYPHS ];
1077 int nMaxGlyphs = rLayout.GetOrientation() ? 1 : MAXGLYPHS;
1078 for( int nStart = 0;;)
1080 int nGlyphs = rLayout.GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart );
1081 if( !nGlyphs )
1082 break;
1084 // #i51924# avoid 32->16bit coordinate truncation problem in X11
1085 // TODO: reevaluate once displays with >30000 pixels are available
1086 if( aPos.X() >= 30000 || aPos.Y() >= 30000 )
1087 continue;
1089 unsigned int aRenderAry[ MAXGLYPHS ];
1090 for( int i = 0; i < nGlyphs; ++i )
1091 aRenderAry[ i ] = rGlyphPeer.GetGlyphId( rFont, aGlyphAry[i] );
1092 rRenderPeer.CompositeString32( rEntry.m_aPicture, aDstPic,
1093 aGlyphSet, aPos.X(), aPos.Y(), aRenderAry, nGlyphs );
1097 //--------------------------------------------------------------------------
1099 bool X11SalGraphics::DrawServerAAForcedString( const ServerFontLayout& rLayout )
1101 ServerFont& rFont = rLayout.GetServerFont();
1103 // prepare glyphs and get extent of operation
1104 X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
1105 int nXmin = 0;
1106 int nXmax = 0;
1107 int nYmin = 0;
1108 int nYmax = 0;
1109 int nStart = 0;
1110 Point aPos;
1111 sal_GlyphId nGlyph;
1112 for( bool bFirst=true; rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); )
1114 const RawBitmap* const pRawBitmap = rGlyphPeer.GetRawBitmap( rFont, nGlyph );
1115 if( !pRawBitmap )
1116 continue;
1118 const int nX1 = aPos.X() + pRawBitmap->mnXOffset;
1119 const int nY1 = aPos.Y() + pRawBitmap->mnYOffset;
1120 const int nX2 = nX1 + pRawBitmap->mnWidth;
1121 const int nY2 = nY1 + pRawBitmap->mnHeight;
1123 if( bFirst )
1125 bFirst = false;
1126 nXmin = nX1;
1127 nXmax = nX2;
1128 nYmin = nY1;
1129 nYmax = nY2;
1131 else
1133 if( nXmin > nX1 ) nXmin = nX1;
1134 if( nXmax < nX2 ) nXmax = nX2;
1135 if( nYmin > nY1 ) nYmin = nY1;
1136 if( nYmax < nY2 ) nYmax = nY2;
1140 // get XImage
1141 GetDisplay()->GetXLib()->PushXErrorLevel( true );
1142 Display* pDisplay = GetXDisplay();
1144 XRectangle aXRect;
1145 long nWidth = 1, nHeight = 1;
1146 if( m_pFrame )
1147 nWidth = m_pFrame->maGeometry.nWidth, nHeight = m_pFrame->maGeometry.nHeight;
1148 else if( m_pVDev )
1149 nWidth = m_pVDev->GetWidth(), nHeight = m_pVDev->GetHeight();
1151 if( pClipRegion_ && !XEmptyRegion( pClipRegion_ ) )
1153 // get bounding box
1154 XClipBox( pClipRegion_, &aXRect );
1155 // clip with window
1156 if( aXRect.x < 0 ) aXRect.x = 0;
1158 if( aXRect.y < 0 ) aXRect.y = 0;
1159 if( aXRect.width+aXRect.x > nWidth ) aXRect.width = nWidth-aXRect.x;
1160 if( aXRect.height+aXRect.y > nHeight ) aXRect.height = nHeight-aXRect.y;
1162 else
1164 aXRect.x = 0;
1165 aXRect.y = 0;
1166 aXRect.width = nWidth;
1167 aXRect.height = nHeight;
1169 if( m_pFrame )
1171 // clip with screen
1172 int nScreenX = m_pFrame->maGeometry.nX+aXRect.x;
1173 int nScreenY = m_pFrame->maGeometry.nY+aXRect.y;
1174 const Size& rScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize;
1175 int nScreenW = rScreenSize.Width();
1176 int nScreenH = rScreenSize.Height();
1177 if( nScreenX < 0 )
1178 aXRect.x -= nScreenX, aXRect.width += nScreenX;
1179 if( nScreenX+aXRect.width > nScreenW )
1180 aXRect.width = nScreenW-nScreenX;
1181 if( nScreenY < 0 )
1182 aXRect.y -= nScreenY, aXRect.height += nScreenY;
1183 if( nScreenY+aXRect.height > nScreenH )
1184 aXRect.height = nScreenH-nScreenY;
1188 if( nXmin < aXRect.x ) nXmin = aXRect.x;
1189 if( nYmin < aXRect.y ) nYmin = aXRect.y;
1190 if( nXmax >= aXRect.x+aXRect.width ) nXmax = aXRect.x + aXRect.width - 1;
1191 if( nYmax >= aXRect.y+aXRect.height ) nYmax = aXRect.y + aXRect.height - 1;
1193 if( nXmin > nXmax )
1194 return false;
1195 if( nYmin > nYmax )
1196 return false;
1198 XImage* pImg = XGetImage( pDisplay, hDrawable_,
1199 nXmin, nYmin,
1200 (nXmax-nXmin+1), (nYmax-nYmin+1),
1201 ~0, ZPixmap );
1202 if( pImg == NULL )
1204 if( m_pFrame )
1206 // the reason we did not get an image could be that the frame
1207 // geometry changed in the meantime; lets get the current geometry
1208 // and clip against the current window size as well as the screen
1209 // with the current frame position
1210 const Size& rScreenSize = GetDisplay()->getDataForScreen(m_nScreen).m_aSize;
1211 int nScreenW = rScreenSize.Width();
1212 int nScreenH = rScreenSize.Height();
1213 XLIB_Window aRoot = None;
1214 int x = 0, y = 0;
1215 unsigned int w = 0, h = 0, bw = 0, d;
1216 XGetGeometry( pDisplay, hDrawable_, &aRoot, &x, &y, &w, &h, &bw, &d );
1217 XTranslateCoordinates( pDisplay, hDrawable_, aRoot, 0, 0, &x, &y, &aRoot );
1218 if( nXmin + x < 0 ) // clip on left screen edge
1219 nXmin += x-nXmin;
1220 if( nYmin + y < 0 ) // clip on top screen edge
1221 nYmin += y-nYmin;
1222 if( nXmax >= int(w) ) // clip on right window egde
1223 nXmax = w-1;
1224 if( nYmax >= int(h) ) // clip on bottom window edge
1225 nYmax = h-1;
1226 if( nXmax + x >= nScreenW ) // clip on right screen edge
1227 nXmax -= (nXmax + x - nScreenW)+1;
1228 if( nYmax + y >= nScreenH ) // clip on bottom screen edge
1229 nYmax -= (nYmax + y - nScreenH)+1;
1230 if( nXmax >= nXmin && nYmax >= nYmin )
1232 // try again to get the image
1233 pImg = XGetImage( pDisplay, hDrawable_,
1234 nXmin, nYmin,
1235 (nXmax-nXmin+1), (nYmax-nYmin+1),
1236 ~0, ZPixmap );
1239 if( pImg == NULL )
1241 GetDisplay()->GetXLib()->PopXErrorLevel();
1242 return false;
1246 // prepare context
1247 GC nGC = SelectFont();
1248 XGCValues aGCVal;
1249 XGetGCValues( pDisplay, nGC, GCForeground, &aGCVal );
1251 unsigned long nOrigColor = XGetPixel( pImg, 0, 0 );
1252 XPutPixel( pImg, 0, 0, aGCVal.foreground );
1253 unsigned char aColor[4];
1254 aColor[0] = pImg->data[0];
1255 aColor[1] = pImg->data[1];
1256 aColor[2] = pImg->data[2];
1257 aColor[3] = pImg->data[3];
1258 XPutPixel( pImg, 0, 0, nOrigColor );
1260 // work on XImage
1261 const int bpp = pImg->bits_per_pixel >> 3;
1262 for( nStart = 0; rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); )
1264 const RawBitmap* const pRawBitmap = rGlyphPeer.GetRawBitmap( rFont, nGlyph );
1265 if( !pRawBitmap )
1266 continue;
1268 const int nX1 = aPos.X() + pRawBitmap->mnXOffset;
1269 const int nY1 = aPos.Y() + pRawBitmap->mnYOffset;
1271 if( (nX1 <= nXmax) && (int(nX1 + pRawBitmap->mnWidth) > nXmin)
1272 && (nY1 <= nYmax) && (int(nY1 + pRawBitmap->mnHeight) > nYmin) )
1274 const unsigned char* p10 = pRawBitmap->mpBits;
1275 unsigned char* p20 = (unsigned char*)pImg->data; // dest left limit
1276 p20 += (nY1 - nYmin) * pImg->bytes_per_line;
1277 unsigned char* p21 = p20 + (nX1 - nXmin + pImg->xoffset) * bpp;
1278 int y = pRawBitmap->mnHeight;
1279 if( y > nYmax - nY1 )
1280 y = nYmax - nY1 + 1;
1281 while( --y >= 0 )
1283 if( p20 >= (unsigned char*)pImg->data )
1285 unsigned char* const p22 = p20 + pImg->width * bpp; // dest right limit
1286 unsigned char* pDst = p21;
1287 const unsigned char* pSrc = p10;
1288 for( int x = pRawBitmap->mnWidth; (--x >= 0) && (p22 > pDst); ++pSrc )
1290 if( (*pSrc == 0) || (p20 > pDst) ) // keep background
1291 pDst += bpp;
1292 else if( *pSrc == 0xFF ) // paint foreground
1294 const unsigned char* pColor = aColor;
1295 for( int z = bpp; --z >= 0; ++pColor, ++pDst )
1296 *pDst = *pColor;
1298 else // blend fg into bg
1300 const unsigned char* pColor = aColor;
1301 for( int z = bpp; --z >= 0; ++pColor, ++pDst )
1302 // theoretically it should be *257) >> 16
1303 // but the error is <0.4% worst case and we are in
1304 // the innermost loop of very perf-sensitive code
1306 *pDst += (*pSrc * ((int)*pColor - *pDst)) >> 8;
1310 p10 += pRawBitmap->mnScanlineSize;
1311 p20 += pImg->bytes_per_line;
1312 p21 += pImg->bytes_per_line;
1317 // put XImage
1318 XPutImage( pDisplay, hDrawable_, nGC, pImg,
1319 0, 0, nXmin, nYmin, (nXmax - nXmin + 1), (nYmax - nYmin + 1) );
1320 XDestroyImage( pImg );
1322 GetDisplay()->GetXLib()->PopXErrorLevel();
1323 return true;
1326 //--------------------------------------------------------------------------
1328 void X11SalGraphics::DrawServerSimpleFontString( const ServerFontLayout& rSalLayout )
1330 ServerFont& rFont = rSalLayout.GetServerFont();
1331 X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
1333 Display* pDisplay = GetXDisplay();
1334 GC nGC = SelectFont();
1336 XGCValues aGCVal;
1337 aGCVal.fill_style = FillStippled;
1338 aGCVal.line_width = 0;
1339 GC tmpGC = XCreateGC( pDisplay, hDrawable_, GCFillStyle|GCLineWidth, &aGCVal );
1340 XCopyGC( pDisplay, nGC, (1<<GCLastBit)-(1+GCFillStyle+GCLineWidth), tmpGC );
1342 Point aPos;
1343 sal_GlyphId nGlyph;
1344 for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); )
1346 // #i51924# avoid 32->16bit coordinate truncation problem in X11
1347 // TODO: reevaluate once displays with >30000 pixels are available
1348 if( aPos.X() >= 30000 || aPos.Y() >= 30000 )
1349 continue;
1351 Pixmap aStipple = rGlyphPeer.GetPixmap( rFont, nGlyph, m_nScreen );
1352 const GlyphMetric& rGM = rFont.GetGlyphMetric( nGlyph );
1354 if( aStipple != None )
1356 const int nDestX = aPos.X() + rGM.GetOffset().X();
1357 const int nDestY = aPos.Y() + rGM.GetOffset().Y();
1359 aGCVal.stipple = aStipple;
1360 aGCVal.ts_x_origin = nDestX;
1361 aGCVal.ts_y_origin = nDestY;
1362 XChangeGC( pDisplay, tmpGC, GCStipple|GCTileStipXOrigin|GCTileStipYOrigin, &aGCVal );
1364 const int nWidth = rGM.GetSize().Width();
1365 const int nHeight = rGM.GetSize().Height();
1366 XFillRectangle( pDisplay, hDrawable_, tmpGC, nDestX, nDestY, nWidth, nHeight );
1370 XFreeGC( pDisplay, tmpGC );
1373 //--------------------------------------------------------------------------
1375 void X11SalGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
1377 // draw complex text
1378 ServerFont& rFont = rLayout.GetServerFont();
1379 const bool bVertical = rFont.GetFontSelData().mbVertical;
1381 if( !bVertical && CairoWrapper::get().isCairoRenderable(rFont) )
1382 DrawCairoAAFontString( rLayout );
1383 else
1385 X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
1386 if( rGlyphPeer.GetGlyphSet( rFont, m_nScreen ) )
1387 DrawServerAAFontString( rLayout );
1388 else if( !rGlyphPeer.ForcedAntialiasing( rFont, m_nScreen ) )
1389 DrawServerSimpleFontString( rLayout );
1390 else
1391 DrawServerAAForcedString( rLayout );
1395 //--------------------------------------------------------------------------
1397 void X11SalGraphics::DrawStringUCS2MB( ExtendedFontStruct& rFont,
1398 const Point& rPoint, const sal_Unicode* pStr, int nLength )
1400 Display* pDisplay = GetXDisplay();
1401 GC nGC = SelectFont();
1403 if( rFont.GetAsciiEncoding() == RTL_TEXTENCODING_UNICODE )
1405 // plain Unicode, can handle all chars and can be handled straight forward
1406 XFontStruct* pFontStruct = rFont.GetFontStruct( RTL_TEXTENCODING_UNICODE );
1407 if( !pFontStruct )
1408 return;
1410 XSetFont( pDisplay, nGC, pFontStruct->fid );
1412 #ifdef OSL_LITENDIAN
1413 sal_Unicode *pBuffer = (sal_Unicode*)alloca( nLength * sizeof(sal_Unicode) );
1414 for ( int i = 0; i < nLength; i++ )
1415 pBuffer[ i ] = SwapBytes(pStr[ i ]) ;
1416 #else
1417 sal_Unicode *pBuffer = const_cast<sal_Unicode*>(pStr);
1418 #endif
1420 XDrawString16( pDisplay, hDrawable_, nGC, rPoint.X(), rPoint.Y(), (XChar2b*)pBuffer, nLength );
1422 else
1424 XTextItem16 *pTextItem = (XTextItem16*)alloca( nLength * sizeof(XTextItem16) );
1425 XChar2b *pMBChar = (XChar2b*)pStr;
1426 int nItem = 0;
1428 DBG_ASSERT( nLength<=1, "#i49902# DrawStringUCS2MB with nLength>1 => problems with XOrg6.8.[0123]");
1430 for( int nChar = 0; nChar < nLength; ++nChar )
1432 rtl_TextEncoding nEnc;
1433 XFontStruct* pFontStruct = rFont.GetFontStruct( pStr[nChar], &nEnc );
1434 if( !pFontStruct )
1435 continue;
1437 pTextItem[ nItem ].chars = pMBChar + nChar;
1438 pTextItem[ nItem ].delta = 0;
1439 pTextItem[ nItem ].font = pFontStruct->fid;
1440 pTextItem[ nItem ].nchars = 1;
1442 ConvertTextItem16( &pTextItem[ nItem ], nEnc );
1443 ++nItem;
1446 XDrawText16( pDisplay, hDrawable_, nGC, rPoint.X(), rPoint.Y(), pTextItem, nItem );
1450 //--------------------------------------------------------------------------
1452 ImplFontCharMap* X11SalGraphics::GetImplFontCharMap() const
1454 // TODO: get ImplFontCharMap directly from fonts
1455 if( !mpServerFont[0] )
1456 #if 0 // RIP XLFD fonts
1457 if( mXFont[0] )
1458 // TODO?: nPairCount = mXFont[0]->GetFontCodeRanges( NULL );
1459 #endif
1460 return NULL;
1462 CmapResult aCmapResult;
1463 if( !mpServerFont[0]->GetFontCodeRanges( aCmapResult ) )
1464 return NULL;
1465 return new ImplFontCharMap( aCmapResult );
1468 // ----------------------------------------------------------------------------
1470 // SalGraphics
1472 // ----------------------------------------------------------------------------
1474 USHORT X11SalGraphics::SetFont( ImplFontSelectData *pEntry, int nFallbackLevel )
1476 USHORT nRetVal = 0;
1477 if( !setFont( pEntry, nFallbackLevel ) )
1478 nRetVal |= SAL_SETFONT_BADFONT;
1479 if( bPrinter_ || (mpServerFont[ nFallbackLevel ] != NULL) )
1480 nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY;
1481 return nRetVal;
1484 // ----------------------------------------------------------------------------
1486 void
1487 X11SalGraphics::SetTextColor( SalColor nSalColor )
1489 if( nTextColor_ != nSalColor )
1491 nTextColor_ = nSalColor;
1492 nTextPixel_ = GetPixel( nSalColor );
1493 bFontGC_ = FALSE;
1497 // ----------------------------------------------------------------------------
1499 bool X11SalGraphics::AddTempDevFont( ImplDevFontList* pFontList,
1500 const String& rFileURL, const String& rFontName )
1502 // inform PSP font manager
1503 rtl::OUString aUSystemPath;
1504 OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFileURL, aUSystemPath ) );
1505 rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
1506 OString aOFileName( OUStringToOString( aUSystemPath, aEncoding ) );
1507 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1508 int nFontId = rMgr.addFontFile( aOFileName, 0 );
1509 if( !nFontId )
1510 return false;
1512 // prepare font data
1513 psp::FastPrintFontInfo aInfo;
1514 rMgr.getFontFastInfo( nFontId, aInfo );
1515 aInfo.m_aFamilyName = rFontName;
1517 // inform glyph cache of new font
1518 ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo );
1519 aDFA.mnQuality += 5800;
1521 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
1522 if( nFaceNum < 0 )
1523 nFaceNum = 0;
1525 GlyphCache& rGC = X11GlyphCache::GetInstance();
1526 const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
1527 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
1529 // announce new font to device's font list
1530 rGC.AnnounceFonts( pFontList );
1531 return true;
1534 // ----------------------------------------------------------------------------
1536 void RegisterFontSubstitutors( ImplDevFontList* );
1538 void X11SalGraphics::GetDevFontList( ImplDevFontList *pList )
1540 // allow disabling of native X11 fonts
1541 static const char* pEnableX11FontStr = getenv( "SAL_ENABLE_NATIVE_XFONTS" );
1542 if( pEnableX11FontStr && (pEnableX11FontStr[0] != '0') )
1544 // announce X11 fonts
1545 XlfdStorage* pX11FontList = GetDisplay()->GetXlfdList();
1546 pX11FontList->AnnounceFonts( pList );
1549 // prepare the GlyphCache using psprint's font infos
1550 X11GlyphCache& rGC = X11GlyphCache::GetInstance();
1552 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1553 ::std::list< psp::fontID > aList;
1554 ::std::list< psp::fontID >::iterator it;
1555 psp::FastPrintFontInfo aInfo;
1556 rMgr.getFontList( aList );
1557 for( it = aList.begin(); it != aList.end(); ++it )
1559 if( !rMgr.getFontFastInfo( *it, aInfo ) )
1560 continue;
1562 // the GlyphCache must not bother with builtin fonts because
1563 // it cannot access or use them anyway
1564 if( aInfo.m_eType == psp::fonttype::Builtin )
1565 continue;
1567 // normalize face number to the GlyphCache
1568 int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
1569 if( nFaceNum < 0 )
1570 nFaceNum = 0;
1572 // for fonts where extra kerning info can be provided on demand
1573 // an ExtraKernInfo object is supplied
1574 const ExtraKernInfo* pExtraKernInfo = NULL;
1575 if( aInfo.m_eType == psp::fonttype::Type1 )
1576 pExtraKernInfo = new PspKernInfo( *it );
1578 // inform GlyphCache about this font provided by the PsPrint subsystem
1579 ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo );
1580 aDFA.mnQuality += 4096;
1581 const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
1582 rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo );
1585 // announce glyphcache fonts
1586 rGC.AnnounceFonts( pList );
1588 // register platform specific font substitutions if available
1589 if( rMgr.hasFontconfig() )
1590 RegisterFontSubstitutors( pList );
1592 ImplGetSVData()->maGDIData.mbNativeFontConfig = rMgr.hasFontconfig();
1595 // ----------------------------------------------------------------------------
1597 void X11SalGraphics::GetDevFontSubstList( OutputDevice* )
1599 // no device specific font substitutions on X11 needed
1602 // ----------------------------------------------------------------------------
1604 void
1605 X11SalGraphics::GetFontMetric( ImplFontMetricData *pMetric )
1607 if( mpServerFont[0] != NULL )
1609 long rDummyFactor;
1610 mpServerFont[0]->FetchFontMetric( *pMetric, rDummyFactor );
1612 else if( mXFont[0] != NULL )
1614 mXFont[0]->ToImplFontMetricData( pMetric );
1615 if ( bFontVertical_ )
1616 pMetric->mnOrientation = 0;
1620 // ---------------------------------------------------------------------------
1622 ULONG
1623 X11SalGraphics::GetKernPairs( ULONG nPairs, ImplKernPairData *pKernPairs )
1625 if( ! bPrinter_ )
1627 if( mpServerFont[0] != NULL )
1629 ImplKernPairData* pTmpKernPairs;
1630 ULONG nGotPairs = mpServerFont[0]->GetKernPairs( &pTmpKernPairs );
1631 for( unsigned int i = 0; i < nPairs && i < nGotPairs; ++i )
1632 pKernPairs[ i ] = pTmpKernPairs[ i ];
1633 delete[] pTmpKernPairs;
1634 return nGotPairs;
1637 return 0;
1640 // ---------------------------------------------------------------------------
1642 BOOL X11SalGraphics::GetGlyphBoundRect( long nGlyphIndex, Rectangle& rRect )
1644 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
1645 if( nLevel >= MAX_FALLBACK )
1646 return FALSE;
1648 ServerFont* pSF = mpServerFont[ nLevel ];
1649 if( !pSF )
1650 return FALSE;
1652 nGlyphIndex &= ~GF_FONTMASK;
1653 const GlyphMetric& rGM = pSF->GetGlyphMetric( nGlyphIndex );
1654 rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
1655 return TRUE;
1658 // ---------------------------------------------------------------------------
1660 BOOL X11SalGraphics::GetGlyphOutline( long nGlyphIndex,
1661 ::basegfx::B2DPolyPolygon& rPolyPoly )
1663 int nLevel = nGlyphIndex >> GF_FONTSHIFT;
1664 if( nLevel >= MAX_FALLBACK )
1665 return FALSE;
1667 ServerFont* pSF = mpServerFont[ nLevel ];
1668 if( !pSF )
1669 return FALSE;
1671 nGlyphIndex &= ~GF_FONTMASK;
1672 if( pSF->GetGlyphOutline( nGlyphIndex, rPolyPoly ) )
1673 return TRUE;
1675 return FALSE;
1678 //--------------------------------------------------------------------------
1680 SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
1682 SalLayout* pLayout = NULL;
1684 if( mpServerFont[ nFallbackLevel ]
1685 && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
1687 #ifdef ENABLE_GRAPHITE
1688 // Is this a Graphite font?
1689 if (!bDisableGraphite_ &&
1690 GraphiteFontAdaptor::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
1692 sal_Int32 xdpi, ydpi;
1694 xdpi = GetDisplay()->GetResolution().A();
1695 ydpi = GetDisplay()->GetResolution().B();
1697 GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *mpServerFont[nFallbackLevel], xdpi, ydpi);
1698 if (!pGrfont) return NULL;
1699 pLayout = new GraphiteServerFontLayout(pGrfont);
1701 else
1702 #endif
1703 pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
1705 else if( mXFont[ nFallbackLevel ] )
1706 pLayout = new X11FontLayout( *mXFont[ nFallbackLevel ] );
1707 else
1708 pLayout = NULL;
1710 return pLayout;
1713 //--------------------------------------------------------------------------
1715 SystemFontData X11SalGraphics::GetSysFontData( int nFallbacklevel ) const
1717 SystemFontData aSysFontData;
1718 aSysFontData.nSize = sizeof( SystemFontData );
1719 aSysFontData.nFontId = 0;
1721 if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
1722 if (nFallbacklevel < 0 ) nFallbacklevel = 0;
1724 if (mpServerFont[nFallbacklevel] != NULL)
1726 ServerFont* rFont = mpServerFont[nFallbacklevel];
1727 aSysFontData.nFontId = rFont->GetFtFace();
1728 aSysFontData.nFontFlags = rFont->GetLoadFlags();
1729 aSysFontData.bFakeBold = rFont->NeedsArtificialBold();
1730 aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic();
1731 aSysFontData.bAntialias = rFont->GetAntialiasAdvice();
1732 aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical;
1735 return aSysFontData;
1738 //--------------------------------------------------------------------------
1740 BOOL X11SalGraphics::CreateFontSubset(
1741 const rtl::OUString& rToFile,
1742 const ImplFontData* pFont,
1743 sal_Int32* pGlyphIDs,
1744 sal_uInt8* pEncoding,
1745 sal_Int32* pWidths,
1746 int nGlyphCount,
1747 FontSubsetInfo& rInfo
1750 // in this context the pFont->GetFontId() is a valid PSP
1751 // font since they are the only ones left after the PDF
1752 // export has filtered its list of subsettable fonts (for
1753 // which this method was created). The correct way would
1754 // be to have the GlyphCache search for the ImplFontData pFont
1755 psp::fontID aFont = pFont->GetFontId();
1757 psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1758 bool bSuccess = rMgr.createFontSubset( rInfo,
1759 aFont,
1760 rToFile,
1761 pGlyphIDs,
1762 pEncoding,
1763 pWidths,
1764 nGlyphCount );
1765 return bSuccess;
1768 //--------------------------------------------------------------------------
1770 const void* X11SalGraphics::GetEmbedFontData( const ImplFontData* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
1772 #ifndef _USE_PRINT_EXTENSION_
1773 // in this context the pFont->GetFontId() is a valid PSP
1774 // font since they are the only ones left after the PDF
1775 // export has filtered its list of subsettable fonts (for
1776 // which this method was created). The correct way would
1777 // be to have the GlyphCache search for the ImplFontData pFont
1778 psp::fontID aFont = pFont->GetFontId();
1779 return PspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
1780 #else
1781 return NULL;
1782 #endif
1785 //--------------------------------------------------------------------------
1787 void X11SalGraphics::FreeEmbedFontData( const void* pData, long nLen )
1789 #ifndef _USE_PRINT_EXTENSION_
1790 PspGraphics::DoFreeEmbedFontData( pData, nLen );
1791 #endif
1794 //--------------------------------------------------------------------------
1796 const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded )
1798 #ifndef _USE_PRINT_EXTENSION_
1799 // in this context the pFont->GetFontId() is a valid PSP
1800 // font since they are the only ones left after the PDF
1801 // export has filtered its list of subsettable fonts (for
1802 // which this method was created). The correct way would
1803 // be to have the GlyphCache search for the ImplFontData pFont
1804 psp::fontID aFont = pFont->GetFontId();
1805 return PspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
1806 #else
1807 return NULL;
1808 #endif
1811 //--------------------------------------------------------------------------
1813 void X11SalGraphics::GetGlyphWidths( const ImplFontData* pFont,
1814 bool bVertical,
1815 Int32Vector& rWidths,
1816 Ucs2UIntMap& rUnicodeEnc )
1818 // in this context the pFont->GetFontId() is a valid PSP
1819 // font since they are the only ones left after the PDF
1820 // export has filtered its list of subsettable fonts (for
1821 // which this method was created). The correct way would
1822 // be to have the GlyphCache search for the ImplFontData pFont
1823 psp::fontID aFont = pFont->GetFontId();
1824 PspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
1827 // ===========================================================================
1828 // platform specific font substitution hooks
1830 class FcPreMatchSubstititution
1831 : public ImplPreMatchFontSubstitution
1833 public:
1834 bool FindFontSubstitute( ImplFontSelectData& ) const;
1836 private:
1837 typedef ::std::hash_map< ::rtl::OUString, ::rtl::OUString, ::rtl::OUStringHash >
1838 CachedFontMapType;
1839 mutable CachedFontMapType maCachedFontMap;
1842 class FcGlyphFallbackSubstititution
1843 : public ImplGlyphFallbackFontSubstitution
1845 // TODO: add a cache
1846 public:
1847 bool FindFontSubstitute( ImplFontSelectData&, OUString& rMissingCodes ) const;
1850 void RegisterFontSubstitutors( ImplDevFontList* pList )
1852 // init font substitution defaults
1853 int nDisableBits = 0;
1854 #ifdef SOLARIS
1855 nDisableBits = 1; // disable "font fallback" here on default
1856 #endif
1857 // apply the environment variable if any
1858 const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
1859 if( pEnvStr )
1861 if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
1862 nDisableBits = (*pEnvStr - '0');
1863 else
1864 nDisableBits = ~0U; // no specific bits set: disable all
1867 // register font fallback substitutions (unless disabled by bit0)
1868 if( (nDisableBits & 1) == 0 )
1870 static FcPreMatchSubstititution aSubstPreMatch;
1871 pList->SetPreMatchHook( &aSubstPreMatch );
1874 // register glyph fallback substitutions (unless disabled by bit1)
1875 if( (nDisableBits & 2) == 0 )
1877 static FcGlyphFallbackSubstititution aSubstFallback;
1878 pList->SetFallbackHook( &aSubstFallback );
1882 // -----------------------------------------------------------------------
1884 static rtl::OUString GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUString& rMissingCodes )
1886 const rtl::OString aLangAttrib; //TODO: = MsLangId::convertLanguageToIsoByteString( rFontSelData.meLanguage );
1888 psp::italic::type eItalic = psp::italic::Unknown;
1889 if( rFontSelData.GetSlant() != ITALIC_DONTKNOW )
1891 switch( rFontSelData.GetSlant() )
1893 case ITALIC_NONE: eItalic = psp::italic::Upright; break;
1894 case ITALIC_NORMAL: eItalic = psp::italic::Italic; break;
1895 case ITALIC_OBLIQUE: eItalic = psp::italic::Oblique; break;
1896 default:
1897 break;
1901 psp::weight::type eWeight = psp::weight::Unknown;
1902 if( rFontSelData.GetWeight() != WEIGHT_DONTKNOW )
1904 switch( rFontSelData.GetWeight() )
1906 case WEIGHT_THIN: eWeight = psp::weight::Thin; break;
1907 case WEIGHT_ULTRALIGHT: eWeight = psp::weight::UltraLight; break;
1908 case WEIGHT_LIGHT: eWeight = psp::weight::Light; break;
1909 case WEIGHT_SEMILIGHT: eWeight = psp::weight::SemiLight; break;
1910 case WEIGHT_NORMAL: eWeight = psp::weight::Normal; break;
1911 case WEIGHT_MEDIUM: eWeight = psp::weight::Medium; break;
1912 case WEIGHT_SEMIBOLD: eWeight = psp::weight::SemiBold; break;
1913 case WEIGHT_BOLD: eWeight = psp::weight::Bold; break;
1914 case WEIGHT_ULTRABOLD: eWeight = psp::weight::UltraBold; break;
1915 case WEIGHT_BLACK: eWeight = psp::weight::Black; break;
1916 default:
1917 break;
1921 psp::width::type eWidth = psp::width::Unknown;
1922 if( rFontSelData.GetWidthType() != WIDTH_DONTKNOW )
1924 switch( rFontSelData.GetWidthType() )
1926 case WIDTH_ULTRA_CONDENSED: eWidth = psp::width::UltraCondensed; break;
1927 case WIDTH_EXTRA_CONDENSED: eWidth = psp::width::ExtraCondensed; break;
1928 case WIDTH_CONDENSED: eWidth = psp::width::Condensed; break;
1929 case WIDTH_SEMI_CONDENSED: eWidth = psp::width::SemiCondensed; break;
1930 case WIDTH_NORMAL: eWidth = psp::width::Normal; break;
1931 case WIDTH_SEMI_EXPANDED: eWidth = psp::width::SemiExpanded; break;
1932 case WIDTH_EXPANDED: eWidth = psp::width::Expanded; break;
1933 case WIDTH_EXTRA_EXPANDED: eWidth = psp::width::ExtraExpanded; break;
1934 case WIDTH_ULTRA_EXPANDED: eWidth = psp::width::UltraExpanded; break;
1935 default:
1936 break;
1940 psp::pitch::type ePitch = psp::pitch::Unknown;
1941 if( rFontSelData.GetPitch() != PITCH_DONTKNOW )
1943 switch( rFontSelData.GetPitch() )
1945 case PITCH_FIXED: ePitch=psp::pitch::Fixed; break;
1946 case PITCH_VARIABLE: ePitch=psp::pitch::Variable; break;
1947 default:
1948 break;
1952 const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1953 return rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch);
1956 //--------------------------------------------------------------------------
1958 bool FcPreMatchSubstititution::FindFontSubstitute( ImplFontSelectData &rFontSelData ) const
1960 // We dont' actually want to talk to Fontconfig at all for symbol fonts
1961 if (rFontSelData.IsSymbolFont())
1962 return false;
1963 // StarSymbol is a unicode font, but it still deserves the symbol flag
1964 if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
1965 || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
1966 return false;
1968 CachedFontMapType::const_iterator itr = maCachedFontMap.find(rFontSelData.maTargetName);
1969 if (itr != maCachedFontMap.end())
1971 // Cached substitution pair
1972 rFontSelData.maSearchName = itr->second;
1973 return true;
1975 rtl::OUString aDummy;
1976 const rtl::OUString aOUName = GetFcSubstitute( rFontSelData, aDummy );
1978 maCachedFontMap.insert(
1979 CachedFontMapType::value_type(rFontSelData.maTargetName, aOUName));
1981 if( !aOUName.getLength() )
1982 return false;
1983 const String aName( aOUName );
1984 if( aName == rFontSelData.maTargetName )
1985 return false;
1987 #ifdef DEBUG
1988 ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
1989 ByteString aSubstName( aName, RTL_TEXTENCODING_UTF8 );
1990 printf( "FcPreMatchSubstititution \"%s\" -> \"%s\"\n",
1991 aOrigName.GetBuffer(), aSubstName.GetBuffer() );
1992 #endif
1993 rFontSelData.maSearchName = aName;
1994 return true;
1997 // -----------------------------------------------------------------------
1999 bool FcGlyphFallbackSubstititution::FindFontSubstitute( ImplFontSelectData& rFontSelData,
2000 rtl::OUString& rMissingCodes ) const
2002 // We dont' actually want to talk to Fontconfig at all for symbol fonts
2003 if( rFontSelData.IsSymbolFont() )
2004 return false;
2005 // StarSymbol is a unicode font, but it still deserves the symbol flag
2006 if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
2007 || 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
2008 return false;
2010 const rtl::OUString aOUName = GetFcSubstitute( rFontSelData, rMissingCodes );
2011 // TODO: cache the unicode+font specific result
2012 if( !aOUName.getLength() )
2013 return false;
2014 const String aName( aOUName );
2015 if( aName == rFontSelData.maTargetName )
2016 return false;
2018 #ifdef DEBUG
2019 ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
2020 ByteString aSubstName( aName, RTL_TEXTENCODING_UTF8 );
2021 printf( "FcGlyphFallbackSubstititution \"%s\" -> \"%s\"\n",
2022 aOrigName.GetBuffer(), aSubstName.GetBuffer() );
2023 #endif
2024 rFontSelData.maSearchName = aName;
2025 return true;
2028 // ===========================================================================