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 * 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"
39 #include <sys/types.h>
41 #include "gcach_xpeer.hxx"
42 #include "xrender_peer.hxx"
44 #include "saldata.hxx"
45 #include "saldisp.hxx"
47 #include "pspgraphics.h"
50 #include <vcl/sysdata.hxx>
51 #include "xlfd_attr.hxx"
52 #include "xlfd_smpl.hxx"
53 #include "xlfd_extd.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"
82 #ifdef ENABLE_GRAPHITE
83 #include <vcl/graphite_layout.hxx>
84 #include <vcl/graphite_serverfont.hxx>
87 struct cairo_surface_t
;
89 struct cairo_font_face_t
;
90 typedef void* FT_Face
;
91 struct cairo_matrix_t
{
104 short x1
, x2
, y1
, y2
;
115 // -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
117 // ----------------------------------------------------------------------------
119 // manage X11 fonts and self rastered fonts
121 // ----------------------------------------------------------------------------
123 #ifndef _USE_PRINT_EXTENSION_
131 typedef ::std::hash_set
< FontLookup
,
133 FontLookup::equal
> fl_hashset
;
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
)
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
;
178 return maName
.hashCode ();
183 bool operator()(const FontLookup
&r1
, const FontLookup
&r2
) const
190 size_t operator()(const FontLookup
&rArg
) const
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);
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
;
227 mnItalic
= ITALIC_DONTKNOW
;
228 mnWeight
= WEIGHT_DONTKNOW
;
233 FontLookup::FontLookup (const Xlfd
& rFont
)
235 AttributeProvider
* pFactory
= rFont
.mpFactory
;
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
;
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
);
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;
275 FontLookup::InSet (const FontLookup::fl_hashset
& rSet
, const Xlfd
& rXlfd
)
277 FontLookup
aNeedle (rXlfd
);
278 return aNeedle
.InSet (rSet
);
283 // ----------------------------------------------------------------------------
287 // ----------------------------------------------------------------------------
290 SalDisplay::GetXlfdList() const
292 if ( mpFontList
!= NULL
)
298 const_cast<SalDisplay
*>(this)->mpFactory
= new AttributeProvider
;
299 const_cast<SalDisplay
*>(this)->mpFontList
= new XlfdStorage
;
300 const_cast<SalDisplay
*>(this)->mpFallbackFactory
= new VirtualXlfd
;
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
) );
314 for ( i
= 0; i
< nFontCount
; i
++ )
316 if ( pXlfdList
[ nXlfdCount
].FromString(ppFontList
[i
], mpFactory
) )
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
);
338 // create a font list with merged encoding information
341 BitmapXlfdStorage aBitmapList
;
342 ScalableXlfd
*pScalableFont
= NULL
;
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
) )
352 // exclude fonts with unknown encoding
353 if ( pXlfdList
[i
].GetEncoding() == RTL_TEXTENCODING_DONTKNOW
)
355 // exclude "interface system" and "interface user"
356 if (pAttr
->HasFeature( XLFD_FEATURE_APPLICATION_FONT
) )
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
]))
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
372 mpFontList
->Add( pScalableFont
);
373 mpFontList
->Add( &aBitmapList
);
374 pScalableFont
= NULL
;
378 // merge the font or generate a new one
382 if ( pScalableFont
== NULL
)
383 pScalableFont
= new ScalableXlfd
;
384 pScalableFont
->AddEncoding(pXlfdList
+ i
);
388 aBitmapList
.AddBitmapFont( pXlfdList
+ i
);
391 case eTypeScalableBitmap
:
392 // ignore scaled X11 bitmap fonts because they look too ugly
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
)
413 // ---------------------------------------------------------------------------
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
422 m_pFontCache
= new SalFontCache( 64, 64, 16 ); // ???
426 ExtendedFontStruct
*pItem
;
427 for ( pItem
= m_pFontCache
->First();
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 );
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();
449 pItem
= m_pFontCache
->Prev() )
451 if( 1 == pItem
->GetRefCount() )
453 m_pFontCache
->Remove( pItem
);
455 if( m_pFontCache
->Count() < 64 )
461 ExtendedFontStruct
*pItem
= new ExtendedFontStruct( GetDisplay(),
462 rPixelSize
, bVertical
,
463 const_cast<ExtendedXlfd
*>(pRequestedFont
) );
464 m_pFontCache
->Insert( pItem
, 0UL );
470 // ---------------------------------------------------------------------------
473 SalDisplay::DestroyFontCache()
477 ExtendedFontStruct
*pItem
= m_pFontCache
->First();
481 pItem
= m_pFontCache
->Next();
487 mpFontList
->Dispose();
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
506 PspKernInfo( int nFontId
) : ExtraKernInfo(nFontId
) {}
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() )
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 // ----------------------------------------------------------------------------
538 // ----------------------------------------------------------------------------
541 X11SalGraphics::SelectFont()
543 Display
*pDisplay
= GetXDisplay();
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
,
559 pFontGC_
= XCreateGC( pDisplay
, hDrawable_
,
560 GCSubwindowMode
| GCFillRule
561 | GCGraphicsExposures
| GCForeground
,
567 XSetForeground( pDisplay
, pFontGC_
, nTextPixel_
);
568 SetClipRegion( pFontGC_
);
575 //--------------------------------------------------------------------------
577 bool X11SalGraphics::setFont( const ImplFontSelectData
*pEntry
, int nFallbackLevel
)
580 ByteString
aReqName( "NULL" );
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() );
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
611 bFontVertical_
= pEntry
->mbVertical
;
613 // return early if this is not a valid font for this graphics
614 if( !pEntry
->mpFontData
)
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_
);
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
);
638 mpServerFont
[ nFallbackLevel
] = pServerFont
;
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
654 ConvertTextItem16( XTextItem16
* pTextItem
, rtl_TextEncoding nEncoding
)
656 if ( (pTextItem
== NULL
) || (pTextItem
->nchars
<= 0) )
659 SalConverterCache
* pCvt
= SalConverterCache::GetInstance();
660 // convert the string into the font encoding
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 ]
681 if ( (unsigned char)pBuffer
[ n
] < 0x80 )
683 pTextChars
[ m
++ ] = 0x0;
684 pTextChars
[ m
++ ] = pBuffer
[ n
++ ];
688 pTextChars
[ m
++ ] = pBuffer
[ n
++ ];
689 pTextChars
[ m
++ ] = pBuffer
[ n
++ ];
692 pTextItem
->nchars
= m
/ 2;
695 if ( pCvt
->IsSingleByteEncoding(nEncoding
) )
697 // Single Byte encoding has to be padded
700 pTextChars
[ m
++ ] = 0x0;
701 pTextChars
[ m
++ ] = pBuffer
[ n
++ ];
703 pTextItem
->nchars
= nSize
;
709 pTextChars
[ m
++ ] = pBuffer
[ n
++ ];
711 pTextItem
->nchars
= nSize
/ 2;
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 //--------------------------------------------------------------------------
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; }
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()
795 static const char* pDisableCairoText
= getenv( "SAL_DISABLE_CAIROTEXT" );
796 if( pDisableCairoText
&& (pDisableCairoText
[0] != '0') )
800 if( !XQueryExtension( GetX11SalData()->GetDisplay()->GetDisplay(), "RENDER", &nDummy
, &nDummy
, &nDummy
) )
804 OUString
aLibName( RTL_CONSTASCII_USTRINGPARAM( "libcairo.2.dylib" ));
806 OUString
aLibName( RTL_CONSTASCII_USTRINGPARAM( "libcairo.so.2" ));
808 mpCairoLib
= osl_loadModule( aLibName
.pData
, SAL_LOADMODULE_DEFAULT
);
813 // check cairo 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
);
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" );
852 mp_xlib_surface_create_with_xrender_format
&&
853 mp_surface_destroy
&&
858 mp_ft_font_face_create_for_ft_face
&&
860 mp_font_face_destroy
&&
861 mp_matrix_init_identity
&&
864 mp_set_font_matrix
&&
869 osl_unloadModule( mpCairoLib
);
871 #if OSL_DEBUG_LEVEL > 1
872 fprintf( stderr
, "not all needed symbols were found\n" );
877 bool CairoWrapper::isCairoRenderable(const ServerFont
& rFont
)
879 return rFont
.GetFtFace() && isValid() && rFont
.GetAntialiasAdvice() &&
880 (rFont
.NeedsArtificialBold() ? canEmbolden() : true);
885 CairoFontsCache::LRUFonts
CairoFontsCache::maLRUFonts
;
886 int CairoFontsCache::mnRefCount
= 0;
888 CairoFontsCache::CairoFontsCache()
893 CairoFontsCache::~CairoFontsCache()
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
)
925 void X11SalGraphics::DrawCairoAAFontString( const ServerFontLayout
& rLayout
)
927 std::vector
<cairo_glyph_t
> cairo_glyphs
;
928 cairo_glyphs
.reserve( 256 );
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
;
938 cairo_glyphs
.push_back(aGlyph
);
941 if (cairo_glyphs
.empty())
944 // find a XRenderPictFormat compatible with the Drawable
945 XRenderPictFormat
* pVisualFormat
= static_cast<XRenderPictFormat
*>(GetXRenderFormat());
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" );
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
)
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
);
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
);
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
);
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());
1024 //--------------------------------------------------------------------------
1026 void X11SalGraphics::DrawServerAAFontString( const ServerFontLayout
& rLayout
)
1028 // get xrender target for this drawable
1029 Picture aDstPic
= GetXRenderPicture();
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();
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" );
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 );
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
);
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
);
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 )
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();
1112 for( bool bFirst
=true; rLayout
.GetNextGlyphs( 1, &nGlyph
, aPos
, nStart
); )
1114 const RawBitmap
* const pRawBitmap
= rGlyphPeer
.GetRawBitmap( rFont
, nGlyph
);
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
;
1133 if( nXmin
> nX1
) nXmin
= nX1
;
1134 if( nXmax
< nX2
) nXmax
= nX2
;
1135 if( nYmin
> nY1
) nYmin
= nY1
;
1136 if( nYmax
< nY2
) nYmax
= nY2
;
1141 GetDisplay()->GetXLib()->PushXErrorLevel( true );
1142 Display
* pDisplay
= GetXDisplay();
1145 long nWidth
= 1, nHeight
= 1;
1147 nWidth
= m_pFrame
->maGeometry
.nWidth
, nHeight
= m_pFrame
->maGeometry
.nHeight
;
1149 nWidth
= m_pVDev
->GetWidth(), nHeight
= m_pVDev
->GetHeight();
1151 if( pClipRegion_
&& !XEmptyRegion( pClipRegion_
) )
1154 XClipBox( pClipRegion_
, &aXRect
);
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
;
1166 aXRect
.width
= nWidth
;
1167 aXRect
.height
= nHeight
;
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();
1178 aXRect
.x
-= nScreenX
, aXRect
.width
+= nScreenX
;
1179 if( nScreenX
+aXRect
.width
> nScreenW
)
1180 aXRect
.width
= nScreenW
-nScreenX
;
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;
1198 XImage
* pImg
= XGetImage( pDisplay
, hDrawable_
,
1200 (nXmax
-nXmin
+1), (nYmax
-nYmin
+1),
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
;
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
1220 if( nYmin
+ y
< 0 ) // clip on top screen edge
1222 if( nXmax
>= int(w
) ) // clip on right window egde
1224 if( nYmax
>= int(h
) ) // clip on bottom window edge
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_
,
1235 (nXmax
-nXmin
+1), (nYmax
-nYmin
+1),
1241 GetDisplay()->GetXLib()->PopXErrorLevel();
1247 GC nGC
= SelectFont();
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
);
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
);
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;
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
1292 else if( *pSrc
== 0xFF ) // paint foreground
1294 const unsigned char* pColor
= aColor
;
1295 for( int z
= bpp
; --z
>= 0; ++pColor
, ++pDst
)
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
;
1318 XPutImage( pDisplay
, hDrawable_
, nGC
, pImg
,
1319 0, 0, nXmin
, nYmin
, (nXmax
- nXmin
+ 1), (nYmax
- nYmin
+ 1) );
1320 XDestroyImage( pImg
);
1322 GetDisplay()->GetXLib()->PopXErrorLevel();
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();
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
);
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 )
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
);
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
);
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
);
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
]) ;
1417 sal_Unicode
*pBuffer
= const_cast<sal_Unicode
*>(pStr
);
1420 XDrawString16( pDisplay
, hDrawable_
, nGC
, rPoint
.X(), rPoint
.Y(), (XChar2b
*)pBuffer
, nLength
);
1424 XTextItem16
*pTextItem
= (XTextItem16
*)alloca( nLength
* sizeof(XTextItem16
) );
1425 XChar2b
*pMBChar
= (XChar2b
*)pStr
;
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
);
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
);
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
1458 // TODO?: nPairCount = mXFont[0]->GetFontCodeRanges( NULL );
1462 CmapResult aCmapResult
;
1463 if( !mpServerFont
[0]->GetFontCodeRanges( aCmapResult
) )
1465 return new ImplFontCharMap( aCmapResult
);
1468 // ----------------------------------------------------------------------------
1472 // ----------------------------------------------------------------------------
1474 USHORT
X11SalGraphics::SetFont( ImplFontSelectData
*pEntry
, int nFallbackLevel
)
1477 if( !setFont( pEntry
, nFallbackLevel
) )
1478 nRetVal
|= SAL_SETFONT_BADFONT
;
1479 if( bPrinter_
|| (mpServerFont
[ nFallbackLevel
] != NULL
) )
1480 nRetVal
|= SAL_SETFONT_USEDRAWTEXTARRAY
;
1484 // ----------------------------------------------------------------------------
1487 X11SalGraphics::SetTextColor( SalColor nSalColor
)
1489 if( nTextColor_
!= nSalColor
)
1491 nTextColor_
= nSalColor
;
1492 nTextPixel_
= GetPixel( nSalColor
);
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 );
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
);
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
);
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
) )
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
)
1567 // normalize face number to the GlyphCache
1568 int nFaceNum
= rMgr
.getFontFaceNumber( aInfo
.m_nID
);
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 // ----------------------------------------------------------------------------
1605 X11SalGraphics::GetFontMetric( ImplFontMetricData
*pMetric
)
1607 if( mpServerFont
[0] != NULL
)
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 // ---------------------------------------------------------------------------
1623 X11SalGraphics::GetKernPairs( ULONG nPairs
, ImplKernPairData
*pKernPairs
)
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
;
1640 // ---------------------------------------------------------------------------
1642 BOOL
X11SalGraphics::GetGlyphBoundRect( long nGlyphIndex
, Rectangle
& rRect
)
1644 int nLevel
= nGlyphIndex
>> GF_FONTSHIFT
;
1645 if( nLevel
>= MAX_FALLBACK
)
1648 ServerFont
* pSF
= mpServerFont
[ nLevel
];
1652 nGlyphIndex
&= ~GF_FONTMASK
;
1653 const GlyphMetric
& rGM
= pSF
->GetGlyphMetric( nGlyphIndex
);
1654 rRect
= Rectangle( rGM
.GetOffset(), rGM
.GetSize() );
1658 // ---------------------------------------------------------------------------
1660 BOOL
X11SalGraphics::GetGlyphOutline( long nGlyphIndex
,
1661 ::basegfx::B2DPolyPolygon
& rPolyPoly
)
1663 int nLevel
= nGlyphIndex
>> GF_FONTSHIFT
;
1664 if( nLevel
>= MAX_FALLBACK
)
1667 ServerFont
* pSF
= mpServerFont
[ nLevel
];
1671 nGlyphIndex
&= ~GF_FONTMASK
;
1672 if( pSF
->GetGlyphOutline( nGlyphIndex
, rPolyPoly
) )
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
);
1703 pLayout
= new ServerFontLayout( *mpServerFont
[ nFallbackLevel
] );
1705 else if( mXFont
[ nFallbackLevel
] )
1706 pLayout
= new X11FontLayout( *mXFont
[ nFallbackLevel
] );
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
,
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
,
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
);
1785 //--------------------------------------------------------------------------
1787 void X11SalGraphics::FreeEmbedFontData( const void* pData
, long nLen
)
1789 #ifndef _USE_PRINT_EXTENSION_
1790 PspGraphics::DoFreeEmbedFontData( pData
, nLen
);
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
);
1811 //--------------------------------------------------------------------------
1813 void X11SalGraphics::GetGlyphWidths( const ImplFontData
* pFont
,
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
1834 bool FindFontSubstitute( ImplFontSelectData
& ) const;
1837 typedef ::std::hash_map
< ::rtl::OUString
, ::rtl::OUString
, ::rtl::OUStringHash
>
1839 mutable CachedFontMapType maCachedFontMap
;
1842 class FcGlyphFallbackSubstititution
1843 : public ImplGlyphFallbackFontSubstitution
1845 // TODO: add a cache
1847 bool FindFontSubstitute( ImplFontSelectData
&, OUString
& rMissingCodes
) const;
1850 void RegisterFontSubstitutors( ImplDevFontList
* pList
)
1852 // init font substitution defaults
1853 int nDisableBits
= 0;
1855 nDisableBits
= 1; // disable "font fallback" here on default
1857 // apply the environment variable if any
1858 const char* pEnvStr
= ::getenv( "SAL_DISABLE_FC_SUBST" );
1861 if( (*pEnvStr
>= '0') && (*pEnvStr
<= '9') )
1862 nDisableBits
= (*pEnvStr
- '0');
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;
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;
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;
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;
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())
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) )
1968 CachedFontMapType::const_iterator itr
= maCachedFontMap
.find(rFontSelData
.maTargetName
);
1969 if (itr
!= maCachedFontMap
.end())
1971 // Cached substitution pair
1972 rFontSelData
.maSearchName
= itr
->second
;
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() )
1983 const String
aName( aOUName
);
1984 if( aName
== rFontSelData
.maTargetName
)
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() );
1993 rFontSelData
.maSearchName
= aName
;
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() )
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) )
2010 const rtl::OUString aOUName
= GetFcSubstitute( rFontSelData
, rMissingCodes
);
2011 // TODO: cache the unicode+font specific result
2012 if( !aOUName
.getLength() )
2014 const String
aName( aOUName
);
2015 if( aName
== rFontSelData
.maTargetName
)
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() );
2024 rFontSelData
.maSearchName
= aName
;
2028 // ===========================================================================