1 /*
2 * GDI font objects
3 *
4 * Copyright 1993 Alexandre Julliard
5 * 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21 */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #include <stdarg.h>
27 #include <stdlib.h>
28 #include <string.h>
29 #include <assert.h>
30 #include "winerror.h"
31 #include "windef.h"
32 #include "winbase.h"
33 #include "winnls.h"
34 #include "wownt32.h"
35 #include "gdi_private.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
38
39 WINE_DEFAULT_DEBUG_CHANNEL(font);
40
41 /* Device -> World size conversion */
42
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
45 */
46 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
47 {
48 FLOAT floatWidth;
49
50 /* Perform operation with floating point */
51 floatWidth = (FLOAT)width * dc->xformVport2World.eM11;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth);
54 }
55
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
58 */
59 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
60 {
61 FLOAT floatHeight;
62
63 /* Perform operation with floating point */
64 floatHeight = (FLOAT)height * dc->xformVport2World.eM22;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight);
67 }
68
69 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
70 {
71 POINT pt[2];
72 pt[0].x = pt[0].y = 0;
73 pt[1].x = width;
74 pt[1].y = 0;
75 LPtoDP(dc->hSelf, pt, 2);
76 return pt[1].x - pt[0].x;
77 }
78
79 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
80 {
81 POINT pt[2];
82 pt[0].x = pt[0].y = 0;
83 pt[1].x = 0;
84 pt[1].y = height;
85 LPtoDP(dc->hSelf, pt, 2);
86 return pt[1].y - pt[0].y;
87 }
88
89 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
90 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
91 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer );
92 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj );
93
94 static const struct gdi_obj_funcs font_funcs =
95 {
96 FONT_SelectObject, /* pSelectObject */
97 FONT_GetObjectA, /* pGetObjectA */
98 FONT_GetObjectW, /* pGetObjectW */
99 NULL, /* pUnrealizeObject */
100 FONT_DeleteObject /* pDeleteObject */
101 };
102
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
105
106 typedef struct
107 {
108 GDIOBJHDR header;
109 LOGFONTW logfont;
110 } FONTOBJ;
111
112 typedef struct
113 {
114 LPLOGFONTW lpLogFontParam;
115 FONTENUMPROCW lpEnumFunc;
116 LPARAM lpData;
117 DWORD dwFlags;
118 HDC hdc;
119 } fontEnum32;
120
121 /*
122 * For TranslateCharsetInfo
123 */
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
126 /* ANSI */
127 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
128 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
129 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
130 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
131 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
132 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
133 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
134 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
135 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
138 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
139 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
140 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
141 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
142 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 /* ANSI and OEM */
145 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
146 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
147 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
148 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
149 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
150 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
153 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
154 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
155 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
156 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
157 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
163 };
164
165 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
166 {
167 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
168 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
169 LF_FACESIZE);
170 fontW->lfFaceName[LF_FACESIZE-1] = 0;
171 }
172
173 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
174 {
175 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
176 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
177 LF_FACESIZE, NULL, NULL);
178 fontA->lfFaceName[LF_FACESIZE-1] = 0;
179 }
180
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
182 {
183 FONT_LogFontWToA( (const LOGFONTW *)fontW, (LPLOGFONTA)fontA);
184
185 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
186 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
187 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
188 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
189 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
190 fontA->elfStyle[LF_FACESIZE-1] = '\0';
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
192 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
193 fontA->elfScript[LF_FACESIZE-1] = '\0';
194 }
195
196 /***********************************************************************
197 * TEXTMETRIC conversion functions.
198 */
199 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
200 {
201 ptmA->tmHeight = ptmW->tmHeight;
202 ptmA->tmAscent = ptmW->tmAscent;
203 ptmA->tmDescent = ptmW->tmDescent;
204 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
205 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
206 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
207 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
208 ptmA->tmWeight = ptmW->tmWeight;
209 ptmA->tmOverhang = ptmW->tmOverhang;
210 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
211 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
212 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
213 if (ptmW->tmCharSet == SYMBOL_CHARSET)
214 {
215 UINT last_char = ptmW->tmLastChar;
216 if (last_char > 0xf000) last_char -= 0xf000;
217 ptmA->tmLastChar = min(last_char, 255);
218 }
219 else
220 ptmA->tmLastChar = min(ptmW->tmLastChar, 255);
221 ptmA->tmDefaultChar = min(ptmW->tmDefaultChar, 255);
222 ptmA->tmBreakChar = min(ptmW->tmBreakChar, 255);
223 ptmA->tmItalic = ptmW->tmItalic;
224 ptmA->tmUnderlined = ptmW->tmUnderlined;
225 ptmA->tmStruckOut = ptmW->tmStruckOut;
226 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
227 ptmA->tmCharSet = ptmW->tmCharSet;
228 }
229
230
231 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
232 {
233 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
234 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
235 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
236 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
237 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
238 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
239 }
240
241
242 /***********************************************************************
243 * GdiGetCodePage (GDI32.@)
244 */
245 DWORD WINAPI GdiGetCodePage( HDC hdc )
246 {
247 UINT cp = CP_ACP;
248 CHARSETINFO csi;
249 int charset = GetTextCharset(hdc);
250
251 /* Hmm, nicely designed api this one! */
252 if(TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
253 cp = csi.ciACP;
254 else {
255 switch(charset) {
256 case OEM_CHARSET:
257 cp = GetOEMCP();
258 break;
259 case DEFAULT_CHARSET:
260 cp = GetACP();
261 break;
262
263 case VISCII_CHARSET:
264 case TCVN_CHARSET:
265 case KOI8_CHARSET:
266 case ISO3_CHARSET:
267 case ISO4_CHARSET:
268 case ISO10_CHARSET:
269 case CELTIC_CHARSET:
270 /* FIXME: These have no place here, but because x11drv
271 enumerates fonts with these (made up) charsets some apps
272 might use them and then the FIXME below would become
273 annoying. Now we could pick the intended codepage for
274 each of these, but since it's broken anyway we'll just
275 use CP_ACP and hope it'll go away...
276 */
277 cp = CP_ACP;
278 break;
279
280 default:
281 FIXME("Can't find codepage for charset %d\n", charset);
282 break;
283 }
284 }
285
286 TRACE("charset %d => cp %d\n", charset, cp);
287 return cp;
288 }
289
290 /***********************************************************************
291 * FONT_mbtowc
292 *
293 * Returns a Unicode translation of str using the charset of the
294 * currently selected font in hdc. If count is -1 then str is assumed
295 * to be '\0' terminated, otherwise it contains the number of bytes to
296 * convert. If plenW is non-NULL, on return it will point to the
297 * number of WCHARs that have been written. If pCP is non-NULL, on
298 * return it will point to the codepage used in the conversion. The
299 * caller should free the returned LPWSTR from the process heap
300 * itself.
301 */
302 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
303 {
304 UINT cp;
305 INT lenW;
306 LPWSTR strW;
307
308 cp = GdiGetCodePage( hdc );
309
310 if(count == -1) count = strlen(str);
311 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
312 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
313 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
314 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
315 if(plenW) *plenW = lenW;
316 if(pCP) *pCP = cp;
317 return strW;
318 }
319
320
321 /***********************************************************************
322 * CreateFontIndirectA (GDI32.@)
323 */
324 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
325 {
326 LOGFONTW lfW;
327
328 if (!plfA) return 0;
329
330 FONT_LogFontAToW( plfA, &lfW );
331 return CreateFontIndirectW( &lfW );
332 }
333
334 /***********************************************************************
335 * CreateFontIndirectW (GDI32.@)
336 */
337 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
338 {
339 static const WCHAR ItalicW[] = {' ','I','t','a','l','i','c','\0'};
340 static const WCHAR BoldW[] = {' ','B','o','l','d','\0'};
341 WCHAR *pFaceNameItalicSuffix, *pFaceNameBoldSuffix;
342 WCHAR *pFaceNameSuffix = NULL;
343 HFONT hFont;
344 FONTOBJ *fontPtr;
345
346 if (!plf) return 0;
347
348 if (!(fontPtr = GDI_AllocObject( sizeof(FONTOBJ), FONT_MAGIC, (HGDIOBJ *)&hFont,
349 &font_funcs ))) return 0;
350
351 fontPtr->logfont = *plf;
352
353 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
354 plf->lfHeight, plf->lfWidth,
355 plf->lfEscapement, plf->lfOrientation,
356 plf->lfPitchAndFamily,
357 plf->lfOutPrecision, plf->lfClipPrecision,
358 plf->lfQuality, plf->lfCharSet,
359 debugstr_w(plf->lfFaceName),
360 plf->lfWeight > 400 ? "Bold" : "",
361 plf->lfItalic ? "Italic" : "",
362 plf->lfUnderline ? "Underline" : "", hFont);
363
364 if (plf->lfEscapement != plf->lfOrientation)
365 {
366 /* this should really depend on whether GM_ADVANCED is set */
367 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
368 WARN("orientation angle %f set to "
369 "escapement angle %f for new font %p\n",
370 plf->lfOrientation/10., plf->lfEscapement/10., hFont);
371 }
372
373 pFaceNameItalicSuffix = strstrW(fontPtr->logfont.lfFaceName, ItalicW);
374 if (pFaceNameItalicSuffix)
375 {
376 fontPtr->logfont.lfItalic = TRUE;
377 pFaceNameSuffix = pFaceNameItalicSuffix;
378 }
379
380 pFaceNameBoldSuffix = strstrW(fontPtr->logfont.lfFaceName, BoldW);
381 if (pFaceNameBoldSuffix)
382 {
383 if (fontPtr->logfont.lfWeight < FW_BOLD)
384 fontPtr->logfont.lfWeight = FW_BOLD;
385 if (!pFaceNameSuffix || (pFaceNameBoldSuffix < pFaceNameSuffix))
386 pFaceNameSuffix = pFaceNameBoldSuffix;
387 }
388
389 if (pFaceNameSuffix) *pFaceNameSuffix = 0;
390
391 GDI_ReleaseObj( hFont );
392 return hFont;
393 }
394
395 /*************************************************************************
396 * CreateFontA (GDI32.@)
397 */
398 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
399 INT orient, INT weight, DWORD italic,
400 DWORD underline, DWORD strikeout, DWORD charset,
401 DWORD outpres, DWORD clippres, DWORD quality,
402 DWORD pitch, LPCSTR name )
403 {
404 LOGFONTA logfont;
405
406 logfont.lfHeight = height;
407 logfont.lfWidth = width;
408 logfont.lfEscapement = esc;
409 logfont.lfOrientation = orient;
410 logfont.lfWeight = weight;
411 logfont.lfItalic = italic;
412 logfont.lfUnderline = underline;
413 logfont.lfStrikeOut = strikeout;
414 logfont.lfCharSet = charset;
415 logfont.lfOutPrecision = outpres;
416 logfont.lfClipPrecision = clippres;
417 logfont.lfQuality = quality;
418 logfont.lfPitchAndFamily = pitch;
419
420 if (name)
421 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
422 else
423 logfont.lfFaceName[0] = '\0';
424
425 return CreateFontIndirectA( &logfont );
426 }
427
428 /*************************************************************************
429 * CreateFontW (GDI32.@)
430 */
431 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
432 INT orient, INT weight, DWORD italic,
433 DWORD underline, DWORD strikeout, DWORD charset,
434 DWORD outpres, DWORD clippres, DWORD quality,
435 DWORD pitch, LPCWSTR name )
436 {
437 LOGFONTW logfont;
438
439 logfont.lfHeight = height;
440 logfont.lfWidth = width;
441 logfont.lfEscapement = esc;
442 logfont.lfOrientation = orient;
443 logfont.lfWeight = weight;
444 logfont.lfItalic = italic;
445 logfont.lfUnderline = underline;
446 logfont.lfStrikeOut = strikeout;
447 logfont.lfCharSet = charset;
448 logfont.lfOutPrecision = outpres;
449 logfont.lfClipPrecision = clippres;
450 logfont.lfQuality = quality;
451 logfont.lfPitchAndFamily = pitch;
452
453 if (name)
454 lstrcpynW(logfont.lfFaceName, name,
455 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
456 else
457 logfont.lfFaceName[0] = '\0';
458
459 return CreateFontIndirectW( &logfont );
460 }
461
462
463 /***********************************************************************
464 * FONT_SelectObject
465 *
466 * If the driver supports vector fonts we create a gdi font first and
467 * then call the driver to give it a chance to supply its own device
468 * font. If the driver wants to do this it returns TRUE and we can
469 * delete the gdi font, if the driver wants to use the gdi font it
470 * should return FALSE, to signal an error return GDI_ERROR. For
471 * drivers that don't support vector fonts they must supply their own
472 * font.
473 */
474 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
475 {
476 HGDIOBJ ret = 0;
477 DC *dc = get_dc_ptr( hdc );
478
479 if (!dc) return 0;
480
481 if (!GDI_inc_ref_count( handle ))
482 {
483 release_dc_ptr( dc );
484 return 0;
485 }
486
487 if (dc->hFont != handle || dc->gdiFont == NULL)
488 {
489 if(GetDeviceCaps(dc->hSelf, TEXTCAPS) & TC_VA_ABLE)
490 {
491 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
492 dc->gdiFont = WineEngCreateFontInstance(dc, handle);
493 if (font) GDI_ReleaseObj( handle );
494 }
495 }
496
497 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
498
499 if (ret && dc->gdiFont) dc->gdiFont = 0;
500
501 if (ret == HGDI_ERROR)
502 {
503 GDI_dec_ref_count( handle );
504 ret = 0; /* SelectObject returns 0 on error */
505 }
506 else
507 {
508 ret = dc->hFont;
509 dc->hFont = handle;
510 GDI_dec_ref_count( ret );
511 }
512 release_dc_ptr( dc );
513 return ret;
514 }
515
516
517 /***********************************************************************
518 * FONT_GetObjectA
519 */
520 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
521 {
522 FONTOBJ *font = obj;
523 LOGFONTA lfA;
524
525 if(!buffer)
526 return sizeof(lfA);
527 FONT_LogFontWToA( &font->logfont, &lfA );
528
529 if (count > sizeof(lfA)) count = sizeof(lfA);
530 memcpy( buffer, &lfA, count );
531 return count;
532 }
533
534 /***********************************************************************
535 * FONT_GetObjectW
536 */
537 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
538 {
539 FONTOBJ *font = obj;
540 if(!buffer)
541 return sizeof(LOGFONTW);
542 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
543 memcpy( buffer, &font->logfont, count );
544 return count;
545 }
546
547
548 /***********************************************************************
549 * FONT_DeleteObject
550 */
551 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
552 {
553 WineEngDestroyFontInstance( handle );
554 return GDI_FreeObject( handle, obj );
555 }
556
557
558 /***********************************************************************
559 * FONT_EnumInstance
560 *
561 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
562 * We have to use other types because of the FONTENUMPROCW definition.
563 */
564 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
565 DWORD fType, LPARAM lp )
566 {
567 fontEnum32 *pfe = (fontEnum32*)lp;
568 INT ret = 1;
569
570 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
571 if ((!pfe->lpLogFontParam ||
572 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
573 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
574 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
575 {
576 /* convert font metrics */
577 ENUMLOGFONTEXA logfont;
578 NEWTEXTMETRICEXA tmA;
579
580 pfe->dwFlags |= ENUM_CALLED;
581 if (!(pfe->dwFlags & ENUM_UNICODE))
582 {
583 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
584 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
585 plf = (LOGFONTW *)&logfont.elfLogFont;
586 ptm = (TEXTMETRICW *)&tmA;
587 }
588
589 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
590 }
591 return ret;
592 }
593
594 /***********************************************************************
595 * FONT_EnumFontFamiliesEx
596 */
597 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
598 FONTENUMPROCW efproc,
599 LPARAM lParam, DWORD dwUnicode)
600 {
601 INT ret = 1, ret2;
602 DC *dc = get_dc_ptr( hDC );
603 fontEnum32 fe32;
604 BOOL enum_gdi_fonts;
605
606 if (!dc) return 0;
607
608 if (plf)
609 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
610 plf->lfCharSet);
611 fe32.lpLogFontParam = plf;
612 fe32.lpEnumFunc = efproc;
613 fe32.lpData = lParam;
614 fe32.dwFlags = dwUnicode;
615 fe32.hdc = hDC;
616
617 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
618
619 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
620 {
621 ret = 0;
622 goto done;
623 }
624
625 if (enum_gdi_fonts)
626 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
627 fe32.dwFlags &= ~ENUM_CALLED;
628 if (ret && dc->funcs->pEnumDeviceFonts) {
629 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
630 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
631 ret = ret2;
632 }
633 done:
634 release_dc_ptr( dc );
635 return ret;
636 }
637
638 /***********************************************************************
639 * EnumFontFamiliesExW (GDI32.@)
640 */
641 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
642 FONTENUMPROCW efproc,
643 LPARAM lParam, DWORD dwFlags )
644 {
645 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
646 }
647
648 /***********************************************************************
649 * EnumFontFamiliesExA (GDI32.@)
650 */
651 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
652 FONTENUMPROCA efproc,
653 LPARAM lParam, DWORD dwFlags)
654 {
655 LOGFONTW lfW, *plfW;
656
657 if (plf)
658 {
659 FONT_LogFontAToW( plf, &lfW );
660 plfW = &lfW;
661 }
662 else plfW = NULL;
663
664 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
665 }
666
667 /***********************************************************************
668 * EnumFontFamiliesA (GDI32.@)
669 */
670 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
671 FONTENUMPROCA efproc, LPARAM lpData )
672 {
673 LOGFONTA lf, *plf;
674
675 if (lpFamily)
676 {
677 if (!*lpFamily) return 1;
678 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
679 lf.lfCharSet = DEFAULT_CHARSET;
680 lf.lfPitchAndFamily = 0;
681 plf = &lf;
682 }
683 else plf = NULL;
684
685 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
686 }
687
688 /***********************************************************************
689 * EnumFontFamiliesW (GDI32.@)
690 */
691 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
692 FONTENUMPROCW efproc, LPARAM lpData )
693 {
694 LOGFONTW lf, *plf;
695
696 if (lpFamily)
697 {
698 if (!*lpFamily) return 1;
699 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
700 lf.lfCharSet = DEFAULT_CHARSET;
701 lf.lfPitchAndFamily = 0;
702 plf = &lf;
703 }
704 else plf = NULL;
705
706 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
707 }
708
709 /***********************************************************************
710 * EnumFontsA (GDI32.@)
711 */
712 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
713 LPARAM lpData )
714 {
715 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
716 }
717
718 /***********************************************************************
719 * EnumFontsW (GDI32.@)
720 */
721 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
722 LPARAM lpData )
723 {
724 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
725 }
726
727
728 /***********************************************************************
729 * GetTextCharacterExtra (GDI32.@)
730 */
731 INT WINAPI GetTextCharacterExtra( HDC hdc )
732 {
733 INT ret;
734 DC *dc = get_dc_ptr( hdc );
735 if (!dc) return 0x80000000;
736 ret = dc->charExtra;
737 release_dc_ptr( dc );
738 return ret;
739 }
740
741
742 /***********************************************************************
743 * SetTextCharacterExtra (GDI32.@)
744 */
745 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
746 {
747 INT prev;
748 DC * dc = get_dc_ptr( hdc );
749 if (!dc) return 0x80000000;
750 if (dc->funcs->pSetTextCharacterExtra)
751 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
752 else
753 {
754 prev = dc->charExtra;
755 dc->charExtra = extra;
756 }
757 release_dc_ptr( dc );
758 return prev;
759 }
760
761
762 /***********************************************************************
763 * SetTextJustification (GDI32.@)
764 */
765 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
766 {
767 BOOL ret = TRUE;
768 DC * dc = get_dc_ptr( hdc );
769 if (!dc) return FALSE;
770 if (dc->funcs->pSetTextJustification)
771 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
772 else
773 {
774 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
775 if (!extra) breaks = 0;
776 if (breaks)
777 {
778 dc->breakExtra = extra / breaks;
779 dc->breakRem = extra - (breaks * dc->breakExtra);
780 }
781 else
782 {
783 dc->breakExtra = 0;
784 dc->breakRem = 0;
785 }
786 }
787 release_dc_ptr( dc );
788 return ret;
789 }
790
791
792 /***********************************************************************
793 * GetTextFaceA (GDI32.@)
794 */
795 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
796 {
797 INT res = GetTextFaceW(hdc, 0, NULL);
798 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
799 GetTextFaceW( hdc, res, nameW );
800
801 if (name)
802 {
803 if (count && !WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL))
804 name[count-1] = 0;
805 res = strlen(name);
806 }
807 else
808 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
809 HeapFree( GetProcessHeap(), 0, nameW );
810 return res;
811 }
812
813 /***********************************************************************
814 * GetTextFaceW (GDI32.@)
815 */
816 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
817 {
818 FONTOBJ *font;
819 INT ret = 0;
820
821 DC * dc = get_dc_ptr( hdc );
822 if (!dc) return 0;
823
824 if(dc->gdiFont)
825 ret = WineEngGetTextFace(dc->gdiFont, count, name);
826 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
827 {
828 if (name)
829 {
830 lstrcpynW( name, font->logfont.lfFaceName, count );
831 ret = strlenW(name);
832 }
833 else ret = strlenW(font->logfont.lfFaceName) + 1;
834 GDI_ReleaseObj( dc->hFont );
835 }
836 release_dc_ptr( dc );
837 return ret;
838 }
839
840
841 /***********************************************************************
842 * GetTextExtentPoint32A (GDI32.@)
843 *
844 * See GetTextExtentPoint32W.
845 */
846 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
847 LPSIZE size )
848 {
849 BOOL ret = FALSE;
850 INT wlen;
851 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
852
853 if (p) {
854 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
855 HeapFree( GetProcessHeap(), 0, p );
856 }
857
858 TRACE("(%p %s %d %p): returning %d x %d\n",
859 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
860 return ret;
861 }
862
863
864 /***********************************************************************
865 * GetTextExtentPoint32W [GDI32.@]
866 *
867 * Computes width/height for a string.
868 *
869 * Computes width and height of the specified string.
870 *
871 * RETURNS
872 * Success: TRUE
873 * Failure: FALSE
874 */
875 BOOL WINAPI GetTextExtentPoint32W(
876 HDC hdc, /* [in] Handle of device context */
877 LPCWSTR str, /* [in] Address of text string */
878 INT count, /* [in] Number of characters in string */
879 LPSIZE size) /* [out] Address of structure for string size */
880 {
881 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
882 }
883
884 /***********************************************************************
885 * GetTextExtentExPointI [GDI32.@]
886 *
887 * Computes width and height of the array of glyph indices.
888 *
889 * PARAMS
890 * hdc [I] Handle of device context.
891 * indices [I] Glyph index array.
892 * count [I] Number of glyphs in array.
893 * max_ext [I] Maximum width in glyphs.
894 * nfit [O] Maximum number of characters.
895 * dxs [O] Partial string widths.
896 * size [O] Returned string size.
897 *
898 * RETURNS
899 * Success: TRUE
900 * Failure: FALSE
901 */
902 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
903 LPINT nfit, LPINT dxs, LPSIZE size )
904 {
905 BOOL ret = FALSE;
906 DC * dc = get_dc_ptr( hdc );
907 if (!dc) return FALSE;
908
909 if(dc->gdiFont) {
910 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
911 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
912 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
913 size->cx += count * dc->charExtra;
914 }
915 else if(dc->funcs->pGetTextExtentExPoint) {
916 FIXME("calling GetTextExtentExPoint\n");
917 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
918 count, max_ext, nfit, dxs, size );
919 }
920
921 release_dc_ptr( dc );
922
923 TRACE("(%p %p %d %p): returning %d x %d\n",
924 hdc, indices, count, size, size->cx, size->cy );
925 return ret;
926 }
927
928 /***********************************************************************
929 * GetTextExtentPointI [GDI32.@]
930 *
931 * Computes width and height of the array of glyph indices.
932 *
933 * PARAMS
934 * hdc [I] Handle of device context.
935 * indices [I] Glyph index array.
936 * count [I] Number of glyphs in array.
937 * size [O] Returned string size.
938 *
939 * RETURNS
940 * Success: TRUE
941 * Failure: FALSE
942 */
943 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
944 {
945 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
946 }
947
948
949 /***********************************************************************
950 * GetTextExtentPointA (GDI32.@)
951 */
952 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
953 LPSIZE size )
954 {
955 TRACE("not bug compatible.\n");
956 return GetTextExtentPoint32A( hdc, str, count, size );
957 }
958
959 /***********************************************************************
960 * GetTextExtentPointW (GDI32.@)
961 */
962 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
963 LPSIZE size )
964 {
965 TRACE("not bug compatible.\n");
966 return GetTextExtentPoint32W( hdc, str, count, size );
967 }
968
969
970 /***********************************************************************
971 * GetTextExtentExPointA (GDI32.@)
972 */
973 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
974 INT maxExt, LPINT lpnFit,
975 LPINT alpDx, LPSIZE size )
976 {
977 BOOL ret;
978 INT wlen;
979 INT *walpDx = NULL;
980 LPWSTR p = NULL;
981
982 if (alpDx &&
983 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
984 return FALSE;
985
986 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
987 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
988 if (walpDx)