Release 950620
[wine/multimedia.git] / objects / font.c
blob57079f0bd9861e652ebc8fc324c4cff806e6241f
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;
263 /***********************************************************************
264 * CreateFontIndirect (GDI.57)
266 HFONT CreateFontIndirect( LOGFONT * font )
268 FONTOBJ * fontPtr;
269 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
270 if (!hfont) return 0;
271 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
272 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
273 AnsiLower( fontPtr->logfont.lfFaceName );
274 dprintf_font(stddeb,"CreateFontIndirect(%p); return %04x\n",font,hfont);
275 return hfont;
279 /***********************************************************************
280 * CreateFont (GDI.56)
282 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
283 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
284 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
285 LPSTR name )
287 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
288 strikeout, charset, outpres, clippres, quality, pitch, };
289 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
290 return CreateFontIndirect( &logfont );
294 /***********************************************************************
295 * FONT_GetObject
297 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
299 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
300 memcpy( buffer, &font->logfont, count );
301 return count;
305 /***********************************************************************
306 * FONT_SelectObject
308 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
310 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
311 X_PHYSFONT * stockPtr;
312 HFONT prevHandle = dc->w.hFont;
313 XFontStruct * fontStruct;
314 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n",
315 dc, hfont, font);
316 /* Load font if necessary */
318 if (!font)
320 HFONT hnewfont;
322 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
323 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
324 DEFAULT_QUALITY, FF_DONTCARE, "*" );
325 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
328 if (dc->header.wMagic == METAFILE_DC_MAGIC)
329 return MF_CreateFontIndirect(dc, hfont, &(font->logfont));
331 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
332 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
333 else
334 stockPtr = NULL;
336 if (!stockPtr || !stockPtr->fstruct)
338 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
340 /* If it is not a stock font, we can simply return 0 */
341 if (!stockPtr) return 0;
342 /* Otherwise we must try to find a substitute */
343 dprintf_font(stddeb,"Loading font 'fixed' for %x\n", hfont );
344 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
345 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
346 fontStruct = XLoadQueryFont( display, "fixed" );
347 if (!fontStruct)
349 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
350 exit( 1 );
354 else
356 fontStruct = stockPtr->fstruct;
357 dprintf_font(stddeb,
358 "FONT_SelectObject: Loaded font from cache %x %p\n",
359 hfont, fontStruct );
362 /* Free previous font */
364 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
366 if (dc->u.x.font.fstruct)
367 XFreeFont( display, dc->u.x.font.fstruct );
370 /* Store font */
372 dc->w.hFont = hfont;
373 if (stockPtr)
375 if (!stockPtr->fstruct)
377 stockPtr->fstruct = fontStruct;
378 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
380 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
382 else
384 dc->u.x.font.fstruct = fontStruct;
385 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
387 return prevHandle;
391 /***********************************************************************
392 * GetTextCharacterExtra (GDI.89)
394 short GetTextCharacterExtra( HDC hdc )
396 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
397 if (!dc) return 0;
398 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
399 / dc->w.VportExtX );
403 /***********************************************************************
404 * SetTextCharacterExtra (GDI.8)
406 short SetTextCharacterExtra( HDC hdc, short extra )
408 short prev;
409 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
410 if (!dc) return 0;
411 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
412 prev = dc->w.charExtra;
413 dc->w.charExtra = abs(extra);
414 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
418 /***********************************************************************
419 * SetTextJustification (GDI.10)
421 short SetTextJustification( HDC hdc, short extra, short breaks )
423 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
424 if (!dc) return 0;
426 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
427 if (!extra) breaks = 0;
428 dc->w.breakTotalExtra = extra;
429 dc->w.breakCount = breaks;
430 if (breaks)
432 dc->w.breakExtra = extra / breaks;
433 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
435 else
437 dc->w.breakExtra = 0;
438 dc->w.breakRem = 0;
440 return 1;
444 /***********************************************************************
445 * GetTextFace (GDI.92)
447 INT GetTextFace( HDC hdc, INT count, LPSTR name )
449 FONTOBJ *font;
451 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
452 if (!dc) return 0;
453 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
454 return 0;
455 strncpy( name, font->logfont.lfFaceName, count );
456 name[count-1] = '\0';
457 return strlen(name);
461 /***********************************************************************
462 * GetTextExtent (GDI.91)
464 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
466 SIZE size;
467 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
468 return MAKELONG( size.cx, size.cy );
472 /***********************************************************************
473 * GetTextExtentPoint (GDI.471)
475 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
477 int dir, ascent, descent;
478 XCharStruct info;
480 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
481 if (!dc) return FALSE;
482 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
483 &ascent, &descent, &info );
484 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
485 * dc->w.WndExtX / dc->w.VportExtX);
486 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
487 * dc->w.WndExtY / dc->w.VportExtY);
489 dprintf_font(stddeb,"GetTextExtentPoint(%d '%*.*s' %d %p): returning %d,%d\n",
490 hdc, count, count, str, count, size, size->cx, size->cy );
491 return TRUE;
495 /***********************************************************************
496 * GetTextMetrics (GDI.93)
498 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
500 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
501 if (!dc) return FALSE;
502 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
504 metrics->tmAscent = abs( metrics->tmAscent
505 * dc->w.WndExtY / dc->w.VportExtY );
506 metrics->tmDescent = abs( metrics->tmDescent
507 * dc->w.WndExtY / dc->w.VportExtY );
508 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
509 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
510 * dc->w.WndExtY / dc->w.VportExtY );
511 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
512 * dc->w.WndExtY / dc->w.VportExtY );
513 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
514 * dc->w.WndExtX / dc->w.VportExtX );
515 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
516 * dc->w.WndExtX / dc->w.VportExtX );
517 return TRUE;
521 /***********************************************************************
522 * SetMapperFlags (GDI.349)
524 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
526 dprintf_font(stdnimp,"SetmapperFlags(%04X, %08lX) // Empty Stub !\n",
527 hDC, dwFlag);
528 return 0L;
532 /***********************************************************************/
535 /***********************************************************************
536 * GetCharWidth (GDI.350)
538 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
540 int i, j;
541 XFontStruct *xfont;
542 XCharStruct *cs, *def;
544 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
545 if (!dc) return FALSE;
546 xfont = dc->u.x.font.fstruct;
548 /* fixed font? */
549 if (xfont->per_char == NULL)
551 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
552 *(lpBuffer + j) = xfont->max_bounds.width;
553 return TRUE;
556 CI_GET_DEFAULT_INFO(xfont, def);
558 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
560 CI_GET_CHAR_INFO(xfont, i, def, cs);
561 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
562 if (*(lpBuffer + j) < 0)
563 *(lpBuffer + j) = 0;
565 return TRUE;
569 /***********************************************************************
570 * AddFontResource (GDI.119)
572 int AddFontResource( LPSTR str )
574 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
575 return 1;
579 /***********************************************************************
580 * RemoveFontResource (GDI.136)
582 BOOL RemoveFontResource( LPSTR str )
584 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
585 return TRUE;
589 /*************************************************************************
590 * ParseFontParms [internal]
592 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
594 int i;
595 dprintf_font(stddeb,"ParseFontParms('%s', %d, %p, %d);\n",
596 lpFont, wParmsNo, lpRetStr, wMaxSiz);
597 if (lpFont == NULL) return 0;
598 if (lpRetStr == NULL) return 0;
599 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
600 if (*lpFont == '-') i++;
601 lpFont++;
603 if (i == wParmsNo) {
604 if (*lpFont == '-') lpFont++;
605 wMaxSiz--;
606 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
607 *(lpRetStr + i) = *lpFont++;
608 *(lpRetStr + i) = '\0';
609 dprintf_font(stddeb,"ParseFontParms // '%s'\n", lpRetStr);
610 return i;
612 else
613 lpRetStr[0] = '\0';
614 return 0;
618 /*************************************************************************
619 * InitFontsList [internal]
622 static int logfcmp(const void *a,const void *b)
624 return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
627 void InitFontsList(void)
629 char str[32];
630 char pattern[100];
631 char *family, *weight, *charset;
632 char **names;
633 char slant, spacing;
634 int i, count;
635 LPLOGFONT lpNewFont;
636 weight = "medium";
637 slant = 'r';
638 spacing = '*';
639 charset = "*";
640 family = "*-*";
641 dprintf_font(stddeb,"InitFontsList !\n");
642 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
643 family, weight, slant, spacing, charset);
644 names = XListFonts( display, pattern, MAX_FONTS, &count );
645 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
646 for (i = 0; i < count; i++) {
647 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
648 if (lpNewFont == NULL) {
649 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
650 break;
652 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
653 ParseFontParms(names[i], 2, str, sizeof(str));
654 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
655 AnsiUpper(str);
656 strcpy(lpNewFont->lfFaceName, str);
657 ParseFontParms(names[i], 8, str, sizeof(str));
658 lpNewFont->lfHeight = atoi(str) / 10;
659 ParseFontParms(names[i], 12, str, sizeof(str));
660 lpNewFont->lfWidth = atoi(str) / 10;
661 lpNewFont->lfEscapement = 0;
662 lpNewFont->lfOrientation = 0;
663 lpNewFont->lfWeight = FW_REGULAR;
664 lpNewFont->lfItalic = 0;
665 lpNewFont->lfUnderline = 0;
666 lpNewFont->lfStrikeOut = 0;
667 ParseFontParms(names[i], 13, str, sizeof(str));
668 if (strcmp(str, "iso8859") == 0) {
669 lpNewFont->lfCharSet = ANSI_CHARSET;
670 } else {
671 lpNewFont->lfCharSet = OEM_CHARSET;
673 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
674 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
675 lpNewFont->lfQuality = DEFAULT_QUALITY;
676 ParseFontParms(names[i], 11, str, sizeof(str));
677 switch(str[0]) {
678 case 'p':
679 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
680 break;
681 case 'm':
682 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
683 break;
684 default:
685 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
686 break;
688 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
689 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
690 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
691 lpLogFontList[i] = lpNewFont;
692 lpLogFontList[i+1] = NULL;
694 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
695 XFreeFontNames(names);
699 /*************************************************************************
700 * EnumFonts [GDI.70]
702 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
704 HANDLE hLog;
705 HANDLE hMet;
706 HFONT hFont;
707 HFONT hOldFont;
708 LPLOGFONT lpLogFont;
709 LPTEXTMETRIC lptm;
710 LPSTR lpOldName;
711 char FaceName[LF_FACESIZE];
712 int nRet;
713 int i;
715 dprintf_font(stddeb,"EnumFonts(%04X, %p='%s', %08lx, %p)\n",
716 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
717 if (lpEnumFunc == 0) return 0;
718 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
719 lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
720 if (lpLogFont == NULL) {
721 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
722 return 0;
724 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
725 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
726 if (lptm == NULL) {
727 GDI_HEAP_FREE(hLog);
728 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
729 return 0;
731 if (lpFaceName != NULL) {
732 strcpy(FaceName, lpFaceName);
733 AnsiUpper(FaceName);
735 lpOldName = NULL;
737 if (lpLogFontList[0] == NULL) InitFontsList();
738 for(i = 0; lpLogFontList[i] != NULL; i++) {
739 if (lpFaceName == NULL) {
740 if (lpOldName != NULL) {
741 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
743 lpOldName = lpLogFontList[i]->lfFaceName;
744 } else {
745 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
747 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
748 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
749 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
750 hFont = CreateFontIndirect(lpLogFont);
751 hOldFont = SelectObject(hDC, hFont);
752 GetTextMetrics(hDC, lptm);
753 SelectObject(hDC, hOldFont);
754 DeleteObject(hFont);
755 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
756 nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
757 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
758 if (nRet == 0) {
759 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
760 break;
763 GDI_HEAP_FREE(hMet);
764 GDI_HEAP_FREE(hLog);
765 return nRet;
769 /*************************************************************************
770 * EnumFontFamilies [GDI.330]
772 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
774 HANDLE hLog;
775 HANDLE hMet;
776 HFONT hFont;
777 HFONT hOldFont;
778 LPENUMLOGFONT lpEnumLogFont;
779 LPTEXTMETRIC lptm;
780 LPSTR lpOldName;
781 char FaceName[LF_FACESIZE];
782 int nRet;
783 int i;
785 dprintf_font(stddeb,"EnumFontFamilies(%04X, %p, %08lx, %p)\n",
786 hDC, lpszFamily, lpEnumFunc, lpData);
787 if (lpEnumFunc == 0) return 0;
788 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
789 lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
790 if (lpEnumLogFont == NULL) {
791 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
792 return 0;
794 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
795 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
796 if (lptm == NULL) {
797 GDI_HEAP_FREE(hLog);
798 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
799 return 0;
801 lpOldName = NULL;
802 if (lpszFamily != NULL) {
803 strcpy(FaceName, lpszFamily);
804 AnsiUpper(FaceName);
806 if (lpLogFontList[0] == NULL) InitFontsList();
807 for(i = 0; lpLogFontList[i] != NULL; i++) {
808 if (lpszFamily == NULL) {
809 if (lpOldName != NULL) {
810 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
812 lpOldName = lpLogFontList[i]->lfFaceName;
813 } else {
814 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
816 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
817 strcpy(lpEnumLogFont->elfFullName,"");
818 strcpy(lpEnumLogFont->elfStyle,"");
819 hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
820 hOldFont = SelectObject(hDC, hFont);
821 GetTextMetrics(hDC, lptm);
822 SelectObject(hDC, hOldFont);
823 DeleteObject(hFont);
824 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
826 nRet = CallEnumFontFamProc( lpEnumFunc,
827 GDI_HEAP_SEG_ADDR(hLog),
828 GDI_HEAP_SEG_ADDR(hMet),
829 0, (LONG)lpData );
830 if (nRet == 0) {
831 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
832 break;
835 GDI_HEAP_FREE(hMet);
836 GDI_HEAP_FREE(hLog);
837 return nRet;
840 /*************************************************************************
841 * GetRasterizerCaps [GDI.313]
844 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, WORD cbNumBytes)
846 /* This is not much more than a dummy */
847 RASTERIZER_STATUS rs;
849 rs.nSize = sizeof(rs);
850 rs.wFlags = 0;
851 rs.nLanguageID = 0;
852 return True;
855 /*************************************************************************
856 * GetKerningPairs [GDI.332]
857 * FIXME: The last parameter is actually LPKERNINGPAIR
859 int GetKerningPairs(WORD hDC,int cBufLen,LPVOID lpKerningPairs)
861 /* Wine fonts are ugly and don't support kerning :) */
862 return 0;