Release 970112
[wine.git] / objects / font.c
blob07b95a61fc1feb39d5a3ff5288bd4f2a53f6d403
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 "heap.h"
18 #include "metafile.h"
19 #include "options.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( !lstrcmpi32A( 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->vportExtX / dc->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->vportExtY / dc->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 ;-) */
284 fontStruct = XLoadQueryFont( display, *names );
285 XFreeFontNames( names );
286 return fontStruct;
290 /***********************************************************************
291 * FONT_LOGFONT32AToLOGFONT16
293 static void FONT_LOGFONT32AToLOGFONT16( const LOGFONT32A *font,
294 LPLOGFONT16 font16 )
296 font16->lfHeight = (INT16)font->lfHeight;
297 font16->lfWidth = (INT16)font->lfWidth;
298 font16->lfEscapement = (INT16)font->lfEscapement;
299 font16->lfOrientation = (INT16)font->lfOrientation;
300 font16->lfWeight = (INT16)font->lfWeight;
301 font16->lfItalic = font->lfItalic;
302 font16->lfUnderline = font->lfUnderline;
303 font16->lfStrikeOut = font->lfStrikeOut;
304 font16->lfCharSet = font->lfCharSet;
305 font16->lfOutPrecision = font->lfOutPrecision;
306 font16->lfClipPrecision = font->lfClipPrecision;
307 font16->lfQuality = font->lfQuality;
308 font16->lfPitchAndFamily = font->lfPitchAndFamily;
309 lstrcpyn32A( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
313 /***********************************************************************
314 * FONT_LOGFONT32WToLOGFONT16
316 static void FONT_LOGFONT32WToLOGFONT16( const LOGFONT32W *font,
317 LPLOGFONT16 font16 )
319 font16->lfHeight = (INT16)font->lfHeight;
320 font16->lfWidth = (INT16)font->lfWidth;
321 font16->lfEscapement = (INT16)font->lfEscapement;
322 font16->lfOrientation = (INT16)font->lfOrientation;
323 font16->lfWeight = (INT16)font->lfWeight;
324 font16->lfItalic = font->lfItalic;
325 font16->lfUnderline = font->lfUnderline;
326 font16->lfStrikeOut = font->lfStrikeOut;
327 font16->lfCharSet = font->lfCharSet;
328 font16->lfOutPrecision = font->lfOutPrecision;
329 font16->lfClipPrecision = font->lfClipPrecision;
330 font16->lfQuality = font->lfQuality;
331 font16->lfPitchAndFamily = font->lfPitchAndFamily;
332 lstrcpynWtoA( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
336 /***********************************************************************
337 * FONT_LOGFONT16ToLOGFONT32A
339 static void FONT_LOGFONT16ToLOGFONT32A( LPLOGFONT16 font,
340 LPLOGFONT32A font32A )
342 font32A->lfHeight = (INT32)font->lfHeight;
343 font32A->lfWidth = (INT32)font->lfWidth;
344 font32A->lfEscapement = (INT32)font->lfEscapement;
345 font32A->lfOrientation = (INT32)font->lfOrientation;
346 font32A->lfWeight = (INT32)font->lfWeight;
347 font32A->lfItalic = font->lfItalic;
348 font32A->lfUnderline = font->lfUnderline;
349 font32A->lfStrikeOut = font->lfStrikeOut;
350 font32A->lfCharSet = font->lfCharSet;
351 font32A->lfOutPrecision = font->lfOutPrecision;
352 font32A->lfClipPrecision = font->lfClipPrecision;
353 font32A->lfQuality = font->lfQuality;
354 font32A->lfPitchAndFamily = font->lfPitchAndFamily;
355 lstrcpyn32A( font32A->lfFaceName, font->lfFaceName, LF_FACESIZE );
359 /***********************************************************************
360 * FONT_LOGFONT16ToLOGFONT32W
362 static void FONT_LOGFONT16ToLOGFONT32W( LPLOGFONT16 font,
363 LPLOGFONT32W font32W )
365 font32W->lfHeight = (INT32)font->lfHeight;
366 font32W->lfWidth = (INT32)font->lfWidth;
367 font32W->lfEscapement = (INT32)font->lfEscapement;
368 font32W->lfOrientation = (INT32)font->lfOrientation;
369 font32W->lfWeight = (INT32)font->lfWeight;
370 font32W->lfItalic = font->lfItalic;
371 font32W->lfUnderline = font->lfUnderline;
372 font32W->lfStrikeOut = font->lfStrikeOut;
373 font32W->lfCharSet = font->lfCharSet;
374 font32W->lfOutPrecision = font->lfOutPrecision;
375 font32W->lfClipPrecision = font->lfClipPrecision;
376 font32W->lfQuality = font->lfQuality;
377 font32W->lfPitchAndFamily = font->lfPitchAndFamily;
378 lstrcpynAtoW( font32W->lfFaceName, font->lfFaceName, LF_FACESIZE );
382 /***********************************************************************
383 * FONT_GetMetrics
385 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
386 TEXTMETRIC16 * metrics )
388 int average, i, count;
389 unsigned long prop;
391 metrics->tmAscent = xfont->ascent;
392 metrics->tmDescent = xfont->descent;
393 metrics->tmHeight = xfont->ascent + xfont->descent;
395 metrics->tmInternalLeading = 0;
396 if (XGetFontProperty( xfont, XA_CAP_HEIGHT, &prop ))
397 metrics->tmInternalLeading = xfont->ascent+xfont->descent-(INT16)prop;
399 metrics->tmExternalLeading = 0;
400 metrics->tmMaxCharWidth = xfont->max_bounds.width;
401 metrics->tmWeight = logfont->lfWeight;
402 metrics->tmItalic = logfont->lfItalic;
403 metrics->tmUnderlined = logfont->lfUnderline;
404 metrics->tmStruckOut = logfont->lfStrikeOut;
405 metrics->tmFirstChar = xfont->min_char_or_byte2;
406 metrics->tmLastChar = xfont->max_char_or_byte2;
407 metrics->tmDefaultChar = xfont->default_char;
408 metrics->tmBreakChar = ' ';
409 metrics->tmCharSet = logfont->lfCharSet;
410 metrics->tmOverhang = 0;
411 metrics->tmDigitizedAspectX = 1;
412 metrics->tmDigitizedAspectY = 1;
413 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
415 /* TMPF_FIXED_PITCH bit means variable pitch...Don't you love Microsoft? */
416 if (xfont->min_bounds.width != xfont->max_bounds.width)
417 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
419 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
420 else
422 XCharStruct * charPtr = xfont->per_char;
423 average = count = 0;
424 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
426 if (!CI_NONEXISTCHAR( charPtr ))
428 average += charPtr->width;
429 count++;
431 charPtr++;
433 if (count) average = (average + count/2) / count;
435 metrics->tmAveCharWidth = average;
438 /***********************************************************************
439 * GetGlyphOutLine (GDI.309)
441 DWORD GetGlyphOutLine( HDC16 hdc, UINT uChar, UINT fuFormat,
442 LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPSTR lpBuffer,
443 LPMAT2 lpmat2)
445 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
446 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
447 return (DWORD)-1; /* failure */
451 /***********************************************************************
452 * CreateScalableFontResource (GDI.310)
454 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
455 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
457 /* fHidden=1 - only visible for the calling app, read-only, not
458 * enumbered with EnumFonts/EnumFontFamilies
459 * lpszCurrentPath can be NULL
461 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
462 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
463 return FALSE; /* create failed */
467 /***********************************************************************
468 * CreateFontIndirect16 (GDI.57)
470 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
472 FONTOBJ * fontPtr;
473 HFONT16 hfont;
475 if (!font)
477 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
478 return 0;
480 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
481 if (!hfont) return 0;
482 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
483 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
484 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
485 font, font->lfHeight, font->lfWidth, hfont);
486 return hfont;
490 /***********************************************************************
491 * CreateFontIndirect32A (GDI32.44)
493 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
495 LOGFONT16 font16;
497 FONT_LOGFONT32AToLOGFONT16(font,&font16);
499 return CreateFontIndirect16( &font16 );
503 /***********************************************************************
504 * CreateFontIndirect32W (GDI32.45)
506 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
508 LOGFONT16 font16;
510 FONT_LOGFONT32WToLOGFONT16(font,&font16);
511 return CreateFontIndirect16( &font16 );
515 /***********************************************************************
516 * CreateFont16 (GDI.56)
518 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
519 INT16 weight, BYTE italic, BYTE underline,
520 BYTE strikeout, BYTE charset, BYTE outpres,
521 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
523 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
524 strikeout, charset, outpres, clippres, quality, pitch, };
525 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
526 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
527 else logfont.lfFaceName[0] = '\0';
528 return CreateFontIndirect16( &logfont );
533 /*************************************************************************
534 * CreateFont32A (GDI32.43)
536 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
537 INT32 weight, DWORD italic, DWORD underline,
538 DWORD strikeout, DWORD charset, DWORD outpres,
539 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
541 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
542 underline, strikeout, charset, outpres,
543 clippres, quality, pitch, name );
547 /*************************************************************************
548 * CreateFont32W (GDI32.46)
550 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
551 INT32 weight, DWORD italic, DWORD underline,
552 DWORD strikeout, DWORD charset, DWORD outpres,
553 DWORD clippres, DWORD quality, DWORD pitch,
554 LPCWSTR name )
556 LPSTR namea = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
557 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
558 italic, underline, strikeout, charset,
559 outpres, clippres, quality, pitch,
560 namea );
561 HeapFree( GetProcessHeap(), 0, namea );
562 return ret;
566 /***********************************************************************
567 * FONT_GetObject16
569 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
571 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
572 memcpy( buffer, &font->logfont, count );
573 return count;
577 /***********************************************************************
578 * FONT_GetObject32A
580 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
582 LOGFONT32A fnt32;
584 memset(&fnt32, 0, sizeof(fnt32));
585 fnt32.lfHeight = font->logfont.lfHeight;
586 fnt32.lfWidth = font->logfont.lfWidth;
587 fnt32.lfEscapement = font->logfont.lfEscapement;
588 fnt32.lfOrientation = font->logfont.lfOrientation;
589 fnt32.lfWeight = font->logfont.lfWeight;
590 fnt32.lfItalic = font->logfont.lfItalic;
591 fnt32.lfUnderline = font->logfont.lfUnderline;
592 fnt32.lfStrikeOut = font->logfont.lfStrikeOut;
593 fnt32.lfCharSet = font->logfont.lfCharSet;
594 fnt32.lfOutPrecision = font->logfont.lfOutPrecision;
595 fnt32.lfClipPrecision = font->logfont.lfClipPrecision;
596 fnt32.lfQuality = font->logfont.lfQuality;
597 fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
598 strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
599 sizeof(fnt32.lfFaceName) );
601 if (count > sizeof(fnt32)) count = sizeof(fnt32);
602 memcpy( buffer, &fnt32, count );
603 return count;
607 /***********************************************************************
608 * FONT_SelectObject
610 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
612 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
614 static struct {
615 HFONT16 id;
616 LOGFONT16 logfont;
617 int access;
618 int used;
619 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
620 int i;
622 X_PHYSFONT * stockPtr;
623 HFONT16 prevHandle = dc->w.hFont;
624 XFontStruct * fontStruct;
625 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
627 #if 0 /* From the code in SelectObject, this can not happen */
628 /* Load font if necessary */
629 if (!font)
631 HFONT16 hnewfont;
633 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
634 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
635 DEFAULT_QUALITY, FF_DONTCARE, "*" );
636 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
638 #endif
640 if (dc->header.wMagic == METAFILE_DC_MAGIC)
641 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
642 return prevHandle;
643 else
644 return 0;
646 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
647 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
648 else {
649 stockPtr = NULL;
651 * Ok, It's not a stock font but
652 * may be it's cached in dynamic cache
654 for(i=0; i<FONTCACHE; i++) /* search for same handle */
655 if (cacheFonts[i].id==hfont) { /* Got the handle */
657 * Check if Handle matches the font
659 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
660 /* No: remove handle id from dynamic font cache */
661 cacheFonts[i].access=0;
662 cacheFonts[i].used=0;
663 cacheFonts[i].id=0;
664 /* may be there is an unused handle which contains the font */
665 for(i=0; i<FONTCACHE; i++) {
666 if((cacheFonts[i].used == 0) &&
667 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
668 /* got it load from cache and set new handle id */
669 stockPtr = &cacheFonts[i].cacheFont;
670 cacheFonts[i].access=1;
671 cacheFonts[i].used=1;
672 cacheFonts[i].id=hfont;
673 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
674 break;
679 else {
680 /* Yes: load from dynamic font cache */
681 stockPtr = &cacheFonts[i].cacheFont;
682 cacheFonts[i].access++;
683 cacheFonts[i].used++;
685 break;
688 if (!stockPtr || !stockPtr->fstruct)
690 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
692 /* If it is not a stock font, we can simply return 0 */
693 if (!stockPtr) return 0;
694 /* Otherwise we must try to find a substitute */
695 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
696 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
697 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
698 fontStruct = XLoadQueryFont( display, "fixed" );
699 if (!fontStruct)
701 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
702 exit( 1 );
706 else
708 fontStruct = stockPtr->fstruct;
709 dprintf_font(stddeb,
710 "FONT_SelectObject: Loaded font from cache %04x %p\n",
711 hfont, fontStruct );
714 /* Unuse previous font */
715 for (i=0; i < FONTCACHE; i++) {
716 if (cacheFonts[i].id == prevHandle) {
717 if(cacheFonts[i].used == 0)
718 fprintf(stderr, "Trying to decrement a use count of 0.\n");
719 else
720 cacheFonts[i].used--;
724 /* Store font */
725 dc->w.hFont = hfont;
726 if (stockPtr)
728 if (!stockPtr->fstruct)
730 stockPtr->fstruct = fontStruct;
731 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
733 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
735 else
738 * Check in cacheFont
740 cacheFontsMin=NULL;
741 for (i=0; i < FONTCACHE; i++) {
742 if (cacheFonts[i].used==0)
743 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
744 cacheFontsMin=&cacheFonts[i];
746 if (!cacheFontsMin) {
747 fprintf(stderr,"No unused font cache entry !!!!\n" );
748 return prevHandle;
750 if (cacheFontsMin->id!=0) {
751 dprintf_font(stddeb,
752 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
753 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
755 cacheFontsMin->cacheFont.fstruct = fontStruct;
756 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
757 cacheFontsMin->access=1;
758 cacheFontsMin->used=1;
759 cacheFontsMin->id=hfont;
760 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
761 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
764 return prevHandle;
768 /***********************************************************************
769 * GetTextCharacterExtra16 (GDI.89)
771 INT16 GetTextCharacterExtra16( HDC16 hdc )
773 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
774 if (!dc) return 0;
775 return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
776 / dc->vportExtX );
780 /***********************************************************************
781 * GetTextCharacterExtra32 (GDI32.225)
783 INT32 GetTextCharacterExtra32( HDC32 hdc )
785 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
786 if (!dc) return 0;
787 return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
788 / dc->vportExtX );
792 /***********************************************************************
793 * SetTextCharacterExtra16 (GDI.8)
795 INT16 SetTextCharacterExtra16( HDC16 hdc, INT16 extra )
797 return (INT16)SetTextCharacterExtra32( hdc, extra );
801 /***********************************************************************
802 * SetTextCharacterExtra32 (GDI32.337)
804 INT32 SetTextCharacterExtra32( HDC32 hdc, INT32 extra )
806 INT32 prev;
807 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
808 if (!dc) return 0;
809 extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;
810 prev = dc->w.charExtra;
811 dc->w.charExtra = abs(extra);
812 return (prev * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
816 /***********************************************************************
817 * SetTextJustification16 (GDI.10)
819 INT16 SetTextJustification16( HDC16 hdc, INT16 extra, INT16 breaks )
821 return SetTextJustification32( hdc, extra, breaks );
825 /***********************************************************************
826 * SetTextJustification32 (GDI32.339)
828 BOOL32 SetTextJustification32( HDC32 hdc, INT32 extra, INT32 breaks )
830 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
831 if (!dc) return 0;
833 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
834 if (!extra) breaks = 0;
835 dc->w.breakTotalExtra = extra;
836 dc->w.breakCount = breaks;
837 if (breaks)
839 dc->w.breakExtra = extra / breaks;
840 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
842 else
844 dc->w.breakExtra = 0;
845 dc->w.breakRem = 0;
847 return 1;
851 /***********************************************************************
852 * GetTextFace16 (GDI.92)
854 INT16 GetTextFace16( HDC16 hdc, INT16 count, LPSTR name )
856 return GetTextFace32A(hdc,count,name);
859 /***********************************************************************
860 * GetTextFace32A (GDI32.234)
862 INT32 GetTextFace32A( HDC32 hdc, INT32 count, LPSTR name )
864 FONTOBJ *font;
866 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
867 if (!dc) return 0;
868 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
869 return 0;
870 lstrcpyn32A( name, font->logfont.lfFaceName, count );
871 return strlen(name);
874 /***********************************************************************
875 * GetTextFace32W (GDI32.235)
877 INT32 GetTextFace32W( HDC32 hdc, INT32 count, LPWSTR name )
879 LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, count );
880 INT32 res = GetTextFace32A(hdc,count,nameA);
881 lstrcpyAtoW( name, nameA );
882 HeapFree( GetProcessHeap(), 0, nameA );
883 return res;
887 /***********************************************************************
888 * GetTextExtent (GDI.91)
890 DWORD GetTextExtent( HDC16 hdc, LPCSTR str, INT16 count )
892 SIZE16 size;
893 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
894 return MAKELONG( size.cx, size.cy );
898 /***********************************************************************
899 * GetTextExtentPoint16 (GDI.471)
901 * FIXME: Should this have a bug for compatibility?
902 * Original Windows versions of GetTextExtentPoint{A,W} have documented
903 * bugs.
905 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
907 SIZE32 size32;
908 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
909 CONV_SIZE32TO16( &size32, size );
910 return (BOOL16)ret;
914 /***********************************************************************
915 * GetTextExtentPoint32A (GDI32.230)
917 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
918 LPSIZE32 size )
920 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
921 if (!dc)
923 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
924 return FALSE;
927 if (!dc->funcs->pGetTextExtentPoint ||
928 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
929 return FALSE;
931 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
932 hdc, count, str, count, size, size->cx, size->cy );
933 return TRUE;
937 /***********************************************************************
938 * GetTextExtentPoint32W (GDI32.231)
940 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
941 LPSIZE32 size )
943 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
944 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
945 HeapFree( GetProcessHeap(), 0, p );
946 return ret;
949 /***********************************************************************
950 * GetTextExtentPoint32ABuggy (GDI32.232)
952 BOOL32 GetTextExtentPoint32ABuggy( HDC32 hdc, LPCSTR str, INT32 count,
953 LPSIZE32 size )
955 dprintf_font( stddeb, "GetTextExtentPoint32ABuggy: not bug compatible.\n");
956 return GetTextExtentPoint32A( hdc, str, count, size );
959 /***********************************************************************
960 * GetTextExtentPoint32WBuggy (GDI32.233)
962 BOOL32 GetTextExtentPoint32WBuggy( HDC32 hdc, LPCWSTR str, INT32 count,
963 LPSIZE32 size )
965 dprintf_font( stddeb, "GetTextExtentPoint32WBuggy: not bug compatible.\n");
966 return GetTextExtentPoint32W( hdc, str, count, size );
970 /***********************************************************************
971 * GetTextExtentExPoint32A (GDI32.228)
973 BOOL32 GetTextExtentExPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
974 INT32 maxExt,LPINT32 lpnFit, LPINT32 alpDx,
975 LPSIZE32 size )
977 int index;
978 SIZE32 tSize;
979 int nFit=0;
980 int extent=0;
981 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
982 if (!dc)
984 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
985 return FALSE;
987 if (!dc->funcs->pGetTextExtentPoint) return FALSE;
989 size->cx=0; size->cy=0;
990 for(index=0;index<count;index++)
992 if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
993 if(extent+tSize.cx<maxExt)
995 extent+=tSize.cx;
996 nFit++;
997 str++;
998 if(alpDx) alpDx[index]=extent;
999 if(tSize.cy > size->cy) size->cy=tSize.cy;
1001 else break;
1003 size->cx=extent;
1004 *lpnFit=nFit;
1005 dprintf_font(stddeb,"GetTextExtentExPoint32A(%08x '%.*s' %d) returning %d %d %d\n",
1006 hdc,count,str,maxExt,nFit, size->cx,size->cy);
1007 return TRUE;
1010 /***********************************************************************
1011 * GetTextExtentExPoint32W (GDI32.229)
1014 BOOL32 GetTextExtentExPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
1015 INT32 maxExt, LPINT32 lpnFit, LPINT32 alpDx,
1016 LPSIZE32 size )
1018 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
1019 BOOL32 ret = GetTextExtentExPoint32A( hdc, p, count, maxExt,
1020 lpnFit, alpDx, size);
1021 HeapFree( GetProcessHeap(), 0, p );
1022 return ret;
1025 /***********************************************************************
1026 * GetTextMetrics16 (GDI.93)
1028 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
1030 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1031 if (!dc) return FALSE;
1032 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
1034 metrics->tmAscent = abs( metrics->tmAscent
1035 * dc->wndExtY / dc->vportExtY );
1036 metrics->tmDescent = abs( metrics->tmDescent
1037 * dc->wndExtY / dc->vportExtY );
1038 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
1039 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
1040 * dc->wndExtY / dc->vportExtY );
1041 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
1042 * dc->wndExtY / dc->vportExtY );
1043 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
1044 * dc->wndExtX / dc->vportExtX );
1045 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
1046 * dc->wndExtX / dc->vportExtX );
1048 dprintf_font(stdnimp,"text metrics:\n
1049 InternalLeading = %i
1050 ExternalLeading = %i
1051 MaxCharWidth = %i
1052 Weight = %i
1053 Italic = %i
1054 Underlined = %i
1055 StruckOut = %i
1056 FirstChar = %i
1057 LastChar = %i
1058 DefaultChar = %i
1059 BreakChar = %i
1060 CharSet = %i
1061 Overhang = %i
1062 DigitizedAspectX = %i
1063 DigitizedAspectY = %i
1064 AveCharWidth = %i
1065 MaxCharWidth = %i
1066 Ascent = %i
1067 Descent = %i
1068 Height = %i\n",
1069 metrics->tmInternalLeading,
1070 metrics->tmExternalLeading,
1071 metrics->tmMaxCharWidth,
1072 metrics->tmWeight,
1073 metrics->tmItalic,
1074 metrics->tmUnderlined,
1075 metrics->tmStruckOut,
1076 metrics->tmFirstChar,
1077 metrics->tmLastChar,
1078 metrics->tmDefaultChar,
1079 metrics->tmBreakChar,
1080 metrics->tmCharSet,
1081 metrics->tmOverhang,
1082 metrics->tmDigitizedAspectX,
1083 metrics->tmDigitizedAspectY,
1084 metrics->tmAveCharWidth,
1085 metrics->tmMaxCharWidth,
1086 metrics->tmAscent,
1087 metrics->tmDescent,
1088 metrics->tmHeight);
1090 return TRUE;
1094 /***********************************************************************
1095 * GetTextMetrics32A (GDI32.236)
1097 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
1099 TEXTMETRIC16 tm;
1100 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1101 metrics->tmHeight = tm.tmHeight;
1102 metrics->tmAscent = tm.tmAscent;
1103 metrics->tmDescent = tm.tmDescent;
1104 metrics->tmInternalLeading = tm.tmInternalLeading;
1105 metrics->tmExternalLeading = tm.tmExternalLeading;
1106 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1107 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1108 metrics->tmWeight = tm.tmWeight;
1109 metrics->tmOverhang = tm.tmOverhang;
1110 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1111 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1112 metrics->tmFirstChar = tm.tmFirstChar;
1113 metrics->tmLastChar = tm.tmLastChar;
1114 metrics->tmDefaultChar = tm.tmDefaultChar;
1115 metrics->tmBreakChar = tm.tmBreakChar;
1116 metrics->tmItalic = tm.tmItalic;
1117 metrics->tmUnderlined = tm.tmUnderlined;
1118 metrics->tmStruckOut = tm.tmStruckOut;
1119 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1120 metrics->tmCharSet = tm.tmCharSet;
1121 return TRUE;
1125 /***********************************************************************
1126 * GetTextMetrics32W (GDI32.237)
1128 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
1130 TEXTMETRIC16 tm;
1131 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1132 metrics->tmHeight = tm.tmHeight;
1133 metrics->tmAscent = tm.tmAscent;
1134 metrics->tmDescent = tm.tmDescent;
1135 metrics->tmInternalLeading = tm.tmInternalLeading;
1136 metrics->tmExternalLeading = tm.tmExternalLeading;
1137 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1138 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1139 metrics->tmWeight = tm.tmWeight;
1140 metrics->tmOverhang = tm.tmOverhang;
1141 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1142 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1143 metrics->tmFirstChar = tm.tmFirstChar;
1144 metrics->tmLastChar = tm.tmLastChar;
1145 metrics->tmDefaultChar = tm.tmDefaultChar;
1146 metrics->tmBreakChar = tm.tmBreakChar;
1147 metrics->tmItalic = tm.tmItalic;
1148 metrics->tmUnderlined = tm.tmUnderlined;
1149 metrics->tmStruckOut = tm.tmStruckOut;
1150 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1151 metrics->tmCharSet = tm.tmCharSet;
1152 return TRUE;
1156 /***********************************************************************
1157 * SetMapperFlags (GDI.349)
1159 DWORD SetMapperFlags(HDC16 hDC, DWORD dwFlag)
1161 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
1162 hDC, dwFlag);
1163 return 0L;
1167 /***********************************************************************
1168 * GetCharABCWidths16 (GDI.307)
1170 BOOL16 GetCharABCWidths16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1171 LPABC16 abc )
1173 ABC32 abc32;
1174 if (!GetCharABCWidths32A( hdc, firstChar, lastChar, &abc32 )) return FALSE;
1175 abc->abcA = abc32.abcA;
1176 abc->abcB = abc32.abcB;
1177 abc->abcC = abc32.abcC;
1178 return TRUE;
1182 /***********************************************************************
1183 * GetCharABCWidths32A (GDI32.149)
1185 BOOL32 GetCharABCWidths32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1186 LPABC32 abc )
1188 /* No TrueType fonts in Wine so far */
1189 fprintf( stdnimp, "STUB: GetCharABCWidths(%04x,%04x,%04x,%p)\n",
1190 hdc, firstChar, lastChar, abc );
1191 return FALSE;
1195 /***********************************************************************
1196 * GetCharABCWidths32W (GDI32.152)
1198 BOOL32 GetCharABCWidths32W( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1199 LPABC32 abc )
1201 return GetCharABCWidths32A( hdc, firstChar, lastChar, abc );
1205 /***********************************************************************
1206 * GetCharWidth16 (GDI.350)
1208 BOOL16 GetCharWidth16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1209 LPINT16 buffer )
1211 int i, width;
1212 XFontStruct *xfont;
1213 XCharStruct *cs, *def;
1215 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1216 if (!dc) return FALSE;
1217 xfont = dc->u.x.font.fstruct;
1219 /* fixed font? */
1220 if (xfont->per_char == NULL)
1222 for (i = firstChar; i <= lastChar; i++)
1223 *buffer++ = xfont->max_bounds.width;
1224 return TRUE;
1227 CI_GET_DEFAULT_INFO(xfont, def);
1229 for (i = firstChar; i <= lastChar; i++)
1231 CI_GET_CHAR_INFO( xfont, i, def, cs );
1232 width = cs ? cs->width : xfont->max_bounds.width;
1233 *buffer++ = MAX( width, 0 );
1235 return TRUE;
1239 /***********************************************************************
1240 * GetCharWidth32A (GDI32.155)
1242 BOOL32 GetCharWidth32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1243 LPINT32 buffer )
1245 int i, width;
1246 XFontStruct *xfont;
1247 XCharStruct *cs, *def;
1249 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1250 if (!dc) return FALSE;
1251 xfont = dc->u.x.font.fstruct;
1253 /* fixed font? */
1254 if (xfont->per_char == NULL)
1256 for (i = firstChar; i <= lastChar; i++)
1257 *buffer++ = xfont->max_bounds.width;
1258 return TRUE;
1261 CI_GET_DEFAULT_INFO(xfont, def);
1263 for (i = firstChar; i <= lastChar; i++)
1265 CI_GET_CHAR_INFO( xfont, i, def, cs );
1266 width = cs ? cs->width : xfont->max_bounds.width;
1267 *buffer++ = MAX( width, 0 );
1269 return TRUE;
1273 /***********************************************************************
1274 * GetCharWidth32W (GDI32.158)
1276 BOOL32 GetCharWidth32W( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1277 LPINT32 buffer )
1279 return GetCharWidth32A( hdc, firstChar, lastChar, buffer );
1283 /***********************************************************************
1284 * AddFontResource (GDI.119)
1286 INT AddFontResource( LPCSTR str )
1288 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1289 return 1;
1293 /***********************************************************************
1294 * RemoveFontResource (GDI.136)
1296 BOOL RemoveFontResource( LPSTR str )
1298 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1299 return TRUE;
1303 /*************************************************************************
1304 * ParseFontParms [internal]
1306 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1308 int i;
1309 if (lpFont == NULL) return 0;
1310 if (lpRetStr == NULL) return 0;
1311 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1312 if (*lpFont == '-') i++;
1313 lpFont++;
1315 if (i == wParmsNo) {
1316 if (*lpFont == '-') lpFont++;
1317 wMaxSiz--;
1318 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1319 *(lpRetStr + i) = *lpFont++;
1320 *(lpRetStr + i) = '\0';
1321 return i;
1323 else
1324 lpRetStr[0] = '\0';
1325 return 0;
1329 /*************************************************************************
1330 * InitFontsList [internal]
1333 static int logfcmp(const void *a,const void *b)
1335 return lstrcmpi32A( (*(LPLOGFONT16 *)a)->lfFaceName,
1336 (*(LPLOGFONT16 *)b)->lfFaceName );
1339 void InitFontsList(void)
1341 char str[32];
1342 char pattern[100];
1343 char *family, *weight, *charset;
1344 char **names;
1345 char slant, spacing;
1346 int i, count;
1347 LPLOGFONT16 lpNewFont;
1349 dprintf_font(stddeb,"InitFontsList !\n");
1351 weight = "medium";
1352 slant = 'r';
1353 spacing = '*';
1354 charset = "*";
1355 family = "*-*";
1357 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1358 family, weight, slant, spacing, charset);
1359 names = XListFonts( display, pattern, MAX_FONTS, &count );
1360 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1362 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1363 if (lpNewFont == NULL) {
1364 dprintf_font(stddeb,
1365 "InitFontsList // Error alloc new font structure !\n");
1366 XFreeFontNames(names);
1367 return;
1370 for (i = 0; i < count; i++) {
1371 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1373 ParseFontParms(names[i], 2, str, sizeof(str));
1374 strcpy(lpNewFont->lfFaceName, str);
1375 ParseFontParms(names[i], 8, str, sizeof(str));
1376 lpNewFont->lfHeight = atoi(str) / 10;
1377 ParseFontParms(names[i], 12, str, sizeof(str));
1378 lpNewFont->lfWidth = atoi(str) / 10;
1379 lpNewFont->lfEscapement = 0;
1380 lpNewFont->lfOrientation = 0;
1381 lpNewFont->lfWeight = FW_REGULAR;
1382 lpNewFont->lfItalic = 0;
1383 lpNewFont->lfUnderline = 0;
1384 lpNewFont->lfStrikeOut = 0;
1385 ParseFontParms(names[i], 13, str, sizeof(str));
1386 if (strcmp(str, "iso8859") == 0) {
1387 lpNewFont->lfCharSet = ANSI_CHARSET;
1388 } else {
1389 lpNewFont->lfCharSet = OEM_CHARSET;
1391 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1392 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1393 lpNewFont->lfQuality = DEFAULT_QUALITY;
1394 ParseFontParms(names[i], 11, str, sizeof(str));
1395 switch(str[0]) {
1396 case 'p':
1397 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1398 break;
1399 case 'm':
1400 case 'c':
1401 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1402 break;
1403 default:
1404 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1405 break;
1407 dprintf_font( stddeb,
1408 "InitFontsList // lpNewFont->lfHeight=%d\n",
1409 lpNewFont->lfHeight );
1410 dprintf_font( stddeb,
1411 "InitFontsList // lpNewFont->lfWidth=%d\n",
1412 lpNewFont->lfWidth );
1413 dprintf_font( stddeb,
1414 "InitFontsList // lfFaceName='%s'\n",
1415 lpNewFont->lfFaceName );
1416 lpLogFontList[i] = lpNewFont;
1417 lpNewFont = (LPLOGFONT16)
1418 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1420 lpLogFontList[i] = NULL;
1422 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1423 XFreeFontNames(names);
1426 /*************************************************************************
1427 * EnumFonts [GDI.70]
1428 * We reuse EnumFontFamilies* for the callback function get the same
1429 * structs (+ extra stuff at the end which will be ignored by the enum funcs)
1431 INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1433 return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData);
1436 /*************************************************************************
1437 * EnumFontsA [GDI32.84]
1439 INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1441 return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData);
1444 /*************************************************************************
1445 * EnumFontsA [GDI32.84]
1447 INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1449 return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData);
1452 /*************************************************************************
1453 * EnumFontFamilies [GDI.330]
1455 INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1457 LOGFONT16 LF;
1459 if (lpszFamily)
1460 strcpy(LF.lfFaceName,lpszFamily);
1461 else
1462 LF.lfFaceName[0]='\0';
1463 LF.lfCharSet = DEFAULT_CHARSET;
1465 return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0);
1468 /*************************************************************************
1469 * EnumFontFamiliesA [GDI32.80]
1471 INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1473 LOGFONT32A LF;
1475 if (lpszFamily)
1476 strcpy(LF.lfFaceName,lpszFamily);
1477 else
1478 LF.lfFaceName[0]='\0';
1479 LF.lfCharSet = DEFAULT_CHARSET;
1481 return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0);
1484 /*************************************************************************
1485 * EnumFontFamiliesW [GDI32.83]
1487 INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1489 LOGFONT32W LF;
1491 if (lpszFamilyW)
1492 lstrcpy32W(LF.lfFaceName,lpszFamilyW);
1493 else
1494 LF.lfFaceName[0]=0;
1495 LF.lfCharSet = DEFAULT_CHARSET;
1496 return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0);
1499 /*************************************************************************
1500 * EnumFontFamiliesEx [GDI.618]
1501 * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures.
1502 * (applies to all EnumFontFamiliesEx*)
1503 * winelib/16 support.
1505 INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved)
1507 HLOCAL16 hLog;
1508 HLOCAL16 hMet;
1509 HFONT16 hFont;
1510 HFONT16 hOldFont;
1511 LPENUMLOGFONTEX16 lpEnumLogFont;
1512 LPNEWTEXTMETRICEX16 lptm;
1513 LPSTR lpOldName;
1514 char FaceName[LF_FACESIZE];
1515 int nRet = 0;
1516 int i;
1518 dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n",
1519 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved);
1520 if (lpEnumFunc == 0) return 0;
1521 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) );
1522 lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog);
1523 if (lpEnumLogFont == NULL) {
1524 fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n");
1525 return 0;
1527 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) );
1528 lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet);
1529 if (lptm == NULL) {
1530 GDI_HEAP_FREE(hLog);
1531 fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n");
1532 return 0;
1534 lpOldName = NULL;
1535 strcpy(FaceName,lpLF->lfFaceName);
1537 if (lpLogFontList[0] == NULL) InitFontsList();
1538 for(i = 0; lpLogFontList[i] != NULL; i++) {
1539 /* lfCharSet */
1540 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1541 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1542 continue;
1544 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1545 /* lfFaceName */
1546 if (FaceName[0])
1548 if (lstrcmpi32A(FaceName,lpLogFontList[i]->lfFaceName))
1549 continue;
1551 else
1553 if ((lpOldName!=NULL) &&
1554 !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1555 continue;
1556 lpOldName=lpLogFontList[i]->lfFaceName;
1559 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1560 strcpy(lpEnumLogFont->elfFullName,"");
1561 strcpy(lpEnumLogFont->elfStyle,"");
1562 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1563 hOldFont = SelectObject32(hDC, hFont);
1564 GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm);
1565 SelectObject32(hDC, hOldFont);
1566 DeleteObject32(hFont);
1567 dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1569 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1570 0, lpData );
1571 if (nRet == 0) {
1572 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1573 break;
1576 GDI_HEAP_FREE(hMet);
1577 GDI_HEAP_FREE(hLog);
1578 return nRet;
1581 /*************************************************************************
1582 * EnumFontFamiliesExA [GDI32.81]
1583 * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*)
1585 INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved)
1587 HLOCAL16 hLog;
1588 HLOCAL16 hMet;
1589 HFONT32 hFont;
1590 HFONT32 hOldFont;
1591 LPENUMLOGFONTEX32A lpEnumLogFont;
1592 LPNEWTEXTMETRICEX32A lptm;
1593 LPSTR lpOldName;
1594 char FaceName[LF_FACESIZE];
1595 int nRet = 0;
1596 int i;
1598 dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n",
1599 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved);
1600 if (lpEnumFunc == 0) return 0;
1601 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) );
1602 lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog);
1603 if (lpEnumLogFont == NULL) {
1604 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1605 return 0;
1607 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) );
1608 lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet);
1609 if (lptm == NULL) {
1610 GDI_HEAP_FREE(hLog);
1611 fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n");
1612 return 0;
1614 lpOldName = NULL;
1615 strcpy(FaceName,lpLF->lfFaceName);
1617 if (lpLogFontList[0] == NULL) InitFontsList();
1618 for(i = 0; lpLogFontList[i] != NULL; i++) {
1619 /* lfCharSet */
1620 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1621 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1622 continue;
1624 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1625 /* lfFaceName */
1626 if (FaceName[0]) {
1627 if (lstrcmpi32A(FaceName,lpLogFontList[i]->lfFaceName))
1628 continue;
1629 } else {
1630 if ((lpOldName!=NULL) &&
1631 !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1632 continue;
1633 lpOldName=lpLogFontList[i]->lfFaceName;
1636 FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1637 strcpy(lpEnumLogFont->elfFullName,"");
1638 strcpy(lpEnumLogFont->elfStyle,"");
1639 strcpy(lpEnumLogFont->elfScript,"");
1640 hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont);
1641 hOldFont = SelectObject32(hDC, hFont);
1642 GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm);
1643 SelectObject32(hDC, hOldFont);
1644 DeleteObject32(hFont);
1645 dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1647 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1648 if (nRet == 0) {
1649 dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n");
1650 break;
1653 GDI_HEAP_FREE(hMet);
1654 GDI_HEAP_FREE(hLog);
1655 return nRet;
1659 /*************************************************************************
1660 * EnumFontFamiliesW [GDI32.82]
1662 INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved)
1664 HLOCAL16 hLog;
1665 HLOCAL16 hMet;
1666 HFONT32 hFont;
1667 HFONT32 hOldFont;
1668 LPENUMLOGFONTEX32W lpEnumLogFont;
1669 LPNEWTEXTMETRICEX32W lptm;
1670 LPSTR lpOldName;
1671 int nRet = 0;
1672 int i;
1673 LPSTR lpszFamily;
1675 dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n",
1676 hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved);
1677 if (lpEnumFunc == 0) return 0;
1678 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) );
1679 lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog);
1680 if (lpEnumLogFont == NULL) {
1681 fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
1682 return 0;
1684 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) );
1685 lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet);
1686 if (lptm == NULL) {
1687 GDI_HEAP_FREE(hLog);
1688 fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n");
1689 return 0;
1691 lpOldName = NULL;
1692 lpszFamily = HEAP_strdupWtoA( GetProcessHeap(), 0, lpLF->lfFaceName );
1693 if (lpLogFontList[0] == NULL) InitFontsList();
1694 for(i = 0; lpLogFontList[i] != NULL; i++) {
1695 /* lfCharSet */
1696 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1697 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1698 continue;
1700 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1701 /* lfFaceName */
1702 if (lpszFamily[0]) {
1703 if (lstrcmpi32A(lpszFamily,lpLogFontList[i]->lfFaceName))
1704 continue;
1705 } else {
1706 if ((lpOldName!=NULL) &&
1707 !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1708 continue;
1709 lpOldName=lpLogFontList[i]->lfFaceName;
1712 FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1713 lpEnumLogFont->elfFullName[0] = 0;
1714 lpEnumLogFont->elfStyle[0] = 0;
1715 lpEnumLogFont->elfScript[0] = 0;
1716 hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont);
1717 hOldFont = SelectObject32(hDC, hFont);
1718 GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm);
1719 SelectObject32(hDC, hOldFont);
1720 DeleteObject32(hFont);
1721 dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1723 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1724 if (nRet == 0) {
1725 dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n");
1726 break;
1729 GDI_HEAP_FREE(hMet);
1730 GDI_HEAP_FREE(hLog);
1731 HeapFree( GetProcessHeap(), 0, lpszFamily );
1732 return nRet;
1736 /*************************************************************************
1737 * GetRasterizerCaps [GDI.313]
1740 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1742 /* This is not much more than a dummy */
1743 RASTERIZER_STATUS rs;
1745 rs.nSize = sizeof(rs);
1746 rs.wFlags = 0;
1747 rs.nLanguageID = 0;
1748 return True;
1751 /*************************************************************************
1752 * GetKerningPairs [GDI.332]
1754 int GetKerningPairs(HDC16 hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1756 /* This has to be dealt with when proper font handling is in place
1758 * At this time kerning is ignored (set to 0)
1761 int i;
1762 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1763 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1764 return 0;