Release 960717
[wine.git] / objects / font.c
blobfb4e2346528d0524bab39b269d4934cbecbdd0cb
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 "callback.h"
19 #include "options.h"
20 #include "string32.h"
21 #include "xmalloc.h"
22 #include "stddebug.h"
23 #include "debug.h"
25 #define FONTCACHE 32 /* dynamic font cache size */
26 #define MAX_FONTS 256
27 static LPLOGFONT16 lpLogFontList[MAX_FONTS+1];
29 static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
31 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
32 (((cs)->rbearing|(cs)->lbearing| \
33 (cs)->ascent|(cs)->descent) == 0))
35 /*
36 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
37 * character. If the character is in the column and exists, then return the
38 * appropriate metrics (note that fonts with common per-character metrics will
39 * return min_bounds). If none of these hold true, try again with the default
40 * char.
42 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
43 { \
44 cs = def; \
45 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
46 if (fs->per_char == NULL) { \
47 cs = &fs->min_bounds; \
48 } else { \
49 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
50 if (CI_NONEXISTCHAR(cs)) cs = def; \
51 } \
52 } \
55 #define CI_GET_DEFAULT_INFO(fs,cs) \
56 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
58 struct FontStructure {
59 char *window;
60 char *x11;
61 } FontNames[32];
62 int FontSize;
65 /***********************************************************************
66 * FONT_Init
68 BOOL FONT_Init( void )
70 char temp[1024];
71 LPSTR ptr;
72 int i;
74 if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
76 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
77 if( strcmp( ptr, "default" ) )
78 FontNames[i++].window = xstrdup( ptr );
79 FontSize = i;
81 for( i = 1; i < FontSize; i++ )
83 PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
84 temp, sizeof(temp) );
85 FontNames[i].x11 = xstrdup( temp );
87 PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
88 FontNames[0].x11 = xstrdup( temp );
90 } else {
91 FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
92 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
93 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
94 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
95 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
96 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
97 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
98 FontSize = 7;
100 return TRUE;
103 /***********************************************************************
104 * FONT_ChkX11Family
106 * returns a valid X11 equivalent if a Windows face name
107 * is like a X11 family - or NULL if translation is needed
109 static char *FONT_ChkX11Family(char *winFaceName )
111 static char x11fam[32+2]; /* will be returned */
112 int i;
114 for(i = 0; lpLogFontList[i] != NULL; i++)
115 if( !lstrcmpi32A(winFaceName, lpLogFontList[i]->lfFaceName) )
117 strcpy(x11fam,"*-");
118 return strcat(x11fam,winFaceName);
120 return NULL; /* a FONT_TranslateName() call is needed */
125 /***********************************************************************
126 * FONT_TranslateName
128 * Translate a Windows face name to its X11 equivalent.
129 * This will probably have to be customizable.
131 static const char *FONT_TranslateName( char *winFaceName )
133 int i;
135 for (i = 1; i < FontSize; i ++)
136 if( !strcmp( winFaceName, FontNames[i].window ) ) {
137 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
138 return FontNames[i].x11;
140 return FontNames[0].x11;
144 /***********************************************************************
145 * FONT_MatchFont
147 * Find a X font matching the logical font.
149 static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc )
151 char pattern[100];
152 const char *family, *weight, *charset;
153 char **names;
154 char slant, oldspacing, spacing;
155 int width, height, oldheight, count;
156 XFontStruct * fontStruct;
158 dprintf_font(stddeb,
159 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
160 font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
161 weight = (font->lfWeight > 550) ? "bold" : "medium";
162 slant = font->lfItalic ? 'i' : 'r';
163 if (font->lfHeight == -1)
164 height = 0;
165 else
166 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
167 if (height == 0) height = 120; /* Default height = 12 */
168 else if (height < 0)
170 /* If height is negative, it means the height of the characters */
171 /* *without* the internal leading. So we adjust it a bit to */
172 /* compensate. 5/4 seems to give good results for small fonts. */
174 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
175 height = 10 * (-height * 9 / 8);
176 * may be we have to use an non linear function
178 /* assume internal leading is 2 pixels. Else small fonts will become
179 * very small. */
180 height = (height-2) * -10;
182 else height *= 10;
183 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
184 if (width < 0) {
185 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
186 width, font->lfWidth );
187 width = -width;
190 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
191 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
194 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
195 if (*font->lfFaceName) {
196 family = FONT_ChkX11Family(font->lfFaceName);
197 /*--do _not_ translate if lfFaceName is family from X11 A.K.*/
198 if (!family)
199 family = FONT_TranslateName( font->lfFaceName );
200 /* FIX ME: I don't if that's correct but it works J.M. */
201 spacing = '*';
203 else switch(font->lfPitchAndFamily & 0xf0)
205 case FF_ROMAN:
206 family = FONT_TranslateName( "roman" );
207 break;
208 case FF_SWISS:
209 family = FONT_TranslateName( "swiss" );
210 break;
211 case FF_MODERN:
212 family = FONT_TranslateName( "modern" );
213 break;
214 case FF_SCRIPT:
215 family = FONT_TranslateName( "script" );
216 break;
217 case FF_DECORATIVE:
218 family = FONT_TranslateName( "decorative" );
219 break;
220 default:
221 family = "*-*";
222 break;
224 oldheight = height;
225 oldspacing = spacing;
226 while (TRUE) {
227 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
228 if ( width == 0 )
229 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
230 family, weight, slant, height, spacing, charset);
231 else
232 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
233 family, weight, slant, height, spacing, width, charset);
234 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
235 names = XListFonts( display, pattern, 1, &count );
236 if (count > 0) break;
237 if (spacing == 'm') /* try 'c' if no 'm' found */ {
239 spacing = 'c';
240 continue;
241 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
242 spacing = '*';
243 continue;
245 spacing = oldspacing;
246 height -= 10;
247 if (height < 10) {
248 if (slant == 'i') {
249 /* try oblique if no italic font */
250 slant = 'o';
251 height = oldheight;
252 continue;
254 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
255 /* If a fixed spacing font could not be found, ignore
256 * the family */
257 family = "*-*";
258 height = oldheight;
259 continue;
261 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
262 return NULL;
265 dprintf_font(stddeb," Found '%s'\n", *names );
266 if (!*font->lfFaceName)
267 ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
268 /* we need a font name for function GetTextFace() even if there isn't one ;-) */
269 AnsiUpper(font->lfFaceName);
271 fontStruct = XLoadQueryFont( display, *names );
272 XFreeFontNames( names );
273 return fontStruct;
277 /***********************************************************************
278 * FONT_GetMetrics
280 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
281 TEXTMETRIC16 * metrics )
283 int average, i, count;
284 unsigned long prop;
286 metrics->tmAscent = xfont->ascent;
287 metrics->tmDescent = xfont->descent;
288 metrics->tmHeight = xfont->ascent + xfont->descent;
290 metrics->tmInternalLeading = 0;
291 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
292 metrics->tmInternalLeading = xfont->ascent - (short)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_GetObject
486 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
488 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
489 memcpy( buffer, &font->logfont, count );
490 return count;
494 /***********************************************************************
495 * FONT_SelectObject
497 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
499 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
501 static struct {
502 HFONT id;
503 LOGFONT16 logfont;
504 int access;
505 int used;
506 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
507 int i;
509 X_PHYSFONT * stockPtr;
510 HFONT prevHandle = dc->w.hFont;
511 XFontStruct * fontStruct;
512 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
514 #if 0 /* From the code in SelectObject, this can not happen */
515 /* Load font if necessary */
516 if (!font)
518 HFONT hnewfont;
520 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
521 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
522 DEFAULT_QUALITY, FF_DONTCARE, "*" );
523 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
525 #endif
527 if (dc->header.wMagic == METAFILE_DC_MAGIC)
528 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
529 return prevHandle;
530 else
531 return 0;
533 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
534 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
535 else {
536 stockPtr = NULL;
538 * Ok, It's not a stock font but
539 * may be it's cached in dynamic cache
541 for(i=0; i<FONTCACHE; i++) /* search for same handle */
542 if (cacheFonts[i].id==hfont) { /* Got the handle */
544 * Check if Handle matches the font
546 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
547 /* No: remove handle id from dynamic font cache */
548 cacheFonts[i].access=0;
549 cacheFonts[i].used=0;
550 cacheFonts[i].id=0;
551 /* may be there is an unused handle which contains the font */
552 for(i=0; i<FONTCACHE; i++) {
553 if((cacheFonts[i].used == 0) &&
554 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
555 /* got it load from cache and set new handle id */
556 stockPtr = &cacheFonts[i].cacheFont;
557 cacheFonts[i].access=1;
558 cacheFonts[i].used=1;
559 cacheFonts[i].id=hfont;
560 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
561 break;
566 else {
567 /* Yes: load from dynamic font cache */
568 stockPtr = &cacheFonts[i].cacheFont;
569 cacheFonts[i].access++;
570 cacheFonts[i].used++;
572 break;
575 if (!stockPtr || !stockPtr->fstruct)
577 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
579 /* If it is not a stock font, we can simply return 0 */
580 if (!stockPtr) return 0;
581 /* Otherwise we must try to find a substitute */
582 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
583 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
584 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
585 fontStruct = XLoadQueryFont( display, "fixed" );
586 if (!fontStruct)
588 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
589 exit( 1 );
593 else
595 fontStruct = stockPtr->fstruct;
596 dprintf_font(stddeb,
597 "FONT_SelectObject: Loaded font from cache %04x %p\n",
598 hfont, fontStruct );
601 /* Unuse previous font */
602 for (i=0; i < FONTCACHE; i++) {
603 if (cacheFonts[i].id == prevHandle) {
604 if(cacheFonts[i].used == 0)
605 fprintf(stderr, "Trying to decrement a use count of 0.\n");
606 else
607 cacheFonts[i].used--;
611 /* Store font */
612 dc->w.hFont = hfont;
613 if (stockPtr)
615 if (!stockPtr->fstruct)
617 stockPtr->fstruct = fontStruct;
618 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
620 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
622 else
625 * Check in cacheFont
627 cacheFontsMin=NULL;
628 for (i=0; i < FONTCACHE; i++) {
629 if (cacheFonts[i].used==0)
630 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
631 cacheFontsMin=&cacheFonts[i];
633 if (!cacheFontsMin) {
634 fprintf(stderr,"No unused font cache entry !!!!\n" );
635 return prevHandle;
637 if (cacheFontsMin->id!=0) {
638 dprintf_font(stddeb,
639 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
640 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
642 cacheFontsMin->cacheFont.fstruct = fontStruct;
643 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
644 cacheFontsMin->access=1;
645 cacheFontsMin->used=1;
646 cacheFontsMin->id=hfont;
647 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
648 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
651 return prevHandle;
655 /***********************************************************************
656 * GetTextCharacterExtra (GDI.89)
658 short GetTextCharacterExtra( HDC hdc )
660 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
661 if (!dc) return 0;
662 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
663 / dc->w.VportExtX );
667 /***********************************************************************
668 * SetTextCharacterExtra (GDI.8)
670 short SetTextCharacterExtra( HDC hdc, short extra )
672 short prev;
673 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
674 if (!dc) return 0;
675 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
676 prev = dc->w.charExtra;
677 dc->w.charExtra = abs(extra);
678 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
682 /***********************************************************************
683 * SetTextJustification (GDI.10)
685 short SetTextJustification( HDC hdc, short extra, short breaks )
687 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
688 if (!dc) return 0;
690 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
691 if (!extra) breaks = 0;
692 dc->w.breakTotalExtra = extra;
693 dc->w.breakCount = breaks;
694 if (breaks)
696 dc->w.breakExtra = extra / breaks;
697 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
699 else
701 dc->w.breakExtra = 0;
702 dc->w.breakRem = 0;
704 return 1;
708 /***********************************************************************
709 * GetTextFace (GDI.92)
711 INT GetTextFace( HDC hdc, INT count, LPSTR name )
713 FONTOBJ *font;
715 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
716 if (!dc) return 0;
717 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
718 return 0;
719 lstrcpyn32A( name, font->logfont.lfFaceName, count );
720 return strlen(name);
724 /***********************************************************************
725 * GetTextExtent (GDI.91)
727 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
729 SIZE16 size;
730 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
731 return MAKELONG( size.cx, size.cy );
735 /***********************************************************************
736 * GetTextExtentPoint16 (GDI.471)
738 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
740 SIZE32 size32;
741 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
742 CONV_SIZE32TO16( &size32, size );
743 return (BOOL16)ret;
747 /***********************************************************************
748 * GetTextExtentPoint32A (GDI32.232)
750 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
751 LPSIZE32 size )
753 int dir, ascent, descent;
754 XCharStruct info;
756 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
757 if (!dc) return FALSE;
758 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
759 &ascent, &descent, &info );
760 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
761 * dc->w.WndExtX / dc->w.VportExtX);
762 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
763 * dc->w.WndExtY / dc->w.VportExtY);
765 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%*.*s' %d %p): returning %d,%d\n",
766 hdc, count, count, str, count, size, size->cx, size->cy );
767 return TRUE;
771 /***********************************************************************
772 * GetTextExtentPoint32W (GDI32.233)
774 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
775 LPSIZE32 size )
777 char *p = STRING32_DupUniToAnsi( str );
778 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
779 free( p );
780 return ret;
784 /***********************************************************************
785 * GetTextMetrics16 (GDI.93)
787 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
789 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
790 if (!dc) return FALSE;
791 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
793 metrics->tmAscent = abs( metrics->tmAscent
794 * dc->w.WndExtY / dc->w.VportExtY );
795 metrics->tmDescent = abs( metrics->tmDescent
796 * dc->w.WndExtY / dc->w.VportExtY );
797 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
798 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
799 * dc->w.WndExtY / dc->w.VportExtY );
800 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
801 * dc->w.WndExtY / dc->w.VportExtY );
802 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
803 * dc->w.WndExtX / dc->w.VportExtX );
804 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
805 * dc->w.WndExtX / dc->w.VportExtX );
807 dprintf_font(stdnimp,"text metrics:\n
808 InternalLeading = %i
809 ExternalLeading = %i
810 MaxCharWidth = %i
811 Weight = %i
812 Italic = %i
813 Underlined = %i
814 StruckOut = %i
815 FirstChar = %i
816 LastChar = %i
817 DefaultChar = %i
818 BreakChar = %i
819 CharSet = %i
820 Overhang = %i
821 DigitizedAspectX = %i
822 DigitizedAspectY = %i
823 AveCharWidth = %i
824 MaxCharWidth = %i
825 Ascent = %i
826 Descent = %i
827 Height = %i\n",
828 metrics->tmInternalLeading,
829 metrics->tmExternalLeading,
830 metrics->tmMaxCharWidth,
831 metrics->tmWeight,
832 metrics->tmItalic,
833 metrics->tmUnderlined,
834 metrics->tmStruckOut,
835 metrics->tmFirstChar,
836 metrics->tmLastChar,
837 metrics->tmDefaultChar,
838 metrics->tmBreakChar,
839 metrics->tmCharSet,
840 metrics->tmOverhang,
841 metrics->tmDigitizedAspectX,
842 metrics->tmDigitizedAspectY,
843 metrics->tmAveCharWidth,
844 metrics->tmMaxCharWidth,
845 metrics->tmAscent,
846 metrics->tmDescent,
847 metrics->tmHeight);
849 return TRUE;
853 /***********************************************************************
854 * GetTextMetrics32A (GDI32.236)
856 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
858 TEXTMETRIC16 tm;
859 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
860 metrics->tmHeight = tm.tmHeight;
861 metrics->tmAscent = tm.tmAscent;
862 metrics->tmDescent = tm.tmDescent;
863 metrics->tmInternalLeading = tm.tmInternalLeading;
864 metrics->tmExternalLeading = tm.tmExternalLeading;
865 metrics->tmAveCharWidth = tm.tmAveCharWidth;
866 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
867 metrics->tmWeight = tm.tmWeight;
868 metrics->tmOverhang = tm.tmOverhang;
869 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
870 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
871 metrics->tmFirstChar = tm.tmFirstChar;
872 metrics->tmLastChar = tm.tmLastChar;
873 metrics->tmDefaultChar = tm.tmDefaultChar;
874 metrics->tmBreakChar = tm.tmBreakChar;
875 metrics->tmItalic = tm.tmItalic;
876 metrics->tmUnderlined = tm.tmUnderlined;
877 metrics->tmStruckOut = tm.tmStruckOut;
878 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
879 metrics->tmCharSet = tm.tmCharSet;
880 return TRUE;
884 /***********************************************************************
885 * GetTextMetrics32W (GDI32.237)
887 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
889 TEXTMETRIC16 tm;
890 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
891 metrics->tmHeight = tm.tmHeight;
892 metrics->tmAscent = tm.tmAscent;
893 metrics->tmDescent = tm.tmDescent;
894 metrics->tmInternalLeading = tm.tmInternalLeading;
895 metrics->tmExternalLeading = tm.tmExternalLeading;
896 metrics->tmAveCharWidth = tm.tmAveCharWidth;
897 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
898 metrics->tmWeight = tm.tmWeight;
899 metrics->tmOverhang = tm.tmOverhang;
900 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
901 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
902 metrics->tmFirstChar = tm.tmFirstChar;
903 metrics->tmLastChar = tm.tmLastChar;
904 metrics->tmDefaultChar = tm.tmDefaultChar;
905 metrics->tmBreakChar = tm.tmBreakChar;
906 metrics->tmItalic = tm.tmItalic;
907 metrics->tmUnderlined = tm.tmUnderlined;
908 metrics->tmStruckOut = tm.tmStruckOut;
909 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
910 metrics->tmCharSet = tm.tmCharSet;
911 return TRUE;
915 /***********************************************************************
916 * SetMapperFlags (GDI.349)
918 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
920 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
921 hDC, dwFlag);
922 return 0L;
926 /***********************************************************************
927 * GetCharABCWidths (GDI.307)
929 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
932 /* No TrueType fonts in Wine so far */
934 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
935 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
937 return FALSE;
941 /***********************************************************************
942 * GetCharWidth (GDI.350)
944 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
946 int i, j;
947 XFontStruct *xfont;
948 XCharStruct *cs, *def;
950 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
951 if (!dc) return FALSE;
952 xfont = dc->u.x.font.fstruct;
954 /* fixed font? */
955 if (xfont->per_char == NULL)
957 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
958 *(lpBuffer + j) = xfont->max_bounds.width;
959 return TRUE;
962 CI_GET_DEFAULT_INFO(xfont, def);
964 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
966 CI_GET_CHAR_INFO(xfont, i, def, cs);
967 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
968 if (*(lpBuffer + j) < 0)
969 *(lpBuffer + j) = 0;
971 return TRUE;
975 /***********************************************************************
976 * AddFontResource (GDI.119)
978 INT AddFontResource( LPCSTR str )
980 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
981 return 1;
985 /***********************************************************************
986 * RemoveFontResource (GDI.136)
988 BOOL RemoveFontResource( LPSTR str )
990 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
991 return TRUE;
995 /*************************************************************************
996 * ParseFontParms [internal]
998 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1000 int i;
1001 if (lpFont == NULL) return 0;
1002 if (lpRetStr == NULL) return 0;
1003 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1004 if (*lpFont == '-') i++;
1005 lpFont++;
1007 if (i == wParmsNo) {
1008 if (*lpFont == '-') lpFont++;
1009 wMaxSiz--;
1010 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1011 *(lpRetStr + i) = *lpFont++;
1012 *(lpRetStr + i) = '\0';
1013 return i;
1015 else
1016 lpRetStr[0] = '\0';
1017 return 0;
1021 /*************************************************************************
1022 * InitFontsList [internal]
1025 static int logfcmp(const void *a,const void *b)
1027 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1028 (*(LPLOGFONT16 *)b)->lfFaceName );
1031 void InitFontsList(void)
1033 char str[32];
1034 char pattern[100];
1035 char *family, *weight, *charset;
1036 char **names;
1037 char slant, spacing;
1038 int i, count;
1039 LPLOGFONT16 lpNewFont;
1041 dprintf_font(stddeb,"InitFontsList !\n");
1043 weight = "medium";
1044 slant = 'r';
1045 spacing = '*';
1046 charset = "*";
1047 family = "*-*";
1049 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1050 family, weight, slant, spacing, charset);
1051 names = XListFonts( display, pattern, MAX_FONTS, &count );
1052 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1054 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1055 if (lpNewFont == NULL) {
1056 dprintf_font(stddeb,
1057 "InitFontsList // Error alloc new font structure !\n");
1058 XFreeFontNames(names);
1059 return;
1062 for (i = 0; i < count; i++) {
1063 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1065 ParseFontParms(names[i], 2, str, sizeof(str));
1066 #if 0
1067 /* not necessary because new function FONT_ChkX11Family() */
1068 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1069 #endif
1070 AnsiUpper(str);
1071 strcpy(lpNewFont->lfFaceName, str);
1072 ParseFontParms(names[i], 8, str, sizeof(str));
1073 lpNewFont->lfHeight = atoi(str) / 10;
1074 ParseFontParms(names[i], 12, str, sizeof(str));
1075 lpNewFont->lfWidth = atoi(str) / 10;
1076 lpNewFont->lfEscapement = 0;
1077 lpNewFont->lfOrientation = 0;
1078 lpNewFont->lfWeight = FW_REGULAR;
1079 lpNewFont->lfItalic = 0;
1080 lpNewFont->lfUnderline = 0;
1081 lpNewFont->lfStrikeOut = 0;
1082 ParseFontParms(names[i], 13, str, sizeof(str));
1083 if (strcmp(str, "iso8859") == 0) {
1084 lpNewFont->lfCharSet = ANSI_CHARSET;
1085 } else {
1086 lpNewFont->lfCharSet = OEM_CHARSET;
1088 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1089 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1090 lpNewFont->lfQuality = DEFAULT_QUALITY;
1091 ParseFontParms(names[i], 11, str, sizeof(str));
1092 switch(str[0]) {
1093 case 'p':
1094 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1095 break;
1096 case 'm':
1097 case 'c':
1098 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1099 break;
1100 default:
1101 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1102 break;
1104 dprintf_font( stddeb,
1105 "InitFontsList // lpNewFont->lfHeight=%d\n",
1106 lpNewFont->lfHeight );
1107 dprintf_font( stddeb,
1108 "InitFontsList // lpNewFont->lfWidth=%d\n",
1109 lpNewFont->lfWidth );
1110 dprintf_font( stddeb,
1111 "InitFontsList // lfFaceName='%s'\n",
1112 lpNewFont->lfFaceName );
1113 lpLogFontList[i] = lpNewFont;
1114 lpNewFont = (LPLOGFONT16)
1115 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1117 lpLogFontList[i] = NULL;
1119 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1120 XFreeFontNames(names);
1124 /*************************************************************************
1125 * EnumFonts [GDI.70]
1127 INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC lpEnumFunc, LPARAM lpData)
1129 HANDLE hLog;
1130 HANDLE hMet;
1131 HFONT hFont;
1132 HFONT hOldFont;
1133 LPLOGFONT16 lpLogFont;
1134 LPTEXTMETRIC16 lptm;
1135 LPSTR lpOldName;
1136 char FaceName[LF_FACESIZE];
1137 int nRet = 0;
1138 int i;
1140 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
1141 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
1142 if (lpEnumFunc == 0) return 0;
1143 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
1144 lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1145 if (lpLogFont == NULL) {
1146 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
1147 return 0;
1149 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1150 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1151 if (lptm == NULL) {
1152 GDI_HEAP_FREE(hLog);
1153 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1154 return 0;
1156 if (lpFaceName != NULL) {
1157 strcpy(FaceName, lpFaceName);
1158 AnsiUpper(FaceName);
1160 lpOldName = NULL;
1162 if (lpLogFontList[0] == NULL) InitFontsList();
1163 for(i = 0; lpLogFontList[i] != NULL; i++) {
1164 if (lpFaceName == NULL) {
1165 if (lpOldName != NULL) {
1166 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1168 lpOldName = lpLogFontList[i]->lfFaceName;
1169 } else {
1170 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1172 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1173 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1174 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
1175 hFont = CreateFontIndirect16(lpLogFont);
1176 hOldFont = SelectObject(hDC, hFont);
1177 GetTextMetrics16(hDC, lptm);
1178 SelectObject(hDC, hOldFont);
1179 DeleteObject(hFont);
1180 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1181 nRet = CallEnumFontsProc((FARPROC16)lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
1182 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
1183 if (nRet == 0) {
1184 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1185 break;
1188 GDI_HEAP_FREE(hMet);
1189 GDI_HEAP_FREE(hLog);
1190 return nRet;
1194 /*************************************************************************
1195 * EnumFontFamilies [GDI.330]
1197 INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC lpEnumFunc, LPARAM lpData)
1199 HANDLE hLog;
1200 HANDLE hMet;
1201 HFONT hFont;
1202 HFONT hOldFont;
1203 LPENUMLOGFONT16 lpEnumLogFont;
1204 LPTEXTMETRIC16 lptm;
1205 LPSTR lpOldName;
1206 char FaceName[LF_FACESIZE];
1207 int nRet = 0;
1208 int i;
1210 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1211 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1212 if (lpEnumFunc == 0) return 0;
1213 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
1214 lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1215 if (lpEnumLogFont == NULL) {
1216 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1217 return 0;
1219 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1220 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1221 if (lptm == NULL) {
1222 GDI_HEAP_FREE(hLog);
1223 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1224 return 0;
1226 lpOldName = NULL;
1227 if (lpszFamily != NULL) {
1228 strcpy(FaceName, lpszFamily);
1229 AnsiUpper(FaceName);
1231 if (lpLogFontList[0] == NULL) InitFontsList();
1232 for(i = 0; lpLogFontList[i] != NULL; i++) {
1233 if (lpszFamily == NULL) {
1234 if (lpOldName != NULL) {
1235 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1237 lpOldName = lpLogFontList[i]->lfFaceName;
1238 } else {
1239 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1241 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1242 strcpy(lpEnumLogFont->elfFullName,"");
1243 strcpy(lpEnumLogFont->elfStyle,"");
1244 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1245 hOldFont = SelectObject(hDC, hFont);
1246 GetTextMetrics16(hDC, lptm);
1247 SelectObject(hDC, hOldFont);
1248 DeleteObject(hFont);
1249 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1251 nRet = CallEnumFontFamProc( (FARPROC16)lpEnumFunc,
1252 GDI_HEAP_SEG_ADDR(hLog),
1253 GDI_HEAP_SEG_ADDR(hMet),
1254 0, lpData );
1255 if (nRet == 0) {
1256 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1257 break;
1260 GDI_HEAP_FREE(hMet);
1261 GDI_HEAP_FREE(hLog);
1262 return nRet;
1265 /*************************************************************************
1266 * GetRasterizerCaps [GDI.313]
1269 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1271 /* This is not much more than a dummy */
1272 RASTERIZER_STATUS rs;
1274 rs.nSize = sizeof(rs);
1275 rs.wFlags = 0;
1276 rs.nLanguageID = 0;
1277 return True;
1280 /*************************************************************************
1281 * GetKerningPairs [GDI.332]
1283 int GetKerningPairs(HDC hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1285 /* This has to be dealt with when proper font handling is in place
1287 * At this time kerning is ignored (set to 0)
1290 int i;
1291 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1292 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1293 return 0;