2 * X11 physical font objects
4 * Copyright 1997 Alex Korobka
6 * TODO: Mapping algorithm tweaks, FO_SYNTH_... flags (ExtTextOut() will
7 * have to be changed for that), dynamic font loading (FreeType).
16 #include <sys/types.h>
20 #include <X11/Xatom.h>
29 #define X_PFONT_MAGIC (0xFADE0000)
30 #define X_FMC_MAGIC (0x0000CAFE)
32 #define MAX_FONT_FAMILIES 128
33 #define MAX_LFD_LENGTH 256
35 #define MAX_FONT_SIZE 5000 /* Max size in pixels */
37 #define REMOVE_SUBSETS 1
38 #define UNMARK_SUBSETS 0
40 #define DEF_SCALABLE_HEIGHT 24
41 #define DEF_SCALABLE_DP 240
43 #define FF_FAMILY (FF_MODERN | FF_SWISS | FF_ROMAN | FF_DECORATIVE | FF_SCRIPT)
45 typedef struct __fontAlias
49 struct __fontAlias
* next
;
58 /* Font alias table - these 2 aliases are always present */
59 /* CHANGING THE FIRST TWO WILL BREAK XFONT_BuildDefaultAliases! */
61 static fontAlias __aliasTable
[2] = {
62 { NULL
, "Helv", &__aliasTable
[1] },
63 { NULL
, "Tms Rmn", NULL
}
66 static fontAlias
*aliasTable
= __aliasTable
;
68 /* Optional built-in aliases, they are installed only when X
69 * cannot supply us with original MS fonts */
70 /* CHANGING THE FIRST TWO WILL BREAK XFONT_BuildDefaultAliases! */
72 static int faTemplateNum
= 4;
73 static aliasTemplate faTemplate
[4] = {
74 { NULL
, "MS Sans Serif" },
76 { "-adobe-times-", "Times New Roman" },
77 { "-adobe-helvetica-", "Arial" }
80 UINT16 XTextCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
|
81 TC_CP_STROKE
| TC_CR_ANY
|
82 TC_SA_DOUBLE
| TC_SA_INTEGER
| TC_SA_CONTIN
|
83 TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
85 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
87 static const char* INIWinePrefix
= "/.wine";
88 static const char* INIFontMetrics
= "/.cachedmetrics";
89 static const char* INIFontSection
= "fonts";
90 static const char* INISubSection
= "Alias";
91 static const char* INIDefault
= "Default";
92 static const char* INIDefaultFixed
= "DefaultFixed";
93 static const char* INIResolution
= "Resolution";
94 static const char* INIGlobalMetrics
= "FontMetrics";
95 static const char* INIDefaultSerif
= "DefaultSerif";
96 static const char* INIDefaultSansSerif
= "DefaultSansSerif";
98 static const char* LFDSeparator
= "*-";
99 static const char* MSEncoding
= "microsoft-";
100 static const char* iso8859Encoding
= "iso8859-";
101 static const char* iso646Encoding
= "iso646.1991-";
102 static const char* ansiEncoding
= "ansi-";
103 static unsigned DefResolution
= 0;
105 static fontResource
* fontList
= NULL
;
106 static fontObject
* fontCache
= NULL
; /* array */
107 static int fontCacheSize
= FONTCACHE
;
108 static int fontLF
= -1, fontMRU
= -1; /* last free, most recently used */
110 #define __PFONT(pFont) ( fontCache + ((UINT32)(pFont) & 0x0000FFFF) )
111 #define CHECK_PFONT(pFont) ( (((UINT32)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
112 (((UINT32)(pFont) & 0x0000FFFF) < fontCacheSize) )
114 static INT32
XFONT_IsSubset(fontInfo
*, fontInfo
*);
115 static void XFONT_CheckFIList(fontResource
*, fontInfo
*, int subset_action
);
116 static void XFONT_GrowFreeList(int start
, int end
);
119 static Atom RAW_ASCENT
;
120 static Atom RAW_DESCENT
;
122 /***********************************************************************
123 * Helper macros from X distribution
126 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
127 (((cs)->rbearing|(cs)->lbearing| \
128 (cs)->ascent|(cs)->descent) == 0))
130 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
133 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
134 if (fs->per_char == NULL) { \
135 cs = &fs->min_bounds; \
137 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
138 if (CI_NONEXISTCHAR(cs)) cs = def; \
143 #define CI_GET_DEFAULT_INFO(fs,cs) \
144 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
146 /***********************************************************************
149 static UINT16
__lfCheckSum( LPLOGFONT16 plf
)
151 CHAR font
[LF_FACESIZE
];
155 #define ptr ((UINT16*)plf)
156 for( i
= 0; i
< 9; i
++ ) checksum
^= *ptr
++;
159 #define ptr ((CHAR*)plf)
160 do { font
[i
++] = tolower(*ptr
++); } while (( i
< LF_FACESIZE
) && (*ptr
) && (*ptr
!=' '));
161 for( ptr
= font
, i
>>= 1; i
> 0; i
-- )
163 #define ptr ((UINT16*)plf)
169 static UINT16
__genericCheckSum( const void *ptr
, int size
)
171 unsigned int checksum
= 0;
172 const char *p
= (const char *)ptr
;
174 checksum
^= (checksum
<< 3) + (checksum
>> 29) + *p
++;
176 return checksum
& 0xffff;
179 /*************************************************************************
180 * LFD parse/compose routines
182 static char* LFD_Advance(LPSTR lpFont
, UINT16 uParmsNo
)
187 for( ; j
< uParmsNo
&& *lpch
; lpch
++ ) if( *lpch
== LFDSeparator
[1] ) j
++;
191 static void LFD_GetWeight( fontInfo
* fi
, LPSTR lpStr
, int j
)
193 if( j
== 1 && *lpStr
== '0' )
194 fi
->fi_flags
|= FI_POLYWEIGHT
;
197 if( !strncasecmp( "bold", lpStr
, 4) )
198 fi
->df
.dfWeight
= FW_BOLD
;
199 else if( !strncasecmp( "demi", lpStr
, 4) )
201 fi
->fi_flags
|= FI_FW_DEMI
;
202 fi
->df
.dfWeight
= FW_DEMIBOLD
;
204 else if( !strncasecmp( "book", lpStr
, 4) )
206 fi
->fi_flags
|= FI_FW_BOOK
;
207 fi
->df
.dfWeight
= FW_REGULAR
;
212 if( !strncasecmp( "light", lpStr
, 5) )
213 fi
->df
.dfWeight
= FW_LIGHT
;
214 else if( !strncasecmp( "black", lpStr
, 5) )
215 fi
->df
.dfWeight
= FW_BLACK
;
217 else if( j
== 6 && !strncasecmp( "medium", lpStr
, 6) )
218 fi
->df
.dfWeight
= FW_REGULAR
;
219 else if( j
== 8 && !strncasecmp( "demibold", lpStr
, 8) )
220 fi
->df
.dfWeight
= FW_DEMIBOLD
;
222 fi
->df
.dfWeight
= FW_DONTCARE
; /* FIXME: try to get something
223 * from the weight property */
226 static int LFD_GetSlant( fontInfo
* fi
, LPSTR lpStr
, int l
)
230 switch( tolower( *lpStr
) )
232 case '0': fi
->fi_flags
|= FI_POLYSLANT
; /* haven't seen this one yet */
234 case 'r': fi
->df
.dfItalic
= 0;
237 fi
->fi_flags
|= FI_OBLIQUE
;
238 case 'i': fi
->df
.dfItalic
= 1;
246 /*************************************************************************
249 * Fill in some fields in the fontInfo struct.
251 static int LFD_InitFontInfo( fontInfo
* fi
, LPSTR lpstr
)
254 int i
, j
, dec_style_check
, scalability
;
257 memset(fi
, 0, sizeof(fontInfo
) );
260 lpch
= LFD_Advance( lpstr
, 1);
261 if( !*lpch
) return FALSE
;
262 j
= lpch
- lpstr
- 1;
263 LFD_GetWeight( fi
, lpstr
, j
);
266 lpch
= LFD_Advance( lpstr
= lpch
, 1);
267 if( !*lpch
) return FALSE
;
268 j
= lpch
- lpstr
- 1;
269 dec_style_check
= LFD_GetSlant( fi
, lpstr
, j
);
272 lpch
= LFD_Advance( lpstr
= lpch
, 1);
273 if( !*lpch
) return FALSE
;
274 if( strncasecmp( "normal", lpstr
, 6) ) /* XXX 'narrow', 'condensed', etc... */
275 dec_style_check
= TRUE
;
277 fi
->fi_flags
|= FI_NORMAL
;
280 lpch
= LFD_Advance( lpstr
= lpch
, 1);
281 if( !*lpch
) return FALSE
;
282 j
= lpch
- lpstr
- 1;
283 if( j
> 3 ) /* find out is there "sans" or "script" */
288 if( strstr(lpstr
, "sans") )
290 fi
->df
.dfPitchAndFamily
|= FF_SWISS
;
293 if( strstr(lpstr
, "script") )
295 fi
->df
.dfPitchAndFamily
|= FF_SCRIPT
;
298 if( !j
&& dec_style_check
)
299 fi
->df
.dfPitchAndFamily
|= FF_DECORATIVE
;
300 *(lpch
- 1) = LFDSeparator
[1];
303 /* pixel height, decipoint height, and res_x */
305 for( i
= scalability
= 0; i
< 3; i
++ )
307 lpch
= LFD_Advance( lpstr
= lpch
, 1);
308 if( !*lpch
) return FALSE
;
309 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
312 if( !(tmp
[i
] = atoi(lpstr
)) ) scalability
++;
313 *(lpch
- 1) = LFDSeparator
[1];
315 if( scalability
== 3 ) /* Type1 */
317 fi
->fi_flags
|= FI_SCALABLE
;
318 fi
->lfd_height
= DEF_SCALABLE_HEIGHT
; fi
->lfd_decipoints
= DEF_SCALABLE_DP
;
319 fi
->lfd_resolution
= DefResolution
;
321 else if( scalability
== 0 ) /* Bitmap */
323 fi
->lfd_height
= tmp
[0]; fi
->lfd_decipoints
= tmp
[1];
324 fi
->lfd_resolution
= tmp
[2];
326 else return FALSE
; /* #$%^!!! X11R6 mutant garbage */
328 /* res_y - skip, spacing - */
329 lpstr
= LFD_Advance( lpch
, 1);
332 case '\0': return FALSE
;
334 case 'p': fi
->fi_flags
|= FI_VARIABLEPITCH
;
336 case 'c': fi
->df
.dfPitchAndFamily
|= FF_MODERN
;
337 fi
->fi_flags
|= FI_FIXEDEX
;
339 case 'm': fi
->fi_flags
|= FI_FIXEDPITCH
;
342 fi
->df
.dfPitchAndFamily
|= DEFAULT_PITCH
| FF_DONTCARE
;
344 lpstr
= LFD_Advance(lpstr
, 1);
345 if( !*lpstr
) return FALSE
;
347 /* average width - */
348 lpch
= LFD_Advance( lpstr
, 1);
349 if( !*lpch
) return FALSE
;
350 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
352 if( !(fi
->lfd_width
= atoi(lpstr
)) && !scalability
) return FALSE
;
353 *(lpch
- 1) = LFDSeparator
[1];
355 /* charset registry, charset encoding - */
356 if( strstr(lpch
, "jisx") ||
357 strstr(lpch
, "ksc") ||
358 strstr(lpch
, "gb2312") ||
359 strstr(lpch
, "big5") ||
360 strstr(lpch
, "unicode") ) return FALSE
; /* 2-byte stuff */
362 fi
->df
.dfCharSet
= ANSI_CHARSET
;
363 if( strstr(lpch
, iso8859Encoding
) ) {
364 fi
->fi_flags
|= FI_ENC_ISO8859
;
365 if( strstr(lpch
, "iso8859-15") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
366 else if( strstr(lpch
, "iso8859-11") ) fi
->df
.dfCharSet
= THAI_CHARSET
;
367 else if( strstr(lpch
, "iso8859-10") ) fi
->df
.dfCharSet
= BALTIC_CHARSET
;
368 else if( strstr(lpch
, "iso8859-9") ) fi
->df
.dfCharSet
= TURKISH_CHARSET
;
369 else if( strstr(lpch
, "iso8859-8") ) fi
->df
.dfCharSet
= HEBREW_CHARSET
;
370 else if( strstr(lpch
, "iso8859-7") ) fi
->df
.dfCharSet
= GREEK_CHARSET
;
371 else if( strstr(lpch
, "iso8859-6") ) fi
->df
.dfCharSet
= ARABIC_CHARSET
;
372 else if( strstr(lpch
, "iso8859-5") ) fi
->df
.dfCharSet
= RUSSIAN_CHARSET
;
373 else if( strstr(lpch
, "iso8859-4") ) fi
->df
.dfCharSet
= ISO4_CHARSET
;
374 else if( strstr(lpch
, "iso8859-3") ) fi
->df
.dfCharSet
= ISO3_CHARSET
;
375 else if( strstr(lpch
, "iso8859-2") ) fi
->df
.dfCharSet
= EE_CHARSET
;
376 else if( strstr(lpch
, "iso8859-1") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
377 else fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
378 } else if( strstr(lpch
, iso646Encoding
) ) {
379 fi
->fi_flags
|= FI_ENC_ISO646
;
380 } else if( strstr(lpch
, ansiEncoding
) ) { /* fnt2bdf produces -ansi-0 LFD */
381 fi
->fi_flags
|= FI_ENC_ANSI
;
382 } else { /* ... and -microsoft-cp125x */
384 fi
->df
.dfCharSet
= OEM_CHARSET
;
385 if( !strncasecmp(lpch
, "microsoft-", 10) ) {
386 fi
->fi_flags
|= FI_ENC_MSCODEPAGE
;
387 if( strstr(lpch
, "-cp1250") ) fi
->df
.dfCharSet
= EE_CHARSET
;
388 else if( strstr(lpch
, "-cp1251") ) fi
->df
.dfCharSet
= RUSSIAN_CHARSET
;
389 else if( strstr(lpch
, "-cp1252") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
390 else if( strstr(lpch
, "-cp1253") ) fi
->df
.dfCharSet
= GREEK_CHARSET
;
391 else if( strstr(lpch
, "-cp1254") ) fi
->df
.dfCharSet
= TURKISH_CHARSET
;
392 else if( strstr(lpch
, "-cp1255") ) fi
->df
.dfCharSet
= HEBREW_CHARSET
;
393 else if( strstr(lpch
, "-cp1256") ) fi
->df
.dfCharSet
= ARABIC_CHARSET
;
394 else if( strstr(lpch
, "-cp1257") ) fi
->df
.dfCharSet
= BALTIC_CHARSET
;
395 else if( strstr(lpch
, "-fontspecific") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
396 else if( strstr(lpch
, "-symbol") ) fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
397 else fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
398 } else if( !strncasecmp(lpch
, "koi8-", 5) ) {
399 fi
->df
.dfCharSet
= KOI8_CHARSET
;
400 } else if( !strncasecmp(lpch
, "viscii", 6) ) {
401 fi
->fi_flags
|= FI_ENC_ISO8859
;
402 fi
->df
.dfCharSet
= VISCII_CHARSET
;
403 } else if( !strncasecmp(lpch
, "tcvn-", 5) ) {
404 fi
->df
.dfCharSet
= TCVN_CHARSET
;
405 } else if( !strncasecmp(lpch
, "tis620", 6) ) {
406 fi
->fi_flags
|= FI_ENC_ISO8859
;
407 fi
->df
.dfCharSet
= THAI_CHARSET
;
408 } else if( !strncasecmp(lpch
, "ascii", 5) ) {
409 fi
->fi_flags
|= FI_ENC_ISO646
;
410 fi
->df
.dfCharSet
= ANSI_CHARSET
;
411 } else if( strstr(lpch
, "fontspecific") ||
412 strstr(lpch
, "microsoft-symbol") ) {
413 fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
420 /*************************************************************************
423 static BOOL32
LFD_ComposeLFD( fontObject
* fo
,
424 INT32 height
, LPSTR lpLFD
, UINT32 uRelax
)
426 int h
, w
, ch
, point
= 0;
429 char h_string
[64], point_string
[64];
431 *(lpLFD
+MAX_LFD_LENGTH
-1)=0;
432 lstrcpy32A( lpLFD
, fo
->fr
->resource
);
435 switch( fo
->fi
->df
.dfWeight
)
438 strcat( lpLFD
, "bold" ); break;
440 if( fo
->fi
->fi_flags
& FI_FW_BOOK
)
441 strcat( lpLFD
, "book" );
443 strcat( lpLFD
, "medium" );
446 strcat( lpLFD
, "demi" );
447 if( !( fo
->fi
->fi_flags
& FI_FW_DEMI
) )
448 strcat ( lpLFD
, "bold" );
451 strcat( lpLFD
, "black" ); break;
453 strcat( lpLFD
, "light" ); break;
455 strcat( lpLFD
, "*" );
459 if( fo
->fi
->df
.dfItalic
)
460 if( fo
->fi
->fi_flags
& FI_OBLIQUE
)
461 strcat( lpLFD
, "-o" );
463 strcat( lpLFD
, "-i" );
465 strcat( lpLFD
, (uRelax
< 6) ? "-r" : "-*" );
467 /* add width style and skip serifs */
468 if( fo
->fi
->fi_flags
& FI_NORMAL
)
469 strcat( lpLFD
, "-normal-*-");
471 strcat( lpLFD
, "-*-*-" );
473 /* add pixelheight, pointheight, and resolution
475 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
477 if( fo
->fo_flags
& FO_SYNTH_HEIGHT
) h
= fo
->fi
->lfd_height
;
478 else h
= (fo
->fi
->lfd_height
* height
) / fo
->fi
->df
.dfPixHeight
;
480 if( XTextCaps
& TC_SF_X_YINDEP
)
482 if( fo
->lf
.lfWidth
&& !(fo
->fo_flags
& FO_SYNTH_WIDTH
) )
483 point
= (fo
->fi
->lfd_decipoints
* fo
->lf
.lfWidth
) / fo
->fi
->df
.dfAvgWidth
;
485 if( fo
->fi
->fi_flags
& FI_SCALABLE
) /* adjust h/w ratio */
486 point
= h
* 72 * 10 / fo
->fi
->lfd_resolution
;
489 /* handle rotated fonts */
490 if (fo
->lf
.lfEscapement
) {
491 /* escapement is in tenths of degrees, theta is in radians */
492 double theta
= M_PI
*fo
->lf
.lfEscapement
/1800.;
493 double h_matrix
[4] = {h
*cos(theta
), h
*sin(theta
), -h
*sin(theta
), h
*cos(theta
)};
494 double point_matrix
[4] = {point
*cos(theta
), point
*sin(theta
), -point
*sin(theta
), point
*cos(theta
)};
496 sprintf(h_string
, "[%+f%+f%+f%+f]", h_matrix
[0], h_matrix
[1], h_matrix
[2], h_matrix
[3]);
497 sprintf(point_string
, "[%+f%+f%+f%+f]", point_matrix
[0], point_matrix
[1], point_matrix
[2], point_matrix
[3]);
498 while ((s
= strchr(h_string
, '-'))) *s
='~';
499 while ((s
= strchr(point_string
, '-'))) *s
='~';
501 sprintf(h_string
, "%d", h
);
502 sprintf(point_string
, "%d", point
);
506 /* spacing and width */
508 if( fo
->fi
->fi_flags
& FI_FIXEDPITCH
)
509 w
= ( fo
->fi
->fi_flags
& FI_FIXEDEX
) ? 'c' : 'm';
511 w
= ( fo
->fi
->fi_flags
& FI_VARIABLEPITCH
) ? 'p' : LFDSeparator
[0];
515 #define CHRS_CASE1(charset) case 0: \
519 case 12: sprintf(lpEncoding, charset ); break;
520 #define CHRS_CASE2(charset) case 1: \
524 case 13: sprintf(lpEncoding, charset ); break;
525 #define CHRS_CASE3(charset) case 2: \
529 case 14: sprintf(lpEncoding, charset ); break;
530 #define CHRS_DEF(charset) default: sprintf(lpEncoding, charset ); break;
532 if( fo
->fi
->df
.dfCharSet
== ANSI_CHARSET
)
534 if( fo
->fi
->fi_flags
& FI_ENC_ISO8859
)
536 CHRS_CASE1( "iso8859-1" );
537 CHRS_CASE2( "iso8859-1" );
538 CHRS_CASE3( "iso8859-15" );
539 CHRS_DEF( "iso8859-*" );
541 else if( fo
->fi
->fi_flags
& FI_ENC_ISO646
)
543 CHRS_CASE1( "ascii-0" );
544 CHRS_DEF( "iso8859-1" );
546 else if( fo
->fi
->fi_flags
& FI_ENC_MSCODEPAGE
)
548 CHRS_CASE1( "microsoft-cp1252" );
549 CHRS_CASE2( "microsoft-fontspecific" );
550 CHRS_CASE3( "microsoft-cp125*" );
551 CHRS_DEF( "microsoft-*" );
555 CHRS_CASE1( "ansi-0" );
556 CHRS_CASE2( "microsoft-125*" );
557 CHRS_CASE3( "microsoft-*");
558 CHRS_DEF( "iso8859-*" );
561 else if( fo
->fi
->fi_flags
& FI_ENC_MSCODEPAGE
)
563 switch (fo
->fi
->df
.dfCharSet
) {
566 CHRS_CASE1( "microsoft-1250" );
567 CHRS_CASE2( "iso8859-2" );
568 CHRS_DEF( "iso8859-*" );
570 case RUSSIAN_CHARSET
:
572 CHRS_CASE1( "microsoft-1251" );
573 CHRS_CASE2( "iso8859-5" );
574 CHRS_CASE3( "koi8-*" );
575 CHRS_DEF( "iso8859-*" );
579 CHRS_CASE1( "microsoft-1252" );
580 CHRS_CASE2( "iso8859-1" );
581 CHRS_CASE3( "iso8859-15" );
582 CHRS_DEF( "iso8859-*" );
586 CHRS_CASE1( "microsoft-1253" );
587 CHRS_CASE2( "iso8859-7" );
588 CHRS_DEF( "iso8859-*" );
590 case TURKISH_CHARSET
:
592 CHRS_CASE1( "microsoft-1254" );
593 CHRS_CASE2( "iso8859-9" );
594 CHRS_DEF( "iso8859-*" );
598 CHRS_CASE1( "microsoft-1255" );
599 CHRS_CASE2( "iso8859-8" );
600 CHRS_DEF( "iso8859-*" );
604 CHRS_CASE1( "microsoft-1256" );
605 CHRS_CASE2( "iso8859-6" );
606 CHRS_DEF( "iso8859-*" );
610 CHRS_CASE1( "microsoft-1257" );
611 CHRS_CASE2( "iso8859-10" );
612 CHRS_CASE3( "iso8859-15" );
613 CHRS_DEF( "iso8859-*" );
617 CHRS_CASE1( "iso8859-11" );
618 CHRS_CASE2( "tis620*" );
619 CHRS_DEF( "iso8859-*" );
623 CHRS_CASE1( "viscii1.1-1" );
624 CHRS_CASE2( "viscii*" );
625 CHRS_DEF( "iso8859-*" );
629 CHRS_CASE1( "tcvn-0" );
630 CHRS_CASE2( "tcvn*" );
631 CHRS_DEF( "iso8859-*" );
635 CHRS_CASE1( "koi8-ru" );
636 CHRS_CASE2( "koi8-r" );
637 CHRS_CASE3( "koi8-*" );
638 CHRS_DEF( "iso8859-*" );
642 CHRS_CASE1( "iso8859-3" );
643 CHRS_DEF( "iso8859-*" );
647 CHRS_CASE1( "iso8859-4" );
648 CHRS_DEF( "iso8859-*" );
652 CHRS_CASE1( "microsoft-symbol" );
653 CHRS_DEF( "microsoft-fontspecific" );
659 CHRS_CASE1( "*-fontspecific" );
660 CHRS_CASE2( "*-symbol" );
661 CHRS_DEF( "*-*" ); /* whatever */
665 lpch
= lpLFD
+ lstrlen32A(lpLFD
);
666 ch
= (fo
->fi
->fi_flags
& FI_SCALABLE
) ? '0' : LFDSeparator
[0];
670 /* RealizeFont() will call us repeatedly with increasing uRelax
671 * until XLoadFont() succeeds. */
678 sprintf( lpch
, "%s-%s-%i-%c-%c-*-%s", h_string
,
680 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
688 case 6: /* 6-8 will have replaced an 'r' in slant by '*' */
691 sprintf( lpch
, "%s-*-%i-%c-%c-*-%s", h_string
,
692 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
698 sprintf( lpch
, "%s-*-%i-%c-*-*-%s",
699 h_string
, fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
705 sprintf( lpch
, "%i-*-%i-%c-*-*-%s", fo
->fi
->lfd_height
,
706 fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
710 sprintf( lpch
, "%i-*-*-*-*-*-%s", fo
->fi
->lfd_height
, lpEncoding
);
714 sprintf( lpch
, "%i-*-*-*-*-*-*-*", fo
->fi
->lfd_height
);
717 /* to avoid an infinite loop; those will allways match */
719 sprintf( lpLFD
, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" );
722 sprintf( lpLFD
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" );
726 TRACE(font
,"\tLFD(uRelax=%d): %s\n", uRelax
, lpLFD
);
727 assert(*(lpLFD
+MAX_LFD_LENGTH
-1)==0); /* check if overwrittem */
732 /***********************************************************************
735 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
736 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
738 static BOOL32
XFONT_GetLeading( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
, INT32
*
739 pIL
, INT32
* pEL
, XFONTTRANS
*XFT
)
741 unsigned long height
;
742 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
743 unsigned max
= (unsigned char)pFI
->dfLastChar
;
744 BOOL32 bHaveCapHeight
= (pFI
->dfCharSet
== ANSI_CHARSET
&& 'X' >= min
&& 'X' <= max
);
749 Atom RAW_CAP_HEIGHT
= TSXInternAtom(display
, "RAW_CAP_HEIGHT", TRUE
);
750 if(TSXGetFontProperty(x_fs
, RAW_CAP_HEIGHT
, &height
))
752 (INT32
)(XFT
->pixelsize
/ 1000.0 * height
);
755 return bHaveCapHeight
&& x_fs
->per_char
;
758 if( TSXGetFontProperty(x_fs
, XA_CAP_HEIGHT
, &height
) == FALSE
)
762 height
= x_fs
->per_char
['X' - min
].ascent
;
764 if (x_fs
->ascent
>= x_fs
->max_bounds
.ascent
)
765 height
= x_fs
->max_bounds
.ascent
;
768 height
= x_fs
->ascent
;
770 *pEL
= x_fs
->max_bounds
.ascent
- height
;
773 height
= x_fs
->min_bounds
.ascent
;
776 *pIL
= x_fs
->ascent
- height
;
777 return (bHaveCapHeight
&& x_fs
->per_char
);
780 static INT32
XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
,
783 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
784 unsigned max
= (unsigned char)pFI
->dfLastChar
;
789 for( j
= 0, width
= 0, chars
= 0, max
-= min
; j
<= max
; j
++ )
790 if( !CI_NONEXISTCHAR(x_fs
->per_char
+ j
) )
793 width
+= x_fs
->per_char
[j
].width
;
795 width
+= x_fs
->per_char
[j
].attributes
*
796 XFT
->pixelsize
/ 1000.0;
799 return (width
/ chars
);
802 return x_fs
->min_bounds
.width
;
805 static INT32
XFONT_GetMaxCharWidth(fontObject
*pfo
)
807 unsigned min
= (unsigned char)pfo
->fs
->min_char_or_byte2
;
808 unsigned max
= (unsigned char)pfo
->fs
->max_char_or_byte2
;
811 return abs(pfo
->fs
->max_bounds
.width
);
813 if( pfo
->fs
->per_char
)
816 for( j
= 0, maxwidth
= 0, max
-= min
; j
<= max
; j
++ )
817 if( !CI_NONEXISTCHAR(pfo
->fs
->per_char
+ j
) )
818 if(maxwidth
< pfo
->fs
->per_char
[j
].attributes
)
819 maxwidth
= pfo
->fs
->per_char
[j
].attributes
;
821 maxwidth
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
824 return pfo
->foAvgCharWidth
;
827 /***********************************************************************
828 * XFONT_SetFontMetric
830 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
832 static void XFONT_SetFontMetric(fontInfo
* fi
, fontResource
* fr
, XFontStruct
* xfs
)
837 fi
->df
.dfFirstChar
= (BYTE
)(min
= xfs
->min_char_or_byte2
);
838 fi
->df
.dfLastChar
= (BYTE
)(max
= xfs
->max_char_or_byte2
);
840 fi
->df
.dfDefaultChar
= (BYTE
)xfs
->default_char
;
841 fi
->df
.dfBreakChar
= (BYTE
)(( ' ' < min
|| ' ' > max
) ? xfs
->default_char
: ' ');
843 fi
->df
.dfPixHeight
= (INT16
)((fi
->df
.dfAscent
= (INT16
)xfs
->ascent
) + xfs
->descent
);
844 fi
->df
.dfPixWidth
= (xfs
->per_char
) ? 0 : xfs
->min_bounds
.width
;
845 fi
->df
.dfMaxWidth
= (INT16
)abs(xfs
->max_bounds
.width
);
847 if( XFONT_GetLeading( &fi
->df
, xfs
, &il
, &el
, NULL
) )
848 fi
->df
.dfAvgWidth
= (INT16
)xfs
->per_char
['X' - min
].width
;
850 fi
->df
.dfAvgWidth
= (INT16
)XFONT_GetAvgCharWidth( &fi
->df
, xfs
, NULL
);
852 fi
->df
.dfInternalLeading
= (INT16
)il
;
853 fi
->df
.dfExternalLeading
= (INT16
)el
;
855 fi
->df
.dfPoints
= (INT16
)(((INT32
)(fi
->df
.dfPixHeight
-
856 fi
->df
.dfInternalLeading
) * 72 + (fi
->df
.dfVertRes
>> 1)) / fi
->df
.dfVertRes
);
858 if( xfs
->min_bounds
.width
!= xfs
->max_bounds
.width
)
859 fi
->df
.dfPitchAndFamily
|= TMPF_FIXED_PITCH
; /* au contraire! */
860 if( fi
->fi_flags
& FI_SCALABLE
)
862 fi
->df
.dfType
= DEVICE_FONTTYPE
;
863 fi
->df
.dfPitchAndFamily
|= TMPF_DEVICE
;
865 else if( fi
->fi_flags
& FI_TRUETYPE
)
866 fi
->df
.dfType
= TRUETYPE_FONTTYPE
;
868 fi
->df
.dfType
= RASTER_FONTTYPE
;
870 fi
->df
.dfFace
= fr
->lfFaceName
;
873 /***********************************************************************
874 * XFONT_GetTextMetric
876 static void XFONT_GetTextMetric( fontObject
* pfo
, LPTEXTMETRIC32A pTM
)
878 LPIFONTINFO16 pdf
= &pfo
->fi
->df
;
880 if( ! pfo
->lpX11Trans
) {
881 pTM
->tmAscent
= pfo
->fs
->ascent
;
882 pTM
->tmDescent
= pfo
->fs
->descent
;
884 pTM
->tmAscent
= pfo
->lpX11Trans
->ascent
;
885 pTM
->tmDescent
= pfo
->lpX11Trans
->descent
;
887 pTM
->tmHeight
= pTM
->tmAscent
+ pTM
->tmDescent
;
889 pTM
->tmAveCharWidth
= pfo
->foAvgCharWidth
;
890 pTM
->tmMaxCharWidth
= pfo
->foMaxCharWidth
;
892 pTM
->tmInternalLeading
= pfo
->foInternalLeading
;
893 pTM
->tmExternalLeading
= pdf
->dfExternalLeading
;
895 pTM
->tmStruckOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
)
896 ? 1 : pdf
->dfStrikeOut
;
897 pTM
->tmUnderlined
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
)
898 ? 1 : pdf
->dfUnderline
;
901 if( pfo
->fo_flags
& FO_SYNTH_ITALIC
)
903 pTM
->tmOverhang
+= pTM
->tmHeight
/3;
906 pTM
->tmItalic
= pdf
->dfItalic
;
908 pTM
->tmWeight
= pdf
->dfWeight
;
909 if( pfo
->fo_flags
& FO_SYNTH_BOLD
)
912 pTM
->tmWeight
+= 100;
915 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pdf
->dfFirstChar
;
917 pTM
->tmCharSet
= pdf
->dfCharSet
;
918 pTM
->tmPitchAndFamily
= pdf
->dfPitchAndFamily
;
920 pTM
->tmDigitizedAspectX
= pdf
->dfHorizRes
;
921 pTM
->tmDigitizedAspectY
= pdf
->dfVertRes
;
924 /***********************************************************************
925 * XFONT_GetFontMetric
927 * Retrieve font metric info (enumeration).
929 static UINT32
XFONT_GetFontMetric( fontInfo
* pfi
, LPENUMLOGFONTEX16 pLF
,
930 LPNEWTEXTMETRIC16 pTM
)
932 memset( pLF
, 0, sizeof(*pLF
) );
933 memset( pTM
, 0, sizeof(*pTM
) );
935 #define plf ((LPLOGFONT16)pLF)
936 plf
->lfHeight
= pTM
->tmHeight
= pfi
->df
.dfPixHeight
;
937 plf
->lfWidth
= pTM
->tmAveCharWidth
= pfi
->df
.dfAvgWidth
;
938 plf
->lfWeight
= pTM
->tmWeight
= pfi
->df
.dfWeight
;
939 plf
->lfItalic
= pTM
->tmItalic
= pfi
->df
.dfItalic
;
940 plf
->lfUnderline
= pTM
->tmUnderlined
= pfi
->df
.dfUnderline
;
941 plf
->lfStrikeOut
= pTM
->tmStruckOut
= pfi
->df
.dfStrikeOut
;
942 plf
->lfCharSet
= pTM
->tmCharSet
= pfi
->df
.dfCharSet
;
944 /* convert pitch values */
946 pTM
->tmPitchAndFamily
= pfi
->df
.dfPitchAndFamily
;
947 plf
->lfPitchAndFamily
= (pfi
->df
.dfPitchAndFamily
& 0xF1) + 1;
949 lstrcpyn32A( plf
->lfFaceName
, pfi
->df
.dfFace
, LF_FACESIZE
);
952 pTM
->tmAscent
= pfi
->df
.dfAscent
;
953 pTM
->tmDescent
= pTM
->tmHeight
- pTM
->tmAscent
;
954 pTM
->tmInternalLeading
= pfi
->df
.dfInternalLeading
;
955 pTM
->tmMaxCharWidth
= pfi
->df
.dfMaxWidth
;
956 pTM
->tmDigitizedAspectX
= pfi
->df
.dfHorizRes
;
957 pTM
->tmDigitizedAspectY
= pfi
->df
.dfVertRes
;
959 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pfi
->df
.dfFirstChar
;
961 /* return font type */
963 return pfi
->df
.dfType
;
967 /***********************************************************************
970 * dfPitchAndFamily flags for some common typefaces.
972 static BYTE
XFONT_FixupFlags( LPCSTR lfFaceName
)
974 switch( lfFaceName
[0] )
977 case 'H': if(!strcasecmp(lfFaceName
, "Helvetica") )
981 case 'C': if(!strcasecmp(lfFaceName
, "Courier") ||
982 !strcasecmp(lfFaceName
, "Charter") )
986 case 'P': if( !strcasecmp(lfFaceName
,"Palatino") )
990 case 'T': if(!strncasecmp(lfFaceName
, "Times", 5) )
994 case 'U': if(!strcasecmp(lfFaceName
, "Utopia") )
998 case 'Z': if(!strcasecmp(lfFaceName
, "Zapf Dingbats") )
999 return FF_DECORATIVE
;
1005 /***********************************************************************
1006 * XFONT_CheckResourceName
1008 static BOOL32
XFONT_CheckResourceName( LPSTR resource
, LPCSTR name
, INT32 n
)
1010 resource
= LFD_Advance( resource
, 2 );
1012 return (!strncasecmp( resource
, name
, n
));
1017 /***********************************************************************
1018 * XFONT_WindowsNames
1020 * Build generic Windows aliases for X font names.
1022 * -misc-fixed- -> "Fixed"
1023 * -sony-fixed- -> "Sony Fixed", etc...
1025 static void XFONT_WindowsNames( char* buffer
)
1027 fontResource
* fr
, *pfr
;
1031 const char* relocTable
[] = { INIDefaultFixed
, INIDefault
, NULL
};
1033 for( fr
= fontList
; fr
; fr
= fr
->next
)
1035 if( fr
->fr_flags
& FR_NAMESET
) continue; /* skip already assigned */
1037 lpstr
= LFD_Advance(fr
->resource
, 2);
1038 i
= LFD_Advance( lpstr
, 1 ) - lpstr
;
1040 for( pfr
= fontList
; pfr
!= fr
; pfr
= pfr
->next
)
1041 if( pfr
->fr_flags
& FR_NAMESET
)
1042 if( XFONT_CheckResourceName( pfr
->resource
, lpstr
, i
) )
1045 if( pfr
!= fr
) /* prepend vendor name */
1046 lpstr
= fr
->resource
+ 1;
1048 for( i
= 0, up
= 1, lpch
= fr
->lfFaceName
; *lpstr
&& i
< 32;
1049 lpch
++, lpstr
++, i
++ )
1051 if( *lpstr
== LFDSeparator
[1] || *lpstr
== ' ' )
1056 else if( isalpha(*lpstr
) && up
)
1058 *lpch
= toupper(*lpstr
);
1063 while (*(lpch
- 1) == ' ') *(--lpch
) = '\0';
1065 if( (bFamilyStyle
= XFONT_FixupFlags( fr
->lfFaceName
)) )
1068 for( fi
= fr
->fi
; fi
; fi
= fi
->next
)
1069 fi
->df
.dfPitchAndFamily
|= bFamilyStyle
;
1072 TRACE(font
,"typeface \'%s\'\n", fr
->lfFaceName
);
1074 fr
->fr_flags
|= FR_NAMESET
;
1077 for( up
= 0; relocTable
[up
]; up
++ )
1078 if( PROFILE_GetWineIniString( INIFontSection
, relocTable
[up
], "", buffer
, 128 ) )
1080 while( *buffer
&& isspace(*buffer
) ) buffer
++;
1081 for( fr
= NULL
, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1083 i
= strlen( pfr
->resource
);
1084 if( !strncasecmp( pfr
->resource
, buffer
, i
) )
1088 fr
->next
= pfr
->next
;
1089 pfr
->next
= fontList
;
1099 /***********************************************************************
1102 static fontAlias
* XFONT_CreateAlias( LPCSTR lpTypeFace
, LPCSTR lpAlias
)
1105 fontAlias
* pfa
= aliasTable
;
1109 /* check if we already got one */
1110 if( !strcasecmp( pfa
->faTypeFace
, lpAlias
) )
1112 TRACE(font
,"\tredundant alias '%s' -> '%s'\n",
1113 lpAlias
, lpTypeFace
);
1116 if( pfa
->next
) pfa
= pfa
->next
;
1120 j
= lstrlen32A(lpTypeFace
) + 1;
1121 pfa
->next
= HeapAlloc( SystemHeap
, 0, sizeof(fontAlias
) +
1122 j
+ lstrlen32A(lpAlias
) + 1 );
1123 if((pfa
= pfa
->next
))
1126 pfa
->faTypeFace
= (LPSTR
)(pfa
+ 1);
1127 lstrcpy32A( pfa
->faTypeFace
, lpTypeFace
);
1128 pfa
->faAlias
= pfa
->faTypeFace
+ j
;
1129 lstrcpy32A( pfa
->faAlias
, lpAlias
);
1131 TRACE(font
, "\tadded alias '%s' for %s\n", lpAlias
, lpTypeFace
);
1138 /***********************************************************************
1141 * Read user-defined aliases from wine.conf. Format is as follows
1143 * Alias# = [Windows font name],[LFD font name], <substitute original name>
1146 * Alias0 = Arial, -adobe-helvetica-
1147 * Alias1 = Times New Roman, -bitstream-courier-, 1
1150 * Note that from 081797 and on we have built-in alias templates that take
1151 * care of the necessary Windows typefaces.
1153 static void XFONT_LoadAliases( char** buffer
, int buf_size
)
1155 char* lpResource
, *lpAlias
;
1156 char subsection
[32];
1158 BOOL32 bHaveAlias
= TRUE
, bSubst
= FALSE
;
1160 if( buf_size
< 128 )
1161 *buffer
= HeapReAlloc(SystemHeap
, 0, *buffer
, 256 );
1164 if( j
< faTemplateNum
)
1166 /* built-in templates first */
1168 lpResource
= faTemplate
[j
].fatResource
;
1169 lpAlias
= faTemplate
[j
].fatAlias
;
1174 /* then WINE.CONF */
1176 wsprintf32A( subsection
, "%s%i", INISubSection
, i
++ );
1178 if( (bHaveAlias
= PROFILE_GetWineIniString( INIFontSection
,
1179 subsection
, "", *buffer
, 128 )) )
1182 while( isspace(*lpAlias
) ) lpAlias
++;
1183 lpResource
= PROFILE_GetStringItem( lpAlias
);
1184 bSubst
= (PROFILE_GetStringItem( lpResource
)) ? TRUE
: FALSE
;
1192 length
= strlen( lpAlias
);
1193 if( lpResource
&& length
)
1195 fontResource
* fr
, *frMatch
= NULL
;
1197 for (fr
= fontList
; fr
; fr
= fr
->next
)
1199 if( !strcasecmp( fr
->resource
, lpResource
) ) frMatch
= fr
;
1200 if( XFONT_CheckResourceName( fr
->resource
, lpAlias
, length
) )
1202 /* alias is not needed since the real font is present */
1203 frMatch
= NULL
; break;
1211 fontAlias
*pfa
, *prev
= NULL
;
1213 for(pfa
= aliasTable
; pfa
; pfa
= pfa
->next
)
1215 /* Remove lpAlias from aliasTable - we should free the old entry */
1216 if(!strcmp(lpAlias
, pfa
->faAlias
))
1219 prev
->next
= pfa
->next
;
1221 aliasTable
= pfa
->next
;
1224 /* Update any references to the substituted font in aliasTable */
1225 if(!strcmp(frMatch
->lfFaceName
,
1227 pfa
->faTypeFace
= HEAP_strdupA( SystemHeap
, 0,
1232 TRACE(font
, "\tsubstituted '%s' with %s\n",
1233 frMatch
->lfFaceName
, lpAlias
);
1235 lstrcpyn32A( frMatch
->lfFaceName
, lpAlias
, LF_FACESIZE
);
1236 frMatch
->fr_flags
|= FR_NAMESET
;
1240 /* create new entry in the alias table */
1241 XFONT_CreateAlias( frMatch
->lfFaceName
, lpAlias
);
1245 else ERR(font
, " malformed font alias '%s'\n", *buffer
);
1251 /***********************************************************************
1252 * XFONT_UserMetricsCache
1254 * Returns expanded name for the ~/.wine/.cachedmetrics file.
1256 static char* XFONT_UserMetricsCache( char* buffer
, int* buf_size
)
1260 pwd
= getpwuid(getuid());
1261 if( pwd
&& pwd
->pw_dir
)
1263 int i
= strlen( pwd
->pw_dir
) + strlen( INIWinePrefix
) +
1264 strlen( INIFontMetrics
) + 2;
1266 buffer
= (char*) HeapReAlloc( SystemHeap
, 0, buffer
, *buf_size
= i
);
1267 strcpy( buffer
, pwd
->pw_dir
);
1268 strcat( buffer
, INIWinePrefix
);
1269 strcat( buffer
, INIFontMetrics
);
1270 } else buffer
[0] = '\0';
1275 /***********************************************************************
1276 * XFONT_ReadCachedMetrics
1278 static BOOL32
XFONT_ReadCachedMetrics( int fd
, int res
, unsigned x_checksum
, int x_count
)
1285 /* read checksums */
1286 read( fd
, &u
, sizeof(unsigned) );
1287 read( fd
, &i
, sizeof(int) );
1289 if( u
== x_checksum
&& i
== x_count
)
1291 off_t length
, offset
= 3 * sizeof(int);
1293 /* read total size */
1294 read( fd
, &i
, sizeof(int) );
1295 length
= lseek( fd
, 0, SEEK_END
);
1297 if( length
== (i
+ offset
) )
1299 lseek( fd
, offset
, SEEK_SET
);
1300 fontList
= (fontResource
*)HeapAlloc( SystemHeap
, 0, i
);
1303 fontResource
* pfr
= fontList
;
1304 fontInfo
* pfi
= NULL
;
1306 TRACE(font
,"Reading cached font metrics:\n");
1308 read( fd
, fontList
, i
); /* read all metrics at once */
1309 while( offset
< length
)
1311 offset
+= sizeof(fontResource
) + sizeof(fontInfo
);
1312 pfr
->fi
= pfi
= (fontInfo
*)(pfr
+ 1);
1316 if( offset
> length
||
1317 (int)(pfi
->next
) != j
++ ) goto fail
;
1319 pfi
->df
.dfFace
= pfr
->lfFaceName
;
1320 pfi
->df
.dfHorizRes
= pfi
->df
.dfVertRes
= res
;
1321 pfi
->df
.dfPoints
= (INT16
)(((INT32
)(pfi
->df
.dfPixHeight
-
1322 pfi
->df
.dfInternalLeading
) * 72 + (res
>> 1)) / res
);
1323 pfi
->next
= pfi
+ 1;
1325 if( j
> pfr
->count
) break;
1328 offset
+= sizeof(fontInfo
);
1333 pfr
->next
= (fontResource
*)(pfi
+ 1);
1338 if( pfr
->next
== NULL
&&
1339 *(int*)(pfi
+ 1) == X_FMC_MAGIC
)
1341 /* read LFD stubs */
1342 char* lpch
= (char*)((int*)(pfi
+ 1) + 1);
1343 offset
+= sizeof(int);
1344 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1346 TRACE(font
,"\t%s, %i instances\n", lpch
, pfr
->count
);
1347 pfr
->resource
= lpch
;
1350 if( ++offset
> length
) goto fail
;
1351 if( !*lpch
++ ) break;
1361 if( fontList
) HeapFree( SystemHeap
, 0, fontList
);
1368 /***********************************************************************
1369 * XFONT_WriteCachedMetrics
1371 static BOOL32
XFONT_WriteCachedMetrics( int fd
, unsigned x_checksum
, int x_count
, int n_ff
)
1380 /* font metrics file:
1384 * +0008 total size to load
1385 * +000C prepackaged font metrics
1388 * +...x + 4 LFD stubs
1391 write( fd
, &x_checksum
, sizeof(unsigned) );
1392 write( fd
, &x_count
, sizeof(int) );
1394 for( j
= i
= 0, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1396 i
+= strlen( pfr
->resource
) + 1;
1399 i
+= n_ff
* sizeof(fontResource
) + j
* sizeof(fontInfo
) + sizeof(int);
1400 write( fd
, &i
, sizeof(int) );
1402 TRACE(font
,"Writing font cache:\n");
1404 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1408 TRACE(font
,"\t%s, %i instances\n", pfr
->resource
, pfr
->count
);
1410 i
= write( fd
, pfr
, sizeof(fontResource
) );
1411 if( i
== sizeof(fontResource
) )
1413 for( k
= 1, pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
1415 memcpy( &fi
, pfi
, sizeof(fi
) );
1417 fi
.df
.dfFace
= NULL
;
1418 fi
.next
= (fontInfo
*)k
; /* loader checks this */
1420 j
= write( fd
, &fi
, sizeof(fi
) );
1423 if( j
== sizeof(fontInfo
) ) continue;
1427 if( i
== sizeof(fontResource
) && j
== sizeof(fontInfo
) )
1429 i
= j
= X_FMC_MAGIC
;
1430 write( fd
, &i
, sizeof(int) );
1431 for( pfr
= fontList
; pfr
&& i
== j
; pfr
= pfr
->next
)
1433 i
= strlen( pfr
->resource
) + 1;
1434 j
= write( fd
, pfr
->resource
, i
);
1443 /***********************************************************************
1444 * XFONT_CheckIniSection
1446 * Examines wine.conf for old/invalid font entries and recommend changes to
1450 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1451 * Original implementation.
1453 static void XFONT_CheckIniCallback(char const *, char const *, void *);
1455 static char const *fontmsgprologue
=
1457 " The following entries in the [fonts] section of the wine.conf file are\n"
1458 " obsolete or invalid:\n";
1460 static char const *fontmsgepilogue
=
1461 " These entries should be eliminated or updated.\n"
1462 " See the documentation/fonts file for more information.\n";
1464 static int XFONT_CheckIniSection()
1468 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback
,
1471 MSG(fontmsgepilogue
);
1476 static void XFONT_CheckIniCallback(
1481 /* Ignore any keys that start with potential comment characters "'", '#',
1483 if(key
[0] == '\'' || key
[0] == '#' || key
[0] == ';' || key
[0] == '\0')
1486 /* Make sure this is a valid key */
1487 if((strncasecmp(key
, INISubSection
, 5) == 0) ||
1488 (strcasecmp( key
, INIDefault
) == 0) ||
1489 (strcasecmp( key
, INIDefaultFixed
) == 0) ||
1490 (strcasecmp( key
, INIGlobalMetrics
) == 0) ||
1491 (strcasecmp( key
, INIResolution
) == 0) ||
1492 (strcasecmp( key
, INIDefaultSerif
) == 0) ||
1493 (strcasecmp( key
, INIDefaultSansSerif
) ==0) )
1495 /* Valid key; make sure the value doesn't contain a wildcard */
1496 if(strchr(value
, '*')) {
1497 if(*(int *)found
== 0) {
1498 MSG(fontmsgprologue
);
1502 MSG(" %s=%s [no wildcards allowed]\n", key
, value
);
1506 /* Not a valid key */
1507 if(*(int *)found
== 0) {
1508 MSG(fontmsgprologue
);
1512 MSG(" %s=%s [obsolete]\n", key
, value
);
1518 /***********************************************************************
1519 * 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
1551 * Alias "Helv", and "Tms Rmn" to the DefaultSansSerif and DefaultSerif
1552 * fonts respectively. Create font alias templates for "MS Sans Serif"
1553 * and "MS Serif", also pointing to DefaultSansSerif and DefaultSerif.
1555 static int XFONT_BuildDefaultAliases( char** buffer
, int* buf_size
)
1558 aliasTemplate fatDefaultSerif
= { "-bitstream-charter-", "Charter" };
1559 aliasTemplate fatDefaultSansSerif
= { "-adobe-helvetica-", "Helvetica" };
1563 /* Make sure our buffer is big enough; update calling function's
1564 buf_size if we change it. */
1566 if( *buf_size
< 128 )
1568 *buffer
= HeapReAlloc( SystemHeap
, 0, *buffer
, 256 );
1572 /* Get the X11 name of the default serif font from the Wine INI file.
1573 (-bitstream-charter- is the default.) */
1575 PROFILE_GetWineIniString( INIFontSection
, INIDefaultSerif
,
1576 fatDefaultSerif
.fatResource
, *buffer
, 128 );
1578 /* Find the Windows typeface which corresponds to the X11 font. */
1580 for( fr
= fontList
; fr
; fr
= fr
->next
)
1581 if( !strcasecmp( fr
->resource
, *buffer
) ) break;
1583 /* Update the Alias Table entry for "Tms Rmn" with the default serif font's
1584 typeface. Update the Alias Template for "MS Serif" with the default
1585 serif font's X11 name. Note that this method leaves us dependant on
1586 the order of the Alias Table and the Alias Templates. Also, we don't
1587 check for or handle a situation in which -bitstream-charter- is not
1592 TRACE(font
, "Using \'%s\' as default serif font\n", fr
->lfFaceName
);
1593 aliasTable
[1].faTypeFace
= fr
->lfFaceName
;
1594 faTemplate
[1].fatResource
= fr
->resource
;
1598 WARN(font
, "No typeface found for \'%s\'; using \'%s\'\n", *buffer
,
1599 fatDefaultSerif
.fatAlias
);
1600 aliasTable
[1].faTypeFace
= fatDefaultSerif
.fatAlias
; /* Charter */
1601 faTemplate
[1].fatResource
= fatDefaultSerif
.fatResource
;
1604 /* Get the X11 name of the default sans serif font from the Wine INI file.
1605 (-adobe-helvetica- is the default.) */
1607 PROFILE_GetWineIniString (INIFontSection
, INIDefaultSansSerif
,
1608 fatDefaultSansSerif
.fatResource
, *buffer
, 128 );
1610 /* Find the Windows typeface which corresponds to the X11 font. */
1612 for( fr
= fontList
; fr
; fr
= fr
->next
)
1613 if ( !strcasecmp( fr
->resource
, *buffer
) ) break;
1615 /* Update the Alias Table entry for "Helv" with the default sans serif font's
1616 typeface. Update the Alias Template for "MS Sans Serif" with the
1617 default sans serif font's X11 name. Note that this method leaves us
1618 dependant on the order of the Alias Table and the Alias Templates.
1619 Also, we don't check for or handle a situation in which
1620 -adobe-helvetica- is not available. */
1624 TRACE(font
, "Using \'%s\' as default sans serif font\n", fr
->lfFaceName
);
1625 aliasTable
[0].faTypeFace
= fr
->lfFaceName
;
1626 faTemplate
[0].fatResource
= fr
->resource
;
1630 WARN(font
, "No typeface found for \'%s\'; using \'%s\'\n", *buffer
,
1631 fatDefaultSansSerif
.fatAlias
);
1632 aliasTable
[0].faTypeFace
= fatDefaultSansSerif
.fatAlias
; /* Helvetica */
1633 faTemplate
[0].fatResource
= fatDefaultSansSerif
.fatResource
;
1639 /***********************************************************************
1642 * Initialize font resource list and allocate font cache.
1644 BOOL32
X11DRV_FONT_Init( DeviceCaps
* pDevCaps
)
1647 fontResource
* fr
, *pfr
;
1649 unsigned x_checksum
;
1650 int i
, j
, res
, x_count
, fd
= -1, buf_size
= 0;
1651 char* lpstr
, *lpch
, *lpmetrics
, *buffer
;
1654 XFONT_CheckIniSection();
1656 res
= XFONT_GetPointResolution( pDevCaps
);
1658 x_pattern
= TSXListFonts(display
, "*", MAX_FONT_FAMILIES
* 16, &x_count
);
1660 TRACE(font
,"Font Mapper: initializing %i fonts [LPY=%i, XDR=%i, DR=%i]\n",
1661 x_count
, pDevCaps
->logPixelsY
, DefResolution
, res
);
1662 for( i
= x_checksum
= 0; i
< x_count
; i
++ )
1665 printf("%i\t: %s\n", i
, x_pattern
[i
] );
1668 j
= strlen( x_pattern
[i
] );
1669 if( j
) x_checksum
^= __genericCheckSum( x_pattern
[i
], j
);
1671 x_checksum
|= X_PFONT_MAGIC
;
1674 buffer
= HeapAlloc( SystemHeap
, 0, buf_size
);
1677 /* deal with systemwide font metrics cache */
1679 if( PROFILE_GetWineIniString( INIFontSection
, INIGlobalMetrics
, "", buffer
, 128 ) )
1680 fd
= open( buffer
, O_RDONLY
);
1682 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1685 buffer
= XFONT_UserMetricsCache( buffer
, &buf_size
);
1688 fd
= open( buffer
, O_RDONLY
);
1689 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1690 lpmetrics
= HEAP_strdupA( SystemHeap
, 0, buffer
); /* update later on */
1695 if( fontList
== NULL
) /* build metrics from scratch */
1700 for( i
= n_ff
= 0; i
< x_count
; i
++ )
1702 typeface
= lpch
= x_pattern
[i
];
1704 lpch
= LFD_Advance(typeface
, 3); /* extra '-' in the beginning */
1705 if( !*lpch
) continue;
1708 j
= lpch
- typeface
; /* resource name length */
1710 /* find a family to insert into */
1712 for( pfr
= NULL
, fr
= fontList
; fr
; fr
= fr
->next
)
1714 if( !strncasecmp(fr
->resource
, typeface
, j
) &&
1715 strlen(fr
->resource
) == j
) break;
1719 if( !fi
) fi
= (fontInfo
*) HeapAlloc(SystemHeap
, 0, sizeof(fontInfo
));
1721 if( !fr
) /* add new family */
1723 if( n_ff
>= MAX_FONT_FAMILIES
) break;
1724 if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1727 fr
= (fontResource
*) HeapAlloc(SystemHeap
, 0, sizeof(fontResource
));
1728 memset(fr
, 0, sizeof(fontResource
));
1729 fr
->resource
= (char*) HeapAlloc(SystemHeap
, 0, j
+ 1 );
1730 lstrcpyn32A( fr
->resource
, typeface
, j
+ 1 );
1732 TRACE(font
," family: %s\n", fr
->resource
);
1734 if( pfr
) pfr
->next
= fr
;
1737 else if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1739 /* check if we already have something better than "fi" */
1741 for( pfi
= fr
->fi
, j
= 0; pfi
&& j
<= 0; pfi
= pfi
->next
)
1742 if( (j
= XFONT_IsSubset( pfi
, fi
)) < 0 )
1743 pfi
->fi_flags
|= FI_SUBSET
; /* superseded by "fi" */
1744 if( j
> 0 ) continue;
1746 /* add new font instance "fi" to the "fr" font resource */
1748 if( fi
->fi_flags
& FI_SCALABLE
)
1750 /* set scalable font height to 24 to get an origin for extrapolation */
1752 j
= strlen(typeface
); j
+= 0x10;
1754 buffer
= (char*)HeapReAlloc( SystemHeap
, 0, buffer
, buf_size
= j
);
1756 lpch
= LFD_Advance(typeface
, 7);
1757 memcpy( buffer
, typeface
, (j
= lpch
- typeface
) );
1758 lpch
= LFD_Advance(lpch
, 4);
1759 sprintf( buffer
+ j
, "%d-%d-%d-*-%c-*-", fi
->lfd_height
,
1760 fi
->lfd_decipoints
, fi
->lfd_resolution
,
1761 (*lpch
== '-')?'*':*lpch
);
1762 lpch
= LFD_Advance(lpch
, 2);
1763 strcat( lpstr
= buffer
, lpch
);
1765 else lpstr
= typeface
;
1767 if( (x_fs
= TSXLoadQueryFont(display
, lpstr
)) )
1769 fi
->df
.dfHorizRes
= fi
->df
.dfVertRes
= res
;
1771 XFONT_SetFontMetric( fi
, fr
, x_fs
);
1772 TSXFreeFont( display
, x_fs
);
1774 TRACE(font
,"\t[% 2ipt] '%s'\n", fi
->df
.dfPoints
, typeface
);
1776 XFONT_CheckFIList( fr
, fi
, REMOVE_SUBSETS
);
1777 fi
= NULL
; /* preventing reuse */
1781 ERR(font
, "failed to load %s\n", lpstr
);
1783 XFONT_CheckFIList( fr
, fi
, UNMARK_SUBSETS
);
1787 if( lpmetrics
) /* update cached metrics */
1789 fd
= open( lpmetrics
, O_CREAT
| O_TRUNC
| O_RDWR
, 0644 ); /* -rw-r--r-- */
1790 if( XFONT_WriteCachedMetrics( fd
, x_checksum
, x_count
, n_ff
) == FALSE
)
1791 if( fd
) remove( lpmetrics
); /* couldn't write entire file */
1792 HeapFree( SystemHeap
, 0, lpmetrics
);
1796 if( fi
) HeapFree(SystemHeap
, 0, fi
);
1797 TSXFreeFontNames(x_pattern
);
1799 /* check if we're dealing with X11 R6 server */
1801 strcpy(buffer
, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1802 if( (x_fs
= TSXLoadQueryFont(display
, buffer
)) )
1804 XTextCaps
|= TC_SF_X_YINDEP
;
1805 TSXFreeFont(display
, x_fs
);
1808 XFONT_WindowsNames( buffer
);
1809 XFONT_BuildDefaultAliases( &buffer
, &buf_size
);
1810 XFONT_LoadAliases( &buffer
, buf_size
);
1811 HeapFree(SystemHeap
, 0, buffer
);
1814 /* fontList initialization is over, allocate X font cache */
1816 fontCache
= (fontObject
*) HeapAlloc(SystemHeap
, 0, fontCacheSize
* sizeof(fontObject
));
1817 XFONT_GrowFreeList(0, fontCacheSize
- 1);
1819 TRACE(font
,"done!\n");
1821 /* update text caps parameter */
1823 pDevCaps
->textCaps
= XTextCaps
;
1825 RAW_ASCENT
= TSXInternAtom(display
, "RAW_ASCENT", TRUE
);
1826 RAW_DESCENT
= TSXInternAtom(display
, "RAW_DESCENT", TRUE
);
1832 /***********************************************************************
1835 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1837 static INT32
XFONT_IsSubset(fontInfo
* match
, fontInfo
* fi
)
1841 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1843 m
= (BYTE
*)&fi
->df
.dfPixWidth
- (BYTE
*)&fi
->df
.dfItalic
;
1844 if( memcmp(&match
->df
.dfItalic
, &fi
->df
.dfItalic
, m
)) return 0;
1846 if( (!((fi
->fi_flags
& FI_SCALABLE
) + (match
->fi_flags
& FI_SCALABLE
))
1847 && fi
->lfd_height
!= match
->lfd_height
) ||
1848 (!((fi
->fi_flags
& FI_POLYWEIGHT
) + (match
->fi_flags
& FI_POLYWEIGHT
))
1849 && fi
->df
.dfWeight
!= match
->df
.dfWeight
) ) return 0;
1851 m
= (int)(match
->fi_flags
& (FI_POLYWEIGHT
| FI_SCALABLE
)) -
1852 (int)(fi
->fi_flags
& (FI_SCALABLE
| FI_POLYWEIGHT
));
1854 if( m
== (FI_POLYWEIGHT
- FI_SCALABLE
) ||
1855 m
== (FI_SCALABLE
- FI_POLYWEIGHT
) ) return 0; /* keep both */
1856 else if( m
>= 0 ) return 1; /* 'match' is better */
1858 return -1; /* 'fi' is better */
1861 /***********************************************************************
1864 * Compute the matching score between the logical font and the device font.
1866 * contributions from highest to lowest:
1870 * family flags (only when the facename is not present)
1872 * weight, italics, underlines, strikeouts
1874 * NOTE: you can experiment with different penalty weights to see what happens.
1875 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
1877 static UINT32
XFONT_Match( fontMatch
* pfm
)
1879 fontInfo
* pfi
= pfm
->pfi
; /* device font to match */
1880 LPLOGFONT16 plf
= pfm
->plf
; /* wanted logical font */
1882 BOOL32 bR6
= pfm
->flags
& FO_MATCH_XYINDEP
; /* from TextCaps */
1883 BOOL32 bScale
= pfi
->fi_flags
& FI_SCALABLE
;
1886 TRACE(font
,"\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi
->df
.dfPoints
,
1887 pfi
->df
.dfPixHeight
, pfi
->df
.dfAvgWidth
,
1888 (pfi
->df
.dfWeight
> 400) ? "Bold " : "Normal ",
1889 (pfi
->df
.dfItalic
) ? "Italic" : "" );
1893 if( plf
->lfCharSet
== DEFAULT_CHARSET
)
1895 if( (pfi
->df
.dfCharSet
!= ANSI_CHARSET
) && (pfi
->df
.dfCharSet
!=DEFAULT_CHARSET
) )
1898 else if (plf
->lfCharSet
!= pfi
->df
.dfCharSet
) penalty
+= 0x200;
1900 /* FIXME: Hack to demote symbols and nil fonts. Should take into
1901 account if a program ever actually asked for this type of
1903 if ( (strcmp(pfm
->pfr
->lfFaceName
,"Symbol")==0) || (strcmp(pfm
->pfr
->lfFaceName
,"Nil")==0) )
1904 penalty
+= 0x200; /* very stiff penality */
1906 /* TMPF_FIXED_PITCH means exactly the opposite */
1908 if( plf
->lfPitchAndFamily
& FIXED_PITCH
)
1910 if( pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) penalty
+= 0x100;
1912 else if( !(pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) ) penalty
+= 0x2;
1914 if( plf
->lfHeight
> 0 )
1915 d
= (h
= pfi
->df
.dfPixHeight
) - plf
->lfHeight
;
1916 else if( plf
->lfHeight
< -1 )
1917 d
= (h
= pfi
->df
.dfPoints
) + plf
->lfHeight
;
1920 if( d
&& plf
->lfHeight
)
1922 UINT16 height
= ( plf
->lfHeight
> 0 ) ? plf
->lfHeight
1923 : ((-plf
->lfHeight
* pfi
->df
.dfPixHeight
) / h
);
1924 if( bScale
) pfm
->height
= height
;
1925 else if( (plf
->lfQuality
!= PROOF_QUALITY
) && bR6
)
1927 if( d
> 0 ) /* do not shrink raster fonts */
1929 pfm
->height
= pfi
->df
.dfPixHeight
;
1930 penalty
+= (pfi
->df
.dfPixHeight
- height
) * 0x4;
1932 else /* expand only in integer multiples */
1934 pfm
->height
= height
- height
%pfi
->df
.dfPixHeight
;
1935 penalty
+= (height
- pfm
->height
+ 1) * height
/ pfi
->df
.dfPixHeight
;
1938 else /* can't be scaled at all */
1940 if( plf
->lfQuality
!= PROOF_QUALITY
) pfm
->flags
|= FO_SYNTH_HEIGHT
;
1941 pfm
->height
= pfi
->df
.dfPixHeight
;
1942 penalty
+= (d
> 0)? d
* 0x8 : -d
* 0x10;
1944 } else pfm
->height
= pfi
->df
.dfPixHeight
;
1946 if((pfm
->flags
& FO_MATCH_PAF
) &&
1947 (plf
->lfPitchAndFamily
& FF_FAMILY
) != (pfi
->df
.dfPitchAndFamily
& FF_FAMILY
) )
1952 if( bR6
&& bScale
) h
= 0;
1955 /* FIXME: not complete */
1957 pfm
->flags
|= FO_SYNTH_WIDTH
;
1958 h
= abs(plf
->lfWidth
- (pfm
->height
* pfi
->df
.dfAvgWidth
)/pfi
->df
.dfPixHeight
);
1960 penalty
+= h
* ( d
) ? 0x2 : 0x1 ;
1962 else if( !(pfi
->fi_flags
& FI_NORMAL
) ) penalty
++;
1964 if( plf
->lfWeight
!= FW_DONTCARE
)
1966 penalty
+= abs(plf
->lfWeight
- pfi
->df
.dfWeight
) / 40;
1967 if( plf
->lfWeight
> pfi
->df
.dfWeight
) pfm
->flags
|= FO_SYNTH_BOLD
;
1968 } else if( pfi
->df
.dfWeight
>= FW_BOLD
) penalty
++; /* choose normal by default */
1970 if( plf
->lfItalic
!= pfi
->df
.dfItalic
)
1973 pfm
->flags
|= FO_SYNTH_ITALIC
;
1976 if( plf
->lfUnderline
) pfm
->flags
|= FO_SYNTH_UNDERLINE
;
1977 if( plf
->lfStrikeOut
) pfm
->flags
|= FO_SYNTH_STRIKEOUT
;
1979 if( penalty
&& pfi
->lfd_resolution
!= DefResolution
)
1982 TRACE(font
," returning %i\n", penalty
);
1987 /***********************************************************************
1990 * Scan a particular font resource for the best match.
1992 static UINT32
XFONT_MatchFIList( fontMatch
* pfm
)
1994 BOOL32 skipRaster
= (pfm
->flags
& FO_MATCH_NORASTER
);
1995 UINT32 current_score
, score
= (UINT32
)(-1);
1996 UINT16 origflags
= pfm
->flags
; /* Preserve FO_MATCH_XYINDEP */
1997 fontMatch fm
= *pfm
;
1999 for( fm
.pfi
= pfm
->pfr
->fi
; fm
.pfi
&& score
; fm
.pfi
= fm
.pfi
->next
,
2000 fm
.flags
= origflags
)
2002 if( skipRaster
&& !(fm
.pfi
->fi_flags
& FI_SCALABLE
) )
2005 current_score
= XFONT_Match( &fm
);
2006 if( score
> current_score
)
2008 memcpy( pfm
, &fm
, sizeof(fontMatch
) );
2009 score
= current_score
;
2015 /***********************************************************************
2018 * REMOVE_SUBSETS - attach new fi and purge subsets
2019 * UNMARK_SUBSETS - remove subset flags from all fi entries
2021 static void XFONT_CheckFIList( fontResource
* fr
, fontInfo
* fi
, int action
)
2024 fontInfo
* pfi
, *prev
;
2026 for( prev
= NULL
, pfi
= fr
->fi
; pfi
; )
2028 if( action
== REMOVE_SUBSETS
)
2030 if( pfi
->fi_flags
& FI_SUBSET
)
2032 fontInfo
* subset
= pfi
;
2036 if( prev
) prev
->next
= pfi
= pfi
->next
;
2037 else fr
->fi
= pfi
= pfi
->next
;
2038 HeapFree( SystemHeap
, 0, subset
);
2042 else pfi
->fi_flags
&= ~FI_SUBSET
;
2048 if( action
== REMOVE_SUBSETS
) /* also add the superset */
2050 if( fi
->fi_flags
& FI_SCALABLE
)
2055 else if( prev
) prev
->next
= fi
; else fr
->fi
= fi
;
2059 if( i
) TRACE(font
,"\t purged %i subsets [%i]\n", i
, fr
->count
);
2062 /***********************************************************************
2065 static fontResource
* XFONT_FindFIList( fontResource
* pfr
, const char* pTypeFace
)
2069 if( !strcasecmp( pfr
->lfFaceName
, pTypeFace
) ) break;
2075 /***********************************************************************
2076 * XFONT_MatchDeviceFont
2078 * Scan font resource tree.
2080 static BOOL32
XFONT_MatchDeviceFont( fontResource
* start
, fontMatch
* pfm
)
2082 fontMatch fm
= *pfm
;
2085 if( fm
.plf
->lfFaceName
[0] )
2090 for( fa
= aliasTable
; fa
; fa
= fa
->next
)
2091 if( !strcmp( fa
->faAlias
, fm
.plf
->lfFaceName
) )
2093 str
= fa
->faTypeFace
;
2096 fm
.pfr
= XFONT_FindFIList( start
, str
? str
: fm
.plf
->lfFaceName
);
2099 if( fm
.pfr
) /* match family */
2101 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
2103 XFONT_MatchFIList( &fm
);
2107 if( !pfm
->pfi
) /* match all available fonts */
2109 UINT32 current_score
, score
= (UINT32
)(-1);
2111 fm
.flags
|= FO_MATCH_PAF
;
2112 for( start
= fontList
; start
&& score
; start
= start
->next
)
2116 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
2118 current_score
= XFONT_MatchFIList( &fm
);
2119 if( current_score
< score
)
2121 score
= current_score
;
2130 /***********************************************************************
2133 static void XFONT_GrowFreeList(int start
, int end
)
2135 /* add all entries from 'start' up to and including 'end' */
2137 memset( fontCache
+ start
, 0, (end
- start
+ 1) * sizeof(fontObject
) );
2139 fontCache
[end
].lru
= fontLF
;
2140 fontCache
[end
].count
= -1;
2142 while( start
< end
)
2144 fontCache
[start
].count
= -1;
2145 fontCache
[start
].lru
= start
+ 1;
2150 static fontObject
* XFONT_LookupCachedFont( LPLOGFONT16 plf
, UINT16
* checksum
)
2152 UINT16 cs
= __lfCheckSum( plf
);
2153 int i
= fontMRU
, prev
= -1;
2158 if( fontCache
[i
].lfchecksum
== cs
&&
2159 !(fontCache
[i
].fo_flags
& FO_REMOVED
) )
2161 /* FIXME: something more intelligent here */
2163 if( !memcmp( plf
, &fontCache
[i
].lf
,
2164 sizeof(LOGFONT16
) - LF_FACESIZE
) &&
2165 !strncasecmp( plf
->lfFaceName
, fontCache
[i
].lf
.lfFaceName
,
2168 /* remove temporarily from the lru list */
2171 fontCache
[prev
].lru
= fontCache
[i
].lru
;
2173 fontMRU
= (INT16
)fontCache
[i
].lru
;
2174 return (fontCache
+ i
);
2178 i
= (INT16
)fontCache
[i
].lru
;
2183 static fontObject
* XFONT_GetCacheEntry()
2189 int prev_i
, prev_j
, j
;
2191 TRACE(font
,"font cache is full\n");
2193 /* lookup the least recently used font */
2195 for( prev_i
= prev_j
= j
= -1, i
= fontMRU
; i
>= 0; i
= (INT16
)fontCache
[i
].lru
)
2197 if( fontCache
[i
].count
<= 0 &&
2198 !(fontCache
[i
].fo_flags
& FO_SYSTEM
) )
2206 if( j
>= 0 ) /* unload font */
2208 /* detach from the lru list */
2210 TRACE(font
,"\tfreeing entry %i\n", j
);
2213 fontCache
[prev_j
].lru
= fontCache
[j
].lru
;
2214 else fontMRU
= (INT16
)fontCache
[j
].lru
;
2216 /* FIXME: lpXForm, lpPixmap */
2217 if(fontCache
[j
].lpX11Trans
)
2218 HeapFree( SystemHeap
, 0, fontCache
[j
].lpX11Trans
);
2220 TSXFreeFont( display
, fontCache
[j
].fs
);
2222 memset( fontCache
+ j
, 0, sizeof(fontObject
) );
2223 return (fontCache
+ j
);
2225 else /* expand cache */
2227 fontObject
* newCache
;
2229 prev_i
= fontCacheSize
+ FONTCACHE
;
2231 TRACE(font
,"\tgrowing font cache from %i to %i\n", fontCacheSize
, prev_i
);
2233 if( (newCache
= (fontObject
*)HeapReAlloc(SystemHeap
, 0,
2234 fontCache
, prev_i
)) )
2237 fontCacheSize
= prev_i
;
2238 fontCache
= newCache
;
2239 XFONT_GrowFreeList( i
, fontCacheSize
- 1);
2245 /* detach from the free list */
2248 fontLF
= (INT16
)fontCache
[i
].lru
;
2249 fontCache
[i
].count
= 0;
2250 return (fontCache
+ i
);
2253 static int XFONT_ReleaseCacheEntry(fontObject
* pfo
)
2255 UINT32 u
= (UINT32
)(pfo
- fontCache
);
2257 if( u
< fontCacheSize
) return (--fontCache
[u
].count
);
2261 /**********************************************************************
2264 static BOOL32
XFONT_SetX11Trans( fontObject
*pfo
)
2271 TSXGetFontProperty( pfo
->fs
, XA_FONT
, &nameAtom
);
2272 fontName
= TSXGetAtomName( display
, nameAtom
);
2273 for(i
= 0, cp
= fontName
; i
< 7; i
++) {
2274 cp
= strchr(cp
, '-');
2282 while((cp
= strchr(cp
, '~')))
2285 #define PX pfo->lpX11Trans
2287 sscanf(start
, "[%f%f%f%f]", &PX
->a
, &PX
->b
, &PX
->c
, &PX
->d
);
2290 TSXGetFontProperty( pfo
->fs
, RAW_ASCENT
, &PX
->RAW_ASCENT
);
2291 TSXGetFontProperty( pfo
->fs
, RAW_DESCENT
, &PX
->RAW_DESCENT
);
2293 PX
->pixelsize
= hypot(PX
->a
, PX
->b
);
2294 PX
->ascent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_ASCENT
;
2295 PX
->descent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_DESCENT
;
2297 TRACE(font
, "[%f %f %f %f] RA = %ld RD = %ld\n", pfo
->lpX11Trans
->a
,
2298 pfo
->lpX11Trans
->b
, pfo
->lpX11Trans
->c
, pfo
->lpX11Trans
->d
,
2299 pfo
->lpX11Trans
->RAW_ASCENT
, pfo
->lpX11Trans
->RAW_DESCENT
);
2305 /***********************************************************************
2306 * X Device Font Objects
2308 static X_PHYSFONT
XFONT_RealizeFont( LPLOGFONT16 plf
)
2311 fontObject
* pfo
= XFONT_LookupCachedFont( plf
, &checksum
);
2315 fontMatch fm
= { NULL
, NULL
, 0, 0, plf
};
2318 if( XTextCaps
& TC_SF_X_YINDEP
) fm
.flags
= FO_MATCH_XYINDEP
;
2320 /* allocate new font cache entry */
2322 if( (pfo
= XFONT_GetCacheEntry()) )
2324 LPSTR lpLFD
= HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH
);
2326 if( lpLFD
) /* initialize entry and load font */
2328 UINT32 uRelaxLevel
= 0;
2330 TRACE(font
,"(%u) '%s' h=%i weight=%i %s\n",
2331 plf
->lfCharSet
, plf
->lfFaceName
, plf
->lfHeight
,
2332 plf
->lfWeight
, (plf
->lfItalic
) ? "Italic" : "" );
2334 if(abs(plf
->lfHeight
) > MAX_FONT_SIZE
) {
2336 "plf->lfHeight = %d, this is probably not right. Setting to 100\n",
2338 plf
->lfHeight
= 100;
2341 XFONT_MatchDeviceFont( fontList
, &fm
);
2345 pfo
->fo_flags
= fm
.flags
& ~FO_MATCH_MASK
;
2347 memcpy( &pfo
->lf
, plf
, sizeof(LOGFONT16
) );
2348 pfo
->lfchecksum
= checksum
;
2352 LFD_ComposeLFD( pfo
, fm
.height
, lpLFD
, uRelaxLevel
++ );
2353 if( (pfo
->fs
= TSXLoadQueryFont( display
, lpLFD
)) ) break;
2354 } while( uRelaxLevel
);
2357 if(pfo
->lf
.lfEscapement
!= 0) {
2358 pfo
->lpX11Trans
= HeapAlloc(SystemHeap
, 0,
2359 sizeof(XFONTTRANS
));
2360 if(!XFONT_SetX11Trans( pfo
)) {
2361 HeapFree(SystemHeap
, 0, pfo
->lpX11Trans
);
2362 pfo
->lpX11Trans
= NULL
;
2366 if( XFONT_GetLeading( &pfo
->fi
->df
, pfo
->fs
, &i
, NULL
,
2369 if(!pfo
->lpX11Trans
)
2370 pfo
->foAvgCharWidth
=
2371 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].width
;
2373 pfo
->foAvgCharWidth
=
2374 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].attributes
2375 * pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2377 pfo
->foAvgCharWidth
= (INT16
)XFONT_GetAvgCharWidth(
2378 &pfo
->fi
->df
, pfo
->fs
, pfo
->lpX11Trans
);
2379 pfo
->foMaxCharWidth
= (INT16
)XFONT_GetMaxCharWidth(pfo
);
2380 pfo
->foInternalLeading
= (INT16
)i
;
2382 /* FIXME: If we've got a soft font or
2383 * there are FO_SYNTH_... flags for the
2384 * non PROOF_QUALITY request, the engine
2385 * should rasterize characters into mono
2386 * pixmaps and store them in the pfo->lpPixmap
2387 * array (pfo->fs should be updated as well).
2388 * X11DRV_ExtTextOut() must be heavily modified
2389 * to support pixmap blitting and FO_SYNTH_...
2393 pfo
->lpXForm
= NULL
;
2394 pfo
->lpPixmap
= NULL
;
2396 HeapFree( GetProcessHeap(), 0, lpLFD
);
2398 else /* attach back to the free list */
2402 fontLF
= (pfo
- fontCache
);
2407 if( !pfo
) /* couldn't get a new entry, get one of the cached fonts */
2409 UINT32 current_score
, score
= (UINT32
)(-1);
2411 i
= index
= fontMRU
;
2412 fm
.flags
|= FO_MATCH_PAF
;
2415 pfo
= fontCache
+ i
;
2416 fm
.pfr
= pfo
->fr
; fm
.pfi
= pfo
->fi
;
2418 current_score
= XFONT_Match( &fm
);
2419 if( current_score
< score
) index
= i
;
2423 pfo
= fontCache
+ index
;
2425 return (X_PHYSFONT
)(X_PFONT_MAGIC
| index
);
2429 /* attach at the head of the lru list */
2433 fontMRU
= (pfo
- fontCache
);
2435 TRACE(font
,"physfont %i\n", fontMRU
);
2437 return (X_PHYSFONT
)(X_PFONT_MAGIC
| fontMRU
);
2440 /***********************************************************************
2441 * XFONT_GetFontObject
2443 fontObject
* XFONT_GetFontObject( X_PHYSFONT pFont
)
2445 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
);
2449 /***********************************************************************
2450 * XFONT_GetFontStruct
2452 XFontStruct
* XFONT_GetFontStruct( X_PHYSFONT pFont
)
2454 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
)->fs
;
2458 /***********************************************************************
2461 LPIFONTINFO16
XFONT_GetFontInfo( X_PHYSFONT pFont
)
2463 if( CHECK_PFONT(pFont
) ) return &(__PFONT(pFont
)->fi
->df
);
2469 /* X11DRV Interface ****************************************************
2471 * Exposed via the dc->funcs dispatch table. *
2473 ***********************************************************************/
2474 /***********************************************************************
2475 * X11DRV_FONT_SelectObject
2477 HFONT32
X11DRV_FONT_SelectObject( DC
* dc
, HFONT32 hfont
, FONTOBJ
* font
)
2479 HFONT32 hPrevFont
= 0;
2481 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2483 if( CHECK_PFONT(physDev
->font
) )
2484 XFONT_ReleaseCacheEntry( __PFONT(physDev
->font
) );
2486 /* FIXME: do we need to pass anything back from here? */
2487 memcpy(&lf
,&font
->logfont
,sizeof(lf
));
2488 lf
.lfWidth
= font
->logfont
.lfWidth
* dc
->vportExtX
/dc
->wndExtX
;
2489 lf
.lfHeight
= font
->logfont
.lfHeight
* dc
->vportExtY
/dc
->wndExtY
;
2491 physDev
->font
= XFONT_RealizeFont( &lf
);
2492 hPrevFont
= dc
->w
.hFont
;
2493 dc
->w
.hFont
= hfont
;
2499 /***********************************************************************
2501 * X11DRV_EnumDeviceFonts
2503 BOOL32
X11DRV_EnumDeviceFonts( DC
* dc
, LPLOGFONT16 plf
,
2504 DEVICEFONTENUMPROC proc
, LPARAM lp
)
2508 fontResource
* pfr
= fontList
;
2511 if( plf
->lfFaceName
[0] )
2513 pfr
= XFONT_FindFIList( pfr
, plf
->lfFaceName
);
2517 for( pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
2518 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2519 XFONT_GetFontMetric( pfi
, &lf
, &tm
), lp
)) )
2525 for( ; pfr
; pfr
= pfr
->next
)
2528 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2529 XFONT_GetFontMetric( pfr
->fi
, &lf
, &tm
), lp
)) )
2538 /***********************************************************************
2539 * X11DRV_GetTextExtentPoint
2541 BOOL32
X11DRV_GetTextExtentPoint( DC
*dc
, LPCSTR str
, INT32 count
,
2544 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2545 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2547 if( !pfo
->lpX11Trans
) {
2548 int dir
, ascent
, descent
;
2551 TSXTextExtents( pfo
->fs
, str
, count
, &dir
, &ascent
, &descent
, &info
);
2552 size
->cx
= abs((info
.width
+ dc
->w
.breakRem
+ count
*
2553 dc
->w
.charExtra
) * dc
->wndExtX
/ dc
->vportExtX
);
2554 size
->cy
= abs((pfo
->fs
->ascent
+ pfo
->fs
->descent
) *
2555 dc
->wndExtY
/ dc
->vportExtY
);
2559 float x
= 0.0, y
= 0.0;
2560 for(i
= 0; i
< count
; i
++) {
2561 x
+= pfo
->fs
->per_char
?
2562 pfo
->fs
->per_char
[str
[i
] - pfo
->fs
->min_char_or_byte2
].attributes
:
2563 pfo
->fs
->min_bounds
.attributes
;
2565 y
= pfo
->lpX11Trans
->RAW_ASCENT
+ pfo
->lpX11Trans
->RAW_DESCENT
;
2566 TRACE(font
, "x = %f y = %f\n", x
, y
);
2567 x
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2568 y
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2569 size
->cx
= fabsf((x
+ dc
->w
.breakRem
+ count
* dc
->w
.charExtra
) *
2570 dc
->wndExtX
/ dc
->vportExtX
);
2571 size
->cy
= fabsf(y
* dc
->wndExtY
/ dc
->vportExtY
);
2579 /***********************************************************************
2580 * X11DRV_GetTextMetrics
2582 BOOL32
X11DRV_GetTextMetrics(DC
*dc
, TEXTMETRIC32A
*metrics
)
2584 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2586 if( CHECK_PFONT(physDev
->font
) )
2588 fontObject
* pfo
= __PFONT(physDev
->font
);
2589 XFONT_GetTextMetric( pfo
, metrics
);
2597 /***********************************************************************
2598 * X11DRV_GetCharWidth
2600 BOOL32
X11DRV_GetCharWidth( DC
*dc
, UINT32 firstChar
, UINT32 lastChar
,
2603 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2604 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2610 if (pfo
->fs
->per_char
== NULL
)
2611 for (i
= firstChar
; i
<= lastChar
; i
++)
2613 *buffer
++ = pfo
->fs
->min_bounds
.attributes
*
2614 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2616 *buffer
++ = pfo
->fs
->min_bounds
.width
;
2619 XCharStruct
*cs
, *def
;
2620 static XCharStruct __null_char
= { 0, 0, 0, 0, 0, 0 };
2622 CI_GET_CHAR_INFO(pfo
->fs
, pfo
->fs
->default_char
, &__null_char
,
2625 for (i
= firstChar
; i
<= lastChar
; i
++)
2627 if (i
>= pfo
->fs
->min_char_or_byte2
&&
2628 i
<= pfo
->fs
->max_char_or_byte2
)
2630 cs
= &pfo
->fs
->per_char
[(i
- pfo
->fs
->min_char_or_byte2
)];
2631 if (CI_NONEXISTCHAR(cs
)) cs
= def
;
2634 *buffer
++ = MAX(cs
->attributes
, 0) *
2635 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2637 *buffer
++ = MAX(cs
->width
, 0 );
2646 /***********************************************************************
2648 * Font Resource API *
2650 ***********************************************************************/
2651 /***********************************************************************
2652 * AddFontResource16 (GDI.119)
2654 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
2656 * FIXME: Load header and find the best-matching font in the fontList;
2657 * fixup dfPoints if all metrics are identical, otherwise create
2658 * new fontAlias. When soft font support is ready this will
2659 * simply create a new fontResource ('filename' will go into
2660 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
2663 INT16 WINAPI
AddFontResource16( LPCSTR filename
)
2665 return AddFontResource32A( filename
);
2669 /***********************************************************************
2670 * AddFontResource32A (GDI32.2)
2672 INT32 WINAPI
AddFontResource32A( LPCSTR str
)
2674 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2679 /***********************************************************************
2680 * AddFontResource32W (GDI32.4)
2682 INT32 WINAPI
AddFontResource32W( LPCWSTR str
)
2684 FIXME(font
, "(%s): stub\n", debugres_w(str
) );
2688 /***********************************************************************
2689 * RemoveFontResource16 (GDI.136)
2691 BOOL16 WINAPI
RemoveFontResource16( SEGPTR str
)
2693 FIXME(font
, "(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str
)));
2698 /***********************************************************************
2699 * RemoveFontResource32A (GDI32.284)
2701 BOOL32 WINAPI
RemoveFontResource32A( LPCSTR str
)
2703 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2708 /***********************************************************************
2709 * RemoveFontResource32W (GDI32.286)
2711 BOOL32 WINAPI
RemoveFontResource32W( LPCWSTR str
)
2713 FIXME(font
, "(%s): stub\n", debugres_w(str
) );