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).
16 #include <sys/types.h>
20 #include <X11/Xatom.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
47 struct __fontAlias* next;
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 UINT16 XTextCaps = TC_OP_CHARACTER | TC_OP_STROKE |
77 TC_CP_STROKE | TC_CR_ANY |
78 TC_SA_DOUBLE | TC_SA_INTEGER | TC_SA_CONTIN |
79 TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
81 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
83 static const char* INIWinePrefix = "/.wine";
84 static const char* INIFontMetrics = "/.cachedmetrics";
85 static const char* INIFontSection = "fonts";
86 static const char* INISubSection = "Alias";
87 static const char* INIDefault = "Default";
88 static const char* INIDefaultFixed = "DefaultFixed";
89 static const char* INIResolution = "Resolution";
90 static const char* INIGlobalMetrics = "FontMetrics";
92 static const char* LFDSeparator = "*-";
93 static const char* MSEncoding = "microsoft-";
94 static const char* iso8859Encoding = "iso8859-";
95 static const char* iso646Encoding = "iso646.1991-";
96 static const char* ansiEncoding = "ansi-";
97 static unsigned DefResolution = 0;
99 static fontResource* fontList = NULL;
100 static fontObject* fontCache = NULL; /* array */
101 static int fontCacheSize = FONTCACHE;
102 static int fontLF = -1, fontMRU = -1; /* last free, most recently used */
104 #define __PFONT(pFont) ( fontCache + ((UINT32)(pFont) & 0x0000FFFF) )
105 #define CHECK_PFONT(pFont) ( (((UINT32)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
106 (((UINT32)(pFont) & 0x0000FFFF) < fontCacheSize) )
108 static INT32 XFONT_IsSubset(fontInfo*, fontInfo*);
109 static void XFONT_CheckFIList(fontResource*, fontInfo*, int subset_action);
110 static void XFONT_GrowFreeList(int start, int end);
113 static Atom RAW_ASCENT;
114 static Atom RAW_DESCENT;
116 /***********************************************************************
117 * Helper macros from X distribution
120 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
121 (((cs)->rbearing|(cs)->lbearing| \
122 (cs)->ascent|(cs)->descent) == 0))
124 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
127 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
128 if (fs->per_char == NULL) { \
129 cs = &fs->min_bounds; \
131 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
132 if (CI_NONEXISTCHAR(cs)) cs = def; \
137 #define CI_GET_DEFAULT_INFO(fs,cs) \
138 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
140 /***********************************************************************
143 static UINT16 __lfCheckSum( LPLOGFONT16 plf )
145 CHAR font[LF_FACESIZE];
149 #define ptr ((UINT16*)plf)
150 for( i = 0; i < 9; i++ ) checksum ^= *ptr++;
153 #define ptr ((CHAR*)plf)
154 do { font[i++] = tolower(*ptr++); } while (( i < LF_FACESIZE) && (*ptr) && (*ptr!=' '));
155 for( ptr = font, i >>= 1; i > 0; i-- )
157 #define ptr ((UINT16*)plf)
163 static UINT16 __genericCheckSum( const void *ptr, int size )
165 unsigned int checksum = 0;
166 const char *p = (const char *)ptr;
168 checksum ^= (checksum << 3) + (checksum >> 29) + *p++;
170 return checksum & 0xffff;
173 /*************************************************************************
174 * LFD parse/compose routines
176 static char* LFD_Advance(LPSTR lpFont, UINT16 uParmsNo)
181 for( ; j < uParmsNo && *lpch; lpch++ ) if( *lpch == LFDSeparator[1] ) j++;
185 static void LFD_GetWeight( fontInfo* fi, LPSTR lpStr, int j)
187 if( j == 1 && *lpStr == '0' )
188 fi->fi_flags |= FI_POLYWEIGHT;
191 if( !strncasecmp( "bold", lpStr, 4) )
192 fi->df.dfWeight = FW_BOLD;
193 else if( !strncasecmp( "demi", lpStr, 4) )
195 fi->fi_flags |= FI_FW_DEMI;
196 fi->df.dfWeight = FW_DEMIBOLD;
198 else if( !strncasecmp( "book", lpStr, 4) )
200 fi->fi_flags |= FI_FW_BOOK;
201 fi->df.dfWeight = FW_REGULAR;
206 if( !strncasecmp( "light", lpStr, 5) )
207 fi->df.dfWeight = FW_LIGHT;
208 else if( !strncasecmp( "black", lpStr, 5) )
209 fi->df.dfWeight = FW_BLACK;
211 else if( j == 6 && !strncasecmp( "medium", lpStr, 6) )
212 fi->df.dfWeight = FW_REGULAR;
213 else if( j == 8 && !strncasecmp( "demibold", lpStr, 8) )
214 fi->df.dfWeight = FW_DEMIBOLD;
216 fi->df.dfWeight = FW_DONTCARE; /* FIXME: try to get something
217 * from the weight property */
220 static int LFD_GetSlant( fontInfo* fi, LPSTR lpStr, int l)
224 switch( tolower( *lpStr ) )
226 case '0': fi->fi_flags |= FI_POLYSLANT; /* haven't seen this one yet */
228 case 'r': fi->df.dfItalic = 0;
231 fi->fi_flags |= FI_OBLIQUE;
232 case 'i': fi->df.dfItalic = 1;
240 /*************************************************************************
243 * Fill in some fields in the fontInfo struct.
245 static int LFD_InitFontInfo( fontInfo* fi, LPSTR lpstr )
248 int i, j, dec_style_check, scalability;
251 memset(fi, 0, sizeof(fontInfo) );
254 lpch = LFD_Advance( lpstr, 1);
255 if( !*lpch ) return FALSE;
256 j = lpch - lpstr - 1;
257 LFD_GetWeight( fi, lpstr, j );
260 lpch = LFD_Advance( lpstr = lpch, 1);
261 if( !*lpch ) return FALSE;
262 j = lpch - lpstr - 1;
263 dec_style_check = LFD_GetSlant( fi, lpstr, j );
266 lpch = LFD_Advance( lpstr = lpch, 1);
267 if( !*lpch ) return FALSE;
268 if( strncasecmp( "normal", lpstr, 6) ) /* XXX 'narrow', 'condensed', etc... */
269 dec_style_check = TRUE;
271 fi->fi_flags |= FI_NORMAL;
274 lpch = LFD_Advance( lpstr = lpch, 1);
275 if( !*lpch ) return FALSE;
276 j = lpch - lpstr - 1;
277 if( j > 3 ) /* find out is there "sans" or "script" */
282 if( strstr(lpstr, "sans") )
284 fi->df.dfPitchAndFamily |= FF_SWISS;
287 if( strstr(lpstr, "script") )
289 fi->df.dfPitchAndFamily |= FF_SCRIPT;
292 if( !j && dec_style_check )
293 fi->df.dfPitchAndFamily |= FF_DECORATIVE;
294 *(lpch - 1) = LFDSeparator[1];
297 /* pixel height, decipoint height, and res_x */
299 for( i = scalability = 0; i < 3; i++ )
301 lpch = LFD_Advance( lpstr = lpch, 1);
302 if( !*lpch ) return FALSE;
303 if( lpch - lpstr == 1 || lpch - lpstr > 4 ) return FALSE; /* ridiculous */
306 if( !(tmp[i] = atoi(lpstr)) ) scalability++;
307 *(lpch - 1) = LFDSeparator[1];
309 if( scalability == 3 ) /* Type1 */
311 fi->fi_flags |= FI_SCALABLE;
312 fi->lfd_height = DEF_SCALABLE_HEIGHT; fi->lfd_decipoints = DEF_SCALABLE_DP;
313 fi->lfd_resolution = DefResolution;
315 else if( scalability == 0 ) /* Bitmap */
317 fi->lfd_height = tmp[0]; fi->lfd_decipoints = tmp[1];
318 fi->lfd_resolution = tmp[2];
320 else return FALSE; /* #$%^!!! X11R6 mutant garbage */
322 /* res_y - skip, spacing - */
323 lpstr = LFD_Advance( lpch, 1);
326 case '\0': return FALSE;
328 case 'p': fi->fi_flags |= FI_VARIABLEPITCH;
330 case 'c': fi->df.dfPitchAndFamily |= FF_MODERN;
331 fi->fi_flags |= FI_FIXEDEX;
333 case 'm': fi->fi_flags |= FI_FIXEDPITCH;
336 fi->df.dfPitchAndFamily |= DEFAULT_PITCH | FF_DONTCARE;
338 lpstr = LFD_Advance(lpstr, 1);
339 if( !*lpstr ) return FALSE;
341 /* average width - */
342 lpch = LFD_Advance( lpstr, 1);
343 if( !*lpch ) return FALSE;
344 if( lpch - lpstr == 1 || lpch - lpstr > 4 ) return FALSE; /* ridiculous */
346 if( !(fi->lfd_width = atoi(lpstr)) && !scalability ) return FALSE;
347 *(lpch - 1) = LFDSeparator[1];
349 /* charset registry, charset encoding - */
350 if( strstr(lpch, "jisx") ||
351 strstr(lpch, "ksc") ||
352 strstr(lpch, "gb2312") ||
353 strstr(lpch, "big5") ||
354 strstr(lpch, "unicode") ) return FALSE; /* 2-byte stuff */
356 fi->df.dfCharSet = ANSI_CHARSET;
357 if( strstr(lpch, iso8859Encoding) ) {
358 fi->fi_flags |= FI_ENC_ISO8859;
359 if( strstr(lpch, "iso8859-15") ) fi->df.dfCharSet = ANSI_CHARSET;
360 else if( strstr(lpch, "iso8859-11") ) fi->df.dfCharSet = THAI_CHARSET;
361 else if( strstr(lpch, "iso8859-10") ) fi->df.dfCharSet = BALTIC_CHARSET;
362 else if( strstr(lpch, "iso8859-9") ) fi->df.dfCharSet = TURKISH_CHARSET;
363 else if( strstr(lpch, "iso8859-8") ) fi->df.dfCharSet = HEBREW_CHARSET;
364 else if( strstr(lpch, "iso8859-7") ) fi->df.dfCharSet = GREEK_CHARSET;
365 else if( strstr(lpch, "iso8859-6") ) fi->df.dfCharSet = ARABIC_CHARSET;
366 else if( strstr(lpch, "iso8859-5") ) fi->df.dfCharSet = RUSSIAN_CHARSET;
367 else if( strstr(lpch, "iso8859-4") ) fi->df.dfCharSet = ISO4_CHARSET;
368 else if( strstr(lpch, "iso8859-3") ) fi->df.dfCharSet = ISO3_CHARSET;
369 else if( strstr(lpch, "iso8859-2") ) fi->df.dfCharSet = EE_CHARSET;
370 else if( strstr(lpch, "iso8859-1") ) fi->df.dfCharSet = ANSI_CHARSET;
371 else fi->df.dfCharSet = SYMBOL_CHARSET;
372 } else if( strstr(lpch, iso646Encoding) ) {
373 fi->fi_flags |= FI_ENC_ISO646;
374 } else if( strstr(lpch, ansiEncoding) ) { /* fnt2bdf produces -ansi-0 LFD */
375 fi->fi_flags |= FI_ENC_ANSI;
376 } else { /* ... and -microsoft-cp125x */
378 fi->df.dfCharSet = OEM_CHARSET;
379 if( !strncasecmp(lpch, "microsoft-", 10) ) {
380 fi->fi_flags |= FI_ENC_MSCODEPAGE;
381 if( strstr(lpch, "-cp1250") ) fi->df.dfCharSet = EE_CHARSET;
382 else if( strstr(lpch, "-cp1251") ) fi->df.dfCharSet = RUSSIAN_CHARSET;
383 else if( strstr(lpch, "-cp1252") ) fi->df.dfCharSet = ANSI_CHARSET;
384 else if( strstr(lpch, "-cp1253") ) fi->df.dfCharSet = GREEK_CHARSET;
385 else if( strstr(lpch, "-cp1254") ) fi->df.dfCharSet = TURKISH_CHARSET;
386 else if( strstr(lpch, "-cp1255") ) fi->df.dfCharSet = HEBREW_CHARSET;
387 else if( strstr(lpch, "-cp1256") ) fi->df.dfCharSet = ARABIC_CHARSET;
388 else if( strstr(lpch, "-cp1257") ) fi->df.dfCharSet = BALTIC_CHARSET;
389 else if( strstr(lpch, "-fontspecific") ) fi->df.dfCharSet = ANSI_CHARSET;
390 else if( strstr(lpch, "-symbol") ) fi->df.dfCharSet = SYMBOL_CHARSET;
391 else fi->df.dfCharSet = SYMBOL_CHARSET;
392 } else if( !strncasecmp(lpch, "koi8-", 5) ) {
393 fi->df.dfCharSet = KOI8_CHARSET;
394 } else if( !strncasecmp(lpch, "viscii", 6) ) {
395 fi->fi_flags |= FI_ENC_ISO8859;
396 fi->df.dfCharSet = VISCII_CHARSET;
397 } else if( !strncasecmp(lpch, "tcvn-", 5) ) {
398 fi->df.dfCharSet = TCVN_CHARSET;
399 } else if( !strncasecmp(lpch, "tis620", 6) ) {
400 fi->fi_flags |= FI_ENC_ISO8859;
401 fi->df.dfCharSet = THAI_CHARSET;
402 } else if( !strncasecmp(lpch, "ascii", 5) ) {
403 fi->fi_flags |= FI_ENC_ISO646;
404 fi->df.dfCharSet = ANSI_CHARSET;
405 } else if( strstr(lpch, "fontspecific") ||
406 strstr(lpch, "microsoft-symbol") ) {
407 fi->df.dfCharSet = SYMBOL_CHARSET;
414 /*************************************************************************
417 static BOOL32 LFD_ComposeLFD( fontObject* fo,
418 INT32 height, LPSTR lpLFD, UINT32 uRelax )
420 int h, w, ch, point = 0;
423 char h_string[64], point_string[64];
425 *(lpLFD+MAX_LFD_LENGTH-1)=0;
426 lstrcpy32A( lpLFD, fo->fr->resource );
429 switch( fo->fi->df.dfWeight )
432 strcat( lpLFD, "bold" ); break;
434 if( fo->fi->fi_flags & FI_FW_BOOK )
435 strcat( lpLFD, "book" );
437 strcat( lpLFD, "medium" );
440 strcat( lpLFD, "demi" );
441 if( !( fo->fi->fi_flags & FI_FW_DEMI) )
442 strcat ( lpLFD, "bold" );
445 strcat( lpLFD, "black" ); break;
447 strcat( lpLFD, "light" ); break;
449 strcat( lpLFD, "*" );
453 if( fo->fi->df.dfItalic )
454 if( fo->fi->fi_flags & FI_OBLIQUE )
455 strcat( lpLFD, "-o" );
457 strcat( lpLFD, "-i" );
459 strcat( lpLFD, (uRelax < 4) ? "-r" : "-*" );
461 /* add width style and skip serifs */
462 if( fo->fi->fi_flags & FI_NORMAL )
463 strcat( lpLFD, "-normal-*-");
465 strcat( lpLFD, "-*-*-" );
467 /* add pixelheight, pointheight, and resolution
469 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
471 if( fo->fo_flags & FO_SYNTH_HEIGHT ) h = fo->fi->lfd_height;
472 else h = (fo->fi->lfd_height * height) / fo->fi->df.dfPixHeight;
474 if( XTextCaps & TC_SF_X_YINDEP )
476 if( fo->lf.lfWidth && !(fo->fo_flags & FO_SYNTH_WIDTH) )
477 point = (fo->fi->lfd_decipoints * fo->lf.lfWidth) / fo->fi->df.dfAvgWidth;
479 if( fo->fi->fi_flags & FI_SCALABLE ) /* adjust h/w ratio */
480 point = h * 72 * 10 / fo->fi->lfd_resolution;
483 /* handle rotated fonts */
484 if (fo->lf.lfEscapement) {
485 /* escapement is in tenths of degrees, theta is in radians */
486 double theta = M_PI*fo->lf.lfEscapement/1800.;
487 double h_matrix[4] = {h*cos(theta), h*sin(theta), -h*sin(theta), h*cos(theta)};
488 double point_matrix[4] = {point*cos(theta), point*sin(theta), -point*sin(theta), point*cos(theta)};
490 sprintf(h_string, "[%+f%+f%+f%+f]", h_matrix[0], h_matrix[1], h_matrix[2], h_matrix[3]);
491 sprintf(point_string, "[%+f%+f%+f%+f]", point_matrix[0], point_matrix[1], point_matrix[2], point_matrix[3]);
492 while ((s = strchr(h_string, '-'))) *s='~';
493 while ((s = strchr(point_string, '-'))) *s='~';
495 sprintf(h_string, "%d", h);
496 sprintf(point_string, "%d", point);
500 /* spacing and width */
502 if( fo->fi->fi_flags & FI_FIXEDPITCH )
503 w = ( fo->fi->fi_flags & FI_FIXEDEX ) ? 'c' : 'm';
505 w = ( fo->fi->fi_flags & FI_VARIABLEPITCH ) ? 'p' : LFDSeparator[0];
509 #define CHRS_CASE1(charset) case 0: \
512 case 9: sprintf(lpEncoding, charset ); break;
513 #define CHRS_CASE2(charset) case 1: \
516 case 10: sprintf(lpEncoding, charset ); break;
517 #define CHRS_CASE3(charset) case 2: \
520 case 11: sprintf(lpEncoding, charset ); break;
521 #define CHRS_DEF(charset) default: sprintf(lpEncoding, charset ); break;
523 if( fo->fi->df.dfCharSet == ANSI_CHARSET )
525 if( fo->fi->fi_flags & FI_ENC_ISO8859 )
527 CHRS_CASE1( "iso8859-1" );
528 CHRS_CASE2( "iso8859-1" );
529 CHRS_CASE3( "iso8859-15" );
530 CHRS_DEF( "iso8859-*" );
532 else if( fo->fi->fi_flags & FI_ENC_ISO646 )
534 CHRS_CASE1( "ascii-0" );
535 CHRS_DEF( "iso8859-1" );
537 else if( fo->fi->fi_flags & FI_ENC_MSCODEPAGE )
539 CHRS_CASE1( "microsoft-cp1252" );
540 CHRS_CASE2( "microsoft-fontspecific" );
541 CHRS_CASE3( "microsoft-cp125*" );
542 CHRS_DEF( "microsoft-*" );
546 CHRS_CASE1( "ansi-0" );
547 CHRS_CASE2( "microsoft-125*" );
548 CHRS_CASE3( "microsoft-*");
549 CHRS_DEF( "iso8859-*" );
552 else if( fo->fi->fi_flags & FI_ENC_MSCODEPAGE )
554 switch (fo->fi->df.dfCharSet) {
557 CHRS_CASE1( "microsoft-1250" );
558 CHRS_CASE2( "iso8859-2" );
559 CHRS_DEF( "iso8859-*" );
561 case RUSSIAN_CHARSET:
563 CHRS_CASE1( "microsoft-1251" );
564 CHRS_CASE2( "iso8859-5" );
565 CHRS_CASE3( "koi8-*" );
566 CHRS_DEF( "iso8859-*" );
570 CHRS_CASE1( "microsoft-1252" );
571 CHRS_CASE2( "iso8859-1" );
572 CHRS_CASE3( "iso8859-15" );
573 CHRS_DEF( "iso8859-*" );
577 CHRS_CASE1( "microsoft-1253" );
578 CHRS_CASE2( "iso8859-7" );
579 CHRS_DEF( "iso8859-*" );
581 case TURKISH_CHARSET:
583 CHRS_CASE1( "microsoft-1254" );
584 CHRS_CASE2( "iso8859-9" );
585 CHRS_DEF( "iso8859-*" );
589 CHRS_CASE1( "microsoft-1255" );
590 CHRS_CASE2( "iso8859-8" );
591 CHRS_DEF( "iso8859-*" );
595 CHRS_CASE1( "microsoft-1256" );
596 CHRS_CASE2( "iso8859-6" );
597 CHRS_DEF( "iso8859-*" );
601 CHRS_CASE1( "microsoft-1257" );
602 CHRS_CASE2( "iso8859-10" );
603 CHRS_CASE3( "iso8859-15" );
604 CHRS_DEF( "iso8859-*" );
608 CHRS_CASE1( "iso8859-11" );
609 CHRS_CASE2( "tis620*" );
610 CHRS_DEF( "iso8859-*" );
614 CHRS_CASE1( "viscii1.1-1" );
615 CHRS_CASE2( "viscii*" );
616 CHRS_DEF( "iso8859-*" );
620 CHRS_CASE1( "tcvn-0" );
621 CHRS_CASE2( "tcvn*" );
622 CHRS_DEF( "iso8859-*" );
626 CHRS_CASE1( "koi8-ru" );
627 CHRS_CASE2( "koi8-r" );
628 CHRS_CASE3( "koi8-*" );
629 CHRS_DEF( "iso8859-*" );
633 CHRS_CASE1( "iso8859-3" );
634 CHRS_DEF( "iso8859-*" );
638 CHRS_CASE1( "iso8859-4" );
639 CHRS_DEF( "iso8859-*" );
643 CHRS_CASE1( "microsoft-symbol" );
644 CHRS_DEF( "microsoft-fontspecific" );
650 CHRS_CASE1( "*-fontspecific" );
651 CHRS_CASE2( "*-symbol" );
652 CHRS_DEF( "*" ); /* whatever */
656 lpch = lpLFD + lstrlen32A(lpLFD);
657 ch = (fo->fi->fi_flags & FI_SCALABLE) ? '0' : LFDSeparator[0];
661 /* RealizeFont() will call us repeatedly with increasing uRelax
662 * until XLoadFont() succeeds. */
669 sprintf( lpch, "%s-%s-%i-%c-%c-*-%s", h_string,
671 fo->fi->lfd_resolution, ch, w, lpEncoding );
679 sprintf( lpch, "%s-*-%i-%c-%c-*-%s", h_string,
680 fo->fi->lfd_resolution, ch, w, lpEncoding );
686 sprintf( lpch, "%s-*-%i-%c-*-*-%s",
687 h_string, fo->fi->lfd_resolution, ch, lpEncoding );
693 sprintf( lpch, "%i-*-%i-%c-*-*-%s", fo->fi->lfd_height,
694 fo->fi->lfd_resolution, ch, lpEncoding );
698 sprintf( lpch, "%i-*-*-*-*-*-%s", fo->fi->lfd_height, lpEncoding );
702 sprintf( lpch, "%i-*-*-*-*-*-*", fo->fi->lfd_height);
705 /* to avoid an infinite loop; those will allways match */
707 sprintf( lpLFD, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" );
710 sprintf( lpLFD, "-*-*-*-*-*-*-*-*-*-*-*-*-*" );
714 TRACE(font,"\tLFD(uRelax=%d): %s\n", uRelax, lpLFD );
715 assert(*(lpLFD+MAX_LFD_LENGTH-1)==0); /* check if overwrittem */
720 /***********************************************************************
723 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
724 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
726 static BOOL32 XFONT_GetLeading( LPIFONTINFO16 pFI, XFontStruct* x_fs, INT32*
727 pIL, INT32* pEL, XFONTTRANS *XFT )
729 unsigned long height;
730 unsigned min = (unsigned char)pFI->dfFirstChar;
731 unsigned max = (unsigned char)pFI->dfLastChar;
732 BOOL32 bHaveCapHeight = (pFI->dfCharSet == ANSI_CHARSET && 'X' >= min && 'X' <= max );
737 Atom RAW_CAP_HEIGHT = TSXInternAtom(display, "RAW_CAP_HEIGHT", TRUE);
738 if(TSXGetFontProperty(x_fs, RAW_CAP_HEIGHT, &height))
740 (INT32)(XFT->pixelsize / 1000.0 * height);
743 return bHaveCapHeight && x_fs->per_char;
746 if( TSXGetFontProperty(x_fs, XA_CAP_HEIGHT, &height) == FALSE )
750 height = x_fs->per_char['X' - min].ascent;
752 if (x_fs->ascent >= x_fs->max_bounds.ascent)
753 height = x_fs->max_bounds.ascent;
756 height = x_fs->ascent;
758 *pEL = x_fs->max_bounds.ascent - height;
761 height = x_fs->min_bounds.ascent;
764 *pIL = x_fs->ascent - height;
765 return (bHaveCapHeight && x_fs->per_char);
768 static INT32 XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI, XFontStruct* x_fs,
771 unsigned min = (unsigned char)pFI->dfFirstChar;
772 unsigned max = (unsigned char)pFI->dfLastChar;
777 for( j = 0, width = 0, chars = 0, max -= min; j <= max; j++ )
778 if( !CI_NONEXISTCHAR(x_fs->per_char + j) )
781 width += x_fs->per_char[j].width;
783 width += x_fs->per_char[j].attributes *
784 XFT->pixelsize / 1000.0;
787 return (width / chars);
790 return x_fs->min_bounds.width;
793 static INT32 XFONT_GetMaxCharWidth(fontObject *pfo)
795 unsigned min = (unsigned char)pfo->fs->min_char_or_byte2;
796 unsigned max = (unsigned char)pfo->fs->max_char_or_byte2;
799 return abs(pfo->fs->max_bounds.width);
801 if( pfo->fs->per_char )
804 for( j = 0, maxwidth = 0, max -= min; j <= max; j++ )
805 if( !CI_NONEXISTCHAR(pfo->fs->per_char + j) )
806 if(maxwidth < pfo->fs->per_char[j].attributes)
807 maxwidth = pfo->fs->per_char[j].attributes;
809 maxwidth *= pfo->lpX11Trans->pixelsize / 1000.0;
812 return pfo->foAvgCharWidth;
815 /***********************************************************************
816 * XFONT_SetFontMetric
818 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
820 static void XFONT_SetFontMetric(fontInfo* fi, fontResource* fr, XFontStruct* xfs)
825 fi->df.dfFirstChar = (BYTE)(min = xfs->min_char_or_byte2);
826 fi->df.dfLastChar = (BYTE)(max = xfs->max_char_or_byte2);
828 fi->df.dfDefaultChar = (BYTE)xfs->default_char;
829 fi->df.dfBreakChar = (BYTE)(( ' ' < min || ' ' > max) ? xfs->default_char: ' ');
831 fi->df.dfPixHeight = (INT16)((fi->df.dfAscent = (INT16)xfs->ascent) + xfs->descent);
832 fi->df.dfPixWidth = (xfs->per_char) ? 0 : xfs->min_bounds.width;
833 fi->df.dfMaxWidth = (INT16)abs(xfs->max_bounds.width);
835 if( XFONT_GetLeading( &fi->df, xfs, &il, &el, NULL ) )
836 fi->df.dfAvgWidth = (INT16)xfs->per_char['X' - min].width;
838 fi->df.dfAvgWidth = (INT16)XFONT_GetAvgCharWidth( &fi->df, xfs, NULL);
840 fi->df.dfInternalLeading = (INT16)il;
841 fi->df.dfExternalLeading = (INT16)el;
843 fi->df.dfPoints = (INT16)(((INT32)(fi->df.dfPixHeight -
844 fi->df.dfInternalLeading) * 72 + (fi->df.dfVertRes >> 1)) / fi->df.dfVertRes);
846 if( xfs->min_bounds.width != xfs->max_bounds.width )
847 fi->df.dfPitchAndFamily |= TMPF_FIXED_PITCH; /* au contraire! */
848 if( fi->fi_flags & FI_SCALABLE )
850 fi->df.dfType = DEVICE_FONTTYPE;
851 fi->df.dfPitchAndFamily |= TMPF_DEVICE;
853 else if( fi->fi_flags & FI_TRUETYPE )
854 fi->df.dfType = TRUETYPE_FONTTYPE;
856 fi->df.dfType = RASTER_FONTTYPE;
858 fi->df.dfFace = fr->lfFaceName;
861 /***********************************************************************
862 * XFONT_GetTextMetric
864 static void XFONT_GetTextMetric( fontObject* pfo, LPTEXTMETRIC32A pTM )
866 LPIFONTINFO16 pdf = &pfo->fi->df;
868 if( ! pfo->lpX11Trans ) {
869 pTM->tmAscent = pfo->fs->ascent;
870 pTM->tmDescent = pfo->fs->descent;
872 pTM->tmAscent = pfo->lpX11Trans->ascent;
873 pTM->tmDescent = pfo->lpX11Trans->descent;
875 pTM->tmHeight = pTM->tmAscent + pTM->tmDescent;
877 pTM->tmAveCharWidth = pfo->foAvgCharWidth;
878 pTM->tmMaxCharWidth = pfo->foMaxCharWidth;
880 pTM->tmInternalLeading = pfo->foInternalLeading;
881 pTM->tmExternalLeading = pdf->dfExternalLeading;
883 pTM->tmStruckOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT )
884 ? 1 : pdf->dfStrikeOut;
885 pTM->tmUnderlined = (pfo->fo_flags & FO_SYNTH_UNDERLINE )
886 ? 1 : pdf->dfUnderline;
889 if( pfo->fo_flags & FO_SYNTH_ITALIC )
891 pTM->tmOverhang += pTM->tmHeight/3;
894 pTM->tmItalic = pdf->dfItalic;
896 pTM->tmWeight = pdf->dfWeight;
897 if( pfo->fo_flags & FO_SYNTH_BOLD )
900 pTM->tmWeight += 100;
903 *(INT32*)&pTM->tmFirstChar = *(INT32*)&pdf->dfFirstChar;
905 pTM->tmCharSet = pdf->dfCharSet;
906 pTM->tmPitchAndFamily = pdf->dfPitchAndFamily;
908 pTM->tmDigitizedAspectX = pdf->dfHorizRes;
909 pTM->tmDigitizedAspectY = pdf->dfVertRes;
912 /***********************************************************************
913 * XFONT_GetFontMetric
915 * Retrieve font metric info (enumeration).
917 static UINT32 XFONT_GetFontMetric( fontInfo* pfi, LPENUMLOGFONTEX16 pLF,
918 LPNEWTEXTMETRIC16 pTM )
920 memset( pLF, 0, sizeof(*pLF) );
921 memset( pTM, 0, sizeof(*pTM) );
923 #define plf ((LPLOGFONT16)pLF)
924 plf->lfHeight = pTM->tmHeight = pfi->df.dfPixHeight;
925 plf->lfWidth = pTM->tmAveCharWidth = pfi->df.dfAvgWidth;
926 plf->lfWeight = pTM->tmWeight = pfi->df.dfWeight;
927 plf->lfItalic = pTM->tmItalic = pfi->df.dfItalic;
928 plf->lfUnderline = pTM->tmUnderlined = pfi->df.dfUnderline;
929 plf->lfStrikeOut = pTM->tmStruckOut = pfi->df.dfStrikeOut;
930 plf->lfCharSet = pTM->tmCharSet = pfi->df.dfCharSet;
932 /* convert pitch values */
934 pTM->tmPitchAndFamily = pfi->df.dfPitchAndFamily;
935 plf->lfPitchAndFamily = (pfi->df.dfPitchAndFamily & 0xF1) + 1;
937 lstrcpyn32A( plf->lfFaceName, pfi->df.dfFace, LF_FACESIZE );
940 pTM->tmAscent = pfi->df.dfAscent;
941 pTM->tmDescent = pTM->tmHeight - pTM->tmAscent;
942 pTM->tmInternalLeading = pfi->df.dfInternalLeading;
943 pTM->tmMaxCharWidth = pfi->df.dfMaxWidth;
944 pTM->tmDigitizedAspectX = pfi->df.dfHorizRes;
945 pTM->tmDigitizedAspectY = pfi->df.dfVertRes;
947 *(INT32*)&pTM->tmFirstChar = *(INT32*)&pfi->df.dfFirstChar;
949 /* return font type */
951 return pfi->df.dfType;
955 /***********************************************************************
958 * dfPitchAndFamily flags for some common typefaces.
960 static BYTE XFONT_FixupFlags( LPCSTR lfFaceName )
962 switch( lfFaceName[0] )
965 case 'H': if(!strcasecmp(lfFaceName, "Helvetica") )
969 case 'C': if(!strcasecmp(lfFaceName, "Courier") ||
970 !strcasecmp(lfFaceName, "Charter") )
974 case 'P': if( !strcasecmp(lfFaceName,"Palatino") )
978 case 'T': if(!strncasecmp(lfFaceName, "Times", 5) )
982 case 'U': if(!strcasecmp(lfFaceName, "Utopia") )
986 case 'Z': if(!strcasecmp(lfFaceName, "Zapf Dingbats") )
987 return FF_DECORATIVE;
993 /***********************************************************************
994 * XFONT_CheckResourceName
996 static BOOL32 XFONT_CheckResourceName( LPSTR resource, LPCSTR name, INT32 n )
998 resource = LFD_Advance( resource, 2 );
1000 return (!strncasecmp( resource, name, n ));
1005 /***********************************************************************
1006 * XFONT_WindowsNames
1008 * Build generic Windows aliases for X font names.
1010 * -misc-fixed- -> "Fixed"
1011 * -sony-fixed- -> "Sony Fixed", etc...
1013 static void XFONT_WindowsNames( char* buffer )
1015 fontResource* fr, *pfr;
1019 const char* relocTable[] = { INIDefaultFixed, INIDefault, NULL };
1021 for( fr = fontList; fr ; fr = fr->next )
1023 if( fr->fr_flags & FR_NAMESET ) continue; /* skip already assigned */
1025 lpstr = LFD_Advance(fr->resource, 2);
1026 i = LFD_Advance( lpstr, 1 ) - lpstr;
1028 for( pfr = fontList; pfr != fr ; pfr = pfr->next )
1029 if( pfr->fr_flags & FR_NAMESET )
1030 if( XFONT_CheckResourceName( pfr->resource, lpstr, i ) )
1033 if( pfr != fr ) /* prepend vendor name */
1034 lpstr = fr->resource + 1;
1036 for( i = 0, up = 1, lpch = fr->lfFaceName; *lpstr && i < 32;
1037 lpch++, lpstr++, i++ )
1039 if( *lpstr == LFDSeparator[1] || *lpstr == ' ' )
1044 else if( isalpha(*lpstr) && up )
1046 *lpch = toupper(*lpstr);
1051 while (*(lpch - 1) == ' ') *(--lpch) = '\0';
1053 if( (bFamilyStyle = XFONT_FixupFlags( fr->lfFaceName )) )
1056 for( fi = fr->fi ; fi ; fi = fi->next )
1057 fi->df.dfPitchAndFamily |= bFamilyStyle;
1060 TRACE(font,"typeface \'%s\'\n", fr->lfFaceName);
1062 fr->fr_flags |= FR_NAMESET;
1065 for( up = 0; relocTable[up]; up++ )
1066 if( PROFILE_GetWineIniString( INIFontSection, relocTable[up], "", buffer, 128 ) )
1068 while( *buffer && isspace(*buffer) ) buffer++;
1069 for( fr = NULL, pfr = fontList; pfr; pfr = pfr->next )
1071 i = strlen( pfr->resource );
1072 if( !strncasecmp( pfr->resource, buffer, i) )
1076 fr->next = pfr->next;
1077 pfr->next = fontList;
1087 /***********************************************************************
1090 static fontAlias* XFONT_CreateAlias( LPCSTR lpTypeFace, LPCSTR lpAlias )
1093 fontAlias* pfa = aliasTable;
1097 /* check if we already got one */
1098 if( !strcasecmp( pfa->faTypeFace, lpAlias ) )
1100 TRACE(font,"\tredundant alias '%s' -> '%s'\n",
1101 lpAlias, lpTypeFace );
1104 if( pfa->next ) pfa = pfa->next;
1108 j = lstrlen32A(lpTypeFace) + 1;
1109 pfa->next = HeapAlloc( SystemHeap, 0, sizeof(fontAlias) +
1110 j + lstrlen32A(lpAlias) + 1 );
1111 if((pfa = pfa->next))
1114 pfa->faTypeFace = (LPSTR)(pfa + 1);
1115 lstrcpy32A( pfa->faTypeFace, lpTypeFace );
1116 pfa->faAlias = pfa->faTypeFace + j;
1117 lstrcpy32A( pfa->faAlias, lpAlias );
1119 TRACE(font, "\tadded alias '%s' for %s\n", lpAlias, lpTypeFace );
1126 /***********************************************************************
1129 * Read user-defined aliases from wine.conf. Format is as follows
1131 * Alias# = [Windows font name],[LFD font name], <substitute original name>
1134 * Alias0 = Arial, -adobe-helvetica-
1135 * Alias1 = Times New Roman, -bitstream-courier-, 1
1138 * Note that from 081797 and on we have built-in alias templates that take
1139 * care of the necessary Windows typefaces.
1141 static void XFONT_LoadAliases( char** buffer, int buf_size )
1143 char* lpResource, *lpAlias;
1144 char subsection[32];
1146 BOOL32 bHaveAlias = TRUE, bSubst = FALSE;
1148 if( buf_size < 128 )
1149 *buffer = HeapReAlloc(SystemHeap, 0, *buffer, 256 );
1152 if( j < faTemplateNum )
1154 /* built-in templates first */
1156 lpResource = faTemplate[j].fatResource;
1157 lpAlias = faTemplate[j].fatAlias;
1162 /* then WINE.CONF */
1164 wsprintf32A( subsection, "%s%i", INISubSection, i++ );
1166 if( (bHaveAlias = PROFILE_GetWineIniString( INIFontSection,
1167 subsection, "", *buffer, 128 )) )
1170 while( isspace(*lpAlias) ) lpAlias++;
1171 lpResource = PROFILE_GetStringItem( lpAlias );
1172 bSubst = (PROFILE_GetStringItem( lpResource )) ? TRUE : FALSE;
1180 length = strlen( lpAlias );
1181 if( lpResource && length )
1183 fontResource* fr, *frMatch = NULL;
1185 for (fr = fontList; fr ; fr = fr->next)
1187 if( !strcasecmp( fr->resource, lpResource ) ) frMatch = fr;
1188 if( XFONT_CheckResourceName( fr->resource, lpAlias, length ) )
1190 /* alias is not needed since the real font is present */
1191 frMatch = NULL; break;
1199 fontAlias *pfa, *prev = NULL;
1201 for(pfa = aliasTable; pfa; pfa = pfa->next)
1203 /* Remove lpAlias from aliasTable - we should free the old entry */
1204 if(!strcmp(lpAlias, pfa->faAlias))
1207 prev->next = pfa->next;
1209 aliasTable = pfa->next;
1212 /* Update any references to the substituted font in aliasTable */
1213 if(!strcmp(frMatch->lfFaceName,
1215 pfa->faTypeFace = HEAP_strdupA( SystemHeap, 0,
1220 TRACE(font, "\tsubstituted '%s' with %s\n",
1221 frMatch->lfFaceName, lpAlias );
1223 lstrcpyn32A( frMatch->lfFaceName, lpAlias, LF_FACESIZE );
1224 frMatch->fr_flags |= FR_NAMESET;
1228 /* create new entry in the alias table */
1229 XFONT_CreateAlias( frMatch->lfFaceName, lpAlias );
1233 else ERR(font, " malformed font alias '%s'\n", *buffer );
1239 /***********************************************************************
1240 * XFONT_UserMetricsCache
1242 * Returns expanded name for the ~/.wine/.cachedmetrics file.
1244 static char* XFONT_UserMetricsCache( char* buffer, int* buf_size )
1248 pwd = getpwuid(getuid());
1249 if( pwd && pwd->pw_dir )
1251 int i = strlen( pwd->pw_dir ) + strlen( INIWinePrefix ) +
1252 strlen( INIFontMetrics ) + 2;
1254 buffer = (char*) HeapReAlloc( SystemHeap, 0, buffer, *buf_size = i );
1255 strcpy( buffer, pwd->pw_dir );
1256 strcat( buffer, INIWinePrefix );
1257 strcat( buffer, INIFontMetrics );
1258 } else buffer[0] = '\0';
1263 /***********************************************************************
1264 * XFONT_ReadCachedMetrics
1266 static BOOL32 XFONT_ReadCachedMetrics( int fd, int res, unsigned x_checksum, int x_count )
1273 /* read checksums */
1274 read( fd, &u, sizeof(unsigned) );
1275 read( fd, &i, sizeof(int) );
1277 if( u == x_checksum && i == x_count )
1279 off_t length, offset = 3 * sizeof(int);
1281 /* read total size */
1282 read( fd, &i, sizeof(int) );
1283 length = lseek( fd, 0, SEEK_END );
1285 if( length == (i + offset) )
1287 lseek( fd, offset, SEEK_SET );
1288 fontList = (fontResource*)HeapAlloc( SystemHeap, 0, i);
1291 fontResource* pfr = fontList;
1292 fontInfo* pfi = NULL;
1294 TRACE(font,"Reading cached font metrics:\n");
1296 read( fd, fontList, i); /* read all metrics at once */
1297 while( offset < length )
1299 offset += sizeof(fontResource) + sizeof(fontInfo);
1300 pfr->fi = pfi = (fontInfo*)(pfr + 1);
1304 if( offset > length ||
1305 (int)(pfi->next) != j++ ) goto fail;
1307 pfi->df.dfFace = pfr->lfFaceName;
1308 pfi->df.dfHorizRes = pfi->df.dfVertRes = res;
1309 pfi->df.dfPoints = (INT16)(((INT32)(pfi->df.dfPixHeight -
1310 pfi->df.dfInternalLeading) * 72 + (res >> 1)) / res );
1311 pfi->next = pfi + 1;
1313 if( j > pfr->count ) break;
1316 offset += sizeof(fontInfo);
1321 pfr->next = (fontResource*)(pfi + 1);
1326 if( pfr->next == NULL &&
1327 *(int*)(pfi + 1) == X_FMC_MAGIC )
1329 /* read LFD stubs */
1330 char* lpch = (char*)((int*)(pfi + 1) + 1);
1331 offset += sizeof(int);
1332 for( pfr = fontList; pfr; pfr = pfr->next )
1334 TRACE(font,"\t%s, %i instances\n", lpch, pfr->count );
1335 pfr->resource = lpch;
1338 if( ++offset > length ) goto fail;
1339 if( !*lpch++ ) break;
1349 if( fontList ) HeapFree( SystemHeap, 0, fontList );
1356 /***********************************************************************
1357 * XFONT_WriteCachedMetrics
1359 static BOOL32 XFONT_WriteCachedMetrics( int fd, unsigned x_checksum, int x_count, int n_ff )
1368 /* font metrics file:
1372 * +0008 total size to load
1373 * +000C prepackaged font metrics
1376 * +...x + 4 LFD stubs
1379 write( fd, &x_checksum, sizeof(unsigned) );
1380 write( fd, &x_count, sizeof(int) );
1382 for( j = i = 0, pfr = fontList; pfr; pfr = pfr->next )
1384 i += strlen( pfr->resource ) + 1;
1387 i += n_ff * sizeof(fontResource) + j * sizeof(fontInfo) + sizeof(int);
1388 write( fd, &i, sizeof(int) );
1390 TRACE(font,"Writing font cache:\n");
1392 for( pfr = fontList; pfr; pfr = pfr->next )
1396 TRACE(font,"\t%s, %i instances\n", pfr->resource, pfr->count );
1398 i = write( fd, pfr, sizeof(fontResource) );
1399 if( i == sizeof(fontResource) )
1401 for( k = 1, pfi = pfr->fi; pfi; pfi = pfi->next )
1403 memcpy( &fi, pfi, sizeof(fi) );
1405 fi.df.dfFace = NULL;
1406 fi.next = (fontInfo*)k; /* loader checks this */
1408 j = write( fd, &fi, sizeof(fi) );
1411 if( j == sizeof(fontInfo) ) continue;
1415 if( i == sizeof(fontResource) && j == sizeof(fontInfo) )
1417 i = j = X_FMC_MAGIC;
1418 write( fd, &i, sizeof(int) );
1419 for( pfr = fontList; pfr && i == j; pfr = pfr->next )
1421 i = strlen( pfr->resource ) + 1;
1422 j = write( fd, pfr->resource, i );
1431 /***********************************************************************
1432 * XFONT_CheckIniSection
1434 * Examines wine.conf for old/invalid font entries and recommend changes to
1438 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1439 * Original implementation.
1441 static void XFONT_CheckIniCallback(char const *, char const *, void *);
1443 static char const *fontmsgprologue =
1445 " The following entries in the [fonts] section of the wine.conf file are\n"
1446 " obsolete or invalid:\n";
1448 static char const *fontmsgepilogue =
1449 " These entries should be eliminated or updated.\n"
1450 " See the documentation/fonts file for more information.\n";
1452 static int XFONT_CheckIniSection()
1456 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback,
1459 MSG(fontmsgepilogue);
1464 static void XFONT_CheckIniCallback(
1469 /* Ignore any keys that start with potential comment characters "'", '#',
1471 if(key[0] == '\'' || key[0] == '#' || key[0] == ';' || key[0] == '\0')
1474 /* Make sure this is a valid key */
1475 if((strncasecmp(key, INISubSection, 5) == 0) ||
1476 (strcasecmp( key, INIDefault) == 0) ||
1477 (strcasecmp( key, INIDefaultFixed) == 0) ||
1478 (strcasecmp( key, INIGlobalMetrics) == 0) ||
1479 (strcasecmp( key, INIResolution) == 0) )
1481 /* Valid key; make sure the value doesn't contain a wildcard */
1482 if(strchr(value, '*')) {
1483 if(*(int *)found == 0) {
1484 MSG(fontmsgprologue);
1488 MSG(" %s=%s [no wildcards allowed]\n", key, value);
1492 /* Not a valid key */
1493 if(*(int *)found == 0) {
1494 MSG(fontmsgprologue);
1498 MSG(" %s=%s [obsolete]\n", key, value);
1504 /***********************************************************************
1505 * XFONT_GetPointResolution()
1507 * Here we initialize DefResolution which is used in the
1508 * XFONT_Match() penalty function. We also load the point
1509 * resolution value (higher values result in larger fonts).
1511 static int XFONT_GetPointResolution( DeviceCaps* pDevCaps )
1513 int i, j, point_resolution, num = 3;
1514 int allowed_xfont_resolutions[3] = { 72, 75, 100 };
1515 int best = 0, best_diff = 65536;
1517 DefResolution = point_resolution = PROFILE_GetWineIniInt( INIFontSection, INIResolution, 0 );
1518 if( !DefResolution ) DefResolution = point_resolution = pDevCaps->logPixelsY;
1519 else pDevCaps->logPixelsX = pDevCaps->logPixelsY = DefResolution;
1521 for( i = best = 0; i < num; i++ )
1523 j = abs( DefResolution - allowed_xfont_resolutions[i] );
1530 DefResolution = allowed_xfont_resolutions[best];
1531 return point_resolution;
1534 /***********************************************************************
1537 * Initialize font resource list and allocate font cache.
1539 BOOL32 X11DRV_FONT_Init( DeviceCaps* pDevCaps )
1542 fontResource* fr, *pfr;
1544 unsigned x_checksum;
1545 int i, j, res, x_count, fd = -1, buf_size = 0;
1546 char* lpstr, *lpch, *lpmetrics, *buffer;
1549 XFONT_CheckIniSection();
1551 res = XFONT_GetPointResolution( pDevCaps );
1553 x_pattern = TSXListFonts(display, "*", MAX_FONT_FAMILIES * 16, &x_count );
1555 TRACE(font,"Font Mapper: initializing %i fonts [LPY=%i, XDR=%i, DR=%i]\n",
1556 x_count, pDevCaps->logPixelsY, DefResolution, res);
1557 for( i = x_checksum = 0; i < x_count; i++ )
1560 printf("%i\t: %s\n", i, x_pattern[i] );
1563 j = strlen( x_pattern[i] );
1564 if( j ) x_checksum ^= __genericCheckSum( x_pattern[i], j );
1566 x_checksum |= X_PFONT_MAGIC;
1569 buffer = HeapAlloc( SystemHeap, 0, buf_size );
1572 /* deal with systemwide font metrics cache */
1574 if( PROFILE_GetWineIniString( INIFontSection, INIGlobalMetrics, "", buffer, 128 ) )
1575 fd = open( buffer, O_RDONLY );
1577 if( XFONT_ReadCachedMetrics(fd, res, x_checksum, x_count) == FALSE )
1580 buffer = XFONT_UserMetricsCache( buffer, &buf_size );
1583 fd = open( buffer, O_RDONLY );
1584 if( XFONT_ReadCachedMetrics(fd, res, x_checksum, x_count) == FALSE )
1585 lpmetrics = HEAP_strdupA( SystemHeap, 0, buffer ); /* update later on */
1590 if( fontList == NULL ) /* build metrics from scratch */
1595 for( i = n_ff = 0; i < x_count; i++ )
1597 typeface = lpch = x_pattern[i];
1599 lpch = LFD_Advance(typeface, 3); /* extra '-' in the beginning */
1600 if( !*lpch ) continue;
1603 j = lpch - typeface; /* resource name length */
1605 /* find a family to insert into */
1607 for( pfr = NULL, fr = fontList; fr; fr = fr->next )
1609 if( !strncasecmp(fr->resource, typeface, j) &&
1610 strlen(fr->resource) == j ) break;
1614 if( !fi ) fi = (fontInfo*) HeapAlloc(SystemHeap, 0, sizeof(fontInfo));
1616 if( !fr ) /* add new family */
1618 if( n_ff >= MAX_FONT_FAMILIES ) break;
1619 if( !LFD_InitFontInfo( fi, lpstr) ) continue;
1622 fr = (fontResource*) HeapAlloc(SystemHeap, 0, sizeof(fontResource));
1623 memset(fr, 0, sizeof(fontResource));
1624 fr->resource = (char*) HeapAlloc(SystemHeap, 0, j + 1 );
1625 lstrcpyn32A( fr->resource, typeface, j + 1 );
1627 TRACE(font," family: %s\n", fr->resource );
1629 if( pfr ) pfr->next = fr;
1632 else if( !LFD_InitFontInfo( fi, lpstr) ) continue;
1634 /* check if we already have something better than "fi" */
1636 for( pfi = fr->fi, j = 0; pfi && j <= 0; pfi = pfi->next )
1637 if( (j = XFONT_IsSubset( pfi, fi )) < 0 )
1638 pfi->fi_flags |= FI_SUBSET; /* superseded by "fi" */
1639 if( j > 0 ) continue;
1641 /* add new font instance "fi" to the "fr" font resource */
1643 if( fi->fi_flags & FI_SCALABLE )
1645 /* set scalable font height to 24 to get an origin for extrapolation */
1647 j = strlen(typeface); j += 0x10;
1649 buffer = (char*)HeapReAlloc( SystemHeap, 0, buffer, buf_size = j );
1651 lpch = LFD_Advance(typeface, 7);
1652 memcpy( buffer, typeface, (j = lpch - typeface) );
1653 lpch = LFD_Advance(lpch, 4);
1654 sprintf( buffer + j, "%d-%d-%d-*-%c-*-", fi->lfd_height,
1655 fi->lfd_decipoints, fi->lfd_resolution,
1656 (*lpch == '-')?'*':*lpch );
1657 lpch = LFD_Advance(lpch, 2);
1658 strcat( lpstr = buffer, lpch);
1660 else lpstr = typeface;
1662 if( (x_fs = TSXLoadQueryFont(display, lpstr)) )
1664 fi->df.dfHorizRes = fi->df.dfVertRes = res;
1666 XFONT_SetFontMetric( fi, fr, x_fs );
1667 TSXFreeFont( display, x_fs );
1669 TRACE(font,"\t[% 2ipt] '%s'\n", fi->df.dfPoints, typeface );
1671 XFONT_CheckFIList( fr, fi, REMOVE_SUBSETS );
1672 fi = NULL; /* preventing reuse */
1676 ERR(font, "failed to load %s\n", lpstr );
1678 XFONT_CheckFIList( fr, fi, UNMARK_SUBSETS );
1682 if( lpmetrics ) /* update cached metrics */
1684 fd = open( lpmetrics, O_CREAT | O_TRUNC | O_RDWR, 0644 ); /* -rw-r--r-- */
1685 if( XFONT_WriteCachedMetrics( fd, x_checksum, x_count, n_ff ) == FALSE )
1686 if( fd ) remove( lpmetrics ); /* couldn't write entire file */
1687 HeapFree( SystemHeap, 0, lpmetrics );
1691 if( fi ) HeapFree(SystemHeap, 0, fi);
1692 TSXFreeFontNames(x_pattern);
1694 /* check if we're dealing with X11 R6 server */
1696 strcpy(buffer, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1697 if( (x_fs = TSXLoadQueryFont(display, buffer)) )
1699 XTextCaps |= TC_SF_X_YINDEP;
1700 TSXFreeFont(display, x_fs);
1703 XFONT_WindowsNames( buffer );
1704 XFONT_LoadAliases( &buffer, buf_size );
1705 HeapFree(SystemHeap, 0, buffer);
1708 /* fontList initialization is over, allocate X font cache */
1710 fontCache = (fontObject*) HeapAlloc(SystemHeap, 0, fontCacheSize * sizeof(fontObject));
1711 XFONT_GrowFreeList(0, fontCacheSize - 1);
1713 TRACE(font,"done!\n");
1715 /* update text caps parameter */
1717 pDevCaps->textCaps = XTextCaps;
1719 RAW_ASCENT = TSXInternAtom(display, "RAW_ASCENT", TRUE);
1720 RAW_DESCENT = TSXInternAtom(display, "RAW_DESCENT", TRUE);
1726 /***********************************************************************
1729 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1731 static INT32 XFONT_IsSubset(fontInfo* match, fontInfo* fi)
1735 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1737 m = (BYTE*)&fi->df.dfPixWidth - (BYTE*)&fi->df.dfItalic;
1738 if( memcmp(&match->df.dfItalic, &fi->df.dfItalic, m )) return 0;
1740 if( (!((fi->fi_flags & FI_SCALABLE) + (match->fi_flags & FI_SCALABLE))
1741 && fi->lfd_height != match->lfd_height) ||
1742 (!((fi->fi_flags & FI_POLYWEIGHT) + (match->fi_flags & FI_POLYWEIGHT))
1743 && fi->df.dfWeight != match->df.dfWeight) ) return 0;
1745 m = (int)(match->fi_flags & (FI_POLYWEIGHT | FI_SCALABLE)) -
1746 (int)(fi->fi_flags & (FI_SCALABLE | FI_POLYWEIGHT));
1748 if( m == (FI_POLYWEIGHT - FI_SCALABLE) ||
1749 m == (FI_SCALABLE - FI_POLYWEIGHT) ) return 0; /* keep both */
1750 else if( m >= 0 ) return 1; /* 'match' is better */
1752 return -1; /* 'fi' is better */
1755 /***********************************************************************
1758 * Compute the matching score between the logical font and the device font.
1760 * contributions from highest to lowest:
1764 * family flags (only when the facename is not present)
1766 * weight, italics, underlines, strikeouts
1768 * NOTE: you can experiment with different penalty weights to see what happens.
1769 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
1771 static UINT32 XFONT_Match( fontMatch* pfm )
1773 fontInfo* pfi = pfm->pfi; /* device font to match */
1774 LPLOGFONT16 plf = pfm->plf; /* wanted logical font */
1776 BOOL32 bR6 = pfm->flags & FO_MATCH_XYINDEP; /* from TextCaps */
1777 BOOL32 bScale = pfi->fi_flags & FI_SCALABLE;
1780 TRACE(font,"\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi->df.dfPoints,
1781 pfi->df.dfPixHeight, pfi->df.dfAvgWidth,
1782 (pfi->df.dfWeight > 400) ? "Bold " : "Normal ",
1783 (pfi->df.dfItalic) ? "Italic" : "" );
1787 if( plf->lfCharSet == DEFAULT_CHARSET )
1789 if( (pfi->df.dfCharSet!= ANSI_CHARSET) && (pfi->df.dfCharSet!=DEFAULT_CHARSET) )
1792 else if (plf->lfCharSet != pfi->df.dfCharSet) penalty += 0x200;
1794 /* FIXME: Hack to demote symbols and nil fonts. Should take into
1795 account if a program ever actually asked for this type of
1797 if ( (strcmp(pfm->pfr->lfFaceName,"Symbol")==0) || (strcmp(pfm->pfr->lfFaceName,"Nil")==0) )
1798 penalty += 0x200; /* very stiff penality */
1800 /* TMPF_FIXED_PITCH means exactly the opposite */
1802 if( plf->lfPitchAndFamily & FIXED_PITCH )
1804 if( pfi->df.dfPitchAndFamily & TMPF_FIXED_PITCH ) penalty += 0x100;
1806 else if( !(pfi->df.dfPitchAndFamily & TMPF_FIXED_PITCH) ) penalty += 0x2;
1808 if( plf->lfHeight > 0 )
1809 d = (h = pfi->df.dfPixHeight) - plf->lfHeight;
1810 else if( plf->lfHeight < -1 )
1811 d = (h = pfi->df.dfPoints) + plf->lfHeight;
1814 if( d && plf->lfHeight )
1816 UINT16 height = ( plf->lfHeight > 0 ) ? plf->lfHeight
1817 : ((-plf->lfHeight * pfi->df.dfPixHeight) / h);
1818 if( bScale ) pfm->height = height;
1819 else if( (plf->lfQuality != PROOF_QUALITY) && bR6 )
1821 if( d > 0 ) /* do not shrink raster fonts */
1823 pfm->height = pfi->df.dfPixHeight;
1824 penalty += (pfi->df.dfPixHeight - height) * 0x4;
1826 else /* expand only in integer multiples */
1828 pfm->height = height - height%pfi->df.dfPixHeight;
1829 penalty += (height - pfm->height + 1) * height / pfi->df.dfPixHeight;
1832 else /* can't be scaled at all */
1834 if( plf->lfQuality != PROOF_QUALITY) pfm->flags |= FO_SYNTH_HEIGHT;
1835 pfm->height = pfi->df.dfPixHeight;
1836 penalty += (d > 0)? d * 0x8 : -d * 0x10;
1838 } else pfm->height = pfi->df.dfPixHeight;
1840 if((pfm->flags & FO_MATCH_PAF) &&
1841 (plf->lfPitchAndFamily & FF_FAMILY) != (pfi->df.dfPitchAndFamily & FF_FAMILY) )
1846 if( bR6 && bScale ) h = 0;
1849 /* FIXME: not complete */
1851 pfm->flags |= FO_SYNTH_WIDTH;
1852 h = abs(plf->lfWidth - (pfm->height * pfi->df.dfAvgWidth)/pfi->df.dfPixHeight);
1854 penalty += h * ( d ) ? 0x2 : 0x1 ;
1856 else if( !(pfi->fi_flags & FI_NORMAL) ) penalty++;
1858 if( plf->lfWeight != FW_DONTCARE )
1860 penalty += abs(plf->lfWeight - pfi->df.dfWeight) / 40;
1861 if( plf->lfWeight > pfi->df.dfWeight ) pfm->flags |= FO_SYNTH_BOLD;
1862 } else if( pfi->df.dfWeight >= FW_BOLD ) penalty++; /* choose normal by default */
1864 if( plf->lfItalic != pfi->df.dfItalic )
1867 pfm->flags |= FO_SYNTH_ITALIC;
1870 if( plf->lfUnderline ) pfm->flags |= FO_SYNTH_UNDERLINE;
1871 if( plf->lfStrikeOut ) pfm->flags |= FO_SYNTH_STRIKEOUT;
1873 if( penalty && pfi->lfd_resolution != DefResolution )
1876 TRACE(font," returning %i\n", penalty );
1881 /***********************************************************************
1884 * Scan a particular font resource for the best match.
1886 static UINT32 XFONT_MatchFIList( fontMatch* pfm )
1888 BOOL32 skipRaster = (pfm->flags & FO_MATCH_NORASTER);
1889 UINT32 current_score, score = (UINT32)(-1);
1890 UINT16 origflags = pfm->flags; /* Preserve FO_MATCH_XYINDEP */
1891 fontMatch fm = *pfm;
1893 for( fm.pfi = pfm->pfr->fi; fm.pfi && score; fm.pfi = fm.pfi->next,
1894 fm.flags = origflags )
1896 if( skipRaster && !(fm.pfi->fi_flags & FI_SCALABLE) )
1899 current_score = XFONT_Match( &fm );
1900 if( score > current_score )
1902 memcpy( pfm, &fm, sizeof(fontMatch) );
1903 score = current_score;
1909 /***********************************************************************
1912 * REMOVE_SUBSETS - attach new fi and purge subsets
1913 * UNMARK_SUBSETS - remove subset flags from all fi entries
1915 static void XFONT_CheckFIList( fontResource* fr, fontInfo* fi, int action)
1918 fontInfo* pfi, *prev;
1920 for( prev = NULL, pfi = fr->fi; pfi; )
1922 if( action == REMOVE_SUBSETS )
1924 if( pfi->fi_flags & FI_SUBSET )
1926 fontInfo* subset = pfi;
1930 if( prev ) prev->next = pfi = pfi->next;
1931 else fr->fi = pfi = pfi->next;
1932 HeapFree( SystemHeap, 0, subset );
1936 else pfi->fi_flags &= ~FI_SUBSET;
1942 if( action == REMOVE_SUBSETS ) /* also add the superset */
1944 if( fi->fi_flags & FI_SCALABLE )
1949 else if( prev ) prev->next = fi; else fr->fi = fi;
1953 if( i ) TRACE(font,"\t purged %i subsets [%i]\n", i , fr->count);
1956 /***********************************************************************
1959 static fontResource* XFONT_FindFIList( fontResource* pfr, const char* pTypeFace )
1963 if( !strcasecmp( pfr->lfFaceName, pTypeFace ) ) break;
1969 /***********************************************************************
1970 * XFONT_MatchDeviceFont
1972 * Scan font resource tree.
1974 static BOOL32 XFONT_MatchDeviceFont( fontResource* start, fontMatch* pfm )
1976 fontMatch fm = *pfm;
1979 if( fm.plf->lfFaceName[0] )
1984 for( fa = aliasTable; fa; fa = fa->next )
1985 if( !strcmp( fa->faAlias, fm.plf->lfFaceName ) )
1987 str = fa->faTypeFace;
1990 fm.pfr = XFONT_FindFIList( start, str ? str : fm.plf->lfFaceName );
1993 if( fm.pfr ) /* match family */
1995 TRACE(font, "%s\n", fm.pfr->lfFaceName );
1997 XFONT_MatchFIList( &fm );
2001 if( !pfm->pfi ) /* match all available fonts */
2003 UINT32 current_score, score = (UINT32)(-1);
2005 fm.flags |= FO_MATCH_PAF;
2006 for( start = fontList; start && score; start = start->next )
2010 TRACE(font, "%s\n", fm.pfr->lfFaceName );
2012 current_score = XFONT_MatchFIList( &fm );
2013 if( current_score < score )
2015 score = current_score;
2024 /***********************************************************************
2027 static void XFONT_GrowFreeList(int start, int end)
2029 /* add all entries from 'start' up to and including 'end' */
2031 memset( fontCache + start, 0, (end - start + 1) * sizeof(fontObject) );
2033 fontCache[end].lru = fontLF;
2034 fontCache[end].count = -1;
2036 while( start < end )
2038 fontCache[start].count = -1;
2039 fontCache[start].lru = start + 1;
2044 static fontObject* XFONT_LookupCachedFont( LPLOGFONT16 plf, UINT16* checksum )
2046 UINT16 cs = __lfCheckSum( plf );
2047 int i = fontMRU, prev = -1;
2052 if( fontCache[i].lfchecksum == cs &&
2053 !(fontCache[i].fo_flags & FO_REMOVED) )
2055 /* FIXME: something more intelligent here */
2057 if( !memcmp( plf, &fontCache[i].lf,
2058 sizeof(LOGFONT16) - LF_FACESIZE ) &&
2059 !strncasecmp( plf->lfFaceName, fontCache[i].lf.lfFaceName,
2062 /* remove temporarily from the lru list */
2065 fontCache[prev].lru = fontCache[i].lru;
2067 fontMRU = (INT16)fontCache[i].lru;
2068 return (fontCache + i);
2072 i = (INT16)fontCache[i].lru;
2077 static fontObject* XFONT_GetCacheEntry()
2083 int prev_i, prev_j, j;
2085 TRACE(font,"font cache is full\n");
2087 /* lookup the least recently used font */
2089 for( prev_i = prev_j = j = -1, i = fontMRU; i >= 0; i = (INT16)fontCache[i].lru )
2091 if( fontCache[i].count <= 0 &&
2092 !(fontCache[i].fo_flags & FO_SYSTEM) )
2100 if( j >= 0 ) /* unload font */
2102 /* detach from the lru list */
2104 TRACE(font,"\tfreeing entry %i\n", j );
2107 fontCache[prev_j].lru = fontCache[j].lru;
2108 else fontMRU = (INT16)fontCache[j].lru;
2110 /* FIXME: lpXForm, lpPixmap */
2111 if(fontCache[j].lpX11Trans)
2112 HeapFree( SystemHeap, 0, fontCache[j].lpX11Trans );
2114 TSXFreeFont( display, fontCache[j].fs );
2116 memset( fontCache + j, 0, sizeof(fontObject) );
2117 return (fontCache + j);
2119 else /* expand cache */
2121 fontObject* newCache;
2123 prev_i = fontCacheSize + FONTCACHE;
2125 TRACE(font,"\tgrowing font cache from %i to %i\n", fontCacheSize, prev_i );
2127 if( (newCache = (fontObject*)HeapReAlloc(SystemHeap, 0,
2128 fontCache, prev_i)) )
2131 fontCacheSize = prev_i;
2132 fontCache = newCache;
2133 XFONT_GrowFreeList( i, fontCacheSize - 1);
2139 /* detach from the free list */
2142 fontLF = (INT16)fontCache[i].lru;
2143 fontCache[i].count = 0;
2144 return (fontCache + i);
2147 static int XFONT_ReleaseCacheEntry(fontObject* pfo)
2149 UINT32 u = (UINT32)(pfo - fontCache);
2151 if( u < fontCacheSize ) return (--fontCache[u].count);
2155 /**********************************************************************
2158 static BOOL32 XFONT_SetX11Trans( fontObject *pfo )
2165 TSXGetFontProperty( pfo->fs, XA_FONT, &nameAtom );
2166 fontName = TSXGetAtomName( display, nameAtom );
2167 for(i = 0, cp = fontName; i < 7; i++) {
2168 cp = strchr(cp, '-');
2176 while((cp = strchr(cp, '~')))
2179 #define PX pfo->lpX11Trans
2181 sscanf(start, "[%f%f%f%f]", &PX->a, &PX->b, &PX->c, &PX->d);
2184 TSXGetFontProperty( pfo->fs, RAW_ASCENT, &PX->RAW_ASCENT );
2185 TSXGetFontProperty( pfo->fs, RAW_DESCENT, &PX->RAW_DESCENT );
2187 PX->pixelsize = hypot(PX->a, PX->b);
2188 PX->ascent = PX->pixelsize / 1000.0 * PX->RAW_ASCENT;
2189 PX->descent = PX->pixelsize / 1000.0 * PX->RAW_DESCENT;
2191 TRACE(font, "[%f %f %f %f] RA = %ld RD = %ld\n", pfo->lpX11Trans->a,
2192 pfo->lpX11Trans->b, pfo->lpX11Trans->c, pfo->lpX11Trans->d,
2193 pfo->lpX11Trans->RAW_ASCENT, pfo->lpX11Trans->RAW_DESCENT);
2199 /***********************************************************************
2200 * X Device Font Objects
2202 static X_PHYSFONT XFONT_RealizeFont( LPLOGFONT16 plf )
2205 fontObject* pfo = XFONT_LookupCachedFont( plf, &checksum );
2209 fontMatch fm = { NULL, NULL, 0, 0, plf};
2212 if( XTextCaps & TC_SF_X_YINDEP ) fm.flags = FO_MATCH_XYINDEP;
2214 /* allocate new font cache entry */
2216 if( (pfo = XFONT_GetCacheEntry()) )
2218 LPSTR lpLFD = HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH );
2220 if( lpLFD ) /* initialize entry and load font */
2222 UINT32 uRelaxLevel = 0;
2224 TRACE(font,"(%u) '%s' h=%i weight=%i %s\n",
2225 plf->lfCharSet, plf->lfFaceName, plf->lfHeight,
2226 plf->lfWeight, (plf->lfItalic) ? "Italic" : "" );
2228 XFONT_MatchDeviceFont( fontList, &fm );
2232 pfo->fo_flags = fm.flags & ~FO_MATCH_MASK;
2234 memcpy( &pfo->lf, plf, sizeof(LOGFONT16) );
2235 pfo->lfchecksum = checksum;
2239 LFD_ComposeLFD( pfo, fm.height, lpLFD, uRelaxLevel++ );
2240 if( (pfo->fs = TSXLoadQueryFont( display, lpLFD )) ) break;
2241 } while( uRelaxLevel );
2244 if(pfo->lf.lfEscapement != 0) {
2245 pfo->lpX11Trans = HeapAlloc(SystemHeap, 0,
2246 sizeof(XFONTTRANS));
2247 if(!XFONT_SetX11Trans( pfo )) {
2248 HeapFree(SystemHeap, 0, pfo->lpX11Trans);
2249 pfo->lpX11Trans = NULL;
2253 if( XFONT_GetLeading( &pfo->fi->df, pfo->fs, &i, NULL,
2256 if(!pfo->lpX11Trans)
2257 pfo->foAvgCharWidth =
2258 (INT16)pfo->fs->per_char['X' - pfo->fs->min_char_or_byte2].width;
2260 pfo->foAvgCharWidth =
2261 (INT16)pfo->fs->per_char['X' - pfo->fs->min_char_or_byte2].attributes
2262 * pfo->lpX11Trans->pixelsize / 1000.0;
2264 pfo->foAvgCharWidth = (INT16)XFONT_GetAvgCharWidth(
2265 &pfo->fi->df, pfo->fs, pfo->lpX11Trans );
2266 pfo->foMaxCharWidth = (INT16)XFONT_GetMaxCharWidth(pfo);
2267 pfo->foInternalLeading = (INT16)i;
2269 /* FIXME: If we've got a soft font or
2270 * there are FO_SYNTH_... flags for the
2271 * non PROOF_QUALITY request, the engine
2272 * should rasterize characters into mono
2273 * pixmaps and store them in the pfo->lpPixmap
2274 * array (pfo->fs should be updated as well).
2275 * X11DRV_ExtTextOut() must be heavily modified
2276 * to support pixmap blitting and FO_SYNTH_...
2280 pfo->lpXForm = NULL;
2281 pfo->lpPixmap = NULL;
2283 HeapFree( GetProcessHeap(), 0, lpLFD );
2285 else /* attach back to the free list */
2289 fontLF = (pfo - fontCache);
2294 if( !pfo ) /* couldn't get a new entry, get one of the cached fonts */
2296 UINT32 current_score, score = (UINT32)(-1);
2298 i = index = fontMRU;
2299 fm.flags |= FO_MATCH_PAF;
2302 pfo = fontCache + i;
2303 fm.pfr = pfo->fr; fm.pfi = pfo->fi;
2305 current_score = XFONT_Match( &fm );
2306 if( current_score < score ) index = i;
2310 pfo = fontCache + index;
2312 return (X_PHYSFONT)(X_PFONT_MAGIC | index);
2316 /* attach at the head of the lru list */
2320 fontMRU = (pfo - fontCache);
2322 TRACE(font,"physfont %i\n", fontMRU);
2324 return (X_PHYSFONT)(X_PFONT_MAGIC | fontMRU);
2327 /***********************************************************************
2328 * XFONT_GetFontObject
2330 fontObject* XFONT_GetFontObject( X_PHYSFONT pFont )
2332 if( CHECK_PFONT(pFont) ) return __PFONT(pFont);
2336 /***********************************************************************
2337 * XFONT_GetFontStruct
2339 XFontStruct* XFONT_GetFontStruct( X_PHYSFONT pFont )
2341 if( CHECK_PFONT(pFont) ) return __PFONT(pFont)->fs;
2345 /***********************************************************************
2348 LPIFONTINFO16 XFONT_GetFontInfo( X_PHYSFONT pFont )
2350 if( CHECK_PFONT(pFont) ) return &(__PFONT(pFont)->fi->df);
2356 /* X11DRV Interface ****************************************************
2358 * Exposed via the dc->funcs dispatch table. *
2360 ***********************************************************************/
2361 /***********************************************************************
2362 * X11DRV_FONT_SelectObject
2364 HFONT32 X11DRV_FONT_SelectObject( DC* dc, HFONT32 hfont, FONTOBJ* font )
2366 HFONT32 hPrevFont = 0;
2368 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2370 if( CHECK_PFONT(physDev->font) )
2371 XFONT_ReleaseCacheEntry( __PFONT(physDev->font) );
2373 /* FIXME: do we need to pass anything back from here? */
2374 memcpy(&lf,&font->logfont,sizeof(lf));
2375 lf.lfWidth = font->logfont.lfWidth * dc->vportExtX/dc->wndExtX;
2376 lf.lfHeight = font->logfont.lfHeight* dc->vportExtY/dc->wndExtY;
2378 physDev->font = XFONT_RealizeFont( &lf );
2379 hPrevFont = dc->w.hFont;
2380 dc->w.hFont = hfont;
2386 /***********************************************************************
2388 * X11DRV_EnumDeviceFonts
2390 BOOL32 X11DRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf,
2391 DEVICEFONTENUMPROC proc, LPARAM lp )
2395 fontResource* pfr = fontList;
2398 if( plf->lfFaceName[0] )
2400 pfr = XFONT_FindFIList( pfr, plf->lfFaceName );
2404 for( pfi = pfr->fi; pfi; pfi = pfi->next )
2405 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
2406 XFONT_GetFontMetric( pfi, &lf, &tm ), lp )) )
2412 for( ; pfr ; pfr = pfr->next )
2415 if( (b = (*proc)( (LPENUMLOGFONT16)&lf, &tm,
2416 XFONT_GetFontMetric( pfr->fi, &lf, &tm ), lp )) )
2425 /***********************************************************************
2426 * X11DRV_GetTextExtentPoint
2428 BOOL32 X11DRV_GetTextExtentPoint( DC *dc, LPCSTR str, INT32 count,
2431 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2432 fontObject* pfo = XFONT_GetFontObject( physDev->font );
2434 if( !pfo->lpX11Trans ) {
2435 int dir, ascent, descent;
2438 TSXTextExtents( pfo->fs, str, count, &dir, &ascent, &descent, &info );
2439 size->cx = abs((info.width + dc->w.breakRem + count *
2440 dc->w.charExtra) * dc->wndExtX / dc->vportExtX);
2441 size->cy = abs((pfo->fs->ascent + pfo->fs->descent) *
2442 dc->wndExtY / dc->vportExtY);
2446 float x = 0.0, y = 0.0;
2447 for(i = 0; i < count; i++) {
2448 x += pfo->fs->per_char ?
2449 pfo->fs->per_char[str[i] - pfo->fs->min_char_or_byte2].attributes :
2450 pfo->fs->min_bounds.attributes;
2452 y = pfo->lpX11Trans->RAW_ASCENT + pfo->lpX11Trans->RAW_DESCENT;
2453 TRACE(font, "x = %f y = %f\n", x, y);
2454 x *= pfo->lpX11Trans->pixelsize / 1000.0;
2455 y *= pfo->lpX11Trans->pixelsize / 1000.0;
2456 size->cx = fabsf((x + dc->w.breakRem + count * dc->w.charExtra) *
2457 dc->wndExtX / dc->vportExtX);
2458 size->cy = fabsf(y * dc->wndExtY / dc->vportExtY);
2466 /***********************************************************************
2467 * X11DRV_GetTextMetrics
2469 BOOL32 X11DRV_GetTextMetrics(DC *dc, TEXTMETRIC32A *metrics)
2471 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2473 if( CHECK_PFONT(physDev->font) )
2475 fontObject* pfo = __PFONT(physDev->font);
2476 XFONT_GetTextMetric( pfo, metrics );
2484 /***********************************************************************
2485 * X11DRV_GetCharWidth
2487 BOOL32 X11DRV_GetCharWidth( DC *dc, UINT32 firstChar, UINT32 lastChar,
2490 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2491 fontObject* pfo = XFONT_GetFontObject( physDev->font );
2497 if (pfo->fs->per_char == NULL)
2498 for (i = firstChar; i <= lastChar; i++)
2500 *buffer++ = pfo->fs->min_bounds.attributes *
2501 pfo->lpX11Trans->pixelsize / 1000.0;
2503 *buffer++ = pfo->fs->min_bounds.width;
2506 XCharStruct *cs, *def;
2507 static XCharStruct __null_char = { 0, 0, 0, 0, 0, 0 };
2509 CI_GET_CHAR_INFO(pfo->fs, pfo->fs->default_char, &__null_char,
2512 for (i = firstChar; i <= lastChar; i++)
2514 if (i >= pfo->fs->min_char_or_byte2 &&
2515 i <= pfo->fs->max_char_or_byte2)
2517 cs = &pfo->fs->per_char[(i - pfo->fs->min_char_or_byte2)];
2518 if (CI_NONEXISTCHAR(cs)) cs = def;
2521 *buffer++ = MAX(cs->attributes, 0) *
2522 pfo->lpX11Trans->pixelsize / 1000.0;
2524 *buffer++ = MAX(cs->width, 0 );
2533 /***********************************************************************
2535 * Font Resource API *
2537 ***********************************************************************/
2538 /***********************************************************************
2539 * AddFontResource16 (GDI.119)
2541 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
2543 * FIXME: Load header and find the best-matching font in the fontList;
2544 * fixup dfPoints if all metrics are identical, otherwise create
2545 * new fontAlias. When soft font support is ready this will
2546 * simply create a new fontResource ('filename' will go into
2547 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
2550 INT16 WINAPI AddFontResource16( LPCSTR filename )
2552 return AddFontResource32A( filename );
2556 /***********************************************************************
2557 * AddFontResource32A (GDI32.2)
2559 INT32 WINAPI AddFontResource32A( LPCSTR str )
2561 FIXME(font, "(%s): stub\n", debugres_a(str));
2566 /***********************************************************************
2567 * AddFontResource32W (GDI32.4)
2569 INT32 WINAPI AddFontResource32W( LPCWSTR str )
2571 FIXME(font, "(%s): stub\n", debugres_w(str) );
2575 /***********************************************************************
2576 * RemoveFontResource16 (GDI.136)
2578 BOOL16 WINAPI RemoveFontResource16( SEGPTR str )
2580 FIXME(font, "(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str)));
2585 /***********************************************************************
2586 * RemoveFontResource32A (GDI32.284)
2588 BOOL32 WINAPI RemoveFontResource32A( LPCSTR str )
2590 FIXME(font, "(%s): stub\n", debugres_a(str));
2595 /***********************************************************************
2596 * RemoveFontResource32W (GDI32.286)
2598 BOOL32 WINAPI RemoveFontResource32W( LPCWSTR str )
2600 FIXME(font, "(%s): stub\n", debugres_w(str) );