Release 960414
[wine.git] / objects / font.c
blobf9cfc8b6e26ce1c43e699ce0c26e9e0615676431
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 "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 LPLOGFONT lpLogFontList[MAX_FONTS] = { NULL };
29 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
30 (((cs)->rbearing|(cs)->lbearing| \
31 (cs)->ascent|(cs)->descent) == 0))
33 /*
34 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
35 * character. If the character is in the column and exists, then return the
36 * appropriate metrics (note that fonts with common per-character metrics will
37 * return min_bounds). If none of these hold true, try again with the default
38 * char.
40 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
41 { \
42 cs = def; \
43 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
44 if (fs->per_char == NULL) { \
45 cs = &fs->min_bounds; \
46 } else { \
47 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
48 if (CI_NONEXISTCHAR(cs)) cs = def; \
49 } \
50 } \
53 #define CI_GET_DEFAULT_INFO(fs,cs) \
54 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
56 struct FontStructure {
57 char *window;
58 char *x11;
59 } FontNames[32];
60 int FontSize;
63 /***********************************************************************
64 * FONT_Init
66 BOOL FONT_Init( void )
68 char temp[1024];
69 LPSTR ptr;
70 int i;
72 if (PROFILE_GetWineIniString( "fonts", NULL, "*", temp, sizeof(temp) ) > 2 )
74 for( ptr = temp, i = 1; strlen(ptr) != 0; ptr += strlen(ptr) + 1 )
75 if( strcmp( ptr, "default" ) )
76 FontNames[i++].window = xstrdup( ptr );
77 FontSize = i;
79 for( i = 1; i < FontSize; i++ )
81 PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
82 temp, sizeof(temp) );
83 FontNames[i].x11 = xstrdup( temp );
85 PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
86 FontNames[0].x11 = xstrdup( temp );
88 } else {
89 FontNames[0].window = NULL; FontNames[0].x11 = "*-helvetica";
90 FontNames[1].window = "ms sans serif"; FontNames[1].x11 = "*-helvetica";
91 FontNames[2].window = "ms serif"; FontNames[2].x11 = "*-times";
92 FontNames[3].window = "fixedsys"; FontNames[3].x11 = "*-fixed";
93 FontNames[4].window = "arial"; FontNames[4].x11 = "*-helvetica";
94 FontNames[5].window = "helv"; FontNames[5].x11 = "*-helvetica";
95 FontNames[6].window = "roman"; FontNames[6].x11 = "*-times";
96 FontSize = 7;
98 return TRUE;
102 /***********************************************************************
103 * FONT_TranslateName
105 * Translate a Windows face name to its X11 equivalent.
106 * This will probably have to be customizable.
108 static const char *FONT_TranslateName( char *winFaceName )
110 int i;
112 for (i = 1; i < FontSize; i ++)
113 if( !strcmp( winFaceName, FontNames[i].window ) ) {
114 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
115 return FontNames[i].x11;
117 return FontNames[0].x11;
121 /***********************************************************************
122 * FONT_MatchFont
124 * Find a X font matching the logical font.
126 static XFontStruct * FONT_MatchFont( LOGFONT * font, DC * dc )
128 char pattern[100];
129 const char *family, *weight, *charset;
130 char **names;
131 char slant, oldspacing, spacing;
132 int width, height, oldheight, count;
133 XFontStruct * fontStruct;
135 dprintf_font(stddeb,
136 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
137 font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
138 weight = (font->lfWeight > 550) ? "bold" : "medium";
139 slant = font->lfItalic ? 'i' : 'r';
140 if (font->lfHeight == -1)
141 height = 0;
142 else
143 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
144 if (height == 0) height = 120; /* Default height = 12 */
145 else if (height < 0)
147 /* If height is negative, it means the height of the characters */
148 /* *without* the internal leading. So we adjust it a bit to */
149 /* compensate. 5/4 seems to give good results for small fonts. */
151 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
152 height = 10 * (-height * 9 / 8);
153 * may be we have to use an non linear function
155 /* assume internal leading is 2 pixels. Else small fonts will become
156 * very small. */
157 height = (height-2) * -10;
159 else height *= 10;
160 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
161 if (width < 0) {
162 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
163 width, font->lfWidth );
164 width = -width;
167 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
168 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
171 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
172 if (*font->lfFaceName) {
173 family = FONT_TranslateName( font->lfFaceName );
174 /* FIX ME: I don't if that's correct but it works J.M. */
175 spacing = '*';
177 else switch(font->lfPitchAndFamily & 0xf0)
179 case FF_ROMAN:
180 family = FONT_TranslateName( "roman" );
181 break;
182 case FF_SWISS:
183 family = FONT_TranslateName( "swiss" );
184 break;
185 case FF_MODERN:
186 family = FONT_TranslateName( "modern" );
187 break;
188 case FF_SCRIPT:
189 family = FONT_TranslateName( "script" );
190 break;
191 case FF_DECORATIVE:
192 family = FONT_TranslateName( "decorative" );
193 break;
194 default:
195 family = "*-*";
196 break;
199 oldheight = height;
200 oldspacing = spacing;
201 while (TRUE) {
202 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
203 if ( width == 0 )
204 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
205 family, weight, slant, height, spacing, charset);
206 else
207 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
208 family, weight, slant, height, spacing, width, charset);
209 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
210 names = XListFonts( display, pattern, 1, &count );
211 if (count > 0) break;
212 if (spacing == 'm') /* try 'c' if no 'm' found */ {
214 spacing = 'c';
215 continue;
216 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
217 spacing = '*';
218 continue;
220 spacing = oldspacing;
221 height -= 10;
222 if (height < 10) {
223 if (slant == 'i') {
224 /* try oblique if no italic font */
225 slant = 'o';
226 height = oldheight;
227 continue;
229 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
230 /* If a fixed spacing font could not be found, ignore
231 * the family */
232 family = "*-*";
233 height = oldheight;
234 continue;
236 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
237 return NULL;
240 dprintf_font(stddeb," Found '%s'\n", *names );
241 fontStruct = XLoadQueryFont( display, *names );
242 XFreeFontNames( names );
243 return fontStruct;
247 /***********************************************************************
248 * FONT_GetMetrics
250 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
251 TEXTMETRIC * metrics )
253 int average, i, count;
254 unsigned long prop;
256 metrics->tmAscent = xfont->ascent;
257 metrics->tmDescent = xfont->descent;
258 metrics->tmHeight = xfont->ascent + xfont->descent;
260 metrics->tmInternalLeading = 0;
261 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
262 metrics->tmInternalLeading = xfont->ascent - (short)prop;
263 metrics->tmExternalLeading = 0;
264 metrics->tmMaxCharWidth = xfont->max_bounds.width;
265 metrics->tmWeight = logfont->lfWeight;
266 metrics->tmItalic = logfont->lfItalic;
267 metrics->tmUnderlined = logfont->lfUnderline;
268 metrics->tmStruckOut = logfont->lfStrikeOut;
269 metrics->tmFirstChar = xfont->min_char_or_byte2;
270 metrics->tmLastChar = xfont->max_char_or_byte2;
271 metrics->tmDefaultChar = xfont->default_char;
272 metrics->tmBreakChar = ' ';
273 metrics->tmCharSet = logfont->lfCharSet;
274 metrics->tmOverhang = 0;
275 metrics->tmDigitizedAspectX = 1;
276 metrics->tmDigitizedAspectY = 1;
277 metrics->tmPitchAndFamily = (logfont->lfPitchAndFamily&0xf0)|TMPF_DEVICE;
278 if (logfont->lfPitchAndFamily & FIXED_PITCH)
279 metrics->tmPitchAndFamily |= TMPF_FIXED_PITCH;
281 if (!xfont->per_char) average = metrics->tmMaxCharWidth;
282 else
284 XCharStruct * charPtr = xfont->per_char;
285 average = count = 0;
286 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
288 if (!CI_NONEXISTCHAR( charPtr ))
290 average += charPtr->width;
291 count++;
293 charPtr++;
295 if (count) average = (average + count/2) / count;
297 metrics->tmAveCharWidth = average;
300 /***********************************************************************
301 * GetGlyphOutLine (GDI.309)
303 DWORD GetGlyphOutLine(HDC hdc, UINT uChar, UINT fuFormat, LPGLYPHMETRICS lpgm,
304 DWORD cbBuffer, LPSTR lpBuffer, LPMAT2 lpmat2)
306 fprintf( stdnimp,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
307 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
308 return (DWORD)-1; /* failure */
312 /***********************************************************************
313 * CreateScalableFontResource (GDI.310)
315 BOOL CreateScalableFontResource( UINT fHidden,LPSTR lpszResourceFile,
316 LPSTR lpszFontFile, LPSTR lpszCurrentPath )
318 /* fHidden=1 - only visible for the calling app, read-only, not
319 * enumbered with EnumFonts/EnumFontFamilies
320 * lpszCurrentPath can be NULL
322 fprintf(stdnimp,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
323 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
324 return FALSE; /* create failed */
328 /***********************************************************************
329 * CreateFontIndirect (GDI.57)
331 HFONT CreateFontIndirect( const LOGFONT * font )
333 FONTOBJ * fontPtr;
334 HFONT hfont;
336 if (!font)
338 fprintf(stderr, "CreateFontIndirect : font is NULL : returning NULL\n");
339 return 0;
341 hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
342 if (!hfont) return 0;
343 fontPtr = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hfont );
344 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
345 AnsiLower( fontPtr->logfont.lfFaceName );
346 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
347 font, font->lfHeight, font->lfWidth, hfont);
348 return hfont;
352 /***********************************************************************
353 * CreateFont (GDI.56)
355 HFONT CreateFont( INT height, INT width, INT esc, INT orient, INT weight,
356 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
357 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
358 LPCSTR name )
360 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
361 strikeout, charset, outpres, clippres, quality, pitch, };
362 dprintf_font(stddeb,"CreateFont(%d,%d)\n", height, width);
363 if (name)
365 strncpy( logfont.lfFaceName, name, LF_FACESIZE - 1 );
366 logfont.lfFaceName[LF_FACESIZE - 1] = '\0';
368 else logfont.lfFaceName[0] = '\0';
369 return CreateFontIndirect( &logfont );
373 /***********************************************************************
374 * FONT_GetObject
376 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
378 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
379 memcpy( buffer, &font->logfont, count );
380 return count;
384 /***********************************************************************
385 * FONT_SelectObject
387 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
389 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
391 static struct {
392 HFONT id;
393 LOGFONT logfont;
394 int access;
395 int used;
396 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
397 int i;
399 X_PHYSFONT * stockPtr;
400 HFONT prevHandle = dc->w.hFont;
401 XFontStruct * fontStruct;
402 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
404 #if 0 /* From the code in SelectObject, this can not happen */
405 /* Load font if necessary */
406 if (!font)
408 HFONT hnewfont;
410 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
411 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
412 DEFAULT_QUALITY, FF_DONTCARE, "*" );
413 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
415 #endif
417 if (dc->header.wMagic == METAFILE_DC_MAGIC)
418 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
419 return prevHandle;
420 else
421 return 0;
423 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
424 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
425 else {
426 stockPtr = NULL;
428 * Ok, It's not a stock font but
429 * may be it's cached in dynamic cache
431 for(i=0; i<FONTCACHE; i++) /* search for same handle */
432 if (cacheFonts[i].id==hfont) { /* Got the handle */
434 * Check if Handle matches the font
436 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT))) {
437 /* No: remove handle id from dynamic font cache */
438 cacheFonts[i].access=0;
439 cacheFonts[i].used=0;
440 cacheFonts[i].id=0;
441 /* may be there is an unused handle which contains the font */
442 for(i=0; i<FONTCACHE; i++) {
443 if((cacheFonts[i].used == 0) &&
444 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT)))== 0) {
445 /* got it load from cache and set new handle id */
446 stockPtr = &cacheFonts[i].cacheFont;
447 cacheFonts[i].access=1;
448 cacheFonts[i].used=1;
449 cacheFonts[i].id=hfont;
450 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
451 break;
456 else {
457 /* Yes: load from dynamic font cache */
458 stockPtr = &cacheFonts[i].cacheFont;
459 cacheFonts[i].access++;
460 cacheFonts[i].used++;
462 break;
465 if (!stockPtr || !stockPtr->fstruct)
467 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
469 /* If it is not a stock font, we can simply return 0 */
470 if (!stockPtr) return 0;
471 /* Otherwise we must try to find a substitute */
472 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
473 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
474 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
475 fontStruct = XLoadQueryFont( display, "fixed" );
476 if (!fontStruct)
478 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
479 exit( 1 );
483 else
485 fontStruct = stockPtr->fstruct;
486 dprintf_font(stddeb,
487 "FONT_SelectObject: Loaded font from cache %04x %p\n",
488 hfont, fontStruct );
491 /* Unuse previous font */
492 for (i=0; i < FONTCACHE; i++) {
493 if (cacheFonts[i].id == prevHandle) {
494 cacheFonts[i].used--;
498 /* Store font */
499 dc->w.hFont = hfont;
500 if (stockPtr)
502 if (!stockPtr->fstruct)
504 stockPtr->fstruct = fontStruct;
505 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
507 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
509 else
512 * Check in cacheFont
514 cacheFontsMin=NULL;
515 for (i=0; i < FONTCACHE; i++) {
516 if (cacheFonts[i].used==0)
517 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
518 cacheFontsMin=&cacheFonts[i];
520 if (!cacheFontsMin)
521 fprintf(stderr,"No unused font cache entry !!!!\n" );
523 if (cacheFontsMin->id!=0) {
524 dprintf_font(stddeb,
525 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
526 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
528 cacheFontsMin->cacheFont.fstruct = fontStruct;
529 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
530 cacheFontsMin->access=1;
531 cacheFontsMin->used=1;
532 cacheFontsMin->id=hfont;
533 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
534 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT));
537 return prevHandle;
541 /***********************************************************************
542 * GetTextCharacterExtra (GDI.89)
544 short GetTextCharacterExtra( HDC hdc )
546 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
547 if (!dc) return 0;
548 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
549 / dc->w.VportExtX );
553 /***********************************************************************
554 * SetTextCharacterExtra (GDI.8)
556 short SetTextCharacterExtra( HDC hdc, short extra )
558 short prev;
559 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
560 if (!dc) return 0;
561 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
562 prev = dc->w.charExtra;
563 dc->w.charExtra = abs(extra);
564 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
568 /***********************************************************************
569 * SetTextJustification (GDI.10)
571 short SetTextJustification( HDC hdc, short extra, short breaks )
573 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
574 if (!dc) return 0;
576 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
577 if (!extra) breaks = 0;
578 dc->w.breakTotalExtra = extra;
579 dc->w.breakCount = breaks;
580 if (breaks)
582 dc->w.breakExtra = extra / breaks;
583 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
585 else
587 dc->w.breakExtra = 0;
588 dc->w.breakRem = 0;
590 return 1;
594 /***********************************************************************
595 * GetTextFace (GDI.92)
597 INT GetTextFace( HDC hdc, INT count, LPSTR name )
599 FONTOBJ *font;
601 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
602 if (!dc) return 0;
603 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
604 return 0;
605 lstrcpyn( name, font->logfont.lfFaceName, count );
606 return strlen(name);
610 /***********************************************************************
611 * GetTextExtent (GDI.91)
613 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
615 SIZE size;
616 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
617 return MAKELONG( size.cx, size.cy );
621 /***********************************************************************
622 * GetTextExtentPoint (GDI.471)
624 BOOL GetTextExtentPoint( HDC hdc, LPCSTR str, short count, LPSIZE size )
626 int dir, ascent, descent;
627 XCharStruct info;
629 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
630 if (!dc) return FALSE;
631 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
632 &ascent, &descent, &info );
633 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
634 * dc->w.WndExtX / dc->w.VportExtX);
635 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
636 * dc->w.WndExtY / dc->w.VportExtY);
638 dprintf_font(stddeb,"GetTextExtentPoint(%04x '%*.*s' %d %p): returning %d,%d\n",
639 hdc, count, count, str, count, size, size->cx, size->cy );
640 return TRUE;
644 /***********************************************************************
645 * GetTextMetrics (GDI.93)
647 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
649 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
650 if (!dc) return FALSE;
651 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
653 metrics->tmAscent = abs( metrics->tmAscent
654 * dc->w.WndExtY / dc->w.VportExtY );
655 metrics->tmDescent = abs( metrics->tmDescent
656 * dc->w.WndExtY / dc->w.VportExtY );
657 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
658 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
659 * dc->w.WndExtY / dc->w.VportExtY );
660 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
661 * dc->w.WndExtY / dc->w.VportExtY );
662 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
663 * dc->w.WndExtX / dc->w.VportExtX );
664 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
665 * dc->w.WndExtX / dc->w.VportExtX );
666 return TRUE;
670 /***********************************************************************
671 * SetMapperFlags (GDI.349)
673 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
675 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
676 hDC, dwFlag);
677 return 0L;
681 /***********************************************************************
682 * GetCharABCWidths (GDI.307)
684 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC lpABC)
686 /* No TrueType fonts in Wine */
687 return FALSE;
691 /***********************************************************************
692 * GetCharWidth (GDI.350)
694 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
696 int i, j;
697 XFontStruct *xfont;
698 XCharStruct *cs, *def;
700 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
701 if (!dc) return FALSE;
702 xfont = dc->u.x.font.fstruct;
704 /* fixed font? */
705 if (xfont->per_char == NULL)
707 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
708 *(lpBuffer + j) = xfont->max_bounds.width;
709 return TRUE;
712 CI_GET_DEFAULT_INFO(xfont, def);
714 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
716 CI_GET_CHAR_INFO(xfont, i, def, cs);
717 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
718 if (*(lpBuffer + j) < 0)
719 *(lpBuffer + j) = 0;
721 return TRUE;
725 /***********************************************************************
726 * AddFontResource (GDI.119)
728 INT AddFontResource( LPCSTR str )
730 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
731 return 1;
735 /***********************************************************************
736 * RemoveFontResource (GDI.136)
738 BOOL RemoveFontResource( LPSTR str )
740 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
741 return TRUE;
745 /*************************************************************************
746 * ParseFontParms [internal]
748 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
750 int i;
751 if (lpFont == NULL) return 0;
752 if (lpRetStr == NULL) return 0;
753 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
754 if (*lpFont == '-') i++;
755 lpFont++;
757 if (i == wParmsNo) {
758 if (*lpFont == '-') lpFont++;
759 wMaxSiz--;
760 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
761 *(lpRetStr + i) = *lpFont++;
762 *(lpRetStr + i) = '\0';
763 return i;
765 else
766 lpRetStr[0] = '\0';
767 return 0;
771 /*************************************************************************
772 * InitFontsList [internal]
775 static int logfcmp(const void *a,const void *b)
777 return strcmp( (*(LPLOGFONT *)a)->lfFaceName, (*(LPLOGFONT *)b)->lfFaceName );
780 void InitFontsList(void)
782 char str[32];
783 char pattern[100];
784 char *family, *weight, *charset;
785 char **names;
786 char slant, spacing;
787 int i, count;
788 LPLOGFONT lpNewFont;
789 weight = "medium";
790 slant = 'r';
791 spacing = '*';
792 charset = "*";
793 family = "*-*";
794 dprintf_font(stddeb,"InitFontsList !\n");
795 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
796 family, weight, slant, spacing, charset);
797 names = XListFonts( display, pattern, MAX_FONTS, &count );
798 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
799 for (i = 0; i < count; i++) {
800 lpNewFont = malloc(sizeof(LOGFONT) + LF_FACESIZE);
801 if (lpNewFont == NULL) {
802 dprintf_font(stddeb, "InitFontsList // Error alloc new font structure !\n");
803 break;
805 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
806 ParseFontParms(names[i], 2, str, sizeof(str));
807 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
808 AnsiUpper(str);
809 strcpy(lpNewFont->lfFaceName, str);
810 ParseFontParms(names[i], 8, str, sizeof(str));
811 lpNewFont->lfHeight = atoi(str) / 10;
812 ParseFontParms(names[i], 12, str, sizeof(str));
813 lpNewFont->lfWidth = atoi(str) / 10;
814 lpNewFont->lfEscapement = 0;
815 lpNewFont->lfOrientation = 0;
816 lpNewFont->lfWeight = FW_REGULAR;
817 lpNewFont->lfItalic = 0;
818 lpNewFont->lfUnderline = 0;
819 lpNewFont->lfStrikeOut = 0;
820 ParseFontParms(names[i], 13, str, sizeof(str));
821 if (strcmp(str, "iso8859") == 0) {
822 lpNewFont->lfCharSet = ANSI_CHARSET;
823 } else {
824 lpNewFont->lfCharSet = OEM_CHARSET;
826 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
827 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
828 lpNewFont->lfQuality = DEFAULT_QUALITY;
829 ParseFontParms(names[i], 11, str, sizeof(str));
830 switch(str[0]) {
831 case 'p':
832 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
833 break;
834 case 'm':
835 case 'c':
836 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
837 break;
838 default:
839 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
840 break;
842 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfHeight=%d \n", lpNewFont->lfHeight);
843 dprintf_font(stddeb,"InitFontsList // lpNewFont->lfWidth=%d \n", lpNewFont->lfWidth);
844 dprintf_font(stddeb,"InitFontsList // lfFaceName='%s' \n", lpNewFont->lfFaceName);
845 lpLogFontList[i] = lpNewFont;
846 lpLogFontList[i+1] = NULL;
848 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
849 XFreeFontNames(names);
853 /*************************************************************************
854 * EnumFonts [GDI.70]
856 INT EnumFonts(HDC hDC, LPCTSTR lpFaceName, FONTENUMPROC lpEnumFunc, LPARAM lpData)
858 HANDLE hLog;
859 HANDLE hMet;
860 HFONT hFont;
861 HFONT hOldFont;
862 LPLOGFONT lpLogFont;
863 LPTEXTMETRIC lptm;
864 LPSTR lpOldName;
865 char FaceName[LF_FACESIZE];
866 int nRet = 0;
867 int i;
869 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
870 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
871 if (lpEnumFunc == 0) return 0;
872 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT) + LF_FACESIZE );
873 lpLogFont = (LPLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
874 if (lpLogFont == NULL) {
875 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
876 return 0;
878 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
879 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
880 if (lptm == NULL) {
881 GDI_HEAP_FREE(hLog);
882 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
883 return 0;
885 if (lpFaceName != NULL) {
886 strcpy(FaceName, lpFaceName);
887 AnsiUpper(FaceName);
889 lpOldName = NULL;
891 if (lpLogFontList[0] == NULL) InitFontsList();
892 for(i = 0; lpLogFontList[i] != NULL; i++) {
893 if (lpFaceName == NULL) {
894 if (lpOldName != NULL) {
895 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
897 lpOldName = lpLogFontList[i]->lfFaceName;
898 } else {
899 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
901 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
902 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
903 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT) + LF_FACESIZE);
904 hFont = CreateFontIndirect(lpLogFont);
905 hOldFont = SelectObject(hDC, hFont);
906 GetTextMetrics(hDC, lptm);
907 SelectObject(hDC, hOldFont);
908 DeleteObject(hFont);
909 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
910 nRet = CallEnumFontsProc(lpEnumFunc, GDI_HEAP_SEG_ADDR(hLog),
911 GDI_HEAP_SEG_ADDR(hMet), 0, (LONG)lpData );
912 if (nRet == 0) {
913 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
914 break;
917 GDI_HEAP_FREE(hMet);
918 GDI_HEAP_FREE(hLog);
919 return nRet;
923 /*************************************************************************
924 * EnumFontFamilies [GDI.330]
926 INT EnumFontFamilies(HDC hDC, LPCTSTR lpszFamily, FONTENUMPROC lpEnumFunc, LPARAM lpData)
928 HANDLE hLog;
929 HANDLE hMet;
930 HFONT hFont;
931 HFONT hOldFont;
932 LPENUMLOGFONT lpEnumLogFont;
933 LPTEXTMETRIC lptm;
934 LPSTR lpOldName;
935 char FaceName[LF_FACESIZE];
936 int nRet = 0;
937 int i;
939 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
940 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
941 if (lpEnumFunc == 0) return 0;
942 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT) );
943 lpEnumLogFont = (LPENUMLOGFONT) GDI_HEAP_LIN_ADDR(hLog);
944 if (lpEnumLogFont == NULL) {
945 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
946 return 0;
948 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC) );
949 lptm = (LPTEXTMETRIC) GDI_HEAP_LIN_ADDR(hMet);
950 if (lptm == NULL) {
951 GDI_HEAP_FREE(hLog);
952 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
953 return 0;
955 lpOldName = NULL;
956 if (lpszFamily != NULL) {
957 strcpy(FaceName, lpszFamily);
958 AnsiUpper(FaceName);
960 if (lpLogFontList[0] == NULL) InitFontsList();
961 for(i = 0; lpLogFontList[i] != NULL; i++) {
962 if (lpszFamily == NULL) {
963 if (lpOldName != NULL) {
964 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
966 lpOldName = lpLogFontList[i]->lfFaceName;
967 } else {
968 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
970 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT));
971 strcpy(lpEnumLogFont->elfFullName,"");
972 strcpy(lpEnumLogFont->elfStyle,"");
973 hFont = CreateFontIndirect((LPLOGFONT)lpEnumLogFont);
974 hOldFont = SelectObject(hDC, hFont);
975 GetTextMetrics(hDC, lptm);
976 SelectObject(hDC, hOldFont);
977 DeleteObject(hFont);
978 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
980 nRet = CallEnumFontFamProc( lpEnumFunc,
981 GDI_HEAP_SEG_ADDR(hLog),
982 GDI_HEAP_SEG_ADDR(hMet),
983 0, lpData );
984 if (nRet == 0) {
985 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
986 break;
989 GDI_HEAP_FREE(hMet);
990 GDI_HEAP_FREE(hLog);
991 return nRet;
994 /*************************************************************************
995 * GetRasterizerCaps [GDI.313]
998 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1000 /* This is not much more than a dummy */
1001 RASTERIZER_STATUS rs;
1003 rs.nSize = sizeof(rs);
1004 rs.wFlags = 0;
1005 rs.nLanguageID = 0;
1006 return True;
1009 /*************************************************************************
1010 * GetKerningPairs [GDI.332]
1012 int GetKerningPairs(HDC hDC,int cBufLen,LPKERNINGPAIR lpKerningPairs)
1014 /* Wine fonts are ugly and don't support kerning :) */
1015 return 0;