mirror of
https://github.com/goatcorp/Dalamud.git
synced 2025-12-12 10:17:22 +01:00
Expose CopyGlyphsAcrossFonts (#824)
This commit is contained in:
parent
9413755ee3
commit
d68b3a1845
4 changed files with 166 additions and 143 deletions
|
|
@ -7,6 +7,7 @@ using System.Text;
|
|||
|
||||
using Dalamud.Data;
|
||||
using Dalamud.Interface.Internal;
|
||||
using Dalamud.Utility;
|
||||
using ImGuiNET;
|
||||
using Lumina.Data.Files;
|
||||
using Serilog;
|
||||
|
|
@ -38,6 +39,9 @@ namespace Dalamud.Interface.GameFonts
|
|||
private readonly Dictionary<GameFontStyle, int> fontUseCounter = new();
|
||||
private readonly Dictionary<GameFontStyle, Dictionary<char, Tuple<int, FdtReader.FontTableEntry>>> glyphRectIds = new();
|
||||
|
||||
private bool isBetweenBuildFontsAndAfterBuildFonts = false;
|
||||
private bool isBuildingAsFallbackFontMode = false;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="GameFontManager"/> class.
|
||||
/// </summary>
|
||||
|
|
@ -110,65 +114,6 @@ namespace Dalamud.Interface.GameFonts
|
|||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills missing glyphs in target font from source font, if both are not null.
|
||||
/// </summary>
|
||||
/// <param name="source">Source font.</param>
|
||||
/// <param name="target">Target font.</param>
|
||||
/// <param name="missingOnly">Whether to copy missing glyphs only.</param>
|
||||
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
|
||||
/// <param name="rangeLow">Low codepoint range to copy.</param>
|
||||
/// <param name="rangeHigh">High codepoing range to copy.</param>
|
||||
public static void CopyGlyphsAcrossFonts(ImFontPtr? source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable, int rangeLow = 32, int rangeHigh = 0xFFFE)
|
||||
{
|
||||
if (!source.HasValue || !target.HasValue)
|
||||
return;
|
||||
|
||||
var scale = target.Value!.FontSize / source.Value!.FontSize;
|
||||
unsafe
|
||||
{
|
||||
var glyphs = (ImFontGlyphReal*)source.Value!.Glyphs.Data;
|
||||
for (int j = 0, j_ = source.Value!.Glyphs.Size; j < j_; j++)
|
||||
{
|
||||
var glyph = &glyphs[j];
|
||||
if (glyph->Codepoint < rangeLow || glyph->Codepoint > rangeHigh)
|
||||
continue;
|
||||
|
||||
var prevGlyphPtr = (ImFontGlyphReal*)target.Value!.FindGlyphNoFallback((ushort)glyph->Codepoint).NativePtr;
|
||||
if ((IntPtr)prevGlyphPtr == IntPtr.Zero)
|
||||
{
|
||||
target.Value!.AddGlyph(
|
||||
target.Value!.ConfigData,
|
||||
(ushort)glyph->Codepoint,
|
||||
glyph->X0 * scale,
|
||||
((glyph->Y0 - source.Value!.Ascent) * scale) + target.Value!.Ascent,
|
||||
glyph->X1 * scale,
|
||||
((glyph->Y1 - source.Value!.Ascent) * scale) + target.Value!.Ascent,
|
||||
glyph->U0,
|
||||
glyph->V0,
|
||||
glyph->U1,
|
||||
glyph->V1,
|
||||
glyph->AdvanceX * scale);
|
||||
}
|
||||
else if (!missingOnly)
|
||||
{
|
||||
prevGlyphPtr->X0 = glyph->X0 * scale;
|
||||
prevGlyphPtr->Y0 = ((glyph->Y0 - source.Value!.Ascent) * scale) + target.Value!.Ascent;
|
||||
prevGlyphPtr->X1 = glyph->X1 * scale;
|
||||
prevGlyphPtr->Y1 = ((glyph->Y1 - source.Value!.Ascent) * scale) + target.Value!.Ascent;
|
||||
prevGlyphPtr->U0 = glyph->U0;
|
||||
prevGlyphPtr->V0 = glyph->V0;
|
||||
prevGlyphPtr->U1 = glyph->U1;
|
||||
prevGlyphPtr->V1 = glyph->V1;
|
||||
prevGlyphPtr->AdvanceX = glyph->AdvanceX * scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rebuildLookupTable)
|
||||
target.Value!.BuildLookupTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Unscales fonts after they have been rendered onto atlas.
|
||||
/// </summary>
|
||||
|
|
@ -191,7 +136,7 @@ namespace Dalamud.Interface.GameFonts
|
|||
font->Descent /= fontScale;
|
||||
if (font->ConfigData != null)
|
||||
font->ConfigData->SizePixels /= fontScale;
|
||||
var glyphs = (ImFontGlyphReal*)font->Glyphs.Data;
|
||||
var glyphs = (Util.ImFontGlyphReal*)font->Glyphs.Data;
|
||||
for (int i = 0, i_ = font->Glyphs.Size; i < i_; i++)
|
||||
{
|
||||
var glyph = &glyphs[i];
|
||||
|
|
@ -223,15 +168,22 @@ namespace Dalamud.Interface.GameFonts
|
|||
|
||||
lock (this.syncRoot)
|
||||
{
|
||||
var prevValue = this.fontUseCounter.GetValueOrDefault(style, 0);
|
||||
var newValue = this.fontUseCounter[style] = prevValue + 1;
|
||||
needRebuild = (prevValue == 0) != (newValue == 0) && !this.fonts.ContainsKey(style);
|
||||
this.fontUseCounter[style] = this.fontUseCounter.GetValueOrDefault(style, 0) + 1;
|
||||
}
|
||||
|
||||
needRebuild = !this.fonts.ContainsKey(style);
|
||||
if (needRebuild)
|
||||
{
|
||||
Log.Information("[GameFontManager] Calling RebuildFonts because {0} has been requested.", style.ToString());
|
||||
this.interfaceManager.RebuildFonts();
|
||||
if (Service<InterfaceManager>.Get().IsBuildingFontsBeforeAtlasBuild && this.isBetweenBuildFontsAndAfterBuildFonts)
|
||||
{
|
||||
Log.Information("[GameFontManager] NewFontRef: Building {0} right now, as it is called while BuildFonts is already in progress yet atlas build has not been called yet.", style.ToString());
|
||||
this.EnsureFont(style);
|
||||
}
|
||||
else
|
||||
{
|
||||
Log.Information("[GameFontManager] NewFontRef: Calling RebuildFonts because {0} has been requested.", style.ToString());
|
||||
this.interfaceManager.RebuildFonts();
|
||||
}
|
||||
}
|
||||
|
||||
return new(this, style);
|
||||
|
|
@ -260,7 +212,7 @@ namespace Dalamud.Interface.GameFonts
|
|||
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
|
||||
public void CopyGlyphsAcrossFonts(ImFontPtr? source, GameFontStyle target, bool missingOnly, bool rebuildLookupTable)
|
||||
{
|
||||
GameFontManager.CopyGlyphsAcrossFonts(source, this.fonts[target], missingOnly, rebuildLookupTable);
|
||||
Util.CopyGlyphsAcrossFonts(source, this.fonts[target], missingOnly, rebuildLookupTable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -272,7 +224,7 @@ namespace Dalamud.Interface.GameFonts
|
|||
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
|
||||
public void CopyGlyphsAcrossFonts(GameFontStyle source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable)
|
||||
{
|
||||
GameFontManager.CopyGlyphsAcrossFonts(this.fonts[source], target, missingOnly, rebuildLookupTable);
|
||||
Util.CopyGlyphsAcrossFonts(this.fonts[source], target, missingOnly, rebuildLookupTable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -284,7 +236,7 @@ namespace Dalamud.Interface.GameFonts
|
|||
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
|
||||
public void CopyGlyphsAcrossFonts(GameFontStyle source, GameFontStyle target, bool missingOnly, bool rebuildLookupTable)
|
||||
{
|
||||
GameFontManager.CopyGlyphsAcrossFonts(this.fonts[source], this.fonts[target], missingOnly, rebuildLookupTable);
|
||||
Util.CopyGlyphsAcrossFonts(this.fonts[source], this.fonts[target], missingOnly, rebuildLookupTable);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -293,57 +245,20 @@ namespace Dalamud.Interface.GameFonts
|
|||
/// <param name="forceMinSize">Whether to load fonts in minimum sizes.</param>
|
||||
public void BuildFonts(bool forceMinSize)
|
||||
{
|
||||
unsafe
|
||||
{
|
||||
ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
|
||||
fontConfig.OversampleH = 1;
|
||||
fontConfig.OversampleV = 1;
|
||||
fontConfig.PixelSnapH = false;
|
||||
this.isBuildingAsFallbackFontMode = forceMinSize;
|
||||
this.isBetweenBuildFontsAndAfterBuildFonts = true;
|
||||
|
||||
var io = ImGui.GetIO();
|
||||
this.glyphRectIds.Clear();
|
||||
this.fonts.Clear();
|
||||
|
||||
this.glyphRectIds.Clear();
|
||||
this.fonts.Clear();
|
||||
|
||||
foreach (var style in this.fontUseCounter.Keys)
|
||||
{
|
||||
var rectIds = this.glyphRectIds[style] = new();
|
||||
|
||||
var fdt = this.fdts[(int)(forceMinSize ? style.FamilyWithMinimumSize : style.FamilyAndSize)];
|
||||
if (fdt == null)
|
||||
continue;
|
||||
|
||||
var font = io.Fonts.AddFontDefault(fontConfig);
|
||||
|
||||
this.fonts[style] = font;
|
||||
foreach (var glyph in fdt.Glyphs)
|
||||
{
|
||||
var c = glyph.Char;
|
||||
if (c < 32 || c >= 0xFFFF)
|
||||
continue;
|
||||
|
||||
var widthAdjustment = style.CalculateBaseWidthAdjustment(fdt, glyph);
|
||||
rectIds[c] = Tuple.Create(
|
||||
io.Fonts.AddCustomRectFontGlyph(
|
||||
font,
|
||||
c,
|
||||
glyph.BoundingWidth + widthAdjustment + 1,
|
||||
glyph.BoundingHeight + 1,
|
||||
glyph.AdvanceWidth,
|
||||
new Vector2(0, glyph.CurrentOffsetY)),
|
||||
glyph);
|
||||
}
|
||||
}
|
||||
|
||||
fontConfig.Destroy();
|
||||
}
|
||||
foreach (var style in this.fontUseCounter.Keys)
|
||||
this.EnsureFont(style);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Post-build fonts before plugins do something more. To be called from InterfaceManager.
|
||||
/// </summary>
|
||||
/// <param name="forceMinSize">Whether to load fonts in minimum sizes.</param>
|
||||
public unsafe void AfterBuildFonts(bool forceMinSize)
|
||||
public unsafe void AfterBuildFonts()
|
||||
{
|
||||
var ioFonts = ImGui.GetIO().Fonts;
|
||||
ioFonts.GetTexDataAsRGBA32(out byte* pixels8, out var width, out var height);
|
||||
|
|
@ -352,7 +267,7 @@ namespace Dalamud.Interface.GameFonts
|
|||
|
||||
foreach (var (style, font) in this.fonts)
|
||||
{
|
||||
var fdt = this.fdts[(int)(forceMinSize ? style.FamilyWithMinimumSize : style.FamilyAndSize)];
|
||||
var fdt = this.fdts[(int)(this.isBuildingAsFallbackFontMode ? style.FamilyWithMinimumSize : style.FamilyAndSize)];
|
||||
var scale = style.SizePt / fdt.FontHeader.Size;
|
||||
var fontPtr = font.NativePtr;
|
||||
fontPtr->FontSize = fdt.FontHeader.Size * 4 / 3;
|
||||
|
|
@ -449,10 +364,12 @@ namespace Dalamud.Interface.GameFonts
|
|||
}
|
||||
}
|
||||
|
||||
CopyGlyphsAcrossFonts(InterfaceManager.DefaultFont, font, true, false);
|
||||
Util.CopyGlyphsAcrossFonts(InterfaceManager.DefaultFont, font, true, false);
|
||||
UnscaleFont(font, 1 / scale, false);
|
||||
font.BuildLookupTable();
|
||||
}
|
||||
|
||||
this.isBetweenBuildFontsAndAfterBuildFonts = false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -471,35 +388,41 @@ namespace Dalamud.Interface.GameFonts
|
|||
}
|
||||
}
|
||||
|
||||
private struct ImFontGlyphReal
|
||||
private unsafe void EnsureFont(GameFontStyle style)
|
||||
{
|
||||
public uint ColoredVisibleCodepoint;
|
||||
public float AdvanceX;
|
||||
public float X0;
|
||||
public float Y0;
|
||||
public float X1;
|
||||
public float Y1;
|
||||
public float U0;
|
||||
public float V0;
|
||||
public float U1;
|
||||
public float V1;
|
||||
var rectIds = this.glyphRectIds[style] = new();
|
||||
|
||||
public bool Colored
|
||||
{
|
||||
get => ((this.ColoredVisibleCodepoint >> 0) & 1) != 0;
|
||||
set => this.ColoredVisibleCodepoint = (this.ColoredVisibleCodepoint & 0xFFFFFFFEu) | (value ? 1u : 0u);
|
||||
}
|
||||
var fdt = this.fdts[(int)(this.isBuildingAsFallbackFontMode ? style.FamilyWithMinimumSize : style.FamilyAndSize)];
|
||||
if (fdt == null)
|
||||
return;
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get => ((this.ColoredVisibleCodepoint >> 1) & 1) != 0;
|
||||
set => this.ColoredVisibleCodepoint = (this.ColoredVisibleCodepoint & 0xFFFFFFFDu) | (value ? 2u : 0u);
|
||||
}
|
||||
ImFontConfigPtr fontConfig = ImGuiNative.ImFontConfig_ImFontConfig();
|
||||
fontConfig.OversampleH = 1;
|
||||
fontConfig.OversampleV = 1;
|
||||
fontConfig.PixelSnapH = false;
|
||||
|
||||
public int Codepoint
|
||||
var io = ImGui.GetIO();
|
||||
var font = io.Fonts.AddFontDefault(fontConfig);
|
||||
|
||||
fontConfig.Destroy();
|
||||
|
||||
this.fonts[style] = font;
|
||||
foreach (var glyph in fdt.Glyphs)
|
||||
{
|
||||
get => (int)(this.ColoredVisibleCodepoint >> 2);
|
||||
set => this.ColoredVisibleCodepoint = (this.ColoredVisibleCodepoint & 3u) | ((uint)this.Codepoint << 2);
|
||||
var c = glyph.Char;
|
||||
if (c < 32 || c >= 0xFFFF)
|
||||
continue;
|
||||
|
||||
var widthAdjustment = style.CalculateBaseWidthAdjustment(fdt, glyph);
|
||||
rectIds[c] = Tuple.Create(
|
||||
io.Fonts.AddCustomRectFontGlyph(
|
||||
font,
|
||||
c,
|
||||
glyph.BoundingWidth + widthAdjustment + 1,
|
||||
glyph.BoundingHeight + 1,
|
||||
glyph.AdvanceWidth,
|
||||
new Vector2(0, glyph.CurrentOffsetY)),
|
||||
glyph);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -248,6 +248,11 @@ namespace Dalamud.Interface.Internal
|
|||
/// </summary>
|
||||
public int FontResolutionLevel => this.FontResolutionLevelOverride ?? Service<DalamudConfiguration>.Get().FontResolutionLevel;
|
||||
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether we're building fonts but haven't generated atlas yet.
|
||||
/// </summary>
|
||||
public bool IsBuildingFontsBeforeAtlasBuild => this.isRebuildingFonts && !this.fontBuildSignal.WaitOne(0);
|
||||
|
||||
/// <summary>
|
||||
/// Enable this module.
|
||||
/// </summary>
|
||||
|
|
@ -900,7 +905,7 @@ namespace Dalamud.Interface.Internal
|
|||
texPixels[i] = (byte)(Math.Pow(texPixels[i] / 255.0f, 1.0f / fontGamma) * 255.0f);
|
||||
}
|
||||
|
||||
gameFontManager.AfterBuildFonts(disableBigFonts);
|
||||
gameFontManager.AfterBuildFonts();
|
||||
|
||||
foreach (var (font, mod) in this.loadedFontInfo)
|
||||
{
|
||||
|
|
@ -929,14 +934,14 @@ namespace Dalamud.Interface.Internal
|
|||
font.Descent = mod.SourceAxis.ImFont.Descent;
|
||||
font.FallbackChar = mod.SourceAxis.ImFont.FallbackChar;
|
||||
font.EllipsisChar = mod.SourceAxis.ImFont.EllipsisChar;
|
||||
GameFontManager.CopyGlyphsAcrossFonts(mod.SourceAxis.ImFont, font, false, false);
|
||||
Util.CopyGlyphsAcrossFonts(mod.SourceAxis.ImFont, font, false, false);
|
||||
}
|
||||
else if (mod.Axis == TargetFontModification.AxisMode.GameGlyphsOnly)
|
||||
{
|
||||
Log.Verbose("[FONT] {0}: Overwrite game specific glyphs from AXIS of size {1}px", mod.Name, mod.SourceAxis.ImFont.FontSize, font.FontSize);
|
||||
if (!this.UseAxis && font.NativePtr == DefaultFont.NativePtr)
|
||||
mod.SourceAxis.ImFont.FontSize -= 1;
|
||||
GameFontManager.CopyGlyphsAcrossFonts(mod.SourceAxis.ImFont, font, true, false, 0xE020, 0xE0DB);
|
||||
Util.CopyGlyphsAcrossFonts(mod.SourceAxis.ImFont, font, true, false, 0xE020, 0xE0DB);
|
||||
if (!this.UseAxis && font.NativePtr == DefaultFont.NativePtr)
|
||||
mod.SourceAxis.ImFont.FontSize += 1;
|
||||
}
|
||||
|
|
@ -946,7 +951,7 @@ namespace Dalamud.Interface.Internal
|
|||
}
|
||||
|
||||
// Fill missing glyphs in MonoFont from DefaultFont
|
||||
GameFontManager.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false);
|
||||
Util.CopyGlyphsAcrossFonts(DefaultFont, MonoFont, true, false);
|
||||
|
||||
for (int i = 0, i_ = ioFonts.Fonts.Size; i < i_; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -176,7 +176,8 @@ namespace Dalamud.Interface.Internal.Windows
|
|||
var configuration = Service<DalamudConfiguration>.Get();
|
||||
var interfaceManager = Service<InterfaceManager>.Get();
|
||||
|
||||
var rebuildFont = interfaceManager.FontGamma != configuration.FontGammaLevel
|
||||
var rebuildFont = ImGui.GetIO().FontGlobalScale != configuration.GlobalUiScale
|
||||
|| interfaceManager.FontGamma != configuration.FontGammaLevel
|
||||
|| interfaceManager.FontResolutionLevel != configuration.FontResolutionLevel
|
||||
|| interfaceManager.UseAxis != configuration.UseAxisFontsFromGame;
|
||||
|
||||
|
|
|
|||
|
|
@ -526,6 +526,65 @@ namespace Dalamud.Utility
|
|||
Process.Start(process);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Fills missing glyphs in target font from source font, if both are not null.
|
||||
/// </summary>
|
||||
/// <param name="source">Source font.</param>
|
||||
/// <param name="target">Target font.</param>
|
||||
/// <param name="missingOnly">Whether to copy missing glyphs only.</param>
|
||||
/// <param name="rebuildLookupTable">Whether to call target.BuildLookupTable().</param>
|
||||
/// <param name="rangeLow">Low codepoint range to copy.</param>
|
||||
/// <param name="rangeHigh">High codepoing range to copy.</param>
|
||||
public static void CopyGlyphsAcrossFonts(ImFontPtr? source, ImFontPtr? target, bool missingOnly, bool rebuildLookupTable, int rangeLow = 32, int rangeHigh = 0xFFFE)
|
||||
{
|
||||
if (!source.HasValue || !target.HasValue)
|
||||
return;
|
||||
|
||||
var scale = target.Value!.FontSize / source.Value!.FontSize;
|
||||
unsafe
|
||||
{
|
||||
var glyphs = (ImFontGlyphReal*)source.Value!.Glyphs.Data;
|
||||
for (int j = 0, j_ = source.Value!.Glyphs.Size; j < j_; j++)
|
||||
{
|
||||
var glyph = &glyphs[j];
|
||||
if (glyph->Codepoint < rangeLow || glyph->Codepoint > rangeHigh)
|
||||
continue;
|
||||
|
||||
var prevGlyphPtr = (ImFontGlyphReal*)target.Value!.FindGlyphNoFallback((ushort)glyph->Codepoint).NativePtr;
|
||||
if ((IntPtr)prevGlyphPtr == IntPtr.Zero)
|
||||
{
|
||||
target.Value!.AddGlyph(
|
||||
target.Value!.ConfigData,
|
||||
(ushort)glyph->Codepoint,
|
||||
glyph->X0 * scale,
|
||||
((glyph->Y0 - source.Value!.Ascent) * scale) + target.Value!.Ascent,
|
||||
glyph->X1 * scale,
|
||||
((glyph->Y1 - source.Value!.Ascent) * scale) + target.Value!.Ascent,
|
||||
glyph->U0,
|
||||
glyph->V0,
|
||||
glyph->U1,
|
||||
glyph->V1,
|
||||
glyph->AdvanceX * scale);
|
||||
}
|
||||
else if (!missingOnly)
|
||||
{
|
||||
prevGlyphPtr->X0 = glyph->X0 * scale;
|
||||
prevGlyphPtr->Y0 = ((glyph->Y0 - source.Value!.Ascent) * scale) + target.Value!.Ascent;
|
||||
prevGlyphPtr->X1 = glyph->X1 * scale;
|
||||
prevGlyphPtr->Y1 = ((glyph->Y1 - source.Value!.Ascent) * scale) + target.Value!.Ascent;
|
||||
prevGlyphPtr->U0 = glyph->U0;
|
||||
prevGlyphPtr->V0 = glyph->V0;
|
||||
prevGlyphPtr->U1 = glyph->U1;
|
||||
prevGlyphPtr->V1 = glyph->V1;
|
||||
prevGlyphPtr->AdvanceX = glyph->AdvanceX * scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rebuildLookupTable)
|
||||
target.Value!.BuildLookupTable();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Dispose this object.
|
||||
/// </summary>
|
||||
|
|
@ -590,5 +649,40 @@ namespace Dalamud.Utility
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// ImFontGlyph the correct version.
|
||||
/// </summary>
|
||||
public struct ImFontGlyphReal
|
||||
{
|
||||
public uint ColoredVisibleCodepoint;
|
||||
public float AdvanceX;
|
||||
public float X0;
|
||||
public float Y0;
|
||||
public float X1;
|
||||
public float Y1;
|
||||
public float U0;
|
||||
public float V0;
|
||||
public float U1;
|
||||
public float V1;
|
||||
|
||||
public bool Colored
|
||||
{
|
||||
get => ((this.ColoredVisibleCodepoint >> 0) & 1) != 0;
|
||||
set => this.ColoredVisibleCodepoint = (this.ColoredVisibleCodepoint & 0xFFFFFFFEu) | (value ? 1u : 0u);
|
||||
}
|
||||
|
||||
public bool Visible
|
||||
{
|
||||
get => ((this.ColoredVisibleCodepoint >> 1) & 1) != 0;
|
||||
set => this.ColoredVisibleCodepoint = (this.ColoredVisibleCodepoint & 0xFFFFFFFDu) | (value ? 2u : 0u);
|
||||
}
|
||||
|
||||
public int Codepoint
|
||||
{
|
||||
get => (int)(this.ColoredVisibleCodepoint >> 2);
|
||||
set => this.ColoredVisibleCodepoint = (this.ColoredVisibleCodepoint & 3u) | ((uint)this.Codepoint << 2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue