Backed out scalable bitmap change (gives ugly results).
[wine/multimedia.git] / graphics / x11drv / xfont.c
blobd5d625674edb73879f05426801c7f5d177f37817
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 "config.h"
12 #ifndef X_DISPLAY_MISSING
13 #include <X11/Xatom.h>
14 #include "ts_xlib.h"
15 #include "x11font.h"
16 #endif /* !defined(X_DISPLAY_MISSING) */
18 #include <ctype.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26 #include <math.h>
27 #include <assert.h>
28 #include "winuser.h"
29 #include "heap.h"
30 #include "options.h"
31 #include "font.h"
32 #include "debugtools.h"
33 #include "ldt.h"
34 #include "tweak.h"
36 DEFAULT_DEBUG_CHANNEL(font)
38 #ifndef X_DISPLAY_MISSING
40 #define X_PFONT_MAGIC (0xFADE0000)
41 #define X_FMC_MAGIC (0x0000CAFE)
43 #define MAX_FONTS 1024*16
44 #define MAX_LFD_LENGTH 256
45 #define TILDE '~'
46 #define HYPHEN '-'
48 #define DEF_POINT_SIZE 8 /* CreateFont(0 .. ) gets this */
49 #define DEF_SCALABLE_HEIGHT 100 /* pixels */
50 #define MIN_FONT_SIZE 2 /* Min size in pixels */
51 #define MAX_FONT_SIZE 1000 /* Max size in pixels */
53 #define REMOVE_SUBSETS 1
54 #define UNMARK_SUBSETS 0
57 #define FF_FAMILY (FF_MODERN | FF_SWISS | FF_ROMAN | FF_DECORATIVE | FF_SCRIPT)
59 typedef struct __fontAlias
61 LPSTR faTypeFace;
62 LPSTR faAlias;
63 struct __fontAlias* next;
64 } fontAlias;
66 static fontAlias *aliasTable = NULL;
68 UINT16 XTextCaps = TC_OP_CHARACTER | TC_OP_STROKE |
69 TC_CP_STROKE | TC_CR_ANY |
70 TC_SA_DOUBLE | TC_SA_INTEGER | TC_SA_CONTIN |
71 TC_UA_ABLE | TC_SO_ABLE | TC_RA_ABLE;
73 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
75 static const char* INIWinePrefix = "/.wine";
76 static const char* INIFontMetrics = "/cachedmetrics.";
77 static const char* INIFontSection = "fonts";
78 static const char* INIAliasSection = "Alias";
79 static const char* INIIgnoreSection = "Ignore";
80 static const char* INIDefault = "Default";
81 static const char* INIDefaultFixed = "DefaultFixed";
82 static const char* INIResolution = "Resolution";
83 static const char* INIGlobalMetrics = "FontMetrics";
84 static const char* INIDefaultSerif = "DefaultSerif";
85 static const char* INIDefaultSansSerif = "DefaultSansSerif";
88 /* FIXME - are there any more Latin charsets ? */
89 #define IS_LATIN_CHARSET(ch) \
90 ((ch)==ANSI_CHARSET ||\
91 (ch)==EE_CHARSET ||\
92 (ch)==ISO3_CHARSET ||\
93 (ch)==ISO4_CHARSET ||\
94 (ch)==RUSSIAN_CHARSET ||\
95 (ch)==ARABIC_CHARSET ||\
96 (ch)==GREEK_CHARSET ||\
97 (ch)==HEBREW_CHARSET ||\
98 (ch)==TURKISH_CHARSET ||\
99 (ch)==BALTIC_CHARSET)
101 /* suffix-charset mapping tables - must be less than 254 entries long */
103 typedef struct __sufch
105 LPSTR psuffix;
106 BYTE charset;
107 } SuffixCharset;
109 static SuffixCharset sufch_ansi[] = {
110 { "0", ANSI_CHARSET },
111 { NULL, ANSI_CHARSET }};
113 static SuffixCharset sufch_iso646[] = {
114 { "irv", ANSI_CHARSET },
115 { NULL, SYMBOL_CHARSET }};
117 static SuffixCharset sufch_iso8859[] = {
118 { "1", ANSI_CHARSET },
119 { "2", EE_CHARSET },
120 { "3", ISO3_CHARSET },
121 { "4", ISO4_CHARSET },
122 { "5", RUSSIAN_CHARSET },
123 { "6", ARABIC_CHARSET },
124 { "7", GREEK_CHARSET },
125 { "8", HEBREW_CHARSET },
126 { "9", TURKISH_CHARSET },
127 { "10", BALTIC_CHARSET },
128 { "11", THAI_CHARSET },
129 { "12", SYMBOL_CHARSET },
130 { "13", SYMBOL_CHARSET },
131 { "14", SYMBOL_CHARSET },
132 { "15", ANSI_CHARSET },
133 { NULL, SYMBOL_CHARSET }};
135 static SuffixCharset sufch_microsoft[] = {
136 { "cp1250", EE_CHARSET },
137 { "cp1251", RUSSIAN_CHARSET },
138 { "cp1252", ANSI_CHARSET },
139 { "cp1253", GREEK_CHARSET },
140 { "cp1254", TURKISH_CHARSET },
141 { "cp1255", HEBREW_CHARSET },
142 { "cp1256", ARABIC_CHARSET },
143 { "cp1257", BALTIC_CHARSET },
144 { "fontspecific", SYMBOL_CHARSET },
145 { "symbol", SYMBOL_CHARSET },
146 { NULL, SYMBOL_CHARSET }};
148 static SuffixCharset sufch_tcvn[] = {
149 { "0", TCVN_CHARSET },
150 { NULL, TCVN_CHARSET }};
152 static SuffixCharset sufch_tis620[] = {
153 { "0", THAI_CHARSET },
154 { NULL, THAI_CHARSET }};
156 static SuffixCharset sufch_viscii[] = {
157 { "1", VISCII_CHARSET },
158 { NULL, VISCII_CHARSET }};
160 static SuffixCharset sufch_windows[] = {
161 { "1250", EE_CHARSET },
162 { "1251", RUSSIAN_CHARSET },
163 { "1252", ANSI_CHARSET },
164 { "1253", GREEK_CHARSET },
165 { "1254", TURKISH_CHARSET },
166 { "1255", HEBREW_CHARSET },
167 { "1256", ARABIC_CHARSET },
168 { "1257", BALTIC_CHARSET },
169 { NULL, BALTIC_CHARSET }}; /* CHECK/FIXME is BALTIC really the default ? */
171 static SuffixCharset sufch_koi8[] = {
172 { "r", RUSSIAN_CHARSET },
173 { NULL, RUSSIAN_CHARSET }};
175 /* Each of these must be matched explicitly */
176 static SuffixCharset sufch_any[] = {
177 { "fontspecific", SYMBOL_CHARSET },
178 { NULL, 0 }};
181 typedef struct __fet
183 LPSTR prefix;
184 SuffixCharset* sufch;
185 struct __fet* next;
186 } fontEncodingTemplate;
188 /* Note: we can attach additional encoding mappings to the end
189 * of this table at runtime.
191 static fontEncodingTemplate __fETTable[] = {
192 { "ansi", sufch_ansi, &__fETTable[1] },
193 { "ascii", sufch_ansi, &__fETTable[2] },
194 { "iso646.1991", sufch_iso646, &__fETTable[3] },
195 { "iso8859", sufch_iso8859, &__fETTable[4] },
196 { "microsoft", sufch_microsoft, &__fETTable[5] },
197 { "tcvn", sufch_tcvn, &__fETTable[6] },
198 { "tis620.2533", sufch_tis620, &__fETTable[7] },
199 { "viscii1.1", sufch_viscii, &__fETTable[8] },
200 { "windows", sufch_windows, &__fETTable[9] },
201 { "koi8", sufch_koi8, &__fETTable[10] },
202 /* NULL prefix matches anything so put it last */
203 { NULL, sufch_any, NULL },
205 static fontEncodingTemplate* fETTable = __fETTable;
207 static int DefResolution = 0;
209 static CRITICAL_SECTION crtsc_fonts_X11;
211 static fontResource* fontList = NULL;
212 static fontObject* fontCache = NULL; /* array */
213 static int fontCacheSize = FONTCACHE;
214 static int fontLF = -1, fontMRU = -1; /* last free, most recently used */
216 #define __PFONT(pFont) ( fontCache + ((UINT)(pFont) & 0x0000FFFF) )
217 #define CHECK_PFONT(pFont) ( (((UINT)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
218 (((UINT)(pFont) & 0x0000FFFF) < fontCacheSize) )
220 static Atom RAW_ASCENT;
221 static Atom RAW_DESCENT;
223 /***********************************************************************
224 * Helper macros from X distribution
227 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
228 (((cs)->rbearing|(cs)->lbearing| \
229 (cs)->ascent|(cs)->descent) == 0))
231 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
233 cs = def; \
234 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
235 if (fs->per_char == NULL) { \
236 cs = &fs->min_bounds; \
237 } else { \
238 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
239 if (CI_NONEXISTCHAR(cs)) cs = def; \
244 #define CI_GET_DEFAULT_INFO(fs,cs) \
245 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
247 /***********************************************************************
248 * Checksums
250 static UINT16 __lfCheckSum( LPLOGFONT16 plf )
252 CHAR font[LF_FACESIZE];
253 UINT16 checksum = 0;
254 UINT16 i;
256 #define ptr ((UINT16*)plf)
257 for( i = 0; i < 9; i++ ) checksum ^= *ptr++;
258 #undef ptr
259 i = 0;
260 #define ptr ((CHAR*)plf)
261 do { font[i++] = tolower(*ptr++); } while (( i < LF_FACESIZE) && (*ptr) && (*ptr!=' '));
262 for( ptr = font, i >>= 1; i > 0; i-- )
263 #undef ptr
264 #define ptr ((UINT16*)plf)
265 checksum ^= *ptr++;
266 #undef ptr
267 return checksum;
270 static UINT16 __genericCheckSum( const void *ptr, int size )
272 unsigned int checksum = 0;
273 const char *p = (const char *)ptr;
274 while (size-- > 0)
275 checksum ^= (checksum << 3) + (checksum >> 29) + *p++;
277 return checksum & 0xffff;
280 /*************************************************************************
281 * LFD parse/compose routines
283 * NB. LFD_Parse will use lpFont for its own ends, so if you want to keep it
284 * make a copy first
286 * These functions also do TILDE to HYPHEN conversion
288 static LFD* LFD_Parse(LPSTR lpFont)
290 LFD* lfd;
291 char *lpch = lpFont, *lfd_fld[LFD_FIELDS], *field_start;
292 int i;
293 if (*lpch != HYPHEN)
295 WARN("font '%s' doesn't begin with '%c'\n", lpFont, HYPHEN);
296 return NULL;
299 field_start = ++lpch;
300 for( i = 0; i < LFD_FIELDS; )
302 if (*lpch == HYPHEN)
304 *lpch = '\0';
305 lfd_fld[i] = field_start;
306 i++;
307 field_start = ++lpch;
309 else if (!*lpch)
311 lfd_fld[i] = field_start;
312 i++;
313 break;
315 else if (*lpch == TILDE)
317 *lpch = HYPHEN;
318 ++lpch;
320 else
321 ++lpch;
323 /* Fill in the empty fields with NULLS */
324 for (; i< LFD_FIELDS; i++)
325 lfd_fld[i] = NULL;
326 if (*lpch)
327 WARN("Extra ignored in font '%s'\n", lpFont);
329 lfd = HeapAlloc( SystemHeap, 0, sizeof(LFD) );
330 if (lfd)
332 lfd->foundry = lfd_fld[0];
333 lfd->family = lfd_fld[1];
334 lfd->weight = lfd_fld[2];
335 lfd->slant = lfd_fld[3];
336 lfd->set_width = lfd_fld[4];
337 lfd->add_style = lfd_fld[5];
338 lfd->pixel_size = lfd_fld[6];
339 lfd->point_size = lfd_fld[7];
340 lfd->resolution_x = lfd_fld[8];
341 lfd->resolution_y = lfd_fld[9];
342 lfd->spacing = lfd_fld[10];
343 lfd->average_width = lfd_fld[11];
344 lfd->charset_registry = lfd_fld[12];
345 lfd->charset_encoding = lfd_fld[13];
347 return lfd;
351 static void LFD_UnParse(LPSTR dp, UINT buf_size, LFD* lfd)
353 char* lfd_fld[LFD_FIELDS];
354 int i;
356 if (!buf_size)
357 return; /* Dont be silly */
359 lfd_fld[0] = lfd->foundry;
360 lfd_fld[1] = lfd->family;
361 lfd_fld[2] = lfd->weight ;
362 lfd_fld[3] = lfd->slant ;
363 lfd_fld[4] = lfd->set_width ;
364 lfd_fld[5] = lfd->add_style;
365 lfd_fld[6] = lfd->pixel_size;
366 lfd_fld[7] = lfd->point_size;
367 lfd_fld[8] = lfd->resolution_x;
368 lfd_fld[9] = lfd->resolution_y ;
369 lfd_fld[10] = lfd->spacing ;
370 lfd_fld[11] = lfd->average_width ;
371 lfd_fld[12] = lfd->charset_registry ;
372 lfd_fld[13] = lfd->charset_encoding ;
374 buf_size--; /* Room for the terminator */
376 for (i = 0; i < LFD_FIELDS; i++)
378 char* sp = lfd_fld[i];
379 if (!sp || !buf_size)
380 break;
382 *dp++ = HYPHEN;
383 buf_size--;
384 while (buf_size > 0 && *sp)
386 *dp = (*sp == HYPHEN) ? TILDE : *sp;
387 buf_size--;
388 dp++; sp++;
391 *dp = '\0';
395 static void LFD_GetWeight( fontInfo* fi, LPCSTR lpStr)
397 int j = lstrlenA(lpStr);
398 if( j == 1 && *lpStr == '0')
399 fi->fi_flags |= FI_POLYWEIGHT;
400 else if( j == 4 )
402 if( !strcasecmp( "bold", lpStr) )
403 fi->df.dfWeight = FW_BOLD;
404 else if( !strcasecmp( "demi", lpStr) )
406 fi->fi_flags |= FI_FW_DEMI;
407 fi->df.dfWeight = FW_DEMIBOLD;
409 else if( !strcasecmp( "book", lpStr) )
411 fi->fi_flags |= FI_FW_BOOK;
412 fi->df.dfWeight = FW_REGULAR;
415 else if( j == 5 )
417 if( !strcasecmp( "light", lpStr) )
418 fi->df.dfWeight = FW_LIGHT;
419 else if( !strcasecmp( "black", lpStr) )
420 fi->df.dfWeight = FW_BLACK;
422 else if( j == 6 && !strcasecmp( "medium", lpStr) )
423 fi->df.dfWeight = FW_REGULAR;
424 else if( j == 8 && !strcasecmp( "demibold", lpStr) )
425 fi->df.dfWeight = FW_DEMIBOLD;
426 else
427 fi->df.dfWeight = FW_DONTCARE; /* FIXME: try to get something
428 * from the weight property */
431 static BOOL LFD_GetSlant( fontInfo* fi, LPCSTR lpStr)
433 int l = lstrlenA(lpStr);
434 if( l == 1 )
436 switch( tolower( *lpStr ) )
438 case '0': fi->fi_flags |= FI_POLYSLANT; /* haven't seen this one yet */
439 default:
440 case 'r': fi->df.dfItalic = 0;
441 break;
442 case 'o':
443 fi->fi_flags |= FI_OBLIQUE;
444 case 'i': fi->df.dfItalic = 1;
445 break;
447 return FALSE;
449 return TRUE;
452 static void LFD_GetStyle( fontInfo* fi, LPCSTR lpstr, int dec_style_check)
454 int j = lstrlenA(lpstr);
455 if( j > 3 ) /* find out is there "sans" or "script" */
457 j = 0;
459 if( strstr(lpstr, "sans") )
461 fi->df.dfPitchAndFamily |= FF_SWISS;
462 j = 1;
464 if( strstr(lpstr, "script") )
466 fi->df.dfPitchAndFamily |= FF_SCRIPT;
467 j = 1;
469 if( !j && dec_style_check )
470 fi->df.dfPitchAndFamily |= FF_DECORATIVE;
474 /*************************************************************************
475 * LFD_InitFontInfo
477 * INIT ONLY
479 * Fill in some fields in the fontInfo struct.
481 static int LFD_InitFontInfo( fontInfo* fi, const LFD* lfd, LPCSTR fullname )
483 int i, j, dec_style_check, scalability;
484 fontEncodingTemplate* boba;
485 const char* ridiculous = "font '%s' has ridiculous %s\n";
486 char* lpstr;
488 if (!lfd->charset_registry)
490 WARN("font '%s' does not have enough fields\n", fullname);
491 return FALSE;
494 memset(fi, 0, sizeof(fontInfo) );
496 /* weight name - */
497 LFD_GetWeight( fi, lfd->weight);
499 /* slant - */
500 dec_style_check = LFD_GetSlant( fi, lfd->slant);
502 /* width name - */
503 lpstr = lfd->set_width;
504 if( strcasecmp( "normal", lpstr) ) /* XXX 'narrow', 'condensed', etc... */
505 dec_style_check = TRUE;
506 else
507 fi->fi_flags |= FI_NORMAL;
509 /* style - */
510 LFD_GetStyle(fi, lfd->add_style, dec_style_check);
512 /* pixel & decipoint height, and res_x & y */
514 scalability = 0;
516 j = strlen(lfd->pixel_size);
517 if( j == 0 || j > 3 )
519 WARN(ridiculous, fullname, "pixel_size");
520 return FALSE;
522 if( !(fi->lfd_height = atoi(lfd->pixel_size)) )
523 scalability++;
525 j = strlen(lfd->point_size);
526 if( j == 0 || j > 3 )
528 WARN(ridiculous, fullname, "point_size");
529 return FALSE;
531 if( !(atoi(lfd->point_size)) )
532 scalability++;
534 j = strlen(lfd->resolution_x);
535 if( j == 0 || j > 3 )
537 WARN(ridiculous, fullname, "resolution_x");
538 return FALSE;
540 if( !(fi->lfd_resolution = atoi(lfd->resolution_x)) )
541 scalability++;
543 j = strlen(lfd->resolution_y);
544 if( j == 0 || j > 3 )
546 WARN(ridiculous, fullname, "resolution_y");
547 return FALSE;
549 if( !(atoi(lfd->resolution_y)) )
550 scalability++;
552 /* Check scalability */
553 switch (scalability)
555 case 0: /* Bitmap */
556 break;
557 case 4: /* Scalable */
558 fi->fi_flags |= FI_SCALABLE;
559 break;
560 case 2:
561 /* #$%^!!! X11R6 mutant garbage (scalable bitmap) */
562 TRACE("Skipping scalable bitmap '%s'\n", fullname);
563 return FALSE;
564 default:
565 WARN("Font '%s' has weird scalability\n", fullname);
566 return FALSE;
569 /* spacing - */
570 lpstr = lfd->spacing;
571 switch( *lpstr )
573 case '\0':
574 WARN("font '%s' has no spacing\n", fullname);
575 return FALSE;
577 case 'p': fi->fi_flags |= FI_VARIABLEPITCH;
578 break;
579 case 'c': fi->df.dfPitchAndFamily |= FF_MODERN;
580 fi->fi_flags |= FI_FIXEDEX;
581 /* fall through */
582 case 'm': fi->fi_flags |= FI_FIXEDPITCH;
583 break;
584 default:
585 /* Of course this line does nothing */
586 fi->df.dfPitchAndFamily |= DEFAULT_PITCH | FF_DONTCARE;
589 /* average width - */
590 lpstr = lfd->average_width;
591 j = strlen(lpstr);
592 if( j == 0 || j > 3 )
594 WARN(ridiculous, fullname, "average_width");
595 return FALSE;
598 if( !(atoi(lpstr)) && !scalability )
600 WARN("font '%s' has average_width 0 but is not scalable!!\n", fullname);
601 return FALSE;
604 /* charset registry, charset encoding - */
605 lpstr = lfd->charset_registry;
606 if( strstr(lpstr, "jisx") ||
607 strstr(lpstr, "ksc") ||
608 strstr(lpstr, "gb2312") ||
609 strstr(lpstr, "big5") ||
610 strstr(lpstr, "unicode") )
612 TRACE(" 2-byte fonts like '%s' are not supported\n", fullname);
613 return FALSE;
616 fi->df.dfCharSet = ANSI_CHARSET;
618 for( i = 0, boba = fETTable; boba; boba = boba->next, i++ )
620 if (!boba->prefix || !strcasecmp(lpstr, boba->prefix))
622 if (lfd->charset_encoding)
624 for( j = 0; boba->sufch[j].psuffix; j++ )
626 if( !strcasecmp(lfd->charset_encoding, boba->sufch[j].psuffix ))
628 fi->df.dfCharSet = boba->sufch[j].charset;
629 goto done;
632 if (boba->prefix)
634 WARN("font '%s' has unknown character encoding '%s'\n",
635 fullname, lfd->charset_encoding);
636 fi->df.dfCharSet = boba->sufch[j].charset;
637 j = 254;
638 goto done;
641 else if (boba->prefix)
643 for( j = 0; boba->sufch[j].psuffix; j++ )
645 fi->df.dfCharSet = boba->sufch[j].charset;
646 j = 255;
647 goto done;
651 WARN("font '%s' has unknown character set '%s'\n", fullname, lpstr);
652 return FALSE;
654 done:
655 /* i - index into fETTable
656 * j - index into suffix array for fETTable[i]
657 * except:
658 * 254 - unknown suffix
659 * 255 - no suffix at all.
661 fi->fi_encoding = 256 * (UINT16)i + (UINT16)j;
663 return TRUE;
667 /*************************************************************************
668 * LFD_AngleMatrix
670 * make a matrix suitable for LFD based on theta radians
672 static void LFD_AngleMatrix( char* buffer, int h, double theta)
674 double matrix[4];
675 matrix[0] = h*cos(theta);
676 matrix[1] = h*sin(theta);
677 matrix[2] = -h*sin(theta);
678 matrix[3] = h*cos(theta);
679 sprintf(buffer, "[%+f%+f%+f%+f]", matrix[0], matrix[1], matrix[2], matrix[3]);
682 /*************************************************************************
683 * LFD_ComposeLFD
685 * Note: uRelax is a treatment not a cure. Font mapping algorithm
686 * should be bulletproof enough to allow us to avoid hacks like
687 * this despite LFD being so braindead.
689 static BOOL LFD_ComposeLFD( const fontObject* fo,
690 INT height, LPSTR lpLFD, UINT uRelax )
692 int i, h;
693 char *any = "*";
694 char h_string[64], resx_string[64], resy_string[64];
695 LFD aLFD;
697 /* Get the worst case over with first */
699 /* RealizeFont() will call us repeatedly with increasing uRelax
700 * until XLoadFont() succeeds.
701 * to avoid an infinite loop; these will always match
703 if (uRelax >= 5)
705 if (uRelax == 5)
706 sprintf( lpLFD, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" );
707 else
708 sprintf( lpLFD, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" );
709 return TRUE;
712 /* read foundry + family from fo */
713 aLFD.foundry = fo->fr->resource->foundry;
714 aLFD.family = fo->fr->resource->family;
716 /* add weight */
717 switch( fo->fi->df.dfWeight )
719 case FW_BOLD:
720 aLFD.weight = "bold"; break;
721 case FW_REGULAR:
722 if( fo->fi->fi_flags & FI_FW_BOOK )
723 aLFD.weight = "book";
724 else
725 aLFD.weight = "medium";
726 break;
727 case FW_DEMIBOLD:
728 aLFD.weight = "demi";
729 if( !( fo->fi->fi_flags & FI_FW_DEMI) )
730 aLFD.weight = "bold";
731 break;
732 case FW_BLACK:
733 aLFD.weight = "black"; break;
734 case FW_LIGHT:
735 aLFD.weight = "light"; break;
736 default:
737 aLFD.weight = any;
740 /* add slant */
741 if( fo->fi->df.dfItalic )
742 if( fo->fi->fi_flags & FI_OBLIQUE )
743 aLFD.slant = "o";
744 else
745 aLFD.slant = "i";
746 else
747 aLFD.slant = (uRelax < 1) ? "r" : any;
749 /* add width */
750 if( fo->fi->fi_flags & FI_NORMAL )
751 aLFD.set_width = "normal";
752 else
753 aLFD.set_width = any;
755 /* ignore style */
756 aLFD.add_style = any;
758 /* add pixelheight
760 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
762 if( fo->fo_flags & FO_SYNTH_HEIGHT )
763 h = fo->fi->lfd_height;
764 else
766 h = (fo->fi->lfd_height * height + (fo->fi->df.dfPixHeight>>1));
767 h /= fo->fi->df.dfPixHeight;
769 if (h < MIN_FONT_SIZE) /* Resist rounding down to 0 */
770 h = MIN_FONT_SIZE;
771 else if (h > MAX_FONT_SIZE) /* Sanity check as huge fonts can lock up the font server */
773 WARN("Huge font size %d pixels has been reduced to %d\n", h, MAX_FONT_SIZE);
774 h = MAX_FONT_SIZE;
777 if (uRelax <= 2)
778 /* handle rotated fonts */
779 if (fo->lf.lfEscapement) {
780 /* escapement is in tenths of degrees, theta is in radians */
781 double theta = M_PI*fo->lf.lfEscapement/1800.;
782 LFD_AngleMatrix(h_string, h, theta);
784 else
786 sprintf(h_string, "%d", h);
788 else
789 sprintf(h_string, "%d", fo->fi->lfd_height);
791 aLFD.pixel_size = h_string;
792 aLFD.point_size = any;
794 /* resolution_x,y, average width */
795 /* FOX ME - Why do some font servers ignore average width ?
796 * so that you have to mess around with res_y
798 aLFD.average_width = any;
799 if (uRelax <= 3)
801 sprintf(resx_string, "%d", fo->fi->lfd_resolution);
802 aLFD.resolution_x = resx_string;
804 strcpy(resy_string, resx_string);
805 if( uRelax == 0 && XTextCaps & TC_SF_X_YINDEP )
807 if( fo->lf.lfWidth && !(fo->fo_flags & FO_SYNTH_WIDTH))
809 int resy = 0.5 + fo->fi->lfd_resolution *
810 (fo->fi->df.dfAvgWidth * height) /
811 (fo->lf.lfWidth * fo->fi->df.dfPixHeight) ;
812 sprintf(resy_string, "%d", resy);
814 else
815 ; /* FIXME - synth width */
817 aLFD.resolution_y = resy_string;
819 else
821 aLFD.resolution_x = aLFD.resolution_y = any;
824 /* spacing */
826 char* w;
828 if( fo->fi->fi_flags & FI_FIXEDPITCH )
829 w = ( fo->fi->fi_flags & FI_FIXEDEX ) ? "c" : "m";
830 else
831 w = ( fo->fi->fi_flags & FI_VARIABLEPITCH ) ? "p" : any;
833 aLFD.spacing = (uRelax <= 1) ? w : any;
836 /* encoding */
838 if (uRelax <= 4)
840 fontEncodingTemplate* boba;
842 i = fo->fi->fi_encoding >> 8;
843 for( boba = fETTable; i; i--, boba = boba->next );
845 aLFD.charset_registry = boba->prefix ? boba->prefix : any;
847 i = fo->fi->fi_encoding & 255;
848 switch( i )
850 default:
851 aLFD.charset_encoding = boba->sufch[i].psuffix;
852 break;
854 case 254:
855 aLFD.charset_encoding = any;
856 break;
858 case 255: /* no suffix - it ends eg "-ascii" */
859 aLFD.charset_encoding = NULL;
860 break;
863 else
865 aLFD.charset_registry = any;
866 aLFD.charset_encoding = any;
869 LFD_UnParse(lpLFD, MAX_LFD_LENGTH, &aLFD);
871 TRACE("\tLFD(uRelax=%d): %s\n", uRelax, lpLFD );
872 return TRUE;
876 /***********************************************************************
877 * X Font Resources
879 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
880 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
882 static void XFONT_GetLeading( const LPIFONTINFO16 pFI, const XFontStruct* x_fs,
883 INT16* pIL, INT16* pEL, const XFONTTRANS *XFT )
885 unsigned long height;
886 unsigned min = (unsigned char)pFI->dfFirstChar;
887 BOOL bIsLatin = IS_LATIN_CHARSET(pFI->dfCharSet);
889 if( pEL ) *pEL = 0;
891 if(XFT) {
892 Atom RAW_CAP_HEIGHT = TSXInternAtom(display, "RAW_CAP_HEIGHT", TRUE);
893 if(TSXGetFontProperty((XFontStruct*)x_fs, RAW_CAP_HEIGHT, &height))
894 *pIL = XFT->ascent -
895 (INT)(XFT->pixelsize / 1000.0 * height);
896 else
897 *pIL = 0;
898 return;
901 if( TSXGetFontProperty((XFontStruct*)x_fs, XA_CAP_HEIGHT, &height) == FALSE )
903 if( x_fs->per_char )
904 if( bIsLatin )
905 height = x_fs->per_char['X' - min].ascent;
906 else
907 if (x_fs->ascent >= x_fs->max_bounds.ascent)
908 height = x_fs->max_bounds.ascent;
909 else
911 height = x_fs->ascent;
912 if( pEL )
913 *pEL = x_fs->max_bounds.ascent - height;
915 else
916 height = x_fs->min_bounds.ascent;
919 *pIL = x_fs->ascent - height;
922 /***********************************************************************
923 * XFONT_CharWidth
925 static int XFONT_CharWidth(const XFontStruct* x_fs,
926 const XFONTTRANS *XFT, int ch)
928 if(!XFT)
929 return x_fs->per_char[ch].width;
930 else
931 return x_fs->per_char[ch].attributes * XFT->pixelsize / 1000.0;
934 /***********************************************************************
935 * XFONT_GetAvgCharWidth
937 static INT XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI, const XFontStruct* x_fs,
938 const XFONTTRANS *XFT)
940 unsigned min = (unsigned char)pFI->dfFirstChar;
941 unsigned max = (unsigned char)pFI->dfLastChar;
943 INT avg;
945 if( x_fs->per_char )
947 int width = 0, chars = 0, j;
948 if( IS_LATIN_CHARSET(pFI->dfCharSet))
950 /* FIXME - should use a weighted average */
951 for( j = 0; j < 26; j++ )
952 width += XFONT_CharWidth(x_fs, XFT, 'a' + j - min) +
953 XFONT_CharWidth(x_fs, XFT, 'A' + j - min);
954 chars = 52;
956 else /* unweighted average of everything */
958 for( j = 0, max -= min; j <= max; j++ )
959 if( !CI_NONEXISTCHAR(x_fs->per_char + j) )
961 width += XFONT_CharWidth(x_fs, XFT, j);
962 chars++;
965 avg = (width + (chars>>1))/ chars;
967 else /* uniform width */
968 avg = x_fs->min_bounds.width;
970 return avg;
973 /***********************************************************************
974 * XFONT_GetMaxCharWidth
976 static INT XFONT_GetMaxCharWidth(const XFontStruct* xfs, const XFONTTRANS *XFT)
978 unsigned min = (unsigned char)xfs->min_char_or_byte2;
979 unsigned max = (unsigned char)xfs->max_char_or_byte2;
980 int maxwidth, j;
982 if(!XFT || !xfs->per_char)
983 return abs(xfs->max_bounds.width);
985 for( j = 0, maxwidth = 0, max -= min; j <= max; j++ )
986 if( !CI_NONEXISTCHAR(xfs->per_char + j) )
987 if(maxwidth < xfs->per_char[j].attributes)
988 maxwidth = xfs->per_char[j].attributes;
990 maxwidth *= XFT->pixelsize / 1000.0;
991 return maxwidth;
994 /***********************************************************************
995 * XFONT_SetFontMetric
997 * INIT ONLY
999 * Initializes IFONTINFO16.
1001 static void XFONT_SetFontMetric(fontInfo* fi, const fontResource* fr, XFontStruct* xfs)
1003 unsigned min, max;
1004 fi->df.dfFirstChar = (BYTE)(min = xfs->min_char_or_byte2);
1005 fi->df.dfLastChar = (BYTE)(max = xfs->max_char_or_byte2);
1007 fi->df.dfDefaultChar = (BYTE)xfs->default_char;
1008 fi->df.dfBreakChar = (BYTE)(( ' ' < min || ' ' > max) ? xfs->default_char: ' ');
1010 fi->df.dfPixHeight = (INT16)((fi->df.dfAscent = (INT16)xfs->ascent) + xfs->descent);
1011 fi->df.dfPixWidth = (xfs->per_char) ? 0 : xfs->min_bounds.width;
1013 XFONT_GetLeading( &fi->df, xfs, &fi->df.dfInternalLeading, &fi->df.dfExternalLeading, NULL );
1014 fi->df.dfAvgWidth = (INT16)XFONT_GetAvgCharWidth(&fi->df, xfs, NULL );
1015 fi->df.dfMaxWidth = (INT16)XFONT_GetMaxCharWidth(xfs, NULL);
1017 if( xfs->min_bounds.width != xfs->max_bounds.width )
1018 fi->df.dfPitchAndFamily |= TMPF_FIXED_PITCH; /* au contraire! */
1019 if( fi->fi_flags & FI_SCALABLE )
1021 fi->df.dfType = DEVICE_FONTTYPE;
1022 fi->df.dfPitchAndFamily |= TMPF_DEVICE;
1024 else if( fi->fi_flags & FI_TRUETYPE )
1025 fi->df.dfType = TRUETYPE_FONTTYPE;
1026 else
1027 fi->df.dfType = RASTER_FONTTYPE;
1029 fi->df.dfFace = fr->lfFaceName;
1032 /***********************************************************************
1033 * XFONT_GetTextMetrics
1035 * GetTextMetrics() back end.
1037 static void XFONT_GetTextMetrics( const fontObject* pfo, const LPTEXTMETRICA pTM )
1039 LPIFONTINFO16 pdf = &pfo->fi->df;
1041 if( ! pfo->lpX11Trans ) {
1042 pTM->tmAscent = pfo->fs->ascent;
1043 pTM->tmDescent = pfo->fs->descent;
1044 } else {
1045 pTM->tmAscent = pfo->lpX11Trans->ascent;
1046 pTM->tmDescent = pfo->lpX11Trans->descent;
1049 pTM->tmAscent *= pfo->rescale;
1050 pTM->tmDescent *= pfo->rescale;
1052 pTM->tmHeight = pTM->tmAscent + pTM->tmDescent;
1054 pTM->tmAveCharWidth = pfo->foAvgCharWidth * pfo->rescale;
1055 pTM->tmMaxCharWidth = pfo->foMaxCharWidth * pfo->rescale;
1057 pTM->tmInternalLeading = pfo->foInternalLeading * pfo->rescale;
1058 pTM->tmExternalLeading = pdf->dfExternalLeading * pfo->rescale;
1060 pTM->tmStruckOut = (pfo->fo_flags & FO_SYNTH_STRIKEOUT )
1061 ? 1 : pdf->dfStrikeOut;
1062 pTM->tmUnderlined = (pfo->fo_flags & FO_SYNTH_UNDERLINE )
1063 ? 1 : pdf->dfUnderline;
1065 pTM->tmOverhang = 0;
1066 if( pfo->fo_flags & FO_SYNTH_ITALIC )
1068 pTM->tmOverhang += pTM->tmHeight/3;
1069 pTM->tmItalic = 1;
1070 } else
1071 pTM->tmItalic = pdf->dfItalic;
1073 pTM->tmWeight = pdf->dfWeight;
1074 if( pfo->fo_flags & FO_SYNTH_BOLD )
1076 pTM->tmOverhang++;
1077 pTM->tmWeight += 100;
1080 pTM->tmFirstChar = pdf->dfFirstChar;
1081 pTM->tmLastChar = pdf->dfLastChar;
1082 pTM->tmDefaultChar = pdf->dfDefaultChar;
1083 pTM->tmBreakChar = pdf->dfBreakChar;
1085 pTM->tmCharSet = pdf->dfCharSet;
1086 pTM->tmPitchAndFamily = pdf->dfPitchAndFamily;
1088 pTM->tmDigitizedAspectX = pdf->dfHorizRes;
1089 pTM->tmDigitizedAspectY = pdf->dfVertRes;
1092 /***********************************************************************
1093 * XFONT_GetFontMetric
1095 * Retrieve font metric info (enumeration).
1097 static UINT XFONT_GetFontMetric( const fontInfo* pfi, const LPENUMLOGFONTEX16 pLF,
1098 const LPNEWTEXTMETRIC16 pTM )
1100 memset( pLF, 0, sizeof(*pLF) );
1101 memset( pTM, 0, sizeof(*pTM) );
1103 #define plf ((LPLOGFONT16)pLF)
1104 plf->lfHeight = pTM->tmHeight = pfi->df.dfPixHeight;
1105 plf->lfWidth = pTM->tmAveCharWidth = pfi->df.dfAvgWidth;
1106 plf->lfWeight = pTM->tmWeight = pfi->df.dfWeight;
1107 plf->lfItalic = pTM->tmItalic = pfi->df.dfItalic;
1108 plf->lfUnderline = pTM->tmUnderlined = pfi->df.dfUnderline;
1109 plf->lfStrikeOut = pTM->tmStruckOut = pfi->df.dfStrikeOut;
1110 plf->lfCharSet = pTM->tmCharSet = pfi->df.dfCharSet;
1112 /* convert pitch values */
1114 pTM->tmPitchAndFamily = pfi->df.dfPitchAndFamily;
1115 plf->lfPitchAndFamily = (pfi->df.dfPitchAndFamily & 0xF1) + 1;
1117 lstrcpynA( plf->lfFaceName, pfi->df.dfFace, LF_FACESIZE );
1118 #undef plf
1120 /* FIXME: fill in rest of plF values
1121 lstrcpynA(plF->elfFullName, , LF_FULLFACESIZE);
1122 lstrcpynA(plF->elfStyle, , LF_FACESIZE);
1123 lstrcpynA(plF->elfScript, , LF_FACESIZE);
1126 pTM->tmAscent = pfi->df.dfAscent;
1127 pTM->tmDescent = pTM->tmHeight - pTM->tmAscent;
1128 pTM->tmInternalLeading = pfi->df.dfInternalLeading;
1129 pTM->tmMaxCharWidth = pfi->df.dfMaxWidth;
1130 pTM->tmDigitizedAspectX = pfi->df.dfHorizRes;
1131 pTM->tmDigitizedAspectY = pfi->df.dfVertRes;
1133 pTM->tmFirstChar = pfi->df.dfFirstChar;
1134 pTM->tmLastChar = pfi->df.dfLastChar;
1135 pTM->tmDefaultChar = pfi->df.dfDefaultChar;
1136 pTM->tmBreakChar = pfi->df.dfBreakChar;
1138 /* return font type */
1140 return pfi->df.dfType;
1144 /***********************************************************************
1145 * XFONT_FixupFlags
1147 * INIT ONLY
1149 * dfPitchAndFamily flags for some common typefaces.
1151 static BYTE XFONT_FixupFlags( LPCSTR lfFaceName )
1153 switch( lfFaceName[0] )
1155 case 'a':
1156 case 'A': if(!strncasecmp(lfFaceName, "Arial", 5) )
1157 return FF_SWISS;
1158 break;
1159 case 'h':
1160 case 'H': if(!strcasecmp(lfFaceName, "Helvetica") )
1161 return FF_SWISS;
1162 break;
1163 case 'c':
1164 case 'C': if(!strncasecmp(lfFaceName, "Courier", 7))
1165 return FF_MODERN;
1167 if (!strcasecmp(lfFaceName, "Charter") )
1168 return FF_ROMAN;
1169 break;
1170 case 'p':
1171 case 'P': if( !strcasecmp(lfFaceName,"Palatino") )
1172 return FF_ROMAN;
1173 break;
1174 case 't':
1175 case 'T': if(!strncasecmp(lfFaceName, "Times", 5) )
1176 return FF_ROMAN;
1177 break;
1178 case 'u':
1179 case 'U': if(!strcasecmp(lfFaceName, "Utopia") )
1180 return FF_ROMAN;
1181 break;
1182 case 'z':
1183 case 'Z': if(!strcasecmp(lfFaceName, "Zapf Dingbats") )
1184 return FF_DECORATIVE;
1186 return 0;
1189 /***********************************************************************
1190 * XFONT_SameFoundryAndFamily
1192 * INIT ONLY
1194 static BOOL XFONT_SameFoundryAndFamily( const LFD* lfd1, const LFD* lfd2 )
1196 return ( !strcasecmp( lfd1->foundry, lfd2->foundry ) &&
1197 !strcasecmp( lfd1->family, lfd2->family ) );
1200 /***********************************************************************
1201 * XFONT_InitialCapitals
1203 * INIT ONLY
1205 * Upper case first letters of words & remove multiple spaces
1207 static void XFONT_InitialCapitals(LPSTR lpch)
1209 int i;
1210 BOOL up;
1211 char* lpstr = lpch;
1213 for( i = 0, up = TRUE; *lpch; lpch++, i++ )
1215 if( isspace(*lpch) )
1217 if (!up) /* Not already got one */
1219 *lpstr++ = ' ';
1220 up = TRUE;
1223 else if( isalpha(*lpch) && up )
1225 *lpstr++ = toupper(*lpch);
1226 up = FALSE;
1228 else
1230 *lpstr++ = *lpch;
1231 up = FALSE;
1235 /* Remove possible trailing space */
1236 if (up && i > 0)
1237 --lpstr;
1238 *lpstr = '\0';
1242 /***********************************************************************
1243 * XFONT_WindowsNames
1245 * INIT ONLY
1247 * Build generic Windows aliases for X font names.
1249 * -misc-fixed- -> "Fixed"
1250 * -sony-fixed- -> "Sony Fixed", etc...
1252 static void XFONT_WindowsNames(void)
1254 fontResource* fr;
1256 for( fr = fontList; fr ; fr = fr->next )
1258 fontResource* pfr;
1259 char* lpch;
1261 if( fr->fr_flags & FR_NAMESET ) continue; /* skip already assigned */
1263 for( pfr = fontList; pfr != fr ; pfr = pfr->next )
1264 if( pfr->fr_flags & FR_NAMESET )
1266 if (!strcasecmp( pfr->resource->family, fr->resource->family))
1267 break;
1270 lpch = fr->lfFaceName;
1271 wsnprintfA( fr->lfFaceName, sizeof(fr->lfFaceName), "%s %s",
1272 /* prepend vendor name */
1273 (pfr==fr) ? "" : fr->resource->foundry,
1274 fr->resource->family);
1275 XFONT_InitialCapitals(fr->lfFaceName);
1277 BYTE bFamilyStyle = XFONT_FixupFlags( fr->lfFaceName );
1278 if( bFamilyStyle)
1280 fontInfo* fi;
1281 for( fi = fr->fi ; fi ; fi = fi->next )
1282 fi->df.dfPitchAndFamily |= bFamilyStyle;
1286 TRACE("typeface '%s'\n", fr->lfFaceName);
1288 fr->fr_flags |= FR_NAMESET;
1292 /***********************************************************************
1293 * XFONT_LoadDefaultLFD
1295 * Move lfd to the head of fontList to make it more likely to be matched
1297 static void XFONT_LoadDefaultLFD(LFD* lfd, LPCSTR fonttype)
1300 fontResource *fr, *pfr;
1301 for( fr = NULL, pfr = fontList; pfr; pfr = pfr->next )
1303 if( XFONT_SameFoundryAndFamily(pfr->resource, lfd) )
1305 if( fr )
1307 fr->next = pfr->next;
1308 pfr->next = fontList;
1309 fontList = pfr;
1311 break;
1313 fr = pfr;
1315 if (!pfr)
1316 WARN("Default %sfont '-%s-%s-' not available\n", fonttype,
1317 lfd->foundry, lfd->family);
1321 /***********************************************************************
1322 * XFONT_LoadDefault
1324 static void XFONT_LoadDefault(LPCSTR ini, LPCSTR fonttype)
1326 char buffer[MAX_LFD_LENGTH];
1328 if( PROFILE_GetWineIniString( INIFontSection, ini, "", buffer, sizeof buffer ) )
1330 if (*buffer)
1332 LFD* lfd;
1333 char* pch = buffer;
1334 while( *pch && isspace(*pch) ) pch++;
1336 TRACE("Using '%s' as default %sfont\n", pch, fonttype);
1337 lfd = LFD_Parse(pch);
1338 if (lfd && lfd->foundry && lfd->family)
1339 XFONT_LoadDefaultLFD(lfd, fonttype);
1340 else
1341 WARN("Ini section [%s]%s is malformed\n", INIFontSection, ini);
1342 HeapFree(SystemHeap, 0, lfd);
1347 /***********************************************************************
1348 * XFONT_LoadDefaults
1350 static void XFONT_LoadDefaults(void)
1352 XFONT_LoadDefault(INIDefaultFixed, "fixed ");
1353 XFONT_LoadDefault(INIDefault, "");
1356 /***********************************************************************
1357 * XFONT_CreateAlias
1359 static fontAlias* XFONT_CreateAlias( LPCSTR lpTypeFace, LPCSTR lpAlias )
1361 int j;
1362 fontAlias *pfa, *prev = NULL;
1364 for(pfa = aliasTable; pfa; pfa = pfa->next)
1366 /* check if we already got one */
1367 if( !strcasecmp( pfa->faTypeFace, lpAlias ) )
1369 TRACE("redundant alias '%s' -> '%s'\n",
1370 lpAlias, lpTypeFace );
1371 return NULL;
1373 prev = pfa;
1376 j = lstrlenA(lpTypeFace) + 1;
1377 pfa = HeapAlloc( SystemHeap, 0, sizeof(fontAlias) +
1378 j + lstrlenA(lpAlias) + 1 );
1379 if (pfa)
1381 if (!prev)
1382 aliasTable = pfa;
1383 else
1384 prev->next = pfa;
1386 pfa->next = NULL;
1387 pfa->faTypeFace = (LPSTR)(pfa + 1);
1388 lstrcpyA( pfa->faTypeFace, lpTypeFace );
1389 pfa->faAlias = pfa->faTypeFace + j;
1390 lstrcpyA( pfa->faAlias, lpAlias );
1392 TRACE("added alias '%s' for %s\n", lpAlias, lpTypeFace );
1394 return pfa;
1396 return NULL;
1400 /***********************************************************************
1401 * XFONT_LoadAlias
1403 static void XFONT_LoadAlias(const LFD* lfd, LPCSTR lpAlias, BOOL bSubst)
1405 fontResource *fr, *frMatch = NULL;
1406 if (!lfd->foundry || ! lfd->family)
1408 WARN("Malformed font resource for alias '%s'\n", lpAlias);
1409 return;
1411 for (fr = fontList; fr ; fr = fr->next)
1413 if(!strcasecmp(fr->resource->family, lpAlias))
1415 /* alias is not needed since the real font is present */
1416 TRACE("Ignoring font alias '%s' as it is already available as a real font\n", lpAlias);
1417 return;
1419 if( XFONT_SameFoundryAndFamily( fr->resource, lfd ) )
1421 frMatch = fr;
1422 break;
1426 if( frMatch )
1428 if( bSubst )
1430 fontAlias *pfa, *prev = NULL;
1432 for(pfa = aliasTable; pfa; pfa = pfa->next)
1434 /* Remove lpAlias from aliasTable - we should free the old entry */
1435 if(!strcmp(lpAlias, pfa->faAlias))
1437 if(prev)
1438 prev->next = pfa->next;
1439 else
1440 aliasTable = pfa->next;
1443 /* Update any references to the substituted font in aliasTable */
1444 if(!strcmp(frMatch->lfFaceName, pfa->faTypeFace))
1445 pfa->faTypeFace = HEAP_strdupA( SystemHeap, 0, lpAlias );
1446 prev = pfa;
1449 TRACE("\tsubstituted '%s' with %s\n", frMatch->lfFaceName, lpAlias );
1451 lstrcpynA( frMatch->lfFaceName, lpAlias, LF_FACESIZE );
1452 frMatch->fr_flags |= FR_NAMESET;
1454 else
1456 /* create new entry in the alias table */
1457 XFONT_CreateAlias( frMatch->lfFaceName, lpAlias );
1460 else
1462 WARN("Font alias '-%s-%s-' is not available\n", lfd->foundry, lfd->family);
1466 /***********************************************************************
1467 * XFONT_LoadAliases
1469 * INIT ONLY
1471 * Create font aliases for some standard windows fonts using users
1472 * default choice of (sans-)serif fonts
1474 * Read user-defined aliases from wine.conf. Format is as follows
1476 * Alias# = [Windows font name],[LFD font name], <substitute original name>
1478 * Example:
1479 * Alias0 = Arial, -adobe-helvetica-
1480 * Alias1 = Times New Roman, -bitstream-courier-, 1
1481 * ...
1483 * Note that from 081797 and on we have built-in alias templates that take
1484 * care of the necessary Windows typefaces.
1486 typedef struct
1488 LPSTR fatResource;
1489 LPSTR fatAlias;
1490 } aliasTemplate;
1492 static void XFONT_LoadAliases(void)
1494 char *lpResource;
1495 char buffer[MAX_LFD_LENGTH];
1496 int i = 0;
1497 LFD* lfd;
1499 /* built-ins first */
1500 PROFILE_GetWineIniString( INIFontSection, INIDefaultSerif,
1501 "-bitstream-charter-", buffer, sizeof buffer );
1502 TRACE("Using '%s' as default serif font\n", buffer);
1503 lfd = LFD_Parse(buffer);
1504 /* NB XFONT_InitialCapitals should not change these standard aliases */
1505 if (lfd)
1507 XFONT_LoadAlias( lfd, "Tms Roman", FALSE);
1508 XFONT_LoadAlias( lfd, "MS Serif", FALSE);
1509 XFONT_LoadAlias( lfd, "Times New Roman", FALSE);
1511 XFONT_LoadDefaultLFD( lfd, "serif ");
1512 HeapFree(SystemHeap, 0, lfd);
1515 PROFILE_GetWineIniString( INIFontSection, INIDefaultSansSerif,
1516 "-adobe-helvetica-", buffer, sizeof buffer);
1517 TRACE("Using '%s' as default sans serif font\n", buffer);
1518 lfd = LFD_Parse(buffer);
1519 if (lfd)
1521 XFONT_LoadAlias( lfd, "Helv", FALSE);
1522 XFONT_LoadAlias( lfd, "MS Sans Serif", FALSE);
1523 XFONT_LoadAlias( lfd, "Arial", FALSE);
1525 XFONT_LoadDefaultLFD( lfd, "sans serif ");
1526 HeapFree(SystemHeap, 0, lfd);
1529 /* then user specified aliases */
1532 BOOL bHaveAlias, bSubst;
1533 char subsection[32];
1534 wsnprintfA( subsection, sizeof subsection, "%s%i", INIAliasSection, i++ );
1536 bHaveAlias = PROFILE_GetWineIniString( INIFontSection,
1537 subsection, "", buffer, sizeof buffer);
1538 if (!bHaveAlias)
1539 break;
1541 XFONT_InitialCapitals(buffer);
1542 lpResource = PROFILE_GetStringItem( buffer );
1543 bSubst = (PROFILE_GetStringItem( lpResource )) ? TRUE : FALSE;
1544 if( lpResource && *lpResource )
1546 lfd = LFD_Parse(lpResource);
1547 if (lfd)
1549 XFONT_LoadAlias(lfd, buffer, bSubst);
1550 HeapFree(SystemHeap, 0, lfd);
1553 else
1554 WARN("malformed font alias '%s'\n", buffer );
1556 while(TRUE);
1559 /***********************************************************************
1560 * XFONT_UnAlias
1562 * Convert an (potential) alias into a real windows name
1565 static LPCSTR XFONT_UnAlias(char* font)
1567 if (font[0])
1569 fontAlias* fa;
1570 XFONT_InitialCapitals(font); /* to remove extra white space */
1572 for( fa = aliasTable; fa; fa = fa->next )
1573 /* use case insensitive matching to handle eg "MS Sans Serif" */
1574 if( !strcasecmp( fa->faAlias, font ) )
1576 TRACE("found alias '%s'->%s'\n", font, fa->faTypeFace );
1577 strcpy(font, fa->faTypeFace);
1578 return fa->faAlias;
1579 break;
1582 return NULL;
1585 /***********************************************************************
1586 * XFONT_RemoveFontResource
1588 * Caller should check if the font resource is in use. If it is it should
1589 * set FR_REMOVED flag to delay removal until the resource is not in use
1590 * anymore.
1592 void XFONT_RemoveFontResource( fontResource** ppfr )
1594 fontResource* pfr = *ppfr;
1595 #if 0
1596 fontInfo* pfi;
1598 /* FIXME - if fonts were read from a cache, these HeapFrees will fail */
1599 while( pfr->fi )
1601 pfi = pfr->fi->next;
1602 HeapFree( SystemHeap, 0, pfr->fi );
1603 pfr->fi = pfi;
1605 HeapFree( SystemHeap, 0, pfr );
1606 #endif
1607 *ppfr = pfr->next;
1610 /***********************************************************************
1611 * XFONT_LoadIgnores
1613 * INIT ONLY
1615 * Removes specified fonts from the font table to prevent Wine from
1616 * using it.
1618 * Ignore# = [LFD font name]
1620 * Example:
1621 * Ignore0 = -misc-nil-
1622 * Ignore1 = -sun-open look glyph-
1623 * ...
1626 static void XFONT_LoadIgnore(char* lfdname)
1628 fontResource** ppfr;
1630 LFD* lfd = LFD_Parse(lfdname);
1631 if (lfd && lfd->foundry && lfd->family)
1633 for( ppfr = &fontList; *ppfr ; ppfr = &((*ppfr)->next))
1635 if( XFONT_SameFoundryAndFamily( (*ppfr)->resource, lfd) )
1637 TRACE("Ignoring '-%s-%s-'\n",
1638 (*ppfr)->resource->foundry, (*ppfr)->resource->family );
1640 XFONT_RemoveFontResource( ppfr );
1641 break;
1645 else
1646 WARN("Malformed font resource\n");
1648 HeapFree(SystemHeap, 0, lfd);
1651 static void XFONT_LoadIgnores(void)
1653 int i = 0;
1654 char subsection[32];
1655 char buffer[MAX_LFD_LENGTH];
1657 /* Standard one that noone wants */
1658 strcpy(buffer, "-misc-nil-");
1659 XFONT_LoadIgnore(buffer);
1661 /* Others from INI file */
1664 wsprintfA( subsection, "%s%i", INIIgnoreSection, i++ );
1666 if( PROFILE_GetWineIniString( INIFontSection,
1667 subsection, "", buffer, sizeof buffer) )
1669 char* pch = buffer;
1670 while( *pch && isspace(*pch) ) pch++;
1671 XFONT_LoadIgnore(pch);
1673 else
1674 break;
1675 } while(TRUE);
1679 /***********************************************************************
1680 * XFONT_UserMetricsCache
1682 * Returns expanded name for the cachedmetrics file.
1683 * Now it also appends the current value of the $DISPLAY varaible.
1685 static char* XFONT_UserMetricsCache( char* buffer, int* buf_size )
1687 char* pchDisplay, *home;
1689 pchDisplay = getenv( "DISPLAY" );
1690 if( !pchDisplay ) pchDisplay = "0";
1692 if ((home = getenv( "HOME" )) != NULL)
1694 int i = strlen( home ) + strlen( INIWinePrefix ) +
1695 strlen( INIFontMetrics ) + strlen( pchDisplay ) + 2;
1696 if( i > *buf_size )
1697 buffer = (char*) HeapReAlloc( SystemHeap, 0, buffer, *buf_size = i );
1698 strcpy( buffer, home );
1699 strcat( buffer, INIWinePrefix );
1700 strcat( buffer, INIFontMetrics );
1701 strcat( buffer, pchDisplay );
1702 } else buffer[0] = '\0';
1703 return buffer;
1707 /***********************************************************************
1708 * X Font Matching
1710 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1712 static INT XFONT_IsSubset(const fontInfo* match, const fontInfo* fi)
1714 INT m;
1716 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1718 /* Compare dfItalic, Underline, Strikeout, Weight, Charset */
1719 m = (BYTE*)&fi->df.dfPixWidth - (BYTE*)&fi->df.dfItalic;
1720 if( memcmp(&match->df.dfItalic, &fi->df.dfItalic, m )) return 0;
1722 if( (!((fi->fi_flags & FI_SCALABLE) + (match->fi_flags & FI_SCALABLE))
1723 && fi->lfd_height != match->lfd_height) ||
1724 (!((fi->fi_flags & FI_POLYWEIGHT) + (match->fi_flags & FI_POLYWEIGHT))
1725 && fi->df.dfWeight != match->df.dfWeight) ) return 0;
1727 m = (int)(match->fi_flags & (FI_POLYWEIGHT | FI_SCALABLE)) -
1728 (int)(fi->fi_flags & (FI_SCALABLE | FI_POLYWEIGHT));
1730 if( m == (FI_POLYWEIGHT - FI_SCALABLE) ||
1731 m == (FI_SCALABLE - FI_POLYWEIGHT) ) return 0; /* keep both */
1732 else if( m >= 0 ) return 1; /* 'match' is better */
1734 return -1; /* 'fi' is better */
1737 /***********************************************************************
1738 * XFONT_CheckFIList
1740 * REMOVE_SUBSETS - attach new fi and purge subsets
1741 * UNMARK_SUBSETS - remove subset flags from all fi entries
1743 static void XFONT_CheckFIList( fontResource* fr, fontInfo* fi, int action)
1745 int i = 0;
1746 fontInfo* pfi, *prev;
1748 for( prev = NULL, pfi = fr->fi; pfi; )
1750 if( action == REMOVE_SUBSETS )
1752 if( pfi->fi_flags & FI_SUBSET )
1754 fontInfo* subset = pfi;
1756 i++;
1757 fr->fi_count--;
1758 if( prev ) prev->next = pfi = pfi->next;
1759 else fr->fi = pfi = pfi->next;
1760 HeapFree( SystemHeap, 0, subset );
1761 continue;
1764 else pfi->fi_flags &= ~FI_SUBSET;
1766 prev = pfi;
1767 pfi = pfi->next;
1770 if( action == REMOVE_SUBSETS ) /* also add the superset */
1772 if( fi->fi_flags & FI_SCALABLE )
1774 fi->next = fr->fi;
1775 fr->fi = fi;
1777 else if( prev ) prev->next = fi; else fr->fi = fi;
1778 fr->fi_count++;
1781 if( i ) TRACE("\t purged %i subsets [%i]\n", i , fr->fi_count);
1784 /***********************************************************************
1785 * XFONT_FindFIList
1787 static fontResource* XFONT_FindFIList( fontResource* pfr, const char* pTypeFace )
1789 while( pfr )
1791 if( !strcasecmp( pfr->lfFaceName, pTypeFace ) ) break;
1792 pfr = pfr->next;
1794 /* Give the app back the font name it asked for. Encarta checks this. */
1795 if (pfr) strcpy(pfr->lfFaceName,pTypeFace);
1796 return pfr;
1799 /***********************************************************************
1800 * XFONT_FixupPointSize
1802 static void XFONT_FixupPointSize(fontInfo* fi)
1804 #define df (fi->df)
1805 df.dfHorizRes = df.dfVertRes = fi->lfd_resolution;
1806 df.dfPoints = (INT16)
1807 (((INT)(df.dfPixHeight - df.dfInternalLeading) * 72 + (df.dfVertRes >> 1)) /
1808 df.dfVertRes );
1809 #undef df
1812 /***********************************************************************
1813 * XFONT_BuildMetrics
1815 * Build font metrics from X font
1817 static int XFONT_BuildMetrics(char** x_pattern, int res, unsigned x_checksum, int x_count)
1819 int i;
1820 fontInfo* fi = NULL;
1821 int n_ff = 0;
1823 MESSAGE("Building font metrics. This may take some time...\n");
1824 for( i = 0; i < x_count; i++ )
1826 char* typeface;
1827 LFD* lfd;
1828 fontResource* fr, *pfr;
1829 int j;
1830 char buffer[MAX_LFD_LENGTH];
1831 char* lpstr;
1832 XFontStruct* x_fs;
1833 fontInfo* pfi;
1835 typeface = HEAP_strdupA(SystemHeap, 0, x_pattern[i]);
1836 if (!typeface)
1837 break;
1839 lfd = LFD_Parse(typeface);
1840 if (!lfd)
1842 HeapFree(SystemHeap, 0, typeface);
1843 continue;
1846 /* find a family to insert into */
1848 for( pfr = NULL, fr = fontList; fr; fr = fr->next )
1850 if( XFONT_SameFoundryAndFamily(fr->resource, lfd))
1851 break;
1852 pfr = fr;
1855 if( !fi ) fi = (fontInfo*) HeapAlloc(SystemHeap, 0, sizeof(fontInfo));
1857 if( !LFD_InitFontInfo( fi, lfd, x_pattern[i]) )
1858 goto nextfont;
1860 if( !fr ) /* add new family */
1862 n_ff++;
1863 fr = (fontResource*) HeapAlloc(SystemHeap, 0, sizeof(fontResource));
1864 if (fr)
1866 memset(fr, 0, sizeof(fontResource));
1868 fr->resource = (LFD*) HeapAlloc(SystemHeap, 0, sizeof(LFD));
1869 memset(fr->resource, 0, sizeof(LFD));
1871 TRACE("family: -%s-%s-\n", lfd->foundry, lfd->family );
1872 fr->resource->foundry = HEAP_strdupA(SystemHeap, 0, lfd->foundry);
1873 fr->resource->family = HEAP_strdupA(SystemHeap, 0, lfd->family);
1874 fr->resource->weight = "";
1876 if( pfr ) pfr->next = fr;
1877 else fontList = fr;
1879 else
1880 WARN("Not enough memory for a new font family\n");
1883 /* check if we already have something better than "fi" */
1885 for( pfi = fr->fi, j = 0; pfi && j <= 0; pfi = pfi->next )
1886 if( (j = XFONT_IsSubset( pfi, fi )) < 0 )
1887 pfi->fi_flags |= FI_SUBSET; /* superseded by "fi" */
1888 if( j > 0 ) goto nextfont;
1890 /* add new font instance "fi" to the "fr" font resource */
1892 if( fi->fi_flags & FI_SCALABLE )
1894 LFD lfd1;
1895 char pxl_string[4], res_string[4];
1896 /* set scalable font height to get an basis for extrapolation */
1898 fi->lfd_height = DEF_SCALABLE_HEIGHT;
1899 fi->lfd_resolution = res;
1901 sprintf(pxl_string, "%d", fi->lfd_height);
1902 sprintf(res_string, "%d", fi->lfd_resolution);
1904 lfd1 = *lfd;
1905 lfd1.pixel_size = pxl_string;
1906 lfd1.point_size = "*";
1907 lfd1.resolution_x = res_string;
1908 lfd1.resolution_y = res_string;
1910 LFD_UnParse(buffer, sizeof buffer, &lfd1);
1912 lpstr = buffer;
1914 else lpstr = x_pattern[i];
1916 if( (x_fs = TSXLoadQueryFont(display, lpstr)) )
1918 XFONT_SetFontMetric( fi, fr, x_fs );
1919 TSXFreeFont( display, x_fs );
1921 XFONT_FixupPointSize(fi);
1923 TRACE("\t[% 2ipt] '%s'\n", fi->df.dfPoints, x_pattern[i] );
1925 XFONT_CheckFIList( fr, fi, REMOVE_SUBSETS );
1926 fi = NULL; /* preventing reuse */
1928 else
1930 ERR("failed to load %s\n", lpstr );
1932 XFONT_CheckFIList( fr, fi, UNMARK_SUBSETS );
1934 nextfont:
1935 HeapFree(SystemHeap, 0, lfd);
1936 HeapFree(SystemHeap, 0, typeface);
1938 if( fi ) HeapFree(SystemHeap, 0, fi);
1940 return n_ff;
1943 /***********************************************************************
1944 * XFONT_ReadCachedMetrics
1946 * INIT ONLY
1948 static BOOL XFONT_ReadCachedMetrics( int fd, int res, unsigned x_checksum, int x_count )
1950 if( fd >= 0 )
1952 unsigned u;
1953 int i, j;
1955 /* read checksums */
1956 read( fd, &u, sizeof(unsigned) );
1957 read( fd, &i, sizeof(int) );
1959 if( u == x_checksum && i == x_count )
1961 off_t length, offset = 3 * sizeof(int);
1963 /* read total size */
1964 read( fd, &i, sizeof(int) );
1965 length = lseek( fd, 0, SEEK_END );
1967 if( length == (i + offset) )
1969 lseek( fd, offset, SEEK_SET );
1970 fontList = (fontResource*)HeapAlloc( SystemHeap, 0, i);
1971 if( fontList )
1973 fontResource* pfr = fontList;
1974 fontInfo* pfi = NULL;
1976 TRACE("Reading cached font metrics:\n");
1978 read( fd, fontList, i); /* read all metrics at once */
1979 while( offset < length )
1981 offset += sizeof(fontResource) + sizeof(fontInfo);
1982 pfr->fi = pfi = (fontInfo*)(pfr + 1);
1983 j = 1;
1984 while( TRUE )
1986 if( offset > length ||
1987 (int)(pfi->next) != j++ ) goto fail;
1989 pfi->df.dfFace = pfr->lfFaceName;
1990 if( pfi->fi_flags & FI_SCALABLE )
1992 /* we can pretend we got this font for any resolution */
1993 pfi->lfd_resolution = res;
1994 XFONT_FixupPointSize(pfi);
1996 pfi->next = pfi + 1;
1998 if( j > pfr->fi_count ) break;
2000 pfi = pfi->next;
2001 offset += sizeof(fontInfo);
2003 pfi->next = NULL;
2004 if( pfr->next )
2006 pfr->next = (fontResource*)(pfi + 1);
2007 pfr = pfr->next;
2009 else break;
2011 if( pfr->next == NULL &&
2012 *(int*)(pfi + 1) == X_FMC_MAGIC )
2014 /* read LFD stubs */
2015 char* lpch = (char*)((int*)(pfi + 1) + 1);
2016 offset += sizeof(int);
2017 for( pfr = fontList; pfr; pfr = pfr->next )
2019 size_t len = strlen(lpch) + 1;
2020 TRACE("\t%s, %i instances\n", lpch, pfr->fi_count );
2021 pfr->resource = LFD_Parse(lpch);
2022 lpch += len;
2023 offset += len;
2024 if (offset > length)
2025 goto fail;
2027 close( fd );
2028 return TRUE;
2033 fail:
2034 if( fontList ) HeapFree( SystemHeap, 0, fontList );
2035 fontList = NULL;
2036 close( fd );
2038 return FALSE;
2041 /***********************************************************************
2042 * XFONT_WriteCachedMetrics
2044 * INIT ONLY
2046 static BOOL XFONT_WriteCachedMetrics( int fd, unsigned x_checksum, int x_count, int n_ff )
2048 fontResource* pfr;
2049 fontInfo* pfi;
2051 if( fd >= 0 )
2053 int i, j, k;
2054 char buffer[MAX_LFD_LENGTH];
2056 /* font metrics file:
2058 * +0000 x_checksum
2059 * +0004 x_count
2060 * +0008 total size to load
2061 * +000C prepackaged font metrics
2062 * ...
2063 * +...x X_FMC_MAGIC
2064 * +...x + 4 LFD stubs
2067 write( fd, &x_checksum, sizeof(unsigned) );
2068 write( fd, &x_count, sizeof(int) );
2070 for( j = i = 0, pfr = fontList; pfr; pfr = pfr->next )
2072 LFD_UnParse(buffer, sizeof buffer, pfr->resource);
2073 i += strlen( buffer) + 1;
2074 j += pfr->fi_count;
2076 i += n_ff * sizeof(fontResource) + j * sizeof(fontInfo) + sizeof(int);
2077 write( fd, &i, sizeof(int) );
2079 TRACE("Writing font cache:\n");
2081 for( pfr = fontList; pfr; pfr = pfr->next )
2083 fontInfo fi;
2085 TRACE("\t-%s-%s-, %i instances\n", pfr->resource->foundry, pfr->resource->family, pfr->fi_count );
2087 i = write( fd, pfr, sizeof(fontResource) );
2088 if( i == sizeof(fontResource) )
2090 for( k = 1, pfi = pfr->fi; pfi; pfi = pfi->next )
2092 fi = *pfi;
2094 fi.df.dfFace = NULL;
2095 fi.next = (fontInfo*)k; /* loader checks this */
2097 j = write( fd, &fi, sizeof(fi) );
2098 k++;
2100 if( j == sizeof(fontInfo) ) continue;
2102 break;
2104 if( i == sizeof(fontResource) && j == sizeof(fontInfo) )
2106 i = j = X_FMC_MAGIC;
2107 write( fd, &i, sizeof(int) );
2108 for( pfr = fontList; pfr && i == j; pfr = pfr->next )
2110 LFD_UnParse(buffer, sizeof buffer, pfr->resource);
2111 i = strlen( buffer ) + 1;
2112 j = write( fd, buffer, i );
2115 close( fd );
2116 return ( i == j );
2118 return FALSE;
2121 /***********************************************************************
2122 * XFONT_CheckIniSection
2124 * INIT ONLY
2126 * Examines wine.conf for old/invalid font entries and recommend changes to
2127 * the user.
2129 * Revision history
2130 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
2131 * Original implementation.
2133 static void XFONT_CheckIniCallback(char const *, char const *, void *);
2135 static char const *fontmsgprologue =
2136 "Wine warning:\n"
2137 " The following entries in the [fonts] section of the wine.conf file are\n"
2138 " obsolete or invalid:\n";
2140 static char const *fontmsgepilogue =
2141 " These entries should be eliminated or updated.\n"
2142 " See the documentation/fonts file for more information.\n";
2144 static int XFONT_CheckIniSection(void)
2146 int found = 0;
2148 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback,
2149 (void *)&found);
2150 if(found)
2151 MESSAGE(fontmsgepilogue);
2153 return 1;
2156 static void XFONT_CheckIniCallback(
2157 char const *key,
2158 char const *value,
2159 void *found)
2161 /* Ignore any keys that start with potential comment characters "'", '#',
2162 or ';'. */
2163 if(key[0] == '\'' || key[0] == '#' || key[0] == ';' || key[0] == '\0')
2164 return;
2166 /* Make sure this is a valid key */
2167 if((strncasecmp(key, INIAliasSection, 5) == 0) ||
2168 (strncasecmp(key, INIIgnoreSection, 6) == 0) ||
2169 (strcasecmp( key, INIDefault) == 0) ||
2170 (strcasecmp( key, INIDefaultFixed) == 0) ||
2171 (strcasecmp( key, INIGlobalMetrics) == 0) ||
2172 (strcasecmp( key, INIResolution) == 0) ||
2173 (strcasecmp( key, INIDefaultSerif) == 0) ||
2174 (strcasecmp( key, INIDefaultSansSerif) ==0) )
2176 /* Valid key; make sure the value doesn't contain a wildcard */
2177 if(strchr(value, '*')) {
2178 if(*(int *)found == 0) {
2179 MESSAGE(fontmsgprologue);
2180 ++*(int *)found;
2182 MESSAGE(" %s=%s [no wildcards allowed]\n", key, value);
2185 else {
2186 /* Not a valid key */
2187 if(*(int *)found == 0) {
2188 MESSAGE(fontmsgprologue);
2189 ++*(int *)found;
2192 MESSAGE(" %s=%s [obsolete]\n", key, value);
2195 return;
2198 /***********************************************************************
2199 * XFONT_GetPointResolution()
2201 * INIT ONLY
2203 * Here we initialize DefResolution which is used in the
2204 * XFONT_Match() penalty function. We also load the point
2205 * resolution value (higher values result in larger fonts).
2207 static int XFONT_GetPointResolution( DeviceCaps* pDevCaps )
2209 int i, j, point_resolution, num = 3;
2210 int allowed_xfont_resolutions[3] = { 72, 75, 100 };
2211 int best = 0, best_diff = 65536;
2213 point_resolution = PROFILE_GetWineIniInt( INIFontSection, INIResolution, 0 );
2214 if( !point_resolution )
2215 point_resolution = pDevCaps->logPixelsY;
2216 else
2217 pDevCaps->logPixelsX = pDevCaps->logPixelsY = point_resolution;
2220 /* FIXME We can only really guess at a best DefResolution
2221 * - this should be configurable
2223 for( i = best = 0; i < num; i++ )
2225 j = abs( point_resolution - allowed_xfont_resolutions[i] );
2226 if( j < best_diff )
2228 best = i;
2229 best_diff = j;
2232 DefResolution = allowed_xfont_resolutions[best];
2234 /* FIXME - do win95,nt40,... do this as well ? */
2235 if (TWEAK_WineLook == WIN98_LOOK)
2237 /* Lie about the screen size, so that eg MM_LOMETRIC becomes MM_logical_LOMETRIC */
2238 int denom;
2239 denom = pDevCaps->logPixelsX * 10;
2240 pDevCaps->horzSize = (pDevCaps->horzRes * 254 + (denom>>1)) / denom;
2241 denom = pDevCaps->logPixelsY * 10;
2242 pDevCaps->vertSize = (pDevCaps->vertRes * 254 + (denom>>1)) / denom;
2245 return point_resolution;
2249 /***********************************************************************
2250 * XFONT_Match
2252 * Compute the matching score between the logical font and the device font.
2254 * contributions from highest to lowest:
2255 * charset
2256 * fixed pitch
2257 * height
2258 * family flags (only when the facename is not present)
2259 * width
2260 * weight, italics, underlines, strikeouts
2262 * NOTE: you can experiment with different penalty weights to see what happens.
2263 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
2265 static UINT XFONT_Match( fontMatch* pfm )
2267 fontInfo* pfi = pfm->pfi; /* device font to match */
2268 LPLOGFONT16 plf = pfm->plf; /* wanted logical font */
2269 UINT penalty = 0;
2270 BOOL bR6 = pfm->flags & FO_MATCH_XYINDEP; /* from TextCaps */
2271 BOOL bScale = pfi->fi_flags & FI_SCALABLE;
2272 int d = 0, height;
2274 TRACE("\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi->df.dfPoints,
2275 pfi->df.dfPixHeight, pfi->df.dfAvgWidth,
2276 (pfi->df.dfWeight > FW_NORMAL) ? "Bold " : "Normal ",
2277 (pfi->df.dfItalic) ? "Italic" : "" );
2279 pfm->flags &= FO_MATCH_MASK;
2281 /* Charset */
2282 if( plf->lfCharSet == DEFAULT_CHARSET )
2284 if( (pfi->df.dfCharSet != ANSI_CHARSET) && (pfi->df.dfCharSet != DEFAULT_CHARSET) )
2285 penalty += 0x200;
2287 else if (plf->lfCharSet != pfi->df.dfCharSet) penalty += 0x200;
2289 /* Height */
2290 height = -1;
2292 if( plf->lfHeight > 0 )
2294 int h = pfi->df.dfPixHeight;
2295 d = h - plf->lfHeight;
2296 height = plf->lfHeight;
2298 else
2300 int h = pfi->df.dfPixHeight - pfi->df.dfInternalLeading;
2301 if (h)
2303 d = h + plf->lfHeight;
2304 height = (-plf->lfHeight * pfi->df.dfPixHeight) / h;
2306 else
2308 ERR("PixHeight == InternalLeading\n");
2309 penalty += 0x1000; /* dont want this */
2314 if( height == 0 )
2315 pfm->height = 1; /* Very small */
2316 else if( d )
2318 if( bScale )
2319 pfm->height = height;
2320 else if( (plf->lfQuality != PROOF_QUALITY) && bR6 )
2322 if( d > 0 ) /* do not shrink raster fonts */
2324 pfm->height = pfi->df.dfPixHeight;
2325 penalty += (pfi->df.dfPixHeight - height) * 0x4;
2327 else /* expand only in integer multiples */
2329 pfm->height = height - height%pfi->df.dfPixHeight;
2330 penalty += (height - pfm->height + 1) * height / pfi->df.dfPixHeight;
2333 else /* can't be scaled at all */
2335 if( plf->lfQuality != PROOF_QUALITY) pfm->flags |= FO_SYNTH_HEIGHT;
2336 pfm->height = pfi->df.dfPixHeight;
2337 penalty += (d > 0)? d * 0x8 : -d * 0x10;
2340 else
2341 pfm->height = pfi->df.dfPixHeight;
2343 /* Pitch and Family */
2344 if( pfm->flags & FO_MATCH_PAF ) {
2345 int family = plf->lfPitchAndFamily & FF_FAMILY;
2347 /* TMPF_FIXED_PITCH means exactly the opposite */
2348 if( plf->lfPitchAndFamily & FIXED_PITCH ) {
2349 if( pfi->df.dfPitchAndFamily & TMPF_FIXED_PITCH ) penalty += 0x100;
2350 } else /* Variable is the default */
2351 if( !(pfi->df.dfPitchAndFamily & TMPF_FIXED_PITCH) ) penalty += 0x2;
2353 if (family != FF_DONTCARE && family != (pfi->df.dfPitchAndFamily & FF_FAMILY) )
2354 penalty += 0x10;
2357 /* Width */
2358 if( plf->lfWidth )
2360 int h;
2361 if( bR6 || bScale ) h = 0;
2362 else
2364 /* FIXME: not complete */
2366 pfm->flags |= FO_SYNTH_WIDTH;
2367 h = abs(plf->lfWidth - (pfm->height * pfi->df.dfAvgWidth)/pfi->df.dfPixHeight);
2369 penalty += h * ( d ) ? 0x2 : 0x1 ;
2371 else if( !(pfi->fi_flags & FI_NORMAL) ) penalty++;
2373 /* Weight */
2374 if( plf->lfWeight != FW_DONTCARE )
2376 penalty += abs(plf->lfWeight - pfi->df.dfWeight) / 40;
2377 if( plf->lfWeight > pfi->df.dfWeight ) pfm->flags |= FO_SYNTH_BOLD;
2378 } else if( pfi->df.dfWeight >= FW_BOLD ) penalty++; /* choose normal by default */
2380 /* Italic */
2381 if( plf->lfItalic != pfi->df.dfItalic )
2383 penalty += 0x4;
2384 pfm->flags |= FO_SYNTH_ITALIC;
2386 /* Underline */
2387 if( plf->lfUnderline ) pfm->flags |= FO_SYNTH_UNDERLINE;
2389 /* Strikeout */
2390 if( plf->lfStrikeOut ) pfm->flags |= FO_SYNTH_STRIKEOUT;
2393 if( penalty && !bScale && pfi->lfd_resolution != DefResolution )
2394 penalty++;
2396 TRACE(" returning %i\n", penalty );
2398 return penalty;
2401 /***********************************************************************
2402 * XFONT_MatchFIList
2404 * Scan a particular font resource for the best match.
2406 static UINT XFONT_MatchFIList( fontMatch* pfm )
2408 BOOL skipRaster = (pfm->flags & FO_MATCH_NORASTER);
2409 UINT current_score, score = (UINT)(-1);
2410 fontMatch fm = *pfm;
2412 for( fm.pfi = pfm->pfr->fi; fm.pfi && score; fm.pfi = fm.pfi->next)
2414 if( skipRaster && !(fm.pfi->fi_flags & FI_SCALABLE) )
2415 continue;
2417 current_score = XFONT_Match( &fm );
2418 if( score > current_score )
2420 *pfm = fm;
2421 score = current_score;
2424 return score;
2427 /***********************************************************************
2428 * XFONT_MatchDeviceFont
2430 * Scan font resource tree.
2433 static void XFONT_MatchDeviceFont( fontResource* start, fontMatch* pfm)
2435 fontMatch fm = *pfm;
2436 UINT current_score, score = (UINT)(-1);
2437 fontResource** ppfr;
2439 TRACE("(%u) '%s' h=%i weight=%i %s\n",
2440 pfm->plf->lfCharSet, pfm->plf->lfFaceName, pfm->plf->lfHeight,
2441 pfm->plf->lfWeight, (pfm->plf->lfItalic) ? "Italic" : "" );
2443 pfm->pfi = NULL;
2444 if( fm.plf->lfFaceName[0] )
2446 fm.pfr = XFONT_FindFIList( start, fm.plf->lfFaceName);
2447 if( fm.pfr ) /* match family */
2449 TRACE("found facename '%s'\n", fm.pfr->lfFaceName );
2451 if( fm.pfr->fr_flags & FR_REMOVED )
2452 fm.pfr = 0;
2453 else
2455 XFONT_MatchFIList( &fm );
2456 *pfm = fm;
2457 if (pfm->pfi)
2458 return;
2463 /* match all available fonts */
2465 fm.flags |= FO_MATCH_PAF;
2466 for( ppfr = &fontList; *ppfr && score; ppfr = &(*ppfr)->next )
2468 if( (*ppfr)->fr_flags & FR_REMOVED )
2470 if( (*ppfr)->fo_count == 0 )
2471 XFONT_RemoveFontResource( ppfr );
2472 continue;
2475 fm.pfr = *ppfr;
2477 TRACE("%s\n", fm.pfr->lfFaceName );
2479 current_score = XFONT_MatchFIList( &fm );
2480 if( current_score < score )
2482 score = current_score;
2483 *pfm = fm;
2489 /***********************************************************************
2490 * X Font Cache
2492 static void XFONT_GrowFreeList(int start, int end)
2494 /* add all entries from 'start' up to and including 'end' */
2496 memset( fontCache + start, 0, (end - start + 1) * sizeof(fontObject) );
2498 fontCache[end].lru = fontLF;
2499 fontCache[end].count = -1;
2500 fontLF = start;
2501 while( start < end )
2503 fontCache[start].count = -1;
2504 fontCache[start].lru = start + 1;
2505 start++;
2509 static fontObject* XFONT_LookupCachedFont( const LPLOGFONT16 plf, UINT16* checksum )
2511 UINT16 cs = __lfCheckSum( plf );
2512 int i = fontMRU, prev = -1;
2514 *checksum = cs;
2515 while( i >= 0 )
2517 if( fontCache[i].lfchecksum == cs &&
2518 !(fontCache[i].fo_flags & FO_REMOVED) )
2520 /* FIXME: something more intelligent here ? */
2522 if( !memcmp( plf, &fontCache[i].lf,
2523 sizeof(LOGFONT16) - LF_FACESIZE ) &&
2524 !strcmp( plf->lfFaceName, fontCache[i].lf.lfFaceName) )
2526 /* remove temporarily from the lru list */
2527 if( prev >= 0 )
2528 fontCache[prev].lru = fontCache[i].lru;
2529 else
2530 fontMRU = (INT16)fontCache[i].lru;
2531 return (fontCache + i);
2534 prev = i;
2535 i = (INT16)fontCache[i].lru;
2537 return NULL;
2540 static fontObject* XFONT_GetCacheEntry(void)
2542 int i;
2544 if( fontLF == -1 )
2546 int prev_i, prev_j, j;
2548 TRACE("font cache is full\n");
2550 /* lookup the least recently used font */
2552 for( prev_i = prev_j = j = -1, i = fontMRU; i >= 0; i = (INT16)fontCache[i].lru )
2554 if( fontCache[i].count <= 0 &&
2555 !(fontCache[i].fo_flags & FO_SYSTEM) )
2557 prev_j = prev_i;
2558 j = i;
2560 prev_i = i;
2563 if( j >= 0 ) /* unload font */
2565 /* detach from the lru list */
2567 TRACE("\tfreeing entry %i\n", j );
2569 fontCache[j].fr->fo_count--;
2571 if( prev_j >= 0 )
2572 fontCache[prev_j].lru = fontCache[j].lru;
2573 else fontMRU = (INT16)fontCache[j].lru;
2575 /* FIXME: lpXForm, lpPixmap */
2576 if(fontCache[j].lpX11Trans)
2577 HeapFree( SystemHeap, 0, fontCache[j].lpX11Trans );
2579 TSXFreeFont( display, fontCache[j].fs );
2581 memset( fontCache + j, 0, sizeof(fontObject) );
2582 return (fontCache + j);
2584 else /* expand cache */
2586 fontObject* newCache;
2588 prev_i = fontCacheSize + FONTCACHE;
2590 TRACE("\tgrowing font cache from %i to %i\n", fontCacheSize, prev_i );
2592 if( (newCache = (fontObject*)HeapReAlloc(SystemHeap, 0,
2593 fontCache, prev_i)) )
2595 i = fontCacheSize;
2596 fontCacheSize = prev_i;
2597 fontCache = newCache;
2598 XFONT_GrowFreeList( i, fontCacheSize - 1);
2600 else return NULL;
2604 /* detach from the free list */
2606 i = fontLF;
2607 fontLF = (INT16)fontCache[i].lru;
2608 fontCache[i].count = 0;
2609 return (fontCache + i);
2612 static int XFONT_ReleaseCacheEntry(const fontObject* pfo)
2614 UINT u = (UINT)(pfo - fontCache);
2616 if( u < fontCacheSize ) return (--fontCache[u].count);
2617 return -1;
2620 /***********************************************************************
2621 * X11DRV_FONT_Init
2623 * Initialize font resource list and allocate font cache.
2625 BOOL X11DRV_FONT_Init( DeviceCaps* pDevCaps )
2627 char** x_pattern;
2628 unsigned x_checksum;
2629 int i,res, x_count, fd, buf_size;
2630 char *buffer;
2632 XFONT_CheckIniSection();
2634 res = XFONT_GetPointResolution( pDevCaps );
2636 x_pattern = TSXListFonts(display, "*", MAX_FONTS, &x_count );
2638 TRACE("Font Mapper: initializing %i fonts [logical dpi=%i, default dpi=%i]\n",
2639 x_count, res, DefResolution);
2640 if (x_count == MAX_FONTS)
2641 MESSAGE("There may be more fonts available - try increasing the value of MAX_FONTS\n");
2643 for( i = x_checksum = 0; i < x_count; i++ )
2645 int j;
2646 #if 0
2647 printf("%i\t: %s\n", i, x_pattern[i] );
2648 #endif
2650 j = strlen( x_pattern[i] );
2651 if( j ) x_checksum ^= __genericCheckSum( x_pattern[i], j );
2653 x_checksum |= X_PFONT_MAGIC;
2654 buf_size = 128;
2655 buffer = HeapAlloc( SystemHeap, 0, buf_size );
2657 /* deal with systemwide font metrics cache */
2659 if( PROFILE_GetWineIniString( INIFontSection, INIGlobalMetrics, "", buffer, buf_size ) )
2661 fd = open( buffer, O_RDONLY );
2662 XFONT_ReadCachedMetrics(fd, DefResolution, x_checksum, x_count);
2664 if (fontList == NULL)
2666 /* try per-user */
2667 buffer = XFONT_UserMetricsCache( buffer, &buf_size );
2668 if( buffer[0] )
2670 fd = open( buffer, O_RDONLY );
2671 XFONT_ReadCachedMetrics(fd, DefResolution, x_checksum, x_count);
2675 if( fontList == NULL ) /* build metrics from scratch */
2677 int n_ff = XFONT_BuildMetrics(x_pattern, DefResolution, x_checksum, x_count);
2678 if( buffer[0] ) /* update cached metrics */
2680 fd = open( buffer, O_CREAT | O_TRUNC | O_RDWR, 0644 ); /* -rw-r--r-- */
2681 if( XFONT_WriteCachedMetrics( fd, x_checksum, x_count, n_ff ) == FALSE )
2683 WARN("Unable to write to fontcache '%s'\n", buffer);
2684 if( fd >= 0) remove( buffer ); /* couldn't write entire file */
2689 TSXFreeFontNames(x_pattern);
2691 /* check if we're dealing with X11 R6 server */
2693 XFontStruct* x_fs;
2694 strcpy(buffer, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
2695 if( (x_fs = TSXLoadQueryFont(display, buffer)) )
2697 XTextCaps |= TC_SF_X_YINDEP;
2698 TSXFreeFont(display, x_fs);
2701 HeapFree(SystemHeap, 0, buffer);
2703 XFONT_WindowsNames();
2704 XFONT_LoadAliases();
2705 XFONT_LoadDefaults();
2706 XFONT_LoadIgnores();
2708 InitializeCriticalSection( &crtsc_fonts_X11 );
2709 MakeCriticalSectionGlobal( &crtsc_fonts_X11 );
2711 /* fontList initialization is over, allocate X font cache */
2713 fontCache = (fontObject*) HeapAlloc(SystemHeap, 0, fontCacheSize * sizeof(fontObject));
2714 XFONT_GrowFreeList(0, fontCacheSize - 1);
2716 TRACE("done!\n");
2718 /* update text caps parameter */
2720 pDevCaps->textCaps = XTextCaps;
2722 RAW_ASCENT = TSXInternAtom(display, "RAW_ASCENT", TRUE);
2723 RAW_DESCENT = TSXInternAtom(display, "RAW_DESCENT", TRUE);
2725 return TRUE;
2728 /**********************************************************************
2729 * XFONT_SetX11Trans
2731 static BOOL XFONT_SetX11Trans( fontObject *pfo )
2733 char *fontName;
2734 Atom nameAtom;
2735 LFD* lfd;
2737 TSXGetFontProperty( pfo->fs, XA_FONT, &nameAtom );
2738 fontName = TSXGetAtomName( display, nameAtom );
2739 lfd = LFD_Parse(fontName);
2740 if (!lfd)
2742 TSXFree(fontName);
2743 return FALSE;
2746 if (lfd->pixel_size[0] != '[') {
2747 HeapFree(SystemHeap, 0, lfd);
2748 TSXFree(fontName);
2749 return FALSE;
2752 #define PX pfo->lpX11Trans
2754 sscanf(lfd->pixel_size, "[%f%f%f%f]", &PX->a, &PX->b, &PX->c, &PX->d);
2755 TSXFree(fontName);
2756 HeapFree(SystemHeap, 0, lfd);
2758 TSXGetFontProperty( pfo->fs, RAW_ASCENT, &PX->RAW_ASCENT );
2759 TSXGetFontProperty( pfo->fs, RAW_DESCENT, &PX->RAW_DESCENT );
2761 PX->pixelsize = hypot(PX->a, PX->b);
2762 PX->ascent = PX->pixelsize / 1000.0 * PX->RAW_ASCENT;
2763 PX->descent = PX->pixelsize / 1000.0 * PX->RAW_DESCENT;
2765 TRACE("[%f %f %f %f] RA = %ld RD = %ld\n",
2766 PX->a, PX->b, PX->c, PX->d,
2767 PX->RAW_ASCENT, PX->RAW_DESCENT);
2769 #undef PX
2770 return TRUE;
2773 /***********************************************************************
2774 * X Device Font Objects
2776 static X_PHYSFONT XFONT_RealizeFont( const LPLOGFONT16 plf, LPCSTR* faceMatched)
2778 UINT16 checksum;
2779 INT index = 0;
2780 fontObject* pfo;
2782 pfo = XFONT_LookupCachedFont( plf, &checksum );
2783 if( !pfo )
2785 fontMatch fm;
2786 INT i;
2788 fm.pfr = NULL;
2789 fm.pfi = NULL;
2790 fm.height = 0;
2791 fm.flags = 0;
2792 fm.plf = plf;
2794 if( XTextCaps & TC_SF_X_YINDEP ) fm.flags = FO_MATCH_XYINDEP;
2796 /* allocate new font cache entry */
2798 if( (pfo = XFONT_GetCacheEntry()) )
2800 /* initialize entry and load font */
2801 char lpLFD[MAX_LFD_LENGTH];
2802 UINT uRelaxLevel = 0;
2804 if(abs(plf->lfHeight) > MAX_FONT_SIZE) {
2805 ERR(
2806 "plf->lfHeight = %d, Creating a 100 pixel font and rescaling metrics \n",
2807 plf->lfHeight);
2808 pfo->rescale = fabs(plf->lfHeight / 100.0);
2809 if(plf->lfHeight > 0) plf->lfHeight = 100;
2810 else plf->lfHeight = -100;
2811 } else
2812 pfo->rescale = 1.0;
2814 XFONT_MatchDeviceFont( fontList, &fm );
2815 pfo->fr = fm.pfr;
2816 pfo->fi = fm.pfi;
2817 pfo->fr->fo_count++;
2818 pfo->fo_flags = fm.flags & ~FO_MATCH_MASK;
2820 pfo->lf = *plf;
2821 pfo->lfchecksum = checksum;
2825 LFD_ComposeLFD( pfo, fm.height, lpLFD, uRelaxLevel++ );
2826 if( (pfo->fs = TSXLoadQueryFont( display, lpLFD )) ) break;
2827 } while( uRelaxLevel );
2830 if(pfo->lf.lfEscapement != 0) {
2831 pfo->lpX11Trans = HeapAlloc(SystemHeap, 0, sizeof(XFONTTRANS));
2832 if(!XFONT_SetX11Trans( pfo )) {
2833 HeapFree(SystemHeap, 0, pfo->lpX11Trans);
2834 pfo->lpX11Trans = NULL;
2837 XFONT_GetLeading( &pfo->fi->df, pfo->fs,
2838 &pfo->foInternalLeading, NULL, pfo->lpX11Trans );
2839 pfo->foAvgCharWidth = (INT16)XFONT_GetAvgCharWidth(&pfo->fi->df, pfo->fs, pfo->lpX11Trans );
2840 pfo->foMaxCharWidth = (INT16)XFONT_GetMaxCharWidth(pfo->fs, pfo->lpX11Trans);
2842 /* FIXME: If we've got a soft font or
2843 * there are FO_SYNTH_... flags for the
2844 * non PROOF_QUALITY request, the engine
2845 * should rasterize characters into mono
2846 * pixmaps and store them in the pfo->lpPixmap
2847 * array (pfo->fs should be updated as well).
2848 * array (pfo->fs should be updated as well).
2849 * X11DRV_ExtTextOut() must be heavily modified
2850 * to support pixmap blitting and FO_SYNTH_...
2851 * styles.
2854 pfo->lpPixmap = NULL;
2857 if( !pfo ) /* couldn't get a new entry, get one of the cached fonts */
2859 UINT current_score, score = (UINT)(-1);
2861 i = index = fontMRU;
2862 fm.flags |= FO_MATCH_PAF;
2865 pfo = fontCache + i;
2866 fm.pfr = pfo->fr; fm.pfi = pfo->fi;
2868 current_score = XFONT_Match( &fm );
2869 if( current_score < score ) index = i;
2871 i = pfo->lru;
2872 } while( i >= 0 );
2873 pfo = fontCache + index;
2874 goto END;
2878 /* attach at the head of the lru list */
2879 pfo->lru = fontMRU;
2880 index = fontMRU = (pfo - fontCache);
2882 END:
2883 pfo->count++;
2885 TRACE("physfont %i\n", index);
2886 *faceMatched = pfo->fi->df.dfFace;
2888 return (X_PHYSFONT)(X_PFONT_MAGIC | index);
2891 /***********************************************************************
2892 * XFONT_GetFontObject
2894 fontObject* XFONT_GetFontObject( X_PHYSFONT pFont )
2896 if( CHECK_PFONT(pFont) ) return __PFONT(pFont);
2897 return NULL;
2900 /***********************************************************************
2901 * XFONT_GetFontStruct
2903 XFontStruct* XFONT_GetFontStruct( X_PHYSFONT pFont )
2905 if( CHECK_PFONT(pFont) ) return __PFONT(pFont)->fs;
2906 return NULL;
2909 /***********************************************************************
2910 * XFONT_GetFontInfo
2912 LPIFONTINFO16 XFONT_GetFontInfo( X_PHYSFONT pFont )
2914 if( CHECK_PFONT(pFont) ) return &(__PFONT(pFont)->fi->df);
2915 return NULL;
2920 /* X11DRV Interface ****************************************************
2922 * Exposed via the dc->funcs dispatch table. *
2924 ***********************************************************************/
2925 /***********************************************************************
2926 * X11DRV_FONT_SelectObject
2928 HFONT X11DRV_FONT_SelectObject( DC* dc, HFONT hfont, FONTOBJ* font )
2930 HFONT hPrevFont = 0;
2931 LOGFONT16 lf;
2932 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
2934 EnterCriticalSection( &crtsc_fonts_X11 );
2936 if( CHECK_PFONT(physDev->font) )
2937 XFONT_ReleaseCacheEntry( __PFONT(physDev->font) );
2939 lf = font->logfont;
2941 /* Make sure we don't change the sign when converting to device coords */
2942 /* FIXME - check that the other drivers do this correctly */
2943 if (lf.lfWidth)
2945 int vpt = abs(dc->vportExtX);
2946 int wnd = abs(dc->wndExtX);
2947 lf.lfWidth = (abs(lf.lfWidth) * vpt + (wnd>>1))/wnd;
2948 if (lf.lfWidth == 0)
2949 lf.lfWidth = 1; /* Minimum width */
2951 if (lf.lfHeight)
2953 int vpt = abs(dc->vportExtY);
2954 int wnd = abs(dc->wndExtY);
2955 if (lf.lfHeight > 0)
2956 lf.lfHeight = (lf.lfHeight * vpt + (wnd>>1))/wnd;
2957 else
2958 lf.lfHeight = (lf.lfHeight * vpt - (wnd>>1))/wnd;
2960 if (lf.lfHeight == 0)
2961 lf.lfHeight = MIN_FONT_SIZE;
2963 else
2964 lf.lfHeight = -(DEF_POINT_SIZE * dc->w.devCaps->logPixelsY + (72>>1)) / 72;
2967 /* Fixup aliases before passing to RealizeFont */
2968 /* alias = Windows name in the alias table */
2969 LPCSTR alias = XFONT_UnAlias( lf.lfFaceName );
2970 LPCSTR faceMatched;
2972 TRACE("hfont=%04x\n", hfont); /* to connect with the trace from RealizeFont */
2973 physDev->font = XFONT_RealizeFont( &lf, &faceMatched );
2975 /* set face to the requested facename if it matched
2976 * so that GetTextFace can get the correct face name
2978 if (alias && !strcmp(faceMatched, lf.lfFaceName))
2979 strcpy( font->logfont.lfFaceName, alias );
2980 else
2981 strcpy( font->logfont.lfFaceName, faceMatched );
2984 hPrevFont = dc->w.hFont;
2985 dc->w.hFont = hfont;
2987 LeaveCriticalSection( &crtsc_fonts_X11 );
2989 return hPrevFont;
2993 /***********************************************************************
2995 * X11DRV_EnumDeviceFonts
2997 BOOL X11DRV_EnumDeviceFonts( DC* dc, LPLOGFONT16 plf,
2998 DEVICEFONTENUMPROC proc, LPARAM lp )
3000 ENUMLOGFONTEX16 lf;
3001 NEWTEXTMETRIC16 tm;
3002 fontResource* pfr = fontList;
3003 BOOL b, bRet = 0;
3005 if( plf->lfFaceName[0] )
3007 /* enum all entries in this resource */
3008 pfr = XFONT_FindFIList( pfr, plf->lfFaceName );
3009 if( pfr )
3011 fontInfo* pfi;
3012 for( pfi = pfr->fi; pfi; pfi = pfi->next )
3014 /* Note: XFONT_GetFontMetric() will have to
3015 release the crit section, font list will
3016 have to be retraversed on return */
3018 if( (b = (*proc)( &lf, &tm,
3019 XFONT_GetFontMetric( pfi, &lf, &tm ), lp )) )
3020 bRet = b;
3021 else break;
3025 else /* enum first entry in each resource */
3026 for( ; pfr ; pfr = pfr->next )
3028 if(pfr->fi)
3030 if( (b = (*proc)( &lf, &tm,
3031 XFONT_GetFontMetric( pfr->fi, &lf, &tm ), lp )) )
3032 bRet = b;
3033 else break;
3036 return bRet;
3040 /***********************************************************************
3041 * X11DRV_GetTextExtentPoint
3043 BOOL X11DRV_GetTextExtentPoint( DC *dc, LPCWSTR str, INT count,
3044 LPSIZE size )
3046 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
3047 fontObject* pfo = XFONT_GetFontObject( physDev->font );
3049 TRACE("%s %d\n", debugstr_wn(str,count), count);
3050 if( pfo ) {
3051 if( !pfo->lpX11Trans ) {
3052 int dir, ascent, descent, i;
3053 XCharStruct info;
3054 XChar2b *p = HeapAlloc( GetProcessHeap(), 0,
3055 count * sizeof(XChar2b) );
3056 for(i = 0; i < count; i++) {
3057 p[i].byte1 = str[i] >> 8;
3058 p[i].byte2 = str[i] & 0xff;
3060 TSXTextExtents16( pfo->fs, p, count, &dir, &ascent, &descent, &info );
3061 size->cx = abs((info.width + dc->w.breakRem + count *
3062 dc->w.charExtra) * dc->wndExtX / dc->vportExtX);
3063 size->cy = abs((pfo->fs->ascent + pfo->fs->descent) *
3064 dc->wndExtY / dc->vportExtY);
3065 HeapFree( GetProcessHeap(), 0, p );
3066 } else {
3067 INT i;
3068 float x = 0.0, y = 0.0;
3069 for(i = 0; i < count; i++) {
3070 x += pfo->fs->per_char ?
3071 pfo->fs->per_char[str[i] - pfo->fs->min_char_or_byte2].attributes :
3072 pfo->fs->min_bounds.attributes;
3074 y = pfo->lpX11Trans->RAW_ASCENT + pfo->lpX11Trans->RAW_DESCENT;
3075 TRACE("x = %f y = %f\n", x, y);
3076 x *= pfo->lpX11Trans->pixelsize / 1000.0;
3077 y *= pfo->lpX11Trans->pixelsize / 1000.0;
3078 size->cx = fabs((x + dc->w.breakRem + count * dc->w.charExtra) *
3079 dc->wndExtX / dc->vportExtX);
3080 size->cy = fabs(y * dc->wndExtY / dc->vportExtY);
3082 size->cx *= pfo->rescale;
3083 size->cy *= pfo->rescale;
3084 return TRUE;
3086 return FALSE;
3090 /***********************************************************************
3091 * X11DRV_GetTextMetrics
3093 BOOL X11DRV_GetTextMetrics(DC *dc, TEXTMETRICA *metrics)
3095 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
3097 if( CHECK_PFONT(physDev->font) )
3099 fontObject* pfo = __PFONT(physDev->font);
3100 XFONT_GetTextMetrics( pfo, metrics );
3102 return TRUE;
3104 return FALSE;
3108 /***********************************************************************
3109 * X11DRV_GetCharWidth
3111 BOOL X11DRV_GetCharWidth( DC *dc, UINT firstChar, UINT lastChar,
3112 LPINT buffer )
3114 X11DRV_PDEVICE *physDev = (X11DRV_PDEVICE *)dc->physDev;
3115 fontObject* pfo = XFONT_GetFontObject( physDev->font );
3117 if( pfo )
3119 int i;
3121 if (pfo->fs->per_char == NULL)
3122 for (i = firstChar; i <= lastChar; i++)
3123 if(pfo->lpX11Trans)
3124 *buffer++ = pfo->fs->min_bounds.attributes *
3125 pfo->lpX11Trans->pixelsize / 1000.0 * pfo->rescale;
3126 else
3127 *buffer++ = pfo->fs->min_bounds.width * pfo->rescale;
3128 else
3130 XCharStruct *cs, *def;
3131 static XCharStruct __null_char = { 0, 0, 0, 0, 0, 0 };
3133 CI_GET_CHAR_INFO(pfo->fs, pfo->fs->default_char, &__null_char,
3134 def);
3136 for (i = firstChar; i <= lastChar; i++)
3138 if (i >= pfo->fs->min_char_or_byte2 &&
3139 i <= pfo->fs->max_char_or_byte2)
3141 cs = &pfo->fs->per_char[(i - pfo->fs->min_char_or_byte2)];
3142 if (CI_NONEXISTCHAR(cs)) cs = def;
3143 } else cs = def;
3144 if(pfo->lpX11Trans)
3145 *buffer++ = MAX(cs->attributes, 0) *
3146 pfo->lpX11Trans->pixelsize / 1000.0 * pfo->rescale;
3147 else
3148 *buffer++ = MAX(cs->width, 0 ) * pfo->rescale;
3152 return TRUE;
3154 return FALSE;
3157 #endif /* !defined(X_DISPLAY_MISSING) */
3159 /***********************************************************************
3161 * Font Resource API *
3163 ***********************************************************************/
3164 /***********************************************************************
3165 * AddFontResource16 (GDI.119)
3167 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
3169 * FIXME: Load header and find the best-matching font in the fontList;
3170 * fixup dfPoints if all metrics are identical, otherwise create
3171 * new fontAlias. When soft font support is ready this will
3172 * simply create a new fontResource ('filename' will go into
3173 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
3174 * flag set.
3176 INT16 WINAPI AddFontResource16( LPCSTR filename )
3178 return AddFontResourceA( filename );
3182 /***********************************************************************
3183 * AddFontResource32A (GDI32.2)
3185 INT WINAPI AddFontResourceA( LPCSTR str )
3187 FIXME("(%s): stub\n", debugres_a(str));
3188 return 1;
3192 /***********************************************************************
3193 * AddFontResource32W (GDI32.4)
3195 INT WINAPI AddFontResourceW( LPCWSTR str )
3197 FIXME("(%s): stub\n", debugres_w(str) );
3198 return 1;
3201 /***********************************************************************
3202 * RemoveFontResource16 (GDI.136)
3204 BOOL16 WINAPI RemoveFontResource16( SEGPTR str )
3206 FIXME("(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str)));
3207 return TRUE;
3211 /***********************************************************************
3212 * RemoveFontResource32A (GDI32.284)
3214 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3216 /* This is how it should look like */
3218 fontResource** ppfr;
3219 BOOL32 retVal = FALSE;
3221 EnterCriticalSection( &crtsc_fonts_X11 );
3222 for( ppfr = &fontList; *ppfr; ppfr = &(*ppfr)->next )
3223 if( !strcasecmp( (*ppfr)->lfFaceName, str ) )
3225 if(((*ppfr)->fr_flags & (FR_SOFTFONT | FR_SOFTRESOURCE)) &&
3226 (*ppfr)->hOwnerProcess == GetCurrentProcess() )
3228 if( (*ppfr)->fo_count )
3229 (*ppfr)->fr_flags |= FR_REMOVED;
3230 else
3231 XFONT_RemoveFontResource( ppfr );
3233 retVal = TRUE;
3235 LeaveCriticalSection( &crtsc_fonts_X11 );
3236 return retVal;
3238 FIXME("(%s): stub\n", debugres_a(str));
3239 return TRUE;
3243 /***********************************************************************
3244 * RemoveFontResource32W (GDI32.286)
3246 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3248 FIXME("(%s): stub\n", debugres_w(str) );
3249 return TRUE;