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);
2525 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2528 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2532 /***********************************************************************
2533 * GetGlyphOutlineW (GDI32.@)
2535 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2536 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2537 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2542 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2543 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2545 if (!lpmat2
) return GDI_ERROR
;
2547 dc
= get_dc_ptr(hdc
);
2548 if(!dc
) return GDI_ERROR
;
2551 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2552 cbBuffer
, lpBuffer
, lpmat2
);
2556 release_dc_ptr( dc
);
2561 /***********************************************************************
2562 * CreateScalableFontResourceA (GDI32.@)
2564 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2565 LPCSTR lpszResourceFile
,
2566 LPCSTR lpszFontFile
,
2567 LPCSTR lpszCurrentPath
)
2569 LPWSTR lpszResourceFileW
= NULL
;
2570 LPWSTR lpszFontFileW
= NULL
;
2571 LPWSTR lpszCurrentPathW
= NULL
;
2575 if (lpszResourceFile
)
2577 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2578 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2579 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2584 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2585 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2586 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2589 if (lpszCurrentPath
)
2591 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2592 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2593 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2596 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2597 lpszFontFileW
, lpszCurrentPathW
);
2599 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2600 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2601 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2606 /***********************************************************************
2607 * CreateScalableFontResourceW (GDI32.@)
2609 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2610 LPCWSTR lpszResourceFile
,
2611 LPCWSTR lpszFontFile
,
2612 LPCWSTR lpszCurrentPath
)
2615 FIXME("(%d,%s,%s,%s): stub\n",
2616 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2617 debugstr_w(lpszCurrentPath
) );
2619 /* fHidden=1 - only visible for the calling app, read-only, not
2620 * enumerated with EnumFonts/EnumFontFamilies
2621 * lpszCurrentPath can be NULL
2624 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2625 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2627 SetLastError(ERROR_FILE_EXISTS
);
2630 return FALSE
; /* create failed */
2633 /*************************************************************************
2634 * GetKerningPairsA (GDI32.@)
2636 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2637 LPKERNINGPAIR kern_pairA
)
2641 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2642 KERNINGPAIR
*kern_pairW
;
2644 if (!cPairs
&& kern_pairA
)
2646 SetLastError(ERROR_INVALID_PARAMETER
);
2650 cp
= GdiGetCodePage(hDC
);
2652 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2653 * to fail on an invalid character for CP_SYMBOL.
2655 cpi
.DefaultChar
[0] = 0;
2656 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2658 FIXME("Can't find codepage %u info\n", cp
);
2662 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2663 if (!total_kern_pairs
) return 0;
2665 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2666 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2668 for (i
= 0; i
< total_kern_pairs
; i
++)
2672 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2675 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2678 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2683 if (kern_pairs_copied
>= cPairs
) break;
2685 kern_pairA
->wFirst
= (BYTE
)first
;
2686 kern_pairA
->wSecond
= (BYTE
)second
;
2687 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2690 kern_pairs_copied
++;
2693 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2695 return kern_pairs_copied
;
2698 /*************************************************************************
2699 * GetKerningPairsW (GDI32.@)
2701 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2702 LPKERNINGPAIR lpKerningPairs
)
2707 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2709 if (!cPairs
&& lpKerningPairs
)
2711 SetLastError(ERROR_INVALID_PARAMETER
);
2715 dc
= get_dc_ptr(hDC
);
2719 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2721 release_dc_ptr( dc
);
2725 /*************************************************************************
2726 * TranslateCharsetInfo [GDI32.@]
2728 * Fills a CHARSETINFO structure for a character set, code page, or
2729 * font. This allows making the correspondence between different labels
2730 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2731 * of the same encoding.
2733 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2734 * only one codepage should be set in *lpSrc.
2737 * TRUE on success, FALSE on failure.
2740 BOOL WINAPI
TranslateCharsetInfo(
2741 LPDWORD lpSrc
, /* [in]
2742 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2743 if flags == TCI_SRCCHARSET: a character set value
2744 if flags == TCI_SRCCODEPAGE: a code page value
2746 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2747 DWORD flags
/* [in] determines interpretation of lpSrc */)
2751 case TCI_SRCFONTSIG
:
2752 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2754 case TCI_SRCCODEPAGE
:
2755 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2757 case TCI_SRCCHARSET
:
2758 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2763 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2764 *lpCs
= FONT_tci
[index
];
2768 /*************************************************************************
2769 * GetFontLanguageInfo (GDI32.@)
2771 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2773 FONTSIGNATURE fontsig
;
2774 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2775 GCP_DIACRITIC_MASK
=0x00000000,
2776 FLI_GLYPHS_MASK
=0x00000000,
2777 GCP_GLYPHSHAPE_MASK
=0x00000040,
2778 GCP_KASHIDA_MASK
=0x00000000,
2779 GCP_LIGATE_MASK
=0x00000000,
2780 GCP_USEKERNING_MASK
=0x00000000,
2781 GCP_REORDER_MASK
=0x00000060;
2785 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2786 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2788 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2791 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2792 result
|=GCP_DIACRITIC
;
2794 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2797 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2798 result
|=GCP_GLYPHSHAPE
;
2800 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2801 result
|=GCP_KASHIDA
;
2803 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2806 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2807 result
|=GCP_USEKERNING
;
2809 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2810 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2811 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2812 result
|=GCP_REORDER
;
2818 /*************************************************************************
2819 * GetFontData [GDI32.@]
2821 * Retrieve data for TrueType font.
2825 * success: Number of bytes returned
2826 * failure: GDI_ERROR
2830 * Calls SetLastError()
2833 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2834 LPVOID buffer
, DWORD length
)
2836 DC
*dc
= get_dc_ptr(hdc
);
2837 DWORD ret
= GDI_ERROR
;
2839 if(!dc
) return GDI_ERROR
;
2842 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2844 release_dc_ptr( dc
);
2848 /*************************************************************************
2849 * GetGlyphIndicesA [GDI32.@]
2851 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2852 LPWORD pgi
, DWORD flags
)
2858 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2859 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2861 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2862 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2863 HeapFree(GetProcessHeap(), 0, lpstrW
);
2868 /*************************************************************************
2869 * GetGlyphIndicesW [GDI32.@]
2871 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2872 LPWORD pgi
, DWORD flags
)
2874 DC
*dc
= get_dc_ptr(hdc
);
2875 DWORD ret
= GDI_ERROR
;
2877 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2878 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2880 if(!dc
) return GDI_ERROR
;
2883 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2885 release_dc_ptr( dc
);
2889 /*************************************************************************
2890 * GetCharacterPlacementA [GDI32.@]
2892 * See GetCharacterPlacementW.
2895 * the web browser control of ie4 calls this with dwFlags=0
2898 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2899 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2904 GCP_RESULTSW resultsW
;
2908 TRACE("%s, %d, %d, 0x%08x\n",
2909 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2911 /* both structs are equal in size */
2912 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2914 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2915 if(lpResults
->lpOutString
)
2916 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2918 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2920 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2921 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2923 if(lpResults
->lpOutString
) {
2924 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2925 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2928 HeapFree(GetProcessHeap(), 0, lpStringW
);
2929 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2934 /*************************************************************************
2935 * GetCharacterPlacementW [GDI32.@]
2937 * Retrieve information about a string. This includes the width, reordering,
2938 * Glyphing and so on.
2942 * The width and height of the string if successful, 0 if failed.
2946 * All flags except GCP_REORDER are not yet implemented.
2947 * Reordering is not 100% compliant to the Windows BiDi method.
2948 * Caret positioning is not yet implemented for BiDi.
2949 * Classes are not yet implemented.
2953 GetCharacterPlacementW(
2954 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2955 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2956 INT uCount
, /* [in] Number of WORDS in string. */
2957 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2958 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2959 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2966 TRACE("%s, %d, %d, 0x%08x\n",
2967 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2969 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2970 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2971 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2972 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2973 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2975 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2976 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2977 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2978 FIXME("Caret positions for complex scripts not implemented\n");
2980 nSet
= (UINT
)uCount
;
2981 if(nSet
> lpResults
->nGlyphs
)
2982 nSet
= lpResults
->nGlyphs
;
2984 /* return number of initialized fields */
2985 lpResults
->nGlyphs
= nSet
;
2987 if((dwFlags
&GCP_REORDER
)==0 )
2989 /* Treat the case where no special handling was requested in a fastpath way */
2990 /* copy will do if the GCP_REORDER flag is not set */
2991 if(lpResults
->lpOutString
)
2992 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2994 if(lpResults
->lpOrder
)
2996 for(i
= 0; i
< nSet
; i
++)
2997 lpResults
->lpOrder
[i
] = i
;
3001 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3002 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3005 /* FIXME: Will use the placement chars */
3006 if (lpResults
->lpDx
)
3009 for (i
= 0; i
< nSet
; i
++)
3011 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3012 lpResults
->lpDx
[i
]= c
;
3016 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3020 lpResults
->lpCaretPos
[0] = 0;
3021 for (i
= 1; i
< nSet
; i
++)
3022 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3023 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3026 if(lpResults
->lpGlyphs
)
3027 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3029 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3030 ret
= MAKELONG(size
.cx
, size
.cy
);
3035 /*************************************************************************
3036 * GetCharABCWidthsFloatA [GDI32.@]
3038 * See GetCharABCWidthsFloatW.
3040 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3047 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3051 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3053 for (i
= 0; i
< wlen
; i
++)
3055 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3063 HeapFree( GetProcessHeap(), 0, str
);
3064 HeapFree( GetProcessHeap(), 0, wstr
);
3069 /*************************************************************************
3070 * GetCharABCWidthsFloatW [GDI32.@]
3072 * Retrieves widths of a range of characters.
3075 * hdc [I] Handle to device context.
3076 * first [I] First character in range to query.
3077 * last [I] Last character in range to query.
3078 * abcf [O] Array of LPABCFLOAT structures.
3084 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3088 DC
*dc
= get_dc_ptr( hdc
);
3090 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3092 if (!dc
) return FALSE
;
3096 release_dc_ptr( dc
);
3101 ret
= WineEngGetCharABCWidthsFloat( dc
->gdiFont
, first
, last
, abcf
);
3107 /* convert device units to logical */
3108 for (i
= first
; i
<= last
; i
++, abcf
++)
3110 abcf
->abcfA
= abcf
->abcfA
* dc
->xformVport2World
.eM11
;
3111 abcf
->abcfB
= abcf
->abcfB
* dc
->xformVport2World
.eM11
;
3112 abcf
->abcfC
= abcf
->abcfC
* dc
->xformVport2World
.eM11
;
3116 release_dc_ptr( dc
);
3120 /*************************************************************************
3121 * GetCharWidthFloatA [GDI32.@]
3123 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3124 UINT iLastChar
, PFLOAT pxBuffer
)
3126 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3130 /*************************************************************************
3131 * GetCharWidthFloatW [GDI32.@]
3133 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3134 UINT iLastChar
, PFLOAT pxBuffer
)
3136 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3141 /***********************************************************************
3143 * Font Resource API *
3145 ***********************************************************************/
3147 /***********************************************************************
3148 * AddFontResourceA (GDI32.@)
3150 INT WINAPI
AddFontResourceA( LPCSTR str
)
3152 return AddFontResourceExA( str
, 0, NULL
);
3155 /***********************************************************************
3156 * AddFontResourceW (GDI32.@)
3158 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3160 return AddFontResourceExW(str
, 0, NULL
);
3164 /***********************************************************************
3165 * AddFontResourceExA (GDI32.@)
3167 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3169 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3170 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3173 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3174 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3175 HeapFree(GetProcessHeap(), 0, strW
);
3179 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3181 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3182 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3183 LPVOID
*pMem
= LockResource(hMem
);
3184 int *num_total
= (int *)lParam
;
3187 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3188 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3190 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3194 *num_total
+= num_in_res
;
3198 /***********************************************************************
3199 * AddFontResourceExW (GDI32.@)
3201 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3203 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3206 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3207 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3208 if (hModule
!= NULL
)
3210 int num_resources
= 0;
3211 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3213 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3214 wine_dbgstr_w(str
));
3215 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3216 ret
= num_resources
;
3217 FreeLibrary(hModule
);
3223 /***********************************************************************
3224 * RemoveFontResourceA (GDI32.@)
3226 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3228 return RemoveFontResourceExA(str
, 0, 0);
3231 /***********************************************************************
3232 * RemoveFontResourceW (GDI32.@)
3234 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3236 return RemoveFontResourceExW(str
, 0, 0);
3239 /***********************************************************************
3240 * AddFontMemResourceEx (GDI32.@)
3242 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3247 if (!pbFont
|| !cbFont
|| !pcFonts
)
3249 SetLastError(ERROR_INVALID_PARAMETER
);
3253 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3258 *pcFonts
= num_fonts
;
3262 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3263 RemoveFontMemResourceEx(ret
);
3271 /***********************************************************************
3272 * RemoveFontMemResourceEx (GDI32.@)
3274 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3276 FIXME("(%p) stub\n", fh
);
3280 /***********************************************************************
3281 * RemoveFontResourceExA (GDI32.@)
3283 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3285 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3286 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3289 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3290 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3291 HeapFree(GetProcessHeap(), 0, strW
);
3295 /***********************************************************************
3296 * RemoveFontResourceExW (GDI32.@)
3298 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3300 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3303 /***********************************************************************
3304 * GetTextCharset (GDI32.@)
3306 UINT WINAPI
GetTextCharset(HDC hdc
)
3308 /* MSDN docs say this is equivalent */
3309 return GetTextCharsetInfo(hdc
, NULL
, 0);
3312 /***********************************************************************
3313 * GetTextCharsetInfo (GDI32.@)
3315 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3317 UINT ret
= DEFAULT_CHARSET
;
3318 DC
*dc
= get_dc_ptr(hdc
);
3323 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3325 release_dc_ptr( dc
);
3328 if (ret
== DEFAULT_CHARSET
&& fs
)
3329 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3333 /***********************************************************************
3334 * GdiGetCharDimensions (GDI32.@)
3336 * Gets the average width of the characters in the English alphabet.
3339 * hdc [I] Handle to the device context to measure on.
3340 * lptm [O] Pointer to memory to store the text metrics into.
3341 * height [O] On exit, the maximum height of characters in the English alphabet.
3344 * The average width of characters in the English alphabet.
3347 * This function is used by the dialog manager to get the size of a dialog
3348 * unit. It should also be used by other pieces of code that need to know
3349 * the size of a dialog unit in logical units without having access to the
3350 * window handle of the dialog.
3351 * Windows caches the font metrics from this function, but we don't and
3352 * there doesn't appear to be an immediate advantage to do so.
3355 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3357 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3360 static const WCHAR alphabet
[] = {
3361 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3362 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3363 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3365 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3367 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3369 if (height
) *height
= sz
.cy
;
3370 return (sz
.cx
/ 26 + 1) / 2;
3373 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3375 FIXME("(%d): stub\n", fEnableEUDC
);
3379 /***********************************************************************
3380 * GetCharWidthI (GDI32.@)
3382 * Retrieve widths of characters.
3385 * hdc [I] Handle to a device context.
3386 * first [I] First glyph in range to query.
3387 * count [I] Number of glyph indices to query.
3388 * glyphs [I] Array of glyphs to query.
3389 * buffer [O] Buffer to receive character widths.
3392 * Only works with TrueType fonts.
3398 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3403 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3405 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3408 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3410 HeapFree(GetProcessHeap(), 0, abc
);
3414 for (i
= 0; i
< count
; i
++)
3415 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3417 HeapFree(GetProcessHeap(), 0, abc
);
3421 /***********************************************************************
3422 * GetFontUnicodeRanges (GDI32.@)
3424 * Retrieve a list of supported Unicode characters in a font.
3427 * hdc [I] Handle to a device context.
3428 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3431 * Success: Number of bytes written to the buffer pointed to by lpgs.
3435 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3438 DC
*dc
= get_dc_ptr(hdc
);
3440 TRACE("(%p, %p)\n", hdc
, lpgs
);
3444 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3450 /*************************************************************
3451 * FontIsLinked (GDI32.@)
3453 BOOL WINAPI
FontIsLinked(HDC hdc
)
3455 DC
*dc
= get_dc_ptr(hdc
);
3458 if (!dc
) return FALSE
;
3459 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3461 TRACE("returning %d\n", ret
);
3465 /*************************************************************
3466 * GdiRealizationInfo (GDI32.@)
3468 * Returns a structure that contains some font information.
3470 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3472 DC
*dc
= get_dc_ptr(hdc
);
3475 if (!dc
) return FALSE
;
3476 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);