In windows application(C#), When draw string using DrawString function of System.Drawing.Graphics class. But values are not properly aligned with other values though X and Y coordinates are the same. It behaves differently for different fonts with different font sizes. I have considered an internal leading and deduct it from Y coordinate but still is not working for all font types.
In my example, I want all text part to be top-aligned with the horizontal line. But for different fonts and font size, It is not aligned properly. It is working for first font(Avenir Black) but not for others.
Below is the code I am using to generate this printed document:
static void PrintDocument(string filePath)
{
// Create new document
PrintDocument pd = new PrintDocument();
pd.PrintPage += new PrintPageEventHandler(delegate (Object sender, PrintPageEventArgs e)
{
//e.Graphics.Clear(Color.White);
var Canvas = e.Graphics;
var rectF = new RectangleF(0f, 100, 1000, 78.74016f);
Pen p = new Pen(Color.Black);
p.Width = 1 / 2;
p.DashStyle = DashStyle.Solid;
Canvas.DrawLine(p, rectF.X, rectF.Y, rectF.X + rectF.Width, rectF.Y);
rectF = new RectangleF(0f, 100, 250, 78.74016f);
DrawPrice(Canvas, "Avenir Black", ref rectF);
rectF.X += 20;
rectF.Y = 100;
DrawPrice(Canvas, "Arial", ref rectF);
rectF.X += 20;
rectF.Y = 100;
DrawPrice(Canvas, "Calibri", ref rectF);
rectF.X += 20;
rectF.Y = 100;
DrawPrice(Canvas, "Times New Roman", ref rectF);
});
pd.Print();
Process.Start(filePath);
}
private static void DrawPrice(Graphics Canvas, string fontName, ref RectangleF rectF)
{
StringFormat format = new StringFormat();
format.Alignment = StringAlignment.Center;
format.LineAlignment = StringAlignment.Center;
var superFont = new Font(fontName, 20, new FontStyle());
var font = new Font(fontName, 61, new FontStyle());
Brush brush = new SolidBrush(Color.FromName("black"));
var currencySymbol = "$";
var mainPrice = "29";
var cents = "50";
var superFontMetrics = FontInfo(Canvas, superFont, GraphicsUnit.Point);
var fontMetrics = FontInfo(Canvas, font, GraphicsUnit.Point);
var symbolSize = Canvas.MeasureString(currencySymbol, superFont, rectF.Size, format);
var centsSize = Canvas.MeasureString(cents, superFont, rectF.Size, format);
var dollarSize = Canvas.MeasureString(mainPrice, font, rectF.Size, format);
Canvas.DrawString(currencySymbol, superFont, brush, new RectangleF(rectF.X, rectF.Y - superFontMetrics.InternalLeading, symbolSize.Width, symbolSize.Height), format);
rectF.X += symbolSize.Width;
Canvas.DrawString(mainPrice, font, brush, new RectangleF(rectF.X, rectF.Y, dollarSize.Width, rectF.Height), format);
var mainPriceX = rectF.X + (dollarSize.Width / 2);
rectF.X += dollarSize.Width;
Canvas.DrawString(cents, superFont, brush, new RectangleF(rectF.X, rectF.Y - superFontMetrics.InternalLeading, centsSize.Width, centsSize.Height), format);
rectF.Y += rectF.Height;
rectF.X += centsSize.Width;
var titleFont = new Font(fontName, 5, new FontStyle());
var titleTextSize = Canvas.MeasureString(fontName, titleFont, rectF.Size, format);
Canvas.DrawString(fontName, titleFont, brush, new RectangleF(mainPriceX, rectF.Y, titleTextSize.Width, titleTextSize.Height), format);
}
public static FontMetrics FontInfo(Graphics gr, Font font, GraphicsUnit toUnit)
{
FontMetrics metrics = new FontMetrics();
float em_height = font.FontFamily.GetEmHeight(font.Style);
metrics.EmHeight = ConvertUnits(gr, font.Size, font.Unit, toUnit);
float design_to_points = metrics.EmHeight / em_height;
metrics.Ascent = design_to_points * font.FontFamily.GetCellAscent(font.Style);
metrics.Descent = design_to_points * font.FontFamily.GetCellDescent(font.Style);
metrics.CellHeight = metrics.Ascent + metrics.Descent;
metrics.InternalLeading = metrics.CellHeight - metrics.EmHeight;
metrics.LineSpacing = design_to_points * font.FontFamily.GetLineSpacing(font.Style);
metrics.ExternalLeading = metrics.LineSpacing - metrics.CellHeight;
return metrics;
}