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 */
60 static fontAlias __aliasTable
[2] = {
61 { "Helvetica", "Helv", &__aliasTable
[1] },
62 { "Times", "Tms Rmn", NULL
}
65 static fontAlias
*aliasTable
= __aliasTable
;
67 /* Optional built-in aliases, they are installed only when X
68 * cannot supply us with original MS fonts */
70 static int faTemplateNum
= 4;
71 static aliasTemplate faTemplate
[4] = {
72 { "-adobe-helvetica-", "MS Sans Serif" },
73 { "-bitstream-charter-", "MS Serif" },
74 { "-adobe-times-", "Times New Roman" },
75 { "-adobe-helvetica-", "Arial" }
78 UINT16 XTextCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
|
79 TC_CP_STROKE
| TC_CR_ANY
|
80 TC_SA_DOUBLE
| TC_SA_INTEGER
| TC_SA_CONTIN
|
81 TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
83 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
85 static const char* INIWinePrefix
= "/.wine";
86 static const char* INIFontMetrics
= "/.cachedmetrics";
87 static const char* INIFontSection
= "fonts";
88 static const char* INISubSection
= "Alias";
89 static const char* INIDefault
= "Default";
90 static const char* INIDefaultFixed
= "DefaultFixed";
91 static const char* INIResolution
= "Resolution";
92 static const char* INIGlobalMetrics
= "FontMetrics";
94 static const char* LFDSeparator
= "*-";
95 static const char* MSEncoding
= "microsoft-";
96 static const char* iso8859Encoding
= "iso8859-";
97 static const char* iso646Encoding
= "iso646.1991-";
98 static const char* ansiEncoding
= "ansi-";
99 static unsigned DefResolution
= 0;
101 static fontResource
* fontList
= NULL
;
102 static fontObject
* fontCache
= NULL
; /* array */
103 static int fontCacheSize
= FONTCACHE
;
104 static int fontLF
= -1, fontMRU
= -1; /* last free, most recently used */
106 #define __PFONT(pFont) ( fontCache + ((UINT32)(pFont) & 0x0000FFFF) )
107 #define CHECK_PFONT(pFont) ( (((UINT32)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
108 (((UINT32)(pFont) & 0x0000FFFF) < fontCacheSize) )
110 static INT32
XFONT_IsSubset(fontInfo
*, fontInfo
*);
111 static void XFONT_CheckFIList(fontResource
*, fontInfo
*, int subset_action
);
112 static void XFONT_GrowFreeList(int start
, int end
);
115 static Atom RAW_ASCENT
;
116 static Atom RAW_DESCENT
;
118 /***********************************************************************
119 * Helper macros from X distribution
122 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
123 (((cs)->rbearing|(cs)->lbearing| \
124 (cs)->ascent|(cs)->descent) == 0))
126 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
129 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
130 if (fs->per_char == NULL) { \
131 cs = &fs->min_bounds; \
133 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
134 if (CI_NONEXISTCHAR(cs)) cs = def; \
139 #define CI_GET_DEFAULT_INFO(fs,cs) \
140 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
142 /***********************************************************************
145 static UINT16
__lfCheckSum( LPLOGFONT16 plf
)
147 CHAR font
[LF_FACESIZE
];
151 #define ptr ((UINT16*)plf)
152 for( i
= 0; i
< 9; i
++ ) checksum
^= *ptr
++;
155 #define ptr ((CHAR*)plf)
156 do { font
[i
++] = tolower(*ptr
++); } while (( i
< LF_FACESIZE
) && (*ptr
) && (*ptr
!=' '));
157 for( ptr
= font
, i
>>= 1; i
> 0; i
-- )
159 #define ptr ((UINT16*)plf)
165 static UINT16
__genericCheckSum( const void *ptr
, int size
)
167 unsigned int checksum
= 0;
168 const char *p
= (const char *)ptr
;
170 checksum
^= (checksum
<< 3) + (checksum
>> 29) + *p
++;
172 return checksum
& 0xffff;
175 /*************************************************************************
176 * LFD parse/compose routines
178 static char* LFD_Advance(LPSTR lpFont
, UINT16 uParmsNo
)
183 for( ; j
< uParmsNo
&& *lpch
; lpch
++ ) if( *lpch
== LFDSeparator
[1] ) j
++;
187 static void LFD_GetWeight( fontInfo
* fi
, LPSTR lpStr
, int j
)
189 if( j
== 1 && *lpStr
== '0' )
190 fi
->fi_flags
|= FI_POLYWEIGHT
;
193 if( !strncasecmp( "bold", lpStr
, 4) )
194 fi
->df
.dfWeight
= FW_BOLD
;
195 else if( !strncasecmp( "demi", lpStr
, 4) )
197 fi
->fi_flags
|= FI_FW_DEMI
;
198 fi
->df
.dfWeight
= FW_DEMIBOLD
;
200 else if( !strncasecmp( "book", lpStr
, 4) )
202 fi
->fi_flags
|= FI_FW_BOOK
;
203 fi
->df
.dfWeight
= FW_REGULAR
;
208 if( !strncasecmp( "light", lpStr
, 5) )
209 fi
->df
.dfWeight
= FW_LIGHT
;
210 else if( !strncasecmp( "black", lpStr
, 5) )
211 fi
->df
.dfWeight
= FW_BLACK
;
213 else if( j
== 6 && !strncasecmp( "medium", lpStr
, 6) )
214 fi
->df
.dfWeight
= FW_REGULAR
;
215 else if( j
== 8 && !strncasecmp( "demibold", lpStr
, 8) )
216 fi
->df
.dfWeight
= FW_DEMIBOLD
;
218 fi
->df
.dfWeight
= FW_DONTCARE
; /* FIXME: try to get something
219 * from the weight property */
222 static int LFD_GetSlant( fontInfo
* fi
, LPSTR lpStr
, int l
)
226 switch( tolower( *lpStr
) )
228 case '0': fi
->fi_flags
|= FI_POLYSLANT
; /* haven't seen this one yet */
230 case 'r': fi
->df
.dfItalic
= 0;
233 fi
->fi_flags
|= FI_OBLIQUE
;
234 case 'i': fi
->df
.dfItalic
= 1;
242 /*************************************************************************
245 * Fill in some fields in the fontInfo struct.
247 static int LFD_InitFontInfo( fontInfo
* fi
, LPSTR lpstr
)
250 int i
, j
, dec_style_check
, scalability
;
253 memset(fi
, 0, sizeof(fontInfo
) );
256 lpch
= LFD_Advance( lpstr
, 1);
257 if( !*lpch
) return FALSE
;
258 j
= lpch
- lpstr
- 1;
259 LFD_GetWeight( fi
, lpstr
, j
);
262 lpch
= LFD_Advance( lpstr
= lpch
, 1);
263 if( !*lpch
) return FALSE
;
264 j
= lpch
- lpstr
- 1;
265 dec_style_check
= LFD_GetSlant( fi
, lpstr
, j
);
268 lpch
= LFD_Advance( lpstr
= lpch
, 1);
269 if( !*lpch
) return FALSE
;
270 if( strncasecmp( "normal", lpstr
, 6) ) /* XXX 'narrow', 'condensed', etc... */
271 dec_style_check
= TRUE
;
273 fi
->fi_flags
|= FI_NORMAL
;
276 lpch
= LFD_Advance( lpstr
= lpch
, 1);
277 if( !*lpch
) return FALSE
;
278 j
= lpch
- lpstr
- 1;
279 if( j
> 3 ) /* find out is there "sans" or "script" */
284 if( strstr(lpstr
, "sans") )
286 fi
->df
.dfPitchAndFamily
|= FF_SWISS
;
289 if( strstr(lpstr
, "script") )
291 fi
->df
.dfPitchAndFamily
|= FF_SCRIPT
;
294 if( !j
&& dec_style_check
)
295 fi
->df
.dfPitchAndFamily
|= FF_DECORATIVE
;
296 *(lpch
- 1) = LFDSeparator
[1];
299 /* pixel height, decipoint height, and res_x */
301 for( i
= scalability
= 0; i
< 3; i
++ )
303 lpch
= LFD_Advance( lpstr
= lpch
, 1);
304 if( !*lpch
) return FALSE
;
305 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
308 if( !(tmp
[i
] = atoi(lpstr
)) ) scalability
++;
309 *(lpch
- 1) = LFDSeparator
[1];
311 if( scalability
== 3 ) /* Type1 */
313 fi
->fi_flags
|= FI_SCALABLE
;
314 fi
->lfd_height
= DEF_SCALABLE_HEIGHT
; fi
->lfd_decipoints
= DEF_SCALABLE_DP
;
315 fi
->lfd_resolution
= DefResolution
;
317 else if( scalability
== 0 ) /* Bitmap */
319 fi
->lfd_height
= tmp
[0]; fi
->lfd_decipoints
= tmp
[1];
320 fi
->lfd_resolution
= tmp
[2];
322 else return FALSE
; /* #$%^!!! X11R6 mutant garbage */
324 /* res_y - skip, spacing - */
325 lpstr
= LFD_Advance( lpch
, 1);
328 case '\0': return FALSE
;
330 case 'p': fi
->fi_flags
|= FI_VARIABLEPITCH
;
332 case 'c': fi
->df
.dfPitchAndFamily
|= FF_MODERN
;
333 fi
->fi_flags
|= FI_FIXEDEX
;
335 case 'm': fi
->fi_flags
|= FI_FIXEDPITCH
;
338 fi
->df
.dfPitchAndFamily
|= DEFAULT_PITCH
| FF_DONTCARE
;
340 lpstr
= LFD_Advance(lpstr
, 1);
341 if( !*lpstr
) return FALSE
;
343 /* average width - */
344 lpch
= LFD_Advance( lpstr
, 1);
345 if( !*lpch
) return FALSE
;
346 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
348 if( !(fi
->lfd_width
= atoi(lpstr
)) && !scalability
) return FALSE
;
349 *(lpch
- 1) = LFDSeparator
[1];
351 /* charset registry, charset encoding - */
352 if( strstr(lpch
, "jisx") ||
353 strstr(lpch
, "ksc") ||
354 strstr(lpch
, "gb2312") ||
355 strstr(lpch
, "big5") ||
356 strstr(lpch
, "unicode") ) return FALSE
; /* 2-byte stuff */
358 fi
->df
.dfCharSet
= ANSI_CHARSET
;
359 if( strstr(lpch
, iso8859Encoding
) ) {
360 fi
->fi_flags
|= FI_ENC_ISO8859
;
361 if( strstr(lpch
, "iso8859-15") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
362 else if( strstr(lpch
, "iso8859-11") ) fi
->df
.dfCharSet
= THAI_CHARSET
;
363 else if( strstr(lpch
, "iso8859-10") ) fi
->df
.dfCharSet
= BALTIC_CHARSET
;
364 else if( strstr(lpch
, "iso8859-9") ) fi
->df
.dfCharSet
= TURKISH_CHARSET
;
365 else if( strstr(lpch
, "iso8859-8") ) fi
->df
.dfCharSet
= HEBREW_CHARSET
;
366 else if( strstr(lpch
, "iso8859-7") ) fi
->df
.dfCharSet
= GREEK_CHARSET
;
367 else if( strstr(lpch
, "iso8859-6") ) fi
->df
.dfCharSet
= ARABIC_CHARSET
;
368 else if( strstr(lpch
, "iso8859-5") ) fi
->df
.dfCharSet
= RUSSIAN_CHARSET
;
369 else if( strstr(lpch
, "iso8859-4") ) fi
->df
.dfCharSet
= ISO4_CHARSET
;
370 else if( strstr(lpch
, "iso8859-3") ) fi
->df
.dfCharSet
= ISO3_CHARSET
;
371 else if( strstr(lpch
, "iso8859-2") ) fi
->df
.dfCharSet
= EE_CHARSET
;
372 else if( strstr(lpch
, "iso8859-1") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
373 else fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
374 } else if( strstr(lpch
, iso646Encoding
) ) {
375 fi
->fi_flags
|= FI_ENC_ISO646
;
376 } else if( strstr(lpch
, ansiEncoding
) ) { /* fnt2bdf produces -ansi-0 LFD */
377 fi
->fi_flags
|= FI_ENC_ANSI
;
378 } else { /* ... and -microsoft-cp125x */
380 fi
->df
.dfCharSet
= OEM_CHARSET
;
381 if( !strncasecmp(lpch
, "microsoft-", 10) ) {
382 fi
->fi_flags
|= FI_ENC_MSCODEPAGE
;
383 if( strstr(lpch
, "-cp1250") ) fi
->df
.dfCharSet
= EE_CHARSET
;
384 else if( strstr(lpch
, "-cp1251") ) fi
->df
.dfCharSet
= RUSSIAN_CHARSET
;
385 else if( strstr(lpch
, "-cp1252") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
386 else if( strstr(lpch
, "-cp1253") ) fi
->df
.dfCharSet
= GREEK_CHARSET
;
387 else if( strstr(lpch
, "-cp1254") ) fi
->df
.dfCharSet
= TURKISH_CHARSET
;
388 else if( strstr(lpch
, "-cp1255") ) fi
->df
.dfCharSet
= HEBREW_CHARSET
;
389 else if( strstr(lpch
, "-cp1256") ) fi
->df
.dfCharSet
= ARABIC_CHARSET
;
390 else if( strstr(lpch
, "-cp1257") ) fi
->df
.dfCharSet
= BALTIC_CHARSET
;
391 else if( strstr(lpch
, "-fontspecific") ) fi
->df
.dfCharSet
= ANSI_CHARSET
;
392 else if( strstr(lpch
, "-symbol") ) fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
393 else fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
394 } else if( !strncasecmp(lpch
, "koi8-", 5) ) {
395 fi
->df
.dfCharSet
= KOI8_CHARSET
;
396 } else if( !strncasecmp(lpch
, "viscii", 6) ) {
397 fi
->fi_flags
|= FI_ENC_ISO8859
;
398 fi
->df
.dfCharSet
= VISCII_CHARSET
;
399 } else if( !strncasecmp(lpch
, "tcvn-", 5) ) {
400 fi
->df
.dfCharSet
= TCVN_CHARSET
;
401 } else if( !strncasecmp(lpch
, "tis620", 6) ) {
402 fi
->fi_flags
|= FI_ENC_ISO8859
;
403 fi
->df
.dfCharSet
= THAI_CHARSET
;
404 } else if( !strncasecmp(lpch
, "ascii", 5) ) {
405 fi
->fi_flags
|= FI_ENC_ISO646
;
406 fi
->df
.dfCharSet
= ANSI_CHARSET
;
407 } else if( strstr(lpch
, "fontspecific") ||
408 strstr(lpch
, "microsoft-symbol") ) {
409 fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
416 /*************************************************************************
419 static BOOL32
LFD_ComposeLFD( fontObject
* fo
,
420 INT32 height
, LPSTR lpLFD
, UINT32 uRelax
)
422 int h
, w
, ch
, point
= 0;
425 char h_string
[64], point_string
[64];
427 *(lpLFD
+MAX_LFD_LENGTH
-1)=0;
428 lstrcpy32A( lpLFD
, fo
->fr
->resource
);
431 switch( fo
->fi
->df
.dfWeight
)
434 strcat( lpLFD
, "bold" ); break;
436 if( fo
->fi
->fi_flags
& FI_FW_BOOK
)
437 strcat( lpLFD
, "book" );
439 strcat( lpLFD
, "medium" );
442 strcat( lpLFD
, "demi" );
443 if( !( fo
->fi
->fi_flags
& FI_FW_DEMI
) )
444 strcat ( lpLFD
, "bold" );
447 strcat( lpLFD
, "black" ); break;
449 strcat( lpLFD
, "light" ); break;
451 strcat( lpLFD
, "*" );
455 if( fo
->fi
->df
.dfItalic
)
456 if( fo
->fi
->fi_flags
& FI_OBLIQUE
)
457 strcat( lpLFD
, "-o" );
459 strcat( lpLFD
, "-i" );
461 strcat( lpLFD
, (uRelax
< 6) ? "-r" : "-*" );
463 /* add width style and skip serifs */
464 if( fo
->fi
->fi_flags
& FI_NORMAL
)
465 strcat( lpLFD
, "-normal-*-");
467 strcat( lpLFD
, "-*-*-" );
469 /* add pixelheight, pointheight, and resolution
471 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
473 if( fo
->fo_flags
& FO_SYNTH_HEIGHT
) h
= fo
->fi
->lfd_height
;
474 else h
= (fo
->fi
->lfd_height
* height
) / fo
->fi
->df
.dfPixHeight
;
476 if( XTextCaps
& TC_SF_X_YINDEP
)
478 if( fo
->lf
.lfWidth
&& !(fo
->fo_flags
& FO_SYNTH_WIDTH
) )
479 point
= (fo
->fi
->lfd_decipoints
* fo
->lf
.lfWidth
) / fo
->fi
->df
.dfAvgWidth
;
481 if( fo
->fi
->fi_flags
& FI_SCALABLE
) /* adjust h/w ratio */
482 point
= h
* 72 * 10 / fo
->fi
->lfd_resolution
;
485 /* handle rotated fonts */
486 if (fo
->lf
.lfEscapement
) {
487 /* escapement is in tenths of degrees, theta is in radians */
488 double theta
= M_PI
*fo
->lf
.lfEscapement
/1800.;
489 double h_matrix
[4] = {h
*cos(theta
), h
*sin(theta
), -h
*sin(theta
), h
*cos(theta
)};
490 double point_matrix
[4] = {point
*cos(theta
), point
*sin(theta
), -point
*sin(theta
), point
*cos(theta
)};
492 sprintf(h_string
, "[%+f%+f%+f%+f]", h_matrix
[0], h_matrix
[1], h_matrix
[2], h_matrix
[3]);
493 sprintf(point_string
, "[%+f%+f%+f%+f]", point_matrix
[0], point_matrix
[1], point_matrix
[2], point_matrix
[3]);
494 while ((s
= strchr(h_string
, '-'))) *s
='~';
495 while ((s
= strchr(point_string
, '-'))) *s
='~';
497 sprintf(h_string
, "%d", h
);
498 sprintf(point_string
, "%d", point
);
502 /* spacing and width */
504 if( fo
->fi
->fi_flags
& FI_FIXEDPITCH
)
505 w
= ( fo
->fi
->fi_flags
& FI_FIXEDEX
) ? 'c' : 'm';
507 w
= ( fo
->fi
->fi_flags
& FI_VARIABLEPITCH
) ? 'p' : LFDSeparator
[0];
511 #define CHRS_CASE1(charset) case 0: \
515 case 12: sprintf(lpEncoding, charset ); break;
516 #define CHRS_CASE2(charset) case 1: \
520 case 13: sprintf(lpEncoding, charset ); break;
521 #define CHRS_CASE3(charset) case 2: \
525 case 14: sprintf(lpEncoding, charset ); break;
526 #define CHRS_DEF(charset) default: sprintf(lpEncoding, charset ); break;
528 if( fo
->fi
->df
.dfCharSet
== ANSI_CHARSET
)
530 if( fo
->fi
->fi_flags
& FI_ENC_ISO8859
)
532 CHRS_CASE1( "iso8859-1" );
533 CHRS_CASE2( "iso8859-1" );
534 CHRS_CASE3( "iso8859-15" );
535 CHRS_DEF( "iso8859-*" );
537 else if( fo
->fi
->fi_flags
& FI_ENC_ISO646
)
539 CHRS_CASE1( "ascii-0" );
540 CHRS_DEF( "iso8859-1" );
542 else if( fo
->fi
->fi_flags
& FI_ENC_MSCODEPAGE
)
544 CHRS_CASE1( "microsoft-cp1252" );
545 CHRS_CASE2( "microsoft-fontspecific" );
546 CHRS_CASE3( "microsoft-cp125*" );
547 CHRS_DEF( "microsoft-*" );
551 CHRS_CASE1( "ansi-0" );
552 CHRS_CASE2( "microsoft-125*" );
553 CHRS_CASE3( "microsoft-*");
554 CHRS_DEF( "iso8859-*" );
557 else if( fo
->fi
->fi_flags
& FI_ENC_MSCODEPAGE
)
559 switch (fo
->fi
->df
.dfCharSet
) {
562 CHRS_CASE1( "microsoft-1250" );
563 CHRS_CASE2( "iso8859-2" );
564 CHRS_DEF( "iso8859-*" );
566 case RUSSIAN_CHARSET
:
568 CHRS_CASE1( "microsoft-1251" );
569 CHRS_CASE2( "iso8859-5" );
570 CHRS_CASE3( "koi8-*" );
571 CHRS_DEF( "iso8859-*" );
575 CHRS_CASE1( "microsoft-1252" );
576 CHRS_CASE2( "iso8859-1" );
577 CHRS_CASE3( "iso8859-15" );
578 CHRS_DEF( "iso8859-*" );
582 CHRS_CASE1( "microsoft-1253" );
583 CHRS_CASE2( "iso8859-7" );
584 CHRS_DEF( "iso8859-*" );
586 case TURKISH_CHARSET
:
588 CHRS_CASE1( "microsoft-1254" );
589 CHRS_CASE2( "iso8859-9" );
590 CHRS_DEF( "iso8859-*" );
594 CHRS_CASE1( "microsoft-1255" );
595 CHRS_CASE2( "iso8859-8" );
596 CHRS_DEF( "iso8859-*" );
600 CHRS_CASE1( "microsoft-1256" );
601 CHRS_CASE2( "iso8859-6" );
602 CHRS_DEF( "iso8859-*" );
606 CHRS_CASE1( "microsoft-1257" );
607 CHRS_CASE2( "iso8859-10" );
608 CHRS_CASE3( "iso8859-15" );
609 CHRS_DEF( "iso8859-*" );
613 CHRS_CASE1( "iso8859-11" );
614 CHRS_CASE2( "tis620*" );
615 CHRS_DEF( "iso8859-*" );
619 CHRS_CASE1( "viscii1.1-1" );
620 CHRS_CASE2( "viscii*" );
621 CHRS_DEF( "iso8859-*" );
625 CHRS_CASE1( "tcvn-0" );
626 CHRS_CASE2( "tcvn*" );
627 CHRS_DEF( "iso8859-*" );
631 CHRS_CASE1( "koi8-ru" );
632 CHRS_CASE2( "koi8-r" );
633 CHRS_CASE3( "koi8-*" );
634 CHRS_DEF( "iso8859-*" );
638 CHRS_CASE1( "iso8859-3" );
639 CHRS_DEF( "iso8859-*" );
643 CHRS_CASE1( "iso8859-4" );
644 CHRS_DEF( "iso8859-*" );
648 CHRS_CASE1( "microsoft-symbol" );
649 CHRS_DEF( "microsoft-fontspecific" );
655 CHRS_CASE1( "*-fontspecific" );
656 CHRS_CASE2( "*-symbol" );
657 CHRS_DEF( "*-*" ); /* whatever */
661 lpch
= lpLFD
+ lstrlen32A(lpLFD
);
662 ch
= (fo
->fi
->fi_flags
& FI_SCALABLE
) ? '0' : LFDSeparator
[0];
666 /* RealizeFont() will call us repeatedly with increasing uRelax
667 * until XLoadFont() succeeds. */
674 sprintf( lpch
, "%s-%s-%i-%c-%c-*-%s", h_string
,
676 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
684 case 6: /* 6-8 will have replaced an 'r' in slant by '*' */
687 sprintf( lpch
, "%s-*-%i-%c-%c-*-%s", h_string
,
688 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
694 sprintf( lpch
, "%s-*-%i-%c-*-*-%s",
695 h_string
, fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
701 sprintf( lpch
, "%i-*-%i-%c-*-*-%s", fo
->fi
->lfd_height
,
702 fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
706 sprintf( lpch
, "%i-*-*-*-*-*-%s", fo
->fi
->lfd_height
, lpEncoding
);
710 sprintf( lpch
, "%i-*-*-*-*-*-*-*", fo
->fi
->lfd_height
);
713 /* to avoid an infinite loop; those will allways match */
715 sprintf( lpLFD
, "-*-*-*-*-*-*-*-*-*-*-*-*-iso8859-1" );
718 sprintf( lpLFD
, "-*-*-*-*-*-*-*-*-*-*-*-*-*-*" );
722 TRACE(font
,"\tLFD(uRelax=%d): %s\n", uRelax
, lpLFD
);
723 assert(*(lpLFD
+MAX_LFD_LENGTH
-1)==0); /* check if overwrittem */
728 /***********************************************************************
731 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
732 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
734 static BOOL32
XFONT_GetLeading( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
, INT32
*
735 pIL
, INT32
* pEL
, XFONTTRANS
*XFT
)
737 unsigned long height
;
738 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
739 unsigned max
= (unsigned char)pFI
->dfLastChar
;
740 BOOL32 bHaveCapHeight
= (pFI
->dfCharSet
== ANSI_CHARSET
&& 'X' >= min
&& 'X' <= max
);
745 Atom RAW_CAP_HEIGHT
= TSXInternAtom(display
, "RAW_CAP_HEIGHT", TRUE
);
746 if(TSXGetFontProperty(x_fs
, RAW_CAP_HEIGHT
, &height
))
748 (INT32
)(XFT
->pixelsize
/ 1000.0 * height
);
751 return bHaveCapHeight
&& x_fs
->per_char
;
754 if( TSXGetFontProperty(x_fs
, XA_CAP_HEIGHT
, &height
) == FALSE
)
758 height
= x_fs
->per_char
['X' - min
].ascent
;
760 if (x_fs
->ascent
>= x_fs
->max_bounds
.ascent
)
761 height
= x_fs
->max_bounds
.ascent
;
764 height
= x_fs
->ascent
;
766 *pEL
= x_fs
->max_bounds
.ascent
- height
;
769 height
= x_fs
->min_bounds
.ascent
;
772 *pIL
= x_fs
->ascent
- height
;
773 return (bHaveCapHeight
&& x_fs
->per_char
);
776 static INT32
XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
,
779 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
780 unsigned max
= (unsigned char)pFI
->dfLastChar
;
785 for( j
= 0, width
= 0, chars
= 0, max
-= min
; j
<= max
; j
++ )
786 if( !CI_NONEXISTCHAR(x_fs
->per_char
+ j
) )
789 width
+= x_fs
->per_char
[j
].width
;
791 width
+= x_fs
->per_char
[j
].attributes
*
792 XFT
->pixelsize
/ 1000.0;
795 return (width
/ chars
);
798 return x_fs
->min_bounds
.width
;
801 static INT32
XFONT_GetMaxCharWidth(fontObject
*pfo
)
803 unsigned min
= (unsigned char)pfo
->fs
->min_char_or_byte2
;
804 unsigned max
= (unsigned char)pfo
->fs
->max_char_or_byte2
;
807 return abs(pfo
->fs
->max_bounds
.width
);
809 if( pfo
->fs
->per_char
)
812 for( j
= 0, maxwidth
= 0, max
-= min
; j
<= max
; j
++ )
813 if( !CI_NONEXISTCHAR(pfo
->fs
->per_char
+ j
) )
814 if(maxwidth
< pfo
->fs
->per_char
[j
].attributes
)
815 maxwidth
= pfo
->fs
->per_char
[j
].attributes
;
817 maxwidth
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
820 return pfo
->foAvgCharWidth
;
823 /***********************************************************************
824 * XFONT_SetFontMetric
826 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
828 static void XFONT_SetFontMetric(fontInfo
* fi
, fontResource
* fr
, XFontStruct
* xfs
)
833 fi
->df
.dfFirstChar
= (BYTE
)(min
= xfs
->min_char_or_byte2
);
834 fi
->df
.dfLastChar
= (BYTE
)(max
= xfs
->max_char_or_byte2
);
836 fi
->df
.dfDefaultChar
= (BYTE
)xfs
->default_char
;
837 fi
->df
.dfBreakChar
= (BYTE
)(( ' ' < min
|| ' ' > max
) ? xfs
->default_char
: ' ');
839 fi
->df
.dfPixHeight
= (INT16
)((fi
->df
.dfAscent
= (INT16
)xfs
->ascent
) + xfs
->descent
);
840 fi
->df
.dfPixWidth
= (xfs
->per_char
) ? 0 : xfs
->min_bounds
.width
;
841 fi
->df
.dfMaxWidth
= (INT16
)abs(xfs
->max_bounds
.width
);
843 if( XFONT_GetLeading( &fi
->df
, xfs
, &il
, &el
, NULL
) )
844 fi
->df
.dfAvgWidth
= (INT16
)xfs
->per_char
['X' - min
].width
;
846 fi
->df
.dfAvgWidth
= (INT16
)XFONT_GetAvgCharWidth( &fi
->df
, xfs
, NULL
);
848 fi
->df
.dfInternalLeading
= (INT16
)il
;
849 fi
->df
.dfExternalLeading
= (INT16
)el
;
851 fi
->df
.dfPoints
= (INT16
)(((INT32
)(fi
->df
.dfPixHeight
-
852 fi
->df
.dfInternalLeading
) * 72 + (fi
->df
.dfVertRes
>> 1)) / fi
->df
.dfVertRes
);
854 if( xfs
->min_bounds
.width
!= xfs
->max_bounds
.width
)
855 fi
->df
.dfPitchAndFamily
|= TMPF_FIXED_PITCH
; /* au contraire! */
856 if( fi
->fi_flags
& FI_SCALABLE
)
858 fi
->df
.dfType
= DEVICE_FONTTYPE
;
859 fi
->df
.dfPitchAndFamily
|= TMPF_DEVICE
;
861 else if( fi
->fi_flags
& FI_TRUETYPE
)
862 fi
->df
.dfType
= TRUETYPE_FONTTYPE
;
864 fi
->df
.dfType
= RASTER_FONTTYPE
;
866 fi
->df
.dfFace
= fr
->lfFaceName
;
869 /***********************************************************************
870 * XFONT_GetTextMetric
872 static void XFONT_GetTextMetric( fontObject
* pfo
, LPTEXTMETRIC32A pTM
)
874 LPIFONTINFO16 pdf
= &pfo
->fi
->df
;
876 if( ! pfo
->lpX11Trans
) {
877 pTM
->tmAscent
= pfo
->fs
->ascent
;
878 pTM
->tmDescent
= pfo
->fs
->descent
;
880 pTM
->tmAscent
= pfo
->lpX11Trans
->ascent
;
881 pTM
->tmDescent
= pfo
->lpX11Trans
->descent
;
883 pTM
->tmHeight
= pTM
->tmAscent
+ pTM
->tmDescent
;
885 pTM
->tmAveCharWidth
= pfo
->foAvgCharWidth
;
886 pTM
->tmMaxCharWidth
= pfo
->foMaxCharWidth
;
888 pTM
->tmInternalLeading
= pfo
->foInternalLeading
;
889 pTM
->tmExternalLeading
= pdf
->dfExternalLeading
;
891 pTM
->tmStruckOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
)
892 ? 1 : pdf
->dfStrikeOut
;
893 pTM
->tmUnderlined
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
)
894 ? 1 : pdf
->dfUnderline
;
897 if( pfo
->fo_flags
& FO_SYNTH_ITALIC
)
899 pTM
->tmOverhang
+= pTM
->tmHeight
/3;
902 pTM
->tmItalic
= pdf
->dfItalic
;
904 pTM
->tmWeight
= pdf
->dfWeight
;
905 if( pfo
->fo_flags
& FO_SYNTH_BOLD
)
908 pTM
->tmWeight
+= 100;
911 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pdf
->dfFirstChar
;
913 pTM
->tmCharSet
= pdf
->dfCharSet
;
914 pTM
->tmPitchAndFamily
= pdf
->dfPitchAndFamily
;
916 pTM
->tmDigitizedAspectX
= pdf
->dfHorizRes
;
917 pTM
->tmDigitizedAspectY
= pdf
->dfVertRes
;
920 /***********************************************************************
921 * XFONT_GetFontMetric
923 * Retrieve font metric info (enumeration).
925 static UINT32
XFONT_GetFontMetric( fontInfo
* pfi
, LPENUMLOGFONTEX16 pLF
,
926 LPNEWTEXTMETRIC16 pTM
)
928 memset( pLF
, 0, sizeof(*pLF
) );
929 memset( pTM
, 0, sizeof(*pTM
) );
931 #define plf ((LPLOGFONT16)pLF)
932 plf
->lfHeight
= pTM
->tmHeight
= pfi
->df
.dfPixHeight
;
933 plf
->lfWidth
= pTM
->tmAveCharWidth
= pfi
->df
.dfAvgWidth
;
934 plf
->lfWeight
= pTM
->tmWeight
= pfi
->df
.dfWeight
;
935 plf
->lfItalic
= pTM
->tmItalic
= pfi
->df
.dfItalic
;
936 plf
->lfUnderline
= pTM
->tmUnderlined
= pfi
->df
.dfUnderline
;
937 plf
->lfStrikeOut
= pTM
->tmStruckOut
= pfi
->df
.dfStrikeOut
;
938 plf
->lfCharSet
= pTM
->tmCharSet
= pfi
->df
.dfCharSet
;
940 /* convert pitch values */
942 pTM
->tmPitchAndFamily
= pfi
->df
.dfPitchAndFamily
;
943 plf
->lfPitchAndFamily
= (pfi
->df
.dfPitchAndFamily
& 0xF1) + 1;
945 lstrcpyn32A( plf
->lfFaceName
, pfi
->df
.dfFace
, LF_FACESIZE
);
948 pTM
->tmAscent
= pfi
->df
.dfAscent
;
949 pTM
->tmDescent
= pTM
->tmHeight
- pTM
->tmAscent
;
950 pTM
->tmInternalLeading
= pfi
->df
.dfInternalLeading
;
951 pTM
->tmMaxCharWidth
= pfi
->df
.dfMaxWidth
;
952 pTM
->tmDigitizedAspectX
= pfi
->df
.dfHorizRes
;
953 pTM
->tmDigitizedAspectY
= pfi
->df
.dfVertRes
;
955 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pfi
->df
.dfFirstChar
;
957 /* return font type */
959 return pfi
->df
.dfType
;
963 /***********************************************************************
966 * dfPitchAndFamily flags for some common typefaces.
968 static BYTE
XFONT_FixupFlags( LPCSTR lfFaceName
)
970 switch( lfFaceName
[0] )
973 case 'H': if(!strcasecmp(lfFaceName
, "Helvetica") )
977 case 'C': if(!strcasecmp(lfFaceName
, "Courier") ||
978 !strcasecmp(lfFaceName
, "Charter") )
982 case 'P': if( !strcasecmp(lfFaceName
,"Palatino") )
986 case 'T': if(!strncasecmp(lfFaceName
, "Times", 5) )
990 case 'U': if(!strcasecmp(lfFaceName
, "Utopia") )
994 case 'Z': if(!strcasecmp(lfFaceName
, "Zapf Dingbats") )
995 return FF_DECORATIVE
;
1001 /***********************************************************************
1002 * XFONT_CheckResourceName
1004 static BOOL32
XFONT_CheckResourceName( LPSTR resource
, LPCSTR name
, INT32 n
)
1006 resource
= LFD_Advance( resource
, 2 );
1008 return (!strncasecmp( resource
, name
, n
));
1013 /***********************************************************************
1014 * XFONT_WindowsNames
1016 * Build generic Windows aliases for X font names.
1018 * -misc-fixed- -> "Fixed"
1019 * -sony-fixed- -> "Sony Fixed", etc...
1021 static void XFONT_WindowsNames( char* buffer
)
1023 fontResource
* fr
, *pfr
;
1027 const char* relocTable
[] = { INIDefaultFixed
, INIDefault
, NULL
};
1029 for( fr
= fontList
; fr
; fr
= fr
->next
)
1031 if( fr
->fr_flags
& FR_NAMESET
) continue; /* skip already assigned */
1033 lpstr
= LFD_Advance(fr
->resource
, 2);
1034 i
= LFD_Advance( lpstr
, 1 ) - lpstr
;
1036 for( pfr
= fontList
; pfr
!= fr
; pfr
= pfr
->next
)
1037 if( pfr
->fr_flags
& FR_NAMESET
)
1038 if( XFONT_CheckResourceName( pfr
->resource
, lpstr
, i
) )
1041 if( pfr
!= fr
) /* prepend vendor name */
1042 lpstr
= fr
->resource
+ 1;
1044 for( i
= 0, up
= 1, lpch
= fr
->lfFaceName
; *lpstr
&& i
< 32;
1045 lpch
++, lpstr
++, i
++ )
1047 if( *lpstr
== LFDSeparator
[1] || *lpstr
== ' ' )
1052 else if( isalpha(*lpstr
) && up
)
1054 *lpch
= toupper(*lpstr
);
1059 while (*(lpch
- 1) == ' ') *(--lpch
) = '\0';
1061 if( (bFamilyStyle
= XFONT_FixupFlags( fr
->lfFaceName
)) )
1064 for( fi
= fr
->fi
; fi
; fi
= fi
->next
)
1065 fi
->df
.dfPitchAndFamily
|= bFamilyStyle
;
1068 TRACE(font
,"typeface \'%s\'\n", fr
->lfFaceName
);
1070 fr
->fr_flags
|= FR_NAMESET
;
1073 for( up
= 0; relocTable
[up
]; up
++ )
1074 if( PROFILE_GetWineIniString( INIFontSection
, relocTable
[up
], "", buffer
, 128 ) )
1076 while( *buffer
&& isspace(*buffer
) ) buffer
++;
1077 for( fr
= NULL
, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1079 i
= strlen( pfr
->resource
);
1080 if( !strncasecmp( pfr
->resource
, buffer
, i
) )
1084 fr
->next
= pfr
->next
;
1085 pfr
->next
= fontList
;
1095 /***********************************************************************
1098 static fontAlias
* XFONT_CreateAlias( LPCSTR lpTypeFace
, LPCSTR lpAlias
)
1101 fontAlias
* pfa
= aliasTable
;
1105 /* check if we already got one */
1106 if( !strcasecmp( pfa
->faTypeFace
, lpAlias
) )
1108 TRACE(font
,"\tredundant alias '%s' -> '%s'\n",
1109 lpAlias
, lpTypeFace
);
1112 if( pfa
->next
) pfa
= pfa
->next
;
1116 j
= lstrlen32A(lpTypeFace
) + 1;
1117 pfa
->next
= HeapAlloc( SystemHeap
, 0, sizeof(fontAlias
) +
1118 j
+ lstrlen32A(lpAlias
) + 1 );
1119 if((pfa
= pfa
->next
))
1122 pfa
->faTypeFace
= (LPSTR
)(pfa
+ 1);
1123 lstrcpy32A( pfa
->faTypeFace
, lpTypeFace
);
1124 pfa
->faAlias
= pfa
->faTypeFace
+ j
;
1125 lstrcpy32A( pfa
->faAlias
, lpAlias
);
1127 TRACE(font
, "\tadded alias '%s' for %s\n", lpAlias
, lpTypeFace
);
1134 /***********************************************************************
1137 * Read user-defined aliases from wine.conf. Format is as follows
1139 * Alias# = [Windows font name],[LFD font name], <substitute original name>
1142 * Alias0 = Arial, -adobe-helvetica-
1143 * Alias1 = Times New Roman, -bitstream-courier-, 1
1146 * Note that from 081797 and on we have built-in alias templates that take
1147 * care of the necessary Windows typefaces.
1149 static void XFONT_LoadAliases( char** buffer
, int buf_size
)
1151 char* lpResource
, *lpAlias
;
1152 char subsection
[32];
1154 BOOL32 bHaveAlias
= TRUE
, bSubst
= FALSE
;
1156 if( buf_size
< 128 )
1157 *buffer
= HeapReAlloc(SystemHeap
, 0, *buffer
, 256 );
1160 if( j
< faTemplateNum
)
1162 /* built-in templates first */
1164 lpResource
= faTemplate
[j
].fatResource
;
1165 lpAlias
= faTemplate
[j
].fatAlias
;
1170 /* then WINE.CONF */
1172 wsprintf32A( subsection
, "%s%i", INISubSection
, i
++ );
1174 if( (bHaveAlias
= PROFILE_GetWineIniString( INIFontSection
,
1175 subsection
, "", *buffer
, 128 )) )
1178 while( isspace(*lpAlias
) ) lpAlias
++;
1179 lpResource
= PROFILE_GetStringItem( lpAlias
);
1180 bSubst
= (PROFILE_GetStringItem( lpResource
)) ? TRUE
: FALSE
;
1188 length
= strlen( lpAlias
);
1189 if( lpResource
&& length
)
1191 fontResource
* fr
, *frMatch
= NULL
;
1193 for (fr
= fontList
; fr
; fr
= fr
->next
)
1195 if( !strcasecmp( fr
->resource
, lpResource
) ) frMatch
= fr
;
1196 if( XFONT_CheckResourceName( fr
->resource
, lpAlias
, length
) )
1198 /* alias is not needed since the real font is present */
1199 frMatch
= NULL
; break;
1207 fontAlias
*pfa
, *prev
= NULL
;
1209 for(pfa
= aliasTable
; pfa
; pfa
= pfa
->next
)
1211 /* Remove lpAlias from aliasTable - we should free the old entry */
1212 if(!strcmp(lpAlias
, pfa
->faAlias
))
1215 prev
->next
= pfa
->next
;
1217 aliasTable
= pfa
->next
;
1220 /* Update any references to the substituted font in aliasTable */
1221 if(!strcmp(frMatch
->lfFaceName
,
1223 pfa
->faTypeFace
= HEAP_strdupA( SystemHeap
, 0,
1228 TRACE(font
, "\tsubstituted '%s' with %s\n",
1229 frMatch
->lfFaceName
, lpAlias
);
1231 lstrcpyn32A( frMatch
->lfFaceName
, lpAlias
, LF_FACESIZE
);
1232 frMatch
->fr_flags
|= FR_NAMESET
;
1236 /* create new entry in the alias table */
1237 XFONT_CreateAlias( frMatch
->lfFaceName
, lpAlias
);
1241 else ERR(font
, " malformed font alias '%s'\n", *buffer
);
1247 /***********************************************************************
1248 * XFONT_UserMetricsCache
1250 * Returns expanded name for the ~/.wine/.cachedmetrics file.
1252 static char* XFONT_UserMetricsCache( char* buffer
, int* buf_size
)
1256 pwd
= getpwuid(getuid());
1257 if( pwd
&& pwd
->pw_dir
)
1259 int i
= strlen( pwd
->pw_dir
) + strlen( INIWinePrefix
) +
1260 strlen( INIFontMetrics
) + 2;
1262 buffer
= (char*) HeapReAlloc( SystemHeap
, 0, buffer
, *buf_size
= i
);
1263 strcpy( buffer
, pwd
->pw_dir
);
1264 strcat( buffer
, INIWinePrefix
);
1265 strcat( buffer
, INIFontMetrics
);
1266 } else buffer
[0] = '\0';
1271 /***********************************************************************
1272 * XFONT_ReadCachedMetrics
1274 static BOOL32
XFONT_ReadCachedMetrics( int fd
, int res
, unsigned x_checksum
, int x_count
)
1281 /* read checksums */
1282 read( fd
, &u
, sizeof(unsigned) );
1283 read( fd
, &i
, sizeof(int) );
1285 if( u
== x_checksum
&& i
== x_count
)
1287 off_t length
, offset
= 3 * sizeof(int);
1289 /* read total size */
1290 read( fd
, &i
, sizeof(int) );
1291 length
= lseek( fd
, 0, SEEK_END
);
1293 if( length
== (i
+ offset
) )
1295 lseek( fd
, offset
, SEEK_SET
);
1296 fontList
= (fontResource
*)HeapAlloc( SystemHeap
, 0, i
);
1299 fontResource
* pfr
= fontList
;
1300 fontInfo
* pfi
= NULL
;
1302 TRACE(font
,"Reading cached font metrics:\n");
1304 read( fd
, fontList
, i
); /* read all metrics at once */
1305 while( offset
< length
)
1307 offset
+= sizeof(fontResource
) + sizeof(fontInfo
);
1308 pfr
->fi
= pfi
= (fontInfo
*)(pfr
+ 1);
1312 if( offset
> length
||
1313 (int)(pfi
->next
) != j
++ ) goto fail
;
1315 pfi
->df
.dfFace
= pfr
->lfFaceName
;
1316 pfi
->df
.dfHorizRes
= pfi
->df
.dfVertRes
= res
;
1317 pfi
->df
.dfPoints
= (INT16
)(((INT32
)(pfi
->df
.dfPixHeight
-
1318 pfi
->df
.dfInternalLeading
) * 72 + (res
>> 1)) / res
);
1319 pfi
->next
= pfi
+ 1;
1321 if( j
> pfr
->count
) break;
1324 offset
+= sizeof(fontInfo
);
1329 pfr
->next
= (fontResource
*)(pfi
+ 1);
1334 if( pfr
->next
== NULL
&&
1335 *(int*)(pfi
+ 1) == X_FMC_MAGIC
)
1337 /* read LFD stubs */
1338 char* lpch
= (char*)((int*)(pfi
+ 1) + 1);
1339 offset
+= sizeof(int);
1340 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1342 TRACE(font
,"\t%s, %i instances\n", lpch
, pfr
->count
);
1343 pfr
->resource
= lpch
;
1346 if( ++offset
> length
) goto fail
;
1347 if( !*lpch
++ ) break;
1357 if( fontList
) HeapFree( SystemHeap
, 0, fontList
);
1364 /***********************************************************************
1365 * XFONT_WriteCachedMetrics
1367 static BOOL32
XFONT_WriteCachedMetrics( int fd
, unsigned x_checksum
, int x_count
, int n_ff
)
1376 /* font metrics file:
1380 * +0008 total size to load
1381 * +000C prepackaged font metrics
1384 * +...x + 4 LFD stubs
1387 write( fd
, &x_checksum
, sizeof(unsigned) );
1388 write( fd
, &x_count
, sizeof(int) );
1390 for( j
= i
= 0, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1392 i
+= strlen( pfr
->resource
) + 1;
1395 i
+= n_ff
* sizeof(fontResource
) + j
* sizeof(fontInfo
) + sizeof(int);
1396 write( fd
, &i
, sizeof(int) );
1398 TRACE(font
,"Writing font cache:\n");
1400 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1404 TRACE(font
,"\t%s, %i instances\n", pfr
->resource
, pfr
->count
);
1406 i
= write( fd
, pfr
, sizeof(fontResource
) );
1407 if( i
== sizeof(fontResource
) )
1409 for( k
= 1, pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
1411 memcpy( &fi
, pfi
, sizeof(fi
) );
1413 fi
.df
.dfFace
= NULL
;
1414 fi
.next
= (fontInfo
*)k
; /* loader checks this */
1416 j
= write( fd
, &fi
, sizeof(fi
) );
1419 if( j
== sizeof(fontInfo
) ) continue;
1423 if( i
== sizeof(fontResource
) && j
== sizeof(fontInfo
) )
1425 i
= j
= X_FMC_MAGIC
;
1426 write( fd
, &i
, sizeof(int) );
1427 for( pfr
= fontList
; pfr
&& i
== j
; pfr
= pfr
->next
)
1429 i
= strlen( pfr
->resource
) + 1;
1430 j
= write( fd
, pfr
->resource
, i
);
1439 /***********************************************************************
1440 * XFONT_CheckIniSection
1442 * Examines wine.conf for old/invalid font entries and recommend changes to
1446 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1447 * Original implementation.
1449 static void XFONT_CheckIniCallback(char const *, char const *, void *);
1451 static char const *fontmsgprologue
=
1453 " The following entries in the [fonts] section of the wine.conf file are\n"
1454 " obsolete or invalid:\n";
1456 static char const *fontmsgepilogue
=
1457 " These entries should be eliminated or updated.\n"
1458 " See the documentation/fonts file for more information.\n";
1460 static int XFONT_CheckIniSection()
1464 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback
,
1467 MSG(fontmsgepilogue
);
1472 static void XFONT_CheckIniCallback(
1477 /* Ignore any keys that start with potential comment characters "'", '#',
1479 if(key
[0] == '\'' || key
[0] == '#' || key
[0] == ';' || key
[0] == '\0')
1482 /* Make sure this is a valid key */
1483 if((strncasecmp(key
, INISubSection
, 5) == 0) ||
1484 (strcasecmp( key
, INIDefault
) == 0) ||
1485 (strcasecmp( key
, INIDefaultFixed
) == 0) ||
1486 (strcasecmp( key
, INIGlobalMetrics
) == 0) ||
1487 (strcasecmp( key
, INIResolution
) == 0) )
1489 /* Valid key; make sure the value doesn't contain a wildcard */
1490 if(strchr(value
, '*')) {
1491 if(*(int *)found
== 0) {
1492 MSG(fontmsgprologue
);
1496 MSG(" %s=%s [no wildcards allowed]\n", key
, value
);
1500 /* Not a valid key */
1501 if(*(int *)found
== 0) {
1502 MSG(fontmsgprologue
);
1506 MSG(" %s=%s [obsolete]\n", key
, value
);
1512 /***********************************************************************
1513 * XFONT_GetPointResolution()
1515 * Here we initialize DefResolution which is used in the
1516 * XFONT_Match() penalty function. We also load the point
1517 * resolution value (higher values result in larger fonts).
1519 static int XFONT_GetPointResolution( DeviceCaps
* pDevCaps
)
1521 int i
, j
, point_resolution
, num
= 3;
1522 int allowed_xfont_resolutions
[3] = { 72, 75, 100 };
1523 int best
= 0, best_diff
= 65536;
1525 DefResolution
= point_resolution
= PROFILE_GetWineIniInt( INIFontSection
, INIResolution
, 0 );
1526 if( !DefResolution
) DefResolution
= point_resolution
= pDevCaps
->logPixelsY
;
1527 else pDevCaps
->logPixelsX
= pDevCaps
->logPixelsY
= DefResolution
;
1529 for( i
= best
= 0; i
< num
; i
++ )
1531 j
= abs( DefResolution
- allowed_xfont_resolutions
[i
] );
1538 DefResolution
= allowed_xfont_resolutions
[best
];
1539 return point_resolution
;
1542 /***********************************************************************
1545 * Initialize font resource list and allocate font cache.
1547 BOOL32
X11DRV_FONT_Init( DeviceCaps
* pDevCaps
)
1550 fontResource
* fr
, *pfr
;
1552 unsigned x_checksum
;
1553 int i
, j
, res
, x_count
, fd
= -1, buf_size
= 0;
1554 char* lpstr
, *lpch
, *lpmetrics
, *buffer
;
1557 XFONT_CheckIniSection();
1559 res
= XFONT_GetPointResolution( pDevCaps
);
1561 x_pattern
= TSXListFonts(display
, "*", MAX_FONT_FAMILIES
* 16, &x_count
);
1563 TRACE(font
,"Font Mapper: initializing %i fonts [LPY=%i, XDR=%i, DR=%i]\n",
1564 x_count
, pDevCaps
->logPixelsY
, DefResolution
, res
);
1565 for( i
= x_checksum
= 0; i
< x_count
; i
++ )
1568 printf("%i\t: %s\n", i
, x_pattern
[i
] );
1571 j
= strlen( x_pattern
[i
] );
1572 if( j
) x_checksum
^= __genericCheckSum( x_pattern
[i
], j
);
1574 x_checksum
|= X_PFONT_MAGIC
;
1577 buffer
= HeapAlloc( SystemHeap
, 0, buf_size
);
1580 /* deal with systemwide font metrics cache */
1582 if( PROFILE_GetWineIniString( INIFontSection
, INIGlobalMetrics
, "", buffer
, 128 ) )
1583 fd
= open( buffer
, O_RDONLY
);
1585 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1588 buffer
= XFONT_UserMetricsCache( buffer
, &buf_size
);
1591 fd
= open( buffer
, O_RDONLY
);
1592 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1593 lpmetrics
= HEAP_strdupA( SystemHeap
, 0, buffer
); /* update later on */
1598 if( fontList
== NULL
) /* build metrics from scratch */
1603 for( i
= n_ff
= 0; i
< x_count
; i
++ )
1605 typeface
= lpch
= x_pattern
[i
];
1607 lpch
= LFD_Advance(typeface
, 3); /* extra '-' in the beginning */
1608 if( !*lpch
) continue;
1611 j
= lpch
- typeface
; /* resource name length */
1613 /* find a family to insert into */
1615 for( pfr
= NULL
, fr
= fontList
; fr
; fr
= fr
->next
)
1617 if( !strncasecmp(fr
->resource
, typeface
, j
) &&
1618 strlen(fr
->resource
) == j
) break;
1622 if( !fi
) fi
= (fontInfo
*) HeapAlloc(SystemHeap
, 0, sizeof(fontInfo
));
1624 if( !fr
) /* add new family */
1626 if( n_ff
>= MAX_FONT_FAMILIES
) break;
1627 if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1630 fr
= (fontResource
*) HeapAlloc(SystemHeap
, 0, sizeof(fontResource
));
1631 memset(fr
, 0, sizeof(fontResource
));
1632 fr
->resource
= (char*) HeapAlloc(SystemHeap
, 0, j
+ 1 );
1633 lstrcpyn32A( fr
->resource
, typeface
, j
+ 1 );
1635 TRACE(font
," family: %s\n", fr
->resource
);
1637 if( pfr
) pfr
->next
= fr
;
1640 else if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1642 /* check if we already have something better than "fi" */
1644 for( pfi
= fr
->fi
, j
= 0; pfi
&& j
<= 0; pfi
= pfi
->next
)
1645 if( (j
= XFONT_IsSubset( pfi
, fi
)) < 0 )
1646 pfi
->fi_flags
|= FI_SUBSET
; /* superseded by "fi" */
1647 if( j
> 0 ) continue;
1649 /* add new font instance "fi" to the "fr" font resource */
1651 if( fi
->fi_flags
& FI_SCALABLE
)
1653 /* set scalable font height to 24 to get an origin for extrapolation */
1655 j
= strlen(typeface
); j
+= 0x10;
1657 buffer
= (char*)HeapReAlloc( SystemHeap
, 0, buffer
, buf_size
= j
);
1659 lpch
= LFD_Advance(typeface
, 7);
1660 memcpy( buffer
, typeface
, (j
= lpch
- typeface
) );
1661 lpch
= LFD_Advance(lpch
, 4);
1662 sprintf( buffer
+ j
, "%d-%d-%d-*-%c-*-", fi
->lfd_height
,
1663 fi
->lfd_decipoints
, fi
->lfd_resolution
,
1664 (*lpch
== '-')?'*':*lpch
);
1665 lpch
= LFD_Advance(lpch
, 2);
1666 strcat( lpstr
= buffer
, lpch
);
1668 else lpstr
= typeface
;
1670 if( (x_fs
= TSXLoadQueryFont(display
, lpstr
)) )
1672 fi
->df
.dfHorizRes
= fi
->df
.dfVertRes
= res
;
1674 XFONT_SetFontMetric( fi
, fr
, x_fs
);
1675 TSXFreeFont( display
, x_fs
);
1677 TRACE(font
,"\t[% 2ipt] '%s'\n", fi
->df
.dfPoints
, typeface
);
1679 XFONT_CheckFIList( fr
, fi
, REMOVE_SUBSETS
);
1680 fi
= NULL
; /* preventing reuse */
1684 ERR(font
, "failed to load %s\n", lpstr
);
1686 XFONT_CheckFIList( fr
, fi
, UNMARK_SUBSETS
);
1690 if( lpmetrics
) /* update cached metrics */
1692 fd
= open( lpmetrics
, O_CREAT
| O_TRUNC
| O_RDWR
, 0644 ); /* -rw-r--r-- */
1693 if( XFONT_WriteCachedMetrics( fd
, x_checksum
, x_count
, n_ff
) == FALSE
)
1694 if( fd
) remove( lpmetrics
); /* couldn't write entire file */
1695 HeapFree( SystemHeap
, 0, lpmetrics
);
1699 if( fi
) HeapFree(SystemHeap
, 0, fi
);
1700 TSXFreeFontNames(x_pattern
);
1702 /* check if we're dealing with X11 R6 server */
1704 strcpy(buffer
, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1705 if( (x_fs
= TSXLoadQueryFont(display
, buffer
)) )
1707 XTextCaps
|= TC_SF_X_YINDEP
;
1708 TSXFreeFont(display
, x_fs
);
1711 XFONT_WindowsNames( buffer
);
1712 XFONT_LoadAliases( &buffer
, buf_size
);
1713 HeapFree(SystemHeap
, 0, buffer
);
1716 /* fontList initialization is over, allocate X font cache */
1718 fontCache
= (fontObject
*) HeapAlloc(SystemHeap
, 0, fontCacheSize
* sizeof(fontObject
));
1719 XFONT_GrowFreeList(0, fontCacheSize
- 1);
1721 TRACE(font
,"done!\n");
1723 /* update text caps parameter */
1725 pDevCaps
->textCaps
= XTextCaps
;
1727 RAW_ASCENT
= TSXInternAtom(display
, "RAW_ASCENT", TRUE
);
1728 RAW_DESCENT
= TSXInternAtom(display
, "RAW_DESCENT", TRUE
);
1734 /***********************************************************************
1737 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1739 static INT32
XFONT_IsSubset(fontInfo
* match
, fontInfo
* fi
)
1743 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1745 m
= (BYTE
*)&fi
->df
.dfPixWidth
- (BYTE
*)&fi
->df
.dfItalic
;
1746 if( memcmp(&match
->df
.dfItalic
, &fi
->df
.dfItalic
, m
)) return 0;
1748 if( (!((fi
->fi_flags
& FI_SCALABLE
) + (match
->fi_flags
& FI_SCALABLE
))
1749 && fi
->lfd_height
!= match
->lfd_height
) ||
1750 (!((fi
->fi_flags
& FI_POLYWEIGHT
) + (match
->fi_flags
& FI_POLYWEIGHT
))
1751 && fi
->df
.dfWeight
!= match
->df
.dfWeight
) ) return 0;
1753 m
= (int)(match
->fi_flags
& (FI_POLYWEIGHT
| FI_SCALABLE
)) -
1754 (int)(fi
->fi_flags
& (FI_SCALABLE
| FI_POLYWEIGHT
));
1756 if( m
== (FI_POLYWEIGHT
- FI_SCALABLE
) ||
1757 m
== (FI_SCALABLE
- FI_POLYWEIGHT
) ) return 0; /* keep both */
1758 else if( m
>= 0 ) return 1; /* 'match' is better */
1760 return -1; /* 'fi' is better */
1763 /***********************************************************************
1766 * Compute the matching score between the logical font and the device font.
1768 * contributions from highest to lowest:
1772 * family flags (only when the facename is not present)
1774 * weight, italics, underlines, strikeouts
1776 * NOTE: you can experiment with different penalty weights to see what happens.
1777 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
1779 static UINT32
XFONT_Match( fontMatch
* pfm
)
1781 fontInfo
* pfi
= pfm
->pfi
; /* device font to match */
1782 LPLOGFONT16 plf
= pfm
->plf
; /* wanted logical font */
1784 BOOL32 bR6
= pfm
->flags
& FO_MATCH_XYINDEP
; /* from TextCaps */
1785 BOOL32 bScale
= pfi
->fi_flags
& FI_SCALABLE
;
1788 TRACE(font
,"\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi
->df
.dfPoints
,
1789 pfi
->df
.dfPixHeight
, pfi
->df
.dfAvgWidth
,
1790 (pfi
->df
.dfWeight
> 400) ? "Bold " : "Normal ",
1791 (pfi
->df
.dfItalic
) ? "Italic" : "" );
1795 if( plf
->lfCharSet
== DEFAULT_CHARSET
)
1797 if( (pfi
->df
.dfCharSet
!= ANSI_CHARSET
) && (pfi
->df
.dfCharSet
!=DEFAULT_CHARSET
) )
1800 else if (plf
->lfCharSet
!= pfi
->df
.dfCharSet
) penalty
+= 0x200;
1802 /* FIXME: Hack to demote symbols and nil fonts. Should take into
1803 account if a program ever actually asked for this type of
1805 if ( (strcmp(pfm
->pfr
->lfFaceName
,"Symbol")==0) || (strcmp(pfm
->pfr
->lfFaceName
,"Nil")==0) )
1806 penalty
+= 0x200; /* very stiff penality */
1808 /* TMPF_FIXED_PITCH means exactly the opposite */
1810 if( plf
->lfPitchAndFamily
& FIXED_PITCH
)
1812 if( pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) penalty
+= 0x100;
1814 else if( !(pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) ) penalty
+= 0x2;
1816 if( plf
->lfHeight
> 0 )
1817 d
= (h
= pfi
->df
.dfPixHeight
) - plf
->lfHeight
;
1818 else if( plf
->lfHeight
< -1 )
1819 d
= (h
= pfi
->df
.dfPoints
) + plf
->lfHeight
;
1822 if( d
&& plf
->lfHeight
)
1824 UINT16 height
= ( plf
->lfHeight
> 0 ) ? plf
->lfHeight
1825 : ((-plf
->lfHeight
* pfi
->df
.dfPixHeight
) / h
);
1826 if( bScale
) pfm
->height
= height
;
1827 else if( (plf
->lfQuality
!= PROOF_QUALITY
) && bR6
)
1829 if( d
> 0 ) /* do not shrink raster fonts */
1831 pfm
->height
= pfi
->df
.dfPixHeight
;
1832 penalty
+= (pfi
->df
.dfPixHeight
- height
) * 0x4;
1834 else /* expand only in integer multiples */
1836 pfm
->height
= height
- height
%pfi
->df
.dfPixHeight
;
1837 penalty
+= (height
- pfm
->height
+ 1) * height
/ pfi
->df
.dfPixHeight
;
1840 else /* can't be scaled at all */
1842 if( plf
->lfQuality
!= PROOF_QUALITY
) pfm
->flags
|= FO_SYNTH_HEIGHT
;
1843 pfm
->height
= pfi
->df
.dfPixHeight
;
1844 penalty
+= (d
> 0)? d
* 0x8 : -d
* 0x10;
1846 } else pfm
->height
= pfi
->df
.dfPixHeight
;
1848 if((pfm
->flags
& FO_MATCH_PAF
) &&
1849 (plf
->lfPitchAndFamily
& FF_FAMILY
) != (pfi
->df
.dfPitchAndFamily
& FF_FAMILY
) )
1854 if( bR6
&& bScale
) h
= 0;
1857 /* FIXME: not complete */
1859 pfm
->flags
|= FO_SYNTH_WIDTH
;
1860 h
= abs(plf
->lfWidth
- (pfm
->height
* pfi
->df
.dfAvgWidth
)/pfi
->df
.dfPixHeight
);
1862 penalty
+= h
* ( d
) ? 0x2 : 0x1 ;
1864 else if( !(pfi
->fi_flags
& FI_NORMAL
) ) penalty
++;
1866 if( plf
->lfWeight
!= FW_DONTCARE
)
1868 penalty
+= abs(plf
->lfWeight
- pfi
->df
.dfWeight
) / 40;
1869 if( plf
->lfWeight
> pfi
->df
.dfWeight
) pfm
->flags
|= FO_SYNTH_BOLD
;
1870 } else if( pfi
->df
.dfWeight
>= FW_BOLD
) penalty
++; /* choose normal by default */
1872 if( plf
->lfItalic
!= pfi
->df
.dfItalic
)
1875 pfm
->flags
|= FO_SYNTH_ITALIC
;
1878 if( plf
->lfUnderline
) pfm
->flags
|= FO_SYNTH_UNDERLINE
;
1879 if( plf
->lfStrikeOut
) pfm
->flags
|= FO_SYNTH_STRIKEOUT
;
1881 if( penalty
&& pfi
->lfd_resolution
!= DefResolution
)
1884 TRACE(font
," returning %i\n", penalty
);
1889 /***********************************************************************
1892 * Scan a particular font resource for the best match.
1894 static UINT32
XFONT_MatchFIList( fontMatch
* pfm
)
1896 BOOL32 skipRaster
= (pfm
->flags
& FO_MATCH_NORASTER
);
1897 UINT32 current_score
, score
= (UINT32
)(-1);
1898 UINT16 origflags
= pfm
->flags
; /* Preserve FO_MATCH_XYINDEP */
1899 fontMatch fm
= *pfm
;
1901 for( fm
.pfi
= pfm
->pfr
->fi
; fm
.pfi
&& score
; fm
.pfi
= fm
.pfi
->next
,
1902 fm
.flags
= origflags
)
1904 if( skipRaster
&& !(fm
.pfi
->fi_flags
& FI_SCALABLE
) )
1907 current_score
= XFONT_Match( &fm
);
1908 if( score
> current_score
)
1910 memcpy( pfm
, &fm
, sizeof(fontMatch
) );
1911 score
= current_score
;
1917 /***********************************************************************
1920 * REMOVE_SUBSETS - attach new fi and purge subsets
1921 * UNMARK_SUBSETS - remove subset flags from all fi entries
1923 static void XFONT_CheckFIList( fontResource
* fr
, fontInfo
* fi
, int action
)
1926 fontInfo
* pfi
, *prev
;
1928 for( prev
= NULL
, pfi
= fr
->fi
; pfi
; )
1930 if( action
== REMOVE_SUBSETS
)
1932 if( pfi
->fi_flags
& FI_SUBSET
)
1934 fontInfo
* subset
= pfi
;
1938 if( prev
) prev
->next
= pfi
= pfi
->next
;
1939 else fr
->fi
= pfi
= pfi
->next
;
1940 HeapFree( SystemHeap
, 0, subset
);
1944 else pfi
->fi_flags
&= ~FI_SUBSET
;
1950 if( action
== REMOVE_SUBSETS
) /* also add the superset */
1952 if( fi
->fi_flags
& FI_SCALABLE
)
1957 else if( prev
) prev
->next
= fi
; else fr
->fi
= fi
;
1961 if( i
) TRACE(font
,"\t purged %i subsets [%i]\n", i
, fr
->count
);
1964 /***********************************************************************
1967 static fontResource
* XFONT_FindFIList( fontResource
* pfr
, const char* pTypeFace
)
1971 if( !strcasecmp( pfr
->lfFaceName
, pTypeFace
) ) break;
1977 /***********************************************************************
1978 * XFONT_MatchDeviceFont
1980 * Scan font resource tree.
1982 static BOOL32
XFONT_MatchDeviceFont( fontResource
* start
, fontMatch
* pfm
)
1984 fontMatch fm
= *pfm
;
1987 if( fm
.plf
->lfFaceName
[0] )
1992 for( fa
= aliasTable
; fa
; fa
= fa
->next
)
1993 if( !strcmp( fa
->faAlias
, fm
.plf
->lfFaceName
) )
1995 str
= fa
->faTypeFace
;
1998 fm
.pfr
= XFONT_FindFIList( start
, str
? str
: fm
.plf
->lfFaceName
);
2001 if( fm
.pfr
) /* match family */
2003 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
2005 XFONT_MatchFIList( &fm
);
2009 if( !pfm
->pfi
) /* match all available fonts */
2011 UINT32 current_score
, score
= (UINT32
)(-1);
2013 fm
.flags
|= FO_MATCH_PAF
;
2014 for( start
= fontList
; start
&& score
; start
= start
->next
)
2018 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
2020 current_score
= XFONT_MatchFIList( &fm
);
2021 if( current_score
< score
)
2023 score
= current_score
;
2032 /***********************************************************************
2035 static void XFONT_GrowFreeList(int start
, int end
)
2037 /* add all entries from 'start' up to and including 'end' */
2039 memset( fontCache
+ start
, 0, (end
- start
+ 1) * sizeof(fontObject
) );
2041 fontCache
[end
].lru
= fontLF
;
2042 fontCache
[end
].count
= -1;
2044 while( start
< end
)
2046 fontCache
[start
].count
= -1;
2047 fontCache
[start
].lru
= start
+ 1;
2052 static fontObject
* XFONT_LookupCachedFont( LPLOGFONT16 plf
, UINT16
* checksum
)
2054 UINT16 cs
= __lfCheckSum( plf
);
2055 int i
= fontMRU
, prev
= -1;
2060 if( fontCache
[i
].lfchecksum
== cs
&&
2061 !(fontCache
[i
].fo_flags
& FO_REMOVED
) )
2063 /* FIXME: something more intelligent here */
2065 if( !memcmp( plf
, &fontCache
[i
].lf
,
2066 sizeof(LOGFONT16
) - LF_FACESIZE
) &&
2067 !strncasecmp( plf
->lfFaceName
, fontCache
[i
].lf
.lfFaceName
,
2070 /* remove temporarily from the lru list */
2073 fontCache
[prev
].lru
= fontCache
[i
].lru
;
2075 fontMRU
= (INT16
)fontCache
[i
].lru
;
2076 return (fontCache
+ i
);
2080 i
= (INT16
)fontCache
[i
].lru
;
2085 static fontObject
* XFONT_GetCacheEntry()
2091 int prev_i
, prev_j
, j
;
2093 TRACE(font
,"font cache is full\n");
2095 /* lookup the least recently used font */
2097 for( prev_i
= prev_j
= j
= -1, i
= fontMRU
; i
>= 0; i
= (INT16
)fontCache
[i
].lru
)
2099 if( fontCache
[i
].count
<= 0 &&
2100 !(fontCache
[i
].fo_flags
& FO_SYSTEM
) )
2108 if( j
>= 0 ) /* unload font */
2110 /* detach from the lru list */
2112 TRACE(font
,"\tfreeing entry %i\n", j
);
2115 fontCache
[prev_j
].lru
= fontCache
[j
].lru
;
2116 else fontMRU
= (INT16
)fontCache
[j
].lru
;
2118 /* FIXME: lpXForm, lpPixmap */
2119 if(fontCache
[j
].lpX11Trans
)
2120 HeapFree( SystemHeap
, 0, fontCache
[j
].lpX11Trans
);
2122 TSXFreeFont( display
, fontCache
[j
].fs
);
2124 memset( fontCache
+ j
, 0, sizeof(fontObject
) );
2125 return (fontCache
+ j
);
2127 else /* expand cache */
2129 fontObject
* newCache
;
2131 prev_i
= fontCacheSize
+ FONTCACHE
;
2133 TRACE(font
,"\tgrowing font cache from %i to %i\n", fontCacheSize
, prev_i
);
2135 if( (newCache
= (fontObject
*)HeapReAlloc(SystemHeap
, 0,
2136 fontCache
, prev_i
)) )
2139 fontCacheSize
= prev_i
;
2140 fontCache
= newCache
;
2141 XFONT_GrowFreeList( i
, fontCacheSize
- 1);
2147 /* detach from the free list */
2150 fontLF
= (INT16
)fontCache
[i
].lru
;
2151 fontCache
[i
].count
= 0;
2152 return (fontCache
+ i
);
2155 static int XFONT_ReleaseCacheEntry(fontObject
* pfo
)
2157 UINT32 u
= (UINT32
)(pfo
- fontCache
);
2159 if( u
< fontCacheSize
) return (--fontCache
[u
].count
);
2163 /**********************************************************************
2166 static BOOL32
XFONT_SetX11Trans( fontObject
*pfo
)
2173 TSXGetFontProperty( pfo
->fs
, XA_FONT
, &nameAtom
);
2174 fontName
= TSXGetAtomName( display
, nameAtom
);
2175 for(i
= 0, cp
= fontName
; i
< 7; i
++) {
2176 cp
= strchr(cp
, '-');
2184 while((cp
= strchr(cp
, '~')))
2187 #define PX pfo->lpX11Trans
2189 sscanf(start
, "[%f%f%f%f]", &PX
->a
, &PX
->b
, &PX
->c
, &PX
->d
);
2192 TSXGetFontProperty( pfo
->fs
, RAW_ASCENT
, &PX
->RAW_ASCENT
);
2193 TSXGetFontProperty( pfo
->fs
, RAW_DESCENT
, &PX
->RAW_DESCENT
);
2195 PX
->pixelsize
= hypot(PX
->a
, PX
->b
);
2196 PX
->ascent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_ASCENT
;
2197 PX
->descent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_DESCENT
;
2199 TRACE(font
, "[%f %f %f %f] RA = %ld RD = %ld\n", pfo
->lpX11Trans
->a
,
2200 pfo
->lpX11Trans
->b
, pfo
->lpX11Trans
->c
, pfo
->lpX11Trans
->d
,
2201 pfo
->lpX11Trans
->RAW_ASCENT
, pfo
->lpX11Trans
->RAW_DESCENT
);
2207 /***********************************************************************
2208 * X Device Font Objects
2210 static X_PHYSFONT
XFONT_RealizeFont( LPLOGFONT16 plf
)
2213 fontObject
* pfo
= XFONT_LookupCachedFont( plf
, &checksum
);
2217 fontMatch fm
= { NULL
, NULL
, 0, 0, plf
};
2220 if( XTextCaps
& TC_SF_X_YINDEP
) fm
.flags
= FO_MATCH_XYINDEP
;
2222 /* allocate new font cache entry */
2224 if( (pfo
= XFONT_GetCacheEntry()) )
2226 LPSTR lpLFD
= HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH
);
2228 if( lpLFD
) /* initialize entry and load font */
2230 UINT32 uRelaxLevel
= 0;
2232 TRACE(font
,"(%u) '%s' h=%i weight=%i %s\n",
2233 plf
->lfCharSet
, plf
->lfFaceName
, plf
->lfHeight
,
2234 plf
->lfWeight
, (plf
->lfItalic
) ? "Italic" : "" );
2236 if(abs(plf
->lfHeight
) > MAX_FONT_SIZE
) {
2238 "plf->lfHeight = %d, this is probably not right. Setting to 100\n",
2240 plf
->lfHeight
= 100;
2243 XFONT_MatchDeviceFont( fontList
, &fm
);
2247 pfo
->fo_flags
= fm
.flags
& ~FO_MATCH_MASK
;
2249 memcpy( &pfo
->lf
, plf
, sizeof(LOGFONT16
) );
2250 pfo
->lfchecksum
= checksum
;
2254 LFD_ComposeLFD( pfo
, fm
.height
, lpLFD
, uRelaxLevel
++ );
2255 if( (pfo
->fs
= TSXLoadQueryFont( display
, lpLFD
)) ) break;
2256 } while( uRelaxLevel
);
2259 if(pfo
->lf
.lfEscapement
!= 0) {
2260 pfo
->lpX11Trans
= HeapAlloc(SystemHeap
, 0,
2261 sizeof(XFONTTRANS
));
2262 if(!XFONT_SetX11Trans( pfo
)) {
2263 HeapFree(SystemHeap
, 0, pfo
->lpX11Trans
);
2264 pfo
->lpX11Trans
= NULL
;
2268 if( XFONT_GetLeading( &pfo
->fi
->df
, pfo
->fs
, &i
, NULL
,
2271 if(!pfo
->lpX11Trans
)
2272 pfo
->foAvgCharWidth
=
2273 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].width
;
2275 pfo
->foAvgCharWidth
=
2276 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].attributes
2277 * pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2279 pfo
->foAvgCharWidth
= (INT16
)XFONT_GetAvgCharWidth(
2280 &pfo
->fi
->df
, pfo
->fs
, pfo
->lpX11Trans
);
2281 pfo
->foMaxCharWidth
= (INT16
)XFONT_GetMaxCharWidth(pfo
);
2282 pfo
->foInternalLeading
= (INT16
)i
;
2284 /* FIXME: If we've got a soft font or
2285 * there are FO_SYNTH_... flags for the
2286 * non PROOF_QUALITY request, the engine
2287 * should rasterize characters into mono
2288 * pixmaps and store them in the pfo->lpPixmap
2289 * array (pfo->fs should be updated as well).
2290 * X11DRV_ExtTextOut() must be heavily modified
2291 * to support pixmap blitting and FO_SYNTH_...
2295 pfo
->lpXForm
= NULL
;
2296 pfo
->lpPixmap
= NULL
;
2298 HeapFree( GetProcessHeap(), 0, lpLFD
);
2300 else /* attach back to the free list */
2304 fontLF
= (pfo
- fontCache
);
2309 if( !pfo
) /* couldn't get a new entry, get one of the cached fonts */
2311 UINT32 current_score
, score
= (UINT32
)(-1);
2313 i
= index
= fontMRU
;
2314 fm
.flags
|= FO_MATCH_PAF
;
2317 pfo
= fontCache
+ i
;
2318 fm
.pfr
= pfo
->fr
; fm
.pfi
= pfo
->fi
;
2320 current_score
= XFONT_Match( &fm
);
2321 if( current_score
< score
) index
= i
;
2325 pfo
= fontCache
+ index
;
2327 return (X_PHYSFONT
)(X_PFONT_MAGIC
| index
);
2331 /* attach at the head of the lru list */
2335 fontMRU
= (pfo
- fontCache
);
2337 TRACE(font
,"physfont %i\n", fontMRU
);
2339 return (X_PHYSFONT
)(X_PFONT_MAGIC
| fontMRU
);
2342 /***********************************************************************
2343 * XFONT_GetFontObject
2345 fontObject
* XFONT_GetFontObject( X_PHYSFONT pFont
)
2347 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
);
2351 /***********************************************************************
2352 * XFONT_GetFontStruct
2354 XFontStruct
* XFONT_GetFontStruct( X_PHYSFONT pFont
)
2356 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
)->fs
;
2360 /***********************************************************************
2363 LPIFONTINFO16
XFONT_GetFontInfo( X_PHYSFONT pFont
)
2365 if( CHECK_PFONT(pFont
) ) return &(__PFONT(pFont
)->fi
->df
);
2371 /* X11DRV Interface ****************************************************
2373 * Exposed via the dc->funcs dispatch table. *
2375 ***********************************************************************/
2376 /***********************************************************************
2377 * X11DRV_FONT_SelectObject
2379 HFONT32
X11DRV_FONT_SelectObject( DC
* dc
, HFONT32 hfont
, FONTOBJ
* font
)
2381 HFONT32 hPrevFont
= 0;
2383 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2385 if( CHECK_PFONT(physDev
->font
) )
2386 XFONT_ReleaseCacheEntry( __PFONT(physDev
->font
) );
2388 /* FIXME: do we need to pass anything back from here? */
2389 memcpy(&lf
,&font
->logfont
,sizeof(lf
));
2390 lf
.lfWidth
= font
->logfont
.lfWidth
* dc
->vportExtX
/dc
->wndExtX
;
2391 lf
.lfHeight
= font
->logfont
.lfHeight
* dc
->vportExtY
/dc
->wndExtY
;
2393 physDev
->font
= XFONT_RealizeFont( &lf
);
2394 hPrevFont
= dc
->w
.hFont
;
2395 dc
->w
.hFont
= hfont
;
2401 /***********************************************************************
2403 * X11DRV_EnumDeviceFonts
2405 BOOL32
X11DRV_EnumDeviceFonts( DC
* dc
, LPLOGFONT16 plf
,
2406 DEVICEFONTENUMPROC proc
, LPARAM lp
)
2410 fontResource
* pfr
= fontList
;
2413 if( plf
->lfFaceName
[0] )
2415 pfr
= XFONT_FindFIList( pfr
, plf
->lfFaceName
);
2419 for( pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
2420 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2421 XFONT_GetFontMetric( pfi
, &lf
, &tm
), lp
)) )
2427 for( ; pfr
; pfr
= pfr
->next
)
2430 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2431 XFONT_GetFontMetric( pfr
->fi
, &lf
, &tm
), lp
)) )
2440 /***********************************************************************
2441 * X11DRV_GetTextExtentPoint
2443 BOOL32
X11DRV_GetTextExtentPoint( DC
*dc
, LPCSTR str
, INT32 count
,
2446 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2447 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2449 if( !pfo
->lpX11Trans
) {
2450 int dir
, ascent
, descent
;
2453 TSXTextExtents( pfo
->fs
, str
, count
, &dir
, &ascent
, &descent
, &info
);
2454 size
->cx
= abs((info
.width
+ dc
->w
.breakRem
+ count
*
2455 dc
->w
.charExtra
) * dc
->wndExtX
/ dc
->vportExtX
);
2456 size
->cy
= abs((pfo
->fs
->ascent
+ pfo
->fs
->descent
) *
2457 dc
->wndExtY
/ dc
->vportExtY
);
2461 float x
= 0.0, y
= 0.0;
2462 for(i
= 0; i
< count
; i
++) {
2463 x
+= pfo
->fs
->per_char
?
2464 pfo
->fs
->per_char
[str
[i
] - pfo
->fs
->min_char_or_byte2
].attributes
:
2465 pfo
->fs
->min_bounds
.attributes
;
2467 y
= pfo
->lpX11Trans
->RAW_ASCENT
+ pfo
->lpX11Trans
->RAW_DESCENT
;
2468 TRACE(font
, "x = %f y = %f\n", x
, y
);
2469 x
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2470 y
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2471 size
->cx
= fabsf((x
+ dc
->w
.breakRem
+ count
* dc
->w
.charExtra
) *
2472 dc
->wndExtX
/ dc
->vportExtX
);
2473 size
->cy
= fabsf(y
* dc
->wndExtY
/ dc
->vportExtY
);
2481 /***********************************************************************
2482 * X11DRV_GetTextMetrics
2484 BOOL32
X11DRV_GetTextMetrics(DC
*dc
, TEXTMETRIC32A
*metrics
)
2486 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2488 if( CHECK_PFONT(physDev
->font
) )
2490 fontObject
* pfo
= __PFONT(physDev
->font
);
2491 XFONT_GetTextMetric( pfo
, metrics
);
2499 /***********************************************************************
2500 * X11DRV_GetCharWidth
2502 BOOL32
X11DRV_GetCharWidth( DC
*dc
, UINT32 firstChar
, UINT32 lastChar
,
2505 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2506 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2512 if (pfo
->fs
->per_char
== NULL
)
2513 for (i
= firstChar
; i
<= lastChar
; i
++)
2515 *buffer
++ = pfo
->fs
->min_bounds
.attributes
*
2516 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2518 *buffer
++ = pfo
->fs
->min_bounds
.width
;
2521 XCharStruct
*cs
, *def
;
2522 static XCharStruct __null_char
= { 0, 0, 0, 0, 0, 0 };
2524 CI_GET_CHAR_INFO(pfo
->fs
, pfo
->fs
->default_char
, &__null_char
,
2527 for (i
= firstChar
; i
<= lastChar
; i
++)
2529 if (i
>= pfo
->fs
->min_char_or_byte2
&&
2530 i
<= pfo
->fs
->max_char_or_byte2
)
2532 cs
= &pfo
->fs
->per_char
[(i
- pfo
->fs
->min_char_or_byte2
)];
2533 if (CI_NONEXISTCHAR(cs
)) cs
= def
;
2536 *buffer
++ = MAX(cs
->attributes
, 0) *
2537 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2539 *buffer
++ = MAX(cs
->width
, 0 );
2548 /***********************************************************************
2550 * Font Resource API *
2552 ***********************************************************************/
2553 /***********************************************************************
2554 * AddFontResource16 (GDI.119)
2556 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
2558 * FIXME: Load header and find the best-matching font in the fontList;
2559 * fixup dfPoints if all metrics are identical, otherwise create
2560 * new fontAlias. When soft font support is ready this will
2561 * simply create a new fontResource ('filename' will go into
2562 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
2565 INT16 WINAPI
AddFontResource16( LPCSTR filename
)
2567 return AddFontResource32A( filename
);
2571 /***********************************************************************
2572 * AddFontResource32A (GDI32.2)
2574 INT32 WINAPI
AddFontResource32A( LPCSTR str
)
2576 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2581 /***********************************************************************
2582 * AddFontResource32W (GDI32.4)
2584 INT32 WINAPI
AddFontResource32W( LPCWSTR str
)
2586 FIXME(font
, "(%s): stub\n", debugres_w(str
) );
2590 /***********************************************************************
2591 * RemoveFontResource16 (GDI.136)
2593 BOOL16 WINAPI
RemoveFontResource16( SEGPTR str
)
2595 FIXME(font
, "(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str
)));
2600 /***********************************************************************
2601 * RemoveFontResource32A (GDI32.284)
2603 BOOL32 WINAPI
RemoveFontResource32A( LPCSTR str
)
2605 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2610 /***********************************************************************
2611 * RemoveFontResource32W (GDI32.286)
2613 BOOL32 WINAPI
RemoveFontResource32W( LPCWSTR str
)
2615 FIXME(font
, "(%s): stub\n", debugres_w(str
) );