>(StringComparer.OrdinalIgnoreCase);
+
+ ///
+ /// 注册执行处理的命令处理器。
+ ///
+ /// 执行命令的处理器。
+ /// 触发该命令的命令标识符。
+ public void Register(ICommand command, params string[] commandIDs) {
+ foreach (var cmd in commandIDs) {
+ _container.Add(cmd, command);
+ }
+ }
+
+ ///
+ /// 执行指定的命令。
+ ///
+ /// 命令标识符。
+ /// 处理命令时的上下文变量。
+ /// 参数。
+ /// 如找到对应的命令处理,则返回 true,否则返回 false。
+ public bool Process(string commandID, P context, params string[] parameters) {
+ if (_container.TryGetValue(commandID, out ICommand
cmd)) {
+ cmd.Process(context, parameters);
+ return true;
+ }
+ return false;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/DualKeyDictionary.cs b/pdfpatcher/App/Common/DualKeyDictionary.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b4e7a3997a9857c4880979aaf34f0be6ff4d4e54
--- /dev/null
+++ b/pdfpatcher/App/Common/DualKeyDictionary.cs
@@ -0,0 +1,106 @@
+using System;
+using System.Collections.Generic;
+
+namespace PDFPatcher.Common
+{
+ public class DualKeyDictionary : IDictionary
+ {
+ private readonly Dictionary _keyDictionary = new Dictionary();
+ private readonly Dictionary _reverseDictionary = new Dictionary();
+
+ public DualKeyDictionary() {
+
+ }
+
+ public K GetKeyByValue(V value) {
+ return _reverseDictionary[value];
+ }
+
+ #region IDictionary 成员
+
+ public void Add(K key, V value) {
+ _keyDictionary.Add(key, value);
+ _reverseDictionary.Add(value, key);
+ }
+
+ public bool ContainsKey(K key) {
+ return _keyDictionary.ContainsKey(key);
+ }
+ public bool ContainsValue(V value) {
+ return _reverseDictionary.ContainsKey(value);
+ }
+
+ public ICollection Keys => _keyDictionary.Keys;
+
+ public bool Remove(K key) {
+ if (_keyDictionary.ContainsKey(key) == false) {
+ return false;
+ }
+ var value = _keyDictionary[key];
+ _keyDictionary.Remove(key);
+ _reverseDictionary.Remove(value);
+ return true;
+ }
+
+ public bool TryGetValue(K key, out V value) {
+ return TryGetValue(key, out value);
+ }
+
+ public ICollection Values => _reverseDictionary.Keys;
+
+ public V this[K key] {
+ get => _keyDictionary[key];
+ set {
+ Remove(key);
+ Add(key, value);
+ }
+ }
+
+ #endregion
+
+ #region ICollection> 成员
+
+ public void Add(KeyValuePair item) {
+ Add(item.Key, item.Value);
+ }
+
+ public void Clear() {
+ _keyDictionary.Clear();
+ _reverseDictionary.Clear();
+ }
+
+ public bool Contains(KeyValuePair item) {
+ return _keyDictionary.ContainsKey(item.Key) && _reverseDictionary.ContainsKey(item.Value);
+ }
+
+ public void CopyTo(KeyValuePair[] array, int arrayIndex) {
+ ((ICollection>)_keyDictionary).CopyTo(array, arrayIndex);
+ }
+
+ public int Count => _keyDictionary.Count;
+
+ public bool IsReadOnly => false;
+
+ public bool Remove(KeyValuePair item) {
+ return Remove(item.Key);
+ }
+
+ #endregion
+
+ #region IEnumerable> 成员
+
+ public IEnumerator> GetEnumerator() {
+ return ((IEnumerable>)_keyDictionary).GetEnumerator();
+ }
+
+ #endregion
+
+ #region IEnumerable 成员
+
+ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
+ return ((System.Collections.IEnumerable)_keyDictionary).GetEnumerator();
+ }
+
+ #endregion
+ }
+}
diff --git a/pdfpatcher/App/Common/FileHelper.cs b/pdfpatcher/App/Common/FileHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4eab5d37bfcf44942588e1b5cab6697d5e105517
--- /dev/null
+++ b/pdfpatcher/App/Common/FileHelper.cs
@@ -0,0 +1,267 @@
+using System;
+using System.IO;
+
+namespace PDFPatcher.Common
+{
+ static class FileHelper
+ {
+ enum OverwriteType
+ {
+ Prompt, Overwrite, Skip
+ }
+ static OverwriteType __OverwriteMode;
+
+ public static bool HasExtension(FilePath fileName, string extension) {
+ return fileName.HasExtension(extension);
+ }
+ public static bool HasFileNameMacro(string fileName) {
+ var c = '<';
+ foreach (var item in fileName) {
+ if (item == c) {
+ if (c == '>') {
+ return true;
+ }
+ c = '>';
+ }
+ }
+ return false;
+ }
+ public static int NumericAwareComparePath(string path1, string path2) {
+ const char PathDot = '.';
+ var l1 = path1?.Length ?? 0;
+ var l2 = path2?.Length ?? 0;
+ if (l1 == 0 || l2 == 0) {
+ return l1 - l2;
+ }
+ int n1 = 0, n2 = 0;
+ for (int i1 = 0, i2 = 0; i1 < l1 && i2 < l2; i1++, i2++) {
+ var x = path1[i1];
+ var y = path2[i2];
+ if (x < '0' || x > '9') {
+ // 不区分大小写的文字比较
+ if (x != y) {
+ x = ToLowerAscii(x);
+ y = ToLowerAscii(y);
+ if (x == y) {
+ continue;
+ }
+ return x == PathDot ? -1
+ : y == PathDot ? 1
+ : y < '0' || y > '9' ? LocaleInfo.StringComparer(x.ToString(), y.ToString(), System.Globalization.CompareOptions.StringSort)
+ // path2 为数字,path1 不为数字,path2 排在前面
+ : 1;
+ }
+ }
+ else if (IsPathSeparator(x)) {
+ if (IsPathSeparator(y)) {
+ continue;
+ }
+ return -1;
+ }
+ else if (IsPathSeparator(y)) {
+ return 1;
+ }
+ else {
+ // 数字比较
+ if (y >= '0' && y <= '9') {
+ // 两组均为数字
+ do {
+ if (x > '0' || n1 > 0) {
+ ++n1;
+ }
+ } while (++i1 < l1 && (x = path1[i1]) >= '0' && x <= '9');
+ do {
+ if (y > '0' || n2 > 0) {
+ ++n2;
+ }
+ } while (++i2 < l2 && (y = path2[i2]) >= '0' && y <= '9');
+ // 数字位数少的在前面
+ if (n1 != n2) {
+ return n1 - n2;
+ }
+ // 全是 0,继续后面的比较
+ if (n1 == 0 || n2 == 0) {
+ --i1;
+ --i2;
+ continue;
+ }
+ i1 -= n1;
+ i2 -= n2;
+ for (int i = 0; i < n1; i++, i1++, i2++) {
+ x = path1[i1];
+ y = path2[i2];
+ if (x != y) {
+ return x - y;
+ }
+ }
+ // 数值相等,比较下一组
+ n1 = n2 = 0;
+ --i1;
+ --i2;
+ }
+ else {
+ // 仅 x 为数字,y 不为数字
+ return y == PathDot ? 1 : x - y;
+ }
+ }
+ }
+ return path1.Length - path2.Length;
+ }
+ static char ToLowerAscii(char c) {
+ return c >= 'A' && c <= 'Z' ? (char)(c + ('a' - 'A')) : c;
+ }
+
+ internal static bool CheckOverwrite(string targetFile) {
+ if (!File.Exists(targetFile)) {
+ return true;
+ }
+
+ switch (__OverwriteMode) {
+ case OverwriteType.Prompt:
+ var r = Common.FormHelper.YesNoCancelBox(String.Join("\n", new string[] {
+ "是否覆盖目标文件?", targetFile, "\n按住 Shift 键重复此对话框的选择,本次操作不再弹出覆盖文件提示。"
+ }));
+ if (r == System.Windows.Forms.DialogResult.No) {
+ if (FormHelper.IsShiftKeyDown) {
+ __OverwriteMode = OverwriteType.Skip;
+ }
+ goto case OverwriteType.Skip;
+ }
+ else if (r == System.Windows.Forms.DialogResult.Cancel) {
+ throw new OperationCanceledException();
+ }
+ if (FormHelper.IsShiftKeyDown) {
+ __OverwriteMode = OverwriteType.Overwrite;
+ }
+ break;
+ case OverwriteType.Overwrite:
+ return true;
+ case OverwriteType.Skip:
+ Tracker.TraceMessage(Tracker.Category.ImportantMessage, "取消覆盖文件:" + targetFile);
+ return false;
+ default:
+ goto case OverwriteType.Prompt;
+ }
+
+ return true;
+ }
+
+ public static string CombinePath(string path1, string path2) {
+ if (string.IsNullOrEmpty(path2)) {
+ return path1 ?? string.Empty;
+ }
+ if (string.IsNullOrEmpty(path1)) {
+ return path2;
+ }
+ var l2 = path2.Length;
+ if (l2 > 0) {
+ if (IsPathSeparator(path2[0]) || (l2 > 1 && path2[1] == Path.VolumeSeparatorChar)) {
+ return path2;
+ }
+ }
+ var ch = path1[path1.Length - 1];
+ if (IsPathSeparator(ch) == false) {
+ return path1 + Path.DirectorySeparatorChar + path2;
+ }
+ return path1 + path2;
+ }
+ public static bool ComparePath(FilePath path1, FilePath path2) {
+ return path1.Equals(path2);
+ }
+
+ public static bool IsPathValid(string filePath) {
+ return String.IsNullOrEmpty(filePath) == false && filePath.Trim().Length > 0
+ && filePath.IndexOfAny(FilePath.InvalidPathChars) == -1;
+ }
+ static bool IsPathSeparator(char c) {
+ return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
+ }
+
+ internal static void ResetOverwriteMode() {
+ __OverwriteMode = OverwriteType.Prompt;
+ }
+
+ internal static string MakePathRootedAndWithExtension(string path, string basePath, string extName, bool forceExt) {
+ var p = Path.Combine(Path.GetDirectoryName(basePath), path);
+ return Path.GetExtension(p).Length == 0 || forceExt ? (string)new FilePath(p).EnsureExtension(extName) : p;
+ }
+
+ static FilePath AttachExtensionName(FilePath fileName, string extension) {
+ return fileName.EnsureExtension(extension);
+ }
+
+ static string GetNewFileName(string fileName, string extName) {
+ var tmpName = AttachExtensionName(fileName, extName);
+ var n = 1;
+ while (tmpName.ExistsFile) {
+ tmpName = AttachExtensionName(fileName + "[" + (++n) + "]", extName);
+ }
+ return tmpName.ToString();
+ }
+ public static string GetValidFileName(FilePath fileName) {
+ return fileName.SubstituteInvalidChars('_').ToString();
+ }
+ internal static string GetNewFileNameFromSourceFile(string fileName, string extName) {
+ var d = Path.GetDirectoryName(fileName);
+ return GetNewFileName(
+ d + @"\" + Path.GetFileNameWithoutExtension(fileName),
+ extName)
+ .Replace(@"\\", @"\");
+ }
+ internal static string GetTempNameFromFileDirectory(string fileName, string extName) {
+ var f = Path.GetDirectoryName(fileName);
+ var t = Path.GetTempFileName();
+ return Path.Combine(f, t + extName);
+ }
+ public static string GetEllipticPath(string path, int length) {
+ if (length < 11) {
+ length = 11;
+ }
+ return path == null ? string.Empty
+ : path.Length > length ? (path.Substring(0, 7) + "..." + path.Substring(path.Length - (length - 10)))
+ : path;
+ }
+
+ public static byte[] DumpBytes(this byte[] source, FilePath path) {
+ return source.DumpBytes(path, 0, source?.Length ?? 0);
+ }
+ public static byte[] DumpBytes(this byte[] source, FilePath path, int offset, int count) {
+ using (var f = new FileStream(path.ToFullPath(), FileMode.OpenOrCreate, FileAccess.Write)) {
+ if (source == null) {
+ return null;
+ }
+ f.Write(source, offset, count);
+ }
+ return source;
+ }
+ public static byte[] DumpHexBinBytes(this byte[] source, FilePath path) {
+ using (var f = new StreamWriter(path.ToFullPath())) {
+ if (source == null) {
+ return null;
+ }
+ byte t;
+ for (int i = 0; i < source.Length; i++) {
+ if (i > 0) {
+ if ((i & 0xF) == 0) {
+ f.WriteLine();
+ }
+ if ((i & 0x1) == 0) {
+ f.Write(' ');
+ }
+ }
+ var b = source[i];
+ t = (byte)(b >> 4);
+ f.Write((char)(t + (t > 9 ? ('A' - 10) : 0x30)));
+ t = (byte)(b & 0x0F);
+ f.Write((char)(t + (t > 9 ? ('A' - 10) : 0x30)));
+ }
+ }
+ return source;
+ }
+
+ static class LocaleInfo
+ {
+ public static readonly Func StringComparer = System.Globalization.CultureInfo.CurrentCulture.CompareInfo.Compare;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/FilePath.cs b/pdfpatcher/App/Common/FilePath.cs
new file mode 100644
index 0000000000000000000000000000000000000000..01b350a6017c391d9d6d62b999c93975b9ece408
--- /dev/null
+++ b/pdfpatcher/App/Common/FilePath.cs
@@ -0,0 +1,1051 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Reflection;
+using System.Text;
+using NameList = System.Collections.Generic.List;
+using SysDirectory = System.IO.Directory;
+
+namespace PDFPatcher.Common
+{
+ /// 表示文件路径的结构。此结构可隐式转换为字符串、、 和 。
+ public readonly struct FilePath : IEquatable
+ {
+ internal static readonly char[] InvalidFileNameChars = Path.GetInvalidFileNameChars();
+ internal static readonly char[] InvalidPathChars = Path.GetInvalidPathChars();
+ internal static readonly Func __PathComparer = StringComparer.OrdinalIgnoreCase.Equals;
+
+ /// 表示匹配任何文件的通配符。
+ public const string Wildcard = "*";
+ /// 表示匹配当前目录、递归子目录和任何文件的通配符。
+ public const string RecursiveWildcard = "**";
+
+ /// 表示没有任何内容的路径。
+ public static readonly FilePath Empty = new FilePath(string.Empty, false);
+
+ /// 获取应用程序所在的目录路径。
+ public static readonly FilePath AppRoot = ((FilePath)AppDomain.CurrentDomain.BaseDirectory).AppendPathSeparator();
+
+ /// 获取应用程序的文件路径(对于 Web 应用程序,返回 )。
+ public static readonly FilePath AppPath = Assembly.GetEntryAssembly() != null ? (FilePath)Assembly.GetEntryAssembly().Location : Empty;
+
+ static readonly char[] __PathSeparators = { Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar };
+ static readonly string __CurrentPath = "." + Path.DirectorySeparatorChar;
+ readonly string _value;
+
+ /// 传入文件路径的字符串形式,创建新的 实例。在创建实例时,删除传入字符串内所有的前导和尾随空白。
+ /// 文件路径的字符串形式。
+ public FilePath(string path) : this(path, true) { }
+
+ internal FilePath(string path, bool trim) {
+ _value = string.IsNullOrEmpty(path)
+ ? string.Empty
+ : trim ? path.Trim() : path;
+ }
+
+ /// 返回当前路径的目录部分。如目录为相对路径,则先转换为以当前程序所在目录路径为基准的绝对路径。
+ /// 当前路径的目录部分。
+ public FilePath Directory {
+ get {
+ const int None = 0, EndWithSep = 1, EndWithLetter = 2;
+ var p = AppRoot.Combine(_value)._value;
+ int s = None;
+ for (int i = p.Length - 1; i >= 0; i--) {
+ var c = p[i];
+ bool d = IsDirectorySeparator(c);
+ switch (s) {
+ case None:
+ if (d) {
+ s = EndWithSep;
+ }
+ else if (Char.IsWhiteSpace(c) == false) {
+ s = EndWithLetter;
+ }
+ continue;
+ case EndWithSep:
+ if (d) {
+ continue;
+ }
+ else if (c == Path.VolumeSeparatorChar) {
+ return Empty;
+ }
+ else {
+ return p.Substring(0, i + 1);
+ }
+ case EndWithLetter:
+ if (d) {
+ return p.Substring(0, (i == 2 && p[1] == Path.VolumeSeparatorChar || i == 0) ? i + 1 : i);
+ }
+ else if (c == Path.VolumeSeparatorChar) {
+ return p.Substring(0, i + 1) + Path.DirectorySeparatorChar;
+ }
+ break;
+ }
+ }
+ return Empty;
+ }
+ }
+
+ /// 返回当前路径是否以目录分隔符结束。
+ public bool EndsWithPathSeparator {
+ get {
+ if (String.IsNullOrEmpty(_value)) {
+ return false;
+ }
+ for (int i = _value.Length - 1; i >= 0; i--) {
+ var c = _value[i];
+ if (Char.IsWhiteSpace(c)) {
+ continue;
+ }
+ return IsDirectorySeparator(c);
+ }
+ return false;
+ }
+ }
+
+ /// 检查当前路径对应的文件是否存在。
+ public bool ExistsFile => File.Exists(ToFullPath()._value);
+
+ /// 检查当前路径对应的目录是否存在。
+ public bool ExistsDirectory => SysDirectory.Exists(ToFullPath()._value);
+
+ /// 获取文件路径的文件名部分。
+ public string FileName {
+ get {
+ if (IsEmpty) {
+ return string.Empty;
+ }
+ char c;
+ for (int i = _value.Length - 1; i >= 0; i--) {
+ c = _value[i];
+ if (IsDirectorySeparator(c) || c == Path.VolumeSeparatorChar) {
+ return _value.Substring(++i);
+ }
+ }
+ return _value;
+ }
+ }
+
+ /// 获取文件路径的文件名(不包含扩展名)部分。
+ public string FileNameWithoutExtension {
+ get {
+ if (IsEmpty) {
+ return string.Empty;
+ }
+ char c;
+ var l = _value.Length;
+ var d = l;
+ for (int i = d - 1; i >= 0; i--) {
+ c = _value[i];
+ if (c == '.') {
+ if (d == l) {
+ d = i;
+ }
+ }
+ else if (IsDirectorySeparator(c) || c == Path.VolumeSeparatorChar) {
+ return d != l ? _value.Substring(++i, d - i) : _value.Substring(++i);
+ }
+ }
+ return d != l ? _value.Substring(0, d) : _value;
+ }
+ }
+
+ /// 获取文件路径的文件扩展名部分。
+ public string FileExtension {
+ get {
+ if (IsEmpty) {
+ return string.Empty;
+ }
+ char c;
+ int i;
+ for (i = _value.Length - 1; i >= 0; i--) {
+ c = _value[i];
+ if (IsDirectorySeparator(c)) {
+ i = -1;
+ break;
+ }
+ if (c == '.') {
+ break;
+ }
+ }
+ return i > -1 && i < _value.Length - 1 ? _value.Substring(i) : string.Empty;
+ }
+ }
+
+ /// 返回当前路径是否为空。
+ public bool IsEmpty => String.IsNullOrEmpty(_value);
+
+ /// 返回当前文件路径是否有效。
+ public bool IsValidPath => _value?.Trim().Length > 0 && _value.IndexOfAny(InvalidPathChars) == -1;
+
+ /// 在路径后附加 字符。
+ /// 附加了“\”字符的路径。
+ public FilePath AppendPathSeparator() {
+ return IsEmpty == false && _value[_value.Length - 1] == Path.DirectorySeparatorChar
+ ? this
+ : (FilePath)(_value + Path.DirectorySeparatorChar);
+ }
+ /// 删除路径尾部的 或 字符。
+ /// 删除了尾部“\”字符的路径。
+ public FilePath TrimPathSeparator() {
+ if (_value == null) {
+ return Empty;
+ }
+
+ string p = _value;
+ int i;
+ for (i = p.Length - 1; i >= 0; i--) {
+ char c = p[i];
+ if (!Char.IsWhiteSpace(c) && IsDirectorySeparator(c) == false) {
+ return _value.Substring(0, i + 1);
+ }
+ }
+ return Empty;
+ }
+
+ /// 替换文件路径的扩展名为新的扩展名。
+ /// 新的扩展名。
+ /// 替换扩展名后的路径。
+ public FilePath ChangeExtension(string extension) {
+ if (IsEmpty) {
+ return Empty;
+ }
+ if (extension == null || (extension = extension.TrimEnd()).Length == 0) {
+ extension = String.Empty;
+ }
+ else if (extension[0] != '.') {
+ extension = "." + extension;
+ }
+ int i;
+ char c;
+ for (i = _value.Length - 1; i >= 0; i--) {
+ c = _value[i];
+ if (IsDirectorySeparator(c)) {
+ i = -1;
+ break;
+ }
+ if (c == '.') {
+ break;
+ }
+ }
+ return new FilePath(i >= 0 ? _value.Substring(0, i) + extension : _value + extension, false);
+ }
+
+ ///
+ public FilePath Combine(FilePath path) {
+ return Combine(path, false);
+ }
+
+ /// 合并两个文件路径。如 为绝对路径,则返回该路径。
+ /// 子路径。
+ /// 对于 以 开头的情况,取值为 时,视为以当前目录为基础目录;否则将 视为从根目录开始,返回 。
+ /// 合并后的路径。
+ public FilePath Combine(FilePath path, bool rootAsRelative) {
+ if (path.IsEmpty) {
+ return _value != null ? this : Empty;
+ }
+ if (IsEmpty) {
+ return path._value != null ? path : Empty;
+ }
+ var p2 = path._value;
+ var ps = p2[0];
+ bool p2r;
+ if ((p2r = IsDirectorySeparator(ps)) && rootAsRelative == false // note 不能调转 && 参数的顺序,p2r 在后面有用
+ || p2.Length > 1 && (p2[1] == Path.VolumeSeparatorChar || p2[1] == ps)) {
+ return path;
+ }
+
+ var p1 = _value/*.TrimEnd()*/; // _value 已在创建时 Trim 过,不需再 Trim
+ if (ps == '.') { // 合并扩展名到当前路径
+ return p1 + p2;
+ }
+ return IsDirectorySeparator(p1[p1.Length - 1]) == false && p2r == false
+ ? new FilePath(p1 + Path.DirectorySeparatorChar + p2)
+ : new FilePath(p1 + p2, false);
+ }
+
+ /// 为当前文件路径创建目录。如文件路径为空,则不创建路径。
+ /// 所创建目录的路径。
+ public FilePath CreateDirectory() {
+ if (IsEmpty) {
+ return Empty;
+ }
+ var p = ToFullPath();
+ if (SysDirectory.Exists(p) == false) {
+ SysDirectory.CreateDirectory(p);
+ }
+ return p;
+ }
+
+ /// 为当前文件路径创建其所属的目录。如文件路径为空,则不创建路径。
+ /// 所创建目录的路径。
+ public FilePath CreateContainingDirectory() {
+ if (IsEmpty) {
+ return Empty;
+ }
+ var f = Directory;
+ if (SysDirectory.Exists(f._value) == false) {
+ SysDirectory.CreateDirectory(f._value);
+ }
+ return f;
+ }
+
+ /// 删除当前文件路径对应的文件。
+ public void DeleteFile() {
+ var p = ToFullPath()._value;
+ File.Delete(p);
+ }
+ /// 删除当前文件路径对应的目录。如路径指向的目录不存在,不执行任何操作。
+ /// 是否递归删除子目录的文件
+ public void DeleteDirectory(bool recursive) {
+ var p = ToFullPath()._value;
+ SysDirectory.Delete(p, recursive);
+ }
+
+ /// 返回附加指定扩展名的实例。如当前路径已包含指定的扩展名,则返回当前路径,否则返回附加扩展名的实例。
+ /// 需要附加的文件扩展名。
+ /// 附加指定扩展名的实例。
+ public FilePath EnsureExtension(string extension) {
+ return HasExtension(extension) ? this : new FilePath(_value + extension);
+ }
+
+ /// 创建以应用程序所在目录为基准的路径。
+ /// 相对路径。
+ /// 返回以应用程序所在目录为基准的路径。
+ public static FilePath FromRoot(string path) {
+ return AppRoot.Combine(path);
+ }
+
+ /// 返回与文件关联的版本说明信息。
+ /// 文件 对应的
+ public string GetDescription() {
+ return FileVersionInfo.GetVersionInfo(ToFullPath()).FileDescription;
+ }
+
+ /// 获取当前 下符合匹配模式的文件。在执行匹配前,先将当前实例转换为完整路径。当前用户无权访问的目录将被忽略。
+ /// 匹配文件用的模式。模式中的“\”用于分隔目录,“**”表示当前目录及其包含的所有目录,“*”匹配 0 到多个字符,“?”匹配 1 个字符。模式为空时,返回所有文件。
+ /// 返回匹配模式的所有文件。
+ public FilePath[] GetFiles(string pattern) {
+ return GetFiles(pattern, null);
+ }
+
+ /// 获取当前 下符合匹配模式的目录。在执行匹配前,先将当前实例转换为完整路径。当前用户无权访问的目录将被忽略。
+ /// 匹配目录用的模式。模式中的“\”用于分隔目录,“**”表示当前目录及其包含的所有目录,“*”匹配 0 到多个字符,“?”匹配 1 个字符。模式为空时,返回所有一级子目录。
+ /// 返回匹配模式的所有目录。
+ public FilePath[] GetDirectories(string pattern) {
+ return GetDirectories(pattern, null);
+ }
+
+ /// 获取当前 下符合匹配模式和筛选条件的文件。在执行匹配前,先将当前实例转换为完整路径。当前用户无权访问的目录将被忽略。
+ /// 匹配文件用的模式。模式中的“\”用于分隔目录,“**”表示当前目录及其包含的所有目录,“*”匹配 0 到多个字符,“?”匹配 1 个字符。
+ /// 用于筛选文件名的委托。
+ /// 返回匹配模式的所有文件。
+ public FilePath[] GetFiles(string pattern, Predicate filter) {
+ var f = ToFullPath();
+ if (String.IsNullOrEmpty(pattern)) {
+ return SysDirectory.Exists(f._value)
+ ? GetFiles(f._value, Wildcard, filter)
+ : new FilePath[0];
+ }
+
+ string fp;
+ bool rp = pattern == RecursiveWildcard;
+ var p = new FilePath(pattern).GetParts(false);
+ var pl = p.Length;
+ var t = GetDirectories(f._value, p, rp ? 1 : pl - 1);
+ if (rp) {
+ fp = Wildcard;
+ }
+ else {
+ if (t.Count == 0) {
+ return new FilePath[0];
+ }
+ fp = p[pl - 1];
+ }
+ var r = new List();
+ foreach (var item in t) {
+ try {
+ r.AddRange(GetFiles(item, fp, filter));
+ }
+ catch (UnauthorizedAccessException) {
+ // continue;
+ }
+ }
+ return r.ToArray();
+ }
+
+ static FilePath[] GetFiles(string directory, string filePattern, Predicate filter) {
+ return SysDirectory.Exists(directory) ? Array.ConvertAll(
+ filter != null ? Array.FindAll(SysDirectory.GetFiles(directory, filePattern), filter) : SysDirectory.GetFiles(directory, filePattern)
+ , i => (FilePath)i)
+ : new FilePath[0];
+ }
+
+ /// 获取当前 下符合匹配模式和筛选条件的目录。在执行匹配前,先将当前实例转换为完整路径。当前用户无权访问的目录将被忽略。
+ /// 匹配目录用的模式。模式中的“\”用于分隔目录,“**”表示当前目录及其包含的所有目录,“*”匹配 0 到多个字符,“?”匹配 1 个字符。
+ /// 用于筛选目录名的委托。
+ /// 返回匹配模式的所有目录。
+ public FilePath[] GetDirectories(string pattern, Predicate filter) {
+ var f = ToFullPath();
+ if (String.IsNullOrEmpty(pattern)) {
+ return SysDirectory.Exists(f._value)
+ ? GetDirectories(f._value, Wildcard, filter)
+ : new FilePath[0];
+ }
+
+ string fp;
+ bool rp = pattern == RecursiveWildcard;
+ var p = new FilePath(pattern).GetParts(false);
+ var pl = p.Length;
+ var t = GetDirectories(f._value, p, rp ? 1 : pl - 1);
+ if (rp) {
+ fp = Wildcard;
+ }
+ else {
+ if (t.Count == 0) {
+ return new FilePath[0];
+ }
+ fp = p[p.Length - 1];
+ }
+ var r = new List();
+ foreach (var item in t) {
+ try {
+ r.AddRange(GetDirectories(item, fp, filter));
+ }
+ catch (UnauthorizedAccessException) {
+ // continue;
+ }
+ }
+ return r.ToArray();
+ }
+
+ static FilePath[] GetDirectories(string directory, string filePattern, Predicate filter) {
+ return SysDirectory.Exists(directory)
+ ? Array.ConvertAll(filter != null ? Array.FindAll(SysDirectory.GetDirectories(directory, filePattern), filter) : SysDirectory.GetDirectories(directory, filePattern), i => (FilePath)i)
+ : new FilePath[0];
+ }
+
+ static NameList GetDirectories(string path, string[] parts, int partCount) {
+ NameList r;
+ var t = new NameList(1) { path };
+ for (int i = 0; i < partCount; i++) {
+ r = new NameList(10);
+ var pi = parts[i];
+ if (pi.Length == 0) {
+ t = new NameList(1) { Path.GetPathRoot(path) };
+ continue;
+ }
+ else if (pi == "..") {
+ foreach (var item in t) {
+ var n = IsDirectorySeparator(item[item.Length - 1])
+ ? Path.GetDirectoryName(item.Substring(0, item.Length - 1))
+ : Path.GetDirectoryName(item);
+ if (n != null && r.Contains(n) == false) {
+ r.Add(n);
+ }
+ }
+ }
+ else if (pi == RecursiveWildcard) {
+ foreach (var item in t) {
+ r.Add(item);
+ GetDirectoriesRecursively(item, ref r);
+ }
+ }
+ else {
+ foreach (var item in t) {
+ try {
+ r.AddRange(SysDirectory.GetDirectories(item, pi));
+ }
+ catch (UnauthorizedAccessException) {
+ continue;
+ }
+ }
+ }
+ t = r;
+ }
+ return t;
+ }
+
+ static void GetDirectoriesRecursively(string directoryPath, ref NameList results) {
+ try {
+ var r = SysDirectory.GetDirectories(directoryPath, "*");
+ results.AddRange(r);
+ foreach (var item in r) {
+ GetDirectoriesRecursively(item, ref results);
+ }
+ }
+ catch (UnauthorizedAccessException) {
+ return;
+ }
+ }
+
+ /// 将路径按目录拆分为多个部分,并删除其中的无效部分。
+ /// 目录的各个部分。
+ public string[] GetParts() {
+ return GetParts(true);
+ }
+
+ /// 将路径按目录拆分为多个部分。
+ /// 是否删除无效的部分。
+ /// 目录的各个部分。
+ public string[] GetParts(bool removeInvalidParts) {
+ if (IsEmpty) {
+ return new string[0];
+ }
+ var p = _value.Split(__PathSeparators);
+ string s;
+ var r = false;
+ var v = 0;
+ for (int i = 0; i < p.Length; i++) {
+ s = p[i].Trim();
+ if (s.Length == 0) {
+ // 保留第一个根目录引用
+ if (i == 0) {
+ r = true;
+ ++v;
+ }
+ else if (i == 1 && r) {
+ ++v;
+ }
+ continue;
+ }
+ if (s.Length == 1 && s[0] == '.') {
+ continue;
+ }
+ if (s == ".." || (s.StartsWith("..", StringComparison.Ordinal) && s.TrimEnd('.').Length == 0)) {
+ // 前一级为根目录
+ if (r && v == 1) {
+ // 删除根目录级的目录部分
+ if (p[0].Length > 2) {
+ p[0] = p[0].Substring(0, 2);
+ }
+ continue;
+ }
+ // 保留0级或上一级为“..”的目录符
+ if (v == 0 || p[v - 1] == "..") {
+ s = "..";
+ p[v] = s;
+ ++v;
+ continue;
+ }
+ // 删除前一级
+ --v;
+ continue;
+ }
+ s = s.TrimEnd('.');
+ if (removeInvalidParts) {
+ if (i == 0) {
+ if (s.Length > 1) {
+ // 根目录
+ if (s[1] == Path.VolumeSeparatorChar) {
+ if (Array.IndexOf(InvalidFileNameChars, s[0]) != -1
+ || s.IndexOfAny(InvalidFileNameChars, 2) != -1) {
+ continue;
+ }
+ r = true;
+ }
+ else if (s.IndexOfAny(InvalidFileNameChars) != -1) {
+ continue;
+ }
+ }
+ }
+ else if (s.IndexOfAny(InvalidFileNameChars) != -1) {
+ continue;
+ }
+ }
+ p[v] = s;
+ ++v;
+ }
+ if (v < 1) {
+ return new string[0];
+ }
+ if (v < p.Length) {
+ Array.Resize(ref p, v);
+ }
+ return p;
+ }
+
+ ///
+ ///
+ /// 以当前路径的绝对路径为基准,返回 相对于当前路径的相对路径。 如果
+ /// 与当前路径盘符不一致,返回 。 在计算相对路径前,将把当前路径和 使用 方法转换为绝对路径。
+ ///
+ /// 如当前路径为目录,但不以 结束,应先调用 方法将目录结束符附加到路径末尾。
+ ///
+ /// 要计算相对路径的路径。
+ /// 对于当前路径的相对路径。
+ public FilePath GetRelativePath(FilePath path) {
+ var p1 = ToFullPath()._value;
+ var p2 = path.ToFullPath()._value;
+ var p = -1;
+ var i = 0;
+ var l1 = p1.Length;
+ var l2 = p2.Length;
+ while (i < l1 && i < l2) {
+ var c1 = p1[i];
+ var c2 = p2[i];
+ if (c1 != c2 && Char.ToLowerInvariant(c1) != char.ToLowerInvariant(c2)) {
+ break;
+ }
+ if (c1 == Path.DirectorySeparatorChar) {
+ p = i;
+ }
+ i++;
+ }
+ if (i == 0) {
+ return p2;
+ }
+ if (i == l1 && i == l2) {
+ return string.Empty;
+ }
+ var sb = new StringBuilder(32);
+ while (i < l1) {
+ if (p1[i] == Path.DirectorySeparatorChar) {
+ sb.Append("..").Append(Path.DirectorySeparatorChar);
+ }
+ i++;
+ }
+ if (sb.Length == 0 && l2 - 1 == p) {
+ return __CurrentPath;
+ }
+ sb.Append(p2, p + 1, l2 - p - 1);
+ return sb.ToString();
+ }
+
+
+ /// 检查当前路径是否以指定的扩展名结束(不区分大小写)。
+ /// 文件扩展名。
+ public bool HasExtension(string extension) {
+ return String.IsNullOrEmpty(extension)
+ || (IsEmpty == false && _value.EndsWith(extension, StringComparison.OrdinalIgnoreCase)
+ && (extension[0] == '.' || _value.Length > extension.Length && _value[_value.Length - extension.Length - 1] == '.')
+ );
+ }
+
+ /// 返回文件名是否以指定的任意一个扩展名结尾(不区分大小写)。
+ /// 扩展名列表。
+ public bool HasExtension(params string[] extensions) {
+ var ext = FileExtension;
+ if (extensions == null || extensions.Length == 0) {
+ return true;
+ }
+ if (ext.Length == 0) {
+ return false;
+ }
+ foreach (var item in extensions) {
+ if (string.IsNullOrEmpty(item)) {
+ continue;
+ }
+ if (ext.EndsWith(item, StringComparison.OrdinalIgnoreCase)
+ && (item[0] == '.' || ext.Length > item.Length && ext[ext.Length - item.Length - 1] == '.')) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /// 检查当前路径是否属于指定的路径(子目录或其下文件)。
+ /// 上级目录。
+ /// 是否将当前目录以 开头的情况视为相对路径。
+ public bool IsInDirectory(FilePath containingPath, bool rootAsRelative) {
+ var p = containingPath.ToFullPath()._value;
+ var v = ToFullPath()._value;
+ return v.StartsWith(p, StringComparison.OrdinalIgnoreCase)
+ && (IsDirectorySeparator(p[p.Length - 1]) || v.Length > p.Length && IsDirectorySeparator(v[p.Length]) && new FilePath(v.Substring(p.Length)).IsSubPath(rootAsRelative));
+ }
+
+ /// 返回指定的字符是否 或 。
+ /// 要检查的字符。
+ static bool IsDirectorySeparator(char ch) {
+ return ch == Path.DirectorySeparatorChar || ch == Path.AltDirectorySeparatorChar;
+ }
+
+ /// 返回当前路径是否为子路径(不会指向当前目录的上级目录)。
+ /// 是否将目录以 开头的情况视为子路径。
+ public bool IsSubPath(bool rootAsRelative) {
+ if (String.IsNullOrEmpty(_value)) {
+ return true;
+ }
+ int i, n;
+ if (IsDirectorySeparator(_value[i = 0])) {
+ // rooted
+ if (rootAsRelative) {
+ if (_value.Length == 1) {
+ return true;
+ }
+ i = 1;
+ }
+ else {
+ return false;
+ }
+ }
+
+ if (_value.Length >= 2 && (_value[1] == Path.VolumeSeparatorChar || _value == ".." || _value.Contains("..."))) {
+ // rooted, or starts with "..", or contains "..."
+ return false;
+ }
+ int d = 0;
+ while ((n = _value.IndexOfAny(__PathSeparators, i)) >= 0) {
+ var p = _value.Substring(i, n - i).Trim();
+ if (p.Length == 0 // treat double separators as rooted
+ || p == ".." && --d < 0) { // ".." points to parent folder
+ return false;
+ }
+ else if (p.Length != 1 || p[0] != '.') { // ignore "."
+ ++d;
+ }
+ i = n + 1;
+ }
+ return n != -1
+ || _value.Substring(i).TrimStart() != ".."
+ || --d >= 0; // not end with ".."
+ }
+
+ static readonly string __DirectorySeparator = Path.DirectorySeparatorChar.ToString();
+
+ /// 将文件路径转换为绝对定位路径,并删除目录名称中的空白。同时将 转换为 。
+ /// 标准的绝对定位路径。
+ public FilePath Normalize() {
+ if (_value.IsNullOrWhiteSpace()) {
+ return AppRoot;
+ }
+ if (_value.Length == 3 && _value[1] == Path.VolumeSeparatorChar && IsDirectorySeparator(_value[2])) {
+ return this;
+ }
+ var p = GetParts();
+ // fixes "?:\" (where ? is active directory drive letter) becomes active directory
+ if (EndsWithPathSeparator && p.Length > 0) {
+ p[p.Length - 1] += Path.DirectorySeparatorChar;
+ }
+ return p.Length == 1 && p[0].Length == 3 && p[0][1] == Path.VolumeSeparatorChar
+ ? new FilePath(p[0] + Path.DirectorySeparatorChar)
+ : new FilePath(Path.GetFullPath(AppRoot.Combine(string.Join(__DirectorySeparator, p))._value));
+ }
+
+ /// 只读打开文件路径对应的文件,允许读写共享。
+ public Stream OpenFileReader() {
+ return new FileStream(ToFullPath()._value, FileMode.Open, FileAccess.Read, FileShare.ReadWrite);
+ }
+ /// 打开文件路径对应的文件以准备读写,允许读取共享。
+ /// 指定如文件存在时是否创建新的文件(源文件将被 0 长度的文件覆盖)。
+ public Stream OpenFileWriter(bool overwrite) {
+ return new FileStream(ToFullPath()._value, overwrite ? FileMode.Create : FileMode.OpenOrCreate, FileAccess.ReadWrite, FileShare.Read);
+ }
+
+ /// 返回读写文件的 。
+ ///
+ public Stream OpenFile(FileMode mode, FileAccess access, FileShare share) {
+ return new FileStream(ToFullPath()._value, mode, access, share);
+ }
+
+ /// 返回读写文件的 。
+ /// 指定文件访问方式。
+ /// 指定文件读写方式。
+ /// 指定文件访问共享方式。
+ /// 读写缓冲区的尺寸。
+ public Stream OpenFile(FileMode mode, FileAccess access, FileShare share, int bufferSize) {
+ return new FileStream(ToFullPath()._value, mode, access, share, bufferSize);
+ }
+
+ /// 创建以指定编码读取文件的 实例。
+ /// 用于读取文件的编码。编码为 null 时采用 UTF-8 编码。
+ /// 读取文件的 实例。
+ public StreamReader OpenTextReader(Encoding encoding) {
+ return new StreamReader(ToFullPath()._value, encoding ?? Encoding.UTF8, true);
+ }
+
+ /// 创建以指定编码写入文件的 实例。
+ /// 是否追加到文件结尾。
+ /// 用于写入文件的编码。编码为 null 时采用 UTF-8 编码。
+ /// 写入文件的 实例。
+ public StreamWriter OpenTextWriter(bool append, Encoding encoding) {
+ var fp = ToFullPath();
+ fp.CreateContainingDirectory();
+ return new StreamWriter(fp._value, append, encoding ?? Encoding.UTF8);
+ }
+
+ /// 打开当前路径对应的文件并读取所有内容为字节数组。如文件不存在,返回 0 长度的字节数组。此方法使用 FileStream 读取文件,打开或读取文件过程中可能返回异常。
+ /// 文件的字节数组。
+ public byte[] ReadAllBytes() { return ReadAllBytes(-1); }
+ /// 打开当前路径对应的文件并读取所有内容为字节数组。如文件不存在,返回 0 长度的字节数组。此方法使用 FileStream 读取文件,打开或读取文件过程中可能返回异常。
+ /// 允许读取的最大字节数。如此值非正整数,则按读取文件的大小读取最多 个字节。
+ /// 文件的字节数组。
+ public byte[] ReadAllBytes(int maxBytes) {
+ if (ExistsFile == false) {
+ return new byte[0];
+ }
+ using (var s = new FileStream(ToFullPath()._value, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) {
+ if (s.CanRead == false) {
+ return new byte[0];
+ }
+ var l = s.Length;
+ var r = new byte[maxBytes < 1 || maxBytes > l ? l : maxBytes];
+ s.Read(r, 0, r.Length);
+ return r;
+ }
+ }
+
+ /// 打开当前路径对应的文件,并以指定编码逐行读取所有行。如文件不存在,返回 。
+ /// 用于读取文件的编码。编码为 时采用 UTF-8 编码。
+ /// 包含整个文本文件的字符串。
+ /// 指定的路径、文件名或者两者都超出了系统定义的最大长度。例如,在基于 Windows 的平台上,路径必须小于 248 个字符,文件名必须小于 260 个字符。
+ /// 调用方没有所要求的权限。
+ /// 调用方没有所要求的权限。
+ public string ReadTextFile(Encoding encoding) {
+ return ExistsFile ? File.ReadAllText(ToFullPath()._value, encoding ?? Encoding.UTF8) : String.Empty;
+ }
+
+ /// 打开当前路径对应的文件,并以指定编码逐行读取所有内容为字符串集合。如文件不存在,返回 0 长度的字符串数组。
+ /// 用于读取文件的编码。编码为 时采用 UTF-8 编码。
+ /// 文件中每行对应一个字符串所构成的集合。
+ public IEnumerable ReadLines(Encoding encoding) {
+ return ExistsFile == false
+ ? new string[0]
+ : File.ReadLines(ToFullPath()._value, encoding ?? Encoding.UTF8);
+ }
+
+ /// 将 写入文件。
+ /// 是否追加到文件结尾。
+ /// 需要写入的字节数组。此参数为空时,不写入文件内容。
+ public void WriteAllBytes(bool append, byte[] bytes) {
+ if (bytes == null) {
+ return;
+ }
+ var fp = ToFullPath();
+ fp.CreateContainingDirectory();
+ using (var s = new FileStream(fp._value, append ? FileMode.Append : FileMode.Create, FileAccess.Write, FileShare.Read)) {
+ s.Write(bytes, 0, bytes.Length);
+ }
+ }
+
+ /// 将 以指定编码写入文件。
+ /// 是否追加到文件结尾。
+ /// 用于写入文件的编码。编码为 时采用 UTF-8 编码。
+ /// 需要写入的文本。此参数为空时,不写入文件内容。
+ public void WriteAllText(bool append, Encoding encoding, string text) {
+ if (text == null) {
+ return;
+ }
+ using (var w = OpenTextWriter(append, encoding)) {
+ w.Write(text);
+ }
+ }
+
+ /// 将 的每项内容后附加换行,以指定编码写入文件。
+ /// 是否追加到文件结尾。
+ /// 用于写入文件的编码。编码为 时采用 UTF-8 编码。
+ /// 需要写入的文本。此参数为 时,不写入文件内容。此参数的项为 时,写入对应的空行。
+ public void WriteAllLines(bool append, Encoding encoding, IEnumerable lines) {
+ if (lines == null) {
+ return;
+ }
+ using (var w = OpenTextWriter(append, encoding)) {
+ foreach (var item in lines) {
+ w.WriteLine(item);
+ }
+ }
+ }
+
+ ///
+ public void WriteAllLines(bool append, Encoding encoding, params string[] lines) {
+ WriteAllLines(append, encoding, (IEnumerable)lines);
+ }
+
+ /// 使用关联的程序打开当前路径对应的文件或目录,返回对应的进程。
+ /// 要传递的额外参数。
+ /// 实例。
+ public Process StartProcess(string arguments) {
+ return Process.Start(_value, arguments);
+ }
+
+ /// 使用关联的程序打开当前路径对应的文件或目录,返回对应的进程。
+ /// 实例。
+ public Process StartProcess() {
+ return Process.Start(_value);
+ }
+
+ /// 将路径中的无效字符替换为 。
+ /// 用于替换无效字符的字符。
+ /// 替换了无效字符的路径。
+ public FilePath SubstituteInvalidChars(char substitution) {
+ if (IsEmpty) {
+ return Empty;
+ }
+ var a = _value.ToCharArray();
+ var r = false;
+ for (int i = 0; i < a.Length; i++) {
+ ref var c = ref a[i];
+ if (Array.IndexOf(InvalidFileNameChars, c) != -1) {
+ c = substitution;
+ r = true;
+ }
+ }
+ if (r) {
+ return new FilePath(new string(a));
+ }
+ return this;
+ }
+
+ /// 将路径转换为绝对定位的路径。路径的基准位置为 。执行此方法前,必须确保路径中不包含无效字符,否则将抛出异常。
+ /// 采用绝对定位路径的实例。
+ /// 路径无效。
+ public FilePath ToFullPath() {
+ return Path.GetFullPath(Path.Combine(AppRoot._value, _value));
+ }
+
+ ///
+ /// 将 实例转换为完全路径,再隐式转换为 实例。路径的基准位置为 。
+ /// 事实上, 实例可隐式转换为 实例。
+ ///
+ /// 将当前路径转换为完全路径后对应的 实例。
+ [DebuggerStepThrough]
+ public FileInfo ToFileInfo() {
+ return this;
+ }
+
+ /// 将 实例转换为完全路径,再获取其对应的 。
+ /// 与完全路径对应的文件版本信息。
+ /// 路径无效。
+ /// 找不到对应的文件。
+ [DebuggerStepThrough]
+ public FileVersionInfo ToFileVersionInfo() {
+ return FileVersionInfo.GetVersionInfo(ToFullPath());
+ }
+
+ ///
+ /// 将 实例转换为完全路径,再隐式转换为 实例。路径的基准位置为 。
+ /// 事实上, 实例可隐式转换为 实例。
+ ///
+ /// 将当前路径转换为完全路径后对应的 实例。
+ [DebuggerStepThrough]
+ public DirectoryInfo ToDirectoryInfo() {
+ return this;
+ }
+
+ ///
+ /// 将 实例转换为 实例。
+ /// 事实上, 实例可隐式转换为 实例。
+ ///
+ /// 与当前路径对应的 实例。
+ [DebuggerStepThrough]
+ public Uri ToUri() { return this; }
+
+ #region 类型映射
+
+ /// 将字符串隐式转换为 实例,删除传入字符串内所有的前导和尾随空白。
+ /// 需要转换的路径字符串。
+ /// 实例。
+ [DebuggerStepThrough]
+ public static implicit operator FilePath(string path) {
+ return new FilePath(path);
+ }
+
+ /// 将 实例隐式转换为字符串。
+ /// 需要转换的路径。
+ /// 以字符串形式表示的实例。
+ [DebuggerStepThrough]
+ public static implicit operator string(FilePath path) {
+ return path._value;
+ }
+
+ /// 将 显式转换为 实例。
+ /// 需要转换的路径。
+ [DebuggerStepThrough]
+ public static explicit operator FilePath(FileInfo file) {
+ return file == null ? Empty : new FilePath(file.FullName, false);
+ }
+
+ ///
+ /// 将 实例转换为完全路径,再隐式转换为 实例。路径的基准位置为 。
+ ///
+ /// 需要转换的路径。
+ /// 将当前路径转换为完全路径后对应的 实例。
+ ///
+ [DebuggerStepThrough]
+ public static implicit operator FileInfo(FilePath path) {
+ return new FileInfo(path.ToFullPath()._value);
+ }
+
+ /// 将 显式转换为 实例。
+ /// 需要转换的路径。
+ [DebuggerStepThrough]
+ public static explicit operator FilePath(DirectoryInfo directory) {
+ return directory == null ? Empty : new FilePath(directory.FullName, false);
+ }
+
+ ///
+ /// 将 实例转换为完全路径,再隐式转换为 实例。路径的基准位置为 。
+ ///
+ /// 需要转换的路径。
+ /// 将当前路径转换为完全路径后对应的 实例。
+ ///
+ [DebuggerStepThrough]
+ public static implicit operator DirectoryInfo(FilePath path) {
+ return new DirectoryInfo(path.ToFullPath()._value);
+ }
+
+ /// 将 实例隐式转换为 实例。
+ /// 需要转换的路径。
+ [DebuggerStepThrough]
+ public static implicit operator Uri(FilePath path) {
+ return new Uri(path._value);
+ }
+ #endregion
+
+ #region IEquatable 实现
+
+ /// 比较两个文件路径是否相同。
+ /// 需要比较的第一个路径。
+ /// 需要比较的第二个路径。
+ /// 相同时,返回 true。
+ [DebuggerStepThrough]
+ public static bool operator ==(FilePath path1, FilePath path2) {
+ return path1.Equals(path2);
+ }
+
+ /// 比较两个文件路径是否不相同。
+ /// 需要比较的第一个路径。
+ /// 需要比较的第二个路径。
+ /// 不相同时,返回 true。
+ [DebuggerStepThrough]
+ public static bool operator !=(FilePath path1, FilePath path2) {
+ return !path1.Equals(path2);
+ }
+
+ /// 指示当前文件路径是否等于同一类型的另一个文件路径。
+ /// 与此对象进行比较的对象。
+ /// 如果当前对象等于 参数,则为 ;否则为 。
+ public bool Equals(FilePath other) {
+ return __PathComparer(_value, other._value)
+ || __PathComparer(
+ Path.Combine(AppRoot._value, _value ?? string.Empty),
+ Path.Combine(AppRoot._value, other._value ?? string.Empty));
+ }
+
+ /// 确定当前文件路径是否与另一个实例相等。
+ /// 需要与当前实例比较的对象。
+ /// 在两个文件路径相等时,返回 true。
+ [DebuggerStepThrough]
+ public override bool Equals(object obj) {
+ return obj is FilePath && Equals((FilePath)obj);
+ }
+
+ /// 返回路径字符串的散列值。
+ /// 路径字符串的散列值。
+ [DebuggerStepThrough]
+ public override int GetHashCode() {
+ return _value == null ? 0 : _value.GetHashCode();
+ }
+ #endregion
+
+ /// 返回表示当前文件路径的 实例。
+ /// 表示当前文件路径的 实例。
+ [DebuggerStepThrough]
+ public override string ToString() {
+ return _value ?? string.Empty;
+ }
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Common/FontHelper.cs b/pdfpatcher/App/Common/FontHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..be488eab3404db503f1cc11bf2268354054e4140
--- /dev/null
+++ b/pdfpatcher/App/Common/FontHelper.cs
@@ -0,0 +1,113 @@
+using System;
+using System.Collections.Generic;
+using iTextSharp.text.pdf;
+using CharSet = System.Runtime.InteropServices.CharSet;
+using DllImport = System.Runtime.InteropServices.DllImportAttribute;
+using Microsoft.Win32;
+
+namespace PDFPatcher.Common
+{
+ static class FontHelper
+ {
+ public static string FontDirectory { get; } = System.IO.Path.GetFullPath(Environment.GetFolderPath(Environment.SpecialFolder.System) + "\\..\\fonts\\");
+
+ ///
+ /// 列出已安装的字体及其路径。
+ ///
+ /// 是否包含字体组名称
+ public static Dictionary GetInstalledFonts(bool includeFamilyName) {
+ var d = new Dictionary(50);
+ using (var k = Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts")) {
+ GetFontsFromRegistryKey(includeFamilyName, d, k);
+ }
+ using (var k = Registry.CurrentUser.OpenSubKey(@"SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts")) {
+ GetFontsFromRegistryKey(includeFamilyName, d, k);
+ }
+ return d;
+ }
+
+ static void GetFontsFromRegistryKey(bool includeFamilyName, Dictionary d, RegistryKey k) {
+ foreach (var name in k.GetValueNames()) {
+ var p = k.GetValue(name) as string;
+ if (String.IsNullOrEmpty(p)) {
+ continue;
+ }
+ if (p.IndexOf('\\') == -1) {
+ p = FontDirectory + p;
+ }
+ var fp = new FilePath(p);
+ try {
+ if (fp.HasExtension(Constants.FileExtensions.Ttf)
+ || fp.HasExtension(Constants.FileExtensions.Otf)) {
+ AddFontNames(d, p, includeFamilyName);
+ }
+ else if (fp.HasExtension(Constants.FileExtensions.Ttc)) {
+ var nl = BaseFont.EnumerateTTCNames(p).Length;
+ //Tracker.DebugMessage (p);
+ for (int i = 0; i < nl; i++) {
+ AddFontNames(d, p + "," + i.ToText(), includeFamilyName);
+ }
+ }
+ }
+ catch (System.IO.IOException) {
+ // ignore
+ }
+ catch (NullReferenceException) {
+ }
+ catch (iTextSharp.text.DocumentException) {
+ // ignore
+ }
+ }
+ }
+
+ static void AddFontNames(Dictionary fontNames, string fontPath, bool includeFamilyName) {
+ var nl = BaseFont.GetAllFontNames(fontPath, "Cp936", null);
+ //Tracker.DebugMessage (fontPath);
+ if (includeFamilyName) {
+ fontNames[nl[0] as string] = fontPath;
+ }
+ var ffn = nl[2] as string[][];
+ string n = null;
+ string nn = null, cn = null;
+ foreach (var fn in ffn) {
+ var enc = fn[2];
+ n = fn[3];
+ if ("2052" == enc) {
+ cn = n;
+ break;
+ }
+ if ("1033" == enc) {
+ nn = n;
+ }
+ else if ("0" == enc && nn == null) {
+ nn = n;
+ }
+ }
+ if (n != null) {
+ //Tracker.DebugMessage (cn ?? nn ?? n);
+ fontNames[cn ?? nn ?? n] = fontPath;
+ }
+ //foreach (string[] item in nl[1] as string[][]) {
+ // fontNames[item] = fontPath;
+ // Tracker.DebugMessage (item);
+ //}
+ }
+
+ static class NativeMethods
+ {
+ [DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
+ private static extern int AddFontResourceEx(string fontPath, int flag, IntPtr preserved);
+ [DllImport("Gdi32.dll", CharSet = CharSet.Unicode)]
+ private static extern int RemoveFontResourceEx(string fontPath, int flag, IntPtr preserved);
+
+ internal static int LoadFont(string path) {
+ return AddFontResourceEx(path, 0x10, IntPtr.Zero);
+ }
+ internal static int RemoveFont(string path) {
+ return RemoveFontResourceEx(path, 0x10, IntPtr.Zero);
+ }
+ }
+ }
+}
+
+
diff --git a/pdfpatcher/App/Common/FontUtility.cs b/pdfpatcher/App/Common/FontUtility.cs
new file mode 100644
index 0000000000000000000000000000000000000000..64d7266fe38f91d45293d672dddb6d1767a410bc
--- /dev/null
+++ b/pdfpatcher/App/Common/FontUtility.cs
@@ -0,0 +1,70 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace PDFPatcher.Common
+{
+ static class FontUtility
+ {
+ static readonly Regex _italic = new Regex(" (?:Italic|Oblique)$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
+ static readonly Regex _bold = new Regex(" Bold$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
+ static readonly Regex _boldItalic = new Regex(" Bold (?:Italic|Oblique)$", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
+ static FriendlyFontName[] _Fonts;
+
+ public static FriendlyFontName[] InstalledFonts {
+ get {
+ if (_Fonts == null) {
+ ListInstalledFonts();
+ }
+ return _Fonts;
+ }
+ }
+
+ private static void ListInstalledFonts() {
+ var uf = new List(); // 可能包含中文的字体
+ var of = new List(); // 其他字体
+ var fs = FontHelper.GetInstalledFonts(false);
+ string dn /*显示名称*/, fn /*字体名称*/;
+ foreach (var item in fs.Keys) {
+ fn = item;
+ dn = _boldItalic.Replace(fn, "(粗斜体)");
+ dn = _italic.Replace(dn, "(斜体)");
+ dn = _bold.Replace(dn, "(粗体)");
+ if (dn[0] > 0xFF) {
+ uf.Add(new FriendlyFontName(fn, dn));
+ }
+ else {
+ of.Add(new FriendlyFontName(fn, dn));
+ }
+ }
+ uf.Sort();
+ of.Sort();
+ _Fonts = new FriendlyFontName[uf.Count + of.Count];
+ uf.CopyTo(_Fonts);
+ of.CopyTo(_Fonts, uf.Count);
+ }
+
+ internal struct FriendlyFontName : IComparable
+ {
+ public string OriginalName;
+ public string DisplayName;
+ public FriendlyFontName(string originalName, string displayName) {
+ OriginalName = originalName;
+ DisplayName = displayName != originalName ? displayName : null;
+ }
+ public override string ToString() {
+ return DisplayName ?? OriginalName;
+ }
+
+ #region IComparable 成员
+
+ int IComparable.CompareTo(FriendlyFontName other) {
+ return OriginalName.CompareTo(other.OriginalName);
+ }
+
+ #endregion
+ }
+
+ }
+}
diff --git a/pdfpatcher/App/Common/FormHelper.cs b/pdfpatcher/App/Common/FormHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..760d3fba8e1da6db7acad652745c389bfae82a6c
--- /dev/null
+++ b/pdfpatcher/App/Common/FormHelper.cs
@@ -0,0 +1,395 @@
+using System;
+using System.Drawing;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace PDFPatcher.Common
+{
+ static class FormHelper
+ {
+ public const int ProcMsg = NativeMethods.WM_COPYDATA;
+
+ public static bool IsCtrlKeyDown => (Control.ModifierKeys & Keys.Control) != 0;
+
+ public static bool IsShiftKeyDown => (Control.ModifierKeys & Keys.Shift) != 0;
+
+ public static bool IsAltKeyDown => (Control.ModifierKeys & Keys.Alt) != 0;
+
+ public static bool IsEmptyOrTransparent(this Color color) {
+ return color.IsEmpty || color.A == 0;
+ }
+ public static Point Round(this PointF point) {
+ return new Point(point.X.ToInt32(), point.Y.ToInt32());
+ }
+ public static RectangleF Union(this RectangleF rectangle, RectangleF other) {
+ return RectangleF.FromLTRB(
+ rectangle.Left < other.Left ? rectangle.Left : other.Left,
+ rectangle.Top < other.Top ? rectangle.Top : other.Top,
+ rectangle.Right > other.Right ? rectangle.Right : other.Right,
+ rectangle.Bottom > other.Bottom ? rectangle.Bottom : other.Bottom
+ );
+ }
+ public static Point Transpose(this Point point, int x, int y) {
+ return new Point(point.X + x, point.Y + y);
+ }
+ public static Point Transpose(this Point point, Point transpose) {
+ return new Point(point.X + transpose.X, point.Y + transpose.Y);
+ }
+ public static Size Scale(this Size size, float scale) {
+ return new Size((int)(size.Width * scale), (int)(size.Height * scale));
+ }
+ public static void OnFirstLoad(this Form form, Action handler) {
+ new FormEventHandler(form, handler);
+ }
+ public static void SetIcon(this Form form, Bitmap bitmap) {
+ form.Icon = Icon.FromHandle(bitmap.GetHicon());
+ }
+ public static void OnFirstLoad(this UserControl control, Action handler) {
+ new UserControlLoadHandler(control, handler);
+ }
+ public static ProgressBar SetValue(this ProgressBar control, int value) {
+ control.Value = value < control.Minimum ? control.Minimum
+ : value > control.Maximum ? control.Maximum
+ : value;
+ return control;
+ }
+ public static NumericUpDown SetValue(this NumericUpDown box, int value) {
+ return box.SetValue((decimal)value);
+ }
+ public static NumericUpDown SetValue(this NumericUpDown box, float value) {
+ return box.SetValue((decimal)value);
+ }
+ public static NumericUpDown SetValue(this NumericUpDown box, double value) {
+ return box.SetValue((decimal)value);
+ }
+ public static NumericUpDown SetValue(this NumericUpDown box, decimal value) {
+ box.Value =
+ value >= box.Minimum && value <= box.Maximum ? value
+ : value > box.Maximum ? box.Maximum
+ : box.Minimum;
+ return box;
+ }
+ public static ListBox Select(this ListBox control, string item) {
+ if (control.Items.Count == 0) {
+ return control;
+ }
+ var i = control.FindString(item);
+ if (i != -1) {
+ control.SelectedIndex = i;
+ }
+ return control;
+ }
+ public static ComboBox Select(this ComboBox control, string item) {
+ if (control.Items.Count == 0) {
+ return control;
+ }
+ var i = control.FindString(item);
+ if (i != -1) {
+ control.SelectedIndex = i;
+ }
+ return control;
+ }
+ public static ListBox Select(this ListBox control, int index) {
+ var items = control.Items;
+ if (items.Count == 0) {
+ return control;
+ }
+ control.SelectedIndex = index < 0 ? 0
+ : index > items.Count - 1 ? items.Count - 1
+ : index;
+ return control;
+ }
+ public static ComboBox Select(this ComboBox control, int index) {
+ var items = control.Items;
+ if (items.Count == 0) {
+ return control;
+ }
+ control.SelectedIndex = index < 0 ? 0
+ : index > items.Count - 1 ? items.Count - 1
+ : index;
+ return control;
+ }
+ public static ComboBox AddRange(this ComboBox view, params object[] values) {
+ view.Items.AddRange(values);
+ return view;
+ }
+ public static TTextBox AppendLine(this TTextBox box) where TTextBox : TextBoxBase {
+ box.AppendText(Environment.NewLine);
+ return box;
+ }
+ public static TTextBox AppendLine(this TTextBox box, string text) where TTextBox : TextBoxBase {
+ box.AppendText(text + Environment.NewLine);
+ return box;
+ }
+ public static void SetLocation(this FileDialog dialog, string path) {
+ if (FileHelper.IsPathValid(path) == false) {
+ return;
+ }
+ dialog.InitialDirectory = System.IO.Path.GetDirectoryName(path);
+ dialog.FileName = System.IO.Path.GetFileName(path);
+ }
+ public static ToolStrip ToggleEnabled(this ToolStrip toolStrip, bool enabled, params string[] names) {
+ foreach (ToolStripItem item in toolStrip.Items) {
+ if (Array.IndexOf(names, item.Name) != -1) {
+ item.Enabled = enabled;
+ }
+ }
+ return toolStrip;
+ }
+
+ public static float GetDpiScale(this Control control) {
+ using (var g = control.CreateGraphics()) {
+ return g.DpiX / 96;
+ }
+ }
+
+ public static void ScaleColumnWidths(this ListView listView, float scale) {
+ foreach (ColumnHeader column in listView.Columns) {
+ column.Width = (int)(column.Width * scale);
+ }
+ }
+ public static void ScaleColumnWidths(this ListView listView) {
+ float scale = GetDpiScale(listView);
+ foreach (ColumnHeader column in listView.Columns) {
+ column.Width = (int)(column.Width * scale);
+ }
+ }
+
+ public static ToolStrip ScaleIcons(this ToolStrip toolStrip, int size) {
+ size = (int)(toolStrip.GetDpiScale() * size);
+ return toolStrip.ScaleIcons(new Size(size, size));
+ }
+ public static ToolStrip ScaleIcons(this ToolStrip toolStrip, Size size) {
+ toolStrip.SuspendLayout();
+ toolStrip.AutoSize = false;
+ toolStrip.ImageScalingSize = size;
+ toolStrip.ResumeLayout();
+ toolStrip.AutoSize = true;
+ return toolStrip;
+ }
+
+ internal static void InsertLinkedText(this RichTextBoxLinks.RichTextBoxEx textBox, string text) {
+ const int TokenLength = 2;
+ int p1 = text.IndexOf("<<");
+ int p2 = text.IndexOf(">>");
+ if (p1 != -1 && p2 != -1 && p2 > p1) {
+ textBox.AppendText(text.Substring(0, p1));
+ var c = textBox.SelectionColor;
+ var f = textBox.SelectionFont;
+ textBox.InsertLink(text.Substring(p1 + TokenLength, p2 - p1 - TokenLength));
+ if (p2 < text.Length - TokenLength) {
+ textBox.SelectionColor = c;
+ textBox.SelectionFont = f;
+ textBox.AppendText(text.Substring(p2 + TokenLength));
+ }
+ }
+ else {
+ textBox.AppendText(text);
+ }
+ }
+
+ public static void FeedbackDragFileOver(this DragEventArgs args, params string[] allowedFileExtension) {
+ if (args.Data.GetDataPresent(DataFormats.FileDrop)) {
+ var files = args.Data.GetData(DataFormats.FileDrop) as string[];
+ if (Array.Exists(files,
+ f => {
+ return Array.Exists(allowedFileExtension,
+ ext => f.EndsWith(ext, StringComparison.InvariantCultureIgnoreCase));
+ })) {
+ args.Effect = DragDropEffects.Copy;
+ }
+ }
+ }
+ public static string[] DropFileOver(this DragEventArgs args, params string[] allowedFileExtension) {
+ if (args.Data.GetDataPresent(DataFormats.FileDrop)) {
+ var files = (string[])args.Data.GetData(DataFormats.FileDrop);
+ return Array.FindAll(files, f => {
+ return Array.Exists(allowedFileExtension,
+ ext => f.EndsWith(ext, StringComparison.InvariantCultureIgnoreCase));
+ });
+ }
+ return new string[0];
+ }
+ public static bool DropFileOver(this Control control, DragEventArgs args, params string[] allowedFileExtension) {
+ var files = DropFileOver(args, allowedFileExtension);
+ if (files.Length > 0) {
+ control.Text = files[0];
+ return true;
+ }
+ return false;
+ }
+
+ public static void HidePopupMenu(this ToolStripItem item) {
+ if (item is ToolStripDropDownItem mi && mi.HasDropDownItems) {
+ return;
+ }
+ var oo = item.Owner as ToolStripDropDownMenu;
+ oo?.Hide();
+ var oi = item.OwnerItem as ToolStripDropDownItem;
+ while (oi != null) {
+ oi.DropDown.Close();
+ oo = oi.Owner as ToolStripDropDownMenu;
+ oo?.Hide();
+ oi = oi.OwnerItem as ToolStripDropDownItem;
+ }
+ }
+ public static void ClearDropDownItems(this ToolStripItemCollection items, int keepItems = 0) {
+ if (items.Count == 0) {
+ return;
+ }
+ keepItems--;
+ for (var i = items.Count - 1; i > keepItems; i--) {
+ items[i].Dispose();
+ }
+ }
+ public static void ToggleVisibility(bool visible, params Control[] controls) {
+ foreach (var item in controls) {
+ item.Visible = visible;
+ }
+ }
+ public static DialogResult ShowDialog() where TForm : Form, new() {
+ using (var f = new TForm()) {
+ return f.ShowDialog();
+ }
+ }
+ public static DialogResult ShowDialog(this IWin32Window form) where TForm : Form, new() {
+ using (var f = new TForm()) {
+ return f.ShowDialog(form);
+ }
+ }
+ public static DialogResult ShowDialog(this IWin32Window form, object formParameter)
+ where TForm : Form, new() {
+ using (var f = new TForm()) {
+ f.Tag = formParameter;
+ return f.ShowDialog(form);
+ }
+ }
+ public static DialogResult ShowDialog(this IWin32Window form, Action formConfigurator, Action formConfirmationHandler) where TForm : Form, new() {
+ using (var f = new TForm()) {
+ formConfigurator?.Invoke(f);
+ var r = f.ShowDialog(form);
+ if (formConfirmationHandler != null && (r == DialogResult.OK || r == DialogResult.Yes)) {
+ formConfirmationHandler(f);
+ }
+ return r;
+ }
+ }
+ public static DialogResult ShowCommonDialog(this IWin32Window form, Action formConfigurator, Action formConfirmationHandler) where TDialog : CommonDialog, new() {
+ using (var f = new TDialog()) {
+ formConfigurator?.Invoke(f);
+ var r = f.ShowDialog(form);
+ if (formConfirmationHandler != null && (r == DialogResult.OK || r == DialogResult.Yes)) {
+ formConfirmationHandler(f);
+ }
+ return r;
+ }
+ }
+
+ internal static void ErrorBox(string text) {
+ MessageBox.Show(text, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ public static void ErrorBox(this Control control, string text) {
+ MessageBox.Show(text, control.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ public static void ErrorBox(this Control control, string title, Exception exception) {
+ var s = new System.Text.StringBuilder(title);
+ s.AppendLine();
+ s.AppendLine(exception.Message);
+ while ((exception = exception.InnerException) != null) {
+ s.AppendLine();
+ s.Append(exception.Message);
+ }
+ MessageBox.Show(s.ToString(), control.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
+ }
+ internal static void InfoBox(string text) {
+ MessageBox.Show(text, Constants.AppName, MessageBoxButtons.OK, MessageBoxIcon.Information);
+ }
+ internal static DialogResult YesNoBox(string text) {
+ return MessageBox.Show(text, Constants.AppName, MessageBoxButtons.YesNo, MessageBoxIcon.Question);
+ }
+ internal static DialogResult YesNoCancelBox(string text) {
+ return MessageBox.Show(text, Constants.AppName, MessageBoxButtons.YesNoCancel, MessageBoxIcon.Question);
+ }
+ public static bool ConfirmOKBox(string text) {
+ return MessageBox.Show(text, Constants.AppName, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK;
+ }
+ public static bool ConfirmOKBox(this Control control, string text) {
+ return MessageBox.Show(text, control.Text, MessageBoxButtons.OKCancel, MessageBoxIcon.Question) == DialogResult.OK;
+ }
+ public static bool ConfirmYesBox(this Control control, string text) {
+ return MessageBox.Show(text, control.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
+ }
+ public static int SendCopyDataMessage(this System.Diagnostics.Process process, string text) {
+ var s = new CopyDataStruct(text);
+ var r = NativeMethods.SendMessage(process.MainWindowHandle, ProcMsg, 0, ref s);
+ s.Dispose();
+ return r;
+ }
+ public static string GetCopyDataContent(ref Message message) {
+ if (message.Msg == ProcMsg) {
+ return Marshal.PtrToStringUni(((CopyDataStruct)Marshal.PtrToStructure(message.LParam, typeof(CopyDataStruct))).lpData);
+ }
+ return null;
+ }
+
+ sealed class FormEventHandler
+ {
+ readonly Form _Form;
+ readonly Action _Handler;
+
+ public FormEventHandler(Form form, Action handler) {
+ _Form = form;
+ _Handler = handler;
+ form.Load += OnLoadHandler;
+ }
+ public void OnLoadHandler(object s, EventArgs args) {
+ _Form.Load -= OnLoadHandler;
+ _Handler();
+ }
+ }
+ sealed class UserControlLoadHandler
+ {
+ readonly UserControl _Control;
+ readonly Action _Handler;
+
+ public UserControlLoadHandler(UserControl control, Action handler) {
+ _Control = control;
+ _Handler = handler;
+ control.Load += OnLoadHandler;
+ }
+ public void OnLoadHandler(object s, EventArgs args) {
+ _Control.Load -= OnLoadHandler;
+ _Handler();
+ }
+ }
+
+ static class NativeMethods
+ {
+ const string User32DLL = "User32.dll";
+ internal const int WM_COPYDATA = 0x004A;
+
+ [DllImport(User32DLL, SetLastError = false, CharSet = CharSet.Unicode)]
+ public static extern int SendMessage(IntPtr hWnd, int uMsg, int wParam, ref CopyDataStruct lParam);
+ [DllImport("kernel32.dll", SetLastError = true)]
+ public static extern IntPtr LocalFree(IntPtr p);
+ }
+
+ struct CopyDataStruct : IDisposable
+ {
+ readonly IntPtr dwData;
+ readonly int cbData;
+ internal IntPtr lpData;
+
+ public CopyDataStruct(string text) {
+ cbData = (text.Length + 1) * 2;
+ dwData = (IntPtr)1;
+ lpData = Marshal.StringToBSTR(text);
+ }
+
+ public void Dispose() {
+ NativeMethods.LocalFree(lpData);
+ lpData = IntPtr.Zero;
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/ImageBox/DragHandle.cs b/pdfpatcher/App/Common/ImageBox/DragHandle.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e2677ae0ad22c8f5d04fbc50cdd79f89ebcfaa44
--- /dev/null
+++ b/pdfpatcher/App/Common/ImageBox/DragHandle.cs
@@ -0,0 +1,46 @@
+using System.Drawing;
+
+namespace Cyotek.Windows.Forms.Demo
+{
+ // Cyotek ImageBox
+ // Copyright (c) 2010-2015 Cyotek Ltd.
+ // http://cyotek.com
+ // http://cyotek.com/blog/tag/imagebox
+
+ // Licensed under the MIT License. See license.txt for the full text.
+
+ // If you use this control in your applications, attribution, donations or contributions are welcome.
+
+ internal sealed class DragHandle
+ {
+ #region Public Constructors
+
+ public DragHandle(DragHandleAnchor anchor)
+ : this() {
+ Anchor = anchor;
+ }
+
+ #endregion
+
+ #region Protected Constructors
+
+ private DragHandle() {
+ Enabled = true;
+ Visible = true;
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public DragHandleAnchor Anchor { get; set; }
+
+ public Rectangle Bounds { get; set; }
+
+ public bool Enabled { get; set; }
+
+ public bool Visible { get; set; }
+
+ #endregion
+ }
+}
diff --git a/pdfpatcher/App/Common/ImageBox/DragHandleAnchor.cs b/pdfpatcher/App/Common/ImageBox/DragHandleAnchor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9a283b3d11b8bf8e2eb5ee61bd8b1d0860a6808d
--- /dev/null
+++ b/pdfpatcher/App/Common/ImageBox/DragHandleAnchor.cs
@@ -0,0 +1,32 @@
+namespace Cyotek.Windows.Forms.Demo
+{
+ // Cyotek ImageBox
+ // Copyright (c) 2010-2015 Cyotek Ltd.
+ // http://cyotek.com
+ // http://cyotek.com/blog/tag/imagebox
+
+ // Licensed under the MIT License. See license.txt for the full text.
+
+ // If you use this control in your applications, attribution, donations or contributions are welcome.
+
+ internal enum DragHandleAnchor
+ {
+ None,
+
+ TopLeft,
+
+ TopCenter,
+
+ TopRight,
+
+ MiddleLeft,
+
+ MiddleRight,
+
+ BottomLeft,
+
+ BottomCenter,
+
+ BottomRight
+ }
+}
diff --git a/pdfpatcher/App/Common/ImageBox/DragHandleCollection.cs b/pdfpatcher/App/Common/ImageBox/DragHandleCollection.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9c7465c9ab64cb4f8484b9333dc2d0a6b4843235
--- /dev/null
+++ b/pdfpatcher/App/Common/ImageBox/DragHandleCollection.cs
@@ -0,0 +1,92 @@
+using System.Collections;
+using System.Collections.Generic;
+using System.Drawing;
+
+namespace Cyotek.Windows.Forms.Demo
+{
+ // Cyotek ImageBox
+ // Copyright (c) 2010-2015 Cyotek Ltd.
+ // http://cyotek.com
+ // http://cyotek.com/blog/tag/imagebox
+
+ // Licensed under the MIT License. See license.txt for the full text.
+
+ // If you use this control in your applications, attribution, donations or contributions are welcome.
+
+ internal sealed class DragHandleCollection : IEnumerable
+ {
+ #region Instance Fields
+
+ private readonly IDictionary _items;
+
+ #endregion
+
+ #region Public Constructors
+
+ public DragHandleCollection() {
+ _items = new Dictionary {
+ { DragHandleAnchor.TopLeft, new DragHandle(DragHandleAnchor.TopLeft) },
+ { DragHandleAnchor.TopCenter, new DragHandle(DragHandleAnchor.TopCenter) },
+ { DragHandleAnchor.TopRight, new DragHandle(DragHandleAnchor.TopRight) },
+ { DragHandleAnchor.MiddleLeft, new DragHandle(DragHandleAnchor.MiddleLeft) },
+ { DragHandleAnchor.MiddleRight, new DragHandle(DragHandleAnchor.MiddleRight) },
+ { DragHandleAnchor.BottomLeft, new DragHandle(DragHandleAnchor.BottomLeft) },
+ { DragHandleAnchor.BottomCenter, new DragHandle(DragHandleAnchor.BottomCenter) },
+ { DragHandleAnchor.BottomRight, new DragHandle(DragHandleAnchor.BottomRight) }
+ };
+ }
+
+ #endregion
+
+ #region Public Properties
+
+ public int Count => _items.Count;
+
+ public DragHandle this[DragHandleAnchor index] => _items[index];
+
+ #endregion
+
+ #region Public Members
+
+ ///
+ /// Returns an enumerator that iterates through the collection.
+ ///
+ ///
+ /// A that can be used to iterate through the collection.
+ ///
+ public IEnumerator GetEnumerator() {
+ return _items.Values.GetEnumerator();
+ }
+
+ public DragHandleAnchor HitTest(Point point) {
+ DragHandleAnchor result;
+
+ result = DragHandleAnchor.None;
+
+ foreach (DragHandle handle in this) {
+ if (handle.Visible && handle.Bounds.Contains(point)) {
+ result = handle.Anchor;
+ break;
+ }
+ }
+
+ return result;
+ }
+
+ #endregion
+
+ #region IEnumerable Members
+
+ ///
+ /// Returns an enumerator that iterates through a collection.
+ ///
+ ///
+ /// An object that can be used to iterate through the collection.
+ ///
+ IEnumerator IEnumerable.GetEnumerator() {
+ return GetEnumerator();
+ }
+
+ #endregion
+ }
+}
diff --git a/pdfpatcher/App/Common/ImageBox/ImageBoxEx.cs b/pdfpatcher/App/Common/ImageBox/ImageBoxEx.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1c63c6e1174c6c454692bbbeff26ead44865ebb9
--- /dev/null
+++ b/pdfpatcher/App/Common/ImageBox/ImageBoxEx.cs
@@ -0,0 +1,807 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+
+namespace Cyotek.Windows.Forms.Demo
+{
+ // Cyotek ImageBox
+ // Copyright (c) 2010-2015 Cyotek Ltd.
+ // http://cyotek.com
+ // http://cyotek.com/blog/tag/imagebox
+
+ // Licensed under the MIT License. See license.txt for the full text.
+
+ // If you use this control in your applications, attribution, donations or contributions are welcome.
+
+ internal class ImageBoxEx : ImageBox
+ {
+ #region Constants
+
+ private readonly DragHandleCollection _dragHandles;
+
+ private static readonly object _eventDragHandleSizeChanged = new object();
+
+ private static readonly object _eventMaximumSelectionSizeChanged = new object();
+
+ private static readonly object _eventMinimumSelectionSizeChanged = new object();
+
+ private static readonly object _eventSelectionMoved = new object();
+
+ private static readonly object _eventSelectionMoving = new object();
+
+ private static readonly object _eventSelectionResized = new object();
+
+ private static readonly object _eventSelectionResizing = new object();
+
+ #endregion
+
+ #region Fields
+
+ private int _dragHandleSize;
+
+ private Point _dragOrigin;
+
+ private Point _dragOriginOffset;
+
+ private bool _isMoving;
+
+ private bool _isResizing;
+
+ private Size _maximumSelectionSize;
+
+ private Size _minimumSelectionSize;
+
+ private RectangleF _previousSelectionRegion;
+
+ private DragHandleAnchor _resizeAnchor;
+
+ #endregion
+
+ #region Constructors
+
+ public ImageBoxEx() {
+ _dragHandles = new DragHandleCollection();
+ _dragHandleSize = 8;
+ _maximumSelectionSize = Size.Empty;
+ PositionDragHandles();
+ }
+
+ #endregion
+
+ #region Events
+
+ ///
+ /// Occurs when the DragHandleSize property value changes
+ ///
+ [Category("Property Changed")]
+ public event EventHandler DragHandleSizeChanged {
+ add { Events.AddHandler(_eventDragHandleSizeChanged, value); }
+ remove { Events.RemoveHandler(_eventDragHandleSizeChanged, value); }
+ }
+
+ ///
+ /// Occurs when the MaximumSelectionSize property value changes
+ ///
+ [Category("Property Changed")]
+ public event EventHandler MaximumSelectionSizeChanged {
+ add { Events.AddHandler(_eventMaximumSelectionSizeChanged, value); }
+ remove { Events.RemoveHandler(_eventMaximumSelectionSizeChanged, value); }
+ }
+
+ ///
+ /// Occurs when the MinimumSelectionSize property value changes
+ ///
+ [Category("Property Changed")]
+ public event EventHandler MinimumSelectionSizeChanged {
+ add { Events.AddHandler(_eventMinimumSelectionSizeChanged, value); }
+ remove { Events.RemoveHandler(_eventMinimumSelectionSizeChanged, value); }
+ }
+
+ [Category("Action")]
+ public event EventHandler SelectionMoved {
+ add { Events.AddHandler(_eventSelectionMoved, value); }
+ remove { Events.RemoveHandler(_eventSelectionMoved, value); }
+ }
+
+ [Category("Action")]
+ public event CancelEventHandler SelectionMoving {
+ add { Events.AddHandler(_eventSelectionMoving, value); }
+ remove { Events.RemoveHandler(_eventSelectionMoving, value); }
+ }
+
+ [Category("Action")]
+ public event EventHandler SelectionResized {
+ add { Events.AddHandler(_eventSelectionResized, value); }
+ remove { Events.RemoveHandler(_eventSelectionResized, value); }
+ }
+
+ [Category("Action")]
+ public event CancelEventHandler SelectionResizing {
+ add { Events.AddHandler(_eventSelectionResizing, value); }
+ remove { Events.RemoveHandler(_eventSelectionResizing, value); }
+ }
+
+ #endregion
+
+ #region Properties
+
+ [Browsable(false)]
+ public DragHandleCollection DragHandles => _dragHandles;
+
+ [Category("Appearance")]
+ [DefaultValue(8)]
+ public virtual int DragHandleSize {
+ get => _dragHandleSize;
+ set {
+ if (_dragHandleSize != value) {
+ _dragHandleSize = value;
+
+ OnDragHandleSizeChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool IsMoving {
+ get => _isMoving;
+ protected set => _isMoving = value;
+ }
+
+ [Browsable(false)]
+ [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
+ public bool IsResizing {
+ get => _isResizing;
+ protected set => _isResizing = value;
+ }
+
+ [Category("Behavior")]
+ [DefaultValue(typeof(Size), "0, 0")]
+ public virtual Size MaximumSelectionSize {
+ get => _maximumSelectionSize;
+ set {
+ if (MaximumSelectionSize != value) {
+ _maximumSelectionSize = value;
+
+ OnMaximumSelectionSizeChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [Category("Behavior")]
+ [DefaultValue(typeof(Size), "0, 0")]
+ public virtual Size MinimumSelectionSize {
+ get => _minimumSelectionSize;
+ set {
+ if (MinimumSelectionSize != value) {
+ _minimumSelectionSize = value;
+
+ OnMinimumSelectionSizeChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ [Browsable(false)]
+ public RectangleF PreviousSelectionRegion {
+ get => _previousSelectionRegion;
+ protected set => _previousSelectionRegion = value;
+ }
+
+ protected Point DragOrigin {
+ get => _dragOrigin;
+ set => _dragOrigin = value;
+ }
+
+ protected Point DragOriginOffset {
+ get => _dragOriginOffset;
+ set => _dragOriginOffset = value;
+ }
+
+ protected DragHandleAnchor ResizeAnchor {
+ get => _resizeAnchor;
+ set => _resizeAnchor = value;
+ }
+
+ #endregion
+
+ #region Methods
+
+ public void CancelResize() {
+ SelectionRegion = _previousSelectionRegion;
+ CompleteResize();
+ }
+
+ public void StartMove() {
+ CancelEventArgs e;
+
+ if (_isMoving || _isResizing) {
+ throw new InvalidOperationException("A move or resize action is currently being performed.");
+ }
+
+ e = new CancelEventArgs();
+
+ OnSelectionMoving(e);
+
+ if (!e.Cancel) {
+ _previousSelectionRegion = SelectionRegion;
+ _isMoving = true;
+ }
+ }
+
+ protected virtual void DrawDragHandle(Graphics graphics, DragHandle handle) {
+ int left;
+ int top;
+ int width;
+ int height;
+ Pen outerPen;
+ Brush innerBrush;
+
+ left = handle.Bounds.Left;
+ top = handle.Bounds.Top;
+ width = handle.Bounds.Width;
+ height = handle.Bounds.Height;
+
+ if (handle.Enabled) {
+ outerPen = SystemPens.WindowFrame;
+ innerBrush = SystemBrushes.Window;
+ }
+ else {
+ outerPen = SystemPens.ControlDark;
+ innerBrush = SystemBrushes.Control;
+ }
+
+ graphics.FillRectangle(innerBrush, left + 1, top + 1, width - 2, height - 2);
+ graphics.DrawLine(outerPen, left + 1, top, left + width - 2, top);
+ graphics.DrawLine(outerPen, left, top + 1, left, top + height - 2);
+ graphics.DrawLine(outerPen, left + 1, top + height - 1, left + width - 2, top + height - 1);
+ graphics.DrawLine(outerPen, left + width - 1, top + 1, left + width - 1, top + height - 2);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnDragHandleSizeChanged(EventArgs e) {
+ EventHandler handler;
+
+ PositionDragHandles();
+ Invalidate();
+
+ handler = (EventHandler)Events[_eventDragHandleSizeChanged];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnMaximumSelectionSizeChanged(EventArgs e) {
+ EventHandler handler;
+
+ handler = (EventHandler)Events[_eventMaximumSelectionSizeChanged];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnMinimumSelectionSizeChanged(EventArgs e) {
+ EventHandler handler;
+
+ handler = (EventHandler)Events[_eventMinimumSelectionSizeChanged];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// A that contains the event data.
+ ///
+ protected override void OnMouseDown(MouseEventArgs e) {
+ Point imagePoint;
+ RectangleF selectionRegion;
+
+ imagePoint = PointToImage(e.Location);
+ selectionRegion = SelectionRegion;
+
+ if (e.Button == MouseButtons.Left && (selectionRegion.Contains(imagePoint) || HitTest(e.Location) != DragHandleAnchor.None)) {
+ _dragOrigin = e.Location;
+ _dragOriginOffset = new Point(imagePoint.X - (int)selectionRegion.X, imagePoint.Y - (int)selectionRegion.Y);
+ }
+ else {
+ _dragOriginOffset = Point.Empty;
+ _dragOrigin = Point.Empty;
+ }
+
+ base.OnMouseDown(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// A that contains the event data.
+ ///
+ protected override void OnMouseMove(MouseEventArgs e) {
+ // start either a move or a resize operation
+ if (!IsSelecting && !_isMoving && !_isResizing && e.Button == MouseButtons.Left && !_dragOrigin.IsEmpty && IsOutsideDragZone(e.Location)) {
+ DragHandleAnchor anchor;
+
+ anchor = HitTest(_dragOrigin);
+
+ if (anchor == DragHandleAnchor.None) {
+ // move
+ StartMove();
+ }
+ else if (_dragHandles[anchor].
+ Enabled && _dragHandles[anchor].
+ Visible) {
+ // resize
+ StartResize(anchor);
+ }
+ }
+
+ // set the cursor
+ SetCursor(e.Location);
+
+ // perform operations
+ ProcessSelectionMove(e.Location);
+ ProcessSelectionResize(e.Location);
+
+ base.OnMouseMove(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// A that contains the event data.
+ ///
+ protected override void OnMouseUp(MouseEventArgs e) {
+ if (_isMoving) {
+ CompleteMove();
+ }
+ else if (_isResizing) {
+ CompleteResize();
+ }
+
+ base.OnMouseUp(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// A that contains the event data.
+ ///
+ protected override void OnPaint(PaintEventArgs e) {
+ base.OnPaint(e);
+
+ if (AllowPainting && !SelectionRegion.IsEmpty) {
+ foreach (DragHandle handle in _dragHandles) {
+ if (handle.Visible) {
+ DrawDragHandle(e.Graphics, handle);
+ }
+ }
+ }
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// The instance containing the event data.
+ ///
+ protected override void OnPanStart(CancelEventArgs e) {
+ if (_isMoving || _isResizing || !_dragOrigin.IsEmpty) {
+ e.Cancel = true;
+ }
+
+ base.OnPanStart(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// An that contains the event data.
+ ///
+ protected override void OnResize(EventArgs e) {
+ base.OnResize(e);
+
+ PositionDragHandles();
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// A that contains the event data.
+ ///
+ protected override void OnScroll(ScrollEventArgs se) {
+ base.OnScroll(se);
+
+ PositionDragHandles();
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// The instance containing the event data.
+ ///
+ protected override void OnSelecting(ImageBoxCancelEventArgs e) {
+ e.Cancel = _isMoving || _isResizing || SelectionRegion.Contains(PointToImage(e.Location)) || HitTest(e.Location) != DragHandleAnchor.None;
+
+ base.OnSelecting(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnSelectionMoved(EventArgs e) {
+ EventHandler handler;
+
+ handler = (EventHandler)Events[_eventSelectionMoved];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnSelectionMoving(CancelEventArgs e) {
+ CancelEventHandler handler;
+
+ handler = (CancelEventHandler)Events[_eventSelectionMoving];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// The instance containing the event data.
+ ///
+ protected override void OnSelectionRegionChanged(EventArgs e) {
+ base.OnSelectionRegionChanged(e);
+
+ PositionDragHandles();
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnSelectionResized(EventArgs e) {
+ EventHandler handler;
+
+ handler = (EventHandler)Events[_eventSelectionResized];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected virtual void OnSelectionResizing(CancelEventArgs e) {
+ CancelEventHandler handler;
+
+ handler = (CancelEventHandler)Events[_eventSelectionResizing];
+
+ handler?.Invoke(this, e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ ///
+ /// The instance containing the event data.
+ ///
+ protected override void OnZoomChanged(EventArgs e) {
+ base.OnZoomChanged(e);
+
+ PositionDragHandles();
+ }
+
+ ///
+ /// Processes a dialog key.
+ ///
+ ///
+ /// true if the key was processed by the control; otherwise, false.
+ ///
+ /// One of the values that represents the key to process.
+ protected override bool ProcessDialogKey(Keys keyData) {
+ bool result;
+
+ if (keyData == Keys.Escape && (_isResizing || _isMoving)) {
+ if (_isResizing) {
+ CancelResize();
+ }
+ else {
+ CancelMove();
+ }
+
+ result = true;
+ }
+ else {
+ result = base.ProcessDialogKey(keyData);
+ }
+
+ return result;
+ }
+
+ protected virtual void SetCursor(Point point) {
+ // http://forums.cyotek.com/imagebox/cursor-issue-in-imageboxex/msg92/#msg92
+
+ if (!IsPanning) {
+ Cursor cursor;
+
+ if (IsSelecting) {
+ cursor = Cursors.Default;
+ }
+ else {
+ DragHandleAnchor handleAnchor;
+
+ handleAnchor = _isResizing ? _resizeAnchor : HitTest(point);
+ if (handleAnchor != DragHandleAnchor.None && _dragHandles[handleAnchor].
+ Enabled) {
+ switch (handleAnchor) {
+ case DragHandleAnchor.TopLeft:
+ case DragHandleAnchor.BottomRight:
+ cursor = Cursors.SizeNWSE;
+ break;
+ case DragHandleAnchor.TopCenter:
+ case DragHandleAnchor.BottomCenter:
+ cursor = Cursors.SizeNS;
+ break;
+ case DragHandleAnchor.TopRight:
+ case DragHandleAnchor.BottomLeft:
+ cursor = Cursors.SizeNESW;
+ break;
+ case DragHandleAnchor.MiddleLeft:
+ case DragHandleAnchor.MiddleRight:
+ cursor = Cursors.SizeWE;
+ break;
+ default:
+ throw new ArgumentOutOfRangeException();
+ }
+ }
+ else if (_isMoving || SelectionRegion.Contains(PointToImage(point))) {
+ cursor = Cursors.SizeAll;
+ }
+ else {
+ cursor = Cursors.Default;
+ }
+ }
+
+ Cursor = cursor;
+ }
+ }
+
+ private void CancelMove() {
+ SelectionRegion = _previousSelectionRegion;
+ CompleteMove();
+ }
+
+ private void CompleteMove() {
+ ResetDrag();
+ OnSelectionMoved(EventArgs.Empty);
+ }
+
+ private void CompleteResize() {
+ ResetDrag();
+ OnSelectionResized(EventArgs.Empty);
+ }
+
+ private DragHandleAnchor HitTest(Point cursorPosition) {
+ return _dragHandles.HitTest(cursorPosition);
+ }
+
+ private bool IsOutsideDragZone(Point location) {
+ Rectangle dragZone;
+ int dragWidth;
+ int dragHeight;
+
+ dragWidth = SystemInformation.DragSize.Width;
+ dragHeight = SystemInformation.DragSize.Height;
+ dragZone = new Rectangle(_dragOrigin.X - (dragWidth / 2), _dragOrigin.Y - (dragHeight / 2), dragWidth, dragHeight);
+
+ return !dragZone.Contains(location);
+ }
+
+ private void PositionDragHandles() {
+ if (_dragHandles != null && _dragHandleSize > 0) {
+ RectangleF selectionRegion;
+
+ selectionRegion = SelectionRegion;
+
+ if (selectionRegion.IsEmpty) {
+ foreach (DragHandle handle in _dragHandles) {
+ handle.Bounds = Rectangle.Empty;
+ }
+ }
+ else {
+ int left;
+ int top;
+ int right;
+ int bottom;
+ int halfWidth;
+ int halfHeight;
+ int halfDragHandleSize;
+ Rectangle viewport;
+ int offsetX;
+ int offsetY;
+
+ viewport = GetImageViewPort();
+ offsetX = viewport.Left + Padding.Left + AutoScrollPosition.X;
+ offsetY = viewport.Top + Padding.Top + AutoScrollPosition.Y;
+ halfDragHandleSize = _dragHandleSize / 2;
+ left = Convert.ToInt32((selectionRegion.Left * ZoomFactor) + offsetX);
+ top = Convert.ToInt32((selectionRegion.Top * ZoomFactor) + offsetY);
+ right = left + Convert.ToInt32(selectionRegion.Width * ZoomFactor);
+ bottom = top + Convert.ToInt32(selectionRegion.Height * ZoomFactor);
+ halfWidth = Convert.ToInt32(selectionRegion.Width * ZoomFactor) / 2;
+ halfHeight = Convert.ToInt32(selectionRegion.Height * ZoomFactor) / 2;
+
+ _dragHandles[DragHandleAnchor.TopLeft].
+ Bounds = new Rectangle(left - _dragHandleSize, top - _dragHandleSize, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.TopCenter].
+ Bounds = new Rectangle(left + halfWidth - halfDragHandleSize, top - _dragHandleSize, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.TopRight].
+ Bounds = new Rectangle(right, top - _dragHandleSize, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.MiddleLeft].
+ Bounds = new Rectangle(left - _dragHandleSize, top + halfHeight - halfDragHandleSize, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.MiddleRight].
+ Bounds = new Rectangle(right, top + halfHeight - halfDragHandleSize, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.BottomLeft].
+ Bounds = new Rectangle(left - _dragHandleSize, bottom, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.BottomCenter].
+ Bounds = new Rectangle(left + halfWidth - halfDragHandleSize, bottom, _dragHandleSize, _dragHandleSize);
+ _dragHandles[DragHandleAnchor.BottomRight].
+ Bounds = new Rectangle(right, bottom, _dragHandleSize, _dragHandleSize);
+ }
+ }
+ }
+
+ private void ProcessSelectionMove(Point cursorPosition) {
+ if (_isMoving) {
+ int x;
+ int y;
+ Point imagePoint;
+ Size viewSize;
+ RectangleF selectionRegion;
+
+ imagePoint = PointToImage(cursorPosition, false);
+ viewSize = ViewSize;
+ selectionRegion = SelectionRegion;
+
+ x = Math.Max(0, imagePoint.X - _dragOriginOffset.X);
+ if (x + selectionRegion.Width >= viewSize.Width) {
+ x = viewSize.Width - (int)selectionRegion.Width;
+ }
+
+ y = Math.Max(0, imagePoint.Y - _dragOriginOffset.Y);
+ if (y + selectionRegion.Height >= viewSize.Height) {
+ y = viewSize.Height - (int)selectionRegion.Height;
+ }
+
+ SelectionRegion = new RectangleF(x, y, selectionRegion.Width, selectionRegion.Height);
+ }
+ }
+
+ private void ProcessSelectionResize(Point cursorPosition) {
+ if (_isResizing) {
+ Point imagePosition;
+ float left;
+ float top;
+ float right;
+ float bottom;
+ bool resizingTopEdge;
+ bool resizingBottomEdge;
+ bool resizingLeftEdge;
+ bool resizingRightEdge;
+ RectangleF selectionRegion;
+ Size viewSize;
+
+ imagePosition = PointToImage(cursorPosition);
+ viewSize = ViewSize;
+
+ // get the current selection
+ selectionRegion = SelectionRegion;
+ left = selectionRegion.Left;
+ top = selectionRegion.Top;
+ right = selectionRegion.Right;
+ bottom = selectionRegion.Bottom;
+
+ // decide which edges we're resizing
+ resizingTopEdge = _resizeAnchor >= DragHandleAnchor.TopLeft && _resizeAnchor <= DragHandleAnchor.TopRight;
+ resizingBottomEdge = _resizeAnchor >= DragHandleAnchor.BottomLeft && _resizeAnchor <= DragHandleAnchor.BottomRight;
+ resizingLeftEdge = _resizeAnchor == DragHandleAnchor.TopLeft || _resizeAnchor == DragHandleAnchor.MiddleLeft || _resizeAnchor == DragHandleAnchor.BottomLeft;
+ resizingRightEdge = _resizeAnchor == DragHandleAnchor.TopRight || _resizeAnchor == DragHandleAnchor.MiddleRight || _resizeAnchor == DragHandleAnchor.BottomRight;
+
+ // and resize!
+ if (resizingTopEdge) {
+ top = imagePosition.Y > 0 ? imagePosition.Y : 0;
+
+ if (bottom - top < MinimumSelectionSize.Height) {
+ top = bottom - MinimumSelectionSize.Height;
+ }
+ else if (MaximumSelectionSize.Height > 0 && bottom - top > MaximumSelectionSize.Height) {
+ top = bottom - MaximumSelectionSize.Height;
+ }
+ }
+ else if (resizingBottomEdge) {
+ bottom = imagePosition.Y < viewSize.Height ? imagePosition.Y : viewSize.Height;
+
+ if (bottom - top < MinimumSelectionSize.Height) {
+ bottom = top + MinimumSelectionSize.Height;
+ }
+ else if (MaximumSelectionSize.Height > 0 && bottom - top > MaximumSelectionSize.Height) {
+ bottom = top + MaximumSelectionSize.Height;
+ }
+ }
+
+ if (resizingLeftEdge) {
+ left = imagePosition.X > 0 ? imagePosition.X : 0;
+
+ if (right - left < MinimumSelectionSize.Width) {
+ left = right - MinimumSelectionSize.Width;
+ }
+ else if (MaximumSelectionSize.Width > 0 && right - left > MaximumSelectionSize.Width) {
+ left = right - MaximumSelectionSize.Width;
+ }
+ }
+ else if (resizingRightEdge) {
+ right = imagePosition.X < viewSize.Width ? imagePosition.X : viewSize.Width;
+
+ if (right - left < MinimumSelectionSize.Width) {
+ right = left + MinimumSelectionSize.Width;
+ }
+ else if (MaximumSelectionSize.Width > 0 && right - left > MaximumSelectionSize.Width) {
+ right = left + MaximumSelectionSize.Width;
+ }
+ }
+
+ SelectionRegion = new RectangleF(left, top, right - left, bottom - top);
+ }
+ }
+
+ private void ResetDrag() {
+ _isResizing = false;
+ _isMoving = false;
+ _dragOrigin = Point.Empty;
+ _dragOriginOffset = Point.Empty;
+ }
+
+ private void StartResize(DragHandleAnchor anchor) {
+ CancelEventArgs e;
+
+ if (_isMoving || _isResizing) {
+ throw new InvalidOperationException("A move or resize action is currently being performed.");
+ }
+
+ e = new CancelEventArgs();
+
+ OnSelectionResizing(e);
+
+ if (!e.Cancel) {
+ _resizeAnchor = anchor;
+ _previousSelectionRegion = SelectionRegion;
+ _isResizing = true;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/pdfpatcher/App/Common/ObjectListViewHelper.cs b/pdfpatcher/App/Common/ObjectListViewHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1ee48a12d22a528f19c45f7a19b11ef8254a4c37
--- /dev/null
+++ b/pdfpatcher/App/Common/ObjectListViewHelper.cs
@@ -0,0 +1,218 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+
+namespace BrightIdeasSoftware
+{
+ static class ObjectListViewHelper
+ {
+ /// 修复编辑控件太窄小的问题。
+ public static void FixEditControlWidth(this ObjectListView view) {
+ view.CellEditStarting += View_CellEditStarting;
+ view.Disposed += View_Disposed;
+ }
+
+ static void View_Disposed(object sender, EventArgs e) {
+ var view = (ObjectListView)sender;
+ view.CellEditStarting -= View_CellEditStarting;
+ view.Disposed -= View_Disposed;
+ }
+
+ static void View_CellEditStarting(object sender, CellEditEventArgs e) {
+ var b = e.CellBounds;
+ if (b.Width < 60) {
+ b.Width = 60;
+ }
+ if (e.Control is System.Windows.Forms.Control c) {
+ c.Bounds = b;
+ c.Location = b.Location;
+ }
+ }
+
+ public static void SetTreeViewLine(this TreeListView view) {
+ var tcr = view.TreeColumnRenderer as TreeListView.TreeRenderer;
+ tcr.LinePen = new Pen(SystemColors.ControlDark) {
+ DashCap = DashCap.Round,
+ DashStyle = DashStyle.Dash
+ };
+ }
+
+ public static void ExpandSelected(this TreeListView view) {
+ var so = view.SelectedObjects;
+ foreach (var item in so) {
+ view.Expand(item);
+ }
+ }
+ public static TypedObjectListView AsTyped(this ObjectListView view) where T : class {
+ return view.AsTyped(null);
+ }
+
+ public static TypedObjectListView AsTyped(this ObjectListView view, Action> configurator) where T : class {
+ var v = new TypedObjectListView(view);
+ configurator?.Invoke(v);
+ return v;
+ }
+ public static TypedObjectListView ConfigColumn(this TypedObjectListView view, OLVColumn column, Action> configurator) where T : class {
+ var t = new TypedColumn(column);
+ configurator(t);
+ return view;
+ }
+ public static TypedColumn AsTyped(this OLVColumn column, Action> configurator) where T : class {
+ var t = new TypedColumn(column);
+ configurator(t);
+ return t;
+ }
+ public static T GetParentModel(this TreeListView view, T model) where T : class {
+ return view.GetParent(model) as T;
+ }
+
+ public static List GetAncestorsOrSelf(this TreeListView view, T model) where T : class {
+ var r = new List();
+ do {
+ r.Add(model);
+ } while ((model = view.GetParent(model) as T) != null);
+ return r;
+ }
+
+ public static void CollapseSelected(this TreeListView view) {
+ var so = view.SelectedObjects;
+ foreach (var item in so) {
+ view.Collapse(item);
+ }
+ }
+
+ public static void MoveUpSelection(this ObjectListView view) {
+ var si = view.GetFirstSelectedIndex();
+ if (si < 1) {
+ return;
+ }
+ var so = view.SelectedObjects;
+ view.MoveObjects(--si, so);
+ view.SelectedObjects = so;
+ }
+
+ public static void MoveDownSelection(this ObjectListView view) {
+ var ls = view.GetLastItemInDisplayOrder();
+ if (ls == null || ls.Selected == true) {
+ return;
+ }
+ var si = view.GetFirstSelectedIndex();
+ if (si < 0) {
+ return;
+ }
+ var so = view.SelectedObjects;
+ view.MoveObjects(si + 2, so);
+ view.SelectedObjects = so;
+ }
+
+ public static T GetFirstSelectedModel(this ObjectListView view) where T : class {
+ return view.GetModelObject(view.GetFirstSelectedIndex()) as T;
+ }
+
+ /// 树视图存在子节点且多选节点时,在 SelectedIndexChanged 事件中,SelectedIndices属性可能返回无内容的集合。
+ public static int GetFirstSelectedIndex(this ObjectListView view) {
+ var c = view.GetItemCount();
+ int i = c;
+ foreach (int item in view.SelectedIndices) {
+ if (item < i) {
+ i = item;
+ }
+ }
+ return i == c ? -1 : i;
+ }
+
+ public static int GetLastSelectedIndex(this ObjectListView view) {
+ int i = -1;
+ foreach (int item in view.SelectedIndices) {
+ if (item > i) {
+ i = item;
+ }
+ }
+ return i;
+ }
+
+ public static List GetSelectedModels(this ObjectListView view) where T : class {
+ var s = view.SelectedObjects;
+ var r = new List(s.Count);
+ foreach (T item in s) {
+ if (item != null) {
+ r.Add(item);
+ }
+ }
+ return r;
+ }
+
+ /// 测试坐标点属于哪个单元格。
+ public static GridTestResult GetGridAt(this ObjectListView view, int x, int y) {
+ OLVColumn c = null;
+ var cr = view.ContentRectangle;
+ var ic = view.GetItemCount();
+ var ob = false;
+ if (x < cr.Left) {
+ x = cr.Left;
+ ob = true;
+ }
+ else if (x >= cr.Right) {
+ x = cr.Right - 1;
+ ob = true;
+ }
+ var cb = cr.Top + ic * view.RowHeightEffective;
+ if (y < cr.Top) {
+ y = cr.Top;
+ ob = true;
+ }
+ else if (y >= cb) {
+ y = cb;
+ ob = true;
+ }
+ var r = view.GetItemAt(x, y, out c);
+ if (r != null) {
+ return new GridTestResult(c.DisplayIndex, r.Index, ob);
+ }
+ // 当列表框滚动时,上述方法失效,使用此替补方法
+ r = view.GetNthItemInDisplayOrder((y - 1 - cr.Top) / view.RowHeightEffective);
+ var w = cr.Left;
+ var cl = view.ColumnsInDisplayOrder;
+ for (int i = 0; i < cl.Count; i++) {
+ if (x >= w && x <= (w += cl[i].Width)) {
+ c = cl[i];
+ break;
+ }
+ }
+ if (c == null) {
+ c = cl[cl.Count - 1];
+ ob = true;
+ }
+ y = r.Index + view.TopItemIndex;
+ if (y >= view.GetItemCount()) {
+ y = view.GetItemCount() - 1;
+ }
+ return new GridTestResult(c.DisplayIndex, y, ob);
+ }
+
+ public static void InvertSelect(this ObjectListView view) {
+ view.Freeze();
+ var l = view.GetItemCount();
+ for (int i = 0; i < l; i++) {
+ var oi = view.GetItem(i);
+ oi.Selected = !oi.Selected;
+ }
+ view.Unfreeze();
+ }
+
+ }
+
+ public struct GridTestResult
+ {
+ public int ColumnIndex { get; private set; }
+ public int RowIndex { get; private set; }
+ public bool IsOutOfRange { get; private set; }
+
+ public GridTestResult(int columnIndex, int rowIndex, bool isOutOfRange) {
+ ColumnIndex = columnIndex;
+ RowIndex = rowIndex;
+ IsOutOfRange = isOutOfRange;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/PInvokeHelper.cs b/pdfpatcher/App/Common/PInvokeHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f90dc0b4de44376a870990e66782b693a72512b0
--- /dev/null
+++ b/pdfpatcher/App/Common/PInvokeHelper.cs
@@ -0,0 +1,23 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.InteropServices;
+
+namespace PDFPatcher.Common
+{
+ static class PInvokeHelper
+ {
+ ///
+ /// 将 指针对应的数据转换为 类型实例。
+ ///
+ /// 传出类型实例。
+ /// 指向数据的指针。
+ /// 指针封装后的托管实例。
+ internal static T Unwrap(this IntPtr ptr) where T : class, new() {
+ var t = new T();
+ Marshal.PtrToStructure(ptr, t);
+ return t;
+ }
+
+
+ }
+}
diff --git a/pdfpatcher/App/Common/ShortcutFile.cs b/pdfpatcher/App/Common/ShortcutFile.cs
new file mode 100644
index 0000000000000000000000000000000000000000..815de573c735509b2a78a9155d408e29d1402a4e
--- /dev/null
+++ b/pdfpatcher/App/Common/ShortcutFile.cs
@@ -0,0 +1,115 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Text;
+
+namespace PDFPatcher.Common
+{
+ /// 用于创建或管理快捷方式文件的类。
+ public sealed class ShortcutFile
+ {
+ readonly IShellLink _link;
+
+ /// 获取或设置快捷方式的目标路径。
+ public string Destination { get; private set; }
+ /// 获取或设置快捷方式的工作目录。
+ public string WorkingDirectory { get; set; }
+ /// 获取或设置快捷方式的描述文本。
+ public string Description { get; set; }
+ /// 获取或设置快捷方式的启动参数。
+ public string Arguments { get; set; }
+ /// 获取或设置快捷方式的图标文件位置。
+ public string IconLocation { get; set; }
+ /// 获取或设置快捷方式的图标文件索引。
+ public int IconIndex { get; set; }
+
+ private ShortcutFile() {
+ _link = (IShellLink)new ShellLink();
+ }
+
+ /// 创建快捷方式。
+ /// 快捷方式指向的目标文件路径。
+ public ShortcutFile(string destination) {
+ _link = (IShellLink)new ShellLink();
+ Destination = destination;
+ _link.SetPath(destination);
+ }
+
+ /// 加载快捷方式。
+ /// 快捷方式文件的位置。
+ /// 实例。
+ public static ShortcutFile Load(string shortcutFilePath) {
+ var s = new ShortcutFile();
+ var l = s._link;
+ var file = (System.Runtime.InteropServices.ComTypes.IPersistFile)s._link;
+ file.Load(shortcutFilePath, 0);
+ s.Destination = shortcutFilePath;
+ var sb = new StringBuilder();
+ l.GetDescription(sb, 512);
+ s.Description = sb.ToString();
+ sb.Length = 0;
+ l.GetWorkingDirectory(sb, 256);
+ s.WorkingDirectory = sb.ToString();
+ int ii;
+ sb.Length = 0;
+ l.GetIconLocation(sb, 256, out ii);
+ s.IconLocation = sb.ToString();
+ sb.Length = 0;
+ l.GetArguments(sb, 256);
+ s.Arguments = sb.ToString();
+ return s;
+ }
+
+ /// 将快捷方式保存到目标位置。
+ /// 快捷方式文件的位置。
+ public void Save(string position) {
+ if (String.IsNullOrEmpty(WorkingDirectory) == false) {
+ _link.SetWorkingDirectory(WorkingDirectory);
+ }
+ if (String.IsNullOrEmpty(Description) == false) {
+ _link.SetDescription(Description);
+ }
+ if (String.IsNullOrEmpty(Arguments) == false) {
+ _link.SetArguments(Arguments);
+ }
+ if (String.IsNullOrEmpty(IconLocation) == false) {
+ _link.SetIconLocation(IconLocation, IconIndex >= 0 ? IconIndex : 0);
+ }
+ var file = (System.Runtime.InteropServices.ComTypes.IPersistFile)_link;
+ file.Save(position, false);
+ }
+
+ #region COM Interops
+ [ComImport]
+ [Guid("00021401-0000-0000-C000-000000000046")]
+ class ShellLink
+ {
+ }
+
+ [ComImport]
+ [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
+ [Guid("000214F9-0000-0000-C000-000000000046")]
+ interface IShellLink
+ {
+ void GetPath([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszFile, int cchMaxPath, out IntPtr pfd, int fFlags);
+ void GetIDList(out IntPtr ppidl);
+ void SetIDList(IntPtr pidl);
+ void GetDescription([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszName, int cchMaxName);
+ void SetDescription([MarshalAs(UnmanagedType.LPWStr)] string pszName);
+ void GetWorkingDirectory([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszDir, int cchMaxPath);
+ void SetWorkingDirectory([MarshalAs(UnmanagedType.LPWStr)] string pszDir);
+ void GetArguments([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszArgs, int cchMaxPath);
+ void SetArguments([MarshalAs(UnmanagedType.LPWStr)] string pszArgs);
+ void GetHotkey(out short pwHotkey);
+ void SetHotkey(short wHotkey);
+ void GetShowCmd(out int piShowCmd);
+ void SetShowCmd(int iShowCmd);
+ void GetIconLocation([Out, MarshalAs(UnmanagedType.LPWStr)] StringBuilder pszIconPath, int cchIconPath, out int piIcon);
+ void SetIconLocation([MarshalAs(UnmanagedType.LPWStr)] string pszIconPath, int iIcon);
+ void SetRelativePath([MarshalAs(UnmanagedType.LPWStr)] string pszPathRel, int dwReserved);
+ void Resolve(IntPtr hwnd, int fFlags);
+ void SetPath([MarshalAs(UnmanagedType.LPWStr)] string pszFile);
+ }
+ #endregion
+ }
+
+}
diff --git a/pdfpatcher/App/Common/StringBuilderCache.cs b/pdfpatcher/App/Common/StringBuilderCache.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1aeaf1fd69d4631271d759b64a81619ff212a8d0
--- /dev/null
+++ b/pdfpatcher/App/Common/StringBuilderCache.cs
@@ -0,0 +1,43 @@
+using System;
+using System.Text;
+
+namespace PDFPatcher.Common
+{
+ internal static class StringBuilderCache
+ {
+ internal const int MaxBuilderSize = 360;
+ const int DefaultCapacity = 16; // == StringBuilder.DefaultCapacity
+
+ [ThreadStatic]
+ static StringBuilder __CachedInstance;
+
+ public static StringBuilder Acquire(int capacity = DefaultCapacity) {
+ if (capacity <= MaxBuilderSize) {
+ StringBuilder sb = __CachedInstance;
+ if (sb != null) {
+ // Avoid stringbuilder block fragmentation by getting a new StringBuilder
+ // when the requested size is larger than the current capacity
+ if (capacity <= sb.Capacity) {
+ __CachedInstance = null;
+ sb.Length = 0;
+ return sb;
+ }
+ }
+ }
+
+ return new StringBuilder(capacity);
+ }
+
+ public static void Release(StringBuilder sb) {
+ if (sb.Capacity <= MaxBuilderSize) {
+ __CachedInstance = sb;
+ }
+ }
+
+ public static string GetStringAndRelease(StringBuilder sb) {
+ string result = sb.ToString();
+ Release(sb);
+ return result;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/StringHelper.cs b/pdfpatcher/App/Common/StringHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e9f1c7b9e14f847a7b790aee6cf3f320675833a9
--- /dev/null
+++ b/pdfpatcher/App/Common/StringHelper.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Diagnostics;
+
+namespace PDFPatcher.Common
+{
+ static class StringHelper
+ {
+ [DebuggerStepThrough]
+ public static bool IsNullOrWhiteSpace(this string text) {
+ return String.IsNullOrWhiteSpace(text);
+ }
+
+ public static string ReplaceControlAndBomCharacters(string source) {
+ if (String.IsNullOrEmpty(source)) {
+ return String.Empty;
+ }
+ var p = source.ToCharArray();
+ var m = false;
+ for (int i = 0; i < source.Length; i++) {
+ ref var c = ref p[i];
+ if ((Char.IsControl(c) && c != '\t' && c != '\r' && c != '\n')
+ || (c > 0xFFFD && (c == 0xFFFF || c == 0xFFFE || c == 0xFFEF))
+ ) {
+ c = ' ';
+ m = true;
+ }
+ }
+ return m ? new String(p) : source;
+ }
+
+ public static string Take(this string text, int startIndex, int count) {
+ if (String.IsNullOrEmpty(text) || startIndex >= text.Length) {
+ return String.Empty;
+ }
+ if (startIndex < 0) {
+ startIndex = text.Length + startIndex;
+ if (startIndex < 0) {
+ startIndex = 0;
+ }
+ }
+ return count <= 0
+ ? String.Empty
+ : text.Substring(startIndex, startIndex + count > text.Length ? text.Length - startIndex : count);
+ }
+
+ public static string ToDescription(this TEnum value) where TEnum : Enum {
+ return value.ToString();
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/ValueHelper.cs b/pdfpatcher/App/Common/ValueHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..93fe2459a11131c23d32edd84789ac4e427577ae
--- /dev/null
+++ b/pdfpatcher/App/Common/ValueHelper.cs
@@ -0,0 +1,541 @@
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Globalization;
+using System.Text;
+
+namespace PDFPatcher.Common
+{
+ static class ValueHelper
+ {
+ [DebuggerStepThrough]
+ public static TValue CastOrDefault(this object value, TValue defaultValue) where TValue : struct {
+ return value is TValue v ? v : defaultValue;
+ }
+ [DebuggerStepThrough]
+ public static TValue CastOrDefault(this object value) where TValue : struct {
+ return value is TValue v ? v : default;
+ }
+ [DebuggerStepThrough]
+ public static bool HasContent(this ICollection collection) {
+ return collection?.Count > 0;
+ }
+ [DebuggerStepThrough]
+ public static T SubstituteDefault(this T value, T otherValue) {
+ return EqualityComparer.Default.Equals(value, default(T)) ? otherValue : value;
+ }
+ public static TDisposable TryDispose(this TDisposable disposable)
+ where TDisposable : IDisposable {
+ if (disposable != null) {
+ try {
+ disposable.Dispose();
+ }
+ catch (Exception) {
+ // ignore
+ }
+ }
+ return disposable;
+ }
+ [DebuggerStepThrough]
+ public static bool IsInCollection(T input, params T[] values) {
+ return values != null && input != null && values.Length != 0 && Array.IndexOf(values, input) != -1;
+ }
+ [DebuggerStepThrough]
+ public static IComparer GetReverseComparer()
+ where TItem : IComparable {
+ return new ReverseComparer();
+ }
+ public static T LimitInRange(this T value, T minValue, T maxValue)
+ where T : IComparable {
+ return
+ value.CompareTo(minValue) < 0 ? minValue
+ : value.CompareTo(maxValue) > 0 ? maxValue
+ : value;
+ }
+ public static TValue GetOrDefault(this IDictionary dictionary, TKey key) {
+ TValue r;
+ return dictionary == null ? default : dictionary.TryGetValue(key, out r) ? r : r;
+ }
+ public static TValue GetOrDefault(this IDictionary dictionary, TKey key, TValue defaultValue) {
+ TValue r;
+ return dictionary != null && dictionary.TryGetValue(key, out r) ? r : defaultValue;
+ }
+
+ public static TMapped MapValue(TValue input, TValue[] fromValues, TMapped[] toValues) {
+ return MapValue(input, fromValues, toValues, default(TMapped));
+ }
+ public static TMapped MapValue(TValue input, TValue[] fromValues, TMapped[] toValues, TMapped defaultValue) {
+ if (fromValues == null) {
+ return defaultValue;
+ }
+ if (toValues == null) {
+ return defaultValue;
+ }
+ var i = Array.IndexOf(fromValues, input);
+ if (i == -1 || i >= toValues.Length) {
+ return defaultValue;
+ }
+ return toValues[i];
+ }
+
+ public static TMapped MapValue(TValue input, IEnumerable fromValues, IEnumerable toValues, TMapped defaultValue) {
+ if (fromValues == null) {
+ return defaultValue;
+ }
+ if (toValues == null) {
+ return defaultValue;
+ }
+ var i = 0;
+ var j = 0;
+ var c = EqualityComparer.Default;
+ foreach (var x in fromValues) {
+ if (c.Equals(input, x)) {
+ foreach (var y in toValues) {
+ if (i == j) {
+ return y;
+ }
+ j++;
+ }
+ return defaultValue;
+ }
+ i++;
+ }
+ return defaultValue;
+ }
+ public static IEnumerable ForEach(this IEnumerable collection, Action itemHandler) {
+ if (collection == null || itemHandler == null) {
+ return collection;
+ }
+ foreach (var item in collection) {
+ if (item is TItem v) {
+ itemHandler(v);
+ }
+ }
+ return collection;
+ }
+ public static TCollection AddRange(this TCollection target, IEnumerable source)
+ where TCollection : ICollection {
+ if (source == null || target == null) {
+ return target;
+ }
+ if (target is List list) {
+ list.AddRange(source);
+ return target;
+ }
+
+ foreach (T item in source) {
+ target.Add(item);
+ }
+ return target;
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this DateTimeOffset value) {
+ return value.ToString(NumberFormatInfo.InvariantInfo);
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this int value) {
+ return value.ToString(NumberFormatInfo.InvariantInfo);
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this float value) {
+ return Math.Abs(value) < 0.00001 ? "0" : value.ToString(NumberFormatInfo.InvariantInfo);
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this double value) {
+ return Math.Abs(value) < 0.000000000001 ? "0" : value.ToString(NumberFormatInfo.InvariantInfo);
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this long value) {
+ return value.ToString(CultureInfo.InvariantCulture);
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this decimal value) {
+ return value.ToString(NumberFormatInfo.InvariantInfo);
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this TFormattable value)
+ where TFormattable : IFormattable {
+ return value.ToString(null, NumberFormatInfo.InvariantInfo);
+ }
+ [DebuggerStepThrough]
+ public static string ToText(this TFormattable value, string format)
+ where TFormattable : IFormattable {
+ return value.ToString(format, NumberFormatInfo.InvariantInfo);
+ }
+
+ public static bool ToBoolean(this string value, bool defaultValue) {
+ if (string.IsNullOrEmpty(value)) {
+ return defaultValue;
+ }
+ switch (ParseBoolean(value)) {
+ case 1: return true;
+ case 0: return false;
+ default: return defaultValue;
+ }
+ }
+
+ static int ParseBoolean(string value) {
+ const int True = 1, False = 0, Invalid = -1;
+ var i = 0;
+ var l = value.Length;
+ do {
+ var c = value[i];
+ switch (c) {
+ case 'T':
+ case 't':
+ if (i + 3 < l && ((c = value[++i]) == 'r' || c == 'R') && ((c = value[++i]) == 'u' || c == 'U') && ((c = value[++i]) == 'e' || c == 'E')) {
+ goto EndsWithWhitespaceTrue;
+ }
+ return Invalid;
+ case 'F':
+ case 'f':
+ if (i + 4 < l && ((c = value[++i]) == 'a' || c == 'A') && ((c = value[++i]) == 'l' || c == 'L') && ((c = value[++i]) == 's' || c == 'S') && ((c = value[++i]) == 'e' || c == 'E')) {
+ goto EndsWithWhitespaceFalse;
+ }
+ return Invalid;
+ case 'Y':
+ case 'y':
+ if (i + 2 < l && ((c = value[++i]) == 'e' || c == 'E') && ((c = value[++i]) == 's' || c == 'S')) {
+ goto EndsWithWhitespaceTrue;
+ }
+ return Invalid;
+ case 'N':
+ case 'n':
+ if (i + 1 < l && ((c = value[++i]) == 'o' || c == 'O')) {
+ goto EndsWithWhitespaceFalse;
+ }
+ return Invalid;
+ case 'O':
+ case 'o':
+ if (i + 2 < l && ((c = value[++i]) == 'f' || c == 'F') && ((c = value[++i]) == 'f' || c == 'F')) {
+ goto EndsWithWhitespaceFalse;
+ }
+ if (i + 1 < l && ((c = value[++i]) == 'n' || c == 'N' || c == 'k' || c == 'K')) {
+ goto EndsWithWhitespaceTrue;
+ }
+ return Invalid;
+ case '是':
+ case '对':
+ case '开':
+ goto EndsWithWhitespaceTrue;
+ case '否':
+ case '关':
+ goto EndsWithWhitespaceFalse;
+ case '正':
+ if (i + 1 < l && value[++i] == '确') {
+ goto EndsWithWhitespaceTrue;
+ }
+ goto EndsWithWhitespaceFalse;
+ case '错':
+ if (i + 1 < l && value[++i] == '误') {
+ goto EndsWithWhitespaceFalse;
+ }
+ goto EndsWithWhitespaceFalse;
+ default:
+ if (Char.IsWhiteSpace(c)) {
+ continue;
+ }
+ if (c >= '0' && c <= '9' || c == '-' || c == '+' || c == '.') {
+ bool notZero = c > '0' && c <= '9';
+ var hasDot = false;
+ while (++i < l) {
+ c = value[i];
+ if (Char.IsNumber(c) == false && Char.IsWhiteSpace(c) == false) {
+ if (c == '.') {
+ if (hasDot == false) {
+ hasDot = true;
+ continue;
+ }
+ else {
+ return Invalid;
+ }
+ }
+ return Invalid;
+ }
+ if (notZero == false) {
+ notZero = c > '0' && c <= '9';
+ }
+ }
+ return notZero ? True : False;
+ }
+ return -1;
+ }
+ } while (++i < l);
+ EndsWithWhitespaceTrue:
+ while (++i < l && Char.IsWhiteSpace(value[i])) { }
+ return i == l ? True : Invalid;
+ EndsWithWhitespaceFalse:
+ while (++i < l && Char.IsWhiteSpace(value[i])) { }
+ return i == l ? False : Invalid;
+ }
+
+ [DebuggerStepThrough]
+ public static int ToInt32(this float value) {
+ return (int)(value > 0 ? value + 0.5f : value - 0.5f);
+ }
+
+ [DebuggerStepThrough]
+ public static int ToInt32(this double value) {
+ return (int)(value > 0 ? value + 0.5d : value - 0.5d);
+ }
+
+ [DebuggerStepThrough]
+ public static long ToInt64(this float value) {
+ return (long)(value > 0 ? value + 0.5f : value - 0.5f);
+ }
+
+ [DebuggerStepThrough]
+ public static long ToInt64(this double value) {
+ return (long)(value > 0 ? value + 0.5d : value - 0.5d);
+ }
+
+ [DebuggerStepThrough]
+ public static int ToInt32(this string value) {
+ int i;
+ value.TryParse(out i);
+ return i;
+ }
+ [DebuggerStepThrough]
+ public static int ToInt32(this string value, int defaultValue) {
+ int i;
+ return value.TryParse(out i) ? i : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static long ToInt64(this string value) {
+ long i;
+ value.TryParse(out i);
+ return i;
+ }
+
+ [DebuggerStepThrough]
+ public static long ToInt64(this string value, long defaultValue) {
+ long i;
+ return value.TryParse(out i) ? i : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static float ToSingle(this string value) {
+ float i;
+ value.TryParse(out i);
+ return i;
+ }
+
+ [DebuggerStepThrough]
+ public static float ToSingle(this string value, float defaultValue) {
+ float i;
+ return value.TryParse(out i) ? i : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static double ToDouble(this string value) {
+ double i;
+ value.TryParse(out i);
+ return i;
+ }
+
+ [DebuggerStepThrough]
+ public static double ToDouble(this string value, double defaultValue) {
+ double i;
+ return value.TryParse(out i) ? i : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static string ToText(this byte value) {
+ return value.ToString(CultureInfo.InvariantCulture);
+ }
+ public static bool TryParse(this string value, out int result) {
+ return Int32.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out result)
+ || ParseFloatStringToInt32(value, ref result);
+ }
+
+ static bool ParseFloatStringToInt32(string value, ref int result) {
+ if (double.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var d)) {
+ result = d.ToInt32();
+ return true;
+ }
+ return false;
+ }
+
+ public static bool TryParse(this string value, out long result) {
+ return Int64.TryParse(value, NumberStyles.Integer, NumberFormatInfo.InvariantInfo, out result)
+ || ParseFloatStringToInt64(value, ref result);
+ }
+
+ static bool ParseFloatStringToInt64(string value, ref long result) {
+ if (double.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out var d)) {
+ result = d.ToInt64();
+ return true;
+ }
+ return false;
+ }
+
+ [DebuggerStepThrough]
+ public static bool TryParse(this string value, out float result) {
+ return float.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out result);
+ }
+
+ [DebuggerStepThrough]
+ public static bool TryParse(this string value, out double result) {
+ return double.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out result);
+ }
+
+ [DebuggerStepThrough]
+ public static bool TryParse(this string value, out decimal result) {
+ return decimal.TryParse(value, NumberStyles.Float, NumberFormatInfo.InvariantInfo, out result);
+ }
+
+ public static string ToRoman(this int value) {
+ if (value > 49999 || value < 1) {
+ return string.Empty;
+ }
+ var sb = new StringBuilder();
+ do {
+ for (int i = value < 40 ? 5 : value < 400 ? 9 : Roman.Values.Length - 1; i >= 0; i--) {
+ var n = Roman.Values[i];
+ if (value >= n) {
+ value -= n;
+ sb.Append(Roman.Chars[i]);
+ break;
+ }
+ }
+ } while (value > 0);
+ return sb.ToString();
+ }
+ public static string ToAlphabet(this int value, bool upper) {
+ if (value <= 0) {
+ return string.Empty;
+ }
+ var stack = new char[7];
+ var c = (upper ? 'A' : 'a') - 1;
+ var p = -1;
+ while (value > 0) {
+ var i = value % 26;
+ stack[++p] = (char)(c + (i == 0 ? 26 : i));
+ value = --value / 26;
+ }
+ return new string(stack, 0, ++p);
+ }
+ public static string ToHexBinString(this byte value, bool upperCaseHex) {
+ return HexBinByteToString.ToString(value, upperCaseHex);
+ }
+ public static string ToHexBinString(this byte[] source) {
+ return InternalToHexBinString(source, true, '\0', 0, Int32.MaxValue);
+ }
+ public static string ToHexBinString(this byte[] source, bool upperCaseHex, char separator, int offset, int count) {
+ return InternalToHexBinString(source, upperCaseHex, separator, offset, count);
+ }
+ unsafe static string InternalToHexBinString(byte[] source, bool upperCaseHex, char separator, int offset, int count) {
+ if (source == null || offset < 0 || count < 1) {
+ return String.Empty;
+ }
+ var length = source.Length;
+ if (length == 0 || offset >= length) {
+ return String.Empty;
+ }
+ if (count > length - offset) {
+ count = length - offset;
+ }
+ if (count == 1) {
+ return source[offset].ToHexBinString(upperCaseHex);
+ }
+ var result = new string('0', (count << 1) + (separator > 0 ? count - 1 : 0));
+ fixed (char* p = result)
+ fixed (byte* bp = &source[offset]) {
+ byte* b = bp;
+ byte* end = bp + count;
+ var mapper = HexBinByteValues.GetHexBinMapper(upperCaseHex);
+ if (separator == 0) {
+ int* h = (int*)p;
+ while (b < end) {
+ *(h++) = mapper[*(b++)];
+ }
+ return result;
+ }
+ else {
+ char* c = p;
+ *(int*)(c) = mapper[*bp];
+ while (++b < end) {
+ c += 2;
+ *c = separator;
+ *(int*)(++c) = mapper[*b];
+ }
+ return result;
+ }
+ }
+ }
+
+ static class HexBinByteToString
+ {
+ static readonly string[] __HexBins = InitHexBinStrings(true);
+ static readonly string[] __HexBinLower = InitHexBinStrings(false);
+
+ public static string ToString(byte value, bool upperCase) {
+ return (upperCase ? __HexBins : __HexBinLower)[value];
+ }
+ static string[] InitHexBinStrings(bool upperCase) {
+ var s = new string[Byte.MaxValue + 1];
+ for (int i = 0; i < s.Length; i++) {
+ s[i] = ToHexBinString((byte)i, upperCase);
+ }
+ return s;
+
+ string ToHexBinString(byte value, bool upperCaseHex) {
+ var h = (upperCaseHex ? 0x41 : 0x61) - 10;
+ var a = new char[2];
+ var t = (byte)(value >> 4);
+ a[0] = (char)(t > 9 ? t + h : t + 0x30);
+ t = (byte)(value & 0x0F);
+ a[1] = (char)(t > 9 ? t + h : t + 0x30);
+ return new string(a);
+ }
+ }
+ }
+ static class HexBinByteValues
+ {
+ static readonly int[] __HexBins = InitHexBin(true);
+ static readonly int[] __HexBinLowerCase = InitHexBin(false);
+
+ unsafe static int[] InitHexBin(bool upperCase) {
+ var v = new int[Byte.MaxValue + 1];
+ var a = new char[2];
+ var h = (upperCase ? 0x41 : 0x61) - 10;
+ for (int i = 0; i <= Byte.MaxValue; i++) {
+ var t = (byte)(i >> 4);
+ a[0] = (char)(t > 9 ? t + h : t + 0x30);
+ t = (byte)(i & 0x0F);
+ a[1] = (char)(t > 9 ? t + h : t + 0x30);
+ fixed (char* p = new string(a)) {
+ v[i] = *(int*)p;
+ }
+ }
+ return v;
+ }
+ public static int[] GetHexBinMapper(bool upperCase) {
+ return upperCase ? __HexBins : __HexBinLowerCase;
+ }
+ }
+
+ static class Roman
+ {
+ internal static readonly int[] Values = { 1, 4, 5, 9, 10, 40, 50, 90, 100, 400, 500, 900, 1000, 4000, 5000, 9000, 10000, 40000 };
+ internal static readonly string[] Chars = { "I", "IV", "V", "IX", "X", "XL", "L", "XC", "C", "CD", "D", "CM", "M", "Mv", "v", "Mx", "x", "xl" };
+ }
+
+ sealed class ReverseComparer : IComparer
+ where T : IComparable
+ {
+ int IComparer.Compare(T x, T y) {
+ return y.CompareTo(x);
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/XmlHelper.cs b/pdfpatcher/App/Common/XmlHelper.cs
new file mode 100644
index 0000000000000000000000000000000000000000..11cd2bf4f58eef2c5843c44cf3f644283baa6889
--- /dev/null
+++ b/pdfpatcher/App/Common/XmlHelper.cs
@@ -0,0 +1,247 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.Xml;
+
+namespace PDFPatcher.Common
+{
+ static class XmlHelper
+ {
+ const string BooleanYes = "yes";
+ const string BooleanNo = "no";
+
+ [DebuggerStepThrough]
+ public static bool GetValue(this XmlElement element, string name, bool defaultValue) {
+ if (element == null) {
+ return defaultValue;
+ }
+ var a = element.GetAttributeNode(name);
+ return a != null ? a.Value.ToBoolean(defaultValue) : defaultValue;
+ }
+
+ /// 获取 元素名称为 的属性值,如不存在该属性,或属性不能解析为整数值,则返回 。
+ /// 需要获取属性值的元素。
+ /// 属性的名称。
+ /// 属性的默认值。
+ /// 属性的值;如不存在该属性,返回默认值。
+ [DebuggerStepThrough]
+ public static int GetValue(this XmlElement element, string name, int defaultValue) {
+ if (element == null) {
+ return defaultValue;
+ }
+ var a = element.GetAttributeNode(name);
+ return a != null ? a.Value.ToInt32(defaultValue) : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static long GetValue(this XmlElement element, string name, long defaultValue) {
+ if (element == null) {
+ return defaultValue;
+ }
+ var a = element.GetAttributeNode(name);
+ return a != null ? a.Value.ToInt64(defaultValue) : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static float GetValue(this XmlElement element, string name, float defaultValue) {
+ if (element == null) {
+ return defaultValue;
+ }
+ var a = element.GetAttributeNode(name);
+ return a != null ? a.Value.ToSingle(defaultValue) : defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static double GetValue(this XmlElement element, string name, double defaultValue) {
+ if (element == null) {
+ return defaultValue;
+ }
+ var a = element.GetAttributeNode(name);
+ if (a == null) {
+ return defaultValue;
+ }
+ return a.Value.ToDouble(defaultValue);
+ }
+ [DebuggerStepThrough]
+ public static bool GetValue(this XmlReader reader, string name, bool defaultValue) {
+ if (reader == null) {
+ return defaultValue;
+ }
+ var a = reader.GetAttribute(name);
+ return a?.ToBoolean(defaultValue) ?? defaultValue;
+ }
+ [DebuggerStepThrough]
+ public static int GetValue(this XmlReader reader, string name, int defaultValue) {
+ if (reader == null) {
+ return defaultValue;
+ }
+ var a = reader.GetAttribute(name);
+ return a?.ToInt32(defaultValue) ?? defaultValue;
+ }
+ [DebuggerStepThrough]
+ public static float GetValue(this XmlReader reader, string name, float defaultValue) {
+ if (reader == null) {
+ return defaultValue;
+ }
+ var a = reader.GetAttribute(name);
+ return a?.ToSingle(defaultValue) ?? defaultValue;
+ }
+
+ [DebuggerStepThrough]
+ public static string GetValue(this XmlElement element, string name) {
+ return element?.GetAttributeNode(name)?.Value;
+ }
+
+ [DebuggerStepThrough]
+ public static string GetValue(this XmlElement element, string name, string defaultValue) {
+ return element?.GetAttributeNode(name)?.Value ?? defaultValue;
+ }
+ [DebuggerStepThrough]
+ public static void SetValue(this XmlElement element, string name, bool value, bool defaultValue) {
+ if (element == null) { return; }
+ if (value == defaultValue) {
+ element.RemoveAttribute(name);
+ }
+ else {
+ element.SetAttribute(name, value ? BooleanYes : BooleanNo);
+ }
+ }
+
+ [DebuggerStepThrough]
+ public static void SetValue(this XmlElement element, string name, int value, int defaultValue) {
+ if (element == null) { return; }
+ if (value == defaultValue) {
+ element.RemoveAttribute(name);
+ }
+ else {
+ element.SetAttribute(name, value.ToText());
+ }
+ }
+
+ [DebuggerStepThrough]
+ public static void SetValue(this XmlElement element, string name, float value, float defaultValue) {
+ if (element == null) { return; }
+ if (value == defaultValue) {
+ element.RemoveAttribute(name);
+ }
+ else {
+ element.SetAttribute(name, value.ToText());
+ }
+ }
+
+ [DebuggerStepThrough]
+ public static void SetValue(this XmlElement element, string name, string value) {
+ if (element == null) { return; }
+ if (string.IsNullOrEmpty(value)) {
+ element.RemoveAttribute(name);
+ }
+ else {
+ element.SetAttribute(name, value);
+ }
+ }
+
+ [DebuggerStepThrough]
+ public static void SetValue(this XmlElement element, string name, string value, string defaultValue) {
+ if (element == null) { return; }
+ if (value == null || value == defaultValue) {
+ element.RemoveAttribute(name);
+ }
+ else {
+ element.SetAttribute(name, value);
+ }
+ }
+ [DebuggerStepThrough]
+ public static void WriteValue(this XmlWriter writer, string name, bool value) {
+ writer?.WriteAttributeString(name, value ? BooleanYes : BooleanNo);
+ }
+
+ [DebuggerStepThrough]
+ public static void WriteValue(this XmlWriter writer, string name, bool value, bool defaultValue) {
+ if (writer != null && value != defaultValue) {
+ writer.WriteAttributeString(name, value ? BooleanYes : BooleanNo);
+ }
+ }
+
+ [DebuggerStepThrough]
+ public static void WriteValue(this XmlWriter writer, string name, int value) {
+ writer?.WriteAttributeString(name, value.ToText());
+ }
+
+ [DebuggerStepThrough]
+ public static void WriteValue(this XmlWriter writer, string name, int value, int defaultValue) {
+ if (writer != null && value != defaultValue) {
+ writer.WriteAttributeString(name, value.ToText());
+ }
+ }
+
+ [DebuggerStepThrough]
+ public static void WriteValue(this XmlWriter writer, string name, float value) {
+ writer?.WriteAttributeString(name, value.ToText());
+ }
+
+ [DebuggerStepThrough]
+ public static void WriteValue(this XmlWriter writer, string name, string value, string defaultValue) {
+ if (writer != null && string.Equals(value, defaultValue, StringComparison.OrdinalIgnoreCase) == false) {
+ writer.WriteAttributeString(name, value);
+ }
+ }
+
+ public static XmlElement GetOrCreateElement(this XmlNode parent, string name) {
+ return parent == null
+ ? null
+ : GetElement(parent, name) ?? parent.AppendElement(name);
+ }
+ public static XmlElement GetElement(this XmlNode parent, string name) {
+ if (parent == null) {
+ return null;
+ }
+ var n = parent.FirstChild;
+ while (n != null) {
+ if (n.NodeType == XmlNodeType.Element && n.Name == name) {
+ return n as XmlElement;
+ }
+ n = n.NextSibling;
+ }
+ return null;
+ }
+ [DebuggerStepThrough]
+ public static XmlElement AppendElement(this XmlNode element, string name) {
+ if (element == null) {
+ return null;
+ }
+ var d = element.NodeType != XmlNodeType.Document ? element.OwnerDocument : element as XmlDocument;
+ var e = d.CreateElement(name);
+ element.AppendChild(e);
+ return e;
+ }
+
+ public static XmlNode[] ToXmlNodeArray(this XmlNodeList nodes) {
+ if (nodes == null) {
+ return Empty.Item;
+ }
+ var a = new XmlNode[nodes.Count];
+ var i = -1;
+ foreach (XmlNode item in nodes) {
+ a[++i] = item;
+ }
+ return a;
+ }
+ public static IList ToNodeList(this XmlNodeList nodes) where TNode : XmlNode {
+ if (nodes == null) {
+ return Empty.Item;
+ }
+ var a = new List(7);
+ foreach (var item in nodes) {
+ if (item is TNode n) {
+ a.Add(n);
+ }
+ }
+ return a;
+ }
+
+ static class Empty
+ {
+ public static readonly TNode[] Item = new TNode[0];
+ }
+ }
+}
diff --git a/pdfpatcher/App/Common/app.manifest b/pdfpatcher/App/Common/app.manifest
new file mode 100644
index 0000000000000000000000000000000000000000..7cdf28d8526d421f243a0c8be5fdbf699b21bd4c
--- /dev/null
+++ b/pdfpatcher/App/Common/app.manifest
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ true
+
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/CommonCommands.cs b/pdfpatcher/App/CommonCommands.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8f0ca6bc4382fbf421537859e005b8dbac22bdd0
--- /dev/null
+++ b/pdfpatcher/App/CommonCommands.cs
@@ -0,0 +1,26 @@
+using System;
+using System.Collections.Generic;
+using System.Text;
+using PDFPatcher.Common;
+
+namespace PDFPatcher
+{
+ static class CommonCommands
+ {
+ internal static void CreateShortcut() {
+ var p = System.IO.Path.GetDirectoryName(System.Windows.Forms.Application.ExecutablePath);
+ var s = new ShortcutFile(FileHelper.CombinePath(p, Constants.AppEngName + ".exe")) {
+ WorkingDirectory = p,
+ Description = Constants.AppName
+ };
+ var desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory);
+ s.Save(FileHelper.CombinePath(desktopPath, Constants.AppName + ".lnk"));
+
+ FormHelper.InfoBox("已在桌面创建" + Constants.AppName + "的快捷方式。");
+ }
+
+ internal static void VisitHomePage() {
+ System.Diagnostics.Process.Start(Constants.AppHomePage);
+ }
+ }
+}
diff --git a/pdfpatcher/App/Configuration.Designer.cs b/pdfpatcher/App/Configuration.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dbbda48d2e4eabead2991e066760e60f6ef70459
--- /dev/null
+++ b/pdfpatcher/App/Configuration.Designer.cs
@@ -0,0 +1,252 @@
+//------------------------------------------------------------------------------
+//
+// This code was generated by a tool.
+// Runtime Version:4.0.30319.42000
+//
+// Changes to this file may cause incorrect behavior and will be lost if
+// the code is regenerated.
+//
+//------------------------------------------------------------------------------
+
+namespace PDFPatcher {
+ using System;
+
+
+ ///
+ /// A strongly-typed resource class, for looking up localized strings, etc.
+ ///
+ // This class was auto-generated by the StronglyTypedResourceBuilder
+ // class via a tool like ResGen or Visual Studio.
+ // To add or remove a member, edit your .ResX file then rerun ResGen
+ // with the /str option, or rebuild your VS project.
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
+ internal class Configuration {
+
+ private static global::System.Resources.ResourceManager resourceMan;
+
+ private static global::System.Globalization.CultureInfo resourceCulture;
+
+ [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
+ internal Configuration() {
+ }
+
+ ///
+ /// Returns the cached ResourceManager instance used by this class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Resources.ResourceManager ResourceManager {
+ get {
+ if (object.ReferenceEquals(resourceMan, null)) {
+ global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("PDFPatcher.Configuration", typeof(Configuration).Assembly);
+ resourceMan = temp;
+ }
+ return resourceMan;
+ }
+ }
+
+ ///
+ /// Overrides the current thread's CurrentUICulture property for all
+ /// resource lookups using this strongly typed resource class.
+ ///
+ [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
+ internal static global::System.Globalization.CultureInfo Culture {
+ get {
+ return resourceCulture;
+ }
+ set {
+ resourceCulture = value;
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 书签文本.
+ ///
+ internal static string BookmarkText {
+ get {
+ return ResourceManager.GetString("BookmarkText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 自定义工具栏按钮.
+ ///
+ internal static string CustomToolbarButtons {
+ get {
+ return ResourceManager.GetString("CustomToolbarButtons", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 文档属性.
+ ///
+ internal static string DocInfo {
+ get {
+ return ResourceManager.GetString("DocInfo", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 正文文本.
+ ///
+ internal static string DocText {
+ get {
+ return ResourceManager.GetString("DocText", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 编码方式.
+ ///
+ internal static string Encodings {
+ get {
+ return ResourceManager.GetString("Encodings", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 导出图片目录.
+ ///
+ internal static string Folders {
+ get {
+ return ResourceManager.GetString("Folders", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 信息文件.
+ ///
+ internal static string InfoFiles {
+ get {
+ return ResourceManager.GetString("InfoFiles", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 减少占用内存.
+ ///
+ internal static string OptimalMemoryUsage {
+ get {
+ return ResourceManager.GetString("OptimalMemoryUsage", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 优化处理效率.
+ ///
+ internal static string OptimalSpeed {
+ get {
+ return ResourceManager.GetString("OptimalSpeed", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 处理选项.
+ ///
+ internal static string Options {
+ get {
+ return ResourceManager.GetString("Options", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 路径.
+ ///
+ internal static string Path {
+ get {
+ return ResourceManager.GetString("Path", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to PDF读取方式.
+ ///
+ internal static string PdfLoadMode {
+ get {
+ return ResourceManager.GetString("PdfLoadMode", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to PDF阅读器路径.
+ ///
+ internal static string PdfReaderPath {
+ get {
+ return ResourceManager.GetString("PdfReaderPath", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 历史文件.
+ ///
+ internal static string RecentFiles {
+ get {
+ return ResourceManager.GetString("RecentFiles", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 替换文本.
+ ///
+ internal static string ReplaceItems {
+ get {
+ return ResourceManager.GetString("ReplaceItems", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 配置文件.
+ ///
+ internal static string Root {
+ get {
+ return ResourceManager.GetString("Root", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 保存程序配置.
+ ///
+ internal static string SaveAppSettings {
+ get {
+ return ResourceManager.GetString("SaveAppSettings", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 查找文本.
+ ///
+ internal static string SearchItems {
+ get {
+ return ResourceManager.GetString("SearchItems", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 输入文件.
+ ///
+ internal static string SourceFiles {
+ get {
+ return ResourceManager.GetString("SourceFiles", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 目标文件.
+ ///
+ internal static string TargetFiles {
+ get {
+ return ResourceManager.GetString("TargetFiles", resourceCulture);
+ }
+ }
+
+ ///
+ /// Looks up a localized string similar to 版本.
+ ///
+ internal static string Version {
+ get {
+ return ResourceManager.GetString("Version", resourceCulture);
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Configuration.resx b/pdfpatcher/App/Configuration.resx
new file mode 100644
index 0000000000000000000000000000000000000000..26b31707cdd4f7da43a7c2fdcd73248fdf5e1e3b
--- /dev/null
+++ b/pdfpatcher/App/Configuration.resx
@@ -0,0 +1,183 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 书签文本
+
+
+ 自定义工具栏按钮
+
+
+ 文档属性
+
+
+ 正文文本
+
+
+ 编码方式
+
+
+ 导出图片目录
+
+
+ 信息文件
+
+
+ 减少占用内存
+
+
+ 优化处理效率
+
+
+ 处理选项
+
+
+ 路径
+
+
+ PDF读取方式
+
+
+ PDF阅读器路径
+
+
+ 历史文件
+
+
+ 替换文本
+
+
+ 配置文件
+
+
+ 保存程序配置
+
+
+ 查找文本
+
+
+ 输入文件
+
+
+ 目标文件
+
+
+ 版本
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/ConfigurationSerialization.cs b/pdfpatcher/App/ConfigurationSerialization.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cc3860499d645881d1a26419842e2068a9821a3e
--- /dev/null
+++ b/pdfpatcher/App/ConfigurationSerialization.cs
@@ -0,0 +1,56 @@
+using System;
+using System.Xml.Serialization;
+using PowerJson;
+
+namespace PDFPatcher
+{
+ [XmlRoot("处理选项")]
+ public class ConfigurationSerialization
+ {
+ [XmlAttribute("检查更新时间")]
+ public DateTime CheckUpdateDate { get; set; }
+ [XmlAttribute("检查更新间隔")]
+ public int CheckUpdateInterval { get; set; } = 14;
+
+ [XmlAttribute("保存程序设置")]
+ public bool SaveAppSettings { get; set; }
+
+ [XmlAttribute("文档加载模式")]
+ public string PdfLoadMode { get; set; }
+
+ [XmlElement("编码设置")]
+ public EncodingOptions Encodings { get; set; }
+ ///获取导出设置。
+ [XmlElement("信息文件导出设置")]
+ public ExporterOptions ExporterOptions { get; set; }
+ ///获取导入设置。
+ [XmlElement("信息文件导入设置")]
+ public ImporterOptions ImporterOptions { get; set; }
+ ///获取生成文档的设置。
+ [XmlElement("PDF文件处理设置")]
+ public MergerOptions MergerOptions { get; set; }
+ [XmlElement("PDF文档设置")]
+ public PatcherOptions PatcherOptions { get; set; }
+ [XmlElement("PDF编辑器设置")]
+ public PatcherOptions EditorOptions { get; set; }
+ [XmlElement("自动生成书签设置")]
+ public AutoBookmarkOptions AutoBookmarkOptions { get; set; }
+ [XmlElement("导出图像设置")]
+ public ImageExtracterOptions ImageExporterOptions { get; set; }
+ [XmlElement("转为图片设置")]
+ public MuPdfSharp.ImageRendererOptions ImageRendererOptions { get; set; }
+ [XmlElement("提取页面设置")]
+ public ExtractPageOptions ExtractPageOptions { get; set; }
+ [XmlElement("文本识别设置")]
+ public OcrOptions OcrOptions { get; set; }
+ [XmlElement("工具栏设置")]
+ public ToolbarOptions ToolbarOptions { get; set; }
+ [XmlElement("窗口设置")]
+ public WindowStatus WindowStatus { get; set; }
+
+ [JsonField("最近使用的文档")]
+ [JsonInclude]
+ [JsonSerializable]
+ internal AppContext.RecentItems Recent { get; set; }
+ }
+}
diff --git a/pdfpatcher/App/Constants.cs b/pdfpatcher/App/Constants.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8c9b00c8706d9a7f5b833adc59e0b1a7db5aaf70
--- /dev/null
+++ b/pdfpatcher/App/Constants.cs
@@ -0,0 +1,515 @@
+using System;
+using System.Collections.Generic;
+using iTextSharp.text.pdf;
+using E = System.Text.Encoding;
+
+namespace PDFPatcher
+{
+ internal enum Function
+ {
+ FrontPage, InfoFileOptions, InfoExchanger, ExtractPages, ExtractImages, RenderPages, EditorOptions, Patcher, PatcherOptions, Merger, MergerOptions, About, Editor, Options, BookmarkGenerator, Ocr, Inspector, Rename, Log, Default, CustomizeToolbar
+ }
+
+ internal static class Constants
+ {
+ internal const string AppName = "PDF 补丁丁";
+ internal const string AppEngName = "PDFPatcher";
+ internal const string AppHomePage = "http://pdfpatcher.cnblogs.com";
+ internal const string AppRepository = "https://github.com/wmjordan/pdfpatcher";
+ internal const string AppRepository2 = "https://gitee.com/wmjordan/pdfpatcher";
+ internal const string AppUpdateFile = "http://files.cnblogs.com/pdfpatcher/pdfpatcher.update.xml";
+
+ ///
+ /// 信息文件根元素。
+ ///
+ internal const string PdfInfo = "PDF信息";
+ internal const string InfoDocVersion = "0.3.3";
+ internal const string ContentPrefix = "pdf";
+ internal const string ContentNamespace = "pdf:ContentXml";
+
+ internal static class FileExtensions
+ {
+ internal const string Json = ".json";
+ internal const string JsonFilter = "程序配置文件 (*.json)|*.json";
+ internal const string Pdf = ".pdf";
+ internal const string PdfFilter = "PDF 文件 (*.pdf)|*.pdf";
+ internal const string Txt = ".txt";
+ internal const string TxtFilter = "简易文本书签文件 (*.txt)|*.txt";
+ internal const string Xml = ".xml";
+ internal const string XmlFilter = "PDF 信息文件 (*.xml)|*.xml";
+ internal const string PdfOrXmlFilter = "PDF 文件或信息文件 (*.pdf, *.xml)|*.pdf;*.xml";
+ internal const string XmlOrTxtFilter = "书签文件 (*.xml, *.txt)|*.xml;*.txt";
+ internal const string AllEditableFilter = "所有包含 PDF 信息的文件(*.pdf,*.xml,*.txt)|*.pdf;*.xml;*.txt|" + PdfFilter + "|" + XmlFilter + "|" + TxtFilter;
+ internal const string AllFilter = "所有文件|*.*";
+ internal const string ImageFilter = "图片文件 (*.jpg, *.jpeg, *.tiff, *.tif, *.png, *.gif)|*.jpg;*.jpeg;*.tiff;*.tif;*.png;*.gif";
+ internal const string Tif = ".tif";
+ internal const string Tiff = ".tiff";
+ internal const string Jpg = ".jpg";
+ internal const string Jpeg = ".jpeg";
+ internal const string Png = ".png";
+ internal const string Gif = ".gif";
+ internal const string Jp2 = ".jp2";
+ internal const string Bmp = ".bmp";
+ internal const string Dat = ".dat";
+ internal const string Tmp = ".tmp";
+ internal const string Ttf = ".ttf";
+ internal const string Ttc = ".ttc";
+ internal const string Otf = ".otf";
+ internal readonly static string[] AllBookmarkExtension = { ".xml", ".txt" };
+ internal readonly static string[] PdfAndAllBookmarkExtension = { ".pdf", ".xml", ".txt" };
+ internal readonly static string[] AllSupportedImageExtension = { Tif, Jpg, Png, Gif, Tiff, Jpeg, Bmp, Jp2 };
+ }
+
+ #region 功能名称
+ static class Functions
+ {
+ internal const string FrontPage = "FrontPage";
+ internal const string Patcher = "Patcher";
+ internal const string Merger = "Merger";
+ internal const string ImageExtractor = "ImageExtractor";
+ internal const string PageExtractor = "PageExtractor";
+ internal const string PageRenderer = "PageRenderer";
+ internal const string BookmarkEditor = "BookmarkEditor";
+ internal const string BookmarkGenerator = "BookmarkGenerator";
+ internal const string Ocr = "Ocr";
+ internal const string Inspector = "Inspector";
+ internal const string Log = "Log";
+ internal const string About = "About";
+ }
+ #endregion
+
+ #region PDF 对象类型
+ internal static class ObjectTypes
+ {
+ internal static readonly string[] Names = { "字典", "名称", "数值", "文本", "数组", "布尔", "引用" };
+ internal static readonly int[] IDs = { PdfObject.DICTIONARY, PdfObject.NAME, PdfObject.NUMBER, PdfObject.STRING, PdfObject.ARRAY, PdfObject.BOOLEAN, PdfObject.INDIRECT };
+ }
+ #endregion
+
+ #region 文件名替代符
+ internal static class FileNameMacros
+ {
+ internal const string FileName = "<源文件名>";
+ internal const string FolderName = "<源目录名>";
+ internal const string PathName = "<源目录路径>";
+ internal const string TitleProperty = "<" + Info.Title + ">";
+ internal const string AuthorProperty = "<" + Info.Author + ">";
+ internal const string SubjectProperty = "<" + Info.Subject + ">";
+ internal const string KeywordsProperty = "<" + Info.Keywords + ">";
+ internal const string PageCount = "<页数>";
+ }
+ #endregion
+
+ #region 度量单位
+ internal static class Units
+ {
+ internal const string ThisName = "度量单位";
+ internal const string Unit = "单位";
+ internal const string Point = "点";
+ internal const string CM = "厘米";
+ internal const string MM = "毫米";
+ internal const string Inch = "英寸";
+ internal const float CmToPoint = 72f / 2.54f;
+ internal const float MmToPoint = 7.2f / 2.54f;
+ internal const float DefaultDpi = 72f;
+ internal static readonly string[] Names = { CM, MM, Inch, Point };
+ internal static readonly float[] Factors = { CmToPoint, MmToPoint, DefaultDpi, 1 };
+ }
+ #endregion
+
+ #region 对齐方式
+ internal static class Alignments
+ {
+ internal static readonly string[] HorizontalAlignments = { "左对齐", "水平居中", "右对齐" };
+ internal static readonly string[] VerticalAlignments = { "置顶", "垂直居中", "置底" };
+ }
+ #endregion
+
+ #region 方位
+ internal static class Coordinates
+ {
+ internal const string Left = "左";
+ internal const string Right = "右";
+ internal const string Top = "上";
+ internal const string Bottom = "下";
+ internal const string Width = "宽";
+ internal const string Height = "高";
+ internal const string Direction = "方向";
+ internal const string Horizontal = "横向";
+ internal const string Vertical = "纵向";
+ internal const string ScaleFactor = "比例";
+ internal const string Unchanged = "保持不变";
+ }
+ #endregion
+
+ #region 编码
+ internal static class Encoding
+ {
+ internal const string SystemDefault = "系统默认";
+ internal const string Automatic = "自动选择";
+ internal static readonly string[] EncodingNames = { Automatic,
+ SystemDefault,
+ "UTF-16 Big Endian",
+ "UTF-16 Little Endian",
+ "UTF-8",
+ "GB18030",
+ "BIG5" };
+ internal static readonly E[] Encodings = { null,
+ E.Default,
+ E.BigEndianUnicode,
+ E.Unicode,
+ E.UTF8,
+ E.GetEncoding ("gb18030"),
+ E.GetEncoding ("big5") };
+ }
+ #endregion
+
+ #region 文档信息
+ internal static class Info
+ {
+ internal const string ThisName = "文档信息";
+
+ internal const string ProductName = "程序名称";
+ internal const string ProductVersion = "程序版本";
+ internal const string ExportDate = "导出时间";
+ internal const string DocumentName = "PDF文件名";
+ internal const string DocumentPath = "PDF文件位置";
+ internal const string PageNumber = "页数";
+ internal const string Title = "标题";
+ internal const string Author = "作者";
+ internal const string Subject = "主题";
+ internal const string Keywords = "关键字";
+ internal const string Creator = "创建程序";
+ internal const string Producer = "处理程序";
+ internal const string CreationDate = "创建日期";
+ internal const string ModDate = "最近修改日期";
+ internal const string MetaData = "XML元数据";
+ }
+ internal const string Version = "PDF版本";
+ internal const string Catalog = "文档编录";
+ internal const string Body = "正文内容";
+ internal const string DocumentBookmark = "文档书签";
+ #endregion
+
+ #region 阅读器设定
+ internal const string PageLayout = "页面布局";
+ internal static class PageLayoutType
+ {
+ internal static readonly string[] Names = { "保持不变",
+ "单页连续", "双页连续", "双页连续首页独置",
+ "单页", "双页", "双页首页独置" };
+ internal static readonly PdfName[] PdfNames = { PdfName.NONE,
+ PdfName.ONECOLUMN, PdfName.TWOCOLUMNLEFT, PdfName.TWOCOLUMNRIGHT,
+ PdfName.SINGLEPAGE, PdfName.TWOPAGELEFT, PdfName.TWOPAGERIGHT };
+ }
+ internal const string PageMode = "初始模式";
+ internal static class PageModes
+ {
+ internal static readonly string[] Names = { "保持不变",
+ "不显示边栏", "显示文档书签", "显示页面缩略图",
+ "全屏显示", "显示可选内容组", "显示附件栏" };
+ internal static readonly PdfName[] PdfNames = { PdfName.NONE,
+ PdfName.USENONE, PdfName.USEOUTLINES, PdfName.USETHUMBS,
+ PdfName.FULLSCREEN, PdfName.USEOC, PdfName.USEATTACHMENTS };
+ }
+ internal const string ViewerPreferences = "阅读器设定";
+ internal static class ViewerPreferencesType
+ {
+ internal static readonly string[] Names = { "隐藏菜单", "隐藏工具栏",
+ "只显示文档内容", "窗口适合文档首页",
+ "窗口居中", "显示文档标题" };
+ internal static readonly PdfName[] PdfNames = { PdfName.HIDEMENUBAR, PdfName.HIDETOOLBAR,
+ PdfName.HIDEWINDOWUI, PdfName.FITWINDOW,
+ PdfName.CENTERWINDOW, PdfName.DISPLAYDOCTITLE };
+ internal const string Direction = "阅读方向";
+ internal static class DirectionType
+ {
+ internal static readonly string[] Names = { "保持不变", "从左到右", "从右到左" };
+ internal static readonly PdfName[] PdfNames = { PdfName.NONE, PdfName.L2R, PdfName.R2L };
+ }
+ }
+ #endregion
+
+ #region 页码样式
+ internal const string PageLabels = "页码样式";
+ internal static class PageLabelStyles
+ {
+ internal static readonly string[] Names = { "数字", "大写罗马数字", "小写罗马数字", "大写英文字母", "小写英文字母", "无" };
+ internal static readonly char[] PdfValues = { 'D', 'R', 'r', 'A', 'a', '-' };
+ internal static readonly char[] SimpleInfoIdentifiers = { '0', 'I', 'i', 'A', 'a', '-' };
+ internal static readonly int[] Values = {
+ PdfPageLabels.DECIMAL_ARABIC_NUMERALS,
+ PdfPageLabels.UPPERCASE_ROMAN_NUMERALS,
+ PdfPageLabels.LOWERCASE_ROMAN_NUMERALS,
+ PdfPageLabels.UPPERCASE_LETTERS,
+ PdfPageLabels.LOWERCASE_LETTERS,
+ PdfPageLabels.EMPTY,
+ };
+ }
+ internal static class PageLabelsAttributes
+ {
+ internal const string PageNumber = "实际页码";
+ internal const string StartPage = "起始页码";
+ internal const string Prefix = "页码前缀";
+ internal const string Style = "样式";
+ }
+ #endregion
+
+ #region 页面内容
+ internal static class Content
+ {
+ internal const string Page = "页面";
+ internal const string PageNumber = "页码";
+ internal const string ResourceID = "资源编号";
+ internal const string RefType = "引用对象类型";
+ internal const string Texts = "文本内容";
+ internal const string Operators = "命令";
+ internal const string Operands = "参数";
+ internal const string Name = "名称";
+ internal const string Item = "项目";
+ internal const string Path = "路径";
+ internal const string Type = "类型";
+ internal const string Length = "长度";
+ internal const string Raw = "原始内容";
+ internal const string Value = "值";
+ internal static class PageSettings
+ {
+ internal const string ThisName = "页面设置";
+ internal const string MediaBox = "页面边框";
+ internal const string CropBox = "截取边框";
+ internal const string TrimBox = "裁剪边框";
+ internal const string ArtBox = "内容边框";
+ internal const string BleedBox = "出血边框";
+ internal const string Rotation = "旋转角度";
+ }
+ internal static class OperandNames
+ {
+ internal const string Matrix = "矩阵";
+ internal const string ResourceName = "资源名称";
+ internal const string Size = "尺寸";
+ internal const string Text = "文本";
+ }
+ internal static class RotationDirections
+ {
+ internal const string ThisName = PageSettings.Rotation;
+ internal const string Zero = "保持不变";
+ internal const string Right = "顺时针90度";
+ internal const string HalfClock = "180度";
+ internal const string Left = "逆时针90度";
+ internal static readonly string[] Names = { Zero, Right, HalfClock, Left };
+ internal static readonly int[] Values = { 0, 90, 180, 270 };
+ }
+ }
+ #endregion
+
+ #region 页码范围
+ internal const string PageRange = "页码范围";
+ internal static class PageFilterTypes
+ {
+ internal const string ThisName = "页码筛选";
+ internal const string AllPages = "所有页";
+ internal static readonly string[] Names = { AllPages, "单数页", "双数页" };
+ internal static readonly int[] Values = { -1, 1, 0 };
+ }
+ #endregion
+
+ #region 目标
+ internal const string NamedDestination = "命名位置";
+ internal static class DestinationAttributes
+ {
+ internal const string Page = "页码";
+ internal const string FirstPageNumber = "首页页码";
+ internal const string Action = "动作";
+ internal const string NewWindow = "新窗口";
+ internal const string Path = "路径";
+ internal const string Name = "名称";
+ internal const string Named = "命名位置";
+ internal const string NamedN = "PDF名称";
+ internal const string View = "显示方式";
+ internal const string ScriptContent = "脚本内容";
+ internal static class ViewType
+ {
+ internal const string XYZ = "坐标缩放";
+ internal const string Fit = "适合页面";
+ internal const string FitH = "适合页宽";
+ internal const string FitV = "适合页高";
+ internal const string FitB = "适合窗口";
+ internal const string FitBH = "适合窗口宽度";
+ internal const string FitBV = "适合窗口高度";
+ internal const string FitR = "适合区域";
+ internal static readonly string[] Names = { XYZ, Fit, FitH, FitV, FitB, FitBH, FitBV, FitR };
+ internal static readonly PdfName[] PdfNames = { PdfName.XYZ, PdfName.FIT, PdfName.FITH, PdfName.FITV, PdfName.FITB, PdfName.FITBH, PdfName.FITBV, PdfName.FITR };
+ }
+ }
+ internal static class ActionType
+ {
+ internal const string Goto = "转到页面";
+ internal const string GotoR = "打开外部PDF文档";
+ internal const string Launch = "启动程序";
+ internal const string Uri = "打开网址";
+ internal const string Javascript = "执行脚本";
+ internal static readonly string[] Names = { Goto, GotoR, Launch, Uri, Javascript };
+ internal static readonly PdfName[] PdfNames = { PdfName.GOTO, PdfName.GOTOR, PdfName.LAUNCH, PdfName.URI, PdfName.JAVASCRIPT };
+ }
+ #endregion
+
+ #region 书签
+ internal const string Bookmark = "书签";
+ internal static class BookmarkAttributes
+ {
+ internal const string Title = "文本";
+ internal const string Open = "默认打开";
+ internal const string Style = "样式";
+ internal static class StyleType
+ {
+ internal const string Normal = "常规";
+ internal const string Bold = "粗体";
+ internal const string BoldItalic = "粗斜体";
+ internal const string Italic = "斜体";
+ internal static readonly string[] Names = { Normal, Italic, Bold, BoldItalic };
+ }
+ }
+ internal const string Color = "颜色";
+ internal static class Colors
+ {
+ internal const string Red = "红";
+ internal const string Green = "绿";
+ internal const string Blue = "蓝";
+ internal const string Gray = "灰度";
+ internal const string Transparent = "透明";
+ internal const string Cyan = "青";
+ internal const string Magenta = "紫";
+ internal const string Yellow = "黄";
+ internal const string Black = "黑";
+ }
+ internal static class Boolean
+ {
+ internal const string True = "是";
+ internal const string False = "否";
+ }
+ #endregion
+
+ #region 页面链接
+ internal const string PageLink = "页面链接";
+ internal static class PageLinkAttributes
+ {
+ internal const string Link = "链接";
+ internal const string LinkAction = "链接动作";
+ internal const string PageNumber = "页码";
+ internal const string Border = "边框";
+ internal const string Style = "点击效果";
+ internal const string QuadPoints = "四边形坐标";
+ internal const string Contents = "文本";
+ }
+ #endregion
+
+ #region 光学字符识别
+ internal static class Ocr
+ {
+ internal const int NoLanguage = 0;
+ internal const int SimplifiedChineseLangID = 2052;
+ internal const int TraditionalChineseLangID = 1028;
+ internal const int JapaneseLangID = 1041;
+ internal const int KoreanLangID = 1042;
+ internal const int EnglishLangID = 1033;
+
+ internal const int DanishLangID = 1030;
+ internal const int DutchLangID = 1043;
+ internal const int FinnishLangID = 1035;
+ internal const int FrenchLangID = 1036;
+ internal const int GermanLangID = 1031;
+ internal const int ItalianLangID = 1040;
+ internal const int NorskLangID = 1044;
+ internal const int PortugueseLangID = 1046;
+ internal const int SpanishLangID = 3082;
+ internal const int SwedishLangID = 1053;
+ internal const int CzechLangID = 1029;
+ internal const int PolishLangID = 1045;
+ internal const int HungarianLangID = 1038;
+ internal const int GreekLangID = 1032;
+ internal const int RussianLangID = 1049;
+ internal const int TurkishLangID = 1055;
+
+ internal static int[] LangIDs = { SimplifiedChineseLangID, TraditionalChineseLangID, EnglishLangID, JapaneseLangID, KoreanLangID, DanishLangID, DutchLangID, FinnishLangID, FrenchLangID, GermanLangID, ItalianLangID, NorskLangID, PortugueseLangID, SpanishLangID, SwedishLangID, CzechLangID, PolishLangID, HungarianLangID, GreekLangID, RussianLangID, TurkishLangID };
+ internal static int[] OcrLangIDs = { SimplifiedChineseLangID, TraditionalChineseLangID, 9, 17, 18, 6, 19, 11, 12, 7, 16, 20, 22, 10, 29, 5, 21, 14, 8, 25, 31 };
+ internal static string[] LangNames = { "简体中文", "繁体中文", "英文", "日文", "韩文", "丹麦文", "荷兰文", "芬兰文", "法文", "德文", "意大利文", "挪威文", "葡萄牙文", "西班牙文", "瑞典文", "捷克文", "波兰文", "匈牙利文", "希腊文", "俄文", "土耳其文" };
+ internal const string Result = "识别结果";
+ internal const string Text = "文本";
+ internal const string Content = "内容";
+ internal const string Image = "图片";
+ }
+ #endregion
+
+ #region 字体属性
+ internal static class Font
+ {
+ internal const string ThisName = "字体";
+ internal const string DocumentFont = "文档字体";
+ internal const string ID = "编号";
+ internal const string Name = "名称";
+ internal const string Size = "文本尺寸";
+ }
+ internal static class FontOccurrence
+ {
+ internal const string Count = "出现次数";
+ internal const string FirstText = "首次出现文本";
+ internal const string FirstPage = "首次出现页码";
+ }
+ #endregion
+
+ #region 导出为图片
+ internal static class ColorSpaces
+ {
+ internal const string Rgb = "DeviceRGB";
+ internal const string Bgr = "DeviceBGR";
+ internal const string Cmyk = "DeviceCMYK";
+ internal const string Gray = "DeviceGray";
+ internal static string[] Names = { Rgb, Gray };
+ }
+ #endregion
+
+ #region 超星命名规则
+ internal static class CajNaming
+ {
+ internal const string Cover = "cov";
+ internal const string TitlePage = "bok";
+ internal const string CopyrightPage = "leg";
+ internal const string Foreword = "fow";
+ internal const string Contents = "!";
+ }
+ #endregion
+
+ internal static class AutoBookmark
+ {
+ internal const string ThisName = "自动书签";
+ internal const string Group = "条件集合";
+ internal const string Name = "名称";
+ internal const string Description = "说明";
+ internal const string IsInclusive = "正向过滤";
+
+ }
+
+ internal static class Chinese {
+ public const string Simplified = "皑蔼碍爱翱袄奥坝罢摆败颁办绊帮绑镑谤剥饱宝报鲍辈贝钡狈备惫绷笔毕毙闭边编贬变辩辫鳖瘪濒滨宾摈饼拨钵铂驳卜补参蚕残惭惨灿苍舱仓沧厕侧册测层诧搀掺蝉馋谗缠铲产阐颤场尝长偿肠厂畅钞车彻尘陈衬撑称惩诚骋痴迟驰耻齿炽冲虫宠畴踌筹绸丑橱厨锄雏础储触处传疮闯创锤纯绰辞词赐聪葱囱从丛凑窜错达带贷担单郸掸胆惮诞弹当挡党荡档捣岛祷导盗灯邓敌涤递缔点垫电淀钓调迭谍叠钉顶锭订东动栋冻斗犊独读赌镀锻断缎兑队对吨顿钝夺鹅额讹恶饿儿尔饵贰发罚阀珐矾钒烦范贩饭访纺飞废费纷坟奋愤粪丰枫锋风疯冯缝讽凤肤辐抚辅赋复负讣妇缚该钙盖干赶秆赣冈刚钢纲岗皋镐搁鸽阁铬个给龚宫巩贡钩沟构购够蛊顾剐关观馆惯贯广规硅归龟闺轨诡柜贵刽辊滚锅国过骇韩汉阂鹤贺横轰鸿红后壶护沪户哗华画划话怀坏欢环还缓换唤痪焕涣黄谎挥辉毁贿秽会烩汇讳诲绘荤浑伙获货祸击机积饥讥鸡绩缉极辑级挤几蓟剂济计记际继纪夹荚颊贾钾价驾歼监坚笺间艰缄茧检碱硷拣捡简俭减荐槛鉴践贱见键舰剑饯渐溅涧浆蒋桨奖讲酱胶浇骄娇搅铰矫侥脚饺缴绞轿较秸阶节茎惊经颈静镜径痉竞净纠厩旧驹举据锯惧剧鹃绢杰洁结诫届紧锦仅谨进晋烬尽劲荆觉决诀绝钧军骏开凯颗壳课垦恳抠库裤夸块侩宽矿旷况亏岿窥馈溃扩阔蜡腊莱来赖蓝栏拦篮阑兰澜谰揽览懒缆烂滥捞劳涝乐镭垒类泪篱离里鲤礼丽厉励砾历沥隶俩联莲连镰怜涟帘敛脸链恋炼练粮凉两辆谅疗辽镣猎临邻鳞凛赁龄铃凌灵岭领馏刘龙聋咙笼垄拢陇楼娄搂篓芦卢颅庐炉掳卤虏鲁赂禄录陆驴吕铝侣屡缕虑滤绿峦挛孪滦乱抡轮伦仑沦纶论萝罗逻锣箩骡骆络妈玛码蚂马骂吗买麦卖迈脉瞒馒蛮满谩猫锚铆贸么霉没镁门闷们锰梦谜弥觅绵缅庙灭悯闽鸣铭谬谋亩钠纳难挠脑恼闹馁腻撵捻酿鸟聂啮镊镍柠狞宁拧泞钮纽脓浓农疟诺欧鸥殴呕沤盘庞国爱赔喷鹏骗飘频贫苹凭评泼颇扑铺朴谱脐齐骑岂启气弃讫牵扦钎铅迁签谦钱钳潜浅谴堑枪呛墙蔷强抢锹桥乔侨翘窍窃钦亲轻氢倾顷请庆琼穷趋区躯驱龋颧权劝却鹊让饶扰绕热韧认纫荣绒软锐闰润洒萨鳃赛伞丧骚扫涩杀纱筛晒闪陕赡缮伤赏烧绍赊摄慑设绅审婶肾渗声绳胜圣师狮湿诗尸时蚀实识驶势释饰视试寿兽枢输书赎属术树竖数帅双谁税顺说硕烁丝饲耸怂颂讼诵擞苏诉肃虽绥岁孙损笋缩琐锁獭挞抬摊贪瘫滩坛谭谈叹汤烫涛绦腾誊锑题体屉条贴铁厅听烃铜统头图涂团颓蜕脱鸵驮驼椭洼袜弯湾顽万网韦违围为潍维苇伟伪纬谓卫温闻纹稳问瓮挝蜗涡窝呜钨乌诬无芜吴坞雾务误锡牺袭习铣戏细虾辖峡侠狭厦锨鲜纤咸贤衔闲显险现献县馅羡宪线厢镶乡详响项萧销晓啸蝎协挟携胁谐写泻谢锌衅兴汹锈绣虚嘘须许绪续轩悬选癣绚学勋询寻驯训讯逊压鸦鸭哑亚讶阉烟盐严颜阎艳厌砚彦谚验鸯杨扬疡阳痒养样瑶摇尧遥窑谣药爷页业叶医铱颐遗仪彝蚁艺亿忆义诣议谊译异绎荫阴银饮樱婴鹰应缨莹萤营荧蝇颖哟拥佣痈踊咏涌优忧邮铀犹游诱舆鱼渔娱与屿语吁御狱誉预驭鸳渊辕园员圆缘远愿约跃钥岳粤悦阅云郧匀陨运蕴酝晕韵杂灾载攒暂赞赃脏凿枣灶责择则泽贼赠扎札轧铡闸诈斋债毡盏斩辗崭栈战绽张涨帐账胀赵蛰辙锗这贞针侦诊镇阵挣睁狰帧郑证织职执纸挚掷帜质钟终种肿众诌轴皱昼骤猪诸诛烛瞩嘱贮铸筑驻专砖转赚桩庄装妆壮状锥赘坠缀谆浊兹资渍踪综总纵邹诅组钻致钟么为只凶准启板里雳余链泄";
+ public const string Traditional = "皚藹礙愛翺襖奧壩罷擺敗頒辦絆幫綁鎊謗剝飽寶報鮑輩貝鋇狽備憊繃筆畢斃閉邊編貶變辯辮鼈癟瀕濱賓擯餅撥缽鉑駁蔔補參蠶殘慚慘燦蒼艙倉滄廁側冊測層詫攙摻蟬饞讒纏鏟産闡顫場嘗長償腸廠暢鈔車徹塵陳襯撐稱懲誠騁癡遲馳恥齒熾沖蟲寵疇躊籌綢醜櫥廚鋤雛礎儲觸處傳瘡闖創錘純綽辭詞賜聰蔥囪從叢湊竄錯達帶貸擔單鄲撣膽憚誕彈當擋黨蕩檔搗島禱導盜燈鄧敵滌遞締點墊電澱釣調叠諜疊釘頂錠訂東動棟凍鬥犢獨讀賭鍍鍛斷緞兌隊對噸頓鈍奪鵝額訛惡餓兒爾餌貳發罰閥琺礬釩煩範販飯訪紡飛廢費紛墳奮憤糞豐楓鋒風瘋馮縫諷鳳膚輻撫輔賦複負訃婦縛該鈣蓋幹趕稈贛岡剛鋼綱崗臯鎬擱鴿閣鉻個給龔宮鞏貢鈎溝構購夠蠱顧剮關觀館慣貫廣規矽歸龜閨軌詭櫃貴劊輥滾鍋國過駭韓漢閡鶴賀橫轟鴻紅後壺護滬戶嘩華畫劃話懷壞歡環還緩換喚瘓煥渙黃謊揮輝毀賄穢會燴彙諱誨繪葷渾夥獲貨禍擊機積饑譏雞績緝極輯級擠幾薊劑濟計記際繼紀夾莢頰賈鉀價駕殲監堅箋間艱緘繭檢堿鹼揀撿簡儉減薦檻鑒踐賤見鍵艦劍餞漸濺澗漿蔣槳獎講醬膠澆驕嬌攪鉸矯僥腳餃繳絞轎較稭階節莖驚經頸靜鏡徑痙競淨糾廄舊駒舉據鋸懼劇鵑絹傑潔結誡屆緊錦僅謹進晉燼盡勁荊覺決訣絕鈞軍駿開凱顆殼課墾懇摳庫褲誇塊儈寬礦曠況虧巋窺饋潰擴闊蠟臘萊來賴藍欄攔籃闌蘭瀾讕攬覽懶纜爛濫撈勞澇樂鐳壘類淚籬離裏鯉禮麗厲勵礫曆瀝隸倆聯蓮連鐮憐漣簾斂臉鏈戀煉練糧涼兩輛諒療遼鐐獵臨鄰鱗凜賃齡鈴淩靈嶺領餾劉龍聾嚨籠壟攏隴樓婁摟簍蘆盧顱廬爐擄鹵虜魯賂祿錄陸驢呂鋁侶屢縷慮濾綠巒攣孿灤亂掄輪倫侖淪綸論蘿羅邏鑼籮騾駱絡媽瑪碼螞馬罵嗎買麥賣邁脈瞞饅蠻滿謾貓錨鉚貿麽黴沒鎂門悶們錳夢謎彌覓綿緬廟滅憫閩鳴銘謬謀畝鈉納難撓腦惱鬧餒膩攆撚釀鳥聶齧鑷鎳檸獰甯擰濘鈕紐膿濃農瘧諾歐鷗毆嘔漚盤龐國愛賠噴鵬騙飄頻貧蘋憑評潑頗撲鋪樸譜臍齊騎豈啓氣棄訖牽扡釺鉛遷簽謙錢鉗潛淺譴塹槍嗆牆薔強搶鍬橋喬僑翹竅竊欽親輕氫傾頃請慶瓊窮趨區軀驅齲顴權勸卻鵲讓饒擾繞熱韌認紉榮絨軟銳閏潤灑薩鰓賽傘喪騷掃澀殺紗篩曬閃陝贍繕傷賞燒紹賒攝懾設紳審嬸腎滲聲繩勝聖師獅濕詩屍時蝕實識駛勢釋飾視試壽獸樞輸書贖屬術樹豎數帥雙誰稅順說碩爍絲飼聳慫頌訟誦擻蘇訴肅雖綏歲孫損筍縮瑣鎖獺撻擡攤貪癱灘壇譚談歎湯燙濤縧騰謄銻題體屜條貼鐵廳聽烴銅統頭圖塗團頹蛻脫鴕馱駝橢窪襪彎灣頑萬網韋違圍爲濰維葦偉僞緯謂衛溫聞紋穩問甕撾蝸渦窩嗚鎢烏誣無蕪吳塢霧務誤錫犧襲習銑戲細蝦轄峽俠狹廈鍁鮮纖鹹賢銜閑顯險現獻縣餡羨憲線廂鑲鄉詳響項蕭銷曉嘯蠍協挾攜脅諧寫瀉謝鋅釁興洶鏽繡虛噓須許緒續軒懸選癬絢學勳詢尋馴訓訊遜壓鴉鴨啞亞訝閹煙鹽嚴顔閻豔厭硯彥諺驗鴦楊揚瘍陽癢養樣瑤搖堯遙窯謠藥爺頁業葉醫銥頤遺儀彜蟻藝億憶義詣議誼譯異繹蔭陰銀飲櫻嬰鷹應纓瑩螢營熒蠅穎喲擁傭癰踴詠湧優憂郵鈾猶遊誘輿魚漁娛與嶼語籲禦獄譽預馭鴛淵轅園員圓緣遠願約躍鑰嶽粵悅閱雲鄖勻隕運蘊醞暈韻雜災載攢暫贊贓髒鑿棗竈責擇則澤賊贈紮劄軋鍘閘詐齋債氈盞斬輾嶄棧戰綻張漲帳賬脹趙蟄轍鍺這貞針偵診鎮陣掙睜猙幀鄭證織職執紙摯擲幟質鍾終種腫衆謅軸皺晝驟豬諸誅燭矚囑貯鑄築駐專磚轉賺樁莊裝妝壯狀錐贅墜綴諄濁茲資漬蹤綜總縱鄒詛組鑽緻鐘麼為隻兇準啟闆裡靂餘鍊洩";
+ }
+ }
+
+ internal static class Messages
+ {
+ internal const string Welcome = "PDF 补丁丁——解除 PDF 文档的烦恼";
+ internal const string SourceFileNotFound = "源 PDF 文件不存在,请先指定有效的源 PDF 文件。";
+ internal const string InfoDocNotFound = "信息文件不存在,请先指定有效的信息文件。";
+ internal const string TargetFileNotSpecified = "请指定输出 PDF 文件的路径。";
+ internal const string InfoDocNotSpecified = "请指定输出信息文件的路径。";
+ internal const string SourceFileNameInvalid = "源 PDF 文件名无效。";
+ internal const string TargetFileNameInvalid = "输出 PDF 文件名无效。";
+ internal const string InfoFileNameInvalid = "信息文件的文件名无效。";
+ internal const string SourceFileEqualsTargetFile = "输入 PDF 文件和输出 PDF 文件的文件名不能相同。";
+ internal const string PasswordInvalid = "输入的密码错误,无法打开 PDF 文档。";
+ internal const string UserRightRequired = "此 PDF 文件的作者设置了修改文件的权限控制。\n如果您继续操作,您必须得到创建者对该文档进行修改的授权。\n如果您不能保证自己有权修改此文档,请按“取消”键退出,否则您需要承担修改此文档带来的一切责任。\n\n按住 Ctrl 键点击“确定”按钮,在本次使用过程中将不再提示权限问题。";
+ internal const string PageRanges = "在此输入需要处理的页码范围。\n如:“1-100”表示处理第1~100页。\n如有多个页码范围,可用空格、分号或逗号分开。\n如:“1-10;12;14-20”表示处理1~10、12和14~20页。";
+ internal const string ReversePageRanges = "此外还可以输入逆序页码,如“100-1”表示从第100页开始倒序处理至第1页。";
+ internal const string ModiNotAvailable = "本机尚未安装微软文本识别组件(MODI),无法使用识别文本功能。";
+ }
+}
diff --git a/pdfpatcher/App/Functions/AboutControl.Designer.cs b/pdfpatcher/App/Functions/AboutControl.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6a61cb1ba10d1d1009788a20059ae8dbb2064000
--- /dev/null
+++ b/pdfpatcher/App/Functions/AboutControl.Designer.cs
@@ -0,0 +1,63 @@
+namespace PDFPatcher
+{
+ partial class AboutControl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this._FrontPageBox = new TheArtOfDev.HtmlRenderer.WinForms.HtmlPanel();
+ this.SuspendLayout();
+ //
+ // _FrontPageBox
+ //
+ this._FrontPageBox.AutoScroll = true;
+ this._FrontPageBox.BackColor = System.Drawing.SystemColors.Window;
+ this._FrontPageBox.BaseStylesheet = "";
+ this._FrontPageBox.Dock = System.Windows.Forms.DockStyle.Fill;
+ this._FrontPageBox.IsContextMenuEnabled = false;
+ this._FrontPageBox.IsSelectionEnabled = false;
+ this._FrontPageBox.Location = new System.Drawing.Point(9, 8);
+ this._FrontPageBox.Name = "_FrontPageBox";
+ this._FrontPageBox.Size = new System.Drawing.Size(433, 328);
+ this._FrontPageBox.TabIndex = 1;
+ this._FrontPageBox.Text = null;
+ this._FrontPageBox.LinkClicked += new System.EventHandler(this._FrontPageBox_LinkClicked);
+ this._FrontPageBox.ImageLoad += new System.EventHandler(this._FrontPageBox_ImageLoad);
+ //
+ // AboutControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this._FrontPageBox);
+ this.Name = "AboutControl";
+ this.Padding = new System.Windows.Forms.Padding(9, 8, 9, 8);
+ this.Size = new System.Drawing.Size(451, 344);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private TheArtOfDev.HtmlRenderer.WinForms.HtmlPanel _FrontPageBox;
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/AboutControl.cs b/pdfpatcher/App/Functions/AboutControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..261586e276bdb2bf0f5eb97aee24072347753f19
--- /dev/null
+++ b/pdfpatcher/App/Functions/AboutControl.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.Reflection;
+using System.Windows.Forms;
+
+namespace PDFPatcher
+{
+ [ToolboxItem(false)]
+ sealed partial class AboutControl : Functions.HtmlPageControl
+ {
+ public override string FunctionName => "关于 " + AssemblyTitle;
+
+ public override Bitmap IconImage => Properties.Resources.About;
+
+ public AboutControl() {
+ InitializeComponent();
+ Text = $"关于 {AssemblyTitle}";
+ _FrontPageBox.Text = Properties.Resources.AboutPage
+ .Replace("$AppName", Constants.AppName)
+ .Replace("$AssemblyCopyright", AssemblyCopyright)
+ .Replace("$AppHomePage", Constants.AppHomePage)
+ .Replace("$AppRepository1", Constants.AppRepository)
+ .Replace("$AppRepository2", Constants.AppRepository2)
+ .Replace("$AssemblyCompany", AssemblyCompany)
+ .Replace("$AssemblyVersion", AssemblyVersion);
+ }
+
+ #region 程序集属性访问器
+
+ public string AssemblyTitle {
+ get {
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyTitleAttribute), false);
+ if (attributes.Length > 0) {
+ var titleAttribute = (AssemblyTitleAttribute)attributes[0];
+ if (titleAttribute.Title != "") {
+ return titleAttribute.Title;
+ }
+ }
+ return System.IO.Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
+ }
+ }
+
+ public string AssemblyVersion => Application.ProductVersion;
+
+ public string AssemblyDescription {
+ get {
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyDescriptionAttribute), false);
+ return attributes.Length == 0 ? String.Empty : ((AssemblyDescriptionAttribute)attributes[0]).Description;
+ }
+ }
+
+ public string AssemblyProduct {
+ get {
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyProductAttribute), false);
+ return attributes.Length == 0 ? String.Empty : ((AssemblyProductAttribute)attributes[0]).Product;
+ }
+ }
+
+ public string AssemblyCopyright {
+ get {
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCopyrightAttribute), false);
+ return attributes.Length == 0 ? String.Empty : ((AssemblyCopyrightAttribute)attributes[0]).Copyright;
+ }
+ }
+
+ public string AssemblyCompany {
+ get {
+ var attributes = Assembly.GetExecutingAssembly().GetCustomAttributes(typeof(AssemblyCompanyAttribute), false);
+ return attributes.Length == 0 ? String.Empty : ((AssemblyCompanyAttribute)attributes[0]).Company;
+ }
+ }
+ #endregion
+
+ public override void ExecuteCommand(string commandName, params string[] parameters) {
+ if (commandName == Commands.CheckUpdate) {
+ AppContext.MainForm.ExecuteCommand(commandName);
+ }
+ else {
+ base.ExecuteCommand(commandName, parameters);
+ }
+ }
+
+ private void _FrontPageBox_ImageLoad(object sender, TheArtOfDev.HtmlRenderer.Core.Entities.HtmlImageLoadEventArgs e) {
+ LoadResourceImage(e);
+ }
+
+ private void _FrontPageBox_LinkClicked(object sender, TheArtOfDev.HtmlRenderer.Core.Entities.HtmlLinkClickedEventArgs e) {
+ HandleLinkClicked(e.Link);
+ e.Handled = true;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AboutControl.resx b/pdfpatcher/App/Functions/AboutControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..1af7de150c99c12dd67a509fe57c10d63e4eeb04
--- /dev/null
+++ b/pdfpatcher/App/Functions/AboutControl.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AboutPage.html b/pdfpatcher/App/Functions/AboutPage.html
new file mode 100644
index 0000000000000000000000000000000000000000..c3dd87b8ea30e771dc52f339972f4adb23890704
--- /dev/null
+++ b/pdfpatcher/App/Functions/AboutPage.html
@@ -0,0 +1,79 @@
+
+
+
+ 关于 $AppName
+
+
+
+ 关于 $AppName
+
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AppOptionForm.Designer.cs b/pdfpatcher/App/Functions/AppOptionForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dc7f03a0d7e8ed1c28d34844cb12960995b81e06
--- /dev/null
+++ b/pdfpatcher/App/Functions/AppOptionForm.Designer.cs
@@ -0,0 +1,260 @@
+namespace PDFPatcher.Functions
+{
+ partial class AppOptionForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this._DocInfoEncodingBox = new System.Windows.Forms.ComboBox();
+ this.label11 = new System.Windows.Forms.Label();
+ this._BookmarkEncodingBox = new System.Windows.Forms.ComboBox();
+ this.label10 = new System.Windows.Forms.Label();
+ this.groupBox1 = new System.Windows.Forms.GroupBox();
+ this._LoadPartialFileBox = new System.Windows.Forms.RadioButton();
+ this._LoadEntireFileBox = new System.Windows.Forms.RadioButton();
+ this.label12 = new System.Windows.Forms.Label();
+ this.groupBox2 = new System.Windows.Forms.GroupBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this._TextEncodingBox = new System.Windows.Forms.ComboBox();
+ this._SaveAppSettingsBox = new System.Windows.Forms.CheckBox();
+ this._CreateShortcutButton = new System.Windows.Forms.Button();
+ this._FontNameEncodingBox = new System.Windows.Forms.ComboBox();
+ this.label1 = new System.Windows.Forms.Label();
+ this.groupBox1.SuspendLayout();
+ this.groupBox2.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _DocInfoEncodingBox
+ //
+ this._DocInfoEncodingBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._DocInfoEncodingBox.FormattingEnabled = true;
+ this._DocInfoEncodingBox.Location = new System.Drawing.Point(103, 46);
+ this._DocInfoEncodingBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._DocInfoEncodingBox.Name = "_DocInfoEncodingBox";
+ this._DocInfoEncodingBox.Size = new System.Drawing.Size(177, 23);
+ this._DocInfoEncodingBox.TabIndex = 3;
+ //
+ // label11
+ //
+ this.label11.AutoSize = true;
+ this.label11.Location = new System.Drawing.Point(8, 50);
+ this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label11.Name = "label11";
+ this.label11.Size = new System.Drawing.Size(82, 15);
+ this.label11.TabIndex = 2;
+ this.label11.Text = "文档属性:";
+ //
+ // _BookmarkEncodingBox
+ //
+ this._BookmarkEncodingBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._BookmarkEncodingBox.FormattingEnabled = true;
+ this._BookmarkEncodingBox.Location = new System.Drawing.Point(389, 46);
+ this._BookmarkEncodingBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._BookmarkEncodingBox.Name = "_BookmarkEncodingBox";
+ this._BookmarkEncodingBox.Size = new System.Drawing.Size(177, 23);
+ this._BookmarkEncodingBox.TabIndex = 5;
+ //
+ // label10
+ //
+ this.label10.AutoSize = true;
+ this.label10.Location = new System.Drawing.Point(295, 50);
+ this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label10.Name = "label10";
+ this.label10.Size = new System.Drawing.Size(82, 15);
+ this.label10.TabIndex = 4;
+ this.label10.Text = "书签文本:";
+ //
+ // groupBox1
+ //
+ this.groupBox1.Controls.Add(this._LoadPartialFileBox);
+ this.groupBox1.Controls.Add(this._LoadEntireFileBox);
+ this.groupBox1.Location = new System.Drawing.Point(16, 42);
+ this.groupBox1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this.groupBox1.Name = "groupBox1";
+ this.groupBox1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this.groupBox1.Size = new System.Drawing.Size(573, 58);
+ this.groupBox1.TabIndex = 1;
+ this.groupBox1.TabStop = false;
+ this.groupBox1.Text = "访问 PDF 文档";
+ //
+ // _LoadPartialFileBox
+ //
+ this._LoadPartialFileBox.AutoSize = true;
+ this._LoadPartialFileBox.Location = new System.Drawing.Point(273, 25);
+ this._LoadPartialFileBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._LoadPartialFileBox.Name = "_LoadPartialFileBox";
+ this._LoadPartialFileBox.Size = new System.Drawing.Size(268, 19);
+ this._LoadPartialFileBox.TabIndex = 1;
+ this._LoadPartialFileBox.TabStop = true;
+ this._LoadPartialFileBox.Text = "减少占用内存(仅加载需处理部分)";
+ this._LoadPartialFileBox.UseVisualStyleBackColor = true;
+ //
+ // _LoadEntireFileBox
+ //
+ this._LoadEntireFileBox.AutoSize = true;
+ this._LoadEntireFileBox.Location = new System.Drawing.Point(11, 25);
+ this._LoadEntireFileBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._LoadEntireFileBox.Name = "_LoadEntireFileBox";
+ this._LoadEntireFileBox.Size = new System.Drawing.Size(238, 19);
+ this._LoadEntireFileBox.TabIndex = 0;
+ this._LoadEntireFileBox.TabStop = true;
+ this._LoadEntireFileBox.Text = "优化处理效率(加载整个文件)";
+ this._LoadEntireFileBox.UseVisualStyleBackColor = true;
+ //
+ // label12
+ //
+ this.label12.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.label12.Location = new System.Drawing.Point(8, 21);
+ this.label12.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(560, 21);
+ this.label12.TabIndex = 6;
+ this.label12.Text = "说明:当遇到 PDF 文档的文本为乱码时,可尝试使用此选项强制设定编码。";
+ //
+ // groupBox2
+ //
+ this.groupBox2.Controls.Add(this.label1);
+ this.groupBox2.Controls.Add(this.label2);
+ this.groupBox2.Controls.Add(this._FontNameEncodingBox);
+ this.groupBox2.Controls.Add(this._TextEncodingBox);
+ this.groupBox2.Controls.Add(this._DocInfoEncodingBox);
+ this.groupBox2.Controls.Add(this.label10);
+ this.groupBox2.Controls.Add(this.label12);
+ this.groupBox2.Controls.Add(this._BookmarkEncodingBox);
+ this.groupBox2.Controls.Add(this.label11);
+ this.groupBox2.Location = new System.Drawing.Point(13, 108);
+ this.groupBox2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this.groupBox2.Name = "groupBox2";
+ this.groupBox2.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this.groupBox2.Size = new System.Drawing.Size(576, 114);
+ this.groupBox2.TabIndex = 9;
+ this.groupBox2.TabStop = false;
+ this.groupBox2.Text = "读取文档所用的编码";
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(8, 82);
+ this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(82, 15);
+ this.label2.TabIndex = 7;
+ this.label2.Text = "正文文本:";
+ //
+ // _TextEncodingBox
+ //
+ this._TextEncodingBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._TextEncodingBox.FormattingEnabled = true;
+ this._TextEncodingBox.Location = new System.Drawing.Point(103, 79);
+ this._TextEncodingBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._TextEncodingBox.Name = "_TextEncodingBox";
+ this._TextEncodingBox.Size = new System.Drawing.Size(177, 23);
+ this._TextEncodingBox.TabIndex = 3;
+ //
+ // _SaveAppSettingsBox
+ //
+ this._SaveAppSettingsBox.AutoSize = true;
+ this._SaveAppSettingsBox.Location = new System.Drawing.Point(16, 15);
+ this._SaveAppSettingsBox.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._SaveAppSettingsBox.Name = "_SaveAppSettingsBox";
+ this._SaveAppSettingsBox.Size = new System.Drawing.Size(179, 19);
+ this._SaveAppSettingsBox.TabIndex = 11;
+ this._SaveAppSettingsBox.Text = "自动保存应用程序设置";
+ this._SaveAppSettingsBox.UseVisualStyleBackColor = true;
+ //
+ // _CreateShortcutButton
+ //
+ this._CreateShortcutButton.Location = new System.Drawing.Point(311, 10);
+ this._CreateShortcutButton.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._CreateShortcutButton.Name = "_CreateShortcutButton";
+ this._CreateShortcutButton.Size = new System.Drawing.Size(216, 29);
+ this._CreateShortcutButton.TabIndex = 12;
+ this._CreateShortcutButton.Text = "在桌面创建程序快捷方式";
+ this._CreateShortcutButton.UseVisualStyleBackColor = true;
+ this._CreateShortcutButton.Click += new System.EventHandler(this._CreateShortcutButton_Click);
+ //
+ // _FontNameEncodingBox
+ //
+ this._FontNameEncodingBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._FontNameEncodingBox.FormattingEnabled = true;
+ this._FontNameEncodingBox.Location = new System.Drawing.Point(389, 79);
+ this._FontNameEncodingBox.Margin = new System.Windows.Forms.Padding(4);
+ this._FontNameEncodingBox.Name = "_FontNameEncodingBox";
+ this._FontNameEncodingBox.Size = new System.Drawing.Size(177, 23);
+ this._FontNameEncodingBox.TabIndex = 3;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(294, 82);
+ this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(82, 15);
+ this.label1.TabIndex = 7;
+ this.label1.Text = "字体名称:";
+ //
+ // AppOptionControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(631, 334);
+ this.Controls.Add(this._CreateShortcutButton);
+ this.Controls.Add(this._SaveAppSettingsBox);
+ this.Controls.Add(this.groupBox2);
+ this.Controls.Add(this.groupBox1);
+ this.Font = new System.Drawing.Font("宋体", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedSingle;
+ this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AppOptionControl";
+ this.Text = "程序工作选项";
+ this.groupBox1.ResumeLayout(false);
+ this.groupBox1.PerformLayout();
+ this.groupBox2.ResumeLayout(false);
+ this.groupBox2.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.ComboBox _DocInfoEncodingBox;
+ private System.Windows.Forms.Label label11;
+ private System.Windows.Forms.ComboBox _BookmarkEncodingBox;
+ private System.Windows.Forms.Label label10;
+ private System.Windows.Forms.GroupBox groupBox1;
+ private System.Windows.Forms.Label label12;
+ private System.Windows.Forms.RadioButton _LoadEntireFileBox;
+ private System.Windows.Forms.RadioButton _LoadPartialFileBox;
+ private System.Windows.Forms.GroupBox groupBox2;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.ComboBox _TextEncodingBox;
+ private System.Windows.Forms.CheckBox _SaveAppSettingsBox;
+ private System.Windows.Forms.Button _CreateShortcutButton;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.ComboBox _FontNameEncodingBox;
+ }
+}
diff --git a/pdfpatcher/App/Functions/AppOptionForm.cs b/pdfpatcher/App/Functions/AppOptionForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..450cac87387a491917cbfaa835e77f3d47931206
--- /dev/null
+++ b/pdfpatcher/App/Functions/AppOptionForm.cs
@@ -0,0 +1,89 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using PDFPatcher.Common;
+
+namespace PDFPatcher.Functions
+{
+ [ToolboxItem(false)]
+ public partial class AppOptionForm : Form, IResettableControl
+ {
+ bool locked;
+
+ public AppOptionForm() {
+ InitializeComponent();
+ Reload();
+ this.SetIcon(Properties.Resources.AppOptions);
+ _BookmarkEncodingBox.SelectedIndexChanged += ControlChanged;
+ _DocInfoEncodingBox.SelectedIndexChanged += ControlChanged;
+ _TextEncodingBox.SelectedIndexChanged += ControlChanged;
+ _FontNameEncodingBox.SelectedIndexChanged += ControlChanged;
+ _SaveAppSettingsBox.CheckedChanged += ControlChanged;
+ _LoadEntireFileBox.CheckedChanged += ControlChanged;
+ }
+
+ public void Reset() {
+ AppContext.SaveAppSettings = true;
+ AppContext.LoadPartialPdfFile = false;
+ AppContext.Encodings = new EncodingOptions();
+ Reload();
+ }
+
+ public void Reload() {
+ locked = true;
+ _SaveAppSettingsBox.Checked = AppContext.SaveAppSettings;
+ _LoadPartialFileBox.Checked = AppContext.LoadPartialPdfFile;
+ _LoadEntireFileBox.Checked = !AppContext.LoadPartialPdfFile;
+
+ InitEncodingList(_BookmarkEncodingBox, AppContext.Encodings.BookmarkEncodingName);
+ InitEncodingList(_DocInfoEncodingBox, AppContext.Encodings.DocInfoEncodingName);
+ InitEncodingList(_TextEncodingBox, AppContext.Encodings.TextEncodingName);
+ InitEncodingList(_FontNameEncodingBox, AppContext.Encodings.FontNameEncodingName);
+
+ locked = false;
+ }
+
+ static void InitEncodingList(ComboBox list, string encodingName) {
+ list.Items.Clear();
+ foreach (var item in Constants.Encoding.EncodingNames) {
+ list.Items.Add(item);
+ if (encodingName == item) {
+ list.SelectedIndex = list.Items.Count - 1;
+ }
+ }
+ if (list.SelectedIndex == -1) {
+ list.SelectedIndex = 0;
+ }
+ }
+
+ void ControlChanged(object sender, EventArgs e) {
+ if (locked) {
+ return;
+ }
+
+ if (sender == _DocInfoEncodingBox) {
+ AppContext.Encodings.DocInfoEncodingName = _DocInfoEncodingBox.SelectedItem.ToString();
+ }
+ else if (sender == _BookmarkEncodingBox) {
+ AppContext.Encodings.BookmarkEncodingName = _BookmarkEncodingBox.SelectedItem.ToString();
+ }
+ else if (sender == _TextEncodingBox) {
+ AppContext.Encodings.TextEncodingName = _TextEncodingBox.SelectedItem.ToString();
+ }
+ else if (sender == _FontNameEncodingBox) {
+ AppContext.Encodings.FontNameEncodingName = _FontNameEncodingBox.SelectedItem.ToString();
+ }
+ else if (sender == _SaveAppSettingsBox) {
+ AppContext.SaveAppSettings = _SaveAppSettingsBox.Checked;
+ }
+ else if (sender == _LoadEntireFileBox) {
+ AppContext.LoadPartialPdfFile = _LoadPartialFileBox.Checked;
+ }
+ }
+
+ void _CreateShortcutButton_Click(object sender, EventArgs e) {
+ CommonCommands.CreateShortcut();
+ }
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/AppOptionForm.resx b/pdfpatcher/App/Functions/AppOptionForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AppOptionForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a8fafc57654b20a944d9b453a9b846613e983bc0
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.Designer.cs
@@ -0,0 +1,206 @@
+namespace PDFPatcher.Functions
+{
+ partial class EditAdjustmentForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this._AddFilterMenuItem = new System.Windows.Forms.ToolStripDropDownButton();
+ this._OkButton = new System.Windows.Forms.Button();
+ this._CancelButton = new System.Windows.Forms.Button();
+ this._FilterBox = new BrightIdeasSoftware.ObjectListView();
+ this._TypeColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ConditionColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._IsInclusiveColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._MainToolbar = new System.Windows.Forms.ToolStrip();
+ this._RemoveButton = new System.Windows.Forms.ToolStripButton();
+ this._EditFilterBox = new System.Windows.Forms.GroupBox();
+ this._EditFilterPanel = new System.Windows.Forms.Panel();
+ ((System.ComponentModel.ISupportInitialize)(this._FilterBox)).BeginInit();
+ this._MainToolbar.SuspendLayout();
+ this._EditFilterBox.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _AddFilterMenuItem
+ //
+ this._AddFilterMenuItem.Image = global::PDFPatcher.Properties.Resources.Add;
+ this._AddFilterMenuItem.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._AddFilterMenuItem.Name = "_AddFilterMenuItem";
+ this._AddFilterMenuItem.Size = new System.Drawing.Size(109, 22);
+ this._AddFilterMenuItem.Text = "添加匹配条件";
+ this._AddFilterMenuItem.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this._AddFilterMenuItem_DropDownItemClicked);
+ //
+ // _OkButton
+ //
+ this._OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._OkButton.Location = new System.Drawing.Point(267, 285);
+ this._OkButton.Name = "_OkButton";
+ this._OkButton.Size = new System.Drawing.Size(75, 23);
+ this._OkButton.TabIndex = 0;
+ this._OkButton.Text = "确定(&Q)";
+ this._OkButton.UseVisualStyleBackColor = true;
+ this._OkButton.Click += new System.EventHandler(this._OkButton_Click);
+ //
+ // _CancelButton
+ //
+ this._CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this._CancelButton.Location = new System.Drawing.Point(348, 285);
+ this._CancelButton.Name = "_CancelButton";
+ this._CancelButton.Size = new System.Drawing.Size(75, 23);
+ this._CancelButton.TabIndex = 1;
+ this._CancelButton.Text = "取消(&X)";
+ this._CancelButton.UseVisualStyleBackColor = true;
+ this._CancelButton.Click += new System.EventHandler(this._CancelButton_Click);
+ //
+ // _FilterBox
+ //
+ this._FilterBox.AllColumns.Add(this._TypeColumn);
+ this._FilterBox.AllColumns.Add(this._ConditionColumn);
+ this._FilterBox.AllColumns.Add(this._IsInclusiveColumn);
+ this._FilterBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._FilterBox.CellEditUseWholeCell = false;
+ this._FilterBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._TypeColumn,
+ this._ConditionColumn,
+ this._IsInclusiveColumn});
+ this._FilterBox.Cursor = System.Windows.Forms.Cursors.Default;
+ this._FilterBox.FullRowSelect = true;
+ this._FilterBox.GridLines = true;
+ this._FilterBox.HideSelection = false;
+ this._FilterBox.IsSimpleDragSource = true;
+ this._FilterBox.IsSimpleDropSink = true;
+ this._FilterBox.Location = new System.Drawing.Point(12, 28);
+ this._FilterBox.MultiSelect = false;
+ this._FilterBox.Name = "_FilterBox";
+ this._FilterBox.ShowGroups = false;
+ this._FilterBox.Size = new System.Drawing.Size(411, 141);
+ this._FilterBox.TabIndex = 3;
+ this._FilterBox.UseCompatibleStateImageBehavior = false;
+ this._FilterBox.View = System.Windows.Forms.View.Details;
+ this._FilterBox.SelectedIndexChanged += new System.EventHandler(this._FilterBox_SelectedIndexChanged);
+ //
+ // _TypeColumn
+ //
+ this._TypeColumn.IsEditable = false;
+ this._TypeColumn.Text = "筛选条件";
+ this._TypeColumn.Width = 69;
+ //
+ // _ConditionColumn
+ //
+ this._ConditionColumn.FillsFreeSpace = true;
+ this._ConditionColumn.Text = "匹配条件";
+ this._ConditionColumn.Width = 241;
+ //
+ // _IsInclusiveColumn
+ //
+ this._IsInclusiveColumn.IsEditable = false;
+ this._IsInclusiveColumn.Text = "包含筛选";
+ this._IsInclusiveColumn.Width = 78;
+ //
+ // _MainToolbar
+ //
+ this._MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._AddFilterMenuItem,
+ this._RemoveButton});
+ this._MainToolbar.Location = new System.Drawing.Point(0, 0);
+ this._MainToolbar.Name = "_MainToolbar";
+ this._MainToolbar.Size = new System.Drawing.Size(435, 25);
+ this._MainToolbar.TabIndex = 4;
+ this._MainToolbar.Text = "toolStrip1";
+ //
+ // _RemoveButton
+ //
+ this._RemoveButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._RemoveButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._RemoveButton.Name = "_RemoveButton";
+ this._RemoveButton.Size = new System.Drawing.Size(52, 22);
+ this._RemoveButton.Text = "删除";
+ this._RemoveButton.Click += new System.EventHandler(this._RemoveButton_Click);
+ //
+ // _EditFilterBox
+ //
+ this._EditFilterBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._EditFilterBox.Controls.Add(this._EditFilterPanel);
+ this._EditFilterBox.Location = new System.Drawing.Point(12, 175);
+ this._EditFilterBox.Name = "_EditFilterBox";
+ this._EditFilterBox.Size = new System.Drawing.Size(411, 104);
+ this._EditFilterBox.TabIndex = 5;
+ this._EditFilterBox.TabStop = false;
+ this._EditFilterBox.Text = "更改匹配条件";
+ //
+ // _EditFilterPanel
+ //
+ this._EditFilterPanel.Location = new System.Drawing.Point(6, 20);
+ this._EditFilterPanel.Name = "_EditFilterPanel";
+ this._EditFilterPanel.Size = new System.Drawing.Size(399, 78);
+ this._EditFilterPanel.TabIndex = 0;
+ //
+ // EditAdjustmentForm
+ //
+ this.AcceptButton = this._OkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this._CancelButton;
+ this.ClientSize = new System.Drawing.Size(435, 320);
+ this.ControlBox = false;
+ this.Controls.Add(this._EditFilterBox);
+ this.Controls.Add(this._MainToolbar);
+ this.Controls.Add(this._FilterBox);
+ this.Controls.Add(this._CancelButton);
+ this.Controls.Add(this._OkButton);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.MinimumSize = new System.Drawing.Size(443, 318);
+ this.Name = "EditAdjustmentForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "编辑标题文本筛选条件";
+ ((System.ComponentModel.ISupportInitialize)(this._FilterBox)).EndInit();
+ this._MainToolbar.ResumeLayout(false);
+ this._MainToolbar.PerformLayout();
+ this._EditFilterBox.ResumeLayout(false);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _OkButton;
+ private System.Windows.Forms.Button _CancelButton;
+ private BrightIdeasSoftware.ObjectListView _FilterBox;
+ private BrightIdeasSoftware.OLVColumn _ConditionColumn;
+ private BrightIdeasSoftware.OLVColumn _TypeColumn;
+ private BrightIdeasSoftware.OLVColumn _IsInclusiveColumn;
+ private System.Windows.Forms.ToolStrip _MainToolbar;
+ private System.Windows.Forms.ToolStripButton _RemoveButton;
+ private System.Windows.Forms.GroupBox _EditFilterBox;
+ private System.Windows.Forms.Panel _EditFilterPanel;
+ private System.Windows.Forms.ToolStripDropDownButton _AddFilterMenuItem;
+ }
+}
+
diff --git a/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.cs b/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a896ad0e57cb2df3d3ff5c0cc1611e271edcd418
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.cs
@@ -0,0 +1,148 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class EditAdjustmentForm : Form
+ {
+ internal static string[] FilterNames = new string[] { "字体名称", "文本尺寸", "文本位置", "页码范围", "文本内容" };
+ internal static string[] FilterIDs = new string[] { "_FontNameFilter", "_FontSizeFilter", "_FontPositionFilter", "_PageRangeFilter", "_TextFilter" };
+
+ readonly Dictionary _filterEditors = new Dictionary();
+ internal AutoBookmarkOptions.LevelAdjustmentOption Filter { get; private set; }
+ AutoBookmarkCondition.MultiCondition conditions;
+
+ public EditAdjustmentForm() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ }
+ public EditAdjustmentForm(AutoBookmarkOptions.LevelAdjustmentOption filter) : this() {
+ int i = 0;
+ foreach (var item in FilterNames) {
+ _AddFilterMenuItem.DropDownItems.Add(item).Name = FilterIDs[i++];
+ }
+ _FilterBox.BeforeSorting += (object sender, BrightIdeasSoftware.BeforeSortingEventArgs e) => e.Canceled = true;
+ _ConditionColumn.AspectGetter = (object x) => x is AutoBookmarkCondition f ? f.Description : (object)null;
+ _IsInclusiveColumn.AspectGetter = (object x) => {
+ if (x is AutoBookmarkCondition f) {
+ return f.IsInclusive ? "包含匹配项" : "过滤匹配项";
+ }
+ return null;
+ };
+ _TypeColumn.AspectGetter = (object x) => x is AutoBookmarkCondition f ? f.Name : null;
+ Filter = new AutoBookmarkOptions.LevelAdjustmentOption();
+ if (filter != null) {
+ Filter.AdjustmentLevel = filter.AdjustmentLevel;
+ Filter.RelativeAdjustment = filter.RelativeAdjustment;
+ conditions = new AutoBookmarkCondition.MultiCondition(filter.Condition);
+ _FilterBox.Objects = conditions.Conditions;
+ }
+ if (_FilterBox.Items.Count > 0) {
+ _FilterBox.SelectedIndex = 0;
+ }
+ }
+
+ void OnLoad() {
+ _MainToolbar.ScaleIcons(16);
+ _FilterBox.ScaleColumnWidths();
+ }
+
+ void _OkButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.OK;
+ conditions = new AutoBookmarkCondition.MultiCondition();
+ foreach (ListViewItem item in _FilterBox.Items) {
+ conditions.Conditions.Add((AutoBookmarkCondition)_FilterBox.GetModelObject(item.Index));
+ }
+
+ Filter.Condition = conditions.Conditions.Count switch {
+ 1 => conditions.Conditions[0],
+ 0 => null,
+ _ => conditions
+ };
+ Close();
+ }
+
+ void _CancelButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ private void _AddFilterMenuItem_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ var c = CreateCondition(e.ClickedItem.Name);
+ if (c != null) {
+ _FilterBox.AddObject(c);
+ }
+ }
+
+ private void _FilterBox_SelectedIndexChanged(object sender, EventArgs e) {
+ _EditFilterPanel.Controls.Clear();
+ var o = _FilterBox.SelectedObject;
+ if (o == null) {
+ return;
+ }
+ var ed = GetFilterEditor(o as AutoBookmarkCondition);
+ if (ed == null) {
+ return;
+ }
+ _EditFilterPanel.Controls.Add(ed.EditorControl);
+ ed.EditorControl.Anchor = AnchorStyles.Left | AnchorStyles.Right | AnchorStyles.Top | AnchorStyles.Bottom;
+ ed.EditorControl.Left = ed.EditorControl.Top = 0;
+ ed.EditorControl.Size = _EditFilterPanel.ClientSize;
+ }
+
+ internal static AutoBookmarkCondition CreateCondition(string name) {
+ switch (name) {
+ case "_FontNameFilter": return new AutoBookmarkCondition.FontNameCondition("SimSun", false);
+ case "_FontSizeFilter": return new AutoBookmarkCondition.TextSizeCondition(0, 10);
+ case "_FontPositionFilter": return new AutoBookmarkCondition.TextPositionCondition(1, -9999, 9999);
+ case "_PageRangeFilter": return new AutoBookmarkCondition.PageRangeCondition();
+ case "_TextFilter": return new AutoBookmarkCondition.TextCondition() { Pattern = new MatchPattern("筛选条件", false, false, false) };
+ default: return null;
+ }
+ }
+
+ internal static void UpdateFilter(IFilterConditionEditor filter) {
+ if (filter.EditorControl?.FindForm() is EditAdjustmentForm f) {
+ f._FilterBox.RefreshSelectedObjects();
+ }
+ }
+
+ private IFilterConditionEditor GetFilterEditor(AutoBookmarkCondition filter) {
+ var t = filter.GetType();
+ if (_filterEditors.TryGetValue(t, out IFilterConditionEditor c)) {
+ goto SetEditor;
+ // return c;
+ }
+ else if (t == typeof(AutoBookmarkCondition.FontNameCondition)) {
+ c = new FontNameConditionEditor();
+ }
+ else if (t == typeof(AutoBookmarkCondition.TextSizeCondition)) {
+ c = new TextSizeConditionEditor();
+ }
+ else if (t == typeof(AutoBookmarkCondition.TextPositionCondition)) {
+ c = new TextPositionConditionEditor();
+ }
+ else if (t == typeof(AutoBookmarkCondition.PageRangeCondition)) {
+ c = new PageRangeConditionEditor();
+ }
+ else if (t == typeof(AutoBookmarkCondition.TextCondition)) {
+ c = new TextConditionEditor();
+ }
+ else {
+ Common.FormHelper.ErrorBox("无法编辑选中的筛选条件。");
+ return null;
+ }
+ SetEditor:
+ _filterEditors[t] = c;
+ c.Filter = filter;
+ return c;
+ }
+
+ private void _RemoveButton_Click(object sender, EventArgs e) {
+ _FilterBox.RemoveObjects(_FilterBox.SelectedObjects);
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.resx b/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..e110332264cce335ffd48830765b096407246803
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/EditAdjustmentForm.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8d6275f619be9aea1627031f4d0a6894211948da
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.Designer.cs
@@ -0,0 +1,219 @@
+namespace PDFPatcher.Functions
+{
+ partial class FontFilterForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container ();
+ this._OkButton = new System.Windows.Forms.Button ();
+ this._CancelButton = new System.Windows.Forms.Button ();
+ this._MessageLabel = new System.Windows.Forms.Label ();
+ this._FontNameSizeColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._FirstPageColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._CountColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._FontInfoBox = new BrightIdeasSoftware.TreeListView ();
+ this._AddFilterMenu = new System.Windows.Forms.ContextMenuStrip (this.components);
+ this._FilterBox = new BrightIdeasSoftware.ObjectListView ();
+ this._ConditionColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._AddConditionButton = new System.Windows.Forms.Button ();
+ this._RemoveConditionButton = new System.Windows.Forms.Button ();
+ ((System.ComponentModel.ISupportInitialize)(this._FontInfoBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._FilterBox)).BeginInit ();
+ this.SuspendLayout ();
+ //
+ // _OkButton
+ //
+ this._OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._OkButton.Location = new System.Drawing.Point (368, 376);
+ this._OkButton.Name = "_OkButton";
+ this._OkButton.Size = new System.Drawing.Size (75, 23);
+ this._OkButton.TabIndex = 5;
+ this._OkButton.Text = "确定(&Q)";
+ this._OkButton.UseVisualStyleBackColor = true;
+ this._OkButton.Click += new System.EventHandler (this._OkButton_Click);
+ //
+ // _CancelButton
+ //
+ this._CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this._CancelButton.Location = new System.Drawing.Point (449, 376);
+ this._CancelButton.Name = "_CancelButton";
+ this._CancelButton.Size = new System.Drawing.Size (75, 23);
+ this._CancelButton.TabIndex = 6;
+ this._CancelButton.Text = "取消(&X)";
+ this._CancelButton.UseVisualStyleBackColor = true;
+ this._CancelButton.Click += new System.EventHandler (this._CancelButton_Click);
+ //
+ // _MessageLabel
+ //
+ this._MessageLabel.AutoSize = true;
+ this._MessageLabel.Location = new System.Drawing.Point (12, 9);
+ this._MessageLabel.Name = "_MessageLabel";
+ this._MessageLabel.Size = new System.Drawing.Size (407, 12);
+ this._MessageLabel.TabIndex = 0;
+ this._MessageLabel.Text = "下表列出了 PDF 文档中所使用的字体。右键点击项目可添加字体筛选条件。";
+ //
+ // _FontNameSizeColumn
+ //
+ this._FontNameSizeColumn.Text = "字体名称/文本尺寸(首次出现文本)";
+ this._FontNameSizeColumn.Width = 329;
+ //
+ // _FirstPageColumn
+ //
+ this._FirstPageColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._FirstPageColumn.Text = "首次出现页码";
+ this._FirstPageColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._FirstPageColumn.Width = 51;
+ //
+ // _CountColumn
+ //
+ this._CountColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._CountColumn.Text = "出现次数";
+ this._CountColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._CountColumn.Width = 52;
+ //
+ // _FontInfoBox
+ //
+ this._FontInfoBox.AllColumns.Add (this._FontNameSizeColumn);
+ this._FontInfoBox.AllColumns.Add (this._FirstPageColumn);
+ this._FontInfoBox.AllColumns.Add (this._CountColumn);
+ this._FontInfoBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._FontInfoBox.CheckBoxes = false;
+ this._FontInfoBox.Columns.AddRange (new System.Windows.Forms.ColumnHeader[] {
+ this._FontNameSizeColumn,
+ this._FirstPageColumn,
+ this._CountColumn});
+ this._FontInfoBox.ContextMenuStrip = this._AddFilterMenu;
+ this._FontInfoBox.FullRowSelect = true;
+ this._FontInfoBox.GridLines = true;
+ this._FontInfoBox.HeaderWordWrap = true;
+ this._FontInfoBox.Location = new System.Drawing.Point (14, 36);
+ this._FontInfoBox.MultiSelect = false;
+ this._FontInfoBox.Name = "_FontInfoBox";
+ this._FontInfoBox.OwnerDraw = true;
+ this._FontInfoBox.ShowGroups = false;
+ this._FontInfoBox.Size = new System.Drawing.Size (510, 206);
+ this._FontInfoBox.TabIndex = 1;
+ this._FontInfoBox.UseCompatibleStateImageBehavior = false;
+ this._FontInfoBox.View = System.Windows.Forms.View.Details;
+ this._FontInfoBox.VirtualMode = true;
+ //
+ // _AddFilterMenu
+ //
+ this._AddFilterMenu.Name = "_AddFilterMenu";
+ this._AddFilterMenu.ShowImageMargin = false;
+ this._AddFilterMenu.Size = new System.Drawing.Size (36, 4);
+ this._AddFilterMenu.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler (this._AddFilterMenu_ItemClicked);
+ this._AddFilterMenu.Opening += new System.ComponentModel.CancelEventHandler (this._AddFilterMenu_Opening);
+ //
+ // _FilterBox
+ //
+ this._FilterBox.AllColumns.Add (this._ConditionColumn);
+ this._FilterBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._FilterBox.Columns.AddRange (new System.Windows.Forms.ColumnHeader[] {
+ this._ConditionColumn});
+ this._FilterBox.FullRowSelect = true;
+ this._FilterBox.GridLines = true;
+ this._FilterBox.Location = new System.Drawing.Point (14, 248);
+ this._FilterBox.Name = "_FilterBox";
+ this._FilterBox.ShowGroups = false;
+ this._FilterBox.Size = new System.Drawing.Size (415, 122);
+ this._FilterBox.TabIndex = 2;
+ this._FilterBox.UseCompatibleStateImageBehavior = false;
+ this._FilterBox.View = System.Windows.Forms.View.Details;
+ //
+ // _ConditionColumn
+ //
+ this._ConditionColumn.Text = "筛选条件";
+ this._ConditionColumn.Width = 330;
+ //
+ // _AddConditionButton
+ //
+ this._AddConditionButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._AddConditionButton.Location = new System.Drawing.Point (435, 248);
+ this._AddConditionButton.Name = "_AddConditionButton";
+ this._AddConditionButton.Size = new System.Drawing.Size (89, 23);
+ this._AddConditionButton.TabIndex = 3;
+ this._AddConditionButton.Text = "添加筛选条件";
+ this._AddConditionButton.UseVisualStyleBackColor = true;
+ this._AddConditionButton.Click += new System.EventHandler (this.ControlEvent);
+ //
+ // _RemoveConditionButton
+ //
+ this._RemoveConditionButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._RemoveConditionButton.Location = new System.Drawing.Point (435, 277);
+ this._RemoveConditionButton.Name = "_RemoveConditionButton";
+ this._RemoveConditionButton.Size = new System.Drawing.Size (89, 23);
+ this._RemoveConditionButton.TabIndex = 4;
+ this._RemoveConditionButton.Text = "删除筛选条件";
+ this._RemoveConditionButton.UseVisualStyleBackColor = true;
+ this._RemoveConditionButton.Click += new System.EventHandler (this.ControlEvent);
+ //
+ // FontFilterForm
+ //
+ this.AcceptButton = this._OkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this._CancelButton;
+ this.ClientSize = new System.Drawing.Size (536, 411);
+ this.Controls.Add (this._RemoveConditionButton);
+ this.Controls.Add (this._AddConditionButton);
+ this.Controls.Add (this._FontInfoBox);
+ this.Controls.Add (this._MessageLabel);
+ this.Controls.Add (this._FilterBox);
+ this.Controls.Add (this._CancelButton);
+ this.Controls.Add (this._OkButton);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FontFilterForm";
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "添加字体筛选条件";
+ ((System.ComponentModel.ISupportInitialize)(this._FontInfoBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._FilterBox)).EndInit ();
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _OkButton;
+ private System.Windows.Forms.Button _CancelButton;
+ private System.Windows.Forms.Label _MessageLabel;
+ private BrightIdeasSoftware.OLVColumn _FontNameSizeColumn;
+ private BrightIdeasSoftware.OLVColumn _FirstPageColumn;
+ private BrightIdeasSoftware.OLVColumn _CountColumn;
+ private BrightIdeasSoftware.TreeListView _FontInfoBox;
+ private System.Windows.Forms.ContextMenuStrip _AddFilterMenu;
+ private BrightIdeasSoftware.ObjectListView _FilterBox;
+ private BrightIdeasSoftware.OLVColumn _ConditionColumn;
+ private System.Windows.Forms.Button _AddConditionButton;
+ private System.Windows.Forms.Button _RemoveConditionButton;
+ }
+}
+
diff --git a/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.cs b/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1430a252bb1c0de0359bf9abdaf4ba65c59545f5
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.cs
@@ -0,0 +1,211 @@
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Xml;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class FontFilterForm : Form
+ {
+ sealed class FilterSetting
+ {
+ internal string FontName { get; }
+ internal bool FullMatch { get; }
+ internal float Size { get; }
+ public FilterSetting(string fontName, bool fullMatch, float size) {
+ FontName = fontName;
+ FullMatch = fullMatch;
+ Size = size;
+ }
+ }
+
+ readonly XmlElement _fontInfo;
+ internal AutoBookmarkCondition[] FilterConditions {
+ get;
+ private set;
+ }
+ public FontFilterForm() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ }
+ public FontFilterForm(XmlNode fontInfo) : this() {
+ _fontInfo = fontInfo as XmlElement;
+ }
+
+ void OnLoad() {
+ var tcr = _FontInfoBox.TreeColumnRenderer;
+ tcr.LinePen = new Pen(SystemColors.ControlDark) {
+ DashCap = System.Drawing.Drawing2D.DashCap.Round,
+ DashStyle = System.Drawing.Drawing2D.DashStyle.Dash
+ };
+
+ _FontInfoBox.CanExpandGetter = (object o) => o is XmlElement f && f.Name == Constants.Font.ThisName && f.HasChildNodes;
+ _FontInfoBox.ChildrenGetter = (object o) => o is XmlElement f ? (System.Collections.IEnumerable)f.SelectNodes(Constants.Font.Size) : null;
+ _FontInfoBox.RowFormatter = (BrightIdeasSoftware.OLVListItem o) => {
+ if (_FontInfoBox.GetParent(o.RowObject) == null) {
+ o.SubItems[0].Font = new Font(o.SubItems[0].Font, FontStyle.Bold);
+ o.SubItems[1].Text = String.Empty;
+ o.BackColor = Color.LightBlue;
+ }
+ };
+ _FontNameSizeColumn.AspectGetter = (object o) => {
+ var f = o as XmlElement;
+ if (f == null) {
+ return null;
+ }
+ if (f.Name == Constants.Font.ThisName) {
+ return f.GetAttribute(Constants.Font.Name);
+ }
+ else if (f.ParentNode?.Name == Constants.Font.ThisName) {
+ f.GetAttribute(Constants.Font.Size).TryParse(out float p);
+ var t = f.GetAttribute(Constants.FontOccurrence.FirstText);
+ return String.Concat(p.ToText(), "(", t, ")");
+ }
+ return null;
+ };
+ _CountColumn.AspectGetter = (object o) => {
+ if (o is XmlElement f) {
+ f.GetAttribute(Constants.FontOccurrence.Count).TryParse(out int p);
+ return p;
+ }
+ return null;
+ };
+ _FirstPageColumn.AspectGetter = (object o) => {
+ if (o is XmlElement f) {
+ f.GetAttribute(Constants.FontOccurrence.FirstPage).TryParse(out int p);
+ return p;
+ }
+ return null;
+ };
+ _ConditionColumn.AspectGetter = (object o) => o is AutoBookmarkCondition c ? c.Description : (object)null;
+
+ if (_fontInfo == null) {
+ FormHelper.ErrorBox("缺少字体信息。");
+ _OkButton.Enabled = false;
+ return;
+ }
+
+ var fonts = _fontInfo.SelectNodes(Constants.Font.ThisName + "[@" + Constants.Font.Name + " and " + Constants.Font.Size + "]");
+ var fi = new XmlElement[fonts.Count];
+ var i = 0;
+ foreach (XmlElement f in fonts) {
+ fi[i++] = f;
+ }
+ _FontInfoBox.AddObjects(fi);
+ foreach (XmlElement item in _FontInfoBox.Roots) {
+ _FontInfoBox.Expand(item);
+ }
+ if (_FontInfoBox.GetItemCount() > 0) {
+ _FontInfoBox.EnsureVisible(0);
+ _FontInfoBox.Sort(_CountColumn, SortOrder.Descending);
+ }
+ }
+
+ void _OkButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.OK;
+ if (_FilterBox.Items.Count > 0) {
+ FilterConditions = new AutoBookmarkCondition[_FilterBox.Items.Count];
+ for (int i = 0; i < FilterConditions.Length; i++) {
+ FilterConditions[i] = _FilterBox.GetModelObject(i) as AutoBookmarkCondition;
+ }
+ }
+ Close();
+ }
+
+ void _CancelButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ void _AddFilterMenu_Opening(object sender, CancelEventArgs e) {
+ if (_FontInfoBox.FocusedItem == null) {
+ if (_FontInfoBox.SelectedItem != null) {
+ _FontInfoBox.FocusedItem = _FontInfoBox.SelectedItem;
+ }
+ else {
+ e.Cancel = true;
+ return;
+ }
+ }
+ var f = _FontInfoBox.GetModelObject(_FontInfoBox.FocusedItem.Index) as XmlElement;
+ if (f == null) {
+ e.Cancel = true;
+ return;
+ }
+ var n = (f.ParentNode.Name == Constants.Font.ThisName ? (f.ParentNode as XmlElement) : f).GetAttribute(Constants.Font.Name);
+ if (String.IsNullOrEmpty(n)) {
+ e.Cancel = true;
+ return;
+ }
+ f.GetAttribute(Constants.Font.Size).TryParse(out float s);
+
+ _AddFilterMenu.Items.Clear();
+ var p = n.IndexOf('+');
+ var m = n.IndexOfAny(new char[] { '-', ',' }, p != -1 ? p : 0);
+ string fn;
+ if (p != -1) {
+ if (m > p + 1) {
+ fn = n.Substring(p + 1, m - p - 1);
+ if (s > 0) {
+ _AddFilterMenu.Items.Add("筛选名称包含“" + fn + "”且尺寸为" + s.ToText() + "的字体").Tag = new FilterSetting(fn, false, s);
+ }
+ else {
+ _AddFilterMenu.Items.Add("筛选名称包含“" + fn + "”的字体").Tag = new FilterSetting(fn, false, 0);
+ }
+ }
+ fn = n.Substring(p + 1);
+ if (s > 0) {
+ _AddFilterMenu.Items.Add("筛选名称包含“" + fn + "”且尺寸为" + s.ToText() + "的字体").Tag = new FilterSetting(fn, false, s);
+ }
+ else {
+ _AddFilterMenu.Items.Add("筛选名称包含“" + fn + "”的字体").Tag = new FilterSetting(fn, false, 0);
+ }
+ }
+ else if (p == -1 && m != -1) {
+ fn = n.Substring(0, m);
+ if (s > 0) {
+ _AddFilterMenu.Items.Add("筛选名称包含“" + fn + "”且尺寸为" + s.ToText() + "的字体").Tag = new FilterSetting(fn, false, s);
+ }
+ else {
+ _AddFilterMenu.Items.Add("筛选名称包含“" + fn + "”的字体").Tag = new FilterSetting(fn, false, 0);
+ }
+ }
+ if (_AddFilterMenu.Items.Count > 0) {
+ _AddFilterMenu.Items.Add(new ToolStripSeparator());
+ }
+ if (s > 0) {
+ _AddFilterMenu.Items.Add("筛选名称为“" + n + "”且尺寸为" + s.ToText() + "的字体").Tag = new FilterSetting(n, true, s);
+ }
+ else {
+ _AddFilterMenu.Items.Add("筛选名称为“" + n + "”的字体").Tag = new FilterSetting(n, true, 0);
+ }
+ e.Cancel = false;
+ }
+
+ void _AddFilterMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ var f = e.ClickedItem.Tag as FilterSetting;
+ if (f == null) {
+ return;
+ }
+ AutoBookmarkCondition fc = new AutoBookmarkCondition.FontNameCondition(f.FontName, f.FullMatch);
+ if (f.Size > 0) {
+ var m = new AutoBookmarkCondition.MultiCondition(fc);
+ m.Conditions.Add(new AutoBookmarkCondition.TextSizeCondition(f.Size));
+ fc = m;
+ }
+ _FilterBox.AddObject(fc);
+ }
+
+ void ControlEvent(object sender, EventArgs e) {
+ if (sender == _RemoveConditionButton) {
+ _FilterBox.RemoveObjects(_FilterBox.SelectedObjects);
+ }
+ else if (sender == _AddConditionButton) {
+ _AddFilterMenu.Show(_AddConditionButton, 0, _AddConditionButton.Height);
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.resx b/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..aecbf146ae251fd88464b8f6d8258ed42b2847a0
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/FontFilterForm.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 123, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d293c117c959e5cce39ba0ae48bb5af85002c349
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.Designer.cs
@@ -0,0 +1,83 @@
+namespace PDFPatcher.Functions
+{
+ partial class FontNameConditionEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.label1 = new System.Windows.Forms.Label ();
+ this._FontNameBox = new System.Windows.Forms.TextBox ();
+ this._FullMatchBox = new System.Windows.Forms.CheckBox ();
+ this.SuspendLayout ();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point (3, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size (89, 12);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "匹配字体名称:";
+ //
+ // _FontNameBox
+ //
+ this._FontNameBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._FontNameBox.Location = new System.Drawing.Point (98, 6);
+ this._FontNameBox.Name = "_FontNameBox";
+ this._FontNameBox.Size = new System.Drawing.Size (238, 21);
+ this._FontNameBox.TabIndex = 1;
+ this._FontNameBox.TextChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _FullMatchBox
+ //
+ this._FullMatchBox.AutoSize = true;
+ this._FullMatchBox.Location = new System.Drawing.Point (5, 33);
+ this._FullMatchBox.Name = "_FullMatchBox";
+ this._FullMatchBox.Size = new System.Drawing.Size (120, 16);
+ this._FullMatchBox.TabIndex = 2;
+ this._FullMatchBox.Text = "完全匹配字体名称";
+ this._FullMatchBox.UseVisualStyleBackColor = true;
+ this._FullMatchBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // FontNameFilterEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add (this._FullMatchBox);
+ this.Controls.Add (this._FontNameBox);
+ this.Controls.Add (this.label1);
+ this.Name = "FontNameFilterEditor";
+ this.Size = new System.Drawing.Size (339, 80);
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox _FontNameBox;
+ private System.Windows.Forms.CheckBox _FullMatchBox;
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.cs b/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4489431a8f9d2a2bb2506a4649aedfc6355430be
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.cs
@@ -0,0 +1,48 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ [ToolboxItem(false)]
+ sealed partial class FontNameConditionEditor : UserControl, IFilterConditionEditor
+ {
+ AutoBookmarkCondition.FontNameCondition _filter;
+ bool _lock;
+
+ public FontNameConditionEditor() {
+ InitializeComponent();
+ }
+
+ #region ITextInfoFilterEditor 成员
+ public UserControl EditorControl => this;
+
+ public AutoBookmarkCondition Filter {
+ get => _filter;
+ set {
+ _filter = (AutoBookmarkCondition.FontNameCondition)value;
+ _lock = true;
+ _FontNameBox.Text = _filter.FontName;
+ _FullMatchBox.Checked = _filter.MatchFullName;
+ _lock = false;
+ }
+ }
+
+ #endregion
+
+ void ControlChanged(object sender, EventArgs e) {
+ if (_lock) {
+ return;
+ }
+
+ if (sender == _FontNameBox) {
+ _filter.FontName = _FontNameBox.Text;
+ }
+ else if (sender == _FullMatchBox) {
+ _filter.MatchFullName = _FullMatchBox.Checked;
+ }
+ EditAdjustmentForm.UpdateFilter(this);
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.resx b/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/FontNameConditionEditor.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..23176aca9e650e08aa11fdbc28856e4d43e6f592
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.Designer.cs
@@ -0,0 +1,71 @@
+namespace PDFPatcher.Functions
+{
+ partial class PageRangeConditionEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.label1 = new System.Windows.Forms.Label ();
+ this._PageRangeBox = new System.Windows.Forms.TextBox ();
+ this.SuspendLayout ();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point (3, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size (89, 12);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "匹配页码范围:";
+ //
+ // _PageRangeBox
+ //
+ this._PageRangeBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PageRangeBox.Location = new System.Drawing.Point (98, 6);
+ this._PageRangeBox.Name = "_PageRangeBox";
+ this._PageRangeBox.Size = new System.Drawing.Size (237, 21);
+ this._PageRangeBox.TabIndex = 1;
+ this._PageRangeBox.TextChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // PageNumberConditionEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add (this._PageRangeBox);
+ this.Controls.Add (this.label1);
+ this.Name = "PageNumberConditionEditor";
+ this.Size = new System.Drawing.Size (338, 71);
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox _PageRangeBox;
+
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.cs b/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9e7217aa300374f688e4e9b11a73307e72bb97fd
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.cs
@@ -0,0 +1,40 @@
+using System;
+using System.Windows.Forms;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class PageRangeConditionEditor : UserControl, IFilterConditionEditor
+ {
+ AutoBookmarkCondition.PageRangeCondition _condition;
+ bool _lock;
+
+ public PageRangeConditionEditor() {
+ InitializeComponent();
+ }
+
+ #region ITextInfoFilterEditor 成员
+
+ public AutoBookmarkCondition Filter {
+ get => _condition;
+ set {
+ _condition = (AutoBookmarkCondition.PageRangeCondition)value;
+ _lock = true;
+ _PageRangeBox.Text = _condition.PageRange;
+ _lock = false;
+ }
+ }
+
+ public UserControl EditorControl => this;
+
+ #endregion
+
+ void ControlChanged(object sender, EventArgs e) {
+ if (_lock) {
+ return;
+ }
+ _condition.PageRange = _PageRangeBox.Text;
+ EditAdjustmentForm.UpdateFilter(this);
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.resx b/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/PageRangeConditionEditor.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..e74bbedca784aa02cc3f7246a36e5f68b1954e20
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.Designer.cs
@@ -0,0 +1,111 @@
+namespace PDFPatcher.Functions
+{
+ partial class TextConditionEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.label1 = new System.Windows.Forms.Label ();
+ this._PatternBox = new System.Windows.Forms.TextBox ();
+ this._FullMatchBox = new System.Windows.Forms.CheckBox ();
+ this._MatchCaseBox = new System.Windows.Forms.CheckBox ();
+ this._UseRegexBox = new System.Windows.Forms.CheckBox ();
+ this.SuspendLayout ();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point (3, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size (89, 12);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "匹配文本内容:";
+ //
+ // _PatternBox
+ //
+ this._PatternBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PatternBox.Location = new System.Drawing.Point (98, 6);
+ this._PatternBox.Name = "_PatternBox";
+ this._PatternBox.Size = new System.Drawing.Size (238, 21);
+ this._PatternBox.TabIndex = 1;
+ this._PatternBox.TextChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _FullMatchBox
+ //
+ this._FullMatchBox.AutoSize = true;
+ this._FullMatchBox.Location = new System.Drawing.Point (5, 33);
+ this._FullMatchBox.Name = "_FullMatchBox";
+ this._FullMatchBox.Size = new System.Drawing.Size (72, 16);
+ this._FullMatchBox.TabIndex = 2;
+ this._FullMatchBox.Text = "完全匹配";
+ this._FullMatchBox.UseVisualStyleBackColor = true;
+ this._FullMatchBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _MatchCaseBox
+ //
+ this._MatchCaseBox.AutoSize = true;
+ this._MatchCaseBox.Location = new System.Drawing.Point (98, 33);
+ this._MatchCaseBox.Name = "_MatchCaseBox";
+ this._MatchCaseBox.Size = new System.Drawing.Size (108, 16);
+ this._MatchCaseBox.TabIndex = 3;
+ this._MatchCaseBox.Text = "匹配英文大小写";
+ this._MatchCaseBox.UseVisualStyleBackColor = true;
+ this._MatchCaseBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _UseRegexBox
+ //
+ this._UseRegexBox.AutoSize = true;
+ this._UseRegexBox.Location = new System.Drawing.Point (212, 33);
+ this._UseRegexBox.Name = "_UseRegexBox";
+ this._UseRegexBox.Size = new System.Drawing.Size (108, 16);
+ this._UseRegexBox.TabIndex = 4;
+ this._UseRegexBox.Text = "使用正则表达式";
+ this._UseRegexBox.UseVisualStyleBackColor = true;
+ this._UseRegexBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // TextConditionEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add (this._UseRegexBox);
+ this.Controls.Add (this._MatchCaseBox);
+ this.Controls.Add (this._FullMatchBox);
+ this.Controls.Add (this._PatternBox);
+ this.Controls.Add (this.label1);
+ this.Name = "TextConditionEditor";
+ this.Size = new System.Drawing.Size (339, 80);
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox _PatternBox;
+ private System.Windows.Forms.CheckBox _FullMatchBox;
+ private System.Windows.Forms.CheckBox _MatchCaseBox;
+ private System.Windows.Forms.CheckBox _UseRegexBox;
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.cs b/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..0e07173831f355ed220028d102c8215a1f5a1226
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.cs
@@ -0,0 +1,56 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ [ToolboxItem(false)]
+ sealed partial class TextConditionEditor : UserControl, IFilterConditionEditor
+ {
+ AutoBookmarkCondition.TextCondition _filter;
+ bool _lock;
+
+ public TextConditionEditor() {
+ InitializeComponent();
+ }
+
+ #region ITextInfoFilterEditor 成员
+ public UserControl EditorControl => this;
+
+ public AutoBookmarkCondition Filter {
+ get => _filter;
+ set {
+ _filter = (AutoBookmarkCondition.TextCondition)value;
+ _lock = true;
+ _PatternBox.Text = _filter.Pattern.Text;
+ _FullMatchBox.Checked = _filter.Pattern.FullMatch;
+ _MatchCaseBox.Checked = _filter.Pattern.MatchCase;
+ _UseRegexBox.Checked = _filter.Pattern.UseRegularExpression;
+ _lock = false;
+ }
+ }
+
+ #endregion
+
+ void ControlChanged(object sender, EventArgs e) {
+ if (_lock) {
+ return;
+ }
+
+ if (sender == _PatternBox) {
+ _filter.Pattern.Text = _PatternBox.Text;
+ }
+ else if (sender == _FullMatchBox) {
+ _filter.Pattern.FullMatch = _FullMatchBox.Checked;
+ }
+ else if (sender == _MatchCaseBox) {
+ _filter.Pattern.MatchCase = _MatchCaseBox.Checked;
+ }
+ else if (sender == _UseRegexBox) {
+ _filter.Pattern.UseRegularExpression = _UseRegexBox.Checked;
+ }
+ EditAdjustmentForm.UpdateFilter(this);
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.resx b/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextConditionEditor.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1908d7995d77a20c6f46a215805e48ee8321bad9
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.Designer.cs
@@ -0,0 +1,204 @@
+namespace PDFPatcher.Functions
+{
+ partial class TextPositionConditionEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.panel2 = new System.Windows.Forms.Panel ();
+ this.label2 = new System.Windows.Forms.Label ();
+ this._PositionBox = new System.Windows.Forms.ComboBox ();
+ this._RangeBox = new System.Windows.Forms.RadioButton ();
+ this._SpecificValueBox = new System.Windows.Forms.NumericUpDown ();
+ this._SpecificBox = new System.Windows.Forms.RadioButton ();
+ this._MinBox = new System.Windows.Forms.NumericUpDown ();
+ this.label1 = new System.Windows.Forms.Label ();
+ this._MaxBox = new System.Windows.Forms.NumericUpDown ();
+ this.panel2.SuspendLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._SpecificValueBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._MinBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._MaxBox)).BeginInit ();
+ this.SuspendLayout ();
+ //
+ // panel2
+ //
+ this.panel2.Controls.Add (this.label2);
+ this.panel2.Controls.Add (this._PositionBox);
+ this.panel2.Controls.Add (this._RangeBox);
+ this.panel2.Controls.Add (this._SpecificValueBox);
+ this.panel2.Controls.Add (this._SpecificBox);
+ this.panel2.Controls.Add (this._MinBox);
+ this.panel2.Controls.Add (this.label1);
+ this.panel2.Controls.Add (this._MaxBox);
+ this.panel2.Location = new System.Drawing.Point (3, 0);
+ this.panel2.Name = "panel2";
+ this.panel2.Size = new System.Drawing.Size (377, 88);
+ this.panel2.TabIndex = 5;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point (21, 6);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size (101, 12);
+ this.label2.TabIndex = 5;
+ this.label2.Text = "匹配文本块的坐标";
+ //
+ // _PositionBox
+ //
+ this._PositionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._PositionBox.FormattingEnabled = true;
+ this._PositionBox.Items.AddRange (new object[] {
+ "上坐标",
+ "下坐标",
+ "左坐标",
+ "右坐标"});
+ this._PositionBox.Location = new System.Drawing.Point (135, 3);
+ this._PositionBox.Name = "_PositionBox";
+ this._PositionBox.Size = new System.Drawing.Size (121, 20);
+ this._PositionBox.TabIndex = 4;
+ this._PositionBox.SelectedIndexChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _RangeBox
+ //
+ this._RangeBox.AutoSize = true;
+ this._RangeBox.Location = new System.Drawing.Point (23, 56);
+ this._RangeBox.Name = "_RangeBox";
+ this._RangeBox.Size = new System.Drawing.Size (95, 16);
+ this._RangeBox.TabIndex = 3;
+ this._RangeBox.TabStop = true;
+ this._RangeBox.Text = "匹配坐标范围";
+ this._RangeBox.UseVisualStyleBackColor = true;
+ this._RangeBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _SpecificValueBox
+ //
+ this._SpecificValueBox.DecimalPlaces = 2;
+ this._SpecificValueBox.Location = new System.Drawing.Point (135, 29);
+ this._SpecificValueBox.Maximum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._SpecificValueBox.Minimum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ -2147483648});
+ this._SpecificValueBox.Name = "_SpecificValueBox";
+ this._SpecificValueBox.Size = new System.Drawing.Size (67, 21);
+ this._SpecificValueBox.TabIndex = 1;
+ this._SpecificValueBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._SpecificValueBox.ValueChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _SpecificBox
+ //
+ this._SpecificBox.AutoSize = true;
+ this._SpecificBox.Location = new System.Drawing.Point (23, 29);
+ this._SpecificBox.Name = "_SpecificBox";
+ this._SpecificBox.Size = new System.Drawing.Size (107, 16);
+ this._SpecificBox.TabIndex = 3;
+ this._SpecificBox.TabStop = true;
+ this._SpecificBox.Text = "匹配特定坐标值";
+ this._SpecificBox.UseVisualStyleBackColor = true;
+ this._SpecificBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _MinBox
+ //
+ this._MinBox.DecimalPlaces = 2;
+ this._MinBox.Location = new System.Drawing.Point (135, 56);
+ this._MinBox.Maximum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._MinBox.Minimum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ -2147483648});
+ this._MinBox.Name = "_MinBox";
+ this._MinBox.Size = new System.Drawing.Size (67, 21);
+ this._MinBox.TabIndex = 1;
+ this._MinBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._MinBox.ValueChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point (208, 58);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size (17, 12);
+ this.label1.TabIndex = 2;
+ this.label1.Text = "到";
+ //
+ // _MaxBox
+ //
+ this._MaxBox.DecimalPlaces = 2;
+ this._MaxBox.Location = new System.Drawing.Point (231, 56);
+ this._MaxBox.Maximum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._MaxBox.Minimum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ -2147483648});
+ this._MaxBox.Name = "_MaxBox";
+ this._MaxBox.Size = new System.Drawing.Size (67, 21);
+ this._MaxBox.TabIndex = 1;
+ this._MaxBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._MaxBox.ValueChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // TextPositionConditionEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add (this.panel2);
+ this.Name = "TextPositionConditionEditor";
+ this.Size = new System.Drawing.Size (383, 88);
+ this.panel2.ResumeLayout (false);
+ this.panel2.PerformLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._SpecificValueBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._MinBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._MaxBox)).EndInit ();
+ this.ResumeLayout (false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Panel panel2;
+ private System.Windows.Forms.RadioButton _RangeBox;
+ private System.Windows.Forms.NumericUpDown _SpecificValueBox;
+ private System.Windows.Forms.RadioButton _SpecificBox;
+ private System.Windows.Forms.NumericUpDown _MinBox;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.NumericUpDown _MaxBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.ComboBox _PositionBox;
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.cs b/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..012d0285248fbcad40ee08f8475ccfa1ed0147b7
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.cs
@@ -0,0 +1,67 @@
+using System;
+using System.Windows.Forms;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class TextPositionConditionEditor : UserControl, IFilterConditionEditor
+ {
+ AutoBookmarkCondition.TextPositionCondition _condition;
+ bool _lock;
+
+ public TextPositionConditionEditor() {
+ InitializeComponent();
+ _lock = true;
+ _PositionBox.SelectedIndex = 0;
+ _lock = false;
+ }
+
+ #region ITextInfoFilterEditor 成员
+
+ public AutoBookmarkCondition Filter {
+ get => _condition;
+ set {
+ _condition = (AutoBookmarkCondition.TextPositionCondition)value;
+ _lock = true;
+ _PositionBox.SelectedIndex = _condition.Position - 1;
+ if (_condition.MinValue == _condition.MaxValue) {
+ _SpecificBox.Checked = true;
+ _SpecificValueBox.Value = (decimal)_condition.MaxValue;
+ }
+ else {
+ _RangeBox.Checked = true;
+ _MaxBox.Value = (decimal)_condition.MaxValue;
+ _MinBox.Value = (decimal)_condition.MinValue;
+ }
+ ToggleControlState();
+ _lock = false;
+ }
+ }
+
+ public UserControl EditorControl => this;
+
+ #endregion
+
+ void ControlChanged(object sender, EventArgs e) {
+ ToggleControlState();
+ if (_lock) {
+ return;
+ }
+ float min, max;
+ if (_SpecificBox.Checked) {
+ min = max = (float)_SpecificValueBox.Value;
+ }
+ else /*if (_YRangeBox.Checked)*/ {
+ min = (float)_MinBox.Value;
+ max = (float)_MaxBox.Value;
+ }
+ _condition.SetRange((byte)(_PositionBox.SelectedIndex + 1), min, max);
+ EditAdjustmentForm.UpdateFilter(this);
+ }
+
+ void ToggleControlState() {
+ _MinBox.Enabled = _MaxBox.Enabled = _RangeBox.Checked;
+ _SpecificValueBox.Enabled = _SpecificBox.Checked;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.resx b/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextPositionConditionEditor.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.Designer.cs b/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2ac566693bcc818b4978d6a5132d968959bdb80a
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.Designer.cs
@@ -0,0 +1,147 @@
+namespace PDFPatcher.Functions
+{
+ partial class TextSizeConditionEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this._MinSizeBox = new System.Windows.Forms.NumericUpDown ();
+ this._MaxSizeBox = new System.Windows.Forms.NumericUpDown ();
+ this.label2 = new System.Windows.Forms.Label ();
+ this._SizeBox = new System.Windows.Forms.RadioButton ();
+ this._SpecificSizeBox = new System.Windows.Forms.NumericUpDown ();
+ this._SizeRangeBox = new System.Windows.Forms.RadioButton ();
+ ((System.ComponentModel.ISupportInitialize)(this._MinSizeBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._MaxSizeBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._SpecificSizeBox)).BeginInit ();
+ this.SuspendLayout ();
+ //
+ // _MinSizeBox
+ //
+ this._MinSizeBox.DecimalPlaces = 2;
+ this._MinSizeBox.Location = new System.Drawing.Point (128, 30);
+ this._MinSizeBox.Maximum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._MinSizeBox.Name = "_MinSizeBox";
+ this._MinSizeBox.Size = new System.Drawing.Size (67, 21);
+ this._MinSizeBox.TabIndex = 1;
+ this._MinSizeBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._MinSizeBox.ValueChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _MaxSizeBox
+ //
+ this._MaxSizeBox.DecimalPlaces = 2;
+ this._MaxSizeBox.Location = new System.Drawing.Point (224, 30);
+ this._MaxSizeBox.Maximum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._MaxSizeBox.Name = "_MaxSizeBox";
+ this._MaxSizeBox.Size = new System.Drawing.Size (67, 21);
+ this._MaxSizeBox.TabIndex = 1;
+ this._MaxSizeBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._MaxSizeBox.ValueChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point (201, 32);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size (17, 12);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "到";
+ //
+ // _SizeBox
+ //
+ this._SizeBox.AutoSize = true;
+ this._SizeBox.Location = new System.Drawing.Point (3, 3);
+ this._SizeBox.Name = "_SizeBox";
+ this._SizeBox.Size = new System.Drawing.Size (119, 16);
+ this._SizeBox.TabIndex = 3;
+ this._SizeBox.TabStop = true;
+ this._SizeBox.Text = "匹配特定文本尺寸";
+ this._SizeBox.UseVisualStyleBackColor = true;
+ this._SizeBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _SpecificSizeBox
+ //
+ this._SpecificSizeBox.DecimalPlaces = 2;
+ this._SpecificSizeBox.Location = new System.Drawing.Point (128, 3);
+ this._SpecificSizeBox.Maximum = new decimal (new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._SpecificSizeBox.Name = "_SpecificSizeBox";
+ this._SpecificSizeBox.Size = new System.Drawing.Size (67, 21);
+ this._SpecificSizeBox.TabIndex = 1;
+ this._SpecificSizeBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._SpecificSizeBox.ValueChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // _SizeRangeBox
+ //
+ this._SizeRangeBox.AutoSize = true;
+ this._SizeRangeBox.Location = new System.Drawing.Point (3, 30);
+ this._SizeRangeBox.Name = "_SizeRangeBox";
+ this._SizeRangeBox.Size = new System.Drawing.Size (119, 16);
+ this._SizeRangeBox.TabIndex = 3;
+ this._SizeRangeBox.TabStop = true;
+ this._SizeRangeBox.Text = "匹配文本尺寸范围";
+ this._SizeRangeBox.UseVisualStyleBackColor = true;
+ this._SizeRangeBox.CheckedChanged += new System.EventHandler (this.ControlChanged);
+ //
+ // FontSizeFilterEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add (this._SizeRangeBox);
+ this.Controls.Add (this._SizeBox);
+ this.Controls.Add (this.label2);
+ this.Controls.Add (this._MaxSizeBox);
+ this.Controls.Add (this._SpecificSizeBox);
+ this.Controls.Add (this._MinSizeBox);
+ this.Name = "FontSizeFilterEditor";
+ this.Size = new System.Drawing.Size (338, 71);
+ ((System.ComponentModel.ISupportInitialize)(this._MinSizeBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._MaxSizeBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._SpecificSizeBox)).EndInit ();
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.NumericUpDown _MinSizeBox;
+ private System.Windows.Forms.NumericUpDown _MaxSizeBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.RadioButton _SizeBox;
+ private System.Windows.Forms.NumericUpDown _SpecificSizeBox;
+ private System.Windows.Forms.RadioButton _SizeRangeBox;
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.cs b/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..ffa9e71ee3584f12762be9c4560e98c63e545b61
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.cs
@@ -0,0 +1,60 @@
+using System;
+using System.Windows.Forms;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class TextSizeConditionEditor : UserControl, IFilterConditionEditor
+ {
+ AutoBookmarkCondition.TextSizeCondition _condition;
+ bool _lock;
+
+ public TextSizeConditionEditor() {
+ InitializeComponent();
+ }
+
+ #region ITextInfoFilterEditor 成员
+
+ public AutoBookmarkCondition Filter {
+ get => _condition;
+ set {
+ _condition = (AutoBookmarkCondition.TextSizeCondition)value;
+ _lock = true;
+ if (_condition.MinSize == _condition.MaxSize) {
+ _SizeBox.Checked = true;
+ _SpecificSizeBox.Value = (decimal)_condition.MaxSize;
+ }
+ else {
+ _SizeRangeBox.Checked = true;
+ _MaxSizeBox.Value = (decimal)_condition.MaxSize;
+ _MinSizeBox.Value = (decimal)_condition.MinSize;
+ }
+ ToggleControlState();
+ _lock = false;
+ }
+ }
+
+ public UserControl EditorControl => this;
+
+ #endregion
+
+ void ControlChanged(object sender, EventArgs e) {
+ ToggleControlState();
+ if (_lock) {
+ return;
+ }
+ if (_SizeBox.Checked) {
+ _condition.SetRange((float)_SpecificSizeBox.Value, (float)_SpecificSizeBox.Value);
+ }
+ else if (_SizeRangeBox.Checked) {
+ _condition.SetRange((float)_MinSizeBox.Value, (float)_MaxSizeBox.Value);
+ }
+ EditAdjustmentForm.UpdateFilter(this);
+ }
+
+ void ToggleControlState() {
+ _MinSizeBox.Enabled = _MaxSizeBox.Enabled = _SizeRangeBox.Checked;
+ _SpecificSizeBox.Enabled = _SizeBox.Checked;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.resx b/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmark/TextSizeConditionEditor.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/AutoBookmarkControl.Designer.cs b/pdfpatcher/App/Functions/AutoBookmarkControl.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b1b2680c20dbd710394c864af6ca78d5217d0812
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmarkControl.Designer.cs
@@ -0,0 +1,851 @@
+namespace PDFPatcher.Functions
+{
+ partial class AutoBookmarkControl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.ToolStripDropDownButton _AddAdjustmentButton;
+ System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle1 = new System.Windows.Forms.DataGridViewCellStyle();
+ System.Windows.Forms.DataGridViewCellStyle dataGridViewCellStyle2 = new System.Windows.Forms.DataGridViewCellStyle();
+ this._AddFilterMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this._TitleSizeThresholdBox = new System.Windows.Forms.NumericUpDown();
+ this.label2 = new System.Windows.Forms.Label();
+ this.label3 = new System.Windows.Forms.Label();
+ this._PageRangeBox = new System.Windows.Forms.TextBox();
+ this._MergeAdjacentTitlesBox = new System.Windows.Forms.CheckBox();
+ this._MergeDifferentSizeTitlesBox = new System.Windows.Forms.CheckBox();
+ this.tabControl1 = new System.Windows.Forms.TabControl();
+ this.tabPage1 = new System.Windows.Forms.TabPage();
+ this._FirstLineAsTitleBox = new System.Windows.Forms.CheckBox();
+ this._IgnoreOverlappedTextBox = new System.Windows.Forms.CheckBox();
+ this._CreateBookmarkForFirstPageBox = new System.Windows.Forms.CheckBox();
+ this.label6 = new System.Windows.Forms.Label();
+ this.label5 = new System.Windows.Forms.Label();
+ this._WritingDirectionBox = new System.Windows.Forms.ComboBox();
+ this._AutoHierarchicalArrangementBox = new System.Windows.Forms.CheckBox();
+ this.label11 = new System.Windows.Forms.Label();
+ this._MaxDistanceBetweenLinesBox = new System.Windows.Forms.NumericUpDown();
+ this._GoToPageTopLevelBox = new System.Windows.Forms.NumericUpDown();
+ this.label7 = new System.Windows.Forms.Label();
+ this.label9 = new System.Windows.Forms.Label();
+ this.label4 = new System.Windows.Forms.Label();
+ this._YOffsetBox = new System.Windows.Forms.NumericUpDown();
+ this._MergeDifferentFontTitlesBox = new System.Windows.Forms.CheckBox();
+ this.tabPage2 = new System.Windows.Forms.TabPage();
+ this._IgnoreNumericTitleBox = new System.Windows.Forms.CheckBox();
+ this._IgnoreSingleCharacterTitleBox = new System.Windows.Forms.CheckBox();
+ this._ClearTextFiltersButton = new System.Windows.Forms.Button();
+ this._IgnorePatternsBox = new System.Windows.Forms.DataGridView();
+ this._PatternColumn = new System.Windows.Forms.DataGridViewTextBoxColumn();
+ this._MatchCaseColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this._FullMatchColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this._PatternTypeColumn = new System.Windows.Forms.DataGridViewCheckBoxColumn();
+ this._RemovePatternColumn = new System.Windows.Forms.DataGridViewLinkColumn();
+ this.label10 = new System.Windows.Forms.Label();
+ this.tabPage3 = new System.Windows.Forms.TabPage();
+ this._FilterToolbar = new System.Windows.Forms.ToolStrip();
+ this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
+ this._AddFilterFromInfoFileButton = new System.Windows.Forms.ToolStripButton();
+ this._DeleteAdjustmentButton = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this._CopyFilterButton = new System.Windows.Forms.ToolStripButton();
+ this._PasteButton = new System.Windows.Forms.ToolStripButton();
+ this._LevelAdjustmentBox = new BrightIdeasSoftware.ObjectListView();
+ this._AdvancedFilterColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._AdjustmentLevelColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._RelativeAdjustmentColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._FilterBeforeMergeColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this.label12 = new System.Windows.Forms.Label();
+ this.tabPage5 = new System.Windows.Forms.TabPage();
+ this._ExportTextCoordinateBox = new System.Windows.Forms.CheckBox();
+ this._ShowAllFontsBox = new System.Windows.Forms.CheckBox();
+ this._DisplayFontStatisticsBox = new System.Windows.Forms.CheckBox();
+ this._BookmarkControl = new PDFPatcher.BookmarkControl();
+ this._SourceFileControl = new PDFPatcher.SourceFileControl();
+ this._ExportBookmarkButton = new EnhancedGlassButton.GlassButton();
+ _AddAdjustmentButton = new System.Windows.Forms.ToolStripDropDownButton();
+ ((System.ComponentModel.ISupportInitialize)(this._TitleSizeThresholdBox)).BeginInit();
+ this.tabControl1.SuspendLayout();
+ this.tabPage1.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._MaxDistanceBetweenLinesBox)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this._GoToPageTopLevelBox)).BeginInit();
+ ((System.ComponentModel.ISupportInitialize)(this._YOffsetBox)).BeginInit();
+ this.tabPage2.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._IgnorePatternsBox)).BeginInit();
+ this.tabPage3.SuspendLayout();
+ this._FilterToolbar.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._LevelAdjustmentBox)).BeginInit();
+ this.tabPage5.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _AddAdjustmentButton
+ //
+ _AddAdjustmentButton.DropDown = this._AddFilterMenu;
+ _AddAdjustmentButton.Image = global::PDFPatcher.Properties.Resources.Add;
+ _AddAdjustmentButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ _AddAdjustmentButton.Name = "_AddAdjustmentButton";
+ _AddAdjustmentButton.Size = new System.Drawing.Size(61, 22);
+ _AddAdjustmentButton.Text = "添加";
+ //
+ // _AddFilterMenu
+ //
+ this._AddFilterMenu.Name = "_AddFilterMenu";
+ this._AddFilterMenu.Size = new System.Drawing.Size(61, 4);
+ this._AddFilterMenu.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this._AddFilterMenu_ItemClicked);
+ //
+ // _TitleSizeThresholdBox
+ //
+ this._TitleSizeThresholdBox.DecimalPlaces = 2;
+ this._TitleSizeThresholdBox.Location = new System.Drawing.Point(98, 36);
+ this._TitleSizeThresholdBox.Maximum = new decimal(new int[] {
+ 9999,
+ 0,
+ 0,
+ 0});
+ this._TitleSizeThresholdBox.Name = "_TitleSizeThresholdBox";
+ this._TitleSizeThresholdBox.Size = new System.Drawing.Size(68, 21);
+ this._TitleSizeThresholdBox.TabIndex = 3;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(3, 38);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(89, 12);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "标题文本尺寸:";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(3, 12);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(89, 12);
+ this.label3.TabIndex = 0;
+ this.label3.Text = "识别页码范围:";
+ //
+ // _PageRangeBox
+ //
+ this._PageRangeBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PageRangeBox.Location = new System.Drawing.Point(98, 9);
+ this._PageRangeBox.Name = "_PageRangeBox";
+ this._PageRangeBox.Size = new System.Drawing.Size(321, 21);
+ this._PageRangeBox.TabIndex = 1;
+ //
+ // _MergeAdjacentTitlesBox
+ //
+ this._MergeAdjacentTitlesBox.AutoSize = true;
+ this._MergeAdjacentTitlesBox.Location = new System.Drawing.Point(6, 84);
+ this._MergeAdjacentTitlesBox.Name = "_MergeAdjacentTitlesBox";
+ this._MergeAdjacentTitlesBox.Size = new System.Drawing.Size(132, 16);
+ this._MergeAdjacentTitlesBox.TabIndex = 10;
+ this._MergeAdjacentTitlesBox.Text = "合并连续出现的标题";
+ this._MergeAdjacentTitlesBox.UseVisualStyleBackColor = true;
+ //
+ // _MergeDifferentSizeTitlesBox
+ //
+ this._MergeDifferentSizeTitlesBox.AutoSize = true;
+ this._MergeDifferentSizeTitlesBox.Location = new System.Drawing.Point(6, 105);
+ this._MergeDifferentSizeTitlesBox.Name = "_MergeDifferentSizeTitlesBox";
+ this._MergeDifferentSizeTitlesBox.Size = new System.Drawing.Size(156, 16);
+ this._MergeDifferentSizeTitlesBox.TabIndex = 14;
+ this._MergeDifferentSizeTitlesBox.Text = "合并不同文本尺寸的标题";
+ this._MergeDifferentSizeTitlesBox.UseVisualStyleBackColor = true;
+ //
+ // tabControl1
+ //
+ this.tabControl1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.tabControl1.Controls.Add(this.tabPage1);
+ this.tabControl1.Controls.Add(this.tabPage2);
+ this.tabControl1.Controls.Add(this.tabPage3);
+ this.tabControl1.Controls.Add(this.tabPage5);
+ this.tabControl1.Location = new System.Drawing.Point(12, 93);
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size(463, 229);
+ this.tabControl1.TabIndex = 4;
+ //
+ // tabPage1
+ //
+ this.tabPage1.Controls.Add(this._FirstLineAsTitleBox);
+ this.tabPage1.Controls.Add(this._IgnoreOverlappedTextBox);
+ this.tabPage1.Controls.Add(this._CreateBookmarkForFirstPageBox);
+ this.tabPage1.Controls.Add(this.label6);
+ this.tabPage1.Controls.Add(this.label5);
+ this.tabPage1.Controls.Add(this._WritingDirectionBox);
+ this.tabPage1.Controls.Add(this._AutoHierarchicalArrangementBox);
+ this.tabPage1.Controls.Add(this.label11);
+ this.tabPage1.Controls.Add(this._MaxDistanceBetweenLinesBox);
+ this.tabPage1.Controls.Add(this._GoToPageTopLevelBox);
+ this.tabPage1.Controls.Add(this.label7);
+ this.tabPage1.Controls.Add(this.label9);
+ this.tabPage1.Controls.Add(this.label4);
+ this.tabPage1.Controls.Add(this._YOffsetBox);
+ this.tabPage1.Controls.Add(this._MergeDifferentFontTitlesBox);
+ this.tabPage1.Controls.Add(this._MergeDifferentSizeTitlesBox);
+ this.tabPage1.Controls.Add(this.label3);
+ this.tabPage1.Controls.Add(this._TitleSizeThresholdBox);
+ this.tabPage1.Controls.Add(this.label2);
+ this.tabPage1.Controls.Add(this._MergeAdjacentTitlesBox);
+ this.tabPage1.Controls.Add(this._PageRangeBox);
+ this.tabPage1.Location = new System.Drawing.Point(4, 22);
+ this.tabPage1.Name = "tabPage1";
+ this.tabPage1.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
+ this.tabPage1.Size = new System.Drawing.Size(455, 203);
+ this.tabPage1.TabIndex = 0;
+ this.tabPage1.Text = "标题识别";
+ this.tabPage1.UseVisualStyleBackColor = true;
+ //
+ // _FirstLineAsTitleBox
+ //
+ this._FirstLineAsTitleBox.AutoSize = true;
+ this._FirstLineAsTitleBox.Location = new System.Drawing.Point(6, 170);
+ this._FirstLineAsTitleBox.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2);
+ this._FirstLineAsTitleBox.Name = "_FirstLineAsTitleBox";
+ this._FirstLineAsTitleBox.Size = new System.Drawing.Size(168, 16);
+ this._FirstLineAsTitleBox.TabIndex = 20;
+ this._FirstLineAsTitleBox.Text = "将每页第一行文本作为标题";
+ this._FirstLineAsTitleBox.UseVisualStyleBackColor = true;
+ //
+ // _IgnoreOverlappedTextBox
+ //
+ this._IgnoreOverlappedTextBox.AutoSize = true;
+ this._IgnoreOverlappedTextBox.Location = new System.Drawing.Point(6, 149);
+ this._IgnoreOverlappedTextBox.Name = "_IgnoreOverlappedTextBox";
+ this._IgnoreOverlappedTextBox.Size = new System.Drawing.Size(108, 16);
+ this._IgnoreOverlappedTextBox.TabIndex = 18;
+ this._IgnoreOverlappedTextBox.Text = "忽略重叠的文本";
+ this._IgnoreOverlappedTextBox.UseVisualStyleBackColor = true;
+ //
+ // _CreateBookmarkForFirstPageBox
+ //
+ this._CreateBookmarkForFirstPageBox.AutoSize = true;
+ this._CreateBookmarkForFirstPageBox.Location = new System.Drawing.Point(200, 143);
+ this._CreateBookmarkForFirstPageBox.Name = "_CreateBookmarkForFirstPageBox";
+ this._CreateBookmarkForFirstPageBox.Size = new System.Drawing.Size(132, 16);
+ this._CreateBookmarkForFirstPageBox.TabIndex = 19;
+ this._CreateBookmarkForFirstPageBox.Text = "文件名作为首页书签";
+ this._CreateBookmarkForFirstPageBox.UseVisualStyleBackColor = true;
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(198, 91);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(113, 12);
+ this.label6.TabIndex = 11;
+ this.label6.Text = "合并连续标题不大于";
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(198, 66);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(89, 12);
+ this.label5.TabIndex = 8;
+ this.label5.Text = "文字排版方向:";
+ //
+ // _WritingDirectionBox
+ //
+ this._WritingDirectionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._WritingDirectionBox.FormattingEnabled = true;
+ this._WritingDirectionBox.Items.AddRange(new object[] {
+ "自动检测",
+ "横向",
+ "纵向"});
+ this._WritingDirectionBox.Location = new System.Drawing.Point(293, 63);
+ this._WritingDirectionBox.Name = "_WritingDirectionBox";
+ this._WritingDirectionBox.Size = new System.Drawing.Size(76, 20);
+ this._WritingDirectionBox.TabIndex = 9;
+ //
+ // _AutoHierarchicalArrangementBox
+ //
+ this._AutoHierarchicalArrangementBox.AutoSize = true;
+ this._AutoHierarchicalArrangementBox.Location = new System.Drawing.Point(6, 63);
+ this._AutoHierarchicalArrangementBox.Name = "_AutoHierarchicalArrangementBox";
+ this._AutoHierarchicalArrangementBox.Size = new System.Drawing.Size(120, 16);
+ this._AutoHierarchicalArrangementBox.TabIndex = 7;
+ this._AutoHierarchicalArrangementBox.Text = "自动组织标题层次";
+ this._AutoHierarchicalArrangementBox.UseVisualStyleBackColor = true;
+ //
+ // label11
+ //
+ this.label11.AutoSize = true;
+ this.label11.Location = new System.Drawing.Point(250, 118);
+ this.label11.Name = "label11";
+ this.label11.Size = new System.Drawing.Size(101, 12);
+ this.label11.TabIndex = 17;
+ this.label11.Text = "层标题定位到页首";
+ //
+ // _MaxDistanceBetweenLinesBox
+ //
+ this._MaxDistanceBetweenLinesBox.DecimalPlaces = 2;
+ this._MaxDistanceBetweenLinesBox.Location = new System.Drawing.Point(317, 89);
+ this._MaxDistanceBetweenLinesBox.Maximum = new decimal(new int[] {
+ 9,
+ 0,
+ 0,
+ 0});
+ this._MaxDistanceBetweenLinesBox.Name = "_MaxDistanceBetweenLinesBox";
+ this._MaxDistanceBetweenLinesBox.Size = new System.Drawing.Size(55, 21);
+ this._MaxDistanceBetweenLinesBox.TabIndex = 12;
+ //
+ // _GoToPageTopLevelBox
+ //
+ this._GoToPageTopLevelBox.Location = new System.Drawing.Point(200, 116);
+ this._GoToPageTopLevelBox.Maximum = new decimal(new int[] {
+ 9,
+ 0,
+ 0,
+ 0});
+ this._GoToPageTopLevelBox.Name = "_GoToPageTopLevelBox";
+ this._GoToPageTopLevelBox.Size = new System.Drawing.Size(41, 21);
+ this._GoToPageTopLevelBox.TabIndex = 16;
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Location = new System.Drawing.Point(378, 91);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size(41, 12);
+ this.label7.TabIndex = 13;
+ this.label7.Text = "倍行距";
+ //
+ // label9
+ //
+ this.label9.AutoSize = true;
+ this.label9.Location = new System.Drawing.Point(359, 38);
+ this.label9.Name = "label9";
+ this.label9.Size = new System.Drawing.Size(41, 12);
+ this.label9.TabIndex = 6;
+ this.label9.Text = "倍行距";
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(174, 38);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(113, 12);
+ this.label4.TabIndex = 4;
+ this.label4.Text = "定位位置向上偏移:";
+ //
+ // _YOffsetBox
+ //
+ this._YOffsetBox.DecimalPlaces = 2;
+ this._YOffsetBox.Increment = new decimal(new int[] {
+ 1,
+ 0,
+ 0,
+ 65536});
+ this._YOffsetBox.Location = new System.Drawing.Point(293, 36);
+ this._YOffsetBox.Maximum = new decimal(new int[] {
+ 10,
+ 0,
+ 0,
+ 0});
+ this._YOffsetBox.Minimum = new decimal(new int[] {
+ 10,
+ 0,
+ 0,
+ -2147483648});
+ this._YOffsetBox.Name = "_YOffsetBox";
+ this._YOffsetBox.Size = new System.Drawing.Size(60, 21);
+ this._YOffsetBox.TabIndex = 5;
+ //
+ // _MergeDifferentFontTitlesBox
+ //
+ this._MergeDifferentFontTitlesBox.AutoSize = true;
+ this._MergeDifferentFontTitlesBox.Location = new System.Drawing.Point(6, 127);
+ this._MergeDifferentFontTitlesBox.Name = "_MergeDifferentFontTitlesBox";
+ this._MergeDifferentFontTitlesBox.Size = new System.Drawing.Size(132, 16);
+ this._MergeDifferentFontTitlesBox.TabIndex = 15;
+ this._MergeDifferentFontTitlesBox.Text = "合并不同字体的标题";
+ this._MergeDifferentFontTitlesBox.UseVisualStyleBackColor = true;
+ //
+ // tabPage2
+ //
+ this.tabPage2.Controls.Add(this._IgnoreNumericTitleBox);
+ this.tabPage2.Controls.Add(this._IgnoreSingleCharacterTitleBox);
+ this.tabPage2.Controls.Add(this._ClearTextFiltersButton);
+ this.tabPage2.Controls.Add(this._IgnorePatternsBox);
+ this.tabPage2.Controls.Add(this.label10);
+ this.tabPage2.Location = new System.Drawing.Point(4, 22);
+ this.tabPage2.Name = "tabPage2";
+ this.tabPage2.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
+ this.tabPage2.Size = new System.Drawing.Size(455, 203);
+ this.tabPage2.TabIndex = 1;
+ this.tabPage2.Text = "文本过滤";
+ this.tabPage2.UseVisualStyleBackColor = true;
+ //
+ // _IgnoreNumericTitleBox
+ //
+ this._IgnoreNumericTitleBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this._IgnoreNumericTitleBox.AutoSize = true;
+ this._IgnoreNumericTitleBox.Location = new System.Drawing.Point(170, 171);
+ this._IgnoreNumericTitleBox.Name = "_IgnoreNumericTitleBox";
+ this._IgnoreNumericTitleBox.Size = new System.Drawing.Size(132, 16);
+ this._IgnoreNumericTitleBox.TabIndex = 22;
+ this._IgnoreNumericTitleBox.Text = "忽略只有数字的标题";
+ this._IgnoreNumericTitleBox.UseVisualStyleBackColor = true;
+ //
+ // _IgnoreSingleCharacterTitleBox
+ //
+ this._IgnoreSingleCharacterTitleBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this._IgnoreSingleCharacterTitleBox.AutoSize = true;
+ this._IgnoreSingleCharacterTitleBox.Location = new System.Drawing.Point(8, 171);
+ this._IgnoreSingleCharacterTitleBox.Name = "_IgnoreSingleCharacterTitleBox";
+ this._IgnoreSingleCharacterTitleBox.Size = new System.Drawing.Size(156, 16);
+ this._IgnoreSingleCharacterTitleBox.TabIndex = 21;
+ this._IgnoreSingleCharacterTitleBox.Text = "忽略只有一个字符的标题";
+ this._IgnoreSingleCharacterTitleBox.UseVisualStyleBackColor = true;
+ //
+ // _ClearTextFiltersButton
+ //
+ this._ClearTextFiltersButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._ClearTextFiltersButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._ClearTextFiltersButton.Location = new System.Drawing.Point(369, 6);
+ this._ClearTextFiltersButton.Name = "_ClearTextFiltersButton";
+ this._ClearTextFiltersButton.Size = new System.Drawing.Size(80, 23);
+ this._ClearTextFiltersButton.TabIndex = 2;
+ this._ClearTextFiltersButton.Text = "清空列表";
+ this._ClearTextFiltersButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._ClearTextFiltersButton.UseVisualStyleBackColor = true;
+ this._ClearTextFiltersButton.Click += new System.EventHandler(this.ControlEvent);
+ //
+ // _IgnorePatternsBox
+ //
+ this._IgnorePatternsBox.AllowUserToResizeRows = false;
+ this._IgnorePatternsBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._IgnorePatternsBox.BackgroundColor = System.Drawing.SystemColors.Window;
+ dataGridViewCellStyle1.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+ dataGridViewCellStyle1.BackColor = System.Drawing.SystemColors.Control;
+ dataGridViewCellStyle1.Font = new System.Drawing.Font("SimSun", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ dataGridViewCellStyle1.ForeColor = System.Drawing.SystemColors.WindowText;
+ dataGridViewCellStyle1.SelectionBackColor = System.Drawing.SystemColors.Highlight;
+ dataGridViewCellStyle1.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
+ dataGridViewCellStyle1.WrapMode = System.Windows.Forms.DataGridViewTriState.True;
+ this._IgnorePatternsBox.ColumnHeadersDefaultCellStyle = dataGridViewCellStyle1;
+ this._IgnorePatternsBox.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize;
+ this._IgnorePatternsBox.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] {
+ this._PatternColumn,
+ this._MatchCaseColumn,
+ this._FullMatchColumn,
+ this._PatternTypeColumn,
+ this._RemovePatternColumn});
+ dataGridViewCellStyle2.Alignment = System.Windows.Forms.DataGridViewContentAlignment.MiddleLeft;
+ dataGridViewCellStyle2.BackColor = System.Drawing.SystemColors.Window;
+ dataGridViewCellStyle2.Font = new System.Drawing.Font("SimSun", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ dataGridViewCellStyle2.ForeColor = System.Drawing.SystemColors.ControlText;
+ dataGridViewCellStyle2.SelectionBackColor = System.Drawing.SystemColors.Highlight;
+ dataGridViewCellStyle2.SelectionForeColor = System.Drawing.SystemColors.HighlightText;
+ dataGridViewCellStyle2.WrapMode = System.Windows.Forms.DataGridViewTriState.False;
+ this._IgnorePatternsBox.DefaultCellStyle = dataGridViewCellStyle2;
+ this._IgnorePatternsBox.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnEnter;
+ this._IgnorePatternsBox.Location = new System.Drawing.Point(8, 35);
+ this._IgnorePatternsBox.Name = "_IgnorePatternsBox";
+ this._IgnorePatternsBox.RowHeadersVisible = false;
+ this._IgnorePatternsBox.Size = new System.Drawing.Size(441, 130);
+ this._IgnorePatternsBox.TabIndex = 1;
+ this._IgnorePatternsBox.CellContentClick += new System.Windows.Forms.DataGridViewCellEventHandler(this._IgnorePatternsBox_CellContentClick);
+ //
+ // _PatternColumn
+ //
+ this._PatternColumn.Frozen = true;
+ this._PatternColumn.HeaderText = "忽略内容";
+ this._PatternColumn.MinimumWidth = 50;
+ this._PatternColumn.Name = "_PatternColumn";
+ this._PatternColumn.ToolTipText = "忽略匹配此内容的标题";
+ this._PatternColumn.Width = 150;
+ //
+ // _MatchCaseColumn
+ //
+ this._MatchCaseColumn.HeaderText = "区分大小写";
+ this._MatchCaseColumn.MinimumWidth = 70;
+ this._MatchCaseColumn.Name = "_MatchCaseColumn";
+ this._MatchCaseColumn.ToolTipText = "是否区分大小写";
+ this._MatchCaseColumn.Width = 70;
+ //
+ // _FullMatchColumn
+ //
+ this._FullMatchColumn.HeaderText = "匹配全标题";
+ this._FullMatchColumn.MinimumWidth = 70;
+ this._FullMatchColumn.Name = "_FullMatchColumn";
+ this._FullMatchColumn.ToolTipText = "是否匹配整个标题";
+ this._FullMatchColumn.Width = 70;
+ //
+ // _PatternTypeColumn
+ //
+ this._PatternTypeColumn.HeaderText = "正则表达式";
+ this._PatternTypeColumn.MinimumWidth = 70;
+ this._PatternTypeColumn.Name = "_PatternTypeColumn";
+ this._PatternTypeColumn.ToolTipText = "是否使用正则表达式";
+ this._PatternTypeColumn.Width = 70;
+ //
+ // _RemovePatternColumn
+ //
+ this._RemovePatternColumn.HeaderText = "删除";
+ this._RemovePatternColumn.MinimumWidth = 35;
+ this._RemovePatternColumn.Name = "_RemovePatternColumn";
+ this._RemovePatternColumn.Text = "删除";
+ this._RemovePatternColumn.ToolTipText = "删除此忽略模板";
+ this._RemovePatternColumn.UseColumnTextForLinkValue = true;
+ this._RemovePatternColumn.Width = 35;
+ //
+ // label10
+ //
+ this.label10.AutoSize = true;
+ this.label10.Location = new System.Drawing.Point(3, 11);
+ this.label10.Name = "label10";
+ this.label10.Size = new System.Drawing.Size(149, 12);
+ this.label10.TabIndex = 0;
+ this.label10.Text = "忽略匹配以下内容的文本:";
+ //
+ // tabPage3
+ //
+ this.tabPage3.Controls.Add(this._FilterToolbar);
+ this.tabPage3.Controls.Add(this._LevelAdjustmentBox);
+ this.tabPage3.Controls.Add(this.label12);
+ this.tabPage3.Location = new System.Drawing.Point(4, 22);
+ this.tabPage3.Name = "tabPage3";
+ this.tabPage3.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
+ this.tabPage3.Size = new System.Drawing.Size(455, 203);
+ this.tabPage3.TabIndex = 2;
+ this.tabPage3.Text = "高级筛选处理";
+ this.tabPage3.UseVisualStyleBackColor = true;
+ //
+ // _FilterToolbar
+ //
+ this._FilterToolbar.GripStyle = System.Windows.Forms.ToolStripGripStyle.Hidden;
+ this._FilterToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this.toolStripLabel1,
+ _AddAdjustmentButton,
+ this._AddFilterFromInfoFileButton,
+ this._DeleteAdjustmentButton,
+ this.toolStripSeparator1,
+ this._CopyFilterButton,
+ this._PasteButton});
+ this._FilterToolbar.Location = new System.Drawing.Point(3, 3);
+ this._FilterToolbar.Name = "_FilterToolbar";
+ this._FilterToolbar.Size = new System.Drawing.Size(449, 25);
+ this._FilterToolbar.TabIndex = 0;
+ //
+ // toolStripLabel1
+ //
+ this.toolStripLabel1.Name = "toolStripLabel1";
+ this.toolStripLabel1.Size = new System.Drawing.Size(68, 22);
+ this.toolStripLabel1.Text = "筛选条件:";
+ //
+ // _AddFilterFromInfoFileButton
+ //
+ this._AddFilterFromInfoFileButton.Image = global::PDFPatcher.Properties.Resources.BookmarkFile;
+ this._AddFilterFromInfoFileButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._AddFilterFromInfoFileButton.Name = "_AddFilterFromInfoFileButton";
+ this._AddFilterFromInfoFileButton.Size = new System.Drawing.Size(112, 22);
+ this._AddFilterFromInfoFileButton.Text = "从信息文件添加";
+ this._AddFilterFromInfoFileButton.Click += new System.EventHandler(this.ControlEvent);
+ //
+ // _DeleteAdjustmentButton
+ //
+ this._DeleteAdjustmentButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this._DeleteAdjustmentButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._DeleteAdjustmentButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._DeleteAdjustmentButton.Name = "_DeleteAdjustmentButton";
+ this._DeleteAdjustmentButton.Size = new System.Drawing.Size(23, 22);
+ this._DeleteAdjustmentButton.Text = "删除";
+ this._DeleteAdjustmentButton.Click += new System.EventHandler(this.ControlEvent);
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+ //
+ // _CopyFilterButton
+ //
+ this._CopyFilterButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this._CopyFilterButton.Image = global::PDFPatcher.Properties.Resources.Copy;
+ this._CopyFilterButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._CopyFilterButton.Name = "_CopyFilterButton";
+ this._CopyFilterButton.Size = new System.Drawing.Size(23, 22);
+ this._CopyFilterButton.Text = "复制";
+ this._CopyFilterButton.Click += new System.EventHandler(this.ControlEvent);
+ //
+ // _PasteButton
+ //
+ this._PasteButton.Image = global::PDFPatcher.Properties.Resources.Paste;
+ this._PasteButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._PasteButton.Name = "_PasteButton";
+ this._PasteButton.Size = new System.Drawing.Size(52, 22);
+ this._PasteButton.Text = "粘贴";
+ this._PasteButton.Click += new System.EventHandler(this.ControlEvent);
+ //
+ // _LevelAdjustmentBox
+ //
+ this._LevelAdjustmentBox.AllColumns.Add(this._AdvancedFilterColumn);
+ this._LevelAdjustmentBox.AllColumns.Add(this._AdjustmentLevelColumn);
+ this._LevelAdjustmentBox.AllColumns.Add(this._RelativeAdjustmentColumn);
+ this._LevelAdjustmentBox.AllColumns.Add(this._FilterBeforeMergeColumn);
+ this._LevelAdjustmentBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._LevelAdjustmentBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this._LevelAdjustmentBox.CellEditUseWholeCell = false;
+ this._LevelAdjustmentBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._AdvancedFilterColumn,
+ this._AdjustmentLevelColumn,
+ this._RelativeAdjustmentColumn,
+ this._FilterBeforeMergeColumn});
+ this._LevelAdjustmentBox.Cursor = System.Windows.Forms.Cursors.Default;
+ this._LevelAdjustmentBox.GridLines = true;
+ this._LevelAdjustmentBox.HideSelection = false;
+ this._LevelAdjustmentBox.IsSimpleDragSource = true;
+ this._LevelAdjustmentBox.IsSimpleDropSink = true;
+ this._LevelAdjustmentBox.Location = new System.Drawing.Point(6, 50);
+ this._LevelAdjustmentBox.Name = "_LevelAdjustmentBox";
+ this._LevelAdjustmentBox.ShowGroups = false;
+ this._LevelAdjustmentBox.Size = new System.Drawing.Size(443, 137);
+ this._LevelAdjustmentBox.TabIndex = 2;
+ this._LevelAdjustmentBox.UseCompatibleStateImageBehavior = false;
+ this._LevelAdjustmentBox.View = System.Windows.Forms.View.Details;
+ this._LevelAdjustmentBox.ItemActivate += new System.EventHandler(this._LevelAdjustmentBox_ItemActivate);
+ //
+ // _AdvancedFilterColumn
+ //
+ this._AdvancedFilterColumn.IsEditable = false;
+ this._AdvancedFilterColumn.Text = "筛选条件";
+ this._AdvancedFilterColumn.Width = 273;
+ //
+ // _AdjustmentLevelColumn
+ //
+ this._AdjustmentLevelColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._AdjustmentLevelColumn.Text = "调整级别";
+ //
+ // _RelativeAdjustmentColumn
+ //
+ this._RelativeAdjustmentColumn.CheckBoxes = true;
+ this._RelativeAdjustmentColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._RelativeAdjustmentColumn.Text = "相对调整";
+ this._RelativeAdjustmentColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ //
+ // _FilterBeforeMergeColumn
+ //
+ this._FilterBeforeMergeColumn.CheckBoxes = true;
+ this._FilterBeforeMergeColumn.Text = "合并文本前筛选";
+ this._FilterBeforeMergeColumn.Width = 100;
+ //
+ // label12
+ //
+ this.label12.AutoSize = true;
+ this.label12.Location = new System.Drawing.Point(3, 35);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(251, 12);
+ this.label12.TabIndex = 1;
+ this.label12.Text = "调整匹配字体的尺寸级别(级别为0时忽略):";
+ //
+ // tabPage5
+ //
+ this.tabPage5.Controls.Add(this._ExportTextCoordinateBox);
+ this.tabPage5.Controls.Add(this._ShowAllFontsBox);
+ this.tabPage5.Controls.Add(this._DisplayFontStatisticsBox);
+ this.tabPage5.Location = new System.Drawing.Point(4, 22);
+ this.tabPage5.Name = "tabPage5";
+ this.tabPage5.Padding = new System.Windows.Forms.Padding(3, 3, 3, 3);
+ this.tabPage5.Size = new System.Drawing.Size(455, 203);
+ this.tabPage5.TabIndex = 4;
+ this.tabPage5.Text = "其它选项";
+ this.tabPage5.UseVisualStyleBackColor = true;
+ //
+ // _ExportTextCoordinateBox
+ //
+ this._ExportTextCoordinateBox.AutoSize = true;
+ this._ExportTextCoordinateBox.Location = new System.Drawing.Point(6, 50);
+ this._ExportTextCoordinateBox.Name = "_ExportTextCoordinateBox";
+ this._ExportTextCoordinateBox.Size = new System.Drawing.Size(120, 16);
+ this._ExportTextCoordinateBox.TabIndex = 2;
+ this._ExportTextCoordinateBox.Text = "导出文本位置信息";
+ this._ExportTextCoordinateBox.UseVisualStyleBackColor = true;
+ //
+ // _ShowAllFontsBox
+ //
+ this._ShowAllFontsBox.AutoSize = true;
+ this._ShowAllFontsBox.Location = new System.Drawing.Point(6, 28);
+ this._ShowAllFontsBox.Name = "_ShowAllFontsBox";
+ this._ShowAllFontsBox.Size = new System.Drawing.Size(120, 16);
+ this._ShowAllFontsBox.TabIndex = 1;
+ this._ShowAllFontsBox.Text = "列出被忽略的字体";
+ this._ShowAllFontsBox.UseVisualStyleBackColor = true;
+ //
+ // _DisplayFontStatisticsBox
+ //
+ this._DisplayFontStatisticsBox.AutoSize = true;
+ this._DisplayFontStatisticsBox.Checked = true;
+ this._DisplayFontStatisticsBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this._DisplayFontStatisticsBox.Location = new System.Drawing.Point(6, 6);
+ this._DisplayFontStatisticsBox.Name = "_DisplayFontStatisticsBox";
+ this._DisplayFontStatisticsBox.Size = new System.Drawing.Size(192, 16);
+ this._DisplayFontStatisticsBox.TabIndex = 0;
+ this._DisplayFontStatisticsBox.Text = "完成识别后统计用于标题的字体";
+ this._DisplayFontStatisticsBox.UseVisualStyleBackColor = true;
+ //
+ // _BookmarkControl
+ //
+ this._BookmarkControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._BookmarkControl.LabelText = "P&DF 信息文件:";
+ this._BookmarkControl.Location = new System.Drawing.Point(12, 33);
+ this._BookmarkControl.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._BookmarkControl.Name = "_BookmarkControl";
+ this._BookmarkControl.Size = new System.Drawing.Size(463, 25);
+ this._BookmarkControl.TabIndex = 2;
+ this._BookmarkControl.UseForBookmarkExport = true;
+ //
+ // _SourceFileControl
+ //
+ this._SourceFileControl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._SourceFileControl.Location = new System.Drawing.Point(12, 3);
+ this._SourceFileControl.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4);
+ this._SourceFileControl.Name = "_SourceFileControl";
+ this._SourceFileControl.Size = new System.Drawing.Size(463, 24);
+ this._SourceFileControl.TabIndex = 1;
+ //
+ // _ExportBookmarkButton
+ //
+ this._ExportBookmarkButton.AlternativeFocusBorderColor = System.Drawing.SystemColors.Highlight;
+ this._ExportBookmarkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._ExportBookmarkButton.AnimateGlow = true;
+ this._ExportBookmarkButton.BackColor = System.Drawing.SystemColors.Highlight;
+ this._ExportBookmarkButton.CornerRadius = 3;
+ this._ExportBookmarkButton.ForeColor = System.Drawing.SystemColors.ControlText;
+ this._ExportBookmarkButton.GlowColor = System.Drawing.Color.White;
+ this._ExportBookmarkButton.Image = global::PDFPatcher.Properties.Resources.Save;
+ this._ExportBookmarkButton.InnerBorderColor = System.Drawing.SystemColors.ControlDarkDark;
+ this._ExportBookmarkButton.Location = new System.Drawing.Point(349, 63);
+ this._ExportBookmarkButton.Name = "_ExportBookmarkButton";
+ this._ExportBookmarkButton.OuterBorderColor = System.Drawing.SystemColors.ControlLightLight;
+ this._ExportBookmarkButton.ShowFocusBorder = true;
+ this._ExportBookmarkButton.Size = new System.Drawing.Size(123, 29);
+ this._ExportBookmarkButton.TabIndex = 15;
+ this._ExportBookmarkButton.Text = " 生成书签(&S)";
+ this._ExportBookmarkButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._ExportBookmarkButton.Click += new System.EventHandler(this._ExportBookmarkButton_Click);
+ //
+ // AutoBookmarkControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this._ExportBookmarkButton);
+ this.Controls.Add(this._SourceFileControl);
+ this.Controls.Add(this._BookmarkControl);
+ this.Controls.Add(this.tabControl1);
+ this.Font = new System.Drawing.Font("SimSun", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.Name = "AutoBookmarkControl";
+ this.Size = new System.Drawing.Size(487, 333);
+ ((System.ComponentModel.ISupportInitialize)(this._TitleSizeThresholdBox)).EndInit();
+ this.tabControl1.ResumeLayout(false);
+ this.tabPage1.ResumeLayout(false);
+ this.tabPage1.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._MaxDistanceBetweenLinesBox)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this._GoToPageTopLevelBox)).EndInit();
+ ((System.ComponentModel.ISupportInitialize)(this._YOffsetBox)).EndInit();
+ this.tabPage2.ResumeLayout(false);
+ this.tabPage2.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._IgnorePatternsBox)).EndInit();
+ this.tabPage3.ResumeLayout(false);
+ this.tabPage3.PerformLayout();
+ this._FilterToolbar.ResumeLayout(false);
+ this._FilterToolbar.PerformLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._LevelAdjustmentBox)).EndInit();
+ this.tabPage5.ResumeLayout(false);
+ this.tabPage5.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private SourceFileControl _SourceFileControl;
+ private BookmarkControl _BookmarkControl;
+ private System.Windows.Forms.NumericUpDown _TitleSizeThresholdBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.TextBox _PageRangeBox;
+ private System.Windows.Forms.CheckBox _MergeAdjacentTitlesBox;
+ private System.Windows.Forms.CheckBox _MergeDifferentSizeTitlesBox;
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage tabPage1;
+ private System.Windows.Forms.TabPage tabPage2;
+ private System.Windows.Forms.Label label10;
+ private System.Windows.Forms.Label label11;
+ private System.Windows.Forms.NumericUpDown _GoToPageTopLevelBox;
+ private System.Windows.Forms.Label label9;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.NumericUpDown _YOffsetBox;
+ private System.Windows.Forms.DataGridView _IgnorePatternsBox;
+ private System.Windows.Forms.DataGridViewTextBoxColumn _PatternColumn;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn _MatchCaseColumn;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn _FullMatchColumn;
+ private System.Windows.Forms.DataGridViewCheckBoxColumn _PatternTypeColumn;
+ private System.Windows.Forms.DataGridViewLinkColumn _RemovePatternColumn;
+ private System.Windows.Forms.TabPage tabPage3;
+ private System.Windows.Forms.Label label12;
+ private System.Windows.Forms.Button _ClearTextFiltersButton;
+ private System.Windows.Forms.CheckBox _AutoHierarchicalArrangementBox;
+ private BrightIdeasSoftware.ObjectListView _LevelAdjustmentBox;
+ private BrightIdeasSoftware.OLVColumn _AdvancedFilterColumn;
+ private BrightIdeasSoftware.OLVColumn _AdjustmentLevelColumn;
+ private BrightIdeasSoftware.OLVColumn _RelativeAdjustmentColumn;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.ComboBox _WritingDirectionBox;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.TabPage tabPage5;
+ private System.Windows.Forms.CheckBox _ShowAllFontsBox;
+ private System.Windows.Forms.CheckBox _DisplayFontStatisticsBox;
+ private System.Windows.Forms.NumericUpDown _MaxDistanceBetweenLinesBox;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.CheckBox _ExportTextCoordinateBox;
+ private System.Windows.Forms.ContextMenuStrip _AddFilterMenu;
+ private System.Windows.Forms.ToolStrip _FilterToolbar;
+ private System.Windows.Forms.ToolStripButton _DeleteAdjustmentButton;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripButton _CopyFilterButton;
+ private System.Windows.Forms.ToolStripButton _PasteButton;
+ private System.Windows.Forms.ToolStripLabel toolStripLabel1;
+ private System.Windows.Forms.ToolStripButton _AddFilterFromInfoFileButton;
+ private System.Windows.Forms.CheckBox _CreateBookmarkForFirstPageBox;
+ private System.Windows.Forms.CheckBox _MergeDifferentFontTitlesBox;
+ private System.Windows.Forms.CheckBox _IgnoreOverlappedTextBox;
+ private System.Windows.Forms.CheckBox _IgnoreNumericTitleBox;
+ private System.Windows.Forms.CheckBox _IgnoreSingleCharacterTitleBox;
+ private BrightIdeasSoftware.OLVColumn _FilterBeforeMergeColumn;
+ private EnhancedGlassButton.GlassButton _ExportBookmarkButton;
+ private System.Windows.Forms.CheckBox _FirstLineAsTitleBox;
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmarkControl.cs b/pdfpatcher/App/Functions/AutoBookmarkControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1ce928b4be0c9b360d89b8fac1ab879d30772254
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmarkControl.cs
@@ -0,0 +1,336 @@
+using System;
+using System.ComponentModel;
+using System.IO;
+using System.Windows.Forms;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ [ToolboxItem(false)]
+ public partial class AutoBookmarkControl : FunctionControl, IResettableControl
+ {
+ AutoBookmarkOptions _options;
+ static AutoBookmarkOptions.LevelAdjustmentOption[] _copiedLevelAdjustments;
+
+ public override string FunctionName => "自动生成书签";
+
+ public override System.Drawing.Bitmap IconImage => Properties.Resources.AutoBookmark;
+
+ public override Button DefaultButton => _ExportBookmarkButton;
+
+ public AutoBookmarkControl() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ }
+
+ void OnLoad() {
+ _FilterToolbar.ScaleIcons(16);
+ _LevelAdjustmentBox.ScaleColumnWidths();
+ AppContext.MainForm.SetTooltip(_SourceFileControl.FileList, "需要识别标题为书签的 PDF 源文件路径");
+ AppContext.MainForm.SetTooltip(_BookmarkControl.FileList, "指定识别书签后生成的信息文件或简易文本书签文件路径");
+ AppContext.MainForm.SetTooltip(_ExportBookmarkButton, "点击此按钮识别 PDF 文件的标题为信息文件");
+ AppContext.MainForm.SetTooltip(_TitleSizeThresholdBox, "指定标题文本的最小尺寸,小于此尺寸的文本将被忽略");
+ AppContext.MainForm.SetTooltip(_AutoHierarchicalArrangementBox, "根据标题文本的尺寸级别生成多层次的书签");
+ AppContext.MainForm.SetTooltip(_YOffsetBox, "将标题的定位位置向上偏移的行距");
+ AppContext.MainForm.SetTooltip(_MergeAdjacentTitlesBox, "将连续出现的标题合并为一个标题");
+ AppContext.MainForm.SetTooltip(_MergeDifferentSizeTitlesBox, "合并不同尺寸的相邻标题");
+ AppContext.MainForm.SetTooltip(_GoToPageTopLevelBox, "小于指定层数的标题定位到页首,而非所在精确位置");
+ AppContext.MainForm.SetTooltip(_IgnoreOverlappedTextBox, "忽略用于制作粗体、阴影等效果的重叠文本");
+ AppContext.MainForm.SetTooltip(_CreateBookmarkForFirstPageBox, "生成一个书签指向文档的第一页,书签文本为 PDF 文件的名称");
+ AppContext.MainForm.SetTooltip(_PageRangeBox, Messages.PageRanges);
+
+ int i = 0;
+ foreach (var item in EditAdjustmentForm.FilterNames) {
+ _AddFilterMenu.Items.Add(item).Name = EditAdjustmentForm.FilterIDs[i++];
+ }
+ _LevelAdjustmentBox.CellEditUseWholeCell = true;
+ _LevelAdjustmentBox.BeforeSorting += (object sender, BrightIdeasSoftware.BeforeSortingEventArgs e) => {
+ e.Canceled = true;
+ };
+ _LevelAdjustmentBox.DropSink = new BrightIdeasSoftware.RearrangingDropSink(false);
+ _AdvancedFilterColumn.AspectGetter = (object x) => {
+ var f = x as AutoBookmarkOptions.LevelAdjustmentOption;
+ if (f == null) {
+ return null;
+ }
+ return f.Condition.Description;
+ };
+ _AdjustmentLevelColumn.AspectGetter = (object x) => {
+ var f = x as AutoBookmarkOptions.LevelAdjustmentOption;
+ return f?.AdjustmentLevel ?? 0;
+ };
+ _AdjustmentLevelColumn.AspectPutter = (object x, object value) => {
+ var f = x as AutoBookmarkOptions.LevelAdjustmentOption;
+ if (f == null) {
+ return;
+ }
+ if ((value ?? "0").ToString().TryParse(out float a)) {
+ f.AdjustmentLevel = a;
+ }
+ };
+ _RelativeAdjustmentColumn.AspectGetter = (object x) => (x as AutoBookmarkOptions.LevelAdjustmentOption)?.RelativeAdjustment == true;
+ _RelativeAdjustmentColumn.AspectPutter = (object x, object value) => {
+ var f = x as AutoBookmarkOptions.LevelAdjustmentOption;
+ if (f == null) {
+ return;
+ }
+ f.RelativeAdjustment = value is bool b && b;
+ };
+ _FilterBeforeMergeColumn.AspectGetter = (object x) => ((x as AutoBookmarkOptions.LevelAdjustmentOption)?.FilterBeforeMergeTitle) ?? false;
+ _FilterBeforeMergeColumn.AspectPutter = (object x, object value) => {
+ if (x is AutoBookmarkOptions.LevelAdjustmentOption f) {
+ f.FilterBeforeMergeTitle = value is bool b && b;
+ }
+ };
+ _IgnorePatternsBox.AutoResizeRowHeadersWidth(DataGridViewRowHeadersWidthSizeMode.AutoSizeToAllHeaders);
+ Reload();
+
+ var d = _BookmarkControl.FileDialog;
+ d.CheckFileExists = false;
+ d.CheckPathExists = false;
+
+ var sd = d as SaveFileDialog;
+ if (sd != null) {
+ sd.OverwritePrompt = false;
+ }
+ }
+
+ public void Reset() {
+ AppContext.AutoBookmarker = new AutoBookmarkOptions();
+ Reload();
+ }
+
+ public void Reload() {
+ _options = AppContext.AutoBookmarker;
+ _CreateBookmarkForFirstPageBox.Checked = _options.CreateBookmarkForFirstPage;
+ _MergeAdjacentTitlesBox.Checked = _options.MergeAdjacentTitles;
+ _MergeDifferentSizeTitlesBox.Checked = _options.MergeDifferentSizeTitles;
+ _AutoHierarchicalArrangementBox.Checked = _options.AutoHierarchicalArrangement;
+ _IgnoreNumericTitleBox.Checked = _options.IgnoreNumericTitle;
+ _IgnoreOverlappedTextBox.Checked = _options.IgnoreOverlappedText;
+ _IgnoreSingleCharacterTitleBox.Checked = _options.IgnoreSingleCharacterTitle;
+ _ShowAllFontsBox.Checked = _options.DisplayAllFonts;
+ _DisplayFontStatisticsBox.Checked = _options.DisplayFontStatistics;
+ _WritingDirectionBox.SelectedIndex = (int)_options.WritingDirection;
+ _MergeDifferentFontTitlesBox.Checked = _options.MergeDifferentFontTitles;
+ _TitleSizeThresholdBox.SetValue(_options.TitleThreshold);
+ _YOffsetBox.SetValue(_options.YOffset);
+ _MaxDistanceBetweenLinesBox.SetValue(_options.MaxDistanceBetweenLines);
+ _FirstLineAsTitleBox.Checked = _options.FirstLineAsTitle;
+
+ for (int i = _options.LevelAdjustment.Count - 1; i >= 0; i--) {
+ if (_options.LevelAdjustment[i].Condition == null) {
+ _options.LevelAdjustment.RemoveAt(i);
+ }
+ }
+ _LevelAdjustmentBox.SetObjects(_options.LevelAdjustment);
+ _IgnorePatternsBox.Rows.Clear();
+ foreach (var item in _options.IgnorePatterns) {
+ if (String.IsNullOrEmpty(item.Text)) {
+ continue;
+ }
+ _IgnorePatternsBox.Rows.Add(item.Text, item.MatchCase, item.FullMatch, item.UseRegularExpression);
+ }
+ }
+
+ private void _ExportBookmarkButton_Click(object sender, EventArgs e) {
+ if (File.Exists(_SourceFileControl.FirstFile) == false) {
+ FormHelper.ErrorBox(Messages.SourceFileNotFound);
+ return;
+ }
+ else if (String.IsNullOrEmpty(_BookmarkControl.Text)) {
+ FormHelper.ErrorBox(Messages.InfoDocNotSpecified);
+ return;
+ }
+
+ AppContext.SourceFiles = _SourceFileControl.Files;
+ AppContext.BookmarkFile = _BookmarkControl.Text;
+ if (_SourceFileControl.Files.Length == 1) {
+ _SourceFileControl.FileList.AddHistoryItem();
+ _BookmarkControl.FileList.AddHistoryItem();
+ }
+
+ AppContext.MainForm.ResetWorker();
+ AppContext.MainForm.GetWorker().DoWork += new DoWorkEventHandler(ExportControl_DoWork);
+ SyncOptions();
+ AppContext.MainForm.GetWorker().RunWorkerAsync(new object[] {
+ AppContext.SourceFiles,
+ AppContext.BookmarkFile,
+ _options
+ });
+ }
+
+ private void SyncOptions() {
+ _options.CreateBookmarkForFirstPage = _CreateBookmarkForFirstPageBox.Checked;
+ _options.PageRanges = _PageRangeBox.Text;
+ _options.TitleThreshold = (float)_TitleSizeThresholdBox.Value;
+ _options.MergeAdjacentTitles = _MergeAdjacentTitlesBox.Checked;
+ _options.IgnoreNumericTitle = _IgnoreNumericTitleBox.Checked;
+ _options.IgnoreOverlappedText = _IgnoreOverlappedTextBox.Checked;
+ _options.IgnoreSingleCharacterTitle = _IgnoreSingleCharacterTitleBox.Checked;
+ _options.MergeDifferentSizeTitles = _MergeDifferentSizeTitlesBox.Checked;
+ _options.MergeDifferentFontTitles = _MergeDifferentFontTitlesBox.Checked;
+ _options.YOffset = (float)_YOffsetBox.Value;
+ _options.ExportTextCoordinates = _ExportTextCoordinateBox.Checked;
+ _options.PageTopForLevel = (int)_GoToPageTopLevelBox.Value;
+ _options.AutoHierarchicalArrangement = _AutoHierarchicalArrangementBox.Checked;
+ _options.DisplayFontStatistics = _DisplayFontStatisticsBox.Checked;
+ _options.DisplayAllFonts = _ShowAllFontsBox.Checked;
+ _options.WritingDirection = (WritingDirection)_WritingDirectionBox.SelectedIndex;
+ _options.MaxDistanceBetweenLines = (float)_MaxDistanceBetweenLinesBox.Value;
+ _options.FirstLineAsTitle = _FirstLineAsTitleBox.Checked;
+ _options.IgnorePatterns.Clear();
+ foreach (DataGridViewRow item in _IgnorePatternsBox.Rows) {
+ if (item.IsNewRow) {
+ continue;
+ }
+ var cells = item.Cells;
+ if (cells[0].Value == null) {
+ continue;
+ }
+ _options.IgnorePatterns.Add(new PDFPatcher.Model.MatchPattern(
+ cells[0].Value.ToString(),
+ (bool)(cells[_MatchCaseColumn.Index].Value ?? false),
+ (bool)(cells[_FullMatchColumn.Index].Value ?? false),
+ (bool)(cells[_PatternTypeColumn.Index].Value ?? false)));
+ }
+ _options.LevelAdjustment.Clear();
+ if (_LevelAdjustmentBox.Items.Count > 0) {
+ foreach (ListViewItem item in _LevelAdjustmentBox.Items) {
+ _options.LevelAdjustment.Add(_LevelAdjustmentBox.GetModelObject(item.Index) as AutoBookmarkOptions.LevelAdjustmentOption);
+ }
+ }
+ }
+
+ void ExportControl_DoWork(object sender, DoWorkEventArgs e) {
+ var a = e.Argument as object[];
+ var files = a[0] as string[];
+ var b = a[1] as string;
+ var options = a[2] as AutoBookmarkOptions;
+ if (files.Length > 1) {
+ var p = Path.GetDirectoryName(b);
+ var ext = Path.GetExtension(b);
+ foreach (var file in files) {
+ Processor.Worker.CreateBookmark(file, FileHelper.CombinePath(p, Path.GetFileNameWithoutExtension(file) + ext), options);
+ if (AppContext.Abort) {
+ return;
+ }
+ }
+ }
+ else {
+ Processor.Worker.CreateBookmark(files[0], b, options);
+ }
+ }
+
+ private void _IgnorePatternsBox_CellContentClick(object sender, DataGridViewCellEventArgs e) {
+ if (e.ColumnIndex == _RemovePatternColumn.Index && e.RowIndex >= 0) {
+ _IgnorePatternsBox.Rows.RemoveAt(e.RowIndex);
+ }
+ }
+
+ private void _ImportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
+ AppContext.MainForm.SelectFunctionList(Function.Patcher);
+ }
+
+ private void ControlEvent(object sender, EventArgs e) {
+ if (sender == _DeleteAdjustmentButton && _LevelAdjustmentBox.Items.Count > 0 && FormHelper.YesNoBox("是否删除选中的项?") == DialogResult.Yes) {
+ _LevelAdjustmentBox.RemoveObjects(_LevelAdjustmentBox.SelectedObjects);
+ }
+ else if (sender == _ClearTextFiltersButton && _IgnorePatternsBox.Rows.Count > 0 && FormHelper.YesNoBox("是否清空文本过滤列表?") == DialogResult.Yes) {
+ _IgnorePatternsBox.Rows.Clear();
+ }
+ else if (sender == _CopyFilterButton) {
+ var si = _LevelAdjustmentBox.SelectedObjects;
+ if (si.Count == 0) {
+ return;
+ }
+ _copiedLevelAdjustments = new AutoBookmarkOptions.LevelAdjustmentOption[si.Count];
+ for (int i = 0; i < _copiedLevelAdjustments.Length; i++) {
+ var item = si[i] as AutoBookmarkOptions.LevelAdjustmentOption;
+ _copiedLevelAdjustments[i] = item;
+ }
+ }
+ else if (sender == _PasteButton) {
+ //var s = Clipboard.GetText ();
+ //if (String.IsNullOrEmpty (s) == false && s.Length < 100) {
+ // _LevelAdjustmentBox.AddObject (new AutoBookmarkOptions.LevelAdjustmentOption () {
+ // Condition = new AutoBookmarkCondition.FontNameCondition (s, false)
+ // });
+ // return;
+ //}
+ if (_copiedLevelAdjustments.HasContent() == false) {
+ return;
+ }
+ foreach (var item in _copiedLevelAdjustments) {
+ _LevelAdjustmentBox.AddObject(item.Clone());
+ }
+ }
+ else if (sender == _AddFilterFromInfoFileButton) {
+ if (String.IsNullOrEmpty(_BookmarkControl.Text)) {
+ if (_BookmarkControl.FileDialog.ShowDialog() != DialogResult.OK) {
+ FormHelper.InfoBox("请先指定信息文件的路径。");
+ return;
+ }
+ _BookmarkControl.Text = _BookmarkControl.FileDialog.FileName;
+ }
+ var doc = new System.Xml.XmlDocument();
+ System.Xml.XmlNode fontInfo;
+ try {
+ doc.Load(_BookmarkControl.Text);
+ fontInfo = doc.SelectSingleNode(Constants.PdfInfo + "/" + Constants.Font.DocumentFont);
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox("无法从信息文件加载字体信息。" + ex.Message);
+ return;
+ }
+ if (fontInfo == null) {
+ FormHelper.ErrorBox("无法从信息文件加载字体信息。");
+ return;
+ }
+ using (var f = new FontFilterForm(fontInfo)) {
+ if (f.ShowDialog() == DialogResult.OK && f.FilterConditions != null) {
+ foreach (var item in f.FilterConditions) {
+ _LevelAdjustmentBox.AddObject(new AutoBookmarkOptions.LevelAdjustmentOption() {
+ Condition = item,
+ AdjustmentLevel = 0,
+ RelativeAdjustment = false
+ });
+ }
+ }
+ }
+ }
+ }
+
+ private void _LevelAdjustmentBox_ItemActivate(object sender, EventArgs e) {
+ if (_LevelAdjustmentBox.FocusedItem == null) {
+ return;
+ }
+ var fi = _LevelAdjustmentBox.FocusedItem;
+ var i = fi.Index;
+ var o = _LevelAdjustmentBox.GetModelObject(i) as AutoBookmarkOptions.LevelAdjustmentOption;
+ using (var dialog = new EditAdjustmentForm(o)) {
+ if (dialog.ShowDialog() == DialogResult.OK) {
+ if (dialog.Filter.Condition != null) {
+ _LevelAdjustmentBox.InsertObjects(i, new AutoBookmarkOptions.LevelAdjustmentOption[] { dialog.Filter });
+ _LevelAdjustmentBox.SelectedIndex = i;
+ }
+ _LevelAdjustmentBox.RemoveObject(o);
+ }
+ }
+ }
+
+ private void _AddFilterMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ var c = EditAdjustmentForm.CreateCondition(e.ClickedItem.Name);
+ if (c == null) {
+ return;
+ }
+
+ using (var dialog = new EditAdjustmentForm(new AutoBookmarkOptions.LevelAdjustmentOption { Condition = c })) {
+ if (dialog.ShowDialog() == DialogResult.OK && dialog.Filter.Condition != null) {
+ _LevelAdjustmentBox.AddObject(dialog.Filter);
+ }
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/AutoBookmarkControl.resx b/pdfpatcher/App/Functions/AutoBookmarkControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..1e63dd10ebb20b1fd8af5f875429b4fa76b2cf47
--- /dev/null
+++ b/pdfpatcher/App/Functions/AutoBookmarkControl.resx
@@ -0,0 +1,144 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ 17, 17
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ True
+
+
+ 160, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/BookmarkControl.Designer.cs b/pdfpatcher/App/Functions/BookmarkControl.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7c7cc86a41afe4efdf56c0937878a4cafe814136
--- /dev/null
+++ b/pdfpatcher/App/Functions/BookmarkControl.Designer.cs
@@ -0,0 +1,122 @@
+namespace PDFPatcher
+{
+ partial class BookmarkControl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.label1 = new System.Windows.Forms.Label();
+ this._BrowseBookmarkButton = new System.Windows.Forms.Button();
+ this._OpenBookmarkBox = new System.Windows.Forms.OpenFileDialog();
+ this._SaveBookmarkBox = new System.Windows.Forms.SaveFileDialog();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this._BookmarkBox = new PDFPatcher.HistoryComboBox();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(3, 6);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(89, 12);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "P&DF 信息文件:";
+ //
+ // _BrowseBookmarkButton
+ //
+ this._BrowseBookmarkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._BrowseBookmarkButton.Image = global::PDFPatcher.Properties.Resources.BookmarkFile;
+ this._BrowseBookmarkButton.Location = new System.Drawing.Point(391, 1);
+ this._BrowseBookmarkButton.Name = "_BrowseBookmarkButton";
+ this._BrowseBookmarkButton.Size = new System.Drawing.Size(75, 23);
+ this._BrowseBookmarkButton.TabIndex = 2;
+ this._BrowseBookmarkButton.Text = "浏览...";
+ this._BrowseBookmarkButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._BrowseBookmarkButton.UseVisualStyleBackColor = true;
+ this._BrowseBookmarkButton.Click += new System.EventHandler(this._BrowseSourcePdfButton_Click);
+ //
+ // _OpenBookmarkBox
+ //
+ this._OpenBookmarkBox.DefaultExt = "xml";
+ this._OpenBookmarkBox.Filter = "支持的信息文件 (*.xml,*.txt)|*.xml;*.txt|XML 信息文件 (*.xml)|*.xml|简易文本书签文件(*.txt)|*.txt";
+ this._OpenBookmarkBox.Title = "指定需要导入的信息文件的路径";
+ //
+ // _SaveBookmarkBox
+ //
+ this._SaveBookmarkBox.DefaultExt = "xml";
+ this._SaveBookmarkBox.Filter = "支持的信息文件 (*.xml,*.txt)|*.xml;*.txt|XML 信息文件 (*.xml)|*.xml|简易文本书签文件(*.txt)|*.txt";
+ this._SaveBookmarkBox.Title = "指定导出的信息文件路径";
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this._BookmarkBox);
+ this.panel1.Controls.Add(this.label1);
+ this.panel1.Controls.Add(this._BrowseBookmarkButton);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(469, 26);
+ this.panel1.TabIndex = 3;
+ //
+ // _BookmarkBox
+ //
+ this._BookmarkBox.AllowDrop = true;
+ this._BookmarkBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._BookmarkBox.Contents = null;
+ this._BookmarkBox.FormattingEnabled = true;
+ this._BookmarkBox.Location = new System.Drawing.Point(104, 3);
+ this._BookmarkBox.MaxItemCount = 16;
+ this._BookmarkBox.Name = "_BookmarkBox";
+ this._BookmarkBox.Size = new System.Drawing.Size(281, 20);
+ this._BookmarkBox.TabIndex = 1;
+ this._BookmarkBox.DragDrop += new System.Windows.Forms.DragEventHandler(this._BookmarkBox_DragDrop);
+ this._BookmarkBox.DragEnter += new System.Windows.Forms.DragEventHandler(this._BookmarkBox_DragEnter);
+ this._BookmarkBox.TextChanged += new System.EventHandler(this._BookmarkBox_TextChanged);
+ //
+ // BookmarkControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi;
+ this.Controls.Add(this.panel1);
+ this.Name = "BookmarkControl";
+ this.Size = new System.Drawing.Size(469, 26);
+ this.Load += new System.EventHandler(this.BookmarkControl_Show);
+ this.VisibleChanged += new System.EventHandler(this.BookmarkControl_Show);
+ this.panel1.ResumeLayout(false);
+ this.panel1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.Button _BrowseBookmarkButton;
+ private System.Windows.Forms.OpenFileDialog _OpenBookmarkBox;
+ private System.Windows.Forms.SaveFileDialog _SaveBookmarkBox;
+ private PDFPatcher.HistoryComboBox _BookmarkBox;
+ private System.Windows.Forms.Panel panel1;
+ }
+}
diff --git a/pdfpatcher/App/Functions/BookmarkControl.cs b/pdfpatcher/App/Functions/BookmarkControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2b3de4a71d6aa4af83c8e7cdd48cdfaa52fd1fe2
--- /dev/null
+++ b/pdfpatcher/App/Functions/BookmarkControl.cs
@@ -0,0 +1,101 @@
+using System;
+using System.ComponentModel;
+using System.Windows.Forms;
+using PDFPatcher.Common;
+
+namespace PDFPatcher
+{
+ public partial class BookmarkControl : UserControl
+ {
+ //readonly string[] xmlBookmarkType = new string[] { ".xml" };
+ //private string[] supportedBookmarkTypes;
+ internal event EventHandler BrowseForFile;
+
+ public BookmarkControl() {
+ InitializeComponent();
+ //supportedBookmarkTypes = defaultBookmarkTypes;
+ }
+
+ ///获取或指定书签文件路径的下拉列表框。
+ internal HistoryComboBox FileList => _BookmarkBox;
+
+ internal FileDialog FileDialog => _UseForBookmarkExport ? (FileDialog)_SaveBookmarkBox : _OpenBookmarkBox;
+
+ [Description("标签文本上显示的文本")]
+ public string LabelText {
+ get => label1.Text;
+ set => label1.Text = value;
+ }
+
+ [DefaultValue(null)]
+ ///获取或指定书签文件路径的值。
+ public override string Text {
+ get => _BookmarkBox.Text;
+ set => _BookmarkBox.Text = value;
+ }
+
+ private bool _UseForBookmarkExport;
+ ///获取或指定是否用于导出书签。
+ [DefaultValue(false)]
+ [Description("点击浏览按钮时是否打开保存对话框")]
+ public bool UseForBookmarkExport {
+ get => _UseForBookmarkExport;
+ set =>
+ //supportedBookmarkTypes = value ? xmlBookmarkType : defaultBookmarkTypes;
+ _UseForBookmarkExport = value;
+ }
+
+ private void _BrowseSourcePdfButton_Click(object sender, EventArgs e) {
+ BrowseForFile?.Invoke(sender, e);
+ var sourceFile = (AppContext.SourceFiles != null && AppContext.SourceFiles.Length > 0) ? AppContext.SourceFiles[0] : String.Empty;
+ if (FileHelper.IsPathValid(_BookmarkBox.Text) && System.IO.Path.GetFileName(_BookmarkBox.Text).Length > 0) {
+ var p = new FilePath(_BookmarkBox.Text);
+ _OpenBookmarkBox.SetLocation(p);
+ _SaveBookmarkBox.SetLocation(p);
+ }
+ else if (sourceFile.Length > 0) {
+ var p = new FilePath(sourceFile).ChangeExtension("xml");
+ _SaveBookmarkBox.SetLocation(p);
+ _OpenBookmarkBox.SetLocation(p);
+ }
+ if (_UseForBookmarkExport) {
+ if (_SaveBookmarkBox.ShowDialog() == DialogResult.OK) {
+ _BookmarkBox.Text = _SaveBookmarkBox.FileName;
+ }
+ }
+ else if (_OpenBookmarkBox.ShowDialog() == DialogResult.OK) {
+ if (_OpenBookmarkBox.FileName == _BookmarkBox.Text) {
+ return;
+ }
+ _BookmarkBox.Text = _OpenBookmarkBox.FileName;
+ }
+ }
+
+ private void _BookmarkBox_DragEnter(object sender, DragEventArgs e) {
+ //Common.Form.FeedbackDragFileOver (e, supportedBookmarkTypes);
+ e.FeedbackDragFileOver(Constants.FileExtensions.AllBookmarkExtension);
+ }
+
+ private void _BookmarkBox_DragDrop(object sender, DragEventArgs e) {
+ //Common.Form.DropFileOver ((Control)sender, e, supportedBookmarkTypes);
+ ((Control)sender).DropFileOver(e, Constants.FileExtensions.AllBookmarkExtension);
+ }
+
+ private void _BookmarkBox_TextChanged(object sender, EventArgs e) {
+ AppContext.BookmarkFile = _BookmarkBox.Text;
+ }
+
+ private void BookmarkControl_Show(object sender, EventArgs e) {
+ var t = _BookmarkBox.Text;
+ if (Visible && AppContext.MainForm != null) {
+ // _BookmarkBox.DataSource = new BindingList (_UseForBookmarkExport ? ContextData.Recent.SavedInfoDocuments : ContextData.Recent.InfoDocuments);
+ _BookmarkBox.Contents = AppContext.Recent.InfoDocuments;
+ }
+ else if (Visible == false) {
+ _BookmarkBox.Contents = null;
+ }
+ _BookmarkBox.Text = t;
+ }
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/BookmarkControl.resx b/pdfpatcher/App/Functions/BookmarkControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..71c50d7144c68f30db14a6f34852ea7911306cd0
--- /dev/null
+++ b/pdfpatcher/App/Functions/BookmarkControl.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ 183, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/CustomButton/GlassButton.cs b/pdfpatcher/App/Functions/CustomButton/GlassButton.cs
new file mode 100644
index 0000000000000000000000000000000000000000..d8be14679b7f9332c05bccb0ef7d47811fb68629
--- /dev/null
+++ b/pdfpatcher/App/Functions/CustomButton/GlassButton.cs
@@ -0,0 +1,1334 @@
+/************************************************************************************************
+ * GlassButton - How to create an animating glass button using only GDI+ (and not using WPF). *
+ * *
+ * Original developed by Łukasz Świątkowski - lukasz.swiatkowski@gmail.com *
+ * Form-/Perfomance-/Behavior-Improvements by Fink Christoph - fink.christoph@gmail.com *
+ * *
+ * Feel free to use this control in your application or to improve it in any way! *
+ ***********************************************************************************************/
+
+using System;
+using System.ComponentModel;
+using System.Drawing;
+using System.Drawing.Drawing2D;
+using System.Windows.Forms;
+using PushButtonState = System.Windows.Forms.VisualStyles.PushButtonState;
+
+namespace EnhancedGlassButton
+{
+ ///
+ /// Represents a glass button control.
+ ///
+ [ToolboxBitmap(typeof(System.Windows.Forms.Button)), ToolboxItem(true), ToolboxItemFilter("System.Windows.Forms"), Description("Raises an event when the user clicks it.")]
+ public partial class GlassButton : Button
+ {
+ #region " Global Vareables "
+ private System.ComponentModel.IContainer components = null;
+ private Timer timer;
+
+ #region " Vareables for Drawing "
+
+ GraphicsPath outerBorderPath;
+ GraphicsPath ContentPath;
+ GraphicsPath GlowClip;
+ GraphicsPath GlowBottomRadial;
+ GraphicsPath ShinePath;
+ GraphicsPath BorderPath;
+
+ PathGradientBrush GlowRadialPath;
+
+ LinearGradientBrush ShineBrush;
+
+ Pen outerBorderPen;
+ Pen BorderPen;
+
+ Color specialSymbolColor;
+
+ Brush specialSymbolBrush;
+ Brush ContentBrush;
+
+ Rectangle rect;
+ Rectangle rect2;
+
+ #endregion
+
+ ///
+ /// The ToolTip of the Control.
+ ///
+ readonly ToolTip toolTip = new ToolTip();
+
+ ///
+ /// If false, the shine isn't drawn (-> symbolizes an disabled control).
+ ///
+ bool drawShine = true;
+
+ ///
+ /// Set the trynsperency of the special Symbols.
+ ///
+ readonly int transparencyFactor = 128;
+
+ #endregion
+
+ #region " Constructors "
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public GlassButton() {
+ DoubleBuffered = true;
+
+ InitializeComponent();
+
+ roundCorner = 6;
+ timer.Interval = animationLength / framesCount;
+ base.BackColor = Color.Transparent;
+ BackColor = Color.Black;
+ ForeColor = Color.White;
+ OuterBorderColor = Color.White;
+ InnerBorderColor = Color.Black;
+ ShineColor = Color.White;
+ GlowColor = Color.FromArgb(unchecked((int)(0xFF8DBDFF)));
+ alternativeForm = false;
+ showFocusBorder = false;
+ animateGlow = false;
+ showSpecialSymbol = false;
+ specialSymbol = SpecialSymbols.Play;
+ specialSymbolColor = Color.White;
+ toolTipText = "";
+ specialSymbolBrush = new SolidBrush(Color.FromArgb(transparencyFactor, specialSymbolColor));
+ alternativeFocusBorderColor = Color.Black;
+ alternativeFormDirection = Direction.Left;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ SetStyle(ControlStyles.AllPaintingInWmPaint | ControlStyles.OptimizedDoubleBuffer | ControlStyles.ResizeRedraw | ControlStyles.SupportsTransparentBackColor | ControlStyles.UserPaint, true);
+ SetStyle(ControlStyles.Opaque, false);
+
+ SizeChanged += new EventHandler(GlassButton_SizeChanged);
+ MouseEnter += new EventHandler(GlassButton_MouseEnter);
+ MouseLeave += new EventHandler(GlassButton_MouseLeave);
+ GotFocus += new EventHandler(GlassButton_GotFocus);
+ LostFocus += new EventHandler(GlassButton_LostFocus);
+ }
+
+ private void InitializeComponent() {
+ components = new System.ComponentModel.Container();
+ timer = new System.Windows.Forms.Timer(components);
+ SuspendLayout();
+ //
+ // timer
+ //
+ timer.Tick += new System.EventHandler(timer_Tick);
+ ResumeLayout(false);
+
+ }
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose(bool disposing) {
+ if (disposing) {
+ if (imageButton != null) {
+ imageButton.Parent.Dispose();
+ imageButton.Parent = null;
+ imageButton.Dispose();
+ imageButton = null;
+ }
+
+ DisposeAll(outerBorderPath, ContentPath, GlowClip, GlowBottomRadial, ShinePath, BorderPath, GlowRadialPath, ShineBrush, outerBorderPen, BorderPen, specialSymbolBrush, ContentBrush, toolTip, components);
+ }
+ base.Dispose(disposing);
+ }
+
+ private void DisposeAll(params IDisposable[] objects) {
+ foreach (var item in objects) {
+ item?.Dispose();
+ }
+ }
+ #endregion
+
+ #region " Fields and Properties "
+
+ private Color backColor;
+ ///
+ /// Gets or sets the background color of the control.
+ ///
+ /// A value representing the background color.
+ [DefaultValue(typeof(Color), "Black")]
+ public new Color BackColor {
+ get => backColor;
+ set {
+ if (!backColor.Equals(value)) {
+ backColor = value;
+ UseVisualStyleBackColor = false;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ OnBackColorChanged(EventArgs.Empty);
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the foreground color of the control.
+ ///
+ /// The foreground of the control.
+ [DefaultValue(typeof(Color), "White")]
+ public new Color ForeColor {
+ get => base.ForeColor;
+ set {
+ base.ForeColor = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+ }
+ }
+
+ private Color innerBorderColor;
+ ///
+ /// Gets or sets the inner border color of the control.
+ ///
+ /// A value representing the color of the inner border.
+ [DefaultValue(typeof(Color), "Black"), Category("Appearance"), Description("The inner border color of the control.")]
+ public Color InnerBorderColor {
+ get => innerBorderColor;
+ set {
+ if (innerBorderColor != value) {
+ innerBorderColor = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ ///
+ /// Gets or sets the color of the special symbol.
+ ///
+ /// The color of the special symbol.
+ [DefaultValue(typeof(Color), "White"), Category("Appearance"), Description("The inner border color of the control.")]
+ public Color SpecialSymbolColor {
+ get => specialSymbolColor;
+ set {
+ if (specialSymbolColor != value) {
+ specialSymbolColor = value;
+ specialSymbolBrush = new SolidBrush(Color.FromArgb(transparencyFactor, specialSymbolColor));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private int roundCorner;
+ ///
+ /// Gets or sets the corner radius.
+ ///
+ /// The corner radius.
+ [DefaultValue(6), Category("Appearance"), Description("The radius of the corners.")]
+ public int CornerRadius {
+ get => roundCorner;
+ set {
+ if (roundCorner != value) {
+ roundCorner = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ string toolTipText;
+ ///
+ /// Gets or sets the tool tip text.
+ ///
+ /// The tool tip text.
+ [DefaultValue(""), Category("Appearance"), Description("The ToolTip-Text of the button. Leave blank to not show a ToolTip.")]
+ public string ToolTipText {
+ get => toolTipText;
+ set {
+ if (toolTipText != value) {
+ toolTipText = value;
+
+ if (toolTipText.Length > 0)
+ toolTip.SetToolTip(this, toolTipText);
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private bool alternativeForm;
+ ///
+ /// Gets or sets the alternative form.
+ ///
+ /// The alternative form.
+ [DefaultValue(false), Category("Appearance"), Description("Draws the Button in an alternative Form.")]
+ public bool AlternativeForm {
+ get => alternativeForm;
+ set {
+ if (alternativeForm != value) {
+ alternativeForm = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private bool animateGlow;
+ ///
+ /// Gets or sets a value indicating whether the glow is animated.
+ ///
+ /// true if glow is animated; otherwise, false.
+ [DefaultValue(false), Category("Appearance"), Description("If true the glow is animated.")]
+ public bool AnimateGlow {
+ get => animateGlow;
+ set {
+ if (animateGlow != value) {
+ animateGlow = value;
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private bool showSpecialSymbol;
+ ///
+ /// Gets or sets a value indicating whether a special symbol is drawn.
+ ///
+ /// true if special symbol is drawn; otherwise, false.
+ [DefaultValue(false), Category("Appearance"), Description("If true, the selectet special symbol will be drawn on the button.")]
+ public bool ShowSpecialSymbol {
+ get => showSpecialSymbol;
+ set {
+ if (showSpecialSymbol != value) {
+ showSpecialSymbol = value;
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ ///
+ /// List of all aviable special symbols.
+ ///
+ public enum SpecialSymbols
+ {
+ ArrowLeft,
+ ArrowRight,
+ ArrowUp,
+ ArrowDown,
+ Play,
+ Pause,
+ Stop,
+ FastForward,
+ Forward,
+ Backward,
+ FastBackward,
+ Speaker,
+ NoSpeaker,
+ Repeat,
+ RepeatAll,
+ Shuffle
+ }
+
+ private SpecialSymbols specialSymbol;
+ ///
+ /// Gets or sets the special symbol.
+ ///
+ /// The special symbol.
+ [DefaultValue(typeof(SpecialSymbols), "Play"), Category("Appearance"), Description("Sets the type of the special symbol on the button.")]
+ public SpecialSymbols SpecialSymbol {
+ get => specialSymbol;
+ set {
+ if (specialSymbol != value) {
+ specialSymbol = value;
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ public enum Direction
+ {
+ Left,
+ Right
+ }
+
+ private Direction alternativeFormDirection;
+ ///
+ /// Gets or sets the alternative form direction.
+ ///
+ /// The alternative form direction.
+ [DefaultValue(typeof(Direction), "Left"), Category("Appearance"), Description("Sets the Direction of the alternative Form.")]
+ public Direction AlternativeFormDirection {
+ get => alternativeFormDirection;
+ set {
+ if (alternativeFormDirection != value) {
+ alternativeFormDirection = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private bool showFocusBorder;
+ ///
+ /// Gets or sets a value indicating whether the focus border is shown.
+ ///
+ /// true if focus border shown; otherwise, false.
+ [DefaultValue(false), Category("Appearance"), Description("Draw the normal Focus-Border. Alternativ Focus-Border will be drawed if false.")]
+ public bool ShowFocusBorder {
+ get => showFocusBorder;
+ set {
+ if (showFocusBorder != value) {
+ showFocusBorder = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private Color alternativeFocusBorderColor;
+ ///
+ /// Gets or sets the color of the alternative focus border.
+ ///
+ /// The color of the alternative focus border.
+ [DefaultValue(typeof(Color), "Black"), Category("Appearance"), Description("The color of the alternative Focus-Border.")]
+ public Color AlternativeFocusBorderColor {
+ get => alternativeFocusBorderColor;
+ set {
+ if (alternativeFocusBorderColor != value) {
+ alternativeFocusBorderColor = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private Color outerBorderColor;
+ ///
+ /// Gets or sets the outer border color of the control.
+ ///
+ /// A value representing the color of the outer border.
+ [DefaultValue(typeof(Color), "White"), Category("Appearance"), Description("The outer border color of the control.")]
+ public Color OuterBorderColor {
+ get => outerBorderColor;
+ set {
+ if (outerBorderColor != value) {
+ outerBorderColor = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private Color shineColor;
+ ///
+ /// Gets or sets the shine color of the control.
+ ///
+ /// A value representing the shine color.
+ [DefaultValue(typeof(Color), "White"), Category("Appearance"), Description("The shine color of the control.")]
+ public Color ShineColor {
+ get => shineColor;
+ set {
+ if (shineColor != value) {
+ shineColor = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private Color glowColor;
+ ///
+ /// Gets or sets the glow color of the control.
+ ///
+ /// A value representing the glow color.
+ [DefaultValue(typeof(Color), "255,141,189,255"), Category("Appearance"), Description("The glow color of the control.")]
+ public Color GlowColor {
+ get => glowColor;
+ set {
+ if (glowColor != value) {
+ glowColor = value;
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+
+ if (IsHandleCreated) {
+ Invalidate();
+ }
+ }
+ }
+ }
+
+ private bool isHovered;
+ private bool isFocused;
+ private bool isFocusedByKey;
+ private bool isKeyDown;
+ private bool isMouseDown;
+ private bool isPressed => isKeyDown || (isMouseDown && isHovered);
+
+ ///
+ /// Gets the state of the button control.
+ ///
+ /// The state of the button control.
+ [Browsable(false)]
+ public PushButtonState State {
+ get {
+ if (!Enabled) {
+ return PushButtonState.Disabled;
+ }
+ if (isPressed) {
+ return PushButtonState.Pressed;
+ }
+ if (isHovered) {
+ return PushButtonState.Hot;
+ }
+ if (isFocused || IsDefault) {
+ return PushButtonState.Default;
+ }
+ return PushButtonState.Normal;
+ }
+ }
+
+ #endregion
+
+ #region " Overrided Methods "
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected override void OnClick(EventArgs e) {
+ isKeyDown = isMouseDown = false;
+ base.OnClick(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// An that contains the event data.
+ protected override void OnEnter(EventArgs e) {
+ isFocused = isFocusedByKey = true;
+ base.OnEnter(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// An that contains the event data.
+ protected override void OnLeave(EventArgs e) {
+ base.OnLeave(e);
+ isFocused = isFocusedByKey = isKeyDown = isMouseDown = false;
+ Invalidate();
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnKeyDown(KeyEventArgs kevent) {
+ if (kevent.KeyCode == Keys.Space) {
+ isKeyDown = true;
+ Invalidate();
+ }
+ base.OnKeyDown(kevent);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnKeyUp(KeyEventArgs kevent) {
+ if (isKeyDown && kevent.KeyCode == Keys.Space) {
+ isKeyDown = false;
+ Invalidate();
+ }
+ base.OnKeyUp(kevent);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnMouseDown(MouseEventArgs e) {
+ if (!isMouseDown && e.Button == MouseButtons.Left) {
+ isMouseDown = true;
+ isFocusedByKey = false;
+ Invalidate();
+ }
+ base.OnMouseDown(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnMouseUp(MouseEventArgs e) {
+ if (isMouseDown) {
+ isMouseDown = false;
+ Invalidate();
+ }
+ base.OnMouseUp(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnMouseMove(MouseEventArgs mevent) {
+ base.OnMouseMove(mevent);
+ if (mevent.Button == MouseButtons.None) {
+ return;
+ }
+
+ if (!ClientRectangle.Contains(mevent.X, mevent.Y)) {
+ if (isHovered) {
+ isHovered = false;
+ Invalidate();
+ }
+ }
+ else if (!isHovered) {
+ isHovered = true;
+ Invalidate();
+ }
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected override void OnMouseEnter(EventArgs e) {
+ isHovered = true;
+ FadeIn();
+ Invalidate();
+ base.OnMouseEnter(e);
+ }
+
+ ///
+ /// Raises the event.
+ ///
+ /// The instance containing the event data.
+ protected override void OnMouseLeave(EventArgs e) {
+ isHovered = false;
+ FadeOut();
+ Invalidate();
+ base.OnMouseLeave(e);
+ }
+
+ #endregion
+
+ #region " Painting "
+
+ ///
+ /// Raises the event.
+ ///
+ /// A that contains the event data.
+ protected override void OnPaint(PaintEventArgs pevent) {
+ var sm = pevent.Graphics.SmoothingMode;
+ pevent.Graphics.SmoothingMode = SmoothingMode.AntiAlias;
+
+ DrawButtonBackground(pevent.Graphics);
+ DrawForegroundFromButton(pevent);
+ DrawButtonForeground(pevent.Graphics);
+
+ pevent.Graphics.SmoothingMode = sm;
+ }
+
+ ///
+ /// Draws the button background.
+ ///
+ /// The graphics to draw on.
+ private void DrawButtonBackground(Graphics g) {
+ //white border
+ g.DrawPath(outerBorderPen, outerBorderPath);
+
+ //content
+ g.FillPath(ContentBrush, ContentPath);
+
+ //glow
+ if ((isHovered || isAnimating) && !isPressed) {
+ g.SetClip(GlowClip, CombineMode.Intersect);
+ g.FillPath(GlowRadialPath, GlowBottomRadial);
+
+ g.ResetClip();
+ }
+
+ //shine
+ if (drawShine && Enabled) {
+ g.FillPath(ShineBrush, ShinePath);
+ }
+
+ //black border
+ g.DrawPath(BorderPen, BorderPath);
+
+ //Draws the special Symbol
+ if (showSpecialSymbol)
+ DrawSpecialSymbol(g);
+ }
+
+ ///
+ /// Draws the special symbol.
+ ///
+ /// The graphics to draw on.
+ private void DrawSpecialSymbol(Graphics g) {
+ var offset = 15;
+ var LineWidth = Width / 15;
+ var pen = new Pen(specialSymbolBrush, Width / 8) {
+ EndCap = LineCap.ArrowAnchor
+ };
+ var aPen = new Pen(specialSymbolBrush, Width / 4) {
+ EndCap = LineCap.ArrowAnchor
+ };
+ var font = new Font("Arial", LineWidth * 4, FontStyle.Bold);
+
+ switch (specialSymbol) {
+ #region " Arrow Left "
+ case SpecialSymbols.ArrowLeft:
+ g.DrawLine(aPen, Width - Width / 5, Height / 2, Width / 8, Height / 2);
+ break;
+ #endregion
+ #region " Arrow Right "
+ case SpecialSymbols.ArrowRight:
+ g.DrawLine(aPen, Width / 6, Height / 2, Width - Width / 8, Height / 2);
+ break;
+ #endregion
+ #region " Arrow Up "
+ case SpecialSymbols.ArrowUp:
+ g.DrawLine(aPen, Width / 2, Height - Height / 5, Width / 2, Height / 8);
+ break;
+ #endregion
+ #region " Arrow Down "
+ case SpecialSymbols.ArrowDown:
+ g.DrawLine(aPen, Width / 2, Height / 5, Width / 2, Height - Height / 8);
+ break;
+ #endregion
+ #region " Play "
+ case SpecialSymbols.Play:
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 4 + Width / 20, Height / 4),
+ new Point(Width - Width / 4 + Width / 20, Height / 2),
+ new Point(Width / 4 + Width / 20, Height - Height / 4)});
+ break;
+ #endregion
+ #region " Pause "
+ case SpecialSymbols.Pause:
+ g.FillRectangle(specialSymbolBrush, new Rectangle(Width / 4, Height / 4,
+ (Width / 2 - Width / 10) / 2, Height / 2));
+ g.FillRectangle(specialSymbolBrush, new Rectangle(Width / 2 + Width / 20, Height / 4,
+ (Width / 2 - Width / 10) / 2, Height / 2));
+ break;
+ #endregion
+ #region " Stop "
+ case SpecialSymbols.Stop:
+ g.FillRectangle(specialSymbolBrush, new Rectangle(Width / 4 + Width / 20, Height / 4 + Height / 20,
+ Width / 2 - Width / 10, Height / 2 - Width / 10));
+ break;
+ #endregion
+ #region " FastForward "
+ case SpecialSymbols.FastForward:
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 4, Height / 4),
+ new Point(Width / 2, Height / 2),
+ new Point(Width / 4, Height - Height / 4)});
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 2, Height / 4),
+ new Point(3 * Width / 4, Height / 2),
+ new Point(Width / 2, Height - Height / 4)});
+ g.FillRectangle(specialSymbolBrush, new Rectangle(3 * Width / 4, Height / 4,
+ Width / 12, Height / 2));
+ break;
+ #endregion
+ #region " Forward "
+ case SpecialSymbols.Forward:
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 4 + Width / 12, Height / 4),
+ new Point(Width / 2 + Width / 12, Height / 2),
+ new Point(Width / 4 + Width / 12, Height - Height / 4)});
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 2 + Width / 12, Height / 4),
+ new Point(3 * Width / 4 + Width / 12, Height / 2),
+ new Point(Width / 2 + Width / 12, Height - Height / 4)});
+ break;
+ #endregion
+ #region " Backward "
+ case SpecialSymbols.Backward:
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 4 - Width / 12, Height / 2),
+ new Point(Width / 2 - Width / 12, Height / 4),
+ new Point(Width / 2 - Width / 12, Height - Height / 4)});
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 2 - Width / 12, Height / 2),
+ new Point(3 * Width / 4 - Width / 12, Height / 4),
+ new Point(3 * Width / 4 - Width / 12, Height - Height / 4)});
+ break;
+ #endregion
+ #region " FastBackward "
+ case SpecialSymbols.FastBackward:
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 4, Height / 2),
+ new Point(Width / 2, Height / 4),
+ new Point(Width / 2, Height - Height / 4)});
+ g.FillPolygon(specialSymbolBrush, new Point[3]{
+ new Point(Width / 2, Height / 2),
+ new Point(3 * Width / 4, Height / 4),
+ new Point(3 * Width / 4, Height - Height / 4)});
+ g.FillRectangle(specialSymbolBrush, new Rectangle(Width / 4 - Width / 12, Height / 4,
+ Width / 12, Height / 2));
+ break;
+ #endregion
+ #region " Speaker "
+ case SpecialSymbols.Speaker:
+ g.DrawPolygon(new Pen(specialSymbolBrush, Width / 20), new Point[6] {
+ new Point(Width / 2 - Width / 6 - Width / offset, Height / 4 + Height / 10),
+ new Point(Width / 2 - Width / offset, Height / 4 + Height / 10),
+ new Point(Width / 2 + Width / 5 - Width / offset, Height / 4),
+ new Point(Width / 2 + Width / 5 - Width / offset, 3 * Height / 4),
+ new Point(Width / 2 - Width / offset, 3 * Height / 4 - Height / 10),
+ new Point(Width / 2 - Width / 6 - Width / offset, 3 * Height / 4 - Height / 10)});
+ g.DrawLine(new Pen(specialSymbolBrush, Width / 20), Width / 2 - Width / offset,
+ Height / 4 + Height / 10 + Width / 40, Width / 2 - Width / offset, Height - (Height / 4 + Height / 10 + Width / 40));
+ break;
+ #endregion
+ #region " NoSpeaker "
+ case SpecialSymbols.NoSpeaker:
+ g.DrawPolygon(new Pen(specialSymbolBrush, Width / 20), new Point[6] {
+ new Point(Width / 2 - Width / 6 - Width / offset, Height / 4 + Height / 10),
+ new Point(Width / 2 - Width / offset, Height / 4 + Height / 10),
+ new Point(Width / 2 + Width / 5 - Width / offset, Height / 4),
+ new Point(Width / 2 + Width / 5 - Width / offset, 3 * Height / 4),
+ new Point(Width / 2 - Width / offset, 3 * Height / 4 - Height / 10),
+ new Point(Width / 2 - Width / 6 - Width / offset, 3 * Height / 4 - Height / 10)});
+ g.DrawLine(new Pen(specialSymbolBrush, Width / 20), Width / 2 - Width / offset,
+ Height / 4 + Height / 10 + Width / 40, Width / 2 - Width / offset, Height - (Height / 4 + Height / 10 + Width / 40));
+ g.DrawLine(new Pen(specialSymbolBrush, Width / 20), (int)(Width / 2 - Width / 3.5 - Width / offset), 3 * Height / 4 - Height / 10,
+ Width / 2 + Width / 3 - Width / offset, Height / 4 + Height / 12 + Width / 40);
+ break;
+ #endregion
+ #region " Repeat "
+ case SpecialSymbols.Repeat:
+ g.DrawLine(new Pen(specialSymbolBrush, LineWidth),
+ new Point((int)(Width / 4), (int)(Height / 3)),
+ new Point((int)(Width - Width / 2.4), (int)(Height / 3)));
+ g.DrawArc(new Pen(specialSymbolBrush, LineWidth), (int)(Width - Width * 0.6), (int)(Height / 3),
+ (int)(Width / 3), (int)(Height / 3), 270, 180);
+ g.DrawLine(new Pen(specialSymbolBrush, LineWidth),
+ new Point((int)(Width - Width / 2.4), (int)(Height - Height / 3)),
+ new Point((int)(Width / 3.2), (int)(Height - Height / 3)));
+ g.DrawLine(pen,
+ new Point((int)(Width / 3.2), (int)(Height - Height / 3)),
+ new Point((int)(Width / 4), (int)(Height - Height / 3)));
+ break;
+ #endregion
+ #region " RepeatAll "
+ case SpecialSymbols.RepeatAll:
+ g.DrawLine(new Pen(specialSymbolBrush, LineWidth),
+ new Point((int)(Width / 2.4), (int)(Height / 3)),
+ new Point((int)(Width - Width / 2.4), (int)(Height / 3)));
+ g.DrawArc(new Pen(specialSymbolBrush, LineWidth), (int)(Width - Width * 0.6), (int)(Height / 3),
+ (int)(Width / 3), (int)(Height / 3), 270, 180);
+ g.DrawLine(new Pen(specialSymbolBrush, LineWidth),
+ new Point((int)(Width - Width / 2.4), (int)(Height - Height / 3)),
+ new Point((int)(Width / 2.4), (int)(Height - Height / 3)));
+ g.DrawLine(pen,
+ new Point((int)(Width / 2.4), (int)(Height - Height / 3)),
+ new Point((int)(Width / 3), (int)(Height - Height / 3)));
+ g.DrawArc(new Pen(specialSymbolBrush, LineWidth), (int)(Width / 4), (int)(Height / 3),
+ (int)(Width / 3), (int)(Height / 3), 90, 180);
+ break;
+ #endregion
+ #region " Shuffle "
+ case SpecialSymbols.Shuffle:
+ g.DrawString("1", font, specialSymbolBrush, (Width / 2) / 4, Height / 2 - LineWidth * 2);
+ var sWidth = (int)g.MeasureString("2", font).Width;
+ var sHeigth = (int)g.MeasureString("2", font).Height;
+ g.DrawString("2", font, specialSymbolBrush, Width / 2 - sWidth / 2 - Width / (2 * offset), Height - LineWidth - sHeigth);
+ sWidth = (int)g.MeasureString("3", font).Width;
+ g.DrawString("3", font, specialSymbolBrush, Width - (Width / 2) / 4 - sWidth - Width / (2 * offset), Height / 2 - LineWidth * 2);
+ g.DrawArc(pen, (Width / 2) / 2, Height / 6, Width - (Width / 2), (int)(Height / 2.2), 170, 210);
+ break;
+ #endregion
+ default:
+ break;
+ }
+ }
+
+ ///
+ /// Draws the button foreground.
+ ///
+ /// The graphics to draw on.
+ private void DrawButtonForeground(Graphics g) {
+ if (ShowFocusBorder && Focused && ShowFocusCues && !alternativeForm) {
+ var rect = ClientRectangle;
+ rect.Inflate(-4, -4);
+ ControlPaint.DrawFocusRectangle(g, rect);
+ }
+ }
+
+ private Button imageButton;
+ ///
+ /// Draws the foreground from button.
+ ///
+ /// The instance containing the event data.
+ private void DrawForegroundFromButton(PaintEventArgs pevent) {
+ if (imageButton == null) {
+ imageButton = new Button {
+ Parent = new TransparentControl(),
+ BackColor = Color.Transparent
+ };
+ imageButton.FlatAppearance.BorderSize = 0;
+ imageButton.FlatStyle = FlatStyle.Flat;
+ }
+ if (direction != 0) {
+ imageButton.SuspendLayout();
+ }
+ imageButton.ForeColor = ForeColor;
+ imageButton.Font = Font;
+ imageButton.RightToLeft = RightToLeft;
+ imageButton.Image = Image;
+ imageButton.ImageAlign = ImageAlign;
+ imageButton.ImageIndex = ImageIndex;
+ imageButton.ImageKey = ImageKey;
+ imageButton.ImageList = ImageList;
+ imageButton.Padding = Padding;
+ imageButton.Size = Size;
+ imageButton.Text = Text;
+ imageButton.TextAlign = TextAlign;
+ imageButton.TextImageRelation = TextImageRelation;
+ imageButton.UseCompatibleTextRendering = UseCompatibleTextRendering;
+ imageButton.UseMnemonic = UseMnemonic;
+ if (direction != 0) {
+ imageButton.ResumeLayout();
+ }
+ InvokePaint(imageButton, pevent);
+ }
+
+ sealed class TransparentControl : Control
+ {
+ protected override void OnPaintBackground(PaintEventArgs pevent) { }
+ protected override void OnPaint(PaintEventArgs e) { }
+ }
+
+ ///
+ /// Creates the round rectangle.
+ ///
+ /// The rectangle.
+ /// The radius.
+ ///
+ private GraphicsPath CreateRoundRectangle(Rectangle rectangle, int radius) {
+ var path = new GraphicsPath();
+ var l = rectangle.Left;
+ var t = rectangle.Top;
+ var w = rectangle.Width;
+ var h = rectangle.Height;
+ var d = radius << 1;
+
+ if (alternativeForm) {
+ if (alternativeFormDirection == Direction.Left) {
+ path.AddArc(l, t, h, h, 90, 180);
+ path.AddLine(l + h, t, l + w, t);
+ path.AddCurve(new Point[5] {
+ new Point(l + w, t),
+ new Point(l + w - h / 6, t + h / 4),
+ new Point((int)(l + w - (double)(h / 4.7)), t + h / 2),
+ new Point(l + w - h / 6, t + 3 * h / 4),
+ new Point(l + w, t + h) });
+ path.AddLine(l + h, t + h, l + w, t + h);
+ }
+ else {
+ path.AddCurve(new Point[5] {
+ new Point(l, t),
+ new Point(l + h / 6, t + h / 4),
+ new Point((int)(l + (double)(h / 4.85)), t + h / 2),
+ new Point(l + h / 6, t + 3 * h / 4),
+ new Point(l, t + h) });
+ path.AddLine(l, t + h, l + w - h, t + h);
+ path.AddArc(l + w - h, t, h, h, 90, -180);
+ path.AddLine(l + w - h, t, l, t);
+ }
+ }
+ else {
+ path.AddArc(l, t, d, d, 180, 90); // topleft
+ path.AddLine(l + radius, t, l + w - radius, t); // top
+ path.AddArc(l + w - d, t, d, d, 270, 90); // topright
+ path.AddLine(l + w, t + radius, l + w, t + h - radius); // right
+ path.AddArc(l + w - d, t + h - d, d, d, 0, 90); // bottomright
+ path.AddLine(l + w - radius, t + h, l + radius, t + h); // bottom
+ path.AddArc(l, t + h - d, d, d, 90, 90); // bottomleft
+ path.AddLine(l, t + h - radius, l, t + radius); // left
+ }
+
+ path.CloseFigure();
+
+ return path;
+ }
+
+ ///
+ /// Creates the top round rectangle.
+ ///
+ /// The rectangle.
+ /// The radius.
+ ///
+ private GraphicsPath CreateTopRoundRectangle(Rectangle rectangle, int radius) {
+ var path = new GraphicsPath();
+ var l = rectangle.Left;
+ var t = rectangle.Top;
+ var w = rectangle.Width;
+ var h = rectangle.Height;
+ var d = radius << 1;
+
+ if (alternativeForm) {
+ if (alternativeFormDirection == Direction.Left) {
+ path.AddArc(l, t, h * 2, h * 2, 180, 90);
+ path.AddLine(l + h, t, l + w, t);
+ path.AddCurve(new Point[3] {
+ new Point(l + w, t),
+ new Point(l + w - h / 3, t + h / 2),
+ new Point((int)(l + w - (double)(h / 2.35)), t + h)});
+ }
+ else {
+ path.AddCurve(new Point[3] {
+ new Point(l, t),
+ new Point(l + h / 3, t + h / 2),
+ new Point((int)(l + (double)(h / 2.35)), t + h)});
+ path.AddLine((int)(l + (double)(h / 2.35)), t + h, l + w - h, t + h);
+ path.AddArc(l + w - h * 2, t, h * 2, h * 2, 0, -90);
+ }
+ }
+ else {
+ path.AddArc(l, t, d, d, 180, 90); // topleft
+ path.AddLine(l + radius, t, l + w - radius, t); // top
+ path.AddArc(l + w - d, t, d, d, 270, 90); // topright
+ path.AddLine(l + w, t + radius, l + w, t + h); // right
+ path.AddLine(l + w, t + h, l, t + h); // bottom
+ path.AddLine(l, t + h, l, t + radius); // left
+ }
+
+ path.CloseFigure();
+
+ return path;
+ }
+
+ ///
+ /// Creates the bottom radial path.
+ ///
+ /// The rectangle.
+ ///
+ private GraphicsPath CreateBottomRadialPath(Rectangle rectangle) {
+ var path = new GraphicsPath();
+ RectangleF rect = rectangle;
+ rect.X -= rectangle.Width * .35f;
+ rect.Y -= rectangle.Height * .15f;
+ rect.Width *= 1.7f;
+ rect.Height *= 2.3f;
+ path.AddEllipse(rect);
+ path.CloseFigure();
+ return path;
+ }
+
+ ///
+ /// Handles the SizeChanged event of the GlassButton control.
+ ///
+ /// The source of the event.
+ /// The instance containing the event data.
+ private void GlassButton_SizeChanged(object sender, EventArgs e) {
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+ }
+
+ ///
+ /// Handles the MouseLeave event of the GlassButton control.
+ ///
+ /// The source of the event.
+ /// The instance containing the event data.
+ private void GlassButton_MouseLeave(object sender, EventArgs e) {
+ RecalcGlow((float)currentFrame / (framesCount - 1f));
+ }
+
+ ///
+ /// Handles the MouseEnter event of the GlassButton control.
+ ///
+ /// The source of the event.
+ /// The instance containing the event data.
+ private void GlassButton_MouseEnter(object sender, EventArgs e) {
+ RecalcGlow((float)currentFrame / (framesCount - 1f));
+ }
+
+ ///
+ /// Handles the LostFocus event of the GlassButton control.
+ ///
+ /// The source of the event.
+ /// The instance containing the event data.
+ private void GlassButton_LostFocus(object sender, EventArgs e) {
+ RecalcOuterBorder();
+ }
+
+ ///
+ /// Handles the GotFocus event of the GlassButton control.
+ ///
+ /// The source of the event.
+ /// The instance containing the event data.
+ private void GlassButton_GotFocus(object sender, EventArgs e) {
+ RecalcOuterBorder();
+ }
+
+ ///
+ /// Recalcs the rectangles for drawing.
+ ///
+ /// The glow opacity.
+ private void RecalcRect(float glowOpacity) {
+ try {
+ var rCorner = roundCorner;
+
+ if (roundCorner > Height / 2)
+ rCorner = Height / 2;
+
+ if (roundCorner > Width / 2)
+ rCorner = Width / 2;
+
+ rect = RecalcOuterBorder();
+
+ rect = RecalcContent(rect, out rect2);
+
+ RecalcGlow(glowOpacity);
+
+ rect2 = RecalcShine(rect2);
+
+ BorderPath = CreateRoundRectangle(rect, rCorner);
+
+ BorderPen = new Pen(innerBorderColor);
+ }
+ catch { }
+ }
+
+ ///
+ /// Recalcs the shine.
+ ///
+ /// The rect2.
+ ///
+ private Rectangle RecalcShine(Rectangle rect2) {
+ var rCorner = roundCorner;
+
+ if (roundCorner > Height / 2)
+ rCorner = Height / 2;
+
+ if (roundCorner > Width / 2)
+ rCorner = Width / 2;
+
+ if (rect2.Width > 0 && rect2.Height > 0) {
+ rect2.Height++;
+ ShinePath = CreateTopRoundRectangle(rect2, rCorner);
+
+ rect2.Height++;
+ var opacity = 0x99;
+ if (isPressed)
+ opacity = (int)(.4f * opacity + .5f);
+ ShineBrush = new LinearGradientBrush(rect2, Color.FromArgb(opacity, shineColor), Color.FromArgb(opacity / 3, shineColor), LinearGradientMode.Vertical);
+
+ rect2.Height -= 2;
+
+ drawShine = true;
+ }
+ else
+ drawShine = false;
+ return rect2;
+ }
+
+ ///
+ /// Recalcs the glow.
+ ///
+ /// The glow opacity.
+ private void RecalcGlow(float glowOpacity) {
+ var rCorner = roundCorner;
+
+ if (roundCorner > Height / 2)
+ rCorner = Height / 2;
+
+ if (roundCorner > Width / 2)
+ rCorner = Width / 2;
+
+ GlowClip = CreateRoundRectangle(rect, rCorner);
+ GlowBottomRadial = CreateBottomRadialPath(rect);
+
+ GlowRadialPath = new PathGradientBrush(GlowBottomRadial);
+
+ var opacity = (int)(0xB2 * glowOpacity + .5f);
+
+ if (!animateGlow) {
+ if (isHovered)
+ opacity = 255;
+ else
+ opacity = 0;
+ }
+
+ GlowRadialPath.CenterColor = Color.FromArgb(opacity, glowColor);
+ GlowRadialPath.SurroundColors = new Color[] { Color.FromArgb(0, glowColor) };
+ }
+
+ ///
+ /// Recalcs the content.
+ ///
+ /// The rect.
+ /// The rect2.
+ ///
+ private Rectangle RecalcContent(Rectangle rect, out Rectangle rect2) {
+ var rCorner = roundCorner;
+
+ if (roundCorner > Height / 2)
+ rCorner = Height / 2;
+
+ if (roundCorner > Width / 2)
+ rCorner = Width / 2;
+
+ rect.X++;
+ rect.Y++;
+ rect.Width -= 2;
+ rect.Height -= 2;
+
+ rect2 = rect;
+ rect2.Height >>= 1;
+
+ ContentPath = CreateRoundRectangle(rect, rCorner);
+ var opacity = isPressed ? 0xcc : 0x7f;
+ ContentBrush = new SolidBrush(Color.FromArgb(opacity, backColor));
+ return rect;
+ }
+
+ ///
+ /// Recalcs the outer border.
+ ///
+ ///
+ private Rectangle RecalcOuterBorder() {
+ var rCorner = roundCorner;
+
+ if (roundCorner > Height / 2)
+ rCorner = Height / 2;
+
+ if (roundCorner > Width / 2)
+ rCorner = Width / 2;
+
+ Rectangle rect;
+ rect = ClientRectangle;
+ rect.Width--;
+ rect.Height--;
+ outerBorderPath = CreateRoundRectangle(rect, rCorner);
+ rect.Inflate(1, 1);
+ var region = CreateRoundRectangle(rect, rCorner);
+ Region = new Region(region);
+ rect.Inflate(-1, -1);
+
+ var col = outerBorderColor;
+ if (Focused && !ShowFocusBorder)
+ col = alternativeFocusBorderColor;
+
+ outerBorderPen = new Pen(col);
+ return rect;
+ }
+
+ #endregion
+
+ #region " Unused Properties & Events "
+
+ /// This property is not relevant for this class.
+ /// This property is not relevant for this class.
+ [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
+ public new FlatButtonAppearance FlatAppearance => base.FlatAppearance;
+
+ /// This property is not relevant for this class.
+ /// This property is not relevant for this class.
+ [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
+ public new FlatStyle FlatStyle {
+ get => base.FlatStyle;
+ set => base.FlatStyle = value;
+ }
+
+ /// This property is not relevant for this class.
+ /// This property is not relevant for this class.
+ [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden), EditorBrowsable(EditorBrowsableState.Never)]
+ public new bool UseVisualStyleBackColor {
+ get => base.UseVisualStyleBackColor;
+ set => base.UseVisualStyleBackColor = value;
+ }
+
+ #endregion
+
+ #region " Animation Support "
+
+ private const int animationLength = 300;
+ private const int framesCount = 10;
+ private int currentFrame;
+ private int direction;
+
+ private bool isAnimating => direction != 0;
+
+ private void FadeIn() {
+ direction = 1;
+ timer.Enabled = true;
+ }
+
+ private void FadeOut() {
+ direction = -1;
+ timer.Enabled = true;
+ }
+
+ private void timer_Tick(object sender, EventArgs e) {
+ if (!timer.Enabled || !animateGlow) {
+ return;
+ }
+
+ RecalcRect((float)currentFrame / (framesCount - 1f));
+ Refresh();
+ currentFrame += direction;
+ if (currentFrame == -1) {
+ currentFrame = 0;
+ timer.Enabled = false;
+ direction = 0;
+ return;
+ }
+ if (currentFrame == framesCount) {
+ currentFrame = framesCount - 1;
+ timer.Enabled = false;
+ direction = 0;
+ }
+ }
+
+ #endregion
+ }
+}
diff --git a/pdfpatcher/App/Functions/CustomizeToolbarForm.Designer.cs b/pdfpatcher/App/Functions/CustomizeToolbarForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f52f275d075c3ceb5b2c14f800978421ab6f4a9d
--- /dev/null
+++ b/pdfpatcher/App/Functions/CustomizeToolbarForm.Designer.cs
@@ -0,0 +1,160 @@
+namespace PDFPatcher.Functions
+{
+ partial class CustomizeToolbarForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container();
+ this._ItemListBox = new BrightIdeasSoftware.ObjectListView();
+ this._NameColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._VisibleColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ShowTextColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._DisplayTextColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ButtonImageList = new System.Windows.Forms.ImageList(this.components);
+ this._OkButton = new System.Windows.Forms.Button();
+ this._ResetButton = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ ((System.ComponentModel.ISupportInitialize)(this._ItemListBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // _ItemListBox
+ //
+ this._ItemListBox.AllColumns.Add(this._NameColumn);
+ this._ItemListBox.AllColumns.Add(this._VisibleColumn);
+ this._ItemListBox.AllColumns.Add(this._ShowTextColumn);
+ this._ItemListBox.AllColumns.Add(this._DisplayTextColumn);
+ this._ItemListBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClickAlways;
+ this._ItemListBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._NameColumn,
+ this._VisibleColumn,
+ this._ShowTextColumn,
+ this._DisplayTextColumn});
+ this._ItemListBox.Location = new System.Drawing.Point(12, 46);
+ this._ItemListBox.Name = "_ItemListBox";
+ this._ItemListBox.OwnerDraw = true;
+ this._ItemListBox.ShowGroups = false;
+ this._ItemListBox.Size = new System.Drawing.Size(388, 263);
+ this._ItemListBox.SmallImageList = this._ButtonImageList;
+ this._ItemListBox.TabIndex = 0;
+ this._ItemListBox.UseCompatibleStateImageBehavior = false;
+ this._ItemListBox.View = System.Windows.Forms.View.Details;
+ //
+ // _NameColumn
+ //
+ this._NameColumn.IsEditable = false;
+ this._NameColumn.Text = "工具栏按钮";
+ this._NameColumn.Width = 145;
+ //
+ // _VisibleColumn
+ //
+ this._VisibleColumn.CheckBoxes = true;
+ this._VisibleColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._VisibleColumn.Text = "显示";
+ this._VisibleColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._VisibleColumn.Width = 54;
+ //
+ // _ShowTextColumn
+ //
+ this._ShowTextColumn.CheckBoxes = true;
+ this._ShowTextColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._ShowTextColumn.Text = "显示文本";
+ this._ShowTextColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._ShowTextColumn.Width = 63;
+ //
+ // _DisplayTextColumn
+ //
+ this._DisplayTextColumn.AutoCompleteEditor = false;
+ this._DisplayTextColumn.AutoCompleteEditorMode = System.Windows.Forms.AutoCompleteMode.None;
+ this._DisplayTextColumn.Text = "按钮文本内容";
+ this._DisplayTextColumn.Width = 120;
+ //
+ // _ButtonImageList
+ //
+ this._ButtonImageList.ColorDepth = System.Windows.Forms.ColorDepth.Depth8Bit;
+ this._ButtonImageList.ImageSize = new System.Drawing.Size(16, 16);
+ this._ButtonImageList.TransparentColor = System.Drawing.Color.Transparent;
+ //
+ // _OkButton
+ //
+ this._OkButton.Location = new System.Drawing.Point(325, 315);
+ this._OkButton.Name = "_OkButton";
+ this._OkButton.Size = new System.Drawing.Size(75, 23);
+ this._OkButton.TabIndex = 1;
+ this._OkButton.Text = "确定(&Q)";
+ this._OkButton.UseVisualStyleBackColor = true;
+ this._OkButton.Click += new System.EventHandler(this._OkButton_Click);
+ //
+ // _ResetButton
+ //
+ this._ResetButton.Location = new System.Drawing.Point(12, 315);
+ this._ResetButton.Name = "_ResetButton";
+ this._ResetButton.Size = new System.Drawing.Size(127, 23);
+ this._ResetButton.TabIndex = 2;
+ this._ResetButton.Text = "重置常用工具栏";
+ this._ResetButton.UseVisualStyleBackColor = true;
+ this._ResetButton.Click += new System.EventHandler(this._ResetButton_Click);
+ //
+ // label1
+ //
+ this.label1.Location = new System.Drawing.Point(12, 9);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(305, 34);
+ this.label1.TabIndex = 3;
+ this.label1.Text = "使用鼠标上下拖动项目可调整工具按钮的显示顺序。\r\n要隐藏按钮,请取消“是否显示”的选中状态。";
+ //
+ // CustomizeToolbarForm
+ //
+ this.AcceptButton = this._OkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(412, 350);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this._ResetButton);
+ this.Controls.Add(this._OkButton);
+ this.Controls.Add(this._ItemListBox);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "CustomizeToolbarForm";
+ this.ShowInTaskbar = false;
+ this.Text = "自定义常用工具栏项目";
+ this.Load += new System.EventHandler(this.CustomizeToolbarForm_Load);
+ ((System.ComponentModel.ISupportInitialize)(this._ItemListBox)).EndInit();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private BrightIdeasSoftware.ObjectListView _ItemListBox;
+ private System.Windows.Forms.Button _OkButton;
+ private BrightIdeasSoftware.OLVColumn _NameColumn;
+ private BrightIdeasSoftware.OLVColumn _VisibleColumn;
+ private BrightIdeasSoftware.OLVColumn _ShowTextColumn;
+ private System.Windows.Forms.Button _ResetButton;
+ private System.Windows.Forms.ImageList _ButtonImageList;
+ private System.Windows.Forms.Label label1;
+ private BrightIdeasSoftware.OLVColumn _DisplayTextColumn;
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/CustomizeToolbarForm.cs b/pdfpatcher/App/Functions/CustomizeToolbarForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..840cacc5182a132b41973ff713b1ba7e8d1ca253
--- /dev/null
+++ b/pdfpatcher/App/Functions/CustomizeToolbarForm.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+using PDFPatcher.Common;
+using BO = PDFPatcher.ToolbarOptions.ButtonOption;
+
+namespace PDFPatcher.Functions
+{
+ public partial class CustomizeToolbarForm : Form
+ {
+ public CustomizeToolbarForm() {
+ InitializeComponent();
+ }
+
+ void _ResetButton_Click(object sender, EventArgs e) {
+ AppContext.Toolbar.Reset();
+ _ItemListBox.Objects = AppContext.Toolbar.Buttons;
+ }
+
+ void CustomizeToolbarForm_Load(object sender, EventArgs e) {
+ foreach (var item in Toolkit.Toolkits) {
+ _ItemListBox.SmallImageList.Images.Add(item.Icon, Properties.Resources.ResourceManager.GetObject(item.Icon) as Image);
+ }
+ new TypedColumn(_NameColumn) {
+ AspectGetter = (o) => o.GetToolkit().Name,
+ ImageGetter = (o) => o.GetToolkit().Icon
+ };
+ new TypedColumn(_ShowTextColumn) {
+ AspectGetter = (o) => o.ShowText,
+ AspectPutter = (o, v) => o.ShowText = (bool)v
+ };
+ new TypedColumn(_VisibleColumn) {
+ AspectGetter = (o) => o.Visible,
+ AspectPutter = (o, v) => o.Visible = (bool)v
+ };
+ new TypedColumn(_DisplayTextColumn) {
+ AspectGetter = (o) => o.DisplayName,
+ AspectPutter = (o, v) => o.DisplayName = v as string ?? o.GetToolkit().Name,
+ };
+ AppContext.Toolbar.AddMissedButtons();
+ _ItemListBox.IsSimpleDragSource = true;
+ _ItemListBox.IsSimpleDropSink = true;
+ _ItemListBox.DragSource = new SimpleDragSource(true);
+ _ItemListBox.DropSink = new RearrangingDropSink(false) {
+ CanDropBetween = true,
+ CanDropOnItem = false
+ };
+ _ItemListBox.Objects = AppContext.Toolbar.Buttons;
+ _ItemListBox.FixEditControlWidth();
+ _ItemListBox.ScaleColumnWidths();
+ }
+
+ void _OkButton_Click(object sender, EventArgs e) {
+ var l = new List();
+ foreach (BO item in _ItemListBox.Objects) {
+ l.Add(item);
+ }
+ AppContext.Toolbar.Buttons.Clear();
+ AppContext.Toolbar.Buttons.AddRange(l);
+ Close();
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/CustomizeToolbarForm.resx b/pdfpatcher/App/Functions/CustomizeToolbarForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..b1a334ff148e02a86e9830a423b6569cde4899f6
--- /dev/null
+++ b/pdfpatcher/App/Functions/CustomizeToolbarForm.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.Designer.cs b/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..cdf1268ff1938845b09c1d4b12313f0cb9649216
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.Designer.cs
@@ -0,0 +1,179 @@
+namespace PDFPatcher.Functions
+{
+ partial class AddPdfObjectForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this._OkButton = new System.Windows.Forms.Button();
+ this._CancelButton = new System.Windows.Forms.Button();
+ this.label1 = new System.Windows.Forms.Label();
+ this._ObjectNameBox = new System.Windows.Forms.TextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this._TextValueBox = new System.Windows.Forms.TextBox();
+ this._NumericValueBox = new System.Windows.Forms.TextBox();
+ this._BooleanValueBox = new System.Windows.Forms.CheckBox();
+ this._NameValueBox = new System.Windows.Forms.TextBox();
+ this._CreateAsRefBox = new System.Windows.Forms.CheckBox();
+ this.SuspendLayout();
+ //
+ // _OkButton
+ //
+ this._OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._OkButton.Location = new System.Drawing.Point(111, 141);
+ this._OkButton.Name = "_OkButton";
+ this._OkButton.Size = new System.Drawing.Size(75, 23);
+ this._OkButton.TabIndex = 0;
+ this._OkButton.Text = "确定(&Q)";
+ this._OkButton.UseVisualStyleBackColor = true;
+ this._OkButton.Click += new System.EventHandler(this._OkButton_Click);
+ //
+ // _CancelButton
+ //
+ this._CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this._CancelButton.Location = new System.Drawing.Point(192, 141);
+ this._CancelButton.Name = "_CancelButton";
+ this._CancelButton.Size = new System.Drawing.Size(75, 23);
+ this._CancelButton.TabIndex = 1;
+ this._CancelButton.Text = "取消(&X)";
+ this._CancelButton.UseVisualStyleBackColor = true;
+ this._CancelButton.Click += new System.EventHandler(this._CancelButton_Click);
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(12, 15);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(41, 12);
+ this.label1.TabIndex = 4;
+ this.label1.Text = "名称:";
+ //
+ // _ObjectNameBox
+ //
+ this._ObjectNameBox.Location = new System.Drawing.Point(59, 12);
+ this._ObjectNameBox.Name = "_ObjectNameBox";
+ this._ObjectNameBox.Size = new System.Drawing.Size(208, 21);
+ this._ObjectNameBox.TabIndex = 5;
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(12, 42);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(41, 12);
+ this.label2.TabIndex = 6;
+ this.label2.Text = "取值:";
+ //
+ // _TextValueBox
+ //
+ this._TextValueBox.AcceptsReturn = true;
+ this._TextValueBox.AcceptsTab = true;
+ this._TextValueBox.Location = new System.Drawing.Point(59, 39);
+ this._TextValueBox.Multiline = true;
+ this._TextValueBox.Name = "_TextValueBox";
+ this._TextValueBox.Size = new System.Drawing.Size(208, 56);
+ this._TextValueBox.TabIndex = 7;
+ this._TextValueBox.Visible = false;
+ //
+ // _NumericValueBox
+ //
+ this._NumericValueBox.Location = new System.Drawing.Point(7, 123);
+ this._NumericValueBox.Name = "_NumericValueBox";
+ this._NumericValueBox.Size = new System.Drawing.Size(100, 21);
+ this._NumericValueBox.TabIndex = 8;
+ this._NumericValueBox.Visible = false;
+ //
+ // _BooleanValueBox
+ //
+ this._BooleanValueBox.AutoSize = true;
+ this._BooleanValueBox.Location = new System.Drawing.Point(7, 79);
+ this._BooleanValueBox.Name = "_BooleanValueBox";
+ this._BooleanValueBox.Size = new System.Drawing.Size(48, 16);
+ this._BooleanValueBox.TabIndex = 9;
+ this._BooleanValueBox.Text = "True";
+ this._BooleanValueBox.UseVisualStyleBackColor = true;
+ this._BooleanValueBox.Visible = false;
+ //
+ // _NameValueBox
+ //
+ this._NameValueBox.Location = new System.Drawing.Point(7, 138);
+ this._NameValueBox.Name = "_NameValueBox";
+ this._NameValueBox.Size = new System.Drawing.Size(100, 21);
+ this._NameValueBox.TabIndex = 10;
+ this._NameValueBox.Visible = false;
+ //
+ // _CreateAsRefBox
+ //
+ this._CreateAsRefBox.AutoSize = true;
+ this._CreateAsRefBox.Location = new System.Drawing.Point(59, 101);
+ this._CreateAsRefBox.Name = "_CreateAsRefBox";
+ this._CreateAsRefBox.Size = new System.Drawing.Size(132, 16);
+ this._CreateAsRefBox.TabIndex = 11;
+ this._CreateAsRefBox.Text = "创建为间接引用节点";
+ this._CreateAsRefBox.UseVisualStyleBackColor = true;
+ //
+ // AddPdfObjectForm
+ //
+ this.AcceptButton = this._OkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this._CancelButton;
+ this.ClientSize = new System.Drawing.Size(279, 176);
+ this.Controls.Add(this._CreateAsRefBox);
+ this.Controls.Add(this._NameValueBox);
+ this.Controls.Add(this._BooleanValueBox);
+ this.Controls.Add(this._NumericValueBox);
+ this.Controls.Add(this._TextValueBox);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this._ObjectNameBox);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this._CancelButton);
+ this.Controls.Add(this._OkButton);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AddPdfObjectForm";
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
+ this.Text = "添加PDF对象";
+ this.Load += new System.EventHandler(this.AddPdfObjectForm_Load);
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _OkButton;
+ private System.Windows.Forms.Button _CancelButton;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox _ObjectNameBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox _TextValueBox;
+ private System.Windows.Forms.TextBox _NumericValueBox;
+ private System.Windows.Forms.CheckBox _BooleanValueBox;
+ private System.Windows.Forms.TextBox _NameValueBox;
+ private System.Windows.Forms.CheckBox _CreateAsRefBox;
+ }
+}
+
diff --git a/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.cs b/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..08535e0c5b0ff5b074bc57fd66f56085df7aa300
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Windows.Forms;
+using iTextSharp.text.pdf;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class AddPdfObjectForm : Form
+ {
+ readonly Control[] _editBoxes;
+ public string ObjectName => _ObjectNameBox.Text;
+ int _PdfObjectType;
+ ///获取或指定Description的值。
+ public int PdfObjectType {
+ get => _PdfObjectType;
+ set {
+ _PdfObjectType = value;
+ FormHelper.ToggleVisibility(false, _editBoxes);
+ switch (value) {
+ case PdfObject.ARRAY: break;
+ case PdfObject.BOOLEAN: _BooleanValueBox.Visible = true; break;
+ case PdfObject.DICTIONARY: break;
+ case PdfObject.NAME: _NameValueBox.Visible = true; break;
+ case PdfObject.NUMBER: _NumericValueBox.Visible = true; break;
+ case PdfObject.STRING: _TextValueBox.Visible = true; break;
+ }
+ }
+ }
+ public bool CreateAsIndirect => _CreateAsRefBox.Checked;
+ public PdfObject PdfValue {
+ get {
+ PdfObject o;
+ switch (_PdfObjectType) {
+ case PdfObject.NAME: o = new PdfName(String.IsNullOrEmpty(_NameValueBox.Text) ? "name" : _NameValueBox.Text); break;
+ case PdfObject.DICTIONARY: o = new PdfDictionary(); break;
+ case PdfObject.ARRAY: o = new PdfArray(); break;
+ case PdfObject.BOOLEAN: o = new PdfBoolean(_BooleanValueBox.Checked); break;
+ case PdfObject.STRING: o = _TextValueBox.Text.ToPdfString(); break;
+ case PdfObject.NUMBER: o = new PdfNumber(_NumericValueBox.Text.ToDouble()); break;
+ default: return null;
+ }
+ return o;
+ }
+ }
+ public AddPdfObjectForm() {
+ InitializeComponent();
+ _editBoxes = new Control[] { _NameValueBox, _NumericValueBox, _BooleanValueBox, _TextValueBox };
+ }
+
+ void AddPdfObjectForm_Load(object sender, EventArgs e) {
+ _NameValueBox.Location = _NumericValueBox.Location = _BooleanValueBox.Location = _TextValueBox.Location;
+ }
+
+ void _OkButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ void _CancelButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.resx b/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/AddPdfObjectForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.Designer.cs b/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..172134f88799b4e7e0b59c3a54c7877c2d1120ae
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.Designer.cs
@@ -0,0 +1,121 @@
+namespace PDFPatcher.Functions
+{
+ partial class ImageViewerForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ System.Windows.Forms.ToolStripButton _Save;
+ System.Windows.Forms.ToolStripButton _ZoomReset;
+ this._MainToolbar = new System.Windows.Forms.ToolStrip ();
+ this._FitWindow = new System.Windows.Forms.ToolStripButton ();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator ();
+ this._ImageBox = new Cyotek.Windows.Forms.ImageBox ();
+ _Save = new System.Windows.Forms.ToolStripButton ();
+ _ZoomReset = new System.Windows.Forms.ToolStripButton ();
+ this._MainToolbar.SuspendLayout ();
+ this.SuspendLayout ();
+ //
+ // _MainToolbar
+ //
+ this._MainToolbar.Items.AddRange (new System.Windows.Forms.ToolStripItem[] {
+ _Save,
+ this.toolStripSeparator1,
+ _ZoomReset,
+ this._FitWindow});
+ this._MainToolbar.Location = new System.Drawing.Point (0, 0);
+ this._MainToolbar.Name = "_MainToolbar";
+ this._MainToolbar.Size = new System.Drawing.Size (539, 25);
+ this._MainToolbar.TabIndex = 1;
+ this._MainToolbar.Text = "toolStrip1";
+ this._MainToolbar.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler (this._MainToolbar_ItemClicked);
+ //
+ // _Save
+ //
+ _Save.Image = global::PDFPatcher.Properties.Resources.Save;
+ _Save.ImageTransparentColor = System.Drawing.Color.Magenta;
+ _Save.Name = "_Save";
+ _Save.Size = new System.Drawing.Size (90, 22);
+ _Save.Text = "保存图片(&B)";
+ _Save.ToolTipText = "将显示的图片保存为文件";
+ //
+ // _ZoomReset
+ //
+ _ZoomReset.Image = global::PDFPatcher.Properties.Resources.Zoom;
+ _ZoomReset.ImageTransparentColor = System.Drawing.Color.Magenta;
+ _ZoomReset.Name = "_ZoomReset";
+ _ZoomReset.Size = new System.Drawing.Size (75, 22);
+ _ZoomReset.Text = "原图比例";
+ //
+ // _FitWindow
+ //
+ this._FitWindow.Image = global::PDFPatcher.Properties.Resources.Image;
+ this._FitWindow.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._FitWindow.Name = "_FitWindow";
+ this._FitWindow.Size = new System.Drawing.Size (75, 22);
+ this._FitWindow.Text = "适合窗口";
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size (6, 25);
+ //
+ // _ImageBox
+ //
+ this._ImageBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._ImageBox.ForeColor = System.Drawing.SystemColors.ControlText;
+ this._ImageBox.Location = new System.Drawing.Point (12, 28);
+ this._ImageBox.MinimumSize = new System.Drawing.Size (454, 145);
+ this._ImageBox.Name = "_ImageBox";
+ this._ImageBox.Size = new System.Drawing.Size (515, 380);
+ this._ImageBox.TabIndex = 0;
+ this._ImageBox.TabStop = false;
+ //
+ // ImageViewerForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size (539, 420);
+ this.Controls.Add (this._MainToolbar);
+ this.Controls.Add (this._ImageBox);
+ this.Name = "ImageViewerForm";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.Text = "查看图片";
+ this._MainToolbar.ResumeLayout (false);
+ this._MainToolbar.PerformLayout ();
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private Cyotek.Windows.Forms.ImageBox _ImageBox;
+ private System.Windows.Forms.ToolStrip _MainToolbar;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripButton _FitWindow;
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.cs b/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..b0db2398f978aae382687ca12a02cddb4ce334ff
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.cs
@@ -0,0 +1,71 @@
+using System.Windows.Forms;
+using FreeImageAPI;
+using PDFPatcher.Common;
+using PDFPatcher.Processor;
+using PDFPatcher.Processor.Imaging;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class ImageViewerForm : Form
+ {
+ public ImageViewerForm() {
+ InitializeComponent();
+ }
+ internal ImageViewerForm(ImageInfo image, byte[] bytes) : this() {
+ this.SetIcon(Properties.Resources.ViewContent);
+ if (image.ExtName == Constants.FileExtensions.Png || image.ExtName == Constants.FileExtensions.Tif) {
+ using (FreeImageBitmap bmp = ImageExtractor.CreateFreeImageBitmap(image, ref bytes, false, true)) {
+ _ImageBox.Image = bmp.ToBitmap();
+ }
+ }
+ else {
+ try {
+ using (var s = new System.IO.MemoryStream(bytes)) {
+ using (FreeImageBitmap bmp = new FreeImageBitmap(s)) {
+ _ImageBox.Image = bmp.ToBitmap();
+ }
+ }
+ }
+ catch (System.Exception ex) {
+ this.ErrorBox("无法加载图片", ex);
+ }
+ }
+ }
+
+ protected override void OnClosed(System.EventArgs e) {
+ _ImageBox.Image.TryDispose();
+ base.OnClosed(e);
+ }
+
+ void _MainToolbar_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ var n = e.ClickedItem.Name;
+ switch (n) {
+ case "_Save":
+ using (var f = new SaveFileDialog {
+ Title = "保存图片文件",
+ DefaultExt = Constants.FileExtensions.Png,
+ FileName = "导出图片.png",
+ Filter = Constants.FileExtensions.ImageFilter
+ }) {
+ if (f.ShowDialog() == DialogResult.OK) {
+ try {
+ using (var fi = new FreeImageAPI.FreeImageBitmap(_ImageBox.Image)) {
+ fi.Save(f.FileName);
+ }
+ }
+ catch (System.Exception ex) {
+ FormHelper.ErrorBox(ex.Message);
+ }
+ }
+ }
+ break;
+ case "_ZoomReset":
+ _ImageBox.ActualSize(); break;
+ case "_FitWindow":
+ _ImageBox.ZoomToFit(); break;
+ default:
+ break;
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.resx b/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..574da632cd89c649b5323d399bbb877aa4006cf0
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/ImageViewerForm.resx
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
+ False
+
+
+ False
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.Designer.cs b/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..4b9594fa7c6370f4b2cb894be45bdf92ec1729ba
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.Designer.cs
@@ -0,0 +1,87 @@
+namespace PDFPatcher.Functions
+{
+ partial class TextViewerForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this._TextBox = new System.Windows.Forms.RichTextBox ();
+ this._OkButton = new System.Windows.Forms.Button ();
+ this._CancelButton = new System.Windows.Forms.Button ();
+ this.SuspendLayout ();
+ //
+ // _TextBox
+ //
+ this._TextBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._TextBox.Location = new System.Drawing.Point (12, 12);
+ this._TextBox.Name = "_TextBox";
+ this._TextBox.Size = new System.Drawing.Size (472, 219);
+ this._TextBox.TabIndex = 0;
+ this._TextBox.Text = "";
+ //
+ // _OkButton
+ //
+ this._OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._OkButton.Location = new System.Drawing.Point (328, 240);
+ this._OkButton.Name = "_OkButton";
+ this._OkButton.Size = new System.Drawing.Size (75, 23);
+ this._OkButton.TabIndex = 1;
+ this._OkButton.Text = "确定(&Q)";
+ this._OkButton.UseVisualStyleBackColor = true;
+ //
+ // _CancelButton
+ //
+ this._CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this._CancelButton.Location = new System.Drawing.Point (409, 240);
+ this._CancelButton.Name = "_CancelButton";
+ this._CancelButton.Size = new System.Drawing.Size (75, 23);
+ this._CancelButton.TabIndex = 2;
+ this._CancelButton.Text = "取消(&X)";
+ this._CancelButton.UseVisualStyleBackColor = true;
+ //
+ // TextViewerForm
+ //
+ this.AcceptButton = this._OkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this._CancelButton;
+ this.ClientSize = new System.Drawing.Size (496, 275);
+ this.Controls.Add (this._CancelButton);
+ this.Controls.Add (this._OkButton);
+ this.Controls.Add (this._TextBox);
+ this.Name = "TextViewerForm";
+ this.Text = "文本内容";
+ this.ResumeLayout (false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.RichTextBox _TextBox;
+ private System.Windows.Forms.Button _OkButton;
+ private System.Windows.Forms.Button _CancelButton;
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.cs b/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5e5054c61dbc1ba8c80addeab4e886f76d5dc2fa
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Windows.Forms;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class TextViewerForm : Form
+ {
+ ///获取或指定文本内容是否只读。
+ public bool IsTextReadOnly {
+ get => _TextBox.ReadOnly;
+ set {
+ _TextBox.ReadOnly = value;
+ _OkButton.Visible = !value;
+ }
+ }
+
+ ///获取或指定文本内容。
+ public string TextContent {
+ get => _TextBox.Text;
+ set => _TextBox.Text = value;
+ }
+
+ public TextViewerForm() {
+ InitializeComponent();
+ }
+
+ public TextViewerForm(string textContent, bool isTextReadonly) : this() {
+ TextContent = textContent;
+ IsTextReadOnly = isTextReadonly;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.resx b/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..d58980a38d71402abe7cf7bbbdeb69d761a29c47
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspector/TextViewerForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentInspectorControl.Designer.cs b/pdfpatcher/App/Functions/DocumentInspectorControl.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..30008bbb9f196f48d12914bf79a269147b83fb34
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspectorControl.Designer.cs
@@ -0,0 +1,468 @@
+namespace PDFPatcher.Functions
+{
+ partial class DocumentInspectorControl
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.ToolStripMenuItem _ExportBinary;
+ System.Windows.Forms.ToolStripMenuItem _ExportHexText;
+ System.Windows.Forms.ToolStripMenuItem _ExportXml;
+ System.Windows.Forms.ToolStripMenuItem _ExportUncompressedBinary;
+ System.Windows.Forms.ToolStripMenuItem _ExportUncompressedHexText;
+ System.Windows.Forms.ToolStripMenuItem _ExportToUnicode;
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DocumentInspectorControl));
+ this._Container = new System.Windows.Forms.SplitContainer();
+ this._ObjectDetailBox = new BrightIdeasSoftware.TreeListView();
+ this._NameColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ValueColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._DescriptionColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ObjectTypeIcons = new System.Windows.Forms.ImageList(this.components);
+ this._DescriptionBox = new RichTextBoxLinks.RichTextBoxEx();
+ this._RecentFileMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this._OpenButton = new System.Windows.Forms.ToolStripSplitButton();
+ this._LoadDocumentWorker = new System.ComponentModel.BackgroundWorker();
+ this._MainToolbar = new System.Windows.Forms.ToolStrip();
+ this._SaveButton = new System.Windows.Forms.ToolStripButton();
+ this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ this._ExportButton = new System.Windows.Forms.ToolStripDropDownButton();
+ this._ViewButton = new System.Windows.Forms.ToolStripButton();
+ this._AddObjectMenu = new System.Windows.Forms.ToolStripDropDownButton();
+ this._AddArrayNode = new System.Windows.Forms.ToolStripMenuItem();
+ this._AddDictNode = new System.Windows.Forms.ToolStripMenuItem();
+ this._AddBooleanNode = new System.Windows.Forms.ToolStripMenuItem();
+ this._AddStringNode = new System.Windows.Forms.ToolStripMenuItem();
+ this._AddNumberNode = new System.Windows.Forms.ToolStripMenuItem();
+ this._AddNameNode = new System.Windows.Forms.ToolStripMenuItem();
+ this._DeleteButton = new System.Windows.Forms.ToolStripButton();
+ this._ExpandButton = new System.Windows.Forms.ToolStripButton();
+ this._CollapseButton = new System.Windows.Forms.ToolStripButton();
+ _ExportBinary = new System.Windows.Forms.ToolStripMenuItem();
+ _ExportHexText = new System.Windows.Forms.ToolStripMenuItem();
+ _ExportXml = new System.Windows.Forms.ToolStripMenuItem();
+ _ExportUncompressedBinary = new System.Windows.Forms.ToolStripMenuItem();
+ _ExportUncompressedHexText = new System.Windows.Forms.ToolStripMenuItem();
+ _ExportToUnicode = new System.Windows.Forms.ToolStripMenuItem();
+ ((System.ComponentModel.ISupportInitialize)(this._Container)).BeginInit();
+ this._Container.Panel1.SuspendLayout();
+ this._Container.Panel2.SuspendLayout();
+ this._Container.SuspendLayout();
+ ((System.ComponentModel.ISupportInitialize)(this._ObjectDetailBox)).BeginInit();
+ this._MainToolbar.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _ExportBinary
+ //
+ _ExportBinary.Name = "_ExportBinary";
+ _ExportBinary.Size = new System.Drawing.Size(244, 22);
+ _ExportBinary.Text = "二进制文件(&E)...";
+ //
+ // _ExportHexText
+ //
+ _ExportHexText.Name = "_ExportHexText";
+ _ExportHexText.Size = new System.Drawing.Size(244, 22);
+ _ExportHexText.Text = "二进制文本文件(&W)...";
+ //
+ // _ExportXml
+ //
+ _ExportXml.Name = "_ExportXml";
+ _ExportXml.Size = new System.Drawing.Size(244, 22);
+ _ExportXml.Text = "&XML信息文件...";
+ //
+ // _ExportUncompressedBinary
+ //
+ _ExportUncompressedBinary.Name = "_ExportUncompressedBinary";
+ _ExportUncompressedBinary.Size = new System.Drawing.Size(244, 22);
+ _ExportUncompressedBinary.Text = "原始流对象二进制文件(&Y)...";
+ //
+ // _ExportUncompressedHexText
+ //
+ _ExportUncompressedHexText.Name = "_ExportUncompressedHexText";
+ _ExportUncompressedHexText.Size = new System.Drawing.Size(244, 22);
+ _ExportUncompressedHexText.Text = "原始流对象二进制文本文件(&Y)...";
+ //
+ // _ExportToUnicode
+ //
+ _ExportToUnicode.Name = "_ExportToUnicode";
+ _ExportToUnicode.Size = new System.Drawing.Size(244, 22);
+ _ExportToUnicode.Text = "&ToUnicode 映射表";
+ //
+ // _Container
+ //
+ this._Container.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._Container.FixedPanel = System.Windows.Forms.FixedPanel.Panel2;
+ this._Container.Location = new System.Drawing.Point(3, 28);
+ this._Container.Name = "_Container";
+ this._Container.Orientation = System.Windows.Forms.Orientation.Horizontal;
+ //
+ // _Container.Panel1
+ //
+ this._Container.Panel1.Controls.Add(this._ObjectDetailBox);
+ //
+ // _Container.Panel2
+ //
+ this._Container.Panel2.Controls.Add(this._DescriptionBox);
+ this._Container.Size = new System.Drawing.Size(487, 310);
+ this._Container.SplitterDistance = 229;
+ this._Container.TabIndex = 1;
+ //
+ // _ObjectDetailBox
+ //
+ this._ObjectDetailBox.AllColumns.Add(this._NameColumn);
+ this._ObjectDetailBox.AllColumns.Add(this._ValueColumn);
+ this._ObjectDetailBox.AllColumns.Add(this._DescriptionColumn);
+ this._ObjectDetailBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._ObjectDetailBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this._ObjectDetailBox.CellEditUseWholeCell = false;
+ this._ObjectDetailBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._NameColumn,
+ this._ValueColumn,
+ this._DescriptionColumn});
+ this._ObjectDetailBox.GridLines = true;
+ this._ObjectDetailBox.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this._ObjectDetailBox.HideSelection = false;
+ this._ObjectDetailBox.Location = new System.Drawing.Point(3, 3);
+ this._ObjectDetailBox.Name = "_ObjectDetailBox";
+ this._ObjectDetailBox.RevealAfterExpand = false;
+ this._ObjectDetailBox.ShowGroups = false;
+ this._ObjectDetailBox.Size = new System.Drawing.Size(481, 223);
+ this._ObjectDetailBox.SmallImageList = this._ObjectTypeIcons;
+ this._ObjectDetailBox.TabIndex = 0;
+ this._ObjectDetailBox.UseCompatibleStateImageBehavior = false;
+ this._ObjectDetailBox.View = System.Windows.Forms.View.Details;
+ this._ObjectDetailBox.VirtualMode = true;
+ this._ObjectDetailBox.ItemActivate += new System.EventHandler(this.ControlEvent);
+ //
+ // _NameColumn
+ //
+ this._NameColumn.IsEditable = false;
+ this._NameColumn.Text = "名称";
+ this._NameColumn.Width = 184;
+ //
+ // _ValueColumn
+ //
+ this._ValueColumn.Text = "值";
+ this._ValueColumn.Width = 187;
+ //
+ // _DescriptionColumn
+ //
+ this._DescriptionColumn.IsEditable = false;
+ this._DescriptionColumn.Text = "说明";
+ this._DescriptionColumn.Width = 93;
+ //
+ // _ObjectTypeIcons
+ //
+ this._ObjectTypeIcons.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("_ObjectTypeIcons.ImageStream")));
+ this._ObjectTypeIcons.TransparentColor = System.Drawing.Color.Transparent;
+ this._ObjectTypeIcons.Images.SetKeyName(0, "Current");
+ this._ObjectTypeIcons.Images.SetKeyName(1, "Page");
+ this._ObjectTypeIcons.Images.SetKeyName(2, "Dictionary");
+ this._ObjectTypeIcons.Images.SetKeyName(3, "Array");
+ this._ObjectTypeIcons.Images.SetKeyName(4, "Name");
+ this._ObjectTypeIcons.Images.SetKeyName(5, "String");
+ this._ObjectTypeIcons.Images.SetKeyName(6, "Number");
+ this._ObjectTypeIcons.Images.SetKeyName(7, "Stream");
+ this._ObjectTypeIcons.Images.SetKeyName(8, "Bool");
+ this._ObjectTypeIcons.Images.SetKeyName(9, "Reference");
+ this._ObjectTypeIcons.Images.SetKeyName(10, "Document");
+ this._ObjectTypeIcons.Images.SetKeyName(11, "Pages");
+ this._ObjectTypeIcons.Images.SetKeyName(12, "PageCommands");
+ this._ObjectTypeIcons.Images.SetKeyName(13, "Outlines");
+ this._ObjectTypeIcons.Images.SetKeyName(14, "Outline");
+ this._ObjectTypeIcons.Images.SetKeyName(15, "Trailer");
+ this._ObjectTypeIcons.Images.SetKeyName(16, "GoToPage");
+ this._ObjectTypeIcons.Images.SetKeyName(17, "Image");
+ this._ObjectTypeIcons.Images.SetKeyName(18, "Info");
+ this._ObjectTypeIcons.Images.SetKeyName(19, "Font");
+ this._ObjectTypeIcons.Images.SetKeyName(20, "Resources");
+ this._ObjectTypeIcons.Images.SetKeyName(21, "Null");
+ this._ObjectTypeIcons.Images.SetKeyName(22, "Hidden");
+ this._ObjectTypeIcons.Images.SetKeyName(23, "op_q");
+ this._ObjectTypeIcons.Images.SetKeyName(24, "op_cm");
+ this._ObjectTypeIcons.Images.SetKeyName(25, "op_tm");
+ this._ObjectTypeIcons.Images.SetKeyName(26, "op_cs");
+ this._ObjectTypeIcons.Images.SetKeyName(27, "op_sc");
+ this._ObjectTypeIcons.Images.SetKeyName(28, "op_g");
+ this._ObjectTypeIcons.Images.SetKeyName(29, "op_s");
+ this._ObjectTypeIcons.Images.SetKeyName(30, "op_TJ");
+ this._ObjectTypeIcons.Images.SetKeyName(31, "op_tj_");
+ this._ObjectTypeIcons.Images.SetKeyName(32, "op_f");
+ this._ObjectTypeIcons.Images.SetKeyName(33, "op_Ts");
+ this._ObjectTypeIcons.Images.SetKeyName(34, "op_BT");
+ this._ObjectTypeIcons.Images.SetKeyName(35, "op_Td");
+ this._ObjectTypeIcons.Images.SetKeyName(36, "op_Tr");
+ this._ObjectTypeIcons.Images.SetKeyName(37, "op_BDC");
+ this._ObjectTypeIcons.Images.SetKeyName(38, "op_re");
+ this._ObjectTypeIcons.Images.SetKeyName(39, "op_W*");
+ this._ObjectTypeIcons.Images.SetKeyName(40, "op_c");
+ this._ObjectTypeIcons.Images.SetKeyName(41, "op_l");
+ this._ObjectTypeIcons.Images.SetKeyName(42, "op_tc");
+ this._ObjectTypeIcons.Images.SetKeyName(43, "op_Tz");
+ this._ObjectTypeIcons.Images.SetKeyName(44, "op_Tl");
+ this._ObjectTypeIcons.Images.SetKeyName(45, "op_gs");
+ this._ObjectTypeIcons.Images.SetKeyName(46, "op_w");
+ this._ObjectTypeIcons.Images.SetKeyName(47, "op_M_");
+ this._ObjectTypeIcons.Images.SetKeyName(48, "op_d");
+ this._ObjectTypeIcons.Images.SetKeyName(49, "op_b");
+ this._ObjectTypeIcons.Images.SetKeyName(50, "op_m");
+ this._ObjectTypeIcons.Images.SetKeyName(51, "op_h");
+ //
+ // _DescriptionBox
+ //
+ this._DescriptionBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._DescriptionBox.Location = new System.Drawing.Point(3, 3);
+ this._DescriptionBox.Name = "_DescriptionBox";
+ this._DescriptionBox.ReadOnly = true;
+ this._DescriptionBox.ScrollBars = System.Windows.Forms.RichTextBoxScrollBars.Vertical;
+ this._DescriptionBox.Size = new System.Drawing.Size(481, 71);
+ this._DescriptionBox.TabIndex = 1;
+ this._DescriptionBox.Text = "";
+ //
+ // _RecentFileMenu
+ //
+ this._RecentFileMenu.Name = "_RecentFileMenu";
+ this._RecentFileMenu.OwnerItem = this._OpenButton;
+ this._RecentFileMenu.Size = new System.Drawing.Size(61, 4);
+ //
+ // _OpenButton
+ //
+ this._OpenButton.DropDown = this._RecentFileMenu;
+ this._OpenButton.Image = global::PDFPatcher.Properties.Resources.OpenFile;
+ this._OpenButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._OpenButton.Name = "_OpenButton";
+ this._OpenButton.Size = new System.Drawing.Size(81, 22);
+ this._OpenButton.Text = "打开(&D)";
+ this._OpenButton.ToolTipText = "打开 PDF 文档";
+ this._OpenButton.ButtonClick += new System.EventHandler(this.ControlEvent);
+ //
+ // _LoadDocumentWorker
+ //
+ this._LoadDocumentWorker.DoWork += new System.ComponentModel.DoWorkEventHandler(this._LoadDocumentWorker_DoWork);
+ this._LoadDocumentWorker.RunWorkerCompleted += new System.ComponentModel.RunWorkerCompletedEventHandler(this._LoadDocumentWorker_RunWorkerCompleted);
+ //
+ // _MainToolbar
+ //
+ this._MainToolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._OpenButton,
+ this._SaveButton,
+ this.toolStripSeparator1,
+ this._ExportButton,
+ this._ViewButton,
+ this._AddObjectMenu,
+ this._DeleteButton,
+ this._ExpandButton,
+ this._CollapseButton});
+ this._MainToolbar.Location = new System.Drawing.Point(0, 0);
+ this._MainToolbar.Name = "_MainToolbar";
+ this._MainToolbar.Size = new System.Drawing.Size(495, 25);
+ this._MainToolbar.TabIndex = 0;
+ this._MainToolbar.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.ToolbarItemClicked);
+ //
+ // _SaveButton
+ //
+ this._SaveButton.Enabled = false;
+ this._SaveButton.Image = global::PDFPatcher.Properties.Resources.Save;
+ this._SaveButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._SaveButton.Name = "_SaveButton";
+ this._SaveButton.Size = new System.Drawing.Size(68, 22);
+ this._SaveButton.Text = "保存(&B)";
+ this._SaveButton.ToolTipText = "保存修改后的 PDF 文档";
+ //
+ // toolStripSeparator1
+ //
+ this.toolStripSeparator1.Name = "toolStripSeparator1";
+ this.toolStripSeparator1.Size = new System.Drawing.Size(6, 25);
+ //
+ // _ExportButton
+ //
+ this._ExportButton.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ _ExportBinary,
+ _ExportHexText,
+ _ExportXml,
+ _ExportUncompressedBinary,
+ _ExportUncompressedHexText,
+ _ExportToUnicode});
+ this._ExportButton.Enabled = false;
+ this._ExportButton.Image = global::PDFPatcher.Properties.Resources.ExportFile;
+ this._ExportButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._ExportButton.Name = "_ExportButton";
+ this._ExportButton.Size = new System.Drawing.Size(61, 22);
+ this._ExportButton.Text = "导出";
+ this._ExportButton.ToolTipText = "导出流对象的内容";
+ this._ExportButton.DropDownOpening += new System.EventHandler(this._ExportButton_DropDownOpening);
+ this._ExportButton.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this.ToolbarItemClicked);
+ //
+ // _ViewButton
+ //
+ this._ViewButton.Enabled = false;
+ this._ViewButton.Image = global::PDFPatcher.Properties.Resources.ViewContent;
+ this._ViewButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._ViewButton.Name = "_ViewButton";
+ this._ViewButton.Size = new System.Drawing.Size(52, 22);
+ this._ViewButton.Text = "查看";
+ this._ViewButton.ToolTipText = "查看流对象";
+ //
+ // _AddObjectMenu
+ //
+ this._AddObjectMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._AddArrayNode,
+ this._AddDictNode,
+ this._AddBooleanNode,
+ this._AddStringNode,
+ this._AddNumberNode,
+ this._AddNameNode});
+ this._AddObjectMenu.Enabled = false;
+ this._AddObjectMenu.Image = global::PDFPatcher.Properties.Resources.AddChildNode;
+ this._AddObjectMenu.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._AddObjectMenu.Name = "_AddObjectMenu";
+ this._AddObjectMenu.Size = new System.Drawing.Size(97, 22);
+ this._AddObjectMenu.Text = "插入子节点";
+ this._AddObjectMenu.ToolTipText = "添加子节点对象";
+ this._AddObjectMenu.DropDownItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this._AddObjectMenu_DropDownItemClicked);
+ //
+ // _AddArrayNode
+ //
+ this._AddArrayNode.Name = "_AddArrayNode";
+ this._AddArrayNode.Size = new System.Drawing.Size(136, 22);
+ this._AddArrayNode.Text = "列表节点";
+ //
+ // _AddDictNode
+ //
+ this._AddDictNode.Name = "_AddDictNode";
+ this._AddDictNode.Size = new System.Drawing.Size(136, 22);
+ this._AddDictNode.Text = "字典节点";
+ //
+ // _AddBooleanNode
+ //
+ this._AddBooleanNode.Name = "_AddBooleanNode";
+ this._AddBooleanNode.Size = new System.Drawing.Size(136, 22);
+ this._AddBooleanNode.Text = "真假值节点";
+ //
+ // _AddStringNode
+ //
+ this._AddStringNode.Name = "_AddStringNode";
+ this._AddStringNode.Size = new System.Drawing.Size(136, 22);
+ this._AddStringNode.Text = "字符串节点";
+ //
+ // _AddNumberNode
+ //
+ this._AddNumberNode.Name = "_AddNumberNode";
+ this._AddNumberNode.Size = new System.Drawing.Size(136, 22);
+ this._AddNumberNode.Text = "数值节点";
+ //
+ // _AddNameNode
+ //
+ this._AddNameNode.Name = "_AddNameNode";
+ this._AddNameNode.Size = new System.Drawing.Size(136, 22);
+ this._AddNameNode.Text = "名称节点";
+ //
+ // _DeleteButton
+ //
+ this._DeleteButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this._DeleteButton.Enabled = false;
+ this._DeleteButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._DeleteButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._DeleteButton.Name = "_DeleteButton";
+ this._DeleteButton.Size = new System.Drawing.Size(23, 22);
+ this._DeleteButton.Text = "删除";
+ this._DeleteButton.ToolTipText = "删除选中的对象";
+ //
+ // _ExpandButton
+ //
+ this._ExpandButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this._ExpandButton.Enabled = false;
+ this._ExpandButton.Image = global::PDFPatcher.Properties.Resources.Expand;
+ this._ExpandButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._ExpandButton.Name = "_ExpandButton";
+ this._ExpandButton.Size = new System.Drawing.Size(23, 22);
+ this._ExpandButton.Text = "展开";
+ this._ExpandButton.ToolTipText = "展开选中的项目";
+ //
+ // _CollapseButton
+ //
+ this._CollapseButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this._CollapseButton.Enabled = false;
+ this._CollapseButton.Image = global::PDFPatcher.Properties.Resources.Collapse;
+ this._CollapseButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._CollapseButton.Name = "_CollapseButton";
+ this._CollapseButton.Size = new System.Drawing.Size(23, 22);
+ this._CollapseButton.Text = "收拢";
+ this._CollapseButton.ToolTipText = "收拢选中的项目";
+ //
+ // DocumentInspectorControl
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this._MainToolbar);
+ this.Controls.Add(this._Container);
+ this.Font = new System.Drawing.Font("SimSun", 9F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(134)));
+ this.Name = "DocumentInspectorControl";
+ this.Size = new System.Drawing.Size(495, 341);
+ this._Container.Panel1.ResumeLayout(false);
+ this._Container.Panel2.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this._Container)).EndInit();
+ this._Container.ResumeLayout(false);
+ ((System.ComponentModel.ISupportInitialize)(this._ObjectDetailBox)).EndInit();
+ this._MainToolbar.ResumeLayout(false);
+ this._MainToolbar.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.SplitContainer _Container;
+ private BrightIdeasSoftware.TreeListView _ObjectDetailBox;
+ private BrightIdeasSoftware.OLVColumn _NameColumn;
+ private BrightIdeasSoftware.OLVColumn _ValueColumn;
+ private RichTextBoxLinks.RichTextBoxEx _DescriptionBox;
+ private System.Windows.Forms.ContextMenuStrip _RecentFileMenu;
+ private System.Windows.Forms.ImageList _ObjectTypeIcons;
+ private BrightIdeasSoftware.OLVColumn _DescriptionColumn;
+ private System.ComponentModel.BackgroundWorker _LoadDocumentWorker;
+ private System.Windows.Forms.ToolStripSplitButton _OpenButton;
+ private System.Windows.Forms.ToolStrip _MainToolbar;
+ private System.Windows.Forms.ToolStripButton _SaveButton;
+ private System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ private System.Windows.Forms.ToolStripDropDownButton _ExportButton;
+ private System.Windows.Forms.ToolStripButton _ViewButton;
+ private System.Windows.Forms.ToolStripButton _DeleteButton;
+ private System.Windows.Forms.ToolStripButton _ExpandButton;
+ private System.Windows.Forms.ToolStripButton _CollapseButton;
+ private System.Windows.Forms.ToolStripDropDownButton _AddObjectMenu;
+ private System.Windows.Forms.ToolStripMenuItem _AddNameNode;
+ private System.Windows.Forms.ToolStripMenuItem _AddNumberNode;
+ private System.Windows.Forms.ToolStripMenuItem _AddStringNode;
+ private System.Windows.Forms.ToolStripMenuItem _AddBooleanNode;
+ private System.Windows.Forms.ToolStripMenuItem _AddDictNode;
+ private System.Windows.Forms.ToolStripMenuItem _AddArrayNode;
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentInspectorControl.cs b/pdfpatcher/App/Functions/DocumentInspectorControl.cs
new file mode 100644
index 0000000000000000000000000000000000000000..66b52c3c751a78678dd93480a4cf2f9c1864f0c4
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspectorControl.cs
@@ -0,0 +1,860 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Drawing;
+using System.IO;
+using System.Linq;
+using System.Security.Permissions;
+using System.Windows.Forms;
+using System.Xml;
+using BrightIdeasSoftware;
+using iTextSharp.text.pdf;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+using PDFPatcher.Processor;
+
+namespace PDFPatcher.Functions
+{
+ [ToolboxItem(false)]
+ public sealed partial class DocumentInspectorControl : FunctionControl, IDocumentEditor
+ {
+ static readonly PdfObjectType[] __XmlExportableTypes = new PdfObjectType[] { PdfObjectType.Page, PdfObjectType.Pages, PdfObjectType.Trailer };
+ static Dictionary __OpNameIcons;
+ static Dictionary __PdfObjectIcons;
+
+ PdfPathDocument _pdf;
+ ImageExtractor _imgExp;
+ string _fileName;
+ ToolStripItem[] _addPdfObjectMenuItems;
+ int[] _pdfTypeForAddObjectMenuItems;
+
+ static readonly ImageExtracterOptions _imgExpOption = new ImageExtracterOptions() {
+ OutputPath = Path.GetTempPath(),
+ MergeImages = false
+ };
+
+ public override string FunctionName => "结构探查器";
+
+ public override Bitmap IconImage => Properties.Resources.DocumentInspector;
+
+ public event EventHandler DocumentChanged;
+ public string DocumentPath {
+ get => _fileName;
+ set {
+ if (_fileName != value) {
+ _fileName = value;
+ DocumentChanged?.Invoke(this, new DocumentChangedEventArgs(value));
+ }
+ }
+ }
+
+ public DocumentInspectorControl() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ }
+
+ void OnLoad() {
+ _MainToolbar.ScaleIcons(16);
+ _ObjectDetailBox.ScaleColumnWidths();
+
+ _ObjectDetailBox.EmptyListMsg = "请使用“打开”按钮加载需要检查结构的 PDF 文件,或从资源管理器拖放文件到本列表框";
+
+ if (__OpNameIcons == null || __OpNameIcons.Count == 0) {
+ __OpNameIcons = InitOpNameIcons();
+ }
+ if (__PdfObjectIcons == null || __PdfObjectIcons.Count == 0) {
+ __PdfObjectIcons = InitPdfObjectIcons();
+ }
+ #region TreeListView init
+ _ObjectDetailBox.SetTreeViewLine();
+ _ObjectDetailBox.FixEditControlWidth();
+ new TypedColumn(_NameColumn) {
+ AspectGetter = (DocumentObject d) => {
+ return d.FriendlyName ?? d.Name;
+ },
+ ImageGetter = (DocumentObject d) => {
+ if (d.ImageKey != null) {
+ return d.ImageKey;
+ }
+
+ if (d.Type == PdfObjectType.Normal) {
+ return GetImageKey(d);
+ }
+
+ switch (d.Type) {
+ case PdfObjectType.Trailer:
+ return __OpNameIcons["Document"];
+ case PdfObjectType.Root:
+ break;
+ case PdfObjectType.Pages:
+ return __OpNameIcons["Pages"];
+ case PdfObjectType.Page:
+ return __OpNameIcons["Page"];
+ case PdfObjectType.Image:
+ return __OpNameIcons["Image"];
+ case PdfObjectType.Outline:
+ return __OpNameIcons["Outline"];
+ case PdfObjectType.PageCommands:
+ return __OpNameIcons["PageCommands"];
+ case PdfObjectType.PageCommand:
+ if (d.ImageKey == null) {
+ var n = d.ExtensiveObject as string;
+ if ((n != null && __OpNameIcons.TryGetValue(n, out int ic))
+ || (d.Name.StartsWith(Constants.ContentPrefix + ":") && __OpNameIcons.TryGetValue(d.Name, out ic))
+ ) {
+ d.ImageKey = ic;
+ }
+ else {
+ d.ImageKey = __OpNameIcons["Null"];
+ }
+ }
+ return d.ImageKey;
+ case PdfObjectType.Hidden:
+ return __OpNameIcons["Hidden"];
+ }
+ return GetImageKey(d);
+ }
+ };
+ new TypedColumn(_ValueColumn) {
+ AspectGetter = (DocumentObject d) => {
+ return d.FriendlyValue ?? d.LiteralValue;
+ },
+ AspectPutter = (DocumentObject d, object value) => {
+ if (d.UpdateDocumentObject(value)) {
+ var r = d.FindReferenceAncestor();
+ if (r != null) {
+ RefreshReferences(r);
+ }
+ }
+ else if (d.Parent != null && d.Parent.Type == PdfObjectType.Outline && d.Name == "Title") {
+ d.Parent.Description = (string)value;
+ _ObjectDetailBox.RefreshObject(d.Parent);
+ }
+ }
+ };
+ _DescriptionColumn.AspectGetter = (object o) => {
+ return ((DocumentObject)o).Description;
+ };
+ _ObjectDetailBox.PrimarySortColumn = null;
+ _ObjectDetailBox.CopySelectionOnControlC = true;
+ _ObjectDetailBox.CellEditStarting += (s, args) => {
+ var d = args.RowObject as DocumentObject;
+ var po = d.Value as PdfObject;
+ if (po == null) {
+ args.Cancel = true;
+ return;
+ }
+ if (po.Type == PdfObject.BOOLEAN) {
+ args.Control = new CheckBox() { Checked = (po as PdfBoolean).BooleanValue, Bounds = args.CellBounds };
+ }
+ else if (po.Type == PdfObject.NUMBER) {
+ args.Control = new TextBox() { Text = (po as PdfNumber).DoubleValue.ToText(), Bounds = args.CellBounds };
+ }
+ else if (po.Type == PdfObject.INDIRECT || PdfHelper.CompoundTypes.Contains(po.Type)) {
+ args.Cancel = true;
+ }
+ };
+ _ObjectDetailBox.CanExpandGetter = (object o) => {
+ var d = o as DocumentObject;
+ if (d == null) {
+ return false;
+ }
+ if (d.Type == PdfObjectType.GoToPage) {
+ d.ImageKey = __OpNameIcons["GoToPage"];
+ }
+ return d.HasChildren;
+ };
+ _ObjectDetailBox.ChildrenGetter = delegate (object o) {
+ var d = o as DocumentObject;
+ if (d == null) {
+ return null;
+ }
+ return d.Children;
+ };
+ _ObjectDetailBox.RowFormatter = (OLVListItem olvItem) => {
+ var o = olvItem.RowObject as DocumentObject;
+ if (o == null) {
+ return;
+ }
+ if (o.Type == PdfObjectType.Normal) {
+ var po = o.Value;
+ if (po == null) {
+ return;
+ }
+ if (po.Type == PdfObject.INDIRECT) {
+ olvItem.UseItemStyleForSubItems = false;
+ olvItem.SubItems[_ValueColumn.Index].ForeColor = SystemColors.HotTrack;
+ }
+ else if (PdfHelper.CompoundTypes.Contains(po.Type)) {
+ olvItem.UseItemStyleForSubItems = false;
+ olvItem.SubItems[_ValueColumn.Index].ForeColor = SystemColors.GrayText;
+ }
+ }
+ else if (o.Type == PdfObjectType.Page) {
+ olvItem.ForeColor = Color.DarkRed;
+ }
+ else if (o.Type == PdfObjectType.Pages) {
+ olvItem.Font = new Font(olvItem.Font, FontStyle.Bold);
+ olvItem.ForeColor = Color.DarkRed;
+ olvItem.BackColor = Color.LightYellow;
+ }
+ else if (o.Type == PdfObjectType.Trailer) {
+ olvItem.Font = new Font(olvItem.Font, FontStyle.Bold);
+ olvItem.BackColor = Color.LightYellow;
+ }
+ else if (o.Type == PdfObjectType.Outline) {
+ olvItem.UseItemStyleForSubItems = false;
+ olvItem.SubItems[0].ForeColor = SystemColors.HotTrack;
+ olvItem.SubItems[_ValueColumn.Index].ForeColor = SystemColors.HotTrack;
+ }
+ else if (o.Type == PdfObjectType.PageCommand && (o.Name == "字符串" || o.Name == "换行字符串")) {
+ olvItem.UseItemStyleForSubItems = false;
+ var s = olvItem.SubItems[_DescriptionColumn.Index];
+ s.Font = new Font(olvItem.Font, FontStyle.Underline);
+ }
+ };
+ _ObjectDetailBox.SelectionChanged += _ObjectDetailBox_SelectionChanged;
+ _ObjectDetailBox.IsSimpleDropSink = true;
+ _ObjectDetailBox.CanDrop += _ObjectDetailBox_CanDrop;
+ _ObjectDetailBox.Dropped += _ObjectDetailBox_Dropped;
+ #endregion
+ _AddNameNode.Image = _ObjectTypeIcons.Images["Name"];
+ _AddStringNode.Image = _ObjectTypeIcons.Images["String"];
+ _AddDictNode.Image = _ObjectTypeIcons.Images["Dictionary"];
+ _AddArrayNode.Image = _ObjectTypeIcons.Images["Array"];
+ _AddNumberNode.Image = _ObjectTypeIcons.Images["Number"];
+ _AddBooleanNode.Image = _ObjectTypeIcons.Images["Bool"];
+
+ _addPdfObjectMenuItems = new ToolStripItem[] { _AddNameNode, _AddStringNode, _AddDictNode, _AddArrayNode, _AddNumberNode, _AddBooleanNode };
+ _pdfTypeForAddObjectMenuItems = new int[] { PdfObject.NAME, PdfObject.STRING, PdfObject.DICTIONARY, PdfObject.ARRAY, PdfObject.NUMBER, PdfObject.BOOLEAN };
+
+ _OpenButton.DropDownOpening += FileListHelper.OpenPdfButtonDropDownOpeningHandler;
+ _OpenButton.DropDownItemClicked += (s, args) => {
+ args.ClickedItem.Owner.Hide();
+ LoadDocument(args.ClickedItem.ToolTipText);
+ };
+ Disposed += (s, args) => {
+ _pdf?.Document.Dispose();
+ };
+ }
+
+ public override void SetupCommand(ToolStripItem item) {
+ var n = item.Name;
+ switch (n) {
+ case Commands.Action:
+ item.Text = _SaveButton.Text;
+ item.Image = _SaveButton.Image;
+ item.ToolTipText = _SaveButton.ToolTipText;
+ return;
+ case Commands.Delete:
+ EnableCommand(item, _DeleteButton.Enabled, true);
+ return;
+ default:
+ break;
+ }
+ if (Commands.CommonSelectionCommands.Contains(n)
+ || Commands.RecentFiles == n
+ ) {
+ EnableCommand(item, _ObjectDetailBox.GetItemCount() > 0, true);
+ }
+ else {
+ base.SetupCommand(item);
+ }
+ }
+
+ public override void ExecuteCommand(string commandName, params string[] parameters) {
+ switch (commandName) {
+ case Commands.Open:
+ var p = AppContext.MainForm.ShowPdfFileDialog();
+ if (p != null) {
+ LoadDocument(p);
+ }
+ break;
+ case Commands.OpenFile:
+ LoadDocument(parameters[0]);
+ break;
+ case Commands.Action:
+ SaveDocument();
+ break;
+ case Commands.SelectAllItems:
+ _ObjectDetailBox.SelectAll();
+ break;
+ case Commands.SelectNone:
+ _ObjectDetailBox.SelectedObjects = null;
+ break;
+ case Commands.InvertSelectItem:
+ _ObjectDetailBox.InvertSelect();
+ break;
+ default:
+ base.ExecuteCommand(commandName, parameters);
+ break;
+ }
+ }
+
+ [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
+ protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {
+ if (_ObjectDetailBox.IsCellEditing) {
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+ switch (keyData ^ Keys.Control) {
+ case Keys.O: ExecuteCommand(Commands.Open); return true;
+ case Keys.C: ExecuteCommand(Commands.Copy); return true;
+ case Keys.S: ExecuteCommand(Commands.Action); return true;
+ }
+ return base.ProcessCmdKey(ref msg, keyData);
+ }
+
+ void RefreshReferences(DocumentObject r) {
+ if (r.Value == null || r.Value.Type != PdfObject.INDIRECT) {
+ return;
+ }
+ var v = r.Value as PdfIndirectReference;
+ var l = _ObjectDetailBox.VirtualListSize;
+ for (int i = 0; i < l; i++) {
+ var m = _ObjectDetailBox.GetModelObject(i) as DocumentObject;
+ if (m == null) {
+ continue;
+ }
+ if (m.Type == PdfObjectType.PageCommands) {
+ i += (_ObjectDetailBox.VirtualListDataSource as TreeListView.Tree).GetVisibleDescendentCount(m);
+ }
+ if (m.ExtensiveObject != null && m.Value != null && m.Value.Type == PdfObject.INDIRECT) {
+ var mv = m.Value as PdfIndirectReference;
+ if (mv.Number == v.Number && mv.Generation == v.Generation && m != r) {
+ _ObjectDetailBox.RefreshObject(m);
+ }
+ }
+ }
+ }
+
+ public void CloseDocument() {
+ _pdf.Document?.SafeFile.Close();
+ }
+
+ public void Reopen() {
+ _pdf.Document?.SafeFile.ReOpen();
+ }
+
+ void _ObjectDetailBox_CanDrop(object sender, OlvDropEventArgs e) {
+ var o = e.DataObject as DataObject;
+ if (o == null) {
+ return;
+ }
+ var f = o.GetFileDropList();
+ foreach (var item in f) {
+ if (FileHelper.HasExtension(item, Constants.FileExtensions.Xml)
+ || FileHelper.HasExtension(item, Constants.FileExtensions.Pdf)) {
+ e.Handled = true;
+ e.DropTargetLocation = DropTargetLocation.Background;
+ e.Effect = DragDropEffects.Move;
+ e.InfoMessage = "打开文件" + item;
+ return;
+ }
+ }
+ e.Effect = DragDropEffects.None;
+ e.DropTargetLocation = DropTargetLocation.None;
+ }
+
+ void _ObjectDetailBox_Dropped(object sender, OlvDropEventArgs e) {
+ var o = e.DataObject as DataObject;
+ if (o == null) {
+ return;
+ }
+ var f = o.GetFileDropList();
+ if (f.Count == 0) {
+ return;
+ }
+ LoadDocument(f[0]);
+ }
+
+ void _ObjectDetailBox_SelectionChanged(object sender, EventArgs e) {
+ var si = _ObjectDetailBox.SelectedItem;
+ if (si == null) {
+ return;
+ }
+ _ExpandButton.Enabled = _CollapseButton.Enabled = true;
+ var d = _ObjectDetailBox.GetModelObject(si.Index) as DocumentObject;
+ _ViewButton.Enabled = false;
+ _DeleteButton.Enabled = false;
+ _ExportButton.Enabled = false;
+ _AddObjectMenu.Enabled = false;
+ if (d == null) {
+ return;
+ }
+ if (d.Value != null && (d.Value.Type == PdfObject.INDIRECT || d.Value.Type == PdfObject.STREAM)) {
+ var s = d.Value as PRStream ?? d.ExtensiveObject as PRStream;
+ if (s != null) {
+ _ViewButton.Enabled = d.Name.StartsWith("Font") == false;
+ _ExportButton.Enabled = _AddObjectMenu.Enabled = true;
+ if (PdfName.IMAGE.Equals(s.GetAsName(PdfName.SUBTYPE))) {
+ ShowDescription("图片", null, PdfHelper.GetTypeName(PdfObject.STREAM));
+ return;
+ }
+ }
+ }
+ if (d.Value != null && d.Value is PdfDictionary || d.ExtensiveObject is PdfDictionary) {
+ _AddObjectMenu.Enabled = true;
+ }
+ if (__XmlExportableTypes.Contains(d.Type)) {
+ _ExportButton.Enabled = true;
+ }
+ if (d.Parent == null) {
+ if (d.Type == PdfObjectType.Trailer) {
+ ShowDescription("文档根节点", _fileName, null);
+ }
+ else if (d.Type == PdfObjectType.Pages) {
+ ShowDescription("文档页面", "页数:" + _pdf.PageCount, null);
+ }
+ return;
+ }
+ var i = Model.PdfStructInfo.GetInfo(d.Parent.GetContextName(), d.Name);
+ string t = null;
+ var o = (d.ExtensiveObject as PdfObject ?? d.Value);
+ if (o != null) {
+ t = PdfHelper.GetTypeName(o.Type);
+ }
+ ShowDescription(String.IsNullOrEmpty(i.Name) || d.Name == i.Name ? d.Name : String.Concat(d.Name, ":", i.Name), i.Description, t);
+ _DeleteButton.Enabled = !i.IsRequired && d != null
+ && (d.Type == PdfObjectType.Normal || d.Type == PdfObjectType.Image || d.Type == PdfObjectType.Outline && d.Name == "Outlines");
+ }
+
+ Dictionary InitOpNameIcons() {
+ var p = new string[] { "Document", "Pages", "Page", "PageCommands", "Image", "Hidden", "GoToPage", "Outline", "Null" };
+ var n = new string[] {
+ "q", "Tm", "cm", "gs", "ri", "CS", "cs",
+ "RG", "rg", "scn", "SCN", "sc", "SC", "K", "k",
+ "g", "G", "s", "S",
+ "f", "F", "f*", "b", "B", "b*", "B*",
+ "Tf", "Tz", "Ts", "T*", "Td", "TD",
+ "TJ", "Tj", "'", "\"",
+ "Tk", "Tr", "Tc", "Tw", "TL",
+ "BI", "BT", "BDC", "BMC",
+ "Do",
+ "W*", "W", "c", "v", "y", "l", "re",
+ "m", "h", "n", "w", "J", "j", "M", "d", "i",
+ "pdf:number", "pdf:string", "pdf:name", "pdf:dictionary", "pdf:array", "pdf:boolean" };
+ var ico = new string[] {
+ "op_q", "op_tm", "op_cm", "op_gs", "op_gs", "op_gs", "op_gs",
+ "op_sc", "op_sc", "op_sc", "op_sc", "op_sc", "op_sc", "op_sc", "op_sc",
+ "op_g", "op_g", "op_s", "op_s",
+ "op_f", "op_f", "op_f", "op_b", "op_b", "op_b", "op_b",
+ "Font", "op_Tz", "op_Ts", "op_Td", "op_Td", "op_Td",
+ "op_TJ", "op_TJ", "op_TJ", "op_TJ",
+ "op_Tr", "op_Tr", "op_Tc", "op_Tc", "op_Tl",
+ "Image", "op_BT", "op_BDC", "op_BDC",
+ "Resources",
+ "op_W*", "op_W*", "op_c", "op_c", "op_c", "op_l", "op_re",
+ "op_m", "op_h", "op_h", "op_w", "op_l", "op_l", "op_M_", "op_d", "op_gs",
+ "Number", "String", "Name", "Dictionary", "Array", "Bool" };
+ var d = new Dictionary(n.Length + p.Length);
+ foreach (var i in p) {
+ d.Add(i, _ObjectTypeIcons.Images.IndexOfKey(i));
+ }
+ for (int i = 0; i < n.Length; i++) {
+ d.Add(n[i], _ObjectTypeIcons.Images.IndexOfKey(ico[i]));
+ }
+ return d;
+ }
+ Dictionary InitPdfObjectIcons() {
+ var n = new int[] { PdfObject.NULL, PdfObject.ARRAY, PdfObject.BOOLEAN,
+ PdfObject.DICTIONARY, PdfObject.INDIRECT, PdfObject.NAME,
+ PdfObject.NUMBER, PdfObject.STREAM, PdfObject.STRING };
+ var d = new Dictionary(n.Length);
+ for (int i = 0; i < n.Length; i++) {
+ d.Add(n[i], _ObjectTypeIcons.Images.IndexOfKey(PdfHelper.GetTypeName(n[i])));
+ }
+ return d;
+ }
+
+ static int GetImageKey(DocumentObject d) {
+ if (d.Value != null) {
+ var po = d.Value;
+ if (po.Type == PdfObject.INDIRECT && d.ExtensiveObject is PdfObject) {
+ po = d.ExtensiveObject as PdfObject;
+ }
+ return __PdfObjectIcons.GetOrDefault(po.Type);
+ }
+ return __PdfObjectIcons[PdfObject.NULL];
+ }
+
+ void _GotoImportLink_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) {
+ AppContext.MainForm.SelectFunctionList(Function.Patcher);
+ }
+
+ void bookmarkEditor1_DragEnter(object sender, DragEventArgs e) {
+ e.FeedbackDragFileOver(Constants.FileExtensions.PdfAndAllBookmarkExtension);
+ }
+
+ void ControlEvent(object sender, EventArgs e) {
+ if (sender == _OpenButton) {
+ ExecuteCommand(Commands.Open);
+ }
+ }
+
+ void LoadDocument(string path) {
+ _MainToolbar.Enabled = _ObjectDetailBox.Enabled = false;
+ _DescriptionBox.Text = "正在打开文档:" + path;
+ _LoadDocumentWorker.RunWorkerAsync(path);
+ }
+
+ void ShowDescription(string name, string description, string type) {
+ _DescriptionBox.Text = String.Empty;
+ if (String.IsNullOrEmpty(name)) {
+ return;
+ }
+
+ _DescriptionBox.SetSelectionFontSize(13);
+ _DescriptionBox.SetSelectionBold(true);
+ _DescriptionBox.AppendText(name);
+ _DescriptionBox.SetSelectionFontSize(9);
+ if (type != null) {
+ _DescriptionBox.AppendText(Environment.NewLine);
+ _DescriptionBox.AppendText("类型:" + type);
+ }
+ if (description != null) {
+ _DescriptionBox.AppendText(Environment.NewLine);
+ _DescriptionBox.AppendText(description);
+ }
+ }
+
+ void ToolbarItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ if (_ObjectDetailBox.FocusedItem == null) {
+ return;
+ }
+ var ci = e.ClickedItem;
+ if (ci == _SaveButton) {
+ SaveDocument();
+ return;
+ }
+ var cn = ci.Name;
+ var n = _ObjectDetailBox.GetModelObject(_ObjectDetailBox.FocusedItem.Index) as DocumentObject;
+ if (ci == _DeleteButton) {
+ //if (this.ActiveControl == _DocumentTree) {
+ if (n == null || n.Parent == null) {
+ return;
+ }
+ var po = n.Parent.Value as PdfObject;
+ if (po == null) {
+ return;
+ }
+ if (po.Type == PdfObject.INDIRECT) {
+ po = n.Parent.ExtensiveObject as PdfObject;
+ }
+ if (PdfHelper.CompoundTypes.Contains(po.Type)) {
+ if (n.Parent.RemoveChildByName(n.Name)) {
+ _ObjectDetailBox.RefreshObject(n.Parent);
+ }
+ }
+ //}
+ }
+ else if (ci == _ViewButton) {
+ if (n == null) {
+ return;
+ }
+ var s = n.ExtensiveObject as PRStream;
+ if (s == null) {
+ return;
+ }
+ if (PdfName.IMAGE.Equals(s.GetAsName(PdfName.SUBTYPE))
+ || n.Name == "Thumb") {
+ var info = new Processor.Imaging.ImageInfo(s);
+ var bytes = info.DecodeImage(_imgExpOption);
+ if (bytes != null) {
+ if (info.LastDecodeError != null) {
+ FormHelper.ErrorBox("导出图像时出现错误:" + info.LastDecodeError);
+ }
+ else if (info.ExtName != Constants.FileExtensions.Dat) {
+ new ImageViewerForm(info, bytes).Show();
+ }
+ }
+ }
+ else {
+ var b = PdfReader.GetStreamBytes(s);
+ using (var ms = new MemoryStream(b))
+ using (var r = new StreamReader(ms))
+ using (var f = new TextViewerForm(r.ReadToEnd(), true)) {
+ f.ShowDialog(FindForm());
+ //_DescriptionBox.Text = String.Empty;
+ //while (r.Peek () != -1) {
+ // _DescriptionBox.AppendText (r.ReadLine ());
+ // _DescriptionBox.AppendText (Environment.NewLine);
+ //}
+ }
+ }
+ }
+ else if (cn == "_ExportBinary") {
+ ci.HidePopupMenu();
+ ExportBinaryStream(n, true);
+ }
+ else if (cn == "_ExportHexText") {
+ ci.HidePopupMenu();
+ ExportBinHexStream(n, true);
+ }
+ else if (cn == "_ExportUncompressedBinary") {
+ ci.HidePopupMenu();
+ ExportBinaryStream(n, false);
+ }
+ else if (cn == "_ExportUncompressedHexText") {
+ ci.HidePopupMenu();
+ ExportBinHexStream(n, false);
+ }
+ else if (cn == "_ExportToUnicode") {
+ ci.HidePopupMenu();
+ ExportToUnicode(n);
+ }
+ else if (cn == "_ExportXml") {
+ ci.HidePopupMenu();
+ var so = _ObjectDetailBox.SelectedObjects;
+ var ep = new List(so.Count);
+ bool exportTrailer = false;
+ if (_ObjectDetailBox.Items[0].Selected || n.Type == PdfObjectType.Trailer) {
+ exportTrailer = true;
+ }
+ foreach (var item in so) {
+ var d = item as DocumentObject;
+ if (d == null) {
+ continue;
+ }
+ if (d.Type == PdfObjectType.Page) {
+ ep.Add((int)d.ExtensiveObject);
+ }
+ else if (d.Type == PdfObjectType.Pages) {
+ foreach (var r in PageRangeCollection.Parse((string)d.ExtensiveObject, 1, _pdf.PageCount, true)) {
+ foreach (var p in r) {
+ ep.Add(p);
+ }
+ }
+ }
+ }
+ if (ep.Count == 1) {
+ ExportXmlInfo((n.FriendlyName ?? n.Name), exportTrailer, new int[] { (int)n.ExtensiveObject });
+ }
+ else {
+ ExportXmlInfo(Path.GetFileNameWithoutExtension(_fileName), exportTrailer, ep.ToArray());
+ }
+ }
+ else if (cn == "_ExpandButton") {
+ _ObjectDetailBox.ExpandSelected();
+ }
+ else if (cn == "_CollapseButton") {
+ _ObjectDetailBox.CollapseSelected();
+ }
+ }
+
+ void AddChildNode(DocumentObject documentObject, int objectType) {
+ using (var f = new AddPdfObjectForm()) {
+ f.PdfObjectType = objectType;
+ if (f.ShowDialog() == DialogResult.OK) {
+ var d = (documentObject.ExtensiveObject ?? documentObject.ExtensiveObject) as PdfDictionary;
+ var v = f.PdfValue;
+ d.Put(new PdfName(f.ObjectName), f.CreateAsIndirect ? _pdf.Document.AddPdfObject(v) : v);
+ documentObject.PopulateChildren(true);
+ _ObjectDetailBox.RefreshObject(documentObject);
+ }
+ }
+ }
+
+ void ExportXmlInfo(string fileName, bool exportTrailer, int[] pages) {
+ using (var d = new SaveFileDialog() { AddExtension = true, FileName = fileName + Constants.FileExtensions.Xml, DefaultExt = Constants.FileExtensions.Xml, Filter = Constants.FileExtensions.XmlFilter, Title = "请选择信息文件的保存位置" }) {
+ if (d.ShowDialog() == DialogResult.OK) {
+ var exp = new PdfContentExport(new ExporterOptions() { ExtractPageDictionary = true, ExportContentOperators = true });
+ using (XmlWriter w = XmlWriter.Create(d.FileName, DocInfoExporter.GetWriterSettings())) {
+ w.WriteStartDocument();
+ w.WriteStartElement(Constants.PdfInfo);
+ w.WriteAttributeString(Constants.ContentPrefix, "http://www.w3.org/2000/xmlns/", Constants.ContentNamespace);
+ DocInfoExporter.WriteDocumentInfoAttributes(w, _fileName, _pdf.PageCount);
+ if (exportTrailer) {
+ exp.ExportTrailer(w, _pdf.Document);
+ }
+ exp.ExtractPage(_pdf.Document, w, pages);
+ w.WriteEndElement();
+ }
+ }
+ }
+ }
+
+ void ExportBinHexStream(DocumentObject n, bool decode) {
+ using (var d = new SaveFileDialog() { AddExtension = true, FileName = (n.FriendlyName ?? n.Name) + Constants.FileExtensions.Txt, DefaultExt = Constants.FileExtensions.Txt, Filter = "文本形式的二进制数据文件(*.txt)|*.txt|" + Constants.FileExtensions.AllFilter, Title = "请选择文件流的保存位置" }) {
+ if (d.ShowDialog() == DialogResult.OK) {
+ var s = n.ExtensiveObject as PRStream;
+ try {
+ var sb = decode ? DecodeStreamBytes(n) : PdfReader.GetStreamBytesRaw(s);
+ sb.DumpHexBinBytes(d.FileName);
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox("在导出流数据时出错:" + ex.Message);
+ }
+ }
+ }
+ }
+
+ void ExportBinaryStream(DocumentObject n, bool decode) {
+ using (var d = new SaveFileDialog() { AddExtension = true, FileName = (n.FriendlyName ?? n.Name) + ".bin", DefaultExt = ".bin", Filter = "二进制数据文件(*.bin,*.dat)|*.bin;*.dat|" + Constants.FileExtensions.AllFilter, Title = "请选择文件流的保存位置" }) {
+ if (d.ShowDialog() == DialogResult.OK) {
+ var s = n.ExtensiveObject as PRStream;
+ try {
+ var sb = decode ? DecodeStreamBytes(n) : PdfReader.GetStreamBytesRaw(s);
+ sb.DumpBytes(d.FileName);
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox("在导出流数据时出错:" + ex.Message);
+ }
+ }
+ }
+ }
+
+ void ExportToUnicode(DocumentObject n) {
+ using (var d = new SaveFileDialog { AddExtension = true, FileName = (n.Parent.FriendlyName ?? n.Name) + ".xml", DefaultExt = ".xml", Filter = "统一码映射信息文件(*.xml)|*.xml|" + Constants.FileExtensions.AllFilter, Title = "请选择统一码映射表的保存位置" }) {
+ if (d.ShowDialog() == DialogResult.OK) {
+ var s = n.ExtensiveObject as PRStream;
+ try {
+ var touni = PdfReader.GetStreamBytes((PRStream)s);
+ var lb = new iTextSharp.text.pdf.fonts.cmaps.CidLocationFromByte(touni);
+ var m = new iTextSharp.text.pdf.fonts.cmaps.CMapToUnicode();
+ iTextSharp.text.pdf.fonts.cmaps.CMapParserEx.ParseCid("", m, lb);
+ using (var w = XmlWriter.Create(d.FileName, DocInfoExporter.GetWriterSettings())) {
+ w.WriteStartElement("toUnicode");
+ w.WriteAttributeString("name", m.Name);
+ w.WriteAttributeString("registry", m.Registry);
+ w.WriteAttributeString("supplement", m.Supplement.ToText());
+ w.WriteAttributeString("ordering", m.Ordering);
+ w.WriteAttributeString("oneByteMappings", m.HasOneByteMappings().ToString());
+ w.WriteAttributeString("twoByteMappings", m.HasTwoByteMappings().ToString());
+ foreach (var item in m.CreateDirectMapping()) {
+ w.WriteStartElement("map");
+ w.WriteAttributeString("cid", item.Key.ToText());
+ w.WriteAttributeString("uni", Char.ConvertFromUtf32(item.Value));
+ w.WriteEndElement();
+ }
+ w.WriteEndElement();
+ }
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox("在导出统一码映射表数据时出错:" + ex.Message);
+ }
+ }
+ }
+ }
+
+ byte[] DecodeStreamBytes(DocumentObject d) {
+ var s = d.Value as PRStream ?? d.ExtensiveObject as PRStream;
+ if (d.Type == PdfObjectType.Image) {
+ var info = new Processor.Imaging.ImageInfo(s);
+ return info.DecodeImage(_imgExpOption);
+ }
+ return PdfReader.GetStreamBytes(s);
+ }
+
+ void SaveDocument() {
+ string path;
+ using (var d = new SaveFileDialog() {
+ DefaultExt = Constants.FileExtensions.Pdf,
+ Filter = Constants.FileExtensions.PdfFilter,
+ AddExtension = true,
+ FileName = FileHelper.GetNewFileNameFromSourceFile(_fileName, Constants.FileExtensions.Pdf),
+ InitialDirectory = Path.GetDirectoryName(_fileName)
+ }) {
+ if (d.ShowDialog() != DialogResult.OK) {
+ return;
+ }
+ path = d.FileName;
+ }
+
+ bool o = false;
+ var n = String.Empty;
+ if (FileHelper.ComparePath(path, _fileName) && FormHelper.YesNoBox("是否覆盖原始文件?") == DialogResult.Yes) {
+ o = true;
+ }
+ _ObjectDetailBox.ClearObjects();
+ _pdf.Document.RemoveUnusedObjects();
+ try {
+ n = o ? FileHelper.GetTempNameFromFileDirectory(path, Constants.FileExtensions.Pdf) : path;
+ using (var s = new FileStream(n, FileMode.Create)) {
+ var w = new PdfStamper(_pdf.Document, s);
+ if (AppContext.Patcher.FullCompression) {
+ w.SetFullCompression();
+ }
+ w.Close();
+ _pdf.Close();
+ }
+ if (o) {
+ File.Delete(path);
+ File.Move(n, path);
+ }
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox("保存文件时出错:" + ex.Message);
+ if (o && File.Exists(n)) {
+ try {
+ File.Delete(n);
+ }
+ catch (Exception) {
+ FormHelper.ErrorBox("无法删除临时文件:" + n);
+ }
+ }
+ LoadDocument(_fileName);
+ return;
+ }
+ LoadDocument(path);
+ }
+
+ void _LoadDocumentWorker_DoWork(object sender, DoWorkEventArgs e) {
+ var path = e.Argument as string;
+ try {
+ var d = new PdfPathDocument(path);
+ _pdf?.Close();
+ _pdf = d;
+ e.Result = path;
+ //Common.Form.Action ev = delegate () { _FilePathBox.Text = path; };
+ //_FilePathBox.Invoke (ev);
+ }
+ catch (iTextSharp.text.exceptions.BadPasswordException) {
+ FormHelper.ErrorBox(Messages.PasswordInvalid);
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox("在打开 PDF 文件时遇到错误:\n" + ex.Message);
+ }
+ }
+
+ void _LoadDocumentWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
+ var path = e.Result as string;
+ _DescriptionBox.Text = String.Empty;
+ if (path != null) {
+ AppContext.RecentItems.AddHistoryItem(AppContext.Recent.SourcePdfFiles, path);
+ DocumentPath = path;
+ ReloadPdf();
+ }
+ _MainToolbar.Enabled = _ObjectDetailBox.Enabled = true;
+ }
+
+ void ReloadPdf() {
+ _imgExp = new Processor.ImageExtractor(_imgExpOption, _pdf.Document);
+
+ _ObjectDetailBox.ClearObjects();
+ _ObjectDetailBox.Objects = ((IHierarchicalObject)_pdf).Children;
+ _SaveButton.Enabled = true;
+ _AddObjectMenu.Enabled = false;
+ _DeleteButton.Enabled = false;
+ }
+
+ void _ExportButton_DropDownOpening(object sender, EventArgs e) {
+ var n = _ObjectDetailBox.GetModelObject(_ObjectDetailBox.FocusedItem.Index) as DocumentObject;
+ var m = _ExportButton.DropDownItems;
+ m["_ExportHexText"].Enabled
+ = m["_ExportBinary"].Enabled
+ = m["_ExportUncompressedHexText"].Enabled
+ = m["_ExportUncompressedBinary"].Enabled
+ = (n.ExtensiveObject as PRStream) != null;
+ m["_ExportXml"].Enabled
+ = __XmlExportableTypes.Contains(n.Type);
+ m["_ExportToUnicode"].Visible = (n.ExtensiveObject as PRStream) != null && n.Name == "ToUnicode";
+ }
+
+ void _AddObjectMenu_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ AddChildNode(
+ _ObjectDetailBox.GetModelObject(_ObjectDetailBox.FocusedItem.Index) as DocumentObject,
+ ValueHelper.MapValue(e.ClickedItem, _addPdfObjectMenuItems, _pdfTypeForAddObjectMenuItems)
+ );
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentInspectorControl.resx b/pdfpatcher/App/Functions/DocumentInspectorControl.resx
new file mode 100644
index 0000000000000000000000000000000000000000..612a367f8a25763d7da07c13e3008f1e4d60c072
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentInspectorControl.resx
@@ -0,0 +1,425 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ False
+
+
+ 17, 17
+
+
+
+ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w
+ LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0
+ ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACa
+ PgAAAk1TRnQBSQFMAgEBNAEAAUQBAAFEAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo
+ AwABQAMAAeADAAEBAQABCAYAATgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA
+ AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5
+ AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA
+ AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm
+ AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM
+ AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA
+ ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz
+ AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ
+ AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM
+ AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA
+ AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA
+ AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ
+ AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/
+ AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA
+ AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm
+ ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ
+ Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz
+ AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA
+ AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM
+ AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM
+ ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM
+ Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA
+ AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM
+ AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ
+ AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz
+ AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm
+ AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw
+ AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD//8A/wD/AP8AGgABzwES
+ ARw9AAFzAXQBbgHvPAABmQFzARoB7AHvJwABFAG8Aw4BvAEOAbwDDgG8ARQIAAEHAe0B9AHrAZM8AAEH
+ AewBRgFFAZM2AAGSAm0B9wIAAe8BRQFGAUUB7yQAA0MB6gEAA0MBAAHqA0MDAAGSAW0BBwHwAesB7wIA
+ AfcBRQFGAUUBBwUAAQcBTwFJAU8BBwMAAQcB7AHrAewCBwHsAesB7AEHAwABBwFPAUkBTwEHEwAB9wFt
+ AbwB9wHvAfIB7AHvAQABhgH3A0UBvAEAAU8B7wEAAXEDVQFxAwAB7QHvAfIB7wLtAe8B8gHvAe0DAAFx
+ A1UBcQEAAe8BTxAAAewB8QEHAe8B9wHvAfIB7QEHAYYBiwEHAW4BRQFuAfACTwEAAU8DdwFPA/cB7QP0
+ Au0D9AHtA/cBTwN3AU8BAAJPAQABFQG8ARUBvAEVAbwBFQG8ARUBvAEVAbwBFQIAAZIB8gHwAQcBkgES
+ AZIB8wHtAa0BzwEAAfABbwFFAW8BTwGYAQACdwHkAncDAAHvAbwB/wG8Au8BvAH/AbwB7wMAAncB5AJ3
+ AQABmAFPEAABBwGSAfMB8AHtAbwB7AHxAa4BzwG7AwABkwFFAwABBwF3AVUBdwEHAwABvAPvArwD7wG8
+ AwABBwF3AVUBdwEHFAABBwGSAfMBBwHrAQcBbQG0AbUnAAFtCxQBbQQAAQcB7QHzAusB9zsAAZIB9wFt
+ Ae88AAH3AbwB7D0AAQcBkgHvPwABzwESARw9AAFzAXQBbgHvKAABBwHOAQcRAAGZAXMBGgHsAe8YAAEH
+ AbUItAG1AQcDAAOtAQAB6gFDAxEBEAEPARQJAAEHAe0B9AHrAZMGAAEUCw4BFAMAAQcBtQG8CPABvAG1
+ AQcDAAGtFAABBwHsAUYBRQGTBQANEAMAAbUMvAG1AwABpxUAAe8BRQFGAUUB7wQADREDAAG1AfEKvAHw
+ AbUDAAGnAgADFQRDAxEEAAGTAXMCSwFuARwBkwFFAUYBRQEHEwABtQHyAfAJvAHwAbUDAAGGEAABSwGZ
+ ApoBdAFLAW4BkwNFAbwRAAEHAbUBuwHxAfAIvAHwAbUDAAGGEAABcwF0BJoBUgFzAQcBbgFFAW4B8AEA
+ DRUCAAG1AfQBtQPxAfAGvAHwAbUDAAGtAgACFAYVBgABBwFLAZoDmQGaAnQBBwFvAUUBbwEADRUCAAEH
+ AbUBuwTyAfEC8AO8AfABtQMAAa0NAAEcA0sBTAGaAUsBAAFLApoCdAEAAZMBRREAAbUB8wryAfMBtQMA
+ Aa0NAAFLAZkEmgF0AUsBdAGaAe0BiwHrFAABuwHxCvIB8QG7AgABzwG0Ac8BAAFtBhQCFQFtAQACdAGZ
+ A3kBmQGaAZkBeQG0AdwBrQQAAW0LFAFtAwABvAG7AfEB8wEJAbUBCQTzAfEBuwG8AgABCQHVAQkMAAG8
+ AnQBmQFvAekBTAFSAVEBUgHvAbQB9xUAAbwCuwG1AfQBtQW7AbwTAAG8AZMBdAFGARYBRgFSAXoBUQJ0
+ AbwYAAEHAbUBBxoAAfABvAF0ARcBbwFSAVgBdAGZAbxwAAG1AbQBtQ0AAbUBtAG1CAABkgPsAZIgAAG0
+ AfQBtA0AAbQB9AG0CAABkgPzAZIHAAEJAc8GAAGtAQkPAAG7AbQBuwwAAbwCtAG7CAAB9wH0AfMB9AH3
+ BwAB1QG0Aq0ChgKnAq0PAAG8AbUMAAG8AbUBvAMAAQcG7wHtAf8B9AH/Ae0C7wEHBAABCQHPBgABrQEJ
+ DwABBwG7CwABvAG1AbwEAAHvBv8B8gEHAf8BBwHyAv8B7xwAAbwBtQEHCgABvAG1AbwFAAHvB/QB8gEH
+ AfID9AHvBQABFAEPARQBAAH3Ag8BFAoAAQcBtQEHAfABvAG7AQcKAAG8AbUBvAYAAfcC9AH3A/QB9wP0
+ AfcC9AH3BgABFAHvAgABbQEUBwAB8AEHAbsCtQH0ArUBuwEHAfAJAAG8AbUBvAcAAZIC8wEHA/MBBwPz
+ AQcC8wGSBgAB7ARDAewHAAEHAbsBvAHwAQcBtQEHDAABvAG1AbwIAAHtA/IBBwHsAQcH8gHtBgAB7wES
+ Ae8B7AFDAe8GAAEHAbsBvBAAAbwBtQG8CQAB7ALxAQcB7QH0Ae0BBwbxAewHAAETAQcBbQETBwABuwEH
+ EAABvAG1AbwKAAHsAusBbQH0AfMB9AFtBusB7AcAAuwBFQHsBwABuwG8DwABvAG7AbwOAAH3Af8B9AH/
+ AfcOAAEHAeoBFAEHBgABBwG1AQcNAAEHArUBvA8AAe8D/wHvDwACEgcAAbUB9AG1DQABtQH0AbUQAAEH
+ A+8BBxgAAQcBtQEHDQABBwG1AQc/AAHtCusB7TQAAewK/wHsAgABtQG0AbUKAAG1AbQBtQEAAQcBtQq0
+ AbUBBxMAAewK/wHsAgABtAH0DLQB9AG0AQABtQEJCvABCQG1BAAB8AEIAeAB2QHTAUIB/AHJAbUB8AUA
+ Ae0I/wH0Af8B7QIAAbsBtAG7CvABuwG0AbsBAAG1AfADvATwA7wB8AG1BAAB8AEIAbMBxwHFAYABpQGD
+ AbUB8AUAAe0C/wHwAeoC8gHqAbwB9AH/Ae0DAAG1AfAKvAHwAbUCAAG1AfADvAG7ArUBuwO8AfABtQQA
+ AfABCAHAAbgB/AHFAacBzgG1AfAFAAHtAf8B8wFtAQcC/wEHAW0B8gH/Ae0DAAG1AfAKvAHwAbUCAAG1
+ AfACvAG1AQcCvAEHAbUCvAHwAbUFAAHwAbwBmwFCAfwBrQEJAfAGAAGSAf8B7wH3Av8C9AH3Ae8B/wGS
+ AwABtQHyAfAJvAHwAbUCAAG1AfEB8AG7AQcEAAEHAbsC8AG1BgABvAF7AdMBQgGsAbsB8AYAAfcB/wHz
+ AewBvAL0AQcB7AHyAfQB9wMAAbUB8gHxAfAIvAHwAbUCAAG1AvIBtQG8BAABvAG1AvABtQYAAbwBPAH+
+ AdMBsgG7AfAGAAH3Av8B8QHsAfMB8gHsAbwB8wH0AfcDAAG1AfID8QHwBrwB8AG1AgABtQLyAbUBvAQA
+ AbwBtQLwAbUDAAPwAbwB+gG+Af4BgQG7A/AEAAH3Av8F9ALzAfQB9wMAAbUF8gHxAvADvAHwAbUCAAG1
+ AvIBuwEHBAABBwG7AbwB8AG1AwAEvAEdAXsBvgGVAbsEvAMAAfcB/wX0AvMB8QH0AfcDAAG1AfMK8gHz
+ AbUCAAG1AfMB8gHwAbUBBwK8AQcBtQHwAfIB8wG1AwABUwFSAV0BvAE5AfoBewF2AbsB4AGzAboBvAMA
+ AfcB/wT0AvMC8QH0AfcDAAG7AfMK8gHzAbsCAAG7AfMC8gHwAbsCtQG7AfAC8gHzAbsDAAFNASUBWAF+
+ AToBOQH6AVQBfAGcAbIBuQG8AwAB9wH/A/QC8wHxA/cB7AIAAQcBtQEJCvMBCQG1AQcBAAG7AfME8gLz
+ BPIB8wG7AwABTQEgASUBMQE3AToBHQEzAXYBlQHZAbkBvAMAAfcB/wL0AvMC8QHvAf8B9wEHAgABtQH0
+ AbUKuwG1AfQBtQEAAbsB8ArzAfABuwMAAUcBTQFTAXoB+wE7AToBOQJaAXwBnAG8AwAB7wL/BfQBBwHv
+ AQcDAAEHAbUBBwoAAQcBtQEHAQABvAy7AbwTAAnvAQcoAAH3Am0B9xsAAfAKAAG8CAAB7wGSCgAB9wFt
+ AbwB8AFtAfcYAAHwAbsBkgHvAQcFAAG8Ae8C9wHwBQAB8AHtAeoB6wH3Ae8BvAYAAfcB6wLvAQcB8AHs
+ Ae8EAAGuAgABEQsAAUMDAAEJAdMB1AG0Ae0B7wEHAQAB8AHvAbMC0wHvAfAEAAEHAesF6gFtAewBvAMA
+ Ae8B6wEHAvcB7wEHAfAB7AHvAwABpgG0AQABEQsAAUMEAAG7AdQC0wG0AZIB7wG0AtMBswG7AbwEAAH3
+ BosD6gFtAbwBAAHvAewBvAEHAe8C9wHvAQcB8QHtAQcCAAKGBQAB1ALTAdQB2woAAQkB1AHTArMB0wGz
+ AbsB8AYAAbwB9wGRAtMBswGRAesD6gHsAQAB7AHxAbwCBwHvAvcB7wEHAfIB7QEHAQACpwYAAdQB0wHb
+ DQABuwLTAbMBkgHwCQABvALTAbMB7wEAAe8BbQLqAQcB7QHyAfEBvAIHAe8C9wHvAQcB8wHtAQcCrQYA
+ AdQB0wHbDAABvAHUAdMB1AHTAZEB7wkAAbwC0wHbAwAB7ALqAfcBBwHtAfIB8QG8AgcBkgESAe0B7wEH
+ AfMB7QGtAc8GAAHUAdMB2wsAAfABswHTAfcBvALUAe0BvAgAAbwC0wHbAwAB7QLqAZIBAAEHAe0B8gHx
+ AbwBBwHtAbwB7AH3Ae8B8gGuAc8BCQYAAdQB0wHbCwABuwHTAbQBvAEAAbsB0wGRAe8IAAG8AtMB2wMA
+ AewC6gH3AgABBwHtAfIB8QG8Ae8B6wL3AfAB6wG0AbUHAAHUAdMB2wkAAvAB1AHTAfcD8AHUAbMB7QLw
+ BgABvALTAdsCAAHwAW0C6gEHAwABBwHtAfMB8QG8AesBBwHwAW0B9wYAAbsCAAHUAdMB2wEAAbwBuwUA
+ AfABBwHtAdMBswGRAZIB9wGSAbMB0wHsAe0B9wG8BQABvALTAdsCAAEHAesB6gHrBQABBwHtAfMB8QHr
+ AfMBbQH3BwAB1AIAAdQB0wHbAQABvAHUBQABvAzTAbUBvAIAAdQBvAEAAbwC0wHbAgAB1AEJAQcB7wYA
+ AZIB7QHzAesB7AHvCAAI1AHbBQAB8AS8AbsB0wGzAe8FvAMAAdQDuwLTAdQCuwHUAbsIAAGSAQcB7QFt
+ Ae8cAAG7AdMBtQHwCAAK1AEJCAAB9wIAAeseAAEJAfAcAAEHAZIB7QHvbgAB7wGSGAABvAIJAbwB8B8A
+ AfAB7QHqAesB9wHvAbwHAAEHAewB6wJtAuwB9wEHBAABvAHcAdsB2gHbAQkBvB0AAQcB6wXqAW0B7AG8
+ BQAB7AHvAQcB8AG8AQcB7wHtAewB7QEHAgABvAHcAtMB2gHbAQkBvBsAAfcBbQjqAW0BvAQAAewCvAEH
+ BbwB7wHsAe8BAAG8AdwB2gLTAdQB2wEJAbwaAAG8AfcB7AFtAuoB7AHrA+oB7AQAAu0CvAMHAbwBBwK8
+ AewBBwHwAQkB2wHaAtMB1AHbAQkBvBEAArwJAAG8Ae8B7AHvAQAB7wFtAuoBBwMAAbwB7AHtAfAB7AEA
+ AewBvAEHAfcB6gHtAZICAAEJAdsB2gPTAdsB3AG8BQAC1AG8AQABCQLTAtsC0wHUAdMB1AG8AQAC1AG8
+ AQABCQLTAtsC0wHUAdMBsgHqAfcB7wLsAZIB7wHrAbwBkgHrAZICBwLsAW0B7AMAAbwB3AHbA9MB2wHc
+ AbwEAAG8AdsCAAEJAdMB1AIAAdMB1AEAAboB0wG6AQABvAHbAgABCQHTAdQCAAHTAdQBAAG0AdMBiwGS
+ AewB7wEHAfcB7AGSAbwBBwG8AwcB7AEHAe8B6wQAAbwB3AHbA9MB2wHcAbwEAAHUAtsB1AHTAbsCAAHT
+ AdQBAAG7AdMB1AIAAdQC2wHUAdMBuwIAAdMB1AEAAbQB0wGzAfcBkgG8AgcBvAcHAe8BkgLtBQABvAHc
+ AdsD0wHaAdsBCQMAAQkBugG8AtMBvAIAAdMB1AEAAbsB0wHbAgABCQG6AbwC0wG8AgAB0wHUAfABiwHT
+ AYsBBwH3Ae8DBwHtARQB7AIHAe8B7AH3AgcB9wYAAbwBCQHbAdQC0wHaAdsBCQHwAgAB1AG6AdMB2wMA
+ AtMB2wHUAdMBvAMAAdQBugHTAdsDAALTAbQC0wHrAQABBwGSAe8BvAEHAeoBbQETAe0B7wGSAfcB7AHv
+ AfcB7wcAAbwBCQHbAdQC0wHaAdwBvAIAAdsC0wEJAwAB0wHUAQkBuwG8BAAB2wLTAQkDAAHTAdQBCQG7
+ AQcB7wIAAbwC9wEHAesC9wHqAu8C8QHtAZIBvAgAAbwBCQHbAdoC0wHcAbwCAAG8AdMB1AQAAdMB1AcA
+ AbwB0wHUBAAB0wHUBwAB8AEHAfcB7QLsAe8CBwLvAfcBBwoAAbwBCQHbAdoB2wHcAbwDAAEJAbwDAAHb
+ AdQB2wgAAQkBvAMAAdsB1AHbCQAB8AEHAe8B9wKSAfcB7wEHAbwMAAHwAbwCCQG8aAACvA4AArwXAAGU
+ CbECjwNqAbEFAAHwAbUBzQG8DAAB8AG7AdMBvBcACrECjwRqBAABuwHOAs0C1AG0CQABuwHUAtMC2gG6
+ CAAB7wFzBEsBcwEcAQcEAAGUCbECjwNqAbEEAAG1Bs0B1AHwBwABuwbTAdoB8AYAAUsBdAOaAZkCdAFL
+ AXQBBxcAAbwB1AHNAbsBtQLNAdUIAAG8AdoB0wK7AtMB2wYAAUsImgF0AVIBkwMAAc8BEgEcDAAB9wXs
+ Aa4B7wEAAQkCzQG7BQABugTbAgABuwLTAbsFAAJ0ApoDmQSaAXQBmQIAAXMBdAFuAe8LAAGSARMFcwHq
+ AgAB1QHNAdQFAAG7AdoB0wHaAQkDAAHbAdMB2gUAAbwBcwF0AZoBSwEAAUsCmgEcAYsBcwF0AgABmQFz
+ ARoB7AHvCgABvAETBeUBEgEHAQABvALNAbwFAAHaAdMB2wQAAbwC0wG8AQAB7wJLARwB7wFLAZoBdAFL
+ AXQBmgGZArQBiwFuAwABBwHtAfQB6wGTCgAB6wFzBOUBcwHsAgAB1AHNAbsFAAHaAdMB2wUAAdoB0wG7
+ AQACdAGaAXQBUgF0BJoCmQG0AtwBswQAAQcB7AFGAUUBkwkAAe8B6gTlAXkBEgG8BM0BtAQAAdoB0wHb
+ AwABvATTAboBdAGaAZkDmgaZAe8CtAFzBQAB7wFFAUYBRQHvCQABEgF5BOUB6gHvAbUCzQHOBQAB2gHT
+ AdsEAAG7AtMB2gEAAnQBmgJ5AW8B6QFvAnkBdAEwAXQCeQF0BgABkwFFAUYBRQEHCAAB7AFzBOUBcwHr
+ AQAB1AHNAQkFAAHaAdMB2wUAAdoB0wEJAQABvAJ0AZoBeQNGAW8BdAJSAVECdAGZBwABkwNFAbwHAAEH
+ ARIF5QETAbwBCQHVAwAB2gIAAdoB0wHbAQABvAHaAgABCQHbAwABvAJ0AXkBRgIWAUYBdAFYAnoBUQF0
+ AbwIAAEHAW4BRQFuAfAHAAESBXMBEwGSBQAB2gLbAdQB0wHaAtsB2ggAAfABmQF0AW8CFwF0AZoBeQJY
+ AXQBvAoAAfABbwFFAW8HAAHvBuwB9wUACLsBCQoAAfABBwGTBXQBmQG8DQABkwFFAZM+AAGTAUUEAAHt
+ CusB7QQAAe0K6wHtBAAB6wEOCYsBrhQAAewK/wHsBAAB7Ar/AewEAAEPAW0JtAGLAgAB7wn3A+8C9wMA
+ AewF/wFQAk8BcgH/AewEAAHsCv8B7AQAAREBbQm0AYsCAAEHAfEDCALxAvAB8QG8Ad0BvAHzAe8DAAHt
+ Af8BbwJFAUYBUAJXAVAB/wHtBAAB7Qj/AfQB/wHtBAABEQFtA7QB8AG8BLQBiwIAAbwBCAFVAZcBVgG7
+ AdoBugHbAbsBpwHmAacBvAEHAwAB7QH/BEYBUAJXAVAB/wHtBAAB7Qf/AvQB/wHtBAABQwFtA7QBGQHx
+ BLQBiwIAAbwBCAKXAeQBCAPbAQkD5gHxAQcDAAHtAf8BRgLjARcBVgJ9AVYB/wHtBAAB7Qb/A/QB/wHt
+ BAABQwFtCbQBiwIAAbwBCAKXAeQBuwPbAQkD5gHdAQcDAAGSAf8BRgEXAY0BrgGQAXEBVgGYAf8BkgQA
+ AZIF/wT0Af8BkgQAAUMBbQO0AvEEtAGLAgABvAHxAwgB8QPwAfEBtgHXAbYB8wEHAwAB9wH/AZMBRgGL
+ ArMBiwP0AfcEAAH3BP8G9AH3BAABFQHrA7QBtQEZAQkDtAGLAgABvAEbAXkCfgEbAvQB/wHwAaoB0QHL
+ AfIBBwMAAfcD/wSzAfQB8wH0AfcEAAH3A/8F9AHzAfQB9wQAARUB6wS0AbsBGQG7ArQBrQIAAbwBGwN+
+ ARsC9AH/AfED0QHeAQcDAAH3Av8B9AGzAtsBswLzAfQB9wQAAfcC/wX0AvMB9AH3BAABFQHsArQCtQG7
+ ARkBuwK0AbMCAAG8ARsDfgEbA/8B8gPRAfMBvAMAAfcB/wL0AbsCswG6AfMB8QH0AfcEAAH3Af8F9ALz
+ AfEB9AH3BAABFAHsArQEGQG1ArQBswIAAbwB8wMaARsDGgHyAbYB8AG2AfQBBwMAAfcB/wT0AvMC8QH0
+ AfcEAAH3Af8E9ALzAvEB9AH3BAABFAHsAboHtAG6AbQCAAHwARsBeQJ6AZoBFwHjARcBtwGwAdIBqwHe
+ AbwDAAH3Af8D9ALzAfED9wHsBAAB9wH/A/QC8wHxA/cB7AQAARQB7AHcB7oB3AG0AgAB8AEbA3oBGgHj
+ AhYBvQPSAd4BvAMAAfcB/wL0AvMC8QHvAf8B9wEHBAAB9wH/AvQC8wLxAe8B/wH3AQcEAAEUARIKtAIA
+ AfEBGwN6ARoD4wG9A9IB3gG8AwAB7wL/BfQBBwHvAQcFAAHvAv8F9AEHAe8BBwUAAW0B7wIHArwB8ALz
+ AfQB/wH3AgAB8AH/AxsB9gG9AhsB9AHeAfMB3gH/AbwDAAnvAQcGAAnvAQcGAAGSAW0KtAIAAbwB8AHx
+ AfAB8QHwAfED8AHxAfAB8QHwAbwDAAHtCusB7QQAAe0K6wHtJAAB7Ar/AewEAAHsCv8B7AYAAQcBrgSG
+ Aa4BBwgAAQcDiwG1AfEB8AcAAewK/wHsBAAB7AH/BSoBMQIqAf8B7AUAAbUBhgGnAa0CzgGtAacBhgG1
+ BwAB9wRlAQcB8AcAAe0I/wH0Af8B7QQAAe0B/wUxATcCMQH/Ae0EAAG1AYYBrQLOAq0CzgGtAYYBtQYA
+ AbwCBwGLAWUBtQHwBwAB7QH/AfcB7AG8A/8C9AH/Ae0EAAHtAf8BKgMwATEBWQFYATEB/wHtAwABBwGL
+ BK0C8wStAYsBBwIAAfAF8QGuAWUBtQXxAfACAAHtAf8B7QH/AfcB8gH/A/QB/wHtBAAB7QH/AQ8BQwFE
+ AUsBeQGgAXkBWAH/Ae0DAAG0Ba0B8gHzBa0BtAIAAZEFiwFmAWUFiwGRAfEB7QLsAu0B8gH/AbwB8wP0
+ Af8BkgQAAZIB/wEVAUQCWAF6AuUBWQH/AZIDAAHPBa0B8AHyBa0BzwIAAZEFiwJlBYsBkQHwAewI/wT0
+ AfcEAAH3Af8BRAFRAlgBWQHlAVkBWAH0AfcDAAGtAc8DrQGnAbwB8AGnBa0GAALwAZIBZQGLAe8B8QHw
+ AwAB9wLtAvcB8wH/AbwB8wL0AfMB9AH3BAAB9wH/AVIHWAH0AfcDAAGtAc8DrQGnArwEpwKtAgAD8AG1
+ AfcCtQGRAmUBkQHxA/ACAAH3Af8B7wH/AQcB8gL0AvMB9AH3BAAB9wH/CFgB9AH3AwACzwStAoYBpwKG
+ AacBrQHPAgABBwH3AQcBiwZlAYsBvAHvAbwB8AIAAfcB/wG8Ae8B8AL0AvMB8QH0AfcEAAH3Af8IMQH0
+ AfcDAAG1As8DrQL/A60BzwGtAbUCAAH3AWUBkQHvBvcBtQGRAWUBtQHwAgAB9wH/BPQC8wLxAfQB9wQA
+ AfcB/wT0AvMC8QH0AfcDAAEHAa0B1QLPAa0C/wGtAs8BtAGtAQcCAAH3AWUBiwiRAYsBZQG1AfACAAH3
+ Af8D9ALzAfED9wHsBAAB9wH/A/QC8wHxA/cB7AQAAbUBrQLVAbQCzwG0AtUBrQG1AwAB9wxlAfcB8AIA
+ AfcB/wL0AvMC8QHvAf8B9wEHBAAB9wH/AvQC8wLxAe8B/wH3AQcFAAG1Aa0BzwTVAc8BrQG1BAABvATv
+ AfcCZQGSBO8BvAHwAgAB7wL/BfQBBwHvAQcFAAHvAv8F9AEHAe8BBwcAAbwBtQHPAq0BzwG1AbwKAAG8
+ AZIBkQHwCAAJ7wEHBgAJ7wEHLAABSwHvGAAB7QrrAe0TAAHsBesBSwHDAQMBbQPrAewBAALwAbwCBwGS
+ AW0BDgFtAZICBwG8AvADAAHsCv8B7BMAAewB8QG8AQcB8QIHAVIBegFRARwBBwHwAewBAAGuBIsBbQH3
+ Ae0B9wFtBIsBrgMAAe0K/wHtEwAB7QH/AvEB/wLxAZkBUgF6AVEBmQH0Ae0BAAGLAu8BBwG8AfAB8wHt
+ AfMB8AG8AQcC7wGLAwAB7QH/AUYBGgEHAUYD/wH0Af8B7RMAAe0B/wG8AQcB/wEHAbwB8AGZAVgBegFR
+ ARoB7QEAAYsE/wH0AfMB9wL0BP8BiwMAAe0B/wRGAv8C9AH/Ae0IAAEcAUsBHAgAAZIB/wLxAf8D8QHw
+ ARoBUgF6AuwBAAGLAf8BRgIHAUYB8wH3AvQE/wGLAwAB7QH/AUYC4wFGAf8D9AH/Ae0DAAEcAUsBHAEA
+ ARwBSwGZAUsBHAcAAZIB/wEHAbwB/wMHAe8B9AEcAZIB9AHqAZMBiwH/BEYB8wH3AvQE/wGLAwAB9wH/
+ AUYC4wFGBPQB/wH3AwABSwGaAUsBcwFLAZoBSwGaAksBcwEHBAAB9wH/AvEB/wX0AfABBwEcARYBRgGL
+ Af8BRgLjAUYB8wHvAvQE/wGLAwAB9wH/AUYC4wFGA/QB8wH0AfcDAAGTAVIBmgFLAZoBSwGaAXQBmgJ0
+ AUsBHAMAAfcB/wEHAbwB9AHsAe0BbQESAfQB7wIHAUYBkwGLAf8BRgLjAUYB8wHvAvQE/wGLAwAB9wH/
+ ARcC4wFGAvQC8wH0AfcEAAGZAXQBmgF0AZoBdAGaAZkBdAF5AXQBTAMAAfcB/wLxAfQB6gHsAe0BbQHz
+ ArwB8wH3AQABiwH/ARcC4wFGAfMB7wL0BP8BiwMAAfcB/wEXAuMBFwH0AvMB8QH0AfcEAAGTAnQBmgF0
+ ApoCdAGZAZoBdAMAAe8B/wHtAfcB8AESAeoB7AHtAfMB7AH3AbwB7wEAAa0B/wEXAuMBFwHzAQcC9AT/
+ Aa0DAAH3Af8BFwIWARcC8wLxAfQB9wQAAXQBmgJ0ApoBmQOaAXQBmQMAAe8B/wX0AvMB8gLxAfIB7wEA
+ AbMB/wEXAhYBFwHzAQcC9AT/AbMDAAH3Af8BFwIWARcB8wHxA/cB7AQAAZkJdAGZBAAB7wH/AgcB9AMH
+ Ae8B8QP3AewBAAG0Af8BFwIWARcB8wG8AvQE/wG0AwAB9wH/ARcCFgEXAvEB7wH/AfcBBxMAAe8E9ALz
+ AfIC8QHvAf8B7wEHAQABtAH/ARcCFgEXAfMB7wHzAfQE/wG0AwAB7wH/ARcCFgEXAvQBBwHvAQcUAAHv
+ BPQD8wLyAQcB7wEHAgABtAH/ARcCFgFGAe8BBwHvAbwB8gH0Av8BtAMAAu8BRgIWAUYD7wEHFQABBwrv
+ AQcDAALvAkYBbwGTAbwBAAG8AQcF7wUAAW8CFwFvKgAB7QnrAYsBkRQAAe0K6wHtFAAB7An/Aa0BiwG1
+ AQABvAIHAZIBbQEOAW0BkgIHAbwF8AIAAewK/wHsFAAB7AX/AbQEswHaAa0BtQGuAosBbQH3Ae0B9wFt
+ B4sBrgIAAewK/wHsBQABBwjsAQcFAAHtBf8BswHcBdsBswGLAQcBvAHwAfEB7QHzAfABvAEHBe8BiwIA
+ Ae0B/wK8AfABvAP/AfQB/wHtBQABkgG8BvMBvAGSBQAB7QX/AboEtAHcAbMBuwGLAv8B9AHzAfcB8wP0
+ Bf8BiwIAAe0B/wTzAv8C9AH/Ae0FAAHtAfMB8gHwAeoB8ALyAfMB7QUAAe0G/wP0AbQBswG7AQABiwL/
+ AfQB8wH3AfME9AT/AYsBbwcfAW4DvAH/Ae0FAAGSAfMB8QNtAfEC8wGSBQABkgX/BPQB3AG0AgABiwL/
+ AfQB8wH3AfMB9ALvAbwBBwLwAf8BiwIfAyAEHwPxAf8BkgUAAfcB9ALsAfAC7AHxAfQB9wUAAfcE/wb0
+ AfcCAAGLAv8B9AHzAe8B8wT0Af8C8wH/AYsCIAHzAZMCRgEgAh8CvAEHAfQB9wUAAfcB9AHsAfIB9AHy
+ AuwB9AH3BQAB9wP/BfQB8wH0AfcCAAGLAv8B9AHzAe8B8wH0ASoBMAFSAf8B8AG8Af8BiwIgAW8BvQGU
+ Ab0B9AFvAR8D8QH0AfcFAAHvAf8E9AHzAe0B/wHvBQAB9wL/BfQC8wH0AfcCAAGLAv8B9AHzAe8B8wH0
+ AUoBWAFZAf8C8wH/AYsDIAHjAW8BvQFGAiABBwG8AQcB9AH3BQAB7wb/AfIB/wHvBQAB9wH/BfQC8wHx
+ AfQB9wIAAa0C/wH0AfMBBwHzAfQBNwJYAf8B8AG8Af8BrQMgAUYBvQFvAyAC8wHxAfQB9wUAAe8B8gb/
+ AfIB7wUAAfcB/wT0AvMC8QH0AfcCAAGzAv8B9AHzAQcB8wT0BP8BswMgAfkB/wFGAyAB8wLxAfQB9wUA
+ AbwI7wG8BQAB9wH/A/QC8wHxA/cB7AIAAbQC/wH0AfMBvAHzAfQC7wK8A/8BtAIgAvkFIAHxA/cB7BQA
+ AfcB/wL0AvMC8QHvAf8B9wEHAgABtAL/AfQB8wHvAfME9AT/AbQBbwcgAW8B8QHvAf8B9wEHFAAB7wL/
+ BfQBBwHvAQcDAAG0AfQB8gG8Ae8BBwHvAbwB8QHzAfQE/wG0AgAB7wL/BfQBBwHvAQcVAAnvAQcEAAPv
+ AQcBvAEAAbwBBwjvAgAJ7wEHBgAB7QrrAe0EAAHtCusB7QQAAe0K6wHtBAAB7QrrAe0EAAHsCv8B7AQA
+ AewK/wHsBAAB7Ar/AewEAAHsCv8B7AQAAewK/wHsBAAB7Ar/AewEAAHsCv8B7AQAAewC/wG8AeoB8gEH
+ AeoBBwL/AewEAAHtCP8B9AH/Ae0EAAHtAf8CvAHwAbwD/wH0Af8B7QQAAe0C/wHqAbwB/wFtAfEB/wH0
+ Af8B7QQAAe0C/wHyAeoB/wHqAf8B6gH0Af8B7QQAAe0C/wEaAWkC/wFpAQcB9AH/Ae0EAAHtAf8E8wL/
+ AvQB/wHtBAAB7QL/Ae8B7QH/Ae0B7wL0Af8B7QQAAe0C/wHyAW0B/wFtAf8BbQH0Af8B7QQAAe0C/wEa
+ BGkB8AH0Af8B7QQAAe0B/wG8AfABvAEHBLwB/wHtBAAB7QH/Ae8GbQG8Af8B7QQAAe0C/wG8AW0B/wEH
+ AW0BBwH0Af8B7QQAAZID/wGOAhoBjgL0Af8BkgQAAZIB/wPzAfIE8QH/AZIEAAGSA/8B6wLwAesC9AH/
+ AZIEAAGSBf8E9AH/AZIEAAH3A/8BGgGTAW8BGgP0AfcEAAH3Af8BvAIHAbwBBwK8AQcB9AH3BAAB9wH/
+ AfEG7AEHAfQB9wQAAfcC/wG8AewBvAHyAewBvAL0AfcEAAH3A/8B9AJvAvQB8wH0AfcEAAH3Af8B8wHy
+ BvEB9AH3BAAB9wP/AQcB7wH0Ae8BBwHzAfQB9wQAAfcC/wHsAfQB7AH0AewB8gHzAfQB9wQAAfcC/wL0
+ AvMB9ALzAfQB9wQAAfcB/wEHAbwEBwG8AQcB9AH3BAAB9wL/AfQB8gHtAfQBvAHtAfMB9AH3BAAB9wL/
+ AewB9AHsAfQB7AHwAfMB9AH3BAAB9wH/BfQC8wHxAfQB9wQAAfcB/wTxAfQC8wHxAfQB9wQAAfcB/wX0
+ AvMB8QH0AfcEAAH3Af8B9AG8AewBvAHyAewB8AHxAfQB9wQAAfcB/wT0AvMC8QH0AfcEAAH3Af8CBwG8
+ AQcC8wLxAfQB9wQAAfcB/wT0AvMC8QH0AfcEAAH3Af8E9ALzAvEB9AH3BAAB9wH/A/QC8wHxA/cB7AQA
+ AfcB/wP0AvMB8QP3AewEAAH3Af8D9ALzAfED9wHsBAAB9wH/A/QC8wHxA/cB7AQAAfcB/wL0AvMC8QHv
+ Af8B9wEHBAAB9wH/AvQC8wLxAe8B/wH3AQcEAAH3Af8C9ALzAvEB7wH/AfcBBwQAAfcB/wL0AvMC8QHv
+ Af8B9wEHBAAB7wL/BfQBBwHvAQcFAAHvAv8F9AEHAe8BBwUAAe8C/wX0AQcB7wEHBQAB7wL/BfQBBwHv
+ AQcFAAnvAQcGAAnvAQcGAAnvAQcGAAnvAQcWAAHtCusB7QQAAe0K6wHtBAAB7QrrAe0UAAHsCv8B7AQA
+ AewK/wHsBAAB7Ar/AewKAAG0AbUIAAHsCv8B7AQAAewK/wHsBAAB7Ar/AewKAAKLAbUHAAHtAf8BvAHw
+ AbwB8AG8AfACvAH/Ae0EAAHtBv8BBwHtAQcB/wHtBAAB7QH/AdUB/wG8AvAB8QH/AfQB/wHtCgABiwHa
+ AYsBtQYAAe0G/wHyAvEB/wHtBAAB7QT/Ae8CkgH0AZIB/wHtBAAB7Qf/AvQB/wHtCgABrQHZAdoBrQG1
+ BQAB7QH/AioCUgH/AQcCvAH/Ae0EAAHtBP8B9wH/AbwB7wG8Af8B7QQAAe0B/wHrAf8BvAHwAbwB8AG8
+ AfQB/wHtAwABtAetAdoB0wHaAa0BtQQAAZIB/wFEAVIBegFZAfQD8QH/AZIEAAGSBP8B9wT0Af8BkgQA
+ AZIF/wT0Af8BkgMAAbMB3APbAdoFswHaAbMBtQMAAfcB/wI3AlgB9AEHAbwBBwH0AfcEAAH3Af8BBwGS
+ AQcB7wH0AQcBkgEHAfQB9wQAAfcB/wHVAf8BvAHwAbwB8AP0AfcDAAGzBNsB1QG0BbMB2wGzAwAB9wP/
+ A/QD8QH0AfcEAAH3Af8B7wH0BO8B9AH3AfQB9wQAAfcD/wX0AfMB9AH3AwABswHcCdsB3AGzAbsDAAH3
+ Af8BBwG8BAcBvAEHAfQB9wQAAfcB/wHxAbwB8AL0AbwBBwG8AfQB9wQAAfcB/wFvAfQGvAH0AfcDAAG0
+ B7MB3AHbAdwBswG7BAAB9wH/BPEB9ALzAfEB9AH3BAAB9wH/BfQC8wHxAfQB9wQAAfcB/wX0AvMB8QH0
+ AfcKAAG0AtwBtAG7BQAB9wH/AgcBvAEHAvMC8QH0AfcEAAH3Af8E9ALzAvEB9AH3BAAB9wH/AU8B9AEH
+ AbwC8wLxAfQB9woAAbQB3AG0AbsGAAH3Af8D9ALzAfED9wHsBAAB9wH/A/QC8wHxA/cB7AQAAfcB/wP0
+ AvMB8QP3AewKAAK0AbsHAAH3Af8C9ALzAvEB7wH/AfcBBwQAAfcB/wL0AvMC8QHvAf8B9wEHBAAB9wH/
+ AvQC8wLxAe8B/wH3AQcKAAG6AbsIAAHvAv8F9AEHAe8BBwUAAe8C/wX0AQcB7wEHBQAB7wL/BfQBBwHv
+ AQcVAAnvAQcGAAnvAQcGAAnvAQcEAAFCAU0BPgcAAT4DAAEoAwABQAMAAeADAAEBAQABAQYAAQcWAAP/
+ gQAC/wH4B/8B+AF/Bv8B+AE/BP8BgAEDAfwBHwb/Af4BDwb/AcMBBwT/AYQBQwGBAYMC4AIHAv8BAAGB
+ ASAB4AEHAQQC/wIAASACAAEEAYABAwEAARABIAHgAQcBBAL/AQABHALgAgcC/wGAAT8E/wGAAQMBwAf/
+ AeEH/wHjB/8B4wf/AfgH/wH4AX8E/wGPAf8B+AE/Av8BwAEDAYgBBwH8AR8BgAEDAYABAQHfAf8B/gEP
+ AYABAwGAAQEB3wL/AQcBgAEDAYABAQHYAQEB4AEDAv8BgAEBAd8B/wHgAQEC/wEAAQEB3wH/AeABAAGA
+ AQMBAAEBAdgBBwHgAQABgAEDAQABAQHfAf8BAQEEAv8BgAEBAd8B/wEAAQcC/wGAAQEBiAEBAQABBwGA
+ AQMBgAEBAY8B/wEAAQcC/wHAAQMC/wGAAQcC/wH4A/8BwAEPDf8B8QH/AfEB/gEPA/8B8QH/AfEB/gEP
+ AucB/wHxAf8B4QH+AQ8B4AEHAf8B8wH/AccBAAEBAucB/wHzAf8BjwEAAQED/wHjAf8BHwEAAQEB8QEP
+ AfwBBwH+AT8BAAEBAfkBnwHAAQcB/AF/AQABAQH4AR8BwAF/AfgB/wEAAQEB+AEfAY8B/wHxAf8BAAEB
+ AfwBPwGfAf8B4wH/AQABAQH8AT8BnwH/AccB/wHgAf8B/AE/AR8B/wEPAf8B4AH/Af4BfwEfAf8BHwH/
+ AeAD/wEfAf8BHwf/AcABAwb/AcABAwEfAfgBgAEBAv8BwAEDAgABgAEBAeABBwHAAQMCAAGAAQEB4AEH
+ AcABAwGAAQEBgAEBAeABBwHAAQMBgAEBAYABAQHwAQ8BwAEDAYABAQGDAcEB+AEPAcABAwGAAQEBgwHB
+ AfgBDwHAAQMBgAEBAYMBwQHAAQMBwAEDAYABAQGDAcEBwAEBAcABAwGAAQEBgAEBAcABAQHAAQMBgAEB
+ AYABAQHAAQEBwAEDAgABgAEBAcABAQHAAQMCAAGAAQEBwAEBAcABBwEfAfgBgAEBAv8BwAEPBP8B8AP/
+ Ae8B/QH+AX8B4AF/Av8BgwHgAfgBDwHAAT0BgAEDAoAB8AEDAYABHAGAAQMBwAEBAeABAQEAAQwB+AE/
+ AfABBwHgAQEBAAEEAfwBfwH8AQ8B+AEgAgAB/AF/AfgBDwH4AXACAAH8AX8B8AEHAfgBcAGAAQAB/AF/
+ AfABhwH4AXABwAEBAfwBfwHAAQEB+AFgAeABBwHsAU8BgAEAAfgBYQHwAQ8B7AFPAYABAAHIAWEB+AEf
+ AeABDwGAAQEBwAEHAfgBPwL/AfwBPwHAAQcB+wF/Av8B/gF/Av8B+AF/DP8B/gF/Av8BgwP/AfgBDwHg
+ AQ8BAQP/AfABAwHgAQMBAAP/AeABAQHgAQEBAAF/Av8B4AEBAeACAAE/Af8B5wH8ASAB4AGAAcABHwEQ
+ AQEBEAMAAeABDwExAZEBMQGQAgAB8AEHAYEBkQGBAZACAAH4AQMBgQGRAYEBgAIAAfwBAAHDAYEBwwGB
+ AgAB/gEAAcMBgwHDAYEBgAEAAf8BAAHHAZ8BxwGfAcABAQH/AYAB5wEfAecBHwHwAQMB/wHBDP8B/gF/
+ Af4BfwL/AgAB+AF/AfgBfwL/AgAB8AEfAfABHwHgAQ8CAAHwAQcB8AEHAeABAwL/AfgBBwH4AQcB4AEB
+ AccB/wGAAUMB4AHDAeABAAHDAf8BgAFjAeAB4wHgAYABwQH/AYABIQHxAeECAAHgAf8BwAExAvECAAHw
+ AX8BwAEAAfEBwAIAAfgBPwHgAQEB8QHhAgAB/AEfAeABEQLxAgAB/gEPAeABAwGxATMBgAEAAf8BBwHw
+ AQ8BgAE/AcABAQH/AYcB8AEPAYABPwHwAQMB/wHjB/8B8wHAAQMBwAEDAcABAwL/AcABAwHAAQMBwAED
+ AQABAQHAAQMBwAEDAcABAwEAAQEBwAEDAcABAwHAAQMBAAEBAcABAwHAAQMBwAEDAQABAQHAAQMBwAED
+ AcABAwEAAQEBwAEDAcABAwHAAQMBAAEBAcABAwHAAQMBwAEDAQABAQHAAQMBwAEDAcABAwEAAQEBwAED
+ AcABAwHAAQMBAAEBAcABAwHAAQMBwAEDAQABAQHAAQMBwAEDAcABAwEAAQEBwAEDAcABAwHAAQMBAAEB
+ AcABAwHAAQMBwAEDAQABAQHAAQcBwAEHAcABAwEAAQEBwAEPAcABDwHAAQMBAAEBAcABAwHAAQME/wHA
+ AQMBwAEDAfABDwHwAR8BwAEDAcABAwHgAQcB8AEfAcABAwHAAQMBwAEDAfABHwHAAQMBwAEDAYABAQGA
+ AQABwAEDAcABAwGAAQEBgAIAAQMBwAEDAYABAQGAAgABAwHAAQMBgAEBAfgBBwEAAQMBwAEDAYABAQGA
+ AQABwAEDAcABAwGAAQEBgAEAAcABAwHAAQMBgAEBAYABAAHAAQMBwAEDAYABAQGAAQABwAEDAcABAwHA
+ AQMBgAEAAcABAwHAAQMB4AEHAYABAAHAAQcBwAEHAfABDwH8AT8BwAEPAcABDwT/Af4BPwL/AcABAwL/
+ AYABAQEAAQEBwAEDAv8BgAEBAQABAQHAAQMC/wGAAQEBAAEBAcABAwL/AYABAQEAAQEBwAEDAfwBfwGA
+ AQEBAAEBAcABAwGIAT8BgAIAAQEBwAEDAYABBwGAAgABAQHAAQMBgAEDAYACAAEBAcABAwHAAQMBgAEB
+ AQABAQHAAQMBwAEDAYABAQEAAQEBwAEDAcABAwGAAQEBAAEBAcABAwHAAQcBgAEBAQABAQHAAQMC/wGA
+ AQEBAAEBAcABBwL/AYABAwEAAQEBwAEPAv8BgAEHAgEB8AX/AcABAwL/AcABAwL/AcABAQIAAcABAwL/
+ AcADAAHAAQMB4AEHAcADAAHAAQMB4AEHAcADAAHAAQMB4AEHAcABAQMAAQMB4AEHAcABAwMAAQMB4AEH
+ AcABAwMAAQMB4AEHAcABAwMAAQMB4AEHAcABAwMAAQMB4AEHAcABAwMAAQMB4AEHAcABAwMAAQMB4AEH
+ AcABAwMAAQMC/wHAAQMDAAEDAv8BwAEHAgABwAEHAv8BwAEPAQQBAAHAAQ8BwAEDAcABAwHAAQMBwAED
+ AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAED
+ AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAED
+ AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQMBwAED
+ AcABAwHAAQMBwAEDAcABAwHAAQMBwAEDAcABAwHAAQcBwAEHAcABBwHAAQcBwAEPAcABDwHAAQ8BwAEP
+ Av8BwAEDAcABAwHAAQMC/wHAAQMBwAEDAcABAwH/AT8BwAEDAcABAwHAAQMB/wEfAcABAwHAAQMBwAED
+ Af8BDwHAAQMBwAEDAcABAwH/AQcBwAEDAcABAwHAAQMBgAEDAcABAwHAAQMBwAEDAYABAQHAAQMBwAED
+ AcABAwGAAQEBwAEDAcABAwHAAQMBgAEBAcABAwHAAQMBwAEDAYABAwHAAQMBwAEDAcABAwH/AQcBwAED
+ AcABAwHAAQMB/wEPAcABAwHAAQMBwAEDAf8BHwHAAQMBwAEDAcABAwH/AT8BwAEHAcABBwHAAQcC/wHA
+ AQ8BwAEPAcABDws=
+
+
+
+ 257, 17
+
+
+ 393, 17
+
+
+ 158, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.Designer.cs b/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..1952868097516fc9d63308ad3652c67f0cf475eb
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.Designer.cs
@@ -0,0 +1,240 @@
+namespace PDFPatcher.Functions
+{
+ partial class DocumentFontListForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.label1 = new System.Windows.Forms.Label();
+ this._PageRangeBox = new System.Windows.Forms.TextBox();
+ this._FontListBox = new BrightIdeasSoftware.FastObjectListView();
+ this._NameColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._EmbeddedColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._FirstPageColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ReferenceColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._Worker = new System.ComponentModel.BackgroundWorker();
+ this._ProgressBar = new System.Windows.Forms.ProgressBar();
+ this._AddSelectedFontsButton = new System.Windows.Forms.Button();
+ this._SelectAllButton = new System.Windows.Forms.Button();
+ this._ListFontsButton = new System.Windows.Forms.Button();
+ this._SourceFileBox = new PDFPatcher.SourceFileControl();
+ this._AppConfigButton = new System.Windows.Forms.Button();
+ ((System.ComponentModel.ISupportInitialize)(this._FontListBox)).BeginInit();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(23, 61);
+ this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(82, 15);
+ this.label1.TabIndex = 1;
+ this.label1.Text = "页码范围:";
+ //
+ // _PageRangeBox
+ //
+ this._PageRangeBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PageRangeBox.Location = new System.Drawing.Point(146, 55);
+ this._PageRangeBox.Margin = new System.Windows.Forms.Padding(4);
+ this._PageRangeBox.Name = "_PageRangeBox";
+ this._PageRangeBox.Size = new System.Drawing.Size(470, 25);
+ this._PageRangeBox.TabIndex = 2;
+ //
+ // _FontListBox
+ //
+ this._FontListBox.AllColumns.Add(this._NameColumn);
+ this._FontListBox.AllColumns.Add(this._EmbeddedColumn);
+ this._FontListBox.AllColumns.Add(this._FirstPageColumn);
+ this._FontListBox.AllColumns.Add(this._ReferenceColumn);
+ this._FontListBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._FontListBox.CheckBoxes = true;
+ this._FontListBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._NameColumn,
+ this._EmbeddedColumn,
+ this._FirstPageColumn,
+ this._ReferenceColumn});
+ this._FontListBox.GridLines = true;
+ this._FontListBox.Location = new System.Drawing.Point(24, 128);
+ this._FontListBox.Margin = new System.Windows.Forms.Padding(4);
+ this._FontListBox.MultiSelect = false;
+ this._FontListBox.Name = "_FontListBox";
+ this._FontListBox.OwnerDraw = true;
+ this._FontListBox.ShowGroups = false;
+ this._FontListBox.ShowImagesOnSubItems = true;
+ this._FontListBox.Size = new System.Drawing.Size(699, 309);
+ this._FontListBox.TabIndex = 8;
+ this._FontListBox.UseCompatibleStateImageBehavior = false;
+ this._FontListBox.View = System.Windows.Forms.View.Details;
+ this._FontListBox.VirtualMode = true;
+ //
+ // _NameColumn
+ //
+ this._NameColumn.AspectName = "";
+ this._NameColumn.Text = "字体名称";
+ this._NameColumn.Width = 273;
+ //
+ // _EmbeddedColumn
+ //
+ this._EmbeddedColumn.AspectName = "";
+ this._EmbeddedColumn.CheckBoxes = true;
+ this._EmbeddedColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._EmbeddedColumn.IsEditable = false;
+ this._EmbeddedColumn.Text = "已嵌入";
+ this._EmbeddedColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ //
+ // _FirstPageColumn
+ //
+ this._FirstPageColumn.AspectName = "";
+ this._FirstPageColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._FirstPageColumn.Text = "首次出现页码";
+ this._FirstPageColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._FirstPageColumn.Width = 96;
+ //
+ // _ReferenceColumn
+ //
+ this._ReferenceColumn.AspectName = "";
+ this._ReferenceColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._ReferenceColumn.Text = "出现页数";
+ this._ReferenceColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ //
+ // _Worker
+ //
+ this._Worker.WorkerReportsProgress = true;
+ this._Worker.WorkerSupportsCancellation = true;
+ //
+ // _ProgressBar
+ //
+ this._ProgressBar.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._ProgressBar.Location = new System.Drawing.Point(24, 446);
+ this._ProgressBar.Margin = new System.Windows.Forms.Padding(4);
+ this._ProgressBar.Name = "_ProgressBar";
+ this._ProgressBar.Size = new System.Drawing.Size(700, 29);
+ this._ProgressBar.TabIndex = 9;
+ //
+ // _AddSelectedFontsButton
+ //
+ this._AddSelectedFontsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._AddSelectedFontsButton.Location = new System.Drawing.Point(516, 91);
+ this._AddSelectedFontsButton.Margin = new System.Windows.Forms.Padding(4);
+ this._AddSelectedFontsButton.Name = "_AddSelectedFontsButton";
+ this._AddSelectedFontsButton.Size = new System.Drawing.Size(208, 29);
+ this._AddSelectedFontsButton.TabIndex = 7;
+ this._AddSelectedFontsButton.Text = "添加选中项至替换列表";
+ this._AddSelectedFontsButton.UseVisualStyleBackColor = true;
+ this._AddSelectedFontsButton.Click += new System.EventHandler(this._AddSelectedFontsButton_Click);
+ //
+ // _SelectAllButton
+ //
+ this._SelectAllButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._SelectAllButton.Location = new System.Drawing.Point(381, 91);
+ this._SelectAllButton.Margin = new System.Windows.Forms.Padding(4);
+ this._SelectAllButton.Name = "_SelectAllButton";
+ this._SelectAllButton.Size = new System.Drawing.Size(127, 29);
+ this._SelectAllButton.TabIndex = 6;
+ this._SelectAllButton.Text = "全部选中(&Q)";
+ this._SelectAllButton.UseVisualStyleBackColor = true;
+ this._SelectAllButton.Click += new System.EventHandler(this._SelectAllButton_Click);
+ //
+ // _ListFontsButton
+ //
+ this._ListFontsButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._ListFontsButton.Location = new System.Drawing.Point(624, 55);
+ this._ListFontsButton.Margin = new System.Windows.Forms.Padding(4);
+ this._ListFontsButton.Name = "_ListFontsButton";
+ this._ListFontsButton.Size = new System.Drawing.Size(100, 29);
+ this._ListFontsButton.TabIndex = 3;
+ this._ListFontsButton.Text = "列出字体";
+ this._ListFontsButton.UseVisualStyleBackColor = true;
+ this._ListFontsButton.Click += new System.EventHandler(this._ListFontsButton_Click);
+ //
+ // _SourceFileBox
+ //
+ this._SourceFileBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._SourceFileBox.Location = new System.Drawing.Point(16, 15);
+ this._SourceFileBox.Margin = new System.Windows.Forms.Padding(5);
+ this._SourceFileBox.Name = "_SourceFileBox";
+ this._SourceFileBox.Size = new System.Drawing.Size(712, 32);
+ this._SourceFileBox.TabIndex = 0;
+ //
+ // _AppConfigButton
+ //
+ this._AppConfigButton.Location = new System.Drawing.Point(26, 91);
+ this._AppConfigButton.Name = "_AppConfigButton";
+ this._AppConfigButton.Size = new System.Drawing.Size(127, 29);
+ this._AppConfigButton.TabIndex = 10;
+ this._AppConfigButton.Text = "程序配置...";
+ this._AppConfigButton.UseVisualStyleBackColor = true;
+ this._AppConfigButton.Click += new System.EventHandler(this._AppConfigButton_Click);
+ //
+ // DocumentFontListForm
+ //
+ this.AcceptButton = this._ListFontsButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(744, 490);
+ this.Controls.Add(this._AppConfigButton);
+ this.Controls.Add(this._SelectAllButton);
+ this.Controls.Add(this._AddSelectedFontsButton);
+ this.Controls.Add(this._ProgressBar);
+ this.Controls.Add(this._FontListBox);
+ this.Controls.Add(this._ListFontsButton);
+ this.Controls.Add(this._PageRangeBox);
+ this.Controls.Add(this.label1);
+ this.Controls.Add(this._SourceFileBox);
+ this.Margin = new System.Windows.Forms.Padding(4);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "DocumentFontListForm";
+ this.ShowInTaskbar = false;
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.Text = "PDF 文档使用的字体列表";
+ ((System.ComponentModel.ISupportInitialize)(this._FontListBox)).EndInit();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private SourceFileControl _SourceFileBox;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.TextBox _PageRangeBox;
+ private System.Windows.Forms.Button _ListFontsButton;
+ private BrightIdeasSoftware.FastObjectListView _FontListBox;
+ private BrightIdeasSoftware.OLVColumn _NameColumn;
+ private BrightIdeasSoftware.OLVColumn _FirstPageColumn;
+ private BrightIdeasSoftware.OLVColumn _EmbeddedColumn;
+ private System.ComponentModel.BackgroundWorker _Worker;
+ private System.Windows.Forms.ProgressBar _ProgressBar;
+ private BrightIdeasSoftware.OLVColumn _ReferenceColumn;
+ private System.Windows.Forms.Button _AddSelectedFontsButton;
+ private System.Windows.Forms.Button _SelectAllButton;
+ private System.Windows.Forms.Button _AppConfigButton;
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.cs b/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5a6d509cab2a479bb7aa15cf3380d11ebc06fff7
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.cs
@@ -0,0 +1,192 @@
+using System;
+using System.Collections.Generic;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+using iTextSharp.text.pdf;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+using PDFPatcher.Processor;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class DocumentFontListForm : Form
+ {
+ Dictionary _fontIdNames;
+ Dictionary _pageFonts;
+ internal FontSubstitutionsEditor SubstitutionsEditor { get; set; }
+
+ public IList SelectedFonts {
+ get {
+ var sf = new List();
+ foreach (PageFont item in _FontListBox.CheckedObjects) {
+ sf.Add(item.Name);
+ }
+ return sf;
+ }
+ }
+
+ public DocumentFontListForm() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ }
+
+ void OnLoad() {
+ this.SetIcon(Properties.Resources.Fonts);
+ MinimumSize = Size;
+ if (AppContext.Recent.SourcePdfFiles.HasContent()) {
+ _SourceFileBox.FileList.Text = AppContext.Recent.SourcePdfFiles[0];
+ }
+ _Worker.ProgressChanged += (s, args) => {
+ if (args.ProgressPercentage < 0) {
+ _ProgressBar.Maximum = -args.ProgressPercentage;
+ }
+ else if (args.ProgressPercentage > 0) {
+ _ProgressBar.SetValue(args.ProgressPercentage);
+ }
+ else {
+ if (args.UserState is PageFont pf) {
+ _FontListBox.AddObject(pf);
+ }
+ }
+ };
+ _Worker.RunWorkerCompleted += (s, args) => {
+ _ProgressBar.Value = _ProgressBar.Maximum;
+ if (_pageFonts.HasContent()) {
+ _FontListBox.AddObjects(_pageFonts.Values);
+ }
+ _ListFontsButton.Enabled = true;
+ };
+ _Worker.DoWork += (s, args) => {
+ try {
+ _fontIdNames = new Dictionary();
+ _pageFonts = new Dictionary();
+ _FontListBox.ClearObjects();
+ using (var p = PdfHelper.OpenPdfFile(_SourceFileBox.FirstFile, false, false)) {
+ var r = PageRangeCollection.Parse(_PageRangeBox.Text, 1, p.NumberOfPages, true);
+ var pp = new int[p.NumberOfPages + 1];
+ _Worker.ReportProgress(-r.TotalPages);
+ int i = 0;
+ foreach (var range in r) {
+ foreach (var page in range) {
+ if (_Worker.CancellationPending) {
+ return;
+ }
+ _Worker.ReportProgress(++i);
+ if (pp[page] != 0) {
+ continue;
+ }
+ pp[page] = 1;
+ GetPageFonts(p, page);
+ }
+ }
+ }
+ }
+ catch (Exception ex) {
+ FormHelper.ErrorBox(ex.Message);
+ }
+ };
+ _FontListBox.ScaleColumnWidths();
+ _FontListBox.PersistentCheckBoxes = true;
+ new TypedColumn(_NameColumn) {
+ AspectGetter = (o) => o.Name
+ };
+ new TypedColumn(_FirstPageColumn) {
+ AspectGetter = (o) => o.FirstPage
+ };
+ new TypedColumn(_EmbeddedColumn) {
+ AspectGetter = (o) => o.Embedded
+ };
+ new TypedColumn(_ReferenceColumn) {
+ AspectGetter = (o) => o.Reference
+ };
+ }
+
+ private void GetPageFonts(PdfReader pdf, int pageNumber) {
+ var page = pdf.GetPageNRelease(pageNumber);
+ var fl = page.Locate(true, PdfName.RESOURCES, PdfName.FONT);
+ if (fl == null) {
+ return;
+ }
+ foreach (var item in fl) {
+ var fr = item.Value as PdfIndirectReference;
+ if (fr == null) {
+ continue;
+ }
+ if (_fontIdNames.TryGetValue(fr.Number, out string fn)) {
+ _pageFonts[fn].IncrementReference();
+ continue;
+ }
+ if (PdfReader.GetPdfObjectRelease(fr) is PdfDictionary f) {
+ var bf = f.GetAsName(PdfName.BASEFONT);
+ if (bf == null) {
+ continue;
+ }
+ fn = PdfHelper.GetPdfNameString(bf, AppContext.Encodings.FontNameEncoding); // 字体名称
+ fn = PdfDocumentFont.RemoveSubsetPrefix(fn);
+ _fontIdNames.Add(fr.Number, fn);
+ if (_pageFonts.TryGetValue(fn, out PageFont pf)) {
+ pf.IncrementReference();
+ continue;
+ }
+ _pageFonts.Add(fn, new PageFont(fn, pageNumber, PdfDocumentFont.HasEmbeddedFont(f)));
+ }
+ }
+ }
+
+ private void SetGoal(int goal) { _ProgressBar.Maximum = goal; }
+ private void _ListFontsButton_Click(object sender, EventArgs e) {
+ _ProgressBar.Value = 0;
+ _ListFontsButton.Enabled = false;
+ _Worker.RunWorkerAsync();
+ }
+
+ sealed class PageFont
+ {
+ public string Name { get; }
+ public int FirstPage { get; }
+ public int Reference { get; private set; }
+ public bool Embedded { get; set; }
+
+ public PageFont(string name, int firstPage, bool embedded) {
+ Name = name;
+ FirstPage = firstPage;
+ Embedded = embedded;
+ Reference = 1;
+ }
+
+ public void IncrementReference() {
+ Reference++;
+ }
+ }
+
+ private void _SelectAllButton_Click(object sender, EventArgs e) {
+ if (_FontListBox.GetItemCount() == 0) {
+ return;
+ }
+ if (_FontListBox.GetItem(0).Checked == false) {
+ _FontListBox.CheckObjects(_FontListBox.Objects);
+ }
+ else {
+ _FontListBox.CheckedObjects = null;
+ }
+ _FontListBox.Focus();
+ }
+
+ private void _AddSelectedFontsButton_Click(object sender, EventArgs e) {
+ if (SubstitutionsEditor == null) {
+ return;
+ }
+ var sf = SelectedFonts;
+ if (sf.Count == 0) {
+ FormHelper.ErrorBox("请选择需要添加到替换列表的字体。");
+ return;
+ }
+ SubstitutionsEditor.AddFonts(sf);
+ Close();
+ }
+
+ private void _AppConfigButton_Click(object sender, EventArgs e) {
+ this.ShowDialog();
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.resx b/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..4e4521e8220dd27d1a08482879141165ba84fa20
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/DocumentFontListForm.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.Designer.cs b/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6c5e9d56a47cb9bf26e2a27d71c394ccbd0cf15c
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.Designer.cs
@@ -0,0 +1,221 @@
+namespace PDFPatcher.Functions
+{
+ partial class DocumentInfoEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container ();
+ this.groupBox4 = new System.Windows.Forms.GroupBox ();
+ this._MetadataPanel = new System.Windows.Forms.Panel ();
+ this.label16 = new System.Windows.Forms.Label ();
+ this._KeywordsBox = new System.Windows.Forms.TextBox ();
+ this.label17 = new System.Windows.Forms.Label ();
+ this._SubjectBox = new System.Windows.Forms.TextBox ();
+ this.label18 = new System.Windows.Forms.Label ();
+ this._AuthorBox = new System.Windows.Forms.TextBox ();
+ this.label19 = new System.Windows.Forms.Label ();
+ this._TitleBox = new System.Windows.Forms.TextBox ();
+ this._ForceMetadataBox = new System.Windows.Forms.CheckBox ();
+ this.label5 = new System.Windows.Forms.Label ();
+ this._RewriteXmpBox = new System.Windows.Forms.CheckBox ();
+ this._PropertyMacroMenu = new PDFPatcher.Functions.MacroMenu (this.components);
+ this.groupBox4.SuspendLayout ();
+ this._MetadataPanel.SuspendLayout ();
+ this.SuspendLayout ();
+ //
+ // groupBox4
+ //
+ this.groupBox4.Controls.Add (this._MetadataPanel);
+ this.groupBox4.Controls.Add (this._ForceMetadataBox);
+ this.groupBox4.Location = new System.Drawing.Point (6, 23);
+ this.groupBox4.Name = "groupBox4";
+ this.groupBox4.Size = new System.Drawing.Size (426, 232);
+ this.groupBox4.TabIndex = 2;
+ this.groupBox4.TabStop = false;
+ this.groupBox4.Text = "文档信息";
+ //
+ // _MetadataPanel
+ //
+ this._MetadataPanel.Controls.Add (this._RewriteXmpBox);
+ this._MetadataPanel.Controls.Add (this.label16);
+ this._MetadataPanel.Controls.Add (this._KeywordsBox);
+ this._MetadataPanel.Controls.Add (this.label17);
+ this._MetadataPanel.Controls.Add (this._SubjectBox);
+ this._MetadataPanel.Controls.Add (this.label18);
+ this._MetadataPanel.Controls.Add (this._AuthorBox);
+ this._MetadataPanel.Controls.Add (this.label19);
+ this._MetadataPanel.Controls.Add (this._TitleBox);
+ this._MetadataPanel.Enabled = false;
+ this._MetadataPanel.Location = new System.Drawing.Point (6, 41);
+ this._MetadataPanel.Name = "_MetadataPanel";
+ this._MetadataPanel.Size = new System.Drawing.Size (414, 185);
+ this._MetadataPanel.TabIndex = 1;
+ //
+ // label16
+ //
+ this.label16.AutoSize = true;
+ this.label16.Location = new System.Drawing.Point (3, 0);
+ this.label16.Name = "label16";
+ this.label16.Size = new System.Drawing.Size (41, 12);
+ this.label16.TabIndex = 0;
+ this.label16.Text = "标题:";
+ //
+ // _KeywordsBox
+ //
+ this._KeywordsBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._KeywordsBox.Location = new System.Drawing.Point (5, 133);
+ this._KeywordsBox.Name = "_KeywordsBox";
+ this._KeywordsBox.Size = new System.Drawing.Size (406, 21);
+ this._KeywordsBox.TabIndex = 7;
+ this._KeywordsBox.TextChanged += new System.EventHandler (this.DocumentInfoChanged);
+ //
+ // label17
+ //
+ this.label17.AutoSize = true;
+ this.label17.Location = new System.Drawing.Point (3, 40);
+ this.label17.Name = "label17";
+ this.label17.Size = new System.Drawing.Size (41, 12);
+ this.label17.TabIndex = 2;
+ this.label17.Text = "作者:";
+ //
+ // _SubjectBox
+ //
+ this._SubjectBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._SubjectBox.Location = new System.Drawing.Point (5, 94);
+ this._SubjectBox.Name = "_SubjectBox";
+ this._SubjectBox.Size = new System.Drawing.Size (406, 21);
+ this._SubjectBox.TabIndex = 5;
+ this._SubjectBox.TextChanged += new System.EventHandler (this.DocumentInfoChanged);
+ //
+ // label18
+ //
+ this.label18.AutoSize = true;
+ this.label18.Location = new System.Drawing.Point (3, 79);
+ this.label18.Name = "label18";
+ this.label18.Size = new System.Drawing.Size (41, 12);
+ this.label18.TabIndex = 4;
+ this.label18.Text = "主题:";
+ //
+ // _AuthorBox
+ //
+ this._AuthorBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._AuthorBox.Location = new System.Drawing.Point (5, 55);
+ this._AuthorBox.Name = "_AuthorBox";
+ this._AuthorBox.Size = new System.Drawing.Size (406, 21);
+ this._AuthorBox.TabIndex = 3;
+ this._AuthorBox.TextChanged += new System.EventHandler (this.DocumentInfoChanged);
+ //
+ // label19
+ //
+ this.label19.AutoSize = true;
+ this.label19.Location = new System.Drawing.Point (3, 118);
+ this.label19.Name = "label19";
+ this.label19.Size = new System.Drawing.Size (53, 12);
+ this.label19.TabIndex = 6;
+ this.label19.Text = "关键词:";
+ //
+ // _TitleBox
+ //
+ this._TitleBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._TitleBox.Location = new System.Drawing.Point (5, 15);
+ this._TitleBox.Name = "_TitleBox";
+ this._TitleBox.Size = new System.Drawing.Size (406, 21);
+ this._TitleBox.TabIndex = 1;
+ this._TitleBox.TextChanged += new System.EventHandler (this.DocumentInfoChanged);
+ //
+ // _ForceMetadataBox
+ //
+ this._ForceMetadataBox.AutoSize = true;
+ this._ForceMetadataBox.Location = new System.Drawing.Point (8, 20);
+ this._ForceMetadataBox.Name = "_ForceMetadataBox";
+ this._ForceMetadataBox.Size = new System.Drawing.Size (180, 16);
+ this._ForceMetadataBox.TabIndex = 0;
+ this._ForceMetadataBox.Text = "使用此处设定的文档属性信息";
+ this._ForceMetadataBox.UseVisualStyleBackColor = true;
+ this._ForceMetadataBox.CheckedChanged += new System.EventHandler (this.DocumentInfoChanged);
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point (6, 8);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size (221, 12);
+ this.label5.TabIndex = 0;
+ this.label5.Text = "说明:以下设定优先于信息文件的内容。";
+ //
+ // _RewriteXmpBox
+ //
+ this._RewriteXmpBox.AutoSize = true;
+ this._RewriteXmpBox.Location = new System.Drawing.Point (5, 160);
+ this._RewriteXmpBox.Name = "_RewriteXmpBox";
+ this._RewriteXmpBox.Size = new System.Drawing.Size (198, 16);
+ this._RewriteXmpBox.TabIndex = 8;
+ this._RewriteXmpBox.Text = "重写扩展标记(XML)元数据属性";
+ this._RewriteXmpBox.UseVisualStyleBackColor = true;
+ this._RewriteXmpBox.CheckedChanged += new System.EventHandler (this.DocumentInfoChanged);
+ //
+ // _PropertyMacroMenu
+ //
+ this._PropertyMacroMenu.Name = "_PropertyMacroMenu";
+ this._PropertyMacroMenu.Size = new System.Drawing.Size (61, 4);
+ //
+ // DocumentInfoEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add (this.groupBox4);
+ this.Controls.Add (this.label5);
+ this.Name = "DocumentInfoEditor";
+ this.Size = new System.Drawing.Size (438, 270);
+ this.groupBox4.ResumeLayout (false);
+ this.groupBox4.PerformLayout ();
+ this._MetadataPanel.ResumeLayout (false);
+ this._MetadataPanel.PerformLayout ();
+ this.ResumeLayout (false);
+ this.PerformLayout ();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.GroupBox groupBox4;
+ private System.Windows.Forms.Panel _MetadataPanel;
+ private System.Windows.Forms.Label label16;
+ private System.Windows.Forms.TextBox _KeywordsBox;
+ private System.Windows.Forms.Label label17;
+ private System.Windows.Forms.TextBox _SubjectBox;
+ private System.Windows.Forms.Label label18;
+ private System.Windows.Forms.TextBox _AuthorBox;
+ private System.Windows.Forms.Label label19;
+ private System.Windows.Forms.TextBox _TitleBox;
+ private System.Windows.Forms.CheckBox _ForceMetadataBox;
+ private System.Windows.Forms.Label label5;
+ private Functions.MacroMenu _PropertyMacroMenu;
+ private System.Windows.Forms.CheckBox _RewriteXmpBox;
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.cs b/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..a87527f5a99220fdd59368f9a5342e84ad513445
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Windows.Forms;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class DocumentInfoEditor : UserControl
+ {
+ bool _settingsLockdown;
+ GeneralInfo _Options;
+ internal GeneralInfo Options {
+ get => _Options;
+ set {
+ _Options = value;
+ _settingsLockdown = true;
+ _AuthorBox.Text = _Options.Author;
+ _MetadataPanel.Enabled = _ForceMetadataBox.Checked = _Options.SpecifyMetaData;
+ _KeywordsBox.Text = _Options.Keywords;
+ _SubjectBox.Text = _Options.Subject;
+ _TitleBox.Text = _Options.Title;
+ _RewriteXmpBox.Checked = _Options.RewriteXmp;
+ _settingsLockdown = false;
+ }
+ }
+
+ public DocumentInfoEditor() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ }
+
+ void OnLoad() {
+ _settingsLockdown = true;
+ _TitleBox.ContextMenuStrip = _SubjectBox.ContextMenuStrip = _AuthorBox.ContextMenuStrip = _KeywordsBox.ContextMenuStrip = _PropertyMacroMenu;
+ _PropertyMacroMenu.AddInsertMacroMenuItem(Constants.FileNameMacros.FileName);
+ _PropertyMacroMenu.AddInsertMacroMenuItem(Constants.FileNameMacros.FolderName);
+ _PropertyMacroMenu.ItemClicked += _PropertyMacroMenu.ProcessInsertMacroCommand;
+ _settingsLockdown = false;
+ }
+
+ void DocumentInfoChanged(object sender, EventArgs e) {
+ if (_settingsLockdown) {
+ return;
+ }
+
+ if (sender == _AuthorBox) {
+ Options.Author = _AuthorBox.Text;
+ }
+ else if (sender == _ForceMetadataBox) {
+ _MetadataPanel.Enabled = Options.SpecifyMetaData = _ForceMetadataBox.Checked;
+ }
+ else if (sender == _KeywordsBox) {
+ Options.Keywords = _KeywordsBox.Text;
+ }
+ else if (sender == _SubjectBox) {
+ Options.Subject = _SubjectBox.Text;
+ }
+ else if (sender == _TitleBox) {
+ Options.Title = _TitleBox.Text;
+ }
+ else if (sender == _RewriteXmpBox) {
+ Options.RewriteXmp = _RewriteXmpBox.Checked;
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.resx b/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..bd78db42795653f4341c5e07d08821ab40d13c97
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/DocumentInfoEditor.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.Designer.cs b/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..8f9ed74d44fdd39068517b22e944bb7faa9a0e0e
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.Designer.cs
@@ -0,0 +1,227 @@
+namespace PDFPatcher.Functions
+{
+ partial class FontCharSubstitutionForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent () {
+ this.label1 = new System.Windows.Forms.Label();
+ this._OriginalCharactersBox = new System.Windows.Forms.RichTextBox();
+ this.label2 = new System.Windows.Forms.Label();
+ this._SubstituteCharactersBox = new System.Windows.Forms.RichTextBox();
+ this.label3 = new System.Windows.Forms.Label();
+ this._ChineseCaseBox = new System.Windows.Forms.ComboBox();
+ this.label4 = new System.Windows.Forms.Label();
+ this._NumericWidthBox = new System.Windows.Forms.ComboBox();
+ this._LetterWidthBox = new System.Windows.Forms.ComboBox();
+ this.label5 = new System.Windows.Forms.Label();
+ this._PunctuationWidthBox = new System.Windows.Forms.ComboBox();
+ this.label6 = new System.Windows.Forms.Label();
+ this.SuspendLayout();
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point(30, 34);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size(80, 18);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "原字符:";
+ //
+ // _OriginalCharactersBox
+ //
+ this._OriginalCharactersBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._OriginalCharactersBox.HideSelection = false;
+ this._OriginalCharactersBox.Location = new System.Drawing.Point(112, 30);
+ this._OriginalCharactersBox.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this._OriginalCharactersBox.Multiline = false;
+ this._OriginalCharactersBox.Name = "_OriginalCharactersBox";
+ this._OriginalCharactersBox.Size = new System.Drawing.Size(354, 29);
+ this._OriginalCharactersBox.TabIndex = 1;
+ this._OriginalCharactersBox.Text = "";
+ this._OriginalCharactersBox.SelectionChanged += new System.EventHandler(this._OriginalCharactersBox_SelectionChanged);
+ this._OriginalCharactersBox.TextChanged += new System.EventHandler(this._OriginalCharactersBox_TextChanged);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point(14, 91);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size(98, 18);
+ this.label2.TabIndex = 2;
+ this.label2.Text = "替换字符:";
+ //
+ // _SubstituteCharactersBox
+ //
+ this._SubstituteCharactersBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._SubstituteCharactersBox.HideSelection = false;
+ this._SubstituteCharactersBox.Location = new System.Drawing.Point(112, 88);
+ this._SubstituteCharactersBox.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this._SubstituteCharactersBox.Multiline = false;
+ this._SubstituteCharactersBox.Name = "_SubstituteCharactersBox";
+ this._SubstituteCharactersBox.Size = new System.Drawing.Size(354, 29);
+ this._SubstituteCharactersBox.TabIndex = 1;
+ this._SubstituteCharactersBox.Text = "";
+ this._SubstituteCharactersBox.TextChanged += new System.EventHandler(this._SubstituteCharactersBox_TextChanged);
+ this._SubstituteCharactersBox.Enter += new System.EventHandler(this._SubstituteCharactersBox_Enter);
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point(14, 152);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size(134, 18);
+ this.label3.TabIndex = 3;
+ this.label3.Text = "简繁汉字替换:";
+ //
+ // _ChineseCaseBox
+ //
+ this._ChineseCaseBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._ChineseCaseBox.FormattingEnabled = true;
+ this._ChineseCaseBox.Items.AddRange(new object[] {
+ "不改变",
+ "简体转繁体",
+ "繁体转简体"});
+ this._ChineseCaseBox.Location = new System.Drawing.Point(154, 149);
+ this._ChineseCaseBox.Name = "_ChineseCaseBox";
+ this._ChineseCaseBox.Size = new System.Drawing.Size(161, 26);
+ this._ChineseCaseBox.TabIndex = 4;
+ this._ChineseCaseBox.SelectedIndexChanged += new System.EventHandler(this._ChineseCaseBox_SelectedIndexChanged);
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point(50, 184);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size(98, 18);
+ this.label4.TabIndex = 3;
+ this.label4.Text = "数字替换:";
+ //
+ // _NumericWidthBox
+ //
+ this._NumericWidthBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._NumericWidthBox.FormattingEnabled = true;
+ this._NumericWidthBox.Items.AddRange(new object[] {
+ "不改变",
+ "半角转全角",
+ "全角转半角"});
+ this._NumericWidthBox.Location = new System.Drawing.Point(154, 181);
+ this._NumericWidthBox.Name = "_NumericWidthBox";
+ this._NumericWidthBox.Size = new System.Drawing.Size(161, 26);
+ this._NumericWidthBox.TabIndex = 4;
+ this._NumericWidthBox.SelectedIndexChanged += new System.EventHandler(this._NumericWidthBox_SelectedIndexChanged);
+ //
+ // _LetterWidthBox
+ //
+ this._LetterWidthBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._LetterWidthBox.FormattingEnabled = true;
+ this._LetterWidthBox.Items.AddRange(new object[] {
+ "不改变",
+ "半角转全角",
+ "全角转半角"});
+ this._LetterWidthBox.Location = new System.Drawing.Point(154, 213);
+ this._LetterWidthBox.Name = "_LetterWidthBox";
+ this._LetterWidthBox.Size = new System.Drawing.Size(161, 26);
+ this._LetterWidthBox.TabIndex = 4;
+ this._LetterWidthBox.SelectedIndexChanged += new System.EventHandler(this._LetterWidthBox_SelectedIndexChanged);
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point(50, 216);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size(98, 18);
+ this.label5.TabIndex = 3;
+ this.label5.Text = "字母替换:";
+ //
+ // _PunctuationWidthBox
+ //
+ this._PunctuationWidthBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._PunctuationWidthBox.FormattingEnabled = true;
+ this._PunctuationWidthBox.Items.AddRange(new object[] {
+ "不改变",
+ "半角转全角",
+ "全角转半角"});
+ this._PunctuationWidthBox.Location = new System.Drawing.Point(154, 245);
+ this._PunctuationWidthBox.Name = "_PunctuationWidthBox";
+ this._PunctuationWidthBox.Size = new System.Drawing.Size(161, 26);
+ this._PunctuationWidthBox.TabIndex = 4;
+ this._PunctuationWidthBox.SelectedIndexChanged += new System.EventHandler(this._PunctuationWidthBox_SelectedIndexChanged);
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point(50, 248);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size(98, 18);
+ this.label6.TabIndex = 3;
+ this.label6.Text = "标点替换:";
+ //
+ // FontCharSubstitutionForm
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 18F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(480, 288);
+ this.Controls.Add(this._PunctuationWidthBox);
+ this.Controls.Add(this._LetterWidthBox);
+ this.Controls.Add(this._NumericWidthBox);
+ this.Controls.Add(this._ChineseCaseBox);
+ this.Controls.Add(this.label6);
+ this.Controls.Add(this.label5);
+ this.Controls.Add(this.label4);
+ this.Controls.Add(this.label3);
+ this.Controls.Add(this.label2);
+ this.Controls.Add(this._SubstituteCharactersBox);
+ this.Controls.Add(this._OriginalCharactersBox);
+ this.Controls.Add(this.label1);
+ this.Margin = new System.Windows.Forms.Padding(3, 4, 3, 4);
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "FontCharSubstitutionForm";
+ this.ShowInTaskbar = false;
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent;
+ this.Text = "替换字符";
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.RichTextBox _OriginalCharactersBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.RichTextBox _SubstituteCharactersBox;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.ComboBox _ChineseCaseBox;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.ComboBox _NumericWidthBox;
+ private System.Windows.Forms.ComboBox _LetterWidthBox;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.ComboBox _PunctuationWidthBox;
+ private System.Windows.Forms.Label label6;
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.cs b/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..7ee1010e682950788658211155ce4b1759592583
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.cs
@@ -0,0 +1,65 @@
+using System;
+using System.Drawing;
+using System.Windows.Forms;
+using PDFPatcher.Common;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class FontCharSubstitutionForm : Form
+ {
+ readonly FontSubstitution _Substitution;
+ public FontCharSubstitutionForm() {
+ InitializeComponent();
+ }
+ public FontCharSubstitutionForm(FontSubstitution substitution) : this() {
+ this.SetIcon(Properties.Resources.Replace);
+ MinimumSize = Size;
+ MaximumSize = new Size(999, Size.Height);
+ _Substitution = substitution;
+ _OriginalCharactersBox.Text = substitution.OriginalCharacters;
+ _SubstituteCharactersBox.Text = substitution.SubstituteCharacters;
+ _ChineseCaseBox.Select(substitution.TraditionalChineseConversion == -1 ? 2 : substitution.TraditionalChineseConversion);
+ _LetterWidthBox.Select(substitution.AlphabeticWidthConversion == -1 ? 2 : substitution.AlphabeticWidthConversion);
+ _NumericWidthBox.Select(substitution.NumericWidthConversion == -1 ? 2 : substitution.NumericWidthConversion);
+ _PunctuationWidthBox.Select(substitution.PunctuationWidthConversion == -1 ? 2 : substitution.PunctuationWidthConversion);
+ }
+
+ void _OriginalCharactersBox_TextChanged(object sender, EventArgs e) {
+ _Substitution.OriginalCharacters = _OriginalCharactersBox.Text;
+ }
+
+ void _SubstituteCharactersBox_TextChanged(object sender, EventArgs e) {
+ _Substitution.SubstituteCharacters = _SubstituteCharactersBox.Text;
+ }
+
+ void _SubstituteCharactersBox_Enter(object sender, EventArgs e) {
+ _SubstituteCharactersBox.Select(
+ _OriginalCharactersBox.SelectionStart,
+ _OriginalCharactersBox.SelectionLength
+ );
+ }
+
+ void _OriginalCharactersBox_SelectionChanged(object sender, EventArgs e) {
+ _SubstituteCharactersBox.Select(
+ _OriginalCharactersBox.SelectionStart,
+ _OriginalCharactersBox.SelectionLength
+ );
+ }
+
+ void _ChineseCaseBox_SelectedIndexChanged(object sender, EventArgs e) {
+ _Substitution.TraditionalChineseConversion = _ChineseCaseBox.SelectedIndex == 2 ? -1 : _ChineseCaseBox.SelectedIndex;
+ }
+
+ void _NumericWidthBox_SelectedIndexChanged(object sender, EventArgs e) {
+ _Substitution.NumericWidthConversion = _NumericWidthBox.SelectedIndex == 2 ? -1 : _NumericWidthBox.SelectedIndex;
+ }
+
+ void _LetterWidthBox_SelectedIndexChanged(object sender, EventArgs e) {
+ _Substitution.AlphabeticWidthConversion = _LetterWidthBox.SelectedIndex == 2 ? -1 : _LetterWidthBox.SelectedIndex;
+ }
+
+ void _PunctuationWidthBox_SelectedIndexChanged(object sender, EventArgs e) {
+ _Substitution.PunctuationWidthConversion = _PunctuationWidthBox.SelectedIndex == 2 ? -1 : _PunctuationWidthBox.SelectedIndex;
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.resx b/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..1af7de150c99c12dd67a509fe57c10d63e4eeb04
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/FontCharSubstitutionForm.resx
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.Designer.cs b/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5a9f9f0e3a304826abc34ab667987aa91d81b570
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.Designer.cs
@@ -0,0 +1,255 @@
+namespace PDFPatcher.Functions
+{
+ partial class FontSubstitutionsEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container();
+ this._FontSubstitutionsBox = new BrightIdeasSoftware.ObjectListView();
+ this._SequenceColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._OriginalFontColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._SubstitutionColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._CharSubstitutionColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._FontSubstitutionMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this._CopySubstitutionFont = new System.Windows.Forms.ToolStripMenuItem();
+ this._PasteSubstitutionFont = new System.Windows.Forms.ToolStripMenuItem();
+ this._RemovePageLabelButton = new System.Windows.Forms.Button();
+ this._AddPageLabelButton = new System.Windows.Forms.Button();
+ this._ListDocumentFontButton = new System.Windows.Forms.Button();
+ this._EmbedLegacyCjkFontsBox = new System.Windows.Forms.CheckBox();
+ this._EnableFontSubstitutionsBox = new System.Windows.Forms.CheckBox();
+ this.panel1 = new System.Windows.Forms.Panel();
+ this._TrimTrailingWhiteSpaceBox = new System.Windows.Forms.CheckBox();
+ ((System.ComponentModel.ISupportInitialize)(this._FontSubstitutionsBox)).BeginInit();
+ this._FontSubstitutionMenu.SuspendLayout();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _FontSubstitutionsBox
+ //
+ this._FontSubstitutionsBox.AllColumns.Add(this._SequenceColumn);
+ this._FontSubstitutionsBox.AllColumns.Add(this._OriginalFontColumn);
+ this._FontSubstitutionsBox.AllColumns.Add(this._SubstitutionColumn);
+ this._FontSubstitutionsBox.AllColumns.Add(this._CharSubstitutionColumn);
+ this._FontSubstitutionsBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._FontSubstitutionsBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this._FontSubstitutionsBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._SequenceColumn,
+ this._OriginalFontColumn,
+ this._SubstitutionColumn,
+ this._CharSubstitutionColumn});
+ this._FontSubstitutionsBox.ContextMenuStrip = this._FontSubstitutionMenu;
+ this._FontSubstitutionsBox.Cursor = System.Windows.Forms.Cursors.Default;
+ this._FontSubstitutionsBox.Enabled = false;
+ this._FontSubstitutionsBox.GridLines = true;
+ this._FontSubstitutionsBox.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this._FontSubstitutionsBox.HideSelection = false;
+ this._FontSubstitutionsBox.LabelEdit = true;
+ this._FontSubstitutionsBox.Location = new System.Drawing.Point(4, 69);
+ this._FontSubstitutionsBox.Margin = new System.Windows.Forms.Padding(4);
+ this._FontSubstitutionsBox.Name = "_FontSubstitutionsBox";
+ this._FontSubstitutionsBox.SelectColumnsOnRightClick = false;
+ this._FontSubstitutionsBox.SelectColumnsOnRightClickBehaviour = BrightIdeasSoftware.ObjectListView.ColumnSelectBehaviour.None;
+ this._FontSubstitutionsBox.ShowGroups = false;
+ this._FontSubstitutionsBox.Size = new System.Drawing.Size(575, 275);
+ this._FontSubstitutionsBox.TabIndex = 5;
+ this._FontSubstitutionsBox.UseCompatibleStateImageBehavior = false;
+ this._FontSubstitutionsBox.View = System.Windows.Forms.View.Details;
+ //
+ // _SequenceColumn
+ //
+ this._SequenceColumn.Text = "序号";
+ this._SequenceColumn.Width = 40;
+ //
+ // _OriginalFontColumn
+ //
+ this._OriginalFontColumn.AspectName = "";
+ this._OriginalFontColumn.Text = "原字体";
+ this._OriginalFontColumn.Width = 160;
+ //
+ // _SubstitutionColumn
+ //
+ this._SubstitutionColumn.AspectName = "";
+ this._SubstitutionColumn.Text = "替换字体";
+ this._SubstitutionColumn.Width = 160;
+ //
+ // _CharSubstitutionColumn
+ //
+ this._CharSubstitutionColumn.Text = "替换字符";
+ this._CharSubstitutionColumn.Width = 71;
+ //
+ // _FontSubstitutionMenu
+ //
+ this._FontSubstitutionMenu.ImageScalingSize = new System.Drawing.Size(20, 20);
+ this._FontSubstitutionMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._CopySubstitutionFont,
+ this._PasteSubstitutionFont});
+ this._FontSubstitutionMenu.Name = "_FontSubstitutionMenu";
+ this._FontSubstitutionMenu.Size = new System.Drawing.Size(192, 56);
+ this._FontSubstitutionMenu.Opening += new System.ComponentModel.CancelEventHandler(this._FontSubstitutionMenu_Opening);
+ this._FontSubstitutionMenu.ItemClicked += new System.Windows.Forms.ToolStripItemClickedEventHandler(this._FontSubstitutionMenu_ItemClicked);
+ //
+ // _CopySubstitutionFont
+ //
+ this._CopySubstitutionFont.Image = global::PDFPatcher.Properties.Resources.Copy;
+ this._CopySubstitutionFont.Name = "_CopySubstitutionFont";
+ this._CopySubstitutionFont.Size = new System.Drawing.Size(191, 26);
+ this._CopySubstitutionFont.Text = "复制替换字体(&F)";
+ //
+ // _PasteSubstitutionFont
+ //
+ this._PasteSubstitutionFont.Image = global::PDFPatcher.Properties.Resources.Paste;
+ this._PasteSubstitutionFont.Name = "_PasteSubstitutionFont";
+ this._PasteSubstitutionFont.Size = new System.Drawing.Size(191, 26);
+ this._PasteSubstitutionFont.Text = "粘贴替换字体(&Z)";
+ //
+ // _RemovePageLabelButton
+ //
+ this._RemovePageLabelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._RemovePageLabelButton.Enabled = false;
+ this._RemovePageLabelButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._RemovePageLabelButton.Location = new System.Drawing.Point(509, 4);
+ this._RemovePageLabelButton.Margin = new System.Windows.Forms.Padding(4);
+ this._RemovePageLabelButton.Name = "_RemovePageLabelButton";
+ this._RemovePageLabelButton.Size = new System.Drawing.Size(71, 29);
+ this._RemovePageLabelButton.TabIndex = 4;
+ this._RemovePageLabelButton.Text = "删除";
+ this._RemovePageLabelButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._RemovePageLabelButton.UseVisualStyleBackColor = true;
+ this._RemovePageLabelButton.Click += new System.EventHandler(this._RemovePageLabelButton_Click);
+ //
+ // _AddPageLabelButton
+ //
+ this._AddPageLabelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._AddPageLabelButton.Enabled = false;
+ this._AddPageLabelButton.Image = global::PDFPatcher.Properties.Resources.Add;
+ this._AddPageLabelButton.Location = new System.Drawing.Point(431, 4);
+ this._AddPageLabelButton.Margin = new System.Windows.Forms.Padding(4);
+ this._AddPageLabelButton.Name = "_AddPageLabelButton";
+ this._AddPageLabelButton.Size = new System.Drawing.Size(71, 29);
+ this._AddPageLabelButton.TabIndex = 3;
+ this._AddPageLabelButton.Text = "添加";
+ this._AddPageLabelButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._AddPageLabelButton.UseVisualStyleBackColor = true;
+ this._AddPageLabelButton.Click += new System.EventHandler(this._AddPageLabelButton_Click);
+ //
+ // _ListDocumentFontButton
+ //
+ this._ListDocumentFontButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._ListDocumentFontButton.Enabled = false;
+ this._ListDocumentFontButton.Location = new System.Drawing.Point(276, 4);
+ this._ListDocumentFontButton.Margin = new System.Windows.Forms.Padding(4);
+ this._ListDocumentFontButton.Name = "_ListDocumentFontButton";
+ this._ListDocumentFontButton.Size = new System.Drawing.Size(147, 29);
+ this._ListDocumentFontButton.TabIndex = 2;
+ this._ListDocumentFontButton.Text = "列出文档字体";
+ this._ListDocumentFontButton.UseVisualStyleBackColor = true;
+ this._ListDocumentFontButton.Click += new System.EventHandler(this._ListDocumentFontButton_Click);
+ //
+ // _EmbedLegacyCjkFontsBox
+ //
+ this._EmbedLegacyCjkFontsBox.AutoSize = true;
+ this._EmbedLegacyCjkFontsBox.Location = new System.Drawing.Point(4, 9);
+ this._EmbedLegacyCjkFontsBox.Margin = new System.Windows.Forms.Padding(4);
+ this._EmbedLegacyCjkFontsBox.Name = "_EmbedLegacyCjkFontsBox";
+ this._EmbedLegacyCjkFontsBox.Size = new System.Drawing.Size(104, 19);
+ this._EmbedLegacyCjkFontsBox.TabIndex = 0;
+ this._EmbedLegacyCjkFontsBox.Text = "嵌入汉字库";
+ this._EmbedLegacyCjkFontsBox.UseVisualStyleBackColor = true;
+ //
+ // _EnableFontSubstitutionsBox
+ //
+ this._EnableFontSubstitutionsBox.AutoSize = true;
+ this._EnableFontSubstitutionsBox.Location = new System.Drawing.Point(124, 9);
+ this._EnableFontSubstitutionsBox.Margin = new System.Windows.Forms.Padding(4);
+ this._EnableFontSubstitutionsBox.Name = "_EnableFontSubstitutionsBox";
+ this._EnableFontSubstitutionsBox.Size = new System.Drawing.Size(119, 19);
+ this._EnableFontSubstitutionsBox.TabIndex = 1;
+ this._EnableFontSubstitutionsBox.Text = "允许替换字体";
+ this._EnableFontSubstitutionsBox.UseVisualStyleBackColor = true;
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this._TrimTrailingWhiteSpaceBox);
+ this.panel1.Controls.Add(this._FontSubstitutionsBox);
+ this.panel1.Controls.Add(this._EnableFontSubstitutionsBox);
+ this.panel1.Controls.Add(this._AddPageLabelButton);
+ this.panel1.Controls.Add(this._EmbedLegacyCjkFontsBox);
+ this.panel1.Controls.Add(this._RemovePageLabelButton);
+ this.panel1.Controls.Add(this._ListDocumentFontButton);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Margin = new System.Windows.Forms.Padding(4);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(584, 349);
+ this.panel1.TabIndex = 6;
+ //
+ // _TrimTrailingWhiteSpaceBox
+ //
+ this._TrimTrailingWhiteSpaceBox.AutoSize = true;
+ this._TrimTrailingWhiteSpaceBox.Location = new System.Drawing.Point(4, 35);
+ this._TrimTrailingWhiteSpaceBox.Name = "_TrimTrailingWhiteSpaceBox";
+ this._TrimTrailingWhiteSpaceBox.Size = new System.Drawing.Size(179, 19);
+ this._TrimTrailingWhiteSpaceBox.TabIndex = 6;
+ this._TrimTrailingWhiteSpaceBox.Text = "同时删除文本尾随空格";
+ this._TrimTrailingWhiteSpaceBox.UseVisualStyleBackColor = true;
+ //
+ // FontSubstitutionsEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 15F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.panel1);
+ this.Margin = new System.Windows.Forms.Padding(4);
+ this.Name = "FontSubstitutionsEditor";
+ this.Size = new System.Drawing.Size(584, 349);
+ this.Load += new System.EventHandler(this.FontSubstitutionsEditor_Load);
+ ((System.ComponentModel.ISupportInitialize)(this._FontSubstitutionsBox)).EndInit();
+ this._FontSubstitutionMenu.ResumeLayout(false);
+ this.panel1.ResumeLayout(false);
+ this.panel1.PerformLayout();
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _RemovePageLabelButton;
+ private System.Windows.Forms.Button _AddPageLabelButton;
+ private BrightIdeasSoftware.ObjectListView _FontSubstitutionsBox;
+ private BrightIdeasSoftware.OLVColumn _OriginalFontColumn;
+ private BrightIdeasSoftware.OLVColumn _SubstitutionColumn;
+ private BrightIdeasSoftware.OLVColumn _SequenceColumn;
+ private System.Windows.Forms.Button _ListDocumentFontButton;
+ private System.Windows.Forms.CheckBox _EmbedLegacyCjkFontsBox;
+ private System.Windows.Forms.CheckBox _EnableFontSubstitutionsBox;
+ private System.Windows.Forms.ContextMenuStrip _FontSubstitutionMenu;
+ private System.Windows.Forms.ToolStripMenuItem _CopySubstitutionFont;
+ private System.Windows.Forms.ToolStripMenuItem _PasteSubstitutionFont;
+ private System.Windows.Forms.Panel panel1;
+ private BrightIdeasSoftware.OLVColumn _CharSubstitutionColumn;
+ private System.Windows.Forms.CheckBox _TrimTrailingWhiteSpaceBox;
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.cs b/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..9e0e8d35e1fd17723ab773c761625511cea6e54a
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.cs
@@ -0,0 +1,180 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Text.RegularExpressions;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+using PDFPatcher.Common;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class FontSubstitutionsEditor : UserControl
+ {
+ string _copiedFont;
+
+ FontUtility.FriendlyFontName[] _Fonts;
+ readonly TypedObjectListView _SubstitutionsBox;
+ List _Substitutions;
+ [Browsable(false)]
+ public List Substitutions {
+ get => _Substitutions;
+ set { _Substitutions = value; _FontSubstitutionsBox.Objects = value; }
+ }
+ public PatcherOptions Options { get; set; }
+
+ public FontSubstitutionsEditor() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ _SubstitutionsBox = new TypedObjectListView(_FontSubstitutionsBox);
+ _FontSubstitutionsBox.FormatRow += (s, args) => args.Item.SubItems[0].Text = ValueHelper.ToText(args.RowIndex + 1);
+ new TypedColumn(_OriginalFontColumn) {
+ AspectGetter = (o) => o.OriginalFont,
+ AspectPutter = (o, v) => o.OriginalFont = v as string
+ };
+ new TypedColumn(_SubstitutionColumn) {
+ AspectGetter = (o) => o.Substitution,
+ AspectPutter = (o, v) => o.Substitution = v as string
+ };
+ new TypedColumn(_CharSubstitutionColumn) {
+ AspectGetter = (o) => String.IsNullOrEmpty(o.OriginalCharacters) ? "添加" : "修改"
+ };
+ }
+
+ void OnLoad() {
+ _FontSubstitutionsBox.FixEditControlWidth();
+ _FontSubstitutionsBox.ScaleColumnWidths();
+ _FontSubstitutionsBox.FullRowSelect = true;
+ _FontSubstitutionsBox.HideSelection = false;
+ _FontSubstitutionsBox.LabelEdit = false;
+ _FontSubstitutionsBox.CellEditStarting += (s, args) => {
+ if (args.Column == _SubstitutionColumn) {
+ EditSubstitutionItem(args);
+ }
+ else if (args.Column == _CharSubstitutionColumn) {
+ using (var f = new FontCharSubstitutionForm(args.RowObject as FontSubstitution)) {
+ f.ShowDialog(this);
+ }
+ args.Cancel = true;
+ }
+ };
+ _FontSubstitutionsBox.CellEditFinishing += (s, args) => {
+ if (args.Column == _SubstitutionColumn) {
+ var c = args.Control as ComboBox;
+ if (c.FindString(c.Text) != -1) {
+ args.NewValue = c.Text;
+ }
+ }
+ };
+ }
+
+ void EditSubstitutionItem(CellEditEventArgs args) {
+ var cb = new ComboBox {
+ AutoCompleteSource = AutoCompleteSource.ListItems,
+ AutoCompleteMode = AutoCompleteMode.SuggestAppend,
+ Bounds = args.CellBounds
+ };
+ var b = cb.Items;
+ b.Add(String.Empty);
+ var sf = (args.RowObject as FontSubstitution).Substitution;
+ bool cf = String.IsNullOrEmpty(sf) == false;
+ if (cf) {
+ sf = sf.ToUpperInvariant();
+ }
+ if (_Fonts.HasContent() == false) {
+ _Fonts = FontUtility.InstalledFonts;
+ }
+ var l = _Fonts.Length;
+ string fn;
+ for (int i = 0; i < l; i++) {
+ fn = _Fonts[i].ToString();
+ b.Add(fn);
+ if (String.Equals(fn, sf, StringComparison.OrdinalIgnoreCase)) {
+ cb.SelectedIndex = i + 1;
+ }
+ }
+ if (cb.SelectedIndex == -1) {
+ cb.SelectedIndex = 0;
+ }
+ args.Control = cb;
+ cb.ParentChanged += (s1, a) => {
+ var box = ((ComboBox)s1);
+ if (box.Parent != null) {
+ box.DroppedDown = true;
+ }
+ };
+ }
+
+ void FontSubstitutionsEditor_Load(object sender, EventArgs e) {
+ if (DesignMode) {
+ return;
+ }
+ _EmbedLegacyCjkFontsBox.Checked = Options.EmbedFonts;
+ _EmbedLegacyCjkFontsBox.CheckedChanged += (s, args) => Options.EmbedFonts = _EmbedLegacyCjkFontsBox.Checked;
+ _TrimTrailingWhiteSpaceBox.Checked = Options.TrimTrailingWhiteSpace;
+ _TrimTrailingWhiteSpaceBox.CheckedChanged += (s, args) => Options.TrimTrailingWhiteSpace = _TrimTrailingWhiteSpaceBox.Checked;
+ _EnableFontSubstitutionsBox.CheckedChanged += (s, args) => {
+ _ListDocumentFontButton.Enabled
+ = _AddPageLabelButton.Enabled
+ = _RemovePageLabelButton.Enabled
+ = _FontSubstitutionsBox.Enabled
+ = _TrimTrailingWhiteSpaceBox.Enabled
+ = Options.EnableFontSubstitutions
+ = _EnableFontSubstitutionsBox.Checked;
+ };
+ _EnableFontSubstitutionsBox.Checked = Options.EnableFontSubstitutions;
+ _FontSubstitutionMenu.Invalidate();
+ }
+
+ void _AddPageLabelButton_Click(object sender, EventArgs e) {
+ var s = new FontSubstitution { OriginalFont = "请输入原字体名称" };
+ _Substitutions.Add(s);
+ _FontSubstitutionsBox.AddObject(s);
+ _FontSubstitutionsBox.EditSubItem(_FontSubstitutionsBox.GetLastItemInDisplayOrder(), 1);
+ }
+
+ void _RemovePageLabelButton_Click(object sender, EventArgs e) {
+ _FontSubstitutionsBox.RemoveObjects(_FontSubstitutionsBox.SelectedObjects);
+ _Substitutions.Clear();
+ _Substitutions.AddRange(_SubstitutionsBox.Objects);
+ }
+
+ void _ListDocumentFontButton_Click(object sender, EventArgs e) {
+ using (var f = new DocumentFontListForm()) {
+ f.SubstitutionsEditor = this;
+ f.ShowDialog();
+ }
+ }
+
+ internal void AddFonts(IEnumerable fonts) {
+ var s = new HashSet(StringComparer.CurrentCultureIgnoreCase);
+ foreach (var item in _Substitutions) {
+ s.Add(item.OriginalFont);
+ }
+ foreach (var item in fonts) {
+ if (s.Contains(item)) {
+ continue;
+ }
+ _Substitutions.Add(new FontSubstitution() { OriginalFont = item });
+ }
+ _SubstitutionsBox.Objects = _Substitutions;
+ }
+
+ void _FontSubstitutionMenu_ItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ if (e.ClickedItem == _CopySubstitutionFont) {
+ _copiedFont = _FontSubstitutionsBox.GetFirstSelectedModel().Substitution;
+ }
+ else if (e.ClickedItem == _PasteSubstitutionFont) {
+ foreach (var item in _SubstitutionsBox.SelectedObjects) {
+ item.Substitution = _copiedFont;
+ }
+ _FontSubstitutionsBox.RefreshSelectedObjects();
+ }
+ }
+
+ void _FontSubstitutionMenu_Opening(object sender, CancelEventArgs e) {
+ _CopySubstitutionFont.Enabled = (_FontSubstitutionsBox.SelectedIndex != -1);
+ _PasteSubstitutionFont.Enabled = String.IsNullOrEmpty(_copiedFont) == false;
+ }
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.resx b/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..20323674aae20e16a48675e705479eef3967cc62
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/FontSubstitutionsEditor.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.Designer.cs b/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2a9720619aa600c6797fa43c0019540b1cffb7ad
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.Designer.cs
@@ -0,0 +1,168 @@
+namespace PDFPatcher.Functions
+{
+ partial class PageLabelEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container();
+ this._PageLabelBox = new BrightIdeasSoftware.ObjectListView();
+ this._SequenceColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._PageNumColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._LabelStyleColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._LabelPrefixColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._StartNumColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._RemovePageLabelButton = new System.Windows.Forms.Button();
+ this._AddPageLabelButton = new System.Windows.Forms.Button();
+ this._LabelStyleMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this.panel1 = new System.Windows.Forms.Panel();
+ ((System.ComponentModel.ISupportInitialize)(this._PageLabelBox)).BeginInit();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // _PageLabelBox
+ //
+ this._PageLabelBox.AllColumns.Add(this._SequenceColumn);
+ this._PageLabelBox.AllColumns.Add(this._PageNumColumn);
+ this._PageLabelBox.AllColumns.Add(this._LabelStyleColumn);
+ this._PageLabelBox.AllColumns.Add(this._LabelPrefixColumn);
+ this._PageLabelBox.AllColumns.Add(this._StartNumColumn);
+ this._PageLabelBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PageLabelBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this._PageLabelBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._SequenceColumn,
+ this._PageNumColumn,
+ this._LabelStyleColumn,
+ this._LabelPrefixColumn,
+ this._StartNumColumn});
+ this._PageLabelBox.GridLines = true;
+ this._PageLabelBox.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this._PageLabelBox.HideSelection = false;
+ this._PageLabelBox.LabelEdit = true;
+ this._PageLabelBox.Location = new System.Drawing.Point(3, 32);
+ this._PageLabelBox.Name = "_PageLabelBox";
+ this._PageLabelBox.OwnerDraw = true;
+ this._PageLabelBox.ShowGroups = false;
+ this._PageLabelBox.Size = new System.Drawing.Size(432, 244);
+ this._PageLabelBox.TabIndex = 0;
+ this._PageLabelBox.UseCompatibleStateImageBehavior = false;
+ this._PageLabelBox.View = System.Windows.Forms.View.Details;
+ //
+ // _SequenceColumn
+ //
+ this._SequenceColumn.IsEditable = false;
+ this._SequenceColumn.Text = "序号";
+ this._SequenceColumn.Width = 40;
+ //
+ // _PageNumColumn
+ //
+ this._PageNumColumn.Text = "文档页码";
+ this._PageNumColumn.Width = 65;
+ //
+ // _LabelStyleColumn
+ //
+ this._LabelStyleColumn.IsEditable = false;
+ this._LabelStyleColumn.Text = "页码样式";
+ this._LabelStyleColumn.Width = 103;
+ //
+ // _LabelPrefixColumn
+ //
+ this._LabelPrefixColumn.Text = "前缀文本";
+ this._LabelPrefixColumn.Width = 70;
+ //
+ // _StartNumColumn
+ //
+ this._StartNumColumn.Text = "起始号码";
+ this._StartNumColumn.Width = 70;
+ //
+ // _RemovePageLabelButton
+ //
+ this._RemovePageLabelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._RemovePageLabelButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._RemovePageLabelButton.Location = new System.Drawing.Point(382, 3);
+ this._RemovePageLabelButton.Name = "_RemovePageLabelButton";
+ this._RemovePageLabelButton.Size = new System.Drawing.Size(53, 23);
+ this._RemovePageLabelButton.TabIndex = 2;
+ this._RemovePageLabelButton.Text = "删除";
+ this._RemovePageLabelButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._RemovePageLabelButton.UseVisualStyleBackColor = true;
+ this._RemovePageLabelButton.Click += new System.EventHandler(this._RemovePageLabelButton_Click);
+ //
+ // _AddPageLabelButton
+ //
+ this._AddPageLabelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._AddPageLabelButton.Image = global::PDFPatcher.Properties.Resources.Add;
+ this._AddPageLabelButton.Location = new System.Drawing.Point(323, 3);
+ this._AddPageLabelButton.Name = "_AddPageLabelButton";
+ this._AddPageLabelButton.Size = new System.Drawing.Size(53, 23);
+ this._AddPageLabelButton.TabIndex = 1;
+ this._AddPageLabelButton.Text = "添加";
+ this._AddPageLabelButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._AddPageLabelButton.UseVisualStyleBackColor = true;
+ this._AddPageLabelButton.Click += new System.EventHandler(this._AddPageLabelButton_Click);
+ //
+ // _LabelStyleMenu
+ //
+ this._LabelStyleMenu.Name = "_LabelStyleMenu";
+ this._LabelStyleMenu.Size = new System.Drawing.Size(61, 4);
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this._PageLabelBox);
+ this.panel1.Controls.Add(this._RemovePageLabelButton);
+ this.panel1.Controls.Add(this._AddPageLabelButton);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(438, 279);
+ this.panel1.TabIndex = 3;
+ //
+ // PageLabelEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.panel1);
+ this.Name = "PageLabelEditor";
+ this.Size = new System.Drawing.Size(438, 279);
+ ((System.ComponentModel.ISupportInitialize)(this._PageLabelBox)).EndInit();
+ this.panel1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _RemovePageLabelButton;
+ private System.Windows.Forms.Button _AddPageLabelButton;
+ private BrightIdeasSoftware.ObjectListView _PageLabelBox;
+ private BrightIdeasSoftware.OLVColumn _PageNumColumn;
+ private BrightIdeasSoftware.OLVColumn _LabelStyleColumn;
+ private BrightIdeasSoftware.OLVColumn _LabelPrefixColumn;
+ private BrightIdeasSoftware.OLVColumn _StartNumColumn;
+ private BrightIdeasSoftware.OLVColumn _SequenceColumn;
+ private System.Windows.Forms.ContextMenuStrip _LabelStyleMenu;
+ private System.Windows.Forms.Panel panel1;
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.cs b/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..f318a13c4fe5513733013e3fa364e45c40c5f0a5
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.cs
@@ -0,0 +1,82 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+using PDFPatcher.Common;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class PageLabelEditor : UserControl
+ {
+ readonly TypedObjectListView _LabelBox;
+ List _Labels;
+
+ [Browsable(false)]
+ public List Labels {
+ get => _Labels;
+ set { _Labels = value; _PageLabelBox.Objects = value; }
+ }
+
+ public PageLabelEditor() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ _LabelBox = new TypedObjectListView(_PageLabelBox);
+ _PageLabelBox.FormatRow += (s, args) => args.Item.SubItems[0].Text = (args.RowIndex + 1).ToText();
+ new TypedColumn(_PageNumColumn) {
+ AspectGetter = (o) => o.PageNumber,
+ AspectPutter = (o, v) => { int i = v.ToString().ToInt32(); o.PageNumber = i > 0 ? i : 1; }
+ };
+ new TypedColumn(_StartNumColumn) {
+ AspectGetter = (o) => o.StartPage,
+ AspectPutter = (o, v) => { int i = v.ToString().ToInt32(); o.StartPage = i > 0 ? i : 1; }
+ };
+ new TypedColumn(_LabelStyleColumn) {
+ AspectGetter = (o) => o.Style ?? Constants.PageLabelStyles.Names[0]
+ };
+ new TypedColumn(_LabelPrefixColumn) {
+ AspectGetter = (o) => o.Prefix,
+ AspectPutter = (o, v) => o.Prefix = v as string
+ };
+ }
+
+ void OnLoad() {
+ foreach (var item in Constants.PageLabelStyles.Names) {
+ _LabelStyleMenu.Items.Add(item);
+ }
+ _PageLabelBox.FixEditControlWidth();
+ _PageLabelBox.ScaleColumnWidths();
+ _PageLabelBox.FullRowSelect = true;
+ _PageLabelBox.LabelEdit = false;
+ _PageLabelBox.CellClick += (s, args) => {
+ if (args.Column == _LabelStyleColumn) {
+ var b = _PageLabelBox.GetSubItem(args.RowIndex, args.ColumnIndex).Bounds;
+ _LabelStyleMenu.Show(_PageLabelBox, b.Left, b.Bottom);
+ }
+ };
+ _LabelStyleMenu.ItemClicked += (s, args) => {
+ _LabelBox.SelectedObject.Style = args.ClickedItem.Text;
+ _PageLabelBox.RefreshObject(_PageLabelBox.SelectedObject);
+ };
+ }
+
+ void _AddPageLabelButton_Click(object sender, EventArgs e) {
+ var i = 0;
+ foreach (var item in _Labels) {
+ if (item.PageNumber > i) {
+ i = item.PageNumber;
+ }
+ }
+ ++i;
+ _Labels.Add(new Model.PageLabel() { PageNumber = i, StartPage = 1 });
+ _LabelBox.Objects = _Labels;
+ }
+
+ void _RemovePageLabelButton_Click(object sender, EventArgs e) {
+ _PageLabelBox.RemoveObjects(_PageLabelBox.SelectedObjects);
+ _Labels.Clear();
+ _Labels.AddRange(_LabelBox.Objects);
+ }
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.resx b/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..24882cca85cf5be02be23b2384cf54c4489cfd52
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/PageLabelEditor.resx
@@ -0,0 +1,123 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.Designer.cs b/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..870a1bdec7fb98c48f3b877518c61feb54924d6c
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.Designer.cs
@@ -0,0 +1,292 @@
+namespace PDFPatcher.Functions
+{
+ partial class PageSettingsEditor
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container();
+ System.Windows.Forms.ToolStripSeparator toolStripSeparator1;
+ System.Windows.Forms.ToolStripSeparator toolStripSeparator2;
+ this._RotateZeroMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._PageSettingsBox = new BrightIdeasSoftware.ObjectListView();
+ this._SequenceColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._PageRangeColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._PageFilterColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._SettingsColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._PageRangeFilterTypeMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this._AllPagesMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this._OddPagesMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this._EvenPagesMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this._PortraitPagesMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this._LandscapePagesMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this._PageSettingsMenu = new System.Windows.Forms.ContextMenuStrip(this.components);
+ this._RotateMenu = new System.Windows.Forms.ToolStripMenuItem();
+ this._RotateLeftMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._RotateRightMenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._Rotate180MenuItem = new System.Windows.Forms.ToolStripMenuItem();
+ this._RemoveButton = new System.Windows.Forms.Button();
+ this._AddButton = new System.Windows.Forms.Button();
+ this.panel1 = new System.Windows.Forms.Panel();
+ toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator();
+ toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator();
+ ((System.ComponentModel.ISupportInitialize)(this._PageSettingsBox)).BeginInit();
+ this._PageRangeFilterTypeMenu.SuspendLayout();
+ this._PageSettingsMenu.SuspendLayout();
+ this.panel1.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // toolStripSeparator1
+ //
+ toolStripSeparator1.Name = "toolStripSeparator1";
+ toolStripSeparator1.Size = new System.Drawing.Size(138, 6);
+ //
+ // toolStripSeparator2
+ //
+ toolStripSeparator2.Name = "toolStripSeparator2";
+ toolStripSeparator2.Size = new System.Drawing.Size(138, 6);
+ //
+ // _RotateZeroMenuItem
+ //
+ this._RotateZeroMenuItem.Name = "_RotateZeroMenuItem";
+ this._RotateZeroMenuItem.Size = new System.Drawing.Size(149, 22);
+ this._RotateZeroMenuItem.Text = "保持不变(&B)";
+ //
+ // _PageSettingsBox
+ //
+ this._PageSettingsBox.AllColumns.Add(this._SequenceColumn);
+ this._PageSettingsBox.AllColumns.Add(this._PageRangeColumn);
+ this._PageSettingsBox.AllColumns.Add(this._PageFilterColumn);
+ this._PageSettingsBox.AllColumns.Add(this._SettingsColumn);
+ this._PageSettingsBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PageSettingsBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this._PageSettingsBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._SequenceColumn,
+ this._PageRangeColumn,
+ this._PageFilterColumn,
+ this._SettingsColumn});
+ this._PageSettingsBox.GridLines = true;
+ this._PageSettingsBox.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this._PageSettingsBox.HideSelection = false;
+ this._PageSettingsBox.IsSimpleDragSource = true;
+ this._PageSettingsBox.IsSimpleDropSink = true;
+ this._PageSettingsBox.LabelEdit = true;
+ this._PageSettingsBox.Location = new System.Drawing.Point(3, 32);
+ this._PageSettingsBox.Name = "_PageSettingsBox";
+ this._PageSettingsBox.OwnerDraw = true;
+ this._PageSettingsBox.ShowGroups = false;
+ this._PageSettingsBox.Size = new System.Drawing.Size(432, 244);
+ this._PageSettingsBox.TabIndex = 3;
+ this._PageSettingsBox.UseCompatibleStateImageBehavior = false;
+ this._PageSettingsBox.View = System.Windows.Forms.View.Details;
+ //
+ // _SequenceColumn
+ //
+ this._SequenceColumn.IsEditable = false;
+ this._SequenceColumn.Text = "序号";
+ this._SequenceColumn.Width = 40;
+ //
+ // _PageRangeColumn
+ //
+ this._PageRangeColumn.AspectName = "";
+ this._PageRangeColumn.Text = "页码范围";
+ this._PageRangeColumn.Width = 82;
+ //
+ // _PageFilterColumn
+ //
+ this._PageFilterColumn.AspectName = "";
+ this._PageFilterColumn.IsEditable = false;
+ this._PageFilterColumn.Text = "筛选页面";
+ this._PageFilterColumn.Width = 61;
+ //
+ // _SettingsColumn
+ //
+ this._SettingsColumn.IsEditable = false;
+ this._SettingsColumn.Text = "处理方式";
+ this._SettingsColumn.Width = 214;
+ //
+ // _PageRangeFilterTypeMenu
+ //
+ this._PageRangeFilterTypeMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._AllPagesMenu,
+ toolStripSeparator1,
+ this._OddPagesMenu,
+ this._EvenPagesMenu,
+ toolStripSeparator2,
+ this._PortraitPagesMenu,
+ this._LandscapePagesMenu});
+ this._PageRangeFilterTypeMenu.Name = "_PageRangeFilterTypeMenu";
+ this._PageRangeFilterTypeMenu.Size = new System.Drawing.Size(142, 126);
+ //
+ // _AllPagesMenu
+ //
+ this._AllPagesMenu.Image = global::PDFPatcher.Properties.Resources.Copy;
+ this._AllPagesMenu.Name = "_AllPagesMenu";
+ this._AllPagesMenu.Size = new System.Drawing.Size(141, 22);
+ this._AllPagesMenu.Text = "所有页面(&Y)";
+ //
+ // _OddPagesMenu
+ //
+ this._OddPagesMenu.Image = global::PDFPatcher.Properties.Resources.OddPage;
+ this._OddPagesMenu.Name = "_OddPagesMenu";
+ this._OddPagesMenu.Size = new System.Drawing.Size(141, 22);
+ this._OddPagesMenu.Text = "单数页(&D)";
+ //
+ // _EvenPagesMenu
+ //
+ this._EvenPagesMenu.Image = global::PDFPatcher.Properties.Resources.EvenPage;
+ this._EvenPagesMenu.Name = "_EvenPagesMenu";
+ this._EvenPagesMenu.Size = new System.Drawing.Size(141, 22);
+ this._EvenPagesMenu.Text = "双数页(&S)";
+ //
+ // _PortraitPagesMenu
+ //
+ this._PortraitPagesMenu.Image = global::PDFPatcher.Properties.Resources.Portrait;
+ this._PortraitPagesMenu.Name = "_PortraitPagesMenu";
+ this._PortraitPagesMenu.Size = new System.Drawing.Size(141, 22);
+ this._PortraitPagesMenu.Text = "纵向页面(&Z)";
+ //
+ // _LandscapePagesMenu
+ //
+ this._LandscapePagesMenu.Image = global::PDFPatcher.Properties.Resources.Lanscape;
+ this._LandscapePagesMenu.Name = "_LandscapePagesMenu";
+ this._LandscapePagesMenu.Size = new System.Drawing.Size(141, 22);
+ this._LandscapePagesMenu.Text = "横向页面(&H)";
+ //
+ // _PageSettingsMenu
+ //
+ this._PageSettingsMenu.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._RotateMenu});
+ this._PageSettingsMenu.Name = "_PageSettingsMenu";
+ this._PageSettingsMenu.Size = new System.Drawing.Size(141, 26);
+ //
+ // _RotateMenu
+ //
+ this._RotateMenu.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._RotateZeroMenuItem,
+ this._RotateLeftMenuItem,
+ this._RotateRightMenuItem,
+ this._Rotate180MenuItem});
+ this._RotateMenu.Name = "_RotateMenu";
+ this._RotateMenu.Size = new System.Drawing.Size(140, 22);
+ this._RotateMenu.Text = "旋转页面(&X)";
+ //
+ // _RotateLeftMenuItem
+ //
+ this._RotateLeftMenuItem.Image = global::PDFPatcher.Properties.Resources.RotateLeft;
+ this._RotateLeftMenuItem.Name = "_RotateLeftMenuItem";
+ this._RotateLeftMenuItem.Size = new System.Drawing.Size(149, 22);
+ this._RotateLeftMenuItem.Text = "左转 90 度(&Z)";
+ //
+ // _RotateRightMenuItem
+ //
+ this._RotateRightMenuItem.Image = global::PDFPatcher.Properties.Resources.RotateRight;
+ this._RotateRightMenuItem.Name = "_RotateRightMenuItem";
+ this._RotateRightMenuItem.Size = new System.Drawing.Size(149, 22);
+ this._RotateRightMenuItem.Text = "右转 90 度(&Y)";
+ //
+ // _Rotate180MenuItem
+ //
+ this._Rotate180MenuItem.Image = global::PDFPatcher.Properties.Resources.Refresh;
+ this._Rotate180MenuItem.Name = "_Rotate180MenuItem";
+ this._Rotate180MenuItem.Size = new System.Drawing.Size(149, 22);
+ this._Rotate180MenuItem.Text = "旋转 180 度";
+ //
+ // _RemoveButton
+ //
+ this._RemoveButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._RemoveButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._RemoveButton.Location = new System.Drawing.Point(382, 3);
+ this._RemoveButton.Name = "_RemoveButton";
+ this._RemoveButton.Size = new System.Drawing.Size(53, 23);
+ this._RemoveButton.TabIndex = 5;
+ this._RemoveButton.Text = "删除";
+ this._RemoveButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._RemoveButton.UseVisualStyleBackColor = true;
+ this._RemoveButton.Click += new System.EventHandler(this._RemovePageSettingsButton_Click);
+ //
+ // _AddButton
+ //
+ this._AddButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._AddButton.Image = global::PDFPatcher.Properties.Resources.Add;
+ this._AddButton.Location = new System.Drawing.Point(323, 3);
+ this._AddButton.Name = "_AddButton";
+ this._AddButton.Size = new System.Drawing.Size(53, 23);
+ this._AddButton.TabIndex = 4;
+ this._AddButton.Text = "添加";
+ this._AddButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._AddButton.UseVisualStyleBackColor = true;
+ this._AddButton.Click += new System.EventHandler(this._AddPageSettingsButton_Click);
+ //
+ // panel1
+ //
+ this.panel1.Controls.Add(this._PageSettingsBox);
+ this.panel1.Controls.Add(this._AddButton);
+ this.panel1.Controls.Add(this._RemoveButton);
+ this.panel1.Dock = System.Windows.Forms.DockStyle.Fill;
+ this.panel1.Location = new System.Drawing.Point(0, 0);
+ this.panel1.Name = "panel1";
+ this.panel1.Size = new System.Drawing.Size(438, 279);
+ this.panel1.TabIndex = 6;
+ //
+ // PageSettingsEditor
+ //
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.Controls.Add(this.panel1);
+ this.Name = "PageSettingsEditor";
+ this.Size = new System.Drawing.Size(438, 279);
+ ((System.ComponentModel.ISupportInitialize)(this._PageSettingsBox)).EndInit();
+ this._PageRangeFilterTypeMenu.ResumeLayout(false);
+ this._PageSettingsMenu.ResumeLayout(false);
+ this.panel1.ResumeLayout(false);
+ this.ResumeLayout(false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _RemoveButton;
+ private System.Windows.Forms.Button _AddButton;
+ private BrightIdeasSoftware.ObjectListView _PageSettingsBox;
+ private BrightIdeasSoftware.OLVColumn _SequenceColumn;
+ private BrightIdeasSoftware.OLVColumn _PageRangeColumn;
+ private BrightIdeasSoftware.OLVColumn _PageFilterColumn;
+ private BrightIdeasSoftware.OLVColumn _SettingsColumn;
+ private System.Windows.Forms.ContextMenuStrip _PageRangeFilterTypeMenu;
+ private System.Windows.Forms.ContextMenuStrip _PageSettingsMenu;
+ private System.Windows.Forms.ToolStripMenuItem _RotateMenu;
+ private System.Windows.Forms.ToolStripMenuItem _AllPagesMenu;
+ private System.Windows.Forms.ToolStripMenuItem _OddPagesMenu;
+ private System.Windows.Forms.ToolStripMenuItem _EvenPagesMenu;
+ private System.Windows.Forms.ToolStripMenuItem _LandscapePagesMenu;
+ private System.Windows.Forms.ToolStripMenuItem _PortraitPagesMenu;
+ private System.Windows.Forms.ToolStripMenuItem _RotateZeroMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem _RotateLeftMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem _RotateRightMenuItem;
+ private System.Windows.Forms.ToolStripMenuItem _Rotate180MenuItem;
+ private System.Windows.Forms.Panel panel1;
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.cs b/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.cs
new file mode 100644
index 0000000000000000000000000000000000000000..28b12cc8c69f0d46b7d86f5d283e7dc62235ad48
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.cs
@@ -0,0 +1,166 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class PageSettingsEditor : UserControl
+ {
+ readonly TypedObjectListView _SettingsBox;
+ private List _Settings;
+ [Browsable(false)]
+ public List Settings {
+ get => _Settings;
+ set { _Settings = value; _SettingsBox.Objects = value; }
+ }
+
+ public PageSettingsEditor() {
+ InitializeComponent();
+ this.OnFirstLoad(OnLoad);
+ _SettingsBox = new TypedObjectListView(_PageSettingsBox);
+ new TypedColumn(_PageFilterColumn) {
+ AspectGetter = (o) => {
+ var f = o.Filter;
+ var eo = f & (PageFilterFlag.Even | PageFilterFlag.Odd);
+ var pl = f & (PageFilterFlag.Landscape | PageFilterFlag.Portrait);
+ return f == PageFilterFlag.NotSpecified ? "所有页面"
+ : String.Concat(
+ eo == PageFilterFlag.Odd ? "单数"
+ : eo == PageFilterFlag.Even ? "双数"
+ : String.Empty,
+ pl == PageFilterFlag.Landscape ? "横向"
+ : pl == PageFilterFlag.Portrait ? "纵向"
+ : String.Empty,
+ "页");
+ }
+ };
+ new TypedColumn(_SettingsColumn) {
+ AspectGetter = (o) => {
+ var r = o.Rotation;
+ return String.Concat(
+ r == 0 ? Constants.Content.RotationDirections.Zero
+ : r == 90 ? Constants.Content.RotationDirections.Right
+ : r == 180 ? Constants.Content.RotationDirections.HalfClock
+ : r == 270 ? Constants.Content.RotationDirections.Left
+ : Constants.Content.RotationDirections.Zero
+ );
+ }
+ };
+ new TypedColumn(_PageRangeColumn) {
+ AspectGetter = (o) => { return String.IsNullOrEmpty(o.PageRanges) ? Constants.PageFilterTypes.AllPages : o.PageRanges; },
+ AspectPutter = (o, v) => {
+ var s = v as string;
+ o.PageRanges = s != Constants.PageFilterTypes.AllPages ? s : null;
+ }
+ };
+ _PageSettingsBox.FormatRow += (s, args) => {
+ args.Item.SubItems[0].Text = (args.RowIndex + 1).ToText();
+ };
+ }
+
+ void OnLoad() {
+ _PageSettingsBox.FixEditControlWidth();
+ _PageSettingsBox.ScaleColumnWidths();
+ _PageSettingsBox.FullRowSelect = true;
+ _PageSettingsBox.LabelEdit = false;
+ _PageSettingsBox.CellClick += (s, args) => {
+ if (args.Column == _PageFilterColumn) {
+ ShowMenuForClickedCell(args, _PageRangeFilterTypeMenu);
+ }
+ else if (args.Column == _SettingsColumn) {
+ ShowMenuForClickedCell(args, _PageSettingsMenu);
+ }
+ };
+ _PageRangeFilterTypeMenu.Opening += (s, args) => {
+ var f = _SettingsBox.SelectedObject.Filter;
+ _AllPagesMenu.Checked = f == PageFilterFlag.All || f == PageFilterFlag.NotSpecified;
+ _OddPagesMenu.Checked = (f & PageFilterFlag.Odd) == PageFilterFlag.Odd;
+ _EvenPagesMenu.Checked = (f & PageFilterFlag.Even) == PageFilterFlag.Even;
+ _PortraitPagesMenu.Checked = (f & PageFilterFlag.Portrait) == PageFilterFlag.Portrait;
+ _LandscapePagesMenu.Checked = (f & PageFilterFlag.Landscape) == PageFilterFlag.Landscape;
+ };
+ _PageRangeFilterTypeMenu.ItemClicked += (s, args) => {
+ var o = _SettingsBox.SelectedObject;
+ var i = args.ClickedItem;
+ if (_AllPagesMenu == i) {
+ o.Filter = PageFilterFlag.NotSpecified;
+ }
+ else if (_OddPagesMenu == i) {
+ o.Filter &= ~PageFilterFlag.Even;
+ o.Filter ^= PageFilterFlag.Odd;
+ }
+ else if (_EvenPagesMenu == i) {
+ o.Filter &= ~PageFilterFlag.Odd;
+ o.Filter ^= PageFilterFlag.Even;
+ }
+ else if (_LandscapePagesMenu == i) {
+ o.Filter &= ~PageFilterFlag.Portrait;
+ o.Filter ^= PageFilterFlag.Landscape;
+ }
+ else if (_PortraitPagesMenu == i) {
+ o.Filter &= ~PageFilterFlag.Landscape;
+ o.Filter ^= PageFilterFlag.Portrait;
+ }
+ if (o.Filter == PageFilterFlag.All) {
+ o.Filter = PageFilterFlag.NotSpecified;
+ }
+ _PageSettingsBox.RefreshObject(_PageSettingsBox.SelectedObject);
+ };
+ _RotateMenu.DropDownOpening += (s, args) => {
+ var r = _SettingsBox.SelectedObject.Rotation;
+ foreach (ToolStripMenuItem item in _RotateMenu.DropDownItems) {
+ item.Checked = false;
+ }
+ switch (r) {
+ case 0: _RotateZeroMenuItem.Checked = true; break;
+ case 90: _RotateRightMenuItem.Checked = true; break;
+ case 180: _Rotate180MenuItem.Checked = true; break;
+ case 270: _RotateLeftMenuItem.Checked = true; break;
+ default: _RotateZeroMenuItem.Checked = true; break;
+ }
+ };
+ _RotateMenu.DropDownItemClicked += (s, args) => {
+ var o = _SettingsBox.SelectedObject;
+ var i = args.ClickedItem;
+ if (_RotateZeroMenuItem == i) {
+ o.Rotation = 0;
+ }
+ else if (_RotateRightMenuItem == i) {
+ o.Rotation = 90;
+ }
+ else if (_RotateLeftMenuItem == i) {
+ o.Rotation = 270;
+ }
+ else if (_Rotate180MenuItem == i) {
+ o.Rotation = 180;
+ }
+ _PageSettingsBox.RefreshObject(o);
+ };
+ }
+
+ private void ShowMenuForClickedCell(CellClickEventArgs args, ContextMenuStrip menu) {
+ var b = _PageSettingsBox.GetSubItem(args.RowIndex, args.ColumnIndex).Bounds;
+ menu.Show(_PageSettingsBox, b.Left, b.Bottom);
+ }
+
+ private void _AddPageSettingsButton_Click(object sender, EventArgs e) {
+ _Settings.Add(new PageBoxSettings());
+ _SettingsBox.Objects = _Settings;
+ }
+
+ private void _RemovePageSettingsButton_Click(object sender, EventArgs e) {
+ _PageSettingsBox.RemoveObjects(_PageSettingsBox.SelectedObjects);
+ _Settings.Clear();
+ _Settings.AddRange(_SettingsBox.Objects);
+ }
+
+
+ }
+}
diff --git a/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.resx b/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.resx
new file mode 100644
index 0000000000000000000000000000000000000000..8caaeabe3de44eef9249726ddaba478bb0070473
--- /dev/null
+++ b/pdfpatcher/App/Functions/DocumentOption/PageSettingsEditor.resx
@@ -0,0 +1,132 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ False
+
+
+ 17, 17
+
+
+ 220, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/DraggableForm.cs b/pdfpatcher/App/Functions/DraggableForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..53e4ccdd6fcf5c1beb3fa278849fe42f24a19ba8
--- /dev/null
+++ b/pdfpatcher/App/Functions/DraggableForm.cs
@@ -0,0 +1,30 @@
+using System;
+using System.Runtime.InteropServices;
+using System.Windows.Forms;
+
+namespace PDFPatcher.Functions
+{
+ public class DraggableForm : Form
+ {
+ protected override void OnMouseDown(MouseEventArgs args) {
+ if (args.Button == MouseButtons.Left) {
+ NativeMethods.ReleaseCapture();
+ NativeMethods.SendMessage(Handle, 0xa1, (IntPtr)0x2, (IntPtr)0);
+ }
+ base.OnMouseMove(args);
+ }
+
+ static class NativeMethods
+ {
+ #region Form Dragging API Support
+ //The SendMessage function sends a message to a window or windows.
+ [DllImport("user32.dll", SetLastError = false)]
+ internal static extern IntPtr SendMessage(IntPtr hWnd, UInt32 Msg, IntPtr wParam, IntPtr lParam);
+
+ //ReleaseCapture releases a mouse capture
+ [DllImport("user32.dll", SetLastError = false)]
+ internal static extern bool ReleaseCapture();
+ #endregion
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/Editor/ActionEditorForm.Designer.cs b/pdfpatcher/App/Functions/Editor/ActionEditorForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..bde5a2e4b3ff79eaec4991d84c86539bf81ae896
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/ActionEditorForm.Designer.cs
@@ -0,0 +1,629 @@
+namespace PDFPatcher.Functions
+{
+ partial class ActionEditorForm
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows 窗体设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager (typeof (ActionEditorForm));
+ this._OkButton = new System.Windows.Forms.Button ();
+ this._CancelButton = new System.Windows.Forms.Button ();
+ this._DestinationPanel = new System.Windows.Forms.GroupBox ();
+ this._PathPanel = new System.Windows.Forms.Panel ();
+ this._PathBox = new System.Windows.Forms.TextBox ();
+ this.label4 = new System.Windows.Forms.Label ();
+ this._NewWindowBox = new System.Windows.Forms.CheckBox ();
+ this._NamedBox = new System.Windows.Forms.TextBox ();
+ this._GotoNamedDestBox = new System.Windows.Forms.RadioButton ();
+ this._GotoLocationBox = new System.Windows.Forms.RadioButton ();
+ this._LocationPanel = new System.Windows.Forms.Panel ();
+ this.label10 = new System.Windows.Forms.Label ();
+ this.label3 = new System.Windows.Forms.Label ();
+ this._KeepYBox = new System.Windows.Forms.CheckBox ();
+ this._PageBox = new System.Windows.Forms.NumericUpDown ();
+ this._KeepXBox = new System.Windows.Forms.CheckBox ();
+ this.label5 = new System.Windows.Forms.Label ();
+ this._ZoomRateBox = new System.Windows.Forms.ComboBox ();
+ this._LeftBox = new System.Windows.Forms.NumericUpDown ();
+ this.label7 = new System.Windows.Forms.Label ();
+ this._TopBox = new System.Windows.Forms.NumericUpDown ();
+ this.label6 = new System.Windows.Forms.Label ();
+ this._RectanglePanel = new System.Windows.Forms.Panel ();
+ this.label8 = new System.Windows.Forms.Label ();
+ this._WidthBox = new System.Windows.Forms.NumericUpDown ();
+ this.label9 = new System.Windows.Forms.Label ();
+ this._HeightBox = new System.Windows.Forms.NumericUpDown ();
+ this._ActionBox = new System.Windows.Forms.ComboBox ();
+ this.label2 = new System.Windows.Forms.Label ();
+ this._TitleBox = new System.Windows.Forms.TextBox ();
+ this.label1 = new System.Windows.Forms.Label ();
+ this.tabControl1 = new System.Windows.Forms.TabControl ();
+ this.tabPage1 = new System.Windows.Forms.TabPage ();
+ this._DefaultOpenBox = new System.Windows.Forms.CheckBox ();
+ this._ScriptBox = new System.Windows.Forms.GroupBox ();
+ this._ScriptContentBox = new System.Windows.Forms.TextBox ();
+ this.tabPage2 = new System.Windows.Forms.TabPage ();
+ this._AttributesBox = new BrightIdeasSoftware.ObjectListView ();
+ this._AttrNameColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._AttrValueColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._DestinationPanel.SuspendLayout ();
+ this._PathPanel.SuspendLayout ();
+ this._LocationPanel.SuspendLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._PageBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._LeftBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._TopBox)).BeginInit ();
+ this._RectanglePanel.SuspendLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._WidthBox)).BeginInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._HeightBox)).BeginInit ();
+ this.tabControl1.SuspendLayout ();
+ this.tabPage1.SuspendLayout ();
+ this._ScriptBox.SuspendLayout ();
+ this.tabPage2.SuspendLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._AttributesBox)).BeginInit ();
+ this.SuspendLayout ();
+ //
+ // _OkButton
+ //
+ this._OkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._OkButton.Location = new System.Drawing.Point (293, 348);
+ this._OkButton.Name = "_OkButton";
+ this._OkButton.Size = new System.Drawing.Size (75, 23);
+ this._OkButton.TabIndex = 0;
+ this._OkButton.Text = "确定(&Q)";
+ this._OkButton.UseVisualStyleBackColor = true;
+ this._OkButton.Click += new System.EventHandler (this._OkButton_Click);
+ //
+ // _CancelButton
+ //
+ this._CancelButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
+ this._CancelButton.DialogResult = System.Windows.Forms.DialogResult.Cancel;
+ this._CancelButton.Location = new System.Drawing.Point (374, 348);
+ this._CancelButton.Name = "_CancelButton";
+ this._CancelButton.Size = new System.Drawing.Size (75, 23);
+ this._CancelButton.TabIndex = 1;
+ this._CancelButton.Text = "取消(&X)";
+ this._CancelButton.UseVisualStyleBackColor = true;
+ this._CancelButton.Click += new System.EventHandler (this._CancelButton_Click);
+ //
+ // _DestinationPanel
+ //
+ this._DestinationPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._DestinationPanel.Controls.Add (this._PathPanel);
+ this._DestinationPanel.Controls.Add (this._NamedBox);
+ this._DestinationPanel.Controls.Add (this._GotoNamedDestBox);
+ this._DestinationPanel.Controls.Add (this._GotoLocationBox);
+ this._DestinationPanel.Controls.Add (this._LocationPanel);
+ this._DestinationPanel.Location = new System.Drawing.Point (6, 61);
+ this._DestinationPanel.Name = "_DestinationPanel";
+ this._DestinationPanel.Size = new System.Drawing.Size (417, 238);
+ this._DestinationPanel.TabIndex = 7;
+ this._DestinationPanel.TabStop = false;
+ this._DestinationPanel.Text = "目标";
+ //
+ // _PathPanel
+ //
+ this._PathPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PathPanel.Controls.Add (this._PathBox);
+ this._PathPanel.Controls.Add (this.label4);
+ this._PathPanel.Controls.Add (this._NewWindowBox);
+ this._PathPanel.Enabled = false;
+ this._PathPanel.Location = new System.Drawing.Point (5, 185);
+ this._PathPanel.Name = "_PathPanel";
+ this._PathPanel.Size = new System.Drawing.Size (406, 47);
+ this._PathPanel.TabIndex = 15;
+ //
+ // _PathBox
+ //
+ this._PathBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._PathBox.Location = new System.Drawing.Point (105, 3);
+ this._PathBox.Name = "_PathBox";
+ this._PathBox.Size = new System.Drawing.Size (298, 21);
+ this._PathBox.TabIndex = 3;
+ //
+ // label4
+ //
+ this.label4.AutoSize = true;
+ this.label4.Location = new System.Drawing.Point (13, 6);
+ this.label4.Name = "label4";
+ this.label4.Size = new System.Drawing.Size (89, 12);
+ this.label4.TabIndex = 2;
+ this.label4.Text = "外部文档路径:";
+ //
+ // _NewWindowBox
+ //
+ this._NewWindowBox.AutoSize = true;
+ this._NewWindowBox.Location = new System.Drawing.Point (105, 30);
+ this._NewWindowBox.Name = "_NewWindowBox";
+ this._NewWindowBox.Size = new System.Drawing.Size (96, 16);
+ this._NewWindowBox.TabIndex = 4;
+ this._NewWindowBox.Text = "在新窗口打开";
+ this._NewWindowBox.UseVisualStyleBackColor = true;
+ //
+ // _NamedBox
+ //
+ this._NamedBox.Enabled = false;
+ this._NamedBox.Location = new System.Drawing.Point (110, 158);
+ this._NamedBox.Name = "_NamedBox";
+ this._NamedBox.Size = new System.Drawing.Size (215, 21);
+ this._NamedBox.TabIndex = 14;
+ //
+ // _GotoNamedDestBox
+ //
+ this._GotoNamedDestBox.AutoSize = true;
+ this._GotoNamedDestBox.Location = new System.Drawing.Point (9, 159);
+ this._GotoNamedDestBox.Name = "_GotoNamedDestBox";
+ this._GotoNamedDestBox.Size = new System.Drawing.Size (95, 16);
+ this._GotoNamedDestBox.TabIndex = 13;
+ this._GotoNamedDestBox.TabStop = true;
+ this._GotoNamedDestBox.Text = "转到命名位置";
+ this._GotoNamedDestBox.UseVisualStyleBackColor = true;
+ this._GotoNamedDestBox.CheckedChanged += new System.EventHandler (this.Control_ValueChanged);
+ //
+ // _GotoLocationBox
+ //
+ this._GotoLocationBox.AutoSize = true;
+ this._GotoLocationBox.Location = new System.Drawing.Point (6, 20);
+ this._GotoLocationBox.Name = "_GotoLocationBox";
+ this._GotoLocationBox.Size = new System.Drawing.Size (95, 16);
+ this._GotoLocationBox.TabIndex = 12;
+ this._GotoLocationBox.TabStop = true;
+ this._GotoLocationBox.Text = "转到指定位置";
+ this._GotoLocationBox.UseVisualStyleBackColor = true;
+ this._GotoLocationBox.CheckedChanged += new System.EventHandler (this.Control_ValueChanged);
+ //
+ // _LocationPanel
+ //
+ this._LocationPanel.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._LocationPanel.Controls.Add (this.label10);
+ this._LocationPanel.Controls.Add (this.label3);
+ this._LocationPanel.Controls.Add (this._KeepYBox);
+ this._LocationPanel.Controls.Add (this._PageBox);
+ this._LocationPanel.Controls.Add (this._KeepXBox);
+ this._LocationPanel.Controls.Add (this.label5);
+ this._LocationPanel.Controls.Add (this._ZoomRateBox);
+ this._LocationPanel.Controls.Add (this._LeftBox);
+ this._LocationPanel.Controls.Add (this.label7);
+ this._LocationPanel.Controls.Add (this._TopBox);
+ this._LocationPanel.Controls.Add (this.label6);
+ this._LocationPanel.Controls.Add (this._RectanglePanel);
+ this._LocationPanel.Enabled = false;
+ this._LocationPanel.Location = new System.Drawing.Point (39, 42);
+ this._LocationPanel.Name = "_LocationPanel";
+ this._LocationPanel.Size = new System.Drawing.Size (372, 110);
+ this._LocationPanel.TabIndex = 11;
+ //
+ // label10
+ //
+ this.label10.AutoSize = true;
+ this.label10.Location = new System.Drawing.Point (173, 86);
+ this.label10.Name = "label10";
+ this.label10.Size = new System.Drawing.Size (95, 12);
+ this.label10.TabIndex = 11;
+ this.label10.Text = "(0:保持不变)";
+ //
+ // label3
+ //
+ this.label3.AutoSize = true;
+ this.label3.Location = new System.Drawing.Point (0, 5);
+ this.label3.Name = "label3";
+ this.label3.Size = new System.Drawing.Size (65, 12);
+ this.label3.TabIndex = 0;
+ this.label3.Text = "目标页面:";
+ //
+ // _KeepYBox
+ //
+ this._KeepYBox.AutoSize = true;
+ this._KeepYBox.Location = new System.Drawing.Point (145, 57);
+ this._KeepYBox.Name = "_KeepYBox";
+ this._KeepYBox.Size = new System.Drawing.Size (48, 16);
+ this._KeepYBox.TabIndex = 7;
+ this._KeepYBox.Text = "默认";
+ this._KeepYBox.UseVisualStyleBackColor = true;
+ this._KeepYBox.CheckedChanged += new System.EventHandler (this.Control_ValueChanged);
+ //
+ // _PageBox
+ //
+ this._PageBox.Location = new System.Drawing.Point (71, 3);
+ this._PageBox.Maximum = new decimal (new int[] {
+ 9999999,
+ 0,
+ 0,
+ 0});
+ this._PageBox.Minimum = new decimal (new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ this._PageBox.Name = "_PageBox";
+ this._PageBox.Size = new System.Drawing.Size (68, 21);
+ this._PageBox.TabIndex = 1;
+ this._PageBox.Value = new decimal (new int[] {
+ 1,
+ 0,
+ 0,
+ 0});
+ //
+ // _KeepXBox
+ //
+ this._KeepXBox.AutoSize = true;
+ this._KeepXBox.Location = new System.Drawing.Point (145, 30);
+ this._KeepXBox.Name = "_KeepXBox";
+ this._KeepXBox.Size = new System.Drawing.Size (48, 16);
+ this._KeepXBox.TabIndex = 4;
+ this._KeepXBox.Text = "默认";
+ this._KeepXBox.UseVisualStyleBackColor = true;
+ this._KeepXBox.CheckedChanged += new System.EventHandler (this.Control_ValueChanged);
+ //
+ // label5
+ //
+ this.label5.AutoSize = true;
+ this.label5.Location = new System.Drawing.Point (12, 31);
+ this.label5.Name = "label5";
+ this.label5.Size = new System.Drawing.Size (53, 12);
+ this.label5.TabIndex = 2;
+ this.label5.Text = "横坐标:";
+ //
+ // _ZoomRateBox
+ //
+ this._ZoomRateBox.FormattingEnabled = true;
+ this._ZoomRateBox.Location = new System.Drawing.Point (71, 83);
+ this._ZoomRateBox.Name = "_ZoomRateBox";
+ this._ZoomRateBox.Size = new System.Drawing.Size (96, 20);
+ this._ZoomRateBox.TabIndex = 10;
+ this._ZoomRateBox.SelectedIndexChanged += new System.EventHandler (this.Control_ValueChanged);
+ //
+ // _LeftBox
+ //
+ this._LeftBox.DecimalPlaces = 2;
+ this._LeftBox.Location = new System.Drawing.Point (71, 29);
+ this._LeftBox.Maximum = new decimal (new int[] {
+ 10000,
+ 0,
+ 0,
+ 0});
+ this._LeftBox.Minimum = new decimal (new int[] {
+ 10000,
+ 0,
+ 0,
+ -2147483648});
+ this._LeftBox.Name = "_LeftBox";
+ this._LeftBox.Size = new System.Drawing.Size (68, 21);
+ this._LeftBox.TabIndex = 3;
+ //
+ // label7
+ //
+ this.label7.AutoSize = true;
+ this.label7.Location = new System.Drawing.Point (2, 86);
+ this.label7.Name = "label7";
+ this.label7.Size = new System.Drawing.Size (65, 12);
+ this.label7.TabIndex = 9;
+ this.label7.Text = "缩放比例:";
+ //
+ // _TopBox
+ //
+ this._TopBox.DecimalPlaces = 2;
+ this._TopBox.Location = new System.Drawing.Point (71, 56);
+ this._TopBox.Maximum = new decimal (new int[] {
+ 10000,
+ 0,
+ 0,
+ 0});
+ this._TopBox.Minimum = new decimal (new int[] {
+ 10000,
+ 0,
+ 0,
+ -2147483648});
+ this._TopBox.Name = "_TopBox";
+ this._TopBox.Size = new System.Drawing.Size (68, 21);
+ this._TopBox.TabIndex = 6;
+ //
+ // label6
+ //
+ this.label6.AutoSize = true;
+ this.label6.Location = new System.Drawing.Point (12, 58);
+ this.label6.Name = "label6";
+ this.label6.Size = new System.Drawing.Size (53, 12);
+ this.label6.TabIndex = 5;
+ this.label6.Text = "纵坐标:";
+ //
+ // _RectanglePanel
+ //
+ this._RectanglePanel.Controls.Add (this.label8);
+ this._RectanglePanel.Controls.Add (this._WidthBox);
+ this._RectanglePanel.Controls.Add (this.label9);
+ this._RectanglePanel.Controls.Add (this._HeightBox);
+ this._RectanglePanel.Enabled = false;
+ this._RectanglePanel.Location = new System.Drawing.Point (229, 27);
+ this._RectanglePanel.Name = "_RectanglePanel";
+ this._RectanglePanel.Size = new System.Drawing.Size (128, 56);
+ this._RectanglePanel.TabIndex = 8;
+ //
+ // label8
+ //
+ this.label8.AutoSize = true;
+ this.label8.Location = new System.Drawing.Point (3, 4);
+ this.label8.Name = "label8";
+ this.label8.Size = new System.Drawing.Size (41, 12);
+ this.label8.TabIndex = 0;
+ this.label8.Text = "宽度:";
+ //
+ // _WidthBox
+ //
+ this._WidthBox.DecimalPlaces = 2;
+ this._WidthBox.Location = new System.Drawing.Point (54, 2);
+ this._WidthBox.Maximum = new decimal (new int[] {
+ 10000,
+ 0,
+ 0,
+ 0});
+ this._WidthBox.Name = "_WidthBox";
+ this._WidthBox.Size = new System.Drawing.Size (68, 21);
+ this._WidthBox.TabIndex = 1;
+ //
+ // label9
+ //
+ this.label9.AutoSize = true;
+ this.label9.Location = new System.Drawing.Point (3, 31);
+ this.label9.Name = "label9";
+ this.label9.Size = new System.Drawing.Size (41, 12);
+ this.label9.TabIndex = 2;
+ this.label9.Text = "高度:";
+ //
+ // _HeightBox
+ //
+ this._HeightBox.DecimalPlaces = 2;
+ this._HeightBox.Location = new System.Drawing.Point (54, 29);
+ this._HeightBox.Maximum = new decimal (new int[] {
+ 10000,
+ 0,
+ 0,
+ 0});
+ this._HeightBox.Name = "_HeightBox";
+ this._HeightBox.Size = new System.Drawing.Size (68, 21);
+ this._HeightBox.TabIndex = 3;
+ //
+ // _ActionBox
+ //
+ this._ActionBox.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this._ActionBox.FormattingEnabled = true;
+ this._ActionBox.Location = new System.Drawing.Point (49, 35);
+ this._ActionBox.Name = "_ActionBox";
+ this._ActionBox.Size = new System.Drawing.Size (156, 20);
+ this._ActionBox.TabIndex = 6;
+ this._ActionBox.SelectedIndexChanged += new System.EventHandler (this.Control_ValueChanged);
+ //
+ // label2
+ //
+ this.label2.AutoSize = true;
+ this.label2.Location = new System.Drawing.Point (6, 38);
+ this.label2.Name = "label2";
+ this.label2.Size = new System.Drawing.Size (41, 12);
+ this.label2.TabIndex = 5;
+ this.label2.Text = "动作:";
+ //
+ // _TitleBox
+ //
+ this._TitleBox.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._TitleBox.Location = new System.Drawing.Point (49, 10);
+ this._TitleBox.Name = "_TitleBox";
+ this._TitleBox.Size = new System.Drawing.Size (374, 21);
+ this._TitleBox.TabIndex = 1;
+ //
+ // label1
+ //
+ this.label1.AutoSize = true;
+ this.label1.Location = new System.Drawing.Point (6, 13);
+ this.label1.Name = "label1";
+ this.label1.Size = new System.Drawing.Size (41, 12);
+ this.label1.TabIndex = 0;
+ this.label1.Text = "名称:";
+ //
+ // tabControl1
+ //
+ this.tabControl1.Controls.Add (this.tabPage1);
+ this.tabControl1.Controls.Add (this.tabPage2);
+ this.tabControl1.Location = new System.Drawing.Point (12, 12);
+ this.tabControl1.Name = "tabControl1";
+ this.tabControl1.SelectedIndex = 0;
+ this.tabControl1.Size = new System.Drawing.Size (437, 330);
+ this.tabControl1.TabIndex = 8;
+ //
+ // tabPage1
+ //
+ this.tabPage1.Controls.Add (this._DefaultOpenBox);
+ this.tabPage1.Controls.Add (this._TitleBox);
+ this.tabPage1.Controls.Add (this.label2);
+ this.tabPage1.Controls.Add (this.label1);
+ this.tabPage1.Controls.Add (this._ActionBox);
+ this.tabPage1.Controls.Add (this._DestinationPanel);
+ this.tabPage1.Controls.Add (this._ScriptBox);
+ this.tabPage1.Location = new System.Drawing.Point (4, 22);
+ this.tabPage1.Name = "tabPage1";
+ this.tabPage1.Padding = new System.Windows.Forms.Padding (3);
+ this.tabPage1.Size = new System.Drawing.Size (429, 304);
+ this.tabPage1.TabIndex = 0;
+ this.tabPage1.Text = "常规";
+ this.tabPage1.UseVisualStyleBackColor = true;
+ //
+ // _DefaultOpenBox
+ //
+ this._DefaultOpenBox.AutoSize = true;
+ this._DefaultOpenBox.Location = new System.Drawing.Point (211, 37);
+ this._DefaultOpenBox.Name = "_DefaultOpenBox";
+ this._DefaultOpenBox.Size = new System.Drawing.Size (96, 16);
+ this._DefaultOpenBox.TabIndex = 9;
+ this._DefaultOpenBox.Text = "默认打开书签";
+ this._DefaultOpenBox.UseVisualStyleBackColor = true;
+ //
+ // _ScriptBox
+ //
+ this._ScriptBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._ScriptBox.Controls.Add (this._ScriptContentBox);
+ this._ScriptBox.Location = new System.Drawing.Point (348, 37);
+ this._ScriptBox.Name = "_ScriptBox";
+ this._ScriptBox.Size = new System.Drawing.Size (75, 49);
+ this._ScriptBox.TabIndex = 8;
+ this._ScriptBox.TabStop = false;
+ this._ScriptBox.Text = "脚本内容";
+ this._ScriptBox.Visible = false;
+ //
+ // _ScriptContentBox
+ //
+ this._ScriptContentBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._ScriptContentBox.Location = new System.Drawing.Point (6, 20);
+ this._ScriptContentBox.Multiline = true;
+ this._ScriptContentBox.Name = "_ScriptContentBox";
+ this._ScriptContentBox.Size = new System.Drawing.Size (63, 23);
+ this._ScriptContentBox.TabIndex = 16;
+ //
+ // tabPage2
+ //
+ this.tabPage2.Controls.Add (this._AttributesBox);
+ this.tabPage2.Location = new System.Drawing.Point (4, 22);
+ this.tabPage2.Name = "tabPage2";
+ this.tabPage2.Padding = new System.Windows.Forms.Padding (3);
+ this.tabPage2.Size = new System.Drawing.Size (429, 304);
+ this.tabPage2.TabIndex = 1;
+ this.tabPage2.Text = "属性";
+ this.tabPage2.UseVisualStyleBackColor = true;
+ //
+ // _AttributesBox
+ //
+ this._AttributesBox.AllColumns.Add (this._AttrNameColumn);
+ this._AttributesBox.AllColumns.Add (this._AttrValueColumn);
+ this._AttributesBox.Columns.AddRange (new System.Windows.Forms.ColumnHeader[] {
+ this._AttrNameColumn,
+ this._AttrValueColumn});
+ this._AttributesBox.GridLines = true;
+ this._AttributesBox.Location = new System.Drawing.Point (6, 6);
+ this._AttributesBox.Name = "_AttributesBox";
+ this._AttributesBox.ShowGroups = false;
+ this._AttributesBox.Size = new System.Drawing.Size (417, 293);
+ this._AttributesBox.TabIndex = 0;
+ this._AttributesBox.UseCompatibleStateImageBehavior = false;
+ this._AttributesBox.View = System.Windows.Forms.View.Details;
+ //
+ // _AttrNameColumn
+ //
+ this._AttrNameColumn.Text = "属性名称";
+ //
+ // _AttrValueColumn
+ //
+ this._AttrValueColumn.FillsFreeSpace = true;
+ this._AttrValueColumn.Text = "属性值";
+ //
+ // ActionEditorForm
+ //
+ this.AcceptButton = this._OkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF (6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.CancelButton = this._CancelButton;
+ this.ClientSize = new System.Drawing.Size (461, 383);
+ this.Controls.Add (this._CancelButton);
+ this.Controls.Add (this._OkButton);
+ this.Controls.Add (this.tabControl1);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog;
+ this.Icon = ((System.Drawing.Icon)(resources.GetObject ("$this.Icon")));
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "ActionEditorForm";
+ this.ShowInTaskbar = false;
+ this.Text = "链接属性编辑器";
+ this._DestinationPanel.ResumeLayout (false);
+ this._DestinationPanel.PerformLayout ();
+ this._PathPanel.ResumeLayout (false);
+ this._PathPanel.PerformLayout ();
+ this._LocationPanel.ResumeLayout (false);
+ this._LocationPanel.PerformLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._PageBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._LeftBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._TopBox)).EndInit ();
+ this._RectanglePanel.ResumeLayout (false);
+ this._RectanglePanel.PerformLayout ();
+ ((System.ComponentModel.ISupportInitialize)(this._WidthBox)).EndInit ();
+ ((System.ComponentModel.ISupportInitialize)(this._HeightBox)).EndInit ();
+ this.tabControl1.ResumeLayout (false);
+ this.tabPage1.ResumeLayout (false);
+ this.tabPage1.PerformLayout ();
+ this._ScriptBox.ResumeLayout (false);
+ this._ScriptBox.PerformLayout ();
+ this.tabPage2.ResumeLayout (false);
+ ((System.ComponentModel.ISupportInitialize)(this._AttributesBox)).EndInit ();
+ this.ResumeLayout (false);
+
+ }
+
+ #endregion
+
+ private System.Windows.Forms.Button _OkButton;
+ private System.Windows.Forms.Button _CancelButton;
+ private System.Windows.Forms.GroupBox _DestinationPanel;
+ private System.Windows.Forms.ComboBox _ActionBox;
+ private System.Windows.Forms.Label label2;
+ private System.Windows.Forms.TextBox _TitleBox;
+ private System.Windows.Forms.Label label1;
+ private System.Windows.Forms.NumericUpDown _PageBox;
+ private System.Windows.Forms.Label label3;
+ private System.Windows.Forms.CheckBox _NewWindowBox;
+ private System.Windows.Forms.TextBox _PathBox;
+ private System.Windows.Forms.Label label4;
+ private System.Windows.Forms.Label label5;
+ private System.Windows.Forms.CheckBox _KeepYBox;
+ private System.Windows.Forms.CheckBox _KeepXBox;
+ private System.Windows.Forms.ComboBox _ZoomRateBox;
+ private System.Windows.Forms.Label label7;
+ private System.Windows.Forms.NumericUpDown _TopBox;
+ private System.Windows.Forms.Label label6;
+ private System.Windows.Forms.NumericUpDown _LeftBox;
+ private System.Windows.Forms.NumericUpDown _HeightBox;
+ private System.Windows.Forms.Label label9;
+ private System.Windows.Forms.NumericUpDown _WidthBox;
+ private System.Windows.Forms.Label label8;
+ private System.Windows.Forms.TextBox _NamedBox;
+ private System.Windows.Forms.RadioButton _GotoNamedDestBox;
+ private System.Windows.Forms.RadioButton _GotoLocationBox;
+ private System.Windows.Forms.Panel _LocationPanel;
+ private System.Windows.Forms.Panel _PathPanel;
+ private System.Windows.Forms.Panel _RectanglePanel;
+ private System.Windows.Forms.Label label10;
+ private System.Windows.Forms.TabControl tabControl1;
+ private System.Windows.Forms.TabPage tabPage1;
+ private System.Windows.Forms.TabPage tabPage2;
+ private BrightIdeasSoftware.ObjectListView _AttributesBox;
+ private BrightIdeasSoftware.OLVColumn _AttrNameColumn;
+ private BrightIdeasSoftware.OLVColumn _AttrValueColumn;
+ private System.Windows.Forms.TextBox _ScriptContentBox;
+ private System.Windows.Forms.GroupBox _ScriptBox;
+ private System.Windows.Forms.CheckBox _DefaultOpenBox;
+ }
+}
+
diff --git a/pdfpatcher/App/Functions/Editor/ActionEditorForm.cs b/pdfpatcher/App/Functions/Editor/ActionEditorForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..6516b5aa82cddaa0a9cb7af51a264c8555edd7e1
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/ActionEditorForm.cs
@@ -0,0 +1,249 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Data;
+using System.Drawing;
+using System.Text;
+using System.Windows.Forms;
+using System.Xml;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+using PDFPatcher.Processor;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class ActionEditorForm : System.Windows.Forms.Form
+ {
+ const string KeepZoomRate = "保持不变";
+ const string NoAction = "无";
+ public BookmarkElement Action { get; private set; }
+ internal UndoActionGroup UndoActions { get; private set; }
+
+ public ActionEditorForm(BookmarkElement element) {
+ InitializeComponent();
+ Action = element;
+ _ActionBox.Items.AddRange(Constants.ActionType.Names);
+ _ActionBox.Items.Add(NoAction);
+ _ZoomRateBox.Items.AddRange(Constants.DestinationAttributes.ViewType.Names);
+ _ZoomRateBox.Items.AddRange(new string[] { "————————", "4", "3", "2", "1.5", "1.3", "1.2", "1", "0", "0.9", "0.8", "0.5", "0.3" });
+
+ int i = Array.IndexOf(Constants.ActionType.Names, element.GetAttribute(Constants.DestinationAttributes.Action));
+ _ActionBox.SelectedIndex = (i != -1 ? i : 0);
+ if (_ActionBox.SelectedIndex == 0 && element.HasAttribute(Constants.DestinationAttributes.Page) == false && element.HasAttribute(Constants.DestinationAttributes.Named) == false) {
+ _ActionBox.SelectedItem = NoAction;
+ _DestinationPanel.Enabled = false;
+ }
+ _DefaultOpenBox.Checked = element.IsOpen;
+ i = Array.IndexOf(Constants.DestinationAttributes.ViewType.Names, element.GetAttribute(Constants.DestinationAttributes.View));
+ _ZoomRateBox.SelectedIndex = (i != -1 ? i : 0);
+ i = _ZoomRateBox.FindString(Constants.DestinationAttributes.ViewType.XYZ);
+ if (i != -1) {
+ _ZoomRateBox.Items[i] = KeepZoomRate;
+ }
+
+ if (_ZoomRateBox.Text == Constants.DestinationAttributes.ViewType.XYZ
+ && element.GetAttribute(Constants.Coordinates.ScaleFactor).TryParse(out float f)) {
+ _ZoomRateBox.SelectedIndex = -1;
+ _ZoomRateBox.Text = f.ToText();
+ }
+ _TitleBox.Text = element.GetAttribute(Constants.BookmarkAttributes.Title);
+ _PathBox.Text = element.GetAttribute(Constants.DestinationAttributes.Path);
+ _NewWindowBox.Checked = element.GetAttribute(Constants.DestinationAttributes.NewWindow) == Constants.Boolean.True;
+ _NamedBox.Text = element.GetAttribute(Constants.DestinationAttributes.Named);
+ _GotoNamedDestBox.Checked = String.IsNullOrEmpty(_NamedBox.Text) == false;
+ _GotoLocationBox.Checked = element.HasAttribute(Constants.DestinationAttributes.Named) == false
+ && element.HasAttribute(Constants.DestinationAttributes.NamedN) == false;
+
+ InitCoordinateValue(element, Constants.DestinationAttributes.Page, _PageBox, null);
+ InitCoordinateValue(element, Constants.Coordinates.Left, _LeftBox, _KeepXBox);
+ InitCoordinateValue(element, Constants.Coordinates.Top, _TopBox, _KeepYBox);
+ InitCoordinateValue(element, Constants.Coordinates.Right, _WidthBox, null);
+ _ScriptContentBox.Text = element.GetAttribute(Constants.DestinationAttributes.ScriptContent);
+ if (_WidthBox.Enabled) {
+ var v = _WidthBox.Value - _LeftBox.Value;
+ if (v > _WidthBox.Maximum) {
+ v = _WidthBox.Maximum;
+ }
+ else if (v < _WidthBox.Minimum) {
+ v = _WidthBox.Minimum;
+ }
+ _WidthBox.Value = v;
+ }
+ InitCoordinateValue(element, Constants.Coordinates.Bottom, _HeightBox, null);
+ if (_HeightBox.Enabled) {
+ var v = _TopBox.Value - _HeightBox.Value;
+ if (v > _HeightBox.Maximum) {
+ v = _HeightBox.Maximum;
+ }
+ else if (v < _HeightBox.Minimum) {
+ v = _HeightBox.Minimum;
+ }
+ _HeightBox.Value = v;
+ }
+ _AttrNameColumn.AspectGetter = (object o) => o is XmlAttribute attr ? attr.Name : (object)null;
+ _AttrValueColumn.AspectGetter = (object o) => {
+ if (o is XmlAttribute attr) {
+ if (attr.Name == Constants.Font.ThisName && attr.Value.TryParse(out int fid)) {
+ var n = attr.OwnerDocument.DocumentElement.SelectSingleNode(
+ String.Concat(Constants.Font.DocumentFont, "/", Constants.Font.ThisName,
+ "[@", Constants.Font.ID, "='", attr.Value, "']/@", Constants.Font.Name)
+ );
+ if (n != null) {
+ return String.Concat(attr.Value, " (", n.Value, ")");
+ }
+ }
+ return attr.Value;
+ }
+ return null;
+ };
+ _AttributesBox.ScaleColumnWidths();
+ _AttributesBox.SetObjects(element.Attributes);
+ }
+
+ void InitCoordinateValue(XmlElement element, string name, NumericUpDown control, CheckBox check) {
+ if (element.HasAttribute(name)) {
+ var s = element.GetAttribute(name);
+ if (s.TryParse(out decimal x)) {
+ control.SetValue(x);
+ }
+ else if (check != null) {
+ check.Checked = true;
+ }
+ }
+ else if (check != null) {
+ check.Checked = true;
+ }
+ }
+
+ void SetValue(string name, string value) {
+ if (UndoActions == null) {
+ UndoActions = new UndoActionGroup();
+ }
+ bool a = Action.HasAttribute(name);
+ if ((value == null && a == false)
+ || (a && Action.GetAttribute(name) == value)) {
+ return;
+ }
+ UndoActions.Add(UndoAttributeAction.GetUndoAction(Action, name, value));
+ }
+
+ void _OkButton_Click(object source, EventArgs args) {
+ if (String.IsNullOrEmpty(_TitleBox.Text) == false) {
+ SetValue(Constants.BookmarkAttributes.Title, _TitleBox.Text);
+ }
+ var act = _ActionBox.SelectedItem as string;
+ if (act == NoAction) {
+ act = null;
+ }
+ SetValue(Constants.DestinationAttributes.Action, act);
+ SetValue(Constants.BookmarkAttributes.Open, _DefaultOpenBox.Checked ? Constants.Boolean.True : null);
+ if (act == null) {
+ SetValue(Constants.DestinationAttributes.Page, null);
+ }
+ else if (_ScriptBox.Visible) {
+ SetValue(Constants.DestinationAttributes.ScriptContent, _ScriptContentBox.Text);
+ }
+ else if (_GotoLocationBox.Checked) {
+ SetValue(Constants.DestinationAttributes.Page, _PageBox.Value.ToText());
+ if (_ZoomRateBox.Text.TryParse(out float f)) {
+ SetValue(Constants.DestinationAttributes.View, Constants.DestinationAttributes.ViewType.XYZ);
+ SetValue(Constants.Coordinates.ScaleFactor, f.ToText());
+ }
+ else if (_ZoomRateBox.Text == KeepZoomRate) {
+ SetValue(Constants.DestinationAttributes.View, Constants.DestinationAttributes.ViewType.XYZ);
+ SetValue(Constants.Coordinates.ScaleFactor, null);
+ }
+ else {
+ SetValue(Constants.DestinationAttributes.View, _ZoomRateBox.Text);
+ }
+ if (_LeftBox.Enabled || _KeepXBox.Enabled) {
+ SetValue(Constants.Coordinates.Left, _KeepXBox.Checked ? null : _LeftBox.Value.ToText());
+ }
+ if (_TopBox.Enabled || _KeepYBox.Enabled) {
+ SetValue(Constants.Coordinates.Top, _KeepYBox.Checked ? null : _TopBox.Value.ToText());
+ }
+ if (_RectanglePanel.Enabled) {
+ SetValue(Constants.Coordinates.Right, (_LeftBox.Value + _WidthBox.Value).ToText());
+ SetValue(Constants.Coordinates.Bottom, (_TopBox.Value - _HeightBox.Value).ToText());
+ }
+ }
+ else if (_GotoNamedDestBox.Checked) {
+ SetValue(Constants.DestinationAttributes.Named, _NamedBox.Text);
+ }
+ if (_PathPanel.Enabled) {
+ SetValue(Constants.DestinationAttributes.Path, _PathBox.Text);
+ if (_NewWindowBox.Enabled) {
+ SetValue(Constants.DestinationAttributes.NewWindow, _NewWindowBox.Checked ? Constants.Boolean.True : Constants.Boolean.False);
+ }
+ }
+ DialogResult = DialogResult.OK;
+ Close();
+ }
+
+ void _CancelButton_Click(Object source, EventArgs args) {
+ DialogResult = DialogResult.Cancel;
+ Close();
+ }
+
+ void Control_ValueChanged(object sender, EventArgs e) {
+ if (sender == _ActionBox) {
+ var i = _ActionBox.SelectedItem as string;
+ if (i == Constants.ActionType.Javascript) {
+ _ScriptBox.Parent = _DestinationPanel.Parent;
+ _ScriptBox.Top = _DestinationPanel.Top;
+ _ScriptBox.Left = _DestinationPanel.Left;
+ _ScriptBox.Size = _DestinationPanel.Size;
+ _ScriptBox.Visible = true;
+ _DestinationPanel.Visible = false;
+ }
+ else {
+ _DestinationPanel.Visible = true;
+ _DestinationPanel.Enabled = i != NoAction && i != Constants.ActionType.Javascript;
+ }
+ if (_DestinationPanel.Enabled) {
+ _NewWindowBox.Enabled = ValueHelper.IsInCollection(i, Constants.ActionType.GotoR, Constants.ActionType.Uri);
+ _PathPanel.Enabled = ValueHelper.IsInCollection(i, Constants.ActionType.GotoR, Constants.ActionType.Launch, Constants.ActionType.Uri);
+ }
+ }
+ else if (sender == _GotoLocationBox || sender == _GotoNamedDestBox) {
+ _LocationPanel.Enabled = _GotoLocationBox.Checked;
+ _NamedBox.Enabled = _GotoNamedDestBox.Checked;
+ }
+ else if (sender == _KeepXBox) {
+ _LeftBox.Enabled = !_KeepXBox.Checked;
+ }
+ else if (sender == _KeepYBox) {
+ _TopBox.Enabled = !_KeepYBox.Checked;
+ }
+ else if (sender == _ZoomRateBox) {
+ switch (_ZoomRateBox.Text) {
+ case Constants.DestinationAttributes.ViewType.XYZ:
+ case "保持不变":
+ goto default;
+ case Constants.DestinationAttributes.ViewType.Fit:
+ case Constants.DestinationAttributes.ViewType.FitB:
+ _TopBox.Enabled = _LeftBox.Enabled = _KeepXBox.Enabled = _KeepYBox.Enabled = _RectanglePanel.Enabled = false;
+ break;
+ case Constants.DestinationAttributes.ViewType.FitBH:
+ case Constants.DestinationAttributes.ViewType.FitH:
+ _TopBox.Enabled = _KeepYBox.Enabled = true;
+ _LeftBox.Enabled = _KeepXBox.Enabled = _RectanglePanel.Enabled = false;
+ break;
+ case Constants.DestinationAttributes.ViewType.FitBV:
+ case Constants.DestinationAttributes.ViewType.FitV:
+ _LeftBox.Enabled = _KeepXBox.Enabled = true;
+ _TopBox.Enabled = _KeepYBox.Enabled = _RectanglePanel.Enabled = false;
+ break;
+ case Constants.DestinationAttributes.ViewType.FitR:
+ _TopBox.Enabled = _LeftBox.Enabled = _RectanglePanel.Enabled = true;
+ _KeepXBox.Enabled = _KeepYBox.Enabled = false;
+ break;
+ default:
+ _TopBox.Enabled = _LeftBox.Enabled = _KeepXBox.Enabled = _KeepYBox.Enabled = true;
+ _RectanglePanel.Enabled = false;
+ break;
+ }
+ }
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/Editor/ActionEditorForm.resx b/pdfpatcher/App/Functions/Editor/ActionEditorForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..6fb070e3c60fbba3724bd90c0eb3884e12b23e10
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/ActionEditorForm.resx
@@ -0,0 +1,3251 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+
+
+ AAABAAcAEBAAAAAAAABoBAAAdgAAACAgAAAAAAAAqAgAAN4EAABAQAAAAAAAAChCAACGDQAAwMAAAAAA
+ AAAoUgIArk8AABAQAAAAAAAAaAQAANahAgAgIAAAAAAAAKgQAAA+pgIAMDAAAAAAAACoJQAA5rYCACgA
+ AAAQAAAAIAAAAAEAIAAAAAAAAAQAACMuAAAjLgAAAAAAAAAAAAAAAAAAAAAAACwsDGUqKguHKioLhyoq
+ C4cxPCCNToRyqGzQydV049/kb9fR2lmfkbZCZlCcQWNLeH///xl///8LAAAAAAAAAAA4OBeC////////
+ ///+////9P/+/8H+/v+7zP7//gj//7fb/f+O//7/pP/9/3DWz9V///+Kf///QQAAAAAAAAAASUkme///
+ ///+////+P7+/+H9/f+s/v7/ldT///8A///dSP//f////4P4//+qlfDuorn/9X///50AAAAAAAAAAFRU
+ L3f+////x8/A/7bZzf+h8uz/iPr4/4ns////AP///wD//+BT/v/4FP///wD//7KZ//d///+yAAAAAAAA
+ AABYWDN2/P/+/9rw4v+t+PD/s+Hy/62r/v/fb/3//wD///8A////AP///wD//8du/v1////yf///iAAA
+ qI0AAKT/AACi/wMGov8dO7T/YKvi//sA/v//AP///wD///8A////AP///wD///gQ//+F9P//f///53//
+ /2oAAK7/AACu/wAAsf8CBLL/Fy+//1Ch4f9om+f/paX8/7VM8f//AP///wD///8A////AP//1VL+/X//
+ //N///+LAAC1/wAAuf/h4f//kpPn/09Y1P83XNH/U6Xk/3Hj9v+J7P///wD///8A///ZUfv/9xT///8A
+ //+7iP/3f///sgAAvv8AAMf/UVHe/93d/f+io/D/wcj3/9Lt//97zPH/ldT///8A///rQ/j/f////4P4
+ //+sn/n0orn/83///5YAAMb/AADS/wAA1f9nZ+j/YWHl/8fH9/9FT9n/O3fb/4+5+f/3EP//lNr8/4j3
+ 9f+f/Pf/fOXezn///4l///87AADN/wAA2v8AAN7/LS3l/9PT+v9kZOf/BgzR/yRI1P9Wrej/kfz6/5v5
+ 9f+78Ob/3fTn/3WXeYB///8Zf///CwAA0f8AAOD/AADm/wUF6P/+/v//ICDh/wED1f8KFM3/GzfL/8nv
+ 5P/Q697/3efX//Dy4f90eFFtf///An///wEAANX/AADj/wAA6v8AAOz/AADn/wAA3/8AANb/AQLL/wIF
+ wv/k59b/o6WV/6SllP+kpJP/SUklfAAAAAAAAAAAAADOjQAA2P8AANv/AADc/wAA2f8AANX/AADQ/wAA
+ yv9+fs3/5eXU/7a2pf//////enpRaHp6USUAAAAAAAAAAAAAAAAAAAAAfX1TZ/z89f/5+e//9vbq//T0
+ 5f/z8+L/8vLh//Ly4f/CwrH/fX1TZ319UyUAAAAAAAAAAAAAAAAAAAAAAAAAAH9/VU1/f1Vmf39VZn9/
+ VWZ/f1Vmf39VZn9/VWZ/f1Vmf39VZn9/VSQAAAAAAAAAAAAAAAAAAAAA4Af//8AB4AfgAMAB4ADgAOAA
+ 4AAAAeAAAAAAAQAAAAAAAAAAAAEAAAADAAEABwADAAcABwAPAAfgHwAP///gHygAAAAgAAAAQAAAAAEA
+ CAAAAAAAAAQAACMuAAAjLgAAAAAAAAAAAAAAAAAA5+foAOXl5gDj4+QA4ODgAN7e3gDb29wA2dnbANfX
+ 2gDT09QAzc3QAMfHzwDBwckAtra8AK6usADV1dYA2trcANjY2gDR0dEA0M/QAM7O0QDLy88AurrEAKmo
+ sACsq68A0tLSAN3d3QDc3N0As7O2AN/f3wBCP+wAOjjdAIeG6ACMjO0AionrAIiI6QDJyc8AzMzQAP7Z
+ /gD98v0AUU7pAKSj5ACop+AAn57lAJOS7ACYl+kAZ2bgAOHh4QD+v/4A/lbUAPr6+gD8+/wATEnvAGVj
+ 4wCpqckA3t7fANbW2gB+feQAhYTcAFJQ5wD+xv4A/gT9AO/u7gD+5v0A9vX1ADQy1wBAPeYAqanXALi3
+ wQA9O+AAnJviAG5t2ACioeQAX13jAP4a+AD+D/sAHx27ACUkwwAjIcEAWVmGAENCoAAyMLEAg4LZAElI
+ mgA9O6gAKCa2ACgnxQBwb90A/gf9AO3s6wAfHbcAWlqEAFpZggBWU3wAUlGQAP4u6wDx8fEAOzmsADo4
+ rQA5NqwA/iLzAPLy8gALBhIALiy1ADYzqwBNTJYAqKi0AO/v8AD+BvwA+fn5AFZOcwCxsbQA/kHdAPX0
+ 9AD+y8gA/szTAPDw8ADu7e0A7OrqAPj4+AD+w7kA/lgvAPf29QDz8/IA8fHwAL69ygD+MwAA/p6bAPv7
+ +wD+rpsA/qmYAEhE8AB1dOIA9PPzAMXFzAD+y98A/jUDAPxiPAD+PAwA+Pf2AEpH8ADk5OUA/k4iAO3r
+ 6gBFQu8A5ubnAP5BEgD+NgQA6unpAP4/DwD+kKIA/rOgAFdU4gBPTOoA/sa/AP34/ABEQO8Ae3niAP7A
+ swBcWd8AVlPhAFRS4wBiYOQAeHbhAGtq2gDi4uIA////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP//
+ /wD///8A////AP///wD///8A////AP///wD///8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACUQBhoFHR0JJQYDA6UvBAUaGxsG
+ BwkMAAAAAAAAAAAACQF2j1l1ATajFo1ZWY92AQGRjaUdB4YAAAAAAAAAAAAIj3U+a2BZnYOfhll0az51
+ j3YBkQMbJAAAAAAAAAAAAAd1dGB7cXsgoJ+kEGtlZXRrdXYBjQUlAAAAAAAAAAAXhgF7cUB6elmjHow6
+ hhoBdVkvEgwMGQoAAAAAAAAAAICAC3t6i3dtbXd9oplHahwNHBdHn58WCgAAAAAAAAAznoJ1CXdAAwcP
+ bTICnyg0mKChg4MoKH0UAAAAAAAAAACaiocPGgGAmwFZgG0rSYZSnJ05IC0VLxMAAAAAAAAAAHN+iTOL
+ l4mCi0AzgI2YR5kqcXFla3YvFAAAAAAAJBFZj35+iZV+ljOLMzMzdyIeLHp6cWVrdgQUAAAAADM+eH+J
+ fn5+fokzeoAzMzNtQ4wli3pxdHWUHRQAAAAzc4mSfn5+fn6TcwEGMoCAgHpGHkhxQGVrWQEdCgAAAAAz
+ MzNzgn5+fn6OjwcdbTJtYDqQOWBgdT52kQUlAAAAAAAAADOHfoiBiYp5fBI+d4tgOYxXWY0SDwGNBiQA
+ AAAAAAAAAHN+f4AzcYGCcQF6emAgg4SFJicKBS8IhgAAAAAAAAAAeHltWWVAMjN6e3F7fH01DHEwMW0M
+ GyQUGw0AAAAAADNyc3RrdHR0dHR0dGs+dVl2YDw9MAEFdz8wYAAAAAAAbh0Fbxwcb28cHG9vb28WEAYd
+ Jj1KPzBwSzxxAAAAAGZnaGlpaWlpaWlpaWlpXmoQazMmPT1sPWwwbQAAAAAAVWFiYmJhYmNjYmJiYWFG
+ PzAxZD09PT09MGUAAAAAAABaWlpbWlpaXFtdWl5aWlI/MDFfPT09PT0wYBgAAAAAAExNTjpPUFFSQVJT
+ UlRVVlcqQDM/PT1YPT0wWRcAAAAAQUJCQzpELkNFRkcMSElCQkUTHSY9Sj8wMUs8LwAAAAA0NTUTNhEi
+ NzY4ORA2OjU1OxMaPD0wPgEzPzBAAAAAACghISkqKywqKi0sKiorISMuEy8wMTIlAAAAMwAAAAAAAB4f
+ ICEhISEiIiIjIyMgICQlBiYnBgAAAAAAAAAAAAAAAAAJBB0dBRobBgcRCA8ZFAwcAQUAAAAAAAAAAAAA
+ AAAAABkFGhsGBxEIDwkZExUMHBgMAAAAAAAAAAAAAAAAAAAADxARDwkSExQKFQsMFg4XGAAAAAAAAAAA
+ AAAAAAAAAAABAgMEBQYHCAkKCwwNDg4AAAAAAAAAAAAAAP/////8AAAP/AAAB/wAAAf8AAAH/AAAB/gA
+ AAf4AAAH8AAAB/gAAAf4AAAHwAAAB4AAAAcAAAAHgAAAB/AAAAf4AAAH+AAAAfAAAAHwAAAB4AAAA+AA
+ AAfgAAAD4AAAAeAAAAHgAAAB4AAAO/AAAH/8AAD//AAB//wAA//8AAf/KAAAAEAAAACAAAAAAQAgAAAA
+ AAAAQAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAOzs7AS0tLQctLS0MLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSws
+ LA0sLCwNLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSws
+ LA0sLCwNLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSwsLA0sLCwNLCwsDSws
+ LA0sLCwNLCwsDSwsLA0sLCwNLy8vCywsLAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA0AAAA7AAAAXQAAAGAAAABgAAAAYAAA
+ AGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAA
+ AGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAA
+ AGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAABgAAAAYQAAAFIAAAAkJycnAwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAwMYAwMDbQAA
+ AKsAAACyAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAA
+ ALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAA
+ ALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALIAAACYAAAAQC8v
+ LwUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAGBYWFoCjo6P0rKys9ampqfWrq6v1q6ur9aysrPWsrKz1ra2t9a2trfWurq71rq6u9a+v
+ r/Wurq71r6+v9a+vr/Wrq6v1q6ur9bCwsPW0tLT1tra29ba2tvW2trb1tbW19bW1tfW1tbX1tbW19bS0
+ tPW0tLT1s7Oz9bKysvWysrL1srKy9bGxsfWwsLD1r6+v9bGxsfWysrL1sbGx9bGxsfWxsbH1sLCw9a+v
+ r/WsrKz1rq6u8JiYmMxEREQSAAAAAP///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABcaGhqB2tra/+7u7v/t7e3/7+/v/+/v7//w8PD/8PDw//Ly
+ 8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Hx8f/o6Of/2tjc/9TU1v/c293/5OXn//Dx8P/08/P/8/Pz//Pz
+ 8//z8/P/8vLy//Ly8v/x8fH/8PDw//Dw8P/v7+//7u7u/+7u7v/t7e3/7Ozs/+vr6//q6ur/6enp/+np
+ 6f/o6Oj/6Ojo/+fn5//l5eX/4uLi/+Li4v/GxsbvSUlJFgAAAAD///8BAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXGRkZgdHR0f/l5eX/5OTk/+fn
+ 5//m5ub/5+fn/+jo6P/p6en/6urq/+rq6v/q6ur/6urq/+rq6v/j4+P/zczM/7e5rP+pqKT/tbit/8rK
+ xf/a2Nz/6Ojo/+rq6v/q6ur/6+vr/+rq6v/p6en/6Ojo/+jo6P/o6Oj/5+fn/+bm5v/l5eX/5OTk/+Tk
+ 5P/k5OT/4+Pj/+Hh4f/i4uL/4eHh/+Dg4P/e3t7/3Nzc/9nZ2f7Z2dn/v7+/6klJSRgAAAAA////AQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFxkZ
+ GYHU1NT/6urq/+jo6P/r6+v/7e3t/+3t7f/t7e3/7e3t/+7u7v/v7+//7+/v/+/v7//u7u7/4N/g/8HD
+ vf9racT/UEvd/2pnzf+pqLX/zs/I/+Hh4//s7e3/7+/v/+/v7//v7+//7u7u/+7u7v/t7e3/7e3t/+zs
+ 7P/r6+v/6+vr/+rq6v/p6en/6Ojo/+fn5//m5ub/5+fn/+Xl5f/k5OT/4+Pj/+Dg4P/c3Nz+3Nzc/8PD
+ w+tJSUkZAAAAAP///wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAABcZGRmB1tbW/+zs7P/r6+v/7e3t/+7u7v/u7u7/7+/v/+/v7//w8PD/8fHx//Hx
+ 8f/x8fL/8PDy/+jo3v+UlNP/ODT3/0M9//9IQP//WVTo/6ysvP/Y2dL/5ufp//Dw7//x8fH/8PDw//Dw
+ 8P/v7+//8PDw/+/v7//v7+//7u7u/+3t7f/s7Oz/7Ozs/+rq6v/p6en/6enp/+jo6P/n5+f/5eXl/+Xl
+ 5f/i4uL/3t7e/t7e3v/ExMTsSEhIGQAAAAD///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAXGRkZgdfX1//t7e3/7Ozs/+7u7v/v7+//7+/v//Dw
+ 8P/x8fH/8fHx//Pz8//z8/P/8/Pz//Hx8//w8OX/i4rk/1NS+/9IR9v/Skri/0hB//9VUef/sbO7/97e
+ 2v/r6+3/8vHx//Pz8//y8vL/8fHx//Hx8f/x8fH/8PDw/+/v7//u7u7/7u7u/+3t7f/s7Oz/6+vr/+vr
+ 6//p6en/6Ojo/+fn5//m5ub/4+Pj/9/f3/7f39//x8fH7kpKShwAAAAA////AQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQEBGBoaGoLY2Nj/7e3t/+3t
+ 7f/w8PD/8fHx//Hx8f/y8vL/8/Pz//Pz8//09PT/9PT0//X19f/y8vT//Pzu/42N7P8oIv//XFzb/46Q
+ ov9HRez/SED//2Jg2f/HyL//5eTm//Ly8v/09PT/9PT0//Pz8//y8vL/8vLy//Ly8v/x8fH/8PDw/+/v
+ 7//v7+//7u7u/+3t7f/r6+v/6+vr/+rq6v/p6en/6Ojo/+Xl5f/h4eH+4eHh/8jIyO5KSkocAAAAAP//
+ /wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzMzMAQAA
+ ABcWFhZ+3d3d//Hx8f/t7e3/8fHx//Ly8v/z8/P/9PT0//X19f/09PT/9fX1//b29v/39/f/9fT2//z8
+ 9P/My/L/My/4/zQu/v9pZ8v/eXqy/1JO9/9HQP7/hYXC/9bVyv/n5un/8PDw//T09P/19fX/8/Pz//T0
+ 9P/09PT/8/Pz//Ly8v/x8fH/8PDw/+/v7//u7u7/7e3t/+zs7P/q6uv/6Ojo/+fn5//k5OT/4eHh/uHh
+ 4f/JycnvSkpKHQAAAAD///8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA////AQAAAAATExMaMzMzksnJyf/q6ur/8vLy//Ly8v/09PT/9PT0//X19f/29vb/9vb2//b2
+ 9v/39/f/9/f3//b29v/19fj////0/6Sk8/81MfT/NDH8/1ZU3P9PTuH/UU79/0xG7f+hoq7/zMzJ/9zd
+ 3v/n5+f/7+/v//Ly8//z8/P/9vb2//X19f/z8/P/8vLy//Dx8P/v7u7/6+vr/+fn5//g4OD/2dna/9PT
+ 1P/V1db/19fX/9ra2v7h4eH/y8vL8UtLSx8AAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAC5ubkJnZ2dlr69vfG6ubn/srKy/+Pj4//29vb/9PT0//X1
+ 9f/29vb/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//f2+f////b/v774/09L9P8zLfr/MCz5/05L
+ 9v9RSv//X1zC/6OjlP+1tLb/wsLG/9LS0//c3d3/5eXl/+vr6//t7e3/7+/v//Dw8P/s7Oz/4uLj/9jX
+ 2f/My8//w8PF/7q6uP+4uLP/uLiz/769v//KzM3+3t7d/8zLy/FLS0sfAAAAAP///wIAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wIAAAAAw8PDhf///////////////9jY
+ 2P+vr6//7e3t//j4+P/29vb/9/f3//f39//39/f/+Pj4//n5+f/5+fn/+fn5//j5+f/6+fn/+fj7////
+ +f/l5vr/hIT1/0VA9/85Nff/WVT4/0pE9/9nZqD/lpiQ/66uov+3trD/u7u7/8LCxf/IyMr/0tLU/9bW
+ 1//X1tf/z87Q/7y+wP+ysav/qKmb/56gl/+Skpz/ioqc/4eImf+jpKH/wMC5/tfW2f/MzMzyTExLIAAA
+ AAD///8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3NvcGPz8
+ /PT////+/vr5/v//////////xcXF/8DAwP/5+fn/+Pj4//j4+P/5+fn/+Pj4//n5+f/5+fn/+/v7//7+
+ /v///////P38//r6+v/59/z////5////+//W1/j/dXT0/0ZE9/9aVPz/OjT7/0ZD2/9wbsb/kpS2/62u
+ rP+0taj/s7On/62upf+qqqb/qamo/6Wmnf+Yloz/c3SV/1pYsv9GQtj/OTTw/zs48f85NvD/Skbd/6+w
+ wP7Z2tb/zM3N9ExMTCIAAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8CAAAAAPPz8zP9/Pz///////9uSv//yLr///////r5+P+wsLD/2dnZ//z8/P/4+Pj/+fn5//n5
+ +f/9/f3//v7+//f39//p6en/4eHh//Hx8f/9/v3//Pv7//n6+v/6+fv////7////8P+Njuv/Ukz2/1BI
+ /f8/Of7/QDj//zw39v9QT+X/amfU/3Z5vf94eqH/goGN/4mLif9zcZ7/R0TN/zo09f9IQ///UlH8/2Bd
+ 8v9VU/D/RUH6/zcz/v+Xl9z+5ufa/8vLzvNNTUwiAAAAAP///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA////AgAAAADo5+ct+/r6////////Viz//0og///49v//////4+Pj/6+v
+ r//w8PD//f39//7+/v/8/Pz/7u7u/9nZ2f/Ozs7/zMvL/8PDw/+wsLD/3d3d//7////7+/v/+/v8//n5
+ /P/7/Pf/4ODs/11b8v9TSvv/T0rz/3Bu6/9hWPv/SUH+/z43//8+OP//Qj70/zQw6v8yLeX/Qj34/1JO
+ /v9YVfv/Pz71/0JC5/9QUeD/RUPo/0dA+/9aVPf/v77h/+np4P/Nzs/1TU1NJAAAAAD///8CAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wIAAAAA6ejoIfz6+fj//////3dV//8Z
+ AP//knX////////////Gxsb/vr6+//Pz8//i4uL/0dHR/9LS0v/k4uH/+fb2////////////5eXl/7a2
+ tv/y8vL//v7+//z8/P/9/f3/+Pr8///+8f+amez/TUr4/1FK+P+jpcn/zc7c/6ys6f+Df+P/ambi/0dB
+ /f83MP//Qz///0NA+/82Mvj/Pzj4/0M++f9KQ/v/T0f9/19V/v+Oh/j/yMjq/+fp4v/k4+X/z8/P901N
+ TSUAAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8BAAAAAPj4
+ +Bj++/vu//////+CYv7/JwH//zAD///Owf//////+vn5/7S0tP/Ix8f/3t3d//Lv7///////////////
+ ////9fP//vn3///////T09P/29vb///////8/Pz//f39//z7/f/9/fr/3N3r/11c8f9MRf//bGfk/83P
+ wv/S0Mf/vb2o/2Bdz/81MP7/Tk32/4iG8v+rqvT/oJ34/6Gg+P+kovf/qqj1/7a19v/MzfD/7e7s/+/w
+ 6v/j4+T/5OTk/87OzvZNTU0mAAAAAP///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/v7+Af//
+ /wH///8C////A////wH///8J//794v//////kHP+/yYA//8vAf//UCb///b0///////59vX//Pr5////
+ ///////////////Owf//gmX//0Ma///c0///////6Obm/+rq6v///////f39//39/f/9/f3/+/v+//39
+ 8f+Uk+n/Tkn3/0tF+P+RkbD/qaud/11Y0v88OP//Wlb4/5ub8//3+fL////2////9f////X//P3z//v8
+ 8P/6+/D/9ffv/+3t7v/p6Or/5OXk/+Pj4//Ozs75TU1NKAAAAAD///8CAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAAs7OzEfr29dz//////56F/v8kAP//Ogj//yUA//+M
+ bv//////////////////6eT//6WR//9bNv//MQD//xkA//+dhP///////////+zs7P/5+fn//v7+//z8
+ /P/9/f3//Pz8//z8/f/9/vr/1dPo/1pZ8f9MQv//YGC+/1tYw/88Nv//XVn2/7W07v////f/+fj3//T0
+ 9//19Pb/9PP1//Lx8//x8PP/8O/x/+/u8P/t7e3/6urp/+Tk5P/j4+P/zs7O+k1NTSkAAAAA////AgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADGxsYEq6urHKGhoT6ZmZlsn5+fl6ysrMHy7+35//39//+p
+ lP//JwD//zYE//80A///LQD//8O0///Lv///d1n//z0Q//8mAP//LgD//yYA//+Xff////////////f2
+ 9v/29vb///////39/f/9/f3//f39//z8/P/8/f3/+/v9//j47f+Cguv/TUj6/zw3+P82MPv/U0/5/6Cd
+ 7/////T/9/f5//j4+P/49/f/9vb3//X19f/09PT/8/Pz//Hx8v/w8PD/7e3t/+rq6v/l5eX/4uLi/87O
+ zvpNTU0pAAAAAP///wIAAAAAAAAAAAAAAAAAAAAA////AQAAAACdnZ1Op6enrLu6utrQz87y5uPj//bz
+ 8v//////////////////xrf//ykA//81Av//NAH//zEA//83BP//LwD//yYA//8xAP//Ogj//yYA//+G
+ aP////////7+//j39//19fX//v7+//39/f/+/v7///////7+/v/9/f3//fz9//z8/P/+/vf/vLzj/05K
+ 8v9KQ/3/Qj76/31+6v/y8+3/+fj4//n5+f/5+Pj/9/f3//b29v/19fX/9PPz//Ly8v/x8fH/7+/v/+zs
+ 7P/p6en/5OTk/+Li4v/Pz8/8Tk5OKwAAAAD///8CAAAAAAAAAAAAAAAAAAAAAAAAAACxsbFy7e3t+f/+
+ /f/////////////////////9/////v/v6///0sf//4tu//8uAP//NAL//zMA//80AP//MgD//zQB//82
+ A///NwT//yQA//94Vv/////////+//n4+P/09PT//v7+//39/f/8/Pz//f39//39/f/9/f3//Pz8//z8
+ /P/9/f3/+fn5/97f3f9hYuf/TEb8/0NA9v/Bw9b/9/by//j4+v/5+fj/+Pj4//f39//29vb/9fX1//Pz
+ 8//y8vL/8fHx/+/v7//s7Oz/6enp/+Pj4//h4eH/zs7O/E5OTiwAAAAA////AgAAAAAAAAAAAAAAAAAA
+ AADj4+Mi+fn59v/////////8//79/v7h2f7+uKf//45y//9kPf//RBb//y4A//8qAP//NAD//zMA//8z
+ AP//MwD//zQB//8zAP//NQL//ygA//9pRP//+/r///////38/P/z8/P//f39//39/f/9/f3//f39//z8
+ /P/8/Pz//Pz8//39/f/9/P3//f38//f2+f/j5Nf/fHvR/0pE+/9OSPX/v8LS//bz8v/4+fn/+Pj5//f3
+ 9//39/f/9vb2//T09P/y8vL/8fHx//Dw8P/u7u7/6+vr/+jo6P/i4uL/4eHh/8/Pz/1OTk4sAAAAAP//
+ /wIAAAAAAAAAAAAAAAAAAAAA////XP//////+vn8/35d//88Ef//KwD//yMA//8lAP//LAD//zIA//82
+ A///NgP//zMA//8zAP//MwD//zMA//8zAP//NQL//y0A//9VLP//+/r///////j39//Cw8P/8PDw////
+ ///7+/v//Pz8//z8/P/8/Pz//f39//z8/P/8/Pz//fz9//z9/P/z8/b/39/Q/1pZ2P8+Ovv/R0L7/5WS
+ 3//y9Of/9vX4//j4+P/4+Pj/9vb2//X19f/09PT/8vLy//Dw8P/v7+//7e3t/+vr6//n5+f/4uLi/+Dg
+ 4P/Pz8//T09PLgAAAAD///8CAAAAAAAAAAAAAAAAAAAAAP///0T///////39+/++rvz/jHH+/2lE//9K
+ H///NAH//ykA//8nAP//KwD//zEA//8zAP//MwD//zMA//8zAP//MwD//zQB//8xAf//PhT//8y+////
+ ///9+/v/xcXF/7e3t//39/f//f39//v7+//8/Pz/+/v7//z8/P/8/Pz/+/v7//z8/P/6+/z/7+/v/9DQ
+ y/9BPur/PDb9/0lE+v9xben/6uvf//b1+P/39/f/9/f3//X19f/09PT/8/Pz//Ly8v/w8PD/7u7u/+3t
+ 7f/r6+v/5+fn/+Li4v/g4OD/z8/P/k9PTy8AAAAA////AgAAAAAAAAAAAAAAAAAAAAD///8G////v///
+ ////////////////////9PL9/9fN+/+smP3/gmX//1oy//89Df//MgD//zMA//8zAP//MwD//zUC//81
+ Av//NQH//y0A//84Df//1cr////////////AwMD/vLy8//n5+f/9/f3/+/v7//v7+//8/Pz/+/v7//r6
+ +v/7+/v/+Pn6/+/u6v+6vcv/PTnz/0RA+P9MR/v/WVTw/9jb3f/39vX/9vb3//X19f/09PT/8/Pz//Pz
+ 8//w8PD/7+/v/+3t7f/s7Oz/6urq/+fn5//h4eH/4ODg/87Ozv9PT08wAAAAAP///wIAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP///wr///9q//39sv/8+93//v7/////////////////////////////t6X//ysA//81
+ Av//MwD//zUB//8sAP//KwD//zUC//85Bv//LgD//0EX///g1/////////39/7u7u//AwMD/+fn5//v7
+ +//6+vr/+/v7//r6+v/6+vr/+vr6//j4+v/w8Of/q6rR/z45+f88PPf/SUf3/0tF+v/HyN7/9vbx//X1
+ 9v/29vb/8fHx/+/v7//z8/P/8PDw/+7u7v/s7Oz/6+vr/+np6f/m5ub/4ODg/9/f3//Ozs7/UFBQMgAA
+ AAD///8CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8H////K////lz//v2Q//z7xf/6
+ +ff//////7mo//8pAP//NQP//zUB//8rAP//XjX//1ow//8pAP//JgD//zQA//8uAP//TCP//+nj////
+ ///8+/v/tbW1/8nJyf/7+/v/+vr6//r6+v/6+vr/+fn5//n5+v/49/n/8fHm/6Sj0/86Nv3/QUHs/0lF
+ 9P9CPfr/urnd//f38P/y8vP/2dnZ/8fHx/+2trb/w8PD/+vr6//t7e3/6+vr/+np6f/n5+f/5eXl/9/f
+ 3//e3t7/zc3N/1BQUDIAAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAA////Af///wT///8BAAAAAAAA
+ AAAAAAAAAAAAAAAAAADz8O/S//////+mj/3/JgD//zgF//8vAf//Qhb///Ds///8+///wbL//3hY//88
+ D///KQD//yAA//9VLv//8+////////f29v+ysrL/5eXl//z8/P/4+Pj/+Pj4//j4+P/4+Pj/9/b4//Lz
+ 5/+npdj/NzL+/0pJ3f9NSuv/Ozb8/7S04//49+7/5ubo/+3t7f/28/b/7uzu/7+/v/+7u7v/6+vr/+rq
+ 6v/o6Oj/5ubm/+Pj4//e3t7/3Nzc/8zMzP9QUFAzAAAAAP7+/gMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP///wH///8C////Bf///wT29vYH/Pj33f//////mX/+/yQA//85B///KAD//72s////
+ ////////////////////6eT//6SP//9eN///IQD//1Qq///w7f//////2NfX/9jY2P/8/Pz/9/f3//f3
+ 9//39/f/+Pj3//b3+f/09ej/qqra/zMv//9QT9f/TErm/zcz/v+6uuf/+Pjt//n5+///////////////
+ ///+/v7/tLS0/8nJyf/s7Oz/5ubm/+Xl5f/h4eH/3Nzc/9ra2v/Jycn/UFBQNgAAAAAAAAAAAAAAAP//
+ /wEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wEAAAAA6enpEvv49+j//////4tt//8o
+ AP//KQD//3xa/////////v3/9PLy//36+v///v3//////////////////9DE//+BZP//4dn//////+Xj
+ 4//k5OT/+vr6//b29v/29vb/9vb2//b29v/29fb/9/bu/7i45P88Nfz/SEbq/0hG7v8+OPr/zc3p//X3
+ 7/////////////+J///+4v7//////+3r7f+qqqr/2tra/+fn5//k5OT/4ODg/9ra2v/W1tb/ycnJ/05O
+ Ti4AAAAAxMTEDgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8CAAAAAOPj
+ 4xz6+Pfz//////9+Xf//IgH//0cb///v6///////9PLy/+bm5v/29vb/9/f3//v6+v///Pv/////////
+ ///////////////////u7u7/8/Pz//b29v/29vb/9fX1//T09P/19fb/8/P0//T28f/a2u3/NTH4/zg1
+ +v9HQ/b/aGjx/+/w6//x8PD/////////////Hf///03/////////////0M/Q/7Kysv/k5OT/4+Pj/+Dg
+ 4P/b29v/0dHR/729vf+NjY2FoaGhn6GhocaRkZGWq6urJQAAAAD///8BAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAA/v7+AgAAAADb2tom+vj4/f//////cU7//x8A///Bsf///////fv6/+Tl5f/09PT/9PT0//Pz
+ 8//z8/P/9PT0//j39//8+vr///z7//7+/v/4+Pj/8/Pz//X19f/19fX/9fX1//T09P/z8/P/8/Pz//P0
+ 8//w8PH/+Pfx/5OS9f9WU/f/g4L1/9rZ7v/w8ev/7+/w///9/////////03///8A////rP////////79
+ /v+1trX/w8PD/+Xl5f/V1dX/wsLC/7y8vP/Lysv/6ebp//r3+v/4+Pj/0dHR/5WVlazAwMAJAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wP///8B//7+M/z7+////////0oc//91Uf////////79/+np
+ 6P/t7e3/9PT0//Ly8v/y8vL/8vLy//Ly8v/x8fH/8vLy//Pz8//z8/P/8vLy//Pz8//y8vL/8/Pz//Pz
+ 8//y8vL/8fHx//Hx8f/y8vL/8vLy/+/v8P/4+e7/7u/v//T17v/x8uz/6+vt/+7t7f/+/P7///////9d
+ ////Af///xn////p////////7ezt/6ioqP+/v7//ycnJ/93b3f/28/b////////////////9/////f//
+ //7CwsLyl5eXQgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc3NwBAAAAAJqamjL//////f39/v6j
+ jf/+6+b///7+//Tz8//m5ub/9fX1//Pz8//z8/P/8/Pz//Pz8//y8vL/8vLy//Ly8v/y8vL/8vLy//Pz
+ 8//z8/P/8vLy//Pz8//z8/P/8vLy//Hx8f/x8fH/8fHx//Dw8P/v8O//7u3v/+/u7v/r6+z/6+rs/+rq
+ 6v/p6ur//fn+////////bf///wD///8A////VP/////////////k4+T/6ufq///+///////////////4
+ ///+tv7//1z///7V/v/+/v7+4N7g86CgoDkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABgYGCQAA
+ ABoGBgYv6enq3v/////////////////////Y2Nn/3d3e/9/f4P/e3t//3t7f/97e3//e3t//3t7f/9/e
+ 3//f3+D/39/g/9/f3//f3+D/397f/97e3//e3t//3t7f/93d3v/d3d7/3d3e/9zc3f/c3N3/4ODg/+bm
+ 5//r6+z/7e3t/+3t7f/s7Oz/6urq//z4/P///////3////8A////B////wD///+m////////////////
+ /////////tn+//+C////LP///wD///85///+7/79/////8/Pz8Ourq4IAAAAAAAAAAAAAAAAAAAAAAAA
+ AABLS0sBAAAAFAICA0UFBQZ1AAAAgTAxLJ2/wLvl6OXh9urp5f+3t7P/nZ2Z/6Kinv+hoZ3/oaKd/6Gi
+ nf+goZz/oKCc/6CgnP+goZz/oaGc/6ChnP+goZz/oaGd/6Ghnf+goZz/oKGc/5+gm/+fn5v/n5+b/5+f
+ m/+fn5v/oKCc/6Skov+0tLT/0dHR/93d3f/W1tb/y8vL/8HBwf/07/T///////+Q////AP///wX///8C
+ ////E////+f///72/v//qf///0////8J////AP///wD///88////9//+//////b29vS3t7c6AAAAAP//
+ /wIAAAAAAAAAAAAAAAAAAAAAAAAADAYGB0oAAACTBAUAthERG8wPDSDPEA8hzCsrPttXWGz9W1pu/1xc
+ b/9dXXD/XV1w/11dcP9dXXD/XF1w/1xdcP9bXG//XFxv/1tcb/9cXG//XFxv/1xcb/9cXG//XFxv/1xc
+ b/9cXG//XFxv/1tbb/9bW2//XF1v/1pbbv9mZ3H/iomJ/6qrqv/CwcL/zs3O/9rX2v/s6Oz//ff9////
+ ////qf///wD///8D////Af///wD///8v////KP///wD///8A////Af///wD///8t////6////////vv6
+ +/q9vb1RAAAAAP///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAICAiQDAwF7DAsTwSMgdvE2NKf/REGz/0RB
+ s/89Oar/PTmq/z07qv88Oqv/PDur/zw6q/88Oqv/PDqr/z06qv89Oqr/PDqq/zw6qv88Oqr/PDqq/zw6
+ qv88Oqv/PDqq/zw6qv88Oqr/PDqr/zw6q/88Oqv/Pjur/zg1qv9TUKr/t7bL/+fl5//18fb///7/////
+ /////////////////////v///6D///8A////Av///wD///8B////AP///wD///8C////Bv///wD///8f
+ ////4f////////37/f+6urphAAAAAP///wMAAAAAAAAAAAAAAAAAAAAAAAAAAHt7fAEAAAA0CgoKliQh
+ hfU9OsP/V1fB/1pZwP9cWcL/XlvD/15dxv9eXcf/XVzD/11aw/9cW8L/XFvD/11bwv9eXMX/X13H/2Bc
+ x/9gXMb/X13H/15cxP9eWsL/XlrD/15cxP9fXMf/XVzE/1xcwv9dW8P/XlvD/1xaw/9hXsP/5OTz////
+ ////////////////////6f///sL+//+O////Wv///yn///8I////AP///wD///8A////AP///wL///8C
+ ////Av///wD///8U////1P///////v////vGxsZxAAAAAP///wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAB+foADAAAANCAgQLQkILj/MC6z/i0qs/8sKbP/LSqy/y0qs/8nIqD/JSCd/yopsP8sKrP/LCqz/ywq
+ s/8sK7T/KCao/yMgl/8jH5n/IiCY/yIfnf8nI6z/LSu2/y4qtf8pJaf/Ix+a/ysoq/8sKrX/LSm1/zAt
+ tP8hHrD/cG7L///////8+P7//p/+//9l////OP///xX///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////Af///wH///8Y////yf///////vz7/P+/v7/BAAAAAP///wL9/f0CAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAfn6ABAAAADQnJlfAFRK9/w8Lr/0QDrL/EA6y/xEPs/8NCqr/Pj54/0xN
+ bP8UEKD/EAy0/xAOsP8RDrH/DAmx/yooiP9TVGj/UU9m/09PZf9JSGX/Kipr/w0Llf8NCbP/LSuE/1NU
+ aP8ZGJL/Dwq0/xEOr/8TEbL/AgCt/2Vjzv//////+/b///9m////Gf///wD///8A////AP///wD///8A
+ ////Av///wP///8A////AP///wD///8A////AP///wL///8A////Kf////P////////6+fr/sLCw8ZSU
+ lHMAAAAA////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAH5+gAQAAAA1JCJawBYTx/8QDrb9EA+7/xAP
+ uv8QELv/DQq3/21slP+Gh4n/Gxm3/xEQw/8VE7//FxK6/woHu/9DQqD/k5OH/4uKmf+SlaD/k5SY/4+P
+ g/9DQ3r/AgCt/0xLnf+UlIL/KCan/w8MwP8TErz/EhK7/wwMuv8iIb//7u77/////////////v////3f
+ /v//tP///33///9H////Hv///wD///8A////AP///wD///8A////AP///wH///8A////Av///wD///85
+ ////9P////////f29/+srKz2mJiYZgAAAAD///8BAAAAAAAAAAAAAAAAAAAAAAAAAAB+foEEAAAANSQj
+ X8IdGtP/HBvD/Rwbxf8cG8X/HhzH/xcVxP93dqT/jY+a/xUUof8MDKT/Dw2t/xsaxf8XFMr/TUuw/6Gh
+ l/9TUr7/RUHX/1NR1f+Hhqz/lJWT/xgWqv9SUK3/oqCV/ygnr/8QDb7/FBS9/xkYxf8gHsf/ExPE/09O
+ 0//DwvH/8e78//////////////////////////////L////Q////dv///wD///8C////AP///wD///8A
+ ////AP///wP///8F////AP///0n////7///////+8/Lz/6enp/CWlpZbAAAAAP///wEAAAAAAAAAAAAA
+ AAAAAAAAfn6BBAAAADYkI2DDJCLd/yko0f0oJ9L/KCfS/yop1P8jIc//iIe2/7Szr/94eJL/dXSM/2Rk
+ iv8wMI//GhjG/11cwf+8va//SUnB/x8d0P8eHtX/YmHF/76+rv87Orj/Xly7/728r/9WVpL/PT2D/0ZF
+ hf8xL6T/JSTS/ysq0/8fHtD/IiHQ/0A/1/9XVd//p6Te//Xz7//59fv///3//////////////7b///8A
+ ////Av///wH///8A////CP///wD///8A////AP///wf///8A////Wf///v/+//////7t7e3/o6Oj65mZ
+ mU0AAAAA////AgAAAAAAAAAAAAAAAH5+gQQAAAA3IyNmxC4r6v86ONz9Nzbd/zg23f85N9//MTDZ/5qZ
+ yv/Q0Mz/xsbX/87N2P/b3NT/tLO4/y4tsf9pZ8//1NbI/19dz/80M93/MzLf/2hozf/W2Mr/VFXQ/29t
+ zP/V1Mr/zs3J/9DPxv/X18b/e3vI/y4t3v86ON7/Ojje/zg33v85Ntz/FhXb/09Ovv/b28r/2Njb/9nZ
+ 2f/49Pj///3///+U////AP///wT///8D////Af///7v////I////Yf///xX///8A////AP///wD///9t
+ ///+//7//////uno6f+amprPr6+vHAAAAAAAAAAAAAAAAAAAAAB+foEEAAAANyIiasU4NvT/TErl/UhH
+ 6P9JR+j/S0np/0A/4/+wsdv/09Xh/2Jh6/9iYu//jYze/+7w4f9radP/cXDZ/+zu4P9ra93/QULr/zQy
+ 1P+CgMb/7u7k/1pa4/+BgNz/6erg/5CN6f+JiPT/j47w/2pq8P9JSOr/Skjp/0lI6f9JR+n/UU/o/zEy
+ 6v9cXMj/29vM/9TU1//MzMz/9/L3////////hf///wD///8I////AP///3T////////////////////r
+ //3/nv/+/0H///8F////AP///3P///78/v/////+ycnJ95WVlUwAAAAAAAAAAAAAAAAAAAAAf3+CAwAA
+ AC4kInC/QkL9/11c7f5ZWPH/Wlnw/1xb8v9QT+v/vr/q/+Lj6v9PTab/OTiU/5WUxP/9/vb/gH7u/4GC
+ 5v/8/PP/eHa+/z4+nP9VVZn/19ne/+Pk9v9cWu7/k5Pm//r88v9kYrT/PTyg/0ZEov9HR63/VVPi/1pb
+ 8v9aWfD/WVjw/2Fg8P88PPT/XFvN/9vczP/S0tX/zMzM//j0+P///////3P///8A////Af///yv////3
+ /////v//+vb6///8//7///////////////3/zv/8/3X///8d///+0/7//v7+/d7c3vKenp42AAAAAAAA
+ AAAAAAAAAAAAAHx8fwIAAAIUJid4sFBP//5wcPP9amv3/2xs9v9tbvf/Zmb0/83N9f////n/6ejn/+zs
+ 5/////j/5Ob5/3p49/+dnfL////7/+3v7f/m5+H/+/vy//v9/v+qrPb/ZmP2/6qq8/////z/7e7o/+fo
+ 4f/t7uP/1Nbf/21t5f9qbPn/bW32/2tr9/9zcvf/TEv3/19f2f/f387/zs7S/8zMzP/79/v///////9i
+ ////Af///wP////F////////+vj6/83Nzf3Kysr/7u3ut//8/9n//v//////////////+f/9//n/+///
+ ///GxsanwMDABv///wEAAAAAAAAAAAAAAADMzM4CAAAAACcna3lLS///jI33/H5++/9/fvv/fn76/4B/
+ /P+0tP7/z8/9/9DQ///R0P//w8P8/5uc+/99ffz/oJ7+/83N/P/Q0f//0tH//8nJ//+op/z/g4P8/3x7
+ /P+jpP3/zs78/8/Q///S0f//09L//8bF//+IiP7/fX36/39/+/99ffr/kZH6/0hI/P9xcN//4+PS/8zM
+ z//Ozs7//vv+////////Vf///wD///96//////////7//9ra2vzBwcH/zc3NmAAAAAD///8L////Uv/9
+ /63//P/z///////////s7OzHysvKFwAAAAD///8BAAAAAAAAAAAAAAAA////AV5fXAEBAQUZMTDr42pq
+ /v+fn/79nqD9/p2d/P6fn/3/oaH//6Cg/v+eoP3/n6D9/5+f/v+fn///oaH+/6Kg/v+hoP7/oKH+/5+f
+ /f+dn/7/nZ7//6Gg//+hov7/oaD+/6Gg/v+foP7/n6D9/5+f/v+fn/z/oKH+/6Kh/v+gof7/oaH//3p5
+ //8qKvj/uLna/9va1P/Ly83/0NDQ///+/////////yv///8j////+f///////+zr7PzCwsL/0dHRowAA
+ AAD///8DAAAAAAAAAAAAAAAA////Hv/+/1f///9N9PT0BgAAAAD///8BAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD//v8CAAAAAFpagTZWUv/UQkL7/1NS//9gX///WFf//1BP//9PT///T0///09P//9QT///UE///09P
+ //9PT///T0///1BP//9QT///UE///1BQ//9QT///UE///09P//9PT///UE///1BP//9QT///UE///09P
+ //9QT///UFD//0dG//85OPX/pKTe/93d1P/R0dT/ycnJ/9HQ0f////////////9M////v/////////r5
+ +vzHx8f/0dHRrQAAAAD///8C////Af///wH///8D////AgAAAAAAAAAAAAAAAAAAAAD///8BAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wIAAAAA+Pn+CM7O/zasreg/LzBqThoaVZehot38srPv/6us
+ 6P+sren/q6zo/6ys6f+rrOj/qqvn/6ur5/+rrOj/qqvn/6mq5v+oqeX/qanm/6ip5f+nqOT/p6jk/6en
+ 4/+mpuL/pabi/6Sl4f+kpOH/o6Tg/6Kj3/+oqN7/0NHY/9/g0//Q0dP/0NDP/8fHx//Dw8P//Pz8////
+ /////f////////////zV1dX/zs7Ot/z8/AYAAAAA////AgAAAAAAAAAAAAAAAAAAAAD///8C////A///
+ /wMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AgAAAAAAAAAAAAAAAAEB
+ AQkREQVu4ODT+vb26f/t7d//7u7g/+3t3//t7eD/7e3f/+zs3//s7N//7O3f/+vr3v/r693/6urc/+rq
+ 3P/p6dz/6Ojb/+fo2v/n59r/5ubZ/+bm2P/l5dj/5eXX/+Tj1v/j4tb/4ODU/9fX1P/Q0NT/0dHQ/8zM
+ zP/ExMX/sbGx/9HR0f////////////////zj4+P/zMzMvfr6+goAAAAA////AgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD9/f4B/v7/BM/P0QMCAgQXEhIUd9LS1Pvn5+n/3d3g/97e4f/e3uD/3t7h/97e4P/d3eD/3d3g/93d
+ 3//c3N//29ve/9vb3f/b293/2trd/9rZ3P/Z2dv/2Njb/9jY2v/X19n/1tbZ/9bW2P/U1Nf/09TW/9LS
+ 1f/R0dL/0NDP/8zMzP/Gxsb/vLy8/6urq/+1tbX/3t7e/97d3vzR0dH/zMzMw/n5+Q0AAAAA////AgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wEAAAAAAAAAFBEREXXT09P66Ojo/97e3v/g4OD/39/f/9/f
+ 3//f39//39/f/97e3v/d3d3/3d3d/9zc3P/c3Nz/3Nzc/9vb2//a2tr/2dnZ/9nZ2f/Z2dn/19fX/9bW
+ 1v/W1tb/1NTU/9PT0//R0dH/zs7O/8vLy//Gxsb/vr6+/7S0tP+kpKT/ubm5/83Nzfy/v7//yMjIyPn5
+ +RAAAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8BAAAAAAAAABQRERF109PT++fn
+ 5//d3d3/39/f/97e3v/e3t7/3d3d/93d3f/c3Nz/29vb/9ra2v/Z2dn/2dnZ/9jY2P/X19f/1tbW/9fX
+ 1//W1tb/1dXV/9XV1f/U1NT/0tLS/9HR0f/Pz8//zMzM/8nJyf/ExMT/vr6+/7W1tf+rq6v/oKCg/7y8
+ vPy+vr7/v7+/zvX19RQAAAAA////AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AQAA
+ AAABAQEUEhISdNTU1Prl5eX/3Nzc/97e3v/d3d3/3Nzc/9vb2//a2tr/2dnZ/9jY2P/X19f/1tbW/9XV
+ 1f/V1dX/1NTU/9PT0//T09P/0tLS/9HR0f/Q0ND/z8/P/83Nzf/MzMz/ycnJ/8XFxf/BwcH/u7u7/7S0
+ tP+tra3/oaGh/6Wlpfu1tbX/t7e30/Dw8BcAAAAA////AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAADBoaGlXb29vw4ODg+9jY2PvZ2dn72NjY+9bW1vvV1dX71NTU+9LS
+ 0vvR0dH7z8/P+87OzvvOzs77zs7O+83NzfvMzMz7zMzM+8zMzPvLy8v7ycnJ+8jIyPvGxsb7w8PD+8DA
+ wPu8vLz7t7e3+7Gxsfuqqqr7oKCg/ZmZmf+np6f/tbW11+3t7RoAAAAA////AwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA29vbAQMDAwEhISEj6+vr/uHh4f/e3t7/39/f/97e
+ 3v/c3Nz/29vb/9ra2v/X19f/1tbW/9XV1f/S0tL/0tLS/9HR0f/Pz8//zc3N/8zMzP/Kysr/x8fH/8PD
+ w//BwcH/vb29/7q6uv+2trb/sbGx/6urq/+lpaX/n5+f/52dnf+ysrLxzc3Nn/X19RgAAAAA////AwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wEAAAAA19fXB/r6
+ +mr39/d1+Pj4dfj4+HX39/d19/f3dfb29nX29vZ19vb2dfX19XX19fV19PT0dfT09HXz8/N18/PzdfLy
+ 8nXx8fF17+/vde7u7nXs7Ox17Ozsderq6nXp6el16Ojodebm5nXk5OR14uLidePj42/u7u5O+vr6HgAA
+ AAAAAAAA////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////////////////////////8AAAAAAA///g
+ AAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAB//+AAAAAAAH//4AAAAAAAf//gAAAAAAB///AAAAAA
+ AH//4AAAAAAAf//AAAAAAAB//4AAAAAAAH//gAAAAAAAf/+AAAAAAAB//4AAAAAAAH//gAAAAAAAf/+A
+ AAAAAAB//4AAAAAAAH//gAAAAAAAf/4AAAAAAAB/4AAAAAAAAH/AAAAAAAAAf4AAAAAAAAB/gAAAAAAA
+ AH+AAAAAAAAAf4AAAAAAAAB/4AAAAAAAAH/+AAAAAAAAf/+AAAAAAAB//4AAAAAAAH//gAAAAAAAf/+A
+ AAAAAAAH/4AAAAAAAAP/gAAAAAAAA/+AAAAAAAAD/4AAAAAAAAP/AAAAAAAAB/wAAAAAAAAP/AAAAAAA
+ AB/4AAAAAAAAP/gAAAAAAAA/+AAAAAAAAD/4AAAAAAAAH/gAAAAAAAAP+AAAAAAAAAf4AAAAAAAAA/gA
+ AAAAAAAD+AAAAAAAAAP4AAAAAAAAA/wAAAAAAAcH/AAAAAAAD//+AAAAAAAf///gAAAAAD////AAAAAA
+ f///8AAAAAD////wAAAAAf////AAAAAD////8AAAAAf////wAAAAD/////AAAAAf/////////////ygA
+ AADAAAAAgAEAAAEAIAAAAAAAAEACACMuAAAjLgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAEAAAADAAAABAAAAAUAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAAAAcAAAAHAAAABwAA
+ AAcAAAAHAAAABwAAAAYAAAAFAAAABAAAAAIAAAABAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAA
+ AAQAAAAIAAAADAAAABAAAAATAAAAFgAAABYAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAA
+ ABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAXAAAAFwAAABcAAAAWAAAAFQAA
+ ABMAAAAPAAAACgAAAAcAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABAAAAAkAAAAQAAAAGAAA
+ ACAAAAAmAAAAKwAAAC0AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAA
+ AC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAtAAAAKgAAACUAAAAeAAAAFgAA
+ AA0AAAAHAAAAAwAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABwAAAA8AAAAaAAAAKAAAADYAAABAAAAARwAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABMAAAATAAA
+ AEwAAABMAAAATAAAAEwAAABMAAAATAAAAEwAAABKAAAARgAAAD0AAAAyAAAAJAAAABYAAAANAAAABQAA
+ AAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAAACgAAABYAAAAoAAAAPQAAAFEAAABgAAAAawAAAHEAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAAAHMAAABzAAAAcwAA
+ AHMAAABzAAAAcwAAAHMAAABwAAAAaAAAAFwAAABLAAAANgAAACIAAAATAAAABwAAAAEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAEAAAADQAAABwAAAAyAAAATQAAAGYAAAB5AAAAiAAAAI8AAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAAAJEAAACRAAAAkQAA
+ AJEAAACOAAAAhAAAAHUAAABfAAAARAAAACsAAAAXAAAACgAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAA
+ ACEAAAA6AAAAWQAAAHYAAACNAAAAnQAAAKYAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAA
+ AKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACoAAAAqAAAAKgAAACkAAAAmQAA
+ AIcAAABuAAAATwAAADIAAAAcAAAACwAAAAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACQAAAA/AAAAYQAA
+ AIEAAACaAAAAqwAAALUAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAA
+ ALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAAC4AAAAuAAAALgAAACzAAAApwAAAJQAAAB5AAAAVwAA
+ ADcAAAAeAAAADQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIYAAACgAAAAsgAA
+ ALwAAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAA
+ AL8AAAC/AAAAvwAAAL8AAAC/AAAAvwAAAL8AAAC7AAAArgAAAJoAAAB+AAAAWwAAADkAAAAfAAAADQAA
+ AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTdxMTE/8bGxv/AwMD/vr6+/7u7
+ u/+3t7f/tra2/7e3t/+4uLj/ubm5/7m5uf+5ubn/ubm5/7q6uv+6urr/u7u7/7u7u/+7u7v/vLy8/7y8
+ vP+8vLz/vLy8/729vf+9vb3/vb29/729vf+9vb3/vr6+/76+vv++vr7/vr6+/76+vv+/v7//v7+//7+/
+ v/++vr7/v7+//7+/v/+/v7//v7+//7+/v//AwMD/wMDA/8HBwf/AwMD/v7+//7+/v/+/v7//wMDA/8DA
+ wP/AwMD/x8fH/8rKyv/Pz8//0dHR/9LS0v/S0tL/0tLS/9PT0//S0tL/0tLS/9LS0v/S0tL/0dHR/9HR
+ 0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR
+ 0f/Q0ND/0NDQ/9DQ0P/Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/87Ozv/Ozs7/zc3N/83N
+ zf/Nzc3/zc3N/8zMzP/MzMz/y8vL/8vLy//Ly8v/y8vL/8zMzP/Nzc3/z8/P/9DQ0P/V1dX/1dXV/9XV
+ 1f/V1dX/1dXV/9XV1f/U1NT/1NTU/9TU1P/U1NT/1NTU/9PT0//T09P/09PT/9PT0//T09P/0dHR/9HR
+ 0f/Q0ND/z8/P/83Nzf/Nzc3/zs7O/8/Pz//IyMj/yMjI/8PDw/+cnJxuAAAADQAAAAMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTdzMzM/9nZ2f/a2tr/29vb/9vb2//b29v/29vb/9zc
+ 3P/e3t7/3t7e/97e3v/c3Nz/3d3d/93d3f/e3t7/3t7e/97e3v/f39//39/f/9/f3//f39//4ODg/+Dg
+ 4P/g4OD/4ODg/+Dg4P/h4eH/4eHh/+Hh4f/h4eH/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li
+ 4v/i4uL/4uLi/+Li4v/i4uL/4uLi/9/f3//e3t7/3d3d/9vb2//a2tr/29vb/9zc3P/c3Nz/4eHh/+Dg
+ 4P/g4OD/4eHh/+Li4v/j4+P/4+Pj/+Li4v/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Tk5P/k5OT/5OTk/+Tk
+ 5P/k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//i4uL/4uLi/+Li4v/i4uL/4uLi/+Hh
+ 4f/g4OD/4ODg/+Dg4P/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/97e3v/e3t7/3d3d/93d
+ 3f/d3d3/3d3d/93d3f/c3Nz/29vb/9vb2//c3Nz/3d3d/97e3v/a2tr/2tra/9ra2v/a2tr/2tra/9ra
+ 2v/a2tr/2tra/9nZ2f/Z2dn/2dnZ/9nZ2f/Y2Nj/2NjY/9jY2P/Y2Nj/19fX/9fX1//X19f/1dXV/9PT
+ 0//S0tL/0NDQ/8/Pz//Pz8//zc3N/8fHx/+ZmZlvAAAADQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAA
+ ACUAAABCAAAAZQAAAIaUlJTdzs7O/93d3f/d3d3/3d3d/97e3v/f39//39/f/+Dg4P/h4eH/4eHh/+Hh
+ 4f/h4eH/4eHh/+Li4v/i4uL/4uLi/+Li4v/j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//k5OT/5OTk/+Tk
+ 5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Xl5f/l5eX/5eXl/+Xl5f/m5ub/5eXl/+Xl5f/k5OT/5OTk/+Pj
+ 4//j4+P/4+Pj/+Dg4P/e3t7/29vb/9jY2P/V1dX/1dXV/9fX1//Z2dn/39/f/93d3f/c3Nz/3t7e/+Hh
+ 4f/k5OT/5ubm/+bm5v/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+bm5v/m5ub/5ubm/+bm
+ 5v/m5ub/5ubm/+bm5v/m5ub/5OTk/+Tk5P/k5OT/5OTk/+Pj4//j4+P/4+Pj/+Pj4//k5OT/5OTk/+Pj
+ 4//j4+P/4+Pj/+Pj4//i4uL/4uLi/+Hh4f/h4eH/4eHh/+Hh4f/g4OD/4ODg/+Dg4P/g4OD/4eHh/+Dg
+ 4P/f39//3t7e/97e3v/d3d3/3Nzc/9zc3P/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d
+ 3f/d3d3/3Nzc/9zc3P/c3Nz/3Nzc/9vb2//b29v/2dnZ/9nZ2f/Z2dn/2NjY/9bW1v/W1tb/1NTU/9HR
+ 0f/S0tL/0NDQ/8rKyv+ZmZlvAAAADQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAA
+ AIaUlJTd0NDQ/9/f3//e3t7/3d3d/+Dg4P/h4eH/4eHh/+Hh4f/j4+P/5OTk/+Tk5P/j4+P/4+Pj/+Pj
+ 4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Tk5P/k5OT/5OTk/+Tk5P/l5eX/5eXl/+Xl5f/l5eX/5ubm/+bm
+ 5v/m5ub/5ubm/+fn5//n5+f/5+fn/+fn5//o6Oj/5+fn/+fn5//m5ub/5eXl/+Tk5P/j4+P/4uLi/9ra
+ 2v/Y2Nj/1NTU/8/Pz//MzMz/y8vL/83Nzf/Pz8//1NTU/9TU1P/W1tb/2NjY/9zc3P/h4eH/5OTk/+fn
+ 5//m5ub/5ubm/+bm5v/m5ub/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn
+ 5//n5+f/5ubm/+bm5v/m5ub/5ubm/+Xl5f/l5eX/5eXl/+Xl5f/k5OT/5OTk/+Pj4//j4+P/4+Pj/+Li
+ 4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eH/4ODg/+Dg4P/g4OD/4ODg/+Dg
+ 4P/g4OD/39/f/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/93d3f/d3d3/3Nzc/9zc
+ 3P/c3Nz/3Nzc/9vb2//b29v/29vb/9vb2//a2tr/2NjY/9fX1//W1tb/1NTU/9LS0v/R0dH/0NDQ/8rK
+ yv+YmJhvAAAADQAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd0tLS/+Hh
+ 4f/i4uL/4ODg/+Hh4f/h4eH/4+Pj/+Tk5P/k5OT/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+bm
+ 5v/m5ub/5ubm/+fn5//n5+f/5+fn/+fn5//o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6enp/+np
+ 6f/p6en/6enp/+np6f/o6Oj/6enp/+fn5//n5+f/5ubm/+Xl5f/j4+P/2tra/9XZzv/Szs3/08zR/83F
+ z//Fxsr/vsPG/8TGx//Kxcf/z83D/9PPzv/X09j/0tTV/9fb3P/c3eH/6Ozh/+Xn2//o6Oj/5ubm/+rq
+ 6v/p6en/6enp/+vr6//p6en/6urq/+np6f/p6en/6enp/+np6f/p6en/6enp/+jo6P/o6Oj/6Ojo/+jo
+ 6P/o6Oj/6Ojo/+jo6P/n5+f/5+fn/+fn5//n5+f/5ubm/+bm5v/m5ub/5ubm/+bm5v/l5eX/5eXl/+Xl
+ 5f/l5eX/5OTk/+Tk5P/k5OT/5OTk/+Pj4//j4+P/4uLi/+Li4v/i4uL/4eHh/+Hh4f/i4uL/4uLi/+Li
+ 4v/h4eH/4eHh/+Hh4f/h4eH/4ODg/+Dg4P/g4OD/4ODg/9/f3//f39//39/f/9/f3//e3t7/3t7e/93d
+ 3f/d3d3/3Nzc/9vb2//a2tr/2dnZ/9nZ2f/X19f/1dXV/9TU1P/S0tL/0dHR/83Nzf+YmJhvAAAADgAA
+ AAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd0tLS/+Hh4f/i4uL/4eHh/+Li
+ 4v/j4+P/5OTk/+Xl5f/l5eX/5ubm/+bm5v/m5ub/5ubm/+bm5v/m5ub/5+fn/+fn5//n5+f/5+fn/+jo
+ 6P/o6Oj/6Ojo/+jo6P/p6en/6enp/+np6f/p6en/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq
+ 6v/q6ur/6+vr/+rq6v/p6en/6Ojo/+bm5v/j4+P/2dnZ/83P0P/O0ND/xMbG/8XGxP+6uLf/v7y4/728
+ uP+9u7r/vby+/8XGwv/My83/1dXb/8/U0v/e4+H/2NXe/+fe6P/p6en/6enp/+zs7P/q6ur/6enp/+rq
+ 6v/o6Oj/6enp/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+np6f/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+jo
+ 6P/o6Oj/6Ojo/+jo6P/o6Oj/5+fn/+fn5//n5+f/5+fn/+fn5//m5ub/5ubm/+Xl5f/l5eX/5eXl/+Xl
+ 5f/k5OT/5OTk/+Tk5P/k5OT/4+Pj/+Pj4//j4+P/4+Pj/+Li4v/i4uL/4+Pj/+Pj4//h4eH/4eHh/+Hh
+ 4f/h4eH/4eHh/+Hh4f/g4OD/4ODg/+Dg4P/g4OD/4ODg/9/f3//f39//3t7e/97e3v/d3d3/3d3d/9zc
+ 3P/b29v/2tra/9nZ2f/Y2Nj/1tbW/9TU1P/T09P/0tLS/87Ozv+amppxAAAADgAAAAMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd09PT/+Hh4f/j4+P/4uLi/+Pj4//k5OT/5eXl/+bm
+ 5v/n5+f/5+fn/+fn5//o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+np6f/p6en/6urq/+rq
+ 6v/q6ur/6urq/+rq6v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/7e3t/+vr
+ 6//q6ur/5+fn/+Tk5P/f39//1NTU/9PL0v/IycX/uL65/7S3rv+2rLj/tq+0/7e1u/+vtrH/tLm6/7m8
+ xP/Excn/yMTD/9jR1v/V1Mr/2NTf/9/h6f/n5+f/6urq/+3t7f/r6+v/6+vr/+zs7P/q6ur/6+vr/+vr
+ 6//r6+v/6+vr/+zs7P/r6+v/6+vr/+vr6//q6ur/6enp/+np6f/p6en/6enp/+np6f/p6en/6enp/+np
+ 6f/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/n5+f/5+fn/+bm5v/m5ub/5ubm/+bm5v/l5eX/5eXl/+Xl
+ 5f/l5eX/5eXl/+Xl5f/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li
+ 4v/i4uL/4uLi/+Dg4P/h4eH/4ODg/+Dg4P/g4OD/39/f/9/f3//e3t7/3t7e/93d3f/c3Nz/29vb/9ra
+ 2v/Z2dn/1tbW/9XV1f/T09P/0tLS/87Ozv+enp58AAAADgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAA
+ ACUAAABCAAAAZQAAAIaUlJTd09PT/+Li4v/k5OT/4+Pj/+Tk5P/l5eX/5ubm/+fn5//n5+f/6Ojo/+np
+ 6f/p6en/6enp/+np6f/p6en/6enp/+rq6v/q6ur/6urq/+rq6v/q6ur/6+vr/+vr6//r6+v/6+vr/+zs
+ 7P/s7Oz/6+vr/+vr6//r6+v/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/t7e3/7u7u/+vr6//p6en/5eXl/+Dg
+ 4P/Z2dn/zs7O/8fBzP+8u7//s7qr/6OkqP+pqqH/qaSm/6Wpnv+boJ7/trOu/6utrv+0vrL/wcS7/8zJ
+ u//by9z/2dfW/9Xd3P/g4OD/5ubm/+rq6v/q6ur/6+vr/+3t7f/t7e3/7e3t/+zs7P/s7Oz/7e3t/+3t
+ 7f/s7Oz/7Ozs/+zs7P/s7Oz/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6urq/+rq6v/q6ur/6enp/+np
+ 6f/p6en/6enp/+np6f/o6Oj/6Ojo/+jo6P/n5+f/5+fn/+fn5//n5+f/5ubm/+bm5v/m5ub/5ubm/+bm
+ 5v/m5ub/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Li
+ 4v/i4uL/4uLi/+Hh4f/h4eH/4ODg/+Dg4P/f39//3t7e/93d3f/c3Nz/29vb/9vb2//Z2dn/19fX/9XV
+ 1f/U1NT/09PT/87Ozv+enp58AAAADgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAA
+ AIaUlJTd09PT/+Pj4//k5OT/5OTk/+Xl5f/m5ub/5+fn/+fn5//o6Oj/6enp/+np6f/q6ur/6urq/+rq
+ 6v/q6ur/6urq/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs
+ 7P/s7Oz/7Ozs/+zs7P/t7e3/7e3t/+3t7f/u7u7/7u7u/+vr6//p6en/4+Pj/93d3f/W1tb/ysrK/7vA
+ vv+rsK7/pqip/6OpqP+TmKf/j5Kn/4yKoP+hoKr/qKOk/6+usv+qrbL/srqv/77Ev//Gyr//1tXL/9zZ
+ 1f/a2tr/4+Pj/+jo6P/o6Oj/6urq/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t
+ 7f/s7Oz/7Ozs/+zs7P/s7Oz/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6urq/+rq6v/q6ur/6urq/+rq
+ 6v/p6en/6enp/+np6f/p6en/6enp/+jo6P/o6Oj/6Ojo/+jo6P/n5+f/5+fn/+fn5//n5+f/5ubm/+bm
+ 5v/m5ub/5ubm/+bm5v/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Pj4//j4+P/4+Pj/+Li
+ 4v/i4uL/4eHh/+Hh4f/g4OD/39/f/97e3v/d3d3/3Nzc/9vb2//Z2dn/19fX/9XV1f/V1dX/1NTU/8/P
+ z/+fn598AAAADgAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd1NTU/+Pj
+ 4//l5eX/5OTk/+bm5v/n5+f/6Ojo/+jo6P/p6en/6enp/+rq6v/r6+v/6+vr/+vr6//r6+v/6+vr/+vr
+ 6//s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7e3t/+3t7f/t7e3/7u7u/+7u7v/u7u7/7u7u/+7u
+ 7v/u7u7/7u7u/+7u7v/t7e3/7e3t/+rq6v/n5+f/4uLi/9vb2//T09P/x8fH/8C+tP+0r7D/oZ+y/32I
+ o/9aXr3/TEjQ/0g80P9aVL//Zm+4/42Zo/+pnrj/vbS+/7m1wP+4usX/u7zG/9PVyf/Y2Nj/4+Pj/+fn
+ 5//o6Oj/6+vr/+3t7f/u7u7/7e3t/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+3t7f/t7e3/7e3t/+3t
+ 7f/t7e3/7e3t/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/6+vr/+vr6//r6+v/6+vr/+vr6//q6ur/6urq/+rq
+ 6v/q6ur/6urq/+rq6v/p6en/6enp/+np6f/p6en/6Ojo/+jo6P/n5+f/5+fn/+fn5//m5ub/5ubm/+bm
+ 5v/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4uLi/+Hh
+ 4f/h4eH/4ODg/97e3v/d3d3/3Nzc/9vb2//a2tr/19fX/9XV1f/W1tb/1dXV/8/Pz/+fn598AAAADgAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd1NTU/+Tk5P/m5ub/5eXl/+bm
+ 5v/o6Oj/6enp/+np6f/p6en/6urq/+vr6//s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/t7e3/7e3t/+zs
+ 7P/t7e3/7e3t/+3t7f/t7e3/7u7u/+7u7v/u7u7/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v
+ 7//t7e3/7u7u/+vr6//o6Oj/4uLi/9ra2v/R0dH/xMTE/7+7uv+oq7P/dXq5/zcg7v8uGv//OC///0dM
+ 7/9BOfj/MSv8/zIZ5f+Diaz/o6So/7a1sf+7vb7/vsHF/8bNxv/T09P/4ODg/+Tk5P/m5ub/6+vr/+3t
+ 7f/v7+//7u7u/+7u7v/v7+//7+/v/+/v7//v7+//7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7e3t/+3t
+ 7f/t7e3/7e3t/+3t7f/t7e3/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/r6+v/6+vr/+vr6//r6+v/6+vr/+vr
+ 6//q6ur/6urq/+rq6v/q6ur/6enp/+np6f/o6Oj/6Ojo/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+bm
+ 5v/m5ub/5ubm/+bm5v/m5ub/5ubm/+Tk5P/k5OT/5OTk/+Pj4//j4+P/4uLi/+Li4v/i4uL/4ODg/9/f
+ 3//e3t7/3d3d/9zc3P/a2tr/2NjY/9bW1v/X19f/1dXV/9DQ0P+enp59AAAADgAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd1NTU/+Tk5P/m5ub/5ubm/+fn5//p6en/6enp/+np
+ 6f/q6ur/6+vr/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u
+ 7v/u7u7/7u7u/+7u7v/u7u7/7+/v/+/v7//v7+//7+/v/+/v7//w8PD/8PDw//Dw8P/w8PD/8fHx/+/v
+ 7//r6+v/5OTk/9vb2//R0dH/w8PD/6G1uv9oadn/Jhbw/yQg+/85OP//Skj//1lO//9fWP//WFj//z86
+ +/8tHPX/ZmvI/5qjrf+2rLj/xbrE/8nIxP/Kysr/2dnZ/97e3v/h4eH/6Ojo/+vr6//u7u7/7Ozs/+/v
+ 7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//u7u7/7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u
+ 7v/u7u7/7e3t/+3t7f/t7e3/7e3t/+3t7f/s7Oz/7Ozs/+zs7P/s7Oz/6+vr/+vr6//r6+v/6+vr/+rq
+ 6v/q6ur/6urq/+rq6v/p6en/6Ojo/+jo6P/o6Oj/6Ojo/+jo6P/n5+f/5+fn/+fn5//n5+f/5ubm/+bm
+ 5v/m5ub/5ubm/+Tk5P/k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Li4v/i4uL/4eHh/+Dg4P/f39//3t7e/93d
+ 3f/b29v/2NjY/9fX1//Y2Nj/1dXV/9DQ0P+enp59AAAADwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAA
+ ACUAAABCAAAAZQAAAIaUlJTd1tbW/+fn5//m5ub/5ubm/+fn5//p6en/6urq/+vr6//s7Oz/7Ozs/+zs
+ 7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u7v/u7u7/7+/v/+7u7v/u7u7/7u7u/+/v
+ 7//v7+//8PDw//Dw8P/w8PD/8PDw//Hx8f/x8fH/8fHx//Hx8f/w8PD/7+/v/+/w7v/s7ev/4eHh/9rZ
+ 2//T0tb/xcTI/5Gaxv8UEvT/Nzbg/zE09P9FN///TTn+/0dC+/9QSv3/Yln//2Zo9v9rYP//NB///1Zh
+ 0P+aobX/sLSu/8fEvP/E0L7/0tHT/9vV1v/o5ef/2+Dj/+ft8v/q6e3/8ubs//Hx8f/u7u7/8vLy//Dw
+ 8P/v7+//8fHx//Dw8P/v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7u7u/+7u7v/u7u7/7u7u/+7u
+ 7v/u7u7/7e3t/+3t7f/t7e3/7e3t/+3t7f/s7Oz/7Ozs/+vr6//r6+v/7Ozs/+vr6//r6+v/6urq/+rq
+ 6v/q6ur/6urq/+np6f/p6en/6enp/+jo6P/o6Oj/6Ojo/+jo6P/o6Oj/5+fn/+fn5//m5ub/5ubm/+Xl
+ 5f/l5eX/5eXl/+Tk5P/k5OT/4+Pj/+Pj4//j4+P/4uLi/+Hh4f/f39//39/f/97e3v/c3Nz/2dnZ/9jY
+ 2P/Y2Nj/2NjY/9HR0f+dnZ19AAAADwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAA
+ AIaUlJTd19fX/+fn5//m5ub/5+fn/+jo6P/p6en/6+vr/+zs7P/s7Oz/7e3t/+3t7f/t7e3/7e3t/+3t
+ 7f/t7e3/7e3t/+3t7f/u7u7/7u7u/+7u7v/v7+//7+/v/+/v7//u7u7/7u7u/+/v7//w8PD/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/w8PD/8fHx//Hx8f/y8vL/8fHx//Dx7//t7uz/4uLi/9rZ2//T0tb/xMPH/2ln
+ 2P8yMPj/Vk7u/0tM9P9FP/L/Rz31/zg27v9AO///Sj/6/1xR//9YVvz/X17//zsu//9VUtD/q6W8/7i3
+ u//ExcP/xsnH/9LQ3P/d3tX/6e3h/9/h6f/t7+//8e/n//Hx8f/u7u7/8fHx//Hx8f/w8PD/8PDw/+/v
+ 7//w8PD/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+7u7v/u7u7/7u7u/+7u
+ 7v/u7u7/7e3t/+3t7f/t7e3/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/r6+v/6+vr/+vr6//q6ur/6urq/+rq
+ 6v/p6en/6enp/+np6f/p6en/6Ojo/+jo6P/o6Oj/5+fn/+fn5//n5+f/5+fn/+bm5v/l5eX/5eXl/+Xl
+ 5f/k5OT/5OTk/+Tk5P/k5OT/4uLi/+Hh4f/g4OD/39/f/97e3v/c3Nz/2tra/9jY2P/Z2dn/2NjY/9LS
+ 0v+dnZ19AAAADwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd19fX/+fn
+ 5//m5ub/6Ojo/+jo6P/q6ur/6+vr/+zs7P/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u7v/u7u7/7u7u/+7u
+ 7v/u7u7/7u7u/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Dw8P/w8PD/8PDw//Dw8P/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/y8vL/8fHx//Dx7//u7+3/5eXl/97d3//W1dn/xsXJ/0M67/9MR/b/cGft/2Ji
+ 8v9fYfX/T1fw/zs18v8wNfX/Pjz0/0g89P9DQ/v/V1n0/2JZ/f86Mf3/W1vR/6mmv/+4tLr/xc3C/8XH
+ z//d3Nj/6OLj/+Li3P/m6+L/7/Lw//Hx8f/t7e3/8PDw//Ly8v/x8fH/8PDw//Dw8P/y8vL/8PDw//Dw
+ 8P/w8PD/8PDw/+/v7//v7+//7+/v/+/v7//w8PD/7+/v/+/v7//v7+//7+/v/+7u7v/u7u7/7u7u/+7u
+ 7v/t7e3/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/6+vr/+vr6//r6+v/6+vr/+rq6v/q6ur/6enp/+np
+ 6f/p6en/6enp/+np6f/o6Oj/6Ojo/+fn5//n5+f/5+fn/+bm5v/m5ub/5ubm/+bm5v/l5eX/5eXl/+Tk
+ 5P/k5OT/4uLi/+Hh4f/g4OD/39/f/97e3v/c3Nz/2tra/9jY2P/Z2dn/2dnZ/9LS0v+ioqKHAAAADwAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd19fX/+jo6P/n5+f/6Ojo/+np
+ 6f/q6ur/6+vr/+zs7P/t7e3/7e3t/+3t7f/u7u7/7u7u/+7u7v/u7u7/7u7u/+/v7//v7+//7+/v//Dw
+ 8P/w8PD/8PDw//Dw8P/v7+//8PDw//Dw8P/x8fH/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Hy8P/v8O7/6enp/+Lh4//Z2Nz/ysnN/y0u7v9lZe//eW/4/2509f9OTvT/IyPr/0M3
+ 4/8lFez/Lif+/0hL9P9AOvP/Qz71/1xL//9gWv//LSr1/2Fb0v+lqrn/sre2/8TDxf/RzNX/2t7L/+zi
+ 8v/m5ef/4efm/+/v7//u7u7/8PDw//Ly8v/y8vL/8fHx//Hx8f/y8vL/8fHx//Dw8P/w8PD/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/v7+//7+/v/+/v7//v7+//7+/v/+7u7v/u7u7/7e3t/+3t
+ 7f/t7e3/7e3t/+3t7f/s7Oz/7Ozs/+zs7P/s7Oz/6+vr/+vr6//q6ur/6urq/+rq6v/q6ur/6enp/+np
+ 6f/p6en/6Ojo/+jo6P/o6Oj/5+fn/+fn5//n5+f/5ubm/+bm5v/m5ub/5eXl/+Xl5f/l5eX/4+Pj/+Li
+ 4v/h4eH/4ODg/9/f3//d3d3/29vb/9nZ2f/a2tr/2tra/9LS0v+jo6OKAAAADwAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd19fX/+jo6P/n5+f/6Ojo/+np6f/q6ur/6+vr/+zs
+ 7P/t7e3/7e3t/+3t7f/v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Dw8P/x8fH/8fHx//Dw
+ 8P/w8PD/8PDw//Hx8f/y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz8//09PT/8/Pz//Hy
+ 8P/w8e//6+vr/+Tj5f/b2t7/zczQ/yst/f9mYvf/dXn2/1FW+f8mFv3/FAj8/3iNrP93ha//RD7f/zY6
+ 7f9YVvD/TUf0/z00//9VSfv/Y13//yUp7P9nacf/pqe7/765tv/Aw8H/z9XU/+Ld3//n3+r/4efm/+zs
+ 7P/v7+//8PDw//Hx8f/y8vL/8vLy//Pz8//y8vL/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Dw
+ 8P/w8PD/8PDw//Dw8P/w8PD/8PDw/+/v7//v7+//7+/v/+/v7//u7u7/7u7u/+3t7f/u7u7/7u7u/+3t
+ 7f/t7e3/7e3t/+3t7f/t7e3/7Ozs/+zs7P/r6+v/6+vr/+vr6//q6ur/6urq/+rq6v/p6en/6enp/+jo
+ 6P/o6Oj/6Ojo/+fn5//n5+f/5+fn/+bm5v/m5ub/5ubm/+Xl5f/l5eX/4+Pj/+Li4v/h4eH/4ODg/9/f
+ 3//d3d3/29vb/9nZ2f/b29v/2tra/9PT0/+kpKSKAAAADwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAA
+ ACUAAABCAAAAZQAAAIaUlJTd2NjY/+np6f/o6Oj/6Ojo/+np6f/q6ur/7Ozs/+3t7f/t7e3/7u7u/+7u
+ 7v/v7+//7+/v//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Ly
+ 8v/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Dx7//w8e//7e3t/+jn
+ 6f/g3+P/09LW/ygx7f9hXvr/anX1/ykn/f8yKv//GAv7/3+RqP+Wlqb/h46h/0A21v86PPT/XVr9/0JH
+ 6v9EQ/3/WVD7/09R//8wIO//f4W0/66ru/+8v8P/xs3K/83Pyf/g29z/6Orq/+np6f/v7+//8PDw//Dw
+ 8P/y8vL/8/Pz//T09P/y8vL/8vLy//Ly8v/y8vL/8vLy//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/w8PD/8PDw//Dw8P/w8PD/7+/v//Dw8P/v7+//7u7u/+7u7v/u7u7/7u7u/+7u7v/u7u7/7u7u/+7u
+ 7v/t7e3/7e3t/+zs7P/s7Oz/7Ozs/+zs7P/r6+v/6urq/+rq6v/q6ur/6enp/+np6f/p6en/6Ojo/+jo
+ 6P/o6Oj/5+fn/+fn5//m5ub/5ubm/+bm5v/m5ub/5OTk/+Pj4//i4uL/4eHh/+Dg4P/e3t7/3Nzc/9ra
+ 2v/c3Nz/29vb/9PT0/+kpKSKAAAADwAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAA
+ AIaUlJTd2NjY/+np6f/o6Oj/6enp/+np6f/r6+v/7Ozs/+3t7f/u7u7/7u7u/+7u7v/w8PD/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/x8fH/8fHx//Hx8f/y8vL/8vLy//Ly8v/x8fH/8fHx//Ly8v/z8/P/8/Pz//Pz
+ 8//z8/P/8/Pz//Pz8//z8/P/9PT0//T09P/y8vL/8/Pz//Hy8P/x8vD/8PDw/+3s7v/n5ur/29re/ycn
+ 7/9QTvz/SEX4/ygm/P9XV///JBv0/3WBt/+ippv/m56c/4aOrP8lEvH/SEbz/15c9v86QO3/RTv//2NS
+ //9CPvv/PCTu/5Cdtf+wtLX/wr7E/8vMyP/b3Nj/4d/f/+jo6P/u7u7/7+/v//Hx8f/z8/P/8vLy//Pz
+ 8//z8/P/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/w8PD/8PDw//Dw8P/w8PD/7+/v/+/v7//v7+//7+/v/+/v7//u7u7/7u7u/+7u7v/u7u7/7e3t/+3t
+ 7f/t7e3/7Ozs/+zs7P/r6+v/6+vr/+vr6//q6ur/6urq/+np6f/p6en/6enp/+jo6P/o6Oj/6Ojo/+jo
+ 6P/n5+f/5+fn/+fn5//m5ub/5OTk/+Pj4//i4uL/4eHh/+Dg4P/e3t7/3Nzc/9ra2v/d3d3/29vb/9PT
+ 0/+kpKSKAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd2NjY/+np
+ 6f/o6Oj/6enp/+rq6v/r6+v/7e3t/+7u7v/u7u7/7+/v/+/v7//w8PD/8PDw//Dw8P/w8PD/8fHx//Hx
+ 8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/z8/P/9PT0//T09P/09PT/9PT0//T0
+ 9P/09PT/9PT0//T09P/19fX/9vb2//P08v/z9PL/8vLy/+/u8P/q6e3/397i/z0++v8vHv//MCH4/z5B
+ +v9TSv7/OTL//1BI0f+ema7/lZyl/5KYl/9zc6n/Jxf4/05b9/9fWO//RTX0/05I+/9cWf//ODH4/1hZ
+ y/+nqq7/w7i7/8bHxf/O0dn/5N/g/+jo6P/t7e3/7e3t//Hx8f/09PT/8fHx//Pz8//09PT/8/Pz//Pz
+ 8//y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/w8PD/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+7u7v/u7u7/7u7u/+3t7f/t7e3/7e3t/+3t
+ 7f/r6+v/6+vr/+vr6//q6ur/6urq/+rq6v/p6en/6enp/+np6f/p6en/6enp/+jo6P/o6Oj/5+fn/+fn
+ 5//n5+f/5eXl/+Tk5P/i4uL/4eHh/+Dg4P/f39//3Nzc/9ra2v/d3d3/3Nzc/9PT0/+kpKSKAAAAEAAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd2tra/+rq6v/q6ur/6enp/+rq
+ 6v/s7Oz/7e3t/+7u7v/v7+//8PDw//Dw8P/w8PD/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Pz
+ 8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9PT0//T09P/19fX/9fX1//X19f/19fX/9fX1//X1
+ 9f/29vb/9vb2//X19f/z8/P/8fHx/+/v7//s7Oz/6enp/3OH8v8uIfP/DQX5/0VD//9NQv//Oj7//xkd
+ /v9ZYsn/qaCj/6KXof+VlpT/UFPA/y8r7v9mafP/WVT3/0Y5+f9RTP//XFj9/yAd//9vc8T/pqjA/7y+
+ xv/Rysf/0tLM/+Li4v/l5eX/7e3t//T09P/v7+//8vLy//T09P/y8vL/9PT0//T09P/z8/P/8/Pz//Pz
+ 8//z8/P/8vLy//Ly8v/y8vL/8fHx//T09P/z8/P/8/Pz//Pz8//w8PD/8PDw//Hx8f/x8fH/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/w8PD/8PDw/+/v7//v7+//7+/v/+3t7f/t7e3/7u7u/+zs7P/r6+v/6+vr/+vr
+ 6//r6+v/6urq/+rq6v/r6+v/6+vr/+np6f/q6ur/6Ojo/+jo6P/q6ur/6Ojo/+bm5v/n5+f/5ubm/+Tk
+ 5P/l5eX/5OTk/+Dg4P/e3t7/3d3d/9ra2v/d3d3/3d3d/9PT0/+jo6OLAAAAEAAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAFAAAAEQAAACUAAABCAAAAZQAAAIaUlJTd29vb/+vr6//q6ur/6urq/+vr6//s7Oz/7e3t/+7u
+ 7v/v7+//8PDw//Dw8P/x8fH/8fHx//Hx8f/x8fH/8fHx//Ly8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Pz
+ 8//z8/P/8/Pz//Pz8//z8/P/9PT0//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//T0
+ 9P/z8/P/8/Pz//Ly8v/w8PD/7e3t/8LF8f8bE/r/NTH8/z0z//89Ov//OD3w/0Mu9f8hEv//ZmrQ/5+i
+ p/+ampr/hYmb/0pFyv89QvX/XF/9/1VM8P9JO/7/VFf//1RK+v8rIPL/lqSi/7GtuP+5vb7/1tHQ/9nZ
+ 2f/e3t7/5eXl/+zs7P/r6+v/8fHx//T09P/19fX/8PDw//Ly8v/19fX/9fX1//X19f/09PT/8/Pz//Ly
+ 8v/z8/P/8vLy//T09P/y8vL/8vLy//Pz8//x8fH/8vLy//Ly8v/y8vL/8fHx//Hx8f/w8PD/8PDw//Dw
+ 8P/w8PD/7+/v/+7u7v/v7+//7+/v/+3t7f/t7e3/7u7u/+3t7f/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+vr
+ 6//q6ur/6enp/+rq6v/r6+v/6Ojo/+fn5//o6Oj/6Ojo/+bm5v/l5eX/4+Pj/+Li4v/j4+P/4uLi/9/f
+ 3//d3d3/3Nzc/9ra2v/d3d3/3d3d/9TU1P+jo6OLAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAA
+ ACUAAABCAAAAZQAAAIaUlJTd29vb/+vr6//q6ur/6+vr/+vr6//t7e3/7u7u/+7u7v/v7+//8PDw//Dw
+ 8P/x8fH/8fHx//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Pz8//z8/P/8/Pz//Pz8//09PT/9PT0//T0
+ 9P/09PT/9PT0//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//T09P/09PT/9fX1//b2
+ 9v/09PT/8vLy/+3m8/+Lg/j/HR/2/zQz9P84M+z/STv1/z09+/85Lf//FhP4/2tzzP+YoZ7/oJOh/3aB
+ of8pGfP/VVj3/2Fh8f9IPe3/R0D//2Vc//87NP//UljD/6inq/+qrrn/ycTB/87Ozv/Y2Nj/4eHh/+jo
+ 6P/p6en/7u7u/+3t7f/s7Oz/7u7u//Ly8v/09PT/8/Pz//Ly8v/y8vL/8/Pz//Pz8//z8/P/8vLy//T0
+ 9P/z8/P/8/Pz//T09P/y8vL/8/Pz//Ly8v/y8vL/8vLy//Hx8f/x8fH/8fHx//Hx8f/x8fH/7+/v/+/v
+ 7//w8PD/7+/v/+7u7v/t7e3/7u7u/+7u7v/u7u7/7e3t/+vr6//r6+v/6urq/+rq6v/p6en/6Ojo/+rq
+ 6v/o6Oj/5ubm/+Xl5f/l5eX/5+fn/+fn5//k5OT/4uLi/+Hh4f/i4uL/4eHh/9/f3//e3t7/3d3d/9vb
+ 2//d3d3/3t7e/9TU1P+lpaWNAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQAAACUAAABCAAAAZQAA
+ AIaUlJTd29vb/+vr6//r6+v/6+vr/+zs7P/t7e3/7u7u/+/v7//v7+//8PDw//Hx8f/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9fX1//X1
+ 9f/19fX/9fX1//X19f/19fX/9fX1//X19f/29vb/9vb2//X19f/19fX/9vb2//f39//19fX/8vLy//f2
+ 6P/a4fL/aWP2/yEj8/8/P/H/QT/t/zkz8P87Ovz/OzD//xUW+v9aWNr/n6Gp/5qZuf9VV8P/OSz8/2pw
+ 7f9eU/D/Qzr8/01Q+f9iWf//LyT9/29zrf+sqLP/tby5/8TExP/Q0ND/1tbW/9zc3P/g4OD/6Ojo/+rq
+ 6v/s7Oz/8PDw//Pz8//09PT/8/Pz//Ly8v/z8/P/8/Pz//Pz8//z8/P/8vLy//X19f/19fX/9fX1//b2
+ 9v/z8/P/9PT0//Ly8v/y8vL/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8PDw//Dw8P/x8fH/8PDw/+7u
+ 7v/t7e3/7e3t/+3t7f/u7u7/7Ozs/+rq6v/p6en/6Ojo/+fn5//l5eX/5OTk/+bm5v/i4uL/4ODg/97e
+ 3v/d3d3/4eHh/+Pj4//f39//3t7e/97e3v/f39//39/f/9/f3//e3t7/3d3d/9zc3P/e3t7/3t7e/9TU
+ 1P+pqamXAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFAAAAEQQEBCYJCQlFCAgIaAgICImUlJTe2NjY/+fn
+ 5//n5+f/6urq/+zs7P/u7u7/7+/v/+/v7//w8PD/8fHx//Hx8f/y8vL/8vLy//Ly8v/z8/P/8/Pz//Pz
+ 8//z8/P/8/Pz//T09P/09PT/9PT0//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X1
+ 9f/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//19fX/8vLy/+jv+P/59uH/z8/t/ycW
+ //8rK/P/SEP9/0ZA8/81NvL/Ozb9/zg19v8wK/j/OTnj/31+uv+GjqX/QULa/0lE8/9xbfT/RkXz/0E8
+ /f9YVPr/Uk77/ygX8P+bnqP/nqmt/7e3t//Dw8P/ysrK/9HR0f/X19f/4eHh/+Tk5P/o6Oj/6enp/+zs
+ 7P/v7+//8fHx//Pz8//z8/P/8vLy//Hx8f/w8PD/7+/v//Ly8v/y8vL/8/Pz//T09P/y8vL/8/Pz//Pz
+ 8//z8/P/8vLy//Ly8v/x8fH/8fHx//Hx8f/x8fH/8PDw//Hx8f/w8PD/7+/v/+7u7v/t7e3/7Ozs/+zs
+ 7P/r6+v/6urq/+jo6P/n5+f/5ubm/+Pj4//f39//3d3d/97e3v/Z2dn/19fX/9XV1f/T09P/19fX/9ra
+ 2v/W1tb/2NjY/9nZ2f/a2tr/2tra/9vb2//b29v/2tra/9ra2v/e3t7/3t7e/9XV1f+qqqqXAAAAEAAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAFKioqFzAwMDI1NTVXMTExfC0tLZuWlpbkzc3N/9nZ2f/a2tr/4ODg/+fn
+ 5//s7Oz/7+/v//Dw8P/x8fH/8fHx//Ly8v/z8/P/8/Pz//Pz8//z8/P/8/Pz//T09P/09PT/9PT0//X1
+ 9f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2
+ 9v/19fX/9vb2//b29v/29vb/9/f3//f39//29vb/9PT0//T3/P/o7fD/8vX6/8W+9/8gGPH/NCr4/01J
+ 7v9GS+3/RDvp/z89+/88Qfz/MS72/ycg8/9YVdD/dHiz/x8V//9gYPr/Wl7z/0FB7f9MQv//YFv//zwy
+ 9v9UT8r/j5al/6urq/+3t7f/v7+//8fHx//Ozs7/1tbW/9jY2P/c3Nz/4ODg/+Dg4P/k5OT/6enp/+3t
+ 7f/u7u7/8PDw//Hx8f/v7+//7+/v//Hx8f/x8fH/8vLy//T09P/z8/P/9PT0//X19f/09PT/8/Pz//Ly
+ 8v/y8vL/8fHx//Hx8f/x8fH/7u7u/+/v7//u7u7/7e3t/+zs7P/r6+v/6Ojo/+jo6P/n5+f/5eXl/+Li
+ 4v/f39//3Nzc/9ra2v/Y2Nj/19fX/9LS0v/Nzc3/zc3N/87Ozv/MzMz/z8/P/9LS0v/Q0ND/0NDQ/9LS
+ 0v/U1NT/1tbW/9nZ2f/Z2dn/2dnZ/9ra2v/e3t7/39/f/9XV1f+qqqqXAAAAEAAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AABQUFAKZGRkKWtra1dxcXGMcXFxsXFxccqbm5vytLS0/7i4uP+7u7v/yMjI/9nZ2f/m5ub/7u7u//Dw
+ 8P/x8fH/8vLy//Pz8//z8/P/8/Pz//Pz8//09PT/9PT0//T09P/09PT/9PT0//X19f/19fX/9fX1//X1
+ 9f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//39/f/9/f3//f39//19fX/9vb2//b2
+ 9v/29vb/9/f3//f39//39/f/9vb2//b69f/w9vH/+f3y/+bv8//d2/j/ZGXz/zMs8/9MSO7/UEj5/0k/
+ 7f8uM/r/Qz///0k2//8rJv7/FRDv/0M/5P82Mf7/b3Xy/05I9f9JPvj/Tkz//2Vm9P8rF/n/eX+u/5ub
+ m/+kpKT/rKys/7a2tv+8vLz/x8fH/83Nzf/S0tL/19fX/9fX1//a2tr/4eHh/+Xl5f/m5ub/6urq/+/v
+ 7//u7u7/7u7u//Hx8f/y8vL/8/Pz//X19f/09PT/9fX1//Pz8//z8/P/8vLy//Hx8f/x8fH/8fHx//Hx
+ 8f/x8fH/7e3t/+7u7v/r6+v/6enp/+np6f/m5ub/4+Pj/+Li4v/f39//3Nzc/9jY2P/U1NT/0NDQ/87O
+ zv/Nzc3/zMzM/8XFxf/CwsL/xMTE/8bGxv/FxcX/xsbG/8jIyP/IyMj/ycnJ/8zMzP/Ozs7/0tLS/9bW
+ 1v/Y2Nj/2dnZ/9vb2//e3t7/39/f/9XV1f+oqKiYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnweJiYkgiYmJVouL
+ i5KNjY3Bj4+P3ZCQkOyenp77pKSk/6SkpP+np6f/srKy/8PDw//W1tb/5OTk/+7u7v/y8vL/8vLy//Pz
+ 8//z8/P/8/Pz//Pz8//09PT/9PT0//T09P/09PT/9fX1//X19f/19fX/9fX1//b29v/29vb/9vb2//b2
+ 9v/29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//29vb/9/f3//f39//39/f/9vb2//f3
+ 9//4+Pj/+Pj4//Dy/P/89/T/9u75//b48v/r8/P/5+n7/4F9+/8fIPT/RUL1/0xM9P9XRu3/PTL6/zU8
+ /f89Pfv/NDT+/xcU/f8XC/3/WV3x/29p7P9EPvf/TEX//1RW+v9WSfn/SkfF/4mJif+Tk5P/np6e/6ur
+ q/+xsbH/urq6/76+vv/CwsL/y8vL/8vLy//Q0ND/2dnZ/9vb2//a2tr/3d3d/+Pj4//k5OT/5eXl/+vr
+ 6//t7e3/7u7u/+/v7//t7e3/7e3t//Dw8P/w8PD/8PDw//Dw8P/w8PD/8fHx//Hx8f/x8fH/7u7u/+3t
+ 7f/q6ur/5+fn/+bm5v/j4+P/3t7e/93d3f/U1NT/09PT/9LS0v/Pz8//y8vL/8bGxv/CwsL/wMDA/729
+ vf+7u7v/vb29/8DAwP++vr7/u7u7/7u7u/+9vb3/w8PD/8bGxv/Jycn/zc3N/9PT0//W1tb/19fX/9nZ
+ 2f/e3t7/39/f/9bW1v+oqKiYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn5+fBp+fnxqYmJhNl5eXlKamptjIyMj12tra/dra
+ 2v7Pz8//ycnJ/6ampv+fn5//pKSk/66urv+/v7//1NTU/+Xl5f/v7+//8/Pz//T09P/09PT/9PT0//X1
+ 9f/19fX/9fX1//X19f/19fX/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f3
+ 9//39/f/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//r5
+ 9f/59/b/9fX1//X29P/y9fP/9vX//+Xg/f+9suD/ERf+/zIt9P9ZUO3/VUnv/0E79P84N+v/QTz1/0M9
+ +v8pJ/3/HSD+/2xv+f9kWfX/Qz3u/05M+v9dX///PC3z/1tbp/+OgpT/kZSS/5ydof+qoK3/qq6i/6+r
+ t/+stK3/vLe4/8TCwf/BxcD/xsvJ/8nPzv/P0tb/0dLW/9bX2//Y2Nj/2tra/+Dg4P/j4+P/5OTk/+bm
+ 5v/o6Oj/5+fn/+bm5v/o6Oj/6urq/+3t7f/q6ur/6urq/+/v7//v7+//5+vg/+Lj3//h4t7/3+LZ/9rY
+ 2P/Y0t3/19PY/9LUyP/Qzs3/ycfH/8PCxv/Bwsb/v8HB/7u+vP+5ubn/tLO1/7Szt/+vrrD/r6+v/6+w
+ rv+srav/rq6u/7Kxs/+ysbX/uLm1/766wP/Cvcz/vcPC/8bP0v/O2dH/2NfT/+PX1//c3Nz/3t7e/9bW
+ 1v+pqamYAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACfn58Cn5+fFp+fn0K/v7+q7Ozs8/////////////////////////////////z8
+ /P/V1dX/ra2t/6Ojo/+srKz/vr6+/9PT0//m5ub/8fHx//T09P/19fX/9fX1//X19f/19fX/9fX1//X1
+ 9f/19fX/9fX1//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f3
+ 9//4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//v5+f/7+fn/+Pj4//n6
+ +P/2+vX/9vj5//Ly///m4fz/1tP6/3V5/f8kJPr/Oj3z/1pV+P9LQPv/Q0Dz/zky8f83Mfz/MSb//05G
+ /v9rbOz/UkT2/049//9bUP//VVf8/yAY7v9fd4P/kYmT/5yRk/+XlJD/lZmT/6itrP+qpKn/q6ux/7e2
+ uv/BvL7/yMHE/8jBxP/Kxcb/x8nD/8vRxv/Ozs7/1dXV/9nZ2f/X19f/1tbW/9zc3P/f39//3Nzc/+Xl
+ 5f/m5ub/5ubm/+fn5//k5OT/4+Pj/+jo6P/n5+f/5eHn/+Te6f/b2OH/1NXZ/9PV1v/MzdH/wsTE/8LD
+ v/+/wLz/urq6/7q1t/+4s7X/trGy/7CwsP+prLD/oqWt/6WkqP+ioqL/o6Sg/6SmoP+ho53/oaKe/6Oj
+ o/+joqb/qquh/7Kzt/+xta//v7y3/8/Lxv/Q1Mn/y8rU/9XV1f/c3Nz/3d3d/9bW1v+pqamYAAAAEAAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACfn58Hn5+fLby8vIL7+/v8////////////////////////////////////////////////+fn5/66u
+ rv+ioqL/ra2t/7+/v//a2tr/7Ozs//Pz8//19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9vb2//b2
+ 9v/29vb/9vb2//b29v/29vb/9/f3//f39//39/f/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//j4
+ +P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//z5+//8+fv/+Pf5//n6+P/4/Pb/9Pjy//T2
+ 9v/29/v/9Pn3/+rt8f+mpvT/KBzw/yMc+f9MSez/WVD6/0pP8f9VR/P/OC7z/yAe+v9ubfL/bF75/zY8
+ 7f9IR/H/cmH//00/8f9BSLv/dX2K/3+Gf/+LkI//m5ed/5OYmf+inZz/ra+p/6ysrP+tq7H/srGz/7i4
+ sv/Awbf/xMW8/8XDwv/Hx8f/yMjI/8zMzP/Ozs7/zc3N/8/Pz//U1NT/19fX/9ra2v/b29v/2tra/9zc
+ 3P/a2tr/2tra/93d3f/d3d3/2tLc/9bU1P/Kz8b/xMzB/8PKxf+8v8P/s7K7/7Cwtv+tq7H/q6ix/6ik
+ r/+joKn/n5+f/6Ghm/+hopn/n5yX/5udl/+Zmpj/mpmb/5qYnv+WlJr/lpWX/5mamP+Zm5X/o52Y/6iq
+ qv+rrbX/xL+8/8q+vP/Mws7/y8/J/8zO2P/b29v/3d3d/9bW1v+pqamYAAAAEAAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwGfn58OxcXFYvr6
+ +vX///////////////////////////////////////////////////////////Dw8P+lpaX/o6Oj/6+v
+ r//Kysr/4eHh//Hx8f/19fX/9fX1//X19f/19fX/9vb2//b29v/29vb/9vb2//b29v/29vb/9/f3//f3
+ 9//39/f/9/f3//f39//39/f/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5+fn/+fn5//n5
+ +f/5+fn/+fn5//n5+f/5+fn/+fn5//r4+P/6+fv/+fj6//n4+v/8/fv/+Pz3//X58//1+fP/9/f//+7x
+ 9f/6+fv/7PHw/5yd+P8kHPL/Lij9/1hO9P9UX/f/U1Ts/y4r8/9IRPv/a2/z/0tN8v9LQf//XVD6/2Nd
+ //8tG/L/YWaX/4OFhf99g4j/i5eL/42Slf+cmJ3/nKSZ/6Knnv+ur63/s7Cy/6qprf+tq7H/r7G5/7K1
+ vf++vr7/urq6/729vf/CwsL/wsLC/8HBwf/Gxsb/zMzM/87Ozv/Pz8//zs7O/8/Pz//Pz8//zc3N/83N
+ zf/Ly8v/0M7G/8TCwf+6vbv/trq1/6+xsf+tq7H/rKmr/6mnn/+copf/m5+Z/5ibmf+Ul5X/kZWP/5SW
+ kP+Yl5P/m5aX/4+Rmf+NkJX/jI+U/4qNkf+GiY3/h4qP/4yPlP+OkJj/oZ2i/6akpP+orKf/sriz/7q+
+ sv/NyMf/19HW/9PQ3//c3Nz/3t7e/9fX1/+tra2jAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwHW1tYo+vr65///////////////////
+ ///////////////////////////////////////////////////i4uL/oKCg/6enp/+4uLj/0dHR/+np
+ 6f/09PT/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//j4
+ +P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5
+ +f/5+fn/+fn5//j4+P/5+fn/+/r8//r5/f/49/v/+fj8//r6+v/6+/f/9/b4//z3///39/f/8fL8/+Xr
+ 8v/g7Pj/ioz4/ycY9f8oKvT/VFb6/09Q+P8gG/j/YWP9/3Bo9f8/PPD/Q0L8/2Jg//89QvX/Gwv4/0s4
+ 1f9sa63/fYSd/5CLoP+LlZX/pZ6b/6Kdn/+ko6z/oqWt/6Knqv+nrKv/sK6t/7Svrv+0tLT/tLS0/7W1
+ tf+1tbX/tra2/7q6uv+9vb3/u7u7/7+/v//AwMD/wMDA/8LCwv/CwsL/wMDA/76+vv+7u7v/uLyw/7Kx
+ tf+vq7f/qamp/6Khnf+emJ3/nJSb/5mRkf+WkJH/k5GR/42Skf+KlZP/hpKW/36Lm/94fqH/dnep/2dl
+ sf9mY7P/ZmC5/2Rcu/9hWbj/Yly1/2Visv9nZbH/e4ml/5uepv+xrLX/srq6/7/Kwv/Hwcb/zsbH/9jf
+ 0v/c3Nz/3t7e/9fX1/+vr6+lAAAAEAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwL29vaE////////////////////////////////////////
+ ////////////////////////////////////////w8PD/6Kiov+rq6v/wcHB/9vb2//t7e3/9vb2//b2
+ 9v/29vb/9vb2//f39//39/f/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//n5
+ +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//v8
+ +v/3+Pb/+fr4//r5+//39P3/9/T9//n4/P/6+vr///nu///6///y8v//9Pv+//H39v/y8///3+T9/9Pj
+ +v+SkPT/NiD0/zQt+v8dK+//Ozr7/3Rn//9SU/H/Rz/3/01P//9dYv3/LSX//ywk7f8fGPX/HhL4/19Y
+ x/98fan/n52z/6Chr/+lqqv/oKih/6erpf+srav/rqqp/6+qqf+urq7/rKys/6ysrP+vr6//sLCw/7Ky
+ sv+ysrL/sLCw/62trf+vr6//rq6u/7Gxsf+0tLT/srKy/7CwsP+urq7/oqem/6WnqP+joaH/nZqV/5qX
+ k/+VkJH/iouH/4iNfv9+h4v/fIKJ/3h7iv9ycZj/ZmCx/0lCzf8rH+n/Gwv8/xwb+/8eHfz/HyD6/x8h
+ +P8eIPf/HR74/xwb+v8bGvr/JxX2/2t1q/+io7f/sre6/7vAv//OxtH/1NDV/8vWzv/b29v/3t7e/9fX
+ 1/+vr6+lAAAAEQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwP6+vqw////////////////////////////////////////////////////////
+ ////////////////////////+fn5/6qqqv+jo6P/srKy/8jIyP/i4uL/8fHx//b29v/39/f/9/f3//f3
+ 9//39/f/9/f3//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5
+ +f/5+fn/+fn5//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//z7/f/3+Pb/+fr2//v8
+ +v/7+v7//vr///z5+//9/Pj//P37//r49////fX//f70//T6///r9/n/+v/0//rv8f/o6f7/zM/u/46H
+ //8gHPf/Fhjy/2lq+P9vYvT/TT/4/0pG+f9iWv//TUr+/zAl//9CRvP/ODb0/ysi9P8oHf3/Ni3o/1pX
+ 3P+Hisf/nJ+u/66tr/+vrbP/pKit/6Gtrf+srKz/pqam/6ampv+qqqr/qamp/6Wlpf+jo6P/pKSk/6Cg
+ oP+ioqL/np6e/5+fn/+hoaH/n5+f/5+fn/+enp7/mpyk/56env+Yk5T/j4eR/4yHkP+DiIv/cn6K/2dy
+ kP9mY6H/U0+2/zgw0f8jGuz/IRf9/ygg//81Lvv/QDn4/zk4+v87Ovz/Ozn9/zs5/f87Of3/Ozn9/zk4
+ +v82Nff/IRv8/y4d9v9VRdj/qbK7/7+7xv/HycP/ztHP/87Q2P/b29v/3t7e/9fX1/+vr6+lAAAAEQAA
+ AAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+f
+ nwP9/f3Y/////////////////////////////////9/X//+cg///7Of/////////////////////////
+ /////////////+Li4v+goKD/p6en/7a2tv/S0tL/5+fn//T09P/39/f/9/f3//f39//39/f/9/f3//j4
+ +P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vr6//r6
+ +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r5/f/7/Pr//f/5//n79f/7+fn//fr8//r5
+ 9f/7/PP/9vn9//f79f/6+vr///r////99P//+fX//vb///b4+f/v+ez/6unr/+Lk7P+3t+X/S0jy/zE1
+ +P9xdfL/YFrv/0k4+f9YSvz/ZmT//yQi/v86N/H/UUnq/0VJ9v9DR+z/Oj7x/y8r9v8lGfX/Jx3i/1xX
+ 4v+NjtL/oqW0/7KwqP+vr6//rq6u/62trf+oqKj/o6Oj/6Ghof+enp7/mJiY/5WVlf+VlZX/kJCQ/5CQ
+ kP+Tk5P/lJSU/5WVlf+Wlpb/jY6S/42Pif+QjIv/jYaN/3+Egv9ueIn/Tkm2/zER5v8VF/H/JCP7/zQu
+ //88Nv//QDz//z49/v84O///Njr//0I4/f9COPz/Pzf2/z028f8+N/L/Pzf2/z81+f89M/j/ODn5/yQm
+ /P8lFvP/nKLP/8DDwf/O18r/0dbV/9jT0P/b29v/3t7e/9jY2P+wsLClAAAAEQAAAAQAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAM/Pzwb////7////////
+ /////////////////////////1wz//8zAP//ZT////z7////////////////////////////////////
+ ///Dw8P/oaGh/6qqqv/CwsL/2tra/+7u7v/19fX/9/f3//f39//39/f/9/f3//j4+P/4+Pj/+Pj4//j4
+ +P/4+Pj/+Pj4//j4+P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/6+vr/+fn5//j4
+ +P/29vb/9PT0//Ly8v/19fX/9/f3//n5+f/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6
+ +v/6+vr/+vr6//v7+//7+/v/+vr6//n5+f/49O//7e/v/+Xq6//n5OD/wMTg/yIX+f9rYfv/a2j0/0RB
+ 9f9JQ///WVP//1hS/f8lHfb/QTH6/zw+8P9HO+3/TUbv/0pC8/9ERO7/PD73/yss+P8fHfP/Ghbr/z5F
+ 8P+Hhcv/k5rB/5qewf+borH/pK2q/5mapP+Ulpf/lJeO/42Slf+Nloz/iJKG/4aKhf+MiYT/kJCC/42R
+ i/+DhZD/i4aD/4uJif99gpH/ZW2i/zpCvf8bF/L/IR///ywn//9DOP//RDv//0U8/v9DOvz/QTb2/0U8
+ 8f9VTvL/ZmP1/3ty8f97e+//dnj0/3J38v9zcv7/cWz9/3Bt+f9rbu7/aV76/01P8/8DE/n/nprb/8rG
+ y//Z0dz/1NfO/9PQ2f/a2tr/3d3d/9fX1/+xsbGlAAAAEQAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPf39yL/////////////////////////////
+ /////////zkH//8zAP//MwD//6KL///////////////////////////////////////5+fn/qamp/6Oj
+ o/+wsLD/yMjI/+Tk5P/x8fH/9/f3//f39//4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5
+ +f/5+fn/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+Pj4//X19f/y8vL/7u7u/+rq6v/l5eX/4eHh/9/f
+ 3//j4+P/6urq//Dw8P/19fX/+fn5//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+/v7//v7
+ +//7+/v/+vr6//n5+f/7/Pj//Pf///Xx/f/k7Ov/1tnn/4KH3P8vL/n/fXn2/1pf8P9EOfP/VUj3/2Jd
+ /v84Mv3/PTr//1NL//9OR/z/RTv//zwy+v9DQvD/Qjzv/0o/+v9KR/H/Q0D0/zUx9f8hJOv/HhH7/yIP
+ 7v9QS+L/ZWTM/3p5u/+Lkqb/goOd/4WFl/+Khov/jYWF/42FjP+Ig5L/hYaQ/4eKjv+LiYn/gYKW/29u
+ pv9DOsr/IRX3/ywp+v9AOPr/Qjf5/0I6/f9EPPX/QD3x/0ZK7/9dZvP/dX/1/36F8v95e/H/cHHx/1BJ
+ /v9BOPr/NCj8/ygi/f8bFv//Iyn0/yof/f9BMv//YmT4/2tv7P8ZE/z/mpLZ/8zX1f/X1t//2Nnd/9Pc
+ 2f/b29v/3t7e/9jY2P+xsbGlAAAAEQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAANnZ2QX//////////////////////////////////////0IT//8z
+ AP//MwD//zkH///f1///////////////////////////////////////4uLi/6CgoP+np6f/uLi4/9LS
+ 0v/p6en/9vb2//j4+P/4+Pj/+Pj4//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+vr6//r6
+ +v/6+vr/+fn5//f39//09PT/7e3t/+Pj4//Y2Nj/zc3N/8TExP/AwMD/vb29/7y8vP/BwcH/ysrK/9jY
+ 2P/m5ub/8vLy//n5+f/7+/v/+/v7//v7+//7+/v/+vr6//r6+v/6+vr/+/v7//v7+//7+/v/+vr6//r6
+ +v/0+fj/+fTx//b08//m8Or/4+Pv/8fN1P8lJvL/Y1j6/2pr6/9MP/X/UT7//15X//9XTP//GhP2/15X
+ 9P9ga///bmD7/2ZZ+/9XTP//Qzj//0E8+/8+OvH/RT32/0tF6v9LQ/T/TUrz/0RB9f8zNPD/Jyj0/xob
+ +f8SFfn/Cg73/0o/y/9NRr//U1Kw/2Jkpf9udJf/dn6P/3mAlP92d53/QELE/yUX+f8vKP//RDz//0w6
+ //9GN///Qj30/0pE9/9qZ/n/dnj1/32B+P9qbf7/RkX//y4q+P8vMOz/PULk/2Jj1f90dcv/h46//3V7
+ xP9TVNr/Jhrw/y4s8P8zLfD/KCP6/0dA+/8YEPH/pqbU/8/S2v/k4Nv/4+DS/9rU3//d3d3/39/f/9jY
+ 2P+ysrKlAAAAEQAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwH//////////////////////////////////////0wf//8zAP//MwD//zMA//9f
+ N////Pv//////////////////////////////////////8PDw/+hoaH/rKys/7+/v//c3Nz/7+/v//f3
+ 9//4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//j4+P/09PT/7+/v/+fn
+ 5//f39//1dXV/8nJyf+8vLz/sbGx/6mpqf+np6f/paWl/6Wlpf+oqKj/sLCw/729vf/Ozs7/4ODg//Hx
+ 8f/4+Pj/+/v7//v7+//7+/v/+vr6//r6+v/7+/v/+/v7//v7+//7+/v/+vr6//r6+v/5+f//+vfz//L0
+ 9P/y7u3/7e3z/93f6v+Ijer/NSz+/3Jx9v9mX/b/Oy/z/0tD//9sY///Oiz8/zou5v81J/v/WUr//2pi
+ /f92c/H/dnT8/11Y+/9RT/3/T0r//0c8/P9GPfH/Qjjw/0tA+v9JRO3/UFDw/05J+P9JQvf/RT/w/zAs
+ 9/8qKvj/ICH7/xsW+/8bEPL/GxPq/x0Y7/8YFPX/LDD7/zY0/P9DQvb/PDf4/z476/9ZVPf/bm/7/3R/
+ +P9pbP3/SkT9/zIl9f88MuP/X1/L/3uBvP9/hMH/eXrL/2x5z/9iaNH/SELd/ygZ8f8lI/j/KS/6/zg6
+ 9/9OTff/dnf//1JJ//8mHvT/v7/d/+Tf3v/h3N7/2uTT/9ne3//e3t7/4ODg/9jY2P+0tLSqAAAAEQAA
+ AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+f
+ nwL+/v7i/////////////////////////////////2I7//8zAP//MwD//zMA//8zAP//mX//////////
+ //////////////////////////////n5+f+rq6v/pKSk/6+vr//Kysr/4+Pj//T09P/5+fn/+fn5//r6
+ +v/6+vr/+vr6//r6+v/6+vr/+vr6//n5+f/29vb/8/Pz/+7u7v/m5ub/29vb/8vLy/+9vb3/srKy/7Cw
+ sP++vr7/yMjI/9XV1f/j4+P/4eHh/7q6uv+goKD/oqKi/6enp/+xsbH/xMTE/+Li4v/z8/P/+vr6//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//3+/D/9Pvs//n7/P/48vP/9fDx/+Dh
+ 9f/PzeD/Jh3v/1ZW//9xcfP/UU3z/0U7//9dWfj/YVT8/zk96v99jc//YWvh/0xN8f82K/f/UD///21Z
+ //9+bvz/enD//2pf//9TVvj/U1D//0Y/+v9JQvf/Qjzp/0c97v9LP/P/TEXp/0ZJ8v9HRPT/RUH0/zo5
+ 8/8hIPL/EQz3/yUd/v89Ofz/RTv//0I99P9BPvH/Vlj6/3F87v95eP3/YFv8/zo28/8MDP//Dwz8/xIL
+ 9v8QCvf/Dgv6/xEQ+v8dGPX/KSDy/y0l9P8vKfj/PD/1/zs99v8+Nvn/Szr//2ld/f+Hgv3/hIT//0gx
+ 9/96h+n/1NXj/9vP4f/i4tb/3OHf/9Xc2f/f39//4ODg/9jY2P+0tLSyAAAAEgAAAAUAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwH+/v7a////////
+ /////////////////////////2xH//8zAP//MwD//zMA//8zAP//NQP//9nP////////////////////
+ ///////////////////n5+f/oKCg/6ampv+3t7f/0dHR/+vr6//29vb/+fn5//r6+v/6+vr/+vr6//r6
+ +v/4+Pj/9fX1//Dw8P/m5ub/29vb/8/Pz//ExMT/urq6/7Gxsf+9vb3/29vb//v7+///////////////
+ ///////////////////t7e3/vr6+/6Ghof+kpKT/s7Oz/9HR0f/p6en/+Pj4//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//+/f//9fj8///7/f/1+vj/8+3u//H25//g3+H/iZPq/y8t
+ +/9scun/Zlr6/0A16f9QUP//Ylv//zQs//+Bf8v/r7bH/73Az/+0sNr/lpbi/2dq8f8uJPL/Myb2/1NJ
+ 9/9sX/v/cGf+/3Jv+/9rZv//Xlj9/1dS//9NQ///ST///0RD9/8+Pvb/MCv4/ygd//8oH///NjD//0M8
+ //9DOP//PTf0/1tP//97cfr/gH3w/1BT8v8hG///MCr5/1ZD8P9RS/D/SEjw/0JG8v9ER/b/TEr4/05L
+ 9f9MTPT/Rkzx/0dI8P9ERPb/PkDy/z868/9cVfr/e23//5iS/f+Hd/r/QzD5/4eE4P/H0eL/3d/p/+Dn
+ 4P/h2+D/6ODh/+Hc3f/g4OD/4ODg/9jY2P+0tLSyAAAAEgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD9/f3D////////////////////////
+ /////////39f//8zAP//MwD//zMA//8zAP//MwD//1kv///8+///////////////////////////////
+ ////////x8fH/6Ghof+qqqr/v7+//9vb2//u7u7/9/f3//r6+v/5+fn/9vb2//Hx8f/q6ur/4eHh/9jY
+ 2P/MzMz/wMDA/7S0tP+0tLT/z8/P//Dw8P//////////////////////////////////////////////
+ /////////////+vr6/+jo6P/qamp/8DAwP/d3d3/9PT0//v7+//8/Pz//Pz8//v7+//7+/v/+/v7//z8
+ /P/8/Pz/+/v7//v7+//+/Pz/9fj8//v+7//4//j/8e/1//f26P/b2Oj/0tvo/ygX9P9bXPT/b231/1RM
+ 7f9AOv3/WVr//1FO8f9XUNv/tLm4/7fBwf+/ytL/z9jb/97d7f/Nzev/sb3n/4mT6v9QXvT/KB31/zYm
+ //9FOf3/XVH//29p/v94dPz/fHf8/3py//9LPf//KBr8/zAr/P9CPfz/Qzn9/0Q8+/9FRPL/enD//3J1
+ 9f9JT/b/IiT+/y4w8v9JP/f/T0T0/0NF6v9DQPP/Qz/y/0Q+8f9BPfD/PDvv/zs58P9BOPP/Rzj3/0Y7
+ /f9YS/r/Z1D+/4Zz//+RhP//hoH8/1pF+P9eUvL/qKfp/93j4v/s6N3/4ePk/9/m4//d3en/293e/93j
+ 3v/g4OD/4ODg/9jY2P+0tLSyAAAAEgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwH9/f23/////////////////////////////////4xv//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//+Zf///////////////////////////////////////+vr6/6ur
+ q/+jo6P/sLCw/8fHx//h4eH/8PDw//Pz8//w8PD/6Ojo/93d3f/Pz8//wcHB/7W1tf+vr6//xMTE/+Tk
+ 5P/+/v7/////////////////////////////////////////////////////////////////////////
+ ///Y2Nj/pKSk/7Gxsf/Pz8//7Ozs//j4+P/8/Pz//Pz8//v7+//7+/v/+/v7//z8/P/8/Pz//Pz8//v7
+ +///+/r//fz///T7+P/99v3/7Pj6//v19v/y7+r/3Njj/4eM6f89Mv7/ZXD2/11b9P9ENvn/Skf//3Nl
+ +f8pJPv/oJbB/7+9w//Oysn/2NjS/9fW2P/a1+f/3Nvd/+Db3P/Hx9X/trfM/5mexf9/gNb/WFrX/zY1
+ 3/8jGvf/Kyv//ywi//8vJf//NjD//z49//86Ovz/QDzz/2Fc9f+Affj/S1P0/ykf//8oIfj/Ny37/zoy
+ 9P9APPn/Rkf7/0dH//9TS///Uk///1NT+/9YVvz/YFf//2hd//9vZv3/dm77/4F+/P+Ihf//gHn//2hj
+ //9ANvv/VE/w/5ad7P/T3fX/4N70/9vk5//m5ub/4uPf/+nl4P/k5N7/4eDk/+Le3f/g4OD/4ODg/9fX
+ 1/+0tLSyAAAAEgAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwH8/Pyk/////////////////////////////////5l///8zAP//MwD//zMA//8z
+ AP//MwD//zMA//81A///2c///////////////////////////////////////+fn5/+fn5//pqam/7W1
+ tf/Ozs7/29vb/9zc3P/S0tL/yMjI/729vf+0tLT/urq6/9fX1//4+Pj/////////////////////////
+ ////////////////////////////////////////////////////////////////////////wcHB/6io
+ qP/CwsL/39/f//Pz8//7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz/+/v7//r6
+ +v/4+Pj/9vb2//X19f/u7u7/5eXl/8/a2P8hE///aGft/2xo9/9DSu3/RDz//2ZU//9WU/3/SVDj/7a4
+ wv/Bxcb/1MnF/9zV0v/K3Nv/3Nvd/9PO0P/Ix9D/w8PD/8G3xP+0qrf/pKOl/5OXqv9VW8z/Agz//zUo
+ //9FO///QTj//zk8/P9JT+7/eXT3/2tq8P8rL///FRb6/xwb+/8mI/v/NS/+/0hA//9bUf//amD//3Jp
+ //94bf//eW///3x1//+AeP//gHf//39y//95av//dmP//0pJ/f86MPX/QCzw/3Nm9/+usPD/2OLp/+Tq
+ 5f/p5+3/5+fn/+fn5//m5ub/5eXl/+Pj4//i4uL/4ODg/97e3v/g4OD/4ODg/9fX1/+zs7OzAAAAEgAA
+ AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD8/PyT/////////////////////////////////6+b//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//WS////z7///////////////////////////////////////Hx8f/oaGh/6ioqP+5ubn/wsLC/8HB
+ wf+3t7f/srKy/8vLy//s7Oz/////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////8/Pz/6SkpP+6urr/1tbW//Dw
+ 8P/7+/v//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz/+/v7//z8/P/8/Pz/+vr6//f3
+ 9//09PT/7+/v/9PZ5P+Ag+v/Oy///3Fw9f9TV+z/RDr+/1JM/f9hWv7/MiH7/5CYvf/AwMb/0s3E/8bI
+ yP/T0tz/zNDK/8nAyv/IxcH/ubi6/6myqP+pqaP/n5ms/1pZ0f8kHPz/OjP6/0ZB+v85Of//PT3v/2Nc
+ 8/9+dfv/Tkz6/ycg8/+Yjuv/lpXz/42M8/+AfvX/b231/15c9f9OTvT/REXz/z5A8v9IP/P/SD/0/0s/
+ 9f9MQfX/Uknz/1tX8/9naPb/cXP3/52d9/+usvP/w87u/9nl7//k6+7/6+3u/+7p6//w6uv/6Ojo/+jo
+ 6P/n5+f/5eXl/+Pj4//i4uL/4ODg/93d3f/g4OD/4ODg/9fX1/+zs7OzAAAAEgAAAAUAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/PyD////////
+ /////////////////////////7mn//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//5V7////
+ ///////////////////////////////////6+vr/q6ur/6Ghof+mpqb/qamp/8DAwP/g4OD//Pz8////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////7Kysv+5ubn/1dXV/+/v7//7+/v//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/9/f3/+/v7//z8/P/9/f3/+fn5//X19f/z8/P/8fHx/+Lo
+ 7//ByNf/Ixvy/2Bl9v9uZ/j/SUbw/0A/+f9mWf//SkD+/1la2v+1sb3/u7zG/7nDtv/Oy8P/w8PD/8O+
+ u/+9vav/tLC1/6enrf+QmqT/VVDT/ywb/v89OPn/TkH//zw8+v89O+v/aGzz/3x59P9HOPT/a2f//8/T
+ 7//b3u3/7+vw/+3q8//s6PT/6uf2/+no+P/o6Pj/5+r4/+fq+P/f6PL/3+f0/+Hn9P/e5PH/3OLv/+Dl
+ 7v/k6u//6O/y/+ns6v/u8e//8fLw/+7v7f/q6Oj/7+rs//Hq7f/y6/D/6enp/+np6f/n5+f/5eXl/+Pj
+ 4//h4eH/39/f/9zc3P/g4OD/39/f/9fX1/+zs7OzAAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/Pxr////////////////////////
+ /////////8y///8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zUD///Sx///////////////
+ ////////////////////////5+fn/6urq//R0dH/9fX1////////////////////////////////////
+ /////////////////////////////////////////////////////Pv//8Kz//+Zf///r5v///z7////
+ /////////////////////////////8vLy/+/v7//3d3d//Pz8//7+/v//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz/+/v7//39/f/9/f3/+/v7//n5+f/4+Pj/9vb2/+jt6//b1+P/dXvk/zU1
+ /f97dPP/VFXt/0E9+v9YS///XVv1/ysi+/+ambv/p6zB/7q4uP+1sbb/uq/D/7m2sf+qqa3/rKun/5iY
+ qv9SS9T/IyT2/z5A+f9UQ/7/PjH5/0RF+f91df//c2z3/zMw9/91f/H/4uLo/+nn7f/69f7/8fb0//H2
+ 9f/x9fb/8PT1//L09f/y9PT/8vXz//L28f/y8/f/8vT0//L28P/x9+z/8ffs//Hy8P/w7vT/7+v2//Py
+ 7v/w7u7/7+vw/+7s8v/v7vL/7O7u/+rt6//p7ej/6enp/+np6f/o6Oj/5eXl/+Pj4//h4eH/39/f/9zc
+ 3P/g4OD/39/f/9bW1v+zs7OzAAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD8/Pxi/////////////////////////////////9nP//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//9SJ///+ff/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////+Xf//+Ve///SRv//zMA//8zAP//MwD//8W3////////////////////
+ /////////////9vb2//IyMj/5+fn//f39//8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/7+/v//Pz8//39/f/8/Pz/+/v7//v7+//6+vr/9fX1/+vq7P/i3uP/w87c/ygg9/9mae//Zl/2/0ZC
+ 7/9HPv//YmD5/zc2/P9iZsz/oaul/6+xq/+oqqT/qaqm/6emov+gpKX/lZyl/1FIzv8yJP7/Q0P//zxA
+ 9/8+Ov3/YFL4/3Z9/P9lau//LyX7/5KU8//g6Oj/4u7o//P06v/39O///Prw//v48P/79/L/+vXy//j0
+ 8//48/T/9vT0//b09P/28vj/9PD2//Lu9P/y7vP/8/Dy//bx8v/28vH/9fHw/+7t9//s7fH/7PDr/+vx
+ 7P/q7+7/5+vs/+fr7P/p7u3/6enp/+np6f/n5+f/5eXl/+Pj4//h4eH/39/f/93d3f/g4OD/39/f/9bW
+ 1v+3t7e/AAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD7+/tG/////////////////////////////////+Xf//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//j3P/////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////n3//+5
+ p///bEf//zMA//8zAP//MwD//zMA//8zAP//Pw///+zn/////////////////////////////////9LS
+ 0v/R0dH/8PDw//r6+v/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//39
+ /f/7+/v/+vr6//v7+//5+fn/8/Pz//Tz9//x8eX/1Nfc/25q6P87OP//eHD5/1NS7v9GPvf/VUz//1RR
+ +/8iHer/kZGj/5icp/+oo6L/nKKh/5+jqP+HlKL/T0XO/zss//9COv//Qzr//0A/+f9TWPD/fHv//2NY
+ +v8qGvT/pqnt/+zr9f/y8fX/+fX7//P4+//w8/j/8vX5//H0+P/z9Pj/8vP3//Py9v/18fb/9fH2//fx
+ 9v/x9fD/8fTy//Dy8//w8fX/8PH1/+/x8f/u8u3/7vPq/+3w7v/t7/D/7e7y/+zr7//u7e//7e3t/+/r
+ 8P/s5/D/6enp/+jo6P/n5+f/5eXl/+Pj4//i4uL/39/f/93d3f/g4OD/39/f/9bW1v+2trbAAAAAEwAA
+ AAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8///////////////////////////////////z7//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//NQP//9LH////////////////////////////////////////////////////
+ ///////////////////////////////////////////////c0///j3P//0IT//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//81A///z8P//////////////////////////////////////9DQ0P/c3Nz/9fX1//v7
+ +//8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//39/f/9/f3//f39//7+
+ /v/+/v7/+/v7//Hx8f/39vL/4drn/7i93P8uIvb/XmXy/2Jl8P9HPOz/SD///2Nc//8yKvP/bW25/46R
+ oP+ckZn/kZWa/4KNqP9LR9b/MSby/0Q6//9KRfr/PDj1/19f8/97fPb/WVr4/1pX6f/R0e//4+L2/+zt
+ 9//58vX//Prv//Lv+P/v9/b/9PT6//T0+v/09fn/8fX2//H29f/x9vX/8Pb1//D29f/z8vb/8/L0//Ly
+ 8v/x8u7/8fLu//Dy7P/x8+3/8fPt//Hv7//y8e3/9PXs/+7v5v/v8Of/7u7o//Dv6//t7Oj/6enp/+np
+ 6f/n5+f/5eXl/+Pj4//i4uL/39/f/93d3f/g4OD/39/f/9bW1v+2trbAAAAAEwAAAAUAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn58Bn5+fAZ+fnwH19fUj////////
+ //////////////////////////////81A///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//1In///59///////////////////////////////////////////////////////////////
+ ///////////////18///r5v//183//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zUD//+8
+ q////////////////////////////////////////f39/9PT0//o6Oj/+Pj4//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz/+/v7//z8/P/9/f3//Pz8//v7+//8/Pz//Pz8//f2
+ +P/n5+3/7Ojn/9TZ4v9kXuv/O0j+/3F07v9WR/b/RTv//1pM//9bS/f/NTfR/42Njf+RjIv/jo6O/1NK
+ wv8sI///REL5/0Q//v8+Nvn/ZWD3/3Jv//9VUPP/Wlby/9fb4P/a4fL/9PT6//v39v/6+fX/9fL0//v6
+ 8P/9+Pf/+fj0//n58//7+PP/+vfy//r38v/79vP/+vXy//r19P/08vH/9PLx//Ty8f/08vL/9PHz//Tw
+ 9f/x7/X/8O70//Tz7//x7vD/8O70/+3q8//v7fP/6evs/+rs7P/p6+v/6enp/+np6f/n5+f/5eXl/+Pj
+ 4//h4eH/39/f/9zc3P/g4OD/39/f/9bW1v+2trbAAAAAEwAAAAUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAn5+fAp+fnwefn58Mn5+fEp+fnxfPz882////////////////////////
+ //////////////9MH///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//+P
+ c///////////////////////////////////////////////////////////////////0sf//4Vn//88
+ C///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//6yX////////////////////
+ ////////////////////////5OTk/+Tk5P/09PT/+/v7//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7/+r2+P/78u//7unm/+fp
+ 6f+vruD/LCb7/29u8/9bXPL/STbx/01I9/9TXPr/KCXs/2Z3nv+Dh5r/QEHP/ycf//9GQv//RkP3/z02
+ /f9XXun/eX30/1dG//9iYeb/6eLl/+vr6//z8/P/+Pj4//b29v/09PT/9vb2//j4+P/39/f/9vb2//b2
+ 9v/29vb/9vb2//X19f/19fX/9fX1//X19f/09PT/9PT0//T09P/z8/P/8/Pz//Ly8v/x8fH/8fHx//Dw
+ 8P/w8PD/7+/v/+/v7//u7u7/7e3t/+zs7P/r6+v/6enp/+jo6P/n5+f/5eXl/+Pj4//g4OD/3t7e/9zc
+ 3P/f39//3t7e/9XV1f+3t7fAAAAAEwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwKfn58Gn5+fB5+f
+ nwufn58Rn5+fHZ+fny2fn58/n5+fUZ+fn2Kfn590//////////////////////////////////////9Z
+ L///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//81A///z8P/////////
+ ////////////////////////////////////7+v//6WP//9VK///MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//oov/////////////////////////////////////////
+ ///6+vr/39/f//Ly8v/6+vr//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//X6+//9+vX/7ubx/93h3P/T0e7/UE7j/09Q
+ /v9paPT/TUXw/0pB//9WU///PDL//0dLwf9NT7X/MR34/zs8+P9FO///Pjf+/1ZQ9f9ydf//WVP//1hW
+ 7//g2e7/4+v4//Hx8f/29vb/+Pj4//f39//29vb/+Pj4//j4+P/39/f/9vb2//b29v/29vb/9vb2//X1
+ 9f/19fX/9fX1//X19f/09PT/9PT0//Pz8//z8/P/8/Pz//Ly8v/x8fH/8fHx//Dw8P/w8PD/7+/v/+/v
+ 7//u7u7/7e3t/+zs7P/r6+v/6enp/+jo6P/n5+f/5eXl/+Pj4//g4OD/3t7e/9zc3P/f39//3t7e/9XV
+ 1f+3t7fAAAAAEwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAACfn58Bn5+fA5+fnwefn58Mn5+fFJ+fnx6fn58qn5+fNJ+fnz+fn59Ln5+fXZ+f
+ n3Kfn5+Hn5+fnZ+fn7Ofn5/H+/v7/f////////////////////////////////9lP///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//TB////Xz////////////////////
+ /////////8m7//95V///OQf//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//+Mb/////////////////////////////////////////////39/f/k5OT/8fHx//r6
+ +v/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8///9/f/y8/f/9PLy/+fq4f/h3u3/l57X/yYm//9wbvb/VlP8/z84
+ 9f9PR///VVL1/yUV9v8aEvP/Ni35/0M///8/M///TUb1/3B0+P9gV/v/IhXz/8XK4//q79r/6PD9//b2
+ 9v/39/f/+Pj4//j4+P/4+Pj/+fn5//j4+P/29vb/9vb2//b29v/29vb/9vb2//X19f/19fX/9fX1//X1
+ 9f/09PT/9PT0//Pz8//z8/P/8vLy//Ly8v/x8fH/8fHx//Dw8P/w8PD/7+/v/+/v7//u7u7/7Ozs/+zs
+ 7P/r6+v/6enp/+np6f/n5+f/5eXl/+Pj4//h4eH/3t7e/9zc3P/f39//3t7e/9XV1f+3t7fAAAAAEwAA
+ AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn58Cn5+fCZ+f
+ nw+fn58Un5+fG5+fnyWfn580n5+fR5+fn12fn592n5+fjp+fn6Wfn5+4n5+fxp+fn9Gfn5/Yn5+f4aen
+ p+u+vr71+Pj4/v////////////////////////////////95V///MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//4lr/////////////+nj//+cg///TB///zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//3xb////
+ /////////////////////////////////////////v7+/+fn5//v7+//+fn5//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//32+f/19///9v3u/+zt4//f3uj/z9Hb/ycj5v9WVfn/ZWjz/0M97v9IQP//ZFr//ygf
+ //8QFf7/RD7//z0z//9JP/D/bG/v/21x9f8kE/7/sbTr/+Ha5//p8PP/9/j0//b29v/29vb/9vb2//j4
+ +P/5+fn/+Pj4//f39//39/f/9vb2//b29v/29vb/9fX1//X19f/19fX/9fX1//X19f/09PT/8/Pz//Pz
+ 8//z8/P/8vLy//Ly8v/x8fH/8fHx//Dw8P/v7+//7+/v/+7u7v/t7e3/7Ozs/+vr6//r6+v/6urq/+np
+ 6f/n5+f/5eXl/+Pj4//h4eH/3t7e/9zc3P/f39//3t7e/9XV1f+3t7fAAAAAEwAAAAYAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn5+fA5+fnw2fn58dn5+fNJ+fn0qfn59en5+fcJ+f
+ n4Gfn5+Sn5+foJ+fn7Cfn5/Cn5+f0p+fn+Gjo6Ptt7e398vLy/zg4OD99fX1////////////////////
+ //////////////////////////////+CY///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//+ii///b0v//zUD//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//dVP///z7////////////////////
+ ////////////////////////5+fn/+3t7f/4+Pj//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//39
+ /f/9/f3//f39//39/f/9/f3//f39//39/f/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//75
+ +v/2+ff/+f34//n27v/e5ej/4tzn/4F+5f80Lv//bG/p/1RO+/9BOvX/XU7//0RK+/8ZHvz/PjH//z08
+ 6v9xZvj/cHnh/zEp//+Aiuj/6d/r/+3t7f/x8Pr/9/j0//X19f/29vb/9/f3//n5+f/5+fn/9/f3//f3
+ 9//39/f/9vb2//b29v/29vb/9fX1//X19f/19fX/9fX1//T09P/09PT/8/Pz//Pz8//y8vL/8vLy//Hx
+ 8f/x8fH/8fHx//Dw8P/v7+//7+/v/+7u7v/t7e3/7Ozs/+vr6//r6+v/6enp/+jo6P/n5+f/5eXl/+Pj
+ 4//h4eH/3t7e/9zc3P/f39//3t7e/9XV1f+4uLjFAAAAEwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwGfn58Hn5+fGZ+fnzSfn59Wn5+feJ+fn5Wfn5+vn5+fxZ+fn9efn5/joKCg6bKy
+ svHHx8f42tra/e3t7f//////////////////////////////////////////////////////////////
+ //////////////+Zf///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//9iO///9fP/////////////////////////////////////////
+ ///o6Oj/7e3t//j4+P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//39/f/9/f3//f39//39
+ /f/9/f3//f39//39/f/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//r99P//////9ff4//bu
+ 9f/m7u7/4t/h/7m31f8qI/D/ZGHz/11Y+f9COe3/UUb6/1JV/v8pHP//OC/x/1Vb8P+HfPr/Pzz2/1xp
+ 6//W0uX/4ebl//n19P/49fH/9vr1//f39//4+Pj/+vr6//r6+v/5+fn/9/f3//f39//4+Pj/9vb2//b2
+ 9v/19fX/9fX1//X19f/19fX/9PT0//T09P/09PT/8/Pz//Pz8//y8vL/8vLy//Hx8f/x8fH/8fHx/+/v
+ 7//v7+//7+/v/+7u7v/t7e3/7Ozs/+vr6//r6+v/6enp/+jo6P/n5+f/5eXl/+Pj4//g4OD/3t7e/9zc
+ 3P/f39//3t7e/9XV1f+7u7vMAAAAEwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAn5+fAp+f
+ nwufn58hn5+fTp+fn4Gfn5+yn5+fzp+fn96tra3rv7+/9tbW1vvp6en+/Pz8////////////////////
+ //////////////////////////////////////////////////////////////////////////////+l
+ j///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//1Ur///18////////////////////////////////////////////+zs7P/r6+v/+Pj4//v7
+ +//8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39
+ /f/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//3/+f/5+f//+Pn1//fz/v/q6e3/5+nj/9HP
+ 2/9XWd3/SUT9/2Jj8/9RRfH/SD3//1FR//8+OPX/Myf7/29z//9eXu7/KR3z/8TH3P/b4dz/6+3u//L0
+ 9f/79fb/+fzz//f39//5+fn/+vr6//n5+f/4+Pj/9/f3//f39//39/f/9vb2//b29v/19fX/9fX1//X1
+ 9f/19fX/9PT0//T09P/09PT/8/Pz//Pz8//y8vL/8fHx//Hx8f/x8fH/8fHx/+/v7//v7+//7+/v/+7u
+ 7v/t7e3/7Ozs/+vr6//q6ur/6enp/+jo6P/m5ub/5eXl/+Li4v/g4OD/3d3d/9zc3P/f39//3t7e/9XV
+ 1f+7u7vMAAAAEwAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn58Dn5+fEZ+fnzOfn59ln5+fmbq6
+ utLR0dHy4+Pj/Pj4+P//////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////+yn///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//Uif//+zn////
+ ////////////////////////////////////////7e3t/+rq6v/39/f//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//33///4//n/+Pn3/+vw8f/y6ez/4eLm/8zP3f+OmdP/Ih/+/2dv
+ 8v9hVPD/Ozvz/09N//9OTPn/HhH5/25z9P8YHf//mpnZ/87J3v/f4eL/6uzs//H17//39f//+/T3//b2
+ 9v/4+Pj/+Pj4//f39//39/f/9/f3//f39//39/f/9vb2//X19f/19fX/9fX1//X19f/19fX/9PT0//T0
+ 9P/09PT/8/Pz//Pz8//y8vL/8fHx//Hx8f/x8fH/8fHx/+/v7//v7+//7+/v/+7u7v/t7e3/7Ozs/+vr
+ 6//q6ur/6Ojo/+jo6P/m5ub/5OTk/+Li4v/g4OD/3d3d/9vb2//f39//3t7e/9XV1f+6urrNAAAAEwAA
+ AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn58Kn5+fLKKiomjJycnJ7+/v+P//////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////Ft///MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//9FF///4tv/////////////////////////
+ ///////////////////w8PD/6Ojo//b29v/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z9+//8/Pz/+fn5//T09P/x8fH/5ubm/9fX1//CwcP/HxT3/1td8f9YXfX/PDnz/1JE
+ /v9gWv//Jx3//zE9+/9rWdz/vsLD/+Db2v/d4eL/5vHn//f17f/89fj/9vr1//j4+P/4+Pj/+Pj4//j4
+ +P/4+Pj/9/f3//f39//39/f/9vb2//b29v/29vb/9vb2//X19f/09PT/9PT0//Pz8//z8/P/8/Pz//Ly
+ 8v/x8fH/8fHx//Hx8f/w8PD/8PDw/+/v7//v7+//7u7u/+3t7f/t7e3/7Ozs/+vr6//q6ur/5+fn/+fn
+ 5//m5ub/5OTk/+Hh4f/f39//3d3d/93d3f/e3t7/3d3d/9bW1v+6urrNAAAAFAAAAAYAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwKfn58Uo6OjUOrq6tz/////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////n3///Pw///pY///3VT//9JG///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zwL///f1/////////////////////////////////////////////Pz
+ 8//n5+f/9fX1//v7+//8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z9
+ +//7+/v/+fn5//X19f/y8vL/5ubm/9jY2P/FxMb/XGTf/0M5/f9hZfP/Uk3u/0U7//9YUv//Qjj//xYY
+ +f+dmdv/xcrT/9XZ1P/f3+X/7e7s//z3+f/9+Pn/8vf1//j4+P/4+Pj/+Pj4//j4+P/4+Pj/9/f3//f3
+ 9//39/f/9vb2//b29v/29vb/9vb2//X19f/09PT/9PT0//Pz8//z8/P/8vLy//Ly8v/x8fH/8fHx//Hx
+ 8f/w8PD/8PDw/+/v7//u7u7/7u7u/+3t7f/t7e3/7Ozs/+rq6v/q6ur/5+fn/+fn5//m5ub/5OTk/+Hh
+ 4f/f39//3d3d/9zc3P/e3t7/3d3d/9bW1v+6urrNAAAAFAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+f
+ nwSfn58c6enpv///////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////4tv//7Wj//+Ja///XDP//zUD//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//PAv//8/D////////////////////////////////////////////8/Pz/+fn5//09PT/+/v7//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z9+//6+vr/+Pj4//T0
+ 9P/x8fH/5OTk/9nZ2f/Ix8n/jprE/y4e+P9iZfD/ZFrt/zs1+P9NSvr/X1j9/xYT+f+mrcD/vsfU/9Pe
+ 1P/t6PH/8+nv//vx/f/4+ff/9vv6//j4+P/4+Pj/+Pj4//j4+P/4+Pj/9/f3//f39//29vb/9vb2//b2
+ 9v/29vb/9vb2//X19f/09PT/9PT0//Pz8//z8/P/8vLy//Ly8v/x8fH/8fHx//Hx8f/w8PD/8PDw/+/v
+ 7//u7u7/7u7u/+3t7f/s7Oz/6+vr/+rq6v/p6en/5+fn/+fn5//l5eX/5OTk/+Hh4f/f39//3d3d/9zc
+ 3P/e3t7/3d3d/9bW1v+6urrNAAAAFAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwXw8PB/////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////Lv///Ft///nIP//29L//8/D///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//81A///wrP/////////
+ ///////////////////////////////////39/f/5ubm//T09P/7+/v//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//3+/P/6+vr/9/f3//Pz8//u7u7/4ODg/9bW
+ 1v/JyMr/qKu6/zgy4/9XVvL/aF7x/z868/9JRfz/Ylj+/yso+f+Kj8b/vMfP/9Pay//o4uf/7ebt//nx
+ /P/29vb/9Pn4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/9/f3//f39//29vb/9vb2//b29v/29vb/9fX1//X1
+ 9f/09PT/9PT0//Pz8//y8vL/8vLy//Ly8v/x8fH/8fHx//Dw8P/w8PD/7+/v/+/v7//u7u7/7e3t/+3t
+ 7f/s7Oz/6+vr/+rq6v/p6en/6Ojo/+fn5//l5eX/4+Pj/+Hh4f/f39//3d3d/9zc3P/e3t7/3d3d/9bW
+ 1v+6urrNAAAAFAAAAAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwb9/f3k////////////////////////
+ ///////////////////////////////////////////////8+///2c///6mT//9/X///Uif//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//+5p///////////////////////////////
+ //////////////n5+f/h4eH/8vLy//n5+f/7+/v/+/v7//v7+//7+/v/+/v7//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//3+/P/6+vr/+Pj4//T09P/t7e3/3t7e/9PT0//FxMb/sLO3/0hN
+ 0v88Nfr/aWbx/09G9P9JQf//Ukn//0g///9XT+L/usPM/9zZy//f3d3/5urr//X19f/39Pb/9Pf1//j4
+ +P/4+Pj/+Pj4//j4+P/39/f/9/f3//b29v/29vb/9vb2//b29v/29vb/9fX1//X19f/09PT/8/Pz//Pz
+ 8//y8vL/8vLy//Hx8f/x8fH/8PDw//Dw8P/v7+//7+/v/+7u7v/u7u7/7e3t/+zs7P/s7Oz/6+vr/+rq
+ 6v/p6en/6Ojo/+bm5v/l5eX/4+Pj/+Hh4f/f39//3d3d/9zc3P/e3t7/3d3d/9bW1v+6urrNAAAAFAAA
+ AAYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPn5+VD/////////////////////////////////////////////
+ /////////+nj//+/r///j3P//2I7//88C///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//6WP////////////////////////////////////////////+Pj4/9XV
+ 1f/n5+f/+Pj4//v7+//7+/v/+/v7//v7+//7+/v/+/v7//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z9+//6+vr/+fn5//b29v/v7+//3t7e/9DQ0P/Av8H/qa2y/zo53f8cEv//Zmvv/1tR
+ 8f9EPvv/SEj//15S//8qG/P/pq7M/+HY1P/h39//5Ozr/+/z7f/48/X/9/f3//f39//4+Pj/+Pj4//j4
+ +P/39/f/9/f3//b29v/29vb/9vb2//b29v/19fX/9fX1//X19f/09PT/8/Pz//Pz8//y8vL/8vLy//Hx
+ 8f/x8fH/8PDw/+/v7//v7+//7+/v/+7u7v/t7e3/7e3t/+zs7P/s7Oz/6+vr/+np6f/p6en/6Ojo/+bm
+ 5v/k5OT/4+Pj/+Hh4f/f39//3d3d/9vb2//e3t7/3d3d/9bW1v+9vb3ZAAAAFAAAAAYAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP39/Z7//////////////////////////////////////7mn//91U///SRv//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//j3P////////////////////////////////////////////7+/v/wMDA/8rKyv/j4+P/9PT0//r6
+ +v/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//r7
+ +f/5+fn/+Pj4//Pz8//s7Oz/3Nzc/87Ozv+9vL7/mJu3/yEW9v8KBv//WVj0/2Na8P89Puz/Q0f5/2JY
+ //8yJP7/h4vS/8vK0//d2d7/5Ono/+zw6//z9PL/9fT2//f39//39/f/9/f3//f39//39/f/9/f3//b2
+ 9v/29vb/9vb2//X19f/19fX/9fX1//X19f/09PT/8/Pz//Pz8//x8fH/8fHx//Hx8f/x8fH/8PDw/+/v
+ 7//v7+//7+/v/+7u7v/t7e3/7e3t/+zs7P/r6+v/6+vr/+np6f/o6Oj/6Ojo/+bm5v/k5OT/4+Pj/+Hh
+ 4f/f39//3d3d/9vb2//e3t7/3d3d/9bW1v+9vb3ZAAAAFAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+
+ /qH/////////////////////////////////r5v//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//98W///////////////
+ //////////////////////////////z8/P+1tbX/p6en/7a2tv/Q0ND/5+fn//X19f/7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//r7+f/4+Pj/9PT0/+7u
+ 7v/o6Oj/2tra/83Nzf+8u73/jY66/xEL/v8DDfX/STv3/25n+P8/RO3/REH//1xT/f9DPvj/a27W/7jA
+ 0f/d1+L/6Obm/+rs7P/z+O//9vT6//f39//39/f/9/f3//f39//39/f/9/f3//b29v/29vb/9fX1//X1
+ 9f/19fX/9fX1//T09P/09PT/8/Pz//Pz8//x8fH/8fHx//Hx8f/x8fH/8PDw/+/v7//v7+//7+/v/+7u
+ 7v/t7e3/7Ozs/+zs7P/r6+v/6urq/+np6f/o6Oj/6Ojo/+bm5v/k5OT/4+Pj/+Hh4f/f39//3d3d/9vb
+ 2//e3t7/3d3d/9bW1v+9vb3ZAAAAFAAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP7+/oX/////////////
+ ////////////////////zL///zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//9iO////Pv/////////////////////////
+ ///////////////////Gxsb/oaGh/6ioqP+6urr/0dHR/+fn5//09PT/+vr6//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//X6/f/69vX/9PDv/+nr6//a4dr/29fd/9TK
+ 2/+3uLT/aXPR/yAZ9v8UEv7/IR79/3Fo9P9LUvX/NTXz/1ZN//9WT/j/JBL//7a71P/U29T/5uHe/+rp
+ 6//z8fD/8/L2//n5+f/4+Pj/9/f3//b29v/39/f/9/f3//f39//29vb/9fX1//T09P/09PT/8/Pz//T0
+ 9P/z8/P/8/Pz//Pz8//y8vL/8vLy//Hx8f/w8PD/8PDw/+/v7//v7+//7u7u/+7u7v/t7e3/7e3t/+zs
+ 7P/r6+v/6urq/+rq6v/p6en/5+fn/+bm5v/l5eX/4+Pj/+Hh4f/f39//3Nzc/9vb2//e3t7/3t7e/9TU
+ 1P++vr7aAAAAFQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///4D/////////////////////////////
+ /////////9zT//+Ve///aUP//zwL//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//dVP///z7////////////////////////////////////
+ ///9/f3/vr6+/6Ghof+oqKj/ubm5/9TU1P/p6en/9fX1//r6+v/7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//X5+v/9+fj/9vHy/+jq6v/a4dr/19TW/8vE0f+wtbT/SUnd/ykk
+ +/8hIf3/HBP9/2Zb8f9TVvj/OTnx/05H/P9aVvz/Jxb//6Wq0f/P1tP/5eLe/+np6f/w7/H/9fX1//f3
+ 9//29vb/9vb2//b29v/39/f/9/f3//b29v/29vb/9PT0//T09P/z8/P/8/Pz//Pz8//z8/P/8/Pz//Ly
+ 8v/y8vL/8fHx//Hx8f/w8PD/8PDw/+/v7//u7u7/7u7u/+3t7f/t7e3/7e3t/+zs7P/r6+v/6urq/+rq
+ 6v/p6en/5+fn/+bm5v/k5OT/4uLi/+Dg4P/e3t7/3Nzc/9ra2v/e3t7/3t7e/9TU1P++vr7aAAAAFQAA
+ AAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///y//////////////////////////////////////////////
+ ///////////////Zz///r5v//4Jj//9VK///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//4Jj/////////////////////////////////////////////f39/7W1
+ tf+hoaH/qqqq/7u7u//U1NT/6urq//b29v/6+vr/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//H29f/6+Pf/9/L0/+jq6v/f497/2dfW/8jHy/+usr3/Ihns/zUx//8zM/v/IBX//1dN
+ 9P9eXvj/QT3w/0VB+P9bV/3/NCT//4qL1f/Fz8//4d7a/+fo5v/v7fP/9/nz//X19f/19fX/9vb2//b2
+ 9v/29vb/9vb2//b29v/19fX/9PT0//T09P/z8/P/8/Pz//Pz8//z8/P/8/Pz//Ly8v/x8fH/8fHx//Hx
+ 8f/w8PD/7+/v/+/v7//u7u7/7u7u/+3t7f/t7e3/7Ozs/+zs7P/r6+v/6urq/+np6f/p6en/5ubm/+Xl
+ 5f/k5OT/4uLi/+Dg4P/e3t7/3Nzc/9ra2v/d3d3/3t7e/9TU1P++vr7aAAAAFQAAAAcAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///+v////////////////////////////////////////////////////////
+ ////////////////////9fP//8m7//+cg///b0v//0IT//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//+Mb/////////////////////////////////////////////r6+v+ysrL/oqKi/6qq
+ qv++vr7/1dXV/+vr6//29vb/+vr6//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//7+/v/+/v7//v7+//6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//T5
+ +P/6+Pf/9fL0/+Xn5//a3dv/09PN/7vAv/+Ynb7/Ewr7/zw5//89OPf/Myz//0Q6+P9mZvb/S0Xy/0I9
+ /P9UUP3/Rjv//2li4f++y83/2dfX/+bn5f/v7PX/9fjv//X19f/19fX/9fX1//b29v/29vb/9vb2//X1
+ 9f/19fX/9PT0//Pz8//z8/P/8/Pz//Pz8//z8/P/8vLy//Ly8v/x8fH/8fHx//Dw8P/w8PD/7+/v/+7u
+ 7v/u7u7/7e3t/+3t7f/s7Oz/7Ozs/+vr6//q6ur/6urq/+np6f/p6en/5ubm/+Xl5f/k5OT/4uLi/+Dg
+ 4P/e3t7/3Nzc/9vb2//d3d3/3d3d/9TU1P++vr7aAAAAFQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8v////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////i2///taP//4xv//9cM///NQP//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//pY/////////////////////////////////////////////29vb/rq6u/6Ghof+rq6v/vr6+/9ra
+ 2v/s7Oz/9/f3//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+/v7//v7
+ +//7+/v/+/v7//v7+//6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//T29v/z8fD/8Ozx/+Ll
+ 4//a2tr/09TL/7vDw/+IiMj/GBj//0E9//89NfT/SUj2/ywj9f9laPP/VE30/0M7/v9NSv7/U079/0c4
+ 7f+2xs3/09PZ/+Xm5P/p6u7/9PTu//b29v/29vb/9vb2//b29v/19fX/9fX1//X19f/09PT/8/Pz//Pz
+ 8//y8vL/8vLy//Ly8v/y8vL/8vLy//Hx8f/x8fH/8PDw//Dw8P/v7+//7u7u/+7u7v/t7e3/7e3t/+zs
+ 7P/s7Oz/6+vr/+vr6//q6ur/6enp/+np6f/o6Oj/5+fn/+Xl5f/k5OT/4uLi/+Dg4P/e3t7/3Nzc/9vb
+ 2//c3Nz/3d3d/9TU1P++vr7aAAAAFQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////r///
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////+ff//8/D//+lj///dVP//0kb//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//6+b////
+ ////////////////////////////////////////9PT0/6ioqP+jo6P/ra2t/8DAwP/Z2dn/7u7u//j4
+ +P/7+/v/+/v7//v7+//7+/v/+/v7//v7+//7+/v/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6
+ +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//f5+f/08vH/7ezw/+Pn4v/c2dv/1dLN/7nB
+ yP9xbdL/Iif4/z87//8/NPT/V1vw/xoV9P9cYPX/WlX4/z429f9JRf//WFX4/y8f9v+os9P/1Nbe/+Tl
+ 4//m6Oj/8/Hx//X19f/29vb/9vb2//X19f/19fX/9PT0//T09P/09PT/8/Pz//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8fHx//Hx8f/w8PD/8PDw/+/v7//v7+//7u7u/+3t7f/t7e3/7e3t/+zs7P/s7Oz/6+vr/+rq
+ 6v/p6en/6enp/+jo6P/o6Oj/5+fn/+Xl5f/j4+P/4eHh/+Dg4P/e3t7/3d3d/9zc3P/c3Nz/3Nzc/9PT
+ 0//AwMDhAAAAFQAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////D////3/////v////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////s5///v6///49z//9cM///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zUD//+8q///////////////
+ //////////////////////////////Dw8P+mpqb/o6Oj/66urv/Dw8P/2tra/+7u7v/4+Pj/+vr6//r6
+ +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5+fn/+fn5//n5
+ +f/5+fn/+fn5//n5+f/5+fn/+fn5//b4+f/z9PL/6+rs/+Lm4P/c2N3/0c7K/7C4yf9cUdf/LC/2/0A5
+ //9FPPf/Xl7y/xIQ9v9NUPn/XFv3/0Q47v9FQ///WVL5/ywi/v+Sldn/1NjZ/+Ti4f/k6ej/9PD1//T0
+ 9P/09PT/9fX1//X19f/09PT/9PT0//Pz8//z8/P/8/Pz//Ly8v/y8vL/8vLy//Ly8v/y8vL/8fHx//Hx
+ 8f/w8PD/8PDw/+/v7//u7u7/7u7u/+3t7f/t7e3/7Ozs/+zs7P/r6+v/6+vr/+rq6v/p6en/6Ojo/+jo
+ 6P/o6Oj/5ubm/+Xl5f/j4+P/4eHh/9/f3//e3t7/3Nzc/9vb2//c3Nz/3Nzc/9PT0//AwMDmAAAAFQAA
+ AAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8X////j/////f/////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////Cs///MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//81A///z8P/////////////////////////
+ ///////////////////o6Oj/pKSk/6Ojo/+vr6//w8PD/97e3v/v7+//+Pj4//r6+v/6+vr/+vr6//r6
+ +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5+fn/+fn5//n5+f/5+fn/+fn5//n5
+ +f/5+fn/+fn5//b4+f/4+ff/7ezu/+Pn4f/g2eD/z8rL/62zyv9PQdz/ODf9/0I6//9JQvf/XFf2/w4Q
+ +P89P/v/XWD4/0xD7f9BQPz/W1D//zQv//+AfNv/0NfU/+Lg3//n7Ov/9vL4//Ly8v/z8/P/9PT0//X1
+ 9f/09PT/9PT0//Pz8//z8/P/8vLy//Ly8v/y8vL/8fHx//Ly8v/x8fH/8fHx//Dw8P/w8PD/7+/v/+/v
+ 7//u7u7/7u7u/+3t7f/s7Oz/7Ozs/+zs7P/r6+v/6+vr/+rq6v/p6en/6Ojo/+jo6P/n5+f/5ubm/+Xl
+ 5f/i4uL/4ODg/9/f3//d3d3/3Nzc/9vb2//b29v/3Nzc/9PT0//AwMDmAAAAFQAAAAcAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///w////9H////gP///7T////v////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////+yn///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//PAv//9LH////////////////////////////////////
+ ////////5OTk/6Ghof+kpKT/r6+v/8TExP/c3Nz/7+/v//f39//5+fn/+fn5//n5+f/5+fn/+vr6//r6
+ +v/6+vr/+vr6//r6+v/6+vr/+vr6//r6+v/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//Xz
+ 8//w8vP/8+3y/+Lk5f/T1tT/zM3E/769x/8hJPv/Qzn//zs99v9US/n/TU35/xoW8f8tNvH/YWTv/1BF
+ 9f9BO/7/VUv//0M//P9ZWvL/zc7S/+Lc3f/g5uH/7uvt//Pz8//z8/P/9PT0//T09P/09PT/8/Pz//Pz
+ 8//x8fH/8PDw//Dw8P/u7u7/7e3t/+vr6//s7Oz/7Ozs/+7u7v/v7+//7+/v/+7u7v/u7u7/7e3t/+3t
+ 7f/s7Oz/7Ozs/+rq6v/q6ur/6urq/+np6f/p6en/6Ojo/+fn5//m5ub/5eXl/+Tk5P/i4uL/4eHh/9/f
+ 3//d3d3/29vb/9nZ2f/b29v/29vb/9PT0//BwcHmAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////I////1v///+T////zP//
+ //v/////////////////////////////////////////////////////////////////////////////
+ //////////////+ii///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//0UX///f1////////////////////////////////////////////9/f
+ 3/+goKD/pKSk/7CwsP/Hx8f/39/f//Dw8P/4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5
+ +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n39//w8vL/8Ovt/+Di
+ 4//V2Nb/zs7I/7y6xv8aHPb/Qzv+/zs7+f9XT/b/SEj4/ygm6v8nK/b/Y2Ty/1NL9v8/Ovv/UUn//0M/
+ /P9PUO7/y8vR/+Db3P/i6OP/7+zu//T09P/09PT/9PT0//T09P/z8/P/8fHx/+3t7f/p6en/5ubm/+Tk
+ 5P/h4eH/3t7e/9zc3P/e3t7/4uLi/+np6f/s7Oz/7u7u/+7u7v/t7e3/7e3t/+zs7P/s7Oz/6+vr/+rq
+ 6v/q6ur/6enp/+np6f/o6Oj/5+fn/+bm5v/m5ub/5eXl/+Tk5P/i4uL/4ODg/9/f3//d3d3/2tra/9nZ
+ 2f/b29v/29vb/9PT0//BwcHmAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wf///87////b///
+ /6v////f//////////////////////////////////////////////////////////////////////+Z
+ f///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//9FF///7Of////////////////////////////////////////////V1dX/oKCg/6Sk
+ pP+ysrL/yMjI/+Pj4//y8vL/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5
+ +f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//r49//x8/P/8Ovs/+Di4v/V2Nb/zs3J/7q3
+ x/8UFPT/RD77/zs6//9fVfX/PUH4/zs+3P8aGfj/ZGD1/1dS9f88N/b/Tkb//0VC/P9BQev/zMrQ/9zZ
+ 2//m6uX/7+vw//T09P/09PT/8/Pz//Pz8//w8PD/6urq/9/f3//R0dH/yMjI/8PDw/+/v7//urq6/7m5
+ uf+9vb3/ycnJ/9ra2v/m5ub/6+vr/+3t7f/s7Oz/7Ozs/+vr6//r6+v/6+vr/+rq6v/p6en/6enp/+jo
+ 6P/n5+f/5ubm/+bm5v/m5ub/5OTk/+Pj4//i4uL/4ODg/97e3v/c3Nz/2tra/9nZ2f/b29v/29vb/9PT
+ 0//AwMDmAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////F///
+ /0////+H////vP////P///////////////////////////////////////////9/X///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zUD//+5p///iWv//z8P//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//Uif//+zn////////////////////////////////////////////z8/P/6CgoP+mpqb/tra2/9DQ
+ 0P/m5ub/9vb2//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+Pj4//j4
+ +P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j38//x9PL/8+/u/+Lk5P/V2Nb/zcvK/7m0yf8SEfX/RkH7/zs4
+ //9jWvH/MzX3/05Vyv8UD/T/Xljz/1dW8v88NvP/SUL9/0pI//81Muz/zcrT/9rZ2//n6+b/7enu//Pz
+ 8//z8/P/8/Pz//Hx8f/p6en/2tra/8jIyP+6urr/sbGx/6ysrP+oqKj/paWl/6Wlpf+np6f/s7Oz/8TE
+ xP/V1dX/4uLi/+rq6v/s7Oz/7Ozs/+vr6//r6+v/6urq/+rq6v/p6en/6Ojo/+fn5//m5ub/5ubm/+bm
+ 5v/m5ub/5OTk/+Pj4//h4eH/4ODg/97e3v/c3Nz/2tra/9jY2P/b29v/2tra/9PT0//AwMDmAAAAFgAA
+ AAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8v/v7+6v////////////////////////////////95V///MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//5l///////////////n3//+5p///ZT///zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//183///1
+ 8////////////////////////////////////////////8nJyf+goKD/qamp/729vf/Y2Nj/7+/v//f3
+ 9//4+Pj/+fn5//n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//n5+f/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4
+ +P/4+Pj/+Pj4//f28v/w8/H/9PDv/+Tm5v/W2df/z83N/7u1zP8SD/j/Q0D6/zs4//9kW/H/LSz4/1tk
+ vv8bFOv/WE71/1hZ7/89OPL/R0L8/05J//8nJPD/zcnU/9fa3v/m6uX/6+fs//Ly8v/y8vL/8fHx/+rq
+ 6v/b29v/xMTE/7i4uP/Nzc3/3Nzc/9zc3P/Pz8//ycnJ/6ampv+fn5//pKSk/66urv+/v7//0dHR/+Hh
+ 4f/p6en/6+vr/+vr6//q6ur/6urq/+rq6v/p6en/6Ojo/+fn5//m5ub/5ubm/+bm5v/m5ub/4+Pj/+Li
+ 4v/h4eH/39/f/93d3f/b29v/2dnZ/9jY2P/a2tr/2dnZ/9LS0v/AwMDmAAAAFgAAAAcAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn58E////+P//
+ //////////////////////////////9lP///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//WS////z7/////////////////////////////+Xf//+Sd///SRv//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//9iO////Pv/////////
+ //////////////////////////////39/f+9vb3/o6Oj/6+vr//Ly8v/6Ojo//T09P/4+Pj/+Pj4//j4
+ +P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f1
+ 9P/w8/H/8+/u/+Pl5f/X2tj/0tDQ/7640f8SD/n/Qz79/zw4+/9fWvH/LSb5/2FruP8sKd3/UUX3/1pb
+ 8f8/OvP/RED9/05K//8bFvP/zcnU/9Xc3//m5+P/7Ojt//Hx8f/x8fH/6+vr/93d3f/S0tL/7e3t////
+ //////////////////////////////z8/P/V1dX/ra2t/6Ojo/+srKz/vLy8/8/Pz//h4eH/6enp/+vr
+ 6//q6ur/6urq/+np6f/p6en/6Ojo/+fn5//m5ub/5ubm/+Xl5f/l5eX/4+Pj/+Li4v/g4OD/3t7e/93d
+ 3f/b29v/2NjY/9fX1//Z2dn/2NjY/9HR0f/AwMDmAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACfn58F////////////////////////
+ //////////////9VK///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//81
+ A///2c///////////////////////////////////////////////Pv//8Kz//91U///NQP//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//dVP///z7////////////////////
+ ///////////////////29vb/pKSk/6ioqP+/v7//29vb/+/v7//39/f/9/f3//f39//39/f/9/f3//f3
+ 9//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f19f/v8fH/8u3u/+Pl
+ 5f/Y29n/1NLS/7+50v8SD/n/QDz//z869P9aV/P/MCL8/2Bqt/89Qc//SD34/1pb8f9BPPP/Qz/8/01K
+ /v8XEfr/z8vX/9bf4//l5uL/7urv//Ly8v/w8PD/4+Pj/9bW1v/7+/v/////////////////////////
+ ////////////////////////+fn5/66urv+hoaH/rKys/729vf/V1dX/4+Pj/+np6f/p6en/6enp/+jo
+ 6P/o6Oj/6Ojo/+fn5//m5ub/5eXl/+Xl5f/k5OT/4uLi/+Hh4f/g4OD/3t7e/9zc3P/a2tr/2NjY/9fX
+ 1//Z2dn/19fX/9DQ0P/Dw8PzAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADx8fEk//////////////////////////////////////9M
+ H///MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//+cg///////////////
+ ////////////////////////////////////////////////////7Of//6KL//9SJ///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//4Jj////////////////////////////////////
+ ////////ycnJ/6Wlpf+5ubn/1NTU/+zs7P/39/f/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4
+ +P/39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f09v/w8vP/8+7v/+Pl5f/X2tj/09HQ/7+5
+ 0P8SD/n/Pzz//0E88/9VVfX/MiD9/15otv9JUMP/QTb4/1la8v9BPPH/QD/7/01K/v8WEP//08/b/9rj
+ 5//l5uL/7urv//Ly8v/t7e3/4eHh//n5+f//////////////////////////////////////////////
+ //////////////Dw8P+lpaX/o6Oj/66urv/Gxsb/2dnZ/+Xl5f/p6en/6enp/+jo6P/o6Oj/5+fn/+fn
+ 5//m5ub/5eXl/+Tk5P/j4+P/4uLi/+Hh4f/g4OD/3t7e/9zc3P/a2tr/2NjY/9bW1v/Y2Nj/19fX/9DQ
+ 0P/Dw8PzAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAADv7+8q//////////////////////////////////////81A///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//183///8+///////////////////////////////
+ ////////////////////////////////////////////////////z8P//39f//85B///MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//zMA//+Mb///////////////////////////////////////9vb2/6am
+ pv+4uLj/0tLS/+vr6//29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f3
+ 9//39/f/9/f3//f39//39/f/9/f3//X3+P/0+PP/6fHx/+Xo3//j4Nz/2tDc/7C7yf8TEvH/PkD9/zo+
+ 9P9XSvr/MSb4/15ps/9PU8T/PjL8/1lU8/9APO//Pzn//0lH//8eGfH/yc7X/97g4f/z6PL/7+/v//Dw
+ 8P/t7e3/+fn5////////////////////////////////////////////////////////////////////
+ ///i4uL/oKCg/6ampv+1tbX/y8vL/97e3v/m5ub/6Ojo/+jo6P/n5+f/5ubm/+bm5v/l5eX/5OTk/+Tk
+ 5P/j4+P/4uLi/+Dg4P/e3t7/3Nzc/9vb2//Z2dn/19fX/9bW1v/W1tb/09PT/87Ozv/Dw8PzAAAAFgAA
+ AAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD19fVH//////////////////////////////////z7//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//OQf//9/X////////////////////////////////////////////////////
+ ///////////////////////////////////////////////18///rJf//1wz//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//qZP//////////////////////////////////////8zMzP+6urr/1tbW/+zs
+ 7P/29vb/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f3
+ 9//39/f/9/f3//Tz9f/19vL/6/Dx/+bn4//i39v/2tPa/7bBz/8VE/X/RT7//zk4+f9TT/T/Miz1/19n
+ uv9TV8D/Nizw/1FR8f9BOvX/P0H6/0I8//8sJ/T/zM7g/+Dl5P/y7ez/7/Lw/+7u7v/z8/P/////////
+ ////////////////////////////////////////////////////////////////////////w8PD/6Gh
+ of+pqan/vLy8/9LS0v/h4eH/6Ojo/+fn5//n5+f/5ubm/+Xl5f/l5eX/5OTk/+Tk5P/j4+P/4eHh/+Dg
+ 4P/e3t7/3Nzc/9ra2v/Y2Nj/1tbW/9XV1f/V1dX/0tLS/83Nzf/CwsLzAAAAFgAAAAcAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwH19fVT////////
+ /////////////////////////+Xf//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//oov/////////////////////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////c0///jG///0IT//8zAP//MwD//zMA//8z
+ AP//OQf//+zn/////////////////////////////////9XV1f++vr7/2tra/+7u7v/19fX/9vb2//b2
+ 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//f0
+ 9v/4+PL/7fHy/+jn6f/h397/29nZ/7/H2P8cFPv/ST3//z46/f9LTfH/MSzz/15kw/9ZXcb/Nyvv/01S
+ 9P9AOfb/PED3/z42//88NPP/ztDi/+Dl4//s6+H/6Ovp/+3t7f/39/f/////////////////////////
+ ////////////////////////////////////////////////////////+fn5/6qqqv+jo6P/r6+v/8HB
+ wf/X19f/5OTk/+fn5//m5ub/5eXl/+Xl5f/l5eX/5OTk/+Tk5P/j4+P/4ODg/9/f3//d3d3/3Nzc/9ra
+ 2v/X19f/1dXV/9PT0//U1NT/0dHR/8zMzP/CwsLzAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwH39/do////////////////////////
+ /////////9nP//8zAP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zMA//9fN////Pv/////////
+ //////////////////////////////z8/P//////////////////////////////////////////////
+ //////////////////////////////////////////n3//+5p///bEf//zMA//8zAP//MwD//9/X////
+ /////////////////////////////8fHx//ExMT/4eHh//Dw8P/29vb/9vb2//b29v/29vb/9vb2//b2
+ 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//n2+P/6+PD/7vDx/+zn
+ 8P/i4+H/4eDc/8fO3f8lHPn/QTb+/0I9/P9EQ/H/PDT3/1Nb1P9OUdf/PjH3/01R8P8/PPD/Nzj+/zwx
+ //9USfP/2tvp/+bt6v/s7eT/6uzs/+3t7f/7+/v//////////////////////////////////9f///+D
+ ////5////////////////////////////////////////+Li4v+goKD/pqam/7Kysv/Kysr/29vb/+Tk
+ 5P/l5eX/5eXl/+Tk5P/k5OT/5OTk/+Pj4//j4+P/39/f/9/f3//d3d3/29vb/9nZ2f/X19f/1NTU/9LS
+ 0v/T09P/0NDQ/8vLy//BwcHzAAAAFgAAAAcAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD4+Ph3/////////////////////////////////8y///8z
+ AP//MwD//zMA//8zAP//MwD//zMA//8zAP//MwD//zkH///f1///////////////////////////////
+ ////////6enp/9nZ2f/y8vL//Pz8////////////////////////////////////////////////////
+ /////////////////////////////////////////+Xf//+pk///taP/////////////////////////
+ /////////////8PDw//Pz8//6enp//Pz8//29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2
+ 9v/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//Xy9P/08ez/7Ozs/+rm8f/l6Ob/4+Tg/8zS
+ 3/8zKfH/PTn9/0Y//v9EPvH/T0b6/zk85f80Mur/TUX+/1ZX7f9CQO7/NTb//zMf//97der/4ePt/+nu
+ 7f/r7Oj/6+zw/+3t7f///////////////////////////////////////zP///8A////P/////v/////
+ ///////////////////////////////////Dw8P/oaGh/6ioqP+7u7v/z8/P/97e3v/k5OT/5OTk/+Tk
+ 5P/k5OT/4+Pj/+Pj4//i4uL/39/f/97e3v/d3d3/29vb/9nZ2f/W1tb/09PT/9HR0f/S0tL/z8/P/8rK
+ yv/AwMDzAAAAFwAAAAefn58Cn5+fBZ+fnwifn58On5+fFJ+fnxifn58Sn5+fC5+fnwMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwH5+fmI/////////////////////////////////7mn//8zAP//MwD//zMA//8z
+ AP//MwD//zMA//8zAP//MwD//6KL///////////////////////////////////////5+fn/0NDQ/+bm
+ 5v/x8fH/9PT0//b29v/6+vr//v7+////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////8jI
+ yP/c3Nz/7+/v//T09P/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X1
+ 9f/19fX/9fX1//X19f/19fX/9fX1//X09v/28+//8PHv//Dt9v/s8e//6+no/9fZ4f9NR+z/NTX9/0I2
+ //9APuz/W1X2/yEc9P8jHPP/Wlb1/1xZ6/9EQvD/MjT+/zIg9/+rr9//4uDs/+Pm6v/n6Ob/6unt/+/v
+ 7////////////////////////////////////////wf///8A////AP///4v/////////////////////
+ ///////////////////5+fn/qamp/6Kiov+tra3/wMDA/9bW1v/f39//5OTk/+Pj4//j4+P/4+Pj/+Li
+ 4v/h4eH/39/f/97e3v/c3Nz/2tra/9jY2P/V1dX/0tLS/9DQ0P/R0dH/zs7O/8nJyf/AwMDzIiIiHGxs
+ bBWfn58Zn5+fJJ+fny+fn588n5+fR5+fn02fn59Cn5+fL5+fnxufn58Nn5+fBAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+f
+ nwH6+vqb/////////////////////////////////6+b//8zAP//MwD//zMA//8zAP//MwD//zMA//8z
+ AP//Xzf///z7///////////////////////////////////////Z2dn/3t7e/+7u7v/z8/P/9PT0//T0
+ 9P/09PT/9PT0//f39//8/Pz/////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////9fX1/93d3f/s7Oz/9PT0//X1
+ 9f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/09PT/9PT0//T09P/09PT/9PT0//T0
+ 9P/09PT/9PT0//Hz8//y8O//7vLt/+7t8f/r8O7/6+jq/9/e4P9ubO7/MCv8/0E1//85PvH/W1L8/ygi
+ //9BP/3/Z2by/1tY8f9GQu//KSf9/1pZ7//V3uL/5uLt/+jp7f/q6ur/8O/r/+3t7f//////////////
+ /////////////////////////xP///8A////AP///wf////X////////////////////////////////
+ ////////4uLi/6CgoP+lpaX/s7Oz/8fHx//Z2dn/4uLi/+Pj4//j4+P/4uLi/+Hh4f/h4eH/39/f/97e
+ 3v/b29v/2dnZ/9bW1v/U1NT/0dHR/9DQ0P/Pz8//zc3N/8fHx/++vr76Z2dnOJOTk0Wfn59in5+fgJ+f
+ n5ifn5+kn5+fq5+fn66fn5+in5+fiZ+fn2Gfn585n5+fGJ+fnwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwH7+/un////////
+ /////////////////////////5l///8zAP//MwD//zMA//8zAP//MwD//zMA//85B///39f/////////
+ /////////////////////////////+jo6P/X19f/6urq//Ly8v/09PT/9PT0//T09P/09PT/9PT0//T0
+ 9P/09PT/9fX1//n5+f/9/f3/////////////////////////////////////////////////////////
+ ///////////////////////////////////+/v7/5eXl/+zs7P/z8/P/9fX1//X19f/19fX/9fX1//X1
+ 9f/19fX/9fX1//X19f/19fX/9fX1//X19f/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//D1
+ 9P/z8fH/8PTu/+/u8P/u8/H/7+vw/+3r6v+Njvz/KCD2/z42//8mL/D/QTH0/ykp9/9eaPb/bmrx/1xX
+ +P9JRO3/Ixf//4qg7v/r8ez/6+fs/+7t7//t6uz/8vLm/+7u7v//////////////////////////////
+ /////////x////8A////AP///wD///83////+////////////////////////////////////////8PD
+ w/+hoaH/qamp/7m5uf/Ozs7/3d3d/+Li4v/i4uL/4uLi/+Hh4f/g4OD/39/f/93d3f/b29v/2NjY/9XV
+ 1f/T09P/0dHR/87Ozv/Ly8v/x8fH/7+/v/+2trb/jY2Nd5ubm42fn5+un5+fzJ+fn+Kfn5/qn5+f7Z+f
+ n+2fn5/mn5+f0Z+fn6ufn59+n5+fTJ+fnx2fn58HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwL8/PzB////////////////////////
+ /////////49z//8zAP//MwD//zMA//8zAP//MwD//zMA//+ii///////////////////////////////
+ ////////9/f3/8/Pz//k5OT/8PDw//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Ly8v/y8vL/8/Pz//Pz
+ 8//z8/P/9vb2//r6+v/+/v7/////////////////////////////////////////////////////////
+ ///////////////////v7+//7e3t//Pz8//09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T0
+ 9P/09PT/9PT0//T09P/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//P08v/z9PL/8fHx/+/v
+ 7//v7vD/7+7w/+rp7f/k4+f/GBf2/yAi//8NDfP/Kifz/2dm/P92dPz/ZWL+/05T9f8xJOr/gH/m/9DW
+ 6f/u7u7/7Ovv/+rx6v/w8+r/8uvy/+zs7P/8/Pz//////////////////////////////////zv///8A
+ ////AP///wD///8A////f/////////////////////////////////////////n5+f+rq6v/o6Oj/6ys
+ rP/AwMD/09PT/97e3v/h4eH/4ODg/9/f3//f39//3t7e/93d3f/a2tr/1tbW/9PT0//Q0ND/y8vL/8fH
+ x//Dw8P/u7u7/7Gxsf+qqqr/m5ubzqOjo966urrwx8fH+NXV1f7j4+P+4eHh/7q6uv6fn5/8n5+f9p+f
+ n+mfn5/On5+fmZ+fn0Wfn58Xn5+fAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwL8/PzF/////////////////////////////////39f//8z
+ AP//MwD//zMA//8zAP//MwD//183///8+///////////////////////////////////////1tbW/+Dg
+ 4P/t7e3/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Ly8v/y8vL/8/Pz//Pz8//z8/P/8/Pz//Pz
+ 8//09PT/9/f3//z8/P////////////////////////////////////////////////////////////j4
+ +P/u7u7/8/Pz//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T0
+ 9P/z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Lz8f/x8vD/8PDw/+7u7v/v7vD/8fDy/+/u
+ 8v/r6u7/jJb//y8c9f8kE/7/R0ry/1FW5/9aVvX/RED3/yUc9f+Ghez/0tT//+jq6//o4+T/8e3y/+bs
+ 5//m6uT/8Ozx/+3t7f/7+/v//////////////////////////////////0f///8A////AP///wD///8A
+ ////A////8/////////////////////////////////////////n5+f/oKCg/6SkpP+ysrL/xcXF/9fX
+ 1//f39//4ODg/9/f3//e3t7/3d3d/9zc3P/Y2Nj/09PT/83Nzf/Gxsb/vr6+/7a2tv+xsbH/rKys/6am
+ pv+4uLj/2tra+vv7+//////////////////////////////////t7e3/vr6+/6CgoP2fn5/wn5+fx5+f
+ n3Wfn58zn5+fCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAJ+fnwP+/v7i/////////////////////////////////2xH//8zAP//MwD//zMA//8z
+ AP//PAv//+Xf///////////////////////////////////////n5+f/1tbW/+rq6v/x8fH/8/Pz//Pz
+ 8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Ly8v/y8vL/8/Pz//Pz8//z8/P/8vLy//Ly8v/y8vL/8/Pz//Pz
+ 8//19fX/+fn5//7+/v/////////////////////////////////9/f3/9fX1//Ly8v/z8/P/9PT0//T0
+ 9P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//Pz8//z8/P/8/Pz//Pz8//y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8vLy//P08v/y8/H/8fHx/+/v7//v7vD/8fDy//Dv8f/t7O7/7ufq/7u5
+ 9f9YUPf/KBv//zEo+v9NQPD/hXv3/7fA8v/W3O//6uzt//fx7P/x6er/6ufp/+ft6P/t8ez/8Ozx/+zs
+ 7P/5+fn//////////////////////////////////1////8A////AP///wD///8A////AP///y/////7
+ ////////////////////////////////////////x8fH/6CgoP+np6f/t7e3/8zMzP/Z2dn/39/f/9/f
+ 3//c3Nz/2dnZ/9XV1f/Ozs7/xsbG/8DAwP+4uLj/sLCw/6mpqf+vr6//zc3N//Dw8P//////////////
+ /////////////////////////////////////////////+vr6/+ioqL9n5+f45+fn6Wfn59Wn5+fFp+f
+ nwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+f
+ nwP+/v7q/////////////////////////////////2U///8zAP//MwD//zMA//8zAP//qZP/////////
+ //////////////////////////////f39//T09P/5OTk//Dw8P/z8/P/8/Pz//Pz8//z8/P/8/Pz//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz
+ 8//19fX/+Pj4//r6+v/6+vr/+Pj4//b29v/09PT/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz
+ 8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Lz8f/z8/P/8vLy//Hx8f/w8PD/8O/x/+7t7//s6+3/5e7k/+jx9f/e5/T/2eDv/97g
+ 8v/i5e3/4+zv/+Dq9P/t7e3/6OPk//Lq6//y7ez/6uvp/+rv7f/q7O3/7urw/+vr6//4+Pj/////////
+ /////////////////////////2////8A////AP///wD///8A////AP///wD///9/////////////////
+ ////////////////////////+vr6/6urq/+ioqL/rKys/7y8vP/Q0ND/2tra/9nZ2f/W1tb/z8/P/8fH
+ x/+9vb3/s7Oz/6urq/+pqan/wsLC/+Pj4//+/v7/////////////////////////////////////////
+ ///////////////////////////////////Y2Nj/n5+f8p+fn82fn598n5+fLJ+fnwsAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJ+fnwP/////////////
+ /////////////////////////0wf//8zAP//MwD//zMA//9lP///////////////////////////////
+ /////////////9XV1f/e3t7/7e3t//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8fHx//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8/Pz//Pz
+ 8//z8/P/8/Pz//Ly8v/y8vL/8vLy//Ly8v/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Dw
+ 8P/x8fH/8vLy//Hx8f/x8fH/8PDw/+/v7//t7e3/8/Dy/+fk7f/v8/T/8PXs/+/u6v/27vX/8+rt//bw
+ 6//q6e3/8+/0/+zp6//r7Or/7fDu/+rr7//s6+//7ejp/+rq6v/29vb/////////////////////////
+ /////////3////8A////AP///wD///8A////AP///wD///8D////z///////////////////////////
+ /////////////+fn5/+fn5//pKSk/6+vr//BwcH/ysrK/8nJyf/BwcH/ubm5/7Kysv+srKz/tbW1/9bW
+ 1v/4+Pj/////////////////////////////////////////////////////////////////////////
+ ////////////////////////wMDA+5+fn+Wfn5+fn5+fUJ+fnxmfn58CAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHx8Q3/////////////////////////////
+ /////////0UX//8zAP//MwD//zwL///l3///////////////////////////////////////5ubm/9fX
+ 1//p6en/8fHx//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8fHx//Hx8f/x8fH/8fHx//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Ly8v/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Dw
+ 8P/w8PD/8PDw//Dw8P/v7+//9PLq//Xz8v/u7e//7e3t/+rs7P/q7ev/7/Du/+zs7P/q8er/6O7p/+nv
+ 6v/q7+3/6uvv/+vp7//t6uz/7e3n/+rq6v/09PT//////////////////////////////////5v///8A
+ ////AP///wD///8A////AP///wD///8A////L/////v/////////////////////////////////////
+ ///Hx8f/oaGh/6Wlpf+ysrL/t7e3/7a2tv+vr6//ra2t/8rKyv/s7Oz/////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////8/Pz/5+fn/Cfn5+1n5+faZ+fnyKfn58EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPz8/CD//////////////////////////////////////zMA//8z
+ AP//MwD//6mT///////////////////////////////////////39/f/0NDQ/+Tk5P/v7+//8vLy//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Hx8f/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Ly
+ 8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly8v/x8fH/8fHx//Hx
+ 8f/w8PD/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw//Ly8v/x8fH/8PDw/+/v7//v7+//7u/t/+7v
+ 7f/u7+3/7+3t/+/u6v/x7+7/7u/r/+nx5//o7u3/5uvu/+nw6f/u8ej/5+vl/+zw6//o6uv/7Ovv/+3q
+ 7P/h4uD/6+/q/+np6f/z8/P//////////////////////////////////6f///8A////AP///wD///8A
+ ////AP///wD///8A////AP///3v////////////////////////////////////////6+vr/q6ur/6Gh
+ of+kpKT/pqam/76+vv/f39///Pz8////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////////////////////////66u
+ rvSfn5+4n5+fbJ+fnyOfn58EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP///wv//////////////////////////////////////08j//8zAP//dVP/////////
+ ///////////////////////////////////W1tb/3Nzc/+zs7P/y8vL/8vLy//Ly8v/y8vL/8vLy//Ly
+ 8v/y8vL/8vLy//Hx8f/x8fH/8vLy//Ly8v/y8vL/8vLy//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/8vLy//Ly8v/y8vL/8fHx//Hx8f/x8fH/8fHx//Hx8f/w8PD/8PDw//Dw
+ 8P/w8PD/8PDw//Dw8P/w8PD/8PDw/+/v7//v7+//7u7u/+/v7//v8O7/7u/t/+7v7f/t7uz/7u/z/+7s
+ 6//y7+v/8evw//Dq9f/w7e//7Ovn//Hr8P/v6O//7+vw/+7q7//s6O7/7ejp/+7u6P/q7un/4uXp/+np
+ 6f/w8PD//////////////////////////////////7////8A////AP///wD///8A////AP///wD///8A
+ ////AP///wP////H////////////////////////////////////////5+fn/6urq//R0dH/9fX1////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////+////7P///9/////m/////v//////////////////////////////////8nJyfSfn5+nn5+fVp+f
+ nxqfn58CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAABAAAAAgAA
+ AAL////7/////////////////////////////////9/X//+5p////Pv/////////////////////////
+ /////////////+Pj4//W1tb/6Ojo//Dw8P/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx
+ 8f/x8fH/8fHx//Hx8f/x8fH/8fHx//Hx8f/x8fH/8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw/+/v
+ 7//v7+//7+/v//Dw8P/w8PD/7+/v/+7u7v/t7e3/7e3t/+7u7v/v7+//7e3t/+7u7v/u7u7/7e3t/+3t
+ 7f/t7e3/7Ozs/+rq6v/r6+v/6+vr/+rq6v/q6ur/6enp/+np6f/p6en/6enp/+jo6P/w8PD/////////
+ /////////////////////////8////8A////AP///wD///8A////AP///wD///8A////AP///wD///8n
+ ////9///////////////////////////////////////////////////////////////////////////
+ /////////////////////////////////////////////////////////9////97////G////wD///8A
+ ////AP///7f//////////////////////////////////9nZ2fKfn5+Pn5+fOp+fnw8AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAADAAAABQAAAAcAAAAKAAAACwAAAA38/PzR////////
+ ////////////////////////////////////////////////////////////////////////9vb2/87O
+ zv/g4OD/6+vr/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t
+ 7f/t7e3/7e3t/+3t7f/s7Oz/7e3t/+3t7f/t7e3/7e3t/+7u7v/u7u7/7u7u/+7u7v/t7e3/7e3t/+3t
+ 7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+7u7v/u7u7/7u7u/+3t7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+3t
+ 7f/t7e3/7e3t/+3t7f/t7e3/7e3t/+zs7P/s7Oz/7Ozs/+zs7P/s7Oz/7Ozs/+zs7P/r6+v/6+vr/+vr
+ 6//r6+v/6+vr/+rq6v/q6ur/6+vr/+zs7P/s7Oz/7Ozs/+3t7f/t7e3/7Ozs/+zs7P/s7Oz/6+vr/+np
+ 6f/q6ur/6urq/+np6f/p6en/6enp/+np6f/o6Oj/6Ojo/+fn5//t7e3/////////////////////////
+ /////////9////8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////c///////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////f///+n////R////wD///8A////AP///wD///8A////D////+f/////
+ /////////////////////////////83NzeGfn591n5+fIp+fnwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAACAAAABAAAAAcAAAAMAAAAEAAAABUAAAAZAAAAHAAAAB7U1NRy////////////////////////
+ ////////////////////////////////////////////////////////1NTU/9fX1//g4OD/5OTk/+Tk
+ 5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk
+ 5P/k5OT/4+Pj/+Pj4//j4+P/4+Pj/+Tk5P/k5OT/5OTk/+Tk5P/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl
+ 5f/l5eX/5eXl/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5OTk/+Tk5P/k5OT/5OTk/+Tk5P/k5OT/5OTk/+Tk
+ 5P/k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Hh4f/i4uL/4uLi/+Li
+ 4v/i4uL/4+Pj/+Xl5f/m5ub/6enp/+rq6v/r6+v/6urq/+rq6v/r6+v/6+vr/+rq6v/q6ur/6enp/+np
+ 6f/o6Oj/6Ojo/+jo6P/o6Oj/5+fn/+fn5//t7e3///////////////////////////////////v///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////A////8f/////////////////////
+ ///////////////////////////////////////////////////////////////////////////////T
+ ////c////xP///8A////AP///wD///8A////AP///wD///8D////w///////////////////////////
+ /////////////8LCwsGfn59Yn5+fFJ+fnwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAQAAAAHAAAADQAA
+ ABMAAAAbAAAAIwAAACoAAAAwAAAANAAAADcNDQ079vb24///////////////////////////////////
+ ///////////////////////////////////k5OT/y8vL/9LS0v/V1dX/1tbW/9bW1v/W1tb/1tbW/9bW
+ 1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW
+ 1v/X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX1//X19f/19fX/9bW
+ 1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9XV1f/V1dX/1dXV/9XV
+ 1f/V1dX/1dXV/9XV1f/V1dX/1dXV/9XV1f/U1NT/1NTU/9PT0//T09P/1NTU/9TU1P/V1dX/19fX/9nZ
+ 2f/b29v/3t7e/+Hh4f/l5eX/5+fn/+jo6P/q6ur/6urq/+rq6v/q6ur/6enp/+jo6P/o6Oj/6Ojo/+jo
+ 6P/n5+f/5+fn/+bm5v/o6Oj///////////////////////////////////////8D////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///yf////3////////////////////////////////
+ ///////////////////////////////////////////////z////m////zf///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wP///+r/////////////////////////////////////////f39/aqq
+ qoKfn584n5+fCp+fnwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAABAAAABAAAAAkAAAAQAAAAGgAAACUAAAAxAAAAPQAA
+ AEcAAABPAAAAVQAAAFgAAABbiYmJi/v7+/f/////////////////////////////////////////////
+ /////////////+bm5v+8vLz/v7+//8HBwf/CwsL/wsLC/8LCwv/Dw8P/w8PD/8PDw//Dw8P/w8PD/8PD
+ w//Dw8P/w8PD/8PDw//Dw8P/wsLC/8LCwv/CwsL/wsLC/8LCwv/CwsL/w8PD/8PDw//Dw8P/w8PD/8PD
+ w//Dw8P/w8PD/8PDw//CwsL/wsLC/8LCwv/CwsL/wsLC/8LCwv/CwsL/wsLC/8PDw//Dw8P/wsLC/8LC
+ wv/CwsL/wsLC/8LCwv/CwsL/wsLC/8HBwf/BwcH/wcHB/8HBwf/BwcH/wcHB/8HBwf/BwcH/wcHB/8HB
+ wf/BwcH/wMDA/8DAwP/AwMD/wMDA/8DAwP/AwMD/wcHB/8HBwf/CwsL/xMTE/8jIyP/Ly8v/z8/P/9TU
+ 1P/b29v/4ODg/+Tk5P/n5+f/6Ojo/+np6f/p6en/6enp/+jo6P/o6Oj/5+fn/+bm5v/k5OT/4uLi/+Dg
+ 4P/h4eH///////////////////////////////////////8f////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///9z////////////////////////////////////////////////
+ ////////////////////x////2f///8L////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///5f/////////////////////////////////////////////3d3dyp+fn0Kfn58Xn5+fAgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAAEAAAACgAAABMAAAAfAAAALgAAAD8AAABPAAAAXgAAAGoAAAByAAAAeAAA
+ AHwAAAB+AAAAf1tbW5vy8vLz////////////////////////////////////////////////4eHh/6en
+ p/+oqKj/qKio/6ioqP+pqan/qamp/6mpqf+qqqr/qqqq/6qqqv+qqqr/qqqq/6qqqv+qqqr/qqqq/6mp
+ qf+pqan/qamp/6mpqf+pqan/qamp/6mpqf+pqan/qKio/6ioqP+oqKj/qKio/6ioqP+pqan/qamp/6mp
+ qf+pqan/qamp/6mpqf+pqan/qamp/6mpqf+pqan/qamp/6qqqv+qqqr/qqqq/6qqqv+pqan/qamp/6mp
+ qf+pqan/qKio/6ioqP+oqKj/qKio/6ioqP+oqKj/qKio/6ioqP+oqKj/qKio/6ioqP+np6f/p6en/6en
+ p/+np6f/p6en/6ioqP+oqKj/qKio/6ioqP+pqan/rKys/7Gxsf+0tLT/vb29/8TExP/Ozs7/1tbW/93d
+ 3f/j4+P/5ubm/+fn5//n5+f/5ubm/+Xl5f/j4+P/39/f/9ra2v/V1dX/0NDQ/8vLy//Gxsb/////////
+ //////////////////////////////8v////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8D////w///////////////////////////////////////////////6////4////8r
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////i///////////
+ ///////////////////////////////////6+vr1q6urWZ+fnxyfn58GAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAQAAAAKAAAAFAAAACIAAAA0AAAASQAAAFwAAABvAAAAfQAAAIgAAACRAAAAlQAAAJgAAACaAAAAmgAA
+ AJovLy+nw8PD3/f39/v///////////////////////////r6+v/X19f/jo6O/42Njf+Ojo7/j4+P/4+P
+ j/+Pj4//j4+P/5CQkP+QkJD/kJCQ/5CQkP+QkJD/kJCQ/5CQkP+QkJD/kJCQ/4+Pj/+Pj4//j4+P/4+P
+ j/+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+Pj/+Pj4//kJCQ/5CQkP+QkJD/kJCQ/5CQkP+Pj4//j4+P/4+P
+ j/+Pj4//j4+P/4+Pj/+Pj4//j4+P/5CQkP+QkJD/kJCQ/5CQkP+Pj4//j4+P/4+Pj/+Pj4//j4+P/4+P
+ j/+Ojo7/jo6O/46Ojv+Ojo7/jo6O/46Ojv+Ojo7/jo6O/46Ojv+Ojo7/jo6O/46Ojv+Ojo7/jY2N/46O
+ jv+Ojo7/j4+P/4+Pj/+Pj4//kpKS/5eXl/+ampr/paWl/66urv+6urr/xsbG/9DQ0P/X19f/3Nzc/93d
+ 3f/b29v/2dnZ/9bW1v/S0tL/zMzM/8bGxv/AwMD/urq6/7S0tP+vr6//+/v7////////////////////
+ //////////////8/////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////H/////P//////////////////////////////7v///9X////B////wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///9v////////////////////////////////
+ //////////////39/fzMzMx/n5+fHp+fnwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAgAAAASAAAAIgAA
+ ADYAAABMAAAAZAAAAHkAAACLAAAAmAAAAKEAAACnAAAAqwAAAKwAAACuAAAArgAAAK8AAACvAAAAsAoK
+ CrRWVlbIlJSU239/f9eAgIDugoKC/4KCgv+AgID/fHx8/3x8fP99fX3/fn5+/35+fv9+fn7/fn5+/39/
+ f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//35+fv9+fn7/fn5+/35+fv9+fn7/fn5+/319
+ ff99fX3/fX19/319ff99fX3/fX19/319ff99fX3/fX19/319ff9+fn7/fn5+/35+fv9+fn7/fn5+/35+
+ fv9+fn7/fn5+/35+fv9+fn7/fn5+/35+fv9+fn7/fn5+/319ff99fX3/fn5+/35+fv9+fn7/fn5+/319
+ ff99fX3/fX19/319ff99fX3/fX19/319ff99fX3/fX19/319ff99fX3/fX19/3x8fP98fHz/fX19/319
+ ff9+fn7/gICA/4SEhP+IiIj/kZGR/5qamv+np6f/tLS0/76+vv/Gxsb/ysrK/8jIyP/Gxsb/v7+//7m5
+ uf+zs7P/r6+v/6ysrP+qqqr/p6en/6ysrP/AwMD/+Pj4//////////////////////////////////9X
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///2v/////
+ /////////+P///+D////H////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///1v//////////////////////////////////////////////v7+/tfX
+ 14+fn58ln5+fBwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABgAAAA8AAAAdAAAAMgAAAEwAAABmAAAAfgAA
+ AJIAAACiAAAArAAAALIAAAC2AAAAuAAAALoAAAC6AAAAuwAAALsAAAC7AAAAuwAAALsAAAC8AAAAvQAA
+ AL5BRUPoZmtp/3B1c/9vdHL/b3Bu/3Bxb/9wcW//cHFv/3Bxb/9xcnD/cXJw/3FycP9xcnD/cXJw/3Fy
+ cP9xcnD/cXJw/3FycP9xcnD/cXJw/29ycP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29y
+ cP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29y
+ cP9vcnD/b3Jw/29ycP9vcnD/b3Jw/29ycP9vcnD/cHFv/3Bxb/9wcW//cHFv/3Bxb/9wcW//cHFv/3Bx
+ b/9ucW//bnFv/25xb/9ucW//bnFv/25xb/9ucW//bnFv/29wdP9ucHH/bnBw/3Bxb/9xcm7/cnNx/3d1
+ df98enz/i4KG/4+Mj/+VmZb/naOc/6iqpf+wrq7/s7Gz/7Gxsv+vr6//rKys/6enp/+oqKj/ubm5/8vL
+ y//g4OD/9fX1//////////////////////////////////////////////////9j////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///+L////S////wP///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////U/////v/////////////////////////////////////////////2tranJ+fnyifn58KAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAEAAAADAAAACgAAABcAAAArAAAARQAAAGEAAAB8AAAAlAAAAKYAAACyAAAAuAAA
+ ALwAAAC+AAAAvhcXGMozNDbZMjQ22TI0NtkyNTXZMjU12TIyNdkwMDPZLy8x2SsrLtlKSk/xYWFn/2lp
+ b/9oaG7/ZWVr/2Vla/9mZmz/ZmZs/2ZmbP9mZmz/Z2dt/2dnbf9nZ23/Z2dt/2dnbf9nZ23/Z2dt/2dn
+ bf9nZ23/Z2dt/2dnbf9nZ23/Z2dt/2dnbf9nZ23/Z2dt/2dnbf9nZ23/ZmZs/2ZmbP9mZmz/ZmZs/2Zm
+ bP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2Zm
+ bP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2ZmbP9mZmz/ZmZs/2ZmbP9lZWv/ZWVr/2Vl
+ a/9lZWv/ZWVr/2Vla/9lZWv/ZWVr/2FqZ/9gaGf/Ymdq/2Jma/9kaGz/aWxw/3J1dv97f37/iIuB/46O
+ jv+Vk5f/nJyc/5+goP+hoqL/o6Ok/7S0s//IyMj/2tra/+3t7f//////////////////////////////
+ //////////////////////////////////////////////9/////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///87////8///////////
+ ///////////////////////////////////e3t6pn5+fKZ+fnwoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAEAAAAFAAAAEAAAACAAAAA5AAAAVwAAAHUAAACQAAAApAAAALIAAAC6AAAAvRocHctBR2DqSlB5+kZH
+ gf9BPob/PTeJ/zsyjP86MYv/OjGL/zc0if81Mof/MzCF/zAtgv8tKn//MS6D/zYziP81Mof/NDGG/zQx
+ hv80MYb/NDGG/zQxhv81Mof/NTKH/zUyh/81Mof/NTKH/zUyh/81Mof/NTKH/zUyh/81Mof/NTKH/zUy
+ h/81Mof/NTKH/zUyh/81Mof/NTKH/zUyh/81Mof/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQx
+ hv80MYb/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQx
+ hv80MYb/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQxhv80MYb/NDGG/zQx
+ hv80MYb/NDGG/zkyh/84MIf/OTCJ/zw2h/9GQ4X/W1uH/3J0jf+Fh5T/kZOW/5iYmf+qqar/vr2+/9XV
+ 1f/o6Oj//Pz8////////////////////////////////////////////////////////////////////
+ //////////////////////////////+P////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///yv////z////////////////////////////////
+ /////////////+fn57qfn58un5+fDJ+fnwIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAIAAAAFgAA
+ ACoAAABGAAAAZwAAAIUAAACdAAAArwAAALkHCAjBPEBa5zw3k/8aFpT/GBKV/xcQl/8ZEJ3/GQ+f/xgP
+ n/8ZEZ7/GhOe/xYSof8UEJ//FBCf/xQQn/8SDp3/Ew+e/xURoP8UEJ//EhCf/xIQn/8SEJ//EhCf/xIQ
+ n/8SEJ//EhCf/xMRoP8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQ
+ n/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQ
+ n/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQ
+ n/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xIQn/8SEJ//EhCf/xgR
+ mv8aE5z/IRmf/zMsn/9NR57/aWWd/52ctP/IyM7/4eHi//f39///////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////+f////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////J////+f/////////////////////////////////////////////6Ojoxp+f
+ nzKfn58PAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAAAALAAAAHAAAADMAAABSAAAAdAAA
+ AJEAAACnAAAAtRQVFsZAQXf3IxqZ/xEKk/8VDaD/IBqn/y0qr/84OLT/P0K1/0VJuf9ITbr/Sk+8/1FO
+ u/9PTLn/UE26/1FOu/9QTbr/UE26/1BNuv9QTbr/Tk66/05Ouv9OTrr/Tk66/05Ouv9OTrr/Tk66/05O
+ uv9OTrr/Tk66/05Ouv9OTrr/Tk66/05Ouv9OTrr/Tk66/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BN
+ uv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BN
+ uv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/Tk66/05Ouv9OTrr/Tk66/05O
+ uv9OTrr/Tk66/05Ouv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/0tNvf9OULz/V1q3/2tt
+ sP+rq8X/6urt////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////+3
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8X
+ ////2//////////////////////////////////////////////t7e3SpKSkOZ+fnxCfn58BAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAOAAAAIAAAADoAAABcAAAAfgAAAJkAAACtFRYYw0E+
+ hvcZDZv/Fg2k/yMhqf9PTbf/W1rB/2RmxP9pa8P/am3C/2prxf9qacn/amjM/25rwf9tasD/bWrA/29s
+ wv9vbML/bmvB/21qwP9ua8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9tbML/bWzC/21swv9sa8H/bGvB/2xr
+ wf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xr
+ wf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xr
+ wf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xr
+ wf9sa8H/bGvB/2xrwf9sa8H/bGvB/2xrwf9sa8H/bGvB/2dky/9sa8b/fHy6/9jZ5P//////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////f////D////j////1P///8b////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wv////X////////////////
+ //////////////////////////////Ly8t2kpKQ8n5+fEp+fnwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAQAAAAQAAAAJQAAAEAAAABjAAAAhAAAAJ4CAgOyQ0J58R4Zmv8UCqr/MC24/01O
+ vv9dWcL/Yl/G/2Nhxf9iYMD/YV+//2BdwP9hWsL/Y1zF/11cxP9cW8P/XFvD/11cxP9eXcX/XVzE/1xb
+ w/9dXMT/XVzE/11cxP9dXMT/XVzE/11cxP9dXMT/XVzE/11cxP9dXMT/XVzE/11cxP9dXMT/XVzE/11c
+ xP9dXMT/XVzE/19bxP9fW8T/X1vE/19bxP9fW8T/X1vE/19bxP9fW8T/X1vE/19bxP9fW8T/X1vE/19b
+ xP9fW8T/X1vE/19bxP9fW8T/X1vE/19bxP9fW8T/X1vE/19bxP9fW8T/X1vE/19bxP9fW8T/X1vE/19b
+ xP9fW8T/X1vE/19bxP9fW8T/XVzE/11cxP9dXMT/XVzE/11cxP9dXMT/XVzE/11cxP9fW8T/X1vE/19b
+ xP9fW8T/X1vE/19bxP9fW8T/X1vE/2RdxP9qY8D/x8Xe////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////2////6P///9r////M////wP///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////C////8P/////////////////////////////////////
+ ////////8vLy4q6urkWfn58Wn5+fAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAUAAAATAAAAJwAAAEMAAABnAAAAiAAAAKFERF3WKiGa/w8In/8lKqv/Sk26/1RQuf9MTrr/TE66/01M
+ uv9MSrv/T068/1BNuv9PTbf/UVC4/1FOu/9RTrv/UE26/1BNuv9ST7z/UU67/1FOu/9RTrv/UU67/1FO
+ u/9RTrv/UU67/1FOu/9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1FO
+ u/9RTrv/UU67/1FOu/9RTrv/UU67/1FOu/9RTrv/UE26/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BN
+ uv9RTrv/UU67/1FOu/9RTrv/UU67/1FOu/9RTrv/UU67/1BNuv9QTbr/UE26/1BNuv9QTbr/UE26/1BN
+ uv9QTbr/UU67/1FOu/9RTrv/UU67/1FOu/9RTrv/UU67/1FOu/9RTrv/UU67/1FOu/9RTrv/UU67/1FO
+ u/9RTrv/UU67/1JOtf+hn9T/////////////////////////////////////////////////////////
+ /////////////////////////////////////////+////+3////g////0v///8P////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8D////s//////////////////////////////////////////////29vbsubm5VZ+f
+ nxWfn58DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAATAAAAKAAA
+ AEYAAABqAAAAiwMEBKQ4OJ34EQyj/yAbpv88OrH/QT27/zk7uP9BPbr/QT26/0E9uv9BPbr/QT26/0E9
+ uv9BPbr/QT26/0E+vP9APrn/Qj6//z88uv9ARLT/P0G3/zo6vP87Prj/QT65/z87uP9BP7r/QkK2/0BA
+ tv9BPbr/QDu8/0E5u/9APrr/QD66/0A+uv9APrr/QD66/0A+uv9APrr/QD66/0VCtv9CQbX/QkG5/z4+
+ uv8+Prr/QD+3/0BAtv9CP7r/Qjy5/0M+uf9EP7j/Qz63/0A+tv9BP7f/Qj+6/0E+uf8+QLb/PT62/z48
+ t/9CPrv/Qjy5/0E6uf9EPbz/Qjq8/0Q/uv9CPbb/Q0O1/0A8uf9BP7v/QD65/z8+tv8+P7f/Qj+9/0E/
+ uv8+QLb/P0G3/z9AuP8/QLr/QD65/z89uP9BPrn/QT65/0E+uf9BPrn/QT65/0E+uf9BPrn/QT65/0JA
+ uf/p6fb////////////////////////////////////////////////////////////////////////7
+ ////z////5P///9f////J////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///+n
+ //////////////////////////////////////////////j4+PS1tbVgn5+fGp+fnwYAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAUAAAAKQAAAEYAAABrAAAAi0FD
+ TsErKaD/Dguk/yIerf83NLL/ODK5/y8xs/8zMbP/MzGz/zMxs/8zMbP/MzGz/zMxs/8zMbP/MzGz/zY1
+ tf8zMrD/NDC3/zMvtv8zNK7/NTKw/zMttP83NLL/NjGy/zQvsv8zMbP/MTKy/zAxsf8xMbP/NDK0/zg0
+ tf8zMbP/MzGz/zMxs/8zMbP/MzGz/zMxs/8zMbP/MzGz/zMysv80M7P/NTO1/zMxs/8yMbH/NTOv/zYy
+ r/81MLH/NTGy/zQxr/8zMK7/MzGt/zQyrv81MrD/NDOz/zQzs/82Mbb/NTC1/zo4uv8zMbP/MTCw/zk1
+ tv80L7L/NTCz/zcxuP83Mrf/NzSy/zMvsP8zL7D/NDCx/zQwsf81MbL/NjKz/zYys/80M7H/MzS0/zMy
+ t/81Mrf/NDG2/zYxtP80MrT/NDK0/zQytP80MrT/NDK0/zQytP80MrT/NDK0/3Jwyf//////////////
+ /////////////////////////////////////////+P///+v////c////zv///8L////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///4//////////////////////
+ ////////////////////////9/f3+7S0tJSdnZ04n5+fCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAAUAAAAKgAAAEcAAABsAAAAjFpdedodF57/Dwyo/yAe
+ s/8tJ7T/KSO2/yUnsf8pJrL/KSay/ykmsv8pJrL/KSay/ykmsv8pJrL/KSay/yknr/8nJqz/Kye2/y0m
+ t/8rJqv/JyOg/yYem/8oH5f/Jh6a/ygjnv8mJKb/JiWx/yYns/8lJrL/Jiaw/yYnrf8oJ7P/KCez/ygn
+ s/8oJ7P/KCez/ygns/8oJ7P/KCez/yQktP8oJbb/JiOu/yQjo/8iIJf/JCGU/ychlv8lH5b/ISCU/yEg
+ lP8iIZX/IiGV/yEflv8gH5f/IiCb/yQinv8rIan/LSat/yYiqv8oKLL/Kiq0/yQkrv8rKLP/Kiiw/yQg
+ tf8pJbT/JyOr/ycjoP8mIZr/JSCZ/yUgm/8nIZ7/JSSk/yglqv8pJrH/JyS1/yYjtf8pI7b/KSS1/ygk
+ s/8qJ7P/Kiez/yons/8qJ7P/Kiez/yons/8qJ7P/Kiez/6ur4P//////////////////////////////
+ /////////6f///9T////G////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////c///////////////////////////////////////////
+ ///6+vr/tLS05Jubm4ydnZ1En5+fE5+fnwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAcAAAAUAAAAKgAAAEcAAABtAAAAjGFikecVD6T/Dg2w/xwatP8fGbT/HBe2/xse
+ r/8cGbL/HBmy/xwZsv8cGbL/HBmy/xwZsv8cGbL/HBmy/xsZrv8bGqz/Hhu0/x4ZsP8ZFJn/GhiC/xoV
+ cP8ZEmf/FxFo/xgZcf8XFIf/GBSj/x0bsP8dHLL/HRqz/x0bsP8cGbL/HBmy/xwZsv8cGbL/HBmy/xwZ
+ sv8cGbL/HBmy/x0btP8dGK//FxOa/xcXg/8UFWv/ExJi/xURY/8VEWP/FRNl/xQSZP8TEWP/EBFi/xER
+ Zf8UE2n/FhRu/xUSbv8UD3j/GRWG/x0amP8YGKL/GRmt/x4ctf8bGrD/HBqw/x0Ztf8dGqv/Fg+W/xsa
+ fP8WFG3/ExBm/xYRbP8cF3P/FxaW/xsZof8eGq//HRm1/xwXtv8dGbX/IBu0/x4ZsP8cGbL/HBmy/xwZ
+ sv8cGbL/HBmy/xwZsv8cGbL/HBmy/6qp4v//////////////////////////////////m////wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///9b//////////////////////////////////////////////z8/P+1tbX/n5+f756e
+ nsGenp55n5+fOJ+fnxCfn58BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAcAAAAVAAAAKwAAAEgAAABtAAAAjV9fnO4VDa7/Cwux/xERsf8UDbH/FA20/xIUr/8UErL/FBKy/xQS
+ sv8UErL/FBKy/xQSsv8UErL/FBKy/xcStf8UErL/FRCx/w8Mpf8PDYn/JSl3/zQ6Zf84OVv/Ojlh/zY5
+ Zf8fIHj/EguW/xIPqP8UEK//Fg61/xgQsf8TEbH/ExGx/xMRsf8TEbH/ExGx/xMRsf8TEbH/ExGx/xMT
+ rf8SDaT/Ew2K/ysref82OWX/ODpc/zo7Xf88O13/ODZa/zk4Wv85OFr/ODhc/zo5YP82NV3/KSdR/xoX
+ RP8REkr/Dw5W/xAPb/8QDon/Eg+g/xQRrf8TDrH/FBC1/xURsP8VEp3/EwuI/zAzcP84OWX/Njdd/zg4
+ YP88O2f/CgyJ/xAQmv8UEKv/FA6z/xQOs/8UD7D/FRGw/xMQrP8TEbH/ExGx/xMRsf8TEbH/ExGx/xMR
+ sf8TEbH/ExGx/46N2v//////////////////////////////////v////wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///87
+ ////+//////////////////////////////////////////////Gxsb/n5+f+p+fn+afn5+zn5+fdJ+f
+ nzSfn58Rn5+fAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAVAAAAKwAA
+ AEgAAABtAAAAjV1bnu8TDLH/CAiy/wwKsP8QCq//EQqz/woKsP8LCa//Cwmv/wsJr/8LCa//Cwmv/wsJ
+ r/8LCa//Cwmv/wsIsv8LCLH/Cgmt/wsIpP8VE47/R06H/2t0ff90eXj/dHR6/2dteP84OoD/Fg+a/w8K
+ qf8OCq//EAa2/xIJs/8LCa//Cwmv/wsJr/8LCa//Cwmv/wsJr/8LCa//Cwmv/wwNq/8OCKP/GROK/0xN
+ hf9qcHv/c3d4/3V3eP90dnb/dXR4/3d2eP92dXf/dHN1/3Z1ef96eH7/dnV+/3Fwev9lann/Rkpn/xob
+ U/8JCF7/CQV8/wsGl/8SDa7/DAax/wwIrf8PDJf/GxCK/1hegf9vdH3/cHN3/29yd/9tb3f/BgmJ/woL
+ mf8PCqv/Dwqz/wwKsP8MC67/Dguu/w4Kr/8LCa//Cwmv/wsJr/8LCa//Cwmv/wsJr/8LCa//Cwmv/4aF
+ 1////////////////////////////////////////9P///97////Q////wv///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////U/////v/////
+ ///////////////////////////////////9/f3/vr6+/5+fn/qfn5/ln5+ftZ+fn2qfn58xn5+fDZ+f
+ nwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAVAAAAKwAAAEkAAABtAAAAjVpa
+ ne8UDLP/CQi2/w4Ltf8SDLH/EQ2z/wsJtv8NDbX/DQ21/w0Ntf8NDbX/DQ21/w0Ntf8NDbX/DQ21/w4N
+ t/8MDLb/Cwuz/wwJrP8YE5b/VFaQ/3uAgf+EgXz/goCA/3R7fv8/QYj/Fg2j/wsJr/8MDLT/DQq6/w4M
+ sv8PDLX/Dwy1/w8Mtf8PDLX/Dwy1/w8Mtf8PDLX/Dwy1/wkMtP8PCa7/HRWS/1lZj/97gIP/goR+/4OB
+ gP+DgHz/goB//4SDf/+Eg3//gYF7/31+ev99fnr/f4B+/4GBgf9/gYH/fX6C/3Fxg/9AP2n/FRNf/wwJ
+ fP8NCZ7/EQy1/wsJuf8ODZ//HRGT/2ZtiP98gYD/foB6/4F/fv97enz/Cw6U/w8No/8PC7H/Dwq5/w4L
+ tf8MDbH/DAyy/w4Ltf8NDbX/DQ21/w0Ntf8NDbX/DQ21/w0Ntf8NDbX/DQ21/zo4wv//////////////
+ ///////////////////////////////////////////////P////m////2P///8r////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///2P/////////////////////
+ /////////////////////////f39/7W1tf6fn5/5n5+f4J+fn7Cfn59rn5+fLZ+fnwsAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAVAAAAKwAAAEkAAABuAAAAjlpanO8XELX/DQy6/xEN
+ uv8UD7L/FBC1/xAOvP8PDrj/Dw64/w8OuP8PDrj/Dw64/w8OuP8PDrj/Dw64/w4Qtf8ODrj/Dg64/xIN
+ tv8fFqP/W1mb/4KCiP+JgIP/hH+I/3h/iP9DRJT/Fw+v/w0Nuf8LELn/DQ68/w0Ps/8RDrj/EQ64/xEO
+ uP8RDrj/EQ64/xEOuP8RDrj/EQ64/wgMvv8QC7r/Hhed/1tclv98f4f/gYGB/4eAh/+HgYb/g4KG/3+A
+ hP+AgoP/g4WF/4SGhv+ChIT/gYOE/4GDhP+FgIH/hIF9/4WGhP94eoX/R0h0/xcXcf8LCZH/Dgqv/wkL
+ xP8QEKr/IRSg/2pyj/99gYL/gH97/4SAhf9+e4T/EhOf/xIQqv8TDbr/Egy9/w8Nuv8ODrb/Dg23/w8M
+ vP8PD7f/Dw+3/w8Pt/8PD7f/Dw+3/w8Pt/8PD7f/Dw+3/xEOuP+1tOn/////////////////////////
+ ////////////////////////////////////////////////////8////7v///+D////S////xP///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///9v////////////////////////////////
+ //////////////r6+v+ysrL/n5+f9p+fn9+fn5+pn5+fZ5+fnymfn58LAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAcAAAAVAAAAKwAAAEkAAABuAAAAjlhao+8QCb7/Dwy//xUUvv8TE7n/EhG7/xUS
+ vP8TErz/ExK8/xMSvP8TErz/ExK8/xMSvP8TErz/ExK8/xERu/8UEL3/FBO9/xAStv8bFbD/YGCg/4SI
+ if+KiIf/kYmK/36Eif9ERJ7/GxK2/xUSvP8UEr//FhO9/xQRu/8QEr7/ExO9/xYWvP8VEbb/GBK3/xsU
+ u/8VELn/GRO+/xUTuf8RD7z/Ghep/19env+HiIz/i4mJ/4eJif+Ghoz/hoiT/4aCq/+Ij6j/hpKc/4uT
+ oP+NkJ7/ioyW/4OMif+Fio3/lImF/5CMh/+AhYj/foOG/z47ef8ODYX/Eg+h/xQSsv8VFLf/GxOm/290
+ k/+JhYr/ioWG/4aFh/+BgIn/FBeo/xUUsP8WErj/FhK//xQSv/8VFL7/FBO9/xISvP8VD7z/FxS+/xIR
+ u/8REL7/FBLC/xMSwP8UE73/ERG3/xMSvP8+Psj/////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////b////o////2////8z
+ ////A////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////j///////////////////////////////////////////
+ ///29vb/rq6u/p+fn/mfn5/en5+fqZ+fn1ufn58nn5+fCZ+fnwEAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAcAAAAVAAAAKwAAAEkAAABuAAAAjllapfARCr//EA3B/xcWwP8WFr7/FRS+/xgVv/8WFb//FhW//xYV
+ v/8WFb//FhW//xYVv/8WFb//FhW//xUVv/8ZFcL/FxbA/xMVuf8eGLP/ZGSk/4qOj/+Rj47/lZKO/4KO
+ kP9GSKD/Gxa1/xUVvf8UFL7/FRW//xYWwP8TEsD/ExLA/xYUwf8aFsP/GRbA/xgVv/8aF8H/FxS+/xkX
+ vf8VE8D/Hhut/2Rjo/+NjpL/kY+P/42Pj/+MjJL/eHS1/3pvz/+Cgtb/honT/42K2f+PitX/kYrT/46P
+ yf+Dh6r/k42S/5OOj/+Gi4n/jI6P/29wlv8WFoD/FhOf/xYUtP8YF7r/Hxeq/3R5mP+Pi5D/kYyN/4yL
+ jf+Hho//FRas/xcWtP8YE7z/FxLB/xcTwP8VFL7/FRS+/xUTwP8VFL7/FxbA/xYVv/8VFL7/FRPA/xQS
+ v/8WFb//Fha+/xYVv/8WFb//trbr////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////9////8P///+P
+ ////U////xv///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///5v/////////////////////////////////////////////9PT0/6io
+ qP6fn5/1n5+f2Z+fn6Ofn59dn5+fI5+fnwgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAVAAAAKwAA
+ AEkAAABvAAAAjlxdrPUSC8D/EA/D/xoYxf8aGsL/GhnD/xwZw/8aGcP/GhnD/xoZw/8aGcP/GhnD/xoZ
+ w/8aGcP/GhnD/xkZw/8cGMX/GhnD/xYYvP8hG7b/aGio/5GVlv+YlpX/lpaW/4iTm/9GSqL/HBqw/xoZ
+ vP8WFrz/GRq+/xsbwf8dGsP/HxzG/xkXxP8aGcf/GRfH/xgXxf8cHMj/GBbD/xwawP8YFsP/IR6w/2hn
+ p/+TlJj/mJaW/5SWlv+Tk5n/U1G1/0lByv9RTdT/VlXT/1pV2v9fV9n/ZmDd/2lq2v9uccb/jIut/5KR
+ mv+UmZD/mZeW/4qPmP85Oor/GBSb/xgWtv8aGbz/Ihqt/3p/nv+Wkpf/mJOU/5OTk/+OjZb/Ghq0/xwa
+ uv8eGcL/HRnG/x0Zxv8aGcP/GxrE/xwax/8YG8T/FxrD/xoaxP8cHMT/GxrE/xoZw/8ZF8T/GRnF/xoZ
+ w/8aGcP/JyfH/4yM4f/x8fv/////////////////////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////n
+ ////r////3P///8z////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wP///+r//////////////////////////////////////////////Dw8P+mpqb/n5+f9J+f
+ n9afn5+bn5+fWZ+fnyGfn58HAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAWAAAAKwAAAEkAAABvAAAAjlxd
+ rfUTC8P/EhHF/x4cyf8eHsb/Hh3H/yAdx/8eHcf/Hh3H/x4dx/8eHcf/Hh3H/x4dx/8eHcf/Hh3H/x0d
+ x/8gHMn/HRzG/xocwP8kHrn/bGys/5ebnP+enJv/m5mf/46Vpv9LS5//Hxqf/xsapv8XFKX/Fxik/xYX
+ pf8aFqX/Hhut/xsZs/8cG77/Hh/H/xsbx/8bGsj/HRvL/x8dw/8cGsf/JCGz/2xrq/+am5//n52d/5qc
+ nP+ZmZ//RUm5/ysowf8qKcX/Ky3H/y8qy/8zL8v/PDnS/0FEz/9HS8//bmq8/5SUpP+fopn/oZ2c/5SY
+ k/9tcp//HRad/xkYtv8cHLz/Jh6x/4CFpP+dmZ7/n5qb/5qamv+UlJr/Gxy0/xwbuf8eGr//IBzB/x4d
+ wf8dHL//HRzA/x4cwv8cHsP/GxzE/xwbxf8hHsj/IB3G/yAgyP8eHcf/HR3J/x4dx/8eHcf/Hh3H/x4d
+ x/8yMcz/nJzm//j4/f//////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////////+z
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8D
+ ////w//////////////////////////////////////////////o6Oj/o6Oj/J+fn/Ofn5/Tn5+fm5+f
+ n06fn58fn5+fBQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAWAAAALAAAAEoAAABwAAAAjlxdrfUSDcT/FBLJ/yEf
+ zP8iIsr/IiHL/yQgzf8iIcv/IiHL/yIhy/8iIcv/IiHL/yIhy/8iIcv/IiHL/yIizP8lIc7/IiHL/yAi
+ xv8pI77/cXGx/5+jpP+npaT/rKar/5qbqf9RTY7/HBl1/xUUcv8TEXH/Fxdx/xYXcv8XFnj/FxZ+/xka
+ jP8YGZn/Ghyq/yMiwP8kIcr/Ih/P/yQiyP8hH8z/Kie5/3Jxsf+io6f/qKam/6KkpP+hoaf/Rky9/yYh
+ wv8gH8n/IiLM/yIfz/8nIc7/KifR/yotzP8wM9X/Rj3D/5OWsv+opqX/qKSj/6impv+MlKX/Jhuh/x0c
+ uP8fH7//KiK1/4aLrP+loaf/qKOk/6Kjof+cnaH/HiCk/xwcpP8bGqb/HBun/x0dp/8dHaX/Ghym/xsc
+ qv8dHa3/IR+5/yEdw/8lIc7/Ih/J/yIiyv8iIsr/ISHL/yIhy/8iIcv/IiHL/yIhy/8iIcv/IiHL/y8u
+ zv9gX9n/kJDl/7298P/x8fz/////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////+f////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////C////8f/////
+ ////////////////////////////////////////5OTk/6CgoP2fn5/xn5+f0p+fn5afn59Sn5+fG5+f
+ nwUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAcAAAAWAAAALAAAAEoAAABwAAAAj1xdr/UTDcb/FxXM/yUj0f8mJ8//JibS/ygk
+ 0f8mJc//JiXP/yYlz/8mJc//JiXP/yYlz/8mJc//JiXP/yYm0P8qJtP/JiXP/yQmyv8sJsH/dXW1/6er
+ rP+vraz/s6+q/6alp/9wb5H/Sklz/0VGbP9FRGz/Rkhq/0RFa/82N2r/GRpS/xcXV/8aHGr/Gxt//yEg
+ nv8lI7n/KSXK/ycly/8lI9D/LSq8/3d2tv+pqq7/sK6u/6qsrP+pqa//S1G8/yomwv8oJc7/KSnR/yYk
+ 0v8oJc//KSXS/ykqzv8mKtb/NyvR/4yOt/+trK7/rKqp/7Ovtf+boqX/Ny6n/yAguv8iI8H/Lia5/4yR
+ sv+sqK7/r6qr/6qrqf+lp6j/ICF8/xoZef8WFXX/FRVz/xYXcf8WF3H/FhZ0/xcWeP8ZF3v/IR+X/yAa
+ r/8pJcv/JyXS/yQkzv8mJs7/JibO/ycm0P8nJtD/JybQ/ycm0P8nJtD/JybQ/ycm0P8nJtD/JiXP/yUl
+ 0f8pJs//Q0PW/3Nz4f+Xluj/0M/z//7+/v//////////////////////////////////////////////
+ //////////////////////////////////////////////+L////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///xf////X////////////////
+ /////////////////////////////9/f3/+goKD+n5+f8J+fn86fn5+Pn5+fS5+fnxmfn58EAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAcAAAAWAAAALAAAAEoAAABwAAAAj1xdsPUUDcj/GhjQ/ygn1f8rLNT/KirW/ysp1v8rKtT/KyrU/ysq
+ 1P8rKtT/KyrU/ysq1P8rKtT/KyrU/yoq1P8uKtf/KinT/ygqzv8wKsX/enq6/6+ztP+4trX/urev/7m6
+ tv+rrLr/p6qy/62xsv+ysLb/sbCy/62stf+sq7v/qqq4/5qarP9qaoj/MzJq/xkZc/8gHpr/LCm7/yoo
+ zv8oJtP/MS7A/3x7u/+xsrb/ube3/7O1tf+xsbf/UFi9/zAuxP8tLM//LC7Q/ysr0f8uLdH/LCzU/ywu
+ 0v8kKdL/NCzT/4GAuP+ztLj/sraw/7eyu/+tsLj/UU6x/yUlv/8nKMb/Myu+/5KXuP+0sLb/uLO0/7O0
+ sv+vsbL/UVB6/0xLd/9IR3P/R0dv/0lJbf9ISWv/SEdv/0pHdP9KTHX/QkCM/yEemf8oJcH/KyvV/ygq
+ 1v8sK9X/LSrU/ysq1P8rKtT/KyrU/ysq1P8rKtT/KyrU/ysq1P8rKtT/KinT/yoq1v8uK9T/KSnT/yop
+ 1/8KCcr/GBHG/6OjtP/Nzc3/4uLi//Ly8v/6+vr/////////////////////////////////////////
+ //////////////////////////////9/////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8X////5///////////////////////////
+ ///////////////////V1dX/n5+f/J+fn/Gfn5/Jn5+fip+fnz6fn58Un5+fAQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAWAAAALAAA
+ AEsAAABwAAAAkF1esfUVDsn/HBrS/ysq2P8uL9f/Li7a/y4s2f8vLtj/Ly7Y/y8u2P8vLtj/Ly7Y/y8u
+ 2P8vLtj/Ly7Y/y4u2P8yLtv/Li3X/ywu0v81L8r/gIDA/7a6u/+/vbz/wr+7/7+/v/+7u8f/u8C+/8HC
+ uf/Cvbz/wb24/8K8wf/Av7v/w8G5/8HAtv/BwcH/mZiy/0dGiP8eHoj/KSmr/y0r0f8rKdb/NTLE/4GA
+ wP+3uLz/wL6+/7q8vP+5ub//VVjE/zMuzf8vLNb/Li3X/y8t2v8zL9z/MCzf/y8u3P8qMdT/My7N/4N+
+ w/+6vL3/vMS6/7u6vv+2tsj/XmKx/ysrxf8tLsz/OTHE/5mev/+8uL7/wLu8/7y9u/+4urv/uLa8/7Wy
+ u/+0srj/tbS2/7W2tP+1tLD/tbK0/7ayuP+tsbL/hIWx/zk2nf8rKb7/LS7W/yst2f8xL9z/MizZ/y8u
+ 2P8vLtj/Ly7Y/y8u2P8vLtj/Ly7Y/y8u2P8vLtj/Li7W/y0t2f8xLtf/LCzW/ywr2f8LCsz/GRLH/6Gg
+ tP+/v7//zMzM/9fX1//a2tr/3d3d/+Xl5f/s7Oz/9PT0//39/f//////////////////////////////
+ //////////////9f////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wP///+n////a////w////8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////J////+f/////////////////////////////////////
+ ////////z8/P/5+fn/yfn5/qn5+fv5+fn3Wfn581n5+fCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAWAAAALQAAAEsAAABxAAAAkFtb
+ t/UNCtH/GhzY/zYy3/86M9z/ODPc/zY32/82NNr/NjTa/zY02v82NNr/NjTa/zY02v82NNr/NjTa/zM0
+ 3P84Mt3/NzXb/zM02P85OcP/hILI/8LCzv/Hx8f/yMPF/8bHw//Cws7/xsrF/8vGx//Mx8T/y8bD/8vG
+ x//JyMr/v8m9/8nCyf/RyMT/xMTK/6+yx/9BQIL/IyuW/zEvvv8zMs7/OzbH/4SDx//CxMz/xcXF/8TH
+ xf/CwcX/W17H/zkwzf80Mtj/MzXZ/zMz2f83Ntr/NDTc/zM02P81MtX/Nz3G/4N+yf/Dwsv/vMfF/8jJ
+ x//EwMz/XF/B/zI0z/8yNM//PDPD/5+hyv/FxsL/xsbG/8bGxv/KxsX/x8bK/8LBw//CwcP/xMTE/8PD
+ w//DwsT/wsHF/8C/w/+7wL//lZ6//z85wP8wLNn/MTPf/zMw5P83Ntn/NzPZ/zY02v82NNr/NjTa/zY0
+ 2v82NNr/NjTa/zY02v82NNr/NDHa/zo03/83NdX/NTba/zcz2P8FBdv/CwzS/6Khq/+9vb3/y8vL/9bW
+ 1v/Z2dn/2dnZ/9fX1//V1dX/1dXV/9PT0//Z2dn/+vr6//////////////////////////////////9X
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///3//////
+ //////////f///+n////P////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///zf////z/////////////////////////////////////////////8nJ
+ yf+fn5/7n5+f4p+fn6ifn59bn5+fGZ+fnwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAWAAAALQAAAEsAAABxAAAAkF9fv/kOC9L/HB7a/zk2
+ 4P8+N97/PDfg/zo73/87Od//Oznf/zs53/87Od//Oznf/zs53/87Od//Oznf/zg43v87Nt//Ojje/zY3
+ 2/89Pcf/iIbM/8fI0v/Mzcv/zs7I/8nQyf+5utb/ur7W/8DC2v/Gxtj/xcXX/8TG2P/Bv9X/xtLS/83O
+ zP/WzMz/0c/P/8TFz/+QkLj/MzCd/zIwv/81NND/PjnK/4iHyf/HydH/y8vL/8vOzP/JyMz/YmLM/0A4
+ 0/89Od7/OTvd/zY23P88O9//Ojfg/zg32/84Ndj/NTfF/4qIyv/Ny9H/xs7N/9LRzf/Cwcr/Z2fT/zk7
+ 1v84OtX/QjnJ/6ao0f/Mzcn/zczO/83Nzf/OzMz/zs7O/83OzP/Nzsr/zc7K/8vMyP/Ky8f/ysvH/8rL
+ yf/KydL/pKrP/1RP0P8/PN//OTvf/zk35f87O9v/PTjh/zo43v86ON7/Ojje/zo43v86ON7/Ojje/zo4
+ 3v86ON7/OTbf/z454v87Otj/ODnd/zo22/8GBtz/DA3T/6OirP++vr7/y8vL/9bW1v/Z2dn/2NjY/9bW
+ 1v/U1NT/09PT/9LS0v/Nzc3//f39//////////////////////////////////8/////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////L/////v/////////////////////
+ /////////9////93////G////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///87////+/////////////////////////////////////////39/f+9vb3/n5+f85+f
+ n9Gfn5+An5+fL5+fnwwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAcAAAAWAAAALQAAAEwAAABxAAAAkV5gwvoOC9b/HyHd/z885f9EP+L/QT3i/0FA
+ 4/9AP+P/QD/j/0A/4/9AP+P/QD/j/0A/4/9AP+P/QD/j/z0+4v9BPeP/QD/j/zw+4P9EQsr/jozS/87P
+ 2f/V1tT/1tTT/8nO1/+cmOD/kZDm/5ic6/+cn+n/oaHv/6Gj6f+qqef/srvh/87S1//Z0tf/19fR/9TV
+ 0f/HydT/Ukis/zY0w/84N9P/Qj7N/46Nz//P0tf/1NTU/9TX1f/S0dX/Y2fN/0I80f9BQN7/P0Lg/z49
+ 4f9CP+L/QT3j/z8/3/9APt7/NzXE/5ORxf/Y1df/0dPU/9fW0v/R1Nn/aGbh/0JB3f8+QNv/Rz7O/6ut
+ 1v/S1dP/1dTW/9TT1f/V0tT/wL3W/8bD3P/Kyd3/ycnb/8nJ2//Jydv/ycnb/8nJ2//Dv+P/o6Tg/2Vg
+ 4f9OTOX/P0Pe/0A+5P8/QN7/QD3m/0A/4/9AP+P/QD/j/0A/4/9AP+P/QD/j/0A/4/9AP+P/Pz7i/0RA
+ 5v9BQNz/Pj/j/z084P8HBt7/DQ3V/6Ohrf++vr7/y8vL/9XV1f/Y2Nj/19fX/9XV1f/S0tL/0tLS/9DQ
+ 0P/Kysr///////////////////////////////////////8r////AP///wD///8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8D////z///////////////////////////////////////////
+ ////+////7P///9T////A////wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////U/////v////////////////////////////////////////29vb/oqKi+p+fn+afn5+in5+fU5+f
+ nxmfn58CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAcAAAAWAAAALQAAAEsAAABxAAAAkF5fw/oPDNj/IiTh/0RC6P9LRuX/RkPm/0ZG5v9GQ+b/RkPm/0ZD
+ 5v9GQ+b/RkPm/0ZD5v9GQ+b/RkPm/0VF5f9IQ+b/R0Tn/0BD4v9JR8//lJPX/9XW4P/d3tz/4uDf/83T
+ 5v+Be+b/aGPu/21v8/9wcfH/d3P6/3l69P+Bfuz/gYXk/7W24v/b2d//3N3Z/97f1v/Z29v/gHfI/zw7
+ x/8+Ptj/R0PS/5ST1f/W2d7/3Nzc/9zf3f/Z2Nz/am/V/0RB0/9CRN7/Q0ni/0JE5v9GROT/REHk/0RE
+ 3v84OMz/Qz7B/66u0v/g29z/3tvd/93c2P/M0t3/VVHY/0hI4v9ERN7/S0LS/7Cy2//Y29n/3Nvf/9na
+ 3v/a1tv/jYbh/5mS7f+hm/L/op3y/6Sg8v+kofH/op/v/6Of8f+bluv/h4Xp/2Fg7P9OUen/RUfi/0dE
+ 5/9FROD/R0Pp/0dE5/9HROf/R0Tn/0dE5/9HROf/R0Tn/0dE5/9HROf/R0Tn/0lG6f9GRuD/Q0Xn/0JB
+ 5f8IB9//Dg7W/6Ghr/++vr7/y8vL/9XV1f/X19f/1tbW/9TU1P/R0dH/0NDQ/87Ozv/Q0ND/////////
+ //////////////////////////////8f////AP///wD///8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///+D////////////////////////////////////////////////////////////////
+ ////5////4v///8n////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///2P/////
+ ////////////////////////////////////////ycnJ/p+fn++fn5+0n5+faJ+fnyKfn58EAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAWAAAALAAA
+ AEoAAABwAAAAj19fxfoPC9n/JCbj/0lI7P9QTOf/TEjn/0xL6f9MS+n/TEvp/0xL6f9MS+n/TEvp/0xL
+ 6f9MS+n/TEvp/0pM5/9NSOn/TEvp/0VI5v9NTNL/mZja/9vd5f/j5OL/5ejZ/9Lb5f91cN3/UE3f/1JV
+ 5v9VVub/WFbv/1pc5v9iXOn/Xlvn/42H3v/d4uX/3+Pk/+Hi3v/e3uT/l5bU/0ZF0f9FRd//TEnV/5mY
+ 2v/c3+T/4uLi/+Hk4v/f3uL/b3Lf/0tG3f9ISuT/SE3m/0pK6v9QS+z/Skbl/0RE1v9BQb3/RECn/8XF
+ 3f/n4uP/5OHj/+Tl4//Dxef/V1Tg/09Q6P9KS+P/UEjV/7a44f/f4uD/4+Lm/9/g5P/e3eH/YGHh/2xu
+ 6/90dvL/dXjy/3d78v92evD/dHju/3N37v9wbO3/ZGTu/1ZY8v9NUez/Skrq/09K6/9PS+b/T0rt/0xL
+ 6f9MS+n/TEvp/0xL6f9MS+n/TEvp/0xL6f9MS+n/S0ro/09K6/9NS+T/SUzr/0ZF6P8IB9//DA7Y/6Kh
+ sf++vr7/ysrK/9TU1P/W1tb/1tbW/9PT0//Q0ND/z8/P/8zMzP/Pz8//////////////////////////
+ //////////////8D////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///zf////7
+ ////////////////////////////////////////////////////////////////////////////////
+ ////w////1////8H////AP///wD///8A////AP///wD///8A////AP///wD///9v////////////////
+ ////////////////////////9vb2/6KiovGfn5+3n5+fbJ+fnyOfn58EAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAcAAAAVAAAAKwAAAEgAAABtAAAAjV5g
+ yPoQCt3/Jifn/01M7/9VU+j/UU/p/1FQ7P9RUev/UVHr/1FR6/9RUev/UVHr/1FR6/9RUev/UVHr/1FR
+ 6/9UUOz/U1Ds/0xO6f9SUdb/nZze/+Hj6//p6ub/6erg/9rh8P96ddj/T0zR/1BP2/9PT9n/UEzb/05N
+ 0v9PSs//Qj7F/310zv/f5OX/4+fs/+Tm5v/c3ev/nZ3d/1JS3P9OT+f/Uk/b/52d3f/h5On/6Ojo/+fp
+ 6f/j4ub/b2/Z/09I2f9NTd3/TE7c/05K3/9RTN3/SEPO/zw8uP84OJL/bGyo/93d6//s6ur/6Ojo/+Lk
+ 5f+zsvL/Yl/r/1dW7P9PUOb/VE3Y/7u95f/l6eT/5+nq/+Xm6v/j4ub/TUrj/1FP5f9UUuf/VVTm/1ZW
+ 5v9WVub/VVXl/1VU5v9ZV9//UlLi/1FT5/9OT+X/Uk7t/1VQ7/9UUer/U1Ds/1FR6/9RUev/UVHr/1FR
+ 6/9RUev/UVHr/1FR6/9RUev/UFDq/1RR7f9SUef/TlHw/0xL7v8JCOL/Dg/b/6Kgs/++vr7/ysrK/9TU
+ 1P/W1tb/1dXV/9PT0//Pz8//zc3N/8vLy//T09P///////////////////////////////////v///8A
+ ////AP///wD///8A////AP///wD///8A////AP///wD///8A////B////9f/////////////////////
+ ///////////////////////////////////////////////////////////////////////////////z
+ ////l////zP///8A////AP///wD///8A////AP///wD///8A////k///////////////////////////
+ /////////////8rKyvWfn5+wn5+fYZ+fnx+fn58DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYAAAATAAAAKAAAAEQAAABoAAAAiGBhy/oSDOH/Jyrq/1JS
+ 8v9aWev/VlTt/1dX8f9YVu//WFbv/1hW7/9YVu//WFbv/1hW7/9YVu//WFbv/1dY7v9aVvH/WVfx/1FT
+ 7f9XV9n/oqLi/+bo8P/v8Oz/7+zu/+Pk+P97dcb/R0Wp/0Q/sv9DP7D/Pzyp/zw7ov81NJL/PkKT/6Ch
+ zf/o5+v/6+zw/+7y7f/k5vH/oJvw/15e6P9WV+//V1Tg/6Ki4v/m6e7/7e3t/+zu7v/p6Oz/dHPD/0lC
+ tf9BQrL/QESt/z8+rP8+OqP/NzaU/zM3hf85OnT/ur7Q//Hw+f/s7Oz/7/Lw/+To7f+ck/T/Z2ju/1xc
+ 7v9WVuj/WVHa/8DD6f/r7+n/7O7v/+nr7P/o5+n/Ske7/0RBtP9BP7D/Q0Gy/0NCsP9DQbL/Q0Gy/0RB
+ tP9FQ63/QEC2/0VJv/9KS8v/V1Hm/1lU7f9YWOz/U1bu/1hW7/9YVu//WFbv/1hW7/9YVu//WFbv/1hW
+ 7/9YVu//WFft/1lX8f9XV+v/VVb0/1FQ8/8ICeP/Dw/d/6Oitv+/v7//y8vL/9TU1P/W1tb/1dXV/9LS
+ 0v/Ozs7/zMzM/8fHx//T09P//////////////////////////////////9////8A////AP///wD///8A
+ ////AP///wD///8A////AP///wD///8A////i///////////////////////////////////////////
+ ///////////////////////////////////////////////////////////////////////////////T
+ ////b////xP///8A////AP///wD///8A////B////+f//////////////////////////////////9TU
+ 1PWfn5+jn5+fUZ+fnxifn58CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAQAAAAQAAAAIwAAAD4AAABhAAAAgmVm0/4UDuP/Ki3t/1ZX9f9eXu7/Wlnv/1tb
+ 9f9cW/H/XFvx/1xb8f9cW/H/XFvx/1xb8f9cW/H/XFvx/1tc8v9eW/T/XVv0/1VY8P9aWtz/pqbm/+nr
+ 8//y8+//+PTz/+bo8v90dKr/Nzp3/y0sfP8vLnj/Kixt/yYrav8sLGj/ZG+N/+Hp6P/58fj/8/Dy//H0
+ 6//r7/T/lInx/2Vl7f9cXfX/W1jk/6Wl5f/q7fL/8fHx//Dy8v/t6/H/dXWl/zs1h/8nLHf/KjF2/yos
+ c/8pKWn/LS9l/ztEZf+pqtD/7vbs/+3s8P/09vb/6/Du/9zk6/+IfPL/bG7w/2Fi8v9aW+v/Xlfe/8XJ
+ 7P/v8+3/8PLy/+zw8f/s6+3/Q0KG/zc2ev8wL3H/MTBy/zEwcv8vLnD/MC9z/y8tc/8vLnb/LiyF/zc7
+ lP9ERLD/WlHe/11X6v9bXu//VVzz/1xb8f9cW/H/XFvx/1xb8f9cW/H/XFvx/1xb8f9cW/H/XFvx/11b
+ 9P9bW+3/WVr4/1RT9v8JCuT/ERHf/6Sjt//AwMD/zMzM/9TU1P/W1tb/1dXV/9HR0f/Nzc3/y8vL/8bG
+ xv/X19f//////////////////////////////////8////8A////AP///wD///8A////AP///wD///8A
+ ////AP///wD///83////+/////////////////////////////////////////z8/P//////////////
+ //////////////////////////////////////////////////////////////////////////f///+n
+ ////R////wD///8A////AP///9f//////////////////////////////////8PDw+ufn5+Sn5+fPp+f
+ nxEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAMAAAANAAAAHgAAADcAAABXAAAAeGtp2v8YCe3/LjDz/1pi6/9iY+n/Z2H8/15k6/9jZPL/Y2Ty/2Nk
+ 8v9jZPL/Y2Ty/2Nk8v9jZPL/Y2Ty/2Rj7/9iYPb/X2Px/19h7/9lYOX/pajl/+zx8v/58/j/8vT8/+Tl
+ 7/+8vMr/mJen/5GPov+Ni57/jo2d/5ycqv/LytT/8fDs//jz8P/78/r/+Pnw/+767v/T1v//jHv0/29x
+ 9f9hYPL/YmHf/6ap5v/s7vb/+/bz//f09v/t8vX/sq/I/5yZsv+Ni6H/j42h/5KRof+em6r/wb/L/+jm
+ 8v/17vX/9/Py//X17//2+Pn/4OP//62u8v+CgPH/cm/6/2Rn8f9jYOz/Z1/c/8LG7//w8/f/+fT2//Xx
+ 9v/x8u7/mJas/5ORp/+PjaP/joyi/46Mov+Ni6H/jYuh/46Mov+QjaP/kZGh/5OWtf9XV6P/UlDL/15f
+ 7f9gYvD/YmTu/2Jj8f9iY/H/YmPx/2Jj8f9iY/H/YmPx/2Jj8f9iY/H/XGTz/2xj8/9lZ+v/X2Xs/1lb
+ 9f8GAvX/GA/s/6ius//ExMT/zMzM/9PT0//T09P/0dHR/9DQ0P/MzMz/yMjI/8TExP/b29v/////////
+ /////////////////////////7////8A////AP///wD///8A////AP///wD///8A////AP///wf////X
+ ////////////////////////////////////////5ubm/7+/v//c3Nz/8/Pz////////////////////
+ /////////////////////////////////////////////////////////////////////////9////+T
+ ////o////////////////////////////////////////7e3t86fn59zn5+fJ5+fnwkAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAKAAAAFwAA
+ AC0AAABKAAAAa25w3P8TCe//LzHz/2Ro9v9rZ+//a2r2/2Zn9/9oafX/aGn1/2hp9f9oafX/aGn1/2hp
+ 9f9oafX/aGn1/2pq9P9oZ/n/Zmn0/2Rl8f9sZ+j/ra7q/+/09f/69ff/9ff3//f5+v/x8vb/7ez1//Lx
+ +v/y8fr/7+/1//Hx9//y8vL/+/n4//z3+P/48/T/+Pz3/+fw+f+3uPT/jYP1/3V3+f9pZ/b/a2nk/62x
+ 7P/w8vr//vr1//r49//y9/b/8/T+/+3u+P/u7fb/8PD2//Dx9f/w7/P/9PP1//z7/f/49fH/+/r2//n7
+ +//t8P7/yMz1/5qb6/9+ffH/dHH8/2ps9v9oZfD/cmni/8jO8//0+Pn//Pf4//v29//3+fP/9Pb3//Hz
+ 9P/v8fL/7/Hy/+/x8v/v8fL/7/Hy//Dy8//w8Pb/7fD0/9nd9f+AgMb/YF7V/2Zl8f9oafX/Zmjy/2hp
+ 9f9oafX/aGn1/2hp9f9oafX/aGn1/2hp9f9oafX/Ymn2/25m+f9mZ+3/a2z6/19j8v8HCPL/Egvo/6mv
+ uv/Gxsb/zc3N/9PT0//T09P/0dHR/9DQ0P/MzMz/yMjI/8TExP/e3t7/////////////////////////
+ /////////6f///8A////AP///wD///8A////AP///wD///8A////AP///4v/////////////////////
+ ///////////////////4+Pj/vb29/8nJyf/Hx8f/wsLC/8vLy//l5eX/+Pj4////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ /////////////////////////////6amppKfn59Jn5+fE5+fnwMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAGAAAAEQAAACMAAAA9AAAAW3N2
+ 4f0KCen/Mjf4/2po/f95c/r/b27z/21u/P9vb/f/b2/3/29v9/9vb/f/b2/3/29v9/9vb/f/b2/3/3Fw
+ 9f9wb/v/bXD3/25v9f97du//uLn1//L5/P/9+vz/+Pr0//n69v/6+/n/+/v7//v7+//8/Pz/+/v7//j5
+ 9//7/ff/+Pf7//z6///2+Pj/8Pb9/9HU//+cnPD/i4j2/3h69/9wbvb/d3bq/7e49P/z9f////35//38
+ +P/3/fj/+Pz3//n9+P/7/Pj/+/z4//z9+f/9/vr/+fv1//X38f/+//v/9/n6/+vt///S1Pz/qq3x/4yN
+ 7/+Afvn/dXL9/29v9/9xbvP/fnfq/87U9//2+f3/+/n5//v5+f/5/ff/+vr6//n5+f/5+fn/+vr6//v7
+ +//6+vr/+vr6//r6+v/4+/L//f/7/+3x//+Yl9n/cW7h/25u9v9ucPr/bm72/29v9/9vb/f/b2/3/29v
+ 9/9vb/f/b2/3/29v9/9vb/f/a2/2/3Nt//9vcPb/dnD9/2Ro7/8ECu3/EArr/6+zxf/Kysr/z8/P/9TU
+ 1P/T09P/0dHR/9DQ0P/MzMz/yMjI/8TExP/j4+P//////////////////////////////////5v///8A
+ ////AP///wD///8A////AP///wD///8A////N/////v/////////////////////////////////////
+ ///Pz8//wcHB/8jIyP/Kysr/xsbG/8TExP+4uLj/uLi4rP///1H///+z////+///////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////9fX165+fn0afn58bn5+fBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAEAAAACwAAABkAAAAuAAAASXR43O8JC+z/Ky/6/29t
+ //9/evv/dXP1/3V4+P92dvj/dnb4/3Z2+P92dvj/dnb4/3Z2+P92dvj/dnb4/3V38/90dvr/dHb4/3t6
+ +v+Lhvn/vr/8/+3y///49///+vz9//f4/P/3+Pz/9vf7//X1+//29vz/+fn///j4/v/4+///9fP///Tz
+ ///o7P7/z9P2/66u+v+Tkfv/hIT4/3x8+P99efr/iof0/76+/v/t7///+fn///j5/f/1+v3/+vz9//j6
+ +//3+fr/9vf7//f4/P/5+v7/+fn///j4/v/z8///4eL8/8nM+f+vsfj/lJb1/4eH+f+Af/3/d3T5/3d2
+ +/9/ffn/j4n4/8/W/f/y9f//9vX+//f2///2+f3/+Pr6//j6+v/4+vr/+fv7//n7+//4+vr/+Pr6//j6
+ +v/39/f/+Pr7/+zt//+sqfH/hYP0/3h4+v9zdfn/d3b7/3Z2+P92dvj/dnb4/3Z2+P92dvj/dnb4/3Z2
+ +P92dvj/dnj1/3Zz/v93dvz/eHXz/2Bj9P8CBu7/GxL1/7W5y//Nzc3/0dHR/9TU1P/T09P/0dHR/8/P
+ z//MzMz/yMjI/8TExP/m5ub//////////////////////////////////3////8A////AP///wD///8A
+ ////AP///wD///8H////1////////////////////////////////////////+Tk5P+8vLz/ysrK/8rK
+ yv/Gxsb/w8PD/8LCwv+1tbW36urqBgAAAAAAAAAA////F////3f////X////////////////////////
+ ///////////////////////////////////////////////////////////////////+/v790dHRcZ+f
+ nxqfn58GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAABAAAABwAAABEAAAAhAAAAN32EzMYPBvf/GBf2/3F2//98fPL/gYD4/3x/
+ +f99ffn/fX35/319+f99ffn/fX35/319+f99ffn/fX35/36A9v97ffr/enz4/4WE/P+Sj/3/trX9/9TX
+ /f/e3vz/4d/8/+Lg/f/j4f7/5OL//+Ti///j4f7/4+H+/+Ph///d3P7/1tX8/87N9//Cw/X/qqzy/5iX
+ +f+Pjf//gIH7/4GA+P+GhPz/k5H7/7e2///V1v//39/9/9/g+v/e4Pj/4+L8/+Ph/v/j4f7/4+H//+Lf
+ ///f3v7/3Nv9/9nY+v/OzPr/wb/6/62t+/+YmPz/ior8/4KD/f9+fvr/fH33/4B8/f+Ghvz/lJH+/8DG
+ +//a3P7/4d/9/+Hh///e4vv/4uH7/+Lh+//j4vz/4uH7/+Lh+//h4Pr/4eD6/+Hg+v/k4f//3t78/9XS
+ //+qp/z/jov+/36A/P95e/f/f4D6/319+f99ffn/fX35/319+f99ffn/fX35/319+f99ffn/fYHy/3t6
+ +P96ePr/fIDw/09O/P8FBfP/LiTz/7zAy//Q0ND/09PT/9TU1P/S0tL/0dHR/8/Pz//MzMz/yMjI/8TE
+ xP/t7e3//////////////////////////////////3P///8A////AP///wD///8A////AP///wD///+L
+ ////////////////////////////////////////9vb2/76+vv/FxcX/y8vL/83Nzf/Hx8f/wsLC/7S0
+ tMDm5uYJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////N////5v////z////////////////////////
+ ///////////////////////////////////////////////////t7e2nn5+fFp+fnwMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAABAAAABAAAAAoAAAAWAAAAJo6WuowZBvX/DQn1/1pn+f+Eh/r/ior0/4B///+EhPr/hIT6/4SE
+ +v+EhPr/hIT6/4SE+v+EhPr/hIT6/4WG+P+Eg/v/g4L6/4qJ/f+TkP3/o6T8/7O0+P+8vPj/vLv5/7y7
+ +f+8vPj/u7v3/7y8+P+7u/f/urn3/7y7+f++vP7/t7b4/7Gw+P+lpvf/nJv7/5OS//+Hhv7/goP9/4OD
+ +f+Jifv/k5H7/6Si+/+zsvr/urv4/72++P+9vvj/vbz6/7++/P++vfv/vLv7/727/f++vP7/urn9/7Sz
+ 9/+qqPr/pKL8/5mW/f+Li/3/h4b+/4WE/P+Cgvj/hYX5/4WD+/+Ki/v/kY///6is8/+4t/f/vbr4/76+
+ +v+6vvj/vbr//767//++u///vbr//726//+9uv//vbr//726//+7t/7/t7b2/7Ow+P+dm/v/jo3//4aI
+ /v+Dg/f/hoP3/4SE+v+EhPr/hIT6/4SE+v+EhPr/hIT6/4SE+v+EhPr/goXx/4eF/f+Dgf3/e4X7/zEs
+ /f8JBPP/S0fi/8bJzv/S0tL/09PT/9PT0//S0tL/0NDQ/87Ozv/Ly8v/x8fH/8TExP/u7u7/////////
+ /////////////////////////1////8A////AP///wD///8A////AP///zf////7////////////////
+ ////////////////////////y8vL/8bGxv/Ly8v/ysrK/8rKyv/FxcX/tbW1yerq6g8AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8L////X////8P/////////////////////////////
+ //////////////////////////////n5+baurq4Un5+fAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA
+ AAUAAAAMAAAAGD9DSDVJPfH2DQf6/y849P+AhP//joz2/4WE//+Kivz/ior8/4qK/P+Kivz/ior8/4qK
+ /P+Kivz/ior8/4qL+/+Kif3/iYj8/4yN/f+Rkf3/mJf+/5ya+v+jofv/o6P//6Gi/f+hovz/oqP9/6Kk
+ /P+hovz/oaL9/6Gh//+hovr/np37/5mZ/f+Qkfn/jpD8/42N//+Hh/n/jI39/4qK/v+OjP3/lJL8/5iU
+ /f+cm/3/oKH8/6Oj/f+lov7/oqL8/6Oj/f+jov7/oKH8/6Gh//+iov//nqD+/5qc+v+XmP//k5P9/42O
+ /P+Jifv/ion9/4uL/f+Jivr/jI39/4yN/f+OkPz/kI7//5ea9f+gnPv/o576/6Ki/P+eovv/oqP5/6Kj
+ +f+io/n/oaL4/6Kj+f+jpPr/oqP5/6Gi+P+iof//oaH7/5yd9/+Ulf3/jI3//4mN/f+Mi/n/kIr7/4qK
+ /P+Kivz/ior8/4qK/P+Kivz/ior8/4qK/P+Kivz/iIv4/5GK//+Lif//YWn8/xIO+v8UD/T/f4jY/9DN
+ 1v/T09P/09PT/9LS0v/R0dH/0NDQ/87Ozv/Kysr/x8fH/8PDw//39/f/////////////////////////
+ /////////0f///8A////AP///wD///8A////C////9//////////////////////////////////////
+ ///i4uL/vr6+/8jIyP/Nzc3/yMjI/8LCwv+7u7vS2traFgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8n////h////+f/////////////////////////////
+ ///////k+fn5VJ+fnwWfn58CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAIAAAAGAAAADQAA
+ ABd+gOWjCQb2/xAO+v9tcPb/kYv//4yP//+PkP//j5D//4+Q//+PkP//j5D//4+Q//+PkP//j5D//5CO
+ //+Rkf//jo7//4+Q/v+Pkf3/lJL//5GP//+Wk///kZP//42P//+Okf3/kJT9/46S+/+Okf3/kJP//46R
+ /v+Slff/k5H//4+N//+Pkf//jpH+/4+P//+Tkv//kZP3/46P//+Qj/3/lJH+/5OP//+Rjv//kJH//5KR
+ //+UkP//kpX+/5CT/P+Qk/z/kZP//4+S/v+NkPz/jpH9/46U//+MkP//i4///5CS//+PkP7/kZD+/5OS
+ //+Qj/3/jo/9/5CQ/P+Okfr/kI7//5GR+/+Xkf//lpD//5KR//+Pkv//kJL+/5GT//+Rk///kJL+/5CS
+ /v+Rk///kJL+/4+R/f+Qkf//kJT6/5CT9f+QlP3/i4///4yP/P+Sj/z/mJH//4+Q//+PkP//j5D//4+Q
+ //+PkP//j5D//4+Q//+PkP//j5D//5GH//+Kivz/O0Hu/wMC/P8nIvr/rsTd/9XO2//T09P/09PT/9LS
+ 0v/R0dH/0NDQ/87Ozv/Kysr/xsbG/8PDw//5+fn//////////////////////////////////z////8A
+ ////AP///wD///8A////k/////////////////////////////////////////b29v+/v7//xcXF/8vL
+ y//Nzc3/xsbG/8DAwNvV1dUZAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wP///8v////a////5////+T////b////0f///8PAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAEAAAACAAAABgAAAAxrbHkmRUD35woG
+ //8gGPn/dn///4mY//+Zmvz/mJb//5aS//+Vlf//lpz7/5Wd9/+SmPv/k5b//5aW//+Vlf//lZX//5WV
+ //+Vlf//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW
+ //+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW
+ //+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5aW
+ //+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lZX//5WV//+Wlv//lpb//5aW//+Wlv//lpb//5aW
+ //+Wlv//lpb//5aW//+Wlv//lpb//5aW//+Wlv//lpb//5mW//+YmPz/mJr4/5qZ+/+alf//m5P//5uW
+ //+cm/n/kZf//4GO+P9GSP//BAD9/xgW8v99heL/zNHU/+HT2f/U1NT/09PT/9LS0v/R0dH/0NDQ/83N
+ zf/Jycn/xsbG/8LCwv///////////////////////////////////////x////8A////AP///wD///8/
+ /////////////////////////////////////////////8vLy//ExMT/ycnJ/87Ozv/BwcH/xMTE5NjY
+ 2B8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAgAAAAUAAAAKsbTeVjMs8fwDCfz/Ewv//2Fa
+ //+RkP7/mZv//5ug+/+anfj/nZz+/6Gd//+hnf//oJ3//5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f
+ /f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f
+ /f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f
+ /f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/6Cg/v+goP7/oKD+/6Cg
+ /v+goP7/oKD+/6Cg/v+goP7/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f/f+fn/3/n5/9/5+f
+ /f+fn/3/n5/9/5+f/f+fn/3/n5/9/5yh9v+eoP7/np3//5uc//+anf//mJ79/5ed/v+Umf//c3T//yYg
+ //8DAP7/Fwz2/2pj6f/Dydz/1dnU/9PX0v/U1NT/09PT/9LS0v/Q0ND/z8/P/8zMzP/IyMj/xcXF/8TE
+ xP///////////////////////////////////////xf///8A////AP///wv////f////////////////
+ ////////////////////////4uLi/7+/v//Jycn/y8vL/8PDw//Ly8vq1tbWJQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAEAAAADAAAABrO48GwzMPf8Dgv1/xgE//8wJff/UU3//3R5
+ //+Jkf//lJb//5yX//+imP//pZr//56b/v+em/7/npv+/56b/v+em/7/n5z//5+c//+em/7/npv+/56b
+ /v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b
+ /v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b
+ /v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b
+ /v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b/v+em/7/npv+/56b
+ /v+em/7/npv+/56d+/+dm///mpn//5ia//+Ul///hoT//2pe/v9QPfj/EAX//woH9v8hF/f/enbn/8XJ
+ 2//R1Nj/09fR/9PR0f/T09P/0tLS/9HR0f/Pz8//zc3N/8rKyv/Hx8f/xcXF/8jIyP//////////////
+ /////////////////////////wD///8A////AP///5P/////////////////////////////////////
+ ///29vb/vr6+/8fHx//Jycn/x8fH/8bGxu3X19cuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAALQ0/RFcGr+5RoX7/8PDPz/Cwf6/woF+/8KB/3/CQn9/wgK
+ +P8GC/T/Bw30/wQI+/8FCfz/BQn8/wQI+/8DB/r/BQn8/wYK/f8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ
+ /P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ
+ /P8FCfz/BQn8/wUJ/P8FCfz/Bgr9/wYK/f8GCv3/Bgr9/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ
+ /P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wQI+/8ECPv/BAj7/wQI+/8ECPv/BAj7/wQI+/8ECPv/BQn8/wUJ
+ /P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/wUJ/P8FCfz/BQn8/woF
+ //8JB///CQj+/wcJ+/8HCfv/Bgr9/wQK/f8CCPv/Dw3z/z496/+dpt//z9PY/9PS1v/Q19L/zs3W/93V
+ 3P/T09P/0tLS/9DQ0P/Ozs7/zMzM/8nJyf/Gxsb/xMTE/8LCwv//////////////////////////////
+ /////////yP///8A////U//////////////////////////////////////////////Kysr/xMTE/8rK
+ yv/IyMj/x8fH89ra2jcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAA8vP/D7/K/WpsdP/PTEz8/ywj9v8dD/v/FQz9/xEM+/8ODff/DQ74/w8K
+ //8QC///Eg3//w4J/v8LBvv/Dwr//xEM//8LBvv/Dgn+/w4J/v8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w4J
+ /v8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w4J
+ /v8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w4J/v8OCf7/DQj9/w0I/f8PCv//Dwr//w8K//8PCv//Dwr//w8K
+ //8PCv//Dwr//w8K//8PCv//Dwr//w8K//8PCv//Dwr//w8K//8PCv//Dwr//w8K//8PCv//Dwr//w8K
+ //8OCf7/Dgn+/w4J/v8PCv//Dwr//w8K//8OCf7/Dgn+/w4J/v8OCf7/Dgn+/w8I/f8RC/z/Ew38/xAJ
+ +v8RCPj/Gxb1/y0x9P8/S/f/h4vq/7XB3f/Q19r/09TY/9jT1P/Y0tP/1NLR/8rR1P/S0tL/0dHR/8/P
+ z//Nzc3/y8vL/8jIyP/FxcX/wsLC/729vf/+/v7//////////////////////////////////9f///+n
+ ////+////////////////////////////////////////97e3v/AwMD/yMjI/8jIyP/MzMz21NTUQAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAOrz/yHr8v8z6/L/M+7z/zPl6fU1xsbSPpqcpk12d39hV1hefUJD
+ SJl7fYfPztHg/+Dj8v/f4vH/1Nfm/9TX5v/U1+b/1Nfm/9TX5v/U1+b/1Nfm/9TX5v/U1+b/1Nfm/9TX
+ 5v/U1+b/1Nfm/9TX5v/U1+b/1Nfm/9PW5f/T1uX/09bl/9PW5f/T1uX/09bl/9PW5f/T1uX/0tXk/9LV
+ 5P/S1eT/0tXk/9LV5P/R1OP/0dTj/9HU4//P0uH/z9Lh/8/S4f/P0uH/z9Lh/8/S4f/P0uH/z9Lh/87R
+ 4P/O0eD/ztHg/87R4P/O0eD/ztHg/87R4P/O0eD/zdDf/83Q3//Mz97/zM/e/8zP3v/Mz97/zM/e/8vO
+ 3f/Lzt3/y87d/8vO3f/Lzt3/y87d/8rN3P/Kzdz/ys3c/8TP1//Dztb/xc7X/8rQ2//Nzd3/y8nc/87K
+ 3f/Qzd3/1NnY/9nT2P/a1tX/09fR/9PT0//c19T/2drR/8bP0v/R0dH/0NDQ/87Ozv/MzMz/ysrK/8bG
+ xv/Dw8P/wMDA/7u7u//x8fH/////////////////////////////////////////////////////////
+ ////////////////////////9fX1/76+vv/FxcX/xsbG/8nJyfnX19dMAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9sbWvE3d7c//Hy
+ 8P/r7Or/4uPh/+Lj4f/i4+H/4uPh/+Lj4f/i4+H/4uPh/+Lj4f/h4uD/4eLg/+Hi4P/h4uD/4eLg/+Hi
+ 4P/h4uD/4eLg/+Dh3//g4d//4OHf/+Dh3//g4d//4OHf/+Dh3//g4d//4OHf/+Dh3//g4d//4OHf/9/g
+ 3v/f4N7/3+De/9/g3v/f4N7/3+De/9/g3v/f4N7/3+De/9/g3v/f4N7/3+De/93e3P/d3tz/3d7c/93e
+ 3P/d3tz/3d7c/93e3P/d3tz/29za/9vc2v/b3Nr/29za/9rb2f/a29n/2tvZ/9rb2f/Z2tj/2drY/9na
+ 2P/Y2df/2NnX/9jZ1//Y2df/2NnX/9Xa2f/T19j/0tXZ/9TW1//U19X/1tfT/9fY1v/b2Nr/1dLU/9zT
+ 1v/e1dL/1tfO/9Hbzv/N09L/zcnU/9nW0v/Pz8//zs7O/83Nzf/Ly8v/ycnJ/8XFxf/BwcH/vr6+/7i4
+ uP/R0dH/////////////////////////////////////////////////////////////////////////
+ ////////y8vL/8XFxf/Hx8f/ysrK/NbW1lUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9qamrE3d3d//Pz8//q6ur/4uLi/+Li
+ 4v/i4uL/4uLi/+Li4v/i4uL/4uLi/+Li4v/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Dg
+ 4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4eHh/+Dg4P/g4OD/4ODg/+Dg4P/f39//39/f/9/f
+ 3//d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc
+ 3P/c3Nz/29vb/9vb2//a2tr/2tra/9ra2v/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9jY2P/Y2Nj/2NjY/9jY
+ 2P/X19f/19fX/9vW1//b1tj/29Xa/9nW2P/Y1tb/1dbU/9TV0f/T1c//1tnQ/9XZ1P/T0df/1s7Z/9DR
+ 2//K1NT/0dbN/9vOzP/Ozs7/zc3N/8zMzP/Kysr/yMjI/8TExP/AwMD/vb29/7a2tv+0tLT/9PT0////
+ ///////////////////////////////////////////////////////////////////j4+P/xMTE/8fH
+ x//Hx8f80dHRXgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9ra2vE3d3d//Dw8P/q6ur/4uLi/+Li4v/h4eH/4eHh/+Hh
+ 4f/h4eH/4eHh/+Hh4f/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg
+ 4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/f39//39/f/9/f3//f39//3t7e/97e3v/e3t7/3t7e/93d
+ 3f/d3d3/3d3d/93d3f/d3d3/3d3d/9zc3P/c3Nz/3Nzc/9zc3P/b29v/29vb/9vb2//b29v/2tra/9ra
+ 2v/a2tr/2tra/9ra2v/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Y2Nj/2NjY/9fX
+ 1//X19f/19fX/9bW1v/W1tb/1tbW/9XV1f/V1dX/1dXV/9TU1P/T09P/09PT/9PT0//S0tL/0dHR/9DQ
+ 0P/Pz8//zc3N/8rKyv/IyMj/xcXF/8HBwf+9vb3/urq6/7S0tP+xsbH/xMTE//z8/P//////////////
+ /////////////////////////////////////////////+rq6v/Hx8f/ycnJ/8rKyv/Ozs5kAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAA
+ ACAAAAA6AAAAXAAAAH9ra2vE3d3d//Dw8P/q6ur/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Hh
+ 4f/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg
+ 4P/g4OD/39/f/9/f3//f39//3t7e/97e3v/e3t7/3t7e/97e3v/d3d3/3d3d/93d3f/d3d3/3d3d/93d
+ 3f/d3d3/3d3d/9zc3P/c3Nz/3Nzc/9vb2//b29v/29vb/9vb2//b29v/2tra/9ra2v/a2tr/2tra/9ra
+ 2v/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2dnZ/9jY2P/Y2Nj/19fX/9fX1//W1tb/1tbW/9bW
+ 1v/V1dX/1dXV/9XV1f/V1dX/1NTU/9PT0//T09P/0tLS/9LS0v/R0dH/0NDQ/8/Pz//Ozs7/zMzM/8nJ
+ yf/Gxsb/w8PD/7+/v/+7u7v/uLi4/7Kysv+urq7/qamp/8rKyv/8/Pz/////////////////////////
+ ////////////////////////7e3t/8bGxv/Gxsb/ysrK/8nJyWoAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAA
+ AH9ra2vE3d3d//Dw8P/q6ur/4eHh/+Hh4f/h4eH/4eHh/+Hh4f/h4eH/4eHh/+Dg4P/g4OD/4ODg/+Dg
+ 4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3t7e/97e
+ 3v/e3t7/3t7e/97e3v/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/c3Nz/3Nzc/9zc
+ 3P/b29v/29vb/9vb2//b29v/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/Z2dn/2dnZ/9nZ
+ 2f/Z2dn/2dnZ/9nZ2f/Z2dn/2NjY/9fX1//X19f/1tbW/9bW1v/W1tb/1tbW/9XV1f/V1dX/1NTU/9TU
+ 1P/U1NT/09PT/9LS0v/S0tL/0dHR/9DQ0P/Pz8//zs7O/83Nzf/MzMz/ysrK/8fHx//ExMT/wcHB/729
+ vf+4uLj/tbW1/6+vr/+rq6v/p6en/76+vv/i4uL/8/Pz//39/f////////////////////////////z8
+ /P/t7e3/ycnJ/8jIyP/Gxsb/xsbGcwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9qamrE3d3d//Dw
+ 8P/p6en/4eHh/+Hh4f/h4eH/4eHh/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg
+ 4P/g4OD/4ODg/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3t7e/97e3v/e3t7/3d3d/93d
+ 3f/d3d3/3d3d/93d3f/c3Nz/3Nzc/93d3f/d3d3/3Nzc/9zc3P/c3Nz/3Nzc/9vb2//b29v/29vb/9vb
+ 2//b29v/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/Z2dn/2dnZ/9jY2P/Y2Nj/2NjY/9jY
+ 2P/Y2Nj/19fX/9fX1//W1tb/1tbW/9bW1v/V1dX/1dXV/9XV1f/U1NT/1NTU/9PT0//T09P/0tLS/9HR
+ 0f/Q0ND/0NDQ/8/Pz//Ozs7/zMzM/8vLy//Kysr/yMjI/8XFxf/CwsL/vr6+/7q6uv+1tbX/srKy/62t
+ rf+np6f/pqam/8HBwf/b29v/19fX/9fX1//e3t7/5+fn/+Xl5f/b29v/0NDQ/8rKyv/Kysr/yMjI/8LC
+ wv/Kysp5AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9qamrE3Nzc/+/v7//p6en/4ODg/+Dg
+ 4P/g4OD/4ODg/+Dg4P/g4OD/4ODg/+Dg4P/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f
+ 3//f39//39/f/9/f3//f39//3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3d3d/93d3f/d3d3/3d3d/9zc
+ 3P/c3Nz/3Nzc/9zc3P/c3Nz/29vb/9vb2//c3Nz/3Nzc/9vb2//b29v/29vb/9vb2//a2tr/2tra/9ra
+ 2v/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ2f/Z2dn/2NjY/9jY2P/X19f/19fX/9fX1//X19f/19fX/9fX
+ 1//W1tb/1tbW/9XV1f/V1dX/1dXV/9TU1P/T09P/09PT/9PT0//S0tL/0dHR/9DQ0P/Pz8//zs7O/83N
+ zf/MzMz/y8vL/8rKyv/IyMj/xsbG/8LCwv+/v7//vLy8/7i4uP+zs7P/sLCw/6urq/+lpaX/paWl/8TE
+ xP/W1tb/09PT/9HR0f/Pz8//zc3N/83Nzf/Gxsb/yMjI/8rKyv/ExMT/xMTE/8rKyoEAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9qamrE3Nzc/+/v7//p6en/4ODg/+Dg4P/g4OD/4ODg/+Dg
+ 4P/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f
+ 3//e3t7/3t7e/97e3v/e3t7/3t7e/93d3f/d3d3/3d3d/93d3f/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9vb
+ 2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/2tra/9ra2v/a2tr/2tra/9nZ2f/Z2dn/2NjY/9nZ
+ 2f/Z2dn/2dnZ/9jY2P/Y2Nj/19fX/9fX1//W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1dXV/9XV
+ 1f/U1NT/1NTU/9PT0//T09P/0tLS/9HR0f/R0dH/0NDQ/8/Pz//Ozs7/zc3N/8zMzP/Kysr/ycnJ/8jI
+ yP/FxcX/w8PD/8DAwP+9vb3/ubm5/7W1tf+wsLD/ra2t/6mpqf+jo6P/pqam/8fHx//R0dH/zs7O/83N
+ zf/Ly8v/y8vL/8fHx//Jycn/xcXF/8LCwv/BwcH/ysrKhwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAA
+ ACAAAAA6AAAAXAAAAH9qamrE3Nzc/+/v7//o6Oj/4ODg/+Dg4P/g4OD/39/f/9/f3//f39//39/f/9/f
+ 3//f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//f39//3t7e/97e3v/e3t7/3t7e/93d
+ 3f/d3d3/3d3d/93d3f/d3d3/3Nzc/9zc3P/c3Nz/3Nzc/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb
+ 2//b29v/29vb/9ra2v/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY
+ 2P/X19f/19fX/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9XV1f/V1dX/1dXV/9PT0//T09P/09PT/9LS
+ 0v/R0dH/0dHR/9DQ0P/Q0ND/zs7O/83Nzf/MzMz/y8vL/8rKyv/IyMj/x8fH/8bGxv/CwsL/wMDA/729
+ vf+6urr/tra2/7Kysv+urq7/qqqq/6ampv+ioqL/p6en/8nJyf/Nzc3/y8vL/8rKyv/Hx8f/xMTE/8nJ
+ yf/ExMT/xMTE/8LCwv/JycmQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAA
+ AH9qamrE3Nzc/+/v7//o6Oj/4ODg/+Dg4P/f39//39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f
+ 3//f39//39/f/9/f3//f39//39/f/97e3v/e3t7/3t7e/97e3v/d3d3/3d3d/93d3f/d3d3/3Nzc/9zc
+ 3P/c3Nz/3Nzc/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//a2tr/2tra/9nZ
+ 2f/Z2dn/2dnZ/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/19fX/9fX1//Y2Nj/2NjY/9fX1//X19f/1tbW/9bW
+ 1v/W1tb/1tbW/9bW1v/W1tb/1dXV/9XV1f/U1NT/1NTU/9PT0//S0tL/0tLS/9HR0f/Q0ND/0NDQ/8/P
+ z//Pz8//zc3N/8zMzP/Ly8v/ysrK/8nJyf/Hx8f/xcXF/8TExP/AwMD/vb29/7q6uv+3t7f/tLS0/7Cw
+ sP+srKz/qKio/6SkpP+hoaH/p6en/8vLy//Ly8v/ycnJ/8jIyP/ExMT/wsLC/8DAwP/CwsL/vb29/8bG
+ xpYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9qamrE29vb/+/v
+ 7//o6Oj/39/f/9/f3//f39//39/f/9/f3//f39//39/f/9/f3//e3t7/3t7e/97e3v/e3t7/3d3d/93d
+ 3f/d3d3/3d3d/93d3f/d3d3/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/29vb/9vb
+ 2//a2tr/2tra/9ra2v/a2tr/2tra/9ra2v/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9fX1//X19f/19fX/9fX
+ 1//Y2Nj/2NjY/9jY2P/Y2Nj/19fX/9fX1//X19f/1tbW/9bW1v/W1tb/1tbW/9XV1f/W1tb/1dXV/9XV
+ 1f/U1NT/09PT/9LS0v/S0tL/0dHR/9HR0f/R0dH/0NDQ/9DQ0P/Pz8//zs7O/83Nzf/MzMz/zMzM/8vL
+ y//Jycn/x8fH/8bGxv/ExMT/wcHB/7+/v/+9vb3/urq6/7e3t/+0tLT/r6+v/6ysrP+pqan/pqam/56e
+ nv+ioqL/uLi4/8LCwv/FxcX/xMTE/8TExP/AwMD/v7+//7+/v/+9vb3/yMjInwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9qamrE2tra/+/v7//n5+f/39/f/9/f
+ 3//f39//3t7e/97e3v/e3t7/3t7e/97e3v/e3t7/3t7e/97e3v/d3d3/3d3d/93d3f/d3d3/3d3d/93d
+ 3f/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9vb2//b29v/29vb/9vb2//b29v/2tra/9ra2v/a2tr/2dnZ/9nZ
+ 2f/Z2dn/2dnZ/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9fX1//X19f/19fX/9fX1//X19f/19fX/9fX
+ 1//X19f/1tbW/9bW1v/W1tb/1dXV/9XV1f/V1dX/1dXV/9XV1f/V1dX/1NTU/9TU1P/T09P/0tLS/9LS
+ 0v/R0dH/0dHR/9DQ0P/Q0ND/z8/P/87Ozv/Ozs7/zc3N/8zMzP/Ly8v/ysrK/8nJyf/Hx8f/xcXF/8TE
+ xP/CwsL/v7+//76+vv+6urr/t7e3/7S0tP+ysrL/rq6u/6urq/+np6f/oqKi/5+fn/+fn5//t7e3/8XF
+ xf/ExMT/v7+//8DAwP+8vLz/v7+//7q6uv/BwcGl5eXlAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAADAAAADgAAACAAAAA6AAAAXAAAAH9ra2vE29vb/+7u7v/n5+f/3t7e/97e3v/e3t7/3t7e/97e
+ 3v/d3d3/3d3d/93d3f/e3t7/3d3d/93d3f/d3d3/3d3d/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9zc
+ 3P/b29v/29vb/9vb2//b29v/2tra/9ra2v/Z2dn/2dnZ/9nZ2f/Y2Nj/2NjY/9jY2P/X19f/19fX/9fX
+ 1//X19f/19fX/9fX1//W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9bW1v/W1tb/1NTU/9TU
+ 1P/U1NT/1NTU/9TU1P/T09P/09PT/9PT0//T09P/09PT/9LS0v/S0tL/0dHR/9DQ0P/Q0ND/0NDQ/8/P
+ z//Ozs7/zc3N/83Nzf/MzMz/y8vL/8rKyv/Jycn/yMjI/8bGxv/ExMT/w8PD/8HBwf+/v7//vb29/7u7
+ u/+4uLj/tbW1/7Kysv+urq7/qqqq/6ioqP+kpKT/n5+f/5ycnP+kpKT/u7u7/8LCwv+9vb3/urq6/729
+ vf+5ubn/uLi4/8DAwKvi4uIDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAA
+ ACAAAAA6AAAAXAAAAH9tbW3E3Nzc/+7u7v/o6Oj/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d
+ 3f/d3d3/3d3d/93d3f/d3d3/3Nzc/9zc3P/c3Nz/29vb/9vb2//b29v/29vb/9vb2//a2tr/2tra/9ra
+ 2v/Z2dn/2dnZ/9jY2P/Y2Nj/2NjY/9fX1//X19f/19fX/9bW1v/W1tb/1tbW/9bW1v/W1tb/1tbW/9XV
+ 1f/V1dX/1dXV/9TU1P/U1NT/1NTU/9TU1P/U1NT/1NTU/9TU1P/U1NT/09PT/9LS0v/S0tL/0tLS/9LS
+ 0v/S0tL/0dHR/9HR0f/R0dH/0NDQ/9DQ0P/Q0ND/z8/P/8/Pz//Ozs7/zs7O/83Nzf/Nzc3/zMzM/8vL
+ y//Kysr/ycnJ/8jIyP/Hx8f/xcXF/8TExP/CwsL/wMDA/76+vv+8vLz/ubm5/7i4uP+0tLT/s7Oz/7Cw
+ sP+rq6v/p6en/6SkpP+ioqL/n5+f/5qamv+wsLD/vr6+/7q6uv+4uLj/urq6/7i4uP+1tbX/vLy8seLi
+ 4gYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADgAAACAAAAA6AAAAXAAA
+ AH9ubm7E3d3d/+7u7v/n5+f/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d3f/d3d3/3d3d/93d
+ 3f/c3Nz/3Nzc/9vb2//b29v/29vb/9ra2v/a2tr/2tra/9nZ2f/Z2dn/2NjY/9jY2P/Y2Nj/19fX/9fX
+ 1//X19f/1tbW/9bW1v/W1tb/1dXV/9XV1f/V1dX/1dXV/9XV1f/V1dX/1dXV/9TU1P/U1NT/1NTU/9PT
+ 0//T09P/09PT/9PT0//T09P/0tLS/9LS0v/S0tL/0dHR/9HR0f/R0dH/0dHR/9HR0f/Q0ND/0NDQ/9DQ
+ 0P/Pz8//z8/P/8/Pz//Ozs7/zs7O/83Nzf/Nzc3/zc3N/8vLy//Ly8v/ysrK/8nJyf/IyMj/x8fH/8XF
+ xf/ExMT/wsLC/8HBwf+/v7//vb29/7u7u/+5ubn/tra2/7S0tP+wsLD/r6+v/6ysrP+oqKj/paWl/6Ki
+ ov+fn5//nZ2d/56env+2trb/ubm5/7S0tP+4uLj/tra2/7Kysv+8vLy33d3dBgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADQAAAB8AAAA4AAAAWAAAAHpxcXHA39/f/+3t
+ 7f/m5ub/3d3d/93d3f/d3d3/3Nzc/9zc3P/c3Nz/3Nzc/9zc3P/c3Nz/3Nzc/9vb2//b29v/2tra/9ra
+ 2v/a2tr/2dnZ/9jY2P/Y2Nj/2NjY/9fX1//X19f/1tbW/9bW1v/W1tb/1dXV/9XV1f/V1dX/1dXV/9TU
+ 1P/U1NT/1NTU/9PT0//T09P/09PT/9PT0//T09P/09PT/9PT0//T09P/09PT/9LS0v/S0tL/0tLS/9LS
+ 0v/R0dH/0dHR/9HR0f/R0dH/0NDQ/9DQ0P/Q0ND/0NDQ/8/Pz//Pz8//z8/P/8/Pz//Ozs7/zs7O/83N
+ zf/Nzc3/zMzM/8vLy//Ly8v/y8vL/8nJyf/IyMj/x8fH/8bGxv/FxcX/xMTE/8LCwv/BwcH/v7+//729
+ vf+7u7v/ubm5/7e3t/+1tbX/srKy/7Gxsf+vr6//rKys/6enp/+lpaX/pKSk/5+fn/+ampr/mJiY/6io
+ qP+3t7f/tLS0/7S0tP+zs7P/rq6u/7m5ub3Z2dkJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAAAADAAAABwAAAA0AAAAUQAAAHB5eXm54eHh/+3t7f/k5OT/3Nzc/9zc
+ 3P/c3Nz/3Nzc/9zc3P/b29v/29vb/9vb2//b29v/2tra/9ra2v/a2tr/2dnZ/9jY2P/Y2Nj/2NjY/9fX
+ 1//X19f/1tbW/9bW1v/V1dX/1dXV/9TU1P/U1NT/1NTU/9PT0//T09P/09PT/9LS0v/S0tL/0tLS/9LS
+ 0v/R0dH/0dHR/9HR0f/R0dH/0dHR/9HR0f/R0dH/0dHR/9DQ0P/Q0ND/0NDQ/9DQ0P/Pz8//z8/P/8/P
+ z//Pz8//zs7O/87Ozv/Ozs7/zs7O/83Nzf/Nzc3/zc3N/83Nzf/MzMz/y8vL/8vLy//Kysr/ycnJ/8nJ
+ yf/IyMj/yMjI/8bGxv/FxcX/xMTE/8PDw//CwsL/wMDA/76+vv+9vb3/u7u7/7q6uv+3t7f/tbW1/7S0
+ tP+xsbH/r6+v/62trf+srKz/qKio/6SkpP+ioqL/oKCg/5qamv+ZmZn/nZ2d/6+vr/+0tLT/sbGx/7Ky
+ sv+vr6//urq6w9fX1wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAACAAAACgAAABkAAAAsAAAARgAAAGGDg4Ou5OTk/+3t7f/k5OT/29vb/9vb2//b29v/29vb/9vb
+ 2//b29v/29vb/9vb2//a2tr/2dnZ/9nZ2f/Y2Nj/2NjY/9fX1//X19f/19fX/9bW1v/W1tb/1dXV/9XV
+ 1f/U1NT/1NTU/9PT0//T09P/0tLS/9LS0v/S0tL/0tLS/9HR0f/R0dH/0NDQ/9DQ0P/Q0ND/0NDQ/9DQ
+ 0P/Pz8//z8/P/8/Pz//Pz8//z8/P/8/Pz//Pz8//zs7O/87Ozv/Ozs7/zc3N/83Nzf/Nzc3/zMzM/8zM
+ zP/MzMz/y8vL/8vLy//Ly8v/y8vL/8vLy//Jycn/ycnJ/8jIyP/IyMj/x8fH/8bGxv/FxcX/xcXF/8PD
+ w//Dw8P/wsLC/8DAwP+/v7//vr6+/7y8vP+7u7v/ubm5/7e3t/+1tbX/s7Oz/7Gxsf+vr6//rKys/6qq
+ qv+lpaX/o6Oj/6Ghof+fn5//m5ub/5eXl/+dnZ3/qqqq/7Kysv+xsbH/rq6u/66urv+xsbHJ1NTUDAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAACAAA
+ ABMAAAAjAAAANwAAAEyVlZWg5ubm/+7u7v/i4uL/2tra/9ra2v/a2tr/2dnZ/9nZ2f/Z2dn/2dnZ/9nZ
+ 2f/X19f/19fX/9fX1//W1tb/1tbW/9bW1v/V1dX/1dXV/9TU1P/U1NT/1NTU/9PT0//S0tL/0dHR/9HR
+ 0f/R0dH/0NDQ/9DQ0P/Q0ND/z8/P/87Ozv/Ozs7/zc3N/83Nzf/Ozs7/zc3N/83Nzf/Nzc3/zc3N/83N
+ zf/Nzc3/zc3N/8vLy//Ly8v/y8vL/8vLy//Ly8v/ysrK/8rKyv/Kysr/ysrK/8nJyf/Jycn/yMjI/8jI
+ yP/Hx8f/x8fH/8bGxv/Gxsb/xsbG/8XFxf/ExMT/w8PD/8PDw//CwsL/wsLC/8DAwP+/v7//vr6+/729
+ vf+7u7v/urq6/7m5uf+4uLj/tLS0/7Kysv+ysrL/sbGx/66urv+qqqr/p6en/6enp/+lpaX/oqKi/52d
+ nf+cnJz/mJiY/5qamv+np6f/rq6u/7Kysv+urq7/qqqq/7a2tszV1dUPAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAABQAAAA0AAAAXAAAAJQAA
+ ADOurq6N6enp/+3t7f/k5OT/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/Y2Nj/2NjY/9jY2P/X19f/19fX/9bW
+ 1v/W1tb/1dXV/9XV1f/U1NT/1NTU/9PT0//T09P/09PT/9LS0v/R0dH/0NDQ/9DQ0P/Pz8//z8/P/8/P
+ z//Ozs7/zs7O/83Nzf/MzMz/zMzM/8zMzP/Ly8v/y8vL/8vLy//Ly8v/y8vL/8vLy//Kysr/ysrK/8nJ
+ yf/Jycn/ycnJ/8nJyf/Jycn/ycnJ/8nJyf/Jycn/ycnJ/8nJyf/IyMj/yMjI/8fHx//Gxsb/xsbG/8XF
+ xf/Dw8P/w8PD/8LCwv/CwsL/wcHB/8DAwP/AwMD/wMDA/7y8vP+7u7v/urq6/7m5uf+3t7f/tra2/7S0
+ tP+zs7P/sbGx/7CwsP+urq7/q6ur/6mpqf+np6f/paWl/6Kiov+fn5//n5+f/5mZmf+ampr/mZmZ/52d
+ nf+srKz/sLCw/6mpqf+pqan/vb29z+Hh4RIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABAAAAAwAAAAcAAAAOAAAAFgAAAB/Hx8d/6urq/+rq
+ 6v/l5eX/19fX/9fX1//X19f/19fX/9fX1//X19f/1tbW/9bW1v/V1dX/1dXV/9XV1f/U1NT/09PT/9PT
+ 0//T09P/0tLS/9LS0v/R0dH/0dHR/9DQ0P/Pz8//zs7O/87Ozv/Nzc3/zc3N/83Nzf/MzMz/y8vL/8vL
+ y//Kysr/ysrK/8nJyf/Ly8v/y8vL/8vLy//Kysr/ysrK/8rKyv/Jycn/ycnJ/8nJyf/Jycn/ycnJ/8nJ
+ yf/IyMj/yMjI/8jIyP/Hx8f/x8fH/8bGxv/Gxsb/xcXF/8TExP/Dw8P/wsLC/8LCwv/CwsL/wcHB/8DA
+ wP+/v7//vr6+/729vf+9vb3/vLy8/7u7u/+6urr/uLi4/7e3t/+1tbX/s7Oz/7Kysv+xsbH/ra2t/62t
+ rf+rq6v/qKio/6enp/+np6f/paWl/6Ghof+goKD/l5eX/5mZmf+YmJj/oqKi/7Gxsf+urq7/r6+v/7Oz
+ s/zR0dGH8fHxCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAABAAAAAQAAAAQAAAAHAAAACwAAAA/g4OB07u7u/+vr6//r6+v/6Ojo/+jo
+ 6P/n5+f/5+fn/+fn5//n5+f/5+fn/+fn5//o6Oj/5+fn/+fn5//m5ub/5ubm/+Xl5f/l5eX/5OTk/+Tk
+ 5P/k5OT/4+Pj/+Li4v/h4eH/4eHh/+Dg4P/g4OD/4ODg/+Dg4P/f39//3t7e/97e3v/d3d3/3d3d/9zc
+ 3P/a2tr/2tra/9ra2v/a2tr/2dnZ/9nZ2f/Y2Nj/2NjY/9fX1//X19f/1tbW/9XV1f/U1NT/09PT/9PT
+ 0//S0tL/0NDQ/8/Pz//Ozs7/zc3N/8zMzP/Kysr/ysrK/8nJyf/Hx8f/xsbG/8XFxf/ExMT/wsLC/8HB
+ wf+/v7//v7+//76+vv+9vb3/u7u7/7m5uf+4uLj/tra2/7W1tf+0tLT/sLCw/6+vr/+tra3/q6ur/6io
+ qP+mpqb/o6Oj/6CgoP+goKD/nZ2d/5+fn/+srKz/srKy/7Gxsf+4uLj8v7+/qPDw8DMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAQAAAAEAAAACAAAABAAAAAXw8PBt7u7u/+np6f/q6ur/7e3t/+3t7f/s7Oz/7Ozs/+zs
+ 7P/s7Oz/7Ozs/+zs7P/r6+v/6+vr/+vr6//q6ur/6urq/+np6f/p6en/6enp/+jo6P/o6Oj/6Ojo/+fn
+ 5//m5ub/5ubm/+Xl5f/l5eX/5eXl/+Xl5f/l5eX/5OTk/+Tk5P/j4+P/4+Pj/+Pj4//h4eH/4eHh/+Hh
+ 4f/g4OD/4ODg/9/f3//f39//39/f/9ra2v/a2tr/2dnZ/9jY2P/X19f/1tbW/9XV1f/V1dX/0tLS/9LS
+ 0v/R0dH/z8/P/87Ozv/Nzc3/zMzM/8vLy//IyMj/yMjI/8fHx//FxcX/xMTE/8LCwv/BwcH/wcHB/76+
+ vv+9vb3/u7u7/7q6uv+5ubn/t7e3/7a2tv+1tbX/sbGx/6+vr/+tra3/ra2t/6qqqv+mpqb/pqam/6io
+ qP+ioqL/qKio/7a2tv+2trb/zc3N2PPz84H5+fkYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD8/Pxp8/Pz/+zs7P/t7e3/7Ozs/+zs7P/s7Oz/7Ozs/+vr6//r6+v/6+vr/+vr
+ 6//q6ur/6urq/+rq6v/p6en/6enp/+np6f/o6Oj/6Ojo/+jo6P/o6Oj/6Ojo/+fn5//n5+f/5+fn/+bm
+ 5v/m5ub/5+fn/+bm5v/m5ub/5ubm/+bm5v/m5ub/5eXl/+Xl5f/k5OT/5OTk/+Tk5P/j4+P/4+Pj/+Pj
+ 4//i4uL/4uLi/+Pj4//j4+P/4uLi/+Li4v/i4uL/4eHh/+Hh4f/h4eH/4ODg/9/f3//f39//3t7e/9zc
+ 3P/b29v/29vb/9ra2v/b29v/29vb/9ra2v/a2tr/2dnZ/9nZ2f/Y2Nj/2NjY/9fX1//W1tb/1dXV/9TU
+ 1P/U1NT/09PT/9LS0v/R0dH/z8/P/8zMzP/Ly8v/zc3N/8zMzP/Kysr/zs7O89TU1Mzm5ua98vLylvf3
+ 91f8/PwYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD/////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////////////////////////////////////////////
+ ////////////////////////////////////////+AAAAAAAAAAAAAAAAAAAAAH/////////8AAAAAAA
+ AAAAAAAAAAAAAAD/////////4AAAAAAAAAAAAAAAAAAAAAD/////////4AAAAAAAAAAAAAAAAAAAAAD/
+ ////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAA
+ AAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf
+ ////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAA
+ AAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf
+ ////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAA
+ AAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAf////////4AAAAAAAAAAAAAAAAAAAAAAP
+ ////////4AAAAAAAAAAAAAAAAAAAAAAP////////4AAAAAAAAAAAAAAAAAAAAAAP////////4AAAAAAA
+ AAAAAAAAAAAAAAAP////////4AAAAAAAAAAAAAAAAAAAAAAP////////4AAAAAAAAAAAAAAAAAAAAAAP
+ ////////4AAAAAAAAAAAAAAAAAAAAAAP////////4AAAAAAAAAAAAAAAAAAAAAAP////////4AAAAAAA
+ AAAAAAAAAAAAAAAP////////4AAAAAAAAAAAAAAAAAAAAAAP////////4AAAAAAAAAAAAAAAAAAAAAAP
+ ////////4AAAAAAAAAAAAAAAAAAAAAAP////////gAAAAAAAAAAAAAAAAAAAAAAP////////AAAAAAAA
+ AAAAAAAAAAAAAAAP///////+AAAAAAAAAAAAAAAAAAAAAAAP///////8AAAAAAAAAAAAAAAAAAAAAAAP
+ ///////4AAAAAAAAAAAAAAAAAAAAAAAP///////4AAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAA
+ AAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAA
+ AAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAA
+ AAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////gAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAA
+ AAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAA
+ AAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP//////8AAAAAAAAAAAAAAAAAAAAAAAAP
+ /////+AAAAAAAAAAAAAAAAAAAAAAAAAP/////AAAAAAAAAAAAAAAAAAAAAAAAAAP////4AAAAAAAAAAA
+ AAAAAAAAAAAAAAAP////AAAAAAAAAAAAAAAAAAAAAAAAAAAP///+AAAAAAAAAAAAAAAAAAAAAAAAAAAP
+ ///8AAAAAAAAAAAAAAAAAAAAAAAAAAAP///4AAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///gAAAAAAAAAAAAAAAAAAAAAAAAAAAP
+ ///gAAAAAAAAAAAAAAAAAAAAAAAAAAAP///AAAAAAAAAAAAAAAAAAAAAAAAAAAAP///AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAP///AAAAAAAAAAAAAAAAAAAAAAAAAAAAP///AAAAAAAAAAAAAAAAAAAAAAAAAAAAP
+ ///gAAAAAAAAAAAAAAAAAAAAAAAAAAAP///gAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAP///8AAAAAAAAAAAAAAAAAAAAAAAAAAAP
+ ///+AAAAAAAAAAAAAAAAAAAAAAAAAAAP////wAAAAAAAAAAAAAAAAAAAAAAAAAAP/////gAAAAAAAAAA
+ AAAAAAAAAAAAAAAP//////AAAAAAAAAAAAAAAAAAAAAAAAAP//////8AAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAA
+ AAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP///////wAAAAAAAA
+ AAAAAAAAAAAAAAAP///////wAAAAAAAAAAAAAAAAAAAAAAAP///////gAAAAAAAAAAAAAAAAAAAAAAAP
+ ///////gAAAAAAAAAAAAAAAAAAAAAAAOA//////gAAAAAAAAAAAAAAAAAAAAAAAIAf/////gAAAAAAAA
+ AAAAAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAAAAAAAAAAAAH/////gAAAAAAAAAAAAAAAAAAAAAAAA
+ AD/////gAAAAAAAAAAAAAAAAAAAAAAAAAD/////gAAAAAAAAAAAAAAAAAAAAAAAAAB/////gAAAAAAAA
+ AAAAAAAAAAAAAAAAAB/////gAAAAAAAAAAAAAAAAAAAAAAAAAB/////gAAAAAAAAAAAAAAAAAAAAAAAA
+ AB/////gAAAAAAAAAAAAAAAAAAAAAAAAAB/////gAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAAAAAA
+ AAAAAAAAAAAAAAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAA
+ AH/////4AAAAAAAAAAAAAAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAAAAAAAAAAAAf////gAAAAAAAAA
+ AAAAAAAAAAAAAAAAAf////AAAAAAAAAAAAAAAAAAAAAAAAAAA////+AAAAAAAAAAAAAAAAAAAAAAAAAA
+ B////8AAAAAAAAAAAAAAAAAAAAAAAAAAD////4AAAAAAAAAAAAAAAAAAAAAAAAAAH////4AAAAAAAAAA
+ AAAAAAAAAAAAAAAAP////4AAAAAAAAAAAAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAAAAAAAAAAAA
+ /////wAAAAAAAAAAAAAAAAAAAAAAAAAB/////wAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAAAAAAAA
+ AAAAAAAAAAAAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAD/////wAAAAAAAAAAAAAAAAAAAAAAAAAD
+ /////wAAAAAAAAAAAAAAAAAAAAAAAAAB/////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////wAAAAAAAAAA
+ AAAAAAAAAAAAAAAAf////wAAAAAAAAAAAAAAAAAAAAAAAAAAP////wAAAAAAAAAAAAAAAAAAAAAAAAAA
+ H////wAAAAAAAAAAAAAAAAAAAAAAAAAAD////wAAAAAAAAAAAAAAAAAAAAAAAAAAB////wAAAAAAAAAA
+ AAAAAAAAAAAAAAAAA////wAAAAAAAAAAAAAAAAAAAAAAAAAAAf///wAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAH///wAAAAAAAAAAAAAAAAAAAAAAAAAAAH///wAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAD///wAAAAAAAAAAAAAAAAAAAAAAAAAAAB///wAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AB///wAAAAAAAAAAAAAAAAAAAAAAAAAAAB///wAAAAAAAAAAAAAAAAAAAAAAAAAAAB///wAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAB///wAAAAAAAAAAAAAAAAAAAAAAAAAAAB///wAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AB///4AAAAAAAAAAAAAAAAAAAAAAAAAAAD///4AAAAAAAAAAAAAAAAAAAAAAAAAAAD///4AAAAAAAAAA
+ AAAAAAAAAAAAAEAAAH///4AAAAAAAAAAAAAAAAAAAAAAAPgAAP///4AAAAAAAAAAAAAAAAAAAAAAAf4A
+ AP///4AAAAAAAAAAAAAAAAAAAAAAA//AAf///8AAAAAAAAAAAAAAAAAAAAAAB//wB////8AAAAAAAAAA
+ AAAAAAAAAAAAD///P////+AAAAAAAAAAAAAAAAAAAAAAH/////////AAAAAAAAAAAAAAAAAAAAAAP///
+ //////gAAAAAAAAAAAAAAAAAAAAAf/////////wAAAAAAAAAAAAAAAAAAAAA//////////8AAAAAAAAA
+ AAAAAAAAAAAB////////////4AAAAAAAAAAAAAAAAAAD////////////8AAAAAAAAAAAAAAAAAAH////
+ ////////8AAAAAAAAAAAAAAAAAAP////////////8AAAAAAAAAAAAAAAAAAf////////////8AAAAAAA
+ AAAAAAAAAAA/////////////8AAAAAAAAAAAAAAAAAB/////////////8AAAAAAAAAAAAAAAAAD/////
+ ////////8AAAAAAAAAAAAAAAAAD/////////////8AAAAAAAAAAAAAAAAAH/////////////8AAAAAAA
+ AAAAAAAAAAP/////////////8AAAAAAAAAAAAAAAAAf/////////////8AAAAAAAAAAAAAAAAA//////
+ ////////8AAAAAAAAAAAAAAAAB//////////////8AAAAAAAAAAAAAAAAD//////////////8AAAAAAA
+ AAAAAAAAAH//////////////8AAAAAAAAAAAAAAAAP//////////////8AAAAAAAAAAAAAAAAf//////
+ ////////8AAAAAAAAAAAAAAAA///////////////8AAAAAAAAAAAAAAAB///////////////8AAAAAAA
+ AAAAAAAAD///////////////8AAAAAAAAAAAAAAAH///////////////+AAAAAAAAAAAAAAAP///////
+ ////////+AAAAAAAAAAAAAAA////////////////+AAAAAAAAAAAAAAD////////////////+AAAAAAA
+ AAAAAAA/////////////////////////////////////////////////////////////////////////
+ //8oAAAAEAAAACAAAAABACAAAAAAAAAEAAAjLgAAIy4AAAAAAAAAAAAAAAAAAAAAAAAsLAxlKioLhyoq
+ C4ctMhSJOE0zkjxXP5Y8Vz+WPFY+ljdMMZI7VTyVPFY+lkFjS3h///8bf///BwAAAAAAAAAAODgXgv//
+ ////////+f///8r7/v+66/7/vOb+/7rq/f/b8Pv/t+38/7zn/P97ssbPhvH/cH///xAAAAAAAAAAAElJ
+ Jnv///////////j+/v/J9/3/54j9//lN/f/NtP3/r+H8/8m4+//4Tv3/v0TS0Yzl/3R///8RAAAAAAAA
+ AABUVC93/////8zMu//Hzb3/suzi/7qx6//7K/7/+i7+/+tg/P/6Lv3/+yv+/56S2dN///93f///EAAA
+ AAAAAAAAWFgzdv///v/t7dz/6u3d/8zy5v+q3fX/5y////kH///4Df///gH//+cv//+LxuLbf///S3//
+ /wYAAKiNAACk/wAAov8AAKD/AACe/x06s/9YseD/fZbp/95C///JNv//7RL//+0S///eQv//mLXp4X//
+ /7F///86AACu/wAArv8AALH/AACx/wAAsP9XruX/aHHg/8AP7f+6TP//oV7//61S//+nWP//x0D//+Ub
+ 6eGls/+hf///rgAAtf8AALn/4eH//5KS5/9MTNH/Ybzs/7UD6f+7Eez/2Uv//9lM//+Ucf//2Uz//9lM
+ ///jIOje/QP/tX///7QAAL7/AADH/1FR3v/d3f3/oqLw/5bs/P+h+P//fNPz/1u25//Wg/L/8zn2/9SC
+ 8f+g/Pj/e+bf0X///6x///+rAADG/wAA0v8AANX/Z2fo/2Fh5f/Fyff/QkbX/wYNv/85c9X/tK7h/+1G
+ 7P+2sOP/v/jv/299WnR///8If///CAAAzf8AANr/AADe/y0t5f/T0/r/ZGTn/wAAz/8BA8T/Hj3J/6vw
+ 8//3TPL/qe7w/9b16P9xdU1uAAAAAAAAAAAAANH/AADg/wAA5v8FBej//v7//yAg4f8AANT/AADJ/wgR
+ wf+k9/H/offx/6P28P/q8+P/dHRMawAAAAAAAAAAAADV/wAA4/8AAOr/AADs/wAA5/8AAN//AADW/wAA
+ y/8AAMH/5ubV/6Skk/+kpJP/pKST/0lJJXwAAAAAAAAAAAAAzo0AANj/AADb/wAA3P8AANn/AADV/wAA
+ 0P8AAMr/fn7N/+Xl1P+2tqX//////3p6UWh6elElAAAAAAAAAAAAAAAAAAAAAH19U2f8/PX/+fnv//b2
+ 6v/09OX/8/Pi//Ly4f/y8uH/wsKx/319U2d9fVMlAAAAAAAAAAAAAAAAAAAAAAAAAAB/f1VNf39VZn9/
+ VWZ/f1Vmf39VZn9/VWZ/f1Vmf39VZn9/VWZ/f1UkAAAAAAAAAAAAAAAAAAAAAOAH///AA+AH4APAA+AD
+ 4APgA+ADAAHgAwAAAAEAAAAAAAAAAAAHAAAABwAHAAcABwAHAAcADwAH4B8AD///4B8oAAAAIAAAAEAA
+ AAABACAAAAAAAAAQAAAjLgAAIy4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADAAAADAAA
+ AAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAAAAwAAAAMAAAADAAA
+ AAwAAAAMAAAADAAAAAwAAAAMAAAACwAAAAMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AC0AAACMAAAAkgAAAJIAAACSAAAAkgAAAJIAAACSAAAAkgAAAJIAAACSAAAAkgAAAJIAAACSAAAAkgAA
+ AJIAAACSAAAAkgAAAJIAAACSAAAAkgAAAJIAAACKAAAAKAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAPMzMzPna2tr/29vb/93d3f/e3t7/39/f/9/f3//U1NT/zMzM/9vb2//j4+P/4+Pj/+Li
+ 4v/h4eH/4ODg/97e3v/d3d3/3Nzc/9zc3P/b29v/2dnZ/9TU1P/CwsKUAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAA81NTU+efn5//q6ur/6+vr/+zs7P/t7e3/5+fn/6ysxP96d8n/urnE/+Tk
+ 5P/s7Oz/7Ozs/+vr6//q6ur/6Ojo/+fn5//m5ub/5OTk/+Li4v/f39//2dnZ/8bGxpcAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADzX19f56+vr/+3t7f/u7u7/7+/v//Hx8f/r7Ov/enrm/0hF
+ 6f9dWen/w8TP/+zs7P/w8PD/7+/v/+7u7v/t7e3/6+vr/+rq6v/o6Oj/5ubm/+Pj4//c3Nz/ysrKmAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPNnZ2fnt7e3/8PDw//Hx8f/z8/P/9PT0//Pz
+ 8v+IhvP/VlTc/1xZ2/9tat3/2tra/+/v7//y8vL/8vLy//Dw8P/v7+//7e3t/+rq6v/n5+f/5OTk/97e
+ 3v/MzMyaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAJmZmQOfn5+KxMTE/Ofn5//z8/P/9PT0//X1
+ 9f/29vb/9vb2/+zs9f94dvX/QD3t/0xH9/+JiLn/xcXF/93d3f/o6Oj/7e3t/+zs7P/h4eH/0dDQ/8HB
+ wf/BwMD/0tLS/83NzZwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9PT0Vv77+v78+/v/yMjI//Pz
+ 8//29vb/9/f3//j4+P/5+fn/+fn5//j4+P+8vPf/YmD0/1BL6f9ubb7/oKG1/7W1tf+2trb/tLS0/5iX
+ ov9vb7X/XFrM/15cyv+6usf/zc3NnQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD9/f1+/7+w//+q
+ lf/t7e3/09PT//j4+P/19fX/4+Pj/9nZ2f/V1dX/+fn5//r6+v/l5fD/XFf0/1RO8v9PSfX/V1Pn/1ZU
+ zf9UUcj/SUXv/0ZE8/9RUen/U073/7u73v/Ozs6fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP39
+ /W7/zcD//zwL///j3f/W1tb/3d3d/+fn5//7+/v///j2/+fn5//s7Oz/+/v7//n5+P+dnO7/X1vs/8XF
+ zf+Egsv/RUD5/3t49f9/fff/iIX1/5uW9f/Lyuz/4eHh/8/Pz6EAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AACXl5cD8vLyaP/c1P//MwD//2U////9/f//9/X//7Sh//9kPv//ppD/9/f3//X19f/8/Pz/+/v7/+Tk
+ 7/9YU/X/bm6+/1BM7/+qqPP/9PT0//X09P/y8fL/7+/v/+rq6v/h4eH/zs7OowAAAAAAAAAAAAAAAJSU
+ lAKysrJKycnJmNjY2M3s7Ozy/+vn//8zAP//MwD//2pE//8/D///MwD//5B0//39/f/39/f//Pz8//z8
+ /P/8/Pz/+Pj3/4mJ6/9CPPj/kpDt//X29f/29vb/9PT0//Ly8v/v7+//6urq/+Dg4P/Ozs6kAAAAAAAA
+ AAAAAAAA8fHxWP39/f3/7+v//8O1//+Xff//aUT//zMA//8zAP//MwD//zMA//+AYP/9/Pz/9vb2//v7
+ +//8/Pz//Pz8//z8/P/5+fn/srHa/0pF+P/MzN//9/f3//b29v/09PT/8PDw/+3t7f/p6en/39/f/87O
+ zqYAAAAAAAAAAAAAAAD+/v6O/9rR//9tSf//QRL//zMA//8zAP//MwD//zMA//8zAP//NgT//9/Y/+fn
+ 5//b29v/+vr6//v7+//7+/v/+/v7//b29v+dnNf/Qj73/6Oh5P/19PX/9fX1//Ly8v/v7+//7Ozs/+jo
+ 6P/f39//zc3NqAAAAAAAAAAAAAAAAP7+/h////+q////6P/+/v//4Nj//6yY//8zAP//MwD//zMA//8z
+ AP//TiL//+vm/9nZ2f/f39//+fn5//r6+v/5+fn/8fLx/4WD4P9FQvT/gX/r//Hx8f/x8fH/7e3t/+7u
+ 7v/q6ur/5ubm/97e3v/MzMypAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////IP7+/on/5uD//zMA//81
+ A///sJ3//4Bh//88C///Vy3///Hu/9HR0f/u7u7/+Pj4//f39//x8fH/fXvl/0lH6P9vbO3/7Ozs/+Tk
+ 5P/R0dH/1tbW/+jo6P/k5OT/29vb/8rKyqoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/Pz8ZP/X
+ zf//MwD//5R5//v7+//9/f3///Tx//+umf//qpX/9PT0/+jo6P/29vb/9vb2//Hx8f+Hher/R0Xo/3Vz
+ 8P/09PP//9/////u///Nzc3/3t7e/+Hh4f/X19f/xcXFrJqamgqYmJgFAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD8/Px1/8i6//9WLP/++ff/7Ozs//Ly8v/19fX/+vr6//39/f/29vb/8/Pz//T09P/z8/P/8fHw/7y7
+ 8f9kYvT/wsLs//X09P//tP///1z///n5+f/CwsL/3Nzc/8nJyf/Ozs7q3Nzc5rm5ubmZmZkKAAAAAAAA
+ AAAAAAAAAAAAAPz8/ID/0MT//9fN//Dw8P/v7+//8PDw//Dw8P/w8PD/8PDw//Dw8P/w8PD/8PDw/+/v
+ 7//u7u7/7e3t/+3s7P/q6uv/8fHx///H////AP///6///+jo6P/e3t7/+Pj4///k////vP//8fHx+5yc
+ nCsAAAAAAAAAAAAAAAYAAAA9TExMht/f3/He3t7+srKy/7Ozs/+zs7P/srKy/7Kysv+zs7P/s7Oz/7Ky
+ sv+ysrL/sbGx/7Gxsf+6urr/2tra/9vb2//f39///9r///8A////F////+f///+w////TP///xD////K
+ ///09PS/mJiYBQAAAAAAAAAAAAAANw8OMb0uLHnqNTOA7UtKkf1OTZT/Tk6V/05Nlf9OTZT/Tk2U/05N
+ lP9OTZT/Tk2U/05NlP9OTZT/U1KU/6qqtP/a2tr/7+/v//39/f//3////wD///8A////Bv///wD///8G
+ ////u///+fn51NfX1xQAAAAAAAAAAAAAAAAPEBZcJyWm+js5t/87OLf/Ojeq/zo4tf87Obj/Ozi1/zk2
+ pf85NqX/Oziz/zw4tP86N6v/Ozm4/zw5uP+dnNr//+b///+X////YP///yj///8B////AP///wD///8A
+ ////Av///6r///Ly8vXNzc0mAAAAAAAAAAAAAAAAAAAAASEhO2gQDbb/EA+2/xAOtf9eX4b/GBas/xEP
+ tv8dGqr/dHSB/3R1iv9RUX7/Hx2g/1JSiP8RDrX/EA+2/39/2P//6v///53///9m////Lv///wP///8A
+ ////AP///wD///8B////pP//8fHx/aysrJaXl5cFAAAAAAAAAAAAAAABIiNBah4cy/8kI83/IyLM/4mI
+ rv9ZWZ3/QUCh/zEvvv+EhLH/NDLR/4KBtf9IR7L/g4Kk/zw6oP8qKbv/JybO/29v4P+op+n/9fX1//7+
+ /v//4v///wD///8A////CP///wD///8E////tf//7Ozs/Kenp4eYmJgCAAAAAAAAAAEjI0lrNDLg/0NB
+ 4/9CQOP/sLHV/4uK3f+4t9f/ZmTL/6qq1v9AQN3/nJvO/29u2P/Cwdf/oKDc/19f4P9DQeP/Q0Hj/z4+
+ 1v/Pz8//39/f///a////AP///xn////q////tv///1P///8P////w///4eHh95ycnCoAAAAAAAAAADIz
+ ZldNTPH/ZmXz/2Vl8//Pz/H/qqnK/9fY5/+KiPD/3d7q/6ipx//T1e//f33w/9ra5/+lpcb/hoXU/2Rl
+ 8/9lZfP/UVHm/8/Pz//d3d3//8f///8A////sv//7u7u/+fn5+f////q/+n////A///19fXpmpqaFQAA
+ AAAAAAAAREhlElBP9+mMjPv/jY38/6Sk/P+rq/z/oKD7/5KS/P+qqvz/qqr9/5eX/P+Skvv/q6r8/6ur
+ /P+dnvz/jY37/4eH+/9oaOv/0NDQ/+Hh4f//tP///17///r6+v/MzMzpvr6+J/7+/gX+/v5S////kfj4
+ +DcAAAAAAAAAAAAAAAAAAAAAR0L0K0A9+4M6OdOhhITq+oyM8P+Li+//i4vv/4uL7/+Kiu7/ioru/4mJ
+ 7f+IiOz/h4fr/4eH6/+Ghur/h4bm/8nJ1f/MzMz/29vb///f////7///29vb7sjIyC8AAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADbT09P14ODg/9/f3//f39//3t7e/93d
+ 3f/c3Nz/29vb/9nZ2f/Y2Nj/19fX/9XV1f/S0tL/zs7O/8PDw/+0tLT/5+fn/97e3vHHx8c2AAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANtLS0vXe3t7/3d3d/9zc
+ 3P/b29v/2dnZ/9jY2P/X19f/1tbW/9TU1P/S0tL/z8/P/8vLy//CwsL/s7Oz/6urq//AwMDzwcHBOwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAp1dXV8dra
+ 2v/Y2Nj/1tbW/9PT0//R0dH/z8/P/87Ozv/Nzc3/y8vL/8jIyP/Dw8P/u7u7/7CwsP+hoaH/q6ur9bOz
+ s0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAPn5+ea5eXlquPj46rg4OCq3t7eqtvb26rZ2dmq19fXqtPT06rNzc2qyMjIqsLCwqq5ubmqr6+vqK+v
+ r4e4uLgmAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP/////8AAAP/AAAB/wA
+ AAf8AAAH/AAAB/gAAAf4AAAH+AAAB/gAAAf4AAAHwAAAB4AAAAcAAAAHgAAAB/AAAAf4AAAH+AAAAfAA
+ AAHwAAAB4AAAA+AAAAfgAAAD4AAAAeAAAAHgAAAB4AAAO/AAAH/8AAD//AAB//wAA//8AAf/KAAAADAA
+ AABgAAAAAQAgAAAAAAAAJAAAIy4AACMuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADAwMDIQQEBDQEBAQ2BAQENgQEBDYEBAQ2BAQENgQEBDYEBAQ2BAQENgQE
+ BDYEBAQ2BAQENgQEBDYEBAQ2BAQENgQEBDYEBAQ2BAQENgQEBDYEBAQ2BAQENgQEBDYEBAQ2BAQENgQE
+ BDYEBAQ2BAQENgQEBDYEBAQ2BAQENgQEBDYEBAQ2BQUFLgAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMAgICbQAAAKsAAACxAAAAsQAAALEAAACxAAAAsQAA
+ ALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAA
+ ALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAsQAAALEAAACxAAAAmAAAAEAAAAACAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFRUVgKGhofSpqan1qqqq9aqq
+ qvWrq6v1rKys9aysrPWtra31rq6u9a2trfWurq71qqqq9aqqqvWxsbH1tbW19bW1tfW0tLT1tLS09bS0
+ tPWzs7P1s7Oz9bGxsfWxsbH1sbGx9bCwsPWurq71sLCw9bGxsfWwsLD1sLCw9a+vr/WsrKz1ra2t8JeX
+ l8w4ODgJ////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGBgYgdXV
+ 1f/o6Oj/6+vr/+rq6v/r6+v/7e3t/+7u7v/u7u7/7u7u/+7u7v/i4eH/yMjE/76+vf/P0M3/5eTm/+7t
+ 7f/u7u7/7+/v/+7u7v/s7Oz/7Ozs/+zs7P/q6ur/6enp/+jo6P/n5+f/5ubm/+Xl5f/k5OT/5OTk/+Li
+ 4v/e3t7+3d3d/8HBwexBQUEL////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAALFxcXgdTU1P/p6en/6+vr/+3t7f/t7e3/7e3t/+7u7v/v7+//7+/v/+7u7v/Q0c7/a2nE/1BL
+ 3f+Jh8H/zs/I/+Hh4//t7u7/7+/v/+/v7//u7u7/7e3t/+3t7f/r6+v/6+vr/+rq6v/o6Oj/5+fn/+bm
+ 5v/m5ub/5OTk/+Pj4//d3d3+3Nzc/8LCwutHR0cM////AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAALFxcXgdbW1v/r6+v/7e3t/+7u7v/u7u7/7+/v//Dw8P/x8fH/8fHy//Dw
+ 8v++vtj/ODT3/0M9//9QSvP/rKy8/9jZ0v/r6+z/8fHx//Dw8P/v7+//8PDw/+/v7//u7u7/7e3t/+zs
+ 7P/r6+v/6enp/+np6f/n5+f/5eXl/+Xl5f/f39/+3t7e/8PDw+xHR0cM////AQAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAALGBgYgdfX1//s7Oz/7+/v//Dw8P/w8PD/8vLy//Ly
+ 8v/z8/P/9PT0//Hx8//AwOj/PTr9/1JR2/9ZV9v/Tkjz/4mJyv/d3dr/8vHx//Pz8//y8vL/8fHx//Hx
+ 8f/w8PD/7+/v/+7u7v/t7e3/7Ozs/+vr6//p6en/6Ojo/+fn5//h4eH+4ODg/8bGxu5ISEgO////AQAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMFBQUft3d3f/v7+//8fHx//Ly
+ 8v/z8/P/9fX1//T09P/19fX/9/f3//X09v/k4/P/My/4/zQu/v9xcL7/Uk73/0dA/v+trcb/5+bp//Dw
+ 8P/09PT/8/Pz//T09P/z8/P/8vLy//Hx8f/v7+//7u7u/+3t7f/r6+v/6Ojo/+fn5//i4uL+4eHh/8jI
+ yO9GRkYO////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wEJCQkNMjIyksnJ
+ yf/u7u7/8vLy//T09P/09PT/9vb2//b29v/29vb/9/f3//b29v/6+vb/pKTz/zUx9P9FQuz/T07h/1FO
+ /f92dM3/zMzJ/9zd3v/r6+v/8vLz//Pz8//19fX/8/Pz//Ly8v/v7+//6+vr/+fn5//c3N3/09PU/9XV
+ 1v/X19f+4eHh/8rKyvFKSkoP////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AQAA
+ AADS0tKI3t7e+Nzc3P/Gxsb/8fHx//b29v/19fX/9/f3//f39//39/f/+Pj4//j4+P/4+Pj//Pv4/9/e
+ +P96ePf/Ojb4/0NA9v9UT+v/hYSa/6Wmo/++vrr/y8zM/9PT1f/c3N3/4uLj/+Pj4//W1tf/xcTC/7q6
+ tf+rq6v/oaGn/5+gpv+5urj+2trb/8vKyvFISEgP////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAANTU1Bj9/f35/fn4/v/////i4uL/wMDA//n5+f/4+Pj/+fn5//j4+P/5+fn/+/v7//7+
+ /v/9/v3/+vr6//n3/P////r/1tf4/3V09P9QTPn/OjT7/0ZD2/+Bgb7/ra6s/7S1qP+wsKb/qqqm/6mp
+ qP+enpT/c3SV/1pYsv8/O+T/Ozjx/zk28P97es7+2drW/8vMzPRLS0sR////AgAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///8BAAAAAPDw8DP+/f3//25K///Iuv/8/Pv/sLCw/9nZ2f/6+vr/+fn5//n5
+ +f/9/f3/9/f3/+np6f/p6en//f79//z7+//5+fr////7////8P9vbfD/UEj9/z85/v8+N/r/UE/l/2pn
+ 1P93ea//goGN/4mLif9dWrX/OjT1/0hD//9ZV/f/VVPw/0VB+v9lZOv+5ufa/8rKzfNLS0sR////AgAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8BAAAAAOTk5Cf8+/v9/2ZA//8xEP//4dr/8fHx/7q6
+ uv/n5+f/8PDw/+bm5v/f3t7/4+Li/+Xl5f/V1dX/ycnJ//j4+P/8/Pz/+/v8//n7+f+1tO7/UEr5/1BK
+ 9f+QjuL/enbz/2Bb8f9MR/T/NTD0/zo28v9DP/r/S0b5/0E+9/9KR+//Ukzz/2pj+f+xsOn/5ubi/83N
+ zvZISEgS////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPT09Bj+/Pz2/4Fh/v8n
+ Af//f2L///////r5+f++vb3/3t3d//Lv7//////////////18//+/Pv/09PT/9vb2//9/f3//f39//z7
+ /f/s7fL/XVzx/0xF//+cm9P/0tDH/729qP9KRub/Tk32/4iG8v+lo/b/oaD4/6Si9/+wrvX/zM3w/+3u
+ 7P/p6ef/5OTk/83NzfZJSUkT////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAf///wH///8C////Af//
+ /wn//v3w/49y/v8mAP//PxP///b0///////6+Pf/////////////5uD//4Jl//9DGv//7en/6Obm/+rq
+ 6v/+/v7//f39//39/f/8/Pf/lJPp/05J9/9ua9T/qaud/11Y0v9LR/v/m5vz//f58v////X////1//z9
+ 8//6+/D/9ffv/+3t7v/m5uf/4+Pj/83NzflMTEwU////AgAAAAAAAAAAAAAAAAAAAAAAAAAAv7+/AqOj
+ ow6ampoqnp6eS6mpqWn59/b0/6OM/v8lAP//MgP//1w3///h2f//0MX//5N6//9lSP//OA3//1g+///O
+ wf/9/Pz/8fHx//z8/P/9/f3//f39//z8/P/7/Pz/5uXq/25t7v9NSOv/SETf/0dC/P+sqvH/+/v4//j4
+ 9//19fb/9PT1//Py8//x8PL/7+/w/+3t7f/n5+b/4uLi/83NzfpKSkoU////AgAAAAAAAAAAAAAAAP//
+ /wGcnJwnpqamrLm5udra2Nj49vPy/////////////8a3//8pAP//NAH//zEA//83BP//KgD//zEA//86
+ CP//VjT////////+/v/29vb//v7+//39/f/+/v7//v7+//39/f/8/Pz//v73/7y84/9MRvf/Qj76/31+
+ 6v/19fL/+fn5//n4+P/29vb/9fX1//Tz8//x8fH/7+/v/+zs7P/m5ub/4uLi/87OzvxNTU0V////AgAA
+ AAAAAAAAAAAAAAAAAADZ2dm1//79/////////////////f////7/4Nn//4tu//8uAP//MwH//zQA//8y
+ AP//NQL//zcE//8kAP//u6r////+//n4+P/5+fn//f39//z8/P/9/f3//f39//z8/P/8/Pz/+fn5/97f
+ 3f9WVPH/Q0D2/8HD1v/39/b/+fn4//j4+P/29vb/9fX1//Pz8//x8fH/7+/v/+zs7P/m5ub/4eHh/83N
+ zfxLS0sW////AgAAAAAAAAAAAAAAAPb29j/9+/v7/76t/f+chf7+eF/+/1k5//9IHv//Ngb//zAB//8z
+ AP//MwD//zMA//8zAP//MgH//z4W//+yn//9/Pv/39/f//Hx8f/9/f3//Pz8//z8/P/8/Pz//Pz8//z8
+ /P/8/Pz/9fT3/+Hh0/9XVOf/SkX4/6qq2P/19fL/+Pj4//f39//19fX/9PT0//Ly8v/v7+//7e3t/+vr
+ 6//k5OT/4ODg/87Ozv5MTEwW////AgAAAAAAAAAAAAAAAP///0T//f39/72t/P+LcP7/WTH//zQB//8p
+ AP//KQD//zEA//8zAP//MwD//zMA//8zAP//MgH//z4U///Mvv/+/f3/xcXF/7e3t//6+vr/+/v7//z8
+ /P/7+/v//Pz8//v7+//7+/z/7+/v/9DQy/8+OvP/SUT6/3Ft6f/w8Ov/9/f3//f39//09PT/8/Pz//Ly
+ 8v/v7+//7e3t/+vr6//k5OT/4ODg/87Ozv5LS0sX////AgAAAAAAAAAAAAAAAP///wb////f////////
+ ////+fj+/9bM+/+rl/3/bkv//z0N//8yAP//MwD//zMA//81Av//NQH//y0A//84Df//6uT//////8DA
+ wP/a2tr//f39//v7+//7+/v/+/v7//r6+v/5+vr/7+7q/7q9y/9APPX/TEf7/1lU8P/n6On/9vb3//X1
+ 9f/z8/P/8/Pz//Dw8P/u7u7/7Ozs/+rq6v/k5OT/4ODg/87Ozv9KSkoY////AgAAAAAAAAAAAAAAAAAA
+ AAD+/v4d//z8Wf/7+nL//v2h//79x//8/OL+/f39/7im//8qAP//NAH//zAA//9FGv//OAz//y8D//8x
+ AP//ZkT///Tx///+/v/Kysr/4eHh//v7+//6+vr/+vr6//n5+f/4+Pn/8PDm/6em0v89Ovb/SUb1/0ZB
+ +v/b2+b/8/P0/+fn5//X19f/29vb/+3t7f/s7Oz/6urq/+jo6P/i4uL/3t7e/83Nzf9MTEwZ////AgAA
+ AAAAAAAAAAAAAAAAAAD///8C////AQAAAAAAAAAAAAAAAAAAAAD59/fo/6WN/f8mAP//MwP//0IW///w
+ 7P//3tb//3hY//88D///JAD//1Uu///z7//7+vr/srKy/+Xl5f/6+vr/+Pj4//j4+P/39/j/8vPn/6el
+ 2P9APe3/TUrr/zs2/P/W1ej/5ubo/+3t7f/y7/L/v7+//7u7u//q6ur/6Ojo/+bm5v/g4OD/3Nzc/8zM
+ zP9QUFAZqqqqAwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wH///8D////BNra2gf9+vru/5h9/v8k
+ AP//MAP//72s///////////////////p5P//gWP//yEA//9UKv//9/b/2NfX/9jY2P/5+fn/9/f3//f3
+ 9//39/j/9PXo/6qq2v9BP+v/TErm/zcz/v/Z2er/+fn7/////////////v7+/7S0tP/a2tr/5ubm/+Xl
+ 5f/e3t7/2tra/8nJyf9LS0sbAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN3d
+ 3Rf8+/r2/4Rl//8lAP//dlj///////n49//z8vL/+/r6//38/P///v7//+fh///Asf//9/X/6ejo/+vr
+ 6//39/f/9fX1//X19f/19PX/9fbv/8nJ6P88OPb/R0Ty/1NQ9f/o6ez////////////+df7///////b1
+ 9v/BwcH/5eXl/+Pj4//d3d3/09PT/8PDw/+MjIxUoaGhapCQkEulpaUJAAAAAAAAAAAAAAAAAAAAAAAA
+ AAB/f38BAAAAANbW1ib7+/v+/3FO//8fAP//4Nj//fv6/+Tl5f/09PT/8/Pz//Pz8//29fX//Pr6///8
+ +//7+/v/8/Pz//X19f/19fX/9PT0//Pz8//z8/P/8PDx//j38f90cvb/g4L1/9rZ7v/v8O3///3/////
+ ////Jv///6z////////Z2dn/w8PD/+Xl5f/Ly8v/vLy8/8vKy//x7vH/+Pj4/9HR0f+VlZVaAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///8B////Af/6+jP9/f3//0oc//91Uf///v7/6eno/+3t7f/z8/P/8vLy//Ly
+ 8v/x8fH/8vLy//Pz8//y8vL/8/Pz//Ly8v/z8/P/8vLy//Hx8f/x8fH/8vLy/+/v8P/z9O7/9PXu//Hy
+ 7P/s7O3//vz+////////L////xn////p///29fb/qKio/7+/v//T0tP/9vP2///////////+/////f//
+ //63t7eaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAADVFRUTD4+Pj2/tHG//718v/y8fL/4eHi/+rq
+ 6v/o6On/6Ojp/+jo6f/o6Oj/6Ojp/+jo6f/o6Oj/6ejp/+jo6P/o6On/5+fo/+fn5//m5uf/5ubm/+fo
+ 5//r6uv/7Ozs/+zr7P/q6ur//Pj9////////Ov///wP///8q////6P//8fHx//Tz9P/+9f7//8D///+S
+ ///+Uv7//eD9/v7+/v7Pzs99AAAAAAAAAAAAAAAAAAAAAAAAAAEAAAAsBAQEdQAAAIGDhH/B5+Tg9urp
+ 5f+qqqb/oqKe/6Ghnf+hop3/oKGc/6CgnP+goJz/oaGc/6ChnP+goZz/oaGd/6ChnP+foJv/n5+b/5+f
+ m/+fn5v/oKCc/6Skov/CwsL/3d3d/9bW1v/Gxsb/9O/0////////SP///wX///8C////ff///vb+//+p
+ ////LP///wD///8A////mP/+//////X19fS0tLQd////AgAAAAAAAAAAAAAAAAAAAAwBAQJuAgQAthAQ
+ GswODR7NKSk921ZWav1bW27/XV1w/11dcP9dXXD/XF1w/1xdcP9bXG//W1xv/1xcb/9cXG//XFxv/1xc
+ b/9cXG//XFxv/1tbb/9bXG//Wltu/2Zncf+ampn/wsHC/87Nzv/j3+P//ff9////////VP///wP///8B
+ ////F////yj///8A////AP///wD///8t////9P/++vn6+ry8vFH///8BAAAAAAAAAAAAAAAAAAAAAAAA
+ ACwQDjOxLyyd+EZFtP9PTbr/TUq2/01LuP9MS7f/TEq3/0xKtv9MSrb/TUu3/05LuP9OS7j/TUu4/01L
+ t/9NSrb/TUu3/01LuP9MS7b/TEq3/01Kt/9MSrb/m5rO/9va5f/29fb///7////0///+0/7//6z///+T
+ ////Kv///wH///8A////AP///wH///8C////Bv///3n////v//729fbauLi4MP///wEAAAAAAAAAAAAA
+ AAAAAAAAVVVVAwAAADQhH4XZLi2y/i0qs/8sKbL/LSqz/ycioP8nJKb/LCqz/ywqs/8sKrP/KCao/yMg
+ l/8iH5j/Ih+d/ycjrP8tKrX/KSWn/yMfmv8rKbD/LSm1/zAttP9IRr3///////z4/v/+gv7//zj///8V
+ ////AP///wD///8A////AP///wD///8A////AP///wH///8B////cP///////vz7/P++vr5g////An9/
+ fwIAAAAAAAAAAAAAAAAAAAAAPz9/BAAAADQbGpDfDgqt/RAOsv8QDrL/DQqq/z4+eP8wLob/EAy0/xAO
+ sP8OC7H/KiiI/1NUaP9QT2X/SUhl/yoqa/8NCqT/LSuE/1NUaP8UEaP/EQ6v/xMRsv8zMb3///////v2
+ ////P////wD///8A////AP///wD///8C////Af///wD///8A////AP///wL///8A////jv////////r5
+ +v+lpaWyAAAAAP///wEAAAAAAAAAAAAAAAAAAAAAPz9/BAAAADUdG5vfFRO7/RYVwP8WFcD/Eg+9/3Jx
+ nP9QUJ7/Dg6z/xIQtv8UEcD/SEao/5qaj/9tbLP/c3K2/4uKl/88O5j/T02l/5uai/8bGbT/ExO8/xUV
+ wP8YF8D/np7n/+Hg+P/7+v7//u/+///Z////sP///4j///9o////Hf///wH///8A////AP///wD///8C
+ ////D////57////9///k5OT8oaGhq5SUlC0AAAAAAAAAAAAAAAAAAAAAPz9/BAAAADYjIqbhKCfQ/Sgn
+ 0v8pKNP/IyHP/4iHtv+WlaD/dXSM/2Rkiv8lJKr/XVzB/7y9r/80M8j/Hh7V/2Jhxf98fLP/Xly7/728
+ r/9JSYr/RkWF/zEvpP8oJ9L/Hx7Q/yIh0P9LStv/p6Te//Xz7//8+f3/////////////W////wL///8B
+ ////BP///wD///8A////A////wD///9Z///+//7+7e3t/6KiouuYmJgm////AgAAAAAAAAAAPz9/BAAA
+ ADcoJrDhOTfb/Tc23f84Nt7/MTDZ/5qZyv/Ly9H/zs3Y/9vc1P9xcLT/aWfP/9TWyP9JSNb/MzLf/2ho
+ zf+Vls3/b23M/9XUyv/Pzsf/19fG/3t7yP80Mt7/Ojje/zg33v8nJdv/T06+/9vbyv/Y2Nr/+PT4///9
+ ////Sv///wT///8D////Xv///8j///9h////Cv///wD///8A///+tv7//////uno6f+bm5t1AAAAAAAA
+ AAAAAAAASEhtAwAAADIwL7rgU1Ln/VBP7P9SUez/SEfn/7e44v+Zmdf/TU3B/5GQ0f+1teb/eXnf//T1
+ 6f9YWMj/REO2/6ys0v+hoer/ionh//Hz6f9ubMz/amnJ/1hYzv9QT+n/UVDs/1FP7P9HR+3/XFvK/9vb
+ zP/Pz9D/9/P3////////Pf///wT///8V////2f///Pr8///9//7/4f/+/5///v9o//3/Qf///uf+//7+
+ /v3FxMWaAAAAAAAAAAAAAAAAAAAAAgAAABQ9PcbXbm7y/Wpr9/9sbfb/Zmb0/83N9f/08/D/7Ozn////
+ +P+vr/j/nZ3y////+//p6+f/+/vy//v9/v+Ih/b/qqrz/////P/q6+T/7e7j/9TW3/9rbO//bW32/2tr
+ 9/9fXvf/X1/Z/9/fzv/Nzc//+/f7////////Mf///wP////F///8+/z/zMzM/crKyv/29PbI//7/////
+ ////+//+//j/+//////Dw8NW////AQAAAAAAAAAAf39/AgAAAAA+Ps68i4z2/H5++/9+fvr/gH/8/7S0
+ /v/Pz/7/0dD//8PD/P+MjPv/oJ7+/83N/P/R0f//ycn//6in/P9/f/z/o6T9/87O/P/Q0P//09L//8bF
+ //+Cgvz/f3/7/319+v9sbPv/cXDf/+Pj0v/Nzc7//vv+////////Kv///3r////////s6+z9wcHB/8zM
+ zJj///8F/v7+Uv/8/63//f/5/////+vr68fHx8cL////AQAAAAAAAAAAAAAAAKpUqgEzMsNMYF7+6W9v
+ +/56ev3+e3v+/3h4//93d/7/d3f+/3d3/v93d/7/eHf+/3h3/v93d/7/dnf+/3Z3//94eP7/eHf+/3h3
+ /v93d/7/d3f+/3d3/f94eP7/eHj+/3Rz//9gX/L/ysvX/9bV1P/NzM3///7/////////Vv////z///z7
+ /P3Qz9Dp0NDQUf///wH///8B////Af///wH+/P4d////JtTU1AMAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAD///8B39/fCMvL/zZkZKBGGRlUl6Ch3Pyur+v/rK3p/6us6P+rrOj/qqvn/6ur5/+qq+f/qarm/6ip
+ 5f+oqeX/p6jk/6eo5P+mpuL/pabi/6Sl4f+jpOD/oqPf/6io3v/X2NX/0NHT/9DQz//FxcX//Pz8////
+ /////v///////NXV1f/MzMxeAAAAAP///wIAAAAAAAAAAAAAAAD///8C////AwAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAD///8BAAAAAAAAAAAAAAAEEBAEbt/f0vrx8eT/7u7g/+3t3//t7d//7Ozf/+zs
+ 3//r7N7/6+vd/+rq3P/p6dz/6Ojb/+fo2v/m5tn/5ubY/+Xl2P/k5Nb/4+LW/+Dg1P/T09T/0dHQ/8zM
+ zP+6urv/0dHR///////////94+Pj/8vLy73l5eUF////AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMvL/wIKCgoLEBARdtHR0vri4uP/39/g/97e
+ 3//e3t//3t7f/93d3//c3N7/29vd/9vb3P/a2tz/2tnb/9nZ2v/Y2Nn/19fY/9bW1//V1db/09PU/9HR
+ 0//Ozs7/ycnJ/8LCwv+vr6//t7e3/9XV1f3MzMzwzs7Oaevr6wb///8BAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wEAAAAKDw8PddLS
+ 0vvi4uL/39/f/97e3v/d3d3/3d3d/9zc3P/a2tr/2dnZ/9nZ2f/X19f/1tbW/9fX1//V1dX/1dXV/9TU
+ 1P/R0dH/z8/P/8zMzP/Gxsb/vr6+/7W1tf+lpaX/u7u7/L6+vv/CwsJxAAAAAP///wMAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//
+ /wEAAAAKERERdNPT0/rg4OD/3t7e/93d3f/b29v/2tra/9nZ2f/X19f/1tbW/9XV1f/U1NT/09PT/9PT
+ 0//R0dH/0NDQ/8/Pz//MzMz/ycnJ/8XFxf++vr7/tLS0/62trf+ioqL9tbW1/7a2ttPo6OgL////AwAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAADGRkZPOLi4vfd3d3929vb/dra2v3X19f91tbW/dTU1P3S0tL9z8/P/c/P
+ z/3Ozs79zMzM/cvLy/3IyMj9xcXF/cPDw/2+vr79ubm5/bW1tf2tra39o6Oj/Z2dnf6rq6vjubm5d+vr
+ 6w3///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAtra2B/f392r29vZ19vb2dfb29nX19fV19PT0dfT0
+ 9HX09PR18fHxdfHx8XXx8fF18fHxde/v73Xt7e116+vrdevr63Xo6Oh15+fndeTk5HXg4OB14eHhb+vr
+ 60729vYPAAAAAP///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
+ AAAAAAAAAAAAAP//////////////////////gAAAAD////8AAAAAH/+A/wAAAAAf/wD/AAAAAB//AP8A
+ AAAAH/8A/wAAAAAf/wD/gAAAAB//AP8AAAAAH/+A/gAAAAAf/wD+AAAAAB/+AP4AAAAAH/4A/gAAAAAf
+ /gD+AAAAAB/+AP4AAAAAH/4A/gAAAAAf/gDAAAAAAB/+AIAAAAAAH8AAgAAAAAAfgACAAAAAAB+AAIAA
+ AAAAH4AA8AAAAAAfgAD+AAAAAB/wAP4AAAAAH/4A/gAAAAAf/gD+AAAAAAP+AP4AAAAAAf4A/gAAAAAD
+ /gD8AAAAAAP+APgAAAAAB/wA8AAAAAAP+ADwAAAAAB/wAPAAAAAAD/AA8AAAAAAH8ADwAAAAAAPwAPAA
+ AAAAA/AA8AAAAAAB8ADwAAAAAAPwAPAAAAAAw/AA+AAAAAP/8AD/AAAAB//4AP+AAAAH//8A/4AAAB//
+ /4D/gAAAP///gP+AAAA///+A/4AAAP///4D/////////gA==
+
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.Designer.cs b/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..5270b46bb6deed7275144a11adec9504006b32f4
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.Designer.cs
@@ -0,0 +1,264 @@
+namespace PDFPatcher.Functions
+{
+ partial class AutoBookmarkForm
+ {
+ ///
+ /// Required designer variable.
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// Clean up any resources being used.
+ ///
+ /// true if managed resources should be disposed; otherwise, false.
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region Windows Form Designer generated code
+
+ ///
+ /// Required method for Designer support - do not modify
+ /// the contents of this method with the code editor.
+ ///
+ private void InitializeComponent () {
+ System.Windows.Forms.ToolStripDropDownButton toolStripDropDownButton1;
+ this._LoadListButton = new System.Windows.Forms.ToolStripMenuItem();
+ this._SaveListButton = new System.Windows.Forms.ToolStripMenuItem();
+ this._BookmarkConditionBox = new BrightIdeasSoftware.ObjectListView();
+ this._ConditionColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._LevelColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._BoldColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ItalicColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._ColorColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._OpenColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._GoToTopColumn = ((BrightIdeasSoftware.OLVColumn)(new BrightIdeasSoftware.OLVColumn()));
+ this._AutoBookmarkButton = new System.Windows.Forms.Button();
+ this._MergeAdjacentTitleBox = new System.Windows.Forms.CheckBox();
+ this._Toolbar = new System.Windows.Forms.ToolStrip();
+ this._SetPatternMenu = new System.Windows.Forms.ToolStripDropDownButton();
+ this._RemoveButton = new System.Windows.Forms.ToolStripButton();
+ this._KeepExistingBookmarksBox = new System.Windows.Forms.CheckBox();
+ toolStripDropDownButton1 = new System.Windows.Forms.ToolStripDropDownButton();
+ ((System.ComponentModel.ISupportInitialize)(this._BookmarkConditionBox)).BeginInit();
+ this._Toolbar.SuspendLayout();
+ this.SuspendLayout();
+ //
+ // toolStripDropDownButton1
+ //
+ toolStripDropDownButton1.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ this._LoadListButton,
+ this._SaveListButton});
+ toolStripDropDownButton1.Image = global::PDFPatcher.Properties.Resources.TextFile;
+ toolStripDropDownButton1.ImageTransparentColor = System.Drawing.Color.Magenta;
+ toolStripDropDownButton1.Name = "toolStripDropDownButton1";
+ toolStripDropDownButton1.Size = new System.Drawing.Size(109, 22);
+ toolStripDropDownButton1.Text = "识别条件列表";
+ //
+ // _LoadListButton
+ //
+ this._LoadListButton.Image = global::PDFPatcher.Properties.Resources.OpenFile;
+ this._LoadListButton.Name = "_LoadListButton";
+ this._LoadListButton.Size = new System.Drawing.Size(180, 22);
+ this._LoadListButton.Text = "加载条件列表...";
+ //
+ // _SaveListButton
+ //
+ this._SaveListButton.Image = global::PDFPatcher.Properties.Resources.Save;
+ this._SaveListButton.Name = "_SaveListButton";
+ this._SaveListButton.Size = new System.Drawing.Size(180, 22);
+ this._SaveListButton.Text = "保存条件列表...";
+ //
+ // _BookmarkConditionBox
+ //
+ this._BookmarkConditionBox.AllColumns.Add(this._ConditionColumn);
+ this._BookmarkConditionBox.AllColumns.Add(this._LevelColumn);
+ this._BookmarkConditionBox.AllColumns.Add(this._BoldColumn);
+ this._BookmarkConditionBox.AllColumns.Add(this._ItalicColumn);
+ this._BookmarkConditionBox.AllColumns.Add(this._ColorColumn);
+ this._BookmarkConditionBox.AllColumns.Add(this._OpenColumn);
+ this._BookmarkConditionBox.AllColumns.Add(this._GoToTopColumn);
+ this._BookmarkConditionBox.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this._BookmarkConditionBox.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this._BookmarkConditionBox.CellEditUseWholeCell = false;
+ this._BookmarkConditionBox.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] {
+ this._ConditionColumn,
+ this._LevelColumn,
+ this._BoldColumn,
+ this._ItalicColumn,
+ this._ColorColumn,
+ this._OpenColumn,
+ this._GoToTopColumn});
+ this._BookmarkConditionBox.Cursor = System.Windows.Forms.Cursors.Default;
+ this._BookmarkConditionBox.GridLines = true;
+ this._BookmarkConditionBox.HideSelection = false;
+ this._BookmarkConditionBox.Location = new System.Drawing.Point(14, 24);
+ this._BookmarkConditionBox.Name = "_BookmarkConditionBox";
+ this._BookmarkConditionBox.ShowGroups = false;
+ this._BookmarkConditionBox.Size = new System.Drawing.Size(453, 143);
+ this._BookmarkConditionBox.TabIndex = 1;
+ this._BookmarkConditionBox.UseCompatibleStateImageBehavior = false;
+ this._BookmarkConditionBox.View = System.Windows.Forms.View.Details;
+ //
+ // _ConditionColumn
+ //
+ this._ConditionColumn.IsEditable = false;
+ this._ConditionColumn.Text = "识别条件";
+ this._ConditionColumn.Width = 148;
+ //
+ // _LevelColumn
+ //
+ this._LevelColumn.Text = "书签级别";
+ //
+ // _BoldColumn
+ //
+ this._BoldColumn.CheckBoxes = true;
+ this._BoldColumn.Text = "粗体";
+ this._BoldColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._BoldColumn.Width = 37;
+ //
+ // _ItalicColumn
+ //
+ this._ItalicColumn.CheckBoxes = true;
+ this._ItalicColumn.Text = "斜体";
+ this._ItalicColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._ItalicColumn.Width = 37;
+ //
+ // _ColorColumn
+ //
+ this._ColorColumn.IsEditable = false;
+ this._ColorColumn.Text = "颜色";
+ //
+ // _OpenColumn
+ //
+ this._OpenColumn.CheckBoxes = true;
+ this._OpenColumn.Text = "展开";
+ this._OpenColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._OpenColumn.Width = 37;
+ //
+ // _GoToTopColumn
+ //
+ this._GoToTopColumn.CheckBoxes = true;
+ this._GoToTopColumn.Text = "到页首";
+ this._GoToTopColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._GoToTopColumn.Width = 49;
+ //
+ // _AutoBookmarkButton
+ //
+ this._AutoBookmarkButton.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right)));
+ this._AutoBookmarkButton.Image = global::PDFPatcher.Properties.Resources.AutoBookmark;
+ this._AutoBookmarkButton.Location = new System.Drawing.Point(367, 4);
+ this._AutoBookmarkButton.Name = "_AutoBookmarkButton";
+ this._AutoBookmarkButton.Size = new System.Drawing.Size(101, 23);
+ this._AutoBookmarkButton.TabIndex = 4;
+ this._AutoBookmarkButton.Text = "生成书签(&K)";
+ this._AutoBookmarkButton.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText;
+ this._AutoBookmarkButton.UseVisualStyleBackColor = true;
+ this._AutoBookmarkButton.Click += new System.EventHandler(this._AutoBookmarkButton_Click);
+ //
+ // _MergeAdjacentTitleBox
+ //
+ this._MergeAdjacentTitleBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this._MergeAdjacentTitleBox.AutoSize = true;
+ this._MergeAdjacentTitleBox.Checked = true;
+ this._MergeAdjacentTitleBox.CheckState = System.Windows.Forms.CheckState.Checked;
+ this._MergeAdjacentTitleBox.Location = new System.Drawing.Point(14, 171);
+ this._MergeAdjacentTitleBox.Margin = new System.Windows.Forms.Padding(2, 3, 2, 3);
+ this._MergeAdjacentTitleBox.Name = "_MergeAdjacentTitleBox";
+ this._MergeAdjacentTitleBox.Size = new System.Drawing.Size(168, 16);
+ this._MergeAdjacentTitleBox.TabIndex = 5;
+ this._MergeAdjacentTitleBox.Text = "合并同字体尺寸的相邻标题";
+ this._MergeAdjacentTitleBox.UseVisualStyleBackColor = true;
+ //
+ // _Toolbar
+ //
+ this._Toolbar.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
+ toolStripDropDownButton1,
+ this._SetPatternMenu,
+ this._RemoveButton});
+ this._Toolbar.Location = new System.Drawing.Point(0, 0);
+ this._Toolbar.Name = "_Toolbar";
+ this._Toolbar.Size = new System.Drawing.Size(485, 25);
+ this._Toolbar.TabIndex = 6;
+ //
+ // _SetPatternMenu
+ //
+ this._SetPatternMenu.Enabled = false;
+ this._SetPatternMenu.Image = global::PDFPatcher.Properties.Resources.SelectItem;
+ this._SetPatternMenu.Name = "_SetPatternMenu";
+ this._SetPatternMenu.Size = new System.Drawing.Size(109, 22);
+ this._SetPatternMenu.Text = "文本识别模式";
+ //
+ // _RemoveButton
+ //
+ this._RemoveButton.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image;
+ this._RemoveButton.Enabled = false;
+ this._RemoveButton.Image = global::PDFPatcher.Properties.Resources.Delete;
+ this._RemoveButton.ImageTransparentColor = System.Drawing.Color.Magenta;
+ this._RemoveButton.Name = "_RemoveButton";
+ this._RemoveButton.Size = new System.Drawing.Size(23, 22);
+ this._RemoveButton.Text = "删除";
+ this._RemoveButton.Click += new System.EventHandler(this._RemoveButton_Click);
+ //
+ // _KeepExistingBookmarksBox
+ //
+ this._KeepExistingBookmarksBox.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
+ this._KeepExistingBookmarksBox.AutoSize = true;
+ this._KeepExistingBookmarksBox.Location = new System.Drawing.Point(223, 171);
+ this._KeepExistingBookmarksBox.Name = "_KeepExistingBookmarksBox";
+ this._KeepExistingBookmarksBox.Size = new System.Drawing.Size(96, 16);
+ this._KeepExistingBookmarksBox.TabIndex = 7;
+ this._KeepExistingBookmarksBox.Text = "保留原有书签";
+ this._KeepExistingBookmarksBox.UseVisualStyleBackColor = true;
+ //
+ // AutoBookmarkForm
+ //
+ this.AcceptButton = this._AutoBookmarkButton;
+ this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F);
+ this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
+ this.ClientSize = new System.Drawing.Size(485, 195);
+ this.Controls.Add(this._KeepExistingBookmarksBox);
+ this.Controls.Add(this._MergeAdjacentTitleBox);
+ this.Controls.Add(this._AutoBookmarkButton);
+ this.Controls.Add(this._BookmarkConditionBox);
+ this.Controls.Add(this._Toolbar);
+ this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.SizableToolWindow;
+ this.MaximizeBox = false;
+ this.MinimizeBox = false;
+ this.Name = "AutoBookmarkForm";
+ this.ShowIcon = false;
+ this.ShowInTaskbar = false;
+ this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show;
+ this.Text = "自动生成书签";
+ ((System.ComponentModel.ISupportInitialize)(this._BookmarkConditionBox)).EndInit();
+ this._Toolbar.ResumeLayout(false);
+ this._Toolbar.PerformLayout();
+ this.ResumeLayout(false);
+ this.PerformLayout();
+
+ }
+
+ #endregion
+ private BrightIdeasSoftware.ObjectListView _BookmarkConditionBox;
+ private BrightIdeasSoftware.OLVColumn _ConditionColumn;
+ private System.Windows.Forms.Button _AutoBookmarkButton;
+ private BrightIdeasSoftware.OLVColumn _LevelColumn;
+ private BrightIdeasSoftware.OLVColumn _BoldColumn;
+ private BrightIdeasSoftware.OLVColumn _ItalicColumn;
+ private BrightIdeasSoftware.OLVColumn _ColorColumn;
+ private BrightIdeasSoftware.OLVColumn _OpenColumn;
+ private System.Windows.Forms.CheckBox _MergeAdjacentTitleBox;
+ private BrightIdeasSoftware.OLVColumn _GoToTopColumn;
+ private System.Windows.Forms.ToolStrip _Toolbar;
+ private System.Windows.Forms.ToolStripMenuItem _LoadListButton;
+ private System.Windows.Forms.ToolStripMenuItem _SaveListButton;
+ private System.Windows.Forms.CheckBox _KeepExistingBookmarksBox;
+ private System.Windows.Forms.ToolStripDropDownButton _SetPatternMenu;
+ private System.Windows.Forms.ToolStripButton _RemoveButton;
+ }
+}
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.cs b/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.cs
new file mode 100644
index 0000000000000000000000000000000000000000..dd4f393aae7a566d7238f45abc76419091bd2be5
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.cs
@@ -0,0 +1,223 @@
+using System;
+using System.Collections.Generic;
+using System.Drawing;
+using System.Windows.Forms;
+using BrightIdeasSoftware;
+using PDFPatcher.Common;
+using PDFPatcher.Functions.Editor;
+using PDFPatcher.Model;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class AutoBookmarkForm : DraggableForm
+ {
+ List _list;
+ readonly Controller _controller;
+
+ internal AutoBookmarkForm() {
+ InitializeComponent();
+ }
+
+ internal AutoBookmarkForm(Controller controller) : this() {
+ _controller = controller;
+ this.OnFirstLoad(OnLoad);
+ }
+
+ void OnLoad() {
+ MinimumSize = Size;
+ _Toolbar.ScaleIcons(16);
+
+ _ConditionColumn.AsTyped(c => {
+ c.AspectGetter = o => $"字体为{o.FontName} 尺寸为{o.FontSize}{(o.MatchPattern != null ? o.MatchPattern.ToString() : String.Empty)}";
+ });
+ _LevelColumn.CellEditUseWholeCell = true;
+ _LevelColumn.AsTyped(c => {
+ c.AspectGetter = o => o.Level;
+ c.AspectPutter = (o, v) => o.Level = Convert.ToInt32(v).LimitInRange(1, 10);
+ });
+ _BoldColumn.AsTyped(c => {
+ c.AspectGetter = o => o.Bookmark.IsBold;
+ c.AspectPutter = (o, v) => o.Bookmark.IsBold = (bool)v;
+ });
+ _ItalicColumn.AsTyped(c => {
+ c.AspectGetter = o => o.Bookmark.IsItalic;
+ c.AspectPutter = (o, v) => o.Bookmark.IsItalic = (bool)v;
+ });
+ _ColorColumn.AsTyped(c => {
+ c.AspectGetter = o => "点击设置颜色";
+ });
+ _OpenColumn.AsTyped(c => {
+ c.AspectGetter = o => o.Bookmark.IsOpened;
+ c.AspectPutter = (o, v) => o.Bookmark.IsOpened = (bool)v;
+ });
+ _GoToTopColumn.AsTyped(c => {
+ c.AspectGetter = o => o.Bookmark.GoToTop;
+ c.AspectPutter = (o, v) => o.Bookmark.GoToTop = (bool)v;
+ });
+ _BookmarkConditionBox.ScaleColumnWidths();
+ _BookmarkConditionBox.IsSimpleDragSource = true;
+ _BookmarkConditionBox.IsSimpleDropSink = true;
+ _BookmarkConditionBox.CellClick += (s, args) => {
+ if (args.ColumnIndex == _ColorColumn.Index) {
+ var b = ((EditModel.AutoBookmarkStyle)args.Model).Bookmark;
+ this.ShowCommonDialog(
+ f => f.Color = b.ForeColor == Color.Transparent ? Color.White : b.ForeColor,
+ f => {
+ b.ForeColor = f.Color == Color.White || f.Color == Color.Black ? Color.Transparent : f.Color;
+ _BookmarkConditionBox.RefreshItem(args.Item);
+ }
+ );
+ }
+ };
+ _BookmarkConditionBox.RowFormatter = (r) => {
+ var b = ((EditModel.AutoBookmarkStyle)r.RowObject).Bookmark;
+ r.UseItemStyleForSubItems = false;
+ r.SubItems[_ColorColumn.Index].ForeColor = b.ForeColor == Color.Transparent ? _BookmarkConditionBox.ForeColor : b.ForeColor;
+ };
+ _BookmarkConditionBox.SelectionChanged += _BookmarkConditionBox_SelectionChanged;
+ _LoadListButton.Click += _LoadListButton_Click;
+ _SaveListButton.Click += _SaveListButton_Click;
+
+ QuickSelectCommand.RegisterMenuItemsWithPattern(_SetPatternMenu.DropDownItems);
+ _SetPatternMenu.DropDownItems.AddRange(new ToolStripItem[] {
+ new ToolStripSeparator(),
+ new ToolStripMenuItem("自定义文本匹配模式...") {
+ Tag = "CustomPattern"
+ },
+ new ToolStripMenuItem("清除文本匹配模式") {
+ Tag = "ClearPattern",
+ Image = Properties.Resources.Delete
+ }
+ });
+ _SetPatternMenu.DropDownItemClicked += _SetPattern_DropDownItemClicked;
+ }
+
+ void _BookmarkConditionBox_SelectionChanged(object sender, EventArgs e) {
+ _SetPatternMenu.Enabled = _RemoveButton.Enabled = _BookmarkConditionBox.SelectedItems.Count > 0;
+ }
+
+ void _SetPattern_DropDownItemClicked(object sender, ToolStripItemClickedEventArgs e) {
+ if (e.ClickedItem.Tag is MatchPattern p) {
+ SetMatchPatternToSelectedBookmarkStyles(p);
+ return;
+ }
+ if (e.ClickedItem.Tag is string s) {
+ switch (s) {
+ case "ClearPattern":
+ SetMatchPatternToSelectedBookmarkStyles(null);
+ return;
+ case "CustomPattern":
+ p = (_BookmarkConditionBox.SelectedObject as EditModel.AutoBookmarkStyle)?.MatchPattern;
+ this.ShowDialog(f => {
+ if (p != null) {
+ f.Pattern = p.Text;
+ f.MatchCase = p.MatchCase;
+ f.FullMatch = p.FullMatch;
+ }
+ }, f => {
+ SetMatchPatternToSelectedBookmarkStyles(f.Pattern.Length != 0 ? new MatchPattern(f.Pattern, f.MatchCase, f.FullMatch, true) : null);
+ });
+ return;
+ }
+ }
+ }
+
+ void SetMatchPatternToSelectedBookmarkStyles(MatchPattern p) {
+ foreach (EditModel.AutoBookmarkStyle item in _BookmarkConditionBox.SelectedObjects) {
+ item.MatchPattern = p;
+ }
+ _BookmarkConditionBox.RefreshObjects(_BookmarkConditionBox.SelectedObjects);
+ }
+
+ internal void SetValues(List list) {
+ _BookmarkConditionBox.Objects = _list = list;
+ }
+
+ void _RemoveButton_Click(object sender, EventArgs e) {
+ _BookmarkConditionBox.SelectedObjects.ForEach(i => _list.Remove(i));
+ _BookmarkConditionBox.RemoveObjects(_BookmarkConditionBox.SelectedObjects);
+ }
+
+ void _AutoBookmarkButton_Click(object sender, EventArgs e) {
+ SyncList();
+ _controller.AutoBookmark(_list, _MergeAdjacentTitleBox.Checked, _KeepExistingBookmarksBox.Checked);
+ }
+
+ void _SaveListButton_Click(object sender, EventArgs e) {
+ this.ShowCommonDialog(d => {
+ d.Title = "请输入需要保存自动书签格式列表的文件名";
+ d.Filter = Constants.FileExtensions.XmlFilter;
+ d.DefaultExt = Constants.FileExtensions.Xml;
+ }, d => {
+ try {
+ SyncList();
+ using (var w = new FilePath(d.FileName).OpenTextWriter(false, null)) {
+ Serialize(_list, w);
+ }
+ }
+ catch (Exception ex) {
+ this.ErrorBox("保存自动书签格式列表时出现错误", ex);
+ }
+ });
+ }
+
+ static void Serialize(List list, System.IO.StreamWriter writer) {
+ using (var x = System.Xml.XmlWriter.Create(writer)) {
+ x.WriteStartDocument();
+ x.WriteStartElement("autoBookmark");
+ foreach (var item in list) {
+ x.WriteStartElement("style");
+ x.WriteAttributeString("fontName", item.FontName);
+ x.WriteAttributeString("fontSize", item.FontSize.ToText());
+ x.WriteAttributeString("level", item.Level.ToText());
+ item.Bookmark.WriteXml(x);
+ item.MatchPattern?.WriteXml(x);
+ x.WriteEndElement();
+ }
+ x.WriteEndElement();
+ x.WriteEndDocument();
+ }
+ }
+
+ void _LoadListButton_Click(object sender, EventArgs e) {
+ this.ShowCommonDialog(d => {
+ d.Title = "请选择需要打开的自动书签格式列表";
+ d.Filter = Constants.FileExtensions.XmlFilter;
+ d.DefaultExt = Constants.FileExtensions.Xml;
+ }, d => {
+ try {
+ SetValues(Deserialize(d.FileName));
+ }
+ catch (Exception ex) {
+ this.ErrorBox("加载自动书签格式列表时出现错误", ex);
+ }
+ });
+ }
+
+ static List Deserialize(FilePath path) {
+ var doc = new System.Xml.XmlDocument();
+ doc.Load(path);
+ var l = new List();
+ foreach (System.Xml.XmlElement item in doc.DocumentElement.GetElementsByTagName("style")) {
+ var s = new EditModel.AutoBookmarkStyle(
+ item.GetValue("level", 1),
+ item.GetValue("fontName"),
+ item.GetValue("fontSize", 0));
+ s.Bookmark.ReadXml(item.GetElement("bookmark").CreateNavigator().ReadSubtree());
+ var p = item.GetElement("pattern");
+ if (p != null) {
+ s.MatchPattern = new Model.MatchPattern();
+ s.MatchPattern.ReadXml(p.CreateNavigator().ReadSubtree());
+ }
+
+ l.Add(s);
+ }
+ return l;
+ }
+
+ void SyncList() {
+ _list.Clear();
+ _list.AddRange(new TypedObjectListView(_BookmarkConditionBox).Objects);
+ }
+ }
+}
diff --git a/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.resx b/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.resx
new file mode 100644
index 0000000000000000000000000000000000000000..4140e094b4c96c60bc06a4fafe0e6b4b35d1e5be
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/AutoBookmarkForm.resx
@@ -0,0 +1,126 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ False
+
+
+ 17, 17
+
+
\ No newline at end of file
diff --git a/pdfpatcher/App/Functions/Editor/BookmarkEditorView.Designer.cs b/pdfpatcher/App/Functions/Editor/BookmarkEditorView.Designer.cs
new file mode 100644
index 0000000000000000000000000000000000000000..2c787fe4bb77fc8d5901dd108833d0dc6de72f3d
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/BookmarkEditorView.Designer.cs
@@ -0,0 +1,126 @@
+namespace PDFPatcher.Functions
+{
+ partial class BookmarkEditorView
+ {
+ ///
+ /// 必需的设计器变量。
+ ///
+ private System.ComponentModel.IContainer components = null;
+
+ ///
+ /// 清理所有正在使用的资源。
+ ///
+ /// 如果应释放托管资源,为 true;否则为 false。
+ protected override void Dispose (bool disposing) {
+ if (disposing && (components != null)) {
+ components.Dispose ();
+ }
+ base.Dispose (disposing);
+ }
+
+ #region 组件设计器生成的代码
+
+ ///
+ /// 设计器支持所需的方法 - 不要
+ /// 使用代码编辑器修改此方法的内容。
+ ///
+ private void InitializeComponent () {
+ this.components = new System.ComponentModel.Container ();
+ this._BookmarkNameColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._BookmarkOpenColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._BookmarkPageColumn = new BrightIdeasSoftware.OLVColumn ();
+ this._ActionColumn = new BrightIdeasSoftware.OLVColumn ();
+ ((System.ComponentModel.ISupportInitialize)(this)).BeginInit ();
+ this.SuspendLayout ();
+ //
+ // _BookmarkBox
+ //
+ this.AllColumns.Add (this._BookmarkNameColumn);
+ this.AllColumns.Add (this._BookmarkOpenColumn);
+ this.AllColumns.Add (this._BookmarkPageColumn);
+ this.AllColumns.Add (this._ActionColumn);
+ this.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
+ | System.Windows.Forms.AnchorStyles.Left)
+ | System.Windows.Forms.AnchorStyles.Right)));
+ this.CellEditActivation = BrightIdeasSoftware.ObjectListView.CellEditActivateMode.SingleClick;
+ this.Columns.AddRange (new System.Windows.Forms.ColumnHeader[] {
+ this._BookmarkNameColumn,
+ this._BookmarkOpenColumn,
+ this._BookmarkPageColumn,
+ this._ActionColumn});
+ this.CopySelectionOnControlC = false;
+ this.Cursor = System.Windows.Forms.Cursors.Default;
+ this.GridLines = true;
+ this.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable;
+ this.HideSelection = false;
+ this.IsSimpleDragSource = true;
+ this.IsSimpleDropSink = true;
+ this.LabelEdit = true;
+ this.Location = new System.Drawing.Point (0, 0);
+ this.Name = "_BookmarkBox";
+ this.OwnerDraw = true;
+ this.RevealAfterExpand = false;
+ this.ShowGroups = false;
+ this.Size = new System.Drawing.Size (408, 208);
+ this.TabIndex = 0;
+ this.UseCellFormatEvents = false;
+ this.UseHotItem = false;
+ this.UseCompatibleStateImageBehavior = false;
+ this.UseHyperlinks = true;
+ this.View = System.Windows.Forms.View.Details;
+ this.VirtualMode = true;
+ this.BeforeLabelEdit += new System.Windows.Forms.LabelEditEventHandler(this.BookmarkEditorView_BeforeLabelEdit);
+ this.AfterLabelEdit += new System.Windows.Forms.LabelEditEventHandler (this._BookmarkBox_AfterLabelEdit);
+ this.FormatRow += new System.EventHandler (this._BookmarkBox_FormatRow);
+ this.HyperlinkClicked += new System.EventHandler(BookmarkEditor_CellClick);
+ this.HotItemChanged += new System.EventHandler (BookmarkEditor_HotItemChanged);
+ //
+ // _BookmarkNameColumn
+ //
+ this._BookmarkNameColumn.AspectName = "";
+ this._BookmarkNameColumn.Text = "书签文本";
+ this._BookmarkNameColumn.Width = 160;
+ //
+ // _BookmarkOpenColumn
+ //
+ this._BookmarkOpenColumn.AspectName = "";
+ this._BookmarkOpenColumn.CheckBoxes = true;
+ this._BookmarkOpenColumn.DisplayIndex = 2;
+ this._BookmarkOpenColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._BookmarkOpenColumn.Text = "打开";
+ this._BookmarkOpenColumn.TextAlign = System.Windows.Forms.HorizontalAlignment.Center;
+ this._BookmarkOpenColumn.Width = 40;
+ //
+ // _BookmarkPageColumn
+ //
+ this._BookmarkPageColumn.AspectName = "";
+ this._BookmarkPageColumn.DisplayIndex = 1;
+ this._BookmarkPageColumn.HeaderTextAlign = System.Windows.Forms.HorizontalAlignment.Right;
+ this._BookmarkPageColumn.Text = "页码";
+ this._BookmarkPageColumn.Width = 42;
+ //
+ // _ActionColumn
+ //
+ this._ActionColumn.AspectName = "";
+ this._ActionColumn.Hyperlink = true;
+ this._ActionColumn.IsEditable = false;
+ this._ActionColumn.Text = "书签动作";
+ this._ActionColumn.Width = 100;
+ //
+ // Editor
+ //
+ this.Name = "BookmarkEditor";
+ this.Size = new System.Drawing.Size (408, 208);
+ ((System.ComponentModel.ISupportInitialize)(this)).EndInit ();
+ this.ResumeLayout (false);
+
+ }
+
+ #endregion
+
+ private BrightIdeasSoftware.OLVColumn _BookmarkNameColumn;
+ private BrightIdeasSoftware.OLVColumn _BookmarkOpenColumn;
+ private BrightIdeasSoftware.OLVColumn _BookmarkPageColumn;
+ private BrightIdeasSoftware.OLVColumn _ActionColumn;
+ }
+}
diff --git a/pdfpatcher/App/Functions/Editor/BookmarkEditorView.cs b/pdfpatcher/App/Functions/Editor/BookmarkEditorView.cs
new file mode 100644
index 0000000000000000000000000000000000000000..206588e9eaa3d77f027afca38e34b7557dd997fd
--- /dev/null
+++ b/pdfpatcher/App/Functions/Editor/BookmarkEditorView.cs
@@ -0,0 +1,615 @@
+using System;
+using System.Collections.Generic;
+using System.ComponentModel;
+using System.Diagnostics;
+using System.Drawing;
+using System.Windows.Forms;
+using System.Xml;
+using BrightIdeasSoftware;
+using PDFPatcher.Common;
+using PDFPatcher.Model;
+using PDFPatcher.Processor;
+
+namespace PDFPatcher.Functions
+{
+ sealed partial class BookmarkEditorView : TreeListView
+ {
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal static List _copiedBookmarks;
+
+ [EditorBrowsable(EditorBrowsableState.Never)]
+ internal UndoManager Undo { get; set; }
+
+ public bool OperationAffectsDescendants { get; set; }
+ public OLVColumn BookmarkOpenColumn => _BookmarkOpenColumn;
+ public OLVColumn BookmarkNameColumn => _BookmarkNameColumn;
+ public OLVColumn BookmarkPageColumn => _BookmarkPageColumn;
+ public bool HasMarker => _markers.Count > 0;
+ public bool IsLabelEditing { get; private set; }
+
+ readonly Dictionary _markers = new Dictionary();
+
+ public BookmarkEditorView() {
+ InitializeComponent();
+ InitEditorBox();
+ }
+
+ private void InitEditorBox() {
+ if (IsDesignMode) {
+ return;
+ }
+ UseOverlays = false;
+ #region 修复树视图无法正确选择节点的问题
+ SmallImageList = new ImageList();
+ #endregion
+ this.SetTreeViewLine();
+ this.FixEditControlWidth();
+ CanExpandGetter = (object x) => x is BookmarkElement e && e.HasSubBookmarks;
+ ChildrenGetter = (object x) => ((BookmarkElement)x).SubBookmarks;
+ _BookmarkNameColumn.AutoCompleteEditorMode = AutoCompleteMode.Suggest;
+ //this.SelectedRowDecoration = new RowBorderDecoration ()
+ //{
+ // FillBrush = new SolidBrush (Color.FromArgb (64, SystemColors.Highlight)),
+ // BoundsPadding = new Size (0, 0),
+ // CornerRounding = 2,
+ // BorderPen = new Pen (Color.FromArgb (216, SystemColors.Highlight))
+ //};
+ new TypedColumn(_BookmarkNameColumn) {
+ AspectGetter = (e) => e.Title,
+ AspectPutter = (e, newValue) => {
+ var s = newValue as string;
+ if (e.Title == s) {
+ return;
+ }
+ var p = new ReplaceTitleTextProcessor(s);
+ Undo?.AddUndo("编辑书签文本", p.Process(e));
+ }
+ };
+ new TypedColumn(_BookmarkOpenColumn) {
+ AspectGetter = (e) => e == null ? false : (object)e.IsOpen,
+ AspectPutter = (e, newValue) => {
+ if (e == null || e.HasSubBookmarks == false) {
+ return;
+ }
+ var p = new BookmarkOpenStatusProcessor((bool)newValue);
+ Undo.AddUndo(p.Name, p.Process(e));
+ }
+ };
+ new TypedColumn(_BookmarkPageColumn) {
+ AspectGetter = (e) => {
+ if (e == null) {
+ return 0;
+ }
+ int p = e.GetValue(Constants.DestinationAttributes.Page, 0);
+ if (e.HasAttribute(Constants.DestinationAttributes.FirstPageNumber)) {
+ int o = e.GetValue(Constants.DestinationAttributes.FirstPageNumber, 0);
+ if (o > 0) {
+ p += o;
+ e.RemoveAttribute(Constants.DestinationAttributes.FirstPageNumber);
+ }
+ }
+ return p;
+ },
+ AspectPutter = (e, value) => {
+ if (e == null) {
+ return;
+ }
+ if (value.ToString().TryParse(out int n)) {
+ var p = new ChangePageNumberProcessor(n, true, false);
+ Undo.AddUndo(p.Name, p.Process(e));
+ }
+ }
+ };
+ _ActionColumn.AspectGetter = (object x) => {
+ var e = x as XmlElement;
+ if (e == null) {
+ return String.Empty;
+ }
+ var a = e.GetAttribute(Constants.DestinationAttributes.Action);
+ if (String.IsNullOrEmpty(a)) {
+ return e.HasAttribute(Constants.DestinationAttributes.Page) ? Constants.ActionType.Goto : "无";
+ }
+ return a;
+ };
+ }
+ protected override void OnBeforeSorting(BeforeSortingEventArgs e) {
+ e.Canceled = true; // 禁止排序
+ base.OnBeforeSorting(e);
+ }
+ protected override void OnItemActivate(EventArgs e) {
+ base.OnItemActivate(e);
+ EditSubItem(SelectedItem, 0);
+ }
+ #region 拖放操作
+ protected override void OnCanDrop(OlvDropEventArgs args) {
+ var o = args.DataObject as DataObject;
+ if (o == null) {
+ return;
+ }
+ var f = o.GetFileDropList();
+ foreach (var item in f) {
+ if (FileHelper.HasExtension(item, Constants.FileExtensions.Xml)
+ || FileHelper.HasExtension(item, Constants.FileExtensions.Pdf)) {
+ args.Handled = true;
+ args.DropTargetLocation = DropTargetLocation.Background;
+ args.Effect = DragDropEffects.Copy;
+ args.InfoMessage = "打开文件" + item;
+ return;
+ }
+ }
+ base.OnCanDrop(args);
+ }
+ protected override void OnModelCanDrop(ModelDropEventArgs e) {
+ var si = e.SourceModels;
+ var ti = e.TargetModel as XmlElement;
+ if (si == null || si.Count == 0 || e.TargetModel == null) {
+ e.Effect = DragDropEffects.None;
+ return;
+ }
+ var copy = (Control.ModifierKeys & Keys.Control) != Keys.None || (e.SourceModels[0] as XmlElement).OwnerDocument != ti.OwnerDocument;
+ if (copy == false) {
+ if (e.DropTargetItem.Selected) {
+ e.Effect = DragDropEffects.None;
+ return;
+ }
+ foreach (XmlElement item in si) {
+ if (IsAncestorOrSelf(item, ti)) {
+ e.Effect = DragDropEffects.None;
+ e.InfoMessage = "目标书签不能是源书签的子书签。";
+ return;
+ }
+ }
+ }
+ var d = e.DropTargetItem;
+ var ml = e.MouseLocation;
+ var child = ml.X > d.Position.X + d.GetBounds(ItemBoundsPortion.ItemOnly).Width / 2;
+ var append = ml.Y > d.Position.Y + d.Bounds.Height / 2;
+ if (child == false && copy == false) {
+ var xi = e.DropTargetIndex + (append ? 1 : -1);
+ if (xi > -1 && xi < e.ListView.Items.Count
+ && e.ListView.Items[xi].Selected
+ && ti.ParentNode == (e.ListView.GetModelObject(xi) as XmlElement).ParentNode) {
+ e.Effect = DragDropEffects.None;
+ return;
+ }
+ }
+ e.Effect = copy ? DragDropEffects.Copy : DragDropEffects.Move;
+ e.InfoMessage = String.Concat((copy ? "复制" : "移动"), "到", (child ? "所有子书签" : String.Empty), (append ? "后面" : "前面"));
+ base.OnModelCanDrop(e);
+ }
+
+ protected override void OnModelDropped(ModelDropEventArgs args) {
+ base.OnModelDropped(args);
+ var t = args.TargetModel as BookmarkElement;
+ var se = GetSelectedElements(args.SourceListView as BrightIdeasSoftware.TreeListView, false);
+ if (se == null) {
+ return;
+ }
+ var ti = args.TargetModel as BookmarkElement;
+ var d = args.DropTargetItem;
+ var ml = args.MouseLocation;
+ Freeze();
+ var child = ml.X > d.Position.X + d.GetBounds(ItemBoundsPortion.ItemOnly).Width / 2;
+ var append = ml.Y > d.Position.Y + d.Bounds.Height / 2;
+ var copy = (Control.ModifierKeys & Keys.Control) != Keys.None || (args.SourceModels[0] as BookmarkElement).OwnerDocument != ti.OwnerDocument;
+ var deepCopy = copy && (OperationAffectsDescendants || (Control.ModifierKeys & Keys.Shift) != Keys.None);
+ var tii = TopItemIndex;
+ CopyOrMoveElement(se, ti, child, append, copy, deepCopy);
+ //e.RefreshObjects ();
+ TopItemIndex = tii;
+ Unfreeze();
+ args.Handled = true;
+ }
+ #endregion
+
+ internal void LoadBookmarks(XmlNodeList bookmarks) {
+ Roots = bookmarks.ToXmlNodeArray();
+ foreach (BookmarkElement item in Roots) {
+ if (item?.IsOpen == true) {
+ Expand(item);
+ }
+ }
+ _markers.Clear();
+ Mark(bookmarks);
+ }
+
+ void Mark(XmlNodeList bookmarks) {
+ foreach (BookmarkElement item in bookmarks) {
+ if (item == null || item.MarkerColor == 0) {
+ continue;
+ }
+ _markers.Add(item, Color.FromArgb(item.MarkerColor));
+ Mark(item.ChildNodes);
+ }
+ }
+
+ ///
+ /// 复制或移动书签。
+ ///
+ /// 需要复制或移动的源书签。
+ /// 目标书签。
+ /// 是否复制为子节点。
+ /// 是否复制到后面。
+ /// 是否复制书签。
+ /// 是否深度复制书签。
+ internal void CopyOrMoveElement(List source, XmlElement target, bool child, bool after, bool copy, bool deepCopy) {
+ var undo = new UndoActionGroup();
+ bool spr = false; // source parent is root
+ bool tpr = false; // target parent is root
+ var pn = new List();
+ if (copy) {
+ var clones = new List(source.Count);
+ var td = target.OwnerDocument;
+ foreach (XmlElement item in source) {
+ if (item.OwnerDocument == td) {
+ clones.Add((BookmarkElement)item.CloneNode(deepCopy));
+ }
+ else {
+ clones.Add(td.ImportNode(item, deepCopy) as BookmarkElement);
+ }
+ }
+ source = clones;
+ }
+ else {
+ foreach (var item in source) {
+ var e = item.ParentNode as XmlElement;
+ if (e.Name == Constants.DocumentBookmark) {
+ spr = true;
+ pn = null;
+ break;
+ }
+ pn.Add(e);
+ }
+ }
+ //else {
+ // foreach (var item in source) {
+ // this.Collapse (item);
+ // }
+ // this.RemoveObjects (source);
+ //}
+ if (child) {
+ if (after) {
+ tpr = target.Name == Constants.DocumentBookmark;
+ foreach (XmlElement item in source) {
+ if (!copy) {
+ undo.Add(new AddElementAction(item));
+ }
+ target.AppendChild(item);
+ undo.Add(new RemoveElementAction(item));
+ }
+ }
+ else {
+ source.Reverse();
+ foreach (XmlElement item in source) {
+ if (!copy) {
+ undo.Add(new AddElementAction(item));
+ }
+ target.PrependChild(item);
+ undo.Add(new RemoveElementAction(item));
+ }
+ }
+ Expand(target);
+ }
+ else {
+ var p = target.ParentNode;
+ if (after) {
+ tpr = p.Name == Constants.DocumentBookmark;
+ source.Reverse();
+ foreach (XmlElement item in source) {
+ if (!copy) {
+ undo.Add(new AddElementAction(item));
+ }
+ p.InsertAfter(item, target);
+ undo.Add(new RemoveElementAction(item));
+ }
+ }
+ else {
+ foreach (XmlElement item in source) {
+ if (!copy) {
+ undo.Add(new AddElementAction(item));
+ }
+ p.InsertBefore(item, target);
+ undo.Add(new RemoveElementAction(item));
+ }
+ }
+ }
+ Undo?.AddUndo(copy ? "复制书签" : "移动书签", undo);
+ if (copy == false && spr || tpr) {
+ Roots = (target.OwnerDocument as PdfInfoXmlDocument).BookmarkRoot.SubBookmarks;
+ }
+ if (pn != null) {
+ RefreshObjects(pn);
+ }
+ RefreshObject(target);
+ SelectedObjects = source;
+ }
+
+ ///
+ /// 检查 是否为 的先代元素。
+ ///
+ private static bool IsAncestorOrSelf(XmlElement source, XmlElement target) {
+ do {
+ if (source == target) {
+ return true;
+ }
+ } while ((target = target.ParentNode as XmlElement) != null);
+ return false;
+ }
+
+ internal void MarkItems(List items, Color color) {
+ foreach (var item in items) {
+ _markers[item] = color;
+ item.MarkerColor = color.ToArgb();
+ }
+ RefreshObjects(items);
+ }
+ internal List SelectMarkedItems(Color color) {
+ Freeze();
+ var items = new List();
+ var c = color.ToArgb();
+ var r = new List();
+ foreach (var item in _markers) {
+ if (item.Value.ToArgb() == c) {
+ var k = item.Key;
+ Debug.Assert((k.ParentNode == null || k.OwnerDocument == null) == false);
+ if (k.ParentNode == null || k.OwnerDocument == null) {
+ r.Add(k);
+ continue;
+ }
+ items.Add(k);
+ MakeItemVisible(k);
+ }
+ }
+ foreach (var item in r) {
+ _markers.Remove(item);
+ }
+ SelectObjects(items);
+ EnsureItemsVisible(items);
+ Unfreeze();
+ return items;
+ }
+ internal void UnmarkItems(List items) {
+ foreach (var item in items) {
+ _markers.Remove(item);
+ item.MarkerColor = 0;
+ }
+ RefreshObjects(items);
+ }
+ internal void ClearMarks(bool refresh) {
+ if (refresh) {
+ var items = new List(_markers.Count);
+ foreach (var item in _markers) {
+ items.Add(item.Key);
+ item.Key.MarkerColor = 0;
+ }
+ _markers.Clear();
+ RefreshObjects(items);
+ }
+ else {
+ _markers.Clear();
+ }
+ }
+
+ internal void MakeItemVisible(XmlElement item) {
+ var p = item.ParentNode;
+ var a = new Stack(); //ancestorsToExpand
+ a.Push(null);
+ a.Push(p);
+ while (p.Name != Constants.DocumentBookmark) {
+ p = p.ParentNode;
+ a.Push(p);
+ }
+ while (a.Peek() != null) {
+ Expand(a.Pop());
+ }
+ }
+
+ internal void EnsureItemsVisible(ICollection items) {
+ if (items.Count == 0) {
+ return;
+ }
+ var cr = ClientRectangle;
+ OLVListItem fi = null, li = null;
+ foreach (var item in items) {
+ var i = ModelToItem(item);
+ if (i != null) {
+ var r = GetItemRect(i.Index);
+ if (r.Top >= cr.Top && r.Bottom <= cr.Bottom) {
+ return;
+ }
+ li = i;
+ if (fi == null) {
+ fi = i;
+ }
+ }
+ }
+ if ((fi ?? li) != null) {
+ EnsureVisible(fi.Index);
+ }
+ }
+
+ internal void CopySelectedBookmark() {
+ _copiedBookmarks = GetSelectedElements(false);
+ Clipboard.Clear();
+ }
+ internal void PasteBookmarks(XmlElement target, bool asChild) {
+ try {
+ var t = Clipboard.GetText();
+ bool c = false;
+ if (t.IsNullOrWhiteSpace() == false) {
+ var doc = new PdfInfoXmlDocument();
+ using (var s = new System.IO.StringReader(t)) {
+ OutlineManager.ImportSimpleBookmarks(s, doc);
+ }
+ _copiedBookmarks = doc.Bookmarks.ToNodeList() as List;
+ c = true;
+ }
+ if (_copiedBookmarks == null || _copiedBookmarks.Count == 0) {
+ return;
+ }
+ CopyOrMoveElement(_copiedBookmarks, target, asChild, true, true, c || OperationAffectsDescendants);
+ }
+ catch (Exception) {
+ // ignore
+ }
+ }
+
+ internal List GetSelectedElements() { return GetSelectedElements(this, true); }
+ internal List GetSelectedElements(bool selectChildren) { return GetSelectedElements(this, selectChildren); }
+ private static List GetSelectedElements(TreeListView treeList, bool selectChildren) {
+ if (treeList == null) {
+ return null;
+ }
+ var si = treeList.SelectedIndices;
+ var il = new int[si.Count];
+ si.CopyTo(il, 0);
+ Array.Sort(il);
+ var el = new List