Release 0.3.0
[wine/multimedia.git] / objects / font.c
blobc30fcecc90f17b1c7ba54d1db7e06124dee38f12
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 <X11/Xatom.h>
12 #include "gdi.h"
14 extern Display * XT_display;
15 extern Screen * XT_screen;
18 /***********************************************************************
19 * FONT_MatchFont
21 * Find a X font matching the logical font.
23 XFontStruct * FONT_MatchFont( DC * dc, LOGFONT * font )
25 char pattern[100];
26 char *family, *weight, *charset;
27 char **names;
28 char slant, spacing;
29 int width, height, count;
30 XFontStruct * fontStruct;
32 weight = (font->lfWeight > 550) ? "bold" : "medium";
33 slant = font->lfItalic ? 'i' : 'r';
34 height = font->lfHeight * 10;
35 width = font->lfWidth * 10;
36 spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
37 (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
38 charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
39 family = font->lfFaceName;
40 if (!*family) switch(font->lfPitchAndFamily & 0xf0)
42 case FF_ROMAN: family = "times"; break;
43 case FF_SWISS: family = "helvetica"; break;
44 case FF_MODERN: family = "courier"; break;
45 case FF_SCRIPT: family = "*"; break;
46 case FF_DECORATIVE: family = "*"; break;
47 default: family = "*"; break;
50 sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
51 family, weight, slant, height, spacing, width, charset );
52 #ifdef DEBUG_FONT
53 printf( "FONT_MatchFont: '%s'\n", pattern );
54 #endif
55 names = XListFonts( XT_display, pattern, 1, &count );
56 if (!count)
58 #ifdef DEBUG_FONT
59 printf( " No matching font found\n" );
60 #endif
61 return NULL;
63 #ifdef DEBUG_FONT
64 printf( " Found '%s'\n", *names );
65 #endif
66 fontStruct = XLoadQueryFont( XT_display, *names );
67 XFreeFontNames( names );
68 return fontStruct;
72 /***********************************************************************
73 * FONT_GetMetrics
75 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
76 TEXTMETRIC * metrics )
78 int average, i;
79 unsigned long prop;
81 metrics->tmAscent = xfont->ascent;
82 metrics->tmDescent = xfont->descent;
83 metrics->tmHeight = xfont->ascent + xfont->descent;
85 metrics->tmInternalLeading = 0;
86 if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
87 metrics->tmInternalLeading = xfont->ascent - (short)prop;
88 metrics->tmExternalLeading = 0;
89 metrics->tmMaxCharWidth = xfont->max_bounds.width;
90 metrics->tmWeight = logfont->lfWeight;
91 metrics->tmItalic = logfont->lfItalic;
92 metrics->tmUnderlined = logfont->lfUnderline;
93 metrics->tmStruckOut = logfont->lfStrikeOut;
94 metrics->tmFirstChar = xfont->min_char_or_byte2;
95 metrics->tmLastChar = xfont->max_char_or_byte2;
96 metrics->tmDefaultChar = xfont->default_char;
97 metrics->tmBreakChar = ' ';
98 metrics->tmPitchAndFamily = logfont->lfPitchAndFamily;
99 metrics->tmCharSet = logfont->lfCharSet;
100 metrics->tmOverhang = 0;
101 metrics->tmDigitizedAspectX = 1;
102 metrics->tmDigitizedAspectY = 1;
104 if (xfont->per_char) average = metrics->tmMaxCharWidth;
105 else
107 XCharStruct * charPtr = xfont->per_char;
108 average = 0;
109 for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
111 average += charPtr->width;
112 charPtr++;
114 average /= metrics->tmLastChar - metrics->tmFirstChar + 1;
116 metrics->tmAveCharWidth = average;
120 /***********************************************************************
121 * CreateFontIndirect (GDI.57)
123 HFONT CreateFontIndirect( LOGFONT * font )
125 FONTOBJ * fontPtr;
126 HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
127 if (!hfont) return 0;
128 fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
129 memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
130 return hfont;
134 /***********************************************************************
135 * CreateFont (GDI.56)
137 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
138 BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
139 BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
140 LPSTR name )
142 LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
143 strikeout, charset, outpres, clippres, quality, pitch, };
144 strncpy( logfont.lfFaceName, name, LF_FACESIZE );
145 return CreateFontIndirect( &logfont );
149 /***********************************************************************
150 * FONT_GetObject
152 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
154 if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
155 memcpy( buffer, &font->logfont, count );
156 return count;
160 /***********************************************************************
161 * FONT_SelectObject
163 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
165 static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
166 X_PHYSFONT * stockPtr;
167 HFONT prevHandle = dc->w.hFont;
168 XFontStruct * fontStruct;
170 /* Load font if necessary */
172 if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
173 stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
174 else stockPtr = NULL;
176 if (!stockPtr || !stockPtr->fstruct)
178 fontStruct = FONT_MatchFont( dc, &font->logfont );
180 else
182 fontStruct = stockPtr->fstruct;
183 #ifdef DEBUG_FONT
184 printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
185 hfont, fontStruct );
186 #endif
188 if (!fontStruct) return 0;
190 /* Free previous font */
192 if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
194 if (dc->u.x.font.fstruct)
195 XFreeFont( XT_display, dc->u.x.font.fstruct );
198 /* Store font */
200 dc->w.hFont = hfont;
201 if (stockPtr)
203 if (!stockPtr->fstruct)
205 stockPtr->fstruct = fontStruct;
206 FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
208 memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
210 else
212 dc->u.x.font.fstruct = fontStruct;
213 FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
215 return prevHandle;
219 /***********************************************************************
220 * GetTextCharacterExtra (GDI.89)
222 short GetTextCharacterExtra( HDC hdc )
224 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
225 if (!dc) return 0;
226 return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
227 / dc->w.VportExtX );
231 /***********************************************************************
232 * SetTextCharacterExtra (GDI.8)
234 short SetTextCharacterExtra( HDC hdc, short extra )
236 short prev;
237 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
238 if (!dc) return 0;
239 extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;
240 prev = dc->w.charExtra;
241 dc->w.charExtra = abs(extra);
242 return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
246 /***********************************************************************
247 * SetTextJustification (GDI.10)
249 short SetTextJustification( HDC hdc, short extra, short breaks )
251 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
252 if (!dc) return 0;
254 extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
255 if (!extra) breaks = 0;
256 dc->w.breakTotalExtra = extra;
257 dc->w.breakCount = breaks;
258 if (breaks)
260 dc->w.breakExtra = extra / breaks;
261 dc->w.breakRem = extra - (dc->w.breakCount * dc->w.breakExtra);
263 else
265 dc->w.breakExtra = 0;
266 dc->w.breakRem = 0;
268 return 1;
272 /***********************************************************************
273 * GetTextExtent (GDI.91)
275 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
277 SIZE size;
278 if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
279 return size.cx | (size.cy << 16);
283 /***********************************************************************
284 * GetTextExtentPoint (GDI.471)
286 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
288 int dir, ascent, descent;
289 XCharStruct info;
291 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
292 if (!dc) return FALSE;
293 XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
294 &ascent, &descent, &info );
295 size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
296 * dc->w.WndExtX / dc->w.VportExtX);
297 size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
298 * dc->w.WndExtY / dc->w.VportExtY);
300 #ifdef DEBUG_FONT
301 printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
302 hdc, str, count, size, size->cx, size->cy );
303 #endif
304 return TRUE;
308 /***********************************************************************
309 * GetTextMetrics (GDI.93)
311 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
313 DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
314 if (!dc) return FALSE;
315 memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
317 metrics->tmAscent = abs( metrics->tmAscent
318 * dc->w.WndExtY / dc->w.VportExtY );
319 metrics->tmDescent = abs( metrics->tmDescent
320 * dc->w.WndExtY / dc->w.VportExtY );
321 metrics->tmHeight = metrics->tmAscent + metrics->tmDescent;
322 metrics->tmInternalLeading = abs( metrics->tmInternalLeading
323 * dc->w.WndExtY / dc->w.VportExtY );
324 metrics->tmExternalLeading = abs( metrics->tmExternalLeading
325 * dc->w.WndExtY / dc->w.VportExtY );
326 metrics->tmMaxCharWidth = abs( metrics->tmMaxCharWidth
327 * dc->w.WndExtX / dc->w.VportExtX );
328 metrics->tmAveCharWidth = abs( metrics->tmAveCharWidth
329 * dc->w.WndExtX / dc->w.VportExtX );
330 return TRUE;