Draw underline and strikeout for ExtTextOut on an open path using
[wine/wine64.git] / dlls / gdi / font.c
blob3ccc1aaf372e1f765f3dafd1cc329822fd492577
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 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1065 LPSIZE size )
1067 BOOL ret = FALSE;
1068 INT wlen;
1069 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1071 if (p) {
1072 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1073 HeapFree( GetProcessHeap(), 0, p );
1076 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1077 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1078 return ret;
1082 /***********************************************************************
1083 * GetTextExtentPoint32W [GDI32.@]
1085 * Computes width/height for a string.
1087 * Computes width and height of the specified string.
1089 * RETURNS
1090 * Success: TRUE
1091 * Failure: FALSE
1093 BOOL WINAPI GetTextExtentPoint32W(
1094 HDC hdc, /* [in] Handle of device context */
1095 LPCWSTR str, /* [in] Address of text string */
1096 INT count, /* [in] Number of characters in string */
1097 LPSIZE size) /* [out] Address of structure for string size */
1099 BOOL ret = FALSE;
1100 DC * dc = DC_GetDCPtr( hdc );
1101 if (!dc) return FALSE;
1103 if(dc->gdiFont)
1104 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1105 else if(dc->funcs->pGetTextExtentPoint)
1106 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1108 if (ret)
1110 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1111 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1112 size->cx += count * dc->charExtra + dc->breakRem;
1115 GDI_ReleaseObj( hdc );
1117 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1118 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1119 return ret;
1122 /***********************************************************************
1123 * GetTextExtentPointI [GDI32.@]
1125 * Computes width and height of the array of glyph indices.
1127 * RETURNS
1128 * Success: TRUE
1129 * Failure: FALSE
1131 BOOL WINAPI GetTextExtentPointI(
1132 HDC hdc, /* [in] Handle of device context */
1133 const WORD *indices, /* [in] Address of glyph index array */
1134 INT count, /* [in] Number of glyphs in array */
1135 LPSIZE size) /* [out] Address of structure for string size */
1137 BOOL ret = FALSE;
1138 DC * dc = DC_GetDCPtr( hdc );
1139 if (!dc) return FALSE;
1141 if(dc->gdiFont) {
1142 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1143 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1144 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1145 size->cx += count * dc->charExtra;
1147 else if(dc->funcs->pGetTextExtentPoint) {
1148 FIXME("calling GetTextExtentPoint\n");
1149 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1152 GDI_ReleaseObj( hdc );
1154 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1155 hdc, indices, count, size, size->cx, size->cy );
1156 return ret;
1160 /***********************************************************************
1161 * GetTextExtentPointA (GDI32.@)
1163 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1164 LPSIZE size )
1166 TRACE("not bug compatible.\n");
1167 return GetTextExtentPoint32A( hdc, str, count, size );
1170 /***********************************************************************
1171 * GetTextExtentPointW (GDI32.@)
1173 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1174 LPSIZE size )
1176 TRACE("not bug compatible.\n");
1177 return GetTextExtentPoint32W( hdc, str, count, size );
1181 /***********************************************************************
1182 * GetTextExtentExPointA (GDI32.@)
1184 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1185 INT maxExt, LPINT lpnFit,
1186 LPINT alpDx, LPSIZE size )
1188 BOOL ret;
1189 INT wlen;
1190 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1191 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1192 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1193 HeapFree( GetProcessHeap(), 0, p );
1194 return ret;
1198 /***********************************************************************
1199 * GetTextExtentExPointW (GDI32.@)
1201 * Return the size of the string as it would be if it was output properly by
1202 * e.g. TextOut.
1204 * This should include
1205 * - Intercharacter spacing
1206 * - justification spacing (not yet done)
1207 * - kerning? see below
1209 * Kerning. Since kerning would be carried out by the rendering code it should
1210 * be done by the driver. However they don't support it yet. Also I am not
1211 * yet persuaded that (certainly under Win95) any kerning is actually done.
1213 * str: According to MSDN this should be null-terminated. That is not true; a
1214 * null will not terminate it early.
1215 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1216 * than count. I have seen it be either the size of the full string or
1217 * 1 less than the size of the full string. I have not seen it bear any
1218 * resemblance to the portion that would fit.
1219 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1220 * trailing intercharacter spacing and any trailing justification.
1222 * FIXME
1223 * Currently we do this by measuring each character etc. We should do it by
1224 * passing the request to the driver, perhaps by extending the
1225 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1226 * thinking about kerning issues and rounding issues in the justification.
1229 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1230 INT maxExt, LPINT lpnFit,
1231 LPINT alpDx, LPSIZE size )
1233 int index, nFit, extent;
1234 SIZE tSize;
1235 BOOL ret = FALSE;
1237 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1239 size->cx = size->cy = nFit = extent = 0;
1240 for(index = 0; index < count; index++)
1242 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1243 /* GetTextExtentPoint includes intercharacter spacing. */
1244 /* FIXME - justification needs doing yet. Remember that the base
1245 * data will not be in logical coordinates.
1247 extent += tSize.cx;
1248 if( !lpnFit || extent <= maxExt )
1249 /* It is allowed to be equal. */
1251 nFit++;
1252 if( alpDx ) alpDx[index] = extent;
1254 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1255 str++;
1257 size->cx = extent;
1258 if(lpnFit) *lpnFit = nFit;
1259 ret = TRUE;
1261 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1263 done:
1264 return ret;
1267 /***********************************************************************
1268 * GetTextMetricsA (GDI32.@)
1270 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1272 TEXTMETRICW tm32;
1274 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1275 FONT_TextMetricWToA( &tm32, metrics );
1276 return TRUE;
1279 /***********************************************************************
1280 * GetTextMetricsW (GDI32.@)
1282 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1284 BOOL ret = FALSE;
1285 DC * dc = DC_GetDCPtr( hdc );
1286 if (!dc) return FALSE;
1288 if (dc->gdiFont)
1289 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1290 else if (dc->funcs->pGetTextMetrics)
1291 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1293 if (ret)
1295 /* device layer returns values in device units
1296 * therefore we have to convert them to logical */
1298 #define WDPTOLP(x) ((x<0)? \
1299 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1300 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1301 #define HDPTOLP(y) ((y<0)? \
1302 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1303 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1305 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1306 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1307 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1308 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1309 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1310 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1311 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1312 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1313 ret = TRUE;
1314 #undef WDPTOLP
1315 #undef HDPTOLP
1316 TRACE("text metrics:\n"
1317 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1318 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1319 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1320 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1321 " PitchAndFamily = %02x\n"
1322 " --------------------\n"
1323 " InternalLeading = %li\n"
1324 " Ascent = %li\n"
1325 " Descent = %li\n"
1326 " Height = %li\n",
1327 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1328 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1329 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1330 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1331 metrics->tmPitchAndFamily,
1332 metrics->tmInternalLeading,
1333 metrics->tmAscent,
1334 metrics->tmDescent,
1335 metrics->tmHeight );
1337 GDI_ReleaseObj( hdc );
1338 return ret;
1342 /***********************************************************************
1343 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1345 * NOTES
1346 * lpOTM should be LPOUTLINETEXTMETRIC
1348 * RETURNS
1349 * Success: Non-zero or size of required buffer
1350 * Failure: 0
1352 UINT16 WINAPI GetOutlineTextMetrics16(
1353 HDC16 hdc, /* [in] Handle of device context */
1354 UINT16 cbData, /* [in] Size of metric data array */
1355 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1357 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1358 return 0;
1362 /***********************************************************************
1363 * GetOutlineTextMetricsA (GDI32.@)
1364 * Gets metrics for TrueType fonts.
1366 * NOTES
1367 * If the supplied buffer isn't big enough Windows partially fills it up to
1368 * its given length and returns that length.
1370 * RETURNS
1371 * Success: Non-zero or size of required buffer
1372 * Failure: 0
1374 UINT WINAPI GetOutlineTextMetricsA(
1375 HDC hdc, /* [in] Handle of device context */
1376 UINT cbData, /* [in] Size of metric data array */
1377 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1379 char buf[512], *ptr;
1380 UINT ret, needed;
1381 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1382 OUTLINETEXTMETRICA *output = lpOTM;
1383 INT left, len;
1385 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1386 return 0;
1387 if(ret > sizeof(buf))
1388 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1389 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1391 needed = sizeof(OUTLINETEXTMETRICA);
1392 if(lpOTMW->otmpFamilyName)
1393 needed += WideCharToMultiByte(CP_ACP, 0,
1394 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1395 NULL, 0, NULL, NULL);
1396 if(lpOTMW->otmpFaceName)
1397 needed += WideCharToMultiByte(CP_ACP, 0,
1398 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1399 NULL, 0, NULL, NULL);
1400 if(lpOTMW->otmpStyleName)
1401 needed += WideCharToMultiByte(CP_ACP, 0,
1402 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1403 NULL, 0, NULL, NULL);
1404 if(lpOTMW->otmpFullName)
1405 needed += WideCharToMultiByte(CP_ACP, 0,
1406 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1407 NULL, 0, NULL, NULL);
1409 if(!lpOTM) {
1410 ret = needed;
1411 goto end;
1414 TRACE("needed = %d\n", needed);
1415 if(needed > cbData)
1416 /* Since the supplied buffer isn't big enough, we'll alloc one
1417 that is and memcpy the first cbData bytes into the lpOTM at
1418 the end. */
1419 output = HeapAlloc(GetProcessHeap(), 0, needed);
1421 ret = output->otmSize = min(needed, cbData);
1422 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1423 output->otmFiller = 0;
1424 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1425 output->otmfsSelection = lpOTMW->otmfsSelection;
1426 output->otmfsType = lpOTMW->otmfsType;
1427 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1428 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1429 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1430 output->otmEMSquare = lpOTMW->otmEMSquare;
1431 output->otmAscent = lpOTMW->otmAscent;
1432 output->otmDescent = lpOTMW->otmDescent;
1433 output->otmLineGap = lpOTMW->otmLineGap;
1434 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1435 output->otmsXHeight = lpOTMW->otmsXHeight;
1436 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1437 output->otmMacAscent = lpOTMW->otmMacAscent;
1438 output->otmMacDescent = lpOTMW->otmMacDescent;
1439 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1440 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1441 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1442 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1443 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1444 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1445 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1446 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1447 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1448 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1451 ptr = (char*)(output + 1);
1452 left = needed - sizeof(*output);
1454 if(lpOTMW->otmpFamilyName) {
1455 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1456 len = WideCharToMultiByte(CP_ACP, 0,
1457 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1458 ptr, left, NULL, NULL);
1459 left -= len;
1460 ptr += len;
1461 } else
1462 output->otmpFamilyName = 0;
1464 if(lpOTMW->otmpFaceName) {
1465 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1466 len = WideCharToMultiByte(CP_ACP, 0,
1467 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1468 ptr, left, NULL, NULL);
1469 left -= len;
1470 ptr += len;
1471 } else
1472 output->otmpFaceName = 0;
1474 if(lpOTMW->otmpStyleName) {
1475 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1476 len = WideCharToMultiByte(CP_ACP, 0,
1477 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1478 ptr, left, NULL, NULL);
1479 left -= len;
1480 ptr += len;
1481 } else
1482 output->otmpStyleName = 0;
1484 if(lpOTMW->otmpFullName) {
1485 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1486 len = WideCharToMultiByte(CP_ACP, 0,
1487 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1488 ptr, left, NULL, NULL);
1489 left -= len;
1490 } else
1491 output->otmpFullName = 0;
1493 assert(left == 0);
1495 if(output != lpOTM) {
1496 memcpy(lpOTM, output, cbData);
1497 HeapFree(GetProcessHeap(), 0, output);
1500 end:
1501 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1502 HeapFree(GetProcessHeap(), 0, lpOTMW);
1504 return ret;
1508 /***********************************************************************
1509 * GetOutlineTextMetricsW [GDI32.@]
1511 UINT WINAPI GetOutlineTextMetricsW(
1512 HDC hdc, /* [in] Handle of device context */
1513 UINT cbData, /* [in] Size of metric data array */
1514 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1516 DC *dc = DC_GetDCPtr( hdc );
1517 OUTLINETEXTMETRICW *output = lpOTM;
1518 UINT ret;
1520 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1521 if(!dc) return 0;
1523 if(dc->gdiFont) {
1524 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1525 if(lpOTM && ret) {
1526 if(ret > cbData) {
1527 output = HeapAlloc(GetProcessHeap(), 0, ret);
1528 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1531 #define WDPTOLP(x) ((x<0)? \
1532 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1533 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1534 #define HDPTOLP(y) ((y<0)? \
1535 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1536 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1538 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1539 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1540 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1541 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1542 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1543 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1544 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1545 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1546 output->otmAscent = HDPTOLP(output->otmAscent);
1547 output->otmDescent = HDPTOLP(output->otmDescent);
1548 output->otmLineGap = HDPTOLP(output->otmLineGap);
1549 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1550 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1551 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1552 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1553 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1554 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1555 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1556 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1557 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1558 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1559 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1560 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1561 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1562 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1563 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1564 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1565 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1566 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1567 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1568 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1569 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1570 #undef WDPTOLP
1571 #undef HDPTOLP
1572 if(output != lpOTM) {
1573 memcpy(lpOTM, output, cbData);
1574 HeapFree(GetProcessHeap(), 0, output);
1575 ret = cbData;
1580 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1581 but really this should just be a return 0. */
1583 ret = sizeof(*lpOTM);
1584 if (lpOTM) {
1585 if(cbData < ret)
1586 ret = 0;
1587 else {
1588 memset(lpOTM, 0, ret);
1589 lpOTM->otmSize = sizeof(*lpOTM);
1590 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1592 Further fill of the structure not implemented,
1593 Needs real values for the structure members
1598 GDI_ReleaseObj(hdc);
1599 return ret;
1603 /***********************************************************************
1604 * GetCharWidthW (GDI32.@)
1605 * GetCharWidth32W (GDI32.@)
1607 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1608 LPINT buffer )
1610 UINT i;
1611 BOOL ret = FALSE;
1612 DC * dc = DC_GetDCPtr( hdc );
1613 if (!dc) return FALSE;
1615 if (dc->gdiFont)
1616 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1617 else if (dc->funcs->pGetCharWidth)
1618 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1620 if (ret)
1622 /* convert device units to logical */
1623 for( i = firstChar; i <= lastChar; i++, buffer++ )
1624 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1625 ret = TRUE;
1627 GDI_ReleaseObj( hdc );
1628 return ret;
1632 /***********************************************************************
1633 * GetCharWidthA (GDI32.@)
1634 * GetCharWidth32A (GDI32.@)
1636 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1637 LPINT buffer )
1639 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1640 LPSTR str;
1641 LPWSTR wstr;
1642 BOOL ret = TRUE;
1644 if(count <= 0) return FALSE;
1646 str = HeapAlloc(GetProcessHeap(), 0, count);
1647 for(i = 0; i < count; i++)
1648 str[i] = (BYTE)(firstChar + i);
1650 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1652 for(i = 0; i < wlen; i++)
1654 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1656 ret = FALSE;
1657 break;
1659 buffer++;
1662 HeapFree(GetProcessHeap(), 0, str);
1663 HeapFree(GetProcessHeap(), 0, wstr);
1665 return ret;
1669 /***********************************************************************
1670 * ExtTextOutA (GDI32.@)
1672 * See ExtTextOutW.
1674 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1675 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1677 INT wlen;
1678 UINT codepage;
1679 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1680 BOOL ret;
1681 LPINT lpDxW = NULL;
1683 if (lpDx) {
1684 unsigned int i = 0, j = 0;
1686 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1687 while(i < count) {
1688 if(IsDBCSLeadByteEx(codepage, str[i])) {
1689 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1690 i = i + 2;
1691 } else {
1692 lpDxW[j++] = lpDx[i];
1693 i = i + 1;
1698 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1700 HeapFree( GetProcessHeap(), 0, p );
1701 HeapFree( GetProcessHeap(), 0, lpDxW );
1702 return ret;
1706 /***********************************************************************
1707 * ExtTextOutW (GDI32.@)
1709 * Draws text using the currently selected font, background color, and text color.
1712 * PARAMS
1713 * x,y [I] coordinates of string
1714 * flags [I]
1715 * ETO_GRAYED - undocumented on MSDN
1716 * ETO_OPAQUE - use background color for fill the rectangle
1717 * ETO_CLIPPED - clipping text to the rectangle
1718 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1719 * than encoded characters. Implies ETO_IGNORELANGUAGE
1720 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1721 * Affects BiDi ordering
1722 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1723 * ETO_PDY - unimplemented
1724 * ETO_NUMERICSLATIN - unimplemented always assumed -
1725 * do not translate numbers into locale representations
1726 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1727 * lprect [I] dimensions for clipping or/and opaquing
1728 * str [I] text string
1729 * count [I] number of symbols in string
1730 * lpDx [I] optional parameter with distance between drawing characters
1732 * RETURNS
1733 * Success: TRUE
1734 * Failure: FALSE
1736 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1737 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1739 BOOL ret = FALSE;
1740 LPWSTR reordered_str = (LPWSTR)str;
1741 WORD *glyphs = NULL;
1742 UINT align = GetTextAlign( hdc );
1743 POINT pt;
1744 TEXTMETRICW tm;
1745 LOGFONTW lf;
1746 double cosEsc, sinEsc;
1747 INT *deltas = NULL, char_extra;
1748 SIZE sz;
1749 RECT rc;
1750 BOOL done_extents = FALSE;
1751 INT width, xwidth = 0, ywidth = 0;
1752 DWORD type;
1753 DC * dc = DC_GetDCUpdate( hdc );
1755 if (!dc) return FALSE;
1757 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1758 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1760 if(PATH_IsPathOpen(dc->path))
1762 FIXME("called on an open path\n");
1763 GDI_ReleaseObj( hdc );
1764 return ret;
1767 if(!dc->funcs->pExtTextOut)
1769 GDI_ReleaseObj( hdc );
1770 return ret;
1773 type = GetObjectType(hdc);
1774 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1776 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1777 GDI_ReleaseObj( hdc );
1778 return ret;
1781 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1783 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1785 BIDI_Reorder( str, count, GCP_REORDER,
1786 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1787 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1788 reordered_str, count, NULL );
1790 flags |= ETO_IGNORELANGUAGE;
1793 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1794 lprect, debugstr_wn(str, count), count, lpDx);
1796 if(flags & ETO_GLYPH_INDEX)
1797 glyphs = reordered_str;
1799 if(lprect)
1800 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1801 lprect->bottom);
1802 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1804 if(align & TA_UPDATECP)
1806 GetCurrentPositionEx( hdc, &pt );
1807 x = pt.x;
1808 y = pt.y;
1811 GetTextMetricsW(hdc, &tm);
1812 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1814 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1815 lf.lfEscapement = 0;
1817 if(lf.lfEscapement != 0)
1819 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1820 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1822 else
1824 cosEsc = 1;
1825 sinEsc = 0;
1828 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1830 if(!lprect)
1832 if(flags & ETO_CLIPPED) goto done;
1833 if(flags & ETO_GLYPH_INDEX)
1834 GetTextExtentPointI(hdc, glyphs, count, &sz);
1835 else
1836 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1838 done_extents = TRUE;
1839 rc.left = x;
1840 rc.top = y;
1841 rc.right = x + sz.cx;
1842 rc.bottom = y + sz.cy;
1844 else
1846 rc = *lprect;
1849 LPtoDP(hdc, (POINT*)&rc, 2);
1851 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1852 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1855 if(flags & ETO_OPAQUE)
1856 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1858 if(count == 0)
1860 ret = TRUE;
1861 goto done;
1864 pt.x = x;
1865 pt.y = y;
1866 LPtoDP(hdc, &pt, 1);
1867 x = pt.x;
1868 y = pt.y;
1870 char_extra = GetTextCharacterExtra(hdc);
1871 width = 0;
1872 if(char_extra || dc->breakExtra || lpDx)
1874 UINT i;
1875 SIZE tmpsz;
1876 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1877 for(i = 0; i < count; i++)
1879 if(lpDx)
1880 deltas[i] = lpDx[i] + char_extra;
1881 else
1883 if(flags & ETO_GLYPH_INDEX)
1884 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1885 else
1886 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1888 deltas[i] = tmpsz.cx;
1891 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1893 deltas[i] = deltas[i] + dc->breakExtra;
1895 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1896 width += deltas[i];
1899 else
1901 if(!done_extents)
1903 if(flags & ETO_GLYPH_INDEX)
1904 GetTextExtentPointI(hdc, glyphs, count, &sz);
1905 else
1906 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1907 done_extents = TRUE;
1909 width = INTERNAL_XWSTODS(dc, sz.cx);
1911 xwidth = width * cosEsc;
1912 ywidth = width * sinEsc;
1914 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1915 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1916 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1918 case TA_LEFT:
1919 if (align & TA_UPDATECP)
1921 pt.x = x + xwidth;
1922 pt.y = y - ywidth;
1923 DPtoLP(hdc, &pt, 1);
1924 MoveToEx(hdc, pt.x, pt.y, NULL);
1926 break;
1928 case TA_CENTER:
1929 x -= xwidth / 2;
1930 y += ywidth / 2;
1931 break;
1933 case TA_RIGHT:
1934 x -= xwidth;
1935 y += ywidth;
1936 if (align & TA_UPDATECP)
1938 pt.x = x;
1939 pt.y = y;
1940 DPtoLP(hdc, &pt, 1);
1941 MoveToEx(hdc, pt.x, pt.y, NULL);
1943 break;
1946 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1948 case TA_TOP:
1949 y += tm.tmAscent * cosEsc;
1950 x += tm.tmAscent * sinEsc;
1951 break;
1953 case TA_BOTTOM:
1954 y -= tm.tmDescent * cosEsc;
1955 x -= tm.tmDescent * sinEsc;
1956 break;
1958 case TA_BASELINE:
1959 break;
1962 if(GetBkMode(hdc) != TRANSPARENT)
1964 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1966 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1967 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1969 RECT rc;
1970 rc.left = x;
1971 rc.right = x + width;
1972 rc.top = y - tm.tmAscent;
1973 rc.bottom = y + tm.tmDescent;
1974 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1979 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1981 HFONT orig_font = dc->hFont, cur_font;
1982 UINT glyph;
1983 INT span = 0, *offsets = NULL, i;
1985 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1986 for(i = 0; i < count; i++)
1988 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1989 if(cur_font != dc->hFont)
1991 if(!offsets)
1993 int j;
1994 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1995 offsets[0] = 0;
1996 if(!deltas)
1998 SIZE tmpsz;
1999 for(j = 1; j < count; j++)
2001 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2002 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2005 else
2007 for(j = 1; j < count; j++)
2008 offsets[j] = offsets[j-1] + deltas[j];
2011 if(span)
2013 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2014 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2015 glyphs, span, deltas ? deltas + i - span : NULL);
2016 span = 0;
2018 SelectObject(hdc, cur_font);
2020 glyphs[span++] = glyph;
2022 if(i == count - 1)
2024 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2025 y - (offsets ? offsets[count - span] * sinEsc : 0),
2026 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2027 glyphs, span, deltas ? deltas + count - span : NULL);
2028 SelectObject(hdc, orig_font);
2029 HeapFree(GetProcessHeap(), 0, offsets);
2033 else
2035 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2037 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2038 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2039 flags |= ETO_GLYPH_INDEX;
2041 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2042 glyphs ? glyphs : reordered_str, count, deltas);
2045 done:
2046 HeapFree(GetProcessHeap(), 0, deltas);
2047 if(glyphs != reordered_str)
2048 HeapFree(GetProcessHeap(), 0, glyphs);
2049 if(reordered_str != str)
2050 HeapFree(GetProcessHeap(), 0, reordered_str);
2052 GDI_ReleaseObj( hdc );
2054 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2056 int underlinePos, strikeoutPos;
2057 int underlineWidth, strikeoutWidth;
2058 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2059 OUTLINETEXTMETRICW* otm = NULL;
2061 if(!size)
2063 underlinePos = 0;
2064 underlineWidth = tm.tmAscent / 20 + 1;
2065 strikeoutPos = tm.tmAscent / 2;
2066 strikeoutWidth = underlineWidth;
2068 else
2070 otm = HeapAlloc(GetProcessHeap(), 0, size);
2071 GetOutlineTextMetricsW(hdc, size, otm);
2072 underlinePos = otm->otmsUnderscorePosition;
2073 underlineWidth = otm->otmsUnderscoreSize;
2074 strikeoutPos = otm->otmsStrikeoutPosition;
2075 strikeoutWidth = otm->otmsStrikeoutSize;
2076 HeapFree(GetProcessHeap(), 0, otm);
2079 if (PATH_IsPathOpen(dc->path))
2081 POINT pts[5];
2082 HPEN hpen;
2083 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2085 hbrush = SelectObject(hdc, hbrush);
2086 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2088 if (lf.lfUnderline)
2090 pts[0].x = x - underlinePos * sinEsc;
2091 pts[0].y = y - underlinePos * cosEsc;
2092 pts[1].x = x + xwidth - underlinePos * sinEsc;
2093 pts[1].y = y - ywidth - underlinePos * cosEsc;
2094 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2095 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2096 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2097 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2098 pts[4].x = pts[0].x;
2099 pts[4].y = pts[0].y;
2100 DPtoLP(hdc, pts, 5);
2101 Polygon(hdc, pts, 5);
2104 if (lf.lfStrikeOut)
2106 pts[0].x = x - strikeoutPos * sinEsc;
2107 pts[0].y = y - strikeoutPos * cosEsc;
2108 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2109 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2110 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2111 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2112 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2113 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2114 pts[4].x = pts[0].x;
2115 pts[4].y = pts[0].y;
2116 DPtoLP(hdc, pts, 5);
2117 Polygon(hdc, pts, 5);
2120 SelectObject(hdc, hpen);
2121 hbrush = SelectObject(hdc, hbrush);
2122 DeleteObject(hbrush);
2124 else
2126 POINT pts[2], oldpt;
2127 HPEN hpen;
2129 if (lf.lfUnderline)
2131 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2132 hpen = SelectObject(hdc, hpen);
2133 pts[0].x = x;
2134 pts[0].y = y;
2135 pts[1].x = x + xwidth;
2136 pts[1].y = y - ywidth;
2137 DPtoLP(hdc, pts, 2);
2138 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2139 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2140 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2141 DeleteObject(SelectObject(hdc, hpen));
2144 if (lf.lfStrikeOut)
2146 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2147 hpen = SelectObject(hdc, hpen);
2148 pts[0].x = x;
2149 pts[0].y = y;
2150 pts[1].x = x + xwidth;
2151 pts[1].y = y - ywidth;
2152 DPtoLP(hdc, pts, 2);
2153 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2154 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2155 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2156 DeleteObject(SelectObject(hdc, hpen));
2161 return ret;
2165 /***********************************************************************
2166 * TextOutA (GDI32.@)
2168 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2170 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2174 /***********************************************************************
2175 * TextOutW (GDI32.@)
2177 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2179 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2183 /***********************************************************************
2184 * PolyTextOutA (GDI32.@)
2186 * Draw several Strings
2188 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2189 PPOLYTEXTA pptxt, /* [in] Array of strings */
2190 INT cStrings ) /* [in] Number of strings in array */
2192 for (; cStrings>0; cStrings--, pptxt++)
2193 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2194 return FALSE;
2195 return TRUE;
2200 /***********************************************************************
2201 * PolyTextOutW (GDI32.@)
2203 * Draw several Strings
2205 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2206 PPOLYTEXTW pptxt, /* [in] Array of strings */
2207 INT cStrings ) /* [in] Number of strings in array */
2209 for (; cStrings>0; cStrings--, pptxt++)
2210 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2211 return FALSE;
2212 return TRUE;
2216 /* FIXME: all following APIs ******************************************/
2219 /***********************************************************************
2220 * SetMapperFlags (GDI32.@)
2222 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2224 DC *dc = DC_GetDCPtr( hDC );
2225 DWORD ret = 0;
2226 if(!dc) return 0;
2227 if(dc->funcs->pSetMapperFlags)
2228 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2229 else
2230 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2231 GDI_ReleaseObj( hDC );
2232 return ret;
2235 /***********************************************************************
2236 * GetAspectRatioFilterEx (GDI.486)
2238 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2240 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2241 return FALSE;
2244 /***********************************************************************
2245 * GetAspectRatioFilterEx (GDI32.@)
2247 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2249 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2250 return FALSE;
2254 /***********************************************************************
2255 * GetCharABCWidthsA (GDI32.@)
2257 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2258 LPABC abc )
2260 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2261 LPSTR str;
2262 LPWSTR wstr;
2263 BOOL ret = TRUE;
2265 if(count <= 0) return FALSE;
2267 str = HeapAlloc(GetProcessHeap(), 0, count);
2268 for(i = 0; i < count; i++)
2269 str[i] = (BYTE)(firstChar + i);
2271 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2273 for(i = 0; i < wlen; i++)
2275 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2277 ret = FALSE;
2278 break;
2280 abc++;
2283 HeapFree(GetProcessHeap(), 0, str);
2284 HeapFree(GetProcessHeap(), 0, wstr);
2286 return ret;
2290 /******************************************************************************
2291 * GetCharABCWidthsW [GDI32.@]
2293 * Retrieves widths of characters in range.
2295 * PARAMS
2296 * hdc [I] Handle of device context
2297 * firstChar [I] First character in range to query
2298 * lastChar [I] Last character in range to query
2299 * abc [O] Address of character-width structure
2301 * NOTES
2302 * Only works with TrueType fonts
2304 * RETURNS
2305 * Success: TRUE
2306 * Failure: FALSE
2308 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2309 LPABC abc )
2311 DC *dc = DC_GetDCPtr(hdc);
2312 unsigned int i;
2313 BOOL ret = FALSE;
2315 if(dc->gdiFont)
2316 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2317 else
2318 FIXME(": stub\n");
2320 if (ret)
2322 /* convert device units to logical */
2323 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2324 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2325 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2326 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2328 ret = TRUE;
2331 GDI_ReleaseObj(hdc);
2332 return ret;
2336 /***********************************************************************
2337 * GetGlyphOutlineA (GDI32.@)
2339 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2340 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2341 LPVOID lpBuffer, const MAT2 *lpmat2 )
2343 LPWSTR p = NULL;
2344 DWORD ret;
2345 UINT c;
2347 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2348 int len;
2349 char mbchs[2];
2350 if(uChar > 0xff) { /* but, 2 bytes character only */
2351 len = 2;
2352 mbchs[0] = (uChar & 0xff00) >> 8;
2353 mbchs[1] = (uChar & 0xff);
2354 } else {
2355 len = 1;
2356 mbchs[0] = (uChar & 0xff);
2358 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2359 c = p[0];
2360 } else
2361 c = uChar;
2362 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2363 lpmat2);
2364 HeapFree(GetProcessHeap(), 0, p);
2365 return ret;
2368 /***********************************************************************
2369 * GetGlyphOutlineW (GDI32.@)
2371 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2372 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2373 LPVOID lpBuffer, const MAT2 *lpmat2 )
2375 DC *dc = DC_GetDCPtr(hdc);
2376 DWORD ret;
2378 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2379 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2381 if(!dc) return GDI_ERROR;
2383 if(dc->gdiFont)
2384 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2385 cbBuffer, lpBuffer, lpmat2);
2386 else
2387 ret = GDI_ERROR;
2389 GDI_ReleaseObj(hdc);
2390 return ret;
2394 /***********************************************************************
2395 * CreateScalableFontResourceA (GDI32.@)
2397 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2398 LPCSTR lpszResourceFile,
2399 LPCSTR lpszFontFile,
2400 LPCSTR lpszCurrentPath )
2402 HANDLE f;
2404 /* fHidden=1 - only visible for the calling app, read-only, not
2405 * enumbered with EnumFonts/EnumFontFamilies
2406 * lpszCurrentPath can be NULL
2408 FIXME("(%ld,%s,%s,%s): stub\n",
2409 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2410 debugstr_a(lpszCurrentPath) );
2412 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2413 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2414 CloseHandle(f);
2415 SetLastError(ERROR_FILE_EXISTS);
2416 return FALSE;
2418 return FALSE; /* create failed */
2421 /***********************************************************************
2422 * CreateScalableFontResourceW (GDI32.@)
2424 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2425 LPCWSTR lpszResourceFile,
2426 LPCWSTR lpszFontFile,
2427 LPCWSTR lpszCurrentPath )
2429 FIXME("(%ld,%p,%p,%p): stub\n",
2430 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2431 return FALSE; /* create failed */
2435 /*************************************************************************
2436 * GetRasterizerCaps (GDI32.@)
2438 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
2440 lprs->nSize = sizeof(RASTERIZER_STATUS);
2441 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
2442 lprs->nLanguageID = 0;
2443 return TRUE;
2447 /*************************************************************************
2448 * GetKerningPairsA (GDI32.@)
2450 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2451 LPKERNINGPAIR lpKerningPairs )
2453 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2457 /*************************************************************************
2458 * GetKerningPairsW (GDI32.@)
2460 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2461 LPKERNINGPAIR lpKerningPairs )
2463 unsigned int i;
2464 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2465 for (i = 0; i < cPairs; i++)
2466 lpKerningPairs[i].iKernAmount = 0;
2467 return 0;
2470 /*************************************************************************
2471 * TranslateCharsetInfo [GDI32.@]
2473 * Fills a CHARSETINFO structure for a character set, code page, or
2474 * font. This allows making the correspondance between different labelings
2475 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2476 * of the same encoding.
2478 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2479 * only one codepage should be set in *lpSrc.
2481 * RETURNS
2482 * TRUE on success, FALSE on failure.
2485 BOOL WINAPI TranslateCharsetInfo(
2486 LPDWORD lpSrc, /* [in]
2487 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2488 if flags == TCI_SRCCHARSET: a character set value
2489 if flags == TCI_SRCCODEPAGE: a code page value
2491 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2492 DWORD flags /* [in] determines interpretation of lpSrc */)
2494 int index = 0;
2495 switch (flags) {
2496 case TCI_SRCFONTSIG:
2497 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2498 break;
2499 case TCI_SRCCODEPAGE:
2500 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2501 break;
2502 case TCI_SRCCHARSET:
2503 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2504 break;
2505 default:
2506 return FALSE;
2508 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2509 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2510 return TRUE;
2513 /*************************************************************************
2514 * GetFontLanguageInfo (GDI32.@)
2516 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2518 FONTSIGNATURE fontsig;
2519 static const DWORD GCP_DBCS_MASK=0x003F0000,
2520 GCP_DIACRITIC_MASK=0x00000000,
2521 FLI_GLYPHS_MASK=0x00000000,
2522 GCP_GLYPHSHAPE_MASK=0x00000040,
2523 GCP_KASHIDA_MASK=0x00000000,
2524 GCP_LIGATE_MASK=0x00000000,
2525 GCP_USEKERNING_MASK=0x00000000,
2526 GCP_REORDER_MASK=0x00000060;
2528 DWORD result=0;
2530 GetTextCharsetInfo( hdc, &fontsig, 0 );
2531 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2533 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2534 result|=GCP_DBCS;
2536 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2537 result|=GCP_DIACRITIC;
2539 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2540 result|=FLI_GLYPHS;
2542 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2543 result|=GCP_GLYPHSHAPE;
2545 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2546 result|=GCP_KASHIDA;
2548 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2549 result|=GCP_LIGATE;
2551 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2552 result|=GCP_USEKERNING;
2554 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2555 if( GetTextAlign( hdc) & TA_RTLREADING )
2556 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2557 result|=GCP_REORDER;
2559 return result;
2563 /*************************************************************************
2564 * GetFontData [GDI32.@]
2566 * Retrieve data for TrueType font.
2568 * RETURNS
2570 * success: Number of bytes returned
2571 * failure: GDI_ERROR
2573 * NOTES
2575 * Calls SetLastError()
2578 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2579 LPVOID buffer, DWORD length)
2581 DC *dc = DC_GetDCPtr(hdc);
2582 DWORD ret = GDI_ERROR;
2584 if(!dc) return GDI_ERROR;
2586 if(dc->gdiFont)
2587 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2589 GDI_ReleaseObj(hdc);
2590 return ret;
2593 /*************************************************************************
2594 * GetGlyphIndicesA [GDI32.@]
2596 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2597 LPWORD pgi, DWORD flags)
2599 DWORD ret;
2600 WCHAR *lpstrW;
2601 INT countW;
2603 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2604 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2606 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2607 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2608 HeapFree(GetProcessHeap(), 0, lpstrW);
2610 return ret;
2613 /*************************************************************************
2614 * GetGlyphIndicesW [GDI32.@]
2616 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2617 LPWORD pgi, DWORD flags)
2619 DC *dc = DC_GetDCPtr(hdc);
2620 DWORD ret = GDI_ERROR;
2622 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2623 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2625 if(!dc) return GDI_ERROR;
2627 if(dc->gdiFont)
2628 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2630 GDI_ReleaseObj(hdc);
2631 return ret;
2634 /*************************************************************************
2635 * GetCharacterPlacementA [GDI32.@]
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;