128 Commits
v1.8 ... v1.10

Author SHA1 Message Date
minjaesong
49f5e649b7 Making FontDemoGDX release-able again 2022-01-02 10:06:48 +09:00
minjaesong
1656e50c3b new year new copyright date 2022-01-01 22:06:26 +09:00
minjaesong
99a1648734 some edits 2022-01-01 19:12:25 +09:00
minjaesong
9672aa8e05 PUA realloc; tamil ligatures 2021-12-29 13:50:55 +09:00
minjaesong
d72ecb5cfd minor fix 2021-12-28 20:11:54 +09:00
minjaesong
39fccbe6cb some random miscellaneous work 2021-12-28 17:43:26 +09:00
minjaesong
84efb253cf testification 2021-12-26 17:41:52 +09:00
minjaesong
4c63860dc1 amendments 2021-12-21 15:26:44 +09:00
minjaesong
36acc7e523 more doc thingy 2021-12-21 14:56:11 +09:00
minjaesong
700397a995 more fixes for diacritics system 2021-12-21 14:05:25 +09:00
minjaesong
dc6bd89497 expanding diacritics types to correctly implement thai diacritics 2021-12-21 12:01:48 +09:00
minjaesong
c2ed83d511 halfwidth ㅆ had bad replacement chars defined 2021-12-20 22:55:33 +09:00
minjaesong
0a41da1659 minor changes 2021-12-20 01:51:15 +09:00
minjaesong
96e412414a slight changes in glyphs 2021-12-18 11:53:08 +09:00
minjaesong
483476b5fa halfwidth and fullwidth forms 2021-12-17 15:19:36 +09:00
minjaesong
ed8bcf7dc8 icon for mouse drag 2021-12-16 16:58:40 +09:00
minjaesong
376c7cf9a4 phonetic extensions 2021-12-14 17:16:13 +09:00
minjaesong
05d34d563d removing global flipY key 2021-12-13 02:52:45 +09:00
minjaesong
e59db6954a fixing wrong kerning tag for 'y'-like characters 2021-12-12 19:32:18 +09:00
minjaesong
9c05fb399b minute thai kerning change 2021-12-12 13:58:49 +09:00
minjaesong
40d4bc41c6 finally working on phonetic extensions 2021-12-09 17:38:11 +09:00
minjaesong
1f9a79db48 Enclosed Alphanumeric Supplement 2021-12-08 15:05:16 +09:00
minjaesong
0943d38926 implementation of "replacewith" compiler directive 2021-12-08 11:12:05 +09:00
minjaesong
5469b56841 minor changes on fraktur letters 2021-12-08 09:32:54 +09:00
minjaesong
d31730b5c3 arts for letterlike_symbols 2021-12-07 15:21:23 +09:00
minjaesong
bd36ee7399 wip 2021-12-06 09:14:15 +09:00
minjaesong
b8f5f57878 more fraktur 2021-12-05 22:04:13 +09:00
minjaesong
63de646eae font wip 2021-12-05 17:50:04 +09:00
minjaesong
e70ee44a37 fixing yet another bug on thai diacritics 2021-12-04 17:36:50 +09:00
minjaesong
6ee66fdccc tsalagi kerning 2021-11-30 14:47:40 +09:00
minjaesong
5ecffa1352 hayeren kerning 2021-11-30 13:04:03 +09:00
minjaesong
46efc42e24 kartuli kerning 2021-11-30 12:41:01 +09:00
minjaesong
35829ce982 greek and insular kerning 2021-11-30 12:21:58 +09:00
minjaesong
756ef4fae5 cyrillic kerning 2021-11-30 11:14:47 +09:00
minjaesong
ce31a5a6ef making use of the long-neglected scale variable 2021-11-28 12:42:34 +09:00
minjaesong
14ea4d8d84 thai kerning 2021-11-27 17:59:20 +09:00
minjaesong
f2eb1464f6 kerning ipa-ext 2021-11-27 11:56:06 +09:00
minjaesong
45b464ee13 hopefully alleviating a bug involving multithreaded (or mixed thread?) usage 2021-11-26 21:06:05 +09:00
minjaesong
c3f9ea47fd fixed a bug where shift+space and shift+backspace would play wrong sound 2021-11-26 17:10:18 +09:00
minjaesong
87012d7671 typewriter: faster typing sound, backspace is working again 2021-11-26 16:58:54 +09:00
minjaesong
1fce4055d7 some sort of an intro for the typewriter 2021-11-26 16:18:13 +09:00
minjaesong
b83dd501fc typewriting sound on typewriter 2021-11-26 15:27:09 +09:00
minjaesong
94a40a4a87 diacritics bit is now colour-coded 2021-11-26 10:59:30 +09:00
minjaesong
2fa867ce44 width adjustment for qwerty typewriter 2021-11-25 17:16:49 +09:00
minjaesong
4d1a599263 typewriter accepting new tagging system 2021-11-25 17:03:11 +09:00
minjaesong
8641c95169 new tagging system 2021-11-25 16:46:22 +09:00
minjaesong
4f6584ac27 minor change in kerning rule 2021-11-25 13:44:18 +09:00
minjaesong
cb25c5bf56 hangul typewriter: more faithful to the machine i'm copying 2021-11-25 11:48:45 +09:00
minjaesong
5c534ed388 glyph control bits spec change 2021-11-25 10:31:16 +09:00
minjaesong
368bf0ee15 typewriter hangul: trying fixed 7 px width... 2021-11-25 09:20:45 +09:00
minjaesong
c9ccf3e7f8 punctuations kerning 2021-11-24 17:57:17 +09:00
minjaesong
0ced94cb57 0000FC for superscripts! 2021-11-24 17:44:44 +09:00
minjaesong
b158e11e25 extd kerned 2021-11-24 17:35:41 +09:00
minjaesong
f4658daa9a extc 2021-11-24 16:19:34 +09:00
minjaesong
56b4ccb848 typewriter minor adjustments 2021-11-24 15:52:19 +09:00
minjaesong
2748eeb367 typewriter keymap minor change 2021-11-24 13:32:09 +09:00
minjaesong
8647578802 wtf is this char??? 2021-11-24 10:05:53 +09:00
minjaesong
3422c20322 latin ext-b updated for unicode 14.0 2021-11-24 09:52:54 +09:00
minjaesong
4561b06428 latin ext-d updated for unicode 14.0 2021-11-24 09:49:16 +09:00
minjaesong
652f239af3 extb 2021-11-21 22:37:14 +09:00
minjaesong
c2428ff7c2 extb wip 2021-11-21 17:46:04 +09:00
minjaesong
2d5e592622 kerning data for ascii,exta,extadditional 2021-11-21 16:55:34 +09:00
minjaesong
3a569a2e2e suppress debug prints if debug=false 2021-11-21 12:19:03 +09:00
minjaesong
f600764364 automatically creating symmetrical dual for kerning rules 2021-11-20 21:05:54 +09:00
minjaesong
ab2669b555 kerning for the pairs such as Pr,Fu,Fo,etc 2021-11-20 18:36:45 +09:00
minjaesong
f43a81de3f kerning bits for 0000..00ff 2021-11-20 16:37:25 +09:00
minjaesong
33ae3fa48a First working version of the Keming Machine 2021-11-20 15:46:43 +09:00
minjaesong
12fc3eee03 fixed a bug where dots on i and j were always being removed 2021-11-20 14:36:53 +09:00
minjaesong
396954e0ee extra args not needed when you've got flipY 2021-11-18 17:42:51 +09:00
minjaesong
d65aaa6da6 added a way to change diacritic shifting direction 2021-11-18 17:34:16 +09:00
minjaesong
ae67833cb2 diacritic dot removal for i and j 2021-11-18 17:18:42 +09:00
minjaesong
4261652bdf thai glyph update 2021-11-16 22:29:35 +09:00
minjaesong
49d83a297f greek F 2021-11-16 17:57:06 +09:00
minjaesong
b3a48b23ee added diacritics placeholders to PUA 2021-11-16 17:04:49 +09:00
minjaesong
b802f9b02e changed the shape of cyrillic palochka 2021-11-16 11:12:45 +09:00
minjaesong
0afdb9c2cf minor modifications on LatinExtABCD; added support for unicode Currency Symbols 2021-11-16 11:11:13 +09:00
minjaesong
c295430866 more errorOnUnknownChar flag check 2021-11-11 16:48:53 +09:00
minjaesong
883375dc9b minor modification on Ł ł and · (middot) 2021-11-09 22:32:22 +09:00
minjaesong
6a1208b45d more wip 2021-11-08 22:23:05 +09:00
minjaesong
25084b7a94 alphanumeric wip 2021-11-07 13:51:49 +09:00
minjaesong
c325c9c30c typewriter: latin alph capitals 2021-11-06 17:28:49 +09:00
minjaesong
d89409cc73 omg i think this is fimally working 2021-11-06 13:54:04 +09:00
minjaesong
0ff564a192 another minor mod 2021-11-05 23:07:35 +09:00
minjaesong
930804cf48 minor mod on Choseong HIEUH 2021-11-05 22:52:32 +09:00
minjaesong
699981d9a2 probably useable now 2021-11-05 22:47:59 +09:00
minjaesong
947c966660 typewriter font is working but not quite 2021-11-05 17:18:11 +09:00
minjaesong
554d9a5d0b will use config string this time 2021-11-04 22:44:40 +09:00
minjaesong
45e5c39739 making new font class for typewriter; renaming existing one with more sensible name 2021-11-04 21:42:00 +09:00
minjaesong
74e540cb61 future work: typewriter input on PUA 2021-11-04 17:49:02 +09:00
minjaesong
c1ec50e166 caching is back to the hashset as we don't iterate over them 2021-10-29 17:20:30 +09:00
minjaesong
58ce18f981 hopefully normalising malformed hangul IPF coding 2021-10-22 17:50:52 +09:00
minjaesong
f1fa98880f print with codepoints will try to normalise them 2021-10-22 17:24:29 +09:00
minjaesong
0c754d09ed making CodepointSequence more useful 2021-10-21 19:21:07 +09:00
minjaesong
b40e4fcc26 wtf with the premultiplying i didn't even told it to do so 2021-10-21 12:19:08 +09:00
minjaesong
a7bb33c3a0 more glyph updates 2021-10-14 20:41:52 +09:00
minjaesong
c3930b2e08 kerning set for slashes; re-doing lowercase k 2021-10-14 15:07:00 +09:00
minjaesong
979180860e flippin' options for TextureRegionPack 2021-09-21 00:26:44 +09:00
minjaesong
61fb70975c shadow opacity configuration 2021-09-18 13:42:37 +09:00
minjaesong
1af9f7c915 adjustments on hangul letters, colon, semicolon, comma and period; importing work-files from the main game to this repo 2021-09-17 10:06:30 +09:00
minjaesong
810411de7e improved caching performance; lwjgl3 for fonttest 2021-09-16 14:51:23 +09:00
minjaesong
b9bf9ca10d copyright date update 2021-09-15 23:58:45 +09:00
minjaesong
526c16daa9 more kerning pairs 2021-09-15 23:10:28 +09:00
minjaesong
e58104d5b5 fixed an overlook where charset override control codes were not actually strings (because UTF-16) but array of characters 2021-09-15 22:43:50 +09:00
minjaesong
92aeb3c8aa update to kotlin 1.4; fixed a bug where trying to colour a text using gdxbatch's colour would cause undesirable results 2021-09-13 01:21:43 +09:00
minjaesong
3841611780 1.9 release 2021-03-15 19:56:53 +09:00
minjaesong
06bc8c9e2d forgot to update demo.png 2020-10-16 15:20:07 +09:00
minjaesong
21415c6f8d add: kerning sets for b and d 2020-10-06 16:31:24 +09:00
minjaesong
22c2a7aa52 fix: issue #12 2020-10-06 15:14:57 +09:00
minjaesong
0eb181f315 time to get off so i'll just commit this 2020-09-29 18:04:58 +09:00
minjaesong
45b431f953 fix: partial fix for issue #12 2020-09-29 14:07:35 +09:00
minjaesong
bbee554fec add: error msg for illegal linotype dimension 2020-09-29 11:36:59 +09:00
minjaesong
c4c67f489e fixing idiotic priority cache impl where they won't get younger 2020-05-04 00:09:05 +09:00
minjaesong
4d867d6523 replacing personalised test text 2020-05-03 23:42:06 +09:00
minjaesong
6620c11178 hangul: minor texture changes 2020-05-03 23:28:59 +09:00
minjaesong
db06cab07c cleaning up unnecessary functions 2020-05-03 22:26:45 +09:00
minjaesong
90b11cdd97 hangul: more microkerning shit 2020-05-03 20:34:12 +09:00
minjaesong
7bb92d1b4e hangul: some of the microkerning implemented in dirty way 2020-05-03 18:13:17 +09:00
minjaesong
b5dd744bd5 hangul: WEO to use wider initials just like WI and YI 2020-05-02 00:03:50 +09:00
minjaesong
34903b10d4 more hangul improvements 2020-05-01 17:12:13 +09:00
minjaesong
0c5b7c8b70 more letters for kerning charsets 2020-04-23 02:50:03 +09:00
minjaesong
cdffca98ef even more kerning pairs i can think of WIP 2020-04-23 01:16:18 +09:00
minjaesong
ce30d1d5fd major modification on hangul font 2020-04-23 01:02:57 +09:00
minjaesong
ab067044f8 more kerning pairs i can think of WIP 2020-04-21 05:17:19 +09:00
minjaesong
3e04b8bbe6 more kerning pairs WIP 2020-04-19 15:03:37 +09:00
minjaesong
4556a9e244 very crude kerning impl for Ys and Ts and AV-VA pairs 2020-04-14 23:56:08 +09:00
minjaesong
e5d04de250 character sets to use ints rather than chars 2020-04-14 23:45:35 +09:00
minjaesong
b7df181729 minor improvement on rotund r 2020-04-14 07:25:11 +09:00
minjaesong
2fd3fcfd46 support for LatinExt-D 2020-04-14 06:41:11 +09:00
146 changed files with 4073 additions and 2790 deletions

