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