shell32/explorer: Support different structure sizes in Shell_NotifyIcon.
[wine/gsoc_dplay.git] / dlls / gdi32 / font.c
blobe8b96c429de7692aa87200c99ced003e5028e939
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, 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_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 FLOAT floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 FLOAT floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
108 typedef struct
110 GDIOBJHDR header;
111 LOGFONTW logfont;
112 } FONTOBJ;
114 typedef struct
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
118 LPARAM lpData;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
123 SEGPTR segLogFont;
124 DWORD dwFlags;
125 HDC hdc;
126 DC *dc;
127 PHYSDEV physDev;
128 } fontEnum16;
130 typedef struct
132 LPLOGFONTW lpLogFontParam;
133 FONTENUMPROCW lpEnumFunc;
134 LPARAM lpData;
135 DWORD dwFlags;
136 HDC hdc;
137 DC *dc;
138 PHYSDEV physDev;
139 } fontEnum32;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
147 /* ANSI */
148 { ANSI_CHARSET, 1252, FS(0)},
149 { EASTEUROPE_CHARSET, 1250, FS(1)},
150 { RUSSIAN_CHARSET, 1251, FS(2)},
151 { GREEK_CHARSET, 1253, FS(3)},
152 { TURKISH_CHARSET, 1254, FS(4)},
153 { HEBREW_CHARSET, 1255, FS(5)},
154 { ARABIC_CHARSET, 1256, FS(6)},
155 { BALTIC_CHARSET, 1257, FS(7)},
156 { VIETNAMESE_CHARSET, 1258, FS(8)},
157 /* reserved by ANSI */
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 { DEFAULT_CHARSET, 0, FS(0)},
165 /* ANSI and OEM */
166 { THAI_CHARSET, 874, FS(16)},
167 { SHIFTJIS_CHARSET, 932, FS(17)},
168 { GB2312_CHARSET, 936, FS(18)},
169 { HANGEUL_CHARSET, 949, FS(19)},
170 { CHINESEBIG5_CHARSET, 950, FS(20)},
171 { JOHAB_CHARSET, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET, 0, FS(0)},
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET, 0, FS(0)},
183 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
191 font16->lfHeight = font32->lfHeight;
192 font16->lfWidth = font32->lfWidth;
193 font16->lfEscapement = font32->lfEscapement;
194 font16->lfOrientation = font32->lfOrientation;
195 font16->lfWeight = font32->lfWeight;
196 font16->lfItalic = font32->lfItalic;
197 font16->lfUnderline = font32->lfUnderline;
198 font16->lfStrikeOut = font32->lfStrikeOut;
199 font16->lfCharSet = font32->lfCharSet;
200 font16->lfOutPrecision = font32->lfOutPrecision;
201 font16->lfClipPrecision = font32->lfClipPrecision;
202 font16->lfQuality = font32->lfQuality;
203 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206 font16->lfFaceName[LF_FACESIZE-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
211 font32->lfHeight = font16->lfHeight;
212 font32->lfWidth = font16->lfWidth;
213 font32->lfEscapement = font16->lfEscapement;
214 font32->lfOrientation = font16->lfOrientation;
215 font32->lfWeight = font16->lfWeight;
216 font32->lfItalic = font16->lfItalic;
217 font32->lfUnderline = font16->lfUnderline;
218 font32->lfStrikeOut = font16->lfStrikeOut;
219 font32->lfCharSet = font16->lfCharSet;
220 font32->lfOutPrecision = font16->lfOutPrecision;
221 font32->lfClipPrecision = font16->lfClipPrecision;
222 font32->lfQuality = font16->lfQuality;
223 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225 font32->lfFaceName[LF_FACESIZE-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
230 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
232 LF_FACESIZE);
233 fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
238 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240 LF_FACESIZE, NULL, NULL);
241 fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
246 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
248 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253 font16->elfStyle[LF_FACESIZE-1] = '\0';
254 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256 font16->elfScript[LF_FACESIZE-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
261 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
263 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268 fontA->elfStyle[LF_FACESIZE-1] = '\0';
269 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271 fontA->elfScript[LF_FACESIZE-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
279 ptmA->tmHeight = ptmW->tmHeight;
280 ptmA->tmAscent = ptmW->tmAscent;
281 ptmA->tmDescent = ptmW->tmDescent;
282 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286 ptmA->tmWeight = ptmW->tmWeight;
287 ptmA->tmOverhang = ptmW->tmOverhang;
288 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
291 if (ptmW->tmCharSet == SYMBOL_CHARSET)
293 UINT last_char = ptmW->tmLastChar;
294 if (last_char > 0xf000) last_char -= 0xf000;
295 ptmA->tmLastChar = min(last_char, 255);
297 else
298 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
299 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
300 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
301 ptmA->tmItalic = ptmW->tmItalic;
302 ptmA->tmUnderlined = ptmW->tmUnderlined;
303 ptmA->tmStruckOut = ptmW->tmStruckOut;
304 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
305 ptmA->tmCharSet = ptmW->tmCharSet;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
311 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
312 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
313 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
314 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
315 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
316 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
317 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
318 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
319 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
320 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
321 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
322 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
323 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
324 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
325 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
326 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
327 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
328 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
329 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
330 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
331 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
332 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
333 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
334 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
335 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
340 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
341 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
342 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
343 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
344 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
345 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
349 /***********************************************************************
350 * FONT_mbtowc
352 * Returns a Unicode translation of str using the charset of the
353 * currently selected font in hdc. If count is -1 then str is assumed
354 * to be '\0' terminated, otherwise it contains the number of bytes to
355 * convert. If plenW is non-NULL, on return it will point to the
356 * number of WCHARs that have been written. If pCP is non-NULL, on
357 * return it will point to the codepage used in the conversion. The
358 * caller should free the returned LPWSTR from the process heap
359 * itself.
361 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
363 UINT cp = CP_ACP;
364 INT lenW;
365 LPWSTR strW;
366 CHARSETINFO csi;
367 int charset = GetTextCharset(hdc);
369 /* Hmm, nicely designed api this one! */
370 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
371 cp = csi.ciACP;
372 else {
373 switch(charset) {
374 case OEM_CHARSET:
375 cp = GetOEMCP();
376 break;
377 case DEFAULT_CHARSET:
378 cp = GetACP();
379 break;
381 case VISCII_CHARSET:
382 case TCVN_CHARSET:
383 case KOI8_CHARSET:
384 case ISO3_CHARSET:
385 case ISO4_CHARSET:
386 case ISO10_CHARSET:
387 case CELTIC_CHARSET:
388 /* FIXME: These have no place here, but because x11drv
389 enumerates fonts with these (made up) charsets some apps
390 might use them and then the FIXME below would become
391 annoying. Now we could pick the intended codepage for
392 each of these, but since it's broken anyway we'll just
393 use CP_ACP and hope it'll go away...
395 cp = CP_ACP;
396 break;
398 default:
399 FIXME("Can't find codepage for charset %d\n", charset);
400 break;
404 TRACE("charset %d => cp %d\n", charset, cp);
406 if(count == -1) count = strlen(str);
407 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
408 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
409 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
410 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
411 if(plenW) *plenW = lenW;
412 if(pCP) *pCP = cp;
413 return strW;
417 /***********************************************************************
418 * CreateFontIndirectA (GDI32.@)
420 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
422 LOGFONTW lfW;
424 if (plfA) {
425 FONT_LogFontAToW( plfA, &lfW );
426 return CreateFontIndirectW( &lfW );
427 } else
428 return CreateFontIndirectW( NULL );
432 /***********************************************************************
433 * CreateFontIndirectW (GDI32.@)
435 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
437 HFONT hFont = 0;
439 if (plf)
441 FONTOBJ* fontPtr;
442 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
443 (HGDIOBJ *)&hFont, &font_funcs )))
445 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
446 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
447 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
448 WCHAR* pFaceNameSuffix = NULL;
450 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
452 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
453 plf->lfHeight, plf->lfWidth,
454 plf->lfEscapement, plf->lfOrientation,
455 plf->lfPitchAndFamily,
456 plf->lfOutPrecision, plf->lfClipPrecision,
457 plf->lfQuality, plf->lfCharSet,
458 debugstr_w(plf->lfFaceName),
459 plf->lfWeight > 400 ? "Bold" : "",
460 plf->lfItalic ? "Italic" : "",
461 plf->lfUnderline ? "Underline" : "", hFont);
463 if (plf->lfEscapement != plf->lfOrientation) {
464 /* this should really depend on whether GM_ADVANCED is set */
465 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
466 WARN("orientation angle %f set to "
467 "escapement angle %f for new font %p\n",
468 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
471 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
472 if (pFaceNameItalicSuffix) {
473 fontPtr->logfont.lfItalic = TRUE;
474 pFaceNameSuffix = pFaceNameItalicSuffix;
477 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
478 if (pFaceNameBoldSuffix) {
479 if (fontPtr->logfont.lfWeight < FW_BOLD) {
480 fontPtr->logfont.lfWeight = FW_BOLD;
482 if (!pFaceNameSuffix ||
483 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
484 pFaceNameSuffix = pFaceNameBoldSuffix;
488 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
490 GDI_ReleaseObj( hFont );
493 else WARN("(NULL) => NULL\n");
495 return hFont;
498 /*************************************************************************
499 * CreateFontA (GDI32.@)
501 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
502 INT orient, INT weight, DWORD italic,
503 DWORD underline, DWORD strikeout, DWORD charset,
504 DWORD outpres, DWORD clippres, DWORD quality,
505 DWORD pitch, LPCSTR name )
507 LOGFONTA logfont;
509 logfont.lfHeight = height;
510 logfont.lfWidth = width;
511 logfont.lfEscapement = esc;
512 logfont.lfOrientation = orient;
513 logfont.lfWeight = weight;
514 logfont.lfItalic = italic;
515 logfont.lfUnderline = underline;
516 logfont.lfStrikeOut = strikeout;
517 logfont.lfCharSet = charset;
518 logfont.lfOutPrecision = outpres;
519 logfont.lfClipPrecision = clippres;
520 logfont.lfQuality = quality;
521 logfont.lfPitchAndFamily = pitch;
523 if (name)
524 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
525 else
526 logfont.lfFaceName[0] = '\0';
528 return CreateFontIndirectA( &logfont );
531 /*************************************************************************
532 * CreateFontW (GDI32.@)
534 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
535 INT orient, INT weight, DWORD italic,
536 DWORD underline, DWORD strikeout, DWORD charset,
537 DWORD outpres, DWORD clippres, DWORD quality,
538 DWORD pitch, LPCWSTR name )
540 LOGFONTW logfont;
542 logfont.lfHeight = height;
543 logfont.lfWidth = width;
544 logfont.lfEscapement = esc;
545 logfont.lfOrientation = orient;
546 logfont.lfWeight = weight;
547 logfont.lfItalic = italic;
548 logfont.lfUnderline = underline;
549 logfont.lfStrikeOut = strikeout;
550 logfont.lfCharSet = charset;
551 logfont.lfOutPrecision = outpres;
552 logfont.lfClipPrecision = clippres;
553 logfont.lfQuality = quality;
554 logfont.lfPitchAndFamily = pitch;
556 if (name)
557 lstrcpynW(logfont.lfFaceName, name,
558 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
559 else
560 logfont.lfFaceName[0] = '\0';
562 return CreateFontIndirectW( &logfont );
566 /***********************************************************************
567 * FONT_SelectObject
569 * If the driver supports vector fonts we create a gdi font first and
570 * then call the driver to give it a chance to supply its own device
571 * font. If the driver wants to do this it returns TRUE and we can
572 * delete the gdi font, if the driver wants to use the gdi font it
573 * should return FALSE, to signal an error return GDI_ERROR. For
574 * drivers that don't support vector fonts they must supply their own
575 * font.
577 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
579 HGDIOBJ ret = 0;
580 DC *dc = DC_GetDCPtr( hdc );
582 if (!dc) return 0;
584 if (dc->hFont != handle || dc->gdiFont == NULL)
586 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
587 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
590 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
592 if (ret && dc->gdiFont) dc->gdiFont = 0;
594 if (ret == HGDI_ERROR)
595 ret = 0; /* SelectObject returns 0 on error */
596 else
598 ret = dc->hFont;
599 dc->hFont = handle;
601 GDI_ReleaseObj( hdc );
602 return ret;
606 /***********************************************************************
607 * FONT_GetObject16
609 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
611 FONTOBJ *font = obj;
612 LOGFONT16 lf16;
614 FONT_LogFontWTo16( &font->logfont, &lf16 );
616 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
617 memcpy( buffer, &lf16, count );
618 return count;
621 /***********************************************************************
622 * FONT_GetObjectA
624 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
626 FONTOBJ *font = obj;
627 LOGFONTA lfA;
629 if(!buffer)
630 return sizeof(lfA);
631 FONT_LogFontWToA( &font->logfont, &lfA );
633 if (count > sizeof(lfA)) count = sizeof(lfA);
634 memcpy( buffer, &lfA, count );
635 return count;
638 /***********************************************************************
639 * FONT_GetObjectW
641 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
643 FONTOBJ *font = obj;
644 if(!buffer)
645 return sizeof(LOGFONTW);
646 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
647 memcpy( buffer, &font->logfont, count );
648 return count;
652 /***********************************************************************
653 * FONT_DeleteObject
655 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
657 WineEngDestroyFontInstance( handle );
658 return GDI_FreeObject( handle, obj );
662 /***********************************************************************
663 * FONT_EnumInstance16
665 * Called by the device driver layer to pass font info
666 * down to the application.
668 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
669 * We have to use other types because of the FONTENUMPROCW definition.
671 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
672 DWORD fType, LPARAM lp )
674 fontEnum16 *pfe = (fontEnum16*)lp;
675 INT ret = 1;
676 DC *dc;
678 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
679 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
681 WORD args[7];
682 DWORD result;
684 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
685 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
686 pfe->dwFlags |= ENUM_CALLED;
687 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
689 args[6] = SELECTOROF(pfe->segLogFont);
690 args[5] = OFFSETOF(pfe->segLogFont);
691 args[4] = SELECTOROF(pfe->segTextMetric);
692 args[3] = OFFSETOF(pfe->segTextMetric);
693 args[2] = fType;
694 args[1] = HIWORD(pfe->lpData);
695 args[0] = LOWORD(pfe->lpData);
696 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
697 ret = LOWORD(result);
699 /* get the lock again and make sure the DC is still valid */
700 dc = DC_GetDCPtr( pfe->hdc );
701 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
703 if (dc) GDI_ReleaseObj( pfe->hdc );
704 pfe->hdc = 0; /* make sure we don't try to release it later on */
705 ret = 0;
708 return ret;
711 /***********************************************************************
712 * FONT_EnumInstance
714 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
715 * We have to use other types because of the FONTENUMPROCW definition.
717 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
718 DWORD fType, LPARAM lp )
720 fontEnum32 *pfe = (fontEnum32*)lp;
721 INT ret = 1;
722 DC *dc;
724 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
725 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
726 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
727 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
729 /* convert font metrics */
730 ENUMLOGFONTEXA logfont;
731 NEWTEXTMETRICEXA tmA;
733 pfe->dwFlags |= ENUM_CALLED;
734 if (!(pfe->dwFlags & ENUM_UNICODE))
736 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
737 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
738 plf = (LOGFONTW *)&logfont.elfLogFont;
739 ptm = (TEXTMETRICW *)&tmA;
741 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
743 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
745 /* get the lock again and make sure the DC is still valid */
746 dc = DC_GetDCPtr( pfe->hdc );
747 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
749 if (dc) GDI_ReleaseObj( pfe->hdc );
750 pfe->hdc = 0; /* make sure we don't try to release it later on */
751 ret = 0;
754 return ret;
757 /***********************************************************************
758 * EnumFontFamiliesEx (GDI.613)
760 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
761 FONTENUMPROC16 efproc, LPARAM lParam,
762 DWORD dwFlags)
764 fontEnum16 fe16;
765 INT16 ret = 1, ret2;
766 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
767 NEWTEXTMETRICEX16 tm16;
768 ENUMLOGFONTEX16 lf16;
769 LOGFONTW lfW;
770 BOOL enum_gdi_fonts;
772 if (!dc) return 0;
773 FONT_LogFont16ToW(plf, &lfW);
775 fe16.hdc = HDC_32(hDC);
776 fe16.dc = dc;
777 fe16.physDev = dc->physDev;
778 fe16.lpLogFontParam = plf;
779 fe16.lpEnumFunc = efproc;
780 fe16.lpData = lParam;
781 fe16.lpTextMetric = &tm16;
782 fe16.lpLogFont = &lf16;
783 fe16.segTextMetric = MapLS( &tm16 );
784 fe16.segLogFont = MapLS( &lf16 );
785 fe16.dwFlags = 0;
787 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
789 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
791 ret = 0;
792 goto done;
795 if (enum_gdi_fonts)
796 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
797 fe16.dwFlags &= ~ENUM_CALLED;
798 if (ret && dc->funcs->pEnumDeviceFonts) {
799 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
800 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
801 ret = ret2;
803 done:
804 UnMapLS( fe16.segTextMetric );
805 UnMapLS( fe16.segLogFont );
806 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
807 return ret;
810 /***********************************************************************
811 * FONT_EnumFontFamiliesEx
813 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
814 FONTENUMPROCW efproc,
815 LPARAM lParam, DWORD dwUnicode)
817 INT ret = 1, ret2;
818 DC *dc = DC_GetDCPtr( hDC );
819 fontEnum32 fe32;
820 BOOL enum_gdi_fonts;
822 if (!dc) return 0;
824 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
825 plf->lfCharSet);
826 fe32.lpLogFontParam = plf;
827 fe32.lpEnumFunc = efproc;
828 fe32.lpData = lParam;
829 fe32.dwFlags = dwUnicode;
830 fe32.hdc = hDC;
831 fe32.dc = dc;
832 fe32.physDev = dc->physDev;
834 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
836 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
838 ret = 0;
839 goto done;
842 if (enum_gdi_fonts)
843 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
844 fe32.dwFlags &= ~ENUM_CALLED;
845 if (ret && dc->funcs->pEnumDeviceFonts) {
846 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
847 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
848 ret = ret2;
850 done:
851 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
852 return ret;
855 /***********************************************************************
856 * EnumFontFamiliesExW (GDI32.@)
858 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
859 FONTENUMPROCW efproc,
860 LPARAM lParam, DWORD dwFlags )
862 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
865 /***********************************************************************
866 * EnumFontFamiliesExA (GDI32.@)
868 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
869 FONTENUMPROCA efproc,
870 LPARAM lParam, DWORD dwFlags)
872 LOGFONTW lfW;
873 FONT_LogFontAToW( plf, &lfW );
875 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
878 /***********************************************************************
879 * EnumFontFamilies (GDI.330)
881 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
882 FONTENUMPROC16 efproc, LPARAM lpData )
884 LOGFONT16 lf;
886 lf.lfCharSet = DEFAULT_CHARSET;
887 if (lpFamily)
889 if (!*lpFamily) return 1;
890 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
892 else lf.lfFaceName[0] = '\0';
894 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
897 /***********************************************************************
898 * EnumFontFamiliesA (GDI32.@)
900 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
901 FONTENUMPROCA efproc, LPARAM lpData )
903 LOGFONTA lf;
905 lf.lfCharSet = DEFAULT_CHARSET;
906 if (lpFamily)
908 if (!*lpFamily) return 1;
909 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
911 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
913 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
916 /***********************************************************************
917 * EnumFontFamiliesW (GDI32.@)
919 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
920 FONTENUMPROCW efproc, LPARAM lpData )
922 LOGFONTW lf;
924 lf.lfCharSet = DEFAULT_CHARSET;
925 if (lpFamily)
927 if (!*lpFamily) return 1;
928 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
930 else lf.lfFaceName[0] = 0;
932 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
935 /***********************************************************************
936 * EnumFonts (GDI.70)
938 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
939 LPARAM lpData )
941 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
944 /***********************************************************************
945 * EnumFontsA (GDI32.@)
947 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
948 LPARAM lpData )
950 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
953 /***********************************************************************
954 * EnumFontsW (GDI32.@)
956 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
957 LPARAM lpData )
959 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
963 /***********************************************************************
964 * GetTextCharacterExtra (GDI32.@)
966 INT WINAPI GetTextCharacterExtra( HDC hdc )
968 INT ret;
969 DC *dc = DC_GetDCPtr( hdc );
970 if (!dc) return 0x80000000;
971 ret = dc->charExtra;
972 GDI_ReleaseObj( hdc );
973 return ret;
977 /***********************************************************************
978 * SetTextCharacterExtra (GDI32.@)
980 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
982 INT prev;
983 DC * dc = DC_GetDCPtr( hdc );
984 if (!dc) return 0x80000000;
985 if (dc->funcs->pSetTextCharacterExtra)
986 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
987 else
989 prev = dc->charExtra;
990 dc->charExtra = extra;
992 GDI_ReleaseObj( hdc );
993 return prev;
997 /***********************************************************************
998 * SetTextJustification (GDI32.@)
1000 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1002 BOOL ret = TRUE;
1003 DC * dc = DC_GetDCPtr( hdc );
1004 if (!dc) return FALSE;
1005 if (dc->funcs->pSetTextJustification)
1006 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1007 else
1009 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1010 if (!extra) breaks = 0;
1011 if (breaks)
1013 dc->breakExtra = extra / breaks;
1014 dc->breakRem = extra - (breaks * dc->breakExtra);
1016 else
1018 dc->breakExtra = 0;
1019 dc->breakRem = 0;
1022 GDI_ReleaseObj( hdc );
1023 return ret;
1027 /***********************************************************************
1028 * GetTextFaceA (GDI32.@)
1030 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1032 INT res = GetTextFaceW(hdc, 0, NULL);
1033 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1034 GetTextFaceW( hdc, res, nameW );
1036 if (name)
1038 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1039 name[count-1] = 0;
1040 res = strlen(name);
1042 else
1043 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1044 HeapFree( GetProcessHeap(), 0, nameW );
1045 return res;
1048 /***********************************************************************
1049 * GetTextFaceW (GDI32.@)
1051 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1053 FONTOBJ *font;
1054 INT ret = 0;
1056 DC * dc = DC_GetDCPtr( hdc );
1057 if (!dc) return 0;
1059 if(dc->gdiFont)
1060 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1061 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1063 if (name)
1065 lstrcpynW( name, font->logfont.lfFaceName, count );
1066 ret = strlenW(name);
1068 else ret = strlenW(font->logfont.lfFaceName) + 1;
1069 GDI_ReleaseObj( dc->hFont );
1071 GDI_ReleaseObj( hdc );
1072 return ret;
1076 /***********************************************************************
1077 * GetTextExtentPoint32A (GDI32.@)
1079 * See GetTextExtentPoint32W.
1081 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1082 LPSIZE size )
1084 BOOL ret = FALSE;
1085 INT wlen;
1086 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1088 if (p) {
1089 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1090 HeapFree( GetProcessHeap(), 0, p );
1093 TRACE("(%p %s %d %p): returning %d x %d\n",
1094 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1095 return ret;
1099 /***********************************************************************
1100 * GetTextExtentPoint32W [GDI32.@]
1102 * Computes width/height for a string.
1104 * Computes width and height of the specified string.
1106 * RETURNS
1107 * Success: TRUE
1108 * Failure: FALSE
1110 BOOL WINAPI GetTextExtentPoint32W(
1111 HDC hdc, /* [in] Handle of device context */
1112 LPCWSTR str, /* [in] Address of text string */
1113 INT count, /* [in] Number of characters in string */
1114 LPSIZE size) /* [out] Address of structure for string size */
1116 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1119 /***********************************************************************
1120 * GetTextExtentPointI [GDI32.@]
1122 * Computes width and height of the array of glyph indices.
1124 * RETURNS
1125 * Success: TRUE
1126 * Failure: FALSE
1128 BOOL WINAPI GetTextExtentPointI(
1129 HDC hdc, /* [in] Handle of device context */
1130 const WORD *indices, /* [in] Address of glyph index array */
1131 INT count, /* [in] Number of glyphs in array */
1132 LPSIZE size) /* [out] Address of structure for string size */
1134 BOOL ret = FALSE;
1135 DC * dc = DC_GetDCPtr( hdc );
1136 if (!dc) return FALSE;
1138 if(dc->gdiFont) {
1139 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1140 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1141 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1142 size->cx += count * dc->charExtra;
1144 else if(dc->funcs->pGetTextExtentExPoint) {
1145 FIXME("calling GetTextExtentExPoint\n");
1146 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1147 count, 0, NULL, NULL, size );
1150 GDI_ReleaseObj( hdc );
1152 TRACE("(%p %p %d %p): returning %d x %d\n",
1153 hdc, indices, count, size, size->cx, size->cy );
1154 return ret;
1158 /***********************************************************************
1159 * GetTextExtentPointA (GDI32.@)
1161 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1162 LPSIZE size )
1164 TRACE("not bug compatible.\n");
1165 return GetTextExtentPoint32A( hdc, str, count, size );
1168 /***********************************************************************
1169 * GetTextExtentPointW (GDI32.@)
1171 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1172 LPSIZE size )
1174 TRACE("not bug compatible.\n");
1175 return GetTextExtentPoint32W( hdc, str, count, size );
1179 /***********************************************************************
1180 * GetTextExtentExPointA (GDI32.@)
1182 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1183 INT maxExt, LPINT lpnFit,
1184 LPINT alpDx, LPSIZE size )
1186 BOOL ret;
1187 INT wlen;
1188 INT *walpDx = NULL;
1189 LPWSTR p = NULL;
1191 if (alpDx &&
1192 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1193 return FALSE;
1195 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1196 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1197 if (walpDx)
1199 INT n = lpnFit ? *lpnFit : wlen;
1200 INT i, j;
1201 for(i = 0, j = 0; i < n; i++, j++)
1203 alpDx[j] = walpDx[i];
1204 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1207 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1208 HeapFree( GetProcessHeap(), 0, p );
1209 HeapFree( GetProcessHeap(), 0, walpDx );
1210 return ret;
1214 /***********************************************************************
1215 * GetTextExtentExPointW (GDI32.@)
1217 * Return the size of the string as it would be if it was output properly by
1218 * e.g. TextOut.
1220 * This should include
1221 * - Intercharacter spacing
1222 * - justification spacing (not yet done)
1223 * - kerning? see below
1225 * Kerning. Since kerning would be carried out by the rendering code it should
1226 * be done by the driver. However they don't support it yet. Also I am not
1227 * yet persuaded that (certainly under Win95) any kerning is actually done.
1229 * str: According to MSDN this should be null-terminated. That is not true; a
1230 * null will not terminate it early.
1231 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1232 * than count. I have seen it be either the size of the full string or
1233 * 1 less than the size of the full string. I have not seen it bear any
1234 * resemblance to the portion that would fit.
1235 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1236 * trailing intercharacter spacing and any trailing justification.
1238 * FIXME
1239 * Currently we do this by measuring each character etc. We should do it by
1240 * passing the request to the driver, perhaps by extending the
1241 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1242 * thinking about kerning issues and rounding issues in the justification.
1245 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1246 INT maxExt, LPINT lpnFit,
1247 LPINT alpDx, LPSIZE size )
1249 INT nFit = 0;
1250 LPINT dxs = NULL;
1251 DC *dc;
1252 BOOL ret = FALSE;
1253 TEXTMETRICW tm;
1255 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1257 dc = DC_GetDCPtr(hdc);
1258 if (! dc)
1259 return FALSE;
1261 GetTextMetricsW(hdc, &tm);
1263 /* If we need to calculate nFit, then we need the partial extents even if
1264 the user hasn't provided us with an array. */
1265 if (lpnFit)
1267 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1268 if (! dxs)
1270 GDI_ReleaseObj(hdc);
1271 SetLastError(ERROR_OUTOFMEMORY);
1272 return FALSE;
1275 else
1276 dxs = alpDx;
1278 if (dc->gdiFont)
1279 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1280 0, NULL, dxs, size);
1281 else if (dc->funcs->pGetTextExtentExPoint)
1282 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1283 0, NULL, dxs, size);
1285 /* Perform device size to world size transformations. */
1286 if (ret)
1288 INT extra = dc->charExtra,
1289 breakExtra = dc->breakExtra,
1290 breakRem = dc->breakRem,
1293 if (dxs)
1295 for (i = 0; i < count; ++i)
1297 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1298 dxs[i] += (i+1) * extra;
1299 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1301 dxs[i] += breakExtra;
1302 if (breakRem > 0)
1304 breakRem--;
1305 dxs[i]++;
1308 if (dxs[i] <= maxExt)
1309 ++nFit;
1311 breakRem = dc->breakRem;
1313 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1314 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1316 if (!dxs && count > 1 && (breakExtra || breakRem))
1318 for (i = 0; i < count; i++)
1320 if (str[i] == tm.tmBreakChar)
1322 size->cx += breakExtra;
1323 if (breakRem > 0)
1325 breakRem--;
1326 (size->cx)++;
1333 if (lpnFit)
1334 *lpnFit = nFit;
1336 if (! alpDx)
1337 HeapFree(GetProcessHeap(), 0, dxs);
1339 GDI_ReleaseObj( hdc );
1341 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1342 return ret;
1345 /***********************************************************************
1346 * GetTextMetricsA (GDI32.@)
1348 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1350 TEXTMETRICW tm32;
1352 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1353 FONT_TextMetricWToA( &tm32, metrics );
1354 return TRUE;
1357 /***********************************************************************
1358 * GetTextMetricsW (GDI32.@)
1360 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1362 BOOL ret = FALSE;
1363 DC * dc = DC_GetDCPtr( hdc );
1364 if (!dc) return FALSE;
1366 if (dc->gdiFont)
1367 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1368 else if (dc->funcs->pGetTextMetrics)
1369 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1371 if (ret)
1373 /* device layer returns values in device units
1374 * therefore we have to convert them to logical */
1376 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1377 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1379 #define WDPTOLP(x) ((x<0)? \
1380 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1381 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1382 #define HDPTOLP(y) ((y<0)? \
1383 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1384 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1386 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1387 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1388 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1389 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1390 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1391 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1392 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1393 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1394 ret = TRUE;
1395 #undef WDPTOLP
1396 #undef HDPTOLP
1397 TRACE("text metrics:\n"
1398 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1399 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1400 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1401 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1402 " PitchAndFamily = %02x\n"
1403 " --------------------\n"
1404 " InternalLeading = %i\n"
1405 " Ascent = %i\n"
1406 " Descent = %i\n"
1407 " Height = %i\n",
1408 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1409 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1410 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1411 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1412 metrics->tmPitchAndFamily,
1413 metrics->tmInternalLeading,
1414 metrics->tmAscent,
1415 metrics->tmDescent,
1416 metrics->tmHeight );
1418 GDI_ReleaseObj( hdc );
1419 return ret;
1423 /***********************************************************************
1424 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1426 * NOTES
1427 * lpOTM should be LPOUTLINETEXTMETRIC
1429 * RETURNS
1430 * Success: Non-zero or size of required buffer
1431 * Failure: 0
1433 UINT16 WINAPI GetOutlineTextMetrics16(
1434 HDC16 hdc, /* [in] Handle of device context */
1435 UINT16 cbData, /* [in] Size of metric data array */
1436 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1438 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1439 return 0;
1443 /***********************************************************************
1444 * GetOutlineTextMetricsA (GDI32.@)
1445 * Gets metrics for TrueType fonts.
1447 * NOTES
1448 * If the supplied buffer isn't big enough Windows partially fills it up to
1449 * its given length and returns that length.
1451 * RETURNS
1452 * Success: Non-zero or size of required buffer
1453 * Failure: 0
1455 UINT WINAPI GetOutlineTextMetricsA(
1456 HDC hdc, /* [in] Handle of device context */
1457 UINT cbData, /* [in] Size of metric data array */
1458 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1460 char buf[512], *ptr;
1461 UINT ret, needed;
1462 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1463 OUTLINETEXTMETRICA *output = lpOTM;
1464 INT left, len;
1466 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1467 return 0;
1468 if(ret > sizeof(buf))
1469 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1470 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1472 needed = sizeof(OUTLINETEXTMETRICA);
1473 if(lpOTMW->otmpFamilyName)
1474 needed += WideCharToMultiByte(CP_ACP, 0,
1475 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1476 NULL, 0, NULL, NULL);
1477 if(lpOTMW->otmpFaceName)
1478 needed += WideCharToMultiByte(CP_ACP, 0,
1479 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1480 NULL, 0, NULL, NULL);
1481 if(lpOTMW->otmpStyleName)
1482 needed += WideCharToMultiByte(CP_ACP, 0,
1483 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1484 NULL, 0, NULL, NULL);
1485 if(lpOTMW->otmpFullName)
1486 needed += WideCharToMultiByte(CP_ACP, 0,
1487 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1488 NULL, 0, NULL, NULL);
1490 if(!lpOTM) {
1491 ret = needed;
1492 goto end;
1495 TRACE("needed = %d\n", needed);
1496 if(needed > cbData)
1497 /* Since the supplied buffer isn't big enough, we'll alloc one
1498 that is and memcpy the first cbData bytes into the lpOTM at
1499 the end. */
1500 output = HeapAlloc(GetProcessHeap(), 0, needed);
1502 ret = output->otmSize = min(needed, cbData);
1503 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1504 output->otmFiller = 0;
1505 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1506 output->otmfsSelection = lpOTMW->otmfsSelection;
1507 output->otmfsType = lpOTMW->otmfsType;
1508 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1509 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1510 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1511 output->otmEMSquare = lpOTMW->otmEMSquare;
1512 output->otmAscent = lpOTMW->otmAscent;
1513 output->otmDescent = lpOTMW->otmDescent;
1514 output->otmLineGap = lpOTMW->otmLineGap;
1515 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1516 output->otmsXHeight = lpOTMW->otmsXHeight;
1517 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1518 output->otmMacAscent = lpOTMW->otmMacAscent;
1519 output->otmMacDescent = lpOTMW->otmMacDescent;
1520 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1521 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1522 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1523 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1524 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1525 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1526 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1527 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1528 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1529 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1532 ptr = (char*)(output + 1);
1533 left = needed - sizeof(*output);
1535 if(lpOTMW->otmpFamilyName) {
1536 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1537 len = WideCharToMultiByte(CP_ACP, 0,
1538 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1539 ptr, left, NULL, NULL);
1540 left -= len;
1541 ptr += len;
1542 } else
1543 output->otmpFamilyName = 0;
1545 if(lpOTMW->otmpFaceName) {
1546 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1547 len = WideCharToMultiByte(CP_ACP, 0,
1548 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1549 ptr, left, NULL, NULL);
1550 left -= len;
1551 ptr += len;
1552 } else
1553 output->otmpFaceName = 0;
1555 if(lpOTMW->otmpStyleName) {
1556 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1557 len = WideCharToMultiByte(CP_ACP, 0,
1558 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1559 ptr, left, NULL, NULL);
1560 left -= len;
1561 ptr += len;
1562 } else
1563 output->otmpStyleName = 0;
1565 if(lpOTMW->otmpFullName) {
1566 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1567 len = WideCharToMultiByte(CP_ACP, 0,
1568 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1569 ptr, left, NULL, NULL);
1570 left -= len;
1571 } else
1572 output->otmpFullName = 0;
1574 assert(left == 0);
1576 if(output != lpOTM) {
1577 memcpy(lpOTM, output, cbData);
1578 HeapFree(GetProcessHeap(), 0, output);
1580 /* check if the string offsets really fit into the provided size */
1581 /* FIXME: should we check string length as well? */
1582 /* make sure that we don't read/write beyond the provided buffer */
1583 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1585 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1586 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1589 /* make sure that we don't read/write beyond the provided buffer */
1590 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1592 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1593 lpOTM->otmpFaceName = 0; /* doesn't fit */
1596 /* make sure that we don't read/write beyond the provided buffer */
1597 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1599 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1600 lpOTM->otmpStyleName = 0; /* doesn't fit */
1603 /* make sure that we don't read/write beyond the provided buffer */
1604 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1606 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1607 lpOTM->otmpFullName = 0; /* doesn't fit */
1611 end:
1612 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1613 HeapFree(GetProcessHeap(), 0, lpOTMW);
1615 return ret;
1619 /***********************************************************************
1620 * GetOutlineTextMetricsW [GDI32.@]
1622 UINT WINAPI GetOutlineTextMetricsW(
1623 HDC hdc, /* [in] Handle of device context */
1624 UINT cbData, /* [in] Size of metric data array */
1625 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1627 DC *dc = DC_GetDCPtr( hdc );
1628 OUTLINETEXTMETRICW *output = lpOTM;
1629 UINT ret;
1631 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1632 if(!dc) return 0;
1634 if(dc->gdiFont) {
1635 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1636 if(lpOTM && ret) {
1637 if(ret > cbData) {
1638 output = HeapAlloc(GetProcessHeap(), 0, ret);
1639 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1642 #define WDPTOLP(x) ((x<0)? \
1643 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1644 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1645 #define HDPTOLP(y) ((y<0)? \
1646 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1647 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1649 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1650 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1651 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1652 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1653 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1654 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1655 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1656 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1657 output->otmAscent = HDPTOLP(output->otmAscent);
1658 output->otmDescent = HDPTOLP(output->otmDescent);
1659 output->otmLineGap = HDPTOLP(output->otmLineGap);
1660 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1661 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1662 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1663 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1664 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1665 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1666 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1667 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1668 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1669 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1670 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1671 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1672 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1673 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1674 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1675 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1676 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1677 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1678 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1679 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1680 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1681 #undef WDPTOLP
1682 #undef HDPTOLP
1683 if(output != lpOTM) {
1684 memcpy(lpOTM, output, cbData);
1685 HeapFree(GetProcessHeap(), 0, output);
1686 ret = cbData;
1691 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1692 but really this should just be a return 0. */
1694 ret = sizeof(*lpOTM);
1695 if (lpOTM) {
1696 if(cbData < ret)
1697 ret = 0;
1698 else {
1699 memset(lpOTM, 0, ret);
1700 lpOTM->otmSize = sizeof(*lpOTM);
1701 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1703 Further fill of the structure not implemented,
1704 Needs real values for the structure members
1709 GDI_ReleaseObj(hdc);
1710 return ret;
1714 /***********************************************************************
1715 * GetCharWidthW (GDI32.@)
1716 * GetCharWidth32W (GDI32.@)
1718 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1719 LPINT buffer )
1721 UINT i;
1722 BOOL ret = FALSE;
1723 DC * dc = DC_GetDCPtr( hdc );
1724 if (!dc) return FALSE;
1726 if (dc->gdiFont)
1727 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1728 else if (dc->funcs->pGetCharWidth)
1729 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1731 if (ret)
1733 /* convert device units to logical */
1734 for( i = firstChar; i <= lastChar; i++, buffer++ )
1735 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1736 ret = TRUE;
1738 GDI_ReleaseObj( hdc );
1739 return ret;
1743 /***********************************************************************
1744 * GetCharWidthA (GDI32.@)
1745 * GetCharWidth32A (GDI32.@)
1747 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1748 LPINT buffer )
1750 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1751 LPSTR str;
1752 LPWSTR wstr;
1753 BOOL ret = TRUE;
1755 if(count <= 0) return FALSE;
1757 str = HeapAlloc(GetProcessHeap(), 0, count);
1758 for(i = 0; i < count; i++)
1759 str[i] = (BYTE)(firstChar + i);
1761 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1763 for(i = 0; i < wlen; i++)
1765 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1767 ret = FALSE;
1768 break;
1770 buffer++;
1773 HeapFree(GetProcessHeap(), 0, str);
1774 HeapFree(GetProcessHeap(), 0, wstr);
1776 return ret;
1780 /***********************************************************************
1781 * ExtTextOutA (GDI32.@)
1783 * See ExtTextOutW.
1785 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1786 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1788 INT wlen;
1789 UINT codepage;
1790 LPWSTR p;
1791 BOOL ret;
1792 LPINT lpDxW = NULL;
1794 if (flags & ETO_GLYPH_INDEX)
1795 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1797 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1799 if (lpDx) {
1800 unsigned int i = 0, j = 0;
1802 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1803 while(i < count) {
1804 if(IsDBCSLeadByteEx(codepage, str[i])) {
1805 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1806 i = i + 2;
1807 } else {
1808 lpDxW[j++] = lpDx[i];
1809 i = i + 1;
1814 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1816 HeapFree( GetProcessHeap(), 0, p );
1817 HeapFree( GetProcessHeap(), 0, lpDxW );
1818 return ret;
1822 /***********************************************************************
1823 * ExtTextOutW (GDI32.@)
1825 * Draws text using the currently selected font, background color, and text color.
1828 * PARAMS
1829 * x,y [I] coordinates of string
1830 * flags [I]
1831 * ETO_GRAYED - undocumented on MSDN
1832 * ETO_OPAQUE - use background color for fill the rectangle
1833 * ETO_CLIPPED - clipping text to the rectangle
1834 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1835 * than encoded characters. Implies ETO_IGNORELANGUAGE
1836 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1837 * Affects BiDi ordering
1838 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1839 * ETO_PDY - unimplemented
1840 * ETO_NUMERICSLATIN - unimplemented always assumed -
1841 * do not translate numbers into locale representations
1842 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1843 * lprect [I] dimensions for clipping or/and opaquing
1844 * str [I] text string
1845 * count [I] number of symbols in string
1846 * lpDx [I] optional parameter with distance between drawing characters
1848 * RETURNS
1849 * Success: TRUE
1850 * Failure: FALSE
1852 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1853 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1855 BOOL ret = FALSE;
1856 LPWSTR reordered_str = (LPWSTR)str;
1857 WORD *glyphs = NULL;
1858 UINT align = GetTextAlign( hdc );
1859 POINT pt;
1860 TEXTMETRICW tm;
1861 LOGFONTW lf;
1862 double cosEsc, sinEsc;
1863 INT *deltas = NULL, char_extra;
1864 SIZE sz;
1865 RECT rc;
1866 BOOL done_extents = FALSE;
1867 INT width = 0, xwidth = 0, ywidth = 0;
1868 DWORD type;
1869 DC * dc = DC_GetDCUpdate( hdc );
1870 INT breakRem;
1872 if (!dc) return FALSE;
1874 breakRem = dc->breakRem;
1876 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1877 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1879 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1881 GDI_ReleaseObj( hdc );
1882 return ret;
1885 type = GetObjectType(hdc);
1886 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1888 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1889 GDI_ReleaseObj( hdc );
1890 return ret;
1893 if (!lprect)
1894 flags &= ~ETO_CLIPPED;
1896 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1898 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1900 BIDI_Reorder( str, count, GCP_REORDER,
1901 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1902 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1903 reordered_str, count, NULL );
1905 flags |= ETO_IGNORELANGUAGE;
1908 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1909 lprect, debugstr_wn(str, count), count, lpDx);
1911 if(flags & ETO_GLYPH_INDEX)
1912 glyphs = reordered_str;
1914 if(lprect)
1915 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1916 lprect->bottom);
1917 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1919 if(align & TA_UPDATECP)
1921 GetCurrentPositionEx( hdc, &pt );
1922 x = pt.x;
1923 y = pt.y;
1926 GetTextMetricsW(hdc, &tm);
1927 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1929 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1930 lf.lfEscapement = 0;
1932 if(lf.lfEscapement != 0)
1934 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1935 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1937 else
1939 cosEsc = 1;
1940 sinEsc = 0;
1943 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1945 if(!lprect)
1947 if(flags & ETO_GLYPH_INDEX)
1948 GetTextExtentPointI(hdc, glyphs, count, &sz);
1949 else
1950 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1952 done_extents = TRUE;
1953 rc.left = x;
1954 rc.top = y;
1955 rc.right = x + sz.cx;
1956 rc.bottom = y + sz.cy;
1958 else
1960 rc = *lprect;
1963 LPtoDP(hdc, (POINT*)&rc, 2);
1965 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1966 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1969 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1970 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1972 if(count == 0)
1974 ret = TRUE;
1975 goto done;
1978 pt.x = x;
1979 pt.y = y;
1980 LPtoDP(hdc, &pt, 1);
1981 x = pt.x;
1982 y = pt.y;
1984 char_extra = GetTextCharacterExtra(hdc);
1985 if(char_extra || dc->breakExtra || breakRem || lpDx)
1987 UINT i;
1988 SIZE tmpsz;
1989 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1990 for(i = 0; i < count; i++)
1992 if(lpDx && (flags & ETO_PDY))
1993 deltas[i] = lpDx[i*2] + char_extra;
1994 else if(lpDx)
1995 deltas[i] = lpDx[i] + char_extra;
1996 else
1998 if(flags & ETO_GLYPH_INDEX)
1999 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2000 else
2001 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2003 deltas[i] = tmpsz.cx;
2006 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2008 deltas[i] = deltas[i] + dc->breakExtra;
2009 if (breakRem > 0)
2011 breakRem--;
2012 deltas[i]++;
2015 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2016 width += deltas[i];
2019 else
2021 if(!done_extents)
2023 if(flags & ETO_GLYPH_INDEX)
2024 GetTextExtentPointI(hdc, glyphs, count, &sz);
2025 else
2026 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2027 done_extents = TRUE;
2029 width = INTERNAL_XWSTODS(dc, sz.cx);
2031 xwidth = width * cosEsc;
2032 ywidth = width * sinEsc;
2034 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2035 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2036 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2038 case TA_LEFT:
2039 if (align & TA_UPDATECP)
2041 pt.x = x + xwidth;
2042 pt.y = y - ywidth;
2043 DPtoLP(hdc, &pt, 1);
2044 MoveToEx(hdc, pt.x, pt.y, NULL);
2046 break;
2048 case TA_CENTER:
2049 x -= xwidth / 2;
2050 y += ywidth / 2;
2051 break;
2053 case TA_RIGHT:
2054 x -= xwidth;
2055 y += ywidth;
2056 if (align & TA_UPDATECP)
2058 pt.x = x;
2059 pt.y = y;
2060 DPtoLP(hdc, &pt, 1);
2061 MoveToEx(hdc, pt.x, pt.y, NULL);
2063 break;
2066 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2068 case TA_TOP:
2069 y += tm.tmAscent * cosEsc;
2070 x += tm.tmAscent * sinEsc;
2071 break;
2073 case TA_BOTTOM:
2074 y -= tm.tmDescent * cosEsc;
2075 x -= tm.tmDescent * sinEsc;
2076 break;
2078 case TA_BASELINE:
2079 break;
2082 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2084 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2086 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2087 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2089 RECT rc;
2090 rc.left = x;
2091 rc.right = x + width;
2092 rc.top = y - tm.tmAscent;
2093 rc.bottom = y + tm.tmDescent;
2094 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2099 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2101 HFONT orig_font = dc->hFont, cur_font;
2102 UINT glyph;
2103 INT span = 0, *offsets = NULL, i;
2105 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2106 for(i = 0; i < count; i++)
2108 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2109 if(cur_font != dc->hFont)
2111 if(!offsets)
2113 int j;
2114 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2115 offsets[0] = 0;
2116 if(!deltas)
2118 SIZE tmpsz;
2119 for(j = 1; j < count; j++)
2121 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2122 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2125 else
2127 for(j = 1; j < count; j++)
2128 offsets[j] = offsets[j-1] + deltas[j];
2131 if(span)
2133 if (PATH_IsPathOpen(dc->path))
2134 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2135 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2136 glyphs, span, deltas ? deltas + i - span : NULL);
2137 else
2138 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2139 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2140 glyphs, span, deltas ? deltas + i - span : NULL);
2141 span = 0;
2143 SelectObject(hdc, cur_font);
2145 glyphs[span++] = glyph;
2147 if(i == count - 1)
2149 if (PATH_IsPathOpen(dc->path))
2150 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2151 y - (offsets ? offsets[count - span] * sinEsc : 0),
2152 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2153 glyphs, span, deltas ? deltas + count - span : NULL);
2154 else
2155 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2156 y - (offsets ? offsets[count - span] * sinEsc : 0),
2157 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2158 glyphs, span, deltas ? deltas + count - span : NULL);
2159 SelectObject(hdc, orig_font);
2160 HeapFree(GetProcessHeap(), 0, offsets);
2164 else
2166 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2168 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2169 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2170 flags |= ETO_GLYPH_INDEX;
2173 if (PATH_IsPathOpen(dc->path))
2174 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2175 glyphs ? glyphs : reordered_str, count, deltas);
2176 else
2177 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2178 glyphs ? glyphs : reordered_str, count, deltas);
2181 done:
2182 HeapFree(GetProcessHeap(), 0, deltas);
2183 if(glyphs != reordered_str)
2184 HeapFree(GetProcessHeap(), 0, glyphs);
2185 if(reordered_str != str)
2186 HeapFree(GetProcessHeap(), 0, reordered_str);
2188 GDI_ReleaseObj( hdc );
2190 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2192 int underlinePos, strikeoutPos;
2193 int underlineWidth, strikeoutWidth;
2194 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2195 OUTLINETEXTMETRICW* otm = NULL;
2197 if(!size)
2199 underlinePos = 0;
2200 underlineWidth = tm.tmAscent / 20 + 1;
2201 strikeoutPos = tm.tmAscent / 2;
2202 strikeoutWidth = underlineWidth;
2204 else
2206 otm = HeapAlloc(GetProcessHeap(), 0, size);
2207 GetOutlineTextMetricsW(hdc, size, otm);
2208 underlinePos = otm->otmsUnderscorePosition;
2209 underlineWidth = otm->otmsUnderscoreSize;
2210 strikeoutPos = otm->otmsStrikeoutPosition;
2211 strikeoutWidth = otm->otmsStrikeoutSize;
2212 HeapFree(GetProcessHeap(), 0, otm);
2215 if (PATH_IsPathOpen(dc->path))
2217 POINT pts[5];
2218 HPEN hpen;
2219 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2221 hbrush = SelectObject(hdc, hbrush);
2222 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2224 if (lf.lfUnderline)
2226 pts[0].x = x - underlinePos * sinEsc;
2227 pts[0].y = y - underlinePos * cosEsc;
2228 pts[1].x = x + xwidth - underlinePos * sinEsc;
2229 pts[1].y = y - ywidth - underlinePos * cosEsc;
2230 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2231 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2232 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2233 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2234 pts[4].x = pts[0].x;
2235 pts[4].y = pts[0].y;
2236 DPtoLP(hdc, pts, 5);
2237 Polygon(hdc, pts, 5);
2240 if (lf.lfStrikeOut)
2242 pts[0].x = x - strikeoutPos * sinEsc;
2243 pts[0].y = y - strikeoutPos * cosEsc;
2244 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2245 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2246 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2247 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2248 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2249 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2250 pts[4].x = pts[0].x;
2251 pts[4].y = pts[0].y;
2252 DPtoLP(hdc, pts, 5);
2253 Polygon(hdc, pts, 5);
2256 SelectObject(hdc, hpen);
2257 hbrush = SelectObject(hdc, hbrush);
2258 DeleteObject(hbrush);
2260 else
2262 POINT pts[2], oldpt;
2263 HPEN hpen;
2265 if (lf.lfUnderline)
2267 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2268 hpen = SelectObject(hdc, hpen);
2269 pts[0].x = x;
2270 pts[0].y = y;
2271 pts[1].x = x + xwidth;
2272 pts[1].y = y - ywidth;
2273 DPtoLP(hdc, pts, 2);
2274 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2275 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2276 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2277 DeleteObject(SelectObject(hdc, hpen));
2280 if (lf.lfStrikeOut)
2282 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2283 hpen = SelectObject(hdc, hpen);
2284 pts[0].x = x;
2285 pts[0].y = y;
2286 pts[1].x = x + xwidth;
2287 pts[1].y = y - ywidth;
2288 DPtoLP(hdc, pts, 2);
2289 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2290 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2291 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2292 DeleteObject(SelectObject(hdc, hpen));
2297 return ret;
2301 /***********************************************************************
2302 * TextOutA (GDI32.@)
2304 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2306 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2310 /***********************************************************************
2311 * TextOutW (GDI32.@)
2313 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2315 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2319 /***********************************************************************
2320 * PolyTextOutA (GDI32.@)
2322 * See PolyTextOutW.
2324 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2325 PPOLYTEXTA pptxt, /* [in] Array of strings */
2326 INT cStrings ) /* [in] Number of strings in array */
2328 for (; cStrings>0; cStrings--, pptxt++)
2329 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2330 return FALSE;
2331 return TRUE;
2336 /***********************************************************************
2337 * PolyTextOutW (GDI32.@)
2339 * Draw several Strings
2341 * RETURNS
2342 * TRUE: Success.
2343 * FALSE: Failure.
2345 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2346 PPOLYTEXTW pptxt, /* [in] Array of strings */
2347 INT cStrings ) /* [in] Number of strings in array */
2349 for (; cStrings>0; cStrings--, pptxt++)
2350 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2351 return FALSE;
2352 return TRUE;
2356 /* FIXME: all following APIs ******************************************/
2359 /***********************************************************************
2360 * SetMapperFlags (GDI32.@)
2362 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2364 DC *dc = DC_GetDCPtr( hDC );
2365 DWORD ret = 0;
2366 if(!dc) return 0;
2367 if(dc->funcs->pSetMapperFlags)
2369 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2370 /* FIXME: ret is just a success flag, we should return a proper value */
2372 else
2373 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2374 GDI_ReleaseObj( hDC );
2375 return ret;
2378 /***********************************************************************
2379 * GetAspectRatioFilterEx (GDI.486)
2381 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2383 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2384 return FALSE;
2387 /***********************************************************************
2388 * GetAspectRatioFilterEx (GDI32.@)
2390 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2392 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2393 return FALSE;
2397 /***********************************************************************
2398 * GetCharABCWidthsA (GDI32.@)
2400 * See GetCharABCWidthsW.
2402 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2403 LPABC abc )
2405 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2406 LPSTR str;
2407 LPWSTR wstr;
2408 BOOL ret = TRUE;
2410 if(count <= 0) return FALSE;
2412 str = HeapAlloc(GetProcessHeap(), 0, count);
2413 for(i = 0; i < count; i++)
2414 str[i] = (BYTE)(firstChar + i);
2416 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2418 for(i = 0; i < wlen; i++)
2420 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2422 ret = FALSE;
2423 break;
2425 abc++;
2428 HeapFree(GetProcessHeap(), 0, str);
2429 HeapFree(GetProcessHeap(), 0, wstr);
2431 return ret;
2435 /******************************************************************************
2436 * GetCharABCWidthsW [GDI32.@]
2438 * Retrieves widths of characters in range.
2440 * PARAMS
2441 * hdc [I] Handle of device context
2442 * firstChar [I] First character in range to query
2443 * lastChar [I] Last character in range to query
2444 * abc [O] Address of character-width structure
2446 * NOTES
2447 * Only works with TrueType fonts
2449 * RETURNS
2450 * Success: TRUE
2451 * Failure: FALSE
2453 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2454 LPABC abc )
2456 DC *dc = DC_GetDCPtr(hdc);
2457 unsigned int i;
2458 BOOL ret = FALSE;
2460 if (!dc) return FALSE;
2462 if(dc->gdiFont)
2463 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2464 else
2465 FIXME(": stub\n");
2467 if (ret)
2469 /* convert device units to logical */
2470 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2471 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2472 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2473 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2475 ret = TRUE;
2478 GDI_ReleaseObj(hdc);
2479 return ret;
2483 /******************************************************************************
2484 * GetCharABCWidthsI [GDI32.@]
2486 * Retrieves widths of characters in range.
2488 * PARAMS
2489 * hdc [I] Handle of device context
2490 * firstChar [I] First glyphs in range to query
2491 * count [I] Last glyphs in range to query
2492 * pgi [i] Array of glyphs to query
2493 * abc [O] Address of character-width structure
2495 * NOTES
2496 * Only works with TrueType fonts
2498 * RETURNS
2499 * Success: TRUE
2500 * Failure: FALSE
2502 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2503 LPWORD pgi, LPABC abc)
2505 DC *dc = DC_GetDCPtr(hdc);
2506 unsigned int i;
2507 BOOL ret = FALSE;
2509 if (!dc) return FALSE;
2511 if(dc->gdiFont)
2512 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2513 else
2514 FIXME(": stub\n");
2516 if (ret)
2518 /* convert device units to logical */
2519 for( i = 0; i < count; i++, abc++ ) {
2520 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2521 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2522 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2524 ret = TRUE;
2527 GDI_ReleaseObj(hdc);
2528 return ret;
2532 /***********************************************************************
2533 * GetGlyphOutlineA (GDI32.@)
2535 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2536 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2537 LPVOID lpBuffer, const MAT2 *lpmat2 )
2539 LPWSTR p = NULL;
2540 DWORD ret;
2541 UINT c;
2543 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2544 int len;
2545 char mbchs[2];
2546 if(uChar > 0xff) { /* but, 2 bytes character only */
2547 len = 2;
2548 mbchs[0] = (uChar & 0xff00) >> 8;
2549 mbchs[1] = (uChar & 0xff);
2550 } else {
2551 len = 1;
2552 mbchs[0] = (uChar & 0xff);
2554 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2555 c = p[0];
2556 } else
2557 c = uChar;
2558 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2559 lpmat2);
2560 HeapFree(GetProcessHeap(), 0, p);
2561 return ret;
2564 /***********************************************************************
2565 * GetGlyphOutlineW (GDI32.@)
2567 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2568 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2569 LPVOID lpBuffer, const MAT2 *lpmat2 )
2571 DC *dc = DC_GetDCPtr(hdc);
2572 DWORD ret;
2574 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2575 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2577 if(!dc) return GDI_ERROR;
2579 if(dc->gdiFont)
2580 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2581 cbBuffer, lpBuffer, lpmat2);
2582 else
2583 ret = GDI_ERROR;
2585 GDI_ReleaseObj(hdc);
2586 return ret;
2590 /***********************************************************************
2591 * CreateScalableFontResourceA (GDI32.@)
2593 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2594 LPCSTR lpszResourceFile,
2595 LPCSTR lpszFontFile,
2596 LPCSTR lpszCurrentPath )
2598 HANDLE f;
2600 /* fHidden=1 - only visible for the calling app, read-only, not
2601 * enumbered with EnumFonts/EnumFontFamilies
2602 * lpszCurrentPath can be NULL
2604 FIXME("(%d,%s,%s,%s): stub\n",
2605 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2606 debugstr_a(lpszCurrentPath) );
2608 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2609 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2610 CloseHandle(f);
2611 SetLastError(ERROR_FILE_EXISTS);
2612 return FALSE;
2614 return FALSE; /* create failed */
2617 /***********************************************************************
2618 * CreateScalableFontResourceW (GDI32.@)
2620 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2621 LPCWSTR lpszResourceFile,
2622 LPCWSTR lpszFontFile,
2623 LPCWSTR lpszCurrentPath )
2625 FIXME("(%d,%p,%p,%p): stub\n",
2626 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2627 return FALSE; /* create failed */
2630 /*************************************************************************
2631 * GetKerningPairsA (GDI32.@)
2633 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2634 LPKERNINGPAIR kern_pairA )
2636 INT charset;
2637 CHARSETINFO csi;
2638 CPINFO cpi;
2639 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2640 KERNINGPAIR *kern_pairW;
2642 if (!cPairs && kern_pairA)
2644 SetLastError(ERROR_INVALID_PARAMETER);
2645 return 0;
2648 charset = GetTextCharset(hDC);
2649 if (!TranslateCharsetInfo((DWORD *)charset, &csi, TCI_SRCCHARSET))
2651 FIXME("Can't find codepage for charset %d\n", charset);
2652 return 0;
2654 if (!GetCPInfo(csi.ciACP, &cpi))
2656 FIXME("Can't find codepage %u info\n", csi.ciACP);
2657 return 0;
2659 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2661 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2662 if (!total_kern_pairs) return 0;
2664 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2665 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2667 for (i = 0; i < total_kern_pairs; i++)
2669 char first, second;
2671 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2672 continue;
2674 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2675 continue;
2677 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2678 continue;
2680 if (kern_pairA)
2682 if (kern_pairs_copied >= cPairs) break;
2684 kern_pairA->wFirst = (BYTE)first;
2685 kern_pairA->wSecond = (BYTE)second;
2686 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2687 kern_pairA++;
2689 kern_pairs_copied++;
2692 HeapFree(GetProcessHeap(), 0, kern_pairW);
2694 return kern_pairs_copied;
2697 /*************************************************************************
2698 * GetKerningPairsW (GDI32.@)
2700 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2701 LPKERNINGPAIR lpKerningPairs )
2703 DC *dc;
2704 DWORD ret = 0;
2706 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2708 if (!cPairs && lpKerningPairs)
2710 SetLastError(ERROR_INVALID_PARAMETER);
2711 return 0;
2714 dc = DC_GetDCPtr(hDC);
2715 if (!dc) return 0;
2717 if (dc->gdiFont)
2718 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2720 GDI_ReleaseObj(hDC);
2721 return ret;
2724 /*************************************************************************
2725 * TranslateCharsetInfo [GDI32.@]
2727 * Fills a CHARSETINFO structure for a character set, code page, or
2728 * font. This allows making the correspondance between different labelings
2729 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2730 * of the same encoding.
2732 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2733 * only one codepage should be set in *lpSrc.
2735 * RETURNS
2736 * TRUE on success, FALSE on failure.
2739 BOOL WINAPI TranslateCharsetInfo(
2740 LPDWORD lpSrc, /* [in]
2741 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2742 if flags == TCI_SRCCHARSET: a character set value
2743 if flags == TCI_SRCCODEPAGE: a code page value
2745 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2746 DWORD flags /* [in] determines interpretation of lpSrc */)
2748 int index = 0;
2749 switch (flags) {
2750 case TCI_SRCFONTSIG:
2751 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2752 break;
2753 case TCI_SRCCODEPAGE:
2754 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2755 break;
2756 case TCI_SRCCHARSET:
2757 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2758 break;
2759 default:
2760 return FALSE;
2762 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2763 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2764 return TRUE;
2767 /*************************************************************************
2768 * GetFontLanguageInfo (GDI32.@)
2770 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2772 FONTSIGNATURE fontsig;
2773 static const DWORD GCP_DBCS_MASK=0x003F0000,
2774 GCP_DIACRITIC_MASK=0x00000000,
2775 FLI_GLYPHS_MASK=0x00000000,
2776 GCP_GLYPHSHAPE_MASK=0x00000040,
2777 GCP_KASHIDA_MASK=0x00000000,
2778 GCP_LIGATE_MASK=0x00000000,
2779 GCP_USEKERNING_MASK=0x00000000,
2780 GCP_REORDER_MASK=0x00000060;
2782 DWORD result=0;
2784 GetTextCharsetInfo( hdc, &fontsig, 0 );
2785 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2787 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2788 result|=GCP_DBCS;
2790 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2791 result|=GCP_DIACRITIC;
2793 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2794 result|=FLI_GLYPHS;
2796 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2797 result|=GCP_GLYPHSHAPE;
2799 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2800 result|=GCP_KASHIDA;
2802 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2803 result|=GCP_LIGATE;
2805 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2806 result|=GCP_USEKERNING;
2808 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2809 if( GetTextAlign( hdc) & TA_RTLREADING )
2810 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2811 result|=GCP_REORDER;
2813 return result;
2817 /*************************************************************************
2818 * GetFontData [GDI32.@]
2820 * Retrieve data for TrueType font.
2822 * RETURNS
2824 * success: Number of bytes returned
2825 * failure: GDI_ERROR
2827 * NOTES
2829 * Calls SetLastError()
2832 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2833 LPVOID buffer, DWORD length)
2835 DC *dc = DC_GetDCPtr(hdc);
2836 DWORD ret = GDI_ERROR;
2838 if(!dc) return GDI_ERROR;
2840 if(dc->gdiFont)
2841 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2843 GDI_ReleaseObj(hdc);
2844 return ret;
2847 /*************************************************************************
2848 * GetGlyphIndicesA [GDI32.@]
2850 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2851 LPWORD pgi, DWORD flags)
2853 DWORD ret;
2854 WCHAR *lpstrW;
2855 INT countW;
2857 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2858 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2860 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2861 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2862 HeapFree(GetProcessHeap(), 0, lpstrW);
2864 return ret;
2867 /*************************************************************************
2868 * GetGlyphIndicesW [GDI32.@]
2870 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2871 LPWORD pgi, DWORD flags)
2873 DC *dc = DC_GetDCPtr(hdc);
2874 DWORD ret = GDI_ERROR;
2876 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2877 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2879 if(!dc) return GDI_ERROR;
2881 if(dc->gdiFont)
2882 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2884 GDI_ReleaseObj(hdc);
2885 return ret;
2888 /*************************************************************************
2889 * GetCharacterPlacementA [GDI32.@]
2891 * See GetCharacterPlacementW.
2893 * NOTES:
2894 * the web browser control of ie4 calls this with dwFlags=0
2896 DWORD WINAPI
2897 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2898 INT nMaxExtent, GCP_RESULTSA *lpResults,
2899 DWORD dwFlags)
2901 WCHAR *lpStringW;
2902 INT uCountW;
2903 GCP_RESULTSW resultsW;
2904 DWORD ret;
2905 UINT font_cp;
2907 TRACE("%s, %d, %d, 0x%08x\n",
2908 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2910 /* both structs are equal in size */
2911 memcpy(&resultsW, lpResults, sizeof(resultsW));
2913 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2914 if(lpResults->lpOutString)
2915 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2917 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2919 lpResults->nGlyphs = resultsW.nGlyphs;
2920 lpResults->nMaxFit = resultsW.nMaxFit;
2922 if(lpResults->lpOutString) {
2923 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2924 lpResults->lpOutString, uCount, NULL, NULL );
2927 HeapFree(GetProcessHeap(), 0, lpStringW);
2928 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2930 return ret;
2933 /*************************************************************************
2934 * GetCharacterPlacementW [GDI32.@]
2936 * Retrieve information about a string. This includes the width, reordering,
2937 * Glyphing and so on.
2939 * RETURNS
2941 * The width and height of the string if successful, 0 if failed.
2943 * BUGS
2945 * All flags except GCP_REORDER are not yet implemented.
2946 * Reordering is not 100% complient to the Windows BiDi method.
2947 * Caret positioning is not yet implemented for BiDi.
2948 * Classes are not yet implemented.
2951 DWORD WINAPI
2952 GetCharacterPlacementW(
2953 HDC hdc, /* [in] Device context for which the rendering is to be done */
2954 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2955 INT uCount, /* [in] Number of WORDS in string. */
2956 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2957 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2958 DWORD dwFlags /* [in] Flags specifying how to process the string */
2961 DWORD ret=0;
2962 SIZE size;
2963 UINT i, nSet;
2965 TRACE("%s, %d, %d, 0x%08x\n",
2966 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2968 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2969 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2970 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2971 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2972 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2974 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2975 if(lpResults->lpClass) FIXME("classes not implemented\n");
2976 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2977 FIXME("Caret positions for complex scripts not implemented\n");
2979 nSet = (UINT)uCount;
2980 if(nSet > lpResults->nGlyphs)
2981 nSet = lpResults->nGlyphs;
2983 /* return number of initialized fields */
2984 lpResults->nGlyphs = nSet;
2986 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2988 /* Treat the case where no special handling was requested in a fastpath way */
2989 /* copy will do if the GCP_REORDER flag is not set */
2990 if(lpResults->lpOutString)
2991 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2993 if(lpResults->lpOrder)
2995 for(i = 0; i < nSet; i++)
2996 lpResults->lpOrder[i] = i;
2998 } else
3000 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3001 nSet, lpResults->lpOrder );
3004 /* FIXME: Will use the placement chars */
3005 if (lpResults->lpDx)
3007 int c;
3008 for (i = 0; i < nSet; i++)
3010 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3011 lpResults->lpDx[i]= c;
3015 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3017 int pos = 0;
3019 lpResults->lpCaretPos[0] = 0;
3020 for (i = 1; i < nSet; i++)
3021 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3022 lpResults->lpCaretPos[i] = (pos += size.cx);
3025 if(lpResults->lpGlyphs)
3026 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3028 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3029 ret = MAKELONG(size.cx, size.cy);
3031 return ret;
3034 /*************************************************************************
3035 * GetCharABCWidthsFloatA [GDI32.@]
3037 * See GetCharABCWidthsFloatW.
3039 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3041 INT i, wlen, count = (INT)(last - first + 1);
3042 LPSTR str;
3043 LPWSTR wstr;
3044 BOOL ret = TRUE;
3046 if (count <= 0) return FALSE;
3048 str = HeapAlloc(GetProcessHeap(), 0, count);
3050 for(i = 0; i < count; i++)
3051 str[i] = (BYTE)(first + i);
3053 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3055 for (i = 0; i < wlen; i++)
3057 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3059 ret = FALSE;
3060 break;
3062 abcf++;
3065 HeapFree( GetProcessHeap(), 0, str );
3066 HeapFree( GetProcessHeap(), 0, wstr );
3068 return ret;
3071 /*************************************************************************
3072 * GetCharABCWidthsFloatW [GDI32.@]
3074 * Retrieves widths of a range of characters.
3076 * PARAMS
3077 * hdc [I] Handle to device context.
3078 * first [I] First character in range to query.
3079 * last [I] Last character in range to query.
3080 * abcf [O] Array of LPABCFLOAT structures.
3082 * RETURNS
3083 * Success: TRUE
3084 * Failure: FALSE
3086 * BUGS
3087 * Only works with TrueType fonts. It also doesn't return real
3088 * floats but converted integers because it's implemented on
3089 * top of GetCharABCWidthsW.
3091 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3093 ABC *abc;
3094 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3095 BOOL ret;
3097 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3099 abc = HeapAlloc( GetProcessHeap(), 0, size );
3100 if (!abc) return FALSE;
3102 ret = GetCharABCWidthsW( hdc, first, last, abc );
3103 if (ret)
3105 for (i = first; i <= last; i++, abc++, abcf++)
3107 abcf->abcfA = abc->abcA;
3108 abcf->abcfB = abc->abcB;
3109 abcf->abcfC = abc->abcC;
3112 HeapFree( GetProcessHeap(), 0, abc );
3113 return ret;
3116 /*************************************************************************
3117 * GetCharWidthFloatA [GDI32.@]
3119 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3120 UINT iLastChar, PFLOAT pxBuffer)
3122 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3123 return 0;
3126 /*************************************************************************
3127 * GetCharWidthFloatW [GDI32.@]
3129 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3130 UINT iLastChar, PFLOAT pxBuffer)
3132 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3133 return 0;
3137 /***********************************************************************
3139 * Font Resource API *
3141 ***********************************************************************/
3143 /***********************************************************************
3144 * AddFontResourceA (GDI32.@)
3146 INT WINAPI AddFontResourceA( LPCSTR str )
3148 return AddFontResourceExA( str, 0, NULL);
3151 /***********************************************************************
3152 * AddFontResourceW (GDI32.@)
3154 INT WINAPI AddFontResourceW( LPCWSTR str )
3156 return AddFontResourceExW(str, 0, NULL);
3160 /***********************************************************************
3161 * AddFontResourceExA (GDI32.@)
3163 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3165 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3166 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3167 INT ret;
3169 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3170 ret = AddFontResourceExW(strW, fl, pdv);
3171 HeapFree(GetProcessHeap(), 0, strW);
3172 return ret;
3175 /***********************************************************************
3176 * AddFontResourceExW (GDI32.@)
3178 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3180 return WineEngAddFontResourceEx(str, fl, pdv);
3183 /***********************************************************************
3184 * RemoveFontResourceA (GDI32.@)
3186 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3188 return RemoveFontResourceExA(str, 0, 0);
3191 /***********************************************************************
3192 * RemoveFontResourceW (GDI32.@)
3194 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3196 return RemoveFontResourceExW(str, 0, 0);
3199 /***********************************************************************
3200 * AddFontMemResourceEx (GDI32.@)
3202 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3204 FIXME("(%p,%08x,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
3205 return NULL;
3208 /***********************************************************************
3209 * RemoveFontResourceExA (GDI32.@)
3211 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3213 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3214 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3215 INT ret;
3217 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3218 ret = RemoveFontResourceExW(strW, fl, pdv);
3219 HeapFree(GetProcessHeap(), 0, strW);
3220 return ret;
3223 /***********************************************************************
3224 * RemoveFontResourceExW (GDI32.@)
3226 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3228 return WineEngRemoveFontResourceEx(str, fl, pdv);
3231 /***********************************************************************
3232 * GetTextCharset (GDI32.@)
3234 UINT WINAPI GetTextCharset(HDC hdc)
3236 /* MSDN docs say this is equivalent */
3237 return GetTextCharsetInfo(hdc, NULL, 0);
3240 /***********************************************************************
3241 * GetTextCharsetInfo (GDI32.@)
3243 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3245 UINT ret = DEFAULT_CHARSET;
3246 DC *dc = DC_GetDCPtr(hdc);
3248 if (dc)
3250 if (dc->gdiFont)
3251 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3253 GDI_ReleaseObj(hdc);
3256 if (ret == DEFAULT_CHARSET && fs)
3257 memset(fs, 0, sizeof(FONTSIGNATURE));
3258 return ret;
3261 /***********************************************************************
3262 * GdiGetCharDimensions (GDI32.@)
3264 * Gets the average width of the characters in the English alphabet.
3266 * PARAMS
3267 * hdc [I] Handle to the device context to measure on.
3268 * lptm [O] Pointer to memory to store the text metrics into.
3269 * height [O] On exit, the maximum height of characters in the English alphabet.
3271 * RETURNS
3272 * The average width of characters in the English alphabet.
3274 * NOTES
3275 * This function is used by the dialog manager to get the size of a dialog
3276 * unit. It should also be used by other pieces of code that need to know
3277 * the size of a dialog unit in logical units without having access to the
3278 * window handle of the dialog.
3279 * Windows caches the font metrics from this function, but we don't and
3280 * there doesn't appear to be an immediate advantage to do so.
3282 * SEE ALSO
3283 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3285 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3287 SIZE sz;
3288 static const WCHAR alphabet[] = {
3289 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3290 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3291 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3293 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3295 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3297 if (height) *height = sz.cy;
3298 return (sz.cx / 26 + 1) / 2;
3301 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3303 FIXME("(%d): stub\n", fEnableEUDC);
3304 return FALSE;
3307 /***********************************************************************
3308 * GetCharWidthI (GDI32.@)
3310 * Retrieve widths of characters.
3312 * PARAMS
3313 * hdc [I] Handle to a device context.
3314 * first [I] First glyph in range to query.
3315 * count [I] Number of glyph indices to query.
3316 * glyphs [I] Array of glyphs to query.
3317 * buffer [O] Buffer to receive character widths.
3319 * NOTES
3320 * Only works with TrueType fonts.
3322 * RETURNS
3323 * Success: TRUE
3324 * Failure: FALSE
3326 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3328 ABC *abc;
3329 unsigned int i;
3331 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3333 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3334 return FALSE;
3336 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3338 HeapFree(GetProcessHeap(), 0, abc);
3339 return FALSE;
3342 for (i = 0; i < count; i++)
3343 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3345 HeapFree(GetProcessHeap(), 0, abc);
3346 return TRUE;
3349 /***********************************************************************
3350 * GetFontUnicodeRanges (GDI32.@)
3352 * Retrieve a list of supported Unicode characters in a font.
3354 * PARAMS
3355 * hdc [I] Handle to a device context.
3356 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3358 * RETURNS
3359 * Success: Number of bytes written to the buffer pointed to by lpgs.
3360 * Failure: 0
3363 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3365 return WineEngGetFontUnicodeRanges(hdc, lpgs);