Release 940301
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  */
6
7 static char Copyright[] = "Copyright  Alexandre Julliard, 1993";
8
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <X11/Xatom.h>
12 #include "gdi.h"
13
14
15 /***********************************************************************
16  *           FONT_MatchFont
17  *
18  * Find a X font matching the logical font.
19  */
20 XFontStruct * FONT_MatchFont( DC * dc, LOGFONT * font )
21 {
22     char pattern[100];
23     char *family, *weight, *charset;
24     char **names;
25     char slant, spacing;
26     int width, height, count;
27     XFontStruct * fontStruct;
28     
29     weight = (font->lfWeight > 550) ? "bold" : "medium";
30     slant = font->lfItalic ? 'i' : 'r';
31     height = font->lfHeight * 10;
32     width = font->lfWidth * 10;
33     spacing = (font->lfPitchAndFamily & FIXED_PITCH) ? 'm' :
34               (font->lfPitchAndFamily & VARIABLE_PITCH) ? 'p' : '*';
35     charset = (font->lfCharSet == ANSI_CHARSET) ? "iso8859-1" : "*";
36     family = font->lfFaceName;
37     if (!*family) switch(font->lfPitchAndFamily & 0xf0)
38     {
39       case FF_ROMAN:      family = "times"; break;
40       case FF_SWISS:      family = "helvetica"; break;
41       case FF_MODERN:     family = "courier"; break;
42       case FF_SCRIPT:     family = "*"; break;
43       case FF_DECORATIVE: family = "*"; break;
44       default:            family = "*"; break;
45     }
46     
47     sprintf( pattern, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
48             family, weight, slant, height, spacing, width, charset );
49 #ifdef DEBUG_FONT
50     printf( "FONT_MatchFont: '%s'\n", pattern );
51 #endif
52     names = XListFonts( XT_display, pattern, 1, &count );
53     if (!count)
54     {
55 #ifdef DEBUG_FONT
56         printf( "        No matching font found\n" );   
57 #endif
58         return NULL;
59     }
60 #ifdef DEBUG_FONT
61     printf( "        Found '%s'\n", *names );
62 #endif
63     fontStruct = XLoadQueryFont( XT_display, *names );
64     XFreeFontNames( names );
65     return fontStruct;
66 }
67
68
69 /***********************************************************************
70  *           FONT_GetMetrics
71  */
72 void FONT_GetMetrics( LOGFONT * logfont, XFontStruct * xfont,
73                       TEXTMETRIC * metrics )
74 {    
75     int average, i;
76     unsigned long prop;
77         
78     metrics->tmAscent  = xfont->ascent;
79     metrics->tmDescent = xfont->descent;
80     metrics->tmHeight  = xfont->ascent + xfont->descent;
81
82     metrics->tmInternalLeading  = 0;
83     if (XGetFontProperty( xfont, XA_X_HEIGHT, &prop ))
84         metrics->tmInternalLeading = xfont->ascent - (short)prop;
85     metrics->tmExternalLeading  = 0;
86     metrics->tmMaxCharWidth     = xfont->max_bounds.width;
87     metrics->tmWeight           = logfont->lfWeight;
88     metrics->tmItalic           = logfont->lfItalic;
89     metrics->tmUnderlined       = logfont->lfUnderline;
90     metrics->tmStruckOut        = logfont->lfStrikeOut;
91     metrics->tmFirstChar        = xfont->min_char_or_byte2;
92     metrics->tmLastChar         = xfont->max_char_or_byte2;
93     metrics->tmDefaultChar      = xfont->default_char;
94     metrics->tmBreakChar        = ' ';
95     metrics->tmPitchAndFamily   = logfont->lfPitchAndFamily;
96     metrics->tmCharSet          = logfont->lfCharSet;
97     metrics->tmOverhang         = 0;
98     metrics->tmDigitizedAspectX = 1;
99     metrics->tmDigitizedAspectY = 1;
100
101     if (xfont->per_char) average = metrics->tmMaxCharWidth;
102     else
103     {
104         XCharStruct * charPtr = xfont->per_char;
105         average = 0;
106         for (i = metrics->tmFirstChar; i <= metrics->tmLastChar; i++)
107         {
108             average += charPtr->width;
109             charPtr++;
110         }
111         average /= metrics->tmLastChar - metrics->tmFirstChar + 1;
112     }
113     metrics->tmAveCharWidth = average;
114 }
115
116
117 /***********************************************************************
118  *           CreateFontIndirect    (GDI.57)
119  */
120 HFONT CreateFontIndirect( LOGFONT * font )
121 {
122     FONTOBJ * fontPtr;
123     HFONT hfont = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC );
124     if (!hfont) return 0;
125     fontPtr = (FONTOBJ *) GDI_HEAP_ADDR( hfont );
126     memcpy( &fontPtr->logfont, font, sizeof(LOGFONT) );
127     return hfont;
128 }
129
130
131 /***********************************************************************
132  *           CreateFont    (GDI.56)
133  */
134 HFONT CreateFont( int height, int width, int esc, int orient, int weight,
135                   BYTE italic, BYTE underline, BYTE strikeout, BYTE charset,
136                   BYTE outpres, BYTE clippres, BYTE quality, BYTE pitch,
137                   LPSTR name )
138 {
139     LOGFONT logfont = { height, width, esc, orient, weight, italic, underline,
140                     strikeout, charset, outpres, clippres, quality, pitch, };
141     strncpy( logfont.lfFaceName, name, LF_FACESIZE );
142     return CreateFontIndirect( &logfont );
143 }
144
145
146 /***********************************************************************
147  *           FONT_GetObject
148  */
149 int FONT_GetObject( FONTOBJ * font, int count, LPSTR buffer )
150 {
151     if (count > sizeof(LOGFONT)) count = sizeof(LOGFONT);
152     memcpy( buffer, &font->logfont, count );
153     return count;
154 }
155
156
157 /***********************************************************************
158  *           FONT_SelectObject
159  */
160 HFONT FONT_SelectObject( DC * dc, HFONT hfont, FONTOBJ * font )
161 {
162     static X_PHYSFONT stockFonts[LAST_STOCK_FONT-FIRST_STOCK_FONT+1];
163     X_PHYSFONT * stockPtr;
164     HFONT prevHandle = dc->w.hFont;
165     XFontStruct * fontStruct;
166
167       /* Load font if necessary */
168
169     if ((hfont >= FIRST_STOCK_FONT) && (hfont <= LAST_STOCK_FONT))
170         stockPtr = &stockFonts[hfont - FIRST_STOCK_FONT];
171     else stockPtr = NULL;
172     
173     if (!stockPtr || !stockPtr->fstruct)
174     {
175         fontStruct = FONT_MatchFont( dc, &font->logfont );
176     }
177     else
178     {
179         fontStruct = stockPtr->fstruct;
180 #ifdef DEBUG_FONT
181         printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
182                 hfont, fontStruct );
183 #endif
184     }   
185     if (!fontStruct) return 0;
186
187       /* Free previous font */
188
189     if ((prevHandle < FIRST_STOCK_FONT) || (prevHandle > LAST_STOCK_FONT))
190     {
191         if (dc->u.x.font.fstruct)
192             XFreeFont( XT_display, dc->u.x.font.fstruct );
193     }
194
195       /* Store font */
196
197     dc->w.hFont = hfont;
198     if (stockPtr)
199     {
200         if (!stockPtr->fstruct)
201         {
202             stockPtr->fstruct = fontStruct;
203             FONT_GetMetrics( &font->logfont, fontStruct, &stockPtr->metrics );
204         }
205         memcpy( &dc->u.x.font, stockPtr, sizeof(*stockPtr) );
206     }
207     else
208     {
209         dc->u.x.font.fstruct = fontStruct;
210         FONT_GetMetrics( &font->logfont, fontStruct, &dc->u.x.font.metrics );
211     }
212     return prevHandle;
213 }
214
215
216 /***********************************************************************
217  *           GetTextCharacterExtra    (GDI.89)
218  */
219 short GetTextCharacterExtra( HDC hdc )
220 {
221     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
222     if (!dc) return 0;
223     return abs( (dc->w.charExtra * dc->w.WndExtX + dc->w.VportExtX / 2)
224                  / dc->w.VportExtX );
225 }
226
227
228 /***********************************************************************
229  *           SetTextCharacterExtra    (GDI.8)
230  */
231 short SetTextCharacterExtra( HDC hdc, short extra )
232 {
233     short prev;
234     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
235     if (!dc) return 0;
236     extra = (extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX;    
237     prev = dc->w.charExtra;
238     dc->w.charExtra = abs(extra);
239     return (prev * dc->w.WndExtX + dc->w.VportExtX / 2) / dc->w.VportExtX;
240 }
241
242
243 /***********************************************************************
244  *           SetTextJustification    (GDI.10)
245  */
246 short SetTextJustification( HDC hdc, short extra, short breaks )
247 {
248     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
249     if (!dc) return 0;
250
251     extra = abs((extra * dc->w.VportExtX + dc->w.WndExtX / 2) / dc->w.WndExtX);
252     if (!extra) breaks = 0;
253     dc->w.breakTotalExtra = extra;
254     dc->w.breakCount = breaks;
255     if (breaks)
256     {   
257         dc->w.breakExtra = extra / breaks;
258         dc->w.breakRem   = extra - (dc->w.breakCount * dc->w.breakExtra);
259     }
260     else
261     {
262         dc->w.breakExtra = 0;
263         dc->w.breakRem   = 0;
264     }
265     return 1;
266 }
267
268
269 /***********************************************************************
270  *           GetTextExtent    (GDI.91)
271  */
272 DWORD GetTextExtent( HDC hdc, LPSTR str, short count )
273 {
274     SIZE size;
275     if (!GetTextExtentPoint( hdc, str, count, &size )) return 0;
276     return size.cx | (size.cy << 16);
277 }
278
279
280 /***********************************************************************
281  *           GetTextExtentPoint    (GDI.471)
282  */
283 BOOL GetTextExtentPoint( HDC hdc, LPSTR str, short count, LPSIZE size )
284 {
285     int dir, ascent, descent;
286     XCharStruct info;
287
288     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
289     if (!dc) return FALSE;
290     XTextExtents( dc->u.x.font.fstruct, str, count, &dir,
291                   &ascent, &descent, &info );
292     size->cx = abs((info.width + dc->w.breakRem + count * dc->w.charExtra)
293                     * dc->w.WndExtX / dc->w.VportExtX);
294     size->cy = abs((dc->u.x.font.fstruct->ascent+dc->u.x.font.fstruct->descent)
295                     * dc->w.WndExtY / dc->w.VportExtY);
296
297 #ifdef DEBUG_FONT
298     printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
299             hdc, str, count, size, size->cx, size->cy );
300 #endif
301     return TRUE;
302 }
303
304
305 /***********************************************************************
306  *           GetTextMetrics    (GDI.93)
307  */
308 BOOL GetTextMetrics( HDC hdc, LPTEXTMETRIC metrics )
309 {
310     DC * dc = (DC *) GDI_GetObjPtr( hdc, DC_MAGIC );
311     if (!dc) return FALSE;
312     memcpy( metrics, &dc->u.x.font.metrics, sizeof(*metrics) );
313
314     metrics->tmAscent  = abs( metrics->tmAscent
315                               * dc->w.WndExtY / dc->w.VportExtY );
316     metrics->tmDescent = abs( metrics->tmDescent
317                               * dc->w.WndExtY / dc->w.VportExtY );
318     metrics->tmHeight  = metrics->tmAscent + metrics->tmDescent;
319     metrics->tmInternalLeading = abs( metrics->tmInternalLeading
320                                       * dc->w.WndExtY / dc->w.VportExtY );
321     metrics->tmExternalLeading = abs( metrics->tmExternalLeading
322                                       * dc->w.WndExtY / dc->w.VportExtY );
323     metrics->tmMaxCharWidth    = abs( metrics->tmMaxCharWidth 
324                                       * dc->w.WndExtX / dc->w.VportExtX );
325     metrics->tmAveCharWidth    = abs( metrics->tmAveCharWidth
326                                       * dc->w.WndExtX / dc->w.VportExtX );
327     return TRUE;
328 }
329
330
331 /***********************************************************************/
332
333 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
334                              (((cs)->rbearing|(cs)->lbearing| \
335                                (cs)->ascent|(cs)->descent) == 0))
336
337 /* 
338  * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
339  * character.  If the character is in the column and exists, then return the
340  * appropriate metrics (note that fonts with common per-character metrics will
341  * return min_bounds).  If none of these hold true, try again with the default
342  * char.
343  */
344 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
345 { \
346     cs = def; \
347     if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
348         if (fs->per_char == NULL) { \
349             cs = &fs->min_bounds; \
350         } else { \
351             cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
352             if (CI_NONEXISTCHAR(cs)) cs = def; \
353         } \
354     } \
355 }
356
357 #define CI_GET_DEFAULT_INFO(fs,cs) \
358   CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
359
360
361 /***********************************************************************
362  *           SetMapperFlags    (GDI.349)
363  */
364 DWORD SetMapperFlags(HDC hDC, DWORD dwFlag)
365 {
366     printf("SetmapperFlags(%04X, %08X) // Empty Stub !\n", hDC, dwFlag); 
367     return 0L;
368 }
369
370  
371 /***********************************************************************
372  *           GetCharWidth    (GDI.350)
373  */
374 BOOL GetCharWidth(HDC hdc, WORD wFirstChar, WORD wLastChar, LPINT lpBuffer)
375 {
376     int i, j;
377     XFontStruct *xfont;
378     XCharStruct *cs, *def;
379
380     DC *dc = (DC *)GDI_GetObjPtr(hdc, DC_MAGIC);
381     if (!dc) return FALSE;
382     xfont = dc->u.x.font.fstruct;
383     
384     /* fixed font? */
385     if (xfont->per_char == NULL)
386     {
387         for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
388             *(lpBuffer + j) = xfont->max_bounds.width;
389         return TRUE;
390     }
391
392     CI_GET_DEFAULT_INFO(xfont, def);
393         
394     for (i = wFirstChar, j = 0; i <= wLastChar; i++, j++)
395     {
396         CI_GET_CHAR_INFO(xfont, i, def, cs);
397         *(lpBuffer + j) = cs->width;
398     }
399     return TRUE;
400 }