├── .gitignore ├── _info └── patch1.jpg ├── TelegramFontPatcher ├── App.config ├── StringExtensions.cs ├── PatternList.cs ├── Properties │ └── AssemblyInfo.cs ├── TelegramFontPatcher.csproj ├── BinaryUtility.cs └── Program.cs ├── TelegramFontPatcher.sln.DotSettings.user ├── fix_telegram_fonts.reg ├── README.md └── TelegramFontPatcher.sln /.gitignore: -------------------------------------------------------------------------------- 1 | bin/ 2 | obj/ 3 | /packages/ 4 | .idea/ 5 | .vs/ 6 | -------------------------------------------------------------------------------- /_info/patch1.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/grandsilence/telegram-font-patcher-csharp/HEAD/_info/patch1.jpg -------------------------------------------------------------------------------- /TelegramFontPatcher/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /TelegramFontPatcher/StringExtensions.cs: -------------------------------------------------------------------------------- 1 | using System.Text; 2 | 3 | namespace TelegramFontPatcher 4 | { 5 | internal static class StringExtensions 6 | { 7 | public static byte[] RawBytes(this string self, Encoding encoding, int length) 8 | { 9 | var result = new byte[encoding.GetMaxByteCount(length)]; 10 | encoding.GetBytes(self, 0, self.Length, result, 0); 11 | 12 | return result; 13 | } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /TelegramFontPatcher.sln.DotSettings.user: -------------------------------------------------------------------------------- 1 | 2 | 0 3 | 0 -------------------------------------------------------------------------------- /fix_telegram_fonts.reg: -------------------------------------------------------------------------------- 1 | Windows Registry Editor Version 5.00 2 | 3 | [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\FontSubstitutes] 4 | "DAOpenSans"="Tahoma" 5 | "DAOpenSansBold"="Tahoma" 6 | "DAOpenSansBoldItalic"="Tahoma" 7 | "DAOpenSansRegular"="Tahoma" 8 | "DAOpenSansRegularItalic"="Tahoma" 9 | "DAOpenSansSemibold"="Tahoma" 10 | "DAOpenSansSemiboldItalic"="Tahoma" 11 | "DAVazir"="Tahoma" 12 | "DAVazirBold"="Tahoma" 13 | "DAVazirMedium"="Tahoma" 14 | "DAVazirRegular"="Tahoma" 15 | ;; Priority font resolving: "Cascadia Mono", "Consolas", "Liberation Mono", "Menlo", "Courier" 16 | ;; Override monospace font: 17 | "Cascadia Mono"="Fixedsys" 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Telegram Desktop (Windows) Font Patcher 2 | 3 | > DEPRECATED! 4 | > Use [fix_telegram_fonts.reg](fix_telegram_fonts.reg) to override fonts without patching EXE. 5 | > In 5.0.0 Telegram Desktop you should set `Chat settings -> Font family option` to `System Value`. 6 | 7 | All [telegram fonts can be found in lib_ui](https://github.com/desktop-app/lib_ui/tree/master/fonts) and [implementaion of font selection is here](https://github.com/desktop-app/lib_ui/blob/master/ui/style/style_core_font.cpp). 8 | 9 | --- 10 | 11 | ## About project 12 | 13 | Patch Telegram fonts to Arial / Tahoma. Makes text more clear. 14 | It's slow but working. If you have a time make it faster on C++. 15 | -------------------------------------------------------------------------------- /TelegramFontPatcher/PatternList.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Text; 4 | 5 | namespace TelegramFontPatcher 6 | { 7 | internal class PatternList : List> 8 | { 9 | public PatternList(string newFont, IEnumerable oldFonts) 10 | { 11 | foreach (string oldFont in oldFonts) 12 | { 13 | Add(oldFont, newFont, Encoding.ASCII); 14 | Add(oldFont, newFont, Encoding.Unicode); 15 | } 16 | } 17 | 18 | private void Add(string oldFont, string newFont, Encoding encoding) 19 | { 20 | Add(new Tuple(oldFont.RawBytes(encoding, oldFont.Length), newFont.RawBytes(encoding, oldFont.Length))); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /TelegramFontPatcher.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.27428.2015 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TelegramFontPatcher", "TelegramFontPatcher\TelegramFontPatcher.csproj", "{D2DDBFA4-1082-4DFE-8512-3C9220237270}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Release|Any CPU = Release|Any CPU 12 | Release|x64 = Release|x64 13 | EndGlobalSection 14 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 15 | {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 16 | {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Debug|Any CPU.Build.0 = Debug|Any CPU 17 | {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Release|Any CPU.ActiveCfg = Release|Any CPU 18 | {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Release|Any CPU.Build.0 = Release|Any CPU 19 | {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Release|x64.ActiveCfg = Release|x64 20 | {D2DDBFA4-1082-4DFE-8512-3C9220237270}.Release|x64.Build.0 = Release|x64 21 | EndGlobalSection 22 | GlobalSection(SolutionProperties) = preSolution 23 | HideSolutionNode = FALSE 24 | EndGlobalSection 25 | GlobalSection(ExtensibilityGlobals) = postSolution 26 | SolutionGuid = {92756B5D-F0B2-490B-93B5-45A1B038DBDE} 27 | EndGlobalSection 28 | EndGlobal 29 | -------------------------------------------------------------------------------- /TelegramFontPatcher/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // Общие сведения об этой сборке предоставляются следующим набором 5 | // набора атрибутов. Измените значения этих атрибутов, чтобы изменить сведения, 6 | // связанные со сборкой. 7 | [assembly: AssemblyTitle("Telegram Patcher 2020")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("Telegram Font Patcher 2020")] 12 | [assembly: AssemblyCopyright("Copyright © 2020")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Установка значения False для параметра ComVisible делает типы в этой сборке невидимыми 17 | // для компонентов COM. Если необходимо обратиться к типу в этой сборке через 18 | // COM, задайте атрибуту ComVisible значение TRUE для этого типа. 19 | [assembly: ComVisible(false)] 20 | 21 | // Следующий GUID служит для идентификации библиотеки типов, если этот проект будет видимым для COM 22 | [assembly: Guid("d2ddbfa4-1082-4dfe-8512-3c9220237270")] 23 | 24 | // Сведения о версии сборки состоят из следующих четырех значений: 25 | // 26 | // Основной номер версии 27 | // Дополнительный номер версии 28 | // Номер сборки 29 | // Редакция 30 | // 31 | // Можно задать все значения или принять номер сборки и номер редакции по умолчанию. 32 | // используя "*", как показано ниже: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("2.1.3.0")] 35 | [assembly: AssemblyFileVersion("2.1.3.0")] 36 | -------------------------------------------------------------------------------- /TelegramFontPatcher/TelegramFontPatcher.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU;x64;x86 7 | {D2DDBFA4-1082-4DFE-8512-3C9220237270} 8 | Exe 9 | TelegramFontPatcher 10 | TelegramFontPatcher 11 | v4.7.2 12 | 512 13 | true 14 | 8 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | bin\x64\Release\ 37 | x64 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | -------------------------------------------------------------------------------- /TelegramFontPatcher/BinaryUtility.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.IO; 4 | using System.Linq; 5 | 6 | //using System.Linq; 7 | 8 | namespace TelegramFontPatcher 9 | { 10 | public static class BinaryUtility 11 | { 12 | public static IEnumerable GetByteStream(BinaryReader reader) 13 | { 14 | const int bufferSize = 1024; 15 | byte[] buffer; 16 | do 17 | { 18 | buffer = reader.ReadBytes(bufferSize); 19 | foreach (var d in buffer) { yield return d; } 20 | } while (bufferSize == buffer.Length); 21 | } 22 | 23 | public static void Replace(BinaryReader reader, BinaryWriter writer, IEnumerable> searchAndReplace) 24 | { 25 | foreach (byte d in Replace(GetByteStream(reader), searchAndReplace)) 26 | writer.Write(d); 27 | } 28 | 29 | private static IEnumerable Replace(IEnumerable source, IEnumerable> searchAndReplace) 30 | { 31 | var result = source; 32 | foreach (var tuple in searchAndReplace) 33 | result = Replace(result, tuple.Item1, tuple.Item2); 34 | 35 | return result; 36 | } 37 | 38 | private static IEnumerable Replace(IEnumerable input, IEnumerable from, IEnumerable to) 39 | { 40 | using var fromEnumerator = from.GetEnumerator(); 41 | fromEnumerator.MoveNext(); 42 | int match = 0; 43 | foreach (var data in input) 44 | { 45 | if (data == fromEnumerator.Current) 46 | { 47 | match++; 48 | if (fromEnumerator.MoveNext()) { continue; } 49 | foreach (byte d in to) { yield return d; } 50 | match = 0; 51 | fromEnumerator.Reset(); 52 | fromEnumerator.MoveNext(); 53 | continue; 54 | } 55 | if (0 != match) 56 | { 57 | foreach (byte d in from.Take(match)) { yield return d; } 58 | match = 0; 59 | fromEnumerator.Reset(); 60 | fromEnumerator.MoveNext(); 61 | } 62 | yield return data; 63 | } 64 | 65 | if (0 != match) 66 | { 67 | foreach (byte d in from.Take(match)) { yield return d; } 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /TelegramFontPatcher/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.IO; 4 | using System.Reflection; 5 | 6 | namespace TelegramFontPatcher 7 | { 8 | internal class Program 9 | { 10 | private const string ProcName = "Telegram"; 11 | private const string ExeName = ProcName + ".exe"; 12 | 13 | private static void Error(string message) 14 | { 15 | Console.WriteLine($"ERROR: {message}"); 16 | Console.ReadLine(); 17 | Environment.Exit(1); 18 | } 19 | 20 | private static void Main(string[] args) 21 | { 22 | Console.Title = $"Telegram Font Patcher {Assembly.GetExecutingAssembly().GetName().Version}"; 23 | Console.WriteLine(Console.Title + Environment.NewLine); 24 | 25 | var processes = Process.GetProcessesByName("Telegram"); 26 | if (processes.Length == 0) 27 | Error(ExeName + " not found"); 28 | 29 | // Backup original Telegram.exe 30 | try 31 | { 32 | var proc = processes[0]; 33 | string path = proc.MainModule.FileName; 34 | 35 | proc.Kill(); 36 | proc.WaitForExit(); 37 | 38 | File.Copy(path, path + ".bak", true); 39 | Console.WriteLine("INFO: Backup saved"); 40 | 41 | Console.WriteLine($"NOTICE: Trying to patch {ExeName}..."); 42 | 43 | var patternsRegular = new PatternList("Arial", new[] { 44 | "Segoe UI", 45 | "Segoe UI Semibold", 46 | "Open Sans", 47 | "Open Sans Semibold", 48 | 49 | "DAOpenSansRegular", 50 | "DAOpenSansRegularItalic", 51 | "DAOpenSansSemiboldAsBold", 52 | "DAOpenSansSemiboldItalicAsBold", 53 | "DAOpenSansSemibold", 54 | "DAOpenSansSemiboldItalic", 55 | 56 | "DAVazirRegular", 57 | "DAVazirMediumAsBold", 58 | "DAVazirMedium", 59 | 60 | "Microsoft YaHei", 61 | "Microsoft JhengHei UI", 62 | "Yu Gothic UI" 63 | }); 64 | 65 | string patchedName = path + ".patched"; 66 | if (File.Exists(patchedName)) 67 | File.Delete(patchedName); 68 | 69 | Console.WriteLine("Patching..."); 70 | 71 | using (var reader = new BinaryReader(new FileStream(path, FileMode.Open))) 72 | using (var writer = new BinaryWriter(new FileStream(patchedName, FileMode.Create))) 73 | { 74 | BinaryUtility.Replace(reader, writer, patternsRegular); 75 | } 76 | 77 | File.Delete(path); 78 | File.Move(patchedName, path); 79 | 80 | Process.Start(path); 81 | } 82 | catch (Exception ex) 83 | { 84 | Error(ex.Message); 85 | } 86 | } 87 | } 88 | } 89 | 90 | --------------------------------------------------------------------------------