10
.gitattributes vendored Normal file
View File

@@ -0,0 +1,10 @@
*.psd filter=lfs diff=lfs merge=lfs -text
*.ogg filter=lfs diff=lfs merge=lfs -text
*.tga filter=lfs diff=lfs merge=lfs -text
*.gz filter=lfs diff=lfs merge=lfs -text
*.opus filter=lfs diff=lfs merge=lfs -text
*.pdf filter=lfs diff=lfs merge=lfs -text
*.zip filter=lfs diff=lfs merge=lfs -text
*.kra filter=lfs diff=lfs merge=lfs -text
*.png filter=lfs diff=lfs merge=lfs -text
*.wav filter=lfs diff=lfs merge=lfs -text

6
.gitignore vendored Normal file → Executable file
View File

@@ -7,3 +7,9 @@ Terrarum-sans-bitmap*.zip
TerrarumSansBitmap*.jar TerrarumSansBitmap*.jar
Font*.jar Font*.jar
tmp_* tmp_*
*~
.tmp*
tmp_*
*.bak
*-autosave.kra
.directory

0
.idea/.name generated Normal file → Executable file
View File

76
.idea/artifacts/FontDemoGDX.xml generated Normal file → Executable file
View File

@@ -6,6 +6,82 @@
<element id="directory" name="META-INF"> <element id="directory" name="META-INF">
<element id="file-copy" path="$PROJECT_DIR$/FontTestGDX/META-INF/MANIFEST.MF" /> <element id="file-copy" path="$PROJECT_DIR$/FontTestGDX/META-INF/MANIFEST.MF" />
</element> </element>
<element id="artifact" artifact-name="TerrarumSansBitmap" />
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar" path-in-jar="/" />
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar" path-in-jar="/" />
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-test.jar" path-in-jar="/" />
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7.jar" path-in-jar="/" />
<element id="extracted-dir" path="$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jnlp.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-1.10.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jinput-2.0.5.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jutils-1.0.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jorbis-0.0.17.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jlayer-1.0.1-gdx.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/TerrarumSansBitmap.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-1.10.0-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-1.10.0-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.10.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jinput-2.0.5-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jinput-2.0.5-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jutils-1.0.0-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jutils-1.0.0-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jorbis-0.0.17-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jorbis-0.0.17-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jlayer-1.0.1-gdx-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jlayer-1.0.1-gdx-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-backend-lwjgl3-1.10.0.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-natives-linux.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-natives-macos.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-natives-windows.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-natives-linux.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-natives-macos.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-natives-linux-arm32.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-natives-linux-arm64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-3.2.3-natives-windows-x86.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-natives-windows.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-natives-linux.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-natives-macos.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-natives-linux.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-natives-macos.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-backend-lwjgl3-1.10.0-javadoc.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-backend-lwjgl3-1.10.0-sources.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jinput-platform-2.0.5-natives-osx.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-natives-linux.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-natives-macos.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-natives-windows.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-natives-windows.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/gdx-platform-1.10.0-natives-desktop.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jinput-platform-2.0.5-natives-linux.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-natives-linux-arm32.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-natives-linux-arm64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-glfw-3.2.3-natives-windows-x86.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-natives-windows.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/jinput-platform-2.0.5-natives-windows.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-natives-linux-arm32.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-natives-linux-arm64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-openal-3.2.3-natives-windows-x86.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-natives-linux-arm32.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-natives-linux-arm64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-opengl-3.2.3-natives-windows-x86.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-natives-linux-arm32.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-natives-linux-arm64.jar" path-in-jar="/" />
<element id="extracted-dir" path="$PROJECT_DIR$/lib/lwjgl-jemalloc-3.2.3-natives-windows-x86.jar" path-in-jar="/" />
</root> </root>
</artifact> </artifact>
</component> </component>

2
.idea/artifacts/TerrarumSansBitmap.xml generated Normal file → Executable file
View File

@@ -1,6 +1,6 @@
<component name="ArtifactManager"> <component name="ArtifactManager">
<artifact type="jar" name="TerrarumSansBitmap"> <artifact type="jar" name="TerrarumSansBitmap">
<output-path>$PROJECT_DIR$/FontTestGDX/lib</output-path> <output-path>$PROJECT_DIR$/lib</output-path>
<root id="archive" name="TerrarumSansBitmap.jar"> <root id="archive" name="TerrarumSansBitmap.jar">
<element id="module-output" name="BuildJAR_TerrarumSansBitmap" /> <element id="module-output" name="BuildJAR_TerrarumSansBitmap" />
<element id="directory" name="META-INF"> <element id="directory" name="META-INF">

0
.idea/codeStyles/Project.xml generated Normal file → Executable file
View File

0
.idea/codeStyles/codeStyleConfig.xml generated Normal file → Executable file
View File

7
.idea/kotlinc.xml generated Normal file → Executable file
View File

@@ -1,10 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="Kotlin2JvmCompilerArguments">
<option name="jvmTarget" value="1.8" />
</component>
<component name="KotlinCommonCompilerArguments"> <component name="KotlinCommonCompilerArguments">
<option name="apiVersion" value="1.2" /> <option name="apiVersion" value="1.4" />
<option name="languageVersion" value="1.2" /> <option name="languageVersion" value="1.4" />
</component> </component>
</project> </project>

View File

@@ -1,12 +1,19 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="KotlinJavaRuntime"> <library name="KotlinJavaRuntime">
<CLASSES> <CLASSES>
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-runtime.jar!/" /> <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" /> <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8.jar!/" />
</CLASSES> </CLASSES>
<JAVADOC /> <JAVADOC />
<SOURCES> <SOURCES>
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-runtime-sources.jar!/" /> <root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-test-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk7-sources.jar!/" />
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-stdlib-jdk8-sources.jar!/" />
</SOURCES> </SOURCES>
</library> </library>
</component> </component>

View File

@@ -1,10 +0,0 @@
<component name="libraryTable">
<library name="TesterLib">
<CLASSES>
<root url="file://$PROJECT_DIR$/FontTestGDX/lib" />
</CLASSES>
<JAVADOC />
<SOURCES />
<jarDirectory url="file://$PROJECT_DIR$/FontTestGDX/lib" recursive="false" />
</library>
</component>

View File

@@ -1,5 +1,5 @@
<component name="libraryTable"> <component name="libraryTable">
<library name="GdxLib"> <library name="lib">
<CLASSES> <CLASSES>
<root url="file://$PROJECT_DIR$/lib" /> <root url="file://$PROJECT_DIR$/lib" />
</CLASSES> </CLASSES>
@@ -9,7 +9,6 @@
</NATIVE> </NATIVE>
<SOURCES> <SOURCES>
<root url="file://$PROJECT_DIR$/lib" /> <root url="file://$PROJECT_DIR$/lib" />
<root url="jar://$PROJECT_DIR$/lib/gdx.jar!/" />
</SOURCES> </SOURCES>
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" /> <jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" />
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" type="SOURCES" /> <jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" type="SOURCES" />

0
.idea/markdown-navigator.xml generated Normal file → Executable file
View File

0
.idea/markdown-navigator/profiles_settings.xml generated Normal file → Executable file
View File

2
.idea/misc.xml generated Normal file → Executable file
View File

@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<project version="4"> <project version="4">
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK"> <component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8.0_242" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" /> <output url="file://$PROJECT_DIR$/out" />
</component> </component>
</project> </project>

0
.idea/modules.xml generated Normal file → Executable file
View File

0
.idea/vcs.xml generated Normal file → Executable file
View File

1033
.idea/workspace.xml generated Normal file → Executable file

File diff suppressed because it is too large Load Diff

2
BuildJAR_TerrarumSansBitmap.iml Normal file → Executable file
View File

@@ -8,6 +8,6 @@
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" /> <orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="library" name="GdxLib" level="project" /> <orderEntry type="library" name="lib" level="project" />
</component> </component>
</module> </module>

95
CONTRIBUTING.md Normal file → Executable file
View File

