Compare commits
313 Commits
0.5.0
...
dev-extens
1
.gitignore
vendored
1
.gitignore
vendored
@@ -68,3 +68,4 @@ crashlytics-build.properties
|
|||||||
/UserSettings
|
/UserSettings
|
||||||
/*.zip
|
/*.zip
|
||||||
*.lnk
|
*.lnk
|
||||||
|
/HybridCLRData
|
||||||
|
|||||||
Binary file not shown.
BIN
Assets/Animations/IConfig.anim
Normal file
BIN
Assets/Animations/IConfig.anim
Normal file
Binary file not shown.
8
Assets/Animations/IConfig.anim.meta
Normal file
8
Assets/Animations/IConfig.anim.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 2e0c61e29fd90f04b9e41265d93e2029
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 7400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
Binary file not shown.
BIN
Assets/Animations/TConfig_Main.anim
Normal file
BIN
Assets/Animations/TConfig_Main.anim
Normal file
Binary file not shown.
8
Assets/Animations/TConfig_Main.anim.meta
Normal file
8
Assets/Animations/TConfig_Main.anim.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d815e4d844e6a1c4d849e96e199f8881
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 7400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
BIN
Assets/Animations/TMain_Config.anim
Normal file
BIN
Assets/Animations/TMain_Config.anim
Normal file
Binary file not shown.
8
Assets/Animations/TMain_Config.anim.meta
Normal file
8
Assets/Animations/TMain_Config.anim.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 82867c59112ff5a419fbea2ebff2d3b9
|
||||||
|
NativeFormatImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 7400000
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -1,8 +0,0 @@
|
|||||||
using System.Reflection;
|
|
||||||
|
|
||||||
[assembly: AssemblyCompany("Cryville")]
|
|
||||||
[assembly: AssemblyCopyright("Copyright © Cryville 2020-2022")]
|
|
||||||
[assembly: AssemblyDefaultAlias("Cosmo Resona")]
|
|
||||||
[assembly: AssemblyProduct("Cosmo Resona")]
|
|
||||||
[assembly: AssemblyTitle("Cosmo Resona")]
|
|
||||||
[assembly: AssemblyVersion("0.5.0")]
|
|
||||||
Binary file not shown.
@@ -33,12 +33,12 @@ namespace Cryville.Common {
|
|||||||
public override object ChangeType(object value, Type type, CultureInfo culture) {
|
public override object ChangeType(object value, Type type, CultureInfo culture) {
|
||||||
if (value == null)
|
if (value == null)
|
||||||
return null;
|
return null;
|
||||||
else if (type == value.GetType())
|
else if (type.IsAssignableFrom(value.GetType()))
|
||||||
return value;
|
return value;
|
||||||
else if (type.IsEnum && value is string) {
|
else if (type.IsEnum && value is string) {
|
||||||
return Enum.Parse(type, (string)value);
|
return Enum.Parse(type, (string)value);
|
||||||
}
|
}
|
||||||
throw new InvalidCastException();
|
throw new InvalidCastException(string.Format("Cannot cast {0} to {1}", value.GetType(), type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void ReorderArgumentArray(ref object[] args, object state) {
|
public override void ReorderArgumentArray(ref object[] args, object state) {
|
||||||
|
|||||||
90
Assets/Cryville/Common/Buffers/CategorizedPool.cs
Normal file
90
Assets/Cryville/Common/Buffers/CategorizedPool.cs
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Buffers {
|
||||||
|
/// <summary>
|
||||||
|
/// A set of resource pools categorized by a category type.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCategory">The category type.</typeparam>
|
||||||
|
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
|
||||||
|
public abstract class CategorizedPool<TCategory, TObject> where TObject : class {
|
||||||
|
/// <summary>
|
||||||
|
/// The set of underlying pools.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>The <see cref="Rent(TCategory)" /> and <see cref="Return(TCategory, TObject)" /> method select an underlying pool directly from this set with the category as the key. When overridden, this set must be available since construction.</para>
|
||||||
|
/// </remarks>
|
||||||
|
protected abstract IReadOnlyDictionary<TCategory, ObjectPool<TObject>> Buckets { get; }
|
||||||
|
/// <summary>
|
||||||
|
/// The count of objects rented from the set of pools.
|
||||||
|
/// </summary>
|
||||||
|
public int RentedCount { get; private set; }
|
||||||
|
/// <summary>
|
||||||
|
/// Rents an object from the pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="category">The category.</param>
|
||||||
|
/// <returns>The rented object.</returns>
|
||||||
|
public TObject Rent(TCategory category) {
|
||||||
|
var obj = Buckets[category].Rent();
|
||||||
|
RentedCount++;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a rented object to the pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="category">The category.</param>
|
||||||
|
/// <param name="obj">The object to return.</param>
|
||||||
|
public void Return(TCategory category, TObject obj) {
|
||||||
|
Buckets[category].Return(obj);
|
||||||
|
--RentedCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// A utility to access a categorized pool, representing a single unit that uses a shared categorized pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="TCategory">The category type.</typeparam>
|
||||||
|
/// <typeparam name="TObject">The type of the objects in the pool.</typeparam>
|
||||||
|
public class CategorizedPoolAccessor<TCategory, TObject> where TObject : class {
|
||||||
|
readonly CategorizedPool<TCategory, TObject> _pool;
|
||||||
|
static readonly SimpleObjectPool<Dictionary<TObject, TCategory>> _dictPool
|
||||||
|
= new SimpleObjectPool<Dictionary<TObject, TCategory>>(1024);
|
||||||
|
Dictionary<TObject, TCategory> _rented;
|
||||||
|
/// <summary>
|
||||||
|
/// Creates an instance of the <see cref="CategorizedPoolAccessor{TCategory, TObject}" /> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="pool">The categorized pool.</param>
|
||||||
|
public CategorizedPoolAccessor(CategorizedPool<TCategory, TObject> pool) {
|
||||||
|
_pool = pool;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Rents an object from the pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="category">The category.</param>
|
||||||
|
/// <returns>The rented object.</returns>
|
||||||
|
public TObject Rent(TCategory category) {
|
||||||
|
var obj = _pool.Rent(category);
|
||||||
|
if (_rented == null) _rented = _dictPool.Rent();
|
||||||
|
_rented.Add(obj, category);
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a rented object to the pool.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object to return.</param>
|
||||||
|
public void Return(TObject obj) {
|
||||||
|
_pool.Return(_rented[obj], obj);
|
||||||
|
_rented.Remove(obj);
|
||||||
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Returns all objects rented by this accessor to the pool.
|
||||||
|
/// </summary>
|
||||||
|
public void ReturnAll() {
|
||||||
|
if (_rented == null) return;
|
||||||
|
foreach (var obj in _rented) {
|
||||||
|
_pool.Return(obj.Value, obj.Key);
|
||||||
|
}
|
||||||
|
_rented.Clear();
|
||||||
|
_dictPool.Return(_rented);
|
||||||
|
_rented = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: d6a3a023271b82a4985d1bbcc86e6fa8
|
guid: ec18f22479042d747b88c093aa90c5c0
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
@@ -14,6 +14,10 @@
|
|||||||
_objs = new T[capacity];
|
_objs = new T[capacity];
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
/// The count of objects rented from the pool.
|
||||||
|
/// </summary>
|
||||||
|
public int RentedCount { get { return _index; } }
|
||||||
|
/// <summary>
|
||||||
/// Rents a object from the pool.
|
/// Rents a object from the pool.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The rented object.</returns>
|
/// <returns>The rented object.</returns>
|
||||||
@@ -24,6 +28,7 @@
|
|||||||
_objs[_index++] = null;
|
_objs[_index++] = null;
|
||||||
}
|
}
|
||||||
if (obj == null) obj = Construct();
|
if (obj == null) obj = Construct();
|
||||||
|
else Reset(obj);
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -38,5 +43,10 @@
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>The new instance.</returns>
|
/// <returns>The new instance.</returns>
|
||||||
protected abstract T Construct();
|
protected abstract T Construct();
|
||||||
|
/// <summary>
|
||||||
|
/// Resets an object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="obj">The object.</param>
|
||||||
|
protected virtual void Reset(T obj) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ namespace Cryville.Common.Buffers {
|
|||||||
/// Creates an instance of the <see cref="TargetString" /> class.
|
/// Creates an instance of the <see cref="TargetString" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="capacity">The initial capacity of the string.</param>
|
/// <param name="capacity">The initial capacity of the string.</param>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException"><paramref name="capacity" /> is less than or equal to 0.</exception>
|
||||||
public TargetString(int capacity) {
|
public TargetString(int capacity) {
|
||||||
|
if (capacity <= 0) throw new ArgumentOutOfRangeException("capacity");
|
||||||
_arr = new char[capacity];
|
_arr = new char[capacity];
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -49,14 +51,16 @@ namespace Cryville.Common.Buffers {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The length of the string.
|
/// The length of the string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">The value specified for a set operation is less than 0.</exception>
|
||||||
public int Length {
|
public int Length {
|
||||||
get {
|
get {
|
||||||
return m_length;
|
return m_length;
|
||||||
}
|
}
|
||||||
set {
|
set {
|
||||||
|
if (Length < 0) throw new ArgumentOutOfRangeException("length");
|
||||||
if (m_length == value) return;
|
if (m_length == value) return;
|
||||||
if (_arr.Length < value) {
|
if (_arr.Length < value) {
|
||||||
var len = m_length;
|
var len = _arr.Length;
|
||||||
while (len < value) len *= 2;
|
while (len < value) len *= 2;
|
||||||
var arr2 = new char[len];
|
var arr2 = new char[len];
|
||||||
Array.Copy(_arr, arr2, m_length);
|
Array.Copy(_arr, arr2, m_length);
|
||||||
@@ -73,20 +77,31 @@ namespace Cryville.Common.Buffers {
|
|||||||
if (!_invalidated) return;
|
if (!_invalidated) return;
|
||||||
_invalidated = false;
|
_invalidated = false;
|
||||||
var ev = OnUpdate;
|
var ev = OnUpdate;
|
||||||
if (ev != null) OnUpdate.Invoke();
|
if (ev != null) ev.Invoke();
|
||||||
}
|
}
|
||||||
|
internal char[] TrustedAsArray() { return _arr; }
|
||||||
|
|
||||||
IEnumerator IEnumerable.GetEnumerator() {
|
/// <summary>
|
||||||
return GetEnumerator();
|
/// Returns an enumerator that iterates through the <see cref="TargetString" />.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A <see cref="Enumerator" /> for the <see cref="TargetString" />.</returns>
|
||||||
|
public Enumerator GetEnumerator() {
|
||||||
|
return new Enumerator(this);
|
||||||
}
|
}
|
||||||
public IEnumerator<char> GetEnumerator() {
|
IEnumerator<char> IEnumerable<char>.GetEnumerator() {
|
||||||
|
return new Enumerator(this);
|
||||||
|
}
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() {
|
||||||
return new Enumerator(this);
|
return new Enumerator(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
class Enumerator : IEnumerator<char> {
|
public struct Enumerator : IEnumerator<char> {
|
||||||
readonly TargetString _self;
|
readonly TargetString _self;
|
||||||
int _index = -1;
|
int _index;
|
||||||
public Enumerator(TargetString self) { _self = self; }
|
internal Enumerator(TargetString self) {
|
||||||
|
_self = self;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
public char Current {
|
public char Current {
|
||||||
get {
|
get {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: b9bd9e24d7c553341a2a12391843542f
|
guid: c4ef48e4a4983de4e9c31483df2a918e
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
8
Assets/Cryville/Common/Collections/Generic.meta
Normal file
8
Assets/Cryville/Common/Collections/Generic.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 9ec674235c0dd6744af2dab2b58dd53c
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Assets/Cryville/Common/Collections/Generic/IPairList.cs
Normal file
8
Assets/Cryville/Common/Collections/Generic/IPairList.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Collections.Generic {
|
||||||
|
public interface IPairList<TKey, TValue> : IList<KeyValuePair<TKey, TValue>> {
|
||||||
|
void Add(TKey key, TValue value);
|
||||||
|
void Insert(int index, TKey key, TValue value);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e3c5a8bf05d5e284ba498e91cb0dd35e
|
guid: 73fb17b484b343242bcce27c15ed7d44
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
46
Assets/Cryville/Common/Collections/Generic/PairCollection.cs
Normal file
46
Assets/Cryville/Common/Collections/Generic/PairCollection.cs
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Collections.Generic {
|
||||||
|
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView<,>))]
|
||||||
|
public struct PairCollection<TKey, TValue> : IDisposable {
|
||||||
|
public void Dispose() { }
|
||||||
|
readonly IPairList<TKey, TValue> _pairList;
|
||||||
|
readonly IDictionary<TKey, TValue> _dictionary;
|
||||||
|
public PairCollection(object collection) : this() {
|
||||||
|
var type = collection.GetType();
|
||||||
|
if (typeof(IPairList<TKey, TValue>).IsAssignableFrom(type)) _pairList = (IPairList<TKey, TValue>)collection;
|
||||||
|
else if (typeof(IDictionary<TKey, TValue>).IsAssignableFrom(type)) _dictionary = (IDictionary<TKey, TValue>)collection;
|
||||||
|
else throw new ArgumentException("Parameter is not a pair collection");
|
||||||
|
}
|
||||||
|
public int Count {
|
||||||
|
get {
|
||||||
|
if (_pairList != null) return _pairList.Count;
|
||||||
|
else return _dictionary.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Add(TKey key, TValue value) {
|
||||||
|
if (_pairList != null) _pairList.Add(key, value);
|
||||||
|
else _dictionary.Add(key, value);
|
||||||
|
}
|
||||||
|
public void CopyTo(KeyValuePair<TKey, TValue>[] array, int index) {
|
||||||
|
if (_pairList != null) _pairList.CopyTo(array, index);
|
||||||
|
else _dictionary.CopyTo(array, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal class PairCollectionDebugView<TKey, TValue> {
|
||||||
|
readonly PairCollection<TKey, TValue> _self;
|
||||||
|
public PairCollectionDebugView(PairCollection<TKey, TValue> self) {
|
||||||
|
_self = self;
|
||||||
|
}
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||||
|
public KeyValuePair<TKey, TValue>[] Items {
|
||||||
|
get {
|
||||||
|
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
|
||||||
|
_self.CopyTo(array, 0);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,7 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 2546fb1d514348842a14a03531be192d
|
guid: 2517e8f040bd36f46948e5fafaf5335c
|
||||||
timeCreated: 1637982768
|
|
||||||
licenseType: Free
|
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
defaultReferences: []
|
defaultReferences: []
|
||||||
executionOrder: 0
|
executionOrder: 0
|
||||||
48
Assets/Cryville/Common/Collections/Generic/PairList.cs
Normal file
48
Assets/Cryville/Common/Collections/Generic/PairList.cs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Collections.Generic {
|
||||||
|
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView<,>))]
|
||||||
|
public class PairList<TKey, TValue> : List<KeyValuePair<TKey, TValue>>, IPairList<TKey, TValue>, IPairList {
|
||||||
|
public void Add(TKey key, TValue value) {
|
||||||
|
Add(new KeyValuePair<TKey, TValue>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Add(object key, object value) {
|
||||||
|
try {
|
||||||
|
Add((TKey)key, (TValue)value);
|
||||||
|
}
|
||||||
|
catch (InvalidCastException) {
|
||||||
|
throw new ArgumentException("Wrong key type or value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, TKey key, TValue value) {
|
||||||
|
Insert(index, new KeyValuePair<TKey, TValue>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, object key, object value) {
|
||||||
|
try {
|
||||||
|
Insert(index, (TKey)key, (TValue)value);
|
||||||
|
}
|
||||||
|
catch (InvalidCastException) {
|
||||||
|
throw new ArgumentException("Wrong key type or value type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal class PairListDebugView<TKey, TValue> {
|
||||||
|
readonly PairList<TKey, TValue> _self;
|
||||||
|
public PairListDebugView(PairList<TKey, TValue> self) {
|
||||||
|
_self = self;
|
||||||
|
}
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||||
|
public KeyValuePair<TKey, TValue>[] Items {
|
||||||
|
get {
|
||||||
|
KeyValuePair<TKey, TValue>[] array = new KeyValuePair<TKey, TValue>[_self.Count];
|
||||||
|
_self.CopyTo(array, 0);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Collections/Generic/PairList.cs.meta
Normal file
11
Assets/Cryville/Common/Collections/Generic/PairList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: d9ed5ea8b7b1a934287e7ec5971166c0
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Assets/Cryville/Common/Collections/IPairList.cs
Normal file
8
Assets/Cryville/Common/Collections/IPairList.cs
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
using System.Collections;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Collections {
|
||||||
|
public interface IPairList : IList {
|
||||||
|
void Add(object key, object value);
|
||||||
|
void Insert(int index, object key, object value);
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Collections/IPairList.cs.meta
Normal file
11
Assets/Cryville/Common/Collections/IPairList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 046617672d437de4ab7e644a55defd3b
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
47
Assets/Cryville/Common/Collections/PairCollection.cs
Normal file
47
Assets/Cryville/Common/Collections/PairCollection.cs
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Collections {
|
||||||
|
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairCollectionDebugView))]
|
||||||
|
public struct PairCollection : IDisposable {
|
||||||
|
public void Dispose() { }
|
||||||
|
readonly IPairList _pairList;
|
||||||
|
readonly IDictionary _dictionary;
|
||||||
|
public PairCollection(object collection) : this() {
|
||||||
|
var type = collection.GetType();
|
||||||
|
if (typeof(IPairList).IsAssignableFrom(type)) _pairList = (IPairList)collection;
|
||||||
|
else if (typeof(IDictionary).IsAssignableFrom(type)) _dictionary = (IDictionary)collection;
|
||||||
|
else throw new ArgumentException("Parameter is not a pair collection");
|
||||||
|
}
|
||||||
|
public int Count {
|
||||||
|
get {
|
||||||
|
if (_pairList != null) return _pairList.Count;
|
||||||
|
else return _dictionary.Count;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void Add(object key, object value) {
|
||||||
|
if (_pairList != null) _pairList.Add(key, value);
|
||||||
|
else _dictionary.Add(key, value);
|
||||||
|
}
|
||||||
|
public void CopyTo(KeyValuePair<object, object>[] array, int index) {
|
||||||
|
if (_pairList != null) _pairList.CopyTo(array, index);
|
||||||
|
else _dictionary.CopyTo(array, index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal class PairCollectionDebugView {
|
||||||
|
readonly PairCollection _self;
|
||||||
|
public PairCollectionDebugView(PairCollection self) {
|
||||||
|
_self = self;
|
||||||
|
}
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||||
|
public KeyValuePair<object, object>[] Items {
|
||||||
|
get {
|
||||||
|
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
|
||||||
|
_self.CopyTo(array, 0);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Collections/PairCollection.cs.meta
Normal file
11
Assets/Cryville/Common/Collections/PairCollection.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 1f87dfb8f6a1f5640b6deae741cd715c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
29
Assets/Cryville/Common/Collections/PairList.cs
Normal file
29
Assets/Cryville/Common/Collections/PairList.cs
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Collections {
|
||||||
|
[DebuggerDisplay("Count = {Count}"), DebuggerTypeProxy(typeof(PairListDebugView))]
|
||||||
|
public class PairList : List<KeyValuePair<object, object>>, IPairList {
|
||||||
|
public void Add(object key, object value) {
|
||||||
|
Add(new KeyValuePair<object, object>(key, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Insert(int index, object key, object value) {
|
||||||
|
Insert(index, new KeyValuePair<object, object>(key, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
internal class PairListDebugView {
|
||||||
|
readonly PairList _self;
|
||||||
|
public PairListDebugView(PairList self) {
|
||||||
|
_self = self;
|
||||||
|
}
|
||||||
|
[DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
|
||||||
|
public KeyValuePair<object, object>[] Items {
|
||||||
|
get {
|
||||||
|
KeyValuePair<object, object>[] array = new KeyValuePair<object, object>[_self.Count];
|
||||||
|
_self.CopyTo(array, 0);
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Collections/PairList.cs.meta
Normal file
11
Assets/Cryville/Common/Collections/PairList.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 57fc9f037c1fda5449e2a365a835c82c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
8
Assets/Cryville/Common/Culture.meta
Normal file
8
Assets/Cryville/Common/Culture.meta
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 520554ce9a8205b4b91e0ff2b8011673
|
||||||
|
folderAsset: yes
|
||||||
|
DefaultImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
37
Assets/Cryville/Common/Culture/ScriptUtils.cs
Normal file
37
Assets/Cryville/Common/Culture/ScriptUtils.cs
Normal file
File diff suppressed because one or more lines are too long
11
Assets/Cryville/Common/Culture/ScriptUtils.cs.meta
Normal file
11
Assets/Cryville/Common/Culture/ScriptUtils.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: ae9dab8f520fadc4194032f523ca87c1
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
113
Assets/Cryville/Common/Font/FontFile.cs
Normal file
113
Assets/Cryville/Common/Font/FontFile.cs
Normal file
@@ -0,0 +1,113 @@
|
|||||||
|
using Cryville.Common.IO;
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Font {
|
||||||
|
public abstract class FontFile : IEnumerable<Typeface> {
|
||||||
|
public abstract int Count { get; }
|
||||||
|
public abstract Typeface this[int index] { get; }
|
||||||
|
protected FileInfo File { get; private set; }
|
||||||
|
protected BinaryReader Reader { get; private set; }
|
||||||
|
public FontFile(FileInfo file) {
|
||||||
|
File = file;
|
||||||
|
Reader = new BinaryReaderBE(new FileStream(file.FullName, FileMode.Open, FileAccess.Read));
|
||||||
|
}
|
||||||
|
public void Close() { Reader.Close(); }
|
||||||
|
|
||||||
|
public static FontFile Create(FileInfo file) {
|
||||||
|
switch (file.Extension) {
|
||||||
|
case ".ttf": case ".otf": return new FontFileTTF(file);
|
||||||
|
case ".ttc": case ".otc": return new FontFileTTC(file);
|
||||||
|
default: return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Enumerator GetEnumerator() {
|
||||||
|
return new Enumerator(this);
|
||||||
|
}
|
||||||
|
IEnumerator<Typeface> IEnumerable<Typeface>.GetEnumerator() {
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
IEnumerator IEnumerable.GetEnumerator() {
|
||||||
|
return GetEnumerator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct Enumerator : IEnumerator<Typeface> {
|
||||||
|
readonly FontFile _self;
|
||||||
|
int _index;
|
||||||
|
internal Enumerator(FontFile self) {
|
||||||
|
_self = self;
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Typeface Current {
|
||||||
|
get {
|
||||||
|
if (_index < 0)
|
||||||
|
throw new InvalidOperationException(_index == -1 ? "Enum not started" : "Enum ended");
|
||||||
|
return _self[_index];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
object IEnumerator.Current { get { return Current; } }
|
||||||
|
|
||||||
|
public void Dispose() {
|
||||||
|
_index = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool MoveNext() {
|
||||||
|
if (_index == -2) return false;
|
||||||
|
_index++;
|
||||||
|
if (_index >= _self.Count) {
|
||||||
|
_index = -2;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Reset() {
|
||||||
|
_index = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class FontFileTTF : FontFile {
|
||||||
|
public override int Count { get { return 1; } }
|
||||||
|
public override Typeface this[int index] {
|
||||||
|
get {
|
||||||
|
if (index != 0) throw new ArgumentOutOfRangeException("index");
|
||||||
|
try {
|
||||||
|
return new TypefaceTTF(Reader, File, index);
|
||||||
|
}
|
||||||
|
catch (Exception) {
|
||||||
|
throw new InvalidDataException("Invalid font");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public FontFileTTF(FileInfo file) : base(file) { }
|
||||||
|
}
|
||||||
|
public class FontFileTTC : FontFile {
|
||||||
|
readonly IReadOnlyList<uint> _offsets;
|
||||||
|
public override int Count { get { return _offsets.Count; } }
|
||||||
|
public override Typeface this[int index] {
|
||||||
|
get {
|
||||||
|
if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index");
|
||||||
|
Reader.BaseStream.Position = _offsets[index];
|
||||||
|
try {
|
||||||
|
return new TypefaceTTF(Reader, File, index);
|
||||||
|
}
|
||||||
|
catch (Exception) {
|
||||||
|
throw new InvalidDataException("Invalid font");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public FontFileTTC(FileInfo file) : base(file) {
|
||||||
|
try {
|
||||||
|
_offsets = new TTCHeader(Reader, 0).GetItems();
|
||||||
|
}
|
||||||
|
catch (Exception) {
|
||||||
|
throw new InvalidDataException("Invalid font");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Font/FontFile.cs.meta
Normal file
11
Assets/Cryville/Common/Font/FontFile.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: c9f44ccf8ddd364418b4f4965414ff9c
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
63
Assets/Cryville/Common/Font/FontManager.cs
Normal file
63
Assets/Cryville/Common/Font/FontManager.cs
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Font {
|
||||||
|
public abstract class FontManager {
|
||||||
|
public IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapFullNameToTypeface { get; private set; }
|
||||||
|
public IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapNameToTypefaces { get; private set; }
|
||||||
|
public FontManager() {
|
||||||
|
var map1 = new Dictionary<string, List<Typeface>>();
|
||||||
|
var map2 = new Dictionary<string, List<Typeface>>();
|
||||||
|
foreach (var f in EnumerateAllTypefaces()) {
|
||||||
|
List<Typeface> set1;
|
||||||
|
if (!map1.TryGetValue(f.FullName, out set1)) {
|
||||||
|
map1.Add(f.FullName, set1 = new List<Typeface>());
|
||||||
|
}
|
||||||
|
set1.Add(f);
|
||||||
|
List<Typeface> set2;
|
||||||
|
if (!map2.TryGetValue(f.FamilyName, out set2)) {
|
||||||
|
map2.Add(f.FamilyName, set2 = new List<Typeface>());
|
||||||
|
}
|
||||||
|
set2.Add(f);
|
||||||
|
}
|
||||||
|
MapFullNameToTypeface = map1.ToDictionary(i => i.Key, i => (IReadOnlyCollection<Typeface>)i.Value);
|
||||||
|
MapNameToTypefaces = map2.ToDictionary(i => i.Key, i => (IReadOnlyCollection<Typeface>)i.Value);
|
||||||
|
}
|
||||||
|
protected abstract IEnumerable<Typeface> EnumerateAllTypefaces();
|
||||||
|
protected static IEnumerable<Typeface> ScanDirectoryForTypefaces(string dir) {
|
||||||
|
foreach (var f in new DirectoryInfo(dir).EnumerateFiles()) {
|
||||||
|
FontFile file;
|
||||||
|
try {
|
||||||
|
file = FontFile.Create(f);
|
||||||
|
}
|
||||||
|
catch (InvalidDataException) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (file == null) continue;
|
||||||
|
var enumerator = file.GetEnumerator();
|
||||||
|
while (enumerator.MoveNext()) {
|
||||||
|
Typeface ret;
|
||||||
|
try {
|
||||||
|
ret = enumerator.Current;
|
||||||
|
}
|
||||||
|
catch (InvalidDataException) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
yield return ret;
|
||||||
|
}
|
||||||
|
file.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class FontManagerAndroid : FontManager {
|
||||||
|
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
|
||||||
|
return ScanDirectoryForTypefaces("/system/fonts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class FontManagerWindows : FontManager {
|
||||||
|
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
|
||||||
|
return ScanDirectoryForTypefaces("C:/Windows/Fonts");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
329
Assets/Cryville/Common/Font/FontMatcher.cs
Normal file
329
Assets/Cryville/Common/Font/FontMatcher.cs
Normal file
@@ -0,0 +1,329 @@
|
|||||||
|
using Cryville.Common.Culture;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Font {
|
||||||
|
public abstract class FontMatcher {
|
||||||
|
protected FontManager Manager { get; private set; }
|
||||||
|
public FontMatcher(FontManager manafer) { Manager = manafer; }
|
||||||
|
public abstract IEnumerable<Typeface> MatchScript(string script = null, bool distinctFamily = false);
|
||||||
|
}
|
||||||
|
public class FallbackListFontMatcher : FontMatcher {
|
||||||
|
public Dictionary<string, List<string>> MapScriptToTypefaces = new Dictionary<string, List<string>>();
|
||||||
|
public void LoadDefaultWindowsFallbackList() {
|
||||||
|
if (Environment.OSVersion.Platform != PlatformID.Win32NT) return;
|
||||||
|
MapScriptToTypefaces.Clear();
|
||||||
|
ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List<string>());
|
||||||
|
// Reference: https://github.com/chromium/chromium/blob/main/third_party/blink/renderer/platform/fonts/win/font_fallback_win.cc
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "SimSun"); // Custom
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "SimHei"); // Custom
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Microsoft YaHei"); // Custom
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Arial");
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Times New Roman");
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Segoe UI"); // Custom
|
||||||
|
MapScriptToTypefaces["arab"].Insert(0, "Tahoma");
|
||||||
|
MapScriptToTypefaces["cyrl"].Insert(0, "Times New Roman");
|
||||||
|
MapScriptToTypefaces["grek"].Insert(0, "Times New Roman");
|
||||||
|
MapScriptToTypefaces["hebr"].Insert(0, "David");
|
||||||
|
MapScriptToTypefaces["jpan"].Insert(0, "MS PGothic");
|
||||||
|
MapScriptToTypefaces["latn"].Insert(0, "Times New Roman");
|
||||||
|
MapScriptToTypefaces["hans"].Insert(0, "SimSun");
|
||||||
|
MapScriptToTypefaces["hans"].Insert(0, "SimHei"); // Custom
|
||||||
|
MapScriptToTypefaces["thai"].Insert(0, "Tahoma");
|
||||||
|
MapScriptToTypefaces["hans"].Insert(0, "PMingLiU");
|
||||||
|
// Reference: https://learn.microsoft.com/en-us/globalization/input/font-support
|
||||||
|
var ver = Environment.OSVersion.Version;
|
||||||
|
if (ver >= new Version(5, 0)) { // Windows 2000
|
||||||
|
MapScriptToTypefaces["armn"].Insert(0, "Sylfaen");
|
||||||
|
MapScriptToTypefaces["deva"].Insert(0, "Mangal");
|
||||||
|
MapScriptToTypefaces["geor"].Insert(0, "Sylfaen");
|
||||||
|
MapScriptToTypefaces["taml"].Insert(0, "Latha");
|
||||||
|
}
|
||||||
|
if (ver >= new Version(5, 1)) { // Windows XP
|
||||||
|
MapScriptToTypefaces["gujr"].Insert(0, "Shruti");
|
||||||
|
MapScriptToTypefaces["guru"].Insert(0, "Raavi");
|
||||||
|
MapScriptToTypefaces["knda"].Insert(0, "Tunga");
|
||||||
|
MapScriptToTypefaces["syrc"].Insert(0, "Estrangelo Edessa");
|
||||||
|
MapScriptToTypefaces["telu"].Insert(0, "Gautami");
|
||||||
|
MapScriptToTypefaces["thaa"].Insert(0, "MV Boli");
|
||||||
|
// SP2
|
||||||
|
MapScriptToTypefaces["beng"].Insert(0, "Vrinda");
|
||||||
|
MapScriptToTypefaces["mlym"].Insert(0, "Kartika");
|
||||||
|
}
|
||||||
|
if (ver >= new Version(6, 0)) { // Windows Vista
|
||||||
|
MapScriptToTypefaces["cans"].Insert(0, "Euphemia");
|
||||||
|
MapScriptToTypefaces["cher"].Insert(0, "Plantagenet");
|
||||||
|
MapScriptToTypefaces["ethi"].Insert(0, "Nyala");
|
||||||
|
MapScriptToTypefaces["khmr"].Insert(0, "DaunPenh MoolBoran");
|
||||||
|
MapScriptToTypefaces["laoo"].Insert(0, "DokChampa");
|
||||||
|
MapScriptToTypefaces["mong"].Insert(0, "Mongolian Baiti");
|
||||||
|
MapScriptToTypefaces["orya"].Insert(0, "Kalinga");
|
||||||
|
MapScriptToTypefaces["sinh"].Insert(0, "Iskoola Pota");
|
||||||
|
MapScriptToTypefaces["tibt"].Insert(0, "Microsoft Himalaya");
|
||||||
|
MapScriptToTypefaces["yiii"].Insert(0, "Microsoft Yi Baiti");
|
||||||
|
MapScriptToTypefaces["arab"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["cyrl"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["grek"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["latn"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["hans"].Add("SimSun-ExtB");
|
||||||
|
MapScriptToTypefaces["hant"].Add("MingLiU-ExtB");
|
||||||
|
MapScriptToTypefaces["hant"].Add("MingLiU_HKSCS-ExtB");
|
||||||
|
MapScriptToTypefaces["arab"].Add("Microsoft Uighur");
|
||||||
|
MapScriptToTypefaces["zmth"].Insert(0, "Cambria Math");
|
||||||
|
// Reference: https://en.wikipedia.org/wiki/List_of_CJK_fonts
|
||||||
|
MapScriptToTypefaces["jpan"].Insert(0, "Meiryo");
|
||||||
|
MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei");
|
||||||
|
}
|
||||||
|
if (ver >= new Version(6, 1)) { // Windows 7
|
||||||
|
MapScriptToTypefaces["brai"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["dsrt"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["talu"].Insert(0, "Microsoft New Tai Lue");
|
||||||
|
MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["osma"].Insert(0, "Ebrima");
|
||||||
|
MapScriptToTypefaces["phag"].Insert(0, "Microsoft PhagsPa");
|
||||||
|
MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["zsym"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["tale"].Insert(0, "Microsoft Tai Le");
|
||||||
|
MapScriptToTypefaces["tfng"].Insert(0, "Ebrima");
|
||||||
|
MapScriptToTypefaces["vaii"].Insert(0, "Ebrima");
|
||||||
|
}
|
||||||
|
if (ver >= new Version(6, 2)) { // Windows 8
|
||||||
|
MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["hang"].Add("Malgun Gothic");
|
||||||
|
MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["lisu"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["mymr"].Insert(0, "Myanmar Text");
|
||||||
|
MapScriptToTypefaces["nkoo"].Insert(0, "Ebrima");
|
||||||
|
MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["ethi"].Insert(0, "Ebrima");
|
||||||
|
MapScriptToTypefaces["cans"].Insert(0, "Gadugi");
|
||||||
|
MapScriptToTypefaces["hant"].Insert(0, "Microsoft JhengHei UI");
|
||||||
|
MapScriptToTypefaces["hans"].Insert(0, "Microsoft YaHei UI");
|
||||||
|
MapScriptToTypefaces["beng"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["deva"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["gujr"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["guru"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
|
||||||
|
MapScriptToTypefaces["knda"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
|
||||||
|
MapScriptToTypefaces["mlym"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["orya"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["sinh"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
|
||||||
|
MapScriptToTypefaces["taml"].Insert(0, "Nirmala UI"); // NOT DOCUMENTED, UNVERIFIED
|
||||||
|
MapScriptToTypefaces["telu"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["armn"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["geor"].Insert(0, "Segoe UI");
|
||||||
|
MapScriptToTypefaces["hebr"].Insert(0, "Segoe UI");
|
||||||
|
}
|
||||||
|
if (ver >= new Version(6, 3)) { // Windows 8.1
|
||||||
|
MapScriptToTypefaces["bugi"].Insert(0, "Leelawadee UI");
|
||||||
|
MapScriptToTypefaces["copt"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["java"].Insert(0, "Javanese Text");
|
||||||
|
MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Symbol");
|
||||||
|
MapScriptToTypefaces["olck"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["sora"].Insert(0, "Nirmala UI");
|
||||||
|
MapScriptToTypefaces["khmr"].Insert(0, "Leelawadee UI");
|
||||||
|
MapScriptToTypefaces["laoo"].Insert(0, "Leelawadee UI");
|
||||||
|
MapScriptToTypefaces["thai"].Insert(0, "Leelawadee UI");
|
||||||
|
MapScriptToTypefaces["zsye"].Insert(0, "Segoe UI Emoji");
|
||||||
|
}
|
||||||
|
if (ver >= new Version(10, 0)) { // Windows 10
|
||||||
|
MapScriptToTypefaces["brah"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["cari"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["cprt"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["egyp"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["armi"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["phli"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["prti"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["khar"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["lyci"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["lydi"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["phnx"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["xpeo"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["sarb"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["shaw"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["xsux"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["ugar"].Insert(0, "Segoe UI Historic");
|
||||||
|
// Segoe UI Symbol -> Segoe UI Historic
|
||||||
|
MapScriptToTypefaces["glag"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["goth"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["merc"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["ogam"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["ital"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["orkh"].Insert(0, "Segoe UI Historic");
|
||||||
|
MapScriptToTypefaces["runr"].Insert(0, "Segoe UI Historic");
|
||||||
|
//
|
||||||
|
MapScriptToTypefaces["jpan"].Insert(0, "Yu Gothic UI");
|
||||||
|
MapScriptToTypefaces["zsym"].Add("Segoe MDL2 Assets");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void LoadDefaultAndroidFallbackList() {
|
||||||
|
if (Environment.OSVersion.Platform != PlatformID.Unix) return;
|
||||||
|
MapScriptToTypefaces.Clear();
|
||||||
|
ScriptUtils.FillKeysWithScripts(MapScriptToTypefaces, () => new List<string>());
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK TC"); // TODO Modify default fallback
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK JP");
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Noto Sans CJK SC");
|
||||||
|
MapScriptToTypefaces["zyyy"].Insert(0, "Roboto");
|
||||||
|
MapScriptToTypefaces["zsye"].Insert(0, "Noto Color Emoji");
|
||||||
|
MapScriptToTypefaces["zsye"].Add("Noto Color Emoji Flags");
|
||||||
|
MapScriptToTypefaces["arab"].Insert(0, "Noto Naskh Arabic");
|
||||||
|
MapScriptToTypefaces["adlm"].Insert(0, "Noto Sans Adlam");
|
||||||
|
MapScriptToTypefaces["ahom"].Insert(0, "Noto Sans Ahom");
|
||||||
|
MapScriptToTypefaces["hluw"].Insert(0, "Noto Sans Anatolian Hieroglyphs");
|
||||||
|
MapScriptToTypefaces["armn"].Insert(0, "Noto Sans Armenian");
|
||||||
|
MapScriptToTypefaces["avst"].Insert(0, "Noto Sans Avestan");
|
||||||
|
MapScriptToTypefaces["bali"].Insert(0, "Noto Sans Balinese");
|
||||||
|
MapScriptToTypefaces["bamu"].Insert(0, "Noto Sans Bamum");
|
||||||
|
MapScriptToTypefaces["bass"].Insert(0, "Noto Sans Bassa Vah");
|
||||||
|
MapScriptToTypefaces["batk"].Insert(0, "Noto Sans Batak");
|
||||||
|
MapScriptToTypefaces["beng"].Insert(0, "Noto Sans Bengali");
|
||||||
|
MapScriptToTypefaces["bhks"].Insert(0, "Noto Sans Bhaiksuki");
|
||||||
|
MapScriptToTypefaces["brah"].Insert(0, "Noto Sans Brahmi");
|
||||||
|
MapScriptToTypefaces["bugi"].Insert(0, "Noto Sans Buginese");
|
||||||
|
MapScriptToTypefaces["buhd"].Insert(0, "Noto Sans Buhid");
|
||||||
|
MapScriptToTypefaces["jpan"].Insert(0, "Noto Sans CJK JP");
|
||||||
|
MapScriptToTypefaces["kore"].Insert(0, "Noto Sans CJK KR");
|
||||||
|
MapScriptToTypefaces["hans"].Insert(0, "Noto Sans CJK SC");
|
||||||
|
MapScriptToTypefaces["hant"].Insert(0, "Noto Sans CJK TC");
|
||||||
|
MapScriptToTypefaces["hant"].Add("Noto Sans CJK HK");
|
||||||
|
MapScriptToTypefaces["cans"].Insert(0, "Noto Sans Canadian Aboriginal");
|
||||||
|
MapScriptToTypefaces["cari"].Insert(0, "Noto Sans Carian");
|
||||||
|
MapScriptToTypefaces["cakm"].Insert(0, "Noto Sans Chakma");
|
||||||
|
MapScriptToTypefaces["cham"].Insert(0, "Noto Sans Cham");
|
||||||
|
MapScriptToTypefaces["cher"].Insert(0, "Noto Sans Cherokee");
|
||||||
|
MapScriptToTypefaces["copt"].Insert(0, "Noto Sans Coptic");
|
||||||
|
MapScriptToTypefaces["xsux"].Insert(0, "Noto Sans Cuneiform");
|
||||||
|
MapScriptToTypefaces["cprt"].Insert(0, "Noto Sans Cypriot");
|
||||||
|
MapScriptToTypefaces["dsrt"].Insert(0, "Noto Sans Deseret");
|
||||||
|
MapScriptToTypefaces["deva"].Insert(0, "Noto Sans Devanagari");
|
||||||
|
MapScriptToTypefaces["egyp"].Insert(0, "Noto Sans Egyptian Hieroglyphs");
|
||||||
|
MapScriptToTypefaces["elba"].Insert(0, "Noto Sans Elbasan");
|
||||||
|
MapScriptToTypefaces["ethi"].Insert(0, "Noto Sans Ethiopic");
|
||||||
|
MapScriptToTypefaces["geor"].Insert(0, "Noto Sans Georgian");
|
||||||
|
MapScriptToTypefaces["glag"].Insert(0, "Noto Sans Glagolitic");
|
||||||
|
MapScriptToTypefaces["goth"].Insert(0, "Noto Sans Gothic");
|
||||||
|
MapScriptToTypefaces["gran"].Insert(0, "Noto Sans Grantha");
|
||||||
|
MapScriptToTypefaces["gujr"].Insert(0, "Noto Sans Gujarati");
|
||||||
|
MapScriptToTypefaces["gong"].Insert(0, "Noto Sans Gunjala Gondi");
|
||||||
|
MapScriptToTypefaces["guru"].Insert(0, "Noto Sans Gurmukhi");
|
||||||
|
MapScriptToTypefaces["rohg"].Insert(0, "Noto Sans Hanifi Rohingya");
|
||||||
|
MapScriptToTypefaces["hano"].Insert(0, "Noto Sans Hanunoo");
|
||||||
|
MapScriptToTypefaces["hatr"].Insert(0, "Noto Sans Hatran");
|
||||||
|
MapScriptToTypefaces["hebr"].Insert(0, "Noto Sans Hebrew");
|
||||||
|
MapScriptToTypefaces["armi"].Insert(0, "Noto Sans Imperial Aramaic");
|
||||||
|
MapScriptToTypefaces["phli"].Insert(0, "Noto Sans Inscriptional Pahlavi");
|
||||||
|
MapScriptToTypefaces["prti"].Insert(0, "Noto Sans Inscriptional Parthian");
|
||||||
|
MapScriptToTypefaces["java"].Insert(0, "Noto Sans Javanese");
|
||||||
|
MapScriptToTypefaces["kthi"].Insert(0, "Noto Sans Kaithi");
|
||||||
|
MapScriptToTypefaces["knda"].Insert(0, "Noto Sans Kannada");
|
||||||
|
MapScriptToTypefaces["kali"].Insert(0, "Noto Sans KayahLi");
|
||||||
|
MapScriptToTypefaces["khar"].Insert(0, "Noto Sans Kharoshthi");
|
||||||
|
MapScriptToTypefaces["khmr"].Insert(0, "Noto Sans Khmer");
|
||||||
|
MapScriptToTypefaces["khoj"].Insert(0, "Noto Sans Khojki");
|
||||||
|
MapScriptToTypefaces["laoo"].Insert(0, "Noto Sans Lao");
|
||||||
|
MapScriptToTypefaces["lepc"].Insert(0, "Noto Sans Lepcha");
|
||||||
|
MapScriptToTypefaces["limb"].Insert(0, "Noto Sans Limbu");
|
||||||
|
MapScriptToTypefaces["lina"].Insert(0, "Noto Sans Linear A");
|
||||||
|
MapScriptToTypefaces["linb"].Insert(0, "Noto Sans Linear B");
|
||||||
|
MapScriptToTypefaces["lisu"].Insert(0, "Noto Sans Lisu");
|
||||||
|
MapScriptToTypefaces["lyci"].Insert(0, "Noto Sans Lycian");
|
||||||
|
MapScriptToTypefaces["lydi"].Insert(0, "Noto Sans Lydian");
|
||||||
|
MapScriptToTypefaces["mlym"].Insert(0, "Noto Sans Malayalam");
|
||||||
|
MapScriptToTypefaces["mand"].Insert(0, "Noto Sans Mandiac");
|
||||||
|
MapScriptToTypefaces["mani"].Insert(0, "Noto Sans Manichaean");
|
||||||
|
MapScriptToTypefaces["marc"].Insert(0, "Noto Sans Marchen");
|
||||||
|
MapScriptToTypefaces["gonm"].Insert(0, "Noto Sans Masaram Gondi");
|
||||||
|
MapScriptToTypefaces["medf"].Insert(0, "Noto Sans Medefaidrin");
|
||||||
|
MapScriptToTypefaces["mtei"].Insert(0, "Noto Sans Meetei Mayek");
|
||||||
|
MapScriptToTypefaces["merc"].Insert(0, "Noto Sans Meroitic");
|
||||||
|
MapScriptToTypefaces["mero"].Insert(0, "Noto Sans Meroitic");
|
||||||
|
MapScriptToTypefaces["plrd"].Insert(0, "Noto Sans Miao");
|
||||||
|
MapScriptToTypefaces["modi"].Insert(0, "Noto Sans Modi");
|
||||||
|
MapScriptToTypefaces["mong"].Insert(0, "Noto Sans Mongolian");
|
||||||
|
MapScriptToTypefaces["mroo"].Insert(0, "Noto Sans Mro");
|
||||||
|
MapScriptToTypefaces["mult"].Insert(0, "Noto Sans Multani");
|
||||||
|
MapScriptToTypefaces["mymr"].Insert(0, "Noto Sans Myanmar");
|
||||||
|
MapScriptToTypefaces["nkoo"].Insert(0, "Noto Sans Nko");
|
||||||
|
MapScriptToTypefaces["nbat"].Insert(0, "Noto Sans Nabataean");
|
||||||
|
MapScriptToTypefaces["talu"].Insert(0, "Noto Sans New Tai Lue");
|
||||||
|
MapScriptToTypefaces["newa"].Insert(0, "Noto Sans Newa");
|
||||||
|
MapScriptToTypefaces["ogam"].Insert(0, "Noto Sans Ogham");
|
||||||
|
MapScriptToTypefaces["olck"].Insert(0, "Noto Sans Ol Chiki");
|
||||||
|
MapScriptToTypefaces["ital"].Insert(0, "Noto Sans Old Italian");
|
||||||
|
MapScriptToTypefaces["narb"].Insert(0, "Noto Sans Old North Arabian");
|
||||||
|
MapScriptToTypefaces["perm"].Insert(0, "Noto Sans Old Permic");
|
||||||
|
MapScriptToTypefaces["xpeo"].Insert(0, "Noto Sans Old Persian");
|
||||||
|
MapScriptToTypefaces["sarb"].Insert(0, "Noto Sans Old South Arabian");
|
||||||
|
MapScriptToTypefaces["orkh"].Insert(0, "Noto Sans Old Turkic");
|
||||||
|
MapScriptToTypefaces["orya"].Insert(0, "Noto Sans Oriya");
|
||||||
|
MapScriptToTypefaces["osge"].Insert(0, "Noto Sans Osage");
|
||||||
|
MapScriptToTypefaces["osma"].Insert(0, "Noto Sans Osmanya");
|
||||||
|
MapScriptToTypefaces["hmng"].Insert(0, "Noto Sans Pahawh Hmong");
|
||||||
|
MapScriptToTypefaces["palm"].Insert(0, "Noto Sans Palmyrene");
|
||||||
|
MapScriptToTypefaces["pauc"].Insert(0, "Noto Sans Pau Cin Hau");
|
||||||
|
MapScriptToTypefaces["phag"].Insert(0, "Noto Sans Phags Pa");
|
||||||
|
MapScriptToTypefaces["phnx"].Insert(0, "Noto Sans Phoenician");
|
||||||
|
MapScriptToTypefaces["rjng"].Insert(0, "Noto Sans Rejang");
|
||||||
|
MapScriptToTypefaces["runr"].Insert(0, "Noto Sans Runic");
|
||||||
|
MapScriptToTypefaces["samr"].Insert(0, "Noto Sans Samaritan");
|
||||||
|
MapScriptToTypefaces["saur"].Insert(0, "Noto Sans Saurashtra");
|
||||||
|
MapScriptToTypefaces["shrd"].Insert(0, "Noto Sans Sharada");
|
||||||
|
MapScriptToTypefaces["shaw"].Insert(0, "Noto Sans Shavian");
|
||||||
|
MapScriptToTypefaces["sinh"].Insert(0, "Noto Sans Sinhala");
|
||||||
|
MapScriptToTypefaces["sora"].Insert(0, "Noto Sans Sora Sompeng");
|
||||||
|
MapScriptToTypefaces["soyo"].Insert(0, "Noto Sans Soyombo");
|
||||||
|
MapScriptToTypefaces["sund"].Insert(0, "Noto Sans Sundanese");
|
||||||
|
MapScriptToTypefaces["sylo"].Insert(0, "Noto Sans Syloti Nagri");
|
||||||
|
MapScriptToTypefaces["zsym"].Insert(0, "Noto Sans Symbols");
|
||||||
|
MapScriptToTypefaces["syrn"].Insert(0, "Noto Sans Syriac Eastern");
|
||||||
|
MapScriptToTypefaces["syre"].Insert(0, "Noto Sans Syriac Estrangela");
|
||||||
|
MapScriptToTypefaces["syrj"].Insert(0, "Noto Sans Syriac Western");
|
||||||
|
MapScriptToTypefaces["tglg"].Insert(0, "Noto Sans Tagalog");
|
||||||
|
MapScriptToTypefaces["tagb"].Insert(0, "Noto Sans Tagbanwa");
|
||||||
|
MapScriptToTypefaces["tale"].Insert(0, "Noto Sans Tai Le");
|
||||||
|
MapScriptToTypefaces["lana"].Insert(0, "Noto Sans Tai Tham");
|
||||||
|
MapScriptToTypefaces["tavt"].Insert(0, "Noto Sans Tai Viet");
|
||||||
|
MapScriptToTypefaces["takr"].Insert(0, "Noto Sans Takri");
|
||||||
|
MapScriptToTypefaces["taml"].Insert(0, "Noto Sans Tamil");
|
||||||
|
MapScriptToTypefaces["telu"].Insert(0, "Noto Sans Telugu");
|
||||||
|
MapScriptToTypefaces["thaa"].Insert(0, "Noto Sans Thaana");
|
||||||
|
MapScriptToTypefaces["thai"].Insert(0, "Noto Sans Thai");
|
||||||
|
MapScriptToTypefaces["tfng"].Insert(0, "Noto Sans Tifinagh");
|
||||||
|
MapScriptToTypefaces["ugar"].Insert(0, "Noto Sans Ugaritic");
|
||||||
|
MapScriptToTypefaces["vaii"].Insert(0, "Noto Sans Vai");
|
||||||
|
MapScriptToTypefaces["wcho"].Insert(0, "Noto Sans Wancho");
|
||||||
|
MapScriptToTypefaces["wara"].Insert(0, "Noto Sans Warang Citi");
|
||||||
|
MapScriptToTypefaces["yiii"].Insert(0, "Noto Sans Yi");
|
||||||
|
}
|
||||||
|
public FallbackListFontMatcher(FontManager manager) : base(manager) { }
|
||||||
|
public override IEnumerable<Typeface> MatchScript(string script = null, bool distinctFamily = false) {
|
||||||
|
if (string.IsNullOrEmpty(script)) script = ScriptUtils.UltimateFallbackScript;
|
||||||
|
List<string> candidates;
|
||||||
|
IEnumerable<string> candidateScripts = new string[] { script };
|
||||||
|
while (candidateScripts != null) {
|
||||||
|
foreach (var candidateScript in candidateScripts) {
|
||||||
|
if (MapScriptToTypefaces.TryGetValue(candidateScript, out candidates)) {
|
||||||
|
foreach (var candidate in candidates) {
|
||||||
|
IReadOnlyCollection<Typeface> typefaces1;
|
||||||
|
if (Manager.MapFullNameToTypeface.TryGetValue(candidate, out typefaces1)) {
|
||||||
|
foreach (var typeface in typefaces1) {
|
||||||
|
yield return typeface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (distinctFamily) continue;
|
||||||
|
IReadOnlyCollection<Typeface> typefaces2;
|
||||||
|
if (Manager.MapNameToTypefaces.TryGetValue(candidate, out typefaces2)) {
|
||||||
|
foreach (var typeface in typefaces2) {
|
||||||
|
if (typefaces1.Contains(typeface)) continue;
|
||||||
|
yield return typeface;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
candidateScripts = ScriptUtils.EnumerateFallbackScripts(script);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Font/FontMatcher.cs.meta
Normal file
11
Assets/Cryville/Common/Font/FontMatcher.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: afcde0ad1865db24da79ca1ce7256791
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
222
Assets/Cryville/Common/Font/FontTable.cs
Normal file
222
Assets/Cryville/Common/Font/FontTable.cs
Normal file
@@ -0,0 +1,222 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Font {
|
||||||
|
public abstract class FontTable<T> {
|
||||||
|
protected UInt32 Offset { get; private set; }
|
||||||
|
protected BinaryReader Reader { get; private set; }
|
||||||
|
|
||||||
|
protected FontTable(BinaryReader reader, UInt32 offset) {
|
||||||
|
Reader = reader;
|
||||||
|
Offset = offset;
|
||||||
|
reader.BaseStream.Position = offset;
|
||||||
|
}
|
||||||
|
public abstract IReadOnlyList<T> GetItems();
|
||||||
|
}
|
||||||
|
public abstract class FontTable<T, U> : FontTable<T> {
|
||||||
|
protected FontTable(BinaryReader reader, UInt32 offset) : base(reader, offset) { }
|
||||||
|
public abstract U GetSubTable(T item);
|
||||||
|
}
|
||||||
|
public sealed class TTCHeader : FontTable<UInt32, TableDirectory> {
|
||||||
|
readonly String ttcTag;
|
||||||
|
readonly UInt16 majorVersion;
|
||||||
|
readonly UInt16 minorVersion;
|
||||||
|
readonly UInt32 numFonts;
|
||||||
|
readonly List<UInt32> tableDirectoryOffsets = new List<UInt32>();
|
||||||
|
readonly String dsigTag;
|
||||||
|
readonly UInt32 dsigLength;
|
||||||
|
readonly UInt32 dsigOffset;
|
||||||
|
public TTCHeader(BinaryReader reader, UInt32 offset) : base(reader, offset) {
|
||||||
|
ttcTag = reader.ReadTag();
|
||||||
|
if (ttcTag != "ttcf") throw new NotImplementedException();
|
||||||
|
majorVersion = reader.ReadUInt16();
|
||||||
|
minorVersion = reader.ReadUInt16();
|
||||||
|
numFonts = reader.ReadUInt32();
|
||||||
|
for (UInt32 i = 0; i < numFonts; i++) tableDirectoryOffsets.Add(reader.ReadUInt32());
|
||||||
|
if (majorVersion == 2) {
|
||||||
|
dsigTag = reader.ReadTag();
|
||||||
|
dsigLength = reader.ReadUInt32();
|
||||||
|
dsigOffset = reader.ReadUInt32();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public override IReadOnlyList<UInt32> GetItems() {
|
||||||
|
return tableDirectoryOffsets;
|
||||||
|
}
|
||||||
|
public override TableDirectory GetSubTable(UInt32 item) {
|
||||||
|
var i = item;
|
||||||
|
return new TableDirectory(Reader, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public sealed class TableDirectory : FontTable<TableRecord, object> {
|
||||||
|
readonly UInt32 sfntVersion;
|
||||||
|
readonly UInt16 numTables;
|
||||||
|
readonly UInt16 searchRange;
|
||||||
|
readonly UInt16 entrySelector;
|
||||||
|
readonly UInt16 rangeShift;
|
||||||
|
readonly List<TableRecord> tableRecords = new List<TableRecord>();
|
||||||
|
public TableDirectory(BinaryReader reader, UInt32 offset) : base(reader, offset) {
|
||||||
|
sfntVersion = reader.ReadUInt32();
|
||||||
|
numTables = reader.ReadUInt16();
|
||||||
|
searchRange = reader.ReadUInt16();
|
||||||
|
entrySelector = reader.ReadUInt16();
|
||||||
|
rangeShift = reader.ReadUInt16();
|
||||||
|
for (int i = 0; i < numTables; i++)
|
||||||
|
tableRecords.Add(new TableRecord {
|
||||||
|
tableTag = reader.ReadTag(),
|
||||||
|
checksum = reader.ReadUInt32(),
|
||||||
|
offset = reader.ReadUInt32(),
|
||||||
|
length = reader.ReadUInt32(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
public override IReadOnlyList<TableRecord> GetItems() {
|
||||||
|
return tableRecords;
|
||||||
|
}
|
||||||
|
public override object GetSubTable(TableRecord item) {
|
||||||
|
switch (item.tableTag) {
|
||||||
|
case "name": return new NameTable(Reader, item.offset);
|
||||||
|
case "meta": return new MetaTable(Reader, item.offset);
|
||||||
|
default: throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public struct TableRecord {
|
||||||
|
public string tableTag;
|
||||||
|
public UInt32 checksum;
|
||||||
|
public UInt32 offset;
|
||||||
|
public UInt32 length;
|
||||||
|
}
|
||||||
|
public sealed class NameTable : FontTable<NameRecord> {
|
||||||
|
readonly UInt16 version;
|
||||||
|
readonly UInt16 count;
|
||||||
|
readonly UInt16 storageOffset;
|
||||||
|
readonly List<NameRecord> nameRecord = new List<NameRecord>();
|
||||||
|
readonly UInt16 langTagCount;
|
||||||
|
readonly List<LangTagRecord> langTagRecord = new List<LangTagRecord>();
|
||||||
|
public NameTable(BinaryReader reader, UInt32 offset) : base(reader, offset) {
|
||||||
|
version = reader.ReadUInt16();
|
||||||
|
count = reader.ReadUInt16();
|
||||||
|
storageOffset = reader.ReadUInt16();
|
||||||
|
for (UInt16 i = 0; i < count; i++)
|
||||||
|
nameRecord.Add(new NameRecord {
|
||||||
|
platformID = reader.ReadUInt16(),
|
||||||
|
encodingID = reader.ReadUInt16(),
|
||||||
|
languageID = reader.ReadUInt16(),
|
||||||
|
nameID = (NameID)reader.ReadUInt16(),
|
||||||
|
length = reader.ReadUInt16(),
|
||||||
|
stringOffset = reader.ReadUInt16(),
|
||||||
|
});
|
||||||
|
if (version == 1) {
|
||||||
|
langTagCount = reader.ReadUInt16();
|
||||||
|
for (UInt16 i = 0; i < langTagCount; i++)
|
||||||
|
langTagRecord.Add(new LangTagRecord {
|
||||||
|
length = reader.ReadUInt16(),
|
||||||
|
langTagOffset = reader.ReadUInt16(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
UInt32 origin = (UInt32)reader.BaseStream.Position;
|
||||||
|
for (int i = 0; i < nameRecord.Count; i++) nameRecord[i] = nameRecord[i].Load(reader, origin);
|
||||||
|
for (int i = 0; i < langTagRecord.Count; i++) langTagRecord[i] = langTagRecord[i].Load(reader, origin);
|
||||||
|
}
|
||||||
|
public sealed override IReadOnlyList<NameRecord> GetItems() {
|
||||||
|
return nameRecord;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public struct NameRecord {
|
||||||
|
public UInt16 platformID;
|
||||||
|
public UInt16 encodingID;
|
||||||
|
public UInt16 languageID;
|
||||||
|
public NameID nameID;
|
||||||
|
public UInt16 length;
|
||||||
|
public UInt16 stringOffset;
|
||||||
|
public String value { get; private set; }
|
||||||
|
public NameRecord Load(BinaryReader reader, UInt32 origin) {
|
||||||
|
reader.BaseStream.Position = origin + stringOffset;
|
||||||
|
Encoding encoding;
|
||||||
|
switch (platformID) {
|
||||||
|
case 0: encoding = Encoding.BigEndianUnicode; break;
|
||||||
|
case 3: encoding = Encoding.BigEndianUnicode; break;
|
||||||
|
default: return this;
|
||||||
|
}
|
||||||
|
value = encoding.GetString(reader.ReadBytes(length));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public enum NameID : UInt16 {
|
||||||
|
CopyrightNotice = 0,
|
||||||
|
FontFamilyName = 1,
|
||||||
|
FontSubfamilyName = 2,
|
||||||
|
UniqueFontIdentifier = 3,
|
||||||
|
FullFontName = 4,
|
||||||
|
VersionString = 5,
|
||||||
|
PostScriptName = 6,
|
||||||
|
Trademark = 7,
|
||||||
|
ManufacturerName = 8,
|
||||||
|
Designer = 9,
|
||||||
|
Description = 10,
|
||||||
|
URLVendor = 11,
|
||||||
|
URLDesigner = 12,
|
||||||
|
LicenseDescription = 13,
|
||||||
|
LicenseInfoURL = 14,
|
||||||
|
|
||||||
|
TypographicFamilyName = 16,
|
||||||
|
TypographicSubfamilyName = 17,
|
||||||
|
CompatibleFull = 18,
|
||||||
|
SampleText = 19,
|
||||||
|
PostScriptCIDFindfontName = 20,
|
||||||
|
WWSFamilyName = 21,
|
||||||
|
WWSSubfamilyName = 22,
|
||||||
|
LightBackgroundPalette = 23,
|
||||||
|
DarkBackgroundPalette = 24,
|
||||||
|
VariationsPostScriptNamePrefix = 25,
|
||||||
|
}
|
||||||
|
public struct LangTagRecord {
|
||||||
|
public UInt16 length;
|
||||||
|
public UInt16 langTagOffset;
|
||||||
|
public String value { get; private set; }
|
||||||
|
public LangTagRecord Load(BinaryReader reader, UInt32 origin) {
|
||||||
|
reader.BaseStream.Position = origin + langTagOffset;
|
||||||
|
value = Encoding.BigEndianUnicode.GetString(reader.ReadBytes(length));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public sealed class MetaTable : FontTable<DataMap> {
|
||||||
|
readonly UInt32 version;
|
||||||
|
readonly UInt32 flags;
|
||||||
|
readonly UInt32 dataMapCount;
|
||||||
|
readonly List<DataMap> dataMaps = new List<DataMap>();
|
||||||
|
public MetaTable(BinaryReader reader, UInt32 offset) : base(reader, offset) {
|
||||||
|
version = reader.ReadUInt32();
|
||||||
|
flags = reader.ReadUInt32();
|
||||||
|
reader.ReadUInt32();
|
||||||
|
dataMapCount = reader.ReadUInt32();
|
||||||
|
for (UInt32 i = 0; i < dataMapCount; i++)
|
||||||
|
dataMaps.Add(new DataMap {
|
||||||
|
tag = reader.ReadTag(),
|
||||||
|
dataOffset = reader.ReadUInt32(),
|
||||||
|
dataLength = reader.ReadUInt32(),
|
||||||
|
});
|
||||||
|
for (int i = 0; i < dataMaps.Count; i++) dataMaps[i] = dataMaps[i].Load(reader, offset);
|
||||||
|
}
|
||||||
|
public sealed override IReadOnlyList<DataMap> GetItems() {
|
||||||
|
return dataMaps;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public struct DataMap {
|
||||||
|
public String tag;
|
||||||
|
public UInt32 dataOffset;
|
||||||
|
public UInt32 dataLength;
|
||||||
|
public String value { get; private set; }
|
||||||
|
public DataMap Load(BinaryReader reader, UInt32 origin) {
|
||||||
|
reader.BaseStream.Position = origin + dataOffset;
|
||||||
|
value = Encoding.ASCII.GetString(reader.ReadBytes((int)dataLength));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public static class BinaryReaderExtensions {
|
||||||
|
public static string ReadTag(this BinaryReader reader) {
|
||||||
|
return Encoding.ASCII.GetString(reader.ReadBytes(4));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Font/FontTable.cs.meta
Normal file
11
Assets/Cryville/Common/Font/FontTable.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 3eed6aa2387582346b7b21c6f8de5e1f
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
using System.Globalization;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Font {
|
|
||||||
public static class FontUtil {
|
|
||||||
/*public static string MatchFontNameWithLang(string lang) {
|
|
||||||
|
|
||||||
}*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
31
Assets/Cryville/Common/Font/Typeface.cs
Normal file
31
Assets/Cryville/Common/Font/Typeface.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Font {
|
||||||
|
public abstract class Typeface {
|
||||||
|
public FileInfo File { get; private set; }
|
||||||
|
public int IndexInFile { get; private set; }
|
||||||
|
public string FamilyName { get; protected set; }
|
||||||
|
public string SubfamilyName { get; protected set; }
|
||||||
|
public string FullName { get; protected set; }
|
||||||
|
protected abstract void GetName(BinaryReader reader);
|
||||||
|
|
||||||
|
public Typeface(BinaryReader reader, FileInfo file, int index) {
|
||||||
|
File = file;
|
||||||
|
IndexInFile = index;
|
||||||
|
GetName(reader);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public class TypefaceTTF : Typeface {
|
||||||
|
public TypefaceTTF(BinaryReader reader, FileInfo file, int index)
|
||||||
|
: base(reader, file, index) { }
|
||||||
|
|
||||||
|
protected override void GetName(BinaryReader reader) {
|
||||||
|
var dir = new TableDirectory(reader, (uint)reader.BaseStream.Position);
|
||||||
|
var nameTable = (NameTable)dir.GetSubTable((from i in dir.GetItems() where i.tableTag == "name" select i).Single());
|
||||||
|
FamilyName = (from i in nameTable.GetItems() where i.nameID == NameID.FontFamilyName && i.value != null select i.value).First();
|
||||||
|
SubfamilyName = (from i in nameTable.GetItems() where i.nameID == NameID.FontSubfamilyName && i.value != null select i.value).First();
|
||||||
|
FullName = (from i in nameTable.GetItems() where i.nameID == NameID.FullFontName && i.value != null select i.value).First();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user