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_XWSTODS(DC
*dc
, INT width
)
87 pt
[0].x
= pt
[0].y
= 0;
90 LPtoDP(dc
->hSelf
, pt
, 2);
91 return pt
[1].x
- pt
[0].x
;
94 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
97 pt
[0].x
= pt
[0].y
= 0;
100 LPtoDP(dc
->hSelf
, pt
, 2);
101 return pt
[1].y
- pt
[0].y
;
104 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
105 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
106 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
107 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
109 static const struct gdi_obj_funcs font_funcs
=
111 FONT_SelectObject
, /* pSelectObject */
112 FONT_GetObjectA
, /* pGetObjectA */
113 FONT_GetObjectW
, /* pGetObjectW */
114 NULL
, /* pUnrealizeObject */
115 FONT_DeleteObject
/* pDeleteObject */
125 LPLOGFONTW lpLogFontParam
;
126 FONTENUMPROCW lpEnumFunc
;
134 * For TranslateCharsetInfo
136 #define MAXTCIINDEX 32
137 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
139 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
140 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
141 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
142 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
143 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
144 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
145 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
146 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
147 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
148 /* reserved by ANSI */
149 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
150 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
151 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
152 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
153 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
154 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
155 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
157 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
158 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
159 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
160 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
161 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
162 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
163 /* reserved for alternate ANSI and OEM */
164 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
165 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
166 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
167 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
168 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
169 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
170 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
171 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
172 /* reserved for system */
173 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
174 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
177 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
179 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
180 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
182 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
185 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
187 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
188 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
189 LF_FACESIZE
, NULL
, NULL
);
190 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
193 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
195 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
197 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
198 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
199 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
200 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
201 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
202 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
203 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
204 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
205 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
208 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
210 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
212 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
213 fontW
->elfFullName
, LF_FULLFACESIZE
);
214 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
215 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
216 fontW
->elfStyle
, LF_FACESIZE
);
217 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
218 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
219 fontW
->elfScript
, LF_FACESIZE
);
220 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
223 /***********************************************************************
224 * TEXTMETRIC conversion functions.
226 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
228 ptmA
->tmHeight
= ptmW
->tmHeight
;
229 ptmA
->tmAscent
= ptmW
->tmAscent
;
230 ptmA
->tmDescent
= ptmW
->tmDescent
;
231 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
232 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
233 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
234 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
235 ptmA
->tmWeight
= ptmW
->tmWeight
;
236 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
237 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
238 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
239 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
240 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
242 ptmA
->tmFirstChar
= 0x1e;
243 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
245 else if (ptmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
247 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
248 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
252 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 0xff);
253 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
255 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
256 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
257 ptmA
->tmItalic
= ptmW
->tmItalic
;
258 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
259 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
260 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
261 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
265 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
267 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
268 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
269 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
270 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
271 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
272 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
275 static DWORD
get_key_value( HKEY key
, const WCHAR
*name
, DWORD
*value
)
278 DWORD count
= sizeof(buf
), type
, err
;
280 err
= RegQueryValueExW( key
, name
, NULL
, &type
, (BYTE
*)buf
, &count
);
283 if (type
== REG_DWORD
) memcpy( value
, buf
, sizeof(*value
) );
284 else *value
= atoiW( buf
);
289 static UINT
get_subpixel_orientation( HKEY key
)
291 static const WCHAR smoothing_orientation
[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',
292 'O','r','i','e','n','t','a','t','i','o','n',0};
295 /* FIXME: handle vertical orientations even though Windows doesn't */
296 if (get_key_value( key
, smoothing_orientation
, &orient
)) return GGO_GRAY4_BITMAP
;
300 case 0: /* FE_FONTSMOOTHINGORIENTATIONBGR */
301 return WINE_GGO_HBGR_BITMAP
;
302 case 1: /* FE_FONTSMOOTHINGORIENTATIONRGB */
303 return WINE_GGO_HRGB_BITMAP
;
305 return GGO_GRAY4_BITMAP
;
308 static UINT
get_default_smoothing( HKEY key
)
310 static const WCHAR smoothing
[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g',0};
311 static const WCHAR smoothing_type
[] = {'F','o','n','t','S','m','o','o','t','h','i','n','g','T','y','p','e',0};
314 if (get_key_value( key
, smoothing
, &enabled
)) return 0;
315 if (!enabled
) return GGO_BITMAP
;
317 if (!get_key_value( key
, smoothing_type
, &type
) && type
== 2 /* FE_FONTSMOOTHINGCLEARTYPE */)
318 return get_subpixel_orientation( key
);
320 return GGO_GRAY4_BITMAP
;
323 /* compute positions for text rendering, in device coords */
324 static BOOL
get_char_positions( DC
*dc
, const WCHAR
*str
, INT count
, INT
*dx
, SIZE
*size
)
329 size
->cx
= size
->cy
= 0;
330 if (!count
) return TRUE
;
332 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
333 dev
->funcs
->pGetTextMetrics( dev
, &tm
);
335 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
336 if (!dev
->funcs
->pGetTextExtentExPoint( dev
, str
, count
, dx
)) return FALSE
;
338 if (dc
->breakExtra
|| dc
->breakRem
)
340 int i
, space
= 0, rem
= dc
->breakRem
;
342 for (i
= 0; i
< count
; i
++)
344 if (str
[i
] == tm
.tmBreakChar
)
346 space
+= dc
->breakExtra
;
356 size
->cx
= dx
[count
- 1];
357 size
->cy
= tm
.tmHeight
;
361 /* compute positions for text rendering, in device coords */
362 static BOOL
get_char_positions_indices( DC
*dc
, const WORD
*indices
, INT count
, INT
*dx
, SIZE
*size
)
367 size
->cx
= size
->cy
= 0;
368 if (!count
) return TRUE
;
370 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
371 dev
->funcs
->pGetTextMetrics( dev
, &tm
);
373 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPointI
);
374 if (!dev
->funcs
->pGetTextExtentExPointI( dev
, indices
, count
, dx
)) return FALSE
;
376 if (dc
->breakExtra
|| dc
->breakRem
)
379 int i
, space
= 0, rem
= dc
->breakRem
;
381 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
382 dev
->funcs
->pGetGlyphIndices( dev
, &tm
.tmBreakChar
, 1, &space_index
, 0 );
384 for (i
= 0; i
< count
; i
++)
386 if (indices
[i
] == space_index
)
388 space
+= dc
->breakExtra
;
398 size
->cx
= dx
[count
- 1];
399 size
->cy
= tm
.tmHeight
;
403 /***********************************************************************
404 * GdiGetCodePage (GDI32.@)
406 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
409 DC
*dc
= get_dc_ptr( hdc
);
413 cp
= dc
->font_code_page
;
414 release_dc_ptr( dc
);
419 /***********************************************************************
422 * Returns a Unicode translation of str using the charset of the
423 * currently selected font in hdc. If count is -1 then str is assumed
424 * to be '\0' terminated, otherwise it contains the number of bytes to
425 * convert. If plenW is non-NULL, on return it will point to the
426 * number of WCHARs that have been written. If pCP is non-NULL, on
427 * return it will point to the codepage used in the conversion. The
428 * caller should free the returned LPWSTR from the process heap
431 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
437 cp
= GdiGetCodePage( hdc
);
439 if(count
== -1) count
= strlen(str
);
440 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
441 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
442 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
443 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
444 if(plenW
) *plenW
= lenW
;
449 /***********************************************************************
450 * CreateFontIndirectExA (GDI32.@)
452 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
454 ENUMLOGFONTEXDVW enumexW
;
456 if (!penumexA
) return 0;
458 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
459 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
460 return CreateFontIndirectExW( &enumexW
);
463 /***********************************************************************
464 * CreateFontIndirectExW (GDI32.@)
466 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
472 if (!penumex
) return 0;
474 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
475 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
476 penumex
->elfEnumLogfontEx
.elfScript
[0])
478 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
479 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
480 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
481 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
484 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
485 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
487 fontPtr
->logfont
= *plf
;
489 if (!(hFont
= alloc_gdi_handle( fontPtr
, OBJ_FONT
, &font_funcs
)))
491 HeapFree( GetProcessHeap(), 0, fontPtr
);
495 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
496 plf
->lfHeight
, plf
->lfWidth
,
497 plf
->lfEscapement
, plf
->lfOrientation
,
498 plf
->lfPitchAndFamily
,
499 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
500 plf
->lfQuality
, plf
->lfCharSet
,
501 debugstr_w(plf
->lfFaceName
),
502 plf
->lfWeight
> 400 ? "Bold" : "",
503 plf
->lfItalic
? "Italic" : "",
504 plf
->lfUnderline
? "Underline" : "", hFont
);
509 /***********************************************************************
510 * CreateFontIndirectA (GDI32.@)
512 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
518 FONT_LogFontAToW( plfA
, &lfW
);
519 return CreateFontIndirectW( &lfW
);
522 /***********************************************************************
523 * CreateFontIndirectW (GDI32.@)
525 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
527 ENUMLOGFONTEXDVW exdv
;
531 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
532 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
533 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
534 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
535 return CreateFontIndirectExW( &exdv
);
538 /*************************************************************************
539 * CreateFontA (GDI32.@)
541 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
542 INT orient
, INT weight
, DWORD italic
,
543 DWORD underline
, DWORD strikeout
, DWORD charset
,
544 DWORD outpres
, DWORD clippres
, DWORD quality
,
545 DWORD pitch
, LPCSTR name
)
549 logfont
.lfHeight
= height
;
550 logfont
.lfWidth
= width
;
551 logfont
.lfEscapement
= esc
;
552 logfont
.lfOrientation
= orient
;
553 logfont
.lfWeight
= weight
;
554 logfont
.lfItalic
= italic
;
555 logfont
.lfUnderline
= underline
;
556 logfont
.lfStrikeOut
= strikeout
;
557 logfont
.lfCharSet
= charset
;
558 logfont
.lfOutPrecision
= outpres
;
559 logfont
.lfClipPrecision
= clippres
;
560 logfont
.lfQuality
= quality
;
561 logfont
.lfPitchAndFamily
= pitch
;
564 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
566 logfont
.lfFaceName
[0] = '\0';
568 return CreateFontIndirectA( &logfont
);
571 /*************************************************************************
572 * CreateFontW (GDI32.@)
574 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
575 INT orient
, INT weight
, DWORD italic
,
576 DWORD underline
, DWORD strikeout
, DWORD charset
,
577 DWORD outpres
, DWORD clippres
, DWORD quality
,
578 DWORD pitch
, LPCWSTR name
)
582 logfont
.lfHeight
= height
;
583 logfont
.lfWidth
= width
;
584 logfont
.lfEscapement
= esc
;
585 logfont
.lfOrientation
= orient
;
586 logfont
.lfWeight
= weight
;
587 logfont
.lfItalic
= italic
;
588 logfont
.lfUnderline
= underline
;
589 logfont
.lfStrikeOut
= strikeout
;
590 logfont
.lfCharSet
= charset
;
591 logfont
.lfOutPrecision
= outpres
;
592 logfont
.lfClipPrecision
= clippres
;
593 logfont
.lfQuality
= quality
;
594 logfont
.lfPitchAndFamily
= pitch
;
597 lstrcpynW(logfont
.lfFaceName
, name
,
598 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
600 logfont
.lfFaceName
[0] = '\0';
602 return CreateFontIndirectW( &logfont
);
605 #define ASSOC_CHARSET_OEM 1
606 #define ASSOC_CHARSET_ANSI 2
607 #define ASSOC_CHARSET_SYMBOL 4
609 static DWORD
get_associated_charset_info(void)
611 static DWORD associated_charset
= -1;
613 if (associated_charset
== -1)
615 static const WCHAR assoc_charset_reg_keyW
[] = {'S','y','s','t','e','m','\\',
616 'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
617 'C','o','n','t','r','o','l','\\','F','o','n','t','A','s','s','o','c','\\',
618 'A','s','s','o','c','i','a','t','e','d',' ','C','h','a','r','s','e','t','\0'};
619 static const WCHAR ansiW
[] = {'A','N','S','I','(','0','0',')','\0'};
620 static const WCHAR oemW
[] = {'O','E','M','(','F','F',')','\0'};
621 static const WCHAR symbolW
[] = {'S','Y','M','B','O','L','(','0','2',')','\0'};
622 static const WCHAR yesW
[] = {'Y','E','S','\0'};
625 DWORD type
, data_len
;
627 associated_charset
= 0;
629 if (RegOpenKeyW(HKEY_LOCAL_MACHINE
,
630 assoc_charset_reg_keyW
, &hkey
) != ERROR_SUCCESS
)
633 data_len
= sizeof(dataW
);
634 if (!RegQueryValueExW(hkey
, ansiW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
635 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
636 associated_charset
|= ASSOC_CHARSET_ANSI
;
638 data_len
= sizeof(dataW
);
639 if (!RegQueryValueExW(hkey
, oemW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
640 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
641 associated_charset
|= ASSOC_CHARSET_OEM
;
643 data_len
= sizeof(dataW
);
644 if (!RegQueryValueExW(hkey
, symbolW
, NULL
, &type
, (LPBYTE
)dataW
, &data_len
) &&
645 type
== REG_SZ
&& !strcmpiW(dataW
, yesW
))
646 associated_charset
|= ASSOC_CHARSET_SYMBOL
;
650 TRACE("associated_charset = %d\n", associated_charset
);
653 return associated_charset
;
656 static void update_font_code_page( DC
*dc
)
659 int charset
= GetTextCharsetInfo( dc
->hSelf
, NULL
, 0 );
661 if (charset
== ANSI_CHARSET
&&
662 get_associated_charset_info() & ASSOC_CHARSET_ANSI
)
663 charset
= DEFAULT_CHARSET
;
665 /* Hmm, nicely designed api this one! */
666 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
667 dc
->font_code_page
= csi
.ciACP
;
671 dc
->font_code_page
= GetOEMCP();
673 case DEFAULT_CHARSET
:
674 dc
->font_code_page
= GetACP();
684 /* FIXME: These have no place here, but because x11drv
685 enumerates fonts with these (made up) charsets some apps
686 might use them and then the FIXME below would become
687 annoying. Now we could pick the intended codepage for
688 each of these, but since it's broken anyway we'll just
689 use CP_ACP and hope it'll go away...
691 dc
->font_code_page
= CP_ACP
;
695 FIXME("Can't find codepage for charset %d\n", charset
);
696 dc
->font_code_page
= CP_ACP
;
701 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
704 /***********************************************************************
707 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
710 DC
*dc
= get_dc_ptr( hdc
);
716 if (!GDI_inc_ref_count( handle
))
718 release_dc_ptr( dc
);
722 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
723 if (physdev
->funcs
->pSelectFont( physdev
, handle
, &aa_flags
))
727 dc
->aa_flags
= aa_flags
? aa_flags
: GGO_BITMAP
;
728 update_font_code_page( dc
);
729 GDI_dec_ref_count( ret
);
731 else GDI_dec_ref_count( handle
);
733 release_dc_ptr( dc
);
738 /***********************************************************************
741 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
743 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
749 FONT_LogFontWToA( &font
->logfont
, &lfA
);
750 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
751 memcpy( buffer
, &lfA
, count
);
753 else count
= sizeof(lfA
);
754 GDI_ReleaseObj( handle
);
758 /***********************************************************************
761 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
763 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
768 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
769 memcpy( buffer
, &font
->logfont
, count
);
771 else count
= sizeof(LOGFONTW
);
772 GDI_ReleaseObj( handle
);
777 /***********************************************************************
780 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
784 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
785 return HeapFree( GetProcessHeap(), 0, obj
);
789 /***********************************************************************
792 HFONT
nulldrv_SelectFont( PHYSDEV dev
, HFONT font
, UINT
*aa_flags
)
794 static const WCHAR desktopW
[] = { 'C','o','n','t','r','o','l',' ','P','a','n','e','l','\\',
795 'D','e','s','k','t','o','p',0 };
796 static int orientation
= -1, smoothing
= -1;
800 if (*aa_flags
) return 0;
802 GetObjectW( font
, sizeof(lf
), &lf
);
803 switch (lf
.lfQuality
)
805 case NONANTIALIASED_QUALITY
:
806 *aa_flags
= GGO_BITMAP
;
808 case ANTIALIASED_QUALITY
:
809 *aa_flags
= GGO_GRAY4_BITMAP
;
811 case CLEARTYPE_QUALITY
:
812 case CLEARTYPE_NATURAL_QUALITY
:
813 if (orientation
== -1)
815 if (RegOpenKeyW( HKEY_CURRENT_USER
, desktopW
, &key
)) break;
816 orientation
= get_subpixel_orientation( key
);
819 *aa_flags
= orientation
;
824 if (RegOpenKeyW( HKEY_CURRENT_USER
, desktopW
, &key
)) break;
825 smoothing
= get_default_smoothing( key
);
828 *aa_flags
= smoothing
;
835 /***********************************************************************
838 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
839 * We have to use other types because of the FONTENUMPROCW definition.
841 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
842 DWORD fType
, LPARAM lp
)
844 struct font_enum
*pfe
= (struct font_enum
*)lp
;
847 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
848 if ((!pfe
->lpLogFontParam
||
849 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
850 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
851 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
853 /* convert font metrics */
854 ENUMLOGFONTEXA logfont
;
855 NEWTEXTMETRICEXA tmA
;
859 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
860 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
861 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
862 ptm
= (TEXTMETRICW
*)&tmA
;
864 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
870 /***********************************************************************
871 * FONT_EnumFontFamiliesEx
873 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
874 LPARAM lParam
, BOOL unicode
)
877 DC
*dc
= get_dc_ptr( hDC
);
882 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
884 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
885 fe
.lpLogFontParam
= plf
;
886 fe
.lpEnumFunc
= efproc
;
888 fe
.unicode
= unicode
;
891 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
892 release_dc_ptr( dc
);
894 return ret
? fe
.retval
: 0;
897 /***********************************************************************
898 * EnumFontFamiliesExW (GDI32.@)
900 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
901 FONTENUMPROCW efproc
,
902 LPARAM lParam
, DWORD dwFlags
)
904 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
907 /***********************************************************************
908 * EnumFontFamiliesExA (GDI32.@)
910 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
911 FONTENUMPROCA efproc
,
912 LPARAM lParam
, DWORD dwFlags
)
918 FONT_LogFontAToW( plf
, &lfW
);
923 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
926 /***********************************************************************
927 * EnumFontFamiliesA (GDI32.@)
929 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
930 FONTENUMPROCA efproc
, LPARAM lpData
)
936 if (!*lpFamily
) return 1;
937 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
938 lf
.lfCharSet
= DEFAULT_CHARSET
;
939 lf
.lfPitchAndFamily
= 0;
944 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
947 /***********************************************************************
948 * EnumFontFamiliesW (GDI32.@)
950 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
951 FONTENUMPROCW efproc
, LPARAM lpData
)
957 if (!*lpFamily
) return 1;
958 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
959 lf
.lfCharSet
= DEFAULT_CHARSET
;
960 lf
.lfPitchAndFamily
= 0;
965 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
968 /***********************************************************************
969 * EnumFontsA (GDI32.@)
971 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
974 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
977 /***********************************************************************
978 * EnumFontsW (GDI32.@)
980 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
983 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
987 /***********************************************************************
988 * GetTextCharacterExtra (GDI32.@)
990 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
993 DC
*dc
= get_dc_ptr( hdc
);
994 if (!dc
) return 0x80000000;
996 release_dc_ptr( dc
);
1001 /***********************************************************************
1002 * SetTextCharacterExtra (GDI32.@)
1004 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
1006 INT ret
= 0x80000000;
1007 DC
* dc
= get_dc_ptr( hdc
);
1011 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
1012 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
1013 if (extra
!= 0x80000000)
1015 ret
= dc
->charExtra
;
1016 dc
->charExtra
= extra
;
1018 release_dc_ptr( dc
);
1024 /***********************************************************************
1025 * SetTextJustification (GDI32.@)
1027 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
1031 DC
* dc
= get_dc_ptr( hdc
);
1033 if (!dc
) return FALSE
;
1035 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
1036 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
1039 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
1040 if (!extra
) breaks
= 0;
1043 dc
->breakExtra
= extra
/ breaks
;
1044 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
1052 release_dc_ptr( dc
);
1057 /***********************************************************************
1058 * GetTextFaceA (GDI32.@)
1060 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
1062 INT res
= GetTextFaceW(hdc
, 0, NULL
);
1063 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
1064 GetTextFaceW( hdc
, res
, nameW
);
1070 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
1074 /* GetTextFaceA does NOT include the nul byte in the return count. */
1081 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
1082 HeapFree( GetProcessHeap(), 0, nameW
);
1086 /***********************************************************************
1087 * GetTextFaceW (GDI32.@)
1089 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
1094 DC
* dc
= get_dc_ptr( hdc
);
1097 dev
= GET_DC_PHYSDEV( dc
, pGetTextFace
);
1098 ret
= dev
->funcs
->pGetTextFace( dev
, count
, name
);
1099 release_dc_ptr( dc
);
1104 /***********************************************************************
1105 * GetTextExtentPoint32A (GDI32.@)
1107 * See GetTextExtentPoint32W.
1109 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
1116 if (count
< 0) return FALSE
;
1118 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1122 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
1123 HeapFree( GetProcessHeap(), 0, p
);
1126 TRACE("(%p %s %d %p): returning %d x %d\n",
1127 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
1132 /***********************************************************************
1133 * GetTextExtentPoint32W [GDI32.@]
1135 * Computes width/height for a string.
1137 * Computes width and height of the specified string.
1143 BOOL WINAPI
GetTextExtentPoint32W(
1144 HDC hdc
, /* [in] Handle of device context */
1145 LPCWSTR str
, /* [in] Address of text string */
1146 INT count
, /* [in] Number of characters in string */
1147 LPSIZE size
) /* [out] Address of structure for string size */
1149 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1152 /***********************************************************************
1153 * GetTextExtentExPointI [GDI32.@]
1155 * Computes width and height of the array of glyph indices.
1158 * hdc [I] Handle of device context.
1159 * indices [I] Glyph index array.
1160 * count [I] Number of glyphs in array.
1161 * max_ext [I] Maximum width in glyphs.
1162 * nfit [O] Maximum number of characters.
1163 * dxs [O] Partial string widths.
1164 * size [O] Returned string size.
1170 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1171 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1176 INT buffer
[256], *pos
= dxs
;
1178 if (count
< 0) return FALSE
;
1180 dc
= get_dc_ptr( hdc
);
1181 if (!dc
) return FALSE
;
1186 if (count
> 256 && !(pos
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pos
) )))
1188 release_dc_ptr( dc
);
1193 ret
= get_char_positions_indices( dc
, indices
, count
, pos
, size
);
1198 for (i
= 0; i
< count
; i
++)
1200 unsigned int dx
= abs( INTERNAL_XDSTOWS( dc
, pos
[i
] )) + (i
+ 1) * dc
->charExtra
;
1201 if (nfit
&& dx
> (unsigned int)max_ext
) break;
1202 if (dxs
) dxs
[i
] = dx
;
1204 if (nfit
) *nfit
= i
;
1207 size
->cx
= abs( INTERNAL_XDSTOWS( dc
, size
->cx
)) + count
* dc
->charExtra
;
1208 size
->cy
= abs( INTERNAL_YDSTOWS( dc
, size
->cy
));
1211 if (pos
!= buffer
&& pos
!= dxs
) HeapFree( GetProcessHeap(), 0, pos
);
1212 release_dc_ptr( dc
);
1214 TRACE("(%p %p %d %p): returning %d x %d\n",
1215 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1219 /***********************************************************************
1220 * GetTextExtentPointI [GDI32.@]
1222 * Computes width and height of the array of glyph indices.
1225 * hdc [I] Handle of device context.
1226 * indices [I] Glyph index array.
1227 * count [I] Number of glyphs in array.
1228 * size [O] Returned string size.
1234 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1236 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1240 /***********************************************************************
1241 * GetTextExtentPointA (GDI32.@)
1243 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1246 TRACE("not bug compatible.\n");
1247 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1250 /***********************************************************************
1251 * GetTextExtentPointW (GDI32.@)
1253 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1256 TRACE("not bug compatible.\n");
1257 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1261 /***********************************************************************
1262 * GetTextExtentExPointA (GDI32.@)
1264 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1265 INT maxExt
, LPINT lpnFit
,
1266 LPINT alpDx
, LPSIZE size
)
1273 if (count
< 0) return FALSE
;
1274 if (maxExt
< -1) return FALSE
;
1278 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1279 if (!walpDx
) return FALSE
;
1282 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1283 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1286 INT n
= lpnFit
? *lpnFit
: wlen
;
1288 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1290 alpDx
[j
] = walpDx
[i
];
1291 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1294 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1295 HeapFree( GetProcessHeap(), 0, p
);
1296 HeapFree( GetProcessHeap(), 0, walpDx
);
1301 /***********************************************************************
1302 * GetTextExtentExPointW (GDI32.@)
1304 * Return the size of the string as it would be if it was output properly by
1307 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
, INT max_ext
,
1308 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1313 INT buffer
[256], *pos
= dxs
;
1315 if (count
< 0) return FALSE
;
1317 dc
= get_dc_ptr(hdc
);
1318 if (!dc
) return FALSE
;
1323 if (count
> 256 && !(pos
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*pos
) )))
1325 release_dc_ptr( dc
);
1330 ret
= get_char_positions( dc
, str
, count
, pos
, size
);
1335 for (i
= 0; i
< count
; i
++)
1337 unsigned int dx
= abs( INTERNAL_XDSTOWS( dc
, pos
[i
] )) + (i
+ 1) * dc
->charExtra
;
1338 if (nfit
&& dx
> (unsigned int)max_ext
) break;
1339 if (dxs
) dxs
[i
] = dx
;
1341 if (nfit
) *nfit
= i
;
1344 size
->cx
= abs( INTERNAL_XDSTOWS( dc
, size
->cx
)) + count
* dc
->charExtra
;
1345 size
->cy
= abs( INTERNAL_YDSTOWS( dc
, size
->cy
));
1348 if (pos
!= buffer
&& pos
!= dxs
) HeapFree( GetProcessHeap(), 0, pos
);
1349 release_dc_ptr( dc
);
1351 TRACE("(%p, %s, %d) returning %dx%d\n", hdc
, debugstr_wn(str
,count
), max_ext
, size
->cx
, size
->cy
);
1355 /***********************************************************************
1356 * GetTextMetricsA (GDI32.@)
1358 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1362 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1363 FONT_TextMetricWToA( &tm32
, metrics
);
1367 /***********************************************************************
1368 * GetTextMetricsW (GDI32.@)
1370 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1374 DC
* dc
= get_dc_ptr( hdc
);
1375 if (!dc
) return FALSE
;
1377 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1378 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1382 /* device layer returns values in device units
1383 * therefore we have to convert them to logical */
1385 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1386 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1387 metrics
->tmHeight
= height_to_LP( dc
, metrics
->tmHeight
);
1388 metrics
->tmAscent
= height_to_LP( dc
, metrics
->tmAscent
);
1389 metrics
->tmDescent
= height_to_LP( dc
, metrics
->tmDescent
);
1390 metrics
->tmInternalLeading
= height_to_LP( dc
, metrics
->tmInternalLeading
);
1391 metrics
->tmExternalLeading
= height_to_LP( dc
, metrics
->tmExternalLeading
);
1392 metrics
->tmAveCharWidth
= width_to_LP( dc
, metrics
->tmAveCharWidth
);
1393 metrics
->tmMaxCharWidth
= width_to_LP( dc
, metrics
->tmMaxCharWidth
);
1394 metrics
->tmOverhang
= width_to_LP( dc
, metrics
->tmOverhang
);
1397 TRACE("text metrics:\n"
1398 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1399 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1400 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1401 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1402 " PitchAndFamily = %02x\n"
1403 " --------------------\n"
1404 " InternalLeading = %i\n"
1408 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1409 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1410 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1411 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1412 metrics
->tmPitchAndFamily
,
1413 metrics
->tmInternalLeading
,
1416 metrics
->tmHeight
);
1418 release_dc_ptr( dc
);
1423 /***********************************************************************
1424 * GetOutlineTextMetricsA (GDI32.@)
1425 * Gets metrics for TrueType fonts.
1428 * If the supplied buffer isn't big enough Windows partially fills it up to
1429 * its given length and returns that length.
1432 * Success: Non-zero or size of required buffer
1435 UINT WINAPI
GetOutlineTextMetricsA(
1436 HDC hdc
, /* [in] Handle of device context */
1437 UINT cbData
, /* [in] Size of metric data array */
1438 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1440 char buf
[512], *ptr
;
1442 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1443 OUTLINETEXTMETRICA
*output
= lpOTM
;
1446 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1448 if(ret
> sizeof(buf
))
1449 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1450 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1452 needed
= sizeof(OUTLINETEXTMETRICA
);
1453 if(lpOTMW
->otmpFamilyName
)
1454 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1455 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1456 NULL
, 0, NULL
, NULL
);
1457 if(lpOTMW
->otmpFaceName
)
1458 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1459 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1460 NULL
, 0, NULL
, NULL
);
1461 if(lpOTMW
->otmpStyleName
)
1462 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1463 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1464 NULL
, 0, NULL
, NULL
);
1465 if(lpOTMW
->otmpFullName
)
1466 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1467 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1468 NULL
, 0, NULL
, NULL
);
1475 TRACE("needed = %d\n", needed
);
1477 /* Since the supplied buffer isn't big enough, we'll alloc one
1478 that is and memcpy the first cbData bytes into the lpOTM at
1480 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1482 ret
= output
->otmSize
= min(needed
, cbData
);
1483 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1484 output
->otmFiller
= 0;
1485 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1486 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1487 output
->otmfsType
= lpOTMW
->otmfsType
;
1488 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1489 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1490 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1491 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1492 output
->otmAscent
= lpOTMW
->otmAscent
;
1493 output
->otmDescent
= lpOTMW
->otmDescent
;
1494 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1495 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1496 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1497 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1498 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1499 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1500 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1501 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1502 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1503 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1504 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1505 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1506 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1507 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1508 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1509 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1512 ptr
= (char*)(output
+ 1);
1513 left
= needed
- sizeof(*output
);
1515 if(lpOTMW
->otmpFamilyName
) {
1516 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1517 len
= WideCharToMultiByte(CP_ACP
, 0,
1518 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1519 ptr
, left
, NULL
, NULL
);
1523 output
->otmpFamilyName
= 0;
1525 if(lpOTMW
->otmpFaceName
) {
1526 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1527 len
= WideCharToMultiByte(CP_ACP
, 0,
1528 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1529 ptr
, left
, NULL
, NULL
);
1533 output
->otmpFaceName
= 0;
1535 if(lpOTMW
->otmpStyleName
) {
1536 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1537 len
= WideCharToMultiByte(CP_ACP
, 0,
1538 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1539 ptr
, left
, NULL
, NULL
);
1543 output
->otmpStyleName
= 0;
1545 if(lpOTMW
->otmpFullName
) {
1546 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1547 len
= WideCharToMultiByte(CP_ACP
, 0,
1548 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1549 ptr
, left
, NULL
, NULL
);
1552 output
->otmpFullName
= 0;
1556 if(output
!= lpOTM
) {
1557 memcpy(lpOTM
, output
, cbData
);
1558 HeapFree(GetProcessHeap(), 0, output
);
1560 /* check if the string offsets really fit into the provided size */
1561 /* FIXME: should we check string length as well? */
1562 /* make sure that we don't read/write beyond the provided buffer */
1563 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1565 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1566 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1569 /* make sure that we don't read/write beyond the provided buffer */
1570 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1572 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1573 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1576 /* make sure that we don't read/write beyond the provided buffer */
1577 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1579 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1580 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1583 /* make sure that we don't read/write beyond the provided buffer */
1584 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1586 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1587 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1592 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1593 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1599 /***********************************************************************
1600 * GetOutlineTextMetricsW [GDI32.@]
1602 UINT WINAPI
GetOutlineTextMetricsW(
1603 HDC hdc
, /* [in] Handle of device context */
1604 UINT cbData
, /* [in] Size of metric data array */
1605 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1607 DC
*dc
= get_dc_ptr( hdc
);
1608 OUTLINETEXTMETRICW
*output
= lpOTM
;
1612 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1615 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1616 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1618 if (lpOTM
&& ret
> cbData
)
1620 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1621 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1626 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1627 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1628 output
->otmTextMetrics
.tmHeight
= height_to_LP( dc
, output
->otmTextMetrics
.tmHeight
);
1629 output
->otmTextMetrics
.tmAscent
= height_to_LP( dc
, output
->otmTextMetrics
.tmAscent
);
1630 output
->otmTextMetrics
.tmDescent
= height_to_LP( dc
, output
->otmTextMetrics
.tmDescent
);
1631 output
->otmTextMetrics
.tmInternalLeading
= height_to_LP( dc
, output
->otmTextMetrics
.tmInternalLeading
);
1632 output
->otmTextMetrics
.tmExternalLeading
= height_to_LP( dc
, output
->otmTextMetrics
.tmExternalLeading
);
1633 output
->otmTextMetrics
.tmAveCharWidth
= width_to_LP( dc
, output
->otmTextMetrics
.tmAveCharWidth
);
1634 output
->otmTextMetrics
.tmMaxCharWidth
= width_to_LP( dc
, output
->otmTextMetrics
.tmMaxCharWidth
);
1635 output
->otmTextMetrics
.tmOverhang
= width_to_LP( dc
, output
->otmTextMetrics
.tmOverhang
);
1636 output
->otmAscent
= height_to_LP( dc
, output
->otmAscent
);
1637 output
->otmDescent
= height_to_LP( dc
, output
->otmDescent
);
1638 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1639 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1640 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1641 output
->otmrcFontBox
.top
= height_to_LP( dc
, output
->otmrcFontBox
.top
);
1642 output
->otmrcFontBox
.bottom
= height_to_LP( dc
, output
->otmrcFontBox
.bottom
);
1643 output
->otmrcFontBox
.left
= width_to_LP( dc
, output
->otmrcFontBox
.left
);
1644 output
->otmrcFontBox
.right
= width_to_LP( dc
, output
->otmrcFontBox
.right
);
1645 output
->otmMacAscent
= height_to_LP( dc
, output
->otmMacAscent
);
1646 output
->otmMacDescent
= height_to_LP( dc
, output
->otmMacDescent
);
1647 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1648 output
->otmptSubscriptSize
.x
= width_to_LP( dc
, output
->otmptSubscriptSize
.x
);
1649 output
->otmptSubscriptSize
.y
= height_to_LP( dc
, output
->otmptSubscriptSize
.y
);
1650 output
->otmptSubscriptOffset
.x
= width_to_LP( dc
, output
->otmptSubscriptOffset
.x
);
1651 output
->otmptSubscriptOffset
.y
= height_to_LP( dc
, output
->otmptSubscriptOffset
.y
);
1652 output
->otmptSuperscriptSize
.x
= width_to_LP( dc
, output
->otmptSuperscriptSize
.x
);
1653 output
->otmptSuperscriptSize
.y
= height_to_LP( dc
, output
->otmptSuperscriptSize
.y
);
1654 output
->otmptSuperscriptOffset
.x
= width_to_LP( dc
, output
->otmptSuperscriptOffset
.x
);
1655 output
->otmptSuperscriptOffset
.y
= height_to_LP( dc
, output
->otmptSuperscriptOffset
.y
);
1656 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1657 output
->otmsStrikeoutPosition
= height_to_LP( dc
, output
->otmsStrikeoutPosition
);
1658 output
->otmsUnderscoreSize
= height_to_LP( dc
, output
->otmsUnderscoreSize
);
1659 output
->otmsUnderscorePosition
= height_to_LP( dc
, output
->otmsUnderscorePosition
);
1664 memcpy(lpOTM
, output
, cbData
);
1665 HeapFree(GetProcessHeap(), 0, output
);
1673 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1675 INT i
, count
= lastChar
- firstChar
+ 1;
1683 mbcp
= GdiGetCodePage(hdc
);
1691 if (lastChar
> 0xffff)
1693 if ((firstChar
^ lastChar
) > 0xff)
1697 if (lastChar
> 0xff)
1703 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1707 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1711 str
[i
++] = (BYTE
)(c
>> 8);
1712 if (c
<= 0xff && IsDBCSLeadByteEx(mbcp
, c
))
1713 str
[i
] = 0x1f; /* FIXME: use default character */
1727 /***********************************************************************
1728 * GetCharWidthW (GDI32.@)
1729 * GetCharWidth32W (GDI32.@)
1731 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1737 DC
* dc
= get_dc_ptr( hdc
);
1739 if (!dc
) return FALSE
;
1741 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1742 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1746 /* convert device units to logical */
1747 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1748 *buffer
= width_to_LP( dc
, *buffer
);
1750 release_dc_ptr( dc
);
1755 /***********************************************************************
1756 * GetCharWidthA (GDI32.@)
1757 * GetCharWidth32A (GDI32.@)
1759 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1767 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1771 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1773 for(i
= 0; i
< wlen
; i
++)
1775 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1783 HeapFree(GetProcessHeap(), 0, str
);
1784 HeapFree(GetProcessHeap(), 0, wstr
);
1790 /* helper for nulldrv_ExtTextOut */
1791 static DWORD
get_glyph_bitmap( HDC hdc
, UINT index
, UINT flags
, UINT aa_flags
,
1792 GLYPHMETRICS
*metrics
, struct gdi_image_bits
*image
)
1794 static const MAT2 identity
= { {0,1}, {0,0}, {0,0}, {0,1} };
1795 UINT indices
[3] = {0, 0, 0x20};
1801 if (flags
& ETO_GLYPH_INDEX
) aa_flags
|= GGO_GLYPH_INDEX
;
1803 for (i
= 0; i
< sizeof(indices
) / sizeof(indices
[0]); i
++)
1806 ret
= GetGlyphOutlineW( hdc
, index
, aa_flags
, metrics
, 0, NULL
, &identity
);
1807 if (ret
!= GDI_ERROR
) break;
1810 if (ret
== GDI_ERROR
) return ERROR_NOT_FOUND
;
1811 if (!image
) return ERROR_SUCCESS
;
1815 if (!ret
) return ERROR_SUCCESS
; /* empty glyph */
1817 stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1818 size
= metrics
->gmBlackBoxY
* stride
;
1820 if (!(image
->ptr
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
1821 image
->is_copy
= TRUE
;
1822 image
->free
= free_heap_bits
;
1824 ret
= GetGlyphOutlineW( hdc
, index
, aa_flags
, metrics
, size
, image
->ptr
, &identity
);
1825 if (ret
== GDI_ERROR
)
1827 HeapFree( GetProcessHeap(), 0, image
->ptr
);
1828 return ERROR_NOT_FOUND
;
1830 return ERROR_SUCCESS
;
1833 /* helper for nulldrv_ExtTextOut */
1834 static RECT
get_total_extents( HDC hdc
, INT x
, INT y
, UINT flags
, UINT aa_flags
,
1835 LPCWSTR str
, UINT count
, const INT
*dx
)
1840 reset_bounds( &bounds
);
1841 for (i
= 0; i
< count
; i
++)
1843 GLYPHMETRICS metrics
;
1845 if (get_glyph_bitmap( hdc
, str
[i
], flags
, aa_flags
, &metrics
, NULL
)) continue;
1847 rect
.left
= x
+ metrics
.gmptGlyphOrigin
.x
;
1848 rect
.top
= y
- metrics
.gmptGlyphOrigin
.y
;
1849 rect
.right
= rect
.left
+ metrics
.gmBlackBoxX
;
1850 rect
.bottom
= rect
.top
+ metrics
.gmBlackBoxY
;
1851 add_bounds_rect( &bounds
, &rect
);
1855 if (flags
& ETO_PDY
)
1858 y
+= dx
[ i
* 2 + 1];
1864 x
+= metrics
.gmCellIncX
;
1865 y
+= metrics
.gmCellIncY
;
1871 /* helper for nulldrv_ExtTextOut */
1872 static void draw_glyph( HDC hdc
, INT origin_x
, INT origin_y
, const GLYPHMETRICS
*metrics
,
1873 const struct gdi_image_bits
*image
, const RECT
*clip
)
1875 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1876 UINT i
, count
, max_count
;
1878 BYTE
*ptr
= image
->ptr
;
1879 int stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1881 RECT rect
, clipped_rect
;
1883 rect
.left
= origin_x
+ metrics
->gmptGlyphOrigin
.x
;
1884 rect
.top
= origin_y
- metrics
->gmptGlyphOrigin
.y
;
1885 rect
.right
= rect
.left
+ metrics
->gmBlackBoxX
;
1886 rect
.bottom
= rect
.top
+ metrics
->gmBlackBoxY
;
1887 if (!clip
) clipped_rect
= rect
;
1888 else if (!intersect_rect( &clipped_rect
, &rect
, clip
)) return;
1890 max_count
= (metrics
->gmBlackBoxX
+ 1) * metrics
->gmBlackBoxY
;
1891 pts
= HeapAlloc( GetProcessHeap(), 0, max_count
* sizeof(*pts
) );
1895 ptr
+= (clipped_rect
.top
- rect
.top
) * stride
;
1896 for (y
= clipped_rect
.top
; y
< clipped_rect
.bottom
; y
++, ptr
+= stride
)
1898 for (x
= clipped_rect
.left
- rect
.left
; x
< clipped_rect
.right
- rect
.left
; x
++)
1900 while (x
< clipped_rect
.right
- rect
.left
&& !(ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1901 pts
[count
].x
= rect
.left
+ x
;
1902 while (x
< clipped_rect
.right
- rect
.left
&& (ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1903 pts
[count
+ 1].x
= rect
.left
+ x
;
1904 if (pts
[count
+ 1].x
> pts
[count
].x
)
1906 pts
[count
].y
= pts
[count
+ 1].y
= y
;
1911 assert( count
<= max_count
);
1912 DPtoLP( hdc
, pts
, count
);
1913 for (i
= 0; i
< count
; i
+= 2) Polyline( hdc
, pts
+ i
, 2 );
1914 HeapFree( GetProcessHeap(), 0, pts
);
1917 /***********************************************************************
1918 * nulldrv_ExtTextOut
1920 BOOL
nulldrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
1921 LPCWSTR str
, UINT count
, const INT
*dx
)
1923 DC
*dc
= get_nulldrv_dc( dev
);
1929 if (flags
& ETO_OPAQUE
)
1932 HBRUSH brush
= CreateSolidBrush( GetNearestColor( dev
->hdc
, GetBkColor(dev
->hdc
) ));
1936 orig
= SelectObject( dev
->hdc
, brush
);
1937 DPtoLP( dev
->hdc
, (POINT
*)&rc
, 2 );
1938 PatBlt( dev
->hdc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, PATCOPY
);
1939 SelectObject( dev
->hdc
, orig
);
1940 DeleteObject( brush
);
1944 if (!count
) return TRUE
;
1946 if (dc
->aa_flags
!= GGO_BITMAP
)
1948 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1949 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1950 struct gdi_image_bits bits
;
1951 struct bitblt_coords src
, dst
;
1953 /* FIXME Subpixel modes */
1954 UINT aa_flags
= GGO_GRAY4_BITMAP
;
1956 dst_dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
1957 src
.visrect
= get_total_extents( dev
->hdc
, x
, y
, flags
, aa_flags
, str
, count
, dx
);
1958 if (flags
& ETO_CLIPPED
) intersect_rect( &src
.visrect
, &src
.visrect
, rect
);
1959 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return TRUE
;
1961 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1962 src
.x
= src
.visrect
.left
;
1963 src
.y
= src
.visrect
.top
;
1964 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1965 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1967 if ((flags
& ETO_OPAQUE
) && (src
.visrect
.left
>= rect
->left
) && (src
.visrect
.top
>= rect
->top
) &&
1968 (src
.visrect
.right
<= rect
->right
) && (src
.visrect
.bottom
<= rect
->bottom
))
1970 /* we can avoid the GetImage, just query the needed format */
1971 memset( &info
->bmiHeader
, 0, sizeof(info
->bmiHeader
) );
1972 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1973 info
->bmiHeader
.biWidth
= src
.width
;
1974 info
->bmiHeader
.biHeight
= -src
.height
;
1975 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, info
, NULL
, NULL
, NULL
, 0 );
1976 if (!err
|| err
== ERROR_BAD_FORMAT
)
1978 /* make the source rectangle relative to the source bits */
1980 src
.visrect
.left
= src
.visrect
.top
= 0;
1981 src
.visrect
.right
= src
.width
;
1982 src
.visrect
.bottom
= src
.height
;
1984 bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1985 if (!bits
.ptr
) return ERROR_OUTOFMEMORY
;
1986 bits
.is_copy
= TRUE
;
1987 bits
.free
= free_heap_bits
;
1988 err
= ERROR_SUCCESS
;
1993 PHYSDEV src_dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
1994 err
= src_dev
->funcs
->pGetImage( src_dev
, info
, &bits
, &src
);
1995 if (!err
&& !bits
.is_copy
)
1997 void *ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
2000 if (bits
.free
) bits
.free( &bits
);
2001 return ERROR_OUTOFMEMORY
;
2003 memcpy( ptr
, bits
.ptr
, get_dib_image_size( info
));
2004 if (bits
.free
) bits
.free( &bits
);
2006 bits
.is_copy
= TRUE
;
2007 bits
.free
= free_heap_bits
;
2012 /* make x,y relative to the image bits */
2013 x
+= src
.visrect
.left
- dst
.visrect
.left
;
2014 y
+= src
.visrect
.top
- dst
.visrect
.top
;
2015 render_aa_text_bitmapinfo( dev
->hdc
, info
, &bits
, &src
, x
, y
, flags
,
2016 aa_flags
, str
, count
, dx
);
2017 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, info
, &bits
, &src
, &dst
, SRCCOPY
);
2018 if (bits
.free
) bits
.free( &bits
);
2023 pen
= CreatePen( PS_SOLID
, 1, GetTextColor(dev
->hdc
) );
2024 orig
= SelectObject( dev
->hdc
, pen
);
2026 for (i
= 0; i
< count
; i
++)
2028 GLYPHMETRICS metrics
;
2029 struct gdi_image_bits image
;
2031 err
= get_glyph_bitmap( dev
->hdc
, str
[i
], flags
, GGO_BITMAP
, &metrics
, &image
);
2034 if (image
.ptr
) draw_glyph( dev
->hdc
, x
, y
, &metrics
, &image
, (flags
& ETO_CLIPPED
) ? rect
: NULL
);
2035 if (image
.free
) image
.free( &image
);
2039 if (flags
& ETO_PDY
)
2042 y
+= dx
[ i
* 2 + 1];
2048 x
+= metrics
.gmCellIncX
;
2049 y
+= metrics
.gmCellIncY
;
2053 SelectObject( dev
->hdc
, orig
);
2054 DeleteObject( pen
);
2059 /***********************************************************************
2060 * ExtTextOutA (GDI32.@)
2064 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
2065 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
2073 if (flags
& ETO_GLYPH_INDEX
)
2074 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
2076 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
2079 unsigned int i
= 0, j
= 0;
2081 /* allocate enough for a ETO_PDY */
2082 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
2084 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
2088 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
2089 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
2092 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
2099 lpDxW
[j
++] = lpDx
[i
* 2];
2100 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
2103 lpDxW
[j
++] = lpDx
[i
];
2109 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
2111 HeapFree( GetProcessHeap(), 0, p
);
2112 HeapFree( GetProcessHeap(), 0, lpDxW
);
2117 /***********************************************************************
2118 * ExtTextOutW (GDI32.@)
2120 * Draws text using the currently selected font, background color, and text color.
2124 * x,y [I] coordinates of string
2126 * ETO_GRAYED - undocumented on MSDN
2127 * ETO_OPAQUE - use background color for fill the rectangle
2128 * ETO_CLIPPED - clipping text to the rectangle
2129 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2130 * than encoded characters. Implies ETO_IGNORELANGUAGE
2131 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2132 * Affects BiDi ordering
2133 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2134 * ETO_PDY - unimplemented
2135 * ETO_NUMERICSLATIN - unimplemented always assumed -
2136 * do not translate numbers into locale representations
2137 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2138 * lprect [I] dimensions for clipping or/and opaquing
2139 * str [I] text string
2140 * count [I] number of symbols in string
2141 * lpDx [I] optional parameter with distance between drawing characters
2147 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
2148 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
2151 LPWSTR reordered_str
= (LPWSTR
)str
;
2152 WORD
*glyphs
= NULL
;
2153 UINT align
= GetTextAlign( hdc
);
2154 DWORD layout
= GetLayout( hdc
);
2158 double cosEsc
, sinEsc
;
2162 POINT
*deltas
= NULL
, width
= {0, 0};
2164 DC
* dc
= get_dc_ptr( hdc
);
2167 static int quietfixme
= 0;
2169 if (!dc
) return FALSE
;
2171 breakRem
= dc
->breakRem
;
2173 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
2175 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2180 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
2181 type
= GetObjectType(hdc
);
2182 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
2184 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
2185 release_dc_ptr( dc
);
2189 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
2190 if (layout
& LAYOUT_RTL
)
2192 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
2193 align
^= TA_RTLREADING
;
2196 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
2199 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
2201 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
2202 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
2203 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
2205 flags
|= ETO_IGNORELANGUAGE
;
2208 flags
|= ETO_GLYPH_INDEX
;
2209 if (cGlyphs
!= count
)
2213 else if(flags
& ETO_GLYPH_INDEX
)
2214 glyphs
= reordered_str
;
2216 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
2217 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
2218 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
2220 if(align
& TA_UPDATECP
)
2222 GetCurrentPositionEx( hdc
, &pt
);
2227 GetTextMetricsW(hdc
, &tm
);
2228 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
2230 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
2231 lf
.lfEscapement
= 0;
2233 if ((dc
->GraphicsMode
== GM_COMPATIBLE
) &&
2234 (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
* dc
->xformWorld2Vport
.eM22
< 0))
2236 lf
.lfEscapement
= -lf
.lfEscapement
;
2239 if(lf
.lfEscapement
!= 0)
2241 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
2242 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
2253 LPtoDP(hdc
, (POINT
*)&rc
, 2);
2255 if (flags
& ETO_OPAQUE
)
2256 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2258 else flags
&= ~ETO_CLIPPED
;
2268 LPtoDP(hdc
, &pt
, 1);
2272 char_extra
= GetTextCharacterExtra(hdc
);
2273 if (char_extra
&& lpDx
&& GetDeviceCaps( hdc
, TECHNOLOGY
) == DT_RASPRINTER
)
2274 char_extra
= 0; /* Printer drivers don't add char_extra if lpDx is supplied */
2276 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2279 POINT total
= {0, 0}, desired
[2];
2281 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2284 if (flags
& ETO_PDY
)
2286 for (i
= 0; i
< count
; i
++)
2288 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
2289 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
2294 for (i
= 0; i
< count
; i
++)
2296 deltas
[i
].x
= lpDx
[i
] + char_extra
;
2303 INT
*dx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(*dx
) );
2305 if (flags
& ETO_GLYPH_INDEX
)
2306 GetTextExtentExPointI( hdc
, glyphs
, count
, -1, NULL
, dx
, &sz
);
2308 GetTextExtentExPointW( hdc
, reordered_str
, count
, -1, NULL
, dx
, &sz
);
2310 deltas
[0].x
= dx
[0];
2312 for (i
= 1; i
< count
; i
++)
2314 deltas
[i
].x
= dx
[i
] - dx
[i
- 1];
2317 HeapFree( GetProcessHeap(), 0, dx
);
2320 for(i
= 0; i
< count
; i
++)
2322 total
.x
+= deltas
[i
].x
;
2323 total
.y
+= deltas
[i
].y
;
2325 desired
[0].x
= desired
[0].y
= 0;
2327 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
2328 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
2330 LPtoDP(hdc
, desired
, 2);
2331 desired
[1].x
-= desired
[0].x
;
2332 desired
[1].y
-= desired
[0].y
;
2334 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2336 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2337 desired
[1].x
= -desired
[1].x
;
2338 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2339 desired
[1].y
= -desired
[1].y
;
2342 deltas
[i
].x
= desired
[1].x
- width
.x
;
2343 deltas
[i
].y
= desired
[1].y
- width
.y
;
2353 if(flags
& ETO_GLYPH_INDEX
)
2354 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2356 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2357 desired
[0].x
= desired
[0].y
= 0;
2358 desired
[1].x
= sz
.cx
;
2360 LPtoDP(hdc
, desired
, 2);
2361 desired
[1].x
-= desired
[0].x
;
2362 desired
[1].y
-= desired
[0].y
;
2364 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2366 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2367 desired
[1].x
= -desired
[1].x
;
2368 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2369 desired
[1].y
= -desired
[1].y
;
2374 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2375 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2376 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2379 if (align
& TA_UPDATECP
)
2383 DPtoLP(hdc
, &pt
, 1);
2384 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2396 if (align
& TA_UPDATECP
)
2400 DPtoLP(hdc
, &pt
, 1);
2401 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2406 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2409 y
+= tm
.tmAscent
* cosEsc
;
2410 x
+= tm
.tmAscent
* sinEsc
;
2414 y
-= tm
.tmDescent
* cosEsc
;
2415 x
-= tm
.tmDescent
* sinEsc
;
2422 if (GetBkMode(hdc
) != TRANSPARENT
)
2424 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2426 if(!(flags
& ETO_OPAQUE
) || !lprect
||
2427 x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2428 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2432 text_box
.right
= x
+ width
.x
;
2433 text_box
.top
= y
- tm
.tmAscent
;
2434 text_box
.bottom
= y
+ tm
.tmDescent
;
2436 if (flags
& ETO_CLIPPED
) intersect_rect( &text_box
, &text_box
, &rc
);
2437 if (!is_rect_empty( &text_box
))
2438 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &text_box
, NULL
, 0, NULL
);
2443 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2444 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2447 HeapFree(GetProcessHeap(), 0, deltas
);
2448 if(glyphs
!= reordered_str
)
2449 HeapFree(GetProcessHeap(), 0, glyphs
);
2450 if(reordered_str
!= str
)
2451 HeapFree(GetProcessHeap(), 0, reordered_str
);
2453 release_dc_ptr( dc
);
2455 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2457 int underlinePos
, strikeoutPos
;
2458 int underlineWidth
, strikeoutWidth
;
2459 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2460 OUTLINETEXTMETRICW
* otm
= NULL
;
2462 HPEN hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2463 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2465 hbrush
= SelectObject(hdc
, hbrush
);
2470 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2471 strikeoutPos
= tm
.tmAscent
/ 2;
2472 strikeoutWidth
= underlineWidth
;
2476 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2477 GetOutlineTextMetricsW(hdc
, size
, otm
);
2478 underlinePos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscorePosition
));
2479 if (otm
->otmsUnderscorePosition
< 0) underlinePos
= -underlinePos
;
2480 underlineWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscoreSize
));
2481 if (otm
->otmsUnderscoreSize
< 0) underlineWidth
= -underlineWidth
;
2482 strikeoutPos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutPosition
));
2483 if (otm
->otmsStrikeoutPosition
< 0) strikeoutPos
= -strikeoutPos
;
2484 strikeoutWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutSize
));
2485 HeapFree(GetProcessHeap(), 0, otm
);
2491 pts
[0].x
= x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2492 pts
[0].y
= y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2493 pts
[1].x
= x
+ width
.x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2494 pts
[1].y
= y
+ width
.y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2495 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2496 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2497 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2498 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2499 pts
[4].x
= pts
[0].x
;
2500 pts
[4].y
= pts
[0].y
;
2501 DPtoLP(hdc
, pts
, 5);
2502 Polygon(hdc
, pts
, 5);
2507 pts
[0].x
= x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2508 pts
[0].y
= y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2509 pts
[1].x
= x
+ width
.x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2510 pts
[1].y
= y
+ width
.y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2511 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2512 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2513 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2514 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2515 pts
[4].x
= pts
[0].x
;
2516 pts
[4].y
= pts
[0].y
;
2517 DPtoLP(hdc
, pts
, 5);
2518 Polygon(hdc
, pts
, 5);
2521 SelectObject(hdc
, hpen
);
2522 hbrush
= SelectObject(hdc
, hbrush
);
2523 DeleteObject(hbrush
);
2530 /***********************************************************************
2531 * TextOutA (GDI32.@)
2533 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2535 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2539 /***********************************************************************
2540 * TextOutW (GDI32.@)
2542 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2544 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2548 /***********************************************************************
2549 * PolyTextOutA (GDI32.@)
2553 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2555 for (; cStrings
>0; cStrings
--, pptxt
++)
2556 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2563 /***********************************************************************
2564 * PolyTextOutW (GDI32.@)
2566 * Draw several Strings
2572 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2574 for (; cStrings
>0; cStrings
--, pptxt
++)
2575 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2581 /***********************************************************************
2582 * SetMapperFlags (GDI32.@)
2584 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2586 DC
*dc
= get_dc_ptr( hdc
);
2587 DWORD ret
= GDI_ERROR
;
2591 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2592 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2593 if (flags
!= GDI_ERROR
)
2595 ret
= dc
->mapperFlags
;
2596 dc
->mapperFlags
= flags
;
2598 release_dc_ptr( dc
);
2603 /***********************************************************************
2604 * GetAspectRatioFilterEx (GDI32.@)
2606 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2608 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2613 /***********************************************************************
2614 * GetCharABCWidthsA (GDI32.@)
2616 * See GetCharABCWidthsW.
2618 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2626 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2630 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2633 HeapFree(GetProcessHeap(), 0, str
);
2637 for(i
= 0; i
< wlen
; i
++)
2639 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2647 HeapFree(GetProcessHeap(), 0, str
);
2648 HeapFree(GetProcessHeap(), 0, wstr
);
2654 /******************************************************************************
2655 * GetCharABCWidthsW [GDI32.@]
2657 * Retrieves widths of characters in range.
2660 * hdc [I] Handle of device context
2661 * firstChar [I] First character in range to query
2662 * lastChar [I] Last character in range to query
2663 * abc [O] Address of character-width structure
2666 * Only works with TrueType fonts
2672 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2675 DC
*dc
= get_dc_ptr(hdc
);
2681 if (!dc
) return FALSE
;
2685 release_dc_ptr( dc
);
2689 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-scalable fonts */
2690 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
2691 if (!dev
->funcs
->pGetTextMetrics( dev
, &tm
) || !(tm
.tmPitchAndFamily
& TMPF_VECTOR
))
2693 release_dc_ptr( dc
);
2697 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2698 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2701 /* convert device units to logical */
2702 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2703 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2704 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2705 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2709 release_dc_ptr( dc
);
2714 /******************************************************************************
2715 * GetCharABCWidthsI [GDI32.@]
2717 * Retrieves widths of characters in range.
2720 * hdc [I] Handle of device context
2721 * firstChar [I] First glyphs in range to query
2722 * count [I] Last glyphs in range to query
2723 * pgi [i] Array of glyphs to query
2724 * abc [O] Address of character-width structure
2727 * Only works with TrueType fonts
2733 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2734 LPWORD pgi
, LPABC abc
)
2736 DC
*dc
= get_dc_ptr(hdc
);
2741 if (!dc
) return FALSE
;
2745 release_dc_ptr( dc
);
2749 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2750 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2753 /* convert device units to logical */
2754 for( i
= 0; i
< count
; i
++, abc
++ ) {
2755 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2756 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2757 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2761 release_dc_ptr( dc
);
2766 /***********************************************************************
2767 * GetGlyphOutlineA (GDI32.@)
2769 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2770 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2771 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2773 if (!lpmat2
) return GDI_ERROR
;
2775 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2780 cp
= GdiGetCodePage(hdc
);
2781 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2783 mbchs
[0] = (uChar
& 0xff00) >> 8;
2784 mbchs
[1] = (uChar
& 0xff);
2787 mbchs
[0] = (uChar
& 0xff);
2790 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2793 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2797 /***********************************************************************
2798 * GetGlyphOutlineW (GDI32.@)
2800 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2801 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2802 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2808 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2809 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2811 if (!lpmat2
) return GDI_ERROR
;
2813 dc
= get_dc_ptr(hdc
);
2814 if(!dc
) return GDI_ERROR
;
2816 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2817 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2818 release_dc_ptr( dc
);
2823 /***********************************************************************
2824 * CreateScalableFontResourceA (GDI32.@)
2826 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2827 LPCSTR lpszResourceFile
,
2828 LPCSTR lpszFontFile
,
2829 LPCSTR lpszCurrentPath
)
2831 LPWSTR lpszResourceFileW
= NULL
;
2832 LPWSTR lpszFontFileW
= NULL
;
2833 LPWSTR lpszCurrentPathW
= NULL
;
2837 if (lpszResourceFile
)
2839 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2840 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2841 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2846 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2847 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2848 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2851 if (lpszCurrentPath
)
2853 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2854 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2855 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2858 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2859 lpszFontFileW
, lpszCurrentPathW
);
2861 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2862 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2863 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2868 /***********************************************************************
2869 * CreateScalableFontResourceW (GDI32.@)
2871 BOOL WINAPI
CreateScalableFontResourceW( DWORD hidden
, LPCWSTR resource_file
,
2872 LPCWSTR font_file
, LPCWSTR font_path
)
2874 TRACE("(%d, %s, %s, %s)\n", hidden
, debugstr_w(resource_file
),
2875 debugstr_w(font_file
), debugstr_w(font_path
) );
2877 return WineEngCreateScalableFontResource( hidden
, resource_file
,
2878 font_file
, font_path
);
2881 /*************************************************************************
2882 * GetKerningPairsA (GDI32.@)
2884 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2885 LPKERNINGPAIR kern_pairA
)
2889 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2890 KERNINGPAIR
*kern_pairW
;
2892 if (!cPairs
&& kern_pairA
)
2894 SetLastError(ERROR_INVALID_PARAMETER
);
2898 cp
= GdiGetCodePage(hDC
);
2900 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2901 * to fail on an invalid character for CP_SYMBOL.
2903 cpi
.DefaultChar
[0] = 0;
2904 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2906 FIXME("Can't find codepage %u info\n", cp
);
2910 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2911 if (!total_kern_pairs
) return 0;
2913 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2914 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2916 for (i
= 0; i
< total_kern_pairs
; i
++)
2920 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2923 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2926 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2931 if (kern_pairs_copied
>= cPairs
) break;
2933 kern_pairA
->wFirst
= (BYTE
)first
;
2934 kern_pairA
->wSecond
= (BYTE
)second
;
2935 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2938 kern_pairs_copied
++;
2941 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2943 return kern_pairs_copied
;
2946 /*************************************************************************
2947 * GetKerningPairsW (GDI32.@)
2949 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2950 LPKERNINGPAIR lpKerningPairs
)
2956 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2958 if (!cPairs
&& lpKerningPairs
)
2960 SetLastError(ERROR_INVALID_PARAMETER
);
2964 dc
= get_dc_ptr(hDC
);
2967 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
2968 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
2969 release_dc_ptr( dc
);
2973 /*************************************************************************
2974 * TranslateCharsetInfo [GDI32.@]
2976 * Fills a CHARSETINFO structure for a character set, code page, or
2977 * font. This allows making the correspondence between different labels
2978 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2979 * of the same encoding.
2981 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2982 * only one codepage should be set in *lpSrc.
2985 * TRUE on success, FALSE on failure.
2988 BOOL WINAPI
TranslateCharsetInfo(
2989 LPDWORD lpSrc
, /* [in]
2990 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2991 if flags == TCI_SRCCHARSET: a character set value
2992 if flags == TCI_SRCCODEPAGE: a code page value
2994 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2995 DWORD flags
/* [in] determines interpretation of lpSrc */)
2999 case TCI_SRCFONTSIG
:
3000 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
3002 case TCI_SRCCODEPAGE
:
3003 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
3005 case TCI_SRCCHARSET
:
3006 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
3011 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
3012 *lpCs
= FONT_tci
[index
];
3016 /*************************************************************************
3017 * GetFontLanguageInfo (GDI32.@)
3019 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
3021 FONTSIGNATURE fontsig
;
3022 static const DWORD GCP_DBCS_MASK
=0x003F0000,
3023 GCP_DIACRITIC_MASK
=0x00000000,
3024 FLI_GLYPHS_MASK
=0x00000000,
3025 GCP_GLYPHSHAPE_MASK
=0x00000040,
3026 GCP_KASHIDA_MASK
=0x00000000,
3027 GCP_LIGATE_MASK
=0x00000000,
3028 GCP_USEKERNING_MASK
=0x00000000,
3029 GCP_REORDER_MASK
=0x00000060;
3033 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
3034 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3036 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
3039 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
3040 result
|=GCP_DIACRITIC
;
3042 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
3045 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
3046 result
|=GCP_GLYPHSHAPE
;
3048 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
3049 result
|=GCP_KASHIDA
;
3051 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
3054 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
3055 result
|=GCP_USEKERNING
;
3057 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3058 if( GetTextAlign( hdc
) & TA_RTLREADING
)
3059 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
3060 result
|=GCP_REORDER
;
3066 /*************************************************************************
3067 * GetFontData [GDI32.@]
3069 * Retrieve data for TrueType font.
3073 * success: Number of bytes returned
3074 * failure: GDI_ERROR
3078 * Calls SetLastError()
3081 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
3082 LPVOID buffer
, DWORD length
)
3084 DC
*dc
= get_dc_ptr(hdc
);
3088 if(!dc
) return GDI_ERROR
;
3090 dev
= GET_DC_PHYSDEV( dc
, pGetFontData
);
3091 ret
= dev
->funcs
->pGetFontData( dev
, table
, offset
, buffer
, length
);
3092 release_dc_ptr( dc
);
3096 /*************************************************************************
3097 * GetGlyphIndicesA [GDI32.@]
3099 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
3100 LPWORD pgi
, DWORD flags
)
3106 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3107 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
3109 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
3110 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
3111 HeapFree(GetProcessHeap(), 0, lpstrW
);
3116 /*************************************************************************
3117 * GetGlyphIndicesW [GDI32.@]
3119 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
3120 LPWORD pgi
, DWORD flags
)
3122 DC
*dc
= get_dc_ptr(hdc
);
3126 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3127 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
3129 if(!dc
) return GDI_ERROR
;
3131 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
3132 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
3133 release_dc_ptr( dc
);
3137 /*************************************************************************
3138 * GetCharacterPlacementA [GDI32.@]
3140 * See GetCharacterPlacementW.
3143 * the web browser control of ie4 calls this with dwFlags=0
3146 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
3147 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
3152 GCP_RESULTSW resultsW
;
3156 TRACE("%s, %d, %d, 0x%08x\n",
3157 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3159 /* both structs are equal in size */
3160 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
3162 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
3163 if(lpResults
->lpOutString
)
3164 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
3166 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
3168 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
3169 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
3171 if(lpResults
->lpOutString
) {
3172 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
3173 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
3176 HeapFree(GetProcessHeap(), 0, lpStringW
);
3177 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
3182 /*************************************************************************
3183 * GetCharacterPlacementW [GDI32.@]
3185 * Retrieve information about a string. This includes the width, reordering,
3186 * Glyphing and so on.
3190 * The width and height of the string if successful, 0 if failed.
3194 * All flags except GCP_REORDER are not yet implemented.
3195 * Reordering is not 100% compliant to the Windows BiDi method.
3196 * Caret positioning is not yet implemented for BiDi.
3197 * Classes are not yet implemented.
3201 GetCharacterPlacementW(
3202 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3203 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3204 INT uCount
, /* [in] Number of WORDS in string. */
3205 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3206 GCP_RESULTSW
*lpResults
, /* [in/out] A pointer to a GCP_RESULTSW struct */
3207 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3214 TRACE("%s, %d, %d, 0x%08x\n",
3215 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3217 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3218 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3219 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3220 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3221 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3223 if(dwFlags
&(~GCP_REORDER
))
3224 FIXME("flags 0x%08x ignored\n", dwFlags
);
3225 if(lpResults
->lpClass
)
3226 FIXME("classes not implemented\n");
3227 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3228 FIXME("Caret positions for complex scripts not implemented\n");
3230 nSet
= (UINT
)uCount
;
3231 if(nSet
> lpResults
->nGlyphs
)
3232 nSet
= lpResults
->nGlyphs
;
3234 /* return number of initialized fields */
3235 lpResults
->nGlyphs
= nSet
;
3237 if((dwFlags
&GCP_REORDER
)==0 )
3239 /* Treat the case where no special handling was requested in a fastpath way */
3240 /* copy will do if the GCP_REORDER flag is not set */
3241 if(lpResults
->lpOutString
)
3242 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3244 if(lpResults
->lpOrder
)
3246 for(i
= 0; i
< nSet
; i
++)
3247 lpResults
->lpOrder
[i
] = i
;
3252 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3253 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3256 /* FIXME: Will use the placement chars */
3257 if (lpResults
->lpDx
)
3260 for (i
= 0; i
< nSet
; i
++)
3262 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3263 lpResults
->lpDx
[i
]= c
;
3267 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3271 lpResults
->lpCaretPos
[0] = 0;
3272 for (i
= 1; i
< nSet
; i
++)
3273 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3274 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3277 if(lpResults
->lpGlyphs
)
3278 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3280 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3281 ret
= MAKELONG(size
.cx
, size
.cy
);
3286 /*************************************************************************
3287 * GetCharABCWidthsFloatA [GDI32.@]
3289 * See GetCharABCWidthsFloatW.
3291 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3298 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3302 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3304 for (i
= 0; i
< wlen
; i
++)
3306 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3314 HeapFree( GetProcessHeap(), 0, str
);
3315 HeapFree( GetProcessHeap(), 0, wstr
);
3320 /*************************************************************************
3321 * GetCharABCWidthsFloatW [GDI32.@]
3323 * Retrieves widths of a range of characters.
3326 * hdc [I] Handle to device context.
3327 * first [I] First character in range to query.
3328 * last [I] Last character in range to query.
3329 * abcf [O] Array of LPABCFLOAT structures.
3335 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3341 DC
*dc
= get_dc_ptr( hdc
);
3343 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3345 if (!dc
) return FALSE
;
3347 if (!abcf
) goto done
;
3348 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
3350 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
3351 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
3354 /* convert device units to logical */
3355 for (i
= first
; i
<= last
; i
++, abcf
++)
3357 abcf
->abcfA
= abc
[i
- first
].abcA
* dc
->xformVport2World
.eM11
;
3358 abcf
->abcfB
= abc
[i
- first
].abcB
* dc
->xformVport2World
.eM11
;
3359 abcf
->abcfC
= abc
[i
- first
].abcC
* dc
->xformVport2World
.eM11
;
3362 HeapFree( GetProcessHeap(), 0, abc
);
3365 release_dc_ptr( dc
);
3369 /*************************************************************************
3370 * GetCharWidthFloatA [GDI32.@]
3372 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3373 UINT iLastChar
, PFLOAT pxBuffer
)
3375 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3379 /*************************************************************************
3380 * GetCharWidthFloatW [GDI32.@]
3382 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3383 UINT iLastChar
, PFLOAT pxBuffer
)
3385 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3390 /***********************************************************************
3392 * Font Resource API *
3394 ***********************************************************************/
3396 /***********************************************************************
3397 * AddFontResourceA (GDI32.@)
3399 INT WINAPI
AddFontResourceA( LPCSTR str
)
3401 return AddFontResourceExA( str
, 0, NULL
);
3404 /***********************************************************************
3405 * AddFontResourceW (GDI32.@)
3407 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3409 return AddFontResourceExW(str
, 0, NULL
);
3413 /***********************************************************************
3414 * AddFontResourceExA (GDI32.@)
3416 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3418 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3419 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3422 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3423 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3424 HeapFree(GetProcessHeap(), 0, strW
);
3428 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3430 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3431 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3432 LPVOID
*pMem
= LockResource(hMem
);
3433 int *num_total
= (int *)lParam
;
3436 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3437 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3439 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3443 *num_total
+= num_in_res
;
3447 static void *map_file( const WCHAR
*filename
, LARGE_INTEGER
*size
)
3449 HANDLE file
, mapping
;
3452 file
= CreateFileW( filename
, GENERIC_READ
, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, NULL
);
3453 if (file
== INVALID_HANDLE_VALUE
) return NULL
;
3455 if (!GetFileSizeEx( file
, size
) || size
->u
.HighPart
)
3457 CloseHandle( file
);
3461 mapping
= CreateFileMappingW( file
, NULL
, PAGE_READONLY
, 0, 0, NULL
);
3462 CloseHandle( file
);
3463 if (!mapping
) return NULL
;
3465 ptr
= MapViewOfFile( mapping
, FILE_MAP_READ
, 0, 0, 0 );
3466 CloseHandle( mapping
);
3471 static void *find_resource( BYTE
*ptr
, WORD type
, DWORD rsrc_off
, DWORD size
, DWORD
*len
)
3473 WORD align
, type_id
, count
;
3476 if (size
< rsrc_off
+ 10) return NULL
;
3477 align
= *(WORD
*)(ptr
+ rsrc_off
);
3479 type_id
= *(WORD
*)(ptr
+ rsrc_off
);
3480 while (type_id
&& type_id
!= type
)
3482 count
= *(WORD
*)(ptr
+ rsrc_off
+ 2);
3483 rsrc_off
+= 8 + count
* 12;
3484 if (size
< rsrc_off
+ 8) return NULL
;
3485 type_id
= *(WORD
*)(ptr
+ rsrc_off
);
3487 if (!type_id
) return NULL
;
3488 count
= *(WORD
*)(ptr
+ rsrc_off
+ 2);
3489 if (size
< rsrc_off
+ 8 + count
* 12) return NULL
;
3490 res_off
= *(WORD
*)(ptr
+ rsrc_off
+ 8) << align
;
3491 *len
= *(WORD
*)(ptr
+ rsrc_off
+ 10) << align
;
3492 if (size
< res_off
+ *len
) return NULL
;
3493 return ptr
+ res_off
;
3496 static WCHAR
*get_scalable_filename( const WCHAR
*res
, BOOL
*hidden
)
3499 BYTE
*ptr
= map_file( res
, &size
);
3500 const IMAGE_DOS_HEADER
*dos
;
3501 const IMAGE_OS2_HEADER
*ne
;
3507 if (!ptr
) return NULL
;
3509 if (size
.u
.LowPart
< sizeof( *dos
)) goto fail
;
3510 dos
= (const IMAGE_DOS_HEADER
*)ptr
;
3511 if (dos
->e_magic
!= IMAGE_DOS_SIGNATURE
) goto fail
;
3512 if (size
.u
.LowPart
< dos
->e_lfanew
+ sizeof( *ne
)) goto fail
;
3513 ne
= (const IMAGE_OS2_HEADER
*)(ptr
+ dos
->e_lfanew
);
3515 fontdir
= find_resource( ptr
, 0x8007, dos
->e_lfanew
+ ne
->ne_rsrctab
, size
.u
.LowPart
, &len
);
3516 if (!fontdir
) goto fail
;
3517 *hidden
= (fontdir
[35] & 0x80) != 0; /* fontdir->dfType */
3519 data
= find_resource( ptr
, 0x80cc, dos
->e_lfanew
+ ne
->ne_rsrctab
, size
.u
.LowPart
, &len
);
3520 if (!data
) goto fail
;
3521 if (!memchr( data
, 0, len
)) goto fail
;
3523 len
= MultiByteToWideChar( CP_ACP
, 0, data
, -1, NULL
, 0 );
3524 name
= HeapAlloc( GetProcessHeap(), 0, len
* sizeof(WCHAR
) );
3525 if (name
) MultiByteToWideChar( CP_ACP
, 0, data
, -1, name
, len
);
3528 UnmapViewOfFile( ptr
);
3532 /***********************************************************************
3533 * AddFontResourceExW (GDI32.@)
3535 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3537 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3543 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3544 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3545 if (hModule
!= NULL
)
3547 int num_resources
= 0;
3548 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3550 TRACE("WineEngAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3551 wine_dbgstr_w(str
));
3552 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3553 ret
= num_resources
;
3554 FreeLibrary(hModule
);
3556 else if ((filename
= get_scalable_filename( str
, &hidden
)) != NULL
)
3558 if (hidden
) fl
|= FR_PRIVATE
| FR_NOT_ENUM
;
3559 ret
= WineEngAddFontResourceEx( filename
, fl
, pdv
);
3560 HeapFree( GetProcessHeap(), 0, filename
);
3566 /***********************************************************************
3567 * RemoveFontResourceA (GDI32.@)
3569 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3571 return RemoveFontResourceExA(str
, 0, 0);
3574 /***********************************************************************
3575 * RemoveFontResourceW (GDI32.@)
3577 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3579 return RemoveFontResourceExW(str
, 0, 0);
3582 /***********************************************************************
3583 * AddFontMemResourceEx (GDI32.@)
3585 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3590 if (!pbFont
|| !cbFont
|| !pcFonts
)
3592 SetLastError(ERROR_INVALID_PARAMETER
);
3596 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3601 *pcFonts
= num_fonts
;
3605 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3606 RemoveFontMemResourceEx(ret
);
3614 /***********************************************************************
3615 * RemoveFontMemResourceEx (GDI32.@)
3617 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3619 FIXME("(%p) stub\n", fh
);
3623 /***********************************************************************
3624 * RemoveFontResourceExA (GDI32.@)
3626 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3628 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3629 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3632 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3633 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3634 HeapFree(GetProcessHeap(), 0, strW
);
3638 /***********************************************************************
3639 * RemoveFontResourceExW (GDI32.@)
3641 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3643 int ret
= WineEngRemoveFontResourceEx( str
, fl
, pdv
);
3649 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3650 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3651 if (hModule
!= NULL
)
3653 WARN("Can't unload resources from PE file %s\n", wine_dbgstr_w(str
));
3654 FreeLibrary(hModule
);
3656 else if ((filename
= get_scalable_filename( str
, &hidden
)) != NULL
)
3658 if (hidden
) fl
|= FR_PRIVATE
| FR_NOT_ENUM
;
3659 ret
= WineEngRemoveFontResourceEx( filename
, fl
, pdv
);
3660 HeapFree( GetProcessHeap(), 0, filename
);
3666 /***********************************************************************
3667 * GetFontResourceInfoW (GDI32.@)
3669 BOOL WINAPI
GetFontResourceInfoW( LPCWSTR str
, LPDWORD size
, PVOID buffer
, DWORD type
)
3671 FIXME("%s %p(%d) %p %d\n", debugstr_w(str
), size
, size
? *size
: 0, buffer
, type
);
3675 /***********************************************************************
3676 * GetTextCharset (GDI32.@)
3678 UINT WINAPI
GetTextCharset(HDC hdc
)
3680 /* MSDN docs say this is equivalent */
3681 return GetTextCharsetInfo(hdc
, NULL
, 0);
3684 /***********************************************************************
3685 * GetTextCharsetInfo (GDI32.@)
3687 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3689 UINT ret
= DEFAULT_CHARSET
;
3690 DC
*dc
= get_dc_ptr(hdc
);
3695 dev
= GET_DC_PHYSDEV( dc
, pGetTextCharsetInfo
);
3696 ret
= dev
->funcs
->pGetTextCharsetInfo( dev
, fs
, flags
);
3697 release_dc_ptr( dc
);
3700 if (ret
== DEFAULT_CHARSET
&& fs
)
3701 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3705 /***********************************************************************
3706 * GdiGetCharDimensions (GDI32.@)
3708 * Gets the average width of the characters in the English alphabet.
3711 * hdc [I] Handle to the device context to measure on.
3712 * lptm [O] Pointer to memory to store the text metrics into.
3713 * height [O] On exit, the maximum height of characters in the English alphabet.
3716 * The average width of characters in the English alphabet.
3719 * This function is used by the dialog manager to get the size of a dialog
3720 * unit. It should also be used by other pieces of code that need to know
3721 * the size of a dialog unit in logical units without having access to the
3722 * window handle of the dialog.
3723 * Windows caches the font metrics from this function, but we don't and
3724 * there doesn't appear to be an immediate advantage to do so.
3727 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3729 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3732 static const WCHAR alphabet
[] = {
3733 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3734 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3735 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3737 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3739 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3741 if (height
) *height
= sz
.cy
;
3742 return (sz
.cx
/ 26 + 1) / 2;
3745 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3747 FIXME("(%d): stub\n", fEnableEUDC
);
3751 /***********************************************************************
3752 * GetCharWidthI (GDI32.@)
3754 * Retrieve widths of characters.
3757 * hdc [I] Handle to a device context.
3758 * first [I] First glyph in range to query.
3759 * count [I] Number of glyph indices to query.
3760 * glyphs [I] Array of glyphs to query.
3761 * buffer [O] Buffer to receive character widths.
3764 * Only works with TrueType fonts.
3770 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3775 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3777 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3780 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3782 HeapFree(GetProcessHeap(), 0, abc
);
3786 for (i
= 0; i
< count
; i
++)
3787 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3789 HeapFree(GetProcessHeap(), 0, abc
);
3793 /***********************************************************************
3794 * GetFontUnicodeRanges (GDI32.@)
3796 * Retrieve a list of supported Unicode characters in a font.
3799 * hdc [I] Handle to a device context.
3800 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3803 * Success: Number of bytes written to the buffer pointed to by lpgs.
3807 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3811 DC
*dc
= get_dc_ptr(hdc
);
3813 TRACE("(%p, %p)\n", hdc
, lpgs
);
3817 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3818 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3824 /*************************************************************
3825 * FontIsLinked (GDI32.@)
3827 BOOL WINAPI
FontIsLinked(HDC hdc
)
3829 DC
*dc
= get_dc_ptr(hdc
);
3833 if (!dc
) return FALSE
;
3834 dev
= GET_DC_PHYSDEV( dc
, pFontIsLinked
);
3835 ret
= dev
->funcs
->pFontIsLinked( dev
);
3837 TRACE("returning %d\n", ret
);
3841 /*************************************************************
3842 * GdiRealizationInfo (GDI32.@)
3844 * Returns a structure that contains some font information.
3846 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3848 DC
*dc
= get_dc_ptr(hdc
);
3852 if (!dc
) return FALSE
;
3853 dev
= GET_DC_PHYSDEV( dc
, pGdiRealizationInfo
);
3854 ret
= dev
->funcs
->pGdiRealizationInfo( dev
, info
);