@@ -7,7 +7,7 @@ Font Spritesheets are stored in ```assets/graphics/fonts``` directory. Image for
#### Before getting started, you did read our design goals, right? Good. Now you may continue your awesome work. #### Before getting started, you did read our design goals, right? Good. Now you may continue your awesome work.
### Ascenders, descenders, width informations (aka Glyph Tags) ## Ascenders, descenders, width informations (aka Glyph Tags)
![Alas, use more modern browser or get better internet connexion!](glyph_height_pos_annotation.png) ![Alas, use more modern browser or get better internet connexion!](glyph_height_pos_annotation.png)
@@ -26,11 +26,11 @@ Each cell is 16 px wide, and any glyph you draw **must be contained within lefts
### Font Metrics ## Font Metrics for variable-width font sheets
Although the font is basically a Spritesheet, some of the sheet expects variable widths to be supported. Any sheets with ```_variable``` means it expects variable widths. Anything else expects fixed width (regular Spritesheet behaviour). ```cjkpunct``` has width of 10, ```kana``` and ```hangul_johab``` has width of 12, ```wenquanyi``` has width of 16. Although the font is basically a Spritesheet, some of the sheet expects variable widths to be supported. Any sheets with ```_variable``` means it expects variable widths. Anything else expects fixed width (regular Spritesheet behaviour). ```cjkpunct``` has width of 10, ```kana``` and ```hangul_johab``` has width of 12, ```wenquanyi``` has width of 16.
### Parsing glyph widths for variable font sheets ### Parsing Glyph Tags
![Sample of Font Spritesheet with annotation](width_bit_encoding_annotated.png) ![Sample of Font Spritesheet with annotation](width_bit_encoding_annotated.png)
@@ -38,21 +38,84 @@ Width is encoded in binary bits, on pixels. On the font spritesheet, every glyph
### Glyph Tags ### Glyph Tags
Green-tinted area (should be 10 px tall) contains the tags. Tags are defined as following: Rightmost vertical column (should be 20 px tall) contains the tags. Tags are defined as following:
``` ```
(LSB) 0 == Use Compiler Directive (Undefined right now, keep it as 0) (LSB) W -,
1 -, 1 = Align to this X pos of prev char, W |
1 | 2 = only valid if write-on-top is 1 W |= Width of the character
1 | 4 = and is centre-aligned and non-zero W |
1 -' 8 = (if this is zero, floorOf(width/2) will be used instead) W -'
0 -, 0 Align 1 Align 0 Align 1 Align before m --Is this character lowheight?
1 -' 0 left 0 right 1 centre 1 the glyph K -,
1 == write-on-top, usually it's diatritics but not always (e.g. devanagari vowel sign O) K |= Tags used by the "Keming Machine"
1 -, 0 Stack 1 Stack 0 Before 1 Up & K -'
(MSB) 0 -' 0 up 0 down 1 &After 1 Down (e.g. U+0C48) Q ---Compiler Directive (see below)
n --,
Y -, `-Nudging Bits (see below)
X |
Y |= Diacritics Anchor Points (see below)
X -'
A -,_ 0 Align 1 Align 0 Align 1 Align before
A -' 0 left 0 right 1 centre 1 the glyph
D --Diacritics Type Bit (see below; not all diacritics are marked as one on the spritesheet)
S -,_ 0 Stack 1 Stack 0 Before 1 Up &
(MSB) S -' 0 up 0 down 1 &After 1 Down (e.g. U+0C48)
``` ```
#### Nudging Bits Encoding
<MSB,Red> SXXXXXXX SYYYYYYY 00000000 <LSB,Blue>
Each X and Y numbers are Signed 8-Bit Integer.
X-positive: nudges towards left
Y-positive: nudges towards up
#### Diacritics Anchor Point Encoding
4 Pixels are further divided as follows:
| LSB | | | | |
| ------------ | ------------ | ------------ | ------------ | ------------ |
| Y | Anchor point Y for: | undefined | undefined | undefined |
| X | Anchor point X for: | undefined | undefined | undefined |
| Y | Anchor point Y for: | (unused) | (unused) | (unused) |
| X | Anchor point X for: | Type-0 | Type-1 | Type-2 |
| MSB | | | | |
<MSB,Red> 1Y1Y1Y1Y 1Y2Y2Y2Y 1Y3Y3Y3Y <LSB,Blue>
<MSB,Red> 1X1X1X1X 1X2X2X2X 1X3X3X3X <LSB,Blue>
where Red is first, Green is second, Blue is the third diacritics.
MSB for each word must be set so that the pixel would appear brighter on the image editor.
(the font program will only read low 7 bits for each RGB channel)
#### Diacritics Type Bit Encoding
<MSB,Red> FFFFFFFF FFFFFFFF FFFFFFFF <LSB,Blue> (For Type-0)
<MSB,Red> TTTT0000 00000000 00000000 <LSB,Blue> (For Type-1 to Type-15)
Certain types of diacritics have predefined meanings:
* Type-0: Above
* Type-1: Below (when it should be separated from being above)
* Type-2: Overlaid (will shift down 2 pixels for lowheight glyphs instead of the default of 4 pixels)
#### Compiler Directives
<MSB,Red> [Opcode] [arg1] [arg2] <LSB,Blue>
Currently supported opcodes:
*00000000: No-operation; does not use the Compiler Directive system.
*10000xxx: Replace a character with xxx subchars (yes, number 0 can be used).
Replacement characters are encoded vertically from X-zero, bit by bit
(colour of the pixel doesn't matter) with LSB sitting on Y-zero.
#### Stack Up/Down #### Stack Up/Down
When the tag is stack-up, it'll be drawn 4 px lower if the underlying When the tag is stack-up, it'll be drawn 4 px lower if the underlying
@@ -89,13 +152,13 @@ Also note that the font compiler will not "stack" these diacritics.
(fun fact: it was drawn on Rhodia memopad with Lamy 2000, then photographed and edited on my iPhone. Letter used is a Cherokee WE Ꮺ) (fun fact: it was drawn on Rhodia memopad with Lamy 2000, then photographed and edited on my iPhone. Letter used is a Cherokee WE Ꮺ)
### Technical Limitations ## Technical Limitations
- Each spritesheet is 4096x4096 maximum, which is a size of 4K Texture. However it is recommended to be smaller or equal to 1024x1024. - Each spritesheet is 4096x4096 maximum, which is a size of 4K Texture. However it is recommended to be smaller or equal to 1024x1024.
- Glyphs exceeding 15px of width needs to be broken down with 2 or more characters. Wider sheets WILL NOT BE IMPLEMENTED, can't waste much pixels just for few superwide glyphs. - Glyphs exceeding 15px of width needs to be broken down with 2 or more characters. Wider sheets WILL NOT BE IMPLEMENTED, can't waste much pixels just for few superwide glyphs.
- Due to how the compiler is coded, actual glyph must have alpha value of 255, the tags must have alpha values LESS THAN 255 (and obviously greater than zero). RGB plane of the TGA image doesn't do anything, keep it as #FFFFFF white. - Due to how the compiler is coded, actual glyph must have alpha value of 255, the tags must have alpha values LESS THAN 255 (and obviously greater than zero). RGB plane of the TGA image doesn't do anything, keep it as #FFFFFF white.
### Implementing the Korean writing system ## Implementation of the Korean writing system
On this font, Hangul letters are printed by assemblying two or three letter pieces. There are 10 sets of Hangul letter pieces on the font. Top 6 are initials, middle 2 are medials, and bottom 2 are finals. On the rightmost side, there's eight assembled glyphs to help you with (assuming you have basic knowledge on the writing system). Top 6 tells you how to use 6 initials, and bottom 2 tells you how to use 2 finals. On this font, Hangul letters are printed by assemblying two or three letter pieces. There are 10 sets of Hangul letter pieces on the font. Top 6 are initials, middle 2 are medials, and bottom 2 are finals. On the rightmost side, there's eight assembled glyphs to help you with (assuming you have basic knowledge on the writing system). Top 6 tells you how to use 6 initials, and bottom 2 tells you how to use 2 finals.

0
CONTRIBUTORS.txt Normal file → Executable file
View File

Binary file not shown.

4
FontTestGDX/FontTestGDX.iml Normal file → Executable file
View File

@@ -7,8 +7,8 @@
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" /> <orderEntry type="sourceFolder" forTests="false" />
<orderEntry type="module" module-name="BuildJAR_TerrarumSansBitmap" />
<orderEntry type="library" name="KotlinJavaRuntime" level="project" /> <orderEntry type="library" name="KotlinJavaRuntime" level="project" />
<orderEntry type="library" name="GdxLib" level="project" /> <orderEntry type="library" name="lib" level="project" />
<orderEntry type="library" name="TesterLib" level="project" />
</component> </component>
</module> </module>

3
FontTestGDX/META-INF/MANIFEST.MF Normal file → Executable file
View File

@@ -1,6 +1,3 @@
Manifest-Version: 1.0 Manifest-Version: 1.0
Class-Path: lib/gdx.jar lib/gdx-backend-lwjgl.jar lib/gdx-backend-lwjg
l-natives.jar lib/gdx-natives.jar lib/kotlin-stdlib.jar TerrarumSansB
itmap.jar
Main-Class: FontTestGDXKt Main-Class: FontTestGDXKt

171
FontTestGDX/src/FontTestGDX.kt Normal file → Executable file
View File

@@ -1,18 +1,23 @@
import com.badlogic.gdx.* import com.badlogic.gdx.*
import com.badlogic.gdx.backends.lwjgl.LwjglApplication import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.FrameBuffer import com.badlogic.gdx.graphics.glutils.FrameBuffer
import com.badlogic.gdx.utils.ScreenUtils import com.badlogic.gdx.utils.ScreenUtils
import net.torvald.terrarumsansbitmap.gdx.GameFontBase import com.badlogic.gdx.utils.StreamUtils
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap
import java.io.File
import java.io.IOException
import java.io.OutputStream
/** /**
* Created by minjaesong on 2018-07-26. * Created by minjaesong on 2018-07-26.
*/ */
class FontTestGDX : Game() { class FontTestGDX : Game() {
lateinit var font: GameFontBase lateinit var font: TerrarumSansBitmap
lateinit var inputText: List<String> lateinit var inputText: List<String>
@@ -27,8 +32,10 @@ class FontTestGDX : Game() {
private val demotextName = if (testing) "testtext.txt" else "demotext.txt" private val demotextName = if (testing) "testtext.txt" else "demotext.txt"
private val outimageName = if (testing) "testing.PNG" else "demo.PNG" private val outimageName = if (testing) "testing.PNG" else "demo.PNG"
private lateinit var faketex: Texture
override fun create() { override fun create() {
font = GameFontBase("./assets", flipY = false, errorOnUnknownChar = false) // must test for two flipY cases font = TerrarumSansBitmap("./assets", debug = true, flipY = false, errorOnUnknownChar = false, shadowAlpha = 0.796f) // must test for two flipY cases
val inTextFile = Gdx.files.internal("./$demotextName") val inTextFile = Gdx.files.internal("./$demotextName")
val reader = inTextFile.reader("UTF-8") val reader = inTextFile.reader("UTF-8")
@@ -38,11 +45,11 @@ class FontTestGDX : Game() {
batch = SpriteBatch() batch = SpriteBatch()
// create faketex
val fakepix = Pixmap(1,1,Pixmap.Format.RGBA8888)
println(font.charsetOverrideDefault) fakepix.drawPixel(0,0,-1)
println(font.charsetOverrideBulgarian) faketex = Texture(fakepix)
println(font.charsetOverrideSerbian) fakepix.dispose()
frameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, TEXW, TEXH, true) frameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, TEXW, TEXH, true)
@@ -67,21 +74,29 @@ class FontTestGDX : Game() {
var tex: Texture? = null var tex: Texture? = null
var screenshotExported = false var screenshotExported = false
private val backcol = Color(.141f, .141f, .141f, 1f)
override fun render() { override fun render() {
if (tex == null) { if (tex == null) {
frameBuffer.begin() frameBuffer.begin()
Gdx.gl.glClearColor(.141f, .141f, .141f, 1f) Gdx.gl.glClearColor(0f,0f,0f,0f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D) Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND) Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA) Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE)
// Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_COLOR, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_SRC_ALPHA, GL20.GL_ONE)
// Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
batch.projectionMatrix = camera.combined batch.projectionMatrix = camera.combined
batch.begin() batch.begin()
batch.color = Color(0xeeeeeeff.toInt()) batch.color = backcol
batch.draw(faketex, 0f, 0f, TEXW.toFloat(), TEXH.toFloat())
batch.color = Color.WHITE
inputText.forEachIndexed { index, s -> inputText.forEachIndexed { index, s ->
font.draw(batch, s, 10f, TEXH - 30f - index * font.lineHeight) font.draw(batch, s, 10f, TEXH - 30f - index * font.lineHeight)
} }
@@ -94,6 +109,7 @@ class FontTestGDX : Game() {
val pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, frameBuffer.width, frameBuffer.height) val pixmap = ScreenUtils.getFrameBufferPixmap(0, 0, frameBuffer.width, frameBuffer.height)
PixmapIO.writePNG(Gdx.files.local(outimageName), pixmap) PixmapIO.writePNG(Gdx.files.local(outimageName), pixmap)
// writeTGA(Gdx.files.local(outimageName), pixmap, false)
pixmap.dispose() pixmap.dispose()
screenshotExported = true screenshotExported = true
@@ -107,9 +123,17 @@ class FontTestGDX : Game() {
tex = frameBuffer.colorBufferTexture tex = frameBuffer.colorBufferTexture
} }
Gdx.gl.glClearColor(.141f, .141f, .141f, 1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE)
batch.begin() batch.begin()
batch.color = Color.WHITE batch.color = Color.WHITE
batch.draw(tex, 0f, (TEXH.toFloat()/appConfig.height)*TEXH - scrollOffsetY, TEXW.toFloat(), -(TEXH.toFloat() / appConfig.height) * TEXH.toFloat()) batch.draw(tex, 0f, (TEXH.toFloat()/HEIGHT)*TEXH - scrollOffsetY, TEXW.toFloat(), -(TEXH.toFloat() / HEIGHT) * TEXH.toFloat())
batch.end() batch.end()
@@ -126,22 +150,24 @@ class FontTestGDX : Game() {
override fun dispose() { override fun dispose() {
font.dispose() font.dispose()
faketex.dispose()
File("./tmp_wenquanyi.tga").delete()
} }
fun scrollAdd(x: Int = 1) { fun scrollAdd(x: Int = 1) {
scrollOffsetY -= (TEXH.toFloat() / appConfig.height) * 20f * x scrollOffsetY -= (TEXH.toFloat() / HEIGHT) * 20f * x
} }
fun scrollSub(x: Int = 1) { fun scrollSub(x: Int = 1) {
scrollOffsetY += (TEXH.toFloat() / appConfig.height) * 20f * x scrollOffsetY += (TEXH.toFloat() / HEIGHT) * 20f * x
} }
class Navigator(val main: FontTestGDX) : InputAdapter() { class Navigator(val main: FontTestGDX) : InputAdapter() {
override fun scrolled(amount: Int): Boolean { override fun scrolled(amountX: Float, amountY: Float): Boolean {
if (amount >= 0) if (amountY >= 0)
main.scrollSub(amount) main.scrollSub(amountY.toInt())
else else
main.scrollAdd(-amount) main.scrollAdd(-amountY.toInt())
return true return true
} }
@@ -155,19 +181,106 @@ class FontTestGDX : Game() {
return true return true
} }
} }
@Throws(IOException::class)
private fun writeTGA(file: FileHandle, pixmap: Pixmap, flipY: Boolean) {
val output = file.write(false)
try {
_writeTGA(output, pixmap, true, flipY)
} finally {
StreamUtils.closeQuietly(output)
}
}
@Throws(IOException::class)
private fun _writeTGA(out: OutputStream, pixmap: Pixmap, verbatim: Boolean, flipY: Boolean) {
val width: ByteArray = toShortLittle(pixmap.width)
val height: ByteArray = toShortLittle(pixmap.height)
val zero: ByteArray = toShortLittle(0)
out.write(0) // ID field: empty
out.write(0) // no colour map, but should be ignored anyway as it being unmapped RGB
out.write(2) // 2 means unmapped RGB
out.write(byteArrayOf(0, 0, 0, 0, 0)) // color map spec: empty
out.write(zero) // x origin: 0
out.write(zero) // y origin: 0
out.write(width) // width
out.write(height) // height
out.write(32) // image pixel size: we're writing 32-bit image (8bpp BGRA)
out.write(8) // image descriptor: dunno, Photoshop writes 8 in there
// write actual image data
// since we're following Photoshop's conventional header, we also follows Photoshop's
// TGA saving scheme, that is:
// 1. BGRA order
// 2. Y-Flipped but not X-Flipped
if (!flipY) {
for (y in pixmap.height - 1 downTo 0) {
for (x in 0 until pixmap.width) {
writeTga(x, y, verbatim, pixmap, out)
}
}
} else {
for (y in 0 until pixmap.height) {
for (x in 0 until pixmap.width) {
writeTga(x, y, verbatim, pixmap, out)
}
}
}
// write footer
// 00 00 00 00 00 00 00 00 TRUEVISION-XFILE 2E 00
out.write(byteArrayOf(0, 0, 0, 0, 0, 0, 0, 0))
if (verbatim) out.write("TRUEVISION-XFILE".toByteArray()) else out.write("TerrarumHappyTGA".toByteArray())
out.write(byteArrayOf(0x2E, 0))
out.flush()
out.close()
}
private val zeroalpha = byteArrayOf(0, 0, 0, 0)
@Throws(IOException::class)
private fun writeTga(x: Int, y: Int, verbatim: Boolean, pixmap: Pixmap, out: OutputStream) {
val color = pixmap.getPixel(x, y)
// if alpha == 0, write special value instead
if (verbatim && color and 0xFF == 0) {
out.write(zeroalpha)
} else {
out.write(RGBAtoBGRA(color))
}
}
private fun toShortLittle(i: Int): ByteArray {
return byteArrayOf(
(i and 0xFF).toByte(),
(i ushr 8 and 0xFF).toByte()
)
}
private fun RGBAtoBGRA(rgba: Int): ByteArray {
return byteArrayOf(
(rgba ushr 8 and 0xFF).toByte(),
(rgba ushr 16 and 0xFF).toByte(),
(rgba ushr 24 and 0xFF).toByte(),
(rgba and 0xFF).toByte()
)
}
} }
lateinit var appConfig: LwjglApplicationConfiguration lateinit var appConfig: Lwjgl3ApplicationConfiguration
const val TEXW = 874 const val TEXW = 874
const val TEXH = 2400 const val TEXH = 128 * 20
const val WIDTH = TEXW
const val HEIGHT = 768
fun main(args: Array<String>) { fun main(args: Array<String>) {
appConfig = LwjglApplicationConfiguration() appConfig = Lwjgl3ApplicationConfiguration()
appConfig.vSyncEnabled = false appConfig.useVsync(false)
appConfig.resizable = false//true; appConfig.setResizable(false)
appConfig.width = TEXW appConfig.setWindowedMode(WIDTH, HEIGHT)
appConfig.height = 768 appConfig.setTitle("Terrarum Sans Bitmap Test")
appConfig.title = "Terrarum Sans Bitmap Test (GDX)"
LwjglApplication(FontTestGDX(), appConfig) Lwjgl3Application(FontTestGDX(), appConfig)
} }

View File

@@ -0,0 +1,247 @@
import com.badlogic.gdx.Game
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.InputAdapter
import com.badlogic.gdx.audio.AudioDevice
import com.badlogic.gdx.audio.Sound
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3Application
import com.badlogic.gdx.backends.lwjgl3.Lwjgl3ApplicationConfiguration
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.GL20
import com.badlogic.gdx.graphics.OrthographicCamera
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.terrarum.gamecontroller.InputStrober
import net.torvald.terrarumsansbitmap.gdx.CodepointSequence
import net.torvald.terrarumtypewriterbitmap.gdx.TerrarumTypewriterBitmap
import java.io.StringReader
import kotlin.math.roundToInt
/**
* Created by minjaesong on 2021-11-05.
*/
class TypewriterGDX(val width: Int, val height: Int, val cols: Int) : Game() {
lateinit var font: TerrarumTypewriterBitmap
lateinit var batch: SpriteBatch
// lateinit var frameBuffer: FrameBuffer
lateinit var camera: OrthographicCamera
lateinit var inputStrober: InputStrober
lateinit var sndMovingkey: Sound
lateinit var sndDeadkey: Sound
lateinit var sndShiftin: Sound
lateinit var sndShiftout: Sound
lateinit var sndSpace: Sound
lateinit var sndCRs: Array<Sound>
lateinit var sndLF: Sound
override fun create() {
font = TerrarumTypewriterBitmap(
"./assets/typewriter",
StringReader(
"""ko_kr_3set-390_typewriter,typewriter_ko_3set-390.tga,16
|en_intl_qwerty_typewriter,typewriter_intl_qwerty.tga,0
""".trimMargin()
),
true, false, 256, true
)
batch = SpriteBatch()
// frameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, TEXW, TEXH, true)
camera = OrthographicCamera(width.toFloat(), height.toFloat())
camera.translate(width.div(2f), 0f)
camera.setToOrtho(true, width.toFloat(), height.toFloat())
camera.update()
inputStrober = InputStrober(this)
try {
sndMovingkey = Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/movingkey.wav"))
sndDeadkey = Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/deadkey.wav"))
sndShiftin = Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/shiftin.wav"))
sndShiftout = Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/shiftout.wav"))
sndSpace = Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/space.wav"))
sndCRs = Array(6) {
Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/cr$it.wav"))
}
sndLF = Gdx.audio.newSound(Gdx.files.internal("assets/typewriter/audio/crlf.wav"))
}
catch (e: GdxRuntimeException) {
e.printStackTrace()
}
}
private val intro = listOf(
39,50,29, // kva (HANG_GONG)
42,31, // nc (HANG_SE)
74,48,51, // ;tw (HANG_BEOL)
62, // space
0x561F71, // shiftin
184,164,171,170, // >HON (ASC_3-90)
0x561F70, // shiftout
62, // space
74,48, // ;t (HANG_BEO)
43,12, // o5 (HANG_CYU)
38,48,51, // jtw (HANG_EOL)
0x561F71, // shiftin
164, // H (ASC_-)
0x561F70, // shiftout
75,34, // 'f (HANG_TA)
40,34, // lf (HANG_JA)
39,32, // kd (HANG_GI)
Input.Keys.ENTER,Input.Keys.ENTER
)
private val textbuf: ArrayList<CodepointSequence> = arrayListOf(
CodepointSequence()
)
var keylayoutbase = 0xF9000
private val printableKeys = ((Input.Keys.NUM_0..Input.Keys.NUM_9) + (Input.Keys.A..Input.Keys.PERIOD) + 62 + (Input.Keys.BACKSPACE..Input.Keys.SLASH)).toHashSet()
var initDone = false
var initTimer = 0f
var initTypingCursor = 0
var keystrokeDelay = 0.08f
fun acceptKey(keycode: Int, force: Boolean = false) {
if (initDone || force) {
// println("[TypewriterGDX] Accepting key: $keycode")
val lowkeycode = keycode and 127
if (keycode == Input.Keys.ENTER) {
val tbufsize = textbuf.last().size.div(cols.toFloat()).times(6f).coerceIn(0f, 6f).roundToInt() // 0..6
textbuf.add(CodepointSequence())
if (tbufsize == 0) sndLF.play()
else sndCRs[tbufsize - 1].play()
} else if (printableKeys.contains(lowkeycode)) {
val cp = keycode + keylayoutbase
textbuf.last().add(cp)
// println("[TypewriterGDX] width: ${font.glyphProps[cp]}")
// play audio
val isDeadkey = font.glyphProps[cp]?.width == 0
if (isDeadkey) {
sndDeadkey.play()
} else if (lowkeycode == Input.Keys.SPACE || lowkeycode == Input.Keys.BACKSPACE) {
sndSpace.play()
} else {
sndMovingkey.play()
}
} else if (lowkeycode == Input.Keys.SHIFT_LEFT || lowkeycode == Input.Keys.SHIFT_RIGHT) {
sndShiftin.play()
}
}
}
/**
* For Shift-out only
*/
fun shiftOut() {
sndShiftout.play()
}
private val textCol = Color(0.1f,0.1f,0.1f,1f)
override fun render() {
Gdx.gl.glClearColor(0.97f,0.96f,0.95f,1f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFuncSeparate(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA, GL20.GL_ONE, GL20.GL_ONE)
batch.projectionMatrix = camera.combined
batch.begin()
batch.color = textCol
try {
textbuf.forEachIndexed { index, s ->
font.draw(batch, s, 40f, 40f + 20 * index)
}
}
catch (e: ConcurrentModificationException) {}
batch.end()
if (!initDone) {
while (initTimer > keystrokeDelay) {
val keyToType = intro[initTypingCursor]
if (keyToType < 256) {
acceptKey(keyToType, true)
}
else if (keyToType == 0x561F71) {
acceptKey(Input.Keys.SHIFT_LEFT + 128, true)
}
else if (keyToType == 0x561F70) {
shiftOut()
}
initTypingCursor += 1
initTimer -= keystrokeDelay
if (keyToType == Input.Keys.ENTER)
initTimer -= 0.35f
else if (keyToType == 0x561F71)
initTimer -= 0.15f
else if (keyToType == 0x561F70)
initTimer -= 0.1f
else
initTimer -= Math.random().toFloat() * 0.04f
}
initTimer += Gdx.graphics.deltaTime
if (initTypingCursor >= intro.size) {
initDone = true
}
}
}
override fun dispose() {
font.dispose()
batch.dispose()
inputStrober.dispose()
sndMovingkey.dispose()
sndDeadkey.dispose()
sndShiftin.dispose()
sndShiftout.dispose()
sndSpace.dispose()
sndCRs.forEach { it.dispose() }
sndLF.dispose()
}
}
class TypewriterInput(val main: TypewriterGDX) : InputAdapter() {
private var shiftIn = false
override fun keyDown(keycode: Int): Boolean {
// FIXME this shiftIn would not work at all...
shiftIn = (keycode == Input.Keys.SHIFT_LEFT || keycode == Input.Keys.SHIFT_RIGHT)
if (keycode < 128 && keycode != Input.Keys.SHIFT_LEFT && keycode != Input.Keys.SHIFT_RIGHT) {
main.acceptKey(shiftIn.toInt() * 128 + keycode)
}
return true
}
private fun Boolean.toInt() = if (this) 1 else 0
}
fun main(args: Array<String>) {
appConfig = Lwjgl3ApplicationConfiguration()
appConfig.useVsync(false)
appConfig.setResizable(false)
appConfig.setWindowedMode(600, 800)
appConfig.setTitle("Terrarum Typewriter Bitmap Test")
Lwjgl3Application(TypewriterGDX(600, 800, 64), appConfig)
}

View File

@@ -0,0 +1,401 @@
package net.torvald.terrarum.gamecontroller
import TypewriterGDX
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
/**
* Created by minjaesong on 2021-11-06.
*/
class InputStrober(val typewriter: TypewriterGDX) {
companion object {
const val KEY_DOWN = 0
const val KEY_CHANGE = 1
const val N_KEY_ROLLOVER = 8
}
var KEYBOARD_DELAYS = longArrayOf(0L,250000000L,0L,25000000L,0L)
private var stroboTime = 0L
private var stroboStatus = 0
private var repeatCount = 0
private var oldKeys = IntArray(N_KEY_ROLLOVER) { 0 }
/** always Low Layer */
// private var keymap = IME.getLowLayerByName(App.getConfigString("basekeyboardlayout"))
private val thread = Thread { while (!Thread.interrupted()) {
if (Gdx.input != null) withKeyboardEvent()
} }
init {
// println("InputStrobe start")
thread.start()
}
fun dispose() {
thread.interrupt()
}
fun resetKeyboardStrobo() {
stroboStatus = 0
repeatCount = 0
}
// code proudly stolen from tsvm's TVDOS.SYS
private fun withKeyboardEvent() {
val keys = strobeKeys()
var keyChanged = !arrayEq(keys, oldKeys)
val keyDiff = arrayDiff(keys, oldKeys)
// println("Key strobed: ${keys.joinToString()}")
if (stroboStatus % 2 == 0 && (keys[0] != 0 || oldKeys[0] != 0)) {
stroboStatus += 1
stroboTime = System.nanoTime()
repeatCount += 1
val shiftin = keys.contains(Input.Keys.SHIFT_LEFT) || keys.contains(Input.Keys.SHIFT_RIGHT)
val newKeysym0 = keysToStr(keyDiff)
val newKeysym = if (newKeysym0 == null) null
else if (shiftin && newKeysym0.size > 1 && newKeysym0[1]?.isNotBlank() == true) newKeysym0[1]
else newKeysym0[0]
val headKeyCode = (if (keyDiff.size < 1) keys[0] else keyDiff[0]).and(127) or (if (shiftin) 128 else 0)
if (repeatCount == 1) {
if (!keyChanged) {
// println("KEY_DOWN '$keysym' ($headKeyCode) $repeatCount; ${keys.joinToString()}")
// App.inputStrobed(TerrarumKeyboardEvent(KEY_DOWN, keysym, headKeyCode, repeatCount, keys))
typewriter.acceptKey(headKeyCode)
} else if (newKeysym != null) {
// println("KEY_DOWC '$newKeysym' ($headKeyCode) $repeatCount; ${keys.joinToString()}")
// App.inputStrobed(TerrarumKeyboardEvent(KEY_DOWN, newKeysym, headKeyCode, repeatCount, keys))
typewriter.acceptKey(headKeyCode)
}
// println("shiftin=${shiftin} oldkeys=${oldKeys.joinToString()}")
if (!shiftin && (oldKeys.contains(Input.Keys.SHIFT_LEFT) || oldKeys.contains(Input.Keys.SHIFT_RIGHT))) {
typewriter.shiftOut()
}
}
oldKeys = keys // don't put this outside of if-cascade
}
else if (keyChanged || keys[0] == 0) {
stroboStatus = 0
repeatCount = 0
if (keys[0] == 0) keyChanged = false
}
else if (stroboStatus % 2 == 1 && System.nanoTime() - stroboTime < KEYBOARD_DELAYS[stroboStatus]) {
Thread.sleep(1L)
}
else {
stroboStatus += 1
if (stroboStatus >= 4)
stroboStatus = 2
}
}
private fun keysToStr(keys: IntArray): Array<String?>? {
if (keys.isEmpty()) return null
val headkey = keys[0]
return keymap[headkey]
}
private fun strobeKeys(): IntArray {
var keysPushed = 0
val keyEventBuffers = IntArray(N_KEY_ROLLOVER) { 0 }
for (k in 1..254) {
if (Gdx.input.isKeyPressed(k)) {
keyEventBuffers[keysPushed] = k
keysPushed += 1
}
if (keysPushed >= N_KEY_ROLLOVER) break
}
return keyEventBuffers
}
private fun arrayEq(a: IntArray, b: IntArray): Boolean {
for (i in a.indices) {
if (a[i] != b.getOrNull(i)) return false
}
return true
}
private fun arrayDiff(a: IntArray, b: IntArray): IntArray {
return a.filter { !b.contains(it) }.toIntArray()
}
private val keymap = arrayOf(arrayOf<String?>(""),arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>("<HOME>"),
arrayOf<String?>(null),
arrayOf<String?>("<CALL>"),
arrayOf<String?>("<ENDCALL>"),
arrayOf<String?>("0",")"),
arrayOf<String?>("1","!"),
arrayOf<String?>("2","@"),
arrayOf<String?>("3","#"),
arrayOf<String?>("4","$"),
arrayOf<String?>("5","%"),
arrayOf<String?>("6","^"),
arrayOf<String?>("7","&"),
arrayOf<String?>("8","*"),
arrayOf<String?>("9","("),
arrayOf<String?>("*"),
arrayOf<String?>("#"),
arrayOf<String?>("<UP>"),
arrayOf<String?>("<DOWN>"),
arrayOf<String?>("<LEFT>"),
arrayOf<String?>("<RIGHT>"),
arrayOf<String?>("<CENTER>"),
arrayOf<String?>("<VOL_UP>"),
arrayOf<String?>("<VOL_DOWN>"),
arrayOf<String?>("<POWER>"),
arrayOf<String?>("<CAMERA>"),
arrayOf<String?>("<CLEAR>"),
arrayOf<String?>("a","A"),
arrayOf<String?>("b","B"),
arrayOf<String?>("c","C"),
arrayOf<String?>("d","D"),
arrayOf<String?>("e","E"),
arrayOf<String?>("f","F"),
arrayOf<String?>("g","G"),
arrayOf<String?>("h","H"),
arrayOf<String?>("i","I"),
arrayOf<String?>("j","J"),
arrayOf<String?>("k","K"),
arrayOf<String?>("l","L"),
arrayOf<String?>("m","M"),
arrayOf<String?>("n","N"),
arrayOf<String?>("o","O"),
arrayOf<String?>("p","P"),
arrayOf<String?>("q","Q"),
arrayOf<String?>("r","R"),
arrayOf<String?>("s","S"),
arrayOf<String?>("t","T"),
arrayOf<String?>("u","U"),
arrayOf<String?>("v","V"),
arrayOf<String?>("w","W"),
arrayOf<String?>("x","X"),
arrayOf<String?>("y","Y"),
arrayOf<String?>("z","Z"),
arrayOf<String?>(",","<"),
arrayOf<String?>(".",">"),
arrayOf<String?>("<ALT_L>"),
arrayOf<String?>("<ALT_R>"),
arrayOf<String?>("<SHIFT_L>"),
arrayOf<String?>("<SHIFT_R>"),
arrayOf<String?>("<TAB>"),
arrayOf<String?>(" "),
arrayOf<String?>("<SYM>"),
arrayOf<String?>("<EXPLORER>"),
arrayOf<String?>("<ENVELOPE>"),
arrayOf<String?>("\n"),
arrayOf<String?>("\u0008"),
arrayOf<String?>("`","~"),
arrayOf<String?>("-","_"),
arrayOf<String?>("=","+"),
arrayOf<String?>("arrayOf<String?>(","{"),
arrayOf<String?>(")","}"),
arrayOf<String?>("\\","|"),
arrayOf<String?>(";",":"),
arrayOf<String?>("'","\""),
arrayOf<String?>("/","?"),
arrayOf<String?>("<AT>"),
arrayOf<String?>("<NUM_LOCK>"),
arrayOf<String?>("<HEADSETHOOK>"),
arrayOf<String?>("<FOCUS>"),
arrayOf<String?>("+"),
arrayOf<String?>("<MENU>"),
arrayOf<String?>("<NOTIFICATION>"),
arrayOf<String?>("<SEARCH>"),
arrayOf<String?>("<PLAY_PAUSE>"),
arrayOf<String?>("<STOP>"),
arrayOf<String?>("<NEXT>"),
arrayOf<String?>("<PREV>"),
arrayOf<String?>("<REW>"),
arrayOf<String?>("<FFWD>"),
arrayOf<String?>("<MUTE>"),
arrayOf<String?>("<PAGE_UP>"),
arrayOf<String?>("<PAGE_DOWN>"),
arrayOf<String?>("<PICTSYMBOLS>"),
arrayOf<String?>("<SW:>TCH_CHARSET>"),
arrayOf<String?>("<:A:>"),
arrayOf<String?>("<:B:>"),
arrayOf<String?>("<:C:>"),
arrayOf<String?>("<:X:>"),
arrayOf<String?>("<:Y:>"),
arrayOf<String?>("<:Z:>"),
arrayOf<String?>("<:L1:>"),
arrayOf<String?>("<:R1:>"),
arrayOf<String?>("<:L2:>"),
arrayOf<String?>("<:R2:>"),
arrayOf<String?>("<:TL:>"),
arrayOf<String?>("<:TR:>"),
arrayOf<String?>("<:START:>"),
arrayOf<String?>("<:SELECT:>"),
arrayOf<String?>("<:MODE:>"),
arrayOf<String?>("<ESC>"),
arrayOf<String?>("<DEL>"),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>("<CAPS_LOCK>"),
arrayOf<String?>("<SCROLL_LOCK>"),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>("<PRINT_SCREEN_SYS_RQ>"),
arrayOf<String?>("<PAUSE_BREAK>"),
arrayOf<String?>(null),
arrayOf<String?>("<END>"),
arrayOf<String?>("<INSERT>"),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>("<CTRL_L>"),
arrayOf<String?>("<CTRL_R>"),
arrayOf<String?>("<F1>"),
arrayOf<String?>("<F2>"),
arrayOf<String?>("<F3>"),
arrayOf<String?>("<F4>"),
arrayOf<String?>("<F5>"),
arrayOf<String?>("<F6>"),
arrayOf<String?>("<F7>"),
arrayOf<String?>("<F8>"),
arrayOf<String?>("<F9>"),
arrayOf<String?>("<F10>"),
arrayOf<String?>("<F11>"),
arrayOf<String?>("<F12>"),
arrayOf<String?>("<NUM_LOCK>"),
arrayOf<String?>("0"),
arrayOf<String?>("1"),
arrayOf<String?>("2"),
arrayOf<String?>("3"),
arrayOf<String?>("4"),
arrayOf<String?>("5"),
arrayOf<String?>("6"),
arrayOf<String?>("7"),
arrayOf<String?>("8"),
arrayOf<String?>("9"),
arrayOf<String?>("/"),
arrayOf<String?>("*"),
arrayOf<String?>("-"),
arrayOf<String?>("+"),
arrayOf<String?>("."),
arrayOf<String?>("."),
arrayOf<String?>("\n"),
arrayOf<String?>("="),
arrayOf<String?>("("),
arrayOf<String?>(")"),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>(null),
arrayOf<String?>("<:CIRCLE:>")
)
}
data class TerrarumKeyboardEvent(
val type: Int,
val character: String?, // representative key symbol
val headkey: Int, // representative keycode
val repeatCount: Int,
val keycodes: IntArray
)

