Compare commits
178 Commits
b407ba88c4
...
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.
@@ -1,7 +1,8 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 215ebdd4cb9187741a2e24f5e7d8511d
|
guid: 2e0c61e29fd90f04b9e41265d93e2029
|
||||||
DefaultImporter:
|
NativeFormatImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
|
mainObjectFileID: 7400000
|
||||||
userData:
|
userData:
|
||||||
assetBundleName:
|
assetBundleName:
|
||||||
assetBundleVariant:
|
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.
Binary file not shown.
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: 4ffe72fef6ebb9e4da3571b4117f0d6d
|
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) { }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: dbc046e7cabacbb4fbf74520399a7340
|
guid: c4ef48e4a4983de4e9c31483df2a918e
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 6823ead66b33bc048bbad48719feb25d
|
guid: 9ec674235c0dd6744af2dab2b58dd53c
|
||||||
folderAsset: yes
|
folderAsset: yes
|
||||||
DefaultImporter:
|
DefaultImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
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: f5b3f3294f679f14f8ec1195b0def630
|
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,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: 23377bf2926d93a4b8e3f3ab6040c7f2
|
guid: 2517e8f040bd36f46948e5fafaf5335c
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
fileFormatVersion: 2
|
fileFormatVersion: 2
|
||||||
guid: e3c5a8bf05d5e284ba498e91cb0dd35e
|
guid: d9ed5ea8b7b1a934287e7ec5971166c0
|
||||||
MonoImporter:
|
MonoImporter:
|
||||||
externalObjects: {}
|
externalObjects: {}
|
||||||
serializedVersion: 2
|
serializedVersion: 2
|
||||||
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:
|
||||||
@@ -3,7 +3,6 @@ using System;
|
|||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Text;
|
|
||||||
|
|
||||||
namespace Cryville.Common.Font {
|
namespace Cryville.Common.Font {
|
||||||
public abstract class FontFile : IEnumerable<Typeface> {
|
public abstract class FontFile : IEnumerable<Typeface> {
|
||||||
|
|||||||
@@ -1,30 +1,30 @@
|
|||||||
using Cryville.Common.Culture;
|
using System.Collections.Generic;
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace Cryville.Common.Font {
|
namespace Cryville.Common.Font {
|
||||||
public abstract class FontManager {
|
public abstract class FontManager {
|
||||||
protected IReadOnlyDictionary<string, Typeface> MapFullNameToTypeface { get; private set; }
|
public IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapFullNameToTypeface { get; private set; }
|
||||||
protected IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapNameToTypefaces { get; private set; }
|
public IReadOnlyDictionary<string, IReadOnlyCollection<Typeface>> MapNameToTypefaces { get; private set; }
|
||||||
public FontManager() {
|
public FontManager() {
|
||||||
var map1 = new Dictionary<string, Typeface>();
|
var map1 = new Dictionary<string, List<Typeface>>();
|
||||||
var map2 = new Dictionary<string, List<Typeface>>();
|
var map2 = new Dictionary<string, List<Typeface>>();
|
||||||
foreach (var f in EnumerateAllTypefaces()) {
|
foreach (var f in EnumerateAllTypefaces()) {
|
||||||
map1.Add(f.FullName, f);
|
List<Typeface> set1;
|
||||||
List<Typeface> set;
|
if (!map1.TryGetValue(f.FullName, out set1)) {
|
||||||
if (!map2.TryGetValue(f.FamilyName, out set)) {
|
map1.Add(f.FullName, set1 = new List<Typeface>());
|
||||||
map2.Add(f.FamilyName, set = new List<Typeface>());
|
|
||||||
}
|
}
|
||||||
set.Add(f);
|
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;
|
MapFullNameToTypeface = map1.ToDictionary(i => i.Key, i => (IReadOnlyCollection<Typeface>)i.Value);
|
||||||
MapNameToTypefaces = map2.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 abstract IEnumerable<Typeface> EnumerateAllTypefaces();
|
||||||
public abstract IEnumerable<Typeface> MatchScript(string script = null);
|
|
||||||
public abstract IEnumerable<Typeface> MatchFamily(string[] candidates);
|
|
||||||
protected static IEnumerable<Typeface> ScanDirectoryForTypefaces(string dir) {
|
protected static IEnumerable<Typeface> ScanDirectoryForTypefaces(string dir) {
|
||||||
foreach (var f in new DirectoryInfo(dir).EnumerateFiles()) {
|
foreach (var f in new DirectoryInfo(dir).EnumerateFiles()) {
|
||||||
FontFile file;
|
FontFile file;
|
||||||
@@ -54,195 +54,10 @@ namespace Cryville.Common.Font {
|
|||||||
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
|
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
|
||||||
return ScanDirectoryForTypefaces("/system/fonts");
|
return ScanDirectoryForTypefaces("/system/fonts");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<Typeface> MatchScript(string script = null) {
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Typeface> MatchFamily(string[] candidates) {
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
public class FontManagerWindows : FontManager {
|
public class FontManagerWindows : FontManager {
|
||||||
public static Dictionary<string, List<string>> MapScriptToTypefaces = new Dictionary<string, List<string>>();
|
|
||||||
|
|
||||||
static FontManagerWindows() {
|
|
||||||
if (Environment.OSVersion.Platform != PlatformID.Win32NT) return;
|
|
||||||
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, "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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
|
protected override IEnumerable<Typeface> EnumerateAllTypefaces() {
|
||||||
return ScanDirectoryForTypefaces("C:/Windows/Fonts");
|
return ScanDirectoryForTypefaces("C:/Windows/Fonts");
|
||||||
}
|
}
|
||||||
|
|
||||||
public override IEnumerable<Typeface> MatchScript(string script = null) {
|
|
||||||
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) {
|
|
||||||
Typeface typeface;
|
|
||||||
if (MapFullNameToTypeface.TryGetValue(candidate, out typeface)) {
|
|
||||||
yield return typeface;
|
|
||||||
}
|
|
||||||
IReadOnlyCollection<Typeface> typefaces;
|
|
||||||
if (MapNameToTypefaces.TryGetValue(candidate, out typefaces)) {
|
|
||||||
foreach (var typeface2 in typefaces) {
|
|
||||||
if (typeface2 == typeface) continue;
|
|
||||||
yield return typeface2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
candidateScripts = ScriptUtils.EnumerateFallbackScripts(script);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public override IEnumerable<Typeface> MatchFamily(string[] candidates) {
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
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:
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace Cryville.Common.Font {
|
namespace Cryville.Common.Font {
|
||||||
@@ -46,7 +45,7 @@ namespace Cryville.Common.Font {
|
|||||||
return tableDirectoryOffsets;
|
return tableDirectoryOffsets;
|
||||||
}
|
}
|
||||||
public override TableDirectory GetSubTable(UInt32 item) {
|
public override TableDirectory GetSubTable(UInt32 item) {
|
||||||
var i = (UInt32)item;
|
var i = item;
|
||||||
return new TableDirectory(Reader, i);
|
return new TableDirectory(Reader, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -77,6 +76,7 @@ namespace Cryville.Common.Font {
|
|||||||
public override object GetSubTable(TableRecord item) {
|
public override object GetSubTable(TableRecord item) {
|
||||||
switch (item.tableTag) {
|
switch (item.tableTag) {
|
||||||
case "name": return new NameTable(Reader, item.offset);
|
case "name": return new NameTable(Reader, item.offset);
|
||||||
|
case "meta": return new MetaTable(Reader, item.offset);
|
||||||
default: throw new NotImplementedException();
|
default: throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -120,7 +120,7 @@ namespace Cryville.Common.Font {
|
|||||||
for (int i = 0; i < langTagRecord.Count; i++) langTagRecord[i] = langTagRecord[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() {
|
public sealed override IReadOnlyList<NameRecord> GetItems() {
|
||||||
return nameRecord.Cast<NameRecord>().ToList();
|
return nameRecord;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public struct NameRecord {
|
public struct NameRecord {
|
||||||
@@ -181,6 +181,39 @@ namespace Cryville.Common.Font {
|
|||||||
return this;
|
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 class BinaryReaderExtensions {
|
||||||
public static string ReadTag(this BinaryReader reader) {
|
public static string ReadTag(this BinaryReader reader) {
|
||||||
return Encoding.ASCII.GetString(reader.ReadBytes(4));
|
return Encoding.ASCII.GetString(reader.ReadBytes(4));
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
namespace Cryville.Common {
|
namespace Cryville.Common {
|
||||||
public struct Identifier : IEquatable<Identifier> {
|
public struct Identifier : IEquatable<Identifier> {
|
||||||
|
public static Identifier Empty = new Identifier(0);
|
||||||
public int Key { get; private set; }
|
public int Key { get; private set; }
|
||||||
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
|
public object Name { get { return IdentifierManager.SharedInstance.Retrieve(Key); } }
|
||||||
public Identifier(int key) {
|
public Identifier(int key) {
|
||||||
@@ -24,11 +25,11 @@ namespace Cryville.Common {
|
|||||||
if (Key == 0) return "";
|
if (Key == 0) return "";
|
||||||
return Name.ToString();
|
return Name.ToString();
|
||||||
}
|
}
|
||||||
public static implicit operator Identifier(string identifier) {
|
public static bool operator ==(Identifier lhs, Identifier rhs) {
|
||||||
return new Identifier(identifier);
|
return lhs.Equals(rhs);
|
||||||
}
|
}
|
||||||
public static implicit operator string(Identifier identifier) {
|
public static bool operator !=(Identifier lhs, Identifier rhs) {
|
||||||
return identifier.ToString();
|
return !lhs.Equals(rhs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -54,16 +54,13 @@ namespace Cryville.Common.Math {
|
|||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a <see cref="System.Single" /> column vector and fills it with polynomial coefficients.
|
/// Fills a <see cref="System.Single" /> column vector with polynomial coefficients.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="size">The size of the column vector.</param>
|
/// <param name="vec">The column vector.</param>
|
||||||
/// <param name="num">The base number.</param>
|
/// <param name="num">The base number.</param>
|
||||||
/// <returns>A <see cref="System.Single" /> column vector filled with polynomial coefficients.</returns>
|
public static void FillWithPolynomialCoefficients(ColumnVector<float> vec, float num) {
|
||||||
public static ColumnVector<float> WithPolynomialCoefficients(int size, float num) {
|
for (var i = 0; i < vec.Size; i++)
|
||||||
var m = new ColumnVector<float>(size);
|
vec[i] = (float)System.Math.Pow(num, i);
|
||||||
for (var i = 0; i < size; i++)
|
|
||||||
m[i] = (float)System.Math.Pow(num, i);
|
|
||||||
return m;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
44
Assets/Cryville/Common/Math/CubicBezier.cs
Normal file
44
Assets/Cryville/Common/Math/CubicBezier.cs
Normal file
@@ -0,0 +1,44 @@
|
|||||||
|
using SMath = System.Math;
|
||||||
|
|
||||||
|
namespace Cryville.Common.Math {
|
||||||
|
// Ported from https://github.com/arian/cubic-bezier/blob/master/index.js
|
||||||
|
public static class CubicBezier {
|
||||||
|
public static float Evaluate(float t, float x1, float y1, float x2, float y2, float epsilon) {
|
||||||
|
float x = t, t0, t1, t2, tx, d2, i;
|
||||||
|
for (t2 = x, i = 0; i < 8; i++) {
|
||||||
|
tx = CurveX(t2, x1, x2) - x;
|
||||||
|
if (SMath.Abs(tx) < epsilon) return CurveY(t2, y1, y2);
|
||||||
|
d2 = DerivativeCurveX(t2, x1, x2);
|
||||||
|
if (SMath.Abs(d2) < 1e-6) break;
|
||||||
|
t2 -= tx / d2;
|
||||||
|
}
|
||||||
|
|
||||||
|
t0 = 0; t1 = 1; t2 = x;
|
||||||
|
|
||||||
|
if (t2 < t0) return CurveY(t0, y1, y2);
|
||||||
|
if (t2 > t1) return CurveY(t1, y1, y2);
|
||||||
|
|
||||||
|
while (t0 < t1) {
|
||||||
|
tx = CurveX(t2, x1, x2);
|
||||||
|
if (SMath.Abs(tx - x) < epsilon) return CurveY(t2, y1, y2);
|
||||||
|
if (x > tx) t0 = t2;
|
||||||
|
else t1 = t2;
|
||||||
|
t2 = (t1 - t0) * .5f + t0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return CurveY(t2, y1, y2);
|
||||||
|
}
|
||||||
|
static float CurveX(float t, float x1, float x2) {
|
||||||
|
float v = 1 - t;
|
||||||
|
return 3 * v * v * t * x1 + 3 * v * t * t * x2 + t * t * t;
|
||||||
|
}
|
||||||
|
static float CurveY(float t, float y1, float y2) {
|
||||||
|
float v = 1 - t;
|
||||||
|
return 3 * v * v * t * y1 + 3 * v * t * t * y2 + t * t * t;
|
||||||
|
}
|
||||||
|
static float DerivativeCurveX(float t, float x1, float x2) {
|
||||||
|
float v = 1 - t;
|
||||||
|
return 3 * (2 * (t - 1) * t + v * v) * x1 + 3 * (-t * t * t + 2 * v * t) * x2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
11
Assets/Cryville/Common/Math/CubicBezier.cs.meta
Normal file
11
Assets/Cryville/Common/Math/CubicBezier.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
fileFormatVersion: 2
|
||||||
|
guid: 17dd6f775fc965f43960da7166b55b87
|
||||||
|
MonoImporter:
|
||||||
|
externalObjects: {}
|
||||||
|
serializedVersion: 2
|
||||||
|
defaultReferences: []
|
||||||
|
executionOrder: 0
|
||||||
|
icon: {instanceID: 0}
|
||||||
|
userData:
|
||||||
|
assetBundleName:
|
||||||
|
assetBundleVariant:
|
||||||
@@ -12,12 +12,12 @@ namespace Cryville.Common.Math {
|
|||||||
/// <param name="error">The error.</param>
|
/// <param name="error">The error.</param>
|
||||||
/// <param name="n">The numerator.</param>
|
/// <param name="n">The numerator.</param>
|
||||||
/// <param name="d">The denominator.</param>
|
/// <param name="d">The denominator.</param>
|
||||||
/// <exception cref="ArgumentOutOfRangeException"><paramref name="value" /> is less than 0 or <paramref name="error" /> is not greater than 0 or not less than 1.</exception>
|
/// <exception cref="ArgumentOutOfRangeException"><paramref name="value" /> is less than 0 or <paramref name="error" /> is not greater than 0 or greater than 1.</exception>
|
||||||
public static void ToFraction(double value, double error, out int n, out int d) {
|
public static void ToFraction(double value, double error, out int n, out int d) {
|
||||||
if (value < 0.0)
|
if (value < 0.0)
|
||||||
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
|
throw new ArgumentOutOfRangeException("value", "Must be >= 0.");
|
||||||
if (error <= 0.0 || error >= 1.0)
|
if (error <= 0.0 || error > 1.0)
|
||||||
throw new ArgumentOutOfRangeException("accuracy", "Must be > 0 and < 1.");
|
throw new ArgumentOutOfRangeException("error", "Must be > 0 and <= 1.");
|
||||||
|
|
||||||
int num = (int)System.Math.Floor(value);
|
int num = (int)System.Math.Floor(value);
|
||||||
value -= num;
|
value -= num;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using UnsafeIL;
|
||||||
|
|
||||||
namespace Cryville.Common.Math {
|
namespace Cryville.Common.Math {
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -40,11 +40,11 @@ namespace Cryville.Common.Math {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The vector type.</typeparam>
|
/// <typeparam name="T">The vector type.</typeparam>
|
||||||
/// <param name="v">The column vector.</param>
|
/// <param name="v">The column vector.</param>
|
||||||
|
/// <param name="result">The result column vector.</param>
|
||||||
/// <param name="o">The column operator.</param>
|
/// <param name="o">The column operator.</param>
|
||||||
/// <returns>The column vector eliminated.</returns>
|
public void Eliminate<T>(ColumnVector<T> v, ColumnVector<T> result, IVectorOperator<T> o) {
|
||||||
public ColumnVector<T> Eliminate<T>(ColumnVector<T> v, IVectorOperator<T> o) {
|
|
||||||
int s = Size;
|
int s = Size;
|
||||||
Array.Copy(content, buffer, Size * Size);
|
FillBuffer();
|
||||||
for (int i = 0; i < s; i++) refl[i] = i;
|
for (int i = 0; i < s; i++) refl[i] = i;
|
||||||
for (int r = 0; r < s; r++) {
|
for (int r = 0; r < s; r++) {
|
||||||
for (int r0 = r; r0 < s; r0++)
|
for (int r0 = r; r0 < s; r0++)
|
||||||
@@ -66,14 +66,17 @@ namespace Cryville.Common.Math {
|
|||||||
v[or1] = o.Add(v[or1], o.ScalarMultiply(-sf1, v[or]));
|
v[or1] = o.Add(v[or1], o.ScalarMultiply(-sf1, v[or]));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ColumnVector<T> res = new ColumnVector<T>(s);
|
|
||||||
for (int r2 = s - 1; r2 >= 0; r2--) {
|
for (int r2 = s - 1; r2 >= 0; r2--) {
|
||||||
var v2 = v[refl[r2]];
|
var v2 = v[refl[r2]];
|
||||||
for (int c2 = r2 + 1; c2 < s; c2++)
|
for (int c2 = r2 + 1; c2 < s; c2++)
|
||||||
v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], res[refl[c2]]));
|
v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], result[refl[c2]]));
|
||||||
res[refl[r2]] = v2;
|
result[refl[r2]] = v2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
unsafe void FillBuffer() {
|
||||||
|
fixed (void* ptrc = content, ptrb = buffer) {
|
||||||
|
Unsafe.CopyBlock(ptrb, ptrc, (uint)(Size * Size * sizeof(float)));
|
||||||
}
|
}
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a square matrix and fills it with polynomial coefficients.
|
/// Creates a square matrix and fills it with polynomial coefficients.
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace Cryville.Common.Pdt {
|
namespace Cryville.Common.Pdt {
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the attributed member is an element list.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>An element list is a <see cref="System.Collections.IDictionary" /> or <see cref="Cryville.Common.Collections.Generic.IPairList" /> that represents a collection of PDT elements. There must be at most one element list in a class.</para>
|
||||||
|
/// </remarks>
|
||||||
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
public class ElementListAttribute : Attribute { }
|
public class ElementListAttribute : Attribute { }
|
||||||
public class ComponentListAttribute : Attribute { }
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the attributed member is a property list.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// <para>A property list is a <see cref="System.Collections.IDictionary" /> or <see cref="Cryville.Common.Collections.Generic.IPairList" /> that represents a collection of PDT properties. There must be at most one property list in a class.</para>
|
||||||
|
/// </remarks>
|
||||||
|
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
|
||||||
public class PropertyListAttribute : Attribute { }
|
public class PropertyListAttribute : Attribute { }
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
protected abstract PdtOperator GetOperator(PdtOperatorSignature sig);
|
protected abstract PdtOperator GetOperator(PdtOperatorSignature sig);
|
||||||
unsafe void Operate(PdtOperator op, int pc, bool noset = false) {
|
unsafe void Operate(PdtOperator op, int pc, bool noset = false) {
|
||||||
fixed (byte* pmem = _mem) {
|
fixed (byte* pmem = _mem) {
|
||||||
op.Begin(this);
|
op.Begin(this, pc);
|
||||||
for (int i = 0; i < pc; i++) {
|
for (int i = 0; i < pc; i++) {
|
||||||
var frame = _stack[--_framecount];
|
var frame = _stack[--_framecount];
|
||||||
op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length));
|
op.LoadOperand(new PdtVariableMemory(frame.Type, pmem + frame.Offset, frame.Length));
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Whether the value of this expression is constant.
|
/// Whether the value of this expression is constant.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <remarks>The value of this property is <c>false</c> until it is optimized.</remarks>
|
/// <remarks>The value of this property is <see langword="false" /> until it is optimized.</remarks>
|
||||||
public bool IsConstant { get; internal set; }
|
public bool IsConstant { get; internal set; }
|
||||||
internal bool IsPotentialConstant;
|
internal bool IsPotentialConstant;
|
||||||
internal PdtExpression(LinkedList<PdtInstruction> ins) {
|
internal PdtExpression(LinkedList<PdtInstruction> ins) {
|
||||||
@@ -92,7 +92,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public partial class PdtInterpreter {
|
public partial class PdtInterpreter {
|
||||||
readonly static Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
|
static readonly Dictionary<char, int> OP_PRIORITY = new Dictionary<char, int> {
|
||||||
{ '@', 7 },
|
{ '@', 7 },
|
||||||
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
{ '*', 6 }, { '/', 6 }, { '%', 6 },
|
||||||
{ '+', 5 }, { '-', 5 },
|
{ '+', 5 }, { '-', 5 },
|
||||||
@@ -103,7 +103,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
{ ',', 0 },
|
{ ',', 0 },
|
||||||
{ '$', -1 },
|
{ '$', -1 },
|
||||||
};
|
};
|
||||||
readonly static Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
|
static readonly Dictionary<char, int> OP_TYPE = new Dictionary<char, int> {
|
||||||
{ '@', 0 },
|
{ '@', 0 },
|
||||||
{ '*', 0 }, { '/', 0 }, { '%', 0 },
|
{ '*', 0 }, { '/', 0 }, { '%', 0 },
|
||||||
{ '+', 0 }, { '-', 0 },
|
{ '+', 0 }, { '-', 0 },
|
||||||
@@ -115,7 +115,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
{ '$', -1 },
|
{ '$', -1 },
|
||||||
};
|
};
|
||||||
|
|
||||||
readonly static PdtExpression _emptyexp;
|
static readonly PdtExpression _emptyexp;
|
||||||
static PdtInterpreter() {
|
static PdtInterpreter() {
|
||||||
var ins = new LinkedList<PdtInstruction>();
|
var ins = new LinkedList<PdtInstruction>();
|
||||||
ins.AddLast(new PdtInstruction.PushConstant(
|
ins.AddLast(new PdtInstruction.PushConstant(
|
||||||
@@ -143,7 +143,7 @@ namespace Cryville.Common.Pdt {
|
|||||||
public override string ToString() {
|
public override string ToString() {
|
||||||
return string.Format("0x{0:x4}: {1}", Type, Value);
|
return string.Format("0x{0:x4}: {1}", Type, Value);
|
||||||
}
|
}
|
||||||
public readonly static PdtExpToken EmptyOperator = new PdtExpToken {
|
public static readonly PdtExpToken EmptyOperator = new PdtExpToken {
|
||||||
Type = 0x0080,
|
Type = 0x0080,
|
||||||
Value = "$",
|
Value = "$",
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,30 +6,30 @@
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Error type.
|
/// Error type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Error = 0x00525245;
|
public const int Error = 0x00525245;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Array of a same variable-length type, with a suffix indicating the element count and the element type.
|
/// Array of a same variable-length type, with a suffix indicating the element count and the element type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Array = 0x00525241;
|
public const int Array = 0x00525241;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Null type.
|
/// Null type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Null = 0x4c4c554e;
|
public const int Null = 0x4c4c554e;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IEEE 754 32-bit floating-point number.
|
/// IEEE 754 32-bit floating-point number.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Number = 0x004d554e;
|
public const int Number = 0x004d554e;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
|
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int String = 0x00525453;
|
public const int String = 0x00525453;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units, representing the name of an undefined variable.
|
/// A sequence of UTF-16 code units, with a prefix indicating the number of the code units, representing the name of an undefined variable.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Undefined = 0x00444e55;
|
public const int Undefined = 0x00444e55;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Vector of a same constant-length type, with a suffix indicating the element type.
|
/// Vector of a same constant-length type, with a suffix indicating the element type.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public readonly static int Vector = 0x00434556;
|
public const int Vector = 0x00434556;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,5 @@
|
|||||||
using System;
|
using Cryville.Common.Collections;
|
||||||
|
using System;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -27,16 +28,16 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// <item><term><c>0x1000</c></term><description>End of Key</description></item>
|
/// <item><term><c>0x1000</c></term><description>End of Key</description></item>
|
||||||
/// </list>
|
/// </list>
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
readonly static int[] cm = new int[] {
|
static readonly int[] cm = new int[] {
|
||||||
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
// 0 1 2 3 4 5 6 7 8 9 A B C D E F
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0001, 0x0001, 0x0000, 0x0000, 0x0001, 0x0000, 0x0000,
|
||||||
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
|
||||||
0x0001, 0x0080, 0x0100, 0x0000, 0x0030, 0x0080, 0x0080, 0x0000, 0x0200, 0x0400, 0x0080, 0x0080, 0x0080, 0x0080, 0x0040, 0x0080,
|
0x0001, 0x0080, 0x0100, 0x0000, 0x0030, 0x0080, 0x0080, 0x0000, 0x0200, 0x0400, 0x0080, 0x0080, 0x0080, 0x0080, 0x0040, 0x0080,
|
||||||
0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x1000, 0x1800, 0x0080, 0x0080, 0x0080, 0x0030,
|
0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x0050, 0x1000, 0x1800, 0x0080, 0x0080, 0x0080, 0x0030,
|
||||||
0x0080, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
0x0080, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0000, 0x0000, 0x0000, 0x0030,
|
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0000, 0x0080, 0x0000, 0x0080, 0x0030,
|
||||||
0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
0x0000, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030,
|
||||||
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x1000, 0x0080, 0x1000, 0x0000, 0x0000,
|
0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x0030, 0x1000, 0x0080, 0x1000, 0x0080, 0x0000,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -54,43 +55,92 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// <param name="binder">The binder.</param>
|
/// <param name="binder">The binder.</param>
|
||||||
/// <returns>The interpreted object.</returns>
|
/// <returns>The interpreted object.</returns>
|
||||||
public static T Interpret<T>(string src, Binder binder) {
|
public static T Interpret<T>(string src, Binder binder) {
|
||||||
return (T)new PdtInterpreter(src, typeof(T), binder).Interpret();
|
return (T)new PdtInterpreter(src, binder).Interpret(typeof(T));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The source string.
|
||||||
|
/// </summary>
|
||||||
public string Source { get; private set; }
|
public string Source { get; private set; }
|
||||||
readonly Type _type;
|
Binder _binder;
|
||||||
readonly Binder _binder;
|
/// <summary>
|
||||||
|
/// The current position in the string being parsed by the interpreter.
|
||||||
|
/// </summary>
|
||||||
public int Position { get; private set; }
|
public int Position { get; private set; }
|
||||||
#pragma warning disable IDE1006
|
#pragma warning disable IDE1006
|
||||||
|
/// <summary>
|
||||||
|
/// The character at the current position.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected char cc { get { return Source[Position]; } }
|
protected char cc { get { return Source[Position]; } }
|
||||||
|
/// <summary>
|
||||||
|
/// The category of the character.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected int ct { get { return cm[cc]; } }
|
protected int ct { get { return cm[cc]; } }
|
||||||
protected string tokenb(int flag) { // Token Whitelist
|
/// <summary>
|
||||||
|
/// Reads a token until a character of type <paramref name="flag" /> is met.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flag">The type filter.</param>
|
||||||
|
/// <returns>A token from the current position (inclusive) to the next character of type <paramref name="flag" /> (exclusive).</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">No character of type <paramref name="flag" /> is met.</exception>
|
||||||
|
protected string tokenb(int flag) {
|
||||||
int sp = Position;
|
int sp = Position;
|
||||||
while ((ct & flag) == 0) Position++;
|
while ((ct & flag) == 0) Position++;
|
||||||
return Source.Substring(sp, Position - sp);
|
return Source.Substring(sp, Position - sp);
|
||||||
}
|
}
|
||||||
protected string tokenw(int flag) { // Token Whitelist
|
/// <summary>
|
||||||
|
/// Reads a token until a character that is not of type <paramref name="flag" /> is met.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="flag">The type filter.</param>
|
||||||
|
/// <returns>A token from the current position (inclusive) to the next character that is not of type <paramref name="flag" /> (exclusive).</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">No character that is not of type <paramref name="flag" /> is met.</exception>
|
||||||
|
protected string tokenw(int flag) {
|
||||||
int sp = Position;
|
int sp = Position;
|
||||||
while ((ct & flag) != 0) Position++;
|
while ((ct & flag) != 0) Position++;
|
||||||
return Source.Substring(sp, Position - sp);
|
return Source.Substring(sp, Position - sp);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Skips over whitespaces.
|
||||||
|
/// </summary>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected void ws() {
|
protected void ws() {
|
||||||
while ((ct & 0x0001) != 0) Position++;
|
while ((ct & 0x0001) != 0) Position++;
|
||||||
}
|
}
|
||||||
#pragma warning restore IDE1006
|
#pragma warning restore IDE1006
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reads the current character and increments the position.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current character.</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected char GetChar() {
|
protected char GetChar() {
|
||||||
char r = cc;
|
char r = cc;
|
||||||
Position++;
|
Position++;
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an identifier.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An identifier.</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected string GetIdentifier() {
|
protected string GetIdentifier() {
|
||||||
if ((ct & 0x0020) == 0) return "";
|
if ((ct & 0x0020) == 0) return "";
|
||||||
return tokenw(0x0010);
|
return tokenw(0x0010);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a number.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A number.</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected string GetNumber() {
|
protected string GetNumber() {
|
||||||
return tokenw(0x0040);
|
return tokenw(0x0040);
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Reads a string.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string.</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected string GetString() {
|
protected string GetString() {
|
||||||
int sp = Position;
|
int sp = Position;
|
||||||
do {
|
do {
|
||||||
@@ -100,6 +150,11 @@ namespace Cryville.Common.Pdt {
|
|||||||
Position++;
|
Position++;
|
||||||
return Regex.Replace(Source.Substring(sp + 1, Position - sp - 2), @"\\(.)", "$1");
|
return Regex.Replace(Source.Substring(sp + 1, Position - sp - 2), @"\\(.)", "$1");
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Reads an expression.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>An expression.</returns>
|
||||||
|
/// <exception cref="IndexOutOfRangeException">The end of the source string is reached.</exception>
|
||||||
protected PdtExpression GetExp() {
|
protected PdtExpression GetExp() {
|
||||||
var ins = new LinkedList<PdtInstruction>();
|
var ins = new LinkedList<PdtInstruction>();
|
||||||
int _;
|
int _;
|
||||||
@@ -112,23 +167,27 @@ namespace Cryville.Common.Pdt {
|
|||||||
/// Creates an instance of the <see cref="PdtInterpreter" /> class.
|
/// Creates an instance of the <see cref="PdtInterpreter" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="src">The source string.</param>
|
/// <param name="src">The source string.</param>
|
||||||
/// <param name="type">The destination type.</param>
|
|
||||||
/// <param name="binder">The binder. May be <c>null</c>.</param>
|
/// <param name="binder">The binder. May be <c>null</c>.</param>
|
||||||
public PdtInterpreter(string src, Type type, Binder binder) {
|
public PdtInterpreter(string src, Binder binder) {
|
||||||
Source = src;
|
Source = src;
|
||||||
_type = type;
|
|
||||||
_binder = binder;
|
_binder = binder;
|
||||||
if (_binder == null)
|
}
|
||||||
_binder = BinderAttribute.CreateBinderOfType(_type);
|
int[] m_formatVersion;
|
||||||
|
public int[] GetFormatVersion() {
|
||||||
|
if (m_formatVersion == null) InterpretDirectives();
|
||||||
|
return m_formatVersion;
|
||||||
}
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Interprets the source to an object.
|
/// Interprets the source to an object.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="type">The output type.</param>
|
||||||
/// <returns>The interpreted object.</returns>
|
/// <returns>The interpreted object.</returns>
|
||||||
public object Interpret() {
|
public object Interpret(Type type) {
|
||||||
try {
|
try {
|
||||||
InterpretDirectives();
|
if (m_formatVersion == null) InterpretDirectives();
|
||||||
return InterpretObject(_type);
|
if (_binder == null)
|
||||||
|
_binder = BinderAttribute.CreateBinderOfType(type);
|
||||||
|
return InterpretObject(type);
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
throw new PdtParsingException(this, ex);
|
throw new PdtParsingException(this, ex);
|
||||||
@@ -146,7 +205,10 @@ namespace Cryville.Common.Pdt {
|
|||||||
break;
|
break;
|
||||||
case "format":
|
case "format":
|
||||||
ws();
|
ws();
|
||||||
if (GetNumber() != "1")
|
m_formatVersion = (from i in GetNumber().Split('.') select int.Parse(i)).ToArray();
|
||||||
|
if (m_formatVersion.Length == 0)
|
||||||
|
throw new FormatException("Invalid format version");
|
||||||
|
if (m_formatVersion[0] != 1)
|
||||||
throw new NotSupportedException("Format not supported");
|
throw new NotSupportedException("Format not supported");
|
||||||
flag = true;
|
flag = true;
|
||||||
break;
|
break;
|
||||||
@@ -167,10 +229,14 @@ namespace Cryville.Common.Pdt {
|
|||||||
}
|
}
|
||||||
object InterpretObject(Type type) {
|
object InterpretObject(Type type) {
|
||||||
var result = ReflectionHelper.InvokeEmptyConstructor(type);
|
var result = ReflectionHelper.InvokeEmptyConstructor(type);
|
||||||
bool dictflag = ReflectionHelper.IsGenericDictionary(type);
|
bool dictflag = typeof(IDictionary).IsAssignableFrom(type);
|
||||||
while (true) {
|
while (true) {
|
||||||
try { ws(); }
|
try { ws(); }
|
||||||
catch (IndexOutOfRangeException) { return result; }
|
catch (IndexOutOfRangeException) { return result; }
|
||||||
|
if (cc == '}') {
|
||||||
|
GetChar();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
object pkey = InterpretKey(type);
|
object pkey = InterpretKey(type);
|
||||||
char c = GetChar();
|
char c = GetChar();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
@@ -183,19 +249,20 @@ namespace Cryville.Common.Pdt {
|
|||||||
((IDictionary)result).Add(key, value);
|
((IDictionary)result).Add(key, value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MemberInfo prop;
|
MemberInfo prop = null;
|
||||||
bool flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop);
|
bool flag = false;
|
||||||
if (!flag && pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
|
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
|
||||||
|
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<ElementListAttribute>(type, out prop);
|
||||||
|
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
|
||||||
Type ptype = ReflectionHelper.GetMemberType(prop);
|
Type ptype = ReflectionHelper.GetMemberType(prop);
|
||||||
if (ReflectionHelper.IsGenericDictionary(ptype)) {
|
if (flag) {
|
||||||
var ktype = ptype.GetGenericArguments()[0];
|
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
|
||||||
var vtype = ptype.GetGenericArguments()[1];
|
var ktype = ptype.GetGenericArguments()[0];
|
||||||
if (flag) {
|
var vtype = ptype.GetGenericArguments()[1];
|
||||||
object key = _binder.ChangeType(pkey, ktype, null);
|
object key = _binder.ChangeType(pkey, ktype, null);
|
||||||
object value = InterpretObject(vtype);
|
object value = InterpretObject(vtype);
|
||||||
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
|
collection.Add(key, value);
|
||||||
}
|
}
|
||||||
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
|
|
||||||
}
|
}
|
||||||
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
|
else ReflectionHelper.SetValue(prop, result, InterpretObject(ptype));
|
||||||
}
|
}
|
||||||
@@ -211,28 +278,36 @@ namespace Cryville.Common.Pdt {
|
|||||||
((IDictionary)result).Add(key, value);
|
((IDictionary)result).Add(key, value);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
MemberInfo prop;
|
MemberInfo prop = null;
|
||||||
bool flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop);
|
bool flag = false;
|
||||||
if (!flag && pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
|
if (pkey is string) prop = ReflectionHelper.GetMember(type, (string)pkey);
|
||||||
|
if (prop == null) flag = ReflectionHelper.TryFindMemberWithAttribute<PropertyListAttribute>(type, out prop);
|
||||||
|
if (prop == null) throw new MissingMemberException(string.Format("The property \"{0}\" is not found", pkey));
|
||||||
var ptype = ReflectionHelper.GetMemberType(prop);
|
var ptype = ReflectionHelper.GetMemberType(prop);
|
||||||
if (!typeof(IDictionary).IsAssignableFrom(ptype)) {
|
if (flag) {
|
||||||
|
using (var collection = new PairCollection(ReflectionHelper.GetValue(prop, result))) {
|
||||||
|
var ktype = ptype.GetGenericArguments()[0];
|
||||||
|
var vtype = ptype.GetGenericArguments()[1];
|
||||||
|
object key = _binder.ChangeType(pkey, ktype, null);
|
||||||
|
object value = _binder.ChangeType(exp, vtype, null);
|
||||||
|
collection.Add(key, value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
object value = _binder.ChangeType(exp, ptype, null);
|
object value = _binder.ChangeType(exp, ptype, null);
|
||||||
ReflectionHelper.SetValue(prop, result, value, _binder);
|
ReflectionHelper.SetValue(prop, result, value, _binder);
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
var ktype = ptype.GetGenericArguments()[0];
|
|
||||||
var vtype = ptype.GetGenericArguments()[1];
|
|
||||||
object key = _binder.ChangeType(pkey, ktype, null);
|
|
||||||
object value = _binder.ChangeType(exp, vtype, null);
|
|
||||||
((IDictionary)ReflectionHelper.GetValue(prop, result)).Add(key, value);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '}':
|
default:
|
||||||
return result;
|
throw new InvalidOperationException("Internal error: Invalid key interpretation");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/// <summary>
|
||||||
|
/// Interprets a key from the current position.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The interpreted key.</returns>
|
||||||
protected virtual object InterpretKey(Type type) {
|
protected virtual object InterpretKey(Type type) {
|
||||||
return tokenb(0x1000).Trim();
|
return tokenb(0x1000).Trim();
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user