Improve c2man Documented-Total count.
[wine.git] / dlls / gdi / font.c
blob301a17ecd42179d2fff2eeac1be6be1a3e59890d
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 FLOAT floatWidth;
52 /* Perform operation with floating point */
53 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 FLOAT floatHeight;
65 /* Perform operation with floating point */
66 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight);
71 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
73 POINT pt[2];
74 pt[0].x = pt[0].y = 0;
75 pt[1].x = width;
76 pt[1].y = 0;
77 LPtoDP(dc->hSelf, pt, 2);
78 return pt[1].x - pt[0].x;
81 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
83 POINT pt[2];
84 pt[0].x = pt[0].y = 0;
85 pt[1].x = 0;
86 pt[1].y = height;
87 LPtoDP(dc->hSelf, pt, 2);
88 return pt[1].y - pt[0].y;
91 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
92 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
94 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
95 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
97 static const struct gdi_obj_funcs font_funcs =
99 FONT_SelectObject, /* pSelectObject */
100 FONT_GetObject16, /* pGetObject16 */
101 FONT_GetObjectA, /* pGetObjectA */
102 FONT_GetObjectW, /* pGetObjectW */
103 NULL, /* pUnrealizeObject */
104 FONT_DeleteObject /* pDeleteObject */
107 #define ENUM_UNICODE 0x00000001
108 #define ENUM_CALLED 0x00000002
110 typedef struct
112 GDIOBJHDR header;
113 LOGFONTW logfont;
114 } FONTOBJ;
116 typedef struct
118 LPLOGFONT16 lpLogFontParam;
119 FONTENUMPROC16 lpEnumFunc;
120 LPARAM lpData;
122 LPNEWTEXTMETRICEX16 lpTextMetric;
123 LPENUMLOGFONTEX16 lpLogFont;
124 SEGPTR segTextMetric;
125 SEGPTR segLogFont;
126 DWORD dwFlags;
127 HDC hdc;
128 DC *dc;
129 PHYSDEV physDev;
130 } fontEnum16;
132 typedef struct
134 LPLOGFONTW lpLogFontParam;
135 FONTENUMPROCW lpEnumFunc;
136 LPARAM lpData;
137 DWORD dwFlags;
138 HDC hdc;
139 DC *dc;
140 PHYSDEV physDev;
141 } fontEnum32;
144 * For TranslateCharsetInfo
146 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
147 #define MAXTCIINDEX 32
148 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
149 /* ANSI */
150 { ANSI_CHARSET, 1252, FS(0)},
151 { EASTEUROPE_CHARSET, 1250, FS(1)},
152 { RUSSIAN_CHARSET, 1251, FS(2)},
153 { GREEK_CHARSET, 1253, FS(3)},
154 { TURKISH_CHARSET, 1254, FS(4)},
155 { HEBREW_CHARSET, 1255, FS(5)},
156 { ARABIC_CHARSET, 1256, FS(6)},
157 { BALTIC_CHARSET, 1257, FS(7)},
158 { VIETNAMESE_CHARSET, 1258, FS(8)},
159 /* reserved by ANSI */
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 { DEFAULT_CHARSET, 0, FS(0)},
166 { DEFAULT_CHARSET, 0, FS(0)},
167 /* ANSI and OEM */
168 { THAI_CHARSET, 874, FS(16)},
169 { SHIFTJIS_CHARSET, 932, FS(17)},
170 { GB2312_CHARSET, 936, FS(18)},
171 { HANGEUL_CHARSET, 949, FS(19)},
172 { CHINESEBIG5_CHARSET, 950, FS(20)},
173 { JOHAB_CHARSET, 1361, FS(21)},
174 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET, 0, FS(0)},
182 { DEFAULT_CHARSET, 0, FS(0)},
183 /* reserved for system */
184 { DEFAULT_CHARSET, 0, FS(0)},
185 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
188 /***********************************************************************
189 * LOGFONT conversion functions.
191 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
193 font16->lfHeight = font32->lfHeight;
194 font16->lfWidth = font32->lfWidth;
195 font16->lfEscapement = font32->lfEscapement;
196 font16->lfOrientation = font32->lfOrientation;
197 font16->lfWeight = font32->lfWeight;
198 font16->lfItalic = font32->lfItalic;
199 font16->lfUnderline = font32->lfUnderline;
200 font16->lfStrikeOut = font32->lfStrikeOut;
201 font16->lfCharSet = font32->lfCharSet;
202 font16->lfOutPrecision = font32->lfOutPrecision;
203 font16->lfClipPrecision = font32->lfClipPrecision;
204 font16->lfQuality = font32->lfQuality;
205 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
206 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
207 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
208 font16->lfFaceName[LF_FACESIZE-1] = 0;
211 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
213 font32->lfHeight = font16->lfHeight;
214 font32->lfWidth = font16->lfWidth;
215 font32->lfEscapement = font16->lfEscapement;
216 font32->lfOrientation = font16->lfOrientation;
217 font32->lfWeight = font16->lfWeight;
218 font32->lfItalic = font16->lfItalic;
219 font32->lfUnderline = font16->lfUnderline;
220 font32->lfStrikeOut = font16->lfStrikeOut;
221 font32->lfCharSet = font16->lfCharSet;
222 font32->lfOutPrecision = font16->lfOutPrecision;
223 font32->lfClipPrecision = font16->lfClipPrecision;
224 font32->lfQuality = font16->lfQuality;
225 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
226 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
227 font32->lfFaceName[LF_FACESIZE-1] = 0;
230 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
232 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
233 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
234 LF_FACESIZE);
235 fontW->lfFaceName[LF_FACESIZE-1] = 0;
238 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
240 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
241 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
242 LF_FACESIZE, NULL, NULL);
243 fontA->lfFaceName[LF_FACESIZE-1] = 0;
246 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
248 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
251 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
252 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
253 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
254 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
255 font16->elfStyle[LF_FACESIZE-1] = '\0';
256 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
257 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
258 font16->elfScript[LF_FACESIZE-1] = '\0';
261 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
263 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
265 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
266 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
267 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
268 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
269 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
270 fontA->elfStyle[LF_FACESIZE-1] = '\0';
271 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
272 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
273 fontA->elfScript[LF_FACESIZE-1] = '\0';
276 /***********************************************************************
277 * TEXTMETRIC conversion functions.
279 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
281 ptmA->tmHeight = ptmW->tmHeight;
282 ptmA->tmAscent = ptmW->tmAscent;
283 ptmA->tmDescent = ptmW->tmDescent;
284 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
285 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
286 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
287 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
288 ptmA->tmWeight = ptmW->tmWeight;
289 ptmA->tmOverhang = ptmW->tmOverhang;
290 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
291 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
292 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
293 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
294 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
295 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
296 ptmA->tmItalic = ptmW->tmItalic;
297 ptmA->tmUnderlined = ptmW->tmUnderlined;
298 ptmA->tmStruckOut = ptmW->tmStruckOut;
299 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
300 ptmA->tmCharSet = ptmW->tmCharSet;
304 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
306 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
307 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
308 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
309 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
310 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
311 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
312 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
313 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
314 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
315 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
316 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
317 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
318 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
319 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
320 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
321 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
322 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
323 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
324 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
325 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
326 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
327 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
328 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
329 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
330 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
333 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
335 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
336 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
337 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
338 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
339 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
340 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
344 /***********************************************************************
345 * FONT_mbtowc
347 * Returns a '\0' terminated Unicode translation of str using the
348 * charset of the currently selected font in hdc. If count is -1 then
349 * str is assumed to be '\0' terminated, otherwise it contains the
350 * number of bytes to convert. If plenW is non-NULL, on return it
351 * will point to the number of WCHARs (excluding the '\0') that have
352 * been written. If pCP is non-NULL, on return it will point to the
353 * codepage used in the conversion.
354 * The caller should free the returned LPWSTR from the process
355 * heap itself.
357 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
359 UINT cp = CP_ACP;
360 INT lenW;
361 LPWSTR strW;
362 CHARSETINFO csi;
363 int charset = GetTextCharset(hdc);
365 /* Hmm, nicely designed api this one! */
366 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
367 cp = csi.ciACP;
368 else {
369 switch(charset) {
370 case OEM_CHARSET:
371 cp = GetOEMCP();
372 break;
373 case DEFAULT_CHARSET:
374 cp = GetACP();
375 break;
377 case VISCII_CHARSET:
378 case TCVN_CHARSET:
379 case KOI8_CHARSET:
380 case ISO3_CHARSET:
381 case ISO4_CHARSET:
382 case ISO10_CHARSET:
383 case CELTIC_CHARSET:
384 /* FIXME: These have no place here, but because x11drv
385 enumerates fonts with these (made up) charsets some apps
386 might use them and then the FIXME below would become
387 annoying. Now we could pick the intended codepage for
388 each of these, but since it's broken anyway we'll just
389 use CP_ACP and hope it'll go away...
391 cp = CP_ACP;
392 break;
394 default:
395 FIXME("Can't find codepage for charset %d\n", charset);
396 break;
400 TRACE("charset %d => cp %d\n", charset, cp);
402 if(count == -1) count = strlen(str);
403 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
404 strW = HeapAlloc(GetProcessHeap(), 0, (lenW + 1) * sizeof(WCHAR));
405 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
406 strW[lenW] = '\0';
407 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
408 if(plenW) *plenW = lenW;
409 if(pCP) *pCP = cp;
410 return strW;
414 /***********************************************************************
415 * CreateFontIndirectA (GDI32.@)
417 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
419 LOGFONTW lfW;
421 if (plfA) {
422 FONT_LogFontAToW( plfA, &lfW );
423 return CreateFontIndirectW( &lfW );
424 } else
425 return CreateFontIndirectW( NULL );
429 /***********************************************************************
430 * CreateFontIndirectW (GDI32.@)
432 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
434 HFONT hFont = 0;
436 if (plf)
438 FONTOBJ* fontPtr;
439 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
440 (HGDIOBJ *)&hFont, &font_funcs )))
442 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
443 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
444 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
445 WCHAR* pFaceNameSuffix = NULL;
447 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
449 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
450 plf->lfHeight, plf->lfWidth,
451 plf->lfEscapement, plf->lfOrientation,
452 plf->lfPitchAndFamily,
453 plf->lfOutPrecision, plf->lfClipPrecision,
454 plf->lfQuality, plf->lfCharSet,
455 debugstr_w(plf->lfFaceName),
456 plf->lfWeight > 400 ? "Bold" : "",
457 plf->lfItalic ? "Italic" : "",
458 plf->lfUnderline ? "Underline" : "", hFont);
460 if (plf->lfEscapement != plf->lfOrientation) {
461 /* this should really depend on whether GM_ADVANCED is set */
462 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
463 WARN("orientation angle %f set to "
464 "escapement angle %f for new font %p\n",
465 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
468 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
469 if (pFaceNameItalicSuffix) {
470 fontPtr->logfont.lfItalic = TRUE;
471 pFaceNameSuffix = pFaceNameItalicSuffix;
474 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
475 if (pFaceNameBoldSuffix) {
476 if (fontPtr->logfont.lfWeight < FW_BOLD) {
477 fontPtr->logfont.lfWeight = FW_BOLD;
479 if (!pFaceNameSuffix ||
480 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
481 pFaceNameSuffix = pFaceNameBoldSuffix;
485 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
487 GDI_ReleaseObj( hFont );
490 else WARN("(NULL) => NULL\n");
492 return hFont;
495 /*************************************************************************
496 * CreateFontA (GDI32.@)
498 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
499 INT orient, INT weight, DWORD italic,
500 DWORD underline, DWORD strikeout, DWORD charset,
501 DWORD outpres, DWORD clippres, DWORD quality,
502 DWORD pitch, LPCSTR name )
504 LOGFONTA logfont;
506 logfont.lfHeight = height;
507 logfont.lfWidth = width;
508 logfont.lfEscapement = esc;
509 logfont.lfOrientation = orient;
510 logfont.lfWeight = weight;
511 logfont.lfItalic = italic;
512 logfont.lfUnderline = underline;
513 logfont.lfStrikeOut = strikeout;
514 logfont.lfCharSet = charset;
515 logfont.lfOutPrecision = outpres;
516 logfont.lfClipPrecision = clippres;
517 logfont.lfQuality = quality;
518 logfont.lfPitchAndFamily = pitch;
520 if (name)
521 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
522 else
523 logfont.lfFaceName[0] = '\0';
525 return CreateFontIndirectA( &logfont );
528 /*************************************************************************
529 * CreateFontW (GDI32.@)
531 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
532 INT orient, INT weight, DWORD italic,
533 DWORD underline, DWORD strikeout, DWORD charset,
534 DWORD outpres, DWORD clippres, DWORD quality,
535 DWORD pitch, LPCWSTR name )
537 LOGFONTW logfont;
539 logfont.lfHeight = height;
540 logfont.lfWidth = width;
541 logfont.lfEscapement = esc;
542 logfont.lfOrientation = orient;
543 logfont.lfWeight = weight;
544 logfont.lfItalic = italic;
545 logfont.lfUnderline = underline;
546 logfont.lfStrikeOut = strikeout;
547 logfont.lfCharSet = charset;
548 logfont.lfOutPrecision = outpres;
549 logfont.lfClipPrecision = clippres;
550 logfont.lfQuality = quality;
551 logfont.lfPitchAndFamily = pitch;
553 if (name)
554 lstrcpynW(logfont.lfFaceName, name,
555 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
556 else
557 logfont.lfFaceName[0] = '\0';
559 return CreateFontIndirectW( &logfont );
563 /***********************************************************************
564 * FONT_SelectObject
566 * If the driver supports vector fonts we create a gdi font first and
567 * then call the driver to give it a chance to supply its own device
568 * font. If the driver wants to do this it returns TRUE and we can
569 * delete the gdi font, if the driver wants to use the gdi font it
570 * should return FALSE, to signal an error return GDI_ERROR. For
571 * drivers that don't support vector fonts they must supply their own
572 * font.
574 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
576 HGDIOBJ ret = 0;
577 DC *dc = DC_GetDCPtr( hdc );
579 if (!dc) return 0;
581 if (dc->hFont != handle || dc->gdiFont == NULL)
583 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
584 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
587 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
589 if (ret && dc->gdiFont) dc->gdiFont = 0;
591 if (ret == HGDI_ERROR)
592 ret = 0; /* SelectObject returns 0 on error */
593 else
595 ret = dc->hFont;
596 dc->hFont = handle;
598 GDI_ReleaseObj( hdc );
599 return ret;
603 /***********************************************************************
604 * FONT_GetObject16
606 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
608 FONTOBJ *font = obj;
609 LOGFONT16 lf16;
611 FONT_LogFontWTo16( &font->logfont, &lf16 );
613 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
614 memcpy( buffer, &lf16, count );
615 return count;
618 /***********************************************************************
619 * FONT_GetObjectA
621 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
623 FONTOBJ *font = obj;
624 LOGFONTA lfA;
626 if(!buffer)
627 return sizeof(lfA);
628 FONT_LogFontWToA( &font->logfont, &lfA );
630 if (count > sizeof(lfA)) count = sizeof(lfA);
631 memcpy( buffer, &lfA, count );
632 return count;
635 /***********************************************************************
636 * FONT_GetObjectW
638 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
640 FONTOBJ *font = obj;
641 if(!buffer)
642 return sizeof(LOGFONTW);
643 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
644 memcpy( buffer, &font->logfont, count );
645 return count;
649 /***********************************************************************
650 * FONT_DeleteObject
652 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
654 WineEngDestroyFontInstance( handle );
655 return GDI_FreeObject( handle, obj );
659 /***********************************************************************
660 * FONT_EnumInstance16
662 * Called by the device driver layer to pass font info
663 * down to the application.
665 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
666 * We have to use other types because of the FONTENUMPROCW definition.
668 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
669 DWORD fType, LPARAM lp )
671 fontEnum16 *pfe = (fontEnum16*)lp;
672 INT ret = 1;
673 DC *dc;
675 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
676 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
678 WORD args[7];
679 DWORD result;
681 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
682 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
683 pfe->dwFlags |= ENUM_CALLED;
684 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
686 args[6] = SELECTOROF(pfe->segLogFont);
687 args[5] = OFFSETOF(pfe->segLogFont);
688 args[4] = SELECTOROF(pfe->segTextMetric);
689 args[3] = OFFSETOF(pfe->segTextMetric);
690 args[2] = fType;
691 args[1] = HIWORD(pfe->lpData);
692 args[0] = LOWORD(pfe->lpData);
693 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
694 ret = LOWORD(result);
696 /* get the lock again and make sure the DC is still valid */
697 dc = DC_GetDCPtr( pfe->hdc );
698 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
700 if (dc) GDI_ReleaseObj( pfe->hdc );
701 pfe->hdc = 0; /* make sure we don't try to release it later on */
702 ret = 0;
705 return ret;
708 /***********************************************************************
709 * FONT_EnumInstance
711 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
712 * We have to use other types because of the FONTENUMPROCW definition.
714 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
715 DWORD fType, LPARAM lp )
717 fontEnum32 *pfe = (fontEnum32*)lp;
718 INT ret = 1;
719 DC *dc;
721 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
722 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
723 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
724 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
726 /* convert font metrics */
727 ENUMLOGFONTEXA logfont;
728 NEWTEXTMETRICEXA tmA;
730 pfe->dwFlags |= ENUM_CALLED;
731 if (!(pfe->dwFlags & ENUM_UNICODE))
733 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
734 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
735 plf = (LOGFONTW *)&logfont.elfLogFont;
736 ptm = (TEXTMETRICW *)&tmA;
738 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
740 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
742 /* get the lock again and make sure the DC is still valid */
743 dc = DC_GetDCPtr( pfe->hdc );
744 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
746 if (dc) GDI_ReleaseObj( pfe->hdc );
747 pfe->hdc = 0; /* make sure we don't try to release it later on */
748 ret = 0;
751 return ret;
754 /***********************************************************************
755 * EnumFontFamiliesEx (GDI.613)
757 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
758 FONTENUMPROC16 efproc, LPARAM lParam,
759 DWORD dwFlags)
761 fontEnum16 fe16;
762 INT16 ret = 1, ret2;
763 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
764 NEWTEXTMETRICEX16 tm16;
765 ENUMLOGFONTEX16 lf16;
766 LOGFONTW lfW;
767 BOOL enum_gdi_fonts;
769 if (!dc) return 0;
770 FONT_LogFont16ToW(plf, &lfW);
772 fe16.hdc = HDC_32(hDC);
773 fe16.dc = dc;
774 fe16.physDev = dc->physDev;
775 fe16.lpLogFontParam = plf;
776 fe16.lpEnumFunc = efproc;
777 fe16.lpData = lParam;
778 fe16.lpTextMetric = &tm16;
779 fe16.lpLogFont = &lf16;
780 fe16.segTextMetric = MapLS( &tm16 );
781 fe16.segLogFont = MapLS( &lf16 );
782 fe16.dwFlags = 0;
784 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
786 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
788 ret = 0;
789 goto done;
792 if (enum_gdi_fonts)
793 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
794 fe16.dwFlags &= ~ENUM_CALLED;
795 if (ret && dc->funcs->pEnumDeviceFonts) {
796 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
797 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
798 ret = ret2;
800 done:
801 UnMapLS( fe16.segTextMetric );
802 UnMapLS( fe16.segLogFont );
803 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
804 return ret;
807 /***********************************************************************
808 * FONT_EnumFontFamiliesEx
810 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
811 FONTENUMPROCW efproc,
812 LPARAM lParam, DWORD dwUnicode)
814 INT ret = 1, ret2;
815 DC *dc = DC_GetDCPtr( hDC );
816 fontEnum32 fe32;
817 BOOL enum_gdi_fonts;
819 if (!dc) return 0;
821 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
822 plf->lfCharSet);
823 fe32.lpLogFontParam = plf;
824 fe32.lpEnumFunc = efproc;
825 fe32.lpData = lParam;
826 fe32.dwFlags = dwUnicode;
827 fe32.hdc = hDC;
828 fe32.dc = dc;
829 fe32.physDev = dc->physDev;
831 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
833 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
835 ret = 0;
836 goto done;
839 if (enum_gdi_fonts)
840 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
841 fe32.dwFlags &= ~ENUM_CALLED;
842 if (ret && dc->funcs->pEnumDeviceFonts) {
843 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
844 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
845 ret = ret2;
847 done:
848 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
849 return ret;
852 /***********************************************************************
853 * EnumFontFamiliesExW (GDI32.@)
855 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
856 FONTENUMPROCW efproc,
857 LPARAM lParam, DWORD dwFlags )
859 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
862 /***********************************************************************
863 * EnumFontFamiliesExA (GDI32.@)
865 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
866 FONTENUMPROCA efproc,
867 LPARAM lParam, DWORD dwFlags)
869 LOGFONTW lfW;
870 FONT_LogFontAToW( plf, &lfW );
872 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
875 /***********************************************************************
876 * EnumFontFamilies (GDI.330)
878 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
879 FONTENUMPROC16 efproc, LPARAM lpData )
881 LOGFONT16 lf;
883 lf.lfCharSet = DEFAULT_CHARSET;
884 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
885 else lf.lfFaceName[0] = '\0';
887 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
890 /***********************************************************************
891 * EnumFontFamiliesA (GDI32.@)
893 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
894 FONTENUMPROCA efproc, LPARAM lpData )
896 LOGFONTA lf;
898 lf.lfCharSet = DEFAULT_CHARSET;
899 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
900 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
902 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
905 /***********************************************************************
906 * EnumFontFamiliesW (GDI32.@)
908 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
909 FONTENUMPROCW efproc, LPARAM lpData )
911 LOGFONTW lf;
913 lf.lfCharSet = DEFAULT_CHARSET;
914 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
915 else lf.lfFaceName[0] = 0;
917 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
920 /***********************************************************************
921 * EnumFonts (GDI.70)
923 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
924 LPARAM lpData )
926 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
929 /***********************************************************************
930 * EnumFontsA (GDI32.@)
932 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
933 LPARAM lpData )
935 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
938 /***********************************************************************
939 * EnumFontsW (GDI32.@)
941 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
942 LPARAM lpData )
944 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
948 /***********************************************************************
949 * GetTextCharacterExtra (GDI32.@)
951 INT WINAPI GetTextCharacterExtra( HDC hdc )
953 INT ret;
954 DC *dc = DC_GetDCPtr( hdc );
955 if (!dc) return 0x80000000;
956 ret = dc->charExtra;
957 GDI_ReleaseObj( hdc );
958 return ret;
962 /***********************************************************************
963 * SetTextCharacterExtra (GDI32.@)
965 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
967 INT prev;
968 DC * dc = DC_GetDCPtr( hdc );
969 if (!dc) return 0x80000000;
970 if (dc->funcs->pSetTextCharacterExtra)
971 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
972 else
974 prev = dc->charExtra;
975 dc->charExtra = extra;
977 GDI_ReleaseObj( hdc );
978 return prev;
982 /***********************************************************************
983 * SetTextJustification (GDI32.@)
985 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
987 BOOL ret = TRUE;
988 DC * dc = DC_GetDCPtr( hdc );
989 if (!dc) return FALSE;
990 if (dc->funcs->pSetTextJustification)
991 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
992 else
994 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
995 if (!extra) breaks = 0;
996 if (breaks)
998 dc->breakExtra = extra / breaks;
999 dc->breakRem = extra - (breaks * dc->breakExtra);
1001 else
1003 dc->breakExtra = 0;
1004 dc->breakRem = 0;
1007 GDI_ReleaseObj( hdc );
1008 return ret;
1012 /***********************************************************************
1013 * GetTextFaceA (GDI32.@)
1015 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1017 INT res = GetTextFaceW(hdc, 0, NULL);
1018 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1019 GetTextFaceW( hdc, res, nameW );
1021 if (name)
1023 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1024 name[count-1] = 0;
1025 res = strlen(name);
1027 else
1028 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1029 HeapFree( GetProcessHeap(), 0, nameW );
1030 return res;
1033 /***********************************************************************
1034 * GetTextFaceW (GDI32.@)
1036 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1038 FONTOBJ *font;
1039 INT ret = 0;
1041 DC * dc = DC_GetDCPtr( hdc );
1042 if (!dc) return 0;
1044 if(dc->gdiFont)
1045 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1046 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1048 if (name)
1050 lstrcpynW( name, font->logfont.lfFaceName, count );
1051 ret = strlenW(name);
1053 else ret = strlenW(font->logfont.lfFaceName) + 1;
1054 GDI_ReleaseObj( dc->hFont );
1056 GDI_ReleaseObj( hdc );
1057 return ret;
1061 /***********************************************************************
1062 * GetTextExtentPoint32A (GDI32.@)
1064 * See GetTextExtentPoint32W.
1066 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1067 LPSIZE size )
1069 BOOL ret = FALSE;
1070 INT wlen;
1071 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1073 if (p) {
1074 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1075 HeapFree( GetProcessHeap(), 0, p );
1078 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1079 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1080 return ret;
1084 /***********************************************************************
1085 * GetTextExtentPoint32W [GDI32.@]
1087 * Computes width/height for a string.
1089 * Computes width and height of the specified string.
1091 * RETURNS
1092 * Success: TRUE
1093 * Failure: FALSE
1095 BOOL WINAPI GetTextExtentPoint32W(
1096 HDC hdc, /* [in] Handle of device context */
1097 LPCWSTR str, /* [in] Address of text string */
1098 INT count, /* [in] Number of characters in string */
1099 LPSIZE size) /* [out] Address of structure for string size */
1101 BOOL ret = FALSE;
1102 DC * dc = DC_GetDCPtr( hdc );
1103 if (!dc) return FALSE;
1105 if(dc->gdiFont)
1106 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1107 else if(dc->funcs->pGetTextExtentPoint)
1108 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1110 if (ret)
1112 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1113 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1114 size->cx += count * dc->charExtra + dc->breakRem;
1117 GDI_ReleaseObj( hdc );
1119 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1120 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1121 return ret;
1124 /***********************************************************************
1125 * GetTextExtentPointI [GDI32.@]
1127 * Computes width and height of the array of glyph indices.
1129 * RETURNS
1130 * Success: TRUE
1131 * Failure: FALSE
1133 BOOL WINAPI GetTextExtentPointI(
1134 HDC hdc, /* [in] Handle of device context */
1135 const WORD *indices, /* [in] Address of glyph index array */
1136 INT count, /* [in] Number of glyphs in array */
1137 LPSIZE size) /* [out] Address of structure for string size */
1139 BOOL ret = FALSE;
1140 DC * dc = DC_GetDCPtr( hdc );
1141 if (!dc) return FALSE;
1143 if(dc->gdiFont) {
1144 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1145 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1146 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1147 size->cx += count * dc->charExtra;
1149 else if(dc->funcs->pGetTextExtentPoint) {
1150 FIXME("calling GetTextExtentPoint\n");
1151 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1154 GDI_ReleaseObj( hdc );
1156 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1157 hdc, indices, count, size, size->cx, size->cy );
1158 return ret;
1162 /***********************************************************************
1163 * GetTextExtentPointA (GDI32.@)
1165 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1166 LPSIZE size )
1168 TRACE("not bug compatible.\n");
1169 return GetTextExtentPoint32A( hdc, str, count, size );
1172 /***********************************************************************
1173 * GetTextExtentPointW (GDI32.@)
1175 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1176 LPSIZE size )
1178 TRACE("not bug compatible.\n");
1179 return GetTextExtentPoint32W( hdc, str, count, size );
1183 /***********************************************************************
1184 * GetTextExtentExPointA (GDI32.@)
1186 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1187 INT maxExt, LPINT lpnFit,
1188 LPINT alpDx, LPSIZE size )
1190 BOOL ret;
1191 INT wlen;
1192 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1193 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1194 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1195 HeapFree( GetProcessHeap(), 0, p );
1196 return ret;
1200 /***********************************************************************
1201 * GetTextExtentExPointW (GDI32.@)
1203 * Return the size of the string as it would be if it was output properly by
1204 * e.g. TextOut.
1206 * This should include
1207 * - Intercharacter spacing
1208 * - justification spacing (not yet done)
1209 * - kerning? see below
1211 * Kerning. Since kerning would be carried out by the rendering code it should
1212 * be done by the driver. However they don't support it yet. Also I am not
1213 * yet persuaded that (certainly under Win95) any kerning is actually done.
1215 * str: According to MSDN this should be null-terminated. That is not true; a
1216 * null will not terminate it early.
1217 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1218 * than count. I have seen it be either the size of the full string or
1219 * 1 less than the size of the full string. I have not seen it bear any
1220 * resemblance to the portion that would fit.
1221 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1222 * trailing intercharacter spacing and any trailing justification.
1224 * FIXME
1225 * Currently we do this by measuring each character etc. We should do it by
1226 * passing the request to the driver, perhaps by extending the
1227 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1228 * thinking about kerning issues and rounding issues in the justification.
1231 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1232 INT maxExt, LPINT lpnFit,
1233 LPINT alpDx, LPSIZE size )
1235 int index, nFit, extent;
1236 SIZE tSize;
1237 BOOL ret = FALSE;
1239 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1241 size->cx = size->cy = nFit = extent = 0;
1242 for(index = 0; index < count; index++)
1244 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1245 /* GetTextExtentPoint includes intercharacter spacing. */
1246 /* FIXME - justification needs doing yet. Remember that the base
1247 * data will not be in logical coordinates.
1249 extent += tSize.cx;
1250 if( !lpnFit || extent <= maxExt )
1251 /* It is allowed to be equal. */
1253 nFit++;
1254 if( alpDx ) alpDx[index] = extent;
1256 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1257 str++;
1259 size->cx = extent;
1260 if(lpnFit) *lpnFit = nFit;
1261 ret = TRUE;
1263 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1265 done:
1266 return ret;
1269 /***********************************************************************
1270 * GetTextMetricsA (GDI32.@)
1272 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1274 TEXTMETRICW tm32;
1276 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1277 FONT_TextMetricWToA( &tm32, metrics );
1278 return TRUE;
1281 /***********************************************************************
1282 * GetTextMetricsW (GDI32.@)
1284 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1286 BOOL ret = FALSE;
1287 DC * dc = DC_GetDCPtr( hdc );
1288 if (!dc) return FALSE;
1290 if (dc->gdiFont)
1291 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1292 else if (dc->funcs->pGetTextMetrics)
1293 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1295 if (ret)
1297 /* device layer returns values in device units
1298 * therefore we have to convert them to logical */
1300 #define WDPTOLP(x) ((x<0)? \
1301 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1302 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1303 #define HDPTOLP(y) ((y<0)? \
1304 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1305 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1307 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1308 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1309 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1310 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1311 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1312 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1313 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1314 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1315 ret = TRUE;
1316 #undef WDPTOLP
1317 #undef HDPTOLP
1318 TRACE("text metrics:\n"
1319 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1320 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1321 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1322 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1323 " PitchAndFamily = %02x\n"
1324 " --------------------\n"
1325 " InternalLeading = %li\n"
1326 " Ascent = %li\n"
1327 " Descent = %li\n"
1328 " Height = %li\n",
1329 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1330 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1331 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1332 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1333 metrics->tmPitchAndFamily,
1334 metrics->tmInternalLeading,
1335 metrics->tmAscent,
1336 metrics->tmDescent,
1337 metrics->tmHeight );
1339 GDI_ReleaseObj( hdc );
1340 return ret;
1344 /***********************************************************************
1345 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1347 * NOTES
1348 * lpOTM should be LPOUTLINETEXTMETRIC
1350 * RETURNS
1351 * Success: Non-zero or size of required buffer
1352 * Failure: 0
1354 UINT16 WINAPI GetOutlineTextMetrics16(
1355 HDC16 hdc, /* [in] Handle of device context */
1356 UINT16 cbData, /* [in] Size of metric data array */
1357 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1359 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1360 return 0;
1364 /***********************************************************************
1365 * GetOutlineTextMetricsA (GDI32.@)
1366 * Gets metrics for TrueType fonts.
1368 * NOTES
1369 * If the supplied buffer isn't big enough Windows partially fills it up to
1370 * its given length and returns that length.
1372 * RETURNS
1373 * Success: Non-zero or size of required buffer
1374 * Failure: 0
1376 UINT WINAPI GetOutlineTextMetricsA(
1377 HDC hdc, /* [in] Handle of device context */
1378 UINT cbData, /* [in] Size of metric data array */
1379 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1381 char buf[512], *ptr;
1382 UINT ret, needed;
1383 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1384 OUTLINETEXTMETRICA *output = lpOTM;
1385 INT left, len;
1387 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1388 return 0;
1389 if(ret > sizeof(buf))
1390 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1391 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1393 needed = sizeof(OUTLINETEXTMETRICA);
1394 if(lpOTMW->otmpFamilyName)
1395 needed += WideCharToMultiByte(CP_ACP, 0,
1396 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1397 NULL, 0, NULL, NULL);
1398 if(lpOTMW->otmpFaceName)
1399 needed += WideCharToMultiByte(CP_ACP, 0,
1400 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1401 NULL, 0, NULL, NULL);
1402 if(lpOTMW->otmpStyleName)
1403 needed += WideCharToMultiByte(CP_ACP, 0,
1404 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1405 NULL, 0, NULL, NULL);
1406 if(lpOTMW->otmpFullName)
1407 needed += WideCharToMultiByte(CP_ACP, 0,
1408 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1409 NULL, 0, NULL, NULL);
1411 if(!lpOTM) {
1412 ret = needed;
1413 goto end;
1416 TRACE("needed = %d\n", needed);
1417 if(needed > cbData)
1418 /* Since the supplied buffer isn't big enough, we'll alloc one
1419 that is and memcpy the first cbData bytes into the lpOTM at
1420 the end. */
1421 output = HeapAlloc(GetProcessHeap(), 0, needed);
1423 ret = output->otmSize = min(needed, cbData);
1424 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1425 output->otmFiller = 0;
1426 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1427 output->otmfsSelection = lpOTMW->otmfsSelection;
1428 output->otmfsType = lpOTMW->otmfsType;
1429 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1430 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1431 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1432 output->otmEMSquare = lpOTMW->otmEMSquare;
1433 output->otmAscent = lpOTMW->otmAscent;
1434 output->otmDescent = lpOTMW->otmDescent;
1435 output->otmLineGap = lpOTMW->otmLineGap;
1436 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1437 output->otmsXHeight = lpOTMW->otmsXHeight;
1438 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1439 output->otmMacAscent = lpOTMW->otmMacAscent;
1440 output->otmMacDescent = lpOTMW->otmMacDescent;
1441 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1442 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1443 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1444 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1445 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1446 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1447 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1448 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1449 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1450 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1453 ptr = (char*)(output + 1);
1454 left = needed - sizeof(*output);
1456 if(lpOTMW->otmpFamilyName) {
1457 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1458 len = WideCharToMultiByte(CP_ACP, 0,
1459 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1460 ptr, left, NULL, NULL);
1461 left -= len;
1462 ptr += len;
1463 } else
1464 output->otmpFamilyName = 0;
1466 if(lpOTMW->otmpFaceName) {
1467 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1468 len = WideCharToMultiByte(CP_ACP, 0,
1469 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1470 ptr, left, NULL, NULL);
1471 left -= len;
1472 ptr += len;
1473 } else
1474 output->otmpFaceName = 0;
1476 if(lpOTMW->otmpStyleName) {
1477 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1478 len = WideCharToMultiByte(CP_ACP, 0,
1479 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1480 ptr, left, NULL, NULL);
1481 left -= len;
1482 ptr += len;
1483 } else
1484 output->otmpStyleName = 0;
1486 if(lpOTMW->otmpFullName) {
1487 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1488 len = WideCharToMultiByte(CP_ACP, 0,
1489 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1490 ptr, left, NULL, NULL);
1491 left -= len;
1492 } else
1493 output->otmpFullName = 0;
1495 assert(left == 0);
1497 if(output != lpOTM) {
1498 memcpy(lpOTM, output, cbData);
1499 HeapFree(GetProcessHeap(), 0, output);
1502 end:
1503 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1504 HeapFree(GetProcessHeap(), 0, lpOTMW);
1506 return ret;
1510 /***********************************************************************
1511 * GetOutlineTextMetricsW [GDI32.@]
1513 UINT WINAPI GetOutlineTextMetricsW(
1514 HDC hdc, /* [in] Handle of device context */
1515 UINT cbData, /* [in] Size of metric data array */
1516 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1518 DC *dc = DC_GetDCPtr( hdc );
1519 OUTLINETEXTMETRICW *output = lpOTM;
1520 UINT ret;
1522 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1523 if(!dc) return 0;
1525 if(dc->gdiFont) {
1526 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1527 if(lpOTM && ret) {
1528 if(ret > cbData) {
1529 output = HeapAlloc(GetProcessHeap(), 0, ret);
1530 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1533 #define WDPTOLP(x) ((x<0)? \
1534 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1535 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1536 #define HDPTOLP(y) ((y<0)? \
1537 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1538 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1540 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1541 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1542 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1543 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1544 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1545 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1546 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1547 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1548 output->otmAscent = HDPTOLP(output->otmAscent);
1549 output->otmDescent = HDPTOLP(output->otmDescent);
1550 output->otmLineGap = HDPTOLP(output->otmLineGap);
1551 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1552 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1553 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1554 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1555 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1556 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1557 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1558 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1559 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1560 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1561 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1562 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1563 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1564 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1565 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1566 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1567 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1568 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1569 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1570 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1571 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1572 #undef WDPTOLP
1573 #undef HDPTOLP
1574 if(output != lpOTM) {
1575 memcpy(lpOTM, output, cbData);
1576 HeapFree(GetProcessHeap(), 0, output);
1577 ret = cbData;
1582 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1583 but really this should just be a return 0. */
1585 ret = sizeof(*lpOTM);
1586 if (lpOTM) {
1587 if(cbData < ret)
1588 ret = 0;
1589 else {
1590 memset(lpOTM, 0, ret);
1591 lpOTM->otmSize = sizeof(*lpOTM);
1592 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1594 Further fill of the structure not implemented,
1595 Needs real values for the structure members
1600 GDI_ReleaseObj(hdc);
1601 return ret;
1605 /***********************************************************************
1606 * GetCharWidthW (GDI32.@)
1607 * GetCharWidth32W (GDI32.@)
1609 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1610 LPINT buffer )
1612 UINT i;
1613 BOOL ret = FALSE;
1614 DC * dc = DC_GetDCPtr( hdc );
1615 if (!dc) return FALSE;
1617 if (dc->gdiFont)
1618 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1619 else if (dc->funcs->pGetCharWidth)
1620 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1622 if (ret)
1624 /* convert device units to logical */
1625 for( i = firstChar; i <= lastChar; i++, buffer++ )
1626 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1627 ret = TRUE;
1629 GDI_ReleaseObj( hdc );
1630 return ret;
1634 /***********************************************************************
1635 * GetCharWidthA (GDI32.@)
1636 * GetCharWidth32A (GDI32.@)
1638 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1639 LPINT buffer )
1641 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1642 LPSTR str;
1643 LPWSTR wstr;
1644 BOOL ret = TRUE;
1646 if(count <= 0) return FALSE;
1648 str = HeapAlloc(GetProcessHeap(), 0, count);
1649 for(i = 0; i < count; i++)
1650 str[i] = (BYTE)(firstChar + i);
1652 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1654 for(i = 0; i < wlen; i++)
1656 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1658 ret = FALSE;
1659 break;
1661 buffer++;
1664 HeapFree(GetProcessHeap(), 0, str);
1665 HeapFree(GetProcessHeap(), 0, wstr);
1667 return ret;
1671 /***********************************************************************
1672 * ExtTextOutA (GDI32.@)
1674 * See ExtTextOutW.
1676 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1677 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1679 INT wlen;
1680 UINT codepage;
1681 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1682 BOOL ret;
1683 LPINT lpDxW = NULL;
1685 if (lpDx) {
1686 unsigned int i = 0, j = 0;
1688 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1689 while(i < count) {
1690 if(IsDBCSLeadByteEx(codepage, str[i])) {
1691 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1692 i = i + 2;
1693 } else {
1694 lpDxW[j++] = lpDx[i];
1695 i = i + 1;
1700 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1702 HeapFree( GetProcessHeap(), 0, p );
1703 HeapFree( GetProcessHeap(), 0, lpDxW );
1704 return ret;
1708 /***********************************************************************
1709 * ExtTextOutW (GDI32.@)
1711 * Draws text using the currently selected font, background color, and text color.
1714 * PARAMS
1715 * x,y [I] coordinates of string
1716 * flags [I]
1717 * ETO_GRAYED - undocumented on MSDN
1718 * ETO_OPAQUE - use background color for fill the rectangle
1719 * ETO_CLIPPED - clipping text to the rectangle
1720 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1721 * than encoded characters. Implies ETO_IGNORELANGUAGE
1722 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1723 * Affects BiDi ordering
1724 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1725 * ETO_PDY - unimplemented
1726 * ETO_NUMERICSLATIN - unimplemented always assumed -
1727 * do not translate numbers into locale representations
1728 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1729 * lprect [I] dimensions for clipping or/and opaquing
1730 * str [I] text string
1731 * count [I] number of symbols in string
1732 * lpDx [I] optional parameter with distance between drawing characters
1734 * RETURNS
1735 * Success: TRUE
1736 * Failure: FALSE
1738 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1739 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1741 BOOL ret = FALSE;
1742 LPWSTR reordered_str = (LPWSTR)str;
1743 WORD *glyphs = NULL;
1744 UINT align = GetTextAlign( hdc );
1745 POINT pt;
1746 TEXTMETRICW tm;
1747 LOGFONTW lf;
1748 double cosEsc, sinEsc;
1749 INT *deltas = NULL, char_extra;
1750 SIZE sz;
1751 RECT rc;
1752 BOOL done_extents = FALSE;
1753 INT width, xwidth = 0, ywidth = 0;
1754 DWORD type;
1755 DC * dc = DC_GetDCUpdate( hdc );
1757 if (!dc) return FALSE;
1759 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1760 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1762 if(PATH_IsPathOpen(dc->path))
1764 FIXME("called on an open path\n");
1765 GDI_ReleaseObj( hdc );
1766 return ret;
1769 if(!dc->funcs->pExtTextOut)
1771 GDI_ReleaseObj( hdc );
1772 return ret;
1775 type = GetObjectType(hdc);
1776 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1778 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1779 GDI_ReleaseObj( hdc );
1780 return ret;
1783 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1785 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1787 BIDI_Reorder( str, count, GCP_REORDER,
1788 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1789 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1790 reordered_str, count, NULL );
1792 flags |= ETO_IGNORELANGUAGE;
1795 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1796 lprect, debugstr_wn(str, count), count, lpDx);
1798 if(flags & ETO_GLYPH_INDEX)
1799 glyphs = reordered_str;
1801 if(lprect)
1802 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1803 lprect->bottom);
1804 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1806 if(align & TA_UPDATECP)
1808 GetCurrentPositionEx( hdc, &pt );
1809 x = pt.x;
1810 y = pt.y;
1813 GetTextMetricsW(hdc, &tm);
1814 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1816 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1817 lf.lfEscapement = 0;
1819 if(lf.lfEscapement != 0)
1821 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1822 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1824 else
1826 cosEsc = 1;
1827 sinEsc = 0;
1830 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1832 if(!lprect)
1834 if(flags & ETO_CLIPPED) goto done;
1835 if(flags & ETO_GLYPH_INDEX)
1836 GetTextExtentPointI(hdc, glyphs, count, &sz);
1837 else
1838 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1840 done_extents = TRUE;
1841 rc.left = x;
1842 rc.top = y;
1843 rc.right = x + sz.cx;
1844 rc.bottom = y + sz.cy;
1846 else
1848 rc = *lprect;
1851 LPtoDP(hdc, (POINT*)&rc, 2);
1853 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1854 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1857 if(flags & ETO_OPAQUE)
1858 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1860 if(count == 0)
1862 ret = TRUE;
1863 goto done;
1866 pt.x = x;
1867 pt.y = y;
1868 LPtoDP(hdc, &pt, 1);
1869 x = pt.x;
1870 y = pt.y;
1872 char_extra = GetTextCharacterExtra(hdc);
1873 width = 0;
1874 if(char_extra || dc->breakExtra || lpDx)
1876 UINT i;
1877 SIZE tmpsz;
1878 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1879 for(i = 0; i < count; i++)
1881 if(lpDx)
1882 deltas[i] = lpDx[i] + char_extra;
1883 else
1885 if(flags & ETO_GLYPH_INDEX)
1886 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1887 else
1888 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1890 deltas[i] = tmpsz.cx;
1893 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1895 deltas[i] = deltas[i] + dc->breakExtra;
1897 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1898 width += deltas[i];
1901 else
1903 if(!done_extents)
1905 if(flags & ETO_GLYPH_INDEX)
1906 GetTextExtentPointI(hdc, glyphs, count, &sz);
1907 else
1908 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1909 done_extents = TRUE;
1911 width = INTERNAL_XWSTODS(dc, sz.cx);
1913 xwidth = width * cosEsc;
1914 ywidth = width * sinEsc;
1916 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1917 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1918 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1920 case TA_LEFT:
1921 if (align & TA_UPDATECP)
1923 pt.x = x + xwidth;
1924 pt.y = y - ywidth;
1925 DPtoLP(hdc, &pt, 1);
1926 MoveToEx(hdc, pt.x, pt.y, NULL);
1928 break;
1930 case TA_CENTER:
1931 x -= xwidth / 2;
1932 y += ywidth / 2;
1933 break;
1935 case TA_RIGHT:
1936 x -= xwidth;
1937 y += ywidth;
1938 if (align & TA_UPDATECP)
1940 pt.x = x;
1941 pt.y = y;
1942 DPtoLP(hdc, &pt, 1);
1943 MoveToEx(hdc, pt.x, pt.y, NULL);
1945 break;
1948 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1950 case TA_TOP:
1951 y += tm.tmAscent * cosEsc;
1952 x += tm.tmAscent * sinEsc;
1953 break;
1955 case TA_BOTTOM:
1956 y -= tm.tmDescent * cosEsc;
1957 x -= tm.tmDescent * sinEsc;
1958 break;
1960 case TA_BASELINE:
1961 break;
1964 if(GetBkMode(hdc) != TRANSPARENT)
1966 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1968 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1969 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1971 RECT rc;
1972 rc.left = x;
1973 rc.right = x + width;
1974 rc.top = y - tm.tmAscent;
1975 rc.bottom = y + tm.tmDescent;
1976 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1981 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1983 HFONT orig_font = dc->hFont, cur_font;
1984 UINT glyph;
1985 INT span = 0, *offsets = NULL, i;
1987 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1988 for(i = 0; i < count; i++)
1990 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1991 if(cur_font != dc->hFont)
1993 if(!offsets)
1995 int j;
1996 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1997 offsets[0] = 0;
1998 if(!deltas)
2000 SIZE tmpsz;
2001 for(j = 1; j < count; j++)
2003 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2004 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2007 else
2009 for(j = 1; j < count; j++)
2010 offsets[j] = offsets[j-1] + deltas[j];
2013 if(span)
2015 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2016 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2017 glyphs, span, deltas ? deltas + i - span : NULL);
2018 span = 0;
2020 SelectObject(hdc, cur_font);
2022 glyphs[span++] = glyph;
2024 if(i == count - 1)
2026 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2027 y - (offsets ? offsets[count - span] * sinEsc : 0),
2028 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2029 glyphs, span, deltas ? deltas + count - span : NULL);
2030 SelectObject(hdc, orig_font);
2031 HeapFree(GetProcessHeap(), 0, offsets);
2035 else
2037 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2039 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2040 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2041 flags |= ETO_GLYPH_INDEX;
2043 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2044 glyphs ? glyphs : reordered_str, count, deltas);
2047 done:
2048 HeapFree(GetProcessHeap(), 0, deltas);
2049 if(glyphs != reordered_str)
2050 HeapFree(GetProcessHeap(), 0, glyphs);
2051 if(reordered_str != str)
2052 HeapFree(GetProcessHeap(), 0, reordered_str);
2054 GDI_ReleaseObj( hdc );
2056 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2058 int underlinePos, strikeoutPos;
2059 int underlineWidth, strikeoutWidth;
2060 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2061 OUTLINETEXTMETRICW* otm = NULL;
2063 if(!size)
2065 underlinePos = 0;
2066 underlineWidth = tm.tmAscent / 20 + 1;
2067 strikeoutPos = tm.tmAscent / 2;
2068 strikeoutWidth = underlineWidth;
2070 else
2072 otm = HeapAlloc(GetProcessHeap(), 0, size);
2073 GetOutlineTextMetricsW(hdc, size, otm);
2074 underlinePos = otm->otmsUnderscorePosition;
2075 underlineWidth = otm->otmsUnderscoreSize;
2076 strikeoutPos = otm->otmsStrikeoutPosition;
2077 strikeoutWidth = otm->otmsStrikeoutSize;
2078 HeapFree(GetProcessHeap(), 0, otm);
2081 if (PATH_IsPathOpen(dc->path))
2083 POINT pts[5];
2084 HPEN hpen;
2085 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2087 hbrush = SelectObject(hdc, hbrush);
2088 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2090 if (lf.lfUnderline)
2092 pts[0].x = x - underlinePos * sinEsc;
2093 pts[0].y = y - underlinePos * cosEsc;
2094 pts[1].x = x + xwidth - underlinePos * sinEsc;
2095 pts[1].y = y - ywidth - underlinePos * cosEsc;
2096 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2097 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2098 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2099 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2100 pts[4].x = pts[0].x;
2101 pts[4].y = pts[0].y;
2102 DPtoLP(hdc, pts, 5);
2103 Polygon(hdc, pts, 5);
2106 if (lf.lfStrikeOut)
2108 pts[0].x = x - strikeoutPos * sinEsc;
2109 pts[0].y = y - strikeoutPos * cosEsc;
2110 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2111 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2112 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2113 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2114 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2115 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2116 pts[4].x = pts[0].x;
2117 pts[4].y = pts[0].y;
2118 DPtoLP(hdc, pts, 5);
2119 Polygon(hdc, pts, 5);
2122 SelectObject(hdc, hpen);
2123 hbrush = SelectObject(hdc, hbrush);
2124 DeleteObject(hbrush);
2126 else
2128 POINT pts[2], oldpt;
2129 HPEN hpen;
2131 if (lf.lfUnderline)
2133 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2134 hpen = SelectObject(hdc, hpen);
2135 pts[0].x = x;
2136 pts[0].y = y;
2137 pts[1].x = x + xwidth;
2138 pts[1].y = y - ywidth;
2139 DPtoLP(hdc, pts, 2);
2140 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2141 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2142 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2143 DeleteObject(SelectObject(hdc, hpen));
2146 if (lf.lfStrikeOut)
2148 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2149 hpen = SelectObject(hdc, hpen);
2150 pts[0].x = x;
2151 pts[0].y = y;
2152 pts[1].x = x + xwidth;
2153 pts[1].y = y - ywidth;
2154 DPtoLP(hdc, pts, 2);
2155 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2156 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2157 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2158 DeleteObject(SelectObject(hdc, hpen));
2163 return ret;
2167 /***********************************************************************
2168 * TextOutA (GDI32.@)
2170 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2172 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2176 /***********************************************************************
2177 * TextOutW (GDI32.@)
2179 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2181 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2185 /***********************************************************************
2186 * PolyTextOutA (GDI32.@)
2188 * See PolyTextOutW.
2190 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2191 PPOLYTEXTA pptxt, /* [in] Array of strings */
2192 INT cStrings ) /* [in] Number of strings in array */
2194 for (; cStrings>0; cStrings--, pptxt++)
2195 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2196 return FALSE;
2197 return TRUE;
2202 /***********************************************************************
2203 * PolyTextOutW (GDI32.@)
2205 * Draw several Strings
2207 * RETURNS
2208 * TRUE: Success.
2209 * FALSE: Failure.
2211 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2212 PPOLYTEXTW pptxt, /* [in] Array of strings */
2213 INT cStrings ) /* [in] Number of strings in array */
2215 for (; cStrings>0; cStrings--, pptxt++)
2216 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2217 return FALSE;
2218 return TRUE;
2222 /* FIXME: all following APIs ******************************************/
2225 /***********************************************************************
2226 * SetMapperFlags (GDI32.@)
2228 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2230 DC *dc = DC_GetDCPtr( hDC );
2231 DWORD ret = 0;
2232 if(!dc) return 0;
2233 if(dc->funcs->pSetMapperFlags)
2235 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2236 /* FIXME: ret is just a success flag, we should return a proper value */
2238 else
2239 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2240 GDI_ReleaseObj( hDC );
2241 return ret;
2244 /***********************************************************************
2245 * GetAspectRatioFilterEx (GDI.486)
2247 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2249 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2250 return FALSE;
2253 /***********************************************************************
2254 * GetAspectRatioFilterEx (GDI32.@)
2256 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2258 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2259 return FALSE;
2263 /***********************************************************************
2264 * GetCharABCWidthsA (GDI32.@)
2266 * See GetCharABCWidthsW.
2268 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2269 LPABC abc )
2271 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2272 LPSTR str;
2273 LPWSTR wstr;
2274 BOOL ret = TRUE;
2276 if(count <= 0) return FALSE;
2278 str = HeapAlloc(GetProcessHeap(), 0, count);
2279 for(i = 0; i < count; i++)
2280 str[i] = (BYTE)(firstChar + i);
2282 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2284 for(i = 0; i < wlen; i++)
2286 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2288 ret = FALSE;
2289 break;
2291 abc++;
2294 HeapFree(GetProcessHeap(), 0, str);
2295 HeapFree(GetProcessHeap(), 0, wstr);
2297 return ret;
2301 /******************************************************************************
2302 * GetCharABCWidthsW [GDI32.@]
2304 * Retrieves widths of characters in range.
2306 * PARAMS
2307 * hdc [I] Handle of device context
2308 * firstChar [I] First character in range to query
2309 * lastChar [I] Last character in range to query
2310 * abc [O] Address of character-width structure
2312 * NOTES
2313 * Only works with TrueType fonts
2315 * RETURNS
2316 * Success: TRUE
2317 * Failure: FALSE
2319 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2320 LPABC abc )
2322 DC *dc = DC_GetDCPtr(hdc);
2323 unsigned int i;
2324 BOOL ret = FALSE;
2326 if(dc->gdiFont)
2327 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2328 else
2329 FIXME(": stub\n");
2331 if (ret)
2333 /* convert device units to logical */
2334 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2335 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2336 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2337 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2339 ret = TRUE;
2342 GDI_ReleaseObj(hdc);
2343 return ret;
2347 /***********************************************************************
2348 * GetGlyphOutlineA (GDI32.@)
2350 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2351 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2352 LPVOID lpBuffer, const MAT2 *lpmat2 )
2354 LPWSTR p = NULL;
2355 DWORD ret;
2356 UINT c;
2358 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2359 int len;
2360 char mbchs[2];
2361 if(uChar > 0xff) { /* but, 2 bytes character only */
2362 len = 2;
2363 mbchs[0] = (uChar & 0xff00) >> 8;
2364 mbchs[1] = (uChar & 0xff);
2365 } else {
2366 len = 1;
2367 mbchs[0] = (uChar & 0xff);
2369 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2370 c = p[0];
2371 } else
2372 c = uChar;
2373 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2374 lpmat2);
2375 HeapFree(GetProcessHeap(), 0, p);
2376 return ret;
2379 /***********************************************************************
2380 * GetGlyphOutlineW (GDI32.@)
2382 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2383 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2384 LPVOID lpBuffer, const MAT2 *lpmat2 )
2386 DC *dc = DC_GetDCPtr(hdc);
2387 DWORD ret;
2389 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2390 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2392 if(!dc) return GDI_ERROR;
2394 if(dc->gdiFont)
2395 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2396 cbBuffer, lpBuffer, lpmat2);
2397 else
2398 ret = GDI_ERROR;
2400 GDI_ReleaseObj(hdc);
2401 return ret;
2405 /***********************************************************************
2406 * CreateScalableFontResourceA (GDI32.@)
2408 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2409 LPCSTR lpszResourceFile,
2410 LPCSTR lpszFontFile,
2411 LPCSTR lpszCurrentPath )
2413 HANDLE f;
2415 /* fHidden=1 - only visible for the calling app, read-only, not
2416 * enumbered with EnumFonts/EnumFontFamilies
2417 * lpszCurrentPath can be NULL
2419 FIXME("(%ld,%s,%s,%s): stub\n",
2420 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2421 debugstr_a(lpszCurrentPath) );
2423 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2424 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2425 CloseHandle(f);
2426 SetLastError(ERROR_FILE_EXISTS);
2427 return FALSE;
2429 return FALSE; /* create failed */
2432 /***********************************************************************
2433 * CreateScalableFontResourceW (GDI32.@)
2435 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2436 LPCWSTR lpszResourceFile,
2437 LPCWSTR lpszFontFile,
2438 LPCWSTR lpszCurrentPath )
2440 FIXME("(%ld,%p,%p,%p): stub\n",
2441 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2442 return FALSE; /* create failed */
2445 /*************************************************************************
2446 * GetKerningPairsA (GDI32.@)
2448 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2449 LPKERNINGPAIR lpKerningPairs )
2451 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2455 /*************************************************************************
2456 * GetKerningPairsW (GDI32.@)
2458 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2459 LPKERNINGPAIR lpKerningPairs )
2461 unsigned int i;
2462 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2463 for (i = 0; i < cPairs; i++)
2464 lpKerningPairs[i].iKernAmount = 0;
2465 return 0;
2468 /*************************************************************************
2469 * TranslateCharsetInfo [GDI32.@]
2471 * Fills a CHARSETINFO structure for a character set, code page, or
2472 * font. This allows making the correspondance between different labelings
2473 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2474 * of the same encoding.
2476 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2477 * only one codepage should be set in *lpSrc.
2479 * RETURNS
2480 * TRUE on success, FALSE on failure.
2483 BOOL WINAPI TranslateCharsetInfo(
2484 LPDWORD lpSrc, /* [in]
2485 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2486 if flags == TCI_SRCCHARSET: a character set value
2487 if flags == TCI_SRCCODEPAGE: a code page value
2489 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2490 DWORD flags /* [in] determines interpretation of lpSrc */)
2492 int index = 0;
2493 switch (flags) {
2494 case TCI_SRCFONTSIG:
2495 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2496 break;
2497 case TCI_SRCCODEPAGE:
2498 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2499 break;
2500 case TCI_SRCCHARSET:
2501 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2502 break;
2503 default:
2504 return FALSE;
2506 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2507 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2508 return TRUE;
2511 /*************************************************************************
2512 * GetFontLanguageInfo (GDI32.@)
2514 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2516 FONTSIGNATURE fontsig;
2517 static const DWORD GCP_DBCS_MASK=0x003F0000,
2518 GCP_DIACRITIC_MASK=0x00000000,
2519 FLI_GLYPHS_MASK=0x00000000,
2520 GCP_GLYPHSHAPE_MASK=0x00000040,
2521 GCP_KASHIDA_MASK=0x00000000,
2522 GCP_LIGATE_MASK=0x00000000,
2523 GCP_USEKERNING_MASK=0x00000000,
2524 GCP_REORDER_MASK=0x00000060;
2526 DWORD result=0;
2528 GetTextCharsetInfo( hdc, &fontsig, 0 );
2529 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2531 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2532 result|=GCP_DBCS;
2534 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2535 result|=GCP_DIACRITIC;
2537 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2538 result|=FLI_GLYPHS;
2540 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2541 result|=GCP_GLYPHSHAPE;
2543 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2544 result|=GCP_KASHIDA;
2546 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2547 result|=GCP_LIGATE;
2549 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2550 result|=GCP_USEKERNING;
2552 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2553 if( GetTextAlign( hdc) & TA_RTLREADING )
2554 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2555 result|=GCP_REORDER;
2557 return result;
2561 /*************************************************************************
2562 * GetFontData [GDI32.@]
2564 * Retrieve data for TrueType font.
2566 * RETURNS
2568 * success: Number of bytes returned
2569 * failure: GDI_ERROR
2571 * NOTES
2573 * Calls SetLastError()
2576 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2577 LPVOID buffer, DWORD length)
2579 DC *dc = DC_GetDCPtr(hdc);
2580 DWORD ret = GDI_ERROR;
2582 if(!dc) return GDI_ERROR;
2584 if(dc->gdiFont)
2585 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2587 GDI_ReleaseObj(hdc);
2588 return ret;
2591 /*************************************************************************
2592 * GetGlyphIndicesA [GDI32.@]
2594 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2595 LPWORD pgi, DWORD flags)
2597 DWORD ret;
2598 WCHAR *lpstrW;
2599 INT countW;
2601 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2602 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2604 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2605 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2606 HeapFree(GetProcessHeap(), 0, lpstrW);
2608 return ret;
2611 /*************************************************************************
2612 * GetGlyphIndicesW [GDI32.@]
2614 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2615 LPWORD pgi, DWORD flags)
2617 DC *dc = DC_GetDCPtr(hdc);
2618 DWORD ret = GDI_ERROR;
2620 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2621 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2623 if(!dc) return GDI_ERROR;
2625 if(dc->gdiFont)
2626 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2628 GDI_ReleaseObj(hdc);
2629 return ret;
2632 /*************************************************************************
2633 * GetCharacterPlacementA [GDI32.@]
2635 * See GetCharacterPlacementW.
2637 * NOTES:
2638 * the web browser control of ie4 calls this with dwFlags=0
2640 DWORD WINAPI
2641 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2642 INT nMaxExtent, GCP_RESULTSA *lpResults,
2643 DWORD dwFlags)
2645 WCHAR *lpStringW;
2646 INT uCountW;
2647 GCP_RESULTSW resultsW;
2648 DWORD ret;
2649 UINT font_cp;
2651 TRACE("%s, %d, %d, 0x%08lx\n",
2652 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2654 /* both structs are equal in size */
2655 memcpy(&resultsW, lpResults, sizeof(resultsW));
2657 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2658 if(lpResults->lpOutString)
2659 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2661 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2663 if(lpResults->lpOutString) {
2664 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2665 lpResults->lpOutString, uCount, NULL, NULL );
2668 HeapFree(GetProcessHeap(), 0, lpStringW);
2669 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2671 return ret;
2674 /*************************************************************************
2675 * GetCharacterPlacementW [GDI32.@]
2677 * Retrieve information about a string. This includes the width, reordering,
2678 * Glyphing and so on.
2680 * RETURNS
2682 * The width and height of the string if successful, 0 if failed.
2684 * BUGS
2686 * All flags except GCP_REORDER are not yet implemented.
2687 * Reordering is not 100% complient to the Windows BiDi method.
2688 * Caret positioning is not yet implemented for BiDi.
2689 * Classes are not yet implemented.
2692 DWORD WINAPI
2693 GetCharacterPlacementW(
2694 HDC hdc, /* [in] Device context for which the rendering is to be done */
2695 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2696 INT uCount, /* [in] Number of WORDS in string. */
2697 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2698 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2699 DWORD dwFlags /* [in] Flags specifying how to process the string */
2702 DWORD ret=0;
2703 SIZE size;
2704 UINT i, nSet;
2706 TRACE("%s, %d, %d, 0x%08lx\n",
2707 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2709 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2710 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2711 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2712 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2713 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2715 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2716 if(lpResults->lpClass) FIXME("classes not implemented\n");
2717 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2718 FIXME("Caret positions for complex scripts not implemented\n");
2720 nSet = (UINT)uCount;
2721 if(nSet > lpResults->nGlyphs)
2722 nSet = lpResults->nGlyphs;
2724 /* return number of initialized fields */
2725 lpResults->nGlyphs = nSet;
2727 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2729 /* Treat the case where no special handling was requested in a fastpath way */
2730 /* copy will do if the GCP_REORDER flag is not set */
2731 if(lpResults->lpOutString)
2732 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2734 if(lpResults->lpOrder)
2736 for(i = 0; i < nSet; i++)
2737 lpResults->lpOrder[i] = i;
2739 } else
2741 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2742 nSet, lpResults->lpOrder );
2745 /* FIXME: Will use the placement chars */
2746 if (lpResults->lpDx)
2748 int c;
2749 for (i = 0; i < nSet; i++)
2751 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2752 lpResults->lpDx[i]= c;
2756 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2758 int pos = 0;
2760 lpResults->lpCaretPos[0] = 0;
2761 for (i = 1; i < nSet; i++)
2762 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2763 lpResults->lpCaretPos[i] = (pos += size.cx);
2766 if(lpResults->lpGlyphs)
2767 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2769 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2770 ret = MAKELONG(size.cx, size.cy);
2772 return ret;
2775 /*************************************************************************
2776 * GetCharABCWidthsFloatA [GDI32.@]
2778 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2779 LPABCFLOAT lpABCF)
2781 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2782 return 0;
2785 /*************************************************************************
2786 * GetCharABCWidthsFloatW [GDI32.@]
2788 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2789 UINT iLastChar, LPABCFLOAT lpABCF)
2791 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2792 return 0;
2795 /*************************************************************************
2796 * GetCharWidthFloatA [GDI32.@]
2798 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2799 UINT iLastChar, PFLOAT pxBuffer)
2801 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2802 return 0;
2805 /*************************************************************************
2806 * GetCharWidthFloatW [GDI32.@]
2808 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2809 UINT iLastChar, PFLOAT pxBuffer)
2811 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2812 return 0;
2816 /***********************************************************************
2818 * Font Resource API *
2820 ***********************************************************************/
2822 /***********************************************************************
2823 * AddFontResourceA (GDI32.@)
2825 INT WINAPI AddFontResourceA( LPCSTR str )
2827 return AddFontResourceExA( str, 0, NULL);
2830 /***********************************************************************
2831 * AddFontResourceW (GDI32.@)
2833 INT WINAPI AddFontResourceW( LPCWSTR str )
2835 return AddFontResourceExW(str, 0, NULL);
2839 /***********************************************************************
2840 * AddFontResourceExA (GDI32.@)
2842 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2844 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2845 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2846 INT ret;
2848 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2849 ret = AddFontResourceExW(strW, fl, pdv);
2850 HeapFree(GetProcessHeap(), 0, strW);
2851 return ret;
2854 /***********************************************************************
2855 * AddFontResourceExW (GDI32.@)
2857 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2859 return WineEngAddFontResourceEx(str, fl, pdv);
2862 /***********************************************************************
2863 * RemoveFontResourceA (GDI32.@)
2865 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2867 return RemoveFontResourceExA(str, 0, 0);
2870 /***********************************************************************
2871 * RemoveFontResourceW (GDI32.@)
2873 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2875 return RemoveFontResourceExW(str, 0, 0);
2878 /***********************************************************************
2879 * RemoveFontResourceExA (GDI32.@)
2881 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2883 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2884 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2885 INT ret;
2887 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2888 ret = RemoveFontResourceExW(strW, fl, pdv);
2889 HeapFree(GetProcessHeap(), 0, strW);
2890 return ret;
2893 /***********************************************************************
2894 * RemoveFontResourceExW (GDI32.@)
2896 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2898 return WineEngRemoveFontResourceEx(str, fl, pdv);
2901 /***********************************************************************
2902 * GetTextCharset (GDI32.@)
2904 UINT WINAPI GetTextCharset(HDC hdc)
2906 /* MSDN docs say this is equivalent */
2907 return GetTextCharsetInfo(hdc, NULL, 0);
2910 /***********************************************************************
2911 * GetTextCharsetInfo (GDI32.@)
2913 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2915 UINT ret = DEFAULT_CHARSET;
2916 DC *dc = DC_GetDCPtr(hdc);
2918 if (!dc) goto done;
2920 if (dc->gdiFont)
2921 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2923 GDI_ReleaseObj(hdc);
2925 done:
2926 if (ret == DEFAULT_CHARSET && fs)
2927 memset(fs, 0, sizeof(FONTSIGNATURE));
2928 return ret;
2931 /***********************************************************************
2932 * GdiGetCharDimensions (GDI32.@)
2934 * Gets the average width of the characters in the English alphabet.
2936 * PARAMS
2937 * hdc [I] Handle to the device context to measure on.
2938 * lptm [O] Pointer to memory to store the text metrics into.
2939 * height [O] On exit, the maximum height of characters in the English alphabet.
2941 * RETURNS
2942 * The average width of characters in the English alphabet.
2944 * NOTES
2945 * This function is used by the dialog manager to get the size of a dialog
2946 * unit. It should also be used by other pieces of code that need to know
2947 * the size of a dialog unit in logical units without having access to the
2948 * window handle of the dialog.
2949 * Windows caches the font metrics from this function, but we don't and
2950 * there doesn't appear to be an immediate advantage to do so.
2952 * SEE ALSO
2953 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
2955 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
2957 SIZE sz;
2958 static const WCHAR alphabet[] = {
2959 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2960 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2961 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2963 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
2965 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
2967 if (height) *height = sz.cy;
2968 return (sz.cx / 26 + 1) / 2;
2971 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
2973 FIXME("(%d): stub\n", fEnableEUDC);
2974 return FALSE;