[RESOLVED] Font Scaling re-opened
My day is done, so I figured I might as well ask a question about the last thing I was working on. There has to be a better way to do this than what I am seeing. Here's the problem:
I have a picturebox that has an image on it. The user will be able to draw rectangles on that image, and the rectangle will have a string drawn into it. Frankly, I have no idea about the shape or size of these rectangles except to say that they will have a "reasonable" size to them. What I am trying to figure out is how best to draw the string inside the rectangle. Obviously, the size of the string is determined by the font, and I can measure this size with MeasureString in the Paint event for the PB. The size of the string as drawn must be less than the size of the rectangle such that the string fits entirely within the rectangle.
The problem is that MeasureString takes a font so that the size of the string can be determined in that font. That seems to require that I create a new font object, measure the string in that font, check to see that it is less than the width of the rectangle (don't have to worry about the height), and if the string is too big, reduce the size of the font and try again. This seems to have the potential to create and destroy plenty of font objects for the sole purpose of checking sizes. Is there a better way? How about a method that figures the maximum font size that can be used to get a string of pixel length X?
The second half of this problem is something I haven't even begun looking at yet, but somebody has probably got an answer that will save me some time, so I'll toss it out here:
It is possible that my rectangles will be high and narrow, in which case few strings will fit horizontally in the rectangle, so I might as well draw them vertically. Is there an easy way to draw text vertically rather than horizontally?
Re: [RESOLVED] Font Scaling
By the way, if you want slightly nicer results, you could declare a graphics path and then use:
GraphicsPath.AddString + Graphics.SmoothingMode=HighQuality + Graphics.FillPath.
This will draw the path with antialiased edges. Graphics.DrawString, on the other hand, doesn't use antialiasing regardless of the SmoothingMode.
Besides anitaliasing, using a GraphicsPath has a couple of other advantages:
1. You can scale the path itself with GraphicsPath.Transform instead of scaling the Graphics object. The scaling works from the GraphicsPath origin. I find this easier to conceptualize and it may save having to do Translate operations to get the scaling origin right (I need to check that).
2. You can get a more accurate fit of the string to the rectangle using GraphicsPath.GetBounds instead of Graphics.MeasureString. It may help to specify a Pen in the AddString method with Pen.MiterLimit property set to 1 (the default is 10); that reduces the empty margin around the characters.
BB
Re: [RESOLVED] Font Scaling
That's good to know. I have the text working now, and it looks good enough. Interestingly, in the normal use of this program, the user will actually look at this part of the program about once a decade, or so. To put it lightly, the graphics quality does not have to be excessively high.
Re: Font Scaling re-opened
I had written a question here, but as I wrote it, I realized that I had to check one further thing, and solved the problem. Still, there is an addition to BBs code that needs to be added for this thread to be fully useful.
Note the transforms used in BBs code. What these do is change the transformation matrix that is applied to the whole graphics object. That's risky! It works really well as long as that string is the last thing you are drawing, but I was drawing multiple rectangles in sequence. The transformations applied for that first string were then being applied to the next rectangle, which so utterly transformed the rectangle that it was either a single point, or wasn't even visible. I was fairly sure what the problem was, but the first time I looked at the methods available in the graphics class, I overlooked the one that I felt had to be there: ResetTransform.
Not seeing that, I tried to use a transform of 0 or 1, but since transformation matrices are additive, this had either no impact, or made the problem worse. I was writing on here to ask how to reset the transformation matrix for a graphics object, and decided to have one more look. That's when I saw the ResetTransform method, which, as a rule, should probably be called after doing any scaling, rotation, or translation transformations on a graphics object unless you know that you will want the same transformations applied to the next element that you are drawing.