Added support for inter-process GetWindowWord.
[wine.git] / objects / font.c
blobfba939b737536448e676780d7fb088e81b0dd32b
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40 WINE_DECLARE_DEBUG_CHANNEL(gdi);
42 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
43 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
44 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
45 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
46 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
48 static const struct gdi_obj_funcs font_funcs =
50 FONT_SelectObject, /* pSelectObject */
51 FONT_GetObject16, /* pGetObject16 */
52 FONT_GetObjectA, /* pGetObjectA */
53 FONT_GetObjectW, /* pGetObjectW */
54 NULL, /* pUnrealizeObject */
55 FONT_DeleteObject /* pDeleteObject */
58 #define ENUM_UNICODE 0x00000001
59 #define ENUM_CALLED 0x00000002
61 typedef struct
63 GDIOBJHDR header;
64 LOGFONTW logfont;
65 } FONTOBJ;
67 typedef struct
69 LPLOGFONT16 lpLogFontParam;
70 FONTENUMPROC16 lpEnumFunc;
71 LPARAM lpData;
73 LPNEWTEXTMETRICEX16 lpTextMetric;
74 LPENUMLOGFONTEX16 lpLogFont;
75 SEGPTR segTextMetric;
76 SEGPTR segLogFont;
77 DWORD dwFlags;
78 HDC hdc;
79 DC *dc;
80 PHYSDEV physDev;
81 } fontEnum16;
83 typedef struct
85 LPLOGFONTW lpLogFontParam;
86 FONTENUMPROCW lpEnumFunc;
87 LPARAM lpData;
88 DWORD dwFlags;
89 HDC hdc;
90 DC *dc;
91 PHYSDEV physDev;
92 } fontEnum32;
95 * For TranslateCharsetInfo
97 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
98 #define MAXTCIINDEX 32
99 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
100 /* ANSI */
101 { ANSI_CHARSET, 1252, FS(0)},
102 { EASTEUROPE_CHARSET, 1250, FS(1)},
103 { RUSSIAN_CHARSET, 1251, FS(2)},
104 { GREEK_CHARSET, 1253, FS(3)},
105 { TURKISH_CHARSET, 1254, FS(4)},
106 { HEBREW_CHARSET, 1255, FS(5)},
107 { ARABIC_CHARSET, 1256, FS(6)},
108 { BALTIC_CHARSET, 1257, FS(7)},
109 { VIETNAMESE_CHARSET, 1258, FS(8)},
110 /* reserved by ANSI */
111 { DEFAULT_CHARSET, 0, FS(0)},
112 { DEFAULT_CHARSET, 0, FS(0)},
113 { DEFAULT_CHARSET, 0, FS(0)},
114 { DEFAULT_CHARSET, 0, FS(0)},
115 { DEFAULT_CHARSET, 0, FS(0)},
116 { DEFAULT_CHARSET, 0, FS(0)},
117 { DEFAULT_CHARSET, 0, FS(0)},
118 /* ANSI and OEM */
119 { THAI_CHARSET, 874, FS(16)},
120 { SHIFTJIS_CHARSET, 932, FS(17)},
121 { GB2312_CHARSET, 936, FS(18)},
122 { HANGEUL_CHARSET, 949, FS(19)},
123 { CHINESEBIG5_CHARSET, 950, FS(20)},
124 { JOHAB_CHARSET, 1361, FS(21)},
125 /* reserved for alternate ANSI and OEM */
126 { DEFAULT_CHARSET, 0, FS(0)},
127 { DEFAULT_CHARSET, 0, FS(0)},
128 { DEFAULT_CHARSET, 0, FS(0)},
129 { DEFAULT_CHARSET, 0, FS(0)},
130 { DEFAULT_CHARSET, 0, FS(0)},
131 { DEFAULT_CHARSET, 0, FS(0)},
132 { DEFAULT_CHARSET, 0, FS(0)},
133 { DEFAULT_CHARSET, 0, FS(0)},
134 /* reserved for system */
135 { DEFAULT_CHARSET, 0, FS(0)},
136 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
139 /***********************************************************************
140 * LOGFONT conversion functions.
142 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
144 font16->lfHeight = font32->lfHeight;
145 font16->lfWidth = font32->lfWidth;
146 font16->lfEscapement = font32->lfEscapement;
147 font16->lfOrientation = font32->lfOrientation;
148 font16->lfWeight = font32->lfWeight;
149 font16->lfItalic = font32->lfItalic;
150 font16->lfUnderline = font32->lfUnderline;
151 font16->lfStrikeOut = font32->lfStrikeOut;
152 font16->lfCharSet = font32->lfCharSet;
153 font16->lfOutPrecision = font32->lfOutPrecision;
154 font16->lfClipPrecision = font32->lfClipPrecision;
155 font16->lfQuality = font32->lfQuality;
156 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
157 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
158 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
159 font16->lfFaceName[LF_FACESIZE-1] = 0;
162 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
164 font32->lfHeight = font16->lfHeight;
165 font32->lfWidth = font16->lfWidth;
166 font32->lfEscapement = font16->lfEscapement;
167 font32->lfOrientation = font16->lfOrientation;
168 font32->lfWeight = font16->lfWeight;
169 font32->lfItalic = font16->lfItalic;
170 font32->lfUnderline = font16->lfUnderline;
171 font32->lfStrikeOut = font16->lfStrikeOut;
172 font32->lfCharSet = font16->lfCharSet;
173 font32->lfOutPrecision = font16->lfOutPrecision;
174 font32->lfClipPrecision = font16->lfClipPrecision;
175 font32->lfQuality = font16->lfQuality;
176 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
177 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
178 font32->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
183 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
184 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
185 LF_FACESIZE);
188 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
190 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
191 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
192 LF_FACESIZE, NULL, NULL);
195 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
197 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
199 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
200 font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
201 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
202 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
203 font16->elfStyle, LF_FACESIZE, NULL, NULL );
204 font16->elfStyle[LF_FACESIZE-1] = '\0';
205 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
206 font16->elfScript, LF_FACESIZE, NULL, NULL );
207 font16->elfScript[LF_FACESIZE-1] = '\0';
210 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
212 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
214 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
215 fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
216 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
217 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
218 fontA->elfStyle, LF_FACESIZE, NULL, NULL );
219 fontA->elfStyle[LF_FACESIZE-1] = '\0';
220 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
221 fontA->elfScript, LF_FACESIZE, NULL, NULL );
222 fontA->elfScript[LF_FACESIZE-1] = '\0';
225 /***********************************************************************
226 * TEXTMETRIC conversion functions.
228 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
230 ptmA->tmHeight = ptmW->tmHeight;
231 ptmA->tmAscent = ptmW->tmAscent;
232 ptmA->tmDescent = ptmW->tmDescent;
233 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
234 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
235 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
236 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
237 ptmA->tmWeight = ptmW->tmWeight;
238 ptmA->tmOverhang = ptmW->tmOverhang;
239 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
240 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
241 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
242 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
243 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
244 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
245 ptmA->tmItalic = ptmW->tmItalic;
246 ptmA->tmUnderlined = ptmW->tmUnderlined;
247 ptmA->tmStruckOut = ptmW->tmStruckOut;
248 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
249 ptmA->tmCharSet = ptmW->tmCharSet;
253 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
255 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
256 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
257 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
258 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
259 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
260 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
261 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
262 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
263 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
264 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
265 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
266 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
267 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
268 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
269 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
270 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
271 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
272 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
273 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
274 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
275 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
276 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
277 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
278 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
279 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
282 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
284 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
285 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
286 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
287 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
288 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
289 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
292 /***********************************************************************
293 * CreateFontIndirectA (GDI32.@)
295 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
297 LOGFONTW lfW;
299 if (plfA) {
300 FONT_LogFontAToW( plfA, &lfW );
301 return CreateFontIndirectW( &lfW );
302 } else
303 return CreateFontIndirectW( NULL );
307 /***********************************************************************
308 * CreateFontIndirectW (GDI32.@)
310 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
312 HFONT hFont = 0;
314 if (plf)
316 FONTOBJ* fontPtr;
317 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
318 (HGDIOBJ *)&hFont, &font_funcs )))
320 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
321 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
322 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
323 WCHAR* pFaceNameSuffix = NULL;
325 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
327 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
328 plf->lfHeight, plf->lfWidth,
329 plf->lfEscapement, plf->lfOrientation,
330 plf->lfPitchAndFamily,
331 plf->lfOutPrecision, plf->lfClipPrecision,
332 plf->lfQuality, plf->lfCharSet,
333 debugstr_w(plf->lfFaceName),
334 plf->lfWeight > 400 ? "Bold" : "",
335 plf->lfItalic ? "Italic" : "",
336 plf->lfUnderline ? "Underline" : "", hFont);
338 if (plf->lfEscapement != plf->lfOrientation) {
339 /* this should really depend on whether GM_ADVANCED is set */
340 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
341 WARN("orientation angle %f set to "
342 "escapement angle %f for new font %p\n",
343 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
346 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
347 if (pFaceNameItalicSuffix) {
348 fontPtr->logfont.lfItalic = TRUE;
349 pFaceNameSuffix = pFaceNameItalicSuffix;
352 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
353 if (pFaceNameBoldSuffix) {
354 if (fontPtr->logfont.lfWeight < FW_BOLD) {
355 fontPtr->logfont.lfWeight = FW_BOLD;
357 if (!pFaceNameSuffix ||
358 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
359 pFaceNameSuffix = pFaceNameBoldSuffix;
363 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
365 GDI_ReleaseObj( hFont );
368 else WARN("(NULL) => NULL\n");
370 return hFont;
373 /*************************************************************************
374 * CreateFontA (GDI32.@)
376 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
377 INT orient, INT weight, DWORD italic,
378 DWORD underline, DWORD strikeout, DWORD charset,
379 DWORD outpres, DWORD clippres, DWORD quality,
380 DWORD pitch, LPCSTR name )
382 LOGFONTA logfont;
384 logfont.lfHeight = height;
385 logfont.lfWidth = width;
386 logfont.lfEscapement = esc;
387 logfont.lfOrientation = orient;
388 logfont.lfWeight = weight;
389 logfont.lfItalic = italic;
390 logfont.lfUnderline = underline;
391 logfont.lfStrikeOut = strikeout;
392 logfont.lfCharSet = charset;
393 logfont.lfOutPrecision = outpres;
394 logfont.lfClipPrecision = clippres;
395 logfont.lfQuality = quality;
396 logfont.lfPitchAndFamily = pitch;
398 if (name)
399 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
400 else
401 logfont.lfFaceName[0] = '\0';
403 return CreateFontIndirectA( &logfont );
406 /*************************************************************************
407 * CreateFontW (GDI32.@)
409 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
410 INT orient, INT weight, DWORD italic,
411 DWORD underline, DWORD strikeout, DWORD charset,
412 DWORD outpres, DWORD clippres, DWORD quality,
413 DWORD pitch, LPCWSTR name )
415 LOGFONTW logfont;
417 logfont.lfHeight = height;
418 logfont.lfWidth = width;
419 logfont.lfEscapement = esc;
420 logfont.lfOrientation = orient;
421 logfont.lfWeight = weight;
422 logfont.lfItalic = italic;
423 logfont.lfUnderline = underline;
424 logfont.lfStrikeOut = strikeout;
425 logfont.lfCharSet = charset;
426 logfont.lfOutPrecision = outpres;
427 logfont.lfClipPrecision = clippres;
428 logfont.lfQuality = quality;
429 logfont.lfPitchAndFamily = pitch;
431 if (name)
432 lstrcpynW(logfont.lfFaceName, name,
433 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
434 else
435 logfont.lfFaceName[0] = '\0';
437 return CreateFontIndirectW( &logfont );
441 /***********************************************************************
442 * FONT_SelectObject
444 * If the driver supports vector fonts we create a gdi font first and
445 * then call the driver to give it a chance to supply its own device
446 * font. If the driver wants to do this it returns TRUE and we can
447 * delete the gdi font, if the driver wants to use the gdi font it
448 * should return FALSE, to signal an error return GDI_ERROR. For
449 * drivers that don't support vector fonts they must supply their own
450 * font.
452 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
454 HGDIOBJ ret = 0;
455 DC *dc = DC_GetDCPtr( hdc );
457 if (!dc) return 0;
459 if (dc->hFont != handle || dc->gdiFont == NULL)
461 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
462 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
465 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle );
467 if (ret && dc->gdiFont) dc->gdiFont = 0;
469 if (ret == HGDI_ERROR)
470 ret = 0; /* SelectObject returns 0 on error */
471 else
473 ret = dc->hFont;
474 dc->hFont = handle;
476 GDI_ReleaseObj( hdc );
477 return ret;
481 /***********************************************************************
482 * FONT_GetObject16
484 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
486 FONTOBJ *font = obj;
487 LOGFONT16 lf16;
489 FONT_LogFontWTo16( &font->logfont, &lf16 );
491 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
492 memcpy( buffer, &lf16, count );
493 return count;
496 /***********************************************************************
497 * FONT_GetObjectA
499 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
501 FONTOBJ *font = obj;
502 LOGFONTA lfA;
504 if(!buffer)
505 return sizeof(lfA);
506 FONT_LogFontWToA( &font->logfont, &lfA );
508 if (count > sizeof(lfA)) count = sizeof(lfA);
509 memcpy( buffer, &lfA, count );
510 return count;
513 /***********************************************************************
514 * FONT_GetObjectW
516 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
518 FONTOBJ *font = obj;
519 if(!buffer)
520 return sizeof(LOGFONTW);
521 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
522 memcpy( buffer, &font->logfont, count );
523 return count;
527 /***********************************************************************
528 * FONT_DeleteObject
530 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
532 WineEngDestroyFontInstance( handle );
533 return GDI_FreeObject( handle, obj );
537 /***********************************************************************
538 * FONT_EnumInstance16
540 * Called by the device driver layer to pass font info
541 * down to the application.
543 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
544 DWORD fType, LPARAM lp )
546 fontEnum16 *pfe = (fontEnum16*)lp;
547 INT ret = 1;
548 DC *dc;
550 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
551 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
553 WORD args[7];
554 DWORD result;
556 FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
557 FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
558 pfe->dwFlags |= ENUM_CALLED;
559 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
561 args[6] = SELECTOROF(pfe->segLogFont);
562 args[5] = OFFSETOF(pfe->segLogFont);
563 args[4] = SELECTOROF(pfe->segTextMetric);
564 args[3] = OFFSETOF(pfe->segTextMetric);
565 args[2] = fType;
566 args[1] = HIWORD(pfe->lpData);
567 args[0] = LOWORD(pfe->lpData);
568 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
569 ret = LOWORD(result);
571 /* get the lock again and make sure the DC is still valid */
572 dc = DC_GetDCPtr( pfe->hdc );
573 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
575 if (dc) GDI_ReleaseObj( pfe->hdc );
576 pfe->hdc = 0; /* make sure we don't try to release it later on */
577 ret = 0;
580 return ret;
583 /***********************************************************************
584 * FONT_EnumInstance
586 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
587 DWORD fType, LPARAM lp )
589 fontEnum32 *pfe = (fontEnum32*)lp;
590 INT ret = 1;
591 DC *dc;
593 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
594 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
595 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
597 /* convert font metrics */
598 ENUMLOGFONTEXA logfont;
599 NEWTEXTMETRICEXA tmA;
601 pfe->dwFlags |= ENUM_CALLED;
602 if (!(pfe->dwFlags & ENUM_UNICODE))
604 FONT_EnumLogFontExWToA( plf, &logfont);
605 FONT_NewTextMetricExWToA( ptm, &tmA );
606 plf = (LPENUMLOGFONTEXW)&logfont;
607 ptm = (NEWTEXTMETRICEXW *)&tmA;
609 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
611 ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
613 /* get the lock again and make sure the DC is still valid */
614 dc = DC_GetDCPtr( pfe->hdc );
615 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
617 if (dc) GDI_ReleaseObj( pfe->hdc );
618 pfe->hdc = 0; /* make sure we don't try to release it later on */
619 ret = 0;
622 return ret;
625 /***********************************************************************
626 * EnumFontFamiliesEx (GDI.613)
628 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
629 FONTENUMPROC16 efproc, LPARAM lParam,
630 DWORD dwFlags)
632 fontEnum16 fe16;
633 INT16 ret = 1, ret2;
634 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
635 NEWTEXTMETRICEX16 tm16;
636 ENUMLOGFONTEX16 lf16;
637 LOGFONTW lfW;
638 BOOL enum_gdi_fonts;
640 if (!dc) return 0;
641 FONT_LogFont16ToW(plf, &lfW);
643 fe16.hdc = HDC_32(hDC);
644 fe16.dc = dc;
645 fe16.physDev = dc->physDev;
646 fe16.lpLogFontParam = plf;
647 fe16.lpEnumFunc = efproc;
648 fe16.lpData = lParam;
649 fe16.lpTextMetric = &tm16;
650 fe16.lpLogFont = &lf16;
651 fe16.segTextMetric = MapLS( &tm16 );
652 fe16.segLogFont = MapLS( &lf16 );
653 fe16.dwFlags = 0;
655 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
657 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
659 ret = 0;
660 goto done;
663 if (enum_gdi_fonts)
664 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
665 fe16.dwFlags &= ~ENUM_CALLED;
666 if (ret && dc->funcs->pEnumDeviceFonts) {
667 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
668 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
669 ret = ret2;
671 done:
672 UnMapLS( fe16.segTextMetric );
673 UnMapLS( fe16.segLogFont );
674 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
675 return ret;
678 /***********************************************************************
679 * FONT_EnumFontFamiliesEx
681 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
682 FONTENUMPROCW efproc,
683 LPARAM lParam, DWORD dwUnicode)
685 INT ret = 1, ret2;
686 DC *dc = DC_GetDCPtr( hDC );
687 fontEnum32 fe32;
688 BOOL enum_gdi_fonts;
690 if (!dc) return 0;
692 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
693 plf->lfCharSet);
694 fe32.lpLogFontParam = plf;
695 fe32.lpEnumFunc = efproc;
696 fe32.lpData = lParam;
697 fe32.dwFlags = dwUnicode;
698 fe32.hdc = hDC;
699 fe32.dc = dc;
700 fe32.physDev = dc->physDev;
702 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
704 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
706 ret = 0;
707 goto done;
710 if (enum_gdi_fonts)
711 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
712 fe32.dwFlags &= ~ENUM_CALLED;
713 if (ret && dc->funcs->pEnumDeviceFonts) {
714 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
715 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
716 ret = ret2;
718 done:
719 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
720 return ret;
723 /***********************************************************************
724 * EnumFontFamiliesExW (GDI32.@)
726 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
727 FONTENUMPROCW efproc,
728 LPARAM lParam, DWORD dwFlags )
730 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
733 /***********************************************************************
734 * EnumFontFamiliesExA (GDI32.@)
736 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
737 FONTENUMPROCA efproc,
738 LPARAM lParam, DWORD dwFlags)
740 LOGFONTW lfW;
741 FONT_LogFontAToW( plf, &lfW );
743 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
746 /***********************************************************************
747 * EnumFontFamilies (GDI.330)
749 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
750 FONTENUMPROC16 efproc, LPARAM lpData )
752 LOGFONT16 lf;
754 lf.lfCharSet = DEFAULT_CHARSET;
755 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
756 else lf.lfFaceName[0] = '\0';
758 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
761 /***********************************************************************
762 * EnumFontFamiliesA (GDI32.@)
764 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
765 FONTENUMPROCA efproc, LPARAM lpData )
767 LOGFONTA lf;
769 lf.lfCharSet = DEFAULT_CHARSET;
770 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
771 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
773 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
776 /***********************************************************************
777 * EnumFontFamiliesW (GDI32.@)
779 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
780 FONTENUMPROCW efproc, LPARAM lpData )
782 LOGFONTW lf;
784 lf.lfCharSet = DEFAULT_CHARSET;
785 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
786 else lf.lfFaceName[0] = 0;
788 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
791 /***********************************************************************
792 * EnumFonts (GDI.70)
794 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
795 LPARAM lpData )
797 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
800 /***********************************************************************
801 * EnumFontsA (GDI32.@)
803 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
804 LPARAM lpData )
806 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
809 /***********************************************************************
810 * EnumFontsW (GDI32.@)
812 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
813 LPARAM lpData )
815 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
819 /***********************************************************************
820 * GetTextCharacterExtra (GDI32.@)
822 INT WINAPI GetTextCharacterExtra( HDC hdc )
824 INT ret;
825 DC *dc = DC_GetDCPtr( hdc );
826 if (!dc) return 0x80000000;
827 ret = dc->charExtra;
828 GDI_ReleaseObj( hdc );
829 return ret;
833 /***********************************************************************
834 * SetTextCharacterExtra (GDI32.@)
836 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
838 INT prev;
839 DC * dc = DC_GetDCPtr( hdc );
840 if (!dc) return 0x80000000;
841 if (dc->funcs->pSetTextCharacterExtra)
842 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
843 else
845 prev = dc->charExtra;
846 dc->charExtra = extra;
848 GDI_ReleaseObj( hdc );
849 return prev;
853 /***********************************************************************
854 * SetTextJustification (GDI32.@)
856 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
858 BOOL ret = TRUE;
859 DC * dc = DC_GetDCPtr( hdc );
860 if (!dc) return FALSE;
861 if (dc->funcs->pSetTextJustification)
862 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
863 else
865 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
866 if (!extra) breaks = 0;
867 dc->breakTotalExtra = extra;
868 dc->breakCount = breaks;
869 if (breaks)
871 dc->breakExtra = extra / breaks;
872 dc->breakRem = extra - (dc->breakCount * dc->breakExtra);
874 else
876 dc->breakExtra = 0;
877 dc->breakRem = 0;
880 GDI_ReleaseObj( hdc );
881 return ret;
885 /***********************************************************************
886 * GetTextFaceA (GDI32.@)
888 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
890 INT res = GetTextFaceW(hdc, 0, NULL);
891 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
892 GetTextFaceW( hdc, res, nameW );
894 if (name)
896 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
897 name[count-1] = 0;
898 res = strlen(name);
900 else
901 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
902 HeapFree( GetProcessHeap(), 0, nameW );
903 return res;
906 /***********************************************************************
907 * GetTextFaceW (GDI32.@)
909 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
911 FONTOBJ *font;
912 INT ret = 0;
914 DC * dc = DC_GetDCPtr( hdc );
915 if (!dc) return 0;
917 if(dc->gdiFont)
918 ret = WineEngGetTextFace(dc->gdiFont, count, name);
919 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
921 if (name)
923 lstrcpynW( name, font->logfont.lfFaceName, count );
924 ret = strlenW(name);
926 else ret = strlenW(font->logfont.lfFaceName) + 1;
927 GDI_ReleaseObj( dc->hFont );
929 GDI_ReleaseObj( hdc );
930 return ret;
934 /***********************************************************************
935 * GetTextExtentPoint32A (GDI32.@)
937 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
938 LPSIZE size )
940 BOOL ret = FALSE;
941 INT wlen;
942 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
944 if (p) {
945 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
946 HeapFree( GetProcessHeap(), 0, p );
949 TRACE("(%p %s %d %p): returning %ld x %ld\n",
950 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
951 return ret;
955 /***********************************************************************
956 * GetTextExtentPoint32W [GDI32.@] Computes width/height for a string
958 * Computes width and height of the specified string.
960 * RETURNS
961 * Success: TRUE
962 * Failure: FALSE
964 BOOL WINAPI GetTextExtentPoint32W(
965 HDC hdc, /* [in] Handle of device context */
966 LPCWSTR str, /* [in] Address of text string */
967 INT count, /* [in] Number of characters in string */
968 LPSIZE size) /* [out] Address of structure for string size */
970 BOOL ret = FALSE;
971 DC * dc = DC_GetDCPtr( hdc );
972 if (!dc) return FALSE;
974 if(dc->gdiFont) {
975 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
976 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
977 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
978 size->cx += count * dc->charExtra;
980 else if(dc->funcs->pGetTextExtentPoint)
981 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
983 GDI_ReleaseObj( hdc );
985 TRACE("(%p %s %d %p): returning %ld x %ld\n",
986 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
987 return ret;
990 /***********************************************************************
991 * GetTextExtentPointI [GDI32.@]
993 * Computes width and height of the array of glyph indices.
995 * RETURNS
996 * Success: TRUE
997 * Failure: FALSE
999 BOOL WINAPI GetTextExtentPointI(
1000 HDC hdc, /* [in] Handle of device context */
1001 const WORD *indices, /* [in] Address of glyph index array */
1002 INT count, /* [in] Number of glyphs in array */
1003 LPSIZE size) /* [out] Address of structure for string size */
1005 BOOL ret = FALSE;
1006 DC * dc = DC_GetDCPtr( hdc );
1007 if (!dc) return FALSE;
1009 if(dc->gdiFont) {
1010 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1011 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1012 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1013 size->cx += count * dc->charExtra;
1015 else if(dc->funcs->pGetTextExtentPoint) {
1016 FIXME("calling GetTextExtentPoint\n");
1017 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1020 GDI_ReleaseObj( hdc );
1022 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1023 hdc, indices, count, size, size->cx, size->cy );
1024 return ret;
1028 /***********************************************************************
1029 * GetTextExtentPointA (GDI32.@)
1031 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1032 LPSIZE size )
1034 TRACE("not bug compatible.\n");
1035 return GetTextExtentPoint32A( hdc, str, count, size );
1038 /***********************************************************************
1039 * GetTextExtentPointW (GDI32.@)
1041 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1042 LPSIZE size )
1044 TRACE("not bug compatible.\n");
1045 return GetTextExtentPoint32W( hdc, str, count, size );
1049 /***********************************************************************
1050 * GetTextExtentExPointA (GDI32.@)
1052 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1053 INT maxExt, LPINT lpnFit,
1054 LPINT alpDx, LPSIZE size )
1056 BOOL ret;
1057 INT wlen;
1058 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1059 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1060 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1061 HeapFree( GetProcessHeap(), 0, p );
1062 return ret;
1066 /***********************************************************************
1067 * GetTextExtentExPointW (GDI32.@)
1069 * Return the size of the string as it would be if it was output properly by
1070 * e.g. TextOut.
1072 * This should include
1073 * - Intercharacter spacing
1074 * - justification spacing (not yet done)
1075 * - kerning? see below
1077 * Kerning. Since kerning would be carried out by the rendering code it should
1078 * be done by the driver. However they don't support it yet. Also I am not
1079 * yet persuaded that (certainly under Win95) any kerning is actually done.
1081 * str: According to MSDN this should be null-terminated. That is not true; a
1082 * null will not terminate it early.
1083 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1084 * than count. I have seen it be either the size of the full string or
1085 * 1 less than the size of the full string. I have not seen it bear any
1086 * resemblance to the portion that would fit.
1087 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1088 * trailing intercharacter spacing and any trailing justification.
1090 * FIXME
1091 * Currently we do this by measuring each character etc. We should do it by
1092 * passing the request to the driver, perhaps by extending the
1093 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1094 * thinking about kerning issues and rounding issues in the justification.
1097 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1098 INT maxExt, LPINT lpnFit,
1099 LPINT alpDx, LPSIZE size )
1101 int index, nFit, extent;
1102 SIZE tSize;
1103 BOOL ret = FALSE;
1105 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1107 size->cx = size->cy = nFit = extent = 0;
1108 for(index = 0; index < count; index++)
1110 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1111 /* GetTextExtentPoint includes intercharacter spacing. */
1112 /* FIXME - justification needs doing yet. Remember that the base
1113 * data will not be in logical coordinates.
1115 extent += tSize.cx;
1116 if( !lpnFit || extent <= maxExt )
1117 /* It is allowed to be equal. */
1119 nFit++;
1120 if( alpDx ) alpDx[index] = extent;
1122 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1123 str++;
1125 size->cx = extent;
1126 if(lpnFit) *lpnFit = nFit;
1127 ret = TRUE;
1129 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1131 done:
1132 return ret;
1135 /***********************************************************************
1136 * GetTextMetricsA (GDI32.@)
1138 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1140 TEXTMETRICW tm32;
1142 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1143 FONT_TextMetricWToA( &tm32, metrics );
1144 return TRUE;
1147 /***********************************************************************
1148 * GetTextMetricsW (GDI32.@)
1150 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1152 BOOL ret = FALSE;
1153 DC * dc = DC_GetDCPtr( hdc );
1154 if (!dc) return FALSE;
1156 if (dc->gdiFont)
1157 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1158 else if (dc->funcs->pGetTextMetrics)
1159 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1161 if (ret)
1163 /* device layer returns values in device units
1164 * therefore we have to convert them to logical */
1166 #define WDPTOLP(x) ((x<0)? \
1167 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1168 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1169 #define HDPTOLP(y) ((y<0)? \
1170 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1171 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1173 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1174 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1175 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1176 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1177 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1178 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1179 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1180 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1181 ret = TRUE;
1182 #undef WDPTOLP
1183 #undef HDPTOLP
1184 TRACE("text metrics:\n"
1185 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1186 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1187 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1188 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1189 " PitchAndFamily = %02x\n"
1190 " --------------------\n"
1191 " InternalLeading = %li\n"
1192 " Ascent = %li\n"
1193 " Descent = %li\n"
1194 " Height = %li\n",
1195 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1196 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1197 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1198 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1199 metrics->tmPitchAndFamily,
1200 metrics->tmInternalLeading,
1201 metrics->tmAscent,
1202 metrics->tmDescent,
1203 metrics->tmHeight );
1205 GDI_ReleaseObj( hdc );
1206 return ret;
1210 /***********************************************************************
1211 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1213 * NOTES
1214 * lpOTM should be LPOUTLINETEXTMETRIC
1216 * RETURNS
1217 * Success: Non-zero or size of required buffer
1218 * Failure: 0
1220 UINT16 WINAPI GetOutlineTextMetrics16(
1221 HDC16 hdc, /* [in] Handle of device context */
1222 UINT16 cbData, /* [in] Size of metric data array */
1223 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1225 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1226 return 0;
1230 /***********************************************************************
1231 * GetOutlineTextMetricsA (GDI32.@)
1232 * Gets metrics for TrueType fonts.
1234 * NOTES
1235 * If the supplied buffer isn't big enough Windows partially fills it up to
1236 * its given length and returns that length.
1238 * RETURNS
1239 * Success: Non-zero or size of required buffer
1240 * Failure: 0
1242 UINT WINAPI GetOutlineTextMetricsA(
1243 HDC hdc, /* [in] Handle of device context */
1244 UINT cbData, /* [in] Size of metric data array */
1245 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1247 char buf[512], *ptr;
1248 UINT ret, needed;
1249 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1250 OUTLINETEXTMETRICA *output = lpOTM;
1251 INT left, len;
1253 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1254 return 0;
1255 if(ret > sizeof(buf))
1256 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1257 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1259 needed = sizeof(OUTLINETEXTMETRICA);
1260 if(lpOTMW->otmpFamilyName)
1261 needed += WideCharToMultiByte(CP_ACP, 0,
1262 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1263 NULL, 0, NULL, NULL);
1264 if(lpOTMW->otmpFaceName)
1265 needed += WideCharToMultiByte(CP_ACP, 0,
1266 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1267 NULL, 0, NULL, NULL);
1268 if(lpOTMW->otmpStyleName)
1269 needed += WideCharToMultiByte(CP_ACP, 0,
1270 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1271 NULL, 0, NULL, NULL);
1272 if(lpOTMW->otmpFullName)
1273 needed += WideCharToMultiByte(CP_ACP, 0,
1274 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1275 NULL, 0, NULL, NULL);
1277 if(!lpOTM) {
1278 ret = needed;
1279 goto end;
1282 TRACE("needed = %d\n", needed);
1283 if(needed > cbData)
1284 /* Since the supplied buffer isn't big enough, we'll alloc one
1285 that is and memcpy the first cbData bytes into the lpOTM at
1286 the end. */
1287 output = HeapAlloc(GetProcessHeap(), 0, needed);
1289 ret = output->otmSize = min(needed, cbData);
1290 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1291 output->otmFiller = 0;
1292 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1293 output->otmfsSelection = lpOTMW->otmfsSelection;
1294 output->otmfsType = lpOTMW->otmfsType;
1295 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1296 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1297 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1298 output->otmEMSquare = lpOTMW->otmEMSquare;
1299 output->otmAscent = lpOTMW->otmAscent;
1300 output->otmDescent = lpOTMW->otmDescent;
1301 output->otmLineGap = lpOTMW->otmLineGap;
1302 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1303 output->otmsXHeight = lpOTMW->otmsXHeight;
1304 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1305 output->otmMacAscent = lpOTMW->otmMacAscent;
1306 output->otmMacDescent = lpOTMW->otmMacDescent;
1307 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1308 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1309 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1310 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1311 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1312 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1313 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1314 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1315 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1316 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1319 ptr = (char*)(output + 1);
1320 left = needed - sizeof(*output);
1322 if(lpOTMW->otmpFamilyName) {
1323 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1324 len = WideCharToMultiByte(CP_ACP, 0,
1325 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1326 ptr, left, NULL, NULL);
1327 left -= len;
1328 ptr += len;
1329 } else
1330 output->otmpFamilyName = 0;
1332 if(lpOTMW->otmpFaceName) {
1333 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1334 len = WideCharToMultiByte(CP_ACP, 0,
1335 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1336 ptr, left, NULL, NULL);
1337 left -= len;
1338 ptr += len;
1339 } else
1340 output->otmpFaceName = 0;
1342 if(lpOTMW->otmpStyleName) {
1343 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1344 len = WideCharToMultiByte(CP_ACP, 0,
1345 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1346 ptr, left, NULL, NULL);
1347 left -= len;
1348 ptr += len;
1349 } else
1350 output->otmpStyleName = 0;
1352 if(lpOTMW->otmpFullName) {
1353 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1354 len = WideCharToMultiByte(CP_ACP, 0,
1355 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1356 ptr, left, NULL, NULL);
1357 left -= len;
1358 } else
1359 output->otmpFullName = 0;
1361 assert(left == 0);
1363 if(output != lpOTM) {
1364 memcpy(lpOTM, output, cbData);
1365 HeapFree(GetProcessHeap(), 0, output);
1368 end:
1369 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1370 HeapFree(GetProcessHeap(), 0, lpOTMW);
1372 return ret;
1376 /***********************************************************************
1377 * GetOutlineTextMetricsW [GDI32.@]
1379 UINT WINAPI GetOutlineTextMetricsW(
1380 HDC hdc, /* [in] Handle of device context */
1381 UINT cbData, /* [in] Size of metric data array */
1382 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1384 DC *dc = DC_GetDCPtr( hdc );
1385 OUTLINETEXTMETRICW *output = lpOTM;
1386 UINT ret;
1388 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1389 if(!dc) return 0;
1391 if(dc->gdiFont) {
1392 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1393 if(lpOTM && ret) {
1394 if(ret > cbData) {
1395 output = HeapAlloc(GetProcessHeap(), 0, ret);
1396 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1399 #define WDPTOLP(x) ((x<0)? \
1400 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1401 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1402 #define HDPTOLP(y) ((y<0)? \
1403 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1404 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1406 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1407 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1408 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1409 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1410 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1411 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1412 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1413 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1414 output->otmAscent = HDPTOLP(output->otmAscent);
1415 output->otmDescent = HDPTOLP(output->otmDescent);
1416 output->otmLineGap = HDPTOLP(output->otmLineGap);
1417 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1418 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1419 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1420 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1421 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1422 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1423 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1424 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1425 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1426 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1427 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1428 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1429 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1430 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1431 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1432 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1433 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1434 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1435 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1436 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1437 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1438 #undef WDPTOLP
1439 #undef HDPTOLP
1440 if(output != lpOTM) {
1441 memcpy(lpOTM, output, cbData);
1442 HeapFree(GetProcessHeap(), 0, output);
1443 ret = cbData;
1448 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1449 but really this should just be a return 0. */
1451 ret = sizeof(*lpOTM);
1452 if (lpOTM) {
1453 if(cbData < ret)
1454 ret = 0;
1455 else {
1456 memset(lpOTM, 0, ret);
1457 lpOTM->otmSize = sizeof(*lpOTM);
1458 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1460 Further fill of the structure not implemented,
1461 Needs real values for the structure members
1466 GDI_ReleaseObj(hdc);
1467 return ret;
1471 /***********************************************************************
1472 * GetCharWidthW (GDI32.@)
1473 * GetCharWidth32W (GDI32.@)
1475 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1476 LPINT buffer )
1478 UINT i;
1479 BOOL ret = FALSE;
1480 DC * dc = DC_GetDCPtr( hdc );
1481 if (!dc) return FALSE;
1483 if (dc->gdiFont)
1484 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1485 else if (dc->funcs->pGetCharWidth)
1486 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1488 if (ret)
1490 /* convert device units to logical */
1491 for( i = firstChar; i <= lastChar; i++, buffer++ )
1492 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1493 ret = TRUE;
1495 GDI_ReleaseObj( hdc );
1496 return ret;
1500 /***********************************************************************
1501 * GetCharWidthA (GDI32.@)
1502 * GetCharWidth32A (GDI32.@)
1504 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1505 LPINT buffer )
1507 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1508 LPSTR str;
1509 LPWSTR wstr;
1510 BOOL ret = TRUE;
1512 if(count <= 0) return FALSE;
1514 str = HeapAlloc(GetProcessHeap(), 0, count);
1515 for(i = 0; i < count; i++)
1516 str[i] = (BYTE)(firstChar + i);
1518 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1520 for(i = 0; i < wlen; i++)
1522 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1524 ret = FALSE;
1525 break;
1527 buffer++;
1530 HeapFree(GetProcessHeap(), 0, str);
1531 HeapFree(GetProcessHeap(), 0, wstr);
1533 return ret;
1537 /* FIXME: all following APIs ******************************************/
1540 /***********************************************************************
1541 * SetMapperFlags (GDI32.@)
1543 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1545 DC *dc = DC_GetDCPtr( hDC );
1546 DWORD ret = 0;
1547 if(!dc) return 0;
1548 if(dc->funcs->pSetMapperFlags)
1549 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1550 else
1551 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1552 GDI_ReleaseObj( hDC );
1553 return ret;
1556 /***********************************************************************
1557 * GetAspectRatioFilterEx (GDI.486)
1559 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1561 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1562 return FALSE;
1565 /***********************************************************************
1566 * GetAspectRatioFilterEx (GDI32.@)
1568 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1570 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1571 return FALSE;
1575 /***********************************************************************
1576 * GetCharABCWidthsA (GDI32.@)
1578 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1579 LPABC abc )
1581 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1582 LPSTR str;
1583 LPWSTR wstr;
1584 BOOL ret = TRUE;
1586 if(count <= 0) return FALSE;
1588 str = HeapAlloc(GetProcessHeap(), 0, count);
1589 for(i = 0; i < count; i++)
1590 str[i] = (BYTE)(firstChar + i);
1592 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1594 for(i = 0; i < wlen; i++)
1596 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1598 ret = FALSE;
1599 break;
1601 abc++;
1604 HeapFree(GetProcessHeap(), 0, str);
1605 HeapFree(GetProcessHeap(), 0, wstr);
1607 return ret;
1611 /******************************************************************************
1612 * GetCharABCWidthsW [GDI32.@] Retrieves widths of characters in range
1614 * PARAMS
1615 * hdc [I] Handle of device context
1616 * firstChar [I] First character in range to query
1617 * lastChar [I] Last character in range to query
1618 * abc [O] Address of character-width structure
1620 * NOTES
1621 * Only works with TrueType fonts
1623 * RETURNS
1624 * Success: TRUE
1625 * Failure: FALSE
1627 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1628 LPABC abc )
1630 DC *dc = DC_GetDCPtr(hdc);
1631 int i;
1632 GLYPHMETRICS gm;
1633 BOOL ret = FALSE;
1635 if(dc->gdiFont) {
1636 for (i=firstChar;i<=lastChar;i++) {
1637 GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1638 abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1639 abc[i-firstChar].abcB = gm.gmBlackBoxX;
1640 abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1642 ret = TRUE;
1644 GDI_ReleaseObj(hdc);
1645 return ret;
1649 /***********************************************************************
1650 * GetGlyphOutline (GDI.309)
1652 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1653 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1654 LPVOID lpBuffer, const MAT2 *lpmat2 )
1656 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1657 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1658 return (DWORD)-1; /* failure */
1662 /***********************************************************************
1663 * GetGlyphOutlineA (GDI32.@)
1665 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1666 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1667 LPVOID lpBuffer, const MAT2 *lpmat2 )
1669 LPWSTR p = NULL;
1670 DWORD ret;
1671 UINT c;
1673 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1674 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1675 c = p[0];
1676 } else
1677 c = uChar;
1678 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1679 lpmat2);
1680 if(p)
1681 HeapFree(GetProcessHeap(), 0, p);
1682 return ret;
1685 /***********************************************************************
1686 * GetGlyphOutlineW (GDI32.@)
1688 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1689 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1690 LPVOID lpBuffer, const MAT2 *lpmat2 )
1692 DC *dc = DC_GetDCPtr(hdc);
1693 DWORD ret;
1695 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1696 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1698 if(!dc) return GDI_ERROR;
1700 if(dc->gdiFont)
1701 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1702 cbBuffer, lpBuffer, lpmat2);
1703 else
1704 ret = GDI_ERROR;
1706 GDI_ReleaseObj(hdc);
1707 return ret;
1711 /***********************************************************************
1712 * CreateScalableFontResourceA (GDI32.@)
1714 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1715 LPCSTR lpszResourceFile,
1716 LPCSTR lpszFontFile,
1717 LPCSTR lpszCurrentPath )
1719 HANDLE f;
1721 /* fHidden=1 - only visible for the calling app, read-only, not
1722 * enumbered with EnumFonts/EnumFontFamilies
1723 * lpszCurrentPath can be NULL
1725 FIXME("(%ld,%s,%s,%s): stub\n",
1726 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1727 debugstr_a(lpszCurrentPath) );
1729 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1730 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1731 CloseHandle(f);
1732 SetLastError(ERROR_FILE_EXISTS);
1733 return FALSE;
1735 return FALSE; /* create failed */
1738 /***********************************************************************
1739 * CreateScalableFontResourceW (GDI32.@)
1741 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1742 LPCWSTR lpszResourceFile,
1743 LPCWSTR lpszFontFile,
1744 LPCWSTR lpszCurrentPath )
1746 FIXME("(%ld,%p,%p,%p): stub\n",
1747 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1748 return FALSE; /* create failed */
1752 /*************************************************************************
1753 * GetRasterizerCaps (GDI32.@)
1755 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1757 lprs->nSize = sizeof(RASTERIZER_STATUS);
1758 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1759 lprs->nLanguageID = 0;
1760 return TRUE;
1764 /*************************************************************************
1765 * GetKerningPairsA (GDI32.@)
1767 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1768 LPKERNINGPAIR lpKerningPairs )
1770 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1774 /*************************************************************************
1775 * GetKerningPairsW (GDI32.@)
1777 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1778 LPKERNINGPAIR lpKerningPairs )
1780 int i;
1781 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1782 for (i = 0; i < cPairs; i++)
1783 lpKerningPairs[i].iKernAmount = 0;
1784 return 0;
1787 /*************************************************************************
1788 * TranslateCharsetInfo [GDI32.@]
1790 * Fills a CHARSETINFO structure for a character set, code page, or
1791 * font. This allows making the correspondance between different labelings
1792 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1793 * of the same encoding.
1795 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1796 * only one codepage should be set in *lpSrc.
1798 * RETURNS
1799 * TRUE on success, FALSE on failure.
1802 BOOL WINAPI TranslateCharsetInfo(
1803 LPDWORD lpSrc, /* [in]
1804 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1805 if flags == TCI_SRCCHARSET: a character set value
1806 if flags == TCI_SRCCODEPAGE: a code page value
1808 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1809 DWORD flags /* [in] determines interpretation of lpSrc */
1811 int index = 0;
1812 switch (flags) {
1813 case TCI_SRCFONTSIG:
1814 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1815 break;
1816 case TCI_SRCCODEPAGE:
1817 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1818 break;
1819 case TCI_SRCCHARSET:
1820 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1821 break;
1822 default:
1823 return FALSE;
1825 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1826 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1827 return TRUE;
1830 /*************************************************************************
1831 * GetFontLanguageInfo (GDI32.@)
1833 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1835 FONTSIGNATURE fontsig;
1836 static const DWORD GCP_DBCS_MASK=0x003F0000,
1837 GCP_DIACRITIC_MASK=0x00000000,
1838 FLI_GLYPHS_MASK=0x00000000,
1839 GCP_GLYPHSHAPE_MASK=0x00000040,
1840 GCP_KASHIDA_MASK=0x00000000,
1841 GCP_LIGATE_MASK=0x00000000,
1842 GCP_USEKERNING_MASK=0x00000000,
1843 GCP_REORDER_MASK=0x00000060;
1845 DWORD result=0;
1847 GetTextCharsetInfo( hdc, &fontsig, 0 );
1848 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1850 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1851 result|=GCP_DBCS;
1853 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1854 result|=GCP_DIACRITIC;
1856 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1857 result|=FLI_GLYPHS;
1859 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1860 result|=GCP_GLYPHSHAPE;
1862 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1863 result|=GCP_KASHIDA;
1865 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1866 result|=GCP_LIGATE;
1868 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1869 result|=GCP_USEKERNING;
1871 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1872 result|=GCP_REORDER;
1874 return result;
1878 /*************************************************************************
1879 * GetFontData [GDI32.@] Retrieve data for TrueType font
1881 * RETURNS
1883 * success: Number of bytes returned
1884 * failure: GDI_ERROR
1886 * NOTES
1888 * Calls SetLastError()
1891 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1892 LPVOID buffer, DWORD length)
1894 DC *dc = DC_GetDCPtr(hdc);
1895 DWORD ret = GDI_ERROR;
1897 if(!dc) return GDI_ERROR;
1899 if(dc->gdiFont)
1900 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1902 GDI_ReleaseObj(hdc);
1903 return ret;
1906 /*************************************************************************
1907 * GetGlyphIndicesA [GDI32.@]
1909 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1910 LPWORD pgi, DWORD flags)
1912 DWORD ret;
1913 WCHAR *lpstrW;
1914 INT countW;
1916 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1917 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1919 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1920 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1921 HeapFree(GetProcessHeap(), 0, lpstrW);
1923 return ret;
1926 /*************************************************************************
1927 * GetGlyphIndicesW [GDI32.@]
1929 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1930 LPWORD pgi, DWORD flags)
1932 DC *dc = DC_GetDCPtr(hdc);
1933 DWORD ret = GDI_ERROR;
1935 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1936 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1938 if(!dc) return GDI_ERROR;
1940 if(dc->gdiFont)
1941 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1943 GDI_ReleaseObj(hdc);
1944 return ret;
1947 /*************************************************************************
1948 * GetCharacterPlacementA [GDI32.@]
1950 * NOTES:
1951 * the web browser control of ie4 calls this with dwFlags=0
1953 DWORD WINAPI
1954 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1955 INT nMaxExtent, GCP_RESULTSA *lpResults,
1956 DWORD dwFlags)
1958 WCHAR *lpStringW;
1959 INT uCountW, i;
1960 GCP_RESULTSW resultsW;
1961 DWORD ret;
1962 UINT font_cp;
1964 TRACE("%s, %d, %d, 0x%08lx\n",
1965 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1967 /* both structs are equal in size */
1968 memcpy(&resultsW, lpResults, sizeof(resultsW));
1970 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1971 if(lpResults->lpOutString)
1972 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1974 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1976 if(lpResults->lpOutString) {
1977 if(font_cp != CP_SYMBOL)
1978 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1979 lpResults->lpOutString, uCount, NULL, NULL );
1980 else
1981 for(i = 0; i < uCount; i++)
1982 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1985 HeapFree(GetProcessHeap(), 0, lpStringW);
1986 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1988 return ret;
1991 /*************************************************************************
1992 * GetCharacterPlacementW [GDI32.@]
1994 * Retrieve information about a string. This includes the width, reordering,
1995 * Glyphing and so on.
1997 * RETURNS
1999 * The width and height of the string if successful, 0 if failed.
2001 * BUGS
2003 * All flags except GCP_REORDER are not yet implemented.
2004 * Reordering is not 100% complient to the Windows BiDi method.
2005 * Caret positioning is not yet implemented for BiDi.
2006 * Classes are not yet implemented.
2009 DWORD WINAPI
2010 GetCharacterPlacementW(
2011 HDC hdc, /* [in] Device context for which the rendering is to be done */
2012 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2013 INT uCount, /* [in] Number of WORDS in string. */
2014 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2015 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2016 DWORD dwFlags /* [in] Flags specifying how to process the string */
2019 DWORD ret=0;
2020 SIZE size;
2021 UINT i, nSet;
2023 TRACE("%s, %d, %d, 0x%08lx\n",
2024 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2026 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2027 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2028 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2029 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2030 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2032 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2033 if(lpResults->lpClass) FIXME("classes not implemented\n");
2034 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2035 FIXME("Caret positions for complex scripts not implemented\n");
2037 nSet = (UINT)uCount;
2038 if(nSet > lpResults->nGlyphs)
2039 nSet = lpResults->nGlyphs;
2041 /* return number of initialized fields */
2042 lpResults->nGlyphs = nSet;
2044 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2046 /* Treat the case where no special handling was requested in a fastpath way */
2047 /* copy will do if the GCP_REORDER flag is not set */
2048 if(lpResults->lpOutString)
2049 strncpyW( lpResults->lpOutString, lpString, nSet );
2051 if(lpResults->lpOrder)
2053 for(i = 0; i < nSet; i++)
2054 lpResults->lpOrder[i] = i;
2056 } else
2058 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2059 nSet, lpResults->lpOrder );
2062 /* FIXME: Will use the placement chars */
2063 if (lpResults->lpDx)
2065 int c;
2066 for (i = 0; i < nSet; i++)
2068 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2069 lpResults->lpDx[i]= c;
2073 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2075 int pos = 0;
2077 lpResults->lpCaretPos[0] = 0;
2078 for (i = 1; i < nSet; i++)
2079 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2080 lpResults->lpCaretPos[i] = (pos += size.cx);
2083 if(lpResults->lpGlyphs)
2084 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2086 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2087 ret = MAKELONG(size.cx, size.cy);
2089 return ret;
2092 /*************************************************************************
2093 * GetCharABCWidthsFloatA [GDI32.@]
2095 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2096 LPABCFLOAT lpABCF)
2098 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2099 return 0;
2102 /*************************************************************************
2103 * GetCharABCWidthsFloatW [GDI32.@]
2105 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2106 UINT iLastChar, LPABCFLOAT lpABCF)
2108 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2109 return 0;
2112 /*************************************************************************
2113 * GetCharWidthFloatA [GDI32.@]
2115 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2116 UINT iLastChar, PFLOAT pxBuffer)
2118 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2119 return 0;
2122 /*************************************************************************
2123 * GetCharWidthFloatW [GDI32.@]
2125 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2126 UINT iLastChar, PFLOAT pxBuffer)
2128 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2129 return 0;
2133 /***********************************************************************
2135 * Font Resource API *
2137 ***********************************************************************/
2139 /***********************************************************************
2140 * AddFontResourceA (GDI32.@)
2142 INT WINAPI AddFontResourceA( LPCSTR str )
2144 return AddFontResourceExA( str, 0, NULL);
2147 /***********************************************************************
2148 * AddFontResourceW (GDI32.@)
2150 INT WINAPI AddFontResourceW( LPCWSTR str )
2152 return AddFontResourceExW(str, 0, NULL);
2156 /***********************************************************************
2157 * AddFontResourceExA (GDI32.@)
2159 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2161 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2162 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2163 INT ret;
2165 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2166 ret = AddFontResourceExW(strW, fl, pdv);
2167 HeapFree(GetProcessHeap(), 0, strW);
2168 return ret;
2171 /***********************************************************************
2172 * AddFontResourceExW (GDI32.@)
2174 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2176 return WineEngAddFontResourceEx(str, fl, pdv);
2179 /***********************************************************************
2180 * RemoveFontResourceA (GDI32.@)
2182 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2184 return RemoveFontResourceExA(str, 0, 0);
2187 /***********************************************************************
2188 * RemoveFontResourceW (GDI32.@)
2190 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2192 return RemoveFontResourceExW(str, 0, 0);
2195 /***********************************************************************
2196 * RemoveFontResourceExA (GDI32.@)
2198 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2200 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2201 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2202 INT ret;
2204 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2205 ret = RemoveFontResourceExW(strW, fl, pdv);
2206 HeapFree(GetProcessHeap(), 0, strW);
2207 return ret;
2210 /***********************************************************************
2211 * RemoveFontResourceExW (GDI32.@)
2213 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2215 return WineEngRemoveFontResourceEx(str, fl, pdv);
2218 /***********************************************************************
2219 * GetTextCharset (GDI32.@)
2221 UINT WINAPI GetTextCharset(HDC hdc)
2223 /* MSDN docs say this is equivalent */
2224 return GetTextCharsetInfo(hdc, NULL, 0);
2227 /***********************************************************************
2228 * GetTextCharsetInfo (GDI32.@)
2230 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2232 UINT ret = DEFAULT_CHARSET;
2233 DC *dc = DC_GetDCPtr(hdc);
2235 if (!dc) goto done;
2237 if (dc->gdiFont)
2238 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2240 GDI_ReleaseObj(hdc);
2242 done:
2243 if (ret == DEFAULT_CHARSET && fs)
2244 memset(fs, 0, sizeof(FONTSIGNATURE));
2245 return ret;