Release 961215
[wine/multimedia.git] / objects / font.c
blob40f12a29eff82a9f869c3a2a1ac4db0f5fff4012
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;
802 /***********************************************************************
803 * GetTextFace16 (GDI.92)
805 INT16 GetTextFace16( HDC16 hdc, INT16 count, LPSTR name )
807 return GetTextFace32A(hdc,count,name);
810 /***********************************************************************
811 * GetTextFace32A (GDI32.234)
813 INT32 GetTextFace32A( HDC32 hdc, INT32 count, LPSTR name )
815 FONTOBJ *font;
817 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
818 if (!dc) return 0;
819 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
820 return 0;
821 lstrcpyn32A( name, font->logfont.lfFaceName, count );
822 return strlen(name);
825 /***********************************************************************
826 * GetTextFace32W (GDI32.235)
828 INT32 GetTextFace32W( HDC32 hdc, INT32 count, LPWSTR name )
830 LPSTR nameA = (LPSTR)xmalloc(count);
831 INT32 res = GetTextFace32A(hdc,count,nameA);
833 lstrcpynAtoW(name,nameA,count);
834 free(nameA);
835 return res;
839 /***********************************************************************
840 * GetTextExtent (GDI.91)
842 DWORD GetTextExtent( HDC16 hdc, LPCSTR str, short count )
844 SIZE16 size;
845 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
846 return MAKELONG( size.cx, size.cy );
850 /***********************************************************************
851 * GetTextExtentPoint16 (GDI.471)
853 * FIXME: Should this have a bug for compatibility?
854 * Original Windows versions of GetTextExtentPoint{A,W} have documented
855 * bugs.
857 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
859 SIZE32 size32;
860 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
861 CONV_SIZE32TO16( &size32, size );
862 return (BOOL16)ret;
866 /***********************************************************************
867 * GetTextExtentPoint32A (GDI32.230)
869 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
870 LPSIZE32 size )
872 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
873 if (!dc)
875 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
876 return FALSE;
879 if (!dc->funcs->pGetTextExtentPoint ||
880 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
881 return FALSE;
883 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
884 hdc, count, str, count, size, size->cx, size->cy );
885 return TRUE;
889 /***********************************************************************
890 * GetTextExtentPoint32W (GDI32.231)
892 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
893 LPSIZE32 size )
895 char *p = STRING32_DupUniToAnsi( str );
896 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
897 free( p );
898 return ret;
901 /***********************************************************************
902 * GetTextExtentPoint32ABuggy (GDI32.232)
904 BOOL32 GetTextExtentPoint32ABuggy( HDC32 hdc, LPCSTR str, INT32 count,
905 LPSIZE32 size )
907 dprintf_font( stddeb, "GetTextExtentPoint32ABuggy: not bug compatible.\n");
908 return GetTextExtentPoint32A( hdc, str, count, size );
911 /***********************************************************************
912 * GetTextExtentPoint32WBuggy (GDI32.233)
914 BOOL32 GetTextExtentPoint32WBuggy( HDC32 hdc, LPCWSTR str, INT32 count,
915 LPSIZE32 size )
917 dprintf_font( stddeb, "GetTextExtentPoint32WBuggy: not bug compatible.\n");
918 return GetTextExtentPoint32W( hdc, str, count, size );
922 /***********************************************************************
923 * GetTextExtentExPoint32A (GDI32.228)
925 BOOL32 GetTextExtentExPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
926 INT32 maxExt,LPINT32 lpnFit, LPINT32 alpDx,
927 LPSIZE32 size )
929 int index;
930 SIZE32 tSize;
931 int nFit=0;
932 int extent=0;
933 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
934 if (!dc)
936 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
937 return FALSE;
939 if (!dc->funcs->pGetTextExtentPoint) return FALSE;
941 size->cx=0; size->cy=0;
942 for(index=0;index<count;index++)
944 if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
945 if(extent+tSize.cx<maxExt)
947 extent+=tSize.cx;
948 nFit++;
949 str++;
950 if(alpDx) alpDx[index]=extent;
951 if(tSize.cy > size->cy) size->cy=tSize.cy;
953 else break;
955 size->cx=extent;
956 *lpnFit=nFit;
957 dprintf_font(stddeb,"GetTextExtentExPoint32A(%08x '%.*s' %d) returning %d %d %d\n",
958 hdc,count,str,maxExt,nFit, size->cx,size->cy);
959 return TRUE;
962 /***********************************************************************
963 * GetTextExtentExPoint32W (GDI32.229)
966 BOOL32 GetTextExtentExPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
967 INT32 maxExt, LPINT32 lpnFit, LPINT32 alpDx,
968 LPSIZE32 size )
970 char *p = STRING32_DupUniToAnsi( str );
971 BOOL32 ret = GetTextExtentExPoint32A( hdc, p, count, maxExt,
972 lpnFit, alpDx, size);
973 free( p );
974 return ret;
977 /***********************************************************************
978 * GetTextMetrics16 (GDI.93)
980 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
982 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
983 if (!dc) return FALSE;
984 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
986 metrics->tmAscent = abs( metrics->tmAscent
987 * dc->w.WndExtY / dc->w.VportExtY );
988 metrics->tmDescent = abs( metrics->tmDescent
989 * dc->w.WndExtY / dc->w.VportExtY );
990 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
991 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
992 * dc->w.WndExtY / dc->w.VportExtY );
993 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
994 * dc->w.WndExtY / dc->w.VportExtY );
995 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
996 * dc->w.WndExtX / dc->w.VportExtX );
997 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
998 * dc->w.WndExtX / dc->w.VportExtX );
1000 dprintf_font(stdnimp,"text metrics:\n
1001 InternalLeading = %i
1002 ExternalLeading = %i
1003 MaxCharWidth = %i
1004 Weight = %i
1005 Italic = %i
1006 Underlined = %i
1007 StruckOut = %i
1008 FirstChar = %i
1009 LastChar = %i
1010 DefaultChar = %i
1011 BreakChar = %i
1012 CharSet = %i
1013 Overhang = %i
1014 DigitizedAspectX = %i
1015 DigitizedAspectY = %i
1016 AveCharWidth = %i
1017 MaxCharWidth = %i
1018 Ascent = %i
1019 Descent = %i
1020 Height = %i\n",
1021 metrics->tmInternalLeading,
1022 metrics->tmExternalLeading,
1023 metrics->tmMaxCharWidth,
1024 metrics->tmWeight,
1025 metrics->tmItalic,
1026 metrics->tmUnderlined,
1027 metrics->tmStruckOut,
1028 metrics->tmFirstChar,
1029 metrics->tmLastChar,
1030 metrics->tmDefaultChar,
1031 metrics->tmBreakChar,
1032 metrics->tmCharSet,
1033 metrics->tmOverhang,
1034 metrics->tmDigitizedAspectX,
1035 metrics->tmDigitizedAspectY,
1036 metrics->tmAveCharWidth,
1037 metrics->tmMaxCharWidth,
1038 metrics->tmAscent,
1039 metrics->tmDescent,
1040 metrics->tmHeight);
1042 return TRUE;
1046 /***********************************************************************
1047 * GetTextMetrics32A (GDI32.236)
1049 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
1051 TEXTMETRIC16 tm;
1052 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1053 metrics->tmHeight = tm.tmHeight;
1054 metrics->tmAscent = tm.tmAscent;
1055 metrics->tmDescent = tm.tmDescent;
1056 metrics->tmInternalLeading = tm.tmInternalLeading;
1057 metrics->tmExternalLeading = tm.tmExternalLeading;
1058 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1059 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1060 metrics->tmWeight = tm.tmWeight;
1061 metrics->tmOverhang = tm.tmOverhang;
1062 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1063 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1064 metrics->tmFirstChar = tm.tmFirstChar;
1065 metrics->tmLastChar = tm.tmLastChar;
1066 metrics->tmDefaultChar = tm.tmDefaultChar;
1067 metrics->tmBreakChar = tm.tmBreakChar;
1068 metrics->tmItalic = tm.tmItalic;
1069 metrics->tmUnderlined = tm.tmUnderlined;
1070 metrics->tmStruckOut = tm.tmStruckOut;
1071 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1072 metrics->tmCharSet = tm.tmCharSet;
1073 return TRUE;
1077 /***********************************************************************
1078 * GetTextMetrics32W (GDI32.237)
1080 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
1082 TEXTMETRIC16 tm;
1083 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1084 metrics->tmHeight = tm.tmHeight;
1085 metrics->tmAscent = tm.tmAscent;
1086 metrics->tmDescent = tm.tmDescent;
1087 metrics->tmInternalLeading = tm.tmInternalLeading;
1088 metrics->tmExternalLeading = tm.tmExternalLeading;
1089 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1090 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1091 metrics->tmWeight = tm.tmWeight;
1092 metrics->tmOverhang = tm.tmOverhang;
1093 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1094 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1095 metrics->tmFirstChar = tm.tmFirstChar;
1096 metrics->tmLastChar = tm.tmLastChar;
1097 metrics->tmDefaultChar = tm.tmDefaultChar;
1098 metrics->tmBreakChar = tm.tmBreakChar;
1099 metrics->tmItalic = tm.tmItalic;
1100 metrics->tmUnderlined = tm.tmUnderlined;
1101 metrics->tmStruckOut = tm.tmStruckOut;
1102 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1103 metrics->tmCharSet = tm.tmCharSet;
1104 return TRUE;
1108 /***********************************************************************
1109 * SetMapperFlags (GDI.349)
1111 DWORD SetMapperFlags(HDC16 hDC, DWORD dwFlag)
1113 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
1114 hDC, dwFlag);
1115 return 0L;
1119 /***********************************************************************
1120 * GetCharABCWidths (GDI.307)
1122 BOOL GetCharABCWidths(HDC16 hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
1125 /* No TrueType fonts in Wine so far */
1127 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
1128 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
1130 return FALSE;
1134 /***********************************************************************
1135 * GetCharWidth (GDI.350)
1137 BOOL GetCharWidth(HDC16 hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
1139 int i, j;
1140 XFontStruct *xfont;
1141 XCharStruct *cs, *def;
1143 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1144 if (!dc) return FALSE;
1145 xfont = dc->u.x.font.fstruct;
1147 /* fixed font? */
1148 if (xfont->per_char == NULL)
1150 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
1151 *(lpBuffer + j) = xfont->max_bounds.width;
1152 return TRUE;
1155 CI_GET_DEFAULT_INFO(xfont, def);
1157 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
1159 CI_GET_CHAR_INFO(xfont, i, def, cs);
1160 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
1161 if (*(lpBuffer + j) < 0)
1162 *(lpBuffer + j) = 0;
1164 return TRUE;
1168 /***********************************************************************
1169 * AddFontResource (GDI.119)
1171 INT AddFontResource( LPCSTR str )
1173 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1174 return 1;
1178 /***********************************************************************
1179 * RemoveFontResource (GDI.136)
1181 BOOL RemoveFontResource( LPSTR str )
1183 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1184 return TRUE;
1188 /*************************************************************************
1189 * ParseFontParms [internal]
1191 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1193 int i;
1194 if (lpFont == NULL) return 0;
1195 if (lpRetStr == NULL) return 0;
1196 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1197 if (*lpFont == '-') i++;
1198 lpFont++;
1200 if (i == wParmsNo) {
1201 if (*lpFont == '-') lpFont++;
1202 wMaxSiz--;
1203 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1204 *(lpRetStr + i) = *lpFont++;
1205 *(lpRetStr + i) = '\0';
1206 return i;
1208 else
1209 lpRetStr[0] = '\0';
1210 return 0;
1214 /*************************************************************************
1215 * InitFontsList [internal]
1218 static int logfcmp(const void *a,const void *b)
1220 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1221 (*(LPLOGFONT16 *)b)->lfFaceName );
1224 void InitFontsList(void)
1226 char str[32];
1227 char pattern[100];
1228 char *family, *weight, *charset;
1229 char **names;
1230 char slant, spacing;
1231 int i, count;
1232 LPLOGFONT16 lpNewFont;
1234 dprintf_font(stddeb,"InitFontsList !\n");
1236 weight = "medium";
1237 slant = 'r';
1238 spacing = '*';
1239 charset = "*";
1240 family = "*-*";
1242 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1243 family, weight, slant, spacing, charset);
1244 names = XListFonts( display, pattern, MAX_FONTS, &count );
1245 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1247 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1248 if (lpNewFont == NULL) {
1249 dprintf_font(stddeb,
1250 "InitFontsList // Error alloc new font structure !\n");
1251 XFreeFontNames(names);
1252 return;
1255 for (i = 0; i < count; i++) {
1256 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1258 ParseFontParms(names[i], 2, str, sizeof(str));
1259 #if 0
1260 /* not necessary because new function FONT_ChkX11Family() */
1261 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1262 #endif
1263 AnsiUpper(str);
1264 strcpy(lpNewFont->lfFaceName, str);
1265 ParseFontParms(names[i], 8, str, sizeof(str));
1266 lpNewFont->lfHeight = atoi(str) / 10;
1267 ParseFontParms(names[i], 12, str, sizeof(str));
1268 lpNewFont->lfWidth = atoi(str) / 10;
1269 lpNewFont->lfEscapement = 0;
1270 lpNewFont->lfOrientation = 0;
1271 lpNewFont->lfWeight = FW_REGULAR;
1272 lpNewFont->lfItalic = 0;
1273 lpNewFont->lfUnderline = 0;
1274 lpNewFont->lfStrikeOut = 0;
1275 ParseFontParms(names[i], 13, str, sizeof(str));
1276 if (strcmp(str, "iso8859") == 0) {
1277 lpNewFont->lfCharSet = ANSI_CHARSET;
1278 } else {
1279 lpNewFont->lfCharSet = OEM_CHARSET;
1281 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1282 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1283 lpNewFont->lfQuality = DEFAULT_QUALITY;
1284 ParseFontParms(names[i], 11, str, sizeof(str));
1285 switch(str[0]) {
1286 case 'p':
1287 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1288 break;
1289 case 'm':
1290 case 'c':
1291 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1292 break;
1293 default:
1294 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1295 break;
1297 dprintf_font( stddeb,
1298 "InitFontsList // lpNewFont->lfHeight=%d\n",
1299 lpNewFont->lfHeight );
1300 dprintf_font( stddeb,
1301 "InitFontsList // lpNewFont->lfWidth=%d\n",
1302 lpNewFont->lfWidth );
1303 dprintf_font( stddeb,
1304 "InitFontsList // lfFaceName='%s'\n",
1305 lpNewFont->lfFaceName );
1306 lpLogFontList[i] = lpNewFont;
1307 lpNewFont = (LPLOGFONT16)
1308 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1310 lpLogFontList[i] = NULL;
1312 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1313 XFreeFontNames(names);
1316 /*************************************************************************
1317 * EnumFonts [GDI.70]
1318 * We reuse EnumFontFamilies* for the callback function get the same
1319 * structs (+ extra stuff at the end which will be ignored by the enum funcs)
1321 INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1323 return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData);
1326 /*************************************************************************
1327 * EnumFontsA [GDI32.84]
1329 INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1331 return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData);
1334 /*************************************************************************
1335 * EnumFontsA [GDI32.84]
1337 INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1339 return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData);
1342 /*************************************************************************
1343 * EnumFontFamilies [GDI.330]
1345 INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1347 LOGFONT16 LF;
1349 if (lpszFamily)
1350 strcpy(LF.lfFaceName,lpszFamily);
1351 else
1352 LF.lfFaceName[0]='\0';
1353 LF.lfCharSet = DEFAULT_CHARSET;
1355 return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0);
1358 /*************************************************************************
1359 * EnumFontFamiliesA [GDI32.80]
1361 INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1363 LOGFONT32A LF;
1365 if (lpszFamily)
1366 strcpy(LF.lfFaceName,lpszFamily);
1367 else
1368 LF.lfFaceName[0]='\0';
1369 LF.lfCharSet = DEFAULT_CHARSET;
1371 return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0);
1374 /*************************************************************************
1375 * EnumFontFamiliesW [GDI32.83]
1377 INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1379 LOGFONT32W LF;
1381 if (lpszFamilyW)
1382 lstrcpy32W(LF.lfFaceName,lpszFamilyW);
1383 else
1384 LF.lfFaceName[0]=0;
1385 LF.lfCharSet = DEFAULT_CHARSET;
1386 return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0);
1389 /*************************************************************************
1390 * EnumFontFamiliesEx [GDI.618]
1391 * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures.
1392 * (applies to all EnumFontFamiliesEx*)
1393 * winelib/16 support.
1395 INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved)
1397 HLOCAL16 hLog;
1398 HLOCAL16 hMet;
1399 HFONT16 hFont;
1400 HFONT16 hOldFont;
1401 LPENUMLOGFONTEX16 lpEnumLogFont;
1402 LPNEWTEXTMETRICEX16 lptm;
1403 LPSTR lpOldName;
1404 char FaceName[LF_FACESIZE];
1405 int nRet = 0;
1406 int i;
1408 dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n",
1409 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved);
1410 if (lpEnumFunc == 0) return 0;
1411 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) );
1412 lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog);
1413 if (lpEnumLogFont == NULL) {
1414 fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n");
1415 return 0;
1417 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) );
1418 lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet);
1419 if (lptm == NULL) {
1420 GDI_HEAP_FREE(hLog);
1421 fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n");
1422 return 0;
1424 lpOldName = NULL;
1425 strcpy(FaceName,lpLF->lfFaceName);
1426 AnsiUpper(lpLF->lfFaceName);
1428 if (lpLogFontList[0] == NULL) InitFontsList();
1429 for(i = 0; lpLogFontList[i] != NULL; i++) {
1430 /* lfCharSet */
1431 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1432 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1433 continue;
1435 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1436 /* lfFaceName */
1437 if (FaceName[0]) {
1438 if (strcmp(FaceName,lpLogFontList[i]->lfFaceName))
1439 continue;
1440 } else {
1441 if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
1442 continue;
1443 lpOldName=lpLogFontList[i]->lfFaceName;
1446 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1447 strcpy(lpEnumLogFont->elfFullName,"");
1448 strcpy(lpEnumLogFont->elfStyle,"");
1449 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1450 hOldFont = SelectObject32(hDC, hFont);
1451 GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm);
1452 SelectObject32(hDC, hOldFont);
1453 DeleteObject32(hFont);
1454 dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1456 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1457 0, lpData );
1458 if (nRet == 0) {
1459 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1460 break;
1463 GDI_HEAP_FREE(hMet);
1464 GDI_HEAP_FREE(hLog);
1465 return nRet;
1468 /*************************************************************************
1469 * EnumFontFamiliesExA [GDI32.81]
1470 * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*)
1472 INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved)
1474 HLOCAL16 hLog;
1475 HLOCAL16 hMet;
1476 HFONT32 hFont;
1477 HFONT32 hOldFont;
1478 LPENUMLOGFONTEX32A lpEnumLogFont;
1479 LPNEWTEXTMETRICEX32A lptm;
1480 LPSTR lpOldName;
1481 char FaceName[LF_FACESIZE];
1482 int nRet = 0;
1483 int i;
1485 dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n",
1486 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved);
1487 if (lpEnumFunc == 0) return 0;
1488 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) );
1489 lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog);
1490 if (lpEnumLogFont == NULL) {
1491 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1492 return 0;
1494 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) );
1495 lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet);
1496 if (lptm == NULL) {
1497 GDI_HEAP_FREE(hLog);
1498 fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n");
1499 return 0;
1501 lpOldName = NULL;
1502 strcpy(FaceName,lpLF->lfFaceName);
1503 AnsiUpper(lpLF->lfFaceName);
1505 if (lpLogFontList[0] == NULL) InitFontsList();
1506 for(i = 0; lpLogFontList[i] != NULL; i++) {
1507 /* lfCharSet */
1508 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1509 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1510 continue;
1512 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1513 /* lfFaceName */
1514 if (FaceName[0]) {
1515 if (strcmp(FaceName,lpLogFontList[i]->lfFaceName))
1516 continue;
1517 } else {
1518 if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
1519 continue;
1520 lpOldName=lpLogFontList[i]->lfFaceName;
1523 FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1524 strcpy(lpEnumLogFont->elfFullName,"");
1525 strcpy(lpEnumLogFont->elfStyle,"");
1526 strcpy(lpEnumLogFont->elfScript,"");
1527 hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont);
1528 hOldFont = SelectObject32(hDC, hFont);
1529 GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm);
1530 SelectObject32(hDC, hOldFont);
1531 DeleteObject32(hFont);
1532 dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1534 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1535 if (nRet == 0) {
1536 dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n");
1537 break;
1540 GDI_HEAP_FREE(hMet);
1541 GDI_HEAP_FREE(hLog);
1542 return nRet;
1546 /*************************************************************************
1547 * EnumFontFamiliesW [GDI32.82]
1549 INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved)
1551 HLOCAL16 hLog;
1552 HLOCAL16 hMet;
1553 HFONT32 hFont;
1554 HFONT32 hOldFont;
1555 LPENUMLOGFONTEX32W lpEnumLogFont;
1556 LPNEWTEXTMETRICEX32W lptm;
1557 LPSTR lpOldName;
1558 int nRet = 0;
1559 int i;
1560 LPSTR lpszFamily=STRING32_DupUniToAnsi(lpLF->lfFaceName);
1562 dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n",
1563 hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved);
1564 if (lpEnumFunc == 0) {
1565 free(lpszFamily);
1566 return 0;
1568 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) );
1569 lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog);
1570 if (lpEnumLogFont == NULL) {
1571 fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
1572 free(lpszFamily);
1573 return 0;
1575 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) );
1576 lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet);
1577 if (lptm == NULL) {
1578 GDI_HEAP_FREE(hLog);
1579 fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n");
1580 free(lpszFamily);
1581 return 0;
1583 lpOldName = NULL;
1584 AnsiUpper(lpszFamily);
1585 if (lpLogFontList[0] == NULL) InitFontsList();
1586 for(i = 0; lpLogFontList[i] != NULL; i++) {
1587 /* lfCharSet */
1588 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1589 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1590 continue;
1592 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1593 /* lfFaceName */
1594 if (lpszFamily[0]) {
1595 if (strcmp(lpszFamily,lpLogFontList[i]->lfFaceName))
1596 continue;
1597 } else {
1598 if ((lpOldName!=NULL)&&!strcmp(lpOldName,lpLogFontList[i]->lfFaceName))
1599 continue;
1600 lpOldName=lpLogFontList[i]->lfFaceName;
1603 FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1604 lstrcpynAtoW(lpEnumLogFont->elfFullName,"",1);
1605 lstrcpynAtoW(lpEnumLogFont->elfStyle,"",1);
1606 lstrcpynAtoW(lpEnumLogFont->elfScript,"",1);
1607 hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont);
1608 hOldFont = SelectObject32(hDC, hFont);
1609 GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm);
1610 SelectObject32(hDC, hOldFont);
1611 DeleteObject32(hFont);
1612 dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1614 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1615 if (nRet == 0) {
1616 dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n");
1617 break;
1620 GDI_HEAP_FREE(hMet);
1621 GDI_HEAP_FREE(hLog);
1622 free(lpszFamily);
1623 return nRet;
1627 /*************************************************************************
1628 * GetRasterizerCaps [GDI.313]
1631 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1633 /* This is not much more than a dummy */
1634 RASTERIZER_STATUS rs;
1636 rs.nSize = sizeof(rs);
1637 rs.wFlags = 0;
1638 rs.nLanguageID = 0;
1639 return True;
1642 /*************************************************************************
1643 * GetKerningPairs [GDI.332]
1645 int GetKerningPairs(HDC16 hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1647 /* This has to be dealt with when proper font handling is in place
1649 * At this time kerning is ignored (set to 0)
1652 int i;
1653 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1654 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1655 return 0;