[MDX] Direct3D.Font and find the height of the rect given a fixed width/font size...

This topic is 4297 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

Recommended Posts

I am trying to dynamically adjust the size of a font so it will fit within a bounding rectangle of width/height I specify. I am rendering using the managed Direct3D.Font class. The approach I have taken is to calculate the height of the rectangle given a certain font size and a fixed width. If this height is larger then the bounding box height, then reduce the font size and try again. Now I have this "working" using GDI+ (Graphics.MeasureString) and GDI (TextRenderer.MeasureText) to calculate the size, however, if I set the System.Drawing.Font object's Unit property to "GraphicsUnit.Pixel" then when Direct3D.Font draws the font to screen, it is too large - if I leave the property with it's default, then it appears to fit ok.
Bitmap currentTempGraphicsBitmap = new Bitmap(1, 1);
Graphics currentTempGraphics = Graphics.FromImage(currentTempGraphicsBitmap);

currentTempGraphics.PageUnit = GraphicsUnit.Pixel;
currentTempGraphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

currentFont = new Font(_currentTextAreaTemplate.FontFace, currentFontSize, _currentTextAreaTemplate.Fontstyle, GraphicsUnit.Pixel);

Size messageRectSize = System.Windows.Forms.TextRenderer.MeasureText(currentTempGraphics, text, currentFont, new Size(this.Width, Int32.MaxValue), System.Windows.Forms.TextFormatFlags.WordBreak);


I know ID3DXFont::DrawText has a DT_CALCRECT flag that will calculate the height of the rectangle with a fixed width, however there doesn't seem to be a way to call this from managed code (Managed DirectX/C#)? Does anyone know how I can use the DT_CALCRECT flag with the managed Direct3D.Font object? Would I use the "UnmanagedComPointer" property - are there any examples of its use (I couldn't find any). The only other option I can think of is to create a class library in Managed C++ and pass results back to the C# code - I'd rather keep everything in C# though :( Or could anyone explain to me why if I set GraphucsUnit.Pixel as the value for the Unit property on the System.Drawing.Font object the font is too big? Is this the expecected result... am I missing something obvious here? :) Thanks for your help! EDIT: changed your [code] tags to be [source] instead. Wide lines of text break the forum layout! [Edited by - jollyjeffers on May 18, 2006 1:50:12 PM]

Share on other sites
Direct3d.Font.MeasureString is the same as DT_CALCRECT

I suspect that the fact that the GDI one works at all is more luck than anything. Since the fonts are drawn in totally different ways they will likely be different sizes in D3D and GDI.

Share on other sites
Quote:
 Original post by thezbufferDirect3d.Font.MeasureString is the same as DT_CALCRECT

Unfortunatly, MeasureString is not exactly the same as using DT_CALCRECT. You cannot pass in a rect object for it to use, thus I cannot find the height of the rect given a fixed width (i.e. mulitple lines, word wrapping). Which is what I am trying to do.

Quote:
 Unmanaged DocsDT_CALCRECTDetermines the width and height of the rectangle. If there are multiple lines of text, DrawText uses the width of the rectangle pointed to by the pRect parameter and extends the base of the rectangle to bound the last line of text. If there is only one line of text, DrawText modifies the right side of the rectangle so that it bounds the last character in the line. In either case, DrawText returns the height of the formatted text but does not draw the text.

I'm thinking I'll have to break up my string into words and measure each word individually, then do the word wrapping myself. I'm just trying not to reinvent the wheel here, DT_CALCRECT in ID3DXFont::DrawText would give do exactly what I want, but the Direct3D.Font object, not so much :( Why Microsoft thought it would be a great idea to hide this feature from us is anyone's guess :(

Quote:
 Original post by thezbufferI suspect that the fact that the GDI one works at all is more luck than anything. Since the fonts are drawn in totally different ways they will likely be different sizes in D3D and GDI.

Yea... that's what I thought. I believe ID3DXFont uses GDI under the hood, but how it uses GDI is a bit of mystery :(

Share on other sites
Excellent observation, I've only ever measured single lines of text so I had not noticed that limitation. What is really odd is that you can pass in the multi line flags etc into the format parsamter but measure string uses the DrawText overload without a rect (look at it with reflector).

Unless you want to drop into some C++/CLI and use the COM points to the ID3DXFOnt I think you are out of luck here.

The only connection to GDI tht I know of is that D3DXFont uses GDI to draw each character into a texture and to determine the space of each character and otehr kerning information. The actual rendering is done using this information that is cached somewhere so you end up with some spacing differences possibly.