4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
37 #include "gdi_private.h"
38 #include "wine/exception.h"
39 #include "wine/unicode.h"
40 #include "wine/debug.h"
42 WINE_DEFAULT_DEBUG_CHANNEL(font
);
44 /* Device -> World size conversion */
46 /* Performs a device to world transformation on the specified width (which
47 * is in integer format).
49 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
53 /* Perform operation with floating point */
54 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
55 /* Round to integers */
56 return GDI_ROUND(floatWidth
);
59 /* Performs a device to world transformation on the specified size (which
60 * is in integer format).
62 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
66 /* Perform operation with floating point */
67 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
68 /* Round to integers */
69 return GDI_ROUND(floatHeight
);
72 /* scale width and height but don't mirror them */
74 static inline INT
width_to_LP( DC
*dc
, INT width
)
76 return GDI_ROUND( (double)width
* fabs( dc
->xformVport2World
.eM11
));
79 static inline INT
height_to_LP( DC
*dc
, INT height
)
81 return GDI_ROUND( (double)height
* fabs( dc
->xformVport2World
.eM22
));
84 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
87 pt
[0].x
= pt
[0].y
= 0;
91 return pt
[1].y
- pt
[0].y
;
94 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
95 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
96 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
97 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
99 static const struct gdi_obj_funcs font_funcs
=
101 FONT_SelectObject
, /* pSelectObject */
102 FONT_GetObjectA
, /* pGetObjectA */
103 FONT_GetObjectW
, /* pGetObjectW */
104 NULL
, /* pUnrealizeObject */
105 FONT_DeleteObject
/* pDeleteObject */
115 LPLOGFONTW lpLogFontParam
;
116 FONTENUMPROCW lpEnumFunc
;
124 * For TranslateCharsetInfo
126 #define MAXTCIINDEX 32
127 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
129 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
130 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
131 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
132 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
133 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
134 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
135 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
136 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
137 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
138 /* reserved by ANSI */
139 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
140 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
141 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
142 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
143 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
144 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
145 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
147 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
148 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
149 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
150 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
151 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
152 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
153 /* reserved for alternate ANSI and OEM */
154 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
155 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
156 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
157 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
160 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
161 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 /* reserved for system */
163 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
164 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
167 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
169 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
170 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
172 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
175 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
177 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
178 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
179 LF_FACESIZE
, NULL
, NULL
);
180 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
183 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
185 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
187 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
188 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
189 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
190 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
191 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
192 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
193 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
194 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
195 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
198 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
200 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
202 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
203 fontW
->elfFullName
, LF_FULLFACESIZE
);
204 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
205 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
206 fontW
->elfStyle
, LF_FACESIZE
);
207 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
208 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
209 fontW
->elfScript
, LF_FACESIZE
);
210 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
213 /***********************************************************************
214 * TEXTMETRIC conversion functions.
216 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
218 ptmA
->tmHeight
= ptmW
->tmHeight
;
219 ptmA
->tmAscent
= ptmW
->tmAscent
;
220 ptmA
->tmDescent
= ptmW
->tmDescent
;
221 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
222 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
223 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
224 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
225 ptmA
->tmWeight
= ptmW
->tmWeight
;
226 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
227 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
228 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
229 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
230 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
232 ptmA
->tmFirstChar
= 0x1e;
233 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
235 else if (ptmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
237 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
238 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
242 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 0xff);
243 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
245 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
246 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
247 ptmA
->tmItalic
= ptmW
->tmItalic
;
248 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
249 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
250 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
251 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
255 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
257 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
258 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
259 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
260 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
261 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
262 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
265 static DWORD
get_key_value( HKEY key
, const WCHAR
*name
, DWORD
*value
)
268 DWORD count
= sizeof(buf
), type
, err
;
270 err
= RegQueryValueExW( key
, name
, NULL
, &type
, (BYTE
*)buf
, &count
);
273 if (type
== REG_DWORD
) memcpy( value
, buf
, sizeof(*value
) );
274 else *value
= atoiW( buf
);
279 static UINT
get_subpixel_orientation( HKEY key
)
281 static const WCHAR smoothing_orientation
[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',
282 'O','r','i','e','n','t','a','t','i','o','n',0};
285 /* FIXME: handle vertical orientations even though Windows doesn't */
286 if (get_key_value( key
, smoothing_orientation
, &orient
)) return GGO_GRAY4_BITMAP
;
290 case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */
291 return WINE_GGO_HBGR_BITMAP
;
292 case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */
293 return WINE_GGO_HRGB_BITMAP
;
295 return GGO_GRAY4_BITMAP
;
298 static UINT
get_default_smoothing( HKEY key
)
300 static const WCHAR smoothing
[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',0};
301 static const WCHAR smoothing_type
[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0};
304 if (get_key_value( key
, smoothing
, &enabled
)) return 0;
305 if (!enabled
) return GGO_BITMAP
;
307 if (!get_key_value( key
, smoothing_type
, &type
) && type
== 2 /* FE_FONTSMOOTHINGCLEARTYPE */)
308 return get_subpixel_orientation( key
);
310 return GGO_GRAY4_BITMAP
;
313 /* compute positions for text rendering, in device coords */
314 static BOOL
get_char_positions( DC
*dc
, const WCHAR
*str
, INT count
, INT
*dx
, SIZE
*size
)
319 size
->cx
= size
->cy
= 0;
320 if (!count
) return TRUE
;
322 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
323 dev
->funcs
->pGetTextMetrics( dev
, &tm
);
325 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
326 if (!dev
->funcs
->pGetTextExtentExPoint( dev
, str
, count
, dx
)) return FALSE
;
328 if (dc
->breakExtra
|| dc
->breakRem
)
330 int i
, space
= 0, rem
= dc
->breakRem
;
332 for (i
= 0; i
< count
; i
++)
334 if (str
[i
] == tm
.tmBreakChar
)
336 space
+= dc
->breakExtra
;
346 size
->cx
= dx
[count
- 1];
347 size
->cy
= tm
.tmHeight
;
351 /* compute positions for text rendering, in device coords */
352 static BOOL
get_char_positions_indices( DC
*dc
, const WORD
*indices
, INT count
, INT
*dx
, SIZE
*size
)
357 size
->cx
= size
->cy
= 0;
358 if (!count
) return TRUE
;
360 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
361 dev
->funcs
->pGetTextMetrics( dev
, &tm
);
363 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPointI
);
364 if (!dev
->funcs
->pGetTextExtentExPointI( dev
, indices
, count
, dx
)) return FALSE
;
366 if (dc
->breakExtra
|| dc
->breakRem
)
369 int i
, space
= 0, rem
= dc
->breakRem
;
371 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
372 dev
->funcs
->pGetGlyphIndices( dev
, &tm
.tmBreakChar
, 1, &space_index
, 0 );
374 for (i
= 0; i
< count
; i
++)
376 if (indices
[i
] == space_index
)
378 space
+= dc
->breakExtra
;
388 size
->cx
= dx
[count
- 1];
389 size
->cy
= tm
.tmHeight
;
393 /***********************************************************************
394 * GdiGetCodePage (GDI32.@)
396 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
399 DC
*dc
= get_dc_ptr( hdc
);
403 cp
= dc
->font_code_page
;
404 release_dc_ptr( dc
);
409 /***********************************************************************
410 * get_text_charset_info
412 * Internal version of GetTextCharsetInfo() that takes a DC pointer.
414 static UINT
get_text_charset_info(DC
*dc
, FONTSIGNATURE
*fs
, DWORD flags
)
416 UINT ret
= DEFAULT_CHARSET
;
419 dev
= GET_DC_PHYSDEV( dc
, pGetTextCharsetInfo
);
420 ret
= dev
->funcs
->pGetTextCharsetInfo( dev
, fs
, flags
);
422 if (ret
== DEFAULT_CHARSET
&& fs
)
423 memset(fs
, 0, sizeof(FONTSIGNATURE
));
427 /***********************************************************************
428 * GetTextCharsetInfo (GDI32.@)
430 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, FONTSIGNATURE
*fs
, DWORD flags
)
432 UINT ret
= DEFAULT_CHARSET
;
433 DC
*dc
= get_dc_ptr(hdc
);
437 ret
= get_text_charset_info( dc
, fs
, flags
);
438 release_dc_ptr( dc
);
443 /***********************************************************************
446 * Returns a Unicode translation of str using the charset of the
447 * currently selected font in hdc. If count is -1 then str is assumed
448 * to be '\0' terminated, otherwise it contains the number of bytes to
449 * convert. If plenW is non-NULL, on return it will point to the
450 * number of WCHARs that have been written. If pCP is non-NULL, on
451 * return it will point to the codepage used in the conversion. The
452 * caller should free the returned LPWSTR from the process heap
455 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
461 cp
= GdiGetCodePage( hdc
);
463 if(count
== -1) count
= strlen(str
);
464 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
465 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
466 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
467 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
468 if(plenW
) *plenW
= lenW
;
473 /***********************************************************************
474 * CreateFontIndirectExA (GDI32.@)
476 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
478 ENUMLOGFONTEXDVW enumexW
;
480 if (!penumexA
) return 0;
482 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
483 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
484 return CreateFontIndirectExW( &enumexW
);
487 /***********************************************************************
488 * CreateFontIndirectExW (GDI32.@)
490 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
496 if (!penumex
) return 0;
498 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
499 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
500 penumex
->elfEnumLogfontEx
.elfScript
[0])
502 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
503 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
504 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
505 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
508 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
509 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
511 fontPtr
->logfont
= *plf
;
513 if (!(hFont
= alloc_gdi_handle( fontPtr
, OBJ_FONT
, &font_funcs
)))
515 HeapFree( GetProcessHeap(), 0, fontPtr
);
519 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
520 plf
->lfHeight
, plf
->lfWidth
,
521 plf
->lfEscapement
, plf
->lfOrientation
,
522 plf
->lfPitchAndFamily
,
523 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
524 plf
->lfQuality
, plf
->lfCharSet
,
525 debugstr_w(plf
->lfFaceName
),
526 plf
->lfWeight
> 400 ? "Bold" : "",
527 plf
->lfItalic
? "Italic" : "",
528 plf
->lfUnderline
? "Underline" : "", hFont
);
533 /***********************************************************************
534 * CreateFontIndirectA (GDI32.@)
536 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
542 FONT_LogFontAToW( plfA
, &lfW
);
543 return CreateFontIndirectW( &lfW
);
546 /***********************************************************************
547 * CreateFontIndirectW (GDI32.@)
549 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
551 ENUMLOGFONTEXDVW exdv
;
555 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
556 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
557 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
558 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
559 return CreateFontIndirectExW( &exdv
);
562 /*************************************************************************
563 * CreateFontA (GDI32.@)
565 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
566 INT orient
, INT weight
, DWORD italic
,
567 DWORD underline
, DWORD strikeout
, DWORD charset
,
568 DWORD outpres
, DWORD clippres
, DWORD quality
,
569 DWORD pitch
, LPCSTR name
)
573 logfont
.lfHeight
= height
;
574 logfont
.lfWidth
= width
;
575 logfont
.lfEscapement
= esc
;
576 logfont
.lfOrientation
= orient
;
577 logfont
.lfWeight
= weight
;
578 logfont
.lfItalic
= italic
;
579 logfont
.lfUnderline
= underline
;
580 logfont
.lfStrikeOut
= strikeout
;
581 logfont
.lfCharSet
= charset
;
582 logfont
.lfOutPrecision
= outpres
;
583 logfont
.lfClipPrecision
= clippres
;
584 logfont
.lfQuality
= quality
;
585 logfont
.lfPitchAndFamily
= pitch
;
588 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
590 logfont
.lfFaceName
[0] = '\0';
592 return CreateFontIndirectA( &logfont
);
595 /*************************************************************************
596 * CreateFontW (GDI32.@)
598 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
599 INT orient
, INT weight
, DWORD italic
,
600 DWORD underline
, DWORD strikeout
, DWORD charset
,
601 DWORD outpres
, DWORD clippres
, DWORD quality
,
602 DWORD pitch
, LPCWSTR name
)
606 logfont
.lfHeight
= height
;
607 logfont
.lfWidth
= width
;
608 logfont
.lfEscapement
= esc
;
609 logfont
.lfOrientation
= orient
;
610 logfont
.lfWeight
= weight
;
611 logfont
.lfItalic
= italic
;
612 logfont
.lfUnderline
= underline
;
613 logfont
.lfStrikeOut
= strikeout
;
614 logfont
.lfCharSet
= charset
;
615 logfont
.lfOutPrecision
= outpres
;
616 logfont
.lfClipPrecision
= clippres
;
617 logfont
.lfQuality
= quality
;
618 logfont
.lfPitchAndFamily
= pitch
;
621 lstrcpynW(logfont
.lfFaceName
, name
,
622 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
624 logfont
.lfFaceName
[0] = '\0';
626 return CreateFontIndirectW( &logfont
);
629 #define ASSOC_CHARSET_OEM 1
630 #define ASSOC_CHARSET_ANSI 2
631 #define ASSOC_CHARSET_SYMBOL 4
633 static DWORD
get_associated_charset_info(void)
635 static DWORD associated_charset
= -1;
637 if (associated_charset
== -1)
639 static const WCHAR assoc_charset_reg_keyW
[] = {'S','y','s','t','e','m','\\',
640 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
641 'C','o','n','t','r','o','l','\\','F','o','n','t','A','s','s','o','c','\\',
642 'A','s','s','o','c','i','a','t','e','d',' ','C','h','a','r','s','e','t','\0'};
643 static const WCHAR ansiW
[] = {'A','N','S','I','(','0','0',')','\0'};
644 static const WCHAR oemW
[] = {'O','E','M','(','F','F',')','\0'};
645 static const WCHAR symbolW
[] = {'S','Y','M','B','O','L','(','0','2',')','\0'};
646 static const WCHAR yesW
[] = {'Y','E','S','\0'};
649 DWORD type
, data_len
;
651 associated_charset
= 0;
653 if (RegOpenKeyW(HKEY_LOCAL_MACHINE
,
654 assoc_charset_reg_keyW
, &hkey
) != ERROR_SUCCESS
)
657 data_len
= sizeof(dataW
);
658 if (!RegQueryValueExW(hkey
, ansiW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
659 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
660 associated_charset
|= ASSOC_CHARSET_ANSI
;
662 data_len
= sizeof(dataW
);
663 if (!RegQueryValueExW(hkey
, oemW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
664 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
665 associated_charset
|= ASSOC_CHARSET_OEM
;
667 data_len
= sizeof(dataW
);
668 if (!RegQueryValueExW(hkey
, symbolW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
669 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
670 associated_charset
|= ASSOC_CHARSET_SYMBOL
;
674 TRACE("associated_charset = %d\n", associated_charset
);
677 return associated_charset
;
680 static void update_font_code_page( DC
*dc
, HANDLE font
)
683 int charset
= get_text_charset_info( dc
, NULL
, 0 );
685 if (charset
== ANSI_CHARSET
&& get_associated_charset_info() & ASSOC_CHARSET_ANSI
)
689 GetObjectW( font
, sizeof(lf
), &lf
);
690 if (!(lf
.lfClipPrecision
& CLIP_DFA_DISABLE
))
691 charset
= DEFAULT_CHARSET
;
694 /* Hmm, nicely designed api this one! */
695 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
696 dc
->font_code_page
= csi
.ciACP
;
700 dc
->font_code_page
= GetOEMCP();
702 case DEFAULT_CHARSET
:
703 dc
->font_code_page
= GetACP();
713 /* FIXME: These have no place here, but because x11drv
714 enumerates fonts with these (made up) charsets some apps
715 might use them and then the FIXME below would become
716 annoying. Now we could pick the intended codepage for
717 each of these, but since it's broken anyway we'll just
718 use CP_ACP and hope it'll go away...
720 dc
->font_code_page
= CP_ACP
;
724 FIXME("Can't find codepage for charset %d\n", charset
);
725 dc
->font_code_page
= CP_ACP
;
730 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
733 /***********************************************************************
736 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
739 DC
*dc
= get_dc_ptr( hdc
);
745 if (!GDI_inc_ref_count( handle
))
747 release_dc_ptr( dc
);
751 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
752 if (physdev
->funcs
->pSelectFont( physdev
, handle
, &aa_flags
))
756 dc
->aa_flags
= aa_flags
? aa_flags
: GGO_BITMAP
;
757 update_font_code_page( dc
, handle
);
758 GDI_dec_ref_count( ret
);
760 else GDI_dec_ref_count( handle
);
762 release_dc_ptr( dc
);
767 /***********************************************************************
770 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
772 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
778 FONT_LogFontWToA( &font
->logfont
, &lfA
);
779 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
780 memcpy( buffer
, &lfA
, count
);
782 else count
= sizeof(lfA
);
783 GDI_ReleaseObj( handle
);
787 /***********************************************************************
790 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
792 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
797 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
798 memcpy( buffer
, &font
->logfont
, count
);
800 else count
= sizeof(LOGFONTW
);
801 GDI_ReleaseObj( handle
);
806 /***********************************************************************
809 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
813 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
814 return HeapFree( GetProcessHeap(), 0, obj
);
818 /***********************************************************************
821 HFONT
nulldrv_SelectFont( PHYSDEV dev
, HFONT font
, UINT
*aa_flags
)
823 static const WCHAR desktopW
[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
824 'D','e','s','k','t','o','p',0 };
825 static int orientation
= -1, smoothing
= -1;
829 if (*aa_flags
) return 0;
831 GetObjectW( font
, sizeof(lf
), &lf
);
832 switch (lf
.lfQuality
)
834 case NONANTIALIASED_QUALITY
:
835 *aa_flags
= GGO_BITMAP
;
837 case ANTIALIASED_QUALITY
:
838 *aa_flags
= GGO_GRAY4_BITMAP
;
840 case CLEARTYPE_QUALITY
:
841 case CLEARTYPE_NATURAL_QUALITY
:
842 if (orientation
== -1)
844 if (RegOpenKeyW( HKEY_CURRENT_USER
, desktopW
, &key
)) break;
845 orientation
= get_subpixel_orientation( key
);
848 *aa_flags
= orientation
;
853 if (RegOpenKeyW( HKEY_CURRENT_USER
, desktopW
, &key
)) break;
854 smoothing
= get_default_smoothing( key
);
857 *aa_flags
= smoothing
;
864 /***********************************************************************
867 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
868 * We have to use other types because of the FONTENUMPROCW definition.
870 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
871 DWORD fType
, LPARAM lp
)
873 struct font_enum
*pfe
= (struct font_enum
*)lp
;
876 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
877 if ((!pfe
->lpLogFontParam
||
878 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
879 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
880 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
882 /* convert font metrics */
883 ENUMLOGFONTEXA logfont
;
884 NEWTEXTMETRICEXA tmA
;
888 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
889 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
890 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
891 ptm
= (TEXTMETRICW
*)&tmA
;
893 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
899 /***********************************************************************
900 * FONT_EnumFontFamiliesEx
902 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
903 LPARAM lParam
, BOOL unicode
)
906 DC
*dc
= get_dc_ptr( hDC
);
911 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
913 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
914 fe
.lpLogFontParam
= plf
;
915 fe
.lpEnumFunc
= efproc
;
917 fe
.unicode
= unicode
;
920 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
921 release_dc_ptr( dc
);
923 return ret
? fe
.retval
: 0;
926 /***********************************************************************
927 * EnumFontFamiliesExW (GDI32.@)
929 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
930 FONTENUMPROCW efproc
,
931 LPARAM lParam
, DWORD dwFlags
)
933 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
936 /***********************************************************************
937 * EnumFontFamiliesExA (GDI32.@)
939 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
940 FONTENUMPROCA efproc
,
941 LPARAM lParam
, DWORD dwFlags
)
947 FONT_LogFontAToW( plf
, &lfW
);
952 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
955 /***********************************************************************
956 * EnumFontFamiliesA (GDI32.@)
958 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
959 FONTENUMPROCA efproc
, LPARAM lpData
)
965 if (!*lpFamily
) return 1;
966 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
967 lf
.lfCharSet
= DEFAULT_CHARSET
;
968 lf
.lfPitchAndFamily
= 0;
973 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
976 /***********************************************************************
977 * EnumFontFamiliesW (GDI32.@)
979 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
980 FONTENUMPROCW efproc
, LPARAM lpData
)
986 if (!*lpFamily
) return 1;
987 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
988 lf
.lfCharSet
= DEFAULT_CHARSET
;
989 lf
.lfPitchAndFamily
= 0;
994 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
997 /***********************************************************************
998 * EnumFontsA (GDI32.@)
1000 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
1003 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
1006 /***********************************************************************
1007 * EnumFontsW (GDI32.@)
1009 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
1012 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
1016 /***********************************************************************
1017 * GetTextCharacterExtra (GDI32.@)
1019 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
1022 DC
*dc
= get_dc_ptr( hdc
);
1023 if (!dc
) return 0x80000000;
1024 ret
= dc
->charExtra
;
1025 release_dc_ptr( dc
);
1030 /***********************************************************************
1031 * SetTextCharacterExtra (GDI32.@)
1033 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
1035 INT ret
= 0x80000000;
1036 DC
* dc
= get_dc_ptr( hdc
);
1040 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
1041 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
1042 if (extra
!= 0x80000000)
1044 ret
= dc
->charExtra
;
1045 dc
->charExtra
= extra
;
1047 release_dc_ptr( dc
);
1053 /***********************************************************************
1054 * SetTextJustification (GDI32.@)
1056 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1060 DC
* dc
= get_dc_ptr( hdc
);
1062 if (!dc
) return FALSE
;
1064 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
1065 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
1068 extra
= abs((extra
* dc
->vport_ext
.cx
+ dc
->wnd_ext
.cx
/ 2) / dc
->wnd_ext
.cx
);
1069 if (!extra
) breaks
= 0;
1072 dc
->breakExtra
= extra
/ breaks
;
1073 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1081 release_dc_ptr( dc
);
1086 /***********************************************************************
1087 * GetTextFaceA (GDI32.@)
1089 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1091 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1092 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1093 GetTextFaceW( hdc
, res
, nameW
);
1099 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
1103 /* GetTextFaceA does NOT include the nul byte in the return count. */
1110 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1111 HeapFree( GetProcessHeap(), 0, nameW
);
1115 /***********************************************************************
1116 * GetTextFaceW (GDI32.@)
1118 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1123 DC
* dc
= get_dc_ptr( hdc
);
1126 dev
= GET_DC_PHYSDEV( dc
, pGetTextFace
);
1127 ret
= dev
->funcs
->pGetTextFace( dev
, count
, name
);
1128 release_dc_ptr( dc
);
1133 /***********************************************************************
1134 * GetTextExtentPoint32A (GDI32.@)
1136 * See GetTextExtentPoint32W.
1138 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1145 if (count
< 0) return FALSE
;
1147 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1151 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1152 HeapFree( GetProcessHeap(), 0, p
);
1155 TRACE("(%p %s %d %p): returning %d x %d\n",
1156 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1161 /***********************************************************************
1162 * GetTextExtentPoint32W [GDI32.@]
1164 * Computes width/height for a string.
1166 * Computes width and height of the specified string.
1172 BOOL WINAPI
GetTextExtentPoint32W(
1173 HDC hdc
, /* [in] Handle of device context */
1174 LPCWSTR str
, /* [in] Address of text string */
1175 INT count
, /* [in] Number of characters in string */
1176 LPSIZE size
) /* [out] Address of structure for string size */
1178 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1181 /***********************************************************************
1182 * GetTextExtentExPointI [GDI32.@]
1184 * Computes width and height of the array of glyph indices.
1187 * hdc [I] Handle of device context.
1188 * indices [I] Glyph index array.
1189 * count [I] Number of glyphs in array.
1190 * max_ext [I] Maximum width in glyphs.
1191 * nfit [O] Maximum number of characters.
1192 * dxs [O] Partial string widths.
1193 * size [O] Returned string size.
1199 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1200 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1205 INT buffer
[256], *pos
= dxs
;
1207 if (count
< 0) return FALSE
;
1209 dc
= get_dc_ptr( hdc
);
1210 if (!dc
) return FALSE
;
1215 if (count
> 256 && !(pos
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pos
) )))
1217 release_dc_ptr( dc
);
1222 ret
= get_char_positions_indices( dc
, indices
, count
, pos
, size
);
1227 for (i
= 0; i
< count
; i
++)
1229 unsigned int dx
= abs( INTERNAL_XDSTOWS( dc
, pos
[i
] )) + (i
+ 1) * dc
->charExtra
;
1230 if (nfit
&& dx
> (unsigned int)max_ext
) break;
1231 if (dxs
) dxs
[i
] = dx
;
1233 if (nfit
) *nfit
= i
;
1236 size
->cx
= abs( INTERNAL_XDSTOWS( dc
, size
->cx
)) + count
* dc
->charExtra
;
1237 size
->cy
= abs( INTERNAL_YDSTOWS( dc
, size
->cy
));
1240 if (pos
!= buffer
&& pos
!= dxs
) HeapFree( GetProcessHeap(), 0, pos
);
1241 release_dc_ptr( dc
);
1243 TRACE("(%p %p %d %p): returning %d x %d\n",
1244 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1248 /***********************************************************************
1249 * GetTextExtentPointI [GDI32.@]
1251 * Computes width and height of the array of glyph indices.
1254 * hdc [I] Handle of device context.
1255 * indices [I] Glyph index array.
1256 * count [I] Number of glyphs in array.
1257 * size [O] Returned string size.
1263 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1265 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1269 /***********************************************************************
1270 * GetTextExtentPointA (GDI32.@)
1272 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1275 TRACE("not bug compatible.\n");
1276 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1279 /***********************************************************************
1280 * GetTextExtentPointW (GDI32.@)
1282 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1285 TRACE("not bug compatible.\n");
1286 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1290 /***********************************************************************
1291 * GetTextExtentExPointA (GDI32.@)
1293 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1294 INT maxExt
, LPINT lpnFit
,
1295 LPINT alpDx
, LPSIZE size
)
1302 if (count
< 0) return FALSE
;
1303 if (maxExt
< -1) return FALSE
;
1307 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1308 if (!walpDx
) return FALSE
;
1311 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1312 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1315 INT n
= lpnFit
? *lpnFit
: wlen
;
1317 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1319 alpDx
[j
] = walpDx
[i
];
1320 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1323 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1324 HeapFree( GetProcessHeap(), 0, p
);
1325 HeapFree( GetProcessHeap(), 0, walpDx
);
1330 /***********************************************************************
1331 * GetTextExtentExPointW (GDI32.@)
1333 * Return the size of the string as it would be if it was output properly by
1336 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
, INT max_ext
,
1337 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1342 INT buffer
[256], *pos
= dxs
;
1344 if (count
< 0) return FALSE
;
1346 dc
= get_dc_ptr(hdc
);
1347 if (!dc
) return FALSE
;
1352 if (count
> 256 && !(pos
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pos
) )))
1354 release_dc_ptr( dc
);
1359 ret
= get_char_positions( dc
, str
, count
, pos
, size
);
1364 for (i
= 0; i
< count
; i
++)
1366 unsigned int dx
= abs( INTERNAL_XDSTOWS( dc
, pos
[i
] )) + (i
+ 1) * dc
->charExtra
;
1367 if (nfit
&& dx
> (unsigned int)max_ext
) break;
1368 if (dxs
) dxs
[i
] = dx
;
1370 if (nfit
) *nfit
= i
;
1373 size
->cx
= abs( INTERNAL_XDSTOWS( dc
, size
->cx
)) + count
* dc
->charExtra
;
1374 size
->cy
= abs( INTERNAL_YDSTOWS( dc
, size
->cy
));
1377 if (pos
!= buffer
&& pos
!= dxs
) HeapFree( GetProcessHeap(), 0, pos
);
1378 release_dc_ptr( dc
);
1380 TRACE("(%p, %s, %d) returning %dx%d\n", hdc
, debugstr_wn(str
,count
), max_ext
, size
->cx
, size
->cy
);
1384 /***********************************************************************
1385 * GetTextMetricsA (GDI32.@)
1387 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1391 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1392 FONT_TextMetricWToA( &tm32
, metrics
);
1396 /***********************************************************************
1397 * GetTextMetricsW (GDI32.@)
1399 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1403 DC
* dc
= get_dc_ptr( hdc
);
1404 if (!dc
) return FALSE
;
1406 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1407 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1411 /* device layer returns values in device units
1412 * therefore we have to convert them to logical */
1414 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1415 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1416 metrics
->tmHeight
= height_to_LP( dc
, metrics
->tmHeight
);
1417 metrics
->tmAscent
= height_to_LP( dc
, metrics
->tmAscent
);
1418 metrics
->tmDescent
= height_to_LP( dc
, metrics
->tmDescent
);
1419 metrics
->tmInternalLeading
= height_to_LP( dc
, metrics
->tmInternalLeading
);
1420 metrics
->tmExternalLeading
= height_to_LP( dc
, metrics
->tmExternalLeading
);
1421 metrics
->tmAveCharWidth
= width_to_LP( dc
, metrics
->tmAveCharWidth
);
1422 metrics
->tmMaxCharWidth
= width_to_LP( dc
, metrics
->tmMaxCharWidth
);
1423 metrics
->tmOverhang
= width_to_LP( dc
, metrics
->tmOverhang
);
1426 TRACE("text metrics:\n"
1427 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1428 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1429 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1430 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1431 " PitchAndFamily = %02x\n"
1432 " --------------------\n"
1433 " InternalLeading = %i\n"
1437 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1438 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1439 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1440 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1441 metrics
->tmPitchAndFamily
,
1442 metrics
->tmInternalLeading
,
1445 metrics
->tmHeight
);
1447 release_dc_ptr( dc
);
1452 /***********************************************************************
1453 * GetOutlineTextMetricsA (GDI32.@)
1454 * Gets metrics for TrueType fonts.
1457 * If the supplied buffer isn't big enough Windows partially fills it up to
1458 * its given length and returns that length.
1461 * Success: Non-zero or size of required buffer
1464 UINT WINAPI
GetOutlineTextMetricsA(
1465 HDC hdc
, /* [in] Handle of device context */
1466 UINT cbData
, /* [in] Size of metric data array */
1467 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1469 char buf
[512], *ptr
;
1471 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1472 OUTLINETEXTMETRICA
*output
= lpOTM
;
1475 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1477 if(ret
> sizeof(buf
))
1478 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1479 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1481 needed
= sizeof(OUTLINETEXTMETRICA
);
1482 if(lpOTMW
->otmpFamilyName
)
1483 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1484 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1485 NULL
, 0, NULL
, NULL
);
1486 if(lpOTMW
->otmpFaceName
)
1487 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1488 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1489 NULL
, 0, NULL
, NULL
);
1490 if(lpOTMW
->otmpStyleName
)
1491 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1492 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1493 NULL
, 0, NULL
, NULL
);
1494 if(lpOTMW
->otmpFullName
)
1495 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1496 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1497 NULL
, 0, NULL
, NULL
);
1504 TRACE("needed = %d\n", needed
);
1506 /* Since the supplied buffer isn't big enough, we'll alloc one
1507 that is and memcpy the first cbData bytes into the lpOTM at
1509 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1511 ret
= output
->otmSize
= min(needed
, cbData
);
1512 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1513 output
->otmFiller
= 0;
1514 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1515 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1516 output
->otmfsType
= lpOTMW
->otmfsType
;
1517 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1518 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1519 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1520 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1521 output
->otmAscent
= lpOTMW
->otmAscent
;
1522 output
->otmDescent
= lpOTMW
->otmDescent
;
1523 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1524 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1525 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1526 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1527 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1528 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1529 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1530 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1531 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1532 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1533 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1534 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1535 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1536 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1537 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1538 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1541 ptr
= (char*)(output
+ 1);
1542 left
= needed
- sizeof(*output
);
1544 if(lpOTMW
->otmpFamilyName
) {
1545 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1546 len
= WideCharToMultiByte(CP_ACP
, 0,
1547 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1548 ptr
, left
, NULL
, NULL
);
1552 output
->otmpFamilyName
= 0;
1554 if(lpOTMW
->otmpFaceName
) {
1555 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1556 len
= WideCharToMultiByte(CP_ACP
, 0,
1557 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1558 ptr
, left
, NULL
, NULL
);
1562 output
->otmpFaceName
= 0;
1564 if(lpOTMW
->otmpStyleName
) {
1565 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1566 len
= WideCharToMultiByte(CP_ACP
, 0,
1567 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1568 ptr
, left
, NULL
, NULL
);
1572 output
->otmpStyleName
= 0;
1574 if(lpOTMW
->otmpFullName
) {
1575 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1576 len
= WideCharToMultiByte(CP_ACP
, 0,
1577 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1578 ptr
, left
, NULL
, NULL
);
1581 output
->otmpFullName
= 0;
1585 if(output
!= lpOTM
) {
1586 memcpy(lpOTM
, output
, cbData
);
1587 HeapFree(GetProcessHeap(), 0, output
);
1589 /* check if the string offsets really fit into the provided size */
1590 /* FIXME: should we check string length as well? */
1591 /* make sure that we don't read/write beyond the provided buffer */
1592 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1594 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1595 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1598 /* make sure that we don't read/write beyond the provided buffer */
1599 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1601 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1602 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1605 /* make sure that we don't read/write beyond the provided buffer */
1606 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1608 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1609 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1612 /* make sure that we don't read/write beyond the provided buffer */
1613 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1615 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1616 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1621 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1622 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1628 /***********************************************************************
1629 * GetOutlineTextMetricsW [GDI32.@]
1631 UINT WINAPI
GetOutlineTextMetricsW(
1632 HDC hdc
, /* [in] Handle of device context */
1633 UINT cbData
, /* [in] Size of metric data array */
1634 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1636 DC
*dc
= get_dc_ptr( hdc
);
1637 OUTLINETEXTMETRICW
*output
= lpOTM
;
1641 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1644 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1645 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1647 if (lpOTM
&& ret
> cbData
)
1649 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1650 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1655 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1656 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1657 output
->otmTextMetrics
.tmHeight
= height_to_LP( dc
, output
->otmTextMetrics
.tmHeight
);
1658 output
->otmTextMetrics
.tmAscent
= height_to_LP( dc
, output
->otmTextMetrics
.tmAscent
);
1659 output
->otmTextMetrics
.tmDescent
= height_to_LP( dc
, output
->otmTextMetrics
.tmDescent
);
1660 output
->otmTextMetrics
.tmInternalLeading
= height_to_LP( dc
, output
->otmTextMetrics
.tmInternalLeading
);
1661 output
->otmTextMetrics
.tmExternalLeading
= height_to_LP( dc
, output
->otmTextMetrics
.tmExternalLeading
);
1662 output
->otmTextMetrics
.tmAveCharWidth
= width_to_LP( dc
, output
->otmTextMetrics
.tmAveCharWidth
);
1663 output
->otmTextMetrics
.tmMaxCharWidth
= width_to_LP( dc
, output
->otmTextMetrics
.tmMaxCharWidth
);
1664 output
->otmTextMetrics
.tmOverhang
= width_to_LP( dc
, output
->otmTextMetrics
.tmOverhang
);
1665 output
->otmAscent
= height_to_LP( dc
, output
->otmAscent
);
1666 output
->otmDescent
= height_to_LP( dc
, output
->otmDescent
);
1667 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1668 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1669 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1670 output
->otmrcFontBox
.top
= height_to_LP( dc
, output
->otmrcFontBox
.top
);
1671 output
->otmrcFontBox
.bottom
= height_to_LP( dc
, output
->otmrcFontBox
.bottom
);
1672 output
->otmrcFontBox
.left
= width_to_LP( dc
, output
->otmrcFontBox
.left
);
1673 output
->otmrcFontBox
.right
= width_to_LP( dc
, output
->otmrcFontBox
.right
);
1674 output
->otmMacAscent
= height_to_LP( dc
, output
->otmMacAscent
);
1675 output
->otmMacDescent
= height_to_LP( dc
, output
->otmMacDescent
);
1676 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1677 output
->otmptSubscriptSize
.x
= width_to_LP( dc
, output
->otmptSubscriptSize
.x
);
1678 output
->otmptSubscriptSize
.y
= height_to_LP( dc
, output
->otmptSubscriptSize
.y
);
1679 output
->otmptSubscriptOffset
.x
= width_to_LP( dc
, output
->otmptSubscriptOffset
.x
);
1680 output
->otmptSubscriptOffset
.y
= height_to_LP( dc
, output
->otmptSubscriptOffset
.y
);
1681 output
->otmptSuperscriptSize
.x
= width_to_LP( dc
, output
->otmptSuperscriptSize
.x
);
1682 output
->otmptSuperscriptSize
.y
= height_to_LP( dc
, output
->otmptSuperscriptSize
.y
);
1683 output
->otmptSuperscriptOffset
.x
= width_to_LP( dc
, output
->otmptSuperscriptOffset
.x
);
1684 output
->otmptSuperscriptOffset
.y
= height_to_LP( dc
, output
->otmptSuperscriptOffset
.y
);
1685 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1686 output
->otmsStrikeoutPosition
= height_to_LP( dc
, output
->otmsStrikeoutPosition
);
1687 output
->otmsUnderscoreSize
= height_to_LP( dc
, output
->otmsUnderscoreSize
);
1688 output
->otmsUnderscorePosition
= height_to_LP( dc
, output
->otmsUnderscorePosition
);
1692 memcpy(lpOTM
, output
, cbData
);
1693 HeapFree(GetProcessHeap(), 0, output
);
1701 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1703 INT i
, count
= lastChar
- firstChar
+ 1;
1711 mbcp
= GdiGetCodePage(hdc
);
1719 if (lastChar
> 0xffff)
1721 if ((firstChar
^ lastChar
) > 0xff)
1725 if (lastChar
> 0xff)
1731 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1735 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1739 str
[i
++] = (BYTE
)(c
>> 8);
1740 if (c
<= 0xff && IsDBCSLeadByteEx(mbcp
, c
))
1741 str
[i
] = 0x1f; /* FIXME: use default character */
1755 /***********************************************************************
1756 * GetCharWidthW (GDI32.@)
1757 * GetCharWidth32W (GDI32.@)
1759 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1765 DC
* dc
= get_dc_ptr( hdc
);
1767 if (!dc
) return FALSE
;
1769 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1770 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1774 /* convert device units to logical */
1775 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1776 *buffer
= width_to_LP( dc
, *buffer
);
1778 release_dc_ptr( dc
);
1783 /***********************************************************************
1784 * GetCharWidthA (GDI32.@)
1785 * GetCharWidth32A (GDI32.@)
1787 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1795 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1799 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1801 for(i
= 0; i
< wlen
; i
++)
1803 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1811 HeapFree(GetProcessHeap(), 0, str
);
1812 HeapFree(GetProcessHeap(), 0, wstr
);
1818 /* helper for nulldrv_ExtTextOut */
1819 static DWORD
get_glyph_bitmap( HDC hdc
, UINT index
, UINT flags
, UINT aa_flags
,
1820 GLYPHMETRICS
*metrics
, struct gdi_image_bits
*image
)
1822 static const MAT2 identity
= { {0,1}, {0,0}, {0,0}, {0,1} };
1823 UINT indices
[3] = {0, 0, 0x20};
1829 if (flags
& ETO_GLYPH_INDEX
) aa_flags
|= GGO_GLYPH_INDEX
;
1831 for (i
= 0; i
< sizeof(indices
) / sizeof(indices
[0]); i
++)
1834 ret
= GetGlyphOutlineW( hdc
, index
, aa_flags
, metrics
, 0, NULL
, &identity
);
1835 if (ret
!= GDI_ERROR
) break;
1838 if (ret
== GDI_ERROR
) return ERROR_NOT_FOUND
;
1839 if (!image
) return ERROR_SUCCESS
;
1843 if (!ret
) /* empty glyph */
1845 metrics
->gmBlackBoxX
= metrics
->gmBlackBoxY
= 0;
1846 return ERROR_SUCCESS
;
1849 stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1850 size
= metrics
->gmBlackBoxY
* stride
;
1852 if (!(image
->ptr
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
1853 image
->is_copy
= TRUE
;
1854 image
->free
= free_heap_bits
;
1856 ret
= GetGlyphOutlineW( hdc
, index
, aa_flags
, metrics
, size
, image
->ptr
, &identity
);
1857 if (ret
== GDI_ERROR
)
1859 HeapFree( GetProcessHeap(), 0, image
->ptr
);
1860 return ERROR_NOT_FOUND
;
1862 return ERROR_SUCCESS
;
1865 /* helper for nulldrv_ExtTextOut */
1866 static RECT
get_total_extents( HDC hdc
, INT x
, INT y
, UINT flags
, UINT aa_flags
,
1867 LPCWSTR str
, UINT count
, const INT
*dx
)
1872 reset_bounds( &bounds
);
1873 for (i
= 0; i
< count
; i
++)
1875 GLYPHMETRICS metrics
;
1877 if (get_glyph_bitmap( hdc
, str
[i
], flags
, aa_flags
, &metrics
, NULL
)) continue;
1879 rect
.left
= x
+ metrics
.gmptGlyphOrigin
.x
;
1880 rect
.top
= y
- metrics
.gmptGlyphOrigin
.y
;
1881 rect
.right
= rect
.left
+ metrics
.gmBlackBoxX
;
1882 rect
.bottom
= rect
.top
+ metrics
.gmBlackBoxY
;
1883 add_bounds_rect( &bounds
, &rect
);
1887 if (flags
& ETO_PDY
)
1890 y
+= dx
[ i
* 2 + 1];
1896 x
+= metrics
.gmCellIncX
;
1897 y
+= metrics
.gmCellIncY
;
1903 /* helper for nulldrv_ExtTextOut */
1904 static void draw_glyph( HDC hdc
, INT origin_x
, INT origin_y
, const GLYPHMETRICS
*metrics
,
1905 const struct gdi_image_bits
*image
, const RECT
*clip
)
1907 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1908 UINT i
, count
, max_count
;
1910 BYTE
*ptr
= image
->ptr
;
1911 int stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1913 RECT rect
, clipped_rect
;
1915 rect
.left
= origin_x
+ metrics
->gmptGlyphOrigin
.x
;
1916 rect
.top
= origin_y
- metrics
->gmptGlyphOrigin
.y
;
1917 rect
.right
= rect
.left
+ metrics
->gmBlackBoxX
;
1918 rect
.bottom
= rect
.top
+ metrics
->gmBlackBoxY
;
1919 if (!clip
) clipped_rect
= rect
;
1920 else if (!intersect_rect( &clipped_rect
, &rect
, clip
)) return;
1922 max_count
= (metrics
->gmBlackBoxX
+ 1) * metrics
->gmBlackBoxY
;
1923 pts
= HeapAlloc( GetProcessHeap(), 0, max_count
* sizeof(*pts
) );
1927 ptr
+= (clipped_rect
.top
- rect
.top
) * stride
;
1928 for (y
= clipped_rect
.top
; y
< clipped_rect
.bottom
; y
++, ptr
+= stride
)
1930 for (x
= clipped_rect
.left
- rect
.left
; x
< clipped_rect
.right
- rect
.left
; x
++)
1932 while (x
< clipped_rect
.right
- rect
.left
&& !(ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1933 pts
[count
].x
= rect
.left
+ x
;
1934 while (x
< clipped_rect
.right
- rect
.left
&& (ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1935 pts
[count
+ 1].x
= rect
.left
+ x
;
1936 if (pts
[count
+ 1].x
> pts
[count
].x
)
1938 pts
[count
].y
= pts
[count
+ 1].y
= y
;
1943 assert( count
<= max_count
);
1944 DPtoLP( hdc
, pts
, count
);
1945 for (i
= 0; i
< count
; i
+= 2) Polyline( hdc
, pts
+ i
, 2 );
1946 HeapFree( GetProcessHeap(), 0, pts
);
1949 /***********************************************************************
1950 * nulldrv_ExtTextOut
1952 BOOL
nulldrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
1953 LPCWSTR str
, UINT count
, const INT
*dx
)
1955 DC
*dc
= get_nulldrv_dc( dev
);
1961 if (flags
& ETO_OPAQUE
)
1964 HBRUSH brush
= CreateSolidBrush( GetNearestColor( dev
->hdc
, GetBkColor(dev
->hdc
) ));
1968 orig
= SelectObject( dev
->hdc
, brush
);
1969 DPtoLP( dev
->hdc
, (POINT
*)&rc
, 2 );
1970 PatBlt( dev
->hdc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, PATCOPY
);
1971 SelectObject( dev
->hdc
, orig
);
1972 DeleteObject( brush
);
1976 if (!count
) return TRUE
;
1978 if (dc
->aa_flags
!= GGO_BITMAP
)
1980 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1981 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1982 struct gdi_image_bits bits
;
1983 struct bitblt_coords src
, dst
;
1985 /* FIXME Subpixel modes */
1986 UINT aa_flags
= GGO_GRAY4_BITMAP
;
1988 dst_dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
1989 src
.visrect
= get_total_extents( dev
->hdc
, x
, y
, flags
, aa_flags
, str
, count
, dx
);
1990 if (flags
& ETO_CLIPPED
) intersect_rect( &src
.visrect
, &src
.visrect
, rect
);
1991 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return TRUE
;
1993 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1994 src
.x
= src
.visrect
.left
;
1995 src
.y
= src
.visrect
.top
;
1996 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1997 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1999 if ((flags
& ETO_OPAQUE
) && (src
.visrect
.left
>= rect
->left
) && (src
.visrect
.top
>= rect
->top
) &&
2000 (src
.visrect
.right
<= rect
->right
) && (src
.visrect
.bottom
<= rect
->bottom
))
2002 /* we can avoid the GetImage, just query the needed format */
2003 memset( &info
->bmiHeader
, 0, sizeof(info
->bmiHeader
) );
2004 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
2005 info
->bmiHeader
.biWidth
= src
.width
;
2006 info
->bmiHeader
.biHeight
= -src
.height
;
2007 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, info
, NULL
, NULL
, NULL
, 0 );
2008 if (!err
|| err
== ERROR_BAD_FORMAT
)
2010 /* make the source rectangle relative to the source bits */
2012 src
.visrect
.left
= src
.visrect
.top
= 0;
2013 src
.visrect
.right
= src
.width
;
2014 src
.visrect
.bottom
= src
.height
;
2016 bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
2017 if (!bits
.ptr
) return ERROR_OUTOFMEMORY
;
2018 bits
.is_copy
= TRUE
;
2019 bits
.free
= free_heap_bits
;
2020 err
= ERROR_SUCCESS
;
2025 PHYSDEV src_dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
2026 err
= src_dev
->funcs
->pGetImage( src_dev
, info
, &bits
, &src
);
2027 if (!err
&& !bits
.is_copy
)
2029 void *ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
2032 if (bits
.free
) bits
.free( &bits
);
2033 return ERROR_OUTOFMEMORY
;
2035 memcpy( ptr
, bits
.ptr
, get_dib_image_size( info
));
2036 if (bits
.free
) bits
.free( &bits
);
2038 bits
.is_copy
= TRUE
;
2039 bits
.free
= free_heap_bits
;
2044 /* make x,y relative to the image bits */
2045 x
+= src
.visrect
.left
- dst
.visrect
.left
;
2046 y
+= src
.visrect
.top
- dst
.visrect
.top
;
2047 render_aa_text_bitmapinfo( dc
, info
, &bits
, &src
, x
, y
, flags
,
2048 aa_flags
, str
, count
, dx
);
2049 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, info
, &bits
, &src
, &dst
, SRCCOPY
);
2050 if (bits
.free
) bits
.free( &bits
);
2055 pen
= CreatePen( PS_SOLID
, 1, GetTextColor(dev
->hdc
) );
2056 orig
= SelectObject( dev
->hdc
, pen
);
2058 for (i
= 0; i
< count
; i
++)
2060 GLYPHMETRICS metrics
;
2061 struct gdi_image_bits image
;
2063 err
= get_glyph_bitmap( dev
->hdc
, str
[i
], flags
, GGO_BITMAP
, &metrics
, &image
);
2066 if (image
.ptr
) draw_glyph( dev
->hdc
, x
, y
, &metrics
, &image
, (flags
& ETO_CLIPPED
) ? rect
: NULL
);
2067 if (image
.free
) image
.free( &image
);
2071 if (flags
& ETO_PDY
)
2074 y
+= dx
[ i
* 2 + 1];
2080 x
+= metrics
.gmCellIncX
;
2081 y
+= metrics
.gmCellIncY
;
2085 SelectObject( dev
->hdc
, orig
);
2086 DeleteObject( pen
);
2091 /***********************************************************************
2092 * ExtTextOutA (GDI32.@)
2096 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
2097 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
2105 if (flags
& ETO_GLYPH_INDEX
)
2106 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
2108 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
2111 unsigned int i
= 0, j
= 0;
2113 /* allocate enough for a ETO_PDY */
2114 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
2116 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
2120 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
2121 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
2124 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
2131 lpDxW
[j
++] = lpDx
[i
* 2];
2132 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
2135 lpDxW
[j
++] = lpDx
[i
];
2141 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
2143 HeapFree( GetProcessHeap(), 0, p
);
2144 HeapFree( GetProcessHeap(), 0, lpDxW
);
2148 /***********************************************************************
2151 * Scale the underline / strikeout line width.
2153 static inline int get_line_width( DC
*dc
, int metric_size
)
2155 int width
= abs( INTERNAL_YWSTODS( dc
, metric_size
));
2156 if (width
== 0) width
= 1;
2157 if (metric_size
< 0) width
= -width
;
2161 /***********************************************************************
2162 * ExtTextOutW (GDI32.@)
2164 * Draws text using the currently selected font, background color, and text color.
2168 * x,y [I] coordinates of string
2170 * ETO_GRAYED - undocumented on MSDN
2171 * ETO_OPAQUE - use background color for fill the rectangle
2172 * ETO_CLIPPED - clipping text to the rectangle
2173 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2174 * than encoded characters. Implies ETO_IGNORELANGUAGE
2175 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2176 * Affects BiDi ordering
2177 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2178 * ETO_PDY - unimplemented
2179 * ETO_NUMERICSLATIN - unimplemented always assumed -
2180 * do not translate numbers into locale representations
2181 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2182 * lprect [I] dimensions for clipping or/and opaquing
2183 * str [I] text string
2184 * count [I] number of symbols in string
2185 * lpDx [I] optional parameter with distance between drawing characters
2191 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
2192 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
2195 LPWSTR reordered_str
= (LPWSTR
)str
;
2196 WORD
*glyphs
= NULL
;
2197 UINT align
= GetTextAlign( hdc
);
2198 DWORD layout
= GetLayout( hdc
);
2202 double cosEsc
, sinEsc
;
2206 POINT
*deltas
= NULL
, width
= {0, 0};
2208 DC
* dc
= get_dc_ptr( hdc
);
2211 static int quietfixme
= 0;
2213 if (!dc
) return FALSE
;
2215 breakRem
= dc
->breakRem
;
2217 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
2219 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2224 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
2225 type
= GetObjectType(hdc
);
2226 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
2228 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
2229 release_dc_ptr( dc
);
2233 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
2234 if (layout
& LAYOUT_RTL
)
2236 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
2237 align
^= TA_RTLREADING
;
2240 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
2243 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
2245 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
2246 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
2247 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
2249 flags
|= ETO_IGNORELANGUAGE
;
2252 flags
|= ETO_GLYPH_INDEX
;
2253 if (cGlyphs
!= count
)
2257 else if(flags
& ETO_GLYPH_INDEX
)
2258 glyphs
= reordered_str
;
2260 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
2261 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
2262 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
2264 if(align
& TA_UPDATECP
)
2266 GetCurrentPositionEx( hdc
, &pt
);
2271 GetTextMetricsW(hdc
, &tm
);
2272 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
2274 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
2275 lf
.lfEscapement
= 0;
2277 if ((dc
->GraphicsMode
== GM_COMPATIBLE
) &&
2278 (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
* dc
->xformWorld2Vport
.eM22
< 0))
2280 lf
.lfEscapement
= -lf
.lfEscapement
;
2283 if(lf
.lfEscapement
!= 0)
2285 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
2286 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
2294 if (lprect
&& (flags
& (ETO_OPAQUE
| ETO_CLIPPED
)))
2297 lp_to_dp(dc
, (POINT
*)&rc
, 2);
2299 if (flags
& ETO_OPAQUE
)
2300 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2302 else flags
&= ~ETO_CLIPPED
;
2312 lp_to_dp(dc
, &pt
, 1);
2316 char_extra
= GetTextCharacterExtra(hdc
);
2317 if (char_extra
&& lpDx
&& GetDeviceCaps( hdc
, TECHNOLOGY
) == DT_RASPRINTER
)
2318 char_extra
= 0; /* Printer drivers don't add char_extra if lpDx is supplied */
2320 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2323 POINT total
= {0, 0}, desired
[2];
2325 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2328 if (flags
& ETO_PDY
)
2330 for (i
= 0; i
< count
; i
++)
2332 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
2333 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
2338 for (i
= 0; i
< count
; i
++)
2340 deltas
[i
].x
= lpDx
[i
] + char_extra
;
2347 INT
*dx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*dx
) );
2349 if (flags
& ETO_GLYPH_INDEX
)
2350 GetTextExtentExPointI( hdc
, glyphs
, count
, -1, NULL
, dx
, &sz
);
2352 GetTextExtentExPointW( hdc
, reordered_str
, count
, -1, NULL
, dx
, &sz
);
2354 deltas
[0].x
= dx
[0];
2356 for (i
= 1; i
< count
; i
++)
2358 deltas
[i
].x
= dx
[i
] - dx
[i
- 1];
2361 HeapFree( GetProcessHeap(), 0, dx
);
2364 for(i
= 0; i
< count
; i
++)
2366 total
.x
+= deltas
[i
].x
;
2367 total
.y
+= deltas
[i
].y
;
2369 desired
[0].x
= desired
[0].y
= 0;
2371 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
2372 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
2374 lp_to_dp(dc
, desired
, 2);
2375 desired
[1].x
-= desired
[0].x
;
2376 desired
[1].y
-= desired
[0].y
;
2378 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2380 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2381 desired
[1].x
= -desired
[1].x
;
2382 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2383 desired
[1].y
= -desired
[1].y
;
2386 deltas
[i
].x
= desired
[1].x
- width
.x
;
2387 deltas
[i
].y
= desired
[1].y
- width
.y
;
2397 if(flags
& ETO_GLYPH_INDEX
)
2398 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2400 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2401 desired
[0].x
= desired
[0].y
= 0;
2402 desired
[1].x
= sz
.cx
;
2404 lp_to_dp(dc
, desired
, 2);
2405 desired
[1].x
-= desired
[0].x
;
2406 desired
[1].y
-= desired
[0].y
;
2408 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2410 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2411 desired
[1].x
= -desired
[1].x
;
2412 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2413 desired
[1].y
= -desired
[1].y
;
2418 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2419 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2420 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2423 if (align
& TA_UPDATECP
)
2427 DPtoLP(hdc
, &pt
, 1);
2428 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2440 if (align
& TA_UPDATECP
)
2444 DPtoLP(hdc
, &pt
, 1);
2445 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2450 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2453 y
+= tm
.tmAscent
* cosEsc
;
2454 x
+= tm
.tmAscent
* sinEsc
;
2458 y
-= tm
.tmDescent
* cosEsc
;
2459 x
-= tm
.tmDescent
* sinEsc
;
2466 if (GetBkMode(hdc
) != TRANSPARENT
)
2468 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2470 if(!(flags
& ETO_OPAQUE
) || !lprect
||
2471 x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2472 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2476 text_box
.right
= x
+ width
.x
;
2477 text_box
.top
= y
- tm
.tmAscent
;
2478 text_box
.bottom
= y
+ tm
.tmDescent
;
2480 if (flags
& ETO_CLIPPED
) intersect_rect( &text_box
, &text_box
, &rc
);
2481 if (!is_rect_empty( &text_box
))
2482 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &text_box
, NULL
, 0, NULL
);
2487 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2488 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2491 HeapFree(GetProcessHeap(), 0, deltas
);
2492 if(glyphs
!= reordered_str
)
2493 HeapFree(GetProcessHeap(), 0, glyphs
);
2494 if(reordered_str
!= str
)
2495 HeapFree(GetProcessHeap(), 0, reordered_str
);
2497 release_dc_ptr( dc
);
2499 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2501 int underlinePos
, strikeoutPos
;
2502 int underlineWidth
, strikeoutWidth
;
2503 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2504 OUTLINETEXTMETRICW
* otm
= NULL
;
2506 HPEN hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2507 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2509 hbrush
= SelectObject(hdc
, hbrush
);
2514 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2515 strikeoutPos
= tm
.tmAscent
/ 2;
2516 strikeoutWidth
= underlineWidth
;
2520 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2521 GetOutlineTextMetricsW(hdc
, size
, otm
);
2522 underlinePos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscorePosition
));
2523 if (otm
->otmsUnderscorePosition
< 0) underlinePos
= -underlinePos
;
2524 underlineWidth
= get_line_width( dc
, otm
->otmsUnderscoreSize
);
2525 strikeoutPos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutPosition
));
2526 if (otm
->otmsStrikeoutPosition
< 0) strikeoutPos
= -strikeoutPos
;
2527 strikeoutWidth
= get_line_width( dc
, otm
->otmsStrikeoutSize
);
2528 HeapFree(GetProcessHeap(), 0, otm
);
2534 pts
[0].x
= x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2535 pts
[0].y
= y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2536 pts
[1].x
= x
+ width
.x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2537 pts
[1].y
= y
+ width
.y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2538 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2539 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2540 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2541 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2542 pts
[4].x
= pts
[0].x
;
2543 pts
[4].y
= pts
[0].y
;
2544 DPtoLP(hdc
, pts
, 5);
2545 Polygon(hdc
, pts
, 5);
2550 pts
[0].x
= x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2551 pts
[0].y
= y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2552 pts
[1].x
= x
+ width
.x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2553 pts
[1].y
= y
+ width
.y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2554 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2555 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2556 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2557 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2558 pts
[4].x
= pts
[0].x
;
2559 pts
[4].y
= pts
[0].y
;
2560 DPtoLP(hdc
, pts
, 5);
2561 Polygon(hdc
, pts
, 5);
2564 SelectObject(hdc
, hpen
);
2565 hbrush
= SelectObject(hdc
, hbrush
);
2566 DeleteObject(hbrush
);
2573 /***********************************************************************
2574 * TextOutA (GDI32.@)
2576 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2578 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2582 /***********************************************************************
2583 * TextOutW (GDI32.@)
2585 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2587 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2591 /***********************************************************************
2592 * PolyTextOutA (GDI32.@)
2596 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2598 for (; cStrings
>0; cStrings
--, pptxt
++)
2599 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2606 /***********************************************************************
2607 * PolyTextOutW (GDI32.@)
2609 * Draw several Strings
2615 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2617 for (; cStrings
>0; cStrings
--, pptxt
++)
2618 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2624 /***********************************************************************
2625 * SetMapperFlags (GDI32.@)
2627 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2629 DC
*dc
= get_dc_ptr( hdc
);
2630 DWORD ret
= GDI_ERROR
;
2634 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2635 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2636 if (flags
!= GDI_ERROR
)
2638 ret
= dc
->mapperFlags
;
2639 dc
->mapperFlags
= flags
;
2641 release_dc_ptr( dc
);
2646 /***********************************************************************
2647 * GetAspectRatioFilterEx (GDI32.@)
2649 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2651 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2656 /***********************************************************************
2657 * GetCharABCWidthsA (GDI32.@)
2659 * See GetCharABCWidthsW.
2661 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2669 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2673 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2676 HeapFree(GetProcessHeap(), 0, str
);
2680 for(i
= 0; i
< wlen
; i
++)
2682 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2690 HeapFree(GetProcessHeap(), 0, str
);
2691 HeapFree(GetProcessHeap(), 0, wstr
);
2697 /******************************************************************************
2698 * GetCharABCWidthsW [GDI32.@]
2700 * Retrieves widths of characters in range.
2703 * hdc [I] Handle of device context
2704 * firstChar [I] First character in range to query
2705 * lastChar [I] Last character in range to query
2706 * abc [O] Address of character-width structure
2709 * Only works with TrueType fonts
2715 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2718 DC
*dc
= get_dc_ptr(hdc
);
2724 if (!dc
) return FALSE
;
2728 release_dc_ptr( dc
);
2732 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2733 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
2734 if (!dev
->funcs
->pGetTextMetrics( dev
, &tm
) || !(tm
.tmPitchAndFamily
& TMPF_VECTOR
))
2736 release_dc_ptr( dc
);
2740 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2741 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2744 /* convert device units to logical */
2745 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2746 abc
->abcA
= width_to_LP(dc
, abc
->abcA
);
2747 abc
->abcB
= width_to_LP(dc
, abc
->abcB
);
2748 abc
->abcC
= width_to_LP(dc
, abc
->abcC
);
2752 release_dc_ptr( dc
);
2757 /******************************************************************************
2758 * GetCharABCWidthsI [GDI32.@]
2760 * Retrieves widths of characters in range.
2763 * hdc [I] Handle of device context
2764 * firstChar [I] First glyphs in range to query
2765 * count [I] Last glyphs in range to query
2766 * pgi [i] Array of glyphs to query
2767 * abc [O] Address of character-width structure
2770 * Only works with TrueType fonts
2776 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2777 LPWORD pgi
, LPABC abc
)
2779 DC
*dc
= get_dc_ptr(hdc
);
2784 if (!dc
) return FALSE
;
2788 release_dc_ptr( dc
);
2792 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2793 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2796 /* convert device units to logical */
2797 for( i
= 0; i
< count
; i
++, abc
++ ) {
2798 abc
->abcA
= width_to_LP(dc
, abc
->abcA
);
2799 abc
->abcB
= width_to_LP(dc
, abc
->abcB
);
2800 abc
->abcC
= width_to_LP(dc
, abc
->abcC
);
2804 release_dc_ptr( dc
);
2809 /***********************************************************************
2810 * GetGlyphOutlineA (GDI32.@)
2812 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2813 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2814 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2816 if (!lpmat2
) return GDI_ERROR
;
2818 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2823 cp
= GdiGetCodePage(hdc
);
2824 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2826 mbchs
[0] = (uChar
& 0xff00) >> 8;
2827 mbchs
[1] = (uChar
& 0xff);
2830 mbchs
[0] = (uChar
& 0xff);
2833 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2836 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2840 /***********************************************************************
2841 * GetGlyphOutlineW (GDI32.@)
2843 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2844 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2845 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2851 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2852 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2854 if (!lpmat2
) return GDI_ERROR
;
2856 dc
= get_dc_ptr(hdc
);
2857 if(!dc
) return GDI_ERROR
;
2859 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2860 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2861 release_dc_ptr( dc
);
2866 /***********************************************************************
2867 * CreateScalableFontResourceA (GDI32.@)
2869 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2870 LPCSTR lpszResourceFile
,
2871 LPCSTR lpszFontFile
,
2872 LPCSTR lpszCurrentPath
)
2874 LPWSTR lpszResourceFileW
= NULL
;
2875 LPWSTR lpszFontFileW
= NULL
;
2876 LPWSTR lpszCurrentPathW
= NULL
;
2880 if (lpszResourceFile
)
2882 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2883 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2884 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2889 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2890 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2891 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2894 if (lpszCurrentPath
)
2896 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2897 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2898 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2901 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2902 lpszFontFileW
, lpszCurrentPathW
);
2904 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2905 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2906 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2911 /***********************************************************************
2912 * CreateScalableFontResourceW (GDI32.@)
2914 BOOL WINAPI
CreateScalableFontResourceW( DWORD hidden
, LPCWSTR resource_file
,
2915 LPCWSTR font_file
, LPCWSTR font_path
)
2917 TRACE("(%d, %s, %s, %s)\n", hidden
, debugstr_w(resource_file
),
2918 debugstr_w(font_file
), debugstr_w(font_path
) );
2920 return WineEngCreateScalableFontResource( hidden
, resource_file
,
2921 font_file
, font_path
);
2924 /*************************************************************************
2925 * GetKerningPairsA (GDI32.@)
2927 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2928 LPKERNINGPAIR kern_pairA
)
2932 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2933 KERNINGPAIR
*kern_pairW
;
2935 if (!cPairs
&& kern_pairA
)
2937 SetLastError(ERROR_INVALID_PARAMETER
);
2941 cp
= GdiGetCodePage(hDC
);
2943 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2944 * to fail on an invalid character for CP_SYMBOL.
2946 cpi
.DefaultChar
[0] = 0;
2947 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2949 FIXME("Can't find codepage %u info\n", cp
);
2953 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2954 if (!total_kern_pairs
) return 0;
2956 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2957 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2959 for (i
= 0; i
< total_kern_pairs
; i
++)
2963 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2966 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2969 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2974 if (kern_pairs_copied
>= cPairs
) break;
2976 kern_pairA
->wFirst
= (BYTE
)first
;
2977 kern_pairA
->wSecond
= (BYTE
)second
;
2978 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2981 kern_pairs_copied
++;
2984 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2986 return kern_pairs_copied
;
2989 /*************************************************************************
2990 * GetKerningPairsW (GDI32.@)
2992 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2993 LPKERNINGPAIR lpKerningPairs
)
2999 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
3001 if (!cPairs
&& lpKerningPairs
)
3003 SetLastError(ERROR_INVALID_PARAMETER
);
3007 dc
= get_dc_ptr(hDC
);
3010 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
3011 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
3012 release_dc_ptr( dc
);
3016 /*************************************************************************
3017 * TranslateCharsetInfo [GDI32.@]
3019 * Fills a CHARSETINFO structure for a character set, code page, or
3020 * font. This allows making the correspondence between different labels
3021 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
3022 * of the same encoding.
3024 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
3025 * only one codepage should be set in *lpSrc.
3028 * TRUE on success, FALSE on failure.
3031 BOOL WINAPI
TranslateCharsetInfo(
3032 LPDWORD lpSrc
, /* [in]
3033 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
3034 if flags == TCI_SRCCHARSET: a character set value
3035 if flags == TCI_SRCCODEPAGE: a code page value
3037 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
3038 DWORD flags
/* [in] determines interpretation of lpSrc */)
3042 case TCI_SRCFONTSIG
:
3043 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
3045 case TCI_SRCCODEPAGE
:
3046 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
3048 case TCI_SRCCHARSET
:
3049 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
3054 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
3055 *lpCs
= FONT_tci
[index
];
3059 /*************************************************************************
3060 * GetFontLanguageInfo (GDI32.@)
3062 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
3064 FONTSIGNATURE fontsig
;
3065 static const DWORD GCP_DBCS_MASK
=FS_JISJAPAN
|FS_CHINESESIMP
|FS_WANSUNG
|FS_CHINESETRAD
|FS_JOHAB
,
3066 GCP_DIACRITIC_MASK
=0x00000000,
3067 FLI_GLYPHS_MASK
=0x00000000,
3068 GCP_GLYPHSHAPE_MASK
=FS_ARABIC
,
3069 GCP_KASHIDA_MASK
=0x00000000,
3070 GCP_LIGATE_MASK
=0x00000000,
3071 GCP_REORDER_MASK
=FS_HEBREW
|FS_ARABIC
;
3075 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
3076 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3078 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
3081 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
3082 result
|=GCP_DIACRITIC
;
3084 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
3087 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
3088 result
|=GCP_GLYPHSHAPE
;
3090 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
3091 result
|=GCP_KASHIDA
;
3093 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
3096 if( GetKerningPairsW( hdc
, 0, NULL
) )
3097 result
|=GCP_USEKERNING
;
3099 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3100 if( GetTextAlign( hdc
) & TA_RTLREADING
)
3101 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
3102 result
|=GCP_REORDER
;
3108 /*************************************************************************
3109 * GetFontData [GDI32.@]
3111 * Retrieve data for TrueType font.
3115 * success: Number of bytes returned
3116 * failure: GDI_ERROR
3120 * Calls SetLastError()
3123 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
3124 LPVOID buffer
, DWORD length
)
3126 DC
*dc
= get_dc_ptr(hdc
);
3130 if(!dc
) return GDI_ERROR
;
3132 dev
= GET_DC_PHYSDEV( dc
, pGetFontData
);
3133 ret
= dev
->funcs
->pGetFontData( dev
, table
, offset
, buffer
, length
);
3134 release_dc_ptr( dc
);
3138 /*************************************************************************
3139 * GetGlyphIndicesA [GDI32.@]
3141 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
3142 LPWORD pgi
, DWORD flags
)
3148 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3149 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
3151 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
3152 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
3153 HeapFree(GetProcessHeap(), 0, lpstrW
);
3158 /*************************************************************************
3159 * GetGlyphIndicesW [GDI32.@]
3161 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
3162 LPWORD pgi
, DWORD flags
)
3164 DC
*dc
= get_dc_ptr(hdc
);
3168 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3169 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
3171 if(!dc
) return GDI_ERROR
;
3173 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
3174 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
3175 release_dc_ptr( dc
);
3179 /*************************************************************************
3180 * GetCharacterPlacementA [GDI32.@]
3182 * See GetCharacterPlacementW.
3185 * the web browser control of ie4 calls this with dwFlags=0
3188 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
3189 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
3194 GCP_RESULTSW resultsW
;
3198 TRACE("%s, %d, %d, 0x%08x\n",
3199 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3201 /* both structs are equal in size */
3202 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
3204 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
3205 if(lpResults
->lpOutString
)
3206 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
3208 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
3210 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
3211 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
3213 if(lpResults
->lpOutString
) {
3214 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
3215 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
3218 HeapFree(GetProcessHeap(), 0, lpStringW
);
3219 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
3224 /*************************************************************************
3225 * GetCharacterPlacementW [GDI32.@]
3227 * Retrieve information about a string. This includes the width, reordering,
3228 * Glyphing and so on.
3232 * The width and height of the string if successful, 0 if failed.
3236 * All flags except GCP_REORDER are not yet implemented.
3237 * Reordering is not 100% compliant to the Windows BiDi method.
3238 * Caret positioning is not yet implemented for BiDi.
3239 * Classes are not yet implemented.
3243 GetCharacterPlacementW(
3244 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3245 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3246 INT uCount
, /* [in] Number of WORDS in string. */
3247 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3248 GCP_RESULTSW
*lpResults
, /* [in/out] A pointer to a GCP_RESULTSW struct */
3249 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3256 TRACE("%s, %d, %d, 0x%08x\n",
3257 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3259 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3260 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3261 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3262 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3263 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3265 if(dwFlags
&(~GCP_REORDER
))
3266 FIXME("flags 0x%08x ignored\n", dwFlags
);
3267 if(lpResults
->lpClass
)
3268 FIXME("classes not implemented\n");
3269 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3270 FIXME("Caret positions for complex scripts not implemented\n");
3272 nSet
= (UINT
)uCount
;
3273 if(nSet
> lpResults
->nGlyphs
)
3274 nSet
= lpResults
->nGlyphs
;
3276 /* return number of initialized fields */
3277 lpResults
->nGlyphs
= nSet
;
3279 if((dwFlags
&GCP_REORDER
)==0 )
3281 /* Treat the case where no special handling was requested in a fastpath way */
3282 /* copy will do if the GCP_REORDER flag is not set */
3283 if(lpResults
->lpOutString
)
3284 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3286 if(lpResults
->lpOrder
)
3288 for(i
= 0; i
< nSet
; i
++)
3289 lpResults
->lpOrder
[i
] = i
;
3294 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3295 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3298 /* FIXME: Will use the placement chars */
3299 if (lpResults
->lpDx
)
3302 for (i
= 0; i
< nSet
; i
++)
3304 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3305 lpResults
->lpDx
[i
]= c
;
3309 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3313 lpResults
->lpCaretPos
[0] = 0;
3314 for (i
= 1; i
< nSet
; i
++)
3315 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3316 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3319 if(lpResults
->lpGlyphs
)
3320 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3322 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3323 ret
= MAKELONG(size
.cx
, size
.cy
);
3328 /*************************************************************************
3329 * GetCharABCWidthsFloatA [GDI32.@]
3331 * See GetCharABCWidthsFloatW.
3333 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3340 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3344 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3346 for (i
= 0; i
< wlen
; i
++)
3348 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3356 HeapFree( GetProcessHeap(), 0, str
);
3357 HeapFree( GetProcessHeap(), 0, wstr
);
3362 /*************************************************************************
3363 * GetCharABCWidthsFloatW [GDI32.@]
3365 * Retrieves widths of a range of characters.
3368 * hdc [I] Handle to device context.
3369 * first [I] First character in range to query.
3370 * last [I] Last character in range to query.
3371 * abcf [O] Array of LPABCFLOAT structures.
3377 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3383 DC
*dc
= get_dc_ptr( hdc
);
3385 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3387 if (!dc
) return FALSE
;
3389 if (!abcf
) goto done
;
3390 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
3392 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
3393 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
3396 /* convert device units to logical */
3397 FLOAT scale
= fabs( dc
->xformVport2World
.eM11
);
3398 for (i
= first
; i
<= last
; i
++, abcf
++)
3400 abcf
->abcfA
= abc
[i
- first
].abcA
* scale
;
3401 abcf
->abcfB
= abc
[i
- first
].abcB
* scale
;
3402 abcf
->abcfC
= abc
[i
- first
].abcC
* scale
;
3405 HeapFree( GetProcessHeap(), 0, abc
);
3408 release_dc_ptr( dc
);
3412 /*************************************************************************
3413 * GetCharWidthFloatA [GDI32.@]
3415 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3416 UINT iLastChar
, PFLOAT pxBuffer
)
3418 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3422 /*************************************************************************
3423 * GetCharWidthFloatW [GDI32.@]
3425 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3426 UINT iLastChar
, PFLOAT pxBuffer
)
3428 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3433 /***********************************************************************
3435 * Font Resource API *
3437 ***********************************************************************/
3439 /***********************************************************************
3440 * AddFontResourceA (GDI32.@)
3442 INT WINAPI
AddFontResourceA( LPCSTR str
)
3444 return AddFontResourceExA( str
, 0, NULL
);
3447 /***********************************************************************
3448 * AddFontResourceW (GDI32.@)
3450 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3452 return AddFontResourceExW(str
, 0, NULL
);
3456 /***********************************************************************
3457 * AddFontResourceExA (GDI32.@)
3459 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3461 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3462 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3465 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3466 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3467 HeapFree(GetProcessHeap(), 0, strW
);
3471 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3473 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3474 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3475 LPVOID
*pMem
= LockResource(hMem
);
3476 int *num_total
= (int *)lParam
;
3479 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3480 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3482 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3486 *num_total
+= num_in_res
;
3490 static void *map_file( const WCHAR
*filename
, LARGE_INTEGER
*size
)
3492 HANDLE file
, mapping
;
3495 file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3496 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
3498 if (!GetFileSizeEx( file
, size
) || size
->u
.HighPart
)
3500 CloseHandle( file
);
3504 mapping
= CreateFileMappingW( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3505 CloseHandle( file
);
3506 if (!mapping
) return NULL
;
3508 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
3509 CloseHandle( mapping
);
3514 static void *find_resource( BYTE
*ptr
, WORD type
, DWORD rsrc_off
, DWORD size
, DWORD
*len
)
3516 WORD align
, type_id
, count
;
3519 if (size
< rsrc_off
+ 10) return NULL
;
3520 align
= *(WORD
*)(ptr
+ rsrc_off
);
3522 type_id
= *(WORD
*)(ptr
+ rsrc_off
);
3523 while (type_id
&& type_id
!= type
)
3525 count
= *(WORD
*)(ptr
+ rsrc_off
+ 2);
3526 rsrc_off
+= 8 + count
* 12;
3527 if (size
< rsrc_off
+ 8) return NULL
;
3528 type_id
= *(WORD
*)(ptr
+ rsrc_off
);
3530 if (!type_id
) return NULL
;
3531 count
= *(WORD
*)(ptr
+ rsrc_off
+ 2);
3532 if (size
< rsrc_off
+ 8 + count
* 12) return NULL
;
3533 res_off
= *(WORD
*)(ptr
+ rsrc_off
+ 8) << align
;
3534 *len
= *(WORD
*)(ptr
+ rsrc_off
+ 10) << align
;
3535 if (size
< res_off
+ *len
) return NULL
;
3536 return ptr
+ res_off
;
3539 static WCHAR
*get_scalable_filename( const WCHAR
*res
, BOOL
*hidden
)
3542 BYTE
*ptr
= map_file( res
, &size
);
3543 const IMAGE_DOS_HEADER
*dos
;
3544 const IMAGE_OS2_HEADER
*ne
;
3550 if (!ptr
) return NULL
;
3552 if (size
.u
.LowPart
< sizeof( *dos
)) goto fail
;
3553 dos
= (const IMAGE_DOS_HEADER
*)ptr
;
3554 if (dos
->e_magic
!= IMAGE_DOS_SIGNATURE
) goto fail
;
3555 if (size
.u
.LowPart
< dos
->e_lfanew
+ sizeof( *ne
)) goto fail
;
3556 ne
= (const IMAGE_OS2_HEADER
*)(ptr
+ dos
->e_lfanew
);
3558 fontdir
= find_resource( ptr
, 0x8007, dos
->e_lfanew
+ ne
->ne_rsrctab
, size
.u
.LowPart
, &len
);
3559 if (!fontdir
) goto fail
;
3560 *hidden
= (fontdir
[35] & 0x80) != 0; /* fontdir->dfType */
3562 data
= find_resource( ptr
, 0x80cc, dos
->e_lfanew
+ ne
->ne_rsrctab
, size
.u
.LowPart
, &len
);
3563 if (!data
) goto fail
;
3564 if (!memchr( data
, 0, len
)) goto fail
;
3566 len
= MultiByteToWideChar( CP_ACP
, 0, data
, -1, NULL
, 0 );
3567 name
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
3568 if (name
) MultiByteToWideChar( CP_ACP
, 0, data
, -1, name
, len
);
3571 UnmapViewOfFile( ptr
);
3575 /***********************************************************************
3576 * AddFontResourceExW (GDI32.@)
3578 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3580 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3586 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3587 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3588 if (hModule
!= NULL
)
3590 int num_resources
= 0;
3591 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3593 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3594 wine_dbgstr_w(str
));
3595 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3596 ret
= num_resources
;
3597 FreeLibrary(hModule
);
3599 else if ((filename
= get_scalable_filename( str
, &hidden
)) != NULL
)
3601 if (hidden
) fl
|= FR_PRIVATE
| FR_NOT_ENUM
;
3602 ret
= WineEngAddFontResourceEx( filename
, fl
, pdv
);
3603 HeapFree( GetProcessHeap(), 0, filename
);
3609 /***********************************************************************
3610 * RemoveFontResourceA (GDI32.@)
3612 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3614 return RemoveFontResourceExA(str
, 0, 0);
3617 /***********************************************************************
3618 * RemoveFontResourceW (GDI32.@)
3620 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3622 return RemoveFontResourceExW(str
, 0, 0);
3625 /***********************************************************************
3626 * AddFontMemResourceEx (GDI32.@)
3628 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3633 if (!pbFont
|| !cbFont
|| !pcFonts
)
3635 SetLastError(ERROR_INVALID_PARAMETER
);
3639 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3644 *pcFonts
= num_fonts
;
3648 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3649 RemoveFontMemResourceEx(ret
);
3657 /***********************************************************************
3658 * RemoveFontMemResourceEx (GDI32.@)
3660 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3662 FIXME("(%p) stub\n", fh
);
3666 /***********************************************************************
3667 * RemoveFontResourceExA (GDI32.@)
3669 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3671 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3672 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3675 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3676 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3677 HeapFree(GetProcessHeap(), 0, strW
);
3681 /***********************************************************************
3682 * RemoveFontResourceExW (GDI32.@)
3684 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3686 int ret
= WineEngRemoveFontResourceEx( str
, fl
, pdv
);
3692 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3693 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3694 if (hModule
!= NULL
)
3696 WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str
));
3697 FreeLibrary(hModule
);
3699 else if ((filename
= get_scalable_filename( str
, &hidden
)) != NULL
)
3701 if (hidden
) fl
|= FR_PRIVATE
| FR_NOT_ENUM
;
3702 ret
= WineEngRemoveFontResourceEx( filename
, fl
, pdv
);
3703 HeapFree( GetProcessHeap(), 0, filename
);
3709 /***********************************************************************
3710 * GetFontResourceInfoW (GDI32.@)
3712 BOOL WINAPI
GetFontResourceInfoW( LPCWSTR str
, LPDWORD size
, PVOID buffer
, DWORD type
)
3714 FIXME("%s %p(%d) %p %d\n", debugstr_w(str
), size
, size
? *size
: 0, buffer
, type
);
3718 /***********************************************************************
3719 * GetTextCharset (GDI32.@)
3721 UINT WINAPI
GetTextCharset(HDC hdc
)
3723 /* MSDN docs say this is equivalent */
3724 return GetTextCharsetInfo(hdc
, NULL
, 0);
3727 /***********************************************************************
3728 * GdiGetCharDimensions (GDI32.@)
3730 * Gets the average width of the characters in the English alphabet.
3733 * hdc [I] Handle to the device context to measure on.
3734 * lptm [O] Pointer to memory to store the text metrics into.
3735 * height [O] On exit, the maximum height of characters in the English alphabet.
3738 * The average width of characters in the English alphabet.
3741 * This function is used by the dialog manager to get the size of a dialog
3742 * unit. It should also be used by other pieces of code that need to know
3743 * the size of a dialog unit in logical units without having access to the
3744 * window handle of the dialog.
3745 * Windows caches the font metrics from this function, but we don't and
3746 * there doesn't appear to be an immediate advantage to do so.
3749 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3751 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3754 static const WCHAR alphabet
[] = {
3755 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3756 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3757 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3759 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3761 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3763 if (height
) *height
= sz
.cy
;
3764 return (sz
.cx
/ 26 + 1) / 2;
3767 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3769 FIXME("(%d): stub\n", fEnableEUDC
);
3773 /***********************************************************************
3774 * GetCharWidthI (GDI32.@)
3776 * Retrieve widths of characters.
3779 * hdc [I] Handle to a device context.
3780 * first [I] First glyph in range to query.
3781 * count [I] Number of glyph indices to query.
3782 * glyphs [I] Array of glyphs to query.
3783 * buffer [O] Buffer to receive character widths.
3786 * Only works with TrueType fonts.
3792 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3797 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3799 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3802 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3804 HeapFree(GetProcessHeap(), 0, abc
);
3808 for (i
= 0; i
< count
; i
++)
3809 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3811 HeapFree(GetProcessHeap(), 0, abc
);
3815 /***********************************************************************
3816 * GetFontUnicodeRanges (GDI32.@)
3818 * Retrieve a list of supported Unicode characters in a font.
3821 * hdc [I] Handle to a device context.
3822 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3825 * Success: Number of bytes written to the buffer pointed to by lpgs.
3829 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3833 DC
*dc
= get_dc_ptr(hdc
);
3835 TRACE("(%p, %p)\n", hdc
, lpgs
);
3839 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3840 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3846 /*************************************************************
3847 * FontIsLinked (GDI32.@)
3849 BOOL WINAPI
FontIsLinked(HDC hdc
)
3851 DC
*dc
= get_dc_ptr(hdc
);
3855 if (!dc
) return FALSE
;
3856 dev
= GET_DC_PHYSDEV( dc
, pFontIsLinked
);
3857 ret
= dev
->funcs
->pFontIsLinked( dev
);
3859 TRACE("returning %d\n", ret
);
3863 /*************************************************************
3864 * GetFontRealizationInfo (GDI32.@)
3866 BOOL WINAPI
GetFontRealizationInfo(HDC hdc
, struct font_realization_info
*info
)
3868 BOOL is_v0
= info
->size
== FIELD_OFFSET(struct font_realization_info
, unk
);
3873 if (info
->size
!= sizeof(*info
) && !is_v0
)
3876 dc
= get_dc_ptr(hdc
);
3877 if (!dc
) return FALSE
;
3878 dev
= GET_DC_PHYSDEV( dc
, pGetFontRealizationInfo
);
3879 ret
= dev
->funcs
->pGetFontRealizationInfo( dev
, info
);
3884 struct realization_info
3886 DWORD flags
; /* 1 for bitmap fonts, 3 for scalable fonts */
3887 DWORD cache_num
; /* keeps incrementing - num of fonts that have been created allowing for caching?? */
3888 DWORD instance_id
; /* identifies a realized font instance */
3891 /*************************************************************
3892 * GdiRealizationInfo (GDI32.@)
3894 * Returns a structure that contains some font information.
3896 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, struct realization_info
*info
)
3898 struct font_realization_info ri
;
3901 ri
.size
= sizeof(ri
);
3902 ret
= GetFontRealizationInfo( hdc
, &ri
);
3905 info
->flags
= ri
.flags
;
3906 info
->cache_num
= ri
.cache_num
;
3907 info
->instance_id
= ri
.instance_id
;