using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using Svg.DataTypes;
using System.Text.RegularExpressions;
namespace Svg
{
internal class FontData
{
private SvgUnit _fontSize;
private SvgFontWeight _fontWeight = SvgFontWeight.inherit;
private string _font;
private string _fontFamily;
private const string DefaultFontFamily = "Times New Roman";
public FontData()
{
this._fontSize = new SvgUnit(0.0f);
}
///
/// Indicates which font family is to be used to render the text.
///
public virtual string FontFamily
{
get { return this._fontFamily ?? DefaultFontFamily; }
set
{
this._fontFamily = ValidateFontFamily(value);
}
}
///
/// Refers to the size of the font from baseline to baseline when multiple lines of text are set solid in a multiline layout environment.
///
public virtual SvgUnit FontSize
{
get { return this._fontSize; }
set { this._fontSize = value; }
}
///
/// Refers to the boldness of the font.
///
public virtual SvgFontWeight FontWeight
{
get { return this._fontWeight; }
set { this._fontWeight = value; }
}
///
/// Set all font information.
///
public string Font
{
get { return this._font; }
set
{
var parts = value.Split(',');
foreach (var part in parts)
{
//This deals with setting font size. Looks for either px or pt style="font: bold 16px/normal 'trebuchet ms', verdana, sans-serif;"
Regex rx = new Regex(@"(\d+)+(?=pt|px)");
var res = rx.Match(part);
if (res.Success)
{
int fontSize = 10;
int.TryParse(res.Value, out fontSize);
this.FontSize = new SvgUnit((float)fontSize);
}
//this assumes "bold" has spaces around it. e.g.: style="font: bold 16px/normal
rx = new Regex(@"\sbold\s");
res = rx.Match(part);
if (res.Success)
{
this.FontWeight = SvgFontWeight.bold;
}
}
var font = ValidateFontFamily(value);
this._fontFamily = font;
this._font = font; //not sure this is used?
}
}
public Font GetFont(ISvgStylable owner, FontData inherit)
{
float fontSize = this.FontSize.ToDeviceValue(owner);
if (fontSize == 0.0f)
{
fontSize = (inherit == null ? 1.0f : inherit.FontSize.ToDeviceValue(owner));
fontSize = (fontSize == 0.0f ? 1.0f : fontSize);
}
var baseWeight = (_fontWeight == SvgFontWeight.inherit && inherit != null ? inherit.FontWeight : _fontWeight);
var fontWeight = (baseWeight == SvgFontWeight.bold ? FontStyle.Bold : FontStyle.Regular);
var family = _fontFamily ?? (inherit == null ? DefaultFontFamily : inherit.FontFamily);
return new Font(family, fontSize, fontWeight, GraphicsUnit.Pixel);
}
private static string ValidateFontFamily(string fontFamilyList)
{
// Split font family list on "," and then trim start and end spaces and quotes.
var fontParts = fontFamilyList.Split(new[] { ',' }).Select(fontName => fontName.Trim(new[] { '"', ' ', '\'' }));
var families = System.Drawing.FontFamily.Families;
// Find a the first font that exists in the list of installed font families.
//styles from IE get sent through as lowercase.
foreach (var f in fontParts.Where(f => families.Any(family => family.Name.ToLower() == f.ToLower())))
{
return f;
}
// No valid font family found from the list requested.
return null;
}
public override bool Equals(object obj)
{
var thisType = obj as FontData;
if (thisType != null) return Equals(thisType);
return base.Equals(obj);
}
public bool Equals(FontData obj)
{
return obj._fontFamily == this._fontFamily && obj._fontSize == this._fontSize && obj._fontWeight == this._fontWeight;
}
public override int GetHashCode()
{
return (this._fontFamily == null ? 0 : this._fontFamily.GetHashCode()) ^
(this._fontSize == null ? 0 : this._fontSize.GetHashCode()) ^
this._fontWeight.GetHashCode();
}
}
}