Add description for ExtTextOut (also include comments from Shachar
[wine/multimedia.git] / dlls / gdi / font.c
blobbf97ff96ff04148f740069aaaa68e046c1e3f4c8
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 const 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 * See ExtTextOutW.
1655 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1656 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1658 INT wlen;
1659 UINT codepage;
1660 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1661 BOOL ret;
1662 LPINT lpDxW = NULL;
1664 if (lpDx) {
1665 unsigned int i = 0, j = 0;
1667 lpDxW = (LPINT)HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1668 while(i < count) {
1669 if(IsDBCSLeadByteEx(codepage, str[i])) {
1670 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1671 i = i + 2;
1672 } else {
1673 lpDxW[j++] = lpDx[i];
1674 i = i + 1;
1679 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1681 HeapFree( GetProcessHeap(), 0, p );
1682 HeapFree( GetProcessHeap(), 0, lpDxW );
1683 return ret;
1687 /***********************************************************************
1688 * ExtTextOutW (GDI32.@)
1690 * Draws text using the currently selected font, background color, and text color.
1693 * PARAMS
1694 * x,y [I] coordinates of string
1695 * flags [I]
1696 * ETO_GRAYED - undocumented on MSDN
1697 * ETO_OPAQUE - use background color for fill the rectangle
1698 * ETO_CLIPPED - clipping text to the rectangle
1699 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1700 * than encoded characters. Implies ETO_IGNORELANGUAGE
1701 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1702 * Affects BiDi ordering
1703 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1704 * ETO_PDY - unimplemented
1705 * ETO_NUMERICSLATIN - unimplemented always assumed -
1706 * do not translate numbers into locale representations
1707 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1708 * lprect [I] dimensions for clipping or/and opaquing
1709 * str [I] text string
1710 * count [I] number of symbols in string
1711 * lpDx [I] optional parameter with distance between drawing characters
1713 * RETURNS
1714 * Success: TRUE
1715 * Failure: FALSE
1717 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1718 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1720 BOOL ret = FALSE;
1721 DC * dc = DC_GetDCUpdate( hdc );
1722 if (dc)
1724 if (flags&(ETO_NUMERICSLOCAL|ETO_NUMERICSLATIN|ETO_PDY))
1725 FIXME("flags ETO_NUMERICSLOCAL|ETO_NUMERICSLATIN|ETO_PDY unimplemented\n");
1727 if(PATH_IsPathOpen(dc->path))
1728 FIXME("called on an open path\n");
1729 else if(dc->funcs->pExtTextOut)
1731 if( !(flags&(ETO_GLYPH_INDEX|ETO_IGNORELANGUAGE)) && BidiAvail && count>0 )
1733 /* The caller did not specify that language processing was already done.
1735 LPWSTR lpReorderedString=HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1737 BIDI_Reorder( str, count, GCP_REORDER,
1738 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1739 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1740 lpReorderedString, count, NULL );
1742 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags|ETO_IGNORELANGUAGE,
1743 lprect,lpReorderedString,count,lpDx,dc->breakExtra);
1744 HeapFree(GetProcessHeap(), 0, lpReorderedString);
1745 } else
1746 ret = dc->funcs->pExtTextOut(dc->physDev,x,y,flags,lprect,str,count,
1747 lpDx,dc->breakExtra);
1749 GDI_ReleaseObj( hdc );
1751 return ret;
1755 /***********************************************************************
1756 * TextOutA (GDI32.@)
1758 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
1760 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
1764 /***********************************************************************
1765 * TextOutW (GDI32.@)
1767 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
1769 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
1773 /***********************************************************************
1774 * PolyTextOutA (GDI32.@)
1776 * Draw several Strings
1778 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
1779 PPOLYTEXTA pptxt, /* [in] Array of strings */
1780 INT cStrings ) /* [in] Number of strings in array */
1782 for (; cStrings>0; cStrings--, pptxt++)
1783 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
1784 return FALSE;
1785 return TRUE;
1790 /***********************************************************************
1791 * PolyTextOutW (GDI32.@)
1793 * Draw several Strings
1795 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
1796 PPOLYTEXTW pptxt, /* [in] Array of strings */
1797 INT cStrings ) /* [in] Number of strings in array */
1799 for (; cStrings>0; cStrings--, pptxt++)
1800 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
1801 return FALSE;
1802 return TRUE;
1806 /* FIXME: all following APIs ******************************************/
1809 /***********************************************************************
1810 * SetMapperFlags (GDI32.@)
1812 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1814 DC *dc = DC_GetDCPtr( hDC );
1815 DWORD ret = 0;
1816 if(!dc) return 0;
1817 if(dc->funcs->pSetMapperFlags)
1818 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1819 else
1820 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1821 GDI_ReleaseObj( hDC );
1822 return ret;
1825 /***********************************************************************
1826 * GetAspectRatioFilterEx (GDI.486)
1828 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1830 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1831 return FALSE;
1834 /***********************************************************************
1835 * GetAspectRatioFilterEx (GDI32.@)
1837 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1839 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1840 return FALSE;
1844 /***********************************************************************
1845 * GetCharABCWidthsA (GDI32.@)
1847 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1848 LPABC abc )
1850 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1851 LPSTR str;
1852 LPWSTR wstr;
1853 BOOL ret = TRUE;
1855 if(count <= 0) return FALSE;
1857 str = HeapAlloc(GetProcessHeap(), 0, count);
1858 for(i = 0; i < count; i++)
1859 str[i] = (BYTE)(firstChar + i);
1861 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1863 for(i = 0; i < wlen; i++)
1865 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1867 ret = FALSE;
1868 break;
1870 abc++;
1873 HeapFree(GetProcessHeap(), 0, str);
1874 HeapFree(GetProcessHeap(), 0, wstr);
1876 return ret;
1880 /******************************************************************************
1881 * GetCharABCWidthsW [GDI32.@]
1883 * Retrieves widths of characters in range.
1885 * PARAMS
1886 * hdc [I] Handle of device context
1887 * firstChar [I] First character in range to query
1888 * lastChar [I] Last character in range to query
1889 * abc [O] Address of character-width structure
1891 * NOTES
1892 * Only works with TrueType fonts
1894 * RETURNS
1895 * Success: TRUE
1896 * Failure: FALSE
1898 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1899 LPABC abc )
1901 DC *dc = DC_GetDCPtr(hdc);
1902 unsigned int i;
1903 BOOL ret = FALSE;
1905 if(dc->gdiFont)
1906 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1907 else
1908 FIXME(": stub\n");
1910 if (ret)
1912 /* convert device units to logical */
1913 for( i = firstChar; i <= lastChar; i++, abc++ ) {
1914 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1915 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1916 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1918 ret = TRUE;
1921 GDI_ReleaseObj(hdc);
1922 return ret;
1926 /***********************************************************************
1927 * GetGlyphOutline (GDI.309)
1929 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1930 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1931 LPVOID lpBuffer, const MAT2 *lpmat2 )
1933 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1934 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1935 return ~0UL; /* failure */
1939 /***********************************************************************
1940 * GetGlyphOutlineA (GDI32.@)
1942 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1943 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1944 LPVOID lpBuffer, const MAT2 *lpmat2 )
1946 LPWSTR p = NULL;
1947 DWORD ret;
1948 UINT c;
1950 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1951 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1952 c = p[0];
1953 } else
1954 c = uChar;
1955 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1956 lpmat2);
1957 HeapFree(GetProcessHeap(), 0, p);
1958 return ret;
1961 /***********************************************************************
1962 * GetGlyphOutlineW (GDI32.@)
1964 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1965 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1966 LPVOID lpBuffer, const MAT2 *lpmat2 )
1968 DC *dc = DC_GetDCPtr(hdc);
1969 DWORD ret;
1971 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1972 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1974 if(!dc) return GDI_ERROR;
1976 if(dc->gdiFont)
1977 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1978 cbBuffer, lpBuffer, lpmat2);
1979 else
1980 ret = GDI_ERROR;
1982 GDI_ReleaseObj(hdc);
1983 return ret;
1987 /***********************************************************************
1988 * CreateScalableFontResourceA (GDI32.@)
1990 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1991 LPCSTR lpszResourceFile,
1992 LPCSTR lpszFontFile,
1993 LPCSTR lpszCurrentPath )
1995 HANDLE f;
1997 /* fHidden=1 - only visible for the calling app, read-only, not
1998 * enumbered with EnumFonts/EnumFontFamilies
1999 * lpszCurrentPath can be NULL
2001 FIXME("(%ld,%s,%s,%s): stub\n",
2002 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2003 debugstr_a(lpszCurrentPath) );
2005 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2006 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2007 CloseHandle(f);
2008 SetLastError(ERROR_FILE_EXISTS);
2009 return FALSE;
2011 return FALSE; /* create failed */
2014 /***********************************************************************
2015 * CreateScalableFontResourceW (GDI32.@)
2017 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2018 LPCWSTR lpszResourceFile,
2019 LPCWSTR lpszFontFile,
2020 LPCWSTR lpszCurrentPath )
2022 FIXME("(%ld,%p,%p,%p): stub\n",
2023 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2024 return FALSE; /* create failed */
2028 /*************************************************************************
2029 * GetRasterizerCaps (GDI32.@)
2031 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
2033 lprs->nSize = sizeof(RASTERIZER_STATUS);
2034 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
2035 lprs->nLanguageID = 0;
2036 return TRUE;
2040 /*************************************************************************
2041 * GetKerningPairsA (GDI32.@)
2043 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2044 LPKERNINGPAIR lpKerningPairs )
2046 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2050 /*************************************************************************
2051 * GetKerningPairsW (GDI32.@)
2053 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2054 LPKERNINGPAIR lpKerningPairs )
2056 unsigned int i;
2057 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2058 for (i = 0; i < cPairs; i++)
2059 lpKerningPairs[i].iKernAmount = 0;
2060 return 0;
2063 /*************************************************************************
2064 * TranslateCharsetInfo [GDI32.@]
2066 * Fills a CHARSETINFO structure for a character set, code page, or
2067 * font. This allows making the correspondance between different labelings
2068 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2069 * of the same encoding.
2071 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2072 * only one codepage should be set in *lpSrc.
2074 * RETURNS
2075 * TRUE on success, FALSE on failure.
2078 BOOL WINAPI TranslateCharsetInfo(
2079 LPDWORD lpSrc, /* [in]
2080 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2081 if flags == TCI_SRCCHARSET: a character set value
2082 if flags == TCI_SRCCODEPAGE: a code page value
2084 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2085 DWORD flags /* [in] determines interpretation of lpSrc */)
2087 int index = 0;
2088 switch (flags) {
2089 case TCI_SRCFONTSIG:
2090 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2091 break;
2092 case TCI_SRCCODEPAGE:
2093 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2094 break;
2095 case TCI_SRCCHARSET:
2096 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2097 break;
2098 default:
2099 return FALSE;
2101 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2102 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2103 return TRUE;
2106 /*************************************************************************
2107 * GetFontLanguageInfo (GDI32.@)
2109 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2111 FONTSIGNATURE fontsig;
2112 static const DWORD GCP_DBCS_MASK=0x003F0000,
2113 GCP_DIACRITIC_MASK=0x00000000,
2114 FLI_GLYPHS_MASK=0x00000000,
2115 GCP_GLYPHSHAPE_MASK=0x00000040,
2116 GCP_KASHIDA_MASK=0x00000000,
2117 GCP_LIGATE_MASK=0x00000000,
2118 GCP_USEKERNING_MASK=0x00000000,
2119 GCP_REORDER_MASK=0x00000060;
2121 DWORD result=0;
2123 GetTextCharsetInfo( hdc, &fontsig, 0 );
2124 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2126 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2127 result|=GCP_DBCS;
2129 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2130 result|=GCP_DIACRITIC;
2132 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2133 result|=FLI_GLYPHS;
2135 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2136 result|=GCP_GLYPHSHAPE;
2138 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2139 result|=GCP_KASHIDA;
2141 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2142 result|=GCP_LIGATE;
2144 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2145 result|=GCP_USEKERNING;
2147 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2148 if( GetTextAlign( hdc) & TA_RTLREADING )
2149 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2150 result|=GCP_REORDER;
2152 return result;
2156 /*************************************************************************
2157 * GetFontData [GDI32.@]
2159 * Retrieve data for TrueType font.
2161 * RETURNS
2163 * success: Number of bytes returned
2164 * failure: GDI_ERROR
2166 * NOTES
2168 * Calls SetLastError()
2171 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2172 LPVOID buffer, DWORD length)
2174 DC *dc = DC_GetDCPtr(hdc);
2175 DWORD ret = GDI_ERROR;
2177 if(!dc) return GDI_ERROR;
2179 if(dc->gdiFont)
2180 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2182 GDI_ReleaseObj(hdc);
2183 return ret;
2186 /*************************************************************************
2187 * GetGlyphIndicesA [GDI32.@]
2189 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2190 LPWORD pgi, DWORD flags)
2192 DWORD ret;
2193 WCHAR *lpstrW;
2194 INT countW;
2196 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2197 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2199 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2200 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2201 HeapFree(GetProcessHeap(), 0, lpstrW);
2203 return ret;
2206 /*************************************************************************
2207 * GetGlyphIndicesW [GDI32.@]
2209 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2210 LPWORD pgi, DWORD flags)
2212 DC *dc = DC_GetDCPtr(hdc);
2213 DWORD ret = GDI_ERROR;
2215 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2216 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2218 if(!dc) return GDI_ERROR;
2220 if(dc->gdiFont)
2221 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2223 GDI_ReleaseObj(hdc);
2224 return ret;
2227 /*************************************************************************
2228 * GetCharacterPlacementA [GDI32.@]
2230 * NOTES:
2231 * the web browser control of ie4 calls this with dwFlags=0
2233 DWORD WINAPI
2234 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2235 INT nMaxExtent, GCP_RESULTSA *lpResults,
2236 DWORD dwFlags)
2238 WCHAR *lpStringW;
2239 INT uCountW;
2240 GCP_RESULTSW resultsW;
2241 DWORD ret;
2242 UINT font_cp;
2244 TRACE("%s, %d, %d, 0x%08lx\n",
2245 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2247 /* both structs are equal in size */
2248 memcpy(&resultsW, lpResults, sizeof(resultsW));
2250 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2251 if(lpResults->lpOutString)
2252 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2254 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2256 if(lpResults->lpOutString) {
2257 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2258 lpResults->lpOutString, uCount, NULL, NULL );
2261 HeapFree(GetProcessHeap(), 0, lpStringW);
2262 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2264 return ret;
2267 /*************************************************************************
2268 * GetCharacterPlacementW [GDI32.@]
2270 * Retrieve information about a string. This includes the width, reordering,
2271 * Glyphing and so on.
2273 * RETURNS
2275 * The width and height of the string if successful, 0 if failed.
2277 * BUGS
2279 * All flags except GCP_REORDER are not yet implemented.
2280 * Reordering is not 100% complient to the Windows BiDi method.
2281 * Caret positioning is not yet implemented for BiDi.
2282 * Classes are not yet implemented.
2285 DWORD WINAPI
2286 GetCharacterPlacementW(
2287 HDC hdc, /* [in] Device context for which the rendering is to be done */
2288 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2289 INT uCount, /* [in] Number of WORDS in string. */
2290 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2291 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2292 DWORD dwFlags /* [in] Flags specifying how to process the string */
2295 DWORD ret=0;
2296 SIZE size;
2297 UINT i, nSet;
2299 TRACE("%s, %d, %d, 0x%08lx\n",
2300 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2302 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2303 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2304 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2305 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2306 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2308 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2309 if(lpResults->lpClass) FIXME("classes not implemented\n");
2310 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2311 FIXME("Caret positions for complex scripts not implemented\n");
2313 nSet = (UINT)uCount;
2314 if(nSet > lpResults->nGlyphs)
2315 nSet = lpResults->nGlyphs;
2317 /* return number of initialized fields */
2318 lpResults->nGlyphs = nSet;
2320 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2322 /* Treat the case where no special handling was requested in a fastpath way */
2323 /* copy will do if the GCP_REORDER flag is not set */
2324 if(lpResults->lpOutString)
2325 strncpyW( lpResults->lpOutString, lpString, nSet );
2327 if(lpResults->lpOrder)
2329 for(i = 0; i < nSet; i++)
2330 lpResults->lpOrder[i] = i;
2332 } else
2334 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2335 nSet, lpResults->lpOrder );
2338 /* FIXME: Will use the placement chars */
2339 if (lpResults->lpDx)
2341 int c;
2342 for (i = 0; i < nSet; i++)
2344 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2345 lpResults->lpDx[i]= c;
2349 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2351 int pos = 0;
2353 lpResults->lpCaretPos[0] = 0;
2354 for (i = 1; i < nSet; i++)
2355 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2356 lpResults->lpCaretPos[i] = (pos += size.cx);
2359 if(lpResults->lpGlyphs)
2360 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2362 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2363 ret = MAKELONG(size.cx, size.cy);
2365 return ret;
2368 /*************************************************************************
2369 * GetCharABCWidthsFloatA [GDI32.@]
2371 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2372 LPABCFLOAT lpABCF)
2374 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2375 return 0;
2378 /*************************************************************************
2379 * GetCharABCWidthsFloatW [GDI32.@]
2381 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2382 UINT iLastChar, LPABCFLOAT lpABCF)
2384 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2385 return 0;
2388 /*************************************************************************
2389 * GetCharWidthFloatA [GDI32.@]
2391 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2392 UINT iLastChar, PFLOAT pxBuffer)
2394 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2395 return 0;
2398 /*************************************************************************
2399 * GetCharWidthFloatW [GDI32.@]
2401 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2402 UINT iLastChar, PFLOAT pxBuffer)
2404 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2405 return 0;
2409 /***********************************************************************
2411 * Font Resource API *
2413 ***********************************************************************/
2415 /***********************************************************************
2416 * AddFontResourceA (GDI32.@)
2418 INT WINAPI AddFontResourceA( LPCSTR str )
2420 return AddFontResourceExA( str, 0, NULL);
2423 /***********************************************************************
2424 * AddFontResourceW (GDI32.@)
2426 INT WINAPI AddFontResourceW( LPCWSTR str )
2428 return AddFontResourceExW(str, 0, NULL);
2432 /***********************************************************************
2433 * AddFontResourceExA (GDI32.@)
2435 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2437 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2438 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2439 INT ret;
2441 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2442 ret = AddFontResourceExW(strW, fl, pdv);
2443 HeapFree(GetProcessHeap(), 0, strW);
2444 return ret;
2447 /***********************************************************************
2448 * AddFontResourceExW (GDI32.@)
2450 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2452 return WineEngAddFontResourceEx(str, fl, pdv);
2455 /***********************************************************************
2456 * RemoveFontResourceA (GDI32.@)
2458 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2460 return RemoveFontResourceExA(str, 0, 0);
2463 /***********************************************************************
2464 * RemoveFontResourceW (GDI32.@)
2466 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2468 return RemoveFontResourceExW(str, 0, 0);
2471 /***********************************************************************
2472 * RemoveFontResourceExA (GDI32.@)
2474 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2476 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2477 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2478 INT ret;
2480 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2481 ret = RemoveFontResourceExW(strW, fl, pdv);
2482 HeapFree(GetProcessHeap(), 0, strW);
2483 return ret;
2486 /***********************************************************************
2487 * RemoveFontResourceExW (GDI32.@)
2489 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2491 return WineEngRemoveFontResourceEx(str, fl, pdv);
2494 /***********************************************************************
2495 * GetTextCharset (GDI32.@)
2497 UINT WINAPI GetTextCharset(HDC hdc)
2499 /* MSDN docs say this is equivalent */
2500 return GetTextCharsetInfo(hdc, NULL, 0);
2503 /***********************************************************************
2504 * GetTextCharsetInfo (GDI32.@)
2506 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2508 UINT ret = DEFAULT_CHARSET;
2509 DC *dc = DC_GetDCPtr(hdc);
2511 if (!dc) goto done;
2513 if (dc->gdiFont)
2514 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2516 GDI_ReleaseObj(hdc);
2518 done:
2519 if (ret == DEFAULT_CHARSET && fs)
2520 memset(fs, 0, sizeof(FONTSIGNATURE));
2521 return ret;