push ab3cc77eb114d2bd400734a9dccad24563f936a6
[wine/hacks.git] / dlls / gdi32 / font.c
blob269638fd3fb6e2d20099ef045199d2102924088b
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 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI GdiGetCodePage( HDC hdc )
354 UINT cp = CP_ACP;
355 CHARSETINFO csi;
356 int charset = GetTextCharset(hdc);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
360 cp = csi.ciACP;
361 else {
362 switch(charset) {
363 case OEM_CHARSET:
364 cp = GetOEMCP();
365 break;
366 case DEFAULT_CHARSET:
367 cp = GetACP();
368 break;
370 case VISCII_CHARSET:
371 case TCVN_CHARSET:
372 case KOI8_CHARSET:
373 case ISO3_CHARSET:
374 case ISO4_CHARSET:
375 case ISO10_CHARSET:
376 case CELTIC_CHARSET:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
384 cp = CP_ACP;
385 break;
387 default:
388 FIXME("Can't find codepage for charset %d\n", charset);
389 break;
393 TRACE("charset %d => cp %d\n", charset, cp);
394 return cp;
397 /***********************************************************************
398 * FONT_mbtowc
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
407 * itself.
409 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
411 UINT cp;
412 INT lenW;
413 LPWSTR strW;
415 cp = GdiGetCodePage( hdc );
417 if(count == -1) count = strlen(str);
418 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
419 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
420 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
421 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
422 if(plenW) *plenW = lenW;
423 if(pCP) *pCP = cp;
424 return strW;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
433 LOGFONTW lfW;
435 if (plfA) {
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
438 } else
439 return CreateFontIndirectW( NULL );
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
448 HFONT hFont = 0;
450 if (plf)
452 FONTOBJ* fontPtr;
453 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
454 (HGDIOBJ *)&hFont, &font_funcs )))
456 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
458 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
459 WCHAR* pFaceNameSuffix = NULL;
461 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf->lfHeight, plf->lfWidth,
465 plf->lfEscapement, plf->lfOrientation,
466 plf->lfPitchAndFamily,
467 plf->lfOutPrecision, plf->lfClipPrecision,
468 plf->lfQuality, plf->lfCharSet,
469 debugstr_w(plf->lfFaceName),
470 plf->lfWeight > 400 ? "Bold" : "",
471 plf->lfItalic ? "Italic" : "",
472 plf->lfUnderline ? "Underline" : "", hFont);
474 if (plf->lfEscapement != plf->lfOrientation) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
482 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
483 if (pFaceNameItalicSuffix) {
484 fontPtr->logfont.lfItalic = TRUE;
485 pFaceNameSuffix = pFaceNameItalicSuffix;
488 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
489 if (pFaceNameBoldSuffix) {
490 if (fontPtr->logfont.lfWeight < FW_BOLD) {
491 fontPtr->logfont.lfWeight = FW_BOLD;
493 if (!pFaceNameSuffix ||
494 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
495 pFaceNameSuffix = pFaceNameBoldSuffix;
499 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
501 GDI_ReleaseObj( hFont );
504 else WARN("(NULL) => NULL\n");
506 return hFont;
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
513 INT orient, INT weight, DWORD italic,
514 DWORD underline, DWORD strikeout, DWORD charset,
515 DWORD outpres, DWORD clippres, DWORD quality,
516 DWORD pitch, LPCSTR name )
518 LOGFONTA logfont;
520 logfont.lfHeight = height;
521 logfont.lfWidth = width;
522 logfont.lfEscapement = esc;
523 logfont.lfOrientation = orient;
524 logfont.lfWeight = weight;
525 logfont.lfItalic = italic;
526 logfont.lfUnderline = underline;
527 logfont.lfStrikeOut = strikeout;
528 logfont.lfCharSet = charset;
529 logfont.lfOutPrecision = outpres;
530 logfont.lfClipPrecision = clippres;
531 logfont.lfQuality = quality;
532 logfont.lfPitchAndFamily = pitch;
534 if (name)
535 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
536 else
537 logfont.lfFaceName[0] = '\0';
539 return CreateFontIndirectA( &logfont );
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
546 INT orient, INT weight, DWORD italic,
547 DWORD underline, DWORD strikeout, DWORD charset,
548 DWORD outpres, DWORD clippres, DWORD quality,
549 DWORD pitch, LPCWSTR name )
551 LOGFONTW logfont;
553 logfont.lfHeight = height;
554 logfont.lfWidth = width;
555 logfont.lfEscapement = esc;
556 logfont.lfOrientation = orient;
557 logfont.lfWeight = weight;
558 logfont.lfItalic = italic;
559 logfont.lfUnderline = underline;
560 logfont.lfStrikeOut = strikeout;
561 logfont.lfCharSet = charset;
562 logfont.lfOutPrecision = outpres;
563 logfont.lfClipPrecision = clippres;
564 logfont.lfQuality = quality;
565 logfont.lfPitchAndFamily = pitch;
567 if (name)
568 lstrcpynW(logfont.lfFaceName, name,
569 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
570 else
571 logfont.lfFaceName[0] = '\0';
573 return CreateFontIndirectW( &logfont );
577 /***********************************************************************
578 * FONT_SelectObject
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
586 * font.
588 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
590 HGDIOBJ ret = 0;
591 DC *dc = DC_GetDCPtr( hdc );
593 if (!dc) return 0;
595 if (dc->hFont != handle || dc->gdiFont == NULL)
597 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
598 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
601 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
603 if (ret && dc->gdiFont) dc->gdiFont = 0;
605 if (ret == HGDI_ERROR)
606 ret = 0; /* SelectObject returns 0 on error */
607 else
609 ret = dc->hFont;
610 dc->hFont = handle;
612 DC_ReleaseDCPtr( dc );
613 return ret;
617 /***********************************************************************
618 * FONT_GetObject16
620 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
622 FONTOBJ *font = obj;
623 LOGFONT16 lf16;
625 FONT_LogFontWTo16( &font->logfont, &lf16 );
627 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
628 memcpy( buffer, &lf16, count );
629 return count;
632 /***********************************************************************
633 * FONT_GetObjectA
635 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
637 FONTOBJ *font = obj;
638 LOGFONTA lfA;
640 if(!buffer)
641 return sizeof(lfA);
642 FONT_LogFontWToA( &font->logfont, &lfA );
644 if (count > sizeof(lfA)) count = sizeof(lfA);
645 memcpy( buffer, &lfA, count );
646 return count;
649 /***********************************************************************
650 * FONT_GetObjectW
652 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
654 FONTOBJ *font = obj;
655 if(!buffer)
656 return sizeof(LOGFONTW);
657 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
658 memcpy( buffer, &font->logfont, count );
659 return count;
663 /***********************************************************************
664 * FONT_DeleteObject
666 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
668 WineEngDestroyFontInstance( handle );
669 return GDI_FreeObject( handle, obj );
673 /***********************************************************************
674 * FONT_EnumInstance16
676 * Called by the device driver layer to pass font info
677 * down to the application.
679 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
680 * We have to use other types because of the FONTENUMPROCW definition.
682 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
683 DWORD fType, LPARAM lp )
685 fontEnum16 *pfe = (fontEnum16*)lp;
686 INT ret = 1;
687 DC *dc;
689 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
690 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
692 WORD args[7];
693 DWORD result;
695 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
696 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
697 pfe->dwFlags |= ENUM_CALLED;
698 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
700 args[6] = SELECTOROF(pfe->segLogFont);
701 args[5] = OFFSETOF(pfe->segLogFont);
702 args[4] = SELECTOROF(pfe->segTextMetric);
703 args[3] = OFFSETOF(pfe->segTextMetric);
704 args[2] = fType;
705 args[1] = HIWORD(pfe->lpData);
706 args[0] = LOWORD(pfe->lpData);
707 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
708 ret = LOWORD(result);
710 /* get the lock again and make sure the DC is still valid */
711 dc = DC_GetDCPtr( pfe->hdc );
712 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
714 if (dc) DC_ReleaseDCPtr( dc );
715 pfe->hdc = 0; /* make sure we don't try to release it later on */
716 pfe->dc = NULL;
717 ret = 0;
720 return ret;
723 /***********************************************************************
724 * FONT_EnumInstance
726 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
727 * We have to use other types because of the FONTENUMPROCW definition.
729 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
730 DWORD fType, LPARAM lp )
732 fontEnum32 *pfe = (fontEnum32*)lp;
733 INT ret = 1;
734 DC *dc;
736 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
737 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
738 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
739 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
741 /* convert font metrics */
742 ENUMLOGFONTEXA logfont;
743 NEWTEXTMETRICEXA tmA;
745 pfe->dwFlags |= ENUM_CALLED;
746 if (!(pfe->dwFlags & ENUM_UNICODE))
748 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
749 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
750 plf = (LOGFONTW *)&logfont.elfLogFont;
751 ptm = (TEXTMETRICW *)&tmA;
753 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
755 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
757 /* get the lock again and make sure the DC is still valid */
758 dc = DC_GetDCPtr( pfe->hdc );
759 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
761 if (dc) DC_ReleaseDCPtr( dc );
762 pfe->hdc = 0; /* make sure we don't try to release it later on */
763 pfe->dc = NULL;
764 ret = 0;
767 return ret;
770 /***********************************************************************
771 * EnumFontFamiliesEx (GDI.613)
773 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
774 FONTENUMPROC16 efproc, LPARAM lParam,
775 DWORD dwFlags)
777 fontEnum16 fe16;
778 INT16 ret = 1, ret2;
779 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
780 NEWTEXTMETRICEX16 tm16;
781 ENUMLOGFONTEX16 lf16;
782 LOGFONTW lfW;
783 BOOL enum_gdi_fonts;
785 if (!dc) return 0;
786 FONT_LogFont16ToW(plf, &lfW);
788 fe16.hdc = HDC_32(hDC);
789 fe16.dc = dc;
790 fe16.physDev = dc->physDev;
791 fe16.lpLogFontParam = plf;
792 fe16.lpEnumFunc = efproc;
793 fe16.lpData = lParam;
794 fe16.lpTextMetric = &tm16;
795 fe16.lpLogFont = &lf16;
796 fe16.segTextMetric = MapLS( &tm16 );
797 fe16.segLogFont = MapLS( &lf16 );
798 fe16.dwFlags = 0;
800 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
802 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
804 ret = 0;
805 goto done;
808 if (enum_gdi_fonts)
809 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
810 fe16.dwFlags &= ~ENUM_CALLED;
811 if (ret && dc->funcs->pEnumDeviceFonts) {
812 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
813 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
814 ret = ret2;
816 done:
817 UnMapLS( fe16.segTextMetric );
818 UnMapLS( fe16.segLogFont );
819 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
820 return ret;
823 /***********************************************************************
824 * FONT_EnumFontFamiliesEx
826 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
827 FONTENUMPROCW efproc,
828 LPARAM lParam, DWORD dwUnicode)
830 INT ret = 1, ret2;
831 DC *dc = DC_GetDCPtr( hDC );
832 fontEnum32 fe32;
833 BOOL enum_gdi_fonts;
835 if (!dc) return 0;
837 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
838 plf->lfCharSet);
839 fe32.lpLogFontParam = plf;
840 fe32.lpEnumFunc = efproc;
841 fe32.lpData = lParam;
842 fe32.dwFlags = dwUnicode;
843 fe32.hdc = hDC;
844 fe32.dc = dc;
845 fe32.physDev = dc->physDev;
847 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
849 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
851 ret = 0;
852 goto done;
855 if (enum_gdi_fonts)
856 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
857 fe32.dwFlags &= ~ENUM_CALLED;
858 if (ret && dc->funcs->pEnumDeviceFonts) {
859 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
860 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
861 ret = ret2;
863 done:
864 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
865 return ret;
868 /***********************************************************************
869 * EnumFontFamiliesExW (GDI32.@)
871 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
872 FONTENUMPROCW efproc,
873 LPARAM lParam, DWORD dwFlags )
875 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
878 /***********************************************************************
879 * EnumFontFamiliesExA (GDI32.@)
881 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
882 FONTENUMPROCA efproc,
883 LPARAM lParam, DWORD dwFlags)
885 LOGFONTW lfW;
886 FONT_LogFontAToW( plf, &lfW );
888 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
891 /***********************************************************************
892 * EnumFontFamilies (GDI.330)
894 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
895 FONTENUMPROC16 efproc, LPARAM lpData )
897 LOGFONT16 lf;
899 lf.lfCharSet = DEFAULT_CHARSET;
900 if (lpFamily)
902 if (!*lpFamily) return 1;
903 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
905 else lf.lfFaceName[0] = '\0';
907 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
910 /***********************************************************************
911 * EnumFontFamiliesA (GDI32.@)
913 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
914 FONTENUMPROCA efproc, LPARAM lpData )
916 LOGFONTA lf;
918 lf.lfCharSet = DEFAULT_CHARSET;
919 if (lpFamily)
921 if (!*lpFamily) return 1;
922 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
924 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
926 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
929 /***********************************************************************
930 * EnumFontFamiliesW (GDI32.@)
932 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
933 FONTENUMPROCW efproc, LPARAM lpData )
935 LOGFONTW lf;
937 lf.lfCharSet = DEFAULT_CHARSET;
938 if (lpFamily)
940 if (!*lpFamily) return 1;
941 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
943 else lf.lfFaceName[0] = 0;
945 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
948 /***********************************************************************
949 * EnumFonts (GDI.70)
951 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
952 LPARAM lpData )
954 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
957 /***********************************************************************
958 * EnumFontsA (GDI32.@)
960 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
961 LPARAM lpData )
963 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
966 /***********************************************************************
967 * EnumFontsW (GDI32.@)
969 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
970 LPARAM lpData )
972 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
976 /***********************************************************************
977 * GetTextCharacterExtra (GDI32.@)
979 INT WINAPI GetTextCharacterExtra( HDC hdc )
981 INT ret;
982 DC *dc = DC_GetDCPtr( hdc );
983 if (!dc) return 0x80000000;
984 ret = dc->charExtra;
985 DC_ReleaseDCPtr( dc );
986 return ret;
990 /***********************************************************************
991 * SetTextCharacterExtra (GDI32.@)
993 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
995 INT prev;
996 DC * dc = DC_GetDCPtr( hdc );
997 if (!dc) return 0x80000000;
998 if (dc->funcs->pSetTextCharacterExtra)
999 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1000 else
1002 prev = dc->charExtra;
1003 dc->charExtra = extra;
1005 DC_ReleaseDCPtr( dc );
1006 return prev;
1010 /***********************************************************************
1011 * SetTextJustification (GDI32.@)
1013 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1015 BOOL ret = TRUE;
1016 DC * dc = DC_GetDCPtr( hdc );
1017 if (!dc) return FALSE;
1018 if (dc->funcs->pSetTextJustification)
1019 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1020 else
1022 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1023 if (!extra) breaks = 0;
1024 if (breaks)
1026 dc->breakExtra = extra / breaks;
1027 dc->breakRem = extra - (breaks * dc->breakExtra);
1029 else
1031 dc->breakExtra = 0;
1032 dc->breakRem = 0;
1035 DC_ReleaseDCPtr( dc );
1036 return ret;
1040 /***********************************************************************
1041 * GetTextFaceA (GDI32.@)
1043 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1045 INT res = GetTextFaceW(hdc, 0, NULL);
1046 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1047 GetTextFaceW( hdc, res, nameW );
1049 if (name)
1051 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1052 name[count-1] = 0;
1053 res = strlen(name);
1055 else
1056 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1057 HeapFree( GetProcessHeap(), 0, nameW );
1058 return res;
1061 /***********************************************************************
1062 * GetTextFaceW (GDI32.@)
1064 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1066 FONTOBJ *font;
1067 INT ret = 0;
1069 DC * dc = DC_GetDCPtr( hdc );
1070 if (!dc) return 0;
1072 if(dc->gdiFont)
1073 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1074 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1076 if (name)
1078 lstrcpynW( name, font->logfont.lfFaceName, count );
1079 ret = strlenW(name);
1081 else ret = strlenW(font->logfont.lfFaceName) + 1;
1082 GDI_ReleaseObj( dc->hFont );
1084 DC_ReleaseDCPtr( dc );
1085 return ret;
1089 /***********************************************************************
1090 * GetTextExtentPoint32A (GDI32.@)
1092 * See GetTextExtentPoint32W.
1094 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1095 LPSIZE size )
1097 BOOL ret = FALSE;
1098 INT wlen;
1099 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1101 if (p) {
1102 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1103 HeapFree( GetProcessHeap(), 0, p );
1106 TRACE("(%p %s %d %p): returning %d x %d\n",
1107 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1108 return ret;
1112 /***********************************************************************
1113 * GetTextExtentPoint32W [GDI32.@]
1115 * Computes width/height for a string.
1117 * Computes width and height of the specified string.
1119 * RETURNS
1120 * Success: TRUE
1121 * Failure: FALSE
1123 BOOL WINAPI GetTextExtentPoint32W(
1124 HDC hdc, /* [in] Handle of device context */
1125 LPCWSTR str, /* [in] Address of text string */
1126 INT count, /* [in] Number of characters in string */
1127 LPSIZE size) /* [out] Address of structure for string size */
1129 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1132 /***********************************************************************
1133 * GetTextExtentPointI [GDI32.@]
1135 * Computes width and height of the array of glyph indices.
1137 * RETURNS
1138 * Success: TRUE
1139 * Failure: FALSE
1141 BOOL WINAPI GetTextExtentPointI(
1142 HDC hdc, /* [in] Handle of device context */
1143 const WORD *indices, /* [in] Address of glyph index array */
1144 INT count, /* [in] Number of glyphs in array */
1145 LPSIZE size) /* [out] Address of structure for string size */
1147 BOOL ret = FALSE;
1148 DC * dc = DC_GetDCPtr( hdc );
1149 if (!dc) return FALSE;
1151 if(dc->gdiFont) {
1152 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1153 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1154 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1155 size->cx += count * dc->charExtra;
1157 else if(dc->funcs->pGetTextExtentExPoint) {
1158 FIXME("calling GetTextExtentExPoint\n");
1159 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1160 count, 0, NULL, NULL, size );
1163 DC_ReleaseDCPtr( dc );
1165 TRACE("(%p %p %d %p): returning %d x %d\n",
1166 hdc, indices, count, size, size->cx, size->cy );
1167 return ret;
1171 /***********************************************************************
1172 * GetTextExtentPointA (GDI32.@)
1174 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1175 LPSIZE size )
1177 TRACE("not bug compatible.\n");
1178 return GetTextExtentPoint32A( hdc, str, count, size );
1181 /***********************************************************************
1182 * GetTextExtentPointW (GDI32.@)
1184 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1185 LPSIZE size )
1187 TRACE("not bug compatible.\n");
1188 return GetTextExtentPoint32W( hdc, str, count, size );
1192 /***********************************************************************
1193 * GetTextExtentExPointA (GDI32.@)
1195 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1196 INT maxExt, LPINT lpnFit,
1197 LPINT alpDx, LPSIZE size )
1199 BOOL ret;
1200 INT wlen;
1201 INT *walpDx = NULL;
1202 LPWSTR p = NULL;
1204 if (alpDx &&
1205 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1206 return FALSE;
1208 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1209 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1210 if (walpDx)
1212 INT n = lpnFit ? *lpnFit : wlen;
1213 INT i, j;
1214 for(i = 0, j = 0; i < n; i++, j++)
1216 alpDx[j] = walpDx[i];
1217 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1220 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1221 HeapFree( GetProcessHeap(), 0, p );
1222 HeapFree( GetProcessHeap(), 0, walpDx );
1223 return ret;
1227 /***********************************************************************
1228 * GetTextExtentExPointW (GDI32.@)
1230 * Return the size of the string as it would be if it was output properly by
1231 * e.g. TextOut.
1233 * This should include
1234 * - Intercharacter spacing
1235 * - justification spacing (not yet done)
1236 * - kerning? see below
1238 * Kerning. Since kerning would be carried out by the rendering code it should
1239 * be done by the driver. However they don't support it yet. Also I am not
1240 * yet persuaded that (certainly under Win95) any kerning is actually done.
1242 * str: According to MSDN this should be null-terminated. That is not true; a
1243 * null will not terminate it early.
1244 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1245 * than count. I have seen it be either the size of the full string or
1246 * 1 less than the size of the full string. I have not seen it bear any
1247 * resemblance to the portion that would fit.
1248 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1249 * trailing intercharacter spacing and any trailing justification.
1251 * FIXME
1252 * Currently we do this by measuring each character etc. We should do it by
1253 * passing the request to the driver, perhaps by extending the
1254 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1255 * thinking about kerning issues and rounding issues in the justification.
1258 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1259 INT maxExt, LPINT lpnFit,
1260 LPINT alpDx, LPSIZE size )
1262 INT nFit = 0;
1263 LPINT dxs = NULL;
1264 DC *dc;
1265 BOOL ret = FALSE;
1266 TEXTMETRICW tm;
1268 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1270 dc = DC_GetDCPtr(hdc);
1271 if (! dc)
1272 return FALSE;
1274 GetTextMetricsW(hdc, &tm);
1276 /* If we need to calculate nFit, then we need the partial extents even if
1277 the user hasn't provided us with an array. */
1278 if (lpnFit)
1280 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1281 if (! dxs)
1283 DC_ReleaseDCPtr(dc);
1284 SetLastError(ERROR_OUTOFMEMORY);
1285 return FALSE;
1288 else
1289 dxs = alpDx;
1291 if (dc->gdiFont)
1292 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1293 0, NULL, dxs, size);
1294 else if (dc->funcs->pGetTextExtentExPoint)
1295 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1296 0, NULL, dxs, size);
1298 /* Perform device size to world size transformations. */
1299 if (ret)
1301 INT extra = dc->charExtra,
1302 breakExtra = dc->breakExtra,
1303 breakRem = dc->breakRem,
1306 if (dxs)
1308 for (i = 0; i < count; ++i)
1310 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1311 dxs[i] += (i+1) * extra;
1312 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1314 dxs[i] += breakExtra;
1315 if (breakRem > 0)
1317 breakRem--;
1318 dxs[i]++;
1321 if (dxs[i] <= maxExt)
1322 ++nFit;
1324 breakRem = dc->breakRem;
1326 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1327 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1329 if (!dxs && count > 1 && (breakExtra || breakRem))
1331 for (i = 0; i < count; i++)
1333 if (str[i] == tm.tmBreakChar)
1335 size->cx += breakExtra;
1336 if (breakRem > 0)
1338 breakRem--;
1339 (size->cx)++;
1346 if (lpnFit)
1347 *lpnFit = nFit;
1349 if (! alpDx)
1350 HeapFree(GetProcessHeap(), 0, dxs);
1352 DC_ReleaseDCPtr( dc );
1354 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1355 return ret;
1358 /***********************************************************************
1359 * GetTextMetricsA (GDI32.@)
1361 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1363 TEXTMETRICW tm32;
1365 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1366 FONT_TextMetricWToA( &tm32, metrics );
1367 return TRUE;
1370 /***********************************************************************
1371 * GetTextMetricsW (GDI32.@)
1373 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1375 BOOL ret = FALSE;
1376 DC * dc = DC_GetDCPtr( hdc );
1377 if (!dc) return FALSE;
1379 if (dc->gdiFont)
1380 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1381 else if (dc->funcs->pGetTextMetrics)
1382 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1384 if (ret)
1386 /* device layer returns values in device units
1387 * therefore we have to convert them to logical */
1389 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1390 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1392 #define WDPTOLP(x) ((x<0)? \
1393 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1394 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1395 #define HDPTOLP(y) ((y<0)? \
1396 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1397 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1399 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1400 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1401 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1402 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1403 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1404 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1405 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1406 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1407 ret = TRUE;
1408 #undef WDPTOLP
1409 #undef HDPTOLP
1410 TRACE("text metrics:\n"
1411 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1412 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1413 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1414 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1415 " PitchAndFamily = %02x\n"
1416 " --------------------\n"
1417 " InternalLeading = %i\n"
1418 " Ascent = %i\n"
1419 " Descent = %i\n"
1420 " Height = %i\n",
1421 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1422 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1423 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1424 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1425 metrics->tmPitchAndFamily,
1426 metrics->tmInternalLeading,
1427 metrics->tmAscent,
1428 metrics->tmDescent,
1429 metrics->tmHeight );
1431 DC_ReleaseDCPtr( dc );
1432 return ret;
1436 /***********************************************************************
1437 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1439 * NOTES
1440 * lpOTM should be LPOUTLINETEXTMETRIC
1442 * RETURNS
1443 * Success: Non-zero or size of required buffer
1444 * Failure: 0
1446 UINT16 WINAPI GetOutlineTextMetrics16(
1447 HDC16 hdc, /* [in] Handle of device context */
1448 UINT16 cbData, /* [in] Size of metric data array */
1449 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1451 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1452 return 0;
1456 /***********************************************************************
1457 * GetOutlineTextMetricsA (GDI32.@)
1458 * Gets metrics for TrueType fonts.
1460 * NOTES
1461 * If the supplied buffer isn't big enough Windows partially fills it up to
1462 * its given length and returns that length.
1464 * RETURNS
1465 * Success: Non-zero or size of required buffer
1466 * Failure: 0
1468 UINT WINAPI GetOutlineTextMetricsA(
1469 HDC hdc, /* [in] Handle of device context */
1470 UINT cbData, /* [in] Size of metric data array */
1471 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1473 char buf[512], *ptr;
1474 UINT ret, needed;
1475 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1476 OUTLINETEXTMETRICA *output = lpOTM;
1477 INT left, len;
1479 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1480 return 0;
1481 if(ret > sizeof(buf))
1482 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1483 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1485 needed = sizeof(OUTLINETEXTMETRICA);
1486 if(lpOTMW->otmpFamilyName)
1487 needed += WideCharToMultiByte(CP_ACP, 0,
1488 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1489 NULL, 0, NULL, NULL);
1490 if(lpOTMW->otmpFaceName)
1491 needed += WideCharToMultiByte(CP_ACP, 0,
1492 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1493 NULL, 0, NULL, NULL);
1494 if(lpOTMW->otmpStyleName)
1495 needed += WideCharToMultiByte(CP_ACP, 0,
1496 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1497 NULL, 0, NULL, NULL);
1498 if(lpOTMW->otmpFullName)
1499 needed += WideCharToMultiByte(CP_ACP, 0,
1500 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1501 NULL, 0, NULL, NULL);
1503 if(!lpOTM) {
1504 ret = needed;
1505 goto end;
1508 TRACE("needed = %d\n", needed);
1509 if(needed > cbData)
1510 /* Since the supplied buffer isn't big enough, we'll alloc one
1511 that is and memcpy the first cbData bytes into the lpOTM at
1512 the end. */
1513 output = HeapAlloc(GetProcessHeap(), 0, needed);
1515 ret = output->otmSize = min(needed, cbData);
1516 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1517 output->otmFiller = 0;
1518 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1519 output->otmfsSelection = lpOTMW->otmfsSelection;
1520 output->otmfsType = lpOTMW->otmfsType;
1521 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1522 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1523 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1524 output->otmEMSquare = lpOTMW->otmEMSquare;
1525 output->otmAscent = lpOTMW->otmAscent;
1526 output->otmDescent = lpOTMW->otmDescent;
1527 output->otmLineGap = lpOTMW->otmLineGap;
1528 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1529 output->otmsXHeight = lpOTMW->otmsXHeight;
1530 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1531 output->otmMacAscent = lpOTMW->otmMacAscent;
1532 output->otmMacDescent = lpOTMW->otmMacDescent;
1533 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1534 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1535 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1536 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1537 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1538 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1539 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1540 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1541 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1542 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1545 ptr = (char*)(output + 1);
1546 left = needed - sizeof(*output);
1548 if(lpOTMW->otmpFamilyName) {
1549 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1550 len = WideCharToMultiByte(CP_ACP, 0,
1551 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1552 ptr, left, NULL, NULL);
1553 left -= len;
1554 ptr += len;
1555 } else
1556 output->otmpFamilyName = 0;
1558 if(lpOTMW->otmpFaceName) {
1559 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1560 len = WideCharToMultiByte(CP_ACP, 0,
1561 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1562 ptr, left, NULL, NULL);
1563 left -= len;
1564 ptr += len;
1565 } else
1566 output->otmpFaceName = 0;
1568 if(lpOTMW->otmpStyleName) {
1569 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1570 len = WideCharToMultiByte(CP_ACP, 0,
1571 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1572 ptr, left, NULL, NULL);
1573 left -= len;
1574 ptr += len;
1575 } else
1576 output->otmpStyleName = 0;
1578 if(lpOTMW->otmpFullName) {
1579 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1580 len = WideCharToMultiByte(CP_ACP, 0,
1581 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1582 ptr, left, NULL, NULL);
1583 left -= len;
1584 } else
1585 output->otmpFullName = 0;
1587 assert(left == 0);
1589 if(output != lpOTM) {
1590 memcpy(lpOTM, output, cbData);
1591 HeapFree(GetProcessHeap(), 0, output);
1593 /* check if the string offsets really fit into the provided size */
1594 /* FIXME: should we check string length as well? */
1595 /* make sure that we don't read/write beyond the provided buffer */
1596 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1598 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1599 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1602 /* make sure that we don't read/write beyond the provided buffer */
1603 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1605 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1606 lpOTM->otmpFaceName = 0; /* doesn't fit */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1612 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1613 lpOTM->otmpStyleName = 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1619 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1620 lpOTM->otmpFullName = 0; /* doesn't fit */
1624 end:
1625 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1626 HeapFree(GetProcessHeap(), 0, lpOTMW);
1628 return ret;
1632 /***********************************************************************
1633 * GetOutlineTextMetricsW [GDI32.@]
1635 UINT WINAPI GetOutlineTextMetricsW(
1636 HDC hdc, /* [in] Handle of device context */
1637 UINT cbData, /* [in] Size of metric data array */
1638 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1640 DC *dc = DC_GetDCPtr( hdc );
1641 OUTLINETEXTMETRICW *output = lpOTM;
1642 UINT ret;
1644 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1645 if(!dc) return 0;
1647 if(dc->gdiFont) {
1648 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1649 if(lpOTM && ret) {
1650 if(ret > cbData) {
1651 output = HeapAlloc(GetProcessHeap(), 0, ret);
1652 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1655 #define WDPTOLP(x) ((x<0)? \
1656 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1657 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1658 #define HDPTOLP(y) ((y<0)? \
1659 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1660 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1662 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1663 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1664 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1665 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1666 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1667 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1668 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1669 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1670 output->otmAscent = HDPTOLP(output->otmAscent);
1671 output->otmDescent = HDPTOLP(output->otmDescent);
1672 output->otmLineGap = HDPTOLP(output->otmLineGap);
1673 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1674 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1675 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1676 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1677 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1678 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1679 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1680 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1681 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1682 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1683 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1684 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1685 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1686 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1687 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1688 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1689 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1690 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1691 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1692 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1693 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1694 #undef WDPTOLP
1695 #undef HDPTOLP
1696 if(output != lpOTM) {
1697 memcpy(lpOTM, output, cbData);
1698 HeapFree(GetProcessHeap(), 0, output);
1699 ret = cbData;
1704 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1705 but really this should just be a return 0. */
1707 ret = sizeof(*lpOTM);
1708 if (lpOTM) {
1709 if(cbData < ret)
1710 ret = 0;
1711 else {
1712 memset(lpOTM, 0, ret);
1713 lpOTM->otmSize = sizeof(*lpOTM);
1714 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1716 Further fill of the structure not implemented,
1717 Needs real values for the structure members
1722 DC_ReleaseDCPtr(dc);
1723 return ret;
1727 /***********************************************************************
1728 * GetCharWidthW (GDI32.@)
1729 * GetCharWidth32W (GDI32.@)
1731 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1732 LPINT buffer )
1734 UINT i;
1735 BOOL ret = FALSE;
1736 DC * dc = DC_GetDCPtr( hdc );
1737 if (!dc) return FALSE;
1739 if (dc->gdiFont)
1740 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1741 else if (dc->funcs->pGetCharWidth)
1742 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1744 if (ret)
1746 /* convert device units to logical */
1747 for( i = firstChar; i <= lastChar; i++, buffer++ )
1748 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1749 ret = TRUE;
1751 DC_ReleaseDCPtr( dc );
1752 return ret;
1756 /***********************************************************************
1757 * GetCharWidthA (GDI32.@)
1758 * GetCharWidth32A (GDI32.@)
1760 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1761 LPINT buffer )
1763 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1764 LPSTR str;
1765 LPWSTR wstr;
1766 BOOL ret = TRUE;
1768 if(count <= 0) return FALSE;
1770 str = HeapAlloc(GetProcessHeap(), 0, count);
1771 for(i = 0; i < count; i++)
1772 str[i] = (BYTE)(firstChar + i);
1774 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1776 for(i = 0; i < wlen; i++)
1778 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1780 ret = FALSE;
1781 break;
1783 buffer++;
1786 HeapFree(GetProcessHeap(), 0, str);
1787 HeapFree(GetProcessHeap(), 0, wstr);
1789 return ret;
1793 /***********************************************************************
1794 * ExtTextOutA (GDI32.@)
1796 * See ExtTextOutW.
1798 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1799 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1801 INT wlen;
1802 UINT codepage;
1803 LPWSTR p;
1804 BOOL ret;
1805 LPINT lpDxW = NULL;
1807 if (flags & ETO_GLYPH_INDEX)
1808 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1810 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1812 if (lpDx) {
1813 unsigned int i = 0, j = 0;
1815 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1816 while(i < count) {
1817 if(IsDBCSLeadByteEx(codepage, str[i])) {
1818 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1819 i = i + 2;
1820 } else {
1821 lpDxW[j++] = lpDx[i];
1822 i = i + 1;
1827 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1829 HeapFree( GetProcessHeap(), 0, p );
1830 HeapFree( GetProcessHeap(), 0, lpDxW );
1831 return ret;
1835 /***********************************************************************
1836 * ExtTextOutW (GDI32.@)
1838 * Draws text using the currently selected font, background color, and text color.
1841 * PARAMS
1842 * x,y [I] coordinates of string
1843 * flags [I]
1844 * ETO_GRAYED - undocumented on MSDN
1845 * ETO_OPAQUE - use background color for fill the rectangle
1846 * ETO_CLIPPED - clipping text to the rectangle
1847 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1848 * than encoded characters. Implies ETO_IGNORELANGUAGE
1849 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1850 * Affects BiDi ordering
1851 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1852 * ETO_PDY - unimplemented
1853 * ETO_NUMERICSLATIN - unimplemented always assumed -
1854 * do not translate numbers into locale representations
1855 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1856 * lprect [I] dimensions for clipping or/and opaquing
1857 * str [I] text string
1858 * count [I] number of symbols in string
1859 * lpDx [I] optional parameter with distance between drawing characters
1861 * RETURNS
1862 * Success: TRUE
1863 * Failure: FALSE
1865 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1866 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1868 BOOL ret = FALSE;
1869 LPWSTR reordered_str = (LPWSTR)str;
1870 WORD *glyphs = NULL;
1871 UINT align = GetTextAlign( hdc );
1872 POINT pt;
1873 TEXTMETRICW tm;
1874 LOGFONTW lf;
1875 double cosEsc, sinEsc;
1876 INT *deltas = NULL, char_extra;
1877 SIZE sz;
1878 RECT rc;
1879 BOOL done_extents = FALSE;
1880 INT width = 0, xwidth = 0, ywidth = 0;
1881 DWORD type;
1882 DC * dc = get_dc_ptr( hdc );
1883 INT breakRem;
1885 if (!dc) return FALSE;
1887 breakRem = dc->breakRem;
1889 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1890 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1892 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1894 release_dc_ptr( dc );
1895 return ret;
1898 update_dc( dc );
1899 type = GetObjectType(hdc);
1900 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1902 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1903 release_dc_ptr( dc );
1904 return ret;
1907 if (!lprect)
1908 flags &= ~ETO_CLIPPED;
1910 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1912 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1914 BIDI_Reorder( str, count, GCP_REORDER,
1915 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1916 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1917 reordered_str, count, NULL );
1919 flags |= ETO_IGNORELANGUAGE;
1922 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1923 lprect, debugstr_wn(str, count), count, lpDx);
1925 if(flags & ETO_GLYPH_INDEX)
1926 glyphs = reordered_str;
1928 if(lprect)
1929 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1930 lprect->bottom);
1931 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1933 if(align & TA_UPDATECP)
1935 GetCurrentPositionEx( hdc, &pt );
1936 x = pt.x;
1937 y = pt.y;
1940 GetTextMetricsW(hdc, &tm);
1941 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1943 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1944 lf.lfEscapement = 0;
1946 if(lf.lfEscapement != 0)
1948 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1949 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1951 else
1953 cosEsc = 1;
1954 sinEsc = 0;
1957 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1959 if(!lprect)
1961 if(flags & ETO_GLYPH_INDEX)
1962 GetTextExtentPointI(hdc, glyphs, count, &sz);
1963 else
1964 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1966 done_extents = TRUE;
1967 rc.left = x;
1968 rc.top = y;
1969 rc.right = x + sz.cx;
1970 rc.bottom = y + sz.cy;
1972 else
1974 rc = *lprect;
1977 LPtoDP(hdc, (POINT*)&rc, 2);
1979 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1980 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1983 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1984 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1986 if(count == 0)
1988 ret = TRUE;
1989 goto done;
1992 pt.x = x;
1993 pt.y = y;
1994 LPtoDP(hdc, &pt, 1);
1995 x = pt.x;
1996 y = pt.y;
1998 char_extra = GetTextCharacterExtra(hdc);
1999 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2001 UINT i;
2002 SIZE tmpsz;
2003 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2004 for(i = 0; i < count; i++)
2006 if(lpDx && (flags & ETO_PDY))
2007 deltas[i] = lpDx[i*2] + char_extra;
2008 else if(lpDx)
2009 deltas[i] = lpDx[i] + char_extra;
2010 else
2012 if(flags & ETO_GLYPH_INDEX)
2013 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2014 else
2015 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2017 deltas[i] = tmpsz.cx;
2020 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2022 deltas[i] = deltas[i] + dc->breakExtra;
2023 if (breakRem > 0)
2025 breakRem--;
2026 deltas[i]++;
2029 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2030 width += deltas[i];
2033 else
2035 if(!done_extents)
2037 if(flags & ETO_GLYPH_INDEX)
2038 GetTextExtentPointI(hdc, glyphs, count, &sz);
2039 else
2040 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2041 done_extents = TRUE;
2043 width = INTERNAL_XWSTODS(dc, sz.cx);
2045 xwidth = width * cosEsc;
2046 ywidth = width * sinEsc;
2048 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2049 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2050 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2052 case TA_LEFT:
2053 if (align & TA_UPDATECP)
2055 pt.x = x + xwidth;
2056 pt.y = y - ywidth;
2057 DPtoLP(hdc, &pt, 1);
2058 MoveToEx(hdc, pt.x, pt.y, NULL);
2060 break;
2062 case TA_CENTER:
2063 x -= xwidth / 2;
2064 y += ywidth / 2;
2065 break;
2067 case TA_RIGHT:
2068 x -= xwidth;
2069 y += ywidth;
2070 if (align & TA_UPDATECP)
2072 pt.x = x;
2073 pt.y = y;
2074 DPtoLP(hdc, &pt, 1);
2075 MoveToEx(hdc, pt.x, pt.y, NULL);
2077 break;
2080 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2082 case TA_TOP:
2083 y += tm.tmAscent * cosEsc;
2084 x += tm.tmAscent * sinEsc;
2085 break;
2087 case TA_BOTTOM:
2088 y -= tm.tmDescent * cosEsc;
2089 x -= tm.tmDescent * sinEsc;
2090 break;
2092 case TA_BASELINE:
2093 break;
2096 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2098 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2100 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2101 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2103 RECT rc;
2104 rc.left = x;
2105 rc.right = x + width;
2106 rc.top = y - tm.tmAscent;
2107 rc.bottom = y + tm.tmDescent;
2108 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2113 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2115 HFONT orig_font = dc->hFont, cur_font;
2116 UINT glyph;
2117 INT span = 0, *offsets = NULL, i;
2119 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2120 for(i = 0; i < count; i++)
2122 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2123 if(cur_font != dc->hFont)
2125 if(!offsets)
2127 int j;
2128 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2129 offsets[0] = 0;
2130 if(!deltas)
2132 SIZE tmpsz;
2133 for(j = 1; j < count; j++)
2135 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2136 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2139 else
2141 for(j = 1; j < count; j++)
2142 offsets[j] = offsets[j-1] + deltas[j];
2145 if(span)
2147 if (PATH_IsPathOpen(dc->path))
2148 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2149 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2150 glyphs, span, deltas ? deltas + i - span : NULL);
2151 else
2152 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2153 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2154 glyphs, span, deltas ? deltas + i - span : NULL);
2155 span = 0;
2157 SelectObject(hdc, cur_font);
2159 glyphs[span++] = glyph;
2161 if(i == count - 1)
2163 if (PATH_IsPathOpen(dc->path))
2164 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2165 y - (offsets ? offsets[count - span] * sinEsc : 0),
2166 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2167 glyphs, span, deltas ? deltas + count - span : NULL);
2168 else
2169 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2170 y - (offsets ? offsets[count - span] * sinEsc : 0),
2171 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2172 glyphs, span, deltas ? deltas + count - span : NULL);
2173 SelectObject(hdc, orig_font);
2174 HeapFree(GetProcessHeap(), 0, offsets);
2178 else
2180 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2182 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2183 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2184 flags |= ETO_GLYPH_INDEX;
2187 if (PATH_IsPathOpen(dc->path))
2188 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2189 glyphs ? glyphs : reordered_str, count, deltas);
2190 else
2191 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2192 glyphs ? glyphs : reordered_str, count, deltas);
2195 done:
2196 HeapFree(GetProcessHeap(), 0, deltas);
2197 if(glyphs != reordered_str)
2198 HeapFree(GetProcessHeap(), 0, glyphs);
2199 if(reordered_str != str)
2200 HeapFree(GetProcessHeap(), 0, reordered_str);
2202 release_dc_ptr( dc );
2204 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2206 int underlinePos, strikeoutPos;
2207 int underlineWidth, strikeoutWidth;
2208 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2209 OUTLINETEXTMETRICW* otm = NULL;
2211 if(!size)
2213 underlinePos = 0;
2214 underlineWidth = tm.tmAscent / 20 + 1;
2215 strikeoutPos = tm.tmAscent / 2;
2216 strikeoutWidth = underlineWidth;
2218 else
2220 otm = HeapAlloc(GetProcessHeap(), 0, size);
2221 GetOutlineTextMetricsW(hdc, size, otm);
2222 underlinePos = otm->otmsUnderscorePosition;
2223 underlineWidth = otm->otmsUnderscoreSize;
2224 strikeoutPos = otm->otmsStrikeoutPosition;
2225 strikeoutWidth = otm->otmsStrikeoutSize;
2226 HeapFree(GetProcessHeap(), 0, otm);
2229 if (PATH_IsPathOpen(dc->path))
2231 POINT pts[5];
2232 HPEN hpen;
2233 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2235 hbrush = SelectObject(hdc, hbrush);
2236 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2238 if (lf.lfUnderline)
2240 pts[0].x = x - underlinePos * sinEsc;
2241 pts[0].y = y - underlinePos * cosEsc;
2242 pts[1].x = x + xwidth - underlinePos * sinEsc;
2243 pts[1].y = y - ywidth - underlinePos * cosEsc;
2244 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2245 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2246 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2247 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2248 pts[4].x = pts[0].x;
2249 pts[4].y = pts[0].y;
2250 DPtoLP(hdc, pts, 5);
2251 Polygon(hdc, pts, 5);
2254 if (lf.lfStrikeOut)
2256 pts[0].x = x - strikeoutPos * sinEsc;
2257 pts[0].y = y - strikeoutPos * cosEsc;
2258 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2259 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2260 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2261 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2262 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2263 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2264 pts[4].x = pts[0].x;
2265 pts[4].y = pts[0].y;
2266 DPtoLP(hdc, pts, 5);
2267 Polygon(hdc, pts, 5);
2270 SelectObject(hdc, hpen);
2271 hbrush = SelectObject(hdc, hbrush);
2272 DeleteObject(hbrush);
2274 else
2276 POINT pts[2], oldpt;
2277 HPEN hpen;
2279 if (lf.lfUnderline)
2281 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2282 hpen = SelectObject(hdc, hpen);
2283 pts[0].x = x;
2284 pts[0].y = y;
2285 pts[1].x = x + xwidth;
2286 pts[1].y = y - ywidth;
2287 DPtoLP(hdc, pts, 2);
2288 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2289 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2290 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2291 DeleteObject(SelectObject(hdc, hpen));
2294 if (lf.lfStrikeOut)
2296 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2297 hpen = SelectObject(hdc, hpen);
2298 pts[0].x = x;
2299 pts[0].y = y;
2300 pts[1].x = x + xwidth;
2301 pts[1].y = y - ywidth;
2302 DPtoLP(hdc, pts, 2);
2303 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2304 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2305 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2306 DeleteObject(SelectObject(hdc, hpen));
2311 return ret;
2315 /***********************************************************************
2316 * TextOutA (GDI32.@)
2318 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2320 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2324 /***********************************************************************
2325 * TextOutW (GDI32.@)
2327 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2329 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2333 /***********************************************************************
2334 * PolyTextOutA (GDI32.@)
2336 * See PolyTextOutW.
2338 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2340 for (; cStrings>0; cStrings--, pptxt++)
2341 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2342 return FALSE;
2343 return TRUE;
2348 /***********************************************************************
2349 * PolyTextOutW (GDI32.@)
2351 * Draw several Strings
2353 * RETURNS
2354 * TRUE: Success.
2355 * FALSE: Failure.
2357 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2359 for (; cStrings>0; cStrings--, pptxt++)
2360 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2361 return FALSE;
2362 return TRUE;
2366 /* FIXME: all following APIs ******************************************/
2369 /***********************************************************************
2370 * SetMapperFlags (GDI32.@)
2372 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2374 DC *dc = DC_GetDCPtr( hDC );
2375 DWORD ret = 0;
2376 if(!dc) return 0;
2377 if(dc->funcs->pSetMapperFlags)
2379 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2380 /* FIXME: ret is just a success flag, we should return a proper value */
2382 else
2383 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2384 DC_ReleaseDCPtr( dc );
2385 return ret;
2388 /***********************************************************************
2389 * GetAspectRatioFilterEx (GDI.486)
2391 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2393 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2394 return FALSE;
2397 /***********************************************************************
2398 * GetAspectRatioFilterEx (GDI32.@)
2400 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2402 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2403 return FALSE;
2407 /***********************************************************************
2408 * GetCharABCWidthsA (GDI32.@)
2410 * See GetCharABCWidthsW.
2412 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2413 LPABC abc )
2415 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2416 LPSTR str;
2417 LPWSTR wstr;
2418 BOOL ret = TRUE;
2420 if(count <= 0) return FALSE;
2422 str = HeapAlloc(GetProcessHeap(), 0, count);
2423 for(i = 0; i < count; i++)
2424 str[i] = (BYTE)(firstChar + i);
2426 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2428 for(i = 0; i < wlen; i++)
2430 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2432 ret = FALSE;
2433 break;
2435 abc++;
2438 HeapFree(GetProcessHeap(), 0, str);
2439 HeapFree(GetProcessHeap(), 0, wstr);
2441 return ret;
2445 /******************************************************************************
2446 * GetCharABCWidthsW [GDI32.@]
2448 * Retrieves widths of characters in range.
2450 * PARAMS
2451 * hdc [I] Handle of device context
2452 * firstChar [I] First character in range to query
2453 * lastChar [I] Last character in range to query
2454 * abc [O] Address of character-width structure
2456 * NOTES
2457 * Only works with TrueType fonts
2459 * RETURNS
2460 * Success: TRUE
2461 * Failure: FALSE
2463 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2464 LPABC abc )
2466 DC *dc = DC_GetDCPtr(hdc);
2467 unsigned int i;
2468 BOOL ret = FALSE;
2470 if (!dc) return FALSE;
2472 if(dc->gdiFont)
2473 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2474 else
2475 FIXME(": stub\n");
2477 if (ret)
2479 /* convert device units to logical */
2480 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2481 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2482 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2483 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2485 ret = TRUE;
2488 DC_ReleaseDCPtr( dc );
2489 return ret;
2493 /******************************************************************************
2494 * GetCharABCWidthsI [GDI32.@]
2496 * Retrieves widths of characters in range.
2498 * PARAMS
2499 * hdc [I] Handle of device context
2500 * firstChar [I] First glyphs in range to query
2501 * count [I] Last glyphs in range to query
2502 * pgi [i] Array of glyphs to query
2503 * abc [O] Address of character-width structure
2505 * NOTES
2506 * Only works with TrueType fonts
2508 * RETURNS
2509 * Success: TRUE
2510 * Failure: FALSE
2512 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2513 LPWORD pgi, LPABC abc)
2515 DC *dc = DC_GetDCPtr(hdc);
2516 unsigned int i;
2517 BOOL ret = FALSE;
2519 if (!dc) return FALSE;
2521 if(dc->gdiFont)
2522 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2523 else
2524 FIXME(": stub\n");
2526 if (ret)
2528 /* convert device units to logical */
2529 for( i = 0; i < count; i++, abc++ ) {
2530 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2531 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2532 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2534 ret = TRUE;
2537 DC_ReleaseDCPtr( dc );
2538 return ret;
2542 /***********************************************************************
2543 * GetGlyphOutlineA (GDI32.@)
2545 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2546 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2547 LPVOID lpBuffer, const MAT2 *lpmat2 )
2549 LPWSTR p = NULL;
2550 DWORD ret;
2551 UINT c;
2553 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2554 int len;
2555 char mbchs[2];
2556 if(uChar > 0xff) { /* but, 2 bytes character only */
2557 len = 2;
2558 mbchs[0] = (uChar & 0xff00) >> 8;
2559 mbchs[1] = (uChar & 0xff);
2560 } else {
2561 len = 1;
2562 mbchs[0] = (uChar & 0xff);
2564 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2565 c = p[0];
2566 } else
2567 c = uChar;
2568 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2569 lpmat2);
2570 HeapFree(GetProcessHeap(), 0, p);
2571 return ret;
2574 /***********************************************************************
2575 * GetGlyphOutlineW (GDI32.@)
2577 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2578 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2579 LPVOID lpBuffer, const MAT2 *lpmat2 )
2581 DC *dc = DC_GetDCPtr(hdc);
2582 DWORD ret;
2584 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2585 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2587 if(!dc) return GDI_ERROR;
2589 if(dc->gdiFont)
2590 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2591 cbBuffer, lpBuffer, lpmat2);
2592 else
2593 ret = GDI_ERROR;
2595 DC_ReleaseDCPtr( dc );
2596 return ret;
2600 /***********************************************************************
2601 * CreateScalableFontResourceA (GDI32.@)
2603 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2604 LPCSTR lpszResourceFile,
2605 LPCSTR lpszFontFile,
2606 LPCSTR lpszCurrentPath )
2608 HANDLE f;
2610 /* fHidden=1 - only visible for the calling app, read-only, not
2611 * enumbered with EnumFonts/EnumFontFamilies
2612 * lpszCurrentPath can be NULL
2614 FIXME("(%d,%s,%s,%s): stub\n",
2615 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2616 debugstr_a(lpszCurrentPath) );
2618 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2619 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2620 CloseHandle(f);
2621 SetLastError(ERROR_FILE_EXISTS);
2622 return FALSE;
2624 return FALSE; /* create failed */
2627 /***********************************************************************
2628 * CreateScalableFontResourceW (GDI32.@)
2630 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2631 LPCWSTR lpszResourceFile,
2632 LPCWSTR lpszFontFile,
2633 LPCWSTR lpszCurrentPath )
2635 FIXME("(%d,%p,%p,%p): stub\n",
2636 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2637 return FALSE; /* create failed */
2640 /*************************************************************************
2641 * GetKerningPairsA (GDI32.@)
2643 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2644 LPKERNINGPAIR kern_pairA )
2646 INT charset;
2647 CHARSETINFO csi;
2648 CPINFO cpi;
2649 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2650 KERNINGPAIR *kern_pairW;
2652 if (!cPairs && kern_pairA)
2654 SetLastError(ERROR_INVALID_PARAMETER);
2655 return 0;
2658 charset = GetTextCharset(hDC);
2659 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2661 FIXME("Can't find codepage for charset %d\n", charset);
2662 return 0;
2664 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2665 * to fail on an invalid character for CP_SYMBOL.
2667 cpi.DefaultChar[0] = 0;
2668 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2670 FIXME("Can't find codepage %u info\n", csi.ciACP);
2671 return 0;
2673 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2675 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2676 if (!total_kern_pairs) return 0;
2678 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2679 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2681 for (i = 0; i < total_kern_pairs; i++)
2683 char first, second;
2685 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2686 continue;
2688 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2689 continue;
2691 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2692 continue;
2694 if (kern_pairA)
2696 if (kern_pairs_copied >= cPairs) break;
2698 kern_pairA->wFirst = (BYTE)first;
2699 kern_pairA->wSecond = (BYTE)second;
2700 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2701 kern_pairA++;
2703 kern_pairs_copied++;
2706 HeapFree(GetProcessHeap(), 0, kern_pairW);
2708 return kern_pairs_copied;
2711 /*************************************************************************
2712 * GetKerningPairsW (GDI32.@)
2714 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2715 LPKERNINGPAIR lpKerningPairs )
2717 DC *dc;
2718 DWORD ret = 0;
2720 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2722 if (!cPairs && lpKerningPairs)
2724 SetLastError(ERROR_INVALID_PARAMETER);
2725 return 0;
2728 dc = DC_GetDCPtr(hDC);
2729 if (!dc) return 0;
2731 if (dc->gdiFont)
2732 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2734 DC_ReleaseDCPtr( dc );
2735 return ret;
2738 /*************************************************************************
2739 * TranslateCharsetInfo [GDI32.@]
2741 * Fills a CHARSETINFO structure for a character set, code page, or
2742 * font. This allows making the correspondance between different labelings
2743 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2744 * of the same encoding.
2746 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2747 * only one codepage should be set in *lpSrc.
2749 * RETURNS
2750 * TRUE on success, FALSE on failure.
2753 BOOL WINAPI TranslateCharsetInfo(
2754 LPDWORD lpSrc, /* [in]
2755 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2756 if flags == TCI_SRCCHARSET: a character set value
2757 if flags == TCI_SRCCODEPAGE: a code page value
2759 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2760 DWORD flags /* [in] determines interpretation of lpSrc */)
2762 int index = 0;
2763 switch (flags) {
2764 case TCI_SRCFONTSIG:
2765 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2766 break;
2767 case TCI_SRCCODEPAGE:
2768 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2769 break;
2770 case TCI_SRCCHARSET:
2771 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2772 break;
2773 default:
2774 return FALSE;
2776 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2777 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2778 return TRUE;
2781 /*************************************************************************
2782 * GetFontLanguageInfo (GDI32.@)
2784 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2786 FONTSIGNATURE fontsig;
2787 static const DWORD GCP_DBCS_MASK=0x003F0000,
2788 GCP_DIACRITIC_MASK=0x00000000,
2789 FLI_GLYPHS_MASK=0x00000000,
2790 GCP_GLYPHSHAPE_MASK=0x00000040,
2791 GCP_KASHIDA_MASK=0x00000000,
2792 GCP_LIGATE_MASK=0x00000000,
2793 GCP_USEKERNING_MASK=0x00000000,
2794 GCP_REORDER_MASK=0x00000060;
2796 DWORD result=0;
2798 GetTextCharsetInfo( hdc, &fontsig, 0 );
2799 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2801 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2802 result|=GCP_DBCS;
2804 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2805 result|=GCP_DIACRITIC;
2807 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2808 result|=FLI_GLYPHS;
2810 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2811 result|=GCP_GLYPHSHAPE;
2813 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2814 result|=GCP_KASHIDA;
2816 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2817 result|=GCP_LIGATE;
2819 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2820 result|=GCP_USEKERNING;
2822 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2823 if( GetTextAlign( hdc) & TA_RTLREADING )
2824 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2825 result|=GCP_REORDER;
2827 return result;
2831 /*************************************************************************
2832 * GetFontData [GDI32.@]
2834 * Retrieve data for TrueType font.
2836 * RETURNS
2838 * success: Number of bytes returned
2839 * failure: GDI_ERROR
2841 * NOTES
2843 * Calls SetLastError()
2846 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2847 LPVOID buffer, DWORD length)
2849 DC *dc = DC_GetDCPtr(hdc);
2850 DWORD ret = GDI_ERROR;
2852 if(!dc) return GDI_ERROR;
2854 if(dc->gdiFont)
2855 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2857 DC_ReleaseDCPtr( dc );
2858 return ret;
2861 /*************************************************************************
2862 * GetGlyphIndicesA [GDI32.@]
2864 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2865 LPWORD pgi, DWORD flags)
2867 DWORD ret;
2868 WCHAR *lpstrW;
2869 INT countW;
2871 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2872 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2874 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2875 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2876 HeapFree(GetProcessHeap(), 0, lpstrW);
2878 return ret;
2881 /*************************************************************************
2882 * GetGlyphIndicesW [GDI32.@]
2884 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2885 LPWORD pgi, DWORD flags)
2887 DC *dc = DC_GetDCPtr(hdc);
2888 DWORD ret = GDI_ERROR;
2890 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2891 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2893 if(!dc) return GDI_ERROR;
2895 if(dc->gdiFont)
2896 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2898 DC_ReleaseDCPtr( dc );
2899 return ret;
2902 /*************************************************************************
2903 * GetCharacterPlacementA [GDI32.@]
2905 * See GetCharacterPlacementW.
2907 * NOTES:
2908 * the web browser control of ie4 calls this with dwFlags=0
2910 DWORD WINAPI
2911 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2912 INT nMaxExtent, GCP_RESULTSA *lpResults,
2913 DWORD dwFlags)
2915 WCHAR *lpStringW;
2916 INT uCountW;
2917 GCP_RESULTSW resultsW;
2918 DWORD ret;
2919 UINT font_cp;
2921 TRACE("%s, %d, %d, 0x%08x\n",
2922 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2924 /* both structs are equal in size */
2925 memcpy(&resultsW, lpResults, sizeof(resultsW));
2927 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2928 if(lpResults->lpOutString)
2929 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2931 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2933 lpResults->nGlyphs = resultsW.nGlyphs;
2934 lpResults->nMaxFit = resultsW.nMaxFit;
2936 if(lpResults->lpOutString) {
2937 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2938 lpResults->lpOutString, uCount, NULL, NULL );
2941 HeapFree(GetProcessHeap(), 0, lpStringW);
2942 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2944 return ret;
2947 /*************************************************************************
2948 * GetCharacterPlacementW [GDI32.@]
2950 * Retrieve information about a string. This includes the width, reordering,
2951 * Glyphing and so on.
2953 * RETURNS
2955 * The width and height of the string if successful, 0 if failed.
2957 * BUGS
2959 * All flags except GCP_REORDER are not yet implemented.
2960 * Reordering is not 100% complient to the Windows BiDi method.
2961 * Caret positioning is not yet implemented for BiDi.
2962 * Classes are not yet implemented.
2965 DWORD WINAPI
2966 GetCharacterPlacementW(
2967 HDC hdc, /* [in] Device context for which the rendering is to be done */
2968 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2969 INT uCount, /* [in] Number of WORDS in string. */
2970 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2971 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2972 DWORD dwFlags /* [in] Flags specifying how to process the string */
2975 DWORD ret=0;
2976 SIZE size;
2977 UINT i, nSet;
2979 TRACE("%s, %d, %d, 0x%08x\n",
2980 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2982 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2983 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2984 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2985 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2986 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2988 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2989 if(lpResults->lpClass) FIXME("classes not implemented\n");
2990 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2991 FIXME("Caret positions for complex scripts not implemented\n");
2993 nSet = (UINT)uCount;
2994 if(nSet > lpResults->nGlyphs)
2995 nSet = lpResults->nGlyphs;
2997 /* return number of initialized fields */
2998 lpResults->nGlyphs = nSet;
3000 if((dwFlags&GCP_REORDER)==0 )
3002 /* Treat the case where no special handling was requested in a fastpath way */
3003 /* copy will do if the GCP_REORDER flag is not set */
3004 if(lpResults->lpOutString)
3005 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3007 if(lpResults->lpOrder)
3009 for(i = 0; i < nSet; i++)
3010 lpResults->lpOrder[i] = i;
3012 } else
3014 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3015 nSet, lpResults->lpOrder );
3018 /* FIXME: Will use the placement chars */
3019 if (lpResults->lpDx)
3021 int c;
3022 for (i = 0; i < nSet; i++)
3024 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3025 lpResults->lpDx[i]= c;
3029 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3031 int pos = 0;
3033 lpResults->lpCaretPos[0] = 0;
3034 for (i = 1; i < nSet; i++)
3035 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3036 lpResults->lpCaretPos[i] = (pos += size.cx);
3039 if(lpResults->lpGlyphs)
3040 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3042 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3043 ret = MAKELONG(size.cx, size.cy);
3045 return ret;
3048 /*************************************************************************
3049 * GetCharABCWidthsFloatA [GDI32.@]
3051 * See GetCharABCWidthsFloatW.
3053 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3055 INT i, wlen, count = (INT)(last - first + 1);
3056 LPSTR str;
3057 LPWSTR wstr;
3058 BOOL ret = TRUE;
3060 if (count <= 0) return FALSE;
3062 str = HeapAlloc(GetProcessHeap(), 0, count);
3064 for(i = 0; i < count; i++)
3065 str[i] = (BYTE)(first + i);
3067 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3069 for (i = 0; i < wlen; i++)
3071 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3073 ret = FALSE;
3074 break;
3076 abcf++;
3079 HeapFree( GetProcessHeap(), 0, str );
3080 HeapFree( GetProcessHeap(), 0, wstr );
3082 return ret;
3085 /*************************************************************************
3086 * GetCharABCWidthsFloatW [GDI32.@]
3088 * Retrieves widths of a range of characters.
3090 * PARAMS
3091 * hdc [I] Handle to device context.
3092 * first [I] First character in range to query.
3093 * last [I] Last character in range to query.
3094 * abcf [O] Array of LPABCFLOAT structures.
3096 * RETURNS
3097 * Success: TRUE
3098 * Failure: FALSE
3100 * BUGS
3101 * Only works with TrueType fonts. It also doesn't return real
3102 * floats but converted integers because it's implemented on
3103 * top of GetCharABCWidthsW.
3105 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3107 ABC *abc;
3108 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3109 BOOL ret;
3111 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3113 abc = HeapAlloc( GetProcessHeap(), 0, size );
3114 if (!abc) return FALSE;
3116 ret = GetCharABCWidthsW( hdc, first, last, abc );
3117 if (ret)
3119 for (i = first; i <= last; i++, abc++, abcf++)
3121 abcf->abcfA = abc->abcA;
3122 abcf->abcfB = abc->abcB;
3123 abcf->abcfC = abc->abcC;
3126 HeapFree( GetProcessHeap(), 0, abc );
3127 return ret;
3130 /*************************************************************************
3131 * GetCharWidthFloatA [GDI32.@]
3133 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3134 UINT iLastChar, PFLOAT pxBuffer)
3136 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3137 return 0;
3140 /*************************************************************************
3141 * GetCharWidthFloatW [GDI32.@]
3143 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3144 UINT iLastChar, PFLOAT pxBuffer)
3146 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3147 return 0;
3151 /***********************************************************************
3153 * Font Resource API *
3155 ***********************************************************************/
3157 /***********************************************************************
3158 * AddFontResourceA (GDI32.@)
3160 INT WINAPI AddFontResourceA( LPCSTR str )
3162 return AddFontResourceExA( str, 0, NULL);
3165 /***********************************************************************
3166 * AddFontResourceW (GDI32.@)
3168 INT WINAPI AddFontResourceW( LPCWSTR str )
3170 return AddFontResourceExW(str, 0, NULL);
3174 /***********************************************************************
3175 * AddFontResourceExA (GDI32.@)
3177 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3179 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3180 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3181 INT ret;
3183 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3184 ret = AddFontResourceExW(strW, fl, pdv);
3185 HeapFree(GetProcessHeap(), 0, strW);
3186 return ret;
3189 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3191 HRSRC rsrc = FindResourceW(hModule, name, type);
3192 HGLOBAL hMem = LoadResource(hModule, rsrc);
3193 LPVOID *pMem = LockResource(hMem);
3194 int *num_total = (int *)lParam;
3195 DWORD num_in_res;
3197 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3198 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3200 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3201 return FALSE;
3204 *num_total += num_in_res;
3205 return TRUE;
3208 /***********************************************************************
3209 * AddFontResourceExW (GDI32.@)
3211 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3213 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3214 if (ret == 0)
3216 /* Freetype <2.3.5 have problems reading resources wrapped in PE files. */
3217 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3218 if (hModule != NULL)
3220 int num_resources = 0;
3221 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3223 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manualy\n",
3224 wine_dbgstr_w(str));
3225 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3226 ret = num_resources;
3227 FreeLibrary(hModule);
3230 return ret;
3233 /***********************************************************************
3234 * RemoveFontResourceA (GDI32.@)
3236 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3238 return RemoveFontResourceExA(str, 0, 0);
3241 /***********************************************************************
3242 * RemoveFontResourceW (GDI32.@)
3244 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3246 return RemoveFontResourceExW(str, 0, 0);
3249 /***********************************************************************
3250 * AddFontMemResourceEx (GDI32.@)
3252 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3254 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3257 /***********************************************************************
3258 * RemoveFontResourceExA (GDI32.@)
3260 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3262 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3263 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3264 INT ret;
3266 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3267 ret = RemoveFontResourceExW(strW, fl, pdv);
3268 HeapFree(GetProcessHeap(), 0, strW);
3269 return ret;
3272 /***********************************************************************
3273 * RemoveFontResourceExW (GDI32.@)
3275 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3277 return WineEngRemoveFontResourceEx(str, fl, pdv);
3280 /***********************************************************************
3281 * GetTextCharset (GDI32.@)
3283 UINT WINAPI GetTextCharset(HDC hdc)
3285 /* MSDN docs say this is equivalent */
3286 return GetTextCharsetInfo(hdc, NULL, 0);
3289 /***********************************************************************
3290 * GetTextCharsetInfo (GDI32.@)
3292 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3294 UINT ret = DEFAULT_CHARSET;
3295 DC *dc = DC_GetDCPtr(hdc);
3297 if (dc)
3299 if (dc->gdiFont)
3300 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3302 DC_ReleaseDCPtr( dc );
3305 if (ret == DEFAULT_CHARSET && fs)
3306 memset(fs, 0, sizeof(FONTSIGNATURE));
3307 return ret;
3310 /***********************************************************************
3311 * GdiGetCharDimensions (GDI32.@)
3313 * Gets the average width of the characters in the English alphabet.
3315 * PARAMS
3316 * hdc [I] Handle to the device context to measure on.
3317 * lptm [O] Pointer to memory to store the text metrics into.
3318 * height [O] On exit, the maximum height of characters in the English alphabet.
3320 * RETURNS
3321 * The average width of characters in the English alphabet.
3323 * NOTES
3324 * This function is used by the dialog manager to get the size of a dialog
3325 * unit. It should also be used by other pieces of code that need to know
3326 * the size of a dialog unit in logical units without having access to the
3327 * window handle of the dialog.
3328 * Windows caches the font metrics from this function, but we don't and
3329 * there doesn't appear to be an immediate advantage to do so.
3331 * SEE ALSO
3332 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3334 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3336 SIZE sz;
3337 static const WCHAR alphabet[] = {
3338 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3339 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3340 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3342 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3344 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3346 if (height) *height = sz.cy;
3347 return (sz.cx / 26 + 1) / 2;
3350 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3352 FIXME("(%d): stub\n", fEnableEUDC);
3353 return FALSE;
3356 /***********************************************************************
3357 * GetCharWidthI (GDI32.@)
3359 * Retrieve widths of characters.
3361 * PARAMS
3362 * hdc [I] Handle to a device context.
3363 * first [I] First glyph in range to query.
3364 * count [I] Number of glyph indices to query.
3365 * glyphs [I] Array of glyphs to query.
3366 * buffer [O] Buffer to receive character widths.
3368 * NOTES
3369 * Only works with TrueType fonts.
3371 * RETURNS
3372 * Success: TRUE
3373 * Failure: FALSE
3375 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3377 ABC *abc;
3378 unsigned int i;
3380 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3382 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3383 return FALSE;
3385 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3387 HeapFree(GetProcessHeap(), 0, abc);
3388 return FALSE;
3391 for (i = 0; i < count; i++)
3392 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3394 HeapFree(GetProcessHeap(), 0, abc);
3395 return TRUE;
3398 /***********************************************************************
3399 * GetFontUnicodeRanges (GDI32.@)
3401 * Retrieve a list of supported Unicode characters in a font.
3403 * PARAMS
3404 * hdc [I] Handle to a device context.
3405 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3407 * RETURNS
3408 * Success: Number of bytes written to the buffer pointed to by lpgs.
3409 * Failure: 0
3412 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3414 DWORD ret = 0;
3415 DC *dc = DC_GetDCPtr(hdc);
3417 TRACE("(%p, %p)\n", hdc, lpgs);
3419 if (!dc) return 0;
3421 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3422 DC_ReleaseDCPtr(dc);
3423 return ret;
3427 /*************************************************************
3428 * FontIsLinked (GDI32.@)
3430 BOOL WINAPI FontIsLinked(HDC hdc)
3432 DC *dc = DC_GetDCPtr(hdc);
3433 BOOL ret = FALSE;
3435 if (!dc) return FALSE;
3436 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3437 DC_ReleaseDCPtr(dc);
3438 TRACE("returning %d\n", ret);
3439 return ret;