Release 940518
[wine/multimedia.git] / objects / font.c
blob2ff21c51404efad6012faf2a105dd292a4de3372
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 */
7 static char Copyright[] = "Copyright Alexandre Julliard, 1993";
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <X11/Xatom.h>
13 #include "user.h"
14 #include "gdi.h"
17 /***********************************************************************
18 * FONT_MatchFont
20 * Find a X font matching the logical font.
22 static XFontStruct * FONT_MatchFont( LOGFONT * font )
24 char pattern[100];
25 char *family, *weight, *charset;
26 char **names;
27 char slant, spacing;
28 int width, height, count;
29 XFontStruct * fontStruct;
31 weight = (font->lfWeight > 550) ? "bold" : "medium";
32 slant = font->lfItalic ? 'i' : 'r';
33 height = font->lfHeight * 10;
34 width = font->lfWidth * 10;
35 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
36 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
37 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
38 family = font->lfFaceName;
39 if (!*family) switch(font->lfPitchAndFamily & 0xf0)
41 case FF_ROMAN: family = "times"; break;
42 case FF_SWISS: family = "helvetica"; break;
43 case FF_MODERN: family = "courier"; break;
44 case FF_SCRIPT: family = "*"; break;
45 case FF_DECORATIVE: family = "*"; break;
46 default: family = "*"; break;
49 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
50 if ( width == 0 )
51 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-*-%s",
52 family, weight, slant, height, spacing, charset
54 else
55 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
56 family, weight, slant, height, spacing, width, charset
59 #ifdef DEBUG_FONT
60 printf( "FONT_MatchFont: '%s'\n", pattern );
61 #endif
62 names = XListFonts( XT_display, pattern, 1, &count );
63 if (!count)
65 #ifdef DEBUG_FONT
66 printf( " No matching font found\n" );
67 #endif
68 return NULL;
70 #ifdef DEBUG_FONT
71 printf( " Found '%s'\n", *names );
72 #endif
73 fontStruct = XLoadQueryFont( XT_display, *names );
74 XFreeFontNames( names );
75 return fontStruct;
79 /***********************************************************************
80 * FONT_GetMetrics
82 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
83 TEXTMETRIC * metrics )
85 int average, i;
86 unsigned long prop;
88 metrics->tmAscent = xfont->ascent;
89 metrics->tmDescent = xfont->descent;
90 metrics->tmHeight = xfont->ascent + xfont->descent;
92 metrics->tmInternalLeading = 0;
93 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
94 metrics->tmInternalLeading = xfont->ascent - (short)prop;
95 metrics->tmExternalLeading = 0;
96 metrics->tmMaxCharWidth = xfont->max_bounds.width;
97 metrics->tmWeight = logfont->lfWeight;
98 metrics->tmItalic = logfont->lfItalic;
99 metrics->tmUnderlined = logfont->lfUnderline;
100 metrics->tmStruckOut = logfont->lfStrikeOut;
101 metrics->tmFirstChar = xfont->min_char_or_byte2;
102 metrics->tmLastChar = xfont->max_char_or_byte2;
103 metrics->tmDefaultChar = xfont->default_char;
104 metrics->tmBreakChar = ' ';
105 metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
106 metrics->tmCharSet = logfont->lfCharSet;
107 metrics->tmOverhang = 0;
108 metrics->tmDigitizedAspectX = 1;
109 metrics->tmDigitizedAspectY = 1;
111 if (xfont->per_char) average = metrics->tmMaxCharWidth;
112 else
114 XCharStruct * charPtr = xfont->per_char;
115 average = 0;
116 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
118 average += charPtr->width;
119 charPtr++;
121 average /= metrics->tmLastChar - metrics->tmFirstChar + 1;
123 metrics->tmAveCharWidth = average;
127 /***********************************************************************
128 * CreateFontIndirect (GDI.57)
130 HFONT CreateFontIndirect( LOGFONT * font )
132 FONTOBJ * fontPtr;
133 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
134 if (!hfont) return 0;
135 fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
136 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
137 return hfont;
141 /***********************************************************************
142 * CreateFont (GDI.56)
144 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
145 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
146 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
147 LPSTR name )
149 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
150 strikeout, charset, outpres, clippres, quality, pitch, };
151 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
152 return CreateFontIndirect( &logfont );
156 /***********************************************************************
157 * FONT_GetObject
159 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
161 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
162 memcpy( buffer, &font->logfont, count );
163 return count;
167 /***********************************************************************
168 * FONT_SelectObject
170 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
172 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
173 X_PHYSFONT * stockPtr;
174 HFONT prevHandle = dc->w.hFont;
175 XFontStruct * fontStruct;
177 /* Load font if necessary */
179 if (!font)
181 HFONT hnewfont;
183 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
184 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
185 DEFAULT_QUALITY, FF_DONTCARE, "*" );
186 font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
189 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
190 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
191 else
192 stockPtr = NULL;
194 if (!stockPtr || !stockPtr->fstruct)
196 fontStruct = FONT_MatchFont( &font->logfont );
198 else
200 fontStruct = stockPtr->fstruct;
201 #ifdef DEBUG_FONT
202 printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
203 hfont, fontStruct );
204 #endif
206 if (!fontStruct) return 0;
208 /* Free previous font */
210 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
212 if (dc->u.x.font.fstruct)
213 XFreeFont( XT_display, dc->u.x.font.fstruct );
216 /* Store font */
218 dc->w.hFont = hfont;
219 if (stockPtr)
221 if (!stockPtr->fstruct)
223 stockPtr->fstruct = fontStruct;
224 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
226 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
228 else
230 dc->u.x.font.fstruct = fontStruct;
231 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
233 return prevHandle;
237 /***********************************************************************
238 * GetTextCharacterExtra (GDI.89)
240 short GetTextCharacterExtra( HDC hdc )
242 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
243 if (!dc) return 0;
244 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
245 / dc->w.VportExtX );
249 /***********************************************************************
250 * SetTextCharacterExtra (GDI.8)
252 short SetTextCharacterExtra( HDC hdc, short extra )
254 short prev;
255 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
256 if (!dc) return 0;
257 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
258 prev = dc->w.charExtra;
259 dc->w.charExtra = abs(extra);
260 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
264 /***********************************************************************
265 * SetTextJustification (GDI.10)
267 short SetTextJustification( HDC hdc, short extra, short breaks )
269 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
270 if (!dc) return 0;
272 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
273 if (!extra) breaks = 0;
274 dc->w.breakTotalExtra = extra;
275 dc->w.breakCount = breaks;
276 if (breaks)
278 dc->w.breakExtra = extra / breaks;
279 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
281 else
283 dc->w.breakExtra = 0;
284 dc->w.breakRem = 0;
286 return 1;
290 /***********************************************************************
291 * GetTextExtent (GDI.91)
293 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
295 SIZE size;
296 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
297 return size.cx | (size.cy << 16);
301 /***********************************************************************
302 * GetTextExtentPoint (GDI.471)
304 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
306 int dir, ascent, descent;
307 XCharStruct info;
309 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
310 if (!dc) return FALSE;
311 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
312 &ascent, &descent, &info );
313 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
314 * dc->w.WndExtX / dc->w.VportExtX);
315 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
316 * dc->w.WndExtY / dc->w.VportExtY);
318 #ifdef DEBUG_FONT
319 printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
320 hdc, str, count, size, size->cx, size->cy );
321 #endif
322 return TRUE;
326 /***********************************************************************
327 * GetTextMetrics (GDI.93)
329 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
331 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
332 if (!dc) return FALSE;
333 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
335 metrics->tmAscent = abs( metrics->tmAscent
336 * dc->w.WndExtY / dc->w.VportExtY );
337 metrics->tmDescent = abs( metrics->tmDescent
338 * dc->w.WndExtY / dc->w.VportExtY );
339 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
340 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
341 * dc->w.WndExtY / dc->w.VportExtY );
342 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
343 * dc->w.WndExtY / dc->w.VportExtY );
344 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
345 * dc->w.WndExtX / dc->w.VportExtX );
346 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
347 * dc->w.WndExtX / dc->w.VportExtX );
348 return TRUE;
352 /***********************************************************************
353 * SetMapperFlags (GDI.349)
355 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
357 printf("SetmapperFlags(%04X, %08X) // Empty Stub !\n", hDC, dwFlag);
358 return 0L;
362 /***********************************************************************/
364 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
365 (((cs)->rbearing|(cs)->lbearing| \
366 (cs)->ascent|(cs)->descent) == 0))
369 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
370 * character. If the character is in the column and exists, then return the
371 * appropriate metrics (note that fonts with common per-character metrics will
372 * return min_bounds). If none of these hold true, try again with the default
373 * char.
375 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
377 cs = def; \
378 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
379 if (fs->per_char == NULL) { \
380 cs = &fs->min_bounds; \
381 } else { \
382 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
383 if (CI_NONEXISTCHAR(cs)) cs = def; \
388 #define CI_GET_DEFAULT_INFO(fs,cs) \
389 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
392 /***********************************************************************
393 * GetCharWidth (GDI.350)
395 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
397 int i, j;
398 XFontStruct *xfont;
399 XCharStruct *cs, *def;
401 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
402 if (!dc) return FALSE;
403 xfont = dc->u.x.font.fstruct;
405 /* fixed font? */
406 if (xfont->per_char == NULL)
408 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
409 *(lpBuffer + j) = xfont->max_bounds.width;
410 return TRUE;
413 CI_GET_DEFAULT_INFO(xfont, def);
415 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
417 CI_GET_CHAR_INFO(xfont, i, def, cs);
418 *(lpBuffer + j) = cs ? cs->width : xfont->max_bounds.width;
419 if (*(lpBuffer + j) < 0)
420 *(lpBuffer + j) = 0;
422 return TRUE;
426 /*************************************************************************
427 * EnumFonts [GDI.70]
429 int EnumFonts(HDC hDC, LPSTR lpFaceName, FARPROC lpEnumFunc, LPSTR lpData)
431 HANDLE hLog;
432 HANDLE hMet;
433 LPLOGFONT lpLogFont;
434 LPTEXTMETRIC lptm;
435 int nRet;
436 printf("EnumFonts(%04X, %08X, %08X, %08X)\n",
437 hDC, lpFaceName, lpEnumFunc, lpData);
438 if (lpEnumFunc == NULL) return 0;
439 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
440 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
441 if (lpLogFont == NULL) {
442 printf("EnumFonts // can't alloc LOGFONT struct !\n");
443 return 0;
445 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
446 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
447 if (lptm == NULL) {
448 USER_HEAP_FREE(hLog);
449 printf("EnumFonts // can't alloc TEXTMETRIC struct !\n");
450 return 0;
452 while (TRUE) {
453 printf("EnumFonts // !\n");
454 lpLogFont->lfHeight = 18;
455 lpLogFont->lfWidth = 12;
456 lpLogFont->lfEscapement = 0;
457 lpLogFont->lfOrientation = 0;
458 lpLogFont->lfWeight = FW_REGULAR;
459 lpLogFont->lfItalic = 0;
460 lpLogFont->lfUnderline = 0;
461 lpLogFont->lfStrikeOut = 0;
462 lpLogFont->lfCharSet = ANSI_CHARSET;
463 lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
464 lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
465 lpLogFont->lfQuality = DEFAULT_QUALITY;
466 lpLogFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
467 strcpy(lpLogFont->lfFaceName, "Courier");
468 printf("lpLogFont=%08X lptm=%08X\n", lpLogFont, lptm);
469 #ifdef WINELIB
470 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
471 #else
472 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
473 2, (int)lptm, 0, (int)0, 2, (int)lpData);
474 #endif
475 if (nRet == 0) break;
476 lpLogFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
477 strcpy(lpLogFont->lfFaceName, "Helvetica");
478 printf("lpLogFont=%08X lptm=%08X\n", lpLogFont, lptm);
479 #ifdef WINELIB
480 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
481 #else
482 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
483 2, (int)lptm, 0, (int)0, 2, (int)lpData);
484 #endif
485 if (nRet == 0) break;
486 else break;
488 USER_HEAP_FREE(hMet);
489 USER_HEAP_FREE(hLog);
490 return 0;
494 /*************************************************************************
495 * EnumFontFamilies [GDI.330]
497 int EnumFontFamilies(HDC hDC, LPSTR lpszFamily, FARPROC lpEnumFunc, LPSTR lpData)
499 HANDLE hLog;
500 HANDLE hMet;
501 LPLOGFONT lpLogFont;
502 LPTEXTMETRIC lptm;
503 int nRet;
504 printf("EnumFontFamilies(%04X, %08X, %08X, %08X)\n",
505 hDC, lpszFamily, lpEnumFunc, lpData);
506 if (lpEnumFunc == NULL) return 0;
507 hLog = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(LOGFONT) + LF_FACESIZE);
508 lpLogFont = (LPLOGFONT) USER_HEAP_ADDR(hLog);
509 if (lpLogFont == NULL) {
510 printf("EnumFontFamilies // can't alloc LOGFONT struct !\n");
511 return 0;
513 hMet = USER_HEAP_ALLOC(GMEM_MOVEABLE, sizeof(TEXTMETRIC));
514 lptm = (LPTEXTMETRIC) USER_HEAP_ADDR(hMet);
515 if (lptm == NULL) {
516 USER_HEAP_FREE(hLog);
517 printf("EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
518 return 0;
520 while (TRUE) {
521 printf("EnumFontFamilies // !\n");
522 lpLogFont->lfHeight = 12;
523 lpLogFont->lfWidth = 8;
524 lpLogFont->lfEscapement = 0;
525 lpLogFont->lfOrientation = 0;
526 lpLogFont->lfWeight = FW_REGULAR;
527 lpLogFont->lfItalic = 0;
528 lpLogFont->lfUnderline = 0;
529 lpLogFont->lfStrikeOut = 0;
530 lpLogFont->lfCharSet = ANSI_CHARSET;
531 lpLogFont->lfOutPrecision = OUT_DEFAULT_PRECIS;
532 lpLogFont->lfClipPrecision = CLIP_DEFAULT_PRECIS;
533 lpLogFont->lfQuality = DEFAULT_QUALITY;
534 lpLogFont->lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
535 strcpy(lpLogFont->lfFaceName, "Courier");
536 /* lpLogFont->lfFullName[LF_FACESIZE] = 12;
537 lpLogFont->lfStyle[LF_FACESIZE] = 12; */
538 printf("lpLogFont=%08X lptm=%08X\n", lpLogFont, lptm);
539 #ifdef WINELIB
540 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
541 #else
542 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
543 2, (int)lptm, 0, (int)0, 2, (int)lpData);
544 #endif
545 if (nRet == 0) break;
546 lpLogFont->lfPitchAndFamily = VARIABLE_PITCH | FF_SWISS;
547 strcpy(lpLogFont->lfFaceName, "Helvetica");
548 printf("lpLogFont=%08X lptm=%08X\n", lpLogFont, lptm);
549 #ifdef WINELIB
550 nRet = (*lpEnumFunc)(lpLogFont, lptm, 0, lpData);
551 #else
552 nRet = CallBack16(lpEnumFunc, 4, 2, (int)lpLogFont,
553 2, (int)lptm, 0, (int)0, 2, (int)lpData);
554 #endif
555 if (nRet == 0) break;
556 else break;
558 USER_HEAP_FREE(hMet);
559 USER_HEAP_FREE(hLog);
560 return 0;