Release 961208
[wine.git] / objects / font.c
blob784cb2f5b1c6b2ecbe33b3d984715556e531814b
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 FontNames[7].window = "system"; FontNames[7].x11 = "*-helvetica";
98 FontSize = 8;
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 sprintf( pattern, "-%s-%s-*-normal-*-*-*-*-*-*-*-%s",
225 family, weight, charset);
226 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
227 names = XListFonts( display, pattern, 1, &count );
228 if (names) XFreeFontNames( names );
229 else
231 if (strcmp(family, "*-*") == 0)
233 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
234 return NULL;
236 else family = "*-*";
238 oldheight = height;
239 oldspacing = spacing;
240 while (TRUE) {
241 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
242 if ( width == 0 )
243 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
244 family, weight, slant, height, spacing, charset);
245 else
246 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
247 family, weight, slant, height, spacing, width, charset);
248 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
249 names = XListFonts( display, pattern, 1, &count );
250 if (count > 0) break;
251 if (spacing == 'm') /* try 'c' if no 'm' found */ {
253 spacing = 'c';
254 continue;
255 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
256 spacing = '*';
257 continue;
259 spacing = oldspacing;
260 height -= 10;
261 if (height < 10) {
262 if (slant == 'i') {
263 /* try oblique if no italic font */
264 slant = 'o';
265 height = oldheight;
266 continue;
268 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
269 /* If a fixed spacing font could not be found, ignore
270 * the family */
271 family = "*-*";
272 height = oldheight;
273 continue;
275 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
276 return NULL;
279 dprintf_font(stddeb," Found '%s'\n", *names );
280 if (!*font->lfFaceName)
281 ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
282 /* we need a font name for function GetTextFace() even if there isn't one ;-) */
283 AnsiUpper(font->lfFaceName);
285 fontStruct = XLoadQueryFont( display, *names );
286 XFreeFontNames( names );
287 return fontStruct;
291 /***********************************************************************
292 * FONT_GetMetrics
294 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
295 TEXTMETRIC16 * metrics )
297 int average, i, count;
298 unsigned long prop;
300 metrics->tmAscent = xfont->ascent;
301 metrics->tmDescent = xfont->descent;
302 metrics->tmHeight = xfont->ascent + xfont->descent;
304 metrics->tmInternalLeading = 0;
305 if (XGetFontProperty( xfont, XA_CAP_HEIGHT, &prop ))
306 metrics->tmInternalLeading = xfont->ascent+xfont->descent-(INT16)prop;
308 metrics->tmExternalLeading = 0;
309 metrics->tmMaxCharWidth = xfont->max_bounds.width;
310 metrics->tmWeight = logfont->lfWeight;
311 metrics->tmItalic = logfont->lfItalic;
312 metrics->tmUnderlined = logfont->lfUnderline;
313 metrics->tmStruckOut = logfont->lfStrikeOut;
314 metrics->tmFirstChar = xfont->min_char_or_byte2;
315 metrics->tmLastChar = xfont->max_char_or_byte2;
316 metrics->tmDefaultChar = xfont->default_char;
317 metrics->tmBreakChar = ' ';
318 metrics->tmCharSet = logfont->lfCharSet;
319 metrics->tmOverhang = 0;
320 metrics->tmDigitizedAspectX = 1;
321 metrics->tmDigitizedAspectY = 1;
322 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
324 /* TMPF_FIXED_PITCH bit means variable pitch...Don't you love Microsoft? */
325 if (xfont->min_bounds.width != xfont->max_bounds.width)
326 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
328 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
329 else
331 XCharStruct * charPtr = xfont->per_char;
332 average = count = 0;
333 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
335 if (!CI_NONEXISTCHAR( charPtr ))
337 average += charPtr->width;
338 count++;
340 charPtr++;
342 if (count) average = (average + count/2) / count;
344 metrics->tmAveCharWidth = average;
347 /***********************************************************************
348 * GetGlyphOutLine (GDI.309)
350 DWORD GetGlyphOutLine( HDC16 hdc, UINT uChar, UINT fuFormat,
351 LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPSTR lpBuffer,
352 LPMAT2 lpmat2)
354 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
355 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
356 return (DWORD)-1; /* failure */
359 void
360 FONT_LOGFONT32AToLOGFONT16(const LOGFONT32A *font,LPLOGFONT16 font16) {
361 font16->lfHeight = (INT16)font->lfHeight;
362 font16->lfWidth = (INT16)font->lfWidth;
363 font16->lfEscapement = (INT16)font->lfEscapement;
364 font16->lfOrientation = (INT16)font->lfOrientation;
365 font16->lfWeight = (INT16)font->lfWeight;
366 font16->lfItalic = font->lfItalic;
367 font16->lfUnderline = font->lfUnderline;
368 font16->lfStrikeOut = font->lfStrikeOut;
369 font16->lfCharSet = font->lfCharSet;
370 font16->lfOutPrecision = font->lfOutPrecision;
371 font16->lfClipPrecision = font->lfClipPrecision;
372 font16->lfQuality = font->lfQuality;
373 font16->lfPitchAndFamily = font->lfPitchAndFamily;
374 lstrcpyn32A( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
377 void
378 FONT_LOGFONT32WToLOGFONT16(const LOGFONT32W *font,LPLOGFONT16 font16) {
379 font16->lfHeight = (INT16)font->lfHeight;
380 font16->lfWidth = (INT16)font->lfWidth;
381 font16->lfEscapement = (INT16)font->lfEscapement;
382 font16->lfOrientation = (INT16)font->lfOrientation;
383 font16->lfWeight = (INT16)font->lfWeight;
384 font16->lfItalic = font->lfItalic;
385 font16->lfUnderline = font->lfUnderline;
386 font16->lfStrikeOut = font->lfStrikeOut;
387 font16->lfCharSet = font->lfCharSet;
388 font16->lfOutPrecision = font->lfOutPrecision;
389 font16->lfClipPrecision = font->lfClipPrecision;
390 font16->lfQuality = font->lfQuality;
391 font16->lfPitchAndFamily = font->lfPitchAndFamily;
392 lstrcpynWtoA( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
395 void
396 FONT_LOGFONT16ToLOGFONT32A(LPLOGFONT16 font,LPLOGFONT32A font32A) {
397 font32A->lfHeight = (INT32)font->lfHeight;
398 font32A->lfWidth = (INT32)font->lfWidth;
399 font32A->lfEscapement = (INT32)font->lfEscapement;
400 font32A->lfOrientation = (INT32)font->lfOrientation;
401 font32A->lfWeight = (INT32)font->lfWeight;
402 font32A->lfItalic = font->lfItalic;
403 font32A->lfUnderline = font->lfUnderline;
404 font32A->lfStrikeOut = font->lfStrikeOut;
405 font32A->lfCharSet = font->lfCharSet;
406 font32A->lfOutPrecision = font->lfOutPrecision;
407 font32A->lfClipPrecision = font->lfClipPrecision;
408 font32A->lfQuality = font->lfQuality;
409 font32A->lfPitchAndFamily = font->lfPitchAndFamily;
410 lstrcpyn32A( font32A->lfFaceName, font->lfFaceName, LF_FACESIZE );
413 void
414 FONT_LOGFONT16ToLOGFONT32W(LPLOGFONT16 font,LPLOGFONT32W font32W) {
415 font32W->lfHeight = (INT32)font->lfHeight;
416 font32W->lfWidth = (INT32)font->lfWidth;
417 font32W->lfEscapement = (INT32)font->lfEscapement;
418 font32W->lfOrientation = (INT32)font->lfOrientation;
419 font32W->lfWeight = (INT32)font->lfWeight;
420 font32W->lfItalic = font->lfItalic;
421 font32W->lfUnderline = font->lfUnderline;
422 font32W->lfStrikeOut = font->lfStrikeOut;
423 font32W->lfCharSet = font->lfCharSet;
424 font32W->lfOutPrecision = font->lfOutPrecision;
425 font32W->lfClipPrecision = font->lfClipPrecision;
426 font32W->lfQuality = font->lfQuality;
427 font32W->lfPitchAndFamily = font->lfPitchAndFamily;
428 lstrcpynAtoW( font32W->lfFaceName, font->lfFaceName, LF_FACESIZE );
432 /***********************************************************************
433 * CreateScalableFontResource (GDI.310)
435 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
436 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
438 /* fHidden=1 - only visible for the calling app, read-only, not
439 * enumbered with EnumFonts/EnumFontFamilies
440 * lpszCurrentPath can be NULL
442 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
443 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
444 return FALSE; /* create failed */
448 /***********************************************************************
449 * CreateFontIndirect16 (GDI.57)
451 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
453 FONTOBJ * fontPtr;
454 HFONT16 hfont;
456 if (!font)
458 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
459 return 0;
461 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
462 if (!hfont) return 0;
463 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
464 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
465 AnsiLower( fontPtr->logfont.lfFaceName );
466 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
467 font, font->lfHeight, font->lfWidth, hfont);
468 return hfont;
472 /***********************************************************************
473 * CreateFontIndirect32A (GDI32.44)
475 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
477 LOGFONT16 font16;
479 FONT_LOGFONT32AToLOGFONT16(font,&font16);
481 return CreateFontIndirect16( &font16 );
485 /***********************************************************************
486 * CreateFontIndirect32W (GDI32.45)
488 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
490 LOGFONT16 font16;
492 FONT_LOGFONT32WToLOGFONT16(font,&font16);
493 return CreateFontIndirect16( &font16 );
497 /***********************************************************************
498 * CreateFont16 (GDI.56)
500 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
501 INT16 weight, BYTE italic, BYTE underline,
502 BYTE strikeout, BYTE charset, BYTE outpres,
503 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
505 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
506 strikeout, charset, outpres, clippres, quality, pitch, };
507 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
508 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
509 else logfont.lfFaceName[0] = '\0';
510 return CreateFontIndirect16( &logfont );
515 /*************************************************************************
516 * CreateFont32A (GDI32.43)
518 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
519 INT32 weight, DWORD italic, DWORD underline,
520 DWORD strikeout, DWORD charset, DWORD outpres,
521 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
523 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
524 underline, strikeout, charset, outpres,
525 clippres, quality, pitch, name );
529 /*************************************************************************
530 * CreateFont32W (GDI32.46)
532 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
533 INT32 weight, DWORD italic, DWORD underline,
534 DWORD strikeout, DWORD charset, DWORD outpres,
535 DWORD clippres, DWORD quality, DWORD pitch,
536 LPCWSTR name )
538 LPSTR namea = name ? STRING32_DupUniToAnsi(name) : NULL;
539 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
540 italic, underline, strikeout, charset,
541 outpres, clippres, quality, pitch,
542 namea );
543 free(namea);
544 return ret;
548 /***********************************************************************
549 * FONT_GetObject16
551 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
553 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
554 memcpy( buffer, &font->logfont, count );
555 return count;
559 /***********************************************************************
560 * FONT_GetObject32A
562 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
564 LOGFONT32A fnt32;
566 memset(&fnt32, 0, sizeof(fnt32));
567 fnt32.lfHeight = font->logfont.lfHeight;
568 fnt32.lfWidth = font->logfont.lfWidth;
569 fnt32.lfEscapement = font->logfont.lfEscapement;
570 fnt32.lfOrientation = font->logfont.lfOrientation;
571 fnt32.lfWeight = font->logfont.lfWeight;
572 fnt32.lfItalic = font->logfont.lfItalic;
573 fnt32.lfUnderline = font->logfont.lfUnderline;
574 fnt32.lfStrikeOut = font->logfont.lfStrikeOut;
575 fnt32.lfCharSet = font->logfont.lfCharSet;
576 fnt32.lfOutPrecision = font->logfont.lfOutPrecision;
577 fnt32.lfClipPrecision = font->logfont.lfClipPrecision;
578 fnt32.lfQuality = font->logfont.lfQuality;
579 fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
580 strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
581 sizeof(fnt32.lfFaceName) );
583 if (count > sizeof(fnt32)) count = sizeof(fnt32);
584 memcpy( buffer, &fnt32, count );
585 return count;
589 /***********************************************************************
590 * FONT_SelectObject
592 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
594 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
596 static struct {
597 HFONT16 id;
598 LOGFONT16 logfont;
599 int access;
600 int used;
601 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
602 int i;
604 X_PHYSFONT * stockPtr;
605 HFONT16 prevHandle = dc->w.hFont;
606 XFontStruct * fontStruct;
607 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
609 #if 0 /* From the code in SelectObject, this can not happen */
610 /* Load font if necessary */
611 if (!font)
613 HFONT16 hnewfont;
615 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
616 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
617 DEFAULT_QUALITY, FF_DONTCARE, "*" );
618 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
620 #endif
622 if (dc->header.wMagic == METAFILE_DC_MAGIC)
623 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
624 return prevHandle;
625 else
626 return 0;
628 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
629 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
630 else {
631 stockPtr = NULL;
633 * Ok, It's not a stock font but
634 * may be it's cached in dynamic cache
636 for(i=0; i<FONTCACHE; i++) /* search for same handle */
637 if (cacheFonts[i].id==hfont) { /* Got the handle */
639 * Check if Handle matches the font
641 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
642 /* No: remove handle id from dynamic font cache */
643 cacheFonts[i].access=0;
644 cacheFonts[i].used=0;
645 cacheFonts[i].id=0;
646 /* may be there is an unused handle which contains the font */
647 for(i=0; i<FONTCACHE; i++) {
648 if((cacheFonts[i].used == 0) &&
649 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
650 /* got it load from cache and set new handle id */
651 stockPtr = &cacheFonts[i].cacheFont;
652 cacheFonts[i].access=1;
653 cacheFonts[i].used=1;
654 cacheFonts[i].id=hfont;
655 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
656 break;
661 else {
662 /* Yes: load from dynamic font cache */
663 stockPtr = &cacheFonts[i].cacheFont;
664 cacheFonts[i].access++;
665 cacheFonts[i].used++;
667 break;
670 if (!stockPtr || !stockPtr->fstruct)
672 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
674 /* If it is not a stock font, we can simply return 0 */
675 if (!stockPtr) return 0;
676 /* Otherwise we must try to find a substitute */
677 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
678 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
679 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
680 fontStruct = XLoadQueryFont( display, "fixed" );
681 if (!fontStruct)
683 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
684 exit( 1 );
688 else
690 fontStruct = stockPtr->fstruct;
691 dprintf_font(stddeb,
692 "FONT_SelectObject: Loaded font from cache %04x %p\n",
693 hfont, fontStruct );
696 /* Unuse previous font */
697 for (i=0; i < FONTCACHE; i++) {
698 if (cacheFonts[i].id == prevHandle) {
699 if(cacheFonts[i].used == 0)
700 fprintf(stderr, "Trying to decrement a use count of 0.\n");
701 else
702 cacheFonts[i].used--;
706 /* Store font */
707 dc->w.hFont = hfont;
708 if (stockPtr)
710 if (!stockPtr->fstruct)
712 stockPtr->fstruct = fontStruct;
713 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
715 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
717 else
720 * Check in cacheFont
722 cacheFontsMin=NULL;
723 for (i=0; i < FONTCACHE; i++) {
724 if (cacheFonts[i].used==0)
725 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
726 cacheFontsMin=&cacheFonts[i];
728 if (!cacheFontsMin) {
729 fprintf(stderr,"No unused font cache entry !!!!\n" );
730 return prevHandle;
732 if (cacheFontsMin->id!=0) {
733 dprintf_font(stddeb,
734 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
735 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
737 cacheFontsMin->cacheFont.fstruct = fontStruct;
738 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
739 cacheFontsMin->access=1;
740 cacheFontsMin->used=1;
741 cacheFontsMin->id=hfont;
742 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
743 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
746 return prevHandle;
750 /***********************************************************************
751 * GetTextCharacterExtra (GDI.89)
753 short GetTextCharacterExtra( HDC16 hdc )
755 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
756 if (!dc) return 0;
757 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
758 / dc->w.VportExtX );
762 /***********************************************************************
763 * SetTextCharacterExtra (GDI.8)
765 short SetTextCharacterExtra( HDC16 hdc, short extra )
767 short prev;
768 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
769 if (!dc) return 0;
770 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
771 prev = dc->w.charExtra;
772 dc->w.charExtra = abs(extra);
773 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
777 /***********************************************************************
778 * SetTextJustification (GDI.10)
780 short SetTextJustification( HDC16 hdc, short extra, short breaks )
782 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
783 if (!dc) return 0;
785 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
786 if (!extra) breaks = 0;
787 dc->w.breakTotalExtra = extra;
788 dc->w.breakCount = breaks;
789 if (breaks)
791 dc->w.breakExtra = extra / breaks;
792 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
794 else
796 dc->w.breakExtra = 0;
797 dc->w.breakRem = 0;
799 return 1;
803 /***********************************************************************
804 * GetTextFace (GDI.92)
806 INT GetTextFace( HDC16 hdc, INT count, LPSTR name )
808 FONTOBJ *font;
810 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
811 if (!dc) return 0;
812 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
813 return 0;
814 lstrcpyn32A( name, font->logfont.lfFaceName, count );
815 return strlen(name);
819 /***********************************************************************
820 * GetTextExtent (GDI.91)
822 DWORD GetTextExtent( HDC16 hdc, LPCSTR str, short count )
824 SIZE16 size;
825 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
826 return MAKELONG( size.cx, size.cy );
830 /***********************************************************************
831 * GetTextExtentPoint16 (GDI.471)
833 * FIXME: Should this have a bug for compatibility?
834 * Original Windows versions of GetTextExtentPoint{A,W} have documented
835 * bugs.
837 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
839 SIZE32 size32;
840 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
841 CONV_SIZE32TO16( &size32, size );
842 return (BOOL16)ret;
846 /***********************************************************************
847 * GetTextExtentPoint32A (GDI32.230)
849 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
850 LPSIZE32 size )
852 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
853 if (!dc)
855 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
856 return FALSE;
859 if (!dc->funcs->pGetTextExtentPoint ||
860 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
861 return FALSE;
863 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
864 hdc, count, str, count, size, size->cx, size->cy );
865 return TRUE;
869 /***********************************************************************
870 * GetTextExtentPoint32W (GDI32.231)
872 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
873 LPSIZE32 size )
875 char *p = STRING32_DupUniToAnsi( str );
876 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
877 free( p );
878 return ret;
881 /***********************************************************************
882 * GetTextExtentPoint32ABuggy (GDI32.232)
884 BOOL32 GetTextExtentPoint32ABuggy( HDC32 hdc, LPCSTR str, INT32 count,
885 LPSIZE32 size )
887 fprintf( stderr, "GetTextExtentPoint32ABuggy: not bug compatible.\n" );
888 return GetTextExtentPoint32A( hdc, str, count, size );
891 /***********************************************************************
892 * GetTextExtentPoint32WBuggy (GDI32.233)
894 BOOL32 GetTextExtentPoint32WBuggy( HDC32 hdc, LPCWSTR str, INT32 count,
895 LPSIZE32 size )
897 fprintf( stderr, "GetTextExtentPoint32WBuggy: not bug compatible.\n" );
898 return GetTextExtentPoint32W( hdc, str, count, size );
902 /***********************************************************************
903 * GetTextMetrics16 (GDI.93)
905 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
907 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
908 if (!dc) return FALSE;
909 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
911 metrics->tmAscent = abs( metrics->tmAscent
912 * dc->w.WndExtY / dc->w.VportExtY );
913 metrics->tmDescent = abs( metrics->tmDescent
914 * dc->w.WndExtY / dc->w.VportExtY );
915 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
916 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
917 * dc->w.WndExtY / dc->w.VportExtY );
918 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
919 * dc->w.WndExtY / dc->w.VportExtY );
920 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
921 * dc->w.WndExtX / dc->w.VportExtX );
922 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
923 * dc->w.WndExtX / dc->w.VportExtX );
925 dprintf_font(stdnimp,"text metrics:\n
926 InternalLeading = %i
927 ExternalLeading = %i
928 MaxCharWidth = %i
929 Weight = %i
930 Italic = %i
931 Underlined = %i
932 StruckOut = %i
933 FirstChar = %i
934 LastChar = %i
935 DefaultChar = %i
936 BreakChar = %i
937 CharSet = %i
938 Overhang = %i
939 DigitizedAspectX = %i
940 DigitizedAspectY = %i
941 AveCharWidth = %i
942 MaxCharWidth = %i
943 Ascent = %i
944 Descent = %i
945 Height = %i\n",
946 metrics->tmInternalLeading,
947 metrics->tmExternalLeading,
948 metrics->tmMaxCharWidth,
949 metrics->tmWeight,
950 metrics->tmItalic,
951 metrics->tmUnderlined,
952 metrics->tmStruckOut,
953 metrics->tmFirstChar,
954 metrics->tmLastChar,
955 metrics->tmDefaultChar,
956 metrics->tmBreakChar,
957 metrics->tmCharSet,
958 metrics->tmOverhang,
959 metrics->tmDigitizedAspectX,
960 metrics->tmDigitizedAspectY,
961 metrics->tmAveCharWidth,
962 metrics->tmMaxCharWidth,
963 metrics->tmAscent,
964 metrics->tmDescent,
965 metrics->tmHeight);
967 return TRUE;
971 /***********************************************************************
972 * GetTextMetrics32A (GDI32.236)
974 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
976 TEXTMETRIC16 tm;
977 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
978 metrics->tmHeight = tm.tmHeight;
979 metrics->tmAscent = tm.tmAscent;
980 metrics->tmDescent = tm.tmDescent;
981 metrics->tmInternalLeading = tm.tmInternalLeading;
982 metrics->tmExternalLeading = tm.tmExternalLeading;
983 metrics->tmAveCharWidth = tm.tmAveCharWidth;
984 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
985 metrics->tmWeight = tm.tmWeight;
986 metrics->tmOverhang = tm.tmOverhang;
987 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
988 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
989 metrics->tmFirstChar = tm.tmFirstChar;
990 metrics->tmLastChar = tm.tmLastChar;
991 metrics->tmDefaultChar = tm.tmDefaultChar;
992 metrics->tmBreakChar = tm.tmBreakChar;
993 metrics->tmItalic = tm.tmItalic;
994 metrics->tmUnderlined = tm.tmUnderlined;
995 metrics->tmStruckOut = tm.tmStruckOut;
996 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
997 metrics->tmCharSet = tm.tmCharSet;
998 return TRUE;
1002 /***********************************************************************
1003 * GetTextMetrics32W (GDI32.237)
1005 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
1007 TEXTMETRIC16 tm;
1008 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1009 metrics->tmHeight = tm.tmHeight;
1010 metrics->tmAscent = tm.tmAscent;
1011 metrics->tmDescent = tm.tmDescent;
1012 metrics->tmInternalLeading = tm.tmInternalLeading;
1013 metrics->tmExternalLeading = tm.tmExternalLeading;
1014 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1015 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1016 metrics->tmWeight = tm.tmWeight;
1017 metrics->tmOverhang = tm.tmOverhang;
1018 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1019 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1020 metrics->tmFirstChar = tm.tmFirstChar;
1021 metrics->tmLastChar = tm.tmLastChar;
1022 metrics->tmDefaultChar = tm.tmDefaultChar;
1023 metrics->tmBreakChar = tm.tmBreakChar;
1024 metrics->tmItalic = tm.tmItalic;
1025 metrics->tmUnderlined = tm.tmUnderlined;
1026 metrics->tmStruckOut = tm.tmStruckOut;
1027 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1028 metrics->tmCharSet = tm.tmCharSet;
1029 return TRUE;
1033 /***********************************************************************
1034 * SetMapperFlags (GDI.349)
1036 DWORD SetMapperFlags(HDC16 hDC, DWORD dwFlag)
1038 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
1039 hDC, dwFlag);
1040 return 0L;
1044 /***********************************************************************
1045 * GetCharABCWidths (GDI.307)
1047 BOOL GetCharABCWidths(HDC16 hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
1050 /* No TrueType fonts in Wine so far */
1052 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
1053 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
1055 return FALSE;
1059 /***********************************************************************
1060 * GetCharWidth (GDI.350)
1062 BOOL GetCharWidth(HDC16 hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
1064 int i, j;
1065 XFontStruct *xfont;
1066 XCharStruct *cs, *def;
1068 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1069 if (!dc) return FALSE;
1070 xfont = dc->u.x.font.fstruct;
1072 /* fixed font? */
1073 if (xfont->per_char == NULL)
1075 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
1076 *(lpBuffer + j) = xfont->max_bounds.width;
1077 return TRUE;
1080 CI_GET_DEFAULT_INFO(xfont, def);
1082 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
1084 CI_GET_CHAR_INFO(xfont, i, def, cs);
1085 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
1086 if (*(lpBuffer + j) < 0)
1087 *(lpBuffer + j) = 0;
1089 return TRUE;
1093 /***********************************************************************
1094 * AddFontResource (GDI.119)
1096 INT AddFontResource( LPCSTR str )
1098 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1099 return 1;
1103 /***********************************************************************
1104 * RemoveFontResource (GDI.136)
1106 BOOL RemoveFontResource( LPSTR str )
1108 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1109 return TRUE;
1113 /*************************************************************************
1114 * ParseFontParms [internal]
1116 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1118 int i;
1119 if (lpFont == NULL) return 0;
1120 if (lpRetStr == NULL) return 0;
1121 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1122 if (*lpFont == '-') i++;
1123 lpFont++;
1125 if (i == wParmsNo) {
1126 if (*lpFont == '-') lpFont++;
1127 wMaxSiz--;
1128 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1129 *(lpRetStr + i) = *lpFont++;
1130 *(lpRetStr + i) = '\0';
1131 return i;
1133 else
1134 lpRetStr[0] = '\0';
1135 return 0;
1139 /*************************************************************************
1140 * InitFontsList [internal]
1143 static int logfcmp(const void *a,const void *b)
1145 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1146 (*(LPLOGFONT16 *)b)->lfFaceName );
1149 void InitFontsList(void)
1151 char str[32];
1152 char pattern[100];
1153 char *family, *weight, *charset;
1154 char **names;
1155 char slant, spacing;
1156 int i, count;
1157 LPLOGFONT16 lpNewFont;
1159 dprintf_font(stddeb,"InitFontsList !\n");
1161 weight = "medium";
1162 slant = 'r';
1163 spacing = '*';
1164 charset = "*";
1165 family = "*-*";
1167 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1168 family, weight, slant, spacing, charset);
1169 names = XListFonts( display, pattern, MAX_FONTS, &count );
1170 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1172 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1173 if (lpNewFont == NULL) {
1174 dprintf_font(stddeb,
1175 "InitFontsList // Error alloc new font structure !\n");
1176 XFreeFontNames(names);
1177 return;
1180 for (i = 0; i < count; i++) {
1181 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1183 ParseFontParms(names[i], 2, str, sizeof(str));
1184 #if 0
1185 /* not necessary because new function FONT_ChkX11Family() */
1186 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1187 #endif
1188 AnsiUpper(str);
1189 strcpy(lpNewFont->lfFaceName, str);
1190 ParseFontParms(names[i], 8, str, sizeof(str));
1191 lpNewFont->lfHeight = atoi(str) / 10;
1192 ParseFontParms(names[i], 12, str, sizeof(str));
1193 lpNewFont->lfWidth = atoi(str) / 10;
1194 lpNewFont->lfEscapement = 0;
1195 lpNewFont->lfOrientation = 0;
1196 lpNewFont->lfWeight = FW_REGULAR;
1197 lpNewFont->lfItalic = 0;
1198 lpNewFont->lfUnderline = 0;
1199 lpNewFont->lfStrikeOut = 0;
1200 ParseFontParms(names[i], 13, str, sizeof(str));
1201 if (strcmp(str, "iso8859") == 0) {
1202 lpNewFont->lfCharSet = ANSI_CHARSET;
1203 } else {
1204 lpNewFont->lfCharSet = OEM_CHARSET;
1206 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1207 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1208 lpNewFont->lfQuality = DEFAULT_QUALITY;
1209 ParseFontParms(names[i], 11, str, sizeof(str));
1210 switch(str[0]) {
1211 case 'p':
1212 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1213 break;
1214 case 'm':
1215 case 'c':
1216 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1217 break;
1218 default:
1219 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1220 break;
1222 dprintf_font( stddeb,
1223 "InitFontsList // lpNewFont->lfHeight=%d\n",
1224 lpNewFont->lfHeight );
1225 dprintf_font( stddeb,
1226 "InitFontsList // lpNewFont->lfWidth=%d\n",
1227 lpNewFont->lfWidth );
1228 dprintf_font( stddeb,
1229 "InitFontsList // lfFaceName='%s'\n",
1230 lpNewFont->lfFaceName );
1231 lpLogFontList[i] = lpNewFont;
1232 lpNewFont = (LPLOGFONT16)
1233 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1235 lpLogFontList[i] = NULL;
1237 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1238 XFreeFontNames(names);
1241 /*************************************************************************
1242 * EnumFonts [GDI.70]
1243 * We reuse EnumFontFamilies* for the callback function get the same
1244 * structs (+ extra stuff at the end which will be ignored by the enum funcs)
1246 INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1248 return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData);
1251 /*************************************************************************
1252 * EnumFontsA [GDI32.84]
1254 INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1256 return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData);
1259 /*************************************************************************
1260 * EnumFontsA [GDI32.84]
1262 INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1264 return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData);
1267 /*************************************************************************
1268 * EnumFontFamilies [GDI.330]
1270 INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1272 LOGFONT16 LF;
1274 if (lpszFamily)
1275 strcpy(LF.lfFaceName,lpszFamily);
1276 else
1277 LF.lfFaceName[0]='\0';
1278 LF.lfCharSet = DEFAULT_CHARSET;
1280 return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0);
1283 /*************************************************************************
1284 * EnumFontFamiliesA [GDI32.80]
1286 INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1288 LOGFONT32A LF;
1290 if (lpszFamily)
1291 strcpy(LF.lfFaceName,lpszFamily);
1292 else
1293 LF.lfFaceName[0]='\0';
1294 LF.lfCharSet = DEFAULT_CHARSET;
1296 return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0);
1299 /*************************************************************************
1300 * EnumFontFamiliesW [GDI32.83]
1302 INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1304 LOGFONT32W LF;
1306 if (lpszFamilyW)
1307 lstrcpy32W(LF.lfFaceName,lpszFamilyW);
1308 else
1309 LF.lfFaceName[0]=0;
1310 LF.lfCharSet = DEFAULT_CHARSET;
1311 return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0);
1314 /*************************************************************************
1315 * EnumFontFamiliesEx [GDI.618]
1316 * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures.
1317 * (applies to all EnumFontFamiliesEx*)
1318 * winelib/16 support.
1320 INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved)
1322 HLOCAL16 hLog;
1323 HLOCAL16 hMet;
1324 HFONT16 hFont;
1325 HFONT16 hOldFont;
1326 LPENUMLOGFONTEX16 lpEnumLogFont;
1327 LPNEWTEXTMETRICEX16 lptm;
1328 LPSTR lpOldName;
1329 char FaceName[LF_FACESIZE];
1330 int nRet = 0;
1331 int i;
1333 dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n",
1334 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved);
1335 if (lpEnumFunc == 0) return 0;
1336 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) );
1337 lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog);
1338 if (lpEnumLogFont == NULL) {
1339 fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n");
1340 return 0;
1342 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) );
1343 lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet);
1344 if (lptm == NULL) {
1345 GDI_HEAP_FREE(hLog);
1346 fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n");
1347 return 0;
1349 lpOldName = NULL;
1350 strcpy(FaceName,lpLF->lfFaceName);
1351 AnsiUpper(lpLF->lfFaceName);
1353 if (lpLogFontList[0] == NULL) InitFontsList();
1354 for(i = 0; lpLogFontList[i] != NULL; i++) {
1355 /* lfCharSet */
1356 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1357 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1358 continue;
1360 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1361 /* lfFaceName */
1362 if (FaceName[0]) {
1363 if (strcmp(FaceName,lpLogFontList[i]->lfFaceName))
1364 continue;
1365 } else {
1366 if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
1367 continue;
1368 lpOldName=lpLogFontList[i]->lfFaceName;
1371 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1372 strcpy(lpEnumLogFont->elfFullName,"");
1373 strcpy(lpEnumLogFont->elfStyle,"");
1374 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1375 hOldFont = SelectObject32(hDC, hFont);
1376 GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm);
1377 SelectObject32(hDC, hOldFont);
1378 DeleteObject32(hFont);
1379 dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1381 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1382 0, lpData );
1383 if (nRet == 0) {
1384 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1385 break;
1388 GDI_HEAP_FREE(hMet);
1389 GDI_HEAP_FREE(hLog);
1390 return nRet;
1393 /*************************************************************************
1394 * EnumFontFamiliesExA [GDI32.81]
1395 * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*)
1397 INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved)
1399 HLOCAL16 hLog;
1400 HLOCAL16 hMet;
1401 HFONT32 hFont;
1402 HFONT32 hOldFont;
1403 LPENUMLOGFONTEX32A lpEnumLogFont;
1404 LPNEWTEXTMETRICEX32A lptm;
1405 LPSTR lpOldName;
1406 char FaceName[LF_FACESIZE];
1407 int nRet = 0;
1408 int i;
1410 dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n",
1411 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved);
1412 if (lpEnumFunc == 0) return 0;
1413 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) );
1414 lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog);
1415 if (lpEnumLogFont == NULL) {
1416 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1417 return 0;
1419 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) );
1420 lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet);
1421 if (lptm == NULL) {
1422 GDI_HEAP_FREE(hLog);
1423 fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n");
1424 return 0;
1426 lpOldName = NULL;
1427 strcpy(FaceName,lpLF->lfFaceName);
1428 AnsiUpper(lpLF->lfFaceName);
1430 if (lpLogFontList[0] == NULL) InitFontsList();
1431 for(i = 0; lpLogFontList[i] != NULL; i++) {
1432 /* lfCharSet */
1433 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1434 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1435 continue;
1437 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1438 /* lfFaceName */
1439 if (FaceName[0]) {
1440 if (strcmp(FaceName,lpLogFontList[i]->lfFaceName))
1441 continue;
1442 } else {
1443 if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
1444 continue;
1445 lpOldName=lpLogFontList[i]->lfFaceName;
1448 FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1449 strcpy(lpEnumLogFont->elfFullName,"");
1450 strcpy(lpEnumLogFont->elfStyle,"");
1451 strcpy(lpEnumLogFont->elfScript,"");
1452 hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont);
1453 hOldFont = SelectObject32(hDC, hFont);
1454 GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm);
1455 SelectObject32(hDC, hOldFont);
1456 DeleteObject32(hFont);
1457 dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1459 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1460 if (nRet == 0) {
1461 dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n");
1462 break;
1465 GDI_HEAP_FREE(hMet);
1466 GDI_HEAP_FREE(hLog);
1467 return nRet;
1471 /*************************************************************************
1472 * EnumFontFamiliesW [GDI32.82]
1474 INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved)
1476 HLOCAL16 hLog;
1477 HLOCAL16 hMet;
1478 HFONT32 hFont;
1479 HFONT32 hOldFont;
1480 LPENUMLOGFONTEX32W lpEnumLogFont;
1481 LPNEWTEXTMETRICEX32W lptm;
1482 LPSTR lpOldName;
1483 int nRet = 0;
1484 int i;
1485 LPSTR lpszFamily=STRING32_DupUniToAnsi(lpLF->lfFaceName);
1487 dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n",
1488 hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved);
1489 if (lpEnumFunc == 0) {
1490 free(lpszFamily);
1491 return 0;
1493 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) );
1494 lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog);
1495 if (lpEnumLogFont == NULL) {
1496 fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
1497 free(lpszFamily);
1498 return 0;
1500 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) );
1501 lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet);
1502 if (lptm == NULL) {
1503 GDI_HEAP_FREE(hLog);
1504 fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n");
1505 free(lpszFamily);
1506 return 0;
1508 lpOldName = NULL;
1509 AnsiUpper(lpszFamily);
1510 if (lpLogFontList[0] == NULL) InitFontsList();
1511 for(i = 0; lpLogFontList[i] != NULL; i++) {
1512 /* lfCharSet */
1513 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1514 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1515 continue;
1517 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1518 /* lfFaceName */
1519 if (lpszFamily[0]) {
1520 if (strcmp(lpszFamily,lpLogFontList[i]->lfFaceName))
1521 continue;
1522 } else {
1523 if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
1524 continue;
1525 lpOldName=lpLogFontList[i]->lfFaceName;
1528 FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1529 lstrcpynAtoW(lpEnumLogFont->elfFullName,"",1);
1530 lstrcpynAtoW(lpEnumLogFont->elfStyle,"",1);
1531 lstrcpynAtoW(lpEnumLogFont->elfScript,"",1);
1532 hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont);
1533 hOldFont = SelectObject32(hDC, hFont);
1534 GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm);
1535 SelectObject32(hDC, hOldFont);
1536 DeleteObject32(hFont);
1537 dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1539 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1540 if (nRet == 0) {
1541 dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n");
1542 break;
1545 GDI_HEAP_FREE(hMet);
1546 GDI_HEAP_FREE(hLog);
1547 free(lpszFamily);
1548 return nRet;
1552 /*************************************************************************
1553 * GetRasterizerCaps [GDI.313]
1556 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1558 /* This is not much more than a dummy */
1559 RASTERIZER_STATUS rs;
1561 rs.nSize = sizeof(rs);
1562 rs.wFlags = 0;
1563 rs.nLanguageID = 0;
1564 return True;
1567 /*************************************************************************
1568 * GetKerningPairs [GDI.332]
1570 int GetKerningPairs(HDC16 hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1572 /* This has to be dealt with when proper font handling is in place
1574 * At this time kerning is ignored (set to 0)
1577 int i;
1578 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1579 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1580 return 0;