4 * Copyright 1993 Alexandre Julliard
6 * Copyright 2002,2003 Shachar Shemesh
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "wine/port.h"
34 #include "gdi_private.h"
35 #include "wine/exception.h"
36 #include "wine/unicode.h"
37 #include "wine/debug.h"
39 WINE_DEFAULT_DEBUG_CHANNEL(font
);
41 /* Device -> World size conversion */
43 /* Performs a device to world transformation on the specified width (which
44 * is in integer format).
46 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
50 /* Perform operation with floating point */
51 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
52 /* Round to integers */
53 return GDI_ROUND(floatWidth
);
56 /* Performs a device to world transformation on the specified size (which
57 * is in integer format).
59 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
63 /* Perform operation with floating point */
64 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
65 /* Round to integers */
66 return GDI_ROUND(floatHeight
);
69 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
72 pt
[0].x
= pt
[0].y
= 0;
75 LPtoDP(dc
->hSelf
, pt
, 2);
76 return pt
[1].x
- pt
[0].x
;
79 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
82 pt
[0].x
= pt
[0].y
= 0;
85 LPtoDP(dc
->hSelf
, pt
, 2);
86 return pt
[1].y
- pt
[0].y
;
89 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
90 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
91 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
92 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
94 static const struct gdi_obj_funcs font_funcs
=
96 FONT_SelectObject
, /* pSelectObject */
97 FONT_GetObjectA
, /* pGetObjectA */
98 FONT_GetObjectW
, /* pGetObjectW */
99 NULL
, /* pUnrealizeObject */
100 FONT_DeleteObject
/* pDeleteObject */
103 #define ENUM_UNICODE 0x00000001
104 #define ENUM_CALLED 0x00000002
114 LPLOGFONTW lpLogFontParam
;
115 FONTENUMPROCW lpEnumFunc
;
122 * For TranslateCharsetInfo
124 #define MAXTCIINDEX 32
125 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
127 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
128 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
129 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
130 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
131 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
132 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
133 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
134 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
135 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
136 /* reserved by ANSI */
137 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
138 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
139 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
140 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
141 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
142 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
143 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
145 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
146 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
147 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
148 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
149 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
150 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
151 /* reserved for alternate ANSI and OEM */
152 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
153 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
154 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
155 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
156 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
157 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
158 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
159 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
160 /* reserved for system */
161 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
165 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
167 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
168 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
170 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
173 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
175 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
176 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
177 LF_FACESIZE
, NULL
, NULL
);
178 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
181 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
183 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
185 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
186 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
187 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
188 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
189 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
190 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
191 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
192 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
193 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
196 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
198 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
200 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
201 fontW
->elfFullName
, LF_FULLFACESIZE
);
202 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
203 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
204 fontW
->elfStyle
, LF_FACESIZE
);
205 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
206 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
207 fontW
->elfScript
, LF_FACESIZE
);
208 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
211 /***********************************************************************
212 * TEXTMETRIC conversion functions.
214 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
216 ptmA
->tmHeight
= ptmW
->tmHeight
;
217 ptmA
->tmAscent
= ptmW
->tmAscent
;
218 ptmA
->tmDescent
= ptmW
->tmDescent
;
219 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
220 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
221 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
222 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
223 ptmA
->tmWeight
= ptmW
->tmWeight
;
224 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
225 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
226 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
227 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
228 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
230 ptmA
->tmFirstChar
= 0x1e;
231 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
233 else if (ptmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
235 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
236 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
240 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 0xff);
241 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
243 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
244 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
245 ptmA
->tmItalic
= ptmW
->tmItalic
;
246 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
247 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
248 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
249 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
253 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
255 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
256 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
257 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
258 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
259 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
260 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
264 /***********************************************************************
265 * GdiGetCodePage (GDI32.@)
267 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
270 DC
*dc
= get_dc_ptr( hdc
);
274 cp
= dc
->font_code_page
;
275 release_dc_ptr( dc
);
280 /***********************************************************************
283 * Returns a Unicode translation of str using the charset of the
284 * currently selected font in hdc. If count is -1 then str is assumed
285 * to be '\0' terminated, otherwise it contains the number of bytes to
286 * convert. If plenW is non-NULL, on return it will point to the
287 * number of WCHARs that have been written. If pCP is non-NULL, on
288 * return it will point to the codepage used in the conversion. The
289 * caller should free the returned LPWSTR from the process heap
292 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
298 cp
= GdiGetCodePage( hdc
);
300 if(count
== -1) count
= strlen(str
);
301 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
302 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
303 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
304 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
305 if(plenW
) *plenW
= lenW
;
310 /***********************************************************************
311 * CreateFontIndirectExA (GDI32.@)
313 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
315 ENUMLOGFONTEXDVW enumexW
;
317 if (!penumexA
) return 0;
319 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
320 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
321 return CreateFontIndirectExW( &enumexW
);
324 /***********************************************************************
325 * CreateFontIndirectExW (GDI32.@)
327 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
333 if (!penumex
) return 0;
335 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
336 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
337 penumex
->elfEnumLogfontEx
.elfScript
[0])
339 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
340 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
341 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
342 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
345 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
346 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
348 fontPtr
->logfont
= *plf
;
350 if (plf
->lfEscapement
!= plf
->lfOrientation
)
352 /* this should really depend on whether GM_ADVANCED is set */
353 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
354 WARN("orientation angle %f set to "
355 "escapement angle %f for new font %p\n",
356 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
359 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
361 HeapFree( GetProcessHeap(), 0, fontPtr
);
365 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
366 plf
->lfHeight
, plf
->lfWidth
,
367 plf
->lfEscapement
, plf
->lfOrientation
,
368 plf
->lfPitchAndFamily
,
369 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
370 plf
->lfQuality
, plf
->lfCharSet
,
371 debugstr_w(plf
->lfFaceName
),
372 plf
->lfWeight
> 400 ? "Bold" : "",
373 plf
->lfItalic
? "Italic" : "",
374 plf
->lfUnderline
? "Underline" : "", hFont
);
379 /***********************************************************************
380 * CreateFontIndirectA (GDI32.@)
382 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
388 FONT_LogFontAToW( plfA
, &lfW
);
389 return CreateFontIndirectW( &lfW
);
392 /***********************************************************************
393 * CreateFontIndirectW (GDI32.@)
395 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
397 ENUMLOGFONTEXDVW exdv
;
401 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
402 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
403 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
404 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
405 return CreateFontIndirectExW( &exdv
);
408 /*************************************************************************
409 * CreateFontA (GDI32.@)
411 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
412 INT orient
, INT weight
, DWORD italic
,
413 DWORD underline
, DWORD strikeout
, DWORD charset
,
414 DWORD outpres
, DWORD clippres
, DWORD quality
,
415 DWORD pitch
, LPCSTR name
)
419 logfont
.lfHeight
= height
;
420 logfont
.lfWidth
= width
;
421 logfont
.lfEscapement
= esc
;
422 logfont
.lfOrientation
= orient
;
423 logfont
.lfWeight
= weight
;
424 logfont
.lfItalic
= italic
;
425 logfont
.lfUnderline
= underline
;
426 logfont
.lfStrikeOut
= strikeout
;
427 logfont
.lfCharSet
= charset
;
428 logfont
.lfOutPrecision
= outpres
;
429 logfont
.lfClipPrecision
= clippres
;
430 logfont
.lfQuality
= quality
;
431 logfont
.lfPitchAndFamily
= pitch
;
434 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
436 logfont
.lfFaceName
[0] = '\0';
438 return CreateFontIndirectA( &logfont
);
441 /*************************************************************************
442 * CreateFontW (GDI32.@)
444 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
445 INT orient
, INT weight
, DWORD italic
,
446 DWORD underline
, DWORD strikeout
, DWORD charset
,
447 DWORD outpres
, DWORD clippres
, DWORD quality
,
448 DWORD pitch
, LPCWSTR name
)
452 logfont
.lfHeight
= height
;
453 logfont
.lfWidth
= width
;
454 logfont
.lfEscapement
= esc
;
455 logfont
.lfOrientation
= orient
;
456 logfont
.lfWeight
= weight
;
457 logfont
.lfItalic
= italic
;
458 logfont
.lfUnderline
= underline
;
459 logfont
.lfStrikeOut
= strikeout
;
460 logfont
.lfCharSet
= charset
;
461 logfont
.lfOutPrecision
= outpres
;
462 logfont
.lfClipPrecision
= clippres
;
463 logfont
.lfQuality
= quality
;
464 logfont
.lfPitchAndFamily
= pitch
;
467 lstrcpynW(logfont
.lfFaceName
, name
,
468 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
470 logfont
.lfFaceName
[0] = '\0';
472 return CreateFontIndirectW( &logfont
);
475 static void update_font_code_page( DC
*dc
)
478 int charset
= DEFAULT_CHARSET
;
481 charset
= WineEngGetTextCharsetInfo( dc
->gdiFont
, NULL
, 0 );
483 /* Hmm, nicely designed api this one! */
484 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
485 dc
->font_code_page
= csi
.ciACP
;
489 dc
->font_code_page
= GetOEMCP();
491 case DEFAULT_CHARSET
:
492 dc
->font_code_page
= GetACP();
502 /* FIXME: These have no place here, but because x11drv
503 enumerates fonts with these (made up) charsets some apps
504 might use them and then the FIXME below would become
505 annoying. Now we could pick the intended codepage for
506 each of these, but since it's broken anyway we'll just
507 use CP_ACP and hope it'll go away...
509 dc
->font_code_page
= CP_ACP
;
513 FIXME("Can't find codepage for charset %d\n", charset
);
514 dc
->font_code_page
= CP_ACP
;
519 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
522 /***********************************************************************
525 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
528 DC
*dc
= get_dc_ptr( hdc
);
533 if (!GDI_inc_ref_count( handle
))
535 release_dc_ptr( dc
);
539 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
540 if (physdev
->funcs
->pSelectFont( physdev
, handle
))
544 update_font_code_page( dc
);
545 GDI_dec_ref_count( ret
);
547 else GDI_dec_ref_count( handle
);
549 release_dc_ptr( dc
);
554 /***********************************************************************
557 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
559 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
565 FONT_LogFontWToA( &font
->logfont
, &lfA
);
566 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
567 memcpy( buffer
, &lfA
, count
);
569 else count
= sizeof(lfA
);
570 GDI_ReleaseObj( handle
);
574 /***********************************************************************
577 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
579 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
584 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
585 memcpy( buffer
, &font
->logfont
, count
);
587 else count
= sizeof(LOGFONTW
);
588 GDI_ReleaseObj( handle
);
593 /***********************************************************************
596 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
600 WineEngDestroyFontInstance( handle
);
602 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
603 return HeapFree( GetProcessHeap(), 0, obj
);
607 /***********************************************************************
610 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
611 * We have to use other types because of the FONTENUMPROCW definition.
613 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
614 DWORD fType
, LPARAM lp
)
616 fontEnum32
*pfe
= (fontEnum32
*)lp
;
619 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
620 if ((!pfe
->lpLogFontParam
||
621 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
622 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
623 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
625 /* convert font metrics */
626 ENUMLOGFONTEXA logfont
;
627 NEWTEXTMETRICEXA tmA
;
629 pfe
->dwFlags
|= ENUM_CALLED
;
630 if (!(pfe
->dwFlags
& ENUM_UNICODE
))
632 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
633 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
634 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
635 ptm
= (TEXTMETRICW
*)&tmA
;
638 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
643 /***********************************************************************
644 * FONT_EnumFontFamiliesEx
646 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
,
647 FONTENUMPROCW efproc
,
648 LPARAM lParam
, DWORD dwUnicode
)
651 DC
*dc
= get_dc_ptr( hDC
);
658 TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
),
660 fe32
.lpLogFontParam
= plf
;
661 fe32
.lpEnumFunc
= efproc
;
662 fe32
.lpData
= lParam
;
663 fe32
.dwFlags
= dwUnicode
;
666 enum_gdi_fonts
= GetDeviceCaps(hDC
, TEXTCAPS
) & TC_VA_ABLE
;
669 ret
= WineEngEnumFonts( plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
670 fe32
.dwFlags
&= ~ENUM_CALLED
;
673 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumDeviceFonts
);
674 ret2
= physdev
->funcs
->pEnumDeviceFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe32
);
675 if(fe32
.dwFlags
& ENUM_CALLED
) /* update ret iff a font gets enumed */
678 release_dc_ptr( dc
);
682 /***********************************************************************
683 * EnumFontFamiliesExW (GDI32.@)
685 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
686 FONTENUMPROCW efproc
,
687 LPARAM lParam
, DWORD dwFlags
)
689 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, ENUM_UNICODE
);
692 /***********************************************************************
693 * EnumFontFamiliesExA (GDI32.@)
695 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
696 FONTENUMPROCA efproc
,
697 LPARAM lParam
, DWORD dwFlags
)
703 FONT_LogFontAToW( plf
, &lfW
);
708 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, 0);
711 /***********************************************************************
712 * EnumFontFamiliesA (GDI32.@)
714 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
715 FONTENUMPROCA efproc
, LPARAM lpData
)
721 if (!*lpFamily
) return 1;
722 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
723 lf
.lfCharSet
= DEFAULT_CHARSET
;
724 lf
.lfPitchAndFamily
= 0;
729 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
732 /***********************************************************************
733 * EnumFontFamiliesW (GDI32.@)
735 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
736 FONTENUMPROCW efproc
, LPARAM lpData
)
742 if (!*lpFamily
) return 1;
743 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
744 lf
.lfCharSet
= DEFAULT_CHARSET
;
745 lf
.lfPitchAndFamily
= 0;
750 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
753 /***********************************************************************
754 * EnumFontsA (GDI32.@)
756 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
759 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
762 /***********************************************************************
763 * EnumFontsW (GDI32.@)
765 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
768 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
772 /***********************************************************************
773 * GetTextCharacterExtra (GDI32.@)
775 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
778 DC
*dc
= get_dc_ptr( hdc
);
779 if (!dc
) return 0x80000000;
781 release_dc_ptr( dc
);
786 /***********************************************************************
787 * SetTextCharacterExtra (GDI32.@)
789 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
791 INT ret
= 0x80000000;
792 DC
* dc
= get_dc_ptr( hdc
);
796 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
797 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
798 if (extra
!= 0x80000000)
801 dc
->charExtra
= extra
;
803 release_dc_ptr( dc
);
809 /***********************************************************************
810 * SetTextJustification (GDI32.@)
812 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
816 DC
* dc
= get_dc_ptr( hdc
);
818 if (!dc
) return FALSE
;
820 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
821 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
824 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
825 if (!extra
) breaks
= 0;
828 dc
->breakExtra
= extra
/ breaks
;
829 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
837 release_dc_ptr( dc
);
842 /***********************************************************************
843 * GetTextFaceA (GDI32.@)
845 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
847 INT res
= GetTextFaceW(hdc
, 0, NULL
);
848 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
849 GetTextFaceW( hdc
, res
, nameW
);
855 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
859 /* GetTextFaceA does NOT include the nul byte in the return count. */
866 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
867 HeapFree( GetProcessHeap(), 0, nameW
);
871 /***********************************************************************
872 * GetTextFaceW (GDI32.@)
874 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
879 DC
* dc
= get_dc_ptr( hdc
);
883 ret
= WineEngGetTextFace(dc
->gdiFont
, count
, name
);
884 else if ((font
= GDI_GetObjPtr( dc
->hFont
, OBJ_FONT
)))
886 INT n
= strlenW(font
->logfont
.lfFaceName
) + 1;
889 lstrcpynW( name
, font
->logfont
.lfFaceName
, count
);
893 GDI_ReleaseObj( dc
->hFont
);
895 release_dc_ptr( dc
);
900 /***********************************************************************
901 * GetTextExtentPoint32A (GDI32.@)
903 * See GetTextExtentPoint32W.
905 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
912 if (count
< 0) return FALSE
;
914 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
918 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
919 HeapFree( GetProcessHeap(), 0, p
);
922 TRACE("(%p %s %d %p): returning %d x %d\n",
923 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
928 /***********************************************************************
929 * GetTextExtentPoint32W [GDI32.@]
931 * Computes width/height for a string.
933 * Computes width and height of the specified string.
939 BOOL WINAPI
GetTextExtentPoint32W(
940 HDC hdc
, /* [in] Handle of device context */
941 LPCWSTR str
, /* [in] Address of text string */
942 INT count
, /* [in] Number of characters in string */
943 LPSIZE size
) /* [out] Address of structure for string size */
945 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
948 /***********************************************************************
949 * GetTextExtentExPointI [GDI32.@]
951 * Computes width and height of the array of glyph indices.
954 * hdc [I] Handle of device context.
955 * indices [I] Glyph index array.
956 * count [I] Number of glyphs in array.
957 * max_ext [I] Maximum width in glyphs.
958 * nfit [O] Maximum number of characters.
959 * dxs [O] Partial string widths.
960 * size [O] Returned string size.
966 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
967 LPINT nfit
, LPINT dxs
, LPSIZE size
)
972 if (count
< 0) return FALSE
;
974 dc
= get_dc_ptr( hdc
);
975 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
;
986 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
987 FIXME("calling GetTextExtentExPoint\n");
988 ret
= physdev
->funcs
->pGetTextExtentExPoint( physdev
, indices
, count
, 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
)
1052 if (count
< 0) return FALSE
;
1056 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1057 if (!walpDx
) return FALSE
;
1060 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1061 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1064 INT n
= lpnFit
? *lpnFit
: wlen
;
1066 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1068 alpDx
[j
] = walpDx
[i
];
1069 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1072 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1073 HeapFree( GetProcessHeap(), 0, p
);
1074 HeapFree( GetProcessHeap(), 0, walpDx
);
1079 /***********************************************************************
1080 * GetTextExtentExPointW (GDI32.@)
1082 * Return the size of the string as it would be if it was output properly by
1085 * This should include
1086 * - Intercharacter spacing
1087 * - justification spacing (not yet done)
1088 * - kerning? see below
1090 * Kerning. Since kerning would be carried out by the rendering code it should
1091 * be done by the driver. However they don't support it yet. Also I am not
1092 * yet persuaded that (certainly under Win95) any kerning is actually done.
1094 * str: According to MSDN this should be null-terminated. That is not true; a
1095 * null will not terminate it early.
1096 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1097 * than count. I have seen it be either the size of the full string or
1098 * 1 less than the size of the full string. I have not seen it bear any
1099 * resemblance to the portion that would fit.
1100 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1101 * trailing intercharacter spacing and any trailing justification.
1104 * Currently we do this by measuring each character etc. We should do it by
1105 * passing the request to the driver, perhaps by extending the
1106 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1107 * thinking about kerning issues and rounding issues in the justification.
1110 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1111 INT maxExt
, LPINT lpnFit
,
1112 LPINT alpDx
, LPSIZE size
)
1121 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1123 if (count
< 0) return FALSE
;
1125 dc
= get_dc_ptr(hdc
);
1126 if (!dc
) return FALSE
;
1128 GetTextMetricsW(hdc
, &tm
);
1130 /* If we need to calculate nFit, then we need the partial extents even if
1131 the user hasn't provided us with an array. */
1134 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1138 SetLastError(ERROR_OUTOFMEMORY
);
1145 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
1146 ret
= dev
->funcs
->pGetTextExtentExPoint(dev
, str
, count
, 0, NULL
, dxs
, size
);
1148 /* Perform device size to world size transformations. */
1151 INT extra
= dc
->charExtra
,
1152 breakExtra
= dc
->breakExtra
,
1153 breakRem
= dc
->breakRem
,
1158 for (i
= 0; i
< count
; ++i
)
1160 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1161 dxs
[i
] += (i
+1) * extra
;
1162 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1164 dxs
[i
] += breakExtra
;
1171 if (dxs
[i
] <= maxExt
)
1174 breakRem
= dc
->breakRem
;
1176 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1177 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1179 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1181 for (i
= 0; i
< count
; i
++)
1183 if (str
[i
] == tm
.tmBreakChar
)
1185 size
->cx
+= breakExtra
;
1200 HeapFree(GetProcessHeap(), 0, dxs
);
1202 release_dc_ptr( dc
);
1204 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1208 /***********************************************************************
1209 * GetTextMetricsA (GDI32.@)
1211 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1215 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1216 FONT_TextMetricWToA( &tm32
, metrics
);
1220 /***********************************************************************
1221 * GetTextMetricsW (GDI32.@)
1223 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1226 DC
* dc
= get_dc_ptr( hdc
);
1227 if (!dc
) return FALSE
;
1230 ret
= WineEngGetTextMetrics(dc
->gdiFont
, metrics
);
1233 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1234 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1239 /* device layer returns values in device units
1240 * therefore we have to convert them to logical */
1242 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1243 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1245 #define WDPTOLP(x) ((x<0)? \
1246 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1247 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1248 #define HDPTOLP(y) ((y<0)? \
1249 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1250 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1252 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1253 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1254 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1255 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1256 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1257 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1258 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1259 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1263 TRACE("text metrics:\n"
1264 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1265 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1266 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1267 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1268 " PitchAndFamily = %02x\n"
1269 " --------------------\n"
1270 " InternalLeading = %i\n"
1274 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1275 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1276 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1277 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1278 metrics
->tmPitchAndFamily
,
1279 metrics
->tmInternalLeading
,
1282 metrics
->tmHeight
);
1284 release_dc_ptr( dc
);
1289 /***********************************************************************
1290 * GetOutlineTextMetricsA (GDI32.@)
1291 * Gets metrics for TrueType fonts.
1294 * If the supplied buffer isn't big enough Windows partially fills it up to
1295 * its given length and returns that length.
1298 * Success: Non-zero or size of required buffer
1301 UINT WINAPI
GetOutlineTextMetricsA(
1302 HDC hdc
, /* [in] Handle of device context */
1303 UINT cbData
, /* [in] Size of metric data array */
1304 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1306 char buf
[512], *ptr
;
1308 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1309 OUTLINETEXTMETRICA
*output
= lpOTM
;
1312 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1314 if(ret
> sizeof(buf
))
1315 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1316 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1318 needed
= sizeof(OUTLINETEXTMETRICA
);
1319 if(lpOTMW
->otmpFamilyName
)
1320 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1321 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1322 NULL
, 0, NULL
, NULL
);
1323 if(lpOTMW
->otmpFaceName
)
1324 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1325 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1326 NULL
, 0, NULL
, NULL
);
1327 if(lpOTMW
->otmpStyleName
)
1328 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1329 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1330 NULL
, 0, NULL
, NULL
);
1331 if(lpOTMW
->otmpFullName
)
1332 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1333 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1334 NULL
, 0, NULL
, NULL
);
1341 TRACE("needed = %d\n", needed
);
1343 /* Since the supplied buffer isn't big enough, we'll alloc one
1344 that is and memcpy the first cbData bytes into the lpOTM at
1346 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1348 ret
= output
->otmSize
= min(needed
, cbData
);
1349 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1350 output
->otmFiller
= 0;
1351 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1352 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1353 output
->otmfsType
= lpOTMW
->otmfsType
;
1354 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1355 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1356 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1357 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1358 output
->otmAscent
= lpOTMW
->otmAscent
;
1359 output
->otmDescent
= lpOTMW
->otmDescent
;
1360 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1361 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1362 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1363 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1364 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1365 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1366 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1367 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1368 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1369 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1370 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1371 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1372 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1373 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1374 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1375 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1378 ptr
= (char*)(output
+ 1);
1379 left
= needed
- sizeof(*output
);
1381 if(lpOTMW
->otmpFamilyName
) {
1382 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1383 len
= WideCharToMultiByte(CP_ACP
, 0,
1384 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1385 ptr
, left
, NULL
, NULL
);
1389 output
->otmpFamilyName
= 0;
1391 if(lpOTMW
->otmpFaceName
) {
1392 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1393 len
= WideCharToMultiByte(CP_ACP
, 0,
1394 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1395 ptr
, left
, NULL
, NULL
);
1399 output
->otmpFaceName
= 0;
1401 if(lpOTMW
->otmpStyleName
) {
1402 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1403 len
= WideCharToMultiByte(CP_ACP
, 0,
1404 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1405 ptr
, left
, NULL
, NULL
);
1409 output
->otmpStyleName
= 0;
1411 if(lpOTMW
->otmpFullName
) {
1412 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1413 len
= WideCharToMultiByte(CP_ACP
, 0,
1414 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1415 ptr
, left
, NULL
, NULL
);
1418 output
->otmpFullName
= 0;
1422 if(output
!= lpOTM
) {
1423 memcpy(lpOTM
, output
, cbData
);
1424 HeapFree(GetProcessHeap(), 0, output
);
1426 /* check if the string offsets really fit into the provided size */
1427 /* FIXME: should we check string length as well? */
1428 /* make sure that we don't read/write beyond the provided buffer */
1429 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1431 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1432 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1435 /* make sure that we don't read/write beyond the provided buffer */
1436 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1438 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1439 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1442 /* make sure that we don't read/write beyond the provided buffer */
1443 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1445 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1446 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1449 /* make sure that we don't read/write beyond the provided buffer */
1450 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1452 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1453 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1458 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1459 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1465 /***********************************************************************
1466 * GetOutlineTextMetricsW [GDI32.@]
1468 UINT WINAPI
GetOutlineTextMetricsW(
1469 HDC hdc
, /* [in] Handle of device context */
1470 UINT cbData
, /* [in] Size of metric data array */
1471 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1473 DC
*dc
= get_dc_ptr( hdc
);
1474 OUTLINETEXTMETRICW
*output
= lpOTM
;
1477 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1481 ret
= WineEngGetOutlineTextMetrics(dc
->gdiFont
, cbData
, output
);
1484 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1485 WineEngGetOutlineTextMetrics(dc
->gdiFont
, ret
, output
);
1488 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1489 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1491 #define WDPTOLP(x) ((x<0)? \
1492 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1493 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1494 #define HDPTOLP(y) ((y<0)? \
1495 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1496 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1498 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1499 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1500 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1501 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1502 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1503 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1504 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1505 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1506 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1507 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1508 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1509 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1510 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1511 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1512 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1513 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1514 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1515 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1516 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1517 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1518 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1519 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1520 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1521 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1522 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1523 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1524 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1525 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1526 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1527 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1528 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1529 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1532 if(output
!= lpOTM
) {
1533 memcpy(lpOTM
, output
, cbData
);
1534 HeapFree(GetProcessHeap(), 0, output
);
1540 else { /* This stuff was in GetOutlineTextMetricsA, I've moved it here
1541 but really this should just be a return 0. */
1543 ret
= sizeof(*lpOTM
);
1548 memset(lpOTM
, 0, ret
);
1549 lpOTM
->otmSize
= sizeof(*lpOTM
);
1550 GetTextMetricsW(hdc
, &lpOTM
->otmTextMetrics
);
1552 Further fill of the structure not implemented,
1553 Needs real values for the structure members
1562 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1564 INT i
, count
= lastChar
- firstChar
+ 1;
1571 switch (GdiGetCodePage(hdc
))
1578 if (lastChar
> 0xffff)
1580 if ((firstChar
^ lastChar
) > 0xff)
1584 if (lastChar
> 0xff)
1589 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1593 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1596 str
[i
++] = (BYTE
)(c
>> 8);
1606 /***********************************************************************
1607 * GetCharWidthW (GDI32.@)
1608 * GetCharWidth32W (GDI32.@)
1610 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1615 DC
* dc
= get_dc_ptr( hdc
);
1616 if (!dc
) return FALSE
;
1619 ret
= WineEngGetCharWidth( dc
->gdiFont
, firstChar
, lastChar
, buffer
);
1622 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1623 ret
= physdev
->funcs
->pGetCharWidth( physdev
, firstChar
, lastChar
, buffer
);
1628 /* convert device units to logical */
1629 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1630 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1633 release_dc_ptr( dc
);
1638 /***********************************************************************
1639 * GetCharWidthA (GDI32.@)
1640 * GetCharWidth32A (GDI32.@)
1642 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1650 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1654 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1656 for(i
= 0; i
< wlen
; i
++)
1658 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1666 HeapFree(GetProcessHeap(), 0, str
);
1667 HeapFree(GetProcessHeap(), 0, wstr
);
1673 /***********************************************************************
1674 * ExtTextOutA (GDI32.@)
1678 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1679 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1687 if (flags
& ETO_GLYPH_INDEX
)
1688 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
1690 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
1693 unsigned int i
= 0, j
= 0;
1695 /* allocate enough for a ETO_PDY */
1696 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
1698 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
1702 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
1703 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
1706 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
1713 lpDxW
[j
++] = lpDx
[i
* 2];
1714 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
1717 lpDxW
[j
++] = lpDx
[i
];
1723 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
1725 HeapFree( GetProcessHeap(), 0, p
);
1726 HeapFree( GetProcessHeap(), 0, lpDxW
);
1731 /***********************************************************************
1732 * ExtTextOutW (GDI32.@)
1734 * Draws text using the currently selected font, background color, and text color.
1738 * x,y [I] coordinates of string
1740 * ETO_GRAYED - undocumented on MSDN
1741 * ETO_OPAQUE - use background color for fill the rectangle
1742 * ETO_CLIPPED - clipping text to the rectangle
1743 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
1744 * than encoded characters. Implies ETO_IGNORELANGUAGE
1745 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
1746 * Affects BiDi ordering
1747 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
1748 * ETO_PDY - unimplemented
1749 * ETO_NUMERICSLATIN - unimplemented always assumed -
1750 * do not translate numbers into locale representations
1751 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
1752 * lprect [I] dimensions for clipping or/and opaquing
1753 * str [I] text string
1754 * count [I] number of symbols in string
1755 * lpDx [I] optional parameter with distance between drawing characters
1761 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
1762 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
1765 LPWSTR reordered_str
= (LPWSTR
)str
;
1766 WORD
*glyphs
= NULL
;
1767 UINT align
= GetTextAlign( hdc
);
1768 DWORD layout
= GetLayout( hdc
);
1772 double cosEsc
, sinEsc
;
1776 BOOL done_extents
= FALSE
;
1777 POINT
*deltas
= NULL
, width
= {0, 0};
1779 DC
* dc
= get_dc_ptr( hdc
);
1782 static int quietfixme
= 0;
1784 if (!dc
) return FALSE
;
1786 breakRem
= dc
->breakRem
;
1788 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
1790 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
1795 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
1796 type
= GetObjectType(hdc
);
1797 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
1799 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
1800 release_dc_ptr( dc
);
1805 flags
&= ~ETO_CLIPPED
;
1807 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
1808 if (layout
& LAYOUT_RTL
)
1810 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
1811 align
^= TA_RTLREADING
;
1814 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
1817 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
1819 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
1820 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
1821 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
1823 flags
|= ETO_IGNORELANGUAGE
;
1826 flags
|= ETO_GLYPH_INDEX
;
1827 if (cGlyphs
!= count
)
1831 else if(flags
& ETO_GLYPH_INDEX
)
1832 glyphs
= reordered_str
;
1834 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
1835 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
1836 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
1838 if(align
& TA_UPDATECP
)
1840 GetCurrentPositionEx( hdc
, &pt
);
1845 GetTextMetricsW(hdc
, &tm
);
1846 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
1848 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
1849 lf
.lfEscapement
= 0;
1851 if(lf
.lfEscapement
!= 0)
1853 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
1854 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
1862 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
1866 if(flags
& ETO_GLYPH_INDEX
)
1867 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1869 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1871 done_extents
= TRUE
;
1874 rc
.right
= x
+ sz
.cx
;
1875 rc
.bottom
= y
+ sz
.cy
;
1882 LPtoDP(hdc
, (POINT
*)&rc
, 2);
1884 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
1885 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
1888 if ((flags
& ETO_OPAQUE
) && !PATH_IsPathOpen(dc
->path
))
1889 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
1899 LPtoDP(hdc
, &pt
, 1);
1903 char_extra
= GetTextCharacterExtra(hdc
);
1904 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
1908 POINT total
= {0, 0}, desired
[2];
1910 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
1911 for(i
= 0; i
< count
; i
++)
1917 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
1918 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
1922 deltas
[i
].x
= lpDx
[i
] + char_extra
;
1929 if(flags
& ETO_GLYPH_INDEX
)
1930 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
1932 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
1934 deltas
[i
].x
= tmpsz
.cx
;
1938 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
1940 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
1947 total
.x
+= deltas
[i
].x
;
1948 total
.y
+= deltas
[i
].y
;
1950 desired
[0].x
= desired
[0].y
= 0;
1952 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
1953 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
1955 LPtoDP(hdc
, desired
, 2);
1956 desired
[1].x
-= desired
[0].x
;
1957 desired
[1].y
-= desired
[0].y
;
1958 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
1960 deltas
[i
].x
= desired
[1].x
- width
.x
;
1961 deltas
[i
].y
= desired
[1].y
- width
.y
;
1971 if(flags
& ETO_GLYPH_INDEX
)
1972 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
1974 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
1975 done_extents
= TRUE
;
1977 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
1981 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
1982 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
1983 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
1986 if (align
& TA_UPDATECP
)
1990 DPtoLP(hdc
, &pt
, 1);
1991 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2003 if (align
& TA_UPDATECP
)
2007 DPtoLP(hdc
, &pt
, 1);
2008 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2013 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2016 y
+= tm
.tmAscent
* cosEsc
;
2017 x
+= tm
.tmAscent
* sinEsc
;
2021 y
-= tm
.tmDescent
* cosEsc
;
2022 x
-= tm
.tmDescent
* sinEsc
;
2029 if (GetBkMode(hdc
) != TRANSPARENT
&& !PATH_IsPathOpen(dc
->path
))
2031 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2033 if(!(flags
& ETO_OPAQUE
) || x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2034 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2038 rc
.right
= x
+ width
.x
;
2039 rc
.top
= y
- tm
.tmAscent
;
2040 rc
.bottom
= y
+ tm
.tmDescent
;
2042 if(flags
& ETO_CLIPPED
)
2044 rc
.left
= max(lprect
->left
, rc
.left
);
2045 rc
.right
= min(lprect
->right
, rc
.right
);
2046 rc
.top
= max(lprect
->top
, rc
.top
);
2047 rc
.bottom
= min(lprect
->bottom
, rc
.bottom
);
2049 if(rc
.left
< rc
.right
&& rc
.top
< rc
.bottom
)
2050 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2055 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2057 HFONT orig_font
= dc
->hFont
, cur_font
;
2060 POINT
*offsets
= NULL
;
2063 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2064 for(i
= 0; i
< count
; i
++)
2066 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2067 if(cur_font
!= dc
->hFont
)
2072 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2073 offsets
[0].x
= offsets
[0].y
= 0;
2078 for(j
= 1; j
< count
; j
++)
2080 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2081 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2087 for(j
= 1; j
< count
; j
++)
2089 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2090 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2096 if (PATH_IsPathOpen(dc
->path
))
2097 ret
= PATH_ExtTextOut(dc
, x
+ offsets
[i
- span
].x
, y
+ offsets
[i
- span
].y
,
2098 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2099 glyphs
, span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2101 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2102 y
+ offsets
[i
- span
].y
,
2103 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2104 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2107 SelectObject(hdc
, cur_font
);
2109 glyphs
[span
++] = glyph
;
2113 if (PATH_IsPathOpen(dc
->path
))
2114 ret
= PATH_ExtTextOut(dc
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2115 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2116 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
,
2117 glyphs
, span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2119 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2120 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2121 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2122 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2123 SelectObject(hdc
, orig_font
);
2124 HeapFree(GetProcessHeap(), 0, offsets
);
2130 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2132 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2133 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2134 flags
|= ETO_GLYPH_INDEX
;
2137 if (PATH_IsPathOpen(dc
->path
))
2138 ret
= PATH_ExtTextOut(dc
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2139 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2141 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2142 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2146 HeapFree(GetProcessHeap(), 0, deltas
);
2147 if(glyphs
!= reordered_str
)
2148 HeapFree(GetProcessHeap(), 0, glyphs
);
2149 if(reordered_str
!= str
)
2150 HeapFree(GetProcessHeap(), 0, reordered_str
);
2152 release_dc_ptr( dc
);
2154 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2156 int underlinePos
, strikeoutPos
;
2157 int underlineWidth
, strikeoutWidth
;
2158 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2159 OUTLINETEXTMETRICW
* otm
= NULL
;
2164 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2165 strikeoutPos
= tm
.tmAscent
/ 2;
2166 strikeoutWidth
= underlineWidth
;
2170 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2171 GetOutlineTextMetricsW(hdc
, size
, otm
);
2172 underlinePos
= otm
->otmsUnderscorePosition
;
2173 underlineWidth
= otm
->otmsUnderscoreSize
;
2174 strikeoutPos
= otm
->otmsStrikeoutPosition
;
2175 strikeoutWidth
= otm
->otmsStrikeoutSize
;
2176 HeapFree(GetProcessHeap(), 0, otm
);
2179 if (PATH_IsPathOpen(dc
->path
))
2183 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2185 hbrush
= SelectObject(hdc
, hbrush
);
2186 hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2190 pts
[0].x
= x
- underlinePos
* sinEsc
;
2191 pts
[0].y
= y
- underlinePos
* cosEsc
;
2192 pts
[1].x
= x
+ width
.x
- underlinePos
* sinEsc
;
2193 pts
[1].y
= y
+ width
.y
- underlinePos
* cosEsc
;
2194 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2195 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2196 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2197 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2198 pts
[4].x
= pts
[0].x
;
2199 pts
[4].y
= pts
[0].y
;
2200 DPtoLP(hdc
, pts
, 5);
2201 Polygon(hdc
, pts
, 5);
2206 pts
[0].x
= x
- strikeoutPos
* sinEsc
;
2207 pts
[0].y
= y
- strikeoutPos
* cosEsc
;
2208 pts
[1].x
= x
+ width
.x
- strikeoutPos
* sinEsc
;
2209 pts
[1].y
= y
+ width
.y
- strikeoutPos
* cosEsc
;
2210 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2211 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2212 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2213 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2214 pts
[4].x
= pts
[0].x
;
2215 pts
[4].y
= pts
[0].y
;
2216 DPtoLP(hdc
, pts
, 5);
2217 Polygon(hdc
, pts
, 5);
2220 SelectObject(hdc
, hpen
);
2221 hbrush
= SelectObject(hdc
, hbrush
);
2222 DeleteObject(hbrush
);
2226 POINT pts
[2], oldpt
;
2231 hpen
= CreatePen(PS_SOLID
, underlineWidth
, GetTextColor(hdc
));
2232 hpen
= SelectObject(hdc
, hpen
);
2235 pts
[1].x
= x
+ width
.x
;
2236 pts
[1].y
= y
+ width
.y
;
2237 DPtoLP(hdc
, pts
, 2);
2238 MoveToEx(hdc
, pts
[0].x
- underlinePos
* sinEsc
, pts
[0].y
- underlinePos
* cosEsc
, &oldpt
);
2239 LineTo(hdc
, pts
[1].x
- underlinePos
* sinEsc
, pts
[1].y
- underlinePos
* cosEsc
);
2240 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2241 DeleteObject(SelectObject(hdc
, hpen
));
2246 hpen
= CreatePen(PS_SOLID
, strikeoutWidth
, GetTextColor(hdc
));
2247 hpen
= SelectObject(hdc
, hpen
);
2250 pts
[1].x
= x
+ width
.x
;
2251 pts
[1].y
= y
+ width
.y
;
2252 DPtoLP(hdc
, pts
, 2);
2253 MoveToEx(hdc
, pts
[0].x
- strikeoutPos
* sinEsc
, pts
[0].y
- strikeoutPos
* cosEsc
, &oldpt
);
2254 LineTo(hdc
, pts
[1].x
- strikeoutPos
* sinEsc
, pts
[1].y
- strikeoutPos
* cosEsc
);
2255 MoveToEx(hdc
, oldpt
.x
, oldpt
.y
, NULL
);
2256 DeleteObject(SelectObject(hdc
, hpen
));
2265 /***********************************************************************
2266 * TextOutA (GDI32.@)
2268 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2270 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2274 /***********************************************************************
2275 * TextOutW (GDI32.@)
2277 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2279 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2283 /***********************************************************************
2284 * PolyTextOutA (GDI32.@)
2288 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2290 for (; cStrings
>0; cStrings
--, pptxt
++)
2291 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2298 /***********************************************************************
2299 * PolyTextOutW (GDI32.@)
2301 * Draw several Strings
2307 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2309 for (; cStrings
>0; cStrings
--, pptxt
++)
2310 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2316 /***********************************************************************
2317 * SetMapperFlags (GDI32.@)
2319 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2321 DC
*dc
= get_dc_ptr( hdc
);
2322 DWORD ret
= GDI_ERROR
;
2326 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2327 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2328 if (flags
!= GDI_ERROR
)
2330 ret
= dc
->mapperFlags
;
2331 dc
->mapperFlags
= flags
;
2333 release_dc_ptr( dc
);
2338 /***********************************************************************
2339 * GetAspectRatioFilterEx (GDI32.@)
2341 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2343 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2348 /***********************************************************************
2349 * GetCharABCWidthsA (GDI32.@)
2351 * See GetCharABCWidthsW.
2353 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2361 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2365 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2368 HeapFree(GetProcessHeap(), 0, str
);
2372 for(i
= 0; i
< wlen
; i
++)
2374 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2382 HeapFree(GetProcessHeap(), 0, str
);
2383 HeapFree(GetProcessHeap(), 0, wstr
);
2389 /******************************************************************************
2390 * GetCharABCWidthsW [GDI32.@]
2392 * Retrieves widths of characters in range.
2395 * hdc [I] Handle of device context
2396 * firstChar [I] First character in range to query
2397 * lastChar [I] Last character in range to query
2398 * abc [O] Address of character-width structure
2401 * Only works with TrueType fonts
2407 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2410 DC
*dc
= get_dc_ptr(hdc
);
2414 if (!dc
) return FALSE
;
2418 release_dc_ptr( dc
);
2423 ret
= WineEngGetCharABCWidths( dc
->gdiFont
, firstChar
, lastChar
, abc
);
2429 /* convert device units to logical */
2430 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2431 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2432 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2433 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2438 release_dc_ptr( dc
);
2443 /******************************************************************************
2444 * GetCharABCWidthsI [GDI32.@]
2446 * Retrieves widths of characters in range.
2449 * hdc [I] Handle of device context
2450 * firstChar [I] First glyphs in range to query
2451 * count [I] Last glyphs in range to query
2452 * pgi [i] Array of glyphs to query
2453 * abc [O] Address of character-width structure
2456 * Only works with TrueType fonts
2462 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2463 LPWORD pgi
, LPABC abc
)
2465 DC
*dc
= get_dc_ptr(hdc
);
2469 if (!dc
) return FALSE
;
2473 release_dc_ptr( dc
);
2478 ret
= WineEngGetCharABCWidthsI( dc
->gdiFont
, firstChar
, count
, pgi
, abc
);
2484 /* convert device units to logical */
2485 for( i
= 0; i
< count
; i
++, abc
++ ) {
2486 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2487 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2488 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2493 release_dc_ptr( dc
);
2498 /***********************************************************************
2499 * GetGlyphOutlineA (GDI32.@)
2501 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2502 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2503 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2505 if (!lpmat2
) return GDI_ERROR
;
2507 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2512 cp
= GdiGetCodePage(hdc
);
2513 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2515 mbchs
[0] = (uChar
& 0xff00) >> 8;
2516 mbchs
[1] = (uChar
& 0xff);
2519 mbchs
[0] = (uChar
& 0xff);
2522 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2525 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2529 /***********************************************************************
2530 * GetGlyphOutlineW (GDI32.@)
2532 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2533 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2534 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2539 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2540 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2542 if (!lpmat2
) return GDI_ERROR
;
2544 dc
= get_dc_ptr(hdc
);
2545 if(!dc
) return GDI_ERROR
;
2548 ret
= WineEngGetGlyphOutline(dc
->gdiFont
, uChar
, fuFormat
, lpgm
,
2549 cbBuffer
, lpBuffer
, lpmat2
);
2553 release_dc_ptr( dc
);
2558 /***********************************************************************
2559 * CreateScalableFontResourceA (GDI32.@)
2561 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2562 LPCSTR lpszResourceFile
,
2563 LPCSTR lpszFontFile
,
2564 LPCSTR lpszCurrentPath
)
2566 LPWSTR lpszResourceFileW
= NULL
;
2567 LPWSTR lpszFontFileW
= NULL
;
2568 LPWSTR lpszCurrentPathW
= NULL
;
2572 if (lpszResourceFile
)
2574 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2575 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2576 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2581 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2582 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2583 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2586 if (lpszCurrentPath
)
2588 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2589 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2590 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2593 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2594 lpszFontFileW
, lpszCurrentPathW
);
2596 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2597 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2598 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2603 /***********************************************************************
2604 * CreateScalableFontResourceW (GDI32.@)
2606 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2607 LPCWSTR lpszResourceFile
,
2608 LPCWSTR lpszFontFile
,
2609 LPCWSTR lpszCurrentPath
)
2612 FIXME("(%d,%s,%s,%s): stub\n",
2613 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2614 debugstr_w(lpszCurrentPath
) );
2616 /* fHidden=1 - only visible for the calling app, read-only, not
2617 * enumerated with EnumFonts/EnumFontFamilies
2618 * lpszCurrentPath can be NULL
2621 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2622 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2624 SetLastError(ERROR_FILE_EXISTS
);
2627 return FALSE
; /* create failed */
2630 /*************************************************************************
2631 * GetKerningPairsA (GDI32.@)
2633 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2634 LPKERNINGPAIR kern_pairA
)
2638 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2639 KERNINGPAIR
*kern_pairW
;
2641 if (!cPairs
&& kern_pairA
)
2643 SetLastError(ERROR_INVALID_PARAMETER
);
2647 cp
= GdiGetCodePage(hDC
);
2649 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2650 * to fail on an invalid character for CP_SYMBOL.
2652 cpi
.DefaultChar
[0] = 0;
2653 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2655 FIXME("Can't find codepage %u info\n", cp
);
2659 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2660 if (!total_kern_pairs
) return 0;
2662 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2663 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2665 for (i
= 0; i
< total_kern_pairs
; i
++)
2669 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2672 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2675 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2680 if (kern_pairs_copied
>= cPairs
) break;
2682 kern_pairA
->wFirst
= (BYTE
)first
;
2683 kern_pairA
->wSecond
= (BYTE
)second
;
2684 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2687 kern_pairs_copied
++;
2690 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2692 return kern_pairs_copied
;
2695 /*************************************************************************
2696 * GetKerningPairsW (GDI32.@)
2698 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2699 LPKERNINGPAIR lpKerningPairs
)
2704 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2706 if (!cPairs
&& lpKerningPairs
)
2708 SetLastError(ERROR_INVALID_PARAMETER
);
2712 dc
= get_dc_ptr(hDC
);
2716 ret
= WineEngGetKerningPairs(dc
->gdiFont
, cPairs
, lpKerningPairs
);
2718 release_dc_ptr( dc
);
2722 /*************************************************************************
2723 * TranslateCharsetInfo [GDI32.@]
2725 * Fills a CHARSETINFO structure for a character set, code page, or
2726 * font. This allows making the correspondence between different labels
2727 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2728 * of the same encoding.
2730 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
2731 * only one codepage should be set in *lpSrc.
2734 * TRUE on success, FALSE on failure.
2737 BOOL WINAPI
TranslateCharsetInfo(
2738 LPDWORD lpSrc
, /* [in]
2739 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
2740 if flags == TCI_SRCCHARSET: a character set value
2741 if flags == TCI_SRCCODEPAGE: a code page value
2743 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
2744 DWORD flags
/* [in] determines interpretation of lpSrc */)
2748 case TCI_SRCFONTSIG
:
2749 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
2751 case TCI_SRCCODEPAGE
:
2752 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
2754 case TCI_SRCCHARSET
:
2755 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
2760 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
2761 *lpCs
= FONT_tci
[index
];
2765 /*************************************************************************
2766 * GetFontLanguageInfo (GDI32.@)
2768 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
2770 FONTSIGNATURE fontsig
;
2771 static const DWORD GCP_DBCS_MASK
=0x003F0000,
2772 GCP_DIACRITIC_MASK
=0x00000000,
2773 FLI_GLYPHS_MASK
=0x00000000,
2774 GCP_GLYPHSHAPE_MASK
=0x00000040,
2775 GCP_KASHIDA_MASK
=0x00000000,
2776 GCP_LIGATE_MASK
=0x00000000,
2777 GCP_USEKERNING_MASK
=0x00000000,
2778 GCP_REORDER_MASK
=0x00000060;
2782 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
2783 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
2785 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
2788 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
2789 result
|=GCP_DIACRITIC
;
2791 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
2794 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
2795 result
|=GCP_GLYPHSHAPE
;
2797 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
2798 result
|=GCP_KASHIDA
;
2800 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
2803 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
2804 result
|=GCP_USEKERNING
;
2806 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
2807 if( GetTextAlign( hdc
) & TA_RTLREADING
)
2808 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
2809 result
|=GCP_REORDER
;
2815 /*************************************************************************
2816 * GetFontData [GDI32.@]
2818 * Retrieve data for TrueType font.
2822 * success: Number of bytes returned
2823 * failure: GDI_ERROR
2827 * Calls SetLastError()
2830 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
2831 LPVOID buffer
, DWORD length
)
2833 DC
*dc
= get_dc_ptr(hdc
);
2834 DWORD ret
= GDI_ERROR
;
2836 if(!dc
) return GDI_ERROR
;
2839 ret
= WineEngGetFontData(dc
->gdiFont
, table
, offset
, buffer
, length
);
2841 release_dc_ptr( dc
);
2845 /*************************************************************************
2846 * GetGlyphIndicesA [GDI32.@]
2848 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
2849 LPWORD pgi
, DWORD flags
)
2855 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2856 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
2858 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
2859 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
2860 HeapFree(GetProcessHeap(), 0, lpstrW
);
2865 /*************************************************************************
2866 * GetGlyphIndicesW [GDI32.@]
2868 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
2869 LPWORD pgi
, DWORD flags
)
2871 DC
*dc
= get_dc_ptr(hdc
);
2872 DWORD ret
= GDI_ERROR
;
2874 TRACE("(%p, %s, %d, %p, 0x%x)\n",
2875 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
2877 if(!dc
) return GDI_ERROR
;
2880 ret
= WineEngGetGlyphIndices(dc
->gdiFont
, lpstr
, count
, pgi
, flags
);
2882 release_dc_ptr( dc
);
2886 /*************************************************************************
2887 * GetCharacterPlacementA [GDI32.@]
2889 * See GetCharacterPlacementW.
2892 * the web browser control of ie4 calls this with dwFlags=0
2895 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
2896 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
2901 GCP_RESULTSW resultsW
;
2905 TRACE("%s, %d, %d, 0x%08x\n",
2906 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2908 /* both structs are equal in size */
2909 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
2911 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
2912 if(lpResults
->lpOutString
)
2913 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
2915 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
2917 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
2918 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
2920 if(lpResults
->lpOutString
) {
2921 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
2922 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
2925 HeapFree(GetProcessHeap(), 0, lpStringW
);
2926 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
2931 /*************************************************************************
2932 * GetCharacterPlacementW [GDI32.@]
2934 * Retrieve information about a string. This includes the width, reordering,
2935 * Glyphing and so on.
2939 * The width and height of the string if successful, 0 if failed.
2943 * All flags except GCP_REORDER are not yet implemented.
2944 * Reordering is not 100% compliant to the Windows BiDi method.
2945 * Caret positioning is not yet implemented for BiDi.
2946 * Classes are not yet implemented.
2950 GetCharacterPlacementW(
2951 HDC hdc
, /* [in] Device context for which the rendering is to be done */
2952 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
2953 INT uCount
, /* [in] Number of WORDS in string. */
2954 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
2955 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
2956 DWORD dwFlags
/* [in] Flags specifying how to process the string */
2963 TRACE("%s, %d, %d, 0x%08x\n",
2964 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
2966 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
2967 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
2968 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
2969 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
2970 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
2972 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
2973 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
2974 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
2975 FIXME("Caret positions for complex scripts not implemented\n");
2977 nSet
= (UINT
)uCount
;
2978 if(nSet
> lpResults
->nGlyphs
)
2979 nSet
= lpResults
->nGlyphs
;
2981 /* return number of initialized fields */
2982 lpResults
->nGlyphs
= nSet
;
2984 if((dwFlags
&GCP_REORDER
)==0 )
2986 /* Treat the case where no special handling was requested in a fastpath way */
2987 /* copy will do if the GCP_REORDER flag is not set */
2988 if(lpResults
->lpOutString
)
2989 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
2991 if(lpResults
->lpOrder
)
2993 for(i
= 0; i
< nSet
; i
++)
2994 lpResults
->lpOrder
[i
] = i
;
2998 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
2999 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3002 /* FIXME: Will use the placement chars */
3003 if (lpResults
->lpDx
)
3006 for (i
= 0; i
< nSet
; i
++)
3008 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3009 lpResults
->lpDx
[i
]= c
;
3013 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3017 lpResults
->lpCaretPos
[0] = 0;
3018 for (i
= 1; i
< nSet
; i
++)
3019 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3020 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3023 if(lpResults
->lpGlyphs
)
3024 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3026 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3027 ret
= MAKELONG(size
.cx
, size
.cy
);
3032 /*************************************************************************
3033 * GetCharABCWidthsFloatA [GDI32.@]
3035 * See GetCharABCWidthsFloatW.
3037 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3044 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3048 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3050 for (i
= 0; i
< wlen
; i
++)
3052 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3060 HeapFree( GetProcessHeap(), 0, str
);
3061 HeapFree( GetProcessHeap(), 0, wstr
);
3066 /*************************************************************************
3067 * GetCharABCWidthsFloatW [GDI32.@]
3069 * Retrieves widths of a range of characters.
3072 * hdc [I] Handle to device context.
3073 * first [I] First character in range to query.
3074 * last [I] Last character in range to query.
3075 * abcf [O] Array of LPABCFLOAT structures.
3081 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3085 DC
*dc
= get_dc_ptr( hdc
);
3087 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3089 if (!dc
) return FALSE
;
3093 release_dc_ptr( dc
);
3098 ret
= WineEngGetCharABCWidthsFloat( dc
->gdiFont
, first
, last
, abcf
);
3104 /* convert device units to logical */
3105 for (i
= first
; i
<= last
; i
++, abcf
++)
3107 abcf
->abcfA
= abcf
->abcfA
* dc
->xformVport2World
.eM11
;
3108 abcf
->abcfB
= abcf
->abcfB
* dc
->xformVport2World
.eM11
;
3109 abcf
->abcfC
= abcf
->abcfC
* dc
->xformVport2World
.eM11
;
3113 release_dc_ptr( dc
);
3117 /*************************************************************************
3118 * GetCharWidthFloatA [GDI32.@]
3120 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3121 UINT iLastChar
, PFLOAT pxBuffer
)
3123 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3127 /*************************************************************************
3128 * GetCharWidthFloatW [GDI32.@]
3130 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3131 UINT iLastChar
, PFLOAT pxBuffer
)
3133 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3138 /***********************************************************************
3140 * Font Resource API *
3142 ***********************************************************************/
3144 /***********************************************************************
3145 * AddFontResourceA (GDI32.@)
3147 INT WINAPI
AddFontResourceA( LPCSTR str
)
3149 return AddFontResourceExA( str
, 0, NULL
);
3152 /***********************************************************************
3153 * AddFontResourceW (GDI32.@)
3155 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3157 return AddFontResourceExW(str
, 0, NULL
);
3161 /***********************************************************************
3162 * AddFontResourceExA (GDI32.@)
3164 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3166 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3167 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3170 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3171 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3172 HeapFree(GetProcessHeap(), 0, strW
);
3176 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3178 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3179 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3180 LPVOID
*pMem
= LockResource(hMem
);
3181 int *num_total
= (int *)lParam
;
3184 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3185 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3187 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3191 *num_total
+= num_in_res
;
3195 /***********************************************************************
3196 * AddFontResourceExW (GDI32.@)
3198 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3200 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3203 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3204 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3205 if (hModule
!= NULL
)
3207 int num_resources
= 0;
3208 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3210 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3211 wine_dbgstr_w(str
));
3212 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3213 ret
= num_resources
;
3214 FreeLibrary(hModule
);
3220 /***********************************************************************
3221 * RemoveFontResourceA (GDI32.@)
3223 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3225 return RemoveFontResourceExA(str
, 0, 0);
3228 /***********************************************************************
3229 * RemoveFontResourceW (GDI32.@)
3231 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3233 return RemoveFontResourceExW(str
, 0, 0);
3236 /***********************************************************************
3237 * AddFontMemResourceEx (GDI32.@)
3239 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3244 if (!pbFont
|| !cbFont
|| !pcFonts
)
3246 SetLastError(ERROR_INVALID_PARAMETER
);
3250 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3255 *pcFonts
= num_fonts
;
3259 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3260 RemoveFontMemResourceEx(ret
);
3268 /***********************************************************************
3269 * RemoveFontMemResourceEx (GDI32.@)
3271 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3273 FIXME("(%p) stub\n", fh
);
3277 /***********************************************************************
3278 * RemoveFontResourceExA (GDI32.@)
3280 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3282 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3283 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3286 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3287 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3288 HeapFree(GetProcessHeap(), 0, strW
);
3292 /***********************************************************************
3293 * RemoveFontResourceExW (GDI32.@)
3295 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3297 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3300 /***********************************************************************
3301 * GetTextCharset (GDI32.@)
3303 UINT WINAPI
GetTextCharset(HDC hdc
)
3305 /* MSDN docs say this is equivalent */
3306 return GetTextCharsetInfo(hdc
, NULL
, 0);
3309 /***********************************************************************
3310 * GetTextCharsetInfo (GDI32.@)
3312 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3314 UINT ret
= DEFAULT_CHARSET
;
3315 DC
*dc
= get_dc_ptr(hdc
);
3320 ret
= WineEngGetTextCharsetInfo(dc
->gdiFont
, fs
, flags
);
3322 release_dc_ptr( dc
);
3325 if (ret
== DEFAULT_CHARSET
&& fs
)
3326 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3330 /***********************************************************************
3331 * GdiGetCharDimensions (GDI32.@)
3333 * Gets the average width of the characters in the English alphabet.
3336 * hdc [I] Handle to the device context to measure on.
3337 * lptm [O] Pointer to memory to store the text metrics into.
3338 * height [O] On exit, the maximum height of characters in the English alphabet.
3341 * The average width of characters in the English alphabet.
3344 * This function is used by the dialog manager to get the size of a dialog
3345 * unit. It should also be used by other pieces of code that need to know
3346 * the size of a dialog unit in logical units without having access to the
3347 * window handle of the dialog.
3348 * Windows caches the font metrics from this function, but we don't and
3349 * there doesn't appear to be an immediate advantage to do so.
3352 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3354 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3357 static const WCHAR alphabet
[] = {
3358 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3359 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3360 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3362 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3364 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3366 if (height
) *height
= sz
.cy
;
3367 return (sz
.cx
/ 26 + 1) / 2;
3370 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3372 FIXME("(%d): stub\n", fEnableEUDC
);
3376 /***********************************************************************
3377 * GetCharWidthI (GDI32.@)
3379 * Retrieve widths of characters.
3382 * hdc [I] Handle to a device context.
3383 * first [I] First glyph in range to query.
3384 * count [I] Number of glyph indices to query.
3385 * glyphs [I] Array of glyphs to query.
3386 * buffer [O] Buffer to receive character widths.
3389 * Only works with TrueType fonts.
3395 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3400 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3402 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3405 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3407 HeapFree(GetProcessHeap(), 0, abc
);
3411 for (i
= 0; i
< count
; i
++)
3412 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3414 HeapFree(GetProcessHeap(), 0, abc
);
3418 /***********************************************************************
3419 * GetFontUnicodeRanges (GDI32.@)
3421 * Retrieve a list of supported Unicode characters in a font.
3424 * hdc [I] Handle to a device context.
3425 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3428 * Success: Number of bytes written to the buffer pointed to by lpgs.
3432 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3435 DC
*dc
= get_dc_ptr(hdc
);
3437 TRACE("(%p, %p)\n", hdc
, lpgs
);
3441 if (dc
->gdiFont
) ret
= WineEngGetFontUnicodeRanges(dc
->gdiFont
, lpgs
);
3447 /*************************************************************
3448 * FontIsLinked (GDI32.@)
3450 BOOL WINAPI
FontIsLinked(HDC hdc
)
3452 DC
*dc
= get_dc_ptr(hdc
);
3455 if (!dc
) return FALSE
;
3456 if (dc
->gdiFont
) ret
= WineEngFontIsLinked(dc
->gdiFont
);
3458 TRACE("returning %d\n", ret
);
3462 /*************************************************************
3463 * GdiRealizationInfo (GDI32.@)
3465 * Returns a structure that contains some font information.
3467 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3469 DC
*dc
= get_dc_ptr(hdc
);
3472 if (!dc
) return FALSE
;
3473 if (dc
->gdiFont
) ret
= WineEngRealizationInfo(dc
->gdiFont
, info
);