Moved a bunch of definitions from gdi.h into a new gdi_private.h to
[wine/multimedia.git] / objects / font.c
blob78ecd4363bf6d905cd486b900b6494dcba2f31bd
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 );
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 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
574 DWORD fType, LPARAM lp )
576 fontEnum16 *pfe = (fontEnum16*)lp;
577 INT ret = 1;
578 DC *dc;
580 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
581 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
583 WORD args[7];
584 DWORD result;
586 FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
587 FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
588 pfe->dwFlags |= ENUM_CALLED;
589 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
591 args[6] = SELECTOROF(pfe->segLogFont);
592 args[5] = OFFSETOF(pfe->segLogFont);
593 args[4] = SELECTOROF(pfe->segTextMetric);
594 args[3] = OFFSETOF(pfe->segTextMetric);
595 args[2] = fType;
596 args[1] = HIWORD(pfe->lpData);
597 args[0] = LOWORD(pfe->lpData);
598 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
599 ret = LOWORD(result);
601 /* get the lock again and make sure the DC is still valid */
602 dc = DC_GetDCPtr( pfe->hdc );
603 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
605 if (dc) GDI_ReleaseObj( pfe->hdc );
606 pfe->hdc = 0; /* make sure we don't try to release it later on */
607 ret = 0;
610 return ret;
613 /***********************************************************************
614 * FONT_EnumInstance
616 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
617 DWORD fType, LPARAM lp )
619 fontEnum32 *pfe = (fontEnum32*)lp;
620 INT ret = 1;
621 DC *dc;
623 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
624 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
625 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
627 /* convert font metrics */
628 ENUMLOGFONTEXA logfont;
629 NEWTEXTMETRICEXA tmA;
631 pfe->dwFlags |= ENUM_CALLED;
632 if (!(pfe->dwFlags & ENUM_UNICODE))
634 FONT_EnumLogFontExWToA( plf, &logfont);
635 FONT_NewTextMetricExWToA( ptm, &tmA );
636 plf = (LPENUMLOGFONTEXW)&logfont;
637 ptm = (NEWTEXTMETRICEXW *)&tmA;
639 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
641 ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
643 /* get the lock again and make sure the DC is still valid */
644 dc = DC_GetDCPtr( pfe->hdc );
645 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
647 if (dc) GDI_ReleaseObj( pfe->hdc );
648 pfe->hdc = 0; /* make sure we don't try to release it later on */
649 ret = 0;
652 return ret;
655 /***********************************************************************
656 * EnumFontFamiliesEx (GDI.613)
658 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
659 FONTENUMPROC16 efproc, LPARAM lParam,
660 DWORD dwFlags)
662 fontEnum16 fe16;
663 INT16 ret = 1, ret2;
664 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
665 NEWTEXTMETRICEX16 tm16;
666 ENUMLOGFONTEX16 lf16;
667 LOGFONTW lfW;
668 BOOL enum_gdi_fonts;
670 if (!dc) return 0;
671 FONT_LogFont16ToW(plf, &lfW);
673 fe16.hdc = HDC_32(hDC);
674 fe16.dc = dc;
675 fe16.physDev = dc->physDev;
676 fe16.lpLogFontParam = plf;
677 fe16.lpEnumFunc = efproc;
678 fe16.lpData = lParam;
679 fe16.lpTextMetric = &tm16;
680 fe16.lpLogFont = &lf16;
681 fe16.segTextMetric = MapLS( &tm16 );
682 fe16.segLogFont = MapLS( &lf16 );
683 fe16.dwFlags = 0;
685 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
687 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
689 ret = 0;
690 goto done;
693 if (enum_gdi_fonts)
694 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
695 fe16.dwFlags &= ~ENUM_CALLED;
696 if (ret && dc->funcs->pEnumDeviceFonts) {
697 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
698 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
699 ret = ret2;
701 done:
702 UnMapLS( fe16.segTextMetric );
703 UnMapLS( fe16.segLogFont );
704 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
705 return ret;
708 /***********************************************************************
709 * FONT_EnumFontFamiliesEx
711 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
712 FONTENUMPROCW efproc,
713 LPARAM lParam, DWORD dwUnicode)
715 INT ret = 1, ret2;
716 DC *dc = DC_GetDCPtr( hDC );
717 fontEnum32 fe32;
718 BOOL enum_gdi_fonts;
720 if (!dc) return 0;
722 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
723 plf->lfCharSet);
724 fe32.lpLogFontParam = plf;
725 fe32.lpEnumFunc = efproc;
726 fe32.lpData = lParam;
727 fe32.dwFlags = dwUnicode;
728 fe32.hdc = hDC;
729 fe32.dc = dc;
730 fe32.physDev = dc->physDev;
732 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
734 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
736 ret = 0;
737 goto done;
740 if (enum_gdi_fonts)
741 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
742 fe32.dwFlags &= ~ENUM_CALLED;
743 if (ret && dc->funcs->pEnumDeviceFonts) {
744 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
745 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
746 ret = ret2;
748 done:
749 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
750 return ret;
753 /***********************************************************************
754 * EnumFontFamiliesExW (GDI32.@)
756 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
757 FONTENUMPROCW efproc,
758 LPARAM lParam, DWORD dwFlags )
760 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
763 /***********************************************************************
764 * EnumFontFamiliesExA (GDI32.@)
766 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
767 FONTENUMPROCA efproc,
768 LPARAM lParam, DWORD dwFlags)
770 LOGFONTW lfW;
771 FONT_LogFontAToW( plf, &lfW );
773 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
776 /***********************************************************************
777 * EnumFontFamilies (GDI.330)
779 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
780 FONTENUMPROC16 efproc, LPARAM lpData )
782 LOGFONT16 lf;
784 lf.lfCharSet = DEFAULT_CHARSET;
785 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
786 else lf.lfFaceName[0] = '\0';
788 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
791 /***********************************************************************
792 * EnumFontFamiliesA (GDI32.@)
794 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
795 FONTENUMPROCA efproc, LPARAM lpData )
797 LOGFONTA lf;
799 lf.lfCharSet = DEFAULT_CHARSET;
800 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
801 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
803 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
806 /***********************************************************************
807 * EnumFontFamiliesW (GDI32.@)
809 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
810 FONTENUMPROCW efproc, LPARAM lpData )
812 LOGFONTW lf;
814 lf.lfCharSet = DEFAULT_CHARSET;
815 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
816 else lf.lfFaceName[0] = 0;
818 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
821 /***********************************************************************
822 * EnumFonts (GDI.70)
824 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
825 LPARAM lpData )
827 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
830 /***********************************************************************
831 * EnumFontsA (GDI32.@)
833 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
834 LPARAM lpData )
836 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
839 /***********************************************************************
840 * EnumFontsW (GDI32.@)
842 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
843 LPARAM lpData )
845 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
849 /***********************************************************************
850 * GetTextCharacterExtra (GDI32.@)
852 INT WINAPI GetTextCharacterExtra( HDC hdc )
854 INT ret;
855 DC *dc = DC_GetDCPtr( hdc );
856 if (!dc) return 0x80000000;
857 ret = dc->charExtra;
858 GDI_ReleaseObj( hdc );
859 return ret;
863 /***********************************************************************
864 * SetTextCharacterExtra (GDI32.@)
866 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
868 INT prev;
869 DC * dc = DC_GetDCPtr( hdc );
870 if (!dc) return 0x80000000;
871 if (dc->funcs->pSetTextCharacterExtra)
872 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
873 else
875 prev = dc->charExtra;
876 dc->charExtra = extra;
878 GDI_ReleaseObj( hdc );
879 return prev;
883 /***********************************************************************
884 * SetTextJustification (GDI32.@)
886 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
888 BOOL ret = TRUE;
889 DC * dc = DC_GetDCPtr( hdc );
890 if (!dc) return FALSE;
891 if (dc->funcs->pSetTextJustification)
892 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
893 else
895 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
896 if (!extra) breaks = 0;
897 dc->breakTotalExtra = extra;
898 dc->breakCount = breaks;
899 if (breaks)
901 dc->breakExtra = extra / breaks;
902 dc->breakRem = extra - (dc->breakCount * dc->breakExtra);
904 else
906 dc->breakExtra = 0;
907 dc->breakRem = 0;
910 GDI_ReleaseObj( hdc );
911 return ret;
915 /***********************************************************************
916 * GetTextFaceA (GDI32.@)
918 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
920 INT res = GetTextFaceW(hdc, 0, NULL);
921 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
922 GetTextFaceW( hdc, res, nameW );
924 if (name)
926 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
927 name[count-1] = 0;
928 res = strlen(name);
930 else
931 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
932 HeapFree( GetProcessHeap(), 0, nameW );
933 return res;
936 /***********************************************************************
937 * GetTextFaceW (GDI32.@)
939 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
941 FONTOBJ *font;
942 INT ret = 0;
944 DC * dc = DC_GetDCPtr( hdc );
945 if (!dc) return 0;
947 if(dc->gdiFont)
948 ret = WineEngGetTextFace(dc->gdiFont, count, name);
949 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
951 if (name)
953 lstrcpynW( name, font->logfont.lfFaceName, count );
954 ret = strlenW(name);
956 else ret = strlenW(font->logfont.lfFaceName) + 1;
957 GDI_ReleaseObj( dc->hFont );
959 GDI_ReleaseObj( hdc );
960 return ret;
964 /***********************************************************************
965 * GetTextExtentPoint32A (GDI32.@)
967 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
968 LPSIZE size )
970 BOOL ret = FALSE;
971 INT wlen;
972 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
974 if (p) {
975 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
976 HeapFree( GetProcessHeap(), 0, p );
979 TRACE("(%p %s %d %p): returning %ld x %ld\n",
980 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
981 return ret;
985 /***********************************************************************
986 * GetTextExtentPoint32W [GDI32.@] Computes width/height for a string
988 * Computes width and height of the specified string.
990 * RETURNS
991 * Success: TRUE
992 * Failure: FALSE
994 BOOL WINAPI GetTextExtentPoint32W(
995 HDC hdc, /* [in] Handle of device context */
996 LPCWSTR str, /* [in] Address of text string */
997 INT count, /* [in] Number of characters in string */
998 LPSIZE size) /* [out] Address of structure for string size */
1000 BOOL ret = FALSE;
1001 DC * dc = DC_GetDCPtr( hdc );
1002 if (!dc) return FALSE;
1004 if(dc->gdiFont) {
1005 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1006 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1007 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1008 size->cx += count * dc->charExtra;
1010 else if(dc->funcs->pGetTextExtentPoint)
1011 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1013 GDI_ReleaseObj( hdc );
1015 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1016 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1017 return ret;
1020 /***********************************************************************
1021 * GetTextExtentPointI [GDI32.@]
1023 * Computes width and height of the array of glyph indices.
1025 * RETURNS
1026 * Success: TRUE
1027 * Failure: FALSE
1029 BOOL WINAPI GetTextExtentPointI(
1030 HDC hdc, /* [in] Handle of device context */
1031 const WORD *indices, /* [in] Address of glyph index array */
1032 INT count, /* [in] Number of glyphs in array */
1033 LPSIZE size) /* [out] Address of structure for string size */
1035 BOOL ret = FALSE;
1036 DC * dc = DC_GetDCPtr( hdc );
1037 if (!dc) return FALSE;
1039 if(dc->gdiFont) {
1040 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1041 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1042 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1043 size->cx += count * dc->charExtra;
1045 else if(dc->funcs->pGetTextExtentPoint) {
1046 FIXME("calling GetTextExtentPoint\n");
1047 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1050 GDI_ReleaseObj( hdc );
1052 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1053 hdc, indices, count, size, size->cx, size->cy );
1054 return ret;
1058 /***********************************************************************
1059 * GetTextExtentPointA (GDI32.@)
1061 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1062 LPSIZE size )
1064 TRACE("not bug compatible.\n");
1065 return GetTextExtentPoint32A( hdc, str, count, size );
1068 /***********************************************************************
1069 * GetTextExtentPointW (GDI32.@)
1071 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1072 LPSIZE size )
1074 TRACE("not bug compatible.\n");
1075 return GetTextExtentPoint32W( hdc, str, count, size );
1079 /***********************************************************************
1080 * GetTextExtentExPointA (GDI32.@)
1082 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1083 INT maxExt, LPINT lpnFit,
1084 LPINT alpDx, LPSIZE size )
1086 BOOL ret;
1087 INT wlen;
1088 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1089 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1090 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1091 HeapFree( GetProcessHeap(), 0, p );
1092 return ret;
1096 /***********************************************************************
1097 * GetTextExtentExPointW (GDI32.@)
1099 * Return the size of the string as it would be if it was output properly by
1100 * e.g. TextOut.
1102 * This should include
1103 * - Intercharacter spacing
1104 * - justification spacing (not yet done)
1105 * - kerning? see below
1107 * Kerning. Since kerning would be carried out by the rendering code it should
1108 * be done by the driver. However they don't support it yet. Also I am not
1109 * yet persuaded that (certainly under Win95) any kerning is actually done.
1111 * str: According to MSDN this should be null-terminated. That is not true; a
1112 * null will not terminate it early.
1113 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1114 * than count. I have seen it be either the size of the full string or
1115 * 1 less than the size of the full string. I have not seen it bear any
1116 * resemblance to the portion that would fit.
1117 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1118 * trailing intercharacter spacing and any trailing justification.
1120 * FIXME
1121 * Currently we do this by measuring each character etc. We should do it by
1122 * passing the request to the driver, perhaps by extending the
1123 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1124 * thinking about kerning issues and rounding issues in the justification.
1127 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1128 INT maxExt, LPINT lpnFit,
1129 LPINT alpDx, LPSIZE size )
1131 int index, nFit, extent;
1132 SIZE tSize;
1133 BOOL ret = FALSE;
1135 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1137 size->cx = size->cy = nFit = extent = 0;
1138 for(index = 0; index < count; index++)
1140 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1141 /* GetTextExtentPoint includes intercharacter spacing. */
1142 /* FIXME - justification needs doing yet. Remember that the base
1143 * data will not be in logical coordinates.
1145 extent += tSize.cx;
1146 if( !lpnFit || extent <= maxExt )
1147 /* It is allowed to be equal. */
1149 nFit++;
1150 if( alpDx ) alpDx[index] = extent;
1152 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1153 str++;
1155 size->cx = extent;
1156 if(lpnFit) *lpnFit = nFit;
1157 ret = TRUE;
1159 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1161 done:
1162 return ret;
1165 /***********************************************************************
1166 * GetTextMetricsA (GDI32.@)
1168 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1170 TEXTMETRICW tm32;
1172 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1173 FONT_TextMetricWToA( &tm32, metrics );
1174 return TRUE;
1177 /***********************************************************************
1178 * GetTextMetricsW (GDI32.@)
1180 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1182 BOOL ret = FALSE;
1183 DC * dc = DC_GetDCPtr( hdc );
1184 if (!dc) return FALSE;
1186 if (dc->gdiFont)
1187 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1188 else if (dc->funcs->pGetTextMetrics)
1189 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1191 if (ret)
1193 /* device layer returns values in device units
1194 * therefore we have to convert them to logical */
1196 #define WDPTOLP(x) ((x<0)? \
1197 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1198 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1199 #define HDPTOLP(y) ((y<0)? \
1200 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1201 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1203 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1204 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1205 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1206 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1207 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1208 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1209 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1210 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1211 ret = TRUE;
1212 #undef WDPTOLP
1213 #undef HDPTOLP
1214 TRACE("text metrics:\n"
1215 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1216 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1217 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1218 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1219 " PitchAndFamily = %02x\n"
1220 " --------------------\n"
1221 " InternalLeading = %li\n"
1222 " Ascent = %li\n"
1223 " Descent = %li\n"
1224 " Height = %li\n",
1225 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1226 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1227 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1228 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1229 metrics->tmPitchAndFamily,
1230 metrics->tmInternalLeading,
1231 metrics->tmAscent,
1232 metrics->tmDescent,
1233 metrics->tmHeight );
1235 GDI_ReleaseObj( hdc );
1236 return ret;
1240 /***********************************************************************
1241 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1243 * NOTES
1244 * lpOTM should be LPOUTLINETEXTMETRIC
1246 * RETURNS
1247 * Success: Non-zero or size of required buffer
1248 * Failure: 0
1250 UINT16 WINAPI GetOutlineTextMetrics16(
1251 HDC16 hdc, /* [in] Handle of device context */
1252 UINT16 cbData, /* [in] Size of metric data array */
1253 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1255 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1256 return 0;
1260 /***********************************************************************
1261 * GetOutlineTextMetricsA (GDI32.@)
1262 * Gets metrics for TrueType fonts.
1264 * NOTES
1265 * If the supplied buffer isn't big enough Windows partially fills it up to
1266 * its given length and returns that length.
1268 * RETURNS
1269 * Success: Non-zero or size of required buffer
1270 * Failure: 0
1272 UINT WINAPI GetOutlineTextMetricsA(
1273 HDC hdc, /* [in] Handle of device context */
1274 UINT cbData, /* [in] Size of metric data array */
1275 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1277 char buf[512], *ptr;
1278 UINT ret, needed;
1279 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1280 OUTLINETEXTMETRICA *output = lpOTM;
1281 INT left, len;
1283 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1284 return 0;
1285 if(ret > sizeof(buf))
1286 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1287 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1289 needed = sizeof(OUTLINETEXTMETRICA);
1290 if(lpOTMW->otmpFamilyName)
1291 needed += WideCharToMultiByte(CP_ACP, 0,
1292 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1293 NULL, 0, NULL, NULL);
1294 if(lpOTMW->otmpFaceName)
1295 needed += WideCharToMultiByte(CP_ACP, 0,
1296 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1297 NULL, 0, NULL, NULL);
1298 if(lpOTMW->otmpStyleName)
1299 needed += WideCharToMultiByte(CP_ACP, 0,
1300 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1301 NULL, 0, NULL, NULL);
1302 if(lpOTMW->otmpFullName)
1303 needed += WideCharToMultiByte(CP_ACP, 0,
1304 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1305 NULL, 0, NULL, NULL);
1307 if(!lpOTM) {
1308 ret = needed;
1309 goto end;
1312 TRACE("needed = %d\n", needed);
1313 if(needed > cbData)
1314 /* Since the supplied buffer isn't big enough, we'll alloc one
1315 that is and memcpy the first cbData bytes into the lpOTM at
1316 the end. */
1317 output = HeapAlloc(GetProcessHeap(), 0, needed);
1319 ret = output->otmSize = min(needed, cbData);
1320 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1321 output->otmFiller = 0;
1322 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1323 output->otmfsSelection = lpOTMW->otmfsSelection;
1324 output->otmfsType = lpOTMW->otmfsType;
1325 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1326 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1327 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1328 output->otmEMSquare = lpOTMW->otmEMSquare;
1329 output->otmAscent = lpOTMW->otmAscent;
1330 output->otmDescent = lpOTMW->otmDescent;
1331 output->otmLineGap = lpOTMW->otmLineGap;
1332 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1333 output->otmsXHeight = lpOTMW->otmsXHeight;
1334 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1335 output->otmMacAscent = lpOTMW->otmMacAscent;
1336 output->otmMacDescent = lpOTMW->otmMacDescent;
1337 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1338 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1339 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1340 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1341 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1342 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1343 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1344 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1345 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1346 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1349 ptr = (char*)(output + 1);
1350 left = needed - sizeof(*output);
1352 if(lpOTMW->otmpFamilyName) {
1353 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1354 len = WideCharToMultiByte(CP_ACP, 0,
1355 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1356 ptr, left, NULL, NULL);
1357 left -= len;
1358 ptr += len;
1359 } else
1360 output->otmpFamilyName = 0;
1362 if(lpOTMW->otmpFaceName) {
1363 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1364 len = WideCharToMultiByte(CP_ACP, 0,
1365 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1366 ptr, left, NULL, NULL);
1367 left -= len;
1368 ptr += len;
1369 } else
1370 output->otmpFaceName = 0;
1372 if(lpOTMW->otmpStyleName) {
1373 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1374 len = WideCharToMultiByte(CP_ACP, 0,
1375 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1376 ptr, left, NULL, NULL);
1377 left -= len;
1378 ptr += len;
1379 } else
1380 output->otmpStyleName = 0;
1382 if(lpOTMW->otmpFullName) {
1383 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1384 len = WideCharToMultiByte(CP_ACP, 0,
1385 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1386 ptr, left, NULL, NULL);
1387 left -= len;
1388 } else
1389 output->otmpFullName = 0;
1391 assert(left == 0);
1393 if(output != lpOTM) {
1394 memcpy(lpOTM, output, cbData);
1395 HeapFree(GetProcessHeap(), 0, output);
1398 end:
1399 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1400 HeapFree(GetProcessHeap(), 0, lpOTMW);
1402 return ret;
1406 /***********************************************************************
1407 * GetOutlineTextMetricsW [GDI32.@]
1409 UINT WINAPI GetOutlineTextMetricsW(
1410 HDC hdc, /* [in] Handle of device context */
1411 UINT cbData, /* [in] Size of metric data array */
1412 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1414 DC *dc = DC_GetDCPtr( hdc );
1415 OUTLINETEXTMETRICW *output = lpOTM;
1416 UINT ret;
1418 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1419 if(!dc) return 0;
1421 if(dc->gdiFont) {
1422 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1423 if(lpOTM && ret) {
1424 if(ret > cbData) {
1425 output = HeapAlloc(GetProcessHeap(), 0, ret);
1426 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1429 #define WDPTOLP(x) ((x<0)? \
1430 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1431 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1432 #define HDPTOLP(y) ((y<0)? \
1433 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1434 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1436 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1437 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1438 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1439 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1440 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1441 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1442 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1443 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1444 output->otmAscent = HDPTOLP(output->otmAscent);
1445 output->otmDescent = HDPTOLP(output->otmDescent);
1446 output->otmLineGap = HDPTOLP(output->otmLineGap);
1447 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1448 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1449 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1450 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1451 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1452 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1453 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1454 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1455 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1456 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1457 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1458 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1459 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1460 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1461 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1462 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1463 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1464 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1465 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1466 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1467 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1468 #undef WDPTOLP
1469 #undef HDPTOLP
1470 if(output != lpOTM) {
1471 memcpy(lpOTM, output, cbData);
1472 HeapFree(GetProcessHeap(), 0, output);
1473 ret = cbData;
1478 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1479 but really this should just be a return 0. */
1481 ret = sizeof(*lpOTM);
1482 if (lpOTM) {
1483 if(cbData < ret)
1484 ret = 0;
1485 else {
1486 memset(lpOTM, 0, ret);
1487 lpOTM->otmSize = sizeof(*lpOTM);
1488 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1490 Further fill of the structure not implemented,
1491 Needs real values for the structure members
1496 GDI_ReleaseObj(hdc);
1497 return ret;
1501 /***********************************************************************
1502 * GetCharWidthW (GDI32.@)
1503 * GetCharWidth32W (GDI32.@)
1505 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1506 LPINT buffer )
1508 UINT i;
1509 BOOL ret = FALSE;
1510 DC * dc = DC_GetDCPtr( hdc );
1511 if (!dc) return FALSE;
1513 if (dc->gdiFont)
1514 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1515 else if (dc->funcs->pGetCharWidth)
1516 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1518 if (ret)
1520 /* convert device units to logical */
1521 for( i = firstChar; i <= lastChar; i++, buffer++ )
1522 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1523 ret = TRUE;
1525 GDI_ReleaseObj( hdc );
1526 return ret;
1530 /***********************************************************************
1531 * GetCharWidthA (GDI32.@)
1532 * GetCharWidth32A (GDI32.@)
1534 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1535 LPINT buffer )
1537 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1538 LPSTR str;
1539 LPWSTR wstr;
1540 BOOL ret = TRUE;
1542 if(count <= 0) return FALSE;
1544 str = HeapAlloc(GetProcessHeap(), 0, count);
1545 for(i = 0; i < count; i++)
1546 str[i] = (BYTE)(firstChar + i);
1548 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1550 for(i = 0; i < wlen; i++)
1552 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1554 ret = FALSE;
1555 break;
1557 buffer++;
1560 HeapFree(GetProcessHeap(), 0, str);
1561 HeapFree(GetProcessHeap(), 0, wstr);
1563 return ret;
1567 /* FIXME: all following APIs ******************************************/
1570 /***********************************************************************
1571 * SetMapperFlags (GDI32.@)
1573 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1575 DC *dc = DC_GetDCPtr( hDC );
1576 DWORD ret = 0;
1577 if(!dc) return 0;
1578 if(dc->funcs->pSetMapperFlags)
1579 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1580 else
1581 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1582 GDI_ReleaseObj( hDC );
1583 return ret;
1586 /***********************************************************************
1587 * GetAspectRatioFilterEx (GDI.486)
1589 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1591 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1592 return FALSE;
1595 /***********************************************************************
1596 * GetAspectRatioFilterEx (GDI32.@)
1598 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1600 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1601 return FALSE;
1605 /***********************************************************************
1606 * GetCharABCWidthsA (GDI32.@)
1608 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1609 LPABC abc )
1611 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1612 LPSTR str;
1613 LPWSTR wstr;
1614 BOOL ret = TRUE;
1616 if(count <= 0) return FALSE;
1618 str = HeapAlloc(GetProcessHeap(), 0, count);
1619 for(i = 0; i < count; i++)
1620 str[i] = (BYTE)(firstChar + i);
1622 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1624 for(i = 0; i < wlen; i++)
1626 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1628 ret = FALSE;
1629 break;
1631 abc++;
1634 HeapFree(GetProcessHeap(), 0, str);
1635 HeapFree(GetProcessHeap(), 0, wstr);
1637 return ret;
1641 /******************************************************************************
1642 * GetCharABCWidthsW [GDI32.@] Retrieves widths of characters in range
1644 * PARAMS
1645 * hdc [I] Handle of device context
1646 * firstChar [I] First character in range to query
1647 * lastChar [I] Last character in range to query
1648 * abc [O] Address of character-width structure
1650 * NOTES
1651 * Only works with TrueType fonts
1653 * RETURNS
1654 * Success: TRUE
1655 * Failure: FALSE
1657 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1658 LPABC abc )
1660 DC *dc = DC_GetDCPtr(hdc);
1661 int i;
1662 GLYPHMETRICS gm;
1663 BOOL ret = FALSE;
1665 if(dc->gdiFont) {
1666 for (i=firstChar;i<=lastChar;i++) {
1667 GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1668 abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1669 abc[i-firstChar].abcB = gm.gmBlackBoxX;
1670 abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1672 ret = TRUE;
1674 GDI_ReleaseObj(hdc);
1675 return ret;
1679 /***********************************************************************
1680 * GetGlyphOutline (GDI.309)
1682 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1683 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1684 LPVOID lpBuffer, const MAT2 *lpmat2 )
1686 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1687 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1688 return (DWORD)-1; /* failure */
1692 /***********************************************************************
1693 * GetGlyphOutlineA (GDI32.@)
1695 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1696 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1697 LPVOID lpBuffer, const MAT2 *lpmat2 )
1699 LPWSTR p = NULL;
1700 DWORD ret;
1701 UINT c;
1703 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1704 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1705 c = p[0];
1706 } else
1707 c = uChar;
1708 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1709 lpmat2);
1710 if(p)
1711 HeapFree(GetProcessHeap(), 0, p);
1712 return ret;
1715 /***********************************************************************
1716 * GetGlyphOutlineW (GDI32.@)
1718 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1719 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1720 LPVOID lpBuffer, const MAT2 *lpmat2 )
1722 DC *dc = DC_GetDCPtr(hdc);
1723 DWORD ret;
1725 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1726 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1728 if(!dc) return GDI_ERROR;
1730 if(dc->gdiFont)
1731 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1732 cbBuffer, lpBuffer, lpmat2);
1733 else
1734 ret = GDI_ERROR;
1736 GDI_ReleaseObj(hdc);
1737 return ret;
1741 /***********************************************************************
1742 * CreateScalableFontResourceA (GDI32.@)
1744 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1745 LPCSTR lpszResourceFile,
1746 LPCSTR lpszFontFile,
1747 LPCSTR lpszCurrentPath )
1749 HANDLE f;
1751 /* fHidden=1 - only visible for the calling app, read-only, not
1752 * enumbered with EnumFonts/EnumFontFamilies
1753 * lpszCurrentPath can be NULL
1755 FIXME("(%ld,%s,%s,%s): stub\n",
1756 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1757 debugstr_a(lpszCurrentPath) );
1759 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1760 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1761 CloseHandle(f);
1762 SetLastError(ERROR_FILE_EXISTS);
1763 return FALSE;
1765 return FALSE; /* create failed */
1768 /***********************************************************************
1769 * CreateScalableFontResourceW (GDI32.@)
1771 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1772 LPCWSTR lpszResourceFile,
1773 LPCWSTR lpszFontFile,
1774 LPCWSTR lpszCurrentPath )
1776 FIXME("(%ld,%p,%p,%p): stub\n",
1777 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1778 return FALSE; /* create failed */
1782 /*************************************************************************
1783 * GetRasterizerCaps (GDI32.@)
1785 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1787 lprs->nSize = sizeof(RASTERIZER_STATUS);
1788 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1789 lprs->nLanguageID = 0;
1790 return TRUE;
1794 /*************************************************************************
1795 * GetKerningPairsA (GDI32.@)
1797 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1798 LPKERNINGPAIR lpKerningPairs )
1800 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1804 /*************************************************************************
1805 * GetKerningPairsW (GDI32.@)
1807 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1808 LPKERNINGPAIR lpKerningPairs )
1810 int i;
1811 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1812 for (i = 0; i < cPairs; i++)
1813 lpKerningPairs[i].iKernAmount = 0;
1814 return 0;
1817 /*************************************************************************
1818 * TranslateCharsetInfo [GDI32.@]
1820 * Fills a CHARSETINFO structure for a character set, code page, or
1821 * font. This allows making the correspondance between different labelings
1822 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1823 * of the same encoding.
1825 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1826 * only one codepage should be set in *lpSrc.
1828 * RETURNS
1829 * TRUE on success, FALSE on failure.
1832 BOOL WINAPI TranslateCharsetInfo(
1833 LPDWORD lpSrc, /* [in]
1834 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1835 if flags == TCI_SRCCHARSET: a character set value
1836 if flags == TCI_SRCCODEPAGE: a code page value
1838 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1839 DWORD flags /* [in] determines interpretation of lpSrc */
1841 int index = 0;
1842 switch (flags) {
1843 case TCI_SRCFONTSIG:
1844 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1845 break;
1846 case TCI_SRCCODEPAGE:
1847 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1848 break;
1849 case TCI_SRCCHARSET:
1850 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1851 break;
1852 default:
1853 return FALSE;
1855 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1856 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1857 return TRUE;
1860 /*************************************************************************
1861 * GetFontLanguageInfo (GDI32.@)
1863 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1865 FONTSIGNATURE fontsig;
1866 static const DWORD GCP_DBCS_MASK=0x003F0000,
1867 GCP_DIACRITIC_MASK=0x00000000,
1868 FLI_GLYPHS_MASK=0x00000000,
1869 GCP_GLYPHSHAPE_MASK=0x00000040,
1870 GCP_KASHIDA_MASK=0x00000000,
1871 GCP_LIGATE_MASK=0x00000000,
1872 GCP_USEKERNING_MASK=0x00000000,
1873 GCP_REORDER_MASK=0x00000060;
1875 DWORD result=0;
1877 GetTextCharsetInfo( hdc, &fontsig, 0 );
1878 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1880 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1881 result|=GCP_DBCS;
1883 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1884 result|=GCP_DIACRITIC;
1886 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1887 result|=FLI_GLYPHS;
1889 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1890 result|=GCP_GLYPHSHAPE;
1892 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1893 result|=GCP_KASHIDA;
1895 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1896 result|=GCP_LIGATE;
1898 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1899 result|=GCP_USEKERNING;
1901 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1902 result|=GCP_REORDER;
1904 return result;
1908 /*************************************************************************
1909 * GetFontData [GDI32.@] Retrieve data for TrueType font
1911 * RETURNS
1913 * success: Number of bytes returned
1914 * failure: GDI_ERROR
1916 * NOTES
1918 * Calls SetLastError()
1921 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1922 LPVOID buffer, DWORD length)
1924 DC *dc = DC_GetDCPtr(hdc);
1925 DWORD ret = GDI_ERROR;
1927 if(!dc) return GDI_ERROR;
1929 if(dc->gdiFont)
1930 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1932 GDI_ReleaseObj(hdc);
1933 return ret;
1936 /*************************************************************************
1937 * GetGlyphIndicesA [GDI32.@]
1939 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1940 LPWORD pgi, DWORD flags)
1942 DWORD ret;
1943 WCHAR *lpstrW;
1944 INT countW;
1946 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1947 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1949 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1950 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1951 HeapFree(GetProcessHeap(), 0, lpstrW);
1953 return ret;
1956 /*************************************************************************
1957 * GetGlyphIndicesW [GDI32.@]
1959 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1960 LPWORD pgi, DWORD flags)
1962 DC *dc = DC_GetDCPtr(hdc);
1963 DWORD ret = GDI_ERROR;
1965 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1966 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1968 if(!dc) return GDI_ERROR;
1970 if(dc->gdiFont)
1971 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1973 GDI_ReleaseObj(hdc);
1974 return ret;
1977 /*************************************************************************
1978 * GetCharacterPlacementA [GDI32.@]
1980 * NOTES:
1981 * the web browser control of ie4 calls this with dwFlags=0
1983 DWORD WINAPI
1984 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1985 INT nMaxExtent, GCP_RESULTSA *lpResults,
1986 DWORD dwFlags)
1988 WCHAR *lpStringW;
1989 INT uCountW, i;
1990 GCP_RESULTSW resultsW;
1991 DWORD ret;
1992 UINT font_cp;
1994 TRACE("%s, %d, %d, 0x%08lx\n",
1995 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1997 /* both structs are equal in size */
1998 memcpy(&resultsW, lpResults, sizeof(resultsW));
2000 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2001 if(lpResults->lpOutString)
2002 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2004 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2006 if(lpResults->lpOutString) {
2007 if(font_cp != CP_SYMBOL)
2008 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2009 lpResults->lpOutString, uCount, NULL, NULL );
2010 else
2011 for(i = 0; i < uCount; i++)
2012 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
2015 HeapFree(GetProcessHeap(), 0, lpStringW);
2016 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2018 return ret;
2021 /*************************************************************************
2022 * GetCharacterPlacementW [GDI32.@]
2024 * Retrieve information about a string. This includes the width, reordering,
2025 * Glyphing and so on.
2027 * RETURNS
2029 * The width and height of the string if successful, 0 if failed.
2031 * BUGS
2033 * All flags except GCP_REORDER are not yet implemented.
2034 * Reordering is not 100% complient to the Windows BiDi method.
2035 * Caret positioning is not yet implemented for BiDi.
2036 * Classes are not yet implemented.
2039 DWORD WINAPI
2040 GetCharacterPlacementW(
2041 HDC hdc, /* [in] Device context for which the rendering is to be done */
2042 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2043 INT uCount, /* [in] Number of WORDS in string. */
2044 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2045 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2046 DWORD dwFlags /* [in] Flags specifying how to process the string */
2049 DWORD ret=0;
2050 SIZE size;
2051 UINT i, nSet;
2053 TRACE("%s, %d, %d, 0x%08lx\n",
2054 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2056 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2057 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2058 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2059 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2060 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2062 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2063 if(lpResults->lpClass) FIXME("classes not implemented\n");
2064 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2065 FIXME("Caret positions for complex scripts not implemented\n");
2067 nSet = (UINT)uCount;
2068 if(nSet > lpResults->nGlyphs)
2069 nSet = lpResults->nGlyphs;
2071 /* return number of initialized fields */
2072 lpResults->nGlyphs = nSet;
2074 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2076 /* Treat the case where no special handling was requested in a fastpath way */
2077 /* copy will do if the GCP_REORDER flag is not set */
2078 if(lpResults->lpOutString)
2079 strncpyW( lpResults->lpOutString, lpString, nSet );
2081 if(lpResults->lpOrder)
2083 for(i = 0; i < nSet; i++)
2084 lpResults->lpOrder[i] = i;
2086 } else
2088 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2089 nSet, lpResults->lpOrder );
2092 /* FIXME: Will use the placement chars */
2093 if (lpResults->lpDx)
2095 int c;
2096 for (i = 0; i < nSet; i++)
2098 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2099 lpResults->lpDx[i]= c;
2103 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2105 int pos = 0;
2107 lpResults->lpCaretPos[0] = 0;
2108 for (i = 1; i < nSet; i++)
2109 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2110 lpResults->lpCaretPos[i] = (pos += size.cx);
2113 if(lpResults->lpGlyphs)
2114 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2116 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2117 ret = MAKELONG(size.cx, size.cy);
2119 return ret;
2122 /*************************************************************************
2123 * GetCharABCWidthsFloatA [GDI32.@]
2125 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2126 LPABCFLOAT lpABCF)
2128 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2129 return 0;
2132 /*************************************************************************
2133 * GetCharABCWidthsFloatW [GDI32.@]
2135 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2136 UINT iLastChar, LPABCFLOAT lpABCF)
2138 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2139 return 0;
2142 /*************************************************************************
2143 * GetCharWidthFloatA [GDI32.@]
2145 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2146 UINT iLastChar, PFLOAT pxBuffer)
2148 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2149 return 0;
2152 /*************************************************************************
2153 * GetCharWidthFloatW [GDI32.@]
2155 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2156 UINT iLastChar, PFLOAT pxBuffer)
2158 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2159 return 0;
2163 /***********************************************************************
2165 * Font Resource API *
2167 ***********************************************************************/
2169 /***********************************************************************
2170 * AddFontResourceA (GDI32.@)
2172 INT WINAPI AddFontResourceA( LPCSTR str )
2174 return AddFontResourceExA( str, 0, NULL);
2177 /***********************************************************************
2178 * AddFontResourceW (GDI32.@)
2180 INT WINAPI AddFontResourceW( LPCWSTR str )
2182 return AddFontResourceExW(str, 0, NULL);
2186 /***********************************************************************
2187 * AddFontResourceExA (GDI32.@)
2189 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2191 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2192 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2193 INT ret;
2195 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2196 ret = AddFontResourceExW(strW, fl, pdv);
2197 HeapFree(GetProcessHeap(), 0, strW);
2198 return ret;
2201 /***********************************************************************
2202 * AddFontResourceExW (GDI32.@)
2204 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2206 return WineEngAddFontResourceEx(str, fl, pdv);
2209 /***********************************************************************
2210 * RemoveFontResourceA (GDI32.@)
2212 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2214 return RemoveFontResourceExA(str, 0, 0);
2217 /***********************************************************************
2218 * RemoveFontResourceW (GDI32.@)
2220 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2222 return RemoveFontResourceExW(str, 0, 0);
2225 /***********************************************************************
2226 * RemoveFontResourceExA (GDI32.@)
2228 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2230 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2231 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2232 INT ret;
2234 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2235 ret = RemoveFontResourceExW(strW, fl, pdv);
2236 HeapFree(GetProcessHeap(), 0, strW);
2237 return ret;
2240 /***********************************************************************
2241 * RemoveFontResourceExW (GDI32.@)
2243 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2245 return WineEngRemoveFontResourceEx(str, fl, pdv);
2248 /***********************************************************************
2249 * GetTextCharset (GDI32.@)
2251 UINT WINAPI GetTextCharset(HDC hdc)
2253 /* MSDN docs say this is equivalent */
2254 return GetTextCharsetInfo(hdc, NULL, 0);
2257 /***********************************************************************
2258 * GetTextCharsetInfo (GDI32.@)
2260 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2262 UINT ret = DEFAULT_CHARSET;
2263 DC *dc = DC_GetDCPtr(hdc);
2265 if (!dc) goto done;
2267 if (dc->gdiFont)
2268 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2270 GDI_ReleaseObj(hdc);
2272 done:
2273 if (ret == DEFAULT_CHARSET && fs)
2274 memset(fs, 0, sizeof(FONTSIGNATURE));
2275 return ret;