Release 961023
[wine/multimedia.git] / objects / font.c
blobd41a6e1b67d6b03339ba11bb97695a841bacce4f
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( HDC16 hdc, UINT uChar, UINT fuFormat,
334 LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPSTR lpBuffer,
335 LPMAT2 lpmat2)
337 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
338 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
339 return (DWORD)-1; /* failure */
343 /***********************************************************************
344 * CreateScalableFontResource (GDI.310)
346 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
347 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
349 /* fHidden=1 - only visible for the calling app, read-only, not
350 * enumbered with EnumFonts/EnumFontFamilies
351 * lpszCurrentPath can be NULL
353 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
354 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
355 return FALSE; /* create failed */
359 /***********************************************************************
360 * CreateFontIndirect16 (GDI.57)
362 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
364 FONTOBJ * fontPtr;
365 HFONT16 hfont;
367 if (!font)
369 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
370 return 0;
372 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
373 if (!hfont) return 0;
374 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
375 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
376 AnsiLower( fontPtr->logfont.lfFaceName );
377 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
378 font, font->lfHeight, font->lfWidth, hfont);
379 return hfont;
383 /***********************************************************************
384 * CreateFontIndirect32A (GDI32.44)
386 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
388 LOGFONT16 font16;
390 font16.lfHeight = (INT16)font->lfHeight;
391 font16.lfWidth = (INT16)font->lfWidth;
392 font16.lfEscapement = (INT16)font->lfEscapement;
393 font16.lfOrientation = (INT16)font->lfOrientation;
394 font16.lfWeight = (INT16)font->lfWeight;
395 font16.lfItalic = font->lfItalic;
396 font16.lfUnderline = font->lfUnderline;
397 font16.lfStrikeOut = font->lfStrikeOut;
398 font16.lfCharSet = font->lfCharSet;
399 font16.lfOutPrecision = font->lfOutPrecision;
400 font16.lfClipPrecision = font->lfClipPrecision;
401 font16.lfQuality = font->lfQuality;
402 font16.lfPitchAndFamily = font->lfPitchAndFamily;
403 lstrcpyn32A( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
404 return CreateFontIndirect16( &font16 );
408 /***********************************************************************
409 * CreateFontIndirect32W (GDI32.45)
411 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
413 LOGFONT16 font16;
415 font16.lfHeight = (INT16)font->lfHeight;
416 font16.lfWidth = (INT16)font->lfWidth;
417 font16.lfEscapement = (INT16)font->lfEscapement;
418 font16.lfOrientation = (INT16)font->lfOrientation;
419 font16.lfWeight = (INT16)font->lfWeight;
420 font16.lfItalic = font->lfItalic;
421 font16.lfUnderline = font->lfUnderline;
422 font16.lfStrikeOut = font->lfStrikeOut;
423 font16.lfCharSet = font->lfCharSet;
424 font16.lfOutPrecision = font->lfOutPrecision;
425 font16.lfClipPrecision = font->lfClipPrecision;
426 font16.lfQuality = font->lfQuality;
427 font16.lfPitchAndFamily = font->lfPitchAndFamily;
428 lstrcpynWtoA( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
429 return CreateFontIndirect16( &font16 );
433 /***********************************************************************
434 * CreateFont16 (GDI.56)
436 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
437 INT16 weight, BYTE italic, BYTE underline,
438 BYTE strikeout, BYTE charset, BYTE outpres,
439 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
441 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
442 strikeout, charset, outpres, clippres, quality, pitch, };
443 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
444 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
445 else logfont.lfFaceName[0] = '\0';
446 return CreateFontIndirect16( &logfont );
451 /*************************************************************************
452 * CreateFont32A (GDI32.43)
454 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
455 INT32 weight, DWORD italic, DWORD underline,
456 DWORD strikeout, DWORD charset, DWORD outpres,
457 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
459 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
460 underline, strikeout, charset, outpres,
461 clippres, quality, pitch, name );
465 /*************************************************************************
466 * CreateFont32W (GDI32.46)
468 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
469 INT32 weight, DWORD italic, DWORD underline,
470 DWORD strikeout, DWORD charset, DWORD outpres,
471 DWORD clippres, DWORD quality, DWORD pitch,
472 LPCWSTR name )
474 LPSTR namea = name ? STRING32_DupUniToAnsi(name) : NULL;
475 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
476 italic, underline, strikeout, charset,
477 outpres, clippres, quality, pitch,
478 namea );
479 free(namea);
480 return ret;
484 /***********************************************************************
485 * FONT_GetObject16
487 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
489 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
490 memcpy( buffer, &font->logfont, count );
491 return count;
495 /***********************************************************************
496 * FONT_GetObject32A
498 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
500 LOGFONT32A fnt32;
502 memset(&fnt32, 0, sizeof(fnt32));
503 fnt32.lfHeight = font->logfont.lfHeight;
504 fnt32.lfWidth = font->logfont.lfWidth;
505 fnt32.lfEscapement = font->logfont.lfEscapement;
506 fnt32.lfOrientation = font->logfont.lfOrientation;
507 fnt32.lfWeight = font->logfont.lfWeight;
508 fnt32.lfItalic = font->logfont.lfItalic;
509 fnt32.lfUnderline = font->logfont.lfUnderline;
510 fnt32.lfStrikeOut = font->logfont.lfStrikeOut;
511 fnt32.lfCharSet = font->logfont.lfCharSet;
512 fnt32.lfOutPrecision = font->logfont.lfOutPrecision;
513 fnt32.lfClipPrecision = font->logfont.lfClipPrecision;
514 fnt32.lfQuality = font->logfont.lfQuality;
515 fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
516 strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
517 sizeof(fnt32.lfFaceName) );
519 if (count > sizeof(fnt32)) count = sizeof(fnt32);
520 memcpy( buffer, &fnt32, count );
521 return count;
525 /***********************************************************************
526 * FONT_SelectObject
528 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
530 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
532 static struct {
533 HFONT16 id;
534 LOGFONT16 logfont;
535 int access;
536 int used;
537 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
538 int i;
540 X_PHYSFONT * stockPtr;
541 HFONT16 prevHandle = dc->w.hFont;
542 XFontStruct * fontStruct;
543 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
545 #if 0 /* From the code in SelectObject, this can not happen */
546 /* Load font if necessary */
547 if (!font)
549 HFONT16 hnewfont;
551 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
552 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
553 DEFAULT_QUALITY, FF_DONTCARE, "*" );
554 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
556 #endif
558 if (dc->header.wMagic == METAFILE_DC_MAGIC)
559 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
560 return prevHandle;
561 else
562 return 0;
564 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
565 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
566 else {
567 stockPtr = NULL;
569 * Ok, It's not a stock font but
570 * may be it's cached in dynamic cache
572 for(i=0; i<FONTCACHE; i++) /* search for same handle */
573 if (cacheFonts[i].id==hfont) { /* Got the handle */
575 * Check if Handle matches the font
577 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
578 /* No: remove handle id from dynamic font cache */
579 cacheFonts[i].access=0;
580 cacheFonts[i].used=0;
581 cacheFonts[i].id=0;
582 /* may be there is an unused handle which contains the font */
583 for(i=0; i<FONTCACHE; i++) {
584 if((cacheFonts[i].used == 0) &&
585 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
586 /* got it load from cache and set new handle id */
587 stockPtr = &cacheFonts[i].cacheFont;
588 cacheFonts[i].access=1;
589 cacheFonts[i].used=1;
590 cacheFonts[i].id=hfont;
591 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
592 break;
597 else {
598 /* Yes: load from dynamic font cache */
599 stockPtr = &cacheFonts[i].cacheFont;
600 cacheFonts[i].access++;
601 cacheFonts[i].used++;
603 break;
606 if (!stockPtr || !stockPtr->fstruct)
608 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
610 /* If it is not a stock font, we can simply return 0 */
611 if (!stockPtr) return 0;
612 /* Otherwise we must try to find a substitute */
613 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
614 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
615 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
616 fontStruct = XLoadQueryFont( display, "fixed" );
617 if (!fontStruct)
619 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
620 exit( 1 );
624 else
626 fontStruct = stockPtr->fstruct;
627 dprintf_font(stddeb,
628 "FONT_SelectObject: Loaded font from cache %04x %p\n",
629 hfont, fontStruct );
632 /* Unuse previous font */
633 for (i=0; i < FONTCACHE; i++) {
634 if (cacheFonts[i].id == prevHandle) {
635 if(cacheFonts[i].used == 0)
636 fprintf(stderr, "Trying to decrement a use count of 0.\n");
637 else
638 cacheFonts[i].used--;
642 /* Store font */
643 dc->w.hFont = hfont;
644 if (stockPtr)
646 if (!stockPtr->fstruct)
648 stockPtr->fstruct = fontStruct;
649 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
651 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
653 else
656 * Check in cacheFont
658 cacheFontsMin=NULL;
659 for (i=0; i < FONTCACHE; i++) {
660 if (cacheFonts[i].used==0)
661 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
662 cacheFontsMin=&cacheFonts[i];
664 if (!cacheFontsMin) {
665 fprintf(stderr,"No unused font cache entry !!!!\n" );
666 return prevHandle;
668 if (cacheFontsMin->id!=0) {
669 dprintf_font(stddeb,
670 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
671 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
673 cacheFontsMin->cacheFont.fstruct = fontStruct;
674 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
675 cacheFontsMin->access=1;
676 cacheFontsMin->used=1;
677 cacheFontsMin->id=hfont;
678 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
679 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
682 return prevHandle;
686 /***********************************************************************
687 * GetTextCharacterExtra (GDI.89)
689 short GetTextCharacterExtra( HDC16 hdc )
691 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
692 if (!dc) return 0;
693 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
694 / dc->w.VportExtX );
698 /***********************************************************************
699 * SetTextCharacterExtra (GDI.8)
701 short SetTextCharacterExtra( HDC16 hdc, short extra )
703 short prev;
704 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
705 if (!dc) return 0;
706 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
707 prev = dc->w.charExtra;
708 dc->w.charExtra = abs(extra);
709 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
713 /***********************************************************************
714 * SetTextJustification (GDI.10)
716 short SetTextJustification( HDC16 hdc, short extra, short breaks )
718 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
719 if (!dc) return 0;
721 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
722 if (!extra) breaks = 0;
723 dc->w.breakTotalExtra = extra;
724 dc->w.breakCount = breaks;
725 if (breaks)
727 dc->w.breakExtra = extra / breaks;
728 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
730 else
732 dc->w.breakExtra = 0;
733 dc->w.breakRem = 0;
735 return 1;
739 /***********************************************************************
740 * GetTextFace (GDI.92)
742 INT GetTextFace( HDC16 hdc, INT count, LPSTR name )
744 FONTOBJ *font;
746 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
747 if (!dc) return 0;
748 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
749 return 0;
750 lstrcpyn32A( name, font->logfont.lfFaceName, count );
751 return strlen(name);
755 /***********************************************************************
756 * GetTextExtent (GDI.91)
758 DWORD GetTextExtent( HDC16 hdc, LPCSTR str, short count )
760 SIZE16 size;
761 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
762 return MAKELONG( size.cx, size.cy );
766 /***********************************************************************
767 * GetTextExtentPoint16 (GDI.471)
769 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
771 SIZE32 size32;
772 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
773 CONV_SIZE32TO16( &size32, size );
774 return (BOOL16)ret;
778 /***********************************************************************
779 * GetTextExtentPoint32A (GDI32.232)
781 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
782 LPSIZE32 size )
784 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
785 if (!dc)
787 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
788 return FALSE;
791 if (!dc->funcs->pGetTextExtentPoint ||
792 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
793 return FALSE;
795 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
796 hdc, count, str, count, size, size->cx, size->cy );
797 return TRUE;
801 /***********************************************************************
802 * GetTextExtentPoint32W (GDI32.233)
804 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
805 LPSIZE32 size )
807 char *p = STRING32_DupUniToAnsi( str );
808 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
809 free( p );
810 return ret;
814 /***********************************************************************
815 * GetTextMetrics16 (GDI.93)
817 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
819 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
820 if (!dc) return FALSE;
821 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
823 metrics->tmAscent = abs( metrics->tmAscent
824 * dc->w.WndExtY / dc->w.VportExtY );
825 metrics->tmDescent = abs( metrics->tmDescent
826 * dc->w.WndExtY / dc->w.VportExtY );
827 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
828 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
829 * dc->w.WndExtY / dc->w.VportExtY );
830 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
831 * dc->w.WndExtY / dc->w.VportExtY );
832 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
833 * dc->w.WndExtX / dc->w.VportExtX );
834 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
835 * dc->w.WndExtX / dc->w.VportExtX );
837 dprintf_font(stdnimp,"text metrics:\n
838 InternalLeading = %i
839 ExternalLeading = %i
840 MaxCharWidth = %i
841 Weight = %i
842 Italic = %i
843 Underlined = %i
844 StruckOut = %i
845 FirstChar = %i
846 LastChar = %i
847 DefaultChar = %i
848 BreakChar = %i
849 CharSet = %i
850 Overhang = %i
851 DigitizedAspectX = %i
852 DigitizedAspectY = %i
853 AveCharWidth = %i
854 MaxCharWidth = %i
855 Ascent = %i
856 Descent = %i
857 Height = %i\n",
858 metrics->tmInternalLeading,
859 metrics->tmExternalLeading,
860 metrics->tmMaxCharWidth,
861 metrics->tmWeight,
862 metrics->tmItalic,
863 metrics->tmUnderlined,
864 metrics->tmStruckOut,
865 metrics->tmFirstChar,
866 metrics->tmLastChar,
867 metrics->tmDefaultChar,
868 metrics->tmBreakChar,
869 metrics->tmCharSet,
870 metrics->tmOverhang,
871 metrics->tmDigitizedAspectX,
872 metrics->tmDigitizedAspectY,
873 metrics->tmAveCharWidth,
874 metrics->tmMaxCharWidth,
875 metrics->tmAscent,
876 metrics->tmDescent,
877 metrics->tmHeight);
879 return TRUE;
883 /***********************************************************************
884 * GetTextMetrics32A (GDI32.236)
886 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
888 TEXTMETRIC16 tm;
889 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
890 metrics->tmHeight = tm.tmHeight;
891 metrics->tmAscent = tm.tmAscent;
892 metrics->tmDescent = tm.tmDescent;
893 metrics->tmInternalLeading = tm.tmInternalLeading;
894 metrics->tmExternalLeading = tm.tmExternalLeading;
895 metrics->tmAveCharWidth = tm.tmAveCharWidth;
896 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
897 metrics->tmWeight = tm.tmWeight;
898 metrics->tmOverhang = tm.tmOverhang;
899 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
900 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
901 metrics->tmFirstChar = tm.tmFirstChar;
902 metrics->tmLastChar = tm.tmLastChar;
903 metrics->tmDefaultChar = tm.tmDefaultChar;
904 metrics->tmBreakChar = tm.tmBreakChar;
905 metrics->tmItalic = tm.tmItalic;
906 metrics->tmUnderlined = tm.tmUnderlined;
907 metrics->tmStruckOut = tm.tmStruckOut;
908 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
909 metrics->tmCharSet = tm.tmCharSet;
910 return TRUE;
914 /***********************************************************************
915 * GetTextMetrics32W (GDI32.237)
917 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
919 TEXTMETRIC16 tm;
920 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
921 metrics->tmHeight = tm.tmHeight;
922 metrics->tmAscent = tm.tmAscent;
923 metrics->tmDescent = tm.tmDescent;
924 metrics->tmInternalLeading = tm.tmInternalLeading;
925 metrics->tmExternalLeading = tm.tmExternalLeading;
926 metrics->tmAveCharWidth = tm.tmAveCharWidth;
927 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
928 metrics->tmWeight = tm.tmWeight;
929 metrics->tmOverhang = tm.tmOverhang;
930 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
931 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
932 metrics->tmFirstChar = tm.tmFirstChar;
933 metrics->tmLastChar = tm.tmLastChar;
934 metrics->tmDefaultChar = tm.tmDefaultChar;
935 metrics->tmBreakChar = tm.tmBreakChar;
936 metrics->tmItalic = tm.tmItalic;
937 metrics->tmUnderlined = tm.tmUnderlined;
938 metrics->tmStruckOut = tm.tmStruckOut;
939 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
940 metrics->tmCharSet = tm.tmCharSet;
941 return TRUE;
945 /***********************************************************************
946 * SetMapperFlags (GDI.349)
948 DWORD SetMapperFlags(HDC16 hDC, DWORD dwFlag)
950 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
951 hDC, dwFlag);
952 return 0L;
956 /***********************************************************************
957 * GetCharABCWidths (GDI.307)
959 BOOL GetCharABCWidths(HDC16 hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
962 /* No TrueType fonts in Wine so far */
964 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
965 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
967 return FALSE;
971 /***********************************************************************
972 * GetCharWidth (GDI.350)
974 BOOL GetCharWidth(HDC16 hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
976 int i, j;
977 XFontStruct *xfont;
978 XCharStruct *cs, *def;
980 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
981 if (!dc) return FALSE;
982 xfont = dc->u.x.font.fstruct;
984 /* fixed font? */
985 if (xfont->per_char == NULL)
987 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
988 *(lpBuffer + j) = xfont->max_bounds.width;
989 return TRUE;
992 CI_GET_DEFAULT_INFO(xfont, def);
994 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
996 CI_GET_CHAR_INFO(xfont, i, def, cs);
997 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
998 if (*(lpBuffer + j) < 0)
999 *(lpBuffer + j) = 0;
1001 return TRUE;
1005 /***********************************************************************
1006 * AddFontResource (GDI.119)
1008 INT AddFontResource( LPCSTR str )
1010 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1011 return 1;
1015 /***********************************************************************
1016 * RemoveFontResource (GDI.136)
1018 BOOL RemoveFontResource( LPSTR str )
1020 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1021 return TRUE;
1025 /*************************************************************************
1026 * ParseFontParms [internal]
1028 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1030 int i;
1031 if (lpFont == NULL) return 0;
1032 if (lpRetStr == NULL) return 0;
1033 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1034 if (*lpFont == '-') i++;
1035 lpFont++;
1037 if (i == wParmsNo) {
1038 if (*lpFont == '-') lpFont++;
1039 wMaxSiz--;
1040 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1041 *(lpRetStr + i) = *lpFont++;
1042 *(lpRetStr + i) = '\0';
1043 return i;
1045 else
1046 lpRetStr[0] = '\0';
1047 return 0;
1051 /*************************************************************************
1052 * InitFontsList [internal]
1055 static int logfcmp(const void *a,const void *b)
1057 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1058 (*(LPLOGFONT16 *)b)->lfFaceName );
1061 void InitFontsList(void)
1063 char str[32];
1064 char pattern[100];
1065 char *family, *weight, *charset;
1066 char **names;
1067 char slant, spacing;
1068 int i, count;
1069 LPLOGFONT16 lpNewFont;
1071 dprintf_font(stddeb,"InitFontsList !\n");
1073 weight = "medium";
1074 slant = 'r';
1075 spacing = '*';
1076 charset = "*";
1077 family = "*-*";
1079 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1080 family, weight, slant, spacing, charset);
1081 names = XListFonts( display, pattern, MAX_FONTS, &count );
1082 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1084 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1085 if (lpNewFont == NULL) {
1086 dprintf_font(stddeb,
1087 "InitFontsList // Error alloc new font structure !\n");
1088 XFreeFontNames(names);
1089 return;
1092 for (i = 0; i < count; i++) {
1093 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1095 ParseFontParms(names[i], 2, str, sizeof(str));
1096 #if 0
1097 /* not necessary because new function FONT_ChkX11Family() */
1098 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1099 #endif
1100 AnsiUpper(str);
1101 strcpy(lpNewFont->lfFaceName, str);
1102 ParseFontParms(names[i], 8, str, sizeof(str));
1103 lpNewFont->lfHeight = atoi(str) / 10;
1104 ParseFontParms(names[i], 12, str, sizeof(str));
1105 lpNewFont->lfWidth = atoi(str) / 10;
1106 lpNewFont->lfEscapement = 0;
1107 lpNewFont->lfOrientation = 0;
1108 lpNewFont->lfWeight = FW_REGULAR;
1109 lpNewFont->lfItalic = 0;
1110 lpNewFont->lfUnderline = 0;
1111 lpNewFont->lfStrikeOut = 0;
1112 ParseFontParms(names[i], 13, str, sizeof(str));
1113 if (strcmp(str, "iso8859") == 0) {
1114 lpNewFont->lfCharSet = ANSI_CHARSET;
1115 } else {
1116 lpNewFont->lfCharSet = OEM_CHARSET;
1118 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1119 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1120 lpNewFont->lfQuality = DEFAULT_QUALITY;
1121 ParseFontParms(names[i], 11, str, sizeof(str));
1122 switch(str[0]) {
1123 case 'p':
1124 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1125 break;
1126 case 'm':
1127 case 'c':
1128 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1129 break;
1130 default:
1131 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1132 break;
1134 dprintf_font( stddeb,
1135 "InitFontsList // lpNewFont->lfHeight=%d\n",
1136 lpNewFont->lfHeight );
1137 dprintf_font( stddeb,
1138 "InitFontsList // lpNewFont->lfWidth=%d\n",
1139 lpNewFont->lfWidth );
1140 dprintf_font( stddeb,
1141 "InitFontsList // lfFaceName='%s'\n",
1142 lpNewFont->lfFaceName );
1143 lpLogFontList[i] = lpNewFont;
1144 lpNewFont = (LPLOGFONT16)
1145 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1147 lpLogFontList[i] = NULL;
1149 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1150 XFreeFontNames(names);
1154 /*************************************************************************
1155 * EnumFonts [GDI.70]
1157 INT EnumFonts(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1159 HLOCAL16 hLog;
1160 HLOCAL16 hMet;
1161 HFONT16 hFont;
1162 HFONT16 hOldFont;
1163 LPLOGFONT16 lpLogFont;
1164 LPTEXTMETRIC16 lptm;
1165 LPSTR lpOldName;
1166 char FaceName[LF_FACESIZE];
1167 int nRet = 0;
1168 int i;
1170 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
1171 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
1172 if (lpEnumFunc == 0) return 0;
1173 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
1174 lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1175 if (lpLogFont == NULL) {
1176 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
1177 return 0;
1179 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1180 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1181 if (lptm == NULL) {
1182 GDI_HEAP_FREE(hLog);
1183 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1184 return 0;
1186 if (lpFaceName != NULL) {
1187 strcpy(FaceName, lpFaceName);
1188 AnsiUpper(FaceName);
1190 lpOldName = NULL;
1192 if (lpLogFontList[0] == NULL) InitFontsList();
1193 for(i = 0; lpLogFontList[i] != NULL; i++) {
1194 if (lpFaceName == NULL) {
1195 if (lpOldName != NULL) {
1196 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1198 lpOldName = lpLogFontList[i]->lfFaceName;
1199 } else {
1200 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1202 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1203 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1204 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
1205 hFont = CreateFontIndirect16(lpLogFont);
1206 hOldFont = SelectObject(hDC, hFont);
1207 GetTextMetrics16(hDC, lptm);
1208 SelectObject(hDC, hOldFont);
1209 DeleteObject(hFont);
1210 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1211 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1212 0, (LONG)lpData );
1213 if (nRet == 0) {
1214 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1215 break;
1218 GDI_HEAP_FREE(hMet);
1219 GDI_HEAP_FREE(hLog);
1220 return nRet;
1224 /*************************************************************************
1225 * EnumFontFamilies [GDI.330]
1227 INT EnumFontFamilies(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1229 HLOCAL16 hLog;
1230 HLOCAL16 hMet;
1231 HFONT16 hFont;
1232 HFONT16 hOldFont;
1233 LPENUMLOGFONT16 lpEnumLogFont;
1234 LPTEXTMETRIC16 lptm;
1235 LPSTR lpOldName;
1236 char FaceName[LF_FACESIZE];
1237 int nRet = 0;
1238 int i;
1240 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1241 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1242 if (lpEnumFunc == 0) return 0;
1243 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
1244 lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1245 if (lpEnumLogFont == NULL) {
1246 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1247 return 0;
1249 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1250 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1251 if (lptm == NULL) {
1252 GDI_HEAP_FREE(hLog);
1253 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1254 return 0;
1256 lpOldName = NULL;
1257 if (lpszFamily != NULL) {
1258 strcpy(FaceName, lpszFamily);
1259 AnsiUpper(FaceName);
1261 if (lpLogFontList[0] == NULL) InitFontsList();
1262 for(i = 0; lpLogFontList[i] != NULL; i++) {
1263 if (lpszFamily == NULL) {
1264 if (lpOldName != NULL) {
1265 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1267 lpOldName = lpLogFontList[i]->lfFaceName;
1268 } else {
1269 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1271 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1272 strcpy(lpEnumLogFont->elfFullName,"");
1273 strcpy(lpEnumLogFont->elfStyle,"");
1274 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1275 hOldFont = SelectObject(hDC, hFont);
1276 GetTextMetrics16(hDC, lptm);
1277 SelectObject(hDC, hOldFont);
1278 DeleteObject(hFont);
1279 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1281 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1282 0, lpData );
1283 if (nRet == 0) {
1284 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1285 break;
1288 GDI_HEAP_FREE(hMet);
1289 GDI_HEAP_FREE(hLog);
1290 return nRet;
1293 /*************************************************************************
1294 * GetRasterizerCaps [GDI.313]
1297 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1299 /* This is not much more than a dummy */
1300 RASTERIZER_STATUS rs;
1302 rs.nSize = sizeof(rs);
1303 rs.wFlags = 0;
1304 rs.nLanguageID = 0;
1305 return True;
1308 /*************************************************************************
1309 * GetKerningPairs [GDI.332]
1311 int GetKerningPairs(HDC16 hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1313 /* This has to be dealt with when proper font handling is in place
1315 * At this time kerning is ignored (set to 0)
1318 int i;
1319 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1320 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1321 return 0;