Add UTC to the time zone list.
[wine/multimedia.git] / dlls / gdi / font.c
bloba0a37d9be607305dc765a2f50c7cf05d57a5bcc3
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);
216 fontW->lfFaceName[LF_FACESIZE-1] = 0;
219 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
221 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
222 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
223 LF_FACESIZE, NULL, NULL);
224 fontA->lfFaceName[LF_FACESIZE-1] = 0;
227 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
229 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
231 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
232 font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
233 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
234 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
235 font16->elfStyle, LF_FACESIZE, NULL, NULL );
236 font16->elfStyle[LF_FACESIZE-1] = '\0';
237 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
238 font16->elfScript, LF_FACESIZE, NULL, NULL );
239 font16->elfScript[LF_FACESIZE-1] = '\0';
242 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
244 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
246 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
247 fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
248 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
249 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
250 fontA->elfStyle, LF_FACESIZE, NULL, NULL );
251 fontA->elfStyle[LF_FACESIZE-1] = '\0';
252 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
253 fontA->elfScript, LF_FACESIZE, NULL, NULL );
254 fontA->elfScript[LF_FACESIZE-1] = '\0';
257 /***********************************************************************
258 * TEXTMETRIC conversion functions.
260 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
262 ptmA->tmHeight = ptmW->tmHeight;
263 ptmA->tmAscent = ptmW->tmAscent;
264 ptmA->tmDescent = ptmW->tmDescent;
265 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
266 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
267 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
268 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
269 ptmA->tmWeight = ptmW->tmWeight;
270 ptmA->tmOverhang = ptmW->tmOverhang;
271 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
272 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
273 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
274 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
275 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
276 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
277 ptmA->tmItalic = ptmW->tmItalic;
278 ptmA->tmUnderlined = ptmW->tmUnderlined;
279 ptmA->tmStruckOut = ptmW->tmStruckOut;
280 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
281 ptmA->tmCharSet = ptmW->tmCharSet;
285 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
287 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
288 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
289 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
290 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
291 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
292 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
293 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
294 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
295 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
296 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
297 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
298 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
299 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
300 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
301 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
302 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
303 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
304 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
305 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
306 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
307 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
308 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
309 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
310 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
311 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
314 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
316 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
317 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
318 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
319 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
320 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
321 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
325 /***********************************************************************
326 * FONT_mbtowc
328 * Returns a '\0' terminated Unicode translation of str using the
329 * charset of the currently selected font in hdc. If count is -1 then
330 * str is assumed to be '\0' terminated, otherwise it contains the
331 * number of bytes to convert. If plenW is non-NULL, on return it
332 * will point to the number of WCHARs (excluding the '\0') that have
333 * been written. If pCP is non-NULL, on return it will point to the
334 * codepage used in the conversion.
335 * The caller should free the returned LPWSTR from the process
336 * heap itself.
338 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
340 UINT cp = CP_ACP;
341 INT lenW;
342 LPWSTR strW;
343 CHARSETINFO csi;
344 int charset = GetTextCharset(hdc);
346 /* Hmm, nicely designed api this one! */
347 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
348 cp = csi.ciACP;
349 else {
350 switch(charset) {
351 case OEM_CHARSET:
352 cp = GetOEMCP();
353 break;
354 case DEFAULT_CHARSET:
355 cp = GetACP();
356 break;
358 case VISCII_CHARSET:
359 case TCVN_CHARSET:
360 case KOI8_CHARSET:
361 case ISO3_CHARSET:
362 case ISO4_CHARSET:
363 case ISO10_CHARSET:
364 case CELTIC_CHARSET:
365 /* FIXME: These have no place here, but because x11drv
366 enumerates fonts with these (made up) charsets some apps
367 might use them and then the FIXME below would become
368 annoying. Now we could pick the intended codepage for
369 each of these, but since it's broken anyway we'll just
370 use CP_ACP and hope it'll go away...
372 cp = CP_ACP;
373 break;
375 default:
376 FIXME("Can't find codepage for charset %d\n", charset);
377 break;
381 TRACE("charset %d => cp %d\n", charset, cp);
383 if(count == -1) count = strlen(str);
384 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
385 strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
386 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
387 strW[lenW] = '\0';
388 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
389 if(plenW) *plenW = lenW;
390 if(pCP) *pCP = cp;
391 return strW;
395 /***********************************************************************
396 * CreateFontIndirectA (GDI32.@)
398 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
400 LOGFONTW lfW;
402 if (plfA) {
403 FONT_LogFontAToW( plfA, &lfW );
404 return CreateFontIndirectW( &lfW );
405 } else
406 return CreateFontIndirectW( NULL );
410 /***********************************************************************
411 * CreateFontIndirectW (GDI32.@)
413 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
415 HFONT hFont = 0;
417 if (plf)
419 FONTOBJ* fontPtr;
420 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
421 (HGDIOBJ *)&hFont, &font_funcs )))
423 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
424 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
425 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
426 WCHAR* pFaceNameSuffix = NULL;
428 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
430 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
431 plf->lfHeight, plf->lfWidth,
432 plf->lfEscapement, plf->lfOrientation,
433 plf->lfPitchAndFamily,
434 plf->lfOutPrecision, plf->lfClipPrecision,
435 plf->lfQuality, plf->lfCharSet,
436 debugstr_w(plf->lfFaceName),
437 plf->lfWeight > 400 ? "Bold" : "",
438 plf->lfItalic ? "Italic" : "",
439 plf->lfUnderline ? "Underline" : "", hFont);
441 if (plf->lfEscapement != plf->lfOrientation) {
442 /* this should really depend on whether GM_ADVANCED is set */
443 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
444 WARN("orientation angle %f set to "
445 "escapement angle %f for new font %p\n",
446 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
449 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
450 if (pFaceNameItalicSuffix) {
451 fontPtr->logfont.lfItalic = TRUE;
452 pFaceNameSuffix = pFaceNameItalicSuffix;
455 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
456 if (pFaceNameBoldSuffix) {
457 if (fontPtr->logfont.lfWeight < FW_BOLD) {
458 fontPtr->logfont.lfWeight = FW_BOLD;
460 if (!pFaceNameSuffix ||
461 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
462 pFaceNameSuffix = pFaceNameBoldSuffix;
466 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
468 GDI_ReleaseObj( hFont );
471 else WARN("(NULL) => NULL\n");
473 return hFont;
476 /*************************************************************************
477 * CreateFontA (GDI32.@)
479 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
480 INT orient, INT weight, DWORD italic,
481 DWORD underline, DWORD strikeout, DWORD charset,
482 DWORD outpres, DWORD clippres, DWORD quality,
483 DWORD pitch, LPCSTR name )
485 LOGFONTA logfont;
487 logfont.lfHeight = height;
488 logfont.lfWidth = width;
489 logfont.lfEscapement = esc;
490 logfont.lfOrientation = orient;
491 logfont.lfWeight = weight;
492 logfont.lfItalic = italic;
493 logfont.lfUnderline = underline;
494 logfont.lfStrikeOut = strikeout;
495 logfont.lfCharSet = charset;
496 logfont.lfOutPrecision = outpres;
497 logfont.lfClipPrecision = clippres;
498 logfont.lfQuality = quality;
499 logfont.lfPitchAndFamily = pitch;
501 if (name)
502 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
503 else
504 logfont.lfFaceName[0] = '\0';
506 return CreateFontIndirectA( &logfont );
509 /*************************************************************************
510 * CreateFontW (GDI32.@)
512 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
513 INT orient, INT weight, DWORD italic,
514 DWORD underline, DWORD strikeout, DWORD charset,
515 DWORD outpres, DWORD clippres, DWORD quality,
516 DWORD pitch, LPCWSTR name )
518 LOGFONTW logfont;
520 logfont.lfHeight = height;
521 logfont.lfWidth = width;
522 logfont.lfEscapement = esc;
523 logfont.lfOrientation = orient;
524 logfont.lfWeight = weight;
525 logfont.lfItalic = italic;
526 logfont.lfUnderline = underline;
527 logfont.lfStrikeOut = strikeout;
528 logfont.lfCharSet = charset;
529 logfont.lfOutPrecision = outpres;
530 logfont.lfClipPrecision = clippres;
531 logfont.lfQuality = quality;
532 logfont.lfPitchAndFamily = pitch;
534 if (name)
535 lstrcpynW(logfont.lfFaceName, name,
536 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
537 else
538 logfont.lfFaceName[0] = '\0';
540 return CreateFontIndirectW( &logfont );
544 /***********************************************************************
545 * FONT_SelectObject
547 * If the driver supports vector fonts we create a gdi font first and
548 * then call the driver to give it a chance to supply its own device
549 * font. If the driver wants to do this it returns TRUE and we can
550 * delete the gdi font, if the driver wants to use the gdi font it
551 * should return FALSE, to signal an error return GDI_ERROR. For
552 * drivers that don't support vector fonts they must supply their own
553 * font.
555 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
557 HGDIOBJ ret = 0;
558 DC *dc = DC_GetDCPtr( hdc );
560 if (!dc) return 0;
562 if (dc->hFont != handle || dc->gdiFont == NULL)
564 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
565 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
568 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
570 if (ret && dc->gdiFont) dc->gdiFont = 0;
572 if (ret == HGDI_ERROR)
573 ret = 0; /* SelectObject returns 0 on error */
574 else
576 ret = dc->hFont;
577 dc->hFont = handle;
579 GDI_ReleaseObj( hdc );
580 return ret;
584 /***********************************************************************
585 * FONT_GetObject16
587 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
589 FONTOBJ *font = obj;
590 LOGFONT16 lf16;
592 FONT_LogFontWTo16( &font->logfont, &lf16 );
594 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
595 memcpy( buffer, &lf16, count );
596 return count;
599 /***********************************************************************
600 * FONT_GetObjectA
602 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
604 FONTOBJ *font = obj;
605 LOGFONTA lfA;
607 if(!buffer)
608 return sizeof(lfA);
609 FONT_LogFontWToA( &font->logfont, &lfA );
611 if (count > sizeof(lfA)) count = sizeof(lfA);
612 memcpy( buffer, &lfA, count );
613 return count;
616 /***********************************************************************
617 * FONT_GetObjectW
619 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
621 FONTOBJ *font = obj;
622 if(!buffer)
623 return sizeof(LOGFONTW);
624 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
625 memcpy( buffer, &font->logfont, count );
626 return count;
630 /***********************************************************************
631 * FONT_DeleteObject
633 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
635 WineEngDestroyFontInstance( handle );
636 return GDI_FreeObject( handle, obj );
640 /***********************************************************************
641 * FONT_EnumInstance16
643 * Called by the device driver layer to pass font info
644 * down to the application.
646 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
647 * We have to use other types because of the FONTENUMPROCW definition.
649 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
650 DWORD fType, LPARAM lp )
652 fontEnum16 *pfe = (fontEnum16*)lp;
653 INT ret = 1;
654 DC *dc;
656 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
657 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
659 WORD args[7];
660 DWORD result;
662 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
663 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
664 pfe->dwFlags |= ENUM_CALLED;
665 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
667 args[6] = SELECTOROF(pfe->segLogFont);
668 args[5] = OFFSETOF(pfe->segLogFont);
669 args[4] = SELECTOROF(pfe->segTextMetric);
670 args[3] = OFFSETOF(pfe->segTextMetric);
671 args[2] = fType;
672 args[1] = HIWORD(pfe->lpData);
673 args[0] = LOWORD(pfe->lpData);
674 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
675 ret = LOWORD(result);
677 /* get the lock again and make sure the DC is still valid */
678 dc = DC_GetDCPtr( pfe->hdc );
679 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
681 if (dc) GDI_ReleaseObj( pfe->hdc );
682 pfe->hdc = 0; /* make sure we don't try to release it later on */
683 ret = 0;
686 return ret;
689 /***********************************************************************
690 * FONT_EnumInstance
692 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
693 * We have to use other types because of the FONTENUMPROCW definition.
695 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
696 DWORD fType, LPARAM lp )
698 fontEnum32 *pfe = (fontEnum32*)lp;
699 INT ret = 1;
700 DC *dc;
702 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
703 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
704 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
705 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
707 /* convert font metrics */
708 ENUMLOGFONTEXA logfont;
709 NEWTEXTMETRICEXA tmA;
711 pfe->dwFlags |= ENUM_CALLED;
712 if (!(pfe->dwFlags & ENUM_UNICODE))
714 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
715 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
716 plf = (LOGFONTW *)&logfont.elfLogFont;
717 ptm = (TEXTMETRICW *)&tmA;
719 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
721 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
723 /* get the lock again and make sure the DC is still valid */
724 dc = DC_GetDCPtr( pfe->hdc );
725 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
727 if (dc) GDI_ReleaseObj( pfe->hdc );
728 pfe->hdc = 0; /* make sure we don't try to release it later on */
729 ret = 0;
732 return ret;
735 /***********************************************************************
736 * EnumFontFamiliesEx (GDI.613)
738 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
739 FONTENUMPROC16 efproc, LPARAM lParam,
740 DWORD dwFlags)
742 fontEnum16 fe16;
743 INT16 ret = 1, ret2;
744 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
745 NEWTEXTMETRICEX16 tm16;
746 ENUMLOGFONTEX16 lf16;
747 LOGFONTW lfW;
748 BOOL enum_gdi_fonts;
750 if (!dc) return 0;
751 FONT_LogFont16ToW(plf, &lfW);
753 fe16.hdc = HDC_32(hDC);
754 fe16.dc = dc;
755 fe16.physDev = dc->physDev;
756 fe16.lpLogFontParam = plf;
757 fe16.lpEnumFunc = efproc;
758 fe16.lpData = lParam;
759 fe16.lpTextMetric = &tm16;
760 fe16.lpLogFont = &lf16;
761 fe16.segTextMetric = MapLS( &tm16 );
762 fe16.segLogFont = MapLS( &lf16 );
763 fe16.dwFlags = 0;
765 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
767 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
769 ret = 0;
770 goto done;
773 if (enum_gdi_fonts)
774 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
775 fe16.dwFlags &= ~ENUM_CALLED;
776 if (ret && dc->funcs->pEnumDeviceFonts) {
777 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
778 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
779 ret = ret2;
781 done:
782 UnMapLS( fe16.segTextMetric );
783 UnMapLS( fe16.segLogFont );
784 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
785 return ret;
788 /***********************************************************************
789 * FONT_EnumFontFamiliesEx
791 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
792 FONTENUMPROCW efproc,
793 LPARAM lParam, DWORD dwUnicode)
795 INT ret = 1, ret2;
796 DC *dc = DC_GetDCPtr( hDC );
797 fontEnum32 fe32;
798 BOOL enum_gdi_fonts;
800 if (!dc) return 0;
802 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
803 plf->lfCharSet);
804 fe32.lpLogFontParam = plf;
805 fe32.lpEnumFunc = efproc;
806 fe32.lpData = lParam;
807 fe32.dwFlags = dwUnicode;
808 fe32.hdc = hDC;
809 fe32.dc = dc;
810 fe32.physDev = dc->physDev;
812 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
814 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
816 ret = 0;
817 goto done;
820 if (enum_gdi_fonts)
821 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
822 fe32.dwFlags &= ~ENUM_CALLED;
823 if (ret && dc->funcs->pEnumDeviceFonts) {
824 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
825 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
826 ret = ret2;
828 done:
829 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
830 return ret;
833 /***********************************************************************
834 * EnumFontFamiliesExW (GDI32.@)
836 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
837 FONTENUMPROCW efproc,
838 LPARAM lParam, DWORD dwFlags )
840 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
843 /***********************************************************************
844 * EnumFontFamiliesExA (GDI32.@)
846 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
847 FONTENUMPROCA efproc,
848 LPARAM lParam, DWORD dwFlags)
850 LOGFONTW lfW;
851 FONT_LogFontAToW( plf, &lfW );
853 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
856 /***********************************************************************
857 * EnumFontFamilies (GDI.330)
859 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
860 FONTENUMPROC16 efproc, LPARAM lpData )
862 LOGFONT16 lf;
864 lf.lfCharSet = DEFAULT_CHARSET;
865 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
866 else lf.lfFaceName[0] = '\0';
868 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
871 /***********************************************************************
872 * EnumFontFamiliesA (GDI32.@)
874 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
875 FONTENUMPROCA efproc, LPARAM lpData )
877 LOGFONTA lf;
879 lf.lfCharSet = DEFAULT_CHARSET;
880 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
881 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
883 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
886 /***********************************************************************
887 * EnumFontFamiliesW (GDI32.@)
889 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
890 FONTENUMPROCW efproc, LPARAM lpData )
892 LOGFONTW lf;
894 lf.lfCharSet = DEFAULT_CHARSET;
895 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
896 else lf.lfFaceName[0] = 0;
898 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
901 /***********************************************************************
902 * EnumFonts (GDI.70)
904 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
905 LPARAM lpData )
907 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
910 /***********************************************************************
911 * EnumFontsA (GDI32.@)
913 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
914 LPARAM lpData )
916 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
919 /***********************************************************************
920 * EnumFontsW (GDI32.@)
922 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
923 LPARAM lpData )
925 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
929 /***********************************************************************
930 * GetTextCharacterExtra (GDI32.@)
932 INT WINAPI GetTextCharacterExtra( HDC hdc )
934 INT ret;
935 DC *dc = DC_GetDCPtr( hdc );
936 if (!dc) return 0x80000000;
937 ret = dc->charExtra;
938 GDI_ReleaseObj( hdc );
939 return ret;
943 /***********************************************************************
944 * SetTextCharacterExtra (GDI32.@)
946 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
948 INT prev;
949 DC * dc = DC_GetDCPtr( hdc );
950 if (!dc) return 0x80000000;
951 if (dc->funcs->pSetTextCharacterExtra)
952 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
953 else
955 prev = dc->charExtra;
956 dc->charExtra = extra;
958 GDI_ReleaseObj( hdc );
959 return prev;
963 /***********************************************************************
964 * SetTextJustification (GDI32.@)
966 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
968 BOOL ret = TRUE;
969 DC * dc = DC_GetDCPtr( hdc );
970 if (!dc) return FALSE;
971 if (dc->funcs->pSetTextJustification)
972 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
973 else
975 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
976 if (!extra) breaks = 0;
977 if (breaks)
979 dc->breakExtra = extra / breaks;
980 dc->breakRem = extra - (breaks * dc->breakExtra);
982 else
984 dc->breakExtra = 0;
985 dc->breakRem = 0;
988 GDI_ReleaseObj( hdc );
989 return ret;
993 /***********************************************************************
994 * GetTextFaceA (GDI32.@)
996 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
998 INT res = GetTextFaceW(hdc, 0, NULL);
999 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1000 GetTextFaceW( hdc, res, nameW );
1002 if (name)
1004 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1005 name[count-1] = 0;
1006 res = strlen(name);
1008 else
1009 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1010 HeapFree( GetProcessHeap(), 0, nameW );
1011 return res;
1014 /***********************************************************************
1015 * GetTextFaceW (GDI32.@)
1017 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1019 FONTOBJ *font;
1020 INT ret = 0;
1022 DC * dc = DC_GetDCPtr( hdc );
1023 if (!dc) return 0;
1025 if(dc->gdiFont)
1026 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1027 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1029 if (name)
1031 lstrcpynW( name, font->logfont.lfFaceName, count );
1032 ret = strlenW(name);
1034 else ret = strlenW(font->logfont.lfFaceName) + 1;
1035 GDI_ReleaseObj( dc->hFont );
1037 GDI_ReleaseObj( hdc );
1038 return ret;
1042 /***********************************************************************
1043 * GetTextExtentPoint32A (GDI32.@)
1045 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1046 LPSIZE size )
1048 BOOL ret = FALSE;
1049 INT wlen;
1050 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1052 if (p) {
1053 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1054 HeapFree( GetProcessHeap(), 0, p );
1057 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1058 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1059 return ret;
1063 /***********************************************************************
1064 * GetTextExtentPoint32W [GDI32.@]
1066 * Computes width/height for a string.
1068 * Computes width and height of the specified string.
1070 * RETURNS
1071 * Success: TRUE
1072 * Failure: FALSE
1074 BOOL WINAPI GetTextExtentPoint32W(
1075 HDC hdc, /* [in] Handle of device context */
1076 LPCWSTR str, /* [in] Address of text string */
1077 INT count, /* [in] Number of characters in string */
1078 LPSIZE size) /* [out] Address of structure for string size */
1080 BOOL ret = FALSE;
1081 DC * dc = DC_GetDCPtr( hdc );
1082 if (!dc) return FALSE;
1084 if(dc->gdiFont)
1085 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1086 else if(dc->funcs->pGetTextExtentPoint)
1087 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1089 if (ret)
1091 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1092 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1093 size->cx += count * dc->charExtra + dc->breakRem;
1096 GDI_ReleaseObj( hdc );
1098 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1099 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1100 return ret;
1103 /***********************************************************************
1104 * GetTextExtentPointI [GDI32.@]
1106 * Computes width and height of the array of glyph indices.
1108 * RETURNS
1109 * Success: TRUE
1110 * Failure: FALSE
1112 BOOL WINAPI GetTextExtentPointI(
1113 HDC hdc, /* [in] Handle of device context */
1114 const WORD *indices, /* [in] Address of glyph index array */
1115 INT count, /* [in] Number of glyphs in array */
1116 LPSIZE size) /* [out] Address of structure for string size */
1118 BOOL ret = FALSE;
1119 DC * dc = DC_GetDCPtr( hdc );
1120 if (!dc) return FALSE;
1122 if(dc->gdiFont) {
1123 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1124 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1125 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1126 size->cx += count * dc->charExtra;
1128 else if(dc->funcs->pGetTextExtentPoint) {
1129 FIXME("calling GetTextExtentPoint\n");
1130 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1133 GDI_ReleaseObj( hdc );
1135 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1136 hdc, indices, count, size, size->cx, size->cy );
1137 return ret;
1141 /***********************************************************************
1142 * GetTextExtentPointA (GDI32.@)
1144 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1145 LPSIZE size )
1147 TRACE("not bug compatible.\n");
1148 return GetTextExtentPoint32A( hdc, str, count, size );
1151 /***********************************************************************
1152 * GetTextExtentPointW (GDI32.@)
1154 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1155 LPSIZE size )
1157 TRACE("not bug compatible.\n");
1158 return GetTextExtentPoint32W( hdc, str, count, size );
1162 /***********************************************************************
1163 * GetTextExtentExPointA (GDI32.@)
1165 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1166 INT maxExt, LPINT lpnFit,
1167 LPINT alpDx, LPSIZE size )
1169 BOOL ret;
1170 INT wlen;
1171 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1172 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1173 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1174 HeapFree( GetProcessHeap(), 0, p );
1175 return ret;
1179 /***********************************************************************
1180 * GetTextExtentExPointW (GDI32.@)
1182 * Return the size of the string as it would be if it was output properly by
1183 * e.g. TextOut.
1185 * This should include
1186 * - Intercharacter spacing
1187 * - justification spacing (not yet done)
1188 * - kerning? see below
1190 * Kerning. Since kerning would be carried out by the rendering code it should
1191 * be done by the driver. However they don't support it yet. Also I am not
1192 * yet persuaded that (certainly under Win95) any kerning is actually done.
1194 * str: According to MSDN this should be null-terminated. That is not true; a
1195 * null will not terminate it early.
1196 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1197 * than count. I have seen it be either the size of the full string or
1198 * 1 less than the size of the full string. I have not seen it bear any
1199 * resemblance to the portion that would fit.
1200 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1201 * trailing intercharacter spacing and any trailing justification.
1203 * FIXME
1204 * Currently we do this by measuring each character etc. We should do it by
1205 * passing the request to the driver, perhaps by extending the
1206 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1207 * thinking about kerning issues and rounding issues in the justification.
1210 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1211 INT maxExt, LPINT lpnFit,
1212 LPINT alpDx, LPSIZE size )
1214 int index, nFit, extent;
1215 SIZE tSize;
1216 BOOL ret = FALSE;
1218 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1220 size->cx = size->cy = nFit = extent = 0;
1221 for(index = 0; index < count; index++)
1223 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1224 /* GetTextExtentPoint includes intercharacter spacing. */
1225 /* FIXME - justification needs doing yet. Remember that the base
1226 * data will not be in logical coordinates.
1228 extent += tSize.cx;
1229 if( !lpnFit || extent <= maxExt )
1230 /* It is allowed to be equal. */
1232 nFit++;
1233 if( alpDx ) alpDx[index] = extent;
1235 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1236 str++;
1238 size->cx = extent;
1239 if(lpnFit) *lpnFit = nFit;
1240 ret = TRUE;
1242 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1244 done:
1245 return ret;
1248 /***********************************************************************
1249 * GetTextMetricsA (GDI32.@)
1251 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1253 TEXTMETRICW tm32;
1255 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1256 FONT_TextMetricWToA( &tm32, metrics );
1257 return TRUE;
1260 /***********************************************************************
1261 * GetTextMetricsW (GDI32.@)
1263 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1265 BOOL ret = FALSE;
1266 DC * dc = DC_GetDCPtr( hdc );
1267 if (!dc) return FALSE;
1269 if (dc->gdiFont)
1270 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1271 else if (dc->funcs->pGetTextMetrics)
1272 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1274 if (ret)
1276 /* device layer returns values in device units
1277 * therefore we have to convert them to logical */
1279 #define WDPTOLP(x) ((x<0)? \
1280 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1281 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1282 #define HDPTOLP(y) ((y<0)? \
1283 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1284 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1286 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1287 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1288 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1289 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1290 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1291 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1292 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1293 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1294 ret = TRUE;
1295 #undef WDPTOLP
1296 #undef HDPTOLP
1297 TRACE("text metrics:\n"
1298 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1299 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1300 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1301 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1302 " PitchAndFamily = %02x\n"
1303 " --------------------\n"
1304 " InternalLeading = %li\n"
1305 " Ascent = %li\n"
1306 " Descent = %li\n"
1307 " Height = %li\n",
1308 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1309 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1310 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1311 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1312 metrics->tmPitchAndFamily,
1313 metrics->tmInternalLeading,
1314 metrics->tmAscent,
1315 metrics->tmDescent,
1316 metrics->tmHeight );
1318 GDI_ReleaseObj( hdc );
1319 return ret;
1323 /***********************************************************************
1324 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1326 * NOTES
1327 * lpOTM should be LPOUTLINETEXTMETRIC
1329 * RETURNS
1330 * Success: Non-zero or size of required buffer
1331 * Failure: 0
1333 UINT16 WINAPI GetOutlineTextMetrics16(
1334 HDC16 hdc, /* [in] Handle of device context */
1335 UINT16 cbData, /* [in] Size of metric data array */
1336 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1338 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1339 return 0;
1343 /***********************************************************************
1344 * GetOutlineTextMetricsA (GDI32.@)
1345 * Gets metrics for TrueType fonts.
1347 * NOTES
1348 * If the supplied buffer isn't big enough Windows partially fills it up to
1349 * its given length and returns that length.
1351 * RETURNS
1352 * Success: Non-zero or size of required buffer
1353 * Failure: 0
1355 UINT WINAPI GetOutlineTextMetricsA(
1356 HDC hdc, /* [in] Handle of device context */
1357 UINT cbData, /* [in] Size of metric data array */
1358 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1360 char buf[512], *ptr;
1361 UINT ret, needed;
1362 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1363 OUTLINETEXTMETRICA *output = lpOTM;
1364 INT left, len;
1366 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1367 return 0;
1368 if(ret > sizeof(buf))
1369 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1370 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1372 needed = sizeof(OUTLINETEXTMETRICA);
1373 if(lpOTMW->otmpFamilyName)
1374 needed += WideCharToMultiByte(CP_ACP, 0,
1375 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1376 NULL, 0, NULL, NULL);
1377 if(lpOTMW->otmpFaceName)
1378 needed += WideCharToMultiByte(CP_ACP, 0,
1379 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1380 NULL, 0, NULL, NULL);
1381 if(lpOTMW->otmpStyleName)
1382 needed += WideCharToMultiByte(CP_ACP, 0,
1383 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1384 NULL, 0, NULL, NULL);
1385 if(lpOTMW->otmpFullName)
1386 needed += WideCharToMultiByte(CP_ACP, 0,
1387 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1388 NULL, 0, NULL, NULL);
1390 if(!lpOTM) {
1391 ret = needed;
1392 goto end;
1395 TRACE("needed = %d\n", needed);
1396 if(needed > cbData)
1397 /* Since the supplied buffer isn't big enough, we'll alloc one
1398 that is and memcpy the first cbData bytes into the lpOTM at
1399 the end. */
1400 output = HeapAlloc(GetProcessHeap(), 0, needed);
1402 ret = output->otmSize = min(needed, cbData);
1403 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1404 output->otmFiller = 0;
1405 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1406 output->otmfsSelection = lpOTMW->otmfsSelection;
1407 output->otmfsType = lpOTMW->otmfsType;
1408 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1409 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1410 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1411 output->otmEMSquare = lpOTMW->otmEMSquare;
1412 output->otmAscent = lpOTMW->otmAscent;
1413 output->otmDescent = lpOTMW->otmDescent;
1414 output->otmLineGap = lpOTMW->otmLineGap;
1415 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1416 output->otmsXHeight = lpOTMW->otmsXHeight;
1417 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1418 output->otmMacAscent = lpOTMW->otmMacAscent;
1419 output->otmMacDescent = lpOTMW->otmMacDescent;
1420 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1421 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1422 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1423 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1424 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1425 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1426 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1427 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1428 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1429 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1432 ptr = (char*)(output + 1);
1433 left = needed - sizeof(*output);
1435 if(lpOTMW->otmpFamilyName) {
1436 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1437 len = WideCharToMultiByte(CP_ACP, 0,
1438 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1439 ptr, left, NULL, NULL);
1440 left -= len;
1441 ptr += len;
1442 } else
1443 output->otmpFamilyName = 0;
1445 if(lpOTMW->otmpFaceName) {
1446 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1447 len = WideCharToMultiByte(CP_ACP, 0,
1448 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1449 ptr, left, NULL, NULL);
1450 left -= len;
1451 ptr += len;
1452 } else
1453 output->otmpFaceName = 0;
1455 if(lpOTMW->otmpStyleName) {
1456 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1457 len = WideCharToMultiByte(CP_ACP, 0,
1458 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1459 ptr, left, NULL, NULL);
1460 left -= len;
1461 ptr += len;
1462 } else
1463 output->otmpStyleName = 0;
1465 if(lpOTMW->otmpFullName) {
1466 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1467 len = WideCharToMultiByte(CP_ACP, 0,
1468 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1469 ptr, left, NULL, NULL);
1470 left -= len;
1471 } else
1472 output->otmpFullName = 0;
1474 assert(left == 0);
1476 if(output != lpOTM) {
1477 memcpy(lpOTM, output, cbData);
1478 HeapFree(GetProcessHeap(), 0, output);
1481 end:
1482 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1483 HeapFree(GetProcessHeap(), 0, lpOTMW);
1485 return ret;
1489 /***********************************************************************
1490 * GetOutlineTextMetricsW [GDI32.@]
1492 UINT WINAPI GetOutlineTextMetricsW(
1493 HDC hdc, /* [in] Handle of device context */
1494 UINT cbData, /* [in] Size of metric data array */
1495 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1497 DC *dc = DC_GetDCPtr( hdc );
1498 OUTLINETEXTMETRICW *output = lpOTM;
1499 UINT ret;
1501 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1502 if(!dc) return 0;
1504 if(dc->gdiFont) {
1505 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1506 if(lpOTM && ret) {
1507 if(ret > cbData) {
1508 output = HeapAlloc(GetProcessHeap(), 0, ret);
1509 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1512 #define WDPTOLP(x) ((x<0)? \
1513 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1514 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1515 #define HDPTOLP(y) ((y<0)? \
1516 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1517 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1519 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1520 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1521 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1522 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1523 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1524 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1525 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1526 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1527 output->otmAscent = HDPTOLP(output->otmAscent);
1528 output->otmDescent = HDPTOLP(output->otmDescent);
1529 output->otmLineGap = HDPTOLP(output->otmLineGap);
1530 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1531 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1532 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1533 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1534 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1535 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1536 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1537 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1538 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1539 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1540 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1541 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1542 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1543 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1544 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1545 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1546 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1547 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1548 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1549 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1550 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1551 #undef WDPTOLP
1552 #undef HDPTOLP
1553 if(output != lpOTM) {
1554 memcpy(lpOTM, output, cbData);
1555 HeapFree(GetProcessHeap(), 0, output);
1556 ret = cbData;
1561 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1562 but really this should just be a return 0. */
1564 ret = sizeof(*lpOTM);
1565 if (lpOTM) {
1566 if(cbData < ret)
1567 ret = 0;
1568 else {
1569 memset(lpOTM, 0, ret);
1570 lpOTM->otmSize = sizeof(*lpOTM);
1571 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1573 Further fill of the structure not implemented,
1574 Needs real values for the structure members
1579 GDI_ReleaseObj(hdc);
1580 return ret;
1584 /***********************************************************************
1585 * GetCharWidthW (GDI32.@)
1586 * GetCharWidth32W (GDI32.@)
1588 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1589 LPINT buffer )
1591 UINT i;
1592 BOOL ret = FALSE;
1593 DC * dc = DC_GetDCPtr( hdc );
1594 if (!dc) return FALSE;
1596 if (dc->gdiFont)
1597 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1598 else if (dc->funcs->pGetCharWidth)
1599 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1601 if (ret)
1603 /* convert device units to logical */
1604 for( i = firstChar; i <= lastChar; i++, buffer++ )
1605 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1606 ret = TRUE;
1608 GDI_ReleaseObj( hdc );
1609 return ret;
1613 /***********************************************************************
1614 * GetCharWidthA (GDI32.@)
1615 * GetCharWidth32A (GDI32.@)
1617 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1618 LPINT buffer )
1620 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1621 LPSTR str;
1622 LPWSTR wstr;
1623 BOOL ret = TRUE;
1625 if(count <= 0) return FALSE;
1627 str = HeapAlloc(GetProcessHeap(), 0, count);
1628 for(i = 0; i < count; i++)
1629 str[i] = (BYTE)(firstChar + i);
1631 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1633 for(i = 0; i < wlen; i++)
1635 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1637 ret = FALSE;
1638 break;
1640 buffer++;
1643 HeapFree(GetProcessHeap(), 0, str);
1644 HeapFree(GetProcessHeap(), 0, wstr);
1646 return ret;
1650 /***********************************************************************
1651 * ExtTextOutA (GDI32.@)
1653 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1654 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1656 INT wlen;
1657 UINT codepage;
1658 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1659 BOOL ret;
1660 LPINT lpDxW = NULL;
1662 if (lpDx) {
1663 unsigned int i = 0, j = 0;
1665 lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1666 while(i < count) {
1667 if(IsDBCSLeadByteEx(codepage, str[i])) {
1668 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1669 i = i + 2;
1670 } else {
1671 lpDxW[j++] = lpDx[i];
1672 i = i + 1;
1677 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1679 HeapFree( GetProcessHeap(), 0, p );
1680 if (lpDxW) HeapFree( GetProcessHeap(), 0, lpDxW );
1681 return ret;
1685 /***********************************************************************
1686 * ExtTextOutW (GDI32.@)
1688 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1689 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1691 BOOL ret = FALSE;
1692 DC * dc = DC_GetDCUpdate( hdc );
1693 if (dc)
1695 if(PATH_IsPathOpen(dc->path))
1696 FIXME("called on an open path\n");
1697 else if(dc->funcs->pExtTextOut)
1699 if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
1701 /* The caller did not specify that language processing was already done.
1703 LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1705 BIDI_Reorder( str, count, GCP_REORDER,
1706 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1707 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1708 lpReorderedString, count, NULL );
1710 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
1711 lprect,lpReorderedString,count,lpDx,dc->breakExtra);
1712 HeapFree(GetProcessHeap(), 0, lpReorderedString);
1713 } else
1714 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,
1715 lpDx,dc->breakExtra);
1717 GDI_ReleaseObj( hdc );
1719 return ret;
1723 /***********************************************************************
1724 * TextOutA (GDI32.@)
1726 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
1728 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
1732 /***********************************************************************
1733 * TextOutW (GDI32.@)
1735 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
1737 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
1741 /***********************************************************************
1742 * PolyTextOutA (GDI32.@)
1744 * Draw several Strings
1746 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
1747 PPOLYTEXTA pptxt, /* [in] Array of strings */
1748 INT cStrings ) /* [in] Number of strings in array */
1750 for (; cStrings>0; cStrings--, pptxt++)
1751 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
1752 return FALSE;
1753 return TRUE;
1758 /***********************************************************************
1759 * PolyTextOutW (GDI32.@)
1761 * Draw several Strings
1763 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
1764 PPOLYTEXTW pptxt, /* [in] Array of strings */
1765 INT cStrings ) /* [in] Number of strings in array */
1767 for (; cStrings>0; cStrings--, pptxt++)
1768 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
1769 return FALSE;
1770 return TRUE;
1774 /* FIXME: all following APIs ******************************************/
1777 /***********************************************************************
1778 * SetMapperFlags (GDI32.@)
1780 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1782 DC *dc = DC_GetDCPtr( hDC );
1783 DWORD ret = 0;
1784 if(!dc) return 0;
1785 if(dc->funcs->pSetMapperFlags)
1786 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1787 else
1788 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1789 GDI_ReleaseObj( hDC );
1790 return ret;
1793 /***********************************************************************
1794 * GetAspectRatioFilterEx (GDI.486)
1796 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1798 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1799 return FALSE;
1802 /***********************************************************************
1803 * GetAspectRatioFilterEx (GDI32.@)
1805 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1807 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1808 return FALSE;
1812 /***********************************************************************
1813 * GetCharABCWidthsA (GDI32.@)
1815 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1816 LPABC abc )
1818 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1819 LPSTR str;
1820 LPWSTR wstr;
1821 BOOL ret = TRUE;
1823 if(count <= 0) return FALSE;
1825 str = HeapAlloc(GetProcessHeap(), 0, count);
1826 for(i = 0; i < count; i++)
1827 str[i] = (BYTE)(firstChar + i);
1829 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1831 for(i = 0; i < wlen; i++)
1833 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1835 ret = FALSE;
1836 break;
1838 abc++;
1841 HeapFree(GetProcessHeap(), 0, str);
1842 HeapFree(GetProcessHeap(), 0, wstr);
1844 return ret;
1848 /******************************************************************************
1849 * GetCharABCWidthsW [GDI32.@]
1851 * Retrieves widths of characters in range.
1853 * PARAMS
1854 * hdc [I] Handle of device context
1855 * firstChar [I] First character in range to query
1856 * lastChar [I] Last character in range to query
1857 * abc [O] Address of character-width structure
1859 * NOTES
1860 * Only works with TrueType fonts
1862 * RETURNS
1863 * Success: TRUE
1864 * Failure: FALSE
1866 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1867 LPABC abc )
1869 DC *dc = DC_GetDCPtr(hdc);
1870 unsigned int i;
1871 BOOL ret = FALSE;
1873 if(dc->gdiFont)
1874 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1875 else
1876 FIXME(": stub\n");
1878 if (ret)
1880 /* convert device units to logical */
1881 for( i = firstChar; i <= lastChar; i++, abc++ ) {
1882 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1883 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1884 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1886 ret = TRUE;
1889 GDI_ReleaseObj(hdc);
1890 return ret;
1894 /***********************************************************************
1895 * GetGlyphOutline (GDI.309)
1897 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1898 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1899 LPVOID lpBuffer, const MAT2 *lpmat2 )
1901 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1902 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1903 return ~0UL; /* failure */
1907 /***********************************************************************
1908 * GetGlyphOutlineA (GDI32.@)
1910 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1911 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1912 LPVOID lpBuffer, const MAT2 *lpmat2 )
1914 LPWSTR p = NULL;
1915 DWORD ret;
1916 UINT c;
1918 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1919 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1920 c = p[0];
1921 } else
1922 c = uChar;
1923 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1924 lpmat2);
1925 if(p)
1926 HeapFree(GetProcessHeap(), 0, p);
1927 return ret;
1930 /***********************************************************************
1931 * GetGlyphOutlineW (GDI32.@)
1933 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1934 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1935 LPVOID lpBuffer, const MAT2 *lpmat2 )
1937 DC *dc = DC_GetDCPtr(hdc);
1938 DWORD ret;
1940 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1941 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1943 if(!dc) return GDI_ERROR;
1945 if(dc->gdiFont)
1946 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1947 cbBuffer, lpBuffer, lpmat2);
1948 else
1949 ret = GDI_ERROR;
1951 GDI_ReleaseObj(hdc);
1952 return ret;
1956 /***********************************************************************
1957 * CreateScalableFontResourceA (GDI32.@)
1959 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1960 LPCSTR lpszResourceFile,
1961 LPCSTR lpszFontFile,
1962 LPCSTR lpszCurrentPath )
1964 HANDLE f;
1966 /* fHidden=1 - only visible for the calling app, read-only, not
1967 * enumbered with EnumFonts/EnumFontFamilies
1968 * lpszCurrentPath can be NULL
1970 FIXME("(%ld,%s,%s,%s): stub\n",
1971 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1972 debugstr_a(lpszCurrentPath) );
1974 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1975 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1976 CloseHandle(f);
1977 SetLastError(ERROR_FILE_EXISTS);
1978 return FALSE;
1980 return FALSE; /* create failed */
1983 /***********************************************************************
1984 * CreateScalableFontResourceW (GDI32.@)
1986 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1987 LPCWSTR lpszResourceFile,
1988 LPCWSTR lpszFontFile,
1989 LPCWSTR lpszCurrentPath )
1991 FIXME("(%ld,%p,%p,%p): stub\n",
1992 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1993 return FALSE; /* create failed */
1997 /*************************************************************************
1998 * GetRasterizerCaps (GDI32.@)
2000 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
2002 lprs->nSize = sizeof(RASTERIZER_STATUS);
2003 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
2004 lprs->nLanguageID = 0;
2005 return TRUE;
2009 /*************************************************************************
2010 * GetKerningPairsA (GDI32.@)
2012 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2013 LPKERNINGPAIR lpKerningPairs )
2015 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2019 /*************************************************************************
2020 * GetKerningPairsW (GDI32.@)
2022 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2023 LPKERNINGPAIR lpKerningPairs )
2025 unsigned int i;
2026 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2027 for (i = 0; i < cPairs; i++)
2028 lpKerningPairs[i].iKernAmount = 0;
2029 return 0;
2032 /*************************************************************************
2033 * TranslateCharsetInfo [GDI32.@]
2035 * Fills a CHARSETINFO structure for a character set, code page, or
2036 * font. This allows making the correspondance between different labelings
2037 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2038 * of the same encoding.
2040 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2041 * only one codepage should be set in *lpSrc.
2043 * RETURNS
2044 * TRUE on success, FALSE on failure.
2047 BOOL WINAPI TranslateCharsetInfo(
2048 LPDWORD lpSrc, /* [in]
2049 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2050 if flags == TCI_SRCCHARSET: a character set value
2051 if flags == TCI_SRCCODEPAGE: a code page value
2053 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2054 DWORD flags /* [in] determines interpretation of lpSrc */)
2056 int index = 0;
2057 switch (flags) {
2058 case TCI_SRCFONTSIG:
2059 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2060 break;
2061 case TCI_SRCCODEPAGE:
2062 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2063 break;
2064 case TCI_SRCCHARSET:
2065 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2066 break;
2067 default:
2068 return FALSE;
2070 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2071 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2072 return TRUE;
2075 /*************************************************************************
2076 * GetFontLanguageInfo (GDI32.@)
2078 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2080 FONTSIGNATURE fontsig;
2081 static const DWORD GCP_DBCS_MASK=0x003F0000,
2082 GCP_DIACRITIC_MASK=0x00000000,
2083 FLI_GLYPHS_MASK=0x00000000,
2084 GCP_GLYPHSHAPE_MASK=0x00000040,
2085 GCP_KASHIDA_MASK=0x00000000,
2086 GCP_LIGATE_MASK=0x00000000,
2087 GCP_USEKERNING_MASK=0x00000000,
2088 GCP_REORDER_MASK=0x00000060;
2090 DWORD result=0;
2092 GetTextCharsetInfo( hdc, &fontsig, 0 );
2093 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2095 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2096 result|=GCP_DBCS;
2098 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2099 result|=GCP_DIACRITIC;
2101 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2102 result|=FLI_GLYPHS;
2104 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2105 result|=GCP_GLYPHSHAPE;
2107 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2108 result|=GCP_KASHIDA;
2110 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2111 result|=GCP_LIGATE;
2113 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2114 result|=GCP_USEKERNING;
2116 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2117 if( GetTextAlign( hdc) & TA_RTLREADING )
2118 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2119 result|=GCP_REORDER;
2121 return result;
2125 /*************************************************************************
2126 * GetFontData [GDI32.@]
2128 * Retrieve data for TrueType font.
2130 * RETURNS
2132 * success: Number of bytes returned
2133 * failure: GDI_ERROR
2135 * NOTES
2137 * Calls SetLastError()
2140 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2141 LPVOID buffer, DWORD length)
2143 DC *dc = DC_GetDCPtr(hdc);
2144 DWORD ret = GDI_ERROR;
2146 if(!dc) return GDI_ERROR;
2148 if(dc->gdiFont)
2149 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2151 GDI_ReleaseObj(hdc);
2152 return ret;
2155 /*************************************************************************
2156 * GetGlyphIndicesA [GDI32.@]
2158 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2159 LPWORD pgi, DWORD flags)
2161 DWORD ret;
2162 WCHAR *lpstrW;
2163 INT countW;
2165 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2166 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2168 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2169 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2170 HeapFree(GetProcessHeap(), 0, lpstrW);
2172 return ret;
2175 /*************************************************************************
2176 * GetGlyphIndicesW [GDI32.@]
2178 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2179 LPWORD pgi, DWORD flags)
2181 DC *dc = DC_GetDCPtr(hdc);
2182 DWORD ret = GDI_ERROR;
2184 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2185 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2187 if(!dc) return GDI_ERROR;
2189 if(dc->gdiFont)
2190 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2192 GDI_ReleaseObj(hdc);
2193 return ret;
2196 /*************************************************************************
2197 * GetCharacterPlacementA [GDI32.@]
2199 * NOTES:
2200 * the web browser control of ie4 calls this with dwFlags=0
2202 DWORD WINAPI
2203 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2204 INT nMaxExtent, GCP_RESULTSA *lpResults,
2205 DWORD dwFlags)
2207 WCHAR *lpStringW;
2208 INT uCountW;
2209 GCP_RESULTSW resultsW;
2210 DWORD ret;
2211 UINT font_cp;
2213 TRACE("%s, %d, %d, 0x%08lx\n",
2214 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2216 /* both structs are equal in size */
2217 memcpy(&resultsW, lpResults, sizeof(resultsW));
2219 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2220 if(lpResults->lpOutString)
2221 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2223 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2225 if(lpResults->lpOutString) {
2226 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2227 lpResults->lpOutString, uCount, NULL, NULL );
2230 HeapFree(GetProcessHeap(), 0, lpStringW);
2231 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2233 return ret;
2236 /*************************************************************************
2237 * GetCharacterPlacementW [GDI32.@]
2239 * Retrieve information about a string. This includes the width, reordering,
2240 * Glyphing and so on.
2242 * RETURNS
2244 * The width and height of the string if successful, 0 if failed.
2246 * BUGS
2248 * All flags except GCP_REORDER are not yet implemented.
2249 * Reordering is not 100% complient to the Windows BiDi method.
2250 * Caret positioning is not yet implemented for BiDi.
2251 * Classes are not yet implemented.
2254 DWORD WINAPI
2255 GetCharacterPlacementW(
2256 HDC hdc, /* [in] Device context for which the rendering is to be done */
2257 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2258 INT uCount, /* [in] Number of WORDS in string. */
2259 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2260 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2261 DWORD dwFlags /* [in] Flags specifying how to process the string */
2264 DWORD ret=0;
2265 SIZE size;
2266 UINT i, nSet;
2268 TRACE("%s, %d, %d, 0x%08lx\n",
2269 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2271 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2272 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2273 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2274 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2275 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2277 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2278 if(lpResults->lpClass) FIXME("classes not implemented\n");
2279 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2280 FIXME("Caret positions for complex scripts not implemented\n");
2282 nSet = (UINT)uCount;
2283 if(nSet > lpResults->nGlyphs)
2284 nSet = lpResults->nGlyphs;
2286 /* return number of initialized fields */
2287 lpResults->nGlyphs = nSet;
2289 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2291 /* Treat the case where no special handling was requested in a fastpath way */
2292 /* copy will do if the GCP_REORDER flag is not set */
2293 if(lpResults->lpOutString)
2294 strncpyW( lpResults->lpOutString, lpString, nSet );
2296 if(lpResults->lpOrder)
2298 for(i = 0; i < nSet; i++)
2299 lpResults->lpOrder[i] = i;
2301 } else
2303 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2304 nSet, lpResults->lpOrder );
2307 /* FIXME: Will use the placement chars */
2308 if (lpResults->lpDx)
2310 int c;
2311 for (i = 0; i < nSet; i++)
2313 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2314 lpResults->lpDx[i]= c;
2318 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2320 int pos = 0;
2322 lpResults->lpCaretPos[0] = 0;
2323 for (i = 1; i < nSet; i++)
2324 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2325 lpResults->lpCaretPos[i] = (pos += size.cx);
2328 if(lpResults->lpGlyphs)
2329 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2331 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2332 ret = MAKELONG(size.cx, size.cy);
2334 return ret;
2337 /*************************************************************************
2338 * GetCharABCWidthsFloatA [GDI32.@]
2340 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2341 LPABCFLOAT lpABCF)
2343 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2344 return 0;
2347 /*************************************************************************
2348 * GetCharABCWidthsFloatW [GDI32.@]
2350 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2351 UINT iLastChar, LPABCFLOAT lpABCF)
2353 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2354 return 0;
2357 /*************************************************************************
2358 * GetCharWidthFloatA [GDI32.@]
2360 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2361 UINT iLastChar, PFLOAT pxBuffer)
2363 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2364 return 0;
2367 /*************************************************************************
2368 * GetCharWidthFloatW [GDI32.@]
2370 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2371 UINT iLastChar, PFLOAT pxBuffer)
2373 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2374 return 0;
2378 /***********************************************************************
2380 * Font Resource API *
2382 ***********************************************************************/
2384 /***********************************************************************
2385 * AddFontResourceA (GDI32.@)
2387 INT WINAPI AddFontResourceA( LPCSTR str )
2389 return AddFontResourceExA( str, 0, NULL);
2392 /***********************************************************************
2393 * AddFontResourceW (GDI32.@)
2395 INT WINAPI AddFontResourceW( LPCWSTR str )
2397 return AddFontResourceExW(str, 0, NULL);
2401 /***********************************************************************
2402 * AddFontResourceExA (GDI32.@)
2404 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2406 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2407 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2408 INT ret;
2410 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2411 ret = AddFontResourceExW(strW, fl, pdv);
2412 HeapFree(GetProcessHeap(), 0, strW);
2413 return ret;
2416 /***********************************************************************
2417 * AddFontResourceExW (GDI32.@)
2419 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2421 return WineEngAddFontResourceEx(str, fl, pdv);
2424 /***********************************************************************
2425 * RemoveFontResourceA (GDI32.@)
2427 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2429 return RemoveFontResourceExA(str, 0, 0);
2432 /***********************************************************************
2433 * RemoveFontResourceW (GDI32.@)
2435 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2437 return RemoveFontResourceExW(str, 0, 0);
2440 /***********************************************************************
2441 * RemoveFontResourceExA (GDI32.@)
2443 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2445 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2446 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2447 INT ret;
2449 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2450 ret = RemoveFontResourceExW(strW, fl, pdv);
2451 HeapFree(GetProcessHeap(), 0, strW);
2452 return ret;
2455 /***********************************************************************
2456 * RemoveFontResourceExW (GDI32.@)
2458 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2460 return WineEngRemoveFontResourceEx(str, fl, pdv);
2463 /***********************************************************************
2464 * GetTextCharset (GDI32.@)
2466 UINT WINAPI GetTextCharset(HDC hdc)
2468 /* MSDN docs say this is equivalent */
2469 return GetTextCharsetInfo(hdc, NULL, 0);
2472 /***********************************************************************
2473 * GetTextCharsetInfo (GDI32.@)
2475 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2477 UINT ret = DEFAULT_CHARSET;
2478 DC *dc = DC_GetDCPtr(hdc);
2480 if (!dc) goto done;
2482 if (dc->gdiFont)
2483 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2485 GDI_ReleaseObj(hdc);
2487 done:
2488 if (ret == DEFAULT_CHARSET && fs)
2489 memset(fs, 0, sizeof(FONTSIGNATURE));
2490 return ret;