270 lines
9.1 KiB
C#
270 lines
9.1 KiB
C#
// Copyright (c) Six Labors.
|
|
// Licensed under the Six Labors Split License.
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Diagnostics;
|
|
using SixLabors.Fonts.Tables.AdvancedTypographic;
|
|
using SixLabors.Fonts.Unicode;
|
|
using static SixLabors.Fonts.Unicode.Resources.IndicShapingData;
|
|
|
|
namespace SixLabors.Fonts {
|
|
/// <summary>
|
|
/// Contains supplementary data that allows the shaping of glyphs.
|
|
/// </summary>
|
|
[DebuggerDisplay("{DebuggerDisplay,nq}")]
|
|
internal class GlyphShapingData
|
|
{
|
|
private ushort glyphId;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="GlyphShapingData"/> class.
|
|
/// </summary>
|
|
/// <param name="textRun">The text run.</param>
|
|
public GlyphShapingData(TextRun textRun) => this.TextRun = textRun;
|
|
|
|
/// <summary>
|
|
/// Initializes a new instance of the <see cref="GlyphShapingData"/> class.
|
|
/// </summary>
|
|
/// <param name="data">The data to copy properties from.</param>
|
|
/// <param name="clearFeatures">Whether to clear features.</param>
|
|
public GlyphShapingData(GlyphShapingData data, bool clearFeatures = false)
|
|
{
|
|
this.GlyphId = data.GlyphId;
|
|
this.CodePoint = data.CodePoint;
|
|
this.CodePointCount = data.CodePointCount;
|
|
this.Direction = data.Direction;
|
|
this.TextRun = data.TextRun;
|
|
this.LigatureId = data.LigatureId;
|
|
this.IsLigated = data.IsLigated;
|
|
this.LigatureComponent = data.LigatureComponent;
|
|
this.MarkAttachment = data.MarkAttachment;
|
|
this.CursiveAttachment = data.CursiveAttachment;
|
|
this.IsSubstituted = data.IsSubstituted;
|
|
this.IsDecomposed = data.IsDecomposed;
|
|
this.IsPlaceholder = data.IsPlaceholder;
|
|
this.BidiRun = data.BidiRun;
|
|
this.IsPositioned = data.IsPositioned;
|
|
this.IsKerned = data.IsKerned;
|
|
|
|
if (data.UniversalShapingEngineInfo != null)
|
|
{
|
|
this.UniversalShapingEngineInfo = new(
|
|
data.UniversalShapingEngineInfo.Category,
|
|
data.UniversalShapingEngineInfo.SyllableType,
|
|
data.UniversalShapingEngineInfo.Syllable);
|
|
}
|
|
|
|
if (data.IndicShapingEngineInfo != null)
|
|
{
|
|
this.IndicShapingEngineInfo = new(
|
|
data.IndicShapingEngineInfo.Category,
|
|
data.IndicShapingEngineInfo.Position,
|
|
data.IndicShapingEngineInfo.SyllableType,
|
|
data.IndicShapingEngineInfo.Syllable);
|
|
}
|
|
|
|
if (!clearFeatures)
|
|
{
|
|
this.Features.AddRange(data.Features);
|
|
foreach (Tag tag in data.EnabledFeatureTags)
|
|
{
|
|
this.EnabledFeatureTags.Add(tag);
|
|
}
|
|
}
|
|
|
|
foreach (Tag feature in data.AppliedFeatures)
|
|
{
|
|
this.AppliedFeatures.Add(feature);
|
|
}
|
|
|
|
this.Bounds = data.Bounds;
|
|
this.CachedShapingClass = data.CachedShapingClass;
|
|
this.ShapingClassCacheKey = data.ShapingClassCacheKey;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the glyph id. Setting this value invalidates the cached shaping class.
|
|
/// </summary>
|
|
public ushort GlyphId
|
|
{
|
|
get => this.glyphId;
|
|
set
|
|
{
|
|
if (this.glyphId != value)
|
|
{
|
|
this.glyphId = value;
|
|
this.ShapingClassCacheKey = -1;
|
|
}
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the cached glyph shaping class, avoiding repeated GDEF lookups.
|
|
/// </summary>
|
|
internal GlyphShapingClass CachedShapingClass { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the cache key for <see cref="CachedShapingClass"/>.
|
|
/// A value of <c>-1</c> indicates the cache is invalid. Valid entries store the glyph id.
|
|
/// </summary>
|
|
internal int ShapingClassCacheKey { get; set; } = -1;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the leading codepoint.
|
|
/// </summary>
|
|
public CodePoint CodePoint { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the codepoint count represented by this glyph.
|
|
/// </summary>
|
|
public int CodePointCount { get; set; } = 1;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the text direction.
|
|
/// </summary>
|
|
public TextDirection Direction { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the text run this glyph belongs to.
|
|
/// </summary>
|
|
public TextRun TextRun { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the id of any ligature this glyph is a member of.
|
|
/// </summary>
|
|
public int LigatureId { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether the glyph is ligated.
|
|
/// </summary>
|
|
public bool IsLigated { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the ligature component index of the glyph.
|
|
/// </summary>
|
|
public int LigatureComponent { get; set; } = -1;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the index of any mark attachment.
|
|
/// </summary>
|
|
public int MarkAttachment { get; set; } = -1;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the index of any cursive attachment.
|
|
/// </summary>
|
|
public int CursiveAttachment { get; set; } = -1;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the collection of features.
|
|
/// </summary>
|
|
public List<TagEntry> Features { get; set; } = [];
|
|
|
|
/// <summary>
|
|
/// Gets the set of feature tags that are currently enabled, maintained
|
|
/// in sync with <see cref="Features"/> for O(1) lookup.
|
|
/// </summary>
|
|
internal HashSet<Tag> EnabledFeatureTags { get; } = [];
|
|
|
|
/// <summary>
|
|
/// Gets or sets the collection of applied features.
|
|
/// </summary>
|
|
public HashSet<Tag> AppliedFeatures { get; set; } = [];
|
|
|
|
/// <summary>
|
|
/// Gets or sets the shaping bounds.
|
|
/// </summary>
|
|
public GlyphShapingBounds Bounds { get; set; } = new(0, 0, 0, 0);
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this glyph is the result of a substitution.
|
|
/// </summary>
|
|
public bool IsSubstituted { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this glyph is the result of a decomposition substitution
|
|
/// </summary>
|
|
public bool IsDecomposed { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this glyph represents an inline placeholder.
|
|
/// </summary>
|
|
public bool IsPlaceholder { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the bidi run assigned to an inline placeholder.
|
|
/// </summary>
|
|
public BidiRun BidiRun { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this glyph has been positioned.
|
|
/// </summary>
|
|
public bool IsPositioned { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets a value indicating whether this glyph has been kerned.
|
|
/// </summary>
|
|
public bool IsKerned { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the universal shaping information.
|
|
/// </summary>
|
|
public UniversalShapingEngineInfo? UniversalShapingEngineInfo { get; set; }
|
|
|
|
/// <summary>
|
|
/// Gets or sets the Indic shaping information.
|
|
/// </summary>
|
|
public IndicShapingEngineInfo? IndicShapingEngineInfo { get; set; }
|
|
|
|
private string DebuggerDisplay
|
|
=> FormattableString
|
|
.Invariant($" {this.GlyphId} : {this.CodePoint.ToDebuggerDisplay()} : {CodePoint.GetScriptClass(this.CodePoint)} : {this.Direction} : {this.TextRun.TextAttributes} : {this.LigatureId} : {this.LigatureComponent} : {this.IsDecomposed}");
|
|
|
|
internal string ToDebuggerDisplay() => this.DebuggerDisplay;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Represents information required for universal shaping.
|
|
/// </summary>
|
|
internal class UniversalShapingEngineInfo
|
|
{
|
|
public UniversalShapingEngineInfo(string category, string syllableType, int syllable)
|
|
{
|
|
this.Category = category;
|
|
this.SyllableType = syllableType;
|
|
this.Syllable = syllable;
|
|
}
|
|
|
|
public string Category { get; set; }
|
|
|
|
public string SyllableType { get; set; }
|
|
|
|
public int Syllable { get; set; }
|
|
}
|
|
|
|
internal class IndicShapingEngineInfo
|
|
{
|
|
public IndicShapingEngineInfo(
|
|
Categories category,
|
|
Positions position,
|
|
string syllableType,
|
|
int syllable)
|
|
{
|
|
this.Category = category;
|
|
this.Position = position;
|
|
this.SyllableType = syllableType;
|
|
this.Syllable = syllable;
|
|
}
|
|
|
|
public Categories Category { get; set; }
|
|
|
|
public MyanmarCategories MyanmarCategory => (MyanmarCategories)this.Category;
|
|
|
|
public Positions Position { get; set; }
|
|
|
|
public string SyllableType { get; set; }
|
|
|
|
public int Syllable { get; set; }
|
|
}
|
|
}
|