4 * Copyright 1993 Alexandre Julliard
6 * Enhacements by Juergen Marquardt 1996
8 * Implementation of a second font cache which
9 * will be updated dynamically
15 #include <X11/Xatom.h>
24 #define FONTCACHE 32 /* dynamic font cache size */
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))
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
41 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
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; \
48 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
49 if (CI_NONEXISTCHAR(cs)) cs = def; \
54 #define CI_GET_DEFAULT_INFO(fs,cs) \
55 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
57 struct FontStructure {
64 /***********************************************************************
67 BOOL FONT_Init( void )
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 );
80 for( i = 1; i < FontSize; i++ )
82 PROFILE_GetWineIniString( "fonts", FontNames[i].window, "*",
84 FontNames[i].x11 = xstrdup( temp );
86 PROFILE_GetWineIniString( "fonts", "default", "*", temp, sizeof(temp) );
87 FontNames[0].x11 = xstrdup( temp );
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";
102 /***********************************************************************
105 * returns a valid X11 equivalent if a Windows face name
106 * is like a X11 family - or NULL if translation is needed
108 static char *FONT_ChkX11Family(char *winFaceName )
110 static char x11fam[32+2]; /* will be returned */
113 for(i = 0; lpLogFontList[i] != NULL; i++)
114 if( !lstrcmpi32A(winFaceName, lpLogFontList[i]->lfFaceName) )
117 return strcat(x11fam,winFaceName);
119 return NULL; /* a FONT_TranslateName() call is needed */
124 /***********************************************************************
127 * Translate a Windows face name to its X11 equivalent.
128 * This will probably have to be customizable.
130 static const char *FONT_TranslateName( char *winFaceName )
134 for (i = 1; i < FontSize; i ++)
135 if( !strcmp( winFaceName, FontNames[i].window ) ) {
136 dprintf_font(stddeb, "---- Mapped %s to %s\n", winFaceName, FontNames[i].x11 );
137 return FontNames[i].x11;
139 return FontNames[0].x11;
143 /***********************************************************************
146 * Find a X font matching the logical font.
148 static XFontStruct * FONT_MatchFont( LOGFONT16 * font, DC * dc )
151 const char *family, *weight, *charset;
153 char slant, oldspacing, spacing;
154 int width, height, oldheight, count;
155 XFontStruct * fontStruct;
158 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
159 font->lfHeight, font->lfWidth, font->lfWeight, font->lfItalic, font->lfFaceName);
160 weight = (font->lfWeight > 550) ? "bold" : "medium";
161 slant = font->lfItalic ? 'i' : 'r';
162 if (font->lfHeight == -1)
165 height = font->lfHeight * dc->w.VportExtX / dc->w.WndExtX;
166 if (height == 0) height = 120; /* Default height = 12 */
169 /* If height is negative, it means the height of the characters */
170 /* *without* the internal leading. So we adjust it a bit to */
171 /* compensate. 5/4 seems to give good results for small fonts. */
173 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
174 height = 10 * (-height * 9 / 8);
175 * may be we have to use an non linear function
177 /* assume internal leading is 2 pixels. Else small fonts will become
179 height = (height-2) * -10;
182 width = 10 * (font->lfWidth * dc->w.VportExtY / dc->w.WndExtY);
184 dprintf_font( stddeb, "FONT_MatchFont: negative width %d(%d)\n",
185 width, font->lfWidth );
189 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
190 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
193 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*-*";
194 if (*font->lfFaceName) {
195 family = FONT_ChkX11Family(font->lfFaceName);
196 /*--do _not_ translate if lfFaceName is family from X11 A.K.*/
198 family = FONT_TranslateName( font->lfFaceName );
199 /* FIX ME: I don't if that's correct but it works J.M. */
202 else switch(font->lfPitchAndFamily & 0xf0)
205 family = FONT_TranslateName( "roman" );
208 family = FONT_TranslateName( "swiss" );
211 family = FONT_TranslateName( "modern" );
214 family = FONT_TranslateName( "script" );
217 family = FONT_TranslateName( "decorative" );
224 oldspacing = spacing;
226 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
228 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
229 family, weight, slant, height, spacing, charset);
231 sprintf( pattern, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
232 family, weight, slant, height, spacing, width, charset);
233 dprintf_font(stddeb, "FONT_MatchFont: '%s'\n", pattern );
234 names = XListFonts( display, pattern, 1, &count );
235 if (count > 0) break;
236 if (spacing == 'm') /* try 'c' if no 'm' found */ {
240 } else if (spacing == 'p') /* try '*' if no 'p' found */ {
244 spacing = oldspacing;
248 /* try oblique if no italic font */
253 if (spacing == 'm' && strcmp(family, "*-*") != 0) {
254 /* If a fixed spacing font could not be found, ignore
260 fprintf(stderr, "FONT_MatchFont(%s) : returning NULL\n", pattern);
264 dprintf_font(stddeb," Found '%s'\n", *names );
265 if (!*font->lfFaceName)
266 ParseFontParms(*names, 2, font->lfFaceName , LF_FACESIZE-1);
267 /* we need a font name for function GetTextFace() even if there isn't one ;-) */
268 AnsiUpper(font->lfFaceName);
270 fontStruct = XLoadQueryFont( display, *names );
271 XFreeFontNames( names );
276 /***********************************************************************
279 void FONT_GetMetrics( LOGFONT16 * logfont, XFontStruct * xfont,
280 TEXTMETRIC16 * metrics )
282 int average, i, count;
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;
313 XCharStruct * charPtr = xfont->per_char;
315 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
317 if (!CI_NONEXISTCHAR( charPtr ))
319 average += charPtr->width;
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 * CreateFontIndirect16 (GDI.57)
360 HFONT16 CreateFontIndirect16( const LOGFONT16 *font )
367 fprintf(stderr,"CreateFontIndirect: font is NULL : returning NULL\n");
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(LOGFONT16) );
374 AnsiLower( fontPtr->logfont.lfFaceName );
375 dprintf_font(stddeb,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
376 font, font->lfHeight, font->lfWidth, hfont);
381 /***********************************************************************
382 * CreateFontIndirect32A (GDI32.44)
384 HFONT32 CreateFontIndirect32A( const LOGFONT32A *font )
388 font16.lfHeight = (INT16)font->lfHeight;
389 font16.lfWidth = (INT16)font->lfWidth;
390 font16.lfEscapement = (INT16)font->lfEscapement;
391 font16.lfOrientation = (INT16)font->lfOrientation;
392 font16.lfWeight = (INT16)font->lfWeight;
393 font16.lfItalic = font->lfItalic;
394 font16.lfUnderline = font->lfUnderline;
395 font16.lfStrikeOut = font->lfStrikeOut;
396 font16.lfCharSet = font->lfCharSet;
397 font16.lfOutPrecision = font->lfOutPrecision;
398 font16.lfClipPrecision = font->lfClipPrecision;
399 font16.lfQuality = font->lfQuality;
400 font16.lfPitchAndFamily = font->lfPitchAndFamily;
401 lstrcpyn32A( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
402 return CreateFontIndirect16( &font16 );
406 /***********************************************************************
407 * CreateFontIndirect32W (GDI32.45)
409 HFONT32 CreateFontIndirect32W( const LOGFONT32W *font )
413 font16.lfHeight = (INT16)font->lfHeight;
414 font16.lfWidth = (INT16)font->lfWidth;
415 font16.lfEscapement = (INT16)font->lfEscapement;
416 font16.lfOrientation = (INT16)font->lfOrientation;
417 font16.lfWeight = (INT16)font->lfWeight;
418 font16.lfItalic = font->lfItalic;
419 font16.lfUnderline = font->lfUnderline;
420 font16.lfStrikeOut = font->lfStrikeOut;
421 font16.lfCharSet = font->lfCharSet;
422 font16.lfOutPrecision = font->lfOutPrecision;
423 font16.lfClipPrecision = font->lfClipPrecision;
424 font16.lfQuality = font->lfQuality;
425 font16.lfPitchAndFamily = font->lfPitchAndFamily;
426 lstrcpynWtoA( font16.lfFaceName, font->lfFaceName, LF_FACESIZE );
427 return CreateFontIndirect16( &font16 );
431 /***********************************************************************
432 * CreateFont16 (GDI.56)
434 HFONT16 CreateFont16( INT16 height, INT16 width, INT16 esc, INT16 orient,
435 INT16 weight, BYTE italic, BYTE underline,
436 BYTE strikeout, BYTE charset, BYTE outpres,
437 BYTE clippres, BYTE quality, BYTE pitch, LPCSTR name )
439 LOGFONT16 logfont = {height, width, esc, orient, weight, italic, underline,
440 strikeout, charset, outpres, clippres, quality, pitch, };
441 dprintf_font(stddeb,"CreateFont16(%d,%d)\n", height, width);
442 if (name) lstrcpyn32A(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
443 else logfont.lfFaceName[0] = '\0';
444 return CreateFontIndirect16( &logfont );
449 /*************************************************************************
450 * CreateFont32A (GDI32.43)
452 HFONT32 CreateFont32A( INT32 height, INT32 width, INT32 esc, INT32 orient,
453 INT32 weight, DWORD italic, DWORD underline,
454 DWORD strikeout, DWORD charset, DWORD outpres,
455 DWORD clippres, DWORD quality, DWORD pitch, LPCSTR name)
457 return (HFONT32)CreateFont16( height, width, esc, orient, weight, italic,
458 underline, strikeout, charset, outpres,
459 clippres, quality, pitch, name );
463 /*************************************************************************
464 * CreateFont32W (GDI32.46)
466 HFONT32 CreateFont32W( INT32 height, INT32 width, INT32 esc, INT32 orient,
467 INT32 weight, DWORD italic, DWORD underline,
468 DWORD strikeout, DWORD charset, DWORD outpres,
469 DWORD clippres, DWORD quality, DWORD pitch,
472 LPSTR namea = name ? STRING32_DupUniToAnsi(name) : NULL;
473 HFONT32 ret = (HFONT32)CreateFont16( height, width, esc, orient, weight,
474 italic, underline, strikeout, charset,
475 outpres, clippres, quality, pitch,
482 /***********************************************************************
485 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
487 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
488 memcpy( buffer, &font->logfont, count );
493 /***********************************************************************
496 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
498 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
505 X_PHYSFONT cacheFont; } cacheFonts[FONTCACHE], *cacheFontsMin;
508 X_PHYSFONT * stockPtr;
509 HFONT prevHandle = dc->w.hFont;
510 XFontStruct * fontStruct;
511 dprintf_font(stddeb,"FONT_SelectObject(%p, %04x, %p)\n", dc, hfont, font);
513 #if 0 /* From the code in SelectObject, this can not happen */
514 /* Load font if necessary */
519 hnewfont = CreateFont16(10, 7, 0, 0, FW_DONTCARE,
520 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
521 DEFAULT_QUALITY, FF_DONTCARE, "*" );
522 font = (FONTOBJ *) GDI_HEAP_LIN_ADDR( hnewfont );
526 if (dc->header.wMagic == METAFILE_DC_MAGIC)
527 if (MF_CreateFontIndirect(dc, hfont, &(font->logfont)))
532 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
533 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
537 * Ok, It's not a stock font but
538 * may be it's cached in dynamic cache
540 for(i=0; i<FONTCACHE; i++) /* search for same handle */
541 if (cacheFonts[i].id==hfont) { /* Got the handle */
543 * Check if Handle matches the font
545 if(memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16))) {
546 /* No: remove handle id from dynamic font cache */
547 cacheFonts[i].access=0;
548 cacheFonts[i].used=0;
550 /* may be there is an unused handle which contains the font */
551 for(i=0; i<FONTCACHE; i++) {
552 if((cacheFonts[i].used == 0) &&
553 (memcmp(&cacheFonts[i].logfont,&(font->logfont), sizeof(LOGFONT16)))== 0) {
554 /* got it load from cache and set new handle id */
555 stockPtr = &cacheFonts[i].cacheFont;
556 cacheFonts[i].access=1;
557 cacheFonts[i].used=1;
558 cacheFonts[i].id=hfont;
559 dprintf_font(stddeb,"FONT_SelectObject: got font from unused handle\n");
566 /* Yes: load from dynamic font cache */
567 stockPtr = &cacheFonts[i].cacheFont;
568 cacheFonts[i].access++;
569 cacheFonts[i].used++;
574 if (!stockPtr || !stockPtr->fstruct)
576 if (!(fontStruct = FONT_MatchFont( &font->logfont, dc )))
578 /* If it is not a stock font, we can simply return 0 */
579 if (!stockPtr) return 0;
580 /* Otherwise we must try to find a substitute */
581 dprintf_font(stddeb,"Loading font 'fixed' for %04x\n", hfont );
582 font->logfont.lfPitchAndFamily &= ~VARIABLE_PITCH;
583 font->logfont.lfPitchAndFamily |= FIXED_PITCH;
584 fontStruct = XLoadQueryFont( display, "fixed" );
587 fprintf( stderr, "No system font could be found. Please check your font path.\n" );
594 fontStruct = stockPtr->fstruct;
596 "FONT_SelectObject: Loaded font from cache %04x %p\n",
600 /* Unuse previous font */
601 for (i=0; i < FONTCACHE; i++) {
602 if (cacheFonts[i].id == prevHandle) {
603 if(cacheFonts[i].used == 0)
604 fprintf(stderr, "Trying to decrement a use count of 0.\n");
606 cacheFonts[i].used--;
614 if (!stockPtr->fstruct)
616 stockPtr->fstruct = fontStruct;
617 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
619 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
627 for (i=0; i < FONTCACHE; i++) {
628 if (cacheFonts[i].used==0)
629 if ((!cacheFontsMin) || ((cacheFontsMin) && (cacheFontsMin->access > cacheFonts[i].access)))
630 cacheFontsMin=&cacheFonts[i];
632 if (!cacheFontsMin) {
633 fprintf(stderr,"No unused font cache entry !!!!\n" );
636 if (cacheFontsMin->id!=0) {
638 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin->id );
639 XFreeFont( display, cacheFontsMin->cacheFont.fstruct );
641 cacheFontsMin->cacheFont.fstruct = fontStruct;
642 FONT_GetMetrics( &font->logfont, fontStruct, &cacheFontsMin->cacheFont.metrics );
643 cacheFontsMin->access=1;
644 cacheFontsMin->used=1;
645 cacheFontsMin->id=hfont;
646 memcpy( &dc->u.x.font, &(cacheFontsMin->cacheFont), sizeof(cacheFontsMin->cacheFont) );
647 memcpy(&cacheFontsMin->logfont,&(font->logfont), sizeof(LOGFONT16));
654 /***********************************************************************
655 * GetTextCharacterExtra (GDI.89)
657 short GetTextCharacterExtra( HDC hdc )
659 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
661 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
666 /***********************************************************************
667 * SetTextCharacterExtra (GDI.8)
669 short SetTextCharacterExtra( HDC hdc, short extra )
672 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
674 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
675 prev = dc->w.charExtra;
676 dc->w.charExtra = abs(extra);
677 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
681 /***********************************************************************
682 * SetTextJustification (GDI.10)
684 short SetTextJustification( HDC hdc, short extra, short breaks )
686 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
689 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
690 if (!extra) breaks = 0;
691 dc->w.breakTotalExtra = extra;
692 dc->w.breakCount = breaks;
695 dc->w.breakExtra = extra / breaks;
696 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
700 dc->w.breakExtra = 0;
707 /***********************************************************************
708 * GetTextFace (GDI.92)
710 INT GetTextFace( HDC hdc, INT count, LPSTR name )
714 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
716 if (!(font = (FONTOBJ *) GDI_GetObjPtr( dc->w.hFont, FONT_MAGIC )))
718 lstrcpyn32A( name, font->logfont.lfFaceName, count );
723 /***********************************************************************
724 * GetTextExtent (GDI.91)
726 DWORD GetTextExtent( HDC hdc, LPCSTR str, short count )
729 if (!GetTextExtentPoint16( hdc, str, count, &size )) return 0;
730 return MAKELONG( size.cx, size.cy );
734 /***********************************************************************
735 * GetTextExtentPoint16 (GDI.471)
737 BOOL16 GetTextExtentPoint16( HDC16 hdc, LPCSTR str, INT16 count, LPSIZE16 size)
740 BOOL32 ret = GetTextExtentPoint32A( hdc, str, count, &size32 );
741 CONV_SIZE32TO16( &size32, size );
746 /***********************************************************************
747 * GetTextExtentPoint32A (GDI32.232)
749 BOOL32 GetTextExtentPoint32A( HDC32 hdc, LPCSTR str, INT32 count,
752 int dir, ascent, descent;
755 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
756 if (!dc) return FALSE;
757 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
758 &ascent, &descent, &info );
759 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
760 * dc->w.WndExtX / dc->w.VportExtX);
761 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
762 * dc->w.WndExtY / dc->w.VportExtY);
764 dprintf_font(stddeb,"GetTextExtentPoint(%08x '%*.*s' %d %p): returning %d,%d\n",
765 hdc, count, count, str, count, size, size->cx, size->cy );
770 /***********************************************************************
771 * GetTextExtentPoint32W (GDI32.233)
773 BOOL32 GetTextExtentPoint32W( HDC32 hdc, LPCWSTR str, INT32 count,
776 char *p = STRING32_DupUniToAnsi( str );
777 BOOL32 ret = GetTextExtentPoint32A( hdc, p, count, size );
783 /***********************************************************************
784 * GetTextMetrics16 (GDI.93)
786 BOOL16 GetTextMetrics16( HDC16 hdc, TEXTMETRIC16 *metrics )
788 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
789 if (!dc) return FALSE;
790 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
792 metrics->tmAscent = abs( metrics->tmAscent
793 * dc->w.WndExtY / dc->w.VportExtY );
794 metrics->tmDescent = abs( metrics->tmDescent
795 * dc->w.WndExtY / dc->w.VportExtY );
796 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
797 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
798 * dc->w.WndExtY / dc->w.VportExtY );
799 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
800 * dc->w.WndExtY / dc->w.VportExtY );
801 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
802 * dc->w.WndExtX / dc->w.VportExtX );
803 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
804 * dc->w.WndExtX / dc->w.VportExtX );
806 dprintf_font(stdnimp,"text metrics:\n
820 DigitizedAspectX = %i
821 DigitizedAspectY = %i
827 metrics->tmInternalLeading,
828 metrics->tmExternalLeading,
829 metrics->tmMaxCharWidth,
832 metrics->tmUnderlined,
833 metrics->tmStruckOut,
834 metrics->tmFirstChar,
836 metrics->tmDefaultChar,
837 metrics->tmBreakChar,
840 metrics->tmDigitizedAspectX,
841 metrics->tmDigitizedAspectY,
842 metrics->tmAveCharWidth,
843 metrics->tmMaxCharWidth,
852 /***********************************************************************
853 * GetTextMetrics32A (GDI32.236)
855 BOOL32 GetTextMetrics32A( HDC32 hdc, TEXTMETRIC32A *metrics )
858 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
859 metrics->tmHeight = tm.tmHeight;
860 metrics->tmAscent = tm.tmAscent;
861 metrics->tmDescent = tm.tmDescent;
862 metrics->tmInternalLeading = tm.tmInternalLeading;
863 metrics->tmExternalLeading = tm.tmExternalLeading;
864 metrics->tmAveCharWidth = tm.tmAveCharWidth;
865 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
866 metrics->tmWeight = tm.tmWeight;
867 metrics->tmOverhang = tm.tmOverhang;
868 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
869 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
870 metrics->tmFirstChar = tm.tmFirstChar;
871 metrics->tmLastChar = tm.tmLastChar;
872 metrics->tmDefaultChar = tm.tmDefaultChar;
873 metrics->tmBreakChar = tm.tmBreakChar;
874 metrics->tmItalic = tm.tmItalic;
875 metrics->tmUnderlined = tm.tmUnderlined;
876 metrics->tmStruckOut = tm.tmStruckOut;
877 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
878 metrics->tmCharSet = tm.tmCharSet;
883 /***********************************************************************
884 * GetTextMetrics32W (GDI32.237)
886 BOOL32 GetTextMetrics32W( HDC32 hdc, TEXTMETRIC32W *metrics )
889 if (!GetTextMetrics16( (HDC16)hdc, &tm )) return FALSE;
890 metrics->tmHeight = tm.tmHeight;
891 metrics->tmAscent = tm.tmAscent;
892 metrics->tmDescent = tm.tmDescent;
893 metrics->tmInternalLeading = tm.tmInternalLeading;
894 metrics->tmExternalLeading = tm.tmExternalLeading;
895 metrics->tmAveCharWidth = tm.tmAveCharWidth;
896 metrics->tmMaxCharWidth = tm.tmMaxCharWidth;
897 metrics->tmWeight = tm.tmWeight;
898 metrics->tmOverhang = tm.tmOverhang;
899 metrics->tmDigitizedAspectX = tm.tmDigitizedAspectX;
900 metrics->tmDigitizedAspectY = tm.tmDigitizedAspectY;
901 metrics->tmFirstChar = tm.tmFirstChar;
902 metrics->tmLastChar = tm.tmLastChar;
903 metrics->tmDefaultChar = tm.tmDefaultChar;
904 metrics->tmBreakChar = tm.tmBreakChar;
905 metrics->tmItalic = tm.tmItalic;
906 metrics->tmUnderlined = tm.tmUnderlined;
907 metrics->tmStruckOut = tm.tmStruckOut;
908 metrics->tmPitchAndFamily = tm.tmPitchAndFamily;
909 metrics->tmCharSet = tm.tmCharSet;
914 /***********************************************************************
915 * SetMapperFlags (GDI.349)
917 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
919 dprintf_font(stdnimp,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
925 /***********************************************************************
926 * GetCharABCWidths (GDI.307)
928 BOOL GetCharABCWidths(HDC hdc, UINT wFirstChar, UINT wLastChar, LPABC16 lpABC)
931 /* No TrueType fonts in Wine so far */
933 fprintf(stdnimp,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
934 hdc,wFirstChar,wLastChar,(unsigned)lpABC);
940 /***********************************************************************
941 * GetCharWidth (GDI.350)
943 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT16 lpBuffer)
947 XCharStruct *cs, *def;
949 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
950 if (!dc) return FALSE;
951 xfont = dc->u.x.font.fstruct;
954 if (xfont->per_char == NULL)
956 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
957 *(lpBuffer + j) = xfont->max_bounds.width;
961 CI_GET_DEFAULT_INFO(xfont, def);
963 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
965 CI_GET_CHAR_INFO(xfont, i, def, cs);
966 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
967 if (*(lpBuffer + j) < 0)
974 /***********************************************************************
975 * AddFontResource (GDI.119)
977 INT AddFontResource( LPCSTR str )
979 fprintf( stdnimp, "STUB: AddFontResource('%s')\n", str );
984 /***********************************************************************
985 * RemoveFontResource (GDI.136)
987 BOOL RemoveFontResource( LPSTR str )
989 fprintf( stdnimp, "STUB: RemoveFontResource('%s')\n", str );
994 /*************************************************************************
995 * ParseFontParms [internal]
997 int ParseFontParms(LPSTR lpFont, WORD wParmsNo, LPSTR lpRetStr, WORD wMaxSiz)
1000 if (lpFont == NULL) return 0;
1001 if (lpRetStr == NULL) return 0;
1002 for (i = 0; (*lpFont != '\0' && i != wParmsNo); ) {
1003 if (*lpFont == '-') i++;
1006 if (i == wParmsNo) {
1007 if (*lpFont == '-') lpFont++;
1009 for (i = 0; (*lpFont != '\0' && *lpFont != '-' && i < wMaxSiz); i++)
1010 *(lpRetStr + i) = *lpFont++;
1011 *(lpRetStr + i) = '\0';
1020 /*************************************************************************
1021 * InitFontsList [internal]
1024 static int logfcmp(const void *a,const void *b)
1026 return strcmp( (*(LPLOGFONT16 *)a)->lfFaceName,
1027 (*(LPLOGFONT16 *)b)->lfFaceName );
1030 void InitFontsList(void)
1034 char *family, *weight, *charset;
1036 char slant, spacing;
1038 LPLOGFONT16 lpNewFont;
1040 dprintf_font(stddeb,"InitFontsList !\n");
1048 sprintf( pattern, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1049 family, weight, slant, spacing, charset);
1050 names = XListFonts( display, pattern, MAX_FONTS, &count );
1051 dprintf_font(stddeb,"InitFontsList // count=%d \n", count);
1053 lpNewFont = malloc((sizeof(LOGFONT16)+LF_FACESIZE)*count);
1054 if (lpNewFont == NULL) {
1055 dprintf_font(stddeb,
1056 "InitFontsList // Error alloc new font structure !\n");
1057 XFreeFontNames(names);
1061 for (i = 0; i < count; i++) {
1062 dprintf_font(stddeb,"InitFontsList // names[%d]='%s' \n", i, names[i]);
1064 ParseFontParms(names[i], 2, str, sizeof(str));
1066 /* not necessary because new function FONT_ChkX11Family() */
1067 if (strcmp(str, "fixed") == 0) strcat(str, "sys");
1070 strcpy(lpNewFont->lfFaceName, str);
1071 ParseFontParms(names[i], 8, str, sizeof(str));
1072 lpNewFont->lfHeight = atoi(str) / 10;
1073 ParseFontParms(names[i], 12, str, sizeof(str));
1074 lpNewFont->lfWidth = atoi(str) / 10;
1075 lpNewFont->lfEscapement = 0;
1076 lpNewFont->lfOrientation = 0;
1077 lpNewFont->lfWeight = FW_REGULAR;
1078 lpNewFont->lfItalic = 0;
1079 lpNewFont->lfUnderline = 0;
1080 lpNewFont->lfStrikeOut = 0;
1081 ParseFontParms(names[i], 13, str, sizeof(str));
1082 if (strcmp(str, "iso8859") == 0) {
1083 lpNewFont->lfCharSet = ANSI_CHARSET;
1085 lpNewFont->lfCharSet = OEM_CHARSET;
1087 lpNewFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
1088 lpNewFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
1089 lpNewFont->lfQuality = DEFAULT_QUALITY;
1090 ParseFontParms(names[i], 11, str, sizeof(str));
1093 lpNewFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
1097 lpNewFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
1100 lpNewFont->lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
1103 dprintf_font( stddeb,
1104 "InitFontsList // lpNewFont->lfHeight=%d\n",
1105 lpNewFont->lfHeight );
1106 dprintf_font( stddeb,
1107 "InitFontsList // lpNewFont->lfWidth=%d\n",
1108 lpNewFont->lfWidth );
1109 dprintf_font( stddeb,
1110 "InitFontsList // lfFaceName='%s'\n",
1111 lpNewFont->lfFaceName );
1112 lpLogFontList[i] = lpNewFont;
1113 lpNewFont = (LPLOGFONT16)
1114 ((char *)lpNewFont + sizeof(LOGFONT16)+LF_FACESIZE);
1116 lpLogFontList[i] = NULL;
1118 qsort(lpLogFontList,count,sizeof(*lpLogFontList),logfcmp);
1119 XFreeFontNames(names);
1123 /*************************************************************************
1124 * EnumFonts [GDI.70]
1126 INT EnumFonts(HDC hDC, LPCSTR lpFaceName, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1132 LPLOGFONT16 lpLogFont;
1133 LPTEXTMETRIC16 lptm;
1135 char FaceName[LF_FACESIZE];
1139 dprintf_font(stddeb,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
1140 hDC, lpFaceName, lpFaceName, (LONG)lpEnumFunc, lpData);
1141 if (lpEnumFunc == 0) return 0;
1142 hLog = GDI_HEAP_ALLOC( sizeof(LOGFONT16) + LF_FACESIZE );
1143 lpLogFont = (LPLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1144 if (lpLogFont == NULL) {
1145 fprintf(stderr,"EnumFonts // can't alloc LOGFONT struct !\n");
1148 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1149 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1151 GDI_HEAP_FREE(hLog);
1152 fprintf(stderr, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1155 if (lpFaceName != NULL) {
1156 strcpy(FaceName, lpFaceName);
1157 AnsiUpper(FaceName);
1161 if (lpLogFontList[0] == NULL) InitFontsList();
1162 for(i = 0; lpLogFontList[i] != NULL; i++) {
1163 if (lpFaceName == NULL) {
1164 if (lpOldName != NULL) {
1165 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1167 lpOldName = lpLogFontList[i]->lfFaceName;
1169 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1171 dprintf_font(stddeb,"EnumFonts // enum '%s' !\n", lpLogFontList[i]->lfFaceName);
1172 dprintf_font(stddeb,"EnumFonts // %p !\n", lpLogFontList[i]);
1173 memcpy(lpLogFont, lpLogFontList[i], sizeof(LOGFONT16) + LF_FACESIZE);
1174 hFont = CreateFontIndirect16(lpLogFont);
1175 hOldFont = SelectObject(hDC, hFont);
1176 GetTextMetrics16(hDC, lptm);
1177 SelectObject(hDC, hOldFont);
1178 DeleteObject(hFont);
1179 dprintf_font(stddeb,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i, lpLogFont, lptm);
1180 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1183 dprintf_font(stddeb,"EnumFonts // EnumEnd requested by application !\n");
1187 GDI_HEAP_FREE(hMet);
1188 GDI_HEAP_FREE(hLog);
1193 /*************************************************************************
1194 * EnumFontFamilies [GDI.330]
1196 INT EnumFontFamilies(HDC hDC, LPCSTR lpszFamily, FONTENUMPROC16 lpEnumFunc, LPARAM lpData)
1202 LPENUMLOGFONT16 lpEnumLogFont;
1203 LPTEXTMETRIC16 lptm;
1205 char FaceName[LF_FACESIZE];
1209 dprintf_font(stddeb,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1210 hDC, lpszFamily, (DWORD)lpEnumFunc, lpData);
1211 if (lpEnumFunc == 0) return 0;
1212 hLog = GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16) );
1213 lpEnumLogFont = (LPENUMLOGFONT16) GDI_HEAP_LIN_ADDR(hLog);
1214 if (lpEnumLogFont == NULL) {
1215 fprintf(stderr,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1218 hMet = GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16) );
1219 lptm = (LPTEXTMETRIC16) GDI_HEAP_LIN_ADDR(hMet);
1221 GDI_HEAP_FREE(hLog);
1222 fprintf(stderr,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1226 if (lpszFamily != NULL) {
1227 strcpy(FaceName, lpszFamily);
1228 AnsiUpper(FaceName);
1230 if (lpLogFontList[0] == NULL) InitFontsList();
1231 for(i = 0; lpLogFontList[i] != NULL; i++) {
1232 if (lpszFamily == NULL) {
1233 if (lpOldName != NULL) {
1234 if (strcmp(lpOldName,lpLogFontList[i]->lfFaceName) == 0) continue;
1236 lpOldName = lpLogFontList[i]->lfFaceName;
1238 if (strcmp(FaceName, lpLogFontList[i]->lfFaceName) != 0) continue;
1240 memcpy(lpEnumLogFont, lpLogFontList[i], sizeof(LOGFONT16));
1241 strcpy(lpEnumLogFont->elfFullName,"");
1242 strcpy(lpEnumLogFont->elfStyle,"");
1243 hFont = CreateFontIndirect16((LPLOGFONT16)lpEnumLogFont);
1244 hOldFont = SelectObject(hDC, hFont);
1245 GetTextMetrics16(hDC, lptm);
1246 SelectObject(hDC, hOldFont);
1247 DeleteObject(hFont);
1248 dprintf_font(stddeb, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i, lpEnumLogFont, lptm);
1250 nRet = lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog), GDI_HEAP_SEG_ADDR(hMet),
1253 dprintf_font(stddeb,"EnumFontFamilies // EnumEnd requested by application !\n");
1257 GDI_HEAP_FREE(hMet);
1258 GDI_HEAP_FREE(hLog);
1262 /*************************************************************************
1263 * GetRasterizerCaps [GDI.313]
1266 BOOL GetRasterizerCaps(LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1268 /* This is not much more than a dummy */
1269 RASTERIZER_STATUS rs;
1271 rs.nSize = sizeof(rs);
1277 /*************************************************************************
1278 * GetKerningPairs [GDI.332]
1280 int GetKerningPairs(HDC hDC,int cPairs,LPKERNINGPAIR16 lpKerningPairs)
1282 /* This has to be dealt with when proper font handling is in place
1284 * At this time kerning is ignored (set to 0)
1288 fprintf(stdnimp,"GetKerningPairs: almost empty stub!\n");
1289 for (i = 0; i < cPairs; i++) lpKerningPairs[i].iKernAmount = 0;