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).
12 #ifndef X_DISPLAY_MISSING
13 #include <X11/Xatom.h>
16 #endif /* !defined(X_DISPLAY_MISSING) */
24 #include <sys/types.h>
35 #ifndef X_DISPLAY_MISSING
37 #define X_PFONT_MAGIC (0xFADE0000)
38 #define X_FMC_MAGIC (0x0000CAFE)
40 #define MAX_FONT_FAMILIES 128
41 #define MAX_LFD_LENGTH 256
43 #define MAX_FONT_SIZE 1000 /* Max size in pixels */
45 #define REMOVE_SUBSETS 1
46 #define UNMARK_SUBSETS 0
48 #define DEF_SCALABLE_HEIGHT 24
49 #define DEF_SCALABLE_DP 240
51 #define FF_FAMILY (FF_MODERN | FF_SWISS | FF_ROMAN | FF_DECORATIVE | FF_SCRIPT)
53 typedef struct __fontAlias
57 struct __fontAlias
* next
;
66 /* Font alias table - these 2 aliases are always present */
67 /* CHANGING THE FIRST TWO WILL BREAK XFONT_BuildDefaultAliases! */
69 static fontAlias __aliasTable
[2] = {
70 { NULL
, "Helv", &__aliasTable
[1] },
71 { NULL
, "Tms Rmn", NULL
}
74 static fontAlias
*aliasTable
= __aliasTable
;
76 /* Optional built-in aliases, they are installed only when X
77 * cannot supply us with original MS fonts */
78 /* CHANGING THE FIRST TWO WILL BREAK XFONT_BuildDefaultAliases! */
80 static int faTemplateNum
= 4;
81 static aliasTemplate faTemplate
[4] = {
82 { NULL
, "MS Sans Serif" },
84 { "-adobe-times-", "Times New Roman" },
85 { "-adobe-helvetica-", "Arial" }
88 UINT16 XTextCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
|
89 TC_CP_STROKE
| TC_CR_ANY
|
90 TC_SA_DOUBLE
| TC_SA_INTEGER
| TC_SA_CONTIN
|
91 TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
93 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
95 static const char* INIWinePrefix
= "/.wine";
96 static const char* INIFontMetrics
= "/.cachedmetrics.";
97 static const char* INIFontSection
= "fonts";
98 static const char* INIAliasSection
= "Alias";
99 static const char* INIIgnoreSection
= "Ignore";
100 static const char* INIDefault
= "Default";
101 static const char* INIDefaultFixed
= "DefaultFixed";
102 static const char* INIResolution
= "Resolution";
103 static const char* INIGlobalMetrics
= "FontMetrics";
104 static const char* INIDefaultSerif
= "DefaultSerif";
105 static const char* INIDefaultSansSerif
= "DefaultSansSerif";
107 static const char* LFDSeparator
= "*-";
109 /* suffix tables, must be less than 254 entries long */
111 static LPSTR suffx_iso
[] = { "-1", "-2", "-3", "-4", "-5", "-6", "-7", "-8",
112 "-9", "-10", "-11", "-12", "-13", "-14", "-15", NULL
};
113 static LPSTR suffx_iso646
[] = { "-irv", NULL
};
114 static LPSTR suffx_microsoft
[] = { "-cp1252", "-cp1251", "-cp1250", "-cp1253", "-cp1254", "-cp1255",
115 "-cp1256", "-cp1257", "-fontspecific", "-symbol", NULL
};
116 static LPSTR suffx_viscii
[] = { "-1", NULL
};
117 static LPSTR suffx_ansi
[] = { "-0", NULL
};
118 static LPSTR suffx_koi8
[] = { "-ru", "-r", NULL
};
119 static LPSTR suffx_null
[] = { NULL
};
121 /* charset mapping tables, have to have the same number of entries as corresponding suffix tables */
123 static BYTE chset_iso8859
[] = { ANSI_CHARSET
, EE_CHARSET
, ISO3_CHARSET
, ISO4_CHARSET
, RUSSIAN_CHARSET
,
124 ARABIC_CHARSET
, GREEK_CHARSET
, HEBREW_CHARSET
, TURKISH_CHARSET
, BALTIC_CHARSET
,
125 THAI_CHARSET
, SYMBOL_CHARSET
, SYMBOL_CHARSET
, SYMBOL_CHARSET
, ANSI_CHARSET
,
127 static BYTE chset_iso646
[] = { ANSI_CHARSET
, SYMBOL_CHARSET
};
128 static BYTE chset_microsoft
[] = { ANSI_CHARSET
, RUSSIAN_CHARSET
, EE_CHARSET
, GREEK_CHARSET
, TURKISH_CHARSET
,
129 HEBREW_CHARSET
, ARABIC_CHARSET
, BALTIC_CHARSET
, SYMBOL_CHARSET
, SYMBOL_CHARSET
,
131 static BYTE chset_ansi
[] = { ANSI_CHARSET
, ANSI_CHARSET
};
132 static BYTE chset_koi8
[] = { KOI8_CHARSET
, KOI8_CHARSET
, KOI8_CHARSET
};
133 static BYTE chset_tcvn
[] = { TCVN_CHARSET
, TCVN_CHARSET
};
134 static BYTE chset_tis620
[] = { THAI_CHARSET
, THAI_CHARSET
};
135 static BYTE chset_fontspecific
[] = { SYMBOL_CHARSET
};
136 static BYTE chset_viscii
[] = { VISCII_CHARSET
, VISCII_CHARSET
};
144 } fontEncodingTemplate
;
146 /* Note: we can attach additional encoding mappings to the end
147 * of this table at runtime.
150 static fontEncodingTemplate __fETTable
[10] = {
151 { "iso8859", &suffx_iso
, &chset_iso8859
, &__fETTable
[1] },
152 { "iso646.1991", &suffx_iso646
, &chset_iso646
, &__fETTable
[2] },
153 { "microsoft", &suffx_microsoft
, &chset_microsoft
, &__fETTable
[3] },
154 { "ansi", &suffx_ansi
, &chset_ansi
, &__fETTable
[4] },
155 { "ascii", &suffx_ansi
, &chset_ansi
, &__fETTable
[5] },
156 { "fontspecific", &suffx_null
, &chset_fontspecific
, &__fETTable
[6] },
157 { "koi8", &suffx_koi8
, &chset_koi8
, &__fETTable
[7] },
158 { "tcvn", &suffx_ansi
, &chset_tcvn
, &__fETTable
[8] },
159 { "tis620.2533", &suffx_ansi
, &chset_tis620
, &__fETTable
[9] },
160 { "viscii1.1", &suffx_viscii
, &chset_viscii
, NULL
}
162 static fontEncodingTemplate
* fETTable
= __fETTable
;
164 static unsigned DefResolution
= 0;
166 static CRITICAL_SECTION crtsc_fonts_X11
;
168 static fontResource
* fontList
= NULL
;
169 static fontObject
* fontCache
= NULL
; /* array */
170 static int fontCacheSize
= FONTCACHE
;
171 static int fontLF
= -1, fontMRU
= -1; /* last free, most recently used */
173 #define __PFONT(pFont) ( fontCache + ((UINT)(pFont) & 0x0000FFFF) )
174 #define CHECK_PFONT(pFont) ( (((UINT)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
175 (((UINT)(pFont) & 0x0000FFFF) < fontCacheSize) )
177 static INT
XFONT_IsSubset(fontInfo
*, fontInfo
*);
178 static void XFONT_CheckFIList(fontResource
*, fontInfo
*, int subset_action
);
179 static void XFONT_GrowFreeList(int start
, int end
);
180 static void XFONT_RemoveFontResource(fontResource
** ppfr
);
183 static Atom RAW_ASCENT
;
184 static Atom RAW_DESCENT
;
186 /***********************************************************************
187 * Helper macros from X distribution
190 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
191 (((cs)->rbearing|(cs)->lbearing| \
192 (cs)->ascent|(cs)->descent) == 0))
194 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
197 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
198 if (fs->per_char == NULL) { \
199 cs = &fs->min_bounds; \
201 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
202 if (CI_NONEXISTCHAR(cs)) cs = def; \
207 #define CI_GET_DEFAULT_INFO(fs,cs) \
208 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
210 /***********************************************************************
213 static UINT16
__lfCheckSum( LPLOGFONT16 plf
)
215 CHAR font
[LF_FACESIZE
];
219 #define ptr ((UINT16*)plf)
220 for( i
= 0; i
< 9; i
++ ) checksum
^= *ptr
++;
223 #define ptr ((CHAR*)plf)
224 do { font
[i
++] = tolower(*ptr
++); } while (( i
< LF_FACESIZE
) && (*ptr
) && (*ptr
!=' '));
225 for( ptr
= font
, i
>>= 1; i
> 0; i
-- )
227 #define ptr ((UINT16*)plf)
233 static UINT16
__genericCheckSum( const void *ptr
, int size
)
235 unsigned int checksum
= 0;
236 const char *p
= (const char *)ptr
;
238 checksum
^= (checksum
<< 3) + (checksum
>> 29) + *p
++;
240 return checksum
& 0xffff;
243 /*************************************************************************
244 * LFD parse/compose routines
246 static char* LFD_Advance(LPSTR lpFont
, UINT16 uParmsNo
)
251 for( ; j
< uParmsNo
&& *lpch
; lpch
++ ) if( *lpch
== LFDSeparator
[1] ) j
++;
255 static void LFD_GetWeight( fontInfo
* fi
, LPSTR lpStr
, int j
)
257 if( j
== 1 && *lpStr
== '0' )
258 fi
->fi_flags
|= FI_POLYWEIGHT
;
261 if( !strncasecmp( "bold", lpStr
, 4) )
262 fi
->df
.dfWeight
= FW_BOLD
;
263 else if( !strncasecmp( "demi", lpStr
, 4) )
265 fi
->fi_flags
|= FI_FW_DEMI
;
266 fi
->df
.dfWeight
= FW_DEMIBOLD
;
268 else if( !strncasecmp( "book", lpStr
, 4) )
270 fi
->fi_flags
|= FI_FW_BOOK
;
271 fi
->df
.dfWeight
= FW_REGULAR
;
276 if( !strncasecmp( "light", lpStr
, 5) )
277 fi
->df
.dfWeight
= FW_LIGHT
;
278 else if( !strncasecmp( "black", lpStr
, 5) )
279 fi
->df
.dfWeight
= FW_BLACK
;
281 else if( j
== 6 && !strncasecmp( "medium", lpStr
, 6) )
282 fi
->df
.dfWeight
= FW_REGULAR
;
283 else if( j
== 8 && !strncasecmp( "demibold", lpStr
, 8) )
284 fi
->df
.dfWeight
= FW_DEMIBOLD
;
286 fi
->df
.dfWeight
= FW_DONTCARE
; /* FIXME: try to get something
287 * from the weight property */
290 static int LFD_GetSlant( fontInfo
* fi
, LPSTR lpStr
, int l
)
294 switch( tolower( *lpStr
) )
296 case '0': fi
->fi_flags
|= FI_POLYSLANT
; /* haven't seen this one yet */
298 case 'r': fi
->df
.dfItalic
= 0;
301 fi
->fi_flags
|= FI_OBLIQUE
;
302 case 'i': fi
->df
.dfItalic
= 1;
310 /*************************************************************************
315 * Fill in some fields in the fontInfo struct.
317 static int LFD_InitFontInfo( fontInfo
* fi
, LPSTR lpstr
)
320 int i
, j
, dec_style_check
, scalability
;
322 fontEncodingTemplate
* boba
;
324 memset(fi
, 0, sizeof(fontInfo
) );
327 lpch
= LFD_Advance( lpstr
, 1);
328 if( !*lpch
) return FALSE
;
329 j
= lpch
- lpstr
- 1;
330 LFD_GetWeight( fi
, lpstr
, j
);
333 lpch
= LFD_Advance( lpstr
= lpch
, 1);
334 if( !*lpch
) return FALSE
;
335 j
= lpch
- lpstr
- 1;
336 dec_style_check
= LFD_GetSlant( fi
, lpstr
, j
);
339 lpch
= LFD_Advance( lpstr
= lpch
, 1);
340 if( !*lpch
) return FALSE
;
341 if( strncasecmp( "normal", lpstr
, 6) ) /* XXX 'narrow', 'condensed', etc... */
342 dec_style_check
= TRUE
;
344 fi
->fi_flags
|= FI_NORMAL
;
347 lpch
= LFD_Advance( lpstr
= lpch
, 1);
348 if( !*lpch
) return FALSE
;
349 j
= lpch
- lpstr
- 1;
350 if( j
> 3 ) /* find out is there "sans" or "script" */
355 if( strstr(lpstr
, "sans") )
357 fi
->df
.dfPitchAndFamily
|= FF_SWISS
;
360 if( strstr(lpstr
, "script") )
362 fi
->df
.dfPitchAndFamily
|= FF_SCRIPT
;
365 if( !j
&& dec_style_check
)
366 fi
->df
.dfPitchAndFamily
|= FF_DECORATIVE
;
367 *(lpch
- 1) = LFDSeparator
[1];
370 /* pixel height, decipoint height, and res_x */
372 for( i
= scalability
= 0; i
< 3; i
++ )
374 lpch
= LFD_Advance( lpstr
= lpch
, 1);
375 if( !*lpch
) return FALSE
;
376 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
379 if( !(tmp
[i
] = atoi(lpstr
)) ) scalability
++;
380 *(lpch
- 1) = LFDSeparator
[1];
382 if( scalability
== 3 ) /* Type1 */
384 fi
->fi_flags
|= FI_SCALABLE
;
385 fi
->lfd_height
= DEF_SCALABLE_HEIGHT
; fi
->lfd_decipoints
= DEF_SCALABLE_DP
;
386 fi
->lfd_resolution
= DefResolution
;
388 else if( scalability
== 0 ) /* Bitmap */
390 fi
->lfd_height
= tmp
[0]; fi
->lfd_decipoints
= tmp
[1];
391 fi
->lfd_resolution
= tmp
[2];
393 else return FALSE
; /* #$%^!!! X11R6 mutant garbage */
395 /* res_y - skip, spacing - */
396 lpstr
= LFD_Advance( lpch
, 1);
399 case '\0': return FALSE
;
401 case 'p': fi
->fi_flags
|= FI_VARIABLEPITCH
;
403 case 'c': fi
->df
.dfPitchAndFamily
|= FF_MODERN
;
404 fi
->fi_flags
|= FI_FIXEDEX
;
406 case 'm': fi
->fi_flags
|= FI_FIXEDPITCH
;
409 fi
->df
.dfPitchAndFamily
|= DEFAULT_PITCH
| FF_DONTCARE
;
411 lpstr
= LFD_Advance(lpstr
, 1);
412 if( !*lpstr
) return FALSE
;
414 /* average width - */
415 lpch
= LFD_Advance( lpstr
, 1);
416 if( !*lpch
) return FALSE
;
417 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
419 if( !(fi
->lfd_width
= atoi(lpstr
)) && !scalability
) return FALSE
;
420 *(lpch
- 1) = LFDSeparator
[1];
422 /* charset registry, charset encoding - */
423 if( strstr(lpch
, "jisx") ||
424 strstr(lpch
, "ksc") ||
425 strstr(lpch
, "gb2312") ||
426 strstr(lpch
, "big5") ||
427 strstr(lpch
, "unicode") ) return FALSE
; /* 2-byte stuff */
429 fi
->df
.dfCharSet
= ANSI_CHARSET
;
431 for( i
= 0, boba
= fETTable
; boba
; boba
= boba
->next
, i
++ )
433 tmp
[0] = strlen( boba
->prefix
);
434 if( !strncasecmp( lpch
, boba
->prefix
, tmp
[0] ) )
436 if( lpch
[tmp
[0]] == '-' )
438 lpstr
= lpch
+ tmp
[0];
439 for( j
= 0; (*(boba
->psuffix
))[j
]; j
++ )
441 tmp
[1] = strlen( (*(boba
->psuffix
))[j
] );
442 if( !strncasecmp( lpstr
, (*(boba
->psuffix
))[j
], tmp
[1] ) )
444 fi
->df
.dfCharSet
= (*(boba
->pcharset
))[j
];
448 /* Note : LFD_ComposeLFD will produce 'prefix-*' encoding *
449 * if (*(boba->psuffix))[j] is NULL here */
453 for( j
= 0; (*(boba
->psuffix
))[j
] ; j
++ );
454 fi
->df
.dfCharSet
= (*(boba
->pcharset
))[j
];
455 j
= lpch
[tmp
[0]] ? 254 : 255;
460 if( !boba
) return FALSE
;
462 /* i - index into fETTable
463 * j - index into suffix array for fETTable[i]
465 * 254 - weird suffix (i.e. no '-' right after prefix )
466 * 255 - no suffix at all.
469 fi
->fi_encoding
= 256 * (UINT16
)i
+ (UINT16
)j
;
475 /*************************************************************************
478 * Note: uRelax is a treatment not a cure. Font mapping algorithm
479 * should be bulletproof enough to allow us to avoid hacks like
480 * if( uRelax == 200 ) even despite LFD being so braindead.
482 static BOOL
LFD_ComposeLFD( fontObject
* fo
,
483 INT height
, LPSTR lpLFD
, UINT uRelax
)
485 fontEncodingTemplate
* boba
;
486 int i
, h
, w
, ch
, point
= 0;
489 char h_string
[64], point_string
[64];
491 *(lpLFD
+MAX_LFD_LENGTH
-1)=0;
492 lstrcpyA( lpLFD
, fo
->fr
->resource
);
495 switch( fo
->fi
->df
.dfWeight
)
498 strcat( lpLFD
, "bold" ); break;
500 if( fo
->fi
->fi_flags
& FI_FW_BOOK
)
501 strcat( lpLFD
, "book" );
503 strcat( lpLFD
, "medium" );
506 strcat( lpLFD
, "demi" );
507 if( !( fo
->fi
->fi_flags
& FI_FW_DEMI
) )
508 strcat ( lpLFD
, "bold" );
511 strcat( lpLFD
, "black" ); break;
513 strcat( lpLFD
, "light" ); break;
515 strcat( lpLFD
, "*" );
519 if( fo
->fi
->df
.dfItalic
)
520 if( fo
->fi
->fi_flags
& FI_OBLIQUE
)
521 strcat( lpLFD
, "-o" );
523 strcat( lpLFD
, "-i" );
525 strcat( lpLFD
, (uRelax
< 2) ? "-r" : "-*" );
527 /* add width style and skip serifs */
528 if( fo
->fi
->fi_flags
& FI_NORMAL
)
529 strcat( lpLFD
, "-normal-*-");
531 strcat( lpLFD
, "-*-*-" );
533 /* add pixelheight, pointheight, and resolution
535 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
537 if( fo
->fo_flags
& FO_SYNTH_HEIGHT
) h
= fo
->fi
->lfd_height
;
538 else h
= (fo
->fi
->lfd_height
* height
) / fo
->fi
->df
.dfPixHeight
;
540 if( XTextCaps
& TC_SF_X_YINDEP
)
542 if( fo
->lf
.lfWidth
&& !(fo
->fo_flags
& FO_SYNTH_WIDTH
) )
543 point
= (fo
->fi
->lfd_decipoints
* fo
->lf
.lfWidth
) / fo
->fi
->df
.dfAvgWidth
;
545 if( fo
->fi
->fi_flags
& FI_SCALABLE
) /* adjust h/w ratio */
546 point
= h
* 72 * 10 / fo
->fi
->lfd_resolution
;
549 /* handle rotated fonts */
550 if (fo
->lf
.lfEscapement
) {
551 /* escapement is in tenths of degrees, theta is in radians */
552 double theta
= M_PI
*fo
->lf
.lfEscapement
/1800.;
553 double h_matrix
[4] = {h
*cos(theta
), h
*sin(theta
), -h
*sin(theta
), h
*cos(theta
)};
554 double point_matrix
[4] = {point
*cos(theta
), point
*sin(theta
), -point
*sin(theta
), point
*cos(theta
)};
556 sprintf(h_string
, "[%+f%+f%+f%+f]", h_matrix
[0], h_matrix
[1], h_matrix
[2], h_matrix
[3]);
557 sprintf(point_string
, "[%+f%+f%+f%+f]", point_matrix
[0], point_matrix
[1], point_matrix
[2], point_matrix
[3]);
558 while ((s
= strchr(h_string
, '-'))) *s
='~';
559 while ((s
= strchr(point_string
, '-'))) *s
='~';
561 sprintf(h_string
, "%d", h
);
562 sprintf(point_string
, "%d", point
);
566 /* spacing and width */
568 if( fo
->fi
->fi_flags
& FI_FIXEDPITCH
)
569 w
= ( fo
->fi
->fi_flags
& FI_FIXEDEX
) ? 'c' : 'm';
571 w
= ( fo
->fi
->fi_flags
& FI_VARIABLEPITCH
) ? 'p' : LFDSeparator
[0];
575 i
= fo
->fi
->fi_encoding
>> 8;
576 for( boba
= fETTable
; i
; i
--, boba
= boba
->next
);
578 strcpy( lpEncoding
, boba
->prefix
);
580 i
= fo
->fi
->fi_encoding
& 255;
583 case 254: strcat( lpEncoding
, "*" );
587 if( (*(boba
->psuffix
))[i
] )
588 strcat( lpEncoding
, (*(boba
->psuffix
))[i
] );
590 strcat( lpEncoding
, "-*" );
593 case 255: /* no suffix */
596 lpch
= lpLFD
+ lstrlenA(lpLFD
);
597 ch
= (fo
->fi
->fi_flags
& FI_SCALABLE
) ? '0' : LFDSeparator
[0];
601 /* RealizeFont() will call us repeatedly with increasing uRelax
602 * until XLoadFont() succeeds. */
607 sprintf( lpch
, "%s-%s-%i-%c-%c-*-%s", h_string
,
609 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
615 case 2: /* 2 will have replaced an 'r' in slant by '*' */
616 sprintf( lpch
, "%s-*-%i-%c-%c-*-%s", h_string
,
617 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
621 sprintf( lpch
, "%s-*-%i-%c-*-*-%s",
622 h_string
, fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
626 sprintf( lpch
, "%i-*-%i-%c-*-*-%s", fo
->fi
->lfd_height
,
627 fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
631 sprintf( lpch
, "%i-*-*-*-*-*-%s", fo
->fi
->lfd_height
, lpEncoding
);
635 sprintf( lpch
, "%i-*-*-*-*-*-*-*", fo
->fi
->lfd_height
);
638 /* to avoid an infinite loop; those will allways match */
640 sprintf( lpLFD
, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" );
643 sprintf( lpLFD
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" );
647 TRACE(font
,"\tLFD(uRelax=%d): %s\n", uRelax
, lpLFD
);
648 assert(*(lpLFD
+MAX_LFD_LENGTH
-1)==0); /* check if overwrittem */
653 /***********************************************************************
656 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
657 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
659 static BOOL
XFONT_GetLeading( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
, INT
*
660 pIL
, INT
* pEL
, XFONTTRANS
*XFT
)
662 unsigned long height
;
663 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
664 unsigned max
= (unsigned char)pFI
->dfLastChar
;
665 BOOL bHaveCapHeight
= (pFI
->dfCharSet
== ANSI_CHARSET
&& 'X' >= min
&& 'X' <= max
);
670 Atom RAW_CAP_HEIGHT
= TSXInternAtom(display
, "RAW_CAP_HEIGHT", TRUE
);
671 if(TSXGetFontProperty(x_fs
, RAW_CAP_HEIGHT
, &height
))
673 (INT
)(XFT
->pixelsize
/ 1000.0 * height
);
676 return bHaveCapHeight
&& x_fs
->per_char
;
679 if( TSXGetFontProperty(x_fs
, XA_CAP_HEIGHT
, &height
) == FALSE
)
683 height
= x_fs
->per_char
['X' - min
].ascent
;
685 if (x_fs
->ascent
>= x_fs
->max_bounds
.ascent
)
686 height
= x_fs
->max_bounds
.ascent
;
689 height
= x_fs
->ascent
;
691 *pEL
= x_fs
->max_bounds
.ascent
- height
;
694 height
= x_fs
->min_bounds
.ascent
;
697 *pIL
= x_fs
->ascent
- height
;
698 return (bHaveCapHeight
&& x_fs
->per_char
);
701 static INT
XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
,
704 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
705 unsigned max
= (unsigned char)pFI
->dfLastChar
;
710 for( j
= 0, width
= 0, chars
= 0, max
-= min
; j
<= max
; j
++ )
711 if( !CI_NONEXISTCHAR(x_fs
->per_char
+ j
) )
714 width
+= x_fs
->per_char
[j
].width
;
716 width
+= x_fs
->per_char
[j
].attributes
*
717 XFT
->pixelsize
/ 1000.0;
720 return (width
/ chars
);
723 return x_fs
->min_bounds
.width
;
726 static INT
XFONT_GetMaxCharWidth(fontObject
*pfo
)
728 unsigned min
= (unsigned char)pfo
->fs
->min_char_or_byte2
;
729 unsigned max
= (unsigned char)pfo
->fs
->max_char_or_byte2
;
732 return abs(pfo
->fs
->max_bounds
.width
);
734 if( pfo
->fs
->per_char
)
737 for( j
= 0, maxwidth
= 0, max
-= min
; j
<= max
; j
++ )
738 if( !CI_NONEXISTCHAR(pfo
->fs
->per_char
+ j
) )
739 if(maxwidth
< pfo
->fs
->per_char
[j
].attributes
)
740 maxwidth
= pfo
->fs
->per_char
[j
].attributes
;
742 maxwidth
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
745 return pfo
->foAvgCharWidth
;
748 /***********************************************************************
749 * XFONT_SetFontMetric
753 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
755 static void XFONT_SetFontMetric(fontInfo
* fi
, fontResource
* fr
, XFontStruct
* xfs
)
760 fi
->df
.dfFirstChar
= (BYTE
)(min
= xfs
->min_char_or_byte2
);
761 fi
->df
.dfLastChar
= (BYTE
)(max
= xfs
->max_char_or_byte2
);
763 fi
->df
.dfDefaultChar
= (BYTE
)xfs
->default_char
;
764 fi
->df
.dfBreakChar
= (BYTE
)(( ' ' < min
|| ' ' > max
) ? xfs
->default_char
: ' ');
766 fi
->df
.dfPixHeight
= (INT16
)((fi
->df
.dfAscent
= (INT16
)xfs
->ascent
) + xfs
->descent
);
767 fi
->df
.dfPixWidth
= (xfs
->per_char
) ? 0 : xfs
->min_bounds
.width
;
768 fi
->df
.dfMaxWidth
= (INT16
)abs(xfs
->max_bounds
.width
);
770 if( XFONT_GetLeading( &fi
->df
, xfs
, &il
, &el
, NULL
) )
771 fi
->df
.dfAvgWidth
= (INT16
)xfs
->per_char
['X' - min
].width
;
773 fi
->df
.dfAvgWidth
= (INT16
)XFONT_GetAvgCharWidth( &fi
->df
, xfs
, NULL
);
775 fi
->df
.dfInternalLeading
= (INT16
)il
;
776 fi
->df
.dfExternalLeading
= (INT16
)el
;
778 fi
->df
.dfPoints
= (INT16
)(((INT
)(fi
->df
.dfPixHeight
-
779 fi
->df
.dfInternalLeading
) * 72 + (fi
->df
.dfVertRes
>> 1)) / fi
->df
.dfVertRes
);
781 if( xfs
->min_bounds
.width
!= xfs
->max_bounds
.width
)
782 fi
->df
.dfPitchAndFamily
|= TMPF_FIXED_PITCH
; /* au contraire! */
783 if( fi
->fi_flags
& FI_SCALABLE
)
785 fi
->df
.dfType
= DEVICE_FONTTYPE
;
786 fi
->df
.dfPitchAndFamily
|= TMPF_DEVICE
;
788 else if( fi
->fi_flags
& FI_TRUETYPE
)
789 fi
->df
.dfType
= TRUETYPE_FONTTYPE
;
791 fi
->df
.dfType
= RASTER_FONTTYPE
;
793 fi
->df
.dfFace
= fr
->lfFaceName
;
796 /***********************************************************************
797 * XFONT_GetTextMetric
799 * GetTextMetrics() back end.
801 static void XFONT_GetTextMetric( fontObject
* pfo
, LPTEXTMETRICA pTM
)
803 LPIFONTINFO16 pdf
= &pfo
->fi
->df
;
805 if( ! pfo
->lpX11Trans
) {
806 pTM
->tmAscent
= pfo
->fs
->ascent
;
807 pTM
->tmDescent
= pfo
->fs
->descent
;
809 pTM
->tmAscent
= pfo
->lpX11Trans
->ascent
;
810 pTM
->tmDescent
= pfo
->lpX11Trans
->descent
;
812 pTM
->tmHeight
= pTM
->tmAscent
+ pTM
->tmDescent
;
814 pTM
->tmAveCharWidth
= pfo
->foAvgCharWidth
;
815 pTM
->tmMaxCharWidth
= pfo
->foMaxCharWidth
;
817 pTM
->tmInternalLeading
= pfo
->foInternalLeading
;
818 pTM
->tmExternalLeading
= pdf
->dfExternalLeading
;
820 pTM
->tmStruckOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
)
821 ? 1 : pdf
->dfStrikeOut
;
822 pTM
->tmUnderlined
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
)
823 ? 1 : pdf
->dfUnderline
;
826 if( pfo
->fo_flags
& FO_SYNTH_ITALIC
)
828 pTM
->tmOverhang
+= pTM
->tmHeight
/3;
831 pTM
->tmItalic
= pdf
->dfItalic
;
833 pTM
->tmWeight
= pdf
->dfWeight
;
834 if( pfo
->fo_flags
& FO_SYNTH_BOLD
)
837 pTM
->tmWeight
+= 100;
840 *(INT
*)&pTM
->tmFirstChar
= *(INT
*)&pdf
->dfFirstChar
;
842 pTM
->tmCharSet
= pdf
->dfCharSet
;
843 pTM
->tmPitchAndFamily
= pdf
->dfPitchAndFamily
;
845 pTM
->tmDigitizedAspectX
= pdf
->dfHorizRes
;
846 pTM
->tmDigitizedAspectY
= pdf
->dfVertRes
;
849 /***********************************************************************
850 * XFONT_GetFontMetric
852 * Retrieve font metric info (enumeration).
854 static UINT
XFONT_GetFontMetric( fontInfo
* pfi
, LPENUMLOGFONTEX16 pLF
,
855 LPNEWTEXTMETRIC16 pTM
)
857 memset( pLF
, 0, sizeof(*pLF
) );
858 memset( pTM
, 0, sizeof(*pTM
) );
860 #define plf ((LPLOGFONT16)pLF)
861 plf
->lfHeight
= pTM
->tmHeight
= pfi
->df
.dfPixHeight
;
862 plf
->lfWidth
= pTM
->tmAveCharWidth
= pfi
->df
.dfAvgWidth
;
863 plf
->lfWeight
= pTM
->tmWeight
= pfi
->df
.dfWeight
;
864 plf
->lfItalic
= pTM
->tmItalic
= pfi
->df
.dfItalic
;
865 plf
->lfUnderline
= pTM
->tmUnderlined
= pfi
->df
.dfUnderline
;
866 plf
->lfStrikeOut
= pTM
->tmStruckOut
= pfi
->df
.dfStrikeOut
;
867 plf
->lfCharSet
= pTM
->tmCharSet
= pfi
->df
.dfCharSet
;
869 /* convert pitch values */
871 pTM
->tmPitchAndFamily
= pfi
->df
.dfPitchAndFamily
;
872 plf
->lfPitchAndFamily
= (pfi
->df
.dfPitchAndFamily
& 0xF1) + 1;
874 lstrcpynA( plf
->lfFaceName
, pfi
->df
.dfFace
, LF_FACESIZE
);
877 pTM
->tmAscent
= pfi
->df
.dfAscent
;
878 pTM
->tmDescent
= pTM
->tmHeight
- pTM
->tmAscent
;
879 pTM
->tmInternalLeading
= pfi
->df
.dfInternalLeading
;
880 pTM
->tmMaxCharWidth
= pfi
->df
.dfMaxWidth
;
881 pTM
->tmDigitizedAspectX
= pfi
->df
.dfHorizRes
;
882 pTM
->tmDigitizedAspectY
= pfi
->df
.dfVertRes
;
884 *(INT
*)&pTM
->tmFirstChar
= *(INT
*)&pfi
->df
.dfFirstChar
;
886 /* return font type */
888 return pfi
->df
.dfType
;
892 /***********************************************************************
897 * dfPitchAndFamily flags for some common typefaces.
899 static BYTE
XFONT_FixupFlags( LPCSTR lfFaceName
)
901 switch( lfFaceName
[0] )
904 case 'H': if(!strcasecmp(lfFaceName
, "Helvetica") )
908 case 'C': if(!strcasecmp(lfFaceName
, "Courier") ||
909 !strcasecmp(lfFaceName
, "Charter") )
913 case 'P': if( !strcasecmp(lfFaceName
,"Palatino") )
917 case 'T': if(!strncasecmp(lfFaceName
, "Times", 5) )
921 case 'U': if(!strcasecmp(lfFaceName
, "Utopia") )
925 case 'Z': if(!strcasecmp(lfFaceName
, "Zapf Dingbats") )
926 return FF_DECORATIVE
;
932 /***********************************************************************
933 * XFONT_CheckResourceName
937 static BOOL
XFONT_CheckResourceName( LPSTR resource
, LPCSTR name
, INT n
)
939 resource
= LFD_Advance( resource
, 2 );
941 return (!strncasecmp( resource
, name
, n
));
946 /***********************************************************************
951 * Build generic Windows aliases for X font names.
953 * -misc-fixed- -> "Fixed"
954 * -sony-fixed- -> "Sony Fixed", etc...
956 static void XFONT_WindowsNames( char* buffer
)
958 fontResource
* fr
, *pfr
;
962 const char* relocTable
[] = { INIDefaultFixed
, INIDefault
, NULL
};
964 for( fr
= fontList
; fr
; fr
= fr
->next
)
966 if( fr
->fr_flags
& FR_NAMESET
) continue; /* skip already assigned */
968 lpstr
= LFD_Advance(fr
->resource
, 2);
969 i
= LFD_Advance( lpstr
, 1 ) - lpstr
;
971 for( pfr
= fontList
; pfr
!= fr
; pfr
= pfr
->next
)
972 if( pfr
->fr_flags
& FR_NAMESET
)
973 if( XFONT_CheckResourceName( pfr
->resource
, lpstr
, i
) )
976 if( pfr
!= fr
) /* prepend vendor name */
977 lpstr
= fr
->resource
+ 1;
979 for( i
= 0, up
= 1, lpch
= fr
->lfFaceName
; *lpstr
&& i
< 32;
980 lpch
++, lpstr
++, i
++ )
982 if( *lpstr
== LFDSeparator
[1] || *lpstr
== ' ' )
987 else if( isalpha(*lpstr
) && up
)
989 *lpch
= toupper(*lpstr
);
994 while (*(lpch
- 1) == ' ') *(--lpch
) = '\0';
996 if( (bFamilyStyle
= XFONT_FixupFlags( fr
->lfFaceName
)) )
999 for( fi
= fr
->fi
; fi
; fi
= fi
->next
)
1000 fi
->df
.dfPitchAndFamily
|= bFamilyStyle
;
1003 TRACE(font
,"typeface \'%s\'\n", fr
->lfFaceName
);
1005 fr
->fr_flags
|= FR_NAMESET
;
1008 for( up
= 0; relocTable
[up
]; up
++ )
1009 if( PROFILE_GetWineIniString( INIFontSection
, relocTable
[up
], "", buffer
, 128 ) )
1011 while( *buffer
&& isspace(*buffer
) ) buffer
++;
1012 for( fr
= NULL
, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1014 i
= strlen( pfr
->resource
);
1015 if( !strncasecmp( pfr
->resource
, buffer
, i
) )
1019 fr
->next
= pfr
->next
;
1020 pfr
->next
= fontList
;
1030 /***********************************************************************
1033 static fontAlias
* XFONT_CreateAlias( LPCSTR lpTypeFace
, LPCSTR lpAlias
)
1036 fontAlias
* pfa
= aliasTable
;
1040 /* check if we already got one */
1041 if( !strcasecmp( pfa
->faTypeFace
, lpAlias
) )
1043 TRACE(font
,"\tredundant alias '%s' -> '%s'\n",
1044 lpAlias
, lpTypeFace
);
1047 if( pfa
->next
) pfa
= pfa
->next
;
1051 j
= lstrlenA(lpTypeFace
) + 1;
1052 pfa
->next
= HeapAlloc( SystemHeap
, 0, sizeof(fontAlias
) +
1053 j
+ lstrlenA(lpAlias
) + 1 );
1054 if((pfa
= pfa
->next
))
1057 pfa
->faTypeFace
= (LPSTR
)(pfa
+ 1);
1058 lstrcpyA( pfa
->faTypeFace
, lpTypeFace
);
1059 pfa
->faAlias
= pfa
->faTypeFace
+ j
;
1060 lstrcpyA( pfa
->faAlias
, lpAlias
);
1062 TRACE(font
, "\tadded alias '%s' for %s\n", lpAlias
, lpTypeFace
);
1069 /***********************************************************************
1072 * Read user-defined aliases from wine.conf. Format is as follows
1074 * Alias# = [Windows font name],[LFD font name], <substitute original name>
1077 * Alias0 = Arial, -adobe-helvetica-
1078 * Alias1 = Times New Roman, -bitstream-courier-, 1
1081 * Note that from 081797 and on we have built-in alias templates that take
1082 * care of the necessary Windows typefaces.
1084 static void XFONT_LoadAliases( char** buffer
, int *buf_size
)
1086 char* lpResource
, *lpAlias
;
1087 char subsection
[32];
1089 BOOL bHaveAlias
= TRUE
, bSubst
= FALSE
;
1091 if( *buf_size
< 128 )
1093 *buffer
= HeapReAlloc(SystemHeap
, 0, *buffer
, 256 );
1098 if( j
< faTemplateNum
)
1100 /* built-in templates first */
1102 lpResource
= faTemplate
[j
].fatResource
;
1103 lpAlias
= faTemplate
[j
].fatAlias
;
1108 /* then WINE.CONF */
1110 wsprintfA( subsection
, "%s%i", INIAliasSection
, i
++ );
1112 if( (bHaveAlias
= PROFILE_GetWineIniString( INIFontSection
,
1113 subsection
, "", *buffer
, 128 )) )
1116 while( isspace(*lpAlias
) ) lpAlias
++;
1117 lpResource
= PROFILE_GetStringItem( lpAlias
);
1118 bSubst
= (PROFILE_GetStringItem( lpResource
)) ? TRUE
: FALSE
;
1126 length
= strlen( lpAlias
);
1127 if( lpResource
&& length
)
1129 fontResource
* fr
, *frMatch
= NULL
;
1131 for (fr
= fontList
; fr
; fr
= fr
->next
)
1133 if( !strcasecmp( fr
->resource
, lpResource
) ) frMatch
= fr
;
1134 if( XFONT_CheckResourceName( fr
->resource
, lpAlias
, length
) )
1136 /* alias is not needed since the real font is present */
1137 frMatch
= NULL
; break;
1145 fontAlias
*pfa
, *prev
= NULL
;
1147 for(pfa
= aliasTable
; pfa
; pfa
= pfa
->next
)
1149 /* Remove lpAlias from aliasTable - we should free the old entry */
1150 if(!strcmp(lpAlias
, pfa
->faAlias
))
1153 prev
->next
= pfa
->next
;
1155 aliasTable
= pfa
->next
;
1158 /* Update any references to the substituted font in aliasTable */
1159 if(!strcmp(frMatch
->lfFaceName
,
1161 pfa
->faTypeFace
= HEAP_strdupA( SystemHeap
, 0,
1166 TRACE(font
, "\tsubstituted '%s' with %s\n",
1167 frMatch
->lfFaceName
, lpAlias
);
1169 lstrcpynA( frMatch
->lfFaceName
, lpAlias
, LF_FACESIZE
);
1170 frMatch
->fr_flags
|= FR_NAMESET
;
1174 /* create new entry in the alias table */
1175 XFONT_CreateAlias( frMatch
->lfFaceName
, lpAlias
);
1179 else ERR(font
, " malformed font alias '%s'\n", *buffer
);
1185 /***********************************************************************
1186 * XFONT_LoadPenalties
1188 * Removes specified fonts from the font table to prevent Wine from
1191 * Ignore# = [LFD font name]
1194 * Ignore0 = -misc-nil-
1195 * Ignore1 = -sun-open look glyph-
1199 static void XFONT_LoadPenalties( char** buffer
, int *buf_size
)
1202 char subsection
[32];
1204 if( *buf_size
< 128 )
1206 *buffer
= HeapReAlloc(SystemHeap
, 0, *buffer
, 256 );
1212 wsprintfA( subsection
, "%s%i", INIIgnoreSection
, i
++ );
1214 if( PROFILE_GetWineIniString( INIFontSection
,
1215 subsection
, "", *buffer
, 255 ) )
1217 fontResource
** ppfr
;
1218 int length
= strlen( *buffer
);
1220 for( ppfr
= &fontList
; *ppfr
; ppfr
= &((*ppfr
)->next
))
1222 if( !strncasecmp( (*ppfr
)->resource
, *buffer
, length
) )
1224 TRACE(font
, "Ignoring '%s'\n", (*ppfr
)->resource
);
1226 XFONT_RemoveFontResource( ppfr
);
1236 /***********************************************************************
1237 * XFONT_UserMetricsCache
1239 * Returns expanded name for the ~/.wine/.cachedmetrics file.
1240 * Now it also appends the current value of the $DISPLAY varaible.
1242 static char* XFONT_UserMetricsCache( char* buffer
, int* buf_size
)
1247 pchDisplay
= getenv( "DISPLAY" );
1248 if( !pchDisplay
) pchDisplay
= "0";
1250 pwd
= getpwuid(getuid());
1251 if( pwd
&& pwd
->pw_dir
)
1253 int i
= strlen( pwd
->pw_dir
) + strlen( INIWinePrefix
) +
1254 strlen( INIFontMetrics
) + strlen( pchDisplay
) + 2;
1256 buffer
= (char*) HeapReAlloc( SystemHeap
, 0, buffer
, *buf_size
= i
);
1257 strcpy( buffer
, pwd
->pw_dir
);
1258 strcat( buffer
, INIWinePrefix
);
1259 strcat( buffer
, INIFontMetrics
);
1260 strcat( buffer
, pchDisplay
);
1261 } else buffer
[0] = '\0';
1266 /***********************************************************************
1267 * XFONT_ReadCachedMetrics
1271 static BOOL
XFONT_ReadCachedMetrics( int fd
, int res
, unsigned x_checksum
, int x_count
)
1278 /* read checksums */
1279 read( fd
, &u
, sizeof(unsigned) );
1280 read( fd
, &i
, sizeof(int) );
1282 if( u
== x_checksum
&& i
== x_count
)
1284 off_t length
, offset
= 3 * sizeof(int);
1286 /* read total size */
1287 read( fd
, &i
, sizeof(int) );
1288 length
= lseek( fd
, 0, SEEK_END
);
1290 if( length
== (i
+ offset
) )
1292 lseek( fd
, offset
, SEEK_SET
);
1293 fontList
= (fontResource
*)HeapAlloc( SystemHeap
, 0, i
);
1296 fontResource
* pfr
= fontList
;
1297 fontInfo
* pfi
= NULL
;
1299 TRACE(font
,"Reading cached font metrics:\n");
1301 read( fd
, fontList
, i
); /* read all metrics at once */
1302 while( offset
< length
)
1304 offset
+= sizeof(fontResource
) + sizeof(fontInfo
);
1305 pfr
->fi
= pfi
= (fontInfo
*)(pfr
+ 1);
1309 if( offset
> length
||
1310 (int)(pfi
->next
) != j
++ ) goto fail
;
1312 pfi
->df
.dfFace
= pfr
->lfFaceName
;
1313 pfi
->df
.dfHorizRes
= pfi
->df
.dfVertRes
= res
;
1314 pfi
->df
.dfPoints
= (INT16
)(((INT
)(pfi
->df
.dfPixHeight
-
1315 pfi
->df
.dfInternalLeading
) * 72 + (res
>> 1)) / res
);
1316 pfi
->next
= pfi
+ 1;
1318 if( j
> pfr
->fi_count
) break;
1321 offset
+= sizeof(fontInfo
);
1326 pfr
->next
= (fontResource
*)(pfi
+ 1);
1331 if( pfr
->next
== NULL
&&
1332 *(int*)(pfi
+ 1) == X_FMC_MAGIC
)
1334 /* read LFD stubs */
1335 char* lpch
= (char*)((int*)(pfi
+ 1) + 1);
1336 offset
+= sizeof(int);
1337 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1339 TRACE(font
,"\t%s, %i instances\n", lpch
, pfr
->fi_count
);
1340 pfr
->resource
= lpch
;
1343 if( ++offset
> length
) goto fail
;
1344 if( !*lpch
++ ) break;
1354 if( fontList
) HeapFree( SystemHeap
, 0, fontList
);
1361 /***********************************************************************
1362 * XFONT_WriteCachedMetrics
1366 static BOOL
XFONT_WriteCachedMetrics( int fd
, unsigned x_checksum
, int x_count
, int n_ff
)
1375 /* font metrics file:
1379 * +0008 total size to load
1380 * +000C prepackaged font metrics
1383 * +...x + 4 LFD stubs
1386 write( fd
, &x_checksum
, sizeof(unsigned) );
1387 write( fd
, &x_count
, sizeof(int) );
1389 for( j
= i
= 0, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1391 i
+= strlen( pfr
->resource
) + 1;
1394 i
+= n_ff
* sizeof(fontResource
) + j
* sizeof(fontInfo
) + sizeof(int);
1395 write( fd
, &i
, sizeof(int) );
1397 TRACE(font
,"Writing font cache:\n");
1399 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1403 TRACE(font
,"\t%s, %i instances\n", pfr
->resource
, pfr
->fi_count
);
1405 i
= write( fd
, pfr
, sizeof(fontResource
) );
1406 if( i
== sizeof(fontResource
) )
1408 for( k
= 1, pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
1410 memcpy( &fi
, pfi
, sizeof(fi
) );
1412 fi
.df
.dfFace
= NULL
;
1413 fi
.next
= (fontInfo
*)k
; /* loader checks this */
1415 j
= write( fd
, &fi
, sizeof(fi
) );
1418 if( j
== sizeof(fontInfo
) ) continue;
1422 if( i
== sizeof(fontResource
) && j
== sizeof(fontInfo
) )
1424 i
= j
= X_FMC_MAGIC
;
1425 write( fd
, &i
, sizeof(int) );
1426 for( pfr
= fontList
; pfr
&& i
== j
; pfr
= pfr
->next
)
1428 i
= strlen( pfr
->resource
) + 1;
1429 j
= write( fd
, pfr
->resource
, i
);
1438 /***********************************************************************
1439 * XFONT_CheckIniSection
1443 * Examines wine.conf for old/invalid font entries and recommend changes to
1447 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1448 * Original implementation.
1450 static void XFONT_CheckIniCallback(char const *, char const *, void *);
1452 static char const *fontmsgprologue
=
1454 " The following entries in the [fonts] section of the wine.conf file are\n"
1455 " obsolete or invalid:\n";
1457 static char const *fontmsgepilogue
=
1458 " These entries should be eliminated or updated.\n"
1459 " See the documentation/fonts file for more information.\n";
1461 static int XFONT_CheckIniSection()
1465 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback
,
1468 MSG(fontmsgepilogue
);
1473 static void XFONT_CheckIniCallback(
1478 /* Ignore any keys that start with potential comment characters "'", '#',
1480 if(key
[0] == '\'' || key
[0] == '#' || key
[0] == ';' || key
[0] == '\0')
1483 /* Make sure this is a valid key */
1484 if((strncasecmp(key
, INIAliasSection
, 5) == 0) ||
1485 (strncasecmp(key
, INIIgnoreSection
, 6) == 0) ||
1486 (strcasecmp( key
, INIDefault
) == 0) ||
1487 (strcasecmp( key
, INIDefaultFixed
) == 0) ||
1488 (strcasecmp( key
, INIGlobalMetrics
) == 0) ||
1489 (strcasecmp( key
, INIResolution
) == 0) ||
1490 (strcasecmp( key
, INIDefaultSerif
) == 0) ||
1491 (strcasecmp( key
, INIDefaultSansSerif
) ==0) )
1493 /* Valid key; make sure the value doesn't contain a wildcard */
1494 if(strchr(value
, '*')) {
1495 if(*(int *)found
== 0) {
1496 MSG(fontmsgprologue
);
1500 MSG(" %s=%s [no wildcards allowed]\n", key
, value
);
1504 /* Not a valid key */
1505 if(*(int *)found
== 0) {
1506 MSG(fontmsgprologue
);
1510 MSG(" %s=%s [obsolete]\n", key
, value
);
1516 /***********************************************************************
1517 * XFONT_GetPointResolution()
1521 * Here we initialize DefResolution which is used in the
1522 * XFONT_Match() penalty function. We also load the point
1523 * resolution value (higher values result in larger fonts).
1525 static int XFONT_GetPointResolution( DeviceCaps
* pDevCaps
)
1527 int i
, j
, point_resolution
, num
= 3;
1528 int allowed_xfont_resolutions
[3] = { 72, 75, 100 };
1529 int best
= 0, best_diff
= 65536;
1531 DefResolution
= point_resolution
= PROFILE_GetWineIniInt( INIFontSection
, INIResolution
, 0 );
1532 if( !DefResolution
) DefResolution
= point_resolution
= pDevCaps
->logPixelsY
;
1533 else pDevCaps
->logPixelsX
= pDevCaps
->logPixelsY
= DefResolution
;
1535 for( i
= best
= 0; i
< num
; i
++ )
1537 j
= abs( DefResolution
- allowed_xfont_resolutions
[i
] );
1544 DefResolution
= allowed_xfont_resolutions
[best
];
1545 return point_resolution
;
1548 /***********************************************************************
1549 * XFONT_BuildDefaultAliases
1553 * Alias "Helv", and "Tms Rmn" to the DefaultSansSerif and DefaultSerif
1554 * fonts respectively. Create font alias templates for "MS Sans Serif"
1555 * and "MS Serif", also pointing to DefaultSansSerif and DefaultSerif.
1557 static int XFONT_BuildDefaultAliases( char** buffer
, int* buf_size
)
1560 aliasTemplate fatDefaultSerif
= { "-bitstream-charter-", "Charter" };
1561 aliasTemplate fatDefaultSansSerif
= { "-adobe-helvetica-", "Helvetica" };
1565 /* Make sure our buffer is big enough; update calling function's
1566 buf_size if we change it. */
1568 if( *buf_size
< 128 )
1570 *buffer
= HeapReAlloc( SystemHeap
, 0, *buffer
, 256 );
1574 /* Get the X11 name of the default serif font from the Wine INI file.
1575 (-bitstream-charter- is the default.) */
1577 PROFILE_GetWineIniString( INIFontSection
, INIDefaultSerif
,
1578 fatDefaultSerif
.fatResource
, *buffer
, 128 );
1580 /* Find the Windows typeface which corresponds to the X11 font. */
1582 for( fr
= fontList
; fr
; fr
= fr
->next
)
1583 if( !strcasecmp( fr
->resource
, *buffer
) ) break;
1585 /* Update the Alias Table entry for "Tms Rmn" with the default serif font's
1586 typeface. Update the Alias Template for "MS Serif" with the default
1587 serif font's X11 name. Note that this method leaves us dependant on
1588 the order of the Alias Table and the Alias Templates. Also, we don't
1589 check for or handle a situation in which -bitstream-charter- is not
1594 TRACE(font
, "Using \'%s\' as default serif font\n", fr
->lfFaceName
);
1595 aliasTable
[1].faTypeFace
= fr
->lfFaceName
;
1596 faTemplate
[1].fatResource
= fr
->resource
;
1600 WARN(font
, "No typeface found for \'%s\'; using \'%s\'\n", *buffer
,
1601 fatDefaultSerif
.fatAlias
);
1602 aliasTable
[1].faTypeFace
= fatDefaultSerif
.fatAlias
; /* Charter */
1603 faTemplate
[1].fatResource
= fatDefaultSerif
.fatResource
;
1606 /* Get the X11 name of the default sans serif font from the Wine INI file.
1607 (-adobe-helvetica- is the default.) */
1609 PROFILE_GetWineIniString (INIFontSection
, INIDefaultSansSerif
,
1610 fatDefaultSansSerif
.fatResource
, *buffer
, 128 );
1612 /* Find the Windows typeface which corresponds to the X11 font. */
1614 for( fr
= fontList
; fr
; fr
= fr
->next
)
1615 if ( !strcasecmp( fr
->resource
, *buffer
) ) break;
1617 /* Update the Alias Table entry for "Helv" with the default sans serif font's
1618 typeface. Update the Alias Template for "MS Sans Serif" with the
1619 default sans serif font's X11 name. Note that this method leaves us
1620 dependant on the order of the Alias Table and the Alias Templates.
1621 Also, we don't check for or handle a situation in which
1622 -adobe-helvetica- is not available. */
1626 TRACE(font
, "Using \'%s\' as default sans serif font\n", fr
->lfFaceName
);
1627 aliasTable
[0].faTypeFace
= fr
->lfFaceName
;
1628 faTemplate
[0].fatResource
= fr
->resource
;
1632 WARN(font
, "No typeface found for \'%s\'; using \'%s\'\n", *buffer
,
1633 fatDefaultSansSerif
.fatAlias
);
1634 aliasTable
[0].faTypeFace
= fatDefaultSansSerif
.fatAlias
; /* Helvetica */
1635 faTemplate
[0].fatResource
= fatDefaultSansSerif
.fatResource
;
1641 /***********************************************************************
1644 * Initialize font resource list and allocate font cache.
1646 BOOL
X11DRV_FONT_Init( DeviceCaps
* pDevCaps
)
1649 fontResource
* fr
, *pfr
;
1651 unsigned x_checksum
;
1652 int i
, j
, res
, x_count
, fd
= -1, buf_size
= 0;
1653 char* lpstr
, *lpch
, *lpmetrics
, *buffer
;
1656 XFONT_CheckIniSection();
1658 res
= XFONT_GetPointResolution( pDevCaps
);
1660 x_pattern
= TSXListFonts(display
, "*", MAX_FONT_FAMILIES
* 16, &x_count
);
1662 TRACE(font
,"Font Mapper: initializing %i fonts [LPY=%i, XDR=%i, DR=%i]\n",
1663 x_count
, pDevCaps
->logPixelsY
, DefResolution
, res
);
1664 for( i
= x_checksum
= 0; i
< x_count
; i
++ )
1667 printf("%i\t: %s\n", i
, x_pattern
[i
] );
1670 j
= strlen( x_pattern
[i
] );
1671 if( j
) x_checksum
^= __genericCheckSum( x_pattern
[i
], j
);
1673 x_checksum
|= X_PFONT_MAGIC
;
1676 buffer
= HeapAlloc( SystemHeap
, 0, buf_size
);
1679 /* deal with systemwide font metrics cache */
1681 if( PROFILE_GetWineIniString( INIFontSection
, INIGlobalMetrics
, "", buffer
, 128 ) )
1682 fd
= open( buffer
, O_RDONLY
);
1684 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1687 buffer
= XFONT_UserMetricsCache( buffer
, &buf_size
);
1690 fd
= open( buffer
, O_RDONLY
);
1691 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1692 lpmetrics
= HEAP_strdupA( SystemHeap
, 0, buffer
); /* update later on */
1697 if( fontList
== NULL
) /* build metrics from scratch */
1702 for( i
= n_ff
= 0; i
< x_count
; i
++ )
1704 typeface
= lpch
= x_pattern
[i
];
1706 lpch
= LFD_Advance(typeface
, 3); /* extra '-' in the beginning */
1707 if( !*lpch
) continue;
1710 j
= lpch
- typeface
; /* resource name length */
1712 /* find a family to insert into */
1714 for( pfr
= NULL
, fr
= fontList
; fr
; fr
= fr
->next
)
1716 if( !strncasecmp(fr
->resource
, typeface
, j
) &&
1717 strlen(fr
->resource
) == j
) break;
1721 if( !fi
) fi
= (fontInfo
*) HeapAlloc(SystemHeap
, 0, sizeof(fontInfo
));
1723 if( !fr
) /* add new family */
1725 if( n_ff
>= MAX_FONT_FAMILIES
) break;
1726 if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1729 fr
= (fontResource
*) HeapAlloc(SystemHeap
, 0, sizeof(fontResource
));
1730 memset(fr
, 0, sizeof(fontResource
));
1731 fr
->resource
= (char*) HeapAlloc(SystemHeap
, 0, j
+ 1 );
1732 lstrcpynA( fr
->resource
, typeface
, j
+ 1 );
1734 TRACE(font
," family: %s\n", fr
->resource
);
1736 if( pfr
) pfr
->next
= fr
;
1739 else if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1741 /* check if we already have something better than "fi" */
1743 for( pfi
= fr
->fi
, j
= 0; pfi
&& j
<= 0; pfi
= pfi
->next
)
1744 if( (j
= XFONT_IsSubset( pfi
, fi
)) < 0 )
1745 pfi
->fi_flags
|= FI_SUBSET
; /* superseded by "fi" */
1746 if( j
> 0 ) continue;
1748 /* add new font instance "fi" to the "fr" font resource */
1750 if( fi
->fi_flags
& FI_SCALABLE
)
1752 /* set scalable font height to 24 to get an origin for extrapolation */
1754 j
= strlen(typeface
); j
+= 0x10;
1756 buffer
= (char*)HeapReAlloc( SystemHeap
, 0, buffer
, buf_size
= j
);
1758 lpch
= LFD_Advance(typeface
, 7);
1759 memcpy( buffer
, typeface
, (j
= lpch
- typeface
) );
1760 lpch
= LFD_Advance(lpch
, 4);
1761 sprintf( buffer
+ j
, "%d-%d-%d-*-%c-*-", fi
->lfd_height
,
1762 fi
->lfd_decipoints
, fi
->lfd_resolution
,
1763 (*lpch
== '-')?'*':*lpch
);
1764 lpch
= LFD_Advance(lpch
, 2);
1765 strcat( lpstr
= buffer
, lpch
);
1767 else lpstr
= typeface
;
1769 if( (x_fs
= TSXLoadQueryFont(display
, lpstr
)) )
1771 fi
->df
.dfHorizRes
= fi
->df
.dfVertRes
= res
;
1773 XFONT_SetFontMetric( fi
, fr
, x_fs
);
1774 TSXFreeFont( display
, x_fs
);
1776 TRACE(font
,"\t[% 2ipt] '%s'\n", fi
->df
.dfPoints
, typeface
);
1778 XFONT_CheckFIList( fr
, fi
, REMOVE_SUBSETS
);
1779 fi
= NULL
; /* preventing reuse */
1783 ERR(font
, "failed to load %s\n", lpstr
);
1785 XFONT_CheckFIList( fr
, fi
, UNMARK_SUBSETS
);
1789 if( lpmetrics
) /* update cached metrics */
1791 fd
= open( lpmetrics
, O_CREAT
| O_TRUNC
| O_RDWR
, 0644 ); /* -rw-r--r-- */
1792 if( XFONT_WriteCachedMetrics( fd
, x_checksum
, x_count
, n_ff
) == FALSE
)
1793 if( fd
) remove( lpmetrics
); /* couldn't write entire file */
1794 HeapFree( SystemHeap
, 0, lpmetrics
);
1798 if( fi
) HeapFree(SystemHeap
, 0, fi
);
1799 TSXFreeFontNames(x_pattern
);
1801 /* check if we're dealing with X11 R6 server */
1803 strcpy(buffer
, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1804 if( (x_fs
= TSXLoadQueryFont(display
, buffer
)) )
1806 XTextCaps
|= TC_SF_X_YINDEP
;
1807 TSXFreeFont(display
, x_fs
);
1810 XFONT_WindowsNames( buffer
);
1811 XFONT_BuildDefaultAliases( &buffer
, &buf_size
);
1812 XFONT_LoadAliases( &buffer
, &buf_size
);
1813 XFONT_LoadPenalties( &buffer
, &buf_size
);
1814 HeapFree(SystemHeap
, 0, buffer
);
1816 InitializeCriticalSection( &crtsc_fonts_X11
);
1817 MakeCriticalSectionGlobal( &crtsc_fonts_X11
);
1819 /* fontList initialization is over, allocate X font cache */
1821 fontCache
= (fontObject
*) HeapAlloc(SystemHeap
, 0, fontCacheSize
* sizeof(fontObject
));
1822 XFONT_GrowFreeList(0, fontCacheSize
- 1);
1824 TRACE(font
,"done!\n");
1826 /* update text caps parameter */
1828 pDevCaps
->textCaps
= XTextCaps
;
1830 RAW_ASCENT
= TSXInternAtom(display
, "RAW_ASCENT", TRUE
);
1831 RAW_DESCENT
= TSXInternAtom(display
, "RAW_DESCENT", TRUE
);
1837 /***********************************************************************
1838 * XFONT_RemoveFontResource
1840 * Caller should check if the font resource is in use. If it is it should
1841 * set FR_REMOVED flag to delay removal until the resource is not in use
1844 void XFONT_RemoveFontResource( fontResource
** ppfr
)
1847 fontResource
* pfr
= *ppfr
;
1852 pfi
= pfr
->fi
->next
;
1853 HeapFree( SystemHeap
, 0, pfr
->fi
);
1856 HeapFree( SystemHeap
, 0, pfr
);
1859 /***********************************************************************
1862 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1864 static INT
XFONT_IsSubset(fontInfo
* match
, fontInfo
* fi
)
1868 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1870 m
= (BYTE
*)&fi
->df
.dfPixWidth
- (BYTE
*)&fi
->df
.dfItalic
;
1871 if( memcmp(&match
->df
.dfItalic
, &fi
->df
.dfItalic
, m
)) return 0;
1873 if( (!((fi
->fi_flags
& FI_SCALABLE
) + (match
->fi_flags
& FI_SCALABLE
))
1874 && fi
->lfd_height
!= match
->lfd_height
) ||
1875 (!((fi
->fi_flags
& FI_POLYWEIGHT
) + (match
->fi_flags
& FI_POLYWEIGHT
))
1876 && fi
->df
.dfWeight
!= match
->df
.dfWeight
) ) return 0;
1878 m
= (int)(match
->fi_flags
& (FI_POLYWEIGHT
| FI_SCALABLE
)) -
1879 (int)(fi
->fi_flags
& (FI_SCALABLE
| FI_POLYWEIGHT
));
1881 if( m
== (FI_POLYWEIGHT
- FI_SCALABLE
) ||
1882 m
== (FI_SCALABLE
- FI_POLYWEIGHT
) ) return 0; /* keep both */
1883 else if( m
>= 0 ) return 1; /* 'match' is better */
1885 return -1; /* 'fi' is better */
1888 /***********************************************************************
1891 * Compute the matching score between the logical font and the device font.
1893 * contributions from highest to lowest:
1897 * family flags (only when the facename is not present)
1899 * weight, italics, underlines, strikeouts
1901 * NOTE: you can experiment with different penalty weights to see what happens.
1902 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
1904 static UINT
XFONT_Match( fontMatch
* pfm
)
1906 fontInfo
* pfi
= pfm
->pfi
; /* device font to match */
1907 LPLOGFONT16 plf
= pfm
->plf
; /* wanted logical font */
1909 BOOL bR6
= pfm
->flags
& FO_MATCH_XYINDEP
; /* from TextCaps */
1910 BOOL bScale
= pfi
->fi_flags
& FI_SCALABLE
;
1913 TRACE(font
,"\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi
->df
.dfPoints
,
1914 pfi
->df
.dfPixHeight
, pfi
->df
.dfAvgWidth
,
1915 (pfi
->df
.dfWeight
> 400) ? "Bold " : "Normal ",
1916 (pfi
->df
.dfItalic
) ? "Italic" : "" );
1920 if( plf
->lfCharSet
== DEFAULT_CHARSET
)
1922 if( (pfi
->df
.dfCharSet
!= ANSI_CHARSET
) && (pfi
->df
.dfCharSet
!=DEFAULT_CHARSET
) )
1925 else if (plf
->lfCharSet
!= pfi
->df
.dfCharSet
) penalty
+= 0x200;
1927 /* FIXME: Hack to demote symbols and nil fonts. Should take into
1928 account if a program ever actually asked for this type of
1930 if ( (strcmp(pfm
->pfr
->lfFaceName
,"Symbol")==0) || (strcmp(pfm
->pfr
->lfFaceName
,"Nil")==0) )
1931 penalty
+= 0x200; /* very stiff penality */
1933 /* TMPF_FIXED_PITCH means exactly the opposite */
1935 if( plf
->lfPitchAndFamily
& FIXED_PITCH
)
1937 if( pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) penalty
+= 0x100;
1939 else if( !(pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) ) penalty
+= 0x2;
1941 if( plf
->lfHeight
> 0 )
1942 d
= (h
= pfi
->df
.dfPixHeight
) - plf
->lfHeight
;
1943 else if( plf
->lfHeight
< -1 )
1944 d
= (h
= pfi
->df
.dfPoints
) + plf
->lfHeight
;
1947 if( d
&& h
&& plf
->lfHeight
)
1949 UINT16 height
= ( plf
->lfHeight
> 0 ) ? plf
->lfHeight
1950 : ((-plf
->lfHeight
* pfi
->df
.dfPixHeight
) / h
);
1951 if( bScale
) pfm
->height
= height
;
1952 else if( (plf
->lfQuality
!= PROOF_QUALITY
) && bR6
)
1954 if( d
> 0 ) /* do not shrink raster fonts */
1956 pfm
->height
= pfi
->df
.dfPixHeight
;
1957 penalty
+= (pfi
->df
.dfPixHeight
- height
) * 0x4;
1959 else /* expand only in integer multiples */
1961 pfm
->height
= height
- height
%pfi
->df
.dfPixHeight
;
1962 penalty
+= (height
- pfm
->height
+ 1) * height
/ pfi
->df
.dfPixHeight
;
1965 else /* can't be scaled at all */
1967 if( plf
->lfQuality
!= PROOF_QUALITY
) pfm
->flags
|= FO_SYNTH_HEIGHT
;
1968 pfm
->height
= pfi
->df
.dfPixHeight
;
1969 penalty
+= (d
> 0)? d
* 0x8 : -d
* 0x10;
1972 else pfm
->height
= pfi
->df
.dfPixHeight
;
1974 if((pfm
->flags
& FO_MATCH_PAF
) &&
1975 (plf
->lfPitchAndFamily
& FF_FAMILY
) != (pfi
->df
.dfPitchAndFamily
& FF_FAMILY
) )
1980 if( bR6
&& bScale
) h
= 0;
1983 /* FIXME: not complete */
1985 pfm
->flags
|= FO_SYNTH_WIDTH
;
1986 h
= abs(plf
->lfWidth
- (pfm
->height
* pfi
->df
.dfAvgWidth
)/pfi
->df
.dfPixHeight
);
1988 penalty
+= h
* ( d
) ? 0x2 : 0x1 ;
1990 else if( !(pfi
->fi_flags
& FI_NORMAL
) ) penalty
++;
1992 if( plf
->lfWeight
!= FW_DONTCARE
)
1994 penalty
+= abs(plf
->lfWeight
- pfi
->df
.dfWeight
) / 40;
1995 if( plf
->lfWeight
> pfi
->df
.dfWeight
) pfm
->flags
|= FO_SYNTH_BOLD
;
1996 } else if( pfi
->df
.dfWeight
>= FW_BOLD
) penalty
++; /* choose normal by default */
1998 if( plf
->lfItalic
!= pfi
->df
.dfItalic
)
2001 pfm
->flags
|= FO_SYNTH_ITALIC
;
2004 if( plf
->lfUnderline
) pfm
->flags
|= FO_SYNTH_UNDERLINE
;
2005 if( plf
->lfStrikeOut
) pfm
->flags
|= FO_SYNTH_STRIKEOUT
;
2007 if( penalty
&& pfi
->lfd_resolution
!= DefResolution
)
2010 TRACE(font
," returning %i\n", penalty
);
2015 /***********************************************************************
2018 * Scan a particular font resource for the best match.
2020 static UINT
XFONT_MatchFIList( fontMatch
* pfm
)
2022 BOOL skipRaster
= (pfm
->flags
& FO_MATCH_NORASTER
);
2023 UINT current_score
, score
= (UINT
)(-1);
2024 UINT16 origflags
= pfm
->flags
; /* Preserve FO_MATCH_XYINDEP */
2025 fontMatch fm
= *pfm
;
2027 for( fm
.pfi
= pfm
->pfr
->fi
; fm
.pfi
&& score
; fm
.pfi
= fm
.pfi
->next
,
2028 fm
.flags
= origflags
)
2030 if( skipRaster
&& !(fm
.pfi
->fi_flags
& FI_SCALABLE
) )
2033 current_score
= XFONT_Match( &fm
);
2034 if( score
> current_score
)
2036 memcpy( pfm
, &fm
, sizeof(fontMatch
) );
2037 score
= current_score
;
2043 /***********************************************************************
2046 * REMOVE_SUBSETS - attach new fi and purge subsets
2047 * UNMARK_SUBSETS - remove subset flags from all fi entries
2049 static void XFONT_CheckFIList( fontResource
* fr
, fontInfo
* fi
, int action
)
2052 fontInfo
* pfi
, *prev
;
2054 for( prev
= NULL
, pfi
= fr
->fi
; pfi
; )
2056 if( action
== REMOVE_SUBSETS
)
2058 if( pfi
->fi_flags
& FI_SUBSET
)
2060 fontInfo
* subset
= pfi
;
2064 if( prev
) prev
->next
= pfi
= pfi
->next
;
2065 else fr
->fi
= pfi
= pfi
->next
;
2066 HeapFree( SystemHeap
, 0, subset
);
2070 else pfi
->fi_flags
&= ~FI_SUBSET
;
2076 if( action
== REMOVE_SUBSETS
) /* also add the superset */
2078 if( fi
->fi_flags
& FI_SCALABLE
)
2083 else if( prev
) prev
->next
= fi
; else fr
->fi
= fi
;
2087 if( i
) TRACE(font
,"\t purged %i subsets [%i]\n", i
, fr
->fi_count
);
2090 /***********************************************************************
2093 static fontResource
* XFONT_FindFIList( fontResource
* pfr
, const char* pTypeFace
)
2097 if( !strcasecmp( pfr
->lfFaceName
, pTypeFace
) ) break;
2103 /***********************************************************************
2104 * XFONT_MatchDeviceFont
2106 * Scan font resource tree.
2108 static BOOL
XFONT_MatchDeviceFont( fontResource
* start
, fontMatch
* pfm
)
2110 fontResource
** ppfr
;
2111 fontMatch fm
= *pfm
;
2114 if( fm
.plf
->lfFaceName
[0] )
2119 for( fa
= aliasTable
; fa
; fa
= fa
->next
)
2120 if( !strcmp( fa
->faAlias
, fm
.plf
->lfFaceName
) )
2122 str
= fa
->faTypeFace
;
2125 fm
.pfr
= XFONT_FindFIList( start
, str
? str
: fm
.plf
->lfFaceName
);
2128 if( fm
.pfr
) /* match family */
2130 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
2132 if( fm
.pfr
->fr_flags
& FR_REMOVED
)
2136 XFONT_MatchFIList( &fm
);
2141 if( !pfm
->pfi
) /* match all available fonts */
2143 UINT current_score
, score
= (UINT
)(-1);
2145 fm
.flags
|= FO_MATCH_PAF
;
2146 for( ppfr
= &fontList
; *ppfr
&& score
; ppfr
= &(*ppfr
)->next
)
2148 if( (*ppfr
)->fr_flags
& FR_REMOVED
)
2150 if( (*ppfr
)->fo_count
== 0 )
2151 XFONT_RemoveFontResource( ppfr
);
2157 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
2159 current_score
= XFONT_MatchFIList( &fm
);
2160 if( current_score
< score
)
2162 score
= current_score
;
2171 /***********************************************************************
2174 static void XFONT_GrowFreeList(int start
, int end
)
2176 /* add all entries from 'start' up to and including 'end' */
2178 memset( fontCache
+ start
, 0, (end
- start
+ 1) * sizeof(fontObject
) );
2180 fontCache
[end
].lru
= fontLF
;
2181 fontCache
[end
].count
= -1;
2183 while( start
< end
)
2185 fontCache
[start
].count
= -1;
2186 fontCache
[start
].lru
= start
+ 1;
2191 static fontObject
* XFONT_LookupCachedFont( LPLOGFONT16 plf
, UINT16
* checksum
)
2193 UINT16 cs
= __lfCheckSum( plf
);
2194 int i
= fontMRU
, prev
= -1;
2199 if( fontCache
[i
].lfchecksum
== cs
&&
2200 !(fontCache
[i
].fo_flags
& FO_REMOVED
) )
2202 /* FIXME: something more intelligent here */
2204 if( !memcmp( plf
, &fontCache
[i
].lf
,
2205 sizeof(LOGFONT16
) - LF_FACESIZE
) &&
2206 !strncasecmp( plf
->lfFaceName
, fontCache
[i
].lf
.lfFaceName
,
2209 /* remove temporarily from the lru list */
2212 fontCache
[prev
].lru
= fontCache
[i
].lru
;
2214 fontMRU
= (INT16
)fontCache
[i
].lru
;
2215 return (fontCache
+ i
);
2219 i
= (INT16
)fontCache
[i
].lru
;
2224 static fontObject
* XFONT_GetCacheEntry()
2230 int prev_i
, prev_j
, j
;
2232 TRACE(font
,"font cache is full\n");
2234 /* lookup the least recently used font */
2236 for( prev_i
= prev_j
= j
= -1, i
= fontMRU
; i
>= 0; i
= (INT16
)fontCache
[i
].lru
)
2238 if( fontCache
[i
].count
<= 0 &&
2239 !(fontCache
[i
].fo_flags
& FO_SYSTEM
) )
2247 if( j
>= 0 ) /* unload font */
2249 /* detach from the lru list */
2251 TRACE(font
,"\tfreeing entry %i\n", j
);
2253 fontCache
[j
].fr
->fo_count
--;
2256 fontCache
[prev_j
].lru
= fontCache
[j
].lru
;
2257 else fontMRU
= (INT16
)fontCache
[j
].lru
;
2259 /* FIXME: lpXForm, lpPixmap */
2260 if(fontCache
[j
].lpX11Trans
)
2261 HeapFree( SystemHeap
, 0, fontCache
[j
].lpX11Trans
);
2263 TSXFreeFont( display
, fontCache
[j
].fs
);
2265 memset( fontCache
+ j
, 0, sizeof(fontObject
) );
2266 return (fontCache
+ j
);
2268 else /* expand cache */
2270 fontObject
* newCache
;
2272 prev_i
= fontCacheSize
+ FONTCACHE
;
2274 TRACE(font
,"\tgrowing font cache from %i to %i\n", fontCacheSize
, prev_i
);
2276 if( (newCache
= (fontObject
*)HeapReAlloc(SystemHeap
, 0,
2277 fontCache
, prev_i
)) )
2280 fontCacheSize
= prev_i
;
2281 fontCache
= newCache
;
2282 XFONT_GrowFreeList( i
, fontCacheSize
- 1);
2288 /* detach from the free list */
2291 fontLF
= (INT16
)fontCache
[i
].lru
;
2292 fontCache
[i
].count
= 0;
2293 return (fontCache
+ i
);
2296 static int XFONT_ReleaseCacheEntry(fontObject
* pfo
)
2298 UINT u
= (UINT
)(pfo
- fontCache
);
2300 if( u
< fontCacheSize
) return (--fontCache
[u
].count
);
2304 /**********************************************************************
2307 static BOOL
XFONT_SetX11Trans( fontObject
*pfo
)
2313 TSXGetFontProperty( pfo
->fs
, XA_FONT
, &nameAtom
);
2314 fontName
= TSXGetAtomName( display
, nameAtom
);
2315 cp
= LFD_Advance( fontName
, 7 );
2321 while((cp
= strchr(cp
, '~')))
2324 #define PX pfo->lpX11Trans
2326 sscanf(start
, "[%f%f%f%f]", &PX
->a
, &PX
->b
, &PX
->c
, &PX
->d
);
2329 TSXGetFontProperty( pfo
->fs
, RAW_ASCENT
, &PX
->RAW_ASCENT
);
2330 TSXGetFontProperty( pfo
->fs
, RAW_DESCENT
, &PX
->RAW_DESCENT
);
2332 PX
->pixelsize
= hypot(PX
->a
, PX
->b
);
2333 PX
->ascent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_ASCENT
;
2334 PX
->descent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_DESCENT
;
2336 TRACE(font
, "[%f %f %f %f] RA = %ld RD = %ld\n", pfo
->lpX11Trans
->a
,
2337 pfo
->lpX11Trans
->b
, pfo
->lpX11Trans
->c
, pfo
->lpX11Trans
->d
,
2338 pfo
->lpX11Trans
->RAW_ASCENT
, pfo
->lpX11Trans
->RAW_DESCENT
);
2344 /***********************************************************************
2345 * X Device Font Objects
2347 static X_PHYSFONT
XFONT_RealizeFont( LPLOGFONT16 plf
)
2350 fontObject
* pfo
= XFONT_LookupCachedFont( plf
, &checksum
);
2354 fontMatch fm
= { NULL
, NULL
, 0, 0, plf
};
2357 if( XTextCaps
& TC_SF_X_YINDEP
) fm
.flags
= FO_MATCH_XYINDEP
;
2359 /* allocate new font cache entry */
2361 if( (pfo
= XFONT_GetCacheEntry()) )
2363 LPSTR lpLFD
= HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH
);
2365 if( lpLFD
) /* initialize entry and load font */
2367 UINT uRelaxLevel
= 0;
2369 TRACE(font
,"(%u) '%s' h=%i weight=%i %s\n",
2370 plf
->lfCharSet
, plf
->lfFaceName
, plf
->lfHeight
,
2371 plf
->lfWeight
, (plf
->lfItalic
) ? "Italic" : "" );
2373 if(abs(plf
->lfHeight
) > MAX_FONT_SIZE
) {
2375 "plf->lfHeight = %d, this is probably not right. Setting to 100\n",
2377 plf
->lfHeight
= 100;
2380 XFONT_MatchDeviceFont( fontList
, &fm
);
2384 pfo
->fr
->fo_count
++;
2385 pfo
->fo_flags
= fm
.flags
& ~FO_MATCH_MASK
;
2387 memcpy( &pfo
->lf
, plf
, sizeof(LOGFONT16
) );
2388 pfo
->lfchecksum
= checksum
;
2392 LFD_ComposeLFD( pfo
, fm
.height
, lpLFD
, uRelaxLevel
++ );
2393 if( (pfo
->fs
= TSXLoadQueryFont( display
, lpLFD
)) ) break;
2394 } while( uRelaxLevel
);
2397 if(pfo
->lf
.lfEscapement
!= 0) {
2398 pfo
->lpX11Trans
= HeapAlloc(SystemHeap
, 0,
2399 sizeof(XFONTTRANS
));
2400 if(!XFONT_SetX11Trans( pfo
)) {
2401 HeapFree(SystemHeap
, 0, pfo
->lpX11Trans
);
2402 pfo
->lpX11Trans
= NULL
;
2406 if( XFONT_GetLeading( &pfo
->fi
->df
, pfo
->fs
, &i
, NULL
,
2409 if(!pfo
->lpX11Trans
)
2410 pfo
->foAvgCharWidth
=
2411 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].width
;
2413 pfo
->foAvgCharWidth
=
2414 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].attributes
2415 * pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2417 pfo
->foAvgCharWidth
= (INT16
)XFONT_GetAvgCharWidth(
2418 &pfo
->fi
->df
, pfo
->fs
, pfo
->lpX11Trans
);
2419 pfo
->foMaxCharWidth
= (INT16
)XFONT_GetMaxCharWidth(pfo
);
2420 pfo
->foInternalLeading
= (INT16
)i
;
2422 /* FIXME: If we've got a soft font or
2423 * there are FO_SYNTH_... flags for the
2424 * non PROOF_QUALITY request, the engine
2425 * should rasterize characters into mono
2426 * pixmaps and store them in the pfo->lpPixmap
2427 * array (pfo->fs should be updated as well).
2428 * array (pfo->fs should be updated as well).
2429 * X11DRV_ExtTextOut() must be heavily modified
2430 * to support pixmap blitting and FO_SYNTH_...
2434 pfo
->lpPixmap
= NULL
;
2436 HeapFree( GetProcessHeap(), 0, lpLFD
);
2438 else /* attach back to the free list */
2442 fontLF
= (pfo
- fontCache
);
2447 if( !pfo
) /* couldn't get a new entry, get one of the cached fonts */
2449 UINT current_score
, score
= (UINT
)(-1);
2451 i
= index
= fontMRU
;
2452 fm
.flags
|= FO_MATCH_PAF
;
2455 pfo
= fontCache
+ i
;
2456 fm
.pfr
= pfo
->fr
; fm
.pfi
= pfo
->fi
;
2458 current_score
= XFONT_Match( &fm
);
2459 if( current_score
< score
) index
= i
;
2463 pfo
= fontCache
+ index
;
2465 return (X_PHYSFONT
)(X_PFONT_MAGIC
| index
);
2469 /* attach at the head of the lru list */
2473 fontMRU
= (pfo
- fontCache
);
2475 TRACE(font
,"physfont %i\n", fontMRU
);
2477 return (X_PHYSFONT
)(X_PFONT_MAGIC
| fontMRU
);
2480 /***********************************************************************
2481 * XFONT_GetFontObject
2483 fontObject
* XFONT_GetFontObject( X_PHYSFONT pFont
)
2485 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
);
2489 /***********************************************************************
2490 * XFONT_GetFontStruct
2492 XFontStruct
* XFONT_GetFontStruct( X_PHYSFONT pFont
)
2494 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
)->fs
;
2498 /***********************************************************************
2501 LPIFONTINFO16
XFONT_GetFontInfo( X_PHYSFONT pFont
)
2503 if( CHECK_PFONT(pFont
) ) return &(__PFONT(pFont
)->fi
->df
);
2509 /* X11DRV Interface ****************************************************
2511 * Exposed via the dc->funcs dispatch table. *
2513 ***********************************************************************/
2514 /***********************************************************************
2515 * X11DRV_FONT_SelectObject
2517 HFONT
X11DRV_FONT_SelectObject( DC
* dc
, HFONT hfont
, FONTOBJ
* font
)
2519 HFONT hPrevFont
= 0;
2521 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2523 EnterCriticalSection( &crtsc_fonts_X11
);
2525 if( CHECK_PFONT(physDev
->font
) )
2526 XFONT_ReleaseCacheEntry( __PFONT(physDev
->font
) );
2528 /* FIXME: do we need to pass anything back from here? */
2529 memcpy(&lf
,&font
->logfont
,sizeof(lf
));
2530 lf
.lfWidth
= font
->logfont
.lfWidth
* dc
->vportExtX
/dc
->wndExtX
;
2531 lf
.lfHeight
= font
->logfont
.lfHeight
* dc
->vportExtY
/dc
->wndExtY
;
2533 physDev
->font
= XFONT_RealizeFont( &lf
);
2534 hPrevFont
= dc
->w
.hFont
;
2535 dc
->w
.hFont
= hfont
;
2537 LeaveCriticalSection( &crtsc_fonts_X11
);
2543 /***********************************************************************
2545 * X11DRV_EnumDeviceFonts
2547 BOOL
X11DRV_EnumDeviceFonts( DC
* dc
, LPLOGFONT16 plf
,
2548 DEVICEFONTENUMPROC proc
, LPARAM lp
)
2552 fontResource
* pfr
= fontList
;
2555 if( plf
->lfFaceName
[0] )
2557 /* enum all entries in this resource */
2558 pfr
= XFONT_FindFIList( pfr
, plf
->lfFaceName
);
2562 for( pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
2564 /* Note: XFONT_GetFontMetric() will have to
2565 release the crit section, font list will
2566 have to be retraversed on return */
2568 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2569 XFONT_GetFontMetric( pfi
, &lf
, &tm
), lp
)) )
2575 else /* enum first entry in each resource */
2576 for( ; pfr
; pfr
= pfr
->next
)
2580 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2581 XFONT_GetFontMetric( pfr
->fi
, &lf
, &tm
), lp
)) )
2590 /***********************************************************************
2591 * X11DRV_GetTextExtentPoint
2593 BOOL
X11DRV_GetTextExtentPoint( DC
*dc
, LPCSTR str
, INT count
,
2596 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2597 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2599 if( !pfo
->lpX11Trans
) {
2600 int dir
, ascent
, descent
;
2603 TSXTextExtents( pfo
->fs
, str
, count
, &dir
, &ascent
, &descent
, &info
);
2604 size
->cx
= abs((info
.width
+ dc
->w
.breakRem
+ count
*
2605 dc
->w
.charExtra
) * dc
->wndExtX
/ dc
->vportExtX
);
2606 size
->cy
= abs((pfo
->fs
->ascent
+ pfo
->fs
->descent
) *
2607 dc
->wndExtY
/ dc
->vportExtY
);
2611 float x
= 0.0, y
= 0.0;
2612 for(i
= 0; i
< count
; i
++) {
2613 x
+= pfo
->fs
->per_char
?
2614 pfo
->fs
->per_char
[str
[i
] - pfo
->fs
->min_char_or_byte2
].attributes
:
2615 pfo
->fs
->min_bounds
.attributes
;
2617 y
= pfo
->lpX11Trans
->RAW_ASCENT
+ pfo
->lpX11Trans
->RAW_DESCENT
;
2618 TRACE(font
, "x = %f y = %f\n", x
, y
);
2619 x
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2620 y
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2621 size
->cx
= fabsf((x
+ dc
->w
.breakRem
+ count
* dc
->w
.charExtra
) *
2622 dc
->wndExtX
/ dc
->vportExtX
);
2623 size
->cy
= fabsf(y
* dc
->wndExtY
/ dc
->vportExtY
);
2631 /***********************************************************************
2632 * X11DRV_GetTextMetrics
2634 BOOL
X11DRV_GetTextMetrics(DC
*dc
, TEXTMETRICA
*metrics
)
2636 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2638 if( CHECK_PFONT(physDev
->font
) )
2640 fontObject
* pfo
= __PFONT(physDev
->font
);
2641 XFONT_GetTextMetric( pfo
, metrics
);
2649 /***********************************************************************
2650 * X11DRV_GetCharWidth
2652 BOOL
X11DRV_GetCharWidth( DC
*dc
, UINT firstChar
, UINT lastChar
,
2655 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2656 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2662 if (pfo
->fs
->per_char
== NULL
)
2663 for (i
= firstChar
; i
<= lastChar
; i
++)
2665 *buffer
++ = pfo
->fs
->min_bounds
.attributes
*
2666 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2668 *buffer
++ = pfo
->fs
->min_bounds
.width
;
2671 XCharStruct
*cs
, *def
;
2672 static XCharStruct __null_char
= { 0, 0, 0, 0, 0, 0 };
2674 CI_GET_CHAR_INFO(pfo
->fs
, pfo
->fs
->default_char
, &__null_char
,
2677 for (i
= firstChar
; i
<= lastChar
; i
++)
2679 if (i
>= pfo
->fs
->min_char_or_byte2
&&
2680 i
<= pfo
->fs
->max_char_or_byte2
)
2682 cs
= &pfo
->fs
->per_char
[(i
- pfo
->fs
->min_char_or_byte2
)];
2683 if (CI_NONEXISTCHAR(cs
)) cs
= def
;
2686 *buffer
++ = MAX(cs
->attributes
, 0) *
2687 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2689 *buffer
++ = MAX(cs
->width
, 0 );
2698 #endif /* !defined(X_DISPLAY_MISSING) */
2700 /***********************************************************************
2702 * Font Resource API *
2704 ***********************************************************************/
2705 /***********************************************************************
2706 * AddFontResource16 (GDI.119)
2708 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
2710 * FIXME: Load header and find the best-matching font in the fontList;
2711 * fixup dfPoints if all metrics are identical, otherwise create
2712 * new fontAlias. When soft font support is ready this will
2713 * simply create a new fontResource ('filename' will go into
2714 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
2717 INT16 WINAPI
AddFontResource16( LPCSTR filename
)
2719 return AddFontResourceA( filename
);
2723 /***********************************************************************
2724 * AddFontResource32A (GDI32.2)
2726 INT WINAPI
AddFontResourceA( LPCSTR str
)
2728 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2733 /***********************************************************************
2734 * AddFontResource32W (GDI32.4)
2736 INT WINAPI
AddFontResourceW( LPCWSTR str
)
2738 FIXME(font
, "(%s): stub\n", debugres_w(str
) );
2742 /***********************************************************************
2743 * RemoveFontResource16 (GDI.136)
2745 BOOL16 WINAPI
RemoveFontResource16( SEGPTR str
)
2747 FIXME(font
, "(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str
)));
2752 /***********************************************************************
2753 * RemoveFontResource32A (GDI32.284)
2755 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
2757 /* This is how it should look like */
2759 fontResource** ppfr;
2760 BOOL32 retVal = FALSE;
2762 EnterCriticalSection( &crtsc_fonts_X11 );
2763 for( ppfr = &fontList; *ppfr; ppfr = &(*ppfr)->next )
2764 if( !strcasecmp( (*ppfr)->lfFaceName, str ) )
2766 if(((*ppfr)->fr_flags & (FR_SOFTFONT | FR_SOFTRESOURCE)) &&
2767 (*ppfr)->hOwnerProcess == GetCurrentProcess() )
2769 if( (*ppfr)->fo_count )
2770 (*ppfr)->fr_flags |= FR_REMOVED;
2772 XFONT_RemoveFontResource( ppfr );
2776 LeaveCriticalSection( &crtsc_fontList );
2779 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2784 /***********************************************************************
2785 * RemoveFontResource32W (GDI32.286)
2787 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
2789 FIXME(font
, "(%s): stub\n", debugres_w(str
) );