I'm writing a program that takes bitmaps and writes some text onto them. I have a functional method that will do this, I provide it with the string that needs to be drawn, the rectangle it needs to be fitted to, the name of the font family to use, gets the largest size it possibly can for the font and then draws it onto the provided bitmap (centred to the rectangle if that is what is desired)
The code I am currently using is as follow
public static Bitmap Write_Text(Bitmap i, string s, Rectangle r, string font, bool centered, bool bold)
{
//TODO check that there isnt a better way to do this
//first off we need to make sure this rectangle we are given remains in the bounds
//of the bitmap it will be drawn on
//since pixels start at (0,0) we need the combined origin and dimension of the rectangle
//to be of a lesser value than the dimenion of the rectangle (since = could give out of bounds)
if((r.Width + r.X)<i.Width && (r.Height + r.Y) < i.Height && r.X >= 0 && r.Y >= 0)
{
//now we need to ensure that the graphics object that
//draws the text is properly disposed of
using(Graphics g = Graphics.FromImage(i))
{
//The graphics object will have some settings tweaked
//to ensure high quality rendering
g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
//Normally Compositing Mode Would Be Set But Writing Text requires its own non enum setting
//and so is excluded here
g.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality;
//and one more dedicated to ensuring the text renders with nice contrast
//and non jagged letters
g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;
//now since we need to actually loop over to try and fit the text to the box
//we need a control variable for a do-while loop
bool fits = false;
//and storage for the parameter for the fonts size
//the font can't actually be any larger than the smaller
//dimension of the box it goes in
int size = Math.Min(r.Width, r.Height);
do
{
//now a font family may not exist on the computer microsofts
//sans seriff will be used so no need for try catches
Font f;
//If the font is to be bold set it as such
if (bold)
{
f = new Font(font, size, System.Drawing.FontStyle.Bold, GraphicsUnit.Pixel);
}
else
{
f = new Font(font, size, GraphicsUnit.Pixel);
}
//now we measure the string and if it fits inside the rectangle we can proceed
if(g.MeasureString(s,f).Width <= r.Width && g.MeasureString(s,f).Height <= r.Height)
{
fits = true;
}
else
{
//if the string doesnt fit the box decrease the size and try again
size--;
}
//regardless dispose of f to avoid memory leaks
f.Dispose();
}
while (!fits);
//now we just need to make a string attributes object since the string may want to be centered
StringFormat Format = new StringFormat();
if (centered)
{
Format.Alignment = StringAlignment.Center;
Format.LineAlignment = StringAlignment.Center;
}
//now construct the font object that will be used for the drawing
//as above
Font ff;
if (bold)
{
ff = new Font(font, size, System.Drawing.FontStyle.Bold, GraphicsUnit.Pixel);
}
else
{
ff = new Font(font, size, GraphicsUnit.Pixel);
}
//now draw the text in place on the bitmap
g.DrawString(s, ff, Brushes.Black, r, Format);
//dispose of the font so its not leaking memory
ff.Dispose();
Format.Dispose();
}
}
return i;
}
The problem is that this code looks ugly and its kind of slow as well. So I suppose I was just wondering if there was a better way to do this, some sort of function call or property I had missed somewhere when trying to make this all work, since I've managed to get the rest of the programs bitmap manipulation to a rather clean state, its just this, which looks kinda awful.
Thankyou in advance for any help given on this matter.