Release 960902
[wine/multimedia.git] / objects / font.c
bloba63275457a40a196edac421660883c0239967c4c
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_CAP_HEIGHT, &prop ))
291 metrics->tmInternalLeading = xfont->ascent+xfont->descent-(INT16)prop;
293 metrics->tmExternalLeading = 0;
294 metrics->tmMaxCharWidth = xfont->max_bounds.width;
295 metrics->tmWeight = logfont->lfWeight;
296 metrics->tmItalic = logfont->lfItalic;
297 metrics->tmUnderlined = logfont->lfUnderline;
298 metrics->tmStruckOut = logfont->lfStrikeOut;
299 metrics->tmFirstChar = xfont->min_char_or_byte2;
300 metrics->tmLastChar = xfont->max_char_or_byte2;
301 metrics->tmDefaultChar = xfont->default_char;
302 metrics->tmBreakChar = ' ';
303 metrics->tmCharSet = logfont->lfCharSet;
304 metrics->tmOverhang = 0;
305 metrics->tmDigitizedAspectX = 1;
306 metrics->tmDigitizedAspectY = 1;
307 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
308 if (logfont->lfPitchAndFamily & FIXED_PITCH)
309 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
311 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
312 else
314 XCharStruct * charPtr = xfont->per_char;
315 average = count = 0;
316 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
318 if (!CI_NONEXISTCHAR( charPtr ))
320 average += charPtr->width;
321 count++;
323 charPtr++;
325 if (count) average = (average + count/2) / count;
327 metrics->tmAveCharWidth = average;
330 /***********************************************************************
331 * GetGlyphOutLine (GDI.309)
333 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm,
334 DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2)
336 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
337 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
338 return (DWORD)-1; /* failure */
342 /***********************************************************************
343 * CreateScalableFontResource (GDI.310)
345 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
346 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
348 /* fHidden=1 - only visible for the calling app, read-only, not
349 * enumbered with EnumFonts/EnumFontFamilies
350 * lpszCurrentPath can be NULL
352 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
353 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
354 return FALSE; /* create failed */
358 /***********************************************************************
359 * CreateFontIndirect16 (GDI.57)
361 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
363 FONTOBJ * fontPtr;
364 HFONT16 hfont;
366 if (!font)
368 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
369 return 0;
371 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
372 if (!hfont) return 0;
373 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
374 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
375 AnsiLower( fontPtr->logfont.lfFaceName );
376 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
377 font, font->lfHeight, font->lfWidth, hfont);
378 return hfont;
382 /***********************************************************************
383 * CreateFontIndirect32A (GDI32.44)
385 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
387 LOGFONT16 font16;
389 font16.lfHeight = (INT16)font->lfHeight;
390 font16.lfWidth = (INT16)font->lfWidth;
391 font16.lfEscapement = (INT16)font->lfEscapement;
392 font16.lfOrientation = (INT16)font->lfOrientation;
393 font16.lfWeight = (INT16)font->lfWeight;
394 font16.lfItalic = font->lfItalic;
395 font16.lfUnderline = font->lfUnderline;
396 font16.lfStrikeOut = font->lfStrikeOut;
397 font16.lfCharSet = font->lfCharSet;
398 font16.lfOutPrecision = font->lfOutPrecision;
399 font16.lfClipPrecision = font->lfClipPrecision;
400 font16.lfQuality = font->lfQuality;
401 font16.lfPitchAndFamily = font->lfPitchAndFamily;
402 lstrcpyn32A( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
403 return CreateFontIndirect16( &font16 );
407 /***********************************************************************
408 * CreateFontIndirect32W (GDI32.45)
410 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
412 LOGFONT16 font16;
414 font16.lfHeight = (INT16)font->lfHeight;
415 font16.lfWidth = (INT16)font->lfWidth;
416 font16.lfEscapement = (INT16)font->lfEscapement;
417 font16.lfOrientation = (INT16)font->lfOrientation;
418 font16.lfWeight = (INT16)font->lfWeight;
419 font16.lfItalic = font->lfItalic;
420 font16.lfUnderline = font->lfUnderline;
421 font16.lfStrikeOut = font->lfStrikeOut;
422 font16.lfCharSet = font->lfCharSet;
423 font16.lfOutPrecision = font->lfOutPrecision;
424 font16.lfClipPrecision = font->lfClipPrecision;
425 font16.lfQuality = font->lfQuality;
426 font16.lfPitchAndFamily = font->lfPitchAndFamily;
427 lstrcpynWtoA( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
428 return CreateFontIndirect16( &font16 );
432 /***********************************************************************
433 * CreateFont16 (GDI.56)
435 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
436 INT16 weight, BYTE italic, BYTE underline,
437 BYTE strikeout, BYTE charset, BYTE outpres,
438 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
440 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
441 strikeout, charset, outpres, clippres, quality, pitch, };
442 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
443 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
444 else logfont.lfFaceName[0] = '\0';
445 return CreateFontIndirect16( &logfont );
450 /*************************************************************************
451 * CreateFont32A (GDI32.43)
453 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
454 INT32 weight, DWORD italic, DWORD underline,
455 DWORD strikeout, DWORD charset, DWORD outpres,
456 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
458 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
459 underline, strikeout, charset, outpres,
460 clippres, quality, pitch, name );
464 /*************************************************************************
465 * CreateFont32W (GDI32.46)
467 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
468 INT32 weight, DWORD italic, DWORD underline,
469 DWORD strikeout, DWORD charset, DWORD outpres,
470 DWORD clippres, DWORD quality, DWORD pitch,
471 LPCWSTR name )
473 LPSTR namea = name ? STRING32_DupUniToAnsi(name) : NULL;
474 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
475 italic, underline, strikeout, charset,
476 outpres, clippres, quality, pitch,
477 namea );
478 free(namea);
479 return ret;
483 /***********************************************************************
484 * FONT_GetObject16
486 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
488 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
489 memcpy( buffer, &font->logfont, count );
490 return count;
494 /***********************************************************************
495 * FONT_GetObject32A
497 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
499 LOGFONT32A fnt32;
501 memset(&fnt32, 0, sizeof(fnt32));
502 fnt32.lfHeight = font->logfont.lfHeight;
503 fnt32.lfWidth = font->logfont.lfWidth;
504 fnt32.lfEscapement = font->logfont.lfEscapement;
505 fnt32.lfOrientation = font->logfont.lfOrientation;
506 fnt32.lfWeight = font->logfont.lfWeight;
507 fnt32.lfItalic = font->logfont.lfItalic;
508 fnt32.lfUnderline = font->logfont.lfUnderline;
509 fnt32.lfStrikeOut = font->logfont.lfStrikeOut;
510 fnt32.lfCharSet = font->logfont.lfCharSet;
511 fnt32.lfOutPrecision = font->logfont.lfOutPrecision;
512 fnt32.lfClipPrecision = font->logfont.lfClipPrecision;
513 fnt32.lfQuality = font->logfont.lfQuality;
514 fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
515 strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
516 sizeof(fnt32.lfFaceName) );
518 if (count > sizeof(fnt32)) count = sizeof(fnt32);
519 memcpy( buffer, &fnt32, count );
520 return count;
524 /***********************************************************************
525 * FONT_SelectObject
527 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
529 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
531 static struct {
532 HFONT id;
533 LOGFONT16 logfont;
534 int access;
535 int used;
536 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
537 int i;
539 X_PHYSFONT * stockPtr;
540 HFONT prevHandle = dc->w.hFont;
541 XFontStruct * fontStruct;
542 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
544 #if 0 /* From the code in SelectObject, this can not happen */
545 /* Load font if necessary */
546 if (!font)
548 HFONT hnewfont;
550 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
551 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
552 DEFAULT_QUALITY, FF_DONTCARE, "*" );
553 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
555 #endif
557 if (dc->header.wMagic == METAFILE_DC_MAGIC)
558 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
559 return prevHandle;
560 else
561 return 0;
563 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
564 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
565 else {
566 stockPtr = NULL;
568 * Ok, It's not a stock font but
569 * may be it's cached in dynamic cache
571 for(i=0; i<FONTCACHE; i++) /* search for same handle */
572 if (cacheFonts[i].id==hfont) { /* Got the handle */
574 * Check if Handle matches the font
576 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
577 /* No: remove handle id from dynamic font cache */
578 cacheFonts[i].access=0;
579 cacheFonts[i].used=0;
580 cacheFonts[i].id=0;
581 /* may be there is an unused handle which contains the font */
582 for(i=0; i<FONTCACHE; i++) {
583 if((cacheFonts[i].used == 0) &&
584 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
585 /* got it load from cache and set new handle id */
586 stockPtr = &cacheFonts[i].cacheFont;
587 cacheFonts[i].access=1;
588 cacheFonts[i].used=1;
589 cacheFonts[i].id=hfont;
590 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
591 break;
596 else {
597 /* Yes: load from dynamic font cache */
598 stockPtr = &cacheFonts[i].cacheFont;
599 cacheFonts[i].access++;
600 cacheFonts[i].used++;
602 break;
605 if (!stockPtr || !stockPtr->fstruct)
607 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
609 /* If it is not a stock font, we can simply return 0 */
610 if (!stockPtr) return 0;
611 /* Otherwise we must try to find a substitute */
612 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
613 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
614 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
615 fontStruct = XLoadQueryFont( display, "fixed" );
616 if (!fontStruct)
618 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
619 exit( 1 );
623 else
625 fontStruct = stockPtr->fstruct;
626 dprintf_font(stddeb,
627 "FONT_SelectObject: Loaded font from cache %04x %p\n",
628 hfont, fontStruct );
631 /* Unuse previous font */
632 for (i=0; i < FONTCACHE; i++) {
633 if (cacheFonts[i].id == prevHandle) {
634 if(cacheFonts[i].used == 0)
635 fprintf(stderr, "Trying to decrement a use count of 0.\n");
636 else
637 cacheFonts[i].used--;
641 /* Store font */
642 dc->w.hFont = hfont;
643 if (stockPtr)
645 if (!stockPtr->fstruct)
647 stockPtr->fstruct = fontStruct;
648 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
650 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
652 else
655 * Check in cacheFont
657 cacheFontsMin=NULL;
658 for (i=0; i < FONTCACHE; i++) {
659 if (cacheFonts[i].used==0)
660 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
661 cacheFontsMin=&cacheFonts[i];
663 if (!cacheFontsMin) {
664 fprintf(stderr,"No unused font cache entry !!!!\n" );
665 return prevHandle;
667 if (cacheFontsMin->id!=0) {
668 dprintf_font(stddeb,
669 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
670 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
672 cacheFontsMin->cacheFont.fstruct = fontStruct;
673 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
674 cacheFontsMin->access=1;
675 cacheFontsMin->used=1;
676 cacheFontsMin->id=hfont;
677 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
678 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
681 return prevHandle;
685 /***********************************************************************
686 * GetTextCharacterExtra (GDI.89)
688 short GetTextCharacterExtra( HDC hdc )
690 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
691 if (!dc) return 0;
692 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
693 / dc->w.VportExtX );
697 /***********************************************************************
698 * SetTextCharacterExtra (GDI.8)
700 short SetTextCharacterExtra( HDC hdc, short extra )
702 short prev;
703 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
704 if (!dc) return 0;
705 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
706 prev = dc->w.charExtra;
707 dc->w.charExtra = abs(extra);
708 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
712 /***********************************************************************
713 * SetTextJustification (GDI.10)
715 short SetTextJustification( HDC hdc, short extra, short breaks )
717 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
718 if (!dc) return 0;
720 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
721 if (!extra) breaks = 0;
722 dc->w.breakTotalExtra = extra;
723 dc->w.breakCount = breaks;
724 if (breaks)
726 dc->w.breakExtra = extra / breaks;
727 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
729 else
731 dc->w.breakExtra = 0;
732 dc->w.breakRem = 0;
734 return 1;
738 /***********************************************************************
739 * GetTextFace (GDI.92)
741 INT GetTextFace( HDC hdc, INT count, LPSTR name )
743 FONTOBJ *font;
745 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
746 if (!dc) return 0;
747 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
748 return 0;
749 lstrcpyn32A( name, font->logfont.lfFaceName, count );
750 return strlen(name);
754 /***********************************************************************
755 * GetTextExtent (GDI.91)
757 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
759 SIZE16 size;
760 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
761 return MAKELONG( size.cx, size.cy );
765 /***********************************************************************
766 * GetTextExtentPoint16 (GDI.471)
768 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
770 SIZE32 size32;
771 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
772 CONV_SIZE32TO16( &size32, size );
773 return (BOOL16)ret;
777 /***********************************************************************
778 * GetTextExtentPoint32A (GDI32.232)
780 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
781 LPSIZE32 size )
783 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
784 if (!dc)
786 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
787 return FALSE;
790 if (!dc->funcs->pGetTextExtentPoint ||
791 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
792 return FALSE;
794 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
795 hdc, count, str, count, size, size->cx, size->cy );
796 return TRUE;
800 /***********************************************************************
801 * GetTextExtentPoint32W (GDI32.233)
803 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
804 LPSIZE32 size )
806 char *p = STRING32_DupUniToAnsi( str );
807 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
808 free( p );
809 return ret;
813 /***********************************************************************
814 * GetTextMetrics16 (GDI.93)
816 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
818 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
819 if (!dc) return FALSE;
820 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
822 metrics->tmAscent = abs( metrics->tmAscent
823 * dc->w.WndExtY / dc->w.VportExtY );
824 metrics->tmDescent = abs( metrics->tmDescent
825 * dc->w.WndExtY / dc->w.VportExtY );
826 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
827 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
828 * dc->w.WndExtY / dc->w.VportExtY );
829 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
830 * dc->w.WndExtY / dc->w.VportExtY );
831 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
832 * dc->w.WndExtX / dc->w.VportExtX );
833 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
834 * dc->w.WndExtX / dc->w.VportExtX );
836 dprintf_font(stdnimp,"text metrics:\n
837 InternalLeading = %i
838 ExternalLeading = %i
839 MaxCharWidth = %i
840 Weight = %i
841 Italic = %i
842 Underlined = %i
843 StruckOut = %i
844 FirstChar = %i
845 LastChar = %i
846 DefaultChar = %i
847 BreakChar = %i
848 CharSet = %i
849 Overhang = %i
850 DigitizedAspectX = %i
851 DigitizedAspectY = %i
852 AveCharWidth = %i
853 MaxCharWidth = %i
854 Ascent = %i
855 Descent = %i
856 Height = %i\n",
857 metrics->tmInternalLeading,
858 metrics->tmExternalLeading,
859 metrics->tmMaxCharWidth,
860 metrics->tmWeight,
861 metrics->tmItalic,
862 metrics->tmUnderlined,
863 metrics->tmStruckOut,
864 metrics->tmFirstChar,
865 metrics->tmLastChar,
866 metrics->tmDefaultChar,
867 metrics->tmBreakChar,
868 metrics->tmCharSet,
869 metrics->tmOverhang,
870 metrics->tmDigitizedAspectX,
871 metrics->tmDigitizedAspectY,
872 metrics->tmAveCharWidth,
873 metrics->tmMaxCharWidth,
874 metrics->tmAscent,
875 metrics->tmDescent,
876 metrics->tmHeight);
878 return TRUE;
882 /***********************************************************************
883 * GetTextMetrics32A (GDI32.236)
885 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
887 TEXTMETRIC16 tm;
888 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
889 metrics->tmHeight = tm.tmHeight;
890 metrics->tmAscent = tm.tmAscent;
891 metrics->tmDescent = tm.tmDescent;
892 metrics->tmInternalLeading = tm.tmInternalLeading;
893 metrics->tmExternalLeading = tm.tmExternalLeading;
894 metrics->tmAveCharWidth = tm.tmAveCharWidth;
895 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
896 metrics->tmWeight = tm.tmWeight;
897 metrics->tmOverhang = tm.tmOverhang;
898 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
899 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
900 metrics->tmFirstChar = tm.tmFirstChar;
901 metrics->tmLastChar = tm.tmLastChar;
902 metrics->tmDefaultChar = tm.tmDefaultChar;
903 metrics->tmBreakChar = tm.tmBreakChar;
904 metrics->tmItalic = tm.tmItalic;
905 metrics->tmUnderlined = tm.tmUnderlined;
906 metrics->tmStruckOut = tm.tmStruckOut;
907 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
908 metrics->tmCharSet = tm.tmCharSet;
909 return TRUE;
913 /***********************************************************************
914 * GetTextMetrics32W (GDI32.237)
916 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
918 TEXTMETRIC16 tm;
919 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
920 metrics->tmHeight = tm.tmHeight;
921 metrics->tmAscent = tm.tmAscent;
922 metrics->tmDescent = tm.tmDescent;
923 metrics->tmInternalLeading = tm.tmInternalLeading;
924 metrics->tmExternalLeading = tm.tmExternalLeading;
925 metrics->tmAveCharWidth = tm.tmAveCharWidth;
926 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
927 metrics->tmWeight = tm.tmWeight;
928 metrics->tmOverhang = tm.tmOverhang;
929 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
930 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
931 metrics->tmFirstChar = tm.tmFirstChar;
932 metrics->tmLastChar = tm.tmLastChar;
933 metrics->tmDefaultChar = tm.tmDefaultChar;
934 metrics->tmBreakChar = tm.tmBreakChar;
935 metrics->tmItalic = tm.tmItalic;
936 metrics->tmUnderlined = tm.tmUnderlined;
937 metrics->tmStruckOut = tm.tmStruckOut;
938 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
939 metrics->tmCharSet = tm.tmCharSet;
940 return TRUE;
944 /***********************************************************************
945 * SetMapperFlags (GDI.349)
947 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
949 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
950 hDC, dwFlag);
951 return 0L;
955 /***********************************************************************
956 * GetCharABCWidths (GDI.307)
958 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
961 /* No TrueType fonts in Wine so far */
963 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
964 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
966 return FALSE;
970 /***********************************************************************
971 * GetCharWidth (GDI.350)
973 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
975 int i, j;
976 XFontStruct *xfont;
977 XCharStruct *cs, *def;
979 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
980 if (!dc) return FALSE;
981 xfont = dc->u.x.font.fstruct;
983 /* fixed font? */
984 if (xfont->per_char == NULL)
986 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
987 *(lpBuffer + j) = xfont->max_bounds.width;
988 return TRUE;
991 CI_GET_DEFAULT_INFO(xfont, def);
993 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
995 CI_GET_CHAR_INFO(xfont, i, def, cs);
996 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
997 if (*(lpBuffer + j) < 0)
998 *(lpBuffer + j) = 0;
1000 return TRUE;
1004 /***********************************************************************
1005 * AddFontResource (GDI.119)
1007 INT AddFontResource( LPCSTR str )
1009 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1010 return 1;
1014 /***********************************************************************
1015 * RemoveFontResource (GDI.136)
1017 BOOL RemoveFontResource( LPSTR str )
1019 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1020 return TRUE;
1024 /*************************************************************************
1025 * ParseFontParms [internal]
1027 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1029 int i;
1030 if (lpFont == NULL) return 0;
1031 if (lpRetStr == NULL) return 0;
1032 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1033 if (*lpFont == '-') i++;
1034 lpFont++;
1036 if (i == wParmsNo) {
1037 if (*lpFont == '-') lpFont++;
1038 wMaxSiz--;
1039 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1040 *(lpRetStr + i) = *lpFont++;
1041 *(lpRetStr + i) = '\0';
1042 return i;
1044 else
1045 lpRetStr[0] = '\0';
1046 return 0;
1050 /*************************************************************************
1051 * InitFontsList [internal]
1054 static int logfcmp(const void *a,const void *b)
1056 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1057 (*(LPLOGFONT16 *)b)->lfFaceName );
1060 void InitFontsList(void)
1062 char str[32];
1063 char pattern[100];
1064 char *family, *weight, *charset;
1065 char **names;
1066 char slant, spacing;
1067 int i, count;
1068 LPLOGFONT16 lpNewFont;
1070 dprintf_font(stddeb,"InitFontsList !\n");
1072 weight = "medium";
1073 slant = 'r';
1074 spacing = '*';
1075 charset = "*";
1076 family = "*-*";
1078 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1079 family, weight, slant, spacing, charset);
1080 names = XListFonts( display, pattern, MAX_FONTS, &count );
1081 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1083 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1084 if (lpNewFont == NULL) {
1085 dprintf_font(stddeb,
1086 "InitFontsList // Error alloc new font structure !\n");
1087 XFreeFontNames(names);
1088 return;
1091 for (i = 0; i < count; i++) {
1092 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1094 ParseFontParms(names[i], 2, str, sizeof(str));
1095 #if 0
1096 /* not necessary because new function FONT_ChkX11Family() */
1097 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1098 #endif
1099 AnsiUpper(str);
1100 strcpy(lpNewFont->lfFaceName, str);
1101 ParseFontParms(names[i], 8, str, sizeof(str));
1102 lpNewFont->lfHeight = atoi(str) / 10;
1103 ParseFontParms(names[i], 12, str, sizeof(str));
1104 lpNewFont->lfWidth = atoi(str) / 10;
1105 lpNewFont->lfEscapement = 0;
1106 lpNewFont->lfOrientation = 0;
1107 lpNewFont->lfWeight = FW_REGULAR;
1108 lpNewFont->lfItalic = 0;
1109 lpNewFont->lfUnderline = 0;
1110 lpNewFont->lfStrikeOut = 0;
1111 ParseFontParms(names[i], 13, str, sizeof(str));
1112 if (strcmp(str, "iso8859") == 0) {
1113 lpNewFont->lfCharSet = ANSI_CHARSET;
1114 } else {
1115 lpNewFont->lfCharSet = OEM_CHARSET;
1117 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1118 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1119 lpNewFont->lfQuality = DEFAULT_QUALITY;
1120 ParseFontParms(names[i], 11, str, sizeof(str));
1121 switch(str[0]) {
1122 case 'p':
1123 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1124 break;
1125 case 'm':
1126 case 'c':
1127 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1128 break;
1129 default:
1130 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1131 break;
1133 dprintf_font( stddeb,
1134 "InitFontsList // lpNewFont->lfHeight=%d\n",
1135 lpNewFont->lfHeight );
1136 dprintf_font( stddeb,
1137 "InitFontsList // lpNewFont->lfWidth=%d\n",
1138 lpNewFont->lfWidth );
1139 dprintf_font( stddeb,
1140 "InitFontsList // lfFaceName='%s'\n",
1141 lpNewFont->lfFaceName );
1142 lpLogFontList[i] = lpNewFont;
1143 lpNewFont = (LPLOGFONT16)
1144 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1146 lpLogFontList[i] = NULL;
1148 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1149 XFreeFontNames(names);
1153 /*************************************************************************
1154 * EnumFonts [GDI.70]
1156 INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1158 HANDLE hLog;
1159 HANDLE hMet;
1160 HFONT hFont;
1161 HFONT hOldFont;
1162 LPLOGFONT16 lpLogFont;
1163 LPTEXTMETRIC16 lptm;
1164 LPSTR lpOldName;
1165 char FaceName[LF_FACESIZE];
1166 int nRet = 0;
1167 int i;
1169 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
1170 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
1171 if (lpEnumFunc == 0) return 0;
1172 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
1173 lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1174 if (lpLogFont == NULL) {
1175 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
1176 return 0;
1178 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1179 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1180 if (lptm == NULL) {
1181 GDI_HEAP_FREE(hLog);
1182 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1183 return 0;
1185 if (lpFaceName != NULL) {
1186 strcpy(FaceName, lpFaceName);
1187 AnsiUpper(FaceName);
1189 lpOldName = NULL;
1191 if (lpLogFontList[0] == NULL) InitFontsList();
1192 for(i = 0; lpLogFontList[i] != NULL; i++) {
1193 if (lpFaceName == NULL) {
1194 if (lpOldName != NULL) {
1195 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1197 lpOldName = lpLogFontList[i]->lfFaceName;
1198 } else {
1199 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1201 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1202 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1203 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
1204 hFont = CreateFontIndirect16(lpLogFont);
1205 hOldFont = SelectObject(hDC, hFont);
1206 GetTextMetrics16(hDC, lptm);
1207 SelectObject(hDC, hOldFont);
1208 DeleteObject(hFont);
1209 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1210 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1211 0, (LONG)lpData );
1212 if (nRet == 0) {
1213 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1214 break;
1217 GDI_HEAP_FREE(hMet);
1218 GDI_HEAP_FREE(hLog);
1219 return nRet;
1223 /*************************************************************************
1224 * EnumFontFamilies [GDI.330]
1226 INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1228 HANDLE hLog;
1229 HANDLE hMet;
1230 HFONT hFont;
1231 HFONT hOldFont;
1232 LPENUMLOGFONT16 lpEnumLogFont;
1233 LPTEXTMETRIC16 lptm;
1234 LPSTR lpOldName;
1235 char FaceName[LF_FACESIZE];
1236 int nRet = 0;
1237 int i;
1239 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1240 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1241 if (lpEnumFunc == 0) return 0;
1242 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
1243 lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1244 if (lpEnumLogFont == NULL) {
1245 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1246 return 0;
1248 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1249 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1250 if (lptm == NULL) {
1251 GDI_HEAP_FREE(hLog);
1252 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1253 return 0;
1255 lpOldName = NULL;
1256 if (lpszFamily != NULL) {
1257 strcpy(FaceName, lpszFamily);
1258 AnsiUpper(FaceName);
1260 if (lpLogFontList[0] == NULL) InitFontsList();
1261 for(i = 0; lpLogFontList[i] != NULL; i++) {
1262 if (lpszFamily == NULL) {
1263 if (lpOldName != NULL) {
1264 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1266 lpOldName = lpLogFontList[i]->lfFaceName;
1267 } else {
1268 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1270 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1271 strcpy(lpEnumLogFont->elfFullName,"");
1272 strcpy(lpEnumLogFont->elfStyle,"");
1273 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1274 hOldFont = SelectObject(hDC, hFont);
1275 GetTextMetrics16(hDC, lptm);
1276 SelectObject(hDC, hOldFont);
1277 DeleteObject(hFont);
1278 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1280 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1281 0, lpData );
1282 if (nRet == 0) {
1283 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1284 break;
1287 GDI_HEAP_FREE(hMet);
1288 GDI_HEAP_FREE(hLog);
1289 return nRet;
1292 /*************************************************************************
1293 * GetRasterizerCaps [GDI.313]
1296 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1298 /* This is not much more than a dummy */
1299 RASTERIZER_STATUS rs;
1301 rs.nSize = sizeof(rs);
1302 rs.wFlags = 0;
1303 rs.nLanguageID = 0;
1304 return True;
1307 /*************************************************************************
1308 * GetKerningPairs [GDI.332]
1310 int GetKerningPairs(HDC hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1312 /* This has to be dealt with when proper font handling is in place
1314 * At this time kerning is ignored (set to 0)
1317 int i;
1318 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1319 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1320 return 0;