Add new font search criterea.
This commit is contained in:
parent
bc3dcff3ea
commit
ccb0c6ffe7
240
Quik/Media/Font/FontFace.cs
Normal file
240
Quik/Media/Font/FontFace.cs
Normal file
@ -0,0 +1,240 @@
|
||||
using System;
|
||||
using System.Net.WebSockets;
|
||||
using System.Text;
|
||||
using Quik.Media.Font;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
9
Quik/Media/Font/FontSlant.cs
Normal file
9
Quik/Media/Font/FontSlant.cs
Normal file
@ -0,0 +1,9 @@
|
||||
namespace Quik.Media.Font
|
||||
{
|
||||
public enum FontSlant
|
||||
{
|
||||
Normal = 0,
|
||||
Italic = 1,
|
||||
Oblique = 2,
|
||||
}
|
||||
}
|
18
Quik/Media/Font/FontStretch.cs
Normal file
18
Quik/Media/Font/FontStretch.cs
Normal file
@ -0,0 +1,18 @@
|
||||
namespace Quik.Media.Font
|
||||
{
|
||||
/// <summary>
|
||||
/// Enumeration of font stretch values.
|
||||
/// </summary>
|
||||
public enum FontStretch
|
||||
{
|
||||
UltraCondensed = 500,
|
||||
ExtraCondensed = 625,
|
||||
Condensed = 750,
|
||||
SemiCondensed = 875,
|
||||
Normal = 1000,
|
||||
SemiExpanded = 1125,
|
||||
Expanded = 1250,
|
||||
ExtraExpanded = 1500,
|
||||
UltraExpanded = 2000,
|
||||
}
|
||||
}
|
22
Quik/Media/Font/FontWeight.cs
Normal file
22
Quik/Media/Font/FontWeight.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System;
|
||||
|
||||
namespace Quik.Media.Font
|
||||
{
|
||||
public enum FontWeight
|
||||
{
|
||||
_100 = 100,
|
||||
_200 = 200,
|
||||
_300 = 300,
|
||||
_400 = 400,
|
||||
_500 = 500,
|
||||
_600 = 600,
|
||||
_700 = 700,
|
||||
_800 = 800,
|
||||
_900 = 900,
|
||||
|
||||
Thin = _100,
|
||||
Normal = _400,
|
||||
Bold = _700,
|
||||
Heavy = _900,
|
||||
}
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Quik.Media
|
||||
{
|
||||
public struct FontInfo : IEquatable<FontInfo>
|
||||
{
|
||||
public string Family { get; }
|
||||
public FontStyle Style { get; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"{Family} {Style}";
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return Family.GetHashCode() ^
|
||||
(Style.GetHashCode() * 3976061);
|
||||
}
|
||||
|
||||
public static bool operator==(FontInfo a, FontInfo b)
|
||||
{
|
||||
return (a.Style == b.Style) &&
|
||||
(a.Family == a.Family);
|
||||
}
|
||||
|
||||
public static bool operator!=(FontInfo a, FontInfo b)
|
||||
{
|
||||
return (a.Style != b.Style) ||
|
||||
(a.Family != b.Family);
|
||||
}
|
||||
|
||||
public bool Equals(FontInfo other)
|
||||
{
|
||||
return this == other;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return (obj.GetType() == typeof(FontInfo)) &&
|
||||
this == (FontInfo)obj;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,14 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Quik.Media
|
||||
{
|
||||
[Flags]
|
||||
public enum FontStyle
|
||||
{
|
||||
Italic = 1 << 0,
|
||||
Bold = 1 << 1,
|
||||
|
||||
Normal = 0,
|
||||
BoldItalic = Italic | Bold,
|
||||
}
|
||||
}
|
@ -1,4 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Quik.Media;
|
||||
using Quik.Media.Font;
|
||||
|
||||
namespace Quik.Media
|
||||
{
|
||||
@ -7,9 +10,11 @@ namespace Quik.Media
|
||||
/// </summary>
|
||||
public abstract class QFont : IDisposable
|
||||
{
|
||||
public abstract FontInfo Info { get; }
|
||||
public string Family => Info.Family;
|
||||
public FontStyle Style => Info.Style;
|
||||
public abstract FontFace Face { get; }
|
||||
public string Family => Face.Family;
|
||||
public FontSlant Slant => Face.Slant;
|
||||
public FontWeight Weight => Face.Weight;
|
||||
public FontStretch Stretch => Face.Stretch;
|
||||
|
||||
public abstract bool HasRune(int rune);
|
||||
public abstract QFontPage RasterizePage(int codepage, float size, in FontRasterizerOptions options);
|
||||
|
@ -10,11 +10,6 @@ namespace Quik.Media
|
||||
/// </summary>
|
||||
public int Rune { get; }
|
||||
|
||||
// /// <summary>
|
||||
// /// Location of the glyph on the atlas.
|
||||
// /// </summary>
|
||||
// public QRectangle Location { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Size of the glyph in units.
|
||||
/// </summary>
|
||||
@ -37,14 +32,12 @@ namespace Quik.Media
|
||||
|
||||
public QGlyphMetrics(
|
||||
int character,
|
||||
// QRectangle location,
|
||||
QVec2 size,
|
||||
QVec2 horizontalBearing,
|
||||
QVec2 verticalBearing,
|
||||
QVec2 advance)
|
||||
{
|
||||
Rune = character;
|
||||
// Location = location;
|
||||
Size = size;
|
||||
HorizontalBearing = horizontalBearing;
|
||||
VerticalBearing = verticalBearing;
|
||||
|
54
Quik/PAL/IFontDatabase.cs
Normal file
54
Quik/PAL/IFontDatabase.cs
Normal file
@ -0,0 +1,54 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Quik.Media.Font;
|
||||
|
||||
namespace Quik.PAL
|
||||
{
|
||||
/// <summary>
|
||||
/// Flags that effect font search criterea.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum FontMatchCriteria
|
||||
{
|
||||
None = 0,
|
||||
Family = 1 << 0,
|
||||
Slant = 1 << 1,
|
||||
Weight = 1 << 2,
|
||||
Stretch = 1 << 3,
|
||||
All = Family | Slant | Weight | Stretch,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// An abstraction over the system font database.
|
||||
/// </summary>
|
||||
public interface IFontDataBase
|
||||
{
|
||||
/// <summary>
|
||||
/// All the fonts installed in the system.
|
||||
/// </summary>
|
||||
IEnumerable<FontFace> All { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Search for the given font face.
|
||||
/// </summary>
|
||||
/// <param name="prototype">The font face prototype.</param>
|
||||
/// <param name="criteria">The match criteria</param>
|
||||
/// <returns>A list of fonts sorted by the closest match first.</returns>
|
||||
IEnumerable<FontFace> Search(FontFace prototype, FontMatchCriteria criteria = FontMatchCriteria.All);
|
||||
|
||||
/// <summary>
|
||||
/// Get the font face file info if it exists.
|
||||
/// </summary>
|
||||
/// <param name="face">The face to look for.</param>
|
||||
/// <returns>The file info if it exists.</returns>
|
||||
FileInfo FontFileInfo(FontFace face);
|
||||
|
||||
/// <summary>
|
||||
/// Open a font face.
|
||||
/// </summary>
|
||||
/// <param name="face">The font face to open.</param>
|
||||
/// <returns>The stream to the font face.</returns>
|
||||
Stream Open(FontFace face);
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Quik.Media;
|
||||
using Quik.Typography;
|
||||
using Quik.Media.Font;
|
||||
|
||||
namespace Quik
|
||||
{
|
||||
@ -109,9 +109,9 @@ namespace Quik
|
||||
set => this["list-marker-position"] = value;
|
||||
}
|
||||
|
||||
public QuikTexture ListMarkerImage
|
||||
public QImage ListMarkerImage
|
||||
{
|
||||
get => (QuikTexture)this["list-marker-image"];
|
||||
get => (QImage)this["list-marker-image"];
|
||||
set => this["list-marker-image"] = value;
|
||||
}
|
||||
|
||||
@ -127,9 +127,9 @@ namespace Quik
|
||||
set => this["stroke-color"] = value;
|
||||
}
|
||||
|
||||
public FontInfo Font
|
||||
public FontFace Font
|
||||
{
|
||||
get => (FontInfo)this["font"];
|
||||
get => (FontFace)this["font"];
|
||||
set => this["font"] = value;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user