Use same formula to convert from device to logical units as everywhere
[wine] / objects / font.c
1 /*
2  * GDI font objects
3  *
4  * Copyright 1993 Alexandre Julliard
5  *           1997 Alex Korobka
6  * Copyright 2002,2003 Shachar Shemesh
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdlib.h>
27 #include <string.h>
28 #include <assert.h>
29 #include "winerror.h"
30 #include "winnls.h"
31 #include "wownt32.h"
32 #include "gdi.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
35
36 WINE_DEFAULT_DEBUG_CHANNEL(font);
37 WINE_DECLARE_DEBUG_CHANNEL(gdi);
38
39 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
40 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
41 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
42 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
43 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
44
45 static const struct gdi_obj_funcs font_funcs =
46 {
47     FONT_SelectObject,  /* pSelectObject */
48     FONT_GetObject16,   /* pGetObject16 */
49     FONT_GetObjectA,    /* pGetObjectA */
50     FONT_GetObjectW,    /* pGetObjectW */
51     NULL,               /* pUnrealizeObject */
52     FONT_DeleteObject   /* pDeleteObject */
53 };
54
55 #define ENUM_UNICODE    0x00000001
56 #define ENUM_CALLED     0x00000002
57
58 typedef struct
59 {
60     GDIOBJHDR   header;
61     LOGFONTW    logfont;
62 } FONTOBJ;
63
64 typedef struct
65 {
66   LPLOGFONT16           lpLogFontParam;
67   FONTENUMPROC16        lpEnumFunc;
68   LPARAM                lpData;
69
70   LPNEWTEXTMETRICEX16   lpTextMetric;
71   LPENUMLOGFONTEX16     lpLogFont;
72   SEGPTR                segTextMetric;
73   SEGPTR                segLogFont;
74   DWORD                 dwFlags;
75   HDC                   hdc;
76   DC                   *dc;
77   PHYSDEV               physDev;
78 } fontEnum16;
79
80 typedef struct
81 {
82   LPLOGFONTW          lpLogFontParam;
83   FONTENUMPROCW       lpEnumFunc;
84   LPARAM              lpData;
85   DWORD               dwFlags;
86   HDC                 hdc;
87   DC                 *dc;
88   PHYSDEV             physDev;
89 } fontEnum32;
90
91 /*
92  *  For TranslateCharsetInfo
93  */
94 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
95 #define MAXTCIINDEX 32
96 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
97   /* ANSI */
98   { ANSI_CHARSET, 1252, FS(0)},
99   { EASTEUROPE_CHARSET, 1250, FS(1)},
100   { RUSSIAN_CHARSET, 1251, FS(2)},
101   { GREEK_CHARSET, 1253, FS(3)},
102   { TURKISH_CHARSET, 1254, FS(4)},
103   { HEBREW_CHARSET, 1255, FS(5)},
104   { ARABIC_CHARSET, 1256, FS(6)},
105   { BALTIC_CHARSET, 1257, FS(7)},
106   { VIETNAMESE_CHARSET, 1258, FS(8)},
107   /* reserved by ANSI */
108   { DEFAULT_CHARSET, 0, FS(0)},
109   { DEFAULT_CHARSET, 0, FS(0)},
110   { DEFAULT_CHARSET, 0, FS(0)},
111   { DEFAULT_CHARSET, 0, FS(0)},
112   { DEFAULT_CHARSET, 0, FS(0)},
113   { DEFAULT_CHARSET, 0, FS(0)},
114   { DEFAULT_CHARSET, 0, FS(0)},
115   /* ANSI and OEM */
116   { THAI_CHARSET,  874,  FS(16)},
117   { SHIFTJIS_CHARSET, 932, FS(17)},
118   { GB2312_CHARSET, 936, FS(18)},
119   { HANGEUL_CHARSET, 949, FS(19)},
120   { CHINESEBIG5_CHARSET, 950, FS(20)},
121   { JOHAB_CHARSET, 1361, FS(21)},
122   /* reserved for alternate ANSI and OEM */
123   { DEFAULT_CHARSET, 0, FS(0)},
124   { DEFAULT_CHARSET, 0, FS(0)},
125   { DEFAULT_CHARSET, 0, FS(0)},
126   { DEFAULT_CHARSET, 0, FS(0)},
127   { DEFAULT_CHARSET, 0, FS(0)},
128   { DEFAULT_CHARSET, 0, FS(0)},
129   { DEFAULT_CHARSET, 0, FS(0)},
130   { DEFAULT_CHARSET, 0, FS(0)},
131   /* reserved for system */
132   { DEFAULT_CHARSET, 0, FS(0)},
133   { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
134 };
135
136 /***********************************************************************
137  *              LOGFONT conversion functions.
138  */
139 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
140 {
141     font16->lfHeight = font32->lfHeight;
142     font16->lfWidth = font32->lfWidth;
143     font16->lfEscapement = font32->lfEscapement;
144     font16->lfOrientation = font32->lfOrientation;
145     font16->lfWeight = font32->lfWeight;
146     font16->lfItalic = font32->lfItalic;
147     font16->lfUnderline = font32->lfUnderline;
148     font16->lfStrikeOut = font32->lfStrikeOut;
149     font16->lfCharSet = font32->lfCharSet;
150     font16->lfOutPrecision = font32->lfOutPrecision;
151     font16->lfClipPrecision = font32->lfClipPrecision;
152     font16->lfQuality = font32->lfQuality;
153     font16->lfPitchAndFamily = font32->lfPitchAndFamily;
154     WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
155                          font16->lfFaceName, LF_FACESIZE, NULL, NULL );
156     font16->lfFaceName[LF_FACESIZE-1] = 0;
157 }
158
159 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
160 {
161     font32->lfHeight = font16->lfHeight;
162     font32->lfWidth = font16->lfWidth;
163     font32->lfEscapement = font16->lfEscapement;
164     font32->lfOrientation = font16->lfOrientation;
165     font32->lfWeight = font16->lfWeight;
166     font32->lfItalic = font16->lfItalic;
167     font32->lfUnderline = font16->lfUnderline;
168     font32->lfStrikeOut = font16->lfStrikeOut;
169     font32->lfCharSet = font16->lfCharSet;
170     font32->lfOutPrecision = font16->lfOutPrecision;
171     font32->lfClipPrecision = font16->lfClipPrecision;
172     font32->lfQuality = font16->lfQuality;
173     font32->lfPitchAndFamily = font16->lfPitchAndFamily;
174     MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
175     font32->lfFaceName[LF_FACESIZE-1] = 0;
176 }
177
178 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
179 {
180     memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
181     MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
182                         LF_FACESIZE);
183 }
184
185 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
186 {
187     memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
188     WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
189                         LF_FACESIZE, NULL, NULL);
190 }
191
192 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
193 {
194     FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
195
196     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
197                          font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
198     font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
199     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
200                          font16->elfStyle, LF_FACESIZE, NULL, NULL );
201     font16->elfStyle[LF_FACESIZE-1] = '\0';
202     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
203                          font16->elfScript, LF_FACESIZE, NULL, NULL );
204     font16->elfScript[LF_FACESIZE-1] = '\0';
205 }
206
207 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
208 {
209     FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
210
211     WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
212                          fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
213     fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
214     WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
215                          fontA->elfStyle, LF_FACESIZE, NULL, NULL );
216     fontA->elfStyle[LF_FACESIZE-1] = '\0';
217     WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
218                          fontA->elfScript, LF_FACESIZE, NULL, NULL );
219     fontA->elfScript[LF_FACESIZE-1] = '\0';
220 }
221
222 /***********************************************************************
223  *              TEXTMETRIC conversion functions.
224  */
225 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
226 {
227     ptmA->tmHeight = ptmW->tmHeight;
228     ptmA->tmAscent = ptmW->tmAscent;
229     ptmA->tmDescent = ptmW->tmDescent;
230     ptmA->tmInternalLeading = ptmW->tmInternalLeading;
231     ptmA->tmExternalLeading = ptmW->tmExternalLeading;
232     ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
233     ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
234     ptmA->tmWeight = ptmW->tmWeight;
235     ptmA->tmOverhang = ptmW->tmOverhang;
236     ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
237     ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
238     ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
239     ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
240     ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
241     ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
242     ptmA->tmItalic = ptmW->tmItalic;
243     ptmA->tmUnderlined = ptmW->tmUnderlined;
244     ptmA->tmStruckOut = ptmW->tmStruckOut;
245     ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
246     ptmA->tmCharSet = ptmW->tmCharSet;
247 }
248
249
250 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
251 {
252     ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
253     ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
254     ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
255     ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
256     ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
257     ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
258     ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
259     ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
260     ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
261     ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
262     ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
263     ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
264     ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
265     ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
266     ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
267     ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
268     ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
269     ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
270     ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
271     ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
272     ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
273     ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
274     ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
275     ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
276     memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
277 }
278
279 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
280 {
281     FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
282     ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
283     ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
284     ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
285     ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
286     memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
287 }
288
289 /***********************************************************************
290  *           CreateFontIndirectA   (GDI32.@)
291  */
292 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
293 {
294     LOGFONTW lfW;
295
296     if (plfA) {
297         FONT_LogFontAToW( plfA, &lfW );
298         return CreateFontIndirectW( &lfW );
299      } else
300         return CreateFontIndirectW( NULL );
301
302 }
303
304 /***********************************************************************
305  *           CreateFontIndirectW   (GDI32.@)
306  */
307 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
308 {
309     HFONT hFont = 0;
310
311     if (plf)
312     {
313         FONTOBJ* fontPtr;
314         if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
315                                         (HGDIOBJ *)&hFont, &font_funcs )))
316         {
317             memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
318
319             TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s => %p\n",
320                   plf->lfHeight, plf->lfWidth,
321                   plf->lfEscapement, plf->lfOrientation,
322                   plf->lfPitchAndFamily,
323                   plf->lfOutPrecision, plf->lfClipPrecision,
324                   plf->lfQuality, plf->lfCharSet,
325                   debugstr_w(plf->lfFaceName),
326                   plf->lfWeight > 400 ? "Bold" : "",
327                   plf->lfItalic ? "Italic" : "", hFont);
328
329             if (plf->lfEscapement != plf->lfOrientation) {
330               /* this should really depend on whether GM_ADVANCED is set */
331               fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
332               WARN("orientation angle %f set to "
333                    "escapement angle %f for new font %p\n",
334                    plf->lfOrientation/10., plf->lfEscapement/10., hFont);
335             }
336             GDI_ReleaseObj( hFont );
337         }
338     }
339     else WARN("(NULL) => NULL\n");
340
341     return hFont;
342 }
343
344 /*************************************************************************
345  *           CreateFontA    (GDI32.@)
346  */
347 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
348                               INT orient, INT weight, DWORD italic,
349                               DWORD underline, DWORD strikeout, DWORD charset,
350                               DWORD outpres, DWORD clippres, DWORD quality,
351                               DWORD pitch, LPCSTR name )
352 {
353     LOGFONTA logfont;
354
355     logfont.lfHeight = height;
356     logfont.lfWidth = width;
357     logfont.lfEscapement = esc;
358     logfont.lfOrientation = orient;
359     logfont.lfWeight = weight;
360     logfont.lfItalic = italic;
361     logfont.lfUnderline = underline;
362     logfont.lfStrikeOut = strikeout;
363     logfont.lfCharSet = charset;
364     logfont.lfOutPrecision = outpres;
365     logfont.lfClipPrecision = clippres;
366     logfont.lfQuality = quality;
367     logfont.lfPitchAndFamily = pitch;
368
369     if (name)
370         lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
371     else
372         logfont.lfFaceName[0] = '\0';
373
374     return CreateFontIndirectA( &logfont );
375 }
376
377 /*************************************************************************
378  *           CreateFontW    (GDI32.@)
379  */
380 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
381                               INT orient, INT weight, DWORD italic,
382                               DWORD underline, DWORD strikeout, DWORD charset,
383                               DWORD outpres, DWORD clippres, DWORD quality,
384                               DWORD pitch, LPCWSTR name )
385 {
386     LOGFONTW logfont;
387
388     logfont.lfHeight = height;
389     logfont.lfWidth = width;
390     logfont.lfEscapement = esc;
391     logfont.lfOrientation = orient;
392     logfont.lfWeight = weight;
393     logfont.lfItalic = italic;
394     logfont.lfUnderline = underline;
395     logfont.lfStrikeOut = strikeout;
396     logfont.lfCharSet = charset;
397     logfont.lfOutPrecision = outpres;
398     logfont.lfClipPrecision = clippres;
399     logfont.lfQuality = quality;
400     logfont.lfPitchAndFamily = pitch;
401
402     if (name)
403         lstrcpynW(logfont.lfFaceName, name,
404                   sizeof(logfont.lfFaceName) / sizeof(WCHAR));
405     else
406         logfont.lfFaceName[0] = '\0';
407
408     return CreateFontIndirectW( &logfont );
409 }
410
411
412 /***********************************************************************
413  *           FONT_SelectObject
414  *
415  * If the driver supports vector fonts we create a gdi font first and
416  * then call the driver to give it a chance to supply its own device
417  * font.  If the driver wants to do this it returns TRUE and we can
418  * delete the gdi font, if the driver wants to use the gdi font it
419  * should return FALSE, to signal an error return GDI_ERROR.  For
420  * drivers that don't support vector fonts they must supply their own
421  * font.
422  */
423 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
424 {
425     HGDIOBJ ret = 0;
426     DC *dc = DC_GetDCPtr( hdc );
427
428     if (!dc) return 0;
429
430     if (dc->hFont != handle || dc->gdiFont == NULL)
431     {
432         if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
433             dc->gdiFont = WineEngCreateFontInstance(dc, handle);
434     }
435
436     if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle );
437
438     if (ret && dc->gdiFont) dc->gdiFont = 0;
439
440     if (ret == HGDI_ERROR)
441         ret = 0; /* SelectObject returns 0 on error */
442     else
443     {
444         ret = dc->hFont;
445         dc->hFont = handle;
446     }
447     GDI_ReleaseObj( hdc );
448     return ret;
449 }
450
451
452 /***********************************************************************
453  *           FONT_GetObject16
454  */
455 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
456 {
457     FONTOBJ *font = obj;
458     LOGFONT16 lf16;
459
460     FONT_LogFontWTo16( &font->logfont, &lf16 );
461
462     if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
463     memcpy( buffer, &lf16, count );
464     return count;
465 }
466
467 /***********************************************************************
468  *           FONT_GetObjectA
469  */
470 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
471 {
472     FONTOBJ *font = obj;
473     LOGFONTA lfA;
474
475     if(!buffer)
476         return sizeof(lfA);
477     FONT_LogFontWToA( &font->logfont, &lfA );
478
479     if (count > sizeof(lfA)) count = sizeof(lfA);
480     memcpy( buffer, &lfA, count );
481     return count;
482 }
483
484 /***********************************************************************
485  *           FONT_GetObjectW
486  */
487 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
488 {
489     FONTOBJ *font = obj;
490     if(!buffer)
491         return sizeof(LOGFONTW);
492     if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
493     memcpy( buffer, &font->logfont, count );
494     return count;
495 }
496
497
498 /***********************************************************************
499  *           FONT_DeleteObject
500  */
501 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
502 {
503     WineEngDestroyFontInstance( handle );
504     return GDI_FreeObject( handle, obj );
505 }
506
507
508 /***********************************************************************
509  *              FONT_EnumInstance16
510  *
511  * Called by the device driver layer to pass font info
512  * down to the application.
513  */
514 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
515                                 DWORD fType, LPARAM lp )
516 {
517     fontEnum16 *pfe = (fontEnum16*)lp;
518     INT ret = 1;
519     DC *dc;
520
521     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
522         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
523     {
524         WORD args[7];
525         DWORD result;
526
527         FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
528         FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
529         pfe->dwFlags |= ENUM_CALLED;
530         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
531
532         args[6] = SELECTOROF(pfe->segLogFont);
533         args[5] = OFFSETOF(pfe->segLogFont);
534         args[4] = SELECTOROF(pfe->segTextMetric);
535         args[3] = OFFSETOF(pfe->segTextMetric);
536         args[2] = fType;
537         args[1] = HIWORD(pfe->lpData);
538         args[0] = LOWORD(pfe->lpData);
539         WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
540         ret = LOWORD(result);
541
542         /* get the lock again and make sure the DC is still valid */
543         dc = DC_GetDCPtr( pfe->hdc );
544         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
545         {
546             if (dc) GDI_ReleaseObj( pfe->hdc );
547             pfe->hdc = 0;  /* make sure we don't try to release it later on */
548             ret = 0;
549         }
550     }
551     return ret;
552 }
553
554 /***********************************************************************
555  *              FONT_EnumInstance
556  */
557 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
558                               DWORD fType, LPARAM lp )
559 {
560     fontEnum32 *pfe = (fontEnum32*)lp;
561     INT ret = 1;
562     DC *dc;
563
564     /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
565     if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
566         pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
567     {
568         /* convert font metrics */
569         ENUMLOGFONTEXA logfont;
570         NEWTEXTMETRICEXA tmA;
571
572         pfe->dwFlags |= ENUM_CALLED;
573         if (!(pfe->dwFlags & ENUM_UNICODE))
574         {
575             FONT_EnumLogFontExWToA( plf, &logfont);
576             FONT_NewTextMetricExWToA( ptm, &tmA );
577             plf = (LPENUMLOGFONTEXW)&logfont;
578             ptm = (NEWTEXTMETRICEXW *)&tmA;
579         }
580         GDI_ReleaseObj( pfe->hdc );  /* release the GDI lock */
581
582         ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
583
584         /* get the lock again and make sure the DC is still valid */
585         dc = DC_GetDCPtr( pfe->hdc );
586         if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
587         {
588             if (dc) GDI_ReleaseObj( pfe->hdc );
589             pfe->hdc = 0;  /* make sure we don't try to release it later on */
590             ret = 0;
591         }
592     }
593     return ret;
594 }
595
596 /***********************************************************************
597  *              EnumFontFamiliesEx      (GDI.613)
598  */
599 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
600                                    FONTENUMPROC16 efproc, LPARAM lParam,
601                                    DWORD dwFlags)
602 {
603     fontEnum16 fe16;
604     INT16       ret = 1, ret2;
605     DC*         dc = DC_GetDCPtr( HDC_32(hDC) );
606     NEWTEXTMETRICEX16 tm16;
607     ENUMLOGFONTEX16 lf16;
608     LOGFONTW lfW;
609     BOOL enum_gdi_fonts;
610
611     if (!dc) return 0;
612     FONT_LogFont16ToW(plf, &lfW);
613
614     fe16.hdc = HDC_32(hDC);
615     fe16.dc = dc;
616     fe16.physDev = dc->physDev;
617     fe16.lpLogFontParam = plf;
618     fe16.lpEnumFunc = efproc;
619     fe16.lpData = lParam;
620     fe16.lpTextMetric = &tm16;
621     fe16.lpLogFont = &lf16;
622     fe16.segTextMetric = MapLS( &tm16 );
623     fe16.segLogFont = MapLS( &lf16 );
624     fe16.dwFlags = 0;
625
626     enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
627
628     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
629     {
630         ret = 0;
631         goto done;
632     }
633
634     if (enum_gdi_fonts)
635         ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
636     fe16.dwFlags &= ~ENUM_CALLED;
637     if (ret && dc->funcs->pEnumDeviceFonts) {
638         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
639         if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
640             ret = ret2;
641     }
642 done:
643     UnMapLS( fe16.segTextMetric );
644     UnMapLS( fe16.segLogFont );
645     if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
646     return ret;
647 }
648
649 /***********************************************************************
650  *              FONT_EnumFontFamiliesEx
651  */
652 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
653                                     FONTENUMPROCW efproc,
654                                     LPARAM lParam, DWORD dwUnicode)
655 {
656     INT ret = 1, ret2;
657     DC *dc = DC_GetDCPtr( hDC );
658     fontEnum32 fe32;
659     BOOL enum_gdi_fonts;
660
661     if (!dc) return 0;
662
663     TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
664           plf->lfCharSet);
665     fe32.lpLogFontParam = plf;
666     fe32.lpEnumFunc = efproc;
667     fe32.lpData = lParam;
668     fe32.dwFlags = dwUnicode;
669     fe32.hdc = hDC;
670     fe32.dc = dc;
671     fe32.physDev = dc->physDev;
672
673     enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
674
675     if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
676     {
677         ret = 0;
678         goto done;
679     }
680
681     if (enum_gdi_fonts)
682         ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
683     fe32.dwFlags &= ~ENUM_CALLED;
684     if (ret && dc->funcs->pEnumDeviceFonts) {
685         ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
686         if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
687             ret = ret2;
688     }
689  done:
690     if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
691     return ret;
692 }
693
694 /***********************************************************************
695  *              EnumFontFamiliesExW     (GDI32.@)
696  */
697 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
698                                     FONTENUMPROCW efproc,
699                                     LPARAM lParam, DWORD dwFlags )
700 {
701     return  FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
702 }
703
704 /***********************************************************************
705  *              EnumFontFamiliesExA     (GDI32.@)
706  */
707 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
708                                     FONTENUMPROCA efproc,
709                                     LPARAM lParam, DWORD dwFlags)
710 {
711     LOGFONTW lfW;
712     FONT_LogFontAToW( plf, &lfW );
713
714     return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
715 }
716
717 /***********************************************************************
718  *              EnumFontFamilies        (GDI.330)
719  */
720 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
721                                  FONTENUMPROC16 efproc, LPARAM lpData )
722 {
723     LOGFONT16   lf;
724
725     lf.lfCharSet = DEFAULT_CHARSET;
726     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
727     else lf.lfFaceName[0] = '\0';
728
729     return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
730 }
731
732 /***********************************************************************
733  *              EnumFontFamiliesA       (GDI32.@)
734  */
735 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
736                                   FONTENUMPROCA efproc, LPARAM lpData )
737 {
738     LOGFONTA    lf;
739
740     lf.lfCharSet = DEFAULT_CHARSET;
741     if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
742     else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
743
744     return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
745 }
746
747 /***********************************************************************
748  *              EnumFontFamiliesW       (GDI32.@)
749  */
750 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
751                                   FONTENUMPROCW efproc, LPARAM lpData )
752 {
753     LOGFONTW  lf;
754
755     lf.lfCharSet = DEFAULT_CHARSET;
756     if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
757     else lf.lfFaceName[0] = 0;
758
759     return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
760 }
761
762 /***********************************************************************
763  *              EnumFonts               (GDI.70)
764  */
765 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
766                           LPARAM lpData )
767 {
768     return EnumFontFamilies16( hDC, lpName, efproc, lpData );
769 }
770
771 /***********************************************************************
772  *              EnumFontsA              (GDI32.@)
773  */
774 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
775                            LPARAM lpData )
776 {
777     return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
778 }
779
780 /***********************************************************************
781  *              EnumFontsW              (GDI32.@)
782  */
783 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
784                            LPARAM lpData )
785 {
786     return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
787 }
788
789
790 /***********************************************************************
791  *           GetTextCharacterExtra    (GDI32.@)
792  */
793 INT WINAPI GetTextCharacterExtra( HDC hdc )
794 {
795     INT ret;
796     DC *dc = DC_GetDCPtr( hdc );
797     if (!dc) return 0x80000000;
798     ret = dc->charExtra;
799     GDI_ReleaseObj( hdc );
800     return ret;
801 }
802
803
804 /***********************************************************************
805  *           SetTextCharacterExtra    (GDI32.@)
806  */
807 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
808 {
809     INT prev;
810     DC * dc = DC_GetDCPtr( hdc );
811     if (!dc) return 0x80000000;
812     if (dc->funcs->pSetTextCharacterExtra)
813         prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
814     else
815     {
816         prev = dc->charExtra;
817         dc->charExtra = extra;
818     }
819     GDI_ReleaseObj( hdc );
820     return prev;
821 }
822
823
824 /***********************************************************************
825  *           SetTextJustification    (GDI32.@)
826  */
827 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
828 {
829     BOOL ret = TRUE;
830     DC * dc = DC_GetDCPtr( hdc );
831     if (!dc) return FALSE;
832     if (dc->funcs->pSetTextJustification)
833         ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
834     else
835     {
836         extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
837         if (!extra) breaks = 0;
838         dc->breakTotalExtra = extra;
839         dc->breakCount = breaks;
840         if (breaks)
841         {
842             dc->breakExtra = extra / breaks;
843             dc->breakRem   = extra - (dc->breakCount * dc->breakExtra);
844         }
845         else
846         {
847             dc->breakExtra = 0;
848             dc->breakRem   = 0;
849         }
850     }
851     GDI_ReleaseObj( hdc );
852     return ret;
853 }
854
855
856 /***********************************************************************
857  *           GetTextFaceA    (GDI32.@)
858  */
859 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
860 {
861     INT res = GetTextFaceW(hdc, 0, NULL);
862     LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
863     GetTextFaceW( hdc, res, nameW );
864
865     if (name)
866     {
867         if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
868             name[count-1] = 0;
869         res = strlen(name);
870     }
871     else
872         res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
873     HeapFree( GetProcessHeap(), 0, nameW );
874     return res;
875 }
876
877 /***********************************************************************
878  *           GetTextFaceW    (GDI32.@)
879  */
880 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
881 {
882     FONTOBJ *font;
883     INT     ret = 0;
884
885     DC * dc = DC_GetDCPtr( hdc );
886     if (!dc) return 0;
887
888     if(dc->gdiFont)
889         ret = WineEngGetTextFace(dc->gdiFont, count, name);
890     else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
891     {
892         if (name)
893         {
894             lstrcpynW( name, font->logfont.lfFaceName, count );
895             ret = strlenW(name);
896         }
897         else ret = strlenW(font->logfont.lfFaceName) + 1;
898         GDI_ReleaseObj( dc->hFont );
899     }
900     GDI_ReleaseObj( hdc );
901     return ret;
902 }
903
904
905 /***********************************************************************
906  *           GetTextExtentPoint32A    (GDI32.@)
907  */
908 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
909                                      LPSIZE size )
910 {
911     BOOL ret = FALSE;
912     INT wlen;
913     LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
914
915     if (p) {
916         ret = GetTextExtentPoint32W( hdc, p, wlen, size );
917         HeapFree( GetProcessHeap(), 0, p );
918     }
919
920     TRACE("(%p %s %d %p): returning %ld x %ld\n",
921           hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
922     return ret;
923 }
924
925
926 /***********************************************************************
927  * GetTextExtentPoint32W [GDI32.@]  Computes width/height for a string
928  *
929  * Computes width and height of the specified string.
930  *
931  * RETURNS
932  *    Success: TRUE
933  *    Failure: FALSE
934  */
935 BOOL WINAPI GetTextExtentPoint32W(
936     HDC hdc,     /* [in]  Handle of device context */
937     LPCWSTR str,   /* [in]  Address of text string */
938     INT count,   /* [in]  Number of characters in string */
939     LPSIZE size) /* [out] Address of structure for string size */
940 {
941     BOOL ret = FALSE;
942     DC * dc = DC_GetDCPtr( hdc );
943     if (!dc) return FALSE;
944
945     if(dc->gdiFont) {
946         ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
947         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
948         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
949     }
950     else if(dc->funcs->pGetTextExtentPoint)
951         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
952
953     GDI_ReleaseObj( hdc );
954
955     TRACE("(%p %s %d %p): returning %ld x %ld\n",
956           hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
957     return ret;
958 }
959
960 /***********************************************************************
961  * GetTextExtentPointI [GDI32.@]
962  *
963  * Computes width and height of the array of glyph indices.
964  *
965  * RETURNS
966  *    Success: TRUE
967  *    Failure: FALSE
968  */
969 BOOL WINAPI GetTextExtentPointI(
970     HDC hdc,     /* [in]  Handle of device context */
971     const WORD *indices,   /* [in]  Address of glyph index array */
972     INT count,   /* [in]  Number of glyphs in array */
973     LPSIZE size) /* [out] Address of structure for string size */
974 {
975     BOOL ret = FALSE;
976     DC * dc = DC_GetDCPtr( hdc );
977     if (!dc) return FALSE;
978
979     if(dc->gdiFont) {
980         ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
981         size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
982         size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
983     }
984     else if(dc->funcs->pGetTextExtentPoint) {
985         FIXME("calling GetTextExtentPoint\n");
986         ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
987     }
988
989     GDI_ReleaseObj( hdc );
990
991     TRACE("(%p %p %d %p): returning %ld x %ld\n",
992           hdc, indices, count, size, size->cx, size->cy );
993     return ret;
994 }
995
996
997 /***********************************************************************
998  *           GetTextExtentPointA    (GDI32.@)
999  */
1000 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1001                                           LPSIZE size )
1002 {
1003     TRACE("not bug compatible.\n");
1004     return GetTextExtentPoint32A( hdc, str, count, size );
1005 }
1006
1007 /***********************************************************************
1008  *           GetTextExtentPointW   (GDI32.@)
1009  */
1010 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1011                                           LPSIZE size )
1012 {
1013     TRACE("not bug compatible.\n");
1014     return GetTextExtentPoint32W( hdc, str, count, size );
1015 }
1016
1017
1018 /***********************************************************************
1019  *           GetTextExtentExPointA    (GDI32.@)
1020  */
1021 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1022                                    INT maxExt, LPINT lpnFit,
1023                                    LPINT alpDx, LPSIZE size )
1024 {
1025     BOOL ret;
1026     INT wlen;
1027     LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1028     ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1029     HeapFree( GetProcessHeap(), 0, p );
1030     return ret;
1031 }
1032
1033
1034 /***********************************************************************
1035  *           GetTextExtentExPointW    (GDI32.@)
1036  *
1037  * Return the size of the string as it would be if it was output properly by
1038  * e.g. TextOut.
1039  *
1040  * This should include
1041  * - Intercharacter spacing
1042  * - justification spacing (not yet done)
1043  * - kerning? see below
1044  *
1045  * Kerning.  Since kerning would be carried out by the rendering code it should
1046  * be done by the driver.  However they don't support it yet.  Also I am not
1047  * yet persuaded that (certainly under Win95) any kerning is actually done.
1048  *
1049  * str: According to MSDN this should be null-terminated.  That is not true; a
1050  *      null will not terminate it early.
1051  * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1052  *       than count.  I have seen it be either the size of the full string or
1053  *       1 less than the size of the full string.  I have not seen it bear any
1054  *       resemblance to the portion that would fit.
1055  * lpnFit: What exactly is fitting?  Stupidly, in my opinion, it includes the
1056  *         trailing intercharacter spacing and any trailing justification.
1057  *
1058  * FIXME
1059  * Currently we do this by measuring each character etc.  We should do it by
1060  * passing the request to the driver, perhaps by extending the
1061  * pGetTextExtentPoint function to take the alpDx argument.  That would avoid
1062  * thinking about kerning issues and rounding issues in the justification.
1063  */
1064
1065 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1066                                    INT maxExt, LPINT lpnFit,
1067                                    LPINT alpDx, LPSIZE size )
1068 {
1069     int index, nFit, extent;
1070     SIZE tSize;
1071     BOOL ret = FALSE;
1072
1073     TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1074
1075     size->cx = size->cy = nFit = extent = 0;
1076     for(index = 0; index < count; index++)
1077     {
1078         if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1079         /* GetTextExtentPoint includes intercharacter spacing. */
1080         /* FIXME - justification needs doing yet.  Remember that the base
1081          * data will not be in logical coordinates.
1082          */
1083         extent += tSize.cx;
1084         if( !lpnFit || extent <= maxExt )
1085         /* It is allowed to be equal. */
1086         {
1087             nFit++;
1088             if( alpDx ) alpDx[index] = extent;
1089         }
1090         if( tSize.cy > size->cy ) size->cy = tSize.cy;
1091         str++;
1092     }
1093     size->cx = extent;
1094     if(lpnFit) *lpnFit = nFit;
1095     ret = TRUE;
1096
1097     TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1098
1099 done:
1100     return ret;
1101 }
1102
1103 /***********************************************************************
1104  *           GetTextMetricsA    (GDI32.@)
1105  */
1106 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1107 {
1108     TEXTMETRICW tm32;
1109
1110     if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1111     FONT_TextMetricWToA( &tm32, metrics );
1112     return TRUE;
1113 }
1114
1115 /***********************************************************************
1116  *           GetTextMetricsW    (GDI32.@)
1117  */
1118 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1119 {
1120     BOOL ret = FALSE;
1121     DC * dc = DC_GetDCPtr( hdc );
1122     if (!dc) return FALSE;
1123
1124     if (dc->gdiFont)
1125         ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1126     else if (dc->funcs->pGetTextMetrics)
1127         ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1128
1129     if (ret)
1130     {
1131     /* device layer returns values in device units
1132      * therefore we have to convert them to logical */
1133
1134 #define WDPTOLP(x) ((x<0)?                                      \
1135                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1136                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1137 #define HDPTOLP(y) ((y<0)?                                      \
1138                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1139                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1140
1141     metrics->tmHeight           = HDPTOLP(metrics->tmHeight);
1142     metrics->tmAscent           = HDPTOLP(metrics->tmAscent);
1143     metrics->tmDescent          = HDPTOLP(metrics->tmDescent);
1144     metrics->tmInternalLeading  = HDPTOLP(metrics->tmInternalLeading);
1145     metrics->tmExternalLeading  = HDPTOLP(metrics->tmExternalLeading);
1146     metrics->tmAveCharWidth     = WDPTOLP(metrics->tmAveCharWidth);
1147     metrics->tmMaxCharWidth     = WDPTOLP(metrics->tmMaxCharWidth);
1148     metrics->tmOverhang         = WDPTOLP(metrics->tmOverhang);
1149         ret = TRUE;
1150 #undef WDPTOLP
1151 #undef HDPTOLP
1152     TRACE("text metrics:\n"
1153           "    Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1154           "    Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1155           "    UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1156           "    StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1157           "    PitchAndFamily = %02x\n"
1158           "    --------------------\n"
1159           "    InternalLeading = %li\n"
1160           "    Ascent = %li\n"
1161           "    Descent = %li\n"
1162           "    Height = %li\n",
1163           metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1164           metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1165           metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1166           metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1167           metrics->tmPitchAndFamily,
1168           metrics->tmInternalLeading,
1169           metrics->tmAscent,
1170           metrics->tmDescent,
1171           metrics->tmHeight );
1172     }
1173     GDI_ReleaseObj( hdc );
1174     return ret;
1175 }
1176
1177
1178 /***********************************************************************
1179  * GetOutlineTextMetrics [GDI.308]  Gets metrics for TrueType fonts.
1180  *
1181  * NOTES
1182  *    lpOTM should be LPOUTLINETEXTMETRIC
1183  *
1184  * RETURNS
1185  *    Success: Non-zero or size of required buffer
1186  *    Failure: 0
1187  */
1188 UINT16 WINAPI GetOutlineTextMetrics16(
1189     HDC16 hdc,    /* [in]  Handle of device context */
1190     UINT16 cbData, /* [in]  Size of metric data array */
1191     LPOUTLINETEXTMETRIC16 lpOTM)  /* [out] Address of metric data array */
1192 {
1193     FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1194     return 0;
1195 }
1196
1197
1198 /***********************************************************************
1199  *              GetOutlineTextMetricsA (GDI32.@)
1200  * Gets metrics for TrueType fonts.
1201  *
1202  *
1203  * RETURNS
1204  *    Success: Non-zero or size of required buffer
1205  *    Failure: 0
1206  */
1207 UINT WINAPI GetOutlineTextMetricsA(
1208     HDC hdc,    /* [in]  Handle of device context */
1209     UINT cbData, /* [in]  Size of metric data array */
1210     LPOUTLINETEXTMETRICA lpOTM)  /* [out] Address of metric data array */
1211 {
1212     char buf[512], *ptr;
1213     UINT ret, needed;
1214     OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1215     INT left, len;
1216
1217     if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
1218         if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1219             return 0;
1220         lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1221         GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1222     }
1223
1224     needed = sizeof(OUTLINETEXTMETRICA);
1225     if(lpOTMW->otmpFamilyName)
1226         needed += WideCharToMultiByte(CP_ACP, 0,
1227            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1228                                       NULL, 0, NULL, NULL);
1229     if(lpOTMW->otmpFaceName)
1230         needed += WideCharToMultiByte(CP_ACP, 0,
1231            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1232                                       NULL, 0, NULL, NULL);
1233     if(lpOTMW->otmpStyleName)
1234         needed += WideCharToMultiByte(CP_ACP, 0,
1235            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1236                                       NULL, 0, NULL, NULL);
1237     if(lpOTMW->otmpFullName)
1238         needed += WideCharToMultiByte(CP_ACP, 0,
1239            (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1240                                       NULL, 0, NULL, NULL);
1241
1242     if(!lpOTM) {
1243         ret = needed;
1244         goto end;
1245     }
1246
1247     if(needed > cbData) {
1248         ret = 0;
1249         goto end;
1250     }
1251
1252
1253     lpOTM->otmSize = needed;
1254     FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
1255     lpOTM->otmFiller = 0;
1256     lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1257     lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
1258     lpOTM->otmfsType = lpOTMW->otmfsType;
1259     lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1260     lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1261     lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
1262     lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
1263     lpOTM->otmAscent = lpOTMW->otmAscent;
1264     lpOTM->otmDescent = lpOTMW->otmDescent;
1265     lpOTM->otmLineGap = lpOTMW->otmLineGap;
1266     lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1267     lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
1268     lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
1269     lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
1270     lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
1271     lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
1272     lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1273     lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1274     lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1275     lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1276     lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1277     lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1278     lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1279     lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1280     lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1281
1282
1283     ptr = (char*)(lpOTM + 1);
1284     left = needed - sizeof(*lpOTM);
1285
1286     if(lpOTMW->otmpFamilyName) {
1287         lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
1288         len = WideCharToMultiByte(CP_ACP, 0,
1289              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1290                                   ptr, left, NULL, NULL);
1291         left -= len;
1292         ptr += len;
1293     } else
1294         lpOTM->otmpFamilyName = 0;
1295
1296     if(lpOTMW->otmpFaceName) {
1297         lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
1298         len = WideCharToMultiByte(CP_ACP, 0,
1299              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1300                                   ptr, left, NULL, NULL);
1301         left -= len;
1302         ptr += len;
1303     } else
1304         lpOTM->otmpFaceName = 0;
1305
1306     if(lpOTMW->otmpStyleName) {
1307         lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
1308         len = WideCharToMultiByte(CP_ACP, 0,
1309              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1310                                   ptr, left, NULL, NULL);
1311         left -= len;
1312         ptr += len;
1313     } else
1314         lpOTM->otmpStyleName = 0;
1315
1316     if(lpOTMW->otmpFullName) {
1317         lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
1318         len = WideCharToMultiByte(CP_ACP, 0,
1319              (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1320                                   ptr, left, NULL, NULL);
1321         left -= len;
1322     } else
1323         lpOTM->otmpFullName = 0;
1324
1325     assert(left == 0);
1326
1327     ret = needed;
1328
1329 end:
1330     if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1331         HeapFree(GetProcessHeap(), 0, lpOTMW);
1332
1333     return ret;
1334 }
1335
1336
1337 /***********************************************************************
1338  *           GetOutlineTextMetricsW [GDI32.@]
1339  */
1340 UINT WINAPI GetOutlineTextMetricsW(
1341     HDC hdc,    /* [in]  Handle of device context */
1342     UINT cbData, /* [in]  Size of metric data array */
1343     LPOUTLINETEXTMETRICW lpOTM)  /* [out] Address of metric data array */
1344 {
1345     DC *dc = DC_GetDCPtr( hdc );
1346     UINT ret;
1347
1348     TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1349     if(!dc) return 0;
1350
1351     if(dc->gdiFont) {
1352         ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
1353         if(ret && ret <= cbData) {
1354 #define WDPTOLP(x) ((x<0)?                                      \
1355                 (-abs(INTERNAL_XDSTOWS(dc, (x)))):              \
1356                 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1357 #define HDPTOLP(y) ((y<0)?                                      \
1358                 (-abs(INTERNAL_YDSTOWS(dc, (y)))):              \
1359                 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1360
1361             lpOTM->otmTextMetrics.tmHeight           = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
1362             lpOTM->otmTextMetrics.tmAscent           = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
1363             lpOTM->otmTextMetrics.tmDescent          = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
1364             lpOTM->otmTextMetrics.tmInternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
1365             lpOTM->otmTextMetrics.tmExternalLeading  = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
1366             lpOTM->otmTextMetrics.tmAveCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
1367             lpOTM->otmTextMetrics.tmMaxCharWidth     = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
1368             lpOTM->otmTextMetrics.tmOverhang         = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
1369             lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
1370             lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
1371             lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
1372             lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
1373             lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
1374             lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
1375             lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
1376             lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
1377             lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
1378             lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
1379             lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
1380             lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
1381             lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
1382             lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
1383             lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
1384             lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
1385             lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
1386             lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
1387             lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
1388             lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
1389             lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
1390             lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
1391             lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
1392             lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
1393 #undef WDPTOLP
1394 #undef HDPTOLP
1395         }
1396     }
1397
1398     else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1399               but really this should just be a return 0. */
1400
1401         ret = sizeof(*lpOTM);
1402         if (lpOTM) {
1403             if(cbData < ret)
1404                 ret = 0;
1405             else {
1406                 memset(lpOTM, 0, ret);
1407                 lpOTM->otmSize = sizeof(*lpOTM);
1408                 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1409                 /*
1410                   Further fill of the structure not implemented,
1411                   Needs real values for the structure members
1412                 */
1413             }
1414         }
1415     }
1416     GDI_ReleaseObj(hdc);
1417     return ret;
1418 }
1419
1420
1421 /***********************************************************************
1422  *           GetCharWidthW      (GDI32.@)
1423  *           GetCharWidth32W    (GDI32.@)
1424  */
1425 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1426                                LPINT buffer )
1427 {
1428     UINT i;
1429     BOOL ret = FALSE;
1430     DC * dc = DC_GetDCPtr( hdc );
1431     if (!dc) return FALSE;
1432
1433     if (dc->gdiFont)
1434         ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1435     else if (dc->funcs->pGetCharWidth)
1436         ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1437
1438     if (ret)
1439     {
1440         /* convert device units to logical */
1441         for( i = firstChar; i <= lastChar; i++, buffer++ )
1442             *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1443         ret = TRUE;
1444     }
1445     GDI_ReleaseObj( hdc );
1446     return ret;
1447 }
1448
1449
1450 /***********************************************************************
1451  *           GetCharWidthA      (GDI32.@)
1452  *           GetCharWidth32A    (GDI32.@)
1453  */
1454 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1455                                LPINT buffer )
1456 {
1457     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1458     LPSTR str;
1459     LPWSTR wstr;
1460     BOOL ret = TRUE;
1461
1462     if(count <= 0) return FALSE;
1463
1464     str = HeapAlloc(GetProcessHeap(), 0, count);
1465     for(i = 0; i < count; i++)
1466         str[i] = (BYTE)(firstChar + i);
1467
1468     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1469
1470     for(i = 0; i < wlen; i++)
1471     {
1472         if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1473         {
1474             ret = FALSE;
1475             break;
1476         }
1477         buffer++;
1478     }
1479
1480     HeapFree(GetProcessHeap(), 0, str);
1481     HeapFree(GetProcessHeap(), 0, wstr);
1482
1483     return ret;
1484 }
1485
1486
1487 /* FIXME: all following APIs ******************************************/
1488
1489
1490 /***********************************************************************
1491  *           SetMapperFlags    (GDI32.@)
1492  */
1493 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1494 {
1495     DC *dc = DC_GetDCPtr( hDC );
1496     DWORD ret = 0;
1497     if(!dc) return 0;
1498     if(dc->funcs->pSetMapperFlags)
1499         ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1500     else
1501         FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1502     GDI_ReleaseObj( hDC );
1503     return ret;
1504 }
1505
1506 /***********************************************************************
1507  *          GetAspectRatioFilterEx  (GDI.486)
1508  */
1509 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1510 {
1511   FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1512   return FALSE;
1513 }
1514
1515 /***********************************************************************
1516  *          GetAspectRatioFilterEx  (GDI32.@)
1517  */
1518 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1519 {
1520   FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1521   return FALSE;
1522 }
1523
1524
1525 /***********************************************************************
1526  *           GetCharABCWidthsA   (GDI32.@)
1527  */
1528 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1529                                   LPABC abc )
1530 {
1531     INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1532     LPSTR str;
1533     LPWSTR wstr;
1534     BOOL ret = TRUE;
1535
1536     if(count <= 0) return FALSE;
1537
1538     str = HeapAlloc(GetProcessHeap(), 0, count);
1539     for(i = 0; i < count; i++)
1540         str[i] = (BYTE)(firstChar + i);
1541
1542     wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1543
1544     for(i = 0; i < wlen; i++)
1545     {
1546         if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1547         {
1548             ret = FALSE;
1549             break;
1550         }
1551         abc++;
1552     }
1553
1554     HeapFree(GetProcessHeap(), 0, str);
1555     HeapFree(GetProcessHeap(), 0, wstr);
1556
1557     return ret;
1558 }
1559
1560
1561 /******************************************************************************
1562  * GetCharABCWidthsW [GDI32.@]  Retrieves widths of characters in range
1563  *
1564  * PARAMS
1565  *    hdc       [I] Handle of device context
1566  *    firstChar [I] First character in range to query
1567  *    lastChar  [I] Last character in range to query
1568  *    abc       [O] Address of character-width structure
1569  *
1570  * NOTES
1571  *    Only works with TrueType fonts
1572  *
1573  * RETURNS
1574  *    Success: TRUE
1575  *    Failure: FALSE
1576  */
1577 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1578                                    LPABC abc )
1579 {
1580     DC *dc = DC_GetDCPtr(hdc);
1581     int         i;
1582     GLYPHMETRICS gm;
1583     BOOL ret = FALSE;
1584
1585     if(dc->gdiFont) {
1586         for (i=firstChar;i<=lastChar;i++) {
1587             GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1588             abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1589             abc[i-firstChar].abcB = gm.gmBlackBoxX;
1590             abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1591         }
1592         ret = TRUE;
1593     }
1594     GDI_ReleaseObj(hdc);
1595     return ret;
1596 }
1597
1598
1599 /***********************************************************************
1600  *           GetGlyphOutline    (GDI.309)
1601  */
1602 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1603                                 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1604                                 LPVOID lpBuffer, const MAT2 *lpmat2 )
1605 {
1606     FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1607           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1608     return (DWORD)-1; /* failure */
1609 }
1610
1611
1612 /***********************************************************************
1613  *           GetGlyphOutlineA    (GDI32.@)
1614  */
1615 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1616                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1617                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1618 {
1619     LPWSTR p = NULL;
1620     DWORD ret;
1621     UINT c;
1622
1623     if(!(fuFormat & GGO_GLYPH_INDEX)) {
1624         p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1625         c = p[0];
1626     } else
1627         c = uChar;
1628     ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1629                            lpmat2);
1630     if(p)
1631         HeapFree(GetProcessHeap(), 0, p);
1632     return ret;
1633 }
1634
1635 /***********************************************************************
1636  *           GetGlyphOutlineW    (GDI32.@)
1637  */
1638 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1639                                  LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1640                                  LPVOID lpBuffer, const MAT2 *lpmat2 )
1641 {
1642     DC *dc = DC_GetDCPtr(hdc);
1643     DWORD ret;
1644
1645     TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1646           hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1647
1648     if(!dc) return GDI_ERROR;
1649
1650     if(dc->gdiFont)
1651       ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1652                                    cbBuffer, lpBuffer, lpmat2);
1653     else
1654       ret = GDI_ERROR;
1655
1656     GDI_ReleaseObj(hdc);
1657     return ret;
1658 }
1659
1660
1661 /***********************************************************************
1662  *           CreateScalableFontResourceA   (GDI32.@)
1663  */
1664 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1665                                              LPCSTR lpszResourceFile,
1666                                              LPCSTR lpszFontFile,
1667                                              LPCSTR lpszCurrentPath )
1668 {
1669     HANDLE f;
1670
1671     /* fHidden=1 - only visible for the calling app, read-only, not
1672      * enumbered with EnumFonts/EnumFontFamilies
1673      * lpszCurrentPath can be NULL
1674      */
1675     FIXME("(%ld,%s,%s,%s): stub\n",
1676           fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1677           debugstr_a(lpszCurrentPath) );
1678
1679     /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1680     if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1681         CloseHandle(f);
1682         SetLastError(ERROR_FILE_EXISTS);
1683         return FALSE;
1684     }
1685     return FALSE; /* create failed */
1686 }
1687
1688 /***********************************************************************
1689  *           CreateScalableFontResourceW   (GDI32.@)
1690  */
1691 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1692                                              LPCWSTR lpszResourceFile,
1693                                              LPCWSTR lpszFontFile,
1694                                              LPCWSTR lpszCurrentPath )
1695 {
1696     FIXME("(%ld,%p,%p,%p): stub\n",
1697           fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1698     return FALSE; /* create failed */
1699 }
1700
1701
1702 /*************************************************************************
1703  *             GetRasterizerCaps   (GDI32.@)
1704  */
1705 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1706 {
1707   lprs->nSize = sizeof(RASTERIZER_STATUS);
1708   lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1709   lprs->nLanguageID = 0;
1710   return TRUE;
1711 }
1712
1713
1714 /*************************************************************************
1715  *             GetKerningPairsA   (GDI32.@)
1716  */
1717 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1718                                LPKERNINGPAIR lpKerningPairs )
1719 {
1720     return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1721 }
1722
1723
1724 /*************************************************************************
1725  *             GetKerningPairsW   (GDI32.@)
1726  */
1727 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1728                                  LPKERNINGPAIR lpKerningPairs )
1729 {
1730     int i;
1731     FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1732     for (i = 0; i < cPairs; i++)
1733         lpKerningPairs[i].iKernAmount = 0;
1734     return 0;
1735 }
1736
1737 /*************************************************************************
1738  * TranslateCharsetInfo [GDI32.@]
1739  *
1740  * Fills a CHARSETINFO structure for a character set, code page, or
1741  * font. This allows making the correspondance between different labelings
1742  * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1743  * of the same encoding.
1744  *
1745  * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1746  * only one codepage should be set in *lpSrc.
1747  *
1748  * RETURNS
1749  *   TRUE on success, FALSE on failure.
1750  *
1751  */
1752 BOOL WINAPI TranslateCharsetInfo(
1753   LPDWORD lpSrc, /* [in]
1754        if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1755        if flags == TCI_SRCCHARSET: a character set value
1756        if flags == TCI_SRCCODEPAGE: a code page value
1757                  */
1758   LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1759   DWORD flags /* [in] determines interpretation of lpSrc */
1760 ) {
1761     int index = 0;
1762     switch (flags) {
1763     case TCI_SRCFONTSIG:
1764         while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1765       break;
1766     case TCI_SRCCODEPAGE:
1767       while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1768       break;
1769     case TCI_SRCCHARSET:
1770       while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1771       break;
1772     default:
1773       return FALSE;
1774     }
1775     if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1776     memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1777     return TRUE;
1778 }
1779
1780 /*************************************************************************
1781  *             GetFontLanguageInfo   (GDI32.@)
1782  */
1783 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1784 {
1785         FONTSIGNATURE fontsig;
1786         static const DWORD GCP_DBCS_MASK=0x003F0000,
1787                 GCP_DIACRITIC_MASK=0x00000000,
1788                 FLI_GLYPHS_MASK=0x00000000,
1789                 GCP_GLYPHSHAPE_MASK=0x00000040,
1790                 GCP_KASHIDA_MASK=0x00000000,
1791                 GCP_LIGATE_MASK=0x00000000,
1792                 GCP_USEKERNING_MASK=0x00000000,
1793                 GCP_REORDER_MASK=0x00000060;
1794
1795         DWORD result=0;
1796
1797         GetTextCharsetInfo( hdc, &fontsig, 0 );
1798         /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1799
1800         if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1801                 result|=GCP_DBCS;
1802
1803         if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1804                 result|=GCP_DIACRITIC;
1805
1806         if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1807                 result|=FLI_GLYPHS;
1808
1809         if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1810                 result|=GCP_GLYPHSHAPE;
1811
1812         if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1813                 result|=GCP_KASHIDA;
1814
1815         if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1816                 result|=GCP_LIGATE;
1817
1818         if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1819                 result|=GCP_USEKERNING;
1820
1821         if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1822                 result|=GCP_REORDER;
1823
1824         return result;
1825 }
1826
1827
1828 /*************************************************************************
1829  * GetFontData [GDI32.@] Retrieve data for TrueType font
1830  *
1831  * RETURNS
1832  *
1833  * success: Number of bytes returned
1834  * failure: GDI_ERROR
1835  *
1836  * NOTES
1837  *
1838  * Calls SetLastError()
1839  *
1840  */
1841 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1842     LPVOID buffer, DWORD length)
1843 {
1844     DC *dc = DC_GetDCPtr(hdc);
1845     DWORD ret = GDI_ERROR;
1846
1847     if(!dc) return GDI_ERROR;
1848
1849     if(dc->gdiFont)
1850       ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1851
1852     GDI_ReleaseObj(hdc);
1853     return ret;
1854 }
1855
1856 /*************************************************************************
1857  * GetGlyphIndicesA [GDI32.@]
1858  */
1859 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1860                               LPWORD pgi, DWORD flags)
1861 {
1862     DWORD ret;
1863     WCHAR *lpstrW;
1864     INT countW;
1865
1866     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1867           hdc, debugstr_an(lpstr, count), count, pgi, flags);
1868
1869     lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1870     ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1871     HeapFree(GetProcessHeap(), 0, lpstrW);
1872
1873     return ret;
1874 }
1875
1876 /*************************************************************************
1877  * GetGlyphIndicesW [GDI32.@]
1878  */
1879 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1880                               LPWORD pgi, DWORD flags)
1881 {
1882     DC *dc = DC_GetDCPtr(hdc);
1883     DWORD ret = GDI_ERROR;
1884
1885     TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1886           hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1887
1888     if(!dc) return GDI_ERROR;
1889
1890     if(dc->gdiFont)
1891         ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1892
1893     GDI_ReleaseObj(hdc);
1894     return ret;
1895 }
1896
1897 /*************************************************************************
1898  * GetCharacterPlacementA [GDI32.@]
1899  *
1900  * NOTES:
1901  *  the web browser control of ie4 calls this with dwFlags=0
1902  */
1903 DWORD WINAPI
1904 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1905                          INT nMaxExtent, GCP_RESULTSA *lpResults,
1906                          DWORD dwFlags)
1907 {
1908     WCHAR *lpStringW;
1909     INT uCountW, i;
1910     GCP_RESULTSW resultsW;
1911     DWORD ret;
1912     UINT font_cp;
1913
1914     TRACE("%s, %d, %d, 0x%08lx\n",
1915           debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1916
1917     /* both structs are equal in size */
1918     memcpy(&resultsW, lpResults, sizeof(resultsW));
1919
1920     lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1921     if(lpResults->lpOutString)
1922         resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1923
1924     ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1925
1926     if(lpResults->lpOutString) {
1927         if(font_cp != CP_SYMBOL)
1928             WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1929                                 lpResults->lpOutString, uCount, NULL, NULL );
1930         else
1931             for(i = 0; i < uCount; i++)
1932                 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1933     }
1934
1935     HeapFree(GetProcessHeap(), 0, lpStringW);
1936     HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1937
1938     return ret;
1939 }
1940
1941 /*************************************************************************
1942  * GetCharacterPlacementW [GDI32.@]
1943  *
1944  *   Retrieve information about a string. This includes the width, reordering,
1945  *   Glyphing and so on.
1946  *
1947  * RETURNS
1948  *
1949  *   The width and height of the string if successful, 0 if failed.
1950  *
1951  * BUGS
1952  *
1953  *   All flags except GCP_REORDER are not yet implemented.
1954  *   Reordering is not 100% complient to the Windows BiDi method.
1955  *   Caret positioning is not yet implemented.
1956  *   Classes are not yet implemented.
1957  *
1958  */
1959 DWORD WINAPI
1960 GetCharacterPlacementW(
1961                 HDC hdc,                /* [in] Device context for which the rendering is to be done */
1962                 LPCWSTR lpString,       /* [in] The string for which information is to be returned */
1963                 INT uCount,             /* [in] Number of WORDS in string. */
1964                 INT nMaxExtent,         /* [in] Maximum extent the string is to take (in HDC logical units) */
1965                 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
1966                 DWORD dwFlags           /* [in] Flags specifying how to process the string */
1967                 )
1968 {
1969     DWORD ret=0;
1970     SIZE size;
1971     UINT i, nSet;
1972
1973     TRACE("%s, %d, %d, 0x%08lx\n",
1974           debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
1975
1976     TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1977           "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1978             lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
1979             lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
1980             lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
1981
1982     if(dwFlags&(~GCP_REORDER))                  FIXME("flags 0x%08lx ignored\n", dwFlags);
1983     if(lpResults->lpCaretPos)   FIXME("caret positions not implemented\n");
1984     if(lpResults->lpClass)      FIXME("classes not implemented\n");
1985
1986         nSet = (UINT)uCount;
1987         if(nSet > lpResults->nGlyphs)
1988                 nSet = lpResults->nGlyphs;
1989
1990         /* return number of initialized fields */
1991         lpResults->nGlyphs = nSet;
1992
1993         if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
1994         {
1995                 /* Treat the case where no special handling was requested in a fastpath way */
1996                 /* copy will do if the GCP_REORDER flag is not set */
1997                 if(lpResults->lpOutString)
1998                     strncpyW( lpResults->lpOutString, lpString, nSet );
1999
2000                 if(lpResults->lpOrder)
2001                 {
2002                         for(i = 0; i < nSet; i++)
2003                                 lpResults->lpOrder[i] = i;
2004                 }
2005         } else
2006         {
2007             BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2008                           nSet, lpResults->lpOrder );
2009         }
2010
2011         /* FIXME: Will use the placement chars */
2012         if (lpResults->lpDx)
2013         {
2014                 int c;
2015                 for (i = 0; i < nSet; i++)
2016                 {
2017                         if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2018                                 lpResults->lpDx[i]= c;
2019                 }
2020         }
2021
2022     if(lpResults->lpGlyphs)
2023         GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2024
2025     if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2026       ret = MAKELONG(size.cx, size.cy);
2027
2028     return ret;
2029 }
2030
2031 /*************************************************************************
2032  *      GetCharABCWidthsFloatA [GDI32.@]
2033  */
2034 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2035                                         LPABCFLOAT lpABCF)
2036 {
2037        FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2038        return 0;
2039 }
2040
2041 /*************************************************************************
2042  *      GetCharABCWidthsFloatW [GDI32.@]
2043  */
2044 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2045                                         UINT iLastChar, LPABCFLOAT lpABCF)
2046 {
2047        FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2048        return 0;
2049 }
2050
2051 /*************************************************************************
2052  *      GetCharWidthFloatA [GDI32.@]
2053  */
2054 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2055                                     UINT iLastChar, PFLOAT pxBuffer)
2056 {
2057        FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2058        return 0;
2059 }
2060
2061 /*************************************************************************
2062  *      GetCharWidthFloatW [GDI32.@]
2063  */
2064 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2065                                     UINT iLastChar, PFLOAT pxBuffer)
2066 {
2067        FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2068        return 0;
2069 }
2070
2071
2072 /***********************************************************************
2073  *                                                                     *
2074  *           Font Resource API                                         *
2075  *                                                                     *
2076  ***********************************************************************/
2077
2078 /***********************************************************************
2079  *           AddFontResourceA    (GDI32.@)
2080  */
2081 INT WINAPI AddFontResourceA( LPCSTR str )
2082 {
2083     return AddFontResourceExA( str, 0, NULL);
2084 }
2085
2086 /***********************************************************************
2087  *           AddFontResourceW    (GDI32.@)
2088  */
2089 INT WINAPI AddFontResourceW( LPCWSTR str )
2090 {
2091     return AddFontResourceExW(str, 0, NULL);
2092 }
2093
2094
2095 /***********************************************************************
2096  *           AddFontResourceExA    (GDI32.@)
2097  */
2098 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2099 {
2100     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2101     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2102     INT ret;
2103
2104     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2105     ret = AddFontResourceExW(strW, fl, pdv);
2106     HeapFree(GetProcessHeap(), 0, strW);
2107     return ret;
2108 }
2109
2110 /***********************************************************************
2111  *           AddFontResourceExW    (GDI32.@)
2112  */
2113 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2114 {
2115     return WineEngAddFontResourceEx(str, fl, pdv);
2116 }
2117
2118 /***********************************************************************
2119  *           RemoveFontResourceA    (GDI32.@)
2120  */
2121 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2122 {
2123     return RemoveFontResourceExA(str, 0, 0);
2124 }
2125
2126 /***********************************************************************
2127  *           RemoveFontResourceW    (GDI32.@)
2128  */
2129 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2130 {
2131     return RemoveFontResourceExW(str, 0, 0);
2132 }
2133
2134 /***********************************************************************
2135  *           RemoveFontResourceExA    (GDI32.@)
2136  */
2137 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2138 {
2139     DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2140     LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2141     INT ret;
2142
2143     MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2144     ret = RemoveFontResourceExW(strW, fl, pdv);
2145     HeapFree(GetProcessHeap(), 0, strW);
2146     return ret;
2147 }
2148
2149 /***********************************************************************
2150  *           RemoveFontResourceExW    (GDI32.@)
2151  */
2152 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2153 {
2154     return WineEngRemoveFontResourceEx(str, fl, pdv);
2155 }
2156
2157 /***********************************************************************
2158  *           GetTextCharset    (GDI32.@)
2159  */
2160 UINT WINAPI GetTextCharset(HDC hdc)
2161 {
2162     /* MSDN docs say this is equivalent */
2163     return GetTextCharsetInfo(hdc, NULL, 0);
2164 }
2165
2166 /***********************************************************************
2167  *           GetTextCharsetInfo    (GDI32.@)
2168  */
2169 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2170 {
2171     UINT ret = DEFAULT_CHARSET;
2172     DC *dc = DC_GetDCPtr(hdc);
2173
2174     if (!dc) goto done;
2175
2176     if (dc->gdiFont)
2177         ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2178
2179     GDI_ReleaseObj(hdc);
2180
2181 done:
2182     if (ret == DEFAULT_CHARSET && fs)
2183         memset(fs, 0, sizeof(FONTSIGNATURE));
2184     return ret;
2185 }