4 * Copyright 1993 Alexandre Julliard
6 * Enhacements by Juergen Marquardt 1996
8 * Implementation of a second font cache which
9 * will be updated dynamically
15 #include <X11/Xatom.h>
24 #define FONTCACHE 32 /* dynamic font cache size */
26 static LPLOGFONT16 lpLogFontList
[MAX_FONTS
+1];
28 static int ParseFontParms(LPSTR lpFont
, WORD wParmsNo
, LPSTR lpRetStr
, WORD wMaxSiz
);
30 #define CI_NONEXISTCHAR(cs) (((cs)->width == 0) && \
31 (((cs)->rbearing|(cs)->lbearing| \
32 (cs)->ascent|(cs)->descent) == 0))
35 * CI_GET_CHAR_INFO - return the charinfo struct for the indicated 8bit
36 * character. If the character is in the column and exists, then return the
37 * appropriate metrics (note that fonts with common per-character metrics will
38 * return min_bounds). If none of these hold true, try again with the default
41 #define CI_GET_CHAR_INFO(fs,col,def,cs) \
44 if (col >= fs->min_char_or_byte2 && col <= fs->max_char_or_byte2) { \
45 if (fs->per_char == NULL) { \
46 cs = &fs->min_bounds; \
48 cs = &fs->per_char[(col - fs->min_char_or_byte2)]; \
49 if (CI_NONEXISTCHAR(cs)) cs = def; \
54 #define CI_GET_DEFAULT_INFO(fs,cs) \
55 CI_GET_CHAR_INFO(fs, fs->default_char, NULL, cs)
57 struct FontStructure
{
64 /***********************************************************************
67 BOOL32
FONT_Init( void )
73 if (PROFILE_GetWineIniString( "fonts", NULL
, "*", temp
, sizeof(temp
) ) > 2 )
75 for( ptr
= temp
, i
= 1; strlen(ptr
) != 0; ptr
+= strlen(ptr
) + 1 )
76 if( strcmp( ptr
, "default" ) )
77 FontNames
[i
++].window
= xstrdup( ptr
);
80 for( i
= 1; i
< FontSize
; i
++ )
82 PROFILE_GetWineIniString( "fonts", FontNames
[i
].window
, "*",
84 FontNames
[i
].x11
= xstrdup( temp
);
86 PROFILE_GetWineIniString( "fonts", "default", "*", temp
, sizeof(temp
) );
87 FontNames
[0].x11
= xstrdup( temp
);
90 FontNames
[0].window
= NULL
; FontNames
[0].x11
= "*-helvetica";
91 FontNames
[1].window
= "ms sans serif"; FontNames
[1].x11
= "*-helvetica";
92 FontNames
[2].window
= "ms serif"; FontNames
[2].x11
= "*-times";
93 FontNames
[3].window
= "fixedsys"; FontNames
[3].x11
= "*-fixed";
94 FontNames
[4].window
= "arial"; FontNames
[4].x11
= "*-helvetica";
95 FontNames
[5].window
= "helv"; FontNames
[5].x11
= "*-helvetica";
96 FontNames
[6].window
= "roman"; FontNames
[6].x11
= "*-times";
102 /***********************************************************************
105 * returns a valid X11 equivalent if a Windows face name
106 * is like a X11 family - or NULL if translation is needed
108 static char *FONT_ChkX11Family(char *winFaceName
)
110 static char x11fam
[32+2]; /* will be returned */
113 for(i
= 0; lpLogFontList
[i
] != NULL
; i
++)
114 if( !lstrcmpi32A(winFaceName
, lpLogFontList
[i
]->lfFaceName
) )
117 return strcat(x11fam
,winFaceName
);
119 return NULL
; /* a FONT_TranslateName() call is needed */
124 /***********************************************************************
127 * Translate a Windows face name to its X11 equivalent.
128 * This will probably have to be customizable.
130 static const char *FONT_TranslateName( char *winFaceName
)
134 for (i
= 1; i
< FontSize
; i
++)
135 if( !strcmp( winFaceName
, FontNames
[i
].window
) ) {
136 dprintf_font(stddeb
, "---- Mapped %s to %s\n", winFaceName
, FontNames
[i
].x11
);
137 return FontNames
[i
].x11
;
139 return FontNames
[0].x11
;
143 /***********************************************************************
146 * Find a X font matching the logical font.
148 static XFontStruct
* FONT_MatchFont( LOGFONT16
* font
, DC
* dc
)
151 const char *family
, *weight
, *charset
;
153 char slant
, oldspacing
, spacing
;
154 int width
, height
, oldheight
, count
;
155 XFontStruct
* fontStruct
;
158 "FONT_MatchFont(H,W = %d,%d; Weight = %d; Italic = %d; FaceName = '%s'\n",
159 font
->lfHeight
, font
->lfWidth
, font
->lfWeight
, font
->lfItalic
, font
->lfFaceName
);
160 weight
= (font
->lfWeight
> 550) ? "bold" : "medium";
161 slant
= font
->lfItalic
? 'i' : 'r';
162 if (font
->lfHeight
== -1)
165 height
= font
->lfHeight
* dc
->w
.VportExtX
/ dc
->w
.WndExtX
;
166 if (height
== 0) height
= 120; /* Default height = 12 */
169 /* If height is negative, it means the height of the characters */
170 /* *without* the internal leading. So we adjust it a bit to */
171 /* compensate. 5/4 seems to give good results for small fonts. */
173 * J.M.: This causes wrong font size for bigger fonts e.g. in Winword & Write
174 height = 10 * (-height * 9 / 8);
175 * may be we have to use an non linear function
177 /* assume internal leading is 2 pixels. Else small fonts will become
179 height
= (height
-2) * -10;
182 width
= 10 * (font
->lfWidth
* dc
->w
.VportExtY
/ dc
->w
.WndExtY
);
184 dprintf_font( stddeb
, "FONT_MatchFont: negative width %d(%d)\n",
185 width
, font
->lfWidth
);
189 spacing
= (font
->lfPitchAndFamily
& FIXED_PITCH
) ? 'm' :
190 (font
->lfPitchAndFamily
& VARIABLE_PITCH
) ? 'p' : '*';
193 charset
= (font
->lfCharSet
== ANSI_CHARSET
) ? "iso8859-1" : "*-*";
194 if (*font
->lfFaceName
) {
195 family
= FONT_ChkX11Family(font
->lfFaceName
);
196 /*--do _not_ translate if lfFaceName is family from X11 A.K.*/
198 family
= FONT_TranslateName( font
->lfFaceName
);
199 /* FIX ME: I don't if that's correct but it works J.M. */
202 else switch(font
->lfPitchAndFamily
& 0xf0)
205 family
= FONT_TranslateName( "roman" );
208 family
= FONT_TranslateName( "swiss" );
211 family
= FONT_TranslateName( "modern" );
214 family
= FONT_TranslateName( "script" );
217 family
= FONT_TranslateName( "decorative" );
224 oldspacing
= spacing
;
226 /* Width==0 seems not to be a valid wildcard on SGI's, using * instead */
228 sprintf( pattern
, "-%s-%s-%c-normal-*-*-%d-*-*-%c-*-%s",
229 family
, weight
, slant
, height
, spacing
, charset
);
231 sprintf( pattern
, "-%s-%s-%c-normal-*-*-%d-*-*-%c-%d-%s",
232 family
, weight
, slant
, height
, spacing
, width
, charset
);
233 dprintf_font(stddeb
, "FONT_MatchFont: '%s'\n", pattern
);
234 names
= XListFonts( display
, pattern
, 1, &count
);
235 if (count
> 0) break;
236 if (spacing
== 'm') /* try 'c' if no 'm' found */ {
240 } else if (spacing
== 'p') /* try '*' if no 'p' found */ {
244 spacing
= oldspacing
;
248 /* try oblique if no italic font */
253 if (spacing
== 'm' && strcmp(family
, "*-*") != 0) {
254 /* If a fixed spacing font could not be found, ignore
260 fprintf(stderr
, "FONT_MatchFont(%s) : returning NULL\n", pattern
);
264 dprintf_font(stddeb
," Found '%s'\n", *names
);
265 if (!*font
->lfFaceName
)
266 ParseFontParms(*names
, 2, font
->lfFaceName
, LF_FACESIZE
-1);
267 /* we need a font name for function GetTextFace() even if there isn't one ;-) */
268 AnsiUpper(font
->lfFaceName
);
270 fontStruct
= XLoadQueryFont( display
, *names
);
271 XFreeFontNames( names
);
276 /***********************************************************************
279 void FONT_GetMetrics( LOGFONT16
* logfont
, XFontStruct
* xfont
,
280 TEXTMETRIC16
* metrics
)
282 int average
, i
, count
;
285 metrics
->tmAscent
= xfont
->ascent
;
286 metrics
->tmDescent
= xfont
->descent
;
287 metrics
->tmHeight
= xfont
->ascent
+ xfont
->descent
;
289 metrics
->tmInternalLeading
= 0;
290 if (XGetFontProperty( xfont
, XA_CAP_HEIGHT
, &prop
))
291 metrics
->tmInternalLeading
= xfont
->ascent
+xfont
->descent
-(INT16
)prop
;
293 metrics
->tmExternalLeading
= 0;
294 metrics
->tmMaxCharWidth
= xfont
->max_bounds
.width
;
295 metrics
->tmWeight
= logfont
->lfWeight
;
296 metrics
->tmItalic
= logfont
->lfItalic
;
297 metrics
->tmUnderlined
= logfont
->lfUnderline
;
298 metrics
->tmStruckOut
= logfont
->lfStrikeOut
;
299 metrics
->tmFirstChar
= xfont
->min_char_or_byte2
;
300 metrics
->tmLastChar
= xfont
->max_char_or_byte2
;
301 metrics
->tmDefaultChar
= xfont
->default_char
;
302 metrics
->tmBreakChar
= ' ';
303 metrics
->tmCharSet
= logfont
->lfCharSet
;
304 metrics
->tmOverhang
= 0;
305 metrics
->tmDigitizedAspectX
= 1;
306 metrics
->tmDigitizedAspectY
= 1;
307 metrics
->tmPitchAndFamily
= (logfont
->lfPitchAndFamily
&0xf0)|TMPF_DEVICE
;
308 if (logfont
->lfPitchAndFamily
& FIXED_PITCH
)
309 metrics
->tmPitchAndFamily
|= TMPF_FIXED_PITCH
;
311 if (!xfont
->per_char
) average
= metrics
->tmMaxCharWidth
;
314 XCharStruct
* charPtr
= xfont
->per_char
;
316 for (i
= metrics
->tmFirstChar
; i
<= metrics
->tmLastChar
; i
++)
318 if (!CI_NONEXISTCHAR( charPtr
))
320 average
+= charPtr
->width
;
325 if (count
) average
= (average
+ count
/2) / count
;
327 metrics
->tmAveCharWidth
= average
;
330 /***********************************************************************
331 * GetGlyphOutLine (GDI.309)
333 DWORD
GetGlyphOutLine(HDC hdc
, UINT uChar
, UINT fuFormat
, LPGLYPHMETRICS lpgm
,
334 DWORD cbBuffer
, LPSTR lpBuffer
, LPMAT2 lpmat2
)
336 fprintf( stdnimp
,"GetGlyphOutLine(%04x, '%c', %04x, %p, %ld, %p, %p) // - empty stub!\n",
337 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
338 return (DWORD
)-1; /* failure */
342 /***********************************************************************
343 * CreateScalableFontResource (GDI.310)
345 BOOL
CreateScalableFontResource( UINT fHidden
,LPSTR lpszResourceFile
,
346 LPSTR lpszFontFile
, LPSTR lpszCurrentPath
)
348 /* fHidden=1 - only visible for the calling app, read-only, not
349 * enumbered with EnumFonts/EnumFontFamilies
350 * lpszCurrentPath can be NULL
352 fprintf(stdnimp
,"CreateScalableFontResource(%d,%s,%s,%s) // empty stub!\n",
353 fHidden
, lpszResourceFile
, lpszFontFile
, lpszCurrentPath
);
354 return FALSE
; /* create failed */
358 /***********************************************************************
359 * CreateFontIndirect16 (GDI.57)
361 HFONT16
CreateFontIndirect16( const LOGFONT16
*font
)
368 fprintf(stderr
,"CreateFontIndirect: font is NULL : returning NULL\n");
371 hfont
= GDI_AllocObject( sizeof(FONTOBJ
), FONT_MAGIC
);
372 if (!hfont
) return 0;
373 fontPtr
= (FONTOBJ
*) GDI_HEAP_LIN_ADDR( hfont
);
374 memcpy( &fontPtr
->logfont
, font
, sizeof(LOGFONT16
) );
375 AnsiLower( fontPtr
->logfont
.lfFaceName
);
376 dprintf_font(stddeb
,"CreateFontIndirect(%p (%d,%d)); return %04x\n",
377 font
, font
->lfHeight
, font
->lfWidth
, hfont
);
382 /***********************************************************************
383 * CreateFontIndirect32A (GDI32.44)
385 HFONT32
CreateFontIndirect32A( const LOGFONT32A
*font
)
389 font16
.lfHeight
= (INT16
)font
->lfHeight
;
390 font16
.lfWidth
= (INT16
)font
->lfWidth
;
391 font16
.lfEscapement
= (INT16
)font
->lfEscapement
;
392 font16
.lfOrientation
= (INT16
)font
->lfOrientation
;
393 font16
.lfWeight
= (INT16
)font
->lfWeight
;
394 font16
.lfItalic
= font
->lfItalic
;
395 font16
.lfUnderline
= font
->lfUnderline
;
396 font16
.lfStrikeOut
= font
->lfStrikeOut
;
397 font16
.lfCharSet
= font
->lfCharSet
;
398 font16
.lfOutPrecision
= font
->lfOutPrecision
;
399 font16
.lfClipPrecision
= font
->lfClipPrecision
;
400 font16
.lfQuality
= font
->lfQuality
;
401 font16
.lfPitchAndFamily
= font
->lfPitchAndFamily
;
402 lstrcpyn32A( font16
.lfFaceName
, font
->lfFaceName
, LF_FACESIZE
);
403 return CreateFontIndirect16( &font16
);
407 /***********************************************************************
408 * CreateFontIndirect32W (GDI32.45)
410 HFONT32
CreateFontIndirect32W( const LOGFONT32W
*font
)
414 font16
.lfHeight
= (INT16
)font
->lfHeight
;
415 font16
.lfWidth
= (INT16
)font
->lfWidth
;
416 font16
.lfEscapement
= (INT16
)font
->lfEscapement
;
417 font16
.lfOrientation
= (INT16
)font
->lfOrientation
;
418 font16
.lfWeight
= (INT16
)font
->lfWeight
;
419 font16
.lfItalic
= font
->lfItalic
;
420 font16
.lfUnderline
= font
->lfUnderline
;
421 font16
.lfStrikeOut
= font
->lfStrikeOut
;
422 font16
.lfCharSet
= font
->lfCharSet
;
423 font16
.lfOutPrecision
= font
->lfOutPrecision
;
424 font16
.lfClipPrecision
= font
->lfClipPrecision
;
425 font16
.lfQuality
= font
->lfQuality
;
426 font16
.lfPitchAndFamily
= font
->lfPitchAndFamily
;
427 lstrcpynWtoA( font16
.lfFaceName
, font
->lfFaceName
, LF_FACESIZE
);
428 return CreateFontIndirect16( &font16
);
432 /***********************************************************************
433 * CreateFont16 (GDI.56)
435 HFONT16
CreateFont16( INT16 height
, INT16 width
, INT16 esc
, INT16 orient
,
436 INT16 weight
, BYTE italic
, BYTE underline
,
437 BYTE strikeout
, BYTE charset
, BYTE outpres
,
438 BYTE clippres
, BYTE quality
, BYTE pitch
, LPCSTR name
)
440 LOGFONT16 logfont
= {height
, width
, esc
, orient
, weight
, italic
, underline
,
441 strikeout
, charset
, outpres
, clippres
, quality
, pitch
, };
442 dprintf_font(stddeb
,"CreateFont16(%d,%d)\n", height
, width
);
443 if (name
) lstrcpyn32A(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
444 else logfont
.lfFaceName
[0] = '\0';
445 return CreateFontIndirect16( &logfont
);
450 /*************************************************************************
451 * CreateFont32A (GDI32.43)
453 HFONT32
CreateFont32A( INT32 height
, INT32 width
, INT32 esc
, INT32 orient
,
454 INT32 weight
, DWORD italic
, DWORD underline
,
455 DWORD strikeout
, DWORD charset
, DWORD outpres
,
456 DWORD clippres
, DWORD quality
, DWORD pitch
, LPCSTR name
)
458 return (HFONT32
)CreateFont16( height
, width
, esc
, orient
, weight
, italic
,
459 underline
, strikeout
, charset
, outpres
,
460 clippres
, quality
, pitch
, name
);
464 /*************************************************************************
465 * CreateFont32W (GDI32.46)
467 HFONT32
CreateFont32W( INT32 height
, INT32 width
, INT32 esc
, INT32 orient
,
468 INT32 weight
, DWORD italic
, DWORD underline
,
469 DWORD strikeout
, DWORD charset
, DWORD outpres
,
470 DWORD clippres
, DWORD quality
, DWORD pitch
,
473 LPSTR namea
= name
? STRING32_DupUniToAnsi(name
) : NULL
;
474 HFONT32 ret
= (HFONT32
)CreateFont16( height
, width
, esc
, orient
, weight
,
475 italic
, underline
, strikeout
, charset
,
476 outpres
, clippres
, quality
, pitch
,
483 /***********************************************************************
486 INT16
FONT_GetObject16( FONTOBJ
* font
, INT16 count
, LPSTR buffer
)
488 if (count
> sizeof(LOGFONT16
)) count
= sizeof(LOGFONT16
);
489 memcpy( buffer
, &font
->logfont
, count
);
494 /***********************************************************************
497 INT32
FONT_GetObject32A( FONTOBJ
*font
, INT32 count
, LPSTR buffer
)
501 memset(&fnt32
, 0, sizeof(fnt32
));
502 fnt32
.lfHeight
= font
->logfont
.lfHeight
;
503 fnt32
.lfWidth
= font
->logfont
.lfWidth
;
504 fnt32
.lfEscapement
= font
->logfont
.lfEscapement
;
505 fnt32
.lfOrientation
= font
->logfont
.lfOrientation
;
506 fnt32
.lfWeight
= font
->logfont
.lfWeight
;
507 fnt32
.lfItalic
= font
->logfont
.lfItalic
;
508 fnt32
.lfUnderline
= font
->logfont
.lfUnderline
;
509 fnt32
.lfStrikeOut
= font
->logfont
.lfStrikeOut
;
510 fnt32
.lfCharSet
= font
->logfont
.lfCharSet
;
511 fnt32
.lfOutPrecision
= font
->logfont
.lfOutPrecision
;
512 fnt32
.lfClipPrecision
= font
->logfont
.lfClipPrecision
;
513 fnt32
.lfQuality
= font
->logfont
.lfQuality
;
514 fnt32
.lfPitchAndFamily
= font
->logfont
.lfPitchAndFamily
;
515 strncpy( fnt32
.lfFaceName
, font
->logfont
.lfFaceName
,
516 sizeof(fnt32
.lfFaceName
) );
518 if (count
> sizeof(fnt32
)) count
= sizeof(fnt32
);
519 memcpy( buffer
, &fnt32
, count
);
524 /***********************************************************************
527 HFONT16
FONT_SelectObject( DC
* dc
, HFONT16 hfont
, FONTOBJ
* font
)
529 static X_PHYSFONT stockFonts
[LAST_STOCK_FONT
-FIRST_STOCK_FONT
+1];
536 X_PHYSFONT cacheFont
; } cacheFonts
[FONTCACHE
], *cacheFontsMin
;
539 X_PHYSFONT
* stockPtr
;
540 HFONT prevHandle
= dc
->w
.hFont
;
541 XFontStruct
* fontStruct
;
542 dprintf_font(stddeb
,"FONT_SelectObject(%p, %04x, %p)\n", dc
, hfont
, font
);
544 #if 0 /* From the code in SelectObject, this can not happen */
545 /* Load font if necessary */
550 hnewfont
= CreateFont16(10, 7, 0, 0, FW_DONTCARE
,
551 FALSE
, FALSE
, FALSE
, DEFAULT_CHARSET
, 0, 0,
552 DEFAULT_QUALITY
, FF_DONTCARE
, "*" );
553 font
= (FONTOBJ
*) GDI_HEAP_LIN_ADDR( hnewfont
);
557 if (dc
->header
.wMagic
== METAFILE_DC_MAGIC
)
558 if (MF_CreateFontIndirect(dc
, hfont
, &(font
->logfont
)))
563 if ((hfont
>= FIRST_STOCK_FONT
) && (hfont
<= LAST_STOCK_FONT
))
564 stockPtr
= &stockFonts
[hfont
- FIRST_STOCK_FONT
];
568 * Ok, It's not a stock font but
569 * may be it's cached in dynamic cache
571 for(i
=0; i
<FONTCACHE
; i
++) /* search for same handle */
572 if (cacheFonts
[i
].id
==hfont
) { /* Got the handle */
574 * Check if Handle matches the font
576 if(memcmp(&cacheFonts
[i
].logfont
,&(font
->logfont
), sizeof(LOGFONT16
))) {
577 /* No: remove handle id from dynamic font cache */
578 cacheFonts
[i
].access
=0;
579 cacheFonts
[i
].used
=0;
581 /* may be there is an unused handle which contains the font */
582 for(i
=0; i
<FONTCACHE
; i
++) {
583 if((cacheFonts
[i
].used
== 0) &&
584 (memcmp(&cacheFonts
[i
].logfont
,&(font
->logfont
), sizeof(LOGFONT16
)))== 0) {
585 /* got it load from cache and set new handle id */
586 stockPtr
= &cacheFonts
[i
].cacheFont
;
587 cacheFonts
[i
].access
=1;
588 cacheFonts
[i
].used
=1;
589 cacheFonts
[i
].id
=hfont
;
590 dprintf_font(stddeb
,"FONT_SelectObject: got font from unused handle\n");
597 /* Yes: load from dynamic font cache */
598 stockPtr
= &cacheFonts
[i
].cacheFont
;
599 cacheFonts
[i
].access
++;
600 cacheFonts
[i
].used
++;
605 if (!stockPtr
|| !stockPtr
->fstruct
)
607 if (!(fontStruct
= FONT_MatchFont( &font
->logfont
, dc
)))
609 /* If it is not a stock font, we can simply return 0 */
610 if (!stockPtr
) return 0;
611 /* Otherwise we must try to find a substitute */
612 dprintf_font(stddeb
,"Loading font 'fixed' for %04x\n", hfont
);
613 font
->logfont
.lfPitchAndFamily
&= ~VARIABLE_PITCH
;
614 font
->logfont
.lfPitchAndFamily
|= FIXED_PITCH
;
615 fontStruct
= XLoadQueryFont( display
, "fixed" );
618 fprintf( stderr
, "No system font could be found. Please check your font path.\n" );
625 fontStruct
= stockPtr
->fstruct
;
627 "FONT_SelectObject: Loaded font from cache %04x %p\n",
631 /* Unuse previous font */
632 for (i
=0; i
< FONTCACHE
; i
++) {
633 if (cacheFonts
[i
].id
== prevHandle
) {
634 if(cacheFonts
[i
].used
== 0)
635 fprintf(stderr
, "Trying to decrement a use count of 0.\n");
637 cacheFonts
[i
].used
--;
645 if (!stockPtr
->fstruct
)
647 stockPtr
->fstruct
= fontStruct
;
648 FONT_GetMetrics( &font
->logfont
, fontStruct
, &stockPtr
->metrics
);
650 memcpy( &dc
->u
.x
.font
, stockPtr
, sizeof(*stockPtr
) );
658 for (i
=0; i
< FONTCACHE
; i
++) {
659 if (cacheFonts
[i
].used
==0)
660 if ((!cacheFontsMin
) || ((cacheFontsMin
) && (cacheFontsMin
->access
> cacheFonts
[i
].access
)))
661 cacheFontsMin
=&cacheFonts
[i
];
663 if (!cacheFontsMin
) {
664 fprintf(stderr
,"No unused font cache entry !!!!\n" );
667 if (cacheFontsMin
->id
!=0) {
669 "FONT_SelectObject: Freeing %04x \n",cacheFontsMin
->id
);
670 XFreeFont( display
, cacheFontsMin
->cacheFont
.fstruct
);
672 cacheFontsMin
->cacheFont
.fstruct
= fontStruct
;
673 FONT_GetMetrics( &font
->logfont
, fontStruct
, &cacheFontsMin
->cacheFont
.metrics
);
674 cacheFontsMin
->access
=1;
675 cacheFontsMin
->used
=1;
676 cacheFontsMin
->id
=hfont
;
677 memcpy( &dc
->u
.x
.font
, &(cacheFontsMin
->cacheFont
), sizeof(cacheFontsMin
->cacheFont
) );
678 memcpy(&cacheFontsMin
->logfont
,&(font
->logfont
), sizeof(LOGFONT16
));
685 /***********************************************************************
686 * GetTextCharacterExtra (GDI.89)
688 short GetTextCharacterExtra( HDC hdc
)
690 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
692 return abs( (dc
->w
.charExtra
* dc
->w
.WndExtX
+ dc
->w
.VportExtX
/ 2)
697 /***********************************************************************
698 * SetTextCharacterExtra (GDI.8)
700 short SetTextCharacterExtra( HDC hdc
, short extra
)
703 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
705 extra
= (extra
* dc
->w
.VportExtX
+ dc
->w
.WndExtX
/ 2) / dc
->w
.WndExtX
;
706 prev
= dc
->w
.charExtra
;
707 dc
->w
.charExtra
= abs(extra
);
708 return (prev
* dc
->w
.WndExtX
+ dc
->w
.VportExtX
/ 2) / dc
->w
.VportExtX
;
712 /***********************************************************************
713 * SetTextJustification (GDI.10)
715 short SetTextJustification( HDC hdc
, short extra
, short breaks
)
717 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
720 extra
= abs((extra
* dc
->w
.VportExtX
+ dc
->w
.WndExtX
/ 2) / dc
->w
.WndExtX
);
721 if (!extra
) breaks
= 0;
722 dc
->w
.breakTotalExtra
= extra
;
723 dc
->w
.breakCount
= breaks
;
726 dc
->w
.breakExtra
= extra
/ breaks
;
727 dc
->w
.breakRem
= extra
- (dc
->w
.breakCount
* dc
->w
.breakExtra
);
731 dc
->w
.breakExtra
= 0;
738 /***********************************************************************
739 * GetTextFace (GDI.92)
741 INT
GetTextFace( HDC hdc
, INT count
, LPSTR name
)
745 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
747 if (!(font
= (FONTOBJ
*) GDI_GetObjPtr( dc
->w
.hFont
, FONT_MAGIC
)))
749 lstrcpyn32A( name
, font
->logfont
.lfFaceName
, count
);
754 /***********************************************************************
755 * GetTextExtent (GDI.91)
757 DWORD
GetTextExtent( HDC hdc
, LPCSTR str
, short count
)
760 if (!GetTextExtentPoint16( hdc
, str
, count
, &size
)) return 0;
761 return MAKELONG( size
.cx
, size
.cy
);
765 /***********************************************************************
766 * GetTextExtentPoint16 (GDI.471)
768 BOOL16
GetTextExtentPoint16( HDC16 hdc
, LPCSTR str
, INT16 count
, LPSIZE16 size
)
771 BOOL32 ret
= GetTextExtentPoint32A( hdc
, str
, count
, &size32
);
772 CONV_SIZE32TO16( &size32
, size
);
777 /***********************************************************************
778 * GetTextExtentPoint32A (GDI32.232)
780 BOOL32
GetTextExtentPoint32A( HDC32 hdc
, LPCSTR str
, INT32 count
,
783 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
786 if (!(dc
= (DC
*)GDI_GetObjPtr( hdc
, METAFILE_DC_MAGIC
)))
790 if (!dc
->funcs
->pGetTextExtentPoint
||
791 !dc
->funcs
->pGetTextExtentPoint( dc
, str
, count
, size
))
794 dprintf_font(stddeb
,"GetTextExtentPoint(%08x '%.*s' %d %p): returning %d,%d\n",
795 hdc
, count
, str
, count
, size
, size
->cx
, size
->cy
);
800 /***********************************************************************
801 * GetTextExtentPoint32W (GDI32.233)
803 BOOL32
GetTextExtentPoint32W( HDC32 hdc
, LPCWSTR str
, INT32 count
,
806 char *p
= STRING32_DupUniToAnsi( str
);
807 BOOL32 ret
= GetTextExtentPoint32A( hdc
, p
, count
, size
);
813 /***********************************************************************
814 * GetTextMetrics16 (GDI.93)
816 BOOL16
GetTextMetrics16( HDC16 hdc
, TEXTMETRIC16
*metrics
)
818 DC
* dc
= (DC
*) GDI_GetObjPtr( hdc
, DC_MAGIC
);
819 if (!dc
) return FALSE
;
820 memcpy( metrics
, &dc
->u
.x
.font
.metrics
, sizeof(*metrics
) );
822 metrics
->tmAscent
= abs( metrics
->tmAscent
823 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
824 metrics
->tmDescent
= abs( metrics
->tmDescent
825 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
826 metrics
->tmHeight
= metrics
->tmAscent
+ metrics
->tmDescent
;
827 metrics
->tmInternalLeading
= abs( metrics
->tmInternalLeading
828 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
829 metrics
->tmExternalLeading
= abs( metrics
->tmExternalLeading
830 * dc
->w
.WndExtY
/ dc
->w
.VportExtY
);
831 metrics
->tmMaxCharWidth
= abs( metrics
->tmMaxCharWidth
832 * dc
->w
.WndExtX
/ dc
->w
.VportExtX
);
833 metrics
->tmAveCharWidth
= abs( metrics
->tmAveCharWidth
834 * dc
->w
.WndExtX
/ dc
->w
.VportExtX
);
836 dprintf_font(stdnimp
,"text metrics:\n
850 DigitizedAspectX = %i
851 DigitizedAspectY = %i
857 metrics
->tmInternalLeading
,
858 metrics
->tmExternalLeading
,
859 metrics
->tmMaxCharWidth
,
862 metrics
->tmUnderlined
,
863 metrics
->tmStruckOut
,
864 metrics
->tmFirstChar
,
866 metrics
->tmDefaultChar
,
867 metrics
->tmBreakChar
,
870 metrics
->tmDigitizedAspectX
,
871 metrics
->tmDigitizedAspectY
,
872 metrics
->tmAveCharWidth
,
873 metrics
->tmMaxCharWidth
,
882 /***********************************************************************
883 * GetTextMetrics32A (GDI32.236)
885 BOOL32
GetTextMetrics32A( HDC32 hdc
, TEXTMETRIC32A
*metrics
)
888 if (!GetTextMetrics16( (HDC16
)hdc
, &tm
)) return FALSE
;
889 metrics
->tmHeight
= tm
.tmHeight
;
890 metrics
->tmAscent
= tm
.tmAscent
;
891 metrics
->tmDescent
= tm
.tmDescent
;
892 metrics
->tmInternalLeading
= tm
.tmInternalLeading
;
893 metrics
->tmExternalLeading
= tm
.tmExternalLeading
;
894 metrics
->tmAveCharWidth
= tm
.tmAveCharWidth
;
895 metrics
->tmMaxCharWidth
= tm
.tmMaxCharWidth
;
896 metrics
->tmWeight
= tm
.tmWeight
;
897 metrics
->tmOverhang
= tm
.tmOverhang
;
898 metrics
->tmDigitizedAspectX
= tm
.tmDigitizedAspectX
;
899 metrics
->tmDigitizedAspectY
= tm
.tmDigitizedAspectY
;
900 metrics
->tmFirstChar
= tm
.tmFirstChar
;
901 metrics
->tmLastChar
= tm
.tmLastChar
;
902 metrics
->tmDefaultChar
= tm
.tmDefaultChar
;
903 metrics
->tmBreakChar
= tm
.tmBreakChar
;
904 metrics
->tmItalic
= tm
.tmItalic
;
905 metrics
->tmUnderlined
= tm
.tmUnderlined
;
906 metrics
->tmStruckOut
= tm
.tmStruckOut
;
907 metrics
->tmPitchAndFamily
= tm
.tmPitchAndFamily
;
908 metrics
->tmCharSet
= tm
.tmCharSet
;
913 /***********************************************************************
914 * GetTextMetrics32W (GDI32.237)
916 BOOL32
GetTextMetrics32W( HDC32 hdc
, TEXTMETRIC32W
*metrics
)
919 if (!GetTextMetrics16( (HDC16
)hdc
, &tm
)) return FALSE
;
920 metrics
->tmHeight
= tm
.tmHeight
;
921 metrics
->tmAscent
= tm
.tmAscent
;
922 metrics
->tmDescent
= tm
.tmDescent
;
923 metrics
->tmInternalLeading
= tm
.tmInternalLeading
;
924 metrics
->tmExternalLeading
= tm
.tmExternalLeading
;
925 metrics
->tmAveCharWidth
= tm
.tmAveCharWidth
;
926 metrics
->tmMaxCharWidth
= tm
.tmMaxCharWidth
;
927 metrics
->tmWeight
= tm
.tmWeight
;
928 metrics
->tmOverhang
= tm
.tmOverhang
;
929 metrics
->tmDigitizedAspectX
= tm
.tmDigitizedAspectX
;
930 metrics
->tmDigitizedAspectY
= tm
.tmDigitizedAspectY
;
931 metrics
->tmFirstChar
= tm
.tmFirstChar
;
932 metrics
->tmLastChar
= tm
.tmLastChar
;
933 metrics
->tmDefaultChar
= tm
.tmDefaultChar
;
934 metrics
->tmBreakChar
= tm
.tmBreakChar
;
935 metrics
->tmItalic
= tm
.tmItalic
;
936 metrics
->tmUnderlined
= tm
.tmUnderlined
;
937 metrics
->tmStruckOut
= tm
.tmStruckOut
;
938 metrics
->tmPitchAndFamily
= tm
.tmPitchAndFamily
;
939 metrics
->tmCharSet
= tm
.tmCharSet
;
944 /***********************************************************************
945 * SetMapperFlags (GDI.349)
947 DWORD
SetMapperFlags(HDC hDC
, DWORD dwFlag
)
949 dprintf_font(stdnimp
,"SetmapperFlags(%04x, %08lX) // Empty Stub !\n",
955 /***********************************************************************
956 * GetCharABCWidths (GDI.307)
958 BOOL
GetCharABCWidths(HDC hdc
, UINT wFirstChar
, UINT wLastChar
, LPABC16 lpABC
)
961 /* No TrueType fonts in Wine so far */
963 fprintf(stdnimp
,"STUB: GetCharABCWidths(%04x,%04x,%04x,%08x)\n",
964 hdc
,wFirstChar
,wLastChar
,(unsigned)lpABC
);
970 /***********************************************************************
971 * GetCharWidth (GDI.350)
973 BOOL
GetCharWidth(HDC hdc
, WORD wFirstChar
, WORD wLastChar
, LPINT16 lpBuffer
)
977 XCharStruct
*cs
, *def
;
979 DC
*dc
= (DC
*)GDI_GetObjPtr(hdc
, DC_MAGIC
);
980 if (!dc
) return FALSE
;
981 xfont
= dc
->u
.x
.font
.fstruct
;
984 if (xfont
->per_char
== NULL
)
986 for (i
= wFirstChar
, j
= 0; i
<= wLastChar
; i
++, j
++)
987 *(lpBuffer
+ j
) = xfont
->max_bounds
.width
;
991 CI_GET_DEFAULT_INFO(xfont
, def
);
993 for (i
= wFirstChar
, j
= 0; i
<= wLastChar
; i
++, j
++)
995 CI_GET_CHAR_INFO(xfont
, i
, def
, cs
);
996 *(lpBuffer
+ j
) = cs
? cs
->width
: xfont
->max_bounds
.width
;
997 if (*(lpBuffer
+ j
) < 0)
1004 /***********************************************************************
1005 * AddFontResource (GDI.119)
1007 INT
AddFontResource( LPCSTR str
)
1009 fprintf( stdnimp
, "STUB: AddFontResource('%s')\n", str
);
1014 /***********************************************************************
1015 * RemoveFontResource (GDI.136)
1017 BOOL
RemoveFontResource( LPSTR str
)
1019 fprintf( stdnimp
, "STUB: RemoveFontResource('%s')\n", str
);
1024 /*************************************************************************
1025 * ParseFontParms [internal]
1027 int ParseFontParms(LPSTR lpFont
, WORD wParmsNo
, LPSTR lpRetStr
, WORD wMaxSiz
)
1030 if (lpFont
== NULL
) return 0;
1031 if (lpRetStr
== NULL
) return 0;
1032 for (i
= 0; (*lpFont
!= '\0' && i
!= wParmsNo
); ) {
1033 if (*lpFont
== '-') i
++;
1036 if (i
== wParmsNo
) {
1037 if (*lpFont
== '-') lpFont
++;
1039 for (i
= 0; (*lpFont
!= '\0' && *lpFont
!= '-' && i
< wMaxSiz
); i
++)
1040 *(lpRetStr
+ i
) = *lpFont
++;
1041 *(lpRetStr
+ i
) = '\0';
1050 /*************************************************************************
1051 * InitFontsList [internal]
1054 static int logfcmp(const void *a
,const void *b
)
1056 return strcmp( (*(LPLOGFONT16
*)a
)->lfFaceName
,
1057 (*(LPLOGFONT16
*)b
)->lfFaceName
);
1060 void InitFontsList(void)
1064 char *family
, *weight
, *charset
;
1066 char slant
, spacing
;
1068 LPLOGFONT16 lpNewFont
;
1070 dprintf_font(stddeb
,"InitFontsList !\n");
1078 sprintf( pattern
, "-%s-%s-%c-normal-*-*-*-*-*-%c-*-%s",
1079 family
, weight
, slant
, spacing
, charset
);
1080 names
= XListFonts( display
, pattern
, MAX_FONTS
, &count
);
1081 dprintf_font(stddeb
,"InitFontsList // count=%d \n", count
);
1083 lpNewFont
= malloc((sizeof(LOGFONT16
)+LF_FACESIZE
)*count
);
1084 if (lpNewFont
== NULL
) {
1085 dprintf_font(stddeb
,
1086 "InitFontsList // Error alloc new font structure !\n");
1087 XFreeFontNames(names
);
1091 for (i
= 0; i
< count
; i
++) {
1092 dprintf_font(stddeb
,"InitFontsList // names[%d]='%s' \n", i
, names
[i
]);
1094 ParseFontParms(names
[i
], 2, str
, sizeof(str
));
1096 /* not necessary because new function FONT_ChkX11Family() */
1097 if (strcmp(str
, "fixed") == 0) strcat(str
, "sys");
1100 strcpy(lpNewFont
->lfFaceName
, str
);
1101 ParseFontParms(names
[i
], 8, str
, sizeof(str
));
1102 lpNewFont
->lfHeight
= atoi(str
) / 10;
1103 ParseFontParms(names
[i
], 12, str
, sizeof(str
));
1104 lpNewFont
->lfWidth
= atoi(str
) / 10;
1105 lpNewFont
->lfEscapement
= 0;
1106 lpNewFont
->lfOrientation
= 0;
1107 lpNewFont
->lfWeight
= FW_REGULAR
;
1108 lpNewFont
->lfItalic
= 0;
1109 lpNewFont
->lfUnderline
= 0;
1110 lpNewFont
->lfStrikeOut
= 0;
1111 ParseFontParms(names
[i
], 13, str
, sizeof(str
));
1112 if (strcmp(str
, "iso8859") == 0) {
1113 lpNewFont
->lfCharSet
= ANSI_CHARSET
;
1115 lpNewFont
->lfCharSet
= OEM_CHARSET
;
1117 lpNewFont
->lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1118 lpNewFont
->lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1119 lpNewFont
->lfQuality
= DEFAULT_QUALITY
;
1120 ParseFontParms(names
[i
], 11, str
, sizeof(str
));
1123 lpNewFont
->lfPitchAndFamily
= VARIABLE_PITCH
| FF_SWISS
;
1127 lpNewFont
->lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
1130 lpNewFont
->lfPitchAndFamily
= DEFAULT_PITCH
| FF_DONTCARE
;
1133 dprintf_font( stddeb
,
1134 "InitFontsList // lpNewFont->lfHeight=%d\n",
1135 lpNewFont
->lfHeight
);
1136 dprintf_font( stddeb
,
1137 "InitFontsList // lpNewFont->lfWidth=%d\n",
1138 lpNewFont
->lfWidth
);
1139 dprintf_font( stddeb
,
1140 "InitFontsList // lfFaceName='%s'\n",
1141 lpNewFont
->lfFaceName
);
1142 lpLogFontList
[i
] = lpNewFont
;
1143 lpNewFont
= (LPLOGFONT16
)
1144 ((char *)lpNewFont
+ sizeof(LOGFONT16
)+LF_FACESIZE
);
1146 lpLogFontList
[i
] = NULL
;
1148 qsort(lpLogFontList
,count
,sizeof(*lpLogFontList
),logfcmp
);
1149 XFreeFontNames(names
);
1153 /*************************************************************************
1154 * EnumFonts [GDI.70]
1156 INT
EnumFonts(HDC hDC
, LPCSTR lpFaceName
, FONTENUMPROC16 lpEnumFunc
, LPARAM lpData
)
1162 LPLOGFONT16 lpLogFont
;
1163 LPTEXTMETRIC16 lptm
;
1165 char FaceName
[LF_FACESIZE
];
1169 dprintf_font(stddeb
,"EnumFonts(%04x, %p='%s', %08lx, %08lx)\n",
1170 hDC
, lpFaceName
, lpFaceName
, (LONG
)lpEnumFunc
, lpData
);
1171 if (lpEnumFunc
== 0) return 0;
1172 hLog
= GDI_HEAP_ALLOC( sizeof(LOGFONT16
) + LF_FACESIZE
);
1173 lpLogFont
= (LPLOGFONT16
) GDI_HEAP_LIN_ADDR(hLog
);
1174 if (lpLogFont
== NULL
) {
1175 fprintf(stderr
,"EnumFonts // can't alloc LOGFONT struct !\n");
1178 hMet
= GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16
) );
1179 lptm
= (LPTEXTMETRIC16
) GDI_HEAP_LIN_ADDR(hMet
);
1181 GDI_HEAP_FREE(hLog
);
1182 fprintf(stderr
, "EnumFonts // can't alloc TEXTMETRIC struct !\n");
1185 if (lpFaceName
!= NULL
) {
1186 strcpy(FaceName
, lpFaceName
);
1187 AnsiUpper(FaceName
);
1191 if (lpLogFontList
[0] == NULL
) InitFontsList();
1192 for(i
= 0; lpLogFontList
[i
] != NULL
; i
++) {
1193 if (lpFaceName
== NULL
) {
1194 if (lpOldName
!= NULL
) {
1195 if (strcmp(lpOldName
,lpLogFontList
[i
]->lfFaceName
) == 0) continue;
1197 lpOldName
= lpLogFontList
[i
]->lfFaceName
;
1199 if (strcmp(FaceName
, lpLogFontList
[i
]->lfFaceName
) != 0) continue;
1201 dprintf_font(stddeb
,"EnumFonts // enum '%s' !\n", lpLogFontList
[i
]->lfFaceName
);
1202 dprintf_font(stddeb
,"EnumFonts // %p !\n", lpLogFontList
[i
]);
1203 memcpy(lpLogFont
, lpLogFontList
[i
], sizeof(LOGFONT16
) + LF_FACESIZE
);
1204 hFont
= CreateFontIndirect16(lpLogFont
);
1205 hOldFont
= SelectObject(hDC
, hFont
);
1206 GetTextMetrics16(hDC
, lptm
);
1207 SelectObject(hDC
, hOldFont
);
1208 DeleteObject(hFont
);
1209 dprintf_font(stddeb
,"EnumFonts // i=%d lpLogFont=%p lptm=%p\n", i
, lpLogFont
, lptm
);
1210 nRet
= lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog
), GDI_HEAP_SEG_ADDR(hMet
),
1213 dprintf_font(stddeb
,"EnumFonts // EnumEnd requested by application !\n");
1217 GDI_HEAP_FREE(hMet
);
1218 GDI_HEAP_FREE(hLog
);
1223 /*************************************************************************
1224 * EnumFontFamilies [GDI.330]
1226 INT
EnumFontFamilies(HDC hDC
, LPCSTR lpszFamily
, FONTENUMPROC16 lpEnumFunc
, LPARAM lpData
)
1232 LPENUMLOGFONT16 lpEnumLogFont
;
1233 LPTEXTMETRIC16 lptm
;
1235 char FaceName
[LF_FACESIZE
];
1239 dprintf_font(stddeb
,"EnumFontFamilies(%04x, %p, %08lx, %08lx)\n",
1240 hDC
, lpszFamily
, (DWORD
)lpEnumFunc
, lpData
);
1241 if (lpEnumFunc
== 0) return 0;
1242 hLog
= GDI_HEAP_ALLOC( sizeof(ENUMLOGFONT16
) );
1243 lpEnumLogFont
= (LPENUMLOGFONT16
) GDI_HEAP_LIN_ADDR(hLog
);
1244 if (lpEnumLogFont
== NULL
) {
1245 fprintf(stderr
,"EnumFontFamilies // can't alloc LOGFONT struct !\n");
1248 hMet
= GDI_HEAP_ALLOC( sizeof(TEXTMETRIC16
) );
1249 lptm
= (LPTEXTMETRIC16
) GDI_HEAP_LIN_ADDR(hMet
);
1251 GDI_HEAP_FREE(hLog
);
1252 fprintf(stderr
,"EnumFontFamilies // can't alloc TEXTMETRIC struct !\n");
1256 if (lpszFamily
!= NULL
) {
1257 strcpy(FaceName
, lpszFamily
);
1258 AnsiUpper(FaceName
);
1260 if (lpLogFontList
[0] == NULL
) InitFontsList();
1261 for(i
= 0; lpLogFontList
[i
] != NULL
; i
++) {
1262 if (lpszFamily
== NULL
) {
1263 if (lpOldName
!= NULL
) {
1264 if (strcmp(lpOldName
,lpLogFontList
[i
]->lfFaceName
) == 0) continue;
1266 lpOldName
= lpLogFontList
[i
]->lfFaceName
;
1268 if (strcmp(FaceName
, lpLogFontList
[i
]->lfFaceName
) != 0) continue;
1270 memcpy(lpEnumLogFont
, lpLogFontList
[i
], sizeof(LOGFONT16
));
1271 strcpy(lpEnumLogFont
->elfFullName
,"");
1272 strcpy(lpEnumLogFont
->elfStyle
,"");
1273 hFont
= CreateFontIndirect16((LPLOGFONT16
)lpEnumLogFont
);
1274 hOldFont
= SelectObject(hDC
, hFont
);
1275 GetTextMetrics16(hDC
, lptm
);
1276 SelectObject(hDC
, hOldFont
);
1277 DeleteObject(hFont
);
1278 dprintf_font(stddeb
, "EnumFontFamilies // i=%d lpLogFont=%p lptm=%p\n", i
, lpEnumLogFont
, lptm
);
1280 nRet
= lpEnumFunc( GDI_HEAP_SEG_ADDR(hLog
), GDI_HEAP_SEG_ADDR(hMet
),
1283 dprintf_font(stddeb
,"EnumFontFamilies // EnumEnd requested by application !\n");
1287 GDI_HEAP_FREE(hMet
);
1288 GDI_HEAP_FREE(hLog
);
1292 /*************************************************************************
1293 * GetRasterizerCaps [GDI.313]
1296 BOOL
GetRasterizerCaps(LPRASTERIZER_STATUS lprs
, UINT cbNumBytes
)
1298 /* This is not much more than a dummy */
1299 RASTERIZER_STATUS rs
;
1301 rs
.nSize
= sizeof(rs
);
1307 /*************************************************************************
1308 * GetKerningPairs [GDI.332]
1310 int GetKerningPairs(HDC hDC
,int cPairs
,LPKERNINGPAIR16 lpKerningPairs
)
1312 /* This has to be dealt with when proper font handling is in place
1314 * At this time kerning is ignored (set to 0)
1318 fprintf(stdnimp
,"GetKerningPairs: almost empty stub!\n");
1319 for (i
= 0; i
< cPairs
; i
++) lpKerningPairs
[i
].iKernAmount
= 0;