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"
36 #include "gdi_private.h"
37 #include "wine/exception.h"
38 #include "wine/unicode.h"
39 #include "wine/debug.h"
41 #ifdef WORDS_BIGENDIAN
42 #define get_be_word(x) (x)
44 #define get_be_word(x) RtlUshortByteSwap(x)
47 WINE_DEFAULT_DEBUG_CHANNEL(font
);
49 /* Device -> World size conversion */
51 /* Performs a device to world transformation on the specified width (which
52 * is in integer format).
54 static inline INT
INTERNAL_XDSTOWS(DC
*dc
, INT width
)
58 /* Perform operation with floating point */
59 floatWidth
= (double)width
* dc
->xformVport2World
.eM11
;
60 /* Round to integers */
61 return GDI_ROUND(floatWidth
);
64 /* Performs a device to world transformation on the specified size (which
65 * is in integer format).
67 static inline INT
INTERNAL_YDSTOWS(DC
*dc
, INT height
)
71 /* Perform operation with floating point */
72 floatHeight
= (double)height
* dc
->xformVport2World
.eM22
;
73 /* Round to integers */
74 return GDI_ROUND(floatHeight
);
77 static inline INT
INTERNAL_XWSTODS(DC
*dc
, INT width
)
80 pt
[0].x
= pt
[0].y
= 0;
83 LPtoDP(dc
->hSelf
, pt
, 2);
84 return pt
[1].x
- pt
[0].x
;
87 static inline INT
INTERNAL_YWSTODS(DC
*dc
, INT height
)
90 pt
[0].x
= pt
[0].y
= 0;
93 LPtoDP(dc
->hSelf
, pt
, 2);
94 return pt
[1].y
- pt
[0].y
;
97 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
);
98 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
);
99 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
);
100 static BOOL
FONT_DeleteObject( HGDIOBJ handle
);
102 static const struct gdi_obj_funcs font_funcs
=
104 FONT_SelectObject
, /* pSelectObject */
105 FONT_GetObjectA
, /* pGetObjectA */
106 FONT_GetObjectW
, /* pGetObjectW */
107 NULL
, /* pUnrealizeObject */
108 FONT_DeleteObject
/* pDeleteObject */
119 LPLOGFONTW lpLogFontParam
;
120 FONTENUMPROCW lpEnumFunc
;
128 * For TranslateCharsetInfo
130 #define MAXTCIINDEX 32
131 static const CHARSETINFO FONT_tci
[MAXTCIINDEX
] = {
133 { ANSI_CHARSET
, 1252, {{0,0,0,0},{FS_LATIN1
,0}} },
134 { EASTEUROPE_CHARSET
, 1250, {{0,0,0,0},{FS_LATIN2
,0}} },
135 { RUSSIAN_CHARSET
, 1251, {{0,0,0,0},{FS_CYRILLIC
,0}} },
136 { GREEK_CHARSET
, 1253, {{0,0,0,0},{FS_GREEK
,0}} },
137 { TURKISH_CHARSET
, 1254, {{0,0,0,0},{FS_TURKISH
,0}} },
138 { HEBREW_CHARSET
, 1255, {{0,0,0,0},{FS_HEBREW
,0}} },
139 { ARABIC_CHARSET
, 1256, {{0,0,0,0},{FS_ARABIC
,0}} },
140 { BALTIC_CHARSET
, 1257, {{0,0,0,0},{FS_BALTIC
,0}} },
141 { VIETNAMESE_CHARSET
, 1258, {{0,0,0,0},{FS_VIETNAMESE
,0}} },
142 /* reserved by ANSI */
143 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
144 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
145 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
146 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
147 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
148 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
149 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
151 { THAI_CHARSET
, 874, {{0,0,0,0},{FS_THAI
,0}} },
152 { SHIFTJIS_CHARSET
, 932, {{0,0,0,0},{FS_JISJAPAN
,0}} },
153 { GB2312_CHARSET
, 936, {{0,0,0,0},{FS_CHINESESIMP
,0}} },
154 { HANGEUL_CHARSET
, 949, {{0,0,0,0},{FS_WANSUNG
,0}} },
155 { CHINESEBIG5_CHARSET
, 950, {{0,0,0,0},{FS_CHINESETRAD
,0}} },
156 { JOHAB_CHARSET
, 1361, {{0,0,0,0},{FS_JOHAB
,0}} },
157 /* reserved for alternate ANSI and OEM */
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 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
162 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
163 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
164 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
165 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
166 /* reserved for system */
167 { DEFAULT_CHARSET
, 0, {{0,0,0,0},{FS_LATIN1
,0}} },
168 { SYMBOL_CHARSET
, CP_SYMBOL
, {{0,0,0,0},{FS_SYMBOL
,0}} }
171 static void FONT_LogFontAToW( const LOGFONTA
*fontA
, LPLOGFONTW fontW
)
173 memcpy(fontW
, fontA
, sizeof(LOGFONTA
) - LF_FACESIZE
);
174 MultiByteToWideChar(CP_ACP
, 0, fontA
->lfFaceName
, -1, fontW
->lfFaceName
,
176 fontW
->lfFaceName
[LF_FACESIZE
-1] = 0;
179 static void FONT_LogFontWToA( const LOGFONTW
*fontW
, LPLOGFONTA fontA
)
181 memcpy(fontA
, fontW
, sizeof(LOGFONTA
) - LF_FACESIZE
);
182 WideCharToMultiByte(CP_ACP
, 0, fontW
->lfFaceName
, -1, fontA
->lfFaceName
,
183 LF_FACESIZE
, NULL
, NULL
);
184 fontA
->lfFaceName
[LF_FACESIZE
-1] = 0;
187 static void FONT_EnumLogFontExWToA( const ENUMLOGFONTEXW
*fontW
, LPENUMLOGFONTEXA fontA
)
189 FONT_LogFontWToA( &fontW
->elfLogFont
, &fontA
->elfLogFont
);
191 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfFullName
, -1,
192 (LPSTR
) fontA
->elfFullName
, LF_FULLFACESIZE
, NULL
, NULL
);
193 fontA
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
194 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfStyle
, -1,
195 (LPSTR
) fontA
->elfStyle
, LF_FACESIZE
, NULL
, NULL
);
196 fontA
->elfStyle
[LF_FACESIZE
-1] = '\0';
197 WideCharToMultiByte( CP_ACP
, 0, fontW
->elfScript
, -1,
198 (LPSTR
) fontA
->elfScript
, LF_FACESIZE
, NULL
, NULL
);
199 fontA
->elfScript
[LF_FACESIZE
-1] = '\0';
202 static void FONT_EnumLogFontExAToW( const ENUMLOGFONTEXA
*fontA
, LPENUMLOGFONTEXW fontW
)
204 FONT_LogFontAToW( &fontA
->elfLogFont
, &fontW
->elfLogFont
);
206 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfFullName
, -1,
207 fontW
->elfFullName
, LF_FULLFACESIZE
);
208 fontW
->elfFullName
[LF_FULLFACESIZE
-1] = '\0';
209 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfStyle
, -1,
210 fontW
->elfStyle
, LF_FACESIZE
);
211 fontW
->elfStyle
[LF_FACESIZE
-1] = '\0';
212 MultiByteToWideChar( CP_ACP
, 0, (LPCSTR
)fontA
->elfScript
, -1,
213 fontW
->elfScript
, LF_FACESIZE
);
214 fontW
->elfScript
[LF_FACESIZE
-1] = '\0';
217 /***********************************************************************
218 * TEXTMETRIC conversion functions.
220 static void FONT_TextMetricWToA(const TEXTMETRICW
*ptmW
, LPTEXTMETRICA ptmA
)
222 ptmA
->tmHeight
= ptmW
->tmHeight
;
223 ptmA
->tmAscent
= ptmW
->tmAscent
;
224 ptmA
->tmDescent
= ptmW
->tmDescent
;
225 ptmA
->tmInternalLeading
= ptmW
->tmInternalLeading
;
226 ptmA
->tmExternalLeading
= ptmW
->tmExternalLeading
;
227 ptmA
->tmAveCharWidth
= ptmW
->tmAveCharWidth
;
228 ptmA
->tmMaxCharWidth
= ptmW
->tmMaxCharWidth
;
229 ptmA
->tmWeight
= ptmW
->tmWeight
;
230 ptmA
->tmOverhang
= ptmW
->tmOverhang
;
231 ptmA
->tmDigitizedAspectX
= ptmW
->tmDigitizedAspectX
;
232 ptmA
->tmDigitizedAspectY
= ptmW
->tmDigitizedAspectY
;
233 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 255);
234 if (ptmW
->tmCharSet
== SYMBOL_CHARSET
)
236 ptmA
->tmFirstChar
= 0x1e;
237 ptmA
->tmLastChar
= 0xff; /* win9x behaviour - we need the OS2 table data to calculate correctly */
239 else if (ptmW
->tmPitchAndFamily
& TMPF_TRUETYPE
)
241 ptmA
->tmFirstChar
= ptmW
->tmDefaultChar
- 1;
242 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
246 ptmA
->tmFirstChar
= min(ptmW
->tmFirstChar
, 0xff);
247 ptmA
->tmLastChar
= min(ptmW
->tmLastChar
, 0xff);
249 ptmA
->tmDefaultChar
= ptmW
->tmDefaultChar
;
250 ptmA
->tmBreakChar
= ptmW
->tmBreakChar
;
251 ptmA
->tmItalic
= ptmW
->tmItalic
;
252 ptmA
->tmUnderlined
= ptmW
->tmUnderlined
;
253 ptmA
->tmStruckOut
= ptmW
->tmStruckOut
;
254 ptmA
->tmPitchAndFamily
= ptmW
->tmPitchAndFamily
;
255 ptmA
->tmCharSet
= ptmW
->tmCharSet
;
259 static void FONT_NewTextMetricExWToA(const NEWTEXTMETRICEXW
*ptmW
, NEWTEXTMETRICEXA
*ptmA
)
261 FONT_TextMetricWToA((const TEXTMETRICW
*)ptmW
, (LPTEXTMETRICA
)ptmA
);
262 ptmA
->ntmTm
.ntmFlags
= ptmW
->ntmTm
.ntmFlags
;
263 ptmA
->ntmTm
.ntmSizeEM
= ptmW
->ntmTm
.ntmSizeEM
;
264 ptmA
->ntmTm
.ntmCellHeight
= ptmW
->ntmTm
.ntmCellHeight
;
265 ptmA
->ntmTm
.ntmAvgWidth
= ptmW
->ntmTm
.ntmAvgWidth
;
266 memcpy(&ptmA
->ntmFontSig
, &ptmW
->ntmFontSig
, sizeof(FONTSIGNATURE
));
269 static DWORD
get_font_ppem( HDC hdc
)
273 DC
*dc
= get_dc_ptr( hdc
);
275 if (!dc
) return GDI_ERROR
;
277 GetTextMetricsW( hdc
, &tm
);
278 ppem
= abs( INTERNAL_YWSTODS( dc
, tm
.tmAscent
+ tm
.tmDescent
- tm
.tmInternalLeading
) );
279 release_dc_ptr( dc
);
283 #define GASP_GRIDFIT 0x01
284 #define GASP_DOGRAY 0x02
286 static BOOL
get_gasp_flags( HDC hdc
, WORD
*flags
)
288 DWORD size
, gasp_tag
= 0x70736167;
289 WORD buf
[16]; /* Enough for seven ranges before we need to alloc */
290 WORD
*alloced
= NULL
, *ptr
= buf
;
291 WORD num_recs
, version
;
292 DWORD ppem
= get_font_ppem( hdc
);
296 if (ppem
== GDI_ERROR
) return FALSE
;
298 size
= GetFontData( hdc
, gasp_tag
, 0, NULL
, 0 );
299 if (size
== GDI_ERROR
) return FALSE
;
300 if (size
< 4 * sizeof(WORD
)) return FALSE
;
301 if (size
> sizeof(buf
))
303 ptr
= alloced
= HeapAlloc( GetProcessHeap(), 0, size
);
304 if (!ptr
) return FALSE
;
307 GetFontData( hdc
, gasp_tag
, 0, ptr
, size
);
309 version
= get_be_word( *ptr
++ );
310 num_recs
= get_be_word( *ptr
++ );
312 if (version
> 1 || size
< (num_recs
* 2 + 2) * sizeof(WORD
))
314 FIXME( "Unsupported gasp table: ver %d size %d recs %d\n", version
, size
, num_recs
);
320 *flags
= get_be_word( *(ptr
+ 1) );
321 if (ppem
<= get_be_word( *ptr
)) break;
324 TRACE( "got flags %04x for ppem %d\n", *flags
, ppem
);
328 HeapFree( GetProcessHeap(), 0, alloced
);
332 UINT
get_font_aa_flags( HDC hdc
)
337 if (GetObjectType( hdc
) == OBJ_MEMDC
)
340 GetObjectW( GetCurrentObject( hdc
, OBJ_BITMAP
), sizeof(bm
), &bm
);
341 if (bm
.bmBitsPixel
<= 8) return GGO_BITMAP
;
343 else if (GetDeviceCaps( hdc
, BITSPIXEL
) <= 8) return GGO_BITMAP
;
345 GetObjectW( GetCurrentObject( hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
346 if (lf
.lfQuality
== NONANTIALIASED_QUALITY
) return GGO_BITMAP
;
348 if (get_gasp_flags( hdc
, &gasp_flags
) && !(gasp_flags
& GASP_DOGRAY
))
351 /* FIXME, check user prefs */
352 return GGO_GRAY4_BITMAP
;
355 /***********************************************************************
356 * GdiGetCodePage (GDI32.@)
358 DWORD WINAPI
GdiGetCodePage( HDC hdc
)
361 DC
*dc
= get_dc_ptr( hdc
);
365 cp
= dc
->font_code_page
;
366 release_dc_ptr( dc
);
371 /***********************************************************************
374 * Returns a Unicode translation of str using the charset of the
375 * currently selected font in hdc. If count is -1 then str is assumed
376 * to be '\0' terminated, otherwise it contains the number of bytes to
377 * convert. If plenW is non-NULL, on return it will point to the
378 * number of WCHARs that have been written. If pCP is non-NULL, on
379 * return it will point to the codepage used in the conversion. The
380 * caller should free the returned LPWSTR from the process heap
383 static LPWSTR
FONT_mbtowc(HDC hdc
, LPCSTR str
, INT count
, INT
*plenW
, UINT
*pCP
)
389 cp
= GdiGetCodePage( hdc
);
391 if(count
== -1) count
= strlen(str
);
392 lenW
= MultiByteToWideChar(cp
, 0, str
, count
, NULL
, 0);
393 strW
= HeapAlloc(GetProcessHeap(), 0, lenW
*sizeof(WCHAR
));
394 MultiByteToWideChar(cp
, 0, str
, count
, strW
, lenW
);
395 TRACE("mapped %s -> %s\n", debugstr_an(str
, count
), debugstr_wn(strW
, lenW
));
396 if(plenW
) *plenW
= lenW
;
401 /***********************************************************************
402 * CreateFontIndirectExA (GDI32.@)
404 HFONT WINAPI
CreateFontIndirectExA( const ENUMLOGFONTEXDVA
*penumexA
)
406 ENUMLOGFONTEXDVW enumexW
;
408 if (!penumexA
) return 0;
410 FONT_EnumLogFontExAToW( &penumexA
->elfEnumLogfontEx
, &enumexW
.elfEnumLogfontEx
);
411 enumexW
.elfDesignVector
= penumexA
->elfDesignVector
;
412 return CreateFontIndirectExW( &enumexW
);
415 /***********************************************************************
416 * CreateFontIndirectExW (GDI32.@)
418 HFONT WINAPI
CreateFontIndirectExW( const ENUMLOGFONTEXDVW
*penumex
)
424 if (!penumex
) return 0;
426 if (penumex
->elfEnumLogfontEx
.elfFullName
[0] ||
427 penumex
->elfEnumLogfontEx
.elfStyle
[0] ||
428 penumex
->elfEnumLogfontEx
.elfScript
[0])
430 FIXME("some fields ignored. fullname=%s, style=%s, script=%s\n",
431 debugstr_w(penumex
->elfEnumLogfontEx
.elfFullName
),
432 debugstr_w(penumex
->elfEnumLogfontEx
.elfStyle
),
433 debugstr_w(penumex
->elfEnumLogfontEx
.elfScript
));
436 plf
= &penumex
->elfEnumLogfontEx
.elfLogFont
;
437 if (!(fontPtr
= HeapAlloc( GetProcessHeap(), 0, sizeof(*fontPtr
) ))) return 0;
439 fontPtr
->logfont
= *plf
;
441 if (plf
->lfEscapement
!= plf
->lfOrientation
)
443 /* this should really depend on whether GM_ADVANCED is set */
444 fontPtr
->logfont
.lfOrientation
= fontPtr
->logfont
.lfEscapement
;
445 WARN("orientation angle %f set to "
446 "escapement angle %f for new font %p\n",
447 plf
->lfOrientation
/10., plf
->lfEscapement
/10., fontPtr
);
450 if (!(hFont
= alloc_gdi_handle( &fontPtr
->header
, OBJ_FONT
, &font_funcs
)))
452 HeapFree( GetProcessHeap(), 0, fontPtr
);
456 TRACE("(%d %d %d %d %x %d %x %d %d) %s %s %s %s => %p\n",
457 plf
->lfHeight
, plf
->lfWidth
,
458 plf
->lfEscapement
, plf
->lfOrientation
,
459 plf
->lfPitchAndFamily
,
460 plf
->lfOutPrecision
, plf
->lfClipPrecision
,
461 plf
->lfQuality
, plf
->lfCharSet
,
462 debugstr_w(plf
->lfFaceName
),
463 plf
->lfWeight
> 400 ? "Bold" : "",
464 plf
->lfItalic
? "Italic" : "",
465 plf
->lfUnderline
? "Underline" : "", hFont
);
470 /***********************************************************************
471 * CreateFontIndirectA (GDI32.@)
473 HFONT WINAPI
CreateFontIndirectA( const LOGFONTA
*plfA
)
479 FONT_LogFontAToW( plfA
, &lfW
);
480 return CreateFontIndirectW( &lfW
);
483 /***********************************************************************
484 * CreateFontIndirectW (GDI32.@)
486 HFONT WINAPI
CreateFontIndirectW( const LOGFONTW
*plf
)
488 ENUMLOGFONTEXDVW exdv
;
492 exdv
.elfEnumLogfontEx
.elfLogFont
= *plf
;
493 exdv
.elfEnumLogfontEx
.elfFullName
[0] = 0;
494 exdv
.elfEnumLogfontEx
.elfStyle
[0] = 0;
495 exdv
.elfEnumLogfontEx
.elfScript
[0] = 0;
496 return CreateFontIndirectExW( &exdv
);
499 /*************************************************************************
500 * CreateFontA (GDI32.@)
502 HFONT WINAPI
CreateFontA( INT height
, INT width
, INT esc
,
503 INT orient
, INT weight
, DWORD italic
,
504 DWORD underline
, DWORD strikeout
, DWORD charset
,
505 DWORD outpres
, DWORD clippres
, DWORD quality
,
506 DWORD pitch
, LPCSTR name
)
510 logfont
.lfHeight
= height
;
511 logfont
.lfWidth
= width
;
512 logfont
.lfEscapement
= esc
;
513 logfont
.lfOrientation
= orient
;
514 logfont
.lfWeight
= weight
;
515 logfont
.lfItalic
= italic
;
516 logfont
.lfUnderline
= underline
;
517 logfont
.lfStrikeOut
= strikeout
;
518 logfont
.lfCharSet
= charset
;
519 logfont
.lfOutPrecision
= outpres
;
520 logfont
.lfClipPrecision
= clippres
;
521 logfont
.lfQuality
= quality
;
522 logfont
.lfPitchAndFamily
= pitch
;
525 lstrcpynA(logfont
.lfFaceName
,name
,sizeof(logfont
.lfFaceName
));
527 logfont
.lfFaceName
[0] = '\0';
529 return CreateFontIndirectA( &logfont
);
532 /*************************************************************************
533 * CreateFontW (GDI32.@)
535 HFONT WINAPI
CreateFontW( INT height
, INT width
, INT esc
,
536 INT orient
, INT weight
, DWORD italic
,
537 DWORD underline
, DWORD strikeout
, DWORD charset
,
538 DWORD outpres
, DWORD clippres
, DWORD quality
,
539 DWORD pitch
, LPCWSTR name
)
543 logfont
.lfHeight
= height
;
544 logfont
.lfWidth
= width
;
545 logfont
.lfEscapement
= esc
;
546 logfont
.lfOrientation
= orient
;
547 logfont
.lfWeight
= weight
;
548 logfont
.lfItalic
= italic
;
549 logfont
.lfUnderline
= underline
;
550 logfont
.lfStrikeOut
= strikeout
;
551 logfont
.lfCharSet
= charset
;
552 logfont
.lfOutPrecision
= outpres
;
553 logfont
.lfClipPrecision
= clippres
;
554 logfont
.lfQuality
= quality
;
555 logfont
.lfPitchAndFamily
= pitch
;
558 lstrcpynW(logfont
.lfFaceName
, name
,
559 sizeof(logfont
.lfFaceName
) / sizeof(WCHAR
));
561 logfont
.lfFaceName
[0] = '\0';
563 return CreateFontIndirectW( &logfont
);
566 static void update_font_code_page( DC
*dc
)
569 int charset
= GetTextCharsetInfo( dc
->hSelf
, NULL
, 0 );
571 /* Hmm, nicely designed api this one! */
572 if (TranslateCharsetInfo( ULongToPtr(charset
), &csi
, TCI_SRCCHARSET
) )
573 dc
->font_code_page
= csi
.ciACP
;
577 dc
->font_code_page
= GetOEMCP();
579 case DEFAULT_CHARSET
:
580 dc
->font_code_page
= GetACP();
590 /* FIXME: These have no place here, but because x11drv
591 enumerates fonts with these (made up) charsets some apps
592 might use them and then the FIXME below would become
593 annoying. Now we could pick the intended codepage for
594 each of these, but since it's broken anyway we'll just
595 use CP_ACP and hope it'll go away...
597 dc
->font_code_page
= CP_ACP
;
601 FIXME("Can't find codepage for charset %d\n", charset
);
602 dc
->font_code_page
= CP_ACP
;
607 TRACE("charset %d => cp %d\n", charset
, dc
->font_code_page
);
610 /***********************************************************************
613 static HGDIOBJ
FONT_SelectObject( HGDIOBJ handle
, HDC hdc
)
616 DC
*dc
= get_dc_ptr( hdc
);
621 if (!GDI_inc_ref_count( handle
))
623 release_dc_ptr( dc
);
627 physdev
= GET_DC_PHYSDEV( dc
, pSelectFont
);
628 if (physdev
->funcs
->pSelectFont( physdev
, handle
))
632 update_font_code_page( dc
);
633 GDI_dec_ref_count( ret
);
635 else GDI_dec_ref_count( handle
);
637 release_dc_ptr( dc
);
642 /***********************************************************************
645 static INT
FONT_GetObjectA( HGDIOBJ handle
, INT count
, LPVOID buffer
)
647 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
653 FONT_LogFontWToA( &font
->logfont
, &lfA
);
654 if (count
> sizeof(lfA
)) count
= sizeof(lfA
);
655 memcpy( buffer
, &lfA
, count
);
657 else count
= sizeof(lfA
);
658 GDI_ReleaseObj( handle
);
662 /***********************************************************************
665 static INT
FONT_GetObjectW( HGDIOBJ handle
, INT count
, LPVOID buffer
)
667 FONTOBJ
*font
= GDI_GetObjPtr( handle
, OBJ_FONT
);
672 if (count
> sizeof(LOGFONTW
)) count
= sizeof(LOGFONTW
);
673 memcpy( buffer
, &font
->logfont
, count
);
675 else count
= sizeof(LOGFONTW
);
676 GDI_ReleaseObj( handle
);
681 /***********************************************************************
684 static BOOL
FONT_DeleteObject( HGDIOBJ handle
)
688 WineEngDestroyFontInstance( handle
);
690 if (!(obj
= free_gdi_handle( handle
))) return FALSE
;
691 return HeapFree( GetProcessHeap(), 0, obj
);
695 /***********************************************************************
698 * Note: plf is really an ENUMLOGFONTEXW, and ptm is a NEWTEXTMETRICEXW.
699 * We have to use other types because of the FONTENUMPROCW definition.
701 static INT CALLBACK
FONT_EnumInstance( const LOGFONTW
*plf
, const TEXTMETRICW
*ptm
,
702 DWORD fType
, LPARAM lp
)
704 struct font_enum
*pfe
= (struct font_enum
*)lp
;
707 /* lfCharSet is at the same offset in both LOGFONTA and LOGFONTW */
708 if ((!pfe
->lpLogFontParam
||
709 pfe
->lpLogFontParam
->lfCharSet
== DEFAULT_CHARSET
||
710 pfe
->lpLogFontParam
->lfCharSet
== plf
->lfCharSet
) &&
711 (!(fType
& RASTER_FONTTYPE
) || GetDeviceCaps(pfe
->hdc
, TEXTCAPS
) & TC_RA_ABLE
) )
713 /* convert font metrics */
714 ENUMLOGFONTEXA logfont
;
715 NEWTEXTMETRICEXA tmA
;
719 FONT_EnumLogFontExWToA( (const ENUMLOGFONTEXW
*)plf
, &logfont
);
720 FONT_NewTextMetricExWToA( (const NEWTEXTMETRICEXW
*)ptm
, &tmA
);
721 plf
= (LOGFONTW
*)&logfont
.elfLogFont
;
722 ptm
= (TEXTMETRICW
*)&tmA
;
724 ret
= pfe
->lpEnumFunc( plf
, ptm
, fType
, pfe
->lpData
);
730 /***********************************************************************
731 * FONT_EnumFontFamiliesEx
733 static INT
FONT_EnumFontFamiliesEx( HDC hDC
, LPLOGFONTW plf
, FONTENUMPROCW efproc
,
734 LPARAM lParam
, BOOL unicode
)
737 DC
*dc
= get_dc_ptr( hDC
);
742 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pEnumFonts
);
744 if (plf
) TRACE("lfFaceName = %s lfCharset = %d\n", debugstr_w(plf
->lfFaceName
), plf
->lfCharSet
);
745 fe
.lpLogFontParam
= plf
;
746 fe
.lpEnumFunc
= efproc
;
748 fe
.unicode
= unicode
;
751 ret
= physdev
->funcs
->pEnumFonts( physdev
, plf
, FONT_EnumInstance
, (LPARAM
)&fe
);
752 release_dc_ptr( dc
);
754 return ret
? fe
.retval
: 0;
757 /***********************************************************************
758 * EnumFontFamiliesExW (GDI32.@)
760 INT WINAPI
EnumFontFamiliesExW( HDC hDC
, LPLOGFONTW plf
,
761 FONTENUMPROCW efproc
,
762 LPARAM lParam
, DWORD dwFlags
)
764 return FONT_EnumFontFamiliesEx( hDC
, plf
, efproc
, lParam
, TRUE
);
767 /***********************************************************************
768 * EnumFontFamiliesExA (GDI32.@)
770 INT WINAPI
EnumFontFamiliesExA( HDC hDC
, LPLOGFONTA plf
,
771 FONTENUMPROCA efproc
,
772 LPARAM lParam
, DWORD dwFlags
)
778 FONT_LogFontAToW( plf
, &lfW
);
783 return FONT_EnumFontFamiliesEx( hDC
, plfW
, (FONTENUMPROCW
)efproc
, lParam
, FALSE
);
786 /***********************************************************************
787 * EnumFontFamiliesA (GDI32.@)
789 INT WINAPI
EnumFontFamiliesA( HDC hDC
, LPCSTR lpFamily
,
790 FONTENUMPROCA efproc
, LPARAM lpData
)
796 if (!*lpFamily
) return 1;
797 lstrcpynA( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
798 lf
.lfCharSet
= DEFAULT_CHARSET
;
799 lf
.lfPitchAndFamily
= 0;
804 return EnumFontFamiliesExA( hDC
, plf
, efproc
, lpData
, 0 );
807 /***********************************************************************
808 * EnumFontFamiliesW (GDI32.@)
810 INT WINAPI
EnumFontFamiliesW( HDC hDC
, LPCWSTR lpFamily
,
811 FONTENUMPROCW efproc
, LPARAM lpData
)
817 if (!*lpFamily
) return 1;
818 lstrcpynW( lf
.lfFaceName
, lpFamily
, LF_FACESIZE
);
819 lf
.lfCharSet
= DEFAULT_CHARSET
;
820 lf
.lfPitchAndFamily
= 0;
825 return EnumFontFamiliesExW( hDC
, plf
, efproc
, lpData
, 0 );
828 /***********************************************************************
829 * EnumFontsA (GDI32.@)
831 INT WINAPI
EnumFontsA( HDC hDC
, LPCSTR lpName
, FONTENUMPROCA efproc
,
834 return EnumFontFamiliesA( hDC
, lpName
, efproc
, lpData
);
837 /***********************************************************************
838 * EnumFontsW (GDI32.@)
840 INT WINAPI
EnumFontsW( HDC hDC
, LPCWSTR lpName
, FONTENUMPROCW efproc
,
843 return EnumFontFamiliesW( hDC
, lpName
, efproc
, lpData
);
847 /***********************************************************************
848 * GetTextCharacterExtra (GDI32.@)
850 INT WINAPI
GetTextCharacterExtra( HDC hdc
)
853 DC
*dc
= get_dc_ptr( hdc
);
854 if (!dc
) return 0x80000000;
856 release_dc_ptr( dc
);
861 /***********************************************************************
862 * SetTextCharacterExtra (GDI32.@)
864 INT WINAPI
SetTextCharacterExtra( HDC hdc
, INT extra
)
866 INT ret
= 0x80000000;
867 DC
* dc
= get_dc_ptr( hdc
);
871 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetTextCharacterExtra
);
872 extra
= physdev
->funcs
->pSetTextCharacterExtra( physdev
, extra
);
873 if (extra
!= 0x80000000)
876 dc
->charExtra
= extra
;
878 release_dc_ptr( dc
);
884 /***********************************************************************
885 * SetTextJustification (GDI32.@)
887 BOOL WINAPI
SetTextJustification( HDC hdc
, INT extra
, INT breaks
)
891 DC
* dc
= get_dc_ptr( hdc
);
893 if (!dc
) return FALSE
;
895 physdev
= GET_DC_PHYSDEV( dc
, pSetTextJustification
);
896 ret
= physdev
->funcs
->pSetTextJustification( physdev
, extra
, breaks
);
899 extra
= abs((extra
* dc
->vportExtX
+ dc
->wndExtX
/ 2) / dc
->wndExtX
);
900 if (!extra
) breaks
= 0;
903 dc
->breakExtra
= extra
/ breaks
;
904 dc
->breakRem
= extra
- (breaks
* dc
->breakExtra
);
912 release_dc_ptr( dc
);
917 /***********************************************************************
918 * GetTextFaceA (GDI32.@)
920 INT WINAPI
GetTextFaceA( HDC hdc
, INT count
, LPSTR name
)
922 INT res
= GetTextFaceW(hdc
, 0, NULL
);
923 LPWSTR nameW
= HeapAlloc( GetProcessHeap(), 0, res
* 2 );
924 GetTextFaceW( hdc
, res
, nameW
);
930 res
= WideCharToMultiByte(CP_ACP
, 0, nameW
, -1, name
, count
, NULL
, NULL
);
934 /* GetTextFaceA does NOT include the nul byte in the return count. */
941 res
= WideCharToMultiByte( CP_ACP
, 0, nameW
, -1, NULL
, 0, NULL
, NULL
);
942 HeapFree( GetProcessHeap(), 0, nameW
);
946 /***********************************************************************
947 * GetTextFaceW (GDI32.@)
949 INT WINAPI
GetTextFaceW( HDC hdc
, INT count
, LPWSTR name
)
954 DC
* dc
= get_dc_ptr( hdc
);
957 dev
= GET_DC_PHYSDEV( dc
, pGetTextFace
);
958 ret
= dev
->funcs
->pGetTextFace( dev
, count
, name
);
959 release_dc_ptr( dc
);
964 /***********************************************************************
965 * GetTextExtentPoint32A (GDI32.@)
967 * See GetTextExtentPoint32W.
969 BOOL WINAPI
GetTextExtentPoint32A( HDC hdc
, LPCSTR str
, INT count
,
976 if (count
< 0) return FALSE
;
978 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
982 ret
= GetTextExtentPoint32W( hdc
, p
, wlen
, size
);
983 HeapFree( GetProcessHeap(), 0, p
);
986 TRACE("(%p %s %d %p): returning %d x %d\n",
987 hdc
, debugstr_an (str
, count
), count
, size
, size
->cx
, size
->cy
);
992 /***********************************************************************
993 * GetTextExtentPoint32W [GDI32.@]
995 * Computes width/height for a string.
997 * Computes width and height of the specified string.
1003 BOOL WINAPI
GetTextExtentPoint32W(
1004 HDC hdc
, /* [in] Handle of device context */
1005 LPCWSTR str
, /* [in] Address of text string */
1006 INT count
, /* [in] Number of characters in string */
1007 LPSIZE size
) /* [out] Address of structure for string size */
1009 return GetTextExtentExPointW(hdc
, str
, count
, 0, NULL
, NULL
, size
);
1012 /***********************************************************************
1013 * GetTextExtentExPointI [GDI32.@]
1015 * Computes width and height of the array of glyph indices.
1018 * hdc [I] Handle of device context.
1019 * indices [I] Glyph index array.
1020 * count [I] Number of glyphs in array.
1021 * max_ext [I] Maximum width in glyphs.
1022 * nfit [O] Maximum number of characters.
1023 * dxs [O] Partial string widths.
1024 * size [O] Returned string size.
1030 BOOL WINAPI
GetTextExtentExPointI( HDC hdc
, const WORD
*indices
, INT count
, INT max_ext
,
1031 LPINT nfit
, LPINT dxs
, LPSIZE size
)
1037 if (count
< 0) return FALSE
;
1039 dc
= get_dc_ptr( hdc
);
1040 if (!dc
) return FALSE
;
1042 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPointI
);
1043 ret
= dev
->funcs
->pGetTextExtentExPointI( dev
, indices
, count
, max_ext
, nfit
, dxs
, size
);
1044 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1045 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1046 size
->cx
+= count
* dc
->charExtra
;
1047 release_dc_ptr( dc
);
1049 TRACE("(%p %p %d %p): returning %d x %d\n",
1050 hdc
, indices
, count
, size
, size
->cx
, size
->cy
);
1054 /***********************************************************************
1055 * GetTextExtentPointI [GDI32.@]
1057 * Computes width and height of the array of glyph indices.
1060 * hdc [I] Handle of device context.
1061 * indices [I] Glyph index array.
1062 * count [I] Number of glyphs in array.
1063 * size [O] Returned string size.
1069 BOOL WINAPI
GetTextExtentPointI( HDC hdc
, const WORD
*indices
, INT count
, LPSIZE size
)
1071 return GetTextExtentExPointI( hdc
, indices
, count
, 0, NULL
, NULL
, size
);
1075 /***********************************************************************
1076 * GetTextExtentPointA (GDI32.@)
1078 BOOL WINAPI
GetTextExtentPointA( HDC hdc
, LPCSTR str
, INT count
,
1081 TRACE("not bug compatible.\n");
1082 return GetTextExtentPoint32A( hdc
, str
, count
, size
);
1085 /***********************************************************************
1086 * GetTextExtentPointW (GDI32.@)
1088 BOOL WINAPI
GetTextExtentPointW( HDC hdc
, LPCWSTR str
, INT count
,
1091 TRACE("not bug compatible.\n");
1092 return GetTextExtentPoint32W( hdc
, str
, count
, size
);
1096 /***********************************************************************
1097 * GetTextExtentExPointA (GDI32.@)
1099 BOOL WINAPI
GetTextExtentExPointA( HDC hdc
, LPCSTR str
, INT count
,
1100 INT maxExt
, LPINT lpnFit
,
1101 LPINT alpDx
, LPSIZE size
)
1108 if (count
< 0) return FALSE
;
1112 walpDx
= HeapAlloc( GetProcessHeap(), 0, count
* sizeof(INT
) );
1113 if (!walpDx
) return FALSE
;
1116 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, NULL
);
1117 ret
= GetTextExtentExPointW( hdc
, p
, wlen
, maxExt
, lpnFit
, walpDx
, size
);
1120 INT n
= lpnFit
? *lpnFit
: wlen
;
1122 for(i
= 0, j
= 0; i
< n
; i
++, j
++)
1124 alpDx
[j
] = walpDx
[i
];
1125 if (IsDBCSLeadByte(str
[j
])) alpDx
[++j
] = walpDx
[i
];
1128 if (lpnFit
) *lpnFit
= WideCharToMultiByte(CP_ACP
,0,p
,*lpnFit
,NULL
,0,NULL
,NULL
);
1129 HeapFree( GetProcessHeap(), 0, p
);
1130 HeapFree( GetProcessHeap(), 0, walpDx
);
1135 /***********************************************************************
1136 * GetTextExtentExPointW (GDI32.@)
1138 * Return the size of the string as it would be if it was output properly by
1141 * This should include
1142 * - Intercharacter spacing
1143 * - justification spacing (not yet done)
1144 * - kerning? see below
1146 * Kerning. Since kerning would be carried out by the rendering code it should
1147 * be done by the driver. However they don't support it yet. Also I am not
1148 * yet persuaded that (certainly under Win95) any kerning is actually done.
1150 * str: According to MSDN this should be null-terminated. That is not true; a
1151 * null will not terminate it early.
1152 * size: Certainly under Win95 this appears buggy or weird if *lpnFit is less
1153 * than count. I have seen it be either the size of the full string or
1154 * 1 less than the size of the full string. I have not seen it bear any
1155 * resemblance to the portion that would fit.
1156 * lpnFit: What exactly is fitting? Stupidly, in my opinion, it includes the
1157 * trailing intercharacter spacing and any trailing justification.
1160 * Currently we do this by measuring each character etc. We should do it by
1161 * passing the request to the driver, perhaps by extending the
1162 * pGetTextExtentPoint function to take the alpDx argument. That would avoid
1163 * thinking about kerning issues and rounding issues in the justification.
1166 BOOL WINAPI
GetTextExtentExPointW( HDC hdc
, LPCWSTR str
, INT count
,
1167 INT maxExt
, LPINT lpnFit
,
1168 LPINT alpDx
, LPSIZE size
)
1177 TRACE("(%p, %s, %d)\n",hdc
,debugstr_wn(str
,count
),maxExt
);
1179 if (count
< 0) return FALSE
;
1181 dc
= get_dc_ptr(hdc
);
1182 if (!dc
) return FALSE
;
1184 GetTextMetricsW(hdc
, &tm
);
1186 /* If we need to calculate nFit, then we need the partial extents even if
1187 the user hasn't provided us with an array. */
1190 dxs
= alpDx
? alpDx
: HeapAlloc(GetProcessHeap(), 0, count
* sizeof alpDx
[0]);
1194 SetLastError(ERROR_OUTOFMEMORY
);
1201 dev
= GET_DC_PHYSDEV( dc
, pGetTextExtentExPoint
);
1202 ret
= dev
->funcs
->pGetTextExtentExPoint(dev
, str
, count
, 0, NULL
, dxs
, size
);
1204 /* Perform device size to world size transformations. */
1207 INT extra
= dc
->charExtra
,
1208 breakExtra
= dc
->breakExtra
,
1209 breakRem
= dc
->breakRem
,
1214 for (i
= 0; i
< count
; ++i
)
1216 dxs
[i
] = abs(INTERNAL_XDSTOWS(dc
, dxs
[i
]));
1217 dxs
[i
] += (i
+1) * extra
;
1218 if (count
> 1 && (breakExtra
|| breakRem
) && str
[i
] == tm
.tmBreakChar
)
1220 dxs
[i
] += breakExtra
;
1227 if (dxs
[i
] <= maxExt
)
1230 breakRem
= dc
->breakRem
;
1232 size
->cx
= abs(INTERNAL_XDSTOWS(dc
, size
->cx
));
1233 size
->cy
= abs(INTERNAL_YDSTOWS(dc
, size
->cy
));
1235 if (!dxs
&& count
> 1 && (breakExtra
|| breakRem
))
1237 for (i
= 0; i
< count
; i
++)
1239 if (str
[i
] == tm
.tmBreakChar
)
1241 size
->cx
+= breakExtra
;
1256 HeapFree(GetProcessHeap(), 0, dxs
);
1258 release_dc_ptr( dc
);
1260 TRACE("returning %d %d x %d\n",nFit
,size
->cx
,size
->cy
);
1264 /***********************************************************************
1265 * GetTextMetricsA (GDI32.@)
1267 BOOL WINAPI
GetTextMetricsA( HDC hdc
, TEXTMETRICA
*metrics
)
1271 if (!GetTextMetricsW( hdc
, &tm32
)) return FALSE
;
1272 FONT_TextMetricWToA( &tm32
, metrics
);
1276 /***********************************************************************
1277 * GetTextMetricsW (GDI32.@)
1279 BOOL WINAPI
GetTextMetricsW( HDC hdc
, TEXTMETRICW
*metrics
)
1283 DC
* dc
= get_dc_ptr( hdc
);
1284 if (!dc
) return FALSE
;
1286 physdev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
1287 ret
= physdev
->funcs
->pGetTextMetrics( physdev
, metrics
);
1291 /* device layer returns values in device units
1292 * therefore we have to convert them to logical */
1294 metrics
->tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1295 metrics
->tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1297 #define WDPTOLP(x) ((x<0)? \
1298 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1299 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1300 #define HDPTOLP(y) ((y<0)? \
1301 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1302 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1304 metrics
->tmHeight
= HDPTOLP(metrics
->tmHeight
);
1305 metrics
->tmAscent
= HDPTOLP(metrics
->tmAscent
);
1306 metrics
->tmDescent
= HDPTOLP(metrics
->tmDescent
);
1307 metrics
->tmInternalLeading
= HDPTOLP(metrics
->tmInternalLeading
);
1308 metrics
->tmExternalLeading
= HDPTOLP(metrics
->tmExternalLeading
);
1309 metrics
->tmAveCharWidth
= WDPTOLP(metrics
->tmAveCharWidth
);
1310 metrics
->tmMaxCharWidth
= WDPTOLP(metrics
->tmMaxCharWidth
);
1311 metrics
->tmOverhang
= WDPTOLP(metrics
->tmOverhang
);
1315 TRACE("text metrics:\n"
1316 " Weight = %03i\t FirstChar = %i\t AveCharWidth = %i\n"
1317 " Italic = % 3i\t LastChar = %i\t\t MaxCharWidth = %i\n"
1318 " UnderLined = %01i\t DefaultChar = %i\t Overhang = %i\n"
1319 " StruckOut = %01i\t BreakChar = %i\t CharSet = %i\n"
1320 " PitchAndFamily = %02x\n"
1321 " --------------------\n"
1322 " InternalLeading = %i\n"
1326 metrics
->tmWeight
, metrics
->tmFirstChar
, metrics
->tmAveCharWidth
,
1327 metrics
->tmItalic
, metrics
->tmLastChar
, metrics
->tmMaxCharWidth
,
1328 metrics
->tmUnderlined
, metrics
->tmDefaultChar
, metrics
->tmOverhang
,
1329 metrics
->tmStruckOut
, metrics
->tmBreakChar
, metrics
->tmCharSet
,
1330 metrics
->tmPitchAndFamily
,
1331 metrics
->tmInternalLeading
,
1334 metrics
->tmHeight
);
1336 release_dc_ptr( dc
);
1341 /***********************************************************************
1342 * GetOutlineTextMetricsA (GDI32.@)
1343 * Gets metrics for TrueType fonts.
1346 * If the supplied buffer isn't big enough Windows partially fills it up to
1347 * its given length and returns that length.
1350 * Success: Non-zero or size of required buffer
1353 UINT WINAPI
GetOutlineTextMetricsA(
1354 HDC hdc
, /* [in] Handle of device context */
1355 UINT cbData
, /* [in] Size of metric data array */
1356 LPOUTLINETEXTMETRICA lpOTM
) /* [out] Address of metric data array */
1358 char buf
[512], *ptr
;
1360 OUTLINETEXTMETRICW
*lpOTMW
= (OUTLINETEXTMETRICW
*)buf
;
1361 OUTLINETEXTMETRICA
*output
= lpOTM
;
1364 if((ret
= GetOutlineTextMetricsW(hdc
, 0, NULL
)) == 0)
1366 if(ret
> sizeof(buf
))
1367 lpOTMW
= HeapAlloc(GetProcessHeap(), 0, ret
);
1368 GetOutlineTextMetricsW(hdc
, ret
, lpOTMW
);
1370 needed
= sizeof(OUTLINETEXTMETRICA
);
1371 if(lpOTMW
->otmpFamilyName
)
1372 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1373 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1374 NULL
, 0, NULL
, NULL
);
1375 if(lpOTMW
->otmpFaceName
)
1376 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1377 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1378 NULL
, 0, NULL
, NULL
);
1379 if(lpOTMW
->otmpStyleName
)
1380 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1381 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1382 NULL
, 0, NULL
, NULL
);
1383 if(lpOTMW
->otmpFullName
)
1384 needed
+= WideCharToMultiByte(CP_ACP
, 0,
1385 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1386 NULL
, 0, NULL
, NULL
);
1393 TRACE("needed = %d\n", needed
);
1395 /* Since the supplied buffer isn't big enough, we'll alloc one
1396 that is and memcpy the first cbData bytes into the lpOTM at
1398 output
= HeapAlloc(GetProcessHeap(), 0, needed
);
1400 ret
= output
->otmSize
= min(needed
, cbData
);
1401 FONT_TextMetricWToA( &lpOTMW
->otmTextMetrics
, &output
->otmTextMetrics
);
1402 output
->otmFiller
= 0;
1403 output
->otmPanoseNumber
= lpOTMW
->otmPanoseNumber
;
1404 output
->otmfsSelection
= lpOTMW
->otmfsSelection
;
1405 output
->otmfsType
= lpOTMW
->otmfsType
;
1406 output
->otmsCharSlopeRise
= lpOTMW
->otmsCharSlopeRise
;
1407 output
->otmsCharSlopeRun
= lpOTMW
->otmsCharSlopeRun
;
1408 output
->otmItalicAngle
= lpOTMW
->otmItalicAngle
;
1409 output
->otmEMSquare
= lpOTMW
->otmEMSquare
;
1410 output
->otmAscent
= lpOTMW
->otmAscent
;
1411 output
->otmDescent
= lpOTMW
->otmDescent
;
1412 output
->otmLineGap
= lpOTMW
->otmLineGap
;
1413 output
->otmsCapEmHeight
= lpOTMW
->otmsCapEmHeight
;
1414 output
->otmsXHeight
= lpOTMW
->otmsXHeight
;
1415 output
->otmrcFontBox
= lpOTMW
->otmrcFontBox
;
1416 output
->otmMacAscent
= lpOTMW
->otmMacAscent
;
1417 output
->otmMacDescent
= lpOTMW
->otmMacDescent
;
1418 output
->otmMacLineGap
= lpOTMW
->otmMacLineGap
;
1419 output
->otmusMinimumPPEM
= lpOTMW
->otmusMinimumPPEM
;
1420 output
->otmptSubscriptSize
= lpOTMW
->otmptSubscriptSize
;
1421 output
->otmptSubscriptOffset
= lpOTMW
->otmptSubscriptOffset
;
1422 output
->otmptSuperscriptSize
= lpOTMW
->otmptSuperscriptSize
;
1423 output
->otmptSuperscriptOffset
= lpOTMW
->otmptSuperscriptOffset
;
1424 output
->otmsStrikeoutSize
= lpOTMW
->otmsStrikeoutSize
;
1425 output
->otmsStrikeoutPosition
= lpOTMW
->otmsStrikeoutPosition
;
1426 output
->otmsUnderscoreSize
= lpOTMW
->otmsUnderscoreSize
;
1427 output
->otmsUnderscorePosition
= lpOTMW
->otmsUnderscorePosition
;
1430 ptr
= (char*)(output
+ 1);
1431 left
= needed
- sizeof(*output
);
1433 if(lpOTMW
->otmpFamilyName
) {
1434 output
->otmpFamilyName
= (LPSTR
)(ptr
- (char*)output
);
1435 len
= WideCharToMultiByte(CP_ACP
, 0,
1436 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFamilyName
), -1,
1437 ptr
, left
, NULL
, NULL
);
1441 output
->otmpFamilyName
= 0;
1443 if(lpOTMW
->otmpFaceName
) {
1444 output
->otmpFaceName
= (LPSTR
)(ptr
- (char*)output
);
1445 len
= WideCharToMultiByte(CP_ACP
, 0,
1446 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFaceName
), -1,
1447 ptr
, left
, NULL
, NULL
);
1451 output
->otmpFaceName
= 0;
1453 if(lpOTMW
->otmpStyleName
) {
1454 output
->otmpStyleName
= (LPSTR
)(ptr
- (char*)output
);
1455 len
= WideCharToMultiByte(CP_ACP
, 0,
1456 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpStyleName
), -1,
1457 ptr
, left
, NULL
, NULL
);
1461 output
->otmpStyleName
= 0;
1463 if(lpOTMW
->otmpFullName
) {
1464 output
->otmpFullName
= (LPSTR
)(ptr
- (char*)output
);
1465 len
= WideCharToMultiByte(CP_ACP
, 0,
1466 (WCHAR
*)((char*)lpOTMW
+ (ptrdiff_t)lpOTMW
->otmpFullName
), -1,
1467 ptr
, left
, NULL
, NULL
);
1470 output
->otmpFullName
= 0;
1474 if(output
!= lpOTM
) {
1475 memcpy(lpOTM
, output
, cbData
);
1476 HeapFree(GetProcessHeap(), 0, output
);
1478 /* check if the string offsets really fit into the provided size */
1479 /* FIXME: should we check string length as well? */
1480 /* make sure that we don't read/write beyond the provided buffer */
1481 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFamilyName
) + sizeof(LPSTR
))
1483 if ((UINT_PTR
)lpOTM
->otmpFamilyName
>= lpOTM
->otmSize
)
1484 lpOTM
->otmpFamilyName
= 0; /* doesn't fit */
1487 /* make sure that we don't read/write beyond the provided buffer */
1488 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFaceName
) + sizeof(LPSTR
))
1490 if ((UINT_PTR
)lpOTM
->otmpFaceName
>= lpOTM
->otmSize
)
1491 lpOTM
->otmpFaceName
= 0; /* doesn't fit */
1494 /* make sure that we don't read/write beyond the provided buffer */
1495 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpStyleName
) + sizeof(LPSTR
))
1497 if ((UINT_PTR
)lpOTM
->otmpStyleName
>= lpOTM
->otmSize
)
1498 lpOTM
->otmpStyleName
= 0; /* doesn't fit */
1501 /* make sure that we don't read/write beyond the provided buffer */
1502 if (lpOTM
->otmSize
>= FIELD_OFFSET(OUTLINETEXTMETRICA
, otmpFullName
) + sizeof(LPSTR
))
1504 if ((UINT_PTR
)lpOTM
->otmpFullName
>= lpOTM
->otmSize
)
1505 lpOTM
->otmpFullName
= 0; /* doesn't fit */
1510 if(lpOTMW
!= (OUTLINETEXTMETRICW
*)buf
)
1511 HeapFree(GetProcessHeap(), 0, lpOTMW
);
1517 /***********************************************************************
1518 * GetOutlineTextMetricsW [GDI32.@]
1520 UINT WINAPI
GetOutlineTextMetricsW(
1521 HDC hdc
, /* [in] Handle of device context */
1522 UINT cbData
, /* [in] Size of metric data array */
1523 LPOUTLINETEXTMETRICW lpOTM
) /* [out] Address of metric data array */
1525 DC
*dc
= get_dc_ptr( hdc
);
1526 OUTLINETEXTMETRICW
*output
= lpOTM
;
1530 TRACE("(%p,%d,%p)\n", hdc
, cbData
, lpOTM
);
1533 dev
= GET_DC_PHYSDEV( dc
, pGetOutlineTextMetrics
);
1534 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, cbData
, output
);
1536 if (lpOTM
&& ret
> cbData
)
1538 output
= HeapAlloc(GetProcessHeap(), 0, ret
);
1539 ret
= dev
->funcs
->pGetOutlineTextMetrics( dev
, ret
, output
);
1544 output
->otmTextMetrics
.tmDigitizedAspectX
= GetDeviceCaps(hdc
, LOGPIXELSX
);
1545 output
->otmTextMetrics
.tmDigitizedAspectY
= GetDeviceCaps(hdc
, LOGPIXELSY
);
1547 #define WDPTOLP(x) ((x<0)? \
1548 (-abs(INTERNAL_XDSTOWS(dc, (x)))): \
1549 (abs(INTERNAL_XDSTOWS(dc, (x)))))
1550 #define HDPTOLP(y) ((y<0)? \
1551 (-abs(INTERNAL_YDSTOWS(dc, (y)))): \
1552 (abs(INTERNAL_YDSTOWS(dc, (y)))))
1554 output
->otmTextMetrics
.tmHeight
= HDPTOLP(output
->otmTextMetrics
.tmHeight
);
1555 output
->otmTextMetrics
.tmAscent
= HDPTOLP(output
->otmTextMetrics
.tmAscent
);
1556 output
->otmTextMetrics
.tmDescent
= HDPTOLP(output
->otmTextMetrics
.tmDescent
);
1557 output
->otmTextMetrics
.tmInternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmInternalLeading
);
1558 output
->otmTextMetrics
.tmExternalLeading
= HDPTOLP(output
->otmTextMetrics
.tmExternalLeading
);
1559 output
->otmTextMetrics
.tmAveCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmAveCharWidth
);
1560 output
->otmTextMetrics
.tmMaxCharWidth
= WDPTOLP(output
->otmTextMetrics
.tmMaxCharWidth
);
1561 output
->otmTextMetrics
.tmOverhang
= WDPTOLP(output
->otmTextMetrics
.tmOverhang
);
1562 output
->otmAscent
= HDPTOLP(output
->otmAscent
);
1563 output
->otmDescent
= HDPTOLP(output
->otmDescent
);
1564 output
->otmLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmLineGap
));
1565 output
->otmsCapEmHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsCapEmHeight
));
1566 output
->otmsXHeight
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsXHeight
));
1567 output
->otmrcFontBox
.top
= HDPTOLP(output
->otmrcFontBox
.top
);
1568 output
->otmrcFontBox
.bottom
= HDPTOLP(output
->otmrcFontBox
.bottom
);
1569 output
->otmrcFontBox
.left
= WDPTOLP(output
->otmrcFontBox
.left
);
1570 output
->otmrcFontBox
.right
= WDPTOLP(output
->otmrcFontBox
.right
);
1571 output
->otmMacAscent
= HDPTOLP(output
->otmMacAscent
);
1572 output
->otmMacDescent
= HDPTOLP(output
->otmMacDescent
);
1573 output
->otmMacLineGap
= abs(INTERNAL_YDSTOWS(dc
,output
->otmMacLineGap
));
1574 output
->otmptSubscriptSize
.x
= WDPTOLP(output
->otmptSubscriptSize
.x
);
1575 output
->otmptSubscriptSize
.y
= HDPTOLP(output
->otmptSubscriptSize
.y
);
1576 output
->otmptSubscriptOffset
.x
= WDPTOLP(output
->otmptSubscriptOffset
.x
);
1577 output
->otmptSubscriptOffset
.y
= HDPTOLP(output
->otmptSubscriptOffset
.y
);
1578 output
->otmptSuperscriptSize
.x
= WDPTOLP(output
->otmptSuperscriptSize
.x
);
1579 output
->otmptSuperscriptSize
.y
= HDPTOLP(output
->otmptSuperscriptSize
.y
);
1580 output
->otmptSuperscriptOffset
.x
= WDPTOLP(output
->otmptSuperscriptOffset
.x
);
1581 output
->otmptSuperscriptOffset
.y
= HDPTOLP(output
->otmptSuperscriptOffset
.y
);
1582 output
->otmsStrikeoutSize
= abs(INTERNAL_YDSTOWS(dc
,output
->otmsStrikeoutSize
));
1583 output
->otmsStrikeoutPosition
= HDPTOLP(output
->otmsStrikeoutPosition
);
1584 output
->otmsUnderscoreSize
= HDPTOLP(output
->otmsUnderscoreSize
);
1585 output
->otmsUnderscorePosition
= HDPTOLP(output
->otmsUnderscorePosition
);
1590 memcpy(lpOTM
, output
, cbData
);
1591 HeapFree(GetProcessHeap(), 0, output
);
1599 static LPSTR
FONT_GetCharsByRangeA(HDC hdc
, UINT firstChar
, UINT lastChar
, PINT pByteLen
)
1601 INT i
, count
= lastChar
- firstChar
+ 1;
1609 mbcp
= GdiGetCodePage(hdc
);
1617 if (lastChar
> 0xffff)
1619 if ((firstChar
^ lastChar
) > 0xff)
1623 if (lastChar
> 0xff)
1629 str
= HeapAlloc(GetProcessHeap(), 0, count
* 2 + 1);
1633 for(i
= 0, c
= firstChar
; c
<= lastChar
; i
++, c
++)
1637 str
[i
++] = (BYTE
)(c
>> 8);
1638 if (c
<= 0xff && IsDBCSLeadByteEx(mbcp
, c
))
1639 str
[i
] = 0x1f; /* FIXME: use default character */
1653 /***********************************************************************
1654 * GetCharWidthW (GDI32.@)
1655 * GetCharWidth32W (GDI32.@)
1657 BOOL WINAPI
GetCharWidth32W( HDC hdc
, UINT firstChar
, UINT lastChar
,
1663 DC
* dc
= get_dc_ptr( hdc
);
1665 if (!dc
) return FALSE
;
1667 dev
= GET_DC_PHYSDEV( dc
, pGetCharWidth
);
1668 ret
= dev
->funcs
->pGetCharWidth( dev
, firstChar
, lastChar
, buffer
);
1672 /* convert device units to logical */
1673 for( i
= firstChar
; i
<= lastChar
; i
++, buffer
++ )
1674 *buffer
= INTERNAL_XDSTOWS(dc
, *buffer
);
1676 release_dc_ptr( dc
);
1681 /***********************************************************************
1682 * GetCharWidthA (GDI32.@)
1683 * GetCharWidth32A (GDI32.@)
1685 BOOL WINAPI
GetCharWidth32A( HDC hdc
, UINT firstChar
, UINT lastChar
,
1693 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
1697 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
1699 for(i
= 0; i
< wlen
; i
++)
1701 if(!GetCharWidth32W(hdc
, wstr
[i
], wstr
[i
], buffer
))
1709 HeapFree(GetProcessHeap(), 0, str
);
1710 HeapFree(GetProcessHeap(), 0, wstr
);
1716 /* helper for nulldrv_ExtTextOut */
1717 static DWORD
get_glyph_bitmap( HDC hdc
, UINT index
, UINT aa_flags
,
1718 GLYPHMETRICS
*metrics
, struct gdi_image_bits
*image
)
1720 UINT ggo_flags
= aa_flags
| GGO_GLYPH_INDEX
;
1721 static const MAT2 identity
= { {0,1}, {0,0}, {0,0}, {0,1} };
1722 UINT indices
[3] = {0, 0, 0x20};
1729 for (i
= 0; i
< sizeof(indices
) / sizeof(indices
[0]); i
++)
1732 ret
= GetGlyphOutlineW( hdc
, index
, ggo_flags
, metrics
, 0, NULL
, &identity
);
1733 if (ret
!= GDI_ERROR
) break;
1736 if (ret
== GDI_ERROR
) return ERROR_NOT_FOUND
;
1737 if (!image
) return ERROR_SUCCESS
;
1741 if (!ret
) return ERROR_SUCCESS
; /* empty glyph */
1743 stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1744 size
= metrics
->gmBlackBoxY
* stride
;
1746 if (!(image
->ptr
= HeapAlloc( GetProcessHeap(), 0, size
))) return ERROR_OUTOFMEMORY
;
1747 image
->is_copy
= TRUE
;
1748 image
->free
= free_heap_bits
;
1750 ret
= GetGlyphOutlineW( hdc
, index
, ggo_flags
, metrics
, size
, image
->ptr
, &identity
);
1751 if (ret
== GDI_ERROR
)
1753 HeapFree( GetProcessHeap(), 0, image
->ptr
);
1754 return ERROR_NOT_FOUND
;
1756 return ERROR_SUCCESS
;
1759 /* helper for nulldrv_ExtTextOut */
1760 static RECT
get_total_extents( HDC hdc
, INT x
, INT y
, UINT flags
, UINT aa_flags
,
1761 LPCWSTR str
, UINT count
, const INT
*dx
)
1766 rect
.left
= rect
.top
= INT_MAX
;
1767 rect
.right
= rect
.bottom
= INT_MIN
;
1768 for (i
= 0; i
< count
; i
++)
1770 GLYPHMETRICS metrics
;
1772 if (get_glyph_bitmap( hdc
, (UINT
)str
[i
], aa_flags
, &metrics
, NULL
)) continue;
1774 rect
.left
= min( rect
.left
, x
+ metrics
.gmptGlyphOrigin
.x
);
1775 rect
.top
= min( rect
.top
, y
- metrics
.gmptGlyphOrigin
.y
);
1776 rect
.right
= max( rect
.right
, x
+ metrics
.gmptGlyphOrigin
.x
+ (int)metrics
.gmBlackBoxX
);
1777 rect
.bottom
= max( rect
.bottom
, y
- metrics
.gmptGlyphOrigin
.y
+ (int)metrics
.gmBlackBoxY
);
1781 if (flags
& ETO_PDY
)
1784 y
+= dx
[ i
* 2 + 1];
1790 x
+= metrics
.gmCellIncX
;
1791 y
+= metrics
.gmCellIncY
;
1797 /* helper for nulldrv_ExtTextOut */
1798 static void draw_glyph( HDC hdc
, INT origin_x
, INT origin_y
, const GLYPHMETRICS
*metrics
,
1799 const struct gdi_image_bits
*image
, const RECT
*clip
)
1801 static const BYTE masks
[8] = {0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01};
1802 UINT x
, y
, i
, count
;
1803 BYTE
*ptr
= image
->ptr
;
1804 int stride
= get_dib_stride( metrics
->gmBlackBoxX
, 1 );
1806 RECT rect
, clipped_rect
;
1808 rect
.left
= origin_x
+ metrics
->gmptGlyphOrigin
.x
;
1809 rect
.top
= origin_y
- metrics
->gmptGlyphOrigin
.y
;
1810 rect
.right
= rect
.left
+ metrics
->gmBlackBoxX
;
1811 rect
.bottom
= rect
.top
+ metrics
->gmBlackBoxY
;
1812 if (!clip
) clipped_rect
= rect
;
1813 else if (!intersect_rect( &clipped_rect
, &rect
, clip
)) return;
1815 pts
= HeapAlloc( GetProcessHeap(), 0,
1816 max(2,metrics
->gmBlackBoxX
) * metrics
->gmBlackBoxY
* sizeof(*pts
) );
1820 ptr
+= (clipped_rect
.top
- rect
.top
) * stride
;
1821 for (y
= clipped_rect
.top
; y
< clipped_rect
.bottom
; y
++, ptr
+= stride
)
1823 for (x
= clipped_rect
.left
- rect
.left
; x
< clipped_rect
.right
- rect
.left
; x
++)
1825 while (x
< clipped_rect
.right
- rect
.left
&& !(ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1826 pts
[count
].x
= rect
.left
+ x
;
1827 while (x
< clipped_rect
.right
- rect
.left
&& (ptr
[x
/ 8] & masks
[x
% 8])) x
++;
1828 pts
[count
+ 1].x
= rect
.left
+ x
;
1829 if (pts
[count
+ 1].x
> pts
[count
].x
)
1831 pts
[count
].y
= pts
[count
+ 1].y
= y
;
1836 DPtoLP( hdc
, pts
, count
);
1837 for (i
= 0; i
< count
; i
+= 2) Polyline( hdc
, pts
+ i
, 2 );
1838 HeapFree( GetProcessHeap(), 0, pts
);
1841 /***********************************************************************
1842 * nulldrv_ExtTextOut
1844 BOOL
nulldrv_ExtTextOut( PHYSDEV dev
, INT x
, INT y
, UINT flags
, const RECT
*rect
,
1845 LPCWSTR str
, UINT count
, const INT
*dx
)
1847 DC
*dc
= get_nulldrv_dc( dev
);
1853 if (flags
& ETO_OPAQUE
)
1856 HBRUSH brush
= CreateSolidBrush( GetNearestColor( dev
->hdc
, GetBkColor(dev
->hdc
) ));
1860 orig
= SelectObject( dev
->hdc
, brush
);
1861 DPtoLP( dev
->hdc
, (POINT
*)&rc
, 2 );
1862 PatBlt( dev
->hdc
, rc
.left
, rc
.top
, rc
.right
- rc
.left
, rc
.bottom
- rc
.top
, PATCOPY
);
1863 SelectObject( dev
->hdc
, orig
);
1864 DeleteObject( brush
);
1868 if (!count
) return TRUE
;
1870 aa_flags
= get_font_aa_flags( dev
->hdc
);
1872 if (aa_flags
!= GGO_BITMAP
)
1874 char buffer
[FIELD_OFFSET( BITMAPINFO
, bmiColors
[256] )];
1875 BITMAPINFO
*info
= (BITMAPINFO
*)buffer
;
1876 struct gdi_image_bits bits
;
1877 struct bitblt_coords src
, dst
;
1880 dst_dev
= GET_DC_PHYSDEV( dc
, pPutImage
);
1881 src
.visrect
= get_total_extents( dev
->hdc
, x
, y
, flags
, aa_flags
, str
, count
, dx
);
1882 if (flags
& ETO_CLIPPED
) intersect_rect( &src
.visrect
, &src
.visrect
, rect
);
1883 if (!clip_visrect( dc
, &src
.visrect
, &src
.visrect
)) return TRUE
;
1885 /* FIXME: check for ETO_OPAQUE and avoid GetImage */
1886 src
.x
= src
.visrect
.left
;
1887 src
.y
= src
.visrect
.top
;
1888 src
.width
= src
.visrect
.right
- src
.visrect
.left
;
1889 src
.height
= src
.visrect
.bottom
- src
.visrect
.top
;
1891 if ((flags
& ETO_OPAQUE
) && (src
.visrect
.left
>= rect
->left
) && (src
.visrect
.top
>= rect
->top
) &&
1892 (src
.visrect
.right
<= rect
->right
) && (src
.visrect
.bottom
<= rect
->bottom
))
1894 /* we can avoid the GetImage, just query the needed format */
1895 memset( &info
->bmiHeader
, 0, sizeof(info
->bmiHeader
) );
1896 info
->bmiHeader
.biSize
= sizeof(info
->bmiHeader
);
1897 info
->bmiHeader
.biWidth
= src
.width
;
1898 info
->bmiHeader
.biHeight
= -src
.height
;
1899 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, 0, info
, NULL
, NULL
, NULL
, 0 );
1900 if (!err
|| err
== ERROR_BAD_FORMAT
)
1902 /* make the source rectangle relative to the source bits */
1904 src
.visrect
.left
= src
.visrect
.top
= 0;
1905 src
.visrect
.right
= src
.width
;
1906 src
.visrect
.bottom
= src
.height
;
1908 bits
.ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1909 if (!bits
.ptr
) return ERROR_OUTOFMEMORY
;
1910 bits
.is_copy
= TRUE
;
1911 bits
.free
= free_heap_bits
;
1912 err
= ERROR_SUCCESS
;
1917 PHYSDEV src_dev
= GET_DC_PHYSDEV( dc
, pGetImage
);
1918 err
= src_dev
->funcs
->pGetImage( src_dev
, 0, info
, &bits
, &src
);
1919 if (!err
&& !bits
.is_copy
)
1921 void *ptr
= HeapAlloc( GetProcessHeap(), 0, get_dib_image_size( info
));
1924 if (bits
.free
) bits
.free( &bits
);
1925 return ERROR_OUTOFMEMORY
;
1927 memcpy( ptr
, bits
.ptr
, get_dib_image_size( info
));
1928 if (bits
.free
) bits
.free( &bits
);
1930 bits
.is_copy
= TRUE
;
1931 bits
.free
= free_heap_bits
;
1936 /* make x,y relative to the image bits */
1937 x
+= src
.visrect
.left
- dst
.visrect
.left
;
1938 y
+= src
.visrect
.top
- dst
.visrect
.top
;
1939 render_aa_text_bitmapinfo( dev
->hdc
, info
, &bits
, &src
, x
, y
, flags
,
1940 aa_flags
, str
, count
, dx
);
1941 err
= dst_dev
->funcs
->pPutImage( dst_dev
, 0, 0, info
, &bits
, &src
, &dst
, SRCCOPY
);
1942 if (bits
.free
) bits
.free( &bits
);
1947 pen
= CreatePen( PS_SOLID
, 1, GetTextColor(dev
->hdc
) );
1948 orig
= SelectObject( dev
->hdc
, pen
);
1950 for (i
= 0; i
< count
; i
++)
1952 GLYPHMETRICS metrics
;
1953 struct gdi_image_bits image
;
1955 err
= get_glyph_bitmap( dev
->hdc
, (UINT
)str
[i
], GGO_BITMAP
, &metrics
, &image
);
1958 if (image
.ptr
) draw_glyph( dev
->hdc
, x
, y
, &metrics
, &image
, (flags
& ETO_CLIPPED
) ? rect
: NULL
);
1959 if (image
.free
) image
.free( &image
);
1963 if (flags
& ETO_PDY
)
1966 y
+= dx
[ i
* 2 + 1];
1972 x
+= metrics
.gmCellIncX
;
1973 y
+= metrics
.gmCellIncY
;
1977 SelectObject( dev
->hdc
, orig
);
1978 DeleteObject( pen
);
1983 /***********************************************************************
1984 * ExtTextOutA (GDI32.@)
1988 BOOL WINAPI
ExtTextOutA( HDC hdc
, INT x
, INT y
, UINT flags
,
1989 const RECT
*lprect
, LPCSTR str
, UINT count
, const INT
*lpDx
)
1997 if (flags
& ETO_GLYPH_INDEX
)
1998 return ExtTextOutW( hdc
, x
, y
, flags
, lprect
, (LPCWSTR
)str
, count
, lpDx
);
2000 p
= FONT_mbtowc(hdc
, str
, count
, &wlen
, &codepage
);
2003 unsigned int i
= 0, j
= 0;
2005 /* allocate enough for a ETO_PDY */
2006 lpDxW
= HeapAlloc( GetProcessHeap(), 0, 2*wlen
*sizeof(INT
));
2008 if(IsDBCSLeadByteEx(codepage
, str
[i
]))
2012 lpDxW
[j
++] = lpDx
[i
* 2] + lpDx
[(i
+ 1) * 2];
2013 lpDxW
[j
++] = lpDx
[i
* 2 + 1] + lpDx
[(i
+ 1) * 2 + 1];
2016 lpDxW
[j
++] = lpDx
[i
] + lpDx
[i
+ 1];
2023 lpDxW
[j
++] = lpDx
[i
* 2];
2024 lpDxW
[j
++] = lpDx
[i
* 2 + 1];
2027 lpDxW
[j
++] = lpDx
[i
];
2033 ret
= ExtTextOutW( hdc
, x
, y
, flags
, lprect
, p
, wlen
, lpDxW
);
2035 HeapFree( GetProcessHeap(), 0, p
);
2036 HeapFree( GetProcessHeap(), 0, lpDxW
);
2041 /***********************************************************************
2042 * ExtTextOutW (GDI32.@)
2044 * Draws text using the currently selected font, background color, and text color.
2048 * x,y [I] coordinates of string
2050 * ETO_GRAYED - undocumented on MSDN
2051 * ETO_OPAQUE - use background color for fill the rectangle
2052 * ETO_CLIPPED - clipping text to the rectangle
2053 * ETO_GLYPH_INDEX - Buffer is of glyph locations in fonts rather
2054 * than encoded characters. Implies ETO_IGNORELANGUAGE
2055 * ETO_RTLREADING - Paragraph is basically a right-to-left paragraph.
2056 * Affects BiDi ordering
2057 * ETO_IGNORELANGUAGE - Undocumented in MSDN - instructs ExtTextOut not to do BiDi reordering
2058 * ETO_PDY - unimplemented
2059 * ETO_NUMERICSLATIN - unimplemented always assumed -
2060 * do not translate numbers into locale representations
2061 * ETO_NUMERICSLOCAL - unimplemented - Numerals in Arabic/Farsi context should assume local form
2062 * lprect [I] dimensions for clipping or/and opaquing
2063 * str [I] text string
2064 * count [I] number of symbols in string
2065 * lpDx [I] optional parameter with distance between drawing characters
2071 BOOL WINAPI
ExtTextOutW( HDC hdc
, INT x
, INT y
, UINT flags
,
2072 const RECT
*lprect
, LPCWSTR str
, UINT count
, const INT
*lpDx
)
2075 LPWSTR reordered_str
= (LPWSTR
)str
;
2076 WORD
*glyphs
= NULL
;
2077 UINT align
= GetTextAlign( hdc
);
2078 DWORD layout
= GetLayout( hdc
);
2082 double cosEsc
, sinEsc
;
2086 BOOL done_extents
= FALSE
;
2087 POINT
*deltas
= NULL
, width
= {0, 0};
2089 DC
* dc
= get_dc_ptr( hdc
);
2092 static int quietfixme
= 0;
2094 if (!dc
) return FALSE
;
2096 breakRem
= dc
->breakRem
;
2098 if (quietfixme
== 0 && flags
& (ETO_NUMERICSLOCAL
| ETO_NUMERICSLATIN
))
2100 FIXME("flags ETO_NUMERICSLOCAL | ETO_NUMERICSLATIN unimplemented\n");
2105 physdev
= GET_DC_PHYSDEV( dc
, pExtTextOut
);
2106 type
= GetObjectType(hdc
);
2107 if(type
== OBJ_METADC
|| type
== OBJ_ENHMETADC
)
2109 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, flags
, lprect
, str
, count
, lpDx
);
2110 release_dc_ptr( dc
);
2115 flags
&= ~ETO_CLIPPED
;
2117 if (flags
& ETO_RTLREADING
) align
|= TA_RTLREADING
;
2118 if (layout
& LAYOUT_RTL
)
2120 if ((align
& TA_CENTER
) != TA_CENTER
) align
^= TA_RIGHT
;
2121 align
^= TA_RTLREADING
;
2124 if( !(flags
& (ETO_GLYPH_INDEX
| ETO_IGNORELANGUAGE
)) && count
> 0 )
2127 reordered_str
= HeapAlloc(GetProcessHeap(), 0, count
*sizeof(WCHAR
));
2129 BIDI_Reorder( hdc
, str
, count
, GCP_REORDER
,
2130 (align
& TA_RTLREADING
) ? WINE_GCPW_FORCE_RTL
: WINE_GCPW_FORCE_LTR
,
2131 reordered_str
, count
, NULL
, &glyphs
, &cGlyphs
);
2133 flags
|= ETO_IGNORELANGUAGE
;
2136 flags
|= ETO_GLYPH_INDEX
;
2137 if (cGlyphs
!= count
)
2141 else if(flags
& ETO_GLYPH_INDEX
)
2142 glyphs
= reordered_str
;
2144 TRACE("%p, %d, %d, %08x, %s, %s, %d, %p)\n", hdc
, x
, y
, flags
,
2145 wine_dbgstr_rect(lprect
), debugstr_wn(str
, count
), count
, lpDx
);
2146 TRACE("align = %x bkmode = %x mapmode = %x\n", align
, GetBkMode(hdc
), GetMapMode(hdc
));
2148 if(align
& TA_UPDATECP
)
2150 GetCurrentPositionEx( hdc
, &pt
);
2155 GetTextMetricsW(hdc
, &tm
);
2156 GetObjectW(GetCurrentObject(hdc
, OBJ_FONT
), sizeof(lf
), &lf
);
2158 if(!(tm
.tmPitchAndFamily
& TMPF_VECTOR
)) /* Non-scalable fonts shouldn't be rotated */
2159 lf
.lfEscapement
= 0;
2161 if ((dc
->GraphicsMode
== GM_COMPATIBLE
) &&
2162 (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
* dc
->xformWorld2Vport
.eM22
< 0))
2164 lf
.lfEscapement
= -lf
.lfEscapement
;
2167 if(lf
.lfEscapement
!= 0)
2169 cosEsc
= cos(lf
.lfEscapement
* M_PI
/ 1800);
2170 sinEsc
= sin(lf
.lfEscapement
* M_PI
/ 1800);
2178 if(flags
& (ETO_CLIPPED
| ETO_OPAQUE
))
2182 if(flags
& ETO_GLYPH_INDEX
)
2183 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2185 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2187 done_extents
= TRUE
;
2190 rc
.right
= x
+ sz
.cx
;
2191 rc
.bottom
= y
+ sz
.cy
;
2198 LPtoDP(hdc
, (POINT
*)&rc
, 2);
2200 if(rc
.left
> rc
.right
) {INT tmp
= rc
.left
; rc
.left
= rc
.right
; rc
.right
= tmp
;}
2201 if(rc
.top
> rc
.bottom
) {INT tmp
= rc
.top
; rc
.top
= rc
.bottom
; rc
.bottom
= tmp
;}
2204 if (lprect
&& (flags
& ETO_OPAQUE
))
2205 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &rc
, NULL
, 0, NULL
);
2215 LPtoDP(hdc
, &pt
, 1);
2219 char_extra
= GetTextCharacterExtra(hdc
);
2220 if(char_extra
|| dc
->breakExtra
|| breakRem
|| lpDx
|| lf
.lfEscapement
!= 0)
2224 POINT total
= {0, 0}, desired
[2];
2226 deltas
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2227 for(i
= 0; i
< count
; i
++)
2233 deltas
[i
].x
= lpDx
[i
* 2] + char_extra
;
2234 deltas
[i
].y
= -lpDx
[i
* 2 + 1];
2238 deltas
[i
].x
= lpDx
[i
] + char_extra
;
2245 if(flags
& ETO_GLYPH_INDEX
)
2246 GetTextExtentPointI(hdc
, glyphs
+ i
, 1, &tmpsz
);
2248 GetTextExtentPointW(hdc
, reordered_str
+ i
, 1, &tmpsz
);
2250 deltas
[i
].x
= tmpsz
.cx
;
2254 if (!(flags
& ETO_GLYPH_INDEX
) && (dc
->breakExtra
|| breakRem
) && reordered_str
[i
] == tm
.tmBreakChar
)
2256 deltas
[i
].x
= deltas
[i
].x
+ dc
->breakExtra
;
2263 total
.x
+= deltas
[i
].x
;
2264 total
.y
+= deltas
[i
].y
;
2266 desired
[0].x
= desired
[0].y
= 0;
2268 desired
[1].x
= cosEsc
* total
.x
+ sinEsc
* total
.y
;
2269 desired
[1].y
= -sinEsc
* total
.x
+ cosEsc
* total
.y
;
2271 LPtoDP(hdc
, desired
, 2);
2272 desired
[1].x
-= desired
[0].x
;
2273 desired
[1].y
-= desired
[0].y
;
2275 if (dc
->GraphicsMode
== GM_COMPATIBLE
)
2277 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM11
< 0)
2278 desired
[1].x
= -desired
[1].x
;
2279 if (dc
->vport2WorldValid
&& dc
->xformWorld2Vport
.eM22
< 0)
2280 desired
[1].y
= -desired
[1].y
;
2284 if (layout
& LAYOUT_RTL
) desired
[1].x
= -desired
[1].x
;
2287 deltas
[i
].x
= desired
[1].x
- width
.x
;
2288 deltas
[i
].y
= desired
[1].y
- width
.y
;
2298 if(flags
& ETO_GLYPH_INDEX
)
2299 GetTextExtentPointI(hdc
, glyphs
, count
, &sz
);
2301 GetTextExtentPointW(hdc
, reordered_str
, count
, &sz
);
2302 done_extents
= TRUE
;
2304 width
.x
= abs(INTERNAL_XWSTODS(dc
, sz
.cx
));
2308 tm
.tmAscent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmAscent
));
2309 tm
.tmDescent
= abs(INTERNAL_YWSTODS(dc
, tm
.tmDescent
));
2310 switch( align
& (TA_LEFT
| TA_RIGHT
| TA_CENTER
) )
2313 if (align
& TA_UPDATECP
)
2317 DPtoLP(hdc
, &pt
, 1);
2318 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2330 if (align
& TA_UPDATECP
)
2334 DPtoLP(hdc
, &pt
, 1);
2335 MoveToEx(hdc
, pt
.x
, pt
.y
, NULL
);
2340 switch( align
& (TA_TOP
| TA_BOTTOM
| TA_BASELINE
) )
2343 y
+= tm
.tmAscent
* cosEsc
;
2344 x
+= tm
.tmAscent
* sinEsc
;
2348 y
-= tm
.tmDescent
* cosEsc
;
2349 x
-= tm
.tmDescent
* sinEsc
;
2356 if (GetBkMode(hdc
) != TRANSPARENT
)
2358 if(!((flags
& ETO_CLIPPED
) && (flags
& ETO_OPAQUE
)))
2360 if(!(flags
& ETO_OPAQUE
) || !lprect
||
2361 x
< rc
.left
|| x
+ width
.x
>= rc
.right
||
2362 y
- tm
.tmAscent
< rc
.top
|| y
+ tm
.tmDescent
>= rc
.bottom
)
2366 text_box
.right
= x
+ width
.x
;
2367 text_box
.top
= y
- tm
.tmAscent
;
2368 text_box
.bottom
= y
+ tm
.tmDescent
;
2370 if (flags
& ETO_CLIPPED
) intersect_rect( &text_box
, &text_box
, &rc
);
2371 if (!is_rect_empty( &text_box
))
2372 physdev
->funcs
->pExtTextOut( physdev
, 0, 0, ETO_OPAQUE
, &text_box
, NULL
, 0, NULL
);
2377 if(FontIsLinked(hdc
) && !(flags
& ETO_GLYPH_INDEX
))
2379 HFONT orig_font
= dc
->hFont
, cur_font
;
2382 POINT
*offsets
= NULL
;
2385 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2386 for(i
= 0; i
< count
; i
++)
2388 WineEngGetLinkedHFont(dc
, reordered_str
[i
], &cur_font
, &glyph
);
2389 if(cur_font
!= dc
->hFont
)
2394 offsets
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(*deltas
));
2395 offsets
[0].x
= offsets
[0].y
= 0;
2400 for(j
= 1; j
< count
; j
++)
2402 GetTextExtentPointW(hdc
, reordered_str
+ j
- 1, 1, &tmpsz
);
2403 offsets
[j
].x
= offsets
[j
- 1].x
+ abs(INTERNAL_XWSTODS(dc
, tmpsz
.cx
));
2409 for(j
= 1; j
< count
; j
++)
2411 offsets
[j
].x
= offsets
[j
- 1].x
+ deltas
[j
].x
;
2412 offsets
[j
].y
= offsets
[j
- 1].y
+ deltas
[j
].y
;
2418 physdev
->funcs
->pExtTextOut( physdev
, x
+ offsets
[i
- span
].x
,
2419 y
+ offsets
[i
- span
].y
,
2420 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2421 span
, deltas
? (INT
*)(deltas
+ (i
- span
)) : NULL
);
2424 SelectObject(hdc
, cur_font
);
2426 glyphs
[span
++] = glyph
;
2430 ret
= physdev
->funcs
->pExtTextOut(physdev
, x
+ (offsets
? offsets
[count
- span
].x
: 0),
2431 y
+ (offsets
? offsets
[count
- span
].y
: 0),
2432 (flags
& ~ETO_OPAQUE
) | ETO_GLYPH_INDEX
, &rc
, glyphs
,
2433 span
, deltas
? (INT
*)(deltas
+ (count
- span
)) : NULL
);
2434 SelectObject(hdc
, orig_font
);
2435 HeapFree(GetProcessHeap(), 0, offsets
);
2441 if(!(flags
& ETO_GLYPH_INDEX
) && dc
->gdiFont
)
2443 glyphs
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(WORD
));
2444 GetGlyphIndicesW(hdc
, reordered_str
, count
, glyphs
, 0);
2445 flags
|= ETO_GLYPH_INDEX
;
2447 ret
= physdev
->funcs
->pExtTextOut( physdev
, x
, y
, (flags
& ~ETO_OPAQUE
), &rc
,
2448 glyphs
? glyphs
: reordered_str
, count
, (INT
*)deltas
);
2452 HeapFree(GetProcessHeap(), 0, deltas
);
2453 if(glyphs
!= reordered_str
)
2454 HeapFree(GetProcessHeap(), 0, glyphs
);
2455 if(reordered_str
!= str
)
2456 HeapFree(GetProcessHeap(), 0, reordered_str
);
2458 release_dc_ptr( dc
);
2460 if (ret
&& (lf
.lfUnderline
|| lf
.lfStrikeOut
))
2462 int underlinePos
, strikeoutPos
;
2463 int underlineWidth
, strikeoutWidth
;
2464 UINT size
= GetOutlineTextMetricsW(hdc
, 0, NULL
);
2465 OUTLINETEXTMETRICW
* otm
= NULL
;
2467 HPEN hpen
= SelectObject(hdc
, GetStockObject(NULL_PEN
));
2468 HBRUSH hbrush
= CreateSolidBrush(GetTextColor(hdc
));
2470 hbrush
= SelectObject(hdc
, hbrush
);
2475 underlineWidth
= tm
.tmAscent
/ 20 + 1;
2476 strikeoutPos
= tm
.tmAscent
/ 2;
2477 strikeoutWidth
= underlineWidth
;
2481 otm
= HeapAlloc(GetProcessHeap(), 0, size
);
2482 GetOutlineTextMetricsW(hdc
, size
, otm
);
2483 underlinePos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscorePosition
));
2484 if (otm
->otmsUnderscorePosition
< 0) underlinePos
= -underlinePos
;
2485 underlineWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsUnderscoreSize
));
2486 if (otm
->otmsUnderscoreSize
< 0) underlineWidth
= -underlineWidth
;
2487 strikeoutPos
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutPosition
));
2488 if (otm
->otmsStrikeoutPosition
< 0) strikeoutPos
= -strikeoutPos
;
2489 strikeoutWidth
= abs( INTERNAL_YWSTODS( dc
, otm
->otmsStrikeoutSize
));
2490 HeapFree(GetProcessHeap(), 0, otm
);
2496 pts
[0].x
= x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2497 pts
[0].y
= y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2498 pts
[1].x
= x
+ width
.x
- (underlinePos
+ underlineWidth
/ 2) * sinEsc
;
2499 pts
[1].y
= y
+ width
.y
- (underlinePos
+ underlineWidth
/ 2) * cosEsc
;
2500 pts
[2].x
= pts
[1].x
+ underlineWidth
* sinEsc
;
2501 pts
[2].y
= pts
[1].y
+ underlineWidth
* cosEsc
;
2502 pts
[3].x
= pts
[0].x
+ underlineWidth
* sinEsc
;
2503 pts
[3].y
= pts
[0].y
+ underlineWidth
* cosEsc
;
2504 pts
[4].x
= pts
[0].x
;
2505 pts
[4].y
= pts
[0].y
;
2506 DPtoLP(hdc
, pts
, 5);
2507 Polygon(hdc
, pts
, 5);
2512 pts
[0].x
= x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2513 pts
[0].y
= y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2514 pts
[1].x
= x
+ width
.x
- (strikeoutPos
+ strikeoutWidth
/ 2) * sinEsc
;
2515 pts
[1].y
= y
+ width
.y
- (strikeoutPos
+ strikeoutWidth
/ 2) * cosEsc
;
2516 pts
[2].x
= pts
[1].x
+ strikeoutWidth
* sinEsc
;
2517 pts
[2].y
= pts
[1].y
+ strikeoutWidth
* cosEsc
;
2518 pts
[3].x
= pts
[0].x
+ strikeoutWidth
* sinEsc
;
2519 pts
[3].y
= pts
[0].y
+ strikeoutWidth
* cosEsc
;
2520 pts
[4].x
= pts
[0].x
;
2521 pts
[4].y
= pts
[0].y
;
2522 DPtoLP(hdc
, pts
, 5);
2523 Polygon(hdc
, pts
, 5);
2526 SelectObject(hdc
, hpen
);
2527 hbrush
= SelectObject(hdc
, hbrush
);
2528 DeleteObject(hbrush
);
2535 /***********************************************************************
2536 * TextOutA (GDI32.@)
2538 BOOL WINAPI
TextOutA( HDC hdc
, INT x
, INT y
, LPCSTR str
, INT count
)
2540 return ExtTextOutA( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2544 /***********************************************************************
2545 * TextOutW (GDI32.@)
2547 BOOL WINAPI
TextOutW(HDC hdc
, INT x
, INT y
, LPCWSTR str
, INT count
)
2549 return ExtTextOutW( hdc
, x
, y
, 0, NULL
, str
, count
, NULL
);
2553 /***********************************************************************
2554 * PolyTextOutA (GDI32.@)
2558 BOOL WINAPI
PolyTextOutA( HDC hdc
, const POLYTEXTA
*pptxt
, INT cStrings
)
2560 for (; cStrings
>0; cStrings
--, pptxt
++)
2561 if (!ExtTextOutA( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2568 /***********************************************************************
2569 * PolyTextOutW (GDI32.@)
2571 * Draw several Strings
2577 BOOL WINAPI
PolyTextOutW( HDC hdc
, const POLYTEXTW
*pptxt
, INT cStrings
)
2579 for (; cStrings
>0; cStrings
--, pptxt
++)
2580 if (!ExtTextOutW( hdc
, pptxt
->x
, pptxt
->y
, pptxt
->uiFlags
, &pptxt
->rcl
, pptxt
->lpstr
, pptxt
->n
, pptxt
->pdx
))
2586 /***********************************************************************
2587 * SetMapperFlags (GDI32.@)
2589 DWORD WINAPI
SetMapperFlags( HDC hdc
, DWORD flags
)
2591 DC
*dc
= get_dc_ptr( hdc
);
2592 DWORD ret
= GDI_ERROR
;
2596 PHYSDEV physdev
= GET_DC_PHYSDEV( dc
, pSetMapperFlags
);
2597 flags
= physdev
->funcs
->pSetMapperFlags( physdev
, flags
);
2598 if (flags
!= GDI_ERROR
)
2600 ret
= dc
->mapperFlags
;
2601 dc
->mapperFlags
= flags
;
2603 release_dc_ptr( dc
);
2608 /***********************************************************************
2609 * GetAspectRatioFilterEx (GDI32.@)
2611 BOOL WINAPI
GetAspectRatioFilterEx( HDC hdc
, LPSIZE pAspectRatio
)
2613 FIXME("(%p, %p): -- Empty Stub !\n", hdc
, pAspectRatio
);
2618 /***********************************************************************
2619 * GetCharABCWidthsA (GDI32.@)
2621 * See GetCharABCWidthsW.
2623 BOOL WINAPI
GetCharABCWidthsA(HDC hdc
, UINT firstChar
, UINT lastChar
,
2631 str
= FONT_GetCharsByRangeA(hdc
, firstChar
, lastChar
, &i
);
2635 wstr
= FONT_mbtowc(hdc
, str
, i
, &wlen
, NULL
);
2638 HeapFree(GetProcessHeap(), 0, str
);
2642 for(i
= 0; i
< wlen
; i
++)
2644 if(!GetCharABCWidthsW(hdc
, wstr
[i
], wstr
[i
], abc
))
2652 HeapFree(GetProcessHeap(), 0, str
);
2653 HeapFree(GetProcessHeap(), 0, wstr
);
2659 /******************************************************************************
2660 * GetCharABCWidthsW [GDI32.@]
2662 * Retrieves widths of characters in range.
2665 * hdc [I] Handle of device context
2666 * firstChar [I] First character in range to query
2667 * lastChar [I] Last character in range to query
2668 * abc [O] Address of character-width structure
2671 * Only works with TrueType fonts
2677 BOOL WINAPI
GetCharABCWidthsW( HDC hdc
, UINT firstChar
, UINT lastChar
,
2680 DC
*dc
= get_dc_ptr(hdc
);
2686 if (!dc
) return FALSE
;
2690 release_dc_ptr( dc
);
2694 /* unlike GetCharABCWidthsFloatW, this one is supposed to fail on non-TrueType fonts */
2695 dev
= GET_DC_PHYSDEV( dc
, pGetTextMetrics
);
2696 if (!dev
->funcs
->pGetTextMetrics( dev
, &tm
) || !(tm
.tmPitchAndFamily
& TMPF_TRUETYPE
))
2698 release_dc_ptr( dc
);
2702 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
2703 ret
= dev
->funcs
->pGetCharABCWidths( dev
, firstChar
, lastChar
, abc
);
2706 /* convert device units to logical */
2707 for( i
= firstChar
; i
<= lastChar
; i
++, abc
++ ) {
2708 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2709 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2710 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2714 release_dc_ptr( dc
);
2719 /******************************************************************************
2720 * GetCharABCWidthsI [GDI32.@]
2722 * Retrieves widths of characters in range.
2725 * hdc [I] Handle of device context
2726 * firstChar [I] First glyphs in range to query
2727 * count [I] Last glyphs in range to query
2728 * pgi [i] Array of glyphs to query
2729 * abc [O] Address of character-width structure
2732 * Only works with TrueType fonts
2738 BOOL WINAPI
GetCharABCWidthsI( HDC hdc
, UINT firstChar
, UINT count
,
2739 LPWORD pgi
, LPABC abc
)
2741 DC
*dc
= get_dc_ptr(hdc
);
2746 if (!dc
) return FALSE
;
2750 release_dc_ptr( dc
);
2754 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidthsI
);
2755 ret
= dev
->funcs
->pGetCharABCWidthsI( dev
, firstChar
, count
, pgi
, abc
);
2758 /* convert device units to logical */
2759 for( i
= 0; i
< count
; i
++, abc
++ ) {
2760 abc
->abcA
= INTERNAL_XDSTOWS(dc
, abc
->abcA
);
2761 abc
->abcB
= INTERNAL_XDSTOWS(dc
, abc
->abcB
);
2762 abc
->abcC
= INTERNAL_XDSTOWS(dc
, abc
->abcC
);
2766 release_dc_ptr( dc
);
2771 /***********************************************************************
2772 * GetGlyphOutlineA (GDI32.@)
2774 DWORD WINAPI
GetGlyphOutlineA( HDC hdc
, UINT uChar
, UINT fuFormat
,
2775 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2776 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2778 if (!lpmat2
) return GDI_ERROR
;
2780 if(!(fuFormat
& GGO_GLYPH_INDEX
)) {
2785 cp
= GdiGetCodePage(hdc
);
2786 if (IsDBCSLeadByteEx(cp
, uChar
>> 8)) {
2788 mbchs
[0] = (uChar
& 0xff00) >> 8;
2789 mbchs
[1] = (uChar
& 0xff);
2792 mbchs
[0] = (uChar
& 0xff);
2795 MultiByteToWideChar(cp
, 0, mbchs
, len
, (LPWSTR
)&uChar
, 1);
2798 return GetGlyphOutlineW(hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
,
2802 /***********************************************************************
2803 * GetGlyphOutlineW (GDI32.@)
2805 DWORD WINAPI
GetGlyphOutlineW( HDC hdc
, UINT uChar
, UINT fuFormat
,
2806 LPGLYPHMETRICS lpgm
, DWORD cbBuffer
,
2807 LPVOID lpBuffer
, const MAT2
*lpmat2
)
2813 TRACE("(%p, %04x, %04x, %p, %d, %p, %p)\n",
2814 hdc
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2816 if (!lpmat2
) return GDI_ERROR
;
2818 dc
= get_dc_ptr(hdc
);
2819 if(!dc
) return GDI_ERROR
;
2821 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphOutline
);
2822 ret
= dev
->funcs
->pGetGlyphOutline( dev
, uChar
, fuFormat
, lpgm
, cbBuffer
, lpBuffer
, lpmat2
);
2823 release_dc_ptr( dc
);
2828 /***********************************************************************
2829 * CreateScalableFontResourceA (GDI32.@)
2831 BOOL WINAPI
CreateScalableFontResourceA( DWORD fHidden
,
2832 LPCSTR lpszResourceFile
,
2833 LPCSTR lpszFontFile
,
2834 LPCSTR lpszCurrentPath
)
2836 LPWSTR lpszResourceFileW
= NULL
;
2837 LPWSTR lpszFontFileW
= NULL
;
2838 LPWSTR lpszCurrentPathW
= NULL
;
2842 if (lpszResourceFile
)
2844 len
= MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, NULL
, 0);
2845 lpszResourceFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2846 MultiByteToWideChar(CP_ACP
, 0, lpszResourceFile
, -1, lpszResourceFileW
, len
);
2851 len
= MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, NULL
, 0);
2852 lpszFontFileW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2853 MultiByteToWideChar(CP_ACP
, 0, lpszFontFile
, -1, lpszFontFileW
, len
);
2856 if (lpszCurrentPath
)
2858 len
= MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, NULL
, 0);
2859 lpszCurrentPathW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
2860 MultiByteToWideChar(CP_ACP
, 0, lpszCurrentPath
, -1, lpszCurrentPathW
, len
);
2863 ret
= CreateScalableFontResourceW(fHidden
, lpszResourceFileW
,
2864 lpszFontFileW
, lpszCurrentPathW
);
2866 HeapFree(GetProcessHeap(), 0, lpszResourceFileW
);
2867 HeapFree(GetProcessHeap(), 0, lpszFontFileW
);
2868 HeapFree(GetProcessHeap(), 0, lpszCurrentPathW
);
2873 /***********************************************************************
2874 * CreateScalableFontResourceW (GDI32.@)
2876 BOOL WINAPI
CreateScalableFontResourceW( DWORD fHidden
,
2877 LPCWSTR lpszResourceFile
,
2878 LPCWSTR lpszFontFile
,
2879 LPCWSTR lpszCurrentPath
)
2882 FIXME("(%d,%s,%s,%s): stub\n",
2883 fHidden
, debugstr_w(lpszResourceFile
), debugstr_w(lpszFontFile
),
2884 debugstr_w(lpszCurrentPath
) );
2886 /* fHidden=1 - only visible for the calling app, read-only, not
2887 * enumerated with EnumFonts/EnumFontFamilies
2888 * lpszCurrentPath can be NULL
2891 /* If the output file already exists, return the ERROR_FILE_EXISTS error as specified in MSDN */
2892 if ((f
= CreateFileW(lpszResourceFile
, 0, 0, NULL
, OPEN_EXISTING
, FILE_ATTRIBUTE_NORMAL
, 0)) != INVALID_HANDLE_VALUE
) {
2894 SetLastError(ERROR_FILE_EXISTS
);
2897 return FALSE
; /* create failed */
2900 /*************************************************************************
2901 * GetKerningPairsA (GDI32.@)
2903 DWORD WINAPI
GetKerningPairsA( HDC hDC
, DWORD cPairs
,
2904 LPKERNINGPAIR kern_pairA
)
2908 DWORD i
, total_kern_pairs
, kern_pairs_copied
= 0;
2909 KERNINGPAIR
*kern_pairW
;
2911 if (!cPairs
&& kern_pairA
)
2913 SetLastError(ERROR_INVALID_PARAMETER
);
2917 cp
= GdiGetCodePage(hDC
);
2919 /* GetCPInfo() will fail on CP_SYMBOL, and WideCharToMultiByte is supposed
2920 * to fail on an invalid character for CP_SYMBOL.
2922 cpi
.DefaultChar
[0] = 0;
2923 if (cp
!= CP_SYMBOL
&& !GetCPInfo(cp
, &cpi
))
2925 FIXME("Can't find codepage %u info\n", cp
);
2929 total_kern_pairs
= GetKerningPairsW(hDC
, 0, NULL
);
2930 if (!total_kern_pairs
) return 0;
2932 kern_pairW
= HeapAlloc(GetProcessHeap(), 0, total_kern_pairs
* sizeof(*kern_pairW
));
2933 GetKerningPairsW(hDC
, total_kern_pairs
, kern_pairW
);
2935 for (i
= 0; i
< total_kern_pairs
; i
++)
2939 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wFirst
, 1, &first
, 1, NULL
, NULL
))
2942 if (!WideCharToMultiByte(cp
, 0, &kern_pairW
[i
].wSecond
, 1, &second
, 1, NULL
, NULL
))
2945 if (first
== cpi
.DefaultChar
[0] || second
== cpi
.DefaultChar
[0])
2950 if (kern_pairs_copied
>= cPairs
) break;
2952 kern_pairA
->wFirst
= (BYTE
)first
;
2953 kern_pairA
->wSecond
= (BYTE
)second
;
2954 kern_pairA
->iKernAmount
= kern_pairW
[i
].iKernAmount
;
2957 kern_pairs_copied
++;
2960 HeapFree(GetProcessHeap(), 0, kern_pairW
);
2962 return kern_pairs_copied
;
2965 /*************************************************************************
2966 * GetKerningPairsW (GDI32.@)
2968 DWORD WINAPI
GetKerningPairsW( HDC hDC
, DWORD cPairs
,
2969 LPKERNINGPAIR lpKerningPairs
)
2975 TRACE("(%p,%d,%p)\n", hDC
, cPairs
, lpKerningPairs
);
2977 if (!cPairs
&& lpKerningPairs
)
2979 SetLastError(ERROR_INVALID_PARAMETER
);
2983 dc
= get_dc_ptr(hDC
);
2986 dev
= GET_DC_PHYSDEV( dc
, pGetKerningPairs
);
2987 ret
= dev
->funcs
->pGetKerningPairs( dev
, cPairs
, lpKerningPairs
);
2988 release_dc_ptr( dc
);
2992 /*************************************************************************
2993 * TranslateCharsetInfo [GDI32.@]
2995 * Fills a CHARSETINFO structure for a character set, code page, or
2996 * font. This allows making the correspondence between different labels
2997 * (character set, Windows, ANSI, and OEM codepages, and Unicode ranges)
2998 * of the same encoding.
3000 * Only one codepage will be set in lpCs->fs. If TCI_SRCFONTSIG is used,
3001 * only one codepage should be set in *lpSrc.
3004 * TRUE on success, FALSE on failure.
3007 BOOL WINAPI
TranslateCharsetInfo(
3008 LPDWORD lpSrc
, /* [in]
3009 if flags == TCI_SRCFONTSIG: pointer to fsCsb of a FONTSIGNATURE
3010 if flags == TCI_SRCCHARSET: a character set value
3011 if flags == TCI_SRCCODEPAGE: a code page value
3013 LPCHARSETINFO lpCs
, /* [out] structure to receive charset information */
3014 DWORD flags
/* [in] determines interpretation of lpSrc */)
3018 case TCI_SRCFONTSIG
:
3019 while (index
< MAXTCIINDEX
&& !(*lpSrc
>>index
& 0x0001)) index
++;
3021 case TCI_SRCCODEPAGE
:
3022 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciACP
) index
++;
3024 case TCI_SRCCHARSET
:
3025 while (index
< MAXTCIINDEX
&& PtrToUlong(lpSrc
) != FONT_tci
[index
].ciCharset
) index
++;
3030 if (index
>= MAXTCIINDEX
|| FONT_tci
[index
].ciCharset
== DEFAULT_CHARSET
) return FALSE
;
3031 *lpCs
= FONT_tci
[index
];
3035 /*************************************************************************
3036 * GetFontLanguageInfo (GDI32.@)
3038 DWORD WINAPI
GetFontLanguageInfo(HDC hdc
)
3040 FONTSIGNATURE fontsig
;
3041 static const DWORD GCP_DBCS_MASK
=0x003F0000,
3042 GCP_DIACRITIC_MASK
=0x00000000,
3043 FLI_GLYPHS_MASK
=0x00000000,
3044 GCP_GLYPHSHAPE_MASK
=0x00000040,
3045 GCP_KASHIDA_MASK
=0x00000000,
3046 GCP_LIGATE_MASK
=0x00000000,
3047 GCP_USEKERNING_MASK
=0x00000000,
3048 GCP_REORDER_MASK
=0x00000060;
3052 GetTextCharsetInfo( hdc
, &fontsig
, 0 );
3053 /* We detect each flag we return using a bitmask on the Codepage Bitfields */
3055 if( (fontsig
.fsCsb
[0]&GCP_DBCS_MASK
)!=0 )
3058 if( (fontsig
.fsCsb
[0]&GCP_DIACRITIC_MASK
)!=0 )
3059 result
|=GCP_DIACRITIC
;
3061 if( (fontsig
.fsCsb
[0]&FLI_GLYPHS_MASK
)!=0 )
3064 if( (fontsig
.fsCsb
[0]&GCP_GLYPHSHAPE_MASK
)!=0 )
3065 result
|=GCP_GLYPHSHAPE
;
3067 if( (fontsig
.fsCsb
[0]&GCP_KASHIDA_MASK
)!=0 )
3068 result
|=GCP_KASHIDA
;
3070 if( (fontsig
.fsCsb
[0]&GCP_LIGATE_MASK
)!=0 )
3073 if( (fontsig
.fsCsb
[0]&GCP_USEKERNING_MASK
)!=0 )
3074 result
|=GCP_USEKERNING
;
3076 /* this might need a test for a HEBREW- or ARABIC_CHARSET as well */
3077 if( GetTextAlign( hdc
) & TA_RTLREADING
)
3078 if( (fontsig
.fsCsb
[0]&GCP_REORDER_MASK
)!=0 )
3079 result
|=GCP_REORDER
;
3085 /*************************************************************************
3086 * GetFontData [GDI32.@]
3088 * Retrieve data for TrueType font.
3092 * success: Number of bytes returned
3093 * failure: GDI_ERROR
3097 * Calls SetLastError()
3100 DWORD WINAPI
GetFontData(HDC hdc
, DWORD table
, DWORD offset
,
3101 LPVOID buffer
, DWORD length
)
3103 DC
*dc
= get_dc_ptr(hdc
);
3107 if(!dc
) return GDI_ERROR
;
3109 dev
= GET_DC_PHYSDEV( dc
, pGetFontData
);
3110 ret
= dev
->funcs
->pGetFontData( dev
, table
, offset
, buffer
, length
);
3111 release_dc_ptr( dc
);
3115 /*************************************************************************
3116 * GetGlyphIndicesA [GDI32.@]
3118 DWORD WINAPI
GetGlyphIndicesA(HDC hdc
, LPCSTR lpstr
, INT count
,
3119 LPWORD pgi
, DWORD flags
)
3125 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3126 hdc
, debugstr_an(lpstr
, count
), count
, pgi
, flags
);
3128 lpstrW
= FONT_mbtowc(hdc
, lpstr
, count
, &countW
, NULL
);
3129 ret
= GetGlyphIndicesW(hdc
, lpstrW
, countW
, pgi
, flags
);
3130 HeapFree(GetProcessHeap(), 0, lpstrW
);
3135 /*************************************************************************
3136 * GetGlyphIndicesW [GDI32.@]
3138 DWORD WINAPI
GetGlyphIndicesW(HDC hdc
, LPCWSTR lpstr
, INT count
,
3139 LPWORD pgi
, DWORD flags
)
3141 DC
*dc
= get_dc_ptr(hdc
);
3145 TRACE("(%p, %s, %d, %p, 0x%x)\n",
3146 hdc
, debugstr_wn(lpstr
, count
), count
, pgi
, flags
);
3148 if(!dc
) return GDI_ERROR
;
3150 dev
= GET_DC_PHYSDEV( dc
, pGetGlyphIndices
);
3151 ret
= dev
->funcs
->pGetGlyphIndices( dev
, lpstr
, count
, pgi
, flags
);
3152 release_dc_ptr( dc
);
3156 /*************************************************************************
3157 * GetCharacterPlacementA [GDI32.@]
3159 * See GetCharacterPlacementW.
3162 * the web browser control of ie4 calls this with dwFlags=0
3165 GetCharacterPlacementA(HDC hdc
, LPCSTR lpString
, INT uCount
,
3166 INT nMaxExtent
, GCP_RESULTSA
*lpResults
,
3171 GCP_RESULTSW resultsW
;
3175 TRACE("%s, %d, %d, 0x%08x\n",
3176 debugstr_an(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3178 /* both structs are equal in size */
3179 memcpy(&resultsW
, lpResults
, sizeof(resultsW
));
3181 lpStringW
= FONT_mbtowc(hdc
, lpString
, uCount
, &uCountW
, &font_cp
);
3182 if(lpResults
->lpOutString
)
3183 resultsW
.lpOutString
= HeapAlloc(GetProcessHeap(), 0, sizeof(WCHAR
)*uCountW
);
3185 ret
= GetCharacterPlacementW(hdc
, lpStringW
, uCountW
, nMaxExtent
, &resultsW
, dwFlags
);
3187 lpResults
->nGlyphs
= resultsW
.nGlyphs
;
3188 lpResults
->nMaxFit
= resultsW
.nMaxFit
;
3190 if(lpResults
->lpOutString
) {
3191 WideCharToMultiByte(font_cp
, 0, resultsW
.lpOutString
, uCountW
,
3192 lpResults
->lpOutString
, uCount
, NULL
, NULL
);
3195 HeapFree(GetProcessHeap(), 0, lpStringW
);
3196 HeapFree(GetProcessHeap(), 0, resultsW
.lpOutString
);
3201 /*************************************************************************
3202 * GetCharacterPlacementW [GDI32.@]
3204 * Retrieve information about a string. This includes the width, reordering,
3205 * Glyphing and so on.
3209 * The width and height of the string if successful, 0 if failed.
3213 * All flags except GCP_REORDER are not yet implemented.
3214 * Reordering is not 100% compliant to the Windows BiDi method.
3215 * Caret positioning is not yet implemented for BiDi.
3216 * Classes are not yet implemented.
3220 GetCharacterPlacementW(
3221 HDC hdc
, /* [in] Device context for which the rendering is to be done */
3222 LPCWSTR lpString
, /* [in] The string for which information is to be returned */
3223 INT uCount
, /* [in] Number of WORDS in string. */
3224 INT nMaxExtent
, /* [in] Maximum extent the string is to take (in HDC logical units) */
3225 GCP_RESULTSW
*lpResults
,/* [in/out] A pointer to a GCP_RESULTSW struct */
3226 DWORD dwFlags
/* [in] Flags specifying how to process the string */
3233 TRACE("%s, %d, %d, 0x%08x\n",
3234 debugstr_wn(lpString
, uCount
), uCount
, nMaxExtent
, dwFlags
);
3236 TRACE("lStructSize=%d, lpOutString=%p, lpOrder=%p, lpDx=%p, lpCaretPos=%p\n"
3237 "lpClass=%p, lpGlyphs=%p, nGlyphs=%u, nMaxFit=%d\n",
3238 lpResults
->lStructSize
, lpResults
->lpOutString
, lpResults
->lpOrder
,
3239 lpResults
->lpDx
, lpResults
->lpCaretPos
, lpResults
->lpClass
,
3240 lpResults
->lpGlyphs
, lpResults
->nGlyphs
, lpResults
->nMaxFit
);
3242 if(dwFlags
&(~GCP_REORDER
)) FIXME("flags 0x%08x ignored\n", dwFlags
);
3243 if(lpResults
->lpClass
) FIXME("classes not implemented\n");
3244 if (lpResults
->lpCaretPos
&& (dwFlags
& GCP_REORDER
))
3245 FIXME("Caret positions for complex scripts not implemented\n");
3247 nSet
= (UINT
)uCount
;
3248 if(nSet
> lpResults
->nGlyphs
)
3249 nSet
= lpResults
->nGlyphs
;
3251 /* return number of initialized fields */
3252 lpResults
->nGlyphs
= nSet
;
3254 if((dwFlags
&GCP_REORDER
)==0 )
3256 /* Treat the case where no special handling was requested in a fastpath way */
3257 /* copy will do if the GCP_REORDER flag is not set */
3258 if(lpResults
->lpOutString
)
3259 memcpy( lpResults
->lpOutString
, lpString
, nSet
* sizeof(WCHAR
));
3261 if(lpResults
->lpOrder
)
3263 for(i
= 0; i
< nSet
; i
++)
3264 lpResults
->lpOrder
[i
] = i
;
3268 BIDI_Reorder(NULL
, lpString
, uCount
, dwFlags
, WINE_GCPW_FORCE_LTR
, lpResults
->lpOutString
,
3269 nSet
, lpResults
->lpOrder
, NULL
, NULL
);
3272 /* FIXME: Will use the placement chars */
3273 if (lpResults
->lpDx
)
3276 for (i
= 0; i
< nSet
; i
++)
3278 if (GetCharWidth32W(hdc
, lpString
[i
], lpString
[i
], &c
))
3279 lpResults
->lpDx
[i
]= c
;
3283 if (lpResults
->lpCaretPos
&& !(dwFlags
& GCP_REORDER
))
3287 lpResults
->lpCaretPos
[0] = 0;
3288 for (i
= 1; i
< nSet
; i
++)
3289 if (GetTextExtentPoint32W(hdc
, &(lpString
[i
- 1]), 1, &size
))
3290 lpResults
->lpCaretPos
[i
] = (pos
+= size
.cx
);
3293 if(lpResults
->lpGlyphs
)
3294 GetGlyphIndicesW(hdc
, lpString
, nSet
, lpResults
->lpGlyphs
, 0);
3296 if (GetTextExtentPoint32W(hdc
, lpString
, uCount
, &size
))
3297 ret
= MAKELONG(size
.cx
, size
.cy
);
3302 /*************************************************************************
3303 * GetCharABCWidthsFloatA [GDI32.@]
3305 * See GetCharABCWidthsFloatW.
3307 BOOL WINAPI
GetCharABCWidthsFloatA( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3314 str
= FONT_GetCharsByRangeA(hdc
, first
, last
, &i
);
3318 wstr
= FONT_mbtowc( hdc
, str
, i
, &wlen
, NULL
);
3320 for (i
= 0; i
< wlen
; i
++)
3322 if (!GetCharABCWidthsFloatW( hdc
, wstr
[i
], wstr
[i
], abcf
))
3330 HeapFree( GetProcessHeap(), 0, str
);
3331 HeapFree( GetProcessHeap(), 0, wstr
);
3336 /*************************************************************************
3337 * GetCharABCWidthsFloatW [GDI32.@]
3339 * Retrieves widths of a range of characters.
3342 * hdc [I] Handle to device context.
3343 * first [I] First character in range to query.
3344 * last [I] Last character in range to query.
3345 * abcf [O] Array of LPABCFLOAT structures.
3351 BOOL WINAPI
GetCharABCWidthsFloatW( HDC hdc
, UINT first
, UINT last
, LPABCFLOAT abcf
)
3357 DC
*dc
= get_dc_ptr( hdc
);
3359 TRACE("%p, %d, %d, %p\n", hdc
, first
, last
, abcf
);
3361 if (!dc
) return FALSE
;
3363 if (!abcf
) goto done
;
3364 if (!(abc
= HeapAlloc( GetProcessHeap(), 0, (last
- first
+ 1) * sizeof(*abc
) ))) goto done
;
3366 dev
= GET_DC_PHYSDEV( dc
, pGetCharABCWidths
);
3367 ret
= dev
->funcs
->pGetCharABCWidths( dev
, first
, last
, abc
);
3370 /* convert device units to logical */
3371 for (i
= first
; i
<= last
; i
++, abcf
++)
3373 abcf
->abcfA
= abc
[i
- first
].abcA
* dc
->xformVport2World
.eM11
;
3374 abcf
->abcfB
= abc
[i
- first
].abcB
* dc
->xformVport2World
.eM11
;
3375 abcf
->abcfC
= abc
[i
- first
].abcC
* dc
->xformVport2World
.eM11
;
3378 HeapFree( GetProcessHeap(), 0, abc
);
3381 release_dc_ptr( dc
);
3385 /*************************************************************************
3386 * GetCharWidthFloatA [GDI32.@]
3388 BOOL WINAPI
GetCharWidthFloatA(HDC hdc
, UINT iFirstChar
,
3389 UINT iLastChar
, PFLOAT pxBuffer
)
3391 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3395 /*************************************************************************
3396 * GetCharWidthFloatW [GDI32.@]
3398 BOOL WINAPI
GetCharWidthFloatW(HDC hdc
, UINT iFirstChar
,
3399 UINT iLastChar
, PFLOAT pxBuffer
)
3401 FIXME("%p, %u, %u, %p: stub!\n", hdc
, iFirstChar
, iLastChar
, pxBuffer
);
3406 /***********************************************************************
3408 * Font Resource API *
3410 ***********************************************************************/
3412 /***********************************************************************
3413 * AddFontResourceA (GDI32.@)
3415 INT WINAPI
AddFontResourceA( LPCSTR str
)
3417 return AddFontResourceExA( str
, 0, NULL
);
3420 /***********************************************************************
3421 * AddFontResourceW (GDI32.@)
3423 INT WINAPI
AddFontResourceW( LPCWSTR str
)
3425 return AddFontResourceExW(str
, 0, NULL
);
3429 /***********************************************************************
3430 * AddFontResourceExA (GDI32.@)
3432 INT WINAPI
AddFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3434 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3435 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3438 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3439 ret
= AddFontResourceExW(strW
, fl
, pdv
);
3440 HeapFree(GetProcessHeap(), 0, strW
);
3444 static BOOL CALLBACK
load_enumed_resource(HMODULE hModule
, LPCWSTR type
, LPWSTR name
, LONG_PTR lParam
)
3446 HRSRC rsrc
= FindResourceW(hModule
, name
, type
);
3447 HGLOBAL hMem
= LoadResource(hModule
, rsrc
);
3448 LPVOID
*pMem
= LockResource(hMem
);
3449 int *num_total
= (int *)lParam
;
3452 TRACE("Found resource %s - trying to load\n", wine_dbgstr_w(type
));
3453 if (!AddFontMemResourceEx(pMem
, SizeofResource(hModule
, rsrc
), NULL
, &num_in_res
))
3455 ERR("Failed to load PE font resource mod=%p ptr=%p\n", hModule
, hMem
);
3459 *num_total
+= num_in_res
;
3463 /***********************************************************************
3464 * AddFontResourceExW (GDI32.@)
3466 INT WINAPI
AddFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3468 int ret
= WineEngAddFontResourceEx(str
, fl
, pdv
);
3471 /* FreeType <2.3.5 has problems reading resources wrapped in PE files. */
3472 HMODULE hModule
= LoadLibraryExW(str
, NULL
, LOAD_LIBRARY_AS_DATAFILE
);
3473 if (hModule
!= NULL
)
3475 int num_resources
= 0;
3476 LPWSTR rt_font
= (LPWSTR
)((ULONG_PTR
)8); /* we don't want to include winuser.h */
3478 TRACE("WineEndAddFontResourceEx failed on PE file %s - trying to load resources manually\n",
3479 wine_dbgstr_w(str
));
3480 if (EnumResourceNamesW(hModule
, rt_font
, load_enumed_resource
, (LONG_PTR
)&num_resources
))
3481 ret
= num_resources
;
3482 FreeLibrary(hModule
);
3488 /***********************************************************************
3489 * RemoveFontResourceA (GDI32.@)
3491 BOOL WINAPI
RemoveFontResourceA( LPCSTR str
)
3493 return RemoveFontResourceExA(str
, 0, 0);
3496 /***********************************************************************
3497 * RemoveFontResourceW (GDI32.@)
3499 BOOL WINAPI
RemoveFontResourceW( LPCWSTR str
)
3501 return RemoveFontResourceExW(str
, 0, 0);
3504 /***********************************************************************
3505 * AddFontMemResourceEx (GDI32.@)
3507 HANDLE WINAPI
AddFontMemResourceEx( PVOID pbFont
, DWORD cbFont
, PVOID pdv
, DWORD
*pcFonts
)
3512 if (!pbFont
|| !cbFont
|| !pcFonts
)
3514 SetLastError(ERROR_INVALID_PARAMETER
);
3518 ret
= WineEngAddFontMemResourceEx(pbFont
, cbFont
, pdv
, &num_fonts
);
3523 *pcFonts
= num_fonts
;
3527 WARN("page fault while writing to *pcFonts (%p)\n", pcFonts
);
3528 RemoveFontMemResourceEx(ret
);
3536 /***********************************************************************
3537 * RemoveFontMemResourceEx (GDI32.@)
3539 BOOL WINAPI
RemoveFontMemResourceEx( HANDLE fh
)
3541 FIXME("(%p) stub\n", fh
);
3545 /***********************************************************************
3546 * RemoveFontResourceExA (GDI32.@)
3548 BOOL WINAPI
RemoveFontResourceExA( LPCSTR str
, DWORD fl
, PVOID pdv
)
3550 DWORD len
= MultiByteToWideChar(CP_ACP
, 0, str
, -1, NULL
, 0);
3551 LPWSTR strW
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
3554 MultiByteToWideChar(CP_ACP
, 0, str
, -1, strW
, len
);
3555 ret
= RemoveFontResourceExW(strW
, fl
, pdv
);
3556 HeapFree(GetProcessHeap(), 0, strW
);
3560 /***********************************************************************
3561 * RemoveFontResourceExW (GDI32.@)
3563 BOOL WINAPI
RemoveFontResourceExW( LPCWSTR str
, DWORD fl
, PVOID pdv
)
3565 return WineEngRemoveFontResourceEx(str
, fl
, pdv
);
3568 /***********************************************************************
3569 * GetTextCharset (GDI32.@)
3571 UINT WINAPI
GetTextCharset(HDC hdc
)
3573 /* MSDN docs say this is equivalent */
3574 return GetTextCharsetInfo(hdc
, NULL
, 0);
3577 /***********************************************************************
3578 * GetTextCharsetInfo (GDI32.@)
3580 UINT WINAPI
GetTextCharsetInfo(HDC hdc
, LPFONTSIGNATURE fs
, DWORD flags
)
3582 UINT ret
= DEFAULT_CHARSET
;
3583 DC
*dc
= get_dc_ptr(hdc
);
3588 dev
= GET_DC_PHYSDEV( dc
, pGetTextCharsetInfo
);
3589 ret
= dev
->funcs
->pGetTextCharsetInfo( dev
, fs
, flags
);
3590 release_dc_ptr( dc
);
3593 if (ret
== DEFAULT_CHARSET
&& fs
)
3594 memset(fs
, 0, sizeof(FONTSIGNATURE
));
3598 /***********************************************************************
3599 * GdiGetCharDimensions (GDI32.@)
3601 * Gets the average width of the characters in the English alphabet.
3604 * hdc [I] Handle to the device context to measure on.
3605 * lptm [O] Pointer to memory to store the text metrics into.
3606 * height [O] On exit, the maximum height of characters in the English alphabet.
3609 * The average width of characters in the English alphabet.
3612 * This function is used by the dialog manager to get the size of a dialog
3613 * unit. It should also be used by other pieces of code that need to know
3614 * the size of a dialog unit in logical units without having access to the
3615 * window handle of the dialog.
3616 * Windows caches the font metrics from this function, but we don't and
3617 * there doesn't appear to be an immediate advantage to do so.
3620 * GetTextExtentPointW, GetTextMetricsW, MapDialogRect.
3622 LONG WINAPI
GdiGetCharDimensions(HDC hdc
, LPTEXTMETRICW lptm
, LONG
*height
)
3625 static const WCHAR alphabet
[] = {
3626 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q',
3627 'r','s','t','u','v','w','x','y','z','A','B','C','D','E','F','G','H',
3628 'I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',0};
3630 if(lptm
&& !GetTextMetricsW(hdc
, lptm
)) return 0;
3632 if(!GetTextExtentPointW(hdc
, alphabet
, 52, &sz
)) return 0;
3634 if (height
) *height
= sz
.cy
;
3635 return (sz
.cx
/ 26 + 1) / 2;
3638 BOOL WINAPI
EnableEUDC(BOOL fEnableEUDC
)
3640 FIXME("(%d): stub\n", fEnableEUDC
);
3644 /***********************************************************************
3645 * GetCharWidthI (GDI32.@)
3647 * Retrieve widths of characters.
3650 * hdc [I] Handle to a device context.
3651 * first [I] First glyph in range to query.
3652 * count [I] Number of glyph indices to query.
3653 * glyphs [I] Array of glyphs to query.
3654 * buffer [O] Buffer to receive character widths.
3657 * Only works with TrueType fonts.
3663 BOOL WINAPI
GetCharWidthI(HDC hdc
, UINT first
, UINT count
, LPWORD glyphs
, LPINT buffer
)
3668 TRACE("(%p, %d, %d, %p, %p)\n", hdc
, first
, count
, glyphs
, buffer
);
3670 if (!(abc
= HeapAlloc(GetProcessHeap(), 0, count
* sizeof(ABC
))))
3673 if (!GetCharABCWidthsI(hdc
, first
, count
, glyphs
, abc
))
3675 HeapFree(GetProcessHeap(), 0, abc
);
3679 for (i
= 0; i
< count
; i
++)
3680 buffer
[i
] = abc
->abcA
+ abc
->abcB
+ abc
->abcC
;
3682 HeapFree(GetProcessHeap(), 0, abc
);
3686 /***********************************************************************
3687 * GetFontUnicodeRanges (GDI32.@)
3689 * Retrieve a list of supported Unicode characters in a font.
3692 * hdc [I] Handle to a device context.
3693 * lpgs [O] GLYPHSET structure specifying supported character ranges.
3696 * Success: Number of bytes written to the buffer pointed to by lpgs.
3700 DWORD WINAPI
GetFontUnicodeRanges(HDC hdc
, LPGLYPHSET lpgs
)
3704 DC
*dc
= get_dc_ptr(hdc
);
3706 TRACE("(%p, %p)\n", hdc
, lpgs
);
3710 dev
= GET_DC_PHYSDEV( dc
, pGetFontUnicodeRanges
);
3711 ret
= dev
->funcs
->pGetFontUnicodeRanges( dev
, lpgs
);
3717 /*************************************************************
3718 * FontIsLinked (GDI32.@)
3720 BOOL WINAPI
FontIsLinked(HDC hdc
)
3722 DC
*dc
= get_dc_ptr(hdc
);
3726 if (!dc
) return FALSE
;
3727 dev
= GET_DC_PHYSDEV( dc
, pFontIsLinked
);
3728 ret
= dev
->funcs
->pFontIsLinked( dev
);
3730 TRACE("returning %d\n", ret
);
3734 /*************************************************************
3735 * GdiRealizationInfo (GDI32.@)
3737 * Returns a structure that contains some font information.
3739 BOOL WINAPI
GdiRealizationInfo(HDC hdc
, realization_info_t
*info
)
3741 DC
*dc
= get_dc_ptr(hdc
);
3745 if (!dc
) return FALSE
;
3746 dev
= GET_DC_PHYSDEV( dc
, pGdiRealizationInfo
);
3747 ret
= dev
->funcs
->pGdiRealizationInfo( dev
, info
);