Release 940405
[wine/multimedia.git] / objects / font.c
blob382976b22356a52d8f059b93cd682457fec75e87
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 "gdi.h"
16 /***********************************************************************
17 * FONT_MatchFont
19 * Find a X font matching the logical font.
21 static XFontStruct * FONT_MatchFont( LOGFONT * font )
23 char pattern[100];
24 char *family, *weight, *charset;
25 char **names;
26 char slant, spacing;
27 int width, height, count;
28 XFontStruct * fontStruct;
30 weight = (font->lfWeight > 550) ? "bold" : "medium";
31 slant = font->lfItalic ? 'i' : 'r';
32 height = font->lfHeight * 10;
33 width = font->lfWidth * 10;
34 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
35 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
36 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
37 family = font->lfFaceName;
38 if (!*family) switch(font->lfPitchAndFamily & 0xf0)
40 case FF_ROMAN: family = "times"; break;
41 case FF_SWISS: family = "helvetica"; break;
42 case FF_MODERN: family = "courier"; break;
43 case FF_SCRIPT: family = "*"; break;
44 case FF_DECORATIVE: family = "*"; break;
45 default: family = "*"; break;
48 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
49 if ( width == 0 )
50 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-*-%s",
51 family, weight, slant, height, spacing, charset
53 else
54 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
55 family, weight, slant, height, spacing, width, charset
58 #ifdef DEBUG_FONT
59 printf( "FONT_MatchFont: '%s'\n", pattern );
60 #endif
61 names = XListFonts( XT_display, pattern, 1, &count );
62 if (!count)
64 #ifdef DEBUG_FONT
65 printf( " No matching font found\n" );
66 #endif
67 return NULL;
69 #ifdef DEBUG_FONT
70 printf( " Found '%s'\n", *names );
71 #endif
72 fontStruct = XLoadQueryFont( XT_display, *names );
73 XFreeFontNames( names );
74 return fontStruct;
78 /***********************************************************************
79 * FONT_GetMetrics
81 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
82 TEXTMETRIC * metrics )
84 int average, i;
85 unsigned long prop;
87 metrics->tmAscent = xfont->ascent;
88 metrics->tmDescent = xfont->descent;
89 metrics->tmHeight = xfont->ascent + xfont->descent;
91 metrics->tmInternalLeading = 0;
92 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
93 metrics->tmInternalLeading = xfont->ascent - (short)prop;
94 metrics->tmExternalLeading = 0;
95 metrics->tmMaxCharWidth = xfont->max_bounds.width;
96 metrics->tmWeight = logfont->lfWeight;
97 metrics->tmItalic = logfont->lfItalic;
98 metrics->tmUnderlined = logfont->lfUnderline;
99 metrics->tmStruckOut = logfont->lfStrikeOut;
100 metrics->tmFirstChar = xfont->min_char_or_byte2;
101 metrics->tmLastChar = xfont->max_char_or_byte2;
102 metrics->tmDefaultChar = xfont->default_char;
103 metrics->tmBreakChar = ' ';
104 metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
105 metrics->tmCharSet = logfont->lfCharSet;
106 metrics->tmOverhang = 0;
107 metrics->tmDigitizedAspectX = 1;
108 metrics->tmDigitizedAspectY = 1;
110 if (xfont->per_char) average = metrics->tmMaxCharWidth;
111 else
113 XCharStruct * charPtr = xfont->per_char;
114 average = 0;
115 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
117 average += charPtr->width;
118 charPtr++;
120 average /= metrics->tmLastChar - metrics->tmFirstChar + 1;
122 metrics->tmAveCharWidth = average;
126 /***********************************************************************
127 * CreateFontIndirect (GDI.57)
129 HFONT CreateFontIndirect( LOGFONT * font )
131 FONTOBJ * fontPtr;
132 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
133 if (!hfont) return 0;
134 fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
135 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
136 return hfont;
140 /***********************************************************************
141 * CreateFont (GDI.56)
143 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
144 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
145 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
146 LPSTR name )
148 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
149 strikeout, charset, outpres, clippres, quality, pitch, };
150 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
151 return CreateFontIndirect( &logfont );
155 /***********************************************************************
156 * FONT_GetObject
158 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
160 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
161 memcpy( buffer, &font->logfont, count );
162 return count;
166 /***********************************************************************
167 * FONT_SelectObject
169 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
171 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
172 X_PHYSFONT * stockPtr;
173 HFONT prevHandle = dc->w.hFont;
174 XFontStruct * fontStruct;
176 /* Load font if necessary */
178 if (!font)
180 HFONT hnewfont;
182 hnewfont = CreateFont(10, 7, 0, 0, FW_DONTCARE,
183 FALSE, FALSE, FALSE, DEFAULT_CHARSET, 0, 0,
184 DEFAULT_QUALITY, FF_DONTCARE, "*" );
185 font = (FONTOBJ *) GDI_HEAP_ADDR( hnewfont );
188 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
189 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
190 else
191 stockPtr = NULL;
193 if (!stockPtr || !stockPtr->fstruct)
195 fontStruct = FONT_MatchFont( &font->logfont );
197 else
199 fontStruct = stockPtr->fstruct;
200 #ifdef DEBUG_FONT
201 printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
202 hfont, fontStruct );
203 #endif
205 if (!fontStruct) return 0;
207 /* Free previous font */
209 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
211 if (dc->u.x.font.fstruct)
212 XFreeFont( XT_display, dc->u.x.font.fstruct );
215 /* Store font */
217 dc->w.hFont = hfont;
218 if (stockPtr)
220 if (!stockPtr->fstruct)
222 stockPtr->fstruct = fontStruct;
223 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
225 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
227 else
229 dc->u.x.font.fstruct = fontStruct;
230 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
232 return prevHandle;
236 /***********************************************************************
237 * GetTextCharacterExtra (GDI.89)
239 short GetTextCharacterExtra( HDC hdc )
241 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
242 if (!dc) return 0;
243 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
244 / dc->w.VportExtX );
248 /***********************************************************************
249 * SetTextCharacterExtra (GDI.8)
251 short SetTextCharacterExtra( HDC hdc, short extra )
253 short prev;
254 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
255 if (!dc) return 0;
256 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
257 prev = dc->w.charExtra;
258 dc->w.charExtra = abs(extra);
259 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
263 /***********************************************************************
264 * SetTextJustification (GDI.10)
266 short SetTextJustification( HDC hdc, short extra, short breaks )
268 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
269 if (!dc) return 0;
271 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
272 if (!extra) breaks = 0;
273 dc->w.breakTotalExtra = extra;
274 dc->w.breakCount = breaks;
275 if (breaks)
277 dc->w.breakExtra = extra / breaks;
278 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
280 else
282 dc->w.breakExtra = 0;
283 dc->w.breakRem = 0;
285 return 1;
289 /***********************************************************************
290 * GetTextExtent (GDI.91)
292 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
294 SIZE size;
295 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
296 return size.cx | (size.cy << 16);
300 /***********************************************************************
301 * GetTextExtentPoint (GDI.471)
303 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
305 int dir, ascent, descent;
306 XCharStruct info;
308 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
309 if (!dc) return FALSE;
310 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
311 &ascent, &descent, &info );
312 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
313 * dc->w.WndExtX / dc->w.VportExtX);
314 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
315 * dc->w.WndExtY / dc->w.VportExtY);
317 #ifdef DEBUG_FONT
318 printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
319 hdc, str, count, size, size->cx, size->cy );
320 #endif
321 return TRUE;
325 /***********************************************************************
326 * GetTextMetrics (GDI.93)
328 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
330 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
331 if (!dc) return FALSE;
332 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
334 metrics->tmAscent = abs( metrics->tmAscent
335 * dc->w.WndExtY / dc->w.VportExtY );
336 metrics->tmDescent = abs( metrics->tmDescent
337 * dc->w.WndExtY / dc->w.VportExtY );
338 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
339 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
340 * dc->w.WndExtY / dc->w.VportExtY );
341 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
342 * dc->w.WndExtY / dc->w.VportExtY );
343 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
344 * dc->w.WndExtX / dc->w.VportExtX );
345 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
346 * dc->w.WndExtX / dc->w.VportExtX );
347 return TRUE;
351 /***********************************************************************/
353 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
354 (((cs)->rbearing|(cs)->lbearing| \
355 (cs)->ascent|(cs)->descent) == 0))
358 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
359 * character. If the character is in the column and exists, then return the
360 * appropriate metrics (note that fonts with common per-character metrics will
361 * return min_bounds). If none of these hold true, try again with the default
362 * char.
364 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
366 cs = def; \
367 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
368 if (fs->per_char == NULL) { \
369 cs = &fs->min_bounds; \
370 } else { \
371 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
372 if (CI_NONEXISTCHAR(cs)) cs = def; \
377 #define CI_GET_DEFAULT_INFO(fs,cs) \
378 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
381 /***********************************************************************
382 * SetMapperFlags (GDI.349)
384 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
386 printf("SetmapperFlags(%04X, %08X) // Empty Stub !\n", hDC, dwFlag);
387 return 0L;
391 /***********************************************************************
392 * GetCharWidth (GDI.350)
394 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
396 int i, j;
397 XFontStruct *xfont;
398 XCharStruct *cs, *def;
400 DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
401 if (!dc) return FALSE;
402 xfont = dc->u.x.font.fstruct;
404 /* fixed font? */
405 if (xfont->per_char == NULL)
407 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
408 *(lpBuffer + j) = xfont->max_bounds.width;
409 return TRUE;
412 CI_GET_DEFAULT_INFO(xfont, def);
414 for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
416 CI_GET_CHAR_INFO(xfont, i, def, cs);
417 *(lpBuffer + j) = cs->width;
419 return TRUE;