include: Add some new ProcThreadAttribute definitions.
[wine.git] / dlls / gdi32 / text.c
blobb0134e529f5ad3e2d9e0c15c330009313fe1e280
1 /*
2 * GDI text handling
4 * Copyright 1993 Alexandre Julliard
5 * Copyright 1997 Alex Korobka
6 * Copyright 2002,2003 Shachar Shemesh
7 * Copyright 2007 Maarten Lankhorst
8 * Copyright 2010 CodeWeavers, Aric Stewart
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 * Code derived from the modified reference implementation
25 * that was found in revision 17 of http://unicode.org/reports/tr9/
26 * "Unicode Standard Annex #9: THE BIDIRECTIONAL ALGORITHM"
28 * -- Copyright (C) 1999-2005, ASMUS, Inc.
30 * Permission is hereby granted, free of charge, to any person obtaining a
31 * copy of the Unicode data files and any associated documentation (the
32 * "Data Files") or Unicode software and any associated documentation (the
33 * "Software") to deal in the Data Files or Software without restriction,
34 * including without limitation the rights to use, copy, modify, merge,
35 * publish, distribute, and/or sell copies of the Data Files or Software,
36 * and to permit persons to whom the Data Files or Software are furnished
37 * to do so, provided that (a) the above copyright notice(s) and this
38 * permission notice appear with all copies of the Data Files or Software,
39 * (b) both the above copyright notice(s) and this permission notice appear
40 * in associated documentation, and (c) there is clear notice in each
41 * modified Data File or in the Software as well as in the documentation
42 * associated with the Data File(s) or Software that the data or software
43 * has been modified.
46 #include <stdarg.h>
47 #include <limits.h>
48 #include <assert.h>
50 #include "windef.h"
51 #include "winbase.h"
52 #include "wingdi.h"
53 #include "winnls.h"
54 #include "usp10.h"
55 #include "wine/debug.h"
56 #include "gdi_private.h"
57 #include "resource.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(bidi);
61 /* HELPER FUNCTIONS AND DECLARATIONS */
63 /* Wine_GCPW Flags */
64 /* Directionality -
65 * LOOSE means taking the directionality of the first strong character, if there is found one.
66 * FORCE means the paragraph direction is forced. (RLE/LRE)
68 #define WINE_GCPW_FORCE_LTR 0
69 #define WINE_GCPW_FORCE_RTL 1
70 #define WINE_GCPW_LOOSE_LTR 2
71 #define WINE_GCPW_LOOSE_RTL 3
72 #define WINE_GCPW_DIR_MASK 3
73 #define WINE_GCPW_LOOSE_MASK 2
75 #define odd(x) ((x) & 1)
77 extern const unsigned short bidi_direction_table[] DECLSPEC_HIDDEN;
79 /*------------------------------------------------------------------------
80 Bidirectional Character Types
82 as defined by the Unicode Bidirectional Algorithm Table 3-7.
84 Note:
86 The list of bidirectional character types here is not grouped the
87 same way as the table 3-7, since the numeric values for the types
88 are chosen to keep the state and action tables compact.
89 ------------------------------------------------------------------------*/
90 enum directions
92 /* input types */
93 /* ON MUST be zero, code relies on ON = N = 0 */
94 ON = 0, /* Other Neutral */
95 L, /* Left Letter */
96 R, /* Right Letter */
97 AN, /* Arabic Number */
98 EN, /* European Number */
99 AL, /* Arabic Letter (Right-to-left) */
100 NSM, /* Non-spacing Mark */
101 CS, /* Common Separator */
102 ES, /* European Separator */
103 ET, /* European Terminator (post/prefix e.g. $ and %) */
105 /* resolved types */
106 BN, /* Boundary neutral (type of RLE etc after explicit levels) */
108 /* input types, */
109 S, /* Segment Separator (TAB) // used only in L1 */
110 WS, /* White space // used only in L1 */
111 B, /* Paragraph Separator (aka as PS) */
113 /* types for explicit controls */
114 RLO, /* these are used only in X1-X9 */
115 RLE,
116 LRO,
117 LRE,
118 PDF,
120 LRI, /* Isolate formatting characters new with 6.3 */
121 RLI,
122 FSI,
123 PDI,
125 /* resolved types, also resolved directions */
126 NI = ON, /* alias, where ON, WS and S are treated the same */
129 /* HELPER FUNCTIONS */
131 static inline unsigned short get_table_entry_32( const unsigned short *table, UINT ch )
133 return table[table[table[table[ch >> 12] + ((ch >> 8) & 0x0f)] + ((ch >> 4) & 0x0f)] + (ch & 0xf)];
136 /* Convert the libwine information to the direction enum */
137 static void classify(LPCWSTR lpString, WORD *chartype, DWORD uCount)
139 unsigned i;
141 for (i = 0; i < uCount; ++i)
142 chartype[i] = get_table_entry_32( bidi_direction_table, lpString[i] );
145 /* Set a run of cval values at locations all prior to, but not including */
146 /* iStart, to the new value nval. */
147 static void SetDeferredRun(BYTE *pval, int cval, int iStart, int nval)
149 int i = iStart - 1;
150 for (; i >= iStart - cval; i--)
152 pval[i] = nval;
156 /* THE PARAGRAPH LEVEL */
158 /*------------------------------------------------------------------------
159 Function: resolveParagraphs
161 Resolves the input strings into blocks over which the algorithm
162 is then applied.
164 Implements Rule P1 of the Unicode Bidi Algorithm
166 Input: Text string
167 Character count
169 Output: revised character count
171 Note: This is a very simplistic function. In effect it restricts
172 the action of the algorithm to the first paragraph in the input
173 where a paragraph ends at the end of the first block separator
174 or at the end of the input text.
176 ------------------------------------------------------------------------*/
178 static int resolveParagraphs(WORD *types, int cch)
180 /* skip characters not of type B */
181 int ich = 0;
182 for(; ich < cch && types[ich] != B; ich++);
183 /* stop after first B, make it a BN for use in the next steps */
184 if (ich < cch && types[ich] == B)
185 types[ich++] = BN;
186 return ich;
189 /* REORDER */
190 /*------------------------------------------------------------------------
191 Function: resolveLines
193 Breaks a paragraph into lines
195 Input: Array of line break flags
196 Character count
197 In/Out: Array of characters
199 Returns the count of characters on the first line
201 Note: This function only breaks lines at hard line breaks. Other
202 line breaks can be passed in. If pbrk[n] is TRUE, then a break
203 occurs after the character in pszInput[n]. Breaks before the first
204 character are not allowed.
205 ------------------------------------------------------------------------*/
206 static int resolveLines(LPCWSTR pszInput, const BOOL * pbrk, int cch)
208 /* skip characters not of type LS */
209 int ich = 0;
210 for(; ich < cch; ich++)
212 if (pszInput[ich] == (WCHAR)'\n' || (pbrk && pbrk[ich]))
214 ich++;
215 break;
219 return ich;
222 /*------------------------------------------------------------------------
223 Function: resolveWhiteSpace
225 Resolves levels for WS and S
226 Implements rule L1 of the Unicode bidi Algorithm.
228 Input: Base embedding level
229 Character count
230 Array of direction classes (for one line of text)
232 In/Out: Array of embedding levels (for one line of text)
234 Note: this should be applied a line at a time. The default driver
235 code supplied in this file assumes a single line of text; for
236 a real implementation, cch and the initial pointer values
237 would have to be adjusted.
238 ------------------------------------------------------------------------*/
239 static void resolveWhitespace(int baselevel, const WORD *pcls, BYTE *plevel, int cch)
241 int cchrun = 0;
242 BYTE oldlevel = baselevel;
244 int ich = 0;
245 for (; ich < cch; ich++)
247 switch(pcls[ich])
249 default:
250 cchrun = 0; /* any other character breaks the run */
251 break;
252 case WS:
253 cchrun++;
254 break;
256 case RLE:
257 case LRE:
258 case LRO:
259 case RLO:
260 case PDF:
261 case LRI:
262 case RLI:
263 case FSI:
264 case PDI:
265 case BN:
266 plevel[ich] = oldlevel;
267 cchrun++;
268 break;
270 case S:
271 case B:
272 /* reset levels for WS before eot */
273 SetDeferredRun(plevel, cchrun, ich, baselevel);
274 cchrun = 0;
275 plevel[ich] = baselevel;
276 break;
278 oldlevel = plevel[ich];
280 /* reset level before eot */
281 SetDeferredRun(plevel, cchrun, ich, baselevel);
284 /*------------------------------------------------------------------------
285 Function: BidiLines
287 Implements the Line-by-Line phases of the Unicode Bidi Algorithm
289 Input: Count of characters
290 Array of character directions
292 Inp/Out: Input text
293 Array of levels
295 ------------------------------------------------------------------------*/
296 static void BidiLines(int baselevel, LPWSTR pszOutLine, LPCWSTR pszLine, const WORD * pclsLine,
297 BYTE * plevelLine, int cchPara, const BOOL * pbrk)
299 int cchLine = 0;
300 int done = 0;
301 int *run;
303 run = HeapAlloc(GetProcessHeap(), 0, cchPara * sizeof(int));
304 if (!run)
306 WARN("Out of memory\n");
307 return;
312 /* break lines at LS */
313 cchLine = resolveLines(pszLine, pbrk, cchPara);
315 /* resolve whitespace */
316 resolveWhitespace(baselevel, pclsLine, plevelLine, cchLine);
318 if (pszOutLine)
320 int i;
321 /* reorder each line in place */
322 ScriptLayout(cchLine, plevelLine, NULL, run);
323 for (i = 0; i < cchLine; i++)
324 pszOutLine[done+run[i]] = pszLine[i];
327 pszLine += cchLine;
328 plevelLine += cchLine;
329 pbrk += pbrk ? cchLine : 0;
330 pclsLine += cchLine;
331 cchPara -= cchLine;
332 done += cchLine;
334 } while (cchPara);
336 HeapFree(GetProcessHeap(), 0, run);
339 /*************************************************************
340 * BIDI_Reorder
342 * Returns TRUE if reordering was required and done.
344 static BOOL BIDI_Reorder( HDC hDC, /* [in] Display DC */
345 LPCWSTR lpString, /* [in] The string for which information is to be returned */
346 INT uCount, /* [in] Number of WCHARs in string. */
347 DWORD dwFlags, /* [in] GetCharacterPlacement compatible flags */
348 DWORD dwWineGCP_Flags, /* [in] Wine internal flags - Force paragraph direction */
349 LPWSTR lpOutString, /* [out] Reordered string */
350 INT uCountOut, /* [in] Size of output buffer */
351 UINT *lpOrder, /* [out] Logical -> Visual order map */
352 WORD **lpGlyphs, /* [out] reordered, mirrored, shaped glyphs to display */
353 INT *cGlyphs ) /* [out] number of glyphs generated */
355 WORD *chartype = NULL;
356 BYTE *levels = NULL;
357 INT i, done;
358 unsigned glyph_i;
359 BOOL is_complex, ret = FALSE;
361 int maxItems;
362 int nItems;
363 SCRIPT_CONTROL Control;
364 SCRIPT_STATE State;
365 SCRIPT_ITEM *pItems = NULL;
366 HRESULT res;
367 SCRIPT_CACHE psc = NULL;
368 WORD *run_glyphs = NULL;
369 WORD *pwLogClust = NULL;
370 SCRIPT_VISATTR *psva = NULL;
371 DWORD cMaxGlyphs = 0;
372 BOOL doGlyphs = TRUE;
374 TRACE("%s, %d, 0x%08lx lpOutString=%p, lpOrder=%p\n",
375 debugstr_wn(lpString, uCount), uCount, dwFlags,
376 lpOutString, lpOrder);
378 memset(&Control, 0, sizeof(Control));
379 memset(&State, 0, sizeof(State));
380 if (lpGlyphs)
381 *lpGlyphs = NULL;
383 if (!(dwFlags & GCP_REORDER))
385 FIXME("Asked to reorder without reorder flag set\n");
386 return FALSE;
389 if (lpOutString && uCountOut < uCount)
391 FIXME("lpOutString too small\n");
392 return FALSE;
395 chartype = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(WORD));
396 if (!chartype)
398 WARN("Out of memory\n");
399 return FALSE;
402 if (lpOutString)
403 memcpy(lpOutString, lpString, uCount * sizeof(WCHAR));
405 is_complex = FALSE;
406 for (i = 0; i < uCount && !is_complex; i++)
408 if ((lpString[i] >= 0x900 && lpString[i] <= 0xfff) ||
409 (lpString[i] >= 0x1cd0 && lpString[i] <= 0x1cff) ||
410 (lpString[i] >= 0xa840 && lpString[i] <= 0xa8ff))
411 is_complex = TRUE;
414 /* Verify reordering will be required */
415 if ((WINE_GCPW_FORCE_RTL == (dwWineGCP_Flags&WINE_GCPW_DIR_MASK)) ||
416 ((dwWineGCP_Flags&WINE_GCPW_DIR_MASK) == WINE_GCPW_LOOSE_RTL))
417 State.uBidiLevel = 1;
418 else if (!is_complex)
420 done = 1;
421 classify(lpString, chartype, uCount);
422 for (i = 0; i < uCount; i++)
423 switch (chartype[i])
425 case R:
426 case AL:
427 case RLE:
428 case RLO:
429 done = 0;
430 break;
432 if (done)
434 HeapFree(GetProcessHeap(), 0, chartype);
435 if (lpOrder)
437 for (i = 0; i < uCount; i++)
438 lpOrder[i] = i;
440 return TRUE;
444 levels = HeapAlloc(GetProcessHeap(), 0, uCount * sizeof(BYTE));
445 if (!levels)
447 WARN("Out of memory\n");
448 goto cleanup;
451 maxItems = 5;
452 pItems = HeapAlloc(GetProcessHeap(),0, maxItems * sizeof(SCRIPT_ITEM));
453 if (!pItems)
455 WARN("Out of memory\n");
456 goto cleanup;
459 if (lpGlyphs)
461 cMaxGlyphs = 1.5 * uCount + 16;
462 run_glyphs = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * cMaxGlyphs);
463 if (!run_glyphs)
465 WARN("Out of memory\n");
466 goto cleanup;
468 pwLogClust = HeapAlloc(GetProcessHeap(),0,sizeof(WORD) * uCount);
469 if (!pwLogClust)
471 WARN("Out of memory\n");
472 goto cleanup;
474 psva = HeapAlloc(GetProcessHeap(),0,sizeof(SCRIPT_VISATTR) * cMaxGlyphs);
475 if (!psva)
477 WARN("Out of memory\n");
478 goto cleanup;
482 done = 0;
483 glyph_i = 0;
484 while (done < uCount)
486 INT j;
487 classify(lpString + done, chartype, uCount - done);
488 /* limit text to first block */
489 i = resolveParagraphs(chartype, uCount - done);
490 for (j = 0; j < i; ++j)
491 switch(chartype[j])
493 case B:
494 case S:
495 case WS:
496 case ON: chartype[j] = NI;
497 default: continue;
500 if ((dwWineGCP_Flags&WINE_GCPW_DIR_MASK) == WINE_GCPW_LOOSE_RTL)
501 State.uBidiLevel = 1;
502 else if ((dwWineGCP_Flags&WINE_GCPW_DIR_MASK) == WINE_GCPW_LOOSE_LTR)
503 State.uBidiLevel = 0;
505 if (dwWineGCP_Flags & WINE_GCPW_LOOSE_MASK)
507 for (j = 0; j < i; ++j)
508 if (chartype[j] == L)
510 State.uBidiLevel = 0;
511 break;
513 else if (chartype[j] == R || chartype[j] == AL)
515 State.uBidiLevel = 1;
516 break;
520 res = ScriptItemize(lpString + done, i, maxItems, &Control, &State, pItems, &nItems);
521 while (res == E_OUTOFMEMORY)
523 SCRIPT_ITEM *new_pItems = HeapReAlloc(GetProcessHeap(), 0, pItems, sizeof(*pItems) * maxItems * 2);
524 if (!new_pItems)
526 WARN("Out of memory\n");
527 goto cleanup;
529 pItems = new_pItems;
530 maxItems *= 2;
531 res = ScriptItemize(lpString + done, i, maxItems, &Control, &State, pItems, &nItems);
534 if (lpOutString || lpOrder)
535 for (j = 0; j < nItems; j++)
537 int k;
538 for (k = pItems[j].iCharPos; k < pItems[j+1].iCharPos; k++)
539 levels[k] = pItems[j].a.s.uBidiLevel;
542 if (lpOutString)
544 /* assign directional types again, but for WS, S this time */
545 classify(lpString + done, chartype, i);
547 BidiLines(State.uBidiLevel, lpOutString + done, lpString + done,
548 chartype, levels, i, 0);
551 if (lpOrder)
553 int k, lastgood;
554 for (j = lastgood = 0; j < i; ++j)
555 if (levels[j] != levels[lastgood])
557 --j;
558 if (odd(levels[lastgood]))
559 for (k = j; k >= lastgood; --k)
560 lpOrder[done + k] = done + j - k;
561 else
562 for (k = lastgood; k <= j; ++k)
563 lpOrder[done + k] = done + k;
564 lastgood = ++j;
566 if (odd(levels[lastgood]))
567 for (k = j - 1; k >= lastgood; --k)
568 lpOrder[done + k] = done + j - 1 - k;
569 else
570 for (k = lastgood; k < j; ++k)
571 lpOrder[done + k] = done + k;
574 if (lpGlyphs && doGlyphs)
576 BYTE *runOrder;
577 int *visOrder;
578 SCRIPT_ITEM *curItem;
580 runOrder = HeapAlloc(GetProcessHeap(), 0, maxItems * sizeof(*runOrder));
581 visOrder = HeapAlloc(GetProcessHeap(), 0, maxItems * sizeof(*visOrder));
582 if (!runOrder || !visOrder)
584 WARN("Out of memory\n");
585 HeapFree(GetProcessHeap(), 0, runOrder);
586 HeapFree(GetProcessHeap(), 0, visOrder);
587 goto cleanup;
590 for (j = 0; j < nItems; j++)
591 runOrder[j] = pItems[j].a.s.uBidiLevel;
593 ScriptLayout(nItems, runOrder, visOrder, NULL);
595 for (j = 0; j < nItems; j++)
597 int k;
598 int cChars,cOutGlyphs;
599 curItem = &pItems[visOrder[j]];
601 cChars = pItems[visOrder[j]+1].iCharPos - curItem->iCharPos;
603 res = ScriptShape(hDC, &psc, lpString + done + curItem->iCharPos, cChars, cMaxGlyphs, &curItem->a, run_glyphs, pwLogClust, psva, &cOutGlyphs);
604 while (res == E_OUTOFMEMORY)
606 WORD *new_run_glyphs = HeapReAlloc(GetProcessHeap(), 0, run_glyphs, sizeof(*run_glyphs) * cMaxGlyphs * 2);
607 SCRIPT_VISATTR *new_psva = HeapReAlloc(GetProcessHeap(), 0, psva, sizeof(*psva) * cMaxGlyphs * 2);
608 if (!new_run_glyphs || !new_psva)
610 WARN("Out of memory\n");
611 HeapFree(GetProcessHeap(), 0, runOrder);
612 HeapFree(GetProcessHeap(), 0, visOrder);
613 HeapFree(GetProcessHeap(), 0, *lpGlyphs);
614 *lpGlyphs = NULL;
615 if (new_run_glyphs)
616 run_glyphs = new_run_glyphs;
617 if (new_psva)
618 psva = new_psva;
619 goto cleanup;
621 run_glyphs = new_run_glyphs;
622 psva = new_psva;
623 cMaxGlyphs *= 2;
624 res = ScriptShape(hDC, &psc, lpString + done + curItem->iCharPos, cChars, cMaxGlyphs, &curItem->a, run_glyphs, pwLogClust, psva, &cOutGlyphs);
626 if (res)
628 if (res == USP_E_SCRIPT_NOT_IN_FONT)
629 TRACE("Unable to shape with currently selected font\n");
630 else
631 FIXME("Unable to shape string (%lx)\n",res);
632 j = nItems;
633 doGlyphs = FALSE;
634 HeapFree(GetProcessHeap(), 0, *lpGlyphs);
635 *lpGlyphs = NULL;
637 else
639 WORD *new_glyphs;
640 if (*lpGlyphs)
641 new_glyphs = HeapReAlloc(GetProcessHeap(), 0, *lpGlyphs, sizeof(**lpGlyphs) * (glyph_i + cOutGlyphs));
642 else
643 new_glyphs = HeapAlloc(GetProcessHeap(), 0, sizeof(**lpGlyphs) * (glyph_i + cOutGlyphs));
644 if (!new_glyphs)
646 WARN("Out of memory\n");
647 HeapFree(GetProcessHeap(), 0, runOrder);
648 HeapFree(GetProcessHeap(), 0, visOrder);
649 HeapFree(GetProcessHeap(), 0, *lpGlyphs);
650 *lpGlyphs = NULL;
651 goto cleanup;
653 *lpGlyphs = new_glyphs;
654 for (k = 0; k < cOutGlyphs; k++)
655 (*lpGlyphs)[glyph_i+k] = run_glyphs[k];
656 glyph_i += cOutGlyphs;
659 HeapFree(GetProcessHeap(), 0, runOrder);
660 HeapFree(GetProcessHeap(), 0, visOrder);
663 done += i;
665 if (cGlyphs)
666 *cGlyphs = glyph_i;
668 ret = TRUE;
669 cleanup:
670 HeapFree(GetProcessHeap(), 0, chartype);
671 HeapFree(GetProcessHeap(), 0, levels);
672 HeapFree(GetProcessHeap(), 0, pItems);
673 HeapFree(GetProcessHeap(), 0, run_glyphs);
674 HeapFree(GetProcessHeap(), 0, pwLogClust);
675 HeapFree(GetProcessHeap(), 0, psva);
676 ScriptFreeCache(&psc);
677 return ret;
680 /***********************************************************************
681 * text_mbtowc
683 * Returns a Unicode translation of str using the charset of the
684 * currently selected font in hdc. If count is -1 then str is assumed
685 * to be '\0' terminated, otherwise it contains the number of bytes to
686 * convert. If plenW is non-NULL, on return it will point to the
687 * number of WCHARs that have been written. If ret_cp is non-NULL, on
688 * return it will point to the codepage used in the conversion. The
689 * caller should free the returned string from the process heap
690 * itself.
692 static WCHAR *text_mbtowc( HDC hdc, const char *str, INT count, INT *plenW, UINT *ret_cp )
694 UINT cp;
695 INT lenW;
696 LPWSTR strW;
698 cp = GdiGetCodePage( hdc );
700 if (count == -1) count = strlen( str );
701 lenW = MultiByteToWideChar( cp, 0, str, count, NULL, 0 );
702 strW = HeapAlloc( GetProcessHeap(), 0, lenW * sizeof(WCHAR) );
703 MultiByteToWideChar( cp, 0, str, count, strW, lenW );
704 TRACE( "mapped %s -> %s\n", debugstr_an(str, count), debugstr_wn(strW, lenW) );
705 if (plenW) *plenW = lenW;
706 if (ret_cp) *ret_cp = cp;
707 return strW;
710 static void text_metric_WtoA( const TEXTMETRICW *tmW, TEXTMETRICA *tmA )
712 tmA->tmHeight = tmW->tmHeight;
713 tmA->tmAscent = tmW->tmAscent;
714 tmA->tmDescent = tmW->tmDescent;
715 tmA->tmInternalLeading = tmW->tmInternalLeading;
716 tmA->tmExternalLeading = tmW->tmExternalLeading;
717 tmA->tmAveCharWidth = tmW->tmAveCharWidth;
718 tmA->tmMaxCharWidth = tmW->tmMaxCharWidth;
719 tmA->tmWeight = tmW->tmWeight;
720 tmA->tmOverhang = tmW->tmOverhang;
721 tmA->tmDigitizedAspectX = tmW->tmDigitizedAspectX;
722 tmA->tmDigitizedAspectY = tmW->tmDigitizedAspectY;
723 tmA->tmFirstChar = min( tmW->tmFirstChar, 255 );
724 if (tmW->tmCharSet == SYMBOL_CHARSET)
726 tmA->tmFirstChar = 0x1e;
727 tmA->tmLastChar = 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
729 else if (tmW->tmPitchAndFamily & TMPF_TRUETYPE)
731 tmA->tmFirstChar = tmW->tmDefaultChar - 1;
732 tmA->tmLastChar = min( tmW->tmLastChar, 0xff );
734 else
736 tmA->tmFirstChar = min( tmW->tmFirstChar, 0xff );
737 tmA->tmLastChar = min( tmW->tmLastChar, 0xff );
739 tmA->tmDefaultChar = tmW->tmDefaultChar;
740 tmA->tmBreakChar = tmW->tmBreakChar;
741 tmA->tmItalic = tmW->tmItalic;
742 tmA->tmUnderlined = tmW->tmUnderlined;
743 tmA->tmStruckOut = tmW->tmStruckOut;
744 tmA->tmPitchAndFamily = tmW->tmPitchAndFamily;
745 tmA->tmCharSet = tmW->tmCharSet;
748 static void text_metric_ex_WtoA(const NEWTEXTMETRICEXW *tmW, NEWTEXTMETRICEXA *tmA )
750 text_metric_WtoA( (const TEXTMETRICW *)tmW, (LPTEXTMETRICA)tmA );
751 tmA->ntmTm.ntmFlags = tmW->ntmTm.ntmFlags;
752 tmA->ntmTm.ntmSizeEM = tmW->ntmTm.ntmSizeEM;
753 tmA->ntmTm.ntmCellHeight = tmW->ntmTm.ntmCellHeight;
754 tmA->ntmTm.ntmAvgWidth = tmW->ntmTm.ntmAvgWidth;
755 memcpy( &tmA->ntmFontSig, &tmW->ntmFontSig, sizeof(FONTSIGNATURE) );
758 static void logfont_AtoW( const LOGFONTA *fontA, LPLOGFONTW fontW )
760 memcpy( fontW, fontA, sizeof(LOGFONTA) - LF_FACESIZE );
761 MultiByteToWideChar( CP_ACP, 0, fontA->lfFaceName, -1, fontW->lfFaceName,
762 LF_FACESIZE );
763 fontW->lfFaceName[LF_FACESIZE - 1] = 0;
766 static void logfont_WtoA( const LOGFONTW *fontW, LPLOGFONTA fontA )
768 memcpy( fontA, fontW, sizeof(LOGFONTA) - LF_FACESIZE );
769 WideCharToMultiByte( CP_ACP, 0, fontW->lfFaceName, -1, fontA->lfFaceName,
770 LF_FACESIZE, NULL, NULL );
771 fontA->lfFaceName[LF_FACESIZE - 1] = 0;
774 static void logfontex_AtoW( const ENUMLOGFONTEXA *fontA, LPENUMLOGFONTEXW fontW )
776 logfont_AtoW( &fontA->elfLogFont, &fontW->elfLogFont );
778 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfFullName, -1,
779 fontW->elfFullName, LF_FULLFACESIZE );
780 fontW->elfFullName[LF_FULLFACESIZE - 1] = '\0';
781 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfStyle, -1,
782 fontW->elfStyle, LF_FACESIZE );
783 fontW->elfStyle[LF_FACESIZE - 1] = '\0';
784 MultiByteToWideChar( CP_ACP, 0, (LPCSTR)fontA->elfScript, -1,
785 fontW->elfScript, LF_FACESIZE );
786 fontW->elfScript[LF_FACESIZE - 1] = '\0';
790 static void logfontex_WtoA( const ENUMLOGFONTEXW *fontW, LPENUMLOGFONTEXA fontA )
792 logfont_WtoA( &fontW->elfLogFont, &fontA->elfLogFont );
794 WideCharToMultiByte( CP_ACP, 0, fontW->elfFullName, -1,
795 (char *)fontA->elfFullName, LF_FULLFACESIZE, NULL, NULL );
796 fontA->elfFullName[LF_FULLFACESIZE - 1] = '\0';
797 WideCharToMultiByte( CP_ACP, 0, fontW->elfStyle, -1,
798 (char *)fontA->elfStyle, LF_FACESIZE, NULL, NULL );
799 fontA->elfStyle[LF_FACESIZE - 1] = '\0';
800 WideCharToMultiByte( CP_ACP, 0, fontW->elfScript, -1,
801 (char *)fontA->elfScript, LF_FACESIZE, NULL, NULL );
802 fontA->elfScript[LF_FACESIZE - 1] = '\0';
805 /***********************************************************************
806 * GdiGetCodePage (GDI32.@)
808 DWORD WINAPI GdiGetCodePage( HDC hdc )
810 DC_ATTR *dc_attr = get_dc_attr( hdc );
811 return dc_attr ? dc_attr->font_code_page : CP_ACP;
814 /***********************************************************************
815 * CreateFontIndirectExA (GDI32.@)
817 HFONT WINAPI CreateFontIndirectExA( const ENUMLOGFONTEXDVA *enumexA )
819 ENUMLOGFONTEXDVW enumexW;
821 if (!enumexA) return 0;
823 logfontex_AtoW( &enumexA->elfEnumLogfontEx, &enumexW.elfEnumLogfontEx );
824 enumexW.elfDesignVector = enumexA->elfDesignVector;
825 return CreateFontIndirectExW( &enumexW );
828 /***********************************************************************
829 * CreateFontIndirectExW (GDI32.@)
831 HFONT WINAPI CreateFontIndirectExW( const ENUMLOGFONTEXDVW *enumex )
833 return NtGdiHfontCreate( enumex, sizeof(*enumex), 0, 0, NULL );
836 /***********************************************************************
837 * CreateFontIndirectA (GDI32.@)
839 HFONT WINAPI CreateFontIndirectA( const LOGFONTA *lfA )
841 LOGFONTW lfW;
843 if (!lfA) return 0;
845 logfont_AtoW( lfA, &lfW );
846 return CreateFontIndirectW( &lfW );
849 /***********************************************************************
850 * CreateFontIndirectW (GDI32.@)
852 HFONT WINAPI CreateFontIndirectW( const LOGFONTW *lf )
854 ENUMLOGFONTEXDVW exdv;
856 if (!lf) return 0;
858 exdv.elfEnumLogfontEx.elfLogFont = *lf;
859 exdv.elfEnumLogfontEx.elfFullName[0] = 0;
860 exdv.elfEnumLogfontEx.elfStyle[0] = 0;
861 exdv.elfEnumLogfontEx.elfScript[0] = 0;
862 return CreateFontIndirectExW( &exdv );
865 /*************************************************************************
866 * CreateFontA (GDI32.@)
868 HFONT WINAPI CreateFontA( INT height, INT width, INT esc, INT orient, INT weight,
869 DWORD italic, DWORD underline, DWORD strikeout,
870 DWORD charset, DWORD outpres, DWORD clippres,
871 DWORD quality, DWORD pitch, const char *name )
873 LOGFONTA logfont;
875 logfont.lfHeight = height;
876 logfont.lfWidth = width;
877 logfont.lfEscapement = esc;
878 logfont.lfOrientation = orient;
879 logfont.lfWeight = weight;
880 logfont.lfItalic = italic;
881 logfont.lfUnderline = underline;
882 logfont.lfStrikeOut = strikeout;
883 logfont.lfCharSet = charset;
884 logfont.lfOutPrecision = outpres;
885 logfont.lfClipPrecision = clippres;
886 logfont.lfQuality = quality;
887 logfont.lfPitchAndFamily = pitch;
889 if (name)
890 lstrcpynA( logfont.lfFaceName, name, sizeof(logfont.lfFaceName) );
891 else
892 logfont.lfFaceName[0] = '\0';
894 return CreateFontIndirectA( &logfont );
897 /*************************************************************************
898 * CreateFontW (GDI32.@)
900 HFONT WINAPI CreateFontW( INT height, INT width, INT esc, INT orient, INT weight,
901 DWORD italic, DWORD underline, DWORD strikeout,
902 DWORD charset, DWORD outpres, DWORD clippres,
903 DWORD quality, DWORD pitch, const WCHAR *name )
905 LOGFONTW logfont;
907 logfont.lfHeight = height;
908 logfont.lfWidth = width;
909 logfont.lfEscapement = esc;
910 logfont.lfOrientation = orient;
911 logfont.lfWeight = weight;
912 logfont.lfItalic = italic;
913 logfont.lfUnderline = underline;
914 logfont.lfStrikeOut = strikeout;
915 logfont.lfCharSet = charset;
916 logfont.lfOutPrecision = outpres;
917 logfont.lfClipPrecision = clippres;
918 logfont.lfQuality = quality;
919 logfont.lfPitchAndFamily = pitch;
921 if (name)
922 lstrcpynW( logfont.lfFaceName, name, ARRAY_SIZE(logfont.lfFaceName) );
923 else
924 logfont.lfFaceName[0] = '\0';
926 return CreateFontIndirectW( &logfont );
929 /***********************************************************************
930 * ExtTextOutW (GDI32.@)
932 BOOL WINAPI ExtTextOutW( HDC hdc, INT x, INT y, UINT flags, const RECT *rect,
933 const WCHAR *str, UINT count, const INT *dx )
935 WORD *glyphs = NULL;
936 DC_ATTR *dc_attr;
937 BOOL ret;
939 if (count > INT_MAX) return FALSE;
940 if (is_meta_dc( hdc )) return METADC_ExtTextOut( hdc, x, y, flags, rect, str, count, dx );
941 if (!(dc_attr = get_dc_attr( hdc ))) return FALSE;
942 if (dc_attr->emf && !EMFDC_ExtTextOut( dc_attr, x, y, flags, rect, str, count, dx ))
943 return FALSE;
945 if (!(flags & (ETO_GLYPH_INDEX | ETO_IGNORELANGUAGE)) && count > 0)
947 UINT bidi_flags;
948 int glyphs_count;
950 bidi_flags = (dc_attr->text_align & TA_RTLREADING) || (flags & ETO_RTLREADING)
951 ? WINE_GCPW_FORCE_RTL : WINE_GCPW_FORCE_LTR;
953 BIDI_Reorder( hdc, str, count, GCP_REORDER, bidi_flags, NULL, 0, NULL,
954 &glyphs, &glyphs_count );
956 flags |= ETO_IGNORELANGUAGE;
957 if (glyphs)
959 flags |= ETO_GLYPH_INDEX;
960 count = glyphs_count;
961 str = glyphs;
965 ret = NtGdiExtTextOutW( hdc, x, y, flags, rect, str, count, dx, 0 );
967 HeapFree( GetProcessHeap(), 0, glyphs );
968 return ret;
971 /***********************************************************************
972 * ExtTextOutA (GDI32.@)
974 BOOL WINAPI ExtTextOutA( HDC hdc, INT x, INT y, UINT flags, const RECT *rect,
975 const char *str, UINT count, const INT *dx )
977 INT wlen;
978 UINT codepage;
979 WCHAR *p;
980 BOOL ret;
981 INT *dxW = NULL;
983 if (count > INT_MAX) return FALSE;
985 if (flags & ETO_GLYPH_INDEX)
986 return ExtTextOutW( hdc, x, y, flags, rect, (const WCHAR *)str, count, dx );
988 p = text_mbtowc( hdc, str, count, &wlen, &codepage );
990 if (dx)
992 unsigned int i = 0, j = 0;
994 /* allocate enough for a ETO_PDY */
995 dxW = HeapAlloc( GetProcessHeap(), 0, 2 * wlen * sizeof(INT) );
996 while (i < count)
998 if (IsDBCSLeadByteEx( codepage, str[i] ))
1000 if (flags & ETO_PDY)
1002 dxW[j++] = dx[i * 2] + dx[(i + 1) * 2];
1003 dxW[j++] = dx[i * 2 + 1] + dx[(i + 1) * 2 + 1];
1005 else
1006 dxW[j++] = dx[i] + dx[i + 1];
1007 i = i + 2;
1009 else
1011 if (flags & ETO_PDY)
1013 dxW[j++] = dx[i * 2];
1014 dxW[j++] = dx[i * 2 + 1];
1016 else
1017 dxW[j++] = dx[i];
1018 i = i + 1;
1023 ret = ExtTextOutW( hdc, x, y, flags, rect, p, wlen, dxW );
1025 HeapFree( GetProcessHeap(), 0, p );
1026 HeapFree( GetProcessHeap(), 0, dxW );
1027 return ret;
1030 /***********************************************************************
1031 * TextOutA (GDI32.@)
1033 BOOL WINAPI TextOutA( HDC hdc, INT x, INT y, const char *str, INT count )
1035 return ExtTextOutA( hdc, x, y, 0, NULL, str, count, NULL );
1038 /***********************************************************************
1039 * TextOutW (GDI32.@)
1041 BOOL WINAPI TextOutW( HDC hdc, INT x, INT y, const WCHAR *str, INT count )
1043 return ExtTextOutW( hdc, x, y, 0, NULL, str, count, NULL );
1047 /***********************************************************************
1048 * PolyTextOutA (GDI32.@)
1050 BOOL WINAPI PolyTextOutA( HDC hdc, const POLYTEXTA *pt, INT count )
1052 for (; count>0; count--, pt++)
1053 if (!ExtTextOutA( hdc, pt->x, pt->y, pt->uiFlags, &pt->rcl, pt->lpstr, pt->n, pt->pdx ))
1054 return FALSE;
1055 return TRUE;
1058 /***********************************************************************
1059 * PolyTextOutW (GDI32.@)
1061 BOOL WINAPI PolyTextOutW( HDC hdc, const POLYTEXTW *pt, INT count )
1063 for (; count>0; count--, pt++)
1064 if (!ExtTextOutW( hdc, pt->x, pt->y, pt->uiFlags, &pt->rcl, pt->lpstr, pt->n, pt->pdx ))
1065 return FALSE;
1066 return TRUE;
1069 static int kern_pair( const KERNINGPAIR *kern, int count, WCHAR c1, WCHAR c2 )
1071 int i;
1073 for (i = 0; i < count; i++)
1075 if (kern[i].wFirst == c1 && kern[i].wSecond == c2)
1076 return kern[i].iKernAmount;
1079 return 0;
1082 static int *kern_string( HDC hdc, const WCHAR *str, int len, int *kern_total )
1084 unsigned int i, count;
1085 KERNINGPAIR *kern = NULL;
1086 int *ret;
1088 *kern_total = 0;
1090 ret = HeapAlloc( GetProcessHeap(), 0, len * sizeof(*ret) );
1091 if (!ret) return NULL;
1093 count = NtGdiGetKerningPairs( hdc, 0, NULL );
1094 if (count)
1096 kern = HeapAlloc( GetProcessHeap(), 0, count * sizeof(*kern) );
1097 if (!kern)
1099 HeapFree( GetProcessHeap(), 0, ret );
1100 return NULL;
1103 NtGdiGetKerningPairs( hdc, count, kern );
1106 for (i = 0; i < len - 1; i++)
1108 ret[i] = kern_pair( kern, count, str[i], str[i + 1] );
1109 *kern_total += ret[i];
1112 ret[len - 1] = 0; /* no kerning for last element */
1114 HeapFree( GetProcessHeap(), 0, kern );
1115 return ret;
1118 /*************************************************************************
1119 * GetCharacterPlacementW (GDI32.@)
1121 * Retrieve information about a string. This includes the width, reordering,
1122 * Glyphing and so on.
1124 * RETURNS
1126 * The width and height of the string if successful, 0 if failed.
1128 * BUGS
1130 * All flags except GCP_REORDER are not yet implemented.
1131 * Reordering is not 100% compliant to the Windows BiDi method.
1132 * Caret positioning is not yet implemented for BiDi.
1133 * Classes are not yet implemented.
1136 DWORD WINAPI GetCharacterPlacementW( HDC hdc, const WCHAR *str, INT count, INT max_extent,
1137 GCP_RESULTSW *result, DWORD flags )
1139 int *kern = NULL, kern_total = 0;
1140 UINT i, set_cnt;
1141 SIZE size;
1142 DWORD ret = 0;
1144 TRACE("%s, %d, %d, 0x%08lx\n", debugstr_wn(str, count), count, max_extent, flags);
1146 if (!count)
1147 return 0;
1149 if (!result)
1150 return GetTextExtentPoint32W( hdc, str, count, &size ) ? MAKELONG(size.cx, size.cy) : 0;
1152 TRACE( "lStructSize=%ld, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1153 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1154 result->lStructSize, result->lpOutString, result->lpOrder,
1155 result->lpDx, result->lpCaretPos, result->lpClass,
1156 result->lpGlyphs, result->nGlyphs, result->nMaxFit );
1158 if (flags & ~(GCP_REORDER | GCP_USEKERNING))
1159 FIXME( "flags 0x%08lx ignored\n", flags );
1160 if (result->lpClass)
1161 FIXME( "classes not implemented\n" );
1162 if (result->lpCaretPos && (flags & GCP_REORDER))
1163 FIXME( "Caret positions for complex scripts not implemented\n" );
1165 set_cnt = (UINT)count;
1166 if (set_cnt > result->nGlyphs) set_cnt = result->nGlyphs;
1168 /* return number of initialized fields */
1169 result->nGlyphs = set_cnt;
1171 if (!(flags & GCP_REORDER))
1173 /* Treat the case where no special handling was requested in a fastpath way */
1174 /* copy will do if the GCP_REORDER flag is not set */
1175 if (result->lpOutString)
1176 memcpy( result->lpOutString, str, set_cnt * sizeof(WCHAR) );
1178 if (result->lpOrder)
1180 for (i = 0; i < set_cnt; i++)
1181 result->lpOrder[i] = i;
1184 else
1186 BIDI_Reorder( NULL, str, count, flags, WINE_GCPW_FORCE_LTR, result->lpOutString,
1187 set_cnt, result->lpOrder, NULL, NULL );
1190 if (flags & GCP_USEKERNING)
1192 kern = kern_string( hdc, str, set_cnt, &kern_total );
1193 if (!kern)
1195 SetLastError( ERROR_NOT_ENOUGH_MEMORY );
1196 return 0;
1200 /* FIXME: Will use the placement chars */
1201 if (result->lpDx)
1203 int c;
1204 for (i = 0; i < set_cnt; i++)
1206 if (GetCharWidth32W( hdc, str[i], str[i], &c ))
1208 result->lpDx[i] = c;
1209 if (flags & GCP_USEKERNING)
1210 result->lpDx[i] += kern[i];
1215 if (result->lpCaretPos && !(flags & GCP_REORDER))
1217 unsigned int pos = 0;
1219 result->lpCaretPos[0] = 0;
1220 for (i = 0; i < set_cnt - 1; i++)
1222 if (flags & GCP_USEKERNING)
1223 pos += kern[i];
1225 if (GetTextExtentPoint32W( hdc, &str[i], 1, &size ))
1226 result->lpCaretPos[i + 1] = (pos += size.cx);
1230 if (result->lpGlyphs)
1231 NtGdiGetGlyphIndicesW( hdc, str, set_cnt, result->lpGlyphs, 0 );
1233 if (GetTextExtentPoint32W( hdc, str, count, &size ))
1234 ret = MAKELONG( size.cx + kern_total, size.cy );
1236 HeapFree( GetProcessHeap(), 0, kern );
1237 return ret;
1240 /*************************************************************************
1241 * GetCharacterPlacementA (GDI32.@)
1243 DWORD WINAPI GetCharacterPlacementA( HDC hdc, const char *str, INT count, INT max_extent,
1244 GCP_RESULTSA *result, DWORD flags )
1246 GCP_RESULTSW resultsW;
1247 WCHAR *strW;
1248 INT countW;
1249 DWORD ret;
1250 UINT font_cp;
1252 TRACE( "%s, %d, %d, 0x%08lx\n", debugstr_an(str, count), count, max_extent, flags );
1254 strW = text_mbtowc( hdc, str, count, &countW, &font_cp );
1256 if (!result)
1258 ret = GetCharacterPlacementW( hdc, strW, countW, max_extent, NULL, flags );
1259 HeapFree( GetProcessHeap(), 0, strW );
1260 return ret;
1263 /* both structs are equal in size */
1264 memcpy( &resultsW, result, sizeof(resultsW) );
1266 if (result->lpOutString)
1267 resultsW.lpOutString = HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR) * countW );
1269 ret = GetCharacterPlacementW( hdc, strW, countW, max_extent, &resultsW, flags );
1271 result->nGlyphs = resultsW.nGlyphs;
1272 result->nMaxFit = resultsW.nMaxFit;
1274 if (result->lpOutString)
1275 WideCharToMultiByte( font_cp, 0, resultsW.lpOutString, countW,
1276 result->lpOutString, count, NULL, NULL );
1278 HeapFree( GetProcessHeap(), 0, strW );
1279 HeapFree( GetProcessHeap(), 0, resultsW.lpOutString );
1280 return ret;
1283 /***********************************************************************
1284 * GetTextFaceA (GDI32.@)
1286 INT WINAPI GetTextFaceA( HDC hdc, INT count, char *name )
1288 INT res = GetTextFaceW( hdc, 0, NULL );
1289 WCHAR *nameW = HeapAlloc( GetProcessHeap(), 0, res * sizeof(WCHAR) );
1291 GetTextFaceW( hdc, res, nameW );
1292 if (name)
1294 if (count)
1296 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, name, count, NULL, NULL );
1297 if (res == 0) res = count;
1298 name[count - 1] = 0;
1299 /* GetTextFaceA does NOT include the nul byte in the return count. */
1300 res--;
1302 else
1303 res = 0;
1305 else
1306 res = WideCharToMultiByte( CP_ACP, 0, nameW, -1, NULL, 0, NULL, NULL );
1307 HeapFree( GetProcessHeap(), 0, nameW );
1308 return res;
1311 /***********************************************************************
1312 * GetTextFaceW (GDI32.@)
1314 INT WINAPI GetTextFaceW( HDC hdc, INT count, WCHAR *name )
1316 return NtGdiGetTextFaceW( hdc, count, name, FALSE );
1319 /***********************************************************************
1320 * GetTextExtentExPointW (GDI32.@)
1322 BOOL WINAPI GetTextExtentExPointW( HDC hdc, const WCHAR *str, INT count, INT max_ext,
1323 INT *nfit, INT *dxs, SIZE *size )
1325 return NtGdiGetTextExtentExW( hdc, str, count, max_ext, nfit, dxs, size, 0 );
1328 /***********************************************************************
1329 * GetTextExtentExPointI (GDI32.@)
1331 BOOL WINAPI GetTextExtentExPointI( HDC hdc, const WORD *indices, INT count, INT max_ext,
1332 INT *nfit, INT *dxs, SIZE *size )
1334 return NtGdiGetTextExtentExW( hdc, indices, count, max_ext, nfit, dxs, size, 1 );
1337 /***********************************************************************
1338 * GetTextExtentExPointA (GDI32.@)
1340 BOOL WINAPI GetTextExtentExPointA( HDC hdc, const char *str, INT count, INT max_ext,
1341 INT *nfit, INT *dxs, SIZE *size )
1343 BOOL ret;
1344 INT wlen;
1345 INT *wdxs = NULL;
1346 WCHAR *p = NULL;
1348 if (count < 0 || max_ext < -1) return FALSE;
1350 if (dxs)
1352 wdxs = HeapAlloc( GetProcessHeap(), 0, count * sizeof(INT) );
1353 if (!wdxs) return FALSE;
1356 p = text_mbtowc( hdc, str, count, &wlen, NULL );
1357 ret = GetTextExtentExPointW( hdc, p, wlen, max_ext, nfit, wdxs, size );
1358 if (wdxs)
1360 INT n = nfit ? *nfit : wlen;
1361 INT i, j;
1362 for (i = 0, j = 0; i < n; i++, j++)
1364 dxs[j] = wdxs[i];
1365 if (IsDBCSLeadByte( str[j] )) dxs[++j] = wdxs[i];
1368 if (nfit) *nfit = WideCharToMultiByte( CP_ACP, 0, p, *nfit, NULL, 0, NULL, NULL );
1369 HeapFree( GetProcessHeap(), 0, p );
1370 HeapFree( GetProcessHeap(), 0, wdxs );
1371 return ret;
1374 /***********************************************************************
1375 * GetTextExtentPoint32W (GDI32.@)
1377 BOOL WINAPI GetTextExtentPoint32W( HDC hdc, const WCHAR *str, INT count, SIZE *size )
1379 return GetTextExtentExPointW( hdc, str, count, 0, NULL, NULL, size );
1382 /***********************************************************************
1383 * GetTextExtentPoint32A (GDI32.@)
1385 BOOL WINAPI GetTextExtentPoint32A( HDC hdc, const char *str, INT count, SIZE *size )
1387 return GetTextExtentExPointA( hdc, str, count, 0, NULL, NULL, size );
1390 /***********************************************************************
1391 * GetTextExtentPointI (GDI32.@)
1393 BOOL WINAPI GetTextExtentPointI( HDC hdc, const WORD *indices, INT count, SIZE *size )
1395 return GetTextExtentExPointI( hdc, indices, count, 0, NULL, NULL, size );
1398 /***********************************************************************
1399 * GetTextExtentPointA (GDI32.@)
1401 BOOL WINAPI GetTextExtentPointA( HDC hdc, const char *str, INT count, SIZE *size )
1403 return GetTextExtentPoint32A( hdc, str, count, size );
1406 /***********************************************************************
1407 * GetTextExtentPointW (GDI32.@)
1409 BOOL WINAPI GetTextExtentPointW( HDC hdc, const WCHAR *str, INT count, SIZE *size )
1411 return GetTextExtentPoint32W( hdc, str, count, size );
1414 /***********************************************************************
1415 * GetTextMetricsW (GDI32.@)
1417 BOOL WINAPI GetTextMetricsW( HDC hdc, TEXTMETRICW *metrics )
1419 return NtGdiGetTextMetricsW( hdc, metrics, 0 );
1422 /***********************************************************************
1423 * GetTextMetricsA (GDI32.@)
1425 BOOL WINAPI GetTextMetricsA( HDC hdc, TEXTMETRICA *metrics )
1427 TEXTMETRICW tm32;
1429 if (!GetTextMetricsW( hdc, &tm32 )) return FALSE;
1430 text_metric_WtoA( &tm32, metrics );
1431 return TRUE;
1434 /***********************************************************************
1435 * GetOutlineTextMetricsA (GDI32.@)
1437 * Gets metrics for TrueType fonts.
1439 * NOTES
1440 * If the supplied buffer isn't big enough Windows partially fills it up to
1441 * its given length and returns that length.
1443 UINT WINAPI GetOutlineTextMetricsA( HDC hdc, UINT size, OUTLINETEXTMETRICA *otm )
1445 char buf[512], *ptr;
1446 UINT ret, needed;
1447 OUTLINETEXTMETRICW *otmW = (OUTLINETEXTMETRICW *)buf;
1448 OUTLINETEXTMETRICA *output = otm;
1449 INT left, len;
1451 if ((ret = GetOutlineTextMetricsW( hdc, 0, NULL )) == 0) return 0;
1452 if (ret > sizeof(buf) && !(otmW = HeapAlloc( GetProcessHeap(), 0, ret )))
1453 return 0;
1455 GetOutlineTextMetricsW( hdc, ret, otmW );
1457 needed = sizeof(OUTLINETEXTMETRICA);
1458 if (otmW->otmpFamilyName)
1459 needed += WideCharToMultiByte( CP_ACP, 0,
1460 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFamilyName),
1461 -1, NULL, 0, NULL, NULL );
1462 if (otmW->otmpFaceName)
1463 needed += WideCharToMultiByte( CP_ACP, 0,
1464 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFaceName),
1465 -1, NULL, 0, NULL, NULL );
1466 if (otmW->otmpStyleName)
1467 needed += WideCharToMultiByte( CP_ACP, 0,
1468 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpStyleName),
1469 -1, NULL, 0, NULL, NULL );
1470 if (otmW->otmpFullName)
1471 needed += WideCharToMultiByte( CP_ACP, 0,
1472 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFullName),
1473 -1, NULL, 0, NULL, NULL );
1475 if (!otm)
1477 ret = needed;
1478 goto end;
1481 TRACE( "needed = %d\n", needed );
1482 if (needed > size)
1483 /* Since the supplied buffer isn't big enough, we'll alloc one
1484 that is and memcpy the first size bytes into the otm at
1485 the end. */
1486 output = HeapAlloc( GetProcessHeap(), 0, needed );
1488 ret = output->otmSize = min( needed, size );
1489 text_metric_WtoA( &otmW->otmTextMetrics, &output->otmTextMetrics );
1490 output->otmFiller = 0;
1491 output->otmPanoseNumber = otmW->otmPanoseNumber;
1492 output->otmfsSelection = otmW->otmfsSelection;
1493 output->otmfsType = otmW->otmfsType;
1494 output->otmsCharSlopeRise = otmW->otmsCharSlopeRise;
1495 output->otmsCharSlopeRun = otmW->otmsCharSlopeRun;
1496 output->otmItalicAngle = otmW->otmItalicAngle;
1497 output->otmEMSquare = otmW->otmEMSquare;
1498 output->otmAscent = otmW->otmAscent;
1499 output->otmDescent = otmW->otmDescent;
1500 output->otmLineGap = otmW->otmLineGap;
1501 output->otmsCapEmHeight = otmW->otmsCapEmHeight;
1502 output->otmsXHeight = otmW->otmsXHeight;
1503 output->otmrcFontBox = otmW->otmrcFontBox;
1504 output->otmMacAscent = otmW->otmMacAscent;
1505 output->otmMacDescent = otmW->otmMacDescent;
1506 output->otmMacLineGap = otmW->otmMacLineGap;
1507 output->otmusMinimumPPEM = otmW->otmusMinimumPPEM;
1508 output->otmptSubscriptSize = otmW->otmptSubscriptSize;
1509 output->otmptSubscriptOffset = otmW->otmptSubscriptOffset;
1510 output->otmptSuperscriptSize = otmW->otmptSuperscriptSize;
1511 output->otmptSuperscriptOffset = otmW->otmptSuperscriptOffset;
1512 output->otmsStrikeoutSize = otmW->otmsStrikeoutSize;
1513 output->otmsStrikeoutPosition = otmW->otmsStrikeoutPosition;
1514 output->otmsUnderscoreSize = otmW->otmsUnderscoreSize;
1515 output->otmsUnderscorePosition = otmW->otmsUnderscorePosition;
1517 ptr = (char *)(output + 1);
1518 left = needed - sizeof(*output);
1520 if (otmW->otmpFamilyName)
1522 output->otmpFamilyName = (char *)(ptr - (char *)output);
1523 len = WideCharToMultiByte( CP_ACP, 0,
1524 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFamilyName),
1525 -1, ptr, left, NULL, NULL );
1526 left -= len;
1527 ptr += len;
1529 else output->otmpFamilyName = 0;
1531 if (otmW->otmpFaceName)
1533 output->otmpFaceName = (char *)(ptr - (char *)output);
1534 len = WideCharToMultiByte( CP_ACP, 0,
1535 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFaceName),
1536 -1, ptr, left, NULL, NULL );
1537 left -= len;
1538 ptr += len;
1540 else output->otmpFaceName = 0;
1542 if (otmW->otmpStyleName)
1544 output->otmpStyleName = (char *)(ptr - (char *)output);
1545 len = WideCharToMultiByte( CP_ACP, 0,
1546 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpStyleName),
1547 -1, ptr, left, NULL, NULL);
1548 left -= len;
1549 ptr += len;
1551 else output->otmpStyleName = 0;
1553 if (otmW->otmpFullName)
1555 output->otmpFullName = (char *)(ptr - (char *)output);
1556 len = WideCharToMultiByte( CP_ACP, 0,
1557 (WCHAR *)((char *)otmW + (ptrdiff_t)otmW->otmpFullName),
1558 -1, ptr, left, NULL, NULL );
1559 left -= len;
1561 else output->otmpFullName = 0;
1563 assert( left == 0 );
1565 if (output != otm)
1567 memcpy( otm, output, size );
1568 HeapFree( GetProcessHeap(), 0, output );
1570 /* check if the string offsets really fit into the provided size */
1571 /* FIXME: should we check string length as well? */
1572 /* make sure that we don't read/write beyond the provided buffer */
1573 if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFamilyName) + sizeof(char *))
1575 if ((UINT_PTR)otm->otmpFamilyName >= otm->otmSize)
1576 otm->otmpFamilyName = 0; /* doesn't fit */
1579 /* make sure that we don't read/write beyond the provided buffer */
1580 if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFaceName) + sizeof(char *))
1582 if ((UINT_PTR)otm->otmpFaceName >= otm->otmSize)
1583 otm->otmpFaceName = 0; /* doesn't fit */
1586 /* make sure that we don't read/write beyond the provided buffer */
1587 if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpStyleName) + sizeof(char *))
1589 if ((UINT_PTR)otm->otmpStyleName >= otm->otmSize)
1590 otm->otmpStyleName = 0; /* doesn't fit */
1593 /* make sure that we don't read/write beyond the provided buffer */
1594 if (otm->otmSize >= FIELD_OFFSET(OUTLINETEXTMETRICA, otmpFullName) + sizeof(char *))
1596 if ((UINT_PTR)otm->otmpFullName >= otm->otmSize)
1597 otm->otmpFullName = 0; /* doesn't fit */
1601 end:
1602 if (otmW != (OUTLINETEXTMETRICW *)buf)
1603 HeapFree(GetProcessHeap(), 0, otmW);
1604 return ret;
1607 /***********************************************************************
1608 * GetOutlineTextMetricsW [GDI32.@]
1610 UINT WINAPI GetOutlineTextMetricsW( HDC hdc, UINT size, OUTLINETEXTMETRICW *otm )
1612 return NtGdiGetOutlineTextMetricsInternalW( hdc, size, otm, 0 );
1615 /***********************************************************************
1616 * GetCharWidthW (GDI32.@)
1617 * GetCharWidth32W (GDI32.@)
1619 BOOL WINAPI GetCharWidth32W( HDC hdc, UINT first, UINT last, INT *buffer )
1621 return NtGdiGetCharWidthW( hdc, first, last, NULL, NTGDI_GETCHARWIDTH_INT, buffer );
1624 static WCHAR *get_chars_by_range( HDC hdc, UINT first, UINT last, INT *ret_len )
1626 INT i, count = last - first + 1;
1627 WCHAR *wstr;
1628 char *str;
1629 UINT mbcp;
1630 UINT c;
1632 if (count <= 0)
1633 return NULL;
1635 mbcp = GdiGetCodePage( hdc );
1636 switch (mbcp)
1638 case 932:
1639 case 936:
1640 case 949:
1641 case 950:
1642 case 1361:
1643 if (last > 0xffff)
1644 return NULL;
1645 if ((first ^ last) > 0xff)
1646 return NULL;
1647 break;
1648 default:
1649 if (last > 0xff)
1650 return NULL;
1651 mbcp = 0;
1652 break;
1655 if (!(str = HeapAlloc( GetProcessHeap(), 0, count * 2 + 1 )))
1656 return NULL;
1658 for (i = 0, c = first; c <= last; i++, c++)
1660 if (mbcp) {
1661 if (c > 0xff)
1662 str[i++] = (BYTE)(c >> 8);
1663 if (c <= 0xff && IsDBCSLeadByteEx( mbcp, c ))
1664 str[i] = 0x1f; /* FIXME: use default character */
1665 else
1666 str[i] = (BYTE)c;
1668 else
1669 str[i] = (BYTE)c;
1671 str[i] = '\0';
1673 wstr = text_mbtowc( hdc, str, i, ret_len, NULL );
1674 HeapFree( GetProcessHeap(), 0, str );
1675 return wstr;
1678 /***********************************************************************
1679 * GetCharWidthA (GDI32.@)
1680 * GetCharWidth32A (GDI32.@)
1682 BOOL WINAPI GetCharWidth32A( HDC hdc, UINT first, UINT last, INT *buffer )
1684 WCHAR *chars;
1685 INT count;
1686 BOOL ret;
1688 if (!(chars = get_chars_by_range( hdc, first, last, &count ))) return FALSE;
1689 ret = NtGdiGetCharWidthW( hdc, 0, count, chars, NTGDI_GETCHARWIDTH_INT, buffer );
1690 HeapFree( GetProcessHeap(), 0, chars );
1691 return ret;
1694 /***********************************************************************
1695 * GetCharWidthFloatW (GDI32.@)
1697 BOOL WINAPI GetCharWidthFloatW( HDC hdc, UINT first, UINT last, float *buffer )
1699 return NtGdiGetCharWidthW( hdc, first, last, NULL, 0, buffer );
1702 /***********************************************************************
1703 * GetCharWidthFloatA (GDI32.@)
1705 BOOL WINAPI GetCharWidthFloatA( HDC hdc, UINT first, UINT last, float *buffer )
1707 WCHAR *chars;
1708 INT count;
1709 BOOL ret;
1711 if (!(chars = get_chars_by_range( hdc, first, last, &count ))) return FALSE;
1712 ret = NtGdiGetCharWidthW( hdc, 0, count, chars, 0, buffer );
1713 HeapFree( GetProcessHeap(), 0, chars );
1714 return ret;
1717 /***********************************************************************
1718 * GetCharWidthI (GDI32.@)
1720 BOOL WINAPI GetCharWidthI( HDC hdc, UINT first, UINT count, WORD *glyphs, INT *buffer )
1722 TRACE( "(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer );
1723 return NtGdiGetCharWidthW( hdc, first, count, glyphs,
1724 NTGDI_GETCHARWIDTH_INT | NTGDI_GETCHARWIDTH_INDICES, buffer );
1727 /***********************************************************************
1728 * GetCharABCWidthsW (GDI32.@)
1730 BOOL WINAPI GetCharABCWidthsW( HDC hdc, UINT first, UINT last, ABC *abc )
1732 return NtGdiGetCharABCWidthsW( hdc, first, last, NULL, NTGDI_GETCHARABCWIDTHS_INT, abc );
1735 /***********************************************************************
1736 * GetCharABCWidthsA (GDI32.@)
1738 * See GetCharABCWidthsW.
1740 BOOL WINAPI GetCharABCWidthsA( HDC hdc, UINT first, UINT last, ABC *abc )
1742 WCHAR *chars;
1743 INT count;
1744 BOOL ret;
1746 if (!(chars = get_chars_by_range( hdc, first, last, &count ))) return FALSE;
1747 ret = NtGdiGetCharABCWidthsW( hdc, 0, count, chars, NTGDI_GETCHARABCWIDTHS_INT, abc );
1748 HeapFree( GetProcessHeap(), 0, chars );
1749 return ret;
1752 /***********************************************************************
1753 * GetCharABCWidthsFloatW (GDI32.@)
1755 BOOL WINAPI GetCharABCWidthsFloatW( HDC hdc, UINT first, UINT last, ABCFLOAT *abcf )
1757 TRACE( "%p, %d, %d, %p\n", hdc, first, last, abcf );
1758 return NtGdiGetCharABCWidthsW( hdc, first, last, NULL, 0, abcf );
1761 /***********************************************************************
1762 * GetCharABCWidthsFloatA (GDI32.@)
1764 BOOL WINAPI GetCharABCWidthsFloatA( HDC hdc, UINT first, UINT last, ABCFLOAT *abcf )
1766 WCHAR *chars;
1767 INT count;
1768 BOOL ret;
1770 if (!(chars = get_chars_by_range( hdc, first, last, &count ))) return FALSE;
1771 ret = NtGdiGetCharABCWidthsW( hdc, 0, count, chars, 0, abcf );
1772 HeapFree( GetProcessHeap(), 0, chars );
1773 return ret;
1776 /***********************************************************************
1777 * GetCharABCWidthsI (GDI32.@)
1779 BOOL WINAPI GetCharABCWidthsI( HDC hdc, UINT first, UINT count, WORD *glyphs, ABC *buffer )
1781 TRACE( "(%p, %d, %d, %p, %p)\n", hdc, first, count, glyphs, buffer );
1782 return NtGdiGetCharABCWidthsW( hdc, first, count, glyphs,
1783 NTGDI_GETCHARABCWIDTHS_INDICES | NTGDI_GETCHARABCWIDTHS_INT,
1784 buffer );
1787 /***********************************************************************
1788 * GetGlyphOutlineA (GDI32.@)
1790 DWORD WINAPI GetGlyphOutlineA( HDC hdc, UINT ch, UINT format, GLYPHMETRICS *metrics, DWORD size,
1791 void *buffer, const MAT2 *mat2 )
1793 if (!mat2) return GDI_ERROR;
1795 if (!(format & GGO_GLYPH_INDEX))
1797 UINT cp;
1798 int len;
1799 char mbchs[2];
1800 WCHAR wChar;
1802 cp = GdiGetCodePage( hdc );
1803 if (IsDBCSLeadByteEx( cp, ch >> 8 ))
1805 len = 2;
1806 mbchs[0] = (ch & 0xff00) >> 8;
1807 mbchs[1] = (ch & 0xff);
1809 else
1811 len = 1;
1812 mbchs[0] = ch & 0xff;
1814 wChar = 0;
1815 MultiByteToWideChar(cp, 0, mbchs, len, &wChar, 1 );
1816 ch = wChar;
1819 return GetGlyphOutlineW( hdc, ch, format, metrics, size, buffer, mat2 );
1822 /***********************************************************************
1823 * GetGlyphOutlineW (GDI32.@)
1825 DWORD WINAPI GetGlyphOutlineW( HDC hdc, UINT ch, UINT format, GLYPHMETRICS *metrics,
1826 DWORD size, void *buffer, const MAT2 *mat2 )
1828 return NtGdiGetGlyphOutline( hdc, ch, format, metrics, size, buffer, mat2, FALSE );
1831 /*************************************************************************
1832 * GetKerningPairsA (GDI32.@)
1834 DWORD WINAPI GetKerningPairsA( HDC hdc, DWORD count, KERNINGPAIR *kern_pairA )
1836 DWORD i, total_kern_pairs, kern_pairs_copied = 0;
1837 KERNINGPAIR *kern_pairW;
1838 CPINFO cpi;
1839 UINT cp;
1841 if (!count && kern_pairA)
1843 SetLastError( ERROR_INVALID_PARAMETER );
1844 return 0;
1847 cp = GdiGetCodePage( hdc );
1849 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
1850 * to fail on an invalid character for CP_SYMBOL.
1852 cpi.DefaultChar[0] = 0;
1853 if (cp != CP_SYMBOL && !GetCPInfo( cp, &cpi ))
1855 FIXME( "Can't find codepage %u info\n", cp );
1856 return 0;
1859 total_kern_pairs = NtGdiGetKerningPairs( hdc, 0, NULL );
1860 if (!total_kern_pairs) return 0;
1862 kern_pairW = HeapAlloc( GetProcessHeap(), 0, total_kern_pairs * sizeof(*kern_pairW) );
1863 NtGdiGetKerningPairs( hdc, total_kern_pairs, kern_pairW );
1865 for (i = 0; i < total_kern_pairs; i++)
1867 char first, second;
1869 if (!WideCharToMultiByte( cp, 0, &kern_pairW[i].wFirst, 1, &first, 1, NULL, NULL ))
1870 continue;
1872 if (!WideCharToMultiByte( cp, 0, &kern_pairW[i].wSecond, 1, &second, 1, NULL, NULL ))
1873 continue;
1875 if (first == cpi.DefaultChar[0] || second == cpi.DefaultChar[0])
1876 continue;
1878 if (kern_pairA)
1880 if (kern_pairs_copied >= count) break;
1882 kern_pairA->wFirst = (BYTE)first;
1883 kern_pairA->wSecond = (BYTE)second;
1884 kern_pairA->iKernAmount = kern_pairW[i].iKernAmount;
1885 kern_pairA++;
1887 kern_pairs_copied++;
1890 HeapFree( GetProcessHeap(), 0, kern_pairW );
1891 return kern_pairs_copied;
1894 /*************************************************************************
1895 * GetFontLanguageInfo (GDI32.@)
1897 DWORD WINAPI GetFontLanguageInfo( HDC hdc )
1899 FONTSIGNATURE fontsig;
1900 DWORD result = 0;
1902 static const DWORD GCP_DBCS_MASK = FS_JISJAPAN|FS_CHINESESIMP|FS_WANSUNG|FS_CHINESETRAD|FS_JOHAB,
1903 GCP_DIACRITIC_MASK = 0x00000000,
1904 FLI_GLYPHS_MASK = 0x00000000,
1905 GCP_GLYPHSHAPE_MASK = FS_ARABIC,
1906 GCP_KASHIDA_MASK = 0x00000000,
1907 GCP_LIGATE_MASK = 0x00000000,
1908 GCP_REORDER_MASK = FS_HEBREW|FS_ARABIC;
1911 NtGdiGetTextCharsetInfo( hdc, &fontsig, 0 );
1912 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
1914 if (fontsig.fsCsb[0] & GCP_DBCS_MASK)
1915 result |= GCP_DBCS;
1917 if (fontsig.fsCsb[0] & GCP_DIACRITIC_MASK)
1918 result |= GCP_DIACRITIC;
1920 if (fontsig.fsCsb[0] & FLI_GLYPHS_MASK)
1921 result |= FLI_GLYPHS;
1923 if (fontsig.fsCsb[0] & GCP_GLYPHSHAPE_MASK)
1924 result |= GCP_GLYPHSHAPE;
1926 if (fontsig.fsCsb[0] & GCP_KASHIDA_MASK)
1927 result |= GCP_KASHIDA;
1929 if (fontsig.fsCsb[0] & GCP_LIGATE_MASK)
1930 result |= GCP_LIGATE;
1932 if (NtGdiGetKerningPairs( hdc, 0, NULL ))
1933 result |= GCP_USEKERNING;
1935 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
1936 if ((GetTextAlign( hdc ) & TA_RTLREADING) && (fontsig.fsCsb[0] & GCP_REORDER_MASK))
1937 result |= GCP_REORDER;
1939 return result;
1942 /*************************************************************************
1943 * GetGlyphIndicesA (GDI32.@)
1945 DWORD WINAPI GetGlyphIndicesA( HDC hdc, const char *str, INT count, WORD *indices, DWORD flags )
1947 DWORD ret;
1948 WCHAR *strW;
1949 INT countW;
1951 TRACE( "(%p, %s, %d, %p, 0x%lx)\n", hdc, debugstr_an(str, count), count, indices, flags );
1953 strW = text_mbtowc( hdc, str, count, &countW, NULL );
1954 ret = NtGdiGetGlyphIndicesW( hdc, strW, countW, indices, flags );
1955 HeapFree( GetProcessHeap(), 0, strW );
1956 return ret;
1959 /***********************************************************************
1960 * GetAspectRatioFilterEx (GDI32.@)
1962 BOOL WINAPI GetAspectRatioFilterEx( HDC hdc, SIZE *aspect_ratio )
1964 FIXME( "(%p, %p): stub\n", hdc, aspect_ratio );
1965 return FALSE;
1968 /***********************************************************************
1969 * GetTextCharset (GDI32.@)
1971 UINT WINAPI GetTextCharset( HDC hdc )
1973 /* MSDN docs say this is equivalent */
1974 return NtGdiGetTextCharsetInfo( hdc, NULL, 0 );
1977 /***********************************************************************
1978 * GdiGetCharDimensions (GDI32.@)
1980 * Gets the average width of the characters in the English alphabet.
1982 * NOTES
1983 * This function is used by the dialog manager to get the size of a dialog
1984 * unit. It should also be used by other pieces of code that need to know
1985 * the size of a dialog unit in logical units without having access to the
1986 * window handle of the dialog.
1987 * Windows caches the font metrics from this function, but we don't and
1988 * there doesn't appear to be an immediate advantage to do so.
1990 LONG WINAPI GdiGetCharDimensions( HDC hdc, TEXTMETRICW *metric, LONG *height )
1992 SIZE sz;
1994 if (metric && !GetTextMetricsW( hdc, metric )) return 0;
1996 if (!GetTextExtentPointW( hdc, L"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
1997 52, &sz ))
1998 return 0;
2000 if (height) *height = sz.cy;
2001 return (sz.cx / 26 + 1) / 2;
2004 /***********************************************************************
2005 * EnableEUDC (GDI32.@)
2007 BOOL WINAPI EnableEUDC( BOOL enable )
2009 FIXME( "(%d): stub\n", enable );
2010 return FALSE;
2013 /*************************************************************************
2014 * GetFontFileData (GDI32.@)
2016 BOOL WINAPI GetFontFileData( DWORD instance_id, DWORD file_index, UINT64 offset,
2017 void *buff, DWORD buff_size )
2019 return NtGdiGetFontFileData( instance_id, file_index, &offset, buff, buff_size );
2022 struct realization_info
2024 DWORD flags; /* 1 for bitmap fonts, 3 for scalable fonts */
2025 DWORD cache_num; /* keeps incrementing - num of fonts that have been created allowing for caching?? */
2026 DWORD instance_id; /* identifies a realized font instance */
2029 /*************************************************************
2030 * GdiRealizationInfo (GDI32.@)
2032 * Returns a structure that contains some font information.
2034 BOOL WINAPI GdiRealizationInfo( HDC hdc, struct realization_info *info )
2036 struct font_realization_info ri;
2038 ri.size = sizeof(ri);
2039 if (!NtGdiGetRealizationInfo( hdc, &ri )) return FALSE;
2041 info->flags = ri.flags;
2042 info->cache_num = ri.cache_num;
2043 info->instance_id = ri.instance_id;
2044 return TRUE;
2047 static void load_script_name( UINT id, WCHAR buffer[LF_FACESIZE] )
2049 HRSRC rsrc;
2050 HGLOBAL hMem;
2051 WCHAR *p;
2052 int i;
2054 id += IDS_FIRST_SCRIPT;
2055 buffer[0] = 0;
2056 rsrc = FindResourceW( gdi32_module, (LPCWSTR)(ULONG_PTR)((id >> 4) + 1), (LPCWSTR)6 /*RT_STRING*/ );
2057 if (!rsrc) return;
2058 hMem = LoadResource( gdi32_module, rsrc );
2059 if (!hMem) return;
2061 p = LockResource( hMem );
2062 id &= 0x000f;
2063 while (id--) p += *p + 1;
2065 i = min( LF_FACESIZE - 1, *p );
2066 memcpy( buffer, p + 1, i * sizeof(WCHAR) );
2067 buffer[i] = 0;
2070 /***********************************************************************
2071 * EnumFontFamiliesExW (GDI32.@)
2073 INT WINAPI EnumFontFamiliesExW( HDC hdc, LOGFONTW *lf, FONTENUMPROCW efproc,
2074 LPARAM lparam, DWORD flags )
2076 struct font_enum_entry buf[32], *entries = buf;
2077 const WCHAR *face_name = NULL;
2078 DWORD charset, face_name_len = 0;
2079 ULONG count, i;
2080 INT ret = 1;
2082 if (lf)
2084 if (lf->lfFaceName[0])
2086 face_name = lf->lfFaceName;
2087 face_name_len = lstrlenW( face_name );
2089 charset = lf->lfCharSet;
2091 else charset = DEFAULT_CHARSET;
2093 count = sizeof(buf);
2094 if (!NtGdiEnumFonts( hdc, 0, 0, face_name_len, face_name, charset, &count, buf ) &&
2095 count <= sizeof(buf))
2096 return 0;
2097 if (count > sizeof(buf))
2099 if (!(entries = HeapAlloc( GetProcessHeap(), 0, count ))) return 0;
2100 ret = NtGdiEnumFonts( hdc, 0, 0, face_name_len, face_name, charset, &count, entries );
2102 count /= sizeof(*entries);
2103 for (i = 0; ret && i < count; i++)
2105 load_script_name( entries[i].lf.elfScript[0], entries[i].lf.elfScript );
2106 ret = efproc( (const LOGFONTW *)&entries[i].lf, (const TEXTMETRICW *)&entries[i].tm,
2107 entries[i].type, lparam );
2110 if (entries != buf) HeapFree( GetProcessHeap(), 0, entries );
2111 return ret;
2114 struct enum_proc_paramsWtoA
2116 LPARAM lparam;
2117 FONTENUMPROCA proc;
2120 static INT WINAPI enum_proc_WtoA( const LOGFONTW *lf, const TEXTMETRICW *tm,
2121 DWORD type, LPARAM lparam )
2123 struct enum_proc_paramsWtoA *params = (struct enum_proc_paramsWtoA *)lparam;
2124 ENUMLOGFONTEXA lfA;
2125 NEWTEXTMETRICEXA tmA;
2127 logfontex_WtoA( (const ENUMLOGFONTEXW *)lf, &lfA );
2128 text_metric_ex_WtoA( (const NEWTEXTMETRICEXW *)tm, &tmA );
2129 return params->proc( (const LOGFONTA *)&lfA, (const TEXTMETRICA *)&tmA, type, params->lparam );
2132 /***********************************************************************
2133 * EnumFontFamiliesExA (GDI32.@)
2135 INT WINAPI EnumFontFamiliesExA( HDC hdc, LOGFONTA *lf, FONTENUMPROCA efproc,
2136 LPARAM lparam, DWORD flags )
2138 struct enum_proc_paramsWtoA param;
2139 LOGFONTW lfW, *plfW;
2141 if (lf)
2143 logfont_AtoW( lf, &lfW );
2144 plfW = &lfW;
2146 else plfW = NULL;
2148 param.lparam = lparam;
2149 param.proc = efproc;
2150 return EnumFontFamiliesExW( hdc, plfW, enum_proc_WtoA, (LPARAM)&param, flags );
2153 /***********************************************************************
2154 * EnumFontFamiliesA (GDI32.@)
2156 INT WINAPI EnumFontFamiliesA( HDC hdc, const char *family, FONTENUMPROCA efproc, LPARAM data )
2158 LOGFONTA lf;
2160 if (family)
2162 if (!*family) return 1;
2163 lstrcpynA( lf.lfFaceName, family, LF_FACESIZE );
2164 lf.lfCharSet = DEFAULT_CHARSET;
2165 lf.lfPitchAndFamily = 0;
2168 return EnumFontFamiliesExA( hdc, family ? &lf : NULL, efproc, data, 0 );
2171 /***********************************************************************
2172 * EnumFontFamiliesW (GDI32.@)
2174 INT WINAPI EnumFontFamiliesW( HDC hdc, const WCHAR *family, FONTENUMPROCW efproc, LPARAM data )
2176 LOGFONTW lf;
2178 if (family)
2180 if (!*family) return 1;
2181 lstrcpynW( lf.lfFaceName, family, LF_FACESIZE );
2182 lf.lfCharSet = DEFAULT_CHARSET;
2183 lf.lfPitchAndFamily = 0;
2186 return EnumFontFamiliesExW( hdc, family ? &lf : NULL, efproc, data, 0 );
2189 /***********************************************************************
2190 * EnumFontsA (GDI32.@)
2192 INT WINAPI EnumFontsA( HDC hdc, const char *name, FONTENUMPROCA efproc, LPARAM data )
2194 return EnumFontFamiliesA( hdc, name, efproc, data );
2197 /***********************************************************************
2198 * EnumFontsW (GDI32.@)
2200 INT WINAPI EnumFontsW( HDC hdc, const WCHAR *name, FONTENUMPROCW efproc, LPARAM data )
2202 return EnumFontFamiliesW( hdc, name, efproc, data );
2205 /***********************************************************************
2206 * CreateScalableFontResourceA (GDI32.@)
2208 BOOL WINAPI CreateScalableFontResourceA( DWORD hidden, const char *resource_file,
2209 const char *font_file, const char *current_path )
2211 WCHAR *resource_fileW = NULL;
2212 WCHAR *current_pathW = NULL;
2213 WCHAR *font_fileW = NULL;
2214 int len;
2215 BOOL ret;
2217 if (resource_file)
2219 len = MultiByteToWideChar( CP_ACP, 0, resource_file, -1, NULL, 0 );
2220 resource_fileW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2221 MultiByteToWideChar( CP_ACP, 0, resource_file, -1, resource_fileW, len );
2224 if (font_file)
2226 len = MultiByteToWideChar( CP_ACP, 0, font_file, -1, NULL, 0 );
2227 font_fileW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2228 MultiByteToWideChar( CP_ACP, 0, font_file, -1, font_fileW, len );
2231 if (current_path)
2233 len = MultiByteToWideChar( CP_ACP, 0, current_path, -1, NULL, 0 );
2234 current_pathW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2235 MultiByteToWideChar( CP_ACP, 0, current_path, -1, current_pathW, len );
2238 ret = CreateScalableFontResourceW( hidden, resource_fileW,
2239 font_fileW, current_pathW );
2241 HeapFree(GetProcessHeap(), 0, resource_fileW);
2242 HeapFree(GetProcessHeap(), 0, font_fileW);
2243 HeapFree(GetProcessHeap(), 0, current_pathW);
2244 return ret;
2247 /***********************************************************************
2248 * AddFontResourceA (GDI32.@)
2250 INT WINAPI AddFontResourceA( const char *str )
2252 return AddFontResourceExA( str, 0, NULL);
2255 /***********************************************************************
2256 * AddFontResourceW (GDI32.@)
2258 INT WINAPI AddFontResourceW( const WCHAR *str )
2260 return AddFontResourceExW( str, 0, NULL );
2263 /***********************************************************************
2264 * AddFontResourceExA (GDI32.@)
2266 INT WINAPI AddFontResourceExA( const char *str, DWORD fl, void *pdv )
2268 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
2269 LPWSTR strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2270 INT ret;
2272 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
2273 ret = AddFontResourceExW( strW, fl, pdv );
2274 HeapFree( GetProcessHeap(), 0, strW );
2275 return ret;
2278 /***********************************************************************
2279 * RemoveFontResourceA (GDI32.@)
2281 BOOL WINAPI RemoveFontResourceA( const char *str )
2283 return RemoveFontResourceExA( str, 0, 0 );
2286 /***********************************************************************
2287 * RemoveFontResourceW (GDI32.@)
2289 BOOL WINAPI RemoveFontResourceW( const WCHAR *str )
2291 return RemoveFontResourceExW( str, 0, 0 );
2294 /***********************************************************************
2295 * RemoveFontResourceExA (GDI32.@)
2297 BOOL WINAPI RemoveFontResourceExA( const char *str, DWORD fl, void *pdv )
2299 DWORD len = MultiByteToWideChar( CP_ACP, 0, str, -1, NULL, 0 );
2300 LPWSTR strW = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2301 INT ret;
2303 MultiByteToWideChar( CP_ACP, 0, str, -1, strW, len );
2304 ret = RemoveFontResourceExW( strW, fl, pdv );
2305 HeapFree( GetProcessHeap(), 0, strW );
2306 return ret;
2309 static void *map_file( const WCHAR *filename, LARGE_INTEGER *size )
2311 HANDLE file, mapping;
2312 void *ptr;
2314 file = CreateFileW( filename, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
2315 if (file == INVALID_HANDLE_VALUE) return NULL;
2317 if (!GetFileSizeEx( file, size ) || size->u.HighPart)
2319 CloseHandle( file );
2320 return NULL;
2323 mapping = CreateFileMappingW( file, NULL, PAGE_READONLY, 0, 0, NULL );
2324 CloseHandle( file );
2325 if (!mapping) return NULL;
2327 ptr = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, 0 );
2328 CloseHandle( mapping );
2330 return ptr;
2333 static void *find_resource( BYTE *ptr, WORD type, DWORD rsrc_off, DWORD size, DWORD *len )
2335 WORD align, type_id, count;
2336 DWORD res_off;
2338 if (size < rsrc_off + 10) return NULL;
2339 align = *(WORD *)(ptr + rsrc_off);
2340 rsrc_off += 2;
2341 type_id = *(WORD *)(ptr + rsrc_off);
2342 while (type_id && type_id != type)
2344 count = *(WORD *)(ptr + rsrc_off + 2);
2345 rsrc_off += 8 + count * 12;
2346 if (size < rsrc_off + 8) return NULL;
2347 type_id = *(WORD *)(ptr + rsrc_off);
2349 if (!type_id) return NULL;
2350 count = *(WORD *)(ptr + rsrc_off + 2);
2351 if (size < rsrc_off + 8 + count * 12) return NULL;
2352 res_off = *(WORD *)(ptr + rsrc_off + 8) << align;
2353 *len = *(WORD *)(ptr + rsrc_off + 10) << align;
2354 if (size < res_off + *len) return NULL;
2355 return ptr + res_off;
2358 static WCHAR *get_scalable_filename( const WCHAR *res, BOOL *hidden )
2360 LARGE_INTEGER size;
2361 BYTE *ptr = map_file( res, &size );
2362 const IMAGE_DOS_HEADER *dos;
2363 const IMAGE_OS2_HEADER *ne;
2364 WORD *fontdir;
2365 char *data;
2366 WCHAR *name = NULL;
2367 DWORD len;
2369 if (!ptr) return NULL;
2371 if (size.u.LowPart < sizeof( *dos )) goto fail;
2372 dos = (const IMAGE_DOS_HEADER *)ptr;
2373 if (dos->e_magic != IMAGE_DOS_SIGNATURE) goto fail;
2374 if (size.u.LowPart < dos->e_lfanew + sizeof( *ne )) goto fail;
2375 ne = (const IMAGE_OS2_HEADER *)(ptr + dos->e_lfanew);
2377 fontdir = find_resource( ptr, 0x8007, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
2378 if (!fontdir) goto fail;
2379 *hidden = (fontdir[35] & 0x80) != 0; /* fontdir->dfType */
2381 data = find_resource( ptr, 0x80cc, dos->e_lfanew + ne->ne_rsrctab, size.u.LowPart, &len );
2382 if (!data) goto fail;
2383 if (!memchr( data, 0, len )) goto fail;
2385 len = MultiByteToWideChar( CP_ACP, 0, data, -1, NULL, 0 );
2386 name = HeapAlloc( GetProcessHeap(), 0, len * sizeof(WCHAR) );
2387 if (name) MultiByteToWideChar( CP_ACP, 0, data, -1, name, len );
2389 fail:
2390 UnmapViewOfFile( ptr );
2391 return name;
2394 static int add_font_resource( const WCHAR *str, DWORD flags, void *dv )
2396 UNICODE_STRING nt_name;
2397 int ret;
2399 if (!RtlDosPathNameToNtPathName_U( str, &nt_name, NULL, NULL )) return 0;
2400 ret = NtGdiAddFontResourceW( nt_name.Buffer, nt_name.Length / sizeof(WCHAR) + 1,
2401 1, flags, 0, dv );
2402 RtlFreeUnicodeString( &nt_name );
2403 if (!ret && !wcschr( str, '\\' ))
2405 /* try as system font */
2406 ret = NtGdiAddFontResourceW( str, lstrlenW( str ) + 1, 1, flags, 0, dv );
2408 return ret;
2411 /***********************************************************************
2412 * AddFontResourceExW (GDI32.@)
2414 INT WINAPI AddFontResourceExW( const WCHAR *str, DWORD flags, void *dv )
2416 WCHAR *filename = NULL;
2417 BOOL hidden;
2418 INT ret;
2420 if ((ret = add_font_resource( str, flags, dv ))) return ret;
2422 if (!(filename = get_scalable_filename( str, &hidden ))) return 0;
2423 if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
2424 ret = add_font_resource( filename, flags, dv );
2425 HeapFree( GetProcessHeap(), 0, filename );
2426 return ret;
2429 static int remove_font_resource( const WCHAR *str, DWORD flags, void *dv )
2431 UNICODE_STRING nt_name;
2432 int ret;
2434 if (!RtlDosPathNameToNtPathName_U( str, &nt_name, NULL, NULL )) return 0;
2435 ret = NtGdiRemoveFontResourceW( nt_name.Buffer, nt_name.Length / sizeof(WCHAR) + 1,
2436 1, flags, 0, dv );
2437 RtlFreeUnicodeString( &nt_name );
2438 if (!ret && !wcschr( str, '\\' ))
2440 /* try as system font */
2441 ret = NtGdiRemoveFontResourceW( str, lstrlenW( str ) + 1, 1, flags, 0, dv );
2443 return ret;
2446 /***********************************************************************
2447 * RemoveFontResourceExW (GDI32.@)
2449 BOOL WINAPI RemoveFontResourceExW( const WCHAR *str, DWORD flags, void *dv )
2451 WCHAR *filename = NULL;
2452 BOOL hidden;
2453 INT ret;
2455 if ((ret = remove_font_resource( str, flags, dv ))) return ret;
2457 if (!(filename = get_scalable_filename( str, &hidden ))) return 0;
2458 if (hidden) flags |= FR_PRIVATE | FR_NOT_ENUM;
2459 ret = remove_font_resource( filename, flags, dv );
2460 HeapFree( GetProcessHeap(), 0, filename );
2461 return ret;
2464 /***********************************************************************
2465 * GetFontResourceInfoW (GDI32.@)
2467 BOOL WINAPI GetFontResourceInfoW( const WCHAR *str, DWORD *size, void *buffer, DWORD type )
2469 FIXME( "%s %p(%ld) %p %ld\n", debugstr_w(str), size, size ? *size : 0, buffer, type );
2470 return FALSE;
2473 /***********************************************************************
2474 * AddFontMemResourceEx (GDI32.@)
2476 HANDLE WINAPI AddFontMemResourceEx( void *ptr, DWORD size, void *dv, DWORD *count )
2478 return NtGdiAddFontMemResourceEx( ptr, size, dv, 0, count );
2481 #define NE_FFLAGS_LIBMODULE 0x8000
2482 #define NE_OSFLAGS_WINDOWS 0x02
2484 static const char dos_string[0x40] = "This is a TrueType resource file";
2485 static const char FONTRES[] = {'F','O','N','T','R','E','S',':'};
2487 #include <pshpack1.h>
2488 struct fontdir
2490 WORD num_of_resources;
2491 WORD res_id;
2492 WORD dfVersion;
2493 DWORD dfSize;
2494 CHAR dfCopyright[60];
2495 WORD dfType;
2496 WORD dfPoints;
2497 WORD dfVertRes;
2498 WORD dfHorizRes;
2499 WORD dfAscent;
2500 WORD dfInternalLeading;
2501 WORD dfExternalLeading;
2502 BYTE dfItalic;
2503 BYTE dfUnderline;
2504 BYTE dfStrikeOut;
2505 WORD dfWeight;
2506 BYTE dfCharSet;
2507 WORD dfPixWidth;
2508 WORD dfPixHeight;
2509 BYTE dfPitchAndFamily;
2510 WORD dfAvgWidth;
2511 WORD dfMaxWidth;
2512 BYTE dfFirstChar;
2513 BYTE dfLastChar;
2514 BYTE dfDefaultChar;
2515 BYTE dfBreakChar;
2516 WORD dfWidthBytes;
2517 DWORD dfDevice;
2518 DWORD dfFace;
2519 DWORD dfReserved;
2520 CHAR szFaceName[LF_FACESIZE];
2522 #include <poppack.h>
2524 #include <pshpack2.h>
2526 struct ne_typeinfo
2528 WORD type_id;
2529 WORD count;
2530 DWORD res;
2533 struct ne_nameinfo
2535 WORD off;
2536 WORD len;
2537 WORD flags;
2538 WORD id;
2539 DWORD res;
2542 struct rsrc_tab
2544 WORD align;
2545 struct ne_typeinfo fontdir_type;
2546 struct ne_nameinfo fontdir_name;
2547 struct ne_typeinfo scalable_type;
2548 struct ne_nameinfo scalable_name;
2549 WORD end_of_rsrc;
2550 BYTE fontdir_res_name[8];
2553 #include <poppack.h>
2555 static BOOL create_fot( const WCHAR *resource, const WCHAR *font_file, const struct fontdir *fontdir )
2557 BOOL ret = FALSE;
2558 HANDLE file;
2559 DWORD size, written;
2560 BYTE *ptr, *start;
2561 BYTE import_name_len, res_name_len, non_res_name_len, font_file_len;
2562 char *font_fileA, *last_part, *ext;
2563 IMAGE_DOS_HEADER dos;
2564 IMAGE_OS2_HEADER ne =
2566 IMAGE_OS2_SIGNATURE, 5, 1, 0, 0, 0, NE_FFLAGS_LIBMODULE, 0,
2567 0, 0, 0, 0, 0, 0,
2568 0, sizeof(ne), sizeof(ne), 0, 0, 0, 0,
2569 0, 4, 2, NE_OSFLAGS_WINDOWS, 0, 0, 0, 0, 0x300
2571 struct rsrc_tab rsrc_tab =
2574 { 0x8007, 1, 0 },
2575 { 0, 0, 0x0c50, 0x2c, 0 },
2576 { 0x80cc, 1, 0 },
2577 { 0, 0, 0x0c50, 0x8001, 0 },
2579 { 7,'F','O','N','T','D','I','R'}
2582 memset( &dos, 0, sizeof(dos) );
2583 dos.e_magic = IMAGE_DOS_SIGNATURE;
2584 dos.e_lfanew = sizeof(dos) + sizeof(dos_string);
2586 /* import name is last part\0, resident name is last part without extension
2587 non-resident name is "FONTRES:" + lfFaceName */
2589 font_file_len = WideCharToMultiByte( CP_ACP, 0, font_file, -1, NULL, 0, NULL, NULL );
2590 font_fileA = HeapAlloc( GetProcessHeap(), 0, font_file_len );
2591 WideCharToMultiByte( CP_ACP, 0, font_file, -1, font_fileA, font_file_len, NULL, NULL );
2593 last_part = strrchr( font_fileA, '\\' );
2594 if (last_part) last_part++;
2595 else last_part = font_fileA;
2596 import_name_len = strlen( last_part ) + 1;
2598 ext = strchr( last_part, '.' );
2599 if (ext) res_name_len = ext - last_part;
2600 else res_name_len = import_name_len - 1;
2602 non_res_name_len = sizeof( FONTRES ) + strlen( fontdir->szFaceName );
2604 ne.ne_cbnrestab = 1 + non_res_name_len + 2 + 1; /* len + string + (WORD) ord_num + 1 byte eod */
2605 ne.ne_restab = ne.ne_rsrctab + sizeof(rsrc_tab);
2606 ne.ne_modtab = ne.ne_imptab = ne.ne_restab + 1 + res_name_len + 2 + 3; /* len + string + (WORD) ord_num + 3 bytes eod */
2607 ne.ne_enttab = ne.ne_imptab + 1 + import_name_len; /* len + string */
2608 ne.ne_cbenttab = 2;
2609 ne.ne_nrestab = ne.ne_enttab + ne.ne_cbenttab + 2 + dos.e_lfanew; /* there are 2 bytes of 0 after entry tab */
2611 rsrc_tab.scalable_name.off = (ne.ne_nrestab + ne.ne_cbnrestab + 0xf) >> 4;
2612 rsrc_tab.scalable_name.len = (font_file_len + 0xf) >> 4;
2613 rsrc_tab.fontdir_name.off = rsrc_tab.scalable_name.off + rsrc_tab.scalable_name.len;
2614 rsrc_tab.fontdir_name.len = (fontdir->dfSize + 0xf) >> 4;
2616 size = (rsrc_tab.fontdir_name.off + rsrc_tab.fontdir_name.len) << 4;
2617 start = ptr = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, size );
2619 if (!ptr)
2621 HeapFree( GetProcessHeap(), 0, font_fileA );
2622 return FALSE;
2625 memcpy( ptr, &dos, sizeof(dos) );
2626 memcpy( ptr + sizeof(dos), dos_string, sizeof(dos_string) );
2627 memcpy( ptr + dos.e_lfanew, &ne, sizeof(ne) );
2629 ptr = start + dos.e_lfanew + ne.ne_rsrctab;
2630 memcpy( ptr, &rsrc_tab, sizeof(rsrc_tab) );
2632 ptr = start + dos.e_lfanew + ne.ne_restab;
2633 *ptr++ = res_name_len;
2634 memcpy( ptr, last_part, res_name_len );
2636 ptr = start + dos.e_lfanew + ne.ne_imptab;
2637 *ptr++ = import_name_len;
2638 memcpy( ptr, last_part, import_name_len );
2640 ptr = start + ne.ne_nrestab;
2641 *ptr++ = non_res_name_len;
2642 memcpy( ptr, FONTRES, sizeof(FONTRES) );
2643 memcpy( ptr + sizeof(FONTRES), fontdir->szFaceName, strlen( fontdir->szFaceName ) );
2645 ptr = start + (rsrc_tab.scalable_name.off << 4);
2646 memcpy( ptr, font_fileA, font_file_len );
2648 ptr = start + (rsrc_tab.fontdir_name.off << 4);
2649 memcpy( ptr, fontdir, fontdir->dfSize );
2651 file = CreateFileW( resource, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL );
2652 if (file != INVALID_HANDLE_VALUE)
2654 if (WriteFile( file, start, size, &written, NULL ) && written == size)
2655 ret = TRUE;
2656 CloseHandle( file );
2659 HeapFree( GetProcessHeap(), 0, start );
2660 HeapFree( GetProcessHeap(), 0, font_fileA );
2662 return ret;
2665 /***********************************************************************
2666 * CreateScalableFontResourceW (GDI32.@)
2668 BOOL WINAPI CreateScalableFontResourceW( DWORD hidden, const WCHAR *resource_file,
2669 const WCHAR *font_file, const WCHAR *font_path )
2671 struct fontdir fontdir = { 0 };
2672 UNICODE_STRING nt_name;
2673 OUTLINETEXTMETRICW otm;
2674 WCHAR path[MAX_PATH];
2675 BOOL ret;
2677 TRACE("(%ld, %s, %s, %s)\n", hidden, debugstr_w(resource_file),
2678 debugstr_w(font_file), debugstr_w(font_path) );
2680 if (!font_file) goto done;
2681 if (font_path && font_path[0])
2683 int len = lstrlenW( font_path ) + lstrlenW( font_file ) + 2;
2684 if (len > MAX_PATH) goto done;
2685 lstrcpynW( path, font_path, MAX_PATH );
2686 lstrcatW( path, L"\\" );
2687 lstrcatW( path, font_file );
2688 if (!RtlDosPathNameToNtPathName_U( path, &nt_name, NULL, NULL )) goto done;
2690 else if (!RtlDosPathNameToNtPathName_U( font_file, &nt_name, NULL, NULL )) goto done;
2691 ret = __wine_get_file_outline_text_metric( nt_name.Buffer, &otm );
2692 RtlFreeUnicodeString( &nt_name );
2693 if (!ret) goto done;
2694 if (!(otm.otmTextMetrics.tmPitchAndFamily & TMPF_TRUETYPE)) goto done;
2696 fontdir.num_of_resources = 1;
2697 fontdir.res_id = 0;
2698 fontdir.dfVersion = 0x200;
2699 fontdir.dfSize = sizeof(fontdir);
2700 strcpy( fontdir.dfCopyright, "Wine fontdir" );
2701 fontdir.dfType = 0x4003; /* 0x0080 set if private */
2702 fontdir.dfPoints = otm.otmEMSquare;
2703 fontdir.dfVertRes = 72;
2704 fontdir.dfHorizRes = 72;
2705 fontdir.dfAscent = otm.otmTextMetrics.tmAscent;
2706 fontdir.dfInternalLeading = otm.otmTextMetrics.tmInternalLeading;
2707 fontdir.dfExternalLeading = otm.otmTextMetrics.tmExternalLeading;
2708 fontdir.dfItalic = otm.otmTextMetrics.tmItalic;
2709 fontdir.dfUnderline = otm.otmTextMetrics.tmUnderlined;
2710 fontdir.dfStrikeOut = otm.otmTextMetrics.tmStruckOut;
2711 fontdir.dfWeight = otm.otmTextMetrics.tmWeight;
2712 fontdir.dfCharSet = otm.otmTextMetrics.tmCharSet;
2713 fontdir.dfPixWidth = 0;
2714 fontdir.dfPixHeight = otm.otmTextMetrics.tmHeight;
2715 fontdir.dfPitchAndFamily = otm.otmTextMetrics.tmPitchAndFamily;
2716 fontdir.dfAvgWidth = otm.otmTextMetrics.tmAveCharWidth;
2717 fontdir.dfMaxWidth = otm.otmTextMetrics.tmMaxCharWidth;
2718 fontdir.dfFirstChar = otm.otmTextMetrics.tmFirstChar;
2719 fontdir.dfLastChar = otm.otmTextMetrics.tmLastChar;
2720 fontdir.dfDefaultChar = otm.otmTextMetrics.tmDefaultChar;
2721 fontdir.dfBreakChar = otm.otmTextMetrics.tmBreakChar;
2722 fontdir.dfWidthBytes = 0;
2723 fontdir.dfDevice = 0;
2724 fontdir.dfFace = FIELD_OFFSET( struct fontdir, szFaceName );
2725 fontdir.dfReserved = 0;
2726 WideCharToMultiByte( CP_ACP, 0, (WCHAR *)otm.otmpFamilyName, -1,
2727 fontdir.szFaceName, LF_FACESIZE, NULL, NULL );
2729 if (hidden) fontdir.dfType |= 0x80;
2730 return create_fot( resource_file, font_file, &fontdir );
2732 done:
2733 SetLastError( ERROR_INVALID_PARAMETER );
2734 return FALSE;
2737 static const CHARSETINFO charset_info[] =
2739 { ANSI_CHARSET, 1252, { {0}, { FS_LATIN1 }}},
2740 { EASTEUROPE_CHARSET, 1250, { {0}, { FS_LATIN2 }}},
2741 { RUSSIAN_CHARSET, 1251, { {0}, { FS_CYRILLIC }}},
2742 { GREEK_CHARSET, 1253, { {0}, { FS_GREEK }}},
2743 { TURKISH_CHARSET, 1254, { {0}, { FS_TURKISH }}},
2744 { HEBREW_CHARSET, 1255, { {0}, { FS_HEBREW }}},
2745 { ARABIC_CHARSET, 1256, { {0}, { FS_ARABIC }}},
2746 { BALTIC_CHARSET, 1257, { {0}, { FS_BALTIC }}},
2747 { VIETNAMESE_CHARSET, 1258, { {0}, { FS_VIETNAMESE }}},
2748 { THAI_CHARSET, 874, { {0}, { FS_THAI }}},
2749 { SHIFTJIS_CHARSET, 932, { {0}, { FS_JISJAPAN }}},
2750 { GB2312_CHARSET, 936, { {0}, { FS_CHINESESIMP }}},
2751 { HANGEUL_CHARSET, 949, { {0}, { FS_WANSUNG }}},
2752 { CHINESEBIG5_CHARSET, 950, { {0}, { FS_CHINESETRAD }}},
2753 { JOHAB_CHARSET, 1361, { {0}, { FS_JOHAB }}},
2754 { 254, CP_UTF8, { {0}, { 0x04000000 }}},
2755 { SYMBOL_CHARSET, CP_SYMBOL, { {0}, { FS_SYMBOL }}}
2758 /***********************************************************************
2759 * TranslateCharsetInfo (GDI32.@)
2761 * Fills a CHARSETINFO structure for a character set, code page, or
2762 * font. This allows making the correspondence between different labels
2763 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2764 * of the same encoding.
2766 * Only one codepage will be set in cs->fs. If TCI_SRCFONTSIG is used,
2767 * only one codepage should be set in *src.
2769 * if flags == TCI_SRCFONTSIG: src is a pointer to fsCsb of a FONTSIGNATURE
2770 * if flags == TCI_SRCCHARSET: src is a character set value
2771 * if flags == TCI_SRCCODEPAGE: src is a code page value
2773 BOOL WINAPI TranslateCharsetInfo( DWORD *src, CHARSETINFO *cs, DWORD flags )
2775 unsigned int i;
2777 switch (flags)
2779 case TCI_SRCFONTSIG:
2780 for (i = 0; i < ARRAY_SIZE(charset_info); i++)
2781 if (charset_info[i].fs.fsCsb[0] & src[0]) goto found;
2782 return FALSE;
2783 case TCI_SRCCODEPAGE:
2784 for (i = 0; i < ARRAY_SIZE(charset_info); i++)
2785 if (PtrToUlong(src) == charset_info[i].ciACP) goto found;
2786 return FALSE;
2787 case TCI_SRCCHARSET:
2788 for (i = 0; i < ARRAY_SIZE(charset_info); i++)
2789 if (PtrToUlong(src) == charset_info[i].ciCharset) goto found;
2790 return FALSE;
2791 default:
2792 return FALSE;
2794 found:
2795 *cs = charset_info[i];
2796 return TRUE;