Handle requests for CLSID_PSDispatch.
[wine.git] / objects / font.c
blob31a18df1d3e42af1b84710efb7a9cdf01954f1f2
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 /***********************************************************************
136 * LOGFONT conversion functions.
138 static void FONT_LogFontWTo16( const LOGFONTW* font32, LPLOGFONT16 font16 )
140 font16->lfHeight = font32->lfHeight;
141 font16->lfWidth = font32->lfWidth;
142 font16->lfEscapement = font32->lfEscapement;
143 font16->lfOrientation = font32->lfOrientation;
144 font16->lfWeight = font32->lfWeight;
145 font16->lfItalic = font32->lfItalic;
146 font16->lfUnderline = font32->lfUnderline;
147 font16->lfStrikeOut = font32->lfStrikeOut;
148 font16->lfCharSet = font32->lfCharSet;
149 font16->lfOutPrecision = font32->lfOutPrecision;
150 font16->lfClipPrecision = font32->lfClipPrecision;
151 font16->lfQuality = font32->lfQuality;
152 font16->lfPitchAndFamily = font32->lfPitchAndFamily;
153 WideCharToMultiByte( CP_ACP, 0, font32->lfFaceName, -1,
154 font16->lfFaceName, LF_FACESIZE, NULL, NULL );
155 font16->lfFaceName[LF_FACESIZE-1] = 0;
158 static void FONT_LogFont16ToW( const LOGFONT16 *font16, LPLOGFONTW font32 )
160 font32->lfHeight = font16->lfHeight;
161 font32->lfWidth = font16->lfWidth;
162 font32->lfEscapement = font16->lfEscapement;
163 font32->lfOrientation = font16->lfOrientation;
164 font32->lfWeight = font16->lfWeight;
165 font32->lfItalic = font16->lfItalic;
166 font32->lfUnderline = font16->lfUnderline;
167 font32->lfStrikeOut = font16->lfStrikeOut;
168 font32->lfCharSet = font16->lfCharSet;
169 font32->lfOutPrecision = font16->lfOutPrecision;
170 font32->lfClipPrecision = font16->lfClipPrecision;
171 font32->lfQuality = font16->lfQuality;
172 font32->lfPitchAndFamily = font16->lfPitchAndFamily;
173 MultiByteToWideChar( CP_ACP, 0, font16->lfFaceName, -1, font32->lfFaceName, LF_FACESIZE );
174 font32->lfFaceName[LF_FACESIZE-1] = 0;
177 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
179 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
180 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
181 LF_FACESIZE);
184 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
186 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
187 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
188 LF_FACESIZE, NULL, NULL);
191 static void FONT_EnumLogFontExWTo16( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEX16 font16 )
193 FONT_LogFontWTo16( (LPLOGFONTW)fontW, (LPLOGFONT16)font16);
195 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
196 font16->elfFullName, LF_FULLFACESIZE, NULL, NULL );
197 font16->elfFullName[LF_FULLFACESIZE-1] = '\0';
198 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
199 font16->elfStyle, LF_FACESIZE, NULL, NULL );
200 font16->elfStyle[LF_FACESIZE-1] = '\0';
201 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
202 font16->elfScript, LF_FACESIZE, NULL, NULL );
203 font16->elfScript[LF_FACESIZE-1] = '\0';
206 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
208 FONT_LogFontWToA( (LPLOGFONTW)fontW, (LPLOGFONTA)fontA);
210 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
211 fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
212 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
213 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
214 fontA->elfStyle, LF_FACESIZE, NULL, NULL );
215 fontA->elfStyle[LF_FACESIZE-1] = '\0';
216 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
217 fontA->elfScript, LF_FACESIZE, NULL, NULL );
218 fontA->elfScript[LF_FACESIZE-1] = '\0';
221 /***********************************************************************
222 * TEXTMETRIC conversion functions.
224 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
226 ptmA->tmHeight = ptmW->tmHeight;
227 ptmA->tmAscent = ptmW->tmAscent;
228 ptmA->tmDescent = ptmW->tmDescent;
229 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
230 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
231 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
232 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
233 ptmA->tmWeight = ptmW->tmWeight;
234 ptmA->tmOverhang = ptmW->tmOverhang;
235 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
236 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
237 ptmA->tmFirstChar = ptmW->tmFirstChar;
238 ptmA->tmLastChar = ptmW->tmLastChar;
239 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
240 ptmA->tmBreakChar = ptmW->tmBreakChar;
241 ptmA->tmItalic = ptmW->tmItalic;
242 ptmA->tmUnderlined = ptmW->tmUnderlined;
243 ptmA->tmStruckOut = ptmW->tmStruckOut;
244 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
245 ptmA->tmCharSet = ptmW->tmCharSet;
249 static void FONT_NewTextMetricExWTo16(const NEWTEXTMETRICEXW *ptmW, LPNEWTEXTMETRICEX16 ptm16 )
251 ptm16->ntmTm.tmHeight = ptmW->ntmTm.tmHeight;
252 ptm16->ntmTm.tmAscent = ptmW->ntmTm.tmAscent;
253 ptm16->ntmTm.tmDescent = ptmW->ntmTm.tmDescent;
254 ptm16->ntmTm.tmInternalLeading = ptmW->ntmTm.tmInternalLeading;
255 ptm16->ntmTm.tmExternalLeading = ptmW->ntmTm.tmExternalLeading;
256 ptm16->ntmTm.tmAveCharWidth = ptmW->ntmTm.tmAveCharWidth;
257 ptm16->ntmTm.tmMaxCharWidth = ptmW->ntmTm.tmMaxCharWidth;
258 ptm16->ntmTm.tmWeight = ptmW->ntmTm.tmWeight;
259 ptm16->ntmTm.tmOverhang = ptmW->ntmTm.tmOverhang;
260 ptm16->ntmTm.tmDigitizedAspectX = ptmW->ntmTm.tmDigitizedAspectX;
261 ptm16->ntmTm.tmDigitizedAspectY = ptmW->ntmTm.tmDigitizedAspectY;
262 ptm16->ntmTm.tmFirstChar = ptmW->ntmTm.tmFirstChar;
263 ptm16->ntmTm.tmLastChar = ptmW->ntmTm.tmLastChar;
264 ptm16->ntmTm.tmDefaultChar = ptmW->ntmTm.tmDefaultChar;
265 ptm16->ntmTm.tmBreakChar = ptmW->ntmTm.tmBreakChar;
266 ptm16->ntmTm.tmItalic = ptmW->ntmTm.tmItalic;
267 ptm16->ntmTm.tmUnderlined = ptmW->ntmTm.tmUnderlined;
268 ptm16->ntmTm.tmStruckOut = ptmW->ntmTm.tmStruckOut;
269 ptm16->ntmTm.tmPitchAndFamily = ptmW->ntmTm.tmPitchAndFamily;
270 ptm16->ntmTm.tmCharSet = ptmW->ntmTm.tmCharSet;
271 ptm16->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
272 ptm16->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
273 ptm16->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
274 ptm16->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
275 memcpy(&ptm16->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
278 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
280 FONT_TextMetricWToA((LPTEXTMETRICW)ptmW, (LPTEXTMETRICA)ptmA);
281 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
282 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
283 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
284 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
285 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
288 /***********************************************************************
289 * CreateFontIndirectA (GDI32.@)
291 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
293 LOGFONTW lfW;
295 if (plfA) {
296 FONT_LogFontAToW( plfA, &lfW );
297 return CreateFontIndirectW( &lfW );
298 } else
299 return CreateFontIndirectW( NULL );
303 /***********************************************************************
304 * CreateFontIndirectW (GDI32.@)
306 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
308 HFONT hFont = 0;
310 if (plf)
312 FONTOBJ* fontPtr;
313 if ((fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC,
314 (HGDIOBJ *)&hFont, &font_funcs )))
316 memcpy( &fontPtr->logfont, plf, sizeof(LOGFONTW) );
318 TRACE("(%ld %ld %ld %ld %x %d %x %d %d) %s %s %s => %p\n",
319 plf->lfHeight, plf->lfWidth,
320 plf->lfEscapement, plf->lfOrientation,
321 plf->lfPitchAndFamily,
322 plf->lfOutPrecision, plf->lfClipPrecision,
323 plf->lfQuality, plf->lfCharSet,
324 debugstr_w(plf->lfFaceName),
325 plf->lfWeight > 400 ? "Bold" : "",
326 plf->lfItalic ? "Italic" : "", hFont);
328 if (plf->lfEscapement != plf->lfOrientation) {
329 /* this should really depend on whether GM_ADVANCED is set */
330 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
331 WARN("orientation angle %f set to "
332 "escapement angle %f for new font %p\n",
333 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
335 GDI_ReleaseObj( hFont );
338 else WARN("(NULL) => NULL\n");
340 return hFont;
343 /*************************************************************************
344 * CreateFontA (GDI32.@)
346 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
347 INT orient, INT weight, DWORD italic,
348 DWORD underline, DWORD strikeout, DWORD charset,
349 DWORD outpres, DWORD clippres, DWORD quality,
350 DWORD pitch, LPCSTR name )
352 LOGFONTA logfont;
354 logfont.lfHeight = height;
355 logfont.lfWidth = width;
356 logfont.lfEscapement = esc;
357 logfont.lfOrientation = orient;
358 logfont.lfWeight = weight;
359 logfont.lfItalic = italic;
360 logfont.lfUnderline = underline;
361 logfont.lfStrikeOut = strikeout;
362 logfont.lfCharSet = charset;
363 logfont.lfOutPrecision = outpres;
364 logfont.lfClipPrecision = clippres;
365 logfont.lfQuality = quality;
366 logfont.lfPitchAndFamily = pitch;
368 if (name)
369 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
370 else
371 logfont.lfFaceName[0] = '\0';
373 return CreateFontIndirectA( &logfont );
376 /*************************************************************************
377 * CreateFontW (GDI32.@)
379 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
380 INT orient, INT weight, DWORD italic,
381 DWORD underline, DWORD strikeout, DWORD charset,
382 DWORD outpres, DWORD clippres, DWORD quality,
383 DWORD pitch, LPCWSTR name )
385 LOGFONTW logfont;
387 logfont.lfHeight = height;
388 logfont.lfWidth = width;
389 logfont.lfEscapement = esc;
390 logfont.lfOrientation = orient;
391 logfont.lfWeight = weight;
392 logfont.lfItalic = italic;
393 logfont.lfUnderline = underline;
394 logfont.lfStrikeOut = strikeout;
395 logfont.lfCharSet = charset;
396 logfont.lfOutPrecision = outpres;
397 logfont.lfClipPrecision = clippres;
398 logfont.lfQuality = quality;
399 logfont.lfPitchAndFamily = pitch;
401 if (name)
402 lstrcpynW(logfont.lfFaceName, name,
403 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
404 else
405 logfont.lfFaceName[0] = '\0';
407 return CreateFontIndirectW( &logfont );
411 /***********************************************************************
412 * FONT_SelectObject
414 * If the driver supports vector fonts we create a gdi font first and
415 * then call the driver to give it a chance to supply its own device
416 * font. If the driver wants to do this it returns TRUE and we can
417 * delete the gdi font, if the driver wants to use the gdi font it
418 * should return FALSE, to signal an error return GDI_ERROR. For
419 * drivers that don't support vector fonts they must supply their own
420 * font.
422 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, void *obj, HDC hdc )
424 HGDIOBJ ret = 0;
425 DC *dc = DC_GetDCPtr( hdc );
427 if (!dc) return 0;
429 if (dc->hFont != handle || dc->gdiFont == NULL)
431 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
432 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
435 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle );
437 if (ret && dc->gdiFont) dc->gdiFont = 0;
439 if (ret == HGDI_ERROR)
440 ret = 0; /* SelectObject returns 0 on error */
441 else
443 ret = dc->hFont;
444 dc->hFont = handle;
446 GDI_ReleaseObj( hdc );
447 return ret;
451 /***********************************************************************
452 * FONT_GetObject16
454 static INT FONT_GetObject16( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
456 FONTOBJ *font = obj;
457 LOGFONT16 lf16;
459 FONT_LogFontWTo16( &font->logfont, &lf16 );
461 if (count > sizeof(LOGFONT16)) count = sizeof(LOGFONT16);
462 memcpy( buffer, &lf16, count );
463 return count;
466 /***********************************************************************
467 * FONT_GetObjectA
469 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
471 FONTOBJ *font = obj;
472 LOGFONTA lfA;
474 FONT_LogFontWToA( &font->logfont, &lfA );
476 if (count > sizeof(lfA)) count = sizeof(lfA);
477 if(buffer)
478 memcpy( buffer, &lfA, count );
479 return count;
482 /***********************************************************************
483 * FONT_GetObjectW
485 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
487 FONTOBJ *font = obj;
488 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
489 if(buffer)
490 memcpy( buffer, &font->logfont, count );
491 return count;
495 /***********************************************************************
496 * FONT_DeleteObject
498 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
500 WineEngDestroyFontInstance( handle );
501 return GDI_FreeObject( handle, obj );
505 /***********************************************************************
506 * FONT_EnumInstance16
508 * Called by the device driver layer to pass font info
509 * down to the application.
511 static INT FONT_EnumInstance16( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
512 DWORD fType, LPARAM lp )
514 fontEnum16 *pfe = (fontEnum16*)lp;
515 INT ret = 1;
516 DC *dc;
518 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
519 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
521 WORD args[7];
522 DWORD result;
524 FONT_EnumLogFontExWTo16(plf, pfe->lpLogFont);
525 FONT_NewTextMetricExWTo16(ptm, pfe->lpTextMetric);
526 pfe->dwFlags |= ENUM_CALLED;
527 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
529 args[6] = SELECTOROF(pfe->segLogFont);
530 args[5] = OFFSETOF(pfe->segLogFont);
531 args[4] = SELECTOROF(pfe->segTextMetric);
532 args[3] = OFFSETOF(pfe->segTextMetric);
533 args[2] = fType;
534 args[1] = HIWORD(pfe->lpData);
535 args[0] = LOWORD(pfe->lpData);
536 WOWCallback16Ex( (DWORD)pfe->lpEnumFunc, WCB16_PASCAL, sizeof(args), args, &result );
537 ret = LOWORD(result);
539 /* get the lock again and make sure the DC is still valid */
540 dc = DC_GetDCPtr( pfe->hdc );
541 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
543 if (dc) GDI_ReleaseObj( pfe->hdc );
544 pfe->hdc = 0; /* make sure we don't try to release it later on */
545 ret = 0;
548 return ret;
551 /***********************************************************************
552 * FONT_EnumInstance
554 static INT FONT_EnumInstance( LPENUMLOGFONTEXW plf, NEWTEXTMETRICEXW *ptm,
555 DWORD fType, LPARAM lp )
557 fontEnum32 *pfe = (fontEnum32*)lp;
558 INT ret = 1;
559 DC *dc;
561 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
562 if( pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
563 pfe->lpLogFontParam->lfCharSet == plf->elfLogFont.lfCharSet )
565 /* convert font metrics */
566 ENUMLOGFONTEXA logfont;
567 NEWTEXTMETRICEXA tmA;
569 pfe->dwFlags |= ENUM_CALLED;
570 if (!(pfe->dwFlags & ENUM_UNICODE))
572 FONT_EnumLogFontExWToA( plf, &logfont);
573 FONT_NewTextMetricExWToA( ptm, &tmA );
574 plf = (LPENUMLOGFONTEXW)&logfont;
575 ptm = (NEWTEXTMETRICEXW *)&tmA;
577 GDI_ReleaseObj( pfe->hdc ); /* release the GDI lock */
579 ret = pfe->lpEnumFunc( &plf->elfLogFont, (TEXTMETRICW *)ptm, fType, pfe->lpData );
581 /* get the lock again and make sure the DC is still valid */
582 dc = DC_GetDCPtr( pfe->hdc );
583 if (!dc || dc != pfe->dc || dc->physDev != pfe->physDev)
585 if (dc) GDI_ReleaseObj( pfe->hdc );
586 pfe->hdc = 0; /* make sure we don't try to release it later on */
587 ret = 0;
590 return ret;
593 /***********************************************************************
594 * EnumFontFamiliesEx (GDI.613)
596 INT16 WINAPI EnumFontFamiliesEx16( HDC16 hDC, LPLOGFONT16 plf,
597 FONTENUMPROC16 efproc, LPARAM lParam,
598 DWORD dwFlags)
600 fontEnum16 fe16;
601 INT16 ret = 1, ret2;
602 DC* dc = DC_GetDCPtr( HDC_32(hDC) );
603 NEWTEXTMETRICEX16 tm16;
604 ENUMLOGFONTEX16 lf16;
605 LOGFONTW lfW;
606 BOOL enum_gdi_fonts;
608 if (!dc) return 0;
609 FONT_LogFont16ToW(plf, &lfW);
611 fe16.hdc = HDC_32(hDC);
612 fe16.dc = dc;
613 fe16.physDev = dc->physDev;
614 fe16.lpLogFontParam = plf;
615 fe16.lpEnumFunc = efproc;
616 fe16.lpData = lParam;
617 fe16.lpTextMetric = &tm16;
618 fe16.lpLogFont = &lf16;
619 fe16.segTextMetric = MapLS( &tm16 );
620 fe16.segLogFont = MapLS( &lf16 );
621 fe16.dwFlags = 0;
623 enum_gdi_fonts = GetDeviceCaps(fe16.hdc, TEXTCAPS) & TC_VA_ABLE;
625 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
627 ret = 0;
628 goto done;
631 if (enum_gdi_fonts)
632 ret = WineEngEnumFonts( &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
633 fe16.dwFlags &= ~ENUM_CALLED;
634 if (ret && dc->funcs->pEnumDeviceFonts) {
635 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, &lfW, FONT_EnumInstance16, (LPARAM)&fe16 );
636 if(fe16.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
637 ret = ret2;
639 done:
640 UnMapLS( fe16.segTextMetric );
641 UnMapLS( fe16.segLogFont );
642 if (fe16.hdc) GDI_ReleaseObj( fe16.hdc );
643 return ret;
646 /***********************************************************************
647 * FONT_EnumFontFamiliesEx
649 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
650 FONTENUMPROCW efproc,
651 LPARAM lParam, DWORD dwUnicode)
653 INT ret = 1, ret2;
654 DC *dc = DC_GetDCPtr( hDC );
655 fontEnum32 fe32;
656 BOOL enum_gdi_fonts;
658 if (!dc) return 0;
660 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
661 plf->lfCharSet);
662 fe32.lpLogFontParam = plf;
663 fe32.lpEnumFunc = efproc;
664 fe32.lpData = lParam;
665 fe32.dwFlags = dwUnicode;
666 fe32.hdc = hDC;
667 fe32.dc = dc;
668 fe32.physDev = dc->physDev;
670 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
672 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
674 ret = 0;
675 goto done;
678 if (enum_gdi_fonts)
679 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
680 fe32.dwFlags &= ~ENUM_CALLED;
681 if (ret && dc->funcs->pEnumDeviceFonts) {
682 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
683 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
684 ret = ret2;
686 done:
687 if (fe32.hdc) GDI_ReleaseObj( fe32.hdc );
688 return ret;
691 /***********************************************************************
692 * EnumFontFamiliesExW (GDI32.@)
694 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
695 FONTENUMPROCW efproc,
696 LPARAM lParam, DWORD dwFlags )
698 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
701 /***********************************************************************
702 * EnumFontFamiliesExA (GDI32.@)
704 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
705 FONTENUMPROCA efproc,
706 LPARAM lParam, DWORD dwFlags)
708 LOGFONTW lfW;
709 FONT_LogFontAToW( plf, &lfW );
711 return FONT_EnumFontFamiliesEx( hDC, &lfW, (FONTENUMPROCW)efproc, lParam, 0);
714 /***********************************************************************
715 * EnumFontFamilies (GDI.330)
717 INT16 WINAPI EnumFontFamilies16( HDC16 hDC, LPCSTR lpFamily,
718 FONTENUMPROC16 efproc, LPARAM lpData )
720 LOGFONT16 lf;
722 lf.lfCharSet = DEFAULT_CHARSET;
723 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
724 else lf.lfFaceName[0] = '\0';
726 return EnumFontFamiliesEx16( hDC, &lf, efproc, lpData, 0 );
729 /***********************************************************************
730 * EnumFontFamiliesA (GDI32.@)
732 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
733 FONTENUMPROCA efproc, LPARAM lpData )
735 LOGFONTA lf;
737 lf.lfCharSet = DEFAULT_CHARSET;
738 if( lpFamily ) lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
739 else lf.lfFaceName[0] = lf.lfFaceName[1] = '\0';
741 return EnumFontFamiliesExA( hDC, &lf, efproc, lpData, 0 );
744 /***********************************************************************
745 * EnumFontFamiliesW (GDI32.@)
747 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
748 FONTENUMPROCW efproc, LPARAM lpData )
750 LOGFONTW lf;
752 lf.lfCharSet = DEFAULT_CHARSET;
753 if( lpFamily ) lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
754 else lf.lfFaceName[0] = 0;
756 return EnumFontFamiliesExW( hDC, &lf, efproc, lpData, 0 );
759 /***********************************************************************
760 * EnumFonts (GDI.70)
762 INT16 WINAPI EnumFonts16( HDC16 hDC, LPCSTR lpName, FONTENUMPROC16 efproc,
763 LPARAM lpData )
765 return EnumFontFamilies16( hDC, lpName, efproc, lpData );
768 /***********************************************************************
769 * EnumFontsA (GDI32.@)
771 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
772 LPARAM lpData )
774 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
777 /***********************************************************************
778 * EnumFontsW (GDI32.@)
780 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
781 LPARAM lpData )
783 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
787 /***********************************************************************
788 * GetTextCharacterExtra (GDI32.@)
790 INT WINAPI GetTextCharacterExtra( HDC hdc )
792 INT ret;
793 DC *dc = DC_GetDCPtr( hdc );
794 if (!dc) return 0x80000000;
795 ret = dc->charExtra;
796 GDI_ReleaseObj( hdc );
797 return ret;
801 /***********************************************************************
802 * SetTextCharacterExtra (GDI32.@)
804 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
806 INT prev;
807 DC * dc = DC_GetDCPtr( hdc );
808 if (!dc) return 0x80000000;
809 if (dc->funcs->pSetTextCharacterExtra)
810 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
811 else
813 prev = dc->charExtra;
814 dc->charExtra = extra;
816 GDI_ReleaseObj( hdc );
817 return prev;
821 /***********************************************************************
822 * SetTextJustification (GDI32.@)
824 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
826 BOOL ret = TRUE;
827 DC * dc = DC_GetDCPtr( hdc );
828 if (!dc) return FALSE;
829 if (dc->funcs->pSetTextJustification)
830 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
831 else
833 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
834 if (!extra) breaks = 0;
835 dc->breakTotalExtra = extra;
836 dc->breakCount = breaks;
837 if (breaks)
839 dc->breakExtra = extra / breaks;
840 dc->breakRem = extra - (dc->breakCount * dc->breakExtra);
842 else
844 dc->breakExtra = 0;
845 dc->breakRem = 0;
848 GDI_ReleaseObj( hdc );
849 return ret;
853 /***********************************************************************
854 * GetTextFaceA (GDI32.@)
856 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
858 INT res = GetTextFaceW(hdc, 0, NULL);
859 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
860 GetTextFaceW( hdc, res, nameW );
862 if (name)
864 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
865 name[count-1] = 0;
866 res = strlen(name);
868 else
869 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
870 HeapFree( GetProcessHeap(), 0, nameW );
871 return res;
874 /***********************************************************************
875 * GetTextFaceW (GDI32.@)
877 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
879 FONTOBJ *font;
880 INT ret = 0;
882 DC * dc = DC_GetDCPtr( hdc );
883 if (!dc) return 0;
885 if(dc->gdiFont)
886 ret = WineEngGetTextFace(dc->gdiFont, count, name);
887 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
889 if (name)
891 lstrcpynW( name, font->logfont.lfFaceName, count );
892 ret = strlenW(name);
894 else ret = strlenW(font->logfont.lfFaceName) + 1;
895 GDI_ReleaseObj( dc->hFont );
897 GDI_ReleaseObj( hdc );
898 return ret;
902 /***********************************************************************
903 * GetTextExtentPoint32A (GDI32.@)
905 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
906 LPSIZE size )
908 BOOL ret = FALSE;
909 INT wlen;
910 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
912 if (p) {
913 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
914 HeapFree( GetProcessHeap(), 0, p );
917 TRACE("(%p %s %d %p): returning %ld x %ld\n",
918 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
919 return ret;
923 /***********************************************************************
924 * GetTextExtentPoint32W [GDI32.@] Computes width/height for a string
926 * Computes width and height of the specified string.
928 * RETURNS
929 * Success: TRUE
930 * Failure: FALSE
932 BOOL WINAPI GetTextExtentPoint32W(
933 HDC hdc, /* [in] Handle of device context */
934 LPCWSTR str, /* [in] Address of text string */
935 INT count, /* [in] Number of characters in string */
936 LPSIZE size) /* [out] Address of structure for string size */
938 BOOL ret = FALSE;
939 DC * dc = DC_GetDCPtr( hdc );
940 if (!dc) return FALSE;
942 if(dc->gdiFont) {
943 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
944 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
945 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
947 else if(dc->funcs->pGetTextExtentPoint)
948 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
950 GDI_ReleaseObj( hdc );
952 TRACE("(%p %s %d %p): returning %ld x %ld\n",
953 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
954 return ret;
957 /***********************************************************************
958 * GetTextExtentPointI [GDI32.@]
960 * Computes width and height of the array of glyph indices.
962 * RETURNS
963 * Success: TRUE
964 * Failure: FALSE
966 BOOL WINAPI GetTextExtentPointI(
967 HDC hdc, /* [in] Handle of device context */
968 const WORD *indices, /* [in] Address of glyph index array */
969 INT count, /* [in] Number of glyphs in array */
970 LPSIZE size) /* [out] Address of structure for string size */
972 BOOL ret = FALSE;
973 DC * dc = DC_GetDCPtr( hdc );
974 if (!dc) return FALSE;
976 if(dc->gdiFont) {
977 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
978 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
979 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
981 else if(dc->funcs->pGetTextExtentPoint) {
982 FIXME("calling GetTextExtentPoint\n");
983 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
986 GDI_ReleaseObj( hdc );
988 TRACE("(%p %p %d %p): returning %ld x %ld\n",
989 hdc, indices, count, size, size->cx, size->cy );
990 return ret;
994 /***********************************************************************
995 * GetTextExtentPointA (GDI32.@)
997 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
998 LPSIZE size )
1000 TRACE("not bug compatible.\n");
1001 return GetTextExtentPoint32A( hdc, str, count, size );
1004 /***********************************************************************
1005 * GetTextExtentPointW (GDI32.@)
1007 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1008 LPSIZE size )
1010 TRACE("not bug compatible.\n");
1011 return GetTextExtentPoint32W( hdc, str, count, size );
1015 /***********************************************************************
1016 * GetTextExtentExPointA (GDI32.@)
1018 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1019 INT maxExt, LPINT lpnFit,
1020 LPINT alpDx, LPSIZE size )
1022 BOOL ret;
1023 INT wlen;
1024 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1025 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1026 HeapFree( GetProcessHeap(), 0, p );
1027 return ret;
1031 /***********************************************************************
1032 * GetTextExtentExPointW (GDI32.@)
1034 * Return the size of the string as it would be if it was output properly by
1035 * e.g. TextOut.
1037 * This should include
1038 * - Intercharacter spacing
1039 * - justification spacing (not yet done)
1040 * - kerning? see below
1042 * Kerning. Since kerning would be carried out by the rendering code it should
1043 * be done by the driver. However they don't support it yet. Also I am not
1044 * yet persuaded that (certainly under Win95) any kerning is actually done.
1046 * str: According to MSDN this should be null-terminated. That is not true; a
1047 * null will not terminate it early.
1048 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1049 * than count. I have seen it be either the size of the full string or
1050 * 1 less than the size of the full string. I have not seen it bear any
1051 * resemblance to the portion that would fit.
1052 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1053 * trailing intercharacter spacing and any trailing justification.
1055 * FIXME
1056 * Currently we do this by measuring each character etc. We should do it by
1057 * passing the request to the driver, perhaps by extending the
1058 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1059 * thinking about kerning issues and rounding issues in the justification.
1062 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1063 INT maxExt, LPINT lpnFit,
1064 LPINT alpDx, LPSIZE size )
1066 int index, nFit, extent;
1067 SIZE tSize;
1068 BOOL ret = FALSE;
1070 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1072 size->cx = size->cy = nFit = extent = 0;
1073 for(index = 0; index < count; index++)
1075 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1076 /* GetTextExtentPoint includes intercharacter spacing. */
1077 /* FIXME - justification needs doing yet. Remember that the base
1078 * data will not be in logical coordinates.
1080 extent += tSize.cx;
1081 if( !lpnFit || extent <= maxExt )
1082 /* It is allowed to be equal. */
1084 nFit++;
1085 if( alpDx ) alpDx[index] = extent;
1087 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1088 str++;
1090 size->cx = extent;
1091 if(lpnFit) *lpnFit = nFit;
1092 ret = TRUE;
1094 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1096 done:
1097 return ret;
1100 /***********************************************************************
1101 * GetTextMetricsA (GDI32.@)
1103 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1105 TEXTMETRICW tm32;
1107 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1108 FONT_TextMetricWToA( &tm32, metrics );
1109 return TRUE;
1112 /***********************************************************************
1113 * GetTextMetricsW (GDI32.@)
1115 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1117 BOOL ret = FALSE;
1118 DC * dc = DC_GetDCPtr( hdc );
1119 if (!dc) return FALSE;
1121 if (dc->gdiFont)
1122 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1123 else if (dc->funcs->pGetTextMetrics)
1124 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1126 if (ret)
1128 /* device layer returns values in device units
1129 * therefore we have to convert them to logical */
1131 #define WDPTOLP(x) ((x<0)? \
1132 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1133 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1134 #define HDPTOLP(y) ((y<0)? \
1135 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1136 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1138 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1139 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1140 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1141 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1142 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1143 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1144 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1145 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1146 ret = TRUE;
1147 #undef WDPTOLP
1148 #undef HDPTOLP
1149 TRACE("text metrics:\n"
1150 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1151 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1152 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1153 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1154 " PitchAndFamily = %02x\n"
1155 " --------------------\n"
1156 " InternalLeading = %li\n"
1157 " Ascent = %li\n"
1158 " Descent = %li\n"
1159 " Height = %li\n",
1160 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1161 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1162 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1163 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1164 metrics->tmPitchAndFamily,
1165 metrics->tmInternalLeading,
1166 metrics->tmAscent,
1167 metrics->tmDescent,
1168 metrics->tmHeight );
1170 GDI_ReleaseObj( hdc );
1171 return ret;
1175 /***********************************************************************
1176 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1178 * NOTES
1179 * lpOTM should be LPOUTLINETEXTMETRIC
1181 * RETURNS
1182 * Success: Non-zero or size of required buffer
1183 * Failure: 0
1185 UINT16 WINAPI GetOutlineTextMetrics16(
1186 HDC16 hdc, /* [in] Handle of device context */
1187 UINT16 cbData, /* [in] Size of metric data array */
1188 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1190 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1191 return 0;
1195 /***********************************************************************
1196 * GetOutlineTextMetricsA (GDI32.@)
1197 * Gets metrics for TrueType fonts.
1200 * RETURNS
1201 * Success: Non-zero or size of required buffer
1202 * Failure: 0
1204 UINT WINAPI GetOutlineTextMetricsA(
1205 HDC hdc, /* [in] Handle of device context */
1206 UINT cbData, /* [in] Size of metric data array */
1207 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1209 char buf[512], *ptr;
1210 UINT ret, needed;
1211 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1212 INT left, len;
1214 if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
1215 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1216 return 0;
1217 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1218 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1221 needed = sizeof(OUTLINETEXTMETRICA);
1222 if(lpOTMW->otmpFamilyName)
1223 needed += WideCharToMultiByte(CP_ACP, 0,
1224 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1225 NULL, 0, NULL, NULL);
1226 if(lpOTMW->otmpFaceName)
1227 needed += WideCharToMultiByte(CP_ACP, 0,
1228 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1229 NULL, 0, NULL, NULL);
1230 if(lpOTMW->otmpStyleName)
1231 needed += WideCharToMultiByte(CP_ACP, 0,
1232 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1233 NULL, 0, NULL, NULL);
1234 if(lpOTMW->otmpFullName)
1235 needed += WideCharToMultiByte(CP_ACP, 0,
1236 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1237 NULL, 0, NULL, NULL);
1239 if(!lpOTM) {
1240 ret = needed;
1241 goto end;
1244 if(needed > cbData) {
1245 ret = 0;
1246 goto end;
1250 lpOTM->otmSize = needed;
1251 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
1252 lpOTM->otmFiller = 0;
1253 lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1254 lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
1255 lpOTM->otmfsType = lpOTMW->otmfsType;
1256 lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1257 lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1258 lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
1259 lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
1260 lpOTM->otmAscent = lpOTMW->otmAscent;
1261 lpOTM->otmDescent = lpOTMW->otmDescent;
1262 lpOTM->otmLineGap = lpOTMW->otmLineGap;
1263 lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1264 lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
1265 lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
1266 lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
1267 lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
1268 lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
1269 lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1270 lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1271 lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1272 lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1273 lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1274 lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1275 lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1276 lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1277 lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1280 ptr = (char*)(lpOTM + 1);
1281 left = needed - sizeof(*lpOTM);
1283 if(lpOTMW->otmpFamilyName) {
1284 lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
1285 len = WideCharToMultiByte(CP_ACP, 0,
1286 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1287 ptr, left, NULL, NULL);
1288 left -= len;
1289 ptr += len;
1290 } else
1291 lpOTM->otmpFamilyName = 0;
1293 if(lpOTMW->otmpFaceName) {
1294 lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
1295 len = WideCharToMultiByte(CP_ACP, 0,
1296 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1297 ptr, left, NULL, NULL);
1298 left -= len;
1299 ptr += len;
1300 } else
1301 lpOTM->otmpFaceName = 0;
1303 if(lpOTMW->otmpStyleName) {
1304 lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
1305 len = WideCharToMultiByte(CP_ACP, 0,
1306 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1307 ptr, left, NULL, NULL);
1308 left -= len;
1309 ptr += len;
1310 } else
1311 lpOTM->otmpStyleName = 0;
1313 if(lpOTMW->otmpFullName) {
1314 lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
1315 len = WideCharToMultiByte(CP_ACP, 0,
1316 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1317 ptr, left, NULL, NULL);
1318 left -= len;
1319 } else
1320 lpOTM->otmpFullName = 0;
1322 assert(left == 0);
1324 ret = needed;
1326 end:
1327 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1328 HeapFree(GetProcessHeap(), 0, lpOTMW);
1330 return ret;
1334 /***********************************************************************
1335 * GetOutlineTextMetricsW [GDI32.@]
1337 UINT WINAPI GetOutlineTextMetricsW(
1338 HDC hdc, /* [in] Handle of device context */
1339 UINT cbData, /* [in] Size of metric data array */
1340 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1342 DC *dc = DC_GetDCPtr( hdc );
1343 UINT ret;
1345 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1346 if(!dc) return 0;
1348 if(dc->gdiFont) {
1349 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
1350 if(ret && ret <= cbData) {
1351 #define WDPTOLP(x) ((x<0)? \
1352 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1353 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1354 #define HDPTOLP(y) ((y<0)? \
1355 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1356 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1358 lpOTM->otmTextMetrics.tmHeight = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
1359 lpOTM->otmTextMetrics.tmAscent = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
1360 lpOTM->otmTextMetrics.tmDescent = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
1361 lpOTM->otmTextMetrics.tmInternalLeading = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
1362 lpOTM->otmTextMetrics.tmExternalLeading = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
1363 lpOTM->otmTextMetrics.tmAveCharWidth = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
1364 lpOTM->otmTextMetrics.tmMaxCharWidth = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
1365 lpOTM->otmTextMetrics.tmOverhang = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
1366 lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
1367 lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
1368 lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
1369 lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
1370 lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
1371 lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
1372 lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
1373 lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
1374 lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
1375 lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
1376 lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
1377 lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
1378 lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
1379 lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
1380 lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
1381 lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
1382 lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
1383 lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
1384 lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
1385 lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
1386 lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
1387 lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
1388 lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
1389 lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
1390 #undef WDPTOLP
1391 #undef HDPTOLP
1395 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1396 but really this should just be a return 0. */
1398 ret = sizeof(*lpOTM);
1399 if (lpOTM) {
1400 if(cbData < ret)
1401 ret = 0;
1402 else {
1403 memset(lpOTM, 0, ret);
1404 lpOTM->otmSize = sizeof(*lpOTM);
1405 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1407 Further fill of the structure not implemented,
1408 Needs real values for the structure members
1413 GDI_ReleaseObj(hdc);
1414 return ret;
1418 /***********************************************************************
1419 * GetCharWidthW (GDI32.@)
1420 * GetCharWidth32W (GDI32.@)
1422 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1423 LPINT buffer )
1425 UINT i, extra;
1426 BOOL ret = FALSE;
1427 DC * dc = DC_GetDCPtr( hdc );
1428 if (!dc) return FALSE;
1430 if (dc->gdiFont)
1431 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1432 else if (dc->funcs->pGetCharWidth)
1433 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1435 if (ret)
1437 /* convert device units to logical */
1439 extra = dc->vportExtX >> 1;
1440 for( i = firstChar; i <= lastChar; i++, buffer++ )
1441 *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
1442 ret = TRUE;
1444 GDI_ReleaseObj( hdc );
1445 return ret;
1449 /***********************************************************************
1450 * GetCharWidthA (GDI32.@)
1451 * GetCharWidth32A (GDI32.@)
1453 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1454 LPINT buffer )
1456 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1457 LPSTR str;
1458 LPWSTR wstr;
1459 BOOL ret = TRUE;
1461 if(count <= 0) return FALSE;
1463 str = HeapAlloc(GetProcessHeap(), 0, count);
1464 for(i = 0; i < count; i++)
1465 str[i] = (BYTE)(firstChar + i);
1467 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1469 for(i = 0; i < wlen; i++)
1471 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1473 ret = FALSE;
1474 break;
1476 buffer++;
1479 HeapFree(GetProcessHeap(), 0, str);
1480 HeapFree(GetProcessHeap(), 0, wstr);
1482 return ret;
1486 /* FIXME: all following APIs ******************************************/
1489 /***********************************************************************
1490 * SetMapperFlags (GDI32.@)
1492 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1494 DC *dc = DC_GetDCPtr( hDC );
1495 DWORD ret = 0;
1496 if(!dc) return 0;
1497 if(dc->funcs->pSetMapperFlags)
1498 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1499 else
1500 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1501 GDI_ReleaseObj( hDC );
1502 return ret;
1505 /***********************************************************************
1506 * GetAspectRatioFilterEx (GDI.486)
1508 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1510 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1511 return FALSE;
1514 /***********************************************************************
1515 * GetAspectRatioFilterEx (GDI32.@)
1517 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1519 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1520 return FALSE;
1524 /***********************************************************************
1525 * GetCharABCWidthsA (GDI32.@)
1527 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1528 LPABC abc )
1530 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1531 LPSTR str;
1532 LPWSTR wstr;
1533 BOOL ret = TRUE;
1535 if(count <= 0) return FALSE;
1537 str = HeapAlloc(GetProcessHeap(), 0, count);
1538 for(i = 0; i < count; i++)
1539 str[i] = (BYTE)(firstChar + i);
1541 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1543 for(i = 0; i < wlen; i++)
1545 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1547 ret = FALSE;
1548 break;
1550 abc++;
1553 HeapFree(GetProcessHeap(), 0, str);
1554 HeapFree(GetProcessHeap(), 0, wstr);
1556 return ret;
1560 /******************************************************************************
1561 * GetCharABCWidthsW [GDI32.@] Retrieves widths of characters in range
1563 * PARAMS
1564 * hdc [I] Handle of device context
1565 * firstChar [I] First character in range to query
1566 * lastChar [I] Last character in range to query
1567 * abc [O] Address of character-width structure
1569 * NOTES
1570 * Only works with TrueType fonts
1572 * RETURNS
1573 * Success: TRUE
1574 * Failure: FALSE
1576 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1577 LPABC abc )
1579 DC *dc = DC_GetDCPtr(hdc);
1580 int i;
1581 GLYPHMETRICS gm;
1582 BOOL ret = FALSE;
1584 if(dc->gdiFont) {
1585 for (i=firstChar;i<=lastChar;i++) {
1586 GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1587 abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1588 abc[i-firstChar].abcB = gm.gmBlackBoxX;
1589 abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1591 ret = TRUE;
1593 GDI_ReleaseObj(hdc);
1594 return ret;
1598 /***********************************************************************
1599 * GetGlyphOutline (GDI.309)
1601 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1602 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1603 LPVOID lpBuffer, const MAT2 *lpmat2 )
1605 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1606 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1607 return (DWORD)-1; /* failure */
1611 /***********************************************************************
1612 * GetGlyphOutlineA (GDI32.@)
1614 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1615 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1616 LPVOID lpBuffer, const MAT2 *lpmat2 )
1618 LPWSTR p = NULL;
1619 DWORD ret;
1620 UINT c;
1622 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1623 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1624 c = p[0];
1625 } else
1626 c = uChar;
1627 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1628 lpmat2);
1629 if(p)
1630 HeapFree(GetProcessHeap(), 0, p);
1631 return ret;
1634 /***********************************************************************
1635 * GetGlyphOutlineW (GDI32.@)
1637 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1638 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1639 LPVOID lpBuffer, const MAT2 *lpmat2 )
1641 DC *dc = DC_GetDCPtr(hdc);
1642 DWORD ret;
1644 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1645 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1647 if(!dc) return GDI_ERROR;
1649 if(dc->gdiFont)
1650 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1651 cbBuffer, lpBuffer, lpmat2);
1652 else
1653 ret = GDI_ERROR;
1655 GDI_ReleaseObj(hdc);
1656 return ret;
1660 /***********************************************************************
1661 * CreateScalableFontResourceA (GDI32.@)
1663 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1664 LPCSTR lpszResourceFile,
1665 LPCSTR lpszFontFile,
1666 LPCSTR lpszCurrentPath )
1668 HANDLE f;
1670 /* fHidden=1 - only visible for the calling app, read-only, not
1671 * enumbered with EnumFonts/EnumFontFamilies
1672 * lpszCurrentPath can be NULL
1674 FIXME("(%ld,%s,%s,%s): stub\n",
1675 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1676 debugstr_a(lpszCurrentPath) );
1678 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1679 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1680 CloseHandle(f);
1681 SetLastError(ERROR_FILE_EXISTS);
1682 return FALSE;
1684 return FALSE; /* create failed */
1687 /***********************************************************************
1688 * CreateScalableFontResourceW (GDI32.@)
1690 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1691 LPCWSTR lpszResourceFile,
1692 LPCWSTR lpszFontFile,
1693 LPCWSTR lpszCurrentPath )
1695 FIXME("(%ld,%p,%p,%p): stub\n",
1696 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1697 return FALSE; /* create failed */
1701 /*************************************************************************
1702 * GetRasterizerCaps (GDI32.@)
1704 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1706 lprs->nSize = sizeof(RASTERIZER_STATUS);
1707 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1708 lprs->nLanguageID = 0;
1709 return TRUE;
1713 /*************************************************************************
1714 * GetKerningPairsA (GDI32.@)
1716 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1717 LPKERNINGPAIR lpKerningPairs )
1719 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1723 /*************************************************************************
1724 * GetKerningPairsW (GDI32.@)
1726 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1727 LPKERNINGPAIR lpKerningPairs )
1729 int i;
1730 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1731 for (i = 0; i < cPairs; i++)
1732 lpKerningPairs[i].iKernAmount = 0;
1733 return 0;
1736 /*************************************************************************
1737 * TranslateCharsetInfo [GDI32.@]
1739 * Fills a CHARSETINFO structure for a character set, code page, or
1740 * font. This allows making the correspondance between different labelings
1741 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1742 * of the same encoding.
1744 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1745 * only one codepage should be set in *lpSrc.
1747 * RETURNS
1748 * TRUE on success, FALSE on failure.
1751 BOOL WINAPI TranslateCharsetInfo(
1752 LPDWORD lpSrc, /* [in]
1753 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1754 if flags == TCI_SRCCHARSET: a character set value
1755 if flags == TCI_SRCCODEPAGE: a code page value
1757 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1758 DWORD flags /* [in] determines interpretation of lpSrc */
1760 int index = 0;
1761 switch (flags) {
1762 case TCI_SRCFONTSIG:
1763 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1764 break;
1765 case TCI_SRCCODEPAGE:
1766 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1767 break;
1768 case TCI_SRCCHARSET:
1769 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1770 break;
1771 default:
1772 return FALSE;
1774 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1775 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1776 return TRUE;
1779 /*************************************************************************
1780 * GetFontLanguageInfo (GDI32.@)
1782 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1784 FONTSIGNATURE fontsig;
1785 static const DWORD GCP_DBCS_MASK=0x003F0000,
1786 GCP_DIACRITIC_MASK=0x00000000,
1787 FLI_GLYPHS_MASK=0x00000000,
1788 GCP_GLYPHSHAPE_MASK=0x00000040,
1789 GCP_KASHIDA_MASK=0x00000000,
1790 GCP_LIGATE_MASK=0x00000000,
1791 GCP_USEKERNING_MASK=0x00000000,
1792 GCP_REORDER_MASK=0x00000060;
1794 DWORD result=0;
1796 GetTextCharsetInfo( hdc, &fontsig, 0 );
1797 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1799 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1800 result|=GCP_DBCS;
1802 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1803 result|=GCP_DIACRITIC;
1805 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1806 result|=FLI_GLYPHS;
1808 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1809 result|=GCP_GLYPHSHAPE;
1811 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1812 result|=GCP_KASHIDA;
1814 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1815 result|=GCP_LIGATE;
1817 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1818 result|=GCP_USEKERNING;
1820 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1821 result|=GCP_REORDER;
1823 return result;
1827 /*************************************************************************
1828 * GetFontData [GDI32.@] Retrieve data for TrueType font
1830 * RETURNS
1832 * success: Number of bytes returned
1833 * failure: GDI_ERROR
1835 * NOTES
1837 * Calls SetLastError()
1840 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1841 LPVOID buffer, DWORD length)
1843 DC *dc = DC_GetDCPtr(hdc);
1844 DWORD ret = GDI_ERROR;
1846 if(!dc) return GDI_ERROR;
1848 if(dc->gdiFont)
1849 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1851 GDI_ReleaseObj(hdc);
1852 return ret;
1855 /*************************************************************************
1856 * GetGlyphIndicesA [GDI32.@]
1858 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1859 LPWORD pgi, DWORD flags)
1861 DWORD ret;
1862 WCHAR *lpstrW;
1863 INT countW;
1865 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1866 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1868 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1869 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1870 HeapFree(GetProcessHeap(), 0, lpstrW);
1872 return ret;
1875 /*************************************************************************
1876 * GetGlyphIndicesW [GDI32.@]
1878 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1879 LPWORD pgi, DWORD flags)
1881 DC *dc = DC_GetDCPtr(hdc);
1882 DWORD ret = GDI_ERROR;
1884 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1885 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1887 if(!dc) return GDI_ERROR;
1889 if(dc->gdiFont)
1890 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1892 GDI_ReleaseObj(hdc);
1893 return ret;
1896 /*************************************************************************
1897 * GetCharacterPlacementA [GDI32.@]
1899 * NOTES:
1900 * the web browser control of ie4 calls this with dwFlags=0
1902 DWORD WINAPI
1903 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1904 INT nMaxExtent, GCP_RESULTSA *lpResults,
1905 DWORD dwFlags)
1907 WCHAR *lpStringW;
1908 INT uCountW, i;
1909 GCP_RESULTSW resultsW;
1910 DWORD ret;
1911 UINT font_cp;
1913 TRACE("%s, %d, %d, 0x%08lx\n",
1914 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1916 /* both structs are equal in size */
1917 memcpy(&resultsW, lpResults, sizeof(resultsW));
1919 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1920 if(lpResults->lpOutString)
1921 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1923 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1925 if(lpResults->lpOutString) {
1926 if(font_cp != CP_SYMBOL)
1927 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1928 lpResults->lpOutString, uCount, NULL, NULL );
1929 else
1930 for(i = 0; i < uCount; i++)
1931 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1934 HeapFree(GetProcessHeap(), 0, lpStringW);
1935 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1937 return ret;
1940 /*************************************************************************
1941 * GetCharacterPlacementW [GDI32.@]
1943 * Retrieve information about a string. This includes the width, reordering,
1944 * Glyphing and so on.
1946 * RETURNS
1948 * The width and height of the string if succesful, 0 if failed.
1950 * BUGS
1952 * All flags except GCP_REORDER are not yet implemented.
1953 * Reordering is not 100% complient to the Windows BiDi method.
1954 * Caret positioning is not yet implemented.
1955 * Classes are not yet implemented.
1958 DWORD WINAPI
1959 GetCharacterPlacementW(
1960 HDC hdc, /* [in] Device context for which the rendering is to be done */
1961 LPCWSTR lpString, /* [in] The string for which information is to be returned */
1962 INT uCount, /* [in] Number of WORDS in string. */
1963 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
1964 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
1965 DWORD dwFlags /* [in] Flags specifying how to process the string */
1968 DWORD ret=0;
1969 SIZE size;
1970 UINT i, nSet;
1972 TRACE("%s, %d, %d, 0x%08lx\n",
1973 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
1975 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1976 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1977 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
1978 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
1979 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
1981 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
1982 if(lpResults->lpCaretPos) FIXME("caret positions not implemented\n");
1983 if(lpResults->lpClass) FIXME("classes not implemented\n");
1985 nSet = (UINT)uCount;
1986 if(nSet > lpResults->nGlyphs)
1987 nSet = lpResults->nGlyphs;
1989 /* return number of initialized fields */
1990 lpResults->nGlyphs = nSet;
1992 if(dwFlags==0)
1994 /* Treat the case where no special handling was requested in a fastpath way */
1995 /* copy will do if the GCP_REORDER flag is not set */
1996 if(lpResults->lpOutString)
1997 for(i=0; i<nSet && lpString[i]!=0; ++i )
1998 lpResults->lpOutString[i]=lpString[i];
2000 if(lpResults->lpOrder)
2002 for(i = 0; i < nSet; i++)
2003 lpResults->lpOrder[i] = i;
2007 if((dwFlags&GCP_REORDER)!=0)
2009 WORD *pwCharType;
2010 int run_end;
2011 /* Keep a static table that translates the C2 types to something meaningful */
2012 /* 1 - left to right
2013 * -1 - right to left
2014 * 0 - neutral
2016 static const int chardir[]={ 0, 1, -1, 1, 0, 0, -1, 0, 0, 0, 0, 0 };
2018 WARN("The BiDi algorythm doesn't conform to Windows' yet\n");
2019 if( (pwCharType=HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)))==NULL )
2021 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2023 return 0;
2026 /* Fill in the order array with directionality values */
2027 GetStringTypeW(CT_CTYPE2, lpString, uCount, pwCharType);
2029 /* The complete and correct (at least according to MS) BiDi algorythm is not
2030 * yet implemented here. Instead, we just make sure that consecutive runs of
2031 * the same direction (or neutral) are ordered correctly. We also assign Neutrals
2032 * that are between runs of opposing directions the base (ok, always LTR) dir.
2033 * While this is a LONG way from a BiDi algorithm, it does produce more or less
2034 * readable results.
2036 for( i=0; i<uCount; i+=run_end )
2038 for( run_end=1; i+run_end<uCount &&
2039 (chardir[pwCharType[i+run_end]]==chardir[pwCharType[i]] ||
2040 chardir[pwCharType[i+run_end]]==0); ++run_end )
2043 if( chardir[pwCharType[i]]==1 || chardir[pwCharType[i]]==0 )
2045 /* A LTR run */
2046 if(lpResults->lpOutString)
2048 int j;
2049 for( j=0; j<run_end; j++ )
2051 lpResults->lpOutString[i+j]=lpString[i+j];
2055 if(lpResults->lpOrder)
2057 int j;
2058 for( j=0; j<run_end; j++ )
2059 lpResults->lpOrder[i+j] = i+j;
2061 } else
2063 /* A RTL run */
2065 /* Since, at this stage, the paragraph context is always LTR,
2066 * remove any neutrals from the end of this run.
2068 if( chardir[pwCharType[i]]!=0 )
2069 while( chardir[pwCharType[i+run_end-1]]==0 )
2070 --run_end;
2072 if(lpResults->lpOutString)
2074 int j;
2075 for( j=0; j<run_end; j++ )
2077 lpResults->lpOutString[i+j]=lpString[i+run_end-j-1];
2081 if(lpResults->lpOrder)
2083 int j;
2084 for( j=0; j<run_end; j++ )
2085 lpResults->lpOrder[i+j] = i+run_end-j-1;
2090 HeapFree(GetProcessHeap(), 0, pwCharType);
2093 /* FIXME: Will use the placement chars */
2094 if (lpResults->lpDx)
2096 int c;
2097 for (i = 0; i < nSet; i++)
2099 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2100 lpResults->lpDx[i]= c;
2104 if(lpResults->lpGlyphs)
2105 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2107 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2108 ret = MAKELONG(size.cx, size.cy);
2110 return ret;
2113 /*************************************************************************
2114 * GetCharABCWidthsFloatA [GDI32.@]
2116 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2117 LPABCFLOAT lpABCF)
2119 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2120 return 0;
2123 /*************************************************************************
2124 * GetCharABCWidthsFloatW [GDI32.@]
2126 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2127 UINT iLastChar, LPABCFLOAT lpABCF)
2129 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2130 return 0;
2133 /*************************************************************************
2134 * GetCharWidthFloatA [GDI32.@]
2136 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2137 UINT iLastChar, PFLOAT pxBuffer)
2139 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2140 return 0;
2143 /*************************************************************************
2144 * GetCharWidthFloatW [GDI32.@]
2146 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2147 UINT iLastChar, PFLOAT pxBuffer)
2149 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2150 return 0;
2154 /***********************************************************************
2156 * Font Resource API *
2158 ***********************************************************************/
2160 /***********************************************************************
2161 * AddFontResourceA (GDI32.@)
2163 INT WINAPI AddFontResourceA( LPCSTR str )
2165 return AddFontResourceExA( str, 0, NULL);
2168 /***********************************************************************
2169 * AddFontResourceW (GDI32.@)
2171 INT WINAPI AddFontResourceW( LPCWSTR str )
2173 return AddFontResourceExW(str, 0, NULL);
2177 /***********************************************************************
2178 * AddFontResourceExA (GDI32.@)
2180 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2182 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2183 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2184 INT ret;
2186 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2187 ret = AddFontResourceExW(strW, fl, pdv);
2188 HeapFree(GetProcessHeap(), 0, strW);
2189 return ret;
2192 /***********************************************************************
2193 * AddFontResourceExW (GDI32.@)
2195 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2197 return WineEngAddFontResourceEx(str, fl, pdv);
2200 /***********************************************************************
2201 * RemoveFontResourceA (GDI32.@)
2203 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2205 return RemoveFontResourceExA(str, 0, 0);
2208 /***********************************************************************
2209 * RemoveFontResourceW (GDI32.@)
2211 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2213 return RemoveFontResourceExW(str, 0, 0);
2216 /***********************************************************************
2217 * RemoveFontResourceExA (GDI32.@)
2219 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2221 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2222 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2223 INT ret;
2225 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2226 ret = RemoveFontResourceExW(strW, fl, pdv);
2227 HeapFree(GetProcessHeap(), 0, strW);
2228 return ret;
2231 /***********************************************************************
2232 * RemoveFontResourceExW (GDI32.@)
2234 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2236 return WineEngRemoveFontResourceEx(str, fl, pdv);