2
LICENSE.md Normal file → Executable file
View File

@@ -1,4 +1,4 @@
Copyright (c) 2017-2020 see CONTRIBUTORS.txt Copyright (c) 2017-2022 see CONTRIBUTORS.txt
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

0
META-INF/MANIFEST.MF Normal file → Executable file
View File

BIN
PUA_allocation_chart.xlsx Normal file → Executable file

Binary file not shown.

0
README.md Normal file → Executable file
View File

0
alignment_illustration.jpg Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 59 KiB

After

Width:  |  Height:  |  Size: 59 KiB

BIN
assets/ascii_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 131 B

0
assets/cjkpunct.tga Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 50 KiB

After

Width:  |  Height:  |  Size: 50 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 60 KiB

BIN
assets/cyrilic_bulgarian_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/cyrilic_serbian_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/cyrilic_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 380 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/devanagari_bengali_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/diacritical_marks_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

0
assets/futhark.tga Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

BIN
assets/greek_polytonic_xyswap_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/greek_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 MiB

After

Width:  |  Height:  |  Size: 2.6 MiB

BIN
assets/hayeren_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

BIN
assets/internal_variable.tga LFS Normal file

Binary file not shown.

BIN
assets/ipa_ext_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 131 B

0
assets/kana.tga Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 210 KiB

