Skip to content

Instantly share code, notes, and snippets.

@adamsmith
Created February 10, 2017 01:30
Show Gist options
  • Save adamsmith/2cd59c775b3768f6f811fe8f63e6b53d to your computer and use it in GitHub Desktop.
Save adamsmith/2cd59c775b3768f6f811fe8f63e6b53d to your computer and use it in GitHub Desktop.
C# FontStack
// License: public domain
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace CommonCode {
public static class FontStack {
static FontStack() {
DefaultAppFontFamily = GetFirstAvailableFontFamily(new string[] { "Segoe UI", "Calibri", "Verdana" });
//DefaultAppFontFamily = GetFirstAvailableFontFamily(new string[] { "Verdana" });
Log.Logger.Debug(string.Format("Using font family {0}", DefaultAppFontFamily.Name));
HeightTargetFontFamily = GetFirstAvailableFontFamily(new string[] { "Verdana" });
}
public static void SetFontFamilyForDescendents(Control control, Graphics g) {
if (DefaultAppFontFamily == null || HeightTargetFontFamily == null) {
return;
}
try {
foreach (Control child in control.Controls) {
if (child is ContainerControl) {
// don't change the fonts of container controls
// they will often have an AutoScaleMode that will change the size of the control depending on the
// font size.
} else {
if (DefaultAppFontFamily.IsStyleAvailable(child.Font.Style)) {
var newFont = new Font(DefaultAppFontFamily, child.Font.Size, child.Font.Style, child.Font.Unit);
// measure difference in font height
// some fonts like Calibri are noticible smaller, unfortunately
var newFamilyTestSize = MeasureRealFontSize(g, newFont);
var oldFamilyTestSize = MeasureRealFontSize(g, child.Font);
var sizeRatio = oldFamilyTestSize / newFamilyTestSize;
newFont = new Font(newFont.FontFamily, newFont.Size * sizeRatio, newFont.Style, newFont.Unit);
child.Font = newFont;
}
}
SetFontFamilyForDescendents(child, g);
}
} catch (Exception e) {
Log.Logger.ErrorException("Error setting font family of control's descendents", e);
}
}
private static FontFamily DefaultAppFontFamily { get; set; }
private static FontFamily HeightTargetFontFamily { get; set; }
private static float MeasureRealFontSize(Graphics g, Font font) {
var testString = "Test String";
using (var format = new StringFormat()) {
format.SetMeasurableCharacterRanges(new CharacterRange[] { new CharacterRange(0, testString.Length) });
using (var region = g.MeasureCharacterRanges(testString, font,
new RectangleF(PointF.Empty, new SizeF(1000, 1000)), format)[0]) {
var bounds = region.GetBounds(g);
return (float)Math.Sqrt(Math.Pow(bounds.Height, 2) + Math.Pow(bounds.Width, 2));
}
}
}
private static FontFamily GetFirstAvailableFontFamily(string[] fontFamilyStack) {
foreach (var fontFamily in fontFamilyStack) {
try {
return new FontFamily(fontFamily);
} catch {
Log.Logger.Debug(string.Format("Exception getting {0} font. Falling back to next default...", fontFamily));
}
}
return FontFamily.GenericSansSerif;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment