spoolss: Add stubs for SpoolerHasInitialized and SpoolerInit.
[wine/gsoc_dplay.git] / dlls / gdi32 / font.c
blob1c8f7da2bc8bb3aec33f3650c0e72b09ec0897af
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, 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) return 0;
437 FONT_LogFontAToW( plfA, &lfW );
438 return CreateFontIndirectW( &lfW );
441 /***********************************************************************
442 * CreateFontIndirectW (GDI32.@)
444 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
446 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
447 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
448 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
449 WCHAR *pFaceNameSuffix = NULL;
450 HFONT hFont;
451 FONTOBJ *fontPtr;
453 if (!plf) return 0;
455 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
456 &font_funcs ))) return 0;
458 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
460 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
461 plf->lfHeight, plf->lfWidth,
462 plf->lfEscapement, plf->lfOrientation,
463 plf->lfPitchAndFamily,
464 plf->lfOutPrecision, plf->lfClipPrecision,
465 plf->lfQuality, plf->lfCharSet,
466 debugstr_w(plf->lfFaceName),
467 plf->lfWeight > 400 ? "Bold" : "",
468 plf->lfItalic ? "Italic" : "",
469 plf->lfUnderline ? "Underline" : "", hFont);
471 if (plf->lfEscapement != plf->lfOrientation)
473 /* this should really depend on whether GM_ADVANCED is set */
474 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
475 WARN("orientation angle %f set to "
476 "escapement angle %f for new font %p\n",
477 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
480 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
481 if (pFaceNameItalicSuffix)
483 fontPtr->logfont.lfItalic = TRUE;
484 pFaceNameSuffix = pFaceNameItalicSuffix;
487 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
488 if (pFaceNameBoldSuffix)
490 if (fontPtr->logfont.lfWeight < FW_BOLD)
491 fontPtr->logfont.lfWeight = FW_BOLD;
492 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
493 pFaceNameSuffix = pFaceNameBoldSuffix;
496 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
498 GDI_ReleaseObj( hFont );
499 return hFont;
502 /*************************************************************************
503 * CreateFontA (GDI32.@)
505 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
506 INT orient, INT weight, DWORD italic,
507 DWORD underline, DWORD strikeout, DWORD charset,
508 DWORD outpres, DWORD clippres, DWORD quality,
509 DWORD pitch, LPCSTR name )
511 LOGFONTA logfont;
513 logfont.lfHeight = height;
514 logfont.lfWidth = width;
515 logfont.lfEscapement = esc;
516 logfont.lfOrientation = orient;
517 logfont.lfWeight = weight;
518 logfont.lfItalic = italic;
519 logfont.lfUnderline = underline;
520 logfont.lfStrikeOut = strikeout;
521 logfont.lfCharSet = charset;
522 logfont.lfOutPrecision = outpres;
523 logfont.lfClipPrecision = clippres;
524 logfont.lfQuality = quality;
525 logfont.lfPitchAndFamily = pitch;
527 if (name)
528 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
529 else
530 logfont.lfFaceName[0] = '\0';
532 return CreateFontIndirectA( &logfont );
535 /*************************************************************************
536 * CreateFontW (GDI32.@)
538 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
539 INT orient, INT weight, DWORD italic,
540 DWORD underline, DWORD strikeout, DWORD charset,
541 DWORD outpres, DWORD clippres, DWORD quality,
542 DWORD pitch, LPCWSTR name )
544 LOGFONTW logfont;
546 logfont.lfHeight = height;
547 logfont.lfWidth = width;
548 logfont.lfEscapement = esc;
549 logfont.lfOrientation = orient;
550 logfont.lfWeight = weight;
551 logfont.lfItalic = italic;
552 logfont.lfUnderline = underline;
553 logfont.lfStrikeOut = strikeout;
554 logfont.lfCharSet = charset;
555 logfont.lfOutPrecision = outpres;
556 logfont.lfClipPrecision = clippres;
557 logfont.lfQuality = quality;
558 logfont.lfPitchAndFamily = pitch;
560 if (name)
561 lstrcpynW(logfont.lfFaceName, name,
562 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
563 else
564 logfont.lfFaceName[0] = '\0';
566 return CreateFontIndirectW( &logfont );
570 /***********************************************************************
571 * FONT_SelectObject
573 * If the driver supports vector fonts we create a gdi font first and
574 * then call the driver to give it a chance to supply its own device
575 * font. If the driver wants to do this it returns TRUE and we can
576 * delete the gdi font, if the driver wants to use the gdi font it
577 * should return FALSE, to signal an error return GDI_ERROR. For
578 * drivers that don't support vector fonts they must supply their own
579 * font.
581 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
583 HGDIOBJ ret = 0;
584 DC *dc = get_dc_ptr( hdc );
586 if (!dc) return 0;
588 if (!GDI_inc_ref_count( handle ))
590 release_dc_ptr( dc );
591 return 0;
594 if (dc->hFont != handle || dc->gdiFont == NULL)
596 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
598 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
599 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
600 if (font) GDI_ReleaseObj( handle );
604 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
606 if (ret && dc->gdiFont) dc->gdiFont = 0;
608 if (ret == HGDI_ERROR)
610 GDI_dec_ref_count( handle );
611 ret = 0; /* SelectObject returns 0 on error */
613 else
615 ret = dc->hFont;
616 dc->hFont = handle;
617 GDI_dec_ref_count( ret );
619 release_dc_ptr( dc );
620 return ret;
624 /***********************************************************************
625 * FONT_GetObject16
627 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
629 FONTOBJ *font = obj;
630 LOGFONT16 lf16;
632 FONT_LogFontWTo16( &font->logfont, &lf16 );
634 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
635 memcpy( buffer, &lf16, count );
636 return count;
639 /***********************************************************************
640 * FONT_GetObjectA
642 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
644 FONTOBJ *font = obj;
645 LOGFONTA lfA;
647 if(!buffer)
648 return sizeof(lfA);
649 FONT_LogFontWToA( &font->logfont, &lfA );
651 if (count > sizeof(lfA)) count = sizeof(lfA);
652 memcpy( buffer, &lfA, count );
653 return count;
656 /***********************************************************************
657 * FONT_GetObjectW
659 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
661 FONTOBJ *font = obj;
662 if(!buffer)
663 return sizeof(LOGFONTW);
664 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
665 memcpy( buffer, &font->logfont, count );
666 return count;
670 /***********************************************************************
671 * FONT_DeleteObject
673 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
675 WineEngDestroyFontInstance( handle );
676 return GDI_FreeObject( handle, obj );
680 /***********************************************************************
681 * FONT_EnumInstance16
683 * Called by the device driver layer to pass font info
684 * down to the application.
686 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
687 * We have to use other types because of the FONTENUMPROCW definition.
689 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
690 DWORD fType, LPARAM lp )
692 fontEnum16 *pfe = (fontEnum16*)lp;
693 INT ret = 1;
694 DC *dc;
696 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
697 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
699 WORD args[7];
700 DWORD result;
702 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
703 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
704 pfe->dwFlags |= ENUM_CALLED;
705 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
707 args[6] = SELECTOROF(pfe->segLogFont);
708 args[5] = OFFSETOF(pfe->segLogFont);
709 args[4] = SELECTOROF(pfe->segTextMetric);
710 args[3] = OFFSETOF(pfe->segTextMetric);
711 args[2] = fType;
712 args[1] = HIWORD(pfe->lpData);
713 args[0] = LOWORD(pfe->lpData);
714 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
715 ret = LOWORD(result);
717 /* get the lock again and make sure the DC is still valid */
718 dc = DC_GetDCPtr( pfe->hdc );
719 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
721 if (dc) DC_ReleaseDCPtr( dc );
722 pfe->hdc = 0; /* make sure we don't try to release it later on */
723 pfe->dc = NULL;
724 ret = 0;
727 return ret;
730 /***********************************************************************
731 * FONT_EnumInstance
733 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
734 * We have to use other types because of the FONTENUMPROCW definition.
736 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
737 DWORD fType, LPARAM lp )
739 fontEnum32 *pfe = (fontEnum32*)lp;
740 INT ret = 1;
741 DC *dc;
743 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
744 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
745 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
746 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
748 /* convert font metrics */
749 ENUMLOGFONTEXA logfont;
750 NEWTEXTMETRICEXA tmA;
752 pfe->dwFlags |= ENUM_CALLED;
753 if (!(pfe->dwFlags & ENUM_UNICODE))
755 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
756 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
757 plf = (LOGFONTW *)&logfont.elfLogFont;
758 ptm = (TEXTMETRICW *)&tmA;
760 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
762 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
764 /* get the lock again and make sure the DC is still valid */
765 dc = DC_GetDCPtr( pfe->hdc );
766 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
768 if (dc) DC_ReleaseDCPtr( dc );
769 pfe->hdc = 0; /* make sure we don't try to release it later on */
770 pfe->dc = NULL;
771 ret = 0;
774 return ret;
777 /***********************************************************************
778 * EnumFontFamiliesEx (GDI.613)
780 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
781 FONTENUMPROC16 efproc, LPARAM lParam,
782 DWORD dwFlags)
784 fontEnum16 fe16;
785 INT16 ret = 1, ret2;
786 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
787 NEWTEXTMETRICEX16 tm16;
788 ENUMLOGFONTEX16 lf16;
789 LOGFONTW lfW;
790 BOOL enum_gdi_fonts;
792 if (!dc) return 0;
793 FONT_LogFont16ToW(plf, &lfW);
795 fe16.hdc = HDC_32(hDC);
796 fe16.dc = dc;
797 fe16.physDev = dc->physDev;
798 fe16.lpLogFontParam = plf;
799 fe16.lpEnumFunc = efproc;
800 fe16.lpData = lParam;
801 fe16.lpTextMetric = &tm16;
802 fe16.lpLogFont = &lf16;
803 fe16.segTextMetric = MapLS( &tm16 );
804 fe16.segLogFont = MapLS( &lf16 );
805 fe16.dwFlags = 0;
807 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
809 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
811 ret = 0;
812 goto done;
815 if (enum_gdi_fonts)
816 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
817 fe16.dwFlags &= ~ENUM_CALLED;
818 if (ret && dc->funcs->pEnumDeviceFonts) {
819 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
820 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
821 ret = ret2;
823 done:
824 UnMapLS( fe16.segTextMetric );
825 UnMapLS( fe16.segLogFont );
826 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
827 return ret;
830 /***********************************************************************
831 * FONT_EnumFontFamiliesEx
833 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
834 FONTENUMPROCW efproc,
835 LPARAM lParam, DWORD dwUnicode)
837 INT ret = 1, ret2;
838 DC *dc = DC_GetDCPtr( hDC );
839 fontEnum32 fe32;
840 BOOL enum_gdi_fonts;
842 if (!dc) return 0;
844 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
845 plf->lfCharSet);
846 fe32.lpLogFontParam = plf;
847 fe32.lpEnumFunc = efproc;
848 fe32.lpData = lParam;
849 fe32.dwFlags = dwUnicode;
850 fe32.hdc = hDC;
851 fe32.dc = dc;
852 fe32.physDev = dc->physDev;
854 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
856 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
858 ret = 0;
859 goto done;
862 if (enum_gdi_fonts)
863 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
864 fe32.dwFlags &= ~ENUM_CALLED;
865 if (ret && dc->funcs->pEnumDeviceFonts) {
866 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
867 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
868 ret = ret2;
870 done:
871 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
872 return ret;
875 /***********************************************************************
876 * EnumFontFamiliesExW (GDI32.@)
878 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
879 FONTENUMPROCW efproc,
880 LPARAM lParam, DWORD dwFlags )
882 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
885 /***********************************************************************
886 * EnumFontFamiliesExA (GDI32.@)
888 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
889 FONTENUMPROCA efproc,
890 LPARAM lParam, DWORD dwFlags)
892 LOGFONTW lfW;
893 FONT_LogFontAToW( plf, &lfW );
895 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
898 /***********************************************************************
899 * EnumFontFamilies (GDI.330)
901 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
902 FONTENUMPROC16 efproc, LPARAM lpData )
904 LOGFONT16 lf;
906 lf.lfCharSet = DEFAULT_CHARSET;
907 if (lpFamily)
909 if (!*lpFamily) return 1;
910 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
912 else lf.lfFaceName[0] = '\0';
914 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
917 /***********************************************************************
918 * EnumFontFamiliesA (GDI32.@)
920 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
921 FONTENUMPROCA efproc, LPARAM lpData )
923 LOGFONTA lf;
925 lf.lfCharSet = DEFAULT_CHARSET;
926 if (lpFamily)
928 if (!*lpFamily) return 1;
929 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
931 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
933 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
936 /***********************************************************************
937 * EnumFontFamiliesW (GDI32.@)
939 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
940 FONTENUMPROCW efproc, LPARAM lpData )
942 LOGFONTW lf;
944 lf.lfCharSet = DEFAULT_CHARSET;
945 if (lpFamily)
947 if (!*lpFamily) return 1;
948 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
950 else lf.lfFaceName[0] = 0;
952 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
955 /***********************************************************************
956 * EnumFonts (GDI.70)
958 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
959 LPARAM lpData )
961 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
964 /***********************************************************************
965 * EnumFontsA (GDI32.@)
967 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
968 LPARAM lpData )
970 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
973 /***********************************************************************
974 * EnumFontsW (GDI32.@)
976 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
977 LPARAM lpData )
979 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
983 /***********************************************************************
984 * GetTextCharacterExtra (GDI32.@)
986 INT WINAPI GetTextCharacterExtra( HDC hdc )
988 INT ret;
989 DC *dc = DC_GetDCPtr( hdc );
990 if (!dc) return 0x80000000;
991 ret = dc->charExtra;
992 DC_ReleaseDCPtr( dc );
993 return ret;
997 /***********************************************************************
998 * SetTextCharacterExtra (GDI32.@)
1000 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1002 INT prev;
1003 DC * dc = DC_GetDCPtr( hdc );
1004 if (!dc) return 0x80000000;
1005 if (dc->funcs->pSetTextCharacterExtra)
1006 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1007 else
1009 prev = dc->charExtra;
1010 dc->charExtra = extra;
1012 DC_ReleaseDCPtr( dc );
1013 return prev;
1017 /***********************************************************************
1018 * SetTextJustification (GDI32.@)
1020 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1022 BOOL ret = TRUE;
1023 DC * dc = DC_GetDCPtr( hdc );
1024 if (!dc) return FALSE;
1025 if (dc->funcs->pSetTextJustification)
1026 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1027 else
1029 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1030 if (!extra) breaks = 0;
1031 if (breaks)
1033 dc->breakExtra = extra / breaks;
1034 dc->breakRem = extra - (breaks * dc->breakExtra);
1036 else
1038 dc->breakExtra = 0;
1039 dc->breakRem = 0;
1042 DC_ReleaseDCPtr( dc );
1043 return ret;
1047 /***********************************************************************
1048 * GetTextFaceA (GDI32.@)
1050 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1052 INT res = GetTextFaceW(hdc, 0, NULL);
1053 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1054 GetTextFaceW( hdc, res, nameW );
1056 if (name)
1058 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1059 name[count-1] = 0;
1060 res = strlen(name);
1062 else
1063 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1064 HeapFree( GetProcessHeap(), 0, nameW );
1065 return res;
1068 /***********************************************************************
1069 * GetTextFaceW (GDI32.@)
1071 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1073 FONTOBJ *font;
1074 INT ret = 0;
1076 DC * dc = DC_GetDCPtr( hdc );
1077 if (!dc) return 0;
1079 if(dc->gdiFont)
1080 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1081 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1083 if (name)
1085 lstrcpynW( name, font->logfont.lfFaceName, count );
1086 ret = strlenW(name);
1088 else ret = strlenW(font->logfont.lfFaceName) + 1;
1089 GDI_ReleaseObj( dc->hFont );
1091 DC_ReleaseDCPtr( dc );
1092 return ret;
1096 /***********************************************************************
1097 * GetTextExtentPoint32A (GDI32.@)
1099 * See GetTextExtentPoint32W.
1101 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1102 LPSIZE size )
1104 BOOL ret = FALSE;
1105 INT wlen;
1106 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1108 if (p) {
1109 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1110 HeapFree( GetProcessHeap(), 0, p );
1113 TRACE("(%p %s %d %p): returning %d x %d\n",
1114 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1115 return ret;
1119 /***********************************************************************
1120 * GetTextExtentPoint32W [GDI32.@]
1122 * Computes width/height for a string.
1124 * Computes width and height of the specified string.
1126 * RETURNS
1127 * Success: TRUE
1128 * Failure: FALSE
1130 BOOL WINAPI GetTextExtentPoint32W(
1131 HDC hdc, /* [in] Handle of device context */
1132 LPCWSTR str, /* [in] Address of text string */
1133 INT count, /* [in] Number of characters in string */
1134 LPSIZE size) /* [out] Address of structure for string size */
1136 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1139 /***********************************************************************
1140 * GetTextExtentExPointI [GDI32.@]
1142 * Computes width and height of the array of glyph indices.
1144 * PARAMS
1145 * hdc [I] Handle of device context.
1146 * indices [I] Glyph index array.
1147 * count [I] Number of glyphs in array.
1148 * max_ext [I] Maximum width in glyphs.
1149 * nfit [O] Maximum number of characters.
1150 * dxs [O] Partial string widths.
1151 * size [O] Returned string size.
1153 * RETURNS
1154 * Success: TRUE
1155 * Failure: FALSE
1157 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1158 LPINT nfit, LPINT dxs, LPSIZE size )
1160 BOOL ret = FALSE;
1161 DC * dc = DC_GetDCPtr( hdc );
1162 if (!dc) return FALSE;
1164 if(dc->gdiFont) {
1165 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
1166 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1167 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1168 size->cx += count * dc->charExtra;
1170 else if(dc->funcs->pGetTextExtentExPoint) {
1171 FIXME("calling GetTextExtentExPoint\n");
1172 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1173 count, max_ext, nfit, dxs, size );
1176 DC_ReleaseDCPtr( dc );
1178 TRACE("(%p %p %d %p): returning %d x %d\n",
1179 hdc, indices, count, size, size->cx, size->cy );
1180 return ret;
1183 /***********************************************************************
1184 * GetTextExtentPointI [GDI32.@]
1186 * Computes width and height of the array of glyph indices.
1188 * PARAMS
1189 * hdc [I] Handle of device context.
1190 * indices [I] Glyph index array.
1191 * count [I] Number of glyphs in array.
1192 * size [O] Returned string size.
1194 * RETURNS
1195 * Success: TRUE
1196 * Failure: FALSE
1198 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1200 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1204 /***********************************************************************
1205 * GetTextExtentPointA (GDI32.@)
1207 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1208 LPSIZE size )
1210 TRACE("not bug compatible.\n");
1211 return GetTextExtentPoint32A( hdc, str, count, size );
1214 /***********************************************************************
1215 * GetTextExtentPointW (GDI32.@)
1217 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1218 LPSIZE size )
1220 TRACE("not bug compatible.\n");
1221 return GetTextExtentPoint32W( hdc, str, count, size );
1225 /***********************************************************************
1226 * GetTextExtentExPointA (GDI32.@)
1228 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1229 INT maxExt, LPINT lpnFit,
1230 LPINT alpDx, LPSIZE size )
1232 BOOL ret;
1233 INT wlen;
1234 INT *walpDx = NULL;
1235 LPWSTR p = NULL;
1237 if (alpDx &&
1238 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1239 return FALSE;
1241 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1242 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1243 if (walpDx)
1245 INT n = lpnFit ? *lpnFit : wlen;
1246 INT i, j;
1247 for(i = 0, j = 0; i < n; i++, j++)
1249 alpDx[j] = walpDx[i];
1250 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1253 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1254 HeapFree( GetProcessHeap(), 0, p );
1255 HeapFree( GetProcessHeap(), 0, walpDx );
1256 return ret;
1260 /***********************************************************************
1261 * GetTextExtentExPointW (GDI32.@)
1263 * Return the size of the string as it would be if it was output properly by
1264 * e.g. TextOut.
1266 * This should include
1267 * - Intercharacter spacing
1268 * - justification spacing (not yet done)
1269 * - kerning? see below
1271 * Kerning. Since kerning would be carried out by the rendering code it should
1272 * be done by the driver. However they don't support it yet. Also I am not
1273 * yet persuaded that (certainly under Win95) any kerning is actually done.
1275 * str: According to MSDN this should be null-terminated. That is not true; a
1276 * null will not terminate it early.
1277 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1278 * than count. I have seen it be either the size of the full string or
1279 * 1 less than the size of the full string. I have not seen it bear any
1280 * resemblance to the portion that would fit.
1281 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1282 * trailing intercharacter spacing and any trailing justification.
1284 * FIXME
1285 * Currently we do this by measuring each character etc. We should do it by
1286 * passing the request to the driver, perhaps by extending the
1287 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1288 * thinking about kerning issues and rounding issues in the justification.
1291 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1292 INT maxExt, LPINT lpnFit,
1293 LPINT alpDx, LPSIZE size )
1295 INT nFit = 0;
1296 LPINT dxs = NULL;
1297 DC *dc;
1298 BOOL ret = FALSE;
1299 TEXTMETRICW tm;
1301 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1303 dc = DC_GetDCPtr(hdc);
1304 if (! dc)
1305 return FALSE;
1307 GetTextMetricsW(hdc, &tm);
1309 /* If we need to calculate nFit, then we need the partial extents even if
1310 the user hasn't provided us with an array. */
1311 if (lpnFit)
1313 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1314 if (! dxs)
1316 DC_ReleaseDCPtr(dc);
1317 SetLastError(ERROR_OUTOFMEMORY);
1318 return FALSE;
1321 else
1322 dxs = alpDx;
1324 if (dc->gdiFont)
1325 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1326 0, NULL, dxs, size);
1327 else if (dc->funcs->pGetTextExtentExPoint)
1328 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1329 0, NULL, dxs, size);
1331 /* Perform device size to world size transformations. */
1332 if (ret)
1334 INT extra = dc->charExtra,
1335 breakExtra = dc->breakExtra,
1336 breakRem = dc->breakRem,
1339 if (dxs)
1341 for (i = 0; i < count; ++i)
1343 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1344 dxs[i] += (i+1) * extra;
1345 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1347 dxs[i] += breakExtra;
1348 if (breakRem > 0)
1350 breakRem--;
1351 dxs[i]++;
1354 if (dxs[i] <= maxExt)
1355 ++nFit;
1357 breakRem = dc->breakRem;
1359 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1360 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1362 if (!dxs && count > 1 && (breakExtra || breakRem))
1364 for (i = 0; i < count; i++)
1366 if (str[i] == tm.tmBreakChar)
1368 size->cx += breakExtra;
1369 if (breakRem > 0)
1371 breakRem--;
1372 (size->cx)++;
1379 if (lpnFit)
1380 *lpnFit = nFit;
1382 if (! alpDx)
1383 HeapFree(GetProcessHeap(), 0, dxs);
1385 DC_ReleaseDCPtr( dc );
1387 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1388 return ret;
1391 /***********************************************************************
1392 * GetTextMetricsA (GDI32.@)
1394 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1396 TEXTMETRICW tm32;
1398 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1399 FONT_TextMetricWToA( &tm32, metrics );
1400 return TRUE;
1403 /***********************************************************************
1404 * GetTextMetricsW (GDI32.@)
1406 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1408 BOOL ret = FALSE;
1409 DC * dc = DC_GetDCPtr( hdc );
1410 if (!dc) return FALSE;
1412 if (dc->gdiFont)
1413 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1414 else if (dc->funcs->pGetTextMetrics)
1415 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1417 if (ret)
1419 /* device layer returns values in device units
1420 * therefore we have to convert them to logical */
1422 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1423 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1425 #define WDPTOLP(x) ((x<0)? \
1426 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1427 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1428 #define HDPTOLP(y) ((y<0)? \
1429 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1430 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1432 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1433 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1434 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1435 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1436 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1437 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1438 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1439 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1440 ret = TRUE;
1441 #undef WDPTOLP
1442 #undef HDPTOLP
1443 TRACE("text metrics:\n"
1444 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1445 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1446 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1447 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1448 " PitchAndFamily = %02x\n"
1449 " --------------------\n"
1450 " InternalLeading = %i\n"
1451 " Ascent = %i\n"
1452 " Descent = %i\n"
1453 " Height = %i\n",
1454 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1455 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1456 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1457 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1458 metrics->tmPitchAndFamily,
1459 metrics->tmInternalLeading,
1460 metrics->tmAscent,
1461 metrics->tmDescent,
1462 metrics->tmHeight );
1464 DC_ReleaseDCPtr( dc );
1465 return ret;
1469 /***********************************************************************
1470 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1472 * NOTES
1473 * lpOTM should be LPOUTLINETEXTMETRIC
1475 * RETURNS
1476 * Success: Non-zero or size of required buffer
1477 * Failure: 0
1479 UINT16 WINAPI GetOutlineTextMetrics16(
1480 HDC16 hdc, /* [in] Handle of device context */
1481 UINT16 cbData, /* [in] Size of metric data array */
1482 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1484 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1485 return 0;
1489 /***********************************************************************
1490 * GetOutlineTextMetricsA (GDI32.@)
1491 * Gets metrics for TrueType fonts.
1493 * NOTES
1494 * If the supplied buffer isn't big enough Windows partially fills it up to
1495 * its given length and returns that length.
1497 * RETURNS
1498 * Success: Non-zero or size of required buffer
1499 * Failure: 0
1501 UINT WINAPI GetOutlineTextMetricsA(
1502 HDC hdc, /* [in] Handle of device context */
1503 UINT cbData, /* [in] Size of metric data array */
1504 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1506 char buf[512], *ptr;
1507 UINT ret, needed;
1508 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1509 OUTLINETEXTMETRICA *output = lpOTM;
1510 INT left, len;
1512 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1513 return 0;
1514 if(ret > sizeof(buf))
1515 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1516 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1518 needed = sizeof(OUTLINETEXTMETRICA);
1519 if(lpOTMW->otmpFamilyName)
1520 needed += WideCharToMultiByte(CP_ACP, 0,
1521 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1522 NULL, 0, NULL, NULL);
1523 if(lpOTMW->otmpFaceName)
1524 needed += WideCharToMultiByte(CP_ACP, 0,
1525 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1526 NULL, 0, NULL, NULL);
1527 if(lpOTMW->otmpStyleName)
1528 needed += WideCharToMultiByte(CP_ACP, 0,
1529 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1530 NULL, 0, NULL, NULL);
1531 if(lpOTMW->otmpFullName)
1532 needed += WideCharToMultiByte(CP_ACP, 0,
1533 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1534 NULL, 0, NULL, NULL);
1536 if(!lpOTM) {
1537 ret = needed;
1538 goto end;
1541 TRACE("needed = %d\n", needed);
1542 if(needed > cbData)
1543 /* Since the supplied buffer isn't big enough, we'll alloc one
1544 that is and memcpy the first cbData bytes into the lpOTM at
1545 the end. */
1546 output = HeapAlloc(GetProcessHeap(), 0, needed);
1548 ret = output->otmSize = min(needed, cbData);
1549 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1550 output->otmFiller = 0;
1551 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1552 output->otmfsSelection = lpOTMW->otmfsSelection;
1553 output->otmfsType = lpOTMW->otmfsType;
1554 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1555 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1556 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1557 output->otmEMSquare = lpOTMW->otmEMSquare;
1558 output->otmAscent = lpOTMW->otmAscent;
1559 output->otmDescent = lpOTMW->otmDescent;
1560 output->otmLineGap = lpOTMW->otmLineGap;
1561 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1562 output->otmsXHeight = lpOTMW->otmsXHeight;
1563 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1564 output->otmMacAscent = lpOTMW->otmMacAscent;
1565 output->otmMacDescent = lpOTMW->otmMacDescent;
1566 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1567 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1568 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1569 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1570 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1571 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1572 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1573 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1574 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1575 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1578 ptr = (char*)(output + 1);
1579 left = needed - sizeof(*output);
1581 if(lpOTMW->otmpFamilyName) {
1582 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1583 len = WideCharToMultiByte(CP_ACP, 0,
1584 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1585 ptr, left, NULL, NULL);
1586 left -= len;
1587 ptr += len;
1588 } else
1589 output->otmpFamilyName = 0;
1591 if(lpOTMW->otmpFaceName) {
1592 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1593 len = WideCharToMultiByte(CP_ACP, 0,
1594 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1595 ptr, left, NULL, NULL);
1596 left -= len;
1597 ptr += len;
1598 } else
1599 output->otmpFaceName = 0;
1601 if(lpOTMW->otmpStyleName) {
1602 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1603 len = WideCharToMultiByte(CP_ACP, 0,
1604 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1605 ptr, left, NULL, NULL);
1606 left -= len;
1607 ptr += len;
1608 } else
1609 output->otmpStyleName = 0;
1611 if(lpOTMW->otmpFullName) {
1612 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1613 len = WideCharToMultiByte(CP_ACP, 0,
1614 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1615 ptr, left, NULL, NULL);
1616 left -= len;
1617 } else
1618 output->otmpFullName = 0;
1620 assert(left == 0);
1622 if(output != lpOTM) {
1623 memcpy(lpOTM, output, cbData);
1624 HeapFree(GetProcessHeap(), 0, output);
1626 /* check if the string offsets really fit into the provided size */
1627 /* FIXME: should we check string length as well? */
1628 /* make sure that we don't read/write beyond the provided buffer */
1629 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1631 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1632 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1635 /* make sure that we don't read/write beyond the provided buffer */
1636 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1638 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1639 lpOTM->otmpFaceName = 0; /* doesn't fit */
1642 /* make sure that we don't read/write beyond the provided buffer */
1643 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1645 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1646 lpOTM->otmpStyleName = 0; /* doesn't fit */
1649 /* make sure that we don't read/write beyond the provided buffer */
1650 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1652 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1653 lpOTM->otmpFullName = 0; /* doesn't fit */
1657 end:
1658 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1659 HeapFree(GetProcessHeap(), 0, lpOTMW);
1661 return ret;
1665 /***********************************************************************
1666 * GetOutlineTextMetricsW [GDI32.@]
1668 UINT WINAPI GetOutlineTextMetricsW(
1669 HDC hdc, /* [in] Handle of device context */
1670 UINT cbData, /* [in] Size of metric data array */
1671 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1673 DC *dc = DC_GetDCPtr( hdc );
1674 OUTLINETEXTMETRICW *output = lpOTM;
1675 UINT ret;
1677 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1678 if(!dc) return 0;
1680 if(dc->gdiFont) {
1681 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1682 if(lpOTM && ret) {
1683 if(ret > cbData) {
1684 output = HeapAlloc(GetProcessHeap(), 0, ret);
1685 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1688 #define WDPTOLP(x) ((x<0)? \
1689 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1690 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1691 #define HDPTOLP(y) ((y<0)? \
1692 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1693 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1695 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1696 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1697 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1698 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1699 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1700 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1701 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1702 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1703 output->otmAscent = HDPTOLP(output->otmAscent);
1704 output->otmDescent = HDPTOLP(output->otmDescent);
1705 output->otmLineGap = HDPTOLP(output->otmLineGap);
1706 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1707 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1708 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1709 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1710 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1711 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1712 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1713 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1714 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1715 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1716 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1717 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1718 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1719 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1720 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1721 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1722 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1723 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1724 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1725 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1726 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1727 #undef WDPTOLP
1728 #undef HDPTOLP
1729 if(output != lpOTM) {
1730 memcpy(lpOTM, output, cbData);
1731 HeapFree(GetProcessHeap(), 0, output);
1732 ret = cbData;
1737 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1738 but really this should just be a return 0. */
1740 ret = sizeof(*lpOTM);
1741 if (lpOTM) {
1742 if(cbData < ret)
1743 ret = 0;
1744 else {
1745 memset(lpOTM, 0, ret);
1746 lpOTM->otmSize = sizeof(*lpOTM);
1747 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1749 Further fill of the structure not implemented,
1750 Needs real values for the structure members
1755 DC_ReleaseDCPtr(dc);
1756 return ret;
1760 /***********************************************************************
1761 * GetCharWidthW (GDI32.@)
1762 * GetCharWidth32W (GDI32.@)
1764 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1765 LPINT buffer )
1767 UINT i;
1768 BOOL ret = FALSE;
1769 DC * dc = DC_GetDCPtr( hdc );
1770 if (!dc) return FALSE;
1772 if (dc->gdiFont)
1773 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1774 else if (dc->funcs->pGetCharWidth)
1775 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1777 if (ret)
1779 /* convert device units to logical */
1780 for( i = firstChar; i <= lastChar; i++, buffer++ )
1781 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1782 ret = TRUE;
1784 DC_ReleaseDCPtr( dc );
1785 return ret;
1789 /***********************************************************************
1790 * GetCharWidthA (GDI32.@)
1791 * GetCharWidth32A (GDI32.@)
1793 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1794 LPINT buffer )
1796 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1797 LPSTR str;
1798 LPWSTR wstr;
1799 BOOL ret = TRUE;
1801 if(count <= 0) return FALSE;
1803 str = HeapAlloc(GetProcessHeap(), 0, count);
1804 for(i = 0; i < count; i++)
1805 str[i] = (BYTE)(firstChar + i);
1807 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1809 for(i = 0; i < wlen; i++)
1811 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1813 ret = FALSE;
1814 break;
1816 buffer++;
1819 HeapFree(GetProcessHeap(), 0, str);
1820 HeapFree(GetProcessHeap(), 0, wstr);
1822 return ret;
1826 /***********************************************************************
1827 * ExtTextOutA (GDI32.@)
1829 * See ExtTextOutW.
1831 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1832 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1834 INT wlen;
1835 UINT codepage;
1836 LPWSTR p;
1837 BOOL ret;
1838 LPINT lpDxW = NULL;
1840 if (flags & ETO_GLYPH_INDEX)
1841 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1843 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1845 if (lpDx) {
1846 unsigned int i = 0, j = 0;
1848 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1849 while(i < count) {
1850 if(IsDBCSLeadByteEx(codepage, str[i])) {
1851 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1852 i = i + 2;
1853 } else {
1854 lpDxW[j++] = lpDx[i];
1855 i = i + 1;
1860 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1862 HeapFree( GetProcessHeap(), 0, p );
1863 HeapFree( GetProcessHeap(), 0, lpDxW );
1864 return ret;
1868 /***********************************************************************
1869 * ExtTextOutW (GDI32.@)
1871 * Draws text using the currently selected font, background color, and text color.
1874 * PARAMS
1875 * x,y [I] coordinates of string
1876 * flags [I]
1877 * ETO_GRAYED - undocumented on MSDN
1878 * ETO_OPAQUE - use background color for fill the rectangle
1879 * ETO_CLIPPED - clipping text to the rectangle
1880 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1881 * than encoded characters. Implies ETO_IGNORELANGUAGE
1882 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1883 * Affects BiDi ordering
1884 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1885 * ETO_PDY - unimplemented
1886 * ETO_NUMERICSLATIN - unimplemented always assumed -
1887 * do not translate numbers into locale representations
1888 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1889 * lprect [I] dimensions for clipping or/and opaquing
1890 * str [I] text string
1891 * count [I] number of symbols in string
1892 * lpDx [I] optional parameter with distance between drawing characters
1894 * RETURNS
1895 * Success: TRUE
1896 * Failure: FALSE
1898 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1899 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1901 BOOL ret = FALSE;
1902 LPWSTR reordered_str = (LPWSTR)str;
1903 WORD *glyphs = NULL;
1904 UINT align = GetTextAlign( hdc );
1905 POINT pt;
1906 TEXTMETRICW tm;
1907 LOGFONTW lf;
1908 double cosEsc, sinEsc;
1909 INT *deltas = NULL, char_extra;
1910 SIZE sz;
1911 RECT rc;
1912 BOOL done_extents = FALSE;
1913 INT width = 0, xwidth = 0, ywidth = 0;
1914 DWORD type;
1915 DC * dc = get_dc_ptr( hdc );
1916 INT breakRem;
1918 if (!dc) return FALSE;
1920 breakRem = dc->breakRem;
1922 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1923 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1925 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1927 release_dc_ptr( dc );
1928 return ret;
1931 update_dc( dc );
1932 type = GetObjectType(hdc);
1933 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1935 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1936 release_dc_ptr( dc );
1937 return ret;
1940 if (!lprect)
1941 flags &= ~ETO_CLIPPED;
1943 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1945 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1947 BIDI_Reorder( str, count, GCP_REORDER,
1948 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1949 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1950 reordered_str, count, NULL );
1952 flags |= ETO_IGNORELANGUAGE;
1955 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1956 lprect, debugstr_wn(str, count), count, lpDx);
1958 if(flags & ETO_GLYPH_INDEX)
1959 glyphs = reordered_str;
1961 if(lprect)
1962 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1963 lprect->bottom);
1964 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1966 if(align & TA_UPDATECP)
1968 GetCurrentPositionEx( hdc, &pt );
1969 x = pt.x;
1970 y = pt.y;
1973 GetTextMetricsW(hdc, &tm);
1974 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1976 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1977 lf.lfEscapement = 0;
1979 if(lf.lfEscapement != 0)
1981 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1982 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1984 else
1986 cosEsc = 1;
1987 sinEsc = 0;
1990 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1992 if(!lprect)
1994 if(flags & ETO_GLYPH_INDEX)
1995 GetTextExtentPointI(hdc, glyphs, count, &sz);
1996 else
1997 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1999 done_extents = TRUE;
2000 rc.left = x;
2001 rc.top = y;
2002 rc.right = x + sz.cx;
2003 rc.bottom = y + sz.cy;
2005 else
2007 rc = *lprect;
2010 LPtoDP(hdc, (POINT*)&rc, 2);
2012 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2013 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2016 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
2017 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2019 if(count == 0)
2021 ret = TRUE;
2022 goto done;
2025 pt.x = x;
2026 pt.y = y;
2027 LPtoDP(hdc, &pt, 1);
2028 x = pt.x;
2029 y = pt.y;
2031 char_extra = GetTextCharacterExtra(hdc);
2032 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2034 UINT i;
2035 SIZE tmpsz;
2036 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2037 for(i = 0; i < count; i++)
2039 if(lpDx && (flags & ETO_PDY))
2040 deltas[i] = lpDx[i*2] + char_extra;
2041 else if(lpDx)
2042 deltas[i] = lpDx[i] + char_extra;
2043 else
2045 if(flags & ETO_GLYPH_INDEX)
2046 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2047 else
2048 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2050 deltas[i] = tmpsz.cx;
2053 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2055 deltas[i] = deltas[i] + dc->breakExtra;
2056 if (breakRem > 0)
2058 breakRem--;
2059 deltas[i]++;
2062 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2063 width += deltas[i];
2066 else
2068 if(!done_extents)
2070 if(flags & ETO_GLYPH_INDEX)
2071 GetTextExtentPointI(hdc, glyphs, count, &sz);
2072 else
2073 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2074 done_extents = TRUE;
2076 width = INTERNAL_XWSTODS(dc, sz.cx);
2078 xwidth = width * cosEsc;
2079 ywidth = width * sinEsc;
2081 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2082 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2083 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2085 case TA_LEFT:
2086 if (align & TA_UPDATECP)
2088 pt.x = x + xwidth;
2089 pt.y = y - ywidth;
2090 DPtoLP(hdc, &pt, 1);
2091 MoveToEx(hdc, pt.x, pt.y, NULL);
2093 break;
2095 case TA_CENTER:
2096 x -= xwidth / 2;
2097 y += ywidth / 2;
2098 break;
2100 case TA_RIGHT:
2101 x -= xwidth;
2102 y += ywidth;
2103 if (align & TA_UPDATECP)
2105 pt.x = x;
2106 pt.y = y;
2107 DPtoLP(hdc, &pt, 1);
2108 MoveToEx(hdc, pt.x, pt.y, NULL);
2110 break;
2113 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2115 case TA_TOP:
2116 y += tm.tmAscent * cosEsc;
2117 x += tm.tmAscent * sinEsc;
2118 break;
2120 case TA_BOTTOM:
2121 y -= tm.tmDescent * cosEsc;
2122 x -= tm.tmDescent * sinEsc;
2123 break;
2125 case TA_BASELINE:
2126 break;
2129 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2131 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2133 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2134 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2136 RECT rc;
2137 rc.left = x;
2138 rc.right = x + width;
2139 rc.top = y - tm.tmAscent;
2140 rc.bottom = y + tm.tmDescent;
2141 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2146 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2148 HFONT orig_font = dc->hFont, cur_font;
2149 UINT glyph;
2150 INT span = 0, *offsets = NULL;
2151 unsigned int i;
2153 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2154 for(i = 0; i < count; i++)
2156 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2157 if(cur_font != dc->hFont)
2159 if(!offsets)
2161 unsigned int j;
2162 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2163 offsets[0] = 0;
2164 if(!deltas)
2166 SIZE tmpsz;
2167 for(j = 1; j < count; j++)
2169 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2170 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2173 else
2175 for(j = 1; j < count; j++)
2176 offsets[j] = offsets[j-1] + deltas[j];
2179 if(span)
2181 if (PATH_IsPathOpen(dc->path))
2182 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2183 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2184 glyphs, span, deltas ? deltas + i - span : NULL);
2185 else
2186 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2187 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2188 glyphs, span, deltas ? deltas + i - span : NULL);
2189 span = 0;
2191 SelectObject(hdc, cur_font);
2193 glyphs[span++] = glyph;
2195 if(i == count - 1)
2197 if (PATH_IsPathOpen(dc->path))
2198 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2199 y - (offsets ? offsets[count - span] * sinEsc : 0),
2200 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2201 glyphs, span, deltas ? deltas + count - span : NULL);
2202 else
2203 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2204 y - (offsets ? offsets[count - span] * sinEsc : 0),
2205 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2206 glyphs, span, deltas ? deltas + count - span : NULL);
2207 SelectObject(hdc, orig_font);
2208 HeapFree(GetProcessHeap(), 0, offsets);
2212 else
2214 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2216 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2217 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2218 flags |= ETO_GLYPH_INDEX;
2221 if (PATH_IsPathOpen(dc->path))
2222 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2223 glyphs ? glyphs : reordered_str, count, deltas);
2224 else
2225 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2226 glyphs ? glyphs : reordered_str, count, deltas);
2229 done:
2230 HeapFree(GetProcessHeap(), 0, deltas);
2231 if(glyphs != reordered_str)
2232 HeapFree(GetProcessHeap(), 0, glyphs);
2233 if(reordered_str != str)
2234 HeapFree(GetProcessHeap(), 0, reordered_str);
2236 release_dc_ptr( dc );
2238 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2240 int underlinePos, strikeoutPos;
2241 int underlineWidth, strikeoutWidth;
2242 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2243 OUTLINETEXTMETRICW* otm = NULL;
2245 if(!size)
2247 underlinePos = 0;
2248 underlineWidth = tm.tmAscent / 20 + 1;
2249 strikeoutPos = tm.tmAscent / 2;
2250 strikeoutWidth = underlineWidth;
2252 else
2254 otm = HeapAlloc(GetProcessHeap(), 0, size);
2255 GetOutlineTextMetricsW(hdc, size, otm);
2256 underlinePos = otm->otmsUnderscorePosition;
2257 underlineWidth = otm->otmsUnderscoreSize;
2258 strikeoutPos = otm->otmsStrikeoutPosition;
2259 strikeoutWidth = otm->otmsStrikeoutSize;
2260 HeapFree(GetProcessHeap(), 0, otm);
2263 if (PATH_IsPathOpen(dc->path))
2265 POINT pts[5];
2266 HPEN hpen;
2267 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2269 hbrush = SelectObject(hdc, hbrush);
2270 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2272 if (lf.lfUnderline)
2274 pts[0].x = x - underlinePos * sinEsc;
2275 pts[0].y = y - underlinePos * cosEsc;
2276 pts[1].x = x + xwidth - underlinePos * sinEsc;
2277 pts[1].y = y - ywidth - underlinePos * cosEsc;
2278 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2279 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2280 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2281 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2282 pts[4].x = pts[0].x;
2283 pts[4].y = pts[0].y;
2284 DPtoLP(hdc, pts, 5);
2285 Polygon(hdc, pts, 5);
2288 if (lf.lfStrikeOut)
2290 pts[0].x = x - strikeoutPos * sinEsc;
2291 pts[0].y = y - strikeoutPos * cosEsc;
2292 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2293 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2294 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2295 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2296 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2297 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2298 pts[4].x = pts[0].x;
2299 pts[4].y = pts[0].y;
2300 DPtoLP(hdc, pts, 5);
2301 Polygon(hdc, pts, 5);
2304 SelectObject(hdc, hpen);
2305 hbrush = SelectObject(hdc, hbrush);
2306 DeleteObject(hbrush);
2308 else
2310 POINT pts[2], oldpt;
2311 HPEN hpen;
2313 if (lf.lfUnderline)
2315 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2316 hpen = SelectObject(hdc, hpen);
2317 pts[0].x = x;
2318 pts[0].y = y;
2319 pts[1].x = x + xwidth;
2320 pts[1].y = y - ywidth;
2321 DPtoLP(hdc, pts, 2);
2322 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2323 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2324 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2325 DeleteObject(SelectObject(hdc, hpen));
2328 if (lf.lfStrikeOut)
2330 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2331 hpen = SelectObject(hdc, hpen);
2332 pts[0].x = x;
2333 pts[0].y = y;
2334 pts[1].x = x + xwidth;
2335 pts[1].y = y - ywidth;
2336 DPtoLP(hdc, pts, 2);
2337 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2338 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2339 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2340 DeleteObject(SelectObject(hdc, hpen));
2345 return ret;
2349 /***********************************************************************
2350 * TextOutA (GDI32.@)
2352 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2354 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2358 /***********************************************************************
2359 * TextOutW (GDI32.@)
2361 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2363 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2367 /***********************************************************************
2368 * PolyTextOutA (GDI32.@)
2370 * See PolyTextOutW.
2372 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2374 for (; cStrings>0; cStrings--, pptxt++)
2375 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2376 return FALSE;
2377 return TRUE;
2382 /***********************************************************************
2383 * PolyTextOutW (GDI32.@)
2385 * Draw several Strings
2387 * RETURNS
2388 * TRUE: Success.
2389 * FALSE: Failure.
2391 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2393 for (; cStrings>0; cStrings--, pptxt++)
2394 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2395 return FALSE;
2396 return TRUE;
2400 /* FIXME: all following APIs ******************************************/
2403 /***********************************************************************
2404 * SetMapperFlags (GDI32.@)
2406 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2408 DC *dc = DC_GetDCPtr( hDC );
2409 DWORD ret = 0;
2410 if(!dc) return 0;
2411 if(dc->funcs->pSetMapperFlags)
2413 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2414 /* FIXME: ret is just a success flag, we should return a proper value */
2416 else
2417 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2418 DC_ReleaseDCPtr( dc );
2419 return ret;
2422 /***********************************************************************
2423 * GetAspectRatioFilterEx (GDI.486)
2425 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2427 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2428 return FALSE;
2431 /***********************************************************************
2432 * GetAspectRatioFilterEx (GDI32.@)
2434 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2436 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2437 return FALSE;
2441 /***********************************************************************
2442 * GetCharABCWidthsA (GDI32.@)
2444 * See GetCharABCWidthsW.
2446 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2447 LPABC abc )
2449 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2450 LPSTR str;
2451 LPWSTR wstr;
2452 BOOL ret = TRUE;
2454 if(count <= 0) return FALSE;
2456 str = HeapAlloc(GetProcessHeap(), 0, count);
2457 for(i = 0; i < count; i++)
2458 str[i] = (BYTE)(firstChar + i);
2460 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2462 for(i = 0; i < wlen; i++)
2464 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2466 ret = FALSE;
2467 break;
2469 abc++;
2472 HeapFree(GetProcessHeap(), 0, str);
2473 HeapFree(GetProcessHeap(), 0, wstr);
2475 return ret;
2479 /******************************************************************************
2480 * GetCharABCWidthsW [GDI32.@]
2482 * Retrieves widths of characters in range.
2484 * PARAMS
2485 * hdc [I] Handle of device context
2486 * firstChar [I] First character in range to query
2487 * lastChar [I] Last character in range to query
2488 * abc [O] Address of character-width structure
2490 * NOTES
2491 * Only works with TrueType fonts
2493 * RETURNS
2494 * Success: TRUE
2495 * Failure: FALSE
2497 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2498 LPABC abc )
2500 DC *dc = DC_GetDCPtr(hdc);
2501 unsigned int i;
2502 BOOL ret = FALSE;
2504 if (!dc) return FALSE;
2506 if (!abc)
2508 DC_ReleaseDCPtr( dc );
2509 return FALSE;
2512 if(dc->gdiFont)
2513 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2514 else
2515 FIXME(": stub\n");
2517 if (ret)
2519 /* convert device units to logical */
2520 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2521 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2522 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2523 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2525 ret = TRUE;
2528 DC_ReleaseDCPtr( dc );
2529 return ret;
2533 /******************************************************************************
2534 * GetCharABCWidthsI [GDI32.@]
2536 * Retrieves widths of characters in range.
2538 * PARAMS
2539 * hdc [I] Handle of device context
2540 * firstChar [I] First glyphs in range to query
2541 * count [I] Last glyphs in range to query
2542 * pgi [i] Array of glyphs to query
2543 * abc [O] Address of character-width structure
2545 * NOTES
2546 * Only works with TrueType fonts
2548 * RETURNS
2549 * Success: TRUE
2550 * Failure: FALSE
2552 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2553 LPWORD pgi, LPABC abc)
2555 DC *dc = DC_GetDCPtr(hdc);
2556 unsigned int i;
2557 BOOL ret = FALSE;
2559 if (!dc) return FALSE;
2561 if (!abc)
2563 DC_ReleaseDCPtr( dc );
2564 return FALSE;
2567 if(dc->gdiFont)
2568 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2569 else
2570 FIXME(": stub\n");
2572 if (ret)
2574 /* convert device units to logical */
2575 for( i = 0; i < count; i++, abc++ ) {
2576 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2577 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2578 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2580 ret = TRUE;
2583 DC_ReleaseDCPtr( dc );
2584 return ret;
2588 /***********************************************************************
2589 * GetGlyphOutlineA (GDI32.@)
2591 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2592 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2593 LPVOID lpBuffer, const MAT2 *lpmat2 )
2595 LPWSTR p = NULL;
2596 DWORD ret;
2597 UINT c;
2599 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2600 int len;
2601 char mbchs[2];
2602 if(uChar > 0xff) { /* but, 2 bytes character only */
2603 len = 2;
2604 mbchs[0] = (uChar & 0xff00) >> 8;
2605 mbchs[1] = (uChar & 0xff);
2606 } else {
2607 len = 1;
2608 mbchs[0] = (uChar & 0xff);
2610 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2611 c = p[0];
2612 } else
2613 c = uChar;
2614 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2615 lpmat2);
2616 HeapFree(GetProcessHeap(), 0, p);
2617 return ret;
2620 /***********************************************************************
2621 * GetGlyphOutlineW (GDI32.@)
2623 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2624 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2625 LPVOID lpBuffer, const MAT2 *lpmat2 )
2627 DC *dc = DC_GetDCPtr(hdc);
2628 DWORD ret;
2630 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2631 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2633 if(!dc) return GDI_ERROR;
2635 if(dc->gdiFont)
2636 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2637 cbBuffer, lpBuffer, lpmat2);
2638 else
2639 ret = GDI_ERROR;
2641 DC_ReleaseDCPtr( dc );
2642 return ret;
2646 /***********************************************************************
2647 * CreateScalableFontResourceA (GDI32.@)
2649 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2650 LPCSTR lpszResourceFile,
2651 LPCSTR lpszFontFile,
2652 LPCSTR lpszCurrentPath )
2654 HANDLE f;
2656 /* fHidden=1 - only visible for the calling app, read-only, not
2657 * enumbered with EnumFonts/EnumFontFamilies
2658 * lpszCurrentPath can be NULL
2660 FIXME("(%d,%s,%s,%s): stub\n",
2661 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2662 debugstr_a(lpszCurrentPath) );
2664 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2665 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2666 CloseHandle(f);
2667 SetLastError(ERROR_FILE_EXISTS);
2668 return FALSE;
2670 return FALSE; /* create failed */
2673 /***********************************************************************
2674 * CreateScalableFontResourceW (GDI32.@)
2676 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2677 LPCWSTR lpszResourceFile,
2678 LPCWSTR lpszFontFile,
2679 LPCWSTR lpszCurrentPath )
2681 FIXME("(%d,%p,%p,%p): stub\n",
2682 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2683 return FALSE; /* create failed */
2686 /*************************************************************************
2687 * GetKerningPairsA (GDI32.@)
2689 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2690 LPKERNINGPAIR kern_pairA )
2692 INT charset;
2693 CHARSETINFO csi;
2694 CPINFO cpi;
2695 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2696 KERNINGPAIR *kern_pairW;
2698 if (!cPairs && kern_pairA)
2700 SetLastError(ERROR_INVALID_PARAMETER);
2701 return 0;
2704 charset = GetTextCharset(hDC);
2705 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2707 FIXME("Can't find codepage for charset %d\n", charset);
2708 return 0;
2710 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2711 * to fail on an invalid character for CP_SYMBOL.
2713 cpi.DefaultChar[0] = 0;
2714 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2716 FIXME("Can't find codepage %u info\n", csi.ciACP);
2717 return 0;
2719 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2721 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2722 if (!total_kern_pairs) return 0;
2724 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2725 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2727 for (i = 0; i < total_kern_pairs; i++)
2729 char first, second;
2731 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2732 continue;
2734 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2735 continue;
2737 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2738 continue;
2740 if (kern_pairA)
2742 if (kern_pairs_copied >= cPairs) break;
2744 kern_pairA->wFirst = (BYTE)first;
2745 kern_pairA->wSecond = (BYTE)second;
2746 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2747 kern_pairA++;
2749 kern_pairs_copied++;
2752 HeapFree(GetProcessHeap(), 0, kern_pairW);
2754 return kern_pairs_copied;
2757 /*************************************************************************
2758 * GetKerningPairsW (GDI32.@)
2760 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2761 LPKERNINGPAIR lpKerningPairs )
2763 DC *dc;
2764 DWORD ret = 0;
2766 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2768 if (!cPairs && lpKerningPairs)
2770 SetLastError(ERROR_INVALID_PARAMETER);
2771 return 0;
2774 dc = DC_GetDCPtr(hDC);
2775 if (!dc) return 0;
2777 if (dc->gdiFont)
2778 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2780 DC_ReleaseDCPtr( dc );
2781 return ret;
2784 /*************************************************************************
2785 * TranslateCharsetInfo [GDI32.@]
2787 * Fills a CHARSETINFO structure for a character set, code page, or
2788 * font. This allows making the correspondence between different labels
2789 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2790 * of the same encoding.
2792 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2793 * only one codepage should be set in *lpSrc.
2795 * RETURNS
2796 * TRUE on success, FALSE on failure.
2799 BOOL WINAPI TranslateCharsetInfo(
2800 LPDWORD lpSrc, /* [in]
2801 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2802 if flags == TCI_SRCCHARSET: a character set value
2803 if flags == TCI_SRCCODEPAGE: a code page value
2805 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2806 DWORD flags /* [in] determines interpretation of lpSrc */)
2808 int index = 0;
2809 switch (flags) {
2810 case TCI_SRCFONTSIG:
2811 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2812 break;
2813 case TCI_SRCCODEPAGE:
2814 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2815 break;
2816 case TCI_SRCCHARSET:
2817 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2818 break;
2819 default:
2820 return FALSE;
2822 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2823 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2824 return TRUE;
2827 /*************************************************************************
2828 * GetFontLanguageInfo (GDI32.@)
2830 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2832 FONTSIGNATURE fontsig;
2833 static const DWORD GCP_DBCS_MASK=0x003F0000,
2834 GCP_DIACRITIC_MASK=0x00000000,
2835 FLI_GLYPHS_MASK=0x00000000,
2836 GCP_GLYPHSHAPE_MASK=0x00000040,
2837 GCP_KASHIDA_MASK=0x00000000,
2838 GCP_LIGATE_MASK=0x00000000,
2839 GCP_USEKERNING_MASK=0x00000000,
2840 GCP_REORDER_MASK=0x00000060;
2842 DWORD result=0;
2844 GetTextCharsetInfo( hdc, &fontsig, 0 );
2845 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2847 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2848 result|=GCP_DBCS;
2850 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2851 result|=GCP_DIACRITIC;
2853 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2854 result|=FLI_GLYPHS;
2856 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2857 result|=GCP_GLYPHSHAPE;
2859 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2860 result|=GCP_KASHIDA;
2862 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2863 result|=GCP_LIGATE;
2865 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2866 result|=GCP_USEKERNING;
2868 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2869 if( GetTextAlign( hdc) & TA_RTLREADING )
2870 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2871 result|=GCP_REORDER;
2873 return result;
2877 /*************************************************************************
2878 * GetFontData [GDI32.@]
2880 * Retrieve data for TrueType font.
2882 * RETURNS
2884 * success: Number of bytes returned
2885 * failure: GDI_ERROR
2887 * NOTES
2889 * Calls SetLastError()
2892 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2893 LPVOID buffer, DWORD length)
2895 DC *dc = DC_GetDCPtr(hdc);
2896 DWORD ret = GDI_ERROR;
2898 if(!dc) return GDI_ERROR;
2900 if(dc->gdiFont)
2901 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2903 DC_ReleaseDCPtr( dc );
2904 return ret;
2907 /*************************************************************************
2908 * GetGlyphIndicesA [GDI32.@]
2910 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2911 LPWORD pgi, DWORD flags)
2913 DWORD ret;
2914 WCHAR *lpstrW;
2915 INT countW;
2917 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2918 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2920 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2921 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2922 HeapFree(GetProcessHeap(), 0, lpstrW);
2924 return ret;
2927 /*************************************************************************
2928 * GetGlyphIndicesW [GDI32.@]
2930 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2931 LPWORD pgi, DWORD flags)
2933 DC *dc = DC_GetDCPtr(hdc);
2934 DWORD ret = GDI_ERROR;
2936 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2937 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2939 if(!dc) return GDI_ERROR;
2941 if(dc->gdiFont)
2942 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2944 DC_ReleaseDCPtr( dc );
2945 return ret;
2948 /*************************************************************************
2949 * GetCharacterPlacementA [GDI32.@]
2951 * See GetCharacterPlacementW.
2953 * NOTES:
2954 * the web browser control of ie4 calls this with dwFlags=0
2956 DWORD WINAPI
2957 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2958 INT nMaxExtent, GCP_RESULTSA *lpResults,
2959 DWORD dwFlags)
2961 WCHAR *lpStringW;
2962 INT uCountW;
2963 GCP_RESULTSW resultsW;
2964 DWORD ret;
2965 UINT font_cp;
2967 TRACE("%s, %d, %d, 0x%08x\n",
2968 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2970 /* both structs are equal in size */
2971 memcpy(&resultsW, lpResults, sizeof(resultsW));
2973 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2974 if(lpResults->lpOutString)
2975 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2977 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2979 lpResults->nGlyphs = resultsW.nGlyphs;
2980 lpResults->nMaxFit = resultsW.nMaxFit;
2982 if(lpResults->lpOutString) {
2983 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2984 lpResults->lpOutString, uCount, NULL, NULL );
2987 HeapFree(GetProcessHeap(), 0, lpStringW);
2988 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2990 return ret;
2993 /*************************************************************************
2994 * GetCharacterPlacementW [GDI32.@]
2996 * Retrieve information about a string. This includes the width, reordering,
2997 * Glyphing and so on.
2999 * RETURNS
3001 * The width and height of the string if successful, 0 if failed.
3003 * BUGS
3005 * All flags except GCP_REORDER are not yet implemented.
3006 * Reordering is not 100% complient to the Windows BiDi method.
3007 * Caret positioning is not yet implemented for BiDi.
3008 * Classes are not yet implemented.
3011 DWORD WINAPI
3012 GetCharacterPlacementW(
3013 HDC hdc, /* [in] Device context for which the rendering is to be done */
3014 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3015 INT uCount, /* [in] Number of WORDS in string. */
3016 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3017 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3018 DWORD dwFlags /* [in] Flags specifying how to process the string */
3021 DWORD ret=0;
3022 SIZE size;
3023 UINT i, nSet;
3025 TRACE("%s, %d, %d, 0x%08x\n",
3026 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3028 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3029 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3030 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3031 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3032 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3034 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3035 if(lpResults->lpClass) FIXME("classes not implemented\n");
3036 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3037 FIXME("Caret positions for complex scripts not implemented\n");
3039 nSet = (UINT)uCount;
3040 if(nSet > lpResults->nGlyphs)
3041 nSet = lpResults->nGlyphs;
3043 /* return number of initialized fields */
3044 lpResults->nGlyphs = nSet;
3046 if((dwFlags&GCP_REORDER)==0 )
3048 /* Treat the case where no special handling was requested in a fastpath way */
3049 /* copy will do if the GCP_REORDER flag is not set */
3050 if(lpResults->lpOutString)
3051 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3053 if(lpResults->lpOrder)
3055 for(i = 0; i < nSet; i++)
3056 lpResults->lpOrder[i] = i;
3058 } else
3060 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3061 nSet, lpResults->lpOrder );
3064 /* FIXME: Will use the placement chars */
3065 if (lpResults->lpDx)
3067 int c;
3068 for (i = 0; i < nSet; i++)
3070 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3071 lpResults->lpDx[i]= c;
3075 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3077 int pos = 0;
3079 lpResults->lpCaretPos[0] = 0;
3080 for (i = 1; i < nSet; i++)
3081 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3082 lpResults->lpCaretPos[i] = (pos += size.cx);
3085 if(lpResults->lpGlyphs)
3086 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3088 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3089 ret = MAKELONG(size.cx, size.cy);
3091 return ret;
3094 /*************************************************************************
3095 * GetCharABCWidthsFloatA [GDI32.@]
3097 * See GetCharABCWidthsFloatW.
3099 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3101 INT i, wlen, count = (INT)(last - first + 1);
3102 LPSTR str;
3103 LPWSTR wstr;
3104 BOOL ret = TRUE;
3106 if (count <= 0) return FALSE;
3108 str = HeapAlloc(GetProcessHeap(), 0, count);
3110 for(i = 0; i < count; i++)
3111 str[i] = (BYTE)(first + i);
3113 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3115 for (i = 0; i < wlen; i++)
3117 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3119 ret = FALSE;
3120 break;
3122 abcf++;
3125 HeapFree( GetProcessHeap(), 0, str );
3126 HeapFree( GetProcessHeap(), 0, wstr );
3128 return ret;
3131 /*************************************************************************
3132 * GetCharABCWidthsFloatW [GDI32.@]
3134 * Retrieves widths of a range of characters.
3136 * PARAMS
3137 * hdc [I] Handle to device context.
3138 * first [I] First character in range to query.
3139 * last [I] Last character in range to query.
3140 * abcf [O] Array of LPABCFLOAT structures.
3142 * RETURNS
3143 * Success: TRUE
3144 * Failure: FALSE
3146 * BUGS
3147 * Only works with TrueType fonts. It also doesn't return real
3148 * floats but converted integers because it's implemented on
3149 * top of GetCharABCWidthsW.
3151 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3153 ABC *abc;
3154 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3155 BOOL ret;
3157 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3159 abc = HeapAlloc( GetProcessHeap(), 0, size );
3160 if (!abc) return FALSE;
3162 ret = GetCharABCWidthsW( hdc, first, last, abc );
3163 if (ret)
3165 for (i = first; i <= last; i++, abc++, abcf++)
3167 abcf->abcfA = abc->abcA;
3168 abcf->abcfB = abc->abcB;
3169 abcf->abcfC = abc->abcC;
3172 HeapFree( GetProcessHeap(), 0, abc );
3173 return ret;
3176 /*************************************************************************
3177 * GetCharWidthFloatA [GDI32.@]
3179 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3180 UINT iLastChar, PFLOAT pxBuffer)
3182 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3183 return 0;
3186 /*************************************************************************
3187 * GetCharWidthFloatW [GDI32.@]
3189 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3190 UINT iLastChar, PFLOAT pxBuffer)
3192 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3193 return 0;
3197 /***********************************************************************
3199 * Font Resource API *
3201 ***********************************************************************/
3203 /***********************************************************************
3204 * AddFontResourceA (GDI32.@)
3206 INT WINAPI AddFontResourceA( LPCSTR str )
3208 return AddFontResourceExA( str, 0, NULL);
3211 /***********************************************************************
3212 * AddFontResourceW (GDI32.@)
3214 INT WINAPI AddFontResourceW( LPCWSTR str )
3216 return AddFontResourceExW(str, 0, NULL);
3220 /***********************************************************************
3221 * AddFontResourceExA (GDI32.@)
3223 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3225 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3226 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3227 INT ret;
3229 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3230 ret = AddFontResourceExW(strW, fl, pdv);
3231 HeapFree(GetProcessHeap(), 0, strW);
3232 return ret;
3235 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3237 HRSRC rsrc = FindResourceW(hModule, name, type);
3238 HGLOBAL hMem = LoadResource(hModule, rsrc);
3239 LPVOID *pMem = LockResource(hMem);
3240 int *num_total = (int *)lParam;
3241 DWORD num_in_res;
3243 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3244 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3246 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3247 return FALSE;
3250 *num_total += num_in_res;
3251 return TRUE;
3254 /***********************************************************************
3255 * AddFontResourceExW (GDI32.@)
3257 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3259 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3260 if (ret == 0)
3262 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3263 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3264 if (hModule != NULL)
3266 int num_resources = 0;
3267 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3269 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3270 wine_dbgstr_w(str));
3271 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3272 ret = num_resources;
3273 FreeLibrary(hModule);
3276 return ret;
3279 /***********************************************************************
3280 * RemoveFontResourceA (GDI32.@)
3282 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3284 return RemoveFontResourceExA(str, 0, 0);
3287 /***********************************************************************
3288 * RemoveFontResourceW (GDI32.@)
3290 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3292 return RemoveFontResourceExW(str, 0, 0);
3295 /***********************************************************************
3296 * AddFontMemResourceEx (GDI32.@)
3298 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3300 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3303 /***********************************************************************
3304 * RemoveFontMemResourceEx (GDI32.@)
3306 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3308 FIXME("(%p) stub\n", fh);
3309 return TRUE;
3312 /***********************************************************************
3313 * RemoveFontResourceExA (GDI32.@)
3315 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3317 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3318 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3319 INT ret;
3321 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3322 ret = RemoveFontResourceExW(strW, fl, pdv);
3323 HeapFree(GetProcessHeap(), 0, strW);
3324 return ret;
3327 /***********************************************************************
3328 * RemoveFontResourceExW (GDI32.@)
3330 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3332 return WineEngRemoveFontResourceEx(str, fl, pdv);
3335 /***********************************************************************
3336 * GetTextCharset (GDI32.@)
3338 UINT WINAPI GetTextCharset(HDC hdc)
3340 /* MSDN docs say this is equivalent */
3341 return GetTextCharsetInfo(hdc, NULL, 0);
3344 /***********************************************************************
3345 * GetTextCharsetInfo (GDI32.@)
3347 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3349 UINT ret = DEFAULT_CHARSET;
3350 DC *dc = DC_GetDCPtr(hdc);
3352 if (dc)
3354 if (dc->gdiFont)
3355 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3357 DC_ReleaseDCPtr( dc );
3360 if (ret == DEFAULT_CHARSET && fs)
3361 memset(fs, 0, sizeof(FONTSIGNATURE));
3362 return ret;
3365 /***********************************************************************
3366 * GdiGetCharDimensions (GDI32.@)
3368 * Gets the average width of the characters in the English alphabet.
3370 * PARAMS
3371 * hdc [I] Handle to the device context to measure on.
3372 * lptm [O] Pointer to memory to store the text metrics into.
3373 * height [O] On exit, the maximum height of characters in the English alphabet.
3375 * RETURNS
3376 * The average width of characters in the English alphabet.
3378 * NOTES
3379 * This function is used by the dialog manager to get the size of a dialog
3380 * unit. It should also be used by other pieces of code that need to know
3381 * the size of a dialog unit in logical units without having access to the
3382 * window handle of the dialog.
3383 * Windows caches the font metrics from this function, but we don't and
3384 * there doesn't appear to be an immediate advantage to do so.
3386 * SEE ALSO
3387 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3389 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3391 SIZE sz;
3392 static const WCHAR alphabet[] = {
3393 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3394 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3395 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3397 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3399 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3401 if (height) *height = sz.cy;
3402 return (sz.cx / 26 + 1) / 2;
3405 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3407 FIXME("(%d): stub\n", fEnableEUDC);
3408 return FALSE;
3411 /***********************************************************************
3412 * GetCharWidthI (GDI32.@)
3414 * Retrieve widths of characters.
3416 * PARAMS
3417 * hdc [I] Handle to a device context.
3418 * first [I] First glyph in range to query.
3419 * count [I] Number of glyph indices to query.
3420 * glyphs [I] Array of glyphs to query.
3421 * buffer [O] Buffer to receive character widths.
3423 * NOTES
3424 * Only works with TrueType fonts.
3426 * RETURNS
3427 * Success: TRUE
3428 * Failure: FALSE
3430 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3432 ABC *abc;
3433 unsigned int i;
3435 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3437 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3438 return FALSE;
3440 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3442 HeapFree(GetProcessHeap(), 0, abc);
3443 return FALSE;
3446 for (i = 0; i < count; i++)
3447 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3449 HeapFree(GetProcessHeap(), 0, abc);
3450 return TRUE;
3453 /***********************************************************************
3454 * GetFontUnicodeRanges (GDI32.@)
3456 * Retrieve a list of supported Unicode characters in a font.
3458 * PARAMS
3459 * hdc [I] Handle to a device context.
3460 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3462 * RETURNS
3463 * Success: Number of bytes written to the buffer pointed to by lpgs.
3464 * Failure: 0
3467 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3469 DWORD ret = 0;
3470 DC *dc = DC_GetDCPtr(hdc);
3472 TRACE("(%p, %p)\n", hdc, lpgs);
3474 if (!dc) return 0;
3476 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3477 DC_ReleaseDCPtr(dc);
3478 return ret;
3482 /*************************************************************
3483 * FontIsLinked (GDI32.@)
3485 BOOL WINAPI FontIsLinked(HDC hdc)
3487 DC *dc = DC_GetDCPtr(hdc);
3488 BOOL ret = FALSE;
3490 if (!dc) return FALSE;
3491 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3492 DC_ReleaseDCPtr(dc);
3493 TRACE("returning %d\n", ret);
3494 return ret;