Compare commits
179 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
49f5e649b7 | ||
|
|
1656e50c3b | ||
|
|
99a1648734 | ||
|
|
9672aa8e05 | ||
|
|
d72ecb5cfd | ||
|
|
39fccbe6cb | ||
|
|
84efb253cf | ||
|
|
4c63860dc1 | ||
|
|
36acc7e523 | ||
|
|
700397a995 | ||
|
|
dc6bd89497 | ||
|
|
c2ed83d511 | ||
|
|
0a41da1659 | ||
|
|
96e412414a | ||
|
|
483476b5fa | ||
|
|
ed8bcf7dc8 | ||
|
|
376c7cf9a4 | ||
|
|
05d34d563d | ||
|
|
e59db6954a | ||
|
|
9c05fb399b | ||
|
|
40d4bc41c6 | ||
|
|
1f9a79db48 | ||
|
|
0943d38926 | ||
|
|
5469b56841 | ||
|
|
d31730b5c3 | ||
|
|
bd36ee7399 | ||
|
|
b8f5f57878 | ||
|
|
63de646eae | ||
|
|
e70ee44a37 | ||
|
|
6ee66fdccc | ||
|
|
5ecffa1352 | ||
|
|
46efc42e24 | ||
|
|
35829ce982 | ||
|
|
756ef4fae5 | ||
|
|
ce31a5a6ef | ||
|
|
14ea4d8d84 | ||
|
|
f2eb1464f6 | ||
|
|
45b464ee13 | ||
|
|
c3f9ea47fd | ||
|
|
87012d7671 | ||
|
|
1fce4055d7 | ||
|
|
b83dd501fc | ||
|
|
94a40a4a87 | ||
|
|
2fa867ce44 | ||
|
|
4d1a599263 | ||
|
|
8641c95169 | ||
|
|
4f6584ac27 | ||
|
|
cb25c5bf56 | ||
|
|
5c534ed388 | ||
|
|
368bf0ee15 | ||
|
|
c9ccf3e7f8 | ||
|
|
0ced94cb57 | ||
|
|
b158e11e25 | ||
|
|
f4658daa9a | ||
|
|
56b4ccb848 | ||
|
|
2748eeb367 | ||
|
|
8647578802 | ||
|
|
3422c20322 | ||
|
|
4561b06428 | ||
|
|
652f239af3 | ||
|
|
c2428ff7c2 | ||
|
|
2d5e592622 | ||
|
|
3a569a2e2e | ||
|
|
f600764364 | ||
|
|
ab2669b555 | ||
|
|
f43a81de3f | ||
|
|
33ae3fa48a | ||
|
|
12fc3eee03 | ||
|
|
396954e0ee | ||
|
|
d65aaa6da6 | ||
|
|
ae67833cb2 | ||
|
|
4261652bdf | ||
|
|
49d83a297f | ||
|
|
b3a48b23ee | ||
|
|
b802f9b02e | ||
|
|
0afdb9c2cf | ||
|
|
c295430866 | ||
|
|
883375dc9b | ||
|
|
6a1208b45d | ||
|
|
25084b7a94 | ||
|
|
c325c9c30c | ||
|
|
d89409cc73 | ||
|
|
0ff564a192 | ||
|
|
930804cf48 | ||
|
|
699981d9a2 | ||
|
|
947c966660 | ||
|
|
554d9a5d0b | ||
|
|
45e5c39739 | ||
|
|
74e540cb61 | ||
|
|
c1ec50e166 | ||
|
|
58ce18f981 | ||
|
|
f1fa98880f | ||
|
|
0c754d09ed | ||
|
|
b40e4fcc26 | ||
|
|
a7bb33c3a0 | ||
|
|
c3930b2e08 | ||
|
|
979180860e | ||
|
|
61fb70975c | ||
|
|
1af9f7c915 | ||
|
|
810411de7e | ||
|
|
b9bf9ca10d | ||
|
|
526c16daa9 | ||
|
|
e58104d5b5 | ||
|
|
92aeb3c8aa | ||
|
|
3841611780 | ||
|
|
06bc8c9e2d | ||
|
|
21415c6f8d | ||
|
|
22c2a7aa52 | ||
|
|
0eb181f315 | ||
|
|
45b431f953 | ||
|
|
bbee554fec | ||
|
|
c4c67f489e | ||
|
|
4d867d6523 | ||
|
|
6620c11178 | ||
|
|
db06cab07c | ||
|
|
90b11cdd97 | ||
|
|
7bb92d1b4e | ||
|
|
b5dd744bd5 | ||
|
|
34903b10d4 | ||
|
|
0c5b7c8b70 | ||
|
|
cdffca98ef | ||
|
|
ce30d1d5fd | ||
|
|
ab067044f8 | ||
|
|
3e04b8bbe6 | ||
|
|
4556a9e244 | ||
|
|
e5d04de250 | ||
|
|
b7df181729 | ||
|
|
2fd3fcfd46 | ||
|
|
73251d70fa | ||
|
|
971f98beb3 | ||
|
|
abe1da35a0 | ||
|
|
29885f3ac9 | ||
|
|
56d2a98a5b | ||
|
|
43342fff00 | ||
|
|
51d4dec6d3 | ||
|
|
81dc38d242 | ||
|
|
863f9d91c8 | ||
|
|
4c99cca7ff | ||
|
|
b807b96b5f | ||
|
|
91c9a7a99c | ||
|
|
778e2b0afb | ||
|
|
c9055ef7b8 | ||
|
|
e60b95efb8 | ||
|
|
9ca70a601b | ||
|
|
6cacc56ea8 | ||
|
|
6d142f082c | ||
|
|
db3b13800b | ||
|
|
7fe0cc9527 | ||
|
|
b62fee89cb | ||
|
|
d88443814f | ||
|
|
dfeab56bb5 | ||
|
|
b623727b1a | ||
|
|
048b683cb2 | ||
|
|
35b384af53 | ||
|
|
cebfa27d59 | ||
|
|
c57de3a21f | ||
|
|
4ad5e47758 | ||
|
|
f06ed4529c | ||
|
|
8da321bdc2 | ||
|
|
920b11e3e9 | ||
|
|
d8dd88c6a7 | ||
|
|
ba28b6d10c | ||
|
|
50ae1789bf | ||
|
|
bd9784a516 | ||
|
|
0bafde9914 | ||
|
|
b3bfe6035f | ||
|
|
c3cf795e9a | ||
|
|
cefc7860b3 | ||
|
|
b8963cd3a9 | ||
|
|
32290dd504 | ||
|
|
2702f850c2 | ||
|
|
2e10249f27 | ||
|
|
04a375328c | ||
|
|
97ef1ddc27 | ||
|
|
4057d86176 | ||
|
|
654f7b9ac4 | ||
|
|
91afc4af31 | ||
|
|
1440908820 | ||
|
|
4ce58cf5d1 |
10
.gitattributes
vendored
Normal 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
|
||||||
11
.gitignore
vendored
Normal file → Executable file
@@ -3,4 +3,13 @@ demo/lib/*
|
|||||||
demo/assets/*
|
demo/assets/*
|
||||||
out/*
|
out/*
|
||||||
lib/*
|
lib/*
|
||||||
Terrarum-sans-bitmap*.zip
|
Terrarum-sans-bitmap*.zip
|
||||||
|
TerrarumSansBitmap*.jar
|
||||||
|
Font*.jar
|
||||||
|
tmp_*
|
||||||
|
*~
|
||||||
|
.tmp*
|
||||||
|
tmp_*
|
||||||
|
*.bak
|
||||||
|
*-autosave.kra
|
||||||
|
.directory
|
||||||
|
|||||||
0
.idea/.name
generated
Normal file → Executable file
76
.idea/artifacts/FontDemoGDX.xml
generated
Normal file → Executable 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
@@ -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
0
.idea/codeStyles/codeStyleConfig.xml
generated
Normal file → Executable file
7
.idea/kotlinc.xml
generated
Normal file → Executable 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>
|
||||||
11
.idea/libraries/KotlinJavaRuntime.xml
generated
@@ -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>
|
||||||
10
.idea/libraries/TesterLib.xml
generated
@@ -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>
|
|
||||||
@@ -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>
|
||||||
0
.idea/markdown-navigator.xml
generated
Normal file → Executable file
0
.idea/markdown-navigator/profiles_settings.xml
generated
Normal file → Executable file
2
.idea/misc.xml
generated
Normal file → Executable 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
0
.idea/vcs.xml
generated
Normal file → Executable file
1026
.idea/workspace.xml
generated
Normal file → Executable file
2
BuildJAR_TerrarumSansBitmap.iml
Normal file → Executable 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>
|
||||||
150
CONTRIBUTING.md
Normal file → Executable file
@@ -1,3 +1,5 @@
|
|||||||
|
#### Pixel Artists Wanted: for Arabic (all four forms) and other Indian scripts (all the ligatures). Must willing to follow the styles and have a knowledge in Unicode. Your name will be inscribed in the list of contributors.
|
||||||
|
|
||||||
You can contribute to the font by fixing wrong glyphs, suggesting better ones, extending character set (letters for other writing systems or filling in the blanks on the existing ones), or code for other game frameworks (not limited to Java). Please leave pull request for that.
|
You can contribute to the font by fixing wrong glyphs, suggesting better ones, extending character set (letters for other writing systems or filling in the blanks on the existing ones), or code for other game frameworks (not limited to Java). Please leave pull request for that.
|
||||||
|
|
||||||
Font Spritesheets are stored in ```assets/graphics/fonts``` directory. Image format must be TGA with Alpha — no PNG. If someone needs PNG, they can batch-convert the font using utils like ImageMagick.
|
Font Spritesheets are stored in ```assets/graphics/fonts``` directory. Image format must be TGA with Alpha — no PNG. If someone needs PNG, they can batch-convert the font using utils like ImageMagick.
|
||||||
@@ -5,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
|
## Ascenders, descenders, width informations (aka Glyph Tags)
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
@@ -24,56 +26,154 @@ 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
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
Width is encoded in binary bits, on pixels. On the font spritesheet, every glyph has vertical dots on their top-right side (to be exact, every (16k - 1)th pixel on x axis). Above image is a sample of the font, with width information coloured in magenta. From top to bottom, each dot represents 1, 2, 4 and 8. For example, in the above image, ! (exclamation mark) has width of 5, " (double quote) has width of 6, # (octothorp) has width of 8, $ (dollar sign) has width of 9.
|
Width is encoded in binary bits, on pixels. On the font spritesheet, every glyph has vertical dots on their top-right side (to be exact, every (16k - 1)th pixel on x axis). Above image is a sample of the font, with width information coloured in magenta. From top to bottom, each dot represents 1, 2, 4 and 8. For example, in the above image, ! (exclamation mark) has width of 5, " (double quote) has width of 6, # (octothorp) has width of 8, $ (dollar sign) has width of 9.
|
||||||
|
|
||||||
### Glyph Tagging System
|
### 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 == RTL
|
(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 -,
|
||||||
0 == Write on top of prev chars (e.g. diacritics)
|
K |= Tags used by the "Keming Machine"
|
||||||
1 == Diacritics stack 0:upward/1:downward
|
K -'
|
||||||
(MSB) X == undefined, should be 0
|
Q ---Compiler Directive (see below)
|
||||||
|
n --,
|
||||||
NOTE: If glyphs are right or centre aligned, they must be aligned in the
|
Y -, `-Nudging Bits (see below)
|
||||||
same way inside of the bitmap; the program assumes every variable-
|
X |
|
||||||
width glyphs to have a width of 15, regardless of the tagged width.
|
Y |= Diacritics Anchor Points (see below)
|
||||||
If the diacritic is aligned before the glyph, the diacritic itself
|
X -'
|
||||||
is always assumed as left-aligned, as this font will swap position
|
A -,_ 0 Align 1 Align 0 Align 1 Align before
|
||||||
of said diacritic and the glyph right before it.
|
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
|
||||||
|
|
||||||
|
When the tag is stack-up, it'll be drawn 4 px lower if the underlying
|
||||||
|
character is lowercase.
|
||||||
|
|
||||||
|
#### Align-To-This-X-Pos
|
||||||
|
|
||||||
|
Since this tag does not make sense for diacritics, they will use the value for compeletely different purpose:
|
||||||
|
|
||||||
|
0 : Nothing special
|
||||||
|
1 : Covers previous character; it's neither stack-up nor down.
|
||||||
|
Will be drawn 2 px lower if the underlying character is lowercase
|
||||||
|
2 : Joiner.
|
||||||
|
3..15: undefined
|
||||||
|
|
||||||
|
#### Diacritics That Comes Before and After
|
||||||
|
|
||||||
|
When this tag is set, the font compiler will replace this glyph with two extra code points given in the bitmap.
|
||||||
|
|
||||||
|
To implement those, this two extra code points are needed, which are provided in the Unicode's Reference Chart (www.unicode.org/charts/PDF/Uxxxx.pdf) The code points must be "drawn" in the bitmap, in the same manor as a tagging system. The zeroth column (x = 0) has the "before" character, the first column (x = 1) has the "after". All nineteen pixels (bits) are read by the font, which encompasses U+0000..U+EFFFF
|
||||||
|
|
||||||
|
For working examples, take a note at the bengali sprite sheet.
|
||||||
|
|
||||||
|
This tag can be used as a general "replace this with these" directive, as long as you're replacing it into two letters. This directive is exploited to construct dutch ligature "IJ" (U+0132 and U+0133), in the sheet LatinExtA.
|
||||||
|
|
||||||
|
Also note that the font compiler will not "stack" these diacritics.
|
||||||
|
|
||||||
|
|
||||||
|
#### NOTES
|
||||||
|
- If glyphs are right or centre aligned, they must be aligned in the same way inside of the bitmap; the font compiler assumes every variable-width glyphs to have a width of 15, regardless of the tagged width.
|
||||||
|
- If the diacritic is aligned before the glyph, the diacritic itself is always assumed as left-aligned, as the font compiler will exchange position of said diacritic and the glyph right before it.
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
(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 Ꮺ)
|
||||||
|
|
||||||
### Implementing the Korean writing system
|
## 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.
|
||||||
|
- 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.
|
||||||
|
|
||||||
|
## 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.
|
||||||
|
|
||||||
This is a Kotlin-like pseudocode for assembling the glyph:
|
This is a Kotlin-like pseudocode for assembling the glyph:
|
||||||
|
|
||||||
|
// NOTE: this code implements modern Hangul only, in the unicode range of 0xAC00..0xD7A3.
|
||||||
|
// the spritesheet is made to accomodate Johab encoding scheme, but can still be used with the following code.
|
||||||
|
// for the code for full Johab encoding (U+1100.. that includes Old Korean), please refer to the actual code in the repo.
|
||||||
|
|
||||||
function getHanChosung(hanIndex: Int) = hanIndex / (21 * 28)
|
function getHanChosung(hanIndex: Int) = hanIndex / (21 * 28)
|
||||||
function getHanJungseong(hanIndex: Int) = hanIndex / 28 % 21
|
function getHanJungseong(hanIndex: Int) = hanIndex / 28 % 21
|
||||||
function getHanJongseong(hanIndex: Int) = hanIndex % 28
|
function getHanJongseong(hanIndex: Int) = hanIndex % 28
|
||||||
|
|
||||||
jungseongWide = arrayOf(8, 12, 13, 17, 18, 21)
|
jungseongWide = arrayOf(9,13,14,18,19)
|
||||||
jungseongComplex = arrayOf(9, 10, 11, 14, 15, 16, 22)
|
jungseongComplex = arrayOf(10,11,12,15,16,17,20,23)
|
||||||
|
|
||||||
function getHanInitialRow(hanIndex: Int): Int {
|
function getHanInitialRow(hanIndex: Int): Int {
|
||||||
val ret: Int
|
val ret: Int
|
||||||
|
|||||||
9
CONTRIBUTORS.txt
Executable file
@@ -0,0 +1,9 @@
|
|||||||
|
Project Maintainer and Programmer
|
||||||
|
|
||||||
|
- minjaesong (Torvald)
|
||||||
|
|
||||||
|
|
||||||
|
This font was not possible without following artists:
|
||||||
|
|
||||||
|
- minjaesong (Torvald)
|
||||||
|
<< Append your name here. If you're getting consistent merge conflicts, push without this and leave a Issue on the GitHub page >>
|
||||||
BIN
FontDemoGDX.jar
4
FontTestGDX/FontTestGDX.iml
Normal file → Executable 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>
|
||||||
9
FontTestGDX/META-INF/MANIFEST.MF
Normal file → Executable 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
|
Main-Class: FontTestGDXKt
|
||||||
l-natives.jar lib/gdx-natives.jar lib/kotlin-stdlib.jar TerrarumSansB
|
|
||||||
itmap.jar
|
|
||||||
Main-Class: FontTestGDXKt
|
|
||||||
|
|
||||||
|
|||||||
283
FontTestGDX/src/FontTestGDX.kt
Normal file → Executable 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>
|
||||||
|
|
||||||
@@ -22,119 +27,29 @@ class FontTestGDX : Game() {
|
|||||||
|
|
||||||
lateinit var camera: OrthographicCamera
|
lateinit var camera: OrthographicCamera
|
||||||
|
|
||||||
override fun create() {
|
private val testing = false
|
||||||
font = GameFontBase("./assets", flipY = false, errorOnUnknownChar = true) // must test for two flipY cases
|
|
||||||
|
|
||||||
val inTextFile = Gdx.files.internal("./FontTestGDX/demotext.txt")
|
private val demotextName = if (testing) "testtext.txt" else "demotext.txt"
|
||||||
val reader = inTextFile.reader()
|
private val outimageName = if (testing) "testing.PNG" else "demo.PNG"
|
||||||
|
|
||||||
|
private lateinit var faketex: Texture
|
||||||
|
|
||||||
|
override fun create() {
|
||||||
|
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 reader = inTextFile.reader("UTF-8")
|
||||||
inputText = reader.readLines()
|
inputText = reader.readLines()
|
||||||
reader.close()
|
reader.close()
|
||||||
|
|
||||||
batch = SpriteBatch()
|
batch = SpriteBatch()
|
||||||
|
|
||||||
|
|
||||||
|
// create faketex
|
||||||
|
val fakepix = Pixmap(1,1,Pixmap.Format.RGBA8888)
|
||||||
println("START")
|
fakepix.drawPixel(0,0,-1)
|
||||||
|
faketex = Texture(fakepix)
|
||||||
val l = intArrayOf(0xFF00,
|
fakepix.dispose()
|
||||||
0xFF10,
|
|
||||||
0xFF20,
|
|
||||||
0xFF30,
|
|
||||||
0xFF40,
|
|
||||||
0xFF50,
|
|
||||||
0xFF60,
|
|
||||||
0xFF70,
|
|
||||||
0xFF80,
|
|
||||||
0xFF90,
|
|
||||||
0xFFA0,
|
|
||||||
0xFFB0,
|
|
||||||
0xFFC0,
|
|
||||||
0xFFD0,
|
|
||||||
0xFFE0,
|
|
||||||
0xFFF0,
|
|
||||||
0xFEF0,
|
|
||||||
0xFDF0,
|
|
||||||
0xFCF0,
|
|
||||||
0xFBF0,
|
|
||||||
0xFAF0,
|
|
||||||
0xF9F0,
|
|
||||||
0xF8F0,
|
|
||||||
0xF7F0,
|
|
||||||
0xF6F0,
|
|
||||||
0xF5F0,
|
|
||||||
0xF4F0,
|
|
||||||
0xF3F0,
|
|
||||||
0xF2F0,
|
|
||||||
0xF1F0,
|
|
||||||
0xF0F0,
|
|
||||||
0xF0F1,
|
|
||||||
0xF0F2,
|
|
||||||
0xF0F3,
|
|
||||||
0xF0F4,
|
|
||||||
0xF0F5,
|
|
||||||
0xF0F6,
|
|
||||||
0xF0F7,
|
|
||||||
0xF0F8,
|
|
||||||
0xF0F9,
|
|
||||||
0xF0FA,
|
|
||||||
0xF0FB,
|
|
||||||
0xF0FC,
|
|
||||||
0xF0FD,
|
|
||||||
0xF0FE,
|
|
||||||
0xF0FF,
|
|
||||||
0xF0EF,
|
|
||||||
0xF0DF,
|
|
||||||
0xF0CF,
|
|
||||||
0xF0BF,
|
|
||||||
0xF0AF,
|
|
||||||
0xF09F,
|
|
||||||
0xF08F,
|
|
||||||
0xF07F,
|
|
||||||
0xF06F,
|
|
||||||
0xF05F,
|
|
||||||
0xF04F,
|
|
||||||
0xF03F,
|
|
||||||
0xF02F,
|
|
||||||
0xF01F,
|
|
||||||
0xF00F,
|
|
||||||
0xF10F,
|
|
||||||
0xF20F,
|
|
||||||
0xF30F,
|
|
||||||
0xF40F,
|
|
||||||
0xF50F,
|
|
||||||
0xF60F,
|
|
||||||
0xF70F,
|
|
||||||
0xF80F,
|
|
||||||
0xF90F,
|
|
||||||
0xFA0F,
|
|
||||||
0xFB0F,
|
|
||||||
0xFC0F,
|
|
||||||
0xFD0F,
|
|
||||||
0xFE0F,
|
|
||||||
0xFF0F)
|
|
||||||
val s = "ᚱᛂᚴᛋᛂᛋᛏᛋᚮᚾᛔᚢᛏᛚᚮᛋ᛬ᚱᛂᚴᛋᛋᚢᚼᚾᚢᛘᚢᛚᚾᛏᚮ᛬ᛏᚮᛋᛁᚮᚵᛂᚢᛏᚮᚱᛘᛔᚱᛂᚴᛋᛏ᛭ᛋᚢᚼᚾᚢᛋᛘᚮᛁᚵᚾᛁᛂᛏᚮᛑ᛭ᚵᛂᚢᛏᚮᚱ"
|
|
||||||
var lc = 0
|
|
||||||
var sc = 0
|
|
||||||
|
|
||||||
while (lc < l.size) {
|
|
||||||
print(font.toColorCode(l[lc]))
|
|
||||||
print(s[sc])
|
|
||||||
|
|
||||||
lc++
|
|
||||||
sc++
|
|
||||||
|
|
||||||
if (sc == s.length) break
|
|
||||||
|
|
||||||
if (s[sc] == ' ') {
|
|
||||||
print(" ")
|
|
||||||
sc++
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
println("${font.noColorCode}\nEND")
|
|
||||||
|
|
||||||
println(font.toColorCode(0xF_EEC))
|
|
||||||
|
|
||||||
frameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, TEXW, TEXH, true)
|
frameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, TEXW, TEXH, true)
|
||||||
|
|
||||||
@@ -159,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)
|
||||||
}
|
}
|
||||||
@@ -185,7 +108,8 @@ class FontTestGDX : Game() {
|
|||||||
if (!screenshotExported) {
|
if (!screenshotExported) {
|
||||||
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("demo.PNG"), pixmap)
|
PixmapIO.writePNG(Gdx.files.local(outimageName), pixmap)
|
||||||
|
// writeTGA(Gdx.files.local(outimageName), pixmap, false)
|
||||||
pixmap.dispose()
|
pixmap.dispose()
|
||||||
|
|
||||||
screenshotExported = true
|
screenshotExported = true
|
||||||
@@ -199,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()
|
||||||
@@ -218,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
|
||||||
}
|
}
|
||||||
@@ -247,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 = 2060
|
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)"
|
|
||||||
|
Lwjgl3Application(FontTestGDX(), appConfig)
|
||||||
LwjglApplication(FontTestGDX(), appConfig)
|
|
||||||
}
|
}
|
||||||
|
|||||||
247
FontTestGDX/src/TypewriterGDX.kt
Normal 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)
|
||||||
|
}
|
||||||
@@ -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
|
||||||
|
)
|
||||||
4
LICENSE.md
Normal file → Executable file
@@ -1,6 +1,4 @@
|
|||||||
Terrarum Sans Bitmap
|
Copyright (c) 2017-2022 see CONTRIBUTORS.txt
|
||||||
|
|
||||||
Copyright (c) 2017-2018 Minjae Song (Torvald) and the contributors
|
|
||||||
|
|
||||||
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
BIN
PUA_allocation_chart.xlsx
Normal file → Executable file
20
README.md
Normal file → Executable file
@@ -1,17 +1,18 @@
|
|||||||
# Terrarum Sans Bitmap
|
# Terrarum Sans Bitmap
|
||||||
|
|
||||||

|

|
||||||
|
|
||||||
This font is a bitmap font used in [my game project called Terrarum](https://gitlab.com/minjaesong/terrarum) (hence the name). The font supports more than 90 % of european languages, as well as Chinese, Japanese and Korean. More technical side, it supports Latin-1 Supplement, Latin Ext-A, Latin Ext-B, IPA Extension (required by some languages), Greek, Cyrillic (+ Bulgarian, Serbian variants) and the supplement, Armenian, Thai (beta version), Georgian, Unicode Punctuations, CJK Punctuations, Kana, Chinese (limited to Unihan and Ext-A), Hangul (all 11 172 possible syllables) and Fullwidth forms.
|
This font is a bitmap font used in [my game project called Terrarum](https://github.com/minjaesong/Terrarum) (hence the name). The font supports more than 90 % of european languages, as well as Chinese, Japanese and Korean. More technical side, it supports Latin-1 Supplement, Latin Ext-A/B/C, IPA Extension, Greek, Cyrillic (+ Bulgarian, Serbian variants) and the supplement, Armenian, Devanagari, Bengali, Thai, Georgian (Mkhedruli and Mtavruli), General Punctuations, Super/Subscrips, CJK Punctuations, All of the Kana (minus the Hentaigana), Chinese (limited to Unihan and Ext-A), Hangul (every possible syllables) and Fullwidth forms.
|
||||||
|
|
||||||
The JAR package is meant to be used with Slick2d (extends ```Font``` class) and LibGDX (extends ```BitmapFont``` class). If you are not using the framework, please refer to the __Font metrics__ section to implement the font metrics correctly on your system.
|
The JAR package is meant to be used with LibGDX (extends ```BitmapFont``` class). If you are not using the framework, please refer to the __Font metrics__ section to implement the font metrics correctly on your system.
|
||||||
|
|
||||||
The issue page is open. If you have some issues to submit, or have a question, please leave it on the page.
|
The issue page is open. If you have some issues to submit, or have a question, please leave it on the page.
|
||||||
|
|
||||||
#### Little notes
|
#### Little notes
|
||||||
- To display Bulgarian/Serbian variants, you need special Control Characters. (GameFontBase.charsetOverrideBulgarian -- U+FFFF9; GameFontBase.charsetOverrideSerbian -- U+FFFFA)
|
- To display Bulgarian/Serbian variants, you need special Control Characters. (GameFontBase.charsetOverrideBulgarian -- U+FFFC1; GameFontBase.charsetOverrideSerbian -- U+FFFC2)
|
||||||
- All Han characters are in Chinese variant, no other variants are to be supported as most Chinese, Japanese and Korean can understand other's variant and to be honest, we don't bother anyway.
|
- All Han characters are in Chinese variant, no other variants are to be supported as most Chinese, Japanese and Korean people can understand other's variant and as long as I can, we don't bother anyway.
|
||||||
- Indian script in general is not perfect: this font will never do the proper ligatures (I can't draw all the 1 224 possible combinations). Hopefully it's still be able to understand without them.
|
- Indian script in general is not perfect: right now this font will never do the proper ligatures (I can't draw all the 1 224 possible combinations). Hopefully it's still be able to understand without them.
|
||||||
|
- Slick2d versions are now unsupported. I couldn't extend myself to work on both versions, but I'm still welcome to merge your pull requests.
|
||||||
|
|
||||||
### Design Goals
|
### Design Goals
|
||||||
|
|
||||||
@@ -20,6 +21,9 @@ The issue page is open. If you have some issues to submit, or have a question, p
|
|||||||
- Combininig with the sans-serif, this stands for **no over-simplification**
|
- Combininig with the sans-serif, this stands for **no over-simplification**
|
||||||
- Condensed capitals for efficient space usage
|
- Condensed capitals for efficient space usage
|
||||||
|
|
||||||
|
## Download
|
||||||
|
|
||||||
|
- Go ahead to the [release tab](https://github.com/minjaesong/Terrarum-sans-bitmap/releases), and download the most recent version. It is **not** advised to use the .jar found within the repository, they're experimental builds I use during the development, and may contain bugs like leaking memory.
|
||||||
|
|
||||||
## Using on your game
|
## Using on your game
|
||||||
|
|
||||||
@@ -68,7 +72,7 @@ On your code (Java):
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
### Using on Slick2d
|
### Using on Slick2d (legacy version only)
|
||||||
|
|
||||||
On your code (Kotlin):
|
On your code (Kotlin):
|
||||||
|
|
||||||
@@ -126,4 +130,4 @@ Please refer to [CONTRIBUTING.md](https://github.com/minjaesong/Terrarum-sans-bi
|
|||||||
|
|
||||||
Thanks to kind people of [/r/Typography](https://www.reddit.com/r/typography/) for amazing feedbacks.
|
Thanks to kind people of [/r/Typography](https://www.reddit.com/r/typography/) for amazing feedbacks.
|
||||||
|
|
||||||
CJK Ideographs are powered by [WenQuanYi Font](http://wenq.org/wqy2/index.cgi?BitmapSong). The font is distributed under the GNU GPL version 2. Although, in some countries including where I'm based on, the shapes of typefaces are not copyrightable (the program codes—e.g. TTF—do), we would like to give a credit for the font and the people behind it.
|
CJK Ideographs are powered by [WenQuanYi Font](http://wenq.org/wqy2/index.cgi?BitmapSong). The font is distributed under the GNU GPL version 2. Although the shapes of typefaces are not copyrightable (the program codes—e.g. TTF—do), we would like to give a credit for the font and the people behind it.
|
||||||
|
|||||||
0
alignment_illustration.jpg
Normal file → Executable file
|
Before Width: | Height: | Size: 59 KiB After Width: | Height: | Size: 59 KiB |
|
Before Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 260 KiB |
BIN
assets/ascii_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 131 B |
0
assets/cjkpunct.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
assets/currencies_variable.tga
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
assets/cyrilic_bulgarian_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
BIN
assets/cyrilic_serbian_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
BIN
assets/cyrilic_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 380 KiB After Width: | Height: | Size: 131 B |
BIN
assets/devanagari_bengali_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 131 B |
BIN
assets/diacritical_marks_variable.tga
LFS
Executable file
BIN
assets/enclosed_alphanumeric_supplement_variable.tga
LFS
Normal file
|
Before Width: | Height: | Size: 40 KiB |
0
assets/futhark.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 68 KiB After Width: | Height: | Size: 68 KiB |
BIN
assets/greek_polytonic_xyswap_variable.tga
LFS
Executable file
BIN
assets/greek_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
BIN
assets/halfwidth_fullwidth_variable.tga
LFS
Normal file
|
Before Width: | Height: | Size: 262 KiB After Width: | Height: | Size: 2.6 MiB |
BIN
assets/hayeren_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
|
Before Width: | Height: | Size: 40 KiB |
BIN
assets/internal_variable.tga
LFS
Normal file
BIN
assets/ipa_ext_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
BIN
assets/kana.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 210 KiB After Width: | Height: | Size: 210 KiB |
BIN
assets/kartuli_allcaps_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 130 B |
BIN
assets/kartuli_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 60 KiB After Width: | Height: | Size: 130 B |
BIN
assets/latinExtA_variable.tga
LFS
Executable file
BIN
assets/latinExtB_variable.tga
LFS
Executable file
BIN
assets/latinExtC_variable.tga
Executable file
|
After Width: | Height: | Size: 40 KiB |
BIN
assets/latinExtD_variable.tga
LFS
Normal file
BIN
assets/latinExt_additional_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 131 B |
BIN
assets/letterlike_symbols_variable.tga
LFS
Normal file
BIN
assets/phonetic_extensions_variable.tga
LFS
Normal file
BIN
assets/puae000-e0ff.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 324 KiB After Width: | Height: | Size: 131 B |
BIN
assets/richtext_furigana.tga
Executable file
|
After Width: | Height: | Size: 24 KiB |
BIN
assets/thai_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
BIN
assets/tsalagi_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 131 B |
BIN
assets/typewriter/audio/cr0.wav
LFS
Normal file
BIN
assets/typewriter/audio/cr1.wav
LFS
Normal file
BIN
assets/typewriter/audio/cr2.wav
LFS
Normal file
BIN
assets/typewriter/audio/cr3.wav
LFS
Normal file
BIN
assets/typewriter/audio/cr4.wav
LFS
Normal file
BIN
assets/typewriter/audio/cr5.wav
LFS
Normal file
BIN
assets/typewriter/audio/crlf.wav
LFS
Normal file
BIN
assets/typewriter/audio/deadkey.wav
LFS
Normal file
BIN
assets/typewriter/audio/movingkey.wav
LFS
Normal file
BIN
assets/typewriter/audio/shiftin.wav
LFS
Normal file
BIN
assets/typewriter/audio/shiftout.wav
LFS
Normal file
BIN
assets/typewriter/audio/space.wav
LFS
Normal file
BIN
assets/typewriter/typewriter_intl_qwerty.tga
Normal file
|
After Width: | Height: | Size: 320 KiB |
BIN
assets/typewriter/typewriter_ko_3set-390.tga
Normal file
|
After Width: | Height: | Size: 320 KiB |
BIN
assets/unipunct_variable.tga
Normal file → Executable file
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 200 KiB |
0
assets/wenquanyi.tga.gz
Normal file → Executable file
BIN
demo.PNG
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 151 KiB |
65
FontTestGDX/demotext.txt → demotext.txt
Normal file → Executable 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, it’s ugly.”
|
“Well, better than nothing… no, it’s 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, it's not even multilingual, and their English look uncanny and inconsistent as hell.
|
Japanese, it’s 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.
|
||||||
|
|
||||||
@@ -26,25 +27,26 @@ How multilingual? Real multilingual!
|
|||||||
գրիչս վայր դրի, վեր կացա և պատրաստվում էի, որ քնեմ, երբ հանկարծ դռանս զանգակը հնչեց
|
գրիչս վայր դրի, վեր կացա և պատրաստվում էի, որ քնեմ, երբ հանկարծ դռանս զանգակը հնչեց
|
||||||
ՄՇԱԿԻՉ ԿԱՄ ԿԵՆՏՐՈՆԱԿԱՆ ՄՇԱԿԻՉ ՀԱՆԳՈՒՅՑԸ ՀԱՆԴԻՍԱՆՈՒՄ Է ՀԱՄԱԿԱՐԳՉԻ ՍԱՐՔԱՎՈՐՈՒՄՆԵՐԻՑ
|
ՄՇԱԿԻՉ ԿԱՄ ԿԵՆՏՐՈՆԱԿԱՆ ՄՇԱԿԻՉ ՀԱՆԳՈՒՅՑԸ ՀԱՆԴԻՍԱՆՈՒՄ Է ՀԱՄԱԿԱՐԳՉԻ ՍԱՐՔԱՎՈՐՈՒՄՆԵՐԻՑ
|
||||||
Zəfər, jaketini də papağını da götür, bu axşam hava çox soyuq olacaq
|
Zəfər, jaketini də papağını da götür, bu axşam hava çox soyuq olacaq
|
||||||
Под южно дърво, цъфтящо в синьо, бягаше малко пухкаво зайче
|
আমি কাঁচ খেতে পারি, তাতে আমার কোনো ক্ষতি হয় না।
|
||||||
|
Под южно дърво, цъфтящо в синьо, бягаше малко пухкаво зайче
|
||||||
ᎠᏍᎦᏯᎡᎦᎢᎾᎨᎢᎣᏍᏓᎤᎩᏍᏗᎥᎴᏓᎯᎲᎢᏔᎵᏕᎦᏟᏗᏖᎸᎳᏗᏗᎧᎵᎢᏘᎴᎩ ᏙᏱᏗᏜᏫᏗᏣᏚᎦᏫᏛᏄᏓᎦᏝᏃᎠᎾᏗᎭᏞᎦᎯᎦᏘᏓᏠᎨᏏᏕᏡᎬᏢᏓᏥᏩᏝᎡᎢᎪᎢ
|
ᎠᏍᎦᏯᎡᎦᎢᎾᎨᎢᎣᏍᏓᎤᎩᏍᏗᎥᎴᏓᎯᎲᎢᏔᎵᏕᎦᏟᏗᏖᎸᎳᏗᏗᎧᎵᎢᏘᎴᎩ ᏙᏱᏗᏜᏫᏗᏣᏚᎦᏫᏛᏄᏓᎦᏝᏃᎠᎾᏗᎭᏞᎦᎯᎦᏘᏓᏠᎨᏏᏕᏡᎬᏢᏓᏥᏩᏝᎡᎢᎪᎢ
|
||||||
ᎠᎦᏂᏗᎮᎢᎫᎩᎬᏩᎴᎢᎠᏆᏅᏛᎫᏊᎾᎥᎠᏁᏙᎲᏐᏈᎵᎤᎩᎸᏓᏭᎷᏤᎢᏏᏉᏯᏌᏊ ᎤᏂᏋᎢᏡᎬᎢᎰᏩᎬᏤᎵᏍᏗᏱᎩᎱᎱᎤᎩᎴᎢᏦᎢᎠᏂᏧᏣᏨᎦᏥᎪᎥᏌᏊᎤᎶᏒᎢᎢᏡᎬᎢ
|
ᎠᎦᏂᏗᎮᎢᎫᎩᎬᏩᎴᎢᎠᏆᏅᏛᎫᏊᎾᎥᎠᏁᏙᎲᏐᏈᎵᎤᎩᎸᏓᏭᎷᏤᎢᏏᏉᏯᏌᏊ ᎤᏂᏋᎢᏡᎬᎢᎰᏩᎬᏤᎵᏍᏗᏱᎩᎱᎱᎤᎩᎴᎢᏦᎢᎠᏂᏧᏣᏨᎦᏥᎪᎥᏌᏊᎤᎶᏒᎢᎢᏡᎬᎢ
|
||||||
ᎹᎦᎺᎵᏥᎻᎼᏏᎽᏗᏩᏂᎦᏘᎾᎿᎠᏁᎬᎢᏅᎩᎾᏂᎡᎢᏌᎶᎵᏎᎷᎠᏑᏍᏗᏪᎩ ᎠᎴ ᏬᏗᏲᏭᎾᏓᏍᏓᏴᏁᎢᎤᎦᏅᏮᏰᎵᏳᏂᎨᎢ
|
ᎹᎦᎺᎵᏥᎻᎼᏏᎽᏗᏩᏂᎦᏘᎾᎿᎠᏁᎬᎢᏅᎩᎾᏂᎡᎢᏌᎶᎵᏎᎷᎠᏑᏍᏗᏪᎩ ᎠᎴ ᏬᏗᏲᏭᎾᏓᏍᏓᏴᏁᎢᎤᎦᏅᏮᏰᎵᏳᏂᎨᎢ
|
||||||
Příliš žluťoučký kůň úpěl ďábelské ódy
|
Příliš žluťoučký kůň úpěl ďábelské ódy
|
||||||
Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Walther spillede på xylofon
|
Quizdeltagerne spiste jordbær med fløde, mens cirkusklovnen Walther spillede på xylofon
|
||||||
PACK MY BOX WITH FIVE DOZEN LIQUOR JUGS
|
PACK MY BOX WITH FIVE DOZEN LIQUOR JUGS
|
||||||
|
hƿæt ƿe ᵹardena inᵹear ꝺaᵹum þeoꝺ cynninᵹa þꞃym ᵹeꝼꞃumon
|
||||||
Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich GROẞEN GROẞE
|
Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich GROẞEN GROẞE
|
||||||
ζαφείρι δέξου πάγκαλο, βαθων ψυχης το σημα
|
ζαφείρι δέξου πάγκαλο, βαθῶν ψυχῆς τὸ σῆμα
|
||||||
ΔΙΑΦΥΛΆΞΤΕ ΓΕΝΙΚΆ ΤΗ ΖΩΉ ΣΑΣ ΑΠΌ ΒΑΘΕΙΆ ΨΥΧΙΚΆ ΤΡΑΎΜΑΤΑ
|
ΔΙΑΦΥΛΆΞΤΕ ΓΕΝΙΚΆ ΤΗ ΖΩΉ ΣΑΣ ΑΠΌ ΒΑΘΕΙΆ ΨΥΧΙΚΆ ΤΡΑΎΜΑΤΑ
|
||||||
სწრაფი ყავისფერი მელა გადაახტა ზარმაც ძაღლს ᲘᲜᲢᲔᲚ ᲞᲔᲜᲢᲘᲣᲛᲘ ᲛᲘᲙᲠᲝᲞᲠᲝᲪᲔᲡᲝᲠᲘ
|
სწრაფი ყავისფერი მელა გადაახტა ზარმაც ძაღლს ᲘᲜᲢᲔᲚ ᲞᲔᲜᲢᲘᲣᲛᲘ ᲛᲘᲙᲠᲝᲞᲠᲝᲪᲔᲡᲝᲠᲘ
|
||||||
ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम अयोध्या के महाराज दशरथ के
|
ऋषियों को सताने वाले दुष्ट राक्षसों के राजा रावण का सर्वनाश करने वाले विष्णुवतार भगवान श्रीराम अयोध्या के महाराज दशरथ के
|
||||||
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
|
||||||
Ꝺꝼuaꞅcail Íoꞅa Úꞃṁac na hÓiᵹe Beannaiꞇe póꞃ Éaḃa aᵹus Áꝺaiṁ
|
Ċuaiġ bé ṁórṡáċ le dlúṫspád fíoꝛḟinn trí hata mo ḋea-ṗoꝛcáin ḃig
|
||||||
Ċuaiġ bé ṁórṡáċ le dlúṫspád fíorḟinn trí hata mo ḋea-ṗorcáin ḃig
|
|
||||||
あめつちほしそら やまかはみねたに くもきりむろこけ ひといぬうへすゑ ゆわさるおふせよ えの𛀁をなれゐて
|
あめつちほしそら やまかはみねたに くもきりむろこけ ひといぬうへすゑ ゆわさるおふせよ えの𛀁をなれゐて
|
||||||
トリナクコヱス ユメサマセ ミヨアケワタル ヒンカシヲ ソライロハエテ オキツヘニ ホフネムレヰヌ モヤノウチ
|
トリナクコヱス ユメサマセ ミヨアケワタル ヒンカシヲ ソライロハエテ オキツヘニ ホフネムレヰヌ モヤノウチ
|
||||||
田居に出で 菜摘むわれをぞ 君召すと 求食り追ひゆく 山城の 打酔へる子ら 藻葉干せよ え舟繋けぬ
|
田居に出で 菜摘むわれをぞ 君召すと 求食り追ひゆく 山城の 打酔へる子ら 藻葉干せよ え舟繋けぬ
|
||||||
정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날 하얬다 도럄직한 퀡봹퉪헰
|
정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날 하얬다 도럄직한 퀡봹퉪헰ꥸᅦퟗꥸᅦퟗᄋힳᆫㅗㅜㅑㄷ
|
||||||
Četri psihi faķīri vēlu vakarā zāģēja guļbūvei durvis, fonā šņācot mežam
|
Četri psihi faķīri vēlu vakarā zāģēja guļbūvei durvis, fonā šņācot mežam
|
||||||
Įlinkdama fechtuotojo špaga sublykčiojusi pragręžė apvalų arbūzą
|
Įlinkdama fechtuotojo špaga sublykčiojusi pragręžė apvalų arbūzą
|
||||||
Ѕидарски пејзаж: шугав билмез со чудење џвака ќофте и кељ на туѓ цех
|
Ѕидарски пејзаж: шугав билмез со чудење џвака ќофте и кељ на туѓ цех
|
||||||
@@ -53,13 +55,14 @@ How multilingual? Real multilingual!
|
|||||||
कः खगौघाङचिच्छौजा झाञ्ज्ञोऽटौठीडडण्ढणः। तथोदधीन् पफर्बाभीर्मयोऽरिल्वाशिषां सहः॥
|
कः खगौघाङचिच्छौजा झाञ्ज्ञोऽटौठीडडण्ढणः। तथोदधीन् पफर्बाभीर्मयोऽरिल्वाशिषां सहः॥
|
||||||
Înjurând pițigăiat, zoofobul comandă vexat whisky și tequila
|
Înjurând pițigăiat, zoofobul comandă vexat whisky și tequila
|
||||||
Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства
|
Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства
|
||||||
Ајшо, лепото и чежњо, за љубав срца мога дођи у Хаџиће на кафу
|
Ајшо, лепото и чежњо, за љубав срца мога дођи у Хаџиће на кафу
|
||||||
Jovencillo emponzoñado de whisky: ¡qué figurota exhibe!
|
Jovencillo emponzoñado de whisky: ¡qué figurota exhibe!
|
||||||
นายสังฆภัณฑ์ เฮงพิทักษ์ฝั่ง ผู้เฒ่าซึ่งมีอาชีพเป็นฅนขายฃวด ถูกตำรวจปฏิบัติการจับฟ้องศาล ฐานลักนาฬิกาคุณหญิงฉัตรชฎา ฌานสมาธิ
|
นายสังฆภัณฑ์ เฮงพิทักษ์ฝั่ง ผู้เฒ่าซึ่งมีอาชีพเป็นฅนขายฃวด ถูกตำรวจปฏิบัติการจับฟ้องศาล ฐานลักนาฬิกาคุณหญิงฉัตรชฎา ฌานสมาธิ
|
||||||
Pijamalı hasta yağız şoföre çabucak güvendi
|
Pijamalı hasta yağız şoföre çabucak güvendi
|
||||||
Жебракують філософи при ґанку церкви в Гадячі, ще й шатро їхнє п’яне знаємо
|
Жебракують філософи при ґанку церкви в Гадячі, ще й шатро їхнє п’яне знаємо
|
||||||
Do bạch kim rất quý nên sẽ dùng để lắp vô xương
|
Do bạch kim rất quý nên sẽ dùng để lắp vô xương
|
||||||
日堀油告観観藤村抄海評業庁経賃室弁市。太撮収改売週法所何都慣次現。価紙一無三洋日話転手治稿載末替付致治。
|
日堀油告観観藤村抄海評業庁経賃室弁市。太撮収改売週法所何都慣次現。価紙一無三洋日話転手治稿載末替付致治。
|
||||||
|
[pʰnɣɬɥi.m͡ŋχɫʍɨnaɸ.cθʊɫɯ.ɹɨɫʏ͡ɛx.ɯ͡ɣaxɲaɣɫ.ɸtʰɑɣɴ]
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
|
||||||
@@ -74,10 +77,10 @@ How multilingual? Real multilingual!
|
|||||||
|
|
||||||
ᚱᛂᚴᛋᛂᛋᛏᛋᚮᚾᛔᚢᛏᛚᚮᛋ᛬ᚱᛂᚴᛋᛋᚢᚼᚾᚢᛘᚢᛚᚾᛏᚮ᛬ᛏᚮᛋᛁᚮᚵᛂᚢᛏᚮᚱᛘᛔᚱᛂᚴᛋᛏ᛭ᛋᚢᚼᚾᚢᛋᛘᚮᛁᚵᚾᛁᛂᛏᚮᛑ᛭ᚵᛂᚢᛏᚮᚱ
|
ᚱᛂᚴᛋᛂᛋᛏᛋᚮᚾᛔᚢᛏᛚᚮᛋ᛬ᚱᛂᚴᛋᛋᚢᚼᚾᚢᛘᚢᛚᚾᛏᚮ᛬ᛏᚮᛋᛁᚮᚵᛂᚢᛏᚮᚱᛘᛔᚱᛂᚴᛋᛏ᛭ᛋᚢᚼᚾᚢᛋᛘᚮᛁᚵᚾᛁᛂᛏᚮᛑ᛭ᚵᛂᚢᛏᚮᚱ
|
||||||
|
|
||||||
Colour-code that supports 65535 opaque or semi-transparent colours via 4 bit ARGB
|
Colour-code that supports 4096 colours via 4 bit RGB
|
||||||
|
|
||||||
Гномът Доцьо приключи спящ в шейна за жаби (Bulgarian)
|
Щиглецът се яде само пържен в юфка без чушки и хвойна (Bulgarian)
|
||||||
Љубазни фењерџија чађавог лица хоће да ми покаже штос (Serbian)
|
Љубазни фењерџија чађавог лица хоће да ми покаже штос (Serbian)
|
||||||
Разъяренный чтец эгоистично бьёт пятью жердями шустрого фехтовальщика (Russian)
|
Разъяренный чтец эгоистично бьёт пятью жердями шустрого фехтовальщика (Russian)
|
||||||
|
|
||||||
Control characters to support Bulgarian and Serbian letter shapes on the fly
|
Control characters to support Bulgarian and Serbian letter shapes on the fly
|
||||||
@@ -90,13 +93,35 @@ How multilingual? Real multilingual!
|
|||||||
|
|
||||||
For all those dash-pedants, we have en-dash, em-dash, and even horizontal bars!
|
For all those dash-pedants, we have en-dash, em-dash, and even horizontal bars!
|
||||||
|
|
||||||
Unicode References:
|
5¹⁹⁄₃₂ inch is 142.1 mm · (C₂F₄)ₙ is godly · Error = MoreCode²
|
||||||
|
NOTE: we don’t do fractions. 142¹⁄₁₀ mm is illegal!
|
||||||
|
|
||||||
Basic Latin Latin-1 Latin Extension A Latin Extionsion B IPA Extension Greek Cyrillic
|
Did you know Unicode supports arbitrary fractions? Actually I didn’t… as they abused super/subscripts!
|
||||||
Cyrillic Supplement Armenian Devanagari Thai Georgian Runic Cherokee Georgian Extended
|
|
||||||
General Punctuations CJK Symbols Kana Kana Phonetic Extension CJK Unihan Extension A CJK Unihan
|
ᄋᆡ급 일 ᄭᅡᄃᆞᆰ에 영국 ᄒᆞ고 불난셔 ᄒᆞ고 ᄃᆡ단이 시비가 잇슬 모양 인ᄃᆡ
|
||||||
Hangul Syllables Fullwidth Forms Kana Supplement
|
일본 농샹공부에셔 젼긔학 학ᄉᆞ 셋ᄉᆞᆯ 미국과 구라파로 보내셔 젼화 쓰ᄂᆞᆫ 법을 더ᄇᆡ호게 ᄒᆞ더라
|
||||||
|
일쳔 구ᄇᆡᆨ년에 불난셔 셔울 파리스에 만국 박남회를 버릴터 인ᄃᆡ 각국이 다 물화와 졔조품을 거긔 보낼터이더라
|
||||||
|
|
||||||
|
Rejoice, now we can render Old Korean in a correct way!
|
||||||
|
|
||||||
|
Supported Unicode Blocks:
|
||||||
|
|
||||||
|
Basic Latin Latin-1 Supplement Latin Extended-A Latin Extended-B IPA Extensions
|
||||||
|
Spacing Modifier Letters Combining Diacritical Marks Greek and Copticᴱ Cyrillicᴭ Cyrillic Supplementᴭ
|
||||||
|
Armenian Devanagariᶠⁱ Bengaliᶠⁱ Thai Georgianჼ Hangul Jamo Cherokee⁷ Runic Georgian Extended
|
||||||
|
Phonetic Extensions Phonetic Extensions Supplement Latin Extended Additional Greek Extended
|
||||||
|
General Punctuations Superscripts and Subscripts Currency Symbols Letterlike Symbols
|
||||||
|
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
|
||||||
|
|
||||||
GitHub’s issue page is open! You can report any errors, or leave suggestions.
|
GitHub’s 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
|
||||||
changes, and make a pull request! I appreciate any and all supports.
|
changes, and make a pull request! I appreciate any and all supports.
|
||||||
|
|
||||||
|
<EFBFBD> 文字化け! <20>
|
||||||
0
font_drawing_template.png
Normal file → Executable 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
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 1.1 KiB |
108
keming_machine.txt
Normal 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
0
samples/wikipedia_x86.png
Normal file → Executable file
|
Before Width: | Height: | Size: 75 KiB After Width: | Height: | Size: 75 KiB |
130
src/net/torvald/terrarumsansbitmap/GlyphProps.kt
Normal file → Executable file
@@ -1,30 +1,128 @@
|
|||||||
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 diacriticsStackDown: Boolean = false,
|
|
||||||
val diacriticsBeforeGlyph: Boolean = false
|
|
||||||
) {
|
) {
|
||||||
companion object {
|
companion object {
|
||||||
const val LEFT = 0
|
const val ALIGN_LEFT = 0
|
||||||
const val RIGHT = 1
|
const val ALIGN_RIGHT = 1
|
||||||
const val CENTRE = 2
|
const val ALIGN_CENTRE = 2
|
||||||
|
const val ALIGN_BEFORE = 3
|
||||||
|
|
||||||
|
const val STACK_UP = 0
|
||||||
|
const val STACK_DOWN = 1
|
||||||
|
const val STACK_BEFORE_N_AFTER = 2
|
||||||
|
const val STACK_UP_N_DOWN = 3
|
||||||
|
|
||||||
|
const val DIA_OVERLAY = 2
|
||||||
|
// const val DIA_JOINER = 2
|
||||||
|
|
||||||
|
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(1) == 1,
|
tags.ushr(8).and(3),
|
||||||
tags.ushr(5).and(3) == 3
|
tags.and(1) == 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 {
|
||||||
|
val tags = rtl.toInt() or alignWhere.shl(5) or
|
||||||
|
writeOnTop.toInt().shl(7) or stackWhere.shl(8)
|
||||||
|
|
||||||
|
var hash = -2128831034
|
||||||
|
|
||||||
|
extInfo.forEach {
|
||||||
|
hash = hash xor it
|
||||||
|
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 * 167677619
|
||||||
|
|
||||||
|
return hash
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean {
|
||||||
|
// comparing hash because I'm lazy
|
||||||
|
return other is GlyphProps && this.hashCode() == other.hashCode()
|
||||||
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
164
src/net/torvald/terrarumsansbitmap/gdx/PixmapRegionPack.kt
Executable file
@@ -0,0 +1,164 @@
|
|||||||
|
/*
|
||||||
|
* Terrarum Sans Bitmap
|
||||||
|
*
|
||||||
|
* Copyright (c) 2017-2021 Minjae Song (Torvald)
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package net.torvald.terrarumsansbitmap.gdx
|
||||||
|
|
||||||
|
import com.badlogic.gdx.files.FileHandle
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Breaks one pixmap atlas into many child pixmaps
|
||||||
|
*
|
||||||
|
* Created by minjaesong on 2018-09-17.
|
||||||
|
*/
|
||||||
|
class PixmapRegionPack(
|
||||||
|
pixmapAtlas: Pixmap,
|
||||||
|
val tileW: Int,
|
||||||
|
val tileH: Int,
|
||||||
|
val hGap: Int = 0,
|
||||||
|
val vGap: Int = 0,
|
||||||
|
val hFrame: Int = 0,
|
||||||
|
val vFrame: Int = 0,
|
||||||
|
val xySwapped: Boolean = false // because Unicode chart does, duh
|
||||||
|
) {
|
||||||
|
|
||||||
|
//constructor(ref: String, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0, xySwapped: Boolean = false) :
|
||||||
|
// this(Pixmap(ref), tileW, tileH, hGap, vGap, hFrame, vFrame, xySwapped)
|
||||||
|
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)
|
||||||
|
|
||||||
|
val horizontalCount = (pixmapAtlas.width - 2 * hFrame + hGap) / (tileW + hGap)
|
||||||
|
val verticalCount = (pixmapAtlas.height - 2 * vFrame + vGap) / (tileH + vGap)
|
||||||
|
|
||||||
|
val regions: Array<Pixmap>
|
||||||
|
|
||||||
|
init {
|
||||||
|
// test print the whole sheet
|
||||||
|
/*pixmap.pixels.rewind()
|
||||||
|
for (y in 0 until pixmap.height) {
|
||||||
|
for (x in 0 until pixmap.width) {
|
||||||
|
pixmap.pixels.get() // discard r
|
||||||
|
pixmap.pixels.get() // discard g
|
||||||
|
pixmap.pixels.get() // discard b
|
||||||
|
val a = pixmap.pixels.get()
|
||||||
|
|
||||||
|
if (a == 255.toByte()) print("█") else print("·")
|
||||||
|
}
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
println()*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pixmapAtlas.pixels.rewind()
|
||||||
|
|
||||||
|
if (!xySwapped) {
|
||||||
|
regions = Array<Pixmap>(horizontalCount * verticalCount) {
|
||||||
|
val rx = (it % horizontalCount * (tileW + hGap)) + hFrame // pixel, not index
|
||||||
|
val ry = (it / horizontalCount * (tileH + vGap)) + vFrame // pixel, not index
|
||||||
|
|
||||||
|
val region = Pixmap(tileW, tileH, Pixmap.Format.RGBA8888)
|
||||||
|
region.pixels.rewind()
|
||||||
|
|
||||||
|
|
||||||
|
// for every "scanline"
|
||||||
|
for (y in 0 until tileH) {
|
||||||
|
|
||||||
|
val offsetY = (ry + y) * (pixmapAtlas.width * 4) + (vFrame * pixmapAtlas.width * 4)
|
||||||
|
val offsetX = rx * 4 + hFrame * 4
|
||||||
|
|
||||||
|
//println("offset: ${offsetX + offsetY}")
|
||||||
|
|
||||||
|
val bytesBuffer = ByteArray(4 * tileW)
|
||||||
|
|
||||||
|
pixmapAtlas.pixels.position(offsetY + offsetX)
|
||||||
|
pixmapAtlas.pixels.get(bytesBuffer, 0, bytesBuffer.size)
|
||||||
|
|
||||||
|
// test print bytesbuffer
|
||||||
|
/*bytesBuffer.forEachIndexed { index, it ->
|
||||||
|
if (index % 4 == 3) {
|
||||||
|
if (it == 255.toByte()) print("█") else print("·")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println()*/
|
||||||
|
|
||||||
|
region.pixels.put(bytesBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
//println()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*return*/region
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
regions = Array<Pixmap>(horizontalCount * verticalCount) {
|
||||||
|
val rx = (it / verticalCount * (tileW + hGap)) + hFrame
|
||||||
|
val ry = (it % verticalCount * (tileH + vGap)) + vFrame
|
||||||
|
|
||||||
|
val region = Pixmap(tileW, tileH, Pixmap.Format.RGBA8888)
|
||||||
|
region.pixels.rewind()
|
||||||
|
|
||||||
|
|
||||||
|
// for every "scanline"
|
||||||
|
for (y in 0 until tileH) {
|
||||||
|
|
||||||
|
val offsetY = (ry + y) * (pixmapAtlas.width * 4) + (vFrame * pixmapAtlas.width * 4)
|
||||||
|
val offsetX = rx * 4 + hFrame * 4
|
||||||
|
|
||||||
|
//println("offset: ${offsetX + offsetY}")
|
||||||
|
|
||||||
|
val bytesBuffer = ByteArray(4 * tileW)
|
||||||
|
|
||||||
|
pixmapAtlas.pixels.position(offsetY + offsetX)
|
||||||
|
pixmapAtlas.pixels.get(bytesBuffer, 0, bytesBuffer.size)
|
||||||
|
|
||||||
|
// test print bytesbuffer
|
||||||
|
/*bytesBuffer.forEachIndexed { index, it ->
|
||||||
|
if (index % 4 == 3) {
|
||||||
|
if (it == 255.toByte()) print("█") else print("·")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
println()*/
|
||||||
|
|
||||||
|
region.pixels.put(bytesBuffer)
|
||||||
|
}
|
||||||
|
|
||||||
|
//println()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*return*/region
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun get(x: Int, y: Int) = regions[y * horizontalCount + x]
|
||||||
|
|
||||||
|
fun dispose() {
|
||||||
|
regions.forEach { it.dispose() }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
1959
src/net/torvald/terrarumsansbitmap/gdx/TerrarumSansBitmap.kt
Executable file
59
src/net/torvald/terrarumsansbitmap/gdx/TextureRegionPack.kt
Normal file → Executable 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
|
||||||
@@ -27,6 +27,7 @@ package net.torvald.terrarumsansbitmap.gdx
|
|||||||
import com.badlogic.gdx.files.FileHandle
|
import com.badlogic.gdx.files.FileHandle
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.graphics.Texture
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by minjaesong on 2017-06-15.
|
* Created by minjaesong on 2017-06-15.
|
||||||
@@ -38,17 +39,19 @@ class TextureRegionPack(
|
|||||||
val hGap: Int = 0,
|
val hGap: Int = 0,
|
||||||
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 flipX: Boolean = false,
|
||||||
|
val flipY: Boolean = false
|
||||||
|
): Disposable {
|
||||||
|
|
||||||
constructor(ref: String, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0) :
|
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)
|
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) :
|
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)
|
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>
|
||||||
@@ -59,23 +62,41 @@ class TextureRegionPack(
|
|||||||
init {
|
init {
|
||||||
//println("texture: $texture, dim: ${texture.width} x ${texture.height}, grid: $horizontalCount x $verticalCount, cellDim: $tileW x $tileH")
|
//println("texture: $texture, dim: ${texture.width} x ${texture.height}, grid: $horizontalCount x $verticalCount, cellDim: $tileW x $tileH")
|
||||||
|
|
||||||
regions = Array<TextureRegion>(horizontalCount * verticalCount, {
|
if (!xySwapped) {
|
||||||
val region = TextureRegion()
|
regions = Array<TextureRegion>(horizontalCount * verticalCount) {
|
||||||
val rx = (it % horizontalCount * (tileW + hGap)) + hFrame
|
val region = TextureRegion()
|
||||||
val ry = (it / horizontalCount * (tileH + vGap)) + vFrame
|
val rx = (it % horizontalCount * (tileW + hGap)) + hFrame
|
||||||
|
val ry = (it / horizontalCount * (tileH + vGap)) + vFrame
|
||||||
|
|
||||||
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
|
||||||
})
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
regions = Array<TextureRegion>(horizontalCount * verticalCount) {
|
||||||
|
val region = TextureRegion()
|
||||||
|
val rx = (it / verticalCount * (tileW + hGap)) + hFrame
|
||||||
|
val ry = (it % verticalCount * (tileH + vGap)) + vFrame
|
||||||
|
|
||||||
|
region.setRegion(texture)
|
||||||
|
region.setRegion(rx, ry, tileW, tileH)
|
||||||
|
|
||||||
|
region.flip(flipX, flipY)
|
||||||
|
|
||||||
|
/*return*/region
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun get(x: Int, y: Int) = regions[y * horizontalCount + x]
|
fun get(x: Int, y: Int) = regions[y * horizontalCount + x]
|
||||||
|
|
||||||
fun dispose() {
|
fun forEach(action: (TextureRegion) -> Unit) = regions.forEach(action)
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
texture.dispose()
|
texture.dispose()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
0
src/net/torvald/terrarumsansbitmap/readme.md
Normal file → Executable file
@@ -1,790 +0,0 @@
|
|||||||
/*
|
|
||||||
* Terrarum Sans Bitmap
|
|
||||||
*
|
|
||||||
* Copyright (c) 2017 Minjae Song (Torvald)
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in all
|
|
||||||
* copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package net.torvald.terrarumsansbitmap.slick2d
|
|
||||||
|
|
||||||
/*import net.torvald.terrarumsansbitmap.gdx.GameFontBase
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.JUNG_COUNT
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.JONG_COUNT
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.W_ASIAN_PUNCT
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.W_HANGUL
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.W_KANA
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.W_UNIHAN
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.W_LATIN_WIDE
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.W_VAR_INIT
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.HGAP_VAR
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.H
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.H_UNIHAN
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SIZE_CUSTOM_SYM
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_ASCII_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_HANGUL
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_EXTA_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_EXTB_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_KANA
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_CJK_PUNCT
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_UNIHAN
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_CYRILIC_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_FW_UNI
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_UNI_PUNCT_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_GREEK_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_THAI_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_HAYEREN_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_KARTULI_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_IPA_VARW
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_CUSTOM_SYM
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_UNKNOWN
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_RUNIC
|
|
||||||
import net.torvald.terrarumsansbitmap.gdx.GameFontBase.Companion.SHEET_LATIN_EXT_ADD_VARW
|
|
||||||
import org.newdawn.slick.Color
|
|
||||||
import org.newdawn.slick.Font
|
|
||||||
import org.newdawn.slick.Image
|
|
||||||
import org.newdawn.slick.SpriteSheet
|
|
||||||
import org.newdawn.slick.opengl.Texture
|
|
||||||
import java.io.BufferedOutputStream
|
|
||||||
import java.io.File
|
|
||||||
import java.io.FileInputStream
|
|
||||||
import java.io.FileOutputStream
|
|
||||||
import java.util.*
|
|
||||||
import java.util.zip.GZIPInputStream
|
|
||||||
|
|
||||||
/**
|
|
||||||
* LibGDX->Slick2D back-port of Terrarum Sans Bitmap implementation
|
|
||||||
*
|
|
||||||
* Filename and Extension for the spritesheet is hard-coded, which are:
|
|
||||||
*
|
|
||||||
* - ascii_variable.tga
|
|
||||||
* - hangul_johab.tga
|
|
||||||
* - LatinExtA_variable.tga
|
|
||||||
* - LatinExtB_variable.tga
|
|
||||||
* - kana.tga
|
|
||||||
* - cjkpunct.tga
|
|
||||||
* - wenquanyi.tga.gz
|
|
||||||
* - cyrillic_variable.tga
|
|
||||||
* - fullwidth_forms.tga
|
|
||||||
* - unipunct_variable.tga
|
|
||||||
* - greek_variable.tga
|
|
||||||
* - thai_variable.tga
|
|
||||||
* - puae000-e0ff.tga
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* Glyphs are drawn lazily (calculated on-the-fly, rather than load up all), which is inevitable as we just can't load
|
|
||||||
* up 40k+ characters on the machine, which will certainly make loading time painfully long.
|
|
||||||
*
|
|
||||||
* Color Codes have following Unicode mapping: U+10RGBA, A must be non-zero to be visible. U+100000 reverts any colour code effects.
|
|
||||||
*
|
|
||||||
* @param noShadow Self-explanatory
|
|
||||||
* @param flipY If you have Y-down coord system implemented on your GDX (e.g. legacy codebase), set this to ```true``` so that the shadow won't be upside-down. For glyph getting upside-down, set ```TextureRegionPack.globalFlipY = true```.
|
|
||||||
*
|
|
||||||
* Created by minjaesong on 2017-06-15.
|
|
||||||
*/
|
|
||||||
class GameFontBase(fontDir: String, val noShadow: Boolean = false) : Font {
|
|
||||||
|
|
||||||
private fun getHanChosung(hanIndex: Int) = hanIndex / (JUNG_COUNT * JONG_COUNT)
|
|
||||||
private fun getHanJungseong(hanIndex: Int) = hanIndex / JONG_COUNT % JUNG_COUNT
|
|
||||||
private fun getHanJongseong(hanIndex: Int) = hanIndex % JONG_COUNT
|
|
||||||
|
|
||||||
private val jungseongWide = arrayOf(8, 12, 13, 17, 18, 21)
|
|
||||||
private val jungseongComplex = arrayOf(9, 10, 11, 14, 15, 16, 22)
|
|
||||||
|
|
||||||
private fun isJungseongWide(hanIndex: Int) = jungseongWide.contains(getHanJungseong(hanIndex))
|
|
||||||
private fun isJungseongComplex(hanIndex: Int) = jungseongComplex.contains(getHanJungseong(hanIndex))
|
|
||||||
|
|
||||||
private fun getHanInitialRow(hanIndex: Int): Int {
|
|
||||||
val ret: Int
|
|
||||||
|
|
||||||
if (isJungseongWide(hanIndex))
|
|
||||||
ret = 2
|
|
||||||
else if (isJungseongComplex(hanIndex))
|
|
||||||
ret = 4
|
|
||||||
else
|
|
||||||
ret = 0
|
|
||||||
|
|
||||||
return if (getHanJongseong(hanIndex) == 0) ret else ret + 1
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getHanMedialRow(hanIndex: Int) = if (getHanJongseong(hanIndex) == 0) 6 else 7
|
|
||||||
|
|
||||||
private fun getHanFinalRow(hanIndex: Int): Int {
|
|
||||||
val jungseongIndex = getHanJungseong(hanIndex)
|
|
||||||
|
|
||||||
return if (jungseongWide.contains(jungseongIndex))
|
|
||||||
8
|
|
||||||
else
|
|
||||||
9
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun isHangul(c: Char) = c.toInt() in codeRange[SHEET_HANGUL]
|
|
||||||
private fun isAscii(c: Char) = c.toInt() in codeRange[SHEET_ASCII_VARW]
|
|
||||||
private fun isRunic(c: Char) = c.toInt() in codeRange[SHEET_RUNIC]
|
|
||||||
private fun isExtA(c: Char) = c.toInt() in codeRange[SHEET_EXTA_VARW]
|
|
||||||
private fun isExtB(c: Char) = c.toInt() in codeRange[SHEET_EXTB_VARW]
|
|
||||||
private fun isKana(c: Char) = c.toInt() in codeRange[SHEET_KANA]
|
|
||||||
private fun isCJKPunct(c: Char) = c.toInt() in codeRange[SHEET_CJK_PUNCT]
|
|
||||||
private fun isUniHan(c: Char) = c.toInt() in codeRange[SHEET_UNIHAN]
|
|
||||||
private fun isCyrilic(c: Char) = c.toInt() in codeRange[SHEET_CYRILIC_VARW]
|
|
||||||
private fun isFullwidthUni(c: Char) = c.toInt() in codeRange[SHEET_FW_UNI]
|
|
||||||
private fun isUniPunct(c: Char) = c.toInt() in codeRange[SHEET_UNI_PUNCT_VARW]
|
|
||||||
private fun isGreek(c: Char) = c.toInt() in codeRange[SHEET_GREEK_VARW]
|
|
||||||
private fun isThai(c: Char) = c.toInt() in codeRange[SHEET_THAI_VARW]
|
|
||||||
private fun isDiacritics(c: Char) = c.toInt() in 0xE34..0xE3A
|
|
||||||
|| c.toInt() in 0xE47..0xE4E
|
|
||||||
|| c.toInt() == 0xE31
|
|
||||||
private fun isCustomSym(c: Char) = c.toInt() in codeRange[SHEET_CUSTOM_SYM]
|
|
||||||
private fun isArmenian(c: Char) = c.toInt() in codeRange[SHEET_HAYEREN_VARW]
|
|
||||||
private fun isKartvelian(c: Char) = c.toInt() in codeRange[SHEET_KARTULI_VARW]
|
|
||||||
private fun isIPA(c: Char) = c.toInt() in codeRange[SHEET_IPA_VARW]
|
|
||||||
private fun isColourCodeHigh(c: Char) = c.toInt() in 0b110110_1111000000..0b110110_1111111111 // only works with JVM (which uses UTF-16 internally)
|
|
||||||
private fun isColourCodeLow(c: Char) = c.toInt() in 0b110111_0000000000..0b110111_1111111111 // only works with JVM (which uses UTF-16 internally)
|
|
||||||
private fun isLatinExtAdd(c: Char) = c.toInt() in 0x1E00..0x1EFF
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private fun extAindexX(c: Char) = (c.toInt() - 0x100) % 16
|
|
||||||
private fun extAindexY(c: Char) = (c.toInt() - 0x100) / 16
|
|
||||||
|
|
||||||
private fun extBindexX(c: Char) = (c.toInt() - 0x180) % 16
|
|
||||||
private fun extBindexY(c: Char) = (c.toInt() - 0x180) / 16
|
|
||||||
|
|
||||||
private fun runicIndexX(c: Char) = (c.toInt() - 0x16A0) % 16
|
|
||||||
private fun runicIndexY(c: Char) = (c.toInt() - 0x16A0) / 16
|
|
||||||
|
|
||||||
private fun kanaIndexX(c: Char) = (c.toInt() - 0x3040) % 16
|
|
||||||
private fun kanaIndexY(c: Char) = (c.toInt() - 0x3040) / 16
|
|
||||||
|
|
||||||
private fun cjkPunctIndexX(c: Char) = (c.toInt() - 0x3000) % 16
|
|
||||||
private fun cjkPunctIndexY(c: Char) = (c.toInt() - 0x3000) / 16
|
|
||||||
|
|
||||||
private fun cyrilicIndexX(c: Char) = (c.toInt() - 0x400) % 16
|
|
||||||
private fun cyrilicIndexY(c: Char) = (c.toInt() - 0x400) / 16
|
|
||||||
|
|
||||||
private fun fullwidthUniIndexX(c: Char) = (c.toInt() - 0xFF00) % 16
|
|
||||||
private fun fullwidthUniIndexY(c: Char) = (c.toInt() - 0xFF00) / 16
|
|
||||||
|
|
||||||
private fun uniPunctIndexX(c: Char) = (c.toInt() - 0x2000) % 16
|
|
||||||
private fun uniPunctIndexY(c: Char) = (c.toInt() - 0x2000) / 16
|
|
||||||
|
|
||||||
private fun unihanIndexX(c: Char) = (c.toInt() - 0x3400) % 256
|
|
||||||
private fun unihanIndexY(c: Char) = (c.toInt() - 0x3400) / 256
|
|
||||||
|
|
||||||
private fun greekIndexX(c: Char) = (c.toInt() - 0x370) % 16
|
|
||||||
private fun greekIndexY(c: Char) = (c.toInt() - 0x370) / 16
|
|
||||||
|
|
||||||
private fun thaiIndexX(c: Char) = (c.toInt() - 0xE00) % 16
|
|
||||||
private fun thaiIndexY(c: Char) = (c.toInt() - 0xE00) / 16
|
|
||||||
|
|
||||||
private fun symbolIndexX(c: Char) = (c.toInt() - 0xE000) % 16
|
|
||||||
private fun symbolIndexY(c: Char) = (c.toInt() - 0xE000) / 16
|
|
||||||
|
|
||||||
private fun armenianIndexX(c: Char) = (c.toInt() - 0x530) % 16
|
|
||||||
private fun armenianIndexY(c: Char) = (c.toInt() - 0x530) / 16
|
|
||||||
|
|
||||||
private fun kartvelianIndexX(c: Char) = (c.toInt() - 0x10D0) % 16
|
|
||||||
private fun kartvelianIndexY(c: Char) = (c.toInt() - 0x10D0) / 16
|
|
||||||
|
|
||||||
private fun ipaIndexX(c: Char) = (c.toInt() - 0x250) % 16
|
|
||||||
private fun ipaIndexY(c: Char) = (c.toInt() - 0x250) / 16
|
|
||||||
|
|
||||||
private fun latinExtAddX(c: Char) = (c.toInt() - 0x1E00) % 16
|
|
||||||
private fun latinExtAddY(c: Char) = (c.toInt() - 0x1E00) / 16
|
|
||||||
|
|
||||||
private fun getColour(charHigh: Char, charLow: Char): Color { // input: 0x10ARGB, out: RGBA8888
|
|
||||||
val codePoint = Character.toCodePoint(charHigh, charLow)
|
|
||||||
|
|
||||||
if (colourBuffer.containsKey(codePoint))
|
|
||||||
return colourBuffer[codePoint]!!
|
|
||||||
|
|
||||||
val r = codePoint.and(0xF000).ushr(12)
|
|
||||||
val g = codePoint.and(0x0F00).ushr(8)
|
|
||||||
val b = codePoint.and(0x00F0).ushr(4)
|
|
||||||
val a = codePoint.and(0x000F)
|
|
||||||
|
|
||||||
val col = Color(a.shl(28) or a.shl(24) or r.shl(20) or r.shl(16) or g.shl(12) or g.shl(8) or b.shl(4) or b)
|
|
||||||
|
|
||||||
|
|
||||||
colourBuffer[codePoint] = col
|
|
||||||
return col
|
|
||||||
}
|
|
||||||
|
|
||||||
private val colourBuffer = HashMap<Int, Color>()
|
|
||||||
|
|
||||||
private val unihanWidthSheets = arrayOf(
|
|
||||||
SHEET_UNIHAN,
|
|
||||||
SHEET_FW_UNI
|
|
||||||
)
|
|
||||||
private val variableWidthSheets = arrayOf(
|
|
||||||
SHEET_ASCII_VARW,
|
|
||||||
SHEET_EXTA_VARW,
|
|
||||||
SHEET_EXTB_VARW,
|
|
||||||
SHEET_CYRILIC_VARW,
|
|
||||||
SHEET_UNI_PUNCT_VARW,
|
|
||||||
SHEET_GREEK_VARW,
|
|
||||||
SHEET_THAI_VARW,
|
|
||||||
SHEET_HAYEREN_VARW,
|
|
||||||
SHEET_KARTULI_VARW,
|
|
||||||
SHEET_IPA_VARW,
|
|
||||||
SHEET_LATIN_EXT_ADD_VARW
|
|
||||||
)
|
|
||||||
|
|
||||||
private val fontParentDir = if (fontDir.endsWith('/') || fontDir.endsWith('\\')) fontDir else "$fontDir/"
|
|
||||||
private val fileList = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!!
|
|
||||||
"ascii_variable.tga",
|
|
||||||
"hangul_johab.tga",
|
|
||||||
"latinExtA_variable.tga",
|
|
||||||
"latinExtB_variable.tga",
|
|
||||||
"kana.tga",
|
|
||||||
"cjkpunct.tga",
|
|
||||||
"wenquanyi.tga.gz",
|
|
||||||
"cyrilic_variable.tga",
|
|
||||||
"fullwidth_forms.tga",
|
|
||||||
"unipunct_variable.tga",
|
|
||||||
"greek_variable.tga",
|
|
||||||
"thai_variable.tga",
|
|
||||||
"hayeren_variable.tga",
|
|
||||||
"kartuli_variable.tga",
|
|
||||||
"ipa_ext_variable.tga",
|
|
||||||
"futhark.tga",
|
|
||||||
"latinExt_additional_variable.tga",
|
|
||||||
"puae000-e0ff.tga"
|
|
||||||
)
|
|
||||||
private val cyrilic_bg = "cyrilic_bulgarian_variable.tga"
|
|
||||||
private val cyrilic_sr = "cyrilic_serbian_variable.tga"
|
|
||||||
private val codeRange = arrayOf( // MUST BE MATCHING WITH SHEET INDICES!!
|
|
||||||
0..0xFF,
|
|
||||||
0xAC00..0xD7A3,
|
|
||||||
0x100..0x17F,
|
|
||||||
0x180..0x24F,
|
|
||||||
0x3040..0x30FF,
|
|
||||||
0x3000..0x303F,
|
|
||||||
0x3400..0x9FFF,
|
|
||||||
0x400..0x52F,
|
|
||||||
0xFF00..0xFF1F,
|
|
||||||
0x2000..0x205F,
|
|
||||||
0x370..0x3CE,
|
|
||||||
0xE00..0xE5F,
|
|
||||||
0x530..0x58F,
|
|
||||||
0x10D0..0x10FF,
|
|
||||||
0x250..0x2AF,
|
|
||||||
0x16A0..0x16FF,
|
|
||||||
0x1E00..0x1EFF,
|
|
||||||
0xE000..0xE0FF
|
|
||||||
)
|
|
||||||
private val glyphWidths: HashMap<Int, Int> = HashMap() // if the value is negative, it's diacritics
|
|
||||||
private val sheets: Array<SpriteSheet>
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
val sheetsPack = ArrayList<SpriteSheet>()
|
|
||||||
|
|
||||||
// first we create pixmap to read pixels, then make texture using pixmap
|
|
||||||
fileList.forEachIndexed { index, it ->
|
|
||||||
val isVariable1 = it.endsWith("_variable.tga")
|
|
||||||
val isVariable2 = variableWidthSheets.contains(index)
|
|
||||||
val isVariable = isVariable1 && isVariable2
|
|
||||||
|
|
||||||
// idiocity check
|
|
||||||
if (isVariable1 && !isVariable2)
|
|
||||||
throw Error("[TerrarumSansBitmap] font is named as variable on the name but not enlisted as")
|
|
||||||
else if (!isVariable1 && isVariable2)
|
|
||||||
throw Error("[TerrarumSansBitmap] font is enlisted as variable on the name but not named as")
|
|
||||||
|
|
||||||
|
|
||||||
val image: Image
|
|
||||||
|
|
||||||
|
|
||||||
// unpack gz if applicable
|
|
||||||
if (it.endsWith(".gz")) {
|
|
||||||
val gzi = GZIPInputStream(FileInputStream(fontParentDir + it))
|
|
||||||
val wholeFile = gzi.readBytes()
|
|
||||||
gzi.close()
|
|
||||||
val fos = BufferedOutputStream(FileOutputStream("tmp_wenquanyi.tga"))
|
|
||||||
fos.write(wholeFile)
|
|
||||||
fos.flush()
|
|
||||||
fos.close()
|
|
||||||
|
|
||||||
image = Image("tmp_wenquanyi.tga")
|
|
||||||
|
|
||||||
File("tmp_wenquanyi.tga").delete()
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
image = Image(fontParentDir + it)
|
|
||||||
}
|
|
||||||
|
|
||||||
val texture = image.texture
|
|
||||||
|
|
||||||
if (isVariable) {
|
|
||||||
println("[TerrarumSansBitmap] loading texture $it [VARIABLE]")
|
|
||||||
buildWidthTable(texture, codeRange[index], 16)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
println("[TerrarumSansBitmap] loading texture $it")
|
|
||||||
}
|
|
||||||
|
|
||||||
val texRegPack = if (isVariable) {
|
|
||||||
SpriteSheet(image, W_VAR_INIT, H - 1, HGAP_VAR)
|
|
||||||
}
|
|
||||||
else if (index == SHEET_UNIHAN) {
|
|
||||||
SpriteSheet(image, W_UNIHAN, H_UNIHAN) // the only exception that is height is 16
|
|
||||||
}
|
|
||||||
// below they all have height of 20 'H'
|
|
||||||
else if (index == SHEET_FW_UNI) {
|
|
||||||
SpriteSheet(image, W_UNIHAN, H)
|
|
||||||
}
|
|
||||||
else if (index == SHEET_CJK_PUNCT) {
|
|
||||||
SpriteSheet(image, W_ASIAN_PUNCT, H)
|
|
||||||
}
|
|
||||||
else if (index == SHEET_KANA) {
|
|
||||||
SpriteSheet(image, W_KANA, H)
|
|
||||||
}
|
|
||||||
else if (index == SHEET_HANGUL) {
|
|
||||||
SpriteSheet(image, W_HANGUL, H)
|
|
||||||
}
|
|
||||||
else if (index == SHEET_CUSTOM_SYM) {
|
|
||||||
SpriteSheet(image, SIZE_CUSTOM_SYM, SIZE_CUSTOM_SYM) // TODO variable
|
|
||||||
}
|
|
||||||
else if (index == SHEET_RUNIC) {
|
|
||||||
SpriteSheet(image, W_LATIN_WIDE, H)
|
|
||||||
}
|
|
||||||
else throw IllegalArgumentException("[TerrarumSansBitmap] Unknown sheet index: $index")
|
|
||||||
|
|
||||||
|
|
||||||
sheetsPack.add(texRegPack)
|
|
||||||
}
|
|
||||||
|
|
||||||
sheets = sheetsPack.toTypedArray()
|
|
||||||
}
|
|
||||||
|
|
||||||
private var localeBuffer = ""
|
|
||||||
|
|
||||||
fun reload(locale: String) {
|
|
||||||
if (!localeBuffer.startsWith("ru") && locale.startsWith("ru")) {
|
|
||||||
val image = Image(fontParentDir + fileList[SHEET_CYRILIC_VARW])
|
|
||||||
sheets[SHEET_CYRILIC_VARW].destroy()
|
|
||||||
sheets[SHEET_CYRILIC_VARW] = SpriteSheet(image, W_VAR_INIT, H, HGAP_VAR, 0)
|
|
||||||
}
|
|
||||||
else if (!localeBuffer.startsWith("bg") && locale.startsWith("bg")) {
|
|
||||||
val image = Image(fontParentDir + cyrilic_bg)
|
|
||||||
sheets[SHEET_CYRILIC_VARW].destroy()
|
|
||||||
sheets[SHEET_CYRILIC_VARW] = SpriteSheet(image, W_VAR_INIT, H, HGAP_VAR, 0)
|
|
||||||
}
|
|
||||||
else if (!localeBuffer.startsWith("sr") && locale.startsWith("sr")) {
|
|
||||||
val image = Image(fontParentDir + cyrilic_sr)
|
|
||||||
sheets[SHEET_CYRILIC_VARW].destroy()
|
|
||||||
sheets[SHEET_CYRILIC_VARW] = SpriteSheet(image, W_VAR_INIT, H, HGAP_VAR, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
localeBuffer = locale
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLineHeight(): Int = H
|
|
||||||
override fun getHeight(p0: String) = lineHeight
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private val offsetUnihan = (H - H_UNIHAN) / 2
|
|
||||||
private val offsetCustomSym = (H - SIZE_CUSTOM_SYM) / 2
|
|
||||||
|
|
||||||
private var textBuffer: CharSequence = ""
|
|
||||||
private var textBWidth = intArrayOf() // absolute posX of glyphs from print-origin
|
|
||||||
private var textBGSize = intArrayOf() // width of each glyph
|
|
||||||
|
|
||||||
override fun drawString(x: Float, y: Float, str: String) {
|
|
||||||
drawString(x, y, str, Color.white)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawString(p0: Float, p1: Float, p2: String?, p3: Color?, p4: Int, p5: Int) {
|
|
||||||
throw UnsupportedOperationException()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun drawString(x: Float, y: Float, str: String, color: Color) {
|
|
||||||
// always draw at integer position; this is bitmap font after all
|
|
||||||
val x = Math.round(x).toFloat()
|
|
||||||
val y = Math.round(y).toFloat()
|
|
||||||
|
|
||||||
|
|
||||||
if (textBuffer != str) {
|
|
||||||
textBuffer = str
|
|
||||||
val widths = getWidthOfCharSeq(str)
|
|
||||||
|
|
||||||
textBGSize = widths
|
|
||||||
|
|
||||||
textBWidth = IntArray(str.length, { charIndex ->
|
|
||||||
if (charIndex == 0)
|
|
||||||
0
|
|
||||||
else {
|
|
||||||
var acc = 0
|
|
||||||
(0..charIndex - 1).forEach { acc += maxOf(0, widths[it]) } // don't accumulate diacrtics (which has negative value)
|
|
||||||
/*return*/acc
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
//print("[TerrarumSansBitmap] widthTable for $textBuffer: ")
|
|
||||||
//textBWidth.forEach { print("$it ") }; println()
|
|
||||||
|
|
||||||
|
|
||||||
var mainCol = color
|
|
||||||
var shadowCol = color.darker(0.5f)
|
|
||||||
|
|
||||||
|
|
||||||
var index = 0
|
|
||||||
while (index <= textBuffer.lastIndex) {
|
|
||||||
val c = textBuffer[index]
|
|
||||||
val sheetID = getSheetType(c)
|
|
||||||
val sheetXY = getSheetwisePosition(c)
|
|
||||||
|
|
||||||
//println("[TerrarumSansBitmap] sprite: $sheetID:${sheetXY[0]}x${sheetXY[1]}")
|
|
||||||
|
|
||||||
if (isColourCodeHigh(c)) {
|
|
||||||
val cchigh = c
|
|
||||||
val cclow = textBuffer[index + 1]
|
|
||||||
|
|
||||||
if (Character.toCodePoint(cchigh, cclow) == 0x100000) {
|
|
||||||
mainCol = color
|
|
||||||
shadowCol = color.darker(0.5f)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
mainCol = getColour(cchigh, cclow)
|
|
||||||
shadowCol = mainCol.darker(0.5f)
|
|
||||||
}
|
|
||||||
|
|
||||||
index += 1
|
|
||||||
}
|
|
||||||
else if (isColourCodeLow(c)) {
|
|
||||||
throw Error("Unexpected encounter of ColourCodeLow at index $index of String '$textBuffer'")
|
|
||||||
}
|
|
||||||
else if (sheetID == SHEET_HANGUL) {
|
|
||||||
val hangulSheet = sheets[SHEET_HANGUL]
|
|
||||||
val hIndex = c.toInt() - 0xAC00
|
|
||||||
|
|
||||||
val indexCho = getHanChosung(hIndex)
|
|
||||||
val indexJung = getHanJungseong(hIndex)
|
|
||||||
val indexJong = getHanJongseong(hIndex)
|
|
||||||
|
|
||||||
val choRow = getHanInitialRow(hIndex)
|
|
||||||
val jungRow = getHanMedialRow(hIndex)
|
|
||||||
val jongRow = getHanFinalRow(hIndex)
|
|
||||||
|
|
||||||
|
|
||||||
if (!noShadow) {
|
|
||||||
hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index] + 1, y, shadowCol)
|
|
||||||
hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index] , y, shadowCol)
|
|
||||||
hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index] + 1, y, shadowCol)
|
|
||||||
|
|
||||||
hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index] + 1, y, shadowCol)
|
|
||||||
hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index] , y, shadowCol)
|
|
||||||
hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index] + 1, y, shadowCol)
|
|
||||||
|
|
||||||
hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index] + 1, y, shadowCol)
|
|
||||||
hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index] , y, shadowCol)
|
|
||||||
hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index] + 1, y, shadowCol)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
hangulSheet.getSubImage(indexCho, choRow ).draw(x + textBWidth[index], y, mainCol)
|
|
||||||
hangulSheet.getSubImage(indexJung, jungRow).draw(x + textBWidth[index], y, mainCol)
|
|
||||||
hangulSheet.getSubImage(indexJong, jongRow).draw(x + textBWidth[index], y, mainCol)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
try {
|
|
||||||
val offset = if (!isDiacritics(c)) 0 else {
|
|
||||||
if (index > 0) // LIMITATION: does not support double (or more) diacritics properly
|
|
||||||
(textBGSize[index] - textBGSize[index - 1]) / 2
|
|
||||||
else
|
|
||||||
textBGSize[index]
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!noShadow) {
|
|
||||||
sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw(
|
|
||||||
x + textBWidth[index] + 1 + offset,
|
|
||||||
y + (if (sheetID == SHEET_UNIHAN) // evil exceptions
|
|
||||||
offsetUnihan
|
|
||||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
|
||||||
offsetCustomSym
|
|
||||||
else
|
|
||||||
0),
|
|
||||||
shadowCol
|
|
||||||
)
|
|
||||||
sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw(
|
|
||||||
x + textBWidth[index] + offset,
|
|
||||||
y + (if (sheetID == SHEET_UNIHAN) // evil exceptions
|
|
||||||
offsetUnihan + 1
|
|
||||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
|
||||||
offsetCustomSym + 1
|
|
||||||
else
|
|
||||||
1),
|
|
||||||
shadowCol
|
|
||||||
)
|
|
||||||
sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw(
|
|
||||||
x + textBWidth[index] + 1 + offset,
|
|
||||||
y + (if (sheetID == SHEET_UNIHAN) // evil exceptions
|
|
||||||
offsetUnihan + 1
|
|
||||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
|
||||||
offsetCustomSym + 1
|
|
||||||
else
|
|
||||||
1),
|
|
||||||
shadowCol
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
sheets[sheetID].getSubImage(sheetXY[0], sheetXY[1]).draw(
|
|
||||||
x + textBWidth[index] + offset,
|
|
||||||
y + if (sheetID == SHEET_UNIHAN) // evil exceptions
|
|
||||||
offsetUnihan
|
|
||||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
|
||||||
offsetCustomSym
|
|
||||||
else 0,
|
|
||||||
mainCol
|
|
||||||
)
|
|
||||||
}
|
|
||||||
catch (noSuchGlyph: ArrayIndexOutOfBoundsException) {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
index += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun dispose() {
|
|
||||||
sheets.forEach { it.destroy() }
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getWidthOfCharSeq(s: CharSequence): IntArray {
|
|
||||||
val len = IntArray(s.length)
|
|
||||||
for (i in 0..s.lastIndex) {
|
|
||||||
val chr = s[i]
|
|
||||||
val ctype = getSheetType(s[i])
|
|
||||||
|
|
||||||
if (variableWidthSheets.contains(ctype)) {
|
|
||||||
if (!glyphWidths.containsKey(chr.toInt())) {
|
|
||||||
println("[TerrarumSansBitmap] no width data for glyph number ${Integer.toHexString(chr.toInt()).toUpperCase()}")
|
|
||||||
len[i] = W_LATIN_WIDE
|
|
||||||
}
|
|
||||||
|
|
||||||
len[i] = glyphWidths[chr.toInt()]!!
|
|
||||||
}
|
|
||||||
else if (isColourCodeHigh(chr) || isColourCodeLow(chr))
|
|
||||||
len[i] = 0
|
|
||||||
else if (ctype == SHEET_CJK_PUNCT)
|
|
||||||
len[i] = W_ASIAN_PUNCT
|
|
||||||
else if (ctype == SHEET_HANGUL)
|
|
||||||
len[i] = W_HANGUL
|
|
||||||
else if (ctype == SHEET_KANA)
|
|
||||||
len[i] = W_KANA
|
|
||||||
else if (unihanWidthSheets.contains(ctype))
|
|
||||||
len[i] = W_UNIHAN
|
|
||||||
else if (ctype == SHEET_CUSTOM_SYM)
|
|
||||||
len[i] = SIZE_CUSTOM_SYM
|
|
||||||
else
|
|
||||||
len[i] = W_LATIN_WIDE
|
|
||||||
|
|
||||||
if (scale > 1) len[i] *= scale
|
|
||||||
|
|
||||||
if (i < s.lastIndex) len[i] += interchar
|
|
||||||
}
|
|
||||||
return len
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSheetType(c: Char): Int {
|
|
||||||
if (isHangul(c))
|
|
||||||
return SHEET_HANGUL
|
|
||||||
else if (isKana(c))
|
|
||||||
return SHEET_KANA
|
|
||||||
else if (isUniHan(c))
|
|
||||||
return SHEET_UNIHAN
|
|
||||||
else if (isAscii(c))
|
|
||||||
return SHEET_ASCII_VARW
|
|
||||||
else if (isExtA(c))
|
|
||||||
return SHEET_EXTA_VARW
|
|
||||||
else if (isExtB(c))
|
|
||||||
return SHEET_EXTB_VARW
|
|
||||||
else if (isCyrilic(c))
|
|
||||||
return SHEET_CYRILIC_VARW
|
|
||||||
else if (isUniPunct(c))
|
|
||||||
return SHEET_UNI_PUNCT_VARW
|
|
||||||
else if (isCJKPunct(c))
|
|
||||||
return SHEET_CJK_PUNCT
|
|
||||||
else if (isFullwidthUni(c))
|
|
||||||
return SHEET_FW_UNI
|
|
||||||
else if (isGreek(c))
|
|
||||||
return SHEET_GREEK_VARW
|
|
||||||
else if (isThai(c))
|
|
||||||
return SHEET_THAI_VARW
|
|
||||||
else if (isCustomSym(c))
|
|
||||||
return SHEET_CUSTOM_SYM
|
|
||||||
else if (isArmenian(c))
|
|
||||||
return SHEET_HAYEREN_VARW
|
|
||||||
else if (isKartvelian(c))
|
|
||||||
return SHEET_KARTULI_VARW
|
|
||||||
else if (isIPA(c))
|
|
||||||
return SHEET_IPA_VARW
|
|
||||||
else if (isRunic(c))
|
|
||||||
return SHEET_RUNIC
|
|
||||||
else if (isLatinExtAdd(c))
|
|
||||||
return SHEET_LATIN_EXT_ADD_VARW
|
|
||||||
else
|
|
||||||
return SHEET_UNKNOWN
|
|
||||||
// fixed width
|
|
||||||
// fallback
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun getSheetwisePosition(ch: Char): IntArray {
|
|
||||||
val sheetX: Int; val sheetY: Int
|
|
||||||
when (getSheetType(ch)) {
|
|
||||||
SHEET_UNIHAN -> {
|
|
||||||
sheetX = unihanIndexX(ch)
|
|
||||||
sheetY = unihanIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_EXTA_VARW -> {
|
|
||||||
sheetX = extAindexX(ch)
|
|
||||||
sheetY = extAindexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_EXTB_VARW -> {
|
|
||||||
sheetX = extBindexX(ch)
|
|
||||||
sheetY = extBindexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_KANA -> {
|
|
||||||
sheetX = kanaIndexX(ch)
|
|
||||||
sheetY = kanaIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_CJK_PUNCT -> {
|
|
||||||
sheetX = cjkPunctIndexX(ch)
|
|
||||||
sheetY = cjkPunctIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_CYRILIC_VARW -> {
|
|
||||||
sheetX = cyrilicIndexX(ch)
|
|
||||||
sheetY = cyrilicIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_FW_UNI -> {
|
|
||||||
sheetX = fullwidthUniIndexX(ch)
|
|
||||||
sheetY = fullwidthUniIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_UNI_PUNCT_VARW -> {
|
|
||||||
sheetX = uniPunctIndexX(ch)
|
|
||||||
sheetY = uniPunctIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_GREEK_VARW -> {
|
|
||||||
sheetX = greekIndexX(ch)
|
|
||||||
sheetY = greekIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_THAI_VARW -> {
|
|
||||||
sheetX = thaiIndexX(ch)
|
|
||||||
sheetY = thaiIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_CUSTOM_SYM -> {
|
|
||||||
sheetX = symbolIndexX(ch)
|
|
||||||
sheetY = symbolIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_HAYEREN_VARW -> {
|
|
||||||
sheetX = armenianIndexX(ch)
|
|
||||||
sheetY = armenianIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_KARTULI_VARW -> {
|
|
||||||
sheetX = kartvelianIndexX(ch)
|
|
||||||
sheetY = kartvelianIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_IPA_VARW -> {
|
|
||||||
sheetX = ipaIndexX(ch)
|
|
||||||
sheetY = ipaIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_RUNIC -> {
|
|
||||||
sheetX = runicIndexX(ch)
|
|
||||||
sheetY = runicIndexY(ch)
|
|
||||||
}
|
|
||||||
SHEET_LATIN_EXT_ADD_VARW -> {
|
|
||||||
sheetX = latinExtAddX(ch)
|
|
||||||
sheetY = latinExtAddY(ch)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
sheetX = ch.toInt() % 16
|
|
||||||
sheetY = ch.toInt() / 16
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return intArrayOf(sheetX, sheetY)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun buildWidthTable(texture: Texture, codeRange: IntRange, cols: Int = 16) {
|
|
||||||
val binaryCodeOffset = W_VAR_INIT
|
|
||||||
|
|
||||||
val cellW = W_VAR_INIT + 1
|
|
||||||
val cellH = H
|
|
||||||
|
|
||||||
for (code in codeRange) {
|
|
||||||
|
|
||||||
val cellX = ((code - codeRange.start) % cols) * cellW
|
|
||||||
val cellY = ((code - codeRange.start) / cols) * cellH
|
|
||||||
|
|
||||||
val codeStartX = cellX + binaryCodeOffset
|
|
||||||
val codeStartY = cellY
|
|
||||||
|
|
||||||
var glyphWidth = 0
|
|
||||||
|
|
||||||
for (downCtr in 0..3) {
|
|
||||||
// if ALPHA is not zero, assume it's 1
|
|
||||||
if (texture.textureData[4 * (codeStartX + (codeStartY + downCtr) * texture.textureWidth) + 3] != 0.toByte()) {
|
|
||||||
glyphWidth = glyphWidth or (1 shl downCtr)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
val isDiacritics = texture.textureData[4 * (codeStartX + (codeStartY + H - 1) * texture.textureWidth) + 3] != 0.toByte()
|
|
||||||
if (isDiacritics)
|
|
||||||
glyphWidth = -glyphWidth
|
|
||||||
|
|
||||||
glyphWidths[code] = glyphWidth
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun getWidth(text: String): Int {
|
|
||||||
return getWidthOfCharSeq(text).sum()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var interchar = 0
|
|
||||||
var scale = 1
|
|
||||||
set(value) {
|
|
||||||
if (value > 0) field = value
|
|
||||||
else throw IllegalArgumentException("Font scale cannot be zero or negative (input: $value)")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun toColorCode(rgba4444: Int): String = GameFontBase.toColorCode(rgba4444)
|
|
||||||
fun toColorCode(r: Int, g: Int, b: Int, a: Int = 0x0F): String = toColorCode(r.shl(12) or g.shl(8) or b.shl(4) or a)
|
|
||||||
val noColorCode = toColorCode(0x0000)
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
fun toColorCode(rgba4444: Int): String = Character.toChars(0x100000 + rgba4444).toColCode()
|
|
||||||
fun toColorCode(r: Int, g: Int, b: Int, a: Int = 0x0F): String = toColorCode(r.shl(12) or g.shl(8) or b.shl(4) or a)
|
|
||||||
private fun CharArray.toColCode(): String = "${this[0]}${this[1]}"
|
|
||||||
|
|
||||||
val noColorCode = toColorCode(0x0000)
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
@@ -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
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 22 KiB |