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
55 #include "wine/debug.h"
56 #include "gdi_private.h"
59 WINE_DEFAULT_DEBUG_CHANNEL(bidi
);
61 /* HELPER FUNCTIONS AND DECLARATIONS */
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.
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 ------------------------------------------------------------------------*/
93 /* ON MUST be zero, code relies on ON = N = 0 */
94 ON
= 0, /* Other Neutral */
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 %) */
106 BN
, /* Boundary neutral (type of RLE etc after explicit levels) */
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 */
120 LRI
, /* Isolate formatting characters new with 6.3 */
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
)
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
)
150 for (; i
>= iStart
- cval
; i
--)
156 /* THE PARAGRAPH LEVEL */
158 /*------------------------------------------------------------------------
159 Function: resolveParagraphs
161 Resolves the input strings into blocks over which the algorithm
164 Implements Rule P1 of the Unicode Bidi Algorithm
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 */
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
)
190 /*------------------------------------------------------------------------
191 Function: resolveLines
193 Breaks a paragraph into lines
195 Input: Array of line break flags
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 */
210 for(; ich
< cch
; ich
++)
212 if (pszInput
[ich
] == (WCHAR
)'\n' || (pbrk
&& pbrk
[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
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
)
242 BYTE oldlevel
= baselevel
;
245 for (; ich
< cch
; ich
++)
250 cchrun
= 0; /* any other character breaks the run */
266 plevel
[ich
] = oldlevel
;
272 /* reset levels for WS before eot */
273 SetDeferredRun(plevel
, cchrun
, ich
, baselevel
);
275 plevel
[ich
] = baselevel
;
278 oldlevel
= plevel
[ich
];
280 /* reset level before eot */
281 SetDeferredRun(plevel
, cchrun
, ich
, baselevel
);
284 /*------------------------------------------------------------------------
287 Implements the Line-by-Line phases of the Unicode Bidi Algorithm
289 Input: Count of characters
290 Array of character directions
295 ------------------------------------------------------------------------*/
296 static void BidiLines(int baselevel
, LPWSTR pszOutLine
, LPCWSTR pszLine
, const WORD
* pclsLine
,
297 BYTE
* plevelLine
, int cchPara
, const BOOL
* pbrk
)
303 run
= HeapAlloc(GetProcessHeap(), 0, cchPara
* sizeof(int));
306 WARN("Out of memory\n");
312 /* break lines at LS */
313 cchLine
= resolveLines(pszLine
, pbrk
, cchPara
);
315 /* resolve whitespace */
316 resolveWhitespace(baselevel
, pclsLine
, plevelLine
, cchLine
);
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
];
328 plevelLine
+= cchLine
;
329 pbrk
+= pbrk
? cchLine
: 0;
336 HeapFree(GetProcessHeap(), 0, run
);
339 /*************************************************************
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
;
359 BOOL is_complex
, ret
= FALSE
;
363 SCRIPT_CONTROL Control
;
365 SCRIPT_ITEM
*pItems
= NULL
;
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
));
383 if (!(dwFlags
& GCP_REORDER
))
385 FIXME("Asked to reorder without reorder flag set\n");
389 if (lpOutString
&& uCountOut
< uCount
)
391 FIXME("lpOutString too small\n");
395 chartype
= HeapAlloc(GetProcessHeap(), 0, uCount
* sizeof(WORD
));
398 WARN("Out of memory\n");
403 memcpy(lpOutString
, lpString
, uCount
* sizeof(WCHAR
));
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))
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
)
421 classify(lpString
, chartype
, uCount
);
422 for (i
= 0; i
< uCount
; i
++)
434 HeapFree(GetProcessHeap(), 0, chartype
);
437 for (i
= 0; i
< uCount
; i
++)
444 levels
= HeapAlloc(GetProcessHeap(), 0, uCount
* sizeof(BYTE
));
447 WARN("Out of memory\n");
452 pItems
= HeapAlloc(GetProcessHeap(),0, maxItems
* sizeof(SCRIPT_ITEM
));
455 WARN("Out of memory\n");
461 cMaxGlyphs
= 1.5 * uCount
+ 16;
462 run_glyphs
= HeapAlloc(GetProcessHeap(),0,sizeof(WORD
) * cMaxGlyphs
);
465 WARN("Out of memory\n");
468 pwLogClust
= HeapAlloc(GetProcessHeap(),0,sizeof(WORD
) * uCount
);
471 WARN("Out of memory\n");
474 psva
= HeapAlloc(GetProcessHeap(),0,sizeof(SCRIPT_VISATTR
) * cMaxGlyphs
);
477 WARN("Out of memory\n");
484 while (done
< uCount
)
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
)
496 case ON
: chartype
[j
] = NI
;
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;
513 else if (chartype
[j
] == R
|| chartype
[j
] == AL
)
515 State
.uBidiLevel
= 1;
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);
526 WARN("Out of memory\n");
531 res
= ScriptItemize(lpString
+ done
, i
, maxItems
, &Control
, &State
, pItems
, &nItems
);
534 if (lpOutString
|| lpOrder
)
535 for (j
= 0; j
< nItems
; j
++)
538 for (k
= pItems
[j
].iCharPos
; k
< pItems
[j
+1].iCharPos
; k
++)
539 levels
[k
] = pItems
[j
].a
.s
.uBidiLevel
;
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);
554 for (j
= lastgood
= 0; j
< i
; ++j
)
555 if (levels
[j
] != levels
[lastgood
])
558 if (odd(levels
[lastgood
]))
559 for (k
= j
; k
>= lastgood
; --k
)
560 lpOrder
[done
+ k
] = done
+ j
- k
;
562 for (k
= lastgood
; k
<= j
; ++k
)
563 lpOrder
[done
+ k
] = done
+ k
;
566 if (odd(levels
[lastgood
]))
567 for (k
= j
- 1; k
>= lastgood
; --k
)
568 lpOrder
[done
+ k
] = done
+ j
- 1 - k
;
570 for (k
= lastgood
; k
< j
; ++k
)
571 lpOrder
[done
+ k
] = done
+ k
;
574 if (lpGlyphs
&& doGlyphs
)
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
);
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
++)
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
);
616 run_glyphs
= new_run_glyphs
;
621 run_glyphs
= new_run_glyphs
;
624 res
= ScriptShape(hDC
, &psc
, lpString
+ done
+ curItem
->iCharPos
, cChars
, cMaxGlyphs
, &curItem
->a
, run_glyphs
, pwLogClust
, psva
, &cOutGlyphs
);
628 if (res
== USP_E_SCRIPT_NOT_IN_FONT
)
629 TRACE("Unable to shape with currently selected font\n");
631 FIXME("Unable to shape string (%lx)\n",res
);
634 HeapFree(GetProcessHeap(), 0, *lpGlyphs
);
641 new_glyphs
= HeapReAlloc(GetProcessHeap(), 0, *lpGlyphs
, sizeof(**lpGlyphs
) * (glyph_i
+ cOutGlyphs
));
643 new_glyphs
= HeapAlloc(GetProcessHeap(), 0, sizeof(**lpGlyphs
) * (glyph_i
+ cOutGlyphs
));
646 WARN("Out of memory\n");
647 HeapFree(GetProcessHeap(), 0, runOrder
);
648 HeapFree(GetProcessHeap(), 0, visOrder
);
649 HeapFree(GetProcessHeap(), 0, *lpGlyphs
);
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
);
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
);
680 /***********************************************************************
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
692 static WCHAR
*text_mbtowc( HDC hdc
, const char *str
, INT count
, INT
*plenW
, UINT
*ret_cp
)
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
;
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 );
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
,
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
)
845 logfont_AtoW( lfA
, &lfW
);
846 return CreateFontIndirectW( &lfW
);
849 /***********************************************************************
850 * CreateFontIndirectW (GDI32.@)
852 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*lf
)
854 ENUMLOGFONTEXDVW exdv
;
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
)
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
;
890 lstrcpynA( logfont
.lfFaceName
, name
, sizeof(logfont
.lfFaceName
) );
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
)
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
;
922 lstrcpynW( logfont
.lfFaceName
, name
, ARRAY_SIZE(logfont
.lfFaceName
) );
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
)
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
))
945 if (!(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0)
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
;
959 flags
|= ETO_GLYPH_INDEX
;
960 count
= glyphs_count
;
965 ret
= NtGdiExtTextOutW( hdc
, x
, y
, flags
, rect
, str
, count
, dx
, 0 );
967 HeapFree( GetProcessHeap(), 0, glyphs
);
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
)
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
);
992 unsigned int i
= 0, j
= 0;
994 /* allocate enough for a ETO_PDY */
995 dxW
= HeapAlloc( GetProcessHeap(), 0, 2 * wlen
* sizeof(INT
) );
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];
1006 dxW
[j
++] = dx
[i
] + dx
[i
+ 1];
1011 if (flags
& ETO_PDY
)
1013 dxW
[j
++] = dx
[i
* 2];
1014 dxW
[j
++] = dx
[i
* 2 + 1];
1023 ret
= ExtTextOutW( hdc
, x
, y
, flags
, rect
, p
, wlen
, dxW
);
1025 HeapFree( GetProcessHeap(), 0, p
);
1026 HeapFree( GetProcessHeap(), 0, dxW
);
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
))
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
))
1069 static int kern_pair( const KERNINGPAIR
*kern
, int count
, WCHAR c1
, WCHAR c2
)
1073 for (i
= 0; i
< count
; i
++)
1075 if (kern
[i
].wFirst
== c1
&& kern
[i
].wSecond
== c2
)
1076 return kern
[i
].iKernAmount
;
1082 static int *kern_string( HDC hdc
, const WCHAR
*str
, int len
, int *kern_total
)
1084 unsigned int i
, count
;
1085 KERNINGPAIR
*kern
= NULL
;
1090 ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(*ret
) );
1091 if (!ret
) return NULL
;
1093 count
= NtGdiGetKerningPairs( hdc
, 0, NULL
);
1096 kern
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*kern
) );
1099 HeapFree( GetProcessHeap(), 0, ret
);
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
);
1118 /*************************************************************************
1119 * GetCharacterPlacementW (GDI32.@)
1121 * Retrieve information about a string. This includes the width, reordering,
1122 * Glyphing and so on.
1126 * The width and height of the string if successful, 0 if failed.
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;
1144 TRACE("%s, %d, %d, 0x%08lx\n", debugstr_wn(str
, count
), count
, max_extent
, flags
);
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
;
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
);
1195 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1200 /* FIXME: Will use the placement chars */
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
)
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
);
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
;
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
);
1258 ret
= GetCharacterPlacementW( hdc
, strW
, countW
, max_extent
, NULL
, flags
);
1259 HeapFree( GetProcessHeap(), 0, strW
);
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
);
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
);
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. */
1306 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1307 HeapFree( GetProcessHeap(), 0, nameW
);
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
)
1348 if (count
< 0 || max_ext
< -1) return FALSE
;
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
);
1360 INT n
= nfit
? *nfit
: wlen
;
1362 for (i
= 0, j
= 0; i
< n
; i
++, j
++)
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
);
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
)
1429 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1430 text_metric_WtoA( &tm32
, metrics
);
1434 /***********************************************************************
1435 * GetOutlineTextMetricsA (GDI32.@)
1437 * Gets metrics for TrueType fonts.
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
;
1447 OUTLINETEXTMETRICW
*otmW
= (OUTLINETEXTMETRICW
*)buf
;
1448 OUTLINETEXTMETRICA
*output
= otm
;
1451 if ((ret
= GetOutlineTextMetricsW( hdc
, 0, NULL
)) == 0) return 0;
1452 if (ret
> sizeof(buf
) && !(otmW
= HeapAlloc( GetProcessHeap(), 0, ret
)))
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
);
1481 TRACE( "needed = %d\n", needed
);
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
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
);
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
);
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
);
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
);
1561 else output
->otmpFullName
= 0;
1563 assert( left
== 0 );
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 */
1602 if (otmW
!= (OUTLINETEXTMETRICW
*)buf
)
1603 HeapFree(GetProcessHeap(), 0, otmW
);
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;
1635 mbcp
= GdiGetCodePage( hdc
);
1645 if ((first
^ last
) > 0xff)
1655 if (!(str
= HeapAlloc( GetProcessHeap(), 0, count
* 2 + 1 )))
1658 for (i
= 0, c
= first
; c
<= last
; i
++, c
++)
1662 str
[i
++] = (BYTE
)(c
>> 8);
1663 if (c
<= 0xff && IsDBCSLeadByteEx( mbcp
, c
))
1664 str
[i
] = 0x1f; /* FIXME: use default character */
1673 wstr
= text_mbtowc( hdc
, str
, i
, ret_len
, NULL
);
1674 HeapFree( GetProcessHeap(), 0, str
);
1678 /***********************************************************************
1679 * GetCharWidthA (GDI32.@)
1680 * GetCharWidth32A (GDI32.@)
1682 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT first
, UINT last
, INT
*buffer
)
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
);
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
)
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
);
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
)
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
);
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
)
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
);
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
,
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
))
1802 cp
= GdiGetCodePage( hdc
);
1803 if (IsDBCSLeadByteEx( cp
, ch
>> 8 ))
1806 mbchs
[0] = (ch
& 0xff00) >> 8;
1807 mbchs
[1] = (ch
& 0xff);
1812 mbchs
[0] = ch
& 0xff;
1815 MultiByteToWideChar(cp
, 0, mbchs
, len
, &wChar
, 1 );
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
;
1841 if (!count
&& kern_pairA
)
1843 SetLastError( ERROR_INVALID_PARAMETER
);
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
);
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
++)
1869 if (!WideCharToMultiByte( cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
1872 if (!WideCharToMultiByte( cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
1875 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
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
;
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
;
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
)
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
;
1942 /*************************************************************************
1943 * GetGlyphIndicesA (GDI32.@)
1945 DWORD WINAPI
GetGlyphIndicesA( HDC hdc
, const char *str
, INT count
, WORD
*indices
, DWORD flags
)
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
);
1959 /***********************************************************************
1960 * GetAspectRatioFilterEx (GDI32.@)
1962 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, SIZE
*aspect_ratio
)
1964 FIXME( "(%p, %p): stub\n", hdc
, aspect_ratio
);
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.
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
)
1994 if (metric
&& !GetTextMetricsW( hdc
, metric
)) return 0;
1996 if (!GetTextExtentPointW( hdc
, L
"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
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
);
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
;
2047 static void load_script_name( UINT id
, WCHAR buffer
[LF_FACESIZE
] )
2054 id
+= IDS_FIRST_SCRIPT
;
2056 rsrc
= FindResourceW( gdi32_module
, (LPCWSTR
)(ULONG_PTR
)((id
>> 4) + 1), (LPCWSTR
)6 /*RT_STRING*/ );
2058 hMem
= LoadResource( gdi32_module
, rsrc
);
2061 p
= LockResource( hMem
);
2063 while (id
--) p
+= *p
+ 1;
2065 i
= min( LF_FACESIZE
- 1, *p
);
2066 memcpy( buffer
, p
+ 1, i
* sizeof(WCHAR
) );
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;
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
))
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
);
2114 struct enum_proc_paramsWtoA
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
;
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
;
2143 logfont_AtoW( lf
, &lfW
);
2148 param
.lparam
= lparam
;
2149 param
.proc
= efproc
;
2150 return EnumFontFamiliesExW( hdc
, plfW
, enum_proc_WtoA
, (LPARAM
)¶m
, flags
);
2153 /***********************************************************************
2154 * EnumFontFamiliesA (GDI32.@)
2156 INT WINAPI
EnumFontFamiliesA( HDC hdc
, const char *family
, FONTENUMPROCA efproc
, LPARAM data
)
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
)
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
;
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
);
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
);
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
);
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
) );
2272 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
2273 ret
= AddFontResourceExW( strW
, fl
, pdv
);
2274 HeapFree( GetProcessHeap(), 0, strW
);
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
) );
2303 MultiByteToWideChar( CP_ACP
, 0, str
, -1, strW
, len
);
2304 ret
= RemoveFontResourceExW( strW
, fl
, pdv
);
2305 HeapFree( GetProcessHeap(), 0, strW
);
2309 static void *map_file( const WCHAR
*filename
, LARGE_INTEGER
*size
)
2311 HANDLE file
, mapping
;
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
);
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
);
2333 static void *find_resource( BYTE
*ptr
, WORD type
, DWORD rsrc_off
, DWORD size
, DWORD
*len
)
2335 WORD align
, type_id
, count
;
2338 if (size
< rsrc_off
+ 10) return NULL
;
2339 align
= *(WORD
*)(ptr
+ rsrc_off
);
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
)
2361 BYTE
*ptr
= map_file( res
, &size
);
2362 const IMAGE_DOS_HEADER
*dos
;
2363 const IMAGE_OS2_HEADER
*ne
;
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
);
2390 UnmapViewOfFile( ptr
);
2394 static int add_font_resource( const WCHAR
*str
, DWORD flags
, void *dv
)
2396 UNICODE_STRING nt_name
;
2399 if (!RtlDosPathNameToNtPathName_U( str
, &nt_name
, NULL
, NULL
)) return 0;
2400 ret
= NtGdiAddFontResourceW( nt_name
.Buffer
, nt_name
.Length
/ sizeof(WCHAR
) + 1,
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
);
2411 /***********************************************************************
2412 * AddFontResourceExW (GDI32.@)
2414 INT WINAPI
AddFontResourceExW( const WCHAR
*str
, DWORD flags
, void *dv
)
2416 WCHAR
*filename
= NULL
;
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
);
2429 static int remove_font_resource( const WCHAR
*str
, DWORD flags
, void *dv
)
2431 UNICODE_STRING nt_name
;
2434 if (!RtlDosPathNameToNtPathName_U( str
, &nt_name
, NULL
, NULL
)) return 0;
2435 ret
= NtGdiRemoveFontResourceW( nt_name
.Buffer
, nt_name
.Length
/ sizeof(WCHAR
) + 1,
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
);
2446 /***********************************************************************
2447 * RemoveFontResourceExW (GDI32.@)
2449 BOOL WINAPI
RemoveFontResourceExW( const WCHAR
*str
, DWORD flags
, void *dv
)
2451 WCHAR
*filename
= NULL
;
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
);
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
);
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>
2490 WORD num_of_resources
;
2494 CHAR dfCopyright
[60];
2500 WORD dfInternalLeading
;
2501 WORD dfExternalLeading
;
2509 BYTE dfPitchAndFamily
;
2520 CHAR szFaceName
[LF_FACESIZE
];
2522 #include <poppack.h>
2524 #include <pshpack2.h>
2545 struct ne_typeinfo fontdir_type
;
2546 struct ne_nameinfo fontdir_name
;
2547 struct ne_typeinfo scalable_type
;
2548 struct ne_nameinfo scalable_name
;
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
)
2559 DWORD size
, written
;
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,
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
=
2575 { 0, 0, 0x0c50, 0x2c, 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 */
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
);
2621 HeapFree( GetProcessHeap(), 0, font_fileA
);
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
)
2656 CloseHandle( file
);
2659 HeapFree( GetProcessHeap(), 0, start
);
2660 HeapFree( GetProcessHeap(), 0, font_fileA
);
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
];
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;
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
);
2733 SetLastError( ERROR_INVALID_PARAMETER
);
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
)
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
;
2783 case TCI_SRCCODEPAGE
:
2784 for (i
= 0; i
< ARRAY_SIZE(charset_info
); i
++)
2785 if (PtrToUlong(src
) == charset_info
[i
].ciACP
) goto found
;
2787 case TCI_SRCCHARSET
:
2788 for (i
= 0; i
< ARRAY_SIZE(charset_info
); i
++)
2789 if (PtrToUlong(src
) == charset_info
[i
].ciCharset
) goto found
;
2795 *cs
= charset_info
[i
];