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>
28 #define DEBUG_FONT_INIT 1
30 #define X_PFONT_MAGIC (0xFADE0000)
31 #define X_FMC_MAGIC (0x0000CAFE)
33 #define MAX_FONT_FAMILIES 64
34 #define MAX_LFD_LENGTH 128
36 #define REMOVE_SUBSETS 1
37 #define UNMARK_SUBSETS 0
39 #define DEF_SCALABLE_HEIGHT 24
40 #define DEF_SCALABLE_DP 240
42 #define FF_FAMILY (FF_MODERN | FF_SWISS | FF_ROMAN | FF_DECORATIVE | FF_SCRIPT)
44 typedef struct __fontAlias
48 struct __fontAlias
* next
;
51 static fontAlias aliasTable
[2] = {
52 { "Helvetica", "Helv", &aliasTable
[1] },
53 { "Times", "Tms Rmn", NULL
}
56 UINT16 XTextCaps
= TC_OP_CHARACTER
| TC_OP_STROKE
| TC_CP_STROKE
|
57 TC_SA_DOUBLE
| TC_SA_INTEGER
| TC_SA_CONTIN
|
58 TC_UA_ABLE
| TC_SO_ABLE
| TC_RA_ABLE
;
60 /* X11R6 adds TC_SF_X_YINDEP, maybe more... */
62 static const char* INIWinePrefix
= "/.wine";
63 static const char* INIFontMetrics
= "/.cachedmetrics";
64 static const char* INIFontSection
= "fonts";
65 static const char* INISubSection
= "Alias";
66 static const char* INIDefault
= "Default";
68 static const char* LFDSeparator
= "*-";
69 static const char* iso8859Encoding
= "iso8859-";
70 static const char* iso646Encoding
= "iso646.1991-";
71 static const char* ansiEncoding
= "ansi-";
72 static fontResource
* fontList
= NULL
;
73 static unsigned DefResolution
= 0;
75 static fontObject
* fontCache
= NULL
; /* array */
76 static int fontCacheSize
= FONTCACHE
;
77 static int fontLF
= -1, fontMRU
= -1; /* last free, most recently used */
79 #define __PFONT(pFont) ( fontCache + ((UINT32)(pFont) & 0x0000FFFF) )
80 #define CHECK_PFONT(pFont) ( (((UINT32)(pFont) & 0xFFFF0000) == X_PFONT_MAGIC) &&\
81 (((UINT32)(pFont) & 0x0000FFFF) < fontCacheSize) )
83 static INT32
XFONT_IsSubset(fontInfo
*, fontInfo
*);
84 static void XFONT_CheckFIList(fontResource
*, fontInfo
*, int subset_action
);
85 static void XFONT_GrowFreeList(int start
, int end
);
87 /***********************************************************************
88 * Helper macros from X distribution
91 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
92 (((cs)->rbearing|(cs)->lbearing| \
93 (cs)->ascent|(cs)->descent) == 0))
95 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
98 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
99 if (fs->per_char == NULL) { \
100 cs = &fs->min_bounds; \
102 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
103 if (CI_NONEXISTCHAR(cs)) cs = def; \
108 #define CI_GET_DEFAULT_INFO(fs,cs) \
109 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
111 /***********************************************************************
114 static UINT16
__lfCheckSum( LPLOGFONT16 plf
)
116 CHAR font
[LF_FACESIZE
];
120 #define ptr ((UINT16*)plf)
121 for( i
= 0; i
< 9; i
++ ) checksum
^= *ptr
++;
124 #define ptr ((CHAR*)plf)
125 do { font
[i
++] = tolower(*ptr
); } while (*ptr
++);
126 for( ptr
= font
, i
>>= 1; i
> 0; i
-- )
128 #define ptr ((UINT16*)plf)
134 static UINT16
__genericCheckSum( UINT16
* ptr
, int size
)
139 for( i
= 0, size
>>= 1; i
< size
; i
++ ) checksum
^= *ptr
++;
143 /*************************************************************************
144 * LFD parse/compose routines
146 static char* LFD_Advance(LPSTR lpFont
, UINT16 uParmsNo
)
151 for( ; j
< uParmsNo
&& *lpch
; lpch
++ ) if( *lpch
== LFDSeparator
[1] ) j
++;
155 static void LFD_GetWeight( fontInfo
* fi
, LPSTR lpStr
, int j
)
157 if( j
== 1 && *lpStr
== '0' )
158 fi
->fi_flags
|= FI_POLYWEIGHT
;
161 if( !lstrncmpi32A( "bold", lpStr
, 4) )
162 fi
->df
.dfWeight
= FW_BOLD
;
163 else if( !lstrncmpi32A( "demi", lpStr
, 4) )
165 fi
->fi_flags
|= FI_FW_DEMI
;
166 fi
->df
.dfWeight
= FW_DEMIBOLD
;
168 else if( !lstrncmpi32A( "book", lpStr
, 4) )
170 fi
->fi_flags
|= FI_FW_BOOK
;
171 fi
->df
.dfWeight
= FW_REGULAR
;
176 if( !lstrncmpi32A( "light", lpStr
, 5) )
177 fi
->df
.dfWeight
= FW_LIGHT
;
178 else if( !lstrncmpi32A( "black", lpStr
, 5) )
179 fi
->df
.dfWeight
= FW_BLACK
;
181 else if( j
== 6 && !lstrncmpi32A( "medium", lpStr
, 6) )
182 fi
->df
.dfWeight
= FW_REGULAR
;
183 else if( j
== 8 && !lstrncmpi32A( "demibold", lpStr
, 8) )
184 fi
->df
.dfWeight
= FW_DEMIBOLD
;
186 fi
->df
.dfWeight
= FW_DONTCARE
; /* FIXME: try to get something
187 * from the weight property */
190 static int LFD_GetSlant( fontInfo
* fi
, LPSTR lpStr
, int l
)
194 switch( tolower( *lpStr
) )
196 case '0': fi
->fi_flags
|= FI_POLYSLANT
; /* haven't seen this one yet */
198 case 'r': fi
->df
.dfItalic
= 0;
201 fi
->fi_flags
|= FI_OBLIQUE
;
202 case 'i': fi
->df
.dfItalic
= 1;
210 /*************************************************************************
213 * Fill in some fields in the fontInfo struct.
215 static int LFD_InitFontInfo( fontInfo
* fi
, LPSTR lpstr
)
218 int i
, j
, dec_style_check
, scalability
;
221 memset(fi
, 0, sizeof(fontInfo
) );
224 lpch
= LFD_Advance( lpstr
, 1);
225 if( !*lpch
) return FALSE
;
226 j
= lpch
- lpstr
- 1;
227 LFD_GetWeight( fi
, lpstr
, j
);
230 lpch
= LFD_Advance( lpstr
= lpch
, 1);
231 if( !*lpch
) return FALSE
;
232 j
= lpch
- lpstr
- 1;
233 dec_style_check
= LFD_GetSlant( fi
, lpstr
, j
);
236 lpch
= LFD_Advance( lpstr
= lpch
, 1);
237 if( !*lpch
) return FALSE
;
238 if( lstrncmpi32A( "normal", lpstr
, 6) ) /* XXX 'narrow', 'condensed', etc... */
239 dec_style_check
= TRUE
;
241 fi
->fi_flags
|= FI_NORMAL
;
244 lpch
= LFD_Advance( lpstr
= lpch
, 1);
245 if( !*lpch
) return FALSE
;
246 j
= lpch
- lpstr
- 1;
247 if( j
> 3 ) /* find out is there "sans" or "script" */
252 if( strstr(lpstr
, "sans") )
254 fi
->df
.dfPitchAndFamily
|= FF_SWISS
;
257 if( strstr(lpstr
, "script") )
259 fi
->df
.dfPitchAndFamily
|= FF_SCRIPT
;
262 if( !j
&& dec_style_check
)
263 fi
->df
.dfPitchAndFamily
|= FF_DECORATIVE
;
264 *(lpch
- 1) = LFDSeparator
[1];
267 /* pixel height, decipoint height, and res_x */
269 for( i
= scalability
= 0; i
< 3; i
++ )
271 lpch
= LFD_Advance( lpstr
= lpch
, 1);
272 if( !*lpch
) return FALSE
;
273 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
276 if( !(tmp
[i
] = atoi(lpstr
)) ) scalability
++;
277 *(lpch
- 1) = LFDSeparator
[1];
279 if( scalability
== 3 ) /* Type1 */
281 fi
->fi_flags
|= FI_SCALABLE
;
282 fi
->lfd_height
= DEF_SCALABLE_HEIGHT
; fi
->lfd_decipoints
= DEF_SCALABLE_DP
;
283 fi
->lfd_resolution
= DefResolution
;
285 else if( scalability
== 0 ) /* Bitmap */
287 fi
->lfd_height
= tmp
[0]; fi
->lfd_decipoints
= tmp
[1];
288 fi
->lfd_resolution
= tmp
[2];
290 else return FALSE
; /* #$%^!!! X11R6 mutant garbage */
292 /* res_y - skip, spacing - */
293 lpstr
= LFD_Advance( lpch
, 1);
296 case '\0': return FALSE
;
298 case 'p': fi
->fi_flags
|= FI_VARIABLEPITCH
;
300 case 'c': fi
->df
.dfPitchAndFamily
|= FF_MODERN
;
301 fi
->fi_flags
|= FI_FIXEDEX
;
303 case 'm': fi
->fi_flags
|= FI_FIXEDPITCH
;
306 fi
->df
.dfPitchAndFamily
|= DEFAULT_PITCH
| FF_DONTCARE
;
308 lpstr
= LFD_Advance(lpstr
, 1);
309 if( !*lpstr
) return FALSE
;
311 /* average width - */
312 lpch
= LFD_Advance( lpstr
, 1);
313 if( !*lpch
) return FALSE
;
314 if( lpch
- lpstr
== 1 || lpch
- lpstr
> 4 ) return FALSE
; /* ridiculous */
316 if( !(fi
->lfd_width
= atoi(lpstr
)) && !scalability
) return FALSE
;
317 *(lpch
- 1) = LFDSeparator
[1];
319 /* charset registry, charset encoding - */
320 if( strstr(lpch
, "jisx") || strstr(lpch
, "ksc") ) return FALSE
; /* 2-byte stuff */
322 if( strstr(lpch
, iso8859Encoding
) )
324 fi
->fi_flags
|= FI_ENC_ISO8859
;
325 fi
->df
.dfCharSet
= ANSI_CHARSET
;
327 else if( strstr(lpch
, iso646Encoding
) )
329 fi
->fi_flags
|= FI_ENC_ISO646
;
330 fi
->df
.dfCharSet
= ANSI_CHARSET
;
332 else if( strstr(lpch
, ansiEncoding
) ) /* font2bdf produces -ansi-0 LFD */
334 fi
->fi_flags
|= FI_ENC_ANSI
;
335 fi
->df
.dfCharSet
= ANSI_CHARSET
;
337 else if( strstr(lpch
, "fontspecific") )
338 fi
->df
.dfCharSet
= SYMBOL_CHARSET
;
340 fi
->df
.dfCharSet
= OEM_CHARSET
; /* FIXME: -cp126-.. from fnt2bdf */
345 /*************************************************************************
348 static BOOL32
LFD_ComposeLFD( fontObject
* fo
,
349 INT32 height
, LPSTR lpLFD
, UINT32 uRelax
)
351 int h
, w
, ch
, point
= 0;
353 const char* lpEncoding
= NULL
;
355 lstrcpy32A( lpLFD
, fo
->fr
->resource
);
358 switch( fo
->fi
->df
.dfWeight
)
361 strcat( lpLFD
, "bold" ); break;
363 if( fo
->fi
->fi_flags
& FI_FW_BOOK
)
364 strcat( lpLFD
, "book" );
366 strcat( lpLFD
, "medium" );
369 strcat( lpLFD
, "demi" );
370 if( !( fo
->fi
->fi_flags
& FI_FW_DEMI
) )
371 strcat ( lpLFD
, "bold" );
374 strcat( lpLFD
, "black" ); break;
376 strcat( lpLFD
, "light" ); break;
378 strcat( lpLFD
, "*" );
382 if( fo
->fi
->df
.dfItalic
)
383 if( fo
->fi
->fi_flags
& FI_OBLIQUE
)
384 strcat( lpLFD
, "-o" );
386 strcat( lpLFD
, "-i" );
388 strcat( lpLFD
, (uRelax
< 4) ? "-r" : "-*" );
390 /* add width style and skip serifs */
391 if( fo
->fi
->fi_flags
& FI_NORMAL
)
392 strcat( lpLFD
, "-normal-*-");
394 strcat( lpLFD
, "-*-*-" );
396 /* add pixelheight, pointheight, and resolution
398 * FIXME: fill in lpXForm and lpPixmap for rotated fonts
400 if( fo
->fo_flags
& FO_SYNTH_HEIGHT
) h
= fo
->fi
->lfd_height
;
401 else h
= (fo
->fi
->lfd_height
* height
) / fo
->fi
->df
.dfPixHeight
;
403 if( fo
->lf
.lfWidth
&& (XTextCaps
& TC_SF_X_YINDEP
)
404 && !(fo
->fo_flags
& FO_SYNTH_WIDTH
) )
405 point
= (fo
->fi
->lfd_decipoints
* fo
->lf
.lfWidth
) / fo
->fi
->df
.dfAvgWidth
;
407 /* spacing and width */
409 if( fo
->fi
->fi_flags
& FI_FIXEDPITCH
)
410 w
= ( fo
->fi
->fi_flags
& FI_FIXEDEX
) ? 'c' : 'm';
412 w
= ( fo
->fi
->fi_flags
& FI_VARIABLEPITCH
) ? 'p' : LFDSeparator
[0];
414 /* encoding, not quite there yet */
416 if( fo
->fi
->df
.dfCharSet
== ANSI_CHARSET
)
418 if( fo
->fi
->fi_flags
& FI_ENC_ISO8859
)
419 lpEncoding
= iso8859Encoding
;
420 else if( fo
->fi
->fi_flags
& FI_ENC_ISO646
)
421 lpEncoding
= iso646Encoding
;
422 else lpEncoding
= ansiEncoding
;
423 } else lpEncoding
= LFDSeparator
;
425 lpch
= lpLFD
+ lstrlen32A(lpLFD
);
426 ch
= (fo
->fi
->fi_flags
& FI_SCALABLE
) ? '0' : LFDSeparator
[0];
430 /* RealizeFont() will call us repeatedly with increasing uRelax
431 * until XLoadFont() succeeds. */
436 sprintf( lpch
, "%i-%i-%i-%c-%c-*-%s*", h
, point
,
437 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
443 sprintf( lpch
, "%i-*-%i-%c-%c-*-%s*", h
,
444 fo
->fi
->lfd_resolution
, ch
, w
, lpEncoding
);
448 sprintf( lpch
, "%i-*-%i-%c-*-*-%s*",
449 h
, fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
453 sprintf( lpch
, "%i-*-%i-%c-*-*-%s*", fo
->fi
->lfd_height
,
454 fo
->fi
->lfd_resolution
, ch
, lpEncoding
);
458 sprintf( lpch
, "%i-*-*-*-*-*-%s*", fo
->fi
->lfd_height
, lpEncoding
);
461 dprintf_font(stddeb
,"\tLFD: %s\n", lpLFD
);
466 /***********************************************************************
469 * font info - http://www.microsoft.com/kb/articles/q65/1/23.htm
470 * Windows font metrics - http://www.microsoft.com/kb/articles/q32/6/67.htm
472 static BOOL32
XFONT_GetLeading( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
, INT32
* pIL
, INT32
* pEL
)
474 unsigned long height
;
475 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
476 unsigned max
= (unsigned char)pFI
->dfLastChar
;
477 BOOL32 bHaveCapHeight
= (pFI
->dfCharSet
== ANSI_CHARSET
&& 'X' >= min
&& 'X' <= max
);
480 if( XGetFontProperty(x_fs
, XA_CAP_HEIGHT
, &height
) == False
)
484 height
= x_fs
->per_char
['X' - min
].ascent
;
486 if (x_fs
->ascent
>= x_fs
->max_bounds
.ascent
)
487 height
= x_fs
->max_bounds
.ascent
;
490 height
= x_fs
->ascent
;
492 *pEL
= x_fs
->max_bounds
.ascent
- height
;
495 height
= x_fs
->min_bounds
.ascent
;
498 *pIL
= x_fs
->ascent
- height
;
499 return (bHaveCapHeight
&& x_fs
->per_char
);
502 static INT32
XFONT_GetAvgCharWidth( LPIFONTINFO16 pFI
, XFontStruct
* x_fs
)
504 unsigned min
= (unsigned char)pFI
->dfFirstChar
;
505 unsigned max
= (unsigned char)pFI
->dfLastChar
;
510 for( j
= 0, width
= 0, chars
= 0, max
-= min
; j
<= max
; j
++ )
511 if( !CI_NONEXISTCHAR(x_fs
->per_char
+ j
) )
513 width
+= x_fs
->per_char
[j
].width
;
516 return (width
/ chars
);
519 return x_fs
->min_bounds
.width
;
522 /***********************************************************************
523 * XFONT_SetFontMetric
525 * Initializes IFONTINFO16. dfHorizRes and dfVertRes must be already set.
527 static void XFONT_SetFontMetric(fontInfo
* fi
, fontResource
* fr
, XFontStruct
* xfs
)
532 fi
->df
.dfFirstChar
= (BYTE
)(min
= xfs
->min_char_or_byte2
);
533 fi
->df
.dfLastChar
= (BYTE
)(max
= xfs
->max_char_or_byte2
);
535 fi
->df
.dfDefaultChar
= (BYTE
)xfs
->default_char
;
536 fi
->df
.dfBreakChar
= (BYTE
)(( ' ' < min
|| ' ' > max
) ? xfs
->default_char
: ' ');
538 fi
->df
.dfPixHeight
= (INT16
)((fi
->df
.dfAscent
= (INT16
)xfs
->ascent
) + xfs
->descent
);
539 fi
->df
.dfPixWidth
= (xfs
->per_char
) ? 0 : xfs
->min_bounds
.width
;
540 fi
->df
.dfMaxWidth
= (INT16
)abs(xfs
->max_bounds
.width
);
542 if( XFONT_GetLeading( &fi
->df
, xfs
, &il
, &el
) )
543 fi
->df
.dfAvgWidth
= (INT16
)xfs
->per_char
['X' - min
].width
;
545 fi
->df
.dfAvgWidth
= (INT16
)XFONT_GetAvgCharWidth( &fi
->df
, xfs
);
547 fi
->df
.dfInternalLeading
= (INT16
)il
;
548 fi
->df
.dfExternalLeading
= (INT16
)el
;
550 fi
->df
.dfPoints
= (INT16
)(((INT32
)(fi
->df
.dfPixHeight
-
551 fi
->df
.dfInternalLeading
) * 72) / fi
->df
.dfVertRes
);
553 if( xfs
->min_bounds
.width
!= xfs
->max_bounds
.width
)
554 fi
->df
.dfPitchAndFamily
|= TMPF_FIXED_PITCH
; /* au contraire! */
555 if( fi
->fi_flags
& FI_SCALABLE
)
557 fi
->df
.dfType
= DEVICE_FONTTYPE
;
558 fi
->df
.dfPitchAndFamily
|= TMPF_DEVICE
;
560 else if( fi
->fi_flags
& FI_TRUETYPE
)
561 fi
->df
.dfType
= TRUETYPE_FONTTYPE
;
563 fi
->df
.dfType
= RASTER_FONTTYPE
;
565 fi
->df
.dfFace
= fr
->lfFaceName
;
568 /***********************************************************************
569 * XFONT_GetTextMetric
571 static void XFONT_GetTextMetric( fontObject
* pfo
, LPTEXTMETRIC32A pTM
)
573 LPIFONTINFO16 pdf
= &pfo
->fi
->df
;
575 pTM
->tmAscent
= pfo
->fs
->ascent
;
576 pTM
->tmDescent
= pfo
->fs
->descent
;
577 pTM
->tmHeight
= pTM
->tmAscent
+ pTM
->tmDescent
;
579 pTM
->tmAveCharWidth
= pfo
->foAvgCharWidth
;
580 pTM
->tmMaxCharWidth
= abs(pfo
->fs
->max_bounds
.width
);
582 pTM
->tmInternalLeading
= pfo
->foInternalLeading
;
583 pTM
->tmExternalLeading
= pdf
->dfExternalLeading
;
585 pTM
->tmStruckOut
= (pfo
->fo_flags
& FO_SYNTH_STRIKEOUT
)
586 ? 1 : pdf
->dfStrikeOut
;
587 pTM
->tmUnderlined
= (pfo
->fo_flags
& FO_SYNTH_UNDERLINE
)
588 ? 1 : pdf
->dfUnderline
;
591 if( pfo
->fo_flags
& FO_SYNTH_ITALIC
)
593 pTM
->tmOverhang
+= pTM
->tmHeight
/3;
596 pTM
->tmItalic
= pdf
->dfItalic
;
598 pTM
->tmWeight
= pdf
->dfWeight
;
599 if( pfo
->fo_flags
& FO_SYNTH_BOLD
)
602 pTM
->tmWeight
+= 100;
605 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pdf
->dfFirstChar
;
607 pTM
->tmCharSet
= pdf
->dfCharSet
;
608 pTM
->tmPitchAndFamily
= pdf
->dfPitchAndFamily
;
610 pTM
->tmDigitizedAspectX
= pdf
->dfHorizRes
;
611 pTM
->tmDigitizedAspectY
= pdf
->dfVertRes
;
614 /***********************************************************************
615 * XFONT_GetFontMetric
617 * Retrieve font metric info (enumeration).
619 static UINT32
XFONT_GetFontMetric( fontInfo
* pfi
, LPENUMLOGFONTEX16 pLF
,
620 LPNEWTEXTMETRIC16 pTM
)
622 memset( pLF
, 0, sizeof(*pLF
) );
623 memset( pTM
, 0, sizeof(*pTM
) );
625 #define plf ((LPLOGFONT16)pLF)
626 plf
->lfHeight
= pTM
->tmHeight
= pfi
->df
.dfPixHeight
;
627 plf
->lfWidth
= pTM
->tmAveCharWidth
= pfi
->df
.dfAvgWidth
;
628 plf
->lfWeight
= pTM
->tmWeight
= pfi
->df
.dfWeight
;
629 plf
->lfItalic
= pTM
->tmItalic
= pfi
->df
.dfItalic
;
630 plf
->lfUnderline
= pTM
->tmUnderlined
= pfi
->df
.dfUnderline
;
631 plf
->lfStrikeOut
= pTM
->tmStruckOut
= pfi
->df
.dfStrikeOut
;
632 plf
->lfCharSet
= pTM
->tmCharSet
= pfi
->df
.dfCharSet
;
634 /* convert pitch values */
636 pTM
->tmPitchAndFamily
= pfi
->df
.dfPitchAndFamily
;
637 plf
->lfPitchAndFamily
= (pfi
->df
.dfPitchAndFamily
& 0xF1) + 1;
639 lstrcpyn32A( plf
->lfFaceName
, pfi
->df
.dfFace
, LF_FACESIZE
);
642 pTM
->tmAscent
= pfi
->df
.dfAscent
;
643 pTM
->tmDescent
= pTM
->tmHeight
- pTM
->tmAscent
;
644 pTM
->tmInternalLeading
= pfi
->df
.dfInternalLeading
;
645 pTM
->tmMaxCharWidth
= pfi
->df
.dfMaxWidth
;
646 pTM
->tmDigitizedAspectX
= pfi
->df
.dfHorizRes
;
647 pTM
->tmDigitizedAspectY
= pfi
->df
.dfVertRes
;
649 *(INT32
*)&pTM
->tmFirstChar
= *(INT32
*)&pfi
->df
.dfFirstChar
;
651 /* return font type */
653 return pfi
->df
.dfType
;
657 /***********************************************************************
660 * dfPitchAndFamily flags for some common typefaces.
662 static BYTE
XFONT_FixupFlags( LPCSTR lfFaceName
)
664 switch( lfFaceName
[0] )
667 case 'H': if(!lstrcmpi32A(lfFaceName
, "Helvetica") )
671 case 'C': if(!lstrcmpi32A(lfFaceName
, "Courier") )
675 case 'P': if( !lstrcmpi32A(lfFaceName
,"Palatino") )
679 case 'T': if(!lstrncmpi32A(lfFaceName
, "Times", 5) )
683 case 'U': if(!lstrcmpi32A(lfFaceName
, "Utopia") )
687 case 'Z': if(!lstrcmpi32A(lfFaceName
, "Zapf Dingbats") )
688 return FF_DECORATIVE
;
694 /***********************************************************************
697 * Build generic Windows aliases for X font names.
699 * -misc-fixed- -> "Fixed"
700 * -sony-fixed- -> "Sony Fixed", etc...
702 static void XFONT_WindowsNames( char* buffer
)
704 fontResource
* fr
, *pfr
;
709 for( fr
= fontList
; fr
; fr
= fr
->next
)
711 if( fr
->fr_flags
& FR_NAMESET
) continue; /* skip already assigned */
713 lpstr
= LFD_Advance(fr
->resource
, 2);
714 i
= lpstr
- LFD_Advance( lpstr
, 1 );
716 for( pfr
= fontList
; pfr
!= fr
; pfr
= pfr
->next
)
717 if( pfr
->fr_flags
& FR_NAMESET
)
719 lpch
= LFD_Advance(pfr
->resource
, 2);
721 /* check if already have the same face name */
723 if( !lstrncmp32A(lpch
, lpstr
, i
) ) break;
725 if( pfr
!= fr
) /* prepend vendor name */
726 lpstr
= fr
->resource
+ 1;
728 for( i
= 0, up
= 1, lpch
= fr
->lfFaceName
; *lpstr
&& i
< 32;
729 lpch
++, lpstr
++, i
++ )
731 if( *lpstr
== LFDSeparator
[1] || *lpstr
== ' ' )
736 else if( isalpha(*lpstr
) && up
)
738 *lpch
= toupper(*lpstr
);
743 while (*(lpch
- 1) == ' ') *(--lpch
) = '\0';
745 if( (bFamilyStyle
= XFONT_FixupFlags( fr
->lfFaceName
)) )
748 for( fi
= fr
->fi
; fi
; fi
= fi
->next
)
749 fi
->df
.dfPitchAndFamily
|= bFamilyStyle
;
752 #ifdef DEBUG_FONT_INIT
753 dprintf_font(stddeb
,"typeface \'%s\'\n", fr
->lfFaceName
);
755 fr
->fr_flags
|= FR_NAMESET
;
758 if( PROFILE_GetWineIniString( INIFontSection
, INIDefault
, "", buffer
, 128 ) )
760 while( *buffer
&& isspace(*buffer
) ) buffer
++;
761 for( fr
= NULL
, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
763 i
= lstrlen32A( pfr
->resource
);
764 if( !lstrncmpi32A( pfr
->resource
, buffer
, i
) )
768 fr
->next
= pfr
->next
;
769 pfr
->next
= fontList
;
779 /***********************************************************************
782 static fontAlias
* XFONT_CreateAlias( LPCSTR lpTypeFace
, LPCSTR lpAlias
)
784 fontAlias
* pfa
= aliasTable
;
785 int j
= lstrlen32A(lpTypeFace
) + 1;
787 while( pfa
->next
) pfa
= pfa
->next
;
788 pfa
->next
= HeapAlloc( SystemHeap
, 0, sizeof(fontAlias
) +
789 j
+ lstrlen32A(lpAlias
) + 1 );
790 if((pfa
= pfa
->next
))
793 pfa
->faTypeFace
= (LPSTR
)(pfa
+ 1);
794 lstrcpy32A( pfa
->faTypeFace
, lpTypeFace
);
795 pfa
->faAlias
= pfa
->faTypeFace
+ j
;
796 lstrcpy32A( pfa
->faAlias
, lpAlias
);
798 #ifdef DEBUG_FONT_INIT
799 dprintf_font(stddeb
, "\tadded alias '%s' for %s\n", lpAlias
, lpTypeFace
);
806 /***********************************************************************
809 * Read user-defined aliases from wine.conf. Format is as follows
811 * Alias# = [Windows font name],[LFD font name], <substitute original name>
814 * Alias0 = Arial, -adobe-helvetica-
815 * Alias1 = Times New Roman, -bitstream-courier-, 1
818 static void XFONT_LoadAliases( char** buffer
, int buf_size
)
824 *buffer
= HeapReAlloc(SystemHeap
, 0, *buffer
, 256 );
827 wsprintf32A( subsection
, "%s%i", INISubSection
, i
++ );
829 if( PROFILE_GetWineIniString( INIFontSection
, subsection
, "", *buffer
, 128 ) )
831 char* lpchX
, *lpchW
= *buffer
;
833 while( isspace(*lpchW
) ) lpchW
++;
834 lpchX
= PROFILE_GetStringItem( lpchW
);
840 for (fr
= fontList
; fr
; fr
= fr
->next
)
844 j
= lstrlen32A( fr
->resource
);
846 if( !lstrncmpi32A( fr
->resource
, lpchX
, j
) )
848 char* lpch
= PROFILE_GetStringItem( lpchX
);
852 #ifdef DEBUG_FONT_INIT
853 dprintf_font(stddeb
, "\tsubstituted '%s' with %s\n",
854 fr
->lfFaceName
, lpchW
);
856 lstrcpyn32A( fr
->lfFaceName
, lpchW
, LF_FACESIZE
);
857 fr
->fr_flags
|= FR_NAMESET
;
861 /* create new entry in the alias table */
862 XFONT_CreateAlias(fr
->lfFaceName
, lpchW
);
868 else fprintf(stderr
, "XFONT_Init: malformed font alias '%s'\n", *buffer
);
874 /***********************************************************************
875 * XFONT_UserMetricsCache
877 * Returns expanded name for the ~/.wine/.cachedmetrics file.
879 static char* XFONT_UserMetricsCache( char* buffer
, int* buf_size
)
883 pwd
= getpwuid(getuid());
884 if( pwd
&& pwd
->pw_dir
)
886 int i
= lstrlen32A( pwd
->pw_dir
) + lstrlen32A( INIWinePrefix
) + lstrlen32A( INIFontMetrics
) + 2;
887 if( i
> *buf_size
) buffer
= (char*) HeapReAlloc( SystemHeap
, 0, buffer
, *buf_size
= i
);
888 lstrcpy32A( buffer
, pwd
->pw_dir
);
889 strcat( buffer
, INIWinePrefix
);
890 strcat( buffer
, INIFontMetrics
);
891 } else buffer
[0] = '\0';
896 /***********************************************************************
897 * XFONT_ReadCachedMetrics
899 static BOOL32
XFONT_ReadCachedMetrics( int fd
, unsigned x_checksum
, int x_count
)
907 read( fd
, &u
, sizeof(unsigned) );
908 read( fd
, &i
, sizeof(int) );
910 if( u
== x_checksum
&& i
== x_count
)
912 off_t length
, offset
= 3 * sizeof(int);
914 /* read total size */
915 read( fd
, &i
, sizeof(int) );
916 length
= lseek( fd
, 0, SEEK_END
);
918 if( length
== (i
+ offset
) )
920 lseek( fd
, offset
, SEEK_SET
);
921 fontList
= (fontResource
*)HeapAlloc( SystemHeap
, 0, i
);
924 fontResource
* pfr
= fontList
;
925 fontInfo
* pfi
= NULL
;
927 dprintf_font(stddeb
,"Reading cached font metrics:\n");
929 read( fd
, fontList
, i
); /* read all metrics at once */
930 while( offset
< length
)
932 offset
+= sizeof(fontResource
) + sizeof(fontInfo
);
933 pfr
->fi
= pfi
= (fontInfo
*)(pfr
+ 1);
937 if( offset
> length
||
938 (int)(pfi
->next
) != j
++ ) goto fail
;
940 pfi
->df
.dfFace
= pfr
->lfFaceName
;
943 if( j
> pfr
->count
) break;
946 offset
+= sizeof(fontInfo
);
951 pfr
->next
= (fontResource
*)(pfi
+ 1);
956 if( pfr
->next
== NULL
&&
957 *(int*)(pfi
+ 1) == X_FMC_MAGIC
)
960 char* lpch
= (char*)((int*)(pfi
+ 1) + 1);
961 offset
+= sizeof(int);
962 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
964 dprintf_font(stddeb
,"\t%s, %i instances\n", lpch
, pfr
->count
);
965 pfr
->resource
= lpch
;
968 if( ++offset
> length
) goto fail
;
969 if( !*lpch
++ ) break;
979 if( fontList
) HeapFree( SystemHeap
, 0, fontList
);
986 /***********************************************************************
987 * XFONT_WriteCachedMetrics
989 static BOOL32
XFONT_WriteCachedMetrics( int fd
, unsigned x_checksum
, int x_count
, int n_ff
)
998 /* font metrics file:
1002 * +0008 total size to load
1003 * +000C prepackaged font metrics
1006 * +...x + 4 LFD stubs
1009 write( fd
, &x_checksum
, sizeof(unsigned) );
1010 write( fd
, &x_count
, sizeof(int) );
1012 for( j
= i
= 0, pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1014 i
+= lstrlen32A( pfr
->resource
) + 1;
1017 i
+= n_ff
* sizeof(fontResource
) + j
* sizeof(fontInfo
) + sizeof(int);
1018 write( fd
, &i
, sizeof(int) );
1020 dprintf_font(stddeb
,"Writing font cache:\n");
1022 for( pfr
= fontList
; pfr
; pfr
= pfr
->next
)
1026 dprintf_font(stddeb
,"\t%s, %i instances\n", pfr
->resource
, pfr
->count
);
1028 i
= write( fd
, pfr
, sizeof(fontResource
) );
1029 if( i
== sizeof(fontResource
) )
1031 for( k
= 1, pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
1033 memcpy( &fi
, pfi
, sizeof(fi
) );
1035 fi
.df
.dfFace
= NULL
;
1036 fi
.next
= (fontInfo
*)k
; /* loader checks this */
1038 j
= write( fd
, &fi
, sizeof(fi
) );
1041 if( j
== sizeof(fontInfo
) ) continue;
1045 if( i
== sizeof(fontResource
) && j
== sizeof(fontInfo
) )
1047 i
= j
= X_FMC_MAGIC
;
1048 write( fd
, &i
, sizeof(int) );
1049 for( pfr
= fontList
; pfr
&& i
== j
; pfr
= pfr
->next
)
1051 i
= lstrlen32A( pfr
->resource
) + 1;
1052 j
= write( fd
, pfr
->resource
, i
);
1061 /***********************************************************************
1064 * Initialize font resource list and allocate font cache.
1066 BOOL32
X11DRV_FONT_Init( DeviceCaps
* pDevCaps
)
1069 fontResource
* fr
, *pfr
;
1071 unsigned x_checksum
;
1072 int i
, j
, k
, x_count
, fd
= -1, buf_size
= 0;
1073 char* lpstr
, *lpch
, *lpmetrics
, *buffer
;
1076 DefResolution
= PROFILE_GetWineIniInt( INIFontSection
, "Resolution", 0 );
1077 if( !DefResolution
) DefResolution
= pDevCaps
->logPixelsY
;
1079 i
= abs(DefResolution
- 72);
1080 j
= abs(DefResolution
- 75);
1081 k
= abs(DefResolution
- 100);
1083 if( i
< j
) DefResolution
= ( i
< k
) ? 72 : 100;
1084 else DefResolution
= ( j
< k
) ? 75 : 100;
1086 x_pattern
= XListFonts(display
, "*", MAX_FONT_FAMILIES
* 16, &x_count
);
1088 dprintf_font(stddeb
,"Font Mapper: initializing %i fonts [LPY=%i, DR=%i]\n",
1089 x_count
, pDevCaps
->logPixelsY
, DefResolution
);
1090 for( i
= x_checksum
= 0; i
< x_count
; i
++ )
1093 printf("%i\t: %s\n", i
, x_pattern
[i
] );
1096 j
= lstrlen32A( x_pattern
[i
] );
1097 if( j
) x_checksum
^= __genericCheckSum( (UINT16
*)(x_pattern
[i
]), j
);
1099 x_checksum
|= X_PFONT_MAGIC
;
1102 buffer
= HeapAlloc( SystemHeap
, 0, buf_size
);
1105 /* deal with systemwide font metrics cache */
1107 if( PROFILE_GetWineIniString( INIFontSection
, "FontMetrics", "", buffer
, 128 ) )
1108 fd
= open( buffer
, O_RDONLY
);
1110 if( XFONT_ReadCachedMetrics(fd
, x_checksum
, x_count
) == FALSE
)
1113 buffer
= XFONT_UserMetricsCache( buffer
, &buf_size
);
1116 fd
= open( buffer
, O_RDONLY
);
1117 if( XFONT_ReadCachedMetrics(fd
, x_checksum
, x_count
) == FALSE
)
1118 lpmetrics
= HEAP_strdupA( SystemHeap
, 0, buffer
); /* update later on */
1123 if( fontList
== NULL
) /* build metrics from scratch */
1128 for( i
= n_ff
= 0; i
< x_count
; i
++ )
1130 typeface
= lpch
= x_pattern
[i
];
1132 lpch
= LFD_Advance(typeface
, 3); /* extra '-' in the beginning */
1133 if( !*lpch
) continue;
1136 j
= lpch
- typeface
; /* resource name length */
1138 /* find a family to insert into */
1140 for( pfr
= NULL
, fr
= fontList
; fr
; fr
= fr
->next
)
1142 if( !lstrncmpi32A(fr
->resource
, typeface
, j
) &&
1143 lstrlen32A(fr
->resource
) == j
) break;
1147 if( !fi
) fi
= (fontInfo
*) HeapAlloc(SystemHeap
, 0, sizeof(fontInfo
));
1149 if( !fr
) /* add new family */
1151 if( n_ff
>= MAX_FONT_FAMILIES
) break;
1152 if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1155 fr
= (fontResource
*) HeapAlloc(SystemHeap
, 0, sizeof(fontResource
));
1156 memset(fr
, 0, sizeof(fontResource
));
1157 fr
->resource
= (char*) HeapAlloc(SystemHeap
, 0, j
+ 1 );
1158 lstrcpyn32A( fr
->resource
, typeface
, j
+ 1 );
1160 #ifdef DEBUG_FONT_INIT
1161 dprintf_font(stddeb
," family: %s\n", fr
->resource
);
1164 if( pfr
) pfr
->next
= fr
;
1167 else if( !LFD_InitFontInfo( fi
, lpstr
) ) continue;
1169 /* check if we already have something better than "fi" */
1171 for( pfi
= fr
->fi
, j
= 0; pfi
&& j
<= 0; pfi
= pfi
->next
)
1172 if( (j
= XFONT_IsSubset( pfi
, fi
)) < 0 )
1173 pfi
->fi_flags
|= FI_SUBSET
; /* superseded by "fi" */
1174 if( j
> 0 ) continue;
1176 /* add new font instance "fi" to the "fr" font resource */
1178 if( fi
->fi_flags
& FI_SCALABLE
)
1180 /* set scalable font height to 24 to get an origin for extrapolation */
1182 j
= lstrlen32A(typeface
); j
+= 0x10;
1184 buffer
= (char*)HeapReAlloc( SystemHeap
, 0, buffer
, buf_size
= j
);
1186 lpch
= LFD_Advance(typeface
, 7);
1187 memcpy( buffer
, typeface
, (j
= lpch
- typeface
) );
1188 lpch
= LFD_Advance(lpch
, 4);
1189 sprintf( buffer
+ j
, "%d-%d-%d-*-%c-*-", fi
->lfd_height
,
1190 fi
->lfd_decipoints
, fi
->lfd_resolution
,
1191 (*lpch
== '-')?'*':*lpch
);
1192 lpch
= LFD_Advance(lpch
, 2);
1193 strcat( lpstr
= buffer
, lpch
);
1195 else lpstr
= typeface
;
1197 if( (x_fs
= XLoadQueryFont(display
, lpstr
)) )
1199 fi
->df
.dfHorizRes
= pDevCaps
->logPixelsX
;
1200 fi
->df
.dfVertRes
= pDevCaps
->logPixelsY
;
1202 XFONT_SetFontMetric( fi
, fr
, x_fs
);
1203 XFreeFont( display
, x_fs
);
1205 #ifdef DEBUG_FONT_INIT
1206 dprintf_font(stddeb
,"\t[% 2ipt] '%s'\n", fi
->df
.dfPoints
, typeface
);
1208 XFONT_CheckFIList( fr
, fi
, REMOVE_SUBSETS
);
1209 fi
= NULL
; /* preventing reuse */
1213 fprintf(stderr
, "FONT_Init: failed to load %s\n", lpstr
);
1215 XFONT_CheckFIList( fr
, fi
, UNMARK_SUBSETS
);
1219 if( lpmetrics
) /* update cached metrics */
1221 fd
= open( lpmetrics
, O_CREAT
| O_TRUNC
| O_RDWR
, 0644 ); /* -rw-r--r-- */
1222 if( XFONT_WriteCachedMetrics( fd
, x_checksum
, x_count
, n_ff
) == FALSE
)
1223 if( fd
) remove( lpmetrics
); /* couldn't write entire file */
1224 HeapFree( SystemHeap
, 0, lpmetrics
);
1228 if( fi
) HeapFree(SystemHeap
, 0, fi
);
1229 XFreeFontNames(x_pattern
);
1231 /* check if we're dealing with X11 R6 server */
1233 lstrcpy32A(buffer
, "-*-*-*-*-normal-*-[12 0 0 12]-*-72-*-*-*-iso8859-1");
1234 if( (x_fs
= XLoadQueryFont(display
, buffer
)) )
1236 XTextCaps
|= TC_SF_X_YINDEP
;
1237 XFreeFont(display
, x_fs
);
1240 XFONT_WindowsNames( buffer
);
1241 XFONT_LoadAliases( &buffer
, buf_size
);
1242 HeapFree(SystemHeap
, 0, buffer
);
1245 /* fontList initialization is over, allocate X font cache */
1247 fontCache
= (fontObject
*) HeapAlloc(SystemHeap
, 0, fontCacheSize
* sizeof(fontObject
));
1248 XFONT_GrowFreeList(0, fontCacheSize
- 1);
1250 #ifdef DEBUG_FONT_INIT
1251 dprintf_font(stddeb
,"done!\n");
1254 /* update text caps parameter */
1256 pDevCaps
->textCaps
= XTextCaps
;
1261 /***********************************************************************
1264 * Compare two fonts (only parameters set by the XFONT_InitFontInfo()).
1266 static INT32
XFONT_IsSubset(fontInfo
* match
, fontInfo
* fi
)
1270 /* 0 - keep both, 1 - keep match, -1 - keep fi */
1272 m
= (BYTE
*)&fi
->df
.dfPixWidth
- (BYTE
*)&fi
->df
.dfItalic
;
1273 if( memcmp(&match
->df
.dfItalic
, &fi
->df
.dfItalic
, m
)) return 0;
1275 if( (!((fi
->fi_flags
& FI_SCALABLE
) + (match
->fi_flags
& FI_SCALABLE
))
1276 && fi
->lfd_height
!= match
->lfd_height
) ||
1277 (!((fi
->fi_flags
& FI_POLYWEIGHT
) + (match
->fi_flags
& FI_POLYWEIGHT
))
1278 && fi
->df
.dfWeight
!= match
->df
.dfWeight
) ) return 0;
1280 m
= (int)(match
->fi_flags
& (FI_POLYWEIGHT
| FI_SCALABLE
)) -
1281 (int)(fi
->fi_flags
& (FI_SCALABLE
| FI_POLYWEIGHT
));
1283 if( m
== (FI_POLYWEIGHT
- FI_SCALABLE
) ||
1284 m
== (FI_SCALABLE
- FI_POLYWEIGHT
) ) return 0; /* keep both */
1285 else if( m
>= 0 ) return 1; /* 'match' is better */
1287 return -1; /* 'fi' is better */
1290 /***********************************************************************
1293 * Compute the matching score between the logical font and the device font.
1295 * contributions from highest to lowest:
1299 * family flags (only when the facename is not present)
1301 * weight, italics, underlines, strikeouts
1303 * NOTE: you can experiment with different penalty weights to see what happens.
1304 * http://premium.microsoft.com/msdn/library/techart/f30/f34/f40/d4d/sa8bf.htm
1306 static UINT32
XFONT_Match( fontMatch
* pfm
)
1308 fontInfo
* pfi
= pfm
->pfi
; /* device font to match */
1309 LPLOGFONT16 plf
= pfm
->plf
; /* wanted logical font */
1311 BOOL32 bR6
= pfm
->flags
& FO_MATCH_XYINDEP
; /* from TextCaps */
1312 BOOL32 bScale
= pfi
->fi_flags
& FI_SCALABLE
;
1315 dprintf_font( stddeb
,"\t[ %-2ipt h=%-3i w=%-3i %s%s]", pfi
->df
.dfPoints
,
1316 pfi
->df
.dfPixHeight
, pfi
->df
.dfAvgWidth
,
1317 (pfi
->df
.dfWeight
> 400) ? "Bold " : "Normal ",
1318 (pfi
->df
.dfItalic
) ? "Italic" : "" );
1322 if( plf
->lfCharSet
== DEFAULT_CHARSET
)
1324 if( (pfi
->df
.dfCharSet
!= ANSI_CHARSET
) && (pfi
->df
.dfCharSet
!=DEFAULT_CHARSET
) ) penalty
+= 0x200;
1326 else if (plf
->lfCharSet
!= pfi
->df
.dfCharSet
) penalty
+= 0x200;
1328 /* TMPF_FIXED_PITCH means exactly the opposite */
1330 if( plf
->lfPitchAndFamily
& FIXED_PITCH
)
1332 if( pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) penalty
+= 0x100;
1334 else if( !(pfi
->df
.dfPitchAndFamily
& TMPF_FIXED_PITCH
) ) penalty
+= 0x2;
1336 if( plf
->lfHeight
> 0 )
1337 d
= (h
= pfi
->df
.dfPixHeight
) - plf
->lfHeight
;
1338 else if( plf
->lfHeight
< -1 )
1339 d
= (h
= pfi
->df
.dfPoints
) + plf
->lfHeight
;
1342 if( d
&& plf
->lfHeight
)
1344 UINT16 height
= ( plf
->lfHeight
> 0 ) ? plf
->lfHeight
1345 : ((-plf
->lfHeight
* pfi
->df
.dfPixHeight
) / h
);
1346 if( bScale
) pfm
->height
= height
;
1347 else if( (plf
->lfQuality
!= PROOF_QUALITY
) && bR6
)
1349 if( d
> 0 ) /* do not shrink raster fonts */
1351 pfm
->height
= pfi
->df
.dfPixHeight
;
1352 penalty
+= (pfi
->df
.dfPixHeight
- height
) * 0x4;
1354 else /* expand only in integer multiples */
1356 pfm
->height
= height
- height
%pfi
->df
.dfPixHeight
;
1357 penalty
+= (height
- pfm
->height
) * pfm
->height
/ height
;
1360 else /* can't be scaled at all */
1362 if( plf
->lfQuality
!= PROOF_QUALITY
) pfm
->flags
|= FO_SYNTH_HEIGHT
;
1363 pfm
->height
= pfi
->df
.dfPixHeight
;
1364 penalty
+= (d
> 0)? d
* 0x8 : -d
* 0x10;
1366 } else pfm
->height
= pfi
->df
.dfPixHeight
;
1368 if((pfm
->flags
& FO_MATCH_PAF
) &&
1369 (plf
->lfPitchAndFamily
& FF_FAMILY
) != (pfi
->df
.dfPitchAndFamily
& FF_FAMILY
) )
1374 if( bR6
&& bScale
) h
= 0;
1377 /* FIXME: not complete */
1379 pfm
->flags
|= FO_SYNTH_WIDTH
;
1380 h
= abs(plf
->lfWidth
- (pfm
->height
* pfi
->df
.dfAvgWidth
)/pfi
->df
.dfPixHeight
);
1382 penalty
+= h
* ( d
) ? 0x2 : 0x1 ;
1384 else if( !(pfi
->fi_flags
& FI_NORMAL
) ) penalty
++;
1386 if( pfi
->lfd_resolution
!= DefResolution
) penalty
++;
1388 if( plf
->lfWeight
!= FW_DONTCARE
)
1390 penalty
+= abs(plf
->lfWeight
- pfi
->df
.dfWeight
) / 40;
1391 if( plf
->lfWeight
> pfi
->df
.dfWeight
) pfm
->flags
|= FO_SYNTH_BOLD
;
1392 } else if( pfi
->df
.dfWeight
>= FW_BOLD
) penalty
++; /* choose normal by default */
1394 if( plf
->lfItalic
!= pfi
->df
.dfItalic
)
1397 pfm
->flags
|= FO_SYNTH_ITALIC
;
1400 if( plf
->lfUnderline
) pfm
->flags
|= FO_SYNTH_UNDERLINE
;
1401 if( plf
->lfStrikeOut
) pfm
->flags
|= FO_SYNTH_STRIKEOUT
;
1403 dprintf_font(stddeb
,"-> %i\n", penalty
);
1408 /***********************************************************************
1411 * Scan a particular font resource for the best match.
1413 static UINT32
XFONT_MatchFIList( fontMatch
* pfm
)
1415 BOOL32 skipRaster
= (pfm
->flags
& FO_MATCH_NORASTER
);
1416 UINT32 current_score
, score
= (UINT32
)(-1);
1417 fontMatch fm
= *pfm
;
1419 for( fm
.pfi
= pfm
->pfr
->fi
; fm
.pfi
&& score
; fm
.pfi
= fm
.pfi
->next
)
1421 if( skipRaster
&& !(fm
.pfi
->fi_flags
& FI_SCALABLE
) )
1424 current_score
= XFONT_Match( &fm
);
1425 if( score
> current_score
)
1427 memcpy( pfm
, &fm
, sizeof(fontMatch
) );
1428 score
= current_score
;
1434 /***********************************************************************
1435 * XFONT_CheckAliasTable
1437 static LPSTR
XFONT_CheckAliasTable( LPSTR lpAlias
)
1441 for( fa
= aliasTable
; fa
; fa
= fa
->next
)
1442 if( !lstrcmpi32A( fa
->faAlias
, lpAlias
) ) return fa
->faTypeFace
;
1446 /***********************************************************************
1449 * REMOVE_SUBSETS - attach new fi and purge subsets
1450 * UNMARK_SUBSETS - remove subset flags from all fi entries
1452 static void XFONT_CheckFIList( fontResource
* fr
, fontInfo
* fi
, int action
)
1455 fontInfo
* pfi
, *prev
;
1457 for( prev
= NULL
, pfi
= fr
->fi
; pfi
; )
1459 if( action
== REMOVE_SUBSETS
)
1461 if( pfi
->fi_flags
& FI_SUBSET
)
1463 fontInfo
* subset
= pfi
;
1467 if( prev
) prev
->next
= pfi
= pfi
->next
;
1468 else fr
->fi
= pfi
= pfi
->next
;
1469 HeapFree( SystemHeap
, 0, subset
);
1473 else pfi
->fi_flags
&= ~FI_SUBSET
;
1479 if( action
== REMOVE_SUBSETS
) /* also add the superset */
1481 if( fi
->fi_flags
& FI_SCALABLE
)
1486 else if( prev
) prev
->next
= fi
; else fr
->fi
= fi
;
1490 #ifdef DEBUG_FONT_INIT
1491 if( i
) dprintf_font(stddeb
,"\t purged %i subsets [%i]\n", i
, fr
->count
);
1495 /***********************************************************************
1498 static fontResource
* XFONT_FindFIList( fontResource
* pfr
, const char* pTypeFace
)
1502 if( !lstrcmpi32A( pfr
->lfFaceName
, pTypeFace
) ) break;
1508 /***********************************************************************
1509 * XFONT_MatchDeviceFont
1511 * Scan font resource tree.
1513 static BOOL32
XFONT_MatchDeviceFont( fontResource
* start
, fontMatch
* pfm
)
1515 fontMatch fm
= *pfm
;
1518 if( fm
.plf
->lfFaceName
[0] )
1520 LPSTR str
= XFONT_CheckAliasTable( fm
.plf
->lfFaceName
);
1521 fm
.pfr
= XFONT_FindFIList( start
, str
? str
: fm
.plf
->lfFaceName
);
1524 if( fm
.pfr
) /* match family */
1526 dprintf_font(stddeb
, "%s\n", fm
.pfr
->lfFaceName
);
1528 XFONT_MatchFIList( &fm
);
1532 if( !pfm
->pfi
) /* match all available fonts */
1534 UINT32 current_score
, score
= (UINT32
)(-1);
1536 fm
.flags
|= FO_MATCH_PAF
;
1537 for( start
= fontList
; start
&& score
; start
= start
->next
)
1540 dprintf_font(stddeb
, "%s\n", fm
.pfr
->lfFaceName
);
1542 current_score
= XFONT_MatchFIList( &fm
);
1543 if( current_score
< score
)
1545 score
= current_score
;
1554 /***********************************************************************
1557 static void XFONT_GrowFreeList(int start
, int end
)
1559 /* add all entries from 'start' up to and including 'end' */
1561 memset( fontCache
+ start
, 0, (end
- start
+ 1) * sizeof(fontObject
) );
1563 fontCache
[end
].lru
= fontLF
;
1564 fontCache
[end
].count
= -1;
1566 while( start
< end
)
1568 fontCache
[start
].count
= -1;
1569 fontCache
[start
].lru
= start
+ 1;
1574 static fontObject
* XFONT_LookupCachedFont( LPLOGFONT16 plf
, UINT16
* checksum
)
1576 UINT16 cs
= __lfCheckSum( plf
);
1577 int i
= fontMRU
, prev
= -1;
1582 if( fontCache
[i
].lfchecksum
== cs
&&
1583 !(fontCache
[i
].fo_flags
& FO_REMOVED
) )
1585 /* FIXME: something more intelligent here */
1587 if( !memcmp( plf
, &fontCache
[i
].lf
,
1588 sizeof(LOGFONT16
) - LF_FACESIZE
) &&
1589 !lstrncmpi32A( plf
->lfFaceName
, fontCache
[i
].lf
.lfFaceName
,
1592 /* remove temporarily from the lru list */
1595 fontCache
[prev
].lru
= fontCache
[i
].lru
;
1597 fontMRU
= (INT16
)fontCache
[i
].lru
;
1598 return (fontCache
+ i
);
1602 i
= (INT16
)fontCache
[i
].lru
;
1607 static fontObject
* XFONT_GetCacheEntry()
1613 int prev_i
, prev_j
, j
;
1615 dprintf_font(stddeb
,"font cache is full\n");
1617 /* lookup the least recently used font */
1619 for( prev_i
= prev_j
= j
= -1, i
= fontMRU
; i
>= 0; i
= (INT16
)fontCache
[i
].lru
)
1621 if( fontCache
[i
].count
<= 0 &&
1622 !(fontCache
[i
].fo_flags
& FO_SYSTEM
) )
1630 if( j
>= 0 ) /* unload font */
1632 /* detach from the lru list */
1634 dprintf_font(stddeb
,"\tfreeing entry %i\n", j
);
1637 fontCache
[prev_j
].lru
= fontCache
[j
].lru
;
1638 else fontMRU
= (INT16
)fontCache
[j
].lru
;
1640 /* FIXME: lpXForm, lpPixmap */
1641 XFreeFont( display
, fontCache
[j
].fs
);
1643 memset( fontCache
+ j
, 0, sizeof(fontObject
) );
1644 return (fontCache
+ j
);
1646 else /* expand cache */
1648 fontObject
* newCache
;
1650 prev_i
= fontCacheSize
+ FONTCACHE
;
1652 dprintf_font(stddeb
,"\tgrowing font cache from %i to %i\n", fontCacheSize
, prev_i
);
1654 if( (newCache
= (fontObject
*)HeapReAlloc(SystemHeap
, 0,
1655 fontCache
, prev_i
)) )
1658 fontCacheSize
= prev_i
;
1659 fontCache
= newCache
;
1660 XFONT_GrowFreeList( i
, fontCacheSize
- 1);
1666 /* detach from the free list */
1669 fontLF
= (INT16
)fontCache
[i
].lru
;
1670 fontCache
[i
].count
= 0;
1671 return (fontCache
+ i
);
1674 static int XFONT_ReleaseCacheEntry(fontObject
* pfo
)
1676 UINT32 u
= (UINT32
)(pfo
- fontCache
);
1678 if( u
< fontCacheSize
) return (--fontCache
[u
].count
);
1682 /***********************************************************************
1683 * X Device Font Objects
1685 static X_PHYSFONT
XFONT_RealizeFont( LPLOGFONT16 plf
)
1688 fontObject
* pfo
= XFONT_LookupCachedFont( plf
, &checksum
);
1692 fontMatch fm
= { NULL
, NULL
, 0, 0, plf
};
1695 if( XTextCaps
& TC_SF_X_YINDEP
) fm
.flags
= FO_MATCH_XYINDEP
;
1697 /* allocate new font cache entry */
1699 if( (pfo
= XFONT_GetCacheEntry()) )
1701 LPSTR lpLFD
= HeapAlloc( GetProcessHeap(), 0, MAX_LFD_LENGTH
);
1703 if( lpLFD
) /* initialize entry and load font */
1705 UINT32 uRelaxLevel
= 0;
1707 dprintf_font(stddeb
,"XRealizeFont: (%u) '%s' h=%i weight=%i %s\n",
1708 plf
->lfCharSet
, plf
->lfFaceName
, plf
->lfHeight
,
1709 plf
->lfWeight
, (plf
->lfItalic
) ? "Italic" : "" );
1711 XFONT_MatchDeviceFont( fontList
, &fm
);
1715 pfo
->fo_flags
= fm
.flags
& ~FO_MATCH_MASK
;
1717 memcpy( &pfo
->lf
, plf
, sizeof(LOGFONT16
) );
1718 pfo
->lfchecksum
= checksum
;
1722 LFD_ComposeLFD( pfo
, fm
.height
, lpLFD
, uRelaxLevel
++ );
1723 if( (pfo
->fs
= XLoadQueryFont( display
, lpLFD
)) ) break;
1724 } while( uRelaxLevel
);
1726 if( XFONT_GetLeading( &pfo
->fi
->df
, pfo
->fs
, &i
, NULL
) )
1727 pfo
->foAvgCharWidth
= (INT16
)pfo
->fs
->per_char
['X' - pfo
->fs
->min_char_or_byte2
].width
;
1729 pfo
->foAvgCharWidth
= (INT16
)XFONT_GetAvgCharWidth( &pfo
->fi
->df
, pfo
->fs
);
1730 pfo
->foInternalLeading
= (INT16
)i
;
1732 /* FIXME: If we've got a soft font or
1733 * there are FO_SYNTH_... flags for the
1734 * non PROOF_QUALITY request, the engine
1735 * should rasterize characters into mono
1736 * pixmaps and store them in the pfo->lpPixmap
1737 * array (pfo->fs should be updated as well).
1738 * X11DRV_ExtTextOut() must be heavily modified
1739 * to support pixmap blitting and FO_SYNTH_...
1743 pfo
->lpXForm
= NULL
;
1744 pfo
->lpPixmap
= NULL
;
1746 HeapFree( GetProcessHeap(), 0, lpLFD
);
1748 else /* attach back to the free list */
1752 fontLF
= (pfo
- fontCache
);
1757 if( !pfo
) /* couldn't get a new entry, get one of the cached fonts */
1759 UINT32 current_score
, score
= (UINT32
)(-1);
1761 i
= index
= fontMRU
;
1762 fm
.flags
|= FO_MATCH_PAF
;
1765 pfo
= fontCache
+ i
;
1766 fm
.pfr
= pfo
->fr
; fm
.pfi
= pfo
->fi
;
1768 current_score
= XFONT_Match( &fm
);
1769 if( current_score
< score
) index
= i
;
1773 pfo
= fontCache
+ index
;
1775 return (X_PHYSFONT
)(X_PFONT_MAGIC
| index
);
1779 /* attach at the head of the lru list */
1783 fontMRU
= (pfo
- fontCache
);
1785 dprintf_font(stddeb
,"physfont %i\n", fontMRU
);
1787 return (X_PHYSFONT
)(X_PFONT_MAGIC
| fontMRU
);
1790 /***********************************************************************
1791 * XFONT_GetFontObject
1793 fontObject
* XFONT_GetFontObject( X_PHYSFONT pFont
)
1795 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
);
1799 /***********************************************************************
1800 * XFONT_GetFontStruct
1802 XFontStruct
* XFONT_GetFontStruct( X_PHYSFONT pFont
)
1804 if( CHECK_PFONT(pFont
) ) return __PFONT(pFont
)->fs
;
1808 /***********************************************************************
1811 LPIFONTINFO16
XFONT_GetFontInfo( X_PHYSFONT pFont
)
1813 if( CHECK_PFONT(pFont
) ) return &(__PFONT(pFont
)->fi
->df
);
1819 /* X11DRV Interface ****************************************************
1821 * Exposed via the dc->funcs dispatch table. *
1823 ***********************************************************************/
1824 /***********************************************************************
1825 * X11DRV_FONT_SelectObject
1827 HFONT32
X11DRV_FONT_SelectObject( DC
* dc
, HFONT32 hfont
, FONTOBJ
* font
)
1829 HFONT32 hPrevFont
= 0;
1831 if( CHECK_PFONT(dc
->u
.x
.font
) )
1832 XFONT_ReleaseCacheEntry( __PFONT(dc
->u
.x
.font
) );
1834 dc
->u
.x
.font
= XFONT_RealizeFont( &font
->logfont
);
1835 hPrevFont
= dc
->w
.hFont
;
1836 dc
->w
.hFont
= hfont
;
1842 /***********************************************************************
1844 * X11DRV_EnumDeviceFonts
1846 BOOL32
X11DRV_EnumDeviceFonts( DC
* dc
, LPLOGFONT16 plf
,
1847 DEVICEFONTENUMPROC proc
, LPARAM lp
)
1851 fontResource
* pfr
= fontList
;
1854 if( plf
->lfFaceName
[0] )
1856 pfr
= XFONT_FindFIList( pfr
, plf
->lfFaceName
);
1860 for( pfi
= pfr
->fi
; pfi
; pfi
= pfi
->next
)
1861 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
1862 XFONT_GetFontMetric( pfi
, &lf
, &tm
), lp
)) )
1868 for( ; pfr
; pfr
= pfr
->next
)
1869 if( (b
= (*proc
)( (LPENUMLOGFONT16
)&lf
, &tm
,
1870 XFONT_GetFontMetric( pfr
->fi
, &lf
, &tm
), lp
)) )
1878 /***********************************************************************
1879 * X11DRV_GetTextExtentPoint
1881 BOOL32
X11DRV_GetTextExtentPoint( DC
*dc
, LPCSTR str
, INT32 count
,
1884 XFontStruct
* pfs
= XFONT_GetFontStruct( dc
->u
.x
.font
);
1887 int dir
, ascent
, descent
;
1890 XTextExtents( pfs
, str
, count
, &dir
, &ascent
, &descent
, &info
);
1891 size
->cx
= abs((info
.width
+ dc
->w
.breakRem
+ count
* dc
->w
.charExtra
)
1892 * dc
->wndExtX
/ dc
->vportExtX
);
1893 size
->cy
= abs((pfs
->ascent
+ pfs
->descent
) * dc
->wndExtY
/ dc
->vportExtY
);
1900 /***********************************************************************
1901 * X11DRV_GetTextMetrics
1903 BOOL32
X11DRV_GetTextMetrics(DC
*dc
, TEXTMETRIC32A
*metrics
)
1905 if( CHECK_PFONT(dc
->u
.x
.font
) )
1907 fontObject
* pfo
= __PFONT(dc
->u
.x
.font
);
1908 XFONT_GetTextMetric( pfo
, metrics
);
1915 /***********************************************************************
1916 * X11DRV_GetCharWidth
1918 BOOL32
X11DRV_GetCharWidth( DC
*dc
, UINT32 firstChar
, UINT32 lastChar
,
1921 XFontStruct
* xfs
= XFONT_GetFontStruct( dc
->u
.x
.font
);
1927 if (xfs
->per_char
== NULL
)
1928 for (i
= firstChar
; i
<= lastChar
; i
++)
1929 *buffer
++ = xfs
->min_bounds
.width
;
1932 XCharStruct
*cs
, *def
;
1933 static XCharStruct __null_char
= { 0, 0, 0, 0, 0, 0 };
1935 CI_GET_CHAR_INFO(xfs
, xfs
->default_char
, &__null_char
, def
);
1937 for (i
= firstChar
; i
<= lastChar
; i
++)
1939 if (i
>= xfs
->min_char_or_byte2
&& i
<= xfs
->max_char_or_byte2
)
1941 cs
= &xfs
->per_char
[(i
- xfs
->min_char_or_byte2
)];
1942 if (CI_NONEXISTCHAR(cs
)) cs
= def
;
1944 *buffer
++ = MAX(cs
->width
, 0 );
1952 /***********************************************************************
1954 * Font Resource API *
1956 ***********************************************************************/
1957 /***********************************************************************
1958 * AddFontResource16 (GDI.119)
1960 * Can be either .FON, or .FNT, or .TTF, or .FOT font file.
1962 * FIXME: Load header and find the best-matching font in the fontList;
1963 * fixup dfPoints if all metrics are identical, otherwise create
1964 * new fontAlias. When soft font support is ready this will
1965 * simply create a new fontResource ('filename' will go into
1966 * the pfr->resource field) with FR_SOFTFONT/FR_SOFTRESOURCE
1969 INT16
AddFontResource16( LPCSTR filename
)
1971 return AddFontResource32A( filename
);
1975 /***********************************************************************
1976 * AddFontResource32A (GDI32.2)
1978 INT32
AddFontResource32A( LPCSTR str
)
1980 if (HIWORD(str
)) /* font file */
1981 fprintf( stdnimp
, "STUB: AddFontResource('%s')\n", str
);
1982 else /* font resource handle */
1983 fprintf( stdnimp
, "STUB: AddFontResource(%04x)\n", LOWORD(str
) );
1988 /***********************************************************************
1989 * AddFontResource32W (GDI32.4)
1991 INT32
AddFontResource32W( LPCWSTR str
)
1993 fprintf( stdnimp
, "STUB: AddFontResource32W(%p)\n", str
);
1997 /***********************************************************************
1998 * RemoveFontResource16 (GDI.136)
2000 BOOL16
RemoveFontResource16( SEGPTR str
)
2003 fprintf( stdnimp
, "STUB: RemoveFontResource('%s')\n",
2004 (char *)PTR_SEG_TO_LIN( str
) );
2006 fprintf( stdnimp
, "STUB: RemoveFontResource(%04x)\n", LOWORD(str
) );
2011 /***********************************************************************
2012 * RemoveFontResource32A (GDI32.284)
2014 BOOL32
RemoveFontResource32A( LPCSTR str
)
2017 fprintf( stdnimp
, "STUB: RemoveFontResource('%s')\n", str
);
2019 fprintf( stdnimp
, "STUB: RemoveFontResource(%04x)\n", LOWORD(str
) );
2024 /***********************************************************************
2025 * RemoveFontResource32W (GDI32.286)
2027 BOOL32
RemoveFontResource32W( LPCWSTR str
)
2029 fprintf( stdnimp
, "STUB: RemoveFontResource32W(%p)\n", str
);