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"
58 WINE_DEFAULT_DEBUG_CHANNEL(bidi
);
60 /* HELPER FUNCTIONS AND DECLARATIONS */
64 * LOOSE means taking the directionality of the first strong character, if there is found one.
65 * FORCE means the paragraph direction is forced. (RLE/LRE)
67 #define WINE_GCPW_FORCE_LTR 0
68 #define WINE_GCPW_FORCE_RTL 1
69 #define WINE_GCPW_LOOSE_LTR 2
70 #define WINE_GCPW_LOOSE_RTL 3
71 #define WINE_GCPW_DIR_MASK 3
72 #define WINE_GCPW_LOOSE_MASK 2
74 #define odd(x) ((x) & 1)
76 extern const unsigned short bidi_direction_table
[] DECLSPEC_HIDDEN
;
78 /*------------------------------------------------------------------------
79 Bidirectional Character Types
81 as defined by the Unicode Bidirectional Algorithm Table 3-7.
85 The list of bidirectional character types here is not grouped the
86 same way as the table 3-7, since the numeric values for the types
87 are chosen to keep the state and action tables compact.
88 ------------------------------------------------------------------------*/
92 /* ON MUST be zero, code relies on ON = N = 0 */
93 ON
= 0, /* Other Neutral */
96 AN
, /* Arabic Number */
97 EN
, /* European Number */
98 AL
, /* Arabic Letter (Right-to-left) */
99 NSM
, /* Non-spacing Mark */
100 CS
, /* Common Separator */
101 ES
, /* European Separator */
102 ET
, /* European Terminator (post/prefix e.g. $ and %) */
105 BN
, /* Boundary neutral (type of RLE etc after explicit levels) */
108 S
, /* Segment Separator (TAB) // used only in L1 */
109 WS
, /* White space // used only in L1 */
110 B
, /* Paragraph Separator (aka as PS) */
112 /* types for explicit controls */
113 RLO
, /* these are used only in X1-X9 */
119 LRI
, /* Isolate formatting characters new with 6.3 */
124 /* resolved types, also resolved directions */
125 NI
= ON
, /* alias, where ON, WS and S are treated the same */
128 /* HELPER FUNCTIONS */
130 static inline unsigned short get_table_entry(const unsigned short *table
, WCHAR ch
)
132 return table
[table
[table
[ch
>> 8] + ((ch
>> 4) & 0x0f)] + (ch
& 0xf)];
135 /* Convert the libwine information to the direction enum */
136 static void classify(LPCWSTR lpString
, WORD
*chartype
, DWORD uCount
)
140 for (i
= 0; i
< uCount
; ++i
)
141 chartype
[i
] = get_table_entry( bidi_direction_table
, lpString
[i
] );
144 /* Set a run of cval values at locations all prior to, but not including */
145 /* iStart, to the new value nval. */
146 static void SetDeferredRun(BYTE
*pval
, int cval
, int iStart
, int nval
)
149 for (; i
>= iStart
- cval
; i
--)
155 /* THE PARAGRAPH LEVEL */
157 /*------------------------------------------------------------------------
158 Function: resolveParagraphs
160 Resolves the input strings into blocks over which the algorithm
163 Implements Rule P1 of the Unicode Bidi Algorithm
168 Output: revised character count
170 Note: This is a very simplistic function. In effect it restricts
171 the action of the algorithm to the first paragraph in the input
172 where a paragraph ends at the end of the first block separator
173 or at the end of the input text.
175 ------------------------------------------------------------------------*/
177 static int resolveParagraphs(WORD
*types
, int cch
)
179 /* skip characters not of type B */
181 for(; ich
< cch
&& types
[ich
] != B
; ich
++);
182 /* stop after first B, make it a BN for use in the next steps */
183 if (ich
< cch
&& types
[ich
] == B
)
189 /*------------------------------------------------------------------------
190 Function: resolveLines
192 Breaks a paragraph into lines
194 Input: Array of line break flags
196 In/Out: Array of characters
198 Returns the count of characters on the first line
200 Note: This function only breaks lines at hard line breaks. Other
201 line breaks can be passed in. If pbrk[n] is TRUE, then a break
202 occurs after the character in pszInput[n]. Breaks before the first
203 character are not allowed.
204 ------------------------------------------------------------------------*/
205 static int resolveLines(LPCWSTR pszInput
, const BOOL
* pbrk
, int cch
)
207 /* skip characters not of type LS */
209 for(; ich
< cch
; ich
++)
211 if (pszInput
[ich
] == (WCHAR
)'\n' || (pbrk
&& pbrk
[ich
]))
221 /*------------------------------------------------------------------------
222 Function: resolveWhiteSpace
224 Resolves levels for WS and S
225 Implements rule L1 of the Unicode bidi Algorithm.
227 Input: Base embedding level
229 Array of direction classes (for one line of text)
231 In/Out: Array of embedding levels (for one line of text)
233 Note: this should be applied a line at a time. The default driver
234 code supplied in this file assumes a single line of text; for
235 a real implementation, cch and the initial pointer values
236 would have to be adjusted.
237 ------------------------------------------------------------------------*/
238 static void resolveWhitespace(int baselevel
, const WORD
*pcls
, BYTE
*plevel
, int cch
)
241 BYTE oldlevel
= baselevel
;
244 for (; ich
< cch
; ich
++)
249 cchrun
= 0; /* any other character breaks the run */
265 plevel
[ich
] = oldlevel
;
271 /* reset levels for WS before eot */
272 SetDeferredRun(plevel
, cchrun
, ich
, baselevel
);
274 plevel
[ich
] = baselevel
;
277 oldlevel
= plevel
[ich
];
279 /* reset level before eot */
280 SetDeferredRun(plevel
, cchrun
, ich
, baselevel
);
283 /*------------------------------------------------------------------------
286 Implements the Line-by-Line phases of the Unicode Bidi Algorithm
288 Input: Count of characters
289 Array of character directions
294 ------------------------------------------------------------------------*/
295 static void BidiLines(int baselevel
, LPWSTR pszOutLine
, LPCWSTR pszLine
, const WORD
* pclsLine
,
296 BYTE
* plevelLine
, int cchPara
, const BOOL
* pbrk
)
302 run
= HeapAlloc(GetProcessHeap(), 0, cchPara
* sizeof(int));
305 WARN("Out of memory\n");
311 /* break lines at LS */
312 cchLine
= resolveLines(pszLine
, pbrk
, cchPara
);
314 /* resolve whitespace */
315 resolveWhitespace(baselevel
, pclsLine
, plevelLine
, cchLine
);
320 /* reorder each line in place */
321 ScriptLayout(cchLine
, plevelLine
, NULL
, run
);
322 for (i
= 0; i
< cchLine
; i
++)
323 pszOutLine
[done
+run
[i
]] = pszLine
[i
];
327 plevelLine
+= cchLine
;
328 pbrk
+= pbrk
? cchLine
: 0;
335 HeapFree(GetProcessHeap(), 0, run
);
338 /*************************************************************
341 * Returns TRUE if reordering was required and done.
343 static BOOL
BIDI_Reorder( HDC hDC
, /* [in] Display DC */
344 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
345 INT uCount
, /* [in] Number of WCHARs in string. */
346 DWORD dwFlags
, /* [in] GetCharacterPlacement compatible flags */
347 DWORD dwWineGCP_Flags
, /* [in] Wine internal flags - Force paragraph direction */
348 LPWSTR lpOutString
, /* [out] Reordered string */
349 INT uCountOut
, /* [in] Size of output buffer */
350 UINT
*lpOrder
, /* [out] Logical -> Visual order map */
351 WORD
**lpGlyphs
, /* [out] reordered, mirrored, shaped glyphs to display */
352 INT
*cGlyphs
) /* [out] number of glyphs generated */
354 WORD
*chartype
= NULL
;
358 BOOL is_complex
, ret
= FALSE
;
362 SCRIPT_CONTROL Control
;
364 SCRIPT_ITEM
*pItems
= NULL
;
366 SCRIPT_CACHE psc
= NULL
;
367 WORD
*run_glyphs
= NULL
;
368 WORD
*pwLogClust
= NULL
;
369 SCRIPT_VISATTR
*psva
= NULL
;
370 DWORD cMaxGlyphs
= 0;
371 BOOL doGlyphs
= TRUE
;
373 TRACE("%s, %d, 0x%08x lpOutString=%p, lpOrder=%p\n",
374 debugstr_wn(lpString
, uCount
), uCount
, dwFlags
,
375 lpOutString
, lpOrder
);
377 memset(&Control
, 0, sizeof(Control
));
378 memset(&State
, 0, sizeof(State
));
382 if (!(dwFlags
& GCP_REORDER
))
384 FIXME("Asked to reorder without reorder flag set\n");
388 if (lpOutString
&& uCountOut
< uCount
)
390 FIXME("lpOutString too small\n");
394 chartype
= HeapAlloc(GetProcessHeap(), 0, uCount
* sizeof(WORD
));
397 WARN("Out of memory\n");
402 memcpy(lpOutString
, lpString
, uCount
* sizeof(WCHAR
));
405 for (i
= 0; i
< uCount
&& !is_complex
; i
++)
407 if ((lpString
[i
] >= 0x900 && lpString
[i
] <= 0xfff) ||
408 (lpString
[i
] >= 0x1cd0 && lpString
[i
] <= 0x1cff) ||
409 (lpString
[i
] >= 0xa840 && lpString
[i
] <= 0xa8ff))
413 /* Verify reordering will be required */
414 if ((WINE_GCPW_FORCE_RTL
== (dwWineGCP_Flags
&WINE_GCPW_DIR_MASK
)) ||
415 ((dwWineGCP_Flags
&WINE_GCPW_DIR_MASK
) == WINE_GCPW_LOOSE_RTL
))
416 State
.uBidiLevel
= 1;
417 else if (!is_complex
)
420 classify(lpString
, chartype
, uCount
);
421 for (i
= 0; i
< uCount
; i
++)
433 HeapFree(GetProcessHeap(), 0, chartype
);
436 for (i
= 0; i
< uCount
; i
++)
443 levels
= HeapAlloc(GetProcessHeap(), 0, uCount
* sizeof(BYTE
));
446 WARN("Out of memory\n");
451 pItems
= HeapAlloc(GetProcessHeap(),0, maxItems
* sizeof(SCRIPT_ITEM
));
454 WARN("Out of memory\n");
460 cMaxGlyphs
= 1.5 * uCount
+ 16;
461 run_glyphs
= HeapAlloc(GetProcessHeap(),0,sizeof(WORD
) * cMaxGlyphs
);
464 WARN("Out of memory\n");
467 pwLogClust
= HeapAlloc(GetProcessHeap(),0,sizeof(WORD
) * uCount
);
470 WARN("Out of memory\n");
473 psva
= HeapAlloc(GetProcessHeap(),0,sizeof(SCRIPT_VISATTR
) * uCount
);
476 WARN("Out of memory\n");
483 while (done
< uCount
)
486 classify(lpString
+ done
, chartype
, uCount
- done
);
487 /* limit text to first block */
488 i
= resolveParagraphs(chartype
, uCount
- done
);
489 for (j
= 0; j
< i
; ++j
)
495 case ON
: chartype
[j
] = NI
;
499 if ((dwWineGCP_Flags
&WINE_GCPW_DIR_MASK
) == WINE_GCPW_LOOSE_RTL
)
500 State
.uBidiLevel
= 1;
501 else if ((dwWineGCP_Flags
&WINE_GCPW_DIR_MASK
) == WINE_GCPW_LOOSE_LTR
)
502 State
.uBidiLevel
= 0;
504 if (dwWineGCP_Flags
& WINE_GCPW_LOOSE_MASK
)
506 for (j
= 0; j
< i
; ++j
)
507 if (chartype
[j
] == L
)
509 State
.uBidiLevel
= 0;
512 else if (chartype
[j
] == R
|| chartype
[j
] == AL
)
514 State
.uBidiLevel
= 1;
519 res
= ScriptItemize(lpString
+ done
, i
, maxItems
, &Control
, &State
, pItems
, &nItems
);
520 while (res
== E_OUTOFMEMORY
)
522 SCRIPT_ITEM
*new_pItems
= HeapReAlloc(GetProcessHeap(), 0, pItems
, sizeof(*pItems
) * maxItems
* 2);
525 WARN("Out of memory\n");
530 res
= ScriptItemize(lpString
+ done
, i
, maxItems
, &Control
, &State
, pItems
, &nItems
);
533 if (lpOutString
|| lpOrder
)
534 for (j
= 0; j
< nItems
; j
++)
537 for (k
= pItems
[j
].iCharPos
; k
< pItems
[j
+1].iCharPos
; k
++)
538 levels
[k
] = pItems
[j
].a
.s
.uBidiLevel
;
543 /* assign directional types again, but for WS, S this time */
544 classify(lpString
+ done
, chartype
, i
);
546 BidiLines(State
.uBidiLevel
, lpOutString
+ done
, lpString
+ done
,
547 chartype
, levels
, i
, 0);
553 for (j
= lastgood
= 0; j
< i
; ++j
)
554 if (levels
[j
] != levels
[lastgood
])
557 if (odd(levels
[lastgood
]))
558 for (k
= j
; k
>= lastgood
; --k
)
559 lpOrder
[done
+ k
] = done
+ j
- k
;
561 for (k
= lastgood
; k
<= j
; ++k
)
562 lpOrder
[done
+ k
] = done
+ k
;
565 if (odd(levels
[lastgood
]))
566 for (k
= j
- 1; k
>= lastgood
; --k
)
567 lpOrder
[done
+ k
] = done
+ j
- 1 - k
;
569 for (k
= lastgood
; k
< j
; ++k
)
570 lpOrder
[done
+ k
] = done
+ k
;
573 if (lpGlyphs
&& doGlyphs
)
577 SCRIPT_ITEM
*curItem
;
579 runOrder
= HeapAlloc(GetProcessHeap(), 0, maxItems
* sizeof(*runOrder
));
580 visOrder
= HeapAlloc(GetProcessHeap(), 0, maxItems
* sizeof(*visOrder
));
581 if (!runOrder
|| !visOrder
)
583 WARN("Out of memory\n");
584 HeapFree(GetProcessHeap(), 0, runOrder
);
585 HeapFree(GetProcessHeap(), 0, visOrder
);
589 for (j
= 0; j
< nItems
; j
++)
590 runOrder
[j
] = pItems
[j
].a
.s
.uBidiLevel
;
592 ScriptLayout(nItems
, runOrder
, visOrder
, NULL
);
594 for (j
= 0; j
< nItems
; j
++)
597 int cChars
,cOutGlyphs
;
598 curItem
= &pItems
[visOrder
[j
]];
600 cChars
= pItems
[visOrder
[j
]+1].iCharPos
- curItem
->iCharPos
;
602 res
= ScriptShape(hDC
, &psc
, lpString
+ done
+ curItem
->iCharPos
, cChars
, cMaxGlyphs
, &curItem
->a
, run_glyphs
, pwLogClust
, psva
, &cOutGlyphs
);
603 while (res
== E_OUTOFMEMORY
)
605 WORD
*new_run_glyphs
= HeapReAlloc(GetProcessHeap(), 0, run_glyphs
, sizeof(*run_glyphs
) * cMaxGlyphs
* 2);
608 WARN("Out of memory\n");
609 HeapFree(GetProcessHeap(), 0, runOrder
);
610 HeapFree(GetProcessHeap(), 0, visOrder
);
611 HeapFree(GetProcessHeap(), 0, *lpGlyphs
);
615 run_glyphs
= new_run_glyphs
;
617 res
= ScriptShape(hDC
, &psc
, lpString
+ done
+ curItem
->iCharPos
, cChars
, cMaxGlyphs
, &curItem
->a
, run_glyphs
, pwLogClust
, psva
, &cOutGlyphs
);
621 if (res
== USP_E_SCRIPT_NOT_IN_FONT
)
622 TRACE("Unable to shape with currently selected font\n");
624 FIXME("Unable to shape string (%x)\n",res
);
627 HeapFree(GetProcessHeap(), 0, *lpGlyphs
);
634 new_glyphs
= HeapReAlloc(GetProcessHeap(), 0, *lpGlyphs
, sizeof(**lpGlyphs
) * (glyph_i
+ cOutGlyphs
));
636 new_glyphs
= HeapAlloc(GetProcessHeap(), 0, sizeof(**lpGlyphs
) * (glyph_i
+ cOutGlyphs
));
639 WARN("Out of memory\n");
640 HeapFree(GetProcessHeap(), 0, runOrder
);
641 HeapFree(GetProcessHeap(), 0, visOrder
);
642 HeapFree(GetProcessHeap(), 0, *lpGlyphs
);
646 *lpGlyphs
= new_glyphs
;
647 for (k
= 0; k
< cOutGlyphs
; k
++)
648 (*lpGlyphs
)[glyph_i
+k
] = run_glyphs
[k
];
649 glyph_i
+= cOutGlyphs
;
652 HeapFree(GetProcessHeap(), 0, runOrder
);
653 HeapFree(GetProcessHeap(), 0, visOrder
);
663 HeapFree(GetProcessHeap(), 0, chartype
);
664 HeapFree(GetProcessHeap(), 0, levels
);
665 HeapFree(GetProcessHeap(), 0, pItems
);
666 HeapFree(GetProcessHeap(), 0, run_glyphs
);
667 HeapFree(GetProcessHeap(), 0, pwLogClust
);
668 HeapFree(GetProcessHeap(), 0, psva
);
669 ScriptFreeCache(&psc
);
673 /***********************************************************************
676 * Returns a Unicode translation of str using the charset of the
677 * currently selected font in hdc. If count is -1 then str is assumed
678 * to be '\0' terminated, otherwise it contains the number of bytes to
679 * convert. If plenW is non-NULL, on return it will point to the
680 * number of WCHARs that have been written. If ret_cp is non-NULL, on
681 * return it will point to the codepage used in the conversion. The
682 * caller should free the returned string from the process heap
685 static WCHAR
*text_mbtowc( HDC hdc
, const char *str
, INT count
, INT
*plenW
, UINT
*ret_cp
)
691 cp
= GdiGetCodePage( hdc
);
693 if (count
== -1) count
= strlen( str
);
694 lenW
= MultiByteToWideChar( cp
, 0, str
, count
, NULL
, 0 );
695 strW
= HeapAlloc( GetProcessHeap(), 0, lenW
* sizeof(WCHAR
) );
696 MultiByteToWideChar( cp
, 0, str
, count
, strW
, lenW
);
697 TRACE( "mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
) );
698 if (plenW
) *plenW
= lenW
;
699 if (ret_cp
) *ret_cp
= cp
;
703 static void text_metric_WtoA( const TEXTMETRICW
*tmW
, TEXTMETRICA
*tmA
)
705 tmA
->tmHeight
= tmW
->tmHeight
;
706 tmA
->tmAscent
= tmW
->tmAscent
;
707 tmA
->tmDescent
= tmW
->tmDescent
;
708 tmA
->tmInternalLeading
= tmW
->tmInternalLeading
;
709 tmA
->tmExternalLeading
= tmW
->tmExternalLeading
;
710 tmA
->tmAveCharWidth
= tmW
->tmAveCharWidth
;
711 tmA
->tmMaxCharWidth
= tmW
->tmMaxCharWidth
;
712 tmA
->tmWeight
= tmW
->tmWeight
;
713 tmA
->tmOverhang
= tmW
->tmOverhang
;
714 tmA
->tmDigitizedAspectX
= tmW
->tmDigitizedAspectX
;
715 tmA
->tmDigitizedAspectY
= tmW
->tmDigitizedAspectY
;
716 tmA
->tmFirstChar
= min( tmW
->tmFirstChar
, 255 );
717 if (tmW
->tmCharSet
== SYMBOL_CHARSET
)
719 tmA
->tmFirstChar
= 0x1e;
720 tmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
722 else if (tmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
724 tmA
->tmFirstChar
= tmW
->tmDefaultChar
- 1;
725 tmA
->tmLastChar
= min( tmW
->tmLastChar
, 0xff );
729 tmA
->tmFirstChar
= min( tmW
->tmFirstChar
, 0xff );
730 tmA
->tmLastChar
= min( tmW
->tmLastChar
, 0xff );
732 tmA
->tmDefaultChar
= tmW
->tmDefaultChar
;
733 tmA
->tmBreakChar
= tmW
->tmBreakChar
;
734 tmA
->tmItalic
= tmW
->tmItalic
;
735 tmA
->tmUnderlined
= tmW
->tmUnderlined
;
736 tmA
->tmStruckOut
= tmW
->tmStruckOut
;
737 tmA
->tmPitchAndFamily
= tmW
->tmPitchAndFamily
;
738 tmA
->tmCharSet
= tmW
->tmCharSet
;
741 static void logfont_AtoW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
743 memcpy( fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
744 MultiByteToWideChar( CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
746 fontW
->lfFaceName
[LF_FACESIZE
- 1] = 0;
749 static void logfontex_AtoW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
751 logfont_AtoW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
753 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
754 fontW
->elfFullName
, LF_FULLFACESIZE
);
755 fontW
->elfFullName
[LF_FULLFACESIZE
- 1] = '\0';
756 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
757 fontW
->elfStyle
, LF_FACESIZE
);
758 fontW
->elfStyle
[LF_FACESIZE
- 1] = '\0';
759 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
760 fontW
->elfScript
, LF_FACESIZE
);
761 fontW
->elfScript
[LF_FACESIZE
- 1] = '\0';
764 /***********************************************************************
765 * GdiGetCodePage (GDI32.@)
767 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
769 DC_ATTR
*dc_attr
= get_dc_attr( hdc
);
770 return dc_attr
? dc_attr
->font_code_page
: CP_ACP
;
773 /***********************************************************************
774 * CreateFontIndirectExA (GDI32.@)
776 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*enumexA
)
778 ENUMLOGFONTEXDVW enumexW
;
780 if (!enumexA
) return 0;
782 logfontex_AtoW( &enumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
783 enumexW
.elfDesignVector
= enumexA
->elfDesignVector
;
784 return CreateFontIndirectExW( &enumexW
);
787 /***********************************************************************
788 * CreateFontIndirectExW (GDI32.@)
790 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*enumex
)
792 return NtGdiHfontCreate( enumex
, sizeof(*enumex
), 0, 0, NULL
);
795 /***********************************************************************
796 * CreateFontIndirectA (GDI32.@)
798 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*lfA
)
804 logfont_AtoW( lfA
, &lfW
);
805 return CreateFontIndirectW( &lfW
);
808 /***********************************************************************
809 * CreateFontIndirectW (GDI32.@)
811 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*lf
)
813 ENUMLOGFONTEXDVW exdv
;
817 exdv
.elfEnumLogfontEx
.elfLogFont
= *lf
;
818 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
819 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
820 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
821 return CreateFontIndirectExW( &exdv
);
824 /*************************************************************************
825 * CreateFontA (GDI32.@)
827 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
, INT orient
, INT weight
,
828 DWORD italic
, DWORD underline
, DWORD strikeout
,
829 DWORD charset
, DWORD outpres
, DWORD clippres
,
830 DWORD quality
, DWORD pitch
, const char *name
)
834 logfont
.lfHeight
= height
;
835 logfont
.lfWidth
= width
;
836 logfont
.lfEscapement
= esc
;
837 logfont
.lfOrientation
= orient
;
838 logfont
.lfWeight
= weight
;
839 logfont
.lfItalic
= italic
;
840 logfont
.lfUnderline
= underline
;
841 logfont
.lfStrikeOut
= strikeout
;
842 logfont
.lfCharSet
= charset
;
843 logfont
.lfOutPrecision
= outpres
;
844 logfont
.lfClipPrecision
= clippres
;
845 logfont
.lfQuality
= quality
;
846 logfont
.lfPitchAndFamily
= pitch
;
849 lstrcpynA( logfont
.lfFaceName
, name
, sizeof(logfont
.lfFaceName
) );
851 logfont
.lfFaceName
[0] = '\0';
853 return CreateFontIndirectA( &logfont
);
856 /*************************************************************************
857 * CreateFontW (GDI32.@)
859 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
, INT orient
, INT weight
,
860 DWORD italic
, DWORD underline
, DWORD strikeout
,
861 DWORD charset
, DWORD outpres
, DWORD clippres
,
862 DWORD quality
, DWORD pitch
, const WCHAR
*name
)
866 logfont
.lfHeight
= height
;
867 logfont
.lfWidth
= width
;
868 logfont
.lfEscapement
= esc
;
869 logfont
.lfOrientation
= orient
;
870 logfont
.lfWeight
= weight
;
871 logfont
.lfItalic
= italic
;
872 logfont
.lfUnderline
= underline
;
873 logfont
.lfStrikeOut
= strikeout
;
874 logfont
.lfCharSet
= charset
;
875 logfont
.lfOutPrecision
= outpres
;
876 logfont
.lfClipPrecision
= clippres
;
877 logfont
.lfQuality
= quality
;
878 logfont
.lfPitchAndFamily
= pitch
;
881 lstrcpynW( logfont
.lfFaceName
, name
, ARRAY_SIZE(logfont
.lfFaceName
) );
883 logfont
.lfFaceName
[0] = '\0';
885 return CreateFontIndirectW( &logfont
);
888 /***********************************************************************
889 * ExtTextOutW (GDI32.@)
891 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
892 const WCHAR
*str
, UINT count
, const INT
*dx
)
898 if (count
> INT_MAX
) return FALSE
;
899 if (is_meta_dc( hdc
)) return METADC_ExtTextOut( hdc
, x
, y
, flags
, rect
, str
, count
, dx
);
900 if (!(dc_attr
= get_dc_attr( hdc
))) return FALSE
;
901 if (dc_attr
->emf
&& !EMFDC_ExtTextOut( dc_attr
, x
, y
, flags
, rect
, str
, count
, dx
))
904 if (!(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0)
909 bidi_flags
= (dc_attr
->text_align
& TA_RTLREADING
) || (flags
& ETO_RTLREADING
)
910 ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
;
912 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
, bidi_flags
, NULL
, 0, NULL
,
913 &glyphs
, &glyphs_count
);
915 flags
|= ETO_IGNORELANGUAGE
;
918 flags
|= ETO_GLYPH_INDEX
;
919 count
= glyphs_count
;
924 ret
= NtGdiExtTextOutW( hdc
, x
, y
, flags
, rect
, str
, count
, dx
, 0 );
926 HeapFree( GetProcessHeap(), 0, glyphs
);
930 /***********************************************************************
931 * ExtTextOutA (GDI32.@)
933 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
934 const char *str
, UINT count
, const INT
*dx
)
942 if (count
> INT_MAX
) return FALSE
;
944 if (flags
& ETO_GLYPH_INDEX
)
945 return ExtTextOutW( hdc
, x
, y
, flags
, rect
, (const WCHAR
*)str
, count
, dx
);
947 p
= text_mbtowc( hdc
, str
, count
, &wlen
, &codepage
);
951 unsigned int i
= 0, j
= 0;
953 /* allocate enough for a ETO_PDY */
954 dxW
= HeapAlloc( GetProcessHeap(), 0, 2 * wlen
* sizeof(INT
) );
957 if (IsDBCSLeadByteEx( codepage
, str
[i
] ))
961 dxW
[j
++] = dx
[i
* 2] + dx
[(i
+ 1) * 2];
962 dxW
[j
++] = dx
[i
* 2 + 1] + dx
[(i
+ 1) * 2 + 1];
965 dxW
[j
++] = dx
[i
] + dx
[i
+ 1];
972 dxW
[j
++] = dx
[i
* 2];
973 dxW
[j
++] = dx
[i
* 2 + 1];
982 ret
= ExtTextOutW( hdc
, x
, y
, flags
, rect
, p
, wlen
, dxW
);
984 HeapFree( GetProcessHeap(), 0, p
);
985 HeapFree( GetProcessHeap(), 0, dxW
);
989 /***********************************************************************
992 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, const char *str
, INT count
)
994 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
997 /***********************************************************************
1000 BOOL WINAPI
TextOutW( HDC hdc
, INT x
, INT y
, const WCHAR
*str
, INT count
)
1002 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
1006 /***********************************************************************
1007 * PolyTextOutA (GDI32.@)
1009 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pt
, INT count
)
1011 for (; count
>0; count
--, pt
++)
1012 if (!ExtTextOutA( hdc
, pt
->x
, pt
->y
, pt
->uiFlags
, &pt
->rcl
, pt
->lpstr
, pt
->n
, pt
->pdx
))
1017 /***********************************************************************
1018 * PolyTextOutW (GDI32.@)
1020 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pt
, INT count
)
1022 for (; count
>0; count
--, pt
++)
1023 if (!ExtTextOutW( hdc
, pt
->x
, pt
->y
, pt
->uiFlags
, &pt
->rcl
, pt
->lpstr
, pt
->n
, pt
->pdx
))
1028 static int kern_pair( const KERNINGPAIR
*kern
, int count
, WCHAR c1
, WCHAR c2
)
1032 for (i
= 0; i
< count
; i
++)
1034 if (kern
[i
].wFirst
== c1
&& kern
[i
].wSecond
== c2
)
1035 return kern
[i
].iKernAmount
;
1041 static int *kern_string( HDC hdc
, const WCHAR
*str
, int len
, int *kern_total
)
1043 unsigned int i
, count
;
1044 KERNINGPAIR
*kern
= NULL
;
1049 ret
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(*ret
) );
1050 if (!ret
) return NULL
;
1052 count
= GetKerningPairsW( hdc
, 0, NULL
);
1055 kern
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*kern
) );
1058 HeapFree( GetProcessHeap(), 0, ret
);
1062 GetKerningPairsW( hdc
, count
, kern
);
1065 for (i
= 0; i
< len
- 1; i
++)
1067 ret
[i
] = kern_pair( kern
, count
, str
[i
], str
[i
+ 1] );
1068 *kern_total
+= ret
[i
];
1071 ret
[len
- 1] = 0; /* no kerning for last element */
1073 HeapFree( GetProcessHeap(), 0, kern
);
1077 /*************************************************************************
1078 * GetCharacterPlacementW (GDI32.@)
1080 * Retrieve information about a string. This includes the width, reordering,
1081 * Glyphing and so on.
1085 * The width and height of the string if successful, 0 if failed.
1089 * All flags except GCP_REORDER are not yet implemented.
1090 * Reordering is not 100% compliant to the Windows BiDi method.
1091 * Caret positioning is not yet implemented for BiDi.
1092 * Classes are not yet implemented.
1095 DWORD WINAPI
GetCharacterPlacementW( HDC hdc
, const WCHAR
*str
, INT count
, INT max_extent
,
1096 GCP_RESULTSW
*result
, DWORD flags
)
1098 int *kern
= NULL
, kern_total
= 0;
1103 TRACE("%s, %d, %d, 0x%08x\n", debugstr_wn(str
, count
), count
, max_extent
, flags
);
1109 return GetTextExtentPoint32W( hdc
, str
, count
, &size
) ? MAKELONG(size
.cx
, size
.cy
) : 0;
1111 TRACE( "lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
1112 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
1113 result
->lStructSize
, result
->lpOutString
, result
->lpOrder
,
1114 result
->lpDx
, result
->lpCaretPos
, result
->lpClass
,
1115 result
->lpGlyphs
, result
->nGlyphs
, result
->nMaxFit
);
1117 if (flags
& ~(GCP_REORDER
| GCP_USEKERNING
))
1118 FIXME( "flags 0x%08x ignored\n", flags
);
1119 if (result
->lpClass
)
1120 FIXME( "classes not implemented\n" );
1121 if (result
->lpCaretPos
&& (flags
& GCP_REORDER
))
1122 FIXME( "Caret positions for complex scripts not implemented\n" );
1124 set_cnt
= (UINT
)count
;
1125 if (set_cnt
> result
->nGlyphs
) set_cnt
= result
->nGlyphs
;
1127 /* return number of initialized fields */
1128 result
->nGlyphs
= set_cnt
;
1130 if (!(flags
& GCP_REORDER
))
1132 /* Treat the case where no special handling was requested in a fastpath way */
1133 /* copy will do if the GCP_REORDER flag is not set */
1134 if (result
->lpOutString
)
1135 memcpy( result
->lpOutString
, str
, set_cnt
* sizeof(WCHAR
) );
1137 if (result
->lpOrder
)
1139 for (i
= 0; i
< set_cnt
; i
++)
1140 result
->lpOrder
[i
] = i
;
1145 BIDI_Reorder( NULL
, str
, count
, flags
, WINE_GCPW_FORCE_LTR
, result
->lpOutString
,
1146 set_cnt
, result
->lpOrder
, NULL
, NULL
);
1149 if (flags
& GCP_USEKERNING
)
1151 kern
= kern_string( hdc
, str
, set_cnt
, &kern_total
);
1154 SetLastError( ERROR_NOT_ENOUGH_MEMORY
);
1159 /* FIXME: Will use the placement chars */
1163 for (i
= 0; i
< set_cnt
; i
++)
1165 if (GetCharWidth32W( hdc
, str
[i
], str
[i
], &c
))
1167 result
->lpDx
[i
] = c
;
1168 if (flags
& GCP_USEKERNING
)
1169 result
->lpDx
[i
] += kern
[i
];
1174 if (result
->lpCaretPos
&& !(flags
& GCP_REORDER
))
1176 unsigned int pos
= 0;
1178 result
->lpCaretPos
[0] = 0;
1179 for (i
= 0; i
< set_cnt
- 1; i
++)
1181 if (flags
& GCP_USEKERNING
)
1184 if (GetTextExtentPoint32W( hdc
, &str
[i
], 1, &size
))
1185 result
->lpCaretPos
[i
+ 1] = (pos
+= size
.cx
);
1189 if (result
->lpGlyphs
)
1190 GetGlyphIndicesW( hdc
, str
, set_cnt
, result
->lpGlyphs
, 0 );
1192 if (GetTextExtentPoint32W( hdc
, str
, count
, &size
))
1193 ret
= MAKELONG( size
.cx
+ kern_total
, size
.cy
);
1195 HeapFree( GetProcessHeap(), 0, kern
);
1199 /*************************************************************************
1200 * GetCharacterPlacementA (GDI32.@)
1202 DWORD WINAPI
GetCharacterPlacementA( HDC hdc
, const char *str
, INT count
, INT max_extent
,
1203 GCP_RESULTSA
*result
, DWORD flags
)
1205 GCP_RESULTSW resultsW
;
1211 TRACE( "%s, %d, %d, 0x%08x\n", debugstr_an(str
, count
), count
, max_extent
, flags
);
1213 strW
= text_mbtowc( hdc
, str
, count
, &countW
, &font_cp
);
1217 ret
= GetCharacterPlacementW( hdc
, strW
, countW
, max_extent
, NULL
, flags
);
1218 HeapFree( GetProcessHeap(), 0, strW
);
1222 /* both structs are equal in size */
1223 memcpy( &resultsW
, result
, sizeof(resultsW
) );
1225 if (result
->lpOutString
)
1226 resultsW
.lpOutString
= HeapAlloc( GetProcessHeap(), 0, sizeof(WCHAR
) * countW
);
1228 ret
= GetCharacterPlacementW( hdc
, strW
, countW
, max_extent
, &resultsW
, flags
);
1230 result
->nGlyphs
= resultsW
.nGlyphs
;
1231 result
->nMaxFit
= resultsW
.nMaxFit
;
1233 if (result
->lpOutString
)
1234 WideCharToMultiByte( font_cp
, 0, resultsW
.lpOutString
, countW
,
1235 result
->lpOutString
, count
, NULL
, NULL
);
1237 HeapFree( GetProcessHeap(), 0, strW
);
1238 HeapFree( GetProcessHeap(), 0, resultsW
.lpOutString
);
1242 /***********************************************************************
1243 * GetTextFaceA (GDI32.@)
1245 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, char *name
)
1247 INT res
= GetTextFaceW( hdc
, 0, NULL
);
1248 WCHAR
*nameW
= HeapAlloc( GetProcessHeap(), 0, res
* sizeof(WCHAR
) );
1250 GetTextFaceW( hdc
, res
, nameW
);
1255 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
1256 if (res
== 0) res
= count
;
1257 name
[count
- 1] = 0;
1258 /* GetTextFaceA does NOT include the nul byte in the return count. */
1265 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1266 HeapFree( GetProcessHeap(), 0, nameW
);
1270 /***********************************************************************
1271 * GetTextFaceW (GDI32.@)
1273 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, WCHAR
*name
)
1275 return NtGdiGetTextFaceW( hdc
, count
, name
, FALSE
);
1278 /***********************************************************************
1279 * GetTextExtentExPointW (GDI32.@)
1281 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, const WCHAR
*str
, INT count
, INT max_ext
,
1282 INT
*nfit
, INT
*dxs
, SIZE
*size
)
1284 return NtGdiGetTextExtentExW( hdc
, str
, count
, max_ext
, nfit
, dxs
, size
, 0 );
1287 /***********************************************************************
1288 * GetTextExtentExPointI (GDI32.@)
1290 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1291 INT
*nfit
, INT
*dxs
, SIZE
*size
)
1293 return NtGdiGetTextExtentExW( hdc
, indices
, count
, max_ext
, nfit
, dxs
, size
, 1 );
1296 /***********************************************************************
1297 * GetTextExtentExPointA (GDI32.@)
1299 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, const char *str
, INT count
, INT max_ext
,
1300 INT
*nfit
, INT
*dxs
, SIZE
*size
)
1307 if (count
< 0 || max_ext
< -1) return FALSE
;
1311 wdxs
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1312 if (!wdxs
) return FALSE
;
1315 p
= text_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
1316 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, max_ext
, nfit
, wdxs
, size
);
1319 INT n
= nfit
? *nfit
: wlen
;
1321 for (i
= 0, j
= 0; i
< n
; i
++, j
++)
1324 if (IsDBCSLeadByte( str
[j
] )) dxs
[++j
] = wdxs
[i
];
1327 if (nfit
) *nfit
= WideCharToMultiByte( CP_ACP
, 0, p
, *nfit
, NULL
, 0, NULL
, NULL
);
1328 HeapFree( GetProcessHeap(), 0, p
);
1329 HeapFree( GetProcessHeap(), 0, wdxs
);
1333 /***********************************************************************
1334 * GetTextExtentPoint32W (GDI32.@)
1336 BOOL WINAPI
GetTextExtentPoint32W( HDC hdc
, const WCHAR
*str
, INT count
, SIZE
*size
)
1338 return GetTextExtentExPointW( hdc
, str
, count
, 0, NULL
, NULL
, size
);
1341 /***********************************************************************
1342 * GetTextExtentPoint32A (GDI32.@)
1344 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, const char *str
, INT count
, SIZE
*size
)
1346 return GetTextExtentExPointA( hdc
, str
, count
, 0, NULL
, NULL
, size
);
1349 /***********************************************************************
1350 * GetTextExtentPointI (GDI32.@)
1352 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, SIZE
*size
)
1354 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1357 /***********************************************************************
1358 * GetTextExtentPointA (GDI32.@)
1360 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, const char *str
, INT count
, SIZE
*size
)
1362 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1365 /***********************************************************************
1366 * GetTextExtentPointW (GDI32.@)
1368 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, const WCHAR
*str
, INT count
, SIZE
*size
)
1370 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1373 /***********************************************************************
1374 * GetTextMetricsW (GDI32.@)
1376 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1378 return NtGdiGetTextMetricsW( hdc
, metrics
, 0 );
1381 /***********************************************************************
1382 * GetTextMetricsA (GDI32.@)
1384 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1388 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1389 text_metric_WtoA( &tm32
, metrics
);
1393 /***********************************************************************
1394 * GetOutlineTextMetricsA (GDI32.@)
1396 * Gets metrics for TrueType fonts.
1399 * If the supplied buffer isn't big enough Windows partially fills it up to
1400 * its given length and returns that length.
1402 UINT WINAPI
GetOutlineTextMetricsA( HDC hdc
, UINT size
, OUTLINETEXTMETRICA
*otm
)
1404 char buf
[512], *ptr
;
1406 OUTLINETEXTMETRICW
*otmW
= (OUTLINETEXTMETRICW
*)buf
;
1407 OUTLINETEXTMETRICA
*output
= otm
;
1410 if ((ret
= GetOutlineTextMetricsW( hdc
, 0, NULL
)) == 0) return 0;
1411 if (ret
> sizeof(buf
) && !(otmW
= HeapAlloc( GetProcessHeap(), 0, ret
)))
1414 GetOutlineTextMetricsW( hdc
, ret
, otmW
);
1416 needed
= sizeof(OUTLINETEXTMETRICA
);
1417 if (otmW
->otmpFamilyName
)
1418 needed
+= WideCharToMultiByte( CP_ACP
, 0,
1419 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpFamilyName
),
1420 -1, NULL
, 0, NULL
, NULL
);
1421 if (otmW
->otmpFaceName
)
1422 needed
+= WideCharToMultiByte( CP_ACP
, 0,
1423 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpFaceName
),
1424 -1, NULL
, 0, NULL
, NULL
);
1425 if (otmW
->otmpStyleName
)
1426 needed
+= WideCharToMultiByte( CP_ACP
, 0,
1427 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpStyleName
),
1428 -1, NULL
, 0, NULL
, NULL
);
1429 if (otmW
->otmpFullName
)
1430 needed
+= WideCharToMultiByte( CP_ACP
, 0,
1431 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpFullName
),
1432 -1, NULL
, 0, NULL
, NULL
);
1440 TRACE( "needed = %d\n", needed
);
1442 /* Since the supplied buffer isn't big enough, we'll alloc one
1443 that is and memcpy the first size bytes into the otm at
1445 output
= HeapAlloc( GetProcessHeap(), 0, needed
);
1447 ret
= output
->otmSize
= min( needed
, size
);
1448 text_metric_WtoA( &otmW
->otmTextMetrics
, &output
->otmTextMetrics
);
1449 output
->otmFiller
= 0;
1450 output
->otmPanoseNumber
= otmW
->otmPanoseNumber
;
1451 output
->otmfsSelection
= otmW
->otmfsSelection
;
1452 output
->otmfsType
= otmW
->otmfsType
;
1453 output
->otmsCharSlopeRise
= otmW
->otmsCharSlopeRise
;
1454 output
->otmsCharSlopeRun
= otmW
->otmsCharSlopeRun
;
1455 output
->otmItalicAngle
= otmW
->otmItalicAngle
;
1456 output
->otmEMSquare
= otmW
->otmEMSquare
;
1457 output
->otmAscent
= otmW
->otmAscent
;
1458 output
->otmDescent
= otmW
->otmDescent
;
1459 output
->otmLineGap
= otmW
->otmLineGap
;
1460 output
->otmsCapEmHeight
= otmW
->otmsCapEmHeight
;
1461 output
->otmsXHeight
= otmW
->otmsXHeight
;
1462 output
->otmrcFontBox
= otmW
->otmrcFontBox
;
1463 output
->otmMacAscent
= otmW
->otmMacAscent
;
1464 output
->otmMacDescent
= otmW
->otmMacDescent
;
1465 output
->otmMacLineGap
= otmW
->otmMacLineGap
;
1466 output
->otmusMinimumPPEM
= otmW
->otmusMinimumPPEM
;
1467 output
->otmptSubscriptSize
= otmW
->otmptSubscriptSize
;
1468 output
->otmptSubscriptOffset
= otmW
->otmptSubscriptOffset
;
1469 output
->otmptSuperscriptSize
= otmW
->otmptSuperscriptSize
;
1470 output
->otmptSuperscriptOffset
= otmW
->otmptSuperscriptOffset
;
1471 output
->otmsStrikeoutSize
= otmW
->otmsStrikeoutSize
;
1472 output
->otmsStrikeoutPosition
= otmW
->otmsStrikeoutPosition
;
1473 output
->otmsUnderscoreSize
= otmW
->otmsUnderscoreSize
;
1474 output
->otmsUnderscorePosition
= otmW
->otmsUnderscorePosition
;
1476 ptr
= (char *)(output
+ 1);
1477 left
= needed
- sizeof(*output
);
1479 if (otmW
->otmpFamilyName
)
1481 output
->otmpFamilyName
= (char *)(ptr
- (char *)output
);
1482 len
= WideCharToMultiByte( CP_ACP
, 0,
1483 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpFamilyName
),
1484 -1, ptr
, left
, NULL
, NULL
);
1488 else output
->otmpFamilyName
= 0;
1490 if (otmW
->otmpFaceName
)
1492 output
->otmpFaceName
= (char *)(ptr
- (char *)output
);
1493 len
= WideCharToMultiByte( CP_ACP
, 0,
1494 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpFaceName
),
1495 -1, ptr
, left
, NULL
, NULL
);
1499 else output
->otmpFaceName
= 0;
1501 if (otmW
->otmpStyleName
)
1503 output
->otmpStyleName
= (char *)(ptr
- (char *)output
);
1504 len
= WideCharToMultiByte( CP_ACP
, 0,
1505 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpStyleName
),
1506 -1, ptr
, left
, NULL
, NULL
);
1510 else output
->otmpStyleName
= 0;
1512 if (otmW
->otmpFullName
)
1514 output
->otmpFullName
= (char *)(ptr
- (char *)output
);
1515 len
= WideCharToMultiByte( CP_ACP
, 0,
1516 (WCHAR
*)((char *)otmW
+ (ptrdiff_t)otmW
->otmpFullName
),
1517 -1, ptr
, left
, NULL
, NULL
);
1520 else output
->otmpFullName
= 0;
1522 assert( left
== 0 );
1526 memcpy( otm
, output
, size
);
1527 HeapFree( GetProcessHeap(), 0, output
);
1529 /* check if the string offsets really fit into the provided size */
1530 /* FIXME: should we check string length as well? */
1531 /* make sure that we don't read/write beyond the provided buffer */
1532 if (otm
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(char *))
1534 if ((UINT_PTR
)otm
->otmpFamilyName
>= otm
->otmSize
)
1535 otm
->otmpFamilyName
= 0; /* doesn't fit */
1538 /* make sure that we don't read/write beyond the provided buffer */
1539 if (otm
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(char *))
1541 if ((UINT_PTR
)otm
->otmpFaceName
>= otm
->otmSize
)
1542 otm
->otmpFaceName
= 0; /* doesn't fit */
1545 /* make sure that we don't read/write beyond the provided buffer */
1546 if (otm
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(char *))
1548 if ((UINT_PTR
)otm
->otmpStyleName
>= otm
->otmSize
)
1549 otm
->otmpStyleName
= 0; /* doesn't fit */
1552 /* make sure that we don't read/write beyond the provided buffer */
1553 if (otm
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(char *))
1555 if ((UINT_PTR
)otm
->otmpFullName
>= otm
->otmSize
)
1556 otm
->otmpFullName
= 0; /* doesn't fit */
1561 if (otmW
!= (OUTLINETEXTMETRICW
*)buf
)
1562 HeapFree(GetProcessHeap(), 0, otmW
);
1566 /***********************************************************************
1567 * GetOutlineTextMetricsW [GDI32.@]
1569 UINT WINAPI
GetOutlineTextMetricsW( HDC hdc
, UINT size
, OUTLINETEXTMETRICW
*otm
)
1571 return NtGdiGetOutlineTextMetricsInternalW( hdc
, size
, otm
, 0 );
1574 /***********************************************************************
1575 * GetCharWidthW (GDI32.@)
1576 * GetCharWidth32W (GDI32.@)
1578 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT first
, UINT last
, INT
*buffer
)
1580 return NtGdiGetCharWidthW( hdc
, first
, last
, NULL
, NTGDI_GETCHARWIDTH_INT
, buffer
);
1583 static WCHAR
*get_chars_by_range( HDC hdc
, UINT first
, UINT last
, INT
*ret_len
)
1585 INT i
, count
= last
- first
+ 1;
1594 mbcp
= GdiGetCodePage( hdc
);
1604 if ((first
^ last
) > 0xff)
1614 if (!(str
= HeapAlloc( GetProcessHeap(), 0, count
* 2 + 1 )))
1617 for (i
= 0, c
= first
; c
<= last
; i
++, c
++)
1621 str
[i
++] = (BYTE
)(c
>> 8);
1622 if (c
<= 0xff && IsDBCSLeadByteEx( mbcp
, c
))
1623 str
[i
] = 0x1f; /* FIXME: use default character */
1632 wstr
= text_mbtowc( hdc
, str
, i
, ret_len
, NULL
);
1633 HeapFree( GetProcessHeap(), 0, str
);
1637 /***********************************************************************
1638 * GetCharWidthA (GDI32.@)
1639 * GetCharWidth32A (GDI32.@)
1641 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT first
, UINT last
, INT
*buffer
)
1647 if (!(chars
= get_chars_by_range( hdc
, first
, last
, &count
))) return FALSE
;
1648 ret
= NtGdiGetCharWidthW( hdc
, 0, count
, chars
, NTGDI_GETCHARWIDTH_INT
, buffer
);
1649 HeapFree( GetProcessHeap(), 0, chars
);
1653 /***********************************************************************
1654 * GetCharWidthFloatW (GDI32.@)
1656 BOOL WINAPI
GetCharWidthFloatW( HDC hdc
, UINT first
, UINT last
, float *buffer
)
1658 return NtGdiGetCharWidthW( hdc
, first
, last
, NULL
, 0, buffer
);
1661 /***********************************************************************
1662 * GetCharWidthFloatA (GDI32.@)
1664 BOOL WINAPI
GetCharWidthFloatA( HDC hdc
, UINT first
, UINT last
, float *buffer
)
1670 if (!(chars
= get_chars_by_range( hdc
, first
, last
, &count
))) return FALSE
;
1671 ret
= NtGdiGetCharWidthW( hdc
, 0, count
, chars
, 0, buffer
);
1672 HeapFree( GetProcessHeap(), 0, chars
);
1676 /***********************************************************************
1677 * GetCharWidthI (GDI32.@)
1679 BOOL WINAPI
GetCharWidthI( HDC hdc
, UINT first
, UINT count
, WORD
*glyphs
, INT
*buffer
)
1681 TRACE( "(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
1682 return NtGdiGetCharWidthW( hdc
, first
, count
, glyphs
,
1683 NTGDI_GETCHARWIDTH_INT
| NTGDI_GETCHARWIDTH_INDICES
, buffer
);
1686 /***********************************************************************
1687 * GetCharABCWidthsW (GDI32.@)
1689 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT first
, UINT last
, ABC
*abc
)
1691 return NtGdiGetCharABCWidthsW( hdc
, first
, last
, NULL
, NTGDI_GETCHARABCWIDTHS_INT
, abc
);
1694 /***********************************************************************
1695 * GetCharABCWidthsA (GDI32.@)
1697 * See GetCharABCWidthsW.
1699 BOOL WINAPI
GetCharABCWidthsA( HDC hdc
, UINT first
, UINT last
, ABC
*abc
)
1705 if (!(chars
= get_chars_by_range( hdc
, first
, last
, &count
))) return FALSE
;
1706 ret
= NtGdiGetCharABCWidthsW( hdc
, 0, count
, chars
, NTGDI_GETCHARABCWIDTHS_INT
, abc
);
1707 HeapFree( GetProcessHeap(), 0, chars
);
1711 /***********************************************************************
1712 * GetCharABCWidthsI (GDI32.@)
1714 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT first
, UINT count
, WORD
*glyphs
, ABC
*buffer
)
1716 TRACE( "(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
1717 return NtGdiGetCharABCWidthsW( hdc
, first
, count
, glyphs
,
1718 NTGDI_GETCHARABCWIDTHS_INDICES
| NTGDI_GETCHARABCWIDTHS_INT
,