字体预览工具 v1.0.0 初始版本
This commit is contained in:
@@ -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]);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user