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"
35 #include "gdi_private.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 * CreateFontIndirectExA (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
);
535 if (!GDI_inc_ref_count( handle
))
537 release_dc_ptr( dc
);
541 if (GetDeviceCaps( dc
->hSelf
, TEXTCAPS
) & TC_VA_ABLE
)
542 dc
->gdiFont
= WineEngCreateFontInstance( dc
, handle
);
544 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
546 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
548 if (ret
== HGDI_ERROR
)
550 GDI_dec_ref_count( handle
);
551 ret
= 0; /* SelectObject returns 0 on error */
557 update_font_code_page( dc
);
558 GDI_dec_ref_count( ret
);
560 release_dc_ptr( dc
);
565 /***********************************************************************
568 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
570 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
576 FONT_LogFontWToA( &font
->logfont
, &lfA
);
577 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
578 memcpy( buffer
, &lfA
, count
);
580 else count
= sizeof(lfA
);
581 GDI_ReleaseObj( handle
);
585 /***********************************************************************
588 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
590 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
595 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
596 memcpy( buffer
, &font
->logfont
, count
);
598 else count
= sizeof(LOGFONTW
);
599 GDI_ReleaseObj( handle
);
604 /***********************************************************************
607 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
611 WineEngDestroyFontInstance( handle
);
613 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
614 return HeapFree( GetProcessHeap(), 0, obj
);
618 /***********************************************************************
621 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
622 * We have to use other types because of the FONTENUMPROCW definition.
624 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
625 DWORD fType
, LPARAM lp
)
627 fontEnum32
*pfe
= (fontEnum32
*)lp
;
630 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
631 if ((!pfe
->lpLogFontParam
||
632 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
633 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
634 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
636 /* convert font metrics */
637 ENUMLOGFONTEXA logfont
;
638 NEWTEXTMETRICEXA tmA
;
640 pfe
->dwFlags
|= ENUM_CALLED
;
641 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
643 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
644 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
645 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
646 ptm
= (TEXTMETRICW
*)&tmA
;
649 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
654 /***********************************************************************
655 * FONT_EnumFontFamiliesEx
657 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
658 FONTENUMPROCW efproc
,
659 LPARAM lParam
, DWORD dwUnicode
)
662 DC
*dc
= get_dc_ptr( hDC
);
669 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
671 fe32
.lpLogFontParam
= plf
;
672 fe32
.lpEnumFunc
= efproc
;
673 fe32
.lpData
= lParam
;
674 fe32
.dwFlags
= dwUnicode
;
677 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
679 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
686 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
687 fe32
.dwFlags
&= ~ENUM_CALLED
;
688 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
689 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
690 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
694 release_dc_ptr( dc
);
698 /***********************************************************************
699 * EnumFontFamiliesExW (GDI32.@)
701 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
702 FONTENUMPROCW efproc
,
703 LPARAM lParam
, DWORD dwFlags
)
705 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
708 /***********************************************************************
709 * EnumFontFamiliesExA (GDI32.@)
711 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
712 FONTENUMPROCA efproc
,
713 LPARAM lParam
, DWORD dwFlags
)
719 FONT_LogFontAToW( plf
, &lfW
);
724 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
727 /***********************************************************************
728 * EnumFontFamiliesA (GDI32.@)
730 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
731 FONTENUMPROCA efproc
, LPARAM lpData
)
737 if (!*lpFamily
) return 1;
738 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
739 lf
.lfCharSet
= DEFAULT_CHARSET
;
740 lf
.lfPitchAndFamily
= 0;
745 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
748 /***********************************************************************
749 * EnumFontFamiliesW (GDI32.@)
751 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
752 FONTENUMPROCW efproc
, LPARAM lpData
)
758 if (!*lpFamily
) return 1;
759 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
760 lf
.lfCharSet
= DEFAULT_CHARSET
;
761 lf
.lfPitchAndFamily
= 0;
766 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
769 /***********************************************************************
770 * EnumFontsA (GDI32.@)
772 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
775 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
778 /***********************************************************************
779 * EnumFontsW (GDI32.@)
781 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
784 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
788 /***********************************************************************
789 * GetTextCharacterExtra (GDI32.@)
791 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
794 DC
*dc
= get_dc_ptr( hdc
);
795 if (!dc
) return 0x80000000;
797 release_dc_ptr( dc
);
802 /***********************************************************************
803 * SetTextCharacterExtra (GDI32.@)
805 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
808 DC
* dc
= get_dc_ptr( hdc
);
809 if (!dc
) return 0x80000000;
810 if (dc
->funcs
->pSetTextCharacterExtra
)
811 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
814 prev
= dc
->charExtra
;
815 dc
->charExtra
= extra
;
817 release_dc_ptr( dc
);
822 /***********************************************************************
823 * SetTextJustification (GDI32.@)
825 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
828 DC
* dc
= get_dc_ptr( hdc
);
829 if (!dc
) return FALSE
;
830 if (dc
->funcs
->pSetTextJustification
)
831 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
834 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
835 if (!extra
) breaks
= 0;
838 dc
->breakExtra
= extra
/ breaks
;
839 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
847 release_dc_ptr( dc
);
852 /***********************************************************************
853 * GetTextFaceA (GDI32.@)
855 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
857 INT res
= GetTextFaceW(hdc
, 0, NULL
);
858 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
859 GetTextFaceW( hdc
, res
, nameW
);
865 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
869 /* GetTextFaceA does NOT include the nul byte in the return count. */
876 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
877 HeapFree( GetProcessHeap(), 0, nameW
);
881 /***********************************************************************
882 * GetTextFaceW (GDI32.@)
884 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
889 DC
* dc
= get_dc_ptr( hdc
);
893 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
894 else if ((font
= GDI_GetObjPtr( dc
->hFont
, OBJ_FONT
)))
896 INT n
= strlenW(font
->logfont
.lfFaceName
) + 1;
899 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
903 GDI_ReleaseObj( dc
->hFont
);
905 release_dc_ptr( dc
);
910 /***********************************************************************
911 * GetTextExtentPoint32A (GDI32.@)
913 * See GetTextExtentPoint32W.
915 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
920 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
923 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
924 HeapFree( GetProcessHeap(), 0, p
);
927 TRACE("(%p %s %d %p): returning %d x %d\n",
928 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
933 /***********************************************************************
934 * GetTextExtentPoint32W [GDI32.@]
936 * Computes width/height for a string.
938 * Computes width and height of the specified string.
944 BOOL WINAPI
GetTextExtentPoint32W(
945 HDC hdc
, /* [in] Handle of device context */
946 LPCWSTR str
, /* [in] Address of text string */
947 INT count
, /* [in] Number of characters in string */
948 LPSIZE size
) /* [out] Address of structure for string size */
950 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
953 /***********************************************************************
954 * GetTextExtentExPointI [GDI32.@]
956 * Computes width and height of the array of glyph indices.
959 * hdc [I] Handle of device context.
960 * indices [I] Glyph index array.
961 * count [I] Number of glyphs in array.
962 * max_ext [I] Maximum width in glyphs.
963 * nfit [O] Maximum number of characters.
964 * dxs [O] Partial string widths.
965 * size [O] Returned string size.
971 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
972 LPINT nfit
, LPINT dxs
, LPSIZE size
)
975 DC
* dc
= get_dc_ptr( hdc
);
976 if (!dc
) return FALSE
;
979 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
980 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
981 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
982 size
->cx
+= count
* dc
->charExtra
;
984 else if(dc
->funcs
->pGetTextExtentExPoint
) {
985 FIXME("calling GetTextExtentExPoint\n");
986 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, indices
, count
,
987 max_ext
, nfit
, dxs
, size
);
990 release_dc_ptr( dc
);
992 TRACE("(%p %p %d %p): returning %d x %d\n",
993 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
997 /***********************************************************************
998 * GetTextExtentPointI [GDI32.@]
1000 * Computes width and height of the array of glyph indices.
1003 * hdc [I] Handle of device context.
1004 * indices [I] Glyph index array.
1005 * count [I] Number of glyphs in array.
1006 * size [O] Returned string size.
1012 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1014 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1018 /***********************************************************************
1019 * GetTextExtentPointA (GDI32.@)
1021 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1024 TRACE("not bug compatible.\n");
1025 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1028 /***********************************************************************
1029 * GetTextExtentPointW (GDI32.@)
1031 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1034 TRACE("not bug compatible.\n");
1035 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1039 /***********************************************************************
1040 * GetTextExtentExPointA (GDI32.@)
1042 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1043 INT maxExt
, LPINT lpnFit
,
1044 LPINT alpDx
, LPSIZE size
)
1052 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1055 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1056 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1059 INT n
= lpnFit
? *lpnFit
: wlen
;
1061 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1063 alpDx
[j
] = walpDx
[i
];
1064 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1067 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1068 HeapFree( GetProcessHeap(), 0, p
);
1069 HeapFree( GetProcessHeap(), 0, walpDx
);
1074 /***********************************************************************
1075 * GetTextExtentExPointW (GDI32.@)
1077 * Return the size of the string as it would be if it was output properly by
1080 * This should include
1081 * - Intercharacter spacing
1082 * - justification spacing (not yet done)
1083 * - kerning? see below
1085 * Kerning. Since kerning would be carried out by the rendering code it should
1086 * be done by the driver. However they don't support it yet. Also I am not
1087 * yet persuaded that (certainly under Win95) any kerning is actually done.
1089 * str: According to MSDN this should be null-terminated. That is not true; a
1090 * null will not terminate it early.
1091 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1092 * than count. I have seen it be either the size of the full string or
1093 * 1 less than the size of the full string. I have not seen it bear any
1094 * resemblance to the portion that would fit.
1095 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1096 * trailing intercharacter spacing and any trailing justification.
1099 * Currently we do this by measuring each character etc. We should do it by
1100 * passing the request to the driver, perhaps by extending the
1101 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1102 * thinking about kerning issues and rounding issues in the justification.
1105 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1106 INT maxExt
, LPINT lpnFit
,
1107 LPINT alpDx
, LPSIZE size
)
1115 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1117 dc
= get_dc_ptr(hdc
);
1121 GetTextMetricsW(hdc
, &tm
);
1123 /* If we need to calculate nFit, then we need the partial extents even if
1124 the user hasn't provided us with an array. */
1127 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1131 SetLastError(ERROR_OUTOFMEMORY
);
1139 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1140 0, NULL
, dxs
, size
);
1141 else if (dc
->funcs
->pGetTextExtentExPoint
)
1142 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1143 0, NULL
, dxs
, size
);
1145 /* Perform device size to world size transformations. */
1148 INT extra
= dc
->charExtra
,
1149 breakExtra
= dc
->breakExtra
,
1150 breakRem
= dc
->breakRem
,
1155 for (i
= 0; i
< count
; ++i
)
1157 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1158 dxs
[i
] += (i
+1) * extra
;
1159 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1161 dxs
[i
] += breakExtra
;
1168 if (dxs
[i
] <= maxExt
)
1171 breakRem
= dc
->breakRem
;
1173 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1174 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1176 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1178 for (i
= 0; i
< count
; i
++)
1180 if (str
[i
] == tm
.tmBreakChar
)
1182 size
->cx
+= breakExtra
;
1197 HeapFree(GetProcessHeap(), 0, dxs
);
1199 release_dc_ptr( dc
);
1201 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1205 /***********************************************************************
1206 * GetTextMetricsA (GDI32.@)
1208 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1212 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1213 FONT_TextMetricWToA( &tm32
, metrics
);
1217 /***********************************************************************
1218 * GetTextMetricsW (GDI32.@)
1220 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1223 DC
* dc
= get_dc_ptr( hdc
);
1224 if (!dc
) return FALSE
;
1227 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1228 else if (dc
->funcs
->pGetTextMetrics
)
1229 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1233 /* device layer returns values in device units
1234 * therefore we have to convert them to logical */
1236 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1237 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1239 #define WDPTOLP(x) ((x<0)? \
1240 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1241 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1242 #define HDPTOLP(y) ((y<0)? \
1243 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1244 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1246 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1247 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1248 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1249 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1250 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1251 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1252 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1253 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1257 TRACE("text metrics:\n"
1258 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1259 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1260 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1261 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1262 " PitchAndFamily = %02x\n"
1263 " --------------------\n"
1264 " InternalLeading = %i\n"
1268 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1269 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1270 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1271 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1272 metrics
->tmPitchAndFamily
,
1273 metrics
->tmInternalLeading
,
1276 metrics
->tmHeight
);
1278 release_dc_ptr( dc
);
1283 /***********************************************************************
1284 * GetOutlineTextMetricsA (GDI32.@)
1285 * Gets metrics for TrueType fonts.
1288 * If the supplied buffer isn't big enough Windows partially fills it up to
1289 * its given length and returns that length.
1292 * Success: Non-zero or size of required buffer
1295 UINT WINAPI
GetOutlineTextMetricsA(
1296 HDC hdc
, /* [in] Handle of device context */
1297 UINT cbData
, /* [in] Size of metric data array */
1298 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1300 char buf
[512], *ptr
;
1302 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1303 OUTLINETEXTMETRICA
*output
= lpOTM
;
1306 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1308 if(ret
> sizeof(buf
))
1309 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1310 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1312 needed
= sizeof(OUTLINETEXTMETRICA
);
1313 if(lpOTMW
->otmpFamilyName
)
1314 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1315 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1316 NULL
, 0, NULL
, NULL
);
1317 if(lpOTMW
->otmpFaceName
)
1318 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1319 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1320 NULL
, 0, NULL
, NULL
);
1321 if(lpOTMW
->otmpStyleName
)
1322 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1323 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1324 NULL
, 0, NULL
, NULL
);
1325 if(lpOTMW
->otmpFullName
)
1326 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1327 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1328 NULL
, 0, NULL
, NULL
);
1335 TRACE("needed = %d\n", needed
);
1337 /* Since the supplied buffer isn't big enough, we'll alloc one
1338 that is and memcpy the first cbData bytes into the lpOTM at
1340 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1342 ret
= output
->otmSize
= min(needed
, cbData
);
1343 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1344 output
->otmFiller
= 0;
1345 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1346 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1347 output
->otmfsType
= lpOTMW
->otmfsType
;
1348 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1349 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1350 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1351 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1352 output
->otmAscent
= lpOTMW
->otmAscent
;
1353 output
->otmDescent
= lpOTMW
->otmDescent
;
1354 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1355 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1356 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1357 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1358 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1359 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1360 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1361 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1362 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1363 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1364 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1365 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1366 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1367 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1368 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1369 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1372 ptr
= (char*)(output
+ 1);
1373 left
= needed
- sizeof(*output
);
1375 if(lpOTMW
->otmpFamilyName
) {
1376 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1377 len
= WideCharToMultiByte(CP_ACP
, 0,
1378 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1379 ptr
, left
, NULL
, NULL
);
1383 output
->otmpFamilyName
= 0;
1385 if(lpOTMW
->otmpFaceName
) {
1386 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1387 len
= WideCharToMultiByte(CP_ACP
, 0,
1388 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1389 ptr
, left
, NULL
, NULL
);
1393 output
->otmpFaceName
= 0;
1395 if(lpOTMW
->otmpStyleName
) {
1396 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1397 len
= WideCharToMultiByte(CP_ACP
, 0,
1398 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1399 ptr
, left
, NULL
, NULL
);
1403 output
->otmpStyleName
= 0;
1405 if(lpOTMW
->otmpFullName
) {
1406 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1407 len
= WideCharToMultiByte(CP_ACP
, 0,
1408 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1409 ptr
, left
, NULL
, NULL
);
1412 output
->otmpFullName
= 0;
1416 if(output
!= lpOTM
) {
1417 memcpy(lpOTM
, output
, cbData
);
1418 HeapFree(GetProcessHeap(), 0, output
);
1420 /* check if the string offsets really fit into the provided size */
1421 /* FIXME: should we check string length as well? */
1422 /* make sure that we don't read/write beyond the provided buffer */
1423 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1425 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1426 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1429 /* make sure that we don't read/write beyond the provided buffer */
1430 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1432 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1433 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1436 /* make sure that we don't read/write beyond the provided buffer */
1437 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1439 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1440 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1443 /* make sure that we don't read/write beyond the provided buffer */
1444 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1446 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1447 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1452 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1453 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1459 /***********************************************************************
1460 * GetOutlineTextMetricsW [GDI32.@]
1462 UINT WINAPI
GetOutlineTextMetricsW(
1463 HDC hdc
, /* [in] Handle of device context */
1464 UINT cbData
, /* [in] Size of metric data array */
1465 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1467 DC
*dc
= get_dc_ptr( hdc
);
1468 OUTLINETEXTMETRICW
*output
= lpOTM
;
1471 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1475 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1478 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1479 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1482 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1483 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1485 #define WDPTOLP(x) ((x<0)? \
1486 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1487 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1488 #define HDPTOLP(y) ((y<0)? \
1489 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1490 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1492 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1493 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1494 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1495 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1496 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1497 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1498 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1499 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1500 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1501 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1502 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1503 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1504 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1505 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1506 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1507 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1508 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1509 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1510 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1511 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1512 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1513 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1514 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1515 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1516 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1517 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1518 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1519 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1520 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1521 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1522 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1523 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1526 if(output
!= lpOTM
) {
1527 memcpy(lpOTM
, output
, cbData
);
1528 HeapFree(GetProcessHeap(), 0, output
);
1534 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1535 but really this should just be a return 0. */
1537 ret
= sizeof(*lpOTM
);
1542 memset(lpOTM
, 0, ret
);
1543 lpOTM
->otmSize
= sizeof(*lpOTM
);
1544 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1546 Further fill of the structure not implemented,
1547 Needs real values for the structure members
1557 /***********************************************************************
1558 * GetCharWidthW (GDI32.@)
1559 * GetCharWidth32W (GDI32.@)
1561 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1566 DC
* dc
= get_dc_ptr( hdc
);
1567 if (!dc
) return FALSE
;
1570 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1571 else if (dc
->funcs
->pGetCharWidth
)
1572 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1576 /* convert device units to logical */
1577 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1578 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1581 release_dc_ptr( dc
);
1586 /***********************************************************************
1587 * GetCharWidthA (GDI32.@)
1588 * GetCharWidth32A (GDI32.@)
1590 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1593 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1598 if(count
<= 0) return FALSE
;
1600 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1601 for(i
= 0; i
< count
; i
++)
1602 str
[i
] = (BYTE
)(firstChar
+ i
);
1604 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1606 for(i
= 0; i
< wlen
; i
++)
1608 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1616 HeapFree(GetProcessHeap(), 0, str
);
1617 HeapFree(GetProcessHeap(), 0, wstr
);
1623 /***********************************************************************
1624 * ExtTextOutA (GDI32.@)
1628 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1629 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1637 if (flags
& ETO_GLYPH_INDEX
)
1638 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1640 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1643 unsigned int i
= 0, j
= 0;
1645 /* allocate enough for a ETO_PDY */
1646 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1648 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1652 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1653 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1656 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1663 lpDxW
[j
++] = lpDx
[i
* 2];
1664 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1667 lpDxW
[j
++] = lpDx
[i
];
1673 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1675 HeapFree( GetProcessHeap(), 0, p
);
1676 HeapFree( GetProcessHeap(), 0, lpDxW
);
1681 /***********************************************************************
1682 * ExtTextOutW (GDI32.@)
1684 * Draws text using the currently selected font, background color, and text color.
1688 * x,y [I] coordinates of string
1690 * ETO_GRAYED - undocumented on MSDN
1691 * ETO_OPAQUE - use background color for fill the rectangle
1692 * ETO_CLIPPED - clipping text to the rectangle
1693 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1694 * than encoded characters. Implies ETO_IGNORELANGUAGE
1695 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1696 * Affects BiDi ordering
1697 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1698 * ETO_PDY - unimplemented
1699 * ETO_NUMERICSLATIN - unimplemented always assumed -
1700 * do not translate numbers into locale representations
1701 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1702 * lprect [I] dimensions for clipping or/and opaquing
1703 * str [I] text string
1704 * count [I] number of symbols in string
1705 * lpDx [I] optional parameter with distance between drawing characters
1711 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1712 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1715 LPWSTR reordered_str
= (LPWSTR
)str
;
1716 WORD
*glyphs
= NULL
;
1717 UINT align
= GetTextAlign( hdc
);
1721 double cosEsc
, sinEsc
;
1725 BOOL done_extents
= FALSE
;
1726 POINT
*deltas
= NULL
, width
= {0, 0};
1728 DC
* dc
= get_dc_ptr( hdc
);
1730 static int quietfixme
= 0;
1732 if (!dc
) return FALSE
;
1734 breakRem
= dc
->breakRem
;
1736 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1738 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1741 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1743 release_dc_ptr( dc
);
1748 type
= GetObjectType(hdc
);
1749 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1751 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1752 release_dc_ptr( dc
);
1757 flags
&= ~ETO_CLIPPED
;
1759 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1762 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1764 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1765 ((flags
&ETO_RTLREADING
)!=0 || (GetTextAlign(hdc
)&TA_RTLREADING
)!=0)?
1766 WINE_GCPW_FORCE_RTL
:WINE_GCPW_FORCE_LTR
,
1767 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1769 flags
|= ETO_IGNORELANGUAGE
;
1772 flags
|= ETO_GLYPH_INDEX
;
1773 if (cGlyphs
!= count
)
1777 else if(flags
& ETO_GLYPH_INDEX
)
1778 glyphs
= reordered_str
;
1780 TRACE("%p, %d, %d, %08x, %p, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1781 lprect
, debugstr_wn(str
, count
), count
, lpDx
);
1784 TRACE("rect: %d,%d - %d,%d\n", lprect
->left
, lprect
->top
, lprect
->right
,
1786 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1788 if(align
& TA_UPDATECP
)
1790 GetCurrentPositionEx( hdc
, &pt
);
1795 GetTextMetricsW(hdc
, &tm
);
1796 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1798 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1799 lf
.lfEscapement
= 0;
1801 if(lf
.lfEscapement
!= 0)
1803 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1804 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1812 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1816 if(flags
& ETO_GLYPH_INDEX
)
1817 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1819 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1821 done_extents
= TRUE
;
1824 rc
.right
= x
+ sz
.cx
;
1825 rc
.bottom
= y
+ sz
.cy
;
1832 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1834 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1835 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1838 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1839 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1849 LPtoDP(hdc
, &pt
, 1);
1853 char_extra
= GetTextCharacterExtra(hdc
);
1854 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1858 POINT total
= {0, 0}, desired
[2];
1860 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1861 for(i
= 0; i
< count
; i
++)
1867 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1868 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1872 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1879 if(flags
& ETO_GLYPH_INDEX
)
1880 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1882 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1884 deltas
[i
].x
= tmpsz
.cx
;
1888 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1890 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1897 total
.x
+= deltas
[i
].x
;
1898 total
.y
+= deltas
[i
].y
;
1900 desired
[0].x
= desired
[0].y
= 0;
1902 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1903 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1905 LPtoDP(hdc
, desired
, 2);
1906 desired
[1].x
-= desired
[0].x
;
1907 desired
[1].y
-= desired
[0].y
;
1909 deltas
[i
].x
= desired
[1].x
- width
.x
;
1910 deltas
[i
].y
= desired
[1].y
- width
.y
;
1920 if(flags
& ETO_GLYPH_INDEX
)
1921 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1923 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1924 done_extents
= TRUE
;
1926 width
.x
= INTERNAL_XWSTODS(dc
, sz
.cx
);
1930 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1931 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1932 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1935 if (align
& TA_UPDATECP
)
1939 DPtoLP(hdc
, &pt
, 1);
1940 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1952 if (align
& TA_UPDATECP
)
1956 DPtoLP(hdc
, &pt
, 1);
1957 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1962 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1965 y
+= tm
.tmAscent
* cosEsc
;
1966 x
+= tm
.tmAscent
* sinEsc
;
1970 y
-= tm
.tmDescent
* cosEsc
;
1971 x
-= tm
.tmDescent
* sinEsc
;
1978 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1980 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1982 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
1983 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1987 rc
.right
= x
+ width
.x
;
1988 rc
.top
= y
- tm
.tmAscent
;
1989 rc
.bottom
= y
+ tm
.tmDescent
;
1990 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1995 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
1997 HFONT orig_font
= dc
->hFont
, cur_font
;
2000 POINT
*offsets
= NULL
;
2003 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2004 for(i
= 0; i
< count
; i
++)
2006 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2007 if(cur_font
!= dc
->hFont
)
2012 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2013 offsets
[0].x
= offsets
[0].y
= 0;
2018 for(j
= 1; j
< count
; j
++)
2020 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2021 offsets
[j
].x
= offsets
[j
- 1].x
+ INTERNAL_XWSTODS(dc
, tmpsz
.cx
);
2027 for(j
= 1; j
< count
; j
++)
2029 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2030 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2036 if (PATH_IsPathOpen(dc
->path
))
2037 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2038 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2039 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2041 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2042 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2043 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2046 SelectObject(hdc
, cur_font
);
2048 glyphs
[span
++] = glyph
;
2052 if (PATH_IsPathOpen(dc
->path
))
2053 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2054 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2055 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2056 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2058 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2059 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2060 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2061 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2062 SelectObject(hdc
, orig_font
);
2063 HeapFree(GetProcessHeap(), 0, offsets
);
2069 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2071 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2072 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2073 flags
|= ETO_GLYPH_INDEX
;
2076 if (PATH_IsPathOpen(dc
->path
))
2077 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2078 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2080 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2081 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2085 HeapFree(GetProcessHeap(), 0, deltas
);
2086 if(glyphs
!= reordered_str
)
2087 HeapFree(GetProcessHeap(), 0, glyphs
);
2088 if(reordered_str
!= str
)
2089 HeapFree(GetProcessHeap(), 0, reordered_str
);
2091 release_dc_ptr( dc
);
2093 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2095 int underlinePos
, strikeoutPos
;
2096 int underlineWidth
, strikeoutWidth
;
2097 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2098 OUTLINETEXTMETRICW
* otm
= NULL
;
2103 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2104 strikeoutPos
= tm
.tmAscent
/ 2;
2105 strikeoutWidth
= underlineWidth
;
2109 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2110 GetOutlineTextMetricsW(hdc
, size
, otm
);
2111 underlinePos
= otm
->otmsUnderscorePosition
;
2112 underlineWidth
= otm
->otmsUnderscoreSize
;
2113 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2114 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2115 HeapFree(GetProcessHeap(), 0, otm
);
2118 if (PATH_IsPathOpen(dc
->path
))
2122 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2124 hbrush
= SelectObject(hdc
, hbrush
);
2125 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2129 pts
[0].x
= x
- underlinePos
* sinEsc
;
2130 pts
[0].y
= y
- underlinePos
* cosEsc
;
2131 pts
[1].x
= x
+ width
.x
- underlinePos
* sinEsc
;
2132 pts
[1].y
= y
+ width
.y
- underlinePos
* cosEsc
;
2133 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2134 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2135 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2136 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2137 pts
[4].x
= pts
[0].x
;
2138 pts
[4].y
= pts
[0].y
;
2139 DPtoLP(hdc
, pts
, 5);
2140 Polygon(hdc
, pts
, 5);
2145 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2146 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2147 pts
[1].x
= x
+ width
.x
- strikeoutPos
* sinEsc
;
2148 pts
[1].y
= y
+ width
.y
- strikeoutPos
* cosEsc
;
2149 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2150 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2151 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2152 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2153 pts
[4].x
= pts
[0].x
;
2154 pts
[4].y
= pts
[0].y
;
2155 DPtoLP(hdc
, pts
, 5);
2156 Polygon(hdc
, pts
, 5);
2159 SelectObject(hdc
, hpen
);
2160 hbrush
= SelectObject(hdc
, hbrush
);
2161 DeleteObject(hbrush
);
2165 POINT pts
[2], oldpt
;
2170 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2171 hpen
= SelectObject(hdc
, hpen
);
2174 pts
[1].x
= x
+ width
.x
;
2175 pts
[1].y
= y
+ width
.y
;
2176 DPtoLP(hdc
, pts
, 2);
2177 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2178 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2179 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2180 DeleteObject(SelectObject(hdc
, hpen
));
2185 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2186 hpen
= SelectObject(hdc
, hpen
);
2189 pts
[1].x
= x
+ width
.x
;
2190 pts
[1].y
= y
+ width
.y
;
2191 DPtoLP(hdc
, pts
, 2);
2192 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2193 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2194 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2195 DeleteObject(SelectObject(hdc
, hpen
));
2204 /***********************************************************************
2205 * TextOutA (GDI32.@)
2207 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2209 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2213 /***********************************************************************
2214 * TextOutW (GDI32.@)
2216 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2218 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2222 /***********************************************************************
2223 * PolyTextOutA (GDI32.@)
2227 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2229 for (; cStrings
>0; cStrings
--, pptxt
++)
2230 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2237 /***********************************************************************
2238 * PolyTextOutW (GDI32.@)
2240 * Draw several Strings
2246 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2248 for (; cStrings
>0; cStrings
--, pptxt
++)
2249 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2255 /* FIXME: all following APIs ******************************************/
2258 /***********************************************************************
2259 * SetMapperFlags (GDI32.@)
2261 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2263 DC
*dc
= get_dc_ptr( hDC
);
2266 if(dc
->funcs
->pSetMapperFlags
)
2268 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2269 /* FIXME: ret is just a success flag, we should return a proper value */
2272 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2273 release_dc_ptr( dc
);
2277 /***********************************************************************
2278 * GetAspectRatioFilterEx (GDI32.@)
2280 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2282 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2287 /***********************************************************************
2288 * GetCharABCWidthsA (GDI32.@)
2290 * See GetCharABCWidthsW.
2292 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2295 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2300 if(count
<= 0) return FALSE
;
2302 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2303 for(i
= 0; i
< count
; i
++)
2304 str
[i
] = (BYTE
)(firstChar
+ i
);
2306 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2308 for(i
= 0; i
< wlen
; i
++)
2310 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2318 HeapFree(GetProcessHeap(), 0, str
);
2319 HeapFree(GetProcessHeap(), 0, wstr
);
2325 /******************************************************************************
2326 * GetCharABCWidthsW [GDI32.@]
2328 * Retrieves widths of characters in range.
2331 * hdc [I] Handle of device context
2332 * firstChar [I] First character in range to query
2333 * lastChar [I] Last character in range to query
2334 * abc [O] Address of character-width structure
2337 * Only works with TrueType fonts
2343 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2346 DC
*dc
= get_dc_ptr(hdc
);
2350 if (!dc
) return FALSE
;
2354 release_dc_ptr( dc
);
2359 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2365 /* convert device units to logical */
2366 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2367 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2368 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2369 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2374 release_dc_ptr( dc
);
2379 /******************************************************************************
2380 * GetCharABCWidthsI [GDI32.@]
2382 * Retrieves widths of characters in range.
2385 * hdc [I] Handle of device context
2386 * firstChar [I] First glyphs in range to query
2387 * count [I] Last glyphs in range to query
2388 * pgi [i] Array of glyphs to query
2389 * abc [O] Address of character-width structure
2392 * Only works with TrueType fonts
2398 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2399 LPWORD pgi
, LPABC abc
)
2401 DC
*dc
= get_dc_ptr(hdc
);
2405 if (!dc
) return FALSE
;
2409 release_dc_ptr( dc
);
2414 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2420 /* convert device units to logical */
2421 for( i
= 0; i
< count
; i
++, abc
++ ) {
2422 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2423 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2424 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2429 release_dc_ptr( dc
);
2434 /***********************************************************************
2435 * GetGlyphOutlineA (GDI32.@)
2437 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2438 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2439 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2445 if (!lpmat2
) return GDI_ERROR
;
2447 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2450 if(uChar
> 0xff) { /* but, 2 bytes character only */
2452 mbchs
[0] = (uChar
& 0xff00) >> 8;
2453 mbchs
[1] = (uChar
& 0xff);
2456 mbchs
[0] = (uChar
& 0xff);
2458 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2462 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2464 HeapFree(GetProcessHeap(), 0, p
);
2468 /***********************************************************************
2469 * GetGlyphOutlineW (GDI32.@)
2471 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2472 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2473 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2478 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2479 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2481 if (!lpmat2
) return GDI_ERROR
;
2483 dc
= get_dc_ptr(hdc
);
2484 if(!dc
) return GDI_ERROR
;
2487 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2488 cbBuffer
, lpBuffer
, lpmat2
);
2492 release_dc_ptr( dc
);
2497 /***********************************************************************
2498 * CreateScalableFontResourceA (GDI32.@)
2500 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2501 LPCSTR lpszResourceFile
,
2502 LPCSTR lpszFontFile
,
2503 LPCSTR lpszCurrentPath
)
2505 LPWSTR lpszResourceFileW
= NULL
;
2506 LPWSTR lpszFontFileW
= NULL
;
2507 LPWSTR lpszCurrentPathW
= NULL
;
2511 if (lpszResourceFile
)
2513 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2514 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2515 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2520 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2521 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2522 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2525 if (lpszCurrentPath
)
2527 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2528 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2529 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2532 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2533 lpszFontFileW
, lpszCurrentPathW
);
2535 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2536 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2537 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2542 /***********************************************************************
2543 * CreateScalableFontResourceW (GDI32.@)
2545 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2546 LPCWSTR lpszResourceFile
,
2547 LPCWSTR lpszFontFile
,
2548 LPCWSTR lpszCurrentPath
)
2551 FIXME("(%d,%s,%s,%s): stub\n",
2552 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2553 debugstr_w(lpszCurrentPath
) );
2555 /* fHidden=1 - only visible for the calling app, read-only, not
2556 * enumerated with EnumFonts/EnumFontFamilies
2557 * lpszCurrentPath can be NULL
2560 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2561 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2563 SetLastError(ERROR_FILE_EXISTS
);
2566 return FALSE
; /* create failed */
2569 /*************************************************************************
2570 * GetKerningPairsA (GDI32.@)
2572 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2573 LPKERNINGPAIR kern_pairA
)
2577 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2578 KERNINGPAIR
*kern_pairW
;
2580 if (!cPairs
&& kern_pairA
)
2582 SetLastError(ERROR_INVALID_PARAMETER
);
2586 cp
= GdiGetCodePage(hDC
);
2588 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2589 * to fail on an invalid character for CP_SYMBOL.
2591 cpi
.DefaultChar
[0] = 0;
2592 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2594 FIXME("Can't find codepage %u info\n", cp
);
2598 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2599 if (!total_kern_pairs
) return 0;
2601 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2602 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2604 for (i
= 0; i
< total_kern_pairs
; i
++)
2608 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2611 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2614 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2619 if (kern_pairs_copied
>= cPairs
) break;
2621 kern_pairA
->wFirst
= (BYTE
)first
;
2622 kern_pairA
->wSecond
= (BYTE
)second
;
2623 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2626 kern_pairs_copied
++;
2629 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2631 return kern_pairs_copied
;
2634 /*************************************************************************
2635 * GetKerningPairsW (GDI32.@)
2637 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2638 LPKERNINGPAIR lpKerningPairs
)
2643 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2645 if (!cPairs
&& lpKerningPairs
)
2647 SetLastError(ERROR_INVALID_PARAMETER
);
2651 dc
= get_dc_ptr(hDC
);
2655 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2657 release_dc_ptr( dc
);
2661 /*************************************************************************
2662 * TranslateCharsetInfo [GDI32.@]
2664 * Fills a CHARSETINFO structure for a character set, code page, or
2665 * font. This allows making the correspondence between different labels
2666 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2667 * of the same encoding.
2669 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2670 * only one codepage should be set in *lpSrc.
2673 * TRUE on success, FALSE on failure.
2676 BOOL WINAPI
TranslateCharsetInfo(
2677 LPDWORD lpSrc
, /* [in]
2678 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2679 if flags == TCI_SRCCHARSET: a character set value
2680 if flags == TCI_SRCCODEPAGE: a code page value
2682 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2683 DWORD flags
/* [in] determines interpretation of lpSrc */)
2687 case TCI_SRCFONTSIG
:
2688 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2690 case TCI_SRCCODEPAGE
:
2691 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2693 case TCI_SRCCHARSET
:
2694 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2699 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2700 *lpCs
= FONT_tci
[index
];
2704 /*************************************************************************
2705 * GetFontLanguageInfo (GDI32.@)
2707 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2709 FONTSIGNATURE fontsig
;
2710 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2711 GCP_DIACRITIC_MASK
=0x00000000,
2712 FLI_GLYPHS_MASK
=0x00000000,
2713 GCP_GLYPHSHAPE_MASK
=0x00000040,
2714 GCP_KASHIDA_MASK
=0x00000000,
2715 GCP_LIGATE_MASK
=0x00000000,
2716 GCP_USEKERNING_MASK
=0x00000000,
2717 GCP_REORDER_MASK
=0x00000060;
2721 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2722 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2724 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2727 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2728 result
|=GCP_DIACRITIC
;
2730 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2733 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2734 result
|=GCP_GLYPHSHAPE
;
2736 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2737 result
|=GCP_KASHIDA
;
2739 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2742 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2743 result
|=GCP_USEKERNING
;
2745 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2746 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2747 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2748 result
|=GCP_REORDER
;
2754 /*************************************************************************
2755 * GetFontData [GDI32.@]
2757 * Retrieve data for TrueType font.
2761 * success: Number of bytes returned
2762 * failure: GDI_ERROR
2766 * Calls SetLastError()
2769 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2770 LPVOID buffer
, DWORD length
)
2772 DC
*dc
= get_dc_ptr(hdc
);
2773 DWORD ret
= GDI_ERROR
;
2775 if(!dc
) return GDI_ERROR
;
2778 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2780 release_dc_ptr( dc
);
2784 /*************************************************************************
2785 * GetGlyphIndicesA [GDI32.@]
2787 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2788 LPWORD pgi
, DWORD flags
)
2794 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2795 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2797 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2798 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2799 HeapFree(GetProcessHeap(), 0, lpstrW
);
2804 /*************************************************************************
2805 * GetGlyphIndicesW [GDI32.@]
2807 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2808 LPWORD pgi
, DWORD flags
)
2810 DC
*dc
= get_dc_ptr(hdc
);
2811 DWORD ret
= GDI_ERROR
;
2813 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2814 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2816 if(!dc
) return GDI_ERROR
;
2819 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2821 release_dc_ptr( dc
);
2825 /*************************************************************************
2826 * GetCharacterPlacementA [GDI32.@]
2828 * See GetCharacterPlacementW.
2831 * the web browser control of ie4 calls this with dwFlags=0
2834 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2835 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2840 GCP_RESULTSW resultsW
;
2844 TRACE("%s, %d, %d, 0x%08x\n",
2845 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2847 /* both structs are equal in size */
2848 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2850 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2851 if(lpResults
->lpOutString
)
2852 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2854 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2856 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2857 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2859 if(lpResults
->lpOutString
) {
2860 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2861 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2864 HeapFree(GetProcessHeap(), 0, lpStringW
);
2865 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2870 /*************************************************************************
2871 * GetCharacterPlacementW [GDI32.@]
2873 * Retrieve information about a string. This includes the width, reordering,
2874 * Glyphing and so on.
2878 * The width and height of the string if successful, 0 if failed.
2882 * All flags except GCP_REORDER are not yet implemented.
2883 * Reordering is not 100% compliant to the Windows BiDi method.
2884 * Caret positioning is not yet implemented for BiDi.
2885 * Classes are not yet implemented.
2889 GetCharacterPlacementW(
2890 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2891 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2892 INT uCount
, /* [in] Number of WORDS in string. */
2893 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2894 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2895 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2902 TRACE("%s, %d, %d, 0x%08x\n",
2903 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2905 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2906 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2907 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2908 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2909 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2911 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2912 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2913 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2914 FIXME("Caret positions for complex scripts not implemented\n");
2916 nSet
= (UINT
)uCount
;
2917 if(nSet
> lpResults
->nGlyphs
)
2918 nSet
= lpResults
->nGlyphs
;
2920 /* return number of initialized fields */
2921 lpResults
->nGlyphs
= nSet
;
2923 if((dwFlags
&GCP_REORDER
)==0 )
2925 /* Treat the case where no special handling was requested in a fastpath way */
2926 /* copy will do if the GCP_REORDER flag is not set */
2927 if(lpResults
->lpOutString
)
2928 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2930 if(lpResults
->lpOrder
)
2932 for(i
= 0; i
< nSet
; i
++)
2933 lpResults
->lpOrder
[i
] = i
;
2937 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2938 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
2941 /* FIXME: Will use the placement chars */
2942 if (lpResults
->lpDx
)
2945 for (i
= 0; i
< nSet
; i
++)
2947 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2948 lpResults
->lpDx
[i
]= c
;
2952 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2956 lpResults
->lpCaretPos
[0] = 0;
2957 for (i
= 1; i
< nSet
; i
++)
2958 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2959 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2962 if(lpResults
->lpGlyphs
)
2963 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2965 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2966 ret
= MAKELONG(size
.cx
, size
.cy
);
2971 /*************************************************************************
2972 * GetCharABCWidthsFloatA [GDI32.@]
2974 * See GetCharABCWidthsFloatW.
2976 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2978 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
2983 if (count
<= 0) return FALSE
;
2985 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2987 for(i
= 0; i
< count
; i
++)
2988 str
[i
] = (BYTE
)(first
+ i
);
2990 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
2992 for (i
= 0; i
< wlen
; i
++)
2994 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3002 HeapFree( GetProcessHeap(), 0, str
);
3003 HeapFree( GetProcessHeap(), 0, wstr
);
3008 /*************************************************************************
3009 * GetCharABCWidthsFloatW [GDI32.@]
3011 * Retrieves widths of a range of characters.
3014 * hdc [I] Handle to device context.
3015 * first [I] First character in range to query.
3016 * last [I] Last character in range to query.
3017 * abcf [O] Array of LPABCFLOAT structures.
3023 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3027 DC
*dc
= get_dc_ptr( hdc
);
3029 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3031 if (!dc
) return FALSE
;
3035 release_dc_ptr( dc
);
3040 ret
= WineEngGetCharABCWidthsFloat( dc
->gdiFont
, first
, last
, abcf
);
3046 /* convert device units to logical */
3047 for (i
= first
; i
<= last
; i
++, abcf
++)
3049 abcf
->abcfA
= abcf
->abcfA
* dc
->xformVport2World
.eM11
;
3050 abcf
->abcfB
= abcf
->abcfB
* dc
->xformVport2World
.eM11
;
3051 abcf
->abcfC
= abcf
->abcfC
* dc
->xformVport2World
.eM11
;
3055 release_dc_ptr( dc
);
3059 /*************************************************************************
3060 * GetCharWidthFloatA [GDI32.@]
3062 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3063 UINT iLastChar
, PFLOAT pxBuffer
)
3065 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3069 /*************************************************************************
3070 * GetCharWidthFloatW [GDI32.@]
3072 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3073 UINT iLastChar
, PFLOAT pxBuffer
)
3075 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3080 /***********************************************************************
3082 * Font Resource API *
3084 ***********************************************************************/
3086 /***********************************************************************
3087 * AddFontResourceA (GDI32.@)
3089 INT WINAPI
AddFontResourceA( LPCSTR str
)
3091 return AddFontResourceExA( str
, 0, NULL
);
3094 /***********************************************************************
3095 * AddFontResourceW (GDI32.@)
3097 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3099 return AddFontResourceExW(str
, 0, NULL
);
3103 /***********************************************************************
3104 * AddFontResourceExA (GDI32.@)
3106 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3108 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3109 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3112 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3113 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3114 HeapFree(GetProcessHeap(), 0, strW
);
3118 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3120 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3121 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3122 LPVOID
*pMem
= LockResource(hMem
);
3123 int *num_total
= (int *)lParam
;
3126 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3127 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3129 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3133 *num_total
+= num_in_res
;
3137 /***********************************************************************
3138 * AddFontResourceExW (GDI32.@)
3140 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3142 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3145 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3146 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3147 if (hModule
!= NULL
)
3149 int num_resources
= 0;
3150 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3152 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3153 wine_dbgstr_w(str
));
3154 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3155 ret
= num_resources
;
3156 FreeLibrary(hModule
);
3162 /***********************************************************************
3163 * RemoveFontResourceA (GDI32.@)
3165 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3167 return RemoveFontResourceExA(str
, 0, 0);
3170 /***********************************************************************
3171 * RemoveFontResourceW (GDI32.@)
3173 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3175 return RemoveFontResourceExW(str
, 0, 0);
3178 /***********************************************************************
3179 * AddFontMemResourceEx (GDI32.@)
3181 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3183 return WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, pcFonts
);
3186 /***********************************************************************
3187 * RemoveFontMemResourceEx (GDI32.@)
3189 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3191 FIXME("(%p) stub\n", fh
);
3195 /***********************************************************************
3196 * RemoveFontResourceExA (GDI32.@)
3198 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3200 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3201 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3204 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3205 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3206 HeapFree(GetProcessHeap(), 0, strW
);
3210 /***********************************************************************
3211 * RemoveFontResourceExW (GDI32.@)
3213 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3215 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3218 /***********************************************************************
3219 * GetTextCharset (GDI32.@)
3221 UINT WINAPI
GetTextCharset(HDC hdc
)
3223 /* MSDN docs say this is equivalent */
3224 return GetTextCharsetInfo(hdc
, NULL
, 0);
3227 /***********************************************************************
3228 * GetTextCharsetInfo (GDI32.@)
3230 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3232 UINT ret
= DEFAULT_CHARSET
;
3233 DC
*dc
= get_dc_ptr(hdc
);
3238 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3240 release_dc_ptr( dc
);
3243 if (ret
== DEFAULT_CHARSET
&& fs
)
3244 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3248 /***********************************************************************
3249 * GdiGetCharDimensions (GDI32.@)
3251 * Gets the average width of the characters in the English alphabet.
3254 * hdc [I] Handle to the device context to measure on.
3255 * lptm [O] Pointer to memory to store the text metrics into.
3256 * height [O] On exit, the maximum height of characters in the English alphabet.
3259 * The average width of characters in the English alphabet.
3262 * This function is used by the dialog manager to get the size of a dialog
3263 * unit. It should also be used by other pieces of code that need to know
3264 * the size of a dialog unit in logical units without having access to the
3265 * window handle of the dialog.
3266 * Windows caches the font metrics from this function, but we don't and
3267 * there doesn't appear to be an immediate advantage to do so.
3270 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3272 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3275 static const WCHAR alphabet
[] = {
3276 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3277 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3278 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3280 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3282 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3284 if (height
) *height
= sz
.cy
;
3285 return (sz
.cx
/ 26 + 1) / 2;
3288 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3290 FIXME("(%d): stub\n", fEnableEUDC
);
3294 /***********************************************************************
3295 * GetCharWidthI (GDI32.@)
3297 * Retrieve widths of characters.
3300 * hdc [I] Handle to a device context.
3301 * first [I] First glyph in range to query.
3302 * count [I] Number of glyph indices to query.
3303 * glyphs [I] Array of glyphs to query.
3304 * buffer [O] Buffer to receive character widths.
3307 * Only works with TrueType fonts.
3313 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3318 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3320 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3323 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3325 HeapFree(GetProcessHeap(), 0, abc
);
3329 for (i
= 0; i
< count
; i
++)
3330 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3332 HeapFree(GetProcessHeap(), 0, abc
);
3336 /***********************************************************************
3337 * GetFontUnicodeRanges (GDI32.@)
3339 * Retrieve a list of supported Unicode characters in a font.
3342 * hdc [I] Handle to a device context.
3343 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3346 * Success: Number of bytes written to the buffer pointed to by lpgs.
3350 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3353 DC
*dc
= get_dc_ptr(hdc
);
3355 TRACE("(%p, %p)\n", hdc
, lpgs
);
3359 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3365 /*************************************************************
3366 * FontIsLinked (GDI32.@)
3368 BOOL WINAPI
FontIsLinked(HDC hdc
)
3370 DC
*dc
= get_dc_ptr(hdc
);
3373 if (!dc
) return FALSE
;
3374 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3376 TRACE("returning %d\n", ret
);
3380 /*************************************************************
3381 * GdiRealizationInfo (GDI32.@)
3383 * Returns a structure that contains some font information.
3385 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3387 DC
*dc
= get_dc_ptr(hdc
);
3390 if (!dc
) return FALSE
;
3391 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);