After

Width:  |  Height:  |  Size: 210 KiB

BIN
assets/kartuli_allcaps_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 130 B

BIN
assets/kartuli_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 60 KiB

After

Width:  |  Height:  |  Size: 130 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 160 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 260 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 40 KiB

BIN
assets/latinExtD_variable.tga LFS Normal file

Binary file not shown.

BIN
assets/latinExt_additional_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 320 KiB

After

Width:  |  Height:  |  Size: 131 B

Binary file not shown.

Binary file not shown.

BIN
assets/puae000-e0ff.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 324 KiB

After

Width:  |  Height:  |  Size: 131 B

0
assets/richtext_furigana.tga Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

BIN
assets/thai_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/tsalagi_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 120 KiB

After

Width:  |  Height:  |  Size: 131 B

BIN
assets/typewriter/audio/cr0.wav LFS Normal file

Binary file not shown.

BIN
assets/typewriter/audio/cr1.wav LFS Normal file

Binary file not shown.

BIN
assets/typewriter/audio/cr2.wav LFS Normal file

Binary file not shown.

BIN
assets/typewriter/audio/cr3.wav LFS Normal file

Binary file not shown.

BIN
assets/typewriter/audio/cr4.wav LFS Normal file

Binary file not shown.

BIN
assets/typewriter/audio/cr5.wav LFS Normal file

Binary file not shown.

BIN
assets/typewriter/audio/crlf.wav LFS Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
assets/typewriter/audio/space.wav LFS Normal file

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 320 KiB

BIN
assets/unipunct_variable.tga Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 200 KiB

After

Width:  |  Height:  |  Size: 200 KiB

0
assets/wenquanyi.tga.gz Normal file → Executable file
View File

BIN
demo.PNG

Binary file not shown.

Before

Width:  |  Height:  |  Size: 146 KiB

After

Width:  |  Height:  |  Size: 151 KiB

34
demotext.txt Normal file → Executable file
View File

@@ -3,16 +3,17 @@
There are many bitmap fonts on the internet. You care for the multilingual support, but alas! There are many bitmap fonts on the internet. You care for the multilingual support, but alas!
most of them do not support your language, vector fonts take too much time to load, and even most of them do not support your language, vector fonts take too much time to load, and even
then their legibility suffers because fuck built-in antialias. then their legibility suffers because screw built-in antialias.
You somehow found a multilingual one, and it makes your game look like an old computer, and you say: You somehow found a multilingual one, and it makes your text as if they came straight from an old
computer terminal, and you say:
“Well, better than nothing… no, its ugly.” “Well, better than nothing… no, its ugly.”
You speak japanese and you wish to support it, but then このクソなfont only goot for displaying You speak Japanese and wish to support it, but then このクソなfont only good for displaying
Japanese, its not even multilingual, and their English look uncanny and inconsistent as hell. Japanese, its not even truly multilingual, and their English look uncanny and inconsistent.
Eventually you just mix different fonts together, and the results were always infuriating. Eventually you just mix different fonts together, and the results were always mildly infuriating.
No more suffering. This font has everything you need. No more suffering. This font has everything you need.
@@ -41,7 +42,7 @@ How multilingual? Real multilingual!
􏻬სწრაფი ყავისფერი მელა გადაახტა ზარმაც ძაღლს ᲘᲜᲢᲔᲚ ᲞᲔᲜᲢᲘᲣᲛᲘ ᲛᲘᲙᲠᲝᲞᲠᲝᲪᲔᲡᲝᲠᲘ􀀀 􏻬სწრაფი ყავისფერი მელა გადაახტა ზარმაც ძაღლს ᲘᲜᲢᲔᲚ ᲞᲔᲜᲢᲘᲣᲛᲘ ᲛᲘᲙᲠᲝᲞᲠᲝᲪᲔᲡᲝᲠᲘ􀀀
􏻬ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम अयोध्या के महाराज दशरथ के􀀀 􏻬ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम अयोध्या के महाराज दशरथ के􀀀
􏻬Kæmi ný öxi hér, ykist þjófum nú bæði víl og ádrepa􀀀 􏻬Kæmi ný öxi hér, ykist þjófum nú bæði víl og ádrepa􀀀
􏻬Ċuaiġ bé ṁórṡáċ le dlúṫspád fíorḟinn trí hata mo ḋea-ṗorcáin ḃig􀀀 􏻬Ċuaiġ bé ṁórṡáċ le dlúṫspád fíoḟinn trí hata mo ḋea-ṗocáin ḃig􀀀
􏻬あめつちほしそら やまかはみねたに くもきりむろこけ ひといぬうへすゑ ゆわさるおふせよ えの𛀁をなれゐて􀀀 􏻬あめつちほしそら やまかはみねたに くもきりむろこけ ひといぬうへすゑ ゆわさるおふせよ えの𛀁をなれゐて􀀀
􏻬トリナクコヱス ユメサマセ ミヨアケワタル ヒンカシヲ ソライロハエテ オキツヘニ ホフネムレヰヌ モヤノウチ􀀀 􏻬トリナクコヱス ユメサマセ ミヨアケワタル ヒンカシヲ ソライロハエテ オキツヘニ ホフネムレヰヌ モヤノウチ􀀀
􏻬田居に出で 菜摘むわれをぞ 君召すと 求食り追ひゆく 山城の 打酔へる子ら 藻葉干せよ え舟繋けぬ􀀀 􏻬田居に出で 菜摘むわれをぞ 君召すと 求食り追ひゆく 山城の 打酔へる子ら 藻葉干せよ え舟繋けぬ􀀀
@@ -103,14 +104,21 @@ How multilingual? Real multilingual!
􎳌Rejoice, now we can render Old Korean in a correct way!􀀀 􎳌Rejoice, now we can render Old Korean in a correct way!􀀀
􏃯Unicode References:􀀀 􏃯Supported Unicode Blocks:􀀀
Basic Latin Latin-1 Supplement Latin Extended-A Latin Extended-B IPA Extension Greek Cyrillic Basic Latin Latin-1 Supplement Latin Extended-A Latin Extended-B IPA Extensions
Cyrillic Supplement Armenian Devanagari Bengali Thai Georgian Hangul Jamo Cherokee Runic Spacing Modifier Letters Combining Diacritical Marks Greek and Coptic􏿆ᴱ􀀀 Cyrillic􏿆ᴭ􀀀 Cyrillic Supplement􏿆ᴭ􀀀
Georgian Extended Greek Extended General Punctuations Superscripts and Subscripts CJK Symbols Armenian Devanagari􏿆ᶠⁱ􀀀 Bengali􏿆ᶠⁱ􀀀 Thai Georgian􏿆ჼ􀀀 Hangul Jamo Cherokee􏿆⁷􀀀 Runic Georgian Extended
Latin Extended-C Kana Hangul Compatibility Jamo Kana Phonetic Extensions CJK Unihan Extension A Phonetic Extensions Phonetic Extensions Supplement Latin Extended Additional Greek Extended
CJK Unihan Hangul Jamo Extended-A Hangul Syllables Hangul Jamo Extended-B Fullwidth Forms General Punctuations Superscripts and Subscripts Currency Symbols Letterlike Symbols
Kana Supplement CJK Symbols and Punctuation Latin Extended-C Hiragana Katakana Hangul Compatibility Jamo
Katakana Phonetic Extensions CJK Unified Ideographs Extension A􏿆¹²·¹􀀀 CJK Unified Ideographs􏿆⁶􀀀
Latin Extended-D Hangul Jamo Extended-A Hangul Syllables Hangul Jamo Extended-B
Halfwidth and Fullwidth Forms Kana Supplement􏿆⁹􀀀 Enclosed Alphanumeric Supplement
􏿆ᴭ􀀀 No support for archæic letters 􏿆ᴱ􀀀 No support for Coptic
􏿆ᶠⁱ􀀀 No support for ligatures 􏿆ჼ􀀀 Mkhedruli only
􏿆⁶􀀀 􏿆⁷􀀀 􏿆⁹􀀀 􏿆¹²·¹􀀀 Up to the specified Unicode version
GitHubs issue page is open! You can report any 􏽕errors􀀀, or leave 􏽕suggestions􀀀. GitHubs issue page is open! You can report any 􏽕errors􀀀, or leave 􏽕suggestions􀀀.
You can help this font to be more versatile. (for more languages, more frameworks) 􏽕Clone􀀀 this repo, make You can help this font to be more versatile. (for more languages, more frameworks) 􏽕Clone􀀀 this repo, make

