我需要打印數字,其中中間的一些數字通過增加字體大小和重量來強調。在下面的例子中,456
被強調。GDI +在基線上繪製不同尺寸的文字有1px的問題
的字體和所使用的兩種尺寸是用戶可配置的。
當前代碼使用三次調用Graphics.DrawString(...)
來完成此操作。
我遇到的問題是,與大多數的字體,我看到的off-by-1像素的問題(相對於灰線,該456
坐在一個額外的像素高於其他數字):
我附加了一些調試轉儲(鮑勃鮑威爾公式)爲我的文章底部的各種字體。其他技術產生了類似的結果。
爲了在通用基線上打印文本,需要計算特定Font
的基線偏移量。
首先,MSDN代碼:http://msdn.microsoft.com/en-us/library/xwf9s90b(v=vs.80).aspx
ascent = fontFamily.GetCellAscent(FontStyle.Regular);
ascentPixel = font.Size * ascent/fontFamily.GetEmHeight(FontStyle.Regular)
最後,從鮑勃·鮑威爾郵編:http://www.bobpowell.net/formattingtext.htm
這裏是我的,我用三種技術嘗試繪製方法:
private void DrawOnBaseline(Graphics g, string text, FontWithBaseline fwb, Brush brush, float x, float y) {
g.DrawString(text, fwb.Font, brush, x, y - fwb.Baseline, StringFormat.GenericTypographic);
}
凡FontWithBaseline
一個簡單的字體具有其各自的基準計算相關聯:
public class FontWithBaseline {
private Font m_font;
private float m_baseline;
public FontWithBaseline(Font font) {
m_font = font;
m_baseline = CalculateBaseline(font);
}
public Font Font { get { return m_font; } }
public float Baseline { get { return m_baseline; } }
private static float CalculateBaseline(Font font) {
... // I've tried the three formulae here.
}
}
我還沒有嘗試Graphics.TestRenderingHint
還。那是不可思議的醬汁? 我錯過了什麼?是否有我可以使用的替代API,在那裏我打電話來向耗材提供基線的Y座標?
更新1
我插我的代碼以@LarsTech。他正在做一個微妙的不同;他正在添加0.5f
。但是,即使這個變體也不能解決這個問題。下面的代碼:
protected override void OnPaint(PaintEventArgs e) {
base.OnPaint(e);
TryLarsTechnique(e);
}
private void TryLarsTechnique(PaintEventArgs e) {
base.OnPaint(e);
Graphics g = e.Graphics;
GraphicsContainer c = g.BeginContainer();
g.Clear(Color.White);
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
Font small = new Font("Arial", 13, FontStyle.Regular, GraphicsUnit.Pixel);
Font large = new Font("Arial", 17, FontStyle.Bold, GraphicsUnit.Pixel);
int x = 100;
int y = 100;
x += DrawLars(g, "12.3", small, x, y);
x += DrawLars(g, "456", large, x, y);
x += DrawLars(g, "8", small, x, y);
g.EndContainer(c);
}
// returns width of text
private int DrawLars(Graphics g, string text, Font font, int x, int y) {
float offset = font.SizeInPoints/
font.FontFamily.GetEmHeight(font.Style) *
font.FontFamily.GetCellAscent(font.Style);
float pixels = g.DpiY/72f * offset;
int numTop = y - (int)(pixels + 0.5f);
TextRenderer.DrawText(g, text, font, new Point(x, numTop), Color.Black, Color.Empty, TextFormatFlags.NoPadding);
return TextRenderer.MeasureText(g, text, font, Size.Empty, TextFormatFlags.NoPadding).Width;
}
我想知道,是否指定使用GraphicsUnit.Pixel
字體大小是罪魁禍首。也許有一種方法可以找到任何特定字體的首選大小?
更新2
我試過在點而不是像素指定的字體大小,而這並不能完全解決問題,無論是。請注意,在我的情況下,僅使用整點大小不是一種選擇。爲了查看這是否可能,我在Windows寫字板上試了這個。尺寸使用96 dpi(根據定義每英寸72點),17px,13px翻譯爲12.75和9.75。下面是輸出比較:
通知的較小的字體是如何在像素級相同的高度。所以寫字板以某種方式設法得到這個正確的數字,而不需要將字體大小舍入爲方便的值。
感謝。我已更新我的問題以添加我的代碼併合並您的方法。 '0.5f'的加入是新東西。唉,我仍然看到這個問題。嘗試使用17像素+ 13像素的字體大小;我懷疑你也會看到這個問題。 – 2012-02-01 19:14:01
@DilumRanatunga的'0.5f'從鮑勃·鮑威爾的例子就是直(請參閱鏈接頁面的底部)。是的,使用'GraphicsUnit.Pixel'可以使它像素化。不知道爲什麼,但離開它再次拉回來。我相信'GraphicsUnit.Point'是默認的,當使用它時,它也起作用。 – LarsTech 2012-02-01 19:29:05
@DilumRanatunga如果我改變代碼GraphicsUnit.Pixel然後用'12.75f'和'9.75'作爲我的字體大小,它線條正確。我不認爲* WorkPad正在進行四捨五入,我認爲它只是爲了方便而向用戶顯示一個整數。我可能錯了。 Visual Studio設計顯示'默認'Microsoft無Serif'字體8.25pt',但如果你點擊對話框更改字體,你只看到整數在下拉。不知道這是否有助於你。 – LarsTech 2012-02-01 21:06:01