diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..31833d4 --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +bin/ +obj/ +/packages/ +.idea/ +.vs/ diff --git a/README.md b/README.md new file mode 100644 index 0000000..9ffb6d4 --- /dev/null +++ b/README.md @@ -0,0 +1,5 @@ +# Telegram Desktop (Windows) Font Patcher + +Replace Segoe UI and Open Sans to Arial / Tahoma when DirectWrite disabled. + +It's slow but working. If you have a time make it faster on c++. diff --git a/TelegramFontPatcher.sln b/TelegramFontPatcher.sln new file mode 100644 index 0000000..a91715d --- /dev/null +++ b/TelegramFontPatcher.sln @@ -0,0 +1,25 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 15 +VisualStudioVersion = 15.0.27428.2015 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramFontPatcher", "TelegramFontPatcher\TelegramFontPatcher.csproj", "{D2DDBFA4-1082-4DFE-8512-3C9220237270}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Debug|Any CPU.Build.0 = Debug|Any CPU + {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Release|Any CPU.ActiveCfg = Release|Any CPU + {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {92756B5D-F0B2-490B-93B5-45A1B038DBDE} + EndGlobalSection +EndGlobal diff --git a/TelegramFontPatcher.sln.DotSettings.user b/TelegramFontPatcher.sln.DotSettings.user new file mode 100644 index 0000000..442f49e --- /dev/null +++ b/TelegramFontPatcher.sln.DotSettings.user @@ -0,0 +1,2 @@ + + 0 \ No newline at end of file diff --git a/TelegramFontPatcher/App.config b/TelegramFontPatcher/App.config new file mode 100644 index 0000000..b50c74f --- /dev/null +++ b/TelegramFontPatcher/App.config @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/TelegramFontPatcher/BinaryUtility.cs b/TelegramFontPatcher/BinaryUtility.cs new file mode 100644 index 0000000..3f80108 --- /dev/null +++ b/TelegramFontPatcher/BinaryUtility.cs @@ -0,0 +1,71 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; + +//using System.Linq; + +namespace TelegramFontPatcher +{ + public static class BinaryUtility + { + public static IEnumerable GetByteStream(BinaryReader reader) + { + const int bufferSize = 1024; + byte[] buffer; + do + { + buffer = reader.ReadBytes(bufferSize); + foreach (var d in buffer) { yield return d; } + } while (bufferSize == buffer.Length); + } + + public static void Replace(BinaryReader reader, BinaryWriter writer, IEnumerable> searchAndReplace) + { + foreach (byte d in Replace(GetByteStream(reader), searchAndReplace)) + writer.Write(d); + } + + private static IEnumerable Replace(IEnumerable source, IEnumerable> searchAndReplace) + { + var result = source; + foreach (var tuple in searchAndReplace) + result = Replace(result, tuple.Item1, tuple.Item2); + + return result; + } + + private static IEnumerable Replace(IEnumerable input, IEnumerable from, IEnumerable to) + { + using var fromEnumerator = from.GetEnumerator(); + fromEnumerator.MoveNext(); + int match = 0; + foreach (var data in input) + { + if (data == fromEnumerator.Current) + { + match++; + if (fromEnumerator.MoveNext()) { continue; } + foreach (byte d in to) { yield return d; } + match = 0; + fromEnumerator.Reset(); + fromEnumerator.MoveNext(); + continue; + } + if (0 != match) + { + foreach (byte d in from.Take(match)) { yield return d; } + match = 0; + fromEnumerator.Reset(); + fromEnumerator.MoveNext(); + } + yield return data; + } + + if (0 != match) + { + foreach (byte d in from.Take(match)) { yield return d; } + } + } + } +} diff --git a/TelegramFontPatcher/PatternList.cs b/TelegramFontPatcher/PatternList.cs new file mode 100644 index 0000000..26f4c67 --- /dev/null +++ b/TelegramFontPatcher/PatternList.cs @@ -0,0 +1,23 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace TelegramFontPatcher +{ + internal class PatternList : List> + { + public PatternList(string newFont, IEnumerable oldFonts) + { + foreach (string oldFont in oldFonts) + { + Add(oldFont, newFont, Encoding.ASCII); + Add(oldFont, newFont, Encoding.Unicode); + } + } + + private void Add(string oldFont, string newFont, Encoding encoding) + { + Add(new Tuple(oldFont.RawBytes(encoding, oldFont.Length), newFont.RawBytes(encoding, oldFont.Length))); + } + } +} diff --git a/TelegramFontPatcher/Program.cs b/TelegramFontPatcher/Program.cs new file mode 100644 index 0000000..248fa7b --- /dev/null +++ b/TelegramFontPatcher/Program.cs @@ -0,0 +1,78 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Reflection; + +namespace TelegramFontPatcher +{ + internal class Program + { + private const string ProcName = "Telegram"; + private const string ExeName = ProcName + ".exe"; + + private static void Error(string message) + { + Console.WriteLine($"ERROR: {message}"); + Console.ReadLine(); + Environment.Exit(1); + } + + private static void Main(string[] args) + { + Console.Title = $"Telegram Font Patcher {Assembly.GetExecutingAssembly().GetName().Version}"; + Console.WriteLine(Console.Title + Environment.NewLine); + + var processes = Process.GetProcessesByName("Telegram"); + if (processes.Length == 0) + Error(ExeName + " not found"); + + // Backup original Telegram.exe + try + { + var proc = processes[0]; + var path = proc.MainModule.FileName; + + proc.Kill(); + proc.WaitForExit(); + + File.Copy(path, path + ".bak", true); + Console.WriteLine("INFO: Backup saved"); + + Console.WriteLine($"NOTICE: Trying to patch {ExeName}..."); + + var patternsRegular = new PatternList("Arial", new[] { + "Segoe UI", "Segoe UI Semibold", + "Open Sans", "Open Sans Semibold", + "DAOpenSansRegular", + "DAOpenSansRegularItalic", + "DAOpenSansBold", + "DAOpenSansBoldItalic", + "DAOpenSansSemibold", + "DAOpenSansSemiboldItalic" + }); + + string patchedName = path + ".patched"; + if (File.Exists(patchedName)) + File.Delete(patchedName); + + Console.WriteLine("Patching..."); + + using (var reader = new BinaryReader(new FileStream(ExeName, FileMode.Open))) + using (var writer = new BinaryWriter(new FileStream(patchedName, FileMode.Create))) + { + BinaryUtility.Replace(reader, writer, patternsRegular); + } + + File.Delete(path); + File.Move(patchedName, path); + + Process.Start(path); + } + catch (Exception ex) + { + Error(ex.Message); + } + } + } +} + diff --git a/TelegramFontPatcher/Properties/AssemblyInfo.cs b/TelegramFontPatcher/Properties/AssemblyInfo.cs new file mode 100644 index 0000000..83ebf39 --- /dev/null +++ b/TelegramFontPatcher/Properties/AssemblyInfo.cs @@ -0,0 +1,35 @@ +using System.Reflection; +using System.Runtime.InteropServices; + +// Общие сведения об этой сборке предоставляются следующим набором +// набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, +// связанные со сборкой. +[assembly: AssemblyTitle("Telegram Patcher 2020")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Telegram Font Patcher 2020")] +[assembly: AssemblyCopyright("Copyright © 2020")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми +// для компонентов COM. Если необходимо обратиться к типу в этой сборке через +// COM, задайте атрибуту ComVisible значение TRUE для этого типа. +[assembly: ComVisible(false)] + +// Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM +[assembly: Guid("d2ddbfa4-1082-4dfe-8512-3c9220237270")] + +// Сведения о версии сборки состоят из следующих четырех значений: +// +// Основной номер версии +// Дополнительный номер версии +// Номер сборки +// Редакция +// +// Можно задать все значения или принять номер сборки и номер редакции по умолчанию. +// используя "*", как показано ниже: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/TelegramFontPatcher/StringExtensions.cs b/TelegramFontPatcher/StringExtensions.cs new file mode 100644 index 0000000..11688d3 --- /dev/null +++ b/TelegramFontPatcher/StringExtensions.cs @@ -0,0 +1,15 @@ +using System.Text; + +namespace TelegramFontPatcher +{ + internal static class StringExtensions + { + public static byte[] RawBytes(this string self, Encoding encoding, int length) + { + var result = new byte[encoding.GetMaxByteCount(length)]; + encoding.GetBytes(self, 0, self.Length, result, 0); + + return result; + } + } +} diff --git a/TelegramFontPatcher/TelegramFontPatcher.csproj b/TelegramFontPatcher/TelegramFontPatcher.csproj new file mode 100644 index 0000000..54cd3d5 --- /dev/null +++ b/TelegramFontPatcher/TelegramFontPatcher.csproj @@ -0,0 +1,50 @@ + + + + + Debug + AnyCPU + {D2DDBFA4-1082-4DFE-8512-3C9220237270} + Exe + TelegramFontPatcher + TelegramFontPatcher + v4.6.2 + 512 + true + 8 + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + \ No newline at end of file