Release 950727
[wine/multimedia.git] / objects / font.c
blob200b605633c508a83080b5de32eccbd4cb7834a6
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
6 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <X11/Xatom.h>
13 #include "font.h"
14 #include "metafile.h"
15 #include "wine.h"
16 #include "callback.h"
17 #include "stddebug.h"
18 #include "debug.h"
20 #define MAX_FONTS 256
21 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
24 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
25 (((cs)->rbearing|(cs)->lbearing| \
26 (cs)->ascent|(cs)->descent) == 0))
28 /*
29 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
30 * character. If the character is in the column and exists, then return the
31 * appropriate metrics (note that fonts with common per-character metrics will
32 * return min_bounds). If none of these hold true, try again with the default
33 * char.
35 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
36 { \
37 cs = def; \
38 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
39 if (fs->per_char == NULL) { \
40 cs = &fs->min_bounds; \
41 } else { \
42 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
43 if (CI_NONEXISTCHAR(cs)) cs = def; \
44 } \
45 } \
48 #define CI_GET_DEFAULT_INFO(fs,cs) \
49 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
51 struct FontStructure {
52 char *window;
53 char *x11;
54 } FontNames[32];
55 int FontSize;
58 /***********************************************************************
59 * FONT_Init
61 BOOL FONT_Init( void )
63 char temp[1024];
64 LPSTR ptr;
65 int i;
67 if( GetPrivateProfileString("fonts", NULL, "*", temp, sizeof(temp), WINE_INI) > 2 ) {
68 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
69 if( strcmp( ptr, "default" ) )
70 FontNames[i++].window = strdup( ptr );
71 FontSize = i;
73 for( i = 1; i < FontSize; i++ ) {
74 GetPrivateProfileString("fonts", FontNames[i].window, "*", temp, sizeof(temp), WINE_INI);
75 FontNames[i].x11 = strdup( temp );
77 GetPrivateProfileString("fonts", "default", "*", temp, sizeof(temp), WINE_INI);
78 FontNames[0].x11 = strdup( temp );
80 } else {
81 FontNames[0].window = NULL; FontNames[0].x11 = "bitstream-courier";
82 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
83 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
84 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
85 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
86 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
87 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
88 FontSize = 7;
90 return TRUE;
94 /***********************************************************************
95 * FONT_TranslateName
97 * Translate a Windows face name to its X11 equivalent.
98 * This will probably have to be customizable.
100 static const char *FONT_TranslateName( char *winFaceName )
102 int i;
104 for (i = 1; i < FontSize; i ++)
105 if( !strcmp( winFaceName, FontNames[i].window ) ) {
106 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
107 return FontNames[i].x11;
109 return FontNames[0].x11;
113 /***********************************************************************
114 * FONT_MatchFont
116 * Find a X font matching the logical font.
118 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
120 char pattern[100];
121 const char *family, *weight, *charset;
122 char **names;
123 char slant, spacing;
124 int width, height, oldheight, count;
125 XFontStruct * fontStruct;
127 weight = (font->lfWeight > 550) ? "bold" : "medium";
128 slant = font->lfItalic ? 'i' : 'r';
129 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
130 if (height == 0) height = 120; /* Default height = 12 */
131 else if (height < 0)
133 /* If height is negative, it means the height of the characters */
134 /* *without* the internal leading. So we adjust it a bit to */
135 /* compensate. 5/4 seems to give good results for small fonts. */
136 height = 10 * (-height * 5 / 4);
138 else height *= 10;
139 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
140 if (width < 0) {
141 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
142 width, font->lfWidth );
143 width = -width;
145 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
146 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
147 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
148 if (*font->lfFaceName) family = FONT_TranslateName( font->lfFaceName );
149 else switch(font->lfPitchAndFamily & 0xf0)
151 case FF_ROMAN:
152 family = FONT_TranslateName( "roman" );
153 break;
154 case FF_SWISS:
155 family = FONT_TranslateName( "swiss" );
156 break;
157 case FF_MODERN:
158 family = FONT_TranslateName( "modern" );
159 break;
160 case FF_SCRIPT:
161 family = FONT_TranslateName( "script" );
162 break;
163 case FF_DECORATIVE:
164 family = FONT_TranslateName( "decorative" );
165 break;
166 default:
167 family = "*-*";
168 break;
171 oldheight = height;
172 while (TRUE) {
173 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
174 if ( width == 0 )
175 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
176 family, weight, slant, height, spacing, charset);
177 else
178 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
179 family, weight, slant, height, spacing, width, charset);
180 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
181 names = XListFonts( display, pattern, 1, &count );
182 if (count > 0) break;
183 height -= 10;
184 if (height < 10) {
185 dprintf_font(stddeb,"*** No match for %s\n", pattern );
186 if(slant == 'i') {
187 /* try oblique if no italic font */
188 slant = 'o';
189 height = oldheight;
190 continue;
192 if (spacing == 'm') {
193 /* If a fixed spacing font could not be found, ignore
194 * the family */
195 family = "*-*";
196 height = oldheight;
197 continue;
199 return NULL;
202 dprintf_font(stddeb," Found '%s'\n", *names );
203 fontStruct = XLoadQueryFont( display, *names );
204 XFreeFontNames( names );
205 return fontStruct;
209 /***********************************************************************
210 * FONT_GetMetrics
212 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
213 TEXTMETRIC * metrics )
215 int average, i, count;
216 unsigned long prop;
218 metrics->tmAscent = xfont->ascent;
219 metrics->tmDescent = xfont->descent;
220 metrics->tmHeight = xfont->ascent + xfont->descent;
222 metrics->tmInternalLeading = 0;
223 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
224 metrics->tmInternalLeading = xfont->ascent - (short)prop;
225 metrics->tmExternalLeading = 0;
226 metrics->tmMaxCharWidth = xfont->max_bounds.width;
227 metrics->tmWeight = logfont->lfWeight;
228 metrics->tmItalic = logfont->lfItalic;
229 metrics->tmUnderlined = logfont->lfUnderline;
230 metrics->tmStruckOut = logfont->lfStrikeOut;
231 metrics->tmFirstChar = xfont->min_char_or_byte2;
232 metrics->tmLastChar = xfont->max_char_or_byte2;
233 metrics->tmDefaultChar = xfont->default_char;
234 metrics->tmBreakChar = ' ';
235 metrics->tmCharSet = logfont->lfCharSet;
236 metrics->tmOverhang = 0;
237 metrics->tmDigitizedAspectX = 1;
238 metrics->tmDigitizedAspectY = 1;
239 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
240 if (logfont->lfPitchAndFamily & FIXED_PITCH)
241 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
243 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
244 else
246 XCharStruct * charPtr = xfont->per_char;
247 average = count = 0;
248 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
250 if (!CI_NONEXISTCHAR( charPtr ))
252 average += charPtr->width;
253 count++;
255 charPtr++;
257 if (count) average = (average + count/2) / count;
259 metrics->tmAveCharWidth = average;
262 /***********************************************************************
263 * GetGlyphOutLine (GDI.309)
265 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm,
266 DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2)
268 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
269 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
270 return (DWORD)-1; /* failure */
274 /***********************************************************************
275 * CreateScalableFontResource (GDI.310)
277 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
278 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
280 /* fHidden=1 - only visible for the calling app, read-only, not
281 * enumbered with EnumFonts/EnumFontFamilies
282 * lpszCurrentPath can be NULL
284 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
285 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
286 return FALSE; /* create failed */
290 /***********************************************************************
291 * CreateFontIndirect (GDI.57)
293 HFONT CreateFontIndirect( LOGFONT * font )
295 FONTOBJ * fontPtr;
296 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
297 if (!hfont) return 0;
298 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
299 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
300 AnsiLower( fontPtr->logfont.lfFaceName );
301 dprintf_font(stddeb,"CreateFontIndirect(%p); return %04x\n",font,hfont);
302 return hfont;
306 /***********************************************************************
307 * CreateFont (GDI.56)
309 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
310 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
311 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
312 LPSTR name )
314 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
315 strikeout, charset, outpres, clippres, quality, pitch, };
316 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
317 return CreateFontIndirect( &logfont );
321 /***********************************************************************
322 * FONT_GetObject
324 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
326 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
327 memcpy( buffer, &font->logfont, count );
328 return count;
332 /***********************************************************************
333 * FONT_SelectObject
335 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
337 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
338 X_PHYSFONT * stockPtr;
339 HFONT prevHandle = dc->w.hFont;
340 XFontStruct * fontStruct;
341 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n",
342 dc, hfont, font);
343 /* Load font if necessary */
345 if (!font)
347 HFONT hnewfont;
349 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
350 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
351 DEFAULT_QUALITY, FF_DONTCARE, "*" );
352 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
355 if (dc->header.wMagic == METAFILE_DC_MAGIC)
356 return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
358 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
359 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
360 else
361 stockPtr = NULL;
363 if (!stockPtr || !stockPtr->fstruct)
365 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
367 /* If it is not a stock font, we can simply return 0 */
368 if (!stockPtr) return 0;
369 /* Otherwise we must try to find a substitute */
370 dprintf_font(stddeb,"Loading font 'fixed' for %x\n", hfont );
371 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
372 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
373 fontStruct = XLoadQueryFont( display, "fixed" );
374 if (!fontStruct)
376 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
377 exit( 1 );
381 else
383 fontStruct = stockPtr->fstruct;
384 dprintf_font(stddeb,
385 "FONT_SelectObject: Loaded font from cache %x %p\n",
386 hfont, fontStruct );
389 /* Free previous font */
391 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
393 if (dc->u.x.font.fstruct)
394 XFreeFont( display, dc->u.x.font.fstruct );
397 /* Store font */
399 dc->w.hFont = hfont;
400 if (stockPtr)
402 if (!stockPtr->fstruct)
404 stockPtr->fstruct = fontStruct;
405 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
407 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
409 else
411 dc->u.x.font.fstruct = fontStruct;
412 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
414 return prevHandle;
418 /***********************************************************************
419 * GetTextCharacterExtra (GDI.89)
421 short GetTextCharacterExtra( HDC hdc )
423 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
424 if (!dc) return 0;
425 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
426 / dc->w.VportExtX );
430 /***********************************************************************
431 * SetTextCharacterExtra (GDI.8)
433 short SetTextCharacterExtra( HDC hdc, short extra )
435 short prev;
436 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
437 if (!dc) return 0;
438 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
439 prev = dc->w.charExtra;
440 dc->w.charExtra = abs(extra);
441 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
445 /***********************************************************************
446 * SetTextJustification (GDI.10)
448 short SetTextJustification( HDC hdc, short extra, short breaks )
450 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
451 if (!dc) return 0;
453 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
454 if (!extra) breaks = 0;
455 dc->w.breakTotalExtra = extra;
456 dc->w.breakCount = breaks;
457 if (breaks)
459 dc->w.breakExtra = extra / breaks;
460 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
462 else
464 dc->w.breakExtra = 0;
465 dc->w.breakRem = 0;
467 return 1;
471 /***********************************************************************
472 * GetTextFace (GDI.92)
474 INT GetTextFace( HDC hdc, INT count, LPSTR name )
476 FONTOBJ *font;
478 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
479 if (!dc) return 0;
480 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
481 return 0;
482 strncpy( name, font->logfont.lfFaceName, count );
483 name[count-1] = '\0';
484 return strlen(name);
488 /***********************************************************************
489 * GetTextExtent (GDI.91)
491 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
493 SIZE size;
494 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
495 return MAKELONG( size.cx, size.cy );
499 /***********************************************************************
500 * GetTextExtentPoint (GDI.471)
502 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
504 int dir, ascent, descent;
505 XCharStruct info;
507 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
508 if (!dc) return FALSE;
509 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
510 &ascent, &descent, &info );
511 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
512 * dc->w.WndExtX / dc->w.VportExtX);
513 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
514 * dc->w.WndExtY / dc->w.VportExtY);
516 dprintf_font(stddeb,"GetTextExtentPoint(%d '%*.*s' %d %p): returning %d,%d\n",
517 hdc, count, count, str, count, size, size->cx, size->cy );
518 return TRUE;
522 /***********************************************************************
523 * GetTextMetrics (GDI.93)
525 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
527 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
528 if (!dc) return FALSE;
529 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
531 metrics->tmAscent = abs( metrics->tmAscent
532 * dc->w.WndExtY / dc->w.VportExtY );
533 metrics->tmDescent = abs( metrics->tmDescent
534 * dc->w.WndExtY / dc->w.VportExtY );
535 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
536 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
537 * dc->w.WndExtY / dc->w.VportExtY );
538 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
539 * dc->w.WndExtY / dc->w.VportExtY );
540 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
541 * dc->w.WndExtX / dc->w.VportExtX );
542 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
543 * dc->w.WndExtX / dc->w.VportExtX );
544 return TRUE;
548 /***********************************************************************
549 * SetMapperFlags (GDI.349)
551 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
553 dprintf_font(stdnimp,"SetmapperFlags(%04X, %08lX) // Empty Stub !\n",
554 hDC, dwFlag);
555 return 0L;
559 /***********************************************************************/
562 /***********************************************************************
563 * GetCharWidth (GDI.350)
565 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
567 int i, j;
568 XFontStruct *xfont;
569 XCharStruct *cs, *def;
571 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
572 if (!dc) return FALSE;
573 xfont = dc->u.x.font.fstruct;
575 /* fixed font? */
576 if (xfont->per_char == NULL)
578 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
579 *(lpBuffer + j) = xfont->max_bounds.width;
580 return TRUE;
583 CI_GET_DEFAULT_INFO(xfont, def);
585 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
587 CI_GET_CHAR_INFO(xfont, i, def, cs);
588 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
589 if (*(lpBuffer + j) < 0)
590 *(lpBuffer + j) = 0;
592 return TRUE;
596 /***********************************************************************
597 * AddFontResource (GDI.119)
599 int AddFontResource( LPSTR str )
601 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
602 return 1;
606 /***********************************************************************
607 * RemoveFontResource (GDI.136)
609 BOOL RemoveFontResource( LPSTR str )
611 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
612 return TRUE;
616 /*************************************************************************
617 * ParseFontParms [internal]
619 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
621 int i;
622 dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n",
623 lpFont, wParmsNo, lpRetStr, wMaxSiz);
624 if (lpFont == NULL) return 0;
625 if (lpRetStr == NULL) return 0;
626 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
627 if (*lpFont == '-') i++;
628 lpFont++;
630 if (i == wParmsNo) {
631 if (*lpFont == '-') lpFont++;
632 wMaxSiz--;
633 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
634 *(lpRetStr + i) = *lpFont++;
635 *(lpRetStr + i) = '\0';
636 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
637 return i;
639 else
640 lpRetStr[0] = '\0';
641 return 0;
645 /*************************************************************************
646 * InitFontsList [internal]
649 static int logfcmp(const void *a,const void *b)
651 return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
654 void InitFontsList(void)
656 char str[32];
657 char pattern[100];
658 char *family, *weight, *charset;
659 char **names;
660 char slant, spacing;
661 int i, count;
662 LPLOGFONT lpNewFont;
663 weight = "medium";
664 slant = 'r';
665 spacing = '*';
666 charset = "*";
667 family = "*-*";
668 dprintf_font(stddeb,"InitFontsList !\n");
669 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
670 family, weight, slant, spacing, charset);
671 names = XListFonts( display, pattern, MAX_FONTS, &count );
672 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
673 for (i = 0; i < count; i++) {
674 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
675 if (lpNewFont == NULL) {
676 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
677 break;
679 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
680 ParseFontParms(names[i], 2, str, sizeof(str));
681 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
682 AnsiUpper(str);
683 strcpy(lpNewFont->lfFaceName, str);
684 ParseFontParms(names[i], 8, str, sizeof(str));
685 lpNewFont->lfHeight = atoi(str) / 10;
686 ParseFontParms(names[i], 12, str, sizeof(str));
687 lpNewFont->lfWidth = atoi(str) / 10;
688 lpNewFont->lfEscapement = 0;
689 lpNewFont->lfOrientation = 0;
690 lpNewFont->lfWeight = FW_REGULAR;
691 lpNewFont->lfItalic = 0;
692 lpNewFont->lfUnderline = 0;
693 lpNewFont->lfStrikeOut = 0;
694 ParseFontParms(names[i], 13, str, sizeof(str));
695 if (strcmp(str, "iso8859") == 0) {
696 lpNewFont->lfCharSet = ANSI_CHARSET;
697 } else {
698 lpNewFont->lfCharSet = OEM_CHARSET;
700 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
701 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
702 lpNewFont->lfQuality = DEFAULT_QUALITY;
703 ParseFontParms(names[i], 11, str, sizeof(str));
704 switch(str[0]) {
705 case 'p':
706 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
707 break;
708 case 'm':
709 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
710 break;
711 default:
712 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
713 break;
715 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
716 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
717 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
718 lpLogFontList[i] = lpNewFont;
719 lpLogFontList[i+1] = NULL;
721 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
722 XFreeFontNames(names);
726 /*************************************************************************
727 * EnumFonts [GDI.70]
729 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
731 HANDLE hLog;
732 HANDLE hMet;
733 HFONT hFont;
734 HFONT hOldFont;
735 LPLOGFONT lpLogFont;
736 LPTEXTMETRIC lptm;
737 LPSTR lpOldName;
738 char FaceName[LF_FACESIZE];
739 int nRet = 0;
740 int i;
742 dprintf_font(stddeb,"EnumFonts(%04X, %p='%s', %08lx, %p)\n",
743 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
744 if (lpEnumFunc == 0) return 0;
745 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
746 lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
747 if (lpLogFont == NULL) {
748 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
749 return 0;
751 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
752 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
753 if (lptm == NULL) {
754 GDI_HEAP_FREE(hLog);
755 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
756 return 0;
758 if (lpFaceName != NULL) {
759 strcpy(FaceName, lpFaceName);
760 AnsiUpper(FaceName);
762 lpOldName = NULL;
764 if (lpLogFontList[0] == NULL) InitFontsList();
765 for(i = 0; lpLogFontList[i] != NULL; i++) {
766 if (lpFaceName == NULL) {
767 if (lpOldName != NULL) {
768 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
770 lpOldName = lpLogFontList[i]->lfFaceName;
771 } else {
772 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
774 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
775 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
776 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
777 hFont = CreateFontIndirect(lpLogFont);
778 hOldFont = SelectObject(hDC, hFont);
779 GetTextMetrics(hDC, lptm);
780 SelectObject(hDC, hOldFont);
781 DeleteObject(hFont);
782 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
783 nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
784 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
785 if (nRet == 0) {
786 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
787 break;
790 GDI_HEAP_FREE(hMet);
791 GDI_HEAP_FREE(hLog);
792 return nRet;
796 /*************************************************************************
797 * EnumFontFamilies [GDI.330]
799 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
801 HANDLE hLog;
802 HANDLE hMet;
803 HFONT hFont;
804 HFONT hOldFont;
805 LPENUMLOGFONT lpEnumLogFont;
806 LPTEXTMETRIC lptm;
807 LPSTR lpOldName;
808 char FaceName[LF_FACESIZE];
809 int nRet = 0;
810 int i;
812 dprintf_font(stddeb,"EnumFontFamilies(%04X, %p, %08lx, %p)\n",
813 hDC, lpszFamily, lpEnumFunc, lpData);
814 if (lpEnumFunc == 0) return 0;
815 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
816 lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
817 if (lpEnumLogFont == NULL) {
818 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
819 return 0;
821 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
822 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
823 if (lptm == NULL) {
824 GDI_HEAP_FREE(hLog);
825 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
826 return 0;
828 lpOldName = NULL;
829 if (lpszFamily != NULL) {
830 strcpy(FaceName, lpszFamily);
831 AnsiUpper(FaceName);
833 if (lpLogFontList[0] == NULL) InitFontsList();
834 for(i = 0; lpLogFontList[i] != NULL; i++) {
835 if (lpszFamily == NULL) {
836 if (lpOldName != NULL) {
837 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
839 lpOldName = lpLogFontList[i]->lfFaceName;
840 } else {
841 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
843 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
844 strcpy(lpEnumLogFont->elfFullName,"");
845 strcpy(lpEnumLogFont->elfStyle,"");
846 hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
847 hOldFont = SelectObject(hDC, hFont);
848 GetTextMetrics(hDC, lptm);
849 SelectObject(hDC, hOldFont);
850 DeleteObject(hFont);
851 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
853 nRet = CallEnumFontFamProc( lpEnumFunc,
854 GDI_HEAP_SEG_ADDR(hLog),
855 GDI_HEAP_SEG_ADDR(hMet),
856 0, (LONG)lpData );
857 if (nRet == 0) {
858 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
859 break;
862 GDI_HEAP_FREE(hMet);
863 GDI_HEAP_FREE(hLog);
864 return nRet;
867 /*************************************************************************
868 * GetRasterizerCaps [GDI.313]
871 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
873 /* This is not much more than a dummy */
874 RASTERIZER_STATUS rs;
876 rs.nSize = sizeof(rs);
877 rs.wFlags = 0;
878 rs.nLanguageID = 0;
879 return True;
882 /*************************************************************************
883 * GetKerningPairs [GDI.332]
884 * FIXME: The last parameter is actually LPKERNINGPAIR
886 int GetKerningPairs(WORD hDC,int cBufLen,LPVOID lpKerningPairs)
888 /* Wine fonts are ugly and don't support kerning :) */
889 return 0;