4 * Copyright 1993 Alexandre Julliard
6 * Enhacements by Juergen Marquardt 1996
8 * Implementation of a second font cache which
9 * will be updated dynamically
15 #include <X11/Xatom.h>
24 #define FONTCACHE 32 /* dynamic font cache size */
26 static LPLOGFONT lpLogFontList
[MAX_FONTS
] = { NULL
};
29 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
30 (((cs)->rbearing|(cs)->lbearing| \
31 (cs)->ascent|(cs)->descent) == 0))
34 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
35 * character. If the character is in the column and exists, then return the
36 * appropriate metrics (note that fonts with common per-character metrics will
37 * return min_bounds). If none of these hold true, try again with the default
40 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
43 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
44 if (fs->per_char == NULL) { \
45 cs = &fs->min_bounds; \
47 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
48 if (CI_NONEXISTCHAR(cs)) cs = def; \
53 #define CI_GET_DEFAULT_INFO(fs,cs) \
54 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
56 struct FontStructure
{
63 /***********************************************************************
66 BOOL
FONT_Init( void )
72 if (PROFILE_GetWineIniString( "fonts", NULL
, "*", temp
, sizeof(temp
) ) > 2 )
74 for( ptr
= temp
, i
= 1; strlen(ptr
) != 0; ptr
+= strlen(ptr
) + 1 )
75 if( strcmp( ptr
, "default" ) )
76 FontNames
[i
++].window
= xstrdup( ptr
);
79 for( i
= 1; i
< FontSize
; i
++ )
81 PROFILE_GetWineIniString( "fonts", FontNames
[i
].window
, "*",
83 FontNames
[i
].x11
= xstrdup( temp
);
85 PROFILE_GetWineIniString( "fonts", "default", "*", temp
, sizeof(temp
) );
86 FontNames
[0].x11
= xstrdup( temp
);
89 FontNames
[0].window
= NULL
; FontNames
[0].x11
= "*-helvetica";
90 FontNames
[1].window
= "ms sans serif"; FontNames
[1].x11
= "*-helvetica";
91 FontNames
[2].window
= "ms serif"; FontNames
[2].x11
= "*-times";
92 FontNames
[3].window
= "fixedsys"; FontNames
[3].x11
= "*-fixed";
93 FontNames
[4].window
= "arial"; FontNames
[4].x11
= "*-helvetica";
94 FontNames
[5].window
= "helv"; FontNames
[5].x11
= "*-helvetica";
95 FontNames
[6].window
= "roman"; FontNames
[6].x11
= "*-times";
102 /***********************************************************************
105 * Translate a Windows face name to its X11 equivalent.
106 * This will probably have to be customizable.
108 static const char *FONT_TranslateName( char *winFaceName
)
112 for (i
= 1; i
< FontSize
; i
++)
113 if( !strcmp( winFaceName
, FontNames
[i
].window
) ) {
114 dprintf_font(stddeb
, "---- Mapped %s to %s\n", winFaceName
, FontNames
[i
].x11
);
115 return FontNames
[i
].x11
;
117 return FontNames
[0].x11
;
121 /***********************************************************************
124 * Find a X font matching the logical font.
126 static XFontStruct
* FONT_MatchFont( LOGFONT
* font
, DC
* dc
)
129 const char *family
, *weight
, *charset
;
131 char slant
, oldspacing
, spacing
;
132 int width
, height
, oldheight
, count
;
133 XFontStruct
* fontStruct
;
136 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
137 font
->lfHeight
, font
->lfWidth
, font
->lfWeight
, font
->lfItalic
, font
->lfFaceName
);
138 weight
= (font
->lfWeight
> 550) ? "bold" : "medium";
139 slant
= font
->lfItalic
? 'i' : 'r';
140 if (font
->lfHeight
== -1)
143 height
= font
->lfHeight
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
;
144 if (height
== 0) height
= 120; /* Default height = 12 */
147 /* If height is negative, it means the height of the characters */
148 /* *without* the internal leading. So we adjust it a bit to */
149 /* compensate. 5/4 seems to give good results for small fonts. */
151 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
152 height = 10 * (-height * 9 / 8);
153 * may be we have to use an non linear function
155 /* assume internal leading is 2 pixels. Else small fonts will become
157 height
= (height
-2) * -10;
160 width
= 10 * (font
->lfWidth
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
162 dprintf_font( stddeb
, "FONT_MatchFont: negative width %d(%d)\n",
163 width
, font
->lfWidth
);
167 spacing
= (font
->lfPitchAndFamily
& FIXED_PITCH
) ? 'm' :
168 (font
->lfPitchAndFamily
& VARIABLE_PITCH
) ? 'p' : '*';
171 charset
= (font
->lfCharSet
== ANSI_CHARSET
) ? "iso8859-1" : "*-*";
172 if (*font
->lfFaceName
) {
173 family
= FONT_TranslateName( font
->lfFaceName
);
174 /* FIX ME: I don't if that's correct but it works J.M. */
177 else switch(font
->lfPitchAndFamily
& 0xf0)
180 family
= FONT_TranslateName( "roman" );
183 family
= FONT_TranslateName( "swiss" );
186 family
= FONT_TranslateName( "modern" );
189 family
= FONT_TranslateName( "script" );
192 family
= FONT_TranslateName( "decorative" );
200 oldspacing
= spacing
;
202 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
204 sprintf( pattern
, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
205 family
, weight
, slant
, height
, spacing
, charset
);
207 sprintf( pattern
, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
208 family
, weight
, slant
, height
, spacing
, width
, charset
);
209 dprintf_font(stddeb
, "FONT_MatchFont: '%s'\n", pattern
);
210 names
= XListFonts( display
, pattern
, 1, &count
);
211 if (count
> 0) break;
212 if (spacing
== 'm') /* try 'c' if no 'm' found */ {
216 } else if (spacing
== 'p') /* try '*' if no 'p' found */ {
220 spacing
= oldspacing
;
224 /* try oblique if no italic font */
229 if (spacing
== 'm' && strcmp(family
, "*-*") != 0) {
230 /* If a fixed spacing font could not be found, ignore
236 fprintf(stderr
, "FONT_MatchFont(%s) : returning NULL\n", pattern
);
240 dprintf_font(stddeb
," Found '%s'\n", *names
);
241 fontStruct
= XLoadQueryFont( display
, *names
);
242 XFreeFontNames( names
);
247 /***********************************************************************
250 void FONT_GetMetrics( LOGFONT
* logfont
, XFontStruct
* xfont
,
251 TEXTMETRIC
* metrics
)
253 int average
, i
, count
;
256 metrics
->tmAscent
= xfont
->ascent
;
257 metrics
->tmDescent
= xfont
->descent
;
258 metrics
->tmHeight
= xfont
->ascent
+ xfont
->descent
;
260 metrics
->tmInternalLeading
= 0;
261 if (XGetFontProperty( xfont
, XA_X_HEIGHT
, &prop
))
262 metrics
->tmInternalLeading
= xfont
->ascent
- (short)prop
;
263 metrics
->tmExternalLeading
= 0;
264 metrics
->tmMaxCharWidth
= xfont
->max_bounds
.width
;
265 metrics
->tmWeight
= logfont
->lfWeight
;
266 metrics
->tmItalic
= logfont
->lfItalic
;
267 metrics
->tmUnderlined
= logfont
->lfUnderline
;
268 metrics
->tmStruckOut
= logfont
->lfStrikeOut
;
269 metrics
->tmFirstChar
= xfont
->min_char_or_byte2
;
270 metrics
->tmLastChar
= xfont
->max_char_or_byte2
;
271 metrics
->tmDefaultChar
= xfont
->default_char
;
272 metrics
->tmBreakChar
= ' ';
273 metrics
->tmCharSet
= logfont
->lfCharSet
;
274 metrics
->tmOverhang
= 0;
275 metrics
->tmDigitizedAspectX
= 1;
276 metrics
->tmDigitizedAspectY
= 1;
277 metrics
->tmPitchAndFamily
= (logfont
->lfPitchAndFamily
&0xf0)|TMPF_DEVICE
;
278 if (logfont
->lfPitchAndFamily
& FIXED_PITCH
)
279 metrics
->tmPitchAndFamily
|= TMPF_FIXED_PITCH
;
281 if (!xfont
->per_char
) average
= metrics
->tmMaxCharWidth
;
284 XCharStruct
* charPtr
= xfont
->per_char
;
286 for (i
= metrics
->tmFirstChar
; i
<= metrics
->tmLastChar
; i
++)
288 if (!CI_NONEXISTCHAR( charPtr
))
290 average
+= charPtr
->width
;
295 if (count
) average
= (average
+ count
/2) / count
;
297 metrics
->tmAveCharWidth
= average
;
300 /***********************************************************************
301 * GetGlyphOutLine (GDI.309)
303 DWORD
GetGlyphOutLine(HDC hdc
, UINT uChar
, UINT fuFormat
, LPGLYPHMETRICS lpgm
,
304 DWORD cbBuffer
, LPSTR lpBuffer
, LPMAT2 lpmat2
)
306 fprintf( stdnimp
,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
307 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
308 return (DWORD
)-1; /* failure */
312 /***********************************************************************
313 * CreateScalableFontResource (GDI.310)
315 BOOL
CreateScalableFontResource( UINT fHidden
,LPSTR lpszResourceFile
,
316 LPSTR lpszFontFile
, LPSTR lpszCurrentPath
)
318 /* fHidden=1 - only visible for the calling app, read-only, not
319 * enumbered with EnumFonts/EnumFontFamilies
320 * lpszCurrentPath can be NULL
322 fprintf(stdnimp
,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
323 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
324 return FALSE
; /* create failed */
328 /***********************************************************************
329 * CreateFontIndirect (GDI.57)
331 HFONT
CreateFontIndirect( const LOGFONT
* font
)
338 fprintf(stderr
, "CreateFontIndirect : font is NULL : returning NULL\n");
341 hfont
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
);
342 if (!hfont
) return 0;
343 fontPtr
= (FONTOBJ
*) GDI_HEAP_LIN_ADDR( hfont
);
344 memcpy( &fontPtr
->logfont
, font
, sizeof(LOGFONT
) );
345 AnsiLower( fontPtr
->logfont
.lfFaceName
);
346 dprintf_font(stddeb
,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
347 font
, font
->lfHeight
, font
->lfWidth
, hfont
);
352 /***********************************************************************
353 * CreateFont (GDI.56)
355 HFONT
CreateFont( INT height
, INT width
, INT esc
, INT orient
, INT weight
,
356 BYTE italic
, BYTE underline
, BYTE strikeout
, BYTE charset
,
357 BYTE outpres
, BYTE clippres
, BYTE quality
, BYTE pitch
,
360 LOGFONT logfont
= { height
, width
, esc
, orient
, weight
, italic
, underline
,
361 strikeout
, charset
, outpres
, clippres
, quality
, pitch
, };
362 dprintf_font(stddeb
,"CreateFont(%d,%d)\n", height
, width
);
365 strncpy( logfont
.lfFaceName
, name
, LF_FACESIZE
- 1 );
366 logfont
.lfFaceName
[LF_FACESIZE
- 1] = '\0';
368 else logfont
.lfFaceName
[0] = '\0';
369 return CreateFontIndirect( &logfont
);
373 /***********************************************************************
376 int FONT_GetObject( FONTOBJ
* font
, int count
, LPSTR buffer
)
378 if (count
> sizeof(LOGFONT
)) count
= sizeof(LOGFONT
);
379 memcpy( buffer
, &font
->logfont
, count
);
384 /***********************************************************************
387 HFONT
FONT_SelectObject( DC
* dc
, HFONT hfont
, FONTOBJ
* font
)
389 static X_PHYSFONT stockFonts
[LAST_STOCK_FONT
-FIRST_STOCK_FONT
+1];
396 X_PHYSFONT cacheFont
; } cacheFonts
[FONTCACHE
], *cacheFontsMin
;
399 X_PHYSFONT
* stockPtr
;
400 HFONT prevHandle
= dc
->w
.hFont
;
401 XFontStruct
* fontStruct
;
402 dprintf_font(stddeb
,"FONT_SelectObject(%p, %04x, %p)\n", dc
, hfont
, font
);
404 #if 0 /* From the code in SelectObject, this can not happen */
405 /* Load font if necessary */
410 hnewfont
= CreateFont(10, 7, 0, 0, FW_DONTCARE
,
411 FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
, 0, 0,
412 DEFAULT_QUALITY
, FF_DONTCARE
, "*" );
413 font
= (FONTOBJ
*) GDI_HEAP_LIN_ADDR( hnewfont
);
417 if (dc
->header
.wMagic
== METAFILE_DC_MAGIC
)
418 if (MF_CreateFontIndirect(dc
, hfont
, &(font
->logfont
)))
423 if ((hfont
>= FIRST_STOCK_FONT
) && (hfont
<= LAST_STOCK_FONT
))
424 stockPtr
= &stockFonts
[hfont
- FIRST_STOCK_FONT
];
428 * Ok, It's not a stock font but
429 * may be it's cached in dynamic cache
431 for(i
=0; i
<FONTCACHE
; i
++) /* search for same handle */
432 if (cacheFonts
[i
].id
==hfont
) { /* Got the handle */
434 * Check if Handle matches the font
436 if(memcmp(&cacheFonts
[i
].logfont
,&(font
->logfont
), sizeof(LOGFONT
))) {
437 /* No: remove handle id from dynamic font cache */
438 cacheFonts
[i
].access
=0;
439 cacheFonts
[i
].used
=0;
441 /* may be there is an unused handle which contains the font */
442 for(i
=0; i
<FONTCACHE
; i
++) {
443 if((cacheFonts
[i
].used
== 0) &&
444 (memcmp(&cacheFonts
[i
].logfont
,&(font
->logfont
), sizeof(LOGFONT
)))== 0) {
445 /* got it load from cache and set new handle id */
446 stockPtr
= &cacheFonts
[i
].cacheFont
;
447 cacheFonts
[i
].access
=1;
448 cacheFonts
[i
].used
=1;
449 cacheFonts
[i
].id
=hfont
;
450 dprintf_font(stddeb
,"FONT_SelectObject: got font from unused handle\n");
457 /* Yes: load from dynamic font cache */
458 stockPtr
= &cacheFonts
[i
].cacheFont
;
459 cacheFonts
[i
].access
++;
460 cacheFonts
[i
].used
++;
465 if (!stockPtr
|| !stockPtr
->fstruct
)
467 if (!(fontStruct
= FONT_MatchFont( &font
->logfont
, dc
)))
469 /* If it is not a stock font, we can simply return 0 */
470 if (!stockPtr
) return 0;
471 /* Otherwise we must try to find a substitute */
472 dprintf_font(stddeb
,"Loading font 'fixed' for %04x\n", hfont
);
473 font
->logfont
.lfPitchAndFamily
&= ~VARIABLE_PITCH
;
474 font
->logfont
.lfPitchAndFamily
|= FIXED_PITCH
;
475 fontStruct
= XLoadQueryFont( display
, "fixed" );
478 fprintf( stderr
, "No system font could be found. Please check your font path.\n" );
485 fontStruct
= stockPtr
->fstruct
;
487 "FONT_SelectObject: Loaded font from cache %04x %p\n",
491 /* Unuse previous font */
492 for (i
=0; i
< FONTCACHE
; i
++) {
493 if (cacheFonts
[i
].id
== prevHandle
) {
494 cacheFonts
[i
].used
--;
502 if (!stockPtr
->fstruct
)
504 stockPtr
->fstruct
= fontStruct
;
505 FONT_GetMetrics( &font
->logfont
, fontStruct
, &stockPtr
->metrics
);
507 memcpy( &dc
->u
.x
.font
, stockPtr
, sizeof(*stockPtr
) );
515 for (i
=0; i
< FONTCACHE
; i
++) {
516 if (cacheFonts
[i
].used
==0)
517 if ((!cacheFontsMin
) || ((cacheFontsMin
) && (cacheFontsMin
->access
> cacheFonts
[i
].access
)))
518 cacheFontsMin
=&cacheFonts
[i
];
521 fprintf(stderr
,"No unused font cache entry !!!!\n" );
523 if (cacheFontsMin
->id
!=0) {
525 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin
->id
);
526 XFreeFont( display
, cacheFontsMin
->cacheFont
.fstruct
);
528 cacheFontsMin
->cacheFont
.fstruct
= fontStruct
;
529 FONT_GetMetrics( &font
->logfont
, fontStruct
, &cacheFontsMin
->cacheFont
.metrics
);
530 cacheFontsMin
->access
=1;
531 cacheFontsMin
->used
=1;
532 cacheFontsMin
->id
=hfont
;
533 memcpy( &dc
->u
.x
.font
, &(cacheFontsMin
->cacheFont
), sizeof(cacheFontsMin
->cacheFont
) );
534 memcpy(&cacheFontsMin
->logfont
,&(font
->logfont
), sizeof(LOGFONT
));
541 /***********************************************************************
542 * GetTextCharacterExtra (GDI.89)
544 short GetTextCharacterExtra( HDC hdc
)
546 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
548 return abs( (dc
->w
.charExtra
* dc
->w
.WndExtX
+ dc
->w
.VportExtX
/ 2)
553 /***********************************************************************
554 * SetTextCharacterExtra (GDI.8)
556 short SetTextCharacterExtra( HDC hdc
, short extra
)
559 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
561 extra
= (extra
* dc
->w
.VportExtX
+ dc
->w
.WndExtX
/ 2) / dc
->w
.WndExtX
;
562 prev
= dc
->w
.charExtra
;
563 dc
->w
.charExtra
= abs(extra
);
564 return (prev
* dc
->w
.WndExtX
+ dc
->w
.VportExtX
/ 2) / dc
->w
.VportExtX
;
568 /***********************************************************************
569 * SetTextJustification (GDI.10)
571 short SetTextJustification( HDC hdc
, short extra
, short breaks
)
573 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
576 extra
= abs((extra
* dc
->w
.VportExtX
+ dc
->w
.WndExtX
/ 2) / dc
->w
.WndExtX
);
577 if (!extra
) breaks
= 0;
578 dc
->w
.breakTotalExtra
= extra
;
579 dc
->w
.breakCount
= breaks
;
582 dc
->w
.breakExtra
= extra
/ breaks
;
583 dc
->w
.breakRem
= extra
- (dc
->w
.breakCount
* dc
->w
.breakExtra
);
587 dc
->w
.breakExtra
= 0;
594 /***********************************************************************
595 * GetTextFace (GDI.92)
597 INT
GetTextFace( HDC hdc
, INT count
, LPSTR name
)
601 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
603 if (!(font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->w
.hFont
, FONT_MAGIC
)))
605 lstrcpyn( name
, font
->logfont
.lfFaceName
, count
);
610 /***********************************************************************
611 * GetTextExtent (GDI.91)
613 DWORD
GetTextExtent( HDC hdc
, LPCSTR str
, short count
)
616 if (!GetTextExtentPoint( hdc
, str
, count
, &size
)) return 0;
617 return MAKELONG( size
.cx
, size
.cy
);
621 /***********************************************************************
622 * GetTextExtentPoint (GDI.471)
624 BOOL
GetTextExtentPoint( HDC hdc
, LPCSTR str
, short count
, LPSIZE size
)
626 int dir
, ascent
, descent
;
629 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
630 if (!dc
) return FALSE
;
631 XTextExtents( dc
->u
.x
.font
.fstruct
, str
, count
, &dir
,
632 &ascent
, &descent
, &info
);
633 size
->cx
= abs((info
.width
+ dc
->w
.breakRem
+ count
* dc
->w
.charExtra
)
634 * dc
->w
.WndExtX
/ dc
->w
.VportExtX
);
635 size
->cy
= abs((dc
->u
.x
.font
.fstruct
->ascent
+dc
->u
.x
.font
.fstruct
->descent
)
636 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
638 dprintf_font(stddeb
,"GetTextExtentPoint(%04x '%*.*s' %d %p): returning %d,%d\n",
639 hdc
, count
, count
, str
, count
, size
, size
->cx
, size
->cy
);
644 /***********************************************************************
645 * GetTextMetrics (GDI.93)
647 BOOL
GetTextMetrics( HDC hdc
, LPTEXTMETRIC metrics
)
649 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
650 if (!dc
) return FALSE
;
651 memcpy( metrics
, &dc
->u
.x
.font
.metrics
, sizeof(*metrics
) );
653 metrics
->tmAscent
= abs( metrics
->tmAscent
654 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
655 metrics
->tmDescent
= abs( metrics
->tmDescent
656 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
657 metrics
->tmHeight
= metrics
->tmAscent
+ metrics
->tmDescent
;
658 metrics
->tmInternalLeading
= abs( metrics
->tmInternalLeading
659 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
660 metrics
->tmExternalLeading
= abs( metrics
->tmExternalLeading
661 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
662 metrics
->tmMaxCharWidth
= abs( metrics
->tmMaxCharWidth
663 * dc
->w
.WndExtX
/ dc
->w
.VportExtX
);
664 metrics
->tmAveCharWidth
= abs( metrics
->tmAveCharWidth
665 * dc
->w
.WndExtX
/ dc
->w
.VportExtX
);
670 /***********************************************************************
671 * SetMapperFlags (GDI.349)
673 DWORD
SetMapperFlags(HDC hDC
, DWORD dwFlag
)
675 dprintf_font(stdnimp
,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
681 /***********************************************************************
682 * GetCharABCWidths (GDI.307)
684 BOOL
GetCharABCWidths(HDC hdc
, UINT wFirstChar
, UINT wLastChar
, LPABC lpABC
)
686 /* No TrueType fonts in Wine */
691 /***********************************************************************
692 * GetCharWidth (GDI.350)
694 BOOL
GetCharWidth(HDC hdc
, WORD wFirstChar
, WORD wLastChar
, LPINT lpBuffer
)
698 XCharStruct
*cs
, *def
;
700 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
701 if (!dc
) return FALSE
;
702 xfont
= dc
->u
.x
.font
.fstruct
;
705 if (xfont
->per_char
== NULL
)
707 for (i
= wFirstChar
, j
= 0; i
<= wLastChar
; i
++, j
++)
708 *(lpBuffer
+ j
) = xfont
->max_bounds
.width
;
712 CI_GET_DEFAULT_INFO(xfont
, def
);
714 for (i
= wFirstChar
, j
= 0; i
<= wLastChar
; i
++, j
++)
716 CI_GET_CHAR_INFO(xfont
, i
, def
, cs
);
717 *(lpBuffer
+ j
) = cs
? cs
->width
: xfont
->max_bounds
.width
;
718 if (*(lpBuffer
+ j
) < 0)
725 /***********************************************************************
726 * AddFontResource (GDI.119)
728 INT
AddFontResource( LPCSTR str
)
730 fprintf( stdnimp
, "STUB: AddFontResource('%s')\n", str
);
735 /***********************************************************************
736 * RemoveFontResource (GDI.136)
738 BOOL
RemoveFontResource( LPSTR str
)
740 fprintf( stdnimp
, "STUB: RemoveFontResource('%s')\n", str
);
745 /*************************************************************************
746 * ParseFontParms [internal]
748 int ParseFontParms(LPSTR lpFont
, WORD wParmsNo
, LPSTR lpRetStr
, WORD wMaxSiz
)
751 if (lpFont
== NULL
) return 0;
752 if (lpRetStr
== NULL
) return 0;
753 for (i
= 0; (*lpFont
!= '\0' && i
!= wParmsNo
); ) {
754 if (*lpFont
== '-') i
++;
758 if (*lpFont
== '-') lpFont
++;
760 for (i
= 0; (*lpFont
!= '\0' && *lpFont
!= '-' && i
< wMaxSiz
); i
++)
761 *(lpRetStr
+ i
) = *lpFont
++;
762 *(lpRetStr
+ i
) = '\0';
771 /*************************************************************************
772 * InitFontsList [internal]
775 static int logfcmp(const void *a
,const void *b
)
777 return strcmp( (*(LPLOGFONT
*)a
)->lfFaceName
, (*(LPLOGFONT
*)b
)->lfFaceName
);
780 void InitFontsList(void)
784 char *family
, *weight
, *charset
;
794 dprintf_font(stddeb
,"InitFontsList !\n");
795 sprintf( pattern
, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
796 family
, weight
, slant
, spacing
, charset
);
797 names
= XListFonts( display
, pattern
, MAX_FONTS
, &count
);
798 dprintf_font(stddeb
,"InitFontsList // count=%d \n", count
);
799 for (i
= 0; i
< count
; i
++) {
800 lpNewFont
= malloc(sizeof(LOGFONT
) + LF_FACESIZE
);
801 if (lpNewFont
== NULL
) {
802 dprintf_font(stddeb
, "InitFontsList // Error alloc new font structure !\n");
805 dprintf_font(stddeb
,"InitFontsList // names[%d]='%s' \n", i
, names
[i
]);
806 ParseFontParms(names
[i
], 2, str
, sizeof(str
));
807 if (strcmp(str
, "fixed") == 0) strcat(str
, "sys");
809 strcpy(lpNewFont
->lfFaceName
, str
);
810 ParseFontParms(names
[i
], 8, str
, sizeof(str
));
811 lpNewFont
->lfHeight
= atoi(str
) / 10;
812 ParseFontParms(names
[i
], 12, str
, sizeof(str
));
813 lpNewFont
->lfWidth
= atoi(str
) / 10;
814 lpNewFont
->lfEscapement
= 0;
815 lpNewFont
->lfOrientation
= 0;
816 lpNewFont
->lfWeight
= FW_REGULAR
;
817 lpNewFont
->lfItalic
= 0;
818 lpNewFont
->lfUnderline
= 0;
819 lpNewFont
->lfStrikeOut
= 0;
820 ParseFontParms(names
[i
], 13, str
, sizeof(str
));
821 if (strcmp(str
, "iso8859") == 0) {
822 lpNewFont
->lfCharSet
= ANSI_CHARSET
;
824 lpNewFont
->lfCharSet
= OEM_CHARSET
;
826 lpNewFont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
827 lpNewFont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
828 lpNewFont
->lfQuality
= DEFAULT_QUALITY
;
829 ParseFontParms(names
[i
], 11, str
, sizeof(str
));
832 lpNewFont
->lfPitchAndFamily
= VARIABLE_PITCH
| FF_SWISS
;
836 lpNewFont
->lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
839 lpNewFont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
842 dprintf_font(stddeb
,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont
->lfHeight
);
843 dprintf_font(stddeb
,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont
->lfWidth
);
844 dprintf_font(stddeb
,"InitFontsList // lfFaceName='%s' \n", lpNewFont
->lfFaceName
);
845 lpLogFontList
[i
] = lpNewFont
;
846 lpLogFontList
[i
+1] = NULL
;
848 qsort(lpLogFontList
,count
,sizeof(*lpLogFontList
),logfcmp
);
849 XFreeFontNames(names
);
853 /*************************************************************************
856 INT
EnumFonts(HDC hDC
, LPCTSTR lpFaceName
, FONTENUMPROC lpEnumFunc
, LPARAM lpData
)
865 char FaceName
[LF_FACESIZE
];
869 dprintf_font(stddeb
,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
870 hDC
, lpFaceName
, lpFaceName
, (LONG
)lpEnumFunc
, lpData
);
871 if (lpEnumFunc
== 0) return 0;
872 hLog
= GDI_HEAP_ALLOC( sizeof(LOGFONT
) + LF_FACESIZE
);
873 lpLogFont
= (LPLOGFONT
) GDI_HEAP_LIN_ADDR(hLog
);
874 if (lpLogFont
== NULL
) {
875 fprintf(stderr
,"EnumFonts // can't alloc LOGFONT struct !\n");
878 hMet
= GDI_HEAP_ALLOC( sizeof(TEXTMETRIC
) );
879 lptm
= (LPTEXTMETRIC
) GDI_HEAP_LIN_ADDR(hMet
);
882 fprintf(stderr
, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
885 if (lpFaceName
!= NULL
) {
886 strcpy(FaceName
, lpFaceName
);
891 if (lpLogFontList
[0] == NULL
) InitFontsList();
892 for(i
= 0; lpLogFontList
[i
] != NULL
; i
++) {
893 if (lpFaceName
== NULL
) {
894 if (lpOldName
!= NULL
) {
895 if (strcmp(lpOldName
,lpLogFontList
[i
]->lfFaceName
) == 0) continue;
897 lpOldName
= lpLogFontList
[i
]->lfFaceName
;
899 if (strcmp(FaceName
, lpLogFontList
[i
]->lfFaceName
) != 0) continue;
901 dprintf_font(stddeb
,"EnumFonts // enum '%s' !\n", lpLogFontList
[i
]->lfFaceName
);
902 dprintf_font(stddeb
,"EnumFonts // %p !\n", lpLogFontList
[i
]);
903 memcpy(lpLogFont
, lpLogFontList
[i
], sizeof(LOGFONT
) + LF_FACESIZE
);
904 hFont
= CreateFontIndirect(lpLogFont
);
905 hOldFont
= SelectObject(hDC
, hFont
);
906 GetTextMetrics(hDC
, lptm
);
907 SelectObject(hDC
, hOldFont
);
909 dprintf_font(stddeb
,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i
, lpLogFont
, lptm
);
910 nRet
= CallEnumFontsProc(lpEnumFunc
, GDI_HEAP_SEG_ADDR(hLog
),
911 GDI_HEAP_SEG_ADDR(hMet
), 0, (LONG
)lpData
);
913 dprintf_font(stddeb
,"EnumFonts // EnumEnd requested by application !\n");
923 /*************************************************************************
924 * EnumFontFamilies [GDI.330]
926 INT
EnumFontFamilies(HDC hDC
, LPCTSTR lpszFamily
, FONTENUMPROC lpEnumFunc
, LPARAM lpData
)
932 LPENUMLOGFONT lpEnumLogFont
;
935 char FaceName
[LF_FACESIZE
];
939 dprintf_font(stddeb
,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
940 hDC
, lpszFamily
, (DWORD
)lpEnumFunc
, lpData
);
941 if (lpEnumFunc
== 0) return 0;
942 hLog
= GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT
) );
943 lpEnumLogFont
= (LPENUMLOGFONT
) GDI_HEAP_LIN_ADDR(hLog
);
944 if (lpEnumLogFont
== NULL
) {
945 fprintf(stderr
,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
948 hMet
= GDI_HEAP_ALLOC( sizeof(TEXTMETRIC
) );
949 lptm
= (LPTEXTMETRIC
) GDI_HEAP_LIN_ADDR(hMet
);
952 fprintf(stderr
,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
956 if (lpszFamily
!= NULL
) {
957 strcpy(FaceName
, lpszFamily
);
960 if (lpLogFontList
[0] == NULL
) InitFontsList();
961 for(i
= 0; lpLogFontList
[i
] != NULL
; i
++) {
962 if (lpszFamily
== NULL
) {
963 if (lpOldName
!= NULL
) {
964 if (strcmp(lpOldName
,lpLogFontList
[i
]->lfFaceName
) == 0) continue;
966 lpOldName
= lpLogFontList
[i
]->lfFaceName
;
968 if (strcmp(FaceName
, lpLogFontList
[i
]->lfFaceName
) != 0) continue;
970 memcpy(lpEnumLogFont
, lpLogFontList
[i
], sizeof(LOGFONT
));
971 strcpy(lpEnumLogFont
->elfFullName
,"");
972 strcpy(lpEnumLogFont
->elfStyle
,"");
973 hFont
= CreateFontIndirect((LPLOGFONT
)lpEnumLogFont
);
974 hOldFont
= SelectObject(hDC
, hFont
);
975 GetTextMetrics(hDC
, lptm
);
976 SelectObject(hDC
, hOldFont
);
978 dprintf_font(stddeb
, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i
, lpEnumLogFont
, lptm
);
980 nRet
= CallEnumFontFamProc( lpEnumFunc
,
981 GDI_HEAP_SEG_ADDR(hLog
),
982 GDI_HEAP_SEG_ADDR(hMet
),
985 dprintf_font(stddeb
,"EnumFontFamilies // EnumEnd requested by application !\n");
994 /*************************************************************************
995 * GetRasterizerCaps [GDI.313]
998 BOOL
GetRasterizerCaps(LPRASTERIZER_STATUS lprs
, UINT cbNumBytes
)
1000 /* This is not much more than a dummy */
1001 RASTERIZER_STATUS rs
;
1003 rs
.nSize
= sizeof(rs
);
1009 /*************************************************************************
1010 * GetKerningPairs [GDI.332]
1012 int GetKerningPairs(HDC hDC
,int cBufLen
,LPKERNINGPAIR lpKerningPairs
)
1014 /* Wine fonts are ugly and don't support kerning :) */