Declare user-marshaller prototypes for types declared with [wire_marshal].
[wine/multimedia.git] / objects / font.c
blob63fac1ba2cc7dc335c5b9b6c2a0ef4b7b12b9f42
1 /*
2 * GDI font objects
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "config.h"
23 #include "wine/port.h"
25 #include <stdlib.h>
26 #include <string.h>
27 #include <assert.h>
28 #include "winerror.h"
29 #include "winnls.h"
30 #include "wownt32.h"
31 #include "gdi.h"
32 #include "wine/unicode.h"
33 #include "wine/debug.h"
35 WINE_DEFAULT_DEBUG_CHANNEL(font);
36 WINE_DECLARE_DEBUG_CHANNEL(gdi);
38 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc );
39 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
40 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
41 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
42 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
44 static const struct gdi_obj_funcs font_funcs =
46 FONT_SelectObject, /* pSelectObject */
47 FONT_GetObject16, /* pGetObject16 */
48 FONT_GetObjectA, /* pGetObjectA */
49 FONT_GetObjectW, /* pGetObjectW */
50 NULL, /* pUnrealizeObject */
51 FONT_DeleteObject /* pDeleteObject */
54 #define ENUM_UNICODE 0x00000001
55 #define ENUM_CALLED 0x00000002
57 typedef struct
59 GDIOBJHDR header;
60 LOGFONTW logfont;
61 } FONTOBJ;
63 typedef struct
65 LPLOGFONT16 lpLogFontParam;
66 FONTENUMPROC16 lpEnumFunc;
67 LPARAM lpData;
69 LPNEWTEXTMETRICEX16 lpTextMetric;
70 LPENUMLOGFONTEX16 lpLogFont;
71 SEGPTR segTextMetric;
72 SEGPTR segLogFont;
73 DWORD dwFlags;
74 HDC hdc;
75 DC *dc;
76 PHYSDEV physDev;
77 } fontEnum16;
79 typedef struct
81 LPLOGFONTW lpLogFontParam;
82 FONTENUMPROCW lpEnumFunc;
83 LPARAM lpData;
84 DWORD dwFlags;
85 HDC hdc;
86 DC *dc;
87 PHYSDEV physDev;
88 } fontEnum32;
91 * For TranslateCharsetInfo
93 #define FS(x) {{0,0,0,0},{0x1<<(x),0}}
94 #define MAXTCIINDEX 32
95 static CHARSETINFO FONT_tci[MAXTCIINDEX] = {
96 /* ANSI */
97 { ANSI_CHARSET, 1252, FS(0)},
98 { EASTEUROPE_CHARSET, 1250, FS(1)},
99 { RUSSIAN_CHARSET, 1251, FS(2)},
100 { GREEK_CHARSET, 1253, FS(3)},
101 { TURKISH_CHARSET, 1254, FS(4)},
102 { HEBREW_CHARSET, 1255, FS(5)},
103 { ARABIC_CHARSET, 1256, FS(6)},
104 { BALTIC_CHARSET, 1257, FS(7)},
105 { VIETNAMESE_CHARSET, 1258, FS(8)},
106 /* reserved by ANSI */
107 { DEFAULT_CHARSET, 0, FS(0)},
108 { DEFAULT_CHARSET, 0, FS(0)},
109 { DEFAULT_CHARSET, 0, FS(0)},
110 { DEFAULT_CHARSET, 0, FS(0)},
111 { DEFAULT_CHARSET, 0, FS(0)},
112 { DEFAULT_CHARSET, 0, FS(0)},
113 { DEFAULT_CHARSET, 0, FS(0)},
114 /* ANSI and OEM */
115 { THAI_CHARSET, 874, FS(16)},
116 { SHIFTJIS_CHARSET, 932, FS(17)},
117 { GB2312_CHARSET, 936, FS(18)},
118 { HANGEUL_CHARSET, 949, FS(19)},
119 { CHINESEBIG5_CHARSET, 950, FS(20)},
120 { JOHAB_CHARSET, 1361, FS(21)},
121 /* reserved for alternate ANSI and OEM */
122 { DEFAULT_CHARSET, 0, FS(0)},
123 { DEFAULT_CHARSET, 0, FS(0)},
124 { DEFAULT_CHARSET, 0, FS(0)},
125 { DEFAULT_CHARSET, 0, FS(0)},
126 { DEFAULT_CHARSET, 0, FS(0)},
127 { DEFAULT_CHARSET, 0, FS(0)},
128 { DEFAULT_CHARSET, 0, FS(0)},
129 { DEFAULT_CHARSET, 0, FS(0)},
130 /* reserved for system */
131 { DEFAULT_CHARSET, 0, FS(0)},
132 { SYMBOL_CHARSET, CP_SYMBOL, FS(31)},
135 /* ### start build ### */
136 extern WORD CALLBACK FONT_CallTo16_word_llwl(FONTENUMPROC16,LONG,LONG,WORD,LONG);
137 /* ### stop build ### */
139 /***********************************************************************
140 * LOGFONT conversion functions.
142 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
144 font16->lfHeight = font32->lfHeight;
145 font16->lfWidth = font32->lfWidth;
146 font16->lfEscapement = font32->lfEscapement;
147 font16->lfOrientation = font32->lfOrientation;
148 font16->lfWeight = font32->lfWeight;
149 font16->lfItalic = font32->lfItalic;
150 font16->lfUnderline = font32->lfUnderline;
151 font16->lfStrikeOut = font32->lfStrikeOut;
152 font16->lfCharSet = font32->lfCharSet;
153 font16->lfOutPrecision = font32->lfOutPrecision;
154 font16->lfClipPrecision = font32->lfClipPrecision;
155 font16->lfQuality = font32->lfQuality;
156 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
157 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
158 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
159 font16->lfFaceName[LF_FACESIZE-1] = 0;
162 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
164 font32->lfHeight = font16->lfHeight;
165 font32->lfWidth = font16->lfWidth;
166 font32->lfEscapement = font16->lfEscapement;
167 font32->lfOrientation = font16->lfOrientation;
168 font32->lfWeight = font16->lfWeight;
169 font32->lfItalic = font16->lfItalic;
170 font32->lfUnderline = font16->lfUnderline;
171 font32->lfStrikeOut = font16->lfStrikeOut;
172 font32->lfCharSet = font16->lfCharSet;
173 font32->lfOutPrecision = font16->lfOutPrecision;
174 font32->lfClipPrecision = font16->lfClipPrecision;
175 font32->lfQuality = font16->lfQuality;
176 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
177 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
178 font32->lfFaceName[LF_FACESIZE-1] = 0;
181 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
183 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
184 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
185 LF_FACESIZE);
188 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
190 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
191 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
192 LF_FACESIZE, NULL, NULL);
195 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
197 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
199 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
200 font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
201 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
202 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
203 font16->elfStyle, LF_FACESIZE, NULL, NULL );
204 font16->elfStyle[LF_FACESIZE-1] = '\0';
205 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
206 font16->elfScript, LF_FACESIZE, NULL, NULL );
207 font16->elfScript[LF_FACESIZE-1] = '\0';
210 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
212 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
214 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
215 fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
216 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
217 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
218 fontA->elfStyle, LF_FACESIZE, NULL, NULL );
219 fontA->elfStyle[LF_FACESIZE-1] = '\0';
220 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
221 fontA->elfScript, LF_FACESIZE, NULL, NULL );
222 fontA->elfScript[LF_FACESIZE-1] = '\0';
225 /***********************************************************************
226 * TEXTMETRIC conversion functions.
228 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
230 ptmA->tmHeight = ptmW->tmHeight;
231 ptmA->tmAscent = ptmW->tmAscent;
232 ptmA->tmDescent = ptmW->tmDescent;
233 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
234 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
235 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
236 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
237 ptmA->tmWeight = ptmW->tmWeight;
238 ptmA->tmOverhang = ptmW->tmOverhang;
239 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
240 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
241 ptmA->tmFirstChar = ptmW->tmFirstChar;
242 ptmA->tmLastChar = ptmW->tmLastChar;
243 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
244 ptmA->tmBreakChar = ptmW->tmBreakChar;
245 ptmA->tmItalic = ptmW->tmItalic;
246 ptmA->tmUnderlined = ptmW->tmUnderlined;
247 ptmA->tmStruckOut = ptmW->tmStruckOut;
248 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
249 ptmA->tmCharSet = ptmW->tmCharSet;
253 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
255 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
256 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
257 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
258 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
259 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
260 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
261 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
262 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
263 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
264 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
265 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
266 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar;
267 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar;
268 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar;
269 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar;
270 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
271 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
272 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
273 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
274 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
275 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
276 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
277 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
278 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
279 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
282 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
284 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
285 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
286 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
287 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
288 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
289 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
292 /***********************************************************************
293 * CreateFontIndirectA (GDI32.@)
295 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
297 LOGFONTW lfW;
299 if (plfA) {
300 FONT_LogFontAToW( plfA, &lfW );
301 return CreateFontIndirectW( &lfW );
302 } else
303 return CreateFontIndirectW( NULL );
307 /***********************************************************************
308 * CreateFontIndirectW (GDI32.@)
310 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
312 HFONT hFont = 0;
314 if (plf)
316 FONTOBJ* fontPtr;
317 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
318 (HGDIOBJ *)&hFont, &font_funcs )))
320 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
322 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s => %p\n",
323 plf->lfHeight, plf->lfWidth,
324 plf->lfEscapement, plf->lfOrientation,
325 plf->lfPitchAndFamily,
326 plf->lfOutPrecision, plf->lfClipPrecision,
327 plf->lfQuality, plf->lfCharSet,
328 debugstr_w(plf->lfFaceName),
329 plf->lfWeight > 400 ? "Bold" : "",
330 plf->lfItalic ? "Italic" : "", hFont);
332 if (plf->lfEscapement != plf->lfOrientation) {
333 /* this should really depend on whether GM_ADVANCED is set */
334 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
335 WARN("orientation angle %f set to "
336 "escapement angle %f for new font %p\n",
337 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
339 GDI_ReleaseObj( hFont );
342 else WARN("(NULL) => NULL\n");
344 return hFont;
347 /*************************************************************************
348 * CreateFontA (GDI32.@)
350 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
351 INT orient, INT weight, DWORD italic,
352 DWORD underline, DWORD strikeout, DWORD charset,
353 DWORD outpres, DWORD clippres, DWORD quality,
354 DWORD pitch, LPCSTR name )
356 LOGFONTA logfont;
358 logfont.lfHeight = height;
359 logfont.lfWidth = width;
360 logfont.lfEscapement = esc;
361 logfont.lfOrientation = orient;
362 logfont.lfWeight = weight;
363 logfont.lfItalic = italic;
364 logfont.lfUnderline = underline;
365 logfont.lfStrikeOut = strikeout;
366 logfont.lfCharSet = charset;
367 logfont.lfOutPrecision = outpres;
368 logfont.lfClipPrecision = clippres;
369 logfont.lfQuality = quality;
370 logfont.lfPitchAndFamily = pitch;
372 if (name)
373 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
374 else
375 logfont.lfFaceName[0] = '\0';
377 return CreateFontIndirectA( &logfont );
380 /*************************************************************************
381 * CreateFontW (GDI32.@)
383 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
384 INT orient, INT weight, DWORD italic,
385 DWORD underline, DWORD strikeout, DWORD charset,
386 DWORD outpres, DWORD clippres, DWORD quality,
387 DWORD pitch, LPCWSTR name )
389 LOGFONTW logfont;
391 logfont.lfHeight = height;
392 logfont.lfWidth = width;
393 logfont.lfEscapement = esc;
394 logfont.lfOrientation = orient;
395 logfont.lfWeight = weight;
396 logfont.lfItalic = italic;
397 logfont.lfUnderline = underline;
398 logfont.lfStrikeOut = strikeout;
399 logfont.lfCharSet = charset;
400 logfont.lfOutPrecision = outpres;
401 logfont.lfClipPrecision = clippres;
402 logfont.lfQuality = quality;
403 logfont.lfPitchAndFamily = pitch;
405 if (name)
406 lstrcpynW(logfont.lfFaceName, name,
407 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
408 else
409 logfont.lfFaceName[0] = '\0';
411 return CreateFontIndirectW( &logfont );
415 /***********************************************************************
416 * FONT_SelectObject
418 * If the driver supports vector fonts we create a gdi font first and
419 * then call the driver to give it a chance to supply its own device
420 * font. If the driver wants to do this it returns TRUE and we can
421 * delete the gdi font, if the driver wants to use the gdi font it
422 * should return FALSE, to signal an error return GDI_ERROR. For
423 * drivers that don't support vector fonts they must supply their own
424 * font.
426 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
428 HGDIOBJ ret = 0;
429 DC *dc = DC_GetDCPtr( hdc );
431 if (!dc) return 0;
433 if (dc->hFont != handle || dc->gdiFont == NULL)
435 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
436 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
439 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle );
441 if (ret && dc->gdiFont) dc->gdiFont = 0;
443 if (ret == HGDI_ERROR)
444 ret = 0; /* SelectObject returns 0 on error */
445 else
447 ret = dc->hFont;
448 dc->hFont = handle;
450 GDI_ReleaseObj( hdc );
451 return ret;
455 /***********************************************************************
456 * FONT_GetObject16
458 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
460 FONTOBJ *font = obj;
461 LOGFONT16 lf16;
463 FONT_LogFontWTo16( &font->logfont, &lf16 );
465 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
466 memcpy( buffer, &lf16, count );
467 return count;
470 /***********************************************************************
471 * FONT_GetObjectA
473 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
475 FONTOBJ *font = obj;
476 LOGFONTA lfA;
478 FONT_LogFontWToA( &font->logfont, &lfA );
480 if (count > sizeof(lfA)) count = sizeof(lfA);
481 if(buffer)
482 memcpy( buffer, &lfA, count );
483 return count;
486 /***********************************************************************
487 * FONT_GetObjectW
489 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
491 FONTOBJ *font = obj;
492 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
493 if(buffer)
494 memcpy( buffer, &font->logfont, count );
495 return count;
499 /***********************************************************************
500 * FONT_DeleteObject
502 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
504 WineEngDestroyFontInstance( handle );
505 return GDI_FreeObject( handle, obj );
509 /***********************************************************************
510 * FONT_EnumInstance16
512 * Called by the device driver layer to pass font info
513 * down to the application.
515 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
516 DWORD fType, LPARAM lp )
518 fontEnum16 *pfe = (fontEnum16*)lp;
519 INT ret = 1;
520 DC *dc;
522 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
523 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
525 FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
526 FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
527 pfe->dwFlags |= ENUM_CALLED;
528 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
530 ret = FONT_CallTo16_word_llwl( pfe->lpEnumFunc, pfe->segLogFont, pfe->segTextMetric,
531 (UINT16)fType, (LPARAM)pfe->lpData );
532 /* get the lock again and make sure the DC is still valid */
533 dc = DC_GetDCPtr( pfe->hdc );
534 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
536 if (dc) GDI_ReleaseObj( pfe->hdc );
537 pfe->hdc = 0; /* make sure we don't try to release it later on */
538 ret = 0;
541 return ret;
544 /***********************************************************************
545 * FONT_EnumInstance
547 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
548 DWORD fType, LPARAM lp )
550 fontEnum32 *pfe = (fontEnum32*)lp;
551 INT ret = 1;
552 DC *dc;
554 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
555 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
556 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
558 /* convert font metrics */
559 ENUMLOGFONTEXA logfont;
560 NEWTEXTMETRICEXA tmA;
562 pfe->dwFlags |= ENUM_CALLED;
563 if (!(pfe->dwFlags & ENUM_UNICODE))
565 FONT_EnumLogFontExWToA( plf, &logfont);
566 FONT_NewTextMetricExWToA( ptm, &tmA );
567 plf = (LPENUMLOGFONTEXW)&logfont;
568 ptm = (NEWTEXTMETRICEXW *)&tmA;
570 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
572 ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
574 /* get the lock again and make sure the DC is still valid */
575 dc = DC_GetDCPtr( pfe->hdc );
576 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
578 if (dc) GDI_ReleaseObj( pfe->hdc );
579 pfe->hdc = 0; /* make sure we don't try to release it later on */
580 ret = 0;
583 return ret;
586 /***********************************************************************
587 * EnumFontFamiliesEx (GDI.613)
589 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
590 FONTENUMPROC16 efproc, LPARAM lParam,
591 DWORD dwFlags)
593 fontEnum16 fe16;
594 INT16 ret = 1, ret2;
595 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
596 NEWTEXTMETRICEX16 tm16;
597 ENUMLOGFONTEX16 lf16;
598 LOGFONTW lfW;
599 BOOL enum_gdi_fonts;
601 if (!dc) return 0;
602 FONT_LogFont16ToW(plf, &lfW);
604 fe16.hdc = HDC_32(hDC);
605 fe16.dc = dc;
606 fe16.physDev = dc->physDev;
607 fe16.lpLogFontParam = plf;
608 fe16.lpEnumFunc = efproc;
609 fe16.lpData = lParam;
610 fe16.lpTextMetric = &tm16;
611 fe16.lpLogFont = &lf16;
612 fe16.segTextMetric = MapLS( &tm16 );
613 fe16.segLogFont = MapLS( &lf16 );
614 fe16.dwFlags = 0;
616 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
618 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
620 ret = 0;
621 goto done;
624 if (enum_gdi_fonts)
625 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
626 fe16.dwFlags &= ~ENUM_CALLED;
627 if (ret && dc->funcs->pEnumDeviceFonts) {
628 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
629 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
630 ret = ret2;
632 done:
633 UnMapLS( fe16.segTextMetric );
634 UnMapLS( fe16.segLogFont );
635 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
636 return ret;
639 /***********************************************************************
640 * FONT_EnumFontFamiliesEx
642 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
643 FONTENUMPROCW efproc,
644 LPARAM lParam, DWORD dwUnicode)
646 INT ret = 1, ret2;
647 DC *dc = DC_GetDCPtr( hDC );
648 fontEnum32 fe32;
649 BOOL enum_gdi_fonts;
651 if (!dc) return 0;
653 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
654 plf->lfCharSet);
655 fe32.lpLogFontParam = plf;
656 fe32.lpEnumFunc = efproc;
657 fe32.lpData = lParam;
658 fe32.dwFlags = dwUnicode;
659 fe32.hdc = hDC;
660 fe32.dc = dc;
661 fe32.physDev = dc->physDev;
663 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
665 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
667 ret = 0;
668 goto done;
671 if (enum_gdi_fonts)
672 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
673 fe32.dwFlags &= ~ENUM_CALLED;
674 if (ret && dc->funcs->pEnumDeviceFonts) {
675 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
676 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
677 ret = ret2;
679 done:
680 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
681 return ret;
684 /***********************************************************************
685 * EnumFontFamiliesExW (GDI32.@)
687 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
688 FONTENUMPROCW efproc,
689 LPARAM lParam, DWORD dwFlags )
691 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
694 /***********************************************************************
695 * EnumFontFamiliesExA (GDI32.@)
697 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
698 FONTENUMPROCA efproc,
699 LPARAM lParam, DWORD dwFlags)
701 LOGFONTW lfW;
702 FONT_LogFontAToW( plf, &lfW );
704 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
707 /***********************************************************************
708 * EnumFontFamilies (GDI.330)
710 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
711 FONTENUMPROC16 efproc, LPARAM lpData )
713 LOGFONT16 lf;
715 lf.lfCharSet = DEFAULT_CHARSET;
716 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
717 else lf.lfFaceName[0] = '\0';
719 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
722 /***********************************************************************
723 * EnumFontFamiliesA (GDI32.@)
725 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
726 FONTENUMPROCA efproc, LPARAM lpData )
728 LOGFONTA lf;
730 lf.lfCharSet = DEFAULT_CHARSET;
731 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
732 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
734 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
737 /***********************************************************************
738 * EnumFontFamiliesW (GDI32.@)
740 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
741 FONTENUMPROCW efproc, LPARAM lpData )
743 LOGFONTW lf;
745 lf.lfCharSet = DEFAULT_CHARSET;
746 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
747 else lf.lfFaceName[0] = 0;
749 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
752 /***********************************************************************
753 * EnumFonts (GDI.70)
755 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
756 LPARAM lpData )
758 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
761 /***********************************************************************
762 * EnumFontsA (GDI32.@)
764 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
765 LPARAM lpData )
767 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
770 /***********************************************************************
771 * EnumFontsW (GDI32.@)
773 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
774 LPARAM lpData )
776 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
780 /***********************************************************************
781 * GetTextCharacterExtra (GDI32.@)
783 INT WINAPI GetTextCharacterExtra( HDC hdc )
785 INT ret;
786 DC *dc = DC_GetDCPtr( hdc );
787 if (!dc) return 0x80000000;
788 ret = dc->charExtra;
789 GDI_ReleaseObj( hdc );
790 return ret;
794 /***********************************************************************
795 * SetTextCharacterExtra (GDI32.@)
797 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
799 INT prev;
800 DC * dc = DC_GetDCPtr( hdc );
801 if (!dc) return 0x80000000;
802 if (dc->funcs->pSetTextCharacterExtra)
803 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
804 else
806 prev = dc->charExtra;
807 dc->charExtra = extra;
809 GDI_ReleaseObj( hdc );
810 return prev;
814 /***********************************************************************
815 * SetTextJustification (GDI32.@)
817 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
819 BOOL ret = TRUE;
820 DC * dc = DC_GetDCPtr( hdc );
821 if (!dc) return FALSE;
822 if (dc->funcs->pSetTextJustification)
823 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
824 else
826 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
827 if (!extra) breaks = 0;
828 dc->breakTotalExtra = extra;
829 dc->breakCount = breaks;
830 if (breaks)
832 dc->breakExtra = extra / breaks;
833 dc->breakRem = extra - (dc->breakCount * dc->breakExtra);
835 else
837 dc->breakExtra = 0;
838 dc->breakRem = 0;
841 GDI_ReleaseObj( hdc );
842 return ret;
846 /***********************************************************************
847 * GetTextFaceA (GDI32.@)
849 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
851 INT res = GetTextFaceW(hdc, 0, NULL);
852 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
853 GetTextFaceW( hdc, res, nameW );
855 if (name)
856 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count,
857 NULL, NULL);
858 else
859 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
860 HeapFree( GetProcessHeap(), 0, nameW );
861 return res;
864 /***********************************************************************
865 * GetTextFaceW (GDI32.@)
867 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
869 FONTOBJ *font;
870 INT ret = 0;
872 DC * dc = DC_GetDCPtr( hdc );
873 if (!dc) return 0;
875 if(dc->gdiFont)
876 ret = WineEngGetTextFace(dc->gdiFont, count, name);
877 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
879 if (name)
881 lstrcpynW( name, font->logfont.lfFaceName, count );
882 ret = strlenW(name);
884 else ret = strlenW(font->logfont.lfFaceName) + 1;
885 GDI_ReleaseObj( dc->hFont );
887 GDI_ReleaseObj( hdc );
888 return ret;
892 /***********************************************************************
893 * GetTextExtentPoint32A (GDI32.@)
895 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
896 LPSIZE size )
898 BOOL ret = FALSE;
899 INT wlen;
900 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
902 if (p) {
903 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
904 HeapFree( GetProcessHeap(), 0, p );
907 TRACE("(%p %s %d %p): returning %ld x %ld\n",
908 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
909 return ret;
913 /***********************************************************************
914 * GetTextExtentPoint32W [GDI32.@] Computes width/height for a string
916 * Computes width and height of the specified string.
918 * RETURNS
919 * Success: TRUE
920 * Failure: FALSE
922 BOOL WINAPI GetTextExtentPoint32W(
923 HDC hdc, /* [in] Handle of device context */
924 LPCWSTR str, /* [in] Address of text string */
925 INT count, /* [in] Number of characters in string */
926 LPSIZE size) /* [out] Address of structure for string size */
928 BOOL ret = FALSE;
929 DC * dc = DC_GetDCPtr( hdc );
930 if (!dc) return FALSE;
932 if(dc->gdiFont) {
933 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
934 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
935 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
937 else if(dc->funcs->pGetTextExtentPoint)
938 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
940 GDI_ReleaseObj( hdc );
942 TRACE("(%p %s %d %p): returning %ld x %ld\n",
943 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
944 return ret;
947 /***********************************************************************
948 * GetTextExtentPointI [GDI32.@]
950 * Computes width and height of the array of glyph indices.
952 * RETURNS
953 * Success: TRUE
954 * Failure: FALSE
956 BOOL WINAPI GetTextExtentPointI(
957 HDC hdc, /* [in] Handle of device context */
958 const WORD *indices, /* [in] Address of glyph index array */
959 INT count, /* [in] Number of glyphs in array */
960 LPSIZE size) /* [out] Address of structure for string size */
962 BOOL ret = FALSE;
963 DC * dc = DC_GetDCPtr( hdc );
964 if (!dc) return FALSE;
966 if(dc->gdiFont) {
967 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
968 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
969 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
971 else if(dc->funcs->pGetTextExtentPoint) {
972 FIXME("calling GetTextExtentPoint\n");
973 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
976 GDI_ReleaseObj( hdc );
978 TRACE("(%p %p %d %p): returning %ld x %ld\n",
979 hdc, indices, count, size, size->cx, size->cy );
980 return ret;
984 /***********************************************************************
985 * GetTextExtentPointA (GDI32.@)
987 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
988 LPSIZE size )
990 TRACE("not bug compatible.\n");
991 return GetTextExtentPoint32A( hdc, str, count, size );
994 /***********************************************************************
995 * GetTextExtentPointW (GDI32.@)
997 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
998 LPSIZE size )
1000 TRACE("not bug compatible.\n");
1001 return GetTextExtentPoint32W( hdc, str, count, size );
1005 /***********************************************************************
1006 * GetTextExtentExPointA (GDI32.@)
1008 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1009 INT maxExt, LPINT lpnFit,
1010 LPINT alpDx, LPSIZE size )
1012 BOOL ret;
1013 INT wlen;
1014 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1015 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1016 HeapFree( GetProcessHeap(), 0, p );
1017 return ret;
1021 /***********************************************************************
1022 * GetTextExtentExPointW (GDI32.@)
1024 * Return the size of the string as it would be if it was output properly by
1025 * e.g. TextOut.
1027 * This should include
1028 * - Intercharacter spacing
1029 * - justification spacing (not yet done)
1030 * - kerning? see below
1032 * Kerning. Since kerning would be carried out by the rendering code it should
1033 * be done by the driver. However they don't support it yet. Also I am not
1034 * yet persuaded that (certainly under Win95) any kerning is actually done.
1036 * str: According to MSDN this should be null-terminated. That is not true; a
1037 * null will not terminate it early.
1038 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1039 * than count. I have seen it be either the size of the full string or
1040 * 1 less than the size of the full string. I have not seen it bear any
1041 * resemblance to the portion that would fit.
1042 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1043 * trailing intercharacter spacing and any trailing justification.
1045 * FIXME
1046 * Currently we do this by measuring each character etc. We should do it by
1047 * passing the request to the driver, perhaps by extending the
1048 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1049 * thinking about kerning issues and rounding issues in the justification.
1052 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1053 INT maxExt, LPINT lpnFit,
1054 LPINT alpDx, LPSIZE size )
1056 int index, nFit, extent;
1057 SIZE tSize;
1058 BOOL ret = FALSE;
1060 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1062 size->cx = size->cy = nFit = extent = 0;
1063 for(index = 0; index < count; index++)
1065 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1066 /* GetTextExtentPoint includes intercharacter spacing. */
1067 /* FIXME - justification needs doing yet. Remember that the base
1068 * data will not be in logical coordinates.
1070 extent += tSize.cx;
1071 if( !lpnFit || extent <= maxExt )
1072 /* It is allowed to be equal. */
1074 nFit++;
1075 if( alpDx ) alpDx[index] = extent;
1077 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1078 str++;
1080 size->cx = extent;
1081 if(lpnFit) *lpnFit = nFit;
1082 ret = TRUE;
1084 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1086 done:
1087 return ret;
1090 /***********************************************************************
1091 * GetTextMetricsA (GDI32.@)
1093 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1095 TEXTMETRICW tm32;
1097 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1098 FONT_TextMetricWToA( &tm32, metrics );
1099 return TRUE;
1102 /***********************************************************************
1103 * GetTextMetricsW (GDI32.@)
1105 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1107 BOOL ret = FALSE;
1108 DC * dc = DC_GetDCPtr( hdc );
1109 if (!dc) return FALSE;
1111 if (dc->gdiFont)
1112 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1113 else if (dc->funcs->pGetTextMetrics)
1114 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1116 if (ret)
1118 /* device layer returns values in device units
1119 * therefore we have to convert them to logical */
1121 #define WDPTOLP(x) ((x<0)? \
1122 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1123 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1124 #define HDPTOLP(y) ((y<0)? \
1125 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1126 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1128 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1129 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1130 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1131 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1132 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1133 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1134 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1135 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1136 ret = TRUE;
1137 #undef WDPTOLP
1138 #undef HDPTOLP
1139 TRACE("text metrics:\n"
1140 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1141 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1142 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1143 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1144 " PitchAndFamily = %02x\n"
1145 " --------------------\n"
1146 " InternalLeading = %li\n"
1147 " Ascent = %li\n"
1148 " Descent = %li\n"
1149 " Height = %li\n",
1150 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1151 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1152 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1153 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1154 metrics->tmPitchAndFamily,
1155 metrics->tmInternalLeading,
1156 metrics->tmAscent,
1157 metrics->tmDescent,
1158 metrics->tmHeight );
1160 GDI_ReleaseObj( hdc );
1161 return ret;
1165 /***********************************************************************
1166 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1168 * NOTES
1169 * lpOTM should be LPOUTLINETEXTMETRIC
1171 * RETURNS
1172 * Success: Non-zero or size of required buffer
1173 * Failure: 0
1175 UINT16 WINAPI GetOutlineTextMetrics16(
1176 HDC16 hdc, /* [in] Handle of device context */
1177 UINT16 cbData, /* [in] Size of metric data array */
1178 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1180 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1181 return 0;
1185 /***********************************************************************
1186 * GetOutlineTextMetricsA (GDI32.@)
1187 * Gets metrics for TrueType fonts.
1190 * RETURNS
1191 * Success: Non-zero or size of required buffer
1192 * Failure: 0
1194 UINT WINAPI GetOutlineTextMetricsA(
1195 HDC hdc, /* [in] Handle of device context */
1196 UINT cbData, /* [in] Size of metric data array */
1197 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1199 char buf[512], *ptr;
1200 UINT ret, needed;
1201 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1202 INT left, len;
1204 if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
1205 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1206 return 0;
1207 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1208 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1211 needed = sizeof(OUTLINETEXTMETRICA);
1212 if(lpOTMW->otmpFamilyName)
1213 needed += WideCharToMultiByte(CP_ACP, 0,
1214 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1215 NULL, 0, NULL, NULL);
1216 if(lpOTMW->otmpFaceName)
1217 needed += WideCharToMultiByte(CP_ACP, 0,
1218 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1219 NULL, 0, NULL, NULL);
1220 if(lpOTMW->otmpStyleName)
1221 needed += WideCharToMultiByte(CP_ACP, 0,
1222 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1223 NULL, 0, NULL, NULL);
1224 if(lpOTMW->otmpFullName)
1225 needed += WideCharToMultiByte(CP_ACP, 0,
1226 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1227 NULL, 0, NULL, NULL);
1229 if(!lpOTM) {
1230 ret = needed;
1231 goto end;
1234 if(needed > cbData) {
1235 ret = 0;
1236 goto end;
1240 lpOTM->otmSize = needed;
1241 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
1242 lpOTM->otmFiller = 0;
1243 lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1244 lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
1245 lpOTM->otmfsType = lpOTMW->otmfsType;
1246 lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1247 lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1248 lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
1249 lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
1250 lpOTM->otmAscent = lpOTMW->otmAscent;
1251 lpOTM->otmDescent = lpOTMW->otmDescent;
1252 lpOTM->otmLineGap = lpOTMW->otmLineGap;
1253 lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1254 lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
1255 lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
1256 lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
1257 lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
1258 lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
1259 lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1260 lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1261 lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1262 lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1263 lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1264 lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1265 lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1266 lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1267 lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1270 ptr = (char*)(lpOTM + 1);
1271 left = needed - sizeof(*lpOTM);
1273 if(lpOTMW->otmpFamilyName) {
1274 lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
1275 len = WideCharToMultiByte(CP_ACP, 0,
1276 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1277 ptr, left, NULL, NULL);
1278 left -= len;
1279 ptr += len;
1280 } else
1281 lpOTM->otmpFamilyName = 0;
1283 if(lpOTMW->otmpFaceName) {
1284 lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
1285 len = WideCharToMultiByte(CP_ACP, 0,
1286 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1287 ptr, left, NULL, NULL);
1288 left -= len;
1289 ptr += len;
1290 } else
1291 lpOTM->otmpFaceName = 0;
1293 if(lpOTMW->otmpStyleName) {
1294 lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
1295 len = WideCharToMultiByte(CP_ACP, 0,
1296 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1297 ptr, left, NULL, NULL);
1298 left -= len;
1299 ptr += len;
1300 } else
1301 lpOTM->otmpStyleName = 0;
1303 if(lpOTMW->otmpFullName) {
1304 lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
1305 len = WideCharToMultiByte(CP_ACP, 0,
1306 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1307 ptr, left, NULL, NULL);
1308 left -= len;
1309 } else
1310 lpOTM->otmpFullName = 0;
1312 assert(left == 0);
1314 ret = needed;
1316 end:
1317 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1318 HeapFree(GetProcessHeap(), 0, lpOTMW);
1320 return ret;
1324 /***********************************************************************
1325 * GetOutlineTextMetricsW [GDI32.@]
1327 UINT WINAPI GetOutlineTextMetricsW(
1328 HDC hdc, /* [in] Handle of device context */
1329 UINT cbData, /* [in] Size of metric data array */
1330 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1332 DC *dc = DC_GetDCPtr( hdc );
1333 UINT ret;
1335 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1336 if(!dc) return 0;
1338 if(dc->gdiFont) {
1339 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
1340 if(ret && ret <= cbData) {
1341 #define WDPTOLP(x) ((x<0)? \
1342 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1343 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1344 #define HDPTOLP(y) ((y<0)? \
1345 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1346 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1348 lpOTM->otmTextMetrics.tmHeight = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
1349 lpOTM->otmTextMetrics.tmAscent = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
1350 lpOTM->otmTextMetrics.tmDescent = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
1351 lpOTM->otmTextMetrics.tmInternalLeading = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
1352 lpOTM->otmTextMetrics.tmExternalLeading = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
1353 lpOTM->otmTextMetrics.tmAveCharWidth = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
1354 lpOTM->otmTextMetrics.tmMaxCharWidth = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
1355 lpOTM->otmTextMetrics.tmOverhang = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
1356 lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
1357 lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
1358 lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
1359 lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
1360 lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
1361 lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
1362 lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
1363 lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
1364 lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
1365 lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
1366 lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
1367 lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
1368 lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
1369 lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
1370 lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
1371 lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
1372 lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
1373 lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
1374 lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
1375 lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
1376 lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
1377 lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
1378 lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
1379 lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
1380 #undef WDPTOLP
1381 #undef HDPTOLP
1385 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1386 but really this should just be a return 0. */
1388 ret = sizeof(*lpOTM);
1389 if (lpOTM) {
1390 if(cbData < ret)
1391 ret = 0;
1392 else {
1393 memset(lpOTM, 0, ret);
1394 lpOTM->otmSize = sizeof(*lpOTM);
1395 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1397 Further fill of the structure not implemented,
1398 Needs real values for the structure members
1403 GDI_ReleaseObj(hdc);
1404 return ret;
1408 /***********************************************************************
1409 * GetCharWidthW (GDI32.@)
1410 * GetCharWidth32W (GDI32.@)
1412 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1413 LPINT buffer )
1415 UINT i, extra;
1416 BOOL ret = FALSE;
1417 DC * dc = DC_GetDCPtr( hdc );
1418 if (!dc) return FALSE;
1420 if (dc->gdiFont)
1421 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1422 else if (dc->funcs->pGetCharWidth)
1423 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1425 if (ret)
1427 /* convert device units to logical */
1429 extra = dc->vportExtX >> 1;
1430 for( i = firstChar; i <= lastChar; i++, buffer++ )
1431 *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
1432 ret = TRUE;
1434 GDI_ReleaseObj( hdc );
1435 return ret;
1439 /***********************************************************************
1440 * GetCharWidthA (GDI32.@)
1441 * GetCharWidth32A (GDI32.@)
1443 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1444 LPINT buffer )
1446 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1447 LPSTR str;
1448 LPWSTR wstr;
1449 BOOL ret = TRUE;
1451 if(count <= 0) return FALSE;
1453 str = HeapAlloc(GetProcessHeap(), 0, count);
1454 for(i = 0; i < count; i++)
1455 str[i] = (BYTE)(firstChar + i);
1457 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1459 for(i = 0; i < wlen; i++)
1461 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1463 ret = FALSE;
1464 break;
1466 buffer++;
1469 HeapFree(GetProcessHeap(), 0, str);
1470 HeapFree(GetProcessHeap(), 0, wstr);
1472 return ret;
1476 /* FIXME: all following APIs ******************************************/
1479 /***********************************************************************
1480 * SetMapperFlags (GDI32.@)
1482 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1484 DC *dc = DC_GetDCPtr( hDC );
1485 DWORD ret = 0;
1486 if(!dc) return 0;
1487 if(dc->funcs->pSetMapperFlags)
1488 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1489 else
1490 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1491 GDI_ReleaseObj( hDC );
1492 return ret;
1495 /***********************************************************************
1496 * GetAspectRatioFilterEx (GDI.486)
1498 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1500 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1501 return FALSE;
1504 /***********************************************************************
1505 * GetAspectRatioFilterEx (GDI32.@)
1507 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1509 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1510 return FALSE;
1514 /***********************************************************************
1515 * GetCharABCWidthsA (GDI32.@)
1517 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1518 LPABC abc )
1520 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1521 LPSTR str;
1522 LPWSTR wstr;
1523 BOOL ret = TRUE;
1525 if(count <= 0) return FALSE;
1527 str = HeapAlloc(GetProcessHeap(), 0, count);
1528 for(i = 0; i < count; i++)
1529 str[i] = (BYTE)(firstChar + i);
1531 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1533 for(i = 0; i < wlen; i++)
1535 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1537 ret = FALSE;
1538 break;
1540 abc++;
1543 HeapFree(GetProcessHeap(), 0, str);
1544 HeapFree(GetProcessHeap(), 0, wstr);
1546 return ret;
1550 /******************************************************************************
1551 * GetCharABCWidthsW [GDI32.@] Retrieves widths of characters in range
1553 * PARAMS
1554 * hdc [I] Handle of device context
1555 * firstChar [I] First character in range to query
1556 * lastChar [I] Last character in range to query
1557 * abc [O] Address of character-width structure
1559 * NOTES
1560 * Only works with TrueType fonts
1562 * RETURNS
1563 * Success: TRUE
1564 * Failure: FALSE
1566 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1567 LPABC abc )
1569 DC *dc = DC_GetDCPtr(hdc);
1570 int i;
1571 GLYPHMETRICS gm;
1572 BOOL ret = FALSE;
1574 if(dc->gdiFont) {
1575 for (i=firstChar;i<=lastChar;i++) {
1576 GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1577 abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1578 abc[i-firstChar].abcB = gm.gmBlackBoxX;
1579 abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1581 ret = TRUE;
1583 GDI_ReleaseObj(hdc);
1584 return ret;
1588 /***********************************************************************
1589 * GetGlyphOutline (GDI.309)
1591 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1592 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1593 LPVOID lpBuffer, const MAT2 *lpmat2 )
1595 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1596 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1597 return (DWORD)-1; /* failure */
1601 /***********************************************************************
1602 * GetGlyphOutlineA (GDI32.@)
1604 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1605 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1606 LPVOID lpBuffer, const MAT2 *lpmat2 )
1608 LPWSTR p = NULL;
1609 DWORD ret;
1610 UINT c;
1612 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1613 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1614 c = p[0];
1615 } else
1616 c = uChar;
1617 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1618 lpmat2);
1619 if(p)
1620 HeapFree(GetProcessHeap(), 0, p);
1621 return ret;
1624 /***********************************************************************
1625 * GetGlyphOutlineW (GDI32.@)
1627 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1628 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1629 LPVOID lpBuffer, const MAT2 *lpmat2 )
1631 DC *dc = DC_GetDCPtr(hdc);
1632 DWORD ret;
1634 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1635 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1637 if(!dc) return GDI_ERROR;
1639 if(dc->gdiFont)
1640 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1641 cbBuffer, lpBuffer, lpmat2);
1642 else
1643 ret = GDI_ERROR;
1645 GDI_ReleaseObj(hdc);
1646 return ret;
1650 /***********************************************************************
1651 * CreateScalableFontResourceA (GDI32.@)
1653 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1654 LPCSTR lpszResourceFile,
1655 LPCSTR lpszFontFile,
1656 LPCSTR lpszCurrentPath )
1658 HANDLE f;
1660 /* fHidden=1 - only visible for the calling app, read-only, not
1661 * enumbered with EnumFonts/EnumFontFamilies
1662 * lpszCurrentPath can be NULL
1664 FIXME("(%ld,%s,%s,%s): stub\n",
1665 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1666 debugstr_a(lpszCurrentPath) );
1668 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1669 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1670 CloseHandle(f);
1671 SetLastError(ERROR_FILE_EXISTS);
1672 return FALSE;
1674 return FALSE; /* create failed */
1677 /***********************************************************************
1678 * CreateScalableFontResourceW (GDI32.@)
1680 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1681 LPCWSTR lpszResourceFile,
1682 LPCWSTR lpszFontFile,
1683 LPCWSTR lpszCurrentPath )
1685 FIXME("(%ld,%p,%p,%p): stub\n",
1686 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1687 return FALSE; /* create failed */
1691 /*************************************************************************
1692 * GetRasterizerCaps (GDI32.@)
1694 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1696 lprs->nSize = sizeof(RASTERIZER_STATUS);
1697 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1698 lprs->nLanguageID = 0;
1699 return TRUE;
1703 /*************************************************************************
1704 * GetKerningPairsA (GDI32.@)
1706 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs, LPKERNINGPAIR lpKerningPairs )
1708 int i;
1709 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1710 for (i = 0; i < cPairs; i++)
1711 lpKerningPairs[i].iKernAmount = 0;
1712 return 0;
1716 /*************************************************************************
1717 * GetKerningPairsW (GDI32.@)
1719 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1720 LPKERNINGPAIR lpKerningPairs )
1722 return GetKerningPairsA( hDC, cPairs, lpKerningPairs );
1725 /*************************************************************************
1726 * TranslateCharsetInfo [GDI32.@]
1728 * Fills a CHARSETINFO structure for a character set, code page, or
1729 * font. This allows making the correspondance between different labelings
1730 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1731 * of the same encoding.
1733 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1734 * only one codepage should be set in *lpSrc.
1736 * RETURNS
1737 * TRUE on success, FALSE on failure.
1740 BOOL WINAPI TranslateCharsetInfo(
1741 LPDWORD lpSrc, /* [in]
1742 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1743 if flags == TCI_SRCCHARSET: a character set value
1744 if flags == TCI_SRCCODEPAGE: a code page value
1746 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1747 DWORD flags /* [in] determines interpretation of lpSrc */
1749 int index = 0;
1750 switch (flags) {
1751 case TCI_SRCFONTSIG:
1752 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1753 break;
1754 case TCI_SRCCODEPAGE:
1755 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1756 break;
1757 case TCI_SRCCHARSET:
1758 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1759 break;
1760 default:
1761 return FALSE;
1763 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1764 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1765 return TRUE;
1768 /*************************************************************************
1769 * GetFontLanguageInfo (GDI32.@)
1771 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1773 FONTSIGNATURE fontsig;
1774 static const DWORD GCP_DBCS_MASK=0x003F0000,
1775 GCP_DIACRITIC_MASK=0x00000000,
1776 FLI_GLYPHS_MASK=0x00000000,
1777 GCP_GLYPHSHAPE_MASK=0x00000040,
1778 GCP_KASHIDA_MASK=0x00000000,
1779 GCP_LIGATE_MASK=0x00000000,
1780 GCP_USEKERNING_MASK=0x00000000,
1781 GCP_REORDER_MASK=0x00000060;
1783 DWORD result=0;
1785 GetTextCharsetInfo( hdc, &fontsig, 0 );
1786 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1788 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1789 result|=GCP_DBCS;
1791 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1792 result|=GCP_DIACRITIC;
1794 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1795 result|=FLI_GLYPHS;
1797 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1798 result|=GCP_GLYPHSHAPE;
1800 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1801 result|=GCP_KASHIDA;
1803 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1804 result|=GCP_LIGATE;
1806 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1807 result|=GCP_USEKERNING;
1809 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1810 result|=GCP_REORDER;
1812 return result;
1816 /*************************************************************************
1817 * GetFontData [GDI32.@] Retrieve data for TrueType font
1819 * RETURNS
1821 * success: Number of bytes returned
1822 * failure: GDI_ERROR
1824 * NOTES
1826 * Calls SetLastError()
1829 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1830 LPVOID buffer, DWORD length)
1832 DC *dc = DC_GetDCPtr(hdc);
1833 DWORD ret = GDI_ERROR;
1835 if(!dc) return GDI_ERROR;
1837 if(dc->gdiFont)
1838 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1840 GDI_ReleaseObj(hdc);
1841 return ret;
1844 /*************************************************************************
1845 * GetGlyphIndicesA [GDI32.@]
1847 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1848 LPWORD pgi, DWORD flags)
1850 DWORD ret;
1851 WCHAR *lpstrW;
1852 INT countW;
1854 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1855 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1857 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1858 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1859 HeapFree(GetProcessHeap(), 0, lpstrW);
1861 return ret;
1864 /*************************************************************************
1865 * GetGlyphIndicesW [GDI32.@]
1867 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1868 LPWORD pgi, DWORD flags)
1870 DC *dc = DC_GetDCPtr(hdc);
1871 DWORD ret = GDI_ERROR;
1873 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1874 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1876 if(!dc) return GDI_ERROR;
1878 if(dc->gdiFont)
1879 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1881 GDI_ReleaseObj(hdc);
1882 return ret;
1885 /*************************************************************************
1886 * GetCharacterPlacementA [GDI32.@]
1888 * NOTES:
1889 * the web browser control of ie4 calls this with dwFlags=0
1891 DWORD WINAPI
1892 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1893 INT nMaxExtent, GCP_RESULTSA *lpResults,
1894 DWORD dwFlags)
1896 WCHAR *lpStringW;
1897 INT uCountW, i;
1898 GCP_RESULTSW resultsW;
1899 DWORD ret;
1900 UINT font_cp;
1902 TRACE("%s, %d, %d, 0x%08lx\n",
1903 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1905 /* both structs are equal in size */
1906 memcpy(&resultsW, lpResults, sizeof(resultsW));
1908 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1909 if(lpResults->lpOutString)
1910 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1912 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1914 if(lpResults->lpOutString) {
1915 if(font_cp != CP_SYMBOL)
1916 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1917 lpResults->lpOutString, uCount, NULL, NULL );
1918 else
1919 for(i = 0; i < uCount; i++)
1920 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1923 HeapFree(GetProcessHeap(), 0, lpStringW);
1924 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1926 return ret;
1929 /*************************************************************************
1930 * GetCharacterPlacementW [GDI32.@]
1932 * Retrieve information about a string. This includes the width, reordering,
1933 * Glyphing and so on.
1935 * RETURNS
1937 * The width and height of the string if succesful, 0 if failed.
1939 * BUGS
1941 * All flags except GCP_REORDER are not yet implemented.
1942 * Reordering is not 100% complient to the Windows BiDi method.
1943 * Caret positioning is not yet implemented.
1944 * Classes are not yet implemented.
1947 DWORD WINAPI
1948 GetCharacterPlacementW(
1949 HDC hdc, /* [in] Device context for which the rendering is to be done */
1950 LPCWSTR lpString, /* [in] The string for which information is to be returned */
1951 INT uCount, /* [in] Number of WORDS in string. */
1952 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
1953 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
1954 DWORD dwFlags /* [in] Flags specifying how to process the string */
1957 DWORD ret=0;
1958 SIZE size;
1959 UINT i, nSet;
1961 TRACE("%s, %d, %d, 0x%08lx\n",
1962 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
1964 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1965 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1966 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
1967 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
1968 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
1970 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
1971 if(lpResults->lpCaretPos) FIXME("caret positions not implemented\n");
1972 if(lpResults->lpClass) FIXME("classes not implemented\n");
1974 nSet = (UINT)uCount;
1975 if(nSet > lpResults->nGlyphs)
1976 nSet = lpResults->nGlyphs;
1978 /* return number of initialized fields */
1979 lpResults->nGlyphs = nSet;
1981 if(dwFlags==0)
1983 /* Treat the case where no special handling was requested in a fastpath way */
1984 /* copy will do if the GCP_REORDER flag is not set */
1985 if(lpResults->lpOutString)
1986 for(i=0; i<nSet && lpString[i]!=0; ++i )
1987 lpResults->lpOutString[i]=lpString[i];
1989 if(lpResults->lpOrder)
1991 for(i = 0; i < nSet; i++)
1992 lpResults->lpOrder[i] = i;
1996 if((dwFlags&GCP_REORDER)!=0)
1998 WORD *pwCharType;
1999 int run_end;
2000 /* Keep a static table that translates the C2 types to something meaningful */
2001 /* 1 - left to right
2002 * -1 - right to left
2003 * 0 - neutral
2005 static const int chardir[]={ 0, 1, -1, 1, 0, 0, -1, 0, 0, 0, 0, 0 };
2007 WARN("The BiDi algorythm doesn't conform to Windows' yet\n");
2008 if( (pwCharType=HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)))==NULL )
2010 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2012 return 0;
2015 /* Fill in the order array with directionality values */
2016 GetStringTypeW(CT_CTYPE2, lpString, uCount, pwCharType);
2018 /* The complete and correct (at least according to MS) BiDi algorythm is not
2019 * yet implemented here. Instead, we just make sure that consecutive runs of
2020 * the same direction (or neutral) are ordered correctly. We also assign Neutrals
2021 * that are between runs of opposing directions the base (ok, always LTR) dir.
2022 * While this is a LONG way from a BiDi algorithm, it does produce more or less
2023 * readable results.
2025 for( i=0; i<uCount; i+=run_end )
2027 for( run_end=1; i+run_end<uCount &&
2028 (chardir[pwCharType[i+run_end]]==chardir[pwCharType[i]] ||
2029 chardir[pwCharType[i+run_end]]==0); ++run_end )
2032 if( chardir[pwCharType[i]]==1 || chardir[pwCharType[i]]==0 )
2034 /* A LTR run */
2035 if(lpResults->lpOutString)
2037 int j;
2038 for( j=0; j<run_end; j++ )
2040 lpResults->lpOutString[i+j]=lpString[i+j];
2044 if(lpResults->lpOrder)
2046 int j;
2047 for( j=0; j<run_end; j++ )
2048 lpResults->lpOrder[i+j] = i+j;
2050 } else
2052 /* A RTL run */
2054 /* Since, at this stage, the paragraph context is always LTR,
2055 * remove any neutrals from the end of this run.
2057 if( chardir[pwCharType[i]]!=0 )
2058 while( chardir[pwCharType[i+run_end-1]]==0 )
2059 --run_end;
2061 if(lpResults->lpOutString)
2063 int j;
2064 for( j=0; j<run_end; j++ )
2066 lpResults->lpOutString[i+j]=lpString[i+run_end-j-1];
2070 if(lpResults->lpOrder)
2072 int j;
2073 for( j=0; j<run_end; j++ )
2074 lpResults->lpOrder[i+j] = i+run_end-j-1;
2079 HeapFree(GetProcessHeap(), 0, pwCharType);
2082 /* FIXME: Will use the placement chars */
2083 if (lpResults->lpDx)
2085 int c;
2086 for (i = 0; i < nSet; i++)
2088 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2089 lpResults->lpDx[i]= c;
2093 if(lpResults->lpGlyphs)
2094 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2096 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2097 ret = MAKELONG(size.cx, size.cy);
2099 return ret;
2102 /*************************************************************************
2103 * GetCharABCWidthsFloatA [GDI32.@]
2105 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2106 LPABCFLOAT lpABCF)
2108 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2109 return 0;
2112 /*************************************************************************
2113 * GetCharABCWidthsFloatW [GDI32.@]
2115 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2116 UINT iLastChar, LPABCFLOAT lpABCF)
2118 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2119 return 0;
2122 /*************************************************************************
2123 * GetCharWidthFloatA [GDI32.@]
2125 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2126 UINT iLastChar, PFLOAT pxBuffer)
2128 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2129 return 0;
2132 /*************************************************************************
2133 * GetCharWidthFloatW [GDI32.@]
2135 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2136 UINT iLastChar, PFLOAT pxBuffer)
2138 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2139 return 0;
2143 /***********************************************************************
2145 * Font Resource API *
2147 ***********************************************************************/
2149 /***********************************************************************
2150 * AddFontResourceA (GDI32.@)
2152 INT WINAPI AddFontResourceA( LPCSTR str )
2154 return AddFontResourceExA( str, 0, NULL);
2157 /***********************************************************************
2158 * AddFontResourceW (GDI32.@)
2160 INT WINAPI AddFontResourceW( LPCWSTR str )
2162 return AddFontResourceExW(str, 0, NULL);
2166 /***********************************************************************
2167 * AddFontResourceExA (GDI32.@)
2169 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2171 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2172 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2173 INT ret;
2175 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2176 ret = AddFontResourceExW(strW, fl, pdv);
2177 HeapFree(GetProcessHeap(), 0, strW);
2178 return ret;
2181 /***********************************************************************
2182 * AddFontResourceExW (GDI32.@)
2184 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2186 return WineEngAddFontResourceEx(str, fl, pdv);
2189 /***********************************************************************
2190 * RemoveFontResourceA (GDI32.@)
2192 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2194 return RemoveFontResourceExA(str, 0, 0);
2197 /***********************************************************************
2198 * RemoveFontResourceW (GDI32.@)
2200 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2202 return RemoveFontResourceExW(str, 0, 0);
2205 /***********************************************************************
2206 * RemoveFontResourceExA (GDI32.@)
2208 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2210 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2211 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2212 INT ret;
2214 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2215 ret = RemoveFontResourceExW(strW, fl, pdv);
2216 HeapFree(GetProcessHeap(), 0, strW);
2217 return ret;
2220 /***********************************************************************
2221 * RemoveFontResourceExW (GDI32.@)
2223 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2225 return WineEngRemoveFontResourceEx(str, fl, pdv);