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;
90 LPtoDP(dc
->hSelf
, pt
, 2);
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 /***********************************************************************
412 * Returns a Unicode translation of str using the charset of the
413 * currently selected font in hdc. If count is -1 then str is assumed
414 * to be '\0' terminated, otherwise it contains the number of bytes to
415 * convert. If plenW is non-NULL, on return it will point to the
416 * number of WCHARs that have been written. If pCP is non-NULL, on
417 * return it will point to the codepage used in the conversion. The
418 * caller should free the returned LPWSTR from the process heap
421 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
427 cp
= GdiGetCodePage( hdc
);
429 if(count
== -1) count
= strlen(str
);
430 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
431 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
432 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
433 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
434 if(plenW
) *plenW
= lenW
;
439 /***********************************************************************
440 * CreateFontIndirectExA (GDI32.@)
442 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
444 ENUMLOGFONTEXDVW enumexW
;
446 if (!penumexA
) return 0;
448 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
449 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
450 return CreateFontIndirectExW( &enumexW
);
453 /***********************************************************************
454 * CreateFontIndirectExW (GDI32.@)
456 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
462 if (!penumex
) return 0;
464 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
465 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
466 penumex
->elfEnumLogfontEx
.elfScript
[0])
468 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
469 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
470 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
471 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
474 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
475 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
477 fontPtr
->logfont
= *plf
;
479 if (!(hFont
= alloc_gdi_handle( fontPtr
, OBJ_FONT
, &font_funcs
)))
481 HeapFree( GetProcessHeap(), 0, fontPtr
);
485 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
486 plf
->lfHeight
, plf
->lfWidth
,
487 plf
->lfEscapement
, plf
->lfOrientation
,
488 plf
->lfPitchAndFamily
,
489 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
490 plf
->lfQuality
, plf
->lfCharSet
,
491 debugstr_w(plf
->lfFaceName
),
492 plf
->lfWeight
> 400 ? "Bold" : "",
493 plf
->lfItalic
? "Italic" : "",
494 plf
->lfUnderline
? "Underline" : "", hFont
);
499 /***********************************************************************
500 * CreateFontIndirectA (GDI32.@)
502 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
508 FONT_LogFontAToW( plfA
, &lfW
);
509 return CreateFontIndirectW( &lfW
);
512 /***********************************************************************
513 * CreateFontIndirectW (GDI32.@)
515 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
517 ENUMLOGFONTEXDVW exdv
;
521 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
522 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
523 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
524 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
525 return CreateFontIndirectExW( &exdv
);
528 /*************************************************************************
529 * CreateFontA (GDI32.@)
531 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
532 INT orient
, INT weight
, DWORD italic
,
533 DWORD underline
, DWORD strikeout
, DWORD charset
,
534 DWORD outpres
, DWORD clippres
, DWORD quality
,
535 DWORD pitch
, LPCSTR name
)
539 logfont
.lfHeight
= height
;
540 logfont
.lfWidth
= width
;
541 logfont
.lfEscapement
= esc
;
542 logfont
.lfOrientation
= orient
;
543 logfont
.lfWeight
= weight
;
544 logfont
.lfItalic
= italic
;
545 logfont
.lfUnderline
= underline
;
546 logfont
.lfStrikeOut
= strikeout
;
547 logfont
.lfCharSet
= charset
;
548 logfont
.lfOutPrecision
= outpres
;
549 logfont
.lfClipPrecision
= clippres
;
550 logfont
.lfQuality
= quality
;
551 logfont
.lfPitchAndFamily
= pitch
;
554 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
556 logfont
.lfFaceName
[0] = '\0';
558 return CreateFontIndirectA( &logfont
);
561 /*************************************************************************
562 * CreateFontW (GDI32.@)
564 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
565 INT orient
, INT weight
, DWORD italic
,
566 DWORD underline
, DWORD strikeout
, DWORD charset
,
567 DWORD outpres
, DWORD clippres
, DWORD quality
,
568 DWORD pitch
, LPCWSTR name
)
572 logfont
.lfHeight
= height
;
573 logfont
.lfWidth
= width
;
574 logfont
.lfEscapement
= esc
;
575 logfont
.lfOrientation
= orient
;
576 logfont
.lfWeight
= weight
;
577 logfont
.lfItalic
= italic
;
578 logfont
.lfUnderline
= underline
;
579 logfont
.lfStrikeOut
= strikeout
;
580 logfont
.lfCharSet
= charset
;
581 logfont
.lfOutPrecision
= outpres
;
582 logfont
.lfClipPrecision
= clippres
;
583 logfont
.lfQuality
= quality
;
584 logfont
.lfPitchAndFamily
= pitch
;
587 lstrcpynW(logfont
.lfFaceName
, name
,
588 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
590 logfont
.lfFaceName
[0] = '\0';
592 return CreateFontIndirectW( &logfont
);
595 #define ASSOC_CHARSET_OEM 1
596 #define ASSOC_CHARSET_ANSI 2
597 #define ASSOC_CHARSET_SYMBOL 4
599 static DWORD
get_associated_charset_info(void)
601 static DWORD associated_charset
= -1;
603 if (associated_charset
== -1)
605 static const WCHAR assoc_charset_reg_keyW
[] = {'S','y','s','t','e','m','\\',
606 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
607 'C','o','n','t','r','o','l','\\','F','o','n','t','A','s','s','o','c','\\',
608 'A','s','s','o','c','i','a','t','e','d',' ','C','h','a','r','s','e','t','\0'};
609 static const WCHAR ansiW
[] = {'A','N','S','I','(','0','0',')','\0'};
610 static const WCHAR oemW
[] = {'O','E','M','(','F','F',')','\0'};
611 static const WCHAR symbolW
[] = {'S','Y','M','B','O','L','(','0','2',')','\0'};
612 static const WCHAR yesW
[] = {'Y','E','S','\0'};
615 DWORD type
, data_len
;
617 associated_charset
= 0;
619 if (RegOpenKeyW(HKEY_LOCAL_MACHINE
,
620 assoc_charset_reg_keyW
, &hkey
) != ERROR_SUCCESS
)
623 data_len
= sizeof(dataW
);
624 if (!RegQueryValueExW(hkey
, ansiW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
625 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
626 associated_charset
|= ASSOC_CHARSET_ANSI
;
628 data_len
= sizeof(dataW
);
629 if (!RegQueryValueExW(hkey
, oemW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
630 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
631 associated_charset
|= ASSOC_CHARSET_OEM
;
633 data_len
= sizeof(dataW
);
634 if (!RegQueryValueExW(hkey
, symbolW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
635 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
636 associated_charset
|= ASSOC_CHARSET_SYMBOL
;
640 TRACE("associated_charset = %d\n", associated_charset
);
643 return associated_charset
;
646 static void update_font_code_page( DC
*dc
, HANDLE font
)
649 int charset
= GetTextCharsetInfo( dc
->hSelf
, NULL
, 0 );
652 GetObjectW( font
, sizeof(lf
), &lf
);
654 if (charset
== ANSI_CHARSET
&& !(lf
.lfClipPrecision
& CLIP_DFA_DISABLE
) &&
655 get_associated_charset_info() & ASSOC_CHARSET_ANSI
)
656 charset
= DEFAULT_CHARSET
;
658 /* Hmm, nicely designed api this one! */
659 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
660 dc
->font_code_page
= csi
.ciACP
;
664 dc
->font_code_page
= GetOEMCP();
666 case DEFAULT_CHARSET
:
667 dc
->font_code_page
= GetACP();
677 /* FIXME: These have no place here, but because x11drv
678 enumerates fonts with these (made up) charsets some apps
679 might use them and then the FIXME below would become
680 annoying. Now we could pick the intended codepage for
681 each of these, but since it's broken anyway we'll just
682 use CP_ACP and hope it'll go away...
684 dc
->font_code_page
= CP_ACP
;
688 FIXME("Can't find codepage for charset %d\n", charset
);
689 dc
->font_code_page
= CP_ACP
;
694 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
697 /***********************************************************************
700 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
703 DC
*dc
= get_dc_ptr( hdc
);
709 if (!GDI_inc_ref_count( handle
))
711 release_dc_ptr( dc
);
715 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
716 if (physdev
->funcs
->pSelectFont( physdev
, handle
, &aa_flags
))
720 dc
->aa_flags
= aa_flags
? aa_flags
: GGO_BITMAP
;
721 update_font_code_page( dc
, handle
);
722 GDI_dec_ref_count( ret
);
724 else GDI_dec_ref_count( handle
);
726 release_dc_ptr( dc
);
731 /***********************************************************************
734 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
736 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
742 FONT_LogFontWToA( &font
->logfont
, &lfA
);
743 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
744 memcpy( buffer
, &lfA
, count
);
746 else count
= sizeof(lfA
);
747 GDI_ReleaseObj( handle
);
751 /***********************************************************************
754 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
756 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
761 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
762 memcpy( buffer
, &font
->logfont
, count
);
764 else count
= sizeof(LOGFONTW
);
765 GDI_ReleaseObj( handle
);
770 /***********************************************************************
773 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
777 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
778 return HeapFree( GetProcessHeap(), 0, obj
);
782 /***********************************************************************
785 HFONT
nulldrv_SelectFont( PHYSDEV dev
, HFONT font
, UINT
*aa_flags
)
787 static const WCHAR desktopW
[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
788 'D','e','s','k','t','o','p',0 };
789 static int orientation
= -1, smoothing
= -1;
793 if (*aa_flags
) return 0;
795 GetObjectW( font
, sizeof(lf
), &lf
);
796 switch (lf
.lfQuality
)
798 case NONANTIALIASED_QUALITY
:
799 *aa_flags
= GGO_BITMAP
;
801 case ANTIALIASED_QUALITY
:
802 *aa_flags
= GGO_GRAY4_BITMAP
;
804 case CLEARTYPE_QUALITY
:
805 case CLEARTYPE_NATURAL_QUALITY
:
806 if (orientation
== -1)
808 if (RegOpenKeyW( HKEY_CURRENT_USER
, desktopW
, &key
)) break;
809 orientation
= get_subpixel_orientation( key
);
812 *aa_flags
= orientation
;
817 if (RegOpenKeyW( HKEY_CURRENT_USER
, desktopW
, &key
)) break;
818 smoothing
= get_default_smoothing( key
);
821 *aa_flags
= smoothing
;
828 /***********************************************************************
831 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
832 * We have to use other types because of the FONTENUMPROCW definition.
834 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
835 DWORD fType
, LPARAM lp
)
837 struct font_enum
*pfe
= (struct font_enum
*)lp
;
840 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
841 if ((!pfe
->lpLogFontParam
||
842 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
843 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
844 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
846 /* convert font metrics */
847 ENUMLOGFONTEXA logfont
;
848 NEWTEXTMETRICEXA tmA
;
852 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
853 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
854 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
855 ptm
= (TEXTMETRICW
*)&tmA
;
857 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
863 /***********************************************************************
864 * FONT_EnumFontFamiliesEx
866 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
867 LPARAM lParam
, BOOL unicode
)
870 DC
*dc
= get_dc_ptr( hDC
);
875 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
877 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
878 fe
.lpLogFontParam
= plf
;
879 fe
.lpEnumFunc
= efproc
;
881 fe
.unicode
= unicode
;
884 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
885 release_dc_ptr( dc
);
887 return ret
? fe
.retval
: 0;
890 /***********************************************************************
891 * EnumFontFamiliesExW (GDI32.@)
893 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
894 FONTENUMPROCW efproc
,
895 LPARAM lParam
, DWORD dwFlags
)
897 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
900 /***********************************************************************
901 * EnumFontFamiliesExA (GDI32.@)
903 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
904 FONTENUMPROCA efproc
,
905 LPARAM lParam
, DWORD dwFlags
)
911 FONT_LogFontAToW( plf
, &lfW
);
916 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
919 /***********************************************************************
920 * EnumFontFamiliesA (GDI32.@)
922 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
923 FONTENUMPROCA efproc
, LPARAM lpData
)
929 if (!*lpFamily
) return 1;
930 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
931 lf
.lfCharSet
= DEFAULT_CHARSET
;
932 lf
.lfPitchAndFamily
= 0;
937 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
940 /***********************************************************************
941 * EnumFontFamiliesW (GDI32.@)
943 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
944 FONTENUMPROCW efproc
, LPARAM lpData
)
950 if (!*lpFamily
) return 1;
951 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
952 lf
.lfCharSet
= DEFAULT_CHARSET
;
953 lf
.lfPitchAndFamily
= 0;
958 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
961 /***********************************************************************
962 * EnumFontsA (GDI32.@)
964 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
967 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
970 /***********************************************************************
971 * EnumFontsW (GDI32.@)
973 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
976 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
980 /***********************************************************************
981 * GetTextCharacterExtra (GDI32.@)
983 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
986 DC
*dc
= get_dc_ptr( hdc
);
987 if (!dc
) return 0x80000000;
989 release_dc_ptr( dc
);
994 /***********************************************************************
995 * SetTextCharacterExtra (GDI32.@)
997 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
999 INT ret
= 0x80000000;
1000 DC
* dc
= get_dc_ptr( hdc
);
1004 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
1005 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
1006 if (extra
!= 0x80000000)
1008 ret
= dc
->charExtra
;
1009 dc
->charExtra
= extra
;
1011 release_dc_ptr( dc
);
1017 /***********************************************************************
1018 * SetTextJustification (GDI32.@)
1020 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1024 DC
* dc
= get_dc_ptr( hdc
);
1026 if (!dc
) return FALSE
;
1028 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
1029 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
1032 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1033 if (!extra
) breaks
= 0;
1036 dc
->breakExtra
= extra
/ breaks
;
1037 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1045 release_dc_ptr( dc
);
1050 /***********************************************************************
1051 * GetTextFaceA (GDI32.@)
1053 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1055 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1056 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1057 GetTextFaceW( hdc
, res
, nameW
);
1063 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
1067 /* GetTextFaceA does NOT include the nul byte in the return count. */
1074 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1075 HeapFree( GetProcessHeap(), 0, nameW
);
1079 /***********************************************************************
1080 * GetTextFaceW (GDI32.@)
1082 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1087 DC
* dc
= get_dc_ptr( hdc
);
1090 dev
= GET_DC_PHYSDEV( dc
, pGetTextFace
);
1091 ret
= dev
->funcs
->pGetTextFace( dev
, count
, name
);
1092 release_dc_ptr( dc
);
1097 /***********************************************************************
1098 * GetTextExtentPoint32A (GDI32.@)
1100 * See GetTextExtentPoint32W.
1102 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1109 if (count
< 0) return FALSE
;
1111 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1115 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1116 HeapFree( GetProcessHeap(), 0, p
);
1119 TRACE("(%p %s %d %p): returning %d x %d\n",
1120 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1125 /***********************************************************************
1126 * GetTextExtentPoint32W [GDI32.@]
1128 * Computes width/height for a string.
1130 * Computes width and height of the specified string.
1136 BOOL WINAPI
GetTextExtentPoint32W(
1137 HDC hdc
, /* [in] Handle of device context */
1138 LPCWSTR str
, /* [in] Address of text string */
1139 INT count
, /* [in] Number of characters in string */
1140 LPSIZE size
) /* [out] Address of structure for string size */
1142 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1145 /***********************************************************************
1146 * GetTextExtentExPointI [GDI32.@]
1148 * Computes width and height of the array of glyph indices.
1151 * hdc [I] Handle of device context.
1152 * indices [I] Glyph index array.
1153 * count [I] Number of glyphs in array.
1154 * max_ext [I] Maximum width in glyphs.
1155 * nfit [O] Maximum number of characters.
1156 * dxs [O] Partial string widths.
1157 * size [O] Returned string size.
1163 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1164 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1169 INT buffer
[256], *pos
= dxs
;
1171 if (count
< 0) return FALSE
;
1173 dc
= get_dc_ptr( hdc
);
1174 if (!dc
) return FALSE
;
1179 if (count
> 256 && !(pos
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pos
) )))
1181 release_dc_ptr( dc
);
1186 ret
= get_char_positions_indices( dc
, indices
, count
, pos
, size
);
1191 for (i
= 0; i
< count
; i
++)
1193 unsigned int dx
= abs( INTERNAL_XDSTOWS( dc
, pos
[i
] )) + (i
+ 1) * dc
->charExtra
;
1194 if (nfit
&& dx
> (unsigned int)max_ext
) break;
1195 if (dxs
) dxs
[i
] = dx
;
1197 if (nfit
) *nfit
= i
;
1200 size
->cx
= abs( INTERNAL_XDSTOWS( dc
, size
->cx
)) + count
* dc
->charExtra
;
1201 size
->cy
= abs( INTERNAL_YDSTOWS( dc
, size
->cy
));
1204 if (pos
!= buffer
&& pos
!= dxs
) HeapFree( GetProcessHeap(), 0, pos
);
1205 release_dc_ptr( dc
);
1207 TRACE("(%p %p %d %p): returning %d x %d\n",
1208 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1212 /***********************************************************************
1213 * GetTextExtentPointI [GDI32.@]
1215 * Computes width and height of the array of glyph indices.
1218 * hdc [I] Handle of device context.
1219 * indices [I] Glyph index array.
1220 * count [I] Number of glyphs in array.
1221 * size [O] Returned string size.
1227 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1229 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1233 /***********************************************************************
1234 * GetTextExtentPointA (GDI32.@)
1236 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1239 TRACE("not bug compatible.\n");
1240 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1243 /***********************************************************************
1244 * GetTextExtentPointW (GDI32.@)
1246 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1249 TRACE("not bug compatible.\n");
1250 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1254 /***********************************************************************
1255 * GetTextExtentExPointA (GDI32.@)
1257 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1258 INT maxExt
, LPINT lpnFit
,
1259 LPINT alpDx
, LPSIZE size
)
1266 if (count
< 0) return FALSE
;
1267 if (maxExt
< -1) return FALSE
;
1271 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1272 if (!walpDx
) return FALSE
;
1275 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1276 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1279 INT n
= lpnFit
? *lpnFit
: wlen
;
1281 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1283 alpDx
[j
] = walpDx
[i
];
1284 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1287 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1288 HeapFree( GetProcessHeap(), 0, p
);
1289 HeapFree( GetProcessHeap(), 0, walpDx
);
1294 /***********************************************************************
1295 * GetTextExtentExPointW (GDI32.@)
1297 * Return the size of the string as it would be if it was output properly by
1300 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
, INT max_ext
,
1301 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1306 INT buffer
[256], *pos
= dxs
;
1308 if (count
< 0) return FALSE
;
1310 dc
= get_dc_ptr(hdc
);
1311 if (!dc
) return FALSE
;
1316 if (count
> 256 && !(pos
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pos
) )))
1318 release_dc_ptr( dc
);
1323 ret
= get_char_positions( dc
, str
, count
, pos
, size
);
1328 for (i
= 0; i
< count
; i
++)
1330 unsigned int dx
= abs( INTERNAL_XDSTOWS( dc
, pos
[i
] )) + (i
+ 1) * dc
->charExtra
;
1331 if (nfit
&& dx
> (unsigned int)max_ext
) break;
1332 if (dxs
) dxs
[i
] = dx
;
1334 if (nfit
) *nfit
= i
;
1337 size
->cx
= abs( INTERNAL_XDSTOWS( dc
, size
->cx
)) + count
* dc
->charExtra
;
1338 size
->cy
= abs( INTERNAL_YDSTOWS( dc
, size
->cy
));
1341 if (pos
!= buffer
&& pos
!= dxs
) HeapFree( GetProcessHeap(), 0, pos
);
1342 release_dc_ptr( dc
);
1344 TRACE("(%p, %s, %d) returning %dx%d\n", hdc
, debugstr_wn(str
,count
), max_ext
, size
->cx
, size
->cy
);
1348 /***********************************************************************
1349 * GetTextMetricsA (GDI32.@)
1351 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1355 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1356 FONT_TextMetricWToA( &tm32
, metrics
);
1360 /***********************************************************************
1361 * GetTextMetricsW (GDI32.@)
1363 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1367 DC
* dc
= get_dc_ptr( hdc
);
1368 if (!dc
) return FALSE
;
1370 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1371 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1375 /* device layer returns values in device units
1376 * therefore we have to convert them to logical */
1378 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1379 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1380 metrics
->tmHeight
= height_to_LP( dc
, metrics
->tmHeight
);
1381 metrics
->tmAscent
= height_to_LP( dc
, metrics
->tmAscent
);
1382 metrics
->tmDescent
= height_to_LP( dc
, metrics
->tmDescent
);
1383 metrics
->tmInternalLeading
= height_to_LP( dc
, metrics
->tmInternalLeading
);
1384 metrics
->tmExternalLeading
= height_to_LP( dc
, metrics
->tmExternalLeading
);
1385 metrics
->tmAveCharWidth
= width_to_LP( dc
, metrics
->tmAveCharWidth
);
1386 metrics
->tmMaxCharWidth
= width_to_LP( dc
, metrics
->tmMaxCharWidth
);
1387 metrics
->tmOverhang
= width_to_LP( dc
, metrics
->tmOverhang
);
1390 TRACE("text metrics:\n"
1391 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1392 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1393 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1394 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1395 " PitchAndFamily = %02x\n"
1396 " --------------------\n"
1397 " InternalLeading = %i\n"
1401 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1402 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1403 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1404 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1405 metrics
->tmPitchAndFamily
,
1406 metrics
->tmInternalLeading
,
1409 metrics
->tmHeight
);
1411 release_dc_ptr( dc
);
1416 /***********************************************************************
1417 * GetOutlineTextMetricsA (GDI32.@)
1418 * Gets metrics for TrueType fonts.
1421 * If the supplied buffer isn't big enough Windows partially fills it up to
1422 * its given length and returns that length.
1425 * Success: Non-zero or size of required buffer
1428 UINT WINAPI
GetOutlineTextMetricsA(
1429 HDC hdc
, /* [in] Handle of device context */
1430 UINT cbData
, /* [in] Size of metric data array */
1431 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1433 char buf
[512], *ptr
;
1435 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1436 OUTLINETEXTMETRICA
*output
= lpOTM
;
1439 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1441 if(ret
> sizeof(buf
))
1442 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1443 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1445 needed
= sizeof(OUTLINETEXTMETRICA
);
1446 if(lpOTMW
->otmpFamilyName
)
1447 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1448 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1449 NULL
, 0, NULL
, NULL
);
1450 if(lpOTMW
->otmpFaceName
)
1451 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1452 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1453 NULL
, 0, NULL
, NULL
);
1454 if(lpOTMW
->otmpStyleName
)
1455 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1456 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1457 NULL
, 0, NULL
, NULL
);
1458 if(lpOTMW
->otmpFullName
)
1459 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1460 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1461 NULL
, 0, NULL
, NULL
);
1468 TRACE("needed = %d\n", needed
);
1470 /* Since the supplied buffer isn't big enough, we'll alloc one
1471 that is and memcpy the first cbData bytes into the lpOTM at
1473 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1475 ret
= output
->otmSize
= min(needed
, cbData
);
1476 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1477 output
->otmFiller
= 0;
1478 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1479 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1480 output
->otmfsType
= lpOTMW
->otmfsType
;
1481 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1482 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1483 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1484 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1485 output
->otmAscent
= lpOTMW
->otmAscent
;
1486 output
->otmDescent
= lpOTMW
->otmDescent
;
1487 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1488 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1489 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1490 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1491 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1492 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1493 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1494 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1495 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1496 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1497 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1498 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1499 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1500 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1501 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1502 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1505 ptr
= (char*)(output
+ 1);
1506 left
= needed
- sizeof(*output
);
1508 if(lpOTMW
->otmpFamilyName
) {
1509 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1510 len
= WideCharToMultiByte(CP_ACP
, 0,
1511 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1512 ptr
, left
, NULL
, NULL
);
1516 output
->otmpFamilyName
= 0;
1518 if(lpOTMW
->otmpFaceName
) {
1519 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1520 len
= WideCharToMultiByte(CP_ACP
, 0,
1521 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1522 ptr
, left
, NULL
, NULL
);
1526 output
->otmpFaceName
= 0;
1528 if(lpOTMW
->otmpStyleName
) {
1529 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1530 len
= WideCharToMultiByte(CP_ACP
, 0,
1531 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1532 ptr
, left
, NULL
, NULL
);
1536 output
->otmpStyleName
= 0;
1538 if(lpOTMW
->otmpFullName
) {
1539 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1540 len
= WideCharToMultiByte(CP_ACP
, 0,
1541 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1542 ptr
, left
, NULL
, NULL
);
1545 output
->otmpFullName
= 0;
1549 if(output
!= lpOTM
) {
1550 memcpy(lpOTM
, output
, cbData
);
1551 HeapFree(GetProcessHeap(), 0, output
);
1553 /* check if the string offsets really fit into the provided size */
1554 /* FIXME: should we check string length as well? */
1555 /* make sure that we don't read/write beyond the provided buffer */
1556 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1558 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1559 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1562 /* make sure that we don't read/write beyond the provided buffer */
1563 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1565 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1566 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1569 /* make sure that we don't read/write beyond the provided buffer */
1570 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1572 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1573 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1576 /* make sure that we don't read/write beyond the provided buffer */
1577 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1579 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1580 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1585 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1586 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1592 /***********************************************************************
1593 * GetOutlineTextMetricsW [GDI32.@]
1595 UINT WINAPI
GetOutlineTextMetricsW(
1596 HDC hdc
, /* [in] Handle of device context */
1597 UINT cbData
, /* [in] Size of metric data array */
1598 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1600 DC
*dc
= get_dc_ptr( hdc
);
1601 OUTLINETEXTMETRICW
*output
= lpOTM
;
1605 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1608 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1609 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1611 if (lpOTM
&& ret
> cbData
)
1613 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1614 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1619 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1620 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1621 output
->otmTextMetrics
.tmHeight
= height_to_LP( dc
, output
->otmTextMetrics
.tmHeight
);
1622 output
->otmTextMetrics
.tmAscent
= height_to_LP( dc
, output
->otmTextMetrics
.tmAscent
);
1623 output
->otmTextMetrics
.tmDescent
= height_to_LP( dc
, output
->otmTextMetrics
.tmDescent
);
1624 output
->otmTextMetrics
.tmInternalLeading
= height_to_LP( dc
, output
->otmTextMetrics
.tmInternalLeading
);
1625 output
->otmTextMetrics
.tmExternalLeading
= height_to_LP( dc
, output
->otmTextMetrics
.tmExternalLeading
);
1626 output
->otmTextMetrics
.tmAveCharWidth
= width_to_LP( dc
, output
->otmTextMetrics
.tmAveCharWidth
);
1627 output
->otmTextMetrics
.tmMaxCharWidth
= width_to_LP( dc
, output
->otmTextMetrics
.tmMaxCharWidth
);
1628 output
->otmTextMetrics
.tmOverhang
= width_to_LP( dc
, output
->otmTextMetrics
.tmOverhang
);
1629 output
->otmAscent
= height_to_LP( dc
, output
->otmAscent
);
1630 output
->otmDescent
= height_to_LP( dc
, output
->otmDescent
);
1631 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1632 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1633 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1634 output
->otmrcFontBox
.top
= height_to_LP( dc
, output
->otmrcFontBox
.top
);
1635 output
->otmrcFontBox
.bottom
= height_to_LP( dc
, output
->otmrcFontBox
.bottom
);
1636 output
->otmrcFontBox
.left
= width_to_LP( dc
, output
->otmrcFontBox
.left
);
1637 output
->otmrcFontBox
.right
= width_to_LP( dc
, output
->otmrcFontBox
.right
);
1638 output
->otmMacAscent
= height_to_LP( dc
, output
->otmMacAscent
);
1639 output
->otmMacDescent
= height_to_LP( dc
, output
->otmMacDescent
);
1640 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1641 output
->otmptSubscriptSize
.x
= width_to_LP( dc
, output
->otmptSubscriptSize
.x
);
1642 output
->otmptSubscriptSize
.y
= height_to_LP( dc
, output
->otmptSubscriptSize
.y
);
1643 output
->otmptSubscriptOffset
.x
= width_to_LP( dc
, output
->otmptSubscriptOffset
.x
);
1644 output
->otmptSubscriptOffset
.y
= height_to_LP( dc
, output
->otmptSubscriptOffset
.y
);
1645 output
->otmptSuperscriptSize
.x
= width_to_LP( dc
, output
->otmptSuperscriptSize
.x
);
1646 output
->otmptSuperscriptSize
.y
= height_to_LP( dc
, output
->otmptSuperscriptSize
.y
);
1647 output
->otmptSuperscriptOffset
.x
= width_to_LP( dc
, output
->otmptSuperscriptOffset
.x
);
1648 output
->otmptSuperscriptOffset
.y
= height_to_LP( dc
, output
->otmptSuperscriptOffset
.y
);
1649 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1650 output
->otmsStrikeoutPosition
= height_to_LP( dc
, output
->otmsStrikeoutPosition
);
1651 output
->otmsUnderscoreSize
= height_to_LP( dc
, output
->otmsUnderscoreSize
);
1652 output
->otmsUnderscorePosition
= height_to_LP( dc
, output
->otmsUnderscorePosition
);
1656 memcpy(lpOTM
, output
, cbData
);
1657 HeapFree(GetProcessHeap(), 0, output
);
1665 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1667 INT i
, count
= lastChar
- firstChar
+ 1;
1675 mbcp
= GdiGetCodePage(hdc
);
1683 if (lastChar
> 0xffff)
1685 if ((firstChar
^ lastChar
) > 0xff)
1689 if (lastChar
> 0xff)
1695 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1699 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1703 str
[i
++] = (BYTE
)(c
>> 8);
1704 if (c
<= 0xff && IsDBCSLeadByteEx(mbcp
, c
))
1705 str
[i
] = 0x1f; /* FIXME: use default character */
1719 /***********************************************************************
1720 * GetCharWidthW (GDI32.@)
1721 * GetCharWidth32W (GDI32.@)
1723 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1729 DC
* dc
= get_dc_ptr( hdc
);
1731 if (!dc
) return FALSE
;
1733 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1734 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1738 /* convert device units to logical */
1739 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1740 *buffer
= width_to_LP( dc
, *buffer
);
1742 release_dc_ptr( dc
);
1747 /***********************************************************************
1748 * GetCharWidthA (GDI32.@)
1749 * GetCharWidth32A (GDI32.@)
1751 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1759 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1763 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1765 for(i
= 0; i
< wlen
; i
++)
1767 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1775 HeapFree(GetProcessHeap(), 0, str
);
1776 HeapFree(GetProcessHeap(), 0, wstr
);
1782 /* helper for nulldrv_ExtTextOut */
1783 static DWORD
get_glyph_bitmap( HDC hdc
, UINT index
, UINT flags
, UINT aa_flags
,
1784 GLYPHMETRICS
*metrics
, struct gdi_image_bits
*image
)
1786 static const MAT2 identity
= { {0,1}, {0,0}, {0,0}, {0,1} };
1787 UINT indices
[3] = {0, 0, 0x20};
1793 if (flags
& ETO_GLYPH_INDEX
) aa_flags
|= GGO_GLYPH_INDEX
;
1795 for (i
= 0; i
< sizeof(indices
) / sizeof(indices
[0]); i
++)
1798 ret
= GetGlyphOutlineW( hdc
, index
, aa_flags
, metrics
, 0, NULL
, &identity
);
1799 if (ret
!= GDI_ERROR
) break;
1802 if (ret
== GDI_ERROR
) return ERROR_NOT_FOUND
;
1803 if (!image
) return ERROR_SUCCESS
;
1807 if (!ret
) /* empty glyph */
1809 metrics
->gmBlackBoxX
= metrics
->gmBlackBoxY
= 0;
1810 return ERROR_SUCCESS
;
1813 stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1814 size
= metrics
->gmBlackBoxY
* stride
;
1816 if (!(image
->ptr
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
1817 image
->is_copy
= TRUE
;
1818 image
->free
= free_heap_bits
;
1820 ret
= GetGlyphOutlineW( hdc
, index
, aa_flags
, metrics
, size
, image
->ptr
, &identity
);
1821 if (ret
== GDI_ERROR
)
1823 HeapFree( GetProcessHeap(), 0, image
->ptr
);
1824 return ERROR_NOT_FOUND
;
1826 return ERROR_SUCCESS
;
1829 /* helper for nulldrv_ExtTextOut */
1830 static RECT
get_total_extents( HDC hdc
, INT x
, INT y
, UINT flags
, UINT aa_flags
,
1831 LPCWSTR str
, UINT count
, const INT
*dx
)
1836 reset_bounds( &bounds
);
1837 for (i
= 0; i
< count
; i
++)
1839 GLYPHMETRICS metrics
;
1841 if (get_glyph_bitmap( hdc
, str
[i
], flags
, aa_flags
, &metrics
, NULL
)) continue;
1843 rect
.left
= x
+ metrics
.gmptGlyphOrigin
.x
;
1844 rect
.top
= y
- metrics
.gmptGlyphOrigin
.y
;
1845 rect
.right
= rect
.left
+ metrics
.gmBlackBoxX
;
1846 rect
.bottom
= rect
.top
+ metrics
.gmBlackBoxY
;
1847 add_bounds_rect( &bounds
, &rect
);
1851 if (flags
& ETO_PDY
)
1854 y
+= dx
[ i
* 2 + 1];
1860 x
+= metrics
.gmCellIncX
;
1861 y
+= metrics
.gmCellIncY
;
1867 /* helper for nulldrv_ExtTextOut */
1868 static void draw_glyph( HDC hdc
, INT origin_x
, INT origin_y
, const GLYPHMETRICS
*metrics
,
1869 const struct gdi_image_bits
*image
, const RECT
*clip
)
1871 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1872 UINT i
, count
, max_count
;
1874 BYTE
*ptr
= image
->ptr
;
1875 int stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1877 RECT rect
, clipped_rect
;
1879 rect
.left
= origin_x
+ metrics
->gmptGlyphOrigin
.x
;
1880 rect
.top
= origin_y
- metrics
->gmptGlyphOrigin
.y
;
1881 rect
.right
= rect
.left
+ metrics
->gmBlackBoxX
;
1882 rect
.bottom
= rect
.top
+ metrics
->gmBlackBoxY
;
1883 if (!clip
) clipped_rect
= rect
;
1884 else if (!intersect_rect( &clipped_rect
, &rect
, clip
)) return;
1886 max_count
= (metrics
->gmBlackBoxX
+ 1) * metrics
->gmBlackBoxY
;
1887 pts
= HeapAlloc( GetProcessHeap(), 0, max_count
* sizeof(*pts
) );
1891 ptr
+= (clipped_rect
.top
- rect
.top
) * stride
;
1892 for (y
= clipped_rect
.top
; y
< clipped_rect
.bottom
; y
++, ptr
+= stride
)
1894 for (x
= clipped_rect
.left
- rect
.left
; x
< clipped_rect
.right
- rect
.left
; x
++)
1896 while (x
< clipped_rect
.right
- rect
.left
&& !(ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1897 pts
[count
].x
= rect
.left
+ x
;
1898 while (x
< clipped_rect
.right
- rect
.left
&& (ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1899 pts
[count
+ 1].x
= rect
.left
+ x
;
1900 if (pts
[count
+ 1].x
> pts
[count
].x
)
1902 pts
[count
].y
= pts
[count
+ 1].y
= y
;
1907 assert( count
<= max_count
);
1908 DPtoLP( hdc
, pts
, count
);
1909 for (i
= 0; i
< count
; i
+= 2) Polyline( hdc
, pts
+ i
, 2 );
1910 HeapFree( GetProcessHeap(), 0, pts
);
1913 /***********************************************************************
1914 * nulldrv_ExtTextOut
1916 BOOL
nulldrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
1917 LPCWSTR str
, UINT count
, const INT
*dx
)
1919 DC
*dc
= get_nulldrv_dc( dev
);
1925 if (flags
& ETO_OPAQUE
)
1928 HBRUSH brush
= CreateSolidBrush( GetNearestColor( dev
->hdc
, GetBkColor(dev
->hdc
) ));
1932 orig
= SelectObject( dev
->hdc
, brush
);
1933 DPtoLP( dev
->hdc
, (POINT
*)&rc
, 2 );
1934 PatBlt( dev
->hdc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, PATCOPY
);
1935 SelectObject( dev
->hdc
, orig
);
1936 DeleteObject( brush
);
1940 if (!count
) return TRUE
;
1942 if (dc
->aa_flags
!= GGO_BITMAP
)
1944 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1945 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1946 struct gdi_image_bits bits
;
1947 struct bitblt_coords src
, dst
;
1949 /* FIXME Subpixel modes */
1950 UINT aa_flags
= GGO_GRAY4_BITMAP
;
1952 dst_dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
1953 src
.visrect
= get_total_extents( dev
->hdc
, x
, y
, flags
, aa_flags
, str
, count
, dx
);
1954 if (flags
& ETO_CLIPPED
) intersect_rect( &src
.visrect
, &src
.visrect
, rect
);
1955 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return TRUE
;
1957 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1958 src
.x
= src
.visrect
.left
;
1959 src
.y
= src
.visrect
.top
;
1960 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1961 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1963 if ((flags
& ETO_OPAQUE
) && (src
.visrect
.left
>= rect
->left
) && (src
.visrect
.top
>= rect
->top
) &&
1964 (src
.visrect
.right
<= rect
->right
) && (src
.visrect
.bottom
<= rect
->bottom
))
1966 /* we can avoid the GetImage, just query the needed format */
1967 memset( &info
->bmiHeader
, 0, sizeof(info
->bmiHeader
) );
1968 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1969 info
->bmiHeader
.biWidth
= src
.width
;
1970 info
->bmiHeader
.biHeight
= -src
.height
;
1971 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, info
, NULL
, NULL
, NULL
, 0 );
1972 if (!err
|| err
== ERROR_BAD_FORMAT
)
1974 /* make the source rectangle relative to the source bits */
1976 src
.visrect
.left
= src
.visrect
.top
= 0;
1977 src
.visrect
.right
= src
.width
;
1978 src
.visrect
.bottom
= src
.height
;
1980 bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1981 if (!bits
.ptr
) return ERROR_OUTOFMEMORY
;
1982 bits
.is_copy
= TRUE
;
1983 bits
.free
= free_heap_bits
;
1984 err
= ERROR_SUCCESS
;
1989 PHYSDEV src_dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
1990 err
= src_dev
->funcs
->pGetImage( src_dev
, info
, &bits
, &src
);
1991 if (!err
&& !bits
.is_copy
)
1993 void *ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1996 if (bits
.free
) bits
.free( &bits
);
1997 return ERROR_OUTOFMEMORY
;
1999 memcpy( ptr
, bits
.ptr
, get_dib_image_size( info
));
2000 if (bits
.free
) bits
.free( &bits
);
2002 bits
.is_copy
= TRUE
;
2003 bits
.free
= free_heap_bits
;
2008 /* make x,y relative to the image bits */
2009 x
+= src
.visrect
.left
- dst
.visrect
.left
;
2010 y
+= src
.visrect
.top
- dst
.visrect
.top
;
2011 render_aa_text_bitmapinfo( dev
->hdc
, info
, &bits
, &src
, x
, y
, flags
,
2012 aa_flags
, str
, count
, dx
);
2013 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, info
, &bits
, &src
, &dst
, SRCCOPY
);
2014 if (bits
.free
) bits
.free( &bits
);
2019 pen
= CreatePen( PS_SOLID
, 1, GetTextColor(dev
->hdc
) );
2020 orig
= SelectObject( dev
->hdc
, pen
);
2022 for (i
= 0; i
< count
; i
++)
2024 GLYPHMETRICS metrics
;
2025 struct gdi_image_bits image
;
2027 err
= get_glyph_bitmap( dev
->hdc
, str
[i
], flags
, GGO_BITMAP
, &metrics
, &image
);
2030 if (image
.ptr
) draw_glyph( dev
->hdc
, x
, y
, &metrics
, &image
, (flags
& ETO_CLIPPED
) ? rect
: NULL
);
2031 if (image
.free
) image
.free( &image
);
2035 if (flags
& ETO_PDY
)
2038 y
+= dx
[ i
* 2 + 1];
2044 x
+= metrics
.gmCellIncX
;
2045 y
+= metrics
.gmCellIncY
;
2049 SelectObject( dev
->hdc
, orig
);
2050 DeleteObject( pen
);
2055 /***********************************************************************
2056 * ExtTextOutA (GDI32.@)
2060 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
2061 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
2069 if (flags
& ETO_GLYPH_INDEX
)
2070 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
2072 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
2075 unsigned int i
= 0, j
= 0;
2077 /* allocate enough for a ETO_PDY */
2078 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
2080 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
2084 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
2085 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
2088 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
2095 lpDxW
[j
++] = lpDx
[i
* 2];
2096 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
2099 lpDxW
[j
++] = lpDx
[i
];
2105 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
2107 HeapFree( GetProcessHeap(), 0, p
);
2108 HeapFree( GetProcessHeap(), 0, lpDxW
);
2113 /***********************************************************************
2114 * ExtTextOutW (GDI32.@)
2116 * Draws text using the currently selected font, background color, and text color.
2120 * x,y [I] coordinates of string
2122 * ETO_GRAYED - undocumented on MSDN
2123 * ETO_OPAQUE - use background color for fill the rectangle
2124 * ETO_CLIPPED - clipping text to the rectangle
2125 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2126 * than encoded characters. Implies ETO_IGNORELANGUAGE
2127 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2128 * Affects BiDi ordering
2129 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2130 * ETO_PDY - unimplemented
2131 * ETO_NUMERICSLATIN - unimplemented always assumed -
2132 * do not translate numbers into locale representations
2133 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2134 * lprect [I] dimensions for clipping or/and opaquing
2135 * str [I] text string
2136 * count [I] number of symbols in string
2137 * lpDx [I] optional parameter with distance between drawing characters
2143 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
2144 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
2147 LPWSTR reordered_str
= (LPWSTR
)str
;
2148 WORD
*glyphs
= NULL
;
2149 UINT align
= GetTextAlign( hdc
);
2150 DWORD layout
= GetLayout( hdc
);
2154 double cosEsc
, sinEsc
;
2158 POINT
*deltas
= NULL
, width
= {0, 0};
2160 DC
* dc
= get_dc_ptr( hdc
);
2163 static int quietfixme
= 0;
2165 if (!dc
) return FALSE
;
2167 breakRem
= dc
->breakRem
;
2169 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
2171 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2176 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
2177 type
= GetObjectType(hdc
);
2178 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
2180 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
2181 release_dc_ptr( dc
);
2185 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
2186 if (layout
& LAYOUT_RTL
)
2188 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
2189 align
^= TA_RTLREADING
;
2192 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
2195 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
2197 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
2198 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
2199 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
2201 flags
|= ETO_IGNORELANGUAGE
;
2204 flags
|= ETO_GLYPH_INDEX
;
2205 if (cGlyphs
!= count
)
2209 else if(flags
& ETO_GLYPH_INDEX
)
2210 glyphs
= reordered_str
;
2212 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
2213 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
2214 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
2216 if(align
& TA_UPDATECP
)
2218 GetCurrentPositionEx( hdc
, &pt
);
2223 GetTextMetricsW(hdc
, &tm
);
2224 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
2226 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
2227 lf
.lfEscapement
= 0;
2229 if ((dc
->GraphicsMode
== GM_COMPATIBLE
) &&
2230 (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
* dc
->xformWorld2Vport
.eM22
< 0))
2232 lf
.lfEscapement
= -lf
.lfEscapement
;
2235 if(lf
.lfEscapement
!= 0)
2237 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
2238 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
2249 LPtoDP(hdc
, (POINT
*)&rc
, 2);
2251 if (flags
& ETO_OPAQUE
)
2252 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2254 else flags
&= ~ETO_CLIPPED
;
2264 LPtoDP(hdc
, &pt
, 1);
2268 char_extra
= GetTextCharacterExtra(hdc
);
2269 if (char_extra
&& lpDx
&& GetDeviceCaps( hdc
, TECHNOLOGY
) == DT_RASPRINTER
)
2270 char_extra
= 0; /* Printer drivers don't add char_extra if lpDx is supplied */
2272 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2275 POINT total
= {0, 0}, desired
[2];
2277 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2280 if (flags
& ETO_PDY
)
2282 for (i
= 0; i
< count
; i
++)
2284 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
2285 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
2290 for (i
= 0; i
< count
; i
++)
2292 deltas
[i
].x
= lpDx
[i
] + char_extra
;
2299 INT
*dx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*dx
) );
2301 if (flags
& ETO_GLYPH_INDEX
)
2302 GetTextExtentExPointI( hdc
, glyphs
, count
, -1, NULL
, dx
, &sz
);
2304 GetTextExtentExPointW( hdc
, reordered_str
, count
, -1, NULL
, dx
, &sz
);
2306 deltas
[0].x
= dx
[0];
2308 for (i
= 1; i
< count
; i
++)
2310 deltas
[i
].x
= dx
[i
] - dx
[i
- 1];
2313 HeapFree( GetProcessHeap(), 0, dx
);
2316 for(i
= 0; i
< count
; i
++)
2318 total
.x
+= deltas
[i
].x
;
2319 total
.y
+= deltas
[i
].y
;
2321 desired
[0].x
= desired
[0].y
= 0;
2323 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
2324 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
2326 LPtoDP(hdc
, desired
, 2);
2327 desired
[1].x
-= desired
[0].x
;
2328 desired
[1].y
-= desired
[0].y
;
2330 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2332 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2333 desired
[1].x
= -desired
[1].x
;
2334 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2335 desired
[1].y
= -desired
[1].y
;
2338 deltas
[i
].x
= desired
[1].x
- width
.x
;
2339 deltas
[i
].y
= desired
[1].y
- width
.y
;
2349 if(flags
& ETO_GLYPH_INDEX
)
2350 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2352 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2353 desired
[0].x
= desired
[0].y
= 0;
2354 desired
[1].x
= sz
.cx
;
2356 LPtoDP(hdc
, desired
, 2);
2357 desired
[1].x
-= desired
[0].x
;
2358 desired
[1].y
-= desired
[0].y
;
2360 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2362 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2363 desired
[1].x
= -desired
[1].x
;
2364 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2365 desired
[1].y
= -desired
[1].y
;
2370 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2371 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2372 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2375 if (align
& TA_UPDATECP
)
2379 DPtoLP(hdc
, &pt
, 1);
2380 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2392 if (align
& TA_UPDATECP
)
2396 DPtoLP(hdc
, &pt
, 1);
2397 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2402 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2405 y
+= tm
.tmAscent
* cosEsc
;
2406 x
+= tm
.tmAscent
* sinEsc
;
2410 y
-= tm
.tmDescent
* cosEsc
;
2411 x
-= tm
.tmDescent
* sinEsc
;
2418 if (GetBkMode(hdc
) != TRANSPARENT
)
2420 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2422 if(!(flags
& ETO_OPAQUE
) || !lprect
||
2423 x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2424 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2428 text_box
.right
= x
+ width
.x
;
2429 text_box
.top
= y
- tm
.tmAscent
;
2430 text_box
.bottom
= y
+ tm
.tmDescent
;
2432 if (flags
& ETO_CLIPPED
) intersect_rect( &text_box
, &text_box
, &rc
);
2433 if (!is_rect_empty( &text_box
))
2434 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &text_box
, NULL
, 0, NULL
);
2439 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2440 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2443 HeapFree(GetProcessHeap(), 0, deltas
);
2444 if(glyphs
!= reordered_str
)
2445 HeapFree(GetProcessHeap(), 0, glyphs
);
2446 if(reordered_str
!= str
)
2447 HeapFree(GetProcessHeap(), 0, reordered_str
);
2449 release_dc_ptr( dc
);
2451 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2453 int underlinePos
, strikeoutPos
;
2454 int underlineWidth
, strikeoutWidth
;
2455 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2456 OUTLINETEXTMETRICW
* otm
= NULL
;
2458 HPEN hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2459 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2461 hbrush
= SelectObject(hdc
, hbrush
);
2466 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2467 strikeoutPos
= tm
.tmAscent
/ 2;
2468 strikeoutWidth
= underlineWidth
;
2472 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2473 GetOutlineTextMetricsW(hdc
, size
, otm
);
2474 underlinePos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscorePosition
));
2475 if (otm
->otmsUnderscorePosition
< 0) underlinePos
= -underlinePos
;
2476 underlineWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscoreSize
));
2477 if (otm
->otmsUnderscoreSize
< 0) underlineWidth
= -underlineWidth
;
2478 strikeoutPos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutPosition
));
2479 if (otm
->otmsStrikeoutPosition
< 0) strikeoutPos
= -strikeoutPos
;
2480 strikeoutWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutSize
));
2481 HeapFree(GetProcessHeap(), 0, otm
);
2487 pts
[0].x
= x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2488 pts
[0].y
= y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2489 pts
[1].x
= x
+ width
.x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2490 pts
[1].y
= y
+ width
.y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2491 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2492 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2493 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2494 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2495 pts
[4].x
= pts
[0].x
;
2496 pts
[4].y
= pts
[0].y
;
2497 DPtoLP(hdc
, pts
, 5);
2498 Polygon(hdc
, pts
, 5);
2503 pts
[0].x
= x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2504 pts
[0].y
= y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2505 pts
[1].x
= x
+ width
.x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2506 pts
[1].y
= y
+ width
.y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2507 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2508 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2509 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2510 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2511 pts
[4].x
= pts
[0].x
;
2512 pts
[4].y
= pts
[0].y
;
2513 DPtoLP(hdc
, pts
, 5);
2514 Polygon(hdc
, pts
, 5);
2517 SelectObject(hdc
, hpen
);
2518 hbrush
= SelectObject(hdc
, hbrush
);
2519 DeleteObject(hbrush
);
2526 /***********************************************************************
2527 * TextOutA (GDI32.@)
2529 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2531 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2535 /***********************************************************************
2536 * TextOutW (GDI32.@)
2538 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2540 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2544 /***********************************************************************
2545 * PolyTextOutA (GDI32.@)
2549 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2551 for (; cStrings
>0; cStrings
--, pptxt
++)
2552 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2559 /***********************************************************************
2560 * PolyTextOutW (GDI32.@)
2562 * Draw several Strings
2568 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2570 for (; cStrings
>0; cStrings
--, pptxt
++)
2571 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2577 /***********************************************************************
2578 * SetMapperFlags (GDI32.@)
2580 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2582 DC
*dc
= get_dc_ptr( hdc
);
2583 DWORD ret
= GDI_ERROR
;
2587 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2588 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2589 if (flags
!= GDI_ERROR
)
2591 ret
= dc
->mapperFlags
;
2592 dc
->mapperFlags
= flags
;
2594 release_dc_ptr( dc
);
2599 /***********************************************************************
2600 * GetAspectRatioFilterEx (GDI32.@)
2602 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2604 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2609 /***********************************************************************
2610 * GetCharABCWidthsA (GDI32.@)
2612 * See GetCharABCWidthsW.
2614 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2622 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2626 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2629 HeapFree(GetProcessHeap(), 0, str
);
2633 for(i
= 0; i
< wlen
; i
++)
2635 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2643 HeapFree(GetProcessHeap(), 0, str
);
2644 HeapFree(GetProcessHeap(), 0, wstr
);
2650 /******************************************************************************
2651 * GetCharABCWidthsW [GDI32.@]
2653 * Retrieves widths of characters in range.
2656 * hdc [I] Handle of device context
2657 * firstChar [I] First character in range to query
2658 * lastChar [I] Last character in range to query
2659 * abc [O] Address of character-width structure
2662 * Only works with TrueType fonts
2668 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2671 DC
*dc
= get_dc_ptr(hdc
);
2677 if (!dc
) return FALSE
;
2681 release_dc_ptr( dc
);
2685 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2686 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
2687 if (!dev
->funcs
->pGetTextMetrics( dev
, &tm
) || !(tm
.tmPitchAndFamily
& TMPF_VECTOR
))
2689 release_dc_ptr( dc
);
2693 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2694 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2697 /* convert device units to logical */
2698 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2699 abc
->abcA
= width_to_LP(dc
, abc
->abcA
);
2700 abc
->abcB
= width_to_LP(dc
, abc
->abcB
);
2701 abc
->abcC
= width_to_LP(dc
, abc
->abcC
);
2705 release_dc_ptr( dc
);
2710 /******************************************************************************
2711 * GetCharABCWidthsI [GDI32.@]
2713 * Retrieves widths of characters in range.
2716 * hdc [I] Handle of device context
2717 * firstChar [I] First glyphs in range to query
2718 * count [I] Last glyphs in range to query
2719 * pgi [i] Array of glyphs to query
2720 * abc [O] Address of character-width structure
2723 * Only works with TrueType fonts
2729 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2730 LPWORD pgi
, LPABC abc
)
2732 DC
*dc
= get_dc_ptr(hdc
);
2737 if (!dc
) return FALSE
;
2741 release_dc_ptr( dc
);
2745 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2746 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2749 /* convert device units to logical */
2750 for( i
= 0; i
< count
; i
++, abc
++ ) {
2751 abc
->abcA
= width_to_LP(dc
, abc
->abcA
);
2752 abc
->abcB
= width_to_LP(dc
, abc
->abcB
);
2753 abc
->abcC
= width_to_LP(dc
, abc
->abcC
);
2757 release_dc_ptr( dc
);
2762 /***********************************************************************
2763 * GetGlyphOutlineA (GDI32.@)
2765 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2766 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2767 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2769 if (!lpmat2
) return GDI_ERROR
;
2771 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2776 cp
= GdiGetCodePage(hdc
);
2777 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2779 mbchs
[0] = (uChar
& 0xff00) >> 8;
2780 mbchs
[1] = (uChar
& 0xff);
2783 mbchs
[0] = (uChar
& 0xff);
2786 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2789 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2793 /***********************************************************************
2794 * GetGlyphOutlineW (GDI32.@)
2796 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2797 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2798 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2804 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2805 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2807 if (!lpmat2
) return GDI_ERROR
;
2809 dc
= get_dc_ptr(hdc
);
2810 if(!dc
) return GDI_ERROR
;
2812 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2813 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2814 release_dc_ptr( dc
);
2819 /***********************************************************************
2820 * CreateScalableFontResourceA (GDI32.@)
2822 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2823 LPCSTR lpszResourceFile
,
2824 LPCSTR lpszFontFile
,
2825 LPCSTR lpszCurrentPath
)
2827 LPWSTR lpszResourceFileW
= NULL
;
2828 LPWSTR lpszFontFileW
= NULL
;
2829 LPWSTR lpszCurrentPathW
= NULL
;
2833 if (lpszResourceFile
)
2835 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2836 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2837 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2842 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2843 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2844 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2847 if (lpszCurrentPath
)
2849 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2850 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2851 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2854 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2855 lpszFontFileW
, lpszCurrentPathW
);
2857 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2858 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2859 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2864 /***********************************************************************
2865 * CreateScalableFontResourceW (GDI32.@)
2867 BOOL WINAPI
CreateScalableFontResourceW( DWORD hidden
, LPCWSTR resource_file
,
2868 LPCWSTR font_file
, LPCWSTR font_path
)
2870 TRACE("(%d, %s, %s, %s)\n", hidden
, debugstr_w(resource_file
),
2871 debugstr_w(font_file
), debugstr_w(font_path
) );
2873 return WineEngCreateScalableFontResource( hidden
, resource_file
,
2874 font_file
, font_path
);
2877 /*************************************************************************
2878 * GetKerningPairsA (GDI32.@)
2880 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2881 LPKERNINGPAIR kern_pairA
)
2885 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2886 KERNINGPAIR
*kern_pairW
;
2888 if (!cPairs
&& kern_pairA
)
2890 SetLastError(ERROR_INVALID_PARAMETER
);
2894 cp
= GdiGetCodePage(hDC
);
2896 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2897 * to fail on an invalid character for CP_SYMBOL.
2899 cpi
.DefaultChar
[0] = 0;
2900 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2902 FIXME("Can't find codepage %u info\n", cp
);
2906 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2907 if (!total_kern_pairs
) return 0;
2909 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2910 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2912 for (i
= 0; i
< total_kern_pairs
; i
++)
2916 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2919 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2922 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2927 if (kern_pairs_copied
>= cPairs
) break;
2929 kern_pairA
->wFirst
= (BYTE
)first
;
2930 kern_pairA
->wSecond
= (BYTE
)second
;
2931 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2934 kern_pairs_copied
++;
2937 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2939 return kern_pairs_copied
;
2942 /*************************************************************************
2943 * GetKerningPairsW (GDI32.@)
2945 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2946 LPKERNINGPAIR lpKerningPairs
)
2952 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2954 if (!cPairs
&& lpKerningPairs
)
2956 SetLastError(ERROR_INVALID_PARAMETER
);
2960 dc
= get_dc_ptr(hDC
);
2963 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
2964 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
2965 release_dc_ptr( dc
);
2969 /*************************************************************************
2970 * TranslateCharsetInfo [GDI32.@]
2972 * Fills a CHARSETINFO structure for a character set, code page, or
2973 * font. This allows making the correspondence between different labels
2974 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2975 * of the same encoding.
2977 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2978 * only one codepage should be set in *lpSrc.
2981 * TRUE on success, FALSE on failure.
2984 BOOL WINAPI
TranslateCharsetInfo(
2985 LPDWORD lpSrc
, /* [in]
2986 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2987 if flags == TCI_SRCCHARSET: a character set value
2988 if flags == TCI_SRCCODEPAGE: a code page value
2990 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2991 DWORD flags
/* [in] determines interpretation of lpSrc */)
2995 case TCI_SRCFONTSIG
:
2996 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2998 case TCI_SRCCODEPAGE
:
2999 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
3001 case TCI_SRCCHARSET
:
3002 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
3007 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
3008 *lpCs
= FONT_tci
[index
];
3012 /*************************************************************************
3013 * GetFontLanguageInfo (GDI32.@)
3015 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
3017 FONTSIGNATURE fontsig
;
3018 static const DWORD GCP_DBCS_MASK
=FS_JISJAPAN
|FS_CHINESESIMP
|FS_WANSUNG
|FS_CHINESETRAD
|FS_JOHAB
,
3019 GCP_DIACRITIC_MASK
=0x00000000,
3020 FLI_GLYPHS_MASK
=0x00000000,
3021 GCP_GLYPHSHAPE_MASK
=FS_ARABIC
,
3022 GCP_KASHIDA_MASK
=0x00000000,
3023 GCP_LIGATE_MASK
=0x00000000,
3024 GCP_USEKERNING_MASK
=0x00000000,
3025 GCP_REORDER_MASK
=FS_HEBREW
|FS_ARABIC
;
3029 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
3030 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3032 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
3035 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
3036 result
|=GCP_DIACRITIC
;
3038 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
3041 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
3042 result
|=GCP_GLYPHSHAPE
;
3044 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
3045 result
|=GCP_KASHIDA
;
3047 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
3050 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
3051 result
|=GCP_USEKERNING
;
3053 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3054 if( GetTextAlign( hdc
) & TA_RTLREADING
)
3055 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
3056 result
|=GCP_REORDER
;
3062 /*************************************************************************
3063 * GetFontData [GDI32.@]
3065 * Retrieve data for TrueType font.
3069 * success: Number of bytes returned
3070 * failure: GDI_ERROR
3074 * Calls SetLastError()
3077 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
3078 LPVOID buffer
, DWORD length
)
3080 DC
*dc
= get_dc_ptr(hdc
);
3084 if(!dc
) return GDI_ERROR
;
3086 dev
= GET_DC_PHYSDEV( dc
, pGetFontData
);
3087 ret
= dev
->funcs
->pGetFontData( dev
, table
, offset
, buffer
, length
);
3088 release_dc_ptr( dc
);
3092 /*************************************************************************
3093 * GetGlyphIndicesA [GDI32.@]
3095 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
3096 LPWORD pgi
, DWORD flags
)
3102 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3103 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
3105 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
3106 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
3107 HeapFree(GetProcessHeap(), 0, lpstrW
);
3112 /*************************************************************************
3113 * GetGlyphIndicesW [GDI32.@]
3115 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
3116 LPWORD pgi
, DWORD flags
)
3118 DC
*dc
= get_dc_ptr(hdc
);
3122 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3123 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
3125 if(!dc
) return GDI_ERROR
;
3127 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
3128 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
3129 release_dc_ptr( dc
);
3133 /*************************************************************************
3134 * GetCharacterPlacementA [GDI32.@]
3136 * See GetCharacterPlacementW.
3139 * the web browser control of ie4 calls this with dwFlags=0
3142 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
3143 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
3148 GCP_RESULTSW resultsW
;
3152 TRACE("%s, %d, %d, 0x%08x\n",
3153 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3155 /* both structs are equal in size */
3156 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
3158 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
3159 if(lpResults
->lpOutString
)
3160 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
3162 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
3164 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
3165 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
3167 if(lpResults
->lpOutString
) {
3168 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
3169 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
3172 HeapFree(GetProcessHeap(), 0, lpStringW
);
3173 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
3178 /*************************************************************************
3179 * GetCharacterPlacementW [GDI32.@]
3181 * Retrieve information about a string. This includes the width, reordering,
3182 * Glyphing and so on.
3186 * The width and height of the string if successful, 0 if failed.
3190 * All flags except GCP_REORDER are not yet implemented.
3191 * Reordering is not 100% compliant to the Windows BiDi method.
3192 * Caret positioning is not yet implemented for BiDi.
3193 * Classes are not yet implemented.
3197 GetCharacterPlacementW(
3198 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3199 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3200 INT uCount
, /* [in] Number of WORDS in string. */
3201 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3202 GCP_RESULTSW
*lpResults
, /* [in/out] A pointer to a GCP_RESULTSW struct */
3203 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3210 TRACE("%s, %d, %d, 0x%08x\n",
3211 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3213 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3214 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3215 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3216 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3217 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3219 if(dwFlags
&(~GCP_REORDER
))
3220 FIXME("flags 0x%08x ignored\n", dwFlags
);
3221 if(lpResults
->lpClass
)
3222 FIXME("classes not implemented\n");
3223 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3224 FIXME("Caret positions for complex scripts not implemented\n");
3226 nSet
= (UINT
)uCount
;
3227 if(nSet
> lpResults
->nGlyphs
)
3228 nSet
= lpResults
->nGlyphs
;
3230 /* return number of initialized fields */
3231 lpResults
->nGlyphs
= nSet
;
3233 if((dwFlags
&GCP_REORDER
)==0 )
3235 /* Treat the case where no special handling was requested in a fastpath way */
3236 /* copy will do if the GCP_REORDER flag is not set */
3237 if(lpResults
->lpOutString
)
3238 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3240 if(lpResults
->lpOrder
)
3242 for(i
= 0; i
< nSet
; i
++)
3243 lpResults
->lpOrder
[i
] = i
;
3248 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3249 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3252 /* FIXME: Will use the placement chars */
3253 if (lpResults
->lpDx
)
3256 for (i
= 0; i
< nSet
; i
++)
3258 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3259 lpResults
->lpDx
[i
]= c
;
3263 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3267 lpResults
->lpCaretPos
[0] = 0;
3268 for (i
= 1; i
< nSet
; i
++)
3269 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3270 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3273 if(lpResults
->lpGlyphs
)
3274 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3276 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3277 ret
= MAKELONG(size
.cx
, size
.cy
);
3282 /*************************************************************************
3283 * GetCharABCWidthsFloatA [GDI32.@]
3285 * See GetCharABCWidthsFloatW.
3287 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3294 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3298 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3300 for (i
= 0; i
< wlen
; i
++)
3302 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3310 HeapFree( GetProcessHeap(), 0, str
);
3311 HeapFree( GetProcessHeap(), 0, wstr
);
3316 /*************************************************************************
3317 * GetCharABCWidthsFloatW [GDI32.@]
3319 * Retrieves widths of a range of characters.
3322 * hdc [I] Handle to device context.
3323 * first [I] First character in range to query.
3324 * last [I] Last character in range to query.
3325 * abcf [O] Array of LPABCFLOAT structures.
3331 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3337 DC
*dc
= get_dc_ptr( hdc
);
3339 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3341 if (!dc
) return FALSE
;
3343 if (!abcf
) goto done
;
3344 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
3346 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
3347 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
3350 /* convert device units to logical */
3351 FLOAT scale
= fabs( dc
->xformVport2World
.eM11
);
3352 for (i
= first
; i
<= last
; i
++, abcf
++)
3354 abcf
->abcfA
= abc
[i
- first
].abcA
* scale
;
3355 abcf
->abcfB
= abc
[i
- first
].abcB
* scale
;
3356 abcf
->abcfC
= abc
[i
- first
].abcC
* scale
;
3359 HeapFree( GetProcessHeap(), 0, abc
);
3362 release_dc_ptr( dc
);
3366 /*************************************************************************
3367 * GetCharWidthFloatA [GDI32.@]
3369 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3370 UINT iLastChar
, PFLOAT pxBuffer
)
3372 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3376 /*************************************************************************
3377 * GetCharWidthFloatW [GDI32.@]
3379 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3380 UINT iLastChar
, PFLOAT pxBuffer
)
3382 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3387 /***********************************************************************
3389 * Font Resource API *
3391 ***********************************************************************/
3393 /***********************************************************************
3394 * AddFontResourceA (GDI32.@)
3396 INT WINAPI
AddFontResourceA( LPCSTR str
)
3398 return AddFontResourceExA( str
, 0, NULL
);
3401 /***********************************************************************
3402 * AddFontResourceW (GDI32.@)
3404 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3406 return AddFontResourceExW(str
, 0, NULL
);
3410 /***********************************************************************
3411 * AddFontResourceExA (GDI32.@)
3413 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3415 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3416 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3419 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3420 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3421 HeapFree(GetProcessHeap(), 0, strW
);
3425 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3427 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3428 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3429 LPVOID
*pMem
= LockResource(hMem
);
3430 int *num_total
= (int *)lParam
;
3433 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3434 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3436 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3440 *num_total
+= num_in_res
;
3444 static void *map_file( const WCHAR
*filename
, LARGE_INTEGER
*size
)
3446 HANDLE file
, mapping
;
3449 file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3450 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
3452 if (!GetFileSizeEx( file
, size
) || size
->u
.HighPart
)
3454 CloseHandle( file
);
3458 mapping
= CreateFileMappingW( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3459 CloseHandle( file
);
3460 if (!mapping
) return NULL
;
3462 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
3463 CloseHandle( mapping
);
3468 static void *find_resource( BYTE
*ptr
, WORD type
, DWORD rsrc_off
, DWORD size
, DWORD
*len
)
3470 WORD align
, type_id
, count
;
3473 if (size
< rsrc_off
+ 10) return NULL
;
3474 align
= *(WORD
*)(ptr
+ rsrc_off
);
3476 type_id
= *(WORD
*)(ptr
+ rsrc_off
);
3477 while (type_id
&& type_id
!= type
)
3479 count
= *(WORD
*)(ptr
+ rsrc_off
+ 2);
3480 rsrc_off
+= 8 + count
* 12;
3481 if (size
< rsrc_off
+ 8) return NULL
;
3482 type_id
= *(WORD
*)(ptr
+ rsrc_off
);
3484 if (!type_id
) return NULL
;
3485 count
= *(WORD
*)(ptr
+ rsrc_off
+ 2);
3486 if (size
< rsrc_off
+ 8 + count
* 12) return NULL
;
3487 res_off
= *(WORD
*)(ptr
+ rsrc_off
+ 8) << align
;
3488 *len
= *(WORD
*)(ptr
+ rsrc_off
+ 10) << align
;
3489 if (size
< res_off
+ *len
) return NULL
;
3490 return ptr
+ res_off
;
3493 static WCHAR
*get_scalable_filename( const WCHAR
*res
, BOOL
*hidden
)
3496 BYTE
*ptr
= map_file( res
, &size
);
3497 const IMAGE_DOS_HEADER
*dos
;
3498 const IMAGE_OS2_HEADER
*ne
;
3504 if (!ptr
) return NULL
;
3506 if (size
.u
.LowPart
< sizeof( *dos
)) goto fail
;
3507 dos
= (const IMAGE_DOS_HEADER
*)ptr
;
3508 if (dos
->e_magic
!= IMAGE_DOS_SIGNATURE
) goto fail
;
3509 if (size
.u
.LowPart
< dos
->e_lfanew
+ sizeof( *ne
)) goto fail
;
3510 ne
= (const IMAGE_OS2_HEADER
*)(ptr
+ dos
->e_lfanew
);
3512 fontdir
= find_resource( ptr
, 0x8007, dos
->e_lfanew
+ ne
->ne_rsrctab
, size
.u
.LowPart
, &len
);
3513 if (!fontdir
) goto fail
;
3514 *hidden
= (fontdir
[35] & 0x80) != 0; /* fontdir->dfType */
3516 data
= find_resource( ptr
, 0x80cc, dos
->e_lfanew
+ ne
->ne_rsrctab
, size
.u
.LowPart
, &len
);
3517 if (!data
) goto fail
;
3518 if (!memchr( data
, 0, len
)) goto fail
;
3520 len
= MultiByteToWideChar( CP_ACP
, 0, data
, -1, NULL
, 0 );
3521 name
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
3522 if (name
) MultiByteToWideChar( CP_ACP
, 0, data
, -1, name
, len
);
3525 UnmapViewOfFile( ptr
);
3529 /***********************************************************************
3530 * AddFontResourceExW (GDI32.@)
3532 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3534 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3540 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3541 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3542 if (hModule
!= NULL
)
3544 int num_resources
= 0;
3545 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3547 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3548 wine_dbgstr_w(str
));
3549 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3550 ret
= num_resources
;
3551 FreeLibrary(hModule
);
3553 else if ((filename
= get_scalable_filename( str
, &hidden
)) != NULL
)
3555 if (hidden
) fl
|= FR_PRIVATE
| FR_NOT_ENUM
;
3556 ret
= WineEngAddFontResourceEx( filename
, fl
, pdv
);
3557 HeapFree( GetProcessHeap(), 0, filename
);
3563 /***********************************************************************
3564 * RemoveFontResourceA (GDI32.@)
3566 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3568 return RemoveFontResourceExA(str
, 0, 0);
3571 /***********************************************************************
3572 * RemoveFontResourceW (GDI32.@)
3574 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3576 return RemoveFontResourceExW(str
, 0, 0);
3579 /***********************************************************************
3580 * AddFontMemResourceEx (GDI32.@)
3582 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3587 if (!pbFont
|| !cbFont
|| !pcFonts
)
3589 SetLastError(ERROR_INVALID_PARAMETER
);
3593 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3598 *pcFonts
= num_fonts
;
3602 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3603 RemoveFontMemResourceEx(ret
);
3611 /***********************************************************************
3612 * RemoveFontMemResourceEx (GDI32.@)
3614 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3616 FIXME("(%p) stub\n", fh
);
3620 /***********************************************************************
3621 * RemoveFontResourceExA (GDI32.@)
3623 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3625 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3626 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3629 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3630 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3631 HeapFree(GetProcessHeap(), 0, strW
);
3635 /***********************************************************************
3636 * RemoveFontResourceExW (GDI32.@)
3638 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3640 int ret
= WineEngRemoveFontResourceEx( str
, fl
, pdv
);
3646 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3647 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3648 if (hModule
!= NULL
)
3650 WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str
));
3651 FreeLibrary(hModule
);
3653 else if ((filename
= get_scalable_filename( str
, &hidden
)) != NULL
)
3655 if (hidden
) fl
|= FR_PRIVATE
| FR_NOT_ENUM
;
3656 ret
= WineEngRemoveFontResourceEx( filename
, fl
, pdv
);
3657 HeapFree( GetProcessHeap(), 0, filename
);
3663 /***********************************************************************
3664 * GetFontResourceInfoW (GDI32.@)
3666 BOOL WINAPI
GetFontResourceInfoW( LPCWSTR str
, LPDWORD size
, PVOID buffer
, DWORD type
)
3668 FIXME("%s %p(%d) %p %d\n", debugstr_w(str
), size
, size
? *size
: 0, buffer
, type
);
3672 /***********************************************************************
3673 * GetTextCharset (GDI32.@)
3675 UINT WINAPI
GetTextCharset(HDC hdc
)
3677 /* MSDN docs say this is equivalent */
3678 return GetTextCharsetInfo(hdc
, NULL
, 0);
3681 /***********************************************************************
3682 * GetTextCharsetInfo (GDI32.@)
3684 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3686 UINT ret
= DEFAULT_CHARSET
;
3687 DC
*dc
= get_dc_ptr(hdc
);
3692 dev
= GET_DC_PHYSDEV( dc
, pGetTextCharsetInfo
);
3693 ret
= dev
->funcs
->pGetTextCharsetInfo( dev
, fs
, flags
);
3694 release_dc_ptr( dc
);
3697 if (ret
== DEFAULT_CHARSET
&& fs
)
3698 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3702 /***********************************************************************
3703 * GdiGetCharDimensions (GDI32.@)
3705 * Gets the average width of the characters in the English alphabet.
3708 * hdc [I] Handle to the device context to measure on.
3709 * lptm [O] Pointer to memory to store the text metrics into.
3710 * height [O] On exit, the maximum height of characters in the English alphabet.
3713 * The average width of characters in the English alphabet.
3716 * This function is used by the dialog manager to get the size of a dialog
3717 * unit. It should also be used by other pieces of code that need to know
3718 * the size of a dialog unit in logical units without having access to the
3719 * window handle of the dialog.
3720 * Windows caches the font metrics from this function, but we don't and
3721 * there doesn't appear to be an immediate advantage to do so.
3724 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3726 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3729 static const WCHAR alphabet
[] = {
3730 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3731 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3732 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3734 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3736 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3738 if (height
) *height
= sz
.cy
;
3739 return (sz
.cx
/ 26 + 1) / 2;
3742 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3744 FIXME("(%d): stub\n", fEnableEUDC
);
3748 /***********************************************************************
3749 * GetCharWidthI (GDI32.@)
3751 * Retrieve widths of characters.
3754 * hdc [I] Handle to a device context.
3755 * first [I] First glyph in range to query.
3756 * count [I] Number of glyph indices to query.
3757 * glyphs [I] Array of glyphs to query.
3758 * buffer [O] Buffer to receive character widths.
3761 * Only works with TrueType fonts.
3767 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3772 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3774 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3777 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3779 HeapFree(GetProcessHeap(), 0, abc
);
3783 for (i
= 0; i
< count
; i
++)
3784 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3786 HeapFree(GetProcessHeap(), 0, abc
);
3790 /***********************************************************************
3791 * GetFontUnicodeRanges (GDI32.@)
3793 * Retrieve a list of supported Unicode characters in a font.
3796 * hdc [I] Handle to a device context.
3797 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3800 * Success: Number of bytes written to the buffer pointed to by lpgs.
3804 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3808 DC
*dc
= get_dc_ptr(hdc
);
3810 TRACE("(%p, %p)\n", hdc
, lpgs
);
3814 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3815 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3821 /*************************************************************
3822 * FontIsLinked (GDI32.@)
3824 BOOL WINAPI
FontIsLinked(HDC hdc
)
3826 DC
*dc
= get_dc_ptr(hdc
);
3830 if (!dc
) return FALSE
;
3831 dev
= GET_DC_PHYSDEV( dc
, pFontIsLinked
);
3832 ret
= dev
->funcs
->pFontIsLinked( dev
);
3834 TRACE("returning %d\n", ret
);
3838 /*************************************************************
3839 * GdiRealizationInfo (GDI32.@)
3841 * Returns a structure that contains some font information.
3843 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3845 DC
*dc
= get_dc_ptr(hdc
);
3849 if (!dc
) return FALSE
;
3850 dev
= GET_DC_PHYSDEV( dc
, pGdiRealizationInfo
);
3851 ret
= dev
->funcs
->pGdiRealizationInfo( dev
, info
);