Stubs for EnumServiceStatus32, small changes.
[wine/multimedia.git] / graphics / x11drv / xfont.c
blob25396d958cc89f485074219f6de8e9687134fca9
1 /*
2 * X11 physical font objects
4 * Copyright 1997 Alex Korobka
6 * TODO: Mapping algorithm tweaks, FO_SYNTH_... flags (ExtTextOut() will
7 * have to be changed for that), dynamic font loading (FreeType).
8 */
10 #include <ctype.h>
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <unistd.h>
15 #include <pwd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include "ts_xlib.h"
20 #include <X11/Xatom.h>
21 #include <math.h>
22 #include <assert.h>
23 #include "heap.h"
24 #include "options.h"
25 #include "x11font.h"
26 #include "font.h"
27 #include "debug.h"
29 #define X_PFONT_MAGIC (0xFADE0000)
30 #define X_FMC_MAGIC (0x0000CAFE)
32 #define MAX_FONT_FAMILIES 128
33 #define MAX_LFD_LENGTH 256
35 #define REMOVE_SUBSETS 1
36 #define UNMARK_SUBSETS 0
38 #define DEF_SCALABLE_HEIGHT 24
39 #define DEF_SCALABLE_DP 240
41 #define FF_FAMILY (FF_MODERN | FF_SWISS | FF_ROMAN | FF_DECORATIVE | FF_SCRIPT)
43 typedef struct __fontAlias
45 LPSTR faTypeFace;
46 LPSTR faAlias;
47 struct __fontAlias* next;
48 } fontAlias;
50 typedef struct
52 LPSTR fatResource;
53 LPSTR fatAlias;
54 } aliasTemplate;
56 /* Font alias table - these 2 aliases are always present */
58 static fontAlias __aliasTable[2] = {
59 { "Helvetica", "Helv", &__aliasTable[1] },
60 { "Times", "Tms Rmn", NULL }
63 static fontAlias *aliasTable = __aliasTable;
65 /* Optional built-in aliases, they are installed only when X
66 * cannot supply us with original MS fonts */
68 static int faTemplateNum = 4;
69 static aliasTemplate faTemplate[4] = {
70 { "-adobe-helvetica-", "MS Sans Serif" },
71 { "-bitstream-charter-", "MS Serif" },
72 { "-adobe-times-", "Times New Roman" },
73 { "-adobe-helvetica-", "Arial" }
76 /* Charset translation table, microsoft-cp125.. encoded fonts are produced by
77 * the fnt2bdf or the True Type X11 font servers */
79 static int numCPTranslation = 8;
80 static BYTE CPTranslation[] = { EE_CHARSET, /* cp1250 */
81 RUSSIAN_CHARSET, /* cp1251 */
82 ANSI_CHARSET, /* cp1252 */
83 GREEK_CHARSET, /* cp1253 */
84 TURKISH_CHARSET, /* cp1254 */
85 HEBREW_CHARSET, /* cp1255 */
86 ARABIC_CHARSET, /* cp1256 */
87 BALTIC_CHARSET /* cp1257 */
88 };
90 UINT16 XTextCaps = TC_OP_CHARACTER | TC_OP_STROKE |
91 TC_CP_STROKE | TC_CR_ANY |
92 TC_SA_DOUBLE | TC_SA_INTEGER | TC_SA_CONTIN |
93 TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
95 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
97 static const char* INIWinePrefix = "/.wine";
98 static const char* INIFontMetrics = "/.cachedmetrics";
99 static const char* INIFontSection = "fonts";
100 static const char* INISubSection = "Alias";
101 static const char* INIDefault = "Default";
102 static const char* INIDefaultFixed = "DefaultFixed";
103 static const char* INIResolution = "Resolution";
104 static const char* INIGlobalMetrics = "FontMetrics";
106 static const char* LFDSeparator = "*-";
107 static const char* localMSEncoding = "microsoft-cp125";
108 static const char* iso8859Encoding = "iso8859-";
109 static const char* iso646Encoding = "iso646.1991-";
110 static const char* ansiEncoding = "ansi-";
111 static unsigned DefResolution = 0;
113 static fontResource* fontList = NULL;
114 static fontObject* fontCache = NULL; /* array */
115 static int fontCacheSize = FONTCACHE;
116 static int fontLF = -1, fontMRU = -1; /* last free, most recently used */
118 #define __PFONT(pFont) ( fontCache + ((UINT32)(pFont) & 0x0000FFFF) )
119 #define CHECK_PFONT(pFont) ( (((UINT32)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
120 (((UINT32)(pFont) & 0x0000FFFF) < fontCacheSize) )
122 static INT32 XFONT_IsSubset(fontInfo*, fontInfo*);
123 static void XFONT_CheckFIList(fontResource*, fontInfo*, int subset_action);
124 static void XFONT_GrowFreeList(int start, int end);
127 static Atom RAW_ASCENT;
128 static Atom RAW_DESCENT;
130 /***********************************************************************
131 * Helper macros from X distribution
134 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
135 (((cs)->rbearing|(cs)->lbearing| \
136 (cs)->ascent|(cs)->descent) == 0))
138 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
140 cs = def; \
141 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
142 if (fs->per_char == NULL) { \
143 cs = &fs->min_bounds; \
144 } else { \
145 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
146 if (CI_NONEXISTCHAR(cs)) cs = def; \
151 #define CI_GET_DEFAULT_INFO(fs,cs) \
152 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
154 /***********************************************************************
155 * Checksums
157 static UINT16 __lfCheckSum( LPLOGFONT16 plf )
159 CHAR font[LF_FACESIZE];
160 UINT16 checksum = 0;
161 UINT16 i;
163 #define ptr ((UINT16*)plf)
164 for( i = 0; i < 9; i++ ) checksum ^= *ptr++;
165 #undef ptr
166 i = 0;
167 #define ptr ((CHAR*)plf)
168 do { font[i++] = tolower(*ptr++); } while (( i < LF_FACESIZE) && (*ptr) && (*ptr!=' '));
169 for( ptr = font, i >>= 1; i > 0; i-- )
170 #undef ptr
171 #define ptr ((UINT16*)plf)
172 checksum ^= *ptr++;
173 #undef ptr
174 return checksum;
177 static UINT16 __genericCheckSum( const void *ptr, int size )
179 unsigned int checksum = 0;
180 const char *p = (const char *)ptr;
181 while (size-- > 0)
182 checksum ^= (checksum << 3) + (checksum >> 29) + *p++;
184 return checksum & 0xffff;
187 /*************************************************************************
188 * LFD parse/compose routines
190 static char* LFD_Advance(LPSTR lpFont, UINT16 uParmsNo)
192 int j = 0;
193 char* lpch = lpFont;
195 for( ; j < uParmsNo && *lpch; lpch++ ) if( *lpch == LFDSeparator[1] ) j++;
196 return lpch;
199 static void LFD_GetWeight( fontInfo* fi, LPSTR lpStr, int j)
201 if( j == 1 && *lpStr == '0' )
202 fi->fi_flags |= FI_POLYWEIGHT;
203 else if( j == 4 )
205 if( !strncasecmp( "bold", lpStr, 4) )
206 fi->df.dfWeight = FW_BOLD;
207 else if( !strncasecmp( "demi", lpStr, 4) )
209 fi->fi_flags |= FI_FW_DEMI;
210 fi->df.dfWeight = FW_DEMIBOLD;
212 else if( !strncasecmp( "book", lpStr, 4) )
214 fi->fi_flags |= FI_FW_BOOK;
215 fi->df.dfWeight = FW_REGULAR;
218 else if( j == 5 )
220 if( !strncasecmp( "light", lpStr, 5) )
221 fi->df.dfWeight = FW_LIGHT;
222 else if( !strncasecmp( "black", lpStr, 5) )
223 fi->df.dfWeight = FW_BLACK;
225 else if( j == 6 && !strncasecmp( "medium", lpStr, 6) )
226 fi->df.dfWeight = FW_REGULAR;
227 else if( j == 8 && !strncasecmp( "demibold", lpStr, 8) )
228 fi->df.dfWeight = FW_DEMIBOLD;
229 else
230 fi->df.dfWeight = FW_DONTCARE; /* FIXME: try to get something
231 * from the weight property */
234 static int LFD_GetSlant( fontInfo* fi, LPSTR lpStr, int l)
236 if( l == 1 )
238 switch( tolower( *lpStr ) )
240 case '0': fi->fi_flags |= FI_POLYSLANT; /* haven't seen this one yet */
241 default:
242 case 'r': fi->df.dfItalic = 0;
243 break;
244 case 'o':
245 fi->fi_flags |= FI_OBLIQUE;
246 case 'i': fi->df.dfItalic = 1;
247 break;
249 return 0;
251 return 1;
254 /*************************************************************************
255 * LFD_InitFontInfo
257 * Fill in some fields in the fontInfo struct.
259 static int LFD_InitFontInfo( fontInfo* fi, LPSTR lpstr )
261 LPSTR lpch;
262 int i, j, dec_style_check, scalability;
263 UINT16 tmp[3];
265 memset(fi, 0, sizeof(fontInfo) );
267 /* weight name - */
268 lpch = LFD_Advance( lpstr, 1);
269 if( !*lpch ) return FALSE;
270 j = lpch - lpstr - 1;
271 LFD_GetWeight( fi, lpstr, j );
273 /* slant - */
274 lpch = LFD_Advance( lpstr = lpch, 1);
275 if( !*lpch ) return FALSE;
276 j = lpch - lpstr - 1;
277 dec_style_check = LFD_GetSlant( fi, lpstr, j );
279 /* width name - */
280 lpch = LFD_Advance( lpstr = lpch, 1);
281 if( !*lpch ) return FALSE;
282 if( strncasecmp( "normal", lpstr, 6) ) /* XXX 'narrow', 'condensed', etc... */
283 dec_style_check = TRUE;
284 else
285 fi->fi_flags |= FI_NORMAL;
287 /* style - */
288 lpch = LFD_Advance( lpstr = lpch, 1);
289 if( !*lpch ) return FALSE;
290 j = lpch - lpstr - 1;
291 if( j > 3 ) /* find out is there "sans" or "script" */
293 j = 0;
294 *(lpch - 1) = '\0';
296 if( strstr(lpstr, "sans") )
298 fi->df.dfPitchAndFamily |= FF_SWISS;
299 j = 1;
301 if( strstr(lpstr, "script") )
303 fi->df.dfPitchAndFamily |= FF_SCRIPT;
304 j = 1;
306 if( !j && dec_style_check )
307 fi->df.dfPitchAndFamily |= FF_DECORATIVE;
308 *(lpch - 1) = LFDSeparator[1];
311 /* pixel height, decipoint height, and res_x */
313 for( i = scalability = 0; i < 3; i++ )
315 lpch = LFD_Advance( lpstr = lpch, 1);
316 if( !*lpch ) return FALSE;
317 if( lpch - lpstr == 1 || lpch - lpstr > 4 ) return FALSE; /* ridiculous */
319 *(lpch - 1) = '\0';
320 if( !(tmp[i] = atoi(lpstr)) ) scalability++;
321 *(lpch - 1) = LFDSeparator[1];
323 if( scalability == 3 ) /* Type1 */
325 fi->fi_flags |= FI_SCALABLE;
326 fi->lfd_height = DEF_SCALABLE_HEIGHT; fi->lfd_decipoints = DEF_SCALABLE_DP;
327 fi->lfd_resolution = DefResolution;
329 else if( scalability == 0 ) /* Bitmap */
331 fi->lfd_height = tmp[0]; fi->lfd_decipoints = tmp[1];
332 fi->lfd_resolution = tmp[2];
334 else return FALSE; /* #$%^!!! X11R6 mutant garbage */
336 /* res_y - skip, spacing - */
337 lpstr = LFD_Advance( lpch, 1);
338 switch( *lpstr )
340 case '\0': return FALSE;
342 case 'p': fi->fi_flags |= FI_VARIABLEPITCH;
343 break;
344 case 'c': fi->df.dfPitchAndFamily |= FF_MODERN;
345 fi->fi_flags |= FI_FIXEDEX;
346 /* fall through */
347 case 'm': fi->fi_flags |= FI_FIXEDPITCH;
348 break;
349 default:
350 fi->df.dfPitchAndFamily |= DEFAULT_PITCH | FF_DONTCARE;
352 lpstr = LFD_Advance(lpstr, 1);
353 if( !*lpstr ) return FALSE;
355 /* average width - */
356 lpch = LFD_Advance( lpstr, 1);
357 if( !*lpch ) return FALSE;
358 if( lpch - lpstr == 1 || lpch - lpstr > 4 ) return FALSE; /* ridiculous */
359 *(lpch - 1) = '\0';
360 if( !(fi->lfd_width = atoi(lpstr)) && !scalability ) return FALSE;
361 *(lpch - 1) = LFDSeparator[1];
363 /* charset registry, charset encoding - */
364 if( strstr(lpch, "jisx") ||
365 strstr(lpch, "ksc") ||
366 strstr(lpch, "gb2312") ) return FALSE; /* 2-byte stuff */
368 fi->df.dfCharSet = ANSI_CHARSET;
369 if( strstr(lpch, iso8859Encoding) )
370 fi->fi_flags |= FI_ENC_ISO8859;
371 else if( strstr(lpch, iso646Encoding) )
372 fi->fi_flags |= FI_ENC_ISO646;
373 else if( strstr(lpch, ansiEncoding) ) /* fnt2bdf produces -ansi-0 LFD */
374 fi->fi_flags |= FI_ENC_ANSI;
375 else /* ... and -microsoft-cp125x */
377 fi->df.dfCharSet = OEM_CHARSET;
378 if( !strncasecmp(lpch, localMSEncoding, 6) )
380 lpch = LFD_Advance( lpch, 1 );
381 if( lpch && (i = atoi( lpch )) < numCPTranslation )
383 fi->fi_flags |= FI_ENC_MSCODEPAGE;
384 fi->df.dfCharSet = CPTranslation[i];
387 else if( strstr(lpch, "fontspecific") ||
388 strstr(lpch, "microsoft-symbol") )
389 fi->df.dfCharSet = SYMBOL_CHARSET;
391 return TRUE;
395 /*************************************************************************
396 * LFD_ComposeLFD
398 static BOOL32 LFD_ComposeLFD( fontObject* fo,
399 INT32 height, LPSTR lpLFD, UINT32 uRelax )
401 int h, w, ch, enc_ch, point = 0;
402 char* lpch;
403 const char* lpEncoding = NULL;
404 char h_string[64], point_string[64];
406 *(lpLFD+MAX_LFD_LENGTH-1)=0;
407 lstrcpy32A( lpLFD, fo->fr->resource );
409 /* add weight */
410 switch( fo->fi->df.dfWeight )
412 case FW_BOLD:
413 strcat( lpLFD, "bold" ); break;
414 case FW_REGULAR:
415 if( fo->fi->fi_flags & FI_FW_BOOK )
416 strcat( lpLFD, "book" );
417 else
418 strcat( lpLFD, "medium" );
419 break;
420 case FW_DEMIBOLD:
421 strcat( lpLFD, "demi" );
422 if( !( fo->fi->fi_flags & FI_FW_DEMI) )
423 strcat ( lpLFD, "bold" );
424 break;
425 case FW_BLACK:
426 strcat( lpLFD, "black" ); break;
427 case FW_LIGHT:
428 strcat( lpLFD, "light" ); break;
429 default:
430 strcat( lpLFD, "*" );
433 /* add slant */
434 if( fo->fi->df.dfItalic )
435 if( fo->fi->fi_flags & FI_OBLIQUE )
436 strcat( lpLFD, "-o" );
437 else
438 strcat( lpLFD, "-i" );
439 else
440 strcat( lpLFD, (uRelax < 4) ? "-r" : "-*" );
442 /* add width style and skip serifs */
443 if( fo->fi->fi_flags & FI_NORMAL )
444 strcat( lpLFD, "-normal-*-");
445 else
446 strcat( lpLFD, "-*-*-" );
448 /* add pixelheight, pointheight, and resolution
450 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
452 if( fo->fo_flags & FO_SYNTH_HEIGHT ) h = fo->fi->lfd_height;
453 else h = (fo->fi->lfd_height * height) / fo->fi->df.dfPixHeight;
455 if( XTextCaps & TC_SF_X_YINDEP )
457 if( fo->lf.lfWidth && !(fo->fo_flags & FO_SYNTH_WIDTH) )
458 point = (fo->fi->lfd_decipoints * fo->lf.lfWidth) / fo->fi->df.dfAvgWidth;
459 else
460 if( fo->fi->fi_flags & FI_SCALABLE ) /* adjust h/w ratio */
461 point = h * 72 * 10 / fo->fi->lfd_resolution;
464 /* handle rotated fonts */
465 if (fo->lf.lfEscapement) {
466 /* escapement is in tenths of degrees, theta is in radians */
467 double theta = M_PI*fo->lf.lfEscapement/1800.;
468 double h_matrix[4] = {h*cos(theta), h*sin(theta), -h*sin(theta), h*cos(theta)};
469 double point_matrix[4] = {point*cos(theta), point*sin(theta), -point*sin(theta), point*cos(theta)};
470 char *s;
471 sprintf(h_string, "[%+f%+f%+f%+f]", h_matrix[0], h_matrix[1], h_matrix[2], h_matrix[3]);
472 sprintf(point_string, "[%+f%+f%+f%+f]", point_matrix[0], point_matrix[1], point_matrix[2], point_matrix[3]);
473 while ((s = strchr(h_string, '-'))) *s='~';
474 while ((s = strchr(point_string, '-'))) *s='~';
475 } else {
476 sprintf(h_string, "%d", h);
477 sprintf(point_string, "%d", point);
481 /* spacing and width */
483 if( fo->fi->fi_flags & FI_FIXEDPITCH )
484 w = ( fo->fi->fi_flags & FI_FIXEDEX ) ? 'c' : 'm';
485 else
486 w = ( fo->fi->fi_flags & FI_VARIABLEPITCH ) ? 'p' : LFDSeparator[0];
488 /* encoding */
490 enc_ch = '*';
491 if( fo->fi->df.dfCharSet == ANSI_CHARSET )
493 if( fo->fi->fi_flags & FI_ENC_ISO8859 )
494 lpEncoding = iso8859Encoding;
495 else if( fo->fi->fi_flags & FI_ENC_ISO646 )
496 lpEncoding = iso646Encoding;
497 else if( fo->fi->fi_flags & FI_ENC_MSCODEPAGE )
499 enc_ch = '2';
500 lpEncoding = localMSEncoding;
502 else lpEncoding = ansiEncoding;
504 else if( fo->fi->fi_flags & FI_ENC_MSCODEPAGE )
506 int i;
508 lpEncoding = localMSEncoding;
509 for( i = 0; i < numCPTranslation; i++ )
510 if( CPTranslation[i] == fo->fi->df.dfCharSet )
512 enc_ch = '0' + i;
513 break;
516 else lpEncoding = LFDSeparator; /* whatever */
518 lpch = lpLFD + lstrlen32A(lpLFD);
519 ch = (fo->fi->fi_flags & FI_SCALABLE) ? '0' : LFDSeparator[0];
521 switch( uRelax )
523 /* RealizeFont() will call us repeatedly with increasing uRelax
524 * until XLoadFont() succeeds. */
526 case 0:
527 if( point )
529 sprintf( lpch, "%s-%s-%i-%c-%c-*-%s%c", h_string,
530 point_string,
531 fo->fi->lfd_resolution, ch, w, lpEncoding, enc_ch );
532 break;
534 /* fall through */
536 case 1:
537 sprintf( lpch, "%s-*-%i-%c-%c-*-%s%c", h_string,
538 fo->fi->lfd_resolution, ch, w, lpEncoding, enc_ch );
539 break;
541 case 2:
542 sprintf( lpch, "%s-*-%i-%c-*-*-%s%c",
543 h_string, fo->fi->lfd_resolution, ch, lpEncoding, enc_ch );
544 break;
546 case 3:
547 sprintf( lpch, "%i-*-%i-%c-*-*-%s*", fo->fi->lfd_height,
548 fo->fi->lfd_resolution, ch, lpEncoding );
549 break;
551 default:
552 sprintf( lpch, "%i-*-*-*-*-*-%s*", fo->fi->lfd_height, lpEncoding );
555 TRACE(font,"\tLFD: %s\n", lpLFD );
556 assert(*(lpLFD+MAX_LFD_LENGTH-1)==0); /* check if overwrittem */
557 return TRUE;
561 /***********************************************************************
562 * X Font Resources
564 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
565 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
567 static BOOL32 XFONT_GetLeading( LPIFONTINFO16 pFI, XFontStruct* x_fs, INT32*
568 pIL, INT32* pEL, XFONTTRANS *XFT )
570 unsigned long height;
571 unsigned min = (unsigned char)pFI->dfFirstChar;
572 unsigned max = (unsigned char)pFI->dfLastChar;
573 BOOL32 bHaveCapHeight = (pFI->dfCharSet == ANSI_CHARSET && 'X' >= min && 'X' <= max );
575 if( pEL ) *pEL = 0;
577 if(XFT) {
578 Atom RAW_CAP_HEIGHT = TSXInternAtom(display, "RAW_CAP_HEIGHT", TRUE);
579 if(TSXGetFontProperty(x_fs, RAW_CAP_HEIGHT, &height))
580 *pIL = XFT->ascent -
581 (INT32)(XFT->pixelsize / 1000.0 * height);
582 else
583 *pIL = 0;
584 return bHaveCapHeight && x_fs->per_char;
587 if( TSXGetFontProperty(x_fs, XA_CAP_HEIGHT, &height) == FALSE )
589 if( x_fs->per_char )
590 if( bHaveCapHeight )
591 height = x_fs->per_char['X' - min].ascent;
592 else
593 if (x_fs->ascent >= x_fs->max_bounds.ascent)
594 height = x_fs->max_bounds.ascent;
595 else
597 height = x_fs->ascent;
598 if( pEL )
599 *pEL = x_fs->max_bounds.ascent - height;
601 else
602 height = x_fs->min_bounds.ascent;
605 *pIL = x_fs->ascent - height;
606 return (bHaveCapHeight && x_fs->per_char);
609 static INT32 XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI, XFontStruct* x_fs,
610 XFONTTRANS *XFT)
612 unsigned min = (unsigned char)pFI->dfFirstChar;
613 unsigned max = (unsigned char)pFI->dfLastChar;
615 if( x_fs->per_char )
617 int width, chars, j;
618 for( j = 0, width = 0, chars = 0, max -= min; j <= max; j++ )
619 if( !CI_NONEXISTCHAR(x_fs->per_char + j) )
621 if(!XFT)
622 width += x_fs->per_char[j].width;
623 else
624 width += x_fs->per_char[j].attributes *
625 XFT->pixelsize / 1000.0;
626 chars++;
628 return (width / chars);
630 /* uniform width */
631 return x_fs->min_bounds.width;
634 static INT32 XFONT_GetMaxCharWidth(fontObject *pfo)
636 unsigned min = (unsigned char)pfo->fs->min_char_or_byte2;
637 unsigned max = (unsigned char)pfo->fs->max_char_or_byte2;
639 if(!pfo->lpX11Trans)
640 return abs(pfo->fs->max_bounds.width);
642 if( pfo->fs->per_char )
644 int maxwidth, j;
645 for( j = 0, maxwidth = 0, max -= min; j <= max; j++ )
646 if( !CI_NONEXISTCHAR(pfo->fs->per_char + j) )
647 if(maxwidth < pfo->fs->per_char[j].attributes)
648 maxwidth = pfo->fs->per_char[j].attributes;
650 maxwidth *= pfo->lpX11Trans->pixelsize / 1000.0;
651 return maxwidth;
653 return pfo->foAvgCharWidth;
656 /***********************************************************************
657 * XFONT_SetFontMetric
659 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
661 static void XFONT_SetFontMetric(fontInfo* fi, fontResource* fr, XFontStruct* xfs)
663 unsigned min, max;
664 INT32 el, il;
666 fi->df.dfFirstChar = (BYTE)(min = xfs->min_char_or_byte2);
667 fi->df.dfLastChar = (BYTE)(max = xfs->max_char_or_byte2);
669 fi->df.dfDefaultChar = (BYTE)xfs->default_char;
670 fi->df.dfBreakChar = (BYTE)(( ' ' < min || ' ' > max) ? xfs->default_char: ' ');
672 fi->df.dfPixHeight = (INT16)((fi->df.dfAscent = (INT16)xfs->ascent) + xfs->descent);
673 fi->df.dfPixWidth = (xfs->per_char) ? 0 : xfs->min_bounds.width;
674 fi->df.dfMaxWidth = (INT16)abs(xfs->max_bounds.width);
676 if( XFONT_GetLeading( &fi->df, xfs, &il, &el, NULL ) )
677 fi->df.dfAvgWidth = (INT16)xfs->per_char['X' - min].width;
678 else
679 fi->df.dfAvgWidth = (INT16)XFONT_GetAvgCharWidth( &fi->df, xfs, NULL);
681 fi->df.dfInternalLeading = (INT16)il;
682 fi->df.dfExternalLeading = (INT16)el;
684 fi->df.dfPoints = (INT16)(((INT32)(fi->df.dfPixHeight -
685 fi->df.dfInternalLeading) * 72 + (fi->df.dfVertRes >> 1)) / fi->df.dfVertRes);
687 if( xfs->min_bounds.width != xfs->max_bounds.width )
688 fi->df.dfPitchAndFamily |= TMPF_FIXED_PITCH; /* au contraire! */
689 if( fi->fi_flags & FI_SCALABLE )
691 fi->df.dfType = DEVICE_FONTTYPE;
692 fi->df.dfPitchAndFamily |= TMPF_DEVICE;
694 else if( fi->fi_flags & FI_TRUETYPE )
695 fi->df.dfType = TRUETYPE_FONTTYPE;
696 else
697 fi->df.dfType = RASTER_FONTTYPE;
699 fi->df.dfFace = fr->lfFaceName;
702 /***********************************************************************
703 * XFONT_GetTextMetric
705 static void XFONT_GetTextMetric( fontObject* pfo, LPTEXTMETRIC32A pTM )
707 LPIFONTINFO16 pdf = &pfo->fi->df;
709 if( ! pfo->lpX11Trans ) {
710 pTM->tmAscent = pfo->fs->ascent;
711 pTM->tmDescent = pfo->fs->descent;
712 } else {
713 pTM->tmAscent = pfo->lpX11Trans->ascent;
714 pTM->tmDescent = pfo->lpX11Trans->descent;
716 pTM->tmHeight = pTM->tmAscent + pTM->tmDescent;
718 pTM->tmAveCharWidth = pfo->foAvgCharWidth;
719 pTM->tmMaxCharWidth = pfo->foMaxCharWidth;
721 pTM->tmInternalLeading = pfo->foInternalLeading;
722 pTM->tmExternalLeading = pdf->dfExternalLeading;
724 pTM->tmStruckOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT )
725 ? 1 : pdf->dfStrikeOut;
726 pTM->tmUnderlined = (pfo->fo_flags & FO_SYNTH_UNDERLINE )
727 ? 1 : pdf->dfUnderline;
729 pTM->tmOverhang = 0;
730 if( pfo->fo_flags & FO_SYNTH_ITALIC )
732 pTM->tmOverhang += pTM->tmHeight/3;
733 pTM->tmItalic = 1;
734 } else
735 pTM->tmItalic = pdf->dfItalic;
737 pTM->tmWeight = pdf->dfWeight;
738 if( pfo->fo_flags & FO_SYNTH_BOLD )
740 pTM->tmOverhang++;
741 pTM->tmWeight += 100;
744 *(INT32*)&pTM->tmFirstChar = *(INT32*)&pdf->dfFirstChar;
746 pTM->tmCharSet = pdf->dfCharSet;
747 pTM->tmPitchAndFamily = pdf->dfPitchAndFamily;
749 pTM->tmDigitizedAspectX = pdf->dfHorizRes;
750 pTM->tmDigitizedAspectY = pdf->dfVertRes;
753 /***********************************************************************
754 * XFONT_GetFontMetric
756 * Retrieve font metric info (enumeration).
758 static UINT32 XFONT_GetFontMetric( fontInfo* pfi, LPENUMLOGFONTEX16 pLF,
759 LPNEWTEXTMETRIC16 pTM )
761 memset( pLF, 0, sizeof(*pLF) );
762 memset( pTM, 0, sizeof(*pTM) );
764 #define plf ((LPLOGFONT16)pLF)
765 plf->lfHeight = pTM->tmHeight = pfi->df.dfPixHeight;
766 plf->lfWidth = pTM->tmAveCharWidth = pfi->df.dfAvgWidth;
767 plf->lfWeight = pTM->tmWeight = pfi->df.dfWeight;
768 plf->lfItalic = pTM->tmItalic = pfi->df.dfItalic;
769 plf->lfUnderline = pTM->tmUnderlined = pfi->df.dfUnderline;
770 plf->lfStrikeOut = pTM->tmStruckOut = pfi->df.dfStrikeOut;
771 plf->lfCharSet = pTM->tmCharSet = pfi->df.dfCharSet;
773 /* convert pitch values */
775 pTM->tmPitchAndFamily = pfi->df.dfPitchAndFamily;
776 plf->lfPitchAndFamily = (pfi->df.dfPitchAndFamily & 0xF1) + 1;
778 lstrcpyn32A( plf->lfFaceName, pfi->df.dfFace, LF_FACESIZE );
779 #undef plf
781 pTM->tmAscent = pfi->df.dfAscent;
782 pTM->tmDescent = pTM->tmHeight - pTM->tmAscent;
783 pTM->tmInternalLeading = pfi->df.dfInternalLeading;
784 pTM->tmMaxCharWidth = pfi->df.dfMaxWidth;
785 pTM->tmDigitizedAspectX = pfi->df.dfHorizRes;
786 pTM->tmDigitizedAspectY = pfi->df.dfVertRes;
788 *(INT32*)&pTM->tmFirstChar = *(INT32*)&pfi->df.dfFirstChar;
790 /* return font type */
792 return pfi->df.dfType;
796 /***********************************************************************
797 * XFONT_FixupFlags
799 * dfPitchAndFamily flags for some common typefaces.
801 static BYTE XFONT_FixupFlags( LPCSTR lfFaceName )
803 switch( lfFaceName[0] )
805 case 'h':
806 case 'H': if(!strcasecmp(lfFaceName, "Helvetica") )
807 return FF_SWISS;
808 break;
809 case 'c':
810 case 'C': if(!strcasecmp(lfFaceName, "Courier") ||
811 !strcasecmp(lfFaceName, "Charter") )
812 return FF_ROMAN;
813 break;
814 case 'p':
815 case 'P': if( !strcasecmp(lfFaceName,"Palatino") )
816 return FF_ROMAN;
817 break;
818 case 't':
819 case 'T': if(!strncasecmp(lfFaceName, "Times", 5) )
820 return FF_ROMAN;
821 break;
822 case 'u':
823 case 'U': if(!strcasecmp(lfFaceName, "Utopia") )
824 return FF_ROMAN;
825 break;
826 case 'z':
827 case 'Z': if(!strcasecmp(lfFaceName, "Zapf Dingbats") )
828 return FF_DECORATIVE;
830 return 0;
834 /***********************************************************************
835 * XFONT_CheckResourceName
837 static BOOL32 XFONT_CheckResourceName( LPSTR resource, LPCSTR name, INT32 n )
839 resource = LFD_Advance( resource, 2 );
840 if( resource )
841 return (!strncasecmp( resource, name, n ));
842 return FALSE;
846 /***********************************************************************
847 * XFONT_WindowsNames
849 * Build generic Windows aliases for X font names.
851 * -misc-fixed- -> "Fixed"
852 * -sony-fixed- -> "Sony Fixed", etc...
854 static void XFONT_WindowsNames( char* buffer )
856 fontResource* fr, *pfr;
857 char* lpstr, *lpch;
858 int i, up;
859 BYTE bFamilyStyle;
860 const char* relocTable[] = { INIDefaultFixed, INIDefault, NULL };
862 for( fr = fontList; fr ; fr = fr->next )
864 if( fr->fr_flags & FR_NAMESET ) continue; /* skip already assigned */
866 lpstr = LFD_Advance(fr->resource, 2);
867 i = LFD_Advance( lpstr, 1 ) - lpstr;
869 for( pfr = fontList; pfr != fr ; pfr = pfr->next )
870 if( pfr->fr_flags & FR_NAMESET )
871 if( XFONT_CheckResourceName( pfr->resource, lpstr, i ) )
872 break;
874 if( pfr != fr ) /* prepend vendor name */
875 lpstr = fr->resource + 1;
877 for( i = 0, up = 1, lpch = fr->lfFaceName; *lpstr && i < 32;
878 lpch++, lpstr++, i++ )
880 if( *lpstr == LFDSeparator[1] || *lpstr == ' ' )
882 *lpch = ' ';
883 up = 1; continue;
885 else if( isalpha(*lpstr) && up )
887 *lpch = toupper(*lpstr);
888 up = 0; continue;
890 *lpch = *lpstr;
892 while (*(lpch - 1) == ' ') *(--lpch) = '\0';
894 if( (bFamilyStyle = XFONT_FixupFlags( fr->lfFaceName )) )
896 fontInfo* fi;
897 for( fi = fr->fi ; fi ; fi = fi->next )
898 fi->df.dfPitchAndFamily |= bFamilyStyle;
901 TRACE(font,"typeface \'%s\'\n", fr->lfFaceName);
903 fr->fr_flags |= FR_NAMESET;
906 for( up = 0; relocTable[up]; up++ )
907 if( PROFILE_GetWineIniString( INIFontSection, relocTable[up], "", buffer, 128 ) )
909 while( *buffer && isspace(*buffer) ) buffer++;
910 for( fr = NULL, pfr = fontList; pfr; pfr = pfr->next )
912 i = strlen( pfr->resource );
913 if( !strncasecmp( pfr->resource, buffer, i) )
915 if( fr )
917 fr->next = pfr->next;
918 pfr->next = fontList;
919 fontList = pfr;
921 break;
923 fr = pfr;
928 /***********************************************************************
929 * XFONT_CreateAlias
931 static fontAlias* XFONT_CreateAlias( LPCSTR lpTypeFace, LPCSTR lpAlias )
933 int j;
934 fontAlias* pfa = aliasTable;
936 while( 1 )
938 /* check if we already got one */
939 if( !strcasecmp( pfa->faTypeFace, lpAlias ) )
941 TRACE(font,"\tredundant alias '%s' -> '%s'\n",
942 lpAlias, lpTypeFace );
943 return NULL;
945 if( pfa->next ) pfa = pfa->next;
946 else break;
949 j = lstrlen32A(lpTypeFace) + 1;
950 pfa->next = HeapAlloc( SystemHeap, 0, sizeof(fontAlias) +
951 j + lstrlen32A(lpAlias) + 1 );
952 if((pfa = pfa->next))
954 pfa->next = NULL;
955 pfa->faTypeFace = (LPSTR)(pfa + 1);
956 lstrcpy32A( pfa->faTypeFace, lpTypeFace );
957 pfa->faAlias = pfa->faTypeFace + j;
958 lstrcpy32A( pfa->faAlias, lpAlias );
960 TRACE(font, "\tadded alias '%s' for %s\n", lpAlias, lpTypeFace );
962 return pfa;
964 return NULL;
967 /***********************************************************************
968 * XFONT_LoadAliases
970 * Read user-defined aliases from wine.conf. Format is as follows
972 * Alias# = [Windows font name],[LFD font name], <substitute original name>
974 * Example:
975 * Alias0 = Arial, -adobe-helvetica-
976 * Alias1 = Times New Roman, -bitstream-courier-, 1
977 * ...
979 * Note that from 081797 and on we have built-in alias templates that take
980 * care of the necessary Windows typefaces.
982 static void XFONT_LoadAliases( char** buffer, int buf_size )
984 char* lpResource, *lpAlias;
985 char subsection[32];
986 int i = 0, j = 0;
987 BOOL32 bHaveAlias = TRUE, bSubst = FALSE;
989 if( buf_size < 128 )
990 *buffer = HeapReAlloc(SystemHeap, 0, *buffer, 256 );
993 if( j < faTemplateNum )
995 /* built-in templates first */
997 lpResource = faTemplate[j].fatResource;
998 lpAlias = faTemplate[j].fatAlias;
999 j++;
1001 else
1003 /* then WINE.CONF */
1005 wsprintf32A( subsection, "%s%i", INISubSection, i++ );
1007 if( (bHaveAlias = PROFILE_GetWineIniString( INIFontSection,
1008 subsection, "", *buffer, 128 )) )
1010 lpAlias = *buffer;
1011 while( isspace(*lpAlias) ) lpAlias++;
1012 lpResource = PROFILE_GetStringItem( lpAlias );
1013 bSubst = (PROFILE_GetStringItem( lpResource )) ? TRUE : FALSE;
1017 if( bHaveAlias )
1019 int length;
1021 length = strlen( lpAlias );
1022 if( lpResource && length )
1024 fontResource* fr, *frMatch = NULL;
1026 for (fr = fontList; fr ; fr = fr->next)
1028 if( !strcasecmp( fr->resource, lpResource ) ) frMatch = fr;
1029 if( XFONT_CheckResourceName( fr->resource, lpAlias, length ) )
1031 /* alias is not needed since the real font is present */
1032 frMatch = NULL; break;
1036 if( frMatch )
1038 if( bSubst )
1040 fontAlias *pfa, *prev = NULL;
1042 for(pfa = aliasTable; pfa; pfa = pfa->next)
1044 /* Remove lpAlias from aliasTable - we should free the old entry */
1045 if(!strcmp(lpAlias, pfa->faAlias))
1047 if(prev)
1048 prev->next = pfa->next;
1049 else
1050 aliasTable = pfa->next;
1053 /* Update any references to the substituted font in aliasTable */
1054 if(!strcmp(frMatch->lfFaceName,
1055 pfa->faTypeFace))
1056 pfa->faTypeFace = HEAP_strdupA( SystemHeap, 0,
1057 lpAlias );
1058 prev = pfa;
1061 TRACE(font, "\tsubstituted '%s' with %s\n",
1062 frMatch->lfFaceName, lpAlias );
1064 lstrcpyn32A( frMatch->lfFaceName, lpAlias, LF_FACESIZE );
1065 frMatch->fr_flags |= FR_NAMESET;
1067 else
1069 /* create new entry in the alias table */
1070 XFONT_CreateAlias( frMatch->lfFaceName, lpAlias );
1074 else ERR(font, " malformed font alias '%s'\n", *buffer );
1076 else break;
1077 } while(TRUE);
1080 /***********************************************************************
1081 * XFONT_UserMetricsCache
1083 * Returns expanded name for the ~/.wine/.cachedmetrics file.
1085 static char* XFONT_UserMetricsCache( char* buffer, int* buf_size )
1087 struct passwd* pwd;
1089 pwd = getpwuid(getuid());
1090 if( pwd && pwd->pw_dir )
1092 int i = strlen( pwd->pw_dir ) + strlen( INIWinePrefix ) +
1093 strlen( INIFontMetrics ) + 2;
1094 if( i > *buf_size )
1095 buffer = (char*) HeapReAlloc( SystemHeap, 0, buffer, *buf_size = i );
1096 strcpy( buffer, pwd->pw_dir );
1097 strcat( buffer, INIWinePrefix );
1098 strcat( buffer, INIFontMetrics );
1099 } else buffer[0] = '\0';
1100 return buffer;
1104 /***********************************************************************
1105 * XFONT_ReadCachedMetrics
1107 static BOOL32 XFONT_ReadCachedMetrics( int fd, int res, unsigned x_checksum, int x_count )
1109 if( fd >= 0 )
1111 unsigned u;
1112 int i, j;
1114 /* read checksums */
1115 read( fd, &u, sizeof(unsigned) );
1116 read( fd, &i, sizeof(int) );
1118 if( u == x_checksum && i == x_count )
1120 off_t length, offset = 3 * sizeof(int);
1122 /* read total size */
1123 read( fd, &i, sizeof(int) );
1124 length = lseek( fd, 0, SEEK_END );
1126 if( length == (i + offset) )
1128 lseek( fd, offset, SEEK_SET );
1129 fontList = (fontResource*)HeapAlloc( SystemHeap, 0, i);
1130 if( fontList )
1132 fontResource* pfr = fontList;
1133 fontInfo* pfi = NULL;
1135 TRACE(font,"Reading cached font metrics:\n");
1137 read( fd, fontList, i); /* read all metrics at once */
1138 while( offset < length )
1140 offset += sizeof(fontResource) + sizeof(fontInfo);
1141 pfr->fi = pfi = (fontInfo*)(pfr + 1);
1142 j = 1;
1143 while( TRUE )
1145 if( offset > length ||
1146 (int)(pfi->next) != j++ ) goto fail;
1148 pfi->df.dfFace = pfr->lfFaceName;
1149 pfi->df.dfHorizRes = pfi->df.dfVertRes = res;
1150 pfi->df.dfPoints = (INT16)(((INT32)(pfi->df.dfPixHeight -
1151 pfi->df.dfInternalLeading) * 72 + (res >> 1)) / res );
1152 pfi->next = pfi + 1;
1154 if( j > pfr->count ) break;
1156 pfi = pfi->next;
1157 offset += sizeof(fontInfo);
1159 pfi->next = NULL;
1160 if( pfr->next )
1162 pfr->next = (fontResource*)(pfi + 1);
1163 pfr = pfr->next;
1165 else break;
1167 if( pfr->next == NULL &&
1168 *(int*)(pfi + 1) == X_FMC_MAGIC )
1170 /* read LFD stubs */
1171 char* lpch = (char*)((int*)(pfi + 1) + 1);
1172 offset += sizeof(int);
1173 for( pfr = fontList; pfr; pfr = pfr->next )
1175 TRACE(font,"\t%s, %i instances\n", lpch, pfr->count );
1176 pfr->resource = lpch;
1177 while( TRUE )
1179 if( ++offset > length ) goto fail;
1180 if( !*lpch++ ) break;
1183 close( fd );
1184 return TRUE;
1189 fail:
1190 if( fontList ) HeapFree( SystemHeap, 0, fontList );
1191 fontList = NULL;
1192 close( fd );
1194 return FALSE;
1197 /***********************************************************************
1198 * XFONT_WriteCachedMetrics
1200 static BOOL32 XFONT_WriteCachedMetrics( int fd, unsigned x_checksum, int x_count, int n_ff )
1202 fontResource* pfr;
1203 fontInfo* pfi;
1205 if( fd >= 0 )
1207 int i, j, k;
1209 /* font metrics file:
1211 * +0000 x_checksum
1212 * +0004 x_count
1213 * +0008 total size to load
1214 * +000C prepackaged font metrics
1215 * ...
1216 * +...x X_FMC_MAGIC
1217 * +...x + 4 LFD stubs
1220 write( fd, &x_checksum, sizeof(unsigned) );
1221 write( fd, &x_count, sizeof(int) );
1223 for( j = i = 0, pfr = fontList; pfr; pfr = pfr->next )
1225 i += strlen( pfr->resource ) + 1;
1226 j += pfr->count;
1228 i += n_ff * sizeof(fontResource) + j * sizeof(fontInfo) + sizeof(int);
1229 write( fd, &i, sizeof(int) );
1231 TRACE(font,"Writing font cache:\n");
1233 for( pfr = fontList; pfr; pfr = pfr->next )
1235 fontInfo fi;
1237 TRACE(font,"\t%s, %i instances\n", pfr->resource, pfr->count );
1239 i = write( fd, pfr, sizeof(fontResource) );
1240 if( i == sizeof(fontResource) )
1242 for( k = 1, pfi = pfr->fi; pfi; pfi = pfi->next )
1244 memcpy( &fi, pfi, sizeof(fi) );
1246 fi.df.dfFace = NULL;
1247 fi.next = (fontInfo*)k; /* loader checks this */
1249 j = write( fd, &fi, sizeof(fi) );
1250 k++;
1252 if( j == sizeof(fontInfo) ) continue;
1254 break;
1256 if( i == sizeof(fontResource) && j == sizeof(fontInfo) )
1258 i = j = X_FMC_MAGIC;
1259 write( fd, &i, sizeof(int) );
1260 for( pfr = fontList; pfr && i == j; pfr = pfr->next )
1262 i = strlen( pfr->resource ) + 1;
1263 j = write( fd, pfr->resource, i );
1266 close( fd );
1267 return ( i == j );
1269 return TRUE;
1272 /***********************************************************************
1273 * XFONT_CheckIniSection
1275 * Examines wine.conf for old/invalid font entries and recommend changes to
1276 * the user.
1278 * Revision history
1279 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1280 * Original implementation.
1282 static void XFONT_CheckIniCallback(char const *, char const *, void *);
1284 static char const *fontmsgprologue =
1285 "Wine warning:\n"
1286 " The following entries in the [fonts] section of the wine.conf file are\n"
1287 " obsolete or invalid:\n";
1289 static char const *fontmsgepilogue =
1290 " These entries should be eliminated or updated.\n"
1291 " See the documentation/fonts file for more information.\n";
1293 static int XFONT_CheckIniSection()
1295 int found = 0;
1297 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback,
1298 (void *)&found);
1299 if(found)
1300 MSG(fontmsgepilogue);
1302 return 1;
1305 static void XFONT_CheckIniCallback(
1306 char const *key,
1307 char const *value,
1308 void *found)
1310 /* Ignore any keys that start with potential comment characters "'", '#',
1311 or ';'. */
1312 if(key[0] == '\'' || key[0] == '#' || key[0] == ';' || key[0] == '\0')
1313 return;
1315 /* Make sure this is a valid key */
1316 if((strncasecmp(key, INISubSection, 5) == 0) ||
1317 (strcasecmp( key, INIDefault) == 0) ||
1318 (strcasecmp( key, INIDefaultFixed) == 0) ||
1319 (strcasecmp( key, INIGlobalMetrics) == 0) ||
1320 (strcasecmp( key, INIResolution) == 0) )
1322 /* Valid key; make sure the value doesn't contain a wildcard */
1323 if(strchr(value, '*')) {
1324 if(*(int *)found == 0) {
1325 MSG(fontmsgprologue);
1326 ++*(int *)found;
1329 MSG(" %s=%s [no wildcards allowed]\n", key, value);
1332 else {
1333 /* Not a valid key */
1334 if(*(int *)found == 0) {
1335 MSG(fontmsgprologue);
1336 ++*(int *)found;
1339 MSG(" %s=%s [obsolete]\n", key, value);
1342 return;
1345 /***********************************************************************
1346 * XFONT_GetPointResolution()
1348 * Here we initialize DefResolution which is used in the
1349 * XFONT_Match() penalty function. We also load the point
1350 * resolution value (higher values result in larger fonts).
1352 static int XFONT_GetPointResolution( DeviceCaps* pDevCaps )
1354 int i, j, point_resolution, num = 3;
1355 int allowed_xfont_resolutions[3] = { 72, 75, 100 };
1356 int best = 0, best_diff = 65536;
1358 DefResolution = point_resolution = PROFILE_GetWineIniInt( INIFontSection, INIResolution, 0 );
1359 if( !DefResolution ) DefResolution = point_resolution = pDevCaps->logPixelsY;
1360 else pDevCaps->logPixelsX = pDevCaps->logPixelsY = DefResolution;
1362 for( i = best = 0; i < num; i++ )
1364 j = abs( DefResolution - allowed_xfont_resolutions[i] );
1365 if( j < best_diff )
1367 best = i;
1368 best_diff = j;
1371 DefResolution = allowed_xfont_resolutions[best];
1372 return point_resolution;
1375 /***********************************************************************
1376 * X11DRV_FONT_Init
1378 * Initialize font resource list and allocate font cache.
1380 BOOL32 X11DRV_FONT_Init( DeviceCaps* pDevCaps )
1382 XFontStruct* x_fs;
1383 fontResource* fr, *pfr;
1384 fontInfo* fi, *pfi;
1385 unsigned x_checksum;
1386 int i, j, res, x_count, fd = -1, buf_size = 0;
1387 char* lpstr, *lpch, *lpmetrics, *buffer;
1388 char** x_pattern;
1390 XFONT_CheckIniSection();
1392 res = XFONT_GetPointResolution( pDevCaps );
1394 x_pattern = TSXListFonts(display, "*", MAX_FONT_FAMILIES * 16, &x_count );
1396 TRACE(font,"Font Mapper: initializing %i fonts [LPY=%i, XDR=%i, DR=%i]\n",
1397 x_count, pDevCaps->logPixelsY, DefResolution, res);
1398 for( i = x_checksum = 0; i < x_count; i++ )
1400 #if 0
1401 printf("%i\t: %s\n", i, x_pattern[i] );
1402 #endif
1404 j = strlen( x_pattern[i] );
1405 if( j ) x_checksum ^= __genericCheckSum( x_pattern[i], j );
1407 x_checksum |= X_PFONT_MAGIC;
1409 buf_size = 128;
1410 buffer = HeapAlloc( SystemHeap, 0, buf_size );
1411 lpmetrics = NULL;
1413 /* deal with systemwide font metrics cache */
1415 if( PROFILE_GetWineIniString( INIFontSection, INIGlobalMetrics, "", buffer, 128 ) )
1416 fd = open( buffer, O_RDONLY );
1418 if( XFONT_ReadCachedMetrics(fd, res, x_checksum, x_count) == FALSE )
1420 /* try per-user */
1421 buffer = XFONT_UserMetricsCache( buffer, &buf_size );
1422 if( buffer[0] )
1424 fd = open( buffer, O_RDONLY );
1425 if( XFONT_ReadCachedMetrics(fd, res, x_checksum, x_count) == FALSE )
1426 lpmetrics = HEAP_strdupA( SystemHeap, 0, buffer ); /* update later on */
1430 fi = NULL;
1431 if( fontList == NULL ) /* build metrics from scratch */
1433 int n_ff;
1434 char* typeface;
1436 for( i = n_ff = 0; i < x_count; i++ )
1438 typeface = lpch = x_pattern[i];
1440 lpch = LFD_Advance(typeface, 3); /* extra '-' in the beginning */
1441 if( !*lpch ) continue;
1443 lpstr = lpch;
1444 j = lpch - typeface; /* resource name length */
1446 /* find a family to insert into */
1448 for( pfr = NULL, fr = fontList; fr; fr = fr->next )
1450 if( !strncasecmp(fr->resource, typeface, j) &&
1451 strlen(fr->resource) == j ) break;
1452 pfr = fr;
1455 if( !fi ) fi = (fontInfo*) HeapAlloc(SystemHeap, 0, sizeof(fontInfo));
1457 if( !fr ) /* add new family */
1459 if( n_ff >= MAX_FONT_FAMILIES ) break;
1460 if( !LFD_InitFontInfo( fi, lpstr) ) continue;
1462 n_ff++;
1463 fr = (fontResource*) HeapAlloc(SystemHeap, 0, sizeof(fontResource));
1464 memset(fr, 0, sizeof(fontResource));
1465 fr->resource = (char*) HeapAlloc(SystemHeap, 0, j + 1 );
1466 lstrcpyn32A( fr->resource, typeface, j + 1 );
1468 TRACE(font," family: %s\n", fr->resource );
1470 if( pfr ) pfr->next = fr;
1471 else fontList = fr;
1473 else if( !LFD_InitFontInfo( fi, lpstr) ) continue;
1475 /* check if we already have something better than "fi" */
1477 for( pfi = fr->fi, j = 0; pfi && j <= 0; pfi = pfi->next )
1478 if( (j = XFONT_IsSubset( pfi, fi )) < 0 )
1479 pfi->fi_flags |= FI_SUBSET; /* superseded by "fi" */
1480 if( j > 0 ) continue;
1482 /* add new font instance "fi" to the "fr" font resource */
1484 if( fi->fi_flags & FI_SCALABLE )
1486 /* set scalable font height to 24 to get an origin for extrapolation */
1488 j = strlen(typeface); j += 0x10;
1489 if( j > buf_size )
1490 buffer = (char*)HeapReAlloc( SystemHeap, 0, buffer, buf_size = j );
1492 lpch = LFD_Advance(typeface, 7);
1493 memcpy( buffer, typeface, (j = lpch - typeface) );
1494 lpch = LFD_Advance(lpch, 4);
1495 sprintf( buffer + j, "%d-%d-%d-*-%c-*-", fi->lfd_height,
1496 fi->lfd_decipoints, fi->lfd_resolution,
1497 (*lpch == '-')?'*':*lpch );
1498 lpch = LFD_Advance(lpch, 2);
1499 strcat( lpstr = buffer, lpch);
1501 else lpstr = typeface;
1503 if( (x_fs = TSXLoadQueryFont(display, lpstr)) )
1505 fi->df.dfHorizRes = fi->df.dfVertRes = res;
1507 XFONT_SetFontMetric( fi, fr, x_fs );
1508 TSXFreeFont( display, x_fs );
1510 TRACE(font,"\t[% 2ipt] '%s'\n", fi->df.dfPoints, typeface );
1512 XFONT_CheckFIList( fr, fi, REMOVE_SUBSETS );
1513 fi = NULL; /* preventing reuse */
1515 else
1517 ERR(font, "failed to load %s\n", lpstr );
1519 XFONT_CheckFIList( fr, fi, UNMARK_SUBSETS );
1523 if( lpmetrics ) /* update cached metrics */
1525 fd = open( lpmetrics, O_CREAT | O_TRUNC | O_RDWR, 0644 ); /* -rw-r--r-- */
1526 if( XFONT_WriteCachedMetrics( fd, x_checksum, x_count, n_ff ) == FALSE )
1527 if( fd ) remove( lpmetrics ); /* couldn't write entire file */
1528 HeapFree( SystemHeap, 0, lpmetrics );
1532 if( fi ) HeapFree(SystemHeap, 0, fi);
1533 TSXFreeFontNames(x_pattern);
1535 /* check if we're dealing with X11 R6 server */
1537 strcpy(buffer, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1538 if( (x_fs = TSXLoadQueryFont(display, buffer)) )
1540 XTextCaps |= TC_SF_X_YINDEP;
1541 TSXFreeFont(display, x_fs);
1544 XFONT_WindowsNames( buffer );
1545 XFONT_LoadAliases( &buffer, buf_size );
1546 HeapFree(SystemHeap, 0, buffer);
1549 /* fontList initialization is over, allocate X font cache */
1551 fontCache = (fontObject*) HeapAlloc(SystemHeap, 0, fontCacheSize * sizeof(fontObject));
1552 XFONT_GrowFreeList(0, fontCacheSize - 1);
1554 TRACE(font,"done!\n");
1556 /* update text caps parameter */
1558 pDevCaps->textCaps = XTextCaps;
1560 RAW_ASCENT = TSXInternAtom(display, "RAW_ASCENT", TRUE);
1561 RAW_DESCENT = TSXInternAtom(display, "RAW_DESCENT", TRUE);
1563 return TRUE;
1567 /***********************************************************************
1568 * X Font Matching
1570 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1572 static INT32 XFONT_IsSubset(fontInfo* match, fontInfo* fi)
1574 INT32 m;
1576 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1578 m = (BYTE*)&fi->df.dfPixWidth - (BYTE*)&fi->df.dfItalic;
1579 if( memcmp(&match->df.dfItalic, &fi->df.dfItalic, m )) return 0;
1581 if( (!((fi->fi_flags & FI_SCALABLE) + (match->fi_flags & FI_SCALABLE))
1582 && fi->lfd_height != match->lfd_height) ||
1583 (!((fi->fi_flags & FI_POLYWEIGHT) + (match->fi_flags & FI_POLYWEIGHT))
1584 && fi->df.dfWeight != match->df.dfWeight) ) return 0;
1586 m = (int)(match->fi_flags & (FI_POLYWEIGHT | FI_SCALABLE)) -
1587 (int)(fi->fi_flags & (FI_SCALABLE | FI_POLYWEIGHT));
1589 if( m == (FI_POLYWEIGHT - FI_SCALABLE) ||
1590 m == (FI_SCALABLE - FI_POLYWEIGHT) ) return 0; /* keep both */
1591 else if( m >= 0 ) return 1; /* 'match' is better */
1593 return -1; /* 'fi' is better */
1596 /***********************************************************************
1597 * XFONT_Match
1599 * Compute the matching score between the logical font and the device font.
1601 * contributions from highest to lowest:
1602 * charset
1603 * fixed pitch
1604 * height
1605 * family flags (only when the facename is not present)
1606 * width
1607 * weight, italics, underlines, strikeouts
1609 * NOTE: you can experiment with different penalty weights to see what happens.
1610 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
1612 static UINT32 XFONT_Match( fontMatch* pfm )
1614 fontInfo* pfi = pfm->pfi; /* device font to match */
1615 LPLOGFONT16 plf = pfm->plf; /* wanted logical font */
1616 UINT32 penalty = 0;
1617 BOOL32 bR6 = pfm->flags & FO_MATCH_XYINDEP; /* from TextCaps */
1618 BOOL32 bScale = pfi->fi_flags & FI_SCALABLE;
1619 INT32 d, h;
1621 TRACE(font,"\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi->df.dfPoints,
1622 pfi->df.dfPixHeight, pfi->df.dfAvgWidth,
1623 (pfi->df.dfWeight > 400) ? "Bold " : "Normal ",
1624 (pfi->df.dfItalic) ? "Italic" : "" );
1626 pfm->flags = 0;
1628 if( plf->lfCharSet == DEFAULT_CHARSET )
1630 if( (pfi->df.dfCharSet!= ANSI_CHARSET) && (pfi->df.dfCharSet!=DEFAULT_CHARSET) )
1631 penalty += 0x200;
1633 else if (plf->lfCharSet != pfi->df.dfCharSet) penalty += 0x200;
1635 /* FIXME: Hack to demote symbols and nil fonts. Should take into
1636 account if a program ever actually asked for this type of
1637 font */
1638 if ( (strcmp(pfm->pfr->lfFaceName,"Symbol")==0) || (strcmp(pfm->pfr->lfFaceName,"Nil")==0) )
1639 penalty += 0x200; /* very stiff penality */
1641 /* TMPF_FIXED_PITCH means exactly the opposite */
1643 if( plf->lfPitchAndFamily & FIXED_PITCH )
1645 if( pfi->df.dfPitchAndFamily & TMPF_FIXED_PITCH ) penalty += 0x100;
1647 else if( !(pfi->df.dfPitchAndFamily & TMPF_FIXED_PITCH) ) penalty += 0x2;
1649 if( plf->lfHeight > 0 )
1650 d = (h = pfi->df.dfPixHeight) - plf->lfHeight;
1651 else if( plf->lfHeight < -1 )
1652 d = (h = pfi->df.dfPoints) + plf->lfHeight;
1653 else d = h = 0;
1655 if( d && plf->lfHeight )
1657 UINT16 height = ( plf->lfHeight > 0 ) ? plf->lfHeight
1658 : ((-plf->lfHeight * pfi->df.dfPixHeight) / h);
1659 if( bScale ) pfm->height = height;
1660 else if( (plf->lfQuality != PROOF_QUALITY) && bR6 )
1662 if( d > 0 ) /* do not shrink raster fonts */
1664 pfm->height = pfi->df.dfPixHeight;
1665 penalty += (pfi->df.dfPixHeight - height) * 0x4;
1667 else /* expand only in integer multiples */
1669 pfm->height = height - height%pfi->df.dfPixHeight;
1670 penalty += (height - pfm->height + 1) * height / pfi->df.dfPixHeight;
1673 else /* can't be scaled at all */
1675 if( plf->lfQuality != PROOF_QUALITY) pfm->flags |= FO_SYNTH_HEIGHT;
1676 pfm->height = pfi->df.dfPixHeight;
1677 penalty += (d > 0)? d * 0x8 : -d * 0x10;
1679 } else pfm->height = pfi->df.dfPixHeight;
1681 if((pfm->flags & FO_MATCH_PAF) &&
1682 (plf->lfPitchAndFamily & FF_FAMILY) != (pfi->df.dfPitchAndFamily & FF_FAMILY) )
1683 penalty += 0x10;
1685 if( plf->lfWidth )
1687 if( bR6 && bScale ) h = 0;
1688 else
1690 /* FIXME: not complete */
1692 pfm->flags |= FO_SYNTH_WIDTH;
1693 h = abs(plf->lfWidth - (pfm->height * pfi->df.dfAvgWidth)/pfi->df.dfPixHeight);
1695 penalty += h * ( d ) ? 0x2 : 0x1 ;
1697 else if( !(pfi->fi_flags & FI_NORMAL) ) penalty++;
1699 if( plf->lfWeight != FW_DONTCARE )
1701 penalty += abs(plf->lfWeight - pfi->df.dfWeight) / 40;
1702 if( plf->lfWeight > pfi->df.dfWeight ) pfm->flags |= FO_SYNTH_BOLD;
1703 } else if( pfi->df.dfWeight >= FW_BOLD ) penalty++; /* choose normal by default */
1705 if( plf->lfItalic != pfi->df.dfItalic )
1707 penalty += 0x4;
1708 pfm->flags |= FO_SYNTH_ITALIC;
1711 if( plf->lfUnderline ) pfm->flags |= FO_SYNTH_UNDERLINE;
1712 if( plf->lfStrikeOut ) pfm->flags |= FO_SYNTH_STRIKEOUT;
1714 if( penalty && pfi->lfd_resolution != DefResolution )
1715 penalty++;
1717 TRACE(font," returning %i\n", penalty );
1719 return penalty;
1722 /***********************************************************************
1723 * XFONT_MatchFIList
1725 * Scan a particular font resource for the best match.
1727 static UINT32 XFONT_MatchFIList( fontMatch* pfm )
1729 BOOL32 skipRaster = (pfm->flags & FO_MATCH_NORASTER);
1730 UINT32 current_score, score = (UINT32)(-1);
1731 UINT16 origflags = pfm->flags; /* Preserve FO_MATCH_XYINDEP */
1732 fontMatch fm = *pfm;
1734 for( fm.pfi = pfm->pfr->fi; fm.pfi && score; fm.pfi = fm.pfi->next,
1735 fm.flags = origflags )
1737 if( skipRaster && !(fm.pfi->fi_flags & FI_SCALABLE) )
1738 continue;
1740 current_score = XFONT_Match( &fm );
1741 if( score > current_score )
1743 memcpy( pfm, &fm, sizeof(fontMatch) );
1744 score = current_score;
1747 return score;
1750 /***********************************************************************
1751 * XFONT_CheckFIList
1753 * REMOVE_SUBSETS - attach new fi and purge subsets
1754 * UNMARK_SUBSETS - remove subset flags from all fi entries
1756 static void XFONT_CheckFIList( fontResource* fr, fontInfo* fi, int action)
1758 int i = 0;
1759 fontInfo* pfi, *prev;
1761 for( prev = NULL, pfi = fr->fi; pfi; )
1763 if( action == REMOVE_SUBSETS )
1765 if( pfi->fi_flags & FI_SUBSET )
1767 fontInfo* subset = pfi;
1769 i++;
1770 fr->count--;
1771 if( prev ) prev->next = pfi = pfi->next;
1772 else fr->fi = pfi = pfi->next;
1773 HeapFree( SystemHeap, 0, subset );
1774 continue;
1777 else pfi->fi_flags &= ~FI_SUBSET;
1779 prev = pfi;
1780 pfi = pfi->next;
1783 if( action == REMOVE_SUBSETS ) /* also add the superset */
1785 if( fi->fi_flags & FI_SCALABLE )
1787 fi->next = fr->fi;
1788 fr->fi = fi;
1790 else if( prev ) prev->next = fi; else fr->fi = fi;
1791 fr->count++;
1794 if( i ) TRACE(font,"\t purged %i subsets [%i]\n", i , fr->count);
1797 /***********************************************************************
1798 * XFONT_FindFIList
1800 static fontResource* XFONT_FindFIList( fontResource* pfr, const char* pTypeFace )
1802 while( pfr )
1804 if( !strcasecmp( pfr->lfFaceName, pTypeFace ) ) break;
1805 pfr = pfr->next;
1807 return pfr;
1810 /***********************************************************************
1811 * XFONT_MatchDeviceFont
1813 * Scan font resource tree.
1815 static BOOL32 XFONT_MatchDeviceFont( fontResource* start, fontMatch* pfm )
1817 fontMatch fm = *pfm;
1819 pfm->pfi = NULL;
1820 if( fm.plf->lfFaceName[0] )
1822 fontAlias* fa;
1823 LPSTR str = NULL;
1825 for( fa = aliasTable; fa; fa = fa->next )
1826 if( !strcmp( fa->faAlias, fm.plf->lfFaceName ) )
1828 str = fa->faTypeFace;
1829 break;
1831 fm.pfr = XFONT_FindFIList( start, str ? str : fm.plf->lfFaceName );
1834 if( fm.pfr ) /* match family */
1836 TRACE(font, "%s\n", fm.pfr->lfFaceName );
1838 XFONT_MatchFIList( &fm );
1839 *pfm = fm;
1842 if( !pfm->pfi ) /* match all available fonts */
1844 UINT32 current_score, score = (UINT32)(-1);
1846 fm.flags |= FO_MATCH_PAF;
1847 for( start = fontList; start && score; start = start->next )
1849 fm.pfr = start;
1851 TRACE(font, "%s\n", fm.pfr->lfFaceName );
1853 current_score = XFONT_MatchFIList( &fm );
1854 if( current_score < score )
1856 score = current_score;
1857 *pfm = fm;
1861 return TRUE;
1865 /***********************************************************************
1866 * X Font Cache
1868 static void XFONT_GrowFreeList(int start, int end)
1870 /* add all entries from 'start' up to and including 'end' */
1872 memset( fontCache + start, 0, (end - start + 1) * sizeof(fontObject) );
1874 fontCache[end].lru = fontLF;
1875 fontCache[end].count = -1;
1876 fontLF = start;
1877 while( start < end )
1879 fontCache[start].count = -1;
1880 fontCache[start].lru = start + 1;
1881 start++;
1885 static fontObject* XFONT_LookupCachedFont( LPLOGFONT16 plf, UINT16* checksum )
1887 UINT16 cs = __lfCheckSum( plf );
1888 int i = fontMRU, prev = -1;
1890 *checksum = cs;
1891 while( i >= 0 )
1893 if( fontCache[i].lfchecksum == cs &&
1894 !(fontCache[i].fo_flags & FO_REMOVED) )
1896 /* FIXME: something more intelligent here */
1898 if( !memcmp( plf, &fontCache[i].lf,
1899 sizeof(LOGFONT16) - LF_FACESIZE ) &&
1900 !strncasecmp( plf->lfFaceName, fontCache[i].lf.lfFaceName,
1901 LF_FACESIZE ) )
1903 /* remove temporarily from the lru list */
1905 if( prev >= 0 )
1906 fontCache[prev].lru = fontCache[i].lru;
1907 else
1908 fontMRU = (INT16)fontCache[i].lru;
1909 return (fontCache + i);
1912 prev = i;
1913 i = (INT16)fontCache[i].lru;
1915 return NULL;
1918 static fontObject* XFONT_GetCacheEntry()
1920 int i;
1922 if( fontLF == -1 )
1924 int prev_i, prev_j, j;
1926 TRACE(font,"font cache is full\n");
1928 /* lookup the least recently used font */
1930 for( prev_i = prev_j = j = -1, i = fontMRU; i >= 0; i = (INT16)fontCache[i].lru )
1932 if( fontCache[i].count <= 0 &&
1933 !(fontCache[i].fo_flags & FO_SYSTEM) )
1935 prev_j = prev_i;
1936 j = i;
1938 prev_i = i;
1941 if( j >= 0 ) /* unload font */
1943 /* detach from the lru list */
1945 TRACE(font,"\tfreeing entry %i\n", j );
1947 if( prev_j >= 0 )
1948 fontCache[prev_j].lru = fontCache[j].lru;
1949 else fontMRU = (INT16)fontCache[j].lru;
1951 /* FIXME: lpXForm, lpPixmap */
1952 if(fontCache[j].lpX11Trans)
1953 HeapFree( SystemHeap, 0, fontCache[j].lpX11Trans );
1955 TSXFreeFont( display, fontCache[j].fs );
1957 memset( fontCache + j, 0, sizeof(fontObject) );
1958 return (fontCache + j);
1960 else /* expand cache */
1962 fontObject* newCache;
1964 prev_i = fontCacheSize + FONTCACHE;
1966 TRACE(font,"\tgrowing font cache from %i to %i\n", fontCacheSize, prev_i );
1968 if( (newCache = (fontObject*)HeapReAlloc(SystemHeap, 0,
1969 fontCache, prev_i)) )
1971 i = fontCacheSize;
1972 fontCacheSize = prev_i;
1973 fontCache = newCache;
1974 XFONT_GrowFreeList( i, fontCacheSize - 1);
1976 else return NULL;
1980 /* detach from the free list */
1982 i = fontLF;
1983 fontLF = (INT16)fontCache[i].lru;
1984 fontCache[i].count = 0;
1985 return (fontCache + i);
1988 static int XFONT_ReleaseCacheEntry(fontObject* pfo)
1990 UINT32 u = (UINT32)(pfo - fontCache);
1992 if( u < fontCacheSize ) return (--fontCache[u].count);
1993 return -1;
1996 /**********************************************************************
1997 * XFONT_SetX11Trans
1999 static BOOL32 XFONT_SetX11Trans( fontObject *pfo )
2001 char *fontName;
2002 Atom nameAtom;
2003 int i;
2004 char *cp, *start;
2006 TSXGetFontProperty( pfo->fs, XA_FONT, &nameAtom );
2007 fontName = TSXGetAtomName( display, nameAtom );
2008 for(i = 0, cp = fontName; i < 7; i++) {
2009 cp = strchr(cp, '-');
2010 cp++;
2012 if(*cp != '[') {
2013 TSXFree(fontName);
2014 return FALSE;
2016 start = cp;
2017 while((cp = strchr(cp, '~')))
2018 *cp = '-';
2020 #define PX pfo->lpX11Trans
2022 sscanf(start, "[%f%f%f%f]", &PX->a, &PX->b, &PX->c, &PX->d);
2023 TSXFree(fontName);
2025 TSXGetFontProperty( pfo->fs, RAW_ASCENT, &PX->RAW_ASCENT );
2026 TSXGetFontProperty( pfo->fs, RAW_DESCENT, &PX->RAW_DESCENT );
2028 PX->pixelsize = hypot(PX->a, PX->b);
2029 PX->ascent = PX->pixelsize / 1000.0 * PX->RAW_ASCENT;
2030 PX->descent = PX->pixelsize / 1000.0 * PX->RAW_DESCENT;
2032 TRACE(font, "[%f %f %f %f] RA = %ld RD = %ld\n", pfo->lpX11Trans->a,
2033 pfo->lpX11Trans->b, pfo->lpX11Trans->c, pfo->lpX11Trans->d,
2034 pfo->lpX11Trans->RAW_ASCENT, pfo->lpX11Trans->RAW_DESCENT);
2036 #undef PX
2037 return TRUE;
2040 /***********************************************************************
2041 * X Device Font Objects
2043 static X_PHYSFONT XFONT_RealizeFont( LPLOGFONT16 plf )
2045 UINT16 checksum;
2046 fontObject* pfo = XFONT_LookupCachedFont( plf, &checksum );
2048 if( !pfo )
2050 fontMatch fm = { NULL, NULL, 0, 0, plf};
2051 INT32 i, index;
2053 if( XTextCaps & TC_SF_X_YINDEP ) fm.flags = FO_MATCH_XYINDEP;
2055 /* allocate new font cache entry */
2057 if( (pfo = XFONT_GetCacheEntry()) )
2059 LPSTR lpLFD = HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH );
2061 if( lpLFD ) /* initialize entry and load font */
2063 UINT32 uRelaxLevel = 0;
2065 TRACE(font,"(%u) '%s' h=%i weight=%i %s\n",
2066 plf->lfCharSet, plf->lfFaceName, plf->lfHeight,
2067 plf->lfWeight, (plf->lfItalic) ? "Italic" : "" );
2069 XFONT_MatchDeviceFont( fontList, &fm );
2071 pfo->fr = fm.pfr;
2072 pfo->fi = fm.pfi;
2073 pfo->fo_flags = fm.flags & ~FO_MATCH_MASK;
2075 memcpy( &pfo->lf, plf, sizeof(LOGFONT16) );
2076 pfo->lfchecksum = checksum;
2080 LFD_ComposeLFD( pfo, fm.height, lpLFD, uRelaxLevel++ );
2081 if( (pfo->fs = TSXLoadQueryFont( display, lpLFD )) ) break;
2082 } while( uRelaxLevel );
2085 if(pfo->lf.lfEscapement != 0) {
2086 pfo->lpX11Trans = HeapAlloc(SystemHeap, 0,
2087 sizeof(XFONTTRANS));
2088 if(!XFONT_SetX11Trans( pfo )) {
2089 HeapFree(SystemHeap, 0, pfo->lpX11Trans);
2090 pfo->lpX11Trans = NULL;
2094 if( XFONT_GetLeading( &pfo->fi->df, pfo->fs, &i, NULL,
2095 pfo->lpX11Trans ) )
2097 if(!pfo->lpX11Trans)
2098 pfo->foAvgCharWidth =
2099 (INT16)pfo->fs->per_char['X' - pfo->fs->min_char_or_byte2].width;
2100 else
2101 pfo->foAvgCharWidth =
2102 (INT16)pfo->fs->per_char['X' - pfo->fs->min_char_or_byte2].attributes
2103 * pfo->lpX11Trans->pixelsize / 1000.0;
2104 else
2105 pfo->foAvgCharWidth = (INT16)XFONT_GetAvgCharWidth(
2106 &pfo->fi->df, pfo->fs, pfo->lpX11Trans );
2107 pfo->foMaxCharWidth = (INT16)XFONT_GetMaxCharWidth(pfo);
2108 pfo->foInternalLeading = (INT16)i;
2110 /* FIXME: If we've got a soft font or
2111 * there are FO_SYNTH_... flags for the
2112 * non PROOF_QUALITY request, the engine
2113 * should rasterize characters into mono
2114 * pixmaps and store them in the pfo->lpPixmap
2115 * array (pfo->fs should be updated as well).
2116 * X11DRV_ExtTextOut() must be heavily modified
2117 * to support pixmap blitting and FO_SYNTH_...
2118 * styles.
2121 pfo->lpXForm = NULL;
2122 pfo->lpPixmap = NULL;
2124 HeapFree( GetProcessHeap(), 0, lpLFD );
2126 else /* attach back to the free list */
2128 pfo->count = -1;
2129 pfo->lru = fontLF;
2130 fontLF = (pfo - fontCache);
2131 pfo = NULL;
2135 if( !pfo ) /* couldn't get a new entry, get one of the cached fonts */
2137 UINT32 current_score, score = (UINT32)(-1);
2139 i = index = fontMRU;
2140 fm.flags |= FO_MATCH_PAF;
2143 pfo = fontCache + i;
2144 fm.pfr = pfo->fr; fm.pfi = pfo->fi;
2146 current_score = XFONT_Match( &fm );
2147 if( current_score < score ) index = i;
2149 i = pfo->lru;
2150 } while( i >= 0 );
2151 pfo = fontCache + index;
2152 pfo->count++;
2153 return (X_PHYSFONT)(X_PFONT_MAGIC | index);
2157 /* attach at the head of the lru list */
2159 pfo->count++;
2160 pfo->lru = fontMRU;
2161 fontMRU = (pfo - fontCache);
2163 TRACE(font,"physfont %i\n", fontMRU);
2165 return (X_PHYSFONT)(X_PFONT_MAGIC | fontMRU);
2168 /***********************************************************************
2169 * XFONT_GetFontObject
2171 fontObject* XFONT_GetFontObject( X_PHYSFONT pFont )
2173 if( CHECK_PFONT(pFont) ) return __PFONT(pFont);
2174 return NULL;
2177 /***********************************************************************
2178 * XFONT_GetFontStruct
2180 XFontStruct* XFONT_GetFontStruct( X_PHYSFONT pFont )
2182 if( CHECK_PFONT(pFont) ) return __PFONT(pFont)->fs;
2183 return NULL;
2186 /***********************************************************************
2187 * XFONT_GetFontInfo
2189 LPIFONTINFO16 XFONT_GetFontInfo( X_PHYSFONT pFont )
2191 if( CHECK_PFONT(pFont) ) return &(__PFONT(pFont)->fi->df);
2192 return NULL;
2197 /* X11DRV Interface ****************************************************
2199 * Exposed via the dc->funcs dispatch table. *
2201 ***********************************************************************/
2202 /***********************************************************************
2203 * X11DRV_FONT_SelectObject
2205 HFONT32 X11DRV_FONT_SelectObject( DC* dc, HFONT32 hfont, FONTOBJ* font )
2207 HFONT32 hPrevFont = 0;
2208 LOGFONT16 lf;
2209 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2211 if( CHECK_PFONT(physDev->font) )
2212 XFONT_ReleaseCacheEntry( __PFONT(physDev->font) );
2214 /* FIXME: do we need to pass anything back from here? */
2215 memcpy(&lf,&font->logfont,sizeof(lf));
2216 lf.lfWidth = font->logfont.lfWidth * dc->vportExtX/dc->wndExtX;
2217 lf.lfHeight = font->logfont.lfHeight* dc->vportExtY/dc->wndExtY;
2219 physDev->font = XFONT_RealizeFont( &lf );
2220 hPrevFont = dc->w.hFont;
2221 dc->w.hFont = hfont;
2223 return hPrevFont;
2227 /***********************************************************************
2229 * X11DRV_EnumDeviceFonts
2231 BOOL32 X11DRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf,
2232 DEVICEFONTENUMPROC proc, LPARAM lp )
2234 ENUMLOGFONTEX16 lf;
2235 NEWTEXTMETRIC16 tm;
2236 fontResource* pfr = fontList;
2237 BOOL32 b, bRet = 0;
2239 if( plf->lfFaceName[0] )
2241 pfr = XFONT_FindFIList( pfr, plf->lfFaceName );
2242 if( pfr )
2244 fontInfo* pfi;
2245 for( pfi = pfr->fi; pfi; pfi = pfi->next )
2246 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
2247 XFONT_GetFontMetric( pfi, &lf, &tm ), lp )) )
2248 bRet = b;
2249 else break;
2252 else
2253 for( ; pfr ; pfr = pfr->next )
2254 if(pfr->fi)
2256 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
2257 XFONT_GetFontMetric( pfr->fi, &lf, &tm ), lp )) )
2258 bRet = b;
2259 else break;
2262 return bRet;
2266 /***********************************************************************
2267 * X11DRV_GetTextExtentPoint
2269 BOOL32 X11DRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT32 count,
2270 LPSIZE32 size )
2272 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2273 fontObject* pfo = XFONT_GetFontObject( physDev->font );
2274 if( pfo ) {
2275 if( !pfo->lpX11Trans ) {
2276 int dir, ascent, descent;
2277 XCharStruct info;
2279 TSXTextExtents( pfo->fs, str, count, &dir, &ascent, &descent, &info );
2280 size->cx = abs((info.width + dc->w.breakRem + count *
2281 dc->w.charExtra) * dc->wndExtX / dc->vportExtX);
2282 size->cy = abs((pfo->fs->ascent + pfo->fs->descent) *
2283 dc->wndExtY / dc->vportExtY);
2284 } else {
2286 INT32 i;
2287 float x = 0.0, y = 0.0;
2288 for(i = 0; i < count; i++) {
2289 x += pfo->fs->per_char ?
2290 pfo->fs->per_char[str[i] - pfo->fs->min_char_or_byte2].attributes :
2291 pfo->fs->min_bounds.attributes;
2293 y = pfo->lpX11Trans->RAW_ASCENT + pfo->lpX11Trans->RAW_DESCENT;
2294 TRACE(font, "x = %f y = %f\n", x, y);
2295 x *= pfo->lpX11Trans->pixelsize / 1000.0;
2296 y *= pfo->lpX11Trans->pixelsize / 1000.0;
2297 size->cx = fabsf((x + dc->w.breakRem + count * dc->w.charExtra) *
2298 dc->wndExtX / dc->vportExtX);
2299 size->cy = fabsf(y * dc->wndExtY / dc->vportExtY);
2301 return TRUE;
2303 return FALSE;
2307 /***********************************************************************
2308 * X11DRV_GetTextMetrics
2310 BOOL32 X11DRV_GetTextMetrics(DC *dc, TEXTMETRIC32A *metrics)
2312 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2314 if( CHECK_PFONT(physDev->font) )
2316 fontObject* pfo = __PFONT(physDev->font);
2317 XFONT_GetTextMetric( pfo, metrics );
2319 return TRUE;
2321 return FALSE;
2325 /***********************************************************************
2326 * X11DRV_GetCharWidth
2328 BOOL32 X11DRV_GetCharWidth( DC *dc, UINT32 firstChar, UINT32 lastChar,
2329 LPINT32 buffer )
2331 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2332 fontObject* pfo = XFONT_GetFontObject( physDev->font );
2334 if( pfo )
2336 int i;
2338 if (pfo->fs->per_char == NULL)
2339 for (i = firstChar; i <= lastChar; i++)
2340 if(pfo->lpX11Trans)
2341 *buffer++ = pfo->fs->min_bounds.attributes *
2342 pfo->lpX11Trans->pixelsize / 1000.0;
2343 else
2344 *buffer++ = pfo->fs->min_bounds.width;
2345 else
2347 XCharStruct *cs, *def;
2348 static XCharStruct __null_char = { 0, 0, 0, 0, 0, 0 };
2350 CI_GET_CHAR_INFO(pfo->fs, pfo->fs->default_char, &__null_char,
2351 def);
2353 for (i = firstChar; i <= lastChar; i++)
2355 if (i >= pfo->fs->min_char_or_byte2 &&
2356 i <= pfo->fs->max_char_or_byte2)
2358 cs = &pfo->fs->per_char[(i - pfo->fs->min_char_or_byte2)];
2359 if (CI_NONEXISTCHAR(cs)) cs = def;
2360 } else cs = def;
2361 if(pfo->lpX11Trans)
2362 *buffer++ = MAX(cs->attributes, 0) *
2363 pfo->lpX11Trans->pixelsize / 1000.0;
2364 else
2365 *buffer++ = MAX(cs->width, 0 );
2369 return TRUE;
2371 return FALSE;
2374 /***********************************************************************
2376 * Font Resource API *
2378 ***********************************************************************/
2379 /***********************************************************************
2380 * AddFontResource16 (GDI.119)
2382 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
2384 * FIXME: Load header and find the best-matching font in the fontList;
2385 * fixup dfPoints if all metrics are identical, otherwise create
2386 * new fontAlias. When soft font support is ready this will
2387 * simply create a new fontResource ('filename' will go into
2388 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
2389 * flag set.
2391 INT16 WINAPI AddFontResource16( LPCSTR filename )
2393 return AddFontResource32A( filename );
2397 /***********************************************************************
2398 * AddFontResource32A (GDI32.2)
2400 INT32 WINAPI AddFontResource32A( LPCSTR str )
2402 FIXME(font, "(%s): stub\n", debugres_a(str));
2403 return 1;
2407 /***********************************************************************
2408 * AddFontResource32W (GDI32.4)
2410 INT32 WINAPI AddFontResource32W( LPCWSTR str )
2412 FIXME(font, "(%s): stub\n", debugres_w(str) );
2413 return 1;
2416 /***********************************************************************
2417 * RemoveFontResource16 (GDI.136)
2419 BOOL16 WINAPI RemoveFontResource16( SEGPTR str )
2421 FIXME(font, "(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str)));
2422 return TRUE;
2426 /***********************************************************************
2427 * RemoveFontResource32A (GDI32.284)
2429 BOOL32 WINAPI RemoveFontResource32A( LPCSTR str )
2431 FIXME(font, "(%s): stub\n", debugres_a(str));
2432 return TRUE;
2436 /***********************************************************************
2437 * RemoveFontResource32W (GDI32.286)
2439 BOOL32 WINAPI RemoveFontResource32W( LPCWSTR str )
2441 FIXME(font, "(%s): stub\n", debugres_w(str) );
2442 return TRUE;