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 <limits.h>
27 #include <stdarg.h>
28 #include <stdlib.h>
29 #include <string.h>
30 #include <assert.h>
31 #include "winerror.h"
32 #include "windef.h"
33 #include "winbase.h"
34 #include "winnls.h"
35 #include "winternl.h"
36 #include "gdi_private.h"
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
40
41 #ifdef WORDS_BIGENDIAN
42 #define get_be_word(x) (x)
43 #else
44 #define get_be_word(x) RtlUshortByteSwap(x)
45 #endif
46
47 WINE_DEFAULT_DEBUG_CHANNEL(font);
48
49 /* Device -> World size conversion */
50
51 /* Performs a device to world transformation on the specified width (which
52 * is in integer format).
53 */
54 static inline INT INTERNAL_XDSTOWS(DC *dc, INT width)
55 {
56 double floatWidth;
57
58 /* Perform operation with floating point */
59 floatWidth = (double)width * dc->xformVport2World.eM11;
60 /* Round to integers */
61 return GDI_ROUND(floatWidth);
62 }
63
64 /* Performs a device to world transformation on the specified size (which
65 * is in integer format).
66 */
67 static inline INT INTERNAL_YDSTOWS(DC *dc, INT height)
68 {
69 double floatHeight;
70
71 /* Perform operation with floating point */
72 floatHeight = (double)height * dc->xformVport2World.eM22;
73 /* Round to integers */
74 return GDI_ROUND(floatHeight);
75 }
76
77 static inline INT INTERNAL_XWSTODS(DC *dc, INT width)
78 {
79 POINT pt[2];
80 pt[0].x = pt[0].y = 0;
81 pt[1].x = width;
82 pt[1].y = 0;
83 LPtoDP(dc->hSelf, pt, 2);
84 return pt[1].x - pt[0].x;
85 }
86
87 static inline INT INTERNAL_YWSTODS(DC *dc, INT height)
88 {
89 POINT pt[2];
90 pt[0].x = pt[0].y = 0;
91 pt[1].x = 0;
92 pt[1].y = height;
93 LPtoDP(dc->hSelf, pt, 2);
94 return pt[1].y - pt[0].y;
95 }
96
97 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc );
98 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer );
99 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer );
100 static BOOL FONT_DeleteObject( HGDIOBJ handle );
101
102 static const struct gdi_obj_funcs font_funcs =
103 {
104 FONT_SelectObject, /* pSelectObject */
105 FONT_GetObjectA, /* pGetObjectA */
106 FONT_GetObjectW, /* pGetObjectW */
107 NULL, /* pUnrealizeObject */
108 FONT_DeleteObject /* pDeleteObject */
109 };
110
111 typedef struct
112 {
113 GDIOBJHDR header;
114 LOGFONTW logfont;
115 } FONTOBJ;
116
117 struct font_enum
118 {
119 LPLOGFONTW lpLogFontParam;
120 FONTENUMPROCW lpEnumFunc;
121 LPARAM lpData;
122 BOOL unicode;
123 HDC hdc;
124 INT retval;
125 };
126
127 /*
128 * For TranslateCharsetInfo
129 */
130 #define MAXTCIINDEX 32
131 static const CHARSETINFO FONT_tci[MAXTCIINDEX] = {
132 /* ANSI */
133 { ANSI_CHARSET, 1252, {{0,0,0,0},{FS_LATIN1,0}} },
134 { EASTEUROPE_CHARSET, 1250, {{0,0,0,0},{FS_LATIN2,0}} },
135 { RUSSIAN_CHARSET, 1251, {{0,0,0,0},{FS_CYRILLIC,0}} },
136 { GREEK_CHARSET, 1253, {{0,0,0,0},{FS_GREEK,0}} },
137 { TURKISH_CHARSET, 1254, {{0,0,0,0},{FS_TURKISH,0}} },
138 { HEBREW_CHARSET, 1255, {{0,0,0,0},{FS_HEBREW,0}} },
139 { ARABIC_CHARSET, 1256, {{0,0,0,0},{FS_ARABIC,0}} },
140 { BALTIC_CHARSET, 1257, {{0,0,0,0},{FS_BALTIC,0}} },
141 { VIETNAMESE_CHARSET, 1258, {{0,0,0,0},{FS_VIETNAMESE,0}} },
142 /* reserved by ANSI */
143 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
144 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
145 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
146 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
147 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
148 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
149 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
150 /* ANSI and OEM */
151 { THAI_CHARSET, 874, {{0,0,0,0},{FS_THAI,0}} },
152 { SHIFTJIS_CHARSET, 932, {{0,0,0,0},{FS_JISJAPAN,0}} },
153 { GB2312_CHARSET, 936, {{0,0,0,0},{FS_CHINESESIMP,0}} },
154 { HANGEUL_CHARSET, 949, {{0,0,0,0},{FS_WANSUNG,0}} },
155 { CHINESEBIG5_CHARSET, 950, {{0,0,0,0},{FS_CHINESETRAD,0}} },
156 { JOHAB_CHARSET, 1361, {{0,0,0,0},{FS_JOHAB,0}} },
157 /* reserved for alternate ANSI and OEM */
158 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
159 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
160 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
161 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
162 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
163 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
164 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
165 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
166 /* reserved for system */
167 { DEFAULT_CHARSET, 0, {{0,0,0,0},{FS_LATIN1,0}} },
168 { SYMBOL_CHARSET, CP_SYMBOL, {{0,0,0,0},{FS_SYMBOL,0}} }
169 };
170
171 static void FONT_LogFontAToW( const LOGFONTA *fontA, LPLOGFONTW fontW )
172 {
173 memcpy(fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE);
174 MultiByteToWideChar(CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
175 LF_FACESIZE);
176 fontW->lfFaceName[LF_FACESIZE-1] = 0;
177 }
178
179 static void FONT_LogFontWToA( const LOGFONTW *fontW, LPLOGFONTA fontA )
180 {
181 memcpy(fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE);
182 WideCharToMultiByte(CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
183 LF_FACESIZE, NULL, NULL);
184 fontA->lfFaceName[LF_FACESIZE-1] = 0;
185 }
186
187 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
188 {
189 FONT_LogFontWToA( &fontW->elfLogFont, &fontA->elfLogFont );
190
191 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
192 (LPSTR) fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
193 fontA->elfFullName[LF_FULLFACESIZE-1] = '\0';
194 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
195 (LPSTR) fontA->elfStyle, LF_FACESIZE, NULL, NULL );
196 fontA->elfStyle[LF_FACESIZE-1] = '\0';
197 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
198 (LPSTR) fontA->elfScript, LF_FACESIZE, NULL, NULL );
199 fontA->elfScript[LF_FACESIZE-1] = '\0';
200 }
201
202 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
203 {
204 FONT_LogFontAToW( &fontA->elfLogFont, &fontW->elfLogFont );
205
206 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
207 fontW->elfFullName, LF_FULLFACESIZE );
208 fontW->elfFullName[LF_FULLFACESIZE-1] = '\0';
209 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
210 fontW->elfStyle, LF_FACESIZE );
211 fontW->elfStyle[LF_FACESIZE-1] = '\0';
212 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
213 fontW->elfScript, LF_FACESIZE );
214 fontW->elfScript[LF_FACESIZE-1] = '\0';
215 }
216
217 /***********************************************************************
218 * TEXTMETRIC conversion functions.
219 */
220 static void FONT_TextMetricWToA(const TEXTMETRICW *ptmW, LPTEXTMETRICA ptmA )
221 {
222 ptmA->tmHeight = ptmW->tmHeight;
223 ptmA->tmAscent = ptmW->tmAscent;
224 ptmA->tmDescent = ptmW->tmDescent;
225 ptmA->tmInternalLeading = ptmW->tmInternalLeading;
226 ptmA->tmExternalLeading = ptmW->tmExternalLeading;
227 ptmA->tmAveCharWidth = ptmW->tmAveCharWidth;
228 ptmA->tmMaxCharWidth = ptmW->tmMaxCharWidth;
229 ptmA->tmWeight = ptmW->tmWeight;
230 ptmA->tmOverhang = ptmW->tmOverhang;
231 ptmA->tmDigitizedAspectX = ptmW->tmDigitizedAspectX;
232 ptmA->tmDigitizedAspectY = ptmW->tmDigitizedAspectY;
233 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 255);
234 if (ptmW->tmCharSet == SYMBOL_CHARSET)
235 {
236 ptmA->tmFirstChar = 0x1e;
237 ptmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
238 }
239 else if (ptmW->tmPitchAndFamily & TMPF_TRUETYPE)
240 {
241 ptmA->tmFirstChar = ptmW->tmDefaultChar - 1;
242 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
243 }
244 else
245 {
246 ptmA->tmFirstChar = min(ptmW->tmFirstChar, 0xff);
247 ptmA->tmLastChar = min(ptmW->tmLastChar, 0xff);
248 }
249 ptmA->tmDefaultChar = ptmW->tmDefaultChar;
250 ptmA->tmBreakChar = ptmW->tmBreakChar;
251 ptmA->tmItalic = ptmW->tmItalic;
252 ptmA->tmUnderlined = ptmW->tmUnderlined;
253 ptmA->tmStruckOut = ptmW->tmStruckOut;
254 ptmA->tmPitchAndFamily = ptmW->tmPitchAndFamily;
255 ptmA->tmCharSet = ptmW->tmCharSet;
256 }
257
258
259 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW *ptmW, NEWTEXTMETRICEXA *ptmA )
260 {
261 FONT_TextMetricWToA((const TEXTMETRICW *)ptmW, (LPTEXTMETRICA)ptmA);
262 ptmA->ntmTm.ntmFlags = ptmW->ntmTm.ntmFlags;
263 ptmA->ntmTm.ntmSizeEM = ptmW->ntmTm.ntmSizeEM;
264 ptmA->ntmTm.ntmCellHeight = ptmW->ntmTm.ntmCellHeight;
265 ptmA->ntmTm.ntmAvgWidth = ptmW->ntmTm.ntmAvgWidth;
266 memcpy(&ptmA->ntmFontSig, &ptmW->ntmFontSig, sizeof(FONTSIGNATURE));
267 }
268
269 static DWORD get_font_ppem( HDC hdc )
270 {
271 TEXTMETRICW tm;
272 DWORD ppem;
273 DC *dc = get_dc_ptr( hdc );
274
275 if (!dc) return GDI_ERROR;
276
277 GetTextMetricsW( hdc, &tm );
278 ppem = abs( INTERNAL_YWSTODS( dc, tm.tmAscent + tm.tmDescent - tm.tmInternalLeading ) );
279 release_dc_ptr( dc );
280 return ppem;
281 }
282
283 #define GASP_GRIDFIT 0x01
284 #define GASP_DOGRAY 0x02
285
286 static BOOL get_gasp_flags( HDC hdc, WORD *flags )
287 {
288 DWORD size, gasp_tag = 0x70736167;
289 WORD buf[16]; /* Enough for seven ranges before we need to alloc */
290 WORD *alloced = NULL, *ptr = buf;
291 WORD num_recs, version;
292 DWORD ppem = get_font_ppem( hdc );
293 BOOL ret = FALSE;
294
295 *flags = 0;
296 if (ppem == GDI_ERROR) return FALSE;
297
298 size = GetFontData( hdc, gasp_tag, 0, NULL, 0 );
299 if (size == GDI_ERROR) return FALSE;
300 if (size < 4 * sizeof(WORD)) return FALSE;
301 if (size > sizeof(buf))
302 {
303 ptr = alloced = HeapAlloc( GetProcessHeap(), 0, size );
304 if (!ptr) return FALSE;
305 }
306
307 GetFontData( hdc, gasp_tag, 0, ptr, size );
308
309 version = get_be_word( *ptr++ );
310 num_recs = get_be_word( *ptr++ );
311
312 if (version > 1 || size < (num_recs * 2 + 2) * sizeof(WORD))
313 {
314 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version, size, num_recs );
315 goto done;
316 }
317
318 while (num_recs--)
319 {
320 *flags = get_be_word( *(ptr + 1) );
321 if (ppem <= get_be_word( *ptr )) break;
322 ptr += 2;
323 }
324 TRACE( "got flags %04x for ppem %d\n", *flags, ppem );
325 ret = TRUE;
326
327 done:
328 HeapFree( GetProcessHeap(), 0, alloced );
329 return ret;
330 }
331
332 UINT get_font_aa_flags( HDC hdc )
333 {
334 LOGFONTW lf;
335 WORD gasp_flags;
336
337 if (GetObjectType( hdc ) == OBJ_MEMDC)
338 {
339 BITMAP bm;
340 GetObjectW( GetCurrentObject( hdc, OBJ_BITMAP ), sizeof(bm), &bm );
341 if (bm.bmBitsPixel <= 8) return GGO_BITMAP;
342 }
343 else if (GetDeviceCaps( hdc, BITSPIXEL ) <= 8) return GGO_BITMAP;
344
345 GetObjectW( GetCurrentObject( hdc, OBJ_FONT ), sizeof(lf), &lf );
346 if (lf.lfQuality == NONANTIALIASED_QUALITY) return GGO_BITMAP;
347
348 if (get_gasp_flags( hdc, &gasp_flags ) && !(gasp_flags & GASP_DOGRAY))
349 return GGO_BITMAP;
350
351 /* FIXME, check user prefs */
352 return GGO_GRAY4_BITMAP;
353 }
354
355 /***********************************************************************
356 * GdiGetCodePage (GDI32.@)
357 */
358 DWORD WINAPI GdiGetCodePage( HDC hdc )
359 {
360 UINT cp = CP_ACP;
361 DC *dc = get_dc_ptr( hdc );
362
363 if (dc)
364 {
365 cp = dc->font_code_page;
366 release_dc_ptr( dc );
367 }
368 return cp;
369 }
370
371 /***********************************************************************
372 * FONT_mbtowc
373 *
374 * Returns a Unicode translation of str using the charset of the
375 * currently selected font in hdc. If count is -1 then str is assumed
376 * to be '\0' terminated, otherwise it contains the number of bytes to
377 * convert. If plenW is non-NULL, on return it will point to the
378 * number of WCHARs that have been written. If pCP is non-NULL, on
379 * return it will point to the codepage used in the conversion. The
380 * caller should free the returned LPWSTR from the process heap
381 * itself.
382 */
383 static LPWSTR FONT_mbtowc(HDC hdc, LPCSTR str, INT count, INT *plenW, UINT *pCP)
384 {
385 UINT cp;
386 INT lenW;
387 LPWSTR strW;
388
389 cp = GdiGetCodePage( hdc );
390
391 if(count == -1) count = strlen(str);
392 lenW = MultiByteToWideChar(cp, 0, str, count, NULL, 0);
393 strW = HeapAlloc(GetProcessHeap(), 0, lenW*sizeof(WCHAR));
394 MultiByteToWideChar(cp, 0, str, count, strW, lenW);
395 TRACE("mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW));
396 if(plenW) *plenW = lenW;
397 if(pCP) *pCP = cp;
398 return strW;
399 }
400
401 /***********************************************************************
402 * CreateFontIndirectExA (GDI32.@)
403 */
404 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *penumexA )
405 {
406 ENUMLOGFONTEXDVW enumexW;
407
408 if (!penumexA) return 0;
409
410 FONT_EnumLogFontExAToW( &penumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
411 enumexW.elfDesignVector = penumexA->elfDesignVector;
412 return CreateFontIndirectExW( &enumexW );
413 }
414
415 /***********************************************************************
416 * CreateFontIndirectExW (GDI32.@)
417 */
418 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *penumex )
419 {
420 HFONT hFont;
421 FONTOBJ *fontPtr;
422 const LOGFONTW *plf;
423
424 if (!penumex) return 0;
425
426 if (penumex->elfEnumLogfontEx.elfFullName[0] ||
427 penumex->elfEnumLogfontEx.elfStyle[0] ||
428 penumex->elfEnumLogfontEx.elfScript[0])
429 {
430 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
431 debugstr_w(penumex->elfEnumLogfontEx.elfFullName),
432 debugstr_w(penumex->elfEnumLogfontEx.elfStyle),
433 debugstr_w(penumex->elfEnumLogfontEx.elfScript));
434 }
435
436 plf = &penumex->elfEnumLogfontEx.elfLogFont;
437 if (!(fontPtr = HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr) ))) return 0;
438
439 fontPtr->logfont = *plf;
440
441 if (plf->lfEscapement != plf->lfOrientation)
442 {
443 /* this should really depend on whether GM_ADVANCED is set */
444 fontPtr->logfont.lfOrientation = fontPtr->logfont.lfEscapement;
445 WARN("orientation angle %f set to "
446 "escapement angle %f for new font %p\n",
447 plf->lfOrientation/10., plf->lfEscapement/10., fontPtr);
448 }
449
450 if (!(hFont = alloc_gdi_handle( &fontPtr->header, OBJ_FONT, &font_funcs )))
451 {
452 HeapFree( GetProcessHeap(), 0, fontPtr );
453 return 0;
454 }
455
456 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
457 plf->lfHeight, plf->lfWidth,
458 plf->lfEscapement, plf->lfOrientation,
459 plf->lfPitchAndFamily,
460 plf->lfOutPrecision, plf->lfClipPrecision,
461 plf->lfQuality, plf->lfCharSet,
462 debugstr_w(plf->lfFaceName),
463 plf->lfWeight > 400 ? "Bold" : "",
464 plf->lfItalic ? "Italic" : "",
465 plf->lfUnderline ? "Underline" : "", hFont);
466
467 return hFont;
468 }
469
470 /***********************************************************************
471 * CreateFontIndirectA (GDI32.@)
472 */
473 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *plfA )
474 {
475 LOGFONTW lfW;
476
477 if (!plfA) return 0;
478
479 FONT_LogFontAToW( plfA, &lfW );
480 return CreateFontIndirectW( &lfW );
481 }
482
483 /***********************************************************************
484 * CreateFontIndirectW (GDI32.@)
485 */
486 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *plf )
487 {
488 ENUMLOGFONTEXDVW exdv;
489
490 if (!plf) return 0;
491
492 exdv.elfEnumLogfontEx.elfLogFont = *plf;
493 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
494 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
495 exdv.elfEnumLogfontEx.elfScript[0] = 0;
496 return CreateFontIndirectExW( &exdv );
497 }
498
499 /*************************************************************************
500 * CreateFontA (GDI32.@)
501 */
502 HFONT WINAPI CreateFontA( INT height, INT width, INT esc,
503 INT orient, INT weight, DWORD italic,
504 DWORD underline, DWORD strikeout, DWORD charset,
505 DWORD outpres, DWORD clippres, DWORD quality,
506 DWORD pitch, LPCSTR name )
507 {
508 LOGFONTA logfont;
509
510 logfont.lfHeight = height;
511 logfont.lfWidth = width;
512 logfont.lfEscapement = esc;
513 logfont.lfOrientation = orient;
514 logfont.lfWeight = weight;
515 logfont.lfItalic = italic;
516 logfont.lfUnderline = underline;
517 logfont.lfStrikeOut = strikeout;
518 logfont.lfCharSet = charset;
519 logfont.lfOutPrecision = outpres;
520 logfont.lfClipPrecision = clippres;
521 logfont.lfQuality = quality;
522 logfont.lfPitchAndFamily = pitch;
523
524 if (name)
525 lstrcpynA(logfont.lfFaceName,name,sizeof(logfont.lfFaceName));
526 else
527 logfont.lfFaceName[0] = '\0';
528
529 return CreateFontIndirectA( &logfont );
530 }
531
532 /*************************************************************************
533 * CreateFontW (GDI32.@)
534 */
535 HFONT WINAPI CreateFontW( INT height, INT width, INT esc,
536 INT orient, INT weight, DWORD italic,
537 DWORD underline, DWORD strikeout, DWORD charset,
538 DWORD outpres, DWORD clippres, DWORD quality,
539 DWORD pitch, LPCWSTR name )
540 {
541 LOGFONTW logfont;
542
543 logfont.lfHeight = height;
544 logfont.lfWidth = width;
545 logfont.lfEscapement = esc;
546 logfont.lfOrientation = orient;
547 logfont.lfWeight = weight;
548 logfont.lfItalic = italic;
549 logfont.lfUnderline = underline;
550 logfont.lfStrikeOut = strikeout;
551 logfont.lfCharSet = charset;
552 logfont.lfOutPrecision = outpres;
553 logfont.lfClipPrecision = clippres;
554 logfont.lfQuality = quality;
555 logfont.lfPitchAndFamily = pitch;
556
557 if (name)
558 lstrcpynW(logfont.lfFaceName, name,
559 sizeof(logfont.lfFaceName) / sizeof(WCHAR));
560 else
561 logfont.lfFaceName[0] = '\0';
562
563 return CreateFontIndirectW( &logfont );
564 }
565
566 static void update_font_code_page( DC *dc )
567 {
568 CHARSETINFO csi;
569 int charset = GetTextCharsetInfo( dc->hSelf, NULL, 0 );
570
571 /* Hmm, nicely designed api this one! */
572 if (TranslateCharsetInfo( ULongToPtr(charset), &csi, TCI_SRCCHARSET) )
573 dc->font_code_page = csi.ciACP;
574 else {
575 switch(charset) {
576 case OEM_CHARSET:
577 dc->font_code_page = GetOEMCP();
578 break;
579 case DEFAULT_CHARSET:
580 dc->font_code_page = GetACP();
581 break;
582
583 case VISCII_CHARSET:
584 case TCVN_CHARSET:
585 case KOI8_CHARSET:
586 case ISO3_CHARSET:
587 case ISO4_CHARSET:
588 case ISO10_CHARSET:
589 case CELTIC_CHARSET:
590 /* FIXME: These have no place here, but because x11drv
591 enumerates fonts with these (made up) charsets some apps
592 might use them and then the FIXME below would become
593 annoying. Now we could pick the intended codepage for
594 each of these, but since it's broken anyway we'll just
595 use CP_ACP and hope it'll go away...
596 */
597 dc->font_code_page = CP_ACP;
598 break;
599
600 default:
601 FIXME("Can't find codepage for charset %d\n", charset);
602 dc->font_code_page = CP_ACP;
603 break;
604 }
605 }
606
607 TRACE("charset %d => cp %d\n", charset, dc->font_code_page);
608 }
609
610 /***********************************************************************
611 * FONT_SelectObject
612 */
613 static HGDIOBJ FONT_SelectObject( HGDIOBJ handle, HDC hdc )
614 {
615 HGDIOBJ ret = 0;
616 DC *dc = get_dc_ptr( hdc );
617 PHYSDEV physdev;
618
619 if (!dc) return 0;
620
621 if (!GDI_inc_ref_count( handle ))
622 {
623 release_dc_ptr( dc );
624 return 0;
625 }
626
627 physdev = GET_DC_PHYSDEV( dc, pSelectFont );
628 if (physdev->funcs->pSelectFont( physdev, handle ))
629 {
630 ret = dc->hFont;
631 dc->hFont = handle;
632 update_font_code_page( dc );
633 GDI_dec_ref_count( ret );
634 }
635 else GDI_dec_ref_count( handle );
636
637 release_dc_ptr( dc );
638 return ret;
639 }
640
641
642 /***********************************************************************
643 * FONT_GetObjectA
644 */
645 static INT FONT_GetObjectA( HGDIOBJ handle, INT count, LPVOID buffer )
646 {
647 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
648 LOGFONTA lfA;
649
650 if (!font) return 0;
651 if (buffer)
652 {
653 FONT_LogFontWToA( &font->logfont, &lfA );
654 if (count > sizeof(lfA)) count = sizeof(lfA);
655 memcpy( buffer, &lfA, count );
656 }
657 else count = sizeof(lfA);
658 GDI_ReleaseObj( handle );
659 return count;
660 }
661
662 /***********************************************************************
663 * FONT_GetObjectW
664 */
665 static INT FONT_GetObjectW( HGDIOBJ handle, INT count, LPVOID buffer )
666 {
667 FONTOBJ *font = GDI_GetObjPtr( handle, OBJ_FONT );
668
669 if (!font) return 0;
670 if (buffer)
671 {
672 if (count > sizeof(LOGFONTW)) count = sizeof(LOGFONTW);
673 memcpy( buffer, &font->logfont, count );
674 }
675 else count = sizeof(LOGFONTW);
676 GDI_ReleaseObj( handle );
677 return count;
678 }
679
680
681 /***********************************************************************
682 * FONT_DeleteObject
683 */
684 static BOOL FONT_DeleteObject( HGDIOBJ handle )
685 {
686 FONTOBJ *obj;
687
688 WineEngDestroyFontInstance( handle );
689
690 if (!(obj = free_gdi_handle( handle ))) return FALSE;
691 return HeapFree( GetProcessHeap(), 0, obj );
692 }
693
694
695 /***********************************************************************
696 * FONT_EnumInstance
697 *
698 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
699 * We have to use other types because of the FONTENUMPROCW definition.
700 */
701 static INT CALLBACK FONT_EnumInstance( const LOGFONTW *plf, const TEXTMETRICW *ptm,
702 DWORD fType, LPARAM lp )
703 {
704 struct font_enum *pfe = (struct font_enum *)lp;
705 INT ret = 1;
706
707 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
708 if ((!pfe->lpLogFontParam ||
709 pfe->lpLogFontParam->lfCharSet == DEFAULT_CHARSET ||
710 pfe->lpLogFontParam->lfCharSet == plf->lfCharSet) &&
711 (!(fType & RASTER_FONTTYPE) || GetDeviceCaps(pfe->hdc, TEXTCAPS) & TC_RA_ABLE) )
712 {
713 /* convert font metrics */
714 ENUMLOGFONTEXA logfont;
715 NEWTEXTMETRICEXA tmA;
716
717 if (!pfe->unicode)
718 {
719 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW *)plf, &logfont);
720 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW *)ptm, &tmA );
721 plf = (LOGFONTW *)&logfont.elfLogFont;
722 ptm = (TEXTMETRICW *)&tmA;
723 }
724 ret = pfe->lpEnumFunc( plf, ptm, fType, pfe->lpData );
725 pfe->retval = ret;
726 }
727 return ret;
728 }
729
730 /***********************************************************************
731 * FONT_EnumFontFamiliesEx
732 */
733 static INT FONT_EnumFontFamiliesEx( HDC hDC, LPLOGFONTW plf, FONTENUMPROCW efproc,
734 LPARAM lParam, BOOL unicode )
735 {
736 INT ret = 0;
737 DC *dc = get_dc_ptr( hDC );
738 struct font_enum fe;
739
740 if (dc)
741 {
742 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pEnumFonts );
743
744 if (plf) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf->lfFaceName), plf->lfCharSet);
745 fe.lpLogFontParam = plf;
746 fe.lpEnumFunc = efproc;
747 fe.lpData = lParam;
748 fe.unicode = unicode;
749 fe.hdc = hDC;
750 fe.retval = 1;
751 ret = physdev->funcs->pEnumFonts( physdev, plf, FONT_EnumInstance, (LPARAM)&fe );
752 release_dc_ptr( dc );
753 }
754 return ret ? fe.retval : 0;
755 }
756
757 /***********************************************************************
758 * EnumFontFamiliesExW (GDI32.@)
759 */
760 INT WINAPI EnumFontFamiliesExW( HDC hDC, LPLOGFONTW plf,
761 FONTENUMPROCW efproc,
762 LPARAM lParam, DWORD dwFlags )
763 {
764 return FONT_EnumFontFamiliesEx( hDC, plf, efproc, lParam, TRUE );
765 }
766
767 /***********************************************************************
768 * EnumFontFamiliesExA (GDI32.@)
769 */
770 INT WINAPI EnumFontFamiliesExA( HDC hDC, LPLOGFONTA plf,
771 FONTENUMPROCA efproc,
772 LPARAM lParam, DWORD dwFlags)
773 {
774 LOGFONTW lfW, *plfW;
775
776 if (plf)
777 {
778 FONT_LogFontAToW( plf, &lfW );
779 plfW = &lfW;
780 }
781 else plfW = NULL;
782
783 return FONT_EnumFontFamiliesEx( hDC, plfW, (FONTENUMPROCW)efproc, lParam, FALSE );
784 }
785
786 /***********************************************************************
787 * EnumFontFamiliesA (GDI32.@)
788 */
789 INT WINAPI EnumFontFamiliesA( HDC hDC, LPCSTR lpFamily,
790 FONTENUMPROCA efproc, LPARAM lpData )
791 {
792 LOGFONTA lf, *plf;
793
794 if (lpFamily)
795 {
796 if (!*lpFamily) return 1;
797 lstrcpynA( lf.lfFaceName, lpFamily, LF_FACESIZE );
798 lf.lfCharSet = DEFAULT_CHARSET;
799 lf.lfPitchAndFamily = 0;
800 plf = &lf;
801 }
802 else plf = NULL;
803
804 return EnumFontFamiliesExA( hDC, plf, efproc, lpData, 0 );
805 }
806
807 /***********************************************************************
808 * EnumFontFamiliesW (GDI32.@)
809 */
810 INT WINAPI EnumFontFamiliesW( HDC hDC, LPCWSTR lpFamily,
811 FONTENUMPROCW efproc, LPARAM lpData )
812 {
813 LOGFONTW lf, *plf;
814
815 if (lpFamily)
816 {
817 if (!*lpFamily) return 1;
818 lstrcpynW( lf.lfFaceName, lpFamily, LF_FACESIZE );
819 lf.lfCharSet = DEFAULT_CHARSET;
820 lf.lfPitchAndFamily = 0;
821 plf = &lf;
822 }
823 else plf = NULL;
824
825 return EnumFontFamiliesExW( hDC, plf, efproc, lpData, 0 );
826 }
827
828 /***********************************************************************
829 * EnumFontsA (GDI32.@)
830 */
831 INT WINAPI EnumFontsA( HDC hDC, LPCSTR lpName, FONTENUMPROCA efproc,
832 LPARAM lpData )
833 {
834 return EnumFontFamiliesA( hDC, lpName, efproc, lpData );
835 }
836
837 /***********************************************************************
838 * EnumFontsW (GDI32.@)
839 */
840 INT WINAPI EnumFontsW( HDC hDC, LPCWSTR lpName, FONTENUMPROCW efproc,
841 LPARAM lpData )
842 {
843 return EnumFontFamiliesW( hDC, lpName, efproc, lpData );
844 }
845
846
847 /***********************************************************************
848 * GetTextCharacterExtra (GDI32.@)
849 */
850 INT WINAPI GetTextCharacterExtra( HDC hdc )
851 {
852 INT ret;
853 DC *dc = get_dc_ptr( hdc );
854 if (!dc) return 0x80000000;
855 ret = dc->charExtra;
856 release_dc_ptr( dc );
857 return ret;
858 }
859
860
861 /***********************************************************************
862 * SetTextCharacterExtra (GDI32.@)
863 */
864 INT WINAPI SetTextCharacterExtra( HDC hdc, INT extra )
865 {
866 INT ret = 0x80000000;
867 DC * dc = get_dc_ptr( hdc );
868
869 if (dc)
870 {
871 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetTextCharacterExtra );
872 extra = physdev->funcs->pSetTextCharacterExtra( physdev, extra );
873 if (extra != 0x80000000)
874 {
875 ret = dc->charExtra;
876 dc->charExtra = extra;
877 }
878 release_dc_ptr( dc );
879 }
880 return ret;
881 }
882
883
884 /***********************************************************************
885 * SetTextJustification (GDI32.@)
886 */
887 BOOL WINAPI SetTextJustification( HDC hdc, INT extra, INT breaks )
888 {
889 BOOL ret;
890 PHYSDEV physdev;
891 DC * dc = get_dc_ptr( hdc );
892
893 if (!dc) return FALSE;
894
895 physdev = GET_DC_PHYSDEV( dc, pSetTextJustification );
896 ret = physdev->funcs->pSetTextJustification( physdev, extra, breaks );
897 if (ret)
898 {
899 extra = abs((extra * dc->vportExtX + dc->wndExtX / 2) / dc->wndExtX);
900 if (!extra) breaks = 0;
901 if (breaks)
902 {
903 dc->breakExtra = extra / breaks;
904 dc->breakRem = extra - (breaks * dc->breakExtra);
905 }
906 else
907 {
908 dc->breakExtra = 0;
909 dc->breakRem = 0;
910 }
911 }
912 release_dc_ptr( dc );
913 return ret;
914 }
915
916
917 /***********************************************************************
918 * GetTextFaceA (GDI32.@)
919 */
920 INT WINAPI GetTextFaceA( HDC hdc, INT count, LPSTR name )
921 {
922 INT res = GetTextFaceW(hdc, 0, NULL);
923 LPWSTR nameW = HeapAlloc( GetProcessHeap(), 0, res * 2 );
924 GetTextFaceW( hdc, res, nameW );
925
926 if (name)
927 {
928 if (count)
929 {
930 res = WideCharToMultiByte(CP_ACP, 0, nameW, -1, name, count, NULL, NULL);
931 if (res == 0)
932 res = count;
933 name[count-1] = 0;
934 /* GetTextFaceA does NOT include the nul byte in the return count. */
935 res--;
936 }
937 else
938 res = 0;
939 }
940 else
941 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL);
942 HeapFree( GetProcessHeap(), 0, nameW );
943 return res;
944 }
945
946 /***********************************************************************
947 * GetTextFaceW (GDI32.@)
948 */
949 INT WINAPI GetTextFaceW( HDC hdc, INT count, LPWSTR name )
950 {
951 PHYSDEV dev;
952 INT ret;
953
954 DC * dc = get_dc_ptr( hdc );
955 if (!dc) return 0;
956
957 dev = GET_DC_PHYSDEV( dc, pGetTextFace );
958 ret = dev->funcs->pGetTextFace( dev, count, name );
959 release_dc_ptr( dc );
960 return ret;
961 }
962
963
964 /***********************************************************************
965 * GetTextExtentPoint32A (GDI32.@)
966 *
967 * See GetTextExtentPoint32W.
968 */
969 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, LPCSTR str, INT count,
970 LPSIZE size )
971 {
972 BOOL ret = FALSE;
973 INT wlen;
974 LPWSTR p;
975
976 if (count < 0) return FALSE;
977
978 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
979
980 if (p)
981 {
982 ret = GetTextExtentPoint32W( hdc, p, wlen, size );
983 HeapFree( GetProcessHeap(), 0, p );
984 }
985
986 TRACE("(%p %s %d %p): returning %d x %d\n",
987 hdc, debugstr_an (str, count), count, size, size->cx, size->cy );
988 return ret;
989 }
990
991
992 /***********************************************************************
993 * GetTextExtentPoint32W [GDI32.@]
994 *
995 * Computes width/height for a string.
996 *
997 * Computes width and height of the specified string.
998 *
999 * RETURNS
1000 * Success: TRUE
1001 * Failure: FALSE
1002 */
1003 BOOL WINAPI GetTextExtentPoint32W(
1004 HDC hdc, /* [in] Handle of device context */
1005 LPCWSTR str, /* [in] Address of text string */
1006 INT count, /* [in] Number of characters in string */
1007 LPSIZE size) /* [out] Address of structure for string size */
1008 {
1009 return GetTextExtentExPointW(hdc, str, count, 0, NULL, NULL, size);
1010 }
1011
1012 /***********************************************************************
1013 * GetTextExtentExPointI [GDI32.@]
1014 *
1015 * Computes width and height of the array of glyph indices.
1016 *
1017 * PARAMS
1018 * hdc [I] Handle of device context.
1019 * indices [I] Glyph index array.
1020 * count [I] Number of glyphs in array.
1021 * max_ext [I] Maximum width in glyphs.
1022 * nfit [O] Maximum number of characters.
1023 * dxs [O] Partial string widths.
1024 * size [O] Returned string size.
1025 *
1026 * RETURNS
1027 * Success: TRUE
1028 * Failure: FALSE
1029 */
1030 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1031 LPINT nfit, LPINT dxs, LPSIZE size )
1032 {
1033 PHYSDEV dev;
1034 BOOL ret;
1035 DC *dc;
1036
1037 if (count < 0) return FALSE;
1038
1039 dc = get_dc_ptr( hdc );
1040 if (!dc) return FALSE;
1041
1042 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPointI );
1043 ret = dev->funcs->pGetTextExtentExPointI( dev, indices, count, max_ext, nfit, dxs, size );
1044 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1045 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1046 size->cx += count * dc->charExtra;
1047 release_dc_ptr( dc );
1048
1049 TRACE("(%p %p %d %p): returning %d x %d\n",
1050 hdc, indices, count, size, size->cx, size->cy );
1051 return ret;
1052 }
1053
1054 /***********************************************************************
1055 * GetTextExtentPointI [GDI32.@]
1056 *
1057 * Computes width and height of the array of glyph indices.
1058 *
1059 * PARAMS
1060 * hdc [I] Handle of device context.
1061 * indices [I] Glyph index array.
1062 * count [I] Number of glyphs in array.
1063 * size [O] Returned string size.
1064 *
1065 * RETURNS
1066 * Success: TRUE
1067 * Failure: FALSE
1068 */
1069 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, LPSIZE size )
1070 {
1071 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1072 }
1073
1074
1075 /***********************************************************************
1076 * GetTextExtentPointA (GDI32.@)
1077 */
1078 BOOL WINAPI GetTextExtentPointA( HDC hdc, LPCSTR str, INT count,
1079 LPSIZE size )
1080 {
1081 TRACE("not bug compatible.\n");
1082 return GetTextExtentPoint32A( hdc, str, count, size );
1083 }
1084
1085 /***********************************************************************
1086 * GetTextExtentPointW (GDI32.@)
1087 */
1088 BOOL WINAPI GetTextExtentPointW( HDC hdc, LPCWSTR str, INT count,
1089 LPSIZE size )
1090 {
1091 TRACE("not bug compatible.\n");
1092 return GetTextExtentPoint32W( hdc, str, count, size );
1093 }
1094
1095
1096 /***********************************************************************
1097 * GetTextExtentExPointA (GDI32.@)
1098 */
1099 BOOL WINAPI GetTextExtentExPointA( HDC hdc, LPCSTR str, INT count,
1100 INT maxExt, LPINT lpnFit,
1101 LPINT alpDx, LPSIZE size )
1102 {
1103 BOOL ret;
1104 INT wlen;
1105 INT *walpDx = NULL;
1106 LPWSTR p = NULL;
1107
1108 if (count < 0) return FALSE;
1109
1110 if (alpDx)
1111 {
1112 walpDx = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1113 if (!walpDx) return FALSE;
1114 }
1115
1116 p = FONT_mbtowc(hdc, str, count, &wlen, NULL);
1117 ret = GetTextExtentExPointW( hdc, p, wlen, maxExt, lpnFit, walpDx, size);
1118 if (walpDx)
1119 {
1120 INT n = lpnFit ? *lpnFit : wlen;
1121 INT i, j;
1122 for(i = 0, j = 0; i < n; i++, j++)
1123 {
1124 alpDx[j] = walpDx[i];
1125 if (IsDBCSLeadByte(str[j])) alpDx[++j] = walpDx[i];
1126 }
1127 }
1128 if (lpnFit) *lpnFit = WideCharToMultiByte(CP_ACP,0,p,*lpnFit,NULL,0,NULL,NULL);
1129 HeapFree( GetProcessHeap(), 0, p );
1130 HeapFree( GetProcessHeap(), 0, walpDx );
1131 return ret;
1132 }
1133
1134
1135 /***********************************************************************
1136 * GetTextExtentExPointW (GDI32.@)
1137 *
1138 * Return the size of the string as it would be if it was output properly by
1139 * e.g. TextOut.
1140 *
1141 * This should include
1142 * - Intercharacter spacing
1143 * - justification spacing (not yet done)
1144 * - kerning? see below
1145 *
1146 * Kerning. Since kerning would be carried out by the rendering code it should
1147 * be done by the driver. However they don't support it yet. Also I am not
1148 * yet persuaded that (certainly under Win95) any kerning is actually done.
1149 *
1150 * str: According to MSDN this should be null-terminated. That is not true; a
1151 * null will not terminate it early.
1152 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1153 * than count. I have seen it be either the size of the full string or
1154 * 1 less than the size of the full string. I have not seen it bear any
1155 * resemblance to the portion that would fit.
1156 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1157 * trailing intercharacter spacing and any trailing justification.
1158 *
1159 * FIXME
1160 * Currently we do this by measuring each character etc. We should do it by
1161 * passing the request to the driver, perhaps by extending the
1162 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1163 * thinking about kerning issues and rounding issues in the justification.
1164 */
1165
1166 BOOL WINAPI GetTextExtentExPointW( HDC hdc, LPCWSTR str, INT count,
1167 INT maxExt, LPINT lpnFit,
1168 LPINT alpDx, LPSIZE size )
1169 {
1170 INT nFit = 0;
1171 LPINT dxs = NULL;
1172 DC *dc;
1173 BOOL ret = FALSE;
1174 TEXTMETRICW tm;
1175 PHYSDEV dev;
1176
1177 TRACE("(%p, %s, %d)\n",hdc,debugstr_wn(str,count),maxExt);
1178
1179 if (count < 0) return FALSE;
1180
1181 dc = get_dc_ptr(hdc);
1182 if (!dc) return FALSE;
1183
1184 GetTextMetricsW(hdc, &tm);
1185
1186 /* If we need to calculate nFit, then we need the partial extents even if
1187 the user hasn't provided us with an array. */
1188 if (lpnFit)
1189 {
1190 dxs = alpDx ? alpDx : HeapAlloc(GetProcessHeap(), 0, count * sizeof alpDx[0]);
1191 if (! dxs)
1192 {
1193 release_dc_ptr(dc);
1194 SetLastError(ERROR_OUTOFMEMORY);
1195 return FALSE;
1196 }
1197 }
1198 else
1199 dxs = alpDx;
1200
1201 dev = GET_DC_PHYSDEV( dc, pGetTextExtentExPoint );
1202 ret = dev->funcs->pGetTextExtentExPoint(dev, str, count, 0, NULL, dxs, size);
1203
1204 /* Perform device size to world size transformations. */
1205 if (ret)
1206 {
1207 INT extra = dc->charExtra,
1208 breakExtra = dc->breakExtra,
1209 breakRem = dc->breakRem,
1210 i;
1211
1212 if (dxs)
1213 {
1214 for (i = 0; i < count; ++i)
1215 {
1216 dxs[i] = abs(INTERNAL_XDSTOWS(dc, dxs[i]));
1217 dxs[i] += (i+1) * extra;
1218 if (count > 1 && (breakExtra || breakRem) && str[i] == tm.tmBreakChar)
1219 {
1220 dxs[i] += breakExtra;
1221 if (breakRem > 0)
1222 {
1223 breakRem--;
1224 dxs[i]++;
1225 }
1226 }
1227 if (dxs[i] <= maxExt)
1228 ++nFit;
1229 }
1230 breakRem = dc->breakRem;
1231 }
1232 size->cx = abs(INTERNAL_XDSTOWS(dc, size->cx));
1233 size->cy = abs(INTERNAL_YDSTOWS(dc, size->cy));
1234
1235 if (!dxs && count > 1 && (breakExtra || breakRem))
1236 {
1237 for (i = 0; i < count; i++)
1238 {
1239 if (str[i] == tm.tmBreakChar)
1240 {
1241 size->cx += breakExtra;
1242 if (breakRem > 0)
1243 {
1244 breakRem--;
1245 (size->cx)++;
1246 }
1247 }
1248 }
1249 }
1250 }
1251
1252 if (lpnFit)
1253 *lpnFit = nFit;
1254
1255 if (! alpDx)
1256 HeapFree(GetProcessHeap(), 0, dxs);
1257
1258 release_dc_ptr( dc );
1259
1260 TRACE("returning %d %d x %d\n",nFit,size->cx,size->cy);
1261 return ret;
1262 }
1263
1264 /***********************************************************************
1265 * GetTextMetricsA (GDI32.@)
1266 */
1267 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1268 {
1269 TEXTMETRICW tm32;
1270
1271 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1272 FONT_TextMetricWToA( &tm32, metrics );
1273 return TRUE;
1274 }
1275
1276 /***********************************************************************
1277 * GetTextMetricsW (GDI32.@)
1278 */
1279 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1280 {
1281 PHYSDEV physdev;
1282 BOOL ret = FALSE;
1283 DC * dc = get_dc_ptr( hdc );
1284 if (!dc) return FALSE;
1285
1286 physdev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
1287 ret = physdev->funcs->pGetTextMetrics( physdev, metrics );
1288
1289 if (ret)
1290 {
1291 /* device layer returns values in device units
1292 * therefore we have to convert them to logical */
1293
1294 metrics->tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1295 metrics->tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1296
1297 #define WDPTOLP(x) ((x<0)? \
1298 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1299 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1300 #define HDPTOLP(y) ((y<0)? \
1301 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1302 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1303
1304 metrics->tmHeight = HDPTOLP(metrics->tmHeight);
1305 metrics->tmAscent = HDPTOLP(metrics->tmAscent);
1306 metrics->tmDescent = HDPTOLP(metrics->tmDescent);
1307 metrics->tmInternalLeading = HDPTOLP(metrics->tmInternalLeading);
1308 metrics->tmExternalLeading = HDPTOLP(metrics->tmExternalLeading);
1309 metrics->tmAveCharWidth = WDPTOLP(metrics->tmAveCharWidth);
1310 metrics->tmMaxCharWidth = WDPTOLP(metrics->tmMaxCharWidth);
1311 metrics->tmOverhang = WDPTOLP(metrics->tmOverhang);
1312 ret = TRUE;
1313 #undef WDPTOLP
1314 #undef HDPTOLP
1315 TRACE("text metrics:\n"
1316 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1317 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1318 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1319 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1320 " PitchAndFamily = %02x\n"
1321 " --------------------\n"
1322 " InternalLeading = %i\n"
1323 " Ascent = %i\n"
1324 " Descent = %i\n"
1325 " Height = %i\n",
1326 metrics->tmWeight, metrics->tmFirstChar, metrics->tmAveCharWidth,
1327 metrics->tmItalic, metrics->tmLastChar, metrics->tmMaxCharWidth,
1328 metrics->tmUnderlined, metrics->tmDefaultChar, metrics->tmOverhang,
1329 metrics->tmStruckOut, metrics->tmBreakChar, metrics->tmCharSet,
1330 metrics->tmPitchAndFamily,
1331 metrics->tmInternalLeading,
1332 metrics->tmAscent,
1333 metrics->tmDescent,
1334 metrics->tmHeight );
1335 }
1336 release_dc_ptr( dc );
1337 return ret;
1338 }
1339
1340
1341 /***********************************************************************
1342 * GetOutlineTextMetricsA (GDI32.@)
1343 * Gets metrics for TrueType fonts.
1344 *
1345 * NOTES
1346 * If the supplied buffer isn't big enough Windows partially fills it up to
1347 * its given length and returns that length.
1348 *
1349 * RETURNS
1350 * Success: Non-zero or size of required buffer
1351 * Failure: 0
1352 */
1353 UINT WINAPI GetOutlineTextMetricsA(
1354 HDC hdc, /* [in] Handle of device context */
1355 UINT cbData, /* [in] Size of metric data array */
1356 LPOUTLINETEXTMETRICA lpOTM) /* [out] Address of metric data array */
1357 {
1358 char buf[512], *ptr;
1359 UINT ret, needed;
1360 OUTLINETEXTMETRICW *lpOTMW = (OUTLINETEXTMETRICW *)buf;
1361 OUTLINETEXTMETRICA *output = lpOTM;
1362 INT left, len;
1363
1364 if((ret = GetOutlineTextMetricsW(hdc, 0, NULL)) == 0)
1365 return 0;
1366 if(ret > sizeof(buf))
1367 lpOTMW = HeapAlloc(GetProcessHeap(), 0, ret);
1368 GetOutlineTextMetricsW(hdc, ret, lpOTMW);
1369
1370 needed = sizeof(OUTLINETEXTMETRICA);
1371 if(lpOTMW->otmpFamilyName)
1372 needed += WideCharToMultiByte(CP_ACP, 0,
1373 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1374 NULL, 0, NULL, NULL);
1375 if(lpOTMW->otmpFaceName)
1376 needed += WideCharToMultiByte(CP_ACP, 0,
1377 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1378 NULL, 0, NULL, NULL);
1379 if(lpOTMW->otmpStyleName)
1380 needed += WideCharToMultiByte(CP_ACP, 0,
1381 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1382 NULL, 0, NULL, NULL);
1383 if(lpOTMW->otmpFullName)
1384 needed += WideCharToMultiByte(CP_ACP, 0,
1385 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1386 NULL, 0, NULL, NULL);
1387
1388 if(!lpOTM) {
1389 ret = needed;
1390 goto end;
1391 }
1392
1393 TRACE("needed = %d\n", needed);
1394 if(needed > cbData)
1395 /* Since the supplied buffer isn't big enough, we'll alloc one
1396 that is and memcpy the first cbData bytes into the lpOTM at
1397 the end. */
1398 output = HeapAlloc(GetProcessHeap(), 0, needed);
1399
1400 ret = output->otmSize = min(needed, cbData);
1401 FONT_TextMetricWToA( &lpOTMW->otmTextMetrics, &output->otmTextMetrics );
1402 output->otmFiller = 0;
1403 output->otmPanoseNumber = lpOTMW->otmPanoseNumber;
1404 output->otmfsSelection = lpOTMW->otmfsSelection;
1405 output->otmfsType = lpOTMW->otmfsType;
1406 output->otmsCharSlopeRise = lpOTMW->otmsCharSlopeRise;
1407 output->otmsCharSlopeRun = lpOTMW->otmsCharSlopeRun;
1408 output->otmItalicAngle = lpOTMW->otmItalicAngle;
1409 output->otmEMSquare = lpOTMW->otmEMSquare;
1410 output->otmAscent = lpOTMW->otmAscent;
1411 output->otmDescent = lpOTMW->otmDescent;
1412 output->otmLineGap = lpOTMW->otmLineGap;
1413 output->otmsCapEmHeight = lpOTMW->otmsCapEmHeight;
1414 output->otmsXHeight = lpOTMW->otmsXHeight;
1415 output->otmrcFontBox = lpOTMW->otmrcFontBox;
1416 output->otmMacAscent = lpOTMW->otmMacAscent;
1417 output->otmMacDescent = lpOTMW->otmMacDescent;
1418 output->otmMacLineGap = lpOTMW->otmMacLineGap;
1419 output->otmusMinimumPPEM = lpOTMW->otmusMinimumPPEM;
1420 output->otmptSubscriptSize = lpOTMW->otmptSubscriptSize;
1421 output->otmptSubscriptOffset = lpOTMW->otmptSubscriptOffset;
1422 output->otmptSuperscriptSize = lpOTMW->otmptSuperscriptSize;
1423 output->otmptSuperscriptOffset = lpOTMW->otmptSuperscriptOffset;
1424 output->otmsStrikeoutSize = lpOTMW->otmsStrikeoutSize;
1425 output->otmsStrikeoutPosition = lpOTMW->otmsStrikeoutPosition;
1426 output->otmsUnderscoreSize = lpOTMW->otmsUnderscoreSize;
1427 output->otmsUnderscorePosition = lpOTMW->otmsUnderscorePosition;
1428
1429
1430 ptr = (char*)(output + 1);
1431 left = needed - sizeof(*output);
1432
1433 if(lpOTMW->otmpFamilyName) {
1434 output->otmpFamilyName = (LPSTR)(ptr - (char*)output);
1435 len = WideCharToMultiByte(CP_ACP, 0,
1436 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFamilyName), -1,
1437 ptr, left, NULL, NULL);
1438 left -= len;
1439 ptr += len;
1440 } else
1441 output->otmpFamilyName = 0;
1442
1443 if(lpOTMW->otmpFaceName) {
1444 output->otmpFaceName = (LPSTR)(ptr - (char*)output);
1445 len = WideCharToMultiByte(CP_ACP, 0,
1446 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFaceName), -1,
1447 ptr, left, NULL, NULL);
1448 left -= len;
1449 ptr += len;
1450 } else
1451 output->otmpFaceName = 0;
1452
1453 if(lpOTMW->otmpStyleName) {
1454 output->otmpStyleName = (LPSTR)(ptr - (char*)output);
1455 len = WideCharToMultiByte(CP_ACP, 0,
1456 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpStyleName), -1,
1457 ptr, left, NULL, NULL);
1458 left -= len;
1459 ptr += len;
1460 } else
1461 output->otmpStyleName = 0;
1462
1463 if(lpOTMW->otmpFullName) {
1464 output->otmpFullName = (LPSTR)(ptr - (char*)output);
1465 len = WideCharToMultiByte(CP_ACP, 0,
1466 (WCHAR*)((char*)lpOTMW + (ptrdiff_t)lpOTMW->otmpFullName), -1,
1467 ptr, left, NULL, NULL);
1468 left -= len;
1469 } else
1470 output->otmpFullName = 0;
1471
1472 assert(left == 0);
1473
1474 if(output != lpOTM) {
1475 memcpy(lpOTM, output, cbData);
1476 HeapFree(GetProcessHeap(), 0, output);
1477
1478 /* check if the string offsets really fit into the provided size */
1479 /* FIXME: should we check string length as well? */
1480 /* make sure that we don't read/write beyond the provided buffer */
1481 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(LPSTR))
1482 {
1483 if ((UINT_PTR)lpOTM->otmpFamilyName >= lpOTM->otmSize)
1484 lpOTM->otmpFamilyName = 0; /* doesn't fit */
1485 }
1486
1487 /* make sure that we don't read/write beyond the provided buffer */
1488 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(LPSTR))
1489 {
1490 if ((UINT_PTR)lpOTM->otmpFaceName >= lpOTM->otmSize)
1491 lpOTM->otmpFaceName = 0; /* doesn't fit */
1492 }
1493
1494 /* make sure that we don't read/write beyond the provided buffer */
1495 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(LPSTR))
1496 {
1497 if ((UINT_PTR)lpOTM->otmpStyleName >= lpOTM->otmSize)
1498 lpOTM->otmpStyleName = 0; /* doesn't fit */
1499 }
1500
1501 /* make sure that we don't read/write beyond the provided buffer */
1502 if (lpOTM->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(LPSTR))
1503 {
1504 if ((UINT_PTR)lpOTM->otmpFullName >= lpOTM->otmSize)
1505 lpOTM->otmpFullName = 0; /* doesn't fit */
1506 }
1507 }
1508
1509 end:
1510 if(lpOTMW != (OUTLINETEXTMETRICW *)buf)
1511 HeapFree(GetProcessHeap(), 0, lpOTMW);
1512
1513 return ret;
1514 }
1515
1516
1517 /***********************************************************************
1518 * GetOutlineTextMetricsW [GDI32.@]
1519 */
1520 UINT WINAPI GetOutlineTextMetricsW(
1521 HDC hdc, /* [in] Handle of device context */
1522 UINT cbData, /* [in] Size of metric data array */
1523 LPOUTLINETEXTMETRICW lpOTM) /* [out] Address of metric data array */
1524 {
1525 DC *dc = get_dc_ptr( hdc );
1526 OUTLINETEXTMETRICW *output = lpOTM;
1527 PHYSDEV dev;
1528 UINT ret;
1529
1530 TRACE("(%p,%d,%p)\n", hdc, cbData, lpOTM);
1531 if(!dc) return 0;
1532
1533 dev = GET_DC_PHYSDEV( dc, pGetOutlineTextMetrics );
1534 ret = dev->funcs->pGetOutlineTextMetrics( dev, cbData, output );
1535
1536 if (lpOTM && ret > cbData)
1537 {
1538 output = HeapAlloc(GetProcessHeap(), 0, ret);
1539 ret = dev->funcs->pGetOutlineTextMetrics( dev, ret, output );
1540 }
1541
1542 if (lpOTM && ret)
1543 {
1544 output->otmTextMetrics.tmDigitizedAspectX = GetDeviceCaps(hdc, LOGPIXELSX);
1545 output->otmTextMetrics.tmDigitizedAspectY = GetDeviceCaps(hdc, LOGPIXELSY);
1546
1547 #define WDPTOLP(x) ((x<0)? \
1548 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1549 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1550 #define HDPTOLP(y) ((y<0)? \
1551 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1552 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1553
1554 output->otmTextMetrics.tmHeight = HDPTOLP(output->otmTextMetrics.tmHeight);
1555 output->otmTextMetrics.tmAscent = HDPTOLP(output->otmTextMetrics.tmAscent);
1556 output->otmTextMetrics.tmDescent = HDPTOLP(output->otmTextMetrics.tmDescent);
1557 output->otmTextMetrics.tmInternalLeading = HDPTOLP(output->otmTextMetrics.tmInternalLeading);
1558 output->otmTextMetrics.tmExternalLeading = HDPTOLP(output->otmTextMetrics.tmExternalLeading);
1559 output->otmTextMetrics.tmAveCharWidth = WDPTOLP(output->otmTextMetrics.tmAveCharWidth);
1560 output->otmTextMetrics.tmMaxCharWidth = WDPTOLP(output->otmTextMetrics.tmMaxCharWidth);
1561 output->otmTextMetrics.tmOverhang = WDPTOLP(output->otmTextMetrics.tmOverhang);
1562 output->otmAscent = HDPTOLP(output->otmAscent);
1563 output->otmDescent = HDPTOLP(output->otmDescent);
1564 output->otmLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmLineGap));
1565 output->otmsCapEmHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsCapEmHeight));
1566 output->otmsXHeight = abs(INTERNAL_YDSTOWS(dc,output->otmsXHeight));
1567 output->otmrcFontBox.top = HDPTOLP(output->otmrcFontBox.top);
1568 output->otmrcFontBox.bottom = HDPTOLP(output->otmrcFontBox.bottom);
1569 output->otmrcFontBox.left = WDPTOLP(output->otmrcFontBox.left);
1570 output->otmrcFontBox.right = WDPTOLP(output->otmrcFontBox.right);
1571 output->otmMacAscent = HDPTOLP(output->otmMacAscent);
1572 output->otmMacDescent = HDPTOLP(output->otmMacDescent);
1573 output->otmMacLineGap = abs(INTERNAL_YDSTOWS(dc,output->otmMacLineGap));
1574 output->otmptSubscriptSize.x = WDPTOLP(output->otmptSubscriptSize.x);
1575 output->otmptSubscriptSize.y = HDPTOLP(output->otmptSubscriptSize.y);
1576 output->otmptSubscriptOffset.x = WDPTOLP(output->otmptSubscriptOffset.x);
1577 output->otmptSubscriptOffset.y = HDPTOLP(output->otmptSubscriptOffset.y);
1578 output->otmptSuperscriptSize.x = WDPTOLP(output->otmptSuperscriptSize.x);
1579 output->otmptSuperscriptSize.y = HDPTOLP(output->otmptSuperscriptSize.y);
1580 output->otmptSuperscriptOffset.x = WDPTOLP(output->otmptSuperscriptOffset.x);
1581 output->otmptSuperscriptOffset.y = HDPTOLP(output->otmptSuperscriptOffset.y);
1582 output->otmsStrikeoutSize = abs(INTERNAL_YDSTOWS(dc,output->otmsStrikeoutSize));
1583 output->otmsStrikeoutPosition = HDPTOLP(output->otmsStrikeoutPosition);
1584 output->otmsUnderscoreSize = HDPTOLP(output->otmsUnderscoreSize);
1585 output->otmsUnderscorePosition = HDPTOLP(output->otmsUnderscorePosition);
1586 #undef WDPTOLP
1587 #undef HDPTOLP
1588 if(output != lpOTM)
1589 {
1590 memcpy(lpOTM, output, cbData);
1591 HeapFree(GetProcessHeap(), 0, output);
1592 ret = cbData;
1593 }
1594 }
1595 release_dc_ptr(dc);
1596 return ret;
1597 }
1598
1599 static LPSTR FONT_GetCharsByRangeA(HDC hdc, UINT firstChar, UINT lastChar, PINT pByteLen)
1600 {
1601 INT i, count = lastChar - firstChar + 1;
1602 UINT mbcp;
1603 UINT c;
1604 LPSTR str;
1605
1606 if (count <= 0)
1607 return NULL;
1608
1609 mbcp = GdiGetCodePage(hdc);
1610 switch (mbcp)
1611 {
1612 case 932:
1613 case 936:
1614 case 949:
1615 case 950:
1616 case 1361:
1617 if (lastChar > 0xffff)
1618 return NULL;
1619 if ((firstChar ^ lastChar) > 0xff)
1620 return NULL;
1621 break;
1622 default:
1623 if (lastChar > 0xff)
1624 return NULL;
1625 mbcp = 0;
1626 break;
1627 }
1628
1629 str = HeapAlloc(GetProcessHeap(), 0, count * 2 + 1);
1630 if (str == NULL)
1631 return NULL;
1632
1633 for(i = 0, c = firstChar; c <= lastChar; i++, c++)
1634 {
1635 if (mbcp) {
1636 if (c > 0xff)
1637 str[i++] = (BYTE)(c >> 8);
1638 if (c <= 0xff && IsDBCSLeadByteEx(mbcp, c))
1639 str[i] = 0x1f; /* FIXME: use default character */
1640 else
1641 str[i] = (BYTE)c;
1642 }
1643 else
1644 str[i] = (BYTE)c;
1645 }
1646 str[i] = '\0';
1647
1648 *pByteLen = i;
1649
1650 return str;
1651 }
1652
1653 /***********************************************************************
1654 * GetCharWidthW (GDI32.@)
1655 * GetCharWidth32W (GDI32.@)
1656 */
1657 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT firstChar, UINT lastChar,
1658 LPINT buffer )
1659 {
1660 UINT i;
1661 BOOL ret;
1662 PHYSDEV dev;
1663 DC * dc = get_dc_ptr( hdc );
1664
1665 if (!dc) return FALSE;
1666
1667 dev = GET_DC_PHYSDEV( dc, pGetCharWidth );
1668 ret = dev->funcs->pGetCharWidth( dev, firstChar, lastChar, buffer );
1669
1670 if (ret)
1671 {
1672 /* convert device units to logical */
1673 for( i = firstChar; i <= lastChar; i++, buffer++ )
1674 *buffer = INTERNAL_XDSTOWS(dc, *buffer);
1675 }
1676 release_dc_ptr( dc );
1677 return ret;
1678 }
1679
1680
1681 /***********************************************************************
1682 * GetCharWidthA (GDI32.@)
1683 * GetCharWidth32A (GDI32.@)
1684 */
1685 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT firstChar, UINT lastChar,
1686 LPINT buffer )
1687 {
1688 INT i, wlen;
1689 LPSTR str;
1690 LPWSTR wstr;
1691 BOOL ret = TRUE;
1692
1693 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
1694 if(str == NULL)
1695 return FALSE;
1696
1697 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
1698
1699 for(i = 0; i < wlen; i++)
1700 {
1701 if(!GetCharWidth32W(hdc, wstr[i], wstr[i], buffer))
1702 {
1703 ret = FALSE;
1704 break;
1705 }
1706 buffer++;
1707 }
1708
1709 HeapFree(GetProcessHeap(), 0, str);
1710 HeapFree(GetProcessHeap(), 0, wstr);
1711
1712 return ret;
1713 }
1714
1715
1716 /* helper for nulldrv_ExtTextOut */
1717 static DWORD get_glyph_bitmap( HDC hdc, UINT index, UINT aa_flags,
1718 GLYPHMETRICS *metrics, struct gdi_image_bits *image )
1719 {
1720 UINT ggo_flags = aa_flags | GGO_GLYPH_INDEX;
1721 static const MAT2 identity = { {0,1}, {0,0}, {0,0}, {0,1} };
1722 UINT indices[3] = {0, 0, 0x20};
1723 int i;
1724 DWORD ret, size;
1725 int stride;
1726
1727 indices[0] = index;
1728
1729 for (i = 0; i < sizeof(indices) / sizeof(indices[0]); i++)
1730 {
1731 index = indices[i];
1732 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, 0, NULL, &identity );
1733 if (ret != GDI_ERROR) break;
1734 }
1735
1736 if (ret == GDI_ERROR) return ERROR_NOT_FOUND;
1737 if (!image) return ERROR_SUCCESS;
1738
1739 image->ptr = NULL;
1740 image->free = NULL;
1741 if (!ret) return ERROR_SUCCESS; /* empty glyph */
1742
1743 stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1744 size = metrics->gmBlackBoxY * stride;
1745
1746 if (!(image->ptr = HeapAlloc( GetProcessHeap(), 0, size ))) return ERROR_OUTOFMEMORY;
1747 image->is_copy = TRUE;
1748 image->free = free_heap_bits;
1749
1750 ret = GetGlyphOutlineW( hdc, index, ggo_flags, metrics, size, image->ptr, &identity );
1751 if (ret == GDI_ERROR)
1752 {
1753 HeapFree( GetProcessHeap(), 0, image->ptr );
1754 return ERROR_NOT_FOUND;
1755 }
1756 return ERROR_SUCCESS;
1757 }
1758
1759 /* helper for nulldrv_ExtTextOut */
1760 static RECT get_total_extents( HDC hdc, INT x, INT y, UINT flags, UINT aa_flags,
1761 LPCWSTR str, UINT count, const INT *dx )
1762 {
1763 int i;
1764 RECT rect, bounds;
1765
1766 reset_bounds( &bounds );
1767 for (i = 0; i < count; i++)
1768 {
1769 GLYPHMETRICS metrics;
1770
1771 if (get_glyph_bitmap( hdc, (UINT)str[i], aa_flags, &metrics, NULL )) continue;
1772
1773 rect.left = x + metrics.gmptGlyphOrigin.x;
1774 rect.top = y - metrics.gmptGlyphOrigin.y;
1775 rect.right = rect.left + metrics.gmBlackBoxX;
1776 rect.bottom = rect.top + metrics.gmBlackBoxY;
1777 add_bounds_rect( &bounds, &rect );
1778
1779 if (dx)
1780 {
1781 if (flags & ETO_PDY)
1782 {
1783 x += dx[ i * 2 ];
1784 y += dx[ i * 2 + 1];
1785 }
1786 else x += dx[ i ];
1787 }
1788 else
1789 {
1790 x += metrics.gmCellIncX;
1791 y += metrics.gmCellIncY;
1792 }
1793 }
1794 return bounds;
1795 }
1796
1797 /* helper for nulldrv_ExtTextOut */
1798 static void draw_glyph( HDC hdc, INT origin_x, INT origin_y, const GLYPHMETRICS *metrics,
1799 const struct gdi_image_bits *image, const RECT *clip )
1800 {
1801 static const BYTE masks[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1802 UINT x, y, i, count;
1803 BYTE *ptr = image->ptr;
1804 int stride = get_dib_stride( metrics->gmBlackBoxX, 1 );
1805 POINT *pts;
1806 RECT rect, clipped_rect;
1807
1808 rect.left = origin_x + metrics->gmptGlyphOrigin.x;
1809 rect.top = origin_y - metrics->gmptGlyphOrigin.y;
1810 rect.right = rect.left + metrics->gmBlackBoxX;
1811 rect.bottom = rect.top + metrics->gmBlackBoxY;
1812 if (!clip) clipped_rect = rect;
1813 else if (!intersect_rect( &clipped_rect, &rect, clip )) return;
1814
1815 pts = HeapAlloc( GetProcessHeap(), 0,
1816 max(2,metrics->gmBlackBoxX) * metrics->gmBlackBoxY * sizeof(*pts) );
1817 if (!pts) return;
1818
1819 count = 0;
1820 ptr += (clipped_rect.top - rect.top) * stride;
1821 for (y = clipped_rect.top; y < clipped_rect.bottom; y++, ptr += stride)
1822 {
1823 for (x = clipped_rect.left - rect.left; x < clipped_rect.right - rect.left; x++)
1824 {
1825 while (x < clipped_rect.right - rect.left && !(ptr[x / 8] & masks[x % 8])) x++;
1826 pts[count].x = rect.left + x;
1827 while (x < clipped_rect.right - rect.left && (ptr[x / 8] & masks[x % 8])) x++;
1828 pts[count + 1].x = rect.left + x;
1829 if (pts[count + 1].x > pts[count].x)
1830 {
1831 pts[count].y = pts[count + 1].y = y;
1832 count += 2;
1833 }
1834 }
1835 }
1836 DPtoLP( hdc, pts, count );
1837 for (i = 0; i < count; i += 2) Polyline( hdc, pts + i, 2 );
1838 HeapFree( GetProcessHeap(), 0, pts );
1839 }
1840
1841 /***********************************************************************
1842 * nulldrv_ExtTextOut
1843 */
1844 BOOL nulldrv_ExtTextOut( PHYSDEV dev, INT x, INT y, UINT flags, const RECT *rect,
1845 LPCWSTR str, UINT count, const INT *dx )
1846 {
1847 DC *dc = get_nulldrv_dc( dev );
1848 UINT aa_flags, i;
1849 DWORD err;
1850 HGDIOBJ orig;
1851 HPEN pen;
1852
1853 if (flags & ETO_OPAQUE)
1854 {
1855 RECT rc = *rect;
1856 HBRUSH brush = CreateSolidBrush( GetNearestColor( dev->hdc, GetBkColor(dev->hdc) ));
1857
1858 if (brush)
1859 {
1860 orig = SelectObject( dev->hdc, brush );
1861 DPtoLP( dev->hdc, (POINT *)&rc, 2 );
1862 PatBlt( dev->hdc, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, PATCOPY );
1863 SelectObject( dev->hdc, orig );
1864 DeleteObject( brush );
1865 }
1866 }
1867
1868 if (!count) return TRUE;
1869
1870 aa_flags = get_font_aa_flags( dev->hdc );
1871
1872 if (aa_flags != GGO_BITMAP)
1873 {
1874 char buffer[FIELD_OFFSET( BITMAPINFO, bmiColors[256] )];
1875 BITMAPINFO *info = (BITMAPINFO *)buffer;
1876 struct gdi_image_bits bits;
1877 struct bitblt_coords src, dst;
1878 PHYSDEV dst_dev;
1879
1880 dst_dev = GET_DC_PHYSDEV( dc, pPutImage );
1881 src.visrect = get_total_extents( dev->hdc, x, y, flags, aa_flags, str, count, dx );
1882 if (flags & ETO_CLIPPED) intersect_rect( &src.visrect, &src.visrect, rect );
1883 if (!clip_visrect( dc, &src.visrect, &src.visrect )) return TRUE;
1884
1885 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1886 src.x = src.visrect.left;
1887 src.y = src.visrect.top;
1888 src.width = src.visrect.right - src.visrect.left;
1889 src.height = src.visrect.bottom - src.visrect.top;
1890 dst = src;
1891 if ((flags & ETO_OPAQUE) && (src.visrect.left >= rect->left) && (src.visrect.top >= rect->top) &&
1892 (src.visrect.right <= rect->right) && (src.visrect.bottom <= rect->bottom))
1893 {
1894 /* we can avoid the GetImage, just query the needed format */
1895 memset( &info->bmiHeader, 0, sizeof(info->bmiHeader) );
1896 info->bmiHeader.biSize = sizeof(info->bmiHeader);
1897 info->bmiHeader.biWidth = src.width;
1898 info->bmiHeader.biHeight = -src.height;
1899 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, NULL, NULL, NULL, 0 );
1900 if (!err || err == ERROR_BAD_FORMAT)
1901 {
1902 /* make the source rectangle relative to the source bits */
1903 src.x = src.y = 0;
1904 src.visrect.left = src.visrect.top = 0;
1905 src.visrect.right = src.width;
1906 src.visrect.bottom = src.height;
1907
1908 bits.ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1909 if (!bits.ptr) return ERROR_OUTOFMEMORY;
1910 bits.is_copy = TRUE;
1911 bits.free = free_heap_bits;
1912 err = ERROR_SUCCESS;
1913 }
1914 }
1915 else
1916 {
1917 PHYSDEV src_dev = GET_DC_PHYSDEV( dc, pGetImage );
1918 err = src_dev->funcs->pGetImage( src_dev, 0, info, &bits, &src );
1919 if (!err && !bits.is_copy)
1920 {
1921 void *ptr = HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info ));
1922 if (!ptr)
1923 {
1924 if (bits.free) bits.free( &bits );
1925 return ERROR_OUTOFMEMORY;
1926 }
1927 memcpy( ptr, bits.ptr, get_dib_image_size( info ));
1928 if (bits.free) bits.free( &bits );
1929 bits.ptr = ptr;
1930 bits.is_copy = TRUE;
1931 bits.free = free_heap_bits;
1932 }
1933 }
1934 if (!err)
1935 {
1936 /* make x,y relative to the image bits */
1937 x += src.visrect.left - dst.visrect.left;
1938 y += src.visrect.top - dst.visrect.top;
1939 render_aa_text_bitmapinfo( dev->hdc, info, &bits, &src, x, y, flags,
1940 aa_flags, str, count, dx );
1941 err = dst_dev->funcs->pPutImage( dst_dev, 0, 0, info, &bits, &src, &dst, SRCCOPY );
1942 if (bits.free) bits.free( &bits );
1943 return !err;
1944 }
1945 }
1946
1947 pen = CreatePen( PS_SOLID, 1, GetTextColor(dev->hdc) );
1948 orig = SelectObject( dev->hdc, pen );
1949
1950 for (i = 0; i < count; i++)
1951 {
1952 GLYPHMETRICS metrics;
1953 struct gdi_image_bits image;
1954
1955 err = get_glyph_bitmap( dev->hdc, (UINT)str[i], GGO_BITMAP, &metrics, &image );
1956 if (err) continue;
1957
1958 if (image.ptr) draw_glyph( dev->hdc, x, y, &metrics, &image, (flags & ETO_CLIPPED) ? rect : NULL );
1959 if (image.free) image.free( &image );
1960
1961 if (dx)
1962 {
1963 if (flags & ETO_PDY)
1964 {
1965 x += dx[ i * 2 ];
1966 y += dx[ i * 2 + 1];
1967 }
1968 else x += dx[ i ];
1969 }
1970 else
1971 {
1972 x += metrics.gmCellIncX;
1973 y += metrics.gmCellIncY;
1974 }
1975 }
1976
1977 SelectObject( dev->hdc, orig );
1978 DeleteObject( pen );
1979 return TRUE;
1980 }
1981
1982
1983 /***********************************************************************
1984 * ExtTextOutA (GDI32.@)
1985 *
1986 * See ExtTextOutW.
1987 */
1988 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags,
1989 const RECT *lprect, LPCSTR str, UINT count, const INT *lpDx )
1990 {
1991 INT wlen;
1992 UINT codepage;
1993 LPWSTR p;
1994 BOOL ret;
1995 LPINT lpDxW = NULL;
1996
1997 if (flags & ETO_GLYPH_INDEX)
1998 return ExtTextOutW( hdc, x, y, flags, lprect, (LPCWSTR)str, count, lpDx );
1999
2000 p = FONT_mbtowc(hdc, str, count, &wlen, &codepage);
2001
2002 if (lpDx) {
2003 unsigned int i = 0, j = 0;
2004
2005 /* allocate enough for a ETO_PDY */
2006 lpDxW = HeapAlloc( GetProcessHeap(), 0, 2*wlen*sizeof(INT));
2007 while(i < count) {
2008 if(IsDBCSLeadByteEx(codepage, str[i]))
2009 {
2010 if(flags & ETO_PDY)
2011 {
2012 lpDxW[j++] = lpDx[i * 2] + lpDx[(i + 1) * 2];
2013 lpDxW[j++] = lpDx[i * 2 + 1] + lpDx[(i + 1) * 2 + 1];
2014 }
2015 else
2016 lpDxW[j++] = lpDx[i] + lpDx[i + 1];
2017 i = i + 2;
2018 }
2019 else
2020 {
2021 if(flags & ETO_PDY)
2022 {
2023 lpDxW[j++] = lpDx[i * 2];
2024 lpDxW[j++] = lpDx[i * 2 + 1];
2025 }
2026 else
2027 lpDxW[j++] = lpDx[i];
2028 i = i + 1;
2029 }
2030 }
2031 }
2032
2033 ret = ExtTextOutW( hdc, x, y, flags, lprect, p, wlen, lpDxW );
2034
2035 HeapFree( GetProcessHeap(), 0, p );
2036 HeapFree( GetProcessHeap(), 0, lpDxW );
2037 return ret;
2038 }
2039
2040
2041 /***********************************************************************
2042 * ExtTextOutW (GDI32.@)
2043 *
2044 * Draws text using the currently selected font, background color, and text color.
2045 *
2046 *
2047 * PARAMS
2048 * x,y [I] coordinates of string
2049 * flags [I]
2050 * ETO_GRAYED - undocumented on MSDN
2051 * ETO_OPAQUE - use background color for fill the rectangle
2052 * ETO_CLIPPED - clipping text to the rectangle
2053 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2054 * than encoded characters. Implies ETO_IGNORELANGUAGE
2055 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2056 * Affects BiDi ordering
2057 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2058 * ETO_PDY - unimplemented
2059 * ETO_NUMERICSLATIN - unimplemented always assumed -
2060 * do not translate numbers into locale representations
2061 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2062 * lprect [I] dimensions for clipping or/and opaquing
2063 * str [I] text string
2064 * count [I] number of symbols in string
2065 * lpDx [I] optional parameter with distance between drawing characters
2066 *
2067 * RETURNS
2068 * Success: TRUE
2069 * Failure: FALSE
2070 */
2071 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags,
2072 const RECT *lprect, LPCWSTR str, UINT count, const INT *lpDx )
2073 {
2074 BOOL ret = FALSE;
2075 LPWSTR reordered_str = (LPWSTR)str;
2076 WORD *glyphs = NULL;
2077 UINT align = GetTextAlign( hdc );
2078 DWORD layout = GetLayout( hdc );
2079 POINT pt;
2080 TEXTMETRICW tm;
2081 LOGFONTW lf;
2082 double cosEsc, sinEsc;
2083 INT char_extra;
2084 SIZE sz;
2085 RECT rc;
2086 BOOL done_extents = FALSE;
2087 POINT *deltas = NULL, width = {0, 0};
2088 DWORD type;
2089 DC * dc = get_dc_ptr( hdc );
2090 PHYSDEV physdev;
2091 INT breakRem;
2092 static int quietfixme = 0;
2093
2094 if (!dc) return FALSE;
2095
2096 breakRem = dc->breakRem;
2097
2098 if (quietfixme == 0 && flags & (ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN))
2099 {
2100 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2101 quietfixme = 1;
2102 }
2103
2104 update_dc( dc );
2105 physdev = GET_DC_PHYSDEV( dc, pExtTextOut );
2106 type = GetObjectType(hdc);
2107 if(type == OBJ_METADC || type == OBJ_ENHMETADC)
2108 {
2109 ret = physdev->funcs->pExtTextOut( physdev, x, y, flags, lprect, str, count, lpDx );
2110 release_dc_ptr( dc );
2111 return ret;
2112 }
2113
2114 if (!lprect)
2115 flags &= ~ETO_CLIPPED;
2116
2117 if (flags & ETO_RTLREADING) align |= TA_RTLREADING;
2118 if (layout & LAYOUT_RTL)
2119 {
2120 if ((align & TA_CENTER) != TA_CENTER) align ^= TA_RIGHT;
2121 align ^= TA_RTLREADING;
2122 }
2123
2124 if( !(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0 )
2125 {
2126 INT cGlyphs;
2127 reordered_str = HeapAlloc(GetProcessHeap(), 0, count*sizeof(WCHAR));
2128
2129 BIDI_Reorder( hdc, str, count, GCP_REORDER,
2130 (align & TA_RTLREADING) ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR,
2131 reordered_str, count, NULL, &glyphs, &cGlyphs);
2132
2133 flags |= ETO_IGNORELANGUAGE;
2134 if (glyphs)
2135 {
2136 flags |= ETO_GLYPH_INDEX;
2137 if (cGlyphs != count)
2138 count = cGlyphs;
2139 }
2140 }
2141 else if(flags & ETO_GLYPH_INDEX)
2142 glyphs = reordered_str;
2143
2144 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc, x, y, flags,
2145 wine_dbgstr_rect(lprect), debugstr_wn(str, count), count, lpDx);
2146 TRACE("align = %x bkmode = %x mapmode = %x\n", align, GetBkMode(hdc), GetMapMode(hdc));
2147
2148 if(align & TA_UPDATECP)
2149 {
2150 GetCurrentPositionEx( hdc, &pt );
2151 x = pt.x;
2152 y = pt.y;
2153 }
2154
2155 GetTextMetricsW(hdc, &tm);
2156 GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf);
2157
2158 if(!(tm.tmPitchAndFamily & TMPF_VECTOR)) /* Non-scalable fonts shouldn't be rotated */
2159 lf.lfEscapement = 0;
2160
2161 if ((dc->GraphicsMode == GM_COMPATIBLE) &&
2162 (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 * dc->xformWorld2Vport.eM22 < 0))
2163 {
2164 lf.lfEscapement = -lf.lfEscapement;
2165 }
2166
2167 if(lf.lfEscapement != 0)
2168 {
2169 cosEsc = cos(lf.lfEscapement * M_PI / 1800);
2170 sinEsc = sin(lf.lfEscapement * M_PI / 1800);
2171 }
2172 else
2173 {
2174 cosEsc = 1;
2175 sinEsc = 0;
2176 }
2177
2178 if(flags & (ETO_CLIPPED | ETO_OPAQUE))
2179 {
2180 if(!lprect)
2181 {
2182 if(flags & ETO_GLYPH_INDEX)
2183 GetTextExtentPointI(hdc, glyphs, count, &sz);
2184 else
2185 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2186
2187 done_extents = TRUE;
2188 rc.left = x;
2189 rc.top = y;
2190 rc.right = x + sz.cx;
2191 rc.bottom = y + sz.cy;
2192 }
2193 else
2194 {
2195 rc = *lprect;
2196 }
2197
2198 LPtoDP(hdc, (POINT*)&rc, 2);
2199
2200 if(rc.left > rc.right) {INT tmp = rc.left; rc.left = rc.right; rc.right = tmp;}
2201 if(rc.top > rc.bottom) {INT tmp = rc.top; rc.top = rc.bottom; rc.bottom = tmp;}
2202 }
2203
2204 if (lprect && (flags & ETO_OPAQUE))
2205 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &rc, NULL, 0, NULL );
2206
2207 if(count == 0)
2208 {
2209 ret = TRUE;
2210 goto done;
2211 }
2212
2213 pt.x = x;
2214 pt.y = y;
2215 LPtoDP(hdc, &pt, 1);
2216 x = pt.x;
2217 y = pt.y;
2218
2219 char_extra = GetTextCharacterExtra(hdc);
2220 if(char_extra || dc->breakExtra || breakRem || lpDx || lf.lfEscapement != 0)
2221 {
2222 UINT i;
2223 SIZE tmpsz;
2224 POINT total = {0, 0}, desired[2];
2225
2226 deltas = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2227 for(i = 0; i < count; i++)
2228 {
2229 if(lpDx)
2230 {
2231 if(flags & ETO_PDY)
2232 {
2233 deltas[i].x = lpDx[i * 2] + char_extra;
2234 deltas[i].y = -lpDx[i * 2 + 1];
2235 }
2236 else
2237 {
2238 deltas[i].x = lpDx[i] + char_extra;
2239 deltas[i].y = 0;
2240 }
2241
2242 }
2243 else
2244 {
2245 if(flags & ETO_GLYPH_INDEX)
2246 GetTextExtentPointI(hdc, glyphs + i, 1, &tmpsz);
2247 else
2248 GetTextExtentPointW(hdc, reordered_str + i, 1, &tmpsz);
2249
2250 deltas[i].x = tmpsz.cx;
2251 deltas[i].y = 0;
2252 }
2253
2254 if (!(flags & ETO_GLYPH_INDEX) && (dc->breakExtra || breakRem) && reordered_str[i] == tm.tmBreakChar)
2255 {
2256 deltas[i].x = deltas[i].x + dc->breakExtra;
2257 if (breakRem > 0)
2258 {
2259 breakRem--;
2260 deltas[i].x++;
2261 }
2262 }
2263 total.x += deltas[i].x;
2264 total.y += deltas[i].y;
2265
2266 desired[0].x = desired[0].y = 0;
2267
2268 desired[1].x = cosEsc * total.x + sinEsc * total.y;
2269 desired[1].y = -sinEsc * total.x + cosEsc * total.y;
2270
2271 LPtoDP(hdc, desired, 2);
2272 desired[1].x -= desired[0].x;
2273 desired[1].y -= desired[0].y;
2274
2275 if (dc->GraphicsMode == GM_COMPATIBLE)
2276 {
2277 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM11 < 0)
2278 desired[1].x = -desired[1].x;
2279 if (dc->vport2WorldValid && dc->xformWorld2Vport.eM22 < 0)
2280 desired[1].y = -desired[1].y;
2281 }
2282 else
2283 {
2284 if (layout & LAYOUT_RTL) desired[1].x = -desired[1].x;
2285 }
2286
2287 deltas[i].x = desired[1].x - width.x;
2288 deltas[i].y = desired[1].y - width.y;
2289
2290 width = desired[1];
2291 }
2292 flags |= ETO_PDY;
2293 }
2294 else
2295 {
2296 if(!done_extents)
2297 {
2298 if(flags & ETO_GLYPH_INDEX)
2299 GetTextExtentPointI(hdc, glyphs, count, &sz);
2300 else
2301 GetTextExtentPointW(hdc, reordered_str, count, &sz);
2302 done_extents = TRUE;
2303 }
2304 width.x = abs(INTERNAL_XWSTODS(dc, sz.cx));
2305 width.y = 0;
2306 }
2307
2308 tm.tmAscent = abs(INTERNAL_YWSTODS(dc, tm.tmAscent));
2309 tm.tmDescent = abs(INTERNAL_YWSTODS(dc, tm.tmDescent));
2310 switch( align & (TA_LEFT | TA_RIGHT | TA_CENTER) )
2311 {
2312 case TA_LEFT:
2313 if (align & TA_UPDATECP)
2314 {
2315 pt.x = x + width.x;
2316 pt.y = y + width.y;
2317 DPtoLP(hdc, &pt, 1);
2318 MoveToEx(hdc, pt.x, pt.y, NULL);
2319 }
2320 break;
2321
2322 case TA_CENTER:
2323 x -= width.x / 2;
2324 y -= width.y / 2;
2325 break;
2326
2327 case TA_RIGHT:
2328 x -= width.x;
2329 y -= width.y;
2330 if (align & TA_UPDATECP)
2331 {
2332 pt.x = x;
2333 pt.y = y;
2334 DPtoLP(hdc, &pt, 1);
2335 MoveToEx(hdc, pt.x, pt.y, NULL);
2336 }
2337 break;
2338 }
2339
2340 switch( align & (TA_TOP | TA_BOTTOM | TA_BASELINE) )
2341 {
2342 case TA_TOP:
2343 y += tm.tmAscent * cosEsc;
2344 x += tm.tmAscent * sinEsc;
2345 break;
2346
2347 case TA_BOTTOM:
2348 y -= tm.tmDescent * cosEsc;
2349 x -= tm.tmDescent * sinEsc;
2350 break;
2351
2352 case TA_BASELINE:
2353 break;
2354 }
2355
2356 if (GetBkMode(hdc) != TRANSPARENT)
2357 {
2358 if(!((flags & ETO_CLIPPED) && (flags & ETO_OPAQUE)))
2359 {
2360 if(!(flags & ETO_OPAQUE) || !lprect ||
2361 x < rc.left || x + width.x >= rc.right ||
2362 y - tm.tmAscent < rc.top || y + tm.tmDescent >= rc.bottom)
2363 {
2364 RECT text_box;
2365 text_box.left = x;
2366 text_box.right = x + width.x;
2367 text_box.top = y - tm.tmAscent;
2368 text_box.bottom = y + tm.tmDescent;
2369
2370 if (flags & ETO_CLIPPED) intersect_rect( &text_box, &text_box, &rc );
2371 if (!is_rect_empty( &text_box ))
2372 physdev->funcs->pExtTextOut( physdev, 0, 0, ETO_OPAQUE, &text_box, NULL, 0, NULL );
2373 }
2374 }
2375 }
2376
2377 if(FontIsLinked(hdc) && !(flags & ETO_GLYPH_INDEX))
2378 {
2379 HFONT orig_font = dc->hFont, cur_font;
2380 UINT glyph;
2381 INT span = 0;
2382 POINT *offsets = NULL;
2383 unsigned int i;
2384
2385 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2386 for(i = 0; i < count; i++)
2387 {
2388 WineEngGetLinkedHFont(dc, reordered_str[i], &cur_font, &glyph);
2389 if(cur_font != dc->hFont)
2390 {
2391 if(!offsets)
2392 {
2393 unsigned int j;
2394 offsets = HeapAlloc(GetProcessHeap(), 0, count * sizeof(*deltas));
2395 offsets[0].x = offsets[0].y = 0;
2396
2397 if(!deltas)
2398 {
2399 SIZE tmpsz;
2400 for(j = 1; j < count; j++)
2401 {
2402 GetTextExtentPointW(hdc, reordered_str + j - 1, 1, &tmpsz);
2403 offsets[j].x = offsets[j - 1].x + abs(INTERNAL_XWSTODS(dc, tmpsz.cx));
2404 offsets[j].y = 0;
2405 }
2406 }
2407 else
2408 {
2409 for(j = 1; j < count; j++)
2410 {
2411 offsets[j].x = offsets[j - 1].x + deltas[j].x;
2412 offsets[j].y = offsets[j - 1].y + deltas[j].y;
2413 }
2414 }
2415 }
2416 if(span)
2417 {
2418 physdev->funcs->pExtTextOut( physdev, x + offsets[i - span].x,
2419 y + offsets[i - span].y,
2420 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2421 span, deltas ? (INT*)(deltas + (i - span)) : NULL);
2422 span = 0;
2423 }
2424 SelectObject(hdc, cur_font);
2425 }
2426 glyphs[span++] = glyph;
2427
2428 if(i == count - 1)
2429 {
2430 ret = physdev->funcs->pExtTextOut(physdev, x + (offsets ? offsets[count - span].x : 0),
2431 y + (offsets ? offsets[count - span].y : 0),
2432 (flags & ~ETO_OPAQUE) | ETO_GLYPH_INDEX, &rc, glyphs,
2433 span, deltas ? (INT*)(deltas + (count - span)) : NULL);
2434 SelectObject(hdc, orig_font);
2435 HeapFree(GetProcessHeap(), 0, offsets);
2436 }
2437 }
2438 }
2439 else
2440 {
2441 if(!(flags & ETO_GLYPH_INDEX) && dc->gdiFont)
2442 {
2443 glyphs = HeapAlloc(GetProcessHeap(), 0, count * sizeof(WORD));
2444 GetGlyphIndicesW(hdc, reordered_str, count, glyphs, 0);
2445 flags |= ETO_GLYPH_INDEX;
2446 }
2447 ret = physdev->funcs->pExtTextOut( physdev, x, y, (flags & ~ETO_OPAQUE), &rc,
2448 glyphs ? glyphs : reordered_str, count, (INT*)deltas );
2449 }
2450
2451 done:
2452 HeapFree(GetProcessHeap(), 0, deltas);
2453 if(glyphs != reordered_str)
2454 HeapFree(GetProcessHeap(), 0, glyphs);
2455 if(reordered_str != str)
2456 HeapFree(GetProcessHeap(), 0, reordered_str);
2457
2458 release_dc_ptr( dc );
2459
2460 if (ret && (lf.lfUnderline || lf.lfStrikeOut))
2461 {
2462 int underlinePos, strikeoutPos;
2463 int underlineWidth, strikeoutWidth;
2464 UINT size = GetOutlineTextMetricsW(hdc, 0, NULL);
2465 OUTLINETEXTMETRICW* otm = NULL;
2466 POINT pts[5];
2467 HPEN hpen = SelectObject(hdc, GetStockObject(NULL_PEN));
2468 HBRUSH hbrush = CreateSolidBrush(GetTextColor(hdc));
2469
2470 hbrush = SelectObject(hdc, hbrush);
2471
2472 if(!size)
2473 {
2474 underlinePos = 0;
2475 underlineWidth = tm.tmAscent / 20 + 1;
2476 strikeoutPos = tm.tmAscent / 2;
2477 strikeoutWidth = underlineWidth;
2478 }
2479 else
2480 {
2481 otm = HeapAlloc(GetProcessHeap(), 0, size);
2482 GetOutlineTextMetricsW(hdc, size, otm);
2483 underlinePos = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscorePosition ));
2484 if (otm->otmsUnderscorePosition < 0) underlinePos = -underlinePos;
2485 underlineWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsUnderscoreSize ));
2486 if (otm->otmsUnderscoreSize < 0) underlineWidth = -underlineWidth;
2487 strikeoutPos = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutPosition ));
2488 if (otm->otmsStrikeoutPosition < 0) strikeoutPos = -strikeoutPos;
2489 strikeoutWidth = abs( INTERNAL_YWSTODS( dc, otm->otmsStrikeoutSize ));
2490 HeapFree(GetProcessHeap(), 0, otm);
2491 }
2492
2493
2494 if (lf.lfUnderline)
2495 {
2496 pts[0].x = x - (underlinePos + underlineWidth / 2) * sinEsc;
2497 pts[0].y = y - (underlinePos + underlineWidth / 2) * cosEsc;
2498 pts[1].x = x + width.x - (underlinePos + underlineWidth / 2) * sinEsc;
2499 pts[1].y = y + width.y - (underlinePos + underlineWidth / 2) * cosEsc;
2500 pts[2].x = pts[1].x + underlineWidth * sinEsc;
2501 pts[2].y = pts[1].y + underlineWidth * cosEsc;
2502 pts[3].x = pts[0].x + underlineWidth * sinEsc;
2503 pts[3].y = pts[0].y + underlineWidth * cosEsc;
2504 pts[4].x = pts[0].x;
2505 pts[4].y = pts[0].y;
2506 DPtoLP(hdc, pts, 5);
2507 Polygon(hdc, pts, 5);
2508 }
2509
2510 if (lf.lfStrikeOut)
2511 {
2512 pts[0].x = x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2513 pts[0].y = y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2514 pts[1].x = x + width.x - (strikeoutPos + strikeoutWidth / 2) * sinEsc;
2515 pts[1].y = y + width.y - (strikeoutPos + strikeoutWidth / 2) * cosEsc;
2516 pts[2].x = pts[1].x + strikeoutWidth * sinEsc;
2517 pts[2].y = pts[1].y + strikeoutWidth * cosEsc;
2518 pts[3].x = pts[0].x + strikeoutWidth * sinEsc;
2519 pts[3].y = pts[0].y + strikeoutWidth * cosEsc;
2520 pts[4].x = pts[0].x;
2521 pts[4].y = pts[0].y;
2522 DPtoLP(hdc, pts, 5);
2523 Polygon(hdc, pts, 5);
2524 }
2525
2526 SelectObject(hdc, hpen);
2527 hbrush = SelectObject(hdc, hbrush);
2528 DeleteObject(hbrush);
2529 }
2530
2531 return ret;
2532 }
2533
2534
2535 /***********************************************************************
2536 * TextOutA (GDI32.@)
2537 */
2538 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, LPCSTR str, INT count )
2539 {
2540 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
2541 }
2542
2543
2544 /***********************************************************************
2545 * TextOutW (GDI32.@)
2546 */
2547 BOOL WINAPI TextOutW(HDC hdc, INT x, INT y, LPCWSTR str, INT count)
2548 {
2549 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
2550 }
2551
2552
2553 /***********************************************************************
2554 * PolyTextOutA (GDI32.@)
2555 *
2556 * See PolyTextOutW.
2557 */
2558 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pptxt, INT cStrings )
2559 {
2560 for (; cStrings>0; cStrings--, pptxt++)
2561 if (!ExtTextOutA( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2562 return FALSE;
2563 return TRUE;
2564 }
2565
2566
2567
2568 /***********************************************************************
2569 * PolyTextOutW (GDI32.@)
2570 *
2571 * Draw several Strings
2572 *
2573 * RETURNS
2574 * TRUE: Success.
2575 * FALSE: Failure.
2576 */
2577 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pptxt, INT cStrings )
2578 {
2579 for (; cStrings>0; cStrings--, pptxt++)
2580 if (!ExtTextOutW( hdc, pptxt->x, pptxt->y, pptxt->uiFlags, &pptxt->rcl, pptxt->lpstr, pptxt->n, pptxt->pdx ))
2581 return FALSE;
2582 return TRUE;
2583 }
2584
2585
2586 /***********************************************************************
2587 * SetMapperFlags (GDI32.@)
2588 */
2589 DWORD WINAPI SetMapperFlags( HDC hdc, DWORD flags )
2590 {
2591 DC *dc = get_dc_ptr( hdc );
2592 DWORD ret = GDI_ERROR;
2593
2594 if (dc)
2595 {
2596 PHYSDEV physdev = GET_DC_PHYSDEV( dc, pSetMapperFlags );
2597 flags = physdev->funcs->pSetMapperFlags( physdev, flags );
2598 if (flags != GDI_ERROR)
2599 {
2600 ret = dc->mapperFlags;
2601 dc->mapperFlags = flags;
2602 }
2603 release_dc_ptr( dc );
2604 }
2605 return ret;
2606 }
2607
2608 /***********************************************************************
2609 * GetAspectRatioFilterEx (GDI32.@)
2610 */
2611 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, LPSIZE pAspectRatio )
2612 {
2613 FIXME("(%p, %p): -- Empty Stub !\n", hdc, pAspectRatio);
2614 return FALSE;
2615 }
2616
2617
2618 /***********************************************************************
2619 * GetCharABCWidthsA (GDI32.@)
2620 *
2621 * See GetCharABCWidthsW.
2622 */
2623 BOOL WINAPI GetCharABCWidthsA(HDC hdc, UINT firstChar, UINT lastChar,
2624 LPABC abc )
2625 {
2626 INT i, wlen;
2627 LPSTR str;
2628 LPWSTR wstr;
2629 BOOL ret = TRUE;
2630
2631 str = FONT_GetCharsByRangeA(hdc, firstChar, lastChar, &i);
2632 if (str == NULL)
2633 return FALSE;
2634
2635 wstr = FONT_mbtowc(hdc, str, i, &wlen, NULL);
2636 if (wstr == NULL)
2637 {
2638 HeapFree(GetProcessHeap(), 0, str);
2639 return FALSE;
2640 }
2641
2642 for(i = 0; i < wlen; i++)
2643 {
2644 if(!GetCharABCWidthsW(hdc, wstr[i], wstr[i], abc))
2645 {
2646 ret = FALSE;
2647 break;
2648 }
2649 abc++;
2650 }
2651
2652 HeapFree(GetProcessHeap(), 0, str);
2653 HeapFree(GetProcessHeap(), 0, wstr);
2654
2655 return ret;
2656 }
2657
2658
2659 /******************************************************************************
2660 * GetCharABCWidthsW [GDI32.@]
2661 *
2662 * Retrieves widths of characters in range.
2663 *
2664 * PARAMS
2665 * hdc [I] Handle of device context
2666 * firstChar [I] First character in range to query
2667 * lastChar [I] Last character in range to query
2668 * abc [O] Address of character-width structure
2669 *
2670 * NOTES
2671 * Only works with TrueType fonts
2672 *
2673 * RETURNS
2674 * Success: TRUE
2675 * Failure: FALSE
2676 */
2677 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT firstChar, UINT lastChar,
2678 LPABC abc )
2679 {
2680 DC *dc = get_dc_ptr(hdc);
2681 PHYSDEV dev;
2682 unsigned int i;
2683 BOOL ret;
2684 TEXTMETRICW tm;
2685
2686 if (!dc) return FALSE;
2687
2688 if (!abc)
2689 {
2690 release_dc_ptr( dc );
2691 return FALSE;
2692 }
2693
2694 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-TrueType fonts */
2695 dev = GET_DC_PHYSDEV( dc, pGetTextMetrics );
2696 if (!dev->funcs->pGetTextMetrics( dev, &tm ) || !(tm.tmPitchAndFamily & TMPF_TRUETYPE))
2697 {
2698 release_dc_ptr( dc );
2699 return FALSE;
2700 }
2701
2702 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
2703 ret = dev->funcs->pGetCharABCWidths( dev, firstChar, lastChar, abc );
2704 if (ret)
2705 {
2706 /* convert device units to logical */
2707 for( i = firstChar; i <= lastChar; i++, abc++ ) {
2708 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2709 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2710 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2711 }
2712 }
2713
2714 release_dc_ptr( dc );
2715 return ret;
2716 }
2717
2718
2719 /******************************************************************************
2720 * GetCharABCWidthsI [GDI32.@]
2721 *
2722 * Retrieves widths of characters in range.
2723 *
2724 * PARAMS
2725 * hdc [I] Handle of device context
2726 * firstChar [I] First glyphs in range to query
2727 * count [I] Last glyphs in range to query
2728 * pgi [i] Array of glyphs to query
2729 * abc [O] Address of character-width structure
2730 *
2731 * NOTES
2732 * Only works with TrueType fonts
2733 *
2734 * RETURNS
2735 * Success: TRUE
2736 * Failure: FALSE
2737 */
2738 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT firstChar, UINT count,
2739 LPWORD pgi, LPABC abc)
2740 {
2741 DC *dc = get_dc_ptr(hdc);
2742 PHYSDEV dev;
2743 unsigned int i;
2744 BOOL ret;
2745
2746 if (!dc) return FALSE;
2747
2748 if (!abc)
2749 {
2750 release_dc_ptr( dc );
2751 return FALSE;
2752 }
2753
2754 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidthsI );
2755 ret = dev->funcs->pGetCharABCWidthsI( dev, firstChar, count, pgi, abc );
2756 if (ret)
2757 {
2758 /* convert device units to logical */
2759 for( i = 0; i < count; i++, abc++ ) {
2760 abc->abcA = INTERNAL_XDSTOWS(dc, abc->abcA);
2761 abc->abcB = INTERNAL_XDSTOWS(dc, abc->abcB);
2762 abc->abcC = INTERNAL_XDSTOWS(dc, abc->abcC);
2763 }
2764 }
2765
2766 release_dc_ptr( dc );
2767 return ret;
2768 }
2769
2770
2771 /***********************************************************************
2772 * GetGlyphOutlineA (GDI32.@)
2773 */
2774 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT uChar, UINT fuFormat,
2775 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2776 LPVOID lpBuffer, const MAT2 *lpmat2 )
2777 {
2778 if (!lpmat2) return GDI_ERROR;
2779
2780 if(!(fuFormat & GGO_GLYPH_INDEX)) {
2781 UINT cp;
2782 int len;
2783 char mbchs[2];
2784
2785 cp = GdiGetCodePage(hdc);
2786 if (IsDBCSLeadByteEx(cp, uChar >> 8)) {
2787 len = 2;
2788 mbchs[0] = (uChar & 0xff00) >> 8;
2789 mbchs[1] = (uChar & 0xff);
2790 } else {
2791 len = 1;
2792 mbchs[0] = (uChar & 0xff);
2793 }
2794 uChar = 0;
2795 MultiByteToWideChar(cp, 0, mbchs, len, (LPWSTR)&uChar, 1);
2796 }
2797
2798 return GetGlyphOutlineW(hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer,
2799 lpmat2);
2800 }
2801
2802 /***********************************************************************
2803 * GetGlyphOutlineW (GDI32.@)
2804 */
2805 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT uChar, UINT fuFormat,
2806 LPGLYPHMETRICS lpgm, DWORD cbBuffer,
2807 LPVOID lpBuffer, const MAT2 *lpmat2 )
2808 {
2809 DC *dc;
2810 DWORD ret;
2811 PHYSDEV dev;
2812
2813 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2814 hdc, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2815
2816 if (!lpmat2) return GDI_ERROR;
2817
2818 dc = get_dc_ptr(hdc);
2819 if(!dc) return GDI_ERROR;
2820
2821 dev = GET_DC_PHYSDEV( dc, pGetGlyphOutline );
2822 ret = dev->funcs->pGetGlyphOutline( dev, uChar, fuFormat, lpgm, cbBuffer, lpBuffer, lpmat2 );
2823 release_dc_ptr( dc );
2824 return ret;
2825 }
2826
2827
2828 /***********************************************************************
2829 * CreateScalableFontResourceA (GDI32.@)
2830 */
2831 BOOL WINAPI CreateScalableFontResourceA( DWORD fHidden,
2832 LPCSTR lpszResourceFile,
2833 LPCSTR lpszFontFile,
2834 LPCSTR lpszCurrentPath )
2835 {
2836 LPWSTR lpszResourceFileW = NULL;
2837 LPWSTR lpszFontFileW = NULL;
2838 LPWSTR lpszCurrentPathW = NULL;
2839 int len;
2840 BOOL ret;
2841
2842 if (lpszResourceFile)
2843 {
2844 len = MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, NULL, 0);
2845 lpszResourceFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2846 MultiByteToWideChar(CP_ACP, 0, lpszResourceFile, -1, lpszResourceFileW, len);
2847 }
2848
2849 if (lpszFontFile)
2850 {
2851 len = MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, NULL, 0);
2852 lpszFontFileW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2853 MultiByteToWideChar(CP_ACP, 0, lpszFontFile, -1, lpszFontFileW, len);
2854 }
2855
2856 if (lpszCurrentPath)
2857 {
2858 len = MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, NULL, 0);
2859 lpszCurrentPathW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
2860 MultiByteToWideChar(CP_ACP, 0, lpszCurrentPath, -1, lpszCurrentPathW, len);
2861 }
2862
2863 ret = CreateScalableFontResourceW(fHidden, lpszResourceFileW,
2864 lpszFontFileW, lpszCurrentPathW);
2865
2866 HeapFree(GetProcessHeap(), 0, lpszResourceFileW);
2867 HeapFree(GetProcessHeap(), 0, lpszFontFileW);
2868 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW);
2869
2870 return ret;
2871 }
2872
2873 /***********************************************************************
2874 * CreateScalableFontResourceW (GDI32.@)
2875 */
2876 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, LPCWSTR resource_file,
2877 LPCWSTR font_file, LPCWSTR font_path )
2878 {
2879 TRACE("(%d, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2880 debugstr_w(font_file), debugstr_w(font_path) );
2881
2882 return WineEngCreateScalableFontResource( hidden, resource_file,
2883 font_file, font_path );
2884 }
2885
2886 /*************************************************************************
2887 * GetKerningPairsA (GDI32.@)
2888 */
2889 DWORD WINAPI GetKerningPairsA( HDC hDC, DWORD cPairs,
2890 LPKERNINGPAIR kern_pairA )
2891 {
2892 UINT cp;
2893 CPINFO cpi;
2894 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
2895 KERNINGPAIR *kern_pairW;
2896
2897 if (!cPairs && kern_pairA)
2898 {
2899 SetLastError(ERROR_INVALID_PARAMETER);
2900 return 0;
2901 }
2902
2903 cp = GdiGetCodePage(hDC);
2904
2905 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2906 * to fail on an invalid character for CP_SYMBOL.
2907 */
2908 cpi.DefaultChar[0] = 0;
2909 if (cp != CP_SYMBOL && !GetCPInfo(cp, &cpi))
2910 {
2911 FIXME("Can't find codepage %u info\n", cp);
2912 return 0;
2913 }
2914
2915 total_kern_pairs = GetKerningPairsW(hDC, 0, NULL);
2916 if (!total_kern_pairs) return 0;
2917
2918 kern_pairW = HeapAlloc(GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW));
2919 GetKerningPairsW(hDC, total_kern_pairs, kern_pairW);
2920
2921 for (i = 0; i < total_kern_pairs; i++)
2922 {
2923 char first, second;
2924
2925 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL))
2926 continue;
2927
2928 if (!WideCharToMultiByte(cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL))
2929 continue;
2930
2931 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
2932 continue;
2933
2934 if (kern_pairA)
2935 {
2936 if (kern_pairs_copied >= cPairs) break;
2937
2938 kern_pairA->wFirst = (BYTE)first;
2939 kern_pairA->wSecond = (BYTE)second;
2940 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
2941 kern_pairA++;
2942 }
2943 kern_pairs_copied++;
2944 }
2945
2946 HeapFree(GetProcessHeap(), 0, kern_pairW);
2947
2948 return kern_pairs_copied;
2949 }
2950
2951 /*************************************************************************
2952 * GetKerningPairsW (GDI32.@)
2953 */
2954 DWORD WINAPI GetKerningPairsW( HDC hDC, DWORD cPairs,
2955 LPKERNINGPAIR lpKerningPairs )
2956 {
2957 DC *dc;
2958 DWORD ret;
2959 PHYSDEV dev;
2960
2961 TRACE("(%p,%d,%p)\n", hDC, cPairs, lpKerningPairs);
2962
2963 if (!cPairs && lpKerningPairs)
2964 {
2965 SetLastError(ERROR_INVALID_PARAMETER);
2966 return 0;
2967 }
2968
2969 dc = get_dc_ptr(hDC);
2970 if (!dc) return 0;
2971
2972 dev = GET_DC_PHYSDEV( dc, pGetKerningPairs );
2973 ret = dev->funcs->pGetKerningPairs( dev, cPairs, lpKerningPairs );
2974 release_dc_ptr( dc );
2975 return ret;
2976 }
2977
2978 /*************************************************************************
2979 * TranslateCharsetInfo [GDI32.@]
2980 *
2981 * Fills a CHARSETINFO structure for a character set, code page, or
2982 * font. This allows making the correspondence between different labels
2983 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2984 * of the same encoding.
2985 *
2986 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2987 * only one codepage should be set in *lpSrc.
2988 *
2989 * RETURNS
2990 * TRUE on success, FALSE on failure.
2991 *
2992 */
2993 BOOL WINAPI TranslateCharsetInfo(
2994 LPDWORD lpSrc, /* [in]
2995 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2996 if flags == TCI_SRCCHARSET: a character set value
2997 if flags == TCI_SRCCODEPAGE: a code page value
2998 */
2999 LPCHARSETINFO lpCs, /* [out] structure to receive charset information */
3000 DWORD flags /* [in] determines interpretation of lpSrc */)
3001 {
3002 int index = 0;
3003 switch (flags) {
3004 case TCI_SRCFONTSIG:
3005 while (index < MAXTCIINDEX && !(*lpSrc>>index & 0x0001)) index++;
3006 break;
3007 case TCI_SRCCODEPAGE:
3008 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciACP) index++;
3009 break;
3010 case TCI_SRCCHARSET:
3011 while (index < MAXTCIINDEX && PtrToUlong(lpSrc) != FONT_tci[index].ciCharset) index++;
3012 break;
3013 default:
3014 return FALSE;
3015 }
3016 if (index >= MAXTCIINDEX || FONT_tci[index].ciCharset == DEFAULT_CHARSET) return FALSE;
3017 *lpCs = FONT_tci[index];
3018 return TRUE;
3019 }
3020
3021 /*************************************************************************
3022 * GetFontLanguageInfo (GDI32.@)
3023 */
3024 DWORD WINAPI GetFontLanguageInfo(HDC hdc)
3025 {
3026 FONTSIGNATURE fontsig;
3027 static const DWORD GCP_DBCS_MASK=0x003F0000,
3028 GCP_DIACRITIC_MASK=0x00000000,
3029 FLI_GLYPHS_MASK=0x00000000,
3030 GCP_GLYPHSHAPE_MASK=0x00000040,
3031 GCP_KASHIDA_MASK=0x00000000,
3032 GCP_LIGATE_MASK=0x00000000,
3033 GCP_USEKERNING_MASK=0x00000000,
3034 GCP_REORDER_MASK=0x00000060;
3035
3036 DWORD result=0;
3037
3038 GetTextCharsetInfo( hdc, &fontsig, 0 );
3039 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3040
3041 if( (fontsig.fsCsb[0]&GCP_DBCS_MASK)!=0 )
3042 result|=GCP_DBCS;
3043
3044 if( (fontsig.fsCsb[0]&GCP_DIACRITIC_MASK)!=0 )
3045 result|=GCP_DIACRITIC;
3046
3047 if( (fontsig.fsCsb[0]&FLI_GLYPHS_MASK)!=0 )
3048 result|=FLI_GLYPHS;
3049
3050 if( (fontsig.fsCsb[0]&GCP_GLYPHSHAPE_MASK)!=0 )
3051 result|=GCP_GLYPHSHAPE;
3052
3053 if( (fontsig.fsCsb[0]&GCP_KASHIDA_MASK)!=0 )
3054 result|=GCP_KASHIDA;
3055
3056 if( (fontsig.fsCsb[0]&GCP_LIGATE_MASK)!=0 )
3057 result|=GCP_LIGATE;
3058
3059 if( (fontsig.fsCsb[0]&GCP_USEKERNING_MASK)!=0 )
3060 result|=GCP_USEKERNING;
3061
3062 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3063 if( GetTextAlign( hdc) & TA_RTLREADING )
3064 if( (fontsig.fsCsb[0]&GCP_REORDER_MASK)!=0 )
3065 result|=GCP_REORDER;
3066
3067 return result;
3068 }
3069
3070
3071 /*************************************************************************
3072 * GetFontData [GDI32.@]
3073 *
3074 * Retrieve data for TrueType font.
3075 *
3076 * RETURNS
3077 *
3078 * success: Number of bytes returned
3079 * failure: GDI_ERROR
3080 *
3081 * NOTES
3082 *
3083 * Calls SetLastError()
3084 *
3085 */
3086 DWORD WINAPI GetFontData(HDC hdc, DWORD table, DWORD offset,
3087 LPVOID buffer, DWORD length)
3088 {
3089 DC *dc = get_dc_ptr(hdc);
3090 PHYSDEV dev;
3091 DWORD ret;
3092
3093 if(!dc) return GDI_ERROR;
3094
3095 dev = GET_DC_PHYSDEV( dc, pGetFontData );
3096 ret = dev->funcs->pGetFontData( dev, table, offset, buffer, length );
3097 release_dc_ptr( dc );
3098 return ret;
3099 }
3100
3101 /*************************************************************************
3102 * GetGlyphIndicesA [GDI32.@]
3103 */
3104 DWORD WINAPI GetGlyphIndicesA(HDC hdc, LPCSTR lpstr, INT count,
3105 LPWORD pgi, DWORD flags)
3106 {
3107 DWORD ret;
3108 WCHAR *lpstrW;
3109 INT countW;
3110
3111 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3112 hdc, debugstr_an(lpstr, count), count, pgi, flags);
3113
3114 lpstrW = FONT_mbtowc(hdc, lpstr, count, &countW, NULL);
3115 ret = GetGlyphIndicesW(hdc, lpstrW, countW, pgi, flags);
3116 HeapFree(GetProcessHeap(), 0, lpstrW);
3117
3118 return ret;
3119 }
3120
3121 /*************************************************************************
3122 * GetGlyphIndicesW [GDI32.@]
3123 */
3124 DWORD WINAPI GetGlyphIndicesW(HDC hdc, LPCWSTR lpstr, INT count,
3125 LPWORD pgi, DWORD flags)
3126 {
3127 DC *dc = get_dc_ptr(hdc);
3128 PHYSDEV dev;
3129 DWORD ret;
3130
3131 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3132 hdc, debugstr_wn(lpstr, count), count, pgi, flags);
3133
3134 if(!dc) return GDI_ERROR;
3135
3136 dev = GET_DC_PHYSDEV( dc, pGetGlyphIndices );
3137 ret = dev->funcs->pGetGlyphIndices( dev, lpstr, count, pgi, flags );
3138 release_dc_ptr( dc );
3139 return ret;
3140 }
3141
3142 /*************************************************************************
3143 * GetCharacterPlacementA [GDI32.@]
3144 *
3145 * See GetCharacterPlacementW.
3146 *
3147 * NOTES:
3148 * the web browser control of ie4 calls this with dwFlags=0
3149 */
3150 DWORD WINAPI
3151 GetCharacterPlacementA(HDC hdc, LPCSTR lpString, INT uCount,
3152 INT nMaxExtent, GCP_RESULTSA *lpResults,
3153 DWORD dwFlags)
3154 {
3155 WCHAR *lpStringW;
3156 INT uCountW;
3157 GCP_RESULTSW resultsW;
3158 DWORD ret;
3159 UINT font_cp;
3160
3161 TRACE("%s, %d, %d, 0x%08x\n",
3162 debugstr_an(lpString, uCount), uCount, nMaxExtent, dwFlags);
3163
3164 /* both structs are equal in size */
3165 memcpy(&resultsW, lpResults, sizeof(resultsW));
3166
3167 lpStringW = FONT_mbtowc(hdc, lpString, uCount, &uCountW, &font_cp);
3168 if(lpResults->lpOutString)
3169 resultsW.lpOutString = HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR)*uCountW);
3170
3171 ret = GetCharacterPlacementW(hdc, lpStringW, uCountW, nMaxExtent, &resultsW, dwFlags);
3172
3173 lpResults->nGlyphs = resultsW.nGlyphs;
3174 lpResults->nMaxFit = resultsW.nMaxFit;
3175
3176 if(lpResults->lpOutString) {
3177 WideCharToMultiByte(font_cp, 0, resultsW.lpOutString, uCountW,
3178 lpResults->lpOutString, uCount, NULL, NULL );
3179 }
3180
3181 HeapFree(GetProcessHeap(), 0, lpStringW);
3182 HeapFree(GetProcessHeap(), 0, resultsW.lpOutString);
3183
3184 return ret;
3185 }
3186
3187 /*************************************************************************
3188 * GetCharacterPlacementW [GDI32.@]
3189 *
3190 * Retrieve information about a string. This includes the width, reordering,
3191 * Glyphing and so on.
3192 *
3193 * RETURNS
3194 *
3195 * The width and height of the string if successful, 0 if failed.
3196 *
3197 * BUGS
3198 *
3199 * All flags except GCP_REORDER are not yet implemented.
3200 * Reordering is not 100% compliant to the Windows BiDi method.
3201 * Caret positioning is not yet implemented for BiDi.
3202 * Classes are not yet implemented.
3203 *
3204 */
3205 DWORD WINAPI
3206 GetCharacterPlacementW(
3207 HDC hdc, /* [in] Device context for which the rendering is to be done */
3208 LPCWSTR lpString, /* [in] The string for which information is to be returned */
3209 INT uCount, /* [in] Number of WORDS in string. */
3210 INT nMaxExtent, /* [in] Maximum extent the string is to take (in HDC logical units) */
3211 GCP_RESULTSW *lpResults,/* [in/out] A pointer to a GCP_RESULTSW struct */
3212 DWORD dwFlags /* [in] Flags specifying how to process the string */
3213 )
3214 {
3215 DWORD ret=0;
3216 SIZE size;
3217 UINT i, nSet;
3218
3219 TRACE("%s, %d, %d, 0x%08x\n",
3220 debugstr_wn(lpString, uCount), uCount, nMaxExtent, dwFlags);
3221
3222 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3223 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3224 lpResults->lStructSize, lpResults->lpOutString, lpResults->lpOrder,
3225 lpResults->lpDx, lpResults->lpCaretPos, lpResults->lpClass,
3226 lpResults->lpGlyphs, lpResults->nGlyphs, lpResults->nMaxFit);
3227
3228 if(dwFlags&(~GCP_REORDER)) FIXME("flags 0x%08x ignored\n", dwFlags);
3229 if(lpResults->lpClass) FIXME("classes not implemented\n");
3230 if (lpResults->lpCaretPos && (dwFlags & GCP_REORDER))
3231 FIXME("Caret positions for complex scripts not implemented\n");
3232
3233 nSet = (UINT)uCount;
3234 if(nSet > lpResults->nGlyphs)
3235 nSet = lpResults->nGlyphs;
3236
3237 /* return number of initialized fields */
3238 lpResults->nGlyphs = nSet;
3239
3240 if((dwFlags&GCP_REORDER)==0 )
3241 {
3242 /* Treat the case where no special handling was requested in a fastpath way */
3243 /* copy will do if the GCP_REORDER flag is not set */
3244 if(lpResults->lpOutString)
3245 memcpy( lpResults->lpOutString, lpString, nSet * sizeof(WCHAR));
3246
3247 if(lpResults->lpOrder)
3248 {
3249 for(i = 0; i < nSet; i++)
3250 lpResults->lpOrder[i] = i;
3251 }
3252 } else
3253 {
3254 BIDI_Reorder(NULL, lpString, uCount, dwFlags, WINE_GCPW_FORCE_LTR, lpResults->lpOutString,
3255 nSet, lpResults->lpOrder, NULL, NULL );
3256 }
3257
3258 /* FIXME: Will use the placement chars */
3259 if (lpResults->lpDx)
3260 {
3261 int c;
3262 for (i = 0; i < nSet; i++)
3263 {
3264 if (GetCharWidth32W(hdc, lpString[i], lpString[i], &c))
3265 lpResults->lpDx[i]= c;
3266 }
3267 }
3268
3269 if (lpResults->lpCaretPos && !(dwFlags & GCP_REORDER))
3270 {
3271 int pos = 0;
3272
3273 lpResults->lpCaretPos[0] = 0;
3274 for (i = 1; i < nSet; i++)
3275 if (GetTextExtentPoint32W(hdc, &(lpString[i - 1]), 1, &size))
3276 lpResults->lpCaretPos[i] = (pos += size.cx);
3277 }
3278
3279 if(lpResults->lpGlyphs)
3280 GetGlyphIndicesW(hdc, lpString, nSet, lpResults->lpGlyphs, 0);
3281
3282 if (GetTextExtentPoint32W(hdc, lpString, uCount, &size))
3283 ret = MAKELONG(size.cx, size.cy);
3284
3285 return ret;
3286 }
3287
3288 /*************************************************************************
3289 * GetCharABCWidthsFloatA [GDI32.@]
3290 *
3291 * See GetCharABCWidthsFloatW.
3292 */
3293 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3294 {
3295 INT i, wlen;
3296 LPSTR str;
3297 LPWSTR wstr;
3298 BOOL ret = TRUE;
3299
3300 str = FONT_GetCharsByRangeA(hdc, first, last, &i);
3301 if (str == NULL)
3302 return FALSE;
3303
3304 wstr = FONT_mbtowc( hdc, str, i, &wlen, NULL );
3305
3306 for (i = 0; i < wlen; i++)
3307 {
3308 if (!GetCharABCWidthsFloatW( hdc, wstr[i], wstr[i], abcf ))
3309 {
3310 ret = FALSE;
3311 break;
3312 }
3313 abcf++;
3314 }
3315
3316 HeapFree( GetProcessHeap(), 0, str );
3317 HeapFree( GetProcessHeap(), 0, wstr );
3318
3319 return ret;
3320 }
3321
3322 /*************************************************************************
3323 * GetCharABCWidthsFloatW [GDI32.@]
3324 *
3325 * Retrieves widths of a range of characters.
3326 *
3327 * PARAMS
3328 * hdc [I] Handle to device context.
3329 * first [I] First character in range to query.
3330 * last [I] Last character in range to query.
3331 * abcf [O] Array of LPABCFLOAT structures.
3332 *
3333 * RETURNS
3334 * Success: TRUE
3335 * Failure: FALSE
3336 */
3337 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, LPABCFLOAT abcf )
3338 {
3339 UINT i;
3340 ABC *abc;
3341 PHYSDEV dev;
3342 BOOL ret = FALSE;
3343 DC *dc = get_dc_ptr( hdc );
3344
3345 TRACE("%p, %d, %d, %p\n", hdc, first, last, abcf);
3346
3347 if (!dc) return FALSE;
3348
3349 if (!abcf) goto done;
3350 if (!(abc = HeapAlloc( GetProcessHeap(), 0, (last - first + 1) * sizeof(*abc) ))) goto done;
3351
3352 dev = GET_DC_PHYSDEV( dc, pGetCharABCWidths );
3353 ret = dev->funcs->pGetCharABCWidths( dev, first, last, abc );
3354 if (ret)
3355 {
3356 /* convert device units to logical */
3357 for (i = first; i <= last; i++, abcf++)
3358 {
3359 abcf->abcfA = abc[i - first].abcA * dc->xformVport2World.eM11;
3360 abcf->abcfB = abc[i - first].abcB * dc->xformVport2World.eM11;
3361 abcf->abcfC = abc[i - first].abcC * dc->xformVport2World.eM11;
3362 }
3363 }
3364 HeapFree( GetProcessHeap(), 0, abc );
3365
3366 done:
3367 release_dc_ptr( dc );
3368 return ret;
3369 }
3370
3371 /*************************************************************************
3372 * GetCharWidthFloatA [GDI32.@]
3373 */
3374 BOOL WINAPI GetCharWidthFloatA(HDC hdc, UINT iFirstChar,
3375 UINT iLastChar, PFLOAT pxBuffer)
3376 {
3377 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3378 return 0;
3379 }
3380
3381 /*************************************************************************
3382 * GetCharWidthFloatW [GDI32.@]
3383 */
3384 BOOL WINAPI GetCharWidthFloatW(HDC hdc, UINT iFirstChar,
3385 UINT iLastChar, PFLOAT pxBuffer)
3386 {
3387 FIXME("%p, %u, %u, %p: stub!\n", hdc, iFirstChar, iLastChar, pxBuffer);
3388 return 0;
3389 }
3390
3391
3392 /***********************************************************************
3393 * *
3394 * Font Resource API *
3395 * *
3396 ***********************************************************************/
3397
3398 /***********************************************************************
3399 * AddFontResourceA (GDI32.@)
3400 */
3401 INT WINAPI AddFontResourceA( LPCSTR str )
3402 {
3403 return AddFontResourceExA( str, 0, NULL);
3404 }
3405
3406 /***********************************************************************
3407 * AddFontResourceW (GDI32.@)
3408 */
3409 INT WINAPI AddFontResourceW( LPCWSTR str )
3410 {
3411 return AddFontResourceExW(str, 0, NULL);
3412 }
3413
3414
3415 /***********************************************************************
3416 * AddFontResourceExA (GDI32.@)
3417 */
3418 INT WINAPI AddFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3419 {
3420 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3421 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3422 INT ret;
3423
3424 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3425 ret = AddFontResourceExW(strW, fl, pdv);
3426 HeapFree(GetProcessHeap(), 0, strW);
3427 return ret;
3428 }
3429
3430 static BOOL CALLBACK load_enumed_resource(HMODULE hModule, LPCWSTR type, LPWSTR name, LONG_PTR lParam)
3431 {
3432 HRSRC rsrc = FindResourceW(hModule, name, type);
3433 HGLOBAL hMem = LoadResource(hModule, rsrc);
3434 LPVOID *pMem = LockResource(hMem);
3435 int *num_total = (int *)lParam;
3436 DWORD num_in_res;
3437
3438 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type));
3439 if (!AddFontMemResourceEx(pMem, SizeofResource(hModule, rsrc), NULL, &num_in_res))
3440 {
3441 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule, hMem);
3442 return FALSE;
3443 }
3444
3445 *num_total += num_in_res;
3446 return TRUE;
3447 }
3448
3449 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
3450 {
3451 HANDLE file, mapping;
3452 void *ptr;
3453
3454 file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
3455 if (file == INVALID_HANDLE_VALUE) return NULL;
3456
3457 if (!GetFileSizeEx( file, size ) || size->u.HighPart)
3458 {
3459 CloseHandle( file );
3460 return NULL;
3461 }
3462
3463 mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
3464 CloseHandle( file );
3465 if (!mapping) return NULL;
3466
3467 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
3468 CloseHandle( mapping );
3469
3470 return ptr;
3471 }
3472
3473 static WCHAR *get_scalable_filename( const WCHAR *res )
3474 {
3475 LARGE_INTEGER size;
3476 BYTE *ptr = map_file( res, &size );
3477 const IMAGE_DOS_HEADER *dos;
3478 const IMAGE_OS2_HEADER *ne;
3479 WCHAR *name = NULL;
3480 WORD rsrc_off, align, type_id, count;
3481 DWORD res_off, res_len, i;
3482 int len;
3483
3484 if (!ptr) return NULL;
3485
3486 if (size.u.LowPart < sizeof( *dos )) goto fail;
3487 dos = (const IMAGE_DOS_HEADER *)ptr;
3488 if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
3489 if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
3490 ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
3491 rsrc_off = dos->e_lfanew + ne->ne_rsrctab;
3492 if (size.u.LowPart < rsrc_off + 10) goto fail;
3493 align = *(WORD *)(ptr + rsrc_off);
3494 rsrc_off += 2;
3495 type_id = *(WORD *)(ptr + rsrc_off);
3496 while (type_id && type_id != 0x80cc)
3497 {
3498 count = *(WORD *)(ptr + rsrc_off + 2);
3499 rsrc_off += 8 + count * 12;
3500 if (size.u.LowPart < rsrc_off + 8) goto fail;
3501 type_id = *(WORD *)(ptr + rsrc_off);
3502 }
3503 if (!type_id) goto fail;
3504 count = *(WORD *)(ptr + rsrc_off + 2);
3505 if (size.u.LowPart < rsrc_off + 8 + count * 12) goto fail;
3506
3507 res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
3508 res_len = *(WORD *)(ptr + rsrc_off + 10) << align;
3509 if (size.u.LowPart < res_off + res_len) goto fail;
3510
3511 for (i = 0; i < res_len; i++)
3512 if (ptr[ res_off + i ] == 0) break;
3513 if (i == res_len) goto fail;
3514
3515 len = MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, NULL, 0 );
3516 name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
3517 if (name) MultiByteToWideChar( CP_ACP, 0, (char *)ptr + res_off, -1, name, len );
3518
3519 fail:
3520 UnmapViewOfFile( ptr );
3521 return name;
3522 }
3523
3524 /***********************************************************************
3525 * AddFontResourceExW (GDI32.@)
3526 */
3527 INT WINAPI AddFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3528 {
3529 int ret = WineEngAddFontResourceEx(str, fl, pdv);
3530 WCHAR *filename;
3531
3532 if (ret == 0)
3533 {
3534 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3535 HMODULE hModule = LoadLibraryExW(str, NULL, LOAD_LIBRARY_AS_DATAFILE);
3536 if (hModule != NULL)
3537 {
3538 int num_resources = 0;
3539 LPWSTR rt_font = (LPWSTR)((ULONG_PTR)8); /* we don't want to include winuser.h */
3540
3541 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3542 wine_dbgstr_w(str));
3543 if (EnumResourceNamesW(hModule, rt_font, load_enumed_resource, (LONG_PTR)&num_resources))
3544 ret = num_resources;
3545 FreeLibrary(hModule);
3546 }
3547 else if ((filename = get_scalable_filename( str )) != NULL)
3548 {
3549 ret = WineEngAddFontResourceEx( filename, fl, pdv );
3550 HeapFree( GetProcessHeap(), 0, filename );
3551 }
3552 }
3553 return ret;
3554 }
3555
3556 /***********************************************************************
3557 * RemoveFontResourceA (GDI32.@)
3558 */
3559 BOOL WINAPI RemoveFontResourceA( LPCSTR str )
3560 {
3561 return RemoveFontResourceExA(str, 0, 0);
3562 }
3563
3564 /***********************************************************************
3565 * RemoveFontResourceW (GDI32.@)
3566 */
3567 BOOL WINAPI RemoveFontResourceW( LPCWSTR str )
3568 {
3569 return RemoveFontResourceExW(str, 0, 0);
3570 }
3571
3572 /***********************************************************************
3573 * AddFontMemResourceEx (GDI32.@)
3574 */
3575 HANDLE WINAPI AddFontMemResourceEx( PVOID pbFont, DWORD cbFont, PVOID pdv, DWORD *pcFonts)
3576 {
3577 HANDLE ret;
3578 DWORD num_fonts;
3579
3580 if (!pbFont || !cbFont || !pcFonts)
3581 {
3582 SetLastError(ERROR_INVALID_PARAMETER);
3583 return NULL;
3584 }
3585
3586 ret = WineEngAddFontMemResourceEx(pbFont, cbFont, pdv, &num_fonts);
3587 if (ret)
3588 {
3589 __TRY
3590 {
3591 *pcFonts = num_fonts;
3592 }
3593 __EXCEPT_PAGE_FAULT
3594 {
3595 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts);
3596 RemoveFontMemResourceEx(ret);
3597 ret = 0;
3598 }
3599 __ENDTRY
3600 }
3601 return ret;
3602 }
3603
3604 /***********************************************************************
3605 * RemoveFontMemResourceEx (GDI32.@)
3606 */
3607 BOOL WINAPI RemoveFontMemResourceEx( HANDLE fh )
3608 {
3609 FIXME("(%p) stub\n", fh);
3610 return TRUE;
3611 }
3612
3613 /***********************************************************************
3614 * RemoveFontResourceExA (GDI32.@)
3615 */
3616 BOOL WINAPI RemoveFontResourceExA( LPCSTR str, DWORD fl, PVOID pdv )
3617 {
3618 DWORD len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
3619 LPWSTR strW = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
3620 INT ret;
3621
3622 MultiByteToWideChar(CP_ACP, 0, str, -1, strW, len);
3623 ret = RemoveFontResourceExW(strW, fl, pdv);
3624 HeapFree(GetProcessHeap(), 0, strW);
3625 return ret;
3626 }
3627
3628 /***********************************************************************
3629 * RemoveFontResourceExW (GDI32.@)
3630 */
3631 BOOL WINAPI RemoveFontResourceExW( LPCWSTR str, DWORD fl, PVOID pdv )
3632 {
3633 return WineEngRemoveFontResourceEx(str, fl, pdv);
3634 }
3635
3636 /***********************************************************************
3637 * GetTextCharset (GDI32.@)
3638 */
3639 UINT WINAPI GetTextCharset(HDC hdc)
3640 {
3641 /* MSDN docs say this is equivalent */
3642 return GetTextCharsetInfo(hdc, NULL, 0);
3643 }
3644
3645 /***********************************************************************
3646 * GetTextCharsetInfo (GDI32.@)
3647 */
3648 UINT WINAPI GetTextCharsetInfo(HDC hdc, LPFONTSIGNATURE fs, DWORD flags)
3649 {
3650 UINT ret = DEFAULT_CHARSET;
3651 DC *dc = get_dc_ptr(hdc);
3652 PHYSDEV dev;
3653
3654 if (dc)
3655 {
3656 dev = GET_DC_PHYSDEV( dc, pGetTextCharsetInfo );
3657 ret = dev->funcs->pGetTextCharsetInfo( dev, fs, flags );
3658 release_dc_ptr( dc );
3659 }
3660
3661 if (ret == DEFAULT_CHARSET && fs)
3662 memset(fs, 0, sizeof(FONTSIGNATURE));
3663 return ret;
3664 }
3665
3666 /***********************************************************************
3667 * GdiGetCharDimensions (GDI32.@)
3668 *
3669 * Gets the average width of the characters in the English alphabet.
3670 *
3671 * PARAMS
3672 * hdc [I] Handle to the device context to measure on.
3673 * lptm [O] Pointer to memory to store the text metrics into.
3674 * height [O] On exit, the maximum height of characters in the English alphabet.
3675 *
3676 * RETURNS
3677 * The average width of characters in the English alphabet.
3678 *
3679 * NOTES
3680 * This function is used by the dialog manager to get the size of a dialog
3681 * unit. It should also be used by other pieces of code that need to know
3682 * the size of a dialog unit in logical units without having access to the
3683 * window handle of the dialog.
3684 * Windows caches the font metrics from this function, but we don't and
3685 * there doesn't appear to be an immediate advantage to do so.
3686 *
3687 * SEE ALSO
3688 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3689 */
3690 LONG WINAPI GdiGetCharDimensions(HDC hdc, LPTEXTMETRICW lptm, LONG *height)
3691 {
3692 SIZE sz;
3693 static const WCHAR alphabet[] = {
3694 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3695 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3696 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3697
3698 if(lptm && !GetTextMetricsW(hdc, lptm)) return 0;
3699
3700 if(!GetTextExtentPointW(hdc, alphabet, 52, &sz)) return 0;
3701
3702 if (height) *height = sz.cy;
3703 return (sz.cx / 26 + 1) / 2;
3704 }
3705
3706 BOOL WINAPI EnableEUDC(BOOL fEnableEUDC)
3707 {
3708 FIXME("(%d): stub\n", fEnableEUDC);
3709 return FALSE;
3710 }
3711
3712 /***********************************************************************
3713 * GetCharWidthI (GDI32.@)
3714 *
3715 * Retrieve widths of characters.
3716 *
3717 * PARAMS
3718 * hdc [I] Handle to a device context.
3719 * first [I] First glyph in range to query.
3720 * count [I] Number of glyph indices to query.
3721 * glyphs [I] Array of glyphs to query.
3722 * buffer [O] Buffer to receive character widths.
3723 *
3724 * NOTES
3725 * Only works with TrueType fonts.
3726 *
3727 * RETURNS
3728 * Success: TRUE
3729 * Failure: FALSE
3730 */
3731 BOOL WINAPI GetCharWidthI(HDC hdc, UINT first, UINT count, LPWORD glyphs, LPINT buffer)
3732 {
3733 ABC *abc;
3734 unsigned int i;
3735
3736 TRACE("(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer);
3737
3738 if (!(abc = HeapAlloc(GetProcessHeap(), 0, count * sizeof(ABC))))
3739 return FALSE;
3740
3741 if (!GetCharABCWidthsI(hdc, first, count, glyphs, abc))
3742 {
3743 HeapFree(GetProcessHeap(), 0, abc);
3744 return FALSE;
3745 }
3746
3747 for (i = 0; i < count; i++)
3748 buffer[i] = abc->abcA + abc->abcB + abc->abcC;
3749
3750 HeapFree(GetProcessHeap(), 0, abc);
3751 return TRUE;
3752 }
3753
3754 /***********************************************************************
3755 * GetFontUnicodeRanges (GDI32.@)
3756 *
3757 * Retrieve a list of supported Unicode characters in a font.
3758 *
3759 * PARAMS
3760 * hdc [I] Handle to a device context.
3761 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3762 *
3763 * RETURNS
3764 * Success: Number of bytes written to the buffer pointed to by lpgs.
3765 * Failure: 0
3766 *
3767 */
3768 DWORD WINAPI GetFontUnicodeRanges(HDC hdc, LPGLYPHSET lpgs)
3769 {
3770 DWORD ret;
3771 PHYSDEV dev;
3772 DC *dc = get_dc_ptr(hdc);
3773
3774 TRACE("(%p, %p)\n", hdc, lpgs);
3775
3776 if (!dc) return 0;
3777
3778 dev = GET_DC_PHYSDEV( dc, pGetFontUnicodeRanges );
3779 ret = dev->funcs->pGetFontUnicodeRanges( dev, lpgs );
3780 release_dc_ptr(dc);
3781 return ret;
3782 }
3783
3784
3785 /*************************************************************
3786 * FontIsLinked (GDI32.@)
3787 */
3788 BOOL WINAPI FontIsLinked(HDC hdc)
3789 {
3790 DC *dc = get_dc_ptr(hdc);
3791 PHYSDEV dev;
3792 BOOL ret;
3793
3794 if (!dc) return FALSE;
3795 dev = GET_DC_PHYSDEV( dc, pFontIsLinked );
3796 ret = dev->funcs->pFontIsLinked( dev );
3797 release_dc_ptr(dc);
3798 TRACE("returning %d\n", ret);
3799 return ret;
3800 }
3801
3802 /*************************************************************
3803 * GdiRealizationInfo (GDI32.@)
3804 *
3805 * Returns a structure that contains some font information.
3806 */
3807 BOOL WINAPI GdiRealizationInfo(HDC hdc, realization_info_t *info)
3808 {
3809 DC *dc = get_dc_ptr(hdc);
3810 PHYSDEV dev;
3811 BOOL ret;
3812
3813 if (!dc) return FALSE;
3814 dev = GET_DC_PHYSDEV( dc, pGdiRealizationInfo );
3815 ret = dev->funcs->pGdiRealizationInfo( dev, info );
3816 release_dc_ptr(dc);
3817 return ret;
3818 }
3819
This page was automatically generated by the
LXR engine.
Visit the LXR main site for more
information.