112 lines
2.8 KiB
C#
112 lines
2.8 KiB
C#
using Cryville.Common.IO;
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using System.IO;
|
|
|
|
namespace Cryville.Common.Font {
|
|
public abstract class FontFile : IEnumerable<Typeface> {
|
|
public abstract int Count { get; }
|
|
public abstract Typeface this[int index] { get; }
|
|
protected FileInfo File { get; private set; }
|
|
protected BinaryReader Reader { get; private set; }
|
|
public FontFile(FileInfo file) {
|
|
File = file;
|
|
Reader = new BinaryReaderBE(new FileStream(file.FullName, FileMode.Open, FileAccess.Read));
|
|
}
|
|
public void Close() { Reader.Close(); }
|
|
|
|
public static FontFile Create(FileInfo file) => file.Extension switch {
|
|
".ttf" or ".otf" => new FontFileTTF(file),
|
|
".ttc" or ".otc" => new FontFileTTC(file),
|
|
_ => null,
|
|
};
|
|
|
|
public Enumerator GetEnumerator() {
|
|
return new Enumerator(this);
|
|
}
|
|
IEnumerator<Typeface> IEnumerable<Typeface>.GetEnumerator() {
|
|
return GetEnumerator();
|
|
}
|
|
IEnumerator IEnumerable.GetEnumerator() {
|
|
return GetEnumerator();
|
|
}
|
|
|
|
public struct Enumerator : IEnumerator<Typeface> {
|
|
readonly FontFile _self;
|
|
int _index;
|
|
internal Enumerator(FontFile self) {
|
|
_self = self;
|
|
_index = -1;
|
|
}
|
|
|
|
public readonly Typeface Current {
|
|
get {
|
|
if (_index < 0)
|
|
throw new InvalidOperationException(_index == -1 ? "Enum not started" : "Enum ended");
|
|
return _self[_index];
|
|
}
|
|
}
|
|
|
|
readonly object IEnumerator.Current => Current;
|
|
|
|
public void Dispose() {
|
|
_index = -2;
|
|
}
|
|
|
|
public bool MoveNext() {
|
|
if (_index == -2) return false;
|
|
_index++;
|
|
if (_index >= _self.Count) {
|
|
_index = -2;
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void Reset() {
|
|
_index = -1;
|
|
}
|
|
}
|
|
}
|
|
public class FontFileTTF : FontFile {
|
|
public override int Count { get { return 1; } }
|
|
public override Typeface this[int index] {
|
|
get {
|
|
if (index != 0) throw new ArgumentOutOfRangeException("index");
|
|
try {
|
|
return new TypefaceTTF(Reader, File, index);
|
|
}
|
|
catch (Exception) {
|
|
throw new InvalidDataException("Invalid font");
|
|
}
|
|
}
|
|
}
|
|
public FontFileTTF(FileInfo file) : base(file) { }
|
|
}
|
|
public class FontFileTTC : FontFile {
|
|
readonly IReadOnlyList<uint> _offsets;
|
|
public override int Count { get { return _offsets.Count; } }
|
|
public override Typeface this[int index] {
|
|
get {
|
|
if (index < 0 || index >= Count) throw new ArgumentOutOfRangeException("index");
|
|
Reader.BaseStream.Position = _offsets[index];
|
|
try {
|
|
return new TypefaceTTF(Reader, File, index);
|
|
}
|
|
catch (Exception) {
|
|
throw new InvalidDataException("Invalid font");
|
|
}
|
|
}
|
|
}
|
|
public FontFileTTC(FileInfo file) : base(file) {
|
|
try {
|
|
_offsets = new TTCHeader(Reader, 0).GetItems();
|
|
}
|
|
catch (Exception) {
|
|
throw new InvalidDataException("Invalid font");
|
|
}
|
|
}
|
|
}
|
|
}
|