Remove the WINEDEBUG variable from the environment of the debugger
[wine/multimedia.git] / objects / font.c
blobcd029bc37f1ef0cbedb73f1b4e14dd10109ea2e3
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config.h"
24 #include "wine/port.h"
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi.h"
36 #include "gdi_private.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font);
41 WINE_DECLARE_DEBUG_CHANNEL(gdi);
43 /* Device -> World size conversion */
45 /* Performs a device to world transformation on the specified width (which
46 * is in integer format).
48 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
50 FLOAT floatWidth;
52 /* Perform operation with floating point */
53 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
54 /* Round to integers */
55 return GDI_ROUND(floatWidth);
58 /* Performs a device to world transformation on the specified size (which
59 * is in integer format).
61 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
63 FLOAT floatHeight;
65 /* Perform operation with floating point */
66 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
67 /* Round to integers */
68 return GDI_ROUND(floatHeight);
72 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
73 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
74 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
75 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
76 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
78 static const struct gdi_obj_funcs font_funcs =
80 FONT_SelectObject, /* pSelectObject */
81 FONT_GetObject16, /* pGetObject16 */
82 FONT_GetObjectA, /* pGetObjectA */
83 FONT_GetObjectW, /* pGetObjectW */
84 NULL, /* pUnrealizeObject */
85 FONT_DeleteObject /* pDeleteObject */
88 #define ENUM_UNICODE 0x00000001
89 #define ENUM_CALLED 0x00000002
91 typedef struct
93 GDIOBJHDR header;
94 LOGFONTW logfont;
95 } FONTOBJ;
97 typedef struct
99 LPLOGFONT16 lpLogFontParam;
100 FONTENUMPROC16 lpEnumFunc;
101 LPARAM lpData;
103 LPNEWTEXTMETRICEX16 lpTextMetric;
104 LPENUMLOGFONTEX16 lpLogFont;
105 SEGPTR segTextMetric;
106 SEGPTR segLogFont;
107 DWORD dwFlags;
108 HDC hdc;
109 DC *dc;
110 PHYSDEV physDev;
111 } fontEnum16;
113 typedef struct
115 LPLOGFONTW lpLogFontParam;
116 FONTENUMPROCW lpEnumFunc;
117 LPARAM lpData;
118 DWORD dwFlags;
119 HDC hdc;
120 DC *dc;
121 PHYSDEV physDev;
122 } fontEnum32;
125 * For TranslateCharsetInfo
127 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
128 #define MAXTCIINDEX 32
129 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
130 /* ANSI */
131 { ANSI_CHARSET, 1252, FS(0)},
132 { EASTEUROPE_CHARSET, 1250, FS(1)},
133 { RUSSIAN_CHARSET, 1251, FS(2)},
134 { GREEK_CHARSET, 1253, FS(3)},
135 { TURKISH_CHARSET, 1254, FS(4)},
136 { HEBREW_CHARSET, 1255, FS(5)},
137 { ARABIC_CHARSET, 1256, FS(6)},
138 { BALTIC_CHARSET, 1257, FS(7)},
139 { VIETNAMESE_CHARSET, 1258, FS(8)},
140 /* reserved by ANSI */
141 { DEFAULT_CHARSET, 0, FS(0)},
142 { DEFAULT_CHARSET, 0, FS(0)},
143 { DEFAULT_CHARSET, 0, FS(0)},
144 { DEFAULT_CHARSET, 0, FS(0)},
145 { DEFAULT_CHARSET, 0, FS(0)},
146 { DEFAULT_CHARSET, 0, FS(0)},
147 { DEFAULT_CHARSET, 0, FS(0)},
148 /* ANSI and OEM */
149 { THAI_CHARSET, 874, FS(16)},
150 { SHIFTJIS_CHARSET, 932, FS(17)},
151 { GB2312_CHARSET, 936, FS(18)},
152 { HANGEUL_CHARSET, 949, FS(19)},
153 { CHINESEBIG5_CHARSET, 950, FS(20)},
154 { JOHAB_CHARSET, 1361, FS(21)},
155 /* reserved for alternate ANSI and OEM */
156 { DEFAULT_CHARSET, 0, FS(0)},
157 { DEFAULT_CHARSET, 0, FS(0)},
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 /* reserved for system */
165 { DEFAULT_CHARSET, 0, FS(0)},
166 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
169 /***********************************************************************
170 * LOGFONT conversion functions.
172 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
174 font16->lfHeight = font32->lfHeight;
175 font16->lfWidth = font32->lfWidth;
176 font16->lfEscapement = font32->lfEscapement;
177 font16->lfOrientation = font32->lfOrientation;
178 font16->lfWeight = font32->lfWeight;
179 font16->lfItalic = font32->lfItalic;
180 font16->lfUnderline = font32->lfUnderline;
181 font16->lfStrikeOut = font32->lfStrikeOut;
182 font16->lfCharSet = font32->lfCharSet;
183 font16->lfOutPrecision = font32->lfOutPrecision;
184 font16->lfClipPrecision = font32->lfClipPrecision;
185 font16->lfQuality = font32->lfQuality;
186 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
187 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
188 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
189 font16->lfFaceName[LF_FACESIZE-1] = 0;
192 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
194 font32->lfHeight = font16->lfHeight;
195 font32->lfWidth = font16->lfWidth;
196 font32->lfEscapement = font16->lfEscapement;
197 font32->lfOrientation = font16->lfOrientation;
198 font32->lfWeight = font16->lfWeight;
199 font32->lfItalic = font16->lfItalic;
200 font32->lfUnderline = font16->lfUnderline;
201 font32->lfStrikeOut = font16->lfStrikeOut;
202 font32->lfCharSet = font16->lfCharSet;
203 font32->lfOutPrecision = font16->lfOutPrecision;
204 font32->lfClipPrecision = font16->lfClipPrecision;
205 font32->lfQuality = font16->lfQuality;
206 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
207 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
208 font32->lfFaceName[LF_FACESIZE-1] = 0;
211 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
213 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
214 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
215 LF_FACESIZE);
218 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
220 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
221 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
222 LF_FACESIZE, NULL, NULL);
225 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
227 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
229 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
230 font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
231 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
232 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
233 font16->elfStyle, LF_FACESIZE, NULL, NULL );
234 font16->elfStyle[LF_FACESIZE-1] = '\0';
235 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
236 font16->elfScript, LF_FACESIZE, NULL, NULL );
237 font16->elfScript[LF_FACESIZE-1] = '\0';
240 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
242 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
244 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
245 fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
246 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
247 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
248 fontA->elfStyle, LF_FACESIZE, NULL, NULL );
249 fontA->elfStyle[LF_FACESIZE-1] = '\0';
250 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
251 fontA->elfScript, LF_FACESIZE, NULL, NULL );
252 fontA->elfScript[LF_FACESIZE-1] = '\0';
255 /***********************************************************************
256 * TEXTMETRIC conversion functions.
258 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
260 ptmA->tmHeight = ptmW->tmHeight;
261 ptmA->tmAscent = ptmW->tmAscent;
262 ptmA->tmDescent = ptmW->tmDescent;
263 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
264 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
265 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
266 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
267 ptmA->tmWeight = ptmW->tmWeight;
268 ptmA->tmOverhang = ptmW->tmOverhang;
269 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
270 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
271 ptmA->tmFirstChar = ptmW->tmFirstChar > 255 ? 255 : ptmW->tmFirstChar;
272 ptmA->tmLastChar = ptmW->tmLastChar > 255 ? 255 : ptmW->tmLastChar;
273 ptmA->tmDefaultChar = ptmW->tmDefaultChar > 255 ? 255 : ptmW->tmDefaultChar;
274 ptmA->tmBreakChar = ptmW->tmBreakChar > 255 ? 255 : ptmW->tmBreakChar;
275 ptmA->tmItalic = ptmW->tmItalic;
276 ptmA->tmUnderlined = ptmW->tmUnderlined;
277 ptmA->tmStruckOut = ptmW->tmStruckOut;
278 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
279 ptmA->tmCharSet = ptmW->tmCharSet;
283 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
285 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
286 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
287 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
288 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
289 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
290 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
291 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
292 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
293 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
294 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
295 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
296 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar > 255 ? 255 : ptmW->ntmTm.tmFirstChar;
297 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar > 255 ? 255 : ptmW->ntmTm.tmLastChar;
298 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar > 255 ? 255 : ptmW->ntmTm.tmDefaultChar;
299 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar > 255 ? 255 : ptmW->ntmTm.tmBreakChar;
300 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
301 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
302 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
303 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
304 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
305 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
306 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
307 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
308 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
309 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
312 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
314 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
315 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
316 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
317 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
318 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
319 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
322 /***********************************************************************
323 * CreateFontIndirectA (GDI32.@)
325 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
327 LOGFONTW lfW;
329 if (plfA) {
330 FONT_LogFontAToW( plfA, &lfW );
331 return CreateFontIndirectW( &lfW );
332 } else
333 return CreateFontIndirectW( NULL );
337 /***********************************************************************
338 * CreateFontIndirectW (GDI32.@)
340 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
342 HFONT hFont = 0;
344 if (plf)
346 FONTOBJ* fontPtr;
347 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
348 (HGDIOBJ *)&hFont, &font_funcs )))
350 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
351 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
352 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
353 WCHAR* pFaceNameSuffix = NULL;
355 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
357 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s %s => %p\n",
358 plf->lfHeight, plf->lfWidth,
359 plf->lfEscapement, plf->lfOrientation,
360 plf->lfPitchAndFamily,
361 plf->lfOutPrecision, plf->lfClipPrecision,
362 plf->lfQuality, plf->lfCharSet,
363 debugstr_w(plf->lfFaceName),
364 plf->lfWeight > 400 ? "Bold" : "",
365 plf->lfItalic ? "Italic" : "",
366 plf->lfUnderline ? "Underline" : "", hFont);
368 if (plf->lfEscapement != plf->lfOrientation) {
369 /* this should really depend on whether GM_ADVANCED is set */
370 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
371 WARN("orientation angle %f set to "
372 "escapement angle %f for new font %p\n",
373 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
376 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
377 if (pFaceNameItalicSuffix) {
378 fontPtr->logfont.lfItalic = TRUE;
379 pFaceNameSuffix = pFaceNameItalicSuffix;
382 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
383 if (pFaceNameBoldSuffix) {
384 if (fontPtr->logfont.lfWeight < FW_BOLD) {
385 fontPtr->logfont.lfWeight = FW_BOLD;
387 if (!pFaceNameSuffix ||
388 (pFaceNameBoldSuffix < pFaceNameSuffix)) {
389 pFaceNameSuffix = pFaceNameBoldSuffix;
393 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
395 GDI_ReleaseObj( hFont );
398 else WARN("(NULL) => NULL\n");
400 return hFont;
403 /*************************************************************************
404 * CreateFontA (GDI32.@)
406 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
407 INT orient, INT weight, DWORD italic,
408 DWORD underline, DWORD strikeout, DWORD charset,
409 DWORD outpres, DWORD clippres, DWORD quality,
410 DWORD pitch, LPCSTR name )
412 LOGFONTA logfont;
414 logfont.lfHeight = height;
415 logfont.lfWidth = width;
416 logfont.lfEscapement = esc;
417 logfont.lfOrientation = orient;
418 logfont.lfWeight = weight;
419 logfont.lfItalic = italic;
420 logfont.lfUnderline = underline;
421 logfont.lfStrikeOut = strikeout;
422 logfont.lfCharSet = charset;
423 logfont.lfOutPrecision = outpres;
424 logfont.lfClipPrecision = clippres;
425 logfont.lfQuality = quality;
426 logfont.lfPitchAndFamily = pitch;
428 if (name)
429 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
430 else
431 logfont.lfFaceName[0] = '\0';
433 return CreateFontIndirectA( &logfont );
436 /*************************************************************************
437 * CreateFontW (GDI32.@)
439 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
440 INT orient, INT weight, DWORD italic,
441 DWORD underline, DWORD strikeout, DWORD charset,
442 DWORD outpres, DWORD clippres, DWORD quality,
443 DWORD pitch, LPCWSTR name )
445 LOGFONTW logfont;
447 logfont.lfHeight = height;
448 logfont.lfWidth = width;
449 logfont.lfEscapement = esc;
450 logfont.lfOrientation = orient;
451 logfont.lfWeight = weight;
452 logfont.lfItalic = italic;
453 logfont.lfUnderline = underline;
454 logfont.lfStrikeOut = strikeout;
455 logfont.lfCharSet = charset;
456 logfont.lfOutPrecision = outpres;
457 logfont.lfClipPrecision = clippres;
458 logfont.lfQuality = quality;
459 logfont.lfPitchAndFamily = pitch;
461 if (name)
462 lstrcpynW(logfont.lfFaceName, name,
463 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
464 else
465 logfont.lfFaceName[0] = '\0';
467 return CreateFontIndirectW( &logfont );
471 /***********************************************************************
472 * FONT_SelectObject
474 * If the driver supports vector fonts we create a gdi font first and
475 * then call the driver to give it a chance to supply its own device
476 * font. If the driver wants to do this it returns TRUE and we can
477 * delete the gdi font, if the driver wants to use the gdi font it
478 * should return FALSE, to signal an error return GDI_ERROR. For
479 * drivers that don't support vector fonts they must supply their own
480 * font.
482 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
484 HGDIOBJ ret = 0;
485 DC *dc = DC_GetDCPtr( hdc );
487 if (!dc) return 0;
489 if (dc->hFont != handle || dc->gdiFont == NULL)
491 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
492 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
495 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
497 if (ret && dc->gdiFont) dc->gdiFont = 0;
499 if (ret == HGDI_ERROR)
500 ret = 0; /* SelectObject returns 0 on error */
501 else
503 ret = dc->hFont;
504 dc->hFont = handle;
506 GDI_ReleaseObj( hdc );
507 return ret;
511 /***********************************************************************
512 * FONT_GetObject16
514 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
516 FONTOBJ *font = obj;
517 LOGFONT16 lf16;
519 FONT_LogFontWTo16( &font->logfont, &lf16 );
521 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
522 memcpy( buffer, &lf16, count );
523 return count;
526 /***********************************************************************
527 * FONT_GetObjectA
529 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
531 FONTOBJ *font = obj;
532 LOGFONTA lfA;
534 if(!buffer)
535 return sizeof(lfA);
536 FONT_LogFontWToA( &font->logfont, &lfA );
538 if (count > sizeof(lfA)) count = sizeof(lfA);
539 memcpy( buffer, &lfA, count );
540 return count;
543 /***********************************************************************
544 * FONT_GetObjectW
546 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
548 FONTOBJ *font = obj;
549 if(!buffer)
550 return sizeof(LOGFONTW);
551 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
552 memcpy( buffer, &font->logfont, count );
553 return count;
557 /***********************************************************************
558 * FONT_DeleteObject
560 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
562 WineEngDestroyFontInstance( handle );
563 return GDI_FreeObject( handle, obj );
567 /***********************************************************************
568 * FONT_EnumInstance16
570 * Called by the device driver layer to pass font info
571 * down to the application.
573 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
574 * We have to use other types because of the FONTENUMPROCW definition.
576 static INT CALLBACK FONT_EnumInstance16( const LOGFONTW *plf, const TEXTMETRICW *ptm,
577 DWORD fType, LPARAM lp )
579 fontEnum16 *pfe = (fontEnum16*)lp;
580 INT ret = 1;
581 DC *dc;
583 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
584 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
586 WORD args[7];
587 DWORD result;
589 FONT_EnumLogFontExWTo16((const ENUMLOGFONTEXW *)plf, pfe->lpLogFont);
590 FONT_NewTextMetricExWTo16((const NEWTEXTMETRICEXW *)ptm, pfe->lpTextMetric);
591 pfe->dwFlags |= ENUM_CALLED;
592 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
594 args[6] = SELECTOROF(pfe->segLogFont);
595 args[5] = OFFSETOF(pfe->segLogFont);
596 args[4] = SELECTOROF(pfe->segTextMetric);
597 args[3] = OFFSETOF(pfe->segTextMetric);
598 args[2] = fType;
599 args[1] = HIWORD(pfe->lpData);
600 args[0] = LOWORD(pfe->lpData);
601 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
602 ret = LOWORD(result);
604 /* get the lock again and make sure the DC is still valid */
605 dc = DC_GetDCPtr( pfe->hdc );
606 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
608 if (dc) GDI_ReleaseObj( pfe->hdc );
609 pfe->hdc = 0; /* make sure we don't try to release it later on */
610 ret = 0;
613 return ret;
616 /***********************************************************************
617 * FONT_EnumInstance
619 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
620 * We have to use other types because of the FONTENUMPROCW definition.
622 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
623 DWORD fType, LPARAM lp )
625 fontEnum32 *pfe = (fontEnum32*)lp;
626 INT ret = 1;
627 DC *dc;
629 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
630 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
631 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet )
633 /* convert font metrics */
634 ENUMLOGFONTEXA logfont;
635 NEWTEXTMETRICEXA tmA;
637 pfe->dwFlags |= ENUM_CALLED;
638 if (!(pfe->dwFlags & ENUM_UNICODE))
640 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
641 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
642 plf = (LOGFONTW *)&logfont.elfLogFont;
643 ptm = (TEXTMETRICW *)&tmA;
645 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
647 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
649 /* get the lock again and make sure the DC is still valid */
650 dc = DC_GetDCPtr( pfe->hdc );
651 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
653 if (dc) GDI_ReleaseObj( pfe->hdc );
654 pfe->hdc = 0; /* make sure we don't try to release it later on */
655 ret = 0;
658 return ret;
661 /***********************************************************************
662 * EnumFontFamiliesEx (GDI.613)
664 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
665 FONTENUMPROC16 efproc, LPARAM lParam,
666 DWORD dwFlags)
668 fontEnum16 fe16;
669 INT16 ret = 1, ret2;
670 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
671 NEWTEXTMETRICEX16 tm16;
672 ENUMLOGFONTEX16 lf16;
673 LOGFONTW lfW;
674 BOOL enum_gdi_fonts;
676 if (!dc) return 0;
677 FONT_LogFont16ToW(plf, &lfW);
679 fe16.hdc = HDC_32(hDC);
680 fe16.dc = dc;
681 fe16.physDev = dc->physDev;
682 fe16.lpLogFontParam = plf;
683 fe16.lpEnumFunc = efproc;
684 fe16.lpData = lParam;
685 fe16.lpTextMetric = &tm16;
686 fe16.lpLogFont = &lf16;
687 fe16.segTextMetric = MapLS( &tm16 );
688 fe16.segLogFont = MapLS( &lf16 );
689 fe16.dwFlags = 0;
691 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
693 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
695 ret = 0;
696 goto done;
699 if (enum_gdi_fonts)
700 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
701 fe16.dwFlags &= ~ENUM_CALLED;
702 if (ret && dc->funcs->pEnumDeviceFonts) {
703 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
704 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
705 ret = ret2;
707 done:
708 UnMapLS( fe16.segTextMetric );
709 UnMapLS( fe16.segLogFont );
710 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
711 return ret;
714 /***********************************************************************
715 * FONT_EnumFontFamiliesEx
717 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
718 FONTENUMPROCW efproc,
719 LPARAM lParam, DWORD dwUnicode)
721 INT ret = 1, ret2;
722 DC *dc = DC_GetDCPtr( hDC );
723 fontEnum32 fe32;
724 BOOL enum_gdi_fonts;
726 if (!dc) return 0;
728 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
729 plf->lfCharSet);
730 fe32.lpLogFontParam = plf;
731 fe32.lpEnumFunc = efproc;
732 fe32.lpData = lParam;
733 fe32.dwFlags = dwUnicode;
734 fe32.hdc = hDC;
735 fe32.dc = dc;
736 fe32.physDev = dc->physDev;
738 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
740 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
742 ret = 0;
743 goto done;
746 if (enum_gdi_fonts)
747 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
748 fe32.dwFlags &= ~ENUM_CALLED;
749 if (ret && dc->funcs->pEnumDeviceFonts) {
750 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
751 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
752 ret = ret2;
754 done:
755 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
756 return ret;
759 /***********************************************************************
760 * EnumFontFamiliesExW (GDI32.@)
762 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
763 FONTENUMPROCW efproc,
764 LPARAM lParam, DWORD dwFlags )
766 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
769 /***********************************************************************
770 * EnumFontFamiliesExA (GDI32.@)
772 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
773 FONTENUMPROCA efproc,
774 LPARAM lParam, DWORD dwFlags)
776 LOGFONTW lfW;
777 FONT_LogFontAToW( plf, &lfW );
779 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
782 /***********************************************************************
783 * EnumFontFamilies (GDI.330)
785 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
786 FONTENUMPROC16 efproc, LPARAM lpData )
788 LOGFONT16 lf;
790 lf.lfCharSet = DEFAULT_CHARSET;
791 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
792 else lf.lfFaceName[0] = '\0';
794 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
797 /***********************************************************************
798 * EnumFontFamiliesA (GDI32.@)
800 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
801 FONTENUMPROCA efproc, LPARAM lpData )
803 LOGFONTA lf;
805 lf.lfCharSet = DEFAULT_CHARSET;
806 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
807 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
809 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
812 /***********************************************************************
813 * EnumFontFamiliesW (GDI32.@)
815 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
816 FONTENUMPROCW efproc, LPARAM lpData )
818 LOGFONTW lf;
820 lf.lfCharSet = DEFAULT_CHARSET;
821 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
822 else lf.lfFaceName[0] = 0;
824 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
827 /***********************************************************************
828 * EnumFonts (GDI.70)
830 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
831 LPARAM lpData )
833 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
836 /***********************************************************************
837 * EnumFontsA (GDI32.@)
839 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
840 LPARAM lpData )
842 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
845 /***********************************************************************
846 * EnumFontsW (GDI32.@)
848 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
849 LPARAM lpData )
851 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
855 /***********************************************************************
856 * GetTextCharacterExtra (GDI32.@)
858 INT WINAPI GetTextCharacterExtra( HDC hdc )
860 INT ret;
861 DC *dc = DC_GetDCPtr( hdc );
862 if (!dc) return 0x80000000;
863 ret = dc->charExtra;
864 GDI_ReleaseObj( hdc );
865 return ret;
869 /***********************************************************************
870 * SetTextCharacterExtra (GDI32.@)
872 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
874 INT prev;
875 DC * dc = DC_GetDCPtr( hdc );
876 if (!dc) return 0x80000000;
877 if (dc->funcs->pSetTextCharacterExtra)
878 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
879 else
881 prev = dc->charExtra;
882 dc->charExtra = extra;
884 GDI_ReleaseObj( hdc );
885 return prev;
889 /***********************************************************************
890 * SetTextJustification (GDI32.@)
892 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
894 BOOL ret = TRUE;
895 DC * dc = DC_GetDCPtr( hdc );
896 if (!dc) return FALSE;
897 if (dc->funcs->pSetTextJustification)
898 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
899 else
901 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
902 if (!extra) breaks = 0;
903 if (breaks)
905 dc->breakExtra = extra / breaks;
906 dc->breakRem = extra - (breaks * dc->breakExtra);
908 else
910 dc->breakExtra = 0;
911 dc->breakRem = 0;
914 GDI_ReleaseObj( hdc );
915 return ret;
919 /***********************************************************************
920 * GetTextFaceA (GDI32.@)
922 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
924 INT res = GetTextFaceW(hdc, 0, NULL);
925 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
926 GetTextFaceW( hdc, res, nameW );
928 if (name)
930 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
931 name[count-1] = 0;
932 res = strlen(name);
934 else
935 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
936 HeapFree( GetProcessHeap(), 0, nameW );
937 return res;
940 /***********************************************************************
941 * GetTextFaceW (GDI32.@)
943 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
945 FONTOBJ *font;
946 INT ret = 0;
948 DC * dc = DC_GetDCPtr( hdc );
949 if (!dc) return 0;
951 if(dc->gdiFont)
952 ret = WineEngGetTextFace(dc->gdiFont, count, name);
953 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
955 if (name)
957 lstrcpynW( name, font->logfont.lfFaceName, count );
958 ret = strlenW(name);
960 else ret = strlenW(font->logfont.lfFaceName) + 1;
961 GDI_ReleaseObj( dc->hFont );
963 GDI_ReleaseObj( hdc );
964 return ret;
968 /***********************************************************************
969 * GetTextExtentPoint32A (GDI32.@)
971 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
972 LPSIZE size )
974 BOOL ret = FALSE;
975 INT wlen;
976 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
978 if (p) {
979 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
980 HeapFree( GetProcessHeap(), 0, p );
983 TRACE("(%p %s %d %p): returning %ld x %ld\n",
984 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
985 return ret;
989 /***********************************************************************
990 * GetTextExtentPoint32W [GDI32.@]
992 * Computes width/height for a string.
994 * Computes width and height of the specified string.
996 * RETURNS
997 * Success: TRUE
998 * Failure: FALSE
1000 BOOL WINAPI GetTextExtentPoint32W(
1001 HDC hdc, /* [in] Handle of device context */
1002 LPCWSTR str, /* [in] Address of text string */
1003 INT count, /* [in] Number of characters in string */
1004 LPSIZE size) /* [out] Address of structure for string size */
1006 BOOL ret = FALSE;
1007 DC * dc = DC_GetDCPtr( hdc );
1008 if (!dc) return FALSE;
1010 if(dc->gdiFont)
1011 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1012 else if(dc->funcs->pGetTextExtentPoint)
1013 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1015 if (ret)
1017 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1018 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1019 size->cx += count * dc->charExtra + dc->breakRem;
1022 GDI_ReleaseObj( hdc );
1024 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1025 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1026 return ret;
1029 /***********************************************************************
1030 * GetTextExtentPointI [GDI32.@]
1032 * Computes width and height of the array of glyph indices.
1034 * RETURNS
1035 * Success: TRUE
1036 * Failure: FALSE
1038 BOOL WINAPI GetTextExtentPointI(
1039 HDC hdc, /* [in] Handle of device context */
1040 const WORD *indices, /* [in] Address of glyph index array */
1041 INT count, /* [in] Number of glyphs in array */
1042 LPSIZE size) /* [out] Address of structure for string size */
1044 BOOL ret = FALSE;
1045 DC * dc = DC_GetDCPtr( hdc );
1046 if (!dc) return FALSE;
1048 if(dc->gdiFont) {
1049 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1050 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1051 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1052 size->cx += count * dc->charExtra;
1054 else if(dc->funcs->pGetTextExtentPoint) {
1055 FIXME("calling GetTextExtentPoint\n");
1056 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1059 GDI_ReleaseObj( hdc );
1061 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1062 hdc, indices, count, size, size->cx, size->cy );
1063 return ret;
1067 /***********************************************************************
1068 * GetTextExtentPointA (GDI32.@)
1070 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1071 LPSIZE size )
1073 TRACE("not bug compatible.\n");
1074 return GetTextExtentPoint32A( hdc, str, count, size );
1077 /***********************************************************************
1078 * GetTextExtentPointW (GDI32.@)
1080 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1081 LPSIZE size )
1083 TRACE("not bug compatible.\n");
1084 return GetTextExtentPoint32W( hdc, str, count, size );
1088 /***********************************************************************
1089 * GetTextExtentExPointA (GDI32.@)
1091 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1092 INT maxExt, LPINT lpnFit,
1093 LPINT alpDx, LPSIZE size )
1095 BOOL ret;
1096 INT wlen;
1097 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1098 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1099 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1100 HeapFree( GetProcessHeap(), 0, p );
1101 return ret;
1105 /***********************************************************************
1106 * GetTextExtentExPointW (GDI32.@)
1108 * Return the size of the string as it would be if it was output properly by
1109 * e.g. TextOut.
1111 * This should include
1112 * - Intercharacter spacing
1113 * - justification spacing (not yet done)
1114 * - kerning? see below
1116 * Kerning. Since kerning would be carried out by the rendering code it should
1117 * be done by the driver. However they don't support it yet. Also I am not
1118 * yet persuaded that (certainly under Win95) any kerning is actually done.
1120 * str: According to MSDN this should be null-terminated. That is not true; a
1121 * null will not terminate it early.
1122 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1123 * than count. I have seen it be either the size of the full string or
1124 * 1 less than the size of the full string. I have not seen it bear any
1125 * resemblance to the portion that would fit.
1126 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1127 * trailing intercharacter spacing and any trailing justification.
1129 * FIXME
1130 * Currently we do this by measuring each character etc. We should do it by
1131 * passing the request to the driver, perhaps by extending the
1132 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1133 * thinking about kerning issues and rounding issues in the justification.
1136 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1137 INT maxExt, LPINT lpnFit,
1138 LPINT alpDx, LPSIZE size )
1140 int index, nFit, extent;
1141 SIZE tSize;
1142 BOOL ret = FALSE;
1144 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1146 size->cx = size->cy = nFit = extent = 0;
1147 for(index = 0; index < count; index++)
1149 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1150 /* GetTextExtentPoint includes intercharacter spacing. */
1151 /* FIXME - justification needs doing yet. Remember that the base
1152 * data will not be in logical coordinates.
1154 extent += tSize.cx;
1155 if( !lpnFit || extent <= maxExt )
1156 /* It is allowed to be equal. */
1158 nFit++;
1159 if( alpDx ) alpDx[index] = extent;
1161 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1162 str++;
1164 size->cx = extent;
1165 if(lpnFit) *lpnFit = nFit;
1166 ret = TRUE;
1168 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1170 done:
1171 return ret;
1174 /***********************************************************************
1175 * GetTextMetricsA (GDI32.@)
1177 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1179 TEXTMETRICW tm32;
1181 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1182 FONT_TextMetricWToA( &tm32, metrics );
1183 return TRUE;
1186 /***********************************************************************
1187 * GetTextMetricsW (GDI32.@)
1189 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1191 BOOL ret = FALSE;
1192 DC * dc = DC_GetDCPtr( hdc );
1193 if (!dc) return FALSE;
1195 if (dc->gdiFont)
1196 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1197 else if (dc->funcs->pGetTextMetrics)
1198 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1200 if (ret)
1202 /* device layer returns values in device units
1203 * therefore we have to convert them to logical */
1205 #define WDPTOLP(x) ((x<0)? \
1206 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1207 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1208 #define HDPTOLP(y) ((y<0)? \
1209 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1210 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1212 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1213 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1214 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1215 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1216 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1217 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1218 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1219 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1220 ret = TRUE;
1221 #undef WDPTOLP
1222 #undef HDPTOLP
1223 TRACE("text metrics:\n"
1224 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1225 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1226 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1227 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1228 " PitchAndFamily = %02x\n"
1229 " --------------------\n"
1230 " InternalLeading = %li\n"
1231 " Ascent = %li\n"
1232 " Descent = %li\n"
1233 " Height = %li\n",
1234 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1235 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1236 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1237 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1238 metrics->tmPitchAndFamily,
1239 metrics->tmInternalLeading,
1240 metrics->tmAscent,
1241 metrics->tmDescent,
1242 metrics->tmHeight );
1244 GDI_ReleaseObj( hdc );
1245 return ret;
1249 /***********************************************************************
1250 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1252 * NOTES
1253 * lpOTM should be LPOUTLINETEXTMETRIC
1255 * RETURNS
1256 * Success: Non-zero or size of required buffer
1257 * Failure: 0
1259 UINT16 WINAPI GetOutlineTextMetrics16(
1260 HDC16 hdc, /* [in] Handle of device context */
1261 UINT16 cbData, /* [in] Size of metric data array */
1262 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1264 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1265 return 0;
1269 /***********************************************************************
1270 * GetOutlineTextMetricsA (GDI32.@)
1271 * Gets metrics for TrueType fonts.
1273 * NOTES
1274 * If the supplied buffer isn't big enough Windows partially fills it up to
1275 * its given length and returns that length.
1277 * RETURNS
1278 * Success: Non-zero or size of required buffer
1279 * Failure: 0
1281 UINT WINAPI GetOutlineTextMetricsA(
1282 HDC hdc, /* [in] Handle of device context */
1283 UINT cbData, /* [in] Size of metric data array */
1284 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1286 char buf[512], *ptr;
1287 UINT ret, needed;
1288 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1289 OUTLINETEXTMETRICA *output = lpOTM;
1290 INT left, len;
1292 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1293 return 0;
1294 if(ret > sizeof(buf))
1295 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1296 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1298 needed = sizeof(OUTLINETEXTMETRICA);
1299 if(lpOTMW->otmpFamilyName)
1300 needed += WideCharToMultiByte(CP_ACP, 0,
1301 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1302 NULL, 0, NULL, NULL);
1303 if(lpOTMW->otmpFaceName)
1304 needed += WideCharToMultiByte(CP_ACP, 0,
1305 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1306 NULL, 0, NULL, NULL);
1307 if(lpOTMW->otmpStyleName)
1308 needed += WideCharToMultiByte(CP_ACP, 0,
1309 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1310 NULL, 0, NULL, NULL);
1311 if(lpOTMW->otmpFullName)
1312 needed += WideCharToMultiByte(CP_ACP, 0,
1313 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1314 NULL, 0, NULL, NULL);
1316 if(!lpOTM) {
1317 ret = needed;
1318 goto end;
1321 TRACE("needed = %d\n", needed);
1322 if(needed > cbData)
1323 /* Since the supplied buffer isn't big enough, we'll alloc one
1324 that is and memcpy the first cbData bytes into the lpOTM at
1325 the end. */
1326 output = HeapAlloc(GetProcessHeap(), 0, needed);
1328 ret = output->otmSize = min(needed, cbData);
1329 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1330 output->otmFiller = 0;
1331 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1332 output->otmfsSelection = lpOTMW->otmfsSelection;
1333 output->otmfsType = lpOTMW->otmfsType;
1334 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1335 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1336 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1337 output->otmEMSquare = lpOTMW->otmEMSquare;
1338 output->otmAscent = lpOTMW->otmAscent;
1339 output->otmDescent = lpOTMW->otmDescent;
1340 output->otmLineGap = lpOTMW->otmLineGap;
1341 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1342 output->otmsXHeight = lpOTMW->otmsXHeight;
1343 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1344 output->otmMacAscent = lpOTMW->otmMacAscent;
1345 output->otmMacDescent = lpOTMW->otmMacDescent;
1346 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1347 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1348 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1349 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1350 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1351 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1352 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1353 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1354 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1355 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1358 ptr = (char*)(output + 1);
1359 left = needed - sizeof(*output);
1361 if(lpOTMW->otmpFamilyName) {
1362 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1363 len = WideCharToMultiByte(CP_ACP, 0,
1364 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1365 ptr, left, NULL, NULL);
1366 left -= len;
1367 ptr += len;
1368 } else
1369 output->otmpFamilyName = 0;
1371 if(lpOTMW->otmpFaceName) {
1372 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1373 len = WideCharToMultiByte(CP_ACP, 0,
1374 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1375 ptr, left, NULL, NULL);
1376 left -= len;
1377 ptr += len;
1378 } else
1379 output->otmpFaceName = 0;
1381 if(lpOTMW->otmpStyleName) {
1382 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1383 len = WideCharToMultiByte(CP_ACP, 0,
1384 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1385 ptr, left, NULL, NULL);
1386 left -= len;
1387 ptr += len;
1388 } else
1389 output->otmpStyleName = 0;
1391 if(lpOTMW->otmpFullName) {
1392 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1393 len = WideCharToMultiByte(CP_ACP, 0,
1394 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1395 ptr, left, NULL, NULL);
1396 left -= len;
1397 } else
1398 output->otmpFullName = 0;
1400 assert(left == 0);
1402 if(output != lpOTM) {
1403 memcpy(lpOTM, output, cbData);
1404 HeapFree(GetProcessHeap(), 0, output);
1407 end:
1408 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1409 HeapFree(GetProcessHeap(), 0, lpOTMW);
1411 return ret;
1415 /***********************************************************************
1416 * GetOutlineTextMetricsW [GDI32.@]
1418 UINT WINAPI GetOutlineTextMetricsW(
1419 HDC hdc, /* [in] Handle of device context */
1420 UINT cbData, /* [in] Size of metric data array */
1421 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1423 DC *dc = DC_GetDCPtr( hdc );
1424 OUTLINETEXTMETRICW *output = lpOTM;
1425 UINT ret;
1427 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1428 if(!dc) return 0;
1430 if(dc->gdiFont) {
1431 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1432 if(lpOTM && ret) {
1433 if(ret > cbData) {
1434 output = HeapAlloc(GetProcessHeap(), 0, ret);
1435 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1438 #define WDPTOLP(x) ((x<0)? \
1439 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1440 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1441 #define HDPTOLP(y) ((y<0)? \
1442 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1443 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1445 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1446 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1447 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1448 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1449 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1450 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1451 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1452 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1453 output->otmAscent = HDPTOLP(output->otmAscent);
1454 output->otmDescent = HDPTOLP(output->otmDescent);
1455 output->otmLineGap = HDPTOLP(output->otmLineGap);
1456 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1457 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1458 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1459 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1460 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1461 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1462 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1463 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1464 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1465 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1466 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1467 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1468 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1469 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1470 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1471 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1472 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1473 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1474 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1475 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1476 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1477 #undef WDPTOLP
1478 #undef HDPTOLP
1479 if(output != lpOTM) {
1480 memcpy(lpOTM, output, cbData);
1481 HeapFree(GetProcessHeap(), 0, output);
1482 ret = cbData;
1487 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1488 but really this should just be a return 0. */
1490 ret = sizeof(*lpOTM);
1491 if (lpOTM) {
1492 if(cbData < ret)
1493 ret = 0;
1494 else {
1495 memset(lpOTM, 0, ret);
1496 lpOTM->otmSize = sizeof(*lpOTM);
1497 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1499 Further fill of the structure not implemented,
1500 Needs real values for the structure members
1505 GDI_ReleaseObj(hdc);
1506 return ret;
1510 /***********************************************************************
1511 * GetCharWidthW (GDI32.@)
1512 * GetCharWidth32W (GDI32.@)
1514 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1515 LPINT buffer )
1517 UINT i;
1518 BOOL ret = FALSE;
1519 DC * dc = DC_GetDCPtr( hdc );
1520 if (!dc) return FALSE;
1522 if (dc->gdiFont)
1523 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1524 else if (dc->funcs->pGetCharWidth)
1525 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1527 if (ret)
1529 /* convert device units to logical */
1530 for( i = firstChar; i <= lastChar; i++, buffer++ )
1531 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1532 ret = TRUE;
1534 GDI_ReleaseObj( hdc );
1535 return ret;
1539 /***********************************************************************
1540 * GetCharWidthA (GDI32.@)
1541 * GetCharWidth32A (GDI32.@)
1543 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1544 LPINT buffer )
1546 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1547 LPSTR str;
1548 LPWSTR wstr;
1549 BOOL ret = TRUE;
1551 if(count <= 0) return FALSE;
1553 str = HeapAlloc(GetProcessHeap(), 0, count);
1554 for(i = 0; i < count; i++)
1555 str[i] = (BYTE)(firstChar + i);
1557 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1559 for(i = 0; i < wlen; i++)
1561 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1563 ret = FALSE;
1564 break;
1566 buffer++;
1569 HeapFree(GetProcessHeap(), 0, str);
1570 HeapFree(GetProcessHeap(), 0, wstr);
1572 return ret;
1576 /* FIXME: all following APIs ******************************************/
1579 /***********************************************************************
1580 * SetMapperFlags (GDI32.@)
1582 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1584 DC *dc = DC_GetDCPtr( hDC );
1585 DWORD ret = 0;
1586 if(!dc) return 0;
1587 if(dc->funcs->pSetMapperFlags)
1588 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1589 else
1590 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1591 GDI_ReleaseObj( hDC );
1592 return ret;
1595 /***********************************************************************
1596 * GetAspectRatioFilterEx (GDI.486)
1598 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1600 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1601 return FALSE;
1604 /***********************************************************************
1605 * GetAspectRatioFilterEx (GDI32.@)
1607 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1609 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1610 return FALSE;
1614 /***********************************************************************
1615 * GetCharABCWidthsA (GDI32.@)
1617 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1618 LPABC abc )
1620 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1621 LPSTR str;
1622 LPWSTR wstr;
1623 BOOL ret = TRUE;
1625 if(count <= 0) return FALSE;
1627 str = HeapAlloc(GetProcessHeap(), 0, count);
1628 for(i = 0; i < count; i++)
1629 str[i] = (BYTE)(firstChar + i);
1631 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1633 for(i = 0; i < wlen; i++)
1635 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1637 ret = FALSE;
1638 break;
1640 abc++;
1643 HeapFree(GetProcessHeap(), 0, str);
1644 HeapFree(GetProcessHeap(), 0, wstr);
1646 return ret;
1650 /******************************************************************************
1651 * GetCharABCWidthsW [GDI32.@]
1653 * Retrieves widths of characters in range.
1655 * PARAMS
1656 * hdc [I] Handle of device context
1657 * firstChar [I] First character in range to query
1658 * lastChar [I] Last character in range to query
1659 * abc [O] Address of character-width structure
1661 * NOTES
1662 * Only works with TrueType fonts
1664 * RETURNS
1665 * Success: TRUE
1666 * Failure: FALSE
1668 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1669 LPABC abc )
1671 DC *dc = DC_GetDCPtr(hdc);
1672 int i;
1673 BOOL ret = FALSE;
1675 if(dc->gdiFont)
1676 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1677 else
1678 FIXME(": stub\n");
1680 if (ret)
1682 /* convert device units to logical */
1683 for( i = firstChar; i <= lastChar; i++, abc++ ) {
1684 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1685 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1686 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1688 ret = TRUE;
1691 GDI_ReleaseObj(hdc);
1692 return ret;
1696 /***********************************************************************
1697 * GetGlyphOutline (GDI.309)
1699 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1700 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1701 LPVOID lpBuffer, const MAT2 *lpmat2 )
1703 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1704 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1705 return ~0UL; /* failure */
1709 /***********************************************************************
1710 * GetGlyphOutlineA (GDI32.@)
1712 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1713 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1714 LPVOID lpBuffer, const MAT2 *lpmat2 )
1716 LPWSTR p = NULL;
1717 DWORD ret;
1718 UINT c;
1720 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1721 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1722 c = p[0];
1723 } else
1724 c = uChar;
1725 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1726 lpmat2);
1727 if(p)
1728 HeapFree(GetProcessHeap(), 0, p);
1729 return ret;
1732 /***********************************************************************
1733 * GetGlyphOutlineW (GDI32.@)
1735 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1736 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1737 LPVOID lpBuffer, const MAT2 *lpmat2 )
1739 DC *dc = DC_GetDCPtr(hdc);
1740 DWORD ret;
1742 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1743 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1745 if(!dc) return GDI_ERROR;
1747 if(dc->gdiFont)
1748 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1749 cbBuffer, lpBuffer, lpmat2);
1750 else
1751 ret = GDI_ERROR;
1753 GDI_ReleaseObj(hdc);
1754 return ret;
1758 /***********************************************************************
1759 * CreateScalableFontResourceA (GDI32.@)
1761 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1762 LPCSTR lpszResourceFile,
1763 LPCSTR lpszFontFile,
1764 LPCSTR lpszCurrentPath )
1766 HANDLE f;
1768 /* fHidden=1 - only visible for the calling app, read-only, not
1769 * enumbered with EnumFonts/EnumFontFamilies
1770 * lpszCurrentPath can be NULL
1772 FIXME("(%ld,%s,%s,%s): stub\n",
1773 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1774 debugstr_a(lpszCurrentPath) );
1776 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1777 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1778 CloseHandle(f);
1779 SetLastError(ERROR_FILE_EXISTS);
1780 return FALSE;
1782 return FALSE; /* create failed */
1785 /***********************************************************************
1786 * CreateScalableFontResourceW (GDI32.@)
1788 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1789 LPCWSTR lpszResourceFile,
1790 LPCWSTR lpszFontFile,
1791 LPCWSTR lpszCurrentPath )
1793 FIXME("(%ld,%p,%p,%p): stub\n",
1794 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1795 return FALSE; /* create failed */
1799 /*************************************************************************
1800 * GetRasterizerCaps (GDI32.@)
1802 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1804 lprs->nSize = sizeof(RASTERIZER_STATUS);
1805 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1806 lprs->nLanguageID = 0;
1807 return TRUE;
1811 /*************************************************************************
1812 * GetKerningPairsA (GDI32.@)
1814 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1815 LPKERNINGPAIR lpKerningPairs )
1817 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1821 /*************************************************************************
1822 * GetKerningPairsW (GDI32.@)
1824 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1825 LPKERNINGPAIR lpKerningPairs )
1827 int i;
1828 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1829 for (i = 0; i < cPairs; i++)
1830 lpKerningPairs[i].iKernAmount = 0;
1831 return 0;
1834 /*************************************************************************
1835 * TranslateCharsetInfo [GDI32.@]
1837 * Fills a CHARSETINFO structure for a character set, code page, or
1838 * font. This allows making the correspondance between different labelings
1839 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1840 * of the same encoding.
1842 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1843 * only one codepage should be set in *lpSrc.
1845 * RETURNS
1846 * TRUE on success, FALSE on failure.
1849 BOOL WINAPI TranslateCharsetInfo(
1850 LPDWORD lpSrc, /* [in]
1851 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1852 if flags == TCI_SRCCHARSET: a character set value
1853 if flags == TCI_SRCCODEPAGE: a code page value
1855 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1856 DWORD flags /* [in] determines interpretation of lpSrc */)
1858 int index = 0;
1859 switch (flags) {
1860 case TCI_SRCFONTSIG:
1861 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1862 break;
1863 case TCI_SRCCODEPAGE:
1864 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1865 break;
1866 case TCI_SRCCHARSET:
1867 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1868 break;
1869 default:
1870 return FALSE;
1872 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1873 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1874 return TRUE;
1877 /*************************************************************************
1878 * GetFontLanguageInfo (GDI32.@)
1880 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1882 FONTSIGNATURE fontsig;
1883 static const DWORD GCP_DBCS_MASK=0x003F0000,
1884 GCP_DIACRITIC_MASK=0x00000000,
1885 FLI_GLYPHS_MASK=0x00000000,
1886 GCP_GLYPHSHAPE_MASK=0x00000040,
1887 GCP_KASHIDA_MASK=0x00000000,
1888 GCP_LIGATE_MASK=0x00000000,
1889 GCP_USEKERNING_MASK=0x00000000,
1890 GCP_REORDER_MASK=0x00000060;
1892 DWORD result=0;
1894 GetTextCharsetInfo( hdc, &fontsig, 0 );
1895 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1897 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1898 result|=GCP_DBCS;
1900 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1901 result|=GCP_DIACRITIC;
1903 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1904 result|=FLI_GLYPHS;
1906 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1907 result|=GCP_GLYPHSHAPE;
1909 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1910 result|=GCP_KASHIDA;
1912 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1913 result|=GCP_LIGATE;
1915 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1916 result|=GCP_USEKERNING;
1918 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1919 result|=GCP_REORDER;
1921 return result;
1925 /*************************************************************************
1926 * GetFontData [GDI32.@]
1928 * Retrieve data for TrueType font.
1930 * RETURNS
1932 * success: Number of bytes returned
1933 * failure: GDI_ERROR
1935 * NOTES
1937 * Calls SetLastError()
1940 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1941 LPVOID buffer, DWORD length)
1943 DC *dc = DC_GetDCPtr(hdc);
1944 DWORD ret = GDI_ERROR;
1946 if(!dc) return GDI_ERROR;
1948 if(dc->gdiFont)
1949 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1951 GDI_ReleaseObj(hdc);
1952 return ret;
1955 /*************************************************************************
1956 * GetGlyphIndicesA [GDI32.@]
1958 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1959 LPWORD pgi, DWORD flags)
1961 DWORD ret;
1962 WCHAR *lpstrW;
1963 INT countW;
1965 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1966 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1968 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1969 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1970 HeapFree(GetProcessHeap(), 0, lpstrW);
1972 return ret;
1975 /*************************************************************************
1976 * GetGlyphIndicesW [GDI32.@]
1978 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1979 LPWORD pgi, DWORD flags)
1981 DC *dc = DC_GetDCPtr(hdc);
1982 DWORD ret = GDI_ERROR;
1984 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1985 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1987 if(!dc) return GDI_ERROR;
1989 if(dc->gdiFont)
1990 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1992 GDI_ReleaseObj(hdc);
1993 return ret;
1996 /*************************************************************************
1997 * GetCharacterPlacementA [GDI32.@]
1999 * NOTES:
2000 * the web browser control of ie4 calls this with dwFlags=0
2002 DWORD WINAPI
2003 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2004 INT nMaxExtent, GCP_RESULTSA *lpResults,
2005 DWORD dwFlags)
2007 WCHAR *lpStringW;
2008 INT uCountW;
2009 GCP_RESULTSW resultsW;
2010 DWORD ret;
2011 UINT font_cp;
2013 TRACE("%s, %d, %d, 0x%08lx\n",
2014 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2016 /* both structs are equal in size */
2017 memcpy(&resultsW, lpResults, sizeof(resultsW));
2019 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2020 if(lpResults->lpOutString)
2021 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2023 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2025 if(lpResults->lpOutString) {
2026 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2027 lpResults->lpOutString, uCount, NULL, NULL );
2030 HeapFree(GetProcessHeap(), 0, lpStringW);
2031 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2033 return ret;
2036 /*************************************************************************
2037 * GetCharacterPlacementW [GDI32.@]
2039 * Retrieve information about a string. This includes the width, reordering,
2040 * Glyphing and so on.
2042 * RETURNS
2044 * The width and height of the string if successful, 0 if failed.
2046 * BUGS
2048 * All flags except GCP_REORDER are not yet implemented.
2049 * Reordering is not 100% complient to the Windows BiDi method.
2050 * Caret positioning is not yet implemented for BiDi.
2051 * Classes are not yet implemented.
2054 DWORD WINAPI
2055 GetCharacterPlacementW(
2056 HDC hdc, /* [in] Device context for which the rendering is to be done */
2057 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2058 INT uCount, /* [in] Number of WORDS in string. */
2059 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2060 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2061 DWORD dwFlags /* [in] Flags specifying how to process the string */
2064 DWORD ret=0;
2065 SIZE size;
2066 UINT i, nSet;
2068 TRACE("%s, %d, %d, 0x%08lx\n",
2069 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2071 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2072 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2073 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2074 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2075 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2077 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2078 if(lpResults->lpClass) FIXME("classes not implemented\n");
2079 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2080 FIXME("Caret positions for complex scripts not implemented\n");
2082 nSet = (UINT)uCount;
2083 if(nSet > lpResults->nGlyphs)
2084 nSet = lpResults->nGlyphs;
2086 /* return number of initialized fields */
2087 lpResults->nGlyphs = nSet;
2089 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2091 /* Treat the case where no special handling was requested in a fastpath way */
2092 /* copy will do if the GCP_REORDER flag is not set */
2093 if(lpResults->lpOutString)
2094 strncpyW( lpResults->lpOutString, lpString, nSet );
2096 if(lpResults->lpOrder)
2098 for(i = 0; i < nSet; i++)
2099 lpResults->lpOrder[i] = i;
2101 } else
2103 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2104 nSet, lpResults->lpOrder );
2107 /* FIXME: Will use the placement chars */
2108 if (lpResults->lpDx)
2110 int c;
2111 for (i = 0; i < nSet; i++)
2113 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2114 lpResults->lpDx[i]= c;
2118 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2120 int pos = 0;
2122 lpResults->lpCaretPos[0] = 0;
2123 for (i = 1; i < nSet; i++)
2124 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2125 lpResults->lpCaretPos[i] = (pos += size.cx);
2128 if(lpResults->lpGlyphs)
2129 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2131 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2132 ret = MAKELONG(size.cx, size.cy);
2134 return ret;
2137 /*************************************************************************
2138 * GetCharABCWidthsFloatA [GDI32.@]
2140 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2141 LPABCFLOAT lpABCF)
2143 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2144 return 0;
2147 /*************************************************************************
2148 * GetCharABCWidthsFloatW [GDI32.@]
2150 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2151 UINT iLastChar, LPABCFLOAT lpABCF)
2153 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2154 return 0;
2157 /*************************************************************************
2158 * GetCharWidthFloatA [GDI32.@]
2160 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2161 UINT iLastChar, PFLOAT pxBuffer)
2163 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2164 return 0;
2167 /*************************************************************************
2168 * GetCharWidthFloatW [GDI32.@]
2170 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2171 UINT iLastChar, PFLOAT pxBuffer)
2173 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2174 return 0;
2178 /***********************************************************************
2180 * Font Resource API *
2182 ***********************************************************************/
2184 /***********************************************************************
2185 * AddFontResourceA (GDI32.@)
2187 INT WINAPI AddFontResourceA( LPCSTR str )
2189 return AddFontResourceExA( str, 0, NULL);
2192 /***********************************************************************
2193 * AddFontResourceW (GDI32.@)
2195 INT WINAPI AddFontResourceW( LPCWSTR str )
2197 return AddFontResourceExW(str, 0, NULL);
2201 /***********************************************************************
2202 * AddFontResourceExA (GDI32.@)
2204 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2206 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2207 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2208 INT ret;
2210 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2211 ret = AddFontResourceExW(strW, fl, pdv);
2212 HeapFree(GetProcessHeap(), 0, strW);
2213 return ret;
2216 /***********************************************************************
2217 * AddFontResourceExW (GDI32.@)
2219 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2221 return WineEngAddFontResourceEx(str, fl, pdv);
2224 /***********************************************************************
2225 * RemoveFontResourceA (GDI32.@)
2227 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2229 return RemoveFontResourceExA(str, 0, 0);
2232 /***********************************************************************
2233 * RemoveFontResourceW (GDI32.@)
2235 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2237 return RemoveFontResourceExW(str, 0, 0);
2240 /***********************************************************************
2241 * RemoveFontResourceExA (GDI32.@)
2243 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2245 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2246 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2247 INT ret;
2249 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2250 ret = RemoveFontResourceExW(strW, fl, pdv);
2251 HeapFree(GetProcessHeap(), 0, strW);
2252 return ret;
2255 /***********************************************************************
2256 * RemoveFontResourceExW (GDI32.@)
2258 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2260 return WineEngRemoveFontResourceEx(str, fl, pdv);
2263 /***********************************************************************
2264 * GetTextCharset (GDI32.@)
2266 UINT WINAPI GetTextCharset(HDC hdc)
2268 /* MSDN docs say this is equivalent */
2269 return GetTextCharsetInfo(hdc, NULL, 0);
2272 /***********************************************************************
2273 * GetTextCharsetInfo (GDI32.@)
2275 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2277 UINT ret = DEFAULT_CHARSET;
2278 DC *dc = DC_GetDCPtr(hdc);
2280 if (!dc) goto done;
2282 if (dc->gdiFont)
2283 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2285 GDI_ReleaseObj(hdc);
2287 done:
2288 if (ret == DEFAULT_CHARSET && fs)
2289 memset(fs, 0, sizeof(FONTSIGNATURE));
2290 return ret;