Release 960528
[wine/gsoc-2012-control.git] / objects / font.c
blobff7c0c6357e758003535b310400e4e00220e5160
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
6 * Enhacements by Juergen Marquardt 1996
8 * Implementation of a second font cache which
9 * will be updated dynamically
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <X11/Xatom.h>
16 #include "font.h"
17 #include "metafile.h"
18 #include "callback.h"
19 #include "options.h"
20 #include "string32.h"
21 #include "xmalloc.h"
22 #include "stddebug.h"
23 #include "debug.h"
25 #define FONTCACHE 32 /* dynamic font cache size */
26 #define MAX_FONTS 256
27 static LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
29 static int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz);
31 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
32 (((cs)->rbearing|(cs)->lbearing| \
33 (cs)->ascent|(cs)->descent) == 0))
35 /*
36 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
37 * character. If the character is in the column and exists, then return the
38 * appropriate metrics (note that fonts with common per-character metrics will
39 * return min_bounds). If none of these hold true, try again with the default
40 * char.
42 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
43 { \
44 cs = def; \
45 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
46 if (fs->per_char == NULL) { \
47 cs = &fs->min_bounds; \
48 } else { \
49 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
50 if (CI_NONEXISTCHAR(cs)) cs = def; \
51 } \
52 } \
55 #define CI_GET_DEFAULT_INFO(fs,cs) \
56 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
58 struct FontStructure {
59 char *window;
60 char *x11;
61 } FontNames[32];
62 int FontSize;
65 /***********************************************************************
66 * FONT_Init
68 BOOL FONT_Init( void )
70 char temp[1024];
71 LPSTR ptr;
72 int i;
74 if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
76 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
77 if( strcmp( ptr, "default" ) )
78 FontNames[i++].window = xstrdup( ptr );
79 FontSize = i;
81 for( i = 1; i < FontSize; i++ )
83 PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
84 temp, sizeof(temp) );
85 FontNames[i].x11 = xstrdup( temp );
87 PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
88 FontNames[0].x11 = xstrdup( temp );
90 } else {
91 FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
92 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
93 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
94 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
95 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
96 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
97 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
98 FontSize = 7;
100 return TRUE;
103 /***********************************************************************
104 * FONT_ChkX11Family
106 * returns a valid X11 equivalent if a Windows face name
107 * is like a X11 family - or NULL if translation is needed
109 static char *FONT_ChkX11Family(char *winFaceName )
111 static char x11fam[32+2]; /* will be returned */
112 int i;
114 for(i = 0; lpLogFontList[i] != NULL; i++)
115 if( !strcasecmp(winFaceName, lpLogFontList[i]->lfFaceName) )
117 strcpy(x11fam,"*-");
118 return strcat(x11fam,winFaceName);
120 return NULL; /* a FONT_TranslateName() call is needed */
125 /***********************************************************************
126 * FONT_TranslateName
128 * Translate a Windows face name to its X11 equivalent.
129 * This will probably have to be customizable.
131 static const char *FONT_TranslateName( char *winFaceName )
133 int i;
135 for (i = 1; i < FontSize; i ++)
136 if( !strcmp( winFaceName, FontNames[i].window ) ) {
137 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
138 return FontNames[i].x11;
140 return FontNames[0].x11;
144 /***********************************************************************
145 * FONT_MatchFont
147 * Find a X font matching the logical font.
149 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
151 char pattern[100];
152 const char *family, *weight, *charset;
153 char **names;
154 char slant, oldspacing, spacing;
155 int width, height, oldheight, count;
156 XFontStruct * fontStruct;
158 dprintf_font(stddeb,
159 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
160 font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
161 weight = (font->lfWeight > 550) ? "bold" : "medium";
162 slant = font->lfItalic ? 'i' : 'r';
163 if (font->lfHeight == -1)
164 height = 0;
165 else
166 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
167 if (height == 0) height = 120; /* Default height = 12 */
168 else if (height < 0)
170 /* If height is negative, it means the height of the characters */
171 /* *without* the internal leading. So we adjust it a bit to */
172 /* compensate. 5/4 seems to give good results for small fonts. */
174 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
175 height = 10 * (-height * 9 / 8);
176 * may be we have to use an non linear function
178 /* assume internal leading is 2 pixels. Else small fonts will become
179 * very small. */
180 height = (height-2) * -10;
182 else height *= 10;
183 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
184 if (width < 0) {
185 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
186 width, font->lfWidth );
187 width = -width;
190 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
191 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
194 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
195 if (*font->lfFaceName) {
196 family = FONT_ChkX11Family(font->lfFaceName);
197 /*--do _not_ translate if lfFaceName is family from X11 A.K.*/
198 if (!family)
199 family = FONT_TranslateName( font->lfFaceName );
200 /* FIX ME: I don't if that's correct but it works J.M. */
201 spacing = '*';
203 else switch(font->lfPitchAndFamily & 0xf0)
205 case FF_ROMAN:
206 family = FONT_TranslateName( "roman" );
207 break;
208 case FF_SWISS:
209 family = FONT_TranslateName( "swiss" );
210 break;
211 case FF_MODERN:
212 family = FONT_TranslateName( "modern" );
213 break;
214 case FF_SCRIPT:
215 family = FONT_TranslateName( "script" );
216 break;
217 case FF_DECORATIVE:
218 family = FONT_TranslateName( "decorative" );
219 break;
220 default:
221 family = "*-*";
222 break;
224 oldheight = height;
225 oldspacing = spacing;
226 while (TRUE) {
227 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
228 if ( width == 0 )
229 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
230 family, weight, slant, height, spacing, charset);
231 else
232 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
233 family, weight, slant, height, spacing, width, charset);
234 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
235 names = XListFonts( display, pattern, 1, &count );
236 if (count > 0) break;
237 if (spacing == 'm') /* try 'c' if no 'm' found */ {
239 spacing = 'c';
240 continue;
241 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
242 spacing = '*';
243 continue;
245 spacing = oldspacing;
246 height -= 10;
247 if (height < 10) {
248 if (slant == 'i') {
249 /* try oblique if no italic font */
250 slant = 'o';
251 height = oldheight;
252 continue;
254 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
255 /* If a fixed spacing font could not be found, ignore
256 * the family */
257 family = "*-*";
258 height = oldheight;
259 continue;
261 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
262 return NULL;
265 dprintf_font(stddeb," Found '%s'\n", *names );
266 if (!*font->lfFaceName)
267 ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
268 /* we need a font name for function GetTextFace() even if there isn't one ;-) */
270 fontStruct = XLoadQueryFont( display, *names );
271 XFreeFontNames( names );
272 return fontStruct;
276 /***********************************************************************
277 * FONT_GetMetrics
279 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
280 TEXTMETRIC * metrics )
282 int average, i, count;
283 unsigned long prop;
285 metrics->tmAscent = xfont->ascent;
286 metrics->tmDescent = xfont->descent;
287 metrics->tmHeight = xfont->ascent + xfont->descent;
289 metrics->tmInternalLeading = 0;
290 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
291 metrics->tmInternalLeading = xfont->ascent - (short)prop;
292 metrics->tmExternalLeading = 0;
293 metrics->tmMaxCharWidth = xfont->max_bounds.width;
294 metrics->tmWeight = logfont->lfWeight;
295 metrics->tmItalic = logfont->lfItalic;
296 metrics->tmUnderlined = logfont->lfUnderline;
297 metrics->tmStruckOut = logfont->lfStrikeOut;
298 metrics->tmFirstChar = xfont->min_char_or_byte2;
299 metrics->tmLastChar = xfont->max_char_or_byte2;
300 metrics->tmDefaultChar = xfont->default_char;
301 metrics->tmBreakChar = ' ';
302 metrics->tmCharSet = logfont->lfCharSet;
303 metrics->tmOverhang = 0;
304 metrics->tmDigitizedAspectX = 1;
305 metrics->tmDigitizedAspectY = 1;
306 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
307 if (logfont->lfPitchAndFamily & FIXED_PITCH)
308 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
310 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
311 else
313 XCharStruct * charPtr = xfont->per_char;
314 average = count = 0;
315 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
317 if (!CI_NONEXISTCHAR( charPtr ))
319 average += charPtr->width;
320 count++;
322 charPtr++;
324 if (count) average = (average + count/2) / count;
326 metrics->tmAveCharWidth = average;
329 /***********************************************************************
330 * GetGlyphOutLine (GDI.309)
332 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm,
333 DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2)
335 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
336 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
337 return (DWORD)-1; /* failure */
341 /***********************************************************************
342 * CreateScalableFontResource (GDI.310)
344 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
345 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
347 /* fHidden=1 - only visible for the calling app, read-only, not
348 * enumbered with EnumFonts/EnumFontFamilies
349 * lpszCurrentPath can be NULL
351 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
352 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
353 return FALSE; /* create failed */
357 /***********************************************************************
358 * CreateFontIndirect (GDI.57)
360 HFONT CreateFontIndirect( const LOGFONT * font )
362 FONTOBJ * fontPtr;
363 HFONT hfont;
365 if (!font)
367 fprintf(stderr, "CreateFontIndirect : font is NULL : returning NULL\n");
368 return 0;
370 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
371 if (!hfont) return 0;
372 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
373 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
374 AnsiLower( fontPtr->logfont.lfFaceName );
375 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
376 font, font->lfHeight, font->lfWidth, hfont);
377 return hfont;
381 /***********************************************************************
382 * CreateFont (GDI.56)
384 HFONT CreateFont( INT height, INT width, INT esc, INT orient, INT weight,
385 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
386 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
387 LPCSTR name )
389 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
390 strikeout, charset, outpres, clippres, quality, pitch, };
391 dprintf_font(stddeb,"CreateFont(%d,%d)\n", height, width);
392 if (name)
394 strncpy( logfont.lfFaceName, name, LF_FACESIZE - 1 );
395 logfont.lfFaceName[LF_FACESIZE - 1] = '\0';
397 else logfont.lfFaceName[0] = '\0';
398 return CreateFontIndirect( &logfont );
402 /***********************************************************************
403 * FONT_GetObject
405 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
407 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
408 memcpy( buffer, &font->logfont, count );
409 return count;
413 /***********************************************************************
414 * FONT_SelectObject
416 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
418 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
420 static struct {
421 HFONT id;
422 LOGFONT logfont;
423 int access;
424 int used;
425 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
426 int i;
428 X_PHYSFONT * stockPtr;
429 HFONT prevHandle = dc->w.hFont;
430 XFontStruct * fontStruct;
431 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
433 #if 0 /* From the code in SelectObject, this can not happen */
434 /* Load font if necessary */
435 if (!font)
437 HFONT hnewfont;
439 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
440 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
441 DEFAULT_QUALITY, FF_DONTCARE, "*" );
442 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
444 #endif
446 if (dc->header.wMagic == METAFILE_DC_MAGIC)
447 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
448 return prevHandle;
449 else
450 return 0;
452 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
453 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
454 else {
455 stockPtr = NULL;
457 * Ok, It's not a stock font but
458 * may be it's cached in dynamic cache
460 for(i=0; i<FONTCACHE; i++) /* search for same handle */
461 if (cacheFonts[i].id==hfont) { /* Got the handle */
463 * Check if Handle matches the font
465 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT))) {
466 /* No: remove handle id from dynamic font cache */
467 cacheFonts[i].access=0;
468 cacheFonts[i].used=0;
469 cacheFonts[i].id=0;
470 /* may be there is an unused handle which contains the font */
471 for(i=0; i<FONTCACHE; i++) {
472 if((cacheFonts[i].used == 0) &&
473 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT)))== 0) {
474 /* got it load from cache and set new handle id */
475 stockPtr = &cacheFonts[i].cacheFont;
476 cacheFonts[i].access=1;
477 cacheFonts[i].used=1;
478 cacheFonts[i].id=hfont;
479 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
480 break;
485 else {
486 /* Yes: load from dynamic font cache */
487 stockPtr = &cacheFonts[i].cacheFont;
488 cacheFonts[i].access++;
489 cacheFonts[i].used++;
491 break;
494 if (!stockPtr || !stockPtr->fstruct)
496 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
498 /* If it is not a stock font, we can simply return 0 */
499 if (!stockPtr) return 0;
500 /* Otherwise we must try to find a substitute */
501 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
502 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
503 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
504 fontStruct = XLoadQueryFont( display, "fixed" );
505 if (!fontStruct)
507 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
508 exit( 1 );
512 else
514 fontStruct = stockPtr->fstruct;
515 dprintf_font(stddeb,
516 "FONT_SelectObject: Loaded font from cache %04x %p\n",
517 hfont, fontStruct );
520 /* Unuse previous font */
521 for (i=0; i < FONTCACHE; i++) {
522 if (cacheFonts[i].id == prevHandle) {
523 if(cacheFonts[i].used == 0)
524 fprintf(stderr, "Trying to decrement a use count of 0.\n");
525 else
526 cacheFonts[i].used--;
530 /* Store font */
531 dc->w.hFont = hfont;
532 if (stockPtr)
534 if (!stockPtr->fstruct)
536 stockPtr->fstruct = fontStruct;
537 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
539 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
541 else
544 * Check in cacheFont
546 cacheFontsMin=NULL;
547 for (i=0; i < FONTCACHE; i++) {
548 if (cacheFonts[i].used==0)
549 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
550 cacheFontsMin=&cacheFonts[i];
552 if (!cacheFontsMin) {
553 fprintf(stderr,"No unused font cache entry !!!!\n" );
554 return prevHandle;
556 if (cacheFontsMin->id!=0) {
557 dprintf_font(stddeb,
558 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
559 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
561 cacheFontsMin->cacheFont.fstruct = fontStruct;
562 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
563 cacheFontsMin->access=1;
564 cacheFontsMin->used=1;
565 cacheFontsMin->id=hfont;
566 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
567 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT));
570 return prevHandle;
574 /***********************************************************************
575 * GetTextCharacterExtra (GDI.89)
577 short GetTextCharacterExtra( HDC hdc )
579 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
580 if (!dc) return 0;
581 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
582 / dc->w.VportExtX );
586 /***********************************************************************
587 * SetTextCharacterExtra (GDI.8)
589 short SetTextCharacterExtra( HDC hdc, short extra )
591 short prev;
592 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
593 if (!dc) return 0;
594 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
595 prev = dc->w.charExtra;
596 dc->w.charExtra = abs(extra);
597 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
601 /***********************************************************************
602 * SetTextJustification (GDI.10)
604 short SetTextJustification( HDC hdc, short extra, short breaks )
606 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
607 if (!dc) return 0;
609 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
610 if (!extra) breaks = 0;
611 dc->w.breakTotalExtra = extra;
612 dc->w.breakCount = breaks;
613 if (breaks)
615 dc->w.breakExtra = extra / breaks;
616 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
618 else
620 dc->w.breakExtra = 0;
621 dc->w.breakRem = 0;
623 return 1;
627 /***********************************************************************
628 * GetTextFace (GDI.92)
630 INT GetTextFace( HDC hdc, INT count, LPSTR name )
632 FONTOBJ *font;
634 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
635 if (!dc) return 0;
636 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
637 return 0;
638 lstrcpyn( name, font->logfont.lfFaceName, count );
639 return strlen(name);
643 /***********************************************************************
644 * GetTextExtent (GDI.91)
646 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
648 SIZE16 size;
649 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
650 return MAKELONG( size.cx, size.cy );
654 /***********************************************************************
655 * GetTextExtentPoint16 (GDI.471)
657 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
659 SIZE32 size32;
660 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
661 CONV_SIZE32TO16( &size32, size );
662 return (BOOL16)ret;
666 /***********************************************************************
667 * GetTextExtentPoint32A (GDI32.232)
669 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
670 LPSIZE32 size )
672 int dir, ascent, descent;
673 XCharStruct info;
675 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
676 if (!dc) return FALSE;
677 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
678 &ascent, &descent, &info );
679 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
680 * dc->w.WndExtX / dc->w.VportExtX);
681 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
682 * dc->w.WndExtY / dc->w.VportExtY);
684 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%*.*s' %d %p): returning %d,%d\n",
685 hdc, count, count, str, count, size, size->cx, size->cy );
686 return TRUE;
690 /***********************************************************************
691 * GetTextExtentPoint32W (GDI32.233)
693 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
694 LPSIZE32 size )
696 char *p = STRING32_DupUniToAnsi( str );
697 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
698 free( p );
699 return ret;
703 /***********************************************************************
704 * GetTextMetrics (GDI.93)
706 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
708 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
709 if (!dc) return FALSE;
710 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
712 metrics->tmAscent = abs( metrics->tmAscent
713 * dc->w.WndExtY / dc->w.VportExtY );
714 metrics->tmDescent = abs( metrics->tmDescent
715 * dc->w.WndExtY / dc->w.VportExtY );
716 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
717 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
718 * dc->w.WndExtY / dc->w.VportExtY );
719 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
720 * dc->w.WndExtY / dc->w.VportExtY );
721 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
722 * dc->w.WndExtX / dc->w.VportExtX );
723 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
724 * dc->w.WndExtX / dc->w.VportExtX );
726 dprintf_font(stdnimp,"text metrics:\n
727 InternalLeading = %i
728 ExternalLeading = %i
729 MaxCharWidth = %i
730 Weight = %i
731 Italic = %i
732 Underlined = %i
733 StruckOut = %i
734 FirstChar = %i
735 LastChar = %i
736 DefaultChar = %i
737 BreakChar = %i
738 CharSet = %i
739 Overhang = %i
740 DigitizedAspectX = %i
741 DigitizedAspectY = %i
742 AveCharWidth = %i
743 MaxCharWidth = %i
744 Ascent = %i
745 Descent = %i
746 Height = %i\n",
747 metrics->tmInternalLeading,
748 metrics->tmExternalLeading,
749 metrics->tmMaxCharWidth,
750 metrics->tmWeight,
751 metrics->tmItalic,
752 metrics->tmUnderlined,
753 metrics->tmStruckOut,
754 metrics->tmFirstChar,
755 metrics->tmLastChar,
756 metrics->tmDefaultChar,
757 metrics->tmBreakChar,
758 metrics->tmCharSet,
759 metrics->tmOverhang,
760 metrics->tmDigitizedAspectX,
761 metrics->tmDigitizedAspectY,
762 metrics->tmAveCharWidth,
763 metrics->tmMaxCharWidth,
764 metrics->tmAscent,
765 metrics->tmDescent,
766 metrics->tmHeight);
768 return TRUE;
772 /***********************************************************************
773 * SetMapperFlags (GDI.349)
775 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
777 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
778 hDC, dwFlag);
779 return 0L;
783 /***********************************************************************
784 * GetCharABCWidths (GDI.307)
786 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC lpABC)
788 /* No TrueType fonts in Wine */
789 return FALSE;
793 /***********************************************************************
794 * GetCharWidth (GDI.350)
796 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
798 int i, j;
799 XFontStruct *xfont;
800 XCharStruct *cs, *def;
802 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
803 if (!dc) return FALSE;
804 xfont = dc->u.x.font.fstruct;
806 /* fixed font? */
807 if (xfont->per_char == NULL)
809 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
810 *(lpBuffer + j) = xfont->max_bounds.width;
811 return TRUE;
814 CI_GET_DEFAULT_INFO(xfont, def);
816 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
818 CI_GET_CHAR_INFO(xfont, i, def, cs);
819 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
820 if (*(lpBuffer + j) < 0)
821 *(lpBuffer + j) = 0;
823 return TRUE;
827 /***********************************************************************
828 * AddFontResource (GDI.119)
830 INT AddFontResource( LPCSTR str )
832 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
833 return 1;
837 /***********************************************************************
838 * RemoveFontResource (GDI.136)
840 BOOL RemoveFontResource( LPSTR str )
842 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
843 return TRUE;
847 /*************************************************************************
848 * ParseFontParms [internal]
850 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
852 int i;
853 if (lpFont == NULL) return 0;
854 if (lpRetStr == NULL) return 0;
855 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
856 if (*lpFont == '-') i++;
857 lpFont++;
859 if (i == wParmsNo) {
860 if (*lpFont == '-') lpFont++;
861 wMaxSiz--;
862 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
863 *(lpRetStr + i) = *lpFont++;
864 *(lpRetStr + i) = '\0';
865 return i;
867 else
868 lpRetStr[0] = '\0';
869 return 0;
873 /*************************************************************************
874 * InitFontsList [internal]
877 static int logfcmp(const void *a,const void *b)
879 return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
882 void InitFontsList(void)
884 char str[32];
885 char pattern[100];
886 char *family, *weight, *charset;
887 char **names;
888 char slant, spacing;
889 int i, count;
890 LPLOGFONT lpNewFont;
891 weight = "medium";
892 slant = 'r';
893 spacing = '*';
894 charset = "*";
895 family = "*-*";
896 dprintf_font(stddeb,"InitFontsList !\n");
897 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
898 family, weight, slant, spacing, charset);
899 names = XListFonts( display, pattern, MAX_FONTS, &count );
900 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
901 for (i = 0; i < count; i++) {
902 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
903 if (lpNewFont == NULL) {
904 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
905 break;
907 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
908 ParseFontParms(names[i], 2, str, sizeof(str));
909 #if 0
910 /* not necessary because new function FONT_ChkX11Family() */
911 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
912 #endif
913 AnsiUpper(str);
914 strcpy(lpNewFont->lfFaceName, str);
915 ParseFontParms(names[i], 8, str, sizeof(str));
916 lpNewFont->lfHeight = atoi(str) / 10;
917 ParseFontParms(names[i], 12, str, sizeof(str));
918 lpNewFont->lfWidth = atoi(str) / 10;
919 lpNewFont->lfEscapement = 0;
920 lpNewFont->lfOrientation = 0;
921 lpNewFont->lfWeight = FW_REGULAR;
922 lpNewFont->lfItalic = 0;
923 lpNewFont->lfUnderline = 0;
924 lpNewFont->lfStrikeOut = 0;
925 ParseFontParms(names[i], 13, str, sizeof(str));
926 if (strcmp(str, "iso8859") == 0) {
927 lpNewFont->lfCharSet = ANSI_CHARSET;
928 } else {
929 lpNewFont->lfCharSet = OEM_CHARSET;
931 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
932 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
933 lpNewFont->lfQuality = DEFAULT_QUALITY;
934 ParseFontParms(names[i], 11, str, sizeof(str));
935 switch(str[0]) {
936 case 'p':
937 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
938 break;
939 case 'm':
940 case 'c':
941 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
942 break;
943 default:
944 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
945 break;
947 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
948 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
949 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
950 lpLogFontList[i] = lpNewFont;
951 lpLogFontList[i+1] = NULL;
953 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
954 XFreeFontNames(names);
958 /*************************************************************************
959 * EnumFonts [GDI.70]
961 INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC lpEnumFunc, LPARAM lpData)
963 HANDLE hLog;
964 HANDLE hMet;
965 HFONT hFont;
966 HFONT hOldFont;
967 LPLOGFONT lpLogFont;
968 LPTEXTMETRIC lptm;
969 LPSTR lpOldName;
970 char FaceName[LF_FACESIZE];
971 int nRet = 0;
972 int i;
974 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
975 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
976 if (lpEnumFunc == 0) return 0;
977 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
978 lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
979 if (lpLogFont == NULL) {
980 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
981 return 0;
983 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
984 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
985 if (lptm == NULL) {
986 GDI_HEAP_FREE(hLog);
987 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
988 return 0;
990 if (lpFaceName != NULL) {
991 strcpy(FaceName, lpFaceName);
992 AnsiUpper(FaceName);
994 lpOldName = NULL;
996 if (lpLogFontList[0] == NULL) InitFontsList();
997 for(i = 0; lpLogFontList[i] != NULL; i++) {
998 if (lpFaceName == NULL) {
999 if (lpOldName != NULL) {
1000 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1002 lpOldName = lpLogFontList[i]->lfFaceName;
1003 } else {
1004 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1006 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1007 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1008 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
1009 hFont = CreateFontIndirect(lpLogFont);
1010 hOldFont = SelectObject(hDC, hFont);
1011 GetTextMetrics(hDC, lptm);
1012 SelectObject(hDC, hOldFont);
1013 DeleteObject(hFont);
1014 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1015 nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
1016 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
1017 if (nRet == 0) {
1018 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1019 break;
1022 GDI_HEAP_FREE(hMet);
1023 GDI_HEAP_FREE(hLog);
1024 return nRet;
1028 /*************************************************************************
1029 * EnumFontFamilies [GDI.330]
1031 INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC lpEnumFunc, LPARAM lpData)
1033 HANDLE hLog;
1034 HANDLE hMet;
1035 HFONT hFont;
1036 HFONT hOldFont;
1037 LPENUMLOGFONT lpEnumLogFont;
1038 LPTEXTMETRIC lptm;
1039 LPSTR lpOldName;
1040 char FaceName[LF_FACESIZE];
1041 int nRet = 0;
1042 int i;
1044 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1045 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1046 if (lpEnumFunc == 0) return 0;
1047 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
1048 lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
1049 if (lpEnumLogFont == NULL) {
1050 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1051 return 0;
1053 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
1054 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
1055 if (lptm == NULL) {
1056 GDI_HEAP_FREE(hLog);
1057 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1058 return 0;
1060 lpOldName = NULL;
1061 if (lpszFamily != NULL) {
1062 strcpy(FaceName, lpszFamily);
1063 AnsiUpper(FaceName);
1065 if (lpLogFontList[0] == NULL) InitFontsList();
1066 for(i = 0; lpLogFontList[i] != NULL; i++) {
1067 if (lpszFamily == NULL) {
1068 if (lpOldName != NULL) {
1069 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1071 lpOldName = lpLogFontList[i]->lfFaceName;
1072 } else {
1073 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1075 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
1076 strcpy(lpEnumLogFont->elfFullName,"");
1077 strcpy(lpEnumLogFont->elfStyle,"");
1078 hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
1079 hOldFont = SelectObject(hDC, hFont);
1080 GetTextMetrics(hDC, lptm);
1081 SelectObject(hDC, hOldFont);
1082 DeleteObject(hFont);
1083 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1085 nRet = CallEnumFontFamProc( lpEnumFunc,
1086 GDI_HEAP_SEG_ADDR(hLog),
1087 GDI_HEAP_SEG_ADDR(hMet),
1088 0, lpData );
1089 if (nRet == 0) {
1090 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1091 break;
1094 GDI_HEAP_FREE(hMet);
1095 GDI_HEAP_FREE(hLog);
1096 return nRet;
1099 /*************************************************************************
1100 * GetRasterizerCaps [GDI.313]
1103 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1105 /* This is not much more than a dummy */
1106 RASTERIZER_STATUS rs;
1108 rs.nSize = sizeof(rs);
1109 rs.wFlags = 0;
1110 rs.nLanguageID = 0;
1111 return True;
1114 /*************************************************************************
1115 * GetKerningPairs [GDI.332]
1117 int GetKerningPairs(HDC hDC,int cBufLen,LPKERNINGPAIR lpKerningPairs)
1119 /* Wine fonts are ugly and don't support kerning :) */
1120 return 0;