d3dx8: Implement D3DXMatrixRotationZ.
[wine/multimedia.git] / dlls / gdi32 / font.c
blob3b6ec3b553fc5ad2b08cb453df998e2bc67aa03c
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
48 FLOAT floatWidth;
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
61 FLOAT floatHeight;
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
93 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
95 static const struct gdi_obj_funcs font_funcs =
97 FONT_SelectObject, /* pSelectObject */
98 FONT_GetObject16, /* pGetObject16 */
99 FONT_GetObjectA, /* pGetObjectA */
100 FONT_GetObjectW, /* pGetObjectW */
101 NULL, /* pUnrealizeObject */
102 FONT_DeleteObject /* pDeleteObject */
105 #define ENUM_UNICODE 0x00000001
106 #define ENUM_CALLED 0x00000002
108 typedef struct
110 GDIOBJHDR header;
111 LOGFONTW logfont;
112 } FONTOBJ;
114 typedef struct
116 LPLOGFONT16 lpLogFontParam;
117 FONTENUMPROC16 lpEnumFunc;
118 LPARAM lpData;
120 LPNEWTEXTMETRICEX16 lpTextMetric;
121 LPENUMLOGFONTEX16 lpLogFont;
122 SEGPTR segTextMetric;
123 SEGPTR segLogFont;
124 DWORD dwFlags;
125 HDC hdc;
126 DC *dc;
127 PHYSDEV physDev;
128 } fontEnum16;
130 typedef struct
132 LPLOGFONTW lpLogFontParam;
133 FONTENUMPROCW lpEnumFunc;
134 LPARAM lpData;
135 DWORD dwFlags;
136 HDC hdc;
137 DC *dc;
138 PHYSDEV physDev;
139 } fontEnum32;
142 * For TranslateCharsetInfo
144 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
145 #define MAXTCIINDEX 32
146 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
147 /* ANSI */
148 { ANSI_CHARSET, 1252, FS(0)},
149 { EASTEUROPE_CHARSET, 1250, FS(1)},
150 { RUSSIAN_CHARSET, 1251, FS(2)},
151 { GREEK_CHARSET, 1253, FS(3)},
152 { TURKISH_CHARSET, 1254, FS(4)},
153 { HEBREW_CHARSET, 1255, FS(5)},
154 { ARABIC_CHARSET, 1256, FS(6)},
155 { BALTIC_CHARSET, 1257, FS(7)},
156 { VIETNAMESE_CHARSET, 1258, FS(8)},
157 /* reserved by ANSI */
158 { DEFAULT_CHARSET, 0, FS(0)},
159 { DEFAULT_CHARSET, 0, FS(0)},
160 { DEFAULT_CHARSET, 0, FS(0)},
161 { DEFAULT_CHARSET, 0, FS(0)},
162 { DEFAULT_CHARSET, 0, FS(0)},
163 { DEFAULT_CHARSET, 0, FS(0)},
164 { DEFAULT_CHARSET, 0, FS(0)},
165 /* ANSI and OEM */
166 { THAI_CHARSET, 874, FS(16)},
167 { SHIFTJIS_CHARSET, 932, FS(17)},
168 { GB2312_CHARSET, 936, FS(18)},
169 { HANGEUL_CHARSET, 949, FS(19)},
170 { CHINESEBIG5_CHARSET, 950, FS(20)},
171 { JOHAB_CHARSET, 1361, FS(21)},
172 /* reserved for alternate ANSI and OEM */
173 { DEFAULT_CHARSET, 0, FS(0)},
174 { DEFAULT_CHARSET, 0, FS(0)},
175 { DEFAULT_CHARSET, 0, FS(0)},
176 { DEFAULT_CHARSET, 0, FS(0)},
177 { DEFAULT_CHARSET, 0, FS(0)},
178 { DEFAULT_CHARSET, 0, FS(0)},
179 { DEFAULT_CHARSET, 0, FS(0)},
180 { DEFAULT_CHARSET, 0, FS(0)},
181 /* reserved for system */
182 { DEFAULT_CHARSET, 0, FS(0)},
183 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
186 /***********************************************************************
187 * LOGFONT conversion functions.
189 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
191 font16->lfHeight = font32->lfHeight;
192 font16->lfWidth = font32->lfWidth;
193 font16->lfEscapement = font32->lfEscapement;
194 font16->lfOrientation = font32->lfOrientation;
195 font16->lfWeight = font32->lfWeight;
196 font16->lfItalic = font32->lfItalic;
197 font16->lfUnderline = font32->lfUnderline;
198 font16->lfStrikeOut = font32->lfStrikeOut;
199 font16->lfCharSet = font32->lfCharSet;
200 font16->lfOutPrecision = font32->lfOutPrecision;
201 font16->lfClipPrecision = font32->lfClipPrecision;
202 font16->lfQuality = font32->lfQuality;
203 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
204 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
205 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
206 font16->lfFaceName[LF_FACESIZE-1] = 0;
209 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
211 font32->lfHeight = font16->lfHeight;
212 font32->lfWidth = font16->lfWidth;
213 font32->lfEscapement = font16->lfEscapement;
214 font32->lfOrientation = font16->lfOrientation;
215 font32->lfWeight = font16->lfWeight;
216 font32->lfItalic = font16->lfItalic;
217 font32->lfUnderline = font16->lfUnderline;
218 font32->lfStrikeOut = font16->lfStrikeOut;
219 font32->lfCharSet = font16->lfCharSet;
220 font32->lfOutPrecision = font16->lfOutPrecision;
221 font32->lfClipPrecision = font16->lfClipPrecision;
222 font32->lfQuality = font16->lfQuality;
223 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
224 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
225 font32->lfFaceName[LF_FACESIZE-1] = 0;
228 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
230 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
231 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
232 LF_FACESIZE);
233 fontW->lfFaceName[LF_FACESIZE-1] = 0;
236 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
238 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
239 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
240 LF_FACESIZE, NULL, NULL);
241 fontA->lfFaceName[LF_FACESIZE-1] = 0;
244 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
246 FONT_LogFontWTo16( (const LOGFONTW *)fontW, (LPLOGFONT16)font16);
248 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
249 (LPSTR) font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
250 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
251 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
252 (LPSTR) font16->elfStyle, LF_FACESIZE, NULL, NULL );
253 font16->elfStyle[LF_FACESIZE-1] = '\0';
254 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
255 (LPSTR) font16->elfScript, LF_FACESIZE, NULL, NULL );
256 font16->elfScript[LF_FACESIZE-1] = '\0';
259 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
261 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
263 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
264 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
265 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
266 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
267 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
268 fontA->elfStyle[LF_FACESIZE-1] = '\0';
269 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
270 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
271 fontA->elfScript[LF_FACESIZE-1] = '\0';
274 /***********************************************************************
275 * TEXTMETRIC conversion functions.
277 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
279 ptmA->tmHeight = ptmW->tmHeight;
280 ptmA->tmAscent = ptmW->tmAscent;
281 ptmA->tmDescent = ptmW->tmDescent;
282 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
283 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
284 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
285 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
286 ptmA->tmWeight = ptmW->tmWeight;
287 ptmA->tmOverhang = ptmW->tmOverhang;
288 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
289 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
290 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
291 if (ptmW->tmCharSet == SYMBOL_CHARSET)
293 UINT last_char = ptmW->tmLastChar;
294 if (last_char > 0xf000) last_char -= 0xf000;
295 ptmA->tmLastChar = min(last_char, 255);
297 else
298 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
299 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
300 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
301 ptmA->tmItalic = ptmW->tmItalic;
302 ptmA->tmUnderlined = ptmW->tmUnderlined;
303 ptmA->tmStruckOut = ptmW->tmStruckOut;
304 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
305 ptmA->tmCharSet = ptmW->tmCharSet;
309 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
311 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
312 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
313 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
314 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
315 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
316 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
317 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
318 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
319 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
320 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
321 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
322 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
323 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
324 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
325 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
326 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
327 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
328 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
329 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
330 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
331 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
332 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
333 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
334 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
335 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
338 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
340 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
341 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
342 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
343 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
344 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
345 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
349 /***********************************************************************
350 * GdiGetCodePage (GDI32.@)
352 DWORD WINAPI GdiGetCodePage( HDC hdc )
354 UINT cp = CP_ACP;
355 CHARSETINFO csi;
356 int charset = GetTextCharset(hdc);
358 /* Hmm, nicely designed api this one! */
359 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
360 cp = csi.ciACP;
361 else {
362 switch(charset) {
363 case OEM_CHARSET:
364 cp = GetOEMCP();
365 break;
366 case DEFAULT_CHARSET:
367 cp = GetACP();
368 break;
370 case VISCII_CHARSET:
371 case TCVN_CHARSET:
372 case KOI8_CHARSET:
373 case ISO3_CHARSET:
374 case ISO4_CHARSET:
375 case ISO10_CHARSET:
376 case CELTIC_CHARSET:
377 /* FIXME: These have no place here, but because x11drv
378 enumerates fonts with these (made up) charsets some apps
379 might use them and then the FIXME below would become
380 annoying. Now we could pick the intended codepage for
381 each of these, but since it's broken anyway we'll just
382 use CP_ACP and hope it'll go away...
384 cp = CP_ACP;
385 break;
387 default:
388 FIXME("Can't find codepage for charset %d\n", charset);
389 break;
393 TRACE("charset %d => cp %d\n", charset, cp);
394 return cp;
397 /***********************************************************************
398 * FONT_mbtowc
400 * Returns a Unicode translation of str using the charset of the
401 * currently selected font in hdc. If count is -1 then str is assumed
402 * to be '\0' terminated, otherwise it contains the number of bytes to
403 * convert. If plenW is non-NULL, on return it will point to the
404 * number of WCHARs that have been written. If pCP is non-NULL, on
405 * return it will point to the codepage used in the conversion. The
406 * caller should free the returned LPWSTR from the process heap
407 * itself.
409 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
411 UINT cp;
412 INT lenW;
413 LPWSTR strW;
415 cp = GdiGetCodePage( hdc );
417 if(count == -1) count = strlen(str);
418 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
419 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
420 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
421 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
422 if(plenW) *plenW = lenW;
423 if(pCP) *pCP = cp;
424 return strW;
428 /***********************************************************************
429 * CreateFontIndirectA (GDI32.@)
431 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
433 LOGFONTW lfW;
435 if (plfA) {
436 FONT_LogFontAToW( plfA, &lfW );
437 return CreateFontIndirectW( &lfW );
438 } else
439 return CreateFontIndirectW( NULL );
443 /***********************************************************************
444 * CreateFontIndirectW (GDI32.@)
446 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
448 HFONT hFont = 0;
450 if (plf)
452 FONTOBJ* fontPtr;
453 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
454 (HGDIOBJ *)&hFont, &font_funcs )))
456 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
457 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
458 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
459 WCHAR* pFaceNameSuffix = NULL;
461 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
463 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
464 plf->lfHeight, plf->lfWidth,
465 plf->lfEscapement, plf->lfOrientation,
466 plf->lfPitchAndFamily,
467 plf->lfOutPrecision, plf->lfClipPrecision,
468 plf->lfQuality, plf->lfCharSet,
469 debugstr_w(plf->lfFaceName),
470 plf->lfWeight > 400 ? "Bold" : "",
471 plf->lfItalic ? "Italic" : "",
472 plf->lfUnderline ? "Underline" : "", hFont);
474 if (plf->lfEscapement != plf->lfOrientation) {
475 /* this should really depend on whether GM_ADVANCED is set */
476 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
477 WARN("orientation angle %f set to "
478 "escapement angle %f for new font %p\n",
479 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
482 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
483 if (pFaceNameItalicSuffix) {
484 fontPtr->logfont.lfItalic = TRUE;
485 pFaceNameSuffix = pFaceNameItalicSuffix;
488 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
489 if (pFaceNameBoldSuffix) {
490 if (fontPtr->logfont.lfWeight < FW_BOLD) {
491 fontPtr->logfont.lfWeight = FW_BOLD;
493 if (!pFaceNameSuffix ||
494 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
495 pFaceNameSuffix = pFaceNameBoldSuffix;
499 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
501 GDI_ReleaseObj( hFont );
504 else WARN("(NULL) => NULL\n");
506 return hFont;
509 /*************************************************************************
510 * CreateFontA (GDI32.@)
512 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
513 INT orient, INT weight, DWORD italic,
514 DWORD underline, DWORD strikeout, DWORD charset,
515 DWORD outpres, DWORD clippres, DWORD quality,
516 DWORD pitch, LPCSTR name )
518 LOGFONTA logfont;
520 logfont.lfHeight = height;
521 logfont.lfWidth = width;
522 logfont.lfEscapement = esc;
523 logfont.lfOrientation = orient;
524 logfont.lfWeight = weight;
525 logfont.lfItalic = italic;
526 logfont.lfUnderline = underline;
527 logfont.lfStrikeOut = strikeout;
528 logfont.lfCharSet = charset;
529 logfont.lfOutPrecision = outpres;
530 logfont.lfClipPrecision = clippres;
531 logfont.lfQuality = quality;
532 logfont.lfPitchAndFamily = pitch;
534 if (name)
535 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
536 else
537 logfont.lfFaceName[0] = '\0';
539 return CreateFontIndirectA( &logfont );
542 /*************************************************************************
543 * CreateFontW (GDI32.@)
545 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
546 INT orient, INT weight, DWORD italic,
547 DWORD underline, DWORD strikeout, DWORD charset,
548 DWORD outpres, DWORD clippres, DWORD quality,
549 DWORD pitch, LPCWSTR name )
551 LOGFONTW logfont;
553 logfont.lfHeight = height;
554 logfont.lfWidth = width;
555 logfont.lfEscapement = esc;
556 logfont.lfOrientation = orient;
557 logfont.lfWeight = weight;
558 logfont.lfItalic = italic;
559 logfont.lfUnderline = underline;
560 logfont.lfStrikeOut = strikeout;
561 logfont.lfCharSet = charset;
562 logfont.lfOutPrecision = outpres;
563 logfont.lfClipPrecision = clippres;
564 logfont.lfQuality = quality;
565 logfont.lfPitchAndFamily = pitch;
567 if (name)
568 lstrcpynW(logfont.lfFaceName, name,
569 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
570 else
571 logfont.lfFaceName[0] = '\0';
573 return CreateFontIndirectW( &logfont );
577 /***********************************************************************
578 * FONT_SelectObject
580 * If the driver supports vector fonts we create a gdi font first and
581 * then call the driver to give it a chance to supply its own device
582 * font. If the driver wants to do this it returns TRUE and we can
583 * delete the gdi font, if the driver wants to use the gdi font it
584 * should return FALSE, to signal an error return GDI_ERROR. For
585 * drivers that don't support vector fonts they must supply their own
586 * font.
588 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
590 HGDIOBJ ret = 0;
591 DC *dc = get_dc_ptr( hdc );
593 if (!dc) return 0;
595 if (!GDI_inc_ref_count( handle ))
597 release_dc_ptr( dc );
598 return 0;
601 if (dc->hFont != handle || dc->gdiFont == NULL)
603 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
605 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
606 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
607 if (font) GDI_ReleaseObj( handle );
611 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
613 if (ret && dc->gdiFont) dc->gdiFont = 0;
615 if (ret == HGDI_ERROR)
617 GDI_dec_ref_count( handle );
618 ret = 0; /* SelectObject returns 0 on error */
620 else
622 ret = dc->hFont;
623 dc->hFont = handle;
624 GDI_dec_ref_count( ret );
626 release_dc_ptr( dc );
627 return ret;
631 /***********************************************************************
632 * FONT_GetObject16
634 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
636 FONTOBJ *font = obj;
637 LOGFONT16 lf16;
639 FONT_LogFontWTo16( &font->logfont, &lf16 );
641 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
642 memcpy( buffer, &lf16, count );
643 return count;
646 /***********************************************************************
647 * FONT_GetObjectA
649 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
651 FONTOBJ *font = obj;
652 LOGFONTA lfA;
654 if(!buffer)
655 return sizeof(lfA);
656 FONT_LogFontWToA( &font->logfont, &lfA );
658 if (count > sizeof(lfA)) count = sizeof(lfA);
659 memcpy( buffer, &lfA, count );
660 return count;
663 /***********************************************************************
664 * FONT_GetObjectW
666 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
668 FONTOBJ *font = obj;
669 if(!buffer)
670 return sizeof(LOGFONTW);
671 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
672 memcpy( buffer, &font->logfont, count );
673 return count;
677 /***********************************************************************
678 * FONT_DeleteObject
680 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
682 WineEngDestroyFontInstance( handle );
683 return GDI_FreeObject( handle, obj );
687 /***********************************************************************
688 * FONT_EnumInstance16
690 * Called by the device driver layer to pass font info
691 * down to the application.
693 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
694 * We have to use other types because of the FONTENUMPROCW definition.
696 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
697 DWORD fType, LPARAM lp )
699 fontEnum16 *pfe = (fontEnum16*)lp;
700 INT ret = 1;
701 DC *dc;
703 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
704 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
706 WORD args[7];
707 DWORD result;
709 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
710 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
711 pfe->dwFlags |= ENUM_CALLED;
712 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
714 args[6] = SELECTOROF(pfe->segLogFont);
715 args[5] = OFFSETOF(pfe->segLogFont);
716 args[4] = SELECTOROF(pfe->segTextMetric);
717 args[3] = OFFSETOF(pfe->segTextMetric);
718 args[2] = fType;
719 args[1] = HIWORD(pfe->lpData);
720 args[0] = LOWORD(pfe->lpData);
721 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
722 ret = LOWORD(result);
724 /* get the lock again and make sure the DC is still valid */
725 dc = DC_GetDCPtr( pfe->hdc );
726 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
728 if (dc) DC_ReleaseDCPtr( dc );
729 pfe->hdc = 0; /* make sure we don't try to release it later on */
730 pfe->dc = NULL;
731 ret = 0;
734 return ret;
737 /***********************************************************************
738 * FONT_EnumInstance
740 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
741 * We have to use other types because of the FONTENUMPROCW definition.
743 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
744 DWORD fType, LPARAM lp )
746 fontEnum32 *pfe = (fontEnum32*)lp;
747 INT ret = 1;
748 DC *dc;
750 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
751 if((pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
752 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
753 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
755 /* convert font metrics */
756 ENUMLOGFONTEXA logfont;
757 NEWTEXTMETRICEXA tmA;
759 pfe->dwFlags |= ENUM_CALLED;
760 if (!(pfe->dwFlags & ENUM_UNICODE))
762 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
763 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
764 plf = (LOGFONTW *)&logfont.elfLogFont;
765 ptm = (TEXTMETRICW *)&tmA;
767 DC_ReleaseDCPtr( pfe->dc ); /* release the GDI lock */
769 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
771 /* get the lock again and make sure the DC is still valid */
772 dc = DC_GetDCPtr( pfe->hdc );
773 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
775 if (dc) DC_ReleaseDCPtr( dc );
776 pfe->hdc = 0; /* make sure we don't try to release it later on */
777 pfe->dc = NULL;
778 ret = 0;
781 return ret;
784 /***********************************************************************
785 * EnumFontFamiliesEx (GDI.613)
787 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
788 FONTENUMPROC16 efproc, LPARAM lParam,
789 DWORD dwFlags)
791 fontEnum16 fe16;
792 INT16 ret = 1, ret2;
793 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
794 NEWTEXTMETRICEX16 tm16;
795 ENUMLOGFONTEX16 lf16;
796 LOGFONTW lfW;
797 BOOL enum_gdi_fonts;
799 if (!dc) return 0;
800 FONT_LogFont16ToW(plf, &lfW);
802 fe16.hdc = HDC_32(hDC);
803 fe16.dc = dc;
804 fe16.physDev = dc->physDev;
805 fe16.lpLogFontParam = plf;
806 fe16.lpEnumFunc = efproc;
807 fe16.lpData = lParam;
808 fe16.lpTextMetric = &tm16;
809 fe16.lpLogFont = &lf16;
810 fe16.segTextMetric = MapLS( &tm16 );
811 fe16.segLogFont = MapLS( &lf16 );
812 fe16.dwFlags = 0;
814 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
816 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
818 ret = 0;
819 goto done;
822 if (enum_gdi_fonts)
823 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
824 fe16.dwFlags &= ~ENUM_CALLED;
825 if (ret && dc->funcs->pEnumDeviceFonts) {
826 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
827 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
828 ret = ret2;
830 done:
831 UnMapLS( fe16.segTextMetric );
832 UnMapLS( fe16.segLogFont );
833 if (fe16.dc) DC_ReleaseDCPtr( fe16.dc );
834 return ret;
837 /***********************************************************************
838 * FONT_EnumFontFamiliesEx
840 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
841 FONTENUMPROCW efproc,
842 LPARAM lParam, DWORD dwUnicode)
844 INT ret = 1, ret2;
845 DC *dc = DC_GetDCPtr( hDC );
846 fontEnum32 fe32;
847 BOOL enum_gdi_fonts;
849 if (!dc) return 0;
851 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
852 plf->lfCharSet);
853 fe32.lpLogFontParam = plf;
854 fe32.lpEnumFunc = efproc;
855 fe32.lpData = lParam;
856 fe32.dwFlags = dwUnicode;
857 fe32.hdc = hDC;
858 fe32.dc = dc;
859 fe32.physDev = dc->physDev;
861 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
863 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
865 ret = 0;
866 goto done;
869 if (enum_gdi_fonts)
870 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
871 fe32.dwFlags &= ~ENUM_CALLED;
872 if (ret && dc->funcs->pEnumDeviceFonts) {
873 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
874 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
875 ret = ret2;
877 done:
878 if (fe32.dc) DC_ReleaseDCPtr( fe32.dc );
879 return ret;
882 /***********************************************************************
883 * EnumFontFamiliesExW (GDI32.@)
885 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
886 FONTENUMPROCW efproc,
887 LPARAM lParam, DWORD dwFlags )
889 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
892 /***********************************************************************
893 * EnumFontFamiliesExA (GDI32.@)
895 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
896 FONTENUMPROCA efproc,
897 LPARAM lParam, DWORD dwFlags)
899 LOGFONTW lfW;
900 FONT_LogFontAToW( plf, &lfW );
902 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
905 /***********************************************************************
906 * EnumFontFamilies (GDI.330)
908 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
909 FONTENUMPROC16 efproc, LPARAM lpData )
911 LOGFONT16 lf;
913 lf.lfCharSet = DEFAULT_CHARSET;
914 if (lpFamily)
916 if (!*lpFamily) return 1;
917 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
919 else lf.lfFaceName[0] = '\0';
921 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
924 /***********************************************************************
925 * EnumFontFamiliesA (GDI32.@)
927 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
928 FONTENUMPROCA efproc, LPARAM lpData )
930 LOGFONTA lf;
932 lf.lfCharSet = DEFAULT_CHARSET;
933 if (lpFamily)
935 if (!*lpFamily) return 1;
936 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
938 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
940 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
943 /***********************************************************************
944 * EnumFontFamiliesW (GDI32.@)
946 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
947 FONTENUMPROCW efproc, LPARAM lpData )
949 LOGFONTW lf;
951 lf.lfCharSet = DEFAULT_CHARSET;
952 if (lpFamily)
954 if (!*lpFamily) return 1;
955 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
957 else lf.lfFaceName[0] = 0;
959 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
962 /***********************************************************************
963 * EnumFonts (GDI.70)
965 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
966 LPARAM lpData )
968 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
971 /***********************************************************************
972 * EnumFontsA (GDI32.@)
974 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
975 LPARAM lpData )
977 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
980 /***********************************************************************
981 * EnumFontsW (GDI32.@)
983 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
984 LPARAM lpData )
986 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
990 /***********************************************************************
991 * GetTextCharacterExtra (GDI32.@)
993 INT WINAPI GetTextCharacterExtra( HDC hdc )
995 INT ret;
996 DC *dc = DC_GetDCPtr( hdc );
997 if (!dc) return 0x80000000;
998 ret = dc->charExtra;
999 DC_ReleaseDCPtr( dc );
1000 return ret;
1004 /***********************************************************************
1005 * SetTextCharacterExtra (GDI32.@)
1007 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
1009 INT prev;
1010 DC * dc = DC_GetDCPtr( hdc );
1011 if (!dc) return 0x80000000;
1012 if (dc->funcs->pSetTextCharacterExtra)
1013 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
1014 else
1016 prev = dc->charExtra;
1017 dc->charExtra = extra;
1019 DC_ReleaseDCPtr( dc );
1020 return prev;
1024 /***********************************************************************
1025 * SetTextJustification (GDI32.@)
1027 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
1029 BOOL ret = TRUE;
1030 DC * dc = DC_GetDCPtr( hdc );
1031 if (!dc) return FALSE;
1032 if (dc->funcs->pSetTextJustification)
1033 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
1034 else
1036 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
1037 if (!extra) breaks = 0;
1038 if (breaks)
1040 dc->breakExtra = extra / breaks;
1041 dc->breakRem = extra - (breaks * dc->breakExtra);
1043 else
1045 dc->breakExtra = 0;
1046 dc->breakRem = 0;
1049 DC_ReleaseDCPtr( dc );
1050 return ret;
1054 /***********************************************************************
1055 * GetTextFaceA (GDI32.@)
1057 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
1059 INT res = GetTextFaceW(hdc, 0, NULL);
1060 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
1061 GetTextFaceW( hdc, res, nameW );
1063 if (name)
1065 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
1066 name[count-1] = 0;
1067 res = strlen(name);
1069 else
1070 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
1071 HeapFree( GetProcessHeap(), 0, nameW );
1072 return res;
1075 /***********************************************************************
1076 * GetTextFaceW (GDI32.@)
1078 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
1080 FONTOBJ *font;
1081 INT ret = 0;
1083 DC * dc = DC_GetDCPtr( hdc );
1084 if (!dc) return 0;
1086 if(dc->gdiFont)
1087 ret = WineEngGetTextFace(dc->gdiFont, count, name);
1088 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
1090 if (name)
1092 lstrcpynW( name, font->logfont.lfFaceName, count );
1093 ret = strlenW(name);
1095 else ret = strlenW(font->logfont.lfFaceName) + 1;
1096 GDI_ReleaseObj( dc->hFont );
1098 DC_ReleaseDCPtr( dc );
1099 return ret;
1103 /***********************************************************************
1104 * GetTextExtentPoint32A (GDI32.@)
1106 * See GetTextExtentPoint32W.
1108 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
1109 LPSIZE size )
1111 BOOL ret = FALSE;
1112 INT wlen;
1113 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1115 if (p) {
1116 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
1117 HeapFree( GetProcessHeap(), 0, p );
1120 TRACE("(%p %s %d %p): returning %d x %d\n",
1121 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
1122 return ret;
1126 /***********************************************************************
1127 * GetTextExtentPoint32W [GDI32.@]
1129 * Computes width/height for a string.
1131 * Computes width and height of the specified string.
1133 * RETURNS
1134 * Success: TRUE
1135 * Failure: FALSE
1137 BOOL WINAPI GetTextExtentPoint32W(
1138 HDC hdc, /* [in] Handle of device context */
1139 LPCWSTR str, /* [in] Address of text string */
1140 INT count, /* [in] Number of characters in string */
1141 LPSIZE size) /* [out] Address of structure for string size */
1143 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1146 /***********************************************************************
1147 * GetTextExtentPointI [GDI32.@]
1149 * Computes width and height of the array of glyph indices.
1151 * RETURNS
1152 * Success: TRUE
1153 * Failure: FALSE
1155 BOOL WINAPI GetTextExtentPointI(
1156 HDC hdc, /* [in] Handle of device context */
1157 const WORD *indices, /* [in] Address of glyph index array */
1158 INT count, /* [in] Number of glyphs in array */
1159 LPSIZE size) /* [out] Address of structure for string size */
1161 BOOL ret = FALSE;
1162 DC * dc = DC_GetDCPtr( hdc );
1163 if (!dc) return FALSE;
1165 if(dc->gdiFont) {
1166 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1167 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1168 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1169 size->cx += count * dc->charExtra;
1171 else if(dc->funcs->pGetTextExtentExPoint) {
1172 FIXME("calling GetTextExtentExPoint\n");
1173 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
1174 count, 0, NULL, NULL, size );
1177 DC_ReleaseDCPtr( dc );
1179 TRACE("(%p %p %d %p): returning %d x %d\n",
1180 hdc, indices, count, size, size->cx, size->cy );
1181 return ret;
1185 /***********************************************************************
1186 * GetTextExtentPointA (GDI32.@)
1188 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1189 LPSIZE size )
1191 TRACE("not bug compatible.\n");
1192 return GetTextExtentPoint32A( hdc, str, count, size );
1195 /***********************************************************************
1196 * GetTextExtentPointW (GDI32.@)
1198 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1199 LPSIZE size )
1201 TRACE("not bug compatible.\n");
1202 return GetTextExtentPoint32W( hdc, str, count, size );
1206 /***********************************************************************
1207 * GetTextExtentExPointA (GDI32.@)
1209 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1210 INT maxExt, LPINT lpnFit,
1211 LPINT alpDx, LPSIZE size )
1213 BOOL ret;
1214 INT wlen;
1215 INT *walpDx = NULL;
1216 LPWSTR p = NULL;
1218 if (alpDx &&
1219 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
1220 return FALSE;
1222 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1223 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1224 if (walpDx)
1226 INT n = lpnFit ? *lpnFit : wlen;
1227 INT i, j;
1228 for(i = 0, j = 0; i < n; i++, j++)
1230 alpDx[j] = walpDx[i];
1231 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1234 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1235 HeapFree( GetProcessHeap(), 0, p );
1236 HeapFree( GetProcessHeap(), 0, walpDx );
1237 return ret;
1241 /***********************************************************************
1242 * GetTextExtentExPointW (GDI32.@)
1244 * Return the size of the string as it would be if it was output properly by
1245 * e.g. TextOut.
1247 * This should include
1248 * - Intercharacter spacing
1249 * - justification spacing (not yet done)
1250 * - kerning? see below
1252 * Kerning. Since kerning would be carried out by the rendering code it should
1253 * be done by the driver. However they don't support it yet. Also I am not
1254 * yet persuaded that (certainly under Win95) any kerning is actually done.
1256 * str: According to MSDN this should be null-terminated. That is not true; a
1257 * null will not terminate it early.
1258 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1259 * than count. I have seen it be either the size of the full string or
1260 * 1 less than the size of the full string. I have not seen it bear any
1261 * resemblance to the portion that would fit.
1262 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1263 * trailing intercharacter spacing and any trailing justification.
1265 * FIXME
1266 * Currently we do this by measuring each character etc. We should do it by
1267 * passing the request to the driver, perhaps by extending the
1268 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1269 * thinking about kerning issues and rounding issues in the justification.
1272 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1273 INT maxExt, LPINT lpnFit,
1274 LPINT alpDx, LPSIZE size )
1276 INT nFit = 0;
1277 LPINT dxs = NULL;
1278 DC *dc;
1279 BOOL ret = FALSE;
1280 TEXTMETRICW tm;
1282 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1284 dc = DC_GetDCPtr(hdc);
1285 if (! dc)
1286 return FALSE;
1288 GetTextMetricsW(hdc, &tm);
1290 /* If we need to calculate nFit, then we need the partial extents even if
1291 the user hasn't provided us with an array. */
1292 if (lpnFit)
1294 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1295 if (! dxs)
1297 DC_ReleaseDCPtr(dc);
1298 SetLastError(ERROR_OUTOFMEMORY);
1299 return FALSE;
1302 else
1303 dxs = alpDx;
1305 if (dc->gdiFont)
1306 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1307 0, NULL, dxs, size);
1308 else if (dc->funcs->pGetTextExtentExPoint)
1309 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1310 0, NULL, dxs, size);
1312 /* Perform device size to world size transformations. */
1313 if (ret)
1315 INT extra = dc->charExtra,
1316 breakExtra = dc->breakExtra,
1317 breakRem = dc->breakRem,
1320 if (dxs)
1322 for (i = 0; i < count; ++i)
1324 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1325 dxs[i] += (i+1) * extra;
1326 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1328 dxs[i] += breakExtra;
1329 if (breakRem > 0)
1331 breakRem--;
1332 dxs[i]++;
1335 if (dxs[i] <= maxExt)
1336 ++nFit;
1338 breakRem = dc->breakRem;
1340 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1341 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1343 if (!dxs && count > 1 && (breakExtra || breakRem))
1345 for (i = 0; i < count; i++)
1347 if (str[i] == tm.tmBreakChar)
1349 size->cx += breakExtra;
1350 if (breakRem > 0)
1352 breakRem--;
1353 (size->cx)++;
1360 if (lpnFit)
1361 *lpnFit = nFit;
1363 if (! alpDx)
1364 HeapFree(GetProcessHeap(), 0, dxs);
1366 DC_ReleaseDCPtr( dc );
1368 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1369 return ret;
1372 /***********************************************************************
1373 * GetTextMetricsA (GDI32.@)
1375 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1377 TEXTMETRICW tm32;
1379 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1380 FONT_TextMetricWToA( &tm32, metrics );
1381 return TRUE;
1384 /***********************************************************************
1385 * GetTextMetricsW (GDI32.@)
1387 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1389 BOOL ret = FALSE;
1390 DC * dc = DC_GetDCPtr( hdc );
1391 if (!dc) return FALSE;
1393 if (dc->gdiFont)
1394 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1395 else if (dc->funcs->pGetTextMetrics)
1396 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1398 if (ret)
1400 /* device layer returns values in device units
1401 * therefore we have to convert them to logical */
1403 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1404 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1406 #define WDPTOLP(x) ((x<0)? \
1407 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1408 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1409 #define HDPTOLP(y) ((y<0)? \
1410 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1411 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1413 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1414 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1415 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1416 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1417 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1418 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1419 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1420 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1421 ret = TRUE;
1422 #undef WDPTOLP
1423 #undef HDPTOLP
1424 TRACE("text metrics:\n"
1425 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1426 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1427 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1428 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1429 " PitchAndFamily = %02x\n"
1430 " --------------------\n"
1431 " InternalLeading = %i\n"
1432 " Ascent = %i\n"
1433 " Descent = %i\n"
1434 " Height = %i\n",
1435 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1436 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1437 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1438 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1439 metrics->tmPitchAndFamily,
1440 metrics->tmInternalLeading,
1441 metrics->tmAscent,
1442 metrics->tmDescent,
1443 metrics->tmHeight );
1445 DC_ReleaseDCPtr( dc );
1446 return ret;
1450 /***********************************************************************
1451 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1453 * NOTES
1454 * lpOTM should be LPOUTLINETEXTMETRIC
1456 * RETURNS
1457 * Success: Non-zero or size of required buffer
1458 * Failure: 0
1460 UINT16 WINAPI GetOutlineTextMetrics16(
1461 HDC16 hdc, /* [in] Handle of device context */
1462 UINT16 cbData, /* [in] Size of metric data array */
1463 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1465 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1466 return 0;
1470 /***********************************************************************
1471 * GetOutlineTextMetricsA (GDI32.@)
1472 * Gets metrics for TrueType fonts.
1474 * NOTES
1475 * If the supplied buffer isn't big enough Windows partially fills it up to
1476 * its given length and returns that length.
1478 * RETURNS
1479 * Success: Non-zero or size of required buffer
1480 * Failure: 0
1482 UINT WINAPI GetOutlineTextMetricsA(
1483 HDC hdc, /* [in] Handle of device context */
1484 UINT cbData, /* [in] Size of metric data array */
1485 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1487 char buf[512], *ptr;
1488 UINT ret, needed;
1489 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1490 OUTLINETEXTMETRICA *output = lpOTM;
1491 INT left, len;
1493 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1494 return 0;
1495 if(ret > sizeof(buf))
1496 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1497 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1499 needed = sizeof(OUTLINETEXTMETRICA);
1500 if(lpOTMW->otmpFamilyName)
1501 needed += WideCharToMultiByte(CP_ACP, 0,
1502 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1503 NULL, 0, NULL, NULL);
1504 if(lpOTMW->otmpFaceName)
1505 needed += WideCharToMultiByte(CP_ACP, 0,
1506 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1507 NULL, 0, NULL, NULL);
1508 if(lpOTMW->otmpStyleName)
1509 needed += WideCharToMultiByte(CP_ACP, 0,
1510 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1511 NULL, 0, NULL, NULL);
1512 if(lpOTMW->otmpFullName)
1513 needed += WideCharToMultiByte(CP_ACP, 0,
1514 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1515 NULL, 0, NULL, NULL);
1517 if(!lpOTM) {
1518 ret = needed;
1519 goto end;
1522 TRACE("needed = %d\n", needed);
1523 if(needed > cbData)
1524 /* Since the supplied buffer isn't big enough, we'll alloc one
1525 that is and memcpy the first cbData bytes into the lpOTM at
1526 the end. */
1527 output = HeapAlloc(GetProcessHeap(), 0, needed);
1529 ret = output->otmSize = min(needed, cbData);
1530 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1531 output->otmFiller = 0;
1532 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1533 output->otmfsSelection = lpOTMW->otmfsSelection;
1534 output->otmfsType = lpOTMW->otmfsType;
1535 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1536 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1537 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1538 output->otmEMSquare = lpOTMW->otmEMSquare;
1539 output->otmAscent = lpOTMW->otmAscent;
1540 output->otmDescent = lpOTMW->otmDescent;
1541 output->otmLineGap = lpOTMW->otmLineGap;
1542 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1543 output->otmsXHeight = lpOTMW->otmsXHeight;
1544 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1545 output->otmMacAscent = lpOTMW->otmMacAscent;
1546 output->otmMacDescent = lpOTMW->otmMacDescent;
1547 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1548 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1549 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1550 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1551 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1552 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1553 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1554 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1555 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1556 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1559 ptr = (char*)(output + 1);
1560 left = needed - sizeof(*output);
1562 if(lpOTMW->otmpFamilyName) {
1563 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1564 len = WideCharToMultiByte(CP_ACP, 0,
1565 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1566 ptr, left, NULL, NULL);
1567 left -= len;
1568 ptr += len;
1569 } else
1570 output->otmpFamilyName = 0;
1572 if(lpOTMW->otmpFaceName) {
1573 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1574 len = WideCharToMultiByte(CP_ACP, 0,
1575 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1576 ptr, left, NULL, NULL);
1577 left -= len;
1578 ptr += len;
1579 } else
1580 output->otmpFaceName = 0;
1582 if(lpOTMW->otmpStyleName) {
1583 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1584 len = WideCharToMultiByte(CP_ACP, 0,
1585 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1586 ptr, left, NULL, NULL);
1587 left -= len;
1588 ptr += len;
1589 } else
1590 output->otmpStyleName = 0;
1592 if(lpOTMW->otmpFullName) {
1593 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1594 len = WideCharToMultiByte(CP_ACP, 0,
1595 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1596 ptr, left, NULL, NULL);
1597 left -= len;
1598 } else
1599 output->otmpFullName = 0;
1601 assert(left == 0);
1603 if(output != lpOTM) {
1604 memcpy(lpOTM, output, cbData);
1605 HeapFree(GetProcessHeap(), 0, output);
1607 /* check if the string offsets really fit into the provided size */
1608 /* FIXME: should we check string length as well? */
1609 /* make sure that we don't read/write beyond the provided buffer */
1610 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1612 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1613 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1616 /* make sure that we don't read/write beyond the provided buffer */
1617 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1619 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1620 lpOTM->otmpFaceName = 0; /* doesn't fit */
1623 /* make sure that we don't read/write beyond the provided buffer */
1624 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1626 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1627 lpOTM->otmpStyleName = 0; /* doesn't fit */
1630 /* make sure that we don't read/write beyond the provided buffer */
1631 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1633 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1634 lpOTM->otmpFullName = 0; /* doesn't fit */
1638 end:
1639 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1640 HeapFree(GetProcessHeap(), 0, lpOTMW);
1642 return ret;
1646 /***********************************************************************
1647 * GetOutlineTextMetricsW [GDI32.@]
1649 UINT WINAPI GetOutlineTextMetricsW(
1650 HDC hdc, /* [in] Handle of device context */
1651 UINT cbData, /* [in] Size of metric data array */
1652 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1654 DC *dc = DC_GetDCPtr( hdc );
1655 OUTLINETEXTMETRICW *output = lpOTM;
1656 UINT ret;
1658 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1659 if(!dc) return 0;
1661 if(dc->gdiFont) {
1662 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1663 if(lpOTM && ret) {
1664 if(ret > cbData) {
1665 output = HeapAlloc(GetProcessHeap(), 0, ret);
1666 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1669 #define WDPTOLP(x) ((x<0)? \
1670 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1671 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1672 #define HDPTOLP(y) ((y<0)? \
1673 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1674 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1676 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1677 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1678 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1679 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1680 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1681 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1682 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1683 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1684 output->otmAscent = HDPTOLP(output->otmAscent);
1685 output->otmDescent = HDPTOLP(output->otmDescent);
1686 output->otmLineGap = HDPTOLP(output->otmLineGap);
1687 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1688 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1689 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1690 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1691 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1692 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1693 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1694 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1695 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1696 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1697 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1698 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1699 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1700 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1701 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1702 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1703 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1704 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1705 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1706 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1707 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1708 #undef WDPTOLP
1709 #undef HDPTOLP
1710 if(output != lpOTM) {
1711 memcpy(lpOTM, output, cbData);
1712 HeapFree(GetProcessHeap(), 0, output);
1713 ret = cbData;
1718 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1719 but really this should just be a return 0. */
1721 ret = sizeof(*lpOTM);
1722 if (lpOTM) {
1723 if(cbData < ret)
1724 ret = 0;
1725 else {
1726 memset(lpOTM, 0, ret);
1727 lpOTM->otmSize = sizeof(*lpOTM);
1728 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1730 Further fill of the structure not implemented,
1731 Needs real values for the structure members
1736 DC_ReleaseDCPtr(dc);
1737 return ret;
1741 /***********************************************************************
1742 * GetCharWidthW (GDI32.@)
1743 * GetCharWidth32W (GDI32.@)
1745 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1746 LPINT buffer )
1748 UINT i;
1749 BOOL ret = FALSE;
1750 DC * dc = DC_GetDCPtr( hdc );
1751 if (!dc) return FALSE;
1753 if (dc->gdiFont)
1754 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1755 else if (dc->funcs->pGetCharWidth)
1756 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1758 if (ret)
1760 /* convert device units to logical */
1761 for( i = firstChar; i <= lastChar; i++, buffer++ )
1762 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1763 ret = TRUE;
1765 DC_ReleaseDCPtr( dc );
1766 return ret;
1770 /***********************************************************************
1771 * GetCharWidthA (GDI32.@)
1772 * GetCharWidth32A (GDI32.@)
1774 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1775 LPINT buffer )
1777 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1778 LPSTR str;
1779 LPWSTR wstr;
1780 BOOL ret = TRUE;
1782 if(count <= 0) return FALSE;
1784 str = HeapAlloc(GetProcessHeap(), 0, count);
1785 for(i = 0; i < count; i++)
1786 str[i] = (BYTE)(firstChar + i);
1788 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1790 for(i = 0; i < wlen; i++)
1792 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1794 ret = FALSE;
1795 break;
1797 buffer++;
1800 HeapFree(GetProcessHeap(), 0, str);
1801 HeapFree(GetProcessHeap(), 0, wstr);
1803 return ret;
1807 /***********************************************************************
1808 * ExtTextOutA (GDI32.@)
1810 * See ExtTextOutW.
1812 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1813 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1815 INT wlen;
1816 UINT codepage;
1817 LPWSTR p;
1818 BOOL ret;
1819 LPINT lpDxW = NULL;
1821 if (flags & ETO_GLYPH_INDEX)
1822 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1824 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1826 if (lpDx) {
1827 unsigned int i = 0, j = 0;
1829 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1830 while(i < count) {
1831 if(IsDBCSLeadByteEx(codepage, str[i])) {
1832 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1833 i = i + 2;
1834 } else {
1835 lpDxW[j++] = lpDx[i];
1836 i = i + 1;
1841 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1843 HeapFree( GetProcessHeap(), 0, p );
1844 HeapFree( GetProcessHeap(), 0, lpDxW );
1845 return ret;
1849 /***********************************************************************
1850 * ExtTextOutW (GDI32.@)
1852 * Draws text using the currently selected font, background color, and text color.
1855 * PARAMS
1856 * x,y [I] coordinates of string
1857 * flags [I]
1858 * ETO_GRAYED - undocumented on MSDN
1859 * ETO_OPAQUE - use background color for fill the rectangle
1860 * ETO_CLIPPED - clipping text to the rectangle
1861 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1862 * than encoded characters. Implies ETO_IGNORELANGUAGE
1863 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1864 * Affects BiDi ordering
1865 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1866 * ETO_PDY - unimplemented
1867 * ETO_NUMERICSLATIN - unimplemented always assumed -
1868 * do not translate numbers into locale representations
1869 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1870 * lprect [I] dimensions for clipping or/and opaquing
1871 * str [I] text string
1872 * count [I] number of symbols in string
1873 * lpDx [I] optional parameter with distance between drawing characters
1875 * RETURNS
1876 * Success: TRUE
1877 * Failure: FALSE
1879 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1880 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1882 BOOL ret = FALSE;
1883 LPWSTR reordered_str = (LPWSTR)str;
1884 WORD *glyphs = NULL;
1885 UINT align = GetTextAlign( hdc );
1886 POINT pt;
1887 TEXTMETRICW tm;
1888 LOGFONTW lf;
1889 double cosEsc, sinEsc;
1890 INT *deltas = NULL, char_extra;
1891 SIZE sz;
1892 RECT rc;
1893 BOOL done_extents = FALSE;
1894 INT width = 0, xwidth = 0, ywidth = 0;
1895 DWORD type;
1896 DC * dc = get_dc_ptr( hdc );
1897 INT breakRem;
1899 if (!dc) return FALSE;
1901 breakRem = dc->breakRem;
1903 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1904 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1906 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1908 release_dc_ptr( dc );
1909 return ret;
1912 update_dc( dc );
1913 type = GetObjectType(hdc);
1914 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1916 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1917 release_dc_ptr( dc );
1918 return ret;
1921 if (!lprect)
1922 flags &= ~ETO_CLIPPED;
1924 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1926 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1928 BIDI_Reorder( str, count, GCP_REORDER,
1929 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1930 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1931 reordered_str, count, NULL );
1933 flags |= ETO_IGNORELANGUAGE;
1936 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1937 lprect, debugstr_wn(str, count), count, lpDx);
1939 if(flags & ETO_GLYPH_INDEX)
1940 glyphs = reordered_str;
1942 if(lprect)
1943 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1944 lprect->bottom);
1945 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1947 if(align & TA_UPDATECP)
1949 GetCurrentPositionEx( hdc, &pt );
1950 x = pt.x;
1951 y = pt.y;
1954 GetTextMetricsW(hdc, &tm);
1955 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1957 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1958 lf.lfEscapement = 0;
1960 if(lf.lfEscapement != 0)
1962 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1963 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1965 else
1967 cosEsc = 1;
1968 sinEsc = 0;
1971 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1973 if(!lprect)
1975 if(flags & ETO_GLYPH_INDEX)
1976 GetTextExtentPointI(hdc, glyphs, count, &sz);
1977 else
1978 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1980 done_extents = TRUE;
1981 rc.left = x;
1982 rc.top = y;
1983 rc.right = x + sz.cx;
1984 rc.bottom = y + sz.cy;
1986 else
1988 rc = *lprect;
1991 LPtoDP(hdc, (POINT*)&rc, 2);
1993 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1994 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1997 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1998 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2000 if(count == 0)
2002 ret = TRUE;
2003 goto done;
2006 pt.x = x;
2007 pt.y = y;
2008 LPtoDP(hdc, &pt, 1);
2009 x = pt.x;
2010 y = pt.y;
2012 char_extra = GetTextCharacterExtra(hdc);
2013 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2015 UINT i;
2016 SIZE tmpsz;
2017 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
2018 for(i = 0; i < count; i++)
2020 if(lpDx && (flags & ETO_PDY))
2021 deltas[i] = lpDx[i*2] + char_extra;
2022 else if(lpDx)
2023 deltas[i] = lpDx[i] + char_extra;
2024 else
2026 if(flags & ETO_GLYPH_INDEX)
2027 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2028 else
2029 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2031 deltas[i] = tmpsz.cx;
2034 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2036 deltas[i] = deltas[i] + dc->breakExtra;
2037 if (breakRem > 0)
2039 breakRem--;
2040 deltas[i]++;
2043 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
2044 width += deltas[i];
2047 else
2049 if(!done_extents)
2051 if(flags & ETO_GLYPH_INDEX)
2052 GetTextExtentPointI(hdc, glyphs, count, &sz);
2053 else
2054 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2055 done_extents = TRUE;
2057 width = INTERNAL_XWSTODS(dc, sz.cx);
2059 xwidth = width * cosEsc;
2060 ywidth = width * sinEsc;
2062 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2063 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2064 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2066 case TA_LEFT:
2067 if (align & TA_UPDATECP)
2069 pt.x = x + xwidth;
2070 pt.y = y - ywidth;
2071 DPtoLP(hdc, &pt, 1);
2072 MoveToEx(hdc, pt.x, pt.y, NULL);
2074 break;
2076 case TA_CENTER:
2077 x -= xwidth / 2;
2078 y += ywidth / 2;
2079 break;
2081 case TA_RIGHT:
2082 x -= xwidth;
2083 y += ywidth;
2084 if (align & TA_UPDATECP)
2086 pt.x = x;
2087 pt.y = y;
2088 DPtoLP(hdc, &pt, 1);
2089 MoveToEx(hdc, pt.x, pt.y, NULL);
2091 break;
2094 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2096 case TA_TOP:
2097 y += tm.tmAscent * cosEsc;
2098 x += tm.tmAscent * sinEsc;
2099 break;
2101 case TA_BOTTOM:
2102 y -= tm.tmDescent * cosEsc;
2103 x -= tm.tmDescent * sinEsc;
2104 break;
2106 case TA_BASELINE:
2107 break;
2110 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
2112 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2114 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
2115 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2117 RECT rc;
2118 rc.left = x;
2119 rc.right = x + width;
2120 rc.top = y - tm.tmAscent;
2121 rc.bottom = y + tm.tmDescent;
2122 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
2127 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2129 HFONT orig_font = dc->hFont, cur_font;
2130 UINT glyph;
2131 INT span = 0, *offsets = NULL, i;
2133 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2134 for(i = 0; i < count; i++)
2136 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2137 if(cur_font != dc->hFont)
2139 if(!offsets)
2141 int j;
2142 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2143 offsets[0] = 0;
2144 if(!deltas)
2146 SIZE tmpsz;
2147 for(j = 1; j < count; j++)
2149 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2150 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
2153 else
2155 for(j = 1; j < count; j++)
2156 offsets[j] = offsets[j-1] + deltas[j];
2159 if(span)
2161 if (PATH_IsPathOpen(dc->path))
2162 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2163 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2164 glyphs, span, deltas ? deltas + i - span : NULL);
2165 else
2166 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
2167 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2168 glyphs, span, deltas ? deltas + i - span : NULL);
2169 span = 0;
2171 SelectObject(hdc, cur_font);
2173 glyphs[span++] = glyph;
2175 if(i == count - 1)
2177 if (PATH_IsPathOpen(dc->path))
2178 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
2179 y - (offsets ? offsets[count - span] * sinEsc : 0),
2180 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2181 glyphs, span, deltas ? deltas + count - span : NULL);
2182 else
2183 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
2184 y - (offsets ? offsets[count - span] * sinEsc : 0),
2185 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
2186 glyphs, span, deltas ? deltas + count - span : NULL);
2187 SelectObject(hdc, orig_font);
2188 HeapFree(GetProcessHeap(), 0, offsets);
2192 else
2194 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2196 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2197 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2198 flags |= ETO_GLYPH_INDEX;
2201 if (PATH_IsPathOpen(dc->path))
2202 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
2203 glyphs ? glyphs : reordered_str, count, deltas);
2204 else
2205 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
2206 glyphs ? glyphs : reordered_str, count, deltas);
2209 done:
2210 HeapFree(GetProcessHeap(), 0, deltas);
2211 if(glyphs != reordered_str)
2212 HeapFree(GetProcessHeap(), 0, glyphs);
2213 if(reordered_str != str)
2214 HeapFree(GetProcessHeap(), 0, reordered_str);
2216 release_dc_ptr( dc );
2218 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2220 int underlinePos, strikeoutPos;
2221 int underlineWidth, strikeoutWidth;
2222 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2223 OUTLINETEXTMETRICW* otm = NULL;
2225 if(!size)
2227 underlinePos = 0;
2228 underlineWidth = tm.tmAscent / 20 + 1;
2229 strikeoutPos = tm.tmAscent / 2;
2230 strikeoutWidth = underlineWidth;
2232 else
2234 otm = HeapAlloc(GetProcessHeap(), 0, size);
2235 GetOutlineTextMetricsW(hdc, size, otm);
2236 underlinePos = otm->otmsUnderscorePosition;
2237 underlineWidth = otm->otmsUnderscoreSize;
2238 strikeoutPos = otm->otmsStrikeoutPosition;
2239 strikeoutWidth = otm->otmsStrikeoutSize;
2240 HeapFree(GetProcessHeap(), 0, otm);
2243 if (PATH_IsPathOpen(dc->path))
2245 POINT pts[5];
2246 HPEN hpen;
2247 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2249 hbrush = SelectObject(hdc, hbrush);
2250 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2252 if (lf.lfUnderline)
2254 pts[0].x = x - underlinePos * sinEsc;
2255 pts[0].y = y - underlinePos * cosEsc;
2256 pts[1].x = x + xwidth - underlinePos * sinEsc;
2257 pts[1].y = y - ywidth - underlinePos * cosEsc;
2258 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2259 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2260 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2261 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2262 pts[4].x = pts[0].x;
2263 pts[4].y = pts[0].y;
2264 DPtoLP(hdc, pts, 5);
2265 Polygon(hdc, pts, 5);
2268 if (lf.lfStrikeOut)
2270 pts[0].x = x - strikeoutPos * sinEsc;
2271 pts[0].y = y - strikeoutPos * cosEsc;
2272 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2273 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2274 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2275 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2276 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2277 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2278 pts[4].x = pts[0].x;
2279 pts[4].y = pts[0].y;
2280 DPtoLP(hdc, pts, 5);
2281 Polygon(hdc, pts, 5);
2284 SelectObject(hdc, hpen);
2285 hbrush = SelectObject(hdc, hbrush);
2286 DeleteObject(hbrush);
2288 else
2290 POINT pts[2], oldpt;
2291 HPEN hpen;
2293 if (lf.lfUnderline)
2295 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2296 hpen = SelectObject(hdc, hpen);
2297 pts[0].x = x;
2298 pts[0].y = y;
2299 pts[1].x = x + xwidth;
2300 pts[1].y = y - ywidth;
2301 DPtoLP(hdc, pts, 2);
2302 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2303 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2304 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2305 DeleteObject(SelectObject(hdc, hpen));
2308 if (lf.lfStrikeOut)
2310 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2311 hpen = SelectObject(hdc, hpen);
2312 pts[0].x = x;
2313 pts[0].y = y;
2314 pts[1].x = x + xwidth;
2315 pts[1].y = y - ywidth;
2316 DPtoLP(hdc, pts, 2);
2317 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2318 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2319 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2320 DeleteObject(SelectObject(hdc, hpen));
2325 return ret;
2329 /***********************************************************************
2330 * TextOutA (GDI32.@)
2332 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2334 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2338 /***********************************************************************
2339 * TextOutW (GDI32.@)
2341 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2343 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2347 /***********************************************************************
2348 * PolyTextOutA (GDI32.@)
2350 * See PolyTextOutW.
2352 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2354 for (; cStrings>0; cStrings--, pptxt++)
2355 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2356 return FALSE;
2357 return TRUE;
2362 /***********************************************************************
2363 * PolyTextOutW (GDI32.@)
2365 * Draw several Strings
2367 * RETURNS
2368 * TRUE: Success.
2369 * FALSE: Failure.
2371 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2373 for (; cStrings>0; cStrings--, pptxt++)
2374 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2375 return FALSE;
2376 return TRUE;
2380 /* FIXME: all following APIs ******************************************/
2383 /***********************************************************************
2384 * SetMapperFlags (GDI32.@)
2386 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2388 DC *dc = DC_GetDCPtr( hDC );
2389 DWORD ret = 0;
2390 if(!dc) return 0;
2391 if(dc->funcs->pSetMapperFlags)
2393 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2394 /* FIXME: ret is just a success flag, we should return a proper value */
2396 else
2397 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2398 DC_ReleaseDCPtr( dc );
2399 return ret;
2402 /***********************************************************************
2403 * GetAspectRatioFilterEx (GDI.486)
2405 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
2407 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2408 return FALSE;
2411 /***********************************************************************
2412 * GetAspectRatioFilterEx (GDI32.@)
2414 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2416 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2417 return FALSE;
2421 /***********************************************************************
2422 * GetCharABCWidthsA (GDI32.@)
2424 * See GetCharABCWidthsW.
2426 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2427 LPABC abc )
2429 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2430 LPSTR str;
2431 LPWSTR wstr;
2432 BOOL ret = TRUE;
2434 if(count <= 0) return FALSE;
2436 str = HeapAlloc(GetProcessHeap(), 0, count);
2437 for(i = 0; i < count; i++)
2438 str[i] = (BYTE)(firstChar + i);
2440 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2442 for(i = 0; i < wlen; i++)
2444 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2446 ret = FALSE;
2447 break;
2449 abc++;
2452 HeapFree(GetProcessHeap(), 0, str);
2453 HeapFree(GetProcessHeap(), 0, wstr);
2455 return ret;
2459 /******************************************************************************
2460 * GetCharABCWidthsW [GDI32.@]
2462 * Retrieves widths of characters in range.
2464 * PARAMS
2465 * hdc [I] Handle of device context
2466 * firstChar [I] First character in range to query
2467 * lastChar [I] Last character in range to query
2468 * abc [O] Address of character-width structure
2470 * NOTES
2471 * Only works with TrueType fonts
2473 * RETURNS
2474 * Success: TRUE
2475 * Failure: FALSE
2477 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2478 LPABC abc )
2480 DC *dc = DC_GetDCPtr(hdc);
2481 unsigned int i;
2482 BOOL ret = FALSE;
2484 if (!dc) return FALSE;
2486 if(dc->gdiFont)
2487 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2488 else
2489 FIXME(": stub\n");
2491 if (ret)
2493 /* convert device units to logical */
2494 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2495 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2496 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2497 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2499 ret = TRUE;
2502 DC_ReleaseDCPtr( dc );
2503 return ret;
2507 /******************************************************************************
2508 * GetCharABCWidthsI [GDI32.@]
2510 * Retrieves widths of characters in range.
2512 * PARAMS
2513 * hdc [I] Handle of device context
2514 * firstChar [I] First glyphs in range to query
2515 * count [I] Last glyphs in range to query
2516 * pgi [i] Array of glyphs to query
2517 * abc [O] Address of character-width structure
2519 * NOTES
2520 * Only works with TrueType fonts
2522 * RETURNS
2523 * Success: TRUE
2524 * Failure: FALSE
2526 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2527 LPWORD pgi, LPABC abc)
2529 DC *dc = DC_GetDCPtr(hdc);
2530 unsigned int i;
2531 BOOL ret = FALSE;
2533 if (!dc) return FALSE;
2535 if(dc->gdiFont)
2536 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2537 else
2538 FIXME(": stub\n");
2540 if (ret)
2542 /* convert device units to logical */
2543 for( i = 0; i < count; i++, abc++ ) {
2544 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2545 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2546 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2548 ret = TRUE;
2551 DC_ReleaseDCPtr( dc );
2552 return ret;
2556 /***********************************************************************
2557 * GetGlyphOutlineA (GDI32.@)
2559 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2560 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2561 LPVOID lpBuffer, const MAT2 *lpmat2 )
2563 LPWSTR p = NULL;
2564 DWORD ret;
2565 UINT c;
2567 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2568 int len;
2569 char mbchs[2];
2570 if(uChar > 0xff) { /* but, 2 bytes character only */
2571 len = 2;
2572 mbchs[0] = (uChar & 0xff00) >> 8;
2573 mbchs[1] = (uChar & 0xff);
2574 } else {
2575 len = 1;
2576 mbchs[0] = (uChar & 0xff);
2578 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2579 c = p[0];
2580 } else
2581 c = uChar;
2582 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2583 lpmat2);
2584 HeapFree(GetProcessHeap(), 0, p);
2585 return ret;
2588 /***********************************************************************
2589 * GetGlyphOutlineW (GDI32.@)
2591 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2592 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2593 LPVOID lpBuffer, const MAT2 *lpmat2 )
2595 DC *dc = DC_GetDCPtr(hdc);
2596 DWORD ret;
2598 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2599 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2601 if(!dc) return GDI_ERROR;
2603 if(dc->gdiFont)
2604 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2605 cbBuffer, lpBuffer, lpmat2);
2606 else
2607 ret = GDI_ERROR;
2609 DC_ReleaseDCPtr( dc );
2610 return ret;
2614 /***********************************************************************
2615 * CreateScalableFontResourceA (GDI32.@)
2617 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2618 LPCSTR lpszResourceFile,
2619 LPCSTR lpszFontFile,
2620 LPCSTR lpszCurrentPath )
2622 HANDLE f;
2624 /* fHidden=1 - only visible for the calling app, read-only, not
2625 * enumbered with EnumFonts/EnumFontFamilies
2626 * lpszCurrentPath can be NULL
2628 FIXME("(%d,%s,%s,%s): stub\n",
2629 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
2630 debugstr_a(lpszCurrentPath) );
2632 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2633 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2634 CloseHandle(f);
2635 SetLastError(ERROR_FILE_EXISTS);
2636 return FALSE;
2638 return FALSE; /* create failed */
2641 /***********************************************************************
2642 * CreateScalableFontResourceW (GDI32.@)
2644 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2645 LPCWSTR lpszResourceFile,
2646 LPCWSTR lpszFontFile,
2647 LPCWSTR lpszCurrentPath )
2649 FIXME("(%d,%p,%p,%p): stub\n",
2650 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
2651 return FALSE; /* create failed */
2654 /*************************************************************************
2655 * GetKerningPairsA (GDI32.@)
2657 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2658 LPKERNINGPAIR kern_pairA )
2660 INT charset;
2661 CHARSETINFO csi;
2662 CPINFO cpi;
2663 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2664 KERNINGPAIR *kern_pairW;
2666 if (!cPairs && kern_pairA)
2668 SetLastError(ERROR_INVALID_PARAMETER);
2669 return 0;
2672 charset = GetTextCharset(hDC);
2673 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2675 FIXME("Can't find codepage for charset %d\n", charset);
2676 return 0;
2678 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2679 * to fail on an invalid character for CP_SYMBOL.
2681 cpi.DefaultChar[0] = 0;
2682 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2684 FIXME("Can't find codepage %u info\n", csi.ciACP);
2685 return 0;
2687 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2689 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2690 if (!total_kern_pairs) return 0;
2692 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2693 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2695 for (i = 0; i < total_kern_pairs; i++)
2697 char first, second;
2699 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2700 continue;
2702 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2703 continue;
2705 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2706 continue;
2708 if (kern_pairA)
2710 if (kern_pairs_copied >= cPairs) break;
2712 kern_pairA->wFirst = (BYTE)first;
2713 kern_pairA->wSecond = (BYTE)second;
2714 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2715 kern_pairA++;
2717 kern_pairs_copied++;
2720 HeapFree(GetProcessHeap(), 0, kern_pairW);
2722 return kern_pairs_copied;
2725 /*************************************************************************
2726 * GetKerningPairsW (GDI32.@)
2728 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2729 LPKERNINGPAIR lpKerningPairs )
2731 DC *dc;
2732 DWORD ret = 0;
2734 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2736 if (!cPairs && lpKerningPairs)
2738 SetLastError(ERROR_INVALID_PARAMETER);
2739 return 0;
2742 dc = DC_GetDCPtr(hDC);
2743 if (!dc) return 0;
2745 if (dc->gdiFont)
2746 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2748 DC_ReleaseDCPtr( dc );
2749 return ret;
2752 /*************************************************************************
2753 * TranslateCharsetInfo [GDI32.@]
2755 * Fills a CHARSETINFO structure for a character set, code page, or
2756 * font. This allows making the correspondance between different labelings
2757 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2758 * of the same encoding.
2760 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2761 * only one codepage should be set in *lpSrc.
2763 * RETURNS
2764 * TRUE on success, FALSE on failure.
2767 BOOL WINAPI TranslateCharsetInfo(
2768 LPDWORD lpSrc, /* [in]
2769 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2770 if flags == TCI_SRCCHARSET: a character set value
2771 if flags == TCI_SRCCODEPAGE: a code page value
2773 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2774 DWORD flags /* [in] determines interpretation of lpSrc */)
2776 int index = 0;
2777 switch (flags) {
2778 case TCI_SRCFONTSIG:
2779 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2780 break;
2781 case TCI_SRCCODEPAGE:
2782 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2783 break;
2784 case TCI_SRCCHARSET:
2785 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2786 break;
2787 default:
2788 return FALSE;
2790 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2791 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
2792 return TRUE;
2795 /*************************************************************************
2796 * GetFontLanguageInfo (GDI32.@)
2798 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2800 FONTSIGNATURE fontsig;
2801 static const DWORD GCP_DBCS_MASK=0x003F0000,
2802 GCP_DIACRITIC_MASK=0x00000000,
2803 FLI_GLYPHS_MASK=0x00000000,
2804 GCP_GLYPHSHAPE_MASK=0x00000040,
2805 GCP_KASHIDA_MASK=0x00000000,
2806 GCP_LIGATE_MASK=0x00000000,
2807 GCP_USEKERNING_MASK=0x00000000,
2808 GCP_REORDER_MASK=0x00000060;
2810 DWORD result=0;
2812 GetTextCharsetInfo( hdc, &fontsig, 0 );
2813 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2815 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2816 result|=GCP_DBCS;
2818 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2819 result|=GCP_DIACRITIC;
2821 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2822 result|=FLI_GLYPHS;
2824 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2825 result|=GCP_GLYPHSHAPE;
2827 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2828 result|=GCP_KASHIDA;
2830 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2831 result|=GCP_LIGATE;
2833 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2834 result|=GCP_USEKERNING;
2836 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2837 if( GetTextAlign( hdc) & TA_RTLREADING )
2838 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2839 result|=GCP_REORDER;
2841 return result;
2845 /*************************************************************************
2846 * GetFontData [GDI32.@]
2848 * Retrieve data for TrueType font.
2850 * RETURNS
2852 * success: Number of bytes returned
2853 * failure: GDI_ERROR
2855 * NOTES
2857 * Calls SetLastError()
2860 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2861 LPVOID buffer, DWORD length)
2863 DC *dc = DC_GetDCPtr(hdc);
2864 DWORD ret = GDI_ERROR;
2866 if(!dc) return GDI_ERROR;
2868 if(dc->gdiFont)
2869 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2871 DC_ReleaseDCPtr( dc );
2872 return ret;
2875 /*************************************************************************
2876 * GetGlyphIndicesA [GDI32.@]
2878 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2879 LPWORD pgi, DWORD flags)
2881 DWORD ret;
2882 WCHAR *lpstrW;
2883 INT countW;
2885 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2886 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2888 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2889 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2890 HeapFree(GetProcessHeap(), 0, lpstrW);
2892 return ret;
2895 /*************************************************************************
2896 * GetGlyphIndicesW [GDI32.@]
2898 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2899 LPWORD pgi, DWORD flags)
2901 DC *dc = DC_GetDCPtr(hdc);
2902 DWORD ret = GDI_ERROR;
2904 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2905 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2907 if(!dc) return GDI_ERROR;
2909 if(dc->gdiFont)
2910 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2912 DC_ReleaseDCPtr( dc );
2913 return ret;
2916 /*************************************************************************
2917 * GetCharacterPlacementA [GDI32.@]
2919 * See GetCharacterPlacementW.
2921 * NOTES:
2922 * the web browser control of ie4 calls this with dwFlags=0
2924 DWORD WINAPI
2925 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2926 INT nMaxExtent, GCP_RESULTSA *lpResults,
2927 DWORD dwFlags)
2929 WCHAR *lpStringW;
2930 INT uCountW;
2931 GCP_RESULTSW resultsW;
2932 DWORD ret;
2933 UINT font_cp;
2935 TRACE("%s, %d, %d, 0x%08x\n",
2936 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2938 /* both structs are equal in size */
2939 memcpy(&resultsW, lpResults, sizeof(resultsW));
2941 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2942 if(lpResults->lpOutString)
2943 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2945 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2947 lpResults->nGlyphs = resultsW.nGlyphs;
2948 lpResults->nMaxFit = resultsW.nMaxFit;
2950 if(lpResults->lpOutString) {
2951 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2952 lpResults->lpOutString, uCount, NULL, NULL );
2955 HeapFree(GetProcessHeap(), 0, lpStringW);
2956 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2958 return ret;
2961 /*************************************************************************
2962 * GetCharacterPlacementW [GDI32.@]
2964 * Retrieve information about a string. This includes the width, reordering,
2965 * Glyphing and so on.
2967 * RETURNS
2969 * The width and height of the string if successful, 0 if failed.
2971 * BUGS
2973 * All flags except GCP_REORDER are not yet implemented.
2974 * Reordering is not 100% complient to the Windows BiDi method.
2975 * Caret positioning is not yet implemented for BiDi.
2976 * Classes are not yet implemented.
2979 DWORD WINAPI
2980 GetCharacterPlacementW(
2981 HDC hdc, /* [in] Device context for which the rendering is to be done */
2982 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2983 INT uCount, /* [in] Number of WORDS in string. */
2984 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2985 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2986 DWORD dwFlags /* [in] Flags specifying how to process the string */
2989 DWORD ret=0;
2990 SIZE size;
2991 UINT i, nSet;
2993 TRACE("%s, %d, %d, 0x%08x\n",
2994 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2996 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2997 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2998 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2999 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3000 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3002 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3003 if(lpResults->lpClass) FIXME("classes not implemented\n");
3004 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3005 FIXME("Caret positions for complex scripts not implemented\n");
3007 nSet = (UINT)uCount;
3008 if(nSet > lpResults->nGlyphs)
3009 nSet = lpResults->nGlyphs;
3011 /* return number of initialized fields */
3012 lpResults->nGlyphs = nSet;
3014 if((dwFlags&GCP_REORDER)==0 )
3016 /* Treat the case where no special handling was requested in a fastpath way */
3017 /* copy will do if the GCP_REORDER flag is not set */
3018 if(lpResults->lpOutString)
3019 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3021 if(lpResults->lpOrder)
3023 for(i = 0; i < nSet; i++)
3024 lpResults->lpOrder[i] = i;
3026 } else
3028 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3029 nSet, lpResults->lpOrder );
3032 /* FIXME: Will use the placement chars */
3033 if (lpResults->lpDx)
3035 int c;
3036 for (i = 0; i < nSet; i++)
3038 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3039 lpResults->lpDx[i]= c;
3043 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3045 int pos = 0;
3047 lpResults->lpCaretPos[0] = 0;
3048 for (i = 1; i < nSet; i++)
3049 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3050 lpResults->lpCaretPos[i] = (pos += size.cx);
3053 if(lpResults->lpGlyphs)
3054 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3056 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3057 ret = MAKELONG(size.cx, size.cy);
3059 return ret;
3062 /*************************************************************************
3063 * GetCharABCWidthsFloatA [GDI32.@]
3065 * See GetCharABCWidthsFloatW.
3067 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3069 INT i, wlen, count = (INT)(last - first + 1);
3070 LPSTR str;
3071 LPWSTR wstr;
3072 BOOL ret = TRUE;
3074 if (count <= 0) return FALSE;
3076 str = HeapAlloc(GetProcessHeap(), 0, count);
3078 for(i = 0; i < count; i++)
3079 str[i] = (BYTE)(first + i);
3081 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
3083 for (i = 0; i < wlen; i++)
3085 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3087 ret = FALSE;
3088 break;
3090 abcf++;
3093 HeapFree( GetProcessHeap(), 0, str );
3094 HeapFree( GetProcessHeap(), 0, wstr );
3096 return ret;
3099 /*************************************************************************
3100 * GetCharABCWidthsFloatW [GDI32.@]
3102 * Retrieves widths of a range of characters.
3104 * PARAMS
3105 * hdc [I] Handle to device context.
3106 * first [I] First character in range to query.
3107 * last [I] Last character in range to query.
3108 * abcf [O] Array of LPABCFLOAT structures.
3110 * RETURNS
3111 * Success: TRUE
3112 * Failure: FALSE
3114 * BUGS
3115 * Only works with TrueType fonts. It also doesn't return real
3116 * floats but converted integers because it's implemented on
3117 * top of GetCharABCWidthsW.
3119 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3121 ABC *abc;
3122 unsigned int i, size = sizeof(ABC) * (last - first + 1);
3123 BOOL ret;
3125 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
3127 abc = HeapAlloc( GetProcessHeap(), 0, size );
3128 if (!abc) return FALSE;
3130 ret = GetCharABCWidthsW( hdc, first, last, abc );
3131 if (ret)
3133 for (i = first; i <= last; i++, abc++, abcf++)
3135 abcf->abcfA = abc->abcA;
3136 abcf->abcfB = abc->abcB;
3137 abcf->abcfC = abc->abcC;
3140 HeapFree( GetProcessHeap(), 0, abc );
3141 return ret;
3144 /*************************************************************************
3145 * GetCharWidthFloatA [GDI32.@]
3147 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3148 UINT iLastChar, PFLOAT pxBuffer)
3150 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3151 return 0;
3154 /*************************************************************************
3155 * GetCharWidthFloatW [GDI32.@]
3157 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3158 UINT iLastChar, PFLOAT pxBuffer)
3160 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3161 return 0;
3165 /***********************************************************************
3167 * Font Resource API *
3169 ***********************************************************************/
3171 /***********************************************************************
3172 * AddFontResourceA (GDI32.@)
3174 INT WINAPI AddFontResourceA( LPCSTR str )
3176 return AddFontResourceExA( str, 0, NULL);
3179 /***********************************************************************
3180 * AddFontResourceW (GDI32.@)
3182 INT WINAPI AddFontResourceW( LPCWSTR str )
3184 return AddFontResourceExW(str, 0, NULL);
3188 /***********************************************************************
3189 * AddFontResourceExA (GDI32.@)
3191 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3193 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3194 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3195 INT ret;
3197 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3198 ret = AddFontResourceExW(strW, fl, pdv);
3199 HeapFree(GetProcessHeap(), 0, strW);
3200 return ret;
3203 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3205 HRSRC rsrc = FindResourceW(hModule, name, type);
3206 HGLOBAL hMem = LoadResource(hModule, rsrc);
3207 LPVOID *pMem = LockResource(hMem);
3208 int *num_total = (int *)lParam;
3209 DWORD num_in_res;
3211 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3212 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3214 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3215 return FALSE;
3218 *num_total += num_in_res;
3219 return TRUE;
3222 /***********************************************************************
3223 * AddFontResourceExW (GDI32.@)
3225 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3227 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3228 if (ret == 0)
3230 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3231 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3232 if (hModule != NULL)
3234 int num_resources = 0;
3235 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3237 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3238 wine_dbgstr_w(str));
3239 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3240 ret = num_resources;
3241 FreeLibrary(hModule);
3244 return ret;
3247 /***********************************************************************
3248 * RemoveFontResourceA (GDI32.@)
3250 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3252 return RemoveFontResourceExA(str, 0, 0);
3255 /***********************************************************************
3256 * RemoveFontResourceW (GDI32.@)
3258 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3260 return RemoveFontResourceExW(str, 0, 0);
3263 /***********************************************************************
3264 * AddFontMemResourceEx (GDI32.@)
3266 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3268 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3271 /***********************************************************************
3272 * RemoveFontResourceExA (GDI32.@)
3274 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3276 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3277 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3278 INT ret;
3280 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3281 ret = RemoveFontResourceExW(strW, fl, pdv);
3282 HeapFree(GetProcessHeap(), 0, strW);
3283 return ret;
3286 /***********************************************************************
3287 * RemoveFontResourceExW (GDI32.@)
3289 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3291 return WineEngRemoveFontResourceEx(str, fl, pdv);
3294 /***********************************************************************
3295 * GetTextCharset (GDI32.@)
3297 UINT WINAPI GetTextCharset(HDC hdc)
3299 /* MSDN docs say this is equivalent */
3300 return GetTextCharsetInfo(hdc, NULL, 0);
3303 /***********************************************************************
3304 * GetTextCharsetInfo (GDI32.@)
3306 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3308 UINT ret = DEFAULT_CHARSET;
3309 DC *dc = DC_GetDCPtr(hdc);
3311 if (dc)
3313 if (dc->gdiFont)
3314 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3316 DC_ReleaseDCPtr( dc );
3319 if (ret == DEFAULT_CHARSET && fs)
3320 memset(fs, 0, sizeof(FONTSIGNATURE));
3321 return ret;
3324 /***********************************************************************
3325 * GdiGetCharDimensions (GDI32.@)
3327 * Gets the average width of the characters in the English alphabet.
3329 * PARAMS
3330 * hdc [I] Handle to the device context to measure on.
3331 * lptm [O] Pointer to memory to store the text metrics into.
3332 * height [O] On exit, the maximum height of characters in the English alphabet.
3334 * RETURNS
3335 * The average width of characters in the English alphabet.
3337 * NOTES
3338 * This function is used by the dialog manager to get the size of a dialog
3339 * unit. It should also be used by other pieces of code that need to know
3340 * the size of a dialog unit in logical units without having access to the
3341 * window handle of the dialog.
3342 * Windows caches the font metrics from this function, but we don't and
3343 * there doesn't appear to be an immediate advantage to do so.
3345 * SEE ALSO
3346 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3348 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3350 SIZE sz;
3351 static const WCHAR alphabet[] = {
3352 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3353 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3354 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3356 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3358 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3360 if (height) *height = sz.cy;
3361 return (sz.cx / 26 + 1) / 2;
3364 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3366 FIXME("(%d): stub\n", fEnableEUDC);
3367 return FALSE;
3370 /***********************************************************************
3371 * GetCharWidthI (GDI32.@)
3373 * Retrieve widths of characters.
3375 * PARAMS
3376 * hdc [I] Handle to a device context.
3377 * first [I] First glyph in range to query.
3378 * count [I] Number of glyph indices to query.
3379 * glyphs [I] Array of glyphs to query.
3380 * buffer [O] Buffer to receive character widths.
3382 * NOTES
3383 * Only works with TrueType fonts.
3385 * RETURNS
3386 * Success: TRUE
3387 * Failure: FALSE
3389 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3391 ABC *abc;
3392 unsigned int i;
3394 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3396 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3397 return FALSE;
3399 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3401 HeapFree(GetProcessHeap(), 0, abc);
3402 return FALSE;
3405 for (i = 0; i < count; i++)
3406 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3408 HeapFree(GetProcessHeap(), 0, abc);
3409 return TRUE;
3412 /***********************************************************************
3413 * GetFontUnicodeRanges (GDI32.@)
3415 * Retrieve a list of supported Unicode characters in a font.
3417 * PARAMS
3418 * hdc [I] Handle to a device context.
3419 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3421 * RETURNS
3422 * Success: Number of bytes written to the buffer pointed to by lpgs.
3423 * Failure: 0
3426 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3428 DWORD ret = 0;
3429 DC *dc = DC_GetDCPtr(hdc);
3431 TRACE("(%p, %p)\n", hdc, lpgs);
3433 if (!dc) return 0;
3435 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3436 DC_ReleaseDCPtr(dc);
3437 return ret;
3441 /*************************************************************
3442 * FontIsLinked (GDI32.@)
3444 BOOL WINAPI FontIsLinked(HDC hdc)
3446 DC *dc = DC_GetDCPtr(hdc);
3447 BOOL ret = FALSE;
3449 if (!dc) return FALSE;
3450 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3451 DC_ReleaseDCPtr(dc);
3452 TRACE("returning %d\n", ret);
3453 return ret;