238 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			238 lines
		
	
	
		
			7.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
| using System;
 | |
| using System.Text;
 | |
| 
 | |
| namespace Quik.Media.Font
 | |
| {
 | |
|     public readonly struct FontFace : IEquatable<FontFace>
 | |
|     {
 | |
|         public string Family { get; }
 | |
|         public FontSlant Slant { get; }
 | |
|         public FontWeight Weight { get; }
 | |
|         public FontStretch Stretch { get; }
 | |
| 
 | |
|         public FontFace(string family, FontSlant slant, FontWeight weight, FontStretch stretch)
 | |
|         {
 | |
|             Family = family;
 | |
|             Slant = slant;
 | |
|             Weight = weight;
 | |
|             Stretch = stretch;
 | |
|         }
 | |
| 
 | |
|         public override string ToString()
 | |
|         {
 | |
|             StringBuilder builder = new StringBuilder(Family);
 | |
|             
 | |
|             if (Slant != FontSlant.Normal)
 | |
|             {
 | |
|                 builder.Append(' ');
 | |
|                 builder.Append(Slant);
 | |
|             }
 | |
|             if (Stretch != FontStretch.Normal)
 | |
|             {
 | |
|                 builder.Append(' ');
 | |
|                 builder.Append(Stretch);
 | |
|             }
 | |
|             if (Weight != FontWeight.Normal)
 | |
|             {
 | |
|                 builder.Append(' ');
 | |
|                 builder.Append(Weight);
 | |
|             }
 | |
| 
 | |
|             if (Slant == FontSlant.Normal &&
 | |
|                 Stretch == FontStretch.Normal &&
 | |
|                 Weight == FontWeight.Normal)
 | |
|             {
 | |
|                 builder.Append(" Regular");
 | |
|             }
 | |
| 
 | |
|             return builder.ToString();
 | |
|         }
 | |
| 
 | |
|         public override int GetHashCode()
 | |
|         {
 | |
|             return HashCode.Combine(Family, Slant, Weight, Stretch);
 | |
|         }
 | |
| 
 | |
|         public static bool operator==(FontFace a, FontFace b)
 | |
|         {
 | |
|             return  (a.Slant == b.Slant) &&
 | |
|                     (a.Weight == b.Weight) &&
 | |
|                     (a.Stretch == b.Stretch) &&
 | |
|                     (a.Family == a.Family);
 | |
|         }
 | |
| 
 | |
|         public static bool operator!=(FontFace a, FontFace b)
 | |
|         {
 | |
|             return  (a.Slant != b.Slant) ||
 | |
|                     (a.Weight != b.Weight) ||
 | |
|                     (a.Stretch != b.Stretch) ||
 | |
|                     (a.Family != b.Family);
 | |
|         }
 | |
| 
 | |
|         public bool Equals(FontFace other)
 | |
|         {
 | |
|             return this == other;
 | |
|         }
 | |
| 
 | |
|         public override bool Equals(object obj)
 | |
|         {
 | |
|             return  (obj.GetType() == typeof(FontFace)) &&
 | |
|                     this == (FontFace)obj;
 | |
|         }
 | |
| 
 | |
|         public static FontFace Parse(string family, string style)
 | |
|         {
 | |
|             FontSlant slant = FontSlant.Normal;
 | |
|             FontWeight weight = FontWeight.Normal;
 | |
|             FontStretch stretch = FontStretch.Normal;
 | |
| 
 | |
|             string[] tokens = style.Split(' ');
 | |
| 
 | |
|             foreach (string token in tokens)
 | |
|             {
 | |
|                 /**/ if (TryParseSlant(token, out FontSlant xslant)) slant = xslant;
 | |
|                 else if (TryParseWeight(token, out FontWeight xweight)) weight = xweight;
 | |
|                 else if (TryParseStretch(token, out FontStretch xstretch)) stretch = xstretch;
 | |
|             }
 | |
| 
 | |
|             return new FontFace(family, slant, weight, stretch);
 | |
|         }
 | |
| 
 | |
|         public static FontFace Parse(string face)
 | |
|         {
 | |
|             StringBuilder family = new StringBuilder();
 | |
|             FontSlant slant = FontSlant.Normal;
 | |
|             FontWeight weight = FontWeight.Normal;
 | |
|             FontStretch stretch = FontStretch.Normal;
 | |
| 
 | |
|             string[] tokens = face.Split(' ');
 | |
|             foreach (string token in tokens)
 | |
|             {
 | |
|                 string xtoken = token.ToLower();
 | |
| 
 | |
|                 if (xtoken == "regular" || xtoken == "normal")
 | |
|                 {
 | |
|                     continue;
 | |
|                 }
 | |
|                 else if (TryParseSlant(xtoken, out FontSlant xslant)) slant = xslant;
 | |
|                 else if (TryParseWeight(xtoken, out FontWeight xweight)) weight = xweight;
 | |
|                 else if (TryParseStretch(xtoken, out FontStretch xstretch)) stretch = xstretch;
 | |
|                 else
 | |
|                 {
 | |
|                     family.Append(token);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             return new FontFace(family.ToString(), slant, weight, stretch);
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Try to convert a token that represents a font slant into its enum.
 | |
|         /// </summary>
 | |
|         /// <param name="token">The token to interpret.</param>
 | |
|         /// <param name="slant">The resulting slant.</param>
 | |
|         /// <returns>True if it matched any.</returns>
 | |
|         public static bool TryParseSlant(string token, out FontSlant slant)
 | |
|         {
 | |
|             switch (token.ToLower())
 | |
|             {
 | |
|                 case "italic":
 | |
|                     slant = FontSlant.Italic;
 | |
|                     return true;
 | |
|                 case "oblique":
 | |
|                     slant = FontSlant.Oblique;
 | |
|                     return true;
 | |
|                 default:
 | |
|                     slant = FontSlant.Normal;
 | |
|                     return false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Try to convert a token that represents a font weight into its enum.
 | |
|         /// </summary>
 | |
|         /// <param name="token">The token to interpret.</param>
 | |
|         /// <param name="weight">The resulting weight.</param>
 | |
|         /// <returns>True if it matched any.</returns>
 | |
|         public static bool TryParseWeight(string token, out FontWeight weight)
 | |
|         {
 | |
|             switch (token.ToLower())
 | |
|             {
 | |
|                 case "thin":
 | |
|                     weight = FontWeight.Thin;
 | |
|                     return true;
 | |
|                 case "extralight":
 | |
|                 case "ultralight":
 | |
|                     weight = FontWeight._200;
 | |
|                     return true;
 | |
|                 case "light":
 | |
|                 case "demilight":
 | |
|                 case "semilight":
 | |
|                     weight = FontWeight._300;
 | |
|                     return true;
 | |
|                 case "demibold":
 | |
|                 case "semibold":
 | |
|                     weight = FontWeight._600;
 | |
|                     return true;
 | |
|                 case "bold":
 | |
|                     weight = FontWeight._700;
 | |
|                     return true;
 | |
|                 case "extrabold":
 | |
|                 case "ultrabold":
 | |
|                     weight = FontWeight._800;
 | |
|                     return true;
 | |
|                 case "heavy":
 | |
|                 case "extrablack":
 | |
|                 case "black":
 | |
|                 case "ultrablack":
 | |
|                     weight = FontWeight._900;
 | |
|                     return true;
 | |
|                 default:
 | |
|                     weight = FontWeight.Normal;
 | |
|                     return false;
 | |
|             }
 | |
|         }
 | |
| 
 | |
|         /// <summary>
 | |
|         /// Try to convert a token that represents a font stretch into its enum.
 | |
|         /// </summary>
 | |
|         /// <param name="token">The token to interpret.</param>
 | |
|         /// <param name="stretch">The resulting stretch.</param>
 | |
|         /// <returns>True if it matched any.</returns>
 | |
|         public static bool TryParseStretch(string token, out FontStretch stretch)
 | |
|         {
 | |
|             switch (token.ToLower())
 | |
|             {
 | |
|                 case "ultracondensed":
 | |
|                     stretch = FontStretch.UltraCondensed;
 | |
|                     return true;
 | |
|                 case "extracondensed":
 | |
|                     stretch = FontStretch.ExtraCondensed;
 | |
|                     return true;
 | |
|                 case "condensed":
 | |
|                     stretch = FontStretch.Condensed;
 | |
|                     return true;
 | |
|                 case "semicondensed":
 | |
|                 case "demicondensed":
 | |
|                     stretch = FontStretch.SemiCondensed;
 | |
|                     return true;
 | |
|                 case "semiexpanded":
 | |
|                 case "demiexpanded":
 | |
|                     stretch = FontStretch.SemiExpanded;
 | |
|                     return true;
 | |
|                 case "expanded":
 | |
|                     stretch = FontStretch.Expanded;
 | |
|                     return true;
 | |
|                 case "extraexpanded":
 | |
|                     stretch = FontStretch.ExtraExpanded;
 | |
|                     return true;
 | |
|                 case "ultraexpanded":
 | |
|                     stretch = FontStretch.UltraExpanded;
 | |
|                     return true;
 | |
|                 default:
 | |
|                     stretch = FontStretch.Normal;
 | |
|                     return false;
 | |
|             }
 | |
|         }
 | |
|     }
 | |
| } |