views:

1238

answers:

3

I need to render some formatted text (colours, different font sizes, underlines, bold, etc) however I'm not sure how to go about doing it. D3DXFont only allows text of a single font/size/weight/colour/etc to be rendered at once, and I cant see a practical way to "combine" multiple calls to ID3DXFont::DrawText to do such things...

I looked around and there doesn't seem to be any existing libraries that do these things, but I have no idea how to implement such a text renderer, and I couldn't even find any documentation on how such a text render would work, only rendering simple fixed width, ASCII bitmap fonts which looking at it is probably an entirely different approach that is only suitable for rendering simple blocks of text where Unicode is not important.

If there's no direct3d font renders capable of doing this, is there any other renderers (eg for use in rendering rich text in a normal window), and would rendering those to a texture in RAM, then uploading that to the video card to render onto the back buffer yield reasonable performance?

+2  A: 

You tagged this with Direct3D, so I'm going to assume that's the target environment. Otherwise, GDI can handle all this stuff.

Actually, looking at GDI is a good place to start, since it supports this as it stands. With GDI, there is only a single font selected at a time for drawing text. Similarly, there can only be a single text color selected at a time. So, to draw a line of text that contains characters in multiple colors and/or fonts, you have to divide the line up into chunks of characters that all have the same rendering state. You set the state for that chunk (text foreground/background color, text font, text spacing, etc.), then call ::TextOut for that chunk of text, then set the state for the next chunk and draw that, and so-on.

The same principle applied in Direct3D. Each chunk of text may require its own ID3DXFont (or your own font mechanism if ID3DXFont isn't sufficient) and color, etc. You set state, draw text, set state, draw text, etc.

Now, if you want to do your own text rendering, you could do fancier things with a shader, but its probably not worth it unless you have the need for really high-quality typography.

In Windows 7 (back-filled for Vista once Windows 7 ships), you'll be able to use DirectWrite for high quality typography in a Direct3D rendering context (D3D10 and later).

legalize
Ok, TextOut:: seems to support working out the position of each block, which ID3DXFont does not (ie I need to calcuate my own RECT for each block somehow...). However I also really need the means to A, precalculate how much space it will take to render something (so for example, I can expand the tool tip box to the required size), and B make it wrap lines above a certain width (using the ability to calculate the needed size to add a vertical scroll bar if needed).
Fire Lancer
IS it possible to do that with GDI? I see plenty of apps that have rich text boxes that do both the things I need (ie wrap it to fit in the box, and work out the "height" of the text so they can add in a vertical scroll bar).
Fire Lancer
Chances are the rich text boxes that you've seen are all leveraging off the underlying RichEdit control in Win32. Because this control is available, its unnecessary for applications to code this low-level functionality for themselves most of the time. However, because its a Win32 control it doesn't know how to render itself in Direct3D. It is possible to perform GDI operations on a hidden Direct3D surface for which you've obtained a GDI device context, but I'm not aware of anyone successfully redirecting an existing Win32 control to a Direct3D surface.
legalize
A: 

I suggest measuring the performance of rendering to a bitmap and uploading to a texture. I suspect that this pretty much what D3DXFont has to do behing the scenes anyway. You could probably cache letters / phrases etc. if needed

John Burton
And that solves the formatting problem how exactly?
Fire Lancer
+1  A: 

In case of using Direct3D9 or early you really have big problems: 1. You always may use GDI, render your text in the HDC, copy it to the Direct3D dynamic texture and use shader to replace background to transparency by color key for example. 2. Take a look on FreeType library may be you'll find it more suitable for you than GDI, but it really will not be easy.

Any way even if you will find a good way of text rendering you obligotary will have problems with small fonts by reason of ClearType Microsoft technology. At first you will not be able just make a matrix of small symbols to type text from it (because symbol is rendered with using of this subpixel rendering). You will probably need some special shader... or you will be enforced reject to use ClearType, but as i've said before it has bad aftereffects on small fonts. At second this technology is patented by Microsoft


But if you do not need support of Windows XP you may try to use Direct2D with DirectWrite and DirectX10 (I didn't try 11). I tried them and they shown good results, you only should avoid often switching between Direct2D and Direct3D contexts, because it may seriously degrade performance. To render something to your texture you may use ID2D1Factory::CreateDxgiSurfaceRenderTarget function

dev_null