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"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font
);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
50 /* Perform operation with floating point */
51 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth
);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
63 /* Perform operation with floating point */
64 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight
);
69 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
72 pt
[0].x
= pt
[0].y
= 0;
75 LPtoDP(dc
->hSelf
, pt
, 2);
76 return pt
[1].x
- pt
[0].x
;
79 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
82 pt
[0].x
= pt
[0].y
= 0;
85 LPtoDP(dc
->hSelf
, pt
, 2);
86 return pt
[1].y
- pt
[0].y
;
89 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
90 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
91 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
92 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
94 static const struct gdi_obj_funcs font_funcs
=
96 FONT_SelectObject
, /* pSelectObject */
97 FONT_GetObjectA
, /* pGetObjectA */
98 FONT_GetObjectW
, /* pGetObjectW */
99 NULL
, /* pUnrealizeObject */
100 FONT_DeleteObject
/* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam
;
115 FONTENUMPROCW lpEnumFunc
;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
127 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
128 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
129 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
130 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
131 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
132 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
133 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
134 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
135 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
138 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
139 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
140 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
141 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
142 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
143 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
145 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
146 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
147 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
148 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
149 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
150 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
151 /* reserved for alternate ANSI and OEM */
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}} },
156 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
157 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
167 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
168 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
170 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
175 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
176 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
177 LF_FACESIZE
, NULL
, NULL
);
178 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
183 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
185 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
186 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
187 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
188 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
189 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
190 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
191 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
192 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
193 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
198 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
200 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
201 fontW
->elfFullName
, LF_FULLFACESIZE
);
202 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
203 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
204 fontW
->elfStyle
, LF_FACESIZE
);
205 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
206 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
207 fontW
->elfScript
, LF_FACESIZE
);
208 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
216 ptmA
->tmHeight
= ptmW
->tmHeight
;
217 ptmA
->tmAscent
= ptmW
->tmAscent
;
218 ptmA
->tmDescent
= ptmW
->tmDescent
;
219 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
220 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
221 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
222 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
223 ptmA
->tmWeight
= ptmW
->tmWeight
;
224 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
225 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
226 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
227 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
228 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
230 ptmA
->tmFirstChar
= 0x1e;
231 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
235 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
236 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
238 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
239 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
240 ptmA
->tmItalic
= ptmW
->tmItalic
;
241 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
242 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
243 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
244 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
248 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
250 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
251 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
252 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
253 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
254 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
255 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
259 /***********************************************************************
260 * GdiGetCodePage (GDI32.@)
262 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
265 DC
*dc
= get_dc_ptr( hdc
);
269 cp
= dc
->font_code_page
;
270 release_dc_ptr( dc
);
275 /***********************************************************************
278 * Returns a Unicode translation of str using the charset of the
279 * currently selected font in hdc. If count is -1 then str is assumed
280 * to be '\0' terminated, otherwise it contains the number of bytes to
281 * convert. If plenW is non-NULL, on return it will point to the
282 * number of WCHARs that have been written. If pCP is non-NULL, on
283 * return it will point to the codepage used in the conversion. The
284 * caller should free the returned LPWSTR from the process heap
287 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
293 cp
= GdiGetCodePage( hdc
);
295 if(count
== -1) count
= strlen(str
);
296 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
297 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
298 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
299 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
300 if(plenW
) *plenW
= lenW
;
305 /***********************************************************************
306 * CreateFontIndirectExA (GDI32.@)
308 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
310 ENUMLOGFONTEXDVW enumexW
;
312 if (!penumexA
) return 0;
314 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
315 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
316 return CreateFontIndirectExW( &enumexW
);
319 /***********************************************************************
320 * CreateFontIndirectExW (GDI32.@)
322 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
328 if (!penumex
) return 0;
330 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
331 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
332 penumex
->elfEnumLogfontEx
.elfScript
[0])
334 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
335 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
336 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
337 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
340 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
341 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
343 fontPtr
->logfont
= *plf
;
345 if (plf
->lfEscapement
!= plf
->lfOrientation
)
347 /* this should really depend on whether GM_ADVANCED is set */
348 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
349 WARN("orientation angle %f set to "
350 "escapement angle %f for new font %p\n",
351 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
354 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
356 HeapFree( GetProcessHeap(), 0, fontPtr
);
360 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
361 plf
->lfHeight
, plf
->lfWidth
,
362 plf
->lfEscapement
, plf
->lfOrientation
,
363 plf
->lfPitchAndFamily
,
364 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
365 plf
->lfQuality
, plf
->lfCharSet
,
366 debugstr_w(plf
->lfFaceName
),
367 plf
->lfWeight
> 400 ? "Bold" : "",
368 plf
->lfItalic
? "Italic" : "",
369 plf
->lfUnderline
? "Underline" : "", hFont
);
374 /***********************************************************************
375 * CreateFontIndirectA (GDI32.@)
377 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
383 FONT_LogFontAToW( plfA
, &lfW
);
384 return CreateFontIndirectW( &lfW
);
387 /***********************************************************************
388 * CreateFontIndirectW (GDI32.@)
390 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
392 ENUMLOGFONTEXDVW exdv
;
396 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
397 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
398 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
399 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
400 return CreateFontIndirectExW( &exdv
);
403 /*************************************************************************
404 * CreateFontA (GDI32.@)
406 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
407 INT orient
, INT weight
, DWORD italic
,
408 DWORD underline
, DWORD strikeout
, DWORD charset
,
409 DWORD outpres
, DWORD clippres
, DWORD quality
,
410 DWORD pitch
, LPCSTR name
)
414 logfont
.lfHeight
= height
;
415 logfont
.lfWidth
= width
;
416 logfont
.lfEscapement
= esc
;
417 logfont
.lfOrientation
= orient
;
418 logfont
.lfWeight
= weight
;
419 logfont
.lfItalic
= italic
;
420 logfont
.lfUnderline
= underline
;
421 logfont
.lfStrikeOut
= strikeout
;
422 logfont
.lfCharSet
= charset
;
423 logfont
.lfOutPrecision
= outpres
;
424 logfont
.lfClipPrecision
= clippres
;
425 logfont
.lfQuality
= quality
;
426 logfont
.lfPitchAndFamily
= pitch
;
429 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
431 logfont
.lfFaceName
[0] = '\0';
433 return CreateFontIndirectA( &logfont
);
436 /*************************************************************************
437 * CreateFontW (GDI32.@)
439 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
440 INT orient
, INT weight
, DWORD italic
,
441 DWORD underline
, DWORD strikeout
, DWORD charset
,
442 DWORD outpres
, DWORD clippres
, DWORD quality
,
443 DWORD pitch
, LPCWSTR name
)
447 logfont
.lfHeight
= height
;
448 logfont
.lfWidth
= width
;
449 logfont
.lfEscapement
= esc
;
450 logfont
.lfOrientation
= orient
;
451 logfont
.lfWeight
= weight
;
452 logfont
.lfItalic
= italic
;
453 logfont
.lfUnderline
= underline
;
454 logfont
.lfStrikeOut
= strikeout
;
455 logfont
.lfCharSet
= charset
;
456 logfont
.lfOutPrecision
= outpres
;
457 logfont
.lfClipPrecision
= clippres
;
458 logfont
.lfQuality
= quality
;
459 logfont
.lfPitchAndFamily
= pitch
;
462 lstrcpynW(logfont
.lfFaceName
, name
,
463 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
465 logfont
.lfFaceName
[0] = '\0';
467 return CreateFontIndirectW( &logfont
);
470 static void update_font_code_page( DC
*dc
)
473 int charset
= DEFAULT_CHARSET
;
476 charset
= WineEngGetTextCharsetInfo( dc
->gdiFont
, NULL
, 0 );
478 /* Hmm, nicely designed api this one! */
479 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
480 dc
->font_code_page
= csi
.ciACP
;
484 dc
->font_code_page
= GetOEMCP();
486 case DEFAULT_CHARSET
:
487 dc
->font_code_page
= GetACP();
497 /* FIXME: These have no place here, but because x11drv
498 enumerates fonts with these (made up) charsets some apps
499 might use them and then the FIXME below would become
500 annoying. Now we could pick the intended codepage for
501 each of these, but since it's broken anyway we'll just
502 use CP_ACP and hope it'll go away...
504 dc
->font_code_page
= CP_ACP
;
508 FIXME("Can't find codepage for charset %d\n", charset
);
509 dc
->font_code_page
= CP_ACP
;
514 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
517 /***********************************************************************
520 * If the driver supports vector fonts we create a gdi font first and
521 * then call the driver to give it a chance to supply its own device
522 * font. If the driver wants to do this it returns TRUE and we can
523 * delete the gdi font, if the driver wants to use the gdi font it
524 * should return FALSE, to signal an error return GDI_ERROR. For
525 * drivers that don't support vector fonts they must supply their own
528 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
531 DC
*dc
= get_dc_ptr( hdc
);
536 if (!GDI_inc_ref_count( handle
))
538 release_dc_ptr( dc
);
542 if (GetDeviceCaps( dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
543 dc
->gdiFont
= WineEngCreateFontInstance( dc
, handle
);
545 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
546 ret
= physdev
->funcs
->pSelectFont( physdev
, handle
, dc
->gdiFont
);
548 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
550 if (ret
== HGDI_ERROR
)
552 GDI_dec_ref_count( handle
);
553 ret
= 0; /* SelectObject returns 0 on error */
559 update_font_code_page( dc
);
560 GDI_dec_ref_count( ret
);
562 release_dc_ptr( dc
);
567 /***********************************************************************
570 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
572 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
578 FONT_LogFontWToA( &font
->logfont
, &lfA
);
579 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
580 memcpy( buffer
, &lfA
, count
);
582 else count
= sizeof(lfA
);
583 GDI_ReleaseObj( handle
);
587 /***********************************************************************
590 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
592 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
597 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
598 memcpy( buffer
, &font
->logfont
, count
);
600 else count
= sizeof(LOGFONTW
);
601 GDI_ReleaseObj( handle
);
606 /***********************************************************************
609 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
613 WineEngDestroyFontInstance( handle
);
615 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
616 return HeapFree( GetProcessHeap(), 0, obj
);
620 /***********************************************************************
623 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
624 * We have to use other types because of the FONTENUMPROCW definition.
626 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
627 DWORD fType
, LPARAM lp
)
629 fontEnum32
*pfe
= (fontEnum32
*)lp
;
632 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
633 if ((!pfe
->lpLogFontParam
||
634 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
635 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
636 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
638 /* convert font metrics */
639 ENUMLOGFONTEXA logfont
;
640 NEWTEXTMETRICEXA tmA
;
642 pfe
->dwFlags
|= ENUM_CALLED
;
643 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
645 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
646 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
647 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
648 ptm
= (TEXTMETRICW
*)&tmA
;
651 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
656 /***********************************************************************
657 * FONT_EnumFontFamiliesEx
659 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
660 FONTENUMPROCW efproc
,
661 LPARAM lParam
, DWORD dwUnicode
)
664 DC
*dc
= get_dc_ptr( hDC
);
671 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
673 fe32
.lpLogFontParam
= plf
;
674 fe32
.lpEnumFunc
= efproc
;
675 fe32
.lpData
= lParam
;
676 fe32
.dwFlags
= dwUnicode
;
679 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
682 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
683 fe32
.dwFlags
&= ~ENUM_CALLED
;
686 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumDeviceFonts
);
687 ret2
= physdev
->funcs
->pEnumDeviceFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
688 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
691 release_dc_ptr( dc
);
695 /***********************************************************************
696 * EnumFontFamiliesExW (GDI32.@)
698 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
699 FONTENUMPROCW efproc
,
700 LPARAM lParam
, DWORD dwFlags
)
702 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
705 /***********************************************************************
706 * EnumFontFamiliesExA (GDI32.@)
708 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
709 FONTENUMPROCA efproc
,
710 LPARAM lParam
, DWORD dwFlags
)
716 FONT_LogFontAToW( plf
, &lfW
);
721 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
724 /***********************************************************************
725 * EnumFontFamiliesA (GDI32.@)
727 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
728 FONTENUMPROCA efproc
, LPARAM lpData
)
734 if (!*lpFamily
) return 1;
735 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
736 lf
.lfCharSet
= DEFAULT_CHARSET
;
737 lf
.lfPitchAndFamily
= 0;
742 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
745 /***********************************************************************
746 * EnumFontFamiliesW (GDI32.@)
748 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
749 FONTENUMPROCW efproc
, LPARAM lpData
)
755 if (!*lpFamily
) return 1;
756 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
757 lf
.lfCharSet
= DEFAULT_CHARSET
;
758 lf
.lfPitchAndFamily
= 0;
763 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
766 /***********************************************************************
767 * EnumFontsA (GDI32.@)
769 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
772 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
775 /***********************************************************************
776 * EnumFontsW (GDI32.@)
778 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
781 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
785 /***********************************************************************
786 * GetTextCharacterExtra (GDI32.@)
788 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
791 DC
*dc
= get_dc_ptr( hdc
);
792 if (!dc
) return 0x80000000;
794 release_dc_ptr( dc
);
799 /***********************************************************************
800 * SetTextCharacterExtra (GDI32.@)
802 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
804 INT ret
= 0x80000000;
805 DC
* dc
= get_dc_ptr( hdc
);
809 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
810 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
811 if (extra
!= 0x80000000)
814 dc
->charExtra
= extra
;
816 release_dc_ptr( dc
);
822 /***********************************************************************
823 * SetTextJustification (GDI32.@)
825 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
829 DC
* dc
= get_dc_ptr( hdc
);
831 if (!dc
) return FALSE
;
833 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
834 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
837 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
838 if (!extra
) breaks
= 0;
841 dc
->breakExtra
= extra
/ breaks
;
842 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
850 release_dc_ptr( dc
);
855 /***********************************************************************
856 * GetTextFaceA (GDI32.@)
858 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
860 INT res
= GetTextFaceW(hdc
, 0, NULL
);
861 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
862 GetTextFaceW( hdc
, res
, nameW
);
868 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
872 /* GetTextFaceA does NOT include the nul byte in the return count. */
879 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
880 HeapFree( GetProcessHeap(), 0, nameW
);
884 /***********************************************************************
885 * GetTextFaceW (GDI32.@)
887 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
892 DC
* dc
= get_dc_ptr( hdc
);
896 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
897 else if ((font
= GDI_GetObjPtr( dc
->hFont
, OBJ_FONT
)))
899 INT n
= strlenW(font
->logfont
.lfFaceName
) + 1;
902 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
906 GDI_ReleaseObj( dc
->hFont
);
908 release_dc_ptr( dc
);
913 /***********************************************************************
914 * GetTextExtentPoint32A (GDI32.@)
916 * See GetTextExtentPoint32W.
918 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
923 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
926 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
927 HeapFree( GetProcessHeap(), 0, p
);
930 TRACE("(%p %s %d %p): returning %d x %d\n",
931 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
936 /***********************************************************************
937 * GetTextExtentPoint32W [GDI32.@]
939 * Computes width/height for a string.
941 * Computes width and height of the specified string.
947 BOOL WINAPI
GetTextExtentPoint32W(
948 HDC hdc
, /* [in] Handle of device context */
949 LPCWSTR str
, /* [in] Address of text string */
950 INT count
, /* [in] Number of characters in string */
951 LPSIZE size
) /* [out] Address of structure for string size */
953 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
956 /***********************************************************************
957 * GetTextExtentExPointI [GDI32.@]
959 * Computes width and height of the array of glyph indices.
962 * hdc [I] Handle of device context.
963 * indices [I] Glyph index array.
964 * count [I] Number of glyphs in array.
965 * max_ext [I] Maximum width in glyphs.
966 * nfit [O] Maximum number of characters.
967 * dxs [O] Partial string widths.
968 * size [O] Returned string size.
974 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
975 LPINT nfit
, LPINT dxs
, LPSIZE size
)
978 DC
* dc
= get_dc_ptr( hdc
);
979 if (!dc
) return FALSE
;
982 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
983 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
984 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
985 size
->cx
+= count
* dc
->charExtra
;
989 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
990 FIXME("calling GetTextExtentExPoint\n");
991 ret
= physdev
->funcs
->pGetTextExtentExPoint( physdev
, indices
, count
, max_ext
, nfit
, dxs
, size
);
994 release_dc_ptr( dc
);
996 TRACE("(%p %p %d %p): returning %d x %d\n",
997 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1001 /***********************************************************************
1002 * GetTextExtentPointI [GDI32.@]
1004 * Computes width and height of the array of glyph indices.
1007 * hdc [I] Handle of device context.
1008 * indices [I] Glyph index array.
1009 * count [I] Number of glyphs in array.
1010 * size [O] Returned string size.
1016 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1018 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1022 /***********************************************************************
1023 * GetTextExtentPointA (GDI32.@)
1025 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1028 TRACE("not bug compatible.\n");
1029 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1032 /***********************************************************************
1033 * GetTextExtentPointW (GDI32.@)
1035 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1038 TRACE("not bug compatible.\n");
1039 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1043 /***********************************************************************
1044 * GetTextExtentExPointA (GDI32.@)
1046 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1047 INT maxExt
, LPINT lpnFit
,
1048 LPINT alpDx
, LPSIZE size
)
1056 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1059 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1060 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1063 INT n
= lpnFit
? *lpnFit
: wlen
;
1065 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1067 alpDx
[j
] = walpDx
[i
];
1068 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1071 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1072 HeapFree( GetProcessHeap(), 0, p
);
1073 HeapFree( GetProcessHeap(), 0, walpDx
);
1078 /***********************************************************************
1079 * GetTextExtentExPointW (GDI32.@)
1081 * Return the size of the string as it would be if it was output properly by
1084 * This should include
1085 * - Intercharacter spacing
1086 * - justification spacing (not yet done)
1087 * - kerning? see below
1089 * Kerning. Since kerning would be carried out by the rendering code it should
1090 * be done by the driver. However they don't support it yet. Also I am not
1091 * yet persuaded that (certainly under Win95) any kerning is actually done.
1093 * str: According to MSDN this should be null-terminated. That is not true; a
1094 * null will not terminate it early.
1095 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1096 * than count. I have seen it be either the size of the full string or
1097 * 1 less than the size of the full string. I have not seen it bear any
1098 * resemblance to the portion that would fit.
1099 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1100 * trailing intercharacter spacing and any trailing justification.
1103 * Currently we do this by measuring each character etc. We should do it by
1104 * passing the request to the driver, perhaps by extending the
1105 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1106 * thinking about kerning issues and rounding issues in the justification.
1109 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1110 INT maxExt
, LPINT lpnFit
,
1111 LPINT alpDx
, LPSIZE size
)
1119 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1121 dc
= get_dc_ptr(hdc
);
1125 GetTextMetricsW(hdc
, &tm
);
1127 /* If we need to calculate nFit, then we need the partial extents even if
1128 the user hasn't provided us with an array. */
1131 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1135 SetLastError(ERROR_OUTOFMEMORY
);
1143 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1144 0, NULL
, dxs
, size
);
1147 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
1148 ret
= physdev
->funcs
->pGetTextExtentExPoint(physdev
, str
, count
, 0, NULL
, dxs
, size
);
1151 /* Perform device size to world size transformations. */
1154 INT extra
= dc
->charExtra
,
1155 breakExtra
= dc
->breakExtra
,
1156 breakRem
= dc
->breakRem
,
1161 for (i
= 0; i
< count
; ++i
)
1163 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1164 dxs
[i
] += (i
+1) * extra
;
1165 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1167 dxs
[i
] += breakExtra
;
1174 if (dxs
[i
] <= maxExt
)
1177 breakRem
= dc
->breakRem
;
1179 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1180 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1182 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1184 for (i
= 0; i
< count
; i
++)
1186 if (str
[i
] == tm
.tmBreakChar
)
1188 size
->cx
+= breakExtra
;
1203 HeapFree(GetProcessHeap(), 0, dxs
);
1205 release_dc_ptr( dc
);
1207 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1211 /***********************************************************************
1212 * GetTextMetricsA (GDI32.@)
1214 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1218 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1219 FONT_TextMetricWToA( &tm32
, metrics
);
1223 /***********************************************************************
1224 * GetTextMetricsW (GDI32.@)
1226 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1229 DC
* dc
= get_dc_ptr( hdc
);
1230 if (!dc
) return FALSE
;
1233 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1236 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1237 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1242 /* device layer returns values in device units
1243 * therefore we have to convert them to logical */
1245 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1246 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1248 #define WDPTOLP(x) ((x<0)? \
1249 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1250 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1251 #define HDPTOLP(y) ((y<0)? \
1252 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1253 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1255 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1256 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1257 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1258 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1259 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1260 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1261 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1262 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1266 TRACE("text metrics:\n"
1267 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1268 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1269 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1270 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1271 " PitchAndFamily = %02x\n"
1272 " --------------------\n"
1273 " InternalLeading = %i\n"
1277 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1278 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1279 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1280 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1281 metrics
->tmPitchAndFamily
,
1282 metrics
->tmInternalLeading
,
1285 metrics
->tmHeight
);
1287 release_dc_ptr( dc
);
1292 /***********************************************************************
1293 * GetOutlineTextMetricsA (GDI32.@)
1294 * Gets metrics for TrueType fonts.
1297 * If the supplied buffer isn't big enough Windows partially fills it up to
1298 * its given length and returns that length.
1301 * Success: Non-zero or size of required buffer
1304 UINT WINAPI
GetOutlineTextMetricsA(
1305 HDC hdc
, /* [in] Handle of device context */
1306 UINT cbData
, /* [in] Size of metric data array */
1307 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1309 char buf
[512], *ptr
;
1311 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1312 OUTLINETEXTMETRICA
*output
= lpOTM
;
1315 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1317 if(ret
> sizeof(buf
))
1318 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1319 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1321 needed
= sizeof(OUTLINETEXTMETRICA
);
1322 if(lpOTMW
->otmpFamilyName
)
1323 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1324 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1325 NULL
, 0, NULL
, NULL
);
1326 if(lpOTMW
->otmpFaceName
)
1327 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1328 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1329 NULL
, 0, NULL
, NULL
);
1330 if(lpOTMW
->otmpStyleName
)
1331 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1332 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1333 NULL
, 0, NULL
, NULL
);
1334 if(lpOTMW
->otmpFullName
)
1335 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1336 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1337 NULL
, 0, NULL
, NULL
);
1344 TRACE("needed = %d\n", needed
);
1346 /* Since the supplied buffer isn't big enough, we'll alloc one
1347 that is and memcpy the first cbData bytes into the lpOTM at
1349 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1351 ret
= output
->otmSize
= min(needed
, cbData
);
1352 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1353 output
->otmFiller
= 0;
1354 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1355 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1356 output
->otmfsType
= lpOTMW
->otmfsType
;
1357 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1358 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1359 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1360 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1361 output
->otmAscent
= lpOTMW
->otmAscent
;
1362 output
->otmDescent
= lpOTMW
->otmDescent
;
1363 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1364 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1365 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1366 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1367 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1368 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1369 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1370 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1371 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1372 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1373 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1374 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1375 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1376 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1377 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1378 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1381 ptr
= (char*)(output
+ 1);
1382 left
= needed
- sizeof(*output
);
1384 if(lpOTMW
->otmpFamilyName
) {
1385 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1386 len
= WideCharToMultiByte(CP_ACP
, 0,
1387 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1388 ptr
, left
, NULL
, NULL
);
1392 output
->otmpFamilyName
= 0;
1394 if(lpOTMW
->otmpFaceName
) {
1395 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1396 len
= WideCharToMultiByte(CP_ACP
, 0,
1397 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1398 ptr
, left
, NULL
, NULL
);
1402 output
->otmpFaceName
= 0;
1404 if(lpOTMW
->otmpStyleName
) {
1405 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1406 len
= WideCharToMultiByte(CP_ACP
, 0,
1407 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1408 ptr
, left
, NULL
, NULL
);
1412 output
->otmpStyleName
= 0;
1414 if(lpOTMW
->otmpFullName
) {
1415 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1416 len
= WideCharToMultiByte(CP_ACP
, 0,
1417 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1418 ptr
, left
, NULL
, NULL
);
1421 output
->otmpFullName
= 0;
1425 if(output
!= lpOTM
) {
1426 memcpy(lpOTM
, output
, cbData
);
1427 HeapFree(GetProcessHeap(), 0, output
);
1429 /* check if the string offsets really fit into the provided size */
1430 /* FIXME: should we check string length as well? */
1431 /* make sure that we don't read/write beyond the provided buffer */
1432 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1434 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1435 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1438 /* make sure that we don't read/write beyond the provided buffer */
1439 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1441 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1442 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1445 /* make sure that we don't read/write beyond the provided buffer */
1446 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1448 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1449 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1452 /* make sure that we don't read/write beyond the provided buffer */
1453 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1455 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1456 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1461 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1462 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1468 /***********************************************************************
1469 * GetOutlineTextMetricsW [GDI32.@]
1471 UINT WINAPI
GetOutlineTextMetricsW(
1472 HDC hdc
, /* [in] Handle of device context */
1473 UINT cbData
, /* [in] Size of metric data array */
1474 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1476 DC
*dc
= get_dc_ptr( hdc
);
1477 OUTLINETEXTMETRICW
*output
= lpOTM
;
1480 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1484 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1487 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1488 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1491 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1492 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1494 #define WDPTOLP(x) ((x<0)? \
1495 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1496 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1497 #define HDPTOLP(y) ((y<0)? \
1498 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1499 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1501 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1502 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1503 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1504 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1505 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1506 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1507 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1508 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1509 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1510 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1511 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1512 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1513 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1514 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1515 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1516 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1517 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1518 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1519 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1520 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1521 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1522 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1523 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1524 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1525 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1526 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1527 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1528 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1529 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1530 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1531 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1532 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1535 if(output
!= lpOTM
) {
1536 memcpy(lpOTM
, output
, cbData
);
1537 HeapFree(GetProcessHeap(), 0, output
);
1543 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1544 but really this should just be a return 0. */
1546 ret
= sizeof(*lpOTM
);
1551 memset(lpOTM
, 0, ret
);
1552 lpOTM
->otmSize
= sizeof(*lpOTM
);
1553 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1555 Further fill of the structure not implemented,
1556 Needs real values for the structure members
1565 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1567 INT i
, count
= lastChar
- firstChar
+ 1;
1574 switch (GdiGetCodePage(hdc
))
1581 if (lastChar
> 0xffff)
1583 if ((firstChar
^ lastChar
) > 0xff)
1587 if (lastChar
> 0xff)
1592 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1596 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1599 str
[i
++] = (BYTE
)(c
>> 8);
1609 /***********************************************************************
1610 * GetCharWidthW (GDI32.@)
1611 * GetCharWidth32W (GDI32.@)
1613 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1618 DC
* dc
= get_dc_ptr( hdc
);
1619 if (!dc
) return FALSE
;
1622 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1625 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1626 ret
= physdev
->funcs
->pGetCharWidth( physdev
, firstChar
, lastChar
, buffer
);
1631 /* convert device units to logical */
1632 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1633 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1636 release_dc_ptr( dc
);
1641 /***********************************************************************
1642 * GetCharWidthA (GDI32.@)
1643 * GetCharWidth32A (GDI32.@)
1645 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1653 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1657 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1659 for(i
= 0; i
< wlen
; i
++)
1661 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1669 HeapFree(GetProcessHeap(), 0, str
);
1670 HeapFree(GetProcessHeap(), 0, wstr
);
1676 /***********************************************************************
1677 * ExtTextOutA (GDI32.@)
1681 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1682 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1690 if (flags
& ETO_GLYPH_INDEX
)
1691 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1693 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1696 unsigned int i
= 0, j
= 0;
1698 /* allocate enough for a ETO_PDY */
1699 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1701 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1705 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1706 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1709 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1716 lpDxW
[j
++] = lpDx
[i
* 2];
1717 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1720 lpDxW
[j
++] = lpDx
[i
];
1726 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1728 HeapFree( GetProcessHeap(), 0, p
);
1729 HeapFree( GetProcessHeap(), 0, lpDxW
);
1734 /***********************************************************************
1735 * ExtTextOutW (GDI32.@)
1737 * Draws text using the currently selected font, background color, and text color.
1741 * x,y [I] coordinates of string
1743 * ETO_GRAYED - undocumented on MSDN
1744 * ETO_OPAQUE - use background color for fill the rectangle
1745 * ETO_CLIPPED - clipping text to the rectangle
1746 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1747 * than encoded characters. Implies ETO_IGNORELANGUAGE
1748 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1749 * Affects BiDi ordering
1750 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1751 * ETO_PDY - unimplemented
1752 * ETO_NUMERICSLATIN - unimplemented always assumed -
1753 * do not translate numbers into locale representations
1754 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1755 * lprect [I] dimensions for clipping or/and opaquing
1756 * str [I] text string
1757 * count [I] number of symbols in string
1758 * lpDx [I] optional parameter with distance between drawing characters
1764 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1765 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1768 LPWSTR reordered_str
= (LPWSTR
)str
;
1769 WORD
*glyphs
= NULL
;
1770 UINT align
= GetTextAlign( hdc
);
1771 DWORD layout
= GetLayout( hdc
);
1775 double cosEsc
, sinEsc
;
1779 BOOL done_extents
= FALSE
;
1780 POINT
*deltas
= NULL
, width
= {0, 0};
1782 DC
* dc
= get_dc_ptr( hdc
);
1785 static int quietfixme
= 0;
1787 if (!dc
) return FALSE
;
1789 breakRem
= dc
->breakRem
;
1791 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1793 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1798 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
1799 type
= GetObjectType(hdc
);
1800 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1802 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1803 release_dc_ptr( dc
);
1808 flags
&= ~ETO_CLIPPED
;
1810 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
1811 if (layout
& LAYOUT_RTL
)
1813 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
1814 align
^= TA_RTLREADING
;
1817 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1820 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1822 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1823 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
1824 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1826 flags
|= ETO_IGNORELANGUAGE
;
1829 flags
|= ETO_GLYPH_INDEX
;
1830 if (cGlyphs
!= count
)
1834 else if(flags
& ETO_GLYPH_INDEX
)
1835 glyphs
= reordered_str
;
1837 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1838 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
1839 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1841 if(align
& TA_UPDATECP
)
1843 GetCurrentPositionEx( hdc
, &pt
);
1848 GetTextMetricsW(hdc
, &tm
);
1849 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1851 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1852 lf
.lfEscapement
= 0;
1854 if(lf
.lfEscapement
!= 0)
1856 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1857 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1865 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1869 if(flags
& ETO_GLYPH_INDEX
)
1870 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1872 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1874 done_extents
= TRUE
;
1877 rc
.right
= x
+ sz
.cx
;
1878 rc
.bottom
= y
+ sz
.cy
;
1885 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1887 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1888 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1891 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1892 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1902 LPtoDP(hdc
, &pt
, 1);
1906 char_extra
= GetTextCharacterExtra(hdc
);
1907 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1911 POINT total
= {0, 0}, desired
[2];
1913 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1914 for(i
= 0; i
< count
; i
++)
1920 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1921 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1925 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1932 if(flags
& ETO_GLYPH_INDEX
)
1933 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1935 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1937 deltas
[i
].x
= tmpsz
.cx
;
1941 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1943 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1950 total
.x
+= deltas
[i
].x
;
1951 total
.y
+= deltas
[i
].y
;
1953 desired
[0].x
= desired
[0].y
= 0;
1955 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1956 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1958 LPtoDP(hdc
, desired
, 2);
1959 desired
[1].x
-= desired
[0].x
;
1960 desired
[1].y
-= desired
[0].y
;
1961 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
1963 deltas
[i
].x
= desired
[1].x
- width
.x
;
1964 deltas
[i
].y
= desired
[1].y
- width
.y
;
1974 if(flags
& ETO_GLYPH_INDEX
)
1975 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1977 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1978 done_extents
= TRUE
;
1980 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
1984 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1985 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1986 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1989 if (align
& TA_UPDATECP
)
1993 DPtoLP(hdc
, &pt
, 1);
1994 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2006 if (align
& TA_UPDATECP
)
2010 DPtoLP(hdc
, &pt
, 1);
2011 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2016 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2019 y
+= tm
.tmAscent
* cosEsc
;
2020 x
+= tm
.tmAscent
* sinEsc
;
2024 y
-= tm
.tmDescent
* cosEsc
;
2025 x
-= tm
.tmDescent
* sinEsc
;
2032 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2034 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2036 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2037 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2041 rc
.right
= x
+ width
.x
;
2042 rc
.top
= y
- tm
.tmAscent
;
2043 rc
.bottom
= y
+ tm
.tmDescent
;
2045 if(flags
& ETO_CLIPPED
)
2047 rc
.left
= max(lprect
->left
, rc
.left
);
2048 rc
.right
= min(lprect
->right
, rc
.right
);
2049 rc
.top
= max(lprect
->top
, rc
.top
);
2050 rc
.bottom
= min(lprect
->bottom
, rc
.bottom
);
2052 if(rc
.left
< rc
.right
&& rc
.top
< rc
.bottom
)
2053 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2058 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2060 HFONT orig_font
= dc
->hFont
, cur_font
;
2063 POINT
*offsets
= NULL
;
2066 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2067 for(i
= 0; i
< count
; i
++)
2069 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2070 if(cur_font
!= dc
->hFont
)
2075 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2076 offsets
[0].x
= offsets
[0].y
= 0;
2081 for(j
= 1; j
< count
; j
++)
2083 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2084 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2090 for(j
= 1; j
< count
; j
++)
2092 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2093 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2099 if (PATH_IsPathOpen(dc
->path
))
2100 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2101 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2102 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2104 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2105 y
+ offsets
[i
- span
].y
,
2106 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2107 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2110 SelectObject(hdc
, cur_font
);
2112 glyphs
[span
++] = glyph
;
2116 if (PATH_IsPathOpen(dc
->path
))
2117 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2118 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2119 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2120 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2122 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2123 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2124 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2125 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2126 SelectObject(hdc
, orig_font
);
2127 HeapFree(GetProcessHeap(), 0, offsets
);
2133 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2135 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2136 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2137 flags
|= ETO_GLYPH_INDEX
;
2140 if (PATH_IsPathOpen(dc
->path
))
2141 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2142 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2144 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2145 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2149 HeapFree(GetProcessHeap(), 0, deltas
);
2150 if(glyphs
!= reordered_str
)
2151 HeapFree(GetProcessHeap(), 0, glyphs
);
2152 if(reordered_str
!= str
)
2153 HeapFree(GetProcessHeap(), 0, reordered_str
);
2155 release_dc_ptr( dc
);
2157 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2159 int underlinePos
, strikeoutPos
;
2160 int underlineWidth
, strikeoutWidth
;
2161 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2162 OUTLINETEXTMETRICW
* otm
= NULL
;
2167 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2168 strikeoutPos
= tm
.tmAscent
/ 2;
2169 strikeoutWidth
= underlineWidth
;
2173 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2174 GetOutlineTextMetricsW(hdc
, size
, otm
);
2175 underlinePos
= otm
->otmsUnderscorePosition
;
2176 underlineWidth
= otm
->otmsUnderscoreSize
;
2177 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2178 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2179 HeapFree(GetProcessHeap(), 0, otm
);
2182 if (PATH_IsPathOpen(dc
->path
))
2186 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2188 hbrush
= SelectObject(hdc
, hbrush
);
2189 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2193 pts
[0].x
= x
- underlinePos
* sinEsc
;
2194 pts
[0].y
= y
- underlinePos
* cosEsc
;
2195 pts
[1].x
= x
+ width
.x
- underlinePos
* sinEsc
;
2196 pts
[1].y
= y
+ width
.y
- underlinePos
* cosEsc
;
2197 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2198 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2199 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2200 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2201 pts
[4].x
= pts
[0].x
;
2202 pts
[4].y
= pts
[0].y
;
2203 DPtoLP(hdc
, pts
, 5);
2204 Polygon(hdc
, pts
, 5);
2209 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2210 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2211 pts
[1].x
= x
+ width
.x
- strikeoutPos
* sinEsc
;
2212 pts
[1].y
= y
+ width
.y
- strikeoutPos
* cosEsc
;
2213 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2214 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2215 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2216 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2217 pts
[4].x
= pts
[0].x
;
2218 pts
[4].y
= pts
[0].y
;
2219 DPtoLP(hdc
, pts
, 5);
2220 Polygon(hdc
, pts
, 5);
2223 SelectObject(hdc
, hpen
);
2224 hbrush
= SelectObject(hdc
, hbrush
);
2225 DeleteObject(hbrush
);
2229 POINT pts
[2], oldpt
;
2234 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2235 hpen
= SelectObject(hdc
, hpen
);
2238 pts
[1].x
= x
+ width
.x
;
2239 pts
[1].y
= y
+ width
.y
;
2240 DPtoLP(hdc
, pts
, 2);
2241 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2242 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2243 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2244 DeleteObject(SelectObject(hdc
, hpen
));
2249 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2250 hpen
= SelectObject(hdc
, hpen
);
2253 pts
[1].x
= x
+ width
.x
;
2254 pts
[1].y
= y
+ width
.y
;
2255 DPtoLP(hdc
, pts
, 2);
2256 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2257 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2258 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2259 DeleteObject(SelectObject(hdc
, hpen
));
2268 /***********************************************************************
2269 * TextOutA (GDI32.@)
2271 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2273 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2277 /***********************************************************************
2278 * TextOutW (GDI32.@)
2280 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2282 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2286 /***********************************************************************
2287 * PolyTextOutA (GDI32.@)
2291 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2293 for (; cStrings
>0; cStrings
--, pptxt
++)
2294 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2301 /***********************************************************************
2302 * PolyTextOutW (GDI32.@)
2304 * Draw several Strings
2310 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2312 for (; cStrings
>0; cStrings
--, pptxt
++)
2313 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2319 /***********************************************************************
2320 * SetMapperFlags (GDI32.@)
2322 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2324 DC
*dc
= get_dc_ptr( hdc
);
2325 DWORD ret
= GDI_ERROR
;
2329 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2330 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2331 if (flags
!= GDI_ERROR
)
2333 ret
= dc
->mapperFlags
;
2334 dc
->mapperFlags
= flags
;
2336 release_dc_ptr( dc
);
2341 /***********************************************************************
2342 * GetAspectRatioFilterEx (GDI32.@)
2344 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2346 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2351 /***********************************************************************
2352 * GetCharABCWidthsA (GDI32.@)
2354 * See GetCharABCWidthsW.
2356 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2364 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2368 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2371 HeapFree(GetProcessHeap(), 0, str
);
2375 for(i
= 0; i
< wlen
; i
++)
2377 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2385 HeapFree(GetProcessHeap(), 0, str
);
2386 HeapFree(GetProcessHeap(), 0, wstr
);
2392 /******************************************************************************
2393 * GetCharABCWidthsW [GDI32.@]
2395 * Retrieves widths of characters in range.
2398 * hdc [I] Handle of device context
2399 * firstChar [I] First character in range to query
2400 * lastChar [I] Last character in range to query
2401 * abc [O] Address of character-width structure
2404 * Only works with TrueType fonts
2410 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2413 DC
*dc
= get_dc_ptr(hdc
);
2417 if (!dc
) return FALSE
;
2421 release_dc_ptr( dc
);
2426 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2432 /* convert device units to logical */
2433 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2434 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2435 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2436 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2441 release_dc_ptr( dc
);
2446 /******************************************************************************
2447 * GetCharABCWidthsI [GDI32.@]
2449 * Retrieves widths of characters in range.
2452 * hdc [I] Handle of device context
2453 * firstChar [I] First glyphs in range to query
2454 * count [I] Last glyphs in range to query
2455 * pgi [i] Array of glyphs to query
2456 * abc [O] Address of character-width structure
2459 * Only works with TrueType fonts
2465 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2466 LPWORD pgi
, LPABC abc
)
2468 DC
*dc
= get_dc_ptr(hdc
);
2472 if (!dc
) return FALSE
;
2476 release_dc_ptr( dc
);
2481 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2487 /* convert device units to logical */
2488 for( i
= 0; i
< count
; i
++, abc
++ ) {
2489 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2490 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2491 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2496 release_dc_ptr( dc
);
2501 /***********************************************************************
2502 * GetGlyphOutlineA (GDI32.@)
2504 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2505 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2506 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2508 if (!lpmat2
) return GDI_ERROR
;
2510 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2515 cp
= GdiGetCodePage(hdc
);
2516 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2518 mbchs
[0] = (uChar
& 0xff00) >> 8;
2519 mbchs
[1] = (uChar
& 0xff);
2522 mbchs
[0] = (uChar
& 0xff);
2524 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2527 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2531 /***********************************************************************
2532 * GetGlyphOutlineW (GDI32.@)
2534 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2535 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2536 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2541 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2542 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2544 if (!lpmat2
) return GDI_ERROR
;
2546 dc
= get_dc_ptr(hdc
);
2547 if(!dc
) return GDI_ERROR
;
2550 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2551 cbBuffer
, lpBuffer
, lpmat2
);
2555 release_dc_ptr( dc
);
2560 /***********************************************************************
2561 * CreateScalableFontResourceA (GDI32.@)
2563 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2564 LPCSTR lpszResourceFile
,
2565 LPCSTR lpszFontFile
,
2566 LPCSTR lpszCurrentPath
)
2568 LPWSTR lpszResourceFileW
= NULL
;
2569 LPWSTR lpszFontFileW
= NULL
;
2570 LPWSTR lpszCurrentPathW
= NULL
;
2574 if (lpszResourceFile
)
2576 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2577 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2578 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2583 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2584 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2585 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2588 if (lpszCurrentPath
)
2590 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2591 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2592 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2595 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2596 lpszFontFileW
, lpszCurrentPathW
);
2598 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2599 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2600 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2605 /***********************************************************************
2606 * CreateScalableFontResourceW (GDI32.@)
2608 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2609 LPCWSTR lpszResourceFile
,
2610 LPCWSTR lpszFontFile
,
2611 LPCWSTR lpszCurrentPath
)
2614 FIXME("(%d,%s,%s,%s): stub\n",
2615 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2616 debugstr_w(lpszCurrentPath
) );
2618 /* fHidden=1 - only visible for the calling app, read-only, not
2619 * enumerated with EnumFonts/EnumFontFamilies
2620 * lpszCurrentPath can be NULL
2623 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2624 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2626 SetLastError(ERROR_FILE_EXISTS
);
2629 return FALSE
; /* create failed */
2632 /*************************************************************************
2633 * GetKerningPairsA (GDI32.@)
2635 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2636 LPKERNINGPAIR kern_pairA
)
2640 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2641 KERNINGPAIR
*kern_pairW
;
2643 if (!cPairs
&& kern_pairA
)
2645 SetLastError(ERROR_INVALID_PARAMETER
);
2649 cp
= GdiGetCodePage(hDC
);
2651 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2652 * to fail on an invalid character for CP_SYMBOL.
2654 cpi
.DefaultChar
[0] = 0;
2655 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2657 FIXME("Can't find codepage %u info\n", cp
);
2661 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2662 if (!total_kern_pairs
) return 0;
2664 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2665 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2667 for (i
= 0; i
< total_kern_pairs
; i
++)
2671 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2674 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2677 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2682 if (kern_pairs_copied
>= cPairs
) break;
2684 kern_pairA
->wFirst
= (BYTE
)first
;
2685 kern_pairA
->wSecond
= (BYTE
)second
;
2686 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2689 kern_pairs_copied
++;
2692 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2694 return kern_pairs_copied
;
2697 /*************************************************************************
2698 * GetKerningPairsW (GDI32.@)
2700 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2701 LPKERNINGPAIR lpKerningPairs
)
2706 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2708 if (!cPairs
&& lpKerningPairs
)
2710 SetLastError(ERROR_INVALID_PARAMETER
);
2714 dc
= get_dc_ptr(hDC
);
2718 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2720 release_dc_ptr( dc
);
2724 /*************************************************************************
2725 * TranslateCharsetInfo [GDI32.@]
2727 * Fills a CHARSETINFO structure for a character set, code page, or
2728 * font. This allows making the correspondence between different labels
2729 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2730 * of the same encoding.
2732 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2733 * only one codepage should be set in *lpSrc.
2736 * TRUE on success, FALSE on failure.
2739 BOOL WINAPI
TranslateCharsetInfo(
2740 LPDWORD lpSrc
, /* [in]
2741 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2742 if flags == TCI_SRCCHARSET: a character set value
2743 if flags == TCI_SRCCODEPAGE: a code page value
2745 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2746 DWORD flags
/* [in] determines interpretation of lpSrc */)
2750 case TCI_SRCFONTSIG
:
2751 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2753 case TCI_SRCCODEPAGE
:
2754 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2756 case TCI_SRCCHARSET
:
2757 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2762 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2763 *lpCs
= FONT_tci
[index
];
2767 /*************************************************************************
2768 * GetFontLanguageInfo (GDI32.@)
2770 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2772 FONTSIGNATURE fontsig
;
2773 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2774 GCP_DIACRITIC_MASK
=0x00000000,
2775 FLI_GLYPHS_MASK
=0x00000000,
2776 GCP_GLYPHSHAPE_MASK
=0x00000040,
2777 GCP_KASHIDA_MASK
=0x00000000,
2778 GCP_LIGATE_MASK
=0x00000000,
2779 GCP_USEKERNING_MASK
=0x00000000,
2780 GCP_REORDER_MASK
=0x00000060;
2784 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2785 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2787 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2790 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2791 result
|=GCP_DIACRITIC
;
2793 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2796 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2797 result
|=GCP_GLYPHSHAPE
;
2799 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2800 result
|=GCP_KASHIDA
;
2802 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2805 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2806 result
|=GCP_USEKERNING
;
2808 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2809 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2810 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2811 result
|=GCP_REORDER
;
2817 /*************************************************************************
2818 * GetFontData [GDI32.@]
2820 * Retrieve data for TrueType font.
2824 * success: Number of bytes returned
2825 * failure: GDI_ERROR
2829 * Calls SetLastError()
2832 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2833 LPVOID buffer
, DWORD length
)
2835 DC
*dc
= get_dc_ptr(hdc
);
2836 DWORD ret
= GDI_ERROR
;
2838 if(!dc
) return GDI_ERROR
;
2841 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2843 release_dc_ptr( dc
);
2847 /*************************************************************************
2848 * GetGlyphIndicesA [GDI32.@]
2850 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2851 LPWORD pgi
, DWORD flags
)
2857 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2858 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2860 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2861 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2862 HeapFree(GetProcessHeap(), 0, lpstrW
);
2867 /*************************************************************************
2868 * GetGlyphIndicesW [GDI32.@]
2870 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2871 LPWORD pgi
, DWORD flags
)
2873 DC
*dc
= get_dc_ptr(hdc
);
2874 DWORD ret
= GDI_ERROR
;
2876 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2877 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2879 if(!dc
) return GDI_ERROR
;
2882 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2884 release_dc_ptr( dc
);
2888 /*************************************************************************
2889 * GetCharacterPlacementA [GDI32.@]
2891 * See GetCharacterPlacementW.
2894 * the web browser control of ie4 calls this with dwFlags=0
2897 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2898 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2903 GCP_RESULTSW resultsW
;
2907 TRACE("%s, %d, %d, 0x%08x\n",
2908 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2910 /* both structs are equal in size */
2911 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2913 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2914 if(lpResults
->lpOutString
)
2915 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2917 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2919 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2920 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2922 if(lpResults
->lpOutString
) {
2923 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2924 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2927 HeapFree(GetProcessHeap(), 0, lpStringW
);
2928 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2933 /*************************************************************************
2934 * GetCharacterPlacementW [GDI32.@]
2936 * Retrieve information about a string. This includes the width, reordering,
2937 * Glyphing and so on.
2941 * The width and height of the string if successful, 0 if failed.
2945 * All flags except GCP_REORDER are not yet implemented.
2946 * Reordering is not 100% compliant to the Windows BiDi method.
2947 * Caret positioning is not yet implemented for BiDi.
2948 * Classes are not yet implemented.
2952 GetCharacterPlacementW(
2953 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2954 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2955 INT uCount
, /* [in] Number of WORDS in string. */
2956 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2957 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2958 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2965 TRACE("%s, %d, %d, 0x%08x\n",
2966 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2968 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2969 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2970 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2971 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2972 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2974 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2975 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2976 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2977 FIXME("Caret positions for complex scripts not implemented\n");
2979 nSet
= (UINT
)uCount
;
2980 if(nSet
> lpResults
->nGlyphs
)
2981 nSet
= lpResults
->nGlyphs
;
2983 /* return number of initialized fields */
2984 lpResults
->nGlyphs
= nSet
;
2986 if((dwFlags
&GCP_REORDER
)==0 )
2988 /* Treat the case where no special handling was requested in a fastpath way */
2989 /* copy will do if the GCP_REORDER flag is not set */
2990 if(lpResults
->lpOutString
)
2991 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2993 if(lpResults
->lpOrder
)
2995 for(i
= 0; i
< nSet
; i
++)
2996 lpResults
->lpOrder
[i
] = i
;
3000 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3001 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3004 /* FIXME: Will use the placement chars */
3005 if (lpResults
->lpDx
)
3008 for (i
= 0; i
< nSet
; i
++)
3010 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3011 lpResults
->lpDx
[i
]= c
;
3015 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3019 lpResults
->lpCaretPos
[0] = 0;
3020 for (i
= 1; i
< nSet
; i
++)
3021 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3022 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3025 if(lpResults
->lpGlyphs
)
3026 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3028 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3029 ret
= MAKELONG(size
.cx
, size
.cy
);
3034 /*************************************************************************
3035 * GetCharABCWidthsFloatA [GDI32.@]
3037 * See GetCharABCWidthsFloatW.
3039 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3046 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3050 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3052 for (i
= 0; i
< wlen
; i
++)
3054 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3062 HeapFree( GetProcessHeap(), 0, str
);
3063 HeapFree( GetProcessHeap(), 0, wstr
);
3068 /*************************************************************************
3069 * GetCharABCWidthsFloatW [GDI32.@]
3071 * Retrieves widths of a range of characters.
3074 * hdc [I] Handle to device context.
3075 * first [I] First character in range to query.
3076 * last [I] Last character in range to query.
3077 * abcf [O] Array of LPABCFLOAT structures.
3083 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3087 DC
*dc
= get_dc_ptr( hdc
);
3089 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3091 if (!dc
) return FALSE
;
3095 release_dc_ptr( dc
);
3100 ret
= WineEngGetCharABCWidthsFloat( dc
->gdiFont
, first
, last
, abcf
);
3106 /* convert device units to logical */
3107 for (i
= first
; i
<= last
; i
++, abcf
++)
3109 abcf
->abcfA
= abcf
->abcfA
* dc
->xformVport2World
.eM11
;
3110 abcf
->abcfB
= abcf
->abcfB
* dc
->xformVport2World
.eM11
;
3111 abcf
->abcfC
= abcf
->abcfC
* dc
->xformVport2World
.eM11
;
3115 release_dc_ptr( dc
);
3119 /*************************************************************************
3120 * GetCharWidthFloatA [GDI32.@]
3122 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3123 UINT iLastChar
, PFLOAT pxBuffer
)
3125 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3129 /*************************************************************************
3130 * GetCharWidthFloatW [GDI32.@]
3132 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3133 UINT iLastChar
, PFLOAT pxBuffer
)
3135 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3140 /***********************************************************************
3142 * Font Resource API *
3144 ***********************************************************************/
3146 /***********************************************************************
3147 * AddFontResourceA (GDI32.@)
3149 INT WINAPI
AddFontResourceA( LPCSTR str
)
3151 return AddFontResourceExA( str
, 0, NULL
);
3154 /***********************************************************************
3155 * AddFontResourceW (GDI32.@)
3157 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3159 return AddFontResourceExW(str
, 0, NULL
);
3163 /***********************************************************************
3164 * AddFontResourceExA (GDI32.@)
3166 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3168 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3169 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3172 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3173 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3174 HeapFree(GetProcessHeap(), 0, strW
);
3178 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3180 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3181 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3182 LPVOID
*pMem
= LockResource(hMem
);
3183 int *num_total
= (int *)lParam
;
3186 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3187 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3189 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3193 *num_total
+= num_in_res
;
3197 /***********************************************************************
3198 * AddFontResourceExW (GDI32.@)
3200 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3202 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3205 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3206 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3207 if (hModule
!= NULL
)
3209 int num_resources
= 0;
3210 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3212 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3213 wine_dbgstr_w(str
));
3214 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3215 ret
= num_resources
;
3216 FreeLibrary(hModule
);
3222 /***********************************************************************
3223 * RemoveFontResourceA (GDI32.@)
3225 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3227 return RemoveFontResourceExA(str
, 0, 0);
3230 /***********************************************************************
3231 * RemoveFontResourceW (GDI32.@)
3233 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3235 return RemoveFontResourceExW(str
, 0, 0);
3238 /***********************************************************************
3239 * AddFontMemResourceEx (GDI32.@)
3241 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3246 if (!pbFont
|| !cbFont
|| !pcFonts
)
3248 SetLastError(ERROR_INVALID_PARAMETER
);
3252 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3257 *pcFonts
= num_fonts
;
3261 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3262 RemoveFontMemResourceEx(ret
);
3270 /***********************************************************************
3271 * RemoveFontMemResourceEx (GDI32.@)
3273 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3275 FIXME("(%p) stub\n", fh
);
3279 /***********************************************************************
3280 * RemoveFontResourceExA (GDI32.@)
3282 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3284 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3285 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3288 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3289 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3290 HeapFree(GetProcessHeap(), 0, strW
);
3294 /***********************************************************************
3295 * RemoveFontResourceExW (GDI32.@)
3297 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3299 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3302 /***********************************************************************
3303 * GetTextCharset (GDI32.@)
3305 UINT WINAPI
GetTextCharset(HDC hdc
)
3307 /* MSDN docs say this is equivalent */
3308 return GetTextCharsetInfo(hdc
, NULL
, 0);
3311 /***********************************************************************
3312 * GetTextCharsetInfo (GDI32.@)
3314 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3316 UINT ret
= DEFAULT_CHARSET
;
3317 DC
*dc
= get_dc_ptr(hdc
);
3322 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3324 release_dc_ptr( dc
);
3327 if (ret
== DEFAULT_CHARSET
&& fs
)
3328 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3332 /***********************************************************************
3333 * GdiGetCharDimensions (GDI32.@)
3335 * Gets the average width of the characters in the English alphabet.
3338 * hdc [I] Handle to the device context to measure on.
3339 * lptm [O] Pointer to memory to store the text metrics into.
3340 * height [O] On exit, the maximum height of characters in the English alphabet.
3343 * The average width of characters in the English alphabet.
3346 * This function is used by the dialog manager to get the size of a dialog
3347 * unit. It should also be used by other pieces of code that need to know
3348 * the size of a dialog unit in logical units without having access to the
3349 * window handle of the dialog.
3350 * Windows caches the font metrics from this function, but we don't and
3351 * there doesn't appear to be an immediate advantage to do so.
3354 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3356 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3359 static const WCHAR alphabet
[] = {
3360 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3361 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3362 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3364 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3366 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3368 if (height
) *height
= sz
.cy
;
3369 return (sz
.cx
/ 26 + 1) / 2;
3372 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3374 FIXME("(%d): stub\n", fEnableEUDC
);
3378 /***********************************************************************
3379 * GetCharWidthI (GDI32.@)
3381 * Retrieve widths of characters.
3384 * hdc [I] Handle to a device context.
3385 * first [I] First glyph in range to query.
3386 * count [I] Number of glyph indices to query.
3387 * glyphs [I] Array of glyphs to query.
3388 * buffer [O] Buffer to receive character widths.
3391 * Only works with TrueType fonts.
3397 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3402 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3404 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3407 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3409 HeapFree(GetProcessHeap(), 0, abc
);
3413 for (i
= 0; i
< count
; i
++)
3414 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3416 HeapFree(GetProcessHeap(), 0, abc
);
3420 /***********************************************************************
3421 * GetFontUnicodeRanges (GDI32.@)
3423 * Retrieve a list of supported Unicode characters in a font.
3426 * hdc [I] Handle to a device context.
3427 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3430 * Success: Number of bytes written to the buffer pointed to by lpgs.
3434 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3437 DC
*dc
= get_dc_ptr(hdc
);
3439 TRACE("(%p, %p)\n", hdc
, lpgs
);
3443 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3449 /*************************************************************
3450 * FontIsLinked (GDI32.@)
3452 BOOL WINAPI
FontIsLinked(HDC hdc
)
3454 DC
*dc
= get_dc_ptr(hdc
);
3457 if (!dc
) return FALSE
;
3458 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3460 TRACE("returning %d\n", ret
);
3464 /*************************************************************
3465 * GdiRealizationInfo (GDI32.@)
3467 * Returns a structure that contains some font information.
3469 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3471 DC
*dc
= get_dc_ptr(hdc
);
3474 if (!dc
) return FALSE
;
3475 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);