Moved (stub) implementation of GetKerningPairs from ascii to unicode.
[wine/multimedia.git] / objects / font.c
blob81139eba5c2d4f4fb309e6e8569044dfd092a98d
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)
863 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count,
864 NULL, NULL);
865 else
866 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
867 HeapFree( GetProcessHeap(), 0, nameW );
868 return res;
871 /***********************************************************************
872 * GetTextFaceW (GDI32.@)
874 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
876 FONTOBJ *font;
877 INT ret = 0;
879 DC * dc = DC_GetDCPtr( hdc );
880 if (!dc) return 0;
882 if(dc->gdiFont)
883 ret = WineEngGetTextFace(dc->gdiFont, count, name);
884 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
886 if (name)
888 lstrcpynW( name, font->logfont.lfFaceName, count );
889 ret = strlenW(name);
891 else ret = strlenW(font->logfont.lfFaceName) + 1;
892 GDI_ReleaseObj( dc->hFont );
894 GDI_ReleaseObj( hdc );
895 return ret;
899 /***********************************************************************
900 * GetTextExtentPoint32A (GDI32.@)
902 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
903 LPSIZE size )
905 BOOL ret = FALSE;
906 INT wlen;
907 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
909 if (p) {
910 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
911 HeapFree( GetProcessHeap(), 0, p );
914 TRACE("(%p %s %d %p): returning %ld x %ld\n",
915 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
916 return ret;
920 /***********************************************************************
921 * GetTextExtentPoint32W [GDI32.@] Computes width/height for a string
923 * Computes width and height of the specified string.
925 * RETURNS
926 * Success: TRUE
927 * Failure: FALSE
929 BOOL WINAPI GetTextExtentPoint32W(
930 HDC hdc, /* [in] Handle of device context */
931 LPCWSTR str, /* [in] Address of text string */
932 INT count, /* [in] Number of characters in string */
933 LPSIZE size) /* [out] Address of structure for string size */
935 BOOL ret = FALSE;
936 DC * dc = DC_GetDCPtr( hdc );
937 if (!dc) return FALSE;
939 if(dc->gdiFont) {
940 ret = WineEngGetTextExtentPoint(dc->gdiFont, str, count, size);
941 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
942 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
944 else if(dc->funcs->pGetTextExtentPoint)
945 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, str, count, size );
947 GDI_ReleaseObj( hdc );
949 TRACE("(%p %s %d %p): returning %ld x %ld\n",
950 hdc, debugstr_wn (str, count), count, size, size->cx, size->cy );
951 return ret;
954 /***********************************************************************
955 * GetTextExtentPointI [GDI32.@]
957 * Computes width and height of the array of glyph indices.
959 * RETURNS
960 * Success: TRUE
961 * Failure: FALSE
963 BOOL WINAPI GetTextExtentPointI(
964 HDC hdc, /* [in] Handle of device context */
965 const WORD *indices, /* [in] Address of glyph index array */
966 INT count, /* [in] Number of glyphs in array */
967 LPSIZE size) /* [out] Address of structure for string size */
969 BOOL ret = FALSE;
970 DC * dc = DC_GetDCPtr( hdc );
971 if (!dc) return FALSE;
973 if(dc->gdiFont) {
974 ret = WineEngGetTextExtentPointI(dc->gdiFont, indices, count, size);
975 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
976 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
978 else if(dc->funcs->pGetTextExtentPoint) {
979 FIXME("calling GetTextExtentPoint\n");
980 ret = dc->funcs->pGetTextExtentPoint( dc->physDev, (LPCWSTR)indices, count, size );
983 GDI_ReleaseObj( hdc );
985 TRACE("(%p %p %d %p): returning %ld x %ld\n",
986 hdc, indices, count, size, size->cx, size->cy );
987 return ret;
991 /***********************************************************************
992 * GetTextExtentPointA (GDI32.@)
994 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
995 LPSIZE size )
997 TRACE("not bug compatible.\n");
998 return GetTextExtentPoint32A( hdc, str, count, size );
1001 /***********************************************************************
1002 * GetTextExtentPointW (GDI32.@)
1004 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1005 LPSIZE size )
1007 TRACE("not bug compatible.\n");
1008 return GetTextExtentPoint32W( hdc, str, count, size );
1012 /***********************************************************************
1013 * GetTextExtentExPointA (GDI32.@)
1015 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1016 INT maxExt, LPINT lpnFit,
1017 LPINT alpDx, LPSIZE size )
1019 BOOL ret;
1020 INT wlen;
1021 LPWSTR p = FONT_mbtowc( hdc, str, count, &wlen, NULL);
1022 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, alpDx, size);
1023 HeapFree( GetProcessHeap(), 0, p );
1024 return ret;
1028 /***********************************************************************
1029 * GetTextExtentExPointW (GDI32.@)
1031 * Return the size of the string as it would be if it was output properly by
1032 * e.g. TextOut.
1034 * This should include
1035 * - Intercharacter spacing
1036 * - justification spacing (not yet done)
1037 * - kerning? see below
1039 * Kerning. Since kerning would be carried out by the rendering code it should
1040 * be done by the driver. However they don't support it yet. Also I am not
1041 * yet persuaded that (certainly under Win95) any kerning is actually done.
1043 * str: According to MSDN this should be null-terminated. That is not true; a
1044 * null will not terminate it early.
1045 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1046 * than count. I have seen it be either the size of the full string or
1047 * 1 less than the size of the full string. I have not seen it bear any
1048 * resemblance to the portion that would fit.
1049 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1050 * trailing intercharacter spacing and any trailing justification.
1052 * FIXME
1053 * Currently we do this by measuring each character etc. We should do it by
1054 * passing the request to the driver, perhaps by extending the
1055 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1056 * thinking about kerning issues and rounding issues in the justification.
1059 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1060 INT maxExt, LPINT lpnFit,
1061 LPINT alpDx, LPSIZE size )
1063 int index, nFit, extent;
1064 SIZE tSize;
1065 BOOL ret = FALSE;
1067 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1069 size->cx = size->cy = nFit = extent = 0;
1070 for(index = 0; index < count; index++)
1072 if(!GetTextExtentPoint32W( hdc, str, 1, &tSize )) goto done;
1073 /* GetTextExtentPoint includes intercharacter spacing. */
1074 /* FIXME - justification needs doing yet. Remember that the base
1075 * data will not be in logical coordinates.
1077 extent += tSize.cx;
1078 if( !lpnFit || extent <= maxExt )
1079 /* It is allowed to be equal. */
1081 nFit++;
1082 if( alpDx ) alpDx[index] = extent;
1084 if( tSize.cy > size->cy ) size->cy = tSize.cy;
1085 str++;
1087 size->cx = extent;
1088 if(lpnFit) *lpnFit = nFit;
1089 ret = TRUE;
1091 TRACE("returning %d %ld x %ld\n",nFit,size->cx,size->cy);
1093 done:
1094 return ret;
1097 /***********************************************************************
1098 * GetTextMetricsA (GDI32.@)
1100 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1102 TEXTMETRICW tm32;
1104 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1105 FONT_TextMetricWToA( &tm32, metrics );
1106 return TRUE;
1109 /***********************************************************************
1110 * GetTextMetricsW (GDI32.@)
1112 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1114 BOOL ret = FALSE;
1115 DC * dc = DC_GetDCPtr( hdc );
1116 if (!dc) return FALSE;
1118 if (dc->gdiFont)
1119 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1120 else if (dc->funcs->pGetTextMetrics)
1121 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1123 if (ret)
1125 /* device layer returns values in device units
1126 * therefore we have to convert them to logical */
1128 #define WDPTOLP(x) ((x<0)? \
1129 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1130 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1131 #define HDPTOLP(y) ((y<0)? \
1132 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1133 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1135 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1136 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1137 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1138 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1139 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1140 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1141 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1142 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1143 ret = TRUE;
1144 #undef WDPTOLP
1145 #undef HDPTOLP
1146 TRACE("text metrics:\n"
1147 " Weight = %03li\t FirstChar = %i\t AveCharWidth = %li\n"
1148 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %li\n"
1149 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %li\n"
1150 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1151 " PitchAndFamily = %02x\n"
1152 " --------------------\n"
1153 " InternalLeading = %li\n"
1154 " Ascent = %li\n"
1155 " Descent = %li\n"
1156 " Height = %li\n",
1157 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1158 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1159 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1160 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1161 metrics->tmPitchAndFamily,
1162 metrics->tmInternalLeading,
1163 metrics->tmAscent,
1164 metrics->tmDescent,
1165 metrics->tmHeight );
1167 GDI_ReleaseObj( hdc );
1168 return ret;
1172 /***********************************************************************
1173 * GetOutlineTextMetrics [GDI.308] Gets metrics for TrueType fonts.
1175 * NOTES
1176 * lpOTM should be LPOUTLINETEXTMETRIC
1178 * RETURNS
1179 * Success: Non-zero or size of required buffer
1180 * Failure: 0
1182 UINT16 WINAPI GetOutlineTextMetrics16(
1183 HDC16 hdc, /* [in] Handle of device context */
1184 UINT16 cbData, /* [in] Size of metric data array */
1185 LPOUTLINETEXTMETRIC16 lpOTM) /* [out] Address of metric data array */
1187 FIXME("(%04x,%04x,%p): stub\n", hdc,cbData,lpOTM);
1188 return 0;
1192 /***********************************************************************
1193 * GetOutlineTextMetricsA (GDI32.@)
1194 * Gets metrics for TrueType fonts.
1197 * RETURNS
1198 * Success: Non-zero or size of required buffer
1199 * Failure: 0
1201 UINT WINAPI GetOutlineTextMetricsA(
1202 HDC hdc, /* [in] Handle of device context */
1203 UINT cbData, /* [in] Size of metric data array */
1204 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1206 char buf[512], *ptr;
1207 UINT ret, needed;
1208 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1209 INT left, len;
1211 if((ret = GetOutlineTextMetricsW(hdc, sizeof(buf), lpOTMW)) == 0) {
1212 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1213 return 0;
1214 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1215 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1218 needed = sizeof(OUTLINETEXTMETRICA);
1219 if(lpOTMW->otmpFamilyName)
1220 needed += WideCharToMultiByte(CP_ACP, 0,
1221 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1222 NULL, 0, NULL, NULL);
1223 if(lpOTMW->otmpFaceName)
1224 needed += WideCharToMultiByte(CP_ACP, 0,
1225 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1226 NULL, 0, NULL, NULL);
1227 if(lpOTMW->otmpStyleName)
1228 needed += WideCharToMultiByte(CP_ACP, 0,
1229 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1230 NULL, 0, NULL, NULL);
1231 if(lpOTMW->otmpFullName)
1232 needed += WideCharToMultiByte(CP_ACP, 0,
1233 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1234 NULL, 0, NULL, NULL);
1236 if(!lpOTM) {
1237 ret = needed;
1238 goto end;
1241 if(needed > cbData) {
1242 ret = 0;
1243 goto end;
1247 lpOTM->otmSize = needed;
1248 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &lpOTM->otmTextMetrics );
1249 lpOTM->otmFiller = 0;
1250 lpOTM->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1251 lpOTM->otmfsSelection = lpOTMW->otmfsSelection;
1252 lpOTM->otmfsType = lpOTMW->otmfsType;
1253 lpOTM->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1254 lpOTM->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1255 lpOTM->otmItalicAngle = lpOTMW->otmItalicAngle;
1256 lpOTM->otmEMSquare = lpOTMW->otmEMSquare;
1257 lpOTM->otmAscent = lpOTMW->otmAscent;
1258 lpOTM->otmDescent = lpOTMW->otmDescent;
1259 lpOTM->otmLineGap = lpOTMW->otmLineGap;
1260 lpOTM->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1261 lpOTM->otmsXHeight = lpOTMW->otmsXHeight;
1262 lpOTM->otmrcFontBox = lpOTMW->otmrcFontBox;
1263 lpOTM->otmMacAscent = lpOTMW->otmMacAscent;
1264 lpOTM->otmMacDescent = lpOTMW->otmMacDescent;
1265 lpOTM->otmMacLineGap = lpOTMW->otmMacLineGap;
1266 lpOTM->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1267 lpOTM->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1268 lpOTM->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1269 lpOTM->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1270 lpOTM->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1271 lpOTM->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1272 lpOTM->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1273 lpOTM->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1274 lpOTM->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1277 ptr = (char*)(lpOTM + 1);
1278 left = needed - sizeof(*lpOTM);
1280 if(lpOTMW->otmpFamilyName) {
1281 lpOTM->otmpFamilyName = (LPSTR)(ptr - (char*)lpOTM);
1282 len = WideCharToMultiByte(CP_ACP, 0,
1283 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1284 ptr, left, NULL, NULL);
1285 left -= len;
1286 ptr += len;
1287 } else
1288 lpOTM->otmpFamilyName = 0;
1290 if(lpOTMW->otmpFaceName) {
1291 lpOTM->otmpFaceName = (LPSTR)(ptr - (char*)lpOTM);
1292 len = WideCharToMultiByte(CP_ACP, 0,
1293 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1294 ptr, left, NULL, NULL);
1295 left -= len;
1296 ptr += len;
1297 } else
1298 lpOTM->otmpFaceName = 0;
1300 if(lpOTMW->otmpStyleName) {
1301 lpOTM->otmpStyleName = (LPSTR)(ptr - (char*)lpOTM);
1302 len = WideCharToMultiByte(CP_ACP, 0,
1303 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1304 ptr, left, NULL, NULL);
1305 left -= len;
1306 ptr += len;
1307 } else
1308 lpOTM->otmpStyleName = 0;
1310 if(lpOTMW->otmpFullName) {
1311 lpOTM->otmpFullName = (LPSTR)(ptr - (char*)lpOTM);
1312 len = WideCharToMultiByte(CP_ACP, 0,
1313 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1314 ptr, left, NULL, NULL);
1315 left -= len;
1316 } else
1317 lpOTM->otmpFullName = 0;
1319 assert(left == 0);
1321 ret = needed;
1323 end:
1324 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1325 HeapFree(GetProcessHeap(), 0, lpOTMW);
1327 return ret;
1331 /***********************************************************************
1332 * GetOutlineTextMetricsW [GDI32.@]
1334 UINT WINAPI GetOutlineTextMetricsW(
1335 HDC hdc, /* [in] Handle of device context */
1336 UINT cbData, /* [in] Size of metric data array */
1337 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1339 DC *dc = DC_GetDCPtr( hdc );
1340 UINT ret;
1342 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1343 if(!dc) return 0;
1345 if(dc->gdiFont) {
1346 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, lpOTM);
1347 if(ret && ret <= cbData) {
1348 #define WDPTOLP(x) ((x<0)? \
1349 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1350 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1351 #define HDPTOLP(y) ((y<0)? \
1352 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1353 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1355 lpOTM->otmTextMetrics.tmHeight = HDPTOLP(lpOTM->otmTextMetrics.tmHeight);
1356 lpOTM->otmTextMetrics.tmAscent = HDPTOLP(lpOTM->otmTextMetrics.tmAscent);
1357 lpOTM->otmTextMetrics.tmDescent = HDPTOLP(lpOTM->otmTextMetrics.tmDescent);
1358 lpOTM->otmTextMetrics.tmInternalLeading = HDPTOLP(lpOTM->otmTextMetrics.tmInternalLeading);
1359 lpOTM->otmTextMetrics.tmExternalLeading = HDPTOLP(lpOTM->otmTextMetrics.tmExternalLeading);
1360 lpOTM->otmTextMetrics.tmAveCharWidth = WDPTOLP(lpOTM->otmTextMetrics.tmAveCharWidth);
1361 lpOTM->otmTextMetrics.tmMaxCharWidth = WDPTOLP(lpOTM->otmTextMetrics.tmMaxCharWidth);
1362 lpOTM->otmTextMetrics.tmOverhang = WDPTOLP(lpOTM->otmTextMetrics.tmOverhang);
1363 lpOTM->otmAscent = HDPTOLP(lpOTM->otmAscent);
1364 lpOTM->otmDescent = HDPTOLP(lpOTM->otmDescent);
1365 lpOTM->otmLineGap = HDPTOLP(lpOTM->otmLineGap);
1366 lpOTM->otmsCapEmHeight = HDPTOLP(lpOTM->otmsCapEmHeight);
1367 lpOTM->otmsXHeight = HDPTOLP(lpOTM->otmsXHeight);
1368 lpOTM->otmrcFontBox.top = HDPTOLP(lpOTM->otmrcFontBox.top);
1369 lpOTM->otmrcFontBox.bottom = HDPTOLP(lpOTM->otmrcFontBox.bottom);
1370 lpOTM->otmrcFontBox.left = WDPTOLP(lpOTM->otmrcFontBox.left);
1371 lpOTM->otmrcFontBox.right = WDPTOLP(lpOTM->otmrcFontBox.right);
1372 lpOTM->otmMacAscent = HDPTOLP(lpOTM->otmMacAscent);
1373 lpOTM->otmMacDescent = HDPTOLP(lpOTM->otmMacDescent);
1374 lpOTM->otmMacLineGap = HDPTOLP(lpOTM->otmMacLineGap);
1375 lpOTM->otmptSubscriptSize.x = WDPTOLP(lpOTM->otmptSubscriptSize.x);
1376 lpOTM->otmptSubscriptSize.y = HDPTOLP(lpOTM->otmptSubscriptSize.y);
1377 lpOTM->otmptSubscriptOffset.x = WDPTOLP(lpOTM->otmptSubscriptOffset.x);
1378 lpOTM->otmptSubscriptOffset.y = HDPTOLP(lpOTM->otmptSubscriptOffset.y);
1379 lpOTM->otmptSuperscriptSize.x = WDPTOLP(lpOTM->otmptSuperscriptSize.x);
1380 lpOTM->otmptSuperscriptSize.y = HDPTOLP(lpOTM->otmptSuperscriptSize.y);
1381 lpOTM->otmptSuperscriptOffset.x = WDPTOLP(lpOTM->otmptSuperscriptOffset.x);
1382 lpOTM->otmptSuperscriptOffset.y = HDPTOLP(lpOTM->otmptSuperscriptOffset.y);
1383 lpOTM->otmsStrikeoutSize = HDPTOLP(lpOTM->otmsStrikeoutSize);
1384 lpOTM->otmsStrikeoutPosition = HDPTOLP(lpOTM->otmsStrikeoutPosition);
1385 lpOTM->otmsUnderscoreSize = HDPTOLP(lpOTM->otmsUnderscoreSize);
1386 lpOTM->otmsUnderscorePosition = HDPTOLP(lpOTM->otmsUnderscorePosition);
1387 #undef WDPTOLP
1388 #undef HDPTOLP
1392 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1393 but really this should just be a return 0. */
1395 ret = sizeof(*lpOTM);
1396 if (lpOTM) {
1397 if(cbData < ret)
1398 ret = 0;
1399 else {
1400 memset(lpOTM, 0, ret);
1401 lpOTM->otmSize = sizeof(*lpOTM);
1402 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1404 Further fill of the structure not implemented,
1405 Needs real values for the structure members
1410 GDI_ReleaseObj(hdc);
1411 return ret;
1415 /***********************************************************************
1416 * GetCharWidthW (GDI32.@)
1417 * GetCharWidth32W (GDI32.@)
1419 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1420 LPINT buffer )
1422 UINT i, extra;
1423 BOOL ret = FALSE;
1424 DC * dc = DC_GetDCPtr( hdc );
1425 if (!dc) return FALSE;
1427 if (dc->gdiFont)
1428 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1429 else if (dc->funcs->pGetCharWidth)
1430 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1432 if (ret)
1434 /* convert device units to logical */
1436 extra = dc->vportExtX >> 1;
1437 for( i = firstChar; i <= lastChar; i++, buffer++ )
1438 *buffer = (*buffer * dc->wndExtX + extra) / dc->vportExtX;
1439 ret = TRUE;
1441 GDI_ReleaseObj( hdc );
1442 return ret;
1446 /***********************************************************************
1447 * GetCharWidthA (GDI32.@)
1448 * GetCharWidth32A (GDI32.@)
1450 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1451 LPINT buffer )
1453 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1454 LPSTR str;
1455 LPWSTR wstr;
1456 BOOL ret = TRUE;
1458 if(count <= 0) return FALSE;
1460 str = HeapAlloc(GetProcessHeap(), 0, count);
1461 for(i = 0; i < count; i++)
1462 str[i] = (BYTE)(firstChar + i);
1464 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1466 for(i = 0; i < wlen; i++)
1468 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1470 ret = FALSE;
1471 break;
1473 buffer++;
1476 HeapFree(GetProcessHeap(), 0, str);
1477 HeapFree(GetProcessHeap(), 0, wstr);
1479 return ret;
1483 /* FIXME: all following APIs ******************************************/
1486 /***********************************************************************
1487 * SetMapperFlags (GDI32.@)
1489 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
1491 DC *dc = DC_GetDCPtr( hDC );
1492 DWORD ret = 0;
1493 if(!dc) return 0;
1494 if(dc->funcs->pSetMapperFlags)
1495 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
1496 else
1497 FIXME("(%p, 0x%08lx): stub - harmless\n", hDC, dwFlag);
1498 GDI_ReleaseObj( hDC );
1499 return ret;
1502 /***********************************************************************
1503 * GetAspectRatioFilterEx (GDI.486)
1505 BOOL16 WINAPI GetAspectRatioFilterEx16( HDC16 hdc, LPSIZE16 pAspectRatio )
1507 FIXME("(%04x, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1508 return FALSE;
1511 /***********************************************************************
1512 * GetAspectRatioFilterEx (GDI32.@)
1514 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
1516 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
1517 return FALSE;
1521 /***********************************************************************
1522 * GetCharABCWidthsA (GDI32.@)
1524 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
1525 LPABC abc )
1527 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1528 LPSTR str;
1529 LPWSTR wstr;
1530 BOOL ret = TRUE;
1532 if(count <= 0) return FALSE;
1534 str = HeapAlloc(GetProcessHeap(), 0, count);
1535 for(i = 0; i < count; i++)
1536 str[i] = (BYTE)(firstChar + i);
1538 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1540 for(i = 0; i < wlen; i++)
1542 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
1544 ret = FALSE;
1545 break;
1547 abc++;
1550 HeapFree(GetProcessHeap(), 0, str);
1551 HeapFree(GetProcessHeap(), 0, wstr);
1553 return ret;
1557 /******************************************************************************
1558 * GetCharABCWidthsW [GDI32.@] Retrieves widths of characters in range
1560 * PARAMS
1561 * hdc [I] Handle of device context
1562 * firstChar [I] First character in range to query
1563 * lastChar [I] Last character in range to query
1564 * abc [O] Address of character-width structure
1566 * NOTES
1567 * Only works with TrueType fonts
1569 * RETURNS
1570 * Success: TRUE
1571 * Failure: FALSE
1573 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
1574 LPABC abc )
1576 DC *dc = DC_GetDCPtr(hdc);
1577 int i;
1578 GLYPHMETRICS gm;
1579 BOOL ret = FALSE;
1581 if(dc->gdiFont) {
1582 for (i=firstChar;i<=lastChar;i++) {
1583 GetGlyphOutlineW(hdc, i, GGO_METRICS, &gm, 0, NULL, NULL);
1584 abc[i-firstChar].abcA = gm.gmptGlyphOrigin.x;
1585 abc[i-firstChar].abcB = gm.gmBlackBoxX;
1586 abc[i-firstChar].abcC = gm.gmCellIncX - gm.gmptGlyphOrigin.x - gm.gmBlackBoxX;
1588 ret = TRUE;
1590 GDI_ReleaseObj(hdc);
1591 return ret;
1595 /***********************************************************************
1596 * GetGlyphOutline (GDI.309)
1598 DWORD WINAPI GetGlyphOutline16( HDC16 hdc, UINT16 uChar, UINT16 fuFormat,
1599 LPGLYPHMETRICS16 lpgm, DWORD cbBuffer,
1600 LPVOID lpBuffer, const MAT2 *lpmat2 )
1602 FIXME("(%04x, '%c', %04x, %p, %ld, %p, %p): stub\n",
1603 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1604 return (DWORD)-1; /* failure */
1608 /***********************************************************************
1609 * GetGlyphOutlineA (GDI32.@)
1611 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
1612 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1613 LPVOID lpBuffer, const MAT2 *lpmat2 )
1615 LPWSTR p = NULL;
1616 DWORD ret;
1617 UINT c;
1619 if(!(fuFormat & GGO_GLYPH_INDEX)) {
1620 p = FONT_mbtowc(hdc, (char*)&uChar, 1, NULL, NULL);
1621 c = p[0];
1622 } else
1623 c = uChar;
1624 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
1625 lpmat2);
1626 if(p)
1627 HeapFree(GetProcessHeap(), 0, p);
1628 return ret;
1631 /***********************************************************************
1632 * GetGlyphOutlineW (GDI32.@)
1634 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
1635 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
1636 LPVOID lpBuffer, const MAT2 *lpmat2 )
1638 DC *dc = DC_GetDCPtr(hdc);
1639 DWORD ret;
1641 TRACE("(%p, %04x, %04x, %p, %ld, %p, %p)\n",
1642 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
1644 if(!dc) return GDI_ERROR;
1646 if(dc->gdiFont)
1647 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
1648 cbBuffer, lpBuffer, lpmat2);
1649 else
1650 ret = GDI_ERROR;
1652 GDI_ReleaseObj(hdc);
1653 return ret;
1657 /***********************************************************************
1658 * CreateScalableFontResourceA (GDI32.@)
1660 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
1661 LPCSTR lpszResourceFile,
1662 LPCSTR lpszFontFile,
1663 LPCSTR lpszCurrentPath )
1665 HANDLE f;
1667 /* fHidden=1 - only visible for the calling app, read-only, not
1668 * enumbered with EnumFonts/EnumFontFamilies
1669 * lpszCurrentPath can be NULL
1671 FIXME("(%ld,%s,%s,%s): stub\n",
1672 fHidden, debugstr_a(lpszResourceFile), debugstr_a(lpszFontFile),
1673 debugstr_a(lpszCurrentPath) );
1675 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
1676 if ((f = CreateFileA(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
1677 CloseHandle(f);
1678 SetLastError(ERROR_FILE_EXISTS);
1679 return FALSE;
1681 return FALSE; /* create failed */
1684 /***********************************************************************
1685 * CreateScalableFontResourceW (GDI32.@)
1687 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
1688 LPCWSTR lpszResourceFile,
1689 LPCWSTR lpszFontFile,
1690 LPCWSTR lpszCurrentPath )
1692 FIXME("(%ld,%p,%p,%p): stub\n",
1693 fHidden, lpszResourceFile, lpszFontFile, lpszCurrentPath );
1694 return FALSE; /* create failed */
1698 /*************************************************************************
1699 * GetRasterizerCaps (GDI32.@)
1701 BOOL WINAPI GetRasterizerCaps( LPRASTERIZER_STATUS lprs, UINT cbNumBytes)
1703 lprs->nSize = sizeof(RASTERIZER_STATUS);
1704 lprs->wFlags = TT_AVAILABLE|TT_ENABLED;
1705 lprs->nLanguageID = 0;
1706 return TRUE;
1710 /*************************************************************************
1711 * GetKerningPairsA (GDI32.@)
1713 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
1714 LPKERNINGPAIR lpKerningPairs )
1716 return GetKerningPairsW( hDC, cPairs, lpKerningPairs );
1720 /*************************************************************************
1721 * GetKerningPairsW (GDI32.@)
1723 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
1724 LPKERNINGPAIR lpKerningPairs )
1726 int i;
1727 FIXME("(%p,%ld,%p): almost empty stub!\n", hDC, cPairs, lpKerningPairs);
1728 for (i = 0; i < cPairs; i++)
1729 lpKerningPairs[i].iKernAmount = 0;
1730 return 0;
1733 /*************************************************************************
1734 * TranslateCharsetInfo [GDI32.@]
1736 * Fills a CHARSETINFO structure for a character set, code page, or
1737 * font. This allows making the correspondance between different labelings
1738 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
1739 * of the same encoding.
1741 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
1742 * only one codepage should be set in *lpSrc.
1744 * RETURNS
1745 * TRUE on success, FALSE on failure.
1748 BOOL WINAPI TranslateCharsetInfo(
1749 LPDWORD lpSrc, /* [in]
1750 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
1751 if flags == TCI_SRCCHARSET: a character set value
1752 if flags == TCI_SRCCODEPAGE: a code page value
1754 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
1755 DWORD flags /* [in] determines interpretation of lpSrc */
1757 int index = 0;
1758 switch (flags) {
1759 case TCI_SRCFONTSIG:
1760 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
1761 break;
1762 case TCI_SRCCODEPAGE:
1763 while ((UINT) (lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
1764 break;
1765 case TCI_SRCCHARSET:
1766 while ((UINT) (lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
1767 break;
1768 default:
1769 return FALSE;
1771 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
1772 memcpy(lpCs, &FONT_tci[index], sizeof(CHARSETINFO));
1773 return TRUE;
1776 /*************************************************************************
1777 * GetFontLanguageInfo (GDI32.@)
1779 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
1781 FONTSIGNATURE fontsig;
1782 static const DWORD GCP_DBCS_MASK=0x003F0000,
1783 GCP_DIACRITIC_MASK=0x00000000,
1784 FLI_GLYPHS_MASK=0x00000000,
1785 GCP_GLYPHSHAPE_MASK=0x00000040,
1786 GCP_KASHIDA_MASK=0x00000000,
1787 GCP_LIGATE_MASK=0x00000000,
1788 GCP_USEKERNING_MASK=0x00000000,
1789 GCP_REORDER_MASK=0x00000060;
1791 DWORD result=0;
1793 GetTextCharsetInfo( hdc, &fontsig, 0 );
1794 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1796 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
1797 result|=GCP_DBCS;
1799 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
1800 result|=GCP_DIACRITIC;
1802 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
1803 result|=FLI_GLYPHS;
1805 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
1806 result|=GCP_GLYPHSHAPE;
1808 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
1809 result|=GCP_KASHIDA;
1811 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
1812 result|=GCP_LIGATE;
1814 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
1815 result|=GCP_USEKERNING;
1817 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
1818 result|=GCP_REORDER;
1820 return result;
1824 /*************************************************************************
1825 * GetFontData [GDI32.@] Retrieve data for TrueType font
1827 * RETURNS
1829 * success: Number of bytes returned
1830 * failure: GDI_ERROR
1832 * NOTES
1834 * Calls SetLastError()
1837 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
1838 LPVOID buffer, DWORD length)
1840 DC *dc = DC_GetDCPtr(hdc);
1841 DWORD ret = GDI_ERROR;
1843 if(!dc) return GDI_ERROR;
1845 if(dc->gdiFont)
1846 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
1848 GDI_ReleaseObj(hdc);
1849 return ret;
1852 /*************************************************************************
1853 * GetGlyphIndicesA [GDI32.@]
1855 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
1856 LPWORD pgi, DWORD flags)
1858 DWORD ret;
1859 WCHAR *lpstrW;
1860 INT countW;
1862 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1863 hdc, debugstr_an(lpstr, count), count, pgi, flags);
1865 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
1866 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
1867 HeapFree(GetProcessHeap(), 0, lpstrW);
1869 return ret;
1872 /*************************************************************************
1873 * GetGlyphIndicesW [GDI32.@]
1875 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
1876 LPWORD pgi, DWORD flags)
1878 DC *dc = DC_GetDCPtr(hdc);
1879 DWORD ret = GDI_ERROR;
1881 TRACE("(%p, %s, %d, %p, 0x%lx)\n",
1882 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
1884 if(!dc) return GDI_ERROR;
1886 if(dc->gdiFont)
1887 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
1889 GDI_ReleaseObj(hdc);
1890 return ret;
1893 /*************************************************************************
1894 * GetCharacterPlacementA [GDI32.@]
1896 * NOTES:
1897 * the web browser control of ie4 calls this with dwFlags=0
1899 DWORD WINAPI
1900 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
1901 INT nMaxExtent, GCP_RESULTSA *lpResults,
1902 DWORD dwFlags)
1904 WCHAR *lpStringW;
1905 INT uCountW, i;
1906 GCP_RESULTSW resultsW;
1907 DWORD ret;
1908 UINT font_cp;
1910 TRACE("%s, %d, %d, 0x%08lx\n",
1911 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
1913 /* both structs are equal in size */
1914 memcpy(&resultsW, lpResults, sizeof(resultsW));
1916 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
1917 if(lpResults->lpOutString)
1918 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
1920 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
1922 if(lpResults->lpOutString) {
1923 if(font_cp != CP_SYMBOL)
1924 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
1925 lpResults->lpOutString, uCount, NULL, NULL );
1926 else
1927 for(i = 0; i < uCount; i++)
1928 lpResults->lpOutString[i] = (CHAR)resultsW.lpOutString[i];
1931 HeapFree(GetProcessHeap(), 0, lpStringW);
1932 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
1934 return ret;
1937 /*************************************************************************
1938 * GetCharacterPlacementW [GDI32.@]
1940 * Retrieve information about a string. This includes the width, reordering,
1941 * Glyphing and so on.
1943 * RETURNS
1945 * The width and height of the string if succesful, 0 if failed.
1947 * BUGS
1949 * All flags except GCP_REORDER are not yet implemented.
1950 * Reordering is not 100% complient to the Windows BiDi method.
1951 * Caret positioning is not yet implemented.
1952 * Classes are not yet implemented.
1955 DWORD WINAPI
1956 GetCharacterPlacementW(
1957 HDC hdc, /* [in] Device context for which the rendering is to be done */
1958 LPCWSTR lpString, /* [in] The string for which information is to be returned */
1959 INT uCount, /* [in] Number of WORDS in string. */
1960 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
1961 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
1962 DWORD dwFlags /* [in] Flags specifying how to process the string */
1965 DWORD ret=0;
1966 SIZE size;
1967 UINT i, nSet;
1969 TRACE("%s, %d, %d, 0x%08lx\n",
1970 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
1972 TRACE("lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1973 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1974 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
1975 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
1976 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
1978 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08lx ignored\n", dwFlags);
1979 if(lpResults->lpCaretPos) FIXME("caret positions not implemented\n");
1980 if(lpResults->lpClass) FIXME("classes not implemented\n");
1982 nSet = (UINT)uCount;
1983 if(nSet > lpResults->nGlyphs)
1984 nSet = lpResults->nGlyphs;
1986 /* return number of initialized fields */
1987 lpResults->nGlyphs = nSet;
1989 if(dwFlags==0)
1991 /* Treat the case where no special handling was requested in a fastpath way */
1992 /* copy will do if the GCP_REORDER flag is not set */
1993 if(lpResults->lpOutString)
1994 for(i=0; i<nSet && lpString[i]!=0; ++i )
1995 lpResults->lpOutString[i]=lpString[i];
1997 if(lpResults->lpOrder)
1999 for(i = 0; i < nSet; i++)
2000 lpResults->lpOrder[i] = i;
2004 if((dwFlags&GCP_REORDER)!=0)
2006 WORD *pwCharType;
2007 int run_end;
2008 /* Keep a static table that translates the C2 types to something meaningful */
2009 /* 1 - left to right
2010 * -1 - right to left
2011 * 0 - neutral
2013 static const int chardir[]={ 0, 1, -1, 1, 0, 0, -1, 0, 0, 0, 0, 0 };
2015 WARN("The BiDi algorythm doesn't conform to Windows' yet\n");
2016 if( (pwCharType=HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD)))==NULL )
2018 SetLastError(ERROR_NOT_ENOUGH_MEMORY);
2020 return 0;
2023 /* Fill in the order array with directionality values */
2024 GetStringTypeW(CT_CTYPE2, lpString, uCount, pwCharType);
2026 /* The complete and correct (at least according to MS) BiDi algorythm is not
2027 * yet implemented here. Instead, we just make sure that consecutive runs of
2028 * the same direction (or neutral) are ordered correctly. We also assign Neutrals
2029 * that are between runs of opposing directions the base (ok, always LTR) dir.
2030 * While this is a LONG way from a BiDi algorithm, it does produce more or less
2031 * readable results.
2033 for( i=0; i<uCount; i+=run_end )
2035 for( run_end=1; i+run_end<uCount &&
2036 (chardir[pwCharType[i+run_end]]==chardir[pwCharType[i]] ||
2037 chardir[pwCharType[i+run_end]]==0); ++run_end )
2040 if( chardir[pwCharType[i]]==1 || chardir[pwCharType[i]]==0 )
2042 /* A LTR run */
2043 if(lpResults->lpOutString)
2045 int j;
2046 for( j=0; j<run_end; j++ )
2048 lpResults->lpOutString[i+j]=lpString[i+j];
2052 if(lpResults->lpOrder)
2054 int j;
2055 for( j=0; j<run_end; j++ )
2056 lpResults->lpOrder[i+j] = i+j;
2058 } else
2060 /* A RTL run */
2062 /* Since, at this stage, the paragraph context is always LTR,
2063 * remove any neutrals from the end of this run.
2065 if( chardir[pwCharType[i]]!=0 )
2066 while( chardir[pwCharType[i+run_end-1]]==0 )
2067 --run_end;
2069 if(lpResults->lpOutString)
2071 int j;
2072 for( j=0; j<run_end; j++ )
2074 lpResults->lpOutString[i+j]=lpString[i+run_end-j-1];
2078 if(lpResults->lpOrder)
2080 int j;
2081 for( j=0; j<run_end; j++ )
2082 lpResults->lpOrder[i+j] = i+run_end-j-1;
2087 HeapFree(GetProcessHeap(), 0, pwCharType);
2090 /* FIXME: Will use the placement chars */
2091 if (lpResults->lpDx)
2093 int c;
2094 for (i = 0; i < nSet; i++)
2096 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2097 lpResults->lpDx[i]= c;
2101 if(lpResults->lpGlyphs)
2102 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2104 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2105 ret = MAKELONG(size.cx, size.cy);
2107 return ret;
2110 /*************************************************************************
2111 * GetCharABCWidthsFloatA [GDI32.@]
2113 BOOL WINAPI GetCharABCWidthsFloatA(HDC hdc, UINT iFirstChar, UINT iLastChar,
2114 LPABCFLOAT lpABCF)
2116 FIXME_(gdi)("GetCharABCWidthsFloatA, stub\n");
2117 return 0;
2120 /*************************************************************************
2121 * GetCharABCWidthsFloatW [GDI32.@]
2123 BOOL WINAPI GetCharABCWidthsFloatW(HDC hdc, UINT iFirstChar,
2124 UINT iLastChar, LPABCFLOAT lpABCF)
2126 FIXME_(gdi)("GetCharABCWidthsFloatW, stub\n");
2127 return 0;
2130 /*************************************************************************
2131 * GetCharWidthFloatA [GDI32.@]
2133 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2134 UINT iLastChar, PFLOAT pxBuffer)
2136 FIXME_(gdi)("GetCharWidthFloatA, stub\n");
2137 return 0;
2140 /*************************************************************************
2141 * GetCharWidthFloatW [GDI32.@]
2143 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2144 UINT iLastChar, PFLOAT pxBuffer)
2146 FIXME_(gdi)("GetCharWidthFloatW, stub\n");
2147 return 0;
2151 /***********************************************************************
2153 * Font Resource API *
2155 ***********************************************************************/
2157 /***********************************************************************
2158 * AddFontResourceA (GDI32.@)
2160 INT WINAPI AddFontResourceA( LPCSTR str )
2162 return AddFontResourceExA( str, 0, NULL);
2165 /***********************************************************************
2166 * AddFontResourceW (GDI32.@)
2168 INT WINAPI AddFontResourceW( LPCWSTR str )
2170 return AddFontResourceExW(str, 0, NULL);
2174 /***********************************************************************
2175 * AddFontResourceExA (GDI32.@)
2177 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2179 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2180 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2181 INT ret;
2183 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2184 ret = AddFontResourceExW(strW, fl, pdv);
2185 HeapFree(GetProcessHeap(), 0, strW);
2186 return ret;
2189 /***********************************************************************
2190 * AddFontResourceExW (GDI32.@)
2192 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2194 return WineEngAddFontResourceEx(str, fl, pdv);
2197 /***********************************************************************
2198 * RemoveFontResourceA (GDI32.@)
2200 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
2202 return RemoveFontResourceExA(str, 0, 0);
2205 /***********************************************************************
2206 * RemoveFontResourceW (GDI32.@)
2208 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
2210 return RemoveFontResourceExW(str, 0, 0);
2213 /***********************************************************************
2214 * RemoveFontResourceExA (GDI32.@)
2216 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2218 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2219 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2220 INT ret;
2222 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2223 ret = RemoveFontResourceExW(strW, fl, pdv);
2224 HeapFree(GetProcessHeap(), 0, strW);
2225 return ret;
2228 /***********************************************************************
2229 * RemoveFontResourceExW (GDI32.@)
2231 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
2233 return WineEngRemoveFontResourceEx(str, fl, pdv);