├── Screenshots ├── 01.png ├── 02.png ├── 01-thumb.png └── 02-thumb.png ├── Docs ├── Example Fonts │ ├── ionicons 20pt.zi │ ├── ionicons 24pt.zi │ ├── ionicons 32pt.zi │ ├── ionicons 48pt.zi │ ├── ionicons 64pt.zi │ └── Readme.md └── Nextion Font Format Specification ZI version 3.md ├── NextionHMITest └── NextionHMITest.HMI ├── NextionFontEditor ├── NextionFontEditor │ ├── ZiLib.dll │ ├── icons8-text-box.ico │ ├── Icons │ │ ├── icons8-grid-16.png │ │ ├── icons8-pen-16.png │ │ ├── icons8-pen-30.png │ │ ├── icons8-save-16.png │ │ ├── icons8-erase-16.png │ │ ├── icons8-search-16.png │ │ ├── icons8-search-30.png │ │ ├── icons8-text-box.ico │ │ ├── icons8-sort-down-16.png │ │ ├── icons8-sort-left-16.png │ │ ├── icons8-sort-up-16.png │ │ ├── icons8-text-box-16.png │ │ ├── icons8-text-box-30.png │ │ ├── icons8-text-box-40.png │ │ ├── icons8-text-box-80.png │ │ ├── icons8-edit-image-16.png │ │ ├── icons8-edit-image-30.png │ │ ├── icons8-sort-right-16.png │ │ ├── icons8-increase-font-16.png │ │ ├── icons8-increase-font-30.png │ │ ├── icons8-opened-folder-16.png │ │ ├── icons8-opened-folder-30.png │ │ ├── icons8-preview-pane-16.png │ │ ├── icons8_search_16_lF9_icon.ico │ │ ├── icons8_edit_image_16_23V_icon.ico │ │ ├── icons8_preview_pane_16_Vww_icon.ico │ │ └── icons8_increase_font_16_mb5_icon.ico │ ├── Test Files │ │ ├── Arial_16_ascii.zi │ │ ├── Arial_40_ascii.zi │ │ ├── Arial_40_gb2312.zi │ │ ├── Arial_16_ASCII_v5.zi │ │ ├── Arial_32_ASCII_v5.zi │ │ ├── Arial_16_ASCII_AA_v5.zi │ │ ├── Arial_32_ASCII_AA_v5.zi │ │ ├── Arial_32_iso-8859-1.zi │ │ ├── Arial_40_iso-8859-1.zi │ │ └── Code Page Test │ │ │ ├── ascii.zi │ │ │ ├── big5.zi │ │ │ ├── gb2312.zi │ │ │ ├── koi8-r.zi │ │ │ ├── iso-8859-1.zi │ │ │ ├── iso-8859-2.zi │ │ │ ├── iso-8859-3.zi │ │ │ ├── iso-8859-4.zi │ │ │ ├── iso-8859-5.zi │ │ │ ├── iso-8859-6.zi │ │ │ ├── iso-8859-7.zi │ │ │ ├── iso-8859-8.zi │ │ │ ├── iso-8859-9.zi │ │ │ ├── iso-8859-11.zi │ │ │ ├── iso-8859-13.zi │ │ │ ├── iso-8859-15.zi │ │ │ ├── windows-1255.zi │ │ │ ├── windows-1256.zi │ │ │ ├── windows-1257.zi │ │ │ ├── windows-1258.zi │ │ │ ├── windows-874.zi │ │ │ ├── ks_c_5601-1987.zi │ │ │ └── iso-8859-11-duplicate.zi │ ├── NextionFontEditor_TemporaryKey.pfx │ ├── App.config │ ├── Properties │ │ ├── Settings.settings │ │ ├── Settings.Designer.cs │ │ ├── AssemblyInfo.cs │ │ ├── Resources.Designer.cs │ │ └── Resources.resx │ ├── Program.cs │ ├── FormFontSuite.cs │ ├── Controls │ │ ├── FontListBox.cs │ │ └── CharEditor.cs │ ├── Extensions │ │ └── FormExtensions.cs │ ├── FormCharacterWidth.cs │ ├── FormFontPreview.cs │ ├── FormFontGenerator.cs │ ├── FormAddCharacters.cs │ ├── FormCharacterWidth.Designer.cs │ ├── FormFontPreview.resx │ ├── FormAddCharacters.resx │ ├── FormFontGenerator.resx │ └── FormFontSuite.Designer.cs ├── ZiLib │ ├── FileVersion │ │ ├── Common │ │ │ ├── CodePageMode.cs │ │ │ ├── FontOrientation.cs │ │ │ ├── ZiFont.cs │ │ │ ├── ZiCharacter.cs │ │ │ ├── CodePageIdentifier.cs │ │ │ ├── CodePages.cs │ │ │ ├── ZiClipboard.cs │ │ │ └── CodePage.cs │ │ ├── V5 │ │ │ ├── CharMapEntry.cs │ │ │ └── BinaryTools.cs │ │ └── V3 │ │ │ ├── ZiFontV3.cs │ │ │ └── ZiCharacterV3.cs │ ├── Interfaces │ │ ├── IZiFont.cs │ │ └── IZiCharacter.cs │ ├── Properties │ │ └── AssemblyInfo.cs │ ├── ZiLib.csproj │ ├── Extensions │ │ └── BitmapExtensions.cs │ └── BinaryTools.cs └── NextionFontEditor.sln ├── .github └── FUNDING.yml ├── test2.linq ├── test1.linq ├── .gitattributes ├── README.md └── .gitignore /Screenshots/01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Screenshots/01.png -------------------------------------------------------------------------------- /Screenshots/02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Screenshots/02.png -------------------------------------------------------------------------------- /Screenshots/01-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Screenshots/01-thumb.png -------------------------------------------------------------------------------- /Screenshots/02-thumb.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Screenshots/02-thumb.png -------------------------------------------------------------------------------- /Docs/Example Fonts/ionicons 20pt.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Docs/Example Fonts/ionicons 20pt.zi -------------------------------------------------------------------------------- /Docs/Example Fonts/ionicons 24pt.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Docs/Example Fonts/ionicons 24pt.zi -------------------------------------------------------------------------------- /Docs/Example Fonts/ionicons 32pt.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Docs/Example Fonts/ionicons 32pt.zi -------------------------------------------------------------------------------- /Docs/Example Fonts/ionicons 48pt.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Docs/Example Fonts/ionicons 48pt.zi -------------------------------------------------------------------------------- /Docs/Example Fonts/ionicons 64pt.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/Docs/Example Fonts/ionicons 64pt.zi -------------------------------------------------------------------------------- /NextionHMITest/NextionHMITest.HMI: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionHMITest/NextionHMITest.HMI -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/ZiLib.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/ZiLib.dll -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/icons8-text-box.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/icons8-text-box.ico -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-grid-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-grid-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-pen-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-pen-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-pen-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-pen-30.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-save-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-save-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-erase-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-erase-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-search-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-search-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-search-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-search-30.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-text-box.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-text-box.ico -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-sort-down-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-sort-down-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-sort-left-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-sort-left-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-sort-up-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-sort-up-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-30.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-40.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-40.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-text-box-80.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_16_ascii.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_16_ascii.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_40_ascii.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_40_ascii.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_40_gb2312.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_40_gb2312.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-edit-image-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-edit-image-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-edit-image-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-edit-image-30.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-sort-right-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-sort-right-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_16_ASCII_v5.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_16_ASCII_v5.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_32_ASCII_v5.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_32_ASCII_v5.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-increase-font-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-increase-font-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-increase-font-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-increase-font-30.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-opened-folder-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-opened-folder-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-opened-folder-30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-opened-folder-30.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8-preview-pane-16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8-preview-pane-16.png -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/NextionFontEditor_TemporaryKey.pfx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/NextionFontEditor_TemporaryKey.pfx -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_16_ASCII_AA_v5.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_16_ASCII_AA_v5.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_32_ASCII_AA_v5.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_32_ASCII_AA_v5.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_32_iso-8859-1.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_32_iso-8859-1.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Arial_40_iso-8859-1.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Arial_40_iso-8859-1.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/ascii.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/ascii.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/big5.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/big5.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8_search_16_lF9_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8_search_16_lF9_icon.ico -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/gb2312.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/gb2312.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/koi8-r.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/koi8-r.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8_edit_image_16_23V_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8_edit_image_16_23V_icon.ico -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-1.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-1.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-2.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-2.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-3.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-3.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-4.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-4.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-5.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-5.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-6.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-6.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-7.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-7.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-8.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-8.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-9.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-9.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8_preview_pane_16_Vww_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8_preview_pane_16_Vww_icon.ico -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-11.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-11.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-13.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-13.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-15.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-15.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1255.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1255.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1256.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1256.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1257.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1257.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1258.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-1258.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-874.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/windows-874.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Icons/icons8_increase_font_16_mb5_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Icons/icons8_increase_font_16_mb5_icon.ico -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/ks_c_5601-1987.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/ks_c_5601-1987.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-11-duplicate.zi: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hagronnestad/nextion-font-editor/HEAD/NextionFontEditor/NextionFontEditor/Test Files/Code Page Test/iso-8859-11-duplicate.zi -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/App.config: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/CodePageMode.cs: -------------------------------------------------------------------------------- 1 | namespace ZiLib 2 | { 3 | public enum CodePageMode : byte 4 | { 5 | SINGLE_BYTE_FULL_CHARSET = 0x00, 6 | DOUBLE_BYTE_FULL_CHARSET = 0x01, 7 | CHARACTER_SUBSET = 0x02 8 | } 9 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/FontOrientation.cs: -------------------------------------------------------------------------------- 1 | namespace ZiLib.FileVersion.Common 2 | { 3 | 4 | public enum FontOrientation : byte 5 | { 6 | Vertical = 0x0a, 7 | Horizontal = 0x0b, 8 | VerticalRotated = 0x0c, 9 | HorizontalRotated = 0x0d 10 | } 11 | 12 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Properties/Settings.settings: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/V5/CharMapEntry.cs: -------------------------------------------------------------------------------- 1 | namespace ZiLib.FileVersion.V5 { 2 | 3 | public struct CharMapEntry { 4 | public ushort Code; 5 | public byte Width; 6 | public byte KerningLeft; 7 | public byte KerningRight; 8 | public uint DataAddressOffset; // Offset from start of entry 9 | public ushort Length; 10 | 11 | public int TotalWidth => Width + KerningLeft + KerningRight; 12 | } 13 | 14 | } -------------------------------------------------------------------------------- /Docs/Example Fonts/Readme.md: -------------------------------------------------------------------------------- 1 | # Example Fonts 2 | 3 | This is a test of the ZI v5 font specification for TJC/Nextion HMI displays. Use these files at your own risk! 4 | The characterset starts with a space (`0x20`) as the first character and ends with character `0x02D7` using the GB2312 encoding. 5 | 6 | The files contain the [ionicons-designerpack](https://github.com/ionic-team/ionicons) in a ZI v5 format. 7 | The original icon files are created by [iconic-team](https://github.com/ionic-team) and licensed under the MIT license. 8 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [ hagronnestad ] 4 | patreon: # Replace with a single Patreon username 5 | open_collective: # Replace with a single Open Collective username 6 | ko_fi: # Replace with a single Ko-fi username 7 | tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel 8 | community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry 9 | liberapay: # Replace with a single Liberapay username 10 | issuehunt: # Replace with a single IssueHunt username 11 | otechie: # Replace with a single Otechie username 12 | custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2'] 13 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Program.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Windows.Forms; 3 | using ZiLib.FileVersion.V5; 4 | 5 | namespace NextionFontEditor { 6 | 7 | internal static class Program { 8 | 9 | /// 10 | /// The main entry point for the application. 11 | /// 12 | [STAThread] 13 | private static void Main() { 14 | //ZiFont f; 15 | //var f = ZiLib.FileVersion.Common.ZiFont.FromFile(@"Test Files\Arial_32_ASCII_AA_v5.zi"); 16 | 17 | Application.EnableVisualStyles(); 18 | Application.SetCompatibleTextRenderingDefault(false); 19 | Application.Run(new FormFontSuite()); 20 | } 21 | } 22 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/Interfaces/IZiFont.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using ZiLib.FileVersion.Common; 4 | 5 | namespace ZiLib { 6 | 7 | public interface IZiFont { 8 | string Name { get; set; } 9 | CodePage CodePage { get; set; } 10 | 11 | byte Version { get; set; } 12 | 13 | byte CharacterWidth { get; set; } 14 | byte CharacterHeight { get; set; } 15 | int CharacterCount { get; } 16 | 17 | long FileSize { get; set; } 18 | 19 | //List CharBitmaps { get; set; } 20 | List Characters { get; set; } 21 | void Save(string fileName, CodePage codepage); 22 | //void AddCharacter(uint codepoint, byte[] bytes, byte width, byte kerningL = 0, byte kerningR = 0); 23 | void AddCharacter(uint codepoint, IZiCharacter character); 24 | void RemoveCharacter(int index); 25 | } 26 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/ZiFont.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using ZiLib.FileVersion.V3; 4 | using ZiLib.FileVersion.V5; 5 | 6 | namespace ZiLib.FileVersion.Common { 7 | 8 | public class ZiFont { 9 | private const long FILE_VERSION_OFFSET = 0x10; 10 | 11 | public static IZiFont FromFile(string fileName) { 12 | var version = 0; 13 | 14 | using (var fs = File.OpenRead(fileName)) { 15 | fs.Seek(FILE_VERSION_OFFSET, SeekOrigin.Begin); 16 | version = fs.ReadByte(); 17 | fs.Close(); 18 | } 19 | 20 | switch (version) { 21 | case 3: 22 | return ZiFontV3.FromFile(fileName); 23 | 24 | case 5: 25 | case 6: 26 | return ZiFontV5.FromFile(fileName); 27 | default: 28 | return null; 29 | } 30 | } 31 | } 32 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/Interfaces/IZiCharacter.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Drawing; 3 | using ZiLib.FileVersion.Common; 4 | 5 | namespace ZiLib { 6 | 7 | public interface IZiCharacter { 8 | 9 | uint CodePoint { get; set; } 10 | 11 | string Txt { get; set; } 12 | 13 | Font Font { get; set; } 14 | 15 | PointF TxtPosition { get; set; } 16 | 17 | byte KerningLeft { get; set; } 18 | byte KerningRight { get; set; } 19 | 20 | byte Width { get; set; } 21 | 22 | IZiFont Parent { get; set; } 23 | 24 | Bitmap ToBitmap(); 25 | 26 | byte[] ToBytes(); 27 | 28 | byte[] GetCharacterData(); 29 | 30 | bool CanRevert(); 31 | 32 | Bitmap RevertBitmap(); 33 | 34 | void SetBitmap(Bitmap bmp); 35 | 36 | void SetPixel(int x, int y, Color pixel); 37 | 38 | void SetString(Font font, PointF location, string txt); 39 | 40 | string GetString(); 41 | } 42 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Properties/Settings.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace NextionFontEditor.Properties 12 | { 13 | 14 | 15 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 16 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] 17 | internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase 18 | { 19 | 20 | private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); 21 | 22 | public static Settings Default 23 | { 24 | get 25 | { 26 | return defaultInstance; 27 | } 28 | } 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormFontSuite.cs: -------------------------------------------------------------------------------- 1 | using NextionFontEditor.Extensions; 2 | using System; 3 | using System.Windows.Forms; 4 | 5 | namespace NextionFontEditor { 6 | 7 | public partial class FormFontSuite : Form { 8 | 9 | public FormFontSuite() { 10 | InitializeComponent(); 11 | } 12 | 13 | private void mnuFileExit_Click(object sender, EventArgs e) { 14 | Close(); 15 | } 16 | 17 | private void btnNewFontGenerator_Click(object sender, EventArgs e) { 18 | var form = new FormFontGenerator { 19 | MdiParent = this, 20 | //WindowState = FormWindowState.Maximized 21 | }; 22 | form.Show(); 23 | } 24 | 25 | private void btnNewFontEditor_Click(object sender, EventArgs e) { 26 | var form = new FormFontEditor { 27 | MdiParent = this, 28 | //WindowState = FormWindowState.Maximized 29 | }; 30 | form.Show(); 31 | } 32 | 33 | private void btnNewFontPreview_Click(object sender, EventArgs e) { 34 | var form = new FormFontPreview { 35 | MdiParent = this, 36 | //WindowState = FormWindowState.Maximized 37 | }; 38 | form.Show(); 39 | } 40 | 41 | private void FormFontSuite_Load(object sender, EventArgs e) { 42 | this.SetBevel(false); 43 | } 44 | } 45 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("ZiLib")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("ZiLib")] 13 | [assembly: AssemblyCopyright("Copyright © 2018")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("656212b8-63ab-4c9d-a654-59f54ab10ea5")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /test2.linq: -------------------------------------------------------------------------------- 1 | 2 | <RuntimeDirectory>\System.Windows.Forms.dll 3 | <RuntimeDirectory>\System.Security.dll 4 | <RuntimeDirectory>\System.Configuration.dll 5 | <RuntimeDirectory>\Accessibility.dll 6 | <RuntimeDirectory>\System.Deployment.dll 7 | <RuntimeDirectory>\System.Runtime.Serialization.Formatters.Soap.dll 8 | System.Windows.Forms 9 | System.Drawing 10 | 11 | 12 | var f = new Form(); 13 | f.Width = 500; 14 | f.Show(); 15 | 16 | var p1 = new PictureBox() 17 | { 18 | Location = new Point(10, 10), 19 | //BackColor = Color.Red, 20 | Size = new Size(200, 200), 21 | //SizeMode = PictureBoxSizeMode.StretchImage 22 | }; 23 | f.Controls.Add(p1); 24 | 25 | var c = "w"; 26 | 27 | var font1 = new Font("Arial Black", 48, GraphicsUnit.Pixel); 28 | var b1 = new Bitmap(200, 200); 29 | var p1g = Graphics.FromImage(b1); 30 | 31 | var size = p1g.MeasureString(c, font1, default(PointF), StringFormat.GenericTypographic); 32 | //var size = TextRenderer.MeasureText(c, font1, new Size(1, 1), TextFormatFlags.Default); 33 | 34 | p1g.DrawRectangle(new Pen(Color.DarkRed), new Rectangle(0, 0, (int)size.Width + 2, (int)size.Height + 2)); 35 | 36 | p1g.DrawString( 37 | c, 38 | font1, 39 | new SolidBrush(Color.Black), 1, 1, StringFormat.GenericTypographic); 40 | 41 | f.Text = size.ToString(); 42 | 43 | p1.Image = b1; 44 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("Nextion Font Suite")] 8 | [assembly: AssemblyDescription("A collection of tools to view, edit and generate Nextion .zi fonts.")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("https://github.com/hagronnestad")] 11 | [assembly: AssemblyProduct("Nextion Font Suite")] 12 | [assembly: AssemblyCopyright("Copyright © 2019")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("ddc95925-4b4a-4fd4-9a57-d1b5b206d8d9")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.1.0.0")] 35 | [assembly: AssemblyFileVersion("1.1.0.0")] 36 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor.sln: -------------------------------------------------------------------------------- 1 | 2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.28010.2041 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NextionFontEditor", "NextionFontEditor\NextionFontEditor.csproj", "{DDC95925-4B4A-4FD4-9A57-D1B5B206D8D9}" 7 | EndProject 8 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ZiLib", "ZiLib\ZiLib.csproj", "{656212B8-63AB-4C9D-A654-59F54AB10EA5}" 9 | EndProject 10 | Global 11 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 12 | Debug|Any CPU = Debug|Any CPU 13 | Release|Any CPU = Release|Any CPU 14 | EndGlobalSection 15 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 16 | {DDC95925-4B4A-4FD4-9A57-D1B5B206D8D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 17 | {DDC95925-4B4A-4FD4-9A57-D1B5B206D8D9}.Debug|Any CPU.Build.0 = Debug|Any CPU 18 | {DDC95925-4B4A-4FD4-9A57-D1B5B206D8D9}.Release|Any CPU.ActiveCfg = Release|Any CPU 19 | {DDC95925-4B4A-4FD4-9A57-D1B5B206D8D9}.Release|Any CPU.Build.0 = Release|Any CPU 20 | {656212B8-63AB-4C9D-A654-59F54AB10EA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {656212B8-63AB-4C9D-A654-59F54AB10EA5}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {656212B8-63AB-4C9D-A654-59F54AB10EA5}.Release|Any CPU.ActiveCfg = Release|Any CPU 23 | {656212B8-63AB-4C9D-A654-59F54AB10EA5}.Release|Any CPU.Build.0 = Release|Any CPU 24 | EndGlobalSection 25 | GlobalSection(SolutionProperties) = preSolution 26 | HideSolutionNode = FALSE 27 | EndGlobalSection 28 | GlobalSection(ExtensibilityGlobals) = postSolution 29 | SolutionGuid = {C93CFD0E-325B-47FD-B72A-E50C55BB4EEC} 30 | EndGlobalSection 31 | EndGlobal 32 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/ZiCharacter.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using ZiLib.FileVersion.V3; 4 | using ZiLib.FileVersion.V5; 5 | 6 | namespace ZiLib.FileVersion.Common { 7 | 8 | public class ZiCharacter { 9 | public static IZiCharacter FromBitmap(IZiFont parent, uint codepoint, Bitmap bmp, byte kerningL, byte kerningR) { 10 | switch (parent.Version) { 11 | case 3: 12 | return new ZiCharacterV3(parent, codepoint, bmp, kerningL, kerningR); 13 | case 5: 14 | return new ZiCharacterV5(parent, codepoint, bmp, kerningL, kerningR); 15 | default: 16 | return null; 17 | } 18 | } 19 | 20 | public static IZiCharacter FromBytes(IZiFont parent, uint codepoint, byte[] bytes, byte width, byte kerningL, byte kerningR) { 21 | switch (parent.Version) { 22 | case 3: 23 | return new ZiCharacterV3(parent, codepoint, bytes, width, kerningL, kerningR); 24 | case 5: 25 | return new ZiCharacterV5(parent, codepoint, bytes, width, kerningL, kerningR); 26 | default: 27 | return null; 28 | } 29 | } 30 | 31 | public static IZiCharacter FromString(IZiFont parent, uint codepoint, Font font, PointF location, String txt) { 32 | switch (parent.Version) { 33 | case 3: 34 | return new ZiCharacterV3(parent, codepoint, font, location, txt); 35 | case 5: 36 | return new ZiCharacterV5(parent, codepoint, font, location, txt); 37 | default: 38 | return null; 39 | } 40 | } 41 | 42 | } 43 | } -------------------------------------------------------------------------------- /test1.linq: -------------------------------------------------------------------------------- 1 | 2 | <RuntimeDirectory>\System.Configuration.dll 3 | <RuntimeDirectory>\System.Design.dll 4 | <RuntimeDirectory>\System.Drawing.Design.dll 5 | <RuntimeDirectory>\System.Web.dll 6 | <RuntimeDirectory>\System.Web.Mobile.dll 7 | <RuntimeDirectory>\System.Web.RegularExpressions.dll 8 | <RuntimeDirectory>\System.Windows.Forms.dll 9 | System.Windows.Forms 10 | System.Drawing 11 | System.Drawing.Text 12 | 13 | 14 | var f = new Form(); 15 | f.Show(); 16 | 17 | var p1 = new PictureBox() 18 | { 19 | Location = new Point(0, 0), 20 | BackColor = Color.Red 21 | }; 22 | f.Controls.Add(p1); 23 | 24 | var p2 = new PictureBox() 25 | { 26 | Location = new Point(0, 100), 27 | BackColor = Color.Red 28 | }; 29 | f.Controls.Add(p2); 30 | 31 | var font1 = new Font("Arial", 24, GraphicsUnit.Pixel); 32 | var b1 = new Bitmap(24, 24); 33 | var p1g = Graphics.FromImage(b1); 34 | p1g.DrawString( 35 | "a", 36 | font1, 37 | new SolidBrush(Color.Black), 0, 0); 38 | p1.Image = b1; 39 | 40 | var font2 = new Font("Arial", 96, GraphicsUnit.Pixel); 41 | var b2 = new Bitmap(96, 96); 42 | 43 | var p2g = Graphics.FromImage(b2); 44 | p2g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; 45 | p2g.TextRenderingHint = TextRenderingHint.SingleBitPerPixel; 46 | 47 | p2g.DrawString( 48 | "a", 49 | font2, 50 | new SolidBrush(Color.Black), 0, 0); 51 | 52 | 53 | 54 | var b3 = new Bitmap(24, 24); 55 | var p3g = Graphics.FromImage(b3); 56 | p3g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; 57 | p3g.DrawImage(b2, 0, 0, 24, 24); 58 | 59 | p2.Image = b3; -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Controls/FontListBox.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Text; 4 | using System.Linq; 5 | using System.Windows.Forms; 6 | 7 | namespace NextionFontEditor.Controls { 8 | public class FontListBox : ListBox { 9 | private int _padding = 3; 10 | 11 | private int _fontPreviewSize = 20; 12 | public int FontPreviewSize { 13 | get => _fontPreviewSize; 14 | set { 15 | _fontPreviewSize = value; 16 | Invalidate(); 17 | Update(); 18 | } 19 | } 20 | 21 | 22 | public FontListBox() { 23 | DrawMode = DrawMode.OwnerDrawVariable; 24 | LoadFontList(); 25 | } 26 | 27 | private void LoadFontList() { 28 | using (InstalledFontCollection col = new InstalledFontCollection()) { 29 | Items.AddRange(col.Families 30 | .OrderBy(x => x.Name) 31 | .Select(x => string.IsNullOrWhiteSpace(x.Name) ? "[No name]" : x.Name) 32 | .ToArray() 33 | ); 34 | } 35 | } 36 | 37 | 38 | protected override void OnMeasureItem(MeasureItemEventArgs e) { 39 | var fontName = Items[e.Index].ToString(); 40 | var font = new Font(fontName, _fontPreviewSize, GraphicsUnit.Pixel); 41 | var size = e.Graphics.MeasureString(fontName, font); 42 | 43 | e.ItemWidth = (int)Math.Ceiling(size.Width); 44 | e.ItemHeight = (int)Math.Ceiling(size.Height) + _padding * 2; 45 | } 46 | 47 | protected override void OnDrawItem(DrawItemEventArgs e) { 48 | e.DrawBackground(); 49 | 50 | var fontName = Items[e.Index].ToString(); 51 | var font = new Font(fontName, _fontPreviewSize, GraphicsUnit.Pixel); 52 | 53 | if ((e.State & DrawItemState.Selected) == DrawItemState.Selected) { 54 | e.Graphics.DrawString(fontName, font, SystemBrushes.HighlightText, e.Bounds.Left, e.Bounds.Top + _padding); 55 | } else { 56 | using (SolidBrush br = new SolidBrush(e.ForeColor)) { 57 | e.Graphics.DrawString(fontName, font, br, e.Bounds.Left, e.Bounds.Top + _padding); 58 | } 59 | } 60 | 61 | e.DrawFocusRectangle(); 62 | } 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Extensions/FormExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Runtime.InteropServices; 3 | using System.Windows.Forms; 4 | 5 | namespace NextionFontEditor.Extensions { 6 | 7 | public static class FormExtensions { 8 | 9 | [DllImport("user32.dll")] 10 | private static extern int GetWindowLong(IntPtr hWnd, int nIndex); 11 | 12 | [DllImport("user32.dll")] 13 | private static extern int SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong); 14 | 15 | [DllImport("user32.dll", ExactSpelling = true)] 16 | private static extern int SetWindowPos(IntPtr hWnd, IntPtr hWndInsertAfter, int X, int Y, int cx, int cy, uint uFlags); 17 | 18 | private const int GWL_EXSTYLE = -20; 19 | private const int WS_EX_CLIENTEDGE = 0x200; 20 | private const uint SWP_NOSIZE = 0x0001; 21 | private const uint SWP_NOMOVE = 0x0002; 22 | private const uint SWP_NOZORDER = 0x0004; 23 | private const uint SWP_NOREDRAW = 0x0008; 24 | private const uint SWP_NOACTIVATE = 0x0010; 25 | private const uint SWP_FRAMECHANGED = 0x0020; 26 | private const uint SWP_SHOWWINDOW = 0x0040; 27 | private const uint SWP_HIDEWINDOW = 0x0080; 28 | private const uint SWP_NOCOPYBITS = 0x0100; 29 | private const uint SWP_NOOWNERZORDER = 0x0200; 30 | private const uint SWP_NOSENDCHANGING = 0x0400; 31 | 32 | public static bool SetBevel(this Form form, bool show) { 33 | foreach (Control c in form.Controls) { 34 | MdiClient client = c as MdiClient; 35 | if (client != null) { 36 | int windowLong = GetWindowLong(c.Handle, GWL_EXSTYLE); 37 | 38 | if (show) { 39 | windowLong |= WS_EX_CLIENTEDGE; 40 | } else { 41 | windowLong &= ~WS_EX_CLIENTEDGE; 42 | } 43 | 44 | SetWindowLong(c.Handle, GWL_EXSTYLE, windowLong); 45 | 46 | // Update the non-client area. 47 | SetWindowPos(client.Handle, IntPtr.Zero, 0, 0, 0, 0, 48 | SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 49 | SWP_NOOWNERZORDER | SWP_FRAMECHANGED); 50 | 51 | return true; 52 | } 53 | } 54 | return false; 55 | } 56 | 57 | } 58 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormCharacterWidth.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.ComponentModel; 4 | using System.Data; 5 | using System.Drawing; 6 | using System.Linq; 7 | using System.Text; 8 | using System.Threading.Tasks; 9 | using System.Windows.Forms; 10 | 11 | namespace NextionFontEditor { 12 | public partial class FormCharacterWidth : Form { 13 | public FormCharacterWidth() { 14 | InitializeComponent(); 15 | } 16 | 17 | private void btnCancel_Click(object sender, EventArgs e) { 18 | this.DialogResult = DialogResult.Cancel; 19 | this.Close(); 20 | } 21 | 22 | private void btnOK_Click(object sender, EventArgs e) { 23 | this.DialogResult = DialogResult.OK; 24 | this.Close(); 25 | } 26 | 27 | private void txtWidth_TextChanged(object sender, EventArgs e) { 28 | 29 | } 30 | 31 | private void numWidth_ValueChanged(object sender, EventArgs e) { 32 | numKerningL.Maximum = numWidth.Value - numKerningR.Value - 1; 33 | if (numKerningL.Value > (numWidth.Value - numKerningR.Value - 1)) 34 | numKerningL.Value = numWidth.Value - numKerningR.Value - 1; 35 | 36 | numKerningR.Maximum = numWidth.Value - numKerningL.Value - 1; 37 | if (numKerningR.Value > (numWidth.Value - numKerningL.Value - 1)) 38 | numKerningR.Value = numWidth.Value - numKerningL.Value - 1; 39 | } 40 | 41 | private void numKerningL_ValueChanged(object sender, EventArgs e) { 42 | numWidth.Minimum = numKerningL.Value + numKerningR.Value + 1; 43 | numKerningR.Maximum = numWidth.Value - numKerningL.Value - 1; 44 | if (numWidth.Value < (numKerningL.Value + numKerningR.Value + 1)) 45 | numWidth.Value = numKerningL.Value + numKerningR.Value + 1; 46 | } 47 | 48 | private void numKerningR_ValueChanged(object sender, EventArgs e) { 49 | numWidth.Minimum = numKerningL.Value + numKerningR.Value + 1; 50 | numKerningL.Maximum = numWidth.Value - numKerningR.Value - 1; 51 | if (numWidth.Value < (numKerningL.Value + numKerningR.Value + 1)) 52 | numWidth.Value = numKerningL.Value + numKerningR.Value + 1; 53 | } 54 | 55 | private void lblKerningL_Click(object sender, EventArgs e) { 56 | 57 | } 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/CodePageIdentifier.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Linq; 3 | using System.Reflection; 4 | using System.ComponentModel; 5 | 6 | namespace ZiLib 7 | { 8 | 9 | public enum CodePageIdentifier : byte 10 | { 11 | [Description("ascii")] 12 | ASCII = 0x01, 13 | [Description("gb2312")] 14 | GB2312 = 0x02, 15 | [Description("iso-8859-1")] 16 | ISO_8859_1 = 0x03, 17 | [Description("iso-8859-2")] 18 | ISO_8859_2 = 0x04, 19 | [Description("iso-8859-3")] 20 | ISO_8859_3 = 0x05, 21 | [Description("iso-8859-4")] 22 | ISO_8859_4 = 0x06, 23 | [Description("iso-8859-5")] 24 | ISO_8859_5 = 0x07, 25 | [Description("iso-8859-6")] 26 | ISO_8859_6 = 0x08, 27 | [Description("iso-8859-7")] 28 | ISO_8859_7 = 0x09, 29 | [Description("iso-8859-8")] 30 | ISO_8859_8 = 0x0A, 31 | [Description("iso-8859-9")] 32 | ISO_8859_9 = 0x0B, 33 | [Description("iso-8859-13")] 34 | ISO_8859_13 = 0x0C, 35 | [Description("iso-8859-15")] 36 | ISO_8859_15 = 0x0D, 37 | [Description("iso-8859-11")] 38 | ISO_8859_11 = 0x0E, 39 | [Description("ks_c_5601-1987")] 40 | KS_C_5601_1987 = 0x0F, 41 | [Description("big5")] 42 | BIG5 = 0x10, 43 | [Description("windows-1255")] 44 | WINDOWS_1255 = 0x11, 45 | [Description("windows-1256")] 46 | WINDOWS_1256 = 0x12, 47 | [Description("windows-1257")] 48 | WINDOWS_1257 = 0x13, 49 | [Description("windows-1258")] 50 | WINDOWS_1258 = 0x14, 51 | [Description("windows-874")] 52 | WINDOWS_874 = 0x15, 53 | [Description("koi8-r")] 54 | KOI8_R = 0x16, 55 | [Description("shift-jis")] 56 | SHIFT_JIS = 0x17, 57 | [Description("utf-8")] 58 | UTF_8 = 0x18 59 | } 60 | 61 | } 62 | 63 | public static class Extensions 64 | { 65 | public static string GetDescription(this Enum e) 66 | { 67 | var attribute = 68 | e.GetType() 69 | .GetTypeInfo() 70 | .GetMember(e.ToString()) 71 | .FirstOrDefault(member => member.MemberType == MemberTypes.Field) 72 | .GetCustomAttributes(typeof(DescriptionAttribute), false) 73 | .SingleOrDefault() 74 | as DescriptionAttribute; 75 | 76 | return attribute?.Description ?? e.ToString(); 77 | } 78 | } -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | ############################################################################### 2 | # Set default behavior to automatically normalize line endings. 3 | ############################################################################### 4 | * text=auto 5 | 6 | ############################################################################### 7 | # Set default behavior for command prompt diff. 8 | # 9 | # This is need for earlier builds of msysgit that does not have it on by 10 | # default for csharp files. 11 | # Note: This is only used by command line 12 | ############################################################################### 13 | #*.cs diff=csharp 14 | 15 | ############################################################################### 16 | # Set the merge driver for project and solution files 17 | # 18 | # Merging from the command prompt will add diff markers to the files if there 19 | # are conflicts (Merging from VS is not affected by the settings below, in VS 20 | # the diff markers are never inserted). Diff markers may cause the following 21 | # file extensions to fail to load in VS. An alternative would be to treat 22 | # these files as binary and thus will always conflict and require user 23 | # intervention with every merge. To do so, just uncomment the entries below 24 | ############################################################################### 25 | #*.sln merge=binary 26 | #*.csproj merge=binary 27 | #*.vbproj merge=binary 28 | #*.vcxproj merge=binary 29 | #*.vcproj merge=binary 30 | #*.dbproj merge=binary 31 | #*.fsproj merge=binary 32 | #*.lsproj merge=binary 33 | #*.wixproj merge=binary 34 | #*.modelproj merge=binary 35 | #*.sqlproj merge=binary 36 | #*.wwaproj merge=binary 37 | 38 | ############################################################################### 39 | # behavior for image files 40 | # 41 | # image files are treated as binary by default. 42 | ############################################################################### 43 | #*.jpg binary 44 | #*.png binary 45 | #*.gif binary 46 | 47 | ############################################################################### 48 | # diff behavior for common document formats 49 | # 50 | # Convert binary document formats to text before diffing them. This feature 51 | # is only available from the command line. Turn it on by uncommenting the 52 | # entries below. 53 | ############################################################################### 54 | #*.doc diff=astextplain 55 | #*.DOC diff=astextplain 56 | #*.docx diff=astextplain 57 | #*.DOCX diff=astextplain 58 | #*.dot diff=astextplain 59 | #*.DOT diff=astextplain 60 | #*.pdf diff=astextplain 61 | #*.PDF diff=astextplain 62 | #*.rtf diff=astextplain 63 | #*.RTF diff=astextplain 64 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Nextion Font Suite 2 | 3 | A collection of tools to work with Nextion Fonts. 4 | 5 | ### Builds 6 | | Branch | Status | 7 | |--------|--------| 8 | | master | [![Build status](https://ci.appveyor.com/api/projects/status/kmi5iikvsod53c4p?svg=true)](https://ci.appveyor.com/project/hagronnestad/nextion-font-editor) | 9 | 10 | ### Binaries 11 | | Version | Link | 12 | |---------|------| 13 | | Stable | https://github.com/hagronnestad/nextion-font-editor/releases | 14 | | Latest | https://ci.appveyor.com/project/hagronnestad/nextion-font-editor/build/artifacts | 15 | 16 | ### Contributors 17 | | User | Feature | Pull request | 18 | |--------|--------|--------| 19 | | [@jyberg](https://github.com/jyberg) | Font generator | [#2](https://github.com/hagronnestad/nextion-font-editor/pull/2) | 20 | | [@fvanroie](https://github.com/fvanroie) | .ZI v5/v6 support | [#7](https://github.com/hagronnestad/nextion-font-editor/pull/7) | 21 | 22 | ## Roadmap 23 | 24 | #### Prioritized tasks 25 | - [x] Reverse engineering of the new Nextion font format (v5/v6) 26 | - [x] Support for anti-aliased and variable width fonts (v5/v6) 27 | 28 | #### Less prioritized tasks 29 | - [x] Reverse engineering of the Nextion font format version 3 for Nextion Editor V0.53 30 | - [x] Font Viewer 31 | - [x] Font Editor 32 | - [x] Font generator 33 | - [x] Support for most code pages supported by Nextion Editor 34 | - [x] ASCII 35 | - [x] ISO-8859-1 36 | - [x] Others 37 | 38 | > Sample screenshot of the "Font Editor"-tool previewing the `$` character from the `Arial_40_ascii.zi` file. 39 | 40 | ![](Screenshots/02-thumb.png) 41 | 42 | > Sample screenshot of the "Font Preview"-tool previewing the `Arial_40_ascii.zi` file. 43 | 44 | ![](Screenshots/01-thumb.png) 45 | 46 | ## Nextion .ZI Font Format Specification 47 | 48 | ### ZI version 3 specification 49 | 50 | A mostly complete reverse engineered specification of the Nextion font format (ZI version 3), can be found here: 51 | 52 | [ZI version 3 specification](Docs/Nextion%20Font%20Format%20Specification%20ZI%20version%203.md) 53 | 54 | ### ZI version 5 specification 55 | 56 | I recently started reverse engineering the new ZI file format version 5 used in TJCs USART HMI editor version `0.55`. ZI version 5 supports variable width fonts and antialiasing. This specification is very much a work in progress. Feel free to contribute. 57 | 58 | [ZI version 5 specification (❗ Work in progress ❗)](Docs/Nextion%20Font%20Format%20Specification%20ZI%20version%205.md) 59 | 60 | ### TJCs USART HMI English Patch 61 | If you want to try the new font features and have a TJC panel, you can use this patch to run USART HMI in english. 62 | 63 | [TJCs USART HMI English Patch](https://github.com/hagronnestad/tjc-usart-hmi-english-patch) 64 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Properties/Resources.Designer.cs: -------------------------------------------------------------------------------- 1 | //------------------------------------------------------------------------------ 2 | // 3 | // This code was generated by a tool. 4 | // Runtime Version:4.0.30319.42000 5 | // 6 | // Changes to this file may cause incorrect behavior and will be lost if 7 | // the code is regenerated. 8 | // 9 | //------------------------------------------------------------------------------ 10 | 11 | namespace NextionFontEditor.Properties 12 | { 13 | 14 | 15 | /// 16 | /// A strongly-typed resource class, for looking up localized strings, etc. 17 | /// 18 | // This class was auto-generated by the StronglyTypedResourceBuilder 19 | // class via a tool like ResGen or Visual Studio. 20 | // To add or remove a member, edit your .ResX file then rerun ResGen 21 | // with the /str option, or rebuild your VS project. 22 | [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] 23 | [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] 24 | [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] 25 | internal class Resources 26 | { 27 | 28 | private static global::System.Resources.ResourceManager resourceMan; 29 | 30 | private static global::System.Globalization.CultureInfo resourceCulture; 31 | 32 | [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] 33 | internal Resources() 34 | { 35 | } 36 | 37 | /// 38 | /// Returns the cached ResourceManager instance used by this class. 39 | /// 40 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 41 | internal static global::System.Resources.ResourceManager ResourceManager 42 | { 43 | get 44 | { 45 | if ((resourceMan == null)) 46 | { 47 | global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("NextionFontEditor.Properties.Resources", typeof(Resources).Assembly); 48 | resourceMan = temp; 49 | } 50 | return resourceMan; 51 | } 52 | } 53 | 54 | /// 55 | /// Overrides the current thread's CurrentUICulture property for all 56 | /// resource lookups using this strongly typed resource class. 57 | /// 58 | [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] 59 | internal static global::System.Globalization.CultureInfo Culture 60 | { 61 | get 62 | { 63 | return resourceCulture; 64 | } 65 | set 66 | { 67 | resourceCulture = value; 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/ZiLib.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {656212B8-63AB-4C9D-A654-59F54AB10EA5} 8 | Library 9 | Properties 10 | ZiLib 11 | ZiLib 12 | v4.6.1 13 | 512 14 | true 15 | 16 | 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | pdbonly 27 | true 28 | bin\Release\ 29 | TRACE 30 | prompt 31 | 4 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/CodePages.cs: -------------------------------------------------------------------------------- 1 | using System.Collections.Generic; 2 | using System.Linq; 3 | using System.Text; 4 | 5 | namespace ZiLib.FileVersion.Common { 6 | ///* 7 | //public class CodePages { 8 | 9 | // public static CodePage CreateAscii() { 10 | // var start = 32; 11 | // var count = 95; 12 | // var bytes = Enumerable.Range(start, count).Select(x => (byte) x).ToArray(); 13 | // var characters = Encoding.ASCII.GetChars(bytes); 14 | 15 | // return new CodePage(CodePageIdentifier.ASCII); 16 | 17 | // /* 18 | // return new CodePage { 19 | // CodePageIdentifier = CodePageIdentifier.ASCII, 20 | // FirstByteStart = (byte)start, 21 | // FirstByteEnd = (byte)(start + count), 22 | // CharacterCount = count, 23 | // Characters = characters 24 | // }; 25 | // */ 26 | // } 27 | 28 | // public static CodePage CreateIso_8859_1() { 29 | // var start = 32; 30 | // var count = 224; 31 | // var bytes = Enumerable.Range(start, count).Select(x => (byte) x).ToArray(); 32 | // var encoding = Encoding.GetEncoding("ISO-8859-1"); 33 | // var characters = encoding.GetChars(bytes); 34 | 35 | // return new CodePage(CodePageIdentifier.ISO_8859_1); 36 | 37 | // /* 38 | // return new CodePage { 39 | // CodePageIdentifier = CodePageIdentifier.ISO_8859_1, 40 | // FirstByteStart = (byte)start, 41 | // FirstByteEnd = (byte)(start + count), 42 | // CharacterCount = count, 43 | // Characters = characters 44 | // }; 45 | // */ 46 | // } 47 | 48 | // // This one is not working correctly, characters doesn't match the Font Generator in Nextion Editor 49 | // public static CodePage CreateBig5() { 50 | // var firstByteStart = (byte)0xA0; 51 | // var firstByteEnd = (byte)0xF9; 52 | // var secondByteStart = (byte)0x40; 53 | // var secondByteEnd = (byte)0xFE; 54 | 55 | // var bytes = new List(); 56 | 57 | // for (int i = firstByteStart; i <= firstByteEnd; i++) { 58 | // for (int j = secondByteStart; j <= secondByteEnd; j++) { 59 | // bytes.Add((byte) i); 60 | // bytes.Add((byte) j); 61 | // } 62 | // } 63 | 64 | // var encoding = Encoding.GetEncoding("big5"); 65 | // var characters = encoding.GetChars(bytes.ToArray()); 66 | 67 | // return new CodePage(CodePageIdentifier.BIG5); 68 | 69 | // /* 70 | // return new CodePage { 71 | // CodePageIdentifier = CodePageIdentifier.BIG5, 72 | // FirstByteStart = firstByteStart, 73 | // FirstByteEnd = firstByteEnd, 74 | // SecondByteStart = secondByteStart, 75 | // SecondByteEnd = secondByteEnd, 76 | // CharacterCount = 0, 77 | // Characters = characters 78 | // }; 79 | // */ 80 | // } 81 | 82 | // public static CodePage GetCodePage(CodePageIdentifier codePage) { 83 | // switch (codePage) { 84 | // case CodePageIdentifier.ASCII: 85 | // return CreateAscii(); 86 | 87 | // case CodePageIdentifier.ISO_8859_1: 88 | // return CreateIso_8859_1(); 89 | 90 | // case CodePageIdentifier.BIG5: 91 | // return CreateBig5(); 92 | // } 93 | 94 | // return null; 95 | // } 96 | //}*/ 97 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/ZiClipboard.cs: -------------------------------------------------------------------------------- 1 | using System.Windows.Forms; 2 | using System.Drawing; 3 | using System.IO; 4 | 5 | namespace ZiLib.FileVersion.Common 6 | { 7 | public static class ZiClipboard 8 | { 9 | public static void CopyToClipboard(IZiCharacter character) { 10 | var bmp = character.ToBitmap(); 11 | if (bmp == null) { 12 | return; 13 | } 14 | // Remove transparency 15 | var clip = new Bitmap(bmp.Width, bmp.Height); 16 | Color color; 17 | 18 | using (var graphics = Graphics.FromImage(clip)) { 19 | graphics.FillRectangle(Brushes.White, 0, 0, clip.Width, clip.Height); 20 | //graphics.DrawImage(bmp, 0, 0); 21 | } 22 | 23 | // Remove ForegroundColor, replace with black 24 | for (int y = 0; y < bmp.Height; y++) { 25 | for (int x = 0; x < bmp.Width; x++) { 26 | color = Color.FromArgb(bmp.GetPixel(x, y).A, Color.Black); 27 | clip.SetPixel(x, y, color); 28 | } 29 | } 30 | 31 | var clip2 = new Bitmap(bmp.Width, bmp.Height); 32 | 33 | using (var graphics = Graphics.FromImage(clip2)) { 34 | graphics.FillRectangle(Brushes.White, 0, 0, clip.Width, clip.Height); 35 | graphics.DrawImage(clip, 0, 0); 36 | } 37 | 38 | Clipboard.SetImage(clip2); 39 | clip.Dispose(); 40 | clip2.Dispose(); 41 | } 42 | 43 | public static bool PasteFromClipboard(IZiCharacter character) { 44 | try 45 | { 46 | if (Clipboard.ContainsData("PNG")) 47 | { 48 | object png = Clipboard.GetData("PNG"); 49 | if (png is MemoryStream) 50 | { 51 | MemoryStream pngstream = png as MemoryStream; 52 | var clip = Image.FromStream(pngstream); 53 | var newbmp = Convert(new Bitmap(clip)); 54 | character.SetBitmap(newbmp); 55 | clip.Dispose(); 56 | return true; 57 | } 58 | 59 | } 60 | } 61 | catch { 62 | } 63 | 64 | if (Clipboard.ContainsImage()) { 65 | var clip = Clipboard.GetImage(); 66 | if (clip.Height > character.Parent.CharacterHeight) 67 | { 68 | var newbmp = Convert(new Bitmap(clip)); 69 | character.SetBitmap(newbmp); 70 | clip.Dispose(); 71 | return true; 72 | } 73 | else { 74 | var newbmp = Convert(new Bitmap(clip)); 75 | character.SetBitmap(newbmp); 76 | clip.Dispose(); 77 | return true; 78 | } 79 | } 80 | 81 | return false; 82 | } 83 | 84 | private static Color GetAlphaColor(Color pixel) { 85 | var curColor = (byte)(255 - (pixel.R + 2 * pixel.G + pixel.B) / 4); // Weighted Color2Grayscale; 86 | return Color.FromArgb(curColor, Color.Black); 87 | } 88 | 89 | private static Bitmap Convert(Bitmap clip) { 90 | var bmp = new Bitmap(clip.Width, clip.Height); 91 | Color color; 92 | for (int y = 0; y < bmp.Height; y++) { 93 | for (int x = 0; x < bmp.Width; x++) { 94 | color = GetAlphaColor(clip.GetPixel(x,y)); 95 | bmp.SetPixel(x, y, color); 96 | } 97 | } 98 | return bmp; 99 | } 100 | 101 | public static bool ContainsImage() { 102 | return Clipboard.ContainsImage() || Clipboard.ContainsData("PNG"); 103 | } 104 | 105 | } 106 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormFontPreview.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.IO; 4 | using System.Windows.Forms; 5 | using ZiLib; 6 | using ZiLib.FileVersion.Common; 7 | 8 | namespace NextionFontEditor { 9 | 10 | public partial class FormFontPreview : Form { 11 | 12 | public FormFontPreview() { 13 | InitializeComponent(); 14 | } 15 | 16 | private void FormFontPreview_Load(object sender, EventArgs e) { 17 | var p = new PictureBox() { 18 | Width = 16, 19 | Height = 32, 20 | BorderStyle = BorderStyle.FixedSingle, 21 | BackColor = Color.White 22 | }; 23 | 24 | flowPanel.Controls.Add(p); 25 | } 26 | 27 | private void CreateCharacterPreview(IZiFont font) { 28 | flowPanel.Controls.Clear(); 29 | this.SuspendLayout(); 30 | 31 | for (int i = 0; i < font.Characters.Count; i++) { 32 | var b = font.Characters[i].ToBitmap(); 33 | if (b != null && b.PixelFormat != System.Drawing.Imaging.PixelFormat.Undefined) { 34 | var p = new PictureBox() { 35 | Width = b.Width + 2, 36 | Height = font.CharacterHeight + 2, 37 | Image = b, 38 | BorderStyle = BorderStyle.FixedSingle, 39 | BackColor = Color.White 40 | }; 41 | flowPanel.Controls.Add(p); 42 | } else { 43 | var img = new Bitmap(font.CharacterHeight + 2, 2); 44 | var p = new PictureBox() { 45 | Width = 2, 46 | Height = font.CharacterHeight + 2, 47 | Image = img, 48 | BorderStyle = BorderStyle.FixedSingle, 49 | BackColor = Color.White 50 | }; 51 | 52 | flowPanel.Controls.Add(p); 53 | } 54 | if (i >= 1024) { break; } 55 | } 56 | this.ResumeLayout(); 57 | } 58 | 59 | private void CreateCharacterPreview2(IZiFont font) { 60 | flowPanel.Controls.Clear(); 61 | this.SuspendLayout(); 62 | 63 | var preview = new Bitmap(flowPanel.Width - 15, flowPanel.Height - 15); 64 | var x = 0; 65 | var y = 0; 66 | 67 | using (var graphics = Graphics.FromImage(preview)) { 68 | graphics.FillRectangle(Brushes.Transparent, 0, 0, preview.Width, preview.Height); 69 | 70 | foreach (var ch in font.Characters) { 71 | var b = ch.ToBitmap(); 72 | 73 | if ((x + b.Width) > preview.Width) { 74 | x = 0; 75 | y += b.Height; 76 | } 77 | 78 | if (y >= preview.Height) { break; } 79 | 80 | graphics.DrawImage(b, x, y); 81 | x += b.Width; 82 | } 83 | 84 | } 85 | 86 | var p = new PictureBox() { 87 | Width = preview.Width, 88 | Height = preview.Height, 89 | Image = preview, 90 | BorderStyle = BorderStyle.FixedSingle, 91 | BackColor = Color.Black 92 | }; 93 | 94 | flowPanel.Controls.Add(p); 95 | 96 | this.ResumeLayout(); 97 | } 98 | 99 | 100 | private void btnOpen_Click(object sender, EventArgs e) { 101 | var res = ofd.ShowDialog(); 102 | 103 | if (res == DialogResult.OK) { 104 | var zifont = ZiFont.FromFile(ofd.FileName); 105 | CreateCharacterPreview2(zifont); 106 | 107 | lblFile.Text = Path.GetFileName(ofd.FileName); 108 | lblFontName.Text = zifont.Name; 109 | lblCodePage.Text = zifont.CodePage.CodePageIdentifier.ToString(); 110 | 111 | lblWidth.Text = zifont.CharacterWidth.ToString(); 112 | lblHeight.Text = zifont.CharacterHeight.ToString(); 113 | lblCharacters.Text = zifont.CodePage.CharacterCount.ToString(); 114 | 115 | lblFileSize.Text = zifont.FileSize.ToString(); 116 | lblFileVersion.Text = zifont.Version.ToString(); 117 | //lblBytesPerChar.Text = zifont.BytesPerChar.ToString(); 118 | } 119 | } 120 | } 121 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/Extensions/BitmapExtensions.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Drawing; 4 | using System.IO; 5 | 6 | namespace ZiLib.Extensions { 7 | 8 | public static class BitmapExtensions { 9 | 10 | public static void SetPixelNumber(this Bitmap b, int number, Color color) { 11 | if (number >= b.Width * b.Height) { 12 | Debug.WriteLine($"!!! pixelNumber >= {b.Width * b.Height} !!!"); 13 | return; 14 | } 15 | 16 | var l = NumberToPoint(number, b.Width); 17 | b.SetPixel(l.X, l.Y, color); 18 | } 19 | 20 | public static Point NumberToPoint(int number, int width) { 21 | var p = new Point { 22 | Y = (int) Math.Floor((double) number / width), 23 | X = number % width 24 | }; 25 | return p; 26 | } 27 | 28 | public static Bitmap DrawString(string txt, string fontname, byte height, FontStyle style = FontStyle.Regular, byte x = 0, byte y = 0, byte contrast = 0) 29 | { 30 | var fontsize = (float)height; 31 | 32 | var strFormat = (StringFormat)StringFormat.GenericTypographic.Clone(); 33 | strFormat.FormatFlags = strFormat.FormatFlags | StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.NoFontFallback; 34 | 35 | var tmp = new Bitmap(1, 1); 36 | var grphtmp = Graphics.FromImage(tmp); 37 | 38 | var font = new Font("Arial", 12); 39 | 40 | // Check if it is a otf/ttf file 41 | if (((Path.GetExtension(fontname) == ".ttf") || (Path.GetExtension(fontname) == ".otf")) && (File.Exists(fontname))) 42 | { 43 | 44 | var pfc = new System.Drawing.Text.PrivateFontCollection(); 45 | pfc.AddFontFile(fontname); 46 | 47 | var i = 0; 48 | 49 | font = new Font(pfc.Families[0], fontsize, style, GraphicsUnit.Pixel); 50 | while (Math.Abs(font.Height - height) > 0.1 && i++<10) 51 | { 52 | fontsize += (float)(height - font.Height) / 2; 53 | font = new Font(pfc.Families[0], fontsize, style, GraphicsUnit.Pixel); 54 | } 55 | 56 | /*while (font.Height > height) 57 | { 58 | fontsize -= (float)0.02; 59 | font.Dispose(); 60 | font = new Font(pfc.Families[0], fontsize, style, GraphicsUnit.Pixel); 61 | }*/ 62 | 63 | // System Font 64 | } 65 | else 66 | { 67 | font = new Font(fontname, fontsize, style, GraphicsUnit.Pixel); 68 | while (Math.Abs(font.Height - height) > 0.1) 69 | { 70 | fontsize += (float)(height - font.Height) / 2; 71 | font = new Font(fontname, fontsize, style, GraphicsUnit.Pixel); 72 | } 73 | 74 | } 75 | var width = (int)Math.Round((grphtmp.MeasureString(txt, font, new PointF(0, 0), strFormat)).Width); 76 | width = width > 255 ? 255 : width; 77 | 78 | if (width > 0) 79 | { 80 | var b = new Bitmap(width, height); 81 | var graphics = Graphics.FromImage(b); 82 | 83 | //Adjust for high quality 84 | graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 85 | graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 86 | graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 87 | graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // AntiAlias // HighQuality 88 | graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; //AntiAliasGridFit; // (B/W = SingleBitPerPixelGridFit) 89 | 90 | var brushBg = Brushes.White; 91 | var brushFg = Brushes.Black; 92 | 93 | graphics.FillRectangle(brushBg, 0, 0, b.Width, b.Height); 94 | graphics.TextContrast = contrast; 95 | graphics.DrawString(txt, font, brushFg, x, y, strFormat); // experimental 96 | //TextRenderer.DrawText(graphics, txt, font, new Point(x, y), Color.Black, Color.White); 97 | graphics.Dispose(); 98 | return b; 99 | 100 | } 101 | else 102 | { 103 | // Nextion requires a minimum width of 1 pixel. It doesn't like zero length chardata as it crashes the Application when rotating the font. 104 | var b = new Bitmap(1, height); 105 | //b.Dispose(); 106 | return b; 107 | } 108 | 109 | } 110 | 111 | } 112 | } -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | ## Ignore Visual Studio temporary files, build results, and 2 | ## files generated by popular Visual Studio add-ons. 3 | 4 | # User-specific files 5 | *.suo 6 | *.user 7 | *.userosscache 8 | *.sln.docstates 9 | 10 | # User-specific files (MonoDevelop/Xamarin Studio) 11 | *.userprefs 12 | 13 | # Build results 14 | [Dd]ebug/ 15 | [Dd]ebugPublic/ 16 | [Rr]elease/ 17 | [Rr]eleases/ 18 | x64/ 19 | x86/ 20 | bld/ 21 | [Bb]in/ 22 | [Oo]bj/ 23 | [Ll]og/ 24 | 25 | # Visual Studio 2015 cache/options directory 26 | .vs/ 27 | # Uncomment if you have tasks that create the project's static files in wwwroot 28 | #wwwroot/ 29 | 30 | # MSTest test Results 31 | [Tt]est[Rr]esult*/ 32 | [Bb]uild[Ll]og.* 33 | 34 | # NUNIT 35 | *.VisualState.xml 36 | TestResult.xml 37 | 38 | # Build Results of an ATL Project 39 | [Dd]ebugPS/ 40 | [Rr]eleasePS/ 41 | dlldata.c 42 | 43 | # DNX 44 | project.lock.json 45 | project.fragment.lock.json 46 | artifacts/ 47 | 48 | *_i.c 49 | *_p.c 50 | *_i.h 51 | *.ilk 52 | *.meta 53 | *.obj 54 | *.pch 55 | *.pdb 56 | *.pgc 57 | *.pgd 58 | *.rsp 59 | *.sbr 60 | *.tlb 61 | *.tli 62 | *.tlh 63 | *.tmp 64 | *.tmp_proj 65 | *.log 66 | *.vspscc 67 | *.vssscc 68 | .builds 69 | *.pidb 70 | *.svclog 71 | *.scc 72 | 73 | # Chutzpah Test files 74 | _Chutzpah* 75 | 76 | # Visual C++ cache files 77 | ipch/ 78 | *.aps 79 | *.ncb 80 | *.opendb 81 | *.opensdf 82 | *.sdf 83 | *.cachefile 84 | *.VC.db 85 | *.VC.VC.opendb 86 | 87 | # Visual Studio profiler 88 | *.psess 89 | *.vsp 90 | *.vspx 91 | *.sap 92 | 93 | # TFS 2012 Local Workspace 94 | $tf/ 95 | 96 | # Guidance Automation Toolkit 97 | *.gpState 98 | 99 | # ReSharper is a .NET coding add-in 100 | _ReSharper*/ 101 | *.[Rr]e[Ss]harper 102 | *.DotSettings.user 103 | 104 | # JustCode is a .NET coding add-in 105 | .JustCode 106 | 107 | # TeamCity is a build add-in 108 | _TeamCity* 109 | 110 | # DotCover is a Code Coverage Tool 111 | *.dotCover 112 | 113 | # NCrunch 114 | _NCrunch_* 115 | .*crunch*.local.xml 116 | nCrunchTemp_* 117 | 118 | # MightyMoose 119 | *.mm.* 120 | AutoTest.Net/ 121 | 122 | # Web workbench (sass) 123 | .sass-cache/ 124 | 125 | # Installshield output folder 126 | [Ee]xpress/ 127 | 128 | # DocProject is a documentation generator add-in 129 | DocProject/buildhelp/ 130 | DocProject/Help/*.HxT 131 | DocProject/Help/*.HxC 132 | DocProject/Help/*.hhc 133 | DocProject/Help/*.hhk 134 | DocProject/Help/*.hhp 135 | DocProject/Help/Html2 136 | DocProject/Help/html 137 | 138 | # Click-Once directory 139 | publish/ 140 | 141 | # Publish Web Output 142 | *.[Pp]ublish.xml 143 | *.azurePubxml 144 | # TODO: Comment the next line if you want to checkin your web deploy settings 145 | # but database connection strings (with potential passwords) will be unencrypted 146 | #*.pubxml 147 | *.publishproj 148 | 149 | # Microsoft Azure Web App publish settings. Comment the next line if you want to 150 | # checkin your Azure Web App publish settings, but sensitive information contained 151 | # in these scripts will be unencrypted 152 | PublishScripts/ 153 | 154 | # NuGet Packages 155 | *.nupkg 156 | # The packages folder can be ignored because of Package Restore 157 | **/packages/* 158 | # except build/, which is used as an MSBuild target. 159 | !**/packages/build/ 160 | # Uncomment if necessary however generally it will be regenerated when needed 161 | #!**/packages/repositories.config 162 | # NuGet v3's project.json files produces more ignoreable files 163 | *.nuget.props 164 | *.nuget.targets 165 | 166 | # Microsoft Azure Build Output 167 | csx/ 168 | *.build.csdef 169 | 170 | # Microsoft Azure Emulator 171 | ecf/ 172 | rcf/ 173 | 174 | # Windows Store app package directories and files 175 | AppPackages/ 176 | BundleArtifacts/ 177 | Package.StoreAssociation.xml 178 | _pkginfo.txt 179 | 180 | # Visual Studio cache files 181 | # files ending in .cache can be ignored 182 | *.[Cc]ache 183 | # but keep track of directories ending in .cache 184 | !*.[Cc]ache/ 185 | 186 | # Others 187 | ClientBin/ 188 | ~$* 189 | *~ 190 | *.dbmdl 191 | *.dbproj.schemaview 192 | *.jfm 193 | *.pfx 194 | *.publishsettings 195 | node_modules/ 196 | orleans.codegen.cs 197 | 198 | # Since there are multiple workflows, uncomment next line to ignore bower_components 199 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) 200 | #bower_components/ 201 | 202 | # RIA/Silverlight projects 203 | Generated_Code/ 204 | 205 | # Backup & report files from converting an old project file 206 | # to a newer Visual Studio version. Backup files are not needed, 207 | # because we have git ;-) 208 | _UpgradeReport_Files/ 209 | Backup*/ 210 | UpgradeLog*.XML 211 | UpgradeLog*.htm 212 | 213 | # SQL Server files 214 | *.mdf 215 | *.ldf 216 | 217 | # Business Intelligence projects 218 | *.rdl.data 219 | *.bim.layout 220 | *.bim_*.settings 221 | 222 | # Microsoft Fakes 223 | FakesAssemblies/ 224 | 225 | # GhostDoc plugin setting file 226 | *.GhostDoc.xml 227 | 228 | # Node.js Tools for Visual Studio 229 | .ntvs_analysis.dat 230 | 231 | # Visual Studio 6 build log 232 | *.plg 233 | 234 | # Visual Studio 6 workspace options file 235 | *.opt 236 | 237 | # Visual Studio LightSwitch build output 238 | **/*.HTMLClient/GeneratedArtifacts 239 | **/*.DesktopClient/GeneratedArtifacts 240 | **/*.DesktopClient/ModelManifest.xml 241 | **/*.Server/GeneratedArtifacts 242 | **/*.Server/ModelManifest.xml 243 | _Pvt_Extensions 244 | 245 | # Paket dependency manager 246 | .paket/paket.exe 247 | paket-files/ 248 | 249 | # FAKE - F# Make 250 | .fake/ 251 | 252 | # JetBrains Rider 253 | .idea/ 254 | *.sln.iml 255 | 256 | # CodeRush 257 | .cr/ 258 | 259 | # Python Tools for Visual Studio (PTVS) 260 | __pycache__/ 261 | *.pyc 262 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Properties/Resources.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | text/microsoft-resx 107 | 108 | 109 | 2.0 110 | 111 | 112 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 113 | 114 | 115 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormFontGenerator.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Drawing; 5 | using System.Drawing.Text; 6 | using System.Linq; 7 | using System.Windows.Forms; 8 | using ZiLib.FileVersion.Common; 9 | using ZiLib.FileVersion.V3; 10 | 11 | namespace NextionFontEditor { 12 | 13 | public partial class FormFontGenerator : Form { 14 | 15 | public FormFontGenerator() { 16 | InitializeComponent(); 17 | } 18 | 19 | private ZiFontV3 ziFont = new ZiFontV3(); 20 | 21 | private void FormFontGenerator_Load(object sender, EventArgs e) { 22 | InitializeNextionFontSizesList(); 23 | 24 | //new FormFontPreview().Show(); 25 | } 26 | 27 | private void InitializeNextionFontSizesList() { 28 | for (int i = 8; i <= 255; i += 8) { 29 | cmbNextionFontSize.Items.Add(i); 30 | } 31 | 32 | cmbNextionFontSize.Text = "16"; 33 | numFontSize.Value = 16; 34 | } 35 | 36 | public Graphics CreateGraphics(Bitmap bitmap = null) { 37 | var b = bitmap ?? new Bitmap(1, 1); 38 | var g = Graphics.FromImage(b); 39 | 40 | g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; 41 | g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; 42 | g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; 43 | g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; 44 | 45 | return g; 46 | } 47 | 48 | private void CreatePreview() { 49 | var codePage = new CodePage(ZiLib.CodePageIdentifier.ISO_8859_1); 50 | 51 | var fontName = lstFonts.SelectedItem?.ToString() ?? ""; 52 | var fontSize = (int)numFontSize.Value; 53 | 54 | var size = int.Parse(cmbNextionFontSize.Text); 55 | var width = size / 2; 56 | var height = size; 57 | 58 | var font = new Font(fontName, fontSize, GraphicsUnit.Pixel); 59 | 60 | var pPreviews = new List(); 61 | 62 | var bLightCoral = new SolidBrush(Color.LightCoral); 63 | var bLightGreen = new SolidBrush(Color.LightGreen); 64 | var bWhite = new SolidBrush(Color.White); 65 | var bBlack = new SolidBrush(Color.Black); 66 | 67 | foreach (var cp in codePage.CodePoints) { 68 | var bPreview = new Bitmap(width, height); 69 | var txt = codePage.Encoding.GetString(BitConverter.GetBytes(cp)); 70 | 71 | using (var gPreview = CreateGraphics(bPreview)) { 72 | 73 | var sChar = gPreview.MeasureString(txt, font, new PointF(0, 0), StringFormat.GenericTypographic).ToSize(); 74 | if (sChar.Width == 0) sChar.Width = 1; 75 | 76 | var bChar = new Bitmap(sChar.Width, sChar.Height); 77 | 78 | using (var gChar = CreateGraphics(bChar)) { 79 | var sb = PreviewTest.Checked ? 80 | bChar.Width > bPreview.Width ? bLightCoral : bLightGreen : 81 | PreviewBW.Checked ? bWhite : bBlack; 82 | 83 | gChar.FillRectangle(sb, 0, 0, sChar.Width, sChar.Height); 84 | 85 | gChar.DrawString(txt, font, 86 | PreviewWB.Checked ? bWhite : bBlack, 87 | (float)numCharOffsetX.Value, (float)numCharOffsetY.Value, StringFormat.GenericTypographic 88 | ); 89 | } 90 | 91 | gPreview.FillRectangle(PreviewTest.Checked ? 92 | bChar.Width > bPreview.Width ? bLightCoral : bLightGreen : 93 | PreviewBW.Checked ? bWhite : bBlack, 94 | 0, 0, width, height); 95 | 96 | if (bChar.Width > bPreview.Width) { 97 | gPreview.DrawImage(bChar, 0, 0, width, height); 98 | 99 | } else { 100 | gPreview.DrawImage(bChar, (width / 2) - (bChar.Width / 2), 0, bChar.Width, height); 101 | } 102 | } 103 | 104 | pPreviews.Add(bPreview); 105 | } 106 | 107 | panelPreview.SuspendLayout(); 108 | panelPreview.Controls.Clear(); 109 | panelPreview.BackColor = PreviewTest.Checked ? Color.Transparent : PreviewBW.Checked ? Color.White : Color.Black; 110 | panelPreview.Controls.AddRange( 111 | pPreviews.Select(x => new PictureBox() { 112 | Width = width, 113 | Height = height, 114 | Image = x, 115 | Margin = new Padding(3) 116 | }).ToArray()); 117 | panelPreview.ResumeLayout(); 118 | 119 | ziFont = ZiFontV3.FromCharacterBitmaps(fontName + " " + cmbNextionFontSize.Text, (byte)width, (byte)height, codePage, pPreviews, PreviewWB.Checked); 120 | } 121 | 122 | private int GetMaxFontSizeForRect(string text, String fontName, int fontSize, SizeF rect) { 123 | 124 | var g = Graphics.FromImage(new Bitmap(10, 10)); 125 | 126 | for (int i = fontSize; i > 0; i--) { 127 | 128 | var font = new Font(fontName, i, GraphicsUnit.Pixel); 129 | 130 | var ss = g.MeasureString(text, font, 0, StringFormat.GenericTypographic); 131 | 132 | if (ss.Width < rect.Width && ss.Height < rect.Height) return i; 133 | } 134 | 135 | return fontSize; 136 | } 137 | 138 | private void lstFonts_SelectedIndexChanged(object sender, EventArgs e) { 139 | CreatePreview(); 140 | } 141 | 142 | private void numCharOffsetX_ValueChanged(object sender, EventArgs e) { 143 | CreatePreview(); 144 | } 145 | 146 | private void numCharOffsetY_ValueChanged(object sender, EventArgs e) { 147 | CreatePreview(); 148 | } 149 | 150 | private void cmbFontSize_SelectedIndexChanged(object sender, EventArgs e) { 151 | CreatePreview(); 152 | } 153 | 154 | private void cmbNextionFontSize_SelectedIndexChanged(object sender, EventArgs e) { 155 | CreatePreview(); 156 | } 157 | 158 | private void numFontSize_ValueChanged(object sender, EventArgs e) { 159 | CreatePreview(); 160 | } 161 | 162 | private void rbManualFontSize_CheckedChanged(object sender, EventArgs e) { 163 | CreatePreview(); 164 | } 165 | 166 | private void rbUseAllCharactersMaxSize_CheckedChanged(object sender, EventArgs e) { 167 | CreatePreview(); 168 | } 169 | 170 | private void rbUseSingleCharacterMaxSize_CheckedChanged(object sender, EventArgs e) { 171 | CreatePreview(); 172 | } 173 | 174 | private void numDbs_ValueChanged(object sender, EventArgs e) { 175 | CreatePreview(); 176 | } 177 | 178 | private void btnSave_Click(object sender, EventArgs e) { 179 | sfd.FileName = ziFont.Name; 180 | var res = sfd.ShowDialog(); 181 | if (res == DialogResult.OK) { 182 | ziFont.Save(sfd.FileName); 183 | } 184 | } 185 | 186 | private void PreviewTest_CheckedChanged(object sender, EventArgs e) { 187 | CreatePreview(); 188 | } 189 | } 190 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormAddCharacters.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Data; 4 | using System.Drawing; 5 | using System.Drawing.Text; 6 | using System.Linq; 7 | using System.Windows.Forms; 8 | using ZiLib.FileVersion.Common; 9 | using ZiLib.FileVersion.V3; 10 | 11 | namespace NextionFontEditor { 12 | 13 | public partial class FormAddCharacters : Form { 14 | 15 | public FormAddCharacters() { 16 | InitializeComponent(); 17 | } 18 | 19 | private ZiFontV3 ziFont = new ZiFontV3(); 20 | 21 | private void FormAddCharacters_Load(object sender, EventArgs e) { 22 | InitializeNextionFontSizesList(); 23 | 24 | //new FormFontPreview().Show(); 25 | } 26 | 27 | private void InitializeNextionFontSizesList() { 28 | for (int i = 8; i <= 255; i++) { 29 | cmbNextionFontSize.Items.Add(i); 30 | } 31 | 32 | cmbNextionFontSize.Text = "16"; 33 | numFontSize.Value = 16; 34 | } 35 | 36 | public Graphics CreateGraphics(Bitmap bitmap = null) { 37 | var b = bitmap ?? new Bitmap(1, 1); 38 | var g = Graphics.FromImage(b); 39 | 40 | g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.NearestNeighbor; 41 | g.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.None; 42 | g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.None; 43 | g.TextRenderingHint = TextRenderingHint.SingleBitPerPixelGridFit; 44 | 45 | return g; 46 | } 47 | 48 | private void CreatePreview() { 49 | var codePage = new CodePage(ZiLib.CodePageIdentifier.ISO_8859_1); 50 | 51 | var fontName = lstFonts.SelectedItem?.ToString() ?? ""; 52 | var fontSize = (int)numFontSize.Value; 53 | 54 | var size = int.Parse(cmbNextionFontSize.Text); 55 | var width = size / 2; 56 | var height = size; 57 | 58 | var font = new Font(fontName, fontSize, GraphicsUnit.Pixel); 59 | 60 | var pPreviews = new List(); 61 | 62 | var bLightCoral = new SolidBrush(Color.LightCoral); 63 | var bLightGreen = new SolidBrush(Color.LightGreen); 64 | var bWhite = new SolidBrush(Color.White); 65 | var bBlack = new SolidBrush(Color.Black); 66 | 67 | foreach (var cp in codePage.CodePoints) { 68 | var bPreview = new Bitmap(width, height); 69 | var txt = codePage.Encoding.GetString(BitConverter.GetBytes(cp)); 70 | 71 | using (var gPreview = CreateGraphics(bPreview)) { 72 | 73 | var sChar = gPreview.MeasureString(txt, font, new PointF(0, 0), StringFormat.GenericTypographic).ToSize(); 74 | if (sChar.Width == 0) sChar.Width = 1; 75 | 76 | var bChar = new Bitmap(sChar.Width, sChar.Height); 77 | 78 | using (var gChar = CreateGraphics(bChar)) { 79 | var sb = PreviewTest.Checked ? 80 | bChar.Width > bPreview.Width ? bLightCoral : bLightGreen : 81 | PreviewBW.Checked ? bWhite : bBlack; 82 | 83 | gChar.FillRectangle(sb, 0, 0, sChar.Width, sChar.Height); 84 | 85 | gChar.DrawString(txt, font, 86 | PreviewWB.Checked ? bWhite : bBlack, 87 | (float)numCharOffsetX.Value, (float)numCharOffsetY.Value, StringFormat.GenericTypographic 88 | ); 89 | } 90 | 91 | gPreview.FillRectangle(PreviewTest.Checked ? 92 | bChar.Width > bPreview.Width ? bLightCoral : bLightGreen : 93 | PreviewBW.Checked ? bWhite : bBlack, 94 | 0, 0, width, height); 95 | 96 | if (bChar.Width > bPreview.Width) { 97 | gPreview.DrawImage(bChar, 0, 0, width, height); 98 | 99 | } else { 100 | gPreview.DrawImage(bChar, (width / 2) - (bChar.Width / 2), 0, bChar.Width, height); 101 | } 102 | } 103 | 104 | pPreviews.Add(bPreview); 105 | } 106 | 107 | panelPreview.SuspendLayout(); 108 | panelPreview.Controls.Clear(); 109 | panelPreview.BackColor = PreviewTest.Checked ? Color.Transparent : PreviewBW.Checked ? Color.White : Color.Black; 110 | panelPreview.Controls.AddRange( 111 | pPreviews.Select(x => new PictureBox() { 112 | Width = width, 113 | Height = height, 114 | Image = x, 115 | Margin = new Padding(3) 116 | }).ToArray()); 117 | panelPreview.ResumeLayout(); 118 | 119 | ziFont = ZiFontV3.FromCharacterBitmaps(fontName + " " + cmbNextionFontSize.Text, (byte)width, (byte)height, codePage, pPreviews, PreviewWB.Checked); 120 | } 121 | 122 | private int GetMaxFontSizeForRect(string text, String fontName, int fontSize, SizeF rect) { 123 | 124 | var g = Graphics.FromImage(new Bitmap(10, 10)); 125 | 126 | for (int i = fontSize; i > 0; i--) { 127 | 128 | var font = new Font(fontName, i, GraphicsUnit.Pixel); 129 | 130 | var ss = g.MeasureString(text, font, 0, StringFormat.GenericTypographic); 131 | 132 | if (ss.Width < rect.Width && ss.Height < rect.Height) return i; 133 | } 134 | 135 | return fontSize; 136 | } 137 | 138 | private void lstFonts_SelectedIndexChanged(object sender, EventArgs e) { 139 | CreatePreview(); 140 | } 141 | 142 | private void numCharOffsetX_ValueChanged(object sender, EventArgs e) { 143 | CreatePreview(); 144 | } 145 | 146 | private void numCharOffsetY_ValueChanged(object sender, EventArgs e) { 147 | CreatePreview(); 148 | } 149 | 150 | private void cmbFontSize_SelectedIndexChanged(object sender, EventArgs e) { 151 | CreatePreview(); 152 | } 153 | 154 | private void cmbNextionFontSize_SelectedIndexChanged(object sender, EventArgs e) { 155 | CreatePreview(); 156 | } 157 | 158 | private void numFontSize_ValueChanged(object sender, EventArgs e) { 159 | CreatePreview(); 160 | } 161 | 162 | private void rbManualFontSize_CheckedChanged(object sender, EventArgs e) { 163 | CreatePreview(); 164 | } 165 | 166 | private void rbUseAllCharactersMaxSize_CheckedChanged(object sender, EventArgs e) { 167 | CreatePreview(); 168 | } 169 | 170 | private void rbUseSingleCharacterMaxSize_CheckedChanged(object sender, EventArgs e) { 171 | CreatePreview(); 172 | } 173 | 174 | private void numDbs_ValueChanged(object sender, EventArgs e) { 175 | CreatePreview(); 176 | } 177 | 178 | private void btnSave_Click(object sender, EventArgs e) { 179 | this.DialogResult = DialogResult.OK; 180 | this.Close(); 181 | } 182 | 183 | private void PreviewTest_CheckedChanged(object sender, EventArgs e) { 184 | CreatePreview(); 185 | } 186 | 187 | private void Label1_Click(object sender, EventArgs e) { 188 | 189 | } 190 | 191 | private void LblFont_Click(object sender, EventArgs e) { 192 | 193 | } 194 | 195 | private void FontDialog1_Apply(object sender, EventArgs e) { 196 | 197 | } 198 | } 199 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormCharacterWidth.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace NextionFontEditor { 2 | partial class FormCharacterWidth { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Windows Form Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormCharacterWidth)); 27 | this.lblWidth = new System.Windows.Forms.Label(); 28 | this.lblKerningL = new System.Windows.Forms.Label(); 29 | this.lblKerningR = new System.Windows.Forms.Label(); 30 | this.btnOK = new System.Windows.Forms.Button(); 31 | this.btnCancel = new System.Windows.Forms.Button(); 32 | this.numWidth = new System.Windows.Forms.NumericUpDown(); 33 | this.numKerningL = new System.Windows.Forms.NumericUpDown(); 34 | this.numKerningR = new System.Windows.Forms.NumericUpDown(); 35 | ((System.ComponentModel.ISupportInitialize)(this.numWidth)).BeginInit(); 36 | ((System.ComponentModel.ISupportInitialize)(this.numKerningL)).BeginInit(); 37 | ((System.ComponentModel.ISupportInitialize)(this.numKerningR)).BeginInit(); 38 | this.SuspendLayout(); 39 | // 40 | // lblWidth 41 | // 42 | this.lblWidth.AutoSize = true; 43 | this.lblWidth.Location = new System.Drawing.Point(47, 14); 44 | this.lblWidth.Name = "lblWidth"; 45 | this.lblWidth.Size = new System.Drawing.Size(87, 13); 46 | this.lblWidth.TabIndex = 0; 47 | this.lblWidth.Text = "Character Width:"; 48 | this.lblWidth.TextAlign = System.Drawing.ContentAlignment.MiddleRight; 49 | // 50 | // lblKerningL 51 | // 52 | this.lblKerningL.AutoSize = true; 53 | this.lblKerningL.Location = new System.Drawing.Point(67, 42); 54 | this.lblKerningL.Name = "lblKerningL"; 55 | this.lblKerningL.Size = new System.Drawing.Size(67, 13); 56 | this.lblKerningL.TabIndex = 2; 57 | this.lblKerningL.Text = "Kerning Left:"; 58 | this.lblKerningL.TextAlign = System.Drawing.ContentAlignment.TopRight; 59 | this.lblKerningL.Click += new System.EventHandler(this.lblKerningL_Click); 60 | // 61 | // lblKerningR 62 | // 63 | this.lblKerningR.AutoSize = true; 64 | this.lblKerningR.Location = new System.Drawing.Point(60, 70); 65 | this.lblKerningR.Name = "lblKerningR"; 66 | this.lblKerningR.Size = new System.Drawing.Size(74, 13); 67 | this.lblKerningR.TabIndex = 4; 68 | this.lblKerningR.Text = "Kerning Right:"; 69 | this.lblKerningR.TextAlign = System.Drawing.ContentAlignment.TopRight; 70 | // 71 | // btnOK 72 | // 73 | this.btnOK.DialogResult = System.Windows.Forms.DialogResult.OK; 74 | this.btnOK.Location = new System.Drawing.Point(235, 65); 75 | this.btnOK.Name = "btnOK"; 76 | this.btnOK.Size = new System.Drawing.Size(75, 23); 77 | this.btnOK.TabIndex = 6; 78 | this.btnOK.Text = "OK"; 79 | this.btnOK.UseVisualStyleBackColor = true; 80 | this.btnOK.Click += new System.EventHandler(this.btnOK_Click); 81 | // 82 | // btnCancel 83 | // 84 | this.btnCancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; 85 | this.btnCancel.Location = new System.Drawing.Point(235, 31); 86 | this.btnCancel.Name = "btnCancel"; 87 | this.btnCancel.Size = new System.Drawing.Size(75, 23); 88 | this.btnCancel.TabIndex = 7; 89 | this.btnCancel.Text = "Cancel"; 90 | this.btnCancel.TextAlign = System.Drawing.ContentAlignment.BottomCenter; 91 | this.btnCancel.UseVisualStyleBackColor = true; 92 | this.btnCancel.Click += new System.EventHandler(this.btnCancel_Click); 93 | // 94 | // numWidth 95 | // 96 | this.numWidth.Location = new System.Drawing.Point(140, 12); 97 | this.numWidth.Maximum = new decimal(new int[] { 98 | 255, 99 | 0, 100 | 0, 101 | 0}); 102 | this.numWidth.Minimum = new decimal(new int[] { 103 | 1, 104 | 0, 105 | 0, 106 | 0}); 107 | this.numWidth.Name = "numWidth"; 108 | this.numWidth.Size = new System.Drawing.Size(60, 20); 109 | this.numWidth.TabIndex = 8; 110 | this.numWidth.Value = new decimal(new int[] { 111 | 1, 112 | 0, 113 | 0, 114 | 0}); 115 | this.numWidth.ValueChanged += new System.EventHandler(this.numWidth_ValueChanged); 116 | // 117 | // numKerningL 118 | // 119 | this.numKerningL.Location = new System.Drawing.Point(140, 40); 120 | this.numKerningL.Maximum = new decimal(new int[] { 121 | 254, 122 | 0, 123 | 0, 124 | 0}); 125 | this.numKerningL.Name = "numKerningL"; 126 | this.numKerningL.Size = new System.Drawing.Size(60, 20); 127 | this.numKerningL.TabIndex = 9; 128 | this.numKerningL.Value = new decimal(new int[] { 129 | 1, 130 | 0, 131 | 0, 132 | 0}); 133 | this.numKerningL.ValueChanged += new System.EventHandler(this.numKerningL_ValueChanged); 134 | // 135 | // numKerningR 136 | // 137 | this.numKerningR.Location = new System.Drawing.Point(140, 68); 138 | this.numKerningR.Maximum = new decimal(new int[] { 139 | 254, 140 | 0, 141 | 0, 142 | 0}); 143 | this.numKerningR.Name = "numKerningR"; 144 | this.numKerningR.Size = new System.Drawing.Size(60, 20); 145 | this.numKerningR.TabIndex = 10; 146 | // 147 | // FormCharacterWidth 148 | // 149 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 150 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 151 | this.ClientSize = new System.Drawing.Size(332, 101); 152 | this.Controls.Add(this.numKerningR); 153 | this.Controls.Add(this.numKerningL); 154 | this.Controls.Add(this.numWidth); 155 | this.Controls.Add(this.btnCancel); 156 | this.Controls.Add(this.btnOK); 157 | this.Controls.Add(this.lblKerningR); 158 | this.Controls.Add(this.lblKerningL); 159 | this.Controls.Add(this.lblWidth); 160 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 161 | this.Name = "FormCharacterWidth"; 162 | this.Text = "Character Width"; 163 | ((System.ComponentModel.ISupportInitialize)(this.numWidth)).EndInit(); 164 | ((System.ComponentModel.ISupportInitialize)(this.numKerningL)).EndInit(); 165 | ((System.ComponentModel.ISupportInitialize)(this.numKerningR)).EndInit(); 166 | this.ResumeLayout(false); 167 | this.PerformLayout(); 168 | 169 | } 170 | 171 | #endregion 172 | 173 | private System.Windows.Forms.Label lblWidth; 174 | private System.Windows.Forms.Label lblKerningL; 175 | private System.Windows.Forms.Label lblKerningR; 176 | private System.Windows.Forms.Button btnOK; 177 | private System.Windows.Forms.Button btnCancel; 178 | public System.Windows.Forms.NumericUpDown numWidth; 179 | public System.Windows.Forms.NumericUpDown numKerningL; 180 | public System.Windows.Forms.NumericUpDown numKerningR; 181 | } 182 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/V3/ZiFontV3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Drawing; 4 | using System.IO; 5 | using System.Linq; 6 | using System.Text; 7 | using ZiLib.FileVersion.Common; 8 | 9 | namespace ZiLib.FileVersion.V3 { 10 | 11 | public class ZiFontV3 : IZiFont { 12 | private static readonly byte[] MagicNumbers = new byte[] { 0x04, 0xFF, 0x00, 0x0A }; 13 | private static readonly byte[] MagicNumbersBig5 = new byte[] { 0x04, 0x7E, 0x22, 0x0A }; // The two middle bytes might not be static 14 | 15 | private const int HEADER_LENGTH = 0x1C; // 28 16 | 17 | private byte[] _header { get; set; } 18 | private byte[] _charData { get; set; } 19 | 20 | public byte CharacterWidth { get; set; } 21 | public byte CharacterHeight { get; set; } 22 | public int CharacterCount => Characters.Count; 23 | 24 | public CodePage CodePage { get; set; } 25 | 26 | public byte Version { get; set; } = 3; 27 | public byte NameLength { get; set; } 28 | public string Name { get; set; } 29 | public long FileSize { get; set; } 30 | 31 | public uint VariableDataLength { get; set; } 32 | public uint CharDataLength { get; set; } 33 | public int BytesPerChar { get; set; } 34 | 35 | public List Characters { get; set; } = new List(); 36 | 37 | //public List CharBitmaps { get; set; } = new List(); 38 | 39 | //public ZiFont(byte width, byte height, CodePage codePage) { 40 | // CharacterWidth = width; 41 | // CharacterHeight = height; 42 | // CodePage = codePage; 43 | //} 44 | public void Save(string fileName, CodePage codePage) { 45 | CodePage = codePage; 46 | //_charData = CreateCharData(CharBitmaps); 47 | Save(fileName); 48 | } 49 | 50 | public void Save(string fileName) { 51 | // _charData = CreateCharData(CharBitmaps); 52 | 53 | var file = new List(); 54 | 55 | file.AddRange(MagicNumbers); 56 | file.AddRange(BitConverter.GetBytes((ushort)CodePage.CodePageIdentifier)); 57 | file.Add(CharacterWidth); 58 | file.Add(CharacterHeight); 59 | file.Add((byte)(CodePage.IsMultibyte ? CodePage.FirstByteStart : 0)); 60 | file.Add((byte)(CodePage.IsMultibyte ? CodePage.FirstByteEnd : 0)); 61 | file.Add((byte)(CodePage.IsMultibyte ? CodePage.SecondByteStart : CodePage.FirstByteStart)); 62 | file.Add((byte)(CodePage.IsMultibyte ? CodePage.SecondByteEnd : CodePage.FirstByteEnd)); 63 | file.AddRange(BitConverter.GetBytes(CodePage.CharacterCount)); 64 | file.Add(Version); 65 | file.Add(NameLength); 66 | file.Add(NameLength); 67 | file.Add(0x00); // Reserved 68 | file.AddRange(BitConverter.GetBytes(VariableDataLength)); 69 | file.Add(0x00); // Reserved 70 | file.Add(0x00); // Reserved 71 | file.Add(0x00); // Reserved 72 | file.Add(0x00); // Reserved 73 | file.AddRange(Encoding.ASCII.GetBytes(Name)); 74 | file.AddRange(_charData); 75 | 76 | File.WriteAllBytes(fileName, file.ToArray()); 77 | } 78 | 79 | public static IZiFont FromFile(string fileName) { 80 | return FromBytes(File.ReadAllBytes(fileName)); 81 | } 82 | 83 | public static IZiFont FromBytes(byte[] bytes) { 84 | if (!VerifyHeader(bytes)) return null; 85 | 86 | var ziFont = new ZiFontV3(); 87 | //var ziFont = new ZiFontV5(); 88 | 89 | byte[] _header = bytes.Take(HEADER_LENGTH).ToArray(); 90 | int NameLength = _header[0x11]; 91 | ziFont.Name = Encoding.ASCII.GetString(bytes.Skip(HEADER_LENGTH).Take(NameLength).ToArray()); 92 | ziFont.FileSize = bytes.Length; 93 | 94 | ziFont.CharacterWidth = _header[0x6]; 95 | ziFont.CharacterHeight = _header[0x7]; 96 | 97 | ziFont.VariableDataLength = BitConverter.ToUInt32(_header.Skip(0x14).Take(4).ToArray(), 0); 98 | ziFont.CharDataLength = ziFont.VariableDataLength - (uint)NameLength; 99 | 100 | byte[] _charData = bytes.Skip(HEADER_LENGTH + NameLength).ToArray(); 101 | //ziFont.BytesPerChar = (ziFont.CharacterWidth * ziFont.CharacterHeight) / 8; 102 | int BytesPerChar = (ziFont.CharacterWidth * ziFont.CharacterHeight) / 8; 103 | 104 | var codePageId = BitConverter.ToUInt16(_header.Skip(0x4).Take(2).ToArray(), 0); 105 | var characterCount = BitConverter.ToUInt32(_header.Skip(0x0C).Take(4).ToArray(), 0); 106 | var calculatedCharCount = ziFont.CharDataLength / BytesPerChar; 107 | 108 | ziFont.CodePage = new CodePage((CodePageIdentifier)codePageId); 109 | 110 | if (characterCount != calculatedCharCount) throw new Exception($"{nameof(characterCount)} and {nameof(calculatedCharCount)} doesn't match."); 111 | 112 | var bb = new SolidBrush(Color.Black); 113 | var pr = new Pen(Color.DarkCyan); 114 | for (int charIndex = 0; charIndex < ziFont.CodePage.CharacterCount; charIndex++) { 115 | var charBitmap = new Bitmap(ziFont.CharacterWidth, ziFont.CharacterHeight); 116 | var g = Graphics.FromImage(charBitmap); 117 | 118 | var charData = _charData.Skip(charIndex * BytesPerChar).Take(BytesPerChar).ToArray(); 119 | var pixels = BinaryTools.BytesToBits(charData); 120 | 121 | var pixel = 0; 122 | 123 | for (int y = 0; y < ziFont.CharacterHeight; y++) { 124 | for (int x = 0; x < ziFont.CharacterWidth; x++) { 125 | if (pixels[pixel]) g.FillRectangle(bb, x, y, 1, 1); 126 | 127 | pixel++; 128 | } 129 | } 130 | 131 | /* var ch = new ZiCharacterV3 132 | ( 133 | ziFont, 134 | ziFont.CodePage.CodePoints[charIndex], 135 | charBitmap 136 | );*/ 137 | var ch = new ZiCharacterV3 138 | ( 139 | ziFont, 140 | ziFont.CodePage.CodePoints[charIndex], 141 | charData 142 | ); 143 | ziFont.Characters.Add(ch); 144 | } 145 | 146 | return ziFont; 147 | } 148 | 149 | 150 | private byte[] CreateCharData(List characters, bool invertColour = false) { 151 | var charData = new List(); 152 | 153 | foreach (var cb in characters) { 154 | charData.AddRange(BinaryTools.BitmapTo1BppData(cb, invertColour)); 155 | } 156 | 157 | return charData.ToArray(); 158 | } 159 | 160 | public static ZiFontV3 FromCharacterBitmaps(string fontName, byte width, byte height, CodePage codePage, List characters, bool invertColour = false) { 161 | var bytesPerChar = width * height / 8; 162 | var charDataLength = (uint)(bytesPerChar * characters.Count()); 163 | 164 | var ziFont = new ZiFontV3 { 165 | Name = fontName, 166 | NameLength = (byte)fontName.Length, 167 | CharacterWidth = width, 168 | CharacterHeight = height, 169 | CodePage = codePage, 170 | CharDataLength = charDataLength, 171 | VariableDataLength = (uint)fontName.Length + charDataLength, 172 | BytesPerChar = bytesPerChar, 173 | }; 174 | 175 | ziFont._charData = ziFont.CreateCharData(characters, invertColour); 176 | 177 | //var charData = new List(); 178 | //foreach (var cb in characters) { 179 | // charData.AddRange(BinaryTools.BitmapTo1BppData(cb)); 180 | //} 181 | //ziFont._charData = charData.ToArray(); 182 | 183 | return ziFont; 184 | } 185 | 186 | public static bool VerifyHeader(byte[] header) { 187 | if (header.Length < 4) return false; 188 | if (header.Length > 5) header = header.Take(4).ToArray(); 189 | 190 | if (header.SequenceEqual(MagicNumbers)) return true; 191 | if (header.SequenceEqual(MagicNumbersBig5)) return true; 192 | 193 | return false; 194 | } 195 | public void AddCharacter(uint codepoint, IZiCharacter character) { 196 | Characters.Add(character); 197 | } 198 | 199 | public void RemoveCharacter(int index) { 200 | Characters.RemoveAt(index); 201 | } 202 | } 203 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/V5/BinaryTools.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | 4 | namespace ZiLib.FileVersion.V5 5 | { 6 | 7 | public class BinaryTools 8 | { 9 | public static byte Get3bppColor(Color pixel, bool invertColour) { 10 | var curColor = (byte)0u; 11 | if (invertColour) 12 | { 13 | // curColor = (byte)((pixel.R + 2 * pixel.G + pixel.B) / 4); // Weighted Color2Grayscale; 14 | curColor = (byte)(255 - pixel.A); 15 | } else 16 | { 17 | // curColor = (byte)(255 - (pixel.R + 2 * pixel.G + pixel.B) / 4); // Weighted Color2Grayscale; 18 | curColor = (byte)pixel.A; 19 | } 20 | // curColor = (byte)(curColor * pixel.A / 255); 21 | // convert to 3 bits 22 | return (byte)(curColor >> 5); 23 | } 24 | 25 | /* A faster 3-bit encoder and compresser combined into one loop instead of consecutive nested loops */ 26 | public static byte[] BitmapTo3BppData(Bitmap b, bool invertColour = false) 27 | { 28 | var data = new List(); 29 | 30 | byte curColor; 31 | var prevColor = (byte)0u; 32 | var prevCount = 0u; 33 | 34 | var antialias = false; 35 | 36 | 37 | if (b == null) 38 | { 39 | //return data.ToArray(); 40 | } 41 | 42 | if (b.PixelFormat == System.Drawing.Imaging.PixelFormat.Undefined) { 43 | return data.ToArray(); 44 | } 45 | data.Add(0x03); 46 | 47 | for (int y = 0; y < b.Height; y++) 48 | { 49 | for (int x = 0; x < b.Width; x++) 50 | { 51 | curColor = Get3bppColor(b.GetPixel(x, y), invertColour); 52 | 53 | if (curColor == prevColor) 54 | { 55 | prevCount++; 56 | continue; // to next pixel 57 | } 58 | 59 | if (prevCount == 0) // No previous data to encode 60 | { 61 | prevColor = curColor; 62 | prevCount = 1; 63 | continue; // to next pixel 64 | } 65 | 66 | if (prevColor == 0) 67 | { 68 | while (prevCount >= 31) 69 | { 70 | data.Add(CompressedByte.RepeatedWhites(31)); 71 | prevCount -= 31; 72 | } 73 | 74 | if (prevCount == 0) 75 | { 76 | // start with fresh color count 77 | prevColor = curColor; 78 | prevCount = 1; 79 | continue; // to next pixel 80 | } 81 | 82 | /* also check for second black pixel */ 83 | if (curColor == 7) 84 | { 85 | var blacks = 1u; 86 | var j = (x + 1) >= b.Width ? y + 1 : y; 87 | var i = (x + 1) >= b.Width ? 0 : x + 1; 88 | while (blacks<2 && j= b.Width ? y + 1 : y; 99 | i = (x + 1) >= b.Width ? 0 : x + 1; 100 | } 101 | data.Add(CompressedByte.RepeatedWhites(prevCount, blacks)); 102 | // start with fresh color count 103 | prevColor = curColor; 104 | prevCount = 0; 105 | continue; // to next pixel 106 | } 107 | 108 | if (prevCount >= 8) 109 | { 110 | data.Add(CompressedByte.RepeatedWhites(prevCount)); 111 | // start with fresh color count 112 | prevColor = curColor; 113 | prevCount = 1; 114 | } 115 | else 116 | { 117 | data.Add(CompressedByte.RepeatedWhites(prevCount, curColor)); 118 | prevColor = curColor; 119 | prevCount = 0; 120 | } 121 | 122 | continue; // to next pixel 123 | } 124 | 125 | if (prevColor == 7) 126 | { 127 | while (prevCount >= 31) 128 | { 129 | data.Add(CompressedByte.RepeatedBlacks(31)); 130 | prevCount -= 31; 131 | } 132 | 133 | switch (prevCount) 134 | { 135 | case 0: // start with fresh color count 136 | prevColor = curColor; 137 | prevCount = 1; 138 | break; 139 | case 1: 140 | data.Add(CompressedByte.AlphaColors(prevColor, curColor)); // one black + one color 141 | prevCount = 0; 142 | prevColor = curColor; 143 | break; 144 | default: 145 | data.Add(CompressedByte.RepeatedBlacks(prevCount)); // remaining blacks 146 | prevColor = curColor; 147 | prevCount = 1; 148 | break; 149 | } 150 | 151 | continue; // to next pixel 152 | } 153 | 154 | // a grayscale 155 | antialias = true; 156 | 157 | while (prevCount >= 2) 158 | { 159 | data.Add(CompressedByte.AlphaColors(prevColor, prevColor)); 160 | prevCount -= 2; 161 | } 162 | 163 | if (prevCount == 0) 164 | { 165 | prevColor = curColor; 166 | prevCount = 1; 167 | } 168 | else 169 | { 170 | data.Add(CompressedByte.AlphaColors(prevColor, curColor)); // one black + one color 171 | prevColor = curColor; 172 | prevCount = 0; 173 | } 174 | continue; // to next pixel 175 | 176 | } 177 | } 178 | 179 | /* Handle remainder stored in PrevColor and PreCount */ 180 | 181 | if (prevCount > 0) // more previous data to encode 182 | { 183 | // remaining whites 184 | if (prevColor == 0) 185 | { 186 | while (prevCount >= 31) 187 | { 188 | data.Add(CompressedByte.RepeatedWhites(31)); 189 | prevCount -= 31; 190 | } 191 | 192 | if (prevCount > 0) 193 | { 194 | data.Add(CompressedByte.RepeatedWhites(prevCount)); 195 | } 196 | 197 | return data.ToArray(); 198 | } 199 | 200 | // remaining blacks 201 | if (prevColor == 7) 202 | { 203 | while (prevCount >= 31) 204 | { 205 | data.Add(CompressedByte.RepeatedBlacks(31)); 206 | prevCount -= 31; 207 | } 208 | 209 | if (prevCount > 0) 210 | { 211 | data.Add(CompressedByte.RepeatedBlacks(prevCount)); 212 | } 213 | 214 | return data.ToArray(); 215 | } 216 | 217 | // remaining grayscales 218 | while (prevCount >= 2) 219 | { 220 | data.Add(CompressedByte.AlphaColors(prevColor, prevColor)); 221 | prevCount -= 2; 222 | } 223 | 224 | if (prevCount > 0) 225 | { 226 | data.Add(CompressedByte.RepeatedWhites((byte)0, prevColor)); // zero whites + one color 227 | } 228 | } 229 | 230 | return data.ToArray(); 231 | } 232 | } 233 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormFontPreview.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 17 122 | 123 | 124 | 125 | 126 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 127 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADzSURBVDhPY6AYTKty+Y+OZ9S41kKlCQOQhtsbUuH4yqqk 128 | /3Pq3b7NrHWrgyrBD9ANQDYE2VXYME4DiMG0N+DMkrj/q7v9UZyMiZ2+gA3Ahhc2e/8/vzbr/+czLf+/ 129 | nmvFwE8PVP2fXeP6GGzAsnY/rIrw4Vvbiv7Prnc/ATZg46QwrIrw4fNrsv/PqXNfCjZg39wErIrw4SOL 130 | k/9Pr3ZuYJhZ4/b/1MoMrIrw4W3To/5PrXRKZpjT4PH/2uYCrIrw4ZXdQf+nVri6Mcyp9/j/aF8FVkX4 131 | 8IIm7//TK520GGZUu2KNRmLwxHoPPnBiIh8wMAAAq106cVRsxHIAAAAASUVORK5CYII= 132 | 133 | 134 | 135 | 122, 17 136 | 137 | 138 | 139 | AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAANcNAADXDQAAAAAAAAAA 140 | AACejnzAno1765qKejAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 141 | AAAAAAAAno1766+fjP2ejnvvm4l2KQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 142 | AAAAAAAAAAAAAJ2LeTmejXryqZqG/Z+NeeebiXYcAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 143 | AAAAAAAAAAAAAAAAAAAAAAAAnY13L5+Ne++klIH9oI564ZeLdBYAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 144 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACajXkmno566qGRfv2fjXvZoouAFp6NeWmikX3YnYx5+52M 145 | efuikX3XnYx4aJmZZgUAAAAAAAAAAAAAAAAAAAAAAAAAAJ2JdhqfjnrhnIt4/6KQffm5p5Hz59W8//zq 146 | zv/86s7/59W7/7emkfKhkX3ZnYl2GgAAAAAAAAAAAAAAAAAAAAAAAAAAn494IKGQfPvNuqT//+3R///t 147 | 0f//7dH//+3R///t0f//7dH/zLqk/KGRfNqqgIAGAAAAAAAAAAAAAAAAAAAAAJ6NeW62pY/2/+3R///t 148 | 0f//7dH//+3R///t0f//7dH//+3R///t0f+2pY/0no54bAAAAAAAAAAAAAAAAAAAAACjkn7Z59W7///t 149 | 0f//7dH//+3R///t0f//7dH//+3R///t0f//7dH/5tW7/6ORftYAAAAAAAAAAAAAAAAAAAAAno16+fvp 150 | zf//7dH//+3R///t0f//7dH//+3R///t0f//7dH//+3R//rozP+ejXr4AAAAAAAAAAAAAAAAAAAAAJ6N 151 | evn76c3//+3R///t0f//7dH//+3R///t0f//7dH//+3R///t0f/66Mz/no16+AAAAAAAAAAAAAAAAAAA 152 | AACikn/Z59W7///t0f//7dH//+3R///t0f//7dH//+3R///t0f//7dH/5tW7/6KRftYAAAAAAAAAAAAA 153 | AAAAAAAAno95dLelkPX/7dH//+3R///t0f//7dH//+3R///t0f//7dH//+3R/7alj/Sfj3lyAAAAAAAA 154 | AAAAAAAAAAAAAJ+AgAiikHvd0b+o/P/t0f//7dH//+3R///t0f//7dH//+3R/9C+qPyhkXzakpJtBwAA 155 | AAAAAAAAAAAAAAAAAAAAAAAAoY57G6GQfdq5qJL059W8//jmy//45sv/59W7/7mnkfShkX3ZnYl2GgAA 156 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACqgIAGoZB9bKKSftmfj3v1n4979aORfdigj3xrmZlmBQAA 157 | AAAAAAAAH/8AAA//AAAH/wAAg/8AAMADAADgAQAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAA 158 | AAD4AQAA/AMAAA== 159 | 160 | 161 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormAddCharacters.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 48 122 | 123 | 124 | 130, 48 125 | 126 | 127 | 128 | 129 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 130 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY6AK6C5d+B8ZF9dN/59W2Y+BS2pn/O+vXFID 131 | 1YYAIE13rn4C42O7noEVP3z9CQODxKfWr/7WX724DqoVAggZUNE9B27A1bOv/0+rX/ulr3JpG1Q7aQaA 132 | 1Fw58wrsVah2VANOH3j5v657CVgxOm6euByuDqcBxGLaGUAI0MeAQy+wYxAgygB8gCgDsNkOwiBAlAH4 133 | AE4DyMFQ7ZQABgYA8IyChn1Fh6IAAAAASUVORK5CYII= 134 | 135 | 136 | 137 | 76 138 | 139 | 140 | 141 | AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAANcNAADXDQAAAAAAAAAA 142 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 143 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 144 | AAAAAAAAAAAAAI95ZtSPeWb/j3pmwQAAAAAAAAAAAAAAAAAAAAAAAAAAj3pmwY95Zv+OeWbVAAAAAAAA 145 | AAAAAAAAAAAAAAAAAACQeWV+j3lm/495ZvqSgG0OAAAAAAAAAAAAAAAAiHdmD495ZvqPeWb/j3pmgAAA 146 | AAAAAAAAAAAAAAAAAAAAAAAAj3ZkKY95Zv+PeWb/j3lm/495Zv+PeWb/j3lm/495Zv+PeWb/j3lm/5F6 147 | aCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPeWbhj3lm/494Zv+PeWb/j3lm/495Zv+PeWb/j3lm/494 148 | ZdsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj3hme495Zv+PeWbl/wAAAQAAAAD/AAABj3lm5Y95 149 | Zv+PemaCAAAAAAAAAAAAAAAAj3lm/wAAAAAAAAAAAAAAAJF8ZyWPeWb/j3lm/414aDEAAAAAj3pmMo95 150 | Zv+PeWb/kHpkLgAAAAAAAAAAAAAAAI95Zv8AAAAAAAAAAAAAAAAAAAAAj3lmzY95Zv+PeGZ7AAAAAJB5 151 | Z3yPeWb/j3lm2QAAAAAAAAAAj3lm/495Zv+PeWb/j3lm/495Zv8AAAAAAAAAAJB4Z3ePeWb/j3llxAAA 152 | AACOeGbFj3lm/496ZoQAAAAAAAAAAAAAAAAAAAAAj3lm/wAAAAAAAAAAAAAAAAAAAACSfGYjj3lm/495 153 | ZvuPeGkij3lm+495Zv+PemUwAAAAAAAAAAAAAAAAAAAAAI95Zv8AAAAAAAAAAAAAAAAAAAAAAAAAAI95 154 | ZsaPeWb/j3hmto95Zv+PeGbYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 155 | AACOemZzj3lm/495Zv+PeWb/kHlmhwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 156 | AAAAAAAAknZkHI95Zv2PeWb/j3lm/496ZTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 157 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 158 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 159 | AAAAAAAA//8AAP//AAAfHwAADh8AAAAfAACAPwAAhDsAAIQ7AADEYAAAxHsAAMB7AADg/wAA4P8AAOD/ 160 | AAD//wAA//8AAA== 161 | 162 | 163 | -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormFontGenerator.resx: -------------------------------------------------------------------------------- 1 | 2 | 3 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | text/microsoft-resx 110 | 111 | 112 | 2.0 113 | 114 | 115 | System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 116 | 117 | 118 | System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 119 | 120 | 121 | 17, 48 122 | 123 | 124 | 130, 48 125 | 126 | 127 | 128 | 129 | iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8 130 | YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAAClSURBVDhPY6AK6C5d+B8ZF9dN/59W2Y+BS2pn/O+vXFID 131 | 1YYAIE13rn4C42O7noEVP3z9CQODxKfWr/7WX724DqoVAggZUNE9B27A1bOv/0+rX/ulr3JpG1Q7aQaA 132 | 1Fw58wrsVah2VANOH3j5v657CVgxOm6euByuDqcBxGLaGUAI0MeAQy+wYxAgygB8gCgDsNkOwiBAlAH4 133 | AE4DyMFQ7ZQABgYA8IyChn1Fh6IAAAAASUVORK5CYII= 134 | 135 | 136 | 137 | 76 138 | 139 | 140 | 141 | AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAANcNAADXDQAAAAAAAAAA 142 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 143 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 144 | AAAAAAAAAAAAAI95ZtSPeWb/j3pmwQAAAAAAAAAAAAAAAAAAAAAAAAAAj3pmwY95Zv+OeWbVAAAAAAAA 145 | AAAAAAAAAAAAAAAAAACQeWV+j3lm/495ZvqSgG0OAAAAAAAAAAAAAAAAiHdmD495ZvqPeWb/j3pmgAAA 146 | AAAAAAAAAAAAAAAAAAAAAAAAj3ZkKY95Zv+PeWb/j3lm/495Zv+PeWb/j3lm/495Zv+PeWb/j3lm/5F6 147 | aCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACPeWbhj3lm/494Zv+PeWb/j3lm/495Zv+PeWb/j3lm/494 148 | ZdsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAj3hme495Zv+PeWbl/wAAAQAAAAD/AAABj3lm5Y95 149 | Zv+PemaCAAAAAAAAAAAAAAAAj3lm/wAAAAAAAAAAAAAAAJF8ZyWPeWb/j3lm/414aDEAAAAAj3pmMo95 150 | Zv+PeWb/kHpkLgAAAAAAAAAAAAAAAI95Zv8AAAAAAAAAAAAAAAAAAAAAj3lmzY95Zv+PeGZ7AAAAAJB5 151 | Z3yPeWb/j3lm2QAAAAAAAAAAj3lm/495Zv+PeWb/j3lm/495Zv8AAAAAAAAAAJB4Z3ePeWb/j3llxAAA 152 | AACOeGbFj3lm/496ZoQAAAAAAAAAAAAAAAAAAAAAj3lm/wAAAAAAAAAAAAAAAAAAAACSfGYjj3lm/495 153 | ZvuPeGkij3lm+495Zv+PemUwAAAAAAAAAAAAAAAAAAAAAI95Zv8AAAAAAAAAAAAAAAAAAAAAAAAAAI95 154 | ZsaPeWb/j3hmto95Zv+PeGbYAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 155 | AACOemZzj3lm/495Zv+PeWb/kHlmhwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 156 | AAAAAAAAknZkHI95Zv2PeWb/j3lm/496ZTAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 157 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 158 | AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA 159 | AAAAAAAA//8AAP//AAAfHwAADh8AAAAfAACAPwAAhDsAAIQ7AADEYAAAxHsAAMB7AADg/wAA4P8AAOD/ 160 | AAD//wAA//8AAA== 161 | 162 | 163 | -------------------------------------------------------------------------------- /Docs/Nextion Font Format Specification ZI version 3.md: -------------------------------------------------------------------------------- 1 | # Nextion Font Format Specification 2 | This is a reverse engineered specification of the Nextion font format. Use at own risk. 3 | 4 | ## General information 5 | 6 | The Nextion Font Format is a proprietary font format used by the Nextion Editor HMI software. Nextion Editor has a built in "Font Generator"-tool which converts standard fonts into .zi files that is compatible with the Nextion HMI displays. 7 | 8 | | Information | | 9 | |-------------------------|-----------------------| 10 | | **Software** | Nextion Editor V0.53 | 11 | | **File extension** | .zi | 12 | | **File format version** | ZI version 3 | 13 | | **Example file** | Arial_40_ascii.zi | 14 | 15 | ## Code pages / character encoding reference 16 | 17 | | Code page / encoding | Value | Number of characters | 18 | |-----------------------|-----------------------|-----------------------| 19 | | ASCII | 0x01 | 95 | 20 | | GB2312 | 0x02 | 8273 | 21 | | ISO-8859-1 | 0x03 | 224 | 22 | | ISO-8859-2 | 0x04 | 224 | 23 | | ISO-8859-3 | 0x05 | 224 | 24 | | ISO-8859-4 | 0x06 | 224 | 25 | | ISO-8859-5 | 0x07 | 224 | 26 | | ISO-8859-6 | 0x08 | 224 | 27 | | ISO-8859-7 | 0x09 | 224 | 28 | | BIG5 | 0x1001 | 14225 | 29 | | ISO-8859-8 | 0x0A | 224 | 30 | | ISO-8859-9 | 0x0B | 224 | 31 | | ISO-8859-13 | 0x0C | 224 | 32 | | ISO-8859-15 | 0x0D | 224 | 33 | | ISO-8859-11 | 0x0E | 224 | 34 | | KS_C_5601-1987 | 0x0F | 3855 | 35 | | WINDOWS-1255 | 0x11 | 224 | 36 | | WINDOWS-1256 | 0x12 | 224 | 37 | | WINDOWS-1257 | 0x13 | 224 | 38 | | WINDOWS-1258 | 0x14 | 224 | 39 | | WINDOWS-874 | 0x15 | 224 | 40 | | KOI8-R | 0x16 | 224 | 41 | 42 | 43 | ## File format structure 44 | 45 | ### Fixed header 46 | 47 | **Length:** 0x1C (28) 48 | 49 | ``` 50 | 0x00000000: 04 FF 00 0A 01 00 14 28 00 00 20 7E 5F 00 00 00 51 | 0x00000010: 03 0E 0E 00 2A 25 00 00 00 00 00 00 52 | ``` 53 | 54 | | Offset | Length | Data | Type | Value | Description | 55 | |------------|-------:|--------------------------------------------------|--------|--------------------:|---------------------------------------------------------------------------------------| 56 | | 0x00000000 | 4 | `04 FF 00 0A` * | byte[] | | File signature / magic numbers | 57 | | 0x00000004 | 2 | `01 00` | uint16 | 1 | Code page / character encoding (possible values listed in the reference table) | 58 | | 0x00000006 | 1 | `14` | byte | 20 | Character width | 59 | | 0x00000007 | 1 | `28` | byte | 40 | Character height | 60 | | 0x00000008 | 1 | `00` | byte | 0 | Code page multibyte - first byte start | 61 | | 0x00000009 | 1 | `00` | byte | 0 | Code page multibyte - first byte end | 62 | | 0x0000000A | 1 | `20` | byte | 32, ' ' (ASCII) | Code page start / multibyte second byte start | 63 | | 0x0000000B | 1 | `7E` | byte | 126, '~' (ASCII) | Code page end / multibyte second byte end | 64 | | 0x0000000C | 4 | `5F 00 00 00` | uint32 | 95 | Number of characters in file | 65 | | 0x00000010 | 1 | `03` | byte | 3 | File Format Version | 66 | | 0x00000011 | 1 | `0E` | byte | 14 | Length of font name | 67 | | 0x00000012 | 1 | `0E` | byte | 14 | Also length of font name? Always the same value as 0x11 | 68 | | 0x00000013 | 1 | `00` | byte | 0 | Reserved | 69 | | 0x00000014 | 4 | `2A 25 00 00` | uint32 | 9514 | Total length of font name and character data | 70 | | 0x00000018 | 4 | `00 00 00 00` | uint32 | 0 | Reserved | 71 | 72 | > **\* The file signature/magic bytes for a .zi file containing the `BIG5` code page is different from all other files. For `BIG5` the magic bytes are `04 7E 22 0A`. Which means that the second and third byte might be variable and have some meaning beyond being magic numbers.** 73 | 74 | ### Font name 75 | Variable length font name. In this case the font name is `0x0E (14)` bytes long as seen in offset `0x00000011`. 76 | 77 | ``` 78 | 0x00000010: 03 0E 0E 00 2A 25 00 00 00 00 00 00 41 72 69 61 79 | 0x00000020: 6C 5F 34 30 5F 61 73 63 69 69 00 00 00 00 00 00 80 | ``` 81 | 82 | | Offset | Length | Data | Type | Value | Description | 83 | |------------|-------:|--------------------------------------------------|--------|--------------------:|------------------------------------------------------------------| 84 | | 0x0000001C | 14 | `41 72 69 61 6C 5F 34 30 5F 61 73 63 69 69` | string | Arial_40_ascii | Font name | 85 | 86 | ### Character data 87 | 88 | The rest of the file contains the actual character data. The length of each character is calculated like this: `character width * character height / 8`. In our example we get; `20 * 40 / 8` which gives us `100` bytes per character. Characters are monochrome, which means that each bit in the `100` bytes gives us one pixel. `20 * 40 = 800 pixels`. 89 | 90 | Example data for one character. This is the exclamation mark character (`!`), which is the second character in the file. I skipped the first one, beacuse that is the space character which is blank. 91 | 92 | ``` 93 | 0x00000080: 00 00 94 | 0x00000090: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 95 | 0x000000a0: 00 00 00 00 01 E0 00 1E 00 01 E0 00 1E 00 01 E0 96 | 0x000000b0: 00 1E 00 00 E0 00 0E 00 00 E0 00 0E 00 00 E0 00 97 | 0x000000c0: 0E 00 00 E0 00 0E 00 00 E0 00 0E 00 00 00 00 00 98 | 0x000000d0: 00 01 E0 00 1E 00 01 E0 00 00 00 00 00 00 00 00 99 | 0x000000e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 100 | 0x000000f0: 00 00 101 | ``` 102 | 103 | The rest of the file contains the remaining characters supported by the font. 104 | 105 | ### Character data example for a 16 pixels tall exclamation mark (`!`) character 106 | 107 | This example shows how to read the pixel data for a character. The height of character is `16` pixels, which means it is `8` pixels wide. This gives us a total of `128` pixels. This also means that each of the `16` bytes contains the data for one line of pixels. 108 | 109 | ``` 110 | 0x00000030: 00 00 00 00 60 60 111 | 0x00000040: 60 60 60 60 00 60 00 00 00 00 112 | ``` 113 | 114 | Let's look at the bits of each byte: 115 | 116 | ``` 117 | 00: 0 0 0 0 0 0 0 0 118 | 00: 0 0 0 0 0 0 0 0 119 | 00: 0 0 0 0 0 0 0 0 120 | 00: 0 0 0 0 0 0 0 0 121 | 60: 0 1 1 0 0 0 0 0 122 | 60: 0 1 1 0 0 0 0 0 123 | 60: 0 1 1 0 0 0 0 0 124 | 60: 0 1 1 0 0 0 0 0 125 | 60: 0 1 1 0 0 0 0 0 126 | 60: 0 1 1 0 0 0 0 0 127 | 00: 0 0 0 0 0 0 0 0 128 | 60: 0 1 1 0 0 0 0 0 129 | 00: 0 0 0 0 0 0 0 0 130 | 00: 0 0 0 0 0 0 0 0 131 | 00: 0 0 0 0 0 0 0 0 132 | 00: 0 0 0 0 0 0 0 0 133 | ``` 134 | 135 | Now let's remove the zeroes (blank pixel) and replace the ones with an X: 136 | 137 | ``` 138 | 00: 139 | 00: 140 | 00: 141 | 00: 142 | 60: X X 143 | 60: X X 144 | 60: X X 145 | 60: X X 146 | 60: X X 147 | 60: X X 148 | 00: 149 | 60: X X 150 | 00: 151 | 00: 152 | 00: 153 | 00: 154 | ``` 155 | 156 | ❗️ There's our exclamation mark ❗️ 157 | -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/BinaryTools.cs: -------------------------------------------------------------------------------- 1 | using System.Drawing; 2 | using System.Collections.Generic; 3 | using ZiLib.FileVersion.V5; 4 | 5 | namespace ZiLib { 6 | 7 | public class BinaryTools { 8 | 9 | public static bool[] BytesToBits(byte[] bytes) { 10 | bool[] bits = new bool[bytes.Length * 8]; 11 | 12 | for (int i = 0; i < bytes.Length; i++) { 13 | for (int j = 0; j < 8; j++) { 14 | var index = i * 8 + j; 15 | bits[index] = (bytes[i] & (1 << (7 - j))) != 0; 16 | } 17 | } 18 | 19 | return bits; 20 | } 21 | 22 | public static byte[] BitmapTo1BppData(Bitmap b, bool invertColour=false) { 23 | var pixels = new bool[b.Width * b.Height]; 24 | 25 | var A = invertColour ? Color.White.A : Color.Black.A; 26 | var B = invertColour ? Color.White.B : Color.Black.B; 27 | var G = invertColour ? Color.White.G : Color.Black.G; 28 | var R = invertColour ? Color.White.R : Color.Black.R; 29 | for (int y = 0; y < b.Height; y++) { 30 | 31 | for (int x = 0; x < b.Width; x++) { 32 | var pixel = b.GetPixel(x, y); 33 | pixels[(y * b.Width) + x] = (pixel.A == A && pixel.R == R && pixel.G == G && pixel.B == B); 34 | } 35 | 36 | } 37 | 38 | var data = new byte[b.Width * b.Height / 8]; 39 | 40 | for (int i = 0; i < data.Length; i++) { 41 | 42 | for (int j = 0; j < 8; j++) { 43 | 44 | var bit = pixels[(i * 8) + j] ? 1 : 0; 45 | data[i] |= (byte) (bit << (7 - j)); 46 | 47 | } 48 | 49 | } 50 | 51 | return data; 52 | } 53 | 54 | /* 55 | public static byte[] BitmapTo3BppData(Bitmap b, bool invertColour = false) 56 | { 57 | var pixels = new byte[b.Width * b.Height]; 58 | 59 | for (int y = 0; y < b.Height; y++) 60 | { 61 | 62 | for (int x = 0; x < b.Width; x++) 63 | { 64 | 65 | var pixel = b.GetPixel(x, y); 66 | pixels[(y * b.Width) + x] = (byte)((pixel.R + 2 * pixel.G + pixel.B) / 4 * pixel.A / 255); // Weighted Color2Grayscale; 67 | 68 | if (!invertColour) 69 | { 70 | pixels[(y * b.Width) + x] = (byte)(255 - pixels[(y * b.Width) + x]); 71 | } 72 | 73 | // convert to 3 bits 74 | pixels[(y * b.Width) + x] = (byte)(pixels[(y * b.Width) + x] >> 5); 75 | 76 | } 77 | 78 | } 79 | 80 | return pixels; 81 | } 82 | */ 83 | 84 | /* A faster 3-bit encoder and compresser combined into one loop instead of consecutive nested loops */ 85 | public static byte[] BitmapTo3BppData(Bitmap b, bool invertColour = false) 86 | { 87 | var data = new List(); 88 | 89 | var curColor = (byte)0u; 90 | var prevColor = (byte)0u; 91 | var prevCount = 0u; 92 | 93 | var antialias = false; 94 | 95 | data.Add(0x03); 96 | 97 | for (int y = 0; y < b.Height; y++) 98 | { 99 | for (int x = 0; x < b.Width; x++) 100 | { 101 | var pixel = b.GetPixel(x, y); 102 | 103 | if (invertColour) 104 | { 105 | curColor = (byte)((pixel.R + 2 * pixel.G + pixel.B) / 4); // Weighted Color2Grayscale; 106 | } 107 | else 108 | { 109 | curColor = (byte)(255 - (pixel.R + 2 * pixel.G + pixel.B) / 4); // Weighted Color2Grayscale; 110 | } 111 | curColor = (byte)(curColor * pixel.A / 255); 112 | // convert to 3 bits 113 | curColor = (byte)(curColor >> 5); 114 | 115 | if (curColor == prevColor) { 116 | prevCount++; 117 | continue; // to next pixel 118 | } 119 | 120 | if (prevCount == 0) // No previous data to encode 121 | { 122 | prevColor = curColor; 123 | prevCount = 1; 124 | continue; // to next pixel 125 | } 126 | 127 | if (prevColor == 0) 128 | { 129 | while (prevCount >= 31) { 130 | data.Add(CompressedByte.RepeatedWhites(31)); 131 | prevCount -= 31; 132 | } 133 | 134 | if (prevCount == 0) 135 | { 136 | // start with fresh color count 137 | prevColor = curColor; 138 | prevCount = 1; 139 | continue; // to next pixel 140 | } 141 | 142 | if (curColor == 7) 143 | { 144 | data.Add(CompressedByte.RepeatedWhites(prevCount, 1u)); 145 | // start with fresh color count 146 | prevColor = curColor; 147 | prevCount = 0; 148 | continue; // to next pixel 149 | } 150 | 151 | if (prevCount >= 8) 152 | { 153 | data.Add(CompressedByte.RepeatedWhites(prevCount)); 154 | // start with fresh color count 155 | prevColor = curColor; 156 | prevCount = 1; 157 | } 158 | else 159 | { 160 | data.Add(CompressedByte.RepeatedWhites(prevCount, curColor)); 161 | prevColor = curColor; 162 | prevCount = 0; 163 | } 164 | 165 | continue; // to next pixel 166 | } 167 | 168 | if (prevColor == 7) 169 | { 170 | while (prevCount >= 31) 171 | { 172 | data.Add(CompressedByte.RepeatedBlacks(31)); 173 | prevCount -= 31; 174 | } 175 | 176 | if (prevCount > 1) 177 | { 178 | data.Add(CompressedByte.RepeatedBlacks(prevCount)); // remaining blacks 179 | prevCount = 1; 180 | } 181 | else 182 | { 183 | data.Add(CompressedByte.AlphaColors(prevColor, curColor)); // one black + one color 184 | prevCount = 0; 185 | } 186 | prevColor = curColor; 187 | continue; // to next pixel 188 | } 189 | 190 | // a grayscale 191 | antialias = true; 192 | 193 | while (prevCount >= 2) 194 | { 195 | data.Add(CompressedByte.AlphaColors(prevColor, prevColor)); 196 | prevCount -= 2; 197 | } 198 | 199 | if (prevCount == 0) 200 | { 201 | prevCount = 1; 202 | } 203 | else 204 | { 205 | data.Add(CompressedByte.AlphaColors(prevColor, curColor)); // one black + one color 206 | prevCount = 0; 207 | } 208 | prevColor = curColor; 209 | continue; // to next pixel 210 | 211 | } 212 | } 213 | 214 | /* Handle remainder stored in PrevColor and PreCount */ 215 | 216 | if (prevCount == 0) // no more previous data to encode 217 | { 218 | return data.ToArray(); 219 | } 220 | 221 | if (prevColor == 0) 222 | { 223 | while (prevCount >= 31) 224 | { 225 | data.Add(CompressedByte.RepeatedWhites(31)); 226 | prevCount -= 31; 227 | } 228 | 229 | if (prevCount > 0) 230 | { 231 | data.Add(CompressedByte.RepeatedWhites(prevCount)); 232 | } 233 | 234 | return data.ToArray(); 235 | } 236 | 237 | if (prevColor == 7) 238 | { 239 | while (prevCount >= 31) 240 | { 241 | data.Add(CompressedByte.RepeatedBlacks(31)); 242 | prevCount -= 31; 243 | } 244 | 245 | if (prevCount > 0) 246 | { 247 | data.Add(CompressedByte.RepeatedBlacks(prevCount)); 248 | } 249 | 250 | return data.ToArray(); 251 | } 252 | 253 | // a grayscale 254 | while (prevCount >= 2) 255 | { 256 | data.Add(CompressedByte.AlphaColors(prevColor, prevColor)); 257 | prevCount -= 2; 258 | } 259 | 260 | if (prevCount > 0) 261 | { 262 | data.Add(CompressedByte.RepeatedWhites((byte)0, prevColor)); // zero whites + one color 263 | } 264 | 265 | return data.ToArray(); 266 | } 267 | } 268 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/FormFontSuite.Designer.cs: -------------------------------------------------------------------------------- 1 | namespace NextionFontEditor { 2 | partial class FormFontSuite { 3 | /// 4 | /// Required designer variable. 5 | /// 6 | private System.ComponentModel.IContainer components = null; 7 | 8 | /// 9 | /// Clean up any resources being used. 10 | /// 11 | /// true if managed resources should be disposed; otherwise, false. 12 | protected override void Dispose(bool disposing) { 13 | if (disposing && (components != null)) { 14 | components.Dispose(); 15 | } 16 | base.Dispose(disposing); 17 | } 18 | 19 | #region Windows Form Designer generated code 20 | 21 | /// 22 | /// Required method for Designer support - do not modify 23 | /// the contents of this method with the code editor. 24 | /// 25 | private void InitializeComponent() { 26 | System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(FormFontSuite)); 27 | this.statusStrip = new System.Windows.Forms.StatusStrip(); 28 | this.lblStatusStatic = new System.Windows.Forms.ToolStripStatusLabel(); 29 | this.toolStrip1 = new System.Windows.Forms.ToolStrip(); 30 | this.btnNewFontGenerator = new System.Windows.Forms.ToolStripButton(); 31 | this.btnNewFontEditor = new System.Windows.Forms.ToolStripButton(); 32 | this.btnNewFontPreview = new System.Windows.Forms.ToolStripButton(); 33 | this.menuStrip1 = new System.Windows.Forms.MenuStrip(); 34 | this.mnuFile = new System.Windows.Forms.ToolStripMenuItem(); 35 | this.mnuFileExit = new System.Windows.Forms.ToolStripMenuItem(); 36 | this.mnuAbout = new System.Windows.Forms.ToolStripMenuItem(); 37 | this.mnuAboutCredit = new System.Windows.Forms.ToolStripMenuItem(); 38 | this.mnuAboutIcons = new System.Windows.Forms.ToolStripMenuItem(); 39 | this.statusStrip.SuspendLayout(); 40 | this.toolStrip1.SuspendLayout(); 41 | this.menuStrip1.SuspendLayout(); 42 | this.SuspendLayout(); 43 | // 44 | // statusStrip 45 | // 46 | this.statusStrip.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 47 | this.lblStatusStatic}); 48 | this.statusStrip.Location = new System.Drawing.Point(0, 527); 49 | this.statusStrip.Name = "statusStrip"; 50 | this.statusStrip.Size = new System.Drawing.Size(961, 22); 51 | this.statusStrip.TabIndex = 1; 52 | this.statusStrip.Text = "statusStrip1"; 53 | // 54 | // lblStatusStatic 55 | // 56 | this.lblStatusStatic.Name = "lblStatusStatic"; 57 | this.lblStatusStatic.Size = new System.Drawing.Size(207, 17); 58 | this.lblStatusStatic.Text = "Nextion Font Suite by @hagronnestad"; 59 | // 60 | // toolStrip1 61 | // 62 | this.toolStrip1.ImageScalingSize = new System.Drawing.Size(30, 30); 63 | this.toolStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 64 | this.btnNewFontGenerator, 65 | this.btnNewFontEditor, 66 | this.btnNewFontPreview}); 67 | this.toolStrip1.Location = new System.Drawing.Point(0, 24); 68 | this.toolStrip1.Name = "toolStrip1"; 69 | this.toolStrip1.RenderMode = System.Windows.Forms.ToolStripRenderMode.System; 70 | this.toolStrip1.Size = new System.Drawing.Size(961, 37); 71 | this.toolStrip1.TabIndex = 2; 72 | this.toolStrip1.Text = "toolStrip1"; 73 | // 74 | // btnNewFontGenerator 75 | // 76 | this.btnNewFontGenerator.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 77 | this.btnNewFontGenerator.Image = ((System.Drawing.Image)(resources.GetObject("btnNewFontGenerator.Image"))); 78 | this.btnNewFontGenerator.ImageTransparentColor = System.Drawing.Color.Magenta; 79 | this.btnNewFontGenerator.Name = "btnNewFontGenerator"; 80 | this.btnNewFontGenerator.Size = new System.Drawing.Size(34, 34); 81 | this.btnNewFontGenerator.Text = "Font Generator"; 82 | this.btnNewFontGenerator.Click += new System.EventHandler(this.btnNewFontGenerator_Click); 83 | // 84 | // btnNewFontEditor 85 | // 86 | this.btnNewFontEditor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 87 | this.btnNewFontEditor.Image = ((System.Drawing.Image)(resources.GetObject("btnNewFontEditor.Image"))); 88 | this.btnNewFontEditor.ImageTransparentColor = System.Drawing.Color.Magenta; 89 | this.btnNewFontEditor.Name = "btnNewFontEditor"; 90 | this.btnNewFontEditor.Size = new System.Drawing.Size(34, 34); 91 | this.btnNewFontEditor.Text = "Font Editor"; 92 | this.btnNewFontEditor.Click += new System.EventHandler(this.btnNewFontEditor_Click); 93 | // 94 | // btnNewFontPreview 95 | // 96 | this.btnNewFontPreview.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Image; 97 | this.btnNewFontPreview.Image = ((System.Drawing.Image)(resources.GetObject("btnNewFontPreview.Image"))); 98 | this.btnNewFontPreview.ImageTransparentColor = System.Drawing.Color.Magenta; 99 | this.btnNewFontPreview.Name = "btnNewFontPreview"; 100 | this.btnNewFontPreview.Size = new System.Drawing.Size(34, 34); 101 | this.btnNewFontPreview.Text = "Font Preview"; 102 | this.btnNewFontPreview.Click += new System.EventHandler(this.btnNewFontPreview_Click); 103 | // 104 | // menuStrip1 105 | // 106 | this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { 107 | this.mnuFile, 108 | this.mnuAbout}); 109 | this.menuStrip1.Location = new System.Drawing.Point(0, 0); 110 | this.menuStrip1.Name = "menuStrip1"; 111 | this.menuStrip1.Size = new System.Drawing.Size(961, 24); 112 | this.menuStrip1.TabIndex = 3; 113 | this.menuStrip1.Text = "menuStrip1"; 114 | // 115 | // mnuFile 116 | // 117 | this.mnuFile.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 118 | this.mnuFileExit}); 119 | this.mnuFile.Name = "mnuFile"; 120 | this.mnuFile.Size = new System.Drawing.Size(37, 20); 121 | this.mnuFile.Text = "File"; 122 | // 123 | // mnuFileExit 124 | // 125 | this.mnuFileExit.Name = "mnuFileExit"; 126 | this.mnuFileExit.Size = new System.Drawing.Size(92, 22); 127 | this.mnuFileExit.Text = "Exit"; 128 | this.mnuFileExit.Click += new System.EventHandler(this.mnuFileExit_Click); 129 | // 130 | // mnuAbout 131 | // 132 | this.mnuAbout.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { 133 | this.mnuAboutCredit, 134 | this.mnuAboutIcons}); 135 | this.mnuAbout.Name = "mnuAbout"; 136 | this.mnuAbout.Size = new System.Drawing.Size(52, 20); 137 | this.mnuAbout.Text = "About"; 138 | // 139 | // mnuAboutCredit 140 | // 141 | this.mnuAboutCredit.Enabled = false; 142 | this.mnuAboutCredit.Name = "mnuAboutCredit"; 143 | this.mnuAboutCredit.Size = new System.Drawing.Size(274, 22); 144 | this.mnuAboutCredit.Text = "Nextion Font Suite by @hagronnestad"; 145 | // 146 | // mnuAboutIcons 147 | // 148 | this.mnuAboutIcons.Enabled = false; 149 | this.mnuAboutIcons.Name = "mnuAboutIcons"; 150 | this.mnuAboutIcons.Size = new System.Drawing.Size(274, 22); 151 | this.mnuAboutIcons.Text = "Icons by Icons8.com"; 152 | // 153 | // FormFontSuite 154 | // 155 | this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); 156 | this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; 157 | this.ClientSize = new System.Drawing.Size(961, 549); 158 | this.Controls.Add(this.toolStrip1); 159 | this.Controls.Add(this.statusStrip); 160 | this.Controls.Add(this.menuStrip1); 161 | this.DoubleBuffered = true; 162 | this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); 163 | this.IsMdiContainer = true; 164 | this.MainMenuStrip = this.menuStrip1; 165 | this.Name = "FormFontSuite"; 166 | this.Text = "Nextion Font Suite"; 167 | this.WindowState = System.Windows.Forms.FormWindowState.Maximized; 168 | this.Load += new System.EventHandler(this.FormFontSuite_Load); 169 | this.statusStrip.ResumeLayout(false); 170 | this.statusStrip.PerformLayout(); 171 | this.toolStrip1.ResumeLayout(false); 172 | this.toolStrip1.PerformLayout(); 173 | this.menuStrip1.ResumeLayout(false); 174 | this.menuStrip1.PerformLayout(); 175 | this.ResumeLayout(false); 176 | this.PerformLayout(); 177 | 178 | } 179 | 180 | #endregion 181 | 182 | private System.Windows.Forms.StatusStrip statusStrip; 183 | private System.Windows.Forms.ToolStrip toolStrip1; 184 | private System.Windows.Forms.MenuStrip menuStrip1; 185 | private System.Windows.Forms.ToolStripMenuItem mnuFile; 186 | private System.Windows.Forms.ToolStripMenuItem mnuFileExit; 187 | private System.Windows.Forms.ToolStripMenuItem mnuAbout; 188 | private System.Windows.Forms.ToolStripMenuItem mnuAboutCredit; 189 | private System.Windows.Forms.ToolStripButton btnNewFontGenerator; 190 | private System.Windows.Forms.ToolStripButton btnNewFontEditor; 191 | private System.Windows.Forms.ToolStripButton btnNewFontPreview; 192 | private System.Windows.Forms.ToolStripStatusLabel lblStatusStatic; 193 | private System.Windows.Forms.ToolStripMenuItem mnuAboutIcons; 194 | } 195 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/Common/CodePage.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Collections.Generic; 3 | using System.Linq; 4 | using System.Text; 5 | 6 | namespace ZiLib.FileVersion.Common 7 | { 8 | 9 | public class CodePage 10 | { 11 | public CodePageIdentifier CodePageIdentifier { get; set; } 12 | 13 | public byte FirstByteStart { get; set; } 14 | public byte FirstByteEnd { get; set; } 15 | public byte SecondByteStart { get; set; } 16 | public byte SecondByteEnd { get; set; } 17 | 18 | public byte FirstByteSkipAfter { get; set; } 19 | public byte FirstByteSkipCount { get; set; } 20 | public byte SecondByteSkipAfter { get; set; } 21 | public byte SecondByteSkipCount { get; set; } 22 | 23 | public int CharacterCount { get; set; } 24 | public ushort[] CodePoints { get; set; } 25 | 26 | public bool IsMultibyte => !Encoding.IsSingleByte; // SecondByteStart.HasValue && SecondByteEnd.HasValue; 27 | 28 | public Encoding Encoding { get; } 29 | // public byte MultiByteMode { get; } // Use Encoding.IsSingleByte 30 | 31 | public CodePage(CodePageIdentifier codePageid) 32 | { 33 | switch (codePageid) 34 | { 35 | case CodePageIdentifier.ASCII: 36 | CreateSingleByte(32, 95, codePageid); 37 | break; 38 | 39 | case CodePageIdentifier.ISO_8859_1: 40 | case CodePageIdentifier.ISO_8859_2: 41 | case CodePageIdentifier.ISO_8859_3: 42 | case CodePageIdentifier.ISO_8859_4: 43 | case CodePageIdentifier.ISO_8859_5: 44 | case CodePageIdentifier.ISO_8859_6: 45 | case CodePageIdentifier.ISO_8859_7: 46 | case CodePageIdentifier.ISO_8859_8: 47 | case CodePageIdentifier.ISO_8859_9: 48 | case CodePageIdentifier.ISO_8859_11: 49 | case CodePageIdentifier.ISO_8859_13: 50 | case CodePageIdentifier.ISO_8859_15: 51 | case CodePageIdentifier.WINDOWS_1255: 52 | case CodePageIdentifier.WINDOWS_1256: 53 | case CodePageIdentifier.WINDOWS_1257: 54 | case CodePageIdentifier.WINDOWS_1258: 55 | case CodePageIdentifier.WINDOWS_874: 56 | case CodePageIdentifier.KOI8_R: 57 | CreateSingleByte(32, 224, codePageid); 58 | break; 59 | 60 | // A1 C8 A1 FE = Swapped order 61 | case CodePageIdentifier.KS_C_5601_1987: 62 | CreateDoubleByte(0xA1, 0xC8, 0xA1, 0xFE, 0xFF, 0x00, 0xFF, 0x00, codePageid); 63 | break; 64 | 65 | // 81 EF 40 FC = Swapped order 66 | case CodePageIdentifier.SHIFT_JIS: 67 | CreateDoubleByte(0x81, 0xEF, 0x40, 0xFC, 0x9F, 0x40, 0x7E, 0x01, codePageid); 68 | break; 69 | 70 | // A1 F7 A1 FE = Swapped order 71 | case CodePageIdentifier.GB2312: 72 | CreateDoubleByte(0xA1, 0xF7, 0xA1, 0xFE, 0xff, 0x00, 0xff, 0x00, codePageid); 73 | break; 74 | 75 | // A0 F9 40 FE = Swapped order 76 | case CodePageIdentifier.BIG5: 77 | CreateDoubleByte(0xA0, 0xF9, 0x40, 0xFE, 0xFF, 0x00, 0x7E, 0x22, codePageid); 78 | break; 79 | 80 | // FF FF 00 FF = Swapped order 81 | case CodePageIdentifier.UTF_8: 82 | CreateUnicode(codePageid); 83 | break; 84 | 85 | default: 86 | break; 87 | } 88 | 89 | if (codePageid == CodePageIdentifier.UTF_8) 90 | { 91 | Encoding = Encoding.Unicode; 92 | } 93 | else 94 | { 95 | Encoding = Encoding.GetEncoding(codePageid.GetDescription()); 96 | } 97 | // MultiByteMode = (byte)(Encoding.IsSingleByte ? 0 : 1); 98 | } 99 | 100 | 101 | public String GetString(int codepoint) { 102 | switch (CodePageIdentifier) { 103 | case CodePageIdentifier.ASCII: 104 | case CodePageIdentifier.ISO_8859_1: 105 | case CodePageIdentifier.ISO_8859_2: 106 | case CodePageIdentifier.ISO_8859_3: 107 | case CodePageIdentifier.ISO_8859_4: 108 | case CodePageIdentifier.ISO_8859_5: 109 | case CodePageIdentifier.ISO_8859_6: 110 | case CodePageIdentifier.ISO_8859_7: 111 | case CodePageIdentifier.ISO_8859_8: 112 | case CodePageIdentifier.ISO_8859_9: 113 | case CodePageIdentifier.ISO_8859_11: 114 | case CodePageIdentifier.ISO_8859_13: 115 | case CodePageIdentifier.ISO_8859_15: 116 | case CodePageIdentifier.WINDOWS_1255: 117 | case CodePageIdentifier.WINDOWS_1256: 118 | case CodePageIdentifier.WINDOWS_1257: 119 | case CodePageIdentifier.WINDOWS_1258: 120 | case CodePageIdentifier.WINDOWS_874: 121 | case CodePageIdentifier.KOI8_R: 122 | if ((codepoint >= 0) & (codepoint <= 255)) { 123 | var bytes = new byte[1]; 124 | bytes[0] = (byte)codepoint; 125 | return Encoding.GetString(bytes); 126 | } else { 127 | return "?"; 128 | } 129 | 130 | case CodePageIdentifier.KS_C_5601_1987: 131 | case CodePageIdentifier.SHIFT_JIS: 132 | case CodePageIdentifier.GB2312: 133 | case CodePageIdentifier.BIG5: 134 | if ((codepoint >= 0) & (codepoint <= 255)) { 135 | var bytes = new byte[1]; 136 | bytes[0] = (byte)codepoint; 137 | return Encoding.GetString(bytes); 138 | } else if ((codepoint >= 256) & (codepoint <= 65535)) { 139 | var bytes = BitConverter.GetBytes((ushort)codepoint); 140 | return Encoding.GetString(bytes); 141 | } else { 142 | return "?"; 143 | } 144 | 145 | case CodePageIdentifier.UTF_8: 146 | if (codepoint < 0x00d800 | codepoint > 0x00dfff) { 147 | return Char.ConvertFromUtf32(codepoint); 148 | } else { 149 | return "?"; 150 | } 151 | 152 | default: 153 | return "?"; 154 | } 155 | } 156 | 157 | private void CreateSingleByte(byte start, byte count, CodePageIdentifier codepageid) 158 | { 159 | var characters = Enumerable.Range(start, count).Select(x => (ushort)x).ToArray(); 160 | 161 | FirstByteStart = start; 162 | FirstByteEnd = (byte)(start + count); 163 | SecondByteStart = SecondByteEnd = 0; 164 | 165 | // No skipped bytes 166 | FirstByteSkipAfter = SecondByteSkipAfter = 0xff; 167 | FirstByteSkipCount = SecondByteSkipCount = 0x00; 168 | 169 | CodePageIdentifier = codepageid; 170 | CodePoints = characters.ToArray(); 171 | CharacterCount = CodePoints.Length; 172 | } 173 | 174 | private void CreateDoubleByte(byte outerStart, byte outerEnd, byte innerStart, byte innerEnd, 175 | byte outerSkip, byte outerCount, byte innerSkip, byte innerCount, 176 | CodePageIdentifier codepageid) 177 | { 178 | var characters = new List(); 179 | 180 | // Outer Loop 181 | for (int i = outerStart; i <= outerEnd; i++) 182 | { 183 | if ((i > outerSkip) && (i <= outerSkip + outerCount)) 184 | { 185 | continue; // i is in exclusion range 186 | } 187 | 188 | // Inner Loop 189 | for (int j = innerStart; j <= innerEnd; j++) 190 | { 191 | if ((j > innerSkip) && (j <= innerSkip + innerCount)) 192 | { 193 | continue; // j is in exclusion range 194 | } 195 | 196 | //bytes.Add((byte) i); 197 | //bytes.Add((byte) j); 198 | characters.Add((char)(j * 256 + i)); 199 | //characters.Add((uint)(i * 256 + j)); 200 | } 201 | } 202 | 203 | // End with ascii standard set 204 | for (int i = 32; i <= 126; i++) 205 | { 206 | characters.Add((char)i); 207 | } 208 | 209 | SecondByteStart = outerStart; 210 | SecondByteEnd = outerEnd; 211 | FirstByteStart = innerStart; 212 | FirstByteEnd = innerEnd; 213 | 214 | SecondByteSkipAfter = outerSkip; 215 | SecondByteSkipCount = outerCount; 216 | FirstByteSkipAfter = innerSkip; 217 | FirstByteSkipCount = innerCount; 218 | 219 | CodePageIdentifier = codepageid; 220 | CodePoints = characters.ToArray(); 221 | CharacterCount = CodePoints.Length; 222 | } 223 | 224 | // The TJC/Nextion UTF-8 is actually Unicode encoding 225 | private void CreateUnicode(CodePageIdentifier codepageid) 226 | { 227 | var characters = new List(); 228 | 229 | SecondByteStart = FirstByteStart = SecondByteSkipCount = FirstByteSkipCount = 0; 230 | SecondByteEnd = FirstByteEnd = SecondByteSkipAfter = FirstByteSkipAfter = 255; 231 | 232 | // Outer Loop 233 | for (int i = SecondByteStart; i <= SecondByteEnd; i++) 234 | { 235 | // Inner Loop 236 | for (int j = FirstByteStart; j <= FirstByteEnd; j++) 237 | { 238 | //bytes.Add((byte) j); 239 | //bytes.Add((byte) i); 240 | characters.Add((char)(i * 256 + j)); 241 | } 242 | } 243 | 244 | SecondByteStart = 255; 245 | CodePageIdentifier = codepageid; 246 | CodePoints = characters.ToArray(); 247 | CharacterCount = CodePoints.Length; 248 | } 249 | } 250 | } -------------------------------------------------------------------------------- /NextionFontEditor/NextionFontEditor/Controls/CharEditor.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Drawing; 3 | using System.Drawing.Drawing2D; 4 | using System.Windows.Forms; 5 | using ZiLib; 6 | 7 | namespace NextionFontEditor.Controls { 8 | 9 | public class CharEditor : Control { 10 | private IZiCharacter _character; 11 | private Graphics _charGraphics; 12 | private int _zoom = 10; 13 | private bool _showGrid = true; 14 | private bool _showKerning = true; 15 | 16 | private Bitmap _bBuffer; 17 | private Graphics _gBuffer; 18 | 19 | private const int GUIDE_SIZE = 5; 20 | 21 | public CharEditor() : base() { 22 | BackColor = Color.WhiteSmoke; 23 | } 24 | 25 | protected override bool DoubleBuffered => true; 26 | 27 | protected override void OnCreateControl() { 28 | base.OnCreateControl(); 29 | 30 | //CharImage = new Bitmap(16, 32); 31 | } 32 | 33 | protected override void OnResize(EventArgs e) { 34 | base.OnResize(e); 35 | SetSize(); 36 | } 37 | 38 | protected override void OnPaintBackground(PaintEventArgs pevent) { 39 | base.OnPaintBackground(pevent); 40 | } 41 | 42 | protected override void OnPaint(PaintEventArgs e) { 43 | base.OnPaint(e); 44 | var _charImage = _character?.ToBitmap(); 45 | 46 | if (_charImage != null && _bBuffer != null && _gBuffer != null) { 47 | _gBuffer.Clear(Color.Transparent); 48 | _gBuffer.DrawImage(_charImage, 0, 0, _charImage.Width * Zoom, _charImage.Height * Zoom); 49 | 50 | if (_showGrid) DrawGrid(); 51 | 52 | /* Kerning updates */ 53 | if (_showKerning) DrawKerning(); 54 | 55 | SolidBrush bgBrush = new SolidBrush(SystemColors.ControlDark); 56 | e.Graphics.FillRectangle(bgBrush, 0, 0, _charImage.Width * Zoom, GUIDE_SIZE); 57 | e.Graphics.FillRectangle(bgBrush, 0, _charImage.Height * Zoom + GUIDE_SIZE, _charImage.Width * Zoom, GUIDE_SIZE); 58 | 59 | SolidBrush fgBrush = new SolidBrush(Color.Red); 60 | Rectangle rect = new Rectangle(2 * Zoom - GUIDE_SIZE, -GUIDE_SIZE, 2 * GUIDE_SIZE, 2 * GUIDE_SIZE); 61 | e.Graphics.FillPie(fgBrush, rect, 90, 90); 62 | fgBrush = new SolidBrush(Color.Red); 63 | rect = new Rectangle(2 * Zoom - GUIDE_SIZE, -GUIDE_SIZE, 2 * GUIDE_SIZE, 2 * GUIDE_SIZE); 64 | e.Graphics.FillPie(fgBrush, rect, 90, -90); 65 | rect = new Rectangle(2 * Zoom - GUIDE_SIZE, _charImage.Height * Zoom - GUIDE_SIZE, 2 * GUIDE_SIZE, 2 * GUIDE_SIZE); 66 | e.Graphics.FillPie(fgBrush, rect, 90, -90); 67 | 68 | fgBrush = new SolidBrush(Color.Red); 69 | rect = new Rectangle(2 * Zoom - GUIDE_SIZE, 0, 2 * GUIDE_SIZE, GUIDE_SIZE); 70 | e.Graphics.FillPie(fgBrush, rect, 270, 90); 71 | rect = new Rectangle(2 * Zoom - GUIDE_SIZE, _charImage.Height * Zoom + GUIDE_SIZE, 2 * GUIDE_SIZE, GUIDE_SIZE); 72 | e.Graphics.FillPie(fgBrush, rect, 270, 90); 73 | 74 | e.Graphics.DrawImage(_bBuffer, 0, GUIDE_SIZE, _bBuffer.Width, _bBuffer.Height); 75 | } 76 | 77 | } 78 | 79 | protected override void OnMouseClick(MouseEventArgs e) { 80 | base.OnMouseClick(e); 81 | if (e.Button != MouseButtons.Left) return; 82 | var _charImage = _character?.ToBitmap(); 83 | 84 | var x = e.X / Zoom; 85 | var y = (e.Y - GUIDE_SIZE) / Zoom; 86 | 87 | if (x < 0 || x > _character?.Width - 1 || y < 0 || y > _character?.Parent.CharacterHeight - 1) return; 88 | 89 | TogglePixel(_charImage, x, y); 90 | 91 | Invalidate(); 92 | Refresh(); 93 | } 94 | 95 | private int lastX = -1; 96 | private int lastY = -1; 97 | 98 | protected override void OnMouseDown(MouseEventArgs e) { 99 | base.OnMouseDown(e); 100 | if (e.Button != MouseButtons.Left) return; 101 | var _charImage = _character?.ToBitmap(); 102 | 103 | var x = e.X / Zoom; 104 | var y = (e.Y - GUIDE_SIZE) / Zoom; 105 | 106 | if (x < 0 || x > _charImage?.Width - 1 || y < 0 || y > _charImage?.Height - 1) return; 107 | 108 | lastX = x; 109 | lastY = y; 110 | } 111 | 112 | protected override void OnMouseMove(MouseEventArgs e) { 113 | base.OnMouseMove(e); 114 | var _charImage = _character?.ToBitmap(); 115 | 116 | var x = e.X / Zoom; 117 | var y = (e.Y - GUIDE_SIZE) / Zoom; 118 | 119 | if (x < 0) x = 0; 120 | if (y < 0) y = 0; 121 | if (y > _charImage?.Height - 1) y = _charImage.Height - 1; 122 | if (x > _charImage?.Width - 1) x = _charImage.Width - 1; 123 | 124 | if (e.Button == MouseButtons.Left) { 125 | if (x != lastX || y != lastY) { 126 | TogglePixel(_charImage, lastX, lastY); 127 | 128 | Invalidate(); 129 | Refresh(); 130 | } 131 | 132 | lastX = x; 133 | lastY = y; 134 | } 135 | } 136 | 137 | public void Clear() { 138 | if (_charGraphics == null) return; 139 | var _charImage = _character.ToBitmap(); 140 | 141 | _charGraphics.Clear(Color.Transparent); 142 | Character.SetBitmap(_charImage); 143 | var ts = (ToolStrip)this.Parent.Parent.Controls["tsCharEditor"]; 144 | ts.Items["btnRevertCharacter"].Enabled = true; 145 | 146 | Invalidate(); 147 | Refresh(); 148 | } 149 | 150 | public void MoveCharacterX(int pixels) { 151 | if (_charGraphics == null) return; 152 | var _charImage = _character.ToBitmap(); 153 | 154 | using (var b = new Bitmap(_charImage)) { 155 | _charGraphics.Clear(Color.White); 156 | _charGraphics.DrawImage(b, pixels, 0); 157 | } 158 | _charImage.Tag = true; // Bitmap is dirty or has changed 159 | var ts = (ToolStrip)this.Parent.Parent.Controls["tsCharEditor"]; 160 | ts.Items["btnRevertCharacter"].Enabled = true; 161 | 162 | Invalidate(); 163 | Refresh(); 164 | } 165 | 166 | public void MoveCharacterY(int pixels) { 167 | if (_charGraphics == null) return; 168 | var _charImage = _character.ToBitmap(); 169 | 170 | using (var b = new Bitmap(_charImage)) { 171 | _charGraphics.Clear(Color.White); 172 | _charGraphics.DrawImage(b, 0, pixels); 173 | } 174 | _charImage.Tag = true; // Bitmap is dirty or has changed 175 | var ts = (ToolStrip)this.Parent.Parent.Controls["tsCharEditor"]; 176 | ts.Items["btnRevertCharacter"].Enabled = true; 177 | 178 | Invalidate(); 179 | Refresh(); 180 | } 181 | 182 | private void CreateBuffer() { 183 | if (_character == null) return; 184 | var _charImage = _character.ToBitmap(); 185 | 186 | _bBuffer = new Bitmap(_charImage.Width * Zoom, _charImage.Height * Zoom); 187 | _gBuffer = Graphics.FromImage(_bBuffer); 188 | 189 | _gBuffer.PixelOffsetMode = PixelOffsetMode.Half; 190 | _gBuffer.InterpolationMode = InterpolationMode.NearestNeighbor; 191 | _gBuffer.SmoothingMode = SmoothingMode.None; 192 | } 193 | 194 | private void TogglePixel(Bitmap b, int x, int y) { 195 | if (x < 0 || y < 0) { return; } 196 | b = _character?.ToBitmap(); 197 | 198 | if (b != null) { 199 | var p = b.GetPixel(x, y); 200 | b.SetPixel(x, y, p.A == 255 && p.R == 0 && p.G == 0 && p.B == 0 ? Color.FromArgb(0, 255, 255, 255) : Color.FromArgb(255, 0, 0, 0)); 201 | Character.SetPixel(x, y, b.GetPixel(x, y)); 202 | //_charImage.Tag = true; // Bitmap is dirty or has changed 203 | var ts = (ToolStrip)this.Parent.Parent.Controls["tsCharEditor"]; 204 | ts.Items["btnRevertCharacter"].Enabled = true; 205 | } 206 | } 207 | 208 | private void SetSize() { 209 | if (_character == null) return; 210 | 211 | Width = _character.Width * Zoom; 212 | Height = _character.Parent.CharacterHeight * Zoom + 10; 213 | } 214 | 215 | private void DrawGrid() { 216 | if (_character == null) return; 217 | if (_gBuffer == null) return; 218 | var _charImage = _character.ToBitmap(); 219 | 220 | for (int x = 0; x < _charImage.Width; x++) { 221 | _gBuffer.DrawLine(Pens.LightGray, x * Zoom, 0, x * Zoom, _charImage.Height * Zoom); 222 | } 223 | 224 | for (int y = 0; y < _charImage.Height; y++) { 225 | _gBuffer.DrawLine(Pens.LightGray, 0, y * Zoom, _charImage.Width * Zoom, y * Zoom); 226 | } 227 | 228 | 229 | _gBuffer.DrawRectangle(Pens.LightGray, 1, 1, _charImage.Width * Zoom - 1, _charImage.Height * Zoom - 1); 230 | } 231 | 232 | private void DrawKerning() { 233 | if (_character == null) return; 234 | if (_gBuffer == null) return; 235 | var _charImage = _character.ToBitmap(); 236 | 237 | if (_character.KerningLeft > 0) { 238 | _gBuffer.DrawLine(Pens.Red, _character.KerningLeft * Zoom, 0, _character.KerningLeft * Zoom, _charImage.Height * Zoom); 239 | } 240 | 241 | if (_character.KerningRight > 0) { 242 | _gBuffer.DrawLine(Pens.Red, (_charImage.Width - _character.KerningRight) * Zoom, 0, (_charImage.Width - _character.KerningRight) * Zoom, _charImage.Height * Zoom); 243 | } 244 | 245 | } 246 | 247 | public IZiCharacter Character { 248 | get => _character; 249 | set { 250 | Bitmap b; 251 | _character = value; 252 | if (_character == null) { 253 | b = new Bitmap(8, 16); 254 | } else { 255 | b = _character.ToBitmap(); 256 | } 257 | _charGraphics = Graphics.FromImage(b); 258 | 259 | CreateBuffer(); 260 | SetSize(); 261 | Invalidate(); 262 | } 263 | 264 | } 265 | 266 | public int Zoom { 267 | get => _zoom; 268 | set { 269 | _zoom = value; 270 | ShowGrid = _zoom > 3; 271 | CreateBuffer(); 272 | SetSize(); 273 | Invalidate(); 274 | } 275 | } 276 | 277 | public bool ShowGrid { 278 | get => _showGrid; 279 | set { 280 | _showGrid = value; 281 | Invalidate(); 282 | } 283 | } 284 | } 285 | } -------------------------------------------------------------------------------- /NextionFontEditor/ZiLib/FileVersion/V3/ZiCharacterV3.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Diagnostics; 3 | using System.Drawing; 4 | using System.Collections.Generic; 5 | 6 | namespace ZiLib.FileVersion.V3 { 7 | internal enum ValidData : byte { 8 | UNKNOWN = 0x0, 9 | TEXT = 0x01, 10 | BITMAP = 0x02, 11 | TEXT_BITMAP = 0x03, 12 | CHARDATA = 0x04, 13 | CHARDATA_BITMAP = 0x06, 14 | TEXT_CHARDATA_BITMAP = 0x07 15 | } 16 | 17 | public class ZiCharacterV3 : IZiCharacter { 18 | byte ColorMode { get; set; } 19 | private ValidData DataState { get; set; } 20 | 21 | /* Common Properties */ 22 | public IZiFont Parent { get; set; } 23 | public uint CodePoint { get; set; } 24 | public byte Width { get; set; } 25 | public byte KerningLeft { get; set; } 26 | public byte KerningRight { get; set; } 27 | public Color ForegroundColor { get; set; } 28 | 29 | /* FromString Constructor */ 30 | public String Txt { get; set; } 31 | public PointF TxtPosition { get; set; } 32 | public Font Font { get; set; } 33 | 34 | /* FromBitmap Constructor and after rendering with DrawString or Decode from bytes */ 35 | private Bitmap _Bitmap { get; set; } 36 | 37 | /* FromBytes constructor and after encoding the bitmap */ 38 | private byte[] _CharacterData { get; set; } 39 | 40 | /* Helpers */ 41 | byte TotalWidth => (byte)(Parent.CharacterWidth); 42 | public byte[] ToBytes() => GetCharacterData(); 43 | 44 | private ValidData OriginalFormat; 45 | 46 | /* Constructors */ 47 | public ZiCharacterV3(IZiFont parent, uint codepoint, Bitmap bmp, byte kerningL = 0, byte kerningR = 0) { 48 | Parent = parent; 49 | CodePoint = codepoint; 50 | _Bitmap = new Bitmap(Parent.CharacterWidth, Parent.CharacterHeight); 51 | using (var graphics = Graphics.FromImage(_Bitmap)) { 52 | graphics.DrawImage(bmp, 0, 0); 53 | } 54 | if (_CharacterData != null) { 55 | _CharacterData = null; 56 | } 57 | KerningRight = KerningLeft = 0; // Kerning is not supported in V3 58 | Width = Parent.CharacterWidth; // Fixed Width set by Parent Font 59 | DataState = ValidData.BITMAP; 60 | OriginalFormat = DataState; 61 | ForegroundColor = Color.Green; 62 | } 63 | public ZiCharacterV3(IZiFont parent, uint codepoint, byte[] bytes, byte width=0, byte kerningL = 0, byte kerningR = 0) { 64 | Parent = parent; 65 | CodePoint = codepoint; 66 | if (_Bitmap != null && _Bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Undefined) { 67 | _Bitmap.Dispose(); 68 | } 69 | _CharacterData = bytes; 70 | KerningRight = KerningLeft = 0; // Kerning is not supported in V3 71 | DataState = ValidData.CHARDATA; 72 | OriginalFormat = DataState; 73 | Width = Parent.CharacterWidth; // Fixed Width set by Parent Font 74 | ForegroundColor = Color.Aqua; 75 | } 76 | 77 | public ZiCharacterV3(IZiFont parent, uint codepoint, Font font, PointF location, String txt = null) { 78 | Parent = parent; 79 | CodePoint = codepoint; 80 | SetString(font, location, txt); 81 | if (_Bitmap != null && _Bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Undefined) { 82 | _Bitmap.Dispose(); 83 | } 84 | if (_CharacterData != null) { 85 | _CharacterData = null; 86 | } 87 | ForegroundColor = Color.Chocolate; 88 | } 89 | 90 | /* Bitmap Operations */ 91 | public void SetPixel(int x, int y, System.Drawing.Color pixel) { 92 | DataState = ValidData.BITMAP; 93 | _Bitmap.SetPixel(x, y, pixel); 94 | } 95 | 96 | public Color GetPixel(int x, int y) { 97 | var bmp = ToBitmap(); 98 | return bmp.GetPixel(x, y); 99 | } 100 | 101 | public void SetPixelNumber(int number, Color color) { 102 | if (number >= _Bitmap.Width * _Bitmap.Height) { 103 | Debug.WriteLine($"!!! pixelNumber >= {_Bitmap.Width * _Bitmap.Height} !!!"); 104 | return; 105 | } 106 | 107 | var l = ZiLib.Extensions.BitmapExtensions.NumberToPoint(number, _Bitmap.Width); 108 | _Bitmap.SetPixel(l.X, l.Y, color); 109 | } 110 | 111 | public Bitmap ToBitmap() { 112 | /* Check if Bitmap bit is 0 in the DataState */ 113 | if ((DataState & ValidData.BITMAP) == 0) { 114 | if ((DataState & ValidData.CHARDATA) != 0) { 115 | Decode(); 116 | } else { 117 | DrawString(Txt, Font, Parent.CharacterHeight, TxtPosition); 118 | Width = 0; // (byte)_Bitmap.Width; 119 | } 120 | DataState = DataState | ValidData.BITMAP; 121 | } 122 | return _Bitmap; 123 | } 124 | 125 | public void SetBitmap(Bitmap bmp) { 126 | if (_Bitmap != null && _Bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Undefined) { 127 | using (var graphics = Graphics.FromImage(_Bitmap)) { 128 | graphics.FillRectangle(Brushes.Transparent, 0, 0, _Bitmap.Width, _Bitmap.Height); 129 | graphics.DrawImage(bmp, 0, 0); 130 | } 131 | DataState = ValidData.BITMAP; 132 | } 133 | } 134 | 135 | public String GetString() { 136 | return Parent.CodePage.GetString((int)CodePoint); 137 | } 138 | 139 | public void SetString(Font font, PointF location, String txt = null) { 140 | DataState = ValidData.TEXT; 141 | OriginalFormat = DataState; 142 | 143 | Txt = txt; 144 | TxtPosition = location; 145 | Font = font; 146 | 147 | ForegroundColor = Color.Crimson; 148 | } 149 | 150 | public Bitmap RevertBitmap() { 151 | DataState = OriginalFormat; 152 | return ToBitmap(); 153 | } 154 | public bool CanRevert() { 155 | return (DataState == ValidData.BITMAP); 156 | } 157 | 158 | /* Byte Array Operations */ 159 | public byte[] GetCharacterData() { 160 | /* Check if CharData bit is 0 in the DataState */ 161 | if ((DataState & ValidData.CHARDATA) == 0) { 162 | if ((DataState & ValidData.BITMAP) == 0) { 163 | var b = ToBitmap(); 164 | } 165 | _CharacterData = Encode(_Bitmap, false); 166 | DataState = DataState | ValidData.CHARDATA; 167 | } 168 | return _CharacterData; 169 | } 170 | 171 | private void DrawString(string txt, Font font, byte height, PointF location, byte contrast = 0) { 172 | var fontsize = (float)height; 173 | 174 | var strFormat = (StringFormat)StringFormat.GenericTypographic.Clone(); 175 | strFormat.FormatFlags = strFormat.FormatFlags | StringFormatFlags.MeasureTrailingSpaces | StringFormatFlags.NoWrap | StringFormatFlags.NoFontFallback; 176 | 177 | var tmp = new Bitmap(1, 1); 178 | var grphtmp = Graphics.FromImage(tmp); 179 | 180 | var width = Parent.CharacterWidth; 181 | //width = width > 255 ? 255 : width; 182 | 183 | if (width <= 0) { 184 | // Nextion requires a minimum width of 1 pixel. It doesn't like zero length chardata as it crashes the Application when rotating the font. 185 | _Bitmap = new Bitmap(1, height); 186 | return; 187 | } 188 | 189 | var b = new Bitmap(width + KerningLeft + KerningRight, height); 190 | location.X += KerningLeft; 191 | 192 | using (var graphics = Graphics.FromImage(b)) { 193 | 194 | //Adjust for high quality 195 | graphics.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality; 196 | graphics.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic; 197 | graphics.PixelOffsetMode = System.Drawing.Drawing2D.PixelOffsetMode.HighQuality; 198 | graphics.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias; // AntiAlias // HighQuality 199 | graphics.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAliasGridFit; //AntiAliasGridFit; // (B/W = SingleBitPerPixelGridFit) 200 | graphics.TextContrast = contrast; 201 | 202 | // Make sure the background is Transparent as the encoder only looks at the Alpha channel, not Text color 203 | graphics.FillRectangle(Brushes.Transparent, 0, 0, b.Width, b.Height); 204 | graphics.DrawString(txt, font, Brushes.Black, location, strFormat); // experimental 205 | 206 | //TextRenderer.DrawText(graphics, txt, font, new Point(x, y), Color.Black, Color.White); 207 | } 208 | 209 | _Bitmap = new Bitmap(b.Width, b.Height); 210 | for (var y = 0; y < b.Height; y++) { 211 | for (var x = 0; x < b.Width; x++) { 212 | var alpha = Get1bppColor(b.GetPixel(x, y), false); 213 | SetPixelNumber(y * b.Width + x, Color.FromArgb((255 / 7) * alpha, ForegroundColor)); 214 | } 215 | } 216 | 217 | b.Dispose(); 218 | } 219 | 220 | private byte Get1bppColor(Color pixel, bool invertColour) { 221 | var curColor = (byte)0u; 222 | if (invertColour) { 223 | curColor = (byte)(255 - pixel.A); 224 | } else { 225 | curColor = (byte)pixel.A; 226 | } 227 | // convert to 1 bits 228 | return (byte)(curColor >> 7); 229 | } 230 | 231 | private byte[] Encode(Bitmap b, bool invertColour = false) { 232 | var data = new List(); 233 | 234 | return data.ToArray(); 235 | } 236 | 237 | private void Decode() { 238 | 239 | var charData = _CharacterData; 240 | if (Parent.CharacterWidth > 0 && Parent.CharacterHeight > 0) { 241 | _Bitmap = new Bitmap(Parent.CharacterWidth, Parent.CharacterHeight); 242 | } else { 243 | if (_Bitmap != null && _Bitmap.PixelFormat != System.Drawing.Imaging.PixelFormat.Undefined) { 244 | _Bitmap.Dispose(); 245 | } 246 | return; 247 | } 248 | 249 | var g = Graphics.FromImage(_Bitmap); 250 | var bb = new SolidBrush(Color.Black); 251 | var pr = new Pen(Color.DarkCyan); 252 | 253 | var pixels = BinaryTools.BytesToBits(_CharacterData); 254 | var pixel = 0; 255 | 256 | for (int y = 0; y < Parent.CharacterHeight; y++) { 257 | for (int x = 0; x < Parent.CharacterWidth; x++) { 258 | if (pixels[pixel]) SetPixelNumber(pixel, Color.Black); // g.FillRectangle(bb, x, y, 1, 1); 259 | 260 | pixel++; 261 | } 262 | } 263 | 264 | } 265 | 266 | } 267 | } --------------------------------------------------------------------------------