5 * Copyright (C) 2008 Tony Wasserka
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 #include "d3dx9_private.h"
27 #endif /* __REACTOS__ */
29 WINE_DEFAULT_DEBUG_CHANNEL(d3dx
);
36 IDirect3DTexture9
*texture
;
38 struct wine_rb_entry entry
;
43 ID3DXFont ID3DXFont_iface
;
46 IDirect3DDevice9
*device
;
53 struct wine_rb_tree glyph_tree
;
55 IDirect3DTexture9
**textures
;
56 unsigned int texture_count
, texture_pos
;
58 unsigned int texture_size
, glyph_size
, glyphs_per_texture
;
61 static int glyph_rb_compare(const void *key
, const struct wine_rb_entry
*entry
)
63 struct d3dx_glyph
*glyph
= WINE_RB_ENTRY_VALUE(entry
, struct d3dx_glyph
, entry
);
64 unsigned int id
= (UINT_PTR
)key
;
66 return id
- glyph
->id
;
69 static void glyph_rb_free(struct wine_rb_entry
*entry
, void *context
)
71 struct d3dx_glyph
*glyph
= WINE_RB_ENTRY_VALUE(entry
, struct d3dx_glyph
, entry
);
76 static inline struct d3dx_font
*impl_from_ID3DXFont(ID3DXFont
*iface
)
78 return CONTAINING_RECORD(iface
, struct d3dx_font
, ID3DXFont_iface
);
81 static HRESULT WINAPI
ID3DXFontImpl_QueryInterface(ID3DXFont
*iface
, REFIID riid
, void **out
)
83 TRACE("iface %p, riid %s, out %p.\n", iface
, debugstr_guid(riid
), out
);
85 if (IsEqualGUID(riid
, &IID_ID3DXFont
)
86 || IsEqualGUID(riid
, &IID_IUnknown
))
88 IUnknown_AddRef(iface
);
93 WARN("%s not implemented, returning E_NOINTERFACE.\n", debugstr_guid(riid
));
99 static ULONG WINAPI
ID3DXFontImpl_AddRef(ID3DXFont
*iface
)
101 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
102 ULONG ref
= InterlockedIncrement(&font
->ref
);
104 TRACE("%p increasing refcount to %u\n", iface
, ref
);
108 static ULONG WINAPI
ID3DXFontImpl_Release(ID3DXFont
*iface
)
110 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
111 ULONG ref
= InterlockedDecrement(&font
->ref
);
114 TRACE("%p decreasing refcount to %u\n", iface
, ref
);
118 for (i
= 0; i
< font
->texture_count
; ++i
)
119 IDirect3DTexture9_Release(font
->textures
[i
]);
121 heap_free(font
->textures
);
123 wine_rb_destroy(&font
->glyph_tree
, glyph_rb_free
, NULL
);
125 DeleteObject(font
->hfont
);
127 IDirect3DDevice9_Release(font
->device
);
133 static HRESULT WINAPI
ID3DXFontImpl_GetDevice(ID3DXFont
*iface
, IDirect3DDevice9
**device
)
135 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
137 TRACE("iface %p, device %p\n", iface
, device
);
139 if( !device
) return D3DERR_INVALIDCALL
;
140 *device
= font
->device
;
141 IDirect3DDevice9_AddRef(font
->device
);
146 static HRESULT WINAPI
ID3DXFontImpl_GetDescA(ID3DXFont
*iface
, D3DXFONT_DESCA
*desc
)
148 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
150 TRACE("iface %p, desc %p\n", iface
, desc
);
152 if( !desc
) return D3DERR_INVALIDCALL
;
153 memcpy(desc
, &font
->desc
, FIELD_OFFSET(D3DXFONT_DESCA
, FaceName
));
154 WideCharToMultiByte(CP_ACP
, 0, font
->desc
.FaceName
, -1, desc
->FaceName
, ARRAY_SIZE(desc
->FaceName
), NULL
, NULL
);
159 static HRESULT WINAPI
ID3DXFontImpl_GetDescW(ID3DXFont
*iface
, D3DXFONT_DESCW
*desc
)
161 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
163 TRACE("iface %p, desc %p\n", iface
, desc
);
165 if( !desc
) return D3DERR_INVALIDCALL
;
171 static BOOL WINAPI
ID3DXFontImpl_GetTextMetricsA(ID3DXFont
*iface
, TEXTMETRICA
*metrics
)
173 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
174 TRACE("iface %p, metrics %p\n", iface
, metrics
);
175 return GetTextMetricsA(font
->hdc
, metrics
);
178 static BOOL WINAPI
ID3DXFontImpl_GetTextMetricsW(ID3DXFont
*iface
, TEXTMETRICW
*metrics
)
180 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
181 TRACE("iface %p, metrics %p\n", iface
, metrics
);
182 return GetTextMetricsW(font
->hdc
, metrics
);
185 static HDC WINAPI
ID3DXFontImpl_GetDC(ID3DXFont
*iface
)
187 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
188 TRACE("iface %p\n", iface
);
192 static HRESULT WINAPI
ID3DXFontImpl_GetGlyphData(ID3DXFont
*iface
, UINT glyph
,
193 IDirect3DTexture9
**texture
, RECT
*black_box
, POINT
*cell_inc
)
195 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
196 struct wine_rb_entry
*entry
;
199 TRACE("iface %p, glyph %#x, texture %p, black_box %p, cell_inc %p.\n",
200 iface
, glyph
, texture
, black_box
, cell_inc
);
202 hr
= ID3DXFont_PreloadGlyphs(iface
, glyph
, glyph
);
206 entry
= wine_rb_get(&font
->glyph_tree
, ULongToPtr(glyph
));
209 struct d3dx_glyph
*current_glyph
= WINE_RB_ENTRY_VALUE(entry
, struct d3dx_glyph
, entry
);
212 *cell_inc
= current_glyph
->cell_inc
;
214 *black_box
= current_glyph
->black_box
;
217 *texture
= current_glyph
->texture
;
219 IDirect3DTexture9_AddRef(current_glyph
->texture
);
224 return D3DXERR_INVALIDDATA
;
227 static HRESULT WINAPI
ID3DXFontImpl_PreloadCharacters(ID3DXFont
*iface
, UINT first
, UINT last
)
229 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
230 unsigned int i
, count
, start
, end
;
234 TRACE("iface %p, first %u, last %u.\n", iface
, first
, last
);
239 count
= last
- first
+ 1;
240 indices
= heap_alloc(count
* sizeof(*indices
));
242 return E_OUTOFMEMORY
;
244 chars
= heap_alloc(count
* sizeof(*chars
));
248 return E_OUTOFMEMORY
;
251 for (i
= 0; i
< count
; ++i
)
252 chars
[i
] = first
+ i
;
254 GetGlyphIndicesW(font
->hdc
, chars
, count
, indices
, 0);
256 start
= end
= indices
[0];
257 for (i
= 1; i
< count
; ++i
)
259 if (indices
[i
] == end
+ 1)
264 ID3DXFont_PreloadGlyphs(iface
, start
, end
);
265 start
= end
= indices
[i
];
267 ID3DXFont_PreloadGlyphs(iface
, start
, end
);
275 static uint32_t morton_decode(uint32_t x
)
278 x
= (x
^ (x
>> 1)) & 0x33333333;
279 x
= (x
^ (x
>> 2)) & 0x0f0f0f0f;
280 x
= (x
^ (x
>> 4)) & 0x00ff00ff;
281 x
= (x
^ (x
>> 8)) & 0x0000ffff;
285 /* The glyphs are stored in a grid. Cell sizes vary between different font
288 * The grid is filled in Morton order:
289 * 1 2 5 6 17 18 21 22
290 * 3 4 7 8 19 20 23 24
291 * 9 10 13 14 25 26 29 30
292 * 11 12 15 16 27 28 31 32
296 * i.e. we try to fill one small square, then three equal-sized squares so
297 * that we get one big square, etc.
299 * The glyphs are positioned around their baseline, which is located at y
300 * position glyph_size * i + tmAscent. Concerning the x position, the glyphs
301 * are centered around glyph_size * (i + 0.5). */
302 static HRESULT WINAPI
ID3DXFontImpl_PreloadGlyphs(ID3DXFont
*iface
, UINT first
, UINT last
)
304 static const MAT2 mat
= { {0,1}, {0,0}, {0,0}, {0,1} };
305 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
306 IDirect3DTexture9
*current_texture
= NULL
;
307 unsigned int size
, stride
, glyph
, x
, y
;
308 struct d3dx_glyph
*current_glyph
;
309 D3DLOCKED_RECT lockrect
;
310 GLYPHMETRICS metrics
;
316 TRACE("iface %p, first %u, last %u.\n", iface
, first
, last
);
321 if (font
->texture_count
)
322 current_texture
= font
->textures
[font
->texture_count
- 1];
324 for (glyph
= first
; glyph
<= last
; ++glyph
)
326 if (wine_rb_get(&font
->glyph_tree
, ULongToPtr(glyph
)))
329 current_glyph
= heap_alloc(sizeof(*current_glyph
));
333 IDirect3DTexture9_UnlockRect(current_texture
, 0);
334 return E_OUTOFMEMORY
;
337 current_glyph
->id
= glyph
;
338 current_glyph
->texture
= NULL
;
339 wine_rb_put(&font
->glyph_tree
, ULongToPtr(current_glyph
->id
), ¤t_glyph
->entry
);
341 size
= GetGlyphOutlineW(font
->hdc
, glyph
, GGO_GLYPH_INDEX
| GGO_GRAY8_BITMAP
, &metrics
, 0, NULL
, &mat
);
342 if (size
== GDI_ERROR
)
344 WARN("GetGlyphOutlineW failed.\n");
350 buffer
= heap_alloc(size
);
354 IDirect3DTexture9_UnlockRect(current_texture
, 0);
355 return E_OUTOFMEMORY
;
358 GetGlyphOutlineW(font
->hdc
, glyph
, GGO_GLYPH_INDEX
| GGO_GRAY8_BITMAP
, &metrics
, size
, buffer
, &mat
);
360 if (font
->texture_pos
== font
->glyphs_per_texture
)
362 unsigned int new_texture_count
= font
->texture_count
+ 1;
363 IDirect3DTexture9
**new_textures
;
366 IDirect3DTexture9_UnlockRect(current_texture
, 0);
368 new_textures
= heap_realloc(font
->textures
, new_texture_count
* sizeof(*new_textures
));
372 return E_OUTOFMEMORY
;
374 font
->textures
= new_textures
;
376 if (FAILED(hr
= IDirect3DDevice9_CreateTexture(font
->device
, font
->texture_size
,
377 font
->texture_size
, 0, 0, D3DFMT_A8R8G8B8
, D3DPOOL_MANAGED
,
378 &font
->textures
[font
->texture_count
], NULL
)))
384 current_texture
= font
->textures
[font
->texture_count
++];
385 font
->texture_pos
= 0;
390 if (FAILED(hr
= IDirect3DTexture9_LockRect(current_texture
, 0, &lockrect
, NULL
, 0)))
398 x
= morton_decode(font
->texture_pos
) * font
->glyph_size
;
399 y
= morton_decode(font
->texture_pos
>> 1) * font
->glyph_size
;
401 current_glyph
->black_box
.left
= x
- metrics
.gmptGlyphOrigin
.x
+ font
->glyph_size
/ 2
402 - metrics
.gmBlackBoxX
/ 2;
403 current_glyph
->black_box
.top
= y
- metrics
.gmptGlyphOrigin
.y
+ font
->metrics
.tmAscent
+ 1;
404 current_glyph
->black_box
.right
= current_glyph
->black_box
.left
+ metrics
.gmBlackBoxX
;
405 current_glyph
->black_box
.bottom
= current_glyph
->black_box
.top
+ metrics
.gmBlackBoxY
;
406 current_glyph
->cell_inc
.x
= metrics
.gmptGlyphOrigin
.x
- 1;
407 current_glyph
->cell_inc
.y
= font
->metrics
.tmAscent
- metrics
.gmptGlyphOrigin
.y
- 1;
408 current_glyph
->texture
= current_texture
;
410 pixel_data
= lockrect
.pBits
;
411 stride
= (metrics
.gmBlackBoxX
+ 3) & ~3;
412 for (y
= 0; y
< metrics
.gmBlackBoxY
; ++y
)
413 for (x
= 0; x
< metrics
.gmBlackBoxX
; ++x
)
414 pixel_data
[(current_glyph
->black_box
.top
+ y
) * lockrect
.Pitch
/ 4
415 + current_glyph
->black_box
.left
+ x
] =
416 (buffer
[y
* stride
+ x
] * 255 / 64 << 24) | 0x00ffffffu
;
422 IDirect3DTexture9_UnlockRect(current_texture
, 0);
427 static HRESULT WINAPI
ID3DXFontImpl_PreloadTextA(ID3DXFont
*iface
, const char *string
, INT count
)
433 TRACE("iface %p, string %s, count %d.\n", iface
, debugstr_an(string
, count
), count
);
435 if (!string
&& !count
)
439 return D3DERR_INVALIDCALL
;
441 countW
= MultiByteToWideChar(CP_ACP
, 0, string
, count
< 0 ? -1 : count
, NULL
, 0);
443 wstr
= heap_alloc(countW
* sizeof(*wstr
));
445 return E_OUTOFMEMORY
;
447 MultiByteToWideChar(CP_ACP
, 0, string
, count
< 0 ? -1 : count
, wstr
, countW
);
449 hr
= ID3DXFont_PreloadTextW(iface
, wstr
, count
< 0 ? countW
- 1 : countW
);
456 static HRESULT WINAPI
ID3DXFontImpl_PreloadTextW(ID3DXFont
*iface
, const WCHAR
*string
, INT count
)
458 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
462 TRACE("iface %p, string %s, count %d.\n", iface
, debugstr_wn(string
, count
), count
);
464 if (!string
&& !count
)
468 return D3DERR_INVALIDCALL
;
471 count
= lstrlenW(string
);
473 indices
= heap_alloc(count
* sizeof(*indices
));
475 return E_OUTOFMEMORY
;
477 GetGlyphIndicesW(font
->hdc
, string
, count
, indices
, 0);
479 for (i
= 0; i
< count
; ++i
)
480 ID3DXFont_PreloadGlyphs(iface
, indices
[i
], indices
[i
]);
487 static INT WINAPI
ID3DXFontImpl_DrawTextA(ID3DXFont
*iface
, ID3DXSprite
*sprite
,
488 const char *string
, INT count
, RECT
*rect
, DWORD format
, D3DCOLOR color
)
493 TRACE("iface %p, sprite %p, string %s, count %d, rect %s, format %#x, color 0x%08x.\n",
494 iface
, sprite
, debugstr_an(string
, count
), count
, wine_dbgstr_rect(rect
), format
, color
);
496 if (!string
|| !count
)
499 countW
= MultiByteToWideChar(CP_ACP
, 0, string
, count
< 0 ? -1 : count
, NULL
, 0);
504 wstr
= heap_alloc_zero(countW
* sizeof(*wstr
));
508 MultiByteToWideChar(CP_ACP
, 0, string
, count
< 0 ? -1 : count
, wstr
, countW
);
510 ret
= ID3DXFont_DrawTextW(iface
, sprite
, wstr
, count
< 0 ? countW
- 1 : countW
,
511 rect
, format
, color
);
518 static void word_break(HDC hdc
, const WCHAR
*str
, unsigned int *str_len
,
519 unsigned int chars_fit
, unsigned int *chars_used
, SIZE
*size
)
527 sla
= heap_alloc(*str_len
* sizeof(*sla
));
531 memset(&sa
, 0, sizeof(sa
));
532 sa
.eScript
= SCRIPT_UNDEFINED
;
534 ScriptBreak(str
, *str_len
, &sa
, sla
);
536 /* Work back from the last character that did fit to a place where we can break */
538 while (i
> 0 && !sla
[i
].fSoftBreak
) /* chars_fit < *str_len so this is valid */
541 /* If the there is no word that fits put in all characters that do fit */
542 if (!sla
[i
].fSoftBreak
)
546 if (sla
[i
].fWhiteSpace
)
549 /* Remove extra spaces */
550 while (i
> 0 && sla
[i
-1].fWhiteSpace
)
554 /* Remeasure the string */
555 GetTextExtentExPointW(hdc
, str
, *str_len
, 0, NULL
, NULL
, size
);
559 static const WCHAR
*read_line(HDC hdc
, const WCHAR
*str
, unsigned int *count
,
560 WCHAR
*dest
, unsigned int *dest_len
, int width
, DWORD format
, SIZE
*size
)
562 unsigned int orig_count
= *count
;
567 while (*count
&& (str
[i
] != '\n' || (format
& DT_SINGLELINE
)))
570 if (str
[i
] != '\r' && str
[i
] != '\n')
571 dest
[(*dest_len
)++] = str
[i
];
576 GetTextExtentExPointW(hdc
, dest
, *dest_len
, width
, &num_fit
, NULL
, size
);
578 if (num_fit
< *dest_len
&& (format
& DT_WORDBREAK
))
580 unsigned int chars_used
;
582 word_break(hdc
, dest
, dest_len
, num_fit
, &chars_used
, size
);
583 *count
= orig_count
- chars_used
;
587 if (*count
&& str
[i
] == '\n')
598 static int compute_rect(struct d3dx_font
*font
, const WCHAR
*string
, unsigned int count
,
599 WCHAR
*line
, RECT
*rect
, DWORD format
)
601 int y
, lh
, width
, top
= rect
->top
;
606 lh
= font
->metrics
.tmHeight
;
607 width
= rect
->right
- rect
->left
;
611 unsigned int line_len
;
613 string
= read_line(font
->hdc
, string
, &count
, line
, &line_len
, width
, format
, &size
);
615 if (size
.cx
> max_width
)
619 if (!(format
& DT_NOCLIP
) && (y
> rect
->bottom
))
623 if (format
& DT_CENTER
)
625 rect
->left
+= (rect
->right
- rect
->left
- max_width
) / 2;
626 rect
->right
= rect
->left
+ max_width
;
628 else if (format
& DT_RIGHT
)
630 rect
->left
= rect
->right
- max_width
;
634 rect
->right
= rect
->left
+ max_width
;
637 if (format
& DT_VCENTER
)
639 rect
->top
+= (rect
->bottom
- y
) / 2;
640 rect
->bottom
= rect
->top
+ y
- top
;
642 else if (format
& DT_BOTTOM
)
644 rect
->top
+= rect
->bottom
- y
;
651 return rect
->bottom
- top
;
654 static INT WINAPI
ID3DXFontImpl_DrawTextW(ID3DXFont
*iface
, ID3DXSprite
*sprite
,
655 const WCHAR
*string
, INT in_count
, RECT
*rect
, DWORD format
, D3DCOLOR color
)
657 struct d3dx_font
*font
= impl_from_ID3DXFont(iface
);
658 int lh
, x
, y
, width
, top
, ret
= 0;
659 ID3DXSprite
*target
= sprite
;
665 TRACE("iface %p, sprite %p, string %s, in_count %d, rect %s, format %#x, color 0x%08x.\n",
666 iface
, sprite
, debugstr_wn(string
, in_count
), in_count
, wine_dbgstr_rect(rect
), format
, color
);
671 count
= in_count
< 0 ? lstrlenW(string
) : in_count
;
676 if (format
& DT_CALCRECT
)
679 if (format
& DT_SINGLELINE
)
680 format
&= ~DT_WORDBREAK
;
682 line
= heap_alloc(count
* sizeof(*line
));
686 if (!rect
|| format
& (DT_CALCRECT
| DT_VCENTER
| DT_BOTTOM
))
693 else if (!(format
& DT_CALCRECT
))
701 ret
= compute_rect(font
, string
, count
, line
, rect
, format
);
703 if (format
& DT_CALCRECT
)
712 lh
= font
->metrics
.tmHeight
;
713 width
= rect
->right
- rect
->left
;
717 D3DXCreateSprite(font
->device
, &target
);
718 ID3DXSprite_Begin(target
, 0);
723 unsigned int line_len
, i
;
724 GCP_RESULTSW results
;
726 string
= read_line(font
->hdc
, string
, &count
, line
, &line_len
, width
, format
, &size
);
728 if (format
& DT_CENTER
)
729 x
= (rect
->left
+ rect
->right
- size
.cx
) / 2;
730 else if (format
& DT_RIGHT
)
731 x
= rect
->right
- size
.cx
;
735 memset(&results
, 0, sizeof(results
));
736 results
.nGlyphs
= line_len
;
738 results
.lpCaretPos
= heap_alloc(line_len
* sizeof(*results
.lpCaretPos
));
739 if (!results
.lpCaretPos
)
742 results
.lpGlyphs
= heap_alloc(line_len
* sizeof(*results
.lpGlyphs
));
743 if (!results
.lpGlyphs
)
745 heap_free(results
.lpCaretPos
);
749 GetCharacterPlacementW(font
->hdc
, line
, line_len
, 0, &results
, 0);
751 for (i
= 0; i
< results
.nGlyphs
; ++i
)
753 IDirect3DTexture9
*texture
;
758 ID3DXFont_GetGlyphData(iface
, results
.lpGlyphs
[i
], &texture
, &black_box
, &cell_inc
);
763 pos
.x
= cell_inc
.x
+ x
+ results
.lpCaretPos
[i
];
764 pos
.y
= cell_inc
.y
+ y
;
767 if (!(format
& DT_NOCLIP
))
769 if (pos
.x
> rect
->right
)
771 IDirect3DTexture9_Release(texture
);
775 if (pos
.x
+ black_box
.right
- black_box
.left
> rect
->right
)
776 black_box
.right
= black_box
.left
+ rect
->right
- pos
.x
;
778 if (pos
.y
+ black_box
.bottom
- black_box
.top
> rect
->bottom
)
779 black_box
.bottom
= black_box
.top
+ rect
->bottom
- pos
.y
;
782 ID3DXSprite_Draw(target
, texture
, &black_box
, NULL
, &pos
, color
);
783 IDirect3DTexture9_Release(texture
);
786 heap_free(results
.lpCaretPos
);
787 heap_free(results
.lpGlyphs
);
790 if (!(DT_NOCLIP
& format
) && (y
> rect
->bottom
))
797 if (target
!= sprite
)
799 ID3DXSprite_End(target
);
800 ID3DXSprite_Release(target
);
808 static HRESULT WINAPI
ID3DXFontImpl_OnLostDevice(ID3DXFont
*iface
)
810 FIXME("iface %p stub!\n", iface
);
814 static HRESULT WINAPI
ID3DXFontImpl_OnResetDevice(ID3DXFont
*iface
)
816 FIXME("iface %p stub\n", iface
);
820 static const ID3DXFontVtbl D3DXFont_Vtbl
=
822 /*** IUnknown methods ***/
823 ID3DXFontImpl_QueryInterface
,
824 ID3DXFontImpl_AddRef
,
825 ID3DXFontImpl_Release
,
826 /*** ID3DXFont methods ***/
827 ID3DXFontImpl_GetDevice
,
828 ID3DXFontImpl_GetDescA
,
829 ID3DXFontImpl_GetDescW
,
830 ID3DXFontImpl_GetTextMetricsA
,
831 ID3DXFontImpl_GetTextMetricsW
,
833 ID3DXFontImpl_GetGlyphData
,
834 ID3DXFontImpl_PreloadCharacters
,
835 ID3DXFontImpl_PreloadGlyphs
,
836 ID3DXFontImpl_PreloadTextA
,
837 ID3DXFontImpl_PreloadTextW
,
838 ID3DXFontImpl_DrawTextA
,
839 ID3DXFontImpl_DrawTextW
,
840 ID3DXFontImpl_OnLostDevice
,
841 ID3DXFontImpl_OnResetDevice
844 HRESULT WINAPI
D3DXCreateFontA(struct IDirect3DDevice9
*device
, INT height
, UINT width
,
845 UINT weight
, UINT miplevels
, BOOL italic
, DWORD charset
, DWORD precision
, DWORD quality
,
846 DWORD pitchandfamily
, const char *facename
, struct ID3DXFont
**font
)
850 if( !device
|| !font
) return D3DERR_INVALIDCALL
;
855 desc
.MipLevels
=miplevels
;
857 desc
.CharSet
=charset
;
858 desc
.OutputPrecision
=precision
;
859 desc
.Quality
=quality
;
860 desc
.PitchAndFamily
=pitchandfamily
;
861 if(facename
!= NULL
) lstrcpyA(desc
.FaceName
, facename
);
862 else desc
.FaceName
[0] = '\0';
864 return D3DXCreateFontIndirectA(device
, &desc
, font
);
867 HRESULT WINAPI
D3DXCreateFontW(IDirect3DDevice9
*device
, INT height
, UINT width
, UINT weight
, UINT miplevels
, BOOL italic
, DWORD charset
,
868 DWORD precision
, DWORD quality
, DWORD pitchandfamily
, const WCHAR
*facename
, ID3DXFont
**font
)
872 if( !device
|| !font
) return D3DERR_INVALIDCALL
;
877 desc
.MipLevels
=miplevels
;
879 desc
.CharSet
=charset
;
880 desc
.OutputPrecision
=precision
;
881 desc
.Quality
=quality
;
882 desc
.PitchAndFamily
=pitchandfamily
;
883 if(facename
!= NULL
) lstrcpyW(desc
.FaceName
, facename
);
884 else desc
.FaceName
[0] = '\0';
886 return D3DXCreateFontIndirectW(device
, &desc
, font
);
889 /***********************************************************************
890 * D3DXCreateFontIndirectA (D3DX9_36.@)
892 HRESULT WINAPI
D3DXCreateFontIndirectA(IDirect3DDevice9
*device
, const D3DXFONT_DESCA
*desc
, ID3DXFont
**font
)
894 D3DXFONT_DESCW widedesc
;
896 if( !device
|| !desc
|| !font
) return D3DERR_INVALIDCALL
;
898 /* Copy everything but the last structure member. This requires the
899 two D3DXFONT_DESC structures to be equal until the FaceName member */
900 memcpy(&widedesc
, desc
, FIELD_OFFSET(D3DXFONT_DESCA
, FaceName
));
901 MultiByteToWideChar(CP_ACP
, 0, desc
->FaceName
, -1, widedesc
.FaceName
, ARRAY_SIZE(widedesc
.FaceName
));
902 return D3DXCreateFontIndirectW(device
, &widedesc
, font
);
905 /***********************************************************************
906 * D3DXCreateFontIndirectW (D3DX9_36.@)
908 HRESULT WINAPI
D3DXCreateFontIndirectW(IDirect3DDevice9
*device
, const D3DXFONT_DESCW
*desc
, ID3DXFont
**font
)
910 D3DDEVICE_CREATION_PARAMETERS cpars
;
911 struct d3dx_font
*object
;
916 TRACE("(%p, %p, %p)\n", device
, desc
, font
);
918 if( !device
|| !desc
|| !font
) return D3DERR_INVALIDCALL
;
920 /* the device MUST support D3DFMT_A8R8G8B8 */
921 IDirect3DDevice9_GetDirect3D(device
, &d3d
);
922 IDirect3DDevice9_GetCreationParameters(device
, &cpars
);
923 IDirect3DDevice9_GetDisplayMode(device
, 0, &mode
);
924 hr
= IDirect3D9_CheckDeviceFormat(d3d
, cpars
.AdapterOrdinal
, cpars
.DeviceType
, mode
.Format
, 0, D3DRTYPE_TEXTURE
, D3DFMT_A8R8G8B8
);
927 IDirect3D9_Release(d3d
);
928 return D3DXERR_INVALIDDATA
;
930 IDirect3D9_Release(d3d
);
932 object
= heap_alloc_zero(sizeof(*object
));
936 return E_OUTOFMEMORY
;
938 object
->ID3DXFont_iface
.lpVtbl
= &D3DXFont_Vtbl
;
940 object
->device
= device
;
941 object
->desc
= *desc
;
943 object
->hdc
= CreateCompatibleDC(NULL
);
947 return D3DXERR_INVALIDDATA
;
950 object
->hfont
= CreateFontW(desc
->Height
, desc
->Width
, 0, 0, desc
->Weight
, desc
->Italic
, FALSE
, FALSE
, desc
->CharSet
,
951 desc
->OutputPrecision
, CLIP_DEFAULT_PRECIS
, desc
->Quality
, desc
->PitchAndFamily
, desc
->FaceName
);
954 DeleteDC(object
->hdc
);
956 return D3DXERR_INVALIDDATA
;
958 SelectObject(object
->hdc
, object
->hfont
);
960 wine_rb_init(&object
->glyph_tree
, glyph_rb_compare
);
962 if (!GetTextMetricsW(object
->hdc
, &object
->metrics
))
964 DeleteObject(object
->hfont
);
965 DeleteDC(object
->hdc
);
967 return D3DXERR_INVALIDDATA
;
970 object
->glyph_size
= make_pow2(object
->metrics
.tmHeight
);
972 object
->texture_size
= object
->glyph_size
;
973 if (object
->glyph_size
< 256)
974 object
->texture_size
= min(256, object
->texture_size
* 16);
976 object
->glyphs_per_texture
= object
->texture_size
* object
->texture_size
977 / (object
->glyph_size
* object
->glyph_size
);
978 object
->texture_pos
= object
->glyphs_per_texture
;
980 IDirect3DDevice9_AddRef(device
);
981 *font
= &object
->ID3DXFont_iface
;