0
font_drawing_template.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

BIN
glyph_height_pos_annotation.png Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 1.1 KiB

108
keming_machine.txt Normal file
View File

@@ -0,0 +1,108 @@
--- Pixel 0
- Lowheight bit
- encoding: has pixel - it's low height
- used by the diacritics system to quickly look up if the character is low height without parsing the Pixel 1
### Legends
#
# A·B < unset for lowheight miniscules, as in e
# |·| < space we don't care
# C·D < middle hole for majuscules, as in C
# E·F < middle hole for miniscules, as in c
# G·H
# ――― < baseline
# |·|
# J·K
--- Pixel 1
- A..K Occupied (1024)
- Is ABGH are all Ys instead of Bars? (2)
- Say, A is Bar but E is wye (e.g. Ꮨ), this condition is false; this character must be encoded as ABDFGH(B).
- encoding:
- <MSB> Y0000000 JK000000 ABCDEFGH <LSB>
- Y: Bar/Wye Mode
- A..K: arguments
- B-type will contract the space by 2 pixels, while Y-type will do it by 1
# Capital/lower itself is given using the pixel 0 due to the diacritics processing
--- Examples
- AB(B): T
- ABCEGH(B): C
- ABCEFGH(Y): K
- ABCDEG: Ꮅ
- ABCDEFGH: B,D,O
- ABCDFH: Ч
- ABCEG: Г
- ABGH: Ꮖ
- ACDEG: Ꮀ
- ACDEFGH: h,Ƅ
- ACDFH: ߆
- ACEGH: L
- AH(Y): \
- BDEFGH: J
- BDFGH: ɺ,ป
- BG(Y): /
- CD: Ⴕ
- CDEF(Y): Φ
- CDEFGH: a,c,e,i,o,φ,ϕ
- CDEFGHJK: g
- CDEFGHK: ƞ
- AB(Y): Y
- ABCD(Y): V
- CDEF(Y): v
- EFGH(Y): ʌ
- CDGH(Y): A
--- Rules
# Legend: _ dont care
# @ must have a bit set
# ` must have a bit unset
- ͟A͟B͟C͟D͟E͟F͟G͟H͟J͟K͟ ͟ ͟ ͟A͟B͟C͟D͟E͟F͟G͟H͟J͟K͟
- _@_`___`__ — `_________ # Γe,TJ ; Ye,YJ,Ve,VJ,TA,ΓA,VA,Vʌ,YA,Yʌ,yA,yʌ,/a,/d
- _@_@___`__ — `___`_@___ # Pɺ but NOT Po,PJ
- _@_@___`__ — `___@_____ # Fo,PJ (always 1 px)
- ___`_`____ — `___@_`___ # Cꟶ,Kꟶ,Lꟶ,Γꟶ
- ___`_`____ — `_@___`___ # CꟵ,KꟵ,LꟵ,ΓꟵ
-----------------------------------------------------
- _`________ — @_`___`___ # eꞀ,LT ; eY,LY,eV,LV,AT,AꞀ,AY,Ay,λY,λy,a\,b\
- _`___`_@__ — @_@___`___ # Lꟼ but NOT oꟼ,bꟼ
- _`___@____ — @_@___`___ # oꟼ,bꟼ (always 1 px)
- _`___@_`__ — __`_`_____ # ⱶƆ,ⱶJ
- _`_@___`__ — __`_`_____ # ⱵƆ,ⱵJ
--- Implementation
code: |
val posTable = intArrayOf(7,6,5,4,3,2,1,0,9,8)
class RuleMask(s: String) {
private var careBits = 0
private var ruleBits = 0
init {
s.forEachIndexed { index, char ->
when (char) {
'@' -> {
careBits = careBits or (1 shl posTable[index])
ruleBits = ruleBits or (1 shl posTable[index])
}
'`' -> {
careBits = careBits or (1 shl posTable[index])
}
}
}
}
fun matches(shapeBits: Int) = ((shapeBits and careBits) and ruleBits) == 0
}
--- Pixel 2
dot removal for diacritics:
- All 24 bits are used to put replacement character
- encoding:
- <MSB> RRRRRRRR GGGGGGGG BBBBBBBB <LSB>

0
samples/README.md Normal file → Executable file
View File

0
samples/wikipedia_x86.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 75 KiB

After

Width:  |  Height:  |  Size: 75 KiB

98
src/net/torvald/terrarumsansbitmap/GlyphProps.kt Normal file → Executable file
View File

