Moved all files from the objects/ directory to dlls/gdi.
[wine/wine64.git] / dlls / gdi / font.c
blob4743f9d52bd1a1d7316dcb3e95f7723deb4cdcb2
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
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.
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.
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
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 FLOAT floatWidth;
52 /* Perform operation with floating point */
53 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 FLOAT floatHeight;
65 /* Perform operation with floating point */
66 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight);
72 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
73 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
74 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
75 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
76 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
78 static const struct gdi_obj_funcs font_funcs =
80 FONT_SelectObject, /* pSelectObject */
81 FONT_GetObject16, /* pGetObject16 */
82 FONT_GetObjectA, /* pGetObjectA */
83 FONT_GetObjectW, /* pGetObjectW */
84 NULL, /* pUnrealizeObject */
85 FONT_DeleteObject /* pDeleteObject */
88 #define ENUM_UNICODE 0x00000001
89 #define ENUM_CALLED 0x00000002
91 typedef struct
93 GDIOBJHDR header;
94 LOGFONTW logfont;
95 } FONTOBJ;
97 typedef struct
99 LPLOGFONT16 lpLogFontParam;
100 FONTENUMPROC16 lpEnumFunc;
101 LPARAM lpData;
103 LPNEWTEXTMETRICEX16 lpTextMetric;
104 LPENUMLOGFONTEX16 lpLogFont;
105 SEGPTR segTextMetric;
106 SEGPTR segLogFont;
107 DWORD dwFlags;
108 HDC hdc;
109 DC *dc;
110 PHYSDEV physDev;
111 } fontEnum16;
113 typedef struct
115 LPLOGFONTW lpLogFontParam;
116 FONTENUMPROCW lpEnumFunc;
117 LPARAM lpData;
118 DWORD dwFlags;
119 HDC hdc;
120 DC *dc;
121 PHYSDEV physDev;
122 } fontEnum32;
125 * For TranslateCharsetInfo
127 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
128 #define MAXTCIINDEX 32
129 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
130 /* ANSI */
131 { ANSI_CHARSET, 1252, FS(0)},
132 { EASTEUROPE_CHARSET, 1250, FS(1)},
133 { RUSSIAN_CHARSET, 1251, FS(2)},
134 { GREEK_CHARSET, 1253, FS(3)},
135 { TURKISH_CHARSET, 1254, FS(4)},
136 { HEBREW_CHARSET, 1255, FS(5)},
137 { ARABIC_CHARSET, 1256, FS(6)},
138 { BALTIC_CHARSET, 1257, FS(7)},
139 { VIETNAMESE_CHARSET, 1258, FS(8)},
140 /* reserved by ANSI */
141 { DEFAULT_CHARSET, 0, FS(0)},
142 { DEFAULT_CHARSET, 0, FS(0)},
143 { DEFAULT_CHARSET, 0, FS(0)},
144 { DEFAULT_CHARSET, 0, FS(0)},
145 { DEFAULT_CHARSET, 0, FS(0)},
146 { DEFAULT_CHARSET, 0, FS(0)},
147 { DEFAULT_CHARSET, 0, FS(0)},
148 /* ANSI and OEM */
149 { THAI_CHARSET, 874, FS(16)},
150 { SHIFTJIS_CHARSET, 932, FS(17)},
151 { GB2312_CHARSET, 936, FS(18)},
152 { HANGEUL_CHARSET, 949, FS(19)},
153 { CHINESEBIG5_CHARSET, 950, FS(20)},
154 { JOHAB_CHARSET, 1361, FS(21)},
155 /* reserved for alternate ANSI and OEM */
156 { DEFAULT_CHARSET, 0, FS(0)},
157 { DEFAULT_CHARSET, 0, FS(0)},
158 { DEFAULT_CHARSET, 0, FS(0)},
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 /* reserved for system */
165 { DEFAULT_CHARSET, 0, FS(0)},
166 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
169 /***********************************************************************
170 * LOGFONT conversion functions.
172 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
174 font16->lfHeight = font32->lfHeight;
175 font16->lfWidth = font32->lfWidth;
176 font16->lfEscapement = font32->lfEscapement;
177 font16->lfOrientation = font32->lfOrientation;
178 font16->lfWeight = font32->lfWeight;
179 font16->lfItalic = font32->lfItalic;
180 font16->lfUnderline = font32->lfUnderline;
181 font16->lfStrikeOut = font32->lfStrikeOut;
182 font16->lfCharSet = font32->lfCharSet;
183 font16->lfOutPrecision = font32->lfOutPrecision;
184 font16->lfClipPrecision = font32->lfClipPrecision;
185 font16->lfQuality = font32->lfQuality;
186 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
187 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
188 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
189 font16->lfFaceName[LF_FACESIZE-1] = 0;
192 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
194 font32->lfHeight = font16->lfHeight;
195 font32->lfWidth = font16->lfWidth;
196 font32->lfEscapement = font16->lfEscapement;
197 font32->lfOrientation = font16->lfOrientation;
198 font32->lfWeight = font16->lfWeight;
199 font32->lfItalic = font16->lfItalic;
200 font32->lfUnderline = font16->lfUnderline;
201 font32->lfStrikeOut = font16->lfStrikeOut;
202 font32->lfCharSet = font16->lfCharSet;
203 font32->lfOutPrecision = font16->lfOutPrecision;
204 font32->lfClipPrecision = font16->lfClipPrecision;
205 font32->lfQuality = font16->lfQuality;
206 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
207 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
208 font32->lfFaceName[LF_FACESIZE-1] = 0;
211 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
213 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
214 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
215 LF_FACESIZE);
218 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
220 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
221 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
222 LF_FACESIZE, NULL, NULL);
225 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
227 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
229 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
230 font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
231 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
232 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
233 font16->elfStyle, LF_FACESIZE, NULL, NULL );
234 font16->elfStyle[LF_FACESIZE-1] = '\0';
235 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
236 font16->elfScript, LF_FACESIZE, NULL, NULL );
237 font16->elfScript[LF_FACESIZE-1] = '\0';
240 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
242 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
244 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
245 fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
246 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
247 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
248 fontA->elfStyle, LF_FACESIZE, NULL, NULL );
249 fontA->elfStyle[LF_FACESIZE-1] = '\0';
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
251 fontA->elfScript, LF_FACESIZE, NULL, NULL );
252 fontA->elfScript[LF_FACESIZE-1] = '\0';
255 /***********************************************************************
256 * TEXTMETRIC conversion functions.
258 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
260 ptmA->tmHeight = ptmW->tmHeight;
261 ptmA->tmAscent = ptmW->tmAscent;
262 ptmA->tmDescent = ptmW->tmDescent;
263 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
264 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
265 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
266 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
267 ptmA->tmWeight = ptmW->tmWeight;
268 ptmA->tmOverhang = ptmW->tmOverhang;
269 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
270 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
271 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
272 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
273 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
274 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
275 ptmA->tmItalic = ptmW->tmItalic;
276 ptmA->tmUnderlined = ptmW->tmUnderlined;
277 ptmA->tmStruckOut = ptmW->tmStruckOut;
278 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
279 ptmA->tmCharSet = ptmW->tmCharSet;
283 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
285 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
286 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
287 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
288 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
289 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
290 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
291 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
292 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
293 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
294 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
295 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
296 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
297 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
298 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
299 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
300 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
301 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
302 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
303 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
304 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
305 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
306 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
307 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
308 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
309 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
312 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
314 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
315 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
316 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
317 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
318 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
319 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
323 /***********************************************************************
324 * FONT_mbtowc
326 * Returns a '\0' terminated Unicode translation of str using the
327 * charset of the currently selected font in hdc. If count is -1 then
328 * str is assumed to be '\0' terminated, otherwise it contains the
329 * number of bytes to convert. If plenW is non-NULL, on return it
330 * will point to the number of WCHARs (excluding the '\0') that have
331 * been written. If pCP is non-NULL, on return it will point to the
332 * codepage used in the conversion.
333 * The caller should free the returned LPWSTR from the process
334 * heap itself.
336 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
338 UINT cp = CP_ACP;
339 INT lenW;
340 LPWSTR strW;
341 CHARSETINFO csi;
342 int charset = GetTextCharset(hdc);
344 /* Hmm, nicely designed api this one! */
345 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
346 cp = csi.ciACP;
347 else {
348 switch(charset) {
349 case OEM_CHARSET:
350 cp = GetOEMCP();
351 break;
352 case DEFAULT_CHARSET:
353 cp = GetACP();
354 break;
356 case VISCII_CHARSET:
357 case TCVN_CHARSET:
358 case KOI8_CHARSET:
359 case ISO3_CHARSET:
360 case ISO4_CHARSET:
361 case ISO10_CHARSET:
362 case CELTIC_CHARSET:
363 /* FIXME: These have no place here, but because x11drv
364 enumerates fonts with these (made up) charsets some apps
365 might use them and then the FIXME below would become
366 annoying. Now we could pick the intended codepage for
367 each of these, but since it's broken anyway we'll just
368 use CP_ACP and hope it'll go away...
370 cp = CP_ACP;
371 break;
373 default:
374 FIXME("Can't find codepage for charset %d\n", charset);
375 break;
379 TRACE("charset %d => cp %d\n", charset, cp);
381 if(count == -1) count = strlen(str);
382 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
383 strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
384 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
385 strW[lenW] = '\0';
386 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
387 if(plenW) *plenW = lenW;
388 if(pCP) *pCP = cp;
389 return strW;
393 /***********************************************************************
394 * CreateFontIndirectA (GDI32.@)
396 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
398 LOGFONTW lfW;
400 if (plfA) {
401 FONT_LogFontAToW( plfA, &lfW );
402 return CreateFontIndirectW( &lfW );
403 } else
404 return CreateFontIndirectW( NULL );
408 /***********************************************************************
409 * CreateFontIndirectW (GDI32.@)
411 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
413 HFONT hFont = 0;
415 if (plf)
417 FONTOBJ* fontPtr;
418 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
419 (HGDIOBJ *)&hFont, &font_funcs )))
421 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
422 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
423 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
424 WCHAR* pFaceNameSuffix = NULL;
426 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
428 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
429 plf->lfHeight, plf->lfWidth,
430 plf->lfEscapement, plf->lfOrientation,
431 plf->lfPitchAndFamily,
432 plf->lfOutPrecision, plf->lfClipPrecision,
433 plf->lfQuality, plf->lfCharSet,
434 debugstr_w(plf->lfFaceName),
435 plf->lfWeight > 400 ? "Bold" : "",
436 plf->lfItalic ? "Italic" : "",
437 plf->lfUnderline ? "Underline" : "", hFont);
439 if (plf->lfEscapement != plf->lfOrientation) {
440 /* this should really depend on whether GM_ADVANCED is set */
441 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
442 WARN("orientation angle %f set to "
443 "escapement angle %f for new font %p\n",
444 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
447 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
448 if (pFaceNameItalicSuffix) {
449 fontPtr->logfont.lfItalic = TRUE;
450 pFaceNameSuffix = pFaceNameItalicSuffix;
453 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
454 if (pFaceNameBoldSuffix) {
455 if (fontPtr->logfont.lfWeight < FW_BOLD) {
456 fontPtr->logfont.lfWeight = FW_BOLD;
458 if (!pFaceNameSuffix ||
459 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
460 pFaceNameSuffix = pFaceNameBoldSuffix;
464 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
466 GDI_ReleaseObj( hFont );
469 else WARN("(NULL) => NULL\n");
471 return hFont;
474 /*************************************************************************
475 * CreateFontA (GDI32.@)
477 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
478 INT orient, INT weight, DWORD italic,
479 DWORD underline, DWORD strikeout, DWORD charset,
480 DWORD outpres, DWORD clippres, DWORD quality,
481 DWORD pitch, LPCSTR name )
483 LOGFONTA logfont;
485 logfont.lfHeight = height;
486 logfont.lfWidth = width;
487 logfont.lfEscapement = esc;
488 logfont.lfOrientation = orient;
489 logfont.lfWeight = weight;
490 logfont.lfItalic = italic;
491 logfont.lfUnderline = underline;
492 logfont.lfStrikeOut = strikeout;
493 logfont.lfCharSet = charset;
494 logfont.lfOutPrecision = outpres;
495 logfont.lfClipPrecision = clippres;
496 logfont.lfQuality = quality;
497 logfont.lfPitchAndFamily = pitch;
499 if (name)
500 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
501 else
502 logfont.lfFaceName[0] = '\0';
504 return CreateFontIndirectA( &logfont );
507 /*************************************************************************
508 * CreateFontW (GDI32.@)
510 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
511 INT orient, INT weight, DWORD italic,
512 DWORD underline, DWORD strikeout, DWORD charset,
513 DWORD outpres, DWORD clippres, DWORD quality,
514 DWORD pitch, LPCWSTR name )
516 LOGFONTW logfont;
518 logfont.lfHeight = height;
519 logfont.lfWidth = width;
520 logfont.lfEscapement = esc;
521 logfont.lfOrientation = orient;
522 logfont.lfWeight = weight;
523 logfont.lfItalic = italic;
524 logfont.lfUnderline = underline;
525 logfont.lfStrikeOut = strikeout;
526 logfont.lfCharSet = charset;
527 logfont.lfOutPrecision = outpres;
528 logfont.lfClipPrecision = clippres;
529 logfont.lfQuality = quality;
530 logfont.lfPitchAndFamily = pitch;
532 if (name)
533 lstrcpynW(logfont.lfFaceName, name,
534 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
535 else
536 logfont.lfFaceName[0] = '\0';
538 return CreateFontIndirectW( &logfont );
542 /***********************************************************************
543 * FONT_SelectObject
545 * If the driver supports vector fonts we create a gdi font first and
546 * then call the driver to give it a chance to supply its own device
547 * font. If the driver wants to do this it returns TRUE and we can
548 * delete the gdi font, if the driver wants to use the gdi font it
549 * should return FALSE, to signal an error return GDI_ERROR. For
550 * drivers that don't support vector fonts they must supply their own
551 * font.
553 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
555 HGDIOBJ ret = 0;
556 DC *dc = DC_GetDCPtr( hdc );
558 if (!dc) return 0;
560 if (dc->hFont != handle || dc->gdiFont == NULL)
562 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
563 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
566 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
568 if (ret && dc->gdiFont) dc->gdiFont = 0;
570 if (ret == HGDI_ERROR)
571 ret = 0; /* SelectObject returns 0 on error */
572 else
574 ret = dc->hFont;
575 dc->hFont = handle;
577 GDI_ReleaseObj( hdc );
578 return ret;
582 /***********************************************************************
583 * FONT_GetObject16
585 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
587 FONTOBJ *font = obj;
588 LOGFONT16 lf16;
590 FONT_LogFontWTo16( &font->logfont, &lf16 );
592 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
593 memcpy( buffer, &lf16, count );
594 return count;
597 /***********************************************************************
598 * FONT_GetObjectA
600 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
602 FONTOBJ *font = obj;
603 LOGFONTA lfA;
605 if(!buffer)
606 return sizeof(lfA);
607 FONT_LogFontWToA( &font->logfont, &lfA );
609 if (count > sizeof(lfA)) count = sizeof(lfA);
610 memcpy( buffer, &lfA, count );
611 return count;
614 /***********************************************************************
615 * FONT_GetObjectW
617 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
619 FONTOBJ *font = obj;
620 if(!buffer)
621 return sizeof(LOGFONTW);
622 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
623 memcpy( buffer, &font->logfont, count );
624 return count;
628 /***********************************************************************
629 * FONT_DeleteObject
631 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
633 WineEngDestroyFontInstance( handle );
634 return GDI_FreeObject( handle, obj );
638 /***********************************************************************
639 * FONT_EnumInstance16
641 * Called by the device driver layer to pass font info
642 * down to the application.
644 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
645 * We have to use other types because of the FONTENUMPROCW definition.
647 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
648 DWORD fType, LPARAM lp )
650 fontEnum16 *pfe = (fontEnum16*)lp;
651 INT ret = 1;
652 DC *dc;
654 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
655 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
657 WORD args[7];
658 DWORD result;
660 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
661 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
662 pfe->dwFlags |= ENUM_CALLED;
663 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
665 args[6] = SELECTOROF(pfe->segLogFont);
666 args[5] = OFFSETOF(pfe->segLogFont);
667 args[4] = SELECTOROF(pfe->segTextMetric);
668 args[3] = OFFSETOF(pfe->segTextMetric);
669 args[2] = fType;
670 args[1] = HIWORD(pfe->lpData);
671 args[0] = LOWORD(pfe->lpData);
672 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
673 ret = LOWORD(result);
675 /* get the lock again and make sure the DC is still valid */
676 dc = DC_GetDCPtr( pfe->hdc );
677 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
679 if (dc) GDI_ReleaseObj( pfe->hdc );
680 pfe->hdc = 0; /* make sure we don't try to release it later on */
681 ret = 0;
684 return ret;
687 /***********************************************************************
688 * FONT_EnumInstance
690 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
691 * We have to use other types because of the FONTENUMPROCW definition.
693 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
694 DWORD fType, LPARAM lp )
696 fontEnum32 *pfe = (fontEnum32*)lp;
697 INT ret = 1;
698 DC *dc;
700 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
701 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
702 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
703 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
705 /* convert font metrics */
706 ENUMLOGFONTEXA logfont;
707 NEWTEXTMETRICEXA tmA;
709 pfe->dwFlags |= ENUM_CALLED;
710 if (!(pfe->dwFlags & ENUM_UNICODE))
712 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
713 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
714 plf = (LOGFONTW *)&logfont.elfLogFont;
715 ptm = (TEXTMETRICW *)&tmA;
717 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
719 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
721 /* get the lock again and make sure the DC is still valid */
722 dc = DC_GetDCPtr( pfe->hdc );
723 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
725 if (dc) GDI_ReleaseObj( pfe->hdc );
726 pfe->hdc = 0; /* make sure we don't try to release it later on */
727 ret = 0;
730 return ret;
733 /***********************************************************************
734 * EnumFontFamiliesEx (GDI.613)
736 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
737 FONTENUMPROC16 efproc, LPARAM lParam,
738 DWORD dwFlags)
740 fontEnum16 fe16;
741 INT16 ret = 1, ret2;
742 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
743 NEWTEXTMETRICEX16 tm16;
744 ENUMLOGFONTEX16 lf16;
745 LOGFONTW lfW;
746 BOOL enum_gdi_fonts;
748 if (!dc) return 0;
749 FONT_LogFont16ToW(plf, &lfW);
751 fe16.hdc = HDC_32(hDC);
752 fe16.dc = dc;
753 fe16.physDev = dc->physDev;
754 fe16.lpLogFontParam = plf;
755 fe16.lpEnumFunc = efproc;
756 fe16.lpData = lParam;
757 fe16.lpTextMetric = &tm16;
758 fe16.lpLogFont = &lf16;
759 fe16.segTextMetric = MapLS( &tm16 );
760 fe16.segLogFont = MapLS( &lf16 );
761 fe16.dwFlags = 0;
763 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
765 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
767 ret = 0;
768 goto done;
771 if (enum_gdi_fonts)
772 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
773 fe16.dwFlags &= ~ENUM_CALLED;
774 if (ret && dc->funcs->pEnumDeviceFonts) {
775 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
776 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
777 ret = ret2;
779 done:
780 UnMapLS( fe16.segTextMetric );
781 UnMapLS( fe16.segLogFont );
782 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
783 return ret;
786 /***********************************************************************
787 * FONT_EnumFontFamiliesEx
789 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
790 FONTENUMPROCW efproc,
791 LPARAM lParam, DWORD dwUnicode)
793 INT ret = 1, ret2;
794 DC *dc = DC_GetDCPtr( hDC );
795 fontEnum32 fe32;
796 BOOL enum_gdi_fonts;
798 if (!dc) return 0;
800 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
801 plf->lfCharSet);
802 fe32.lpLogFontParam = plf;
803 fe32.lpEnumFunc = efproc;
804 fe32.lpData = lParam;
805 fe32.dwFlags = dwUnicode;
806 fe32.hdc = hDC;
807 fe32.dc = dc;
808 fe32.physDev = dc->physDev;
810 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
812 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
814 ret = 0;
815 goto done;
818 if (enum_gdi_fonts)
819 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
820 fe32.dwFlags &= ~ENUM_CALLED;
821 if (ret && dc->funcs->pEnumDeviceFonts) {
822 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
823 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
824 ret = ret2;
826 done:
827 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
828 return ret;
831 /***********************************************************************
832 * EnumFontFamiliesExW (GDI32.@)
834 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
835 FONTENUMPROCW efproc,
836 LPARAM lParam, DWORD dwFlags )
838 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
841 /***********************************************************************
842 * EnumFontFamiliesExA (GDI32.@)
844 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
845 FONTENUMPROCA efproc,
846 LPARAM lParam, DWORD dwFlags)
848 LOGFONTW lfW;
849 FONT_LogFontAToW( plf, &lfW );
851 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
854 /***********************************************************************
855 * EnumFontFamilies (GDI.330)
857 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
858 FONTENUMPROC16 efproc, LPARAM lpData )
860 LOGFONT16 lf;
862 lf.lfCharSet = DEFAULT_CHARSET;
863 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
864 else lf.lfFaceName[0] = '\0';
866 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
869 /***********************************************************************
870 * EnumFontFamiliesA (GDI32.@)
872 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
873 FONTENUMPROCA efproc, LPARAM lpData )
875 LOGFONTA lf;
877 lf.lfCharSet = DEFAULT_CHARSET;
878 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
879 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
881 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
884 /***********************************************************************
885 * EnumFontFamiliesW (GDI32.@)
887 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
888 FONTENUMPROCW efproc, LPARAM lpData )
890 LOGFONTW lf;
892 lf.lfCharSet = DEFAULT_CHARSET;
893 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
894 else lf.lfFaceName[0] = 0;
896 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
899 /***********************************************************************
900 * EnumFonts (GDI.70)
902 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
903 LPARAM lpData )
905 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
908 /***********************************************************************
909 * EnumFontsA (GDI32.@)
911 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
912 LPARAM lpData )
914 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
917 /***********************************************************************
918 * EnumFontsW (GDI32.@)
920 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
921 LPARAM lpData )
923 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
927 /***********************************************************************
928 * GetTextCharacterExtra (GDI32.@)
930 INT WINAPI GetTextCharacterExtra( HDC hdc )
932 INT ret;
933 DC *dc = DC_GetDCPtr( hdc );
934 if (!dc) return 0x80000000;
935 ret = dc->charExtra;
936 GDI_ReleaseObj( hdc );
937 return ret;
941 /***********************************************************************
942 * SetTextCharacterExtra (GDI32.@)
944 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
946 INT prev;
947 DC * dc = DC_GetDCPtr( hdc );
948 if (!dc) return 0x80000000;
949 if (dc->funcs->pSetTextCharacterExtra)
950 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
951 else
953 prev = dc->charExtra;
954 dc->charExtra = extra;
956 GDI_ReleaseObj( hdc );
957 return prev;
961 /***********************************************************************
962 * SetTextJustification (GDI32.@)
964 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
966 BOOL ret = TRUE;
967 DC * dc = DC_GetDCPtr( hdc );
968 if (!dc) return FALSE;
969 if (dc->funcs->pSetTextJustification)
970 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
971 else
973 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
974 if (!extra) breaks = 0;
975 if (breaks)
977 dc->breakExtra = extra / breaks;
978 dc->breakRem = extra - (breaks * dc->breakExtra);
980 else
982 dc->breakExtra = 0;
983 dc->breakRem = 0;
986 GDI_ReleaseObj( hdc );
987 return ret;
991 /***********************************************************************
992 * GetTextFaceA (GDI32.@)
994 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
996 INT res = GetTextFaceW(hdc, 0, NULL);
997 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
998 GetTextFaceW( hdc, res, nameW );
1000 if (name)
1002 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1003 name[count-1] = 0;
1004 res = strlen(name);
1006 else
1007 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1008 HeapFree( GetProcessHeap(), 0, nameW );
1009 return res;
1012 /***********************************************************************
1013 * GetTextFaceW (GDI32.@)
1015 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1017 FONTOBJ *font;
1018 INT ret = 0;
1020 DC * dc = DC_GetDCPtr( hdc );
1021 if (!dc) return 0;
1023 if(dc->gdiFont)
1024 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1025 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1027 if (name)
1029 lstrcpynW( name, font->logfont.lfFaceName, count );
1030 ret = strlenW(name);
1032 else ret = strlenW(font->logfont.lfFaceName) + 1;
1033 GDI_ReleaseObj( dc->hFont );
1035 GDI_ReleaseObj( hdc );
1036 return ret;
1040 /***********************************************************************
1041 * GetTextExtentPoint32A (GDI32.@)
1043 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1044 LPSIZE size )
1046 BOOL ret = FALSE;
1047 INT wlen;
1048 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1050 if (p) {
1051 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1052 HeapFree( GetProcessHeap(), 0, p );
1055 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1056 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1057 return ret;
1061 /***********************************************************************
1062 * GetTextExtentPoint32W [GDI32.@]
1064 * Computes width/height for a string.
1066 * Computes width and height of the specified string.
1068 * RETURNS
1069 * Success: TRUE
1070 * Failure: FALSE
1072 BOOL WINAPI GetTextExtentPoint32W(
1073 HDC hdc, /* [in] Handle of device context */
1074 LPCWSTR str, /* [in] Address of text string */
1075 INT count, /* [in] Number of characters in string */
1076 LPSIZE size) /* [out] Address of structure for string size */
1078 BOOL ret = FALSE;
1079 DC * dc = DC_GetDCPtr( hdc );
1080 if (!dc) return FALSE;
1082 if(dc->gdiFont)
1083 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1084 else if(dc->funcs->pGetTextExtentPoint)
1085 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1087 if (ret)
1089 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1090 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1091 size->cx += count * dc->charExtra + dc->breakRem;
1094 GDI_ReleaseObj( hdc );
1096 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1097 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1098 return ret;
1101 /***********************************************************************
1102 * GetTextExtentPointI [GDI32.@]
1104 * Computes width and height of the array of glyph indices.
1106 * RETURNS
1107 * Success: TRUE
1108 * Failure: FALSE
1110 BOOL WINAPI GetTextExtentPointI(
1111 HDC hdc, /* [in] Handle of device context */
1112 const WORD *indices, /* [in] Address of glyph index array */
1113 INT count, /* [in] Number of glyphs in array */
1114 LPSIZE size) /* [out] Address of structure for string size */
1116 BOOL ret = FALSE;
1117 DC * dc = DC_GetDCPtr( hdc );
1118 if (!dc) return FALSE;
1120 if(dc->gdiFont) {
1121 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1122 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1123 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1124 size->cx += count * dc->charExtra;
1126 else if(dc->funcs->pGetTextExtentPoint) {
1127 FIXME("calling GetTextExtentPoint\n");
1128 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1131 GDI_ReleaseObj( hdc );
1133 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1134 hdc, indices, count, size, size->cx, size->cy );
1135 return ret;
1139 /***********************************************************************
1140 * GetTextExtentPointA (GDI32.@)
1142 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1143 LPSIZE size )
1145 TRACE("not bug compatible.\n");
1146 return GetTextExtentPoint32A( hdc, str, count, size );
1149 /***********************************************************************
1150 * GetTextExtentPointW (GDI32.@)
1152 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1153 LPSIZE size )
1155 TRACE("not bug compatible.\n");
1156 return GetTextExtentPoint32W( hdc, str, count, size );
1160 /***********************************************************************
1161 * GetTextExtentExPointA (GDI32.@)
1163 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1164 INT maxExt, LPINT lpnFit,
1165 LPINT alpDx, LPSIZE size )
1167 BOOL ret;
1168 INT wlen;
1169 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1170 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1171 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1172 HeapFree( GetProcessHeap(), 0, p );
1173 return ret;
1177 /***********************************************************************
1178 * GetTextExtentExPointW (GDI32.@)
1180 * Return the size of the string as it would be if it was output properly by
1181 * e.g. TextOut.
1183 * This should include
1184 * - Intercharacter spacing
1185 * - justification spacing (not yet done)
1186 * - kerning? see below
1188 * Kerning. Since kerning would be carried out by the rendering code it should
1189 * be done by the driver. However they don't support it yet. Also I am not
1190 * yet persuaded that (certainly under Win95) any kerning is actually done.
1192 * str: According to MSDN this should be null-terminated. That is not true; a
1193 * null will not terminate it early.
1194 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1195 * than count. I have seen it be either the size of the full string or
1196 * 1 less than the size of the full string. I have not seen it bear any
1197 * resemblance to the portion that would fit.
1198 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1199 * trailing intercharacter spacing and any trailing justification.
1201 * FIXME
1202 * Currently we do this by measuring each character etc. We should do it by
1203 * passing the request to the driver, perhaps by extending the
1204 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1205 * thinking about kerning issues and rounding issues in the justification.
1208 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1209 INT maxExt, LPINT lpnFit,
1210 LPINT alpDx, LPSIZE size )
1212 int index, nFit, extent;
1213 SIZE tSize;
1214 BOOL ret = FALSE;
1216 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1218 size->cx = size->cy = nFit = extent = 0;
1219 for(index = 0; index < count; index++)
1221 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1222 /* GetTextExtentPoint includes intercharacter spacing. */
1223 /* FIXME - justification needs doing yet. Remember that the base
1224 * data will not be in logical coordinates.
1226 extent += tSize.cx;
1227 if( !lpnFit || extent <= maxExt )
1228 /* It is allowed to be equal. */
1230 nFit++;
1231 if( alpDx ) alpDx[index] = extent;
1233 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1234 str++;
1236 size->cx = extent;
1237 if(lpnFit) *lpnFit = nFit;
1238 ret = TRUE;
1240 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1242 done:
1243 return ret;
1246 /***********************************************************************
1247 * GetTextMetricsA (GDI32.@)
1249 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1251 TEXTMETRICW tm32;
1253 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1254 FONT_TextMetricWToA( &tm32, metrics );
1255 return TRUE;
1258 /***********************************************************************
1259 * GetTextMetricsW (GDI32.@)
1261 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1263 BOOL ret = FALSE;
1264 DC * dc = DC_GetDCPtr( hdc );
1265 if (!dc) return FALSE;
1267 if (dc->gdiFont)
1268 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1269 else if (dc->funcs->pGetTextMetrics)
1270 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1272 if (ret)
1274 /* device layer returns values in device units
1275 * therefore we have to convert them to logical */
1277 #define WDPTOLP(x) ((x<0)? \
1278 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1279 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1280 #define HDPTOLP(y) ((y<0)? \
1281 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1282 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1284 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1285 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1286 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1287 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1288 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1289 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1290 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1291 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1292 ret = TRUE;
1293 #undef WDPTOLP
1294 #undef HDPTOLP
1295 TRACE("text metrics:\n"
1296 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1297 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1298 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1299 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1300 " PitchAndFamily = %02x\n"
1301 " --------------------\n"
1302 " InternalLeading = %li\n"
1303 " Ascent = %li\n"
1304 " Descent = %li\n"
1305 " Height = %li\n",
1306 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1307 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1308 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1309 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1310 metrics->tmPitchAndFamily,
1311 metrics->tmInternalLeading,
1312 metrics->tmAscent,
1313 metrics->tmDescent,
1314 metrics->tmHeight );
1316 GDI_ReleaseObj( hdc );
1317 return ret;
1321 /***********************************************************************
1322 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1324 * NOTES
1325 * lpOTM should be LPOUTLINETEXTMETRIC
1327 * RETURNS
1328 * Success: Non-zero or size of required buffer
1329 * Failure: 0
1331 UINT16 WINAPI GetOutlineTextMetrics16(
1332 HDC16 hdc, /* [in] Handle of device context */
1333 UINT16 cbData, /* [in] Size of metric data array */
1334 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1336 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1337 return 0;
1341 /***********************************************************************
1342 * GetOutlineTextMetricsA (GDI32.@)
1343 * Gets metrics for TrueType fonts.
1345 * NOTES
1346 * If the supplied buffer isn't big enough Windows partially fills it up to
1347 * its given length and returns that length.
1349 * RETURNS
1350 * Success: Non-zero or size of required buffer
1351 * Failure: 0
1353 UINT WINAPI GetOutlineTextMetricsA(
1354 HDC hdc, /* [in] Handle of device context */
1355 UINT cbData, /* [in] Size of metric data array */
1356 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1358 char buf[512], *ptr;
1359 UINT ret, needed;
1360 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1361 OUTLINETEXTMETRICA *output = lpOTM;
1362 INT left, len;
1364 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1365 return 0;
1366 if(ret > sizeof(buf))
1367 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1368 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1370 needed = sizeof(OUTLINETEXTMETRICA);
1371 if(lpOTMW->otmpFamilyName)
1372 needed += WideCharToMultiByte(CP_ACP, 0,
1373 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1374 NULL, 0, NULL, NULL);
1375 if(lpOTMW->otmpFaceName)
1376 needed += WideCharToMultiByte(CP_ACP, 0,
1377 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1378 NULL, 0, NULL, NULL);
1379 if(lpOTMW->otmpStyleName)
1380 needed += WideCharToMultiByte(CP_ACP, 0,
1381 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1382 NULL, 0, NULL, NULL);
1383 if(lpOTMW->otmpFullName)
1384 needed += WideCharToMultiByte(CP_ACP, 0,
1385 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1386 NULL, 0, NULL, NULL);
1388 if(!lpOTM) {
1389 ret = needed;
1390 goto end;
1393 TRACE("needed = %d\n", needed);
1394 if(needed > cbData)
1395 /* Since the supplied buffer isn't big enough, we'll alloc one
1396 that is and memcpy the first cbData bytes into the lpOTM at
1397 the end. */
1398 output = HeapAlloc(GetProcessHeap(), 0, needed);
1400 ret = output->otmSize = min(needed, cbData);
1401 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1402 output->otmFiller = 0;
1403 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1404 output->otmfsSelection = lpOTMW->otmfsSelection;
1405 output->otmfsType = lpOTMW->otmfsType;
1406 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1407 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1408 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1409 output->otmEMSquare = lpOTMW->otmEMSquare;
1410 output->otmAscent = lpOTMW->otmAscent;
1411 output->otmDescent = lpOTMW->otmDescent;
1412 output->otmLineGap = lpOTMW->otmLineGap;
1413 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1414 output->otmsXHeight = lpOTMW->otmsXHeight;
1415 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1416 output->otmMacAscent = lpOTMW->otmMacAscent;
1417 output->otmMacDescent = lpOTMW->otmMacDescent;
1418 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1419 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1420 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1421 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1422 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1423 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1424 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1425 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1426 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1427 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1430 ptr = (char*)(output + 1);
1431 left = needed - sizeof(*output);
1433 if(lpOTMW->otmpFamilyName) {
1434 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1435 len = WideCharToMultiByte(CP_ACP, 0,
1436 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1437 ptr, left, NULL, NULL);
1438 left -= len;
1439 ptr += len;
1440 } else
1441 output->otmpFamilyName = 0;
1443 if(lpOTMW->otmpFaceName) {
1444 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1445 len = WideCharToMultiByte(CP_ACP, 0,
1446 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1447 ptr, left, NULL, NULL);
1448 left -= len;
1449 ptr += len;
1450 } else
1451 output->otmpFaceName = 0;
1453 if(lpOTMW->otmpStyleName) {
1454 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1455 len = WideCharToMultiByte(CP_ACP, 0,
1456 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1457 ptr, left, NULL, NULL);
1458 left -= len;
1459 ptr += len;
1460 } else
1461 output->otmpStyleName = 0;
1463 if(lpOTMW->otmpFullName) {
1464 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1465 len = WideCharToMultiByte(CP_ACP, 0,
1466 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1467 ptr, left, NULL, NULL);
1468 left -= len;
1469 } else
1470 output->otmpFullName = 0;
1472 assert(left == 0);
1474 if(output != lpOTM) {
1475 memcpy(lpOTM, output, cbData);
1476 HeapFree(GetProcessHeap(), 0, output);
1479 end:
1480 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1481 HeapFree(GetProcessHeap(), 0, lpOTMW);
1483 return ret;
1487 /***********************************************************************
1488 * GetOutlineTextMetricsW [GDI32.@]
1490 UINT WINAPI GetOutlineTextMetricsW(
1491 HDC hdc, /* [in] Handle of device context */
1492 UINT cbData, /* [in] Size of metric data array */
1493 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1495 DC *dc = DC_GetDCPtr( hdc );
1496 OUTLINETEXTMETRICW *output = lpOTM;
1497 UINT ret;
1499 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1500 if(!dc) return 0;
1502 if(dc->gdiFont) {
1503 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1504 if(lpOTM && ret) {
1505 if(ret > cbData) {
1506 output = HeapAlloc(GetProcessHeap(), 0, ret);
1507 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1510 #define WDPTOLP(x) ((x<0)? \
1511 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1512 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1513 #define HDPTOLP(y) ((y<0)? \
1514 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1515 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1517 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1518 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1519 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1520 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1521 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1522 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1523 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1524 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1525 output->otmAscent = HDPTOLP(output->otmAscent);
1526 output->otmDescent = HDPTOLP(output->otmDescent);
1527 output->otmLineGap = HDPTOLP(output->otmLineGap);
1528 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1529 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1530 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1531 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1532 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1533 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1534 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1535 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1536 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1537 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1538 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1539 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1540 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1541 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1542 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1543 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1544 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1545 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1546 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1547 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1548 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1549 #undef WDPTOLP
1550 #undef HDPTOLP
1551 if(output != lpOTM) {
1552 memcpy(lpOTM, output, cbData);
1553 HeapFree(GetProcessHeap(), 0, output);
1554 ret = cbData;
1559 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1560 but really this should just be a return 0. */
1562 ret = sizeof(*lpOTM);
1563 if (lpOTM) {
1564 if(cbData < ret)
1565 ret = 0;
1566 else {
1567 memset(lpOTM, 0, ret);
1568 lpOTM->otmSize = sizeof(*lpOTM);
1569 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1571 Further fill of the structure not implemented,
1572 Needs real values for the structure members
1577 GDI_ReleaseObj(hdc);
1578 return ret;
1582 /***********************************************************************
1583 * GetCharWidthW (GDI32.@)
1584 * GetCharWidth32W (GDI32.@)
1586 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1587 LPINT buffer )
1589 UINT i;
1590 BOOL ret = FALSE;
1591 DC * dc = DC_GetDCPtr( hdc );
1592 if (!dc) return FALSE;
1594 if (dc->gdiFont)
1595 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1596 else if (dc->funcs->pGetCharWidth)
1597 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1599 if (ret)
1601 /* convert device units to logical */
1602 for( i = firstChar; i <= lastChar; i++, buffer++ )
1603 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1604 ret = TRUE;
1606 GDI_ReleaseObj( hdc );
1607 return ret;
1611 /***********************************************************************
1612 * GetCharWidthA (GDI32.@)
1613 * GetCharWidth32A (GDI32.@)
1615 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1616 LPINT buffer )
1618 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1619 LPSTR str;
1620 LPWSTR wstr;
1621 BOOL ret = TRUE;
1623 if(count <= 0) return FALSE;
1625 str = HeapAlloc(GetProcessHeap(), 0, count);
1626 for(i = 0; i < count; i++)
1627 str[i] = (BYTE)(firstChar + i);
1629 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1631 for(i = 0; i < wlen; i++)
1633 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1635 ret = FALSE;
1636 break;
1638 buffer++;
1641 HeapFree(GetProcessHeap(), 0, str);
1642 HeapFree(GetProcessHeap(), 0, wstr);
1644 return ret;
1648 /***********************************************************************
1649 * ExtTextOutA (GDI32.@)
1651 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1652 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1654 INT wlen;
1655 UINT codepage;
1656 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1657 BOOL ret;
1658 LPINT lpDxW = NULL;
1660 if (lpDx) {
1661 unsigned int i = 0, j = 0;
1663 lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1664 while(i < count) {
1665 if(IsDBCSLeadByteEx(codepage, str[i])) {
1666 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1667 i = i + 2;
1668 } else {
1669 lpDxW[j++] = lpDx[i];
1670 i = i + 1;
1675 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1677 HeapFree( GetProcessHeap(), 0, p );
1678 if (lpDxW) HeapFree( GetProcessHeap(), 0, lpDxW );
1679 return ret;
1683 /***********************************************************************
1684 * ExtTextOutW (GDI32.@)
1686 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1687 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1689 BOOL ret = FALSE;
1690 DC * dc = DC_GetDCUpdate( hdc );
1691 if (dc)
1693 if(PATH_IsPathOpen(dc->path))
1694 FIXME("called on an open path\n");
1695 else if(dc->funcs->pExtTextOut)
1697 if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
1699 /* The caller did not specify that language processing was already done.
1701 LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1703 BIDI_Reorder( str, count, GCP_REORDER,
1704 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1705 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1706 lpReorderedString, count, NULL );
1708 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
1709 lprect,lpReorderedString,count,lpDx,dc->breakExtra);
1710 HeapFree(GetProcessHeap(), 0, lpReorderedString);
1711 } else
1712 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,
1713 lpDx,dc->breakExtra);
1715 GDI_ReleaseObj( hdc );
1717 return ret;
1721 /***********************************************************************
1722 * TextOutA (GDI32.@)
1724 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
1726 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
1730 /***********************************************************************
1731 * TextOutW (GDI32.@)
1733 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
1735 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
1739 /***********************************************************************
1740 * PolyTextOutA (GDI32.@)
1742 * Draw several Strings
1744 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
1745 PPOLYTEXTA pptxt, /* [in] Array of strings */
1746 INT cStrings ) /* [in] Number of strings in array */
1748 for (; cStrings>0; cStrings--, pptxt++)
1749 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
1750 return FALSE;
1751 return TRUE;
1756 /***********************************************************************
1757 * PolyTextOutW (GDI32.@)
1759 * Draw several Strings
1761 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
1762 PPOLYTEXTW pptxt, /* [in] Array of strings */
1763 INT cStrings ) /* [in] Number of strings in array */
1765 for (; cStrings>0; cStrings--, pptxt++)
1766 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
1767 return FALSE;
1768 return TRUE;
1772 /* FIXME: all following APIs ******************************************/
1775 /***********************************************************************
1776 * SetMapperFlags (GDI32.@)
1778 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1780 DC *dc = DC_GetDCPtr( hDC );
1781 DWORD ret = 0;
1782 if(!dc) return 0;
1783 if(dc->funcs->pSetMapperFlags)
1784 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1785 else
1786 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1787 GDI_ReleaseObj( hDC );
1788 return ret;
1791 /***********************************************************************
1792 * GetAspectRatioFilterEx (GDI.486)
1794 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1796 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1797 return FALSE;
1800 /***********************************************************************
1801 * GetAspectRatioFilterEx (GDI32.@)
1803 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1805 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1806 return FALSE;
1810 /***********************************************************************
1811 * GetCharABCWidthsA (GDI32.@)
1813 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1814 LPABC abc )
1816 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1817 LPSTR str;
1818 LPWSTR wstr;
1819 BOOL ret = TRUE;
1821 if(count <= 0) return FALSE;
1823 str = HeapAlloc(GetProcessHeap(), 0, count);
1824 for(i = 0; i < count; i++)
1825 str[i] = (BYTE)(firstChar + i);
1827 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1829 for(i = 0; i < wlen; i++)
1831 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1833 ret = FALSE;
1834 break;
1836 abc++;
1839 HeapFree(GetProcessHeap(), 0, str);
1840 HeapFree(GetProcessHeap(), 0, wstr);
1842 return ret;
1846 /******************************************************************************
1847 * GetCharABCWidthsW [GDI32.@]
1849 * Retrieves widths of characters in range.
1851 * PARAMS
1852 * hdc [I] Handle of device context
1853 * firstChar [I] First character in range to query
1854 * lastChar [I] Last character in range to query
1855 * abc [O] Address of character-width structure
1857 * NOTES
1858 * Only works with TrueType fonts
1860 * RETURNS
1861 * Success: TRUE
1862 * Failure: FALSE
1864 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1865 LPABC abc )
1867 DC *dc = DC_GetDCPtr(hdc);
1868 int i;
1869 BOOL ret = FALSE;
1871 if(dc->gdiFont)
1872 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1873 else
1874 FIXME(": stub\n");
1876 if (ret)
1878 /* convert device units to logical */
1879 for( i = firstChar; i <= lastChar; i++, abc++ ) {
1880 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1881 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1882 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1884 ret = TRUE;
1887 GDI_ReleaseObj(hdc);
1888 return ret;
1892 /***********************************************************************
1893 * GetGlyphOutline (GDI.309)
1895 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1896 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1897 LPVOID lpBuffer, const MAT2 *lpmat2 )
1899 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1900 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1901 return ~0UL; /* failure */
1905 /***********************************************************************
1906 * GetGlyphOutlineA (GDI32.@)
1908 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1909 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1910 LPVOID lpBuffer, const MAT2 *lpmat2 )
1912 LPWSTR p = NULL;
1913 DWORD ret;
1914 UINT c;
1916 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1917 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1918 c = p[0];
1919 } else
1920 c = uChar;
1921 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1922 lpmat2);
1923 if(p)
1924 HeapFree(GetProcessHeap(), 0, p);
1925 return ret;
1928 /***********************************************************************
1929 * GetGlyphOutlineW (GDI32.@)
1931 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1932 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1933 LPVOID lpBuffer, const MAT2 *lpmat2 )
1935 DC *dc = DC_GetDCPtr(hdc);
1936 DWORD ret;
1938 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1939 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1941 if(!dc) return GDI_ERROR;
1943 if(dc->gdiFont)
1944 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1945 cbBuffer, lpBuffer, lpmat2);
1946 else
1947 ret = GDI_ERROR;
1949 GDI_ReleaseObj(hdc);
1950 return ret;
1954 /***********************************************************************
1955 * CreateScalableFontResourceA (GDI32.@)
1957 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1958 LPCSTR lpszResourceFile,
1959 LPCSTR lpszFontFile,
1960 LPCSTR lpszCurrentPath )
1962 HANDLE f;
1964 /* fHidden=1 - only visible for the calling app, read-only, not
1965 * enumbered with EnumFonts/EnumFontFamilies
1966 * lpszCurrentPath can be NULL
1968 FIXME("(%ld,%s,%s,%s): stub\n",
1969 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1970 debugstr_a(lpszCurrentPath) );
1972 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1973 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1974 CloseHandle(f);
1975 SetLastError(ERROR_FILE_EXISTS);
1976 return FALSE;
1978 return FALSE; /* create failed */
1981 /***********************************************************************
1982 * CreateScalableFontResourceW (GDI32.@)
1984 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1985 LPCWSTR lpszResourceFile,
1986 LPCWSTR lpszFontFile,
1987 LPCWSTR lpszCurrentPath )
1989 FIXME("(%ld,%p,%p,%p): stub\n",
1990 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1991 return FALSE; /* create failed */
1995 /*************************************************************************
1996 * GetRasterizerCaps (GDI32.@)
1998 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
2000 lprs->nSize = sizeof(RASTERIZER_STATUS);
2001 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
2002 lprs->nLanguageID = 0;
2003 return TRUE;
2007 /*************************************************************************
2008 * GetKerningPairsA (GDI32.@)
2010 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2011 LPKERNINGPAIR lpKerningPairs )
2013 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2017 /*************************************************************************
2018 * GetKerningPairsW (GDI32.@)
2020 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2021 LPKERNINGPAIR lpKerningPairs )
2023 int i;
2024 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2025 for (i = 0; i < cPairs; i++)
2026 lpKerningPairs[i].iKernAmount = 0;
2027 return 0;
2030 /*************************************************************************
2031 * TranslateCharsetInfo [GDI32.@]
2033 * Fills a CHARSETINFO structure for a character set, code page, or
2034 * font. This allows making the correspondance between different labelings
2035 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2036 * of the same encoding.
2038 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2039 * only one codepage should be set in *lpSrc.
2041 * RETURNS
2042 * TRUE on success, FALSE on failure.
2045 BOOL WINAPI TranslateCharsetInfo(
2046 LPDWORD lpSrc, /* [in]
2047 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2048 if flags == TCI_SRCCHARSET: a character set value
2049 if flags == TCI_SRCCODEPAGE: a code page value
2051 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2052 DWORD flags /* [in] determines interpretation of lpSrc */)
2054 int index = 0;
2055 switch (flags) {
2056 case TCI_SRCFONTSIG:
2057 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2058 break;
2059 case TCI_SRCCODEPAGE:
2060 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2061 break;
2062 case TCI_SRCCHARSET:
2063 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2064 break;
2065 default:
2066 return FALSE;
2068 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2069 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2070 return TRUE;
2073 /*************************************************************************
2074 * GetFontLanguageInfo (GDI32.@)
2076 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2078 FONTSIGNATURE fontsig;
2079 static const DWORD GCP_DBCS_MASK=0x003F0000,
2080 GCP_DIACRITIC_MASK=0x00000000,
2081 FLI_GLYPHS_MASK=0x00000000,
2082 GCP_GLYPHSHAPE_MASK=0x00000040,
2083 GCP_KASHIDA_MASK=0x00000000,
2084 GCP_LIGATE_MASK=0x00000000,
2085 GCP_USEKERNING_MASK=0x00000000,
2086 GCP_REORDER_MASK=0x00000060;
2088 DWORD result=0;
2090 GetTextCharsetInfo( hdc, &fontsig, 0 );
2091 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2093 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2094 result|=GCP_DBCS;
2096 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2097 result|=GCP_DIACRITIC;
2099 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2100 result|=FLI_GLYPHS;
2102 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2103 result|=GCP_GLYPHSHAPE;
2105 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2106 result|=GCP_KASHIDA;
2108 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2109 result|=GCP_LIGATE;
2111 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2112 result|=GCP_USEKERNING;
2114 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2115 if( GetTextAlign( hdc) & TA_RTLREADING )
2116 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2117 result|=GCP_REORDER;
2119 return result;
2123 /*************************************************************************
2124 * GetFontData [GDI32.@]
2126 * Retrieve data for TrueType font.
2128 * RETURNS
2130 * success: Number of bytes returned
2131 * failure: GDI_ERROR
2133 * NOTES
2135 * Calls SetLastError()
2138 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2139 LPVOID buffer, DWORD length)
2141 DC *dc = DC_GetDCPtr(hdc);
2142 DWORD ret = GDI_ERROR;
2144 if(!dc) return GDI_ERROR;
2146 if(dc->gdiFont)
2147 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2149 GDI_ReleaseObj(hdc);
2150 return ret;
2153 /*************************************************************************
2154 * GetGlyphIndicesA [GDI32.@]
2156 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2157 LPWORD pgi, DWORD flags)
2159 DWORD ret;
2160 WCHAR *lpstrW;
2161 INT countW;
2163 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2164 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2166 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2167 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2168 HeapFree(GetProcessHeap(), 0, lpstrW);
2170 return ret;
2173 /*************************************************************************
2174 * GetGlyphIndicesW [GDI32.@]
2176 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2177 LPWORD pgi, DWORD flags)
2179 DC *dc = DC_GetDCPtr(hdc);
2180 DWORD ret = GDI_ERROR;
2182 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2183 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2185 if(!dc) return GDI_ERROR;
2187 if(dc->gdiFont)
2188 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2190 GDI_ReleaseObj(hdc);
2191 return ret;
2194 /*************************************************************************
2195 * GetCharacterPlacementA [GDI32.@]
2197 * NOTES:
2198 * the web browser control of ie4 calls this with dwFlags=0
2200 DWORD WINAPI
2201 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2202 INT nMaxExtent, GCP_RESULTSA *lpResults,
2203 DWORD dwFlags)
2205 WCHAR *lpStringW;
2206 INT uCountW;
2207 GCP_RESULTSW resultsW;
2208 DWORD ret;
2209 UINT font_cp;
2211 TRACE("%s, %d, %d, 0x%08lx\n",
2212 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2214 /* both structs are equal in size */
2215 memcpy(&resultsW, lpResults, sizeof(resultsW));
2217 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2218 if(lpResults->lpOutString)
2219 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2221 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2223 if(lpResults->lpOutString) {
2224 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2225 lpResults->lpOutString, uCount, NULL, NULL );
2228 HeapFree(GetProcessHeap(), 0, lpStringW);
2229 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2231 return ret;
2234 /*************************************************************************
2235 * GetCharacterPlacementW [GDI32.@]
2237 * Retrieve information about a string. This includes the width, reordering,
2238 * Glyphing and so on.
2240 * RETURNS
2242 * The width and height of the string if successful, 0 if failed.
2244 * BUGS
2246 * All flags except GCP_REORDER are not yet implemented.
2247 * Reordering is not 100% complient to the Windows BiDi method.
2248 * Caret positioning is not yet implemented for BiDi.
2249 * Classes are not yet implemented.
2252 DWORD WINAPI
2253 GetCharacterPlacementW(
2254 HDC hdc, /* [in] Device context for which the rendering is to be done */
2255 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2256 INT uCount, /* [in] Number of WORDS in string. */
2257 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2258 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2259 DWORD dwFlags /* [in] Flags specifying how to process the string */
2262 DWORD ret=0;
2263 SIZE size;
2264 UINT i, nSet;
2266 TRACE("%s, %d, %d, 0x%08lx\n",
2267 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2269 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2270 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2271 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2272 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2273 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2275 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2276 if(lpResults->lpClass) FIXME("classes not implemented\n");
2277 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2278 FIXME("Caret positions for complex scripts not implemented\n");
2280 nSet = (UINT)uCount;
2281 if(nSet > lpResults->nGlyphs)
2282 nSet = lpResults->nGlyphs;
2284 /* return number of initialized fields */
2285 lpResults->nGlyphs = nSet;
2287 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2289 /* Treat the case where no special handling was requested in a fastpath way */
2290 /* copy will do if the GCP_REORDER flag is not set */
2291 if(lpResults->lpOutString)
2292 strncpyW( lpResults->lpOutString, lpString, nSet );
2294 if(lpResults->lpOrder)
2296 for(i = 0; i < nSet; i++)
2297 lpResults->lpOrder[i] = i;
2299 } else
2301 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2302 nSet, lpResults->lpOrder );
2305 /* FIXME: Will use the placement chars */
2306 if (lpResults->lpDx)
2308 int c;
2309 for (i = 0; i < nSet; i++)
2311 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2312 lpResults->lpDx[i]= c;
2316 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2318 int pos = 0;
2320 lpResults->lpCaretPos[0] = 0;
2321 for (i = 1; i < nSet; i++)
2322 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2323 lpResults->lpCaretPos[i] = (pos += size.cx);
2326 if(lpResults->lpGlyphs)
2327 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2329 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2330 ret = MAKELONG(size.cx, size.cy);
2332 return ret;
2335 /*************************************************************************
2336 * GetCharABCWidthsFloatA [GDI32.@]
2338 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2339 LPABCFLOAT lpABCF)
2341 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2342 return 0;
2345 /*************************************************************************
2346 * GetCharABCWidthsFloatW [GDI32.@]
2348 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2349 UINT iLastChar, LPABCFLOAT lpABCF)
2351 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2352 return 0;
2355 /*************************************************************************
2356 * GetCharWidthFloatA [GDI32.@]
2358 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2359 UINT iLastChar, PFLOAT pxBuffer)
2361 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2362 return 0;
2365 /*************************************************************************
2366 * GetCharWidthFloatW [GDI32.@]
2368 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2369 UINT iLastChar, PFLOAT pxBuffer)
2371 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2372 return 0;
2376 /***********************************************************************
2378 * Font Resource API *
2380 ***********************************************************************/
2382 /***********************************************************************
2383 * AddFontResourceA (GDI32.@)
2385 INT WINAPI AddFontResourceA( LPCSTR str )
2387 return AddFontResourceExA( str, 0, NULL);
2390 /***********************************************************************
2391 * AddFontResourceW (GDI32.@)
2393 INT WINAPI AddFontResourceW( LPCWSTR str )
2395 return AddFontResourceExW(str, 0, NULL);
2399 /***********************************************************************
2400 * AddFontResourceExA (GDI32.@)
2402 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2404 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2405 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2406 INT ret;
2408 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2409 ret = AddFontResourceExW(strW, fl, pdv);
2410 HeapFree(GetProcessHeap(), 0, strW);
2411 return ret;
2414 /***********************************************************************
2415 * AddFontResourceExW (GDI32.@)
2417 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2419 return WineEngAddFontResourceEx(str, fl, pdv);
2422 /***********************************************************************
2423 * RemoveFontResourceA (GDI32.@)
2425 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2427 return RemoveFontResourceExA(str, 0, 0);
2430 /***********************************************************************
2431 * RemoveFontResourceW (GDI32.@)
2433 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2435 return RemoveFontResourceExW(str, 0, 0);
2438 /***********************************************************************
2439 * RemoveFontResourceExA (GDI32.@)
2441 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2443 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2444 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2445 INT ret;
2447 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2448 ret = RemoveFontResourceExW(strW, fl, pdv);
2449 HeapFree(GetProcessHeap(), 0, strW);
2450 return ret;
2453 /***********************************************************************
2454 * RemoveFontResourceExW (GDI32.@)
2456 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2458 return WineEngRemoveFontResourceEx(str, fl, pdv);
2461 /***********************************************************************
2462 * GetTextCharset (GDI32.@)
2464 UINT WINAPI GetTextCharset(HDC hdc)
2466 /* MSDN docs say this is equivalent */
2467 return GetTextCharsetInfo(hdc, NULL, 0);
2470 /***********************************************************************
2471 * GetTextCharsetInfo (GDI32.@)
2473 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2475 UINT ret = DEFAULT_CHARSET;
2476 DC *dc = DC_GetDCPtr(hdc);
2478 if (!dc) goto done;
2480 if (dc->gdiFont)
2481 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2483 GDI_ReleaseObj(hdc);
2485 done:
2486 if (ret == DEFAULT_CHARSET && fs)
2487 memset(fs, 0, sizeof(FONTSIGNATURE));
2488 return ret;