Release 961222
[wine/multimedia.git] / objects / font.c
blobcc54c0b05b0a534c406603797af7250fdaa4b628
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 ;-) */
283 /*AnsiUpper(font->lfFaceName);*/
285 fontStruct = XLoadQueryFont( display, *names );
286 XFreeFontNames( names );
287 return fontStruct;
291 /***********************************************************************
292 * FONT_LOGFONT32AToLOGFONT16
294 static void FONT_LOGFONT32AToLOGFONT16( const LOGFONT32A *font,
295 LPLOGFONT16 font16 )
297 font16->lfHeight = (INT16)font->lfHeight;
298 font16->lfWidth = (INT16)font->lfWidth;
299 font16->lfEscapement = (INT16)font->lfEscapement;
300 font16->lfOrientation = (INT16)font->lfOrientation;
301 font16->lfWeight = (INT16)font->lfWeight;
302 font16->lfItalic = font->lfItalic;
303 font16->lfUnderline = font->lfUnderline;
304 font16->lfStrikeOut = font->lfStrikeOut;
305 font16->lfCharSet = font->lfCharSet;
306 font16->lfOutPrecision = font->lfOutPrecision;
307 font16->lfClipPrecision = font->lfClipPrecision;
308 font16->lfQuality = font->lfQuality;
309 font16->lfPitchAndFamily = font->lfPitchAndFamily;
310 lstrcpyn32A( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
314 /***********************************************************************
315 * FONT_LOGFONT32WToLOGFONT16
317 static void FONT_LOGFONT32WToLOGFONT16( const LOGFONT32W *font,
318 LPLOGFONT16 font16 )
320 font16->lfHeight = (INT16)font->lfHeight;
321 font16->lfWidth = (INT16)font->lfWidth;
322 font16->lfEscapement = (INT16)font->lfEscapement;
323 font16->lfOrientation = (INT16)font->lfOrientation;
324 font16->lfWeight = (INT16)font->lfWeight;
325 font16->lfItalic = font->lfItalic;
326 font16->lfUnderline = font->lfUnderline;
327 font16->lfStrikeOut = font->lfStrikeOut;
328 font16->lfCharSet = font->lfCharSet;
329 font16->lfOutPrecision = font->lfOutPrecision;
330 font16->lfClipPrecision = font->lfClipPrecision;
331 font16->lfQuality = font->lfQuality;
332 font16->lfPitchAndFamily = font->lfPitchAndFamily;
333 lstrcpynWtoA( font16->lfFaceName, font->lfFaceName, LF_FACESIZE );
337 /***********************************************************************
338 * FONT_LOGFONT16ToLOGFONT32A
340 static void FONT_LOGFONT16ToLOGFONT32A( LPLOGFONT16 font,
341 LPLOGFONT32A font32A )
343 font32A->lfHeight = (INT32)font->lfHeight;
344 font32A->lfWidth = (INT32)font->lfWidth;
345 font32A->lfEscapement = (INT32)font->lfEscapement;
346 font32A->lfOrientation = (INT32)font->lfOrientation;
347 font32A->lfWeight = (INT32)font->lfWeight;
348 font32A->lfItalic = font->lfItalic;
349 font32A->lfUnderline = font->lfUnderline;
350 font32A->lfStrikeOut = font->lfStrikeOut;
351 font32A->lfCharSet = font->lfCharSet;
352 font32A->lfOutPrecision = font->lfOutPrecision;
353 font32A->lfClipPrecision = font->lfClipPrecision;
354 font32A->lfQuality = font->lfQuality;
355 font32A->lfPitchAndFamily = font->lfPitchAndFamily;
356 lstrcpyn32A( font32A->lfFaceName, font->lfFaceName, LF_FACESIZE );
360 /***********************************************************************
361 * FONT_LOGFONT16ToLOGFONT32W
363 static void FONT_LOGFONT16ToLOGFONT32W( LPLOGFONT16 font,
364 LPLOGFONT32W font32W )
366 font32W->lfHeight = (INT32)font->lfHeight;
367 font32W->lfWidth = (INT32)font->lfWidth;
368 font32W->lfEscapement = (INT32)font->lfEscapement;
369 font32W->lfOrientation = (INT32)font->lfOrientation;
370 font32W->lfWeight = (INT32)font->lfWeight;
371 font32W->lfItalic = font->lfItalic;
372 font32W->lfUnderline = font->lfUnderline;
373 font32W->lfStrikeOut = font->lfStrikeOut;
374 font32W->lfCharSet = font->lfCharSet;
375 font32W->lfOutPrecision = font->lfOutPrecision;
376 font32W->lfClipPrecision = font->lfClipPrecision;
377 font32W->lfQuality = font->lfQuality;
378 font32W->lfPitchAndFamily = font->lfPitchAndFamily;
379 lstrcpynAtoW( font32W->lfFaceName, font->lfFaceName, LF_FACESIZE );
383 /***********************************************************************
384 * FONT_GetMetrics
386 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
387 TEXTMETRIC16 * metrics )
389 int average, i, count;
390 unsigned long prop;
392 metrics->tmAscent = xfont->ascent;
393 metrics->tmDescent = xfont->descent;
394 metrics->tmHeight = xfont->ascent + xfont->descent;
396 metrics->tmInternalLeading = 0;
397 if (XGetFontProperty( xfont, XA_CAP_HEIGHT, &prop ))
398 metrics->tmInternalLeading = xfont->ascent+xfont->descent-(INT16)prop;
400 metrics->tmExternalLeading = 0;
401 metrics->tmMaxCharWidth = xfont->max_bounds.width;
402 metrics->tmWeight = logfont->lfWeight;
403 metrics->tmItalic = logfont->lfItalic;
404 metrics->tmUnderlined = logfont->lfUnderline;
405 metrics->tmStruckOut = logfont->lfStrikeOut;
406 metrics->tmFirstChar = xfont->min_char_or_byte2;
407 metrics->tmLastChar = xfont->max_char_or_byte2;
408 metrics->tmDefaultChar = xfont->default_char;
409 metrics->tmBreakChar = ' ';
410 metrics->tmCharSet = logfont->lfCharSet;
411 metrics->tmOverhang = 0;
412 metrics->tmDigitizedAspectX = 1;
413 metrics->tmDigitizedAspectY = 1;
414 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
416 /* TMPF_FIXED_PITCH bit means variable pitch...Don't you love Microsoft? */
417 if (xfont->min_bounds.width != xfont->max_bounds.width)
418 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
420 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
421 else
423 XCharStruct * charPtr = xfont->per_char;
424 average = count = 0;
425 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
427 if (!CI_NONEXISTCHAR( charPtr ))
429 average += charPtr->width;
430 count++;
432 charPtr++;
434 if (count) average = (average + count/2) / count;
436 metrics->tmAveCharWidth = average;
439 /***********************************************************************
440 * GetGlyphOutLine (GDI.309)
442 DWORD GetGlyphOutLine( HDC16 hdc, UINT uChar, UINT fuFormat,
443 LPGLYPHMETRICS lpgm, DWORD cbBuffer, LPSTR lpBuffer,
444 LPMAT2 lpmat2)
446 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
447 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
448 return (DWORD)-1; /* failure */
452 /***********************************************************************
453 * CreateScalableFontResource (GDI.310)
455 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
456 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
458 /* fHidden=1 - only visible for the calling app, read-only, not
459 * enumbered with EnumFonts/EnumFontFamilies
460 * lpszCurrentPath can be NULL
462 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
463 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
464 return FALSE; /* create failed */
468 /***********************************************************************
469 * CreateFontIndirect16 (GDI.57)
471 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
473 FONTOBJ * fontPtr;
474 HFONT16 hfont;
476 if (!font)
478 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
479 return 0;
481 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
482 if (!hfont) return 0;
483 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
484 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT16) );
485 AnsiLower( fontPtr->logfont.lfFaceName );
486 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
487 font, font->lfHeight, font->lfWidth, hfont);
488 return hfont;
492 /***********************************************************************
493 * CreateFontIndirect32A (GDI32.44)
495 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
497 LOGFONT16 font16;
499 FONT_LOGFONT32AToLOGFONT16(font,&font16);
501 return CreateFontIndirect16( &font16 );
505 /***********************************************************************
506 * CreateFontIndirect32W (GDI32.45)
508 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
510 LOGFONT16 font16;
512 FONT_LOGFONT32WToLOGFONT16(font,&font16);
513 return CreateFontIndirect16( &font16 );
517 /***********************************************************************
518 * CreateFont16 (GDI.56)
520 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
521 INT16 weight, BYTE italic, BYTE underline,
522 BYTE strikeout, BYTE charset, BYTE outpres,
523 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
525 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
526 strikeout, charset, outpres, clippres, quality, pitch, };
527 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
528 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
529 else logfont.lfFaceName[0] = '\0';
530 return CreateFontIndirect16( &logfont );
535 /*************************************************************************
536 * CreateFont32A (GDI32.43)
538 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
539 INT32 weight, DWORD italic, DWORD underline,
540 DWORD strikeout, DWORD charset, DWORD outpres,
541 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
543 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
544 underline, strikeout, charset, outpres,
545 clippres, quality, pitch, name );
549 /*************************************************************************
550 * CreateFont32W (GDI32.46)
552 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
553 INT32 weight, DWORD italic, DWORD underline,
554 DWORD strikeout, DWORD charset, DWORD outpres,
555 DWORD clippres, DWORD quality, DWORD pitch,
556 LPCWSTR name )
558 LPSTR namea = HEAP_strdupWtoA( GetProcessHeap(), 0, name );
559 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
560 italic, underline, strikeout, charset,
561 outpres, clippres, quality, pitch,
562 namea );
563 HeapFree( GetProcessHeap(), 0, namea );
564 return ret;
568 /***********************************************************************
569 * FONT_GetObject16
571 INT16 FONT_GetObject16( FONTOBJ * font, INT16 count, LPSTR buffer )
573 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
574 memcpy( buffer, &font->logfont, count );
575 return count;
579 /***********************************************************************
580 * FONT_GetObject32A
582 INT32 FONT_GetObject32A( FONTOBJ *font, INT32 count, LPSTR buffer )
584 LOGFONT32A fnt32;
586 memset(&fnt32, 0, sizeof(fnt32));
587 fnt32.lfHeight = font->logfont.lfHeight;
588 fnt32.lfWidth = font->logfont.lfWidth;
589 fnt32.lfEscapement = font->logfont.lfEscapement;
590 fnt32.lfOrientation = font->logfont.lfOrientation;
591 fnt32.lfWeight = font->logfont.lfWeight;
592 fnt32.lfItalic = font->logfont.lfItalic;
593 fnt32.lfUnderline = font->logfont.lfUnderline;
594 fnt32.lfStrikeOut = font->logfont.lfStrikeOut;
595 fnt32.lfCharSet = font->logfont.lfCharSet;
596 fnt32.lfOutPrecision = font->logfont.lfOutPrecision;
597 fnt32.lfClipPrecision = font->logfont.lfClipPrecision;
598 fnt32.lfQuality = font->logfont.lfQuality;
599 fnt32.lfPitchAndFamily = font->logfont.lfPitchAndFamily;
600 strncpy( fnt32.lfFaceName, font->logfont.lfFaceName,
601 sizeof(fnt32.lfFaceName) );
603 if (count > sizeof(fnt32)) count = sizeof(fnt32);
604 memcpy( buffer, &fnt32, count );
605 return count;
609 /***********************************************************************
610 * FONT_SelectObject
612 HFONT16 FONT_SelectObject( DC * dc, HFONT16 hfont, FONTOBJ * font )
614 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
616 static struct {
617 HFONT16 id;
618 LOGFONT16 logfont;
619 int access;
620 int used;
621 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
622 int i;
624 X_PHYSFONT * stockPtr;
625 HFONT16 prevHandle = dc->w.hFont;
626 XFontStruct * fontStruct;
627 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
629 #if 0 /* From the code in SelectObject, this can not happen */
630 /* Load font if necessary */
631 if (!font)
633 HFONT16 hnewfont;
635 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
636 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
637 DEFAULT_QUALITY, FF_DONTCARE, "*" );
638 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
640 #endif
642 if (dc->header.wMagic == METAFILE_DC_MAGIC)
643 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
644 return prevHandle;
645 else
646 return 0;
648 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
649 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
650 else {
651 stockPtr = NULL;
653 * Ok, It's not a stock font but
654 * may be it's cached in dynamic cache
656 for(i=0; i<FONTCACHE; i++) /* search for same handle */
657 if (cacheFonts[i].id==hfont) { /* Got the handle */
659 * Check if Handle matches the font
661 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
662 /* No: remove handle id from dynamic font cache */
663 cacheFonts[i].access=0;
664 cacheFonts[i].used=0;
665 cacheFonts[i].id=0;
666 /* may be there is an unused handle which contains the font */
667 for(i=0; i<FONTCACHE; i++) {
668 if((cacheFonts[i].used == 0) &&
669 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
670 /* got it load from cache and set new handle id */
671 stockPtr = &cacheFonts[i].cacheFont;
672 cacheFonts[i].access=1;
673 cacheFonts[i].used=1;
674 cacheFonts[i].id=hfont;
675 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
676 break;
681 else {
682 /* Yes: load from dynamic font cache */
683 stockPtr = &cacheFonts[i].cacheFont;
684 cacheFonts[i].access++;
685 cacheFonts[i].used++;
687 break;
690 if (!stockPtr || !stockPtr->fstruct)
692 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
694 /* If it is not a stock font, we can simply return 0 */
695 if (!stockPtr) return 0;
696 /* Otherwise we must try to find a substitute */
697 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
698 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
699 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
700 fontStruct = XLoadQueryFont( display, "fixed" );
701 if (!fontStruct)
703 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
704 exit( 1 );
708 else
710 fontStruct = stockPtr->fstruct;
711 dprintf_font(stddeb,
712 "FONT_SelectObject: Loaded font from cache %04x %p\n",
713 hfont, fontStruct );
716 /* Unuse previous font */
717 for (i=0; i < FONTCACHE; i++) {
718 if (cacheFonts[i].id == prevHandle) {
719 if(cacheFonts[i].used == 0)
720 fprintf(stderr, "Trying to decrement a use count of 0.\n");
721 else
722 cacheFonts[i].used--;
726 /* Store font */
727 dc->w.hFont = hfont;
728 if (stockPtr)
730 if (!stockPtr->fstruct)
732 stockPtr->fstruct = fontStruct;
733 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
735 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
737 else
740 * Check in cacheFont
742 cacheFontsMin=NULL;
743 for (i=0; i < FONTCACHE; i++) {
744 if (cacheFonts[i].used==0)
745 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
746 cacheFontsMin=&cacheFonts[i];
748 if (!cacheFontsMin) {
749 fprintf(stderr,"No unused font cache entry !!!!\n" );
750 return prevHandle;
752 if (cacheFontsMin->id!=0) {
753 dprintf_font(stddeb,
754 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
755 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
757 cacheFontsMin->cacheFont.fstruct = fontStruct;
758 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
759 cacheFontsMin->access=1;
760 cacheFontsMin->used=1;
761 cacheFontsMin->id=hfont;
762 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
763 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
766 return prevHandle;
770 /***********************************************************************
771 * GetTextCharacterExtra16 (GDI.89)
773 INT16 GetTextCharacterExtra16( HDC16 hdc )
775 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
776 if (!dc) return 0;
777 return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
778 / dc->vportExtX );
782 /***********************************************************************
783 * GetTextCharacterExtra32 (GDI32.225)
785 INT32 GetTextCharacterExtra32( HDC32 hdc )
787 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
788 if (!dc) return 0;
789 return abs( (dc->w.charExtra * dc->wndExtX + dc->vportExtX / 2)
790 / dc->vportExtX );
794 /***********************************************************************
795 * SetTextCharacterExtra16 (GDI.8)
797 INT16 SetTextCharacterExtra16( HDC16 hdc, INT16 extra )
799 return (INT16)SetTextCharacterExtra32( hdc, extra );
803 /***********************************************************************
804 * SetTextCharacterExtra32 (GDI32.337)
806 INT32 SetTextCharacterExtra32( HDC32 hdc, INT32 extra )
808 INT32 prev;
809 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
810 if (!dc) return 0;
811 extra = (extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX;
812 prev = dc->w.charExtra;
813 dc->w.charExtra = abs(extra);
814 return (prev * dc->wndExtX + dc->vportExtX / 2) / dc->vportExtX;
818 /***********************************************************************
819 * SetTextJustification16 (GDI.10)
821 INT16 SetTextJustification16( HDC16 hdc, INT16 extra, INT16 breaks )
823 return SetTextJustification32( hdc, extra, breaks );
827 /***********************************************************************
828 * SetTextJustification32 (GDI32.339)
830 BOOL32 SetTextJustification32( HDC32 hdc, INT32 extra, INT32 breaks )
832 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
833 if (!dc) return 0;
835 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
836 if (!extra) breaks = 0;
837 dc->w.breakTotalExtra = extra;
838 dc->w.breakCount = breaks;
839 if (breaks)
841 dc->w.breakExtra = extra / breaks;
842 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
844 else
846 dc->w.breakExtra = 0;
847 dc->w.breakRem = 0;
849 return 1;
853 /***********************************************************************
854 * GetTextFace16 (GDI.92)
856 INT16 GetTextFace16( HDC16 hdc, INT16 count, LPSTR name )
858 return GetTextFace32A(hdc,count,name);
861 /***********************************************************************
862 * GetTextFace32A (GDI32.234)
864 INT32 GetTextFace32A( HDC32 hdc, INT32 count, LPSTR name )
866 FONTOBJ *font;
868 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
869 if (!dc) return 0;
870 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
871 return 0;
872 lstrcpyn32A( name, font->logfont.lfFaceName, count );
873 return strlen(name);
876 /***********************************************************************
877 * GetTextFace32W (GDI32.235)
879 INT32 GetTextFace32W( HDC32 hdc, INT32 count, LPWSTR name )
881 LPSTR nameA = HeapAlloc( GetProcessHeap(), 0, count );
882 INT32 res = GetTextFace32A(hdc,count,nameA);
883 lstrcpyAtoW( name, nameA );
884 HeapFree( GetProcessHeap(), 0, nameA );
885 return res;
889 /***********************************************************************
890 * GetTextExtent (GDI.91)
892 DWORD GetTextExtent( HDC16 hdc, LPCSTR str, INT16 count )
894 SIZE16 size;
895 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
896 return MAKELONG( size.cx, size.cy );
900 /***********************************************************************
901 * GetTextExtentPoint16 (GDI.471)
903 * FIXME: Should this have a bug for compatibility?
904 * Original Windows versions of GetTextExtentPoint{A,W} have documented
905 * bugs.
907 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
909 SIZE32 size32;
910 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
911 CONV_SIZE32TO16( &size32, size );
912 return (BOOL16)ret;
916 /***********************************************************************
917 * GetTextExtentPoint32A (GDI32.230)
919 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
920 LPSIZE32 size )
922 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
923 if (!dc)
925 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
926 return FALSE;
929 if (!dc->funcs->pGetTextExtentPoint ||
930 !dc->funcs->pGetTextExtentPoint( dc, str, count, size ))
931 return FALSE;
933 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
934 hdc, count, str, count, size, size->cx, size->cy );
935 return TRUE;
939 /***********************************************************************
940 * GetTextExtentPoint32W (GDI32.231)
942 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
943 LPSIZE32 size )
945 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
946 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
947 HeapFree( GetProcessHeap(), 0, p );
948 return ret;
951 /***********************************************************************
952 * GetTextExtentPoint32ABuggy (GDI32.232)
954 BOOL32 GetTextExtentPoint32ABuggy( HDC32 hdc, LPCSTR str, INT32 count,
955 LPSIZE32 size )
957 dprintf_font( stddeb, "GetTextExtentPoint32ABuggy: not bug compatible.\n");
958 return GetTextExtentPoint32A( hdc, str, count, size );
961 /***********************************************************************
962 * GetTextExtentPoint32WBuggy (GDI32.233)
964 BOOL32 GetTextExtentPoint32WBuggy( HDC32 hdc, LPCWSTR str, INT32 count,
965 LPSIZE32 size )
967 dprintf_font( stddeb, "GetTextExtentPoint32WBuggy: not bug compatible.\n");
968 return GetTextExtentPoint32W( hdc, str, count, size );
972 /***********************************************************************
973 * GetTextExtentExPoint32A (GDI32.228)
975 BOOL32 GetTextExtentExPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
976 INT32 maxExt,LPINT32 lpnFit, LPINT32 alpDx,
977 LPSIZE32 size )
979 int index;
980 SIZE32 tSize;
981 int nFit=0;
982 int extent=0;
983 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
984 if (!dc)
986 if (!(dc = (DC *)GDI_GetObjPtr( hdc, METAFILE_DC_MAGIC )))
987 return FALSE;
989 if (!dc->funcs->pGetTextExtentPoint) return FALSE;
991 size->cx=0; size->cy=0;
992 for(index=0;index<count;index++)
994 if(!dc->funcs->pGetTextExtentPoint( dc, str, 1, &tSize )) return FALSE;
995 if(extent+tSize.cx<maxExt)
997 extent+=tSize.cx;
998 nFit++;
999 str++;
1000 if(alpDx) alpDx[index]=extent;
1001 if(tSize.cy > size->cy) size->cy=tSize.cy;
1003 else break;
1005 size->cx=extent;
1006 *lpnFit=nFit;
1007 dprintf_font(stddeb,"GetTextExtentExPoint32A(%08x '%.*s' %d) returning %d %d %d\n",
1008 hdc,count,str,maxExt,nFit, size->cx,size->cy);
1009 return TRUE;
1012 /***********************************************************************
1013 * GetTextExtentExPoint32W (GDI32.229)
1016 BOOL32 GetTextExtentExPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
1017 INT32 maxExt, LPINT32 lpnFit, LPINT32 alpDx,
1018 LPSIZE32 size )
1020 LPSTR p = HEAP_strdupWtoA( GetProcessHeap(), 0, str );
1021 BOOL32 ret = GetTextExtentExPoint32A( hdc, p, count, maxExt,
1022 lpnFit, alpDx, size);
1023 HeapFree( GetProcessHeap(), 0, p );
1024 return ret;
1027 /***********************************************************************
1028 * GetTextMetrics16 (GDI.93)
1030 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
1032 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
1033 if (!dc) return FALSE;
1034 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
1036 metrics->tmAscent = abs( metrics->tmAscent
1037 * dc->wndExtY / dc->vportExtY );
1038 metrics->tmDescent = abs( metrics->tmDescent
1039 * dc->wndExtY / dc->vportExtY );
1040 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
1041 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
1042 * dc->wndExtY / dc->vportExtY );
1043 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
1044 * dc->wndExtY / dc->vportExtY );
1045 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
1046 * dc->wndExtX / dc->vportExtX );
1047 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
1048 * dc->wndExtX / dc->vportExtX );
1050 dprintf_font(stdnimp,"text metrics:\n
1051 InternalLeading = %i
1052 ExternalLeading = %i
1053 MaxCharWidth = %i
1054 Weight = %i
1055 Italic = %i
1056 Underlined = %i
1057 StruckOut = %i
1058 FirstChar = %i
1059 LastChar = %i
1060 DefaultChar = %i
1061 BreakChar = %i
1062 CharSet = %i
1063 Overhang = %i
1064 DigitizedAspectX = %i
1065 DigitizedAspectY = %i
1066 AveCharWidth = %i
1067 MaxCharWidth = %i
1068 Ascent = %i
1069 Descent = %i
1070 Height = %i\n",
1071 metrics->tmInternalLeading,
1072 metrics->tmExternalLeading,
1073 metrics->tmMaxCharWidth,
1074 metrics->tmWeight,
1075 metrics->tmItalic,
1076 metrics->tmUnderlined,
1077 metrics->tmStruckOut,
1078 metrics->tmFirstChar,
1079 metrics->tmLastChar,
1080 metrics->tmDefaultChar,
1081 metrics->tmBreakChar,
1082 metrics->tmCharSet,
1083 metrics->tmOverhang,
1084 metrics->tmDigitizedAspectX,
1085 metrics->tmDigitizedAspectY,
1086 metrics->tmAveCharWidth,
1087 metrics->tmMaxCharWidth,
1088 metrics->tmAscent,
1089 metrics->tmDescent,
1090 metrics->tmHeight);
1092 return TRUE;
1096 /***********************************************************************
1097 * GetTextMetrics32A (GDI32.236)
1099 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
1101 TEXTMETRIC16 tm;
1102 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1103 metrics->tmHeight = tm.tmHeight;
1104 metrics->tmAscent = tm.tmAscent;
1105 metrics->tmDescent = tm.tmDescent;
1106 metrics->tmInternalLeading = tm.tmInternalLeading;
1107 metrics->tmExternalLeading = tm.tmExternalLeading;
1108 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1109 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1110 metrics->tmWeight = tm.tmWeight;
1111 metrics->tmOverhang = tm.tmOverhang;
1112 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1113 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1114 metrics->tmFirstChar = tm.tmFirstChar;
1115 metrics->tmLastChar = tm.tmLastChar;
1116 metrics->tmDefaultChar = tm.tmDefaultChar;
1117 metrics->tmBreakChar = tm.tmBreakChar;
1118 metrics->tmItalic = tm.tmItalic;
1119 metrics->tmUnderlined = tm.tmUnderlined;
1120 metrics->tmStruckOut = tm.tmStruckOut;
1121 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1122 metrics->tmCharSet = tm.tmCharSet;
1123 return TRUE;
1127 /***********************************************************************
1128 * GetTextMetrics32W (GDI32.237)
1130 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
1132 TEXTMETRIC16 tm;
1133 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
1134 metrics->tmHeight = tm.tmHeight;
1135 metrics->tmAscent = tm.tmAscent;
1136 metrics->tmDescent = tm.tmDescent;
1137 metrics->tmInternalLeading = tm.tmInternalLeading;
1138 metrics->tmExternalLeading = tm.tmExternalLeading;
1139 metrics->tmAveCharWidth = tm.tmAveCharWidth;
1140 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
1141 metrics->tmWeight = tm.tmWeight;
1142 metrics->tmOverhang = tm.tmOverhang;
1143 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
1144 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
1145 metrics->tmFirstChar = tm.tmFirstChar;
1146 metrics->tmLastChar = tm.tmLastChar;
1147 metrics->tmDefaultChar = tm.tmDefaultChar;
1148 metrics->tmBreakChar = tm.tmBreakChar;
1149 metrics->tmItalic = tm.tmItalic;
1150 metrics->tmUnderlined = tm.tmUnderlined;
1151 metrics->tmStruckOut = tm.tmStruckOut;
1152 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
1153 metrics->tmCharSet = tm.tmCharSet;
1154 return TRUE;
1158 /***********************************************************************
1159 * SetMapperFlags (GDI.349)
1161 DWORD SetMapperFlags(HDC16 hDC, DWORD dwFlag)
1163 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
1164 hDC, dwFlag);
1165 return 0L;
1169 /***********************************************************************
1170 * GetCharABCWidths16 (GDI.307)
1172 BOOL16 GetCharABCWidths16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1173 LPABC16 abc )
1175 ABC32 abc32;
1176 if (!GetCharABCWidths32A( hdc, firstChar, lastChar, &abc32 )) return FALSE;
1177 abc->abcA = abc32.abcA;
1178 abc->abcB = abc32.abcB;
1179 abc->abcC = abc32.abcC;
1180 return TRUE;
1184 /***********************************************************************
1185 * GetCharABCWidths32A (GDI32.149)
1187 BOOL32 GetCharABCWidths32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1188 LPABC32 abc )
1190 /* No TrueType fonts in Wine so far */
1191 fprintf( stdnimp, "STUB: GetCharABCWidths(%04x,%04x,%04x,%p)\n",
1192 hdc, firstChar, lastChar, abc );
1193 return FALSE;
1197 /***********************************************************************
1198 * GetCharABCWidths32W (GDI32.152)
1200 BOOL32 GetCharABCWidths32W( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1201 LPABC32 abc )
1203 return GetCharABCWidths32A( hdc, firstChar, lastChar, abc );
1207 /***********************************************************************
1208 * GetCharWidth16 (GDI.350)
1210 BOOL16 GetCharWidth16( HDC16 hdc, UINT16 firstChar, UINT16 lastChar,
1211 LPINT16 buffer )
1213 int i, width;
1214 XFontStruct *xfont;
1215 XCharStruct *cs, *def;
1217 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1218 if (!dc) return FALSE;
1219 xfont = dc->u.x.font.fstruct;
1221 /* fixed font? */
1222 if (xfont->per_char == NULL)
1224 for (i = firstChar; i <= lastChar; i++)
1225 *buffer++ = xfont->max_bounds.width;
1226 return TRUE;
1229 CI_GET_DEFAULT_INFO(xfont, def);
1231 for (i = firstChar; i <= lastChar; i++)
1233 CI_GET_CHAR_INFO( xfont, i, def, cs );
1234 width = cs ? cs->width : xfont->max_bounds.width;
1235 *buffer++ = MAX( width, 0 );
1237 return TRUE;
1241 /***********************************************************************
1242 * GetCharWidth32A (GDI32.155)
1244 BOOL32 GetCharWidth32A( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1245 LPINT32 buffer )
1247 int i, width;
1248 XFontStruct *xfont;
1249 XCharStruct *cs, *def;
1251 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
1252 if (!dc) return FALSE;
1253 xfont = dc->u.x.font.fstruct;
1255 /* fixed font? */
1256 if (xfont->per_char == NULL)
1258 for (i = firstChar; i <= lastChar; i++)
1259 *buffer++ = xfont->max_bounds.width;
1260 return TRUE;
1263 CI_GET_DEFAULT_INFO(xfont, def);
1265 for (i = firstChar; i <= lastChar; i++)
1267 CI_GET_CHAR_INFO( xfont, i, def, cs );
1268 width = cs ? cs->width : xfont->max_bounds.width;
1269 *buffer++ = MAX( width, 0 );
1271 return TRUE;
1275 /***********************************************************************
1276 * GetCharWidth32W (GDI32.158)
1278 BOOL32 GetCharWidth32W( HDC32 hdc, UINT32 firstChar, UINT32 lastChar,
1279 LPINT32 buffer )
1281 return GetCharWidth32A( hdc, firstChar, lastChar, buffer );
1285 /***********************************************************************
1286 * AddFontResource (GDI.119)
1288 INT AddFontResource( LPCSTR str )
1290 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
1291 return 1;
1295 /***********************************************************************
1296 * RemoveFontResource (GDI.136)
1298 BOOL RemoveFontResource( LPSTR str )
1300 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
1301 return TRUE;
1305 /*************************************************************************
1306 * ParseFontParms [internal]
1308 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1310 int i;
1311 if (lpFont == NULL) return 0;
1312 if (lpRetStr == NULL) return 0;
1313 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1314 if (*lpFont == '-') i++;
1315 lpFont++;
1317 if (i == wParmsNo) {
1318 if (*lpFont == '-') lpFont++;
1319 wMaxSiz--;
1320 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1321 *(lpRetStr + i) = *lpFont++;
1322 *(lpRetStr + i) = '\0';
1323 return i;
1325 else
1326 lpRetStr[0] = '\0';
1327 return 0;
1331 /*************************************************************************
1332 * InitFontsList [internal]
1335 static int logfcmp(const void *a,const void *b)
1337 return lstrcmpi32A( (*(LPLOGFONT16 *)a)->lfFaceName,
1338 (*(LPLOGFONT16 *)b)->lfFaceName );
1341 void InitFontsList(void)
1343 char str[32];
1344 char pattern[100];
1345 char *family, *weight, *charset;
1346 char **names;
1347 char slant, spacing;
1348 int i, count;
1349 LPLOGFONT16 lpNewFont;
1351 dprintf_font(stddeb,"InitFontsList !\n");
1353 weight = "medium";
1354 slant = 'r';
1355 spacing = '*';
1356 charset = "*";
1357 family = "*-*";
1359 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1360 family, weight, slant, spacing, charset);
1361 names = XListFonts( display, pattern, MAX_FONTS, &count );
1362 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1364 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1365 if (lpNewFont == NULL) {
1366 dprintf_font(stddeb,
1367 "InitFontsList // Error alloc new font structure !\n");
1368 XFreeFontNames(names);
1369 return;
1372 for (i = 0; i < count; i++) {
1373 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1375 ParseFontParms(names[i], 2, str, sizeof(str));
1376 /* AnsiUpper(str);*/
1377 strcpy(lpNewFont->lfFaceName, str);
1378 ParseFontParms(names[i], 8, str, sizeof(str));
1379 lpNewFont->lfHeight = atoi(str) / 10;
1380 ParseFontParms(names[i], 12, str, sizeof(str));
1381 lpNewFont->lfWidth = atoi(str) / 10;
1382 lpNewFont->lfEscapement = 0;
1383 lpNewFont->lfOrientation = 0;
1384 lpNewFont->lfWeight = FW_REGULAR;
1385 lpNewFont->lfItalic = 0;
1386 lpNewFont->lfUnderline = 0;
1387 lpNewFont->lfStrikeOut = 0;
1388 ParseFontParms(names[i], 13, str, sizeof(str));
1389 if (strcmp(str, "iso8859") == 0) {
1390 lpNewFont->lfCharSet = ANSI_CHARSET;
1391 } else {
1392 lpNewFont->lfCharSet = OEM_CHARSET;
1394 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1395 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1396 lpNewFont->lfQuality = DEFAULT_QUALITY;
1397 ParseFontParms(names[i], 11, str, sizeof(str));
1398 switch(str[0]) {
1399 case 'p':
1400 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1401 break;
1402 case 'm':
1403 case 'c':
1404 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1405 break;
1406 default:
1407 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1408 break;
1410 dprintf_font( stddeb,
1411 "InitFontsList // lpNewFont->lfHeight=%d\n",
1412 lpNewFont->lfHeight );
1413 dprintf_font( stddeb,
1414 "InitFontsList // lpNewFont->lfWidth=%d\n",
1415 lpNewFont->lfWidth );
1416 dprintf_font( stddeb,
1417 "InitFontsList // lfFaceName='%s'\n",
1418 lpNewFont->lfFaceName );
1419 lpLogFontList[i] = lpNewFont;
1420 lpNewFont = (LPLOGFONT16)
1421 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1423 lpLogFontList[i] = NULL;
1425 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1426 XFreeFontNames(names);
1429 /*************************************************************************
1430 * EnumFonts [GDI.70]
1431 * We reuse EnumFontFamilies* for the callback function get the same
1432 * structs (+ extra stuff at the end which will be ignored by the enum funcs)
1434 INT16 EnumFonts16(HDC16 hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1436 return EnumFontFamilies16(hDC,lpFaceName,lpEnumFunc,lpData);
1439 /*************************************************************************
1440 * EnumFontsA [GDI32.84]
1442 INT32 EnumFonts32A(HDC32 hDC, LPCSTR lpFaceName, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1444 return EnumFontFamilies32A(hDC,lpFaceName,lpEnumFunc,lpData);
1447 /*************************************************************************
1448 * EnumFontsA [GDI32.84]
1450 INT32 EnumFonts32W(HDC32 hDC, LPCWSTR lpFaceName, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1452 return EnumFontFamilies32W(hDC,lpFaceName,lpEnumFunc,lpData);
1455 /*************************************************************************
1456 * EnumFontFamilies [GDI.330]
1458 INT16 EnumFontFamilies16(HDC16 hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1460 LOGFONT16 LF;
1462 if (lpszFamily)
1463 strcpy(LF.lfFaceName,lpszFamily);
1464 else
1465 LF.lfFaceName[0]='\0';
1466 LF.lfCharSet = DEFAULT_CHARSET;
1468 return EnumFontFamiliesEx16(hDC,&LF,(FONTENUMPROCEX16)lpEnumFunc,lpData,0);
1471 /*************************************************************************
1472 * EnumFontFamiliesA [GDI32.80]
1474 INT32 EnumFontFamilies32A(HDC32 hDC, LPCSTR lpszFamily, FONTENUMPROC32A lpEnumFunc, LPARAM lpData)
1476 LOGFONT32A LF;
1478 if (lpszFamily)
1479 strcpy(LF.lfFaceName,lpszFamily);
1480 else
1481 LF.lfFaceName[0]='\0';
1482 LF.lfCharSet = DEFAULT_CHARSET;
1484 return EnumFontFamiliesEx32A(hDC,&LF,(FONTENUMPROCEX32A)lpEnumFunc,lpData,0);
1487 /*************************************************************************
1488 * EnumFontFamiliesW [GDI32.83]
1490 INT32 EnumFontFamilies32W(HDC32 hDC, LPCWSTR lpszFamilyW, FONTENUMPROC32W lpEnumFunc, LPARAM lpData)
1492 LOGFONT32W LF;
1494 if (lpszFamilyW)
1495 lstrcpy32W(LF.lfFaceName,lpszFamilyW);
1496 else
1497 LF.lfFaceName[0]=0;
1498 LF.lfCharSet = DEFAULT_CHARSET;
1499 return EnumFontFamiliesEx32W(hDC,&LF,(FONTENUMPROCEX32W)lpEnumFunc,lpData,0);
1502 /*************************************************************************
1503 * EnumFontFamiliesEx [GDI.618]
1504 * FIXME: fill the rest of the NEWTEXTMETRICEX and ENUMLOGFONTEX structures.
1505 * (applies to all EnumFontFamiliesEx*)
1506 * winelib/16 support.
1508 INT16 EnumFontFamiliesEx16(HDC16 hDC, LPLOGFONT16 lpLF, FONTENUMPROCEX16 lpEnumFunc, LPARAM lpData,DWORD reserved)
1510 HLOCAL16 hLog;
1511 HLOCAL16 hMet;
1512 HFONT16 hFont;
1513 HFONT16 hOldFont;
1514 LPENUMLOGFONTEX16 lpEnumLogFont;
1515 LPNEWTEXTMETRICEX16 lptm;
1516 LPSTR lpOldName;
1517 char FaceName[LF_FACESIZE];
1518 int nRet = 0;
1519 int i;
1521 dprintf_font(stddeb,"EnumFontFamiliesEx(%04x, '%s', %08lx, %08lx, %08lx)\n",
1522 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData, reserved);
1523 if (lpEnumFunc == 0) return 0;
1524 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX16) );
1525 lpEnumLogFont = (LPENUMLOGFONTEX16) GDI_HEAP_LIN_ADDR(hLog);
1526 if (lpEnumLogFont == NULL) {
1527 fprintf(stderr,"EnumFontFamiliesEx // can't alloc LOGFONT struct !\n");
1528 return 0;
1530 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX16) );
1531 lptm = (LPNEWTEXTMETRICEX16) GDI_HEAP_LIN_ADDR(hMet);
1532 if (lptm == NULL) {
1533 GDI_HEAP_FREE(hLog);
1534 fprintf(stderr,"EnumFontFamiliesEx // can't alloc TEXTMETRIC struct !\n");
1535 return 0;
1537 lpOldName = NULL;
1538 strcpy(FaceName,lpLF->lfFaceName);
1539 /* AnsiUpper(lpLF->lfFaceName);*/
1541 if (lpLogFontList[0] == NULL) InitFontsList();
1542 for(i = 0; lpLogFontList[i] != NULL; i++) {
1543 /* lfCharSet */
1544 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1545 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1546 continue;
1548 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1549 /* lfFaceName */
1550 if (FaceName[0])
1552 if (lstrcmpi32A(FaceName,lpLogFontList[i]->lfFaceName))
1553 continue;
1555 else
1557 if ((lpOldName!=NULL) &&
1558 !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1559 continue;
1560 lpOldName=lpLogFontList[i]->lfFaceName;
1563 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1564 strcpy(lpEnumLogFont->elfFullName,"");
1565 strcpy(lpEnumLogFont->elfStyle,"");
1566 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1567 hOldFont = SelectObject32(hDC, hFont);
1568 GetTextMetrics16(hDC, (LPTEXTMETRIC16)lptm);
1569 SelectObject32(hDC, hOldFont);
1570 DeleteObject32(hFont);
1571 dprintf_font(stddeb, "EnumFontFamiliesEx // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1573 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1574 0, lpData );
1575 if (nRet == 0) {
1576 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1577 break;
1580 GDI_HEAP_FREE(hMet);
1581 GDI_HEAP_FREE(hLog);
1582 return nRet;
1585 /*************************************************************************
1586 * EnumFontFamiliesExA [GDI32.81]
1587 * FIXME: Don't use 16 bit GDI heap functions (applies to EnumFontFamiliesEx32*)
1589 INT32 EnumFontFamiliesEx32A(HDC32 hDC, LPLOGFONT32A lpLF,FONTENUMPROCEX32A lpEnumFunc, LPARAM lpData,DWORD reserved)
1591 HLOCAL16 hLog;
1592 HLOCAL16 hMet;
1593 HFONT32 hFont;
1594 HFONT32 hOldFont;
1595 LPENUMLOGFONTEX32A lpEnumLogFont;
1596 LPNEWTEXTMETRICEX32A lptm;
1597 LPSTR lpOldName;
1598 char FaceName[LF_FACESIZE];
1599 int nRet = 0;
1600 int i;
1602 dprintf_font(stddeb,"EnumFontFamilies32A(%04x, %p, %08lx, %08lx, %08lx)\n",
1603 hDC, lpLF->lfFaceName, (DWORD)lpEnumFunc, lpData,reserved);
1604 if (lpEnumFunc == 0) return 0;
1605 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32A) );
1606 lpEnumLogFont = (LPENUMLOGFONTEX32A) GDI_HEAP_LIN_ADDR(hLog);
1607 if (lpEnumLogFont == NULL) {
1608 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1609 return 0;
1611 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32A) );
1612 lptm = (LPNEWTEXTMETRICEX32A) GDI_HEAP_LIN_ADDR(hMet);
1613 if (lptm == NULL) {
1614 GDI_HEAP_FREE(hLog);
1615 fprintf(stderr,"EnumFontFamilies32A // can't alloc TEXTMETRIC struct !\n");
1616 return 0;
1618 lpOldName = NULL;
1619 strcpy(FaceName,lpLF->lfFaceName);
1620 /* AnsiUpper(lpLF->lfFaceName);*/
1622 if (lpLogFontList[0] == NULL) InitFontsList();
1623 for(i = 0; lpLogFontList[i] != NULL; i++) {
1624 /* lfCharSet */
1625 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1626 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1627 continue;
1629 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1630 /* lfFaceName */
1631 if (FaceName[0]) {
1632 if (lstrcmpi32A(FaceName,lpLogFontList[i]->lfFaceName))
1633 continue;
1634 } else {
1635 if ((lpOldName!=NULL) &&
1636 !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1637 continue;
1638 lpOldName=lpLogFontList[i]->lfFaceName;
1641 FONT_LOGFONT16ToLOGFONT32A(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1642 strcpy(lpEnumLogFont->elfFullName,"");
1643 strcpy(lpEnumLogFont->elfStyle,"");
1644 strcpy(lpEnumLogFont->elfScript,"");
1645 hFont = CreateFontIndirect32A((LPLOGFONT32A)lpEnumLogFont);
1646 hOldFont = SelectObject32(hDC, hFont);
1647 GetTextMetrics32A(hDC, (LPTEXTMETRIC32A)lptm);
1648 SelectObject32(hDC, hOldFont);
1649 DeleteObject32(hFont);
1650 dprintf_font(stddeb, "EnumFontFamiliesEx32A // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1652 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1653 if (nRet == 0) {
1654 dprintf_font(stddeb,"EnumFontFamiliesEx32A // EnumEnd requested by application !\n");
1655 break;
1658 GDI_HEAP_FREE(hMet);
1659 GDI_HEAP_FREE(hLog);
1660 return nRet;
1664 /*************************************************************************
1665 * EnumFontFamiliesW [GDI32.82]
1667 INT32 EnumFontFamiliesEx32W(HDC32 hDC, LPLOGFONT32W lpLF, FONTENUMPROCEX32W lpEnumFunc, LPARAM lpData, DWORD reserved)
1669 HLOCAL16 hLog;
1670 HLOCAL16 hMet;
1671 HFONT32 hFont;
1672 HFONT32 hOldFont;
1673 LPENUMLOGFONTEX32W lpEnumLogFont;
1674 LPNEWTEXTMETRICEX32W lptm;
1675 LPSTR lpOldName;
1676 int nRet = 0;
1677 int i;
1678 LPSTR lpszFamily;
1680 dprintf_font(stddeb,"EnumFontFamiliesEx32W(%04x, %p, %08lx, %08lx, %08lx)\n",
1681 hDC, lpLF, (DWORD)lpEnumFunc, lpData,reserved);
1682 if (lpEnumFunc == 0) return 0;
1683 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONTEX32W) );
1684 lpEnumLogFont = (LPENUMLOGFONTEX32W) GDI_HEAP_LIN_ADDR(hLog);
1685 if (lpEnumLogFont == NULL) {
1686 fprintf(stderr,"EnumFontFamilies32W // can't alloc LOGFONT struct !\n");
1687 return 0;
1689 hMet = GDI_HEAP_ALLOC( sizeof(NEWTEXTMETRICEX32W) );
1690 lptm = (LPNEWTEXTMETRICEX32W) GDI_HEAP_LIN_ADDR(hMet);
1691 if (lptm == NULL) {
1692 GDI_HEAP_FREE(hLog);
1693 fprintf(stderr,"EnumFontFamilies32W // can't alloc TEXTMETRIC struct !\n");
1694 return 0;
1696 lpOldName = NULL;
1697 lpszFamily = HEAP_strdupWtoA( GetProcessHeap(), 0, lpLF->lfFaceName );
1698 AnsiUpper(lpszFamily);
1699 if (lpLogFontList[0] == NULL) InitFontsList();
1700 for(i = 0; lpLogFontList[i] != NULL; i++) {
1701 /* lfCharSet */
1702 if (lpLF->lfCharSet!=DEFAULT_CHARSET)
1703 if (lpLogFontList[i]->lfCharSet != lpLF->lfCharSet)
1704 continue;
1706 /* lfPitchAndFamily only of importance in Hebrew and Arabic versions. */
1707 /* lfFaceName */
1708 if (lpszFamily[0]) {
1709 if (lstrcmpi32A(lpszFamily,lpLogFontList[i]->lfFaceName))
1710 continue;
1711 } else {
1712 if ((lpOldName!=NULL) &&
1713 !lstrcmpi32A(lpOldName,lpLogFontList[i]->lfFaceName))
1714 continue;
1715 lpOldName=lpLogFontList[i]->lfFaceName;
1718 FONT_LOGFONT16ToLOGFONT32W(lpLogFontList[i],&(lpEnumLogFont->elfLogFont));
1719 lpEnumLogFont->elfFullName[0] = 0;
1720 lpEnumLogFont->elfStyle[0] = 0;
1721 lpEnumLogFont->elfScript[0] = 0;
1722 hFont = CreateFontIndirect32W((LPLOGFONT32W)lpEnumLogFont);
1723 hOldFont = SelectObject32(hDC, hFont);
1724 GetTextMetrics32W(hDC, (LPTEXTMETRIC32W)lptm);
1725 SelectObject32(hDC, hOldFont);
1726 DeleteObject32(hFont);
1727 dprintf_font(stddeb, "EnumFontFamilies32W // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1729 nRet = lpEnumFunc(lpEnumLogFont,lptm,0,lpData);
1730 if (nRet == 0) {
1731 dprintf_font(stddeb,"EnumFontFamilies32W // EnumEnd requested by application !\n");
1732 break;
1735 GDI_HEAP_FREE(hMet);
1736 GDI_HEAP_FREE(hLog);
1737 HeapFree( GetProcessHeap(), 0, lpszFamily );
1738 return nRet;
1742 /*************************************************************************
1743 * GetRasterizerCaps [GDI.313]
1746 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1748 /* This is not much more than a dummy */
1749 RASTERIZER_STATUS rs;
1751 rs.nSize = sizeof(rs);
1752 rs.wFlags = 0;
1753 rs.nLanguageID = 0;
1754 return True;
1757 /*************************************************************************
1758 * GetKerningPairs [GDI.332]
1760 int GetKerningPairs(HDC16 hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1762 /* This has to be dealt with when proper font handling is in place
1764 * At this time kerning is ignored (set to 0)
1767 int i;
1768 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1769 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;
1770 return 0;