@@ -1,16 +1,39 @@
package net.torvald.terrarumsansbitmap package net.torvald.terrarumsansbitmap
/**
* Created by minjaesong on 2021-11-25.
*/
data class DiacriticsAnchor(val type: Int, val x: Int, val y: Int, val xUsed: Boolean, val yUsed: Boolean)
/** /**
* Created by minjaesong on 2018-08-07. * Created by minjaesong on 2018-08-07.
*/ */
data class GlyphProps( data class GlyphProps(
val width: Int, val width: Int,
val writeOnTop: Boolean,
val alignWhere: Int, val isLowheight: Boolean = false,
val alignXPos: Int,
val nudgeX: Int = 0,
val nudgeY: Int = 0,
val diacriticsAnchors: Array<DiacriticsAnchor> = Array(6) { DiacriticsAnchor(it, 0, 0, false, false) },
val alignWhere: Int = 0, // ALIGN_LEFT..ALIGN_BEFORE
val writeOnTop: Int = -1, // -1: false, 0: Type-0, 1: Type-1, etc;
val stackWhere: Int = 0, // STACK_UP..STACK_UP_N_DOWN
val extInfo: IntArray = IntArray(15),
val hasKernData: Boolean = false,
val isKernYtype: Boolean = false,
val kerningMask: Int = 255,
val directiveOpcode: Int = 0, // 8-bits wide
val directiveArg1: Int = 0, // 8-bits wide
val directiveArg2: Int = 0, // 8-bits wide
val rtl: Boolean = false, val rtl: Boolean = false,
val stackWhere: Int = 0,
var extInfo: IntArray? = null
) { ) {
companion object { companion object {
const val ALIGN_LEFT = 0 const val ALIGN_LEFT = 0
@@ -23,34 +46,60 @@ data class GlyphProps(
const val STACK_BEFORE_N_AFTER = 2 const val STACK_BEFORE_N_AFTER = 2
const val STACK_UP_N_DOWN = 3 const val STACK_UP_N_DOWN = 3
const val DIA_OVERLAY = 1 const val DIA_OVERLAY = 2
const val DIA_JOINER = 2 // const val DIA_JOINER = 2
private fun Boolean.toInt() = if (this) 1 else 0 private fun Boolean.toInt() = if (this) 1 else 0
} }
constructor(width: Int, tags: Int) : this( /*constructor(width: Int, tags: Int) : this(
width, width,
tags.ushr(7).and(1) == 1, tags.ushr(7).and(1) == 1,
tags.ushr(5).and(3), tags.ushr(5).and(3),
tags.ushr(1).and(15), tags.ushr(1).and(15),
tags.and(1) == 1, tags.and(1) == 1,
tags.ushr(8).and(3) tags.ushr(8).and(3),
tags.and(1) == 1
) )
fun isOverlay() = writeOnTop && alignXPos == 1 constructor(width: Int, tags: Int, isLowheight: Boolean, isKernYtype: Boolean, kerningMask: Int) : this(
width,
tags.ushr(7).and(1) == 1,
tags.ushr(5).and(3),
tags.ushr(1).and(15),
tags.and(1) == 1,
tags.ushr(8).and(3),
tags.and(1) == 1,
null,
true,
isLowheight,
isKernYtype,
kerningMask
)*/
// fun isOverlay() = writeOnTop && alignXPos == 1
override fun hashCode(): Int { override fun hashCode(): Int {
val tags = rtl.toInt() or alignXPos.shl(1) or alignWhere.shl(5) or val tags = rtl.toInt() or alignWhere.shl(5) or
writeOnTop.toInt().shl(7) or stackWhere.shl(8) writeOnTop.toInt().shl(7) or stackWhere.shl(8)
var hash = -2128831034 var hash = -2128831034
extInfo?.forEach { extInfo.forEach {
hash = hash xor it hash = hash xor it
hash = hash * 16777619 hash = hash * 16777619
} }
diacriticsAnchors.forEach {
hash = hash xor it.type
hash = hash * 16777619
hash = hash xor (it.x or (if (it.xUsed) 128 else 0))
hash = hash * 16777619
hash = hash xor (it.y or (if (it.yUsed) 128 else 0))
hash = hash * 16777619
}
hash = hash xor tags hash = hash xor tags
hash = hash * 167677619 hash = hash * 167677619
@@ -62,5 +111,18 @@ data class GlyphProps(
return other is GlyphProps && this.hashCode() == other.hashCode() return other is GlyphProps && this.hashCode() == other.hashCode()
} }
fun requiredExtInfoCount() = if (stackWhere == STACK_BEFORE_N_AFTER) 2 else 0 fun requiredExtInfoCount() =
if (stackWhere == STACK_BEFORE_N_AFTER)
2
else if (directiveOpcode in 0b10000_000..0b10000_111)
directiveOpcode and 7
else 0
fun isPragma(pragma: String) = when (pragma) {
"replacewith" -> directiveOpcode in 0b10000_000..0b10000_111
else -> false
}
fun forEachExtInfo(action: (Int) -> Unit) = extInfo.slice(0 until requiredExtInfoCount()).forEach(action)
fun forEachExtInfoIndexed(action: (Int, Int) -> Unit) = extInfo.slice(0 until requiredExtInfoCount()).forEachIndexed(action)
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* /*
* Terrarum Sans Bitmap * Terrarum Sans Bitmap
* *
* Copyright (c) 2018 Minjae Song (Torvald) * Copyright (c) 2017-2021 Minjae Song (Torvald)
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -25,14 +25,15 @@
package net.torvald.terrarumsansbitmap.gdx package net.torvald.terrarumsansbitmap.gdx
import com.badlogic.gdx.files.FileHandle import com.badlogic.gdx.files.FileHandle
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Pixmap
/** /**
* Breaks one pixmap atlas into many child pixmaps
*
* Created by minjaesong on 2018-09-17. * Created by minjaesong on 2018-09-17.
*/ */
class PixmapRegionPack( class PixmapRegionPack(
pixmap: Pixmap, pixmapAtlas: Pixmap,
val tileW: Int, val tileW: Int,
val tileH: Int, val tileH: Int,
val hGap: Int = 0, val hGap: Int = 0,
@@ -47,8 +48,8 @@ class PixmapRegionPack(
constructor(fileHandle: FileHandle, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) : constructor(fileHandle: FileHandle, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) :
this(Pixmap(fileHandle), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped) this(Pixmap(fileHandle), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped)
val horizontalCount = (pixmap.width - 2 * hFrame + hGap) / (tileW + hGap) val horizontalCount = (pixmapAtlas.width - 2 * hFrame + hGap) / (tileW + hGap)
val verticalCount = (pixmap.height - 2 * vFrame + vGap) / (tileH + vGap) val verticalCount = (pixmapAtlas.height - 2 * vFrame + vGap) / (tileH + vGap)
val regions: Array<Pixmap> val regions: Array<Pixmap>
@@ -70,10 +71,10 @@ class PixmapRegionPack(
pixmap.pixels.rewind() pixmapAtlas.pixels.rewind()
if (!xySwapped) { if (!xySwapped) {
regions = Array<Pixmap>(horizontalCount * verticalCount, { regions = Array<Pixmap>(horizontalCount * verticalCount) {
val rx = (it % horizontalCount * (tileW + hGap)) + hFrame // pixel, not index val rx = (it % horizontalCount * (tileW + hGap)) + hFrame // pixel, not index
val ry = (it / horizontalCount * (tileH + vGap)) + vFrame // pixel, not index val ry = (it / horizontalCount * (tileH + vGap)) + vFrame // pixel, not index
@@ -84,15 +85,15 @@ class PixmapRegionPack(
// for every "scanline" // for every "scanline"
for (y in 0 until tileH) { for (y in 0 until tileH) {
val offsetY = (ry + y) * (pixmap.width * 4) + (vFrame * pixmap.width * 4) val offsetY = (ry + y) * (pixmapAtlas.width * 4) + (vFrame * pixmapAtlas.width * 4)
val offsetX = rx * 4 + hFrame * 4 val offsetX = rx * 4 + hFrame * 4
//println("offset: ${offsetX + offsetY}") //println("offset: ${offsetX + offsetY}")
val bytesBuffer = ByteArray(4 * tileW) val bytesBuffer = ByteArray(4 * tileW)
pixmap.pixels.position(offsetY + offsetX) pixmapAtlas.pixels.position(offsetY + offsetX)
pixmap.pixels.get(bytesBuffer, 0, bytesBuffer.size) pixmapAtlas.pixels.get(bytesBuffer, 0, bytesBuffer.size)
// test print bytesbuffer // test print bytesbuffer
/*bytesBuffer.forEachIndexed { index, it -> /*bytesBuffer.forEachIndexed { index, it ->
@@ -109,13 +110,11 @@ class PixmapRegionPack(
// todo globalFlipY ?
/*return*/region /*return*/region
}) }
} }
else { else {
regions = Array<Pixmap>(horizontalCount * verticalCount, { regions = Array<Pixmap>(horizontalCount * verticalCount) {
val rx = (it / verticalCount * (tileW + hGap)) + hFrame val rx = (it / verticalCount * (tileW + hGap)) + hFrame
val ry = (it % verticalCount * (tileH + vGap)) + vFrame val ry = (it % verticalCount * (tileH + vGap)) + vFrame
@@ -126,15 +125,15 @@ class PixmapRegionPack(
// for every "scanline" // for every "scanline"
for (y in 0 until tileH) { for (y in 0 until tileH) {
val offsetY = (ry + y) * (pixmap.width * 4) + (vFrame * pixmap.width * 4) val offsetY = (ry + y) * (pixmapAtlas.width * 4) + (vFrame * pixmapAtlas.width * 4)
val offsetX = rx * 4 + hFrame * 4 val offsetX = rx * 4 + hFrame * 4
//println("offset: ${offsetX + offsetY}") //println("offset: ${offsetX + offsetY}")
val bytesBuffer = ByteArray(4 * tileW) val bytesBuffer = ByteArray(4 * tileW)
pixmap.pixels.position(offsetY + offsetX) pixmapAtlas.pixels.position(offsetY + offsetX)
pixmap.pixels.get(bytesBuffer, 0, bytesBuffer.size) pixmapAtlas.pixels.get(bytesBuffer, 0, bytesBuffer.size)
// test print bytesbuffer // test print bytesbuffer
/*bytesBuffer.forEachIndexed { index, it -> /*bytesBuffer.forEachIndexed { index, it ->
@@ -151,10 +150,8 @@ class PixmapRegionPack(
// todo globalFlipY ?
/*return*/region /*return*/region
}) }
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,7 +1,7 @@
/* /*
* Terrarum Sans Bitmap * Terrarum Sans Bitmap
* *
* Copyright (c) 2017 Minjae Song (Torvald) * Copyright (c) 2017-2021 Minjae Song (Torvald)
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy * Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal * of this software and associated documentation files (the "Software"), to deal
@@ -40,17 +40,18 @@ class TextureRegionPack(
val vGap: Int = 0, val vGap: Int = 0,
val hFrame: Int = 0, val hFrame: Int = 0,
val vFrame: Int = 0, val vFrame: Int = 0,
val xySwapped: Boolean = false // because Unicode chart does, duh val xySwapped: Boolean = false, // because Unicode chart does, duh
val flipX: Boolean = false,
val flipY: Boolean = false
): Disposable { ): Disposable {
constructor(ref: String, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) : constructor(ref: String, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false, flipX: Boolean = false, flipY: Boolean = false) :
this(Texture(ref), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped) this(Texture(ref), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped, flipX, flipY)
constructor(fileHandle: FileHandle, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) : constructor(fileHandle: FileHandle, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false, flipX: Boolean = false, flipY: Boolean = false) :
this(Texture(fileHandle), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped) this(Texture(fileHandle), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped, flipX, flipY)
companion object { companion object {
/** Intented for Y-down coord system, typically fon Non-GDX codebase */
var globalFlipY = false
} }
val regions: Array<TextureRegion> val regions: Array<TextureRegion>
@@ -70,7 +71,7 @@ class TextureRegionPack(
region.setRegion(texture) region.setRegion(texture)
region.setRegion(rx, ry, tileW, tileH) region.setRegion(rx, ry, tileW, tileH)
region.flip(false, globalFlipY) region.flip(flipX, flipY)
/*return*/region /*return*/region
} }
@@ -84,7 +85,7 @@ class TextureRegionPack(
region.setRegion(texture) region.setRegion(texture)
region.setRegion(rx, ry, tileW, tileH) region.setRegion(rx, ry, tileW, tileH)
region.flip(false, globalFlipY) region.flip(flipX, flipY)
/*return*/region /*return*/region
} }
@@ -93,6 +94,8 @@ class TextureRegionPack(
fun get(x: Int, y: Int) = regions[y * horizontalCount + x] fun get(x: Int, y: Int) = regions[y * horizontalCount + x]
fun forEach(action: (TextureRegion) -> Unit) = regions.forEach(action)
override fun dispose() { override fun dispose() {
texture.dispose() texture.dispose()
} }

0
src/net/torvald/terrarumsansbitmap/readme.md Normal file → Executable file
View File

View File

@@ -0,0 +1,634 @@
package net.torvald.terrarumtypewriterbitmap.gdx
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.g2d.Batch
import com.badlogic.gdx.graphics.g2d.BitmapFont
import com.badlogic.gdx.graphics.g2d.GlyphLayout
import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.terrarumsansbitmap.DiacriticsAnchor
import net.torvald.terrarumsansbitmap.GlyphProps
import net.torvald.terrarumsansbitmap.gdx.*
import net.torvald.terrarumsansbitmap.gdx.CodePoint
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.TextCacheObj
import net.torvald.terrarumsansbitmap.gdx.TerrarumSansBitmap.Companion.ShittyGlyphLayout
import java.io.BufferedOutputStream
import java.io.FileOutputStream
import java.io.Reader
import java.util.zip.GZIPInputStream
import kotlin.math.roundToInt
/**
* Config File Syntax:
*
* ```
* identifier,image file name,relative codepoint
* # working example:
* intl_qwerty_typewriter,typewriter_intl_qwerty.tga,0
* ko_kr_3set-390_typewriter,typewriter_ko_3set-390.tga,16
* ```
*
* // the Relative Codepoint of 16 should point to U+F3000
*
* Created by minjaesong on 2021-11-04.
*/
class TerrarumTypewriterBitmap(
fontDir: String,
configFile: Reader,
val flipY: Boolean = false,
var errorOnUnknownChar: Boolean = false,
val textCacheSize: Int = 256,
val debug: Boolean = false
) : BitmapFont() {
override fun getLineHeight() = 20f
override fun getXHeight() = 8f
override fun getCapHeight() = 12f
override fun getAscent() = 3f
override fun getDescent() = 3f
override fun isFlipped() = flipY
var interchar = 0
val glyphProps = HashMap<CodePoint, GlyphProps>()
private val sheets = HashMap<String, PixmapRegionPack>()
private val spriteSheetNames = HashMap<String, String>()
private val codepointStart = HashMap<String, CodePoint>()
private val codepointToSheetID = HashMap<Int, String>()
private var textCacheCap = 0
private val textCache = HashMap<Long, TextCacheObj>(textCacheSize * 2)
private val colourBuffer = HashMap<CodePoint, ARGB8888>()
/**
* Insertion sorts the last element fo the textCache
*/
private fun addToCache(text: CodepointSequence, linotype: Texture, width: Int) {
val cacheObj =
TextCacheObj(text.getHash(), ShittyGlyphLayout(text, linotype, width))
if (textCacheCap < textCacheSize) {
textCache[cacheObj.hash] = cacheObj
textCacheCap += 1
}
else {
// randomly eliminate one
textCache.remove(textCache.keys.random())!!.dispose()
// add new one
textCache[cacheObj.hash] = cacheObj
}
}
private fun getCache(hash: Long): TextCacheObj? {
return textCache[hash]
}
private fun getColour(codePoint: Int): Int { // input: 0x10F_RGB, out: RGBA8888
if (colourBuffer.containsKey(codePoint))
return colourBuffer[codePoint]!!
val r = codePoint.and(0x0F00).ushr(8)
val g = codePoint.and(0x00F0).ushr(4)
val b = codePoint.and(0x000F)
val col = r.shl(28) or r.shl(24) or
g.shl(20) or g.shl(16) or
b.shl(12) or b.shl(8) or
0xFF
colourBuffer[codePoint] = col
return col
}
init {
val fontParentDir = if (fontDir.endsWith('/') || fontDir.endsWith('\\')) fontDir else "$fontDir/"
configFile.forEachLine {
if (!it.startsWith("#")) {
val csv = it.split(',')
if (csv.size != 3) throw IllegalArgumentException("Malformed CSV line: '$it'")
val key = csv[0]
val sheetname = csv[1]
val cpstart = csv[2].toInt() * 256 + 0xF9000
spriteSheetNames[key] = sheetname
codepointStart[key] = cpstart
for (k in cpstart until cpstart + 256) {
codepointToSheetID[k] = key
}
}
}
spriteSheetNames.forEach { key, filename ->
var pixmap: Pixmap
println("[TerrarumTypewriterBitmap] loading texture $filename [VARIABLE]")
// unpack gz if applicable
if (filename.endsWith(".gz")) {
val tmpFileName = "tmp_${filename.dropLast(7)}.tga"
try {
val gzi = GZIPInputStream(Gdx.files.internal(fontParentDir + filename).read(8192))
val wholeFile = gzi.readBytes()
gzi.close()
val fos = BufferedOutputStream(FileOutputStream(tmpFileName))
fos.write(wholeFile)
fos.flush()
fos.close()
pixmap = Pixmap(Gdx.files.internal(tmpFileName))
}
catch (e: GdxRuntimeException) {
//e.printStackTrace()
System.err.println("[TerrarumTypewriterBitmap] said texture not found, skipping...")
pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888)
}
//File(tmpFileName).delete()
}
else {
pixmap = try {
Pixmap(Gdx.files.internal(fontParentDir + filename))
} catch (e: GdxRuntimeException) {
//e.printStackTrace()
System.err.println("[TerrarumTypewriterBitmap] said texture not found, skipping...")
Pixmap(1, 1, Pixmap.Format.RGBA8888)
}
}
val cpstart = codepointStart[key]!!
buildWidthTable(pixmap, cpstart until cpstart + 256, 16)
val texRegPack = PixmapRegionPack(pixmap,
TerrarumSansBitmap.W_VAR_INIT,
TerrarumSansBitmap.H,
TerrarumSansBitmap.HGAP_VAR, 0
)
sheets[key] = texRegPack
pixmap.dispose() // you are terminated
}
glyphProps[0] = GlyphProps(0)
}
private fun getSheetType(c: CodePoint) = codepointToSheetID[c] ?: "unknown"
private fun getSheetwisePosition(cPrev: Int, ch: Int) = getSheetType(ch).let {
val coff = ch - (codepointStart[it] ?: 0)
intArrayOf(coff % 16, coff / 16)
}
private fun Boolean.toInt() = if (this) 1 else 0
private fun Int.tagify() = if (this and 255 == 0) 0 else this
private fun buildWidthTable(pixmap: Pixmap, codeRange: Iterable<Int>, cols: Int = 16) {
val binaryCodeOffset = TerrarumSansBitmap.W_VAR_INIT
val cellW = TerrarumSansBitmap.W_VAR_INIT + 1
val cellH = TerrarumSansBitmap.H
for (code in codeRange) {
val cellX = ((code - codeRange.first()) % cols) * cellW
val cellY = ((code - codeRange.first()) / cols) * cellH
val codeStartX = cellX + binaryCodeOffset
val codeStartY = cellY
var width = (0..4).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y).and(255) != 0).toInt() shl y) }
val isLowHeight = (pixmap.getPixel(codeStartX, codeStartY + 5).and(255) != 0)
if (code in 0xF2000..0xF3FFF && code and 127 == Input.Keys.BACKSPACE) {
width *= -1
}
// Keming machine parameters
val kerningBit1 = pixmap.getPixel(codeStartX, codeStartY + 6).tagify()
val kerningBit2 = pixmap.getPixel(codeStartX, codeStartY + 7).tagify()
val kerningBit3 = pixmap.getPixel(codeStartX, codeStartY + 8).tagify()
val kerningBit4 = pixmap.getPixel(codeStartX, codeStartY + 9).tagify()
var isKernYtype = ((kerningBit1 and 0x80000000.toInt()) != 0)
var kerningMask = kerningBit1.ushr(8).and(0xFFFFFF)
val hasKernData = kerningBit1 and 255 != 0//(kerningBit1 and 255 != 0 && kerningMask != 0xFFFF)
if (!hasKernData) {
isKernYtype = false
kerningMask = 255
}
val nudgingBits = pixmap.getPixel(codeStartX, codeStartY + 10).tagify()
val nudgeX = nudgingBits.ushr(24).toByte().toInt() // signed 8-bit int
val nudgeY = nudgingBits.ushr(16).toByte().toInt() // signed 8-bit int
val diacriticsAnchors = (0..5).map {
val yPos = 11 + (it / 3) * 2
val shift = (3 - (it % 3)) * 8
val yPixel = pixmap.getPixel(codeStartX, codeStartY + yPos).tagify()
val xPixel = pixmap.getPixel(codeStartX, codeStartY + yPos + 1).tagify()
val y = (yPixel ushr shift) and 127
val x = (xPixel ushr shift) and 127
val yUsed = (yPixel ushr shift) >= 128
val xUsed = (yPixel ushr shift) >= 128
DiacriticsAnchor(it, x, y, xUsed, yUsed)
}.toTypedArray()
val alignWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 15).and(255) != 0).toInt() shl y) }
var writeOnTop = pixmap.getPixel(codeStartX, codeStartY + 17).tagify()
if (writeOnTop == 0) writeOnTop = -1
else if (writeOnTop == 0xFFFFFF) writeOnTop = 0
val stackWhere = (0..1).fold(0) { acc, y -> acc or ((pixmap.getPixel(codeStartX, codeStartY + y + 18).and(255) != 0).toInt() shl y) }
glyphProps[code] = GlyphProps(width, isLowHeight, nudgeX, nudgeY, diacriticsAnchors, alignWhere, writeOnTop, stackWhere, IntArray(15), hasKernData, isKernYtype, kerningMask)
// if (nudgingBits != 0) println("${code.charInfo()} nudgeX=$nudgeX, nudgeY=$nudgeY, nudgingBits=0x${nudgingBits.toString(16)}")
// extra info
val extCount = glyphProps[code]?.requiredExtInfoCount() ?: 0
if (extCount > 0) {
for (x in 0 until extCount) {
var info = 0
for (y in 0..18) {
// if ALPHA is not zero, assume it's 1
if (pixmap.getPixel(cellX + x, cellY + y).and(255) != 0) {
info = info or (1 shl y)
}
}
glyphProps[code]!!.extInfo[x] = info
}
}
}
}
private val pixmapOffsetY = 10
private val linotypePad = 16
private var flagFirstRun = true
private @Volatile var textBuffer = CodepointSequence(256)
private @Volatile lateinit var tempLinotype: Texture
private var nullProp = GlyphProps(15)
fun draw(batch: Batch, codepoints: CodepointSequence, x: Float, y: Float): GlyphLayout? {
// Q&D fix for issue #12
// When the line ends with a diacritics, the whole letter won't render
// If the line starts with a letter-with-diacritic, it will error out
// Some diacritics (e.g. COMBINING TILDE) do not obey lowercase letters
val charSeqNotBlank = codepoints.size > 0 // determine emptiness BEFORE you hack a null chars in
val newCodepoints = CodepointSequence()
newCodepoints.add(0)
newCodepoints.addAll(codepoints)
newCodepoints.add(0)
fun Int.flipY() = this * if (flipY) 1 else -1
// always draw at integer position; this is bitmap font after all
val x = Math.round(x)
val y = Math.round(y)
val charSeqHash = newCodepoints.getHash()
var renderCol = -1 // subject to change with the colour code
if (charSeqNotBlank) {
val cacheObj = getCache(charSeqHash)
if (cacheObj == null || flagFirstRun) {
textBuffer = newCodepoints
val (posXbuffer, posYbuffer) = buildPosMap(textBuffer)
flagFirstRun = false
//println("text not in buffer: $charSeq")
//textBuffer.forEach { print("${it.toHex()} ") }
//println()
// resetHash(charSeq, x.toFloat(), y.toFloat())
val _pw = posXbuffer.last() + 2*linotypePad
val _ph = TerrarumSansBitmap.H + (pixmapOffsetY * 2)
if (_pw < 0 || _ph < 0) throw RuntimeException("Illegal linotype dimension (w: $_pw, h: $_ph)")
val linotypePixmap = Pixmap(_pw, _ph, Pixmap.Format.RGBA8888)
var index = 0
while (index <= textBuffer.lastIndex) {
try {
val c = textBuffer[index]
val sheetID = getSheetType(c)
val (sheetX, sheetY) =
if (index == 0) getSheetwisePosition(0, c)
else getSheetwisePosition(textBuffer[index - 1], c)
val hash = getHash(c) // to be used to simulate printing irregularity
if (TerrarumSansBitmap.isColourCode(c)) {
if (c == 0x100000) {
renderCol = -1
} else {
renderCol = getColour(c)
}
} else {
try {
val posY = posYbuffer[index].flipY()
val posX = posXbuffer[index]
val texture = sheets[sheetID]?.get(sheetX, sheetY)
texture?.let {
linotypePixmap.drawPixmap(it, posX + linotypePad, posY + pixmapOffsetY, renderCol)
}
} catch (noSuchGlyph: ArrayIndexOutOfBoundsException) {
}
}
index++
}
catch (e: NullPointerException) {
System.err.println("Shit hit the multithreaded fan")
e.printStackTrace()
break
}
}
tempLinotype = Texture(linotypePixmap)
tempLinotype.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
// put things into cache
//textCache[charSeq] = ShittyGlyphLayout(textBuffer, linotype!!)
addToCache(textBuffer, tempLinotype, posXbuffer.last())
linotypePixmap.dispose()
}
else {
textBuffer = cacheObj.glyphLayout!!.textBuffer
tempLinotype = cacheObj.glyphLayout!!.linotype
}
batch.draw(tempLinotype,
(x - linotypePad).toFloat(),
(y - pixmapOffsetY).toFloat() + (if (flipY) (tempLinotype.height) else 0),
(tempLinotype.width.toFloat()),
(tempLinotype.height.toFloat()) * (if (flipY) -1 else 1)
)
}
return null
}
/**
* posXbuffer's size is greater than the string, last element marks the width of entire string.
*/
private fun buildPosMap(str: List<Int>): Pair<IntArray, IntArray> {
val posXbuffer = IntArray(str.size + 1) { 0 }
val posYbuffer = IntArray(str.size) { 0 }
var nonDiacriticCounter = 0 // index of last instance of non-diacritic char
var stackUpwardCounter = 0
var stackDownwardCounter = 0
val HALF_VAR_INIT = TerrarumSansBitmap.W_VAR_INIT.minus(1).div(2)
// this is starting to get dirty...
// persisting value. the value is set a few characters before the actual usage
var extraWidth = 0
try {
for (charIndex in 0 until posXbuffer.size - 1) {
if (charIndex > 0) {
// nonDiacriticCounter allows multiple diacritics
val thisChar = str[charIndex]
if (glyphProps[thisChar] == null && errorOnUnknownChar) {
val errorGlyphSB = StringBuilder()
Character.toChars(thisChar).forEach { errorGlyphSB.append(it) }
throw InternalError("No GlyphProps for char '$errorGlyphSB' " +
"(${thisChar.charInfo()})")
}
val thisProp = glyphProps[thisChar] ?: nullProp
val lastNonDiacriticChar = str[nonDiacriticCounter]
val itsProp = glyphProps[lastNonDiacriticChar] ?: nullProp
val kerning = 0
//println("char: ${thisChar.charInfo()}\nproperties: $thisProp")
var alignmentOffset = when (thisProp.alignWhere) {
GlyphProps.ALIGN_LEFT -> 0
GlyphProps.ALIGN_RIGHT -> thisProp.width - TerrarumSansBitmap.W_VAR_INIT
GlyphProps.ALIGN_CENTRE -> Math.ceil((thisProp.width - TerrarumSansBitmap.W_VAR_INIT) / 2.0).toInt()
else -> 0 // implies "diacriticsBeforeGlyph = true"
}
if (thisProp.writeOnTop < 0) {
posXbuffer[charIndex] = -thisProp.nudgeX +
when (itsProp.alignWhere) {
GlyphProps.ALIGN_RIGHT ->
posXbuffer[nonDiacriticCounter] + TerrarumSansBitmap.W_VAR_INIT + alignmentOffset + interchar + kerning + extraWidth
GlyphProps.ALIGN_CENTRE ->
posXbuffer[nonDiacriticCounter] + HALF_VAR_INIT + itsProp.width + alignmentOffset + interchar + kerning + extraWidth
else ->
posXbuffer[nonDiacriticCounter] + itsProp.width + alignmentOffset + interchar + kerning + extraWidth
}
nonDiacriticCounter = charIndex
stackUpwardCounter = 0
stackDownwardCounter = 0
extraWidth = thisProp.nudgeX // NOTE: sign is flipped!
}
/*else if (thisProp.writeOnTop >= 0 && thisProp.diacriticsAnchors[0].x == GlyphProps.DIA_JOINER) {
posXbuffer[charIndex] = when (itsProp.alignWhere) {
GlyphProps.ALIGN_RIGHT ->
posXbuffer[nonDiacriticCounter] + TerrarumSansBitmap.W_VAR_INIT + alignmentOffset
//GlyphProps.ALIGN_CENTRE ->
// posXbuffer[nonDiacriticCounter] + HALF_VAR_INIT + itsProp.width + alignmentOffset
else ->
posXbuffer[nonDiacriticCounter] + itsProp.width + alignmentOffset
}
}*/
else {
// set X pos according to alignment information
posXbuffer[charIndex] = when (thisProp.alignWhere) {
GlyphProps.ALIGN_LEFT, GlyphProps.ALIGN_BEFORE -> posXbuffer[nonDiacriticCounter]
GlyphProps.ALIGN_RIGHT -> {
posXbuffer[nonDiacriticCounter] - (TerrarumSansBitmap.W_VAR_INIT - itsProp.width)
}
GlyphProps.ALIGN_CENTRE -> {
val alignXPos = if (itsProp.diacriticsAnchors[0].x == 0) itsProp.width.div(2) else itsProp.diacriticsAnchors[0].x
if (itsProp.alignWhere == GlyphProps.ALIGN_RIGHT) {
posXbuffer[nonDiacriticCounter] + alignXPos + (itsProp.width + 1).div(2)
}
else {
posXbuffer[nonDiacriticCounter] + alignXPos - HALF_VAR_INIT
}
}
else -> throw InternalError("Unsupported alignment: ${thisProp.alignWhere}")
}
// set Y pos according to diacritics position
if (thisProp.alignWhere == GlyphProps.ALIGN_CENTRE) {
when (thisProp.stackWhere) {
GlyphProps.STACK_DOWN -> {
posYbuffer[charIndex] = TerrarumSansBitmap.H_DIACRITICS * stackDownwardCounter
stackDownwardCounter++
}
GlyphProps.STACK_UP -> {
posYbuffer[charIndex] = -TerrarumSansBitmap.H_DIACRITICS * stackUpwardCounter
// shift down on lowercase if applicable
/*if (getSheetType(thisChar) in TerrarumSansBitmap.autoShiftDownOnLowercase &&
lastNonDiacriticChar.isLowHeight()) {
//println("AAARRRRHHHH for character ${thisChar.toHex()}")
//println("lastNonDiacriticChar: ${lastNonDiacriticChar.toHex()}")
//println("cond: ${thisProp.alignXPos == GlyphProps.DIA_OVERLAY}, charIndex: $charIndex")
if (thisProp.alignXPos == GlyphProps.DIA_OVERLAY)
posYbuffer[charIndex] -= TerrarumSansBitmap.H_OVERLAY_LOWERCASE_SHIFTDOWN // if minus-assign doesn't work, try plus-assign
else
posYbuffer[charIndex] -= TerrarumSansBitmap.H_STACKUP_LOWERCASE_SHIFTDOWN // if minus-assign doesn't work, try plus-assign
}*/
stackUpwardCounter++
}
GlyphProps.STACK_UP_N_DOWN -> {
posYbuffer[charIndex] = TerrarumSansBitmap.H_DIACRITICS * stackDownwardCounter
stackDownwardCounter++
posYbuffer[charIndex] = -TerrarumSansBitmap.H_DIACRITICS * stackUpwardCounter
stackUpwardCounter++
}
// for BEFORE_N_AFTER, do nothing in here
}
}
}
}
}
// fill the last of the posXbuffer
if (str.isNotEmpty()) {
val lastCharProp = glyphProps[str.last()]
val penultCharProp = glyphProps[str[nonDiacriticCounter]]!!
posXbuffer[posXbuffer.lastIndex] = 1 + posXbuffer[posXbuffer.lastIndex - 1] + // adding 1 to house the shadow
if (lastCharProp != null && lastCharProp.writeOnTop >= 0) {
val realDiacriticWidth = if (lastCharProp.alignWhere == GlyphProps.ALIGN_CENTRE) {
(lastCharProp.width).div(2) + penultCharProp.diacriticsAnchors[0].x
}
else if (lastCharProp.alignWhere == GlyphProps.ALIGN_RIGHT) {
(lastCharProp.width) + penultCharProp.diacriticsAnchors[0].x
}
else 0
maxOf(penultCharProp.width, realDiacriticWidth)
}
else {
(lastCharProp?.width ?: 0)
}
}
else {
posXbuffer[0] = 0
}
}
catch (e: NullPointerException) {}
return posXbuffer to posYbuffer
}
/***
* @param col RGBA8888 representation
*/
private fun Pixmap.drawPixmap(pixmap: Pixmap, xPos: Int, yPos: Int, col: Int) {
for (y in 0 until pixmap.height) {
for (x in 0 until pixmap.width) {
val pixel = pixmap.getPixel(x, y) // Pixmap uses RGBA8888, while Color uses ARGB. What the fuck?
val newPixel = pixel colorTimes col
this.drawPixel(xPos + x, yPos + y, newPixel)
}
}
}
private infix fun Int.colorTimes(other: Int): Int {
val thisBytes = IntArray(4) { this.ushr(it * 8).and(255) }
val otherBytes = IntArray(4) { other.ushr(it * 8).and(255) }
return (thisBytes[0] times256 otherBytes[0]) or
(thisBytes[1] times256 otherBytes[1]).shl(8) or
(thisBytes[2] times256 otherBytes[2]).shl(16) or
(thisBytes[3] times256 otherBytes[3]).shl(24)
}
private infix fun Int.times256(other: Int) = multTable255[this][other]
private val multTable255 = Array(256) { left ->
IntArray(256) { right ->
(255f * (left / 255f).times(right / 255f)).roundToInt()
}
}
// randomiser effect hash ONLY
private val hashBasis = -3750763034362895579L
private val hashPrime = 1099511628211L
private var hashAccumulator = hashBasis
fun getHash(char: Int): Long {
hashAccumulator = hashAccumulator xor char.toLong()
hashAccumulator *= hashPrime
return hashAccumulator
}
fun CodepointSequence.getHash(): Long {
val hashBasis = -3750763034362895579L
val hashPrime = 1099511628211L
var hashAccumulator = hashBasis
try {
this.forEach {
hashAccumulator = hashAccumulator xor it.toLong()
hashAccumulator *= hashPrime
}
}
catch (e: NullPointerException) {
System.err.println("CodepointSequence is null?!")
e.printStackTrace()
}
return hashAccumulator
}
private fun Int.charInfo() = "U+${this.toString(16).padStart(4, '0').toUpperCase()}: ${Character.getName(this)}"
override fun dispose() {
super.dispose()
textCache.values.forEach { it.dispose() }
sheets.values.forEach { it.dispose() }
}
}

0
terrarum_sans_cyrillic_2.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 22 KiB

After

Width:  |  Height:  |  Size: 22 KiB

BIN
testing.PNG Normal file → Executable file

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 14 KiB

9
testtext.txt Normal file → Executable file
View File

@@ -1,10 +1,5 @@
re ʘ, ʇ, ʗ, and ʖ, al
ɓ ɗ ɠ
ɐ ɔ ə ɟ ɥ ɯ ɹ ʇ ʌ ʍ ʎ
Vʷ[kʰuˣt̪s̟] and Vʷ[kʰʉˣt͜ʃ].
ʡ̆ A ดุ ตี ปู่ พี่ ป่ ม่ ปั มั พีุ
Labiodental flap [ⱱ] U+2C71 ทิ่ท่ท่ิ ปิ่ป่ป่ิ ทิ้ ปิ้ มำด มําด
acegijmnopqrsuvwxyzɱɳʙɾɽʒʂʐʋɹɻɥɟɡɢʛȵɲŋɴʀɕʑçʝxɣχʁʜʍɰʟɨʉɯuʊøɘɵɤəɛœɜɞʌɔæɐɶɑɒɚɝɩɪʅʈʏʞⱥⱦⱱⱳⱴⱶⱷⱸⱺⱻ

0
width_bit_encoding_annotated.png Normal file → Executable file
View File

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

BIN
work_files/Braille.psd Executable file

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More