4 * Copyright 1993 Alexandre Julliard
7 static char Copyright
[] = "Copyright Alexandre Julliard, 1993";
12 #include <X11/Xatom.h>
17 /***********************************************************************
20 * Find a X font matching the logical font.
22 static XFontStruct
* FONT_MatchFont( LOGFONT
* font
)
25 char *family
, *weight
, *charset
;
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 */
51 sprintf( pattern
, "-*-%s-%s-%c-normal--*-%d-*-*-%c-*-%s",
52 family
, weight
, slant
, height
, spacing
, charset
55 sprintf( pattern
, "-*-%s-%s-%c-normal--*-%d-*-*-%c-%d-%s",
56 family
, weight
, slant
, height
, spacing
, width
, charset
60 printf( "FONT_MatchFont: '%s'\n", pattern
);
62 names
= XListFonts( XT_display
, pattern
, 1, &count
);
66 printf( " No matching font found\n" );
71 printf( " Found '%s'\n", *names
);
73 fontStruct
= XLoadQueryFont( XT_display
, *names
);
74 XFreeFontNames( names
);
79 /***********************************************************************
82 void FONT_GetMetrics( LOGFONT
* logfont
, XFontStruct
* xfont
,
83 TEXTMETRIC
* metrics
)
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
;
114 XCharStruct
* charPtr
= xfont
->per_char
;
116 for (i
= metrics
->tmFirstChar
; i
<= metrics
->tmLastChar
; i
++)
118 average
+= charPtr
->width
;
121 average
/= metrics
->tmLastChar
- metrics
->tmFirstChar
+ 1;
123 metrics
->tmAveCharWidth
= average
;
127 /***********************************************************************
128 * CreateFontIndirect (GDI.57)
130 HFONT
CreateFontIndirect( LOGFONT
* font
)
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
) );
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
,
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 /***********************************************************************
159 int FONT_GetObject( FONTOBJ
* font
, int count
, LPSTR buffer
)
161 if (count
> sizeof(LOGFONT
)) count
= sizeof(LOGFONT
);
162 memcpy( buffer
, &font
->logfont
, count
);
167 /***********************************************************************
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 */
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
];
194 if (!stockPtr
|| !stockPtr
->fstruct
)
196 fontStruct
= FONT_MatchFont( &font
->logfont
);
200 fontStruct
= stockPtr
->fstruct
;
202 printf( "FONT_SelectObject: Loaded font from cache %x %p\n",
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
);
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
) );
230 dc
->u
.x
.font
.fstruct
= fontStruct
;
231 FONT_GetMetrics( &font
->logfont
, fontStruct
, &dc
->u
.x
.font
.metrics
);
237 /***********************************************************************
238 * GetTextCharacterExtra (GDI.89)
240 short GetTextCharacterExtra( HDC hdc
)
242 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
244 return abs( (dc
->w
.charExtra
* dc
->w
.WndExtX
+ dc
->w
.VportExtX
/ 2)
249 /***********************************************************************
250 * SetTextCharacterExtra (GDI.8)
252 short SetTextCharacterExtra( HDC hdc
, short extra
)
255 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
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
);
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
;
278 dc
->w
.breakExtra
= extra
/ breaks
;
279 dc
->w
.breakRem
= extra
- (dc
->w
.breakCount
* dc
->w
.breakExtra
);
283 dc
->w
.breakExtra
= 0;
290 /***********************************************************************
291 * GetTextExtent (GDI.91)
293 DWORD
GetTextExtent( HDC hdc
, LPSTR str
, short count
)
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
;
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
);
319 printf( "GetTextExtentPoint(%d '%s' %d %p): returning %d,%d\n",
320 hdc
, str
, count
, size
, size
->cx
, size
->cy
);
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
);
352 /***********************************************************************
353 * SetMapperFlags (GDI.349)
355 DWORD
SetMapperFlags(HDC hDC
, DWORD dwFlag
)
357 printf("SetmapperFlags(%04X, %08X) // Empty Stub !\n", hDC
, dwFlag
);
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
375 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
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; \
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
)
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
;
406 if (xfont
->per_char
== NULL
)
408 for (i
= wFirstChar
, j
= 0; i
<= wLastChar
; i
++, j
++)
409 *(lpBuffer
+ j
) = xfont
->max_bounds
.width
;
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)
426 /*************************************************************************
429 int EnumFonts(HDC hDC
, LPSTR lpFaceName
, FARPROC lpEnumFunc
, LPSTR lpData
)
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");
445 hMet
= USER_HEAP_ALLOC(GMEM_MOVEABLE
, sizeof(TEXTMETRIC
));
446 lptm
= (LPTEXTMETRIC
) USER_HEAP_ADDR(hMet
);
448 USER_HEAP_FREE(hLog
);
449 printf("EnumFonts // can't alloc TEXTMETRIC struct !\n");
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
);
470 nRet
= (*lpEnumFunc
)(lpLogFont
, lptm
, 0, lpData
);
472 nRet
= CallBack16(lpEnumFunc
, 4, 2, (int)lpLogFont
,
473 2, (int)lptm
, 0, (int)0, 2, (int)lpData
);
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
);
480 nRet
= (*lpEnumFunc
)(lpLogFont
, lptm
, 0, lpData
);
482 nRet
= CallBack16(lpEnumFunc
, 4, 2, (int)lpLogFont
,
483 2, (int)lptm
, 0, (int)0, 2, (int)lpData
);
485 if (nRet
== 0) break;
488 USER_HEAP_FREE(hMet
);
489 USER_HEAP_FREE(hLog
);
494 /*************************************************************************
495 * EnumFontFamilies [GDI.330]
497 int EnumFontFamilies(HDC hDC
, LPSTR lpszFamily
, FARPROC lpEnumFunc
, LPSTR lpData
)
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");
513 hMet
= USER_HEAP_ALLOC(GMEM_MOVEABLE
, sizeof(TEXTMETRIC
));
514 lptm
= (LPTEXTMETRIC
) USER_HEAP_ADDR(hMet
);
516 USER_HEAP_FREE(hLog
);
517 printf("EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
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
);
540 nRet
= (*lpEnumFunc
)(lpLogFont
, lptm
, 0, lpData
);
542 nRet
= CallBack16(lpEnumFunc
, 4, 2, (int)lpLogFont
,
543 2, (int)lptm
, 0, (int)0, 2, (int)lpData
);
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
);
550 nRet
= (*lpEnumFunc
)(lpLogFont
, lptm
, 0, lpData
);
552 nRet
= CallBack16(lpEnumFunc
, 4, 2, (int)lpLogFont
,
553 2, (int)lptm
, 0, (int)0, 2, (int)lpData
);
555 if (nRet
== 0) break;
558 USER_HEAP_FREE(hMet
);
559 USER_HEAP_FREE(hLog
);