xref: /AOO41X/main/vcl/unx/generic/gdi/salgdi3.cxx (revision 8a718ffc477520369c44fdc7c84d0e6da2dd87af)
1c82f2877SAndrew Rist /**************************************************************
2cdf0e10cSrcweir  *
3c82f2877SAndrew Rist  * Licensed to the Apache Software Foundation (ASF) under one
4c82f2877SAndrew Rist  * or more contributor license agreements.  See the NOTICE file
5c82f2877SAndrew Rist  * distributed with this work for additional information
6c82f2877SAndrew Rist  * regarding copyright ownership.  The ASF licenses this file
7c82f2877SAndrew Rist  * to you under the Apache License, Version 2.0 (the
8c82f2877SAndrew Rist  * "License"); you may not use this file except in compliance
9c82f2877SAndrew Rist  * with the License.  You may obtain a copy of the License at
10cdf0e10cSrcweir  *
11c82f2877SAndrew Rist  *   http://www.apache.org/licenses/LICENSE-2.0
12cdf0e10cSrcweir  *
13c82f2877SAndrew Rist  * Unless required by applicable law or agreed to in writing,
14c82f2877SAndrew Rist  * software distributed under the License is distributed on an
15c82f2877SAndrew Rist  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
16c82f2877SAndrew Rist  * KIND, either express or implied.  See the License for the
17c82f2877SAndrew Rist  * specific language governing permissions and limitations
18c82f2877SAndrew Rist  * under the License.
19cdf0e10cSrcweir  *
20c82f2877SAndrew Rist  *************************************************************/
21c82f2877SAndrew Rist 
22c82f2877SAndrew Rist 
23cdf0e10cSrcweir 
24cdf0e10cSrcweir // MARKER(update_precomp.py): autogen include statement, do not remove
25cdf0e10cSrcweir #include "precompiled_vcl.hxx"
26cdf0e10cSrcweir 
27cdf0e10cSrcweir #include <string.h>
28cdf0e10cSrcweir #include <stdio.h>
29cdf0e10cSrcweir #include <stdlib.h>
30cdf0e10cSrcweir #include <math.h>
31cdf0e10cSrcweir #include <unistd.h>
32cdf0e10cSrcweir #include <fcntl.h>
33cdf0e10cSrcweir #include <sys/mman.h>
34cdf0e10cSrcweir #include <sys/stat.h>
35cdf0e10cSrcweir #include <sys/types.h>
36cdf0e10cSrcweir 
37cdf0e10cSrcweir #include "sal/alloca.h"
38cdf0e10cSrcweir #include "sal/types.h"
39cdf0e10cSrcweir 
40cdf0e10cSrcweir #include "rtl/tencinfo.h"
41cdf0e10cSrcweir 
42cdf0e10cSrcweir #include "osl/file.hxx"
43cdf0e10cSrcweir 
44cdf0e10cSrcweir #include "tools/string.hxx"
45cdf0e10cSrcweir #include "tools/debug.hxx"
46cdf0e10cSrcweir #include "tools/stream.hxx"
47cdf0e10cSrcweir 
48cdf0e10cSrcweir #include "basegfx/polygon/b2dpolypolygon.hxx"
49cdf0e10cSrcweir 
50cdf0e10cSrcweir #include "i18npool/mslangid.hxx"
51cdf0e10cSrcweir 
52cdf0e10cSrcweir #include <vcl/sysdata.hxx>
53cdf0e10cSrcweir #include "printergfx.hxx"
54cdf0e10cSrcweir #include "vcl/fontmanager.hxx"
55cdf0e10cSrcweir #include "vcl/jobdata.hxx"
56cdf0e10cSrcweir #include "vcl/printerinfomanager.hxx"
57cdf0e10cSrcweir #include "vcl/svapp.hxx"
58cdf0e10cSrcweir 
59cdf0e10cSrcweir #include "unx/salunx.h"
60cdf0e10cSrcweir #include "unx/saldata.hxx"
61cdf0e10cSrcweir #include "unx/saldisp.hxx"
62cdf0e10cSrcweir #include "unx/salgdi.h"
63cdf0e10cSrcweir #include "unx/pspgraphics.h"
64cdf0e10cSrcweir #include "unx/salvd.h"
65cdf0e10cSrcweir 
66cdf0e10cSrcweir #include "salcvt.hxx"
67cdf0e10cSrcweir #include "gcach_xpeer.hxx"
68cdf0e10cSrcweir #include "xrender_peer.hxx"
69cdf0e10cSrcweir #include "impfont.hxx"
70cdf0e10cSrcweir #include "salframe.hxx"
71cdf0e10cSrcweir #include "outdev.h"
72cdf0e10cSrcweir 
73cdf0e10cSrcweir 
74cdf0e10cSrcweir #include <hash_set>
75cdf0e10cSrcweir 
76cdf0e10cSrcweir #ifdef ENABLE_GRAPHITE
77cdf0e10cSrcweir #include <graphite_layout.hxx>
78cdf0e10cSrcweir #include <graphite_serverfont.hxx>
79cdf0e10cSrcweir #endif
80cdf0e10cSrcweir 
81cdf0e10cSrcweir struct cairo_surface_t;
82cdf0e10cSrcweir struct cairo_t;
83cdf0e10cSrcweir struct cairo_font_face_t;
84cdf0e10cSrcweir typedef void* FT_Face;
85cdf0e10cSrcweir struct cairo_matrix_t {
86cdf0e10cSrcweir     double xx; double yx;
87cdf0e10cSrcweir     double xy; double yy;
88cdf0e10cSrcweir     double x0; double y0;
89cdf0e10cSrcweir };
90cdf0e10cSrcweir struct cairo_glyph_t
91cdf0e10cSrcweir {
92cdf0e10cSrcweir     unsigned long index;
93cdf0e10cSrcweir     double x;
94cdf0e10cSrcweir     double y;
95cdf0e10cSrcweir };
96cdf0e10cSrcweir struct BOX
97cdf0e10cSrcweir {
98cdf0e10cSrcweir     short x1, x2, y1, y2;
99cdf0e10cSrcweir };
100cdf0e10cSrcweir struct _XRegion
101cdf0e10cSrcweir {
102cdf0e10cSrcweir     long size;
103cdf0e10cSrcweir     long numRects;
104cdf0e10cSrcweir     BOX *rects;
105cdf0e10cSrcweir     BOX extents;
106cdf0e10cSrcweir };
107cdf0e10cSrcweir using namespace rtl;
108cdf0e10cSrcweir 
109cdf0e10cSrcweir // ===========================================================================
110cdf0e10cSrcweir 
111cdf0e10cSrcweir // PspKernInfo allows on-demand-querying of psprint provided kerning info (#i29881#)
112cdf0e10cSrcweir class PspKernInfo : public ExtraKernInfo
113cdf0e10cSrcweir {
114cdf0e10cSrcweir public:
PspKernInfo(int nFontId)115cdf0e10cSrcweir     PspKernInfo( int nFontId ) : ExtraKernInfo(nFontId) {}
116cdf0e10cSrcweir protected:
117cdf0e10cSrcweir     virtual void Initialize() const;
118cdf0e10cSrcweir };
119cdf0e10cSrcweir 
120cdf0e10cSrcweir //--------------------------------------------------------------------------
121cdf0e10cSrcweir 
Initialize() const122cdf0e10cSrcweir void PspKernInfo::Initialize() const
123cdf0e10cSrcweir {
124cdf0e10cSrcweir     mbInitialized = true;
125cdf0e10cSrcweir 
126cdf0e10cSrcweir     // get the kerning pairs from psprint
127cdf0e10cSrcweir     const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
128cdf0e10cSrcweir     typedef std::list< psp::KernPair > PspKernPairs;
129cdf0e10cSrcweir     const PspKernPairs& rKernPairs = rMgr.getKernPairs( mnFontId );
130cdf0e10cSrcweir     if( rKernPairs.empty() )
131cdf0e10cSrcweir         return;
132cdf0e10cSrcweir 
133cdf0e10cSrcweir     // feed psprint's kerning list into a lookup-friendly container
134b4fbd7a9SHerbert Dürr     maUnicodeKernPairs.rehash( rKernPairs.size() );
135cdf0e10cSrcweir     PspKernPairs::const_iterator it = rKernPairs.begin();
136cdf0e10cSrcweir     for(; it != rKernPairs.end(); ++it )
137cdf0e10cSrcweir     {
138cdf0e10cSrcweir         ImplKernPairData aKernPair = { it->first, it->second, it->kern_x };
139cdf0e10cSrcweir         maUnicodeKernPairs.insert( aKernPair );
140cdf0e10cSrcweir     }
141cdf0e10cSrcweir }
142cdf0e10cSrcweir 
143cdf0e10cSrcweir // ----------------------------------------------------------------------------
144cdf0e10cSrcweir //
145cdf0e10cSrcweir // X11SalGraphics
146cdf0e10cSrcweir //
147cdf0e10cSrcweir // ----------------------------------------------------------------------------
148cdf0e10cSrcweir 
149cdf0e10cSrcweir GC
GetFontGC()150cdf0e10cSrcweir X11SalGraphics::GetFontGC()
151cdf0e10cSrcweir {
152cdf0e10cSrcweir 	Display *pDisplay = GetXDisplay();
153cdf0e10cSrcweir 
154cdf0e10cSrcweir 	if( !pFontGC_ )
155cdf0e10cSrcweir 	{
156cdf0e10cSrcweir 		XGCValues values;
157cdf0e10cSrcweir 		values.subwindow_mode		= ClipByChildren;
158cdf0e10cSrcweir 		values.fill_rule			= EvenOddRule;		// Pict import/ Gradient
159cdf0e10cSrcweir 		values.graphics_exposures	= False;
160cdf0e10cSrcweir 		values.foreground			= nTextPixel_;
161cdf0e10cSrcweir         pFontGC_ = XCreateGC( pDisplay, hDrawable_,
162cdf0e10cSrcweir                               GCSubwindowMode | GCFillRule
163cdf0e10cSrcweir                               | GCGraphicsExposures | GCForeground,
164cdf0e10cSrcweir                               &values );
165cdf0e10cSrcweir 	}
166cdf0e10cSrcweir 	if( !bFontGC_ )
167cdf0e10cSrcweir 	{
168cdf0e10cSrcweir 		XSetForeground( pDisplay, pFontGC_, nTextPixel_ );
169cdf0e10cSrcweir 		SetClipRegion( pFontGC_ );
170cdf0e10cSrcweir 		bFontGC_ = sal_True;
171cdf0e10cSrcweir 	}
172cdf0e10cSrcweir 
173cdf0e10cSrcweir 	return pFontGC_;
174cdf0e10cSrcweir }
175cdf0e10cSrcweir 
176cdf0e10cSrcweir //--------------------------------------------------------------------------
177cdf0e10cSrcweir 
setFont(const ImplFontSelectData * pEntry,int nFallbackLevel)178cdf0e10cSrcweir bool X11SalGraphics::setFont( const ImplFontSelectData *pEntry, int nFallbackLevel )
179cdf0e10cSrcweir {
180cdf0e10cSrcweir #ifdef HDU_DEBUG
181cdf0e10cSrcweir     ByteString aReqName( "NULL" );
182cdf0e10cSrcweir     if( pEntry )
183cdf0e10cSrcweir         aReqName = ByteString( pEntry->maName, RTL_TEXTENCODING_UTF8 );
184cdf0e10cSrcweir     ByteString aUseName( "NULL" );
185cdf0e10cSrcweir     if( pEntry && pEntry->mpFontData )
186cdf0e10cSrcweir         aUseName = ByteString( pEntry->mpFontData->GetFamilyName(), RTL_TEXTENCODING_UTF8 );
187cdf0e10cSrcweir     fprintf( stderr, "SetFont(lvl=%d,\"%s\", %d*%d, naa=%d,b=%d,i=%d) => \"%s\"\n",
188cdf0e10cSrcweir         nFallbackLevel, aReqName.GetBuffer(),
189cdf0e10cSrcweir 	!pEntry?-1:pEntry->mnWidth, !pEntry?-1:pEntry->mnHeight,
190cdf0e10cSrcweir         !pEntry?-1:pEntry->mbNonAntialiased,
191cdf0e10cSrcweir 	!pEntry?-1:pEntry->meWeight, !pEntry?-1:pEntry->meItalic,
192cdf0e10cSrcweir         aUseName.GetBuffer() );
193cdf0e10cSrcweir #endif
194cdf0e10cSrcweir 
195cdf0e10cSrcweir     // release all no longer needed font resources
196cdf0e10cSrcweir     for( int i = nFallbackLevel; i < MAX_FALLBACK; ++i )
197cdf0e10cSrcweir     {
198cdf0e10cSrcweir         if( mpServerFont[i] != NULL )
199cdf0e10cSrcweir         {
200cdf0e10cSrcweir             // old server side font is no longer referenced
201cdf0e10cSrcweir             GlyphCache::GetInstance().UncacheFont( *mpServerFont[i] );
202cdf0e10cSrcweir             mpServerFont[i] = NULL;
203cdf0e10cSrcweir         }
204cdf0e10cSrcweir     }
205cdf0e10cSrcweir 
206cdf0e10cSrcweir     // return early if there is no new font
207cdf0e10cSrcweir     if( !pEntry )
208cdf0e10cSrcweir 	return false;
209cdf0e10cSrcweir 
210cdf0e10cSrcweir     bFontVertical_ = pEntry->mbVertical;
211cdf0e10cSrcweir 
212cdf0e10cSrcweir     // return early if this is not a valid font for this graphics
213cdf0e10cSrcweir     if( !pEntry->mpFontData )
214cdf0e10cSrcweir         return false;
215cdf0e10cSrcweir 
216cdf0e10cSrcweir     // handle the request for a non-native X11-font => use the GlyphCache
217cdf0e10cSrcweir     ServerFont* pServerFont = GlyphCache::GetInstance().CacheFont( *pEntry );
218cdf0e10cSrcweir     if( pServerFont != NULL )
219cdf0e10cSrcweir     {
220cdf0e10cSrcweir         // ignore fonts with e.g. corrupted font files
221cdf0e10cSrcweir         if( !pServerFont->TestFont() )
222cdf0e10cSrcweir         {
223cdf0e10cSrcweir             GlyphCache::GetInstance().UncacheFont( *pServerFont );
224cdf0e10cSrcweir             return false;
225cdf0e10cSrcweir         }
226cdf0e10cSrcweir 
227cdf0e10cSrcweir         // register to use the font
228cdf0e10cSrcweir         mpServerFont[ nFallbackLevel ] = pServerFont;
229cdf0e10cSrcweir 
230cdf0e10cSrcweir         // apply font specific-hint settings if needed
231cdf0e10cSrcweir         // TODO: also disable it for reference devices
232cdf0e10cSrcweir 	if( !bPrinter_ )
233cdf0e10cSrcweir 	{
234cdf0e10cSrcweir 	    ImplServerFontEntry* pSFE = static_cast<ImplServerFontEntry*>( pEntry->mpFontEntry );
235cdf0e10cSrcweir 	    pSFE->HandleFontOptions();
236cdf0e10cSrcweir         }
237cdf0e10cSrcweir 
238cdf0e10cSrcweir         return true;
239cdf0e10cSrcweir     }
240cdf0e10cSrcweir 
241cdf0e10cSrcweir     return false;
242cdf0e10cSrcweir }
243cdf0e10cSrcweir 
HandleFontOptions(void)244cdf0e10cSrcweir void ImplServerFontEntry::HandleFontOptions( void )
245cdf0e10cSrcweir {
246cdf0e10cSrcweir 	bool GetFCFontOptions( const ImplFontAttributes&, int nSize, ImplFontOptions& );
247cdf0e10cSrcweir 
248cdf0e10cSrcweir 	if( !mpServerFont )
249cdf0e10cSrcweir 		return;
250cdf0e10cSrcweir 	if( !mbGotFontOptions )
251cdf0e10cSrcweir 	{
252cdf0e10cSrcweir 		// get and cache the font options
253cdf0e10cSrcweir 		mbGotFontOptions = true;
254cdf0e10cSrcweir 		mbValidFontOptions = GetFCFontOptions( *maFontSelData.mpFontData,
255cdf0e10cSrcweir 			maFontSelData.mnHeight, maFontOptions );
256cdf0e10cSrcweir 	}
257cdf0e10cSrcweir 	// apply the font options
258cdf0e10cSrcweir 	if( mbValidFontOptions )
259cdf0e10cSrcweir 		mpServerFont->SetFontOptions( maFontOptions );
260cdf0e10cSrcweir }
261cdf0e10cSrcweir 
262cdf0e10cSrcweir //--------------------------------------------------------------------------
263cdf0e10cSrcweir 
264cdf0e10cSrcweir namespace {
265cdf0e10cSrcweir 
266cdf0e10cSrcweir class CairoWrapper
267cdf0e10cSrcweir {
268cdf0e10cSrcweir private:
269cdf0e10cSrcweir     oslModule mpCairoLib;
270cdf0e10cSrcweir 
271cdf0e10cSrcweir     cairo_surface_t* (*mp_xlib_surface_create_with_xrender_format)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int );
272cdf0e10cSrcweir     void (*mp_surface_destroy)(cairo_surface_t *);
273cdf0e10cSrcweir     cairo_t* (*mp_create)(cairo_surface_t *);
274cdf0e10cSrcweir     void (*mp_destroy)(cairo_t*);
275cdf0e10cSrcweir     void (*mp_clip)(cairo_t*);
276cdf0e10cSrcweir     void (*mp_rectangle)(cairo_t*, double, double, double, double);
277cdf0e10cSrcweir     cairo_font_face_t * (*mp_ft_font_face_create_for_ft_face)(FT_Face, int);
278cdf0e10cSrcweir     void (*mp_set_font_face)(cairo_t *, cairo_font_face_t *);
279cdf0e10cSrcweir     void (*mp_font_face_destroy)(cairo_font_face_t *);
280cdf0e10cSrcweir     void (*mp_matrix_init_identity)(cairo_matrix_t *);
281cdf0e10cSrcweir     void (*mp_matrix_scale)(cairo_matrix_t *, double, double);
282cdf0e10cSrcweir     void (*mp_matrix_rotate)(cairo_matrix_t *, double);
283cdf0e10cSrcweir     void (*mp_set_font_matrix)(cairo_t *, const cairo_matrix_t *);
284cdf0e10cSrcweir     void (*mp_show_glyphs)(cairo_t *, const cairo_glyph_t *, int );
285cdf0e10cSrcweir     void (*mp_set_source_rgb)(cairo_t *, double , double , double );
286cdf0e10cSrcweir     void (*mp_set_font_options)(cairo_t *, const void *);
287cdf0e10cSrcweir     void (*mp_ft_font_options_substitute)(const void*, void*);
288cdf0e10cSrcweir 
canEmbolden() const289cdf0e10cSrcweir     bool canEmbolden() const { return false; }
290cdf0e10cSrcweir 
291cdf0e10cSrcweir     CairoWrapper();
292cdf0e10cSrcweir public:
293cdf0e10cSrcweir     static CairoWrapper& get();
isValid() const294cdf0e10cSrcweir     bool isValid() const { return (mpCairoLib != NULL); }
295cdf0e10cSrcweir     bool isCairoRenderable(const ServerFont& rFont);
296cdf0e10cSrcweir 
xlib_surface_create_with_xrender_format(Display * pDisplay,Drawable drawable,Screen * pScreen,XRenderPictFormat * pFormat,int width,int height)297cdf0e10cSrcweir     cairo_surface_t* xlib_surface_create_with_xrender_format(Display *pDisplay, Drawable drawable, Screen *pScreen, XRenderPictFormat *pFormat, int width, int height)
298cdf0e10cSrcweir         { return (*mp_xlib_surface_create_with_xrender_format)(pDisplay, drawable, pScreen, pFormat, width, height); }
surface_destroy(cairo_surface_t * surface)299cdf0e10cSrcweir     void surface_destroy(cairo_surface_t *surface) { (*mp_surface_destroy)(surface); }
create(cairo_surface_t * surface)300cdf0e10cSrcweir     cairo_t* create(cairo_surface_t *surface) { return (*mp_create)(surface); }
destroy(cairo_t * cr)301cdf0e10cSrcweir     void destroy(cairo_t *cr) { (*mp_destroy)(cr); }
clip(cairo_t * cr)302cdf0e10cSrcweir     void clip(cairo_t *cr) { (*mp_clip)(cr); }
rectangle(cairo_t * cr,double x,double y,double width,double height)303cdf0e10cSrcweir     void rectangle(cairo_t *cr, double x, double y, double width, double height)
304cdf0e10cSrcweir         { (*mp_rectangle)(cr, x, y, width, height); }
ft_font_face_create_for_ft_face(FT_Face face,int load_flags)305cdf0e10cSrcweir     cairo_font_face_t* ft_font_face_create_for_ft_face(FT_Face face, int load_flags)
306cdf0e10cSrcweir         { return (*mp_ft_font_face_create_for_ft_face)(face, load_flags); }
set_font_face(cairo_t * cr,cairo_font_face_t * font_face)307cdf0e10cSrcweir     void set_font_face(cairo_t *cr, cairo_font_face_t *font_face)
308cdf0e10cSrcweir         { (*mp_set_font_face)(cr, font_face); }
font_face_destroy(cairo_font_face_t * font_face)309cdf0e10cSrcweir     void font_face_destroy(cairo_font_face_t *font_face)
310cdf0e10cSrcweir         { (*mp_font_face_destroy)(font_face); }
matrix_init_identity(cairo_matrix_t * matrix)311cdf0e10cSrcweir     void matrix_init_identity(cairo_matrix_t *matrix)
312cdf0e10cSrcweir         { (*mp_matrix_init_identity)(matrix); }
matrix_scale(cairo_matrix_t * matrix,double sx,double sy)313cdf0e10cSrcweir     void matrix_scale(cairo_matrix_t *matrix, double sx, double sy)
314cdf0e10cSrcweir         { (*mp_matrix_scale)(matrix, sx, sy); }
matrix_rotate(cairo_matrix_t * matrix,double radians)315cdf0e10cSrcweir     void matrix_rotate(cairo_matrix_t *matrix, double radians)
316cdf0e10cSrcweir         { (*mp_matrix_rotate)(matrix, radians); }
set_font_matrix(cairo_t * cr,const cairo_matrix_t * matrix)317cdf0e10cSrcweir     void set_font_matrix(cairo_t *cr, const cairo_matrix_t *matrix)
318cdf0e10cSrcweir         { (*mp_set_font_matrix)(cr, matrix); }
show_glyphs(cairo_t * cr,const cairo_glyph_t * glyphs,int no_glyphs)319cdf0e10cSrcweir     void show_glyphs(cairo_t *cr, const cairo_glyph_t *glyphs, int no_glyphs)
320cdf0e10cSrcweir         { (*mp_show_glyphs)(cr, glyphs, no_glyphs); }
set_source_rgb(cairo_t * cr,double red,double green,double blue)321cdf0e10cSrcweir     void set_source_rgb(cairo_t *cr, double red, double green, double blue)
322cdf0e10cSrcweir         { (*mp_set_source_rgb)(cr, red, green, blue); }
set_font_options(cairo_t * cr,const void * options)323cdf0e10cSrcweir     void set_font_options(cairo_t *cr, const void *options)
324cdf0e10cSrcweir         { (*mp_set_font_options)(cr, options); }
ft_font_options_substitute(const void * options,void * pattern)325cdf0e10cSrcweir     void ft_font_options_substitute(const void *options, void *pattern)
326cdf0e10cSrcweir         { (*mp_ft_font_options_substitute)(options, pattern); }
327cdf0e10cSrcweir };
328cdf0e10cSrcweir 
329cdf0e10cSrcweir static CairoWrapper* pCairoInstance = NULL;
330cdf0e10cSrcweir 
get()331cdf0e10cSrcweir CairoWrapper& CairoWrapper::get()
332cdf0e10cSrcweir {
333cdf0e10cSrcweir     if( ! pCairoInstance )
334cdf0e10cSrcweir         pCairoInstance = new CairoWrapper();
335cdf0e10cSrcweir     return *pCairoInstance;
336cdf0e10cSrcweir }
337cdf0e10cSrcweir 
CairoWrapper()338cdf0e10cSrcweir CairoWrapper::CairoWrapper()
339cdf0e10cSrcweir :   mpCairoLib( NULL )
340cdf0e10cSrcweir {
341cdf0e10cSrcweir     static const char* pDisableCairoText = getenv( "SAL_DISABLE_CAIROTEXT" );
342cdf0e10cSrcweir     if( pDisableCairoText && (pDisableCairoText[0] != '0') )
343cdf0e10cSrcweir         return;
344cdf0e10cSrcweir 
345cdf0e10cSrcweir     int nDummy;
346cdf0e10cSrcweir     if( !XQueryExtension( GetX11SalData()->GetDisplay()->GetDisplay(), "RENDER", &nDummy, &nDummy, &nDummy ) )
347cdf0e10cSrcweir         return;
348cdf0e10cSrcweir 
349aa150a94SHerbert Dürr     mpCairoLib = osl_loadAsciiModule( "libcairo.so.2", SAL_LOADMODULE_DEFAULT );
350cdf0e10cSrcweir     if( !mpCairoLib )
351cdf0e10cSrcweir         return;
352cdf0e10cSrcweir 
353cdf0e10cSrcweir #ifdef DEBUG
354cdf0e10cSrcweir     // check cairo version
355cdf0e10cSrcweir     int (*p_version)();
356cdf0e10cSrcweir     p_version = (int(*)()) osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_version" );
357cdf0e10cSrcweir 	const int nVersion = p_version ? (*p_version)() : 0;
358cdf0e10cSrcweir     fprintf( stderr, "CAIRO version=%d\n", nVersion );
359cdf0e10cSrcweir #endif
360cdf0e10cSrcweir 
361cdf0e10cSrcweir     mp_xlib_surface_create_with_xrender_format = (cairo_surface_t* (*)(Display *, Drawable , Screen *, XRenderPictFormat *, int , int ))
362cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_xlib_surface_create_with_xrender_format" );
363cdf0e10cSrcweir     mp_surface_destroy = (void(*)(cairo_surface_t*))
364cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_surface_destroy" );
365cdf0e10cSrcweir     mp_create = (cairo_t*(*)(cairo_surface_t*))
366cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_create" );
367cdf0e10cSrcweir     mp_destroy = (void(*)(cairo_t*))
368cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_destroy" );
369cdf0e10cSrcweir     mp_clip = (void(*)(cairo_t*))
370cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_clip" );
371cdf0e10cSrcweir     mp_rectangle = (void(*)(cairo_t*, double, double, double, double))
372cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_rectangle" );
373cdf0e10cSrcweir     mp_ft_font_face_create_for_ft_face = (cairo_font_face_t * (*)(FT_Face, int))
374cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_ft_font_face_create_for_ft_face" );
375cdf0e10cSrcweir     mp_set_font_face = (void (*)(cairo_t *, cairo_font_face_t *))
376cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_face" );
377cdf0e10cSrcweir     mp_font_face_destroy = (void (*)(cairo_font_face_t *))
378cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_font_face_destroy" );
379cdf0e10cSrcweir     mp_matrix_init_identity = (void (*)(cairo_matrix_t *))
380cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_init_identity" );
381cdf0e10cSrcweir     mp_matrix_scale = (void (*)(cairo_matrix_t *, double, double))
382cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_scale" );
383cdf0e10cSrcweir     mp_matrix_rotate = (void (*)(cairo_matrix_t *, double))
384cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_matrix_rotate" );
385cdf0e10cSrcweir     mp_set_font_matrix = (void (*)(cairo_t *, const cairo_matrix_t *))
386cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_matrix" );
387cdf0e10cSrcweir     mp_show_glyphs = (void (*)(cairo_t *, const cairo_glyph_t *, int ))
388cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_show_glyphs" );
389cdf0e10cSrcweir     mp_set_source_rgb = (void (*)(cairo_t *, double , double , double ))
390cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_source_rgb" );
391cdf0e10cSrcweir     mp_set_font_options = (void (*)(cairo_t *, const void *options ))
392cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_set_font_options" );
393cdf0e10cSrcweir     mp_ft_font_options_substitute = (void (*)(const void *, void *))
394cdf0e10cSrcweir         osl_getAsciiFunctionSymbol( mpCairoLib, "cairo_ft_font_options_substitute" );
395cdf0e10cSrcweir 
396cdf0e10cSrcweir     if( !(
397cdf0e10cSrcweir             mp_xlib_surface_create_with_xrender_format &&
398cdf0e10cSrcweir             mp_surface_destroy &&
399cdf0e10cSrcweir             mp_create &&
400cdf0e10cSrcweir             mp_destroy &&
401cdf0e10cSrcweir             mp_clip &&
402cdf0e10cSrcweir             mp_rectangle &&
403cdf0e10cSrcweir             mp_ft_font_face_create_for_ft_face &&
404cdf0e10cSrcweir             mp_set_font_face &&
405cdf0e10cSrcweir             mp_font_face_destroy &&
406cdf0e10cSrcweir             mp_matrix_init_identity &&
407cdf0e10cSrcweir             mp_matrix_scale &&
408cdf0e10cSrcweir             mp_matrix_rotate &&
409cdf0e10cSrcweir             mp_set_font_matrix &&
410cdf0e10cSrcweir             mp_show_glyphs &&
411cdf0e10cSrcweir             mp_set_source_rgb &&
412cdf0e10cSrcweir             mp_set_font_options &&
413cdf0e10cSrcweir             mp_ft_font_options_substitute
414cdf0e10cSrcweir         ) )
415cdf0e10cSrcweir     {
416cdf0e10cSrcweir         osl_unloadModule( mpCairoLib );
417cdf0e10cSrcweir 	mpCairoLib = NULL;
418cdf0e10cSrcweir #if OSL_DEBUG_LEVEL > 1
419cdf0e10cSrcweir         fprintf( stderr, "not all needed symbols were found\n" );
420cdf0e10cSrcweir #endif
421cdf0e10cSrcweir     }
422cdf0e10cSrcweir }
423cdf0e10cSrcweir 
isCairoRenderable(const ServerFont & rFont)424cdf0e10cSrcweir bool CairoWrapper::isCairoRenderable(const ServerFont& rFont)
425cdf0e10cSrcweir {
426cdf0e10cSrcweir     return rFont.GetFtFace() && isValid() && rFont.GetAntialiasAdvice() &&
427cdf0e10cSrcweir         (rFont.NeedsArtificialBold() ? canEmbolden() : true);
428cdf0e10cSrcweir }
429cdf0e10cSrcweir 
430cdf0e10cSrcweir } //namespace
431cdf0e10cSrcweir 
432cdf0e10cSrcweir CairoFontsCache::LRUFonts CairoFontsCache::maLRUFonts;
433cdf0e10cSrcweir int CairoFontsCache::mnRefCount = 0;
434cdf0e10cSrcweir 
CairoFontsCache()435cdf0e10cSrcweir CairoFontsCache::CairoFontsCache()
436cdf0e10cSrcweir {
437cdf0e10cSrcweir     ++mnRefCount;
438cdf0e10cSrcweir }
439cdf0e10cSrcweir 
~CairoFontsCache()440cdf0e10cSrcweir CairoFontsCache::~CairoFontsCache()
441cdf0e10cSrcweir {
442cdf0e10cSrcweir     --mnRefCount;
443cdf0e10cSrcweir     if (!mnRefCount && !maLRUFonts.empty())
444cdf0e10cSrcweir     {
445cdf0e10cSrcweir         CairoWrapper &rCairo = CairoWrapper::get();
446cdf0e10cSrcweir         LRUFonts::iterator aEnd = maLRUFonts.end();
447cdf0e10cSrcweir         for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
448cdf0e10cSrcweir             rCairo.font_face_destroy((cairo_font_face_t*)aI->first);
449cdf0e10cSrcweir     }
450cdf0e10cSrcweir }
451cdf0e10cSrcweir 
CacheFont(void * pFont,void * pId)452cdf0e10cSrcweir void CairoFontsCache::CacheFont(void *pFont, void* pId)
453cdf0e10cSrcweir {
454cdf0e10cSrcweir     maLRUFonts.push_front( std::pair<void*, void *>(pFont, pId) );
455cdf0e10cSrcweir     if (maLRUFonts.size() > 8)
456cdf0e10cSrcweir     {
457cdf0e10cSrcweir         CairoWrapper &rCairo = CairoWrapper::get();
458cdf0e10cSrcweir         rCairo.font_face_destroy((cairo_font_face_t*)maLRUFonts.back().first);
459cdf0e10cSrcweir         maLRUFonts.pop_back();
460cdf0e10cSrcweir     }
461cdf0e10cSrcweir }
462cdf0e10cSrcweir 
FindCachedFont(void * pId)463cdf0e10cSrcweir void* CairoFontsCache::FindCachedFont(void *pId)
464cdf0e10cSrcweir {
465cdf0e10cSrcweir     LRUFonts::iterator aEnd = maLRUFonts.end();
466cdf0e10cSrcweir     for (LRUFonts::iterator aI = maLRUFonts.begin(); aI != aEnd; ++aI)
467cdf0e10cSrcweir         if (aI->second == pId)
468cdf0e10cSrcweir             return aI->first;
469cdf0e10cSrcweir     return NULL;
470cdf0e10cSrcweir }
471cdf0e10cSrcweir 
DrawCairoAAFontString(const ServerFontLayout & rLayout)472cdf0e10cSrcweir void X11SalGraphics::DrawCairoAAFontString( const ServerFontLayout& rLayout )
473cdf0e10cSrcweir {
474cdf0e10cSrcweir     std::vector<cairo_glyph_t> cairo_glyphs;
475cdf0e10cSrcweir     cairo_glyphs.reserve( 256 );
476cdf0e10cSrcweir 
477cdf0e10cSrcweir     Point aPos;
478cdf0e10cSrcweir     sal_GlyphId aGlyphId;
479cdf0e10cSrcweir     for( int nStart = 0; rLayout.GetNextGlyphs( 1, &aGlyphId, aPos, nStart ); )
480cdf0e10cSrcweir     {
481cdf0e10cSrcweir         cairo_glyph_t aGlyph;
482cdf0e10cSrcweir         aGlyph.index = aGlyphId & GF_IDXMASK;
483cdf0e10cSrcweir         aGlyph.x = aPos.X();
484cdf0e10cSrcweir         aGlyph.y = aPos.Y();
485cdf0e10cSrcweir         cairo_glyphs.push_back(aGlyph);
486cdf0e10cSrcweir     }
487cdf0e10cSrcweir 
488cdf0e10cSrcweir     if (cairo_glyphs.empty())
489cdf0e10cSrcweir         return;
490cdf0e10cSrcweir 
491cdf0e10cSrcweir     // find a XRenderPictFormat compatible with the Drawable
492cdf0e10cSrcweir     XRenderPictFormat* pVisualFormat = static_cast<XRenderPictFormat*>(GetXRenderFormat());
493cdf0e10cSrcweir     if( !pVisualFormat )
494cdf0e10cSrcweir     {
495cdf0e10cSrcweir         Visual* pVisual = GetDisplay()->GetVisual( m_nScreen ).GetVisual();
496cdf0e10cSrcweir         pVisualFormat = XRenderPeer::GetInstance().FindVisualFormat( pVisual );
497cdf0e10cSrcweir         // cache the XRenderPictFormat
498cdf0e10cSrcweir         SetXRenderFormat( static_cast<void*>(pVisualFormat) );
499cdf0e10cSrcweir     }
500cdf0e10cSrcweir 
501cdf0e10cSrcweir     DBG_ASSERT( pVisualFormat!=NULL, "no matching XRenderPictFormat for text" );
502cdf0e10cSrcweir     if( !pVisualFormat )
503cdf0e10cSrcweir 	    return;
504cdf0e10cSrcweir 
505cdf0e10cSrcweir     CairoWrapper &rCairo = CairoWrapper::get();
506cdf0e10cSrcweir 
507cdf0e10cSrcweir     Display* pDisplay = GetXDisplay();
508cdf0e10cSrcweir 
509cdf0e10cSrcweir     cairo_surface_t *surface = rCairo.xlib_surface_create_with_xrender_format (pDisplay,
510cdf0e10cSrcweir         hDrawable_, ScreenOfDisplay(pDisplay, m_nScreen), pVisualFormat, SAL_MAX_INT16, SAL_MAX_INT16);
511cdf0e10cSrcweir 
512cdf0e10cSrcweir     /*
513cdf0e10cSrcweir      * It might be ideal to cache surface and cairo context between calls and
514cdf0e10cSrcweir      * only destroy it when the drawable changes, but to do that we need to at
515cdf0e10cSrcweir      * least change the SalFrame etc impls to dtor the SalGraphics *before* the
516cdf0e10cSrcweir      * destruction of the windows they reference
517cdf0e10cSrcweir     */
518cdf0e10cSrcweir     cairo_t *cr = rCairo.create(surface);
519cdf0e10cSrcweir     rCairo.surface_destroy(surface);
520cdf0e10cSrcweir 
521cdf0e10cSrcweir     if (const void *pOptions = Application::GetSettings().GetStyleSettings().GetCairoFontOptions())
522cdf0e10cSrcweir         rCairo.set_font_options( cr, pOptions);
523cdf0e10cSrcweir 
524cdf0e10cSrcweir     if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
525cdf0e10cSrcweir     {
526cdf0e10cSrcweir         for (long i = 0; i < mpClipRegion->numRects; ++i)
527cdf0e10cSrcweir         {
528cdf0e10cSrcweir             rCairo.rectangle(cr,
529cdf0e10cSrcweir             mpClipRegion->rects[i].x1,
530cdf0e10cSrcweir             mpClipRegion->rects[i].y1,
531cdf0e10cSrcweir             mpClipRegion->rects[i].x2 - mpClipRegion->rects[i].x1,
532cdf0e10cSrcweir             mpClipRegion->rects[i].y2 - mpClipRegion->rects[i].y1);
533cdf0e10cSrcweir         }
534cdf0e10cSrcweir         rCairo.clip(cr);
535cdf0e10cSrcweir     }
536cdf0e10cSrcweir 
537cdf0e10cSrcweir     rCairo.set_source_rgb(cr,
538cdf0e10cSrcweir         SALCOLOR_RED(nTextColor_)/255.0,
539cdf0e10cSrcweir         SALCOLOR_GREEN(nTextColor_)/255.0,
540cdf0e10cSrcweir         SALCOLOR_BLUE(nTextColor_)/255.0);
541cdf0e10cSrcweir 
542cdf0e10cSrcweir     ServerFont& rFont = rLayout.GetServerFont();
543cdf0e10cSrcweir 
544cdf0e10cSrcweir     cairo_font_face_t* font_face = NULL;
545cdf0e10cSrcweir 
546cdf0e10cSrcweir     void *pId = rFont.GetFtFace();
547cdf0e10cSrcweir     font_face = (cairo_font_face_t*)m_aCairoFontsCache.FindCachedFont(pId);
548cdf0e10cSrcweir     if (!font_face)
549cdf0e10cSrcweir     {
550cdf0e10cSrcweir         font_face = rCairo.ft_font_face_create_for_ft_face(pId, rFont.GetLoadFlags());
551cdf0e10cSrcweir         m_aCairoFontsCache.CacheFont(font_face, pId);
552cdf0e10cSrcweir     }
553cdf0e10cSrcweir 
554cdf0e10cSrcweir     rCairo.set_font_face(cr, font_face);
555cdf0e10cSrcweir 
556cdf0e10cSrcweir     cairo_matrix_t m;
557cdf0e10cSrcweir     const ImplFontSelectData& rFSD = rFont.GetFontSelData();
558cdf0e10cSrcweir     int nWidth = rFSD.mnWidth ? rFSD.mnWidth : rFSD.mnHeight;
559cdf0e10cSrcweir 
560cdf0e10cSrcweir     rCairo.matrix_init_identity(&m);
561cdf0e10cSrcweir 
562cdf0e10cSrcweir     if (rLayout.GetOrientation())
563cdf0e10cSrcweir         rCairo.matrix_rotate(&m, (3600 - rLayout.GetOrientation()) * M_PI / 1800.0);
564cdf0e10cSrcweir 
565cdf0e10cSrcweir     rCairo.matrix_scale(&m, nWidth, rFSD.mnHeight);
566cdf0e10cSrcweir     if (rFont.NeedsArtificialItalic())
567cdf0e10cSrcweir         m.xy = -m.xx * 0x6000L / 0x10000L;
568cdf0e10cSrcweir 
569cdf0e10cSrcweir     rCairo.set_font_matrix(cr, &m);
570cdf0e10cSrcweir     rCairo.show_glyphs(cr, &cairo_glyphs[0], cairo_glyphs.size());
571cdf0e10cSrcweir     rCairo.destroy(cr);
572cdf0e10cSrcweir }
573cdf0e10cSrcweir 
574cdf0e10cSrcweir //--------------------------------------------------------------------------
575cdf0e10cSrcweir 
DrawServerAAFontString(const ServerFontLayout & rLayout)576cdf0e10cSrcweir void X11SalGraphics::DrawServerAAFontString( const ServerFontLayout& rLayout )
577cdf0e10cSrcweir {
578cdf0e10cSrcweir 	// get xrender target for this drawable
579cdf0e10cSrcweir     Picture aDstPic = GetXRenderPicture();
580cdf0e10cSrcweir 	if( !aDstPic )
581cdf0e10cSrcweir 		return;
582cdf0e10cSrcweir 
583cdf0e10cSrcweir     // get a XRenderPicture for the font foreground
584cdf0e10cSrcweir     // TODO: move into own method
585cdf0e10cSrcweir     XRenderPeer& rRenderPeer = XRenderPeer::GetInstance();
586cdf0e10cSrcweir 	XRenderPictFormat* pVisualFormat = (XRenderPictFormat*)GetXRenderFormat();
587cdf0e10cSrcweir 	DBG_ASSERT( pVisualFormat, "we already have a render picture, but XRenderPictFormat==NULL???");
588cdf0e10cSrcweir     const int nVisualDepth = pVisualFormat->depth;
589cdf0e10cSrcweir     SalDisplay::RenderEntry& rEntry = GetDisplay()->GetRenderEntries( m_nScreen )[ nVisualDepth ];
590cdf0e10cSrcweir     if( !rEntry.m_aPicture )
591cdf0e10cSrcweir     {
592cdf0e10cSrcweir         // create and cache XRenderPicture for the font foreground
593cdf0e10cSrcweir         Display* pDisplay = GetXDisplay();
594cdf0e10cSrcweir #ifdef DEBUG
595cdf0e10cSrcweir         int iDummy;
596cdf0e10cSrcweir         unsigned uDummy;
597cdf0e10cSrcweir         XLIB_Window wDummy;
598cdf0e10cSrcweir         unsigned int nDrawDepth;
599cdf0e10cSrcweir         ::XGetGeometry( pDisplay, hDrawable_, &wDummy, &iDummy, &iDummy,
600cdf0e10cSrcweir                       &uDummy, &uDummy, &uDummy, &nDrawDepth );
601cdf0e10cSrcweir         DBG_ASSERT( static_cast<unsigned>(nVisualDepth) == nDrawDepth, "depth messed up for XRender" );
602cdf0e10cSrcweir #endif
603cdf0e10cSrcweir 
604cdf0e10cSrcweir         rEntry.m_aPixmap = ::XCreatePixmap( pDisplay, hDrawable_, 1, 1, nVisualDepth );
605cdf0e10cSrcweir 
606cdf0e10cSrcweir         XRenderPictureAttributes aAttr;
607cdf0e10cSrcweir         aAttr.repeat = true;
608cdf0e10cSrcweir         rEntry.m_aPicture = rRenderPeer.CreatePicture ( rEntry.m_aPixmap, pVisualFormat, CPRepeat, &aAttr );
609cdf0e10cSrcweir     }
610cdf0e10cSrcweir 
611cdf0e10cSrcweir     // set font foreground color and opacity
612cdf0e10cSrcweir     XRenderColor aRenderColor = GetXRenderColor( nTextColor_ );
613cdf0e10cSrcweir     rRenderPeer.FillRectangle( PictOpSrc, rEntry.m_aPicture, &aRenderColor, 0, 0, 1, 1 );
614cdf0e10cSrcweir 
615cdf0e10cSrcweir     // set clipping
616cdf0e10cSrcweir     // TODO: move into GetXRenderPicture()?
617cdf0e10cSrcweir     if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
618cdf0e10cSrcweir         rRenderPeer.SetPictureClipRegion( aDstPic, mpClipRegion );
619cdf0e10cSrcweir 
620cdf0e10cSrcweir     ServerFont& rFont = rLayout.GetServerFont();
621cdf0e10cSrcweir     X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
622cdf0e10cSrcweir     GlyphSet aGlyphSet = rGlyphPeer.GetGlyphSet( rFont, m_nScreen );
623cdf0e10cSrcweir 
624cdf0e10cSrcweir     Point aPos;
625cdf0e10cSrcweir     static const int MAXGLYPHS = 160;
626cdf0e10cSrcweir     sal_GlyphId aGlyphAry[ MAXGLYPHS ];
627cdf0e10cSrcweir     int nMaxGlyphs = rLayout.GetOrientation() ? 1 : MAXGLYPHS;
628cdf0e10cSrcweir     for( int nStart = 0;;)
629cdf0e10cSrcweir     {
630cdf0e10cSrcweir         int nGlyphs = rLayout.GetNextGlyphs( nMaxGlyphs, aGlyphAry, aPos, nStart );
631cdf0e10cSrcweir         if( !nGlyphs )
632cdf0e10cSrcweir             break;
633cdf0e10cSrcweir 
634cdf0e10cSrcweir         // #i51924# avoid 32->16bit coordinate truncation problem in X11
635cdf0e10cSrcweir         // TODO: reevaluate once displays with >30000 pixels are available
636cdf0e10cSrcweir         if( aPos.X() >= 30000 || aPos.Y() >= 30000 )
637cdf0e10cSrcweir             continue;
638cdf0e10cSrcweir 
639cdf0e10cSrcweir         unsigned int aRenderAry[ MAXGLYPHS ];
640cdf0e10cSrcweir         for( int i = 0; i < nGlyphs; ++i )
641248a599fSHerbert Dürr              aRenderAry[ i ] = rGlyphPeer.GetXRGlyph( rFont, aGlyphAry[i] );
642cdf0e10cSrcweir         rRenderPeer.CompositeString32( rEntry.m_aPicture, aDstPic,
643cdf0e10cSrcweir            aGlyphSet, aPos.X(), aPos.Y(), aRenderAry, nGlyphs );
644cdf0e10cSrcweir     }
645cdf0e10cSrcweir }
646cdf0e10cSrcweir 
647cdf0e10cSrcweir //--------------------------------------------------------------------------
648cdf0e10cSrcweir 
DrawServerAAForcedString(const ServerFontLayout & rLayout)649cdf0e10cSrcweir bool X11SalGraphics::DrawServerAAForcedString( const ServerFontLayout& rLayout )
650cdf0e10cSrcweir {
651cdf0e10cSrcweir     ServerFont& rFont = rLayout.GetServerFont();
652cdf0e10cSrcweir 
653cdf0e10cSrcweir     // prepare glyphs and get extent of operation
654cdf0e10cSrcweir     X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
655cdf0e10cSrcweir     int nXmin = 0;
656cdf0e10cSrcweir     int nXmax = 0;
657cdf0e10cSrcweir     int nYmin = 0;
658cdf0e10cSrcweir     int nYmax = 0;
659cdf0e10cSrcweir     int nStart = 0;
660cdf0e10cSrcweir     Point aPos;
661cdf0e10cSrcweir     sal_GlyphId nGlyph;
662cdf0e10cSrcweir     for( bool bFirst=true; rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); )
663cdf0e10cSrcweir     {
664cdf0e10cSrcweir         const RawBitmap* const pRawBitmap = rGlyphPeer.GetRawBitmap( rFont, nGlyph );
665cdf0e10cSrcweir         if( !pRawBitmap )
666cdf0e10cSrcweir             continue;
667cdf0e10cSrcweir 
668cdf0e10cSrcweir         const int nX1 = aPos.X() + pRawBitmap->mnXOffset;
669cdf0e10cSrcweir         const int nY1 = aPos.Y() + pRawBitmap->mnYOffset;
670cdf0e10cSrcweir         const int nX2 = nX1 + pRawBitmap->mnWidth;
671cdf0e10cSrcweir         const int nY2 = nY1 + pRawBitmap->mnHeight;
672cdf0e10cSrcweir 
673cdf0e10cSrcweir         if( bFirst )
674cdf0e10cSrcweir         {
675cdf0e10cSrcweir             bFirst = false;
676cdf0e10cSrcweir             nXmin = nX1;
677cdf0e10cSrcweir             nXmax = nX2;
678cdf0e10cSrcweir             nYmin = nY1;
679cdf0e10cSrcweir             nYmax = nY2;
680cdf0e10cSrcweir         }
681cdf0e10cSrcweir         else
682cdf0e10cSrcweir         {
683cdf0e10cSrcweir             if( nXmin > nX1 ) nXmin = nX1;
684cdf0e10cSrcweir             if( nXmax < nX2 ) nXmax = nX2;
685cdf0e10cSrcweir             if( nYmin > nY1 ) nYmin = nY1;
686cdf0e10cSrcweir             if( nYmax < nY2 ) nYmax = nY2;
687cdf0e10cSrcweir         }
688cdf0e10cSrcweir     }
689cdf0e10cSrcweir 
690cdf0e10cSrcweir     // get XImage
691cdf0e10cSrcweir     GetDisplay()->GetXLib()->PushXErrorLevel( true );
692cdf0e10cSrcweir     Display* pDisplay = GetXDisplay();
693cdf0e10cSrcweir 
694cdf0e10cSrcweir     XRectangle aXRect;
695cdf0e10cSrcweir     long nWidth = 1, nHeight = 1;
696cdf0e10cSrcweir     if( m_pFrame )
697cdf0e10cSrcweir         nWidth = m_pFrame->maGeometry.nWidth, nHeight = m_pFrame->maGeometry.nHeight;
698cdf0e10cSrcweir     else if( m_pVDev )
699cdf0e10cSrcweir         nWidth = m_pVDev->GetWidth(), nHeight = m_pVDev->GetHeight();
700cdf0e10cSrcweir 
701cdf0e10cSrcweir     if( mpClipRegion && !XEmptyRegion( mpClipRegion ) )
702cdf0e10cSrcweir     {
703cdf0e10cSrcweir         // get bounding box
704cdf0e10cSrcweir         XClipBox( mpClipRegion, &aXRect );
705cdf0e10cSrcweir         // clip with window
706cdf0e10cSrcweir         if( aXRect.x < 0 ) aXRect.x = 0;
707cdf0e10cSrcweir 
708cdf0e10cSrcweir         if( aXRect.y < 0 ) aXRect.y = 0;
709cdf0e10cSrcweir         if( aXRect.width+aXRect.x > nWidth ) aXRect.width = nWidth-aXRect.x;
710cdf0e10cSrcweir         if( aXRect.height+aXRect.y > nHeight ) aXRect.height = nHeight-aXRect.y;
711cdf0e10cSrcweir     }
712cdf0e10cSrcweir     else
713cdf0e10cSrcweir     {
714cdf0e10cSrcweir         aXRect.x = 0;
715cdf0e10cSrcweir         aXRect.y = 0;
716cdf0e10cSrcweir         aXRect.width = nWidth;
717cdf0e10cSrcweir         aXRect.height = nHeight;
718cdf0e10cSrcweir     }
719cdf0e10cSrcweir     if( m_pFrame )
720cdf0e10cSrcweir     {
721cdf0e10cSrcweir         // clip with screen
722cdf0e10cSrcweir         int nScreenX = m_pFrame->maGeometry.nX+aXRect.x;
723cdf0e10cSrcweir         int nScreenY = m_pFrame->maGeometry.nY+aXRect.y;
724cdf0e10cSrcweir         const Size& rScreenSize = GetDisplay()->getDataForScreen( m_nScreen ).m_aSize;
725cdf0e10cSrcweir         int nScreenW = rScreenSize.Width();
726cdf0e10cSrcweir         int nScreenH = rScreenSize.Height();
727cdf0e10cSrcweir         if( nScreenX < 0 )
728cdf0e10cSrcweir             aXRect.x -= nScreenX, aXRect.width += nScreenX;
729cdf0e10cSrcweir         if( nScreenX+aXRect.width > nScreenW )
730cdf0e10cSrcweir             aXRect.width = nScreenW-nScreenX;
731cdf0e10cSrcweir         if( nScreenY < 0 )
732cdf0e10cSrcweir             aXRect.y -= nScreenY, aXRect.height += nScreenY;
733cdf0e10cSrcweir         if( nScreenY+aXRect.height > nScreenH )
734cdf0e10cSrcweir             aXRect.height = nScreenH-nScreenY;
735cdf0e10cSrcweir     }
736cdf0e10cSrcweir 
737cdf0e10cSrcweir 
738cdf0e10cSrcweir     if( nXmin < aXRect.x )  nXmin = aXRect.x;
739cdf0e10cSrcweir     if( nYmin < aXRect.y )  nYmin = aXRect.y;
740cdf0e10cSrcweir     if( nXmax >= aXRect.x+aXRect.width )    nXmax = aXRect.x + aXRect.width - 1;
741cdf0e10cSrcweir     if( nYmax >= aXRect.y+aXRect.height )   nYmax = aXRect.y + aXRect.height - 1;
742cdf0e10cSrcweir 
743cdf0e10cSrcweir     if( nXmin > nXmax )
744cdf0e10cSrcweir         return false;
745cdf0e10cSrcweir     if( nYmin > nYmax )
746cdf0e10cSrcweir         return false;
747cdf0e10cSrcweir 
748cdf0e10cSrcweir     XImage* pImg = XGetImage( pDisplay, hDrawable_,
749cdf0e10cSrcweir                               nXmin, nYmin,
750cdf0e10cSrcweir                               (nXmax-nXmin+1), (nYmax-nYmin+1),
751cdf0e10cSrcweir                               ~0, ZPixmap );
752cdf0e10cSrcweir     if( pImg == NULL )
753cdf0e10cSrcweir     {
754cdf0e10cSrcweir         if( m_pFrame )
755cdf0e10cSrcweir         {
756cdf0e10cSrcweir             // the reason we did not get an image could be that the frame
757cdf0e10cSrcweir             // geometry changed in the meantime; lets get the current geometry
758cdf0e10cSrcweir             // and clip against the current window size as well as the screen
759cdf0e10cSrcweir             // with the current frame position
760cdf0e10cSrcweir             const Size& rScreenSize = GetDisplay()->getDataForScreen(m_nScreen).m_aSize;
761cdf0e10cSrcweir             int nScreenW = rScreenSize.Width();
762cdf0e10cSrcweir             int nScreenH = rScreenSize.Height();
763cdf0e10cSrcweir             XLIB_Window aRoot = None;
764cdf0e10cSrcweir             int x = 0, y = 0;
765cdf0e10cSrcweir             unsigned int w = 0, h = 0, bw = 0, d;
766cdf0e10cSrcweir             XGetGeometry( pDisplay, hDrawable_, &aRoot, &x, &y, &w, &h, &bw, &d );
767cdf0e10cSrcweir             XTranslateCoordinates( pDisplay, hDrawable_, aRoot, 0, 0, &x, &y, &aRoot );
768cdf0e10cSrcweir             if( nXmin + x < 0 ) // clip on left screen edge
769cdf0e10cSrcweir                 nXmin += x-nXmin;
770cdf0e10cSrcweir             if( nYmin + y < 0 ) // clip on top screen edge
771cdf0e10cSrcweir                 nYmin += y-nYmin;
772cdf0e10cSrcweir             if( nXmax >= int(w) ) // clip on right window egde
773cdf0e10cSrcweir                 nXmax = w-1;
774cdf0e10cSrcweir             if( nYmax >= int(h) ) // clip on bottom window edge
775cdf0e10cSrcweir                 nYmax = h-1;
776cdf0e10cSrcweir             if( nXmax + x >= nScreenW ) // clip on right screen edge
777cdf0e10cSrcweir                 nXmax -= (nXmax + x - nScreenW)+1;
778cdf0e10cSrcweir             if( nYmax + y >= nScreenH ) // clip on bottom screen edge
779cdf0e10cSrcweir                 nYmax -= (nYmax + y - nScreenH)+1;
780cdf0e10cSrcweir             if( nXmax >= nXmin && nYmax >= nYmin )
781cdf0e10cSrcweir             {
782cdf0e10cSrcweir                 // try again to get the image
783cdf0e10cSrcweir                 pImg = XGetImage( pDisplay, hDrawable_,
784cdf0e10cSrcweir                                   nXmin, nYmin,
785cdf0e10cSrcweir                                   (nXmax-nXmin+1), (nYmax-nYmin+1),
786cdf0e10cSrcweir                                   ~0, ZPixmap );
787cdf0e10cSrcweir             }
788cdf0e10cSrcweir         }
789cdf0e10cSrcweir         if( pImg == NULL )
790cdf0e10cSrcweir         {
791cdf0e10cSrcweir             GetDisplay()->GetXLib()->PopXErrorLevel();
792cdf0e10cSrcweir             return false;
793cdf0e10cSrcweir         }
794cdf0e10cSrcweir     }
795cdf0e10cSrcweir 
796cdf0e10cSrcweir     // prepare context
797cdf0e10cSrcweir     GC nGC = GetFontGC();
798cdf0e10cSrcweir     XGCValues aGCVal;
799cdf0e10cSrcweir     XGetGCValues( pDisplay, nGC, GCForeground, &aGCVal );
800cdf0e10cSrcweir 
801cdf0e10cSrcweir     unsigned long nOrigColor = XGetPixel( pImg, 0, 0 );
802cdf0e10cSrcweir     XPutPixel( pImg, 0, 0, aGCVal.foreground );
803cdf0e10cSrcweir     unsigned char aColor[4];
804cdf0e10cSrcweir     aColor[0] = pImg->data[0];
805cdf0e10cSrcweir     aColor[1] = pImg->data[1];
806cdf0e10cSrcweir     aColor[2] = pImg->data[2];
807cdf0e10cSrcweir     aColor[3] = pImg->data[3];
808cdf0e10cSrcweir     XPutPixel( pImg, 0, 0, nOrigColor );
809cdf0e10cSrcweir 
810cdf0e10cSrcweir     // work on XImage
811cdf0e10cSrcweir     const int bpp = pImg->bits_per_pixel >> 3;
812cdf0e10cSrcweir     for( nStart = 0; rLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); )
813cdf0e10cSrcweir     {
814cdf0e10cSrcweir         const RawBitmap* const pRawBitmap = rGlyphPeer.GetRawBitmap( rFont, nGlyph );
815cdf0e10cSrcweir         if( !pRawBitmap )
816cdf0e10cSrcweir             continue;
817cdf0e10cSrcweir 
818cdf0e10cSrcweir         const int nX1 = aPos.X() + pRawBitmap->mnXOffset;
819cdf0e10cSrcweir         const int nY1 = aPos.Y() + pRawBitmap->mnYOffset;
820cdf0e10cSrcweir 
821cdf0e10cSrcweir         if( (nX1 <= nXmax) && (int(nX1 + pRawBitmap->mnWidth) > nXmin)
822cdf0e10cSrcweir         &&  (nY1 <= nYmax) && (int(nY1 + pRawBitmap->mnHeight) > nYmin) )
823cdf0e10cSrcweir         {
824cdf0e10cSrcweir             const unsigned char* p10 = pRawBitmap->mpBits;
825cdf0e10cSrcweir             unsigned char* p20 = (unsigned char*)pImg->data;                // dest left limit
826cdf0e10cSrcweir             p20 += (nY1 - nYmin) * pImg->bytes_per_line;
827cdf0e10cSrcweir             unsigned char* p21 = p20 + (nX1 - nXmin + pImg->xoffset) * bpp;
828cdf0e10cSrcweir             int y = pRawBitmap->mnHeight;
829cdf0e10cSrcweir             if( y > nYmax - nY1 )
830cdf0e10cSrcweir                 y = nYmax - nY1 + 1;
831cdf0e10cSrcweir             while( --y >= 0 )
832cdf0e10cSrcweir             {
833cdf0e10cSrcweir                 if( p20 >= (unsigned char*)pImg->data )
834cdf0e10cSrcweir                 {
835cdf0e10cSrcweir                     unsigned char* const p22 = p20 + pImg->width * bpp; // dest right limit
836cdf0e10cSrcweir                     unsigned char* pDst = p21;
837cdf0e10cSrcweir                     const unsigned char* pSrc = p10;
838cdf0e10cSrcweir                     for( int x = pRawBitmap->mnWidth; (--x >= 0) && (p22 > pDst); ++pSrc )
839cdf0e10cSrcweir                     {
840cdf0e10cSrcweir                         if( (*pSrc == 0) || (p20 > pDst) )          // keep background
841cdf0e10cSrcweir                             pDst += bpp;
842cdf0e10cSrcweir                         else if( *pSrc == 0xFF )                    // paint foreground
843cdf0e10cSrcweir                         {
844cdf0e10cSrcweir                             const unsigned char* pColor = aColor;
845cdf0e10cSrcweir                             for( int z = bpp; --z >= 0; ++pColor, ++pDst )
846cdf0e10cSrcweir                                 *pDst = *pColor;
847cdf0e10cSrcweir                         }
848cdf0e10cSrcweir                         else                                        // blend fg into bg
849cdf0e10cSrcweir                         {
850cdf0e10cSrcweir                             const unsigned char* pColor = aColor;
851cdf0e10cSrcweir                             for( int z = bpp; --z >= 0; ++pColor, ++pDst )
852cdf0e10cSrcweir                                 // theoretically it should be *257) >> 16
853cdf0e10cSrcweir                                 // but the error is <0.4% worst case and we are in
854cdf0e10cSrcweir                                 // the innermost loop of very perf-sensitive code
855cdf0e10cSrcweir 
856cdf0e10cSrcweir                                 *pDst += (*pSrc * ((int)*pColor - *pDst)) >> 8;
857cdf0e10cSrcweir                         }
858cdf0e10cSrcweir                     }
859cdf0e10cSrcweir                 }
860cdf0e10cSrcweir                 p10 += pRawBitmap->mnScanlineSize;
861cdf0e10cSrcweir                 p20 += pImg->bytes_per_line;
862cdf0e10cSrcweir                 p21 += pImg->bytes_per_line;
863cdf0e10cSrcweir             }
864cdf0e10cSrcweir         }
865cdf0e10cSrcweir     }
866cdf0e10cSrcweir 
867cdf0e10cSrcweir     // put XImage
868cdf0e10cSrcweir     XPutImage( pDisplay, hDrawable_, nGC, pImg,
869cdf0e10cSrcweir         0, 0, nXmin, nYmin, (nXmax - nXmin + 1), (nYmax - nYmin + 1) );
870cdf0e10cSrcweir     XDestroyImage( pImg );
871cdf0e10cSrcweir 
872cdf0e10cSrcweir     GetDisplay()->GetXLib()->PopXErrorLevel();
873cdf0e10cSrcweir     return true;
874cdf0e10cSrcweir }
875cdf0e10cSrcweir 
876cdf0e10cSrcweir //--------------------------------------------------------------------------
877cdf0e10cSrcweir 
DrawServerSimpleFontString(const ServerFontLayout & rSalLayout)878cdf0e10cSrcweir void X11SalGraphics::DrawServerSimpleFontString( const ServerFontLayout& rSalLayout )
879cdf0e10cSrcweir {
880cdf0e10cSrcweir     ServerFont& rFont = rSalLayout.GetServerFont();
881cdf0e10cSrcweir     X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
882cdf0e10cSrcweir 
883cdf0e10cSrcweir     Display* pDisplay = GetXDisplay();
884cdf0e10cSrcweir     GC nGC = GetFontGC();
885cdf0e10cSrcweir 
886cdf0e10cSrcweir     XGCValues aGCVal;
887cdf0e10cSrcweir     aGCVal.fill_style = FillStippled;
888cdf0e10cSrcweir     aGCVal.line_width = 0;
889cdf0e10cSrcweir     GC tmpGC = XCreateGC( pDisplay, hDrawable_, GCFillStyle|GCLineWidth, &aGCVal );
890cdf0e10cSrcweir     XCopyGC( pDisplay, nGC, (1<<GCLastBit)-(1+GCFillStyle+GCLineWidth), tmpGC );
891cdf0e10cSrcweir 
892cdf0e10cSrcweir     Point aPos;
893cdf0e10cSrcweir     sal_GlyphId nGlyph;
894cdf0e10cSrcweir     for( int nStart = 0; rSalLayout.GetNextGlyphs( 1, &nGlyph, aPos, nStart ); )
895cdf0e10cSrcweir     {
896cdf0e10cSrcweir         // #i51924# avoid 32->16bit coordinate truncation problem in X11
897cdf0e10cSrcweir         // TODO: reevaluate once displays with >30000 pixels are available
898cdf0e10cSrcweir         if( aPos.X() >= 30000 || aPos.Y() >= 30000 )
899cdf0e10cSrcweir             continue;
900cdf0e10cSrcweir 
901cdf0e10cSrcweir         Pixmap aStipple = rGlyphPeer.GetPixmap( rFont, nGlyph, m_nScreen );
902cdf0e10cSrcweir         const GlyphMetric& rGM = rFont.GetGlyphMetric( nGlyph );
903cdf0e10cSrcweir 
904cdf0e10cSrcweir         if( aStipple != None )
905cdf0e10cSrcweir         {
906cdf0e10cSrcweir             const int nDestX    = aPos.X() + rGM.GetOffset().X();
907cdf0e10cSrcweir             const int nDestY    = aPos.Y() + rGM.GetOffset().Y();
908cdf0e10cSrcweir 
909cdf0e10cSrcweir             aGCVal.stipple      = aStipple;
910cdf0e10cSrcweir             aGCVal.ts_x_origin  = nDestX;
911cdf0e10cSrcweir             aGCVal.ts_y_origin  = nDestY;
912cdf0e10cSrcweir             XChangeGC( pDisplay, tmpGC, GCStipple|GCTileStipXOrigin|GCTileStipYOrigin, &aGCVal );
913cdf0e10cSrcweir 
914cdf0e10cSrcweir             const int nWidth    = rGM.GetSize().Width();
915cdf0e10cSrcweir             const int nHeight   = rGM.GetSize().Height();
916cdf0e10cSrcweir             XFillRectangle( pDisplay, hDrawable_, tmpGC, nDestX, nDestY, nWidth, nHeight );
917cdf0e10cSrcweir         }
918cdf0e10cSrcweir     }
919cdf0e10cSrcweir 
920cdf0e10cSrcweir     XFreeGC( pDisplay, tmpGC );
921cdf0e10cSrcweir }
922cdf0e10cSrcweir 
923cdf0e10cSrcweir //--------------------------------------------------------------------------
924cdf0e10cSrcweir 
DrawServerFontLayout(const ServerFontLayout & rLayout)925cdf0e10cSrcweir void X11SalGraphics::DrawServerFontLayout( const ServerFontLayout& rLayout )
926cdf0e10cSrcweir {
927cdf0e10cSrcweir     // draw complex text
928cdf0e10cSrcweir     ServerFont& rFont = rLayout.GetServerFont();
929cdf0e10cSrcweir 	const bool bVertical = rFont.GetFontSelData().mbVertical;
930cdf0e10cSrcweir 
931cdf0e10cSrcweir     if( !bVertical && CairoWrapper::get().isCairoRenderable(rFont) )
932cdf0e10cSrcweir         DrawCairoAAFontString( rLayout );
933cdf0e10cSrcweir     else
934cdf0e10cSrcweir     {
935cdf0e10cSrcweir         X11GlyphPeer& rGlyphPeer = X11GlyphCache::GetInstance().GetPeer();
936cdf0e10cSrcweir         if( rGlyphPeer.GetGlyphSet( rFont, m_nScreen ) )
937cdf0e10cSrcweir             DrawServerAAFontString( rLayout );
938cdf0e10cSrcweir         else if( !rGlyphPeer.ForcedAntialiasing( rFont, m_nScreen ) )
939cdf0e10cSrcweir             DrawServerSimpleFontString( rLayout );
940cdf0e10cSrcweir         else
941cdf0e10cSrcweir             DrawServerAAForcedString( rLayout );
942cdf0e10cSrcweir     }
943cdf0e10cSrcweir }
944cdf0e10cSrcweir 
945cdf0e10cSrcweir //--------------------------------------------------------------------------
946cdf0e10cSrcweir 
GetImplFontCharMap() const947cdf0e10cSrcweir const ImplFontCharMap* X11SalGraphics::GetImplFontCharMap() const
948cdf0e10cSrcweir {
949cdf0e10cSrcweir     if( !mpServerFont[0] )
950cdf0e10cSrcweir         return NULL;
951cdf0e10cSrcweir 
952cdf0e10cSrcweir     const ImplFontCharMap* pIFCMap = mpServerFont[0]->GetImplFontCharMap();
953cdf0e10cSrcweir     return pIFCMap;
954cdf0e10cSrcweir }
955cdf0e10cSrcweir 
956cdf0e10cSrcweir // ----------------------------------------------------------------------------
957cdf0e10cSrcweir //
958cdf0e10cSrcweir // SalGraphics
959cdf0e10cSrcweir //
960cdf0e10cSrcweir // ----------------------------------------------------------------------------
961cdf0e10cSrcweir 
SetFont(ImplFontSelectData * pEntry,int nFallbackLevel)962cdf0e10cSrcweir sal_uInt16 X11SalGraphics::SetFont( ImplFontSelectData *pEntry, int nFallbackLevel )
963cdf0e10cSrcweir {
964cdf0e10cSrcweir     sal_uInt16 nRetVal = 0;
965cdf0e10cSrcweir     if( !setFont( pEntry, nFallbackLevel ) )
966cdf0e10cSrcweir         nRetVal |= SAL_SETFONT_BADFONT;
967cdf0e10cSrcweir     if( bPrinter_ || (mpServerFont[ nFallbackLevel ] != NULL) )
968cdf0e10cSrcweir         nRetVal |= SAL_SETFONT_USEDRAWTEXTARRAY;
969cdf0e10cSrcweir     return nRetVal;
970cdf0e10cSrcweir }
971cdf0e10cSrcweir 
972cdf0e10cSrcweir // ----------------------------------------------------------------------------
973cdf0e10cSrcweir 
974cdf0e10cSrcweir void
SetTextColor(SalColor nSalColor)975cdf0e10cSrcweir X11SalGraphics::SetTextColor( SalColor nSalColor )
976cdf0e10cSrcweir {
977cdf0e10cSrcweir     if( nTextColor_	!= nSalColor )
978cdf0e10cSrcweir     {
979cdf0e10cSrcweir         nTextColor_     = nSalColor;
980cdf0e10cSrcweir         nTextPixel_     = GetPixel( nSalColor );
981cdf0e10cSrcweir         bFontGC_        = sal_False;
982cdf0e10cSrcweir     }
983cdf0e10cSrcweir }
984cdf0e10cSrcweir 
985cdf0e10cSrcweir // ----------------------------------------------------------------------------
986cdf0e10cSrcweir 
AddTempDevFont(ImplDevFontList * pFontList,const String & rFileURL,const String & rFontName)987cdf0e10cSrcweir bool X11SalGraphics::AddTempDevFont( ImplDevFontList* pFontList,
988cdf0e10cSrcweir     const String& rFileURL, const String& rFontName )
989cdf0e10cSrcweir {
990cdf0e10cSrcweir     // inform PSP font manager
991cdf0e10cSrcweir     rtl::OUString aUSystemPath;
992cdf0e10cSrcweir     OSL_VERIFY( !osl::FileBase::getSystemPathFromFileURL( rFileURL, aUSystemPath ) );
993cdf0e10cSrcweir     rtl_TextEncoding aEncoding = osl_getThreadTextEncoding();
994cdf0e10cSrcweir     OString aOFileName( OUStringToOString( aUSystemPath, aEncoding ) );
995cdf0e10cSrcweir     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
996cdf0e10cSrcweir     int nFontId = rMgr.addFontFile( aOFileName, 0 );
997cdf0e10cSrcweir     if( !nFontId )
998cdf0e10cSrcweir         return false;
999cdf0e10cSrcweir 
1000cdf0e10cSrcweir     // prepare font data
1001cdf0e10cSrcweir     psp::FastPrintFontInfo aInfo;
1002cdf0e10cSrcweir     rMgr.getFontFastInfo( nFontId, aInfo );
1003cdf0e10cSrcweir     aInfo.m_aFamilyName = rFontName;
1004cdf0e10cSrcweir 
1005cdf0e10cSrcweir     // inform glyph cache of new font
1006cdf0e10cSrcweir     ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo );
1007cdf0e10cSrcweir     aDFA.mnQuality += 5800;
1008cdf0e10cSrcweir 
1009cdf0e10cSrcweir     int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
1010cdf0e10cSrcweir     if( nFaceNum < 0 )
1011cdf0e10cSrcweir         nFaceNum = 0;
1012cdf0e10cSrcweir 
1013cdf0e10cSrcweir     GlyphCache& rGC = X11GlyphCache::GetInstance();
1014cdf0e10cSrcweir     const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
1015cdf0e10cSrcweir     rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA );
1016cdf0e10cSrcweir 
1017cdf0e10cSrcweir     // announce new font to device's font list
1018cdf0e10cSrcweir     rGC.AnnounceFonts( pFontList );
1019cdf0e10cSrcweir     return true;
1020cdf0e10cSrcweir }
1021cdf0e10cSrcweir 
1022cdf0e10cSrcweir // ----------------------------------------------------------------------------
1023cdf0e10cSrcweir 
1024cdf0e10cSrcweir void RegisterFontSubstitutors( ImplDevFontList* );
1025cdf0e10cSrcweir 
GetDevFontList(ImplDevFontList * pList)1026cdf0e10cSrcweir void X11SalGraphics::GetDevFontList( ImplDevFontList *pList )
1027cdf0e10cSrcweir {
1028cdf0e10cSrcweir     // prepare the GlyphCache using psprint's font infos
1029cdf0e10cSrcweir     X11GlyphCache& rGC = X11GlyphCache::GetInstance();
1030cdf0e10cSrcweir 
1031cdf0e10cSrcweir     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1032cdf0e10cSrcweir     ::std::list< psp::fontID > aList;
1033cdf0e10cSrcweir     ::std::list< psp::fontID >::iterator it;
1034cdf0e10cSrcweir     psp::FastPrintFontInfo aInfo;
1035cdf0e10cSrcweir     rMgr.getFontList( aList );
1036cdf0e10cSrcweir     for( it = aList.begin(); it != aList.end(); ++it )
1037cdf0e10cSrcweir     {
1038cdf0e10cSrcweir         if( !rMgr.getFontFastInfo( *it, aInfo ) )
1039cdf0e10cSrcweir             continue;
1040cdf0e10cSrcweir 
1041cdf0e10cSrcweir         // the GlyphCache must not bother with builtin fonts because
1042cdf0e10cSrcweir         // it cannot access or use them anyway
1043cdf0e10cSrcweir         if( aInfo.m_eType == psp::fonttype::Builtin )
1044cdf0e10cSrcweir             continue;
1045cdf0e10cSrcweir 
1046cdf0e10cSrcweir         // normalize face number to the GlyphCache
1047cdf0e10cSrcweir         int nFaceNum = rMgr.getFontFaceNumber( aInfo.m_nID );
1048cdf0e10cSrcweir         if( nFaceNum < 0 )
1049cdf0e10cSrcweir             nFaceNum = 0;
1050cdf0e10cSrcweir 
1051cdf0e10cSrcweir         // for fonts where extra kerning info can be provided on demand
1052cdf0e10cSrcweir         // an ExtraKernInfo object is supplied
1053cdf0e10cSrcweir         const ExtraKernInfo* pExtraKernInfo = NULL;
1054cdf0e10cSrcweir         if( aInfo.m_eType == psp::fonttype::Type1 )
1055cdf0e10cSrcweir             pExtraKernInfo = new PspKernInfo( *it );
1056cdf0e10cSrcweir 
1057cdf0e10cSrcweir         // inform GlyphCache about this font provided by the PsPrint subsystem
1058cdf0e10cSrcweir         ImplDevFontAttributes aDFA = PspGraphics::Info2DevFontAttributes( aInfo );
1059cdf0e10cSrcweir         aDFA.mnQuality += 4096;
1060cdf0e10cSrcweir         const rtl::OString& rFileName = rMgr.getFontFileSysPath( aInfo.m_nID );
1061cdf0e10cSrcweir         rGC.AddFontFile( rFileName, nFaceNum, aInfo.m_nID, aDFA, pExtraKernInfo );
1062cdf0e10cSrcweir    }
1063cdf0e10cSrcweir 
1064cdf0e10cSrcweir     // announce glyphcache fonts
1065cdf0e10cSrcweir     rGC.AnnounceFonts( pList );
1066cdf0e10cSrcweir 
1067cdf0e10cSrcweir     // register platform specific font substitutions if available
1068cdf0e10cSrcweir     if( rMgr.hasFontconfig() )
1069cdf0e10cSrcweir         RegisterFontSubstitutors( pList );
1070cdf0e10cSrcweir 
1071cdf0e10cSrcweir     ImplGetSVData()->maGDIData.mbNativeFontConfig = rMgr.hasFontconfig();
1072cdf0e10cSrcweir }
1073cdf0e10cSrcweir 
1074cdf0e10cSrcweir // ----------------------------------------------------------------------------
1075cdf0e10cSrcweir 
GetDevFontSubstList(OutputDevice *)1076cdf0e10cSrcweir void X11SalGraphics::GetDevFontSubstList( OutputDevice* )
1077cdf0e10cSrcweir {
1078cdf0e10cSrcweir     // no device specific font substitutions on X11 needed
1079cdf0e10cSrcweir }
1080cdf0e10cSrcweir 
1081cdf0e10cSrcweir // ----------------------------------------------------------------------------
1082cdf0e10cSrcweir 
cairosubcallback(void * pPattern)1083cdf0e10cSrcweir void cairosubcallback( void* pPattern )
1084cdf0e10cSrcweir {
1085cdf0e10cSrcweir     CairoWrapper& rCairo = CairoWrapper::get();
1086cdf0e10cSrcweir     if( !rCairo.isValid() )
1087cdf0e10cSrcweir         return;
1088cdf0e10cSrcweir     const StyleSettings& rStyleSettings = Application::GetSettings().GetStyleSettings();
1089cdf0e10cSrcweir     const void* pFontOptions = rStyleSettings.GetCairoFontOptions();
1090cdf0e10cSrcweir     if( !pFontOptions )
1091cdf0e10cSrcweir         return;
1092cdf0e10cSrcweir     rCairo.ft_font_options_substitute( pFontOptions, pPattern );
1093cdf0e10cSrcweir }
1094cdf0e10cSrcweir 
GetFCFontOptions(const ImplFontAttributes & rFontAttributes,int nSize,ImplFontOptions & rFontOptions)1095cdf0e10cSrcweir bool GetFCFontOptions( const ImplFontAttributes& rFontAttributes, int nSize,
1096cdf0e10cSrcweir 	ImplFontOptions& rFontOptions)
1097cdf0e10cSrcweir {
1098cdf0e10cSrcweir     // TODO: get rid of these insane enum-conversions
1099cdf0e10cSrcweir     // e.g. by using the classic vclenum values inside VCL
1100cdf0e10cSrcweir 
1101cdf0e10cSrcweir     psp::FastPrintFontInfo aInfo;
1102cdf0e10cSrcweir     // set family name
1103cdf0e10cSrcweir     aInfo.m_aFamilyName = rFontAttributes.GetFamilyName();
1104cdf0e10cSrcweir     // set italic
1105cdf0e10cSrcweir     switch( rFontAttributes.GetSlant() )
1106cdf0e10cSrcweir     {
1107cdf0e10cSrcweir         case ITALIC_NONE:
1108cdf0e10cSrcweir             aInfo.m_eItalic = psp::italic::Upright;
1109cdf0e10cSrcweir             break;
1110cdf0e10cSrcweir         case ITALIC_NORMAL:
1111cdf0e10cSrcweir             aInfo.m_eItalic = psp::italic::Italic;
1112cdf0e10cSrcweir             break;
1113cdf0e10cSrcweir         case ITALIC_OBLIQUE:
1114cdf0e10cSrcweir             aInfo.m_eItalic = psp::italic::Oblique;
1115cdf0e10cSrcweir             break;
1116cdf0e10cSrcweir         default:
1117cdf0e10cSrcweir             aInfo.m_eItalic = psp::italic::Unknown;
1118cdf0e10cSrcweir             break;
1119cdf0e10cSrcweir     }
1120cdf0e10cSrcweir     // set weight
1121cdf0e10cSrcweir     switch( rFontAttributes.GetWeight() )
1122cdf0e10cSrcweir     {
1123cdf0e10cSrcweir         case WEIGHT_THIN:
1124cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Thin;
1125cdf0e10cSrcweir             break;
1126cdf0e10cSrcweir         case WEIGHT_ULTRALIGHT:
1127cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::UltraLight;
1128cdf0e10cSrcweir             break;
1129cdf0e10cSrcweir         case WEIGHT_LIGHT:
1130cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Light;
1131cdf0e10cSrcweir             break;
1132cdf0e10cSrcweir         case WEIGHT_SEMILIGHT:
1133cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::SemiLight;
1134cdf0e10cSrcweir             break;
1135cdf0e10cSrcweir         case WEIGHT_NORMAL:
1136cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Normal;
1137cdf0e10cSrcweir             break;
1138cdf0e10cSrcweir         case WEIGHT_MEDIUM:
1139cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Medium;
1140cdf0e10cSrcweir             break;
1141cdf0e10cSrcweir         case WEIGHT_SEMIBOLD:
1142cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::SemiBold;
1143cdf0e10cSrcweir             break;
1144cdf0e10cSrcweir         case WEIGHT_BOLD:
1145cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Bold;
1146cdf0e10cSrcweir             break;
1147cdf0e10cSrcweir         case WEIGHT_ULTRABOLD:
1148cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::UltraBold;
1149cdf0e10cSrcweir             break;
1150cdf0e10cSrcweir         case WEIGHT_BLACK:
1151cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Black;
1152cdf0e10cSrcweir             break;
1153cdf0e10cSrcweir         default:
1154cdf0e10cSrcweir             aInfo.m_eWeight = psp::weight::Unknown;
1155cdf0e10cSrcweir             break;
1156cdf0e10cSrcweir     }
1157cdf0e10cSrcweir     // set width
1158cdf0e10cSrcweir     switch( rFontAttributes.GetWidthType() )
1159cdf0e10cSrcweir     {
1160cdf0e10cSrcweir         case WIDTH_ULTRA_CONDENSED:
1161cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::UltraCondensed;
1162cdf0e10cSrcweir             break;
1163cdf0e10cSrcweir         case WIDTH_EXTRA_CONDENSED:
1164cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::ExtraCondensed;
1165cdf0e10cSrcweir             break;
1166cdf0e10cSrcweir         case WIDTH_CONDENSED:
1167cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::Condensed;
1168cdf0e10cSrcweir             break;
1169cdf0e10cSrcweir         case WIDTH_SEMI_CONDENSED:
1170cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::SemiCondensed;
1171cdf0e10cSrcweir             break;
1172cdf0e10cSrcweir         case WIDTH_NORMAL:
1173cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::Normal;
1174cdf0e10cSrcweir             break;
1175cdf0e10cSrcweir         case WIDTH_SEMI_EXPANDED:
1176cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::SemiExpanded;
1177cdf0e10cSrcweir             break;
1178cdf0e10cSrcweir         case WIDTH_EXPANDED:
1179cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::Expanded;
1180cdf0e10cSrcweir             break;
1181cdf0e10cSrcweir         case WIDTH_EXTRA_EXPANDED:
1182cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::ExtraExpanded;
1183cdf0e10cSrcweir             break;
1184cdf0e10cSrcweir         case WIDTH_ULTRA_EXPANDED:
1185cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::UltraExpanded;
1186cdf0e10cSrcweir             break;
1187cdf0e10cSrcweir         default:
1188cdf0e10cSrcweir             aInfo.m_eWidth = psp::width::Unknown;
1189cdf0e10cSrcweir             break;
1190cdf0e10cSrcweir     }
1191cdf0e10cSrcweir 
1192cdf0e10cSrcweir     const psp::PrintFontManager& rPFM = psp::PrintFontManager::get();
1193cdf0e10cSrcweir     bool bOK = rPFM.getFontOptions( aInfo, nSize, cairosubcallback, rFontOptions);
1194cdf0e10cSrcweir     return bOK;
1195cdf0e10cSrcweir }
1196cdf0e10cSrcweir 
1197cdf0e10cSrcweir // ----------------------------------------------------------------------------
1198cdf0e10cSrcweir 
1199cdf0e10cSrcweir void
GetFontMetric(ImplFontMetricData * pMetric,int nFallbackLevel)1200cdf0e10cSrcweir X11SalGraphics::GetFontMetric( ImplFontMetricData *pMetric, int nFallbackLevel )
1201cdf0e10cSrcweir {
1202cdf0e10cSrcweir     if( nFallbackLevel >= MAX_FALLBACK )
1203cdf0e10cSrcweir         return;
1204cdf0e10cSrcweir 
1205cdf0e10cSrcweir     if( mpServerFont[nFallbackLevel] != NULL )
1206cdf0e10cSrcweir     {
1207cdf0e10cSrcweir         long rDummyFactor;
1208cdf0e10cSrcweir         mpServerFont[nFallbackLevel]->FetchFontMetric( *pMetric, rDummyFactor );
1209cdf0e10cSrcweir     }
1210cdf0e10cSrcweir }
1211cdf0e10cSrcweir 
1212cdf0e10cSrcweir // ---------------------------------------------------------------------------
1213cdf0e10cSrcweir 
1214cdf0e10cSrcweir sal_uLong
GetKernPairs(sal_uLong nPairs,ImplKernPairData * pKernPairs)1215cdf0e10cSrcweir X11SalGraphics::GetKernPairs( sal_uLong nPairs, ImplKernPairData *pKernPairs )
1216cdf0e10cSrcweir {
1217cdf0e10cSrcweir     if( ! bPrinter_ )
1218cdf0e10cSrcweir     {
1219cdf0e10cSrcweir         if( mpServerFont[0] != NULL )
1220cdf0e10cSrcweir         {
1221cdf0e10cSrcweir             ImplKernPairData* pTmpKernPairs;
1222cdf0e10cSrcweir             sal_uLong nGotPairs = mpServerFont[0]->GetKernPairs( &pTmpKernPairs );
1223cdf0e10cSrcweir             for( unsigned int i = 0; i < nPairs && i < nGotPairs; ++i )
1224cdf0e10cSrcweir                 pKernPairs[ i ] = pTmpKernPairs[ i ];
1225cdf0e10cSrcweir             delete[] pTmpKernPairs;
1226cdf0e10cSrcweir             return nGotPairs;
1227cdf0e10cSrcweir         }
1228cdf0e10cSrcweir     }
1229cdf0e10cSrcweir 	return 0;
1230cdf0e10cSrcweir }
1231cdf0e10cSrcweir 
1232cdf0e10cSrcweir // ---------------------------------------------------------------------------
1233cdf0e10cSrcweir 
GetGlyphBoundRect(sal_GlyphId aGlyphId,Rectangle & rRect)1234248a599fSHerbert Dürr bool X11SalGraphics::GetGlyphBoundRect( sal_GlyphId aGlyphId, Rectangle& rRect )
1235cdf0e10cSrcweir {
1236248a599fSHerbert Dürr     const int nLevel = aGlyphId >> GF_FONTSHIFT;
1237cdf0e10cSrcweir     if( nLevel >= MAX_FALLBACK )
1238248a599fSHerbert Dürr         return false;
1239cdf0e10cSrcweir 
1240cdf0e10cSrcweir     ServerFont* pSF = mpServerFont[ nLevel ];
1241cdf0e10cSrcweir     if( !pSF )
1242248a599fSHerbert Dürr         return false;
1243cdf0e10cSrcweir 
1244248a599fSHerbert Dürr     aGlyphId &= ~GF_FONTMASK;
1245248a599fSHerbert Dürr     const GlyphMetric& rGM = pSF->GetGlyphMetric( aGlyphId );
1246cdf0e10cSrcweir     rRect = Rectangle( rGM.GetOffset(), rGM.GetSize() );
1247248a599fSHerbert Dürr     return true;
1248cdf0e10cSrcweir }
1249cdf0e10cSrcweir 
1250cdf0e10cSrcweir // ---------------------------------------------------------------------------
1251cdf0e10cSrcweir 
GetGlyphOutline(sal_GlyphId aGlyphId,::basegfx::B2DPolyPolygon & rPolyPoly)1252248a599fSHerbert Dürr bool X11SalGraphics::GetGlyphOutline( sal_GlyphId aGlyphId,
1253cdf0e10cSrcweir     ::basegfx::B2DPolyPolygon& rPolyPoly )
1254cdf0e10cSrcweir {
1255248a599fSHerbert Dürr     const int nLevel = aGlyphId >> GF_FONTSHIFT;
1256cdf0e10cSrcweir     if( nLevel >= MAX_FALLBACK )
1257248a599fSHerbert Dürr         return false;
1258cdf0e10cSrcweir 
1259cdf0e10cSrcweir     ServerFont* pSF = mpServerFont[ nLevel ];
1260cdf0e10cSrcweir     if( !pSF )
1261248a599fSHerbert Dürr         return false;
1262cdf0e10cSrcweir 
1263248a599fSHerbert Dürr     aGlyphId &= ~GF_FONTMASK;
1264248a599fSHerbert Dürr     bool bOK = pSF->GetGlyphOutline( aGlyphId, rPolyPoly );
1265248a599fSHerbert Dürr     return bOK;
1266cdf0e10cSrcweir }
1267cdf0e10cSrcweir 
1268cdf0e10cSrcweir //--------------------------------------------------------------------------
1269cdf0e10cSrcweir 
GetTextLayout(ImplLayoutArgs & rArgs,int nFallbackLevel)1270cdf0e10cSrcweir SalLayout* X11SalGraphics::GetTextLayout( ImplLayoutArgs& rArgs, int nFallbackLevel )
1271cdf0e10cSrcweir {
1272cdf0e10cSrcweir     SalLayout* pLayout = NULL;
1273cdf0e10cSrcweir 
1274cdf0e10cSrcweir     if( mpServerFont[ nFallbackLevel ]
1275cdf0e10cSrcweir     && !(rArgs.mnFlags & SAL_LAYOUT_DISABLE_GLYPH_PROCESSING) )
1276cdf0e10cSrcweir     {
1277cdf0e10cSrcweir #ifdef ENABLE_GRAPHITE
1278cdf0e10cSrcweir         // Is this a Graphite font?
1279cdf0e10cSrcweir         if (!bDisableGraphite_ &&
1280cdf0e10cSrcweir             GraphiteFontAdaptor::IsGraphiteEnabledFont(*mpServerFont[nFallbackLevel]))
1281cdf0e10cSrcweir         {
1282*8a718ffcSHerbert Dürr             sal_Int32 xdpi = GetDisplay()->GetResolution().A();
1283*8a718ffcSHerbert Dürr             sal_Int32 ydpi = GetDisplay()->GetResolution().B();
1284cdf0e10cSrcweir 
1285cdf0e10cSrcweir             GraphiteFontAdaptor * pGrfont = new GraphiteFontAdaptor( *mpServerFont[nFallbackLevel], xdpi, ydpi);
1286cdf0e10cSrcweir             if (!pGrfont) return NULL;
1287cdf0e10cSrcweir             pLayout = new GraphiteServerFontLayout(pGrfont);
1288cdf0e10cSrcweir         }
1289cdf0e10cSrcweir         else
1290cdf0e10cSrcweir #endif
1291cdf0e10cSrcweir             pLayout = new ServerFontLayout( *mpServerFont[ nFallbackLevel ] );
1292cdf0e10cSrcweir     }
1293cdf0e10cSrcweir 
1294cdf0e10cSrcweir     return pLayout;
1295cdf0e10cSrcweir }
1296cdf0e10cSrcweir 
1297cdf0e10cSrcweir //--------------------------------------------------------------------------
1298cdf0e10cSrcweir 
GetSysFontData(int nFallbacklevel) const1299cdf0e10cSrcweir SystemFontData X11SalGraphics::GetSysFontData( int nFallbacklevel ) const
1300cdf0e10cSrcweir {
1301cdf0e10cSrcweir     SystemFontData aSysFontData;
1302cdf0e10cSrcweir     aSysFontData.nSize = sizeof( SystemFontData );
1303cdf0e10cSrcweir     aSysFontData.nFontId = 0;
1304cdf0e10cSrcweir 
1305cdf0e10cSrcweir     if (nFallbacklevel >= MAX_FALLBACK) nFallbacklevel = MAX_FALLBACK - 1;
1306cdf0e10cSrcweir     if (nFallbacklevel < 0 ) nFallbacklevel = 0;
1307cdf0e10cSrcweir 
1308cdf0e10cSrcweir     if (mpServerFont[nFallbacklevel] != NULL)
1309cdf0e10cSrcweir     {
1310cdf0e10cSrcweir         ServerFont* rFont = mpServerFont[nFallbacklevel];
1311cdf0e10cSrcweir         aSysFontData.nFontId = rFont->GetFtFace();
1312cdf0e10cSrcweir         aSysFontData.nFontFlags = rFont->GetLoadFlags();
1313cdf0e10cSrcweir         aSysFontData.bFakeBold = rFont->NeedsArtificialBold();
1314cdf0e10cSrcweir         aSysFontData.bFakeItalic = rFont->NeedsArtificialItalic();
1315cdf0e10cSrcweir         aSysFontData.bAntialias = rFont->GetAntialiasAdvice();
1316cdf0e10cSrcweir         aSysFontData.bVerticalCharacterType = rFont->GetFontSelData().mbVertical;
1317cdf0e10cSrcweir     }
1318cdf0e10cSrcweir 
1319cdf0e10cSrcweir     return aSysFontData;
1320cdf0e10cSrcweir }
1321cdf0e10cSrcweir 
1322cdf0e10cSrcweir //--------------------------------------------------------------------------
1323cdf0e10cSrcweir 
CreateFontSubset(const rtl::OUString & rToFile,const ImplFontData * pFont,sal_GlyphId * pGlyphIds,sal_uInt8 * pEncoding,sal_Int32 * pWidths,int nGlyphCount,FontSubsetInfo & rInfo)1324cdf0e10cSrcweir sal_Bool X11SalGraphics::CreateFontSubset(
1325cdf0e10cSrcweir                                    const rtl::OUString& rToFile,
1326cdf0e10cSrcweir                                    const ImplFontData* pFont,
1327248a599fSHerbert Dürr                                    sal_GlyphId* pGlyphIds,
1328cdf0e10cSrcweir                                    sal_uInt8* pEncoding,
1329cdf0e10cSrcweir                                    sal_Int32* pWidths,
1330cdf0e10cSrcweir                                    int nGlyphCount,
1331cdf0e10cSrcweir                                    FontSubsetInfo& rInfo
1332cdf0e10cSrcweir                                    )
1333cdf0e10cSrcweir {
1334cdf0e10cSrcweir     // in this context the pFont->GetFontId() is a valid PSP
1335cdf0e10cSrcweir     // font since they are the only ones left after the PDF
1336cdf0e10cSrcweir     // export has filtered its list of subsettable fonts (for
1337cdf0e10cSrcweir     // which this method was created). The correct way would
1338cdf0e10cSrcweir     // be to have the GlyphCache search for the ImplFontData pFont
1339cdf0e10cSrcweir     psp::fontID aFont = pFont->GetFontId();
1340cdf0e10cSrcweir 
1341cdf0e10cSrcweir     psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1342cdf0e10cSrcweir     bool bSuccess = rMgr.createFontSubset( rInfo,
1343cdf0e10cSrcweir                                  aFont,
1344cdf0e10cSrcweir                                  rToFile,
1345248a599fSHerbert Dürr                                  pGlyphIds,
1346cdf0e10cSrcweir                                  pEncoding,
1347cdf0e10cSrcweir                                  pWidths,
1348cdf0e10cSrcweir                                  nGlyphCount );
1349cdf0e10cSrcweir     return bSuccess;
1350cdf0e10cSrcweir }
1351cdf0e10cSrcweir 
1352cdf0e10cSrcweir //--------------------------------------------------------------------------
1353cdf0e10cSrcweir 
GetEmbedFontData(const ImplFontData * pFont,const sal_Ucs * pUnicodes,sal_Int32 * pWidths,FontSubsetInfo & rInfo,long * pDataLen)1354cdf0e10cSrcweir const void* X11SalGraphics::GetEmbedFontData( const ImplFontData* pFont, const sal_Ucs* pUnicodes, sal_Int32* pWidths, FontSubsetInfo& rInfo, long* pDataLen )
1355cdf0e10cSrcweir {
1356cdf0e10cSrcweir     // in this context the pFont->GetFontId() is a valid PSP
1357cdf0e10cSrcweir     // font since they are the only ones left after the PDF
1358cdf0e10cSrcweir     // export has filtered its list of subsettable fonts (for
1359cdf0e10cSrcweir     // which this method was created). The correct way would
1360cdf0e10cSrcweir     // be to have the GlyphCache search for the ImplFontData pFont
1361cdf0e10cSrcweir     psp::fontID aFont = pFont->GetFontId();
1362cdf0e10cSrcweir     return PspGraphics::DoGetEmbedFontData( aFont, pUnicodes, pWidths, rInfo, pDataLen );
1363cdf0e10cSrcweir }
1364cdf0e10cSrcweir 
1365cdf0e10cSrcweir //--------------------------------------------------------------------------
1366cdf0e10cSrcweir 
FreeEmbedFontData(const void * pData,long nLen)1367cdf0e10cSrcweir void X11SalGraphics::FreeEmbedFontData( const void* pData, long nLen )
1368cdf0e10cSrcweir {
1369cdf0e10cSrcweir     PspGraphics::DoFreeEmbedFontData( pData, nLen );
1370cdf0e10cSrcweir }
1371cdf0e10cSrcweir 
1372cdf0e10cSrcweir //--------------------------------------------------------------------------
1373cdf0e10cSrcweir 
GetFontEncodingVector(const ImplFontData * pFont,const Ucs2OStrMap ** pNonEncoded)1374cdf0e10cSrcweir const Ucs2SIntMap* X11SalGraphics::GetFontEncodingVector( const ImplFontData* pFont, const Ucs2OStrMap** pNonEncoded )
1375cdf0e10cSrcweir {
1376cdf0e10cSrcweir     // in this context the pFont->GetFontId() is a valid PSP
1377cdf0e10cSrcweir     // font since they are the only ones left after the PDF
1378cdf0e10cSrcweir     // export has filtered its list of subsettable fonts (for
1379cdf0e10cSrcweir     // which this method was created). The correct way would
1380cdf0e10cSrcweir     // be to have the GlyphCache search for the ImplFontData pFont
1381cdf0e10cSrcweir     psp::fontID aFont = pFont->GetFontId();
1382cdf0e10cSrcweir     return PspGraphics::DoGetFontEncodingVector( aFont, pNonEncoded );
1383cdf0e10cSrcweir }
1384cdf0e10cSrcweir 
1385cdf0e10cSrcweir //--------------------------------------------------------------------------
1386cdf0e10cSrcweir 
GetGlyphWidths(const ImplFontData * pFont,bool bVertical,Int32Vector & rWidths,Ucs2UIntMap & rUnicodeEnc)1387cdf0e10cSrcweir void X11SalGraphics::GetGlyphWidths( const ImplFontData* pFont,
1388cdf0e10cSrcweir                                    bool bVertical,
1389cdf0e10cSrcweir                                    Int32Vector& rWidths,
1390cdf0e10cSrcweir                                    Ucs2UIntMap& rUnicodeEnc )
1391cdf0e10cSrcweir {
1392cdf0e10cSrcweir     // in this context the pFont->GetFontId() is a valid PSP
1393cdf0e10cSrcweir     // font since they are the only ones left after the PDF
1394cdf0e10cSrcweir     // export has filtered its list of subsettable fonts (for
1395cdf0e10cSrcweir     // which this method was created). The correct way would
1396cdf0e10cSrcweir     // be to have the GlyphCache search for the ImplFontData pFont
1397cdf0e10cSrcweir     psp::fontID aFont = pFont->GetFontId();
1398cdf0e10cSrcweir     PspGraphics::DoGetGlyphWidths( aFont, bVertical, rWidths, rUnicodeEnc );
1399cdf0e10cSrcweir }
1400cdf0e10cSrcweir 
1401cdf0e10cSrcweir // ===========================================================================
1402cdf0e10cSrcweir // platform specific font substitution hooks
1403cdf0e10cSrcweir 
1404cdf0e10cSrcweir class FcPreMatchSubstititution
1405cdf0e10cSrcweir :   public ImplPreMatchFontSubstitution
1406cdf0e10cSrcweir {
1407cdf0e10cSrcweir public:
1408cdf0e10cSrcweir     bool FindFontSubstitute( ImplFontSelectData& ) const;
1409cdf0e10cSrcweir };
1410cdf0e10cSrcweir 
1411cdf0e10cSrcweir class FcGlyphFallbackSubstititution
1412cdf0e10cSrcweir :    public ImplGlyphFallbackFontSubstitution
1413cdf0e10cSrcweir {
1414cdf0e10cSrcweir     // TODO: add a cache
1415cdf0e10cSrcweir public:
1416cdf0e10cSrcweir     bool FindFontSubstitute( ImplFontSelectData&, OUString& rMissingCodes ) const;
1417cdf0e10cSrcweir };
1418cdf0e10cSrcweir 
RegisterFontSubstitutors(ImplDevFontList * pList)1419cdf0e10cSrcweir void RegisterFontSubstitutors( ImplDevFontList* pList )
1420cdf0e10cSrcweir {
1421cdf0e10cSrcweir     // init font substitution defaults
1422cdf0e10cSrcweir     int nDisableBits = 0;
1423cdf0e10cSrcweir #ifdef SOLARIS
1424cdf0e10cSrcweir     nDisableBits = 1; // disable "font fallback" here on default
1425cdf0e10cSrcweir #endif
1426cdf0e10cSrcweir     // apply the environment variable if any
1427cdf0e10cSrcweir     const char* pEnvStr = ::getenv( "SAL_DISABLE_FC_SUBST" );
1428cdf0e10cSrcweir     if( pEnvStr )
1429cdf0e10cSrcweir     {
1430cdf0e10cSrcweir         if( (*pEnvStr >= '0') && (*pEnvStr <= '9') )
1431cdf0e10cSrcweir             nDisableBits = (*pEnvStr - '0');
1432cdf0e10cSrcweir         else
1433cdf0e10cSrcweir             nDisableBits = ~0U; // no specific bits set: disable all
1434cdf0e10cSrcweir     }
1435cdf0e10cSrcweir 
1436cdf0e10cSrcweir     // register font fallback substitutions (unless disabled by bit0)
1437cdf0e10cSrcweir     if( (nDisableBits & 1) == 0 )
1438cdf0e10cSrcweir     {
1439cdf0e10cSrcweir         static FcPreMatchSubstititution aSubstPreMatch;
1440cdf0e10cSrcweir         pList->SetPreMatchHook( &aSubstPreMatch );
1441cdf0e10cSrcweir     }
1442cdf0e10cSrcweir 
1443cdf0e10cSrcweir     // register glyph fallback substitutions (unless disabled by bit1)
1444cdf0e10cSrcweir     if( (nDisableBits & 2) == 0 )
1445cdf0e10cSrcweir     {
1446cdf0e10cSrcweir         static FcGlyphFallbackSubstititution aSubstFallback;
1447cdf0e10cSrcweir         pList->SetFallbackHook( &aSubstFallback );
1448cdf0e10cSrcweir     }
1449cdf0e10cSrcweir }
1450cdf0e10cSrcweir 
1451cdf0e10cSrcweir // -----------------------------------------------------------------------
1452cdf0e10cSrcweir 
GetFcSubstitute(const ImplFontSelectData & rFontSelData,OUString & rMissingCodes)1453cdf0e10cSrcweir static ImplFontSelectData GetFcSubstitute(const ImplFontSelectData &rFontSelData, OUString& rMissingCodes )
1454cdf0e10cSrcweir {
1455cdf0e10cSrcweir     ImplFontSelectData aRet(rFontSelData);
1456cdf0e10cSrcweir 
1457cdf0e10cSrcweir     const rtl::OString aLangAttrib = MsLangId::convertLanguageToIsoByteString( rFontSelData.meLanguage );
1458cdf0e10cSrcweir 
1459cdf0e10cSrcweir     psp::italic::type eItalic = psp::italic::Unknown;
1460cdf0e10cSrcweir     if( rFontSelData.GetSlant() != ITALIC_DONTKNOW )
1461cdf0e10cSrcweir     {
1462cdf0e10cSrcweir         switch( rFontSelData.GetSlant() )
1463cdf0e10cSrcweir         {
1464cdf0e10cSrcweir             case ITALIC_NONE:    eItalic = psp::italic::Upright; break;
1465cdf0e10cSrcweir             case ITALIC_NORMAL:  eItalic = psp::italic::Italic; break;
1466cdf0e10cSrcweir             case ITALIC_OBLIQUE: eItalic = psp::italic::Oblique; break;
1467cdf0e10cSrcweir             default:
1468cdf0e10cSrcweir                 break;
1469cdf0e10cSrcweir         }
1470cdf0e10cSrcweir     }
1471cdf0e10cSrcweir 
1472cdf0e10cSrcweir     psp::weight::type eWeight = psp::weight::Unknown;
1473cdf0e10cSrcweir     if( rFontSelData.GetWeight() != WEIGHT_DONTKNOW )
1474cdf0e10cSrcweir     {
1475cdf0e10cSrcweir         switch( rFontSelData.GetWeight() )
1476cdf0e10cSrcweir         {
1477cdf0e10cSrcweir             case WEIGHT_THIN:		eWeight = psp::weight::Thin; break;
1478cdf0e10cSrcweir             case WEIGHT_ULTRALIGHT:	eWeight = psp::weight::UltraLight; break;
1479cdf0e10cSrcweir             case WEIGHT_LIGHT:		eWeight = psp::weight::Light; break;
1480cdf0e10cSrcweir             case WEIGHT_SEMILIGHT:	eWeight = psp::weight::SemiLight; break;
1481cdf0e10cSrcweir             case WEIGHT_NORMAL:		eWeight = psp::weight::Normal; break;
1482cdf0e10cSrcweir             case WEIGHT_MEDIUM:		eWeight = psp::weight::Medium; break;
1483cdf0e10cSrcweir             case WEIGHT_SEMIBOLD:	eWeight = psp::weight::SemiBold; break;
1484cdf0e10cSrcweir             case WEIGHT_BOLD:		eWeight = psp::weight::Bold; break;
1485cdf0e10cSrcweir             case WEIGHT_ULTRABOLD:	eWeight = psp::weight::UltraBold; break;
1486cdf0e10cSrcweir             case WEIGHT_BLACK:		eWeight = psp::weight::Black; break;
1487cdf0e10cSrcweir             default:
1488cdf0e10cSrcweir                 break;
1489cdf0e10cSrcweir         }
1490cdf0e10cSrcweir     }
1491cdf0e10cSrcweir 
1492cdf0e10cSrcweir     psp::width::type eWidth = psp::width::Unknown;
1493cdf0e10cSrcweir     if( rFontSelData.GetWidthType() != WIDTH_DONTKNOW )
1494cdf0e10cSrcweir     {
1495cdf0e10cSrcweir         switch( rFontSelData.GetWidthType() )
1496cdf0e10cSrcweir         {
1497cdf0e10cSrcweir             case WIDTH_ULTRA_CONDENSED:	eWidth = psp::width::UltraCondensed; break;
1498cdf0e10cSrcweir             case WIDTH_EXTRA_CONDENSED: eWidth = psp::width::ExtraCondensed; break;
1499cdf0e10cSrcweir             case WIDTH_CONDENSED:	eWidth = psp::width::Condensed; break;
1500cdf0e10cSrcweir             case WIDTH_SEMI_CONDENSED:	eWidth = psp::width::SemiCondensed; break;
1501cdf0e10cSrcweir             case WIDTH_NORMAL:		eWidth = psp::width::Normal; break;
1502cdf0e10cSrcweir             case WIDTH_SEMI_EXPANDED:	eWidth = psp::width::SemiExpanded; break;
1503cdf0e10cSrcweir             case WIDTH_EXPANDED:	eWidth = psp::width::Expanded; break;
1504cdf0e10cSrcweir             case WIDTH_EXTRA_EXPANDED:	eWidth = psp::width::ExtraExpanded; break;
1505cdf0e10cSrcweir             case WIDTH_ULTRA_EXPANDED:	eWidth = psp::width::UltraExpanded; break;
1506cdf0e10cSrcweir             default:
1507cdf0e10cSrcweir                 break;
1508cdf0e10cSrcweir         }
1509cdf0e10cSrcweir     }
1510cdf0e10cSrcweir 
1511cdf0e10cSrcweir     psp::pitch::type ePitch = psp::pitch::Unknown;
1512cdf0e10cSrcweir     if( rFontSelData.GetPitch() != PITCH_DONTKNOW )
1513cdf0e10cSrcweir     {
1514cdf0e10cSrcweir         switch( rFontSelData.GetPitch() )
1515cdf0e10cSrcweir         {
1516cdf0e10cSrcweir             case PITCH_FIXED:    ePitch=psp::pitch::Fixed; break;
1517cdf0e10cSrcweir             case PITCH_VARIABLE: ePitch=psp::pitch::Variable; break;
1518cdf0e10cSrcweir             default:
1519cdf0e10cSrcweir                 break;
1520cdf0e10cSrcweir         }
1521cdf0e10cSrcweir     }
1522cdf0e10cSrcweir 
1523cdf0e10cSrcweir     const psp::PrintFontManager& rMgr = psp::PrintFontManager::get();
1524cdf0e10cSrcweir     aRet.maSearchName = rMgr.Substitute( rFontSelData.maTargetName, rMissingCodes, aLangAttrib, eItalic, eWeight, eWidth, ePitch);
1525cdf0e10cSrcweir 
1526cdf0e10cSrcweir     switch (eItalic)
1527cdf0e10cSrcweir     {
1528cdf0e10cSrcweir         case psp::italic::Upright: aRet.meItalic = ITALIC_NONE; break;
1529cdf0e10cSrcweir         case psp::italic::Italic: aRet.meItalic = ITALIC_NORMAL; break;
1530cdf0e10cSrcweir         case psp::italic::Oblique: aRet.meItalic = ITALIC_OBLIQUE; break;
1531cdf0e10cSrcweir         default:
1532cdf0e10cSrcweir             break;
1533cdf0e10cSrcweir     }
1534cdf0e10cSrcweir 
1535cdf0e10cSrcweir     switch (eWeight)
1536cdf0e10cSrcweir     {
1537cdf0e10cSrcweir         case psp::weight::Thin: aRet.meWeight = WEIGHT_THIN; break;
1538cdf0e10cSrcweir         case psp::weight::UltraLight: aRet.meWeight = WEIGHT_ULTRALIGHT; break;
1539cdf0e10cSrcweir         case psp::weight::Light: aRet.meWeight = WEIGHT_LIGHT; break;
1540cdf0e10cSrcweir         case psp::weight::SemiLight: aRet.meWeight = WEIGHT_SEMILIGHT; break;
1541cdf0e10cSrcweir         case psp::weight::Normal: aRet.meWeight = WEIGHT_NORMAL; break;
1542cdf0e10cSrcweir         case psp::weight::Medium: aRet.meWeight = WEIGHT_MEDIUM; break;
1543cdf0e10cSrcweir         case psp::weight::SemiBold: aRet.meWeight = WEIGHT_SEMIBOLD; break;
1544cdf0e10cSrcweir         case psp::weight::Bold: aRet.meWeight = WEIGHT_BOLD; break;
1545cdf0e10cSrcweir         case psp::weight::UltraBold: aRet.meWeight = WEIGHT_ULTRABOLD; break;
1546cdf0e10cSrcweir         case psp::weight::Black: aRet.meWeight = WEIGHT_BLACK; break;
1547cdf0e10cSrcweir         default:
1548cdf0e10cSrcweir                 break;
1549cdf0e10cSrcweir     }
1550cdf0e10cSrcweir 
1551cdf0e10cSrcweir     switch (eWidth)
1552cdf0e10cSrcweir     {
1553cdf0e10cSrcweir         case psp::width::UltraCondensed: aRet.meWidthType = WIDTH_ULTRA_CONDENSED; break;
1554cdf0e10cSrcweir         case psp::width::ExtraCondensed: aRet.meWidthType = WIDTH_EXTRA_CONDENSED; break;
1555cdf0e10cSrcweir         case psp::width::Condensed: aRet.meWidthType = WIDTH_CONDENSED; break;
1556cdf0e10cSrcweir         case psp::width::SemiCondensed: aRet.meWidthType = WIDTH_SEMI_CONDENSED; break;
1557cdf0e10cSrcweir         case psp::width::Normal: aRet.meWidthType = WIDTH_NORMAL; break;
1558cdf0e10cSrcweir         case psp::width::SemiExpanded: aRet.meWidthType = WIDTH_SEMI_EXPANDED; break;
1559cdf0e10cSrcweir         case psp::width::Expanded: aRet.meWidthType = WIDTH_EXPANDED; break;
1560cdf0e10cSrcweir         case psp::width::ExtraExpanded: aRet.meWidthType = WIDTH_EXTRA_EXPANDED; break;
1561cdf0e10cSrcweir         case psp::width::UltraExpanded: aRet.meWidthType = WIDTH_ULTRA_EXPANDED; break;
1562cdf0e10cSrcweir         default:
1563cdf0e10cSrcweir             break;
1564cdf0e10cSrcweir     }
1565cdf0e10cSrcweir 
1566cdf0e10cSrcweir     switch (ePitch)
1567cdf0e10cSrcweir     {
1568cdf0e10cSrcweir         case psp::pitch::Fixed: aRet.mePitch = PITCH_FIXED; break;
1569cdf0e10cSrcweir         case psp::pitch::Variable: aRet.mePitch = PITCH_VARIABLE; break;
1570cdf0e10cSrcweir         default:
1571cdf0e10cSrcweir             break;
1572cdf0e10cSrcweir     }
1573cdf0e10cSrcweir 
1574cdf0e10cSrcweir     return aRet;
1575cdf0e10cSrcweir }
1576cdf0e10cSrcweir 
1577cdf0e10cSrcweir namespace
1578cdf0e10cSrcweir {
uselessmatch(const ImplFontSelectData & rOrig,const ImplFontSelectData & rNew)1579cdf0e10cSrcweir     bool uselessmatch(const ImplFontSelectData &rOrig, const ImplFontSelectData &rNew)
1580cdf0e10cSrcweir     {
1581cdf0e10cSrcweir         return
1582cdf0e10cSrcweir           (
1583cdf0e10cSrcweir             rOrig.maTargetName == rNew.maSearchName &&
1584cdf0e10cSrcweir             rOrig.meWeight == rNew.meWeight &&
1585cdf0e10cSrcweir             rOrig.meItalic == rNew.meItalic &&
1586cdf0e10cSrcweir             rOrig.mePitch == rNew.mePitch &&
1587cdf0e10cSrcweir             rOrig.meWidthType == rNew.meWidthType
1588cdf0e10cSrcweir           );
1589cdf0e10cSrcweir     }
1590cdf0e10cSrcweir }
1591cdf0e10cSrcweir 
1592cdf0e10cSrcweir //--------------------------------------------------------------------------
1593cdf0e10cSrcweir 
FindFontSubstitute(ImplFontSelectData & rFontSelData) const1594cdf0e10cSrcweir bool FcPreMatchSubstititution::FindFontSubstitute( ImplFontSelectData &rFontSelData ) const
1595cdf0e10cSrcweir {
1596cdf0e10cSrcweir     // We dont' actually want to talk to Fontconfig at all for symbol fonts
1597cdf0e10cSrcweir     if( rFontSelData.IsSymbolFont() )
1598cdf0e10cSrcweir         return false;
1599cdf0e10cSrcweir     // StarSymbol is a unicode font, but it still deserves the symbol flag
1600cdf0e10cSrcweir     if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
1601cdf0e10cSrcweir     ||  0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
1602cdf0e10cSrcweir         return false;
1603cdf0e10cSrcweir 
1604cdf0e10cSrcweir     rtl::OUString aDummy;
1605cdf0e10cSrcweir     const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, aDummy );
1606cdf0e10cSrcweir     // TODO: cache the font substitution suggestion
1607cdf0e10cSrcweir     // FC doing it would be preferable because it knows the invariables
1608cdf0e10cSrcweir     // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
1609cdf0e10cSrcweir     // whereas we would have to check for every size or attribute
1610cdf0e10cSrcweir     if( !aOut.maSearchName.Len() )
1611cdf0e10cSrcweir         return false;
1612cdf0e10cSrcweir 
1613cdf0e10cSrcweir     const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
1614cdf0e10cSrcweir 
1615cdf0e10cSrcweir #ifdef DEBUG
1616cdf0e10cSrcweir     const ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
1617cdf0e10cSrcweir     const ByteString aSubstName( aOut.maSearchName, RTL_TEXTENCODING_UTF8 );
1618cdf0e10cSrcweir     printf( "FcPreMatchSubstititution \"%s\" bipw=%d%d%d%d -> ",
1619cdf0e10cSrcweir         aOrigName.GetBuffer(), rFontSelData.meWeight, rFontSelData.meItalic,
1620cdf0e10cSrcweir         rFontSelData.mePitch, rFontSelData.meWidthType );
1621cdf0e10cSrcweir     if( !bHaveSubstitute )
1622cdf0e10cSrcweir         printf( "no substitute available\n" );
1623cdf0e10cSrcweir     else
1624cdf0e10cSrcweir         printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.GetBuffer(),
1625cdf0e10cSrcweir 	    aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
1626cdf0e10cSrcweir #endif
1627cdf0e10cSrcweir 
1628cdf0e10cSrcweir     if( bHaveSubstitute )
1629cdf0e10cSrcweir         rFontSelData = aOut;
1630cdf0e10cSrcweir 
1631cdf0e10cSrcweir     return bHaveSubstitute;
1632cdf0e10cSrcweir }
1633cdf0e10cSrcweir 
1634cdf0e10cSrcweir // -----------------------------------------------------------------------
1635cdf0e10cSrcweir 
FindFontSubstitute(ImplFontSelectData & rFontSelData,rtl::OUString & rMissingCodes) const1636cdf0e10cSrcweir bool FcGlyphFallbackSubstititution::FindFontSubstitute( ImplFontSelectData& rFontSelData,
1637cdf0e10cSrcweir     rtl::OUString& rMissingCodes ) const
1638cdf0e10cSrcweir {
1639cdf0e10cSrcweir     // We dont' actually want to talk to Fontconfig at all for symbol fonts
1640cdf0e10cSrcweir     if( rFontSelData.IsSymbolFont() )
1641cdf0e10cSrcweir 	return false;
1642cdf0e10cSrcweir     // StarSymbol is a unicode font, but it still deserves the symbol flag
1643cdf0e10cSrcweir     if( 0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "starsymbol", 10)
1644cdf0e10cSrcweir     ||  0 == rFontSelData.maSearchName.CompareIgnoreCaseToAscii( "opensymbol", 10) )
1645cdf0e10cSrcweir         return false;
1646cdf0e10cSrcweir 
1647cdf0e10cSrcweir     const ImplFontSelectData aOut = GetFcSubstitute( rFontSelData, rMissingCodes );
1648cdf0e10cSrcweir     // TODO: cache the unicode + srcfont specific result
1649cdf0e10cSrcweir     // FC doing it would be preferable because it knows the invariables
1650cdf0e10cSrcweir     // e.g. FC knows the FC rule that all Arial gets replaced by LiberationSans
1651cdf0e10cSrcweir     // whereas we would have to check for every size or attribute
1652cdf0e10cSrcweir     if( !aOut.maSearchName.Len() )
1653cdf0e10cSrcweir         return false;
1654cdf0e10cSrcweir 
1655cdf0e10cSrcweir     const bool bHaveSubstitute = !uselessmatch( rFontSelData, aOut );
1656cdf0e10cSrcweir 
1657cdf0e10cSrcweir #ifdef DEBUG
1658cdf0e10cSrcweir     const ByteString aOrigName( rFontSelData.maTargetName, RTL_TEXTENCODING_UTF8 );
1659cdf0e10cSrcweir     const ByteString aSubstName( aOut.maSearchName, RTL_TEXTENCODING_UTF8 );
1660cdf0e10cSrcweir     printf( "FcGFSubstititution \"%s\" bipw=%d%d%d%d ->",
1661cdf0e10cSrcweir         aOrigName.GetBuffer(), rFontSelData.meWeight, rFontSelData.meItalic,
1662cdf0e10cSrcweir         rFontSelData.mePitch, rFontSelData.meWidthType );
1663cdf0e10cSrcweir     if( !bHaveSubstitute )
1664cdf0e10cSrcweir         printf( "no substitute available\n" );
1665cdf0e10cSrcweir     else
1666cdf0e10cSrcweir         printf( "\"%s\" bipw=%d%d%d%d\n", aSubstName.GetBuffer(),
1667cdf0e10cSrcweir 	    aOut.meWeight, aOut.meItalic, aOut.mePitch, aOut.meWidthType );
1668cdf0e10cSrcweir #endif
1669cdf0e10cSrcweir 
1670cdf0e10cSrcweir     if( bHaveSubstitute )
1671cdf0e10cSrcweir         rFontSelData = aOut;
1672cdf0e10cSrcweir 
1673cdf0e10cSrcweir     return bHaveSubstitute;
1674cdf0e10cSrcweir }
1675cdf0e10cSrcweir 
1676cdf0e10cSrcweir // ===========================================================================
1677cdf0e10cSrcweir 
1678