Release 951003
[wine/multimedia.git] / objects / font.c
blobb1a89a896cdd75abf6a0869333c5e00f23958285
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 = "*-helvetica";
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("NPFMT", '%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 "NPFMT"\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 if (name) strncpy( logfont.lfFaceName, name, LF_FACESIZE );
317 else logfont.lfFaceName[0] = '\0';
318 return CreateFontIndirect( &logfont );
322 /***********************************************************************
323 * FONT_GetObject
325 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
327 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
328 memcpy( buffer, &font->logfont, count );
329 return count;
333 /***********************************************************************
334 * FONT_SelectObject
336 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
338 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
339 X_PHYSFONT * stockPtr;
340 HFONT prevHandle = dc->w.hFont;
341 XFontStruct * fontStruct;
342 dprintf_font(stddeb,"FONT_SelectObject(%p, "NPFMT", %p)\n",
343 dc, hfont, font);
344 /* Load font if necessary */
346 if (!font)
348 HFONT hnewfont;
350 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
351 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
352 DEFAULT_QUALITY, FF_DONTCARE, "*" );
353 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
356 if (dc->header.wMagic == METAFILE_DC_MAGIC)
357 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
358 return prevHandle;
359 else
360 return 0;
362 /* Must be DWORD for WINELIB32 support */
363 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
364 stockPtr = &stockFonts[(DWORD)hfont - (DWORD)FIRST_STOCK_FONT];
365 else
366 stockPtr = NULL;
368 if (!stockPtr || !stockPtr->fstruct)
370 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
372 /* If it is not a stock font, we can simply return 0 */
373 if (!stockPtr) return 0;
374 /* Otherwise we must try to find a substitute */
375 dprintf_font(stddeb,"Loading font 'fixed' for "NPFMT"\n", hfont );
376 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
377 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
378 fontStruct = XLoadQueryFont( display, "fixed" );
379 if (!fontStruct)
381 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
382 exit( 1 );
386 else
388 fontStruct = stockPtr->fstruct;
389 dprintf_font(stddeb,
390 "FONT_SelectObject: Loaded font from cache "NPFMT" %p\n",
391 hfont, fontStruct );
394 /* Free previous font */
396 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
398 if (dc->u.x.font.fstruct)
399 XFreeFont( display, dc->u.x.font.fstruct );
402 /* Store font */
404 dc->w.hFont = hfont;
405 if (stockPtr)
407 if (!stockPtr->fstruct)
409 stockPtr->fstruct = fontStruct;
410 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
412 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
414 else
416 dc->u.x.font.fstruct = fontStruct;
417 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
419 return prevHandle;
423 /***********************************************************************
424 * GetTextCharacterExtra (GDI.89)
426 short GetTextCharacterExtra( HDC hdc )
428 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
429 if (!dc) return 0;
430 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
431 / dc->w.VportExtX );
435 /***********************************************************************
436 * SetTextCharacterExtra (GDI.8)
438 short SetTextCharacterExtra( HDC hdc, short extra )
440 short prev;
441 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
442 if (!dc) return 0;
443 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
444 prev = dc->w.charExtra;
445 dc->w.charExtra = abs(extra);
446 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
450 /***********************************************************************
451 * SetTextJustification (GDI.10)
453 short SetTextJustification( HDC hdc, short extra, short breaks )
455 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
456 if (!dc) return 0;
458 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
459 if (!extra) breaks = 0;
460 dc->w.breakTotalExtra = extra;
461 dc->w.breakCount = breaks;
462 if (breaks)
464 dc->w.breakExtra = extra / breaks;
465 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
467 else
469 dc->w.breakExtra = 0;
470 dc->w.breakRem = 0;
472 return 1;
476 /***********************************************************************
477 * GetTextFace (GDI.92)
479 INT GetTextFace( HDC hdc, INT count, LPSTR name )
481 FONTOBJ *font;
483 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
484 if (!dc) return 0;
485 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
486 return 0;
487 strncpy( name, font->logfont.lfFaceName, count );
488 name[count-1] = '\0';
489 return strlen(name);
493 /***********************************************************************
494 * GetTextExtent (GDI.91)
496 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
498 SIZE size;
499 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
500 return MAKELONG( size.cx, size.cy );
504 /***********************************************************************
505 * GetTextExtentPoint (GDI.471)
507 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
509 int dir, ascent, descent;
510 XCharStruct info;
512 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
513 if (!dc) return FALSE;
514 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
515 &ascent, &descent, &info );
516 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
517 * dc->w.WndExtX / dc->w.VportExtX);
518 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
519 * dc->w.WndExtY / dc->w.VportExtY);
521 dprintf_font(stddeb,"GetTextExtentPoint("NPFMT" '%*.*s' %d %p): returning %d,%d\n",
522 hdc, count, count, str, count, size, size->cx, size->cy );
523 return TRUE;
527 /***********************************************************************
528 * GetTextMetrics (GDI.93)
530 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
532 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
533 if (!dc) return FALSE;
534 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
536 metrics->tmAscent = abs( metrics->tmAscent
537 * dc->w.WndExtY / dc->w.VportExtY );
538 metrics->tmDescent = abs( metrics->tmDescent
539 * dc->w.WndExtY / dc->w.VportExtY );
540 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
541 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
542 * dc->w.WndExtY / dc->w.VportExtY );
543 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
544 * dc->w.WndExtY / dc->w.VportExtY );
545 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
546 * dc->w.WndExtX / dc->w.VportExtX );
547 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
548 * dc->w.WndExtX / dc->w.VportExtX );
549 return TRUE;
553 /***********************************************************************
554 * SetMapperFlags (GDI.349)
556 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
558 dprintf_font(stdnimp,"SetmapperFlags("NPFMT", %08lX) // Empty Stub !\n",
559 hDC, dwFlag);
560 return 0L;
564 /***********************************************************************/
567 /***********************************************************************
568 * GetCharWidth (GDI.350)
570 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
572 int i, j;
573 XFontStruct *xfont;
574 XCharStruct *cs, *def;
576 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
577 if (!dc) return FALSE;
578 xfont = dc->u.x.font.fstruct;
580 /* fixed font? */
581 if (xfont->per_char == NULL)
583 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
584 *(lpBuffer + j) = xfont->max_bounds.width;
585 return TRUE;
588 CI_GET_DEFAULT_INFO(xfont, def);
590 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
592 CI_GET_CHAR_INFO(xfont, i, def, cs);
593 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
594 if (*(lpBuffer + j) < 0)
595 *(lpBuffer + j) = 0;
597 return TRUE;
601 /***********************************************************************
602 * AddFontResource (GDI.119)
604 INT AddFontResource( LPCSTR str )
606 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
607 return 1;
611 /***********************************************************************
612 * RemoveFontResource (GDI.136)
614 BOOL RemoveFontResource( LPSTR str )
616 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
617 return TRUE;
621 /*************************************************************************
622 * ParseFontParms [internal]
624 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
626 int i;
627 dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n",
628 lpFont, wParmsNo, lpRetStr, wMaxSiz);
629 if (lpFont == NULL) return 0;
630 if (lpRetStr == NULL) return 0;
631 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
632 if (*lpFont == '-') i++;
633 lpFont++;
635 if (i == wParmsNo) {
636 if (*lpFont == '-') lpFont++;
637 wMaxSiz--;
638 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
639 *(lpRetStr + i) = *lpFont++;
640 *(lpRetStr + i) = '\0';
641 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
642 return i;
644 else
645 lpRetStr[0] = '\0';
646 return 0;
650 /*************************************************************************
651 * InitFontsList [internal]
654 static int logfcmp(const void *a,const void *b)
656 return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
659 void InitFontsList(void)
661 char str[32];
662 char pattern[100];
663 char *family, *weight, *charset;
664 char **names;
665 char slant, spacing;
666 int i, count;
667 LPLOGFONT lpNewFont;
668 weight = "medium";
669 slant = 'r';
670 spacing = '*';
671 charset = "*";
672 family = "*-*";
673 dprintf_font(stddeb,"InitFontsList !\n");
674 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
675 family, weight, slant, spacing, charset);
676 names = XListFonts( display, pattern, MAX_FONTS, &count );
677 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
678 for (i = 0; i < count; i++) {
679 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
680 if (lpNewFont == NULL) {
681 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
682 break;
684 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
685 ParseFontParms(names[i], 2, str, sizeof(str));
686 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
687 AnsiUpper(str);
688 strcpy(lpNewFont->lfFaceName, str);
689 ParseFontParms(names[i], 8, str, sizeof(str));
690 lpNewFont->lfHeight = atoi(str) / 10;
691 ParseFontParms(names[i], 12, str, sizeof(str));
692 lpNewFont->lfWidth = atoi(str) / 10;
693 lpNewFont->lfEscapement = 0;
694 lpNewFont->lfOrientation = 0;
695 lpNewFont->lfWeight = FW_REGULAR;
696 lpNewFont->lfItalic = 0;
697 lpNewFont->lfUnderline = 0;
698 lpNewFont->lfStrikeOut = 0;
699 ParseFontParms(names[i], 13, str, sizeof(str));
700 if (strcmp(str, "iso8859") == 0) {
701 lpNewFont->lfCharSet = ANSI_CHARSET;
702 } else {
703 lpNewFont->lfCharSet = OEM_CHARSET;
705 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
706 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
707 lpNewFont->lfQuality = DEFAULT_QUALITY;
708 ParseFontParms(names[i], 11, str, sizeof(str));
709 switch(str[0]) {
710 case 'p':
711 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
712 break;
713 case 'm':
714 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
715 break;
716 default:
717 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
718 break;
720 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
721 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
722 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
723 lpLogFontList[i] = lpNewFont;
724 lpLogFontList[i+1] = NULL;
726 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
727 XFreeFontNames(names);
731 /*************************************************************************
732 * EnumFonts [GDI.70]
734 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
736 HANDLE hLog;
737 HANDLE hMet;
738 HFONT hFont;
739 HFONT hOldFont;
740 LPLOGFONT lpLogFont;
741 LPTEXTMETRIC lptm;
742 LPSTR lpOldName;
743 char FaceName[LF_FACESIZE];
744 int nRet = 0;
745 int i;
747 dprintf_font(stddeb,"EnumFonts("NPFMT", %p='%s', %08lx, %p)\n",
748 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
749 if (lpEnumFunc == 0) return 0;
750 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
751 lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
752 if (lpLogFont == NULL) {
753 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
754 return 0;
756 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
757 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
758 if (lptm == NULL) {
759 GDI_HEAP_FREE(hLog);
760 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
761 return 0;
763 if (lpFaceName != NULL) {
764 strcpy(FaceName, lpFaceName);
765 AnsiUpper(FaceName);
767 lpOldName = NULL;
769 if (lpLogFontList[0] == NULL) InitFontsList();
770 for(i = 0; lpLogFontList[i] != NULL; i++) {
771 if (lpFaceName == NULL) {
772 if (lpOldName != NULL) {
773 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
775 lpOldName = lpLogFontList[i]->lfFaceName;
776 } else {
777 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
779 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
780 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
781 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
782 hFont = CreateFontIndirect(lpLogFont);
783 hOldFont = SelectObject(hDC, hFont);
784 GetTextMetrics(hDC, lptm);
785 SelectObject(hDC, hOldFont);
786 DeleteObject(hFont);
787 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
788 nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
789 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
790 if (nRet == 0) {
791 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
792 break;
795 GDI_HEAP_FREE(hMet);
796 GDI_HEAP_FREE(hLog);
797 return nRet;
801 /*************************************************************************
802 * EnumFontFamilies [GDI.330]
804 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
806 HANDLE hLog;
807 HANDLE hMet;
808 HFONT hFont;
809 HFONT hOldFont;
810 LPENUMLOGFONT lpEnumLogFont;
811 LPTEXTMETRIC lptm;
812 LPSTR lpOldName;
813 char FaceName[LF_FACESIZE];
814 int nRet = 0;
815 int i;
817 dprintf_font(stddeb,"EnumFontFamilies("NPFMT", %p, %08lx, %p)\n",
818 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
819 if (lpEnumFunc == 0) return 0;
820 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
821 lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
822 if (lpEnumLogFont == NULL) {
823 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
824 return 0;
826 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
827 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
828 if (lptm == NULL) {
829 GDI_HEAP_FREE(hLog);
830 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
831 return 0;
833 lpOldName = NULL;
834 if (lpszFamily != NULL) {
835 strcpy(FaceName, lpszFamily);
836 AnsiUpper(FaceName);
838 if (lpLogFontList[0] == NULL) InitFontsList();
839 for(i = 0; lpLogFontList[i] != NULL; i++) {
840 if (lpszFamily == NULL) {
841 if (lpOldName != NULL) {
842 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
844 lpOldName = lpLogFontList[i]->lfFaceName;
845 } else {
846 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
848 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
849 strcpy(lpEnumLogFont->elfFullName,"");
850 strcpy(lpEnumLogFont->elfStyle,"");
851 hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
852 hOldFont = SelectObject(hDC, hFont);
853 GetTextMetrics(hDC, lptm);
854 SelectObject(hDC, hOldFont);
855 DeleteObject(hFont);
856 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
858 nRet = CallEnumFontFamProc( lpEnumFunc,
859 GDI_HEAP_SEG_ADDR(hLog),
860 GDI_HEAP_SEG_ADDR(hMet),
861 0, (LONG)lpData );
862 if (nRet == 0) {
863 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
864 break;
867 GDI_HEAP_FREE(hMet);
868 GDI_HEAP_FREE(hLog);
869 return nRet;
872 /*************************************************************************
873 * GetRasterizerCaps [GDI.313]
876 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
878 /* This is not much more than a dummy */
879 RASTERIZER_STATUS rs;
881 rs.nSize = sizeof(rs);
882 rs.wFlags = 0;
883 rs.nLanguageID = 0;
884 return True;
887 /*************************************************************************
888 * GetKerningPairs [GDI.332]
889 * FIXME: The last parameter is actually LPKERNINGPAIR
891 int GetKerningPairs(WORD hDC,int cBufLen,LPVOID lpKerningPairs)
893 /* Wine fonts are ugly and don't support kerning :) */
894 return 0;