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