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 double floatWidth;
49
50 /* Perform operation with floating point */
51 floatWidth = (double)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 double floatHeight;
62
63 /* Perform operation with floating point */
64 floatHeight = (double)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 (GetDeviceCaps( dc->hSelf, TEXTCAPS ) & TC_VA_ABLE)
488 {
489 FONTOBJ *font = GDI_GetObjPtr( handle, FONT_MAGIC ); /* to grab the GDI lock (FIXME) */
490 dc->gdiFont = WineEngCreateFontInstance( dc, handle );
491 if (font) GDI_ReleaseObj( handle );
492 }
493
494 if (dc->funcs->pSelectFont) ret = dc->funcs->pSelectFont( dc->physDev, handle, dc->gdiFont );
495
496 if (ret && dc->gdiFont) dc->gdiFont = 0;
497
498 if (ret == HGDI_ERROR)
499 {
500 GDI_dec_ref_count( handle );
501 ret = 0; /* SelectObject returns 0 on error */
502 }
503 else
504 {
505 ret = dc->hFont;
506 dc->hFont = handle;
507 GDI_dec_ref_count( ret );
508 }
509 release_dc_ptr( dc );
510 return ret;
511 }
512
513
514 /***********************************************************************
515 * FONT_GetObjectA
516 */
517 static INT FONT_GetObjectA( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
518 {
519 FONTOBJ *font = obj;
520 LOGFONTA lfA;
521
522 if(!buffer)
523 return sizeof(lfA);
524 FONT_LogFontWToA( &font->logfont, &lfA );
525
526 if (count > sizeof(lfA)) count = sizeof(lfA);
527 memcpy( buffer, &lfA, count );
528 return count;
529 }
530
531 /***********************************************************************
532 * FONT_GetObjectW
533 */
534 static INT FONT_GetObjectW( HGDIOBJ handle, void *obj, INT count, LPVOID buffer )
535 {
536 FONTOBJ *font = obj;
537 if(!buffer)
538 return sizeof(LOGFONTW);
539 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
540 memcpy( buffer, &font->logfont, count );
541 return count;
542 }
543
544
545 /***********************************************************************
546 * FONT_DeleteObject
547 */
548 static BOOL FONT_DeleteObject( HGDIOBJ handle, void *obj )
549 {
550 WineEngDestroyFontInstance( handle );
551 return GDI_FreeObject( handle, obj );
552 }
553
554
555 /***********************************************************************
556 * FONT_EnumInstance
557 *
558 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
559 * We have to use other types because of the FONTENUMPROCW definition.
560 */
561 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
562 DWORD fType, LPARAM lp )
563 {
564 fontEnum32 *pfe = (fontEnum32*)lp;
565 INT ret = 1;
566
567 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
568 if ((!pfe->lpLogFontParam ||
569 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
570 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
571 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
572 {
573 /* convert font metrics */
574 ENUMLOGFONTEXA logfont;
575 NEWTEXTMETRICEXA tmA;
576
577 pfe->dwFlags |= ENUM_CALLED;
578 if (!(pfe->dwFlags & ENUM_UNICODE))
579 {
580 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
581 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
582 plf = (LOGFONTW *)&logfont.elfLogFont;
583 ptm = (TEXTMETRICW *)&tmA;
584 }
585
586 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
587 }
588 return ret;
589 }
590
591 /***********************************************************************
592 * FONT_EnumFontFamiliesEx
593 */
594 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf,
595 FONTENUMPROCW efproc,
596 LPARAM lParam, DWORD dwUnicode)
597 {
598 INT ret = 1, ret2;
599 DC *dc = get_dc_ptr( hDC );
600 fontEnum32 fe32;
601 BOOL enum_gdi_fonts;
602
603 if (!dc) return 0;
604
605 if (plf)
606 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName),
607 plf->lfCharSet);
608 fe32.lpLogFontParam = plf;
609 fe32.lpEnumFunc = efproc;
610 fe32.lpData = lParam;
611 fe32.dwFlags = dwUnicode;
612 fe32.hdc = hDC;
613
614 enum_gdi_fonts = GetDeviceCaps(hDC, TEXTCAPS) & TC_VA_ABLE;
615
616 if (!dc->funcs->pEnumDeviceFonts && !enum_gdi_fonts)
617 {
618 ret = 0;
619 goto done;
620 }
621
622 if (enum_gdi_fonts)
623 ret = WineEngEnumFonts( plf, FONT_EnumInstance, (LPARAM)&fe32 );
624 fe32.dwFlags &= ~ENUM_CALLED;
625 if (ret && dc->funcs->pEnumDeviceFonts) {
626 ret2 = dc->funcs->pEnumDeviceFonts( dc->physDev, plf, FONT_EnumInstance, (LPARAM)&fe32 );
627 if(fe32.dwFlags & ENUM_CALLED) /* update ret iff a font gets enumed */
628 ret = ret2;
629 }
630 done:
631 release_dc_ptr( dc );
632 return ret;
633 }
634
635 /***********************************************************************
636 * EnumFontFamiliesExW (GDI32.@)
637 */
638 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
639 FONTENUMPROCW efproc,
640 LPARAM lParam, DWORD dwFlags )
641 {
642 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, ENUM_UNICODE );
643 }
644
645 /***********************************************************************
646 * EnumFontFamiliesExA (GDI32.@)
647 */
648 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
649 FONTENUMPROCA efproc,
650 LPARAM lParam, DWORD dwFlags)
651 {
652 LOGFONTW lfW, *plfW;
653
654 if (plf)
655 {
656 FONT_LogFontAToW( plf, &lfW );
657 plfW = &lfW;
658 }
659 else plfW = NULL;
660
661 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, 0);
662 }
663
664 /***********************************************************************
665 * EnumFontFamiliesA (GDI32.@)
666 */
667 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
668 FONTENUMPROCA efproc, LPARAM lpData )
669 {
670 LOGFONTA lf, *plf;
671
672 if (lpFamily)
673 {
674 if (!*lpFamily) return 1;
675 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
676 lf.lfCharSet = DEFAULT_CHARSET;
677 lf.lfPitchAndFamily = 0;
678 plf = &lf;
679 }
680 else plf = NULL;
681
682 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
683 }
684
685 /***********************************************************************
686 * EnumFontFamiliesW (GDI32.@)
687 */
688 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
689 FONTENUMPROCW efproc, LPARAM lpData )
690 {
691 LOGFONTW lf, *plf;
692
693 if (lpFamily)
694 {
695 if (!*lpFamily) return 1;
696 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
697 lf.lfCharSet = DEFAULT_CHARSET;
698 lf.lfPitchAndFamily = 0;
699 plf = &lf;
700 }
701 else plf = NULL;
702
703 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
704 }
705
706 /***********************************************************************
707 * EnumFontsA (GDI32.@)
708 */
709 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
710 LPARAM lpData )
711 {
712 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
713 }
714
715 /***********************************************************************
716 * EnumFontsW (GDI32.@)
717 */
718 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
719 LPARAM lpData )
720 {
721 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
722 }
723
724
725 /***********************************************************************
726 * GetTextCharacterExtra (GDI32.@)
727 */
728 INT WINAPI GetTextCharacterExtra( HDC hdc )
729 {
730 INT ret;
731 DC *dc = get_dc_ptr( hdc );
732 if (!dc) return 0x80000000;
733 ret = dc->charExtra;
734 release_dc_ptr( dc );
735 return ret;
736 }
737
738
739 /***********************************************************************
740 * SetTextCharacterExtra (GDI32.@)
741 */
742 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
743 {
744 INT prev;
745 DC * dc = get_dc_ptr( hdc );
746 if (!dc) return 0x80000000;
747 if (dc->funcs->pSetTextCharacterExtra)
748 prev = dc->funcs->pSetTextCharacterExtra( dc->physDev, extra );
749 else
750 {
751 prev = dc->charExtra;
752 dc->charExtra = extra;
753 }
754 release_dc_ptr( dc );
755 return prev;
756 }
757
758
759 /***********************************************************************
760 * SetTextJustification (GDI32.@)
761 */
762 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
763 {
764 BOOL ret = TRUE;
765 DC * dc = get_dc_ptr( hdc );
766 if (!dc) return FALSE;
767 if (dc->funcs->pSetTextJustification)
768 ret = dc->funcs->pSetTextJustification( dc->physDev, extra, breaks );
769 else
770 {
771 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
772 if (!extra) breaks = 0;
773 if (breaks)
774 {
775 dc->breakExtra = extra / breaks;
776 dc->breakRem = extra - (breaks * dc->breakExtra);
777 }
778 else
779 {
780 dc->breakExtra = 0;
781 dc->breakRem = 0;
782 }
783 }
784 release_dc_ptr( dc );
785 return ret;
786 }
787
788
789 /***********************************************************************
790 * GetTextFaceA (GDI32.@)
791 */
792 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
793 {
794 INT res = GetTextFaceW(hdc, 0, NULL);
795 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
796 GetTextFaceW( hdc, res, nameW );
797
798 if (name)
799 {
800 if (count)
801 {
802 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
803 if (res == 0)
804 res = count;
805 name[count-1] = 0;
806 /* GetTextFaceA does NOT include the nul byte in the return count. */
807 res--;
808 }
809 else
810 res = 0;
811 }
812 else
813 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
814 HeapFree( GetProcessHeap(), 0, nameW );
815 return res;
816 }
817
818 /***********************************************************************
819 * GetTextFaceW (GDI32.@)
820 */
821 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
822 {
823 FONTOBJ *font;
824 INT ret = 0;
825
826 DC * dc = get_dc_ptr( hdc );
827 if (!dc) return 0;
828
829 if(dc->gdiFont)
830 ret = WineEngGetTextFace(dc->gdiFont, count, name);
831 else if ((font = (FONTOBJ *) GDI_GetObjPtr( dc->hFont, FONT_MAGIC )))
832 {
833 INT n = strlenW(font->logfont.lfFaceName) + 1;
834 if (name)
835 {
836 lstrcpynW( name, font->logfont.lfFaceName, count );
837 ret = min(count, n);
838 }
839 else ret = n;
840 GDI_ReleaseObj( dc->hFont );
841 }
842 release_dc_ptr( dc );
843 return ret;
844 }
845
846
847 /***********************************************************************
848 * GetTextExtentPoint32A (GDI32.@)
849 *
850 * See GetTextExtentPoint32W.
851 */
852 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
853 LPSIZE size )
854 {
855 BOOL ret = FALSE;
856 INT wlen;
857 LPWSTR p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
858
859 if (p) {
860 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
861 HeapFree( GetProcessHeap(), 0, p );
862 }
863
864 TRACE("(%p %s %d %p): returning %d x %d\n",
865 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
866 return ret;
867 }
868
869
870 /***********************************************************************
871 * GetTextExtentPoint32W [GDI32.@]
872 *
873 * Computes width/height for a string.
874 *
875 * Computes width and height of the specified string.
876 *
877 * RETURNS
878 * Success: TRUE
879 * Failure: FALSE
880 */
881 BOOL WINAPI GetTextExtentPoint32W(
882 HDC hdc, /* [in] Handle of device context */
883 LPCWSTR str, /* [in] Address of text string */
884 INT count, /* [in] Number of characters in string */
885 LPSIZE size) /* [out] Address of structure for string size */
886 {
887 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
888 }
889
890 /***********************************************************************
891 * GetTextExtentExPointI [GDI32.@]
892 *
893 * Computes width and height of the array of glyph indices.
894 *
895 * PARAMS
896 * hdc [I] Handle of device context.
897 * indices [I] Glyph index array.
898 * count [I] Number of glyphs in array.
899 * max_ext [I] Maximum width in glyphs.
900 * nfit [O] Maximum number of characters.
901 * dxs [O] Partial string widths.
902 * size [O] Returned string size.
903 *
904 * RETURNS
905 * Success: TRUE
906 * Failure: FALSE
907 */
908 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
909 LPINT nfit, LPINT dxs, LPSIZE size )
910 {
911 BOOL ret = FALSE;
912 DC * dc = get_dc_ptr( hdc );
913 if (!dc) return FALSE;
914
915 if(dc->gdiFont) {
916 ret = WineEngGetTextExtentExPointI(dc->gdiFont, indices, count, max_ext, nfit, dxs, size);
917 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
918 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
919 size->cx += count * dc->charExtra;
920 }
921 else if(dc->funcs->pGetTextExtentExPoint) {
922 FIXME("calling GetTextExtentExPoint\n");
923 ret = dc->funcs->pGetTextExtentExPoint( dc->physDev, (LPCWSTR)indices,
924 count, max_ext, nfit, dxs, size );
925 }
926
927 release_dc_ptr( dc );
928
929 TRACE("(%p %p %d %p): returning %d x %d\n",
930 hdc, indices, count, size, size->cx, size->cy );
931 return ret;
932 }
933
934 /***********************************************************************
935 * GetTextExtentPointI [GDI32.@]
936 *
937 * Computes width and height of the array of glyph indices.
938 *
939 * PARAMS
940 * hdc [I] Handle of device context.
941 * indices [I] Glyph index array.
942 * count [I] Number of glyphs in array.
943 * size [O] Returned string size.
944 *
945 * RETURNS
946 * Success: TRUE
947 * Failure: FALSE
948 */
949 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
950 {
951 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
952 }
953
954
955 /***********************************************************************
956 * GetTextExtentPointA (GDI32.@)
957 */
958 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
959 LPSIZE size )
960 {
961 TRACE("not bug compatible.\n");
962 return GetTextExtentPoint32A( hdc, str, count, size );
963 }
964
965 /***********************************************************************
966 * GetTextExtentPointW (GDI32.@)
967 */
968 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
969 LPSIZE size )
970 {
971 TRACE("not bug compatible.\n");
972 return GetTextExtentPoint32W( hdc, str, count, size );
973 }
974
975
976 /***********************************************************************
977 * GetTextExtentExPointA (GDI32.@)
978 */
979 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
980 INT maxExt, LPINT lpnFit,
981 LPINT alpDx, LPSIZE size )
982 {
983 BOOL ret;
984 INT wlen;
985 INT *walpDx = NULL;
986 LPWSTR p = NULL;
987
988 if (alpDx &&
989 NULL == (walpDx = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT))))
990 return FALSE;
991
992 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
993 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
994 if (walpDx)
995 {
996 INT n = lpnFit ? *lpnFit : wlen;
997 INT i, j;
998 for(i = 0, j = 0; i < n; i++, j++)
999 {
1000 alpDx[j] = walpDx[i];
1001 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1002 }
1003 }
1004 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1005 HeapFree( GetProcessHeap(), 0, p );
1006 HeapFree( GetProcessHeap(), 0, walpDx );
1007 return ret;
1008 }
1009
1010
1011 /***********************************************************************
1012 * GetTextExtentExPointW (GDI32.@)
1013 *
1014 * Return the size of the string as it would be if it was output properly by
1015 * e.g. TextOut.
1016 *
1017 * This should include
1018 * - Intercharacter spacing
1019 * - justification spacing (not yet done)
1020 * - kerning? see below
1021 *
1022 * Kerning. Since kerning would be carried out by the rendering code it should
1023 * be done by the driver. However they don't support it yet. Also I am not
1024 * yet persuaded that (certainly under Win95) any kerning is actually done.
1025 *
1026 * str: According to MSDN this should be null-terminated. That is not true; a
1027 * null will not terminate it early.
1028 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1029 * than count. I have seen it be either the size of the full string or
1030 * 1 less than the size of the full string. I have not seen it bear any
1031 * resemblance to the portion that would fit.
1032 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1033 * trailing intercharacter spacing and any trailing justification.
1034 *
1035 * FIXME
1036 * Currently we do this by measuring each character etc. We should do it by
1037 * passing the request to the driver, perhaps by extending the
1038 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1039 * thinking about kerning issues and rounding issues in the justification.
1040 */
1041
1042 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1043 INT maxExt, LPINT lpnFit,
1044 LPINT alpDx, LPSIZE size )
1045 {
1046 INT nFit = 0;
1047 LPINT dxs = NULL;
1048 DC *dc;
1049 BOOL ret = FALSE;
1050 TEXTMETRICW tm;
1051
1052 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1053
1054 dc = get_dc_ptr(hdc);
1055 if (! dc)
1056 return FALSE;
1057
1058 GetTextMetricsW(hdc, &tm);
1059
1060 /* If we need to calculate nFit, then we need the partial extents even if
1061 the user hasn't provided us with an array. */
1062 if (lpnFit)
1063 {
1064 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1065 if (! dxs)
1066 {
1067 release_dc_ptr(dc);
1068 SetLastError(ERROR_OUTOFMEMORY);
1069 return FALSE;
1070 }
1071 }
1072 else
1073 dxs = alpDx;
1074
1075 if (dc->gdiFont)
1076 ret = WineEngGetTextExtentExPoint(dc->gdiFont, str, count,
1077 0, NULL, dxs, size);
1078 else if (dc->funcs->pGetTextExtentExPoint)
1079 ret = dc->funcs->pGetTextExtentExPoint(dc->physDev, str, count,
1080 0, NULL, dxs, size);
1081
1082 /* Perform device size to world size transformations. */
1083 if (ret)
1084 {
1085 INT extra = dc->charExtra,
1086 breakExtra = dc->breakExtra,
1087 breakRem = dc->breakRem,
1088 i;
1089
1090 if (dxs)
1091 {
1092 for (i = 0; i < count; ++i)
1093 {
1094 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1095 dxs[i] += (i+1) * extra;
1096 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1097 {
1098 dxs[i] += breakExtra;
1099 if (breakRem > 0)
1100 {
1101 breakRem--;
1102 dxs[i]++;
1103 }
1104 }
1105 if (dxs[i] <= maxExt)
1106 ++nFit;
1107 }
1108 breakRem = dc->breakRem;
1109 }
1110 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1111 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1112
1113 if (!dxs && count > 1 && (breakExtra || breakRem))
1114 {
1115 for (i = 0; i < count; i++)
1116 {
1117 if (str[i] == tm.tmBreakChar)
1118 {
1119 size->cx += breakExtra;
1120 if (breakRem > 0)
1121 {
1122 breakRem--;
1123 (size->cx)++;
1124 }
1125 }
1126 }
1127 }
1128 }
1129
1130 if (lpnFit)
1131 *lpnFit = nFit;
1132
1133 if (! alpDx)
1134 HeapFree(GetProcessHeap(), 0, dxs);
1135
1136 release_dc_ptr( dc );
1137
1138 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1139 return ret;
1140 }
1141
1142 /***********************************************************************
1143 * GetTextMetricsA (GDI32.@)
1144 */
1145 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1146 {
1147 TEXTMETRICW tm32;
1148
1149 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1150 FONT_TextMetricWToA( &tm32, metrics );
1151 return TRUE;
1152 }
1153
1154 /***********************************************************************
1155 * GetTextMetricsW (GDI32.@)
1156 */
1157 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1158 {
1159 BOOL ret = FALSE;
1160 DC * dc = get_dc_ptr( hdc );
1161 if (!dc) return FALSE;
1162
1163 if (dc->gdiFont)
1164 ret = WineEngGetTextMetrics(dc->gdiFont, metrics);
1165 else if (dc->funcs->pGetTextMetrics)
1166 ret = dc->funcs->pGetTextMetrics( dc->physDev, metrics );
1167
1168 if (ret)
1169 {
1170 /* device layer returns values in device units
1171 * therefore we have to convert them to logical */
1172
1173 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1174 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1175
1176 #define WDPTOLP(x) ((x<0)? \
1177 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1178 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1179 #define HDPTOLP(y) ((y<0)? \
1180 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1181 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1182
1183 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1184 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1185 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1186 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1187 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1188 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1189 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1190 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1191 ret = TRUE;
1192 #undef WDPTOLP
1193 #undef HDPTOLP
1194 TRACE("text metrics:\n"
1195 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1196 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1197 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1198 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1199 " PitchAndFamily = %02x\n"
1200 " --------------------\n"
1201 " InternalLeading = %i\n"
1202 " Ascent = %i\n"
1203 " Descent = %i\n"
1204 " Height = %i\n",
1205 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1206 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1207 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1208 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1209 metrics->tmPitchAndFamily,
1210 metrics->tmInternalLeading,
1211 metrics->tmAscent,
1212 metrics->tmDescent,
1213 metrics->tmHeight );
1214 }
1215 release_dc_ptr( dc );
1216 return ret;
1217 }
1218
1219
1220 /***********************************************************************
1221 * GetOutlineTextMetricsA (GDI32.@)
1222 * Gets metrics for TrueType fonts.
1223 *
1224 * NOTES
1225 * If the supplied buffer isn't big enough Windows partially fills it up to
1226 * its given length and returns that length.
1227 *
1228 * RETURNS
1229 * Success: Non-zero or size of required buffer
1230 * Failure: 0
1231 */
1232 UINT WINAPI GetOutlineTextMetricsA(
1233 HDC hdc, /* [in] Handle of device context */
1234 UINT cbData, /* [in] Size of metric data array */
1235 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1236 {
1237 char buf[512], *ptr;
1238 UINT ret, needed;
1239 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1240 OUTLINETEXTMETRICA *output = lpOTM;
1241 INT left, len;
1242
1243 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1244 return 0;
1245 if(ret > sizeof(buf))
1246 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1247 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1248
1249 needed = sizeof(OUTLINETEXTMETRICA);
1250 if(lpOTMW->otmpFamilyName)
1251 needed += WideCharToMultiByte(CP_ACP, 0,
1252 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1253 NULL, 0, NULL, NULL);
1254 if(lpOTMW->otmpFaceName)
1255 needed += WideCharToMultiByte(CP_ACP, 0,
1256 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1257 NULL, 0, NULL, NULL);
1258 if(lpOTMW->otmpStyleName)
1259 needed += WideCharToMultiByte(CP_ACP, 0,
1260 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1261 NULL, 0, NULL, NULL);
1262 if(lpOTMW->otmpFullName)
1263 needed += WideCharToMultiByte(CP_ACP, 0,
1264 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1265 NULL, 0, NULL, NULL);
1266
1267 if(!lpOTM) {
1268 ret = needed;
1269 goto end;
1270 }
1271
1272 TRACE("needed = %d\n", needed);
1273 if(needed > cbData)
1274 /* Since the supplied buffer isn't big enough, we'll alloc one
1275 that is and memcpy the first cbData bytes into the lpOTM at
1276 the end. */
1277 output = HeapAlloc(GetProcessHeap(), 0, needed);
1278
1279 ret = output->otmSize = min(needed, cbData);
1280 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1281 output->otmFiller = 0;
1282 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1283 output->otmfsSelection = lpOTMW->otmfsSelection;
1284 output->otmfsType = lpOTMW->otmfsType;
1285 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1286 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1287 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1288 output->otmEMSquare = lpOTMW->otmEMSquare;
1289 output->otmAscent = lpOTMW->otmAscent;
1290 output->otmDescent = lpOTMW->otmDescent;
1291 output->otmLineGap = lpOTMW->otmLineGap;
1292 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1293 output->otmsXHeight = lpOTMW->otmsXHeight;
1294 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1295 output->otmMacAscent = lpOTMW->otmMacAscent;
1296 output->otmMacDescent = lpOTMW->otmMacDescent;
1297 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1298 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1299 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1300 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1301 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1302 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1303 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1304 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1305 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1306 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1307
1308
1309 ptr = (char*)(output + 1);
1310 left = needed - sizeof(*output);
1311
1312 if(lpOTMW->otmpFamilyName) {
1313 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1314 len = WideCharToMultiByte(CP_ACP, 0,
1315 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1316 ptr, left, NULL, NULL);
1317 left -= len;
1318 ptr += len;
1319 } else
1320 output->otmpFamilyName = 0;
1321
1322 if(lpOTMW->otmpFaceName) {
1323 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1324 len = WideCharToMultiByte(CP_ACP, 0,
1325 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1326 ptr, left, NULL, NULL);
1327 left -= len;
1328 ptr += len;
1329 } else
1330 output->otmpFaceName = 0;
1331
1332 if(lpOTMW->otmpStyleName) {
1333 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1334 len = WideCharToMultiByte(CP_ACP, 0,
1335 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1336 ptr, left, NULL, NULL);
1337 left -= len;
1338 ptr += len;
1339 } else
1340 output->otmpStyleName = 0;
1341
1342 if(lpOTMW->otmpFullName) {
1343 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1344 len = WideCharToMultiByte(CP_ACP, 0,
1345 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1346 ptr, left, NULL, NULL);
1347 left -= len;
1348 } else
1349 output->otmpFullName = 0;
1350
1351 assert(left == 0);
1352
1353 if(output != lpOTM) {
1354 memcpy(lpOTM, output, cbData);
1355 HeapFree(GetProcessHeap(), 0, output);
1356
1357 /* check if the string offsets really fit into the provided size */
1358 /* FIXME: should we check string length as well? */
1359 /* make sure that we don't read/write beyond the provided buffer */
1360 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1361 {
1362 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1363 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1364 }
1365
1366 /* make sure that we don't read/write beyond the provided buffer */
1367 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1368 {
1369 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1370 lpOTM->otmpFaceName = 0; /* doesn't fit */
1371 }
1372
1373 /* make sure that we don't read/write beyond the provided buffer */
1374 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1375 {
1376 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1377 lpOTM->otmpStyleName = 0; /* doesn't fit */
1378 }
1379
1380 /* make sure that we don't read/write beyond the provided buffer */
1381 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1382 {
1383 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1384 lpOTM->otmpFullName = 0; /* doesn't fit */
1385 }
1386 }
1387
1388 end:
1389 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1390 HeapFree(GetProcessHeap(), 0, lpOTMW);
1391
1392 return ret;
1393 }
1394
1395
1396 /***********************************************************************
1397 * GetOutlineTextMetricsW [GDI32.@]
1398 */
1399 UINT WINAPI GetOutlineTextMetricsW(
1400 HDC hdc, /* [in] Handle of device context */
1401 UINT cbData, /* [in] Size of metric data array */
1402 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1403 {
1404 DC *dc = get_dc_ptr( hdc );
1405 OUTLINETEXTMETRICW *output = lpOTM;
1406 UINT ret;
1407
1408 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1409 if(!dc) return 0;
1410
1411 if(dc->gdiFont) {
1412 ret = WineEngGetOutlineTextMetrics(dc->gdiFont, cbData, output);
1413 if(lpOTM && ret) {
1414 if(ret > cbData) {
1415 output = HeapAlloc(GetProcessHeap(), 0, ret);
1416 WineEngGetOutlineTextMetrics(dc->gdiFont, ret, output);
1417 }
1418
1419 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1420 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1421
1422 #define WDPTOLP(x) ((x<0)? \
1423 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1424 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1425 #define HDPTOLP(y) ((y<0)? \
1426 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1427 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1428
1429 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1430 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1431 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1432 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1433 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1434 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1435 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1436 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1437 output->otmAscent = HDPTOLP(output->otmAscent);
1438 output->otmDescent = HDPTOLP(output->otmDescent);
1439 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1440 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1441 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1442 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1443 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1444 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1445 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1446 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1447 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1448 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1449 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1450 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1451 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1452 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1453 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1454 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1455 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1456 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1457 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1458 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1459 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1460 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1461 #undef WDPTOLP
1462 #undef HDPTOLP
1463 if(output != lpOTM) {
1464 memcpy(lpOTM, output, cbData);
1465 HeapFree(GetProcessHeap(), 0, output);
1466 ret = cbData;
1467 }
1468 }
1469 }
1470
1471 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1472 but really this should just be a return 0. */
1473
1474 ret = sizeof(*lpOTM);
1475 if (lpOTM) {
1476 if(cbData < ret)
1477 ret = 0;
1478 else {
1479 memset(lpOTM, 0, ret);
1480 lpOTM->otmSize = sizeof(*lpOTM);
1481 GetTextMetricsW(hdc, &lpOTM->otmTextMetrics);
1482 /*
1483 Further fill of the structure not implemented,
1484 Needs real values for the structure members
1485 */
1486 }
1487 }
1488 }
1489 release_dc_ptr(dc);
1490 return ret;
1491 }
1492
1493
1494 /***********************************************************************
1495 * GetCharWidthW (GDI32.@)
1496 * GetCharWidth32W (GDI32.@)
1497 */
1498 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1499 LPINT buffer )
1500 {
1501 UINT i;
1502 BOOL ret = FALSE;
1503 DC * dc = get_dc_ptr( hdc );
1504 if (!dc) return FALSE;
1505
1506 if (dc->gdiFont)
1507 ret = WineEngGetCharWidth( dc->gdiFont, firstChar, lastChar, buffer );
1508 else if (dc->funcs->pGetCharWidth)
1509 ret = dc->funcs->pGetCharWidth( dc->physDev, firstChar, lastChar, buffer);
1510
1511 if (ret)
1512 {
1513 /* convert device units to logical */
1514 for( i = firstChar; i <= lastChar; i++, buffer++ )
1515 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1516 ret = TRUE;
1517 }
1518 release_dc_ptr( dc );
1519 return ret;
1520 }
1521
1522
1523 /***********************************************************************
1524 * GetCharWidthA (GDI32.@)
1525 * GetCharWidth32A (GDI32.@)
1526 */
1527 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1528 LPINT buffer )
1529 {
1530 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
1531 LPSTR str;
1532 LPWSTR wstr;
1533 BOOL ret = TRUE;
1534
1535 if(count <= 0) return FALSE;
1536
1537 str = HeapAlloc(GetProcessHeap(), 0, count);
1538 for(i = 0; i < count; i++)
1539 str[i] = (BYTE)(firstChar + i);
1540
1541 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1542
1543 for(i = 0; i < wlen; i++)
1544 {
1545 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1546 {
1547 ret = FALSE;
1548 break;
1549 }
1550 buffer++;
1551 }
1552
1553 HeapFree(GetProcessHeap(), 0, str);
1554 HeapFree(GetProcessHeap(), 0, wstr);
1555
1556 return ret;
1557 }
1558
1559
1560 /***********************************************************************
1561 * ExtTextOutA (GDI32.@)
1562 *
1563 * See ExtTextOutW.
1564 */
1565 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1566 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1567 {
1568 INT wlen;
1569 UINT codepage;
1570 LPWSTR p;
1571 BOOL ret;
1572 LPINT lpDxW = NULL;
1573
1574 if (flags & ETO_GLYPH_INDEX)
1575 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1576
1577 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
1578
1579 if (lpDx) {
1580 unsigned int i = 0, j = 0;
1581
1582 lpDxW = HeapAlloc( GetProcessHeap(), 0, wlen*sizeof(INT));
1583 while(i < count) {
1584 if(IsDBCSLeadByteEx(codepage, str[i])) {
1585 lpDxW[j++] = lpDx[i] + lpDx[i+1];
1586 i = i + 2;
1587 } else {
1588 lpDxW[j++] = lpDx[i];
1589 i = i + 1;
1590 }
1591 }
1592 }
1593
1594 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
1595
1596 HeapFree( GetProcessHeap(), 0, p );
1597 HeapFree( GetProcessHeap(), 0, lpDxW );
1598 return ret;
1599 }
1600
1601
1602 /***********************************************************************
1603 * ExtTextOutW (GDI32.@)
1604 *
1605 * Draws text using the currently selected font, background color, and text color.
1606 *
1607 *
1608 * PARAMS
1609 * x,y [I] coordinates of string
1610 * flags [I]
1611 * ETO_GRAYED - undocumented on MSDN
1612 * ETO_OPAQUE - use background color for fill the rectangle
1613 * ETO_CLIPPED - clipping text to the rectangle
1614 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1615 * than encoded characters. Implies ETO_IGNORELANGUAGE
1616 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1617 * Affects BiDi ordering
1618 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1619 * ETO_PDY - unimplemented
1620 * ETO_NUMERICSLATIN - unimplemented always assumed -
1621 * do not translate numbers into locale representations
1622 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1623 * lprect [I] dimensions for clipping or/and opaquing
1624 * str [I] text string
1625 * count [I] number of symbols in string
1626 * lpDx [I] optional parameter with distance between drawing characters
1627 *
1628 * RETURNS
1629 * Success: TRUE
1630 * Failure: FALSE
1631 */
1632 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
1633 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
1634 {
1635 BOOL ret = FALSE;
1636 LPWSTR reordered_str = (LPWSTR)str;
1637 WORD *glyphs = NULL;
1638 UINT align = GetTextAlign( hdc );
1639 POINT pt;
1640 TEXTMETRICW tm;
1641 LOGFONTW lf;
1642 double cosEsc, sinEsc;
1643 INT *deltas = NULL, char_extra;
1644 SIZE sz;
1645 RECT rc;
1646 BOOL done_extents = FALSE;
1647 INT width = 0, xwidth = 0, ywidth = 0;
1648 DWORD type;
1649 DC * dc = get_dc_ptr( hdc );
1650 INT breakRem;
1651
1652 if (!dc) return FALSE;
1653
1654 breakRem = dc->breakRem;
1655
1656 if (flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY))
1657 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN | ETO_PDY unimplemented\n");
1658
1659 if (!dc->funcs->pExtTextOut && !PATH_IsPathOpen(dc->path))
1660 {
1661 release_dc_ptr( dc );
1662 return ret;
1663 }
1664
1665 update_dc( dc );
1666 type = GetObjectType(hdc);
1667 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
1668 {
1669 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, flags, lprect, str, count, lpDx);
1670 release_dc_ptr( dc );
1671 return ret;
1672 }
1673
1674 if (!lprect)
1675 flags &= ~ETO_CLIPPED;
1676
1677 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
1678 {
1679 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
1680
1681 BIDI_Reorder( str, count, GCP_REORDER,
1682 ((flags&ETO_RTLREADING)!=0 || (GetTextAlign(hdc)&TA_RTLREADING)!=0)?
1683 WINE_GCPW_FORCE_RTL:WINE_GCPW_FORCE_LTR,
1684 reordered_str, count, NULL );
1685
1686 flags |= ETO_IGNORELANGUAGE;
1687 }
1688
1689 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc, x, y, flags,
1690 lprect, debugstr_wn(str, count), count, lpDx);
1691
1692 if(flags & ETO_GLYPH_INDEX)
1693 glyphs = reordered_str;
1694
1695 if(lprect)
1696 TRACE("rect: %d,%d - %d,%d\n", lprect->left, lprect->top, lprect->right,
1697 lprect->bottom);
1698 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
1699
1700 if(align & TA_UPDATECP)
1701 {
1702 GetCurrentPositionEx( hdc, &pt );
1703 x = pt.x;
1704 y = pt.y;
1705 }
1706
1707 GetTextMetricsW(hdc, &tm);
1708 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
1709
1710 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
1711 lf.lfEscapement = 0;
1712
1713 if(lf.lfEscapement != 0)
1714 {
1715 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
1716 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
1717 }
1718 else
1719 {
1720 cosEsc = 1;
1721 sinEsc = 0;
1722 }
1723
1724 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
1725 {
1726 if(!lprect)
1727 {
1728 if(flags & ETO_GLYPH_INDEX)
1729 GetTextExtentPointI(hdc, glyphs, count, &sz);
1730 else
1731 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1732
1733 done_extents = TRUE;
1734 rc.left = x;
1735 rc.top = y;
1736 rc.right = x + sz.cx;
1737 rc.bottom = y + sz.cy;
1738 }
1739 else
1740 {
1741 rc = *lprect;
1742 }
1743
1744 LPtoDP(hdc, (POINT*)&rc, 2);
1745
1746 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
1747 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
1748 }
1749
1750 if ((flags & ETO_OPAQUE) && !PATH_IsPathOpen(dc->path))
1751 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1752
1753 if(count == 0)
1754 {
1755 ret = TRUE;
1756 goto done;
1757 }
1758
1759 pt.x = x;
1760 pt.y = y;
1761 LPtoDP(hdc, &pt, 1);
1762 x = pt.x;
1763 y = pt.y;
1764
1765 char_extra = GetTextCharacterExtra(hdc);
1766 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
1767 {
1768 UINT i;
1769 SIZE tmpsz;
1770 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(INT));
1771 for(i = 0; i < count; i++)
1772 {
1773 if(lpDx && (flags & ETO_PDY))
1774 deltas[i] = lpDx[i*2] + char_extra;
1775 else if(lpDx)
1776 deltas[i] = lpDx[i] + char_extra;
1777 else
1778 {
1779 if(flags & ETO_GLYPH_INDEX)
1780 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
1781 else
1782 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
1783
1784 deltas[i] = tmpsz.cx;
1785 }
1786
1787 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
1788 {
1789 deltas[i] = deltas[i] + dc->breakExtra;
1790 if (breakRem > 0)
1791 {
1792 breakRem--;
1793 deltas[i]++;
1794 }
1795 }
1796 deltas[i] = INTERNAL_XWSTODS(dc, deltas[i]);
1797 width += deltas[i];
1798 }
1799 }
1800 else
1801 {
1802 if(!done_extents)
1803 {
1804 if(flags & ETO_GLYPH_INDEX)
1805 GetTextExtentPointI(hdc, glyphs, count, &sz);
1806 else
1807 GetTextExtentPointW(hdc, reordered_str, count, &sz);
1808 done_extents = TRUE;
1809 }
1810 width = INTERNAL_XWSTODS(dc, sz.cx);
1811 }
1812 xwidth = width * cosEsc;
1813 ywidth = width * sinEsc;
1814
1815 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
1816 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
1817 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
1818 {
1819 case TA_LEFT:
1820 if (align & TA_UPDATECP)
1821 {
1822 pt.x = x + xwidth;
1823 pt.y = y - ywidth;
1824 DPtoLP(hdc, &pt, 1);
1825 MoveToEx(hdc, pt.x, pt.y, NULL);
1826 }
1827 break;
1828
1829 case TA_CENTER:
1830 x -= xwidth / 2;
1831 y += ywidth / 2;
1832 break;
1833
1834 case TA_RIGHT:
1835 x -= xwidth;
1836 y += ywidth;
1837 if (align & TA_UPDATECP)
1838 {
1839 pt.x = x;
1840 pt.y = y;
1841 DPtoLP(hdc, &pt, 1);
1842 MoveToEx(hdc, pt.x, pt.y, NULL);
1843 }
1844 break;
1845 }
1846
1847 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
1848 {
1849 case TA_TOP:
1850 y += tm.tmAscent * cosEsc;
1851 x += tm.tmAscent * sinEsc;
1852 break;
1853
1854 case TA_BOTTOM:
1855 y -= tm.tmDescent * cosEsc;
1856 x -= tm.tmDescent * sinEsc;
1857 break;
1858
1859 case TA_BASELINE:
1860 break;
1861 }
1862
1863 if (GetBkMode(hdc) != TRANSPARENT && !PATH_IsPathOpen(dc->path))
1864 {
1865 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
1866 {
1867 if(!(flags & ETO_OPAQUE) || x < rc.left || x + width >= rc.right ||
1868 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
1869 {
1870 RECT rc;
1871 rc.left = x;
1872 rc.right = x + width;
1873 rc.top = y - tm.tmAscent;
1874 rc.bottom = y + tm.tmDescent;
1875 dc->funcs->pExtTextOut(dc->physDev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL);
1876 }
1877 }
1878 }
1879
1880 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
1881 {
1882 HFONT orig_font = dc->hFont, cur_font;
1883 UINT glyph;
1884 INT span = 0, *offsets = NULL;
1885 unsigned int i;
1886
1887 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1888 for(i = 0; i < count; i++)
1889 {
1890 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
1891 if(cur_font != dc->hFont)
1892 {
1893 if(!offsets)
1894 {
1895 unsigned int j;
1896 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
1897 offsets[0] = 0;
1898 if(!deltas)
1899 {
1900 SIZE tmpsz;
1901 for(j = 1; j < count; j++)
1902 {
1903 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
1904 offsets[j] = offsets[j-1] + INTERNAL_XWSTODS(dc, tmpsz.cx);
1905 }
1906 }
1907 else
1908 {
1909 for(j = 1; j < count; j++)
1910 offsets[j] = offsets[j-1] + deltas[j];
1911 }
1912 }
1913 if(span)
1914 {
1915 if (PATH_IsPathOpen(dc->path))
1916 ret = PATH_ExtTextOut(dc, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1917 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1918 glyphs, span, deltas ? deltas + i - span : NULL);
1919 else
1920 dc->funcs->pExtTextOut(dc->physDev, x + offsets[i - span] * cosEsc, y - offsets[i - span] * sinEsc,
1921 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1922 glyphs, span, deltas ? deltas + i - span : NULL);
1923 span = 0;
1924 }
1925 SelectObject(hdc, cur_font);
1926 }
1927 glyphs[span++] = glyph;
1928
1929 if(i == count - 1)
1930 {
1931 if (PATH_IsPathOpen(dc->path))
1932 ret = PATH_ExtTextOut(dc, x + (offsets ? offsets[count - span] * cosEsc : 0),
1933 y - (offsets ? offsets[count - span] * sinEsc : 0),
1934 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1935 glyphs, span, deltas ? deltas + count - span : NULL);
1936 else
1937 ret = dc->funcs->pExtTextOut(dc->physDev, x + (offsets ? offsets[count - span] * cosEsc : 0),
1938 y - (offsets ? offsets[count - span] * sinEsc : 0),
1939 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc,
1940 glyphs, span, deltas ? deltas + count - span : NULL);
1941 SelectObject(hdc, orig_font);
1942 HeapFree(GetProcessHeap(), 0, offsets);
1943 }
1944 }
1945 }
1946 else
1947 {
1948 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
1949 {
1950 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
1951 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
1952 flags |= ETO_GLYPH_INDEX;
1953 }
1954
1955 if (PATH_IsPathOpen(dc->path))
1956 ret = PATH_ExtTextOut(dc, x, y, (flags & ~ETO_OPAQUE), &rc,
1957 glyphs ? glyphs : reordered_str, count, deltas);
1958 else
1959 ret = dc->funcs->pExtTextOut(dc->physDev, x, y, (flags & ~ETO_OPAQUE), &rc,
1960 glyphs ? glyphs : reordered_str, count, deltas);
1961 }
1962
1963 done:
1964 HeapFree(GetProcessHeap(), 0, deltas);
1965 if(glyphs != reordered_str)
1966 HeapFree(GetProcessHeap(), 0, glyphs);
1967 if(reordered_str != str)
1968 HeapFree(GetProcessHeap(), 0, reordered_str);
1969
1970 release_dc_ptr( dc );
1971
1972 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
1973 {
1974 int underlinePos, strikeoutPos;
1975 int underlineWidth, strikeoutWidth;
1976 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
1977 OUTLINETEXTMETRICW* otm = NULL;
1978
1979 if(!size)
1980 {
1981 underlinePos = 0;
1982 underlineWidth = tm.tmAscent / 20 + 1;
1983 strikeoutPos = tm.tmAscent / 2;
1984 strikeoutWidth = underlineWidth;
1985 }
1986 else
1987 {
1988 otm = HeapAlloc(GetProcessHeap(), 0, size);
1989 GetOutlineTextMetricsW(hdc, size, otm);
1990 underlinePos = otm->otmsUnderscorePosition;
1991 underlineWidth = otm->otmsUnderscoreSize;
1992 strikeoutPos = otm->otmsStrikeoutPosition;
1993 strikeoutWidth = otm->otmsStrikeoutSize;
1994 HeapFree(GetProcessHeap(), 0, otm);
1995 }
1996
1997 if (PATH_IsPathOpen(dc->path))
1998 {
1999 POINT pts[5];
2000 HPEN hpen;
2001 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2002
2003 hbrush = SelectObject(hdc, hbrush);
2004 hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2005
2006 if (lf.lfUnderline)
2007 {
2008 pts[0].x = x - underlinePos * sinEsc;
2009 pts[0].y = y - underlinePos * cosEsc;
2010 pts[1].x = x + xwidth - underlinePos * sinEsc;
2011 pts[1].y = y - ywidth - underlinePos * cosEsc;
2012 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2013 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2014 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2015 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2016 pts[4].x = pts[0].x;
2017 pts[4].y = pts[0].y;
2018 DPtoLP(hdc, pts, 5);
2019 Polygon(hdc, pts, 5);
2020 }
2021
2022 if (lf.lfStrikeOut)
2023 {
2024 pts[0].x = x - strikeoutPos * sinEsc;
2025 pts[0].y = y - strikeoutPos * cosEsc;
2026 pts[1].x = x + xwidth - strikeoutPos * sinEsc;
2027 pts[1].y = y - ywidth - strikeoutPos * cosEsc;
2028 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2029 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2030 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2031 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2032 pts[4].x = pts[0].x;
2033 pts[4].y = pts[0].y;
2034 DPtoLP(hdc, pts, 5);
2035 Polygon(hdc, pts, 5);
2036 }
2037
2038 SelectObject(hdc, hpen);
2039 hbrush = SelectObject(hdc, hbrush);
2040 DeleteObject(hbrush);
2041 }
2042 else
2043 {
2044 POINT pts[2], oldpt;
2045 HPEN hpen;
2046
2047 if (lf.lfUnderline)
2048 {
2049 hpen = CreatePen(PS_SOLID, underlineWidth, GetTextColor(hdc));
2050 hpen = SelectObject(hdc, hpen);
2051 pts[0].x = x;
2052 pts[0].y = y;
2053 pts[1].x = x + xwidth;
2054 pts[1].y = y - ywidth;
2055 DPtoLP(hdc, pts, 2);
2056 MoveToEx(hdc, pts[0].x - underlinePos * sinEsc, pts[0].y - underlinePos * cosEsc, &oldpt);
2057 LineTo(hdc, pts[1].x - underlinePos * sinEsc, pts[1].y - underlinePos * cosEsc);
2058 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2059 DeleteObject(SelectObject(hdc, hpen));
2060 }
2061
2062 if (lf.lfStrikeOut)
2063 {
2064 hpen = CreatePen(PS_SOLID, strikeoutWidth, GetTextColor(hdc));
2065 hpen = SelectObject(hdc, hpen);
2066 pts[0].x = x;
2067 pts[0].y = y;
2068 pts[1].x = x + xwidth;
2069 pts[1].y = y - ywidth;
2070 DPtoLP(hdc, pts, 2);
2071 MoveToEx(hdc, pts[0].x - strikeoutPos * sinEsc, pts[0].y - strikeoutPos * cosEsc, &oldpt);
2072 LineTo(hdc, pts[1].x - strikeoutPos * sinEsc, pts[1].y - strikeoutPos * cosEsc);
2073 MoveToEx(hdc, oldpt.x, oldpt.y, NULL);
2074 DeleteObject(SelectObject(hdc, hpen));
2075 }
2076 }
2077 }
2078
2079 return ret;
2080 }
2081
2082
2083 /***********************************************************************
2084 * TextOutA (GDI32.@)
2085 */
2086 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2087 {
2088 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2089 }
2090
2091
2092 /***********************************************************************
2093 * TextOutW (GDI32.@)
2094 */
2095 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2096 {
2097 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2098 }
2099
2100
2101 /***********************************************************************
2102 * PolyTextOutA (GDI32.@)
2103 *
2104 * See PolyTextOutW.
2105 */
2106 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2107 {
2108 for (; cStrings>0; cStrings--, pptxt++)
2109 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2110 return FALSE;
2111 return TRUE;
2112 }
2113
2114
2115
2116 /***********************************************************************
2117 * PolyTextOutW (GDI32.@)
2118 *
2119 * Draw several Strings
2120 *
2121 * RETURNS
2122 * TRUE: Success.
2123 * FALSE: Failure.
2124 */
2125 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2126 {
2127 for (; cStrings>0; cStrings--, pptxt++)
2128 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2129 return FALSE;
2130 return TRUE;
2131 }
2132
2133
2134 /* FIXME: all following APIs ******************************************/
2135
2136
2137 /***********************************************************************
2138 * SetMapperFlags (GDI32.@)
2139 */
2140 DWORD WINAPI SetMapperFlags( HDC hDC, DWORD dwFlag )
2141 {
2142 DC *dc = get_dc_ptr( hDC );
2143 DWORD ret = 0;
2144 if(!dc) return 0;
2145 if(dc->funcs->pSetMapperFlags)
2146 {
2147 ret = dc->funcs->pSetMapperFlags( dc->physDev, dwFlag );
2148 /* FIXME: ret is just a success flag, we should return a proper value */
2149 }
2150 else
2151 FIXME("(%p, 0x%08x): stub - harmless\n", hDC, dwFlag);
2152 release_dc_ptr( dc );
2153 return ret;
2154 }
2155
2156 /***********************************************************************
2157 * GetAspectRatioFilterEx (GDI32.@)
2158 */
2159 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2160 {
2161 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2162 return FALSE;
2163 }
2164
2165
2166 /***********************************************************************
2167 * GetCharABCWidthsA (GDI32.@)
2168 *
2169 * See GetCharABCWidthsW.
2170 */
2171 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2172 LPABC abc )
2173 {
2174 INT i, wlen, count = (INT)(lastChar - firstChar + 1);
2175 LPSTR str;
2176 LPWSTR wstr;
2177 BOOL ret = TRUE;
2178
2179 if(count <= 0) return FALSE;
2180
2181 str = HeapAlloc(GetProcessHeap(), 0, count);
2182 for(i = 0; i < count; i++)
2183 str[i] = (BYTE)(firstChar + i);
2184
2185 wstr = FONT_mbtowc(hdc, str, count, &wlen, NULL);
2186
2187 for(i = 0; i < wlen; i++)
2188 {
2189 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2190 {
2191 ret = FALSE;
2192 break;
2193 }
2194 abc++;
2195 }
2196
2197 HeapFree(GetProcessHeap(), 0, str);
2198 HeapFree(GetProcessHeap(), 0, wstr);
2199
2200 return ret;
2201 }
2202
2203
2204 /******************************************************************************
2205 * GetCharABCWidthsW [GDI32.@]
2206 *
2207 * Retrieves widths of characters in range.
2208 *
2209 * PARAMS
2210 * hdc [I] Handle of device context
2211 * firstChar [I] First character in range to query
2212 * lastChar [I] Last character in range to query
2213 * abc [O] Address of character-width structure
2214 *
2215 * NOTES
2216 * Only works with TrueType fonts
2217 *
2218 * RETURNS
2219 * Success: TRUE
2220 * Failure: FALSE
2221 */
2222 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2223 LPABC abc )
2224 {
2225 DC *dc = get_dc_ptr(hdc);
2226 unsigned int i;
2227 BOOL ret = FALSE;
2228
2229 if (!dc) return FALSE;
2230
2231 if (!abc)
2232 {
2233 release_dc_ptr( dc );
2234 return FALSE;
2235 }
2236
2237 if(dc->gdiFont)
2238 ret = WineEngGetCharABCWidths( dc->gdiFont, firstChar, lastChar, abc );
2239 else
2240 FIXME(": stub\n");
2241
2242 if (ret)
2243 {
2244 /* convert device units to logical */
2245 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2246 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2247 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2248 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2249 }
2250 ret = TRUE;
2251 }
2252
2253 release_dc_ptr( dc );
2254 return ret;
2255 }
2256
2257
2258 /******************************************************************************
2259 * GetCharABCWidthsI [GDI32.@]
2260 *
2261 * Retrieves widths of characters in range.
2262 *
2263 * PARAMS
2264 * hdc [I] Handle of device context
2265 * firstChar [I] First glyphs in range to query
2266 * count [I] Last glyphs in range to query
2267 * pgi [i] Array of glyphs to query
2268 * abc [O] Address of character-width structure
2269 *
2270 * NOTES
2271 * Only works with TrueType fonts
2272 *
2273 * RETURNS
2274 * Success: TRUE
2275 * Failure: FALSE
2276 */
2277 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2278 LPWORD pgi, LPABC abc)
2279 {
2280 DC *dc = get_dc_ptr(hdc);
2281 unsigned int i;
2282 BOOL ret = FALSE;
2283
2284 if (!dc) return FALSE;
2285
2286 if (!abc)
2287 {
2288 release_dc_ptr( dc );
2289 return FALSE;
2290 }
2291
2292 if(dc->gdiFont)
2293 ret = WineEngGetCharABCWidthsI( dc->gdiFont, firstChar, count, pgi, abc );
2294 else
2295 FIXME(": stub\n");
2296
2297 if (ret)
2298 {
2299 /* convert device units to logical */
2300 for( i = 0; i < count; i++, abc++ ) {
2301 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2302 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2303 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2304 }
2305 ret = TRUE;
2306 }
2307
2308 release_dc_ptr( dc );
2309 return ret;
2310 }
2311
2312
2313 /***********************************************************************
2314 * GetGlyphOutlineA (GDI32.@)
2315 */
2316 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2317 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2318 LPVOID lpBuffer, const MAT2 *lpmat2 )
2319 {
2320 LPWSTR p = NULL;
2321 DWORD ret;
2322 UINT c;
2323
2324 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2325 int len;
2326 char mbchs[2];
2327 if(uChar > 0xff) { /* but, 2 bytes character only */
2328 len = 2;
2329 mbchs[0] = (uChar & 0xff00) >> 8;
2330 mbchs[1] = (uChar & 0xff);
2331 } else {
2332 len = 1;
2333 mbchs[0] = (uChar & 0xff);
2334 }
2335 p = FONT_mbtowc(hdc, mbchs, len, NULL, NULL);
2336 c = p[0];
2337 } else
2338 c = uChar;
2339 ret = GetGlyphOutlineW(hdc, c, fuFormat, lpgm, cbBuffer, lpBuffer,
2340 lpmat2);
2341 HeapFree(GetProcessHeap(), 0, p);
2342 return ret;
2343 }
2344
2345 /***********************************************************************
2346 * GetGlyphOutlineW (GDI32.@)
2347 */
2348 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2349 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2350 LPVOID lpBuffer, const MAT2 *lpmat2 )
2351 {
2352 DC *dc = get_dc_ptr(hdc);
2353 DWORD ret;
2354
2355 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2356 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2357
2358 if(!dc) return GDI_ERROR;
2359
2360 if(dc->gdiFont)
2361 ret = WineEngGetGlyphOutline(dc->gdiFont, uChar, fuFormat, lpgm,
2362 cbBuffer, lpBuffer, lpmat2);
2363 else
2364 ret = GDI_ERROR;
2365
2366 release_dc_ptr( dc );
2367 return ret;
2368 }
2369
2370
2371 /***********************************************************************
2372 * CreateScalableFontResourceA (GDI32.@)
2373 */
2374 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2375 LPCSTR lpszResourceFile,
2376 LPCSTR lpszFontFile,
2377 LPCSTR lpszCurrentPath )
2378 {
2379 LPWSTR lpszResourceFileW = NULL;
2380 LPWSTR lpszFontFileW = NULL;
2381 LPWSTR lpszCurrentPathW = NULL;
2382 int len;
2383 BOOL ret;
2384
2385 if (lpszResourceFile)
2386 {
2387 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2388 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2389 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2390 }
2391
2392 if (lpszFontFile)
2393 {
2394 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2395 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2396 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2397 }
2398
2399 if (lpszCurrentPath)
2400 {
2401 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2402 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2403 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2404 }
2405
2406 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2407 lpszFontFileW, lpszCurrentPathW);
2408
2409 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2410 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2411 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2412
2413 return ret;
2414 }
2415
2416 /***********************************************************************
2417 * CreateScalableFontResourceW (GDI32.@)
2418 */
2419 BOOL WINAPI CreateScalableFontResourceW( DWORD fHidden,
2420 LPCWSTR lpszResourceFile,
2421 LPCWSTR lpszFontFile,
2422 LPCWSTR lpszCurrentPath )
2423 {
2424 HANDLE f;
2425 FIXME("(%d,%s,%s,%s): stub\n",
2426 fHidden, debugstr_w(lpszResourceFile), debugstr_w(lpszFontFile),
2427 debugstr_w(lpszCurrentPath) );
2428
2429 /* fHidden=1 - only visible for the calling app, read-only, not
2430 * enumerated with EnumFonts/EnumFontFamilies
2431 * lpszCurrentPath can be NULL
2432 */
2433
2434 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2435 if ((f = CreateFileW(lpszResourceFile, 0, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) {
2436 CloseHandle(f);
2437 SetLastError(ERROR_FILE_EXISTS);
2438 return FALSE;
2439 }
2440 return FALSE; /* create failed */
2441 }
2442
2443 /*************************************************************************
2444 * GetKerningPairsA (GDI32.@)
2445 */
2446 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2447 LPKERNINGPAIR kern_pairA )
2448 {
2449 INT charset;
2450 CHARSETINFO csi;
2451 CPINFO cpi;
2452 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2453 KERNINGPAIR *kern_pairW;
2454
2455 if (!cPairs && kern_pairA)
2456 {
2457 SetLastError(ERROR_INVALID_PARAMETER);
2458 return 0;
2459 }
2460
2461 charset = GetTextCharset(hDC);
2462 if (!TranslateCharsetInfo(ULongToPtr(charset), &csi, TCI_SRCCHARSET))
2463 {
2464 FIXME("Can't find codepage for charset %d\n", charset);
2465 return 0;
2466 }
2467 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2468 * to fail on an invalid character for CP_SYMBOL.
2469 */
2470 cpi.DefaultChar[0] = 0;
2471 if (csi.ciACP != CP_SYMBOL && !GetCPInfo(csi.ciACP, &cpi))
2472 {
2473 FIXME("Can't find codepage %u info\n", csi.ciACP);
2474 return 0;
2475 }
2476 TRACE("charset %d => codepage %u\n", charset, csi.ciACP);
2477
2478 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2479 if (!total_kern_pairs) return 0;
2480
2481 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2482 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2483
2484 for (i = 0; i < total_kern_pairs; i++)
2485 {
2486 char first, second;
2487
2488 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2489 continue;
2490
2491 if (!WideCharToMultiByte(csi.ciACP, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2492 continue;
2493
2494 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2495 continue;
2496
2497 if (kern_pairA)
2498 {
2499 if (kern_pairs_copied >= cPairs) break;
2500
2501 kern_pairA->wFirst = (BYTE)first;
2502 kern_pairA->wSecond = (BYTE)second;
2503 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2504 kern_pairA++;
2505 }
2506 kern_pairs_copied++;
2507 }
2508
2509 HeapFree(GetProcessHeap(), 0, kern_pairW);
2510
2511 return kern_pairs_copied;
2512 }
2513
2514 /*************************************************************************
2515 * GetKerningPairsW (GDI32.@)
2516 */
2517 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2518 LPKERNINGPAIR lpKerningPairs )
2519 {
2520 DC *dc;
2521 DWORD ret = 0;
2522
2523 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2524
2525 if (!cPairs && lpKerningPairs)
2526 {
2527 SetLastError(ERROR_INVALID_PARAMETER);
2528 return 0;
2529 }
2530
2531 dc = get_dc_ptr(hDC);
2532 if (!dc) return 0;
2533
2534 if (dc->gdiFont)
2535 ret = WineEngGetKerningPairs(dc->gdiFont, cPairs, lpKerningPairs);
2536
2537 release_dc_ptr( dc );
2538 return ret;
2539 }
2540
2541 /*************************************************************************
2542 * TranslateCharsetInfo [GDI32.@]
2543 *
2544 * Fills a CHARSETINFO structure for a character set, code page, or
2545 * font. This allows making the correspondence between different labels
2546 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2547 * of the same encoding.
2548 *
2549 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2550 * only one codepage should be set in *lpSrc.
2551 *
2552 * RETURNS
2553 * TRUE on success, FALSE on failure.
2554 *
2555 */
2556 BOOL WINAPI TranslateCharsetInfo(
2557 LPDWORD lpSrc, /* [in]
2558 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2559 if flags == TCI_SRCCHARSET: a character set value
2560 if flags == TCI_SRCCODEPAGE: a code page value
2561 */
2562 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
2563 DWORD flags /* [in] determines interpretation of lpSrc */)
2564 {
2565 int index = 0;
2566 switch (flags) {
2567 case TCI_SRCFONTSIG:
2568 while (!(*lpSrc>>index & 0x0001) && index<MAXTCIINDEX) index++;
2569 break;
2570 case TCI_SRCCODEPAGE:
2571 while (PtrToUlong(lpSrc) != FONT_tci[index].ciACP && index < MAXTCIINDEX) index++;
2572 break;
2573 case TCI_SRCCHARSET:
2574 while (PtrToUlong(lpSrc) != FONT_tci[index].ciCharset && index < MAXTCIINDEX) index++;
2575 break;
2576 default:
2577 return FALSE;
2578 }
2579 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
2580 *lpCs = FONT_tci[index];
2581 return TRUE;
2582 }
2583
2584 /*************************************************************************
2585 * GetFontLanguageInfo (GDI32.@)
2586 */
2587 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
2588 {
2589 FONTSIGNATURE fontsig;
2590 static const DWORD GCP_DBCS_MASK=0x003F0000,
2591 GCP_DIACRITIC_MASK=0x00000000,
2592 FLI_GLYPHS_MASK=0x00000000,
2593 GCP_GLYPHSHAPE_MASK=0x00000040,
2594 GCP_KASHIDA_MASK=0x00000000,
2595 GCP_LIGATE_MASK=0x00000000,
2596 GCP_USEKERNING_MASK=0x00000000,
2597 GCP_REORDER_MASK=0x00000060;
2598
2599 DWORD result=0;
2600
2601 GetTextCharsetInfo( hdc, &fontsig, 0 );
2602 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2603
2604 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
2605 result|=GCP_DBCS;
2606
2607 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
2608 result|=GCP_DIACRITIC;
2609
2610 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
2611 result|=FLI_GLYPHS;
2612
2613 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
2614 result|=GCP_GLYPHSHAPE;
2615
2616 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
2617 result|=GCP_KASHIDA;
2618
2619 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
2620 result|=GCP_LIGATE;
2621
2622 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
2623 result|=GCP_USEKERNING;
2624
2625 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2626 if( GetTextAlign( hdc) & TA_RTLREADING )
2627 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
2628 result|=GCP_REORDER;
2629
2630 return result;
2631 }
2632
2633
2634 /*************************************************************************
2635 * GetFontData [GDI32.@]
2636 *
2637 * Retrieve data for TrueType font.
2638 *
2639 * RETURNS
2640 *
2641 * success: Number of bytes returned
2642 * failure: GDI_ERROR
2643 *
2644 * NOTES
2645 *
2646 * Calls SetLastError()
2647 *
2648 */
2649 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
2650 LPVOID buffer, DWORD length)
2651 {
2652 DC *dc = get_dc_ptr(hdc);
2653 DWORD ret = GDI_ERROR;
2654
2655 if(!dc) return GDI_ERROR;
2656
2657 if(dc->gdiFont)
2658 ret = WineEngGetFontData(dc->gdiFont, table, offset, buffer, length);
2659
2660 release_dc_ptr( dc );
2661 return ret;
2662 }
2663
2664 /*************************************************************************
2665 * GetGlyphIndicesA [GDI32.@]
2666 */
2667 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
2668 LPWORD pgi, DWORD flags)
2669 {
2670 DWORD ret;
2671 WCHAR *lpstrW;
2672 INT countW;
2673
2674 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2675 hdc, debugstr_an(lpstr, count), count, pgi, flags);
2676
2677 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
2678 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
2679 HeapFree(GetProcessHeap(), 0, lpstrW);
2680
2681 return ret;
2682 }
2683
2684 /*************************************************************************
2685 * GetGlyphIndicesW [GDI32.@]
2686 */
2687 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
2688 LPWORD pgi, DWORD flags)
2689 {
2690 DC *dc = get_dc_ptr(hdc);
2691 DWORD ret = GDI_ERROR;
2692
2693 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2694 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
2695
2696 if(!dc) return GDI_ERROR;
2697
2698 if(dc->gdiFont)
2699 ret = WineEngGetGlyphIndices(dc->gdiFont, lpstr, count, pgi, flags);
2700
2701 release_dc_ptr( dc );
2702 return ret;
2703 }
2704
2705 /*************************************************************************
2706 * GetCharacterPlacementA [GDI32.@]
2707 *
2708 * See GetCharacterPlacementW.
2709 *
2710 * NOTES:
2711 * the web browser control of ie4 calls this with dwFlags=0
2712 */
2713 DWORD WINAPI
2714 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
2715 INT nMaxExtent, GCP_RESULTSA *lpResults,
2716 DWORD dwFlags)
2717 {
2718 WCHAR *lpStringW;
2719 INT uCountW;
2720 GCP_RESULTSW resultsW;
2721 DWORD ret;
2722 UINT font_cp;
2723
2724 TRACE("%s, %d, %d, 0x%08x\n",
2725 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
2726
2727 /* both structs are equal in size */
2728 memcpy(&resultsW, lpResults, sizeof(resultsW));
2729
2730 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
2731 if(lpResults->lpOutString)
2732 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
2733
2734 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
2735
2736 lpResults->nGlyphs = resultsW.nGlyphs;
2737 lpResults->nMaxFit = resultsW.nMaxFit;
2738
2739 if(lpResults->lpOutString) {
2740 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
2741 lpResults->lpOutString, uCount, NULL, NULL );
2742 }
2743
2744 HeapFree(GetProcessHeap(), 0, lpStringW);
2745 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
2746
2747 return ret;
2748 }
2749
2750 /*************************************************************************
2751 * GetCharacterPlacementW [GDI32.@]
2752 *
2753 * Retrieve information about a string. This includes the width, reordering,
2754 * Glyphing and so on.
2755 *
2756 * RETURNS
2757 *
2758 * The width and height of the string if successful, 0 if failed.
2759 *
2760 * BUGS
2761 *
2762 * All flags except GCP_REORDER are not yet implemented.
2763 * Reordering is not 100% compliant to the Windows BiDi method.
2764 * Caret positioning is not yet implemented for BiDi.
2765 * Classes are not yet implemented.
2766 *
2767 */
2768 DWORD WINAPI
2769 GetCharacterPlacementW(
2770 HDC hdc, /* [in] Device context for which the rendering is to be done */
2771 LPCWSTR lpString, /* [in] The string for which information is to be returned */
2772 INT uCount, /* [in] Number of WORDS in string. */
2773 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
2774 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
2775 DWORD dwFlags /* [in] Flags specifying how to process the string */
2776 )
2777 {
2778 DWORD ret=0;
2779 SIZE size;
2780 UINT i, nSet;
2781
2782 TRACE("%s, %d, %d, 0x%08x\n",
2783 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
2784
2785 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2786 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2787 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
2788 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
2789 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
2790
2791 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
2792 if(lpResults->lpClass) FIXME("classes not implemented\n");
2793 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
2794 FIXME("Caret positions for complex scripts not implemented\n");
2795
2796 nSet = (UINT)uCount;
2797 if(nSet > lpResults->nGlyphs)
2798 nSet = lpResults->nGlyphs;
2799
2800 /* return number of initialized fields */
2801 lpResults->nGlyphs = nSet;
2802
2803 if((dwFlags&GCP_REORDER)==0 )
2804 {
2805 /* Treat the case where no special handling was requested in a fastpath way */
2806 /* copy will do if the GCP_REORDER flag is not set */
2807 if(lpResults->lpOutString)
2808 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
2809
2810 if(lpResults->lpOrder)
2811 {
2812 for(i = 0; i < nSet; i++)
2813 lpResults->lpOrder[i] = i;
2814 }
2815 } else
2816 {
2817 BIDI_Reorder( lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
2818 nSet, lpResults->lpOrder );
2819 }
2820
2821 /* FIXME: Will use the placement chars */
2822 if (lpResults->lpDx)
2823 {
2824 int c;
2825 for (i = 0; i < nSet; i++)
2826 {
2827 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
2828 lpResults->lpDx[i]= c;
2829 }
2830 }
2831
2832 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
2833 {
2834 int pos = 0;
2835
2836 lpResults->lpCaretPos[0] = 0;
2837 for (i = 1; i < nSet; i++)
2838 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
2839 lpResults->lpCaretPos[i] = (pos += size.cx);
2840 }
2841
2842 if(lpResults->lpGlyphs)
2843 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
2844
2845 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
2846 ret = MAKELONG(size.cx, size.cy);
2847
2848 return ret;
2849 }
2850
2851 /*************************************************************************
2852 * GetCharABCWidthsFloatA [GDI32.@]
2853 *
2854 * See GetCharABCWidthsFloatW.
2855 */
2856 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2857 {
2858 INT i, wlen, count = (INT)(last - first + 1);
2859 LPSTR str;
2860 LPWSTR wstr;
2861 BOOL ret = TRUE;
2862
2863 if (count <= 0) return FALSE;
2864
2865 str = HeapAlloc(GetProcessHeap(), 0, count);
2866
2867 for(i = 0; i < count; i++)
2868 str[i] = (BYTE)(first + i);
2869
2870 wstr = FONT_mbtowc( hdc, str, count, &wlen, NULL );
2871
2872 for (i = 0; i < wlen; i++)
2873 {
2874 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
2875 {
2876 ret = FALSE;
2877 break;
2878 }
2879 abcf++;
2880 }
2881
2882 HeapFree( GetProcessHeap(), 0, str );
2883 HeapFree( GetProcessHeap(), 0, wstr );
2884
2885 return ret;
2886 }
2887
2888 /*************************************************************************
2889 * GetCharABCWidthsFloatW [GDI32.@]
2890 *
2891 * Retrieves widths of a range of characters.
2892 *
2893 * PARAMS
2894 * hdc [I] Handle to device context.
2895 * first [I] First character in range to query.
2896 * last [I] Last character in range to query.
2897 * abcf [O] Array of LPABCFLOAT structures.
2898 *
2899 * RETURNS
2900 * Success: TRUE
2901 * Failure: FALSE
2902 *
2903 * BUGS
2904 * Only works with TrueType fonts. It also doesn't return real
2905 * floats but converted integers because it's implemented on
2906 * top of GetCharABCWidthsW.
2907 */
2908 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
2909 {
2910 ABC *abc, *abc_base;
2911 unsigned int i, size = sizeof(ABC) * (last - first + 1);
2912 BOOL ret;
2913
2914 TRACE("%p, %d, %d, %p - partial stub\n", hdc, first, last, abcf);
2915
2916 abc = abc_base = HeapAlloc( GetProcessHeap(), 0, size );
2917 if (!abc) return FALSE;
2918
2919 ret = GetCharABCWidthsW( hdc, first, last, abc );
2920 if (ret)
2921 {
2922 for (i = first; i <= last; i++, abc++, abcf++)
2923 {
2924 abcf->abcfA = abc->abcA;
2925 abcf->abcfB = abc->abcB;
2926 abcf->abcfC = abc->abcC;
2927 }
2928 }
2929 HeapFree( GetProcessHeap(), 0, abc_base );
2930 return ret;
2931 }
2932
2933 /*************************************************************************
2934 * GetCharWidthFloatA [GDI32.@]
2935 */
2936 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
2937 UINT iLastChar, PFLOAT pxBuffer)
2938 {
2939 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2940 return 0;
2941 }
2942
2943 /*************************************************************************
2944 * GetCharWidthFloatW [GDI32.@]
2945 */
2946 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
2947 UINT iLastChar, PFLOAT pxBuffer)
2948 {
2949 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
2950 return 0;
2951 }
2952
2953
2954 /***********************************************************************
2955 * *
2956 * Font Resource API *
2957 * *
2958 ***********************************************************************/
2959
2960 /***********************************************************************
2961 * AddFontResourceA (GDI32.@)
2962 */
2963 INT WINAPI AddFontResourceA( LPCSTR str )
2964 {
2965 return AddFontResourceExA( str, 0, NULL);
2966 }
2967
2968 /***********************************************************************
2969 * AddFontResourceW (GDI32.@)
2970 */
2971 INT WINAPI AddFontResourceW( LPCWSTR str )
2972 {
2973 return AddFontResourceExW(str, 0, NULL);
2974 }
2975
2976
2977 /***********************************************************************
2978 * AddFontResourceExA (GDI32.@)
2979 */
2980 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
2981 {
2982 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
2983 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2984 INT ret;
2985
2986 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
2987 ret = AddFontResourceExW(strW, fl, pdv);
2988 HeapFree(GetProcessHeap(), 0, strW);
2989 return ret;
2990 }
2991
2992 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
2993 {
2994 HRSRC rsrc = FindResourceW(hModule, name, type);
2995 HGLOBAL hMem = LoadResource(hModule, rsrc);
2996 LPVOID *pMem = LockResource(hMem);
2997 int *num_total = (int *)lParam;
2998 DWORD num_in_res;
2999
3000 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3001 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3002 {
3003 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3004 return FALSE;
3005 }
3006
3007 *num_total += num_in_res;
3008 return TRUE;
3009 }
3010
3011 /***********************************************************************
3012 * AddFontResourceExW (GDI32.@)
3013 */
3014 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3015 {
3016 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3017 if (ret == 0)
3018 {
3019 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3020 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3021 if (hModule != NULL)
3022 {
3023 int num_resources = 0;
3024 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3025
3026 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3027 wine_dbgstr_w(str));
3028 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3029 ret = num_resources;
3030 FreeLibrary(hModule);
3031 }
3032 }
3033 return ret;
3034 }
3035
3036 /***********************************************************************
3037 * RemoveFontResourceA (GDI32.@)
3038 */
3039 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3040 {
3041 return RemoveFontResourceExA(str, 0, 0);
3042 }
3043
3044 /***********************************************************************
3045 * RemoveFontResourceW (GDI32.@)
3046 */
3047 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3048 {
3049 return RemoveFontResourceExW(str, 0, 0);
3050 }
3051
3052 /***********************************************************************
3053 * AddFontMemResourceEx (GDI32.@)
3054 */
3055 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3056 {
3057 return WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, pcFonts);
3058 }
3059
3060 /***********************************************************************
3061 * RemoveFontMemResourceEx (GDI32.@)
3062 */
3063 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3064 {
3065 FIXME("(%p) stub\n", fh);
3066 return TRUE;
3067 }
3068
3069 /***********************************************************************
3070 * RemoveFontResourceExA (GDI32.@)
3071 */
3072 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3073 {
3074 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3075 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3076 INT ret;
3077
3078 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3079 ret = RemoveFontResourceExW(strW, fl, pdv);
3080 HeapFree(GetProcessHeap(), 0, strW);
3081 return ret;
3082 }
3083
3084 /***********************************************************************
3085 * RemoveFontResourceExW (GDI32.@)
3086 */
3087 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3088 {
3089 return WineEngRemoveFontResourceEx(str, fl, pdv);
3090 }
3091
3092 /***********************************************************************
3093 * GetTextCharset (GDI32.@)
3094 */
3095 UINT WINAPI GetTextCharset(HDC hdc)
3096 {
3097 /* MSDN docs say this is equivalent */
3098 return GetTextCharsetInfo(hdc, NULL, 0);
3099 }
3100
3101 /***********************************************************************
3102 * GetTextCharsetInfo (GDI32.@)
3103 */
3104 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3105 {
3106 UINT ret = DEFAULT_CHARSET;
3107 DC *dc = get_dc_ptr(hdc);
3108
3109 if (dc)
3110 {
3111 if (dc->gdiFont)
3112 ret = WineEngGetTextCharsetInfo(dc->gdiFont, fs, flags);
3113
3114 release_dc_ptr( dc );
3115 }
3116
3117 if (ret == DEFAULT_CHARSET && fs)
3118 memset(fs, 0, sizeof(FONTSIGNATURE));
3119 return ret;
3120 }
3121
3122 /***********************************************************************
3123 * GdiGetCharDimensions (GDI32.@)
3124 *
3125 * Gets the average width of the characters in the English alphabet.
3126 *
3127 * PARAMS
3128 * hdc [I] Handle to the device context to measure on.
3129 * lptm [O] Pointer to memory to store the text metrics into.
3130 * height [O] On exit, the maximum height of characters in the English alphabet.
3131 *
3132 * RETURNS
3133 * The average width of characters in the English alphabet.
3134 *
3135 * NOTES
3136 * This function is used by the dialog manager to get the size of a dialog
3137 * unit. It should also be used by other pieces of code that need to know
3138 * the size of a dialog unit in logical units without having access to the
3139 * window handle of the dialog.
3140 * Windows caches the font metrics from this function, but we don't and
3141 * there doesn't appear to be an immediate advantage to do so.
3142 *
3143 * SEE ALSO
3144 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3145 */
3146 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3147 {
3148 SIZE sz;
3149 static const WCHAR alphabet[] = {
3150 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3151 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3152 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3153
3154 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3155
3156 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3157
3158 if (height) *height = sz.cy;
3159 return (sz.cx / 26 + 1) / 2;
3160 }
3161
3162 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3163 {
3164 FIXME("(%d): stub\n", fEnableEUDC);
3165 return FALSE;
3166 }
3167
3168 /***********************************************************************
3169 * GetCharWidthI (GDI32.@)
3170 *
3171 * Retrieve widths of characters.
3172 *
3173 * PARAMS
3174 * hdc [I] Handle to a device context.
3175 * first [I] First glyph in range to query.
3176 * count [I] Number of glyph indices to query.
3177 * glyphs [I] Array of glyphs to query.
3178 * buffer [O] Buffer to receive character widths.
3179 *
3180 * NOTES
3181 * Only works with TrueType fonts.
3182 *
3183 * RETURNS
3184 * Success: TRUE
3185 * Failure: FALSE
3186 */
3187 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3188 {
3189 ABC *abc;
3190 unsigned int i;
3191
3192 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3193
3194 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3195 return FALSE;
3196
3197 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3198 {
3199 HeapFree(GetProcessHeap(), 0, abc);
3200 return FALSE;
3201 }
3202
3203 for (i = 0; i < count; i++)
3204 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3205
3206 HeapFree(GetProcessHeap(), 0, abc);
3207 return TRUE;
3208 }
3209
3210 /***********************************************************************
3211 * GetFontUnicodeRanges (GDI32.@)
3212 *
3213 * Retrieve a list of supported Unicode characters in a font.
3214 *
3215 * PARAMS
3216 * hdc [I] Handle to a device context.
3217 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3218 *
3219 * RETURNS
3220 * Success: Number of bytes written to the buffer pointed to by lpgs.
3221 * Failure: 0
3222 *
3223 */
3224 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3225 {
3226 DWORD ret = 0;
3227 DC *dc = get_dc_ptr(hdc);
3228
3229 TRACE("(%p, %p)\n", hdc, lpgs);
3230
3231 if (!dc) return 0;
3232
3233 if (dc->gdiFont) ret = WineEngGetFontUnicodeRanges(dc->gdiFont, lpgs);
3234 release_dc_ptr(dc);
3235 return ret;
3236 }
3237
3238
3239 /*************************************************************
3240 * FontIsLinked (GDI32.@)
3241 */
3242 BOOL WINAPI FontIsLinked(HDC hdc)
3243 {
3244 DC *dc = get_dc_ptr(hdc);
3245 BOOL ret = FALSE;
3246
3247 if (!dc) return FALSE;
3248 if (dc->gdiFont) ret = WineEngFontIsLinked(dc->gdiFont);
3249 release_dc_ptr(dc);
3250 TRACE("returning %d\n", ret);
3251 return ret;
3252 }
3253
3254 /*************************************************************
3255 * GdiRealizationInfo (GDI32.@)
3256 *
3257 * Returns a structure that contains some font information.
3258 */
3259 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3260 {
3261 DC *dc = get_dc_ptr(hdc);
3262 BOOL ret = FALSE;
3263
3264 if (!dc) return FALSE;
3265 if (dc->gdiFont) ret = WineEngRealizationInfo(dc->gdiFont, info);
3266 release_dc_ptr(dc);
3267
3268 return ret;
3269 }
3270
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.