mscms: Move repetitive code to helper macros.
[wine.git] / dlls / gdi / font.c
blobf94bda158af3ba31187e55a6bd3f12caf33d3dee
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 Unicode translation of str using the charset of the
348 * currently selected font in hdc. If count is -1 then str is assumed
349 * to be '\0' terminated, otherwise it contains the number of bytes to
350 * convert. If plenW is non-NULL, on return it will point to the
351 * number of WCHARs that have been written. If pCP is non-NULL, on
352 * return it will point to the codepage used in the conversion. The
353 * caller should free the returned LPWSTR from the process heap
354 * itself.
356 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
358 UINT cp = CP_ACP;
359 INT lenW;
360 LPWSTR strW;
361 CHARSETINFO csi;
362 int charset = GetTextCharset(hdc);
364 /* Hmm, nicely designed api this one! */
365 if(TranslateCharsetInfo((DWORD*)charset, &csi, TCI_SRCCHARSET))
366 cp = csi.ciACP;
367 else {
368 switch(charset) {
369 case OEM_CHARSET:
370 cp = GetOEMCP();
371 break;
372 case DEFAULT_CHARSET:
373 cp = GetACP();
374 break;
376 case VISCII_CHARSET:
377 case TCVN_CHARSET:
378 case KOI8_CHARSET:
379 case ISO3_CHARSET:
380 case ISO4_CHARSET:
381 case ISO10_CHARSET:
382 case CELTIC_CHARSET:
383 /* FIXME: These have no place here, but because x11drv
384 enumerates fonts with these (made up) charsets some apps
385 might use them and then the FIXME below would become
386 annoying. Now we could pick the intended codepage for
387 each of these, but since it's broken anyway we'll just
388 use CP_ACP and hope it'll go away...
390 cp = CP_ACP;
391 break;
393 default:
394 FIXME("Can't find codepage for charset %d\n", charset);
395 break;
399 TRACE("charset %d => cp %d\n", charset, cp);
401 if(count == -1) count = strlen(str);
402 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
403 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
404 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
405 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
406 if(plenW) *plenW = lenW;
407 if(pCP) *pCP = cp;
408 return strW;
412 /***********************************************************************
413 * CreateFontIndirectA (GDI32.@)
415 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
417 LOGFONTW lfW;
419 if (plfA) {
420 FONT_LogFontAToW( plfA, &lfW );
421 return CreateFontIndirectW( &lfW );
422 } else
423 return CreateFontIndirectW( NULL );
427 /***********************************************************************
428 * CreateFontIndirectW (GDI32.@)
430 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
432 HFONT hFont = 0;
434 if (plf)
436 FONTOBJ* fontPtr;
437 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
438 (HGDIOBJ *)&hFont, &font_funcs )))
440 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
441 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
442 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
443 WCHAR* pFaceNameSuffix = NULL;
445 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
447 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
448 plf->lfHeight, plf->lfWidth,
449 plf->lfEscapement, plf->lfOrientation,
450 plf->lfPitchAndFamily,
451 plf->lfOutPrecision, plf->lfClipPrecision,
452 plf->lfQuality, plf->lfCharSet,
453 debugstr_w(plf->lfFaceName),
454 plf->lfWeight > 400 ? "Bold" : "",
455 plf->lfItalic ? "Italic" : "",
456 plf->lfUnderline ? "Underline" : "", hFont);
458 if (plf->lfEscapement != plf->lfOrientation) {
459 /* this should really depend on whether GM_ADVANCED is set */
460 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
461 WARN("orientation angle %f set to "
462 "escapement angle %f for new font %p\n",
463 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
466 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
467 if (pFaceNameItalicSuffix) {
468 fontPtr->logfont.lfItalic = TRUE;
469 pFaceNameSuffix = pFaceNameItalicSuffix;
472 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
473 if (pFaceNameBoldSuffix) {
474 if (fontPtr->logfont.lfWeight < FW_BOLD) {
475 fontPtr->logfont.lfWeight = FW_BOLD;
477 if (!pFaceNameSuffix ||
478 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
479 pFaceNameSuffix = pFaceNameBoldSuffix;
483 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
485 GDI_ReleaseObj( hFont );
488 else WARN("(NULL) => NULL\n");
490 return hFont;
493 /*************************************************************************
494 * CreateFontA (GDI32.@)
496 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
497 INT orient, INT weight, DWORD italic,
498 DWORD underline, DWORD strikeout, DWORD charset,
499 DWORD outpres, DWORD clippres, DWORD quality,
500 DWORD pitch, LPCSTR name )
502 LOGFONTA logfont;
504 logfont.lfHeight = height;
505 logfont.lfWidth = width;
506 logfont.lfEscapement = esc;
507 logfont.lfOrientation = orient;
508 logfont.lfWeight = weight;
509 logfont.lfItalic = italic;
510 logfont.lfUnderline = underline;
511 logfont.lfStrikeOut = strikeout;
512 logfont.lfCharSet = charset;
513 logfont.lfOutPrecision = outpres;
514 logfont.lfClipPrecision = clippres;
515 logfont.lfQuality = quality;
516 logfont.lfPitchAndFamily = pitch;
518 if (name)
519 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
520 else
521 logfont.lfFaceName[0] = '\0';
523 return CreateFontIndirectA( &logfont );
526 /*************************************************************************
527 * CreateFontW (GDI32.@)
529 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
530 INT orient, INT weight, DWORD italic,
531 DWORD underline, DWORD strikeout, DWORD charset,
532 DWORD outpres, DWORD clippres, DWORD quality,
533 DWORD pitch, LPCWSTR name )
535 LOGFONTW logfont;
537 logfont.lfHeight = height;
538 logfont.lfWidth = width;
539 logfont.lfEscapement = esc;
540 logfont.lfOrientation = orient;
541 logfont.lfWeight = weight;
542 logfont.lfItalic = italic;
543 logfont.lfUnderline = underline;
544 logfont.lfStrikeOut = strikeout;
545 logfont.lfCharSet = charset;
546 logfont.lfOutPrecision = outpres;
547 logfont.lfClipPrecision = clippres;
548 logfont.lfQuality = quality;
549 logfont.lfPitchAndFamily = pitch;
551 if (name)
552 lstrcpynW(logfont.lfFaceName, name,
553 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
554 else
555 logfont.lfFaceName[0] = '\0';
557 return CreateFontIndirectW( &logfont );
561 /***********************************************************************
562 * FONT_SelectObject
564 * If the driver supports vector fonts we create a gdi font first and
565 * then call the driver to give it a chance to supply its own device
566 * font. If the driver wants to do this it returns TRUE and we can
567 * delete the gdi font, if the driver wants to use the gdi font it
568 * should return FALSE, to signal an error return GDI_ERROR. For
569 * drivers that don't support vector fonts they must supply their own
570 * font.
572 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
574 HGDIOBJ ret = 0;
575 DC *dc = DC_GetDCPtr( hdc );
577 if (!dc) return 0;
579 if (dc->hFont != handle || dc->gdiFont == NULL)
581 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
582 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
585 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
587 if (ret && dc->gdiFont) dc->gdiFont = 0;
589 if (ret == HGDI_ERROR)
590 ret = 0; /* SelectObject returns 0 on error */
591 else
593 ret = dc->hFont;
594 dc->hFont = handle;
596 GDI_ReleaseObj( hdc );
597 return ret;
601 /***********************************************************************
602 * FONT_GetObject16
604 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
606 FONTOBJ *font = obj;
607 LOGFONT16 lf16;
609 FONT_LogFontWTo16( &font->logfont, &lf16 );
611 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
612 memcpy( buffer, &lf16, count );
613 return count;
616 /***********************************************************************
617 * FONT_GetObjectA
619 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
621 FONTOBJ *font = obj;
622 LOGFONTA lfA;
624 if(!buffer)
625 return sizeof(lfA);
626 FONT_LogFontWToA( &font->logfont, &lfA );
628 if (count > sizeof(lfA)) count = sizeof(lfA);
629 memcpy( buffer, &lfA, count );
630 return count;
633 /***********************************************************************
634 * FONT_GetObjectW
636 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
638 FONTOBJ *font = obj;
639 if(!buffer)
640 return sizeof(LOGFONTW);
641 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
642 memcpy( buffer, &font->logfont, count );
643 return count;
647 /***********************************************************************
648 * FONT_DeleteObject
650 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
652 WineEngDestroyFontInstance( handle );
653 return GDI_FreeObject( handle, obj );
657 /***********************************************************************
658 * FONT_EnumInstance16
660 * Called by the device driver layer to pass font info
661 * down to the application.
663 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
664 * We have to use other types because of the FONTENUMPROCW definition.
666 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
667 DWORD fType, LPARAM lp )
669 fontEnum16 *pfe = (fontEnum16*)lp;
670 INT ret = 1;
671 DC *dc;
673 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
674 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
676 WORD args[7];
677 DWORD result;
679 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
680 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
681 pfe->dwFlags |= ENUM_CALLED;
682 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
684 args[6] = SELECTOROF(pfe->segLogFont);
685 args[5] = OFFSETOF(pfe->segLogFont);
686 args[4] = SELECTOROF(pfe->segTextMetric);
687 args[3] = OFFSETOF(pfe->segTextMetric);
688 args[2] = fType;
689 args[1] = HIWORD(pfe->lpData);
690 args[0] = LOWORD(pfe->lpData);
691 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
692 ret = LOWORD(result);
694 /* get the lock again and make sure the DC is still valid */
695 dc = DC_GetDCPtr( pfe->hdc );
696 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
698 if (dc) GDI_ReleaseObj( pfe->hdc );
699 pfe->hdc = 0; /* make sure we don't try to release it later on */
700 ret = 0;
703 return ret;
706 /***********************************************************************
707 * FONT_EnumInstance
709 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
710 * We have to use other types because of the FONTENUMPROCW definition.
712 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
713 DWORD fType, LPARAM lp )
715 fontEnum32 *pfe = (fontEnum32*)lp;
716 INT ret = 1;
717 DC *dc;
719 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
720 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
721 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
722 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
724 /* convert font metrics */
725 ENUMLOGFONTEXA logfont;
726 NEWTEXTMETRICEXA tmA;
728 pfe->dwFlags |= ENUM_CALLED;
729 if (!(pfe->dwFlags & ENUM_UNICODE))
731 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
732 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
733 plf = (LOGFONTW *)&logfont.elfLogFont;
734 ptm = (TEXTMETRICW *)&tmA;
736 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
738 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
740 /* get the lock again and make sure the DC is still valid */
741 dc = DC_GetDCPtr( pfe->hdc );
742 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
744 if (dc) GDI_ReleaseObj( pfe->hdc );
745 pfe->hdc = 0; /* make sure we don't try to release it later on */
746 ret = 0;
749 return ret;
752 /***********************************************************************
753 * EnumFontFamiliesEx (GDI.613)
755 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
756 FONTENUMPROC16 efproc, LPARAM lParam,
757 DWORD dwFlags)
759 fontEnum16 fe16;
760 INT16 ret = 1, ret2;
761 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
762 NEWTEXTMETRICEX16 tm16;
763 ENUMLOGFONTEX16 lf16;
764 LOGFONTW lfW;
765 BOOL enum_gdi_fonts;
767 if (!dc) return 0;
768 FONT_LogFont16ToW(plf, &lfW);
770 fe16.hdc = HDC_32(hDC);
771 fe16.dc = dc;
772 fe16.physDev = dc->physDev;
773 fe16.lpLogFontParam = plf;
774 fe16.lpEnumFunc = efproc;
775 fe16.lpData = lParam;
776 fe16.lpTextMetric = &tm16;
777 fe16.lpLogFont = &lf16;
778 fe16.segTextMetric = MapLS( &tm16 );
779 fe16.segLogFont = MapLS( &lf16 );
780 fe16.dwFlags = 0;
782 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
784 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
786 ret = 0;
787 goto done;
790 if (enum_gdi_fonts)
791 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
792 fe16.dwFlags &= ~ENUM_CALLED;
793 if (ret && dc->funcs->pEnumDeviceFonts) {
794 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
795 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
796 ret = ret2;
798 done:
799 UnMapLS( fe16.segTextMetric );
800 UnMapLS( fe16.segLogFont );
801 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
802 return ret;
805 /***********************************************************************
806 * FONT_EnumFontFamiliesEx
808 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
809 FONTENUMPROCW efproc,
810 LPARAM lParam, DWORD dwUnicode)
812 INT ret = 1, ret2;
813 DC *dc = DC_GetDCPtr( hDC );
814 fontEnum32 fe32;
815 BOOL enum_gdi_fonts;
817 if (!dc) return 0;
819 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
820 plf->lfCharSet);
821 fe32.lpLogFontParam = plf;
822 fe32.lpEnumFunc = efproc;
823 fe32.lpData = lParam;
824 fe32.dwFlags = dwUnicode;
825 fe32.hdc = hDC;
826 fe32.dc = dc;
827 fe32.physDev = dc->physDev;
829 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
831 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
833 ret = 0;
834 goto done;
837 if (enum_gdi_fonts)
838 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
839 fe32.dwFlags &= ~ENUM_CALLED;
840 if (ret && dc->funcs->pEnumDeviceFonts) {
841 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
842 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
843 ret = ret2;
845 done:
846 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
847 return ret;
850 /***********************************************************************
851 * EnumFontFamiliesExW (GDI32.@)
853 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
854 FONTENUMPROCW efproc,
855 LPARAM lParam, DWORD dwFlags )
857 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
860 /***********************************************************************
861 * EnumFontFamiliesExA (GDI32.@)
863 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
864 FONTENUMPROCA efproc,
865 LPARAM lParam, DWORD dwFlags)
867 LOGFONTW lfW;
868 FONT_LogFontAToW( plf, &lfW );
870 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
873 /***********************************************************************
874 * EnumFontFamilies (GDI.330)
876 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
877 FONTENUMPROC16 efproc, LPARAM lpData )
879 LOGFONT16 lf;
881 lf.lfCharSet = DEFAULT_CHARSET;
882 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
883 else lf.lfFaceName[0] = '\0';
885 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
888 /***********************************************************************
889 * EnumFontFamiliesA (GDI32.@)
891 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
892 FONTENUMPROCA efproc, LPARAM lpData )
894 LOGFONTA lf;
896 lf.lfCharSet = DEFAULT_CHARSET;
897 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
898 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
900 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
903 /***********************************************************************
904 * EnumFontFamiliesW (GDI32.@)
906 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
907 FONTENUMPROCW efproc, LPARAM lpData )
909 LOGFONTW lf;
911 lf.lfCharSet = DEFAULT_CHARSET;
912 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
913 else lf.lfFaceName[0] = 0;
915 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
918 /***********************************************************************
919 * EnumFonts (GDI.70)
921 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
922 LPARAM lpData )
924 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
927 /***********************************************************************
928 * EnumFontsA (GDI32.@)
930 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
931 LPARAM lpData )
933 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
936 /***********************************************************************
937 * EnumFontsW (GDI32.@)
939 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
940 LPARAM lpData )
942 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
946 /***********************************************************************
947 * GetTextCharacterExtra (GDI32.@)
949 INT WINAPI GetTextCharacterExtra( HDC hdc )
951 INT ret;
952 DC *dc = DC_GetDCPtr( hdc );
953 if (!dc) return 0x80000000;
954 ret = dc->charExtra;
955 GDI_ReleaseObj( hdc );
956 return ret;
960 /***********************************************************************
961 * SetTextCharacterExtra (GDI32.@)
963 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
965 INT prev;
966 DC * dc = DC_GetDCPtr( hdc );
967 if (!dc) return 0x80000000;
968 if (dc->funcs->pSetTextCharacterExtra)
969 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
970 else
972 prev = dc->charExtra;
973 dc->charExtra = extra;
975 GDI_ReleaseObj( hdc );
976 return prev;
980 /***********************************************************************
981 * SetTextJustification (GDI32.@)
983 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
985 BOOL ret = TRUE;
986 DC * dc = DC_GetDCPtr( hdc );
987 if (!dc) return FALSE;
988 if (dc->funcs->pSetTextJustification)
989 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
990 else
992 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
993 if (!extra) breaks = 0;
994 if (breaks)
996 dc->breakExtra = extra / breaks;
997 dc->breakRem = extra - (breaks * dc->breakExtra);
999 else
1001 dc->breakExtra = 0;
1002 dc->breakRem = 0;
1005 GDI_ReleaseObj( hdc );
1006 return ret;
1010 /***********************************************************************
1011 * GetTextFaceA (GDI32.@)
1013 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1015 INT res = GetTextFaceW(hdc, 0, NULL);
1016 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1017 GetTextFaceW( hdc, res, nameW );
1019 if (name)
1021 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1022 name[count-1] = 0;
1023 res = strlen(name);
1025 else
1026 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1027 HeapFree( GetProcessHeap(), 0, nameW );
1028 return res;
1031 /***********************************************************************
1032 * GetTextFaceW (GDI32.@)
1034 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1036 FONTOBJ *font;
1037 INT ret = 0;
1039 DC * dc = DC_GetDCPtr( hdc );
1040 if (!dc) return 0;
1042 if(dc->gdiFont)
1043 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1044 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1046 if (name)
1048 lstrcpynW( name, font->logfont.lfFaceName, count );
1049 ret = strlenW(name);
1051 else ret = strlenW(font->logfont.lfFaceName) + 1;
1052 GDI_ReleaseObj( dc->hFont );
1054 GDI_ReleaseObj( hdc );
1055 return ret;
1059 /***********************************************************************
1060 * GetTextExtentPoint32A (GDI32.@)
1062 * See GetTextExtentPoint32W.
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 (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1762 GDI_ReleaseObj( hdc );
1763 return ret;
1766 type = GetObjectType(hdc);
1767 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1769 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1770 GDI_ReleaseObj( hdc );
1771 return ret;
1774 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && BidiAvail && count > 0 )
1776 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1778 BIDI_Reorder( str, count, GCP_REORDER,
1779 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1780 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1781 reordered_str, count, NULL );
1783 flags |= ETO_IGNORELANGUAGE;
1786 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1787 lprect, debugstr_wn(str, count), count, lpDx);
1789 if(flags & ETO_GLYPH_INDEX)
1790 glyphs = reordered_str;
1792 if(lprect)
1793 TRACE("rect: %ld,%ld - %ld,%ld\n", lprect->left, lprect->top, lprect->right,
1794 lprect->bottom);
1795 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1797 if(align & TA_UPDATECP)
1799 GetCurrentPositionEx( hdc, &pt );
1800 x = pt.x;
1801 y = pt.y;
1804 GetTextMetricsW(hdc, &tm);
1805 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1807 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1808 lf.lfEscapement = 0;
1810 if(lf.lfEscapement != 0)
1812 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1813 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1815 else
1817 cosEsc = 1;
1818 sinEsc = 0;
1821 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1823 if(!lprect)
1825 if(flags & ETO_CLIPPED) goto done;
1826 if(flags & ETO_GLYPH_INDEX)
1827 GetTextExtentPointI(hdc, glyphs, count, &sz);
1828 else
1829 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1831 done_extents = TRUE;
1832 rc.left = x;
1833 rc.top = y;
1834 rc.right = x + sz.cx;
1835 rc.bottom = y + sz.cy;
1837 else
1839 rc = *lprect;
1842 LPtoDP(hdc, (POINT*)&rc, 2);
1844 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1845 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1848 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1849 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1851 if(count == 0)
1853 ret = TRUE;
1854 goto done;
1857 pt.x = x;
1858 pt.y = y;
1859 LPtoDP(hdc, &pt, 1);
1860 x = pt.x;
1861 y = pt.y;
1863 char_extra = GetTextCharacterExtra(hdc);
1864 width = 0;
1865 if(char_extra || dc->breakExtra || lpDx)
1867 UINT i;
1868 SIZE tmpsz;
1869 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1870 for(i = 0; i < count; i++)
1872 if(lpDx)
1873 deltas[i] = lpDx[i] + char_extra;
1874 else
1876 if(flags & ETO_GLYPH_INDEX)
1877 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1878 else
1879 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1881 deltas[i] = tmpsz.cx;
1884 if (!(flags & ETO_GLYPH_INDEX) && dc->breakExtra && reordered_str[i] == tm.tmBreakChar)
1886 deltas[i] = deltas[i] + dc->breakExtra;
1888 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1889 width += deltas[i];
1892 else
1894 if(!done_extents)
1896 if(flags & ETO_GLYPH_INDEX)
1897 GetTextExtentPointI(hdc, glyphs, count, &sz);
1898 else
1899 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1900 done_extents = TRUE;
1902 width = INTERNAL_XWSTODS(dc, sz.cx);
1904 xwidth = width * cosEsc;
1905 ywidth = width * sinEsc;
1907 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1908 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1909 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1911 case TA_LEFT:
1912 if (align & TA_UPDATECP)
1914 pt.x = x + xwidth;
1915 pt.y = y - ywidth;
1916 DPtoLP(hdc, &pt, 1);
1917 MoveToEx(hdc, pt.x, pt.y, NULL);
1919 break;
1921 case TA_CENTER:
1922 x -= xwidth / 2;
1923 y += ywidth / 2;
1924 break;
1926 case TA_RIGHT:
1927 x -= xwidth;
1928 y += ywidth;
1929 if (align & TA_UPDATECP)
1931 pt.x = x;
1932 pt.y = y;
1933 DPtoLP(hdc, &pt, 1);
1934 MoveToEx(hdc, pt.x, pt.y, NULL);
1936 break;
1939 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1941 case TA_TOP:
1942 y += tm.tmAscent * cosEsc;
1943 x += tm.tmAscent * sinEsc;
1944 break;
1946 case TA_BOTTOM:
1947 y -= tm.tmDescent * cosEsc;
1948 x -= tm.tmDescent * sinEsc;
1949 break;
1951 case TA_BASELINE:
1952 break;
1955 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1957 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1959 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1960 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1962 RECT rc;
1963 rc.left = x;
1964 rc.right = x + width;
1965 rc.top = y - tm.tmAscent;
1966 rc.bottom = y + tm.tmDescent;
1967 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1972 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1974 HFONT orig_font = dc->hFont, cur_font;
1975 UINT glyph;
1976 INT span = 0, *offsets = NULL, i;
1978 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1979 for(i = 0; i < count; i++)
1981 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1982 if(cur_font != dc->hFont)
1984 if(!offsets)
1986 int j;
1987 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1988 offsets[0] = 0;
1989 if(!deltas)
1991 SIZE tmpsz;
1992 for(j = 1; j < count; j++)
1994 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1995 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1998 else
2000 for(j = 1; j < count; j++)
2001 offsets[j] = offsets[j-1] + deltas[j];
2004 if(span)
2006 if (PATH_IsPathOpen(dc->path))
2007 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2008 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2009 glyphs, span, deltas ? deltas + i - span : NULL);
2010 else
2011 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2012 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2013 glyphs, span, deltas ? deltas + i - span : NULL);
2014 span = 0;
2016 SelectObject(hdc, cur_font);
2018 glyphs[span++] = glyph;
2020 if(i == count - 1)
2022 if (PATH_IsPathOpen(dc->path))
2023 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2024 y - (offsets ? offsets[count - span] * sinEsc : 0),
2025 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2026 glyphs, span, deltas ? deltas + count - span : NULL);
2027 else
2028 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2029 y - (offsets ? offsets[count - span] * sinEsc : 0),
2030 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2031 glyphs, span, deltas ? deltas + count - span : NULL);
2032 SelectObject(hdc, orig_font);
2033 HeapFree(GetProcessHeap(), 0, offsets);
2037 else
2039 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2041 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2042 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2043 flags |= ETO_GLYPH_INDEX;
2046 if (PATH_IsPathOpen(dc->path))
2047 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2048 glyphs ? glyphs : reordered_str, count, deltas);
2049 else
2050 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2051 glyphs ? glyphs : reordered_str, count, deltas);
2054 done:
2055 HeapFree(GetProcessHeap(), 0, deltas);
2056 if(glyphs != reordered_str)
2057 HeapFree(GetProcessHeap(), 0, glyphs);
2058 if(reordered_str != str)
2059 HeapFree(GetProcessHeap(), 0, reordered_str);
2061 GDI_ReleaseObj( hdc );
2063 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2065 int underlinePos, strikeoutPos;
2066 int underlineWidth, strikeoutWidth;
2067 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2068 OUTLINETEXTMETRICW* otm = NULL;
2070 if(!size)
2072 underlinePos = 0;
2073 underlineWidth = tm.tmAscent / 20 + 1;
2074 strikeoutPos = tm.tmAscent / 2;
2075 strikeoutWidth = underlineWidth;
2077 else
2079 otm = HeapAlloc(GetProcessHeap(), 0, size);
2080 GetOutlineTextMetricsW(hdc, size, otm);
2081 underlinePos = otm->otmsUnderscorePosition;
2082 underlineWidth = otm->otmsUnderscoreSize;
2083 strikeoutPos = otm->otmsStrikeoutPosition;
2084 strikeoutWidth = otm->otmsStrikeoutSize;
2085 HeapFree(GetProcessHeap(), 0, otm);
2088 if (PATH_IsPathOpen(dc->path))
2090 POINT pts[5];
2091 HPEN hpen;
2092 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2094 hbrush = SelectObject(hdc, hbrush);
2095 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2097 if (lf.lfUnderline)
2099 pts[0].x = x - underlinePos * sinEsc;
2100 pts[0].y = y - underlinePos * cosEsc;
2101 pts[1].x = x + xwidth - underlinePos * sinEsc;
2102 pts[1].y = y - ywidth - underlinePos * cosEsc;
2103 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2104 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2105 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2106 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2107 pts[4].x = pts[0].x;
2108 pts[4].y = pts[0].y;
2109 DPtoLP(hdc, pts, 5);
2110 Polygon(hdc, pts, 5);
2113 if (lf.lfStrikeOut)
2115 pts[0].x = x - strikeoutPos * sinEsc;
2116 pts[0].y = y - strikeoutPos * cosEsc;
2117 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2118 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2119 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2120 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2121 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2122 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2123 pts[4].x = pts[0].x;
2124 pts[4].y = pts[0].y;
2125 DPtoLP(hdc, pts, 5);
2126 Polygon(hdc, pts, 5);
2129 SelectObject(hdc, hpen);
2130 hbrush = SelectObject(hdc, hbrush);
2131 DeleteObject(hbrush);
2133 else
2135 POINT pts[2], oldpt;
2136 HPEN hpen;
2138 if (lf.lfUnderline)
2140 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2141 hpen = SelectObject(hdc, hpen);
2142 pts[0].x = x;
2143 pts[0].y = y;
2144 pts[1].x = x + xwidth;
2145 pts[1].y = y - ywidth;
2146 DPtoLP(hdc, pts, 2);
2147 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2148 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2149 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2150 DeleteObject(SelectObject(hdc, hpen));
2153 if (lf.lfStrikeOut)
2155 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2156 hpen = SelectObject(hdc, hpen);
2157 pts[0].x = x;
2158 pts[0].y = y;
2159 pts[1].x = x + xwidth;
2160 pts[1].y = y - ywidth;
2161 DPtoLP(hdc, pts, 2);
2162 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2163 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2164 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2165 DeleteObject(SelectObject(hdc, hpen));
2170 return ret;
2174 /***********************************************************************
2175 * TextOutA (GDI32.@)
2177 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2179 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2183 /***********************************************************************
2184 * TextOutW (GDI32.@)
2186 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2188 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2192 /***********************************************************************
2193 * PolyTextOutA (GDI32.@)
2195 * See PolyTextOutW.
2197 BOOL WINAPI PolyTextOutA ( HDC hdc, /* [in] Handle to device context */
2198 PPOLYTEXTA pptxt, /* [in] Array of strings */
2199 INT cStrings ) /* [in] Number of strings in array */
2201 for (; cStrings>0; cStrings--, pptxt++)
2202 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2203 return FALSE;
2204 return TRUE;
2209 /***********************************************************************
2210 * PolyTextOutW (GDI32.@)
2212 * Draw several Strings
2214 * RETURNS
2215 * TRUE: Success.
2216 * FALSE: Failure.
2218 BOOL WINAPI PolyTextOutW ( HDC hdc, /* [in] Handle to device context */
2219 PPOLYTEXTW pptxt, /* [in] Array of strings */
2220 INT cStrings ) /* [in] Number of strings in array */
2222 for (; cStrings>0; cStrings--, pptxt++)
2223 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2224 return FALSE;
2225 return TRUE;
2229 /* FIXME: all following APIs ******************************************/
2232 /***********************************************************************
2233 * SetMapperFlags (GDI32.@)
2235 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2237 DC *dc = DC_GetDCPtr( hDC );
2238 DWORD ret = 0;
2239 if(!dc) return 0;
2240 if(dc->funcs->pSetMapperFlags)
2242 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2243 /* FIXME: ret is just a success flag, we should return a proper value */
2245 else
2246 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
2247 GDI_ReleaseObj( hDC );
2248 return ret;
2251 /***********************************************************************
2252 * GetAspectRatioFilterEx (GDI.486)
2254 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2256 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2257 return FALSE;
2260 /***********************************************************************
2261 * GetAspectRatioFilterEx (GDI32.@)
2263 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2265 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2266 return FALSE;
2270 /***********************************************************************
2271 * GetCharABCWidthsA (GDI32.@)
2273 * See GetCharABCWidthsW.
2275 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2276 LPABC abc )
2278 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2279 LPSTR str;
2280 LPWSTR wstr;
2281 BOOL ret = TRUE;
2283 if(count <= 0) return FALSE;
2285 str = HeapAlloc(GetProcessHeap(), 0, count);
2286 for(i = 0; i < count; i++)
2287 str[i] = (BYTE)(firstChar + i);
2289 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2291 for(i = 0; i < wlen; i++)
2293 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2295 ret = FALSE;
2296 break;
2298 abc++;
2301 HeapFree(GetProcessHeap(), 0, str);
2302 HeapFree(GetProcessHeap(), 0, wstr);
2304 return ret;
2308 /******************************************************************************
2309 * GetCharABCWidthsW [GDI32.@]
2311 * Retrieves widths of characters in range.
2313 * PARAMS
2314 * hdc [I] Handle of device context
2315 * firstChar [I] First character in range to query
2316 * lastChar [I] Last character in range to query
2317 * abc [O] Address of character-width structure
2319 * NOTES
2320 * Only works with TrueType fonts
2322 * RETURNS
2323 * Success: TRUE
2324 * Failure: FALSE
2326 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2327 LPABC abc )
2329 DC *dc = DC_GetDCPtr(hdc);
2330 unsigned int i;
2331 BOOL ret = FALSE;
2333 if(dc->gdiFont)
2334 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2335 else
2336 FIXME(": stub\n");
2338 if (ret)
2340 /* convert device units to logical */
2341 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2342 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2343 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2344 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2346 ret = TRUE;
2349 GDI_ReleaseObj(hdc);
2350 return ret;
2354 /***********************************************************************
2355 * GetGlyphOutlineA (GDI32.@)
2357 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2358 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2359 LPVOID lpBuffer, const MAT2 *lpmat2 )
2361 LPWSTR p = NULL;
2362 DWORD ret;
2363 UINT c;
2365 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2366 int len;
2367 char mbchs[2];
2368 if(uChar > 0xff) { /* but, 2 bytes character only */
2369 len = 2;
2370 mbchs[0] = (uChar & 0xff00) >> 8;
2371 mbchs[1] = (uChar & 0xff);
2372 } else {
2373 len = 1;
2374 mbchs[0] = (uChar & 0xff);
2376 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2377 c = p[0];
2378 } else
2379 c = uChar;
2380 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2381 lpmat2);
2382 HeapFree(GetProcessHeap(), 0, p);
2383 return ret;
2386 /***********************************************************************
2387 * GetGlyphOutlineW (GDI32.@)
2389 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2390 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2391 LPVOID lpBuffer, const MAT2 *lpmat2 )
2393 DC *dc = DC_GetDCPtr(hdc);
2394 DWORD ret;
2396 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
2397 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2399 if(!dc) return GDI_ERROR;
2401 if(dc->gdiFont)
2402 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2403 cbBuffer, lpBuffer, lpmat2);
2404 else
2405 ret = GDI_ERROR;
2407 GDI_ReleaseObj(hdc);
2408 return ret;
2412 /***********************************************************************
2413 * CreateScalableFontResourceA (GDI32.@)
2415 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2416 LPCSTR lpszResourceFile,
2417 LPCSTR lpszFontFile,
2418 LPCSTR lpszCurrentPath )
2420 HANDLE f;
2422 /* fHidden=1 - only visible for the calling app, read-only, not
2423 * enumbered with EnumFonts/EnumFontFamilies
2424 * lpszCurrentPath can be NULL
2426 FIXME("(%ld,%s,%s,%s): stub\n",
2427 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2428 debugstr_a(lpszCurrentPath) );
2430 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2431 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2432 CloseHandle(f);
2433 SetLastError(ERROR_FILE_EXISTS);
2434 return FALSE;
2436 return FALSE; /* create failed */
2439 /***********************************************************************
2440 * CreateScalableFontResourceW (GDI32.@)
2442 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2443 LPCWSTR lpszResourceFile,
2444 LPCWSTR lpszFontFile,
2445 LPCWSTR lpszCurrentPath )
2447 FIXME("(%ld,%p,%p,%p): stub\n",
2448 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2449 return FALSE; /* create failed */
2452 /*************************************************************************
2453 * GetKerningPairsA (GDI32.@)
2455 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2456 LPKERNINGPAIR lpKerningPairs )
2458 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
2462 /*************************************************************************
2463 * GetKerningPairsW (GDI32.@)
2465 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2466 LPKERNINGPAIR lpKerningPairs )
2468 unsigned int i;
2469 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
2470 for (i = 0; i < cPairs; i++)
2471 lpKerningPairs[i].iKernAmount = 0;
2472 return 0;
2475 /*************************************************************************
2476 * TranslateCharsetInfo [GDI32.@]
2478 * Fills a CHARSETINFO structure for a character set, code page, or
2479 * font. This allows making the correspondance between different labelings
2480 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2481 * of the same encoding.
2483 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2484 * only one codepage should be set in *lpSrc.
2486 * RETURNS
2487 * TRUE on success, FALSE on failure.
2490 BOOL WINAPI TranslateCharsetInfo(
2491 LPDWORD lpSrc, /* [in]
2492 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2493 if flags == TCI_SRCCHARSET: a character set value
2494 if flags == TCI_SRCCODEPAGE: a code page value
2496 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2497 DWORD flags /* [in] determines interpretation of lpSrc */)
2499 int index = 0;
2500 switch (flags) {
2501 case TCI_SRCFONTSIG:
2502 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2503 break;
2504 case TCI_SRCCODEPAGE:
2505 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2506 break;
2507 case TCI_SRCCHARSET:
2508 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2509 break;
2510 default:
2511 return FALSE;
2513 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2514 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2515 return TRUE;
2518 /*************************************************************************
2519 * GetFontLanguageInfo (GDI32.@)
2521 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2523 FONTSIGNATURE fontsig;
2524 static const DWORD GCP_DBCS_MASK=0x003F0000,
2525 GCP_DIACRITIC_MASK=0x00000000,
2526 FLI_GLYPHS_MASK=0x00000000,
2527 GCP_GLYPHSHAPE_MASK=0x00000040,
2528 GCP_KASHIDA_MASK=0x00000000,
2529 GCP_LIGATE_MASK=0x00000000,
2530 GCP_USEKERNING_MASK=0x00000000,
2531 GCP_REORDER_MASK=0x00000060;
2533 DWORD result=0;
2535 GetTextCharsetInfo( hdc, &fontsig, 0 );
2536 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2538 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2539 result|=GCP_DBCS;
2541 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2542 result|=GCP_DIACRITIC;
2544 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2545 result|=FLI_GLYPHS;
2547 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2548 result|=GCP_GLYPHSHAPE;
2550 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2551 result|=GCP_KASHIDA;
2553 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2554 result|=GCP_LIGATE;
2556 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2557 result|=GCP_USEKERNING;
2559 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2560 if( GetTextAlign( hdc) & TA_RTLREADING )
2561 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2562 result|=GCP_REORDER;
2564 return result;
2568 /*************************************************************************
2569 * GetFontData [GDI32.@]
2571 * Retrieve data for TrueType font.
2573 * RETURNS
2575 * success: Number of bytes returned
2576 * failure: GDI_ERROR
2578 * NOTES
2580 * Calls SetLastError()
2583 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2584 LPVOID buffer, DWORD length)
2586 DC *dc = DC_GetDCPtr(hdc);
2587 DWORD ret = GDI_ERROR;
2589 if(!dc) return GDI_ERROR;
2591 if(dc->gdiFont)
2592 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2594 GDI_ReleaseObj(hdc);
2595 return ret;
2598 /*************************************************************************
2599 * GetGlyphIndicesA [GDI32.@]
2601 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2602 LPWORD pgi, DWORD flags)
2604 DWORD ret;
2605 WCHAR *lpstrW;
2606 INT countW;
2608 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2609 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2611 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2612 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2613 HeapFree(GetProcessHeap(), 0, lpstrW);
2615 return ret;
2618 /*************************************************************************
2619 * GetGlyphIndicesW [GDI32.@]
2621 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2622 LPWORD pgi, DWORD flags)
2624 DC *dc = DC_GetDCPtr(hdc);
2625 DWORD ret = GDI_ERROR;
2627 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
2628 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2630 if(!dc) return GDI_ERROR;
2632 if(dc->gdiFont)
2633 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2635 GDI_ReleaseObj(hdc);
2636 return ret;
2639 /*************************************************************************
2640 * GetCharacterPlacementA [GDI32.@]
2642 * See GetCharacterPlacementW.
2644 * NOTES:
2645 * the web browser control of ie4 calls this with dwFlags=0
2647 DWORD WINAPI
2648 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2649 INT nMaxExtent, GCP_RESULTSA *lpResults,
2650 DWORD dwFlags)
2652 WCHAR *lpStringW;
2653 INT uCountW;
2654 GCP_RESULTSW resultsW;
2655 DWORD ret;
2656 UINT font_cp;
2658 TRACE("%s, %d, %d, 0x%08lx\n",
2659 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2661 /* both structs are equal in size */
2662 memcpy(&resultsW, lpResults, sizeof(resultsW));
2664 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2665 if(lpResults->lpOutString)
2666 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2668 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2670 if(lpResults->lpOutString) {
2671 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2672 lpResults->lpOutString, uCount, NULL, NULL );
2675 HeapFree(GetProcessHeap(), 0, lpStringW);
2676 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2678 return ret;
2681 /*************************************************************************
2682 * GetCharacterPlacementW [GDI32.@]
2684 * Retrieve information about a string. This includes the width, reordering,
2685 * Glyphing and so on.
2687 * RETURNS
2689 * The width and height of the string if successful, 0 if failed.
2691 * BUGS
2693 * All flags except GCP_REORDER are not yet implemented.
2694 * Reordering is not 100% complient to the Windows BiDi method.
2695 * Caret positioning is not yet implemented for BiDi.
2696 * Classes are not yet implemented.
2699 DWORD WINAPI
2700 GetCharacterPlacementW(
2701 HDC hdc, /* [in] Device context for which the rendering is to be done */
2702 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2703 INT uCount, /* [in] Number of WORDS in string. */
2704 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2705 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2706 DWORD dwFlags /* [in] Flags specifying how to process the string */
2709 DWORD ret=0;
2710 SIZE size;
2711 UINT i, nSet;
2713 TRACE("%s, %d, %d, 0x%08lx\n",
2714 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2716 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2717 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2718 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2719 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2720 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2722 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2723 if(lpResults->lpClass) FIXME("classes not implemented\n");
2724 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2725 FIXME("Caret positions for complex scripts not implemented\n");
2727 nSet = (UINT)uCount;
2728 if(nSet > lpResults->nGlyphs)
2729 nSet = lpResults->nGlyphs;
2731 /* return number of initialized fields */
2732 lpResults->nGlyphs = nSet;
2734 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2736 /* Treat the case where no special handling was requested in a fastpath way */
2737 /* copy will do if the GCP_REORDER flag is not set */
2738 if(lpResults->lpOutString)
2739 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2741 if(lpResults->lpOrder)
2743 for(i = 0; i < nSet; i++)
2744 lpResults->lpOrder[i] = i;
2746 } else
2748 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2749 nSet, lpResults->lpOrder );
2752 /* FIXME: Will use the placement chars */
2753 if (lpResults->lpDx)
2755 int c;
2756 for (i = 0; i < nSet; i++)
2758 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2759 lpResults->lpDx[i]= c;
2763 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2765 int pos = 0;
2767 lpResults->lpCaretPos[0] = 0;
2768 for (i = 1; i < nSet; i++)
2769 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2770 lpResults->lpCaretPos[i] = (pos += size.cx);
2773 if(lpResults->lpGlyphs)
2774 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2776 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2777 ret = MAKELONG(size.cx, size.cy);
2779 return ret;
2782 /*************************************************************************
2783 * GetCharABCWidthsFloatA [GDI32.@]
2785 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2786 LPABCFLOAT lpABCF)
2788 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2789 return 0;
2792 /*************************************************************************
2793 * GetCharABCWidthsFloatW [GDI32.@]
2795 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2796 UINT iLastChar, LPABCFLOAT lpABCF)
2798 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2799 return 0;
2802 /*************************************************************************
2803 * GetCharWidthFloatA [GDI32.@]
2805 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2806 UINT iLastChar, PFLOAT pxBuffer)
2808 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2809 return 0;
2812 /*************************************************************************
2813 * GetCharWidthFloatW [GDI32.@]
2815 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2816 UINT iLastChar, PFLOAT pxBuffer)
2818 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2819 return 0;
2823 /***********************************************************************
2825 * Font Resource API *
2827 ***********************************************************************/
2829 /***********************************************************************
2830 * AddFontResourceA (GDI32.@)
2832 INT WINAPI AddFontResourceA( LPCSTR str )
2834 return AddFontResourceExA( str, 0, NULL);
2837 /***********************************************************************
2838 * AddFontResourceW (GDI32.@)
2840 INT WINAPI AddFontResourceW( LPCWSTR str )
2842 return AddFontResourceExW(str, 0, NULL);
2846 /***********************************************************************
2847 * AddFontResourceExA (GDI32.@)
2849 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2851 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2852 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2853 INT ret;
2855 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2856 ret = AddFontResourceExW(strW, fl, pdv);
2857 HeapFree(GetProcessHeap(), 0, strW);
2858 return ret;
2861 /***********************************************************************
2862 * AddFontResourceExW (GDI32.@)
2864 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2866 return WineEngAddFontResourceEx(str, fl, pdv);
2869 /***********************************************************************
2870 * RemoveFontResourceA (GDI32.@)
2872 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2874 return RemoveFontResourceExA(str, 0, 0);
2877 /***********************************************************************
2878 * RemoveFontResourceW (GDI32.@)
2880 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2882 return RemoveFontResourceExW(str, 0, 0);
2885 /***********************************************************************
2886 * AddFontMemResourceEx (GDI32.@)
2888 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
2890 FIXME("(%p,%08lx,%p,%p): stub\n", pbFont, cbFont, pdv, pcFonts);
2891 return NULL;
2894 /***********************************************************************
2895 * RemoveFontResourceExA (GDI32.@)
2897 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2899 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2900 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2901 INT ret;
2903 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2904 ret = RemoveFontResourceExW(strW, fl, pdv);
2905 HeapFree(GetProcessHeap(), 0, strW);
2906 return ret;
2909 /***********************************************************************
2910 * RemoveFontResourceExW (GDI32.@)
2912 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2914 return WineEngRemoveFontResourceEx(str, fl, pdv);
2917 /***********************************************************************
2918 * GetTextCharset (GDI32.@)
2920 UINT WINAPI GetTextCharset(HDC hdc)
2922 /* MSDN docs say this is equivalent */
2923 return GetTextCharsetInfo(hdc, NULL, 0);
2926 /***********************************************************************
2927 * GetTextCharsetInfo (GDI32.@)
2929 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2931 UINT ret = DEFAULT_CHARSET;
2932 DC *dc = DC_GetDCPtr(hdc);
2934 if (!dc) goto done;
2936 if (dc->gdiFont)
2937 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2939 GDI_ReleaseObj(hdc);
2941 done:
2942 if (ret == DEFAULT_CHARSET && fs)
2943 memset(fs, 0, sizeof(FONTSIGNATURE));
2944 return ret;
2947 /***********************************************************************
2948 * GdiGetCharDimensions (GDI32.@)
2950 * Gets the average width of the characters in the English alphabet.
2952 * PARAMS
2953 * hdc [I] Handle to the device context to measure on.
2954 * lptm [O] Pointer to memory to store the text metrics into.
2955 * height [O] On exit, the maximum height of characters in the English alphabet.
2957 * RETURNS
2958 * The average width of characters in the English alphabet.
2960 * NOTES
2961 * This function is used by the dialog manager to get the size of a dialog
2962 * unit. It should also be used by other pieces of code that need to know
2963 * the size of a dialog unit in logical units without having access to the
2964 * window handle of the dialog.
2965 * Windows caches the font metrics from this function, but we don't and
2966 * there doesn't appear to be an immediate advantage to do so.
2968 * SEE ALSO
2969 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
2971 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
2973 SIZE sz;
2974 static const WCHAR alphabet[] = {
2975 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
2976 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
2977 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
2979 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
2981 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
2983 if (height) *height = sz.cy;
2984 return (sz.cx / 26 + 1) / 2;
2987 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
2989 FIXME("(%d): stub\n", fEnableEUDC);
2990 return FALSE;