2 * X11 physical font objects
4 * Copyright 1997 Alex Korobka
6 * TODO: Mapping algorithm tweaks, FO_SYNTH_... flags (ExtTextOut() will
7 * have to be changed for that), dynamic font loading (FreeType).
16 #include <sys/types.h>
20 #include <X11/Xatom.h>
29 #define X_PFONT_MAGIC (0xFADE0000)
30 #define X_FMC_MAGIC (0x0000CAFE)
32 #define MAX_FONT_FAMILIES 128
33 #define MAX_LFD_LENGTH 256
35 #define REMOVE_SUBSETS 1
36 #define UNMARK_SUBSETS 0
38 #define DEF_SCALABLE_HEIGHT 24
39 #define DEF_SCALABLE_DP 240
41 #define FF_FAMILY (FF_MODERN | FF_SWISS | FF_ROMAN | FF_DECORATIVE | FF_SCRIPT)
43 typedef struct __fontAlias
47 struct __fontAlias
* next
;
56 /* Font alias table - these 2 aliases are always present */
58 static fontAlias __aliasTable
[2] = {
59 { "Helvetica", "Helv", &__aliasTable
[1] },
60 { "Times", "Tms Rmn", NULL
}
63 static fontAlias
*aliasTable
= __aliasTable
;
65 /* Optional built-in aliases, they are installed only when X
66 * cannot supply us with original MS fonts */
68 static int faTemplateNum
= 4;
69 static aliasTemplate faTemplate
[4] = {
70 { "-adobe-helvetica-", "MS Sans Serif" },
71 { "-bitstream-charter-", "MS Serif" },
72 { "-adobe-times-", "Times New Roman" },
73 { "-adobe-helvetica-", "Arial" }
76 /* Charset translation table, microsoft-cp125.. encoded fonts are produced by
77 * the fnt2bdf or the True Type X11 font servers */
79 static int numCPTranslation
= 8;
80 static BYTE CPTranslation
[] = { EE_CHARSET
, /* cp1250 */
81 RUSSIAN_CHARSET
, /* cp1251 */
82 ANSI_CHARSET
, /* cp1252 */
83 GREEK_CHARSET
, /* cp1253 */
84 TURKISH_CHARSET
, /* cp1254 */
85 HEBREW_CHARSET
, /* cp1255 */
86 ARABIC_CHARSET
, /* cp1256 */
87 BALTIC_CHARSET
/* cp1257 */
90 UINT16 XTextCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
|
91 TC_CP_STROKE
| TC_CR_ANY
|
92 TC_SA_DOUBLE
| TC_SA_INTEGER
| TC_SA_CONTIN
|
93 TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
95 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
97 static const char* INIWinePrefix
= "/.wine";
98 static const char* INIFontMetrics
= "/.cachedmetrics";
99 static const char* INIFontSection
= "fonts";
100 static const char* INISubSection
= "Alias";
101 static const char* INIDefault
= "Default";
102 static const char* INIDefaultFixed
= "DefaultFixed";
103 static const char* INIResolution
= "Resolution";
104 static const char* INIGlobalMetrics
= "FontMetrics";
106 static const char* LFDSeparator
= "*-";
107 static const char* localMSEncoding
= "microsoft-cp125";
108 static const char* iso8859Encoding
= "iso8859-";
109 static const char* iso646Encoding
= "iso646.1991-";
110 static const char* ansiEncoding
= "ansi-";
111 static unsigned DefResolution
= 0;
113 static fontResource
* fontList
= NULL
;
114 static fontObject
* fontCache
= NULL
; /* array */
115 static int fontCacheSize
= FONTCACHE
;
116 static int fontLF
= -1, fontMRU
= -1; /* last free, most recently used */
118 #define __PFONT(pFont) ( fontCache + ((UINT32)(pFont) & 0x0000FFFF) )
119 #define CHECK_PFONT(pFont) ( (((UINT32)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
120 (((UINT32)(pFont) & 0x0000FFFF) < fontCacheSize) )
122 static INT32
XFONT_IsSubset(fontInfo
*, fontInfo
*);
123 static void XFONT_CheckFIList(fontResource
*, fontInfo
*, int subset_action
);
124 static void XFONT_GrowFreeList(int start
, int end
);
127 static Atom RAW_ASCENT
;
128 static Atom RAW_DESCENT
;
130 /***********************************************************************
131 * Helper macros from X distribution
134 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
135 (((cs)->rbearing|(cs)->lbearing| \
136 (cs)->ascent|(cs)->descent) == 0))
138 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
141 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
142 if (fs->per_char == NULL) { \
143 cs = &fs->min_bounds; \
145 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
146 if (CI_NONEXISTCHAR(cs)) cs = def; \
151 #define CI_GET_DEFAULT_INFO(fs,cs) \
152 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
154 /***********************************************************************
157 static UINT16
__lfCheckSum( LPLOGFONT16 plf
)
159 CHAR font
[LF_FACESIZE
];
163 #define ptr ((UINT16*)plf)
164 for( i
= 0; i
< 9; i
++ ) checksum
^= *ptr
++;
167 #define ptr ((CHAR*)plf)
168 do { font
[i
++] = tolower(*ptr
++); } while (( i
< LF_FACESIZE
) && (*ptr
) && (*ptr
!=' '));
169 for( ptr
= font
, i
>>= 1; i
> 0; i
-- )
171 #define ptr ((UINT16*)plf)
177 static UINT16
__genericCheckSum( const void *ptr
, int size
)
179 unsigned int checksum
= 0;
180 const char *p
= (const char *)ptr
;
182 checksum
^= (checksum
<< 3) + (checksum
>> 29) + *p
++;
184 return checksum
& 0xffff;
187 /*************************************************************************
188 * LFD parse/compose routines
190 static char* LFD_Advance(LPSTR lpFont
, UINT16 uParmsNo
)
195 for( ; j
< uParmsNo
&& *lpch
; lpch
++ ) if( *lpch
== LFDSeparator
[1] ) j
++;
199 static void LFD_GetWeight( fontInfo
* fi
, LPSTR lpStr
, int j
)
201 if( j
== 1 && *lpStr
== '0' )
202 fi
->fi_flags
|= FI_POLYWEIGHT
;
205 if( !strncasecmp( "bold", lpStr
, 4) )
206 fi
->df
.dfWeight
= FW_BOLD
;
207 else if( !strncasecmp( "demi", lpStr
, 4) )
209 fi
->fi_flags
|= FI_FW_DEMI
;
210 fi
->df
.dfWeight
= FW_DEMIBOLD
;
212 else if( !strncasecmp( "book", lpStr
, 4) )
214 fi
->fi_flags
|= FI_FW_BOOK
;
215 fi
->df
.dfWeight
= FW_REGULAR
;
220 if( !strncasecmp( "light", lpStr
, 5) )
221 fi
->df
.dfWeight
= FW_LIGHT
;
222 else if( !strncasecmp( "black", lpStr
, 5) )
223 fi
->df
.dfWeight
= FW_BLACK
;
225 else if( j
== 6 && !strncasecmp( "medium", lpStr
, 6) )
226 fi
->df
.dfWeight
= FW_REGULAR
;
227 else if( j
== 8 && !strncasecmp( "demibold", lpStr
, 8) )
228 fi
->df
.dfWeight
= FW_DEMIBOLD
;
230 fi
->df
.dfWeight
= FW_DONTCARE
; /* FIXME: try to get something
231 * from the weight property */
234 static int LFD_GetSlant( fontInfo
* fi
, LPSTR lpStr
, int l
)
238 switch( tolower( *lpStr
) )
240 case '0': fi
->fi_flags
|= FI_POLYSLANT
; /* haven't seen this one yet */
242 case 'r': fi
->df
.dfItalic
= 0;
245 fi
->fi_flags
|= FI_OBLIQUE
;
246 case 'i': fi
->df
.dfItalic
= 1;
254 /*************************************************************************
257 * Fill in some fields in the fontInfo struct.
259 static int LFD_InitFontInfo( fontInfo
* fi
, LPSTR lpstr
)
262 int i
, j
, dec_style_check
, scalability
;
265 memset(fi
, 0, sizeof(fontInfo
) );
268 lpch
= LFD_Advance( lpstr
, 1);
269 if( !*lpch
) return FALSE
;
270 j
= lpch
- lpstr
- 1;
271 LFD_GetWeight( fi
, lpstr
, j
);
274 lpch
= LFD_Advance( lpstr
= lpch
, 1);
275 if( !*lpch
) return FALSE
;
276 j
= lpch
- lpstr
- 1;
277 dec_style_check
= LFD_GetSlant( fi
, lpstr
, j
);
280 lpch
= LFD_Advance( lpstr
= lpch
, 1);
281 if( !*lpch
) return FALSE
;
282 if( strncasecmp( "normal", lpstr
, 6) ) /* XXX 'narrow', 'condensed', etc... */
283 dec_style_check
= TRUE
;
285 fi
->fi_flags
|= FI_NORMAL
;
288 lpch
= LFD_Advance( lpstr
= lpch
, 1);
289 if( !*lpch
) return FALSE
;
290 j
= lpch
- lpstr
- 1;
291 if( j
> 3 ) /* find out is there "sans" or "script" */
296 if( strstr(lpstr
, "sans") )
298 fi
->df
.dfPitchAndFamily
|= FF_SWISS
;
301 if( strstr(lpstr
, "script") )
303 fi
->df
.dfPitchAndFamily
|= FF_SCRIPT
;
306 if( !j
&& dec_style_check
)
307 fi
->df
.dfPitchAndFamily
|= FF_DECORATIVE
;
308 *(lpch
- 1) = LFDSeparator
[1];
311 /* pixel height, decipoint height, and res_x */
313 for( i
= scalability
= 0; i
< 3; i
++ )
315 lpch
= LFD_Advance( lpstr
= lpch
, 1);
316 if( !*lpch
) return FALSE
;
317 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
320 if( !(tmp
[i
] = atoi(lpstr
)) ) scalability
++;
321 *(lpch
- 1) = LFDSeparator
[1];
323 if( scalability
== 3 ) /* Type1 */
325 fi
->fi_flags
|= FI_SCALABLE
;
326 fi
->lfd_height
= DEF_SCALABLE_HEIGHT
; fi
->lfd_decipoints
= DEF_SCALABLE_DP
;
327 fi
->lfd_resolution
= DefResolution
;
329 else if( scalability
== 0 ) /* Bitmap */
331 fi
->lfd_height
= tmp
[0]; fi
->lfd_decipoints
= tmp
[1];
332 fi
->lfd_resolution
= tmp
[2];
334 else return FALSE
; /* #$%^!!! X11R6 mutant garbage */
336 /* res_y - skip, spacing - */
337 lpstr
= LFD_Advance( lpch
, 1);
340 case '\0': return FALSE
;
342 case 'p': fi
->fi_flags
|= FI_VARIABLEPITCH
;
344 case 'c': fi
->df
.dfPitchAndFamily
|= FF_MODERN
;
345 fi
->fi_flags
|= FI_FIXEDEX
;
347 case 'm': fi
->fi_flags
|= FI_FIXEDPITCH
;
350 fi
->df
.dfPitchAndFamily
|= DEFAULT_PITCH
| FF_DONTCARE
;
352 lpstr
= LFD_Advance(lpstr
, 1);
353 if( !*lpstr
) return FALSE
;
355 /* average width - */
356 lpch
= LFD_Advance( lpstr
, 1);
357 if( !*lpch
) return FALSE
;
358 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
360 if( !(fi
->lfd_width
= atoi(lpstr
)) && !scalability
) return FALSE
;
361 *(lpch
- 1) = LFDSeparator
[1];
363 /* charset registry, charset encoding - */
364 if( strstr(lpch
, "jisx") ||
365 strstr(lpch
, "ksc") ||
366 strstr(lpch
, "gb2312") ) return FALSE
; /* 2-byte stuff */
368 fi
->df
.dfCharSet
= ANSI_CHARSET
;
369 if( strstr(lpch
, iso8859Encoding
) )
370 fi
->fi_flags
|= FI_ENC_ISO8859
;
371 else if( strstr(lpch
, iso646Encoding
) )
372 fi
->fi_flags
|= FI_ENC_ISO646
;
373 else if( strstr(lpch
, ansiEncoding
) ) /* fnt2bdf produces -ansi-0 LFD */
374 fi
->fi_flags
|= FI_ENC_ANSI
;
375 else /* ... and -microsoft-cp125x */
377 fi
->df
.dfCharSet
= OEM_CHARSET
;
378 if( !strncasecmp(lpch
, localMSEncoding
, 6) )
380 lpch
= LFD_Advance( lpch
, 1 );
381 if( lpch
&& (i
= atoi( lpch
)) < numCPTranslation
)
383 fi
->fi_flags
|= FI_ENC_MSCODEPAGE
;
384 fi
->df
.dfCharSet
= CPTranslation
[i
];
387 else if( strstr(lpch
, "fontspecific") ||
388 strstr(lpch
, "microsoft-symbol") )
389 fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
395 /*************************************************************************
398 static BOOL32
LFD_ComposeLFD( fontObject
* fo
,
399 INT32 height
, LPSTR lpLFD
, UINT32 uRelax
)
401 int h
, w
, ch
, enc_ch
, point
= 0;
403 const char* lpEncoding
= NULL
;
404 char h_string
[64], point_string
[64];
406 *(lpLFD
+MAX_LFD_LENGTH
-1)=0;
407 lstrcpy32A( lpLFD
, fo
->fr
->resource
);
410 switch( fo
->fi
->df
.dfWeight
)
413 strcat( lpLFD
, "bold" ); break;
415 if( fo
->fi
->fi_flags
& FI_FW_BOOK
)
416 strcat( lpLFD
, "book" );
418 strcat( lpLFD
, "medium" );
421 strcat( lpLFD
, "demi" );
422 if( !( fo
->fi
->fi_flags
& FI_FW_DEMI
) )
423 strcat ( lpLFD
, "bold" );
426 strcat( lpLFD
, "black" ); break;
428 strcat( lpLFD
, "light" ); break;
430 strcat( lpLFD
, "*" );
434 if( fo
->fi
->df
.dfItalic
)
435 if( fo
->fi
->fi_flags
& FI_OBLIQUE
)
436 strcat( lpLFD
, "-o" );
438 strcat( lpLFD
, "-i" );
440 strcat( lpLFD
, (uRelax
< 4) ? "-r" : "-*" );
442 /* add width style and skip serifs */
443 if( fo
->fi
->fi_flags
& FI_NORMAL
)
444 strcat( lpLFD
, "-normal-*-");
446 strcat( lpLFD
, "-*-*-" );
448 /* add pixelheight, pointheight, and resolution
450 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
452 if( fo
->fo_flags
& FO_SYNTH_HEIGHT
) h
= fo
->fi
->lfd_height
;
453 else h
= (fo
->fi
->lfd_height
* height
) / fo
->fi
->df
.dfPixHeight
;
455 if( XTextCaps
& TC_SF_X_YINDEP
)
457 if( fo
->lf
.lfWidth
&& !(fo
->fo_flags
& FO_SYNTH_WIDTH
) )
458 point
= (fo
->fi
->lfd_decipoints
* fo
->lf
.lfWidth
) / fo
->fi
->df
.dfAvgWidth
;
460 if( fo
->fi
->fi_flags
& FI_SCALABLE
) /* adjust h/w ratio */
461 point
= h
* 72 * 10 / fo
->fi
->lfd_resolution
;
464 /* handle rotated fonts */
465 if (fo
->lf
.lfEscapement
) {
466 /* escapement is in tenths of degrees, theta is in radians */
467 double theta
= M_PI
*fo
->lf
.lfEscapement
/1800.;
468 double h_matrix
[4] = {h
*cos(theta
), h
*sin(theta
), -h
*sin(theta
), h
*cos(theta
)};
469 double point_matrix
[4] = {point
*cos(theta
), point
*sin(theta
), -point
*sin(theta
), point
*cos(theta
)};
471 sprintf(h_string
, "[%+f%+f%+f%+f]", h_matrix
[0], h_matrix
[1], h_matrix
[2], h_matrix
[3]);
472 sprintf(point_string
, "[%+f%+f%+f%+f]", point_matrix
[0], point_matrix
[1], point_matrix
[2], point_matrix
[3]);
473 while ((s
= strchr(h_string
, '-'))) *s
='~';
474 while ((s
= strchr(point_string
, '-'))) *s
='~';
476 sprintf(h_string
, "%d", h
);
477 sprintf(point_string
, "%d", point
);
481 /* spacing and width */
483 if( fo
->fi
->fi_flags
& FI_FIXEDPITCH
)
484 w
= ( fo
->fi
->fi_flags
& FI_FIXEDEX
) ? 'c' : 'm';
486 w
= ( fo
->fi
->fi_flags
& FI_VARIABLEPITCH
) ? 'p' : LFDSeparator
[0];
491 if( fo
->fi
->df
.dfCharSet
== ANSI_CHARSET
)
493 if( fo
->fi
->fi_flags
& FI_ENC_ISO8859
)
494 lpEncoding
= iso8859Encoding
;
495 else if( fo
->fi
->fi_flags
& FI_ENC_ISO646
)
496 lpEncoding
= iso646Encoding
;
497 else if( fo
->fi
->fi_flags
& FI_ENC_MSCODEPAGE
)
500 lpEncoding
= localMSEncoding
;
502 else lpEncoding
= ansiEncoding
;
504 else if( fo
->fi
->fi_flags
& FI_ENC_MSCODEPAGE
)
508 lpEncoding
= localMSEncoding
;
509 for( i
= 0; i
< numCPTranslation
; i
++ )
510 if( CPTranslation
[i
] == fo
->fi
->df
.dfCharSet
)
516 else lpEncoding
= LFDSeparator
; /* whatever */
518 lpch
= lpLFD
+ lstrlen32A(lpLFD
);
519 ch
= (fo
->fi
->fi_flags
& FI_SCALABLE
) ? '0' : LFDSeparator
[0];
523 /* RealizeFont() will call us repeatedly with increasing uRelax
524 * until XLoadFont() succeeds. */
529 sprintf( lpch
, "%s-%s-%i-%c-%c-*-%s%c", h_string
,
531 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
, enc_ch
);
537 sprintf( lpch
, "%s-*-%i-%c-%c-*-%s%c", h_string
,
538 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
, enc_ch
);
542 sprintf( lpch
, "%s-*-%i-%c-*-*-%s%c",
543 h_string
, fo
->fi
->lfd_resolution
, ch
, lpEncoding
, enc_ch
);
547 sprintf( lpch
, "%i-*-%i-%c-*-*-%s*", fo
->fi
->lfd_height
,
548 fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
552 sprintf( lpch
, "%i-*-*-*-*-*-%s*", fo
->fi
->lfd_height
, lpEncoding
);
555 TRACE(font
,"\tLFD: %s\n", lpLFD
);
556 assert(*(lpLFD
+MAX_LFD_LENGTH
-1)==0); /* check if overwrittem */
561 /***********************************************************************
564 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
565 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
567 static BOOL32
XFONT_GetLeading( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
, INT32
*
568 pIL
, INT32
* pEL
, XFONTTRANS
*XFT
)
570 unsigned long height
;
571 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
572 unsigned max
= (unsigned char)pFI
->dfLastChar
;
573 BOOL32 bHaveCapHeight
= (pFI
->dfCharSet
== ANSI_CHARSET
&& 'X' >= min
&& 'X' <= max
);
578 Atom RAW_CAP_HEIGHT
= TSXInternAtom(display
, "RAW_CAP_HEIGHT", TRUE
);
579 if(TSXGetFontProperty(x_fs
, RAW_CAP_HEIGHT
, &height
))
581 (INT32
)(XFT
->pixelsize
/ 1000.0 * height
);
584 return bHaveCapHeight
&& x_fs
->per_char
;
587 if( TSXGetFontProperty(x_fs
, XA_CAP_HEIGHT
, &height
) == FALSE
)
591 height
= x_fs
->per_char
['X' - min
].ascent
;
593 if (x_fs
->ascent
>= x_fs
->max_bounds
.ascent
)
594 height
= x_fs
->max_bounds
.ascent
;
597 height
= x_fs
->ascent
;
599 *pEL
= x_fs
->max_bounds
.ascent
- height
;
602 height
= x_fs
->min_bounds
.ascent
;
605 *pIL
= x_fs
->ascent
- height
;
606 return (bHaveCapHeight
&& x_fs
->per_char
);
609 static INT32
XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
,
612 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
613 unsigned max
= (unsigned char)pFI
->dfLastChar
;
618 for( j
= 0, width
= 0, chars
= 0, max
-= min
; j
<= max
; j
++ )
619 if( !CI_NONEXISTCHAR(x_fs
->per_char
+ j
) )
622 width
+= x_fs
->per_char
[j
].width
;
624 width
+= x_fs
->per_char
[j
].attributes
*
625 XFT
->pixelsize
/ 1000.0;
628 return (width
/ chars
);
631 return x_fs
->min_bounds
.width
;
634 static INT32
XFONT_GetMaxCharWidth(fontObject
*pfo
)
636 unsigned min
= (unsigned char)pfo
->fs
->min_char_or_byte2
;
637 unsigned max
= (unsigned char)pfo
->fs
->max_char_or_byte2
;
640 return abs(pfo
->fs
->max_bounds
.width
);
642 if( pfo
->fs
->per_char
)
645 for( j
= 0, maxwidth
= 0, max
-= min
; j
<= max
; j
++ )
646 if( !CI_NONEXISTCHAR(pfo
->fs
->per_char
+ j
) )
647 if(maxwidth
< pfo
->fs
->per_char
[j
].attributes
)
648 maxwidth
= pfo
->fs
->per_char
[j
].attributes
;
650 maxwidth
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
653 return pfo
->foAvgCharWidth
;
656 /***********************************************************************
657 * XFONT_SetFontMetric
659 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
661 static void XFONT_SetFontMetric(fontInfo
* fi
, fontResource
* fr
, XFontStruct
* xfs
)
666 fi
->df
.dfFirstChar
= (BYTE
)(min
= xfs
->min_char_or_byte2
);
667 fi
->df
.dfLastChar
= (BYTE
)(max
= xfs
->max_char_or_byte2
);
669 fi
->df
.dfDefaultChar
= (BYTE
)xfs
->default_char
;
670 fi
->df
.dfBreakChar
= (BYTE
)(( ' ' < min
|| ' ' > max
) ? xfs
->default_char
: ' ');
672 fi
->df
.dfPixHeight
= (INT16
)((fi
->df
.dfAscent
= (INT16
)xfs
->ascent
) + xfs
->descent
);
673 fi
->df
.dfPixWidth
= (xfs
->per_char
) ? 0 : xfs
->min_bounds
.width
;
674 fi
->df
.dfMaxWidth
= (INT16
)abs(xfs
->max_bounds
.width
);
676 if( XFONT_GetLeading( &fi
->df
, xfs
, &il
, &el
, NULL
) )
677 fi
->df
.dfAvgWidth
= (INT16
)xfs
->per_char
['X' - min
].width
;
679 fi
->df
.dfAvgWidth
= (INT16
)XFONT_GetAvgCharWidth( &fi
->df
, xfs
, NULL
);
681 fi
->df
.dfInternalLeading
= (INT16
)il
;
682 fi
->df
.dfExternalLeading
= (INT16
)el
;
684 fi
->df
.dfPoints
= (INT16
)(((INT32
)(fi
->df
.dfPixHeight
-
685 fi
->df
.dfInternalLeading
) * 72 + (fi
->df
.dfVertRes
>> 1)) / fi
->df
.dfVertRes
);
687 if( xfs
->min_bounds
.width
!= xfs
->max_bounds
.width
)
688 fi
->df
.dfPitchAndFamily
|= TMPF_FIXED_PITCH
; /* au contraire! */
689 if( fi
->fi_flags
& FI_SCALABLE
)
691 fi
->df
.dfType
= DEVICE_FONTTYPE
;
692 fi
->df
.dfPitchAndFamily
|= TMPF_DEVICE
;
694 else if( fi
->fi_flags
& FI_TRUETYPE
)
695 fi
->df
.dfType
= TRUETYPE_FONTTYPE
;
697 fi
->df
.dfType
= RASTER_FONTTYPE
;
699 fi
->df
.dfFace
= fr
->lfFaceName
;
702 /***********************************************************************
703 * XFONT_GetTextMetric
705 static void XFONT_GetTextMetric( fontObject
* pfo
, LPTEXTMETRIC32A pTM
)
707 LPIFONTINFO16 pdf
= &pfo
->fi
->df
;
709 if( ! pfo
->lpX11Trans
) {
710 pTM
->tmAscent
= pfo
->fs
->ascent
;
711 pTM
->tmDescent
= pfo
->fs
->descent
;
713 pTM
->tmAscent
= pfo
->lpX11Trans
->ascent
;
714 pTM
->tmDescent
= pfo
->lpX11Trans
->descent
;
716 pTM
->tmHeight
= pTM
->tmAscent
+ pTM
->tmDescent
;
718 pTM
->tmAveCharWidth
= pfo
->foAvgCharWidth
;
719 pTM
->tmMaxCharWidth
= pfo
->foMaxCharWidth
;
721 pTM
->tmInternalLeading
= pfo
->foInternalLeading
;
722 pTM
->tmExternalLeading
= pdf
->dfExternalLeading
;
724 pTM
->tmStruckOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
)
725 ? 1 : pdf
->dfStrikeOut
;
726 pTM
->tmUnderlined
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
)
727 ? 1 : pdf
->dfUnderline
;
730 if( pfo
->fo_flags
& FO_SYNTH_ITALIC
)
732 pTM
->tmOverhang
+= pTM
->tmHeight
/3;
735 pTM
->tmItalic
= pdf
->dfItalic
;
737 pTM
->tmWeight
= pdf
->dfWeight
;
738 if( pfo
->fo_flags
& FO_SYNTH_BOLD
)
741 pTM
->tmWeight
+= 100;
744 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pdf
->dfFirstChar
;
746 pTM
->tmCharSet
= pdf
->dfCharSet
;
747 pTM
->tmPitchAndFamily
= pdf
->dfPitchAndFamily
;
749 pTM
->tmDigitizedAspectX
= pdf
->dfHorizRes
;
750 pTM
->tmDigitizedAspectY
= pdf
->dfVertRes
;
753 /***********************************************************************
754 * XFONT_GetFontMetric
756 * Retrieve font metric info (enumeration).
758 static UINT32
XFONT_GetFontMetric( fontInfo
* pfi
, LPENUMLOGFONTEX16 pLF
,
759 LPNEWTEXTMETRIC16 pTM
)
761 memset( pLF
, 0, sizeof(*pLF
) );
762 memset( pTM
, 0, sizeof(*pTM
) );
764 #define plf ((LPLOGFONT16)pLF)
765 plf
->lfHeight
= pTM
->tmHeight
= pfi
->df
.dfPixHeight
;
766 plf
->lfWidth
= pTM
->tmAveCharWidth
= pfi
->df
.dfAvgWidth
;
767 plf
->lfWeight
= pTM
->tmWeight
= pfi
->df
.dfWeight
;
768 plf
->lfItalic
= pTM
->tmItalic
= pfi
->df
.dfItalic
;
769 plf
->lfUnderline
= pTM
->tmUnderlined
= pfi
->df
.dfUnderline
;
770 plf
->lfStrikeOut
= pTM
->tmStruckOut
= pfi
->df
.dfStrikeOut
;
771 plf
->lfCharSet
= pTM
->tmCharSet
= pfi
->df
.dfCharSet
;
773 /* convert pitch values */
775 pTM
->tmPitchAndFamily
= pfi
->df
.dfPitchAndFamily
;
776 plf
->lfPitchAndFamily
= (pfi
->df
.dfPitchAndFamily
& 0xF1) + 1;
778 lstrcpyn32A( plf
->lfFaceName
, pfi
->df
.dfFace
, LF_FACESIZE
);
781 pTM
->tmAscent
= pfi
->df
.dfAscent
;
782 pTM
->tmDescent
= pTM
->tmHeight
- pTM
->tmAscent
;
783 pTM
->tmInternalLeading
= pfi
->df
.dfInternalLeading
;
784 pTM
->tmMaxCharWidth
= pfi
->df
.dfMaxWidth
;
785 pTM
->tmDigitizedAspectX
= pfi
->df
.dfHorizRes
;
786 pTM
->tmDigitizedAspectY
= pfi
->df
.dfVertRes
;
788 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pfi
->df
.dfFirstChar
;
790 /* return font type */
792 return pfi
->df
.dfType
;
796 /***********************************************************************
799 * dfPitchAndFamily flags for some common typefaces.
801 static BYTE
XFONT_FixupFlags( LPCSTR lfFaceName
)
803 switch( lfFaceName
[0] )
806 case 'H': if(!strcasecmp(lfFaceName
, "Helvetica") )
810 case 'C': if(!strcasecmp(lfFaceName
, "Courier") ||
811 !strcasecmp(lfFaceName
, "Charter") )
815 case 'P': if( !strcasecmp(lfFaceName
,"Palatino") )
819 case 'T': if(!strncasecmp(lfFaceName
, "Times", 5) )
823 case 'U': if(!strcasecmp(lfFaceName
, "Utopia") )
827 case 'Z': if(!strcasecmp(lfFaceName
, "Zapf Dingbats") )
828 return FF_DECORATIVE
;
834 /***********************************************************************
835 * XFONT_CheckResourceName
837 static BOOL32
XFONT_CheckResourceName( LPSTR resource
, LPCSTR name
, INT32 n
)
839 resource
= LFD_Advance( resource
, 2 );
841 return (!strncasecmp( resource
, name
, n
));
846 /***********************************************************************
849 * Build generic Windows aliases for X font names.
851 * -misc-fixed- -> "Fixed"
852 * -sony-fixed- -> "Sony Fixed", etc...
854 static void XFONT_WindowsNames( char* buffer
)
856 fontResource
* fr
, *pfr
;
860 const char* relocTable
[] = { INIDefaultFixed
, INIDefault
, NULL
};
862 for( fr
= fontList
; fr
; fr
= fr
->next
)
864 if( fr
->fr_flags
& FR_NAMESET
) continue; /* skip already assigned */
866 lpstr
= LFD_Advance(fr
->resource
, 2);
867 i
= LFD_Advance( lpstr
, 1 ) - lpstr
;
869 for( pfr
= fontList
; pfr
!= fr
; pfr
= pfr
->next
)
870 if( pfr
->fr_flags
& FR_NAMESET
)
871 if( XFONT_CheckResourceName( pfr
->resource
, lpstr
, i
) )
874 if( pfr
!= fr
) /* prepend vendor name */
875 lpstr
= fr
->resource
+ 1;
877 for( i
= 0, up
= 1, lpch
= fr
->lfFaceName
; *lpstr
&& i
< 32;
878 lpch
++, lpstr
++, i
++ )
880 if( *lpstr
== LFDSeparator
[1] || *lpstr
== ' ' )
885 else if( isalpha(*lpstr
) && up
)
887 *lpch
= toupper(*lpstr
);
892 while (*(lpch
- 1) == ' ') *(--lpch
) = '\0';
894 if( (bFamilyStyle
= XFONT_FixupFlags( fr
->lfFaceName
)) )
897 for( fi
= fr
->fi
; fi
; fi
= fi
->next
)
898 fi
->df
.dfPitchAndFamily
|= bFamilyStyle
;
901 TRACE(font
,"typeface \'%s\'\n", fr
->lfFaceName
);
903 fr
->fr_flags
|= FR_NAMESET
;
906 for( up
= 0; relocTable
[up
]; up
++ )
907 if( PROFILE_GetWineIniString( INIFontSection
, relocTable
[up
], "", buffer
, 128 ) )
909 while( *buffer
&& isspace(*buffer
) ) buffer
++;
910 for( fr
= NULL
, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
912 i
= strlen( pfr
->resource
);
913 if( !strncasecmp( pfr
->resource
, buffer
, i
) )
917 fr
->next
= pfr
->next
;
918 pfr
->next
= fontList
;
928 /***********************************************************************
931 static fontAlias
* XFONT_CreateAlias( LPCSTR lpTypeFace
, LPCSTR lpAlias
)
934 fontAlias
* pfa
= aliasTable
;
938 /* check if we already got one */
939 if( !strcasecmp( pfa
->faTypeFace
, lpAlias
) )
941 TRACE(font
,"\tredundant alias '%s' -> '%s'\n",
942 lpAlias
, lpTypeFace
);
945 if( pfa
->next
) pfa
= pfa
->next
;
949 j
= lstrlen32A(lpTypeFace
) + 1;
950 pfa
->next
= HeapAlloc( SystemHeap
, 0, sizeof(fontAlias
) +
951 j
+ lstrlen32A(lpAlias
) + 1 );
952 if((pfa
= pfa
->next
))
955 pfa
->faTypeFace
= (LPSTR
)(pfa
+ 1);
956 lstrcpy32A( pfa
->faTypeFace
, lpTypeFace
);
957 pfa
->faAlias
= pfa
->faTypeFace
+ j
;
958 lstrcpy32A( pfa
->faAlias
, lpAlias
);
960 TRACE(font
, "\tadded alias '%s' for %s\n", lpAlias
, lpTypeFace
);
967 /***********************************************************************
970 * Read user-defined aliases from wine.conf. Format is as follows
972 * Alias# = [Windows font name],[LFD font name], <substitute original name>
975 * Alias0 = Arial, -adobe-helvetica-
976 * Alias1 = Times New Roman, -bitstream-courier-, 1
979 * Note that from 081797 and on we have built-in alias templates that take
980 * care of the necessary Windows typefaces.
982 static void XFONT_LoadAliases( char** buffer
, int buf_size
)
984 char* lpResource
, *lpAlias
;
987 BOOL32 bHaveAlias
= TRUE
, bSubst
= FALSE
;
990 *buffer
= HeapReAlloc(SystemHeap
, 0, *buffer
, 256 );
993 if( j
< faTemplateNum
)
995 /* built-in templates first */
997 lpResource
= faTemplate
[j
].fatResource
;
998 lpAlias
= faTemplate
[j
].fatAlias
;
1003 /* then WINE.CONF */
1005 wsprintf32A( subsection
, "%s%i", INISubSection
, i
++ );
1007 if( (bHaveAlias
= PROFILE_GetWineIniString( INIFontSection
,
1008 subsection
, "", *buffer
, 128 )) )
1011 while( isspace(*lpAlias
) ) lpAlias
++;
1012 lpResource
= PROFILE_GetStringItem( lpAlias
);
1013 bSubst
= (PROFILE_GetStringItem( lpResource
)) ? TRUE
: FALSE
;
1021 length
= strlen( lpAlias
);
1022 if( lpResource
&& length
)
1024 fontResource
* fr
, *frMatch
= NULL
;
1026 for (fr
= fontList
; fr
; fr
= fr
->next
)
1028 if( !strcasecmp( fr
->resource
, lpResource
) ) frMatch
= fr
;
1029 if( XFONT_CheckResourceName( fr
->resource
, lpAlias
, length
) )
1031 /* alias is not needed since the real font is present */
1032 frMatch
= NULL
; break;
1040 fontAlias
*pfa
, *prev
= NULL
;
1042 for(pfa
= aliasTable
; pfa
; pfa
= pfa
->next
)
1044 /* Remove lpAlias from aliasTable - we should free the old entry */
1045 if(!strcmp(lpAlias
, pfa
->faAlias
))
1048 prev
->next
= pfa
->next
;
1050 aliasTable
= pfa
->next
;
1053 /* Update any references to the substituted font in aliasTable */
1054 if(!strcmp(frMatch
->lfFaceName
,
1056 pfa
->faTypeFace
= HEAP_strdupA( SystemHeap
, 0,
1061 TRACE(font
, "\tsubstituted '%s' with %s\n",
1062 frMatch
->lfFaceName
, lpAlias
);
1064 lstrcpyn32A( frMatch
->lfFaceName
, lpAlias
, LF_FACESIZE
);
1065 frMatch
->fr_flags
|= FR_NAMESET
;
1069 /* create new entry in the alias table */
1070 XFONT_CreateAlias( frMatch
->lfFaceName
, lpAlias
);
1074 else ERR(font
, " malformed font alias '%s'\n", *buffer
);
1080 /***********************************************************************
1081 * XFONT_UserMetricsCache
1083 * Returns expanded name for the ~/.wine/.cachedmetrics file.
1085 static char* XFONT_UserMetricsCache( char* buffer
, int* buf_size
)
1089 pwd
= getpwuid(getuid());
1090 if( pwd
&& pwd
->pw_dir
)
1092 int i
= strlen( pwd
->pw_dir
) + strlen( INIWinePrefix
) +
1093 strlen( INIFontMetrics
) + 2;
1095 buffer
= (char*) HeapReAlloc( SystemHeap
, 0, buffer
, *buf_size
= i
);
1096 strcpy( buffer
, pwd
->pw_dir
);
1097 strcat( buffer
, INIWinePrefix
);
1098 strcat( buffer
, INIFontMetrics
);
1099 } else buffer
[0] = '\0';
1104 /***********************************************************************
1105 * XFONT_ReadCachedMetrics
1107 static BOOL32
XFONT_ReadCachedMetrics( int fd
, int res
, unsigned x_checksum
, int x_count
)
1114 /* read checksums */
1115 read( fd
, &u
, sizeof(unsigned) );
1116 read( fd
, &i
, sizeof(int) );
1118 if( u
== x_checksum
&& i
== x_count
)
1120 off_t length
, offset
= 3 * sizeof(int);
1122 /* read total size */
1123 read( fd
, &i
, sizeof(int) );
1124 length
= lseek( fd
, 0, SEEK_END
);
1126 if( length
== (i
+ offset
) )
1128 lseek( fd
, offset
, SEEK_SET
);
1129 fontList
= (fontResource
*)HeapAlloc( SystemHeap
, 0, i
);
1132 fontResource
* pfr
= fontList
;
1133 fontInfo
* pfi
= NULL
;
1135 TRACE(font
,"Reading cached font metrics:\n");
1137 read( fd
, fontList
, i
); /* read all metrics at once */
1138 while( offset
< length
)
1140 offset
+= sizeof(fontResource
) + sizeof(fontInfo
);
1141 pfr
->fi
= pfi
= (fontInfo
*)(pfr
+ 1);
1145 if( offset
> length
||
1146 (int)(pfi
->next
) != j
++ ) goto fail
;
1148 pfi
->df
.dfFace
= pfr
->lfFaceName
;
1149 pfi
->df
.dfHorizRes
= pfi
->df
.dfVertRes
= res
;
1150 pfi
->df
.dfPoints
= (INT16
)(((INT32
)(pfi
->df
.dfPixHeight
-
1151 pfi
->df
.dfInternalLeading
) * 72 + (res
>> 1)) / res
);
1152 pfi
->next
= pfi
+ 1;
1154 if( j
> pfr
->count
) break;
1157 offset
+= sizeof(fontInfo
);
1162 pfr
->next
= (fontResource
*)(pfi
+ 1);
1167 if( pfr
->next
== NULL
&&
1168 *(int*)(pfi
+ 1) == X_FMC_MAGIC
)
1170 /* read LFD stubs */
1171 char* lpch
= (char*)((int*)(pfi
+ 1) + 1);
1172 offset
+= sizeof(int);
1173 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1175 TRACE(font
,"\t%s, %i instances\n", lpch
, pfr
->count
);
1176 pfr
->resource
= lpch
;
1179 if( ++offset
> length
) goto fail
;
1180 if( !*lpch
++ ) break;
1190 if( fontList
) HeapFree( SystemHeap
, 0, fontList
);
1197 /***********************************************************************
1198 * XFONT_WriteCachedMetrics
1200 static BOOL32
XFONT_WriteCachedMetrics( int fd
, unsigned x_checksum
, int x_count
, int n_ff
)
1209 /* font metrics file:
1213 * +0008 total size to load
1214 * +000C prepackaged font metrics
1217 * +...x + 4 LFD stubs
1220 write( fd
, &x_checksum
, sizeof(unsigned) );
1221 write( fd
, &x_count
, sizeof(int) );
1223 for( j
= i
= 0, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1225 i
+= strlen( pfr
->resource
) + 1;
1228 i
+= n_ff
* sizeof(fontResource
) + j
* sizeof(fontInfo
) + sizeof(int);
1229 write( fd
, &i
, sizeof(int) );
1231 TRACE(font
,"Writing font cache:\n");
1233 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1237 TRACE(font
,"\t%s, %i instances\n", pfr
->resource
, pfr
->count
);
1239 i
= write( fd
, pfr
, sizeof(fontResource
) );
1240 if( i
== sizeof(fontResource
) )
1242 for( k
= 1, pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
1244 memcpy( &fi
, pfi
, sizeof(fi
) );
1246 fi
.df
.dfFace
= NULL
;
1247 fi
.next
= (fontInfo
*)k
; /* loader checks this */
1249 j
= write( fd
, &fi
, sizeof(fi
) );
1252 if( j
== sizeof(fontInfo
) ) continue;
1256 if( i
== sizeof(fontResource
) && j
== sizeof(fontInfo
) )
1258 i
= j
= X_FMC_MAGIC
;
1259 write( fd
, &i
, sizeof(int) );
1260 for( pfr
= fontList
; pfr
&& i
== j
; pfr
= pfr
->next
)
1262 i
= strlen( pfr
->resource
) + 1;
1263 j
= write( fd
, pfr
->resource
, i
);
1272 /***********************************************************************
1273 * XFONT_CheckIniSection
1275 * Examines wine.conf for old/invalid font entries and recommend changes to
1279 * 05-Jul-1997 Dave Cuthbert (dacut@ece.cmu.edu)
1280 * Original implementation.
1282 static void XFONT_CheckIniCallback(char const *, char const *, void *);
1284 static char const *fontmsgprologue
=
1286 " The following entries in the [fonts] section of the wine.conf file are\n"
1287 " obsolete or invalid:\n";
1289 static char const *fontmsgepilogue
=
1290 " These entries should be eliminated or updated.\n"
1291 " See the documentation/fonts file for more information.\n";
1293 static int XFONT_CheckIniSection()
1297 PROFILE_EnumerateWineIniSection("Fonts", &XFONT_CheckIniCallback
,
1300 MSG(fontmsgepilogue
);
1305 static void XFONT_CheckIniCallback(
1310 /* Ignore any keys that start with potential comment characters "'", '#',
1312 if(key
[0] == '\'' || key
[0] == '#' || key
[0] == ';' || key
[0] == '\0')
1315 /* Make sure this is a valid key */
1316 if((strncasecmp(key
, INISubSection
, 5) == 0) ||
1317 (strcasecmp( key
, INIDefault
) == 0) ||
1318 (strcasecmp( key
, INIDefaultFixed
) == 0) ||
1319 (strcasecmp( key
, INIGlobalMetrics
) == 0) ||
1320 (strcasecmp( key
, INIResolution
) == 0) )
1322 /* Valid key; make sure the value doesn't contain a wildcard */
1323 if(strchr(value
, '*')) {
1324 if(*(int *)found
== 0) {
1325 MSG(fontmsgprologue
);
1329 MSG(" %s=%s [no wildcards allowed]\n", key
, value
);
1333 /* Not a valid key */
1334 if(*(int *)found
== 0) {
1335 MSG(fontmsgprologue
);
1339 MSG(" %s=%s [obsolete]\n", key
, value
);
1345 /***********************************************************************
1346 * XFONT_GetPointResolution()
1348 * Here we initialize DefResolution which is used in the
1349 * XFONT_Match() penalty function. We also load the point
1350 * resolution value (higher values result in larger fonts).
1352 static int XFONT_GetPointResolution( DeviceCaps
* pDevCaps
)
1354 int i
, j
, point_resolution
, num
= 3;
1355 int allowed_xfont_resolutions
[3] = { 72, 75, 100 };
1356 int best
= 0, best_diff
= 65536;
1358 DefResolution
= point_resolution
= PROFILE_GetWineIniInt( INIFontSection
, INIResolution
, 0 );
1359 if( !DefResolution
) DefResolution
= point_resolution
= pDevCaps
->logPixelsY
;
1360 else pDevCaps
->logPixelsX
= pDevCaps
->logPixelsY
= DefResolution
;
1362 for( i
= best
= 0; i
< num
; i
++ )
1364 j
= abs( DefResolution
- allowed_xfont_resolutions
[i
] );
1371 DefResolution
= allowed_xfont_resolutions
[best
];
1372 return point_resolution
;
1375 /***********************************************************************
1378 * Initialize font resource list and allocate font cache.
1380 BOOL32
X11DRV_FONT_Init( DeviceCaps
* pDevCaps
)
1383 fontResource
* fr
, *pfr
;
1385 unsigned x_checksum
;
1386 int i
, j
, res
, x_count
, fd
= -1, buf_size
= 0;
1387 char* lpstr
, *lpch
, *lpmetrics
, *buffer
;
1390 XFONT_CheckIniSection();
1392 res
= XFONT_GetPointResolution( pDevCaps
);
1394 x_pattern
= TSXListFonts(display
, "*", MAX_FONT_FAMILIES
* 16, &x_count
);
1396 TRACE(font
,"Font Mapper: initializing %i fonts [LPY=%i, XDR=%i, DR=%i]\n",
1397 x_count
, pDevCaps
->logPixelsY
, DefResolution
, res
);
1398 for( i
= x_checksum
= 0; i
< x_count
; i
++ )
1401 printf("%i\t: %s\n", i
, x_pattern
[i
] );
1404 j
= strlen( x_pattern
[i
] );
1405 if( j
) x_checksum
^= __genericCheckSum( x_pattern
[i
], j
);
1407 x_checksum
|= X_PFONT_MAGIC
;
1410 buffer
= HeapAlloc( SystemHeap
, 0, buf_size
);
1413 /* deal with systemwide font metrics cache */
1415 if( PROFILE_GetWineIniString( INIFontSection
, INIGlobalMetrics
, "", buffer
, 128 ) )
1416 fd
= open( buffer
, O_RDONLY
);
1418 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1421 buffer
= XFONT_UserMetricsCache( buffer
, &buf_size
);
1424 fd
= open( buffer
, O_RDONLY
);
1425 if( XFONT_ReadCachedMetrics(fd
, res
, x_checksum
, x_count
) == FALSE
)
1426 lpmetrics
= HEAP_strdupA( SystemHeap
, 0, buffer
); /* update later on */
1431 if( fontList
== NULL
) /* build metrics from scratch */
1436 for( i
= n_ff
= 0; i
< x_count
; i
++ )
1438 typeface
= lpch
= x_pattern
[i
];
1440 lpch
= LFD_Advance(typeface
, 3); /* extra '-' in the beginning */
1441 if( !*lpch
) continue;
1444 j
= lpch
- typeface
; /* resource name length */
1446 /* find a family to insert into */
1448 for( pfr
= NULL
, fr
= fontList
; fr
; fr
= fr
->next
)
1450 if( !strncasecmp(fr
->resource
, typeface
, j
) &&
1451 strlen(fr
->resource
) == j
) break;
1455 if( !fi
) fi
= (fontInfo
*) HeapAlloc(SystemHeap
, 0, sizeof(fontInfo
));
1457 if( !fr
) /* add new family */
1459 if( n_ff
>= MAX_FONT_FAMILIES
) break;
1460 if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1463 fr
= (fontResource
*) HeapAlloc(SystemHeap
, 0, sizeof(fontResource
));
1464 memset(fr
, 0, sizeof(fontResource
));
1465 fr
->resource
= (char*) HeapAlloc(SystemHeap
, 0, j
+ 1 );
1466 lstrcpyn32A( fr
->resource
, typeface
, j
+ 1 );
1468 TRACE(font
," family: %s\n", fr
->resource
);
1470 if( pfr
) pfr
->next
= fr
;
1473 else if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1475 /* check if we already have something better than "fi" */
1477 for( pfi
= fr
->fi
, j
= 0; pfi
&& j
<= 0; pfi
= pfi
->next
)
1478 if( (j
= XFONT_IsSubset( pfi
, fi
)) < 0 )
1479 pfi
->fi_flags
|= FI_SUBSET
; /* superseded by "fi" */
1480 if( j
> 0 ) continue;
1482 /* add new font instance "fi" to the "fr" font resource */
1484 if( fi
->fi_flags
& FI_SCALABLE
)
1486 /* set scalable font height to 24 to get an origin for extrapolation */
1488 j
= strlen(typeface
); j
+= 0x10;
1490 buffer
= (char*)HeapReAlloc( SystemHeap
, 0, buffer
, buf_size
= j
);
1492 lpch
= LFD_Advance(typeface
, 7);
1493 memcpy( buffer
, typeface
, (j
= lpch
- typeface
) );
1494 lpch
= LFD_Advance(lpch
, 4);
1495 sprintf( buffer
+ j
, "%d-%d-%d-*-%c-*-", fi
->lfd_height
,
1496 fi
->lfd_decipoints
, fi
->lfd_resolution
,
1497 (*lpch
== '-')?'*':*lpch
);
1498 lpch
= LFD_Advance(lpch
, 2);
1499 strcat( lpstr
= buffer
, lpch
);
1501 else lpstr
= typeface
;
1503 if( (x_fs
= TSXLoadQueryFont(display
, lpstr
)) )
1505 fi
->df
.dfHorizRes
= fi
->df
.dfVertRes
= res
;
1507 XFONT_SetFontMetric( fi
, fr
, x_fs
);
1508 TSXFreeFont( display
, x_fs
);
1510 TRACE(font
,"\t[% 2ipt] '%s'\n", fi
->df
.dfPoints
, typeface
);
1512 XFONT_CheckFIList( fr
, fi
, REMOVE_SUBSETS
);
1513 fi
= NULL
; /* preventing reuse */
1517 ERR(font
, "failed to load %s\n", lpstr
);
1519 XFONT_CheckFIList( fr
, fi
, UNMARK_SUBSETS
);
1523 if( lpmetrics
) /* update cached metrics */
1525 fd
= open( lpmetrics
, O_CREAT
| O_TRUNC
| O_RDWR
, 0644 ); /* -rw-r--r-- */
1526 if( XFONT_WriteCachedMetrics( fd
, x_checksum
, x_count
, n_ff
) == FALSE
)
1527 if( fd
) remove( lpmetrics
); /* couldn't write entire file */
1528 HeapFree( SystemHeap
, 0, lpmetrics
);
1532 if( fi
) HeapFree(SystemHeap
, 0, fi
);
1533 TSXFreeFontNames(x_pattern
);
1535 /* check if we're dealing with X11 R6 server */
1537 strcpy(buffer
, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1538 if( (x_fs
= TSXLoadQueryFont(display
, buffer
)) )
1540 XTextCaps
|= TC_SF_X_YINDEP
;
1541 TSXFreeFont(display
, x_fs
);
1544 XFONT_WindowsNames( buffer
);
1545 XFONT_LoadAliases( &buffer
, buf_size
);
1546 HeapFree(SystemHeap
, 0, buffer
);
1549 /* fontList initialization is over, allocate X font cache */
1551 fontCache
= (fontObject
*) HeapAlloc(SystemHeap
, 0, fontCacheSize
* sizeof(fontObject
));
1552 XFONT_GrowFreeList(0, fontCacheSize
- 1);
1554 TRACE(font
,"done!\n");
1556 /* update text caps parameter */
1558 pDevCaps
->textCaps
= XTextCaps
;
1560 RAW_ASCENT
= TSXInternAtom(display
, "RAW_ASCENT", TRUE
);
1561 RAW_DESCENT
= TSXInternAtom(display
, "RAW_DESCENT", TRUE
);
1567 /***********************************************************************
1570 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1572 static INT32
XFONT_IsSubset(fontInfo
* match
, fontInfo
* fi
)
1576 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1578 m
= (BYTE
*)&fi
->df
.dfPixWidth
- (BYTE
*)&fi
->df
.dfItalic
;
1579 if( memcmp(&match
->df
.dfItalic
, &fi
->df
.dfItalic
, m
)) return 0;
1581 if( (!((fi
->fi_flags
& FI_SCALABLE
) + (match
->fi_flags
& FI_SCALABLE
))
1582 && fi
->lfd_height
!= match
->lfd_height
) ||
1583 (!((fi
->fi_flags
& FI_POLYWEIGHT
) + (match
->fi_flags
& FI_POLYWEIGHT
))
1584 && fi
->df
.dfWeight
!= match
->df
.dfWeight
) ) return 0;
1586 m
= (int)(match
->fi_flags
& (FI_POLYWEIGHT
| FI_SCALABLE
)) -
1587 (int)(fi
->fi_flags
& (FI_SCALABLE
| FI_POLYWEIGHT
));
1589 if( m
== (FI_POLYWEIGHT
- FI_SCALABLE
) ||
1590 m
== (FI_SCALABLE
- FI_POLYWEIGHT
) ) return 0; /* keep both */
1591 else if( m
>= 0 ) return 1; /* 'match' is better */
1593 return -1; /* 'fi' is better */
1596 /***********************************************************************
1599 * Compute the matching score between the logical font and the device font.
1601 * contributions from highest to lowest:
1605 * family flags (only when the facename is not present)
1607 * weight, italics, underlines, strikeouts
1609 * NOTE: you can experiment with different penalty weights to see what happens.
1610 * http://premium.microsoft.com/msdn/library/techart/f365/f36b/f37b/d38b/sa8bf.htm
1612 static UINT32
XFONT_Match( fontMatch
* pfm
)
1614 fontInfo
* pfi
= pfm
->pfi
; /* device font to match */
1615 LPLOGFONT16 plf
= pfm
->plf
; /* wanted logical font */
1617 BOOL32 bR6
= pfm
->flags
& FO_MATCH_XYINDEP
; /* from TextCaps */
1618 BOOL32 bScale
= pfi
->fi_flags
& FI_SCALABLE
;
1621 TRACE(font
,"\t[ %-2ipt h=%-3i w=%-3i %s%s]\n", pfi
->df
.dfPoints
,
1622 pfi
->df
.dfPixHeight
, pfi
->df
.dfAvgWidth
,
1623 (pfi
->df
.dfWeight
> 400) ? "Bold " : "Normal ",
1624 (pfi
->df
.dfItalic
) ? "Italic" : "" );
1628 if( plf
->lfCharSet
== DEFAULT_CHARSET
)
1630 if( (pfi
->df
.dfCharSet
!= ANSI_CHARSET
) && (pfi
->df
.dfCharSet
!=DEFAULT_CHARSET
) )
1633 else if (plf
->lfCharSet
!= pfi
->df
.dfCharSet
) penalty
+= 0x200;
1635 /* FIXME: Hack to demote symbols and nil fonts. Should take into
1636 account if a program ever actually asked for this type of
1638 if ( (strcmp(pfm
->pfr
->lfFaceName
,"Symbol")==0) || (strcmp(pfm
->pfr
->lfFaceName
,"Nil")==0) )
1639 penalty
+= 0x200; /* very stiff penality */
1641 /* TMPF_FIXED_PITCH means exactly the opposite */
1643 if( plf
->lfPitchAndFamily
& FIXED_PITCH
)
1645 if( pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) penalty
+= 0x100;
1647 else if( !(pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) ) penalty
+= 0x2;
1649 if( plf
->lfHeight
> 0 )
1650 d
= (h
= pfi
->df
.dfPixHeight
) - plf
->lfHeight
;
1651 else if( plf
->lfHeight
< -1 )
1652 d
= (h
= pfi
->df
.dfPoints
) + plf
->lfHeight
;
1655 if( d
&& plf
->lfHeight
)
1657 UINT16 height
= ( plf
->lfHeight
> 0 ) ? plf
->lfHeight
1658 : ((-plf
->lfHeight
* pfi
->df
.dfPixHeight
) / h
);
1659 if( bScale
) pfm
->height
= height
;
1660 else if( (plf
->lfQuality
!= PROOF_QUALITY
) && bR6
)
1662 if( d
> 0 ) /* do not shrink raster fonts */
1664 pfm
->height
= pfi
->df
.dfPixHeight
;
1665 penalty
+= (pfi
->df
.dfPixHeight
- height
) * 0x4;
1667 else /* expand only in integer multiples */
1669 pfm
->height
= height
- height
%pfi
->df
.dfPixHeight
;
1670 penalty
+= (height
- pfm
->height
+ 1) * height
/ pfi
->df
.dfPixHeight
;
1673 else /* can't be scaled at all */
1675 if( plf
->lfQuality
!= PROOF_QUALITY
) pfm
->flags
|= FO_SYNTH_HEIGHT
;
1676 pfm
->height
= pfi
->df
.dfPixHeight
;
1677 penalty
+= (d
> 0)? d
* 0x8 : -d
* 0x10;
1679 } else pfm
->height
= pfi
->df
.dfPixHeight
;
1681 if((pfm
->flags
& FO_MATCH_PAF
) &&
1682 (plf
->lfPitchAndFamily
& FF_FAMILY
) != (pfi
->df
.dfPitchAndFamily
& FF_FAMILY
) )
1687 if( bR6
&& bScale
) h
= 0;
1690 /* FIXME: not complete */
1692 pfm
->flags
|= FO_SYNTH_WIDTH
;
1693 h
= abs(plf
->lfWidth
- (pfm
->height
* pfi
->df
.dfAvgWidth
)/pfi
->df
.dfPixHeight
);
1695 penalty
+= h
* ( d
) ? 0x2 : 0x1 ;
1697 else if( !(pfi
->fi_flags
& FI_NORMAL
) ) penalty
++;
1699 if( plf
->lfWeight
!= FW_DONTCARE
)
1701 penalty
+= abs(plf
->lfWeight
- pfi
->df
.dfWeight
) / 40;
1702 if( plf
->lfWeight
> pfi
->df
.dfWeight
) pfm
->flags
|= FO_SYNTH_BOLD
;
1703 } else if( pfi
->df
.dfWeight
>= FW_BOLD
) penalty
++; /* choose normal by default */
1705 if( plf
->lfItalic
!= pfi
->df
.dfItalic
)
1708 pfm
->flags
|= FO_SYNTH_ITALIC
;
1711 if( plf
->lfUnderline
) pfm
->flags
|= FO_SYNTH_UNDERLINE
;
1712 if( plf
->lfStrikeOut
) pfm
->flags
|= FO_SYNTH_STRIKEOUT
;
1714 if( penalty
&& pfi
->lfd_resolution
!= DefResolution
)
1717 TRACE(font
," returning %i\n", penalty
);
1722 /***********************************************************************
1725 * Scan a particular font resource for the best match.
1727 static UINT32
XFONT_MatchFIList( fontMatch
* pfm
)
1729 BOOL32 skipRaster
= (pfm
->flags
& FO_MATCH_NORASTER
);
1730 UINT32 current_score
, score
= (UINT32
)(-1);
1731 UINT16 origflags
= pfm
->flags
; /* Preserve FO_MATCH_XYINDEP */
1732 fontMatch fm
= *pfm
;
1734 for( fm
.pfi
= pfm
->pfr
->fi
; fm
.pfi
&& score
; fm
.pfi
= fm
.pfi
->next
,
1735 fm
.flags
= origflags
)
1737 if( skipRaster
&& !(fm
.pfi
->fi_flags
& FI_SCALABLE
) )
1740 current_score
= XFONT_Match( &fm
);
1741 if( score
> current_score
)
1743 memcpy( pfm
, &fm
, sizeof(fontMatch
) );
1744 score
= current_score
;
1750 /***********************************************************************
1753 * REMOVE_SUBSETS - attach new fi and purge subsets
1754 * UNMARK_SUBSETS - remove subset flags from all fi entries
1756 static void XFONT_CheckFIList( fontResource
* fr
, fontInfo
* fi
, int action
)
1759 fontInfo
* pfi
, *prev
;
1761 for( prev
= NULL
, pfi
= fr
->fi
; pfi
; )
1763 if( action
== REMOVE_SUBSETS
)
1765 if( pfi
->fi_flags
& FI_SUBSET
)
1767 fontInfo
* subset
= pfi
;
1771 if( prev
) prev
->next
= pfi
= pfi
->next
;
1772 else fr
->fi
= pfi
= pfi
->next
;
1773 HeapFree( SystemHeap
, 0, subset
);
1777 else pfi
->fi_flags
&= ~FI_SUBSET
;
1783 if( action
== REMOVE_SUBSETS
) /* also add the superset */
1785 if( fi
->fi_flags
& FI_SCALABLE
)
1790 else if( prev
) prev
->next
= fi
; else fr
->fi
= fi
;
1794 if( i
) TRACE(font
,"\t purged %i subsets [%i]\n", i
, fr
->count
);
1797 /***********************************************************************
1800 static fontResource
* XFONT_FindFIList( fontResource
* pfr
, const char* pTypeFace
)
1804 if( !strcasecmp( pfr
->lfFaceName
, pTypeFace
) ) break;
1810 /***********************************************************************
1811 * XFONT_MatchDeviceFont
1813 * Scan font resource tree.
1815 static BOOL32
XFONT_MatchDeviceFont( fontResource
* start
, fontMatch
* pfm
)
1817 fontMatch fm
= *pfm
;
1820 if( fm
.plf
->lfFaceName
[0] )
1825 for( fa
= aliasTable
; fa
; fa
= fa
->next
)
1826 if( !strcmp( fa
->faAlias
, fm
.plf
->lfFaceName
) )
1828 str
= fa
->faTypeFace
;
1831 fm
.pfr
= XFONT_FindFIList( start
, str
? str
: fm
.plf
->lfFaceName
);
1834 if( fm
.pfr
) /* match family */
1836 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
1838 XFONT_MatchFIList( &fm
);
1842 if( !pfm
->pfi
) /* match all available fonts */
1844 UINT32 current_score
, score
= (UINT32
)(-1);
1846 fm
.flags
|= FO_MATCH_PAF
;
1847 for( start
= fontList
; start
&& score
; start
= start
->next
)
1851 TRACE(font
, "%s\n", fm
.pfr
->lfFaceName
);
1853 current_score
= XFONT_MatchFIList( &fm
);
1854 if( current_score
< score
)
1856 score
= current_score
;
1865 /***********************************************************************
1868 static void XFONT_GrowFreeList(int start
, int end
)
1870 /* add all entries from 'start' up to and including 'end' */
1872 memset( fontCache
+ start
, 0, (end
- start
+ 1) * sizeof(fontObject
) );
1874 fontCache
[end
].lru
= fontLF
;
1875 fontCache
[end
].count
= -1;
1877 while( start
< end
)
1879 fontCache
[start
].count
= -1;
1880 fontCache
[start
].lru
= start
+ 1;
1885 static fontObject
* XFONT_LookupCachedFont( LPLOGFONT16 plf
, UINT16
* checksum
)
1887 UINT16 cs
= __lfCheckSum( plf
);
1888 int i
= fontMRU
, prev
= -1;
1893 if( fontCache
[i
].lfchecksum
== cs
&&
1894 !(fontCache
[i
].fo_flags
& FO_REMOVED
) )
1896 /* FIXME: something more intelligent here */
1898 if( !memcmp( plf
, &fontCache
[i
].lf
,
1899 sizeof(LOGFONT16
) - LF_FACESIZE
) &&
1900 !strncasecmp( plf
->lfFaceName
, fontCache
[i
].lf
.lfFaceName
,
1903 /* remove temporarily from the lru list */
1906 fontCache
[prev
].lru
= fontCache
[i
].lru
;
1908 fontMRU
= (INT16
)fontCache
[i
].lru
;
1909 return (fontCache
+ i
);
1913 i
= (INT16
)fontCache
[i
].lru
;
1918 static fontObject
* XFONT_GetCacheEntry()
1924 int prev_i
, prev_j
, j
;
1926 TRACE(font
,"font cache is full\n");
1928 /* lookup the least recently used font */
1930 for( prev_i
= prev_j
= j
= -1, i
= fontMRU
; i
>= 0; i
= (INT16
)fontCache
[i
].lru
)
1932 if( fontCache
[i
].count
<= 0 &&
1933 !(fontCache
[i
].fo_flags
& FO_SYSTEM
) )
1941 if( j
>= 0 ) /* unload font */
1943 /* detach from the lru list */
1945 TRACE(font
,"\tfreeing entry %i\n", j
);
1948 fontCache
[prev_j
].lru
= fontCache
[j
].lru
;
1949 else fontMRU
= (INT16
)fontCache
[j
].lru
;
1951 /* FIXME: lpXForm, lpPixmap */
1952 if(fontCache
[j
].lpX11Trans
)
1953 HeapFree( SystemHeap
, 0, fontCache
[j
].lpX11Trans
);
1955 TSXFreeFont( display
, fontCache
[j
].fs
);
1957 memset( fontCache
+ j
, 0, sizeof(fontObject
) );
1958 return (fontCache
+ j
);
1960 else /* expand cache */
1962 fontObject
* newCache
;
1964 prev_i
= fontCacheSize
+ FONTCACHE
;
1966 TRACE(font
,"\tgrowing font cache from %i to %i\n", fontCacheSize
, prev_i
);
1968 if( (newCache
= (fontObject
*)HeapReAlloc(SystemHeap
, 0,
1969 fontCache
, prev_i
)) )
1972 fontCacheSize
= prev_i
;
1973 fontCache
= newCache
;
1974 XFONT_GrowFreeList( i
, fontCacheSize
- 1);
1980 /* detach from the free list */
1983 fontLF
= (INT16
)fontCache
[i
].lru
;
1984 fontCache
[i
].count
= 0;
1985 return (fontCache
+ i
);
1988 static int XFONT_ReleaseCacheEntry(fontObject
* pfo
)
1990 UINT32 u
= (UINT32
)(pfo
- fontCache
);
1992 if( u
< fontCacheSize
) return (--fontCache
[u
].count
);
1996 /**********************************************************************
1999 static BOOL32
XFONT_SetX11Trans( fontObject
*pfo
)
2006 TSXGetFontProperty( pfo
->fs
, XA_FONT
, &nameAtom
);
2007 fontName
= TSXGetAtomName( display
, nameAtom
);
2008 for(i
= 0, cp
= fontName
; i
< 7; i
++) {
2009 cp
= strchr(cp
, '-');
2017 while((cp
= strchr(cp
, '~')))
2020 #define PX pfo->lpX11Trans
2022 sscanf(start
, "[%f%f%f%f]", &PX
->a
, &PX
->b
, &PX
->c
, &PX
->d
);
2025 TSXGetFontProperty( pfo
->fs
, RAW_ASCENT
, &PX
->RAW_ASCENT
);
2026 TSXGetFontProperty( pfo
->fs
, RAW_DESCENT
, &PX
->RAW_DESCENT
);
2028 PX
->pixelsize
= hypot(PX
->a
, PX
->b
);
2029 PX
->ascent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_ASCENT
;
2030 PX
->descent
= PX
->pixelsize
/ 1000.0 * PX
->RAW_DESCENT
;
2032 TRACE(font
, "[%f %f %f %f] RA = %ld RD = %ld\n", pfo
->lpX11Trans
->a
,
2033 pfo
->lpX11Trans
->b
, pfo
->lpX11Trans
->c
, pfo
->lpX11Trans
->d
,
2034 pfo
->lpX11Trans
->RAW_ASCENT
, pfo
->lpX11Trans
->RAW_DESCENT
);
2040 /***********************************************************************
2041 * X Device Font Objects
2043 static X_PHYSFONT
XFONT_RealizeFont( LPLOGFONT16 plf
)
2046 fontObject
* pfo
= XFONT_LookupCachedFont( plf
, &checksum
);
2050 fontMatch fm
= { NULL
, NULL
, 0, 0, plf
};
2053 if( XTextCaps
& TC_SF_X_YINDEP
) fm
.flags
= FO_MATCH_XYINDEP
;
2055 /* allocate new font cache entry */
2057 if( (pfo
= XFONT_GetCacheEntry()) )
2059 LPSTR lpLFD
= HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH
);
2061 if( lpLFD
) /* initialize entry and load font */
2063 UINT32 uRelaxLevel
= 0;
2065 TRACE(font
,"(%u) '%s' h=%i weight=%i %s\n",
2066 plf
->lfCharSet
, plf
->lfFaceName
, plf
->lfHeight
,
2067 plf
->lfWeight
, (plf
->lfItalic
) ? "Italic" : "" );
2069 XFONT_MatchDeviceFont( fontList
, &fm
);
2073 pfo
->fo_flags
= fm
.flags
& ~FO_MATCH_MASK
;
2075 memcpy( &pfo
->lf
, plf
, sizeof(LOGFONT16
) );
2076 pfo
->lfchecksum
= checksum
;
2080 LFD_ComposeLFD( pfo
, fm
.height
, lpLFD
, uRelaxLevel
++ );
2081 if( (pfo
->fs
= TSXLoadQueryFont( display
, lpLFD
)) ) break;
2082 } while( uRelaxLevel
);
2085 if(pfo
->lf
.lfEscapement
!= 0) {
2086 pfo
->lpX11Trans
= HeapAlloc(SystemHeap
, 0,
2087 sizeof(XFONTTRANS
));
2088 if(!XFONT_SetX11Trans( pfo
)) {
2089 HeapFree(SystemHeap
, 0, pfo
->lpX11Trans
);
2090 pfo
->lpX11Trans
= NULL
;
2094 if( XFONT_GetLeading( &pfo
->fi
->df
, pfo
->fs
, &i
, NULL
,
2097 if(!pfo
->lpX11Trans
)
2098 pfo
->foAvgCharWidth
=
2099 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].width
;
2101 pfo
->foAvgCharWidth
=
2102 (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].attributes
2103 * pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2105 pfo
->foAvgCharWidth
= (INT16
)XFONT_GetAvgCharWidth(
2106 &pfo
->fi
->df
, pfo
->fs
, pfo
->lpX11Trans
);
2107 pfo
->foMaxCharWidth
= (INT16
)XFONT_GetMaxCharWidth(pfo
);
2108 pfo
->foInternalLeading
= (INT16
)i
;
2110 /* FIXME: If we've got a soft font or
2111 * there are FO_SYNTH_... flags for the
2112 * non PROOF_QUALITY request, the engine
2113 * should rasterize characters into mono
2114 * pixmaps and store them in the pfo->lpPixmap
2115 * array (pfo->fs should be updated as well).
2116 * X11DRV_ExtTextOut() must be heavily modified
2117 * to support pixmap blitting and FO_SYNTH_...
2121 pfo
->lpXForm
= NULL
;
2122 pfo
->lpPixmap
= NULL
;
2124 HeapFree( GetProcessHeap(), 0, lpLFD
);
2126 else /* attach back to the free list */
2130 fontLF
= (pfo
- fontCache
);
2135 if( !pfo
) /* couldn't get a new entry, get one of the cached fonts */
2137 UINT32 current_score
, score
= (UINT32
)(-1);
2139 i
= index
= fontMRU
;
2140 fm
.flags
|= FO_MATCH_PAF
;
2143 pfo
= fontCache
+ i
;
2144 fm
.pfr
= pfo
->fr
; fm
.pfi
= pfo
->fi
;
2146 current_score
= XFONT_Match( &fm
);
2147 if( current_score
< score
) index
= i
;
2151 pfo
= fontCache
+ index
;
2153 return (X_PHYSFONT
)(X_PFONT_MAGIC
| index
);
2157 /* attach at the head of the lru list */
2161 fontMRU
= (pfo
- fontCache
);
2163 TRACE(font
,"physfont %i\n", fontMRU
);
2165 return (X_PHYSFONT
)(X_PFONT_MAGIC
| fontMRU
);
2168 /***********************************************************************
2169 * XFONT_GetFontObject
2171 fontObject
* XFONT_GetFontObject( X_PHYSFONT pFont
)
2173 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
);
2177 /***********************************************************************
2178 * XFONT_GetFontStruct
2180 XFontStruct
* XFONT_GetFontStruct( X_PHYSFONT pFont
)
2182 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
)->fs
;
2186 /***********************************************************************
2189 LPIFONTINFO16
XFONT_GetFontInfo( X_PHYSFONT pFont
)
2191 if( CHECK_PFONT(pFont
) ) return &(__PFONT(pFont
)->fi
->df
);
2197 /* X11DRV Interface ****************************************************
2199 * Exposed via the dc->funcs dispatch table. *
2201 ***********************************************************************/
2202 /***********************************************************************
2203 * X11DRV_FONT_SelectObject
2205 HFONT32
X11DRV_FONT_SelectObject( DC
* dc
, HFONT32 hfont
, FONTOBJ
* font
)
2207 HFONT32 hPrevFont
= 0;
2209 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2211 if( CHECK_PFONT(physDev
->font
) )
2212 XFONT_ReleaseCacheEntry( __PFONT(physDev
->font
) );
2214 /* FIXME: do we need to pass anything back from here? */
2215 memcpy(&lf
,&font
->logfont
,sizeof(lf
));
2216 lf
.lfWidth
= font
->logfont
.lfWidth
* dc
->vportExtX
/dc
->wndExtX
;
2217 lf
.lfHeight
= font
->logfont
.lfHeight
* dc
->vportExtY
/dc
->wndExtY
;
2219 physDev
->font
= XFONT_RealizeFont( &lf
);
2220 hPrevFont
= dc
->w
.hFont
;
2221 dc
->w
.hFont
= hfont
;
2227 /***********************************************************************
2229 * X11DRV_EnumDeviceFonts
2231 BOOL32
X11DRV_EnumDeviceFonts( DC
* dc
, LPLOGFONT16 plf
,
2232 DEVICEFONTENUMPROC proc
, LPARAM lp
)
2236 fontResource
* pfr
= fontList
;
2239 if( plf
->lfFaceName
[0] )
2241 pfr
= XFONT_FindFIList( pfr
, plf
->lfFaceName
);
2245 for( pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
2246 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2247 XFONT_GetFontMetric( pfi
, &lf
, &tm
), lp
)) )
2253 for( ; pfr
; pfr
= pfr
->next
)
2256 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
2257 XFONT_GetFontMetric( pfr
->fi
, &lf
, &tm
), lp
)) )
2266 /***********************************************************************
2267 * X11DRV_GetTextExtentPoint
2269 BOOL32
X11DRV_GetTextExtentPoint( DC
*dc
, LPCSTR str
, INT32 count
,
2272 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2273 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2275 if( !pfo
->lpX11Trans
) {
2276 int dir
, ascent
, descent
;
2279 TSXTextExtents( pfo
->fs
, str
, count
, &dir
, &ascent
, &descent
, &info
);
2280 size
->cx
= abs((info
.width
+ dc
->w
.breakRem
+ count
*
2281 dc
->w
.charExtra
) * dc
->wndExtX
/ dc
->vportExtX
);
2282 size
->cy
= abs((pfo
->fs
->ascent
+ pfo
->fs
->descent
) *
2283 dc
->wndExtY
/ dc
->vportExtY
);
2287 float x
= 0.0, y
= 0.0;
2288 for(i
= 0; i
< count
; i
++) {
2289 x
+= pfo
->fs
->per_char
?
2290 pfo
->fs
->per_char
[str
[i
] - pfo
->fs
->min_char_or_byte2
].attributes
:
2291 pfo
->fs
->min_bounds
.attributes
;
2293 y
= pfo
->lpX11Trans
->RAW_ASCENT
+ pfo
->lpX11Trans
->RAW_DESCENT
;
2294 TRACE(font
, "x = %f y = %f\n", x
, y
);
2295 x
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2296 y
*= pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2297 size
->cx
= fabsf((x
+ dc
->w
.breakRem
+ count
* dc
->w
.charExtra
) *
2298 dc
->wndExtX
/ dc
->vportExtX
);
2299 size
->cy
= fabsf(y
* dc
->wndExtY
/ dc
->vportExtY
);
2307 /***********************************************************************
2308 * X11DRV_GetTextMetrics
2310 BOOL32
X11DRV_GetTextMetrics(DC
*dc
, TEXTMETRIC32A
*metrics
)
2312 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2314 if( CHECK_PFONT(physDev
->font
) )
2316 fontObject
* pfo
= __PFONT(physDev
->font
);
2317 XFONT_GetTextMetric( pfo
, metrics
);
2325 /***********************************************************************
2326 * X11DRV_GetCharWidth
2328 BOOL32
X11DRV_GetCharWidth( DC
*dc
, UINT32 firstChar
, UINT32 lastChar
,
2331 X11DRV_PDEVICE
*physDev
= (X11DRV_PDEVICE
*)dc
->physDev
;
2332 fontObject
* pfo
= XFONT_GetFontObject( physDev
->font
);
2338 if (pfo
->fs
->per_char
== NULL
)
2339 for (i
= firstChar
; i
<= lastChar
; i
++)
2341 *buffer
++ = pfo
->fs
->min_bounds
.attributes
*
2342 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2344 *buffer
++ = pfo
->fs
->min_bounds
.width
;
2347 XCharStruct
*cs
, *def
;
2348 static XCharStruct __null_char
= { 0, 0, 0, 0, 0, 0 };
2350 CI_GET_CHAR_INFO(pfo
->fs
, pfo
->fs
->default_char
, &__null_char
,
2353 for (i
= firstChar
; i
<= lastChar
; i
++)
2355 if (i
>= pfo
->fs
->min_char_or_byte2
&&
2356 i
<= pfo
->fs
->max_char_or_byte2
)
2358 cs
= &pfo
->fs
->per_char
[(i
- pfo
->fs
->min_char_or_byte2
)];
2359 if (CI_NONEXISTCHAR(cs
)) cs
= def
;
2362 *buffer
++ = MAX(cs
->attributes
, 0) *
2363 pfo
->lpX11Trans
->pixelsize
/ 1000.0;
2365 *buffer
++ = MAX(cs
->width
, 0 );
2374 /***********************************************************************
2376 * Font Resource API *
2378 ***********************************************************************/
2379 /***********************************************************************
2380 * AddFontResource16 (GDI.119)
2382 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
2384 * FIXME: Load header and find the best-matching font in the fontList;
2385 * fixup dfPoints if all metrics are identical, otherwise create
2386 * new fontAlias. When soft font support is ready this will
2387 * simply create a new fontResource ('filename' will go into
2388 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
2391 INT16 WINAPI
AddFontResource16( LPCSTR filename
)
2393 return AddFontResource32A( filename
);
2397 /***********************************************************************
2398 * AddFontResource32A (GDI32.2)
2400 INT32 WINAPI
AddFontResource32A( LPCSTR str
)
2402 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2407 /***********************************************************************
2408 * AddFontResource32W (GDI32.4)
2410 INT32 WINAPI
AddFontResource32W( LPCWSTR str
)
2412 FIXME(font
, "(%s): stub\n", debugres_w(str
) );
2416 /***********************************************************************
2417 * RemoveFontResource16 (GDI.136)
2419 BOOL16 WINAPI
RemoveFontResource16( SEGPTR str
)
2421 FIXME(font
, "(%s): stub\n", debugres_a(PTR_SEG_TO_LIN(str
)));
2426 /***********************************************************************
2427 * RemoveFontResource32A (GDI32.284)
2429 BOOL32 WINAPI
RemoveFontResource32A( LPCSTR str
)
2431 FIXME(font
, "(%s): stub\n", debugres_a(str
));
2436 /***********************************************************************
2437 * RemoveFontResource32W (GDI32.286)
2439 BOOL32 WINAPI
RemoveFontResource32W( LPCWSTR str
)
2441 FIXME(font
, "(%s): stub\n", debugres_w(str
) );