Release 960824
[wine/multimedia.git] / objects / font.c
blob615569fc5e78c36ab7d41e3e3b32562ddcdd67e5
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
6 * Enhacements by Juergen Marquardt 1996
8 * Implementation of a second font cache which
9 * will be updated dynamically
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <X11/Xatom.h>
16 #include "font.h"
17 #include "metafile.h"
18 #include "options.h"
19 #include "string32.h"
20 #include "xmalloc.h"
21 #include "stddebug.h"
22 #include "debug.h"
24 #define FONTCACHE 32 /* dynamic font cache size */
25 #define MAX_FONTS 256
26 static LPLOGFONT16 lpLogFontList[MAX_FONTS+1];
28 static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
30 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
31 (((cs)->rbearing|(cs)->lbearing| \
32 (cs)->ascent|(cs)->descent) == 0))
34 /*
35 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
36 * character. If the character is in the column and exists, then return the
37 * appropriate metrics (note that fonts with common per-character metrics will
38 * return min_bounds). If none of these hold true, try again with the default
39 * char.
41 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
42 { \
43 cs = def; \
44 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
45 if (fs->per_char == NULL) { \
46 cs = &fs->min_bounds; \
47 } else { \
48 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
49 if (CI_NONEXISTCHAR(cs)) cs = def; \
50 } \
51 } \
54 #define CI_GET_DEFAULT_INFO(fs,cs) \
55 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
57 struct FontStructure {
58 char *window;
59 char *x11;
60 } FontNames[32];
61 int FontSize;
64 /***********************************************************************
65 * FONT_Init
67 BOOL32 FONT_Init( void )
69 char temp[1024];
70 LPSTR ptr;
71 int i;
73 if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
75 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
76 if( strcmp( ptr, "default" ) )
77 FontNames[i++].window = xstrdup( ptr );
78 FontSize = i;
80 for( i = 1; i < FontSize; i++ )
82 PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
83 temp, sizeof(temp) );
84 FontNames[i].x11 = xstrdup( temp );
86 PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
87 FontNames[0].x11 = xstrdup( temp );
89 } else {
90 FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
91 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
92 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
93 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
94 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
95 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
96 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
97 FontSize = 7;
99 return TRUE;
102 /***********************************************************************
103 * FONT_ChkX11Family
105 * returns a valid X11 equivalent if a Windows face name
106 * is like a X11 family - or NULL if translation is needed
108 static char *FONT_ChkX11Family(char *winFaceName )
110 static char x11fam[32+2]; /* will be returned */
111 int i;
113 for(i = 0; lpLogFontList[i] != NULL; i++)
114 if( !lstrcmpi32A(winFaceName, lpLogFontList[i]->lfFaceName) )
116 strcpy(x11fam,"*-");
117 return strcat(x11fam,winFaceName);
119 return NULL; /* a FONT_TranslateName() call is needed */
124 /***********************************************************************
125 * FONT_TranslateName
127 * Translate a Windows face name to its X11 equivalent.
128 * This will probably have to be customizable.
130 static const char *FONT_TranslateName( char *winFaceName )
132 int i;
134 for (i = 1; i < FontSize; i ++)
135 if( !strcmp( winFaceName, FontNames[i].window ) ) {
136 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
137 return FontNames[i].x11;
139 return FontNames[0].x11;
143 /***********************************************************************
144 * FONT_MatchFont
146 * Find a X font matching the logical font.
148 static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc )
150 char pattern[100];
151 const char *family, *weight, *charset;
152 char **names;
153 char slant, oldspacing, spacing;
154 int width, height, oldheight, count;
155 XFontStruct * fontStruct;
157 dprintf_font(stddeb,
158 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
159 font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
160 weight = (font->lfWeight > 550) ? "bold" : "medium";
161 slant = font->lfItalic ? 'i' : 'r';
162 if (font->lfHeight == -1)
163 height = 0;
164 else
165 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
166 if (height == 0) height = 120; /* Default height = 12 */
167 else if (height < 0)
169 /* If height is negative, it means the height of the characters */
170 /* *without* the internal leading. So we adjust it a bit to */
171 /* compensate. 5/4 seems to give good results for small fonts. */
173 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
174 height = 10 * (-height * 9 / 8);
175 * may be we have to use an non linear function
177 /* assume internal leading is 2 pixels. Else small fonts will become
178 * very small. */
179 height = (height-2) * -10;
181 else height *= 10;
182 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
183 if (width < 0) {
184 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
185 width, font->lfWidth );
186 width = -width;
189 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
190 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
193 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
194 if (*font->lfFaceName) {
195 family = FONT_ChkX11Family(font->lfFaceName);
196 /*--do _not_ translate if lfFaceName is family from X11 A.K.*/
197 if (!family)
198 family = FONT_TranslateName( font->lfFaceName );
199 /* FIX ME: I don't if that's correct but it works J.M. */
200 spacing = '*';
202 else switch(font->lfPitchAndFamily & 0xf0)
204 case FF_ROMAN:
205 family = FONT_TranslateName( "roman" );
206 break;
207 case FF_SWISS:
208 family = FONT_TranslateName( "swiss" );
209 break;
210 case FF_MODERN:
211 family = FONT_TranslateName( "modern" );
212 break;
213 case FF_SCRIPT:
214 family = FONT_TranslateName( "script" );
215 break;
216 case FF_DECORATIVE:
217 family = FONT_TranslateName( "decorative" );
218 break;
219 default:
220 family = "*-*";
221 break;
223 oldheight = height;
224 oldspacing = spacing;
225 while (TRUE) {
226 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
227 if ( width == 0 )
228 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
229 family, weight, slant, height, spacing, charset);
230 else
231 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
232 family, weight, slant, height, spacing, width, charset);
233 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
234 names = XListFonts( display, pattern, 1, &count );
235 if (count > 0) break;
236 if (spacing == 'm') /* try 'c' if no 'm' found */ {
238 spacing = 'c';
239 continue;
240 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
241 spacing = '*';
242 continue;
244 spacing = oldspacing;
245 height -= 10;
246 if (height < 10) {
247 if (slant == 'i') {
248 /* try oblique if no italic font */
249 slant = 'o';
250 height = oldheight;
251 continue;
253 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
254 /* If a fixed spacing font could not be found, ignore
255 * the family */
256 family = "*-*";
257 height = oldheight;
258 continue;
260 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
261 return NULL;
264 dprintf_font(stddeb," Found '%s'\n", *names );
265 if (!*font->lfFaceName)
266 ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
267 /* we need a font name for function GetTextFace() even if there isn't one ;-) */
268 AnsiUpper(font->lfFaceName);
270 fontStruct = XLoadQueryFont( display, *names );
271 XFreeFontNames( names );
272 return fontStruct;
276 /***********************************************************************
277 * FONT_GetMetrics
279 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
280 TEXTMETRIC16 * metrics )
282 int average, i, count;
283 unsigned long prop;
285 metrics->tmAscent = xfont->ascent;
286 metrics->tmDescent = xfont->descent;
287 metrics->tmHeight = xfont->ascent + xfont->descent;
289 metrics->tmInternalLeading = 0;
290 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
291 metrics->tmInternalLeading = xfont->ascent - (short)prop;
292 metrics->tmExternalLeading = 0;
293 metrics->tmMaxCharWidth = xfont->max_bounds.width;
294 metrics->tmWeight = logfont->lfWeight;
295 metrics->tmItalic = logfont->lfItalic;
296 metrics->tmUnderlined = logfont->lfUnderline;
297 metrics->tmStruckOut = logfont->lfStrikeOut;
298 metrics->tmFirstChar = xfont->min_char_or_byte2;
299 metrics->tmLastChar = xfont->max_char_or_byte2;
300 metrics->tmDefaultChar = xfont->default_char;
301 metrics->tmBreakChar = ' ';
302 metrics->tmCharSet = logfont->lfCharSet;
303 metrics->tmOverhang = 0;
304 metrics->tmDigitizedAspectX = 1;
305 metrics->tmDigitizedAspectY = 1;
306 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
307 if (logfont->lfPitchAndFamily & FIXED_PITCH)
308 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
310 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
311 else
313 XCharStruct * charPtr = xfont->per_char;
314 average = count = 0;
315 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
317 if (!CI_NONEXISTCHAR( charPtr ))
319 average += charPtr->width;
320 count++;
322 charPtr++;
324 if (count) average = (average + count/2) / count;
326 metrics->tmAveCharWidth = average;
329 /***********************************************************************
330 * GetGlyphOutLine (GDI.309)
332 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm,
333 DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2)
335 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
336 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
337 return (DWORD)-1; /* failure */
341 /***********************************************************************
342 * CreateScalableFontResource (GDI.310)
344 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
345 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
347 /* fHidden=1 - only visible for the calling app, read-only, not
348 * enumbered with EnumFonts/EnumFontFamilies
349 * lpszCurrentPath can be NULL
351 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
352 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
353 return FALSE; /* create failed */
357 /***********************************************************************
358 * CreateFontIndirect16 (GDI.57)
360 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
362 FONTOBJ * fontPtr;
363 HFONT16 hfont;
365 if (!font)
367 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
368 return 0;
370 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
371 if (!hfont) return 0;
372 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
373 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
374 AnsiLower( fontPtr->logfont.lfFaceName );
375 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
376 font, font->lfHeight, font->lfWidth, hfont);
377 return hfont;
381 /***********************************************************************
382 * CreateFontIndirect32A (GDI32.44)
384 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
386 LOGFONT16 font16;
388 font16.lfHeight = (INT16)font->lfHeight;
389 font16.lfWidth = (INT16)font->lfWidth;
390 font16.lfEscapement = (INT16)font->lfEscapement;
391 font16.lfOrientation = (INT16)font->lfOrientation;
392 font16.lfWeight = (INT16)font->lfWeight;
393 font16.lfItalic = font->lfItalic;
394 font16.lfUnderline = font->lfUnderline;
395 font16.lfStrikeOut = font->lfStrikeOut;
396 font16.lfCharSet = font->lfCharSet;
397 font16.lfOutPrecision = font->lfOutPrecision;
398 font16.lfClipPrecision = font->lfClipPrecision;
399 font16.lfQuality = font->lfQuality;
400 font16.lfPitchAndFamily = font->lfPitchAndFamily;
401 lstrcpyn32A( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
402 return CreateFontIndirect16( &font16 );
406 /***********************************************************************
407 * CreateFontIndirect32W (GDI32.45)
409 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
411 LOGFONT16 font16;
413 font16.lfHeight = (INT16)font->lfHeight;
414 font16.lfWidth = (INT16)font->lfWidth;
415 font16.lfEscapement = (INT16)font->lfEscapement;
416 font16.lfOrientation = (INT16)font->lfOrientation;
417 font16.lfWeight = (INT16)font->lfWeight;
418 font16.lfItalic = font->lfItalic;
419 font16.lfUnderline = font->lfUnderline;
420 font16.lfStrikeOut = font->lfStrikeOut;
421 font16.lfCharSet = font->lfCharSet;
422 font16.lfOutPrecision = font->lfOutPrecision;
423 font16.lfClipPrecision = font->lfClipPrecision;
424 font16.lfQuality = font->lfQuality;
425 font16.lfPitchAndFamily = font->lfPitchAndFamily;
426 lstrcpynWtoA( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
427 return CreateFontIndirect16( &font16 );
431 /***********************************************************************
432 * CreateFont16 (GDI.56)
434 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
435 INT16 weight, BYTE italic, BYTE underline,
436 BYTE strikeout, BYTE charset, BYTE outpres,
437 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
439 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
440 strikeout, charset, outpres, clippres, quality, pitch, };
441 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
442 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
443 else logfont.lfFaceName[0] = '\0';
444 return CreateFontIndirect16( &logfont );
449 /*************************************************************************
450 * CreateFont32A (GDI32.43)
452 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
453 INT32 weight, DWORD italic, DWORD underline,
454 DWORD strikeout, DWORD charset, DWORD outpres,
455 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
457 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
458 underline, strikeout, charset, outpres,
459 clippres, quality, pitch, name );
463 /*************************************************************************
464 * CreateFont32W (GDI32.46)
466 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
467 INT32 weight, DWORD italic, DWORD underline,
468 DWORD strikeout, DWORD charset, DWORD outpres,
469 DWORD clippres, DWORD quality, DWORD pitch,
470 LPCWSTR name )
472 LPSTR namea = name ? STRING32_DupUniToAnsi(name) : NULL;
473 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
474 italic, underline, strikeout, charset,
475 outpres, clippres, quality, pitch,
476 namea );
477 free(namea);
478 return ret;
482 /***********************************************************************
483 * FONT_GetObject16
485 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
487 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
488 memcpy( buffer, &font->logfont, count );
489 return count;
493 /***********************************************************************
494 * FONT_GetObject32A
496 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
498 LOGFONT32A fnt32;
500 memset(&fnt32, 0, sizeof(fnt32));
501 fnt32.lfHeight = font->logfont.lfHeight;
502 fnt32.lfWidth = font->logfont.lfWidth;
503 fnt32.lfEscapement = font->logfont.lfEscapement;
504 fnt32.lfOrientation = font->logfont.lfOrientation;
505 fnt32.lfWeight = font->logfont.lfWeight;
506 fnt32.lfItalic = font->logfont.lfItalic;
507 fnt32.lfUnderline = font->logfont.lfUnderline;
508 fnt32.lfStrikeOut = font->logfont.lfStrikeOut;
509 fnt32.lfCharSet = font->logfont.lfCharSet;
510 fnt32.lfOutPrecision = font->logfont.lfOutPrecision;
511 fnt32.lfClipPrecision = font->logfont.lfClipPrecision;
512 fnt32.lfQuality = font->logfont.lfQuality;
513 fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
514 strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
515 sizeof(fnt32.lfFaceName) );
517 if (count > sizeof(fnt32)) count = sizeof(fnt32);
518 memcpy( buffer, &fnt32, count );
519 return count;
523 /***********************************************************************
524 * FONT_SelectObject
526 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
528 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
530 static struct {
531 HFONT id;
532 LOGFONT16 logfont;
533 int access;
534 int used;
535 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
536 int i;
538 X_PHYSFONT * stockPtr;
539 HFONT prevHandle = dc->w.hFont;
540 XFontStruct * fontStruct;
541 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
543 #if 0 /* From the code in SelectObject, this can not happen */
544 /* Load font if necessary */
545 if (!font)
547 HFONT hnewfont;
549 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
550 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
551 DEFAULT_QUALITY, FF_DONTCARE, "*" );
552 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
554 #endif
556 if (dc->header.wMagic == METAFILE_DC_MAGIC)
557 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
558 return prevHandle;
559 else
560 return 0;
562 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
563 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
564 else {
565 stockPtr = NULL;
567 * Ok, It's not a stock font but
568 * may be it's cached in dynamic cache
570 for(i=0; i<FONTCACHE; i++) /* search for same handle */
571 if (cacheFonts[i].id==hfont) { /* Got the handle */
573 * Check if Handle matches the font
575 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
576 /* No: remove handle id from dynamic font cache */
577 cacheFonts[i].access=0;
578 cacheFonts[i].used=0;
579 cacheFonts[i].id=0;
580 /* may be there is an unused handle which contains the font */
581 for(i=0; i<FONTCACHE; i++) {
582 if((cacheFonts[i].used == 0) &&
583 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
584 /* got it load from cache and set new handle id */
585 stockPtr = &cacheFonts[i].cacheFont;
586 cacheFonts[i].access=1;
587 cacheFonts[i].used=1;
588 cacheFonts[i].id=hfont;
589 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
590 break;
595 else {
596 /* Yes: load from dynamic font cache */
597 stockPtr = &cacheFonts[i].cacheFont;
598 cacheFonts[i].access++;
599 cacheFonts[i].used++;
601 break;
604 if (!stockPtr || !stockPtr->fstruct)
606 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
608 /* If it is not a stock font, we can simply return 0 */
609 if (!stockPtr) return 0;
610 /* Otherwise we must try to find a substitute */
611 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
612 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
613 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
614 fontStruct = XLoadQueryFont( display, "fixed" );
615 if (!fontStruct)
617 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
618 exit( 1 );
622 else
624 fontStruct = stockPtr->fstruct;
625 dprintf_font(stddeb,
626 "FONT_SelectObject: Loaded font from cache %04x %p\n",
627 hfont, fontStruct );
630 /* Unuse previous font */
631 for (i=0; i < FONTCACHE; i++) {
632 if (cacheFonts[i].id == prevHandle) {
633 if(cacheFonts[i].used == 0)
634 fprintf(stderr, "Trying to decrement a use count of 0.\n");
635 else
636 cacheFonts[i].used--;
640 /* Store font */
641 dc->w.hFont = hfont;
642 if (stockPtr)
644 if (!stockPtr->fstruct)
646 stockPtr->fstruct = fontStruct;
647 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
649 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
651 else
654 * Check in cacheFont
656 cacheFontsMin=NULL;
657 for (i=0; i < FONTCACHE; i++) {
658 if (cacheFonts[i].used==0)
659 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
660 cacheFontsMin=&cacheFonts[i];
662 if (!cacheFontsMin) {
663 fprintf(stderr,"No unused font cache entry !!!!\n" );
664 return prevHandle;
666 if (cacheFontsMin->id!=0) {
667 dprintf_font(stddeb,
668 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
669 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
671 cacheFontsMin->cacheFont.fstruct = fontStruct;
672 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
673 cacheFontsMin->access=1;
674 cacheFontsMin->used=1;
675 cacheFontsMin->id=hfont;
676 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
677 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
680 return prevHandle;
684 /***********************************************************************
685 * GetTextCharacterExtra (GDI.89)
687 short GetTextCharacterExtra( HDC hdc )
689 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
690 if (!dc) return 0;
691 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
692 / dc->w.VportExtX );
696 /***********************************************************************
697 * SetTextCharacterExtra (GDI.8)
699 short SetTextCharacterExtra( HDC hdc, short extra )
701 short prev;
702 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
703 if (!dc) return 0;
704 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
705 prev = dc->w.charExtra;
706 dc->w.charExtra = abs(extra);
707 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
711 /***********************************************************************
712 * SetTextJustification (GDI.10)
714 short SetTextJustification( HDC hdc, short extra, short breaks )
716 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
717 if (!dc) return 0;
719 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
720 if (!extra) breaks = 0;
721 dc->w.breakTotalExtra = extra;
722 dc->w.breakCount = breaks;
723 if (breaks)
725 dc->w.breakExtra = extra / breaks;
726 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
728 else
730 dc->w.breakExtra = 0;
731 dc->w.breakRem = 0;
733 return 1;
737 /***********************************************************************
738 * GetTextFace (GDI.92)
740 INT GetTextFace( HDC hdc, INT count, LPSTR name )
742 FONTOBJ *font;
744 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
745 if (!dc) return 0;
746 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
747 return 0;
748 lstrcpyn32A( name, font->logfont.lfFaceName, count );
749 return strlen(name);
753 /***********************************************************************
754 * GetTextExtent (GDI.91)
756 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
758 SIZE16 size;
759 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
760 return MAKELONG( size.cx, size.cy );
764 /***********************************************************************
765 * GetTextExtentPoint16 (GDI.471)
767 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
769 SIZE32 size32;
770 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
771 CONV_SIZE32TO16( &size32, size );
772 return (BOOL16)ret;
776 /***********************************************************************
777 * GetTextExtentPoint32A (GDI32.232)
779 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
780 LPSIZE32 size )
782 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
783 if (!dc)
785 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
786 return FALSE;
789 if (!dc->funcs->pGetTextExtentPoint ||
790 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
791 return FALSE;
793 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
794 hdc, count, str, count, size, size->cx, size->cy );
795 return TRUE;
799 /***********************************************************************
800 * GetTextExtentPoint32W (GDI32.233)
802 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
803 LPSIZE32 size )
805 char *p = STRING32_DupUniToAnsi( str );
806 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
807 free( p );
808 return ret;
812 /***********************************************************************
813 * GetTextMetrics16 (GDI.93)
815 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
817 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
818 if (!dc) return FALSE;
819 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
821 metrics->tmAscent = abs( metrics->tmAscent
822 * dc->w.WndExtY / dc->w.VportExtY );
823 metrics->tmDescent = abs( metrics->tmDescent
824 * dc->w.WndExtY / dc->w.VportExtY );
825 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
826 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
827 * dc->w.WndExtY / dc->w.VportExtY );
828 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
829 * dc->w.WndExtY / dc->w.VportExtY );
830 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
831 * dc->w.WndExtX / dc->w.VportExtX );
832 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
833 * dc->w.WndExtX / dc->w.VportExtX );
835 dprintf_font(stdnimp,"text metrics:\n
836 InternalLeading = %i
837 ExternalLeading = %i
838 MaxCharWidth = %i
839 Weight = %i
840 Italic = %i
841 Underlined = %i
842 StruckOut = %i
843 FirstChar = %i
844 LastChar = %i
845 DefaultChar = %i
846 BreakChar = %i
847 CharSet = %i
848 Overhang = %i
849 DigitizedAspectX = %i
850 DigitizedAspectY = %i
851 AveCharWidth = %i
852 MaxCharWidth = %i
853 Ascent = %i
854 Descent = %i
855 Height = %i\n",
856 metrics->tmInternalLeading,
857 metrics->tmExternalLeading,
858 metrics->tmMaxCharWidth,
859 metrics->tmWeight,
860 metrics->tmItalic,
861 metrics->tmUnderlined,
862 metrics->tmStruckOut,
863 metrics->tmFirstChar,
864 metrics->tmLastChar,
865 metrics->tmDefaultChar,
866 metrics->tmBreakChar,
867 metrics->tmCharSet,
868 metrics->tmOverhang,
869 metrics->tmDigitizedAspectX,
870 metrics->tmDigitizedAspectY,
871 metrics->tmAveCharWidth,
872 metrics->tmMaxCharWidth,
873 metrics->tmAscent,
874 metrics->tmDescent,
875 metrics->tmHeight);
877 return TRUE;
881 /***********************************************************************
882 * GetTextMetrics32A (GDI32.236)
884 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
886 TEXTMETRIC16 tm;
887 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
888 metrics->tmHeight = tm.tmHeight;
889 metrics->tmAscent = tm.tmAscent;
890 metrics->tmDescent = tm.tmDescent;
891 metrics->tmInternalLeading = tm.tmInternalLeading;
892 metrics->tmExternalLeading = tm.tmExternalLeading;
893 metrics->tmAveCharWidth = tm.tmAveCharWidth;
894 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
895 metrics->tmWeight = tm.tmWeight;
896 metrics->tmOverhang = tm.tmOverhang;
897 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
898 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
899 metrics->tmFirstChar = tm.tmFirstChar;
900 metrics->tmLastChar = tm.tmLastChar;
901 metrics->tmDefaultChar = tm.tmDefaultChar;
902 metrics->tmBreakChar = tm.tmBreakChar;
903 metrics->tmItalic = tm.tmItalic;
904 metrics->tmUnderlined = tm.tmUnderlined;
905 metrics->tmStruckOut = tm.tmStruckOut;
906 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
907 metrics->tmCharSet = tm.tmCharSet;
908 return TRUE;
912 /***********************************************************************
913 * GetTextMetrics32W (GDI32.237)
915 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
917 TEXTMETRIC16 tm;
918 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
919 metrics->tmHeight = tm.tmHeight;
920 metrics->tmAscent = tm.tmAscent;
921 metrics->tmDescent = tm.tmDescent;
922 metrics->tmInternalLeading = tm.tmInternalLeading;
923 metrics->tmExternalLeading = tm.tmExternalLeading;
924 metrics->tmAveCharWidth = tm.tmAveCharWidth;
925 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
926 metrics->tmWeight = tm.tmWeight;
927 metrics->tmOverhang = tm.tmOverhang;
928 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
929 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
930 metrics->tmFirstChar = tm.tmFirstChar;
931 metrics->tmLastChar = tm.tmLastChar;
932 metrics->tmDefaultChar = tm.tmDefaultChar;
933 metrics->tmBreakChar = tm.tmBreakChar;
934 metrics->tmItalic = tm.tmItalic;
935 metrics->tmUnderlined = tm.tmUnderlined;
936 metrics->tmStruckOut = tm.tmStruckOut;
937 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
938 metrics->tmCharSet = tm.tmCharSet;
939 return TRUE;
943 /***********************************************************************
944 * SetMapperFlags (GDI.349)
946 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
948 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
949 hDC, dwFlag);
950 return 0L;
954 /***********************************************************************
955 * GetCharABCWidths (GDI.307)
957 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
960 /* No TrueType fonts in Wine so far */
962 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
963 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
965 return FALSE;
969 /***********************************************************************
970 * GetCharWidth (GDI.350)
972 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
974 int i, j;
975 XFontStruct *xfont;
976 XCharStruct *cs, *def;
978 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
979 if (!dc) return FALSE;
980 xfont = dc->u.x.font.fstruct;
982 /* fixed font? */
983 if (xfont->per_char == NULL)
985 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
986 *(lpBuffer + j) = xfont->max_bounds.width;
987 return TRUE;
990 CI_GET_DEFAULT_INFO(xfont, def);
992 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
994 CI_GET_CHAR_INFO(xfont, i, def, cs);
995 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
996 if (*(lpBuffer + j) < 0)
997 *(lpBuffer + j) = 0;
999 return TRUE;
1003 /***********************************************************************
1004 * AddFontResource (GDI.119)
1006 INT AddFontResource( LPCSTR str )
1008 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1009 return 1;
1013 /***********************************************************************
1014 * RemoveFontResource (GDI.136)
1016 BOOL RemoveFontResource( LPSTR str )
1018 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1019 return TRUE;
1023 /*************************************************************************
1024 * ParseFontParms [internal]
1026 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1028 int i;
1029 if (lpFont == NULL) return 0;
1030 if (lpRetStr == NULL) return 0;
1031 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1032 if (*lpFont == '-') i++;
1033 lpFont++;
1035 if (i == wParmsNo) {
1036 if (*lpFont == '-') lpFont++;
1037 wMaxSiz--;
1038 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1039 *(lpRetStr + i) = *lpFont++;
1040 *(lpRetStr + i) = '\0';
1041 return i;
1043 else
1044 lpRetStr[0] = '\0';
1045 return 0;
1049 /*************************************************************************
1050 * InitFontsList [internal]
1053 static int logfcmp(const void *a,const void *b)
1055 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1056 (*(LPLOGFONT16 *)b)->lfFaceName );
1059 void InitFontsList(void)
1061 char str[32];
1062 char pattern[100];
1063 char *family, *weight, *charset;
1064 char **names;
1065 char slant, spacing;
1066 int i, count;
1067 LPLOGFONT16 lpNewFont;
1069 dprintf_font(stddeb,"InitFontsList !\n");
1071 weight = "medium";
1072 slant = 'r';
1073 spacing = '*';
1074 charset = "*";
1075 family = "*-*";
1077 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1078 family, weight, slant, spacing, charset);
1079 names = XListFonts( display, pattern, MAX_FONTS, &count );
1080 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1082 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1083 if (lpNewFont == NULL) {
1084 dprintf_font(stddeb,
1085 "InitFontsList // Error alloc new font structure !\n");
1086 XFreeFontNames(names);
1087 return;
1090 for (i = 0; i < count; i++) {
1091 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1093 ParseFontParms(names[i], 2, str, sizeof(str));
1094 #if 0
1095 /* not necessary because new function FONT_ChkX11Family() */
1096 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1097 #endif
1098 AnsiUpper(str);
1099 strcpy(lpNewFont->lfFaceName, str);
1100 ParseFontParms(names[i], 8, str, sizeof(str));
1101 lpNewFont->lfHeight = atoi(str) / 10;
1102 ParseFontParms(names[i], 12, str, sizeof(str));
1103 lpNewFont->lfWidth = atoi(str) / 10;
1104 lpNewFont->lfEscapement = 0;
1105 lpNewFont->lfOrientation = 0;
1106 lpNewFont->lfWeight = FW_REGULAR;
1107 lpNewFont->lfItalic = 0;
1108 lpNewFont->lfUnderline = 0;
1109 lpNewFont->lfStrikeOut = 0;
1110 ParseFontParms(names[i], 13, str, sizeof(str));
1111 if (strcmp(str, "iso8859") == 0) {
1112 lpNewFont->lfCharSet = ANSI_CHARSET;
1113 } else {
1114 lpNewFont->lfCharSet = OEM_CHARSET;
1116 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1117 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1118 lpNewFont->lfQuality = DEFAULT_QUALITY;
1119 ParseFontParms(names[i], 11, str, sizeof(str));
1120 switch(str[0]) {
1121 case 'p':
1122 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1123 break;
1124 case 'm':
1125 case 'c':
1126 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1127 break;
1128 default:
1129 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1130 break;
1132 dprintf_font( stddeb,
1133 "InitFontsList // lpNewFont->lfHeight=%d\n",
1134 lpNewFont->lfHeight );
1135 dprintf_font( stddeb,
1136 "InitFontsList // lpNewFont->lfWidth=%d\n",
1137 lpNewFont->lfWidth );
1138 dprintf_font( stddeb,
1139 "InitFontsList // lfFaceName='%s'\n",
1140 lpNewFont->lfFaceName );
1141 lpLogFontList[i] = lpNewFont;
1142 lpNewFont = (LPLOGFONT16)
1143 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1145 lpLogFontList[i] = NULL;
1147 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1148 XFreeFontNames(names);
1152 /*************************************************************************
1153 * EnumFonts [GDI.70]
1155 INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1157 HANDLE hLog;
1158 HANDLE hMet;
1159 HFONT hFont;
1160 HFONT hOldFont;
1161 LPLOGFONT16 lpLogFont;
1162 LPTEXTMETRIC16 lptm;
1163 LPSTR lpOldName;
1164 char FaceName[LF_FACESIZE];
1165 int nRet = 0;
1166 int i;
1168 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
1169 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
1170 if (lpEnumFunc == 0) return 0;
1171 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
1172 lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1173 if (lpLogFont == NULL) {
1174 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
1175 return 0;
1177 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1178 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1179 if (lptm == NULL) {
1180 GDI_HEAP_FREE(hLog);
1181 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1182 return 0;
1184 if (lpFaceName != NULL) {
1185 strcpy(FaceName, lpFaceName);
1186 AnsiUpper(FaceName);
1188 lpOldName = NULL;
1190 if (lpLogFontList[0] == NULL) InitFontsList();
1191 for(i = 0; lpLogFontList[i] != NULL; i++) {
1192 if (lpFaceName == NULL) {
1193 if (lpOldName != NULL) {
1194 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1196 lpOldName = lpLogFontList[i]->lfFaceName;
1197 } else {
1198 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1200 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1201 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1202 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
1203 hFont = CreateFontIndirect16(lpLogFont);
1204 hOldFont = SelectObject(hDC, hFont);
1205 GetTextMetrics16(hDC, lptm);
1206 SelectObject(hDC, hOldFont);
1207 DeleteObject(hFont);
1208 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1209 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1210 0, (LONG)lpData );
1211 if (nRet == 0) {
1212 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1213 break;
1216 GDI_HEAP_FREE(hMet);
1217 GDI_HEAP_FREE(hLog);
1218 return nRet;
1222 /*************************************************************************
1223 * EnumFontFamilies [GDI.330]
1225 INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1227 HANDLE hLog;
1228 HANDLE hMet;
1229 HFONT hFont;
1230 HFONT hOldFont;
1231 LPENUMLOGFONT16 lpEnumLogFont;
1232 LPTEXTMETRIC16 lptm;
1233 LPSTR lpOldName;
1234 char FaceName[LF_FACESIZE];
1235 int nRet = 0;
1236 int i;
1238 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1239 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1240 if (lpEnumFunc == 0) return 0;
1241 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
1242 lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1243 if (lpEnumLogFont == NULL) {
1244 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1245 return 0;
1247 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1248 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1249 if (lptm == NULL) {
1250 GDI_HEAP_FREE(hLog);
1251 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1252 return 0;
1254 lpOldName = NULL;
1255 if (lpszFamily != NULL) {
1256 strcpy(FaceName, lpszFamily);
1257 AnsiUpper(FaceName);
1259 if (lpLogFontList[0] == NULL) InitFontsList();
1260 for(i = 0; lpLogFontList[i] != NULL; i++) {
1261 if (lpszFamily == NULL) {
1262 if (lpOldName != NULL) {
1263 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1265 lpOldName = lpLogFontList[i]->lfFaceName;
1266 } else {
1267 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1269 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1270 strcpy(lpEnumLogFont->elfFullName,"");
1271 strcpy(lpEnumLogFont->elfStyle,"");
1272 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1273 hOldFont = SelectObject(hDC, hFont);
1274 GetTextMetrics16(hDC, lptm);
1275 SelectObject(hDC, hOldFont);
1276 DeleteObject(hFont);
1277 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1279 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1280 0, lpData );
1281 if (nRet == 0) {
1282 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1283 break;
1286 GDI_HEAP_FREE(hMet);
1287 GDI_HEAP_FREE(hLog);
1288 return nRet;
1291 /*************************************************************************
1292 * GetRasterizerCaps [GDI.313]
1295 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1297 /* This is not much more than a dummy */
1298 RASTERIZER_STATUS rs;
1300 rs.nSize = sizeof(rs);
1301 rs.wFlags = 0;
1302 rs.nLanguageID = 0;
1303 return True;
1306 /*************************************************************************
1307 * GetKerningPairs [GDI.332]
1309 int GetKerningPairs(HDC hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1311 /* This has to be dealt with when proper font handling is in place
1313 * At this time kerning is ignored (set to 0)
1316 int i;
1317 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1318 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1319 return 0;