字体预览工具 v1.0.0 初始版本

This commit is contained in:
2026-09-19 23:50:45 +08:00
commit 1883e9ba77
50 changed files with 5959 additions and 0 deletions
+252
View File
@@ -0,0 +1,252 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
namespace FontPreview;
internal static class FontNameParser
{
private struct NameRec
{
public int PlatformID;
public int EncodingID;
public int LanguageID;
public int NameID;
public byte[] Data;
}
private const int TTF_DIRREC_LEN = 16;
internal static string GetDisplayName(string fontPath, string fallback)
{
try
{
string text = Parse(fontPath);
return string.IsNullOrEmpty(text) ? fallback : text;
}
catch
{
return fallback;
}
}
private static string Parse(string path)
{
using FileStream fileStream = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite | FileShare.Delete);
byte[] array = new byte[12];
if (!ReadFully(fileStream, array, 0, 12))
{
return null;
}
long num;
if (array[0] == 116 && array[1] == 116 && array[2] == 99 && array[3] == 102)
{
byte[] array2 = new byte[4];
if (!ReadFully(fileStream, array2, 0, 4))
{
return null;
}
num = Be32(array2, 0);
}
else
{
num = 0L;
}
fileStream.Seek(num + 4, SeekOrigin.Begin);
byte[] array3 = new byte[2];
if (!ReadFully(fileStream, array3, 0, 2))
{
return null;
}
int num2 = (array3[0] << 8) | array3[1];
fileStream.Seek(num + 12, SeekOrigin.Begin);
long num3 = 0L;
long num4 = 0L;
byte[] array4 = new byte[16];
for (int i = 0; i < num2; i++)
{
if (!ReadFully(fileStream, array4, 0, 16))
{
return null;
}
if (array4[0] == 110 && array4[1] == 97 && array4[2] == 109 && array4[3] == 101)
{
num3 = Be32(array4, 8);
num4 = Be32(array4, 12);
break;
}
}
if (num3 == 0 || num4 <= 0 || num4 > 4194304)
{
return null;
}
byte[] array5 = new byte[num4];
fileStream.Seek(num3, SeekOrigin.Begin);
if (!ReadFully(fileStream, array5, 0, (int)num4))
{
return null;
}
List<NameRec> list = new List<NameRec>();
int num5 = (array5[2] << 8) | array5[3];
int num6 = (array5[4] << 8) | array5[5];
int num7 = 6;
for (int i = 0; i < num5; i++)
{
if (num7 + 12 > num4)
{
break;
}
int platformID = (array5[num7] << 8) | array5[num7 + 1];
int encodingID = (array5[num7 + 2] << 8) | array5[num7 + 3];
int languageID = (array5[num7 + 4] << 8) | array5[num7 + 5];
int nameID = (array5[num7 + 6] << 8) | array5[num7 + 7];
int num8 = (array5[num7 + 8] << 8) | array5[num7 + 9];
int num9 = (array5[num7 + 10] << 8) | array5[num7 + 11];
if (num9 >= 0 && num8 > 0 && num6 + num9 + num8 <= num4)
{
NameRec item = default(NameRec);
item.PlatformID = platformID;
item.EncodingID = encodingID;
item.LanguageID = languageID;
item.NameID = nameID;
item.Data = new byte[num8];
Array.Copy(array5, num6 + num9, item.Data, 0, num8);
list.Add(item);
}
num7 += 12;
}
int[] array6 = new int[4] { 1, 4, 6, 16 };
int[] array7 = array6;
foreach (int nameID2 in array7)
{
string text = PickBest(list, nameID2);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
return null;
}
private static string PickBest(List<NameRec> recs, int nameID)
{
List<NameRec> list = new List<NameRec>();
foreach (NameRec rec in recs)
{
if (rec.NameID == nameID)
{
list.Add(rec);
}
}
if (list.Count == 0)
{
return null;
}
foreach (NameRec item in list)
{
if (item.PlatformID == 3 && item.LanguageID == 2052)
{
string text = Decode(item);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
foreach (NameRec item2 in list)
{
if (item2.PlatformID == 3 && item2.LanguageID == 1033)
{
string text = Decode(item2);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
foreach (NameRec item3 in list)
{
if (item3.PlatformID == 3 && item3.LanguageID == 0)
{
string text = Decode(item3);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
foreach (NameRec item4 in list)
{
if (item4.PlatformID == 3)
{
string text = Decode(item4);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
foreach (NameRec item5 in list)
{
if (item5.PlatformID == 0)
{
string text = Decode(item5);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
foreach (NameRec item6 in list)
{
if (item6.PlatformID == 1)
{
string text = Decode(item6);
if (!string.IsNullOrEmpty(text))
{
return text;
}
}
}
return null;
}
private static string Decode(NameRec r)
{
string text;
try
{
text = ((r.PlatformID != 3 && r.PlatformID != 0) ? Encoding.GetEncoding(28591).GetString(r.Data) : Encoding.BigEndianUnicode.GetString(r.Data));
}
catch
{
return null;
}
text = text.Trim('\0', ' ', '\t', '\r', '\n');
return string.IsNullOrEmpty(text) ? null : text;
}
private static bool ReadFully(Stream s, byte[] buf, int off, int len)
{
int num;
for (int i = 0; i < len; i += num)
{
num = s.Read(buf, off + i, len - i);
if (num <= 0)
{
return false;
}
}
return true;
}
private static uint Be32(byte[] b, int off)
{
return (uint)((b[off] << 24) | (b[off + 1] << 16) | (b[off + 2] << 8) | b[off + 3]);
}
}