Fixed Extract prototype.
[wine.git] / objects / font.c
blobd52fe95ac47753ab70103a63a9e37e8a69dc4b35
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) &&
632 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
634 /* convert font metrics */
635 ENUMLOGFONTEXA logfont;
636 NEWTEXTMETRICEXA tmA;
638 pfe->dwFlags |= ENUM_CALLED;
639 if (!(pfe->dwFlags & ENUM_UNICODE))
641 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
642 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
643 plf = (LOGFONTW *)&logfont.elfLogFont;
644 ptm = (TEXTMETRICW *)&tmA;
646 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
648 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
650 /* get the lock again and make sure the DC is still valid */
651 dc = DC_GetDCPtr( pfe->hdc );
652 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
654 if (dc) GDI_ReleaseObj( pfe->hdc );
655 pfe->hdc = 0; /* make sure we don't try to release it later on */
656 ret = 0;
659 return ret;
662 /***********************************************************************
663 * EnumFontFamiliesEx (GDI.613)
665 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
666 FONTENUMPROC16 efproc, LPARAM lParam,
667 DWORD dwFlags)
669 fontEnum16 fe16;
670 INT16 ret = 1, ret2;
671 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
672 NEWTEXTMETRICEX16 tm16;
673 ENUMLOGFONTEX16 lf16;
674 LOGFONTW lfW;
675 BOOL enum_gdi_fonts;
677 if (!dc) return 0;
678 FONT_LogFont16ToW(plf, &lfW);
680 fe16.hdc = HDC_32(hDC);
681 fe16.dc = dc;
682 fe16.physDev = dc->physDev;
683 fe16.lpLogFontParam = plf;
684 fe16.lpEnumFunc = efproc;
685 fe16.lpData = lParam;
686 fe16.lpTextMetric = &tm16;
687 fe16.lpLogFont = &lf16;
688 fe16.segTextMetric = MapLS( &tm16 );
689 fe16.segLogFont = MapLS( &lf16 );
690 fe16.dwFlags = 0;
692 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
694 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
696 ret = 0;
697 goto done;
700 if (enum_gdi_fonts)
701 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
702 fe16.dwFlags &= ~ENUM_CALLED;
703 if (ret && dc->funcs->pEnumDeviceFonts) {
704 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
705 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
706 ret = ret2;
708 done:
709 UnMapLS( fe16.segTextMetric );
710 UnMapLS( fe16.segLogFont );
711 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
712 return ret;
715 /***********************************************************************
716 * FONT_EnumFontFamiliesEx
718 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
719 FONTENUMPROCW efproc,
720 LPARAM lParam, DWORD dwUnicode)
722 INT ret = 1, ret2;
723 DC *dc = DC_GetDCPtr( hDC );
724 fontEnum32 fe32;
725 BOOL enum_gdi_fonts;
727 if (!dc) return 0;
729 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
730 plf->lfCharSet);
731 fe32.lpLogFontParam = plf;
732 fe32.lpEnumFunc = efproc;
733 fe32.lpData = lParam;
734 fe32.dwFlags = dwUnicode;
735 fe32.hdc = hDC;
736 fe32.dc = dc;
737 fe32.physDev = dc->physDev;
739 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
741 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
743 ret = 0;
744 goto done;
747 if (enum_gdi_fonts)
748 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
749 fe32.dwFlags &= ~ENUM_CALLED;
750 if (ret && dc->funcs->pEnumDeviceFonts) {
751 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
752 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
753 ret = ret2;
755 done:
756 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
757 return ret;
760 /***********************************************************************
761 * EnumFontFamiliesExW (GDI32.@)
763 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
764 FONTENUMPROCW efproc,
765 LPARAM lParam, DWORD dwFlags )
767 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
770 /***********************************************************************
771 * EnumFontFamiliesExA (GDI32.@)
773 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
774 FONTENUMPROCA efproc,
775 LPARAM lParam, DWORD dwFlags)
777 LOGFONTW lfW;
778 FONT_LogFontAToW( plf, &lfW );
780 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
783 /***********************************************************************
784 * EnumFontFamilies (GDI.330)
786 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
787 FONTENUMPROC16 efproc, LPARAM lpData )
789 LOGFONT16 lf;
791 lf.lfCharSet = DEFAULT_CHARSET;
792 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
793 else lf.lfFaceName[0] = '\0';
795 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
798 /***********************************************************************
799 * EnumFontFamiliesA (GDI32.@)
801 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
802 FONTENUMPROCA efproc, LPARAM lpData )
804 LOGFONTA lf;
806 lf.lfCharSet = DEFAULT_CHARSET;
807 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
808 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
810 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
813 /***********************************************************************
814 * EnumFontFamiliesW (GDI32.@)
816 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
817 FONTENUMPROCW efproc, LPARAM lpData )
819 LOGFONTW lf;
821 lf.lfCharSet = DEFAULT_CHARSET;
822 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
823 else lf.lfFaceName[0] = 0;
825 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
828 /***********************************************************************
829 * EnumFonts (GDI.70)
831 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
832 LPARAM lpData )
834 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
837 /***********************************************************************
838 * EnumFontsA (GDI32.@)
840 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
841 LPARAM lpData )
843 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
846 /***********************************************************************
847 * EnumFontsW (GDI32.@)
849 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
850 LPARAM lpData )
852 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
856 /***********************************************************************
857 * GetTextCharacterExtra (GDI32.@)
859 INT WINAPI GetTextCharacterExtra( HDC hdc )
861 INT ret;
862 DC *dc = DC_GetDCPtr( hdc );
863 if (!dc) return 0x80000000;
864 ret = dc->charExtra;
865 GDI_ReleaseObj( hdc );
866 return ret;
870 /***********************************************************************
871 * SetTextCharacterExtra (GDI32.@)
873 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
875 INT prev;
876 DC * dc = DC_GetDCPtr( hdc );
877 if (!dc) return 0x80000000;
878 if (dc->funcs->pSetTextCharacterExtra)
879 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
880 else
882 prev = dc->charExtra;
883 dc->charExtra = extra;
885 GDI_ReleaseObj( hdc );
886 return prev;
890 /***********************************************************************
891 * SetTextJustification (GDI32.@)
893 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
895 BOOL ret = TRUE;
896 DC * dc = DC_GetDCPtr( hdc );
897 if (!dc) return FALSE;
898 if (dc->funcs->pSetTextJustification)
899 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
900 else
902 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
903 if (!extra) breaks = 0;
904 if (breaks)
906 dc->breakExtra = extra / breaks;
907 dc->breakRem = extra - (breaks * dc->breakExtra);
909 else
911 dc->breakExtra = 0;
912 dc->breakRem = 0;
915 GDI_ReleaseObj( hdc );
916 return ret;
920 /***********************************************************************
921 * GetTextFaceA (GDI32.@)
923 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
925 INT res = GetTextFaceW(hdc, 0, NULL);
926 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
927 GetTextFaceW( hdc, res, nameW );
929 if (name)
931 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
932 name[count-1] = 0;
933 res = strlen(name);
935 else
936 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
937 HeapFree( GetProcessHeap(), 0, nameW );
938 return res;
941 /***********************************************************************
942 * GetTextFaceW (GDI32.@)
944 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
946 FONTOBJ *font;
947 INT ret = 0;
949 DC * dc = DC_GetDCPtr( hdc );
950 if (!dc) return 0;
952 if(dc->gdiFont)
953 ret = WineEngGetTextFace(dc->gdiFont, count, name);
954 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
956 if (name)
958 lstrcpynW( name, font->logfont.lfFaceName, count );
959 ret = strlenW(name);
961 else ret = strlenW(font->logfont.lfFaceName) + 1;
962 GDI_ReleaseObj( dc->hFont );
964 GDI_ReleaseObj( hdc );
965 return ret;
969 /***********************************************************************
970 * GetTextExtentPoint32A (GDI32.@)
972 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
973 LPSIZE size )
975 BOOL ret = FALSE;
976 INT wlen;
977 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
979 if (p) {
980 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
981 HeapFree( GetProcessHeap(), 0, p );
984 TRACE("(%p %s %d %p): returning %ld x %ld\n",
985 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
986 return ret;
990 /***********************************************************************
991 * GetTextExtentPoint32W [GDI32.@]
993 * Computes width/height for a string.
995 * Computes width and height of the specified string.
997 * RETURNS
998 * Success: TRUE
999 * Failure: FALSE
1001 BOOL WINAPI GetTextExtentPoint32W(
1002 HDC hdc, /* [in] Handle of device context */
1003 LPCWSTR str, /* [in] Address of text string */
1004 INT count, /* [in] Number of characters in string */
1005 LPSIZE size) /* [out] Address of structure for string size */
1007 BOOL ret = FALSE;
1008 DC * dc = DC_GetDCPtr( hdc );
1009 if (!dc) return FALSE;
1011 if(dc->gdiFont)
1012 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
1013 else if(dc->funcs->pGetTextExtentPoint)
1014 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
1016 if (ret)
1018 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1019 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1020 size->cx += count * dc->charExtra + dc->breakRem;
1023 GDI_ReleaseObj( hdc );
1025 TRACE("(%p %s %d %p): returning %ld x %ld\n",
1026 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
1027 return ret;
1030 /***********************************************************************
1031 * GetTextExtentPointI [GDI32.@]
1033 * Computes width and height of the array of glyph indices.
1035 * RETURNS
1036 * Success: TRUE
1037 * Failure: FALSE
1039 BOOL WINAPI GetTextExtentPointI(
1040 HDC hdc, /* [in] Handle of device context */
1041 const WORD *indices, /* [in] Address of glyph index array */
1042 INT count, /* [in] Number of glyphs in array */
1043 LPSIZE size) /* [out] Address of structure for string size */
1045 BOOL ret = FALSE;
1046 DC * dc = DC_GetDCPtr( hdc );
1047 if (!dc) return FALSE;
1049 if(dc->gdiFont) {
1050 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
1051 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1052 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1053 size->cx += count * dc->charExtra;
1055 else if(dc->funcs->pGetTextExtentPoint) {
1056 FIXME("calling GetTextExtentPoint\n");
1057 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
1060 GDI_ReleaseObj( hdc );
1062 TRACE("(%p %p %d %p): returning %ld x %ld\n",
1063 hdc, indices, count, size, size->cx, size->cy );
1064 return ret;
1068 /***********************************************************************
1069 * GetTextExtentPointA (GDI32.@)
1071 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1072 LPSIZE size )
1074 TRACE("not bug compatible.\n");
1075 return GetTextExtentPoint32A( hdc, str, count, size );
1078 /***********************************************************************
1079 * GetTextExtentPointW (GDI32.@)
1081 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1082 LPSIZE size )
1084 TRACE("not bug compatible.\n");
1085 return GetTextExtentPoint32W( hdc, str, count, size );
1089 /***********************************************************************
1090 * GetTextExtentExPointA (GDI32.@)
1092 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1093 INT maxExt, LPINT lpnFit,
1094 LPINT alpDx, LPSIZE size )
1096 BOOL ret;
1097 INT wlen;
1098 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1099 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1100 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1101 HeapFree( GetProcessHeap(), 0, p );
1102 return ret;
1106 /***********************************************************************
1107 * GetTextExtentExPointW (GDI32.@)
1109 * Return the size of the string as it would be if it was output properly by
1110 * e.g. TextOut.
1112 * This should include
1113 * - Intercharacter spacing
1114 * - justification spacing (not yet done)
1115 * - kerning? see below
1117 * Kerning. Since kerning would be carried out by the rendering code it should
1118 * be done by the driver. However they don't support it yet. Also I am not
1119 * yet persuaded that (certainly under Win95) any kerning is actually done.
1121 * str: According to MSDN this should be null-terminated. That is not true; a
1122 * null will not terminate it early.
1123 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1124 * than count. I have seen it be either the size of the full string or
1125 * 1 less than the size of the full string. I have not seen it bear any
1126 * resemblance to the portion that would fit.
1127 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1128 * trailing intercharacter spacing and any trailing justification.
1130 * FIXME
1131 * Currently we do this by measuring each character etc. We should do it by
1132 * passing the request to the driver, perhaps by extending the
1133 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1134 * thinking about kerning issues and rounding issues in the justification.
1137 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1138 INT maxExt, LPINT lpnFit,
1139 LPINT alpDx, LPSIZE size )
1141 int index, nFit, extent;
1142 SIZE tSize;
1143 BOOL ret = FALSE;
1145 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1147 size->cx = size->cy = nFit = extent = 0;
1148 for(index = 0; index < count; index++)
1150 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1151 /* GetTextExtentPoint includes intercharacter spacing. */
1152 /* FIXME - justification needs doing yet. Remember that the base
1153 * data will not be in logical coordinates.
1155 extent += tSize.cx;
1156 if( !lpnFit || extent <= maxExt )
1157 /* It is allowed to be equal. */
1159 nFit++;
1160 if( alpDx ) alpDx[index] = extent;
1162 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1163 str++;
1165 size->cx = extent;
1166 if(lpnFit) *lpnFit = nFit;
1167 ret = TRUE;
1169 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1171 done:
1172 return ret;
1175 /***********************************************************************
1176 * GetTextMetricsA (GDI32.@)
1178 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1180 TEXTMETRICW tm32;
1182 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1183 FONT_TextMetricWToA( &tm32, metrics );
1184 return TRUE;
1187 /***********************************************************************
1188 * GetTextMetricsW (GDI32.@)
1190 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1192 BOOL ret = FALSE;
1193 DC * dc = DC_GetDCPtr( hdc );
1194 if (!dc) return FALSE;
1196 if (dc->gdiFont)
1197 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1198 else if (dc->funcs->pGetTextMetrics)
1199 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1201 if (ret)
1203 /* device layer returns values in device units
1204 * therefore we have to convert them to logical */
1206 #define WDPTOLP(x) ((x<0)? \
1207 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1208 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1209 #define HDPTOLP(y) ((y<0)? \
1210 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1211 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1213 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1214 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1215 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1216 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1217 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1218 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1219 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1220 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1221 ret = TRUE;
1222 #undef WDPTOLP
1223 #undef HDPTOLP
1224 TRACE("text metrics:\n"
1225 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1226 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1227 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1228 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1229 " PitchAndFamily = %02x\n"
1230 " --------------------\n"
1231 " InternalLeading = %li\n"
1232 " Ascent = %li\n"
1233 " Descent = %li\n"
1234 " Height = %li\n",
1235 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1236 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1237 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1238 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1239 metrics->tmPitchAndFamily,
1240 metrics->tmInternalLeading,
1241 metrics->tmAscent,
1242 metrics->tmDescent,
1243 metrics->tmHeight );
1245 GDI_ReleaseObj( hdc );
1246 return ret;
1250 /***********************************************************************
1251 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1253 * NOTES
1254 * lpOTM should be LPOUTLINETEXTMETRIC
1256 * RETURNS
1257 * Success: Non-zero or size of required buffer
1258 * Failure: 0
1260 UINT16 WINAPI GetOutlineTextMetrics16(
1261 HDC16 hdc, /* [in] Handle of device context */
1262 UINT16 cbData, /* [in] Size of metric data array */
1263 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1265 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1266 return 0;
1270 /***********************************************************************
1271 * GetOutlineTextMetricsA (GDI32.@)
1272 * Gets metrics for TrueType fonts.
1274 * NOTES
1275 * If the supplied buffer isn't big enough Windows partially fills it up to
1276 * its given length and returns that length.
1278 * RETURNS
1279 * Success: Non-zero or size of required buffer
1280 * Failure: 0
1282 UINT WINAPI GetOutlineTextMetricsA(
1283 HDC hdc, /* [in] Handle of device context */
1284 UINT cbData, /* [in] Size of metric data array */
1285 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1287 char buf[512], *ptr;
1288 UINT ret, needed;
1289 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1290 OUTLINETEXTMETRICA *output = lpOTM;
1291 INT left, len;
1293 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1294 return 0;
1295 if(ret > sizeof(buf))
1296 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1297 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1299 needed = sizeof(OUTLINETEXTMETRICA);
1300 if(lpOTMW->otmpFamilyName)
1301 needed += WideCharToMultiByte(CP_ACP, 0,
1302 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1303 NULL, 0, NULL, NULL);
1304 if(lpOTMW->otmpFaceName)
1305 needed += WideCharToMultiByte(CP_ACP, 0,
1306 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1307 NULL, 0, NULL, NULL);
1308 if(lpOTMW->otmpStyleName)
1309 needed += WideCharToMultiByte(CP_ACP, 0,
1310 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1311 NULL, 0, NULL, NULL);
1312 if(lpOTMW->otmpFullName)
1313 needed += WideCharToMultiByte(CP_ACP, 0,
1314 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1315 NULL, 0, NULL, NULL);
1317 if(!lpOTM) {
1318 ret = needed;
1319 goto end;
1322 TRACE("needed = %d\n", needed);
1323 if(needed > cbData)
1324 /* Since the supplied buffer isn't big enough, we'll alloc one
1325 that is and memcpy the first cbData bytes into the lpOTM at
1326 the end. */
1327 output = HeapAlloc(GetProcessHeap(), 0, needed);
1329 ret = output->otmSize = min(needed, cbData);
1330 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1331 output->otmFiller = 0;
1332 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1333 output->otmfsSelection = lpOTMW->otmfsSelection;
1334 output->otmfsType = lpOTMW->otmfsType;
1335 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1336 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1337 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1338 output->otmEMSquare = lpOTMW->otmEMSquare;
1339 output->otmAscent = lpOTMW->otmAscent;
1340 output->otmDescent = lpOTMW->otmDescent;
1341 output->otmLineGap = lpOTMW->otmLineGap;
1342 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1343 output->otmsXHeight = lpOTMW->otmsXHeight;
1344 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1345 output->otmMacAscent = lpOTMW->otmMacAscent;
1346 output->otmMacDescent = lpOTMW->otmMacDescent;
1347 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1348 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1349 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1350 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1351 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1352 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1353 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1354 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1355 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1356 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1359 ptr = (char*)(output + 1);
1360 left = needed - sizeof(*output);
1362 if(lpOTMW->otmpFamilyName) {
1363 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1364 len = WideCharToMultiByte(CP_ACP, 0,
1365 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1366 ptr, left, NULL, NULL);
1367 left -= len;
1368 ptr += len;
1369 } else
1370 output->otmpFamilyName = 0;
1372 if(lpOTMW->otmpFaceName) {
1373 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1374 len = WideCharToMultiByte(CP_ACP, 0,
1375 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1376 ptr, left, NULL, NULL);
1377 left -= len;
1378 ptr += len;
1379 } else
1380 output->otmpFaceName = 0;
1382 if(lpOTMW->otmpStyleName) {
1383 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1384 len = WideCharToMultiByte(CP_ACP, 0,
1385 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1386 ptr, left, NULL, NULL);
1387 left -= len;
1388 ptr += len;
1389 } else
1390 output->otmpStyleName = 0;
1392 if(lpOTMW->otmpFullName) {
1393 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1394 len = WideCharToMultiByte(CP_ACP, 0,
1395 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1396 ptr, left, NULL, NULL);
1397 left -= len;
1398 } else
1399 output->otmpFullName = 0;
1401 assert(left == 0);
1403 if(output != lpOTM) {
1404 memcpy(lpOTM, output, cbData);
1405 HeapFree(GetProcessHeap(), 0, output);
1408 end:
1409 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1410 HeapFree(GetProcessHeap(), 0, lpOTMW);
1412 return ret;
1416 /***********************************************************************
1417 * GetOutlineTextMetricsW [GDI32.@]
1419 UINT WINAPI GetOutlineTextMetricsW(
1420 HDC hdc, /* [in] Handle of device context */
1421 UINT cbData, /* [in] Size of metric data array */
1422 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1424 DC *dc = DC_GetDCPtr( hdc );
1425 OUTLINETEXTMETRICW *output = lpOTM;
1426 UINT ret;
1428 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1429 if(!dc) return 0;
1431 if(dc->gdiFont) {
1432 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1433 if(lpOTM && ret) {
1434 if(ret > cbData) {
1435 output = HeapAlloc(GetProcessHeap(), 0, ret);
1436 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1439 #define WDPTOLP(x) ((x<0)? \
1440 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1441 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1442 #define HDPTOLP(y) ((y<0)? \
1443 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1444 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1446 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1447 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1448 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1449 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1450 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1451 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1452 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1453 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1454 output->otmAscent = HDPTOLP(output->otmAscent);
1455 output->otmDescent = HDPTOLP(output->otmDescent);
1456 output->otmLineGap = HDPTOLP(output->otmLineGap);
1457 output->otmsCapEmHeight = HDPTOLP(output->otmsCapEmHeight);
1458 output->otmsXHeight = HDPTOLP(output->otmsXHeight);
1459 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1460 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1461 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1462 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1463 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1464 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1465 output->otmMacLineGap = HDPTOLP(output->otmMacLineGap);
1466 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1467 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1468 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1469 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1470 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1471 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1472 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1473 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1474 output->otmsStrikeoutSize = HDPTOLP(output->otmsStrikeoutSize);
1475 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1476 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1477 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1478 #undef WDPTOLP
1479 #undef HDPTOLP
1480 if(output != lpOTM) {
1481 memcpy(lpOTM, output, cbData);
1482 HeapFree(GetProcessHeap(), 0, output);
1483 ret = cbData;
1488 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1489 but really this should just be a return 0. */
1491 ret = sizeof(*lpOTM);
1492 if (lpOTM) {
1493 if(cbData < ret)
1494 ret = 0;
1495 else {
1496 memset(lpOTM, 0, ret);
1497 lpOTM->otmSize = sizeof(*lpOTM);
1498 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1500 Further fill of the structure not implemented,
1501 Needs real values for the structure members
1506 GDI_ReleaseObj(hdc);
1507 return ret;
1511 /***********************************************************************
1512 * GetCharWidthW (GDI32.@)
1513 * GetCharWidth32W (GDI32.@)
1515 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1516 LPINT buffer )
1518 UINT i;
1519 BOOL ret = FALSE;
1520 DC * dc = DC_GetDCPtr( hdc );
1521 if (!dc) return FALSE;
1523 if (dc->gdiFont)
1524 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1525 else if (dc->funcs->pGetCharWidth)
1526 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1528 if (ret)
1530 /* convert device units to logical */
1531 for( i = firstChar; i <= lastChar; i++, buffer++ )
1532 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1533 ret = TRUE;
1535 GDI_ReleaseObj( hdc );
1536 return ret;
1540 /***********************************************************************
1541 * GetCharWidthA (GDI32.@)
1542 * GetCharWidth32A (GDI32.@)
1544 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1545 LPINT buffer )
1547 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1548 LPSTR str;
1549 LPWSTR wstr;
1550 BOOL ret = TRUE;
1552 if(count <= 0) return FALSE;
1554 str = HeapAlloc(GetProcessHeap(), 0, count);
1555 for(i = 0; i < count; i++)
1556 str[i] = (BYTE)(firstChar + i);
1558 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1560 for(i = 0; i < wlen; i++)
1562 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1564 ret = FALSE;
1565 break;
1567 buffer++;
1570 HeapFree(GetProcessHeap(), 0, str);
1571 HeapFree(GetProcessHeap(), 0, wstr);
1573 return ret;
1577 /* FIXME: all following APIs ******************************************/
1580 /***********************************************************************
1581 * SetMapperFlags (GDI32.@)
1583 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1585 DC *dc = DC_GetDCPtr( hDC );
1586 DWORD ret = 0;
1587 if(!dc) return 0;
1588 if(dc->funcs->pSetMapperFlags)
1589 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1590 else
1591 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1592 GDI_ReleaseObj( hDC );
1593 return ret;
1596 /***********************************************************************
1597 * GetAspectRatioFilterEx (GDI.486)
1599 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1601 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1602 return FALSE;
1605 /***********************************************************************
1606 * GetAspectRatioFilterEx (GDI32.@)
1608 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1610 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1611 return FALSE;
1615 /***********************************************************************
1616 * GetCharABCWidthsA (GDI32.@)
1618 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1619 LPABC abc )
1621 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1622 LPSTR str;
1623 LPWSTR wstr;
1624 BOOL ret = TRUE;
1626 if(count <= 0) return FALSE;
1628 str = HeapAlloc(GetProcessHeap(), 0, count);
1629 for(i = 0; i < count; i++)
1630 str[i] = (BYTE)(firstChar + i);
1632 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1634 for(i = 0; i < wlen; i++)
1636 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1638 ret = FALSE;
1639 break;
1641 abc++;
1644 HeapFree(GetProcessHeap(), 0, str);
1645 HeapFree(GetProcessHeap(), 0, wstr);
1647 return ret;
1651 /******************************************************************************
1652 * GetCharABCWidthsW [GDI32.@]
1654 * Retrieves widths of characters in range.
1656 * PARAMS
1657 * hdc [I] Handle of device context
1658 * firstChar [I] First character in range to query
1659 * lastChar [I] Last character in range to query
1660 * abc [O] Address of character-width structure
1662 * NOTES
1663 * Only works with TrueType fonts
1665 * RETURNS
1666 * Success: TRUE
1667 * Failure: FALSE
1669 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1670 LPABC abc )
1672 DC *dc = DC_GetDCPtr(hdc);
1673 int i;
1674 BOOL ret = FALSE;
1676 if(dc->gdiFont)
1677 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
1678 else
1679 FIXME(": stub\n");
1681 if (ret)
1683 /* convert device units to logical */
1684 for( i = firstChar; i <= lastChar; i++, abc++ ) {
1685 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
1686 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
1687 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
1689 ret = TRUE;
1692 GDI_ReleaseObj(hdc);
1693 return ret;
1697 /***********************************************************************
1698 * GetGlyphOutline (GDI.309)
1700 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1701 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1702 LPVOID lpBuffer, const MAT2 *lpmat2 )
1704 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1705 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1706 return ~0UL; /* failure */
1710 /***********************************************************************
1711 * GetGlyphOutlineA (GDI32.@)
1713 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1714 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1715 LPVOID lpBuffer, const MAT2 *lpmat2 )
1717 LPWSTR p = NULL;
1718 DWORD ret;
1719 UINT c;
1721 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1722 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1723 c = p[0];
1724 } else
1725 c = uChar;
1726 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1727 lpmat2);
1728 if(p)
1729 HeapFree(GetProcessHeap(), 0, p);
1730 return ret;
1733 /***********************************************************************
1734 * GetGlyphOutlineW (GDI32.@)
1736 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1737 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1738 LPVOID lpBuffer, const MAT2 *lpmat2 )
1740 DC *dc = DC_GetDCPtr(hdc);
1741 DWORD ret;
1743 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1744 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1746 if(!dc) return GDI_ERROR;
1748 if(dc->gdiFont)
1749 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1750 cbBuffer, lpBuffer, lpmat2);
1751 else
1752 ret = GDI_ERROR;
1754 GDI_ReleaseObj(hdc);
1755 return ret;
1759 /***********************************************************************
1760 * CreateScalableFontResourceA (GDI32.@)
1762 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1763 LPCSTR lpszResourceFile,
1764 LPCSTR lpszFontFile,
1765 LPCSTR lpszCurrentPath )
1767 HANDLE f;
1769 /* fHidden=1 - only visible for the calling app, read-only, not
1770 * enumbered with EnumFonts/EnumFontFamilies
1771 * lpszCurrentPath can be NULL
1773 FIXME("(%ld,%s,%s,%s): stub\n",
1774 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1775 debugstr_a(lpszCurrentPath) );
1777 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1778 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1779 CloseHandle(f);
1780 SetLastError(ERROR_FILE_EXISTS);
1781 return FALSE;
1783 return FALSE; /* create failed */
1786 /***********************************************************************
1787 * CreateScalableFontResourceW (GDI32.@)
1789 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1790 LPCWSTR lpszResourceFile,
1791 LPCWSTR lpszFontFile,
1792 LPCWSTR lpszCurrentPath )
1794 FIXME("(%ld,%p,%p,%p): stub\n",
1795 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1796 return FALSE; /* create failed */
1800 /*************************************************************************
1801 * GetRasterizerCaps (GDI32.@)
1803 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1805 lprs->nSize = sizeof(RASTERIZER_STATUS);
1806 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1807 lprs->nLanguageID = 0;
1808 return TRUE;
1812 /*************************************************************************
1813 * GetKerningPairsA (GDI32.@)
1815 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1816 LPKERNINGPAIR lpKerningPairs )
1818 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1822 /*************************************************************************
1823 * GetKerningPairsW (GDI32.@)
1825 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1826 LPKERNINGPAIR lpKerningPairs )
1828 int i;
1829 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1830 for (i = 0; i < cPairs; i++)
1831 lpKerningPairs[i].iKernAmount = 0;
1832 return 0;
1835 /*************************************************************************
1836 * TranslateCharsetInfo [GDI32.@]
1838 * Fills a CHARSETINFO structure for a character set, code page, or
1839 * font. This allows making the correspondance between different labelings
1840 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1841 * of the same encoding.
1843 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1844 * only one codepage should be set in *lpSrc.
1846 * RETURNS
1847 * TRUE on success, FALSE on failure.
1850 BOOL WINAPI TranslateCharsetInfo(
1851 LPDWORD lpSrc, /* [in]
1852 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1853 if flags == TCI_SRCCHARSET: a character set value
1854 if flags == TCI_SRCCODEPAGE: a code page value
1856 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1857 DWORD flags /* [in] determines interpretation of lpSrc */)
1859 int index = 0;
1860 switch (flags) {
1861 case TCI_SRCFONTSIG:
1862 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1863 break;
1864 case TCI_SRCCODEPAGE:
1865 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1866 break;
1867 case TCI_SRCCHARSET:
1868 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1869 break;
1870 default:
1871 return FALSE;
1873 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1874 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1875 return TRUE;
1878 /*************************************************************************
1879 * GetFontLanguageInfo (GDI32.@)
1881 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1883 FONTSIGNATURE fontsig;
1884 static const DWORD GCP_DBCS_MASK=0x003F0000,
1885 GCP_DIACRITIC_MASK=0x00000000,
1886 FLI_GLYPHS_MASK=0x00000000,
1887 GCP_GLYPHSHAPE_MASK=0x00000040,
1888 GCP_KASHIDA_MASK=0x00000000,
1889 GCP_LIGATE_MASK=0x00000000,
1890 GCP_USEKERNING_MASK=0x00000000,
1891 GCP_REORDER_MASK=0x00000060;
1893 DWORD result=0;
1895 GetTextCharsetInfo( hdc, &fontsig, 0 );
1896 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1898 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1899 result|=GCP_DBCS;
1901 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1902 result|=GCP_DIACRITIC;
1904 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1905 result|=FLI_GLYPHS;
1907 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1908 result|=GCP_GLYPHSHAPE;
1910 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1911 result|=GCP_KASHIDA;
1913 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1914 result|=GCP_LIGATE;
1916 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1917 result|=GCP_USEKERNING;
1919 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
1920 if( GetTextAlign( hdc) & TA_RTLREADING )
1921 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1922 result|=GCP_REORDER;
1924 return result;
1928 /*************************************************************************
1929 * GetFontData [GDI32.@]
1931 * Retrieve data for TrueType font.
1933 * RETURNS
1935 * success: Number of bytes returned
1936 * failure: GDI_ERROR
1938 * NOTES
1940 * Calls SetLastError()
1943 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1944 LPVOID buffer, DWORD length)
1946 DC *dc = DC_GetDCPtr(hdc);
1947 DWORD ret = GDI_ERROR;
1949 if(!dc) return GDI_ERROR;
1951 if(dc->gdiFont)
1952 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1954 GDI_ReleaseObj(hdc);
1955 return ret;
1958 /*************************************************************************
1959 * GetGlyphIndicesA [GDI32.@]
1961 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1962 LPWORD pgi, DWORD flags)
1964 DWORD ret;
1965 WCHAR *lpstrW;
1966 INT countW;
1968 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1969 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1971 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1972 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1973 HeapFree(GetProcessHeap(), 0, lpstrW);
1975 return ret;
1978 /*************************************************************************
1979 * GetGlyphIndicesW [GDI32.@]
1981 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1982 LPWORD pgi, DWORD flags)
1984 DC *dc = DC_GetDCPtr(hdc);
1985 DWORD ret = GDI_ERROR;
1987 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1988 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1990 if(!dc) return GDI_ERROR;
1992 if(dc->gdiFont)
1993 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1995 GDI_ReleaseObj(hdc);
1996 return ret;
1999 /*************************************************************************
2000 * GetCharacterPlacementA [GDI32.@]
2002 * NOTES:
2003 * the web browser control of ie4 calls this with dwFlags=0
2005 DWORD WINAPI
2006 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2007 INT nMaxExtent, GCP_RESULTSA *lpResults,
2008 DWORD dwFlags)
2010 WCHAR *lpStringW;
2011 INT uCountW;
2012 GCP_RESULTSW resultsW;
2013 DWORD ret;
2014 UINT font_cp;
2016 TRACE("%s, %d, %d, 0x%08lx\n",
2017 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2019 /* both structs are equal in size */
2020 memcpy(&resultsW, lpResults, sizeof(resultsW));
2022 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2023 if(lpResults->lpOutString)
2024 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2026 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2028 if(lpResults->lpOutString) {
2029 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2030 lpResults->lpOutString, uCount, NULL, NULL );
2033 HeapFree(GetProcessHeap(), 0, lpStringW);
2034 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2036 return ret;
2039 /*************************************************************************
2040 * GetCharacterPlacementW [GDI32.@]
2042 * Retrieve information about a string. This includes the width, reordering,
2043 * Glyphing and so on.
2045 * RETURNS
2047 * The width and height of the string if successful, 0 if failed.
2049 * BUGS
2051 * All flags except GCP_REORDER are not yet implemented.
2052 * Reordering is not 100% complient to the Windows BiDi method.
2053 * Caret positioning is not yet implemented for BiDi.
2054 * Classes are not yet implemented.
2057 DWORD WINAPI
2058 GetCharacterPlacementW(
2059 HDC hdc, /* [in] Device context for which the rendering is to be done */
2060 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2061 INT uCount, /* [in] Number of WORDS in string. */
2062 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2063 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2064 DWORD dwFlags /* [in] Flags specifying how to process the string */
2067 DWORD ret=0;
2068 SIZE size;
2069 UINT i, nSet;
2071 TRACE("%s, %d, %d, 0x%08lx\n",
2072 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2074 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2075 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2076 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2077 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2078 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2080 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
2081 if(lpResults->lpClass) FIXME("classes not implemented\n");
2082 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2083 FIXME("Caret positions for complex scripts not implemented\n");
2085 nSet = (UINT)uCount;
2086 if(nSet > lpResults->nGlyphs)
2087 nSet = lpResults->nGlyphs;
2089 /* return number of initialized fields */
2090 lpResults->nGlyphs = nSet;
2092 if((dwFlags&GCP_REORDER)==0 || !BidiAvail)
2094 /* Treat the case where no special handling was requested in a fastpath way */
2095 /* copy will do if the GCP_REORDER flag is not set */
2096 if(lpResults->lpOutString)
2097 strncpyW( lpResults->lpOutString, lpString, nSet );
2099 if(lpResults->lpOrder)
2101 for(i = 0; i < nSet; i++)
2102 lpResults->lpOrder[i] = i;
2104 } else
2106 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2107 nSet, lpResults->lpOrder );
2110 /* FIXME: Will use the placement chars */
2111 if (lpResults->lpDx)
2113 int c;
2114 for (i = 0; i < nSet; i++)
2116 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2117 lpResults->lpDx[i]= c;
2121 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2123 int pos = 0;
2125 lpResults->lpCaretPos[0] = 0;
2126 for (i = 1; i < nSet; i++)
2127 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2128 lpResults->lpCaretPos[i] = (pos += size.cx);
2131 if(lpResults->lpGlyphs)
2132 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2134 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2135 ret = MAKELONG(size.cx, size.cy);
2137 return ret;
2140 /*************************************************************************
2141 * GetCharABCWidthsFloatA [GDI32.@]
2143 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2144 LPABCFLOAT lpABCF)
2146 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2147 return 0;
2150 /*************************************************************************
2151 * GetCharABCWidthsFloatW [GDI32.@]
2153 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2154 UINT iLastChar, LPABCFLOAT lpABCF)
2156 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2157 return 0;
2160 /*************************************************************************
2161 * GetCharWidthFloatA [GDI32.@]
2163 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2164 UINT iLastChar, PFLOAT pxBuffer)
2166 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2167 return 0;
2170 /*************************************************************************
2171 * GetCharWidthFloatW [GDI32.@]
2173 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2174 UINT iLastChar, PFLOAT pxBuffer)
2176 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2177 return 0;
2181 /***********************************************************************
2183 * Font Resource API *
2185 ***********************************************************************/
2187 /***********************************************************************
2188 * AddFontResourceA (GDI32.@)
2190 INT WINAPI AddFontResourceA( LPCSTR str )
2192 return AddFontResourceExA( str, 0, NULL);
2195 /***********************************************************************
2196 * AddFontResourceW (GDI32.@)
2198 INT WINAPI AddFontResourceW( LPCWSTR str )
2200 return AddFontResourceExW(str, 0, NULL);
2204 /***********************************************************************
2205 * AddFontResourceExA (GDI32.@)
2207 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2209 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2210 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2211 INT ret;
2213 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2214 ret = AddFontResourceExW(strW, fl, pdv);
2215 HeapFree(GetProcessHeap(), 0, strW);
2216 return ret;
2219 /***********************************************************************
2220 * AddFontResourceExW (GDI32.@)
2222 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2224 return WineEngAddFontResourceEx(str, fl, pdv);
2227 /***********************************************************************
2228 * RemoveFontResourceA (GDI32.@)
2230 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2232 return RemoveFontResourceExA(str, 0, 0);
2235 /***********************************************************************
2236 * RemoveFontResourceW (GDI32.@)
2238 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2240 return RemoveFontResourceExW(str, 0, 0);
2243 /***********************************************************************
2244 * RemoveFontResourceExA (GDI32.@)
2246 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2248 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2249 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2250 INT ret;
2252 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2253 ret = RemoveFontResourceExW(strW, fl, pdv);
2254 HeapFree(GetProcessHeap(), 0, strW);
2255 return ret;
2258 /***********************************************************************
2259 * RemoveFontResourceExW (GDI32.@)
2261 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2263 return WineEngRemoveFontResourceEx(str, fl, pdv);
2266 /***********************************************************************
2267 * GetTextCharset (GDI32.@)
2269 UINT WINAPI GetTextCharset(HDC hdc)
2271 /* MSDN docs say this is equivalent */
2272 return GetTextCharsetInfo(hdc, NULL, 0);
2275 /***********************************************************************
2276 * GetTextCharsetInfo (GDI32.@)
2278 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
2280 UINT ret = DEFAULT_CHARSET;
2281 DC *dc = DC_GetDCPtr(hdc);
2283 if (!dc) goto done;
2285 if (dc->gdiFont)
2286 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
2288 GDI_ReleaseObj(hdc);
2290 done:
2291 if (ret == DEFAULT_CHARSET && fs)
2292 memset(fs, 0, sizeof(FONTSIGNATURE));
2293 return ret;