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/exception.h"
37 #include "wine/unicode.h"
38 #include "wine/debug.h"
40 WINE_DEFAULT_DEBUG_CHANNEL(font
);
42 /* Device -> World size conversion */
44 /* Performs a device to world transformation on the specified width (which
45 * is in integer format).
47 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
51 /* Perform operation with floating point */
52 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
53 /* Round to integers */
54 return GDI_ROUND(floatWidth
);
57 /* Performs a device to world transformation on the specified size (which
58 * is in integer format).
60 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
64 /* Perform operation with floating point */
65 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
66 /* Round to integers */
67 return GDI_ROUND(floatHeight
);
70 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
73 pt
[0].x
= pt
[0].y
= 0;
76 LPtoDP(dc
->hSelf
, pt
, 2);
77 return pt
[1].x
- pt
[0].x
;
80 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
83 pt
[0].x
= pt
[0].y
= 0;
86 LPtoDP(dc
->hSelf
, pt
, 2);
87 return pt
[1].y
- pt
[0].y
;
90 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
91 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
92 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
93 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
95 static const struct gdi_obj_funcs font_funcs
=
97 FONT_SelectObject
, /* pSelectObject */
98 FONT_GetObjectA
, /* pGetObjectA */
99 FONT_GetObjectW
, /* pGetObjectW */
100 NULL
, /* pUnrealizeObject */
101 FONT_DeleteObject
/* pDeleteObject */
104 #define ENUM_UNICODE 0x00000001
105 #define ENUM_CALLED 0x00000002
115 LPLOGFONTW lpLogFontParam
;
116 FONTENUMPROCW lpEnumFunc
;
123 * For TranslateCharsetInfo
125 #define MAXTCIINDEX 32
126 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
128 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
129 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
130 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
131 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
132 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
133 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
134 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
135 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
136 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
137 /* reserved by ANSI */
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}} },
144 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
146 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
147 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
148 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
149 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
150 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
151 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
152 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
161 /* reserved for system */
162 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
163 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
166 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
168 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
169 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
171 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
174 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
176 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
177 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
178 LF_FACESIZE
, NULL
, NULL
);
179 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
182 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
184 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
186 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
187 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
188 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
189 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
190 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
191 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
192 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
193 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
194 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
197 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
199 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
201 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
202 fontW
->elfFullName
, LF_FULLFACESIZE
);
203 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
204 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
205 fontW
->elfStyle
, LF_FACESIZE
);
206 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
207 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
208 fontW
->elfScript
, LF_FACESIZE
);
209 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
212 /***********************************************************************
213 * TEXTMETRIC conversion functions.
215 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
217 ptmA
->tmHeight
= ptmW
->tmHeight
;
218 ptmA
->tmAscent
= ptmW
->tmAscent
;
219 ptmA
->tmDescent
= ptmW
->tmDescent
;
220 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
221 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
222 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
223 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
224 ptmA
->tmWeight
= ptmW
->tmWeight
;
225 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
226 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
227 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
228 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
229 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
231 ptmA
->tmFirstChar
= 0x1e;
232 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
236 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
237 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
239 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
240 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
241 ptmA
->tmItalic
= ptmW
->tmItalic
;
242 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
243 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
244 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
245 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
249 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
251 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
252 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
253 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
254 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
255 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
256 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
260 /***********************************************************************
261 * GdiGetCodePage (GDI32.@)
263 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
266 DC
*dc
= get_dc_ptr( hdc
);
270 cp
= dc
->font_code_page
;
271 release_dc_ptr( dc
);
276 /***********************************************************************
279 * Returns a Unicode translation of str using the charset of the
280 * currently selected font in hdc. If count is -1 then str is assumed
281 * to be '\0' terminated, otherwise it contains the number of bytes to
282 * convert. If plenW is non-NULL, on return it will point to the
283 * number of WCHARs that have been written. If pCP is non-NULL, on
284 * return it will point to the codepage used in the conversion. The
285 * caller should free the returned LPWSTR from the process heap
288 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
294 cp
= GdiGetCodePage( hdc
);
296 if(count
== -1) count
= strlen(str
);
297 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
298 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
299 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
300 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
301 if(plenW
) *plenW
= lenW
;
306 /***********************************************************************
307 * CreateFontIndirectExA (GDI32.@)
309 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
311 ENUMLOGFONTEXDVW enumexW
;
313 if (!penumexA
) return 0;
315 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
316 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
317 return CreateFontIndirectExW( &enumexW
);
320 /***********************************************************************
321 * CreateFontIndirectExW (GDI32.@)
323 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
329 if (!penumex
) return 0;
331 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
332 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
333 penumex
->elfEnumLogfontEx
.elfScript
[0])
335 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
336 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
337 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
338 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
341 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
342 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
344 fontPtr
->logfont
= *plf
;
346 if (plf
->lfEscapement
!= plf
->lfOrientation
)
348 /* this should really depend on whether GM_ADVANCED is set */
349 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
350 WARN("orientation angle %f set to "
351 "escapement angle %f for new font %p\n",
352 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
355 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
357 HeapFree( GetProcessHeap(), 0, fontPtr
);
361 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
362 plf
->lfHeight
, plf
->lfWidth
,
363 plf
->lfEscapement
, plf
->lfOrientation
,
364 plf
->lfPitchAndFamily
,
365 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
366 plf
->lfQuality
, plf
->lfCharSet
,
367 debugstr_w(plf
->lfFaceName
),
368 plf
->lfWeight
> 400 ? "Bold" : "",
369 plf
->lfItalic
? "Italic" : "",
370 plf
->lfUnderline
? "Underline" : "", hFont
);
375 /***********************************************************************
376 * CreateFontIndirectA (GDI32.@)
378 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
384 FONT_LogFontAToW( plfA
, &lfW
);
385 return CreateFontIndirectW( &lfW
);
388 /***********************************************************************
389 * CreateFontIndirectW (GDI32.@)
391 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
393 ENUMLOGFONTEXDVW exdv
;
397 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
398 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
399 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
400 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
401 return CreateFontIndirectExW( &exdv
);
404 /*************************************************************************
405 * CreateFontA (GDI32.@)
407 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
408 INT orient
, INT weight
, DWORD italic
,
409 DWORD underline
, DWORD strikeout
, DWORD charset
,
410 DWORD outpres
, DWORD clippres
, DWORD quality
,
411 DWORD pitch
, LPCSTR name
)
415 logfont
.lfHeight
= height
;
416 logfont
.lfWidth
= width
;
417 logfont
.lfEscapement
= esc
;
418 logfont
.lfOrientation
= orient
;
419 logfont
.lfWeight
= weight
;
420 logfont
.lfItalic
= italic
;
421 logfont
.lfUnderline
= underline
;
422 logfont
.lfStrikeOut
= strikeout
;
423 logfont
.lfCharSet
= charset
;
424 logfont
.lfOutPrecision
= outpres
;
425 logfont
.lfClipPrecision
= clippres
;
426 logfont
.lfQuality
= quality
;
427 logfont
.lfPitchAndFamily
= pitch
;
430 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
432 logfont
.lfFaceName
[0] = '\0';
434 return CreateFontIndirectA( &logfont
);
437 /*************************************************************************
438 * CreateFontW (GDI32.@)
440 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
441 INT orient
, INT weight
, DWORD italic
,
442 DWORD underline
, DWORD strikeout
, DWORD charset
,
443 DWORD outpres
, DWORD clippres
, DWORD quality
,
444 DWORD pitch
, LPCWSTR name
)
448 logfont
.lfHeight
= height
;
449 logfont
.lfWidth
= width
;
450 logfont
.lfEscapement
= esc
;
451 logfont
.lfOrientation
= orient
;
452 logfont
.lfWeight
= weight
;
453 logfont
.lfItalic
= italic
;
454 logfont
.lfUnderline
= underline
;
455 logfont
.lfStrikeOut
= strikeout
;
456 logfont
.lfCharSet
= charset
;
457 logfont
.lfOutPrecision
= outpres
;
458 logfont
.lfClipPrecision
= clippres
;
459 logfont
.lfQuality
= quality
;
460 logfont
.lfPitchAndFamily
= pitch
;
463 lstrcpynW(logfont
.lfFaceName
, name
,
464 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
466 logfont
.lfFaceName
[0] = '\0';
468 return CreateFontIndirectW( &logfont
);
471 static void update_font_code_page( DC
*dc
)
474 int charset
= DEFAULT_CHARSET
;
477 charset
= WineEngGetTextCharsetInfo( dc
->gdiFont
, NULL
, 0 );
479 /* Hmm, nicely designed api this one! */
480 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
481 dc
->font_code_page
= csi
.ciACP
;
485 dc
->font_code_page
= GetOEMCP();
487 case DEFAULT_CHARSET
:
488 dc
->font_code_page
= GetACP();
498 /* FIXME: These have no place here, but because x11drv
499 enumerates fonts with these (made up) charsets some apps
500 might use them and then the FIXME below would become
501 annoying. Now we could pick the intended codepage for
502 each of these, but since it's broken anyway we'll just
503 use CP_ACP and hope it'll go away...
505 dc
->font_code_page
= CP_ACP
;
509 FIXME("Can't find codepage for charset %d\n", charset
);
510 dc
->font_code_page
= CP_ACP
;
515 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
518 /***********************************************************************
521 * If the driver supports vector fonts we create a gdi font first and
522 * then call the driver to give it a chance to supply its own device
523 * font. If the driver wants to do this it returns TRUE and we can
524 * delete the gdi font, if the driver wants to use the gdi font it
525 * should return FALSE, to signal an error return GDI_ERROR. For
526 * drivers that don't support vector fonts they must supply their own
529 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
532 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 if (dc
->funcs
->pSelectFont
) ret
= dc
->funcs
->pSelectFont( dc
->physDev
, handle
, dc
->gdiFont
);
547 if (ret
&& dc
->gdiFont
) dc
->gdiFont
= 0;
549 if (ret
== HGDI_ERROR
)
551 GDI_dec_ref_count( handle
);
552 ret
= 0; /* SelectObject returns 0 on error */
558 update_font_code_page( dc
);
559 GDI_dec_ref_count( ret
);
561 release_dc_ptr( dc
);
566 /***********************************************************************
569 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
571 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
577 FONT_LogFontWToA( &font
->logfont
, &lfA
);
578 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
579 memcpy( buffer
, &lfA
, count
);
581 else count
= sizeof(lfA
);
582 GDI_ReleaseObj( handle
);
586 /***********************************************************************
589 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
591 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
596 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
597 memcpy( buffer
, &font
->logfont
, count
);
599 else count
= sizeof(LOGFONTW
);
600 GDI_ReleaseObj( handle
);
605 /***********************************************************************
608 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
612 WineEngDestroyFontInstance( handle
);
614 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
615 return HeapFree( GetProcessHeap(), 0, obj
);
619 /***********************************************************************
622 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
623 * We have to use other types because of the FONTENUMPROCW definition.
625 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
626 DWORD fType
, LPARAM lp
)
628 fontEnum32
*pfe
= (fontEnum32
*)lp
;
631 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
632 if ((!pfe
->lpLogFontParam
||
633 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
634 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
635 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
637 /* convert font metrics */
638 ENUMLOGFONTEXA logfont
;
639 NEWTEXTMETRICEXA tmA
;
641 pfe
->dwFlags
|= ENUM_CALLED
;
642 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
644 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
645 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
646 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
647 ptm
= (TEXTMETRICW
*)&tmA
;
650 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
655 /***********************************************************************
656 * FONT_EnumFontFamiliesEx
658 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
659 FONTENUMPROCW efproc
,
660 LPARAM lParam
, DWORD dwUnicode
)
663 DC
*dc
= get_dc_ptr( hDC
);
670 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
672 fe32
.lpLogFontParam
= plf
;
673 fe32
.lpEnumFunc
= efproc
;
674 fe32
.lpData
= lParam
;
675 fe32
.dwFlags
= dwUnicode
;
678 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
680 if (!dc
->funcs
->pEnumDeviceFonts
&& !enum_gdi_fonts
)
687 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
688 fe32
.dwFlags
&= ~ENUM_CALLED
;
689 if (ret
&& dc
->funcs
->pEnumDeviceFonts
) {
690 ret2
= dc
->funcs
->pEnumDeviceFonts( dc
->physDev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
691 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
695 release_dc_ptr( dc
);
699 /***********************************************************************
700 * EnumFontFamiliesExW (GDI32.@)
702 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
703 FONTENUMPROCW efproc
,
704 LPARAM lParam
, DWORD dwFlags
)
706 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
709 /***********************************************************************
710 * EnumFontFamiliesExA (GDI32.@)
712 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
713 FONTENUMPROCA efproc
,
714 LPARAM lParam
, DWORD dwFlags
)
720 FONT_LogFontAToW( plf
, &lfW
);
725 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
728 /***********************************************************************
729 * EnumFontFamiliesA (GDI32.@)
731 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
732 FONTENUMPROCA efproc
, LPARAM lpData
)
738 if (!*lpFamily
) return 1;
739 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
740 lf
.lfCharSet
= DEFAULT_CHARSET
;
741 lf
.lfPitchAndFamily
= 0;
746 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
749 /***********************************************************************
750 * EnumFontFamiliesW (GDI32.@)
752 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
753 FONTENUMPROCW efproc
, LPARAM lpData
)
759 if (!*lpFamily
) return 1;
760 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
761 lf
.lfCharSet
= DEFAULT_CHARSET
;
762 lf
.lfPitchAndFamily
= 0;
767 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
770 /***********************************************************************
771 * EnumFontsA (GDI32.@)
773 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
776 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
779 /***********************************************************************
780 * EnumFontsW (GDI32.@)
782 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
785 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
789 /***********************************************************************
790 * GetTextCharacterExtra (GDI32.@)
792 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
795 DC
*dc
= get_dc_ptr( hdc
);
796 if (!dc
) return 0x80000000;
798 release_dc_ptr( dc
);
803 /***********************************************************************
804 * SetTextCharacterExtra (GDI32.@)
806 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
809 DC
* dc
= get_dc_ptr( hdc
);
810 if (!dc
) return 0x80000000;
811 if (dc
->funcs
->pSetTextCharacterExtra
)
812 prev
= dc
->funcs
->pSetTextCharacterExtra( dc
->physDev
, extra
);
815 prev
= dc
->charExtra
;
816 dc
->charExtra
= extra
;
818 release_dc_ptr( dc
);
823 /***********************************************************************
824 * SetTextJustification (GDI32.@)
826 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
829 DC
* dc
= get_dc_ptr( hdc
);
830 if (!dc
) return FALSE
;
831 if (dc
->funcs
->pSetTextJustification
)
832 ret
= dc
->funcs
->pSetTextJustification( dc
->physDev
, extra
, breaks
);
835 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
836 if (!extra
) breaks
= 0;
839 dc
->breakExtra
= extra
/ breaks
;
840 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
848 release_dc_ptr( dc
);
853 /***********************************************************************
854 * GetTextFaceA (GDI32.@)
856 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
858 INT res
= GetTextFaceW(hdc
, 0, NULL
);
859 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
860 GetTextFaceW( hdc
, res
, nameW
);
866 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
870 /* GetTextFaceA does NOT include the nul byte in the return count. */
877 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
878 HeapFree( GetProcessHeap(), 0, nameW
);
882 /***********************************************************************
883 * GetTextFaceW (GDI32.@)
885 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
890 DC
* dc
= get_dc_ptr( hdc
);
894 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
895 else if ((font
= GDI_GetObjPtr( dc
->hFont
, OBJ_FONT
)))
897 INT n
= strlenW(font
->logfont
.lfFaceName
) + 1;
900 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
904 GDI_ReleaseObj( dc
->hFont
);
906 release_dc_ptr( dc
);
911 /***********************************************************************
912 * GetTextExtentPoint32A (GDI32.@)
914 * See GetTextExtentPoint32W.
916 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
921 LPWSTR p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
924 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
925 HeapFree( GetProcessHeap(), 0, p
);
928 TRACE("(%p %s %d %p): returning %d x %d\n",
929 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
934 /***********************************************************************
935 * GetTextExtentPoint32W [GDI32.@]
937 * Computes width/height for a string.
939 * Computes width and height of the specified string.
945 BOOL WINAPI
GetTextExtentPoint32W(
946 HDC hdc
, /* [in] Handle of device context */
947 LPCWSTR str
, /* [in] Address of text string */
948 INT count
, /* [in] Number of characters in string */
949 LPSIZE size
) /* [out] Address of structure for string size */
951 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
954 /***********************************************************************
955 * GetTextExtentExPointI [GDI32.@]
957 * Computes width and height of the array of glyph indices.
960 * hdc [I] Handle of device context.
961 * indices [I] Glyph index array.
962 * count [I] Number of glyphs in array.
963 * max_ext [I] Maximum width in glyphs.
964 * nfit [O] Maximum number of characters.
965 * dxs [O] Partial string widths.
966 * size [O] Returned string size.
972 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
973 LPINT nfit
, LPINT dxs
, LPSIZE size
)
976 DC
* dc
= get_dc_ptr( hdc
);
977 if (!dc
) return FALSE
;
980 ret
= WineEngGetTextExtentExPointI(dc
->gdiFont
, indices
, count
, max_ext
, nfit
, dxs
, size
);
981 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
982 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
983 size
->cx
+= count
* dc
->charExtra
;
985 else if(dc
->funcs
->pGetTextExtentExPoint
) {
986 FIXME("calling GetTextExtentExPoint\n");
987 ret
= dc
->funcs
->pGetTextExtentExPoint( dc
->physDev
, indices
, count
,
988 max_ext
, nfit
, dxs
, size
);
991 release_dc_ptr( dc
);
993 TRACE("(%p %p %d %p): returning %d x %d\n",
994 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
998 /***********************************************************************
999 * GetTextExtentPointI [GDI32.@]
1001 * Computes width and height of the array of glyph indices.
1004 * hdc [I] Handle of device context.
1005 * indices [I] Glyph index array.
1006 * count [I] Number of glyphs in array.
1007 * size [O] Returned string size.
1013 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1015 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1019 /***********************************************************************
1020 * GetTextExtentPointA (GDI32.@)
1022 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1025 TRACE("not bug compatible.\n");
1026 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1029 /***********************************************************************
1030 * GetTextExtentPointW (GDI32.@)
1032 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1035 TRACE("not bug compatible.\n");
1036 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1040 /***********************************************************************
1041 * GetTextExtentExPointA (GDI32.@)
1043 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1044 INT maxExt
, LPINT lpnFit
,
1045 LPINT alpDx
, LPSIZE size
)
1053 NULL
== (walpDx
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(INT
))))
1056 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1057 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1060 INT n
= lpnFit
? *lpnFit
: wlen
;
1062 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1064 alpDx
[j
] = walpDx
[i
];
1065 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1068 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1069 HeapFree( GetProcessHeap(), 0, p
);
1070 HeapFree( GetProcessHeap(), 0, walpDx
);
1075 /***********************************************************************
1076 * GetTextExtentExPointW (GDI32.@)
1078 * Return the size of the string as it would be if it was output properly by
1081 * This should include
1082 * - Intercharacter spacing
1083 * - justification spacing (not yet done)
1084 * - kerning? see below
1086 * Kerning. Since kerning would be carried out by the rendering code it should
1087 * be done by the driver. However they don't support it yet. Also I am not
1088 * yet persuaded that (certainly under Win95) any kerning is actually done.
1090 * str: According to MSDN this should be null-terminated. That is not true; a
1091 * null will not terminate it early.
1092 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1093 * than count. I have seen it be either the size of the full string or
1094 * 1 less than the size of the full string. I have not seen it bear any
1095 * resemblance to the portion that would fit.
1096 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1097 * trailing intercharacter spacing and any trailing justification.
1100 * Currently we do this by measuring each character etc. We should do it by
1101 * passing the request to the driver, perhaps by extending the
1102 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1103 * thinking about kerning issues and rounding issues in the justification.
1106 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1107 INT maxExt
, LPINT lpnFit
,
1108 LPINT alpDx
, LPSIZE size
)
1116 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1118 dc
= get_dc_ptr(hdc
);
1122 GetTextMetricsW(hdc
, &tm
);
1124 /* If we need to calculate nFit, then we need the partial extents even if
1125 the user hasn't provided us with an array. */
1128 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1132 SetLastError(ERROR_OUTOFMEMORY
);
1140 ret
= WineEngGetTextExtentExPoint(dc
->gdiFont
, str
, count
,
1141 0, NULL
, dxs
, size
);
1142 else if (dc
->funcs
->pGetTextExtentExPoint
)
1143 ret
= dc
->funcs
->pGetTextExtentExPoint(dc
->physDev
, str
, count
,
1144 0, NULL
, dxs
, size
);
1146 /* Perform device size to world size transformations. */
1149 INT extra
= dc
->charExtra
,
1150 breakExtra
= dc
->breakExtra
,
1151 breakRem
= dc
->breakRem
,
1156 for (i
= 0; i
< count
; ++i
)
1158 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1159 dxs
[i
] += (i
+1) * extra
;
1160 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1162 dxs
[i
] += breakExtra
;
1169 if (dxs
[i
] <= maxExt
)
1172 breakRem
= dc
->breakRem
;
1174 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1175 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1177 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1179 for (i
= 0; i
< count
; i
++)
1181 if (str
[i
] == tm
.tmBreakChar
)
1183 size
->cx
+= breakExtra
;
1198 HeapFree(GetProcessHeap(), 0, dxs
);
1200 release_dc_ptr( dc
);
1202 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1206 /***********************************************************************
1207 * GetTextMetricsA (GDI32.@)
1209 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1213 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1214 FONT_TextMetricWToA( &tm32
, metrics
);
1218 /***********************************************************************
1219 * GetTextMetricsW (GDI32.@)
1221 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1224 DC
* dc
= get_dc_ptr( hdc
);
1225 if (!dc
) return FALSE
;
1228 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1229 else if (dc
->funcs
->pGetTextMetrics
)
1230 ret
= dc
->funcs
->pGetTextMetrics( dc
->physDev
, metrics
);
1234 /* device layer returns values in device units
1235 * therefore we have to convert them to logical */
1237 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1238 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1240 #define WDPTOLP(x) ((x<0)? \
1241 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1242 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1243 #define HDPTOLP(y) ((y<0)? \
1244 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1245 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1247 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1248 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1249 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1250 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1251 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1252 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1253 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1254 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1258 TRACE("text metrics:\n"
1259 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1260 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1261 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1262 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1263 " PitchAndFamily = %02x\n"
1264 " --------------------\n"
1265 " InternalLeading = %i\n"
1269 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1270 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1271 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1272 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1273 metrics
->tmPitchAndFamily
,
1274 metrics
->tmInternalLeading
,
1277 metrics
->tmHeight
);
1279 release_dc_ptr( dc
);
1284 /***********************************************************************
1285 * GetOutlineTextMetricsA (GDI32.@)
1286 * Gets metrics for TrueType fonts.
1289 * If the supplied buffer isn't big enough Windows partially fills it up to
1290 * its given length and returns that length.
1293 * Success: Non-zero or size of required buffer
1296 UINT WINAPI
GetOutlineTextMetricsA(
1297 HDC hdc
, /* [in] Handle of device context */
1298 UINT cbData
, /* [in] Size of metric data array */
1299 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1301 char buf
[512], *ptr
;
1303 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1304 OUTLINETEXTMETRICA
*output
= lpOTM
;
1307 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1309 if(ret
> sizeof(buf
))
1310 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1311 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1313 needed
= sizeof(OUTLINETEXTMETRICA
);
1314 if(lpOTMW
->otmpFamilyName
)
1315 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1316 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1317 NULL
, 0, NULL
, NULL
);
1318 if(lpOTMW
->otmpFaceName
)
1319 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1320 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1321 NULL
, 0, NULL
, NULL
);
1322 if(lpOTMW
->otmpStyleName
)
1323 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1324 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1325 NULL
, 0, NULL
, NULL
);
1326 if(lpOTMW
->otmpFullName
)
1327 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1328 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1329 NULL
, 0, NULL
, NULL
);
1336 TRACE("needed = %d\n", needed
);
1338 /* Since the supplied buffer isn't big enough, we'll alloc one
1339 that is and memcpy the first cbData bytes into the lpOTM at
1341 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1343 ret
= output
->otmSize
= min(needed
, cbData
);
1344 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1345 output
->otmFiller
= 0;
1346 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1347 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1348 output
->otmfsType
= lpOTMW
->otmfsType
;
1349 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1350 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1351 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1352 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1353 output
->otmAscent
= lpOTMW
->otmAscent
;
1354 output
->otmDescent
= lpOTMW
->otmDescent
;
1355 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1356 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1357 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1358 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1359 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1360 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1361 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1362 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1363 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1364 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1365 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1366 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1367 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1368 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1369 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1370 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1373 ptr
= (char*)(output
+ 1);
1374 left
= needed
- sizeof(*output
);
1376 if(lpOTMW
->otmpFamilyName
) {
1377 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1378 len
= WideCharToMultiByte(CP_ACP
, 0,
1379 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1380 ptr
, left
, NULL
, NULL
);
1384 output
->otmpFamilyName
= 0;
1386 if(lpOTMW
->otmpFaceName
) {
1387 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1388 len
= WideCharToMultiByte(CP_ACP
, 0,
1389 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1390 ptr
, left
, NULL
, NULL
);
1394 output
->otmpFaceName
= 0;
1396 if(lpOTMW
->otmpStyleName
) {
1397 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1398 len
= WideCharToMultiByte(CP_ACP
, 0,
1399 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1400 ptr
, left
, NULL
, NULL
);
1404 output
->otmpStyleName
= 0;
1406 if(lpOTMW
->otmpFullName
) {
1407 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1408 len
= WideCharToMultiByte(CP_ACP
, 0,
1409 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1410 ptr
, left
, NULL
, NULL
);
1413 output
->otmpFullName
= 0;
1417 if(output
!= lpOTM
) {
1418 memcpy(lpOTM
, output
, cbData
);
1419 HeapFree(GetProcessHeap(), 0, output
);
1421 /* check if the string offsets really fit into the provided size */
1422 /* FIXME: should we check string length as well? */
1423 /* make sure that we don't read/write beyond the provided buffer */
1424 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1426 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1427 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1430 /* make sure that we don't read/write beyond the provided buffer */
1431 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1433 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1434 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1437 /* make sure that we don't read/write beyond the provided buffer */
1438 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1440 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1441 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1444 /* make sure that we don't read/write beyond the provided buffer */
1445 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1447 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1448 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1453 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1454 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1460 /***********************************************************************
1461 * GetOutlineTextMetricsW [GDI32.@]
1463 UINT WINAPI
GetOutlineTextMetricsW(
1464 HDC hdc
, /* [in] Handle of device context */
1465 UINT cbData
, /* [in] Size of metric data array */
1466 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1468 DC
*dc
= get_dc_ptr( hdc
);
1469 OUTLINETEXTMETRICW
*output
= lpOTM
;
1472 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1476 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1479 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1480 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1483 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1484 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1486 #define WDPTOLP(x) ((x<0)? \
1487 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1488 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1489 #define HDPTOLP(y) ((y<0)? \
1490 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1491 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1493 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1494 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1495 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1496 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1497 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1498 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1499 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1500 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1501 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1502 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1503 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1504 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1505 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1506 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1507 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1508 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1509 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1510 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1511 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1512 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1513 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1514 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1515 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1516 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1517 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1518 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1519 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1520 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1521 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1522 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1523 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1524 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1527 if(output
!= lpOTM
) {
1528 memcpy(lpOTM
, output
, cbData
);
1529 HeapFree(GetProcessHeap(), 0, output
);
1535 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1536 but really this should just be a return 0. */
1538 ret
= sizeof(*lpOTM
);
1543 memset(lpOTM
, 0, ret
);
1544 lpOTM
->otmSize
= sizeof(*lpOTM
);
1545 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1547 Further fill of the structure not implemented,
1548 Needs real values for the structure members
1558 /***********************************************************************
1559 * GetCharWidthW (GDI32.@)
1560 * GetCharWidth32W (GDI32.@)
1562 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1567 DC
* dc
= get_dc_ptr( hdc
);
1568 if (!dc
) return FALSE
;
1571 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1572 else if (dc
->funcs
->pGetCharWidth
)
1573 ret
= dc
->funcs
->pGetCharWidth( dc
->physDev
, firstChar
, lastChar
, buffer
);
1577 /* convert device units to logical */
1578 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1579 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1582 release_dc_ptr( dc
);
1587 /***********************************************************************
1588 * GetCharWidthA (GDI32.@)
1589 * GetCharWidth32A (GDI32.@)
1591 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1594 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
1599 if(count
<= 0) return FALSE
;
1601 str
= HeapAlloc(GetProcessHeap(), 0, count
);
1602 for(i
= 0; i
< count
; i
++)
1603 str
[i
] = (BYTE
)(firstChar
+ i
);
1605 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1607 for(i
= 0; i
< wlen
; i
++)
1609 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1617 HeapFree(GetProcessHeap(), 0, str
);
1618 HeapFree(GetProcessHeap(), 0, wstr
);
1624 /***********************************************************************
1625 * ExtTextOutA (GDI32.@)
1629 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1630 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1638 if (flags
& ETO_GLYPH_INDEX
)
1639 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1641 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1644 unsigned int i
= 0, j
= 0;
1646 /* allocate enough for a ETO_PDY */
1647 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1649 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1653 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1654 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1657 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1664 lpDxW
[j
++] = lpDx
[i
* 2];
1665 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1668 lpDxW
[j
++] = lpDx
[i
];
1674 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1676 HeapFree( GetProcessHeap(), 0, p
);
1677 HeapFree( GetProcessHeap(), 0, lpDxW
);
1682 /***********************************************************************
1683 * ExtTextOutW (GDI32.@)
1685 * Draws text using the currently selected font, background color, and text color.
1689 * x,y [I] coordinates of string
1691 * ETO_GRAYED - undocumented on MSDN
1692 * ETO_OPAQUE - use background color for fill the rectangle
1693 * ETO_CLIPPED - clipping text to the rectangle
1694 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1695 * than encoded characters. Implies ETO_IGNORELANGUAGE
1696 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1697 * Affects BiDi ordering
1698 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1699 * ETO_PDY - unimplemented
1700 * ETO_NUMERICSLATIN - unimplemented always assumed -
1701 * do not translate numbers into locale representations
1702 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1703 * lprect [I] dimensions for clipping or/and opaquing
1704 * str [I] text string
1705 * count [I] number of symbols in string
1706 * lpDx [I] optional parameter with distance between drawing characters
1712 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1713 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1716 LPWSTR reordered_str
= (LPWSTR
)str
;
1717 WORD
*glyphs
= NULL
;
1718 UINT align
= GetTextAlign( hdc
);
1719 DWORD layout
= GetLayout( hdc
);
1723 double cosEsc
, sinEsc
;
1727 BOOL done_extents
= FALSE
;
1728 POINT
*deltas
= NULL
, width
= {0, 0};
1730 DC
* dc
= get_dc_ptr( hdc
);
1732 static int quietfixme
= 0;
1734 if (!dc
) return FALSE
;
1736 breakRem
= dc
->breakRem
;
1738 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1740 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1743 if (!dc
->funcs
->pExtTextOut
&& !PATH_IsPathOpen(dc
->path
))
1745 release_dc_ptr( dc
);
1750 type
= GetObjectType(hdc
);
1751 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1753 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1754 release_dc_ptr( dc
);
1759 flags
&= ~ETO_CLIPPED
;
1761 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
1762 if (layout
& LAYOUT_RTL
)
1764 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
1765 align
^= TA_RTLREADING
;
1768 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1771 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1773 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1774 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
1775 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1777 flags
|= ETO_IGNORELANGUAGE
;
1780 flags
|= ETO_GLYPH_INDEX
;
1781 if (cGlyphs
!= count
)
1785 else if(flags
& ETO_GLYPH_INDEX
)
1786 glyphs
= reordered_str
;
1788 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1789 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
1790 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1792 if(align
& TA_UPDATECP
)
1794 GetCurrentPositionEx( hdc
, &pt
);
1799 GetTextMetricsW(hdc
, &tm
);
1800 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1802 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1803 lf
.lfEscapement
= 0;
1805 if(lf
.lfEscapement
!= 0)
1807 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1808 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1816 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1820 if(flags
& ETO_GLYPH_INDEX
)
1821 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1823 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1825 done_extents
= TRUE
;
1828 rc
.right
= x
+ sz
.cx
;
1829 rc
.bottom
= y
+ sz
.cy
;
1836 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1838 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1839 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1842 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1843 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1853 LPtoDP(hdc
, &pt
, 1);
1857 char_extra
= GetTextCharacterExtra(hdc
);
1858 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1862 POINT total
= {0, 0}, desired
[2];
1864 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1865 for(i
= 0; i
< count
; i
++)
1871 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1872 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1876 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1883 if(flags
& ETO_GLYPH_INDEX
)
1884 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1886 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1888 deltas
[i
].x
= tmpsz
.cx
;
1892 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1894 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1901 total
.x
+= deltas
[i
].x
;
1902 total
.y
+= deltas
[i
].y
;
1904 desired
[0].x
= desired
[0].y
= 0;
1906 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1907 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1909 LPtoDP(hdc
, desired
, 2);
1910 desired
[1].x
-= desired
[0].x
;
1911 desired
[1].y
-= desired
[0].y
;
1912 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
1914 deltas
[i
].x
= desired
[1].x
- width
.x
;
1915 deltas
[i
].y
= desired
[1].y
- width
.y
;
1925 if(flags
& ETO_GLYPH_INDEX
)
1926 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1928 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1929 done_extents
= TRUE
;
1931 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
1935 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1936 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1937 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1940 if (align
& TA_UPDATECP
)
1944 DPtoLP(hdc
, &pt
, 1);
1945 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1957 if (align
& TA_UPDATECP
)
1961 DPtoLP(hdc
, &pt
, 1);
1962 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
1967 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
1970 y
+= tm
.tmAscent
* cosEsc
;
1971 x
+= tm
.tmAscent
* sinEsc
;
1975 y
-= tm
.tmDescent
* cosEsc
;
1976 x
-= tm
.tmDescent
* sinEsc
;
1983 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
1985 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
1987 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
1988 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
1992 rc
.right
= x
+ width
.x
;
1993 rc
.top
= y
- tm
.tmAscent
;
1994 rc
.bottom
= y
+ tm
.tmDescent
;
1995 dc
->funcs
->pExtTextOut(dc
->physDev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2000 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2002 HFONT orig_font
= dc
->hFont
, cur_font
;
2005 POINT
*offsets
= NULL
;
2008 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2009 for(i
= 0; i
< count
; i
++)
2011 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2012 if(cur_font
!= dc
->hFont
)
2017 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2018 offsets
[0].x
= offsets
[0].y
= 0;
2023 for(j
= 1; j
< count
; j
++)
2025 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2026 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2032 for(j
= 1; j
< count
; j
++)
2034 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2035 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2041 if (PATH_IsPathOpen(dc
->path
))
2042 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2043 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2044 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2046 dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2047 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2048 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2051 SelectObject(hdc
, cur_font
);
2053 glyphs
[span
++] = glyph
;
2057 if (PATH_IsPathOpen(dc
->path
))
2058 ret
= PATH_ExtTextOut(dc
, 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
);
2063 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2064 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2065 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2066 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2067 SelectObject(hdc
, orig_font
);
2068 HeapFree(GetProcessHeap(), 0, offsets
);
2074 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2076 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2077 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2078 flags
|= ETO_GLYPH_INDEX
;
2081 if (PATH_IsPathOpen(dc
->path
))
2082 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2083 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2085 ret
= dc
->funcs
->pExtTextOut(dc
->physDev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2086 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2090 HeapFree(GetProcessHeap(), 0, deltas
);
2091 if(glyphs
!= reordered_str
)
2092 HeapFree(GetProcessHeap(), 0, glyphs
);
2093 if(reordered_str
!= str
)
2094 HeapFree(GetProcessHeap(), 0, reordered_str
);
2096 release_dc_ptr( dc
);
2098 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2100 int underlinePos
, strikeoutPos
;
2101 int underlineWidth
, strikeoutWidth
;
2102 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2103 OUTLINETEXTMETRICW
* otm
= NULL
;
2108 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2109 strikeoutPos
= tm
.tmAscent
/ 2;
2110 strikeoutWidth
= underlineWidth
;
2114 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2115 GetOutlineTextMetricsW(hdc
, size
, otm
);
2116 underlinePos
= otm
->otmsUnderscorePosition
;
2117 underlineWidth
= otm
->otmsUnderscoreSize
;
2118 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2119 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2120 HeapFree(GetProcessHeap(), 0, otm
);
2123 if (PATH_IsPathOpen(dc
->path
))
2127 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2129 hbrush
= SelectObject(hdc
, hbrush
);
2130 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2134 pts
[0].x
= x
- underlinePos
* sinEsc
;
2135 pts
[0].y
= y
- underlinePos
* cosEsc
;
2136 pts
[1].x
= x
+ width
.x
- underlinePos
* sinEsc
;
2137 pts
[1].y
= y
+ width
.y
- underlinePos
* cosEsc
;
2138 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2139 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2140 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2141 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2142 pts
[4].x
= pts
[0].x
;
2143 pts
[4].y
= pts
[0].y
;
2144 DPtoLP(hdc
, pts
, 5);
2145 Polygon(hdc
, pts
, 5);
2150 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2151 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2152 pts
[1].x
= x
+ width
.x
- strikeoutPos
* sinEsc
;
2153 pts
[1].y
= y
+ width
.y
- strikeoutPos
* cosEsc
;
2154 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2155 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2156 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2157 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2158 pts
[4].x
= pts
[0].x
;
2159 pts
[4].y
= pts
[0].y
;
2160 DPtoLP(hdc
, pts
, 5);
2161 Polygon(hdc
, pts
, 5);
2164 SelectObject(hdc
, hpen
);
2165 hbrush
= SelectObject(hdc
, hbrush
);
2166 DeleteObject(hbrush
);
2170 POINT pts
[2], oldpt
;
2175 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2176 hpen
= SelectObject(hdc
, hpen
);
2179 pts
[1].x
= x
+ width
.x
;
2180 pts
[1].y
= y
+ width
.y
;
2181 DPtoLP(hdc
, pts
, 2);
2182 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2183 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2184 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2185 DeleteObject(SelectObject(hdc
, hpen
));
2190 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2191 hpen
= SelectObject(hdc
, hpen
);
2194 pts
[1].x
= x
+ width
.x
;
2195 pts
[1].y
= y
+ width
.y
;
2196 DPtoLP(hdc
, pts
, 2);
2197 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2198 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2199 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2200 DeleteObject(SelectObject(hdc
, hpen
));
2209 /***********************************************************************
2210 * TextOutA (GDI32.@)
2212 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2214 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2218 /***********************************************************************
2219 * TextOutW (GDI32.@)
2221 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2223 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2227 /***********************************************************************
2228 * PolyTextOutA (GDI32.@)
2232 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2234 for (; cStrings
>0; cStrings
--, pptxt
++)
2235 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2242 /***********************************************************************
2243 * PolyTextOutW (GDI32.@)
2245 * Draw several Strings
2251 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2253 for (; cStrings
>0; cStrings
--, pptxt
++)
2254 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2260 /* FIXME: all following APIs ******************************************/
2263 /***********************************************************************
2264 * SetMapperFlags (GDI32.@)
2266 DWORD WINAPI
SetMapperFlags( HDC hDC
, DWORD dwFlag
)
2268 DC
*dc
= get_dc_ptr( hDC
);
2271 if(dc
->funcs
->pSetMapperFlags
)
2273 ret
= dc
->funcs
->pSetMapperFlags( dc
->physDev
, dwFlag
);
2274 /* FIXME: ret is just a success flag, we should return a proper value */
2277 FIXME("(%p, 0x%08x): stub - harmless\n", hDC
, dwFlag
);
2278 release_dc_ptr( dc
);
2282 /***********************************************************************
2283 * GetAspectRatioFilterEx (GDI32.@)
2285 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2287 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2292 /***********************************************************************
2293 * GetCharABCWidthsA (GDI32.@)
2295 * See GetCharABCWidthsW.
2297 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2300 INT i
, wlen
, count
= (INT
)(lastChar
- firstChar
+ 1);
2305 if(count
<= 0) return FALSE
;
2307 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2308 for(i
= 0; i
< count
; i
++)
2309 str
[i
] = (BYTE
)(firstChar
+ i
);
2311 wstr
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
2313 for(i
= 0; i
< wlen
; i
++)
2315 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2323 HeapFree(GetProcessHeap(), 0, str
);
2324 HeapFree(GetProcessHeap(), 0, wstr
);
2330 /******************************************************************************
2331 * GetCharABCWidthsW [GDI32.@]
2333 * Retrieves widths of characters in range.
2336 * hdc [I] Handle of device context
2337 * firstChar [I] First character in range to query
2338 * lastChar [I] Last character in range to query
2339 * abc [O] Address of character-width structure
2342 * Only works with TrueType fonts
2348 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2351 DC
*dc
= get_dc_ptr(hdc
);
2355 if (!dc
) return FALSE
;
2359 release_dc_ptr( dc
);
2364 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2370 /* convert device units to logical */
2371 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2372 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2373 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2374 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2379 release_dc_ptr( dc
);
2384 /******************************************************************************
2385 * GetCharABCWidthsI [GDI32.@]
2387 * Retrieves widths of characters in range.
2390 * hdc [I] Handle of device context
2391 * firstChar [I] First glyphs in range to query
2392 * count [I] Last glyphs in range to query
2393 * pgi [i] Array of glyphs to query
2394 * abc [O] Address of character-width structure
2397 * Only works with TrueType fonts
2403 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2404 LPWORD pgi
, LPABC abc
)
2406 DC
*dc
= get_dc_ptr(hdc
);
2410 if (!dc
) return FALSE
;
2414 release_dc_ptr( dc
);
2419 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2425 /* convert device units to logical */
2426 for( i
= 0; i
< count
; i
++, abc
++ ) {
2427 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2428 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2429 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2434 release_dc_ptr( dc
);
2439 /***********************************************************************
2440 * GetGlyphOutlineA (GDI32.@)
2442 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2443 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2444 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2450 if (!lpmat2
) return GDI_ERROR
;
2452 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2455 if(uChar
> 0xff) { /* but, 2 bytes character only */
2457 mbchs
[0] = (uChar
& 0xff00) >> 8;
2458 mbchs
[1] = (uChar
& 0xff);
2461 mbchs
[0] = (uChar
& 0xff);
2463 p
= FONT_mbtowc(hdc
, mbchs
, len
, NULL
, NULL
);
2467 ret
= GetGlyphOutlineW(hdc
, c
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2469 HeapFree(GetProcessHeap(), 0, p
);
2473 /***********************************************************************
2474 * GetGlyphOutlineW (GDI32.@)
2476 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2477 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2478 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2483 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2484 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2486 if (!lpmat2
) return GDI_ERROR
;
2488 dc
= get_dc_ptr(hdc
);
2489 if(!dc
) return GDI_ERROR
;
2492 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2493 cbBuffer
, lpBuffer
, lpmat2
);
2497 release_dc_ptr( dc
);
2502 /***********************************************************************
2503 * CreateScalableFontResourceA (GDI32.@)
2505 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2506 LPCSTR lpszResourceFile
,
2507 LPCSTR lpszFontFile
,
2508 LPCSTR lpszCurrentPath
)
2510 LPWSTR lpszResourceFileW
= NULL
;
2511 LPWSTR lpszFontFileW
= NULL
;
2512 LPWSTR lpszCurrentPathW
= NULL
;
2516 if (lpszResourceFile
)
2518 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2519 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2520 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2525 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2526 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2527 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2530 if (lpszCurrentPath
)
2532 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2533 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2534 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2537 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2538 lpszFontFileW
, lpszCurrentPathW
);
2540 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2541 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2542 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2547 /***********************************************************************
2548 * CreateScalableFontResourceW (GDI32.@)
2550 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2551 LPCWSTR lpszResourceFile
,
2552 LPCWSTR lpszFontFile
,
2553 LPCWSTR lpszCurrentPath
)
2556 FIXME("(%d,%s,%s,%s): stub\n",
2557 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2558 debugstr_w(lpszCurrentPath
) );
2560 /* fHidden=1 - only visible for the calling app, read-only, not
2561 * enumerated with EnumFonts/EnumFontFamilies
2562 * lpszCurrentPath can be NULL
2565 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2566 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2568 SetLastError(ERROR_FILE_EXISTS
);
2571 return FALSE
; /* create failed */
2574 /*************************************************************************
2575 * GetKerningPairsA (GDI32.@)
2577 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2578 LPKERNINGPAIR kern_pairA
)
2582 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2583 KERNINGPAIR
*kern_pairW
;
2585 if (!cPairs
&& kern_pairA
)
2587 SetLastError(ERROR_INVALID_PARAMETER
);
2591 cp
= GdiGetCodePage(hDC
);
2593 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2594 * to fail on an invalid character for CP_SYMBOL.
2596 cpi
.DefaultChar
[0] = 0;
2597 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2599 FIXME("Can't find codepage %u info\n", cp
);
2603 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2604 if (!total_kern_pairs
) return 0;
2606 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2607 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2609 for (i
= 0; i
< total_kern_pairs
; i
++)
2613 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2616 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2619 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2624 if (kern_pairs_copied
>= cPairs
) break;
2626 kern_pairA
->wFirst
= (BYTE
)first
;
2627 kern_pairA
->wSecond
= (BYTE
)second
;
2628 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2631 kern_pairs_copied
++;
2634 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2636 return kern_pairs_copied
;
2639 /*************************************************************************
2640 * GetKerningPairsW (GDI32.@)
2642 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2643 LPKERNINGPAIR lpKerningPairs
)
2648 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2650 if (!cPairs
&& lpKerningPairs
)
2652 SetLastError(ERROR_INVALID_PARAMETER
);
2656 dc
= get_dc_ptr(hDC
);
2660 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2662 release_dc_ptr( dc
);
2666 /*************************************************************************
2667 * TranslateCharsetInfo [GDI32.@]
2669 * Fills a CHARSETINFO structure for a character set, code page, or
2670 * font. This allows making the correspondence between different labels
2671 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2672 * of the same encoding.
2674 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2675 * only one codepage should be set in *lpSrc.
2678 * TRUE on success, FALSE on failure.
2681 BOOL WINAPI
TranslateCharsetInfo(
2682 LPDWORD lpSrc
, /* [in]
2683 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2684 if flags == TCI_SRCCHARSET: a character set value
2685 if flags == TCI_SRCCODEPAGE: a code page value
2687 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2688 DWORD flags
/* [in] determines interpretation of lpSrc */)
2692 case TCI_SRCFONTSIG
:
2693 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2695 case TCI_SRCCODEPAGE
:
2696 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2698 case TCI_SRCCHARSET
:
2699 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2704 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2705 *lpCs
= FONT_tci
[index
];
2709 /*************************************************************************
2710 * GetFontLanguageInfo (GDI32.@)
2712 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2714 FONTSIGNATURE fontsig
;
2715 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2716 GCP_DIACRITIC_MASK
=0x00000000,
2717 FLI_GLYPHS_MASK
=0x00000000,
2718 GCP_GLYPHSHAPE_MASK
=0x00000040,
2719 GCP_KASHIDA_MASK
=0x00000000,
2720 GCP_LIGATE_MASK
=0x00000000,
2721 GCP_USEKERNING_MASK
=0x00000000,
2722 GCP_REORDER_MASK
=0x00000060;
2726 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2727 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2729 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2732 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2733 result
|=GCP_DIACRITIC
;
2735 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2738 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2739 result
|=GCP_GLYPHSHAPE
;
2741 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2742 result
|=GCP_KASHIDA
;
2744 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2747 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2748 result
|=GCP_USEKERNING
;
2750 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2751 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2752 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2753 result
|=GCP_REORDER
;
2759 /*************************************************************************
2760 * GetFontData [GDI32.@]
2762 * Retrieve data for TrueType font.
2766 * success: Number of bytes returned
2767 * failure: GDI_ERROR
2771 * Calls SetLastError()
2774 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2775 LPVOID buffer
, DWORD length
)
2777 DC
*dc
= get_dc_ptr(hdc
);
2778 DWORD ret
= GDI_ERROR
;
2780 if(!dc
) return GDI_ERROR
;
2783 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2785 release_dc_ptr( dc
);
2789 /*************************************************************************
2790 * GetGlyphIndicesA [GDI32.@]
2792 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2793 LPWORD pgi
, DWORD flags
)
2799 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2800 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2802 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2803 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2804 HeapFree(GetProcessHeap(), 0, lpstrW
);
2809 /*************************************************************************
2810 * GetGlyphIndicesW [GDI32.@]
2812 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2813 LPWORD pgi
, DWORD flags
)
2815 DC
*dc
= get_dc_ptr(hdc
);
2816 DWORD ret
= GDI_ERROR
;
2818 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2819 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2821 if(!dc
) return GDI_ERROR
;
2824 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2826 release_dc_ptr( dc
);
2830 /*************************************************************************
2831 * GetCharacterPlacementA [GDI32.@]
2833 * See GetCharacterPlacementW.
2836 * the web browser control of ie4 calls this with dwFlags=0
2839 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2840 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2845 GCP_RESULTSW resultsW
;
2849 TRACE("%s, %d, %d, 0x%08x\n",
2850 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2852 /* both structs are equal in size */
2853 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2855 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2856 if(lpResults
->lpOutString
)
2857 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2859 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2861 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2862 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2864 if(lpResults
->lpOutString
) {
2865 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2866 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2869 HeapFree(GetProcessHeap(), 0, lpStringW
);
2870 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2875 /*************************************************************************
2876 * GetCharacterPlacementW [GDI32.@]
2878 * Retrieve information about a string. This includes the width, reordering,
2879 * Glyphing and so on.
2883 * The width and height of the string if successful, 0 if failed.
2887 * All flags except GCP_REORDER are not yet implemented.
2888 * Reordering is not 100% compliant to the Windows BiDi method.
2889 * Caret positioning is not yet implemented for BiDi.
2890 * Classes are not yet implemented.
2894 GetCharacterPlacementW(
2895 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2896 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2897 INT uCount
, /* [in] Number of WORDS in string. */
2898 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2899 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2900 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2907 TRACE("%s, %d, %d, 0x%08x\n",
2908 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2910 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2911 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2912 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2913 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2914 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2916 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2917 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2918 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2919 FIXME("Caret positions for complex scripts not implemented\n");
2921 nSet
= (UINT
)uCount
;
2922 if(nSet
> lpResults
->nGlyphs
)
2923 nSet
= lpResults
->nGlyphs
;
2925 /* return number of initialized fields */
2926 lpResults
->nGlyphs
= nSet
;
2928 if((dwFlags
&GCP_REORDER
)==0 )
2930 /* Treat the case where no special handling was requested in a fastpath way */
2931 /* copy will do if the GCP_REORDER flag is not set */
2932 if(lpResults
->lpOutString
)
2933 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2935 if(lpResults
->lpOrder
)
2937 for(i
= 0; i
< nSet
; i
++)
2938 lpResults
->lpOrder
[i
] = i
;
2942 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2943 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
2946 /* FIXME: Will use the placement chars */
2947 if (lpResults
->lpDx
)
2950 for (i
= 0; i
< nSet
; i
++)
2952 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
2953 lpResults
->lpDx
[i
]= c
;
2957 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
2961 lpResults
->lpCaretPos
[0] = 0;
2962 for (i
= 1; i
< nSet
; i
++)
2963 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
2964 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
2967 if(lpResults
->lpGlyphs
)
2968 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
2970 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
2971 ret
= MAKELONG(size
.cx
, size
.cy
);
2976 /*************************************************************************
2977 * GetCharABCWidthsFloatA [GDI32.@]
2979 * See GetCharABCWidthsFloatW.
2981 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
2983 INT i
, wlen
, count
= (INT
)(last
- first
+ 1);
2988 if (count
<= 0) return FALSE
;
2990 str
= HeapAlloc(GetProcessHeap(), 0, count
);
2992 for(i
= 0; i
< count
; i
++)
2993 str
[i
] = (BYTE
)(first
+ i
);
2995 wstr
= FONT_mbtowc( hdc
, str
, count
, &wlen
, NULL
);
2997 for (i
= 0; i
< wlen
; i
++)
2999 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3007 HeapFree( GetProcessHeap(), 0, str
);
3008 HeapFree( GetProcessHeap(), 0, wstr
);
3013 /*************************************************************************
3014 * GetCharABCWidthsFloatW [GDI32.@]
3016 * Retrieves widths of a range of characters.
3019 * hdc [I] Handle to device context.
3020 * first [I] First character in range to query.
3021 * last [I] Last character in range to query.
3022 * abcf [O] Array of LPABCFLOAT structures.
3028 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3032 DC
*dc
= get_dc_ptr( hdc
);
3034 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3036 if (!dc
) return FALSE
;
3040 release_dc_ptr( dc
);
3045 ret
= WineEngGetCharABCWidthsFloat( dc
->gdiFont
, first
, last
, abcf
);
3051 /* convert device units to logical */
3052 for (i
= first
; i
<= last
; i
++, abcf
++)
3054 abcf
->abcfA
= abcf
->abcfA
* dc
->xformVport2World
.eM11
;
3055 abcf
->abcfB
= abcf
->abcfB
* dc
->xformVport2World
.eM11
;
3056 abcf
->abcfC
= abcf
->abcfC
* dc
->xformVport2World
.eM11
;
3060 release_dc_ptr( dc
);
3064 /*************************************************************************
3065 * GetCharWidthFloatA [GDI32.@]
3067 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3068 UINT iLastChar
, PFLOAT pxBuffer
)
3070 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3074 /*************************************************************************
3075 * GetCharWidthFloatW [GDI32.@]
3077 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3078 UINT iLastChar
, PFLOAT pxBuffer
)
3080 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3085 /***********************************************************************
3087 * Font Resource API *
3089 ***********************************************************************/
3091 /***********************************************************************
3092 * AddFontResourceA (GDI32.@)
3094 INT WINAPI
AddFontResourceA( LPCSTR str
)
3096 return AddFontResourceExA( str
, 0, NULL
);
3099 /***********************************************************************
3100 * AddFontResourceW (GDI32.@)
3102 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3104 return AddFontResourceExW(str
, 0, NULL
);
3108 /***********************************************************************
3109 * AddFontResourceExA (GDI32.@)
3111 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3113 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3114 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3117 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3118 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3119 HeapFree(GetProcessHeap(), 0, strW
);
3123 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3125 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3126 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3127 LPVOID
*pMem
= LockResource(hMem
);
3128 int *num_total
= (int *)lParam
;
3131 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3132 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3134 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3138 *num_total
+= num_in_res
;
3142 /***********************************************************************
3143 * AddFontResourceExW (GDI32.@)
3145 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3147 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3150 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3151 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3152 if (hModule
!= NULL
)
3154 int num_resources
= 0;
3155 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3157 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3158 wine_dbgstr_w(str
));
3159 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3160 ret
= num_resources
;
3161 FreeLibrary(hModule
);
3167 /***********************************************************************
3168 * RemoveFontResourceA (GDI32.@)
3170 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3172 return RemoveFontResourceExA(str
, 0, 0);
3175 /***********************************************************************
3176 * RemoveFontResourceW (GDI32.@)
3178 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3180 return RemoveFontResourceExW(str
, 0, 0);
3183 /***********************************************************************
3184 * AddFontMemResourceEx (GDI32.@)
3186 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3191 if (!pbFont
|| !cbFont
|| !pcFonts
)
3193 SetLastError(ERROR_INVALID_PARAMETER
);
3197 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3202 *pcFonts
= num_fonts
;
3206 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3207 RemoveFontMemResourceEx(ret
);
3215 /***********************************************************************
3216 * RemoveFontMemResourceEx (GDI32.@)
3218 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3220 FIXME("(%p) stub\n", fh
);
3224 /***********************************************************************
3225 * RemoveFontResourceExA (GDI32.@)
3227 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3229 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3230 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3233 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3234 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3235 HeapFree(GetProcessHeap(), 0, strW
);
3239 /***********************************************************************
3240 * RemoveFontResourceExW (GDI32.@)
3242 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3244 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3247 /***********************************************************************
3248 * GetTextCharset (GDI32.@)
3250 UINT WINAPI
GetTextCharset(HDC hdc
)
3252 /* MSDN docs say this is equivalent */
3253 return GetTextCharsetInfo(hdc
, NULL
, 0);
3256 /***********************************************************************
3257 * GetTextCharsetInfo (GDI32.@)
3259 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3261 UINT ret
= DEFAULT_CHARSET
;
3262 DC
*dc
= get_dc_ptr(hdc
);
3267 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3269 release_dc_ptr( dc
);
3272 if (ret
== DEFAULT_CHARSET
&& fs
)
3273 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3277 /***********************************************************************
3278 * GdiGetCharDimensions (GDI32.@)
3280 * Gets the average width of the characters in the English alphabet.
3283 * hdc [I] Handle to the device context to measure on.
3284 * lptm [O] Pointer to memory to store the text metrics into.
3285 * height [O] On exit, the maximum height of characters in the English alphabet.
3288 * The average width of characters in the English alphabet.
3291 * This function is used by the dialog manager to get the size of a dialog
3292 * unit. It should also be used by other pieces of code that need to know
3293 * the size of a dialog unit in logical units without having access to the
3294 * window handle of the dialog.
3295 * Windows caches the font metrics from this function, but we don't and
3296 * there doesn't appear to be an immediate advantage to do so.
3299 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3301 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3304 static const WCHAR alphabet
[] = {
3305 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3306 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3307 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3309 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3311 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3313 if (height
) *height
= sz
.cy
;
3314 return (sz
.cx
/ 26 + 1) / 2;
3317 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3319 FIXME("(%d): stub\n", fEnableEUDC
);
3323 /***********************************************************************
3324 * GetCharWidthI (GDI32.@)
3326 * Retrieve widths of characters.
3329 * hdc [I] Handle to a device context.
3330 * first [I] First glyph in range to query.
3331 * count [I] Number of glyph indices to query.
3332 * glyphs [I] Array of glyphs to query.
3333 * buffer [O] Buffer to receive character widths.
3336 * Only works with TrueType fonts.
3342 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3347 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3349 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3352 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3354 HeapFree(GetProcessHeap(), 0, abc
);
3358 for (i
= 0; i
< count
; i
++)
3359 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3361 HeapFree(GetProcessHeap(), 0, abc
);
3365 /***********************************************************************
3366 * GetFontUnicodeRanges (GDI32.@)
3368 * Retrieve a list of supported Unicode characters in a font.
3371 * hdc [I] Handle to a device context.
3372 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3375 * Success: Number of bytes written to the buffer pointed to by lpgs.
3379 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3382 DC
*dc
= get_dc_ptr(hdc
);
3384 TRACE("(%p, %p)\n", hdc
, lpgs
);
3388 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3394 /*************************************************************
3395 * FontIsLinked (GDI32.@)
3397 BOOL WINAPI
FontIsLinked(HDC hdc
)
3399 DC
*dc
= get_dc_ptr(hdc
);
3402 if (!dc
) return FALSE
;
3403 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3405 TRACE("returning %d\n", ret
);
3409 /*************************************************************
3410 * GdiRealizationInfo (GDI32.@)
3412 * Returns a structure that contains some font information.
3414 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3416 DC
*dc
= get_dc_ptr(hdc
);
3419 if (!dc
) return FALSE
;
3420 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);