Compare commits
26 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0c61fa6c68 | ||
|
|
2d9642ff6f | ||
|
|
59ee8e5a48 | ||
|
|
e894471b0d | ||
|
|
b2fe8c3304 | ||
|
|
f2a0fc0d47 | ||
|
|
cdbfa1bab8 | ||
|
|
15bed6f696 | ||
|
|
318c4af68f | ||
|
|
c5004c3ff6 | ||
|
|
31c1adcee4 | ||
|
|
53f44f498c | ||
|
|
4258192f24 | ||
|
|
c59b3cdf27 | ||
|
|
687bc40097 | ||
|
|
ab211d6433 | ||
|
|
65108a0630 | ||
|
|
8c740a5062 | ||
|
|
8897c65b98 | ||
|
|
0a44d5c27a | ||
|
|
4cffd8e864 | ||
|
|
bff8bcf939 | ||
|
|
774982113a | ||
|
|
d1981c34e3 | ||
|
|
275e037ea2 | ||
|
|
3c85722c00 |
3
.gitignore
vendored
@@ -1,2 +1,5 @@
|
||||
demo/out/*
|
||||
demo/lib/*
|
||||
demo/assets/*
|
||||
out/*
|
||||
lib/*
|
||||
1
.idea/.name
generated
Normal file
@@ -0,0 +1 @@
|
||||
BuildJAR_TerrarumSansBitmap
|
||||
12
.idea/artifacts/TerrarumSansBitmap.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<component name="ArtifactManager">
|
||||
<artifact type="jar" name="TerrarumSansBitmap">
|
||||
<output-path>$PROJECT_DIR$/out/artifacts/TerrarumSansBitmap</output-path>
|
||||
<root id="archive" name="TerrarumSansBitmap.jar">
|
||||
<element id="module-output" name="BuildJAR_TerrarumSansBitmap" />
|
||||
<element id="directory" name="META-INF">
|
||||
<element id="file-copy" path="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
|
||||
</element>
|
||||
<element id="dir-copy" path="$PROJECT_DIR$/src" />
|
||||
</root>
|
||||
</artifact>
|
||||
</component>
|
||||
12
.idea/libraries/KotlinJavaRuntime.xml
generated
Normal file
@@ -0,0 +1,12 @@
|
||||
<component name="libraryTable">
|
||||
<library name="KotlinJavaRuntime">
|
||||
<CLASSES>
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-runtime.jar!/" />
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-reflect.jar!/" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES>
|
||||
<root url="jar://$KOTLIN_BUNDLED$/lib/kotlin-runtime-sources.jar!/" />
|
||||
</SOURCES>
|
||||
</library>
|
||||
</component>
|
||||
10
.idea/libraries/lib.xml
generated
Normal file
@@ -0,0 +1,10 @@
|
||||
<component name="libraryTable">
|
||||
<library name="lib">
|
||||
<CLASSES>
|
||||
<root url="file://$PROJECT_DIR$/lib" />
|
||||
</CLASSES>
|
||||
<JAVADOC />
|
||||
<SOURCES />
|
||||
<jarDirectory url="file://$PROJECT_DIR$/lib" recursive="false" />
|
||||
</library>
|
||||
</component>
|
||||
74
.idea/misc.xml
generated
Normal file
@@ -0,0 +1,74 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="MarkdownProjectSettings">
|
||||
<PreviewSettings splitEditorLayout="SPLIT" splitEditorPreview="PREVIEW" useGrayscaleRendering="false" zoomFactor="1.0" maxImageWidth="0" showGitHubPageIfSynced="false" allowBrowsingInPreview="false" synchronizePreviewPosition="true" highlightPreviewType="NONE" highlightFadeOut="5" highlightOnTyping="true" synchronizeSourcePosition="true" verticallyAlignSourceAndPreviewSyncPosition="true" showSearchHighlightsInPreview="false" showSelectionInPreview="true">
|
||||
<PanelProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.panel" providerName="Default - Swing" />
|
||||
</PanelProvider>
|
||||
</PreviewSettings>
|
||||
<ParserSettings gitHubSyntaxChange="false">
|
||||
<PegdownExtensions>
|
||||
<option name="ABBREVIATIONS" value="false" />
|
||||
<option name="ANCHORLINKS" value="true" />
|
||||
<option name="ASIDE" value="false" />
|
||||
<option name="ATXHEADERSPACE" value="true" />
|
||||
<option name="AUTOLINKS" value="true" />
|
||||
<option name="DEFINITIONS" value="false" />
|
||||
<option name="DEFINITION_BREAK_DOUBLE_BLANK_LINE" value="false" />
|
||||
<option name="FENCED_CODE_BLOCKS" value="true" />
|
||||
<option name="FOOTNOTES" value="false" />
|
||||
<option name="HARDWRAPS" value="false" />
|
||||
<option name="INSERTED" value="false" />
|
||||
<option name="QUOTES" value="false" />
|
||||
<option name="RELAXEDHRULES" value="true" />
|
||||
<option name="SMARTS" value="false" />
|
||||
<option name="STRIKETHROUGH" value="true" />
|
||||
<option name="SUBSCRIPT" value="false" />
|
||||
<option name="SUPERSCRIPT" value="false" />
|
||||
<option name="SUPPRESS_HTML_BLOCKS" value="false" />
|
||||
<option name="SUPPRESS_INLINE_HTML" value="false" />
|
||||
<option name="TABLES" value="true" />
|
||||
<option name="TASKLISTITEMS" value="true" />
|
||||
<option name="TOC" value="false" />
|
||||
<option name="WIKILINKS" value="true" />
|
||||
</PegdownExtensions>
|
||||
<ParserOptions>
|
||||
<option name="COMMONMARK_LISTS" value="true" />
|
||||
<option name="DUMMY" value="false" />
|
||||
<option name="EMOJI_SHORTCUTS" value="true" />
|
||||
<option name="FLEXMARK_FRONT_MATTER" value="false" />
|
||||
<option name="GFM_LOOSE_BLANK_LINE_AFTER_ITEM_PARA" value="false" />
|
||||
<option name="GFM_TABLE_RENDERING" value="true" />
|
||||
<option name="GITBOOK_URL_ENCODING" value="false" />
|
||||
<option name="GITHUB_EMOJI_URL" value="false" />
|
||||
<option name="GITHUB_LISTS" value="false" />
|
||||
<option name="GITHUB_WIKI_LINKS" value="true" />
|
||||
<option name="JEKYLL_FRONT_MATTER" value="false" />
|
||||
<option name="SIM_TOC_BLANK_LINE_SPACER" value="true" />
|
||||
</ParserOptions>
|
||||
</ParserSettings>
|
||||
<HtmlSettings headerTopEnabled="false" headerBottomEnabled="false" bodyTopEnabled="false" bodyBottomEnabled="false" embedUrlContent="false" addPageHeader="true">
|
||||
<GeneratorProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.generator" providerName="Default Swing HTML Generator" />
|
||||
</GeneratorProvider>
|
||||
<headerTop />
|
||||
<headerBottom />
|
||||
<bodyTop />
|
||||
<bodyBottom />
|
||||
</HtmlSettings>
|
||||
<CssSettings previewScheme="UI_SCHEME" cssUri="" isCssUriEnabled="false" isCssTextEnabled="false" isDynamicPageWidth="true">
|
||||
<StylesheetProvider>
|
||||
<provider providerId="com.vladsch.idea.multimarkdown.editor.swing.html.css" providerName="Default Swing Stylesheet" />
|
||||
</StylesheetProvider>
|
||||
<ScriptProviders />
|
||||
<cssText />
|
||||
</CssSettings>
|
||||
<HtmlExportSettings updateOnSave="false" parentDir="$ProjectFileDir$" targetDir="$ProjectFileDir$" cssDir="" scriptDir="" plainHtml="false" imageDir="" copyLinkedImages="false" imageUniquifyType="0" targetExt="" useTargetExt="false" noCssNoScripts="false" linkToExportedHtml="true" exportOnSettingsChange="true" regenerateOnProjectOpen="false" />
|
||||
<LinkMapSettings>
|
||||
<textMaps />
|
||||
</LinkMapSettings>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/out" />
|
||||
</component>
|
||||
</project>
|
||||
8
.idea/modules.xml
generated
Normal file
@@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/BuildJAR_TerrarumSansBitmap.iml" filepath="$PROJECT_DIR$/BuildJAR_TerrarumSansBitmap.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
||||
6
.idea/vcs.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="VcsDirectoryMappings">
|
||||
<mapping directory="" vcs="Git" />
|
||||
</component>
|
||||
</project>
|
||||
511
.idea/workspace.xml
generated
Normal file
@@ -0,0 +1,511 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ArtifactsWorkspaceSettings">
|
||||
<artifacts-to-build>
|
||||
<artifact name="TerrarumSansBitmap" />
|
||||
</artifacts-to-build>
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="22c5bc80-996c-4846-b173-7dc8c2096fe3" name="Default" comment="">
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/terrarumsansbitmap/gdx/GameFontBase.kt" afterPath="" />
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/terrarumsansbitmap/gdx/TextureRegionPack.kt" afterPath="" />
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/terrarumsansbitmap/readme.md" afterPath="" />
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/terrarumsansbitmap/slick2d/GameFontBase.kt" afterPath="" />
|
||||
<change type="DELETED" beforePath="$PROJECT_DIR$/terrarumsansbitmap/slick2d/GameFontImpl.kt" afterPath="" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/assets/hangul_johab.tga" afterPath="$PROJECT_DIR$/assets/hangul_johab.tga" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/.gitignore" afterPath="$PROJECT_DIR$/.gitignore" />
|
||||
<change type="MODIFICATION" beforePath="$PROJECT_DIR$/demo/.idea/workspace.xml" afterPath="$PROJECT_DIR$/demo/.idea/workspace.xml" />
|
||||
</list>
|
||||
<ignored path="$PROJECT_DIR$/out/" />
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="TRACKING_ENABLED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
|
||||
<component name="FileEditorManager">
|
||||
<leaf>
|
||||
<file leaf-file-name="GameFontBase.kt" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarumsansbitmap/slick2d/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="112">
|
||||
<caret line="40" column="2" lean-forward="false" selection-start-line="40" selection-start-column="2" selection-end-line="40" selection-end-column="2" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="GameFontBase.kt" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarumsansbitmap/gdx/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="630">
|
||||
<caret line="67" column="39" lean-forward="false" selection-start-line="67" selection-start-column="39" selection-end-line="67" selection-end-column="39" />
|
||||
<folding>
|
||||
<element signature="e#1202#1474#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="Git.Settings">
|
||||
<option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="GradleLocalSettings">
|
||||
<option name="externalProjectsViewState">
|
||||
<projects_view />
|
||||
</option>
|
||||
</component>
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/.gitignore" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="x" value="-1208" />
|
||||
<option name="y" value="-647" />
|
||||
<option name="width" value="1216" />
|
||||
<option name="height" value="1896" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
<flattenPackages />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
<showLibraryContents />
|
||||
<hideEmptyPackages />
|
||||
<abbreviatePackageNames />
|
||||
<autoscrollToSource />
|
||||
<autoscrollFromSource />
|
||||
<sortByType />
|
||||
<manualOrder />
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="PackagesPane" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="BuildJAR_TerrarumSansBitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="Terrarum-sans-bitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="BuildJAR_TerrarumSansBitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="Terrarum-sans-bitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="src" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="terrarumsansbitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="BuildJAR_TerrarumSansBitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="Terrarum-sans-bitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="src" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="terrarumsansbitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="slick2d" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
<PATH>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="BuildJAR_TerrarumSansBitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="Terrarum-sans-bitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="src" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="terrarumsansbitmap" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
<PATH_ELEMENT>
|
||||
<option name="myItemId" value="gdx" />
|
||||
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
|
||||
</PATH_ELEMENT>
|
||||
</PATH>
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
<pane id="Scratches" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="project.structure.last.edited" value="Artifacts" />
|
||||
<property name="project.structure.proportion" value="0.15" />
|
||||
<property name="project.structure.side.proportion" value="0.32068965" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration default="true" type="#org.jetbrains.idea.devkit.run.PluginConfigurationType" factoryName="Plugin">
|
||||
<module name="" />
|
||||
<option name="VM_PARAMETERS" value="-Xmx512m -Xms256m -XX:MaxPermSize=250m -ea" />
|
||||
<option name="PROGRAM_PARAMETERS" />
|
||||
<predefined_log_file id="idea.log" enabled="true" />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="Applet" factoryName="Applet">
|
||||
<option name="HTML_USED" value="false" />
|
||||
<option name="WIDTH" value="400" />
|
||||
<option name="HEIGHT" value="300" />
|
||||
<option name="POLICY_FILE" value="$APPLICATION_HOME_DIR$/bin/appletviewer.policy" />
|
||||
<module />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="Application" factoryName="Application">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="PROGRAM_PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<option name="ENABLE_SWING_INSPECTOR" value="false" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
<option name="PASS_PARENT_ENVS" value="true" />
|
||||
<module name="" />
|
||||
<envs />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="GradleRunConfiguration" factoryName="Gradle">
|
||||
<ExternalSystemSettings>
|
||||
<option name="executionName" />
|
||||
<option name="externalProjectPath" />
|
||||
<option name="externalSystemIdString" value="GRADLE" />
|
||||
<option name="scriptParameters" />
|
||||
<option name="taskDescriptions">
|
||||
<list />
|
||||
</option>
|
||||
<option name="taskNames">
|
||||
<list />
|
||||
</option>
|
||||
<option name="vmOptions" />
|
||||
</ExternalSystemSettings>
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="JUnit" factoryName="JUnit">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<module name="" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<option name="PACKAGE_NAME" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="METHOD_NAME" />
|
||||
<option name="TEST_OBJECT" value="class" />
|
||||
<option name="VM_PARAMETERS" value="-ea" />
|
||||
<option name="PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
<option name="PASS_PARENT_ENVS" value="true" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="singleModule" />
|
||||
</option>
|
||||
<envs />
|
||||
<patterns />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="JarApplication" factoryName="JAR Application">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<envs />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="Java Scratch" factoryName="Java Scratch">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="SCRATCH_FILE_ID" value="0" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="PROGRAM_PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<option name="ENABLE_SWING_INSPECTOR" value="false" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
<option name="PASS_PARENT_ENVS" value="true" />
|
||||
<module name="" />
|
||||
<envs />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="JetRunConfigurationType" factoryName="Kotlin">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="VM_PARAMETERS" />
|
||||
<option name="PROGRAM_PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<option name="PASS_PARENT_ENVS" value="true" />
|
||||
<module name="BuildJAR_TerrarumSansBitmap" />
|
||||
<envs />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="KotlinStandaloneScriptRunConfigurationType" factoryName="Kotlin script">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<option name="filePath" />
|
||||
<option name="vmParameters" />
|
||||
<option name="alternativeJrePath" />
|
||||
<option name="programParameters" />
|
||||
<option name="passParentEnvs" value="true" />
|
||||
<option name="workingDirectory" />
|
||||
<option name="isAlternativeJrePathEnabled" value="false" />
|
||||
<envs />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="Remote" factoryName="Remote">
|
||||
<option name="USE_SOCKET_TRANSPORT" value="true" />
|
||||
<option name="SERVER_MODE" value="false" />
|
||||
<option name="SHMEM_ADDRESS" value="javadebug" />
|
||||
<option name="HOST" value="localhost" />
|
||||
<option name="PORT" value="5005" />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="TestNG" factoryName="TestNG">
|
||||
<extension name="coverage" enabled="false" merge="false" sample_coverage="true" runner="idea" />
|
||||
<module name="" />
|
||||
<option name="ALTERNATIVE_JRE_PATH_ENABLED" value="false" />
|
||||
<option name="ALTERNATIVE_JRE_PATH" />
|
||||
<option name="SUITE_NAME" />
|
||||
<option name="PACKAGE_NAME" />
|
||||
<option name="MAIN_CLASS_NAME" />
|
||||
<option name="METHOD_NAME" />
|
||||
<option name="GROUP_NAME" />
|
||||
<option name="TEST_OBJECT" value="CLASS" />
|
||||
<option name="VM_PARAMETERS" value="-ea" />
|
||||
<option name="PARAMETERS" />
|
||||
<option name="WORKING_DIRECTORY" value="$MODULE_DIR$" />
|
||||
<option name="OUTPUT_DIRECTORY" />
|
||||
<option name="ANNOTATION_TYPE" />
|
||||
<option name="ENV_VARIABLES" />
|
||||
<option name="PASS_PARENT_ENVS" value="true" />
|
||||
<option name="TEST_SEARCH_SCOPE">
|
||||
<value defaultName="singleModule" />
|
||||
</option>
|
||||
<option name="USE_DEFAULT_REPORTERS" value="false" />
|
||||
<option name="PROPERTIES_FILE" />
|
||||
<envs />
|
||||
<properties />
|
||||
<listeners />
|
||||
<method />
|
||||
</configuration>
|
||||
<configuration default="true" type="executeSpecs" factoryName="Gauge Execution">
|
||||
<setting name="environment" value="" />
|
||||
<setting name="specsToExecute" value="" />
|
||||
<setting name="tags" value="" />
|
||||
<setting name="parallelNodes" value="" />
|
||||
<setting name="execInParallel" value="false" />
|
||||
<setting name="programParameters" value="" />
|
||||
<setting name="workingDirectory" value="" />
|
||||
<setting name="moduleName" value="" />
|
||||
<envMap />
|
||||
<setting name="rowsRange" value="" />
|
||||
<method />
|
||||
</configuration>
|
||||
</component>
|
||||
<component name="ShelveChangesManager" show_recycled="false">
|
||||
<option name="remove_strategy" value="false" />
|
||||
</component>
|
||||
<component name="TaskManager">
|
||||
<task active="true" id="Default" summary="Default task">
|
||||
<changelist id="22c5bc80-996c-4846-b173-7dc8c2096fe3" name="Default" comment="" />
|
||||
<created>1497950823354</created>
|
||||
<option name="number" value="Default" />
|
||||
<option name="presentableId" value="Default" />
|
||||
<updated>1497950823354</updated>
|
||||
</task>
|
||||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="-1208" y="-647" width="1216" height="1896" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3295519" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Palette	" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="VcsContentAnnotationSettings">
|
||||
<option name="myLimit" value="2678400000" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager />
|
||||
<watches-manager />
|
||||
</component>
|
||||
<component name="antWorkspaceConfiguration">
|
||||
<option name="IS_AUTOSCROLL_TO_SOURCE" value="false" />
|
||||
<option name="FILTER_TARGETS" value="false" />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/.gitignore">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="56">
|
||||
<caret line="4" column="5" lean-forward="false" selection-start-line="4" selection-start-column="5" selection-end-line="4" selection-end-column="5" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarumsansbitmap/gdx/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="630">
|
||||
<caret line="67" column="39" lean-forward="false" selection-start-line="67" selection-start-column="39" selection-end-line="67" selection-end-column="39" />
|
||||
<folding>
|
||||
<element signature="e#1202#1474#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarumsansbitmap/slick2d/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="112">
|
||||
<caret line="40" column="2" lean-forward="false" selection-start-line="40" selection-start-column="2" selection-end-line="40" selection-end-column="2" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
<component name="masterDetails">
|
||||
<states>
|
||||
<state key="ArtifactsStructureConfigurable.UI">
|
||||
<settings>
|
||||
<artifact-editor />
|
||||
<last-edited>TerrarumSansBitmap</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.32068965" />
|
||||
<option value="0.5" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
<state key="FacetStructureConfigurable.UI">
|
||||
<settings>
|
||||
<last-edited>No facets are configured</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
<state key="GlobalLibrariesConfigurable.UI">
|
||||
<settings>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
<state key="JdkListConfigurable.UI">
|
||||
<settings>
|
||||
<last-edited>1.8</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.2" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
<state key="ModuleStructureConfigurable.UI">
|
||||
<settings>
|
||||
<last-edited>BuildJAR_TerrarumSansBitmap</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.32068965" />
|
||||
<option value="0.6" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
<state key="ProjectLibrariesConfigurable.UI">
|
||||
<settings>
|
||||
<last-edited>lib</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.32068965" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
</settings>
|
||||
</state>
|
||||
</states>
|
||||
</component>
|
||||
</project>
|
||||
13
BuildJAR_TerrarumSansBitmap.iml
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="KotlinJavaRuntime" level="project" />
|
||||
<orderEntry type="library" name="lib" level="project" />
|
||||
</component>
|
||||
</module>
|
||||
2
META-INF/MANIFEST.MF
Normal file
@@ -0,0 +1,2 @@
|
||||
Manifest-Version: 1.0
|
||||
|
||||
68
README.md
@@ -2,18 +2,15 @@
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
(note—you can't display Bulgarian and Russian glyphs at the same time, you must ```reload()``` them upon the change of locale of your game)
|
||||
|
||||
**Font demo** — head to the **[Release](https://github.com/minjaesong/Terrarum-sans-bitmap/releases)** tab
|
||||
|
||||
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, Cyrillic (Russian, Bulgarian, Serbian), Greek, Chinese (limited to Unicode BMP), Japanese, Korean (all 11 172 possible syllables).
|
||||
|
||||
The code for the fonts are meant to be used with Slick2d (extends ```Font``` 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.
|
||||
|
||||
#### Little notes
|
||||
- You can't display Bulgarian, Russian and Serbian variants at the same time without some more codes; ```reload()```ing them or creating multiple instances of the font would be the easiest solutions.
|
||||
- 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.
|
||||
|
||||
## Contribution guidelines
|
||||
|
||||
@@ -22,7 +19,54 @@ You can contribute to the font by fixing wrong glyphs, suggesting better ones, e
|
||||
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.
|
||||
|
||||
|
||||
## Using on Slick2d
|
||||
## Using on your game
|
||||
|
||||
- Firstly, place the .jar to your library path and unzip spritesheets, then:
|
||||
|
||||
### Using on LibGDX
|
||||
|
||||
On your code (Kotlin):
|
||||
|
||||
class YourGame : Game() {
|
||||
|
||||
lateinit var fontGame: Font
|
||||
|
||||
override fun create() {
|
||||
fontGame = GameFontBase(path_to_assets)
|
||||
...
|
||||
}
|
||||
|
||||
override fun render() {
|
||||
batch.begin()
|
||||
...
|
||||
fontGame.draw(batch, text, ...)
|
||||
...
|
||||
batch.end()
|
||||
}
|
||||
}
|
||||
|
||||
On your code (Java):
|
||||
|
||||
class YourGame extends BasicGame {
|
||||
|
||||
Font fontGame;
|
||||
|
||||
@Override void create() {
|
||||
fontGame = new GameFontBase(path_to_assets);
|
||||
...
|
||||
}
|
||||
|
||||
@Override void render() {
|
||||
batch.begin();
|
||||
...
|
||||
fontGame.draw(batch, text, ...);
|
||||
...
|
||||
batch.end();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
### Using on Slick2d
|
||||
|
||||
On your code (Kotlin):
|
||||
|
||||
@@ -31,7 +75,7 @@ On your code (Kotlin):
|
||||
lateinit var fontGame: Font
|
||||
|
||||
override fun init(gc: GameContainer) {
|
||||
fontGame = GameFontImpl()
|
||||
fontGame = GameFontBase(path_to_assets)
|
||||
...
|
||||
}
|
||||
|
||||
@@ -48,7 +92,7 @@ On your code (Java):
|
||||
Font fontGame;
|
||||
|
||||
@Override void init(GameContainer gc) {
|
||||
fontGame = new GameFontImpl();
|
||||
fontGame = new GameFontBase(path_to_assets);
|
||||
...
|
||||
}
|
||||
|
||||
@@ -60,11 +104,13 @@ On your code (Java):
|
||||
|
||||
## Font metrics
|
||||
|
||||
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``` has width of 12, ```hangul_johab``` has width of 11, ```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
|
||||
|
||||
Width is encoded in binary number, on pixels. On the font spritesheet, every glyph has vertical dots on their right side (to be exact, every (16k - 1)th pixel on x axis). From top to bottom, each dot represents 1, 2, 4 and 8. For example, ASCII glyph 'C' has width of 9, 'W' has width of 11, " (double quote) has width of 6.
|
||||

|
||||
|
||||
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.
|
||||
|
||||
### Implementing the Korean writing system
|
||||
|
||||
|
||||
@@ -1,558 +0,0 @@
|
||||
package net.torvald.imagefont
|
||||
|
||||
import org.lwjgl.opengl.GL11
|
||||
import org.newdawn.slick.*
|
||||
import org.newdawn.slick.opengl.Texture
|
||||
import java.nio.ByteOrder
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-01-27.
|
||||
*/
|
||||
open class GameFontBase : Font {
|
||||
|
||||
private fun getHan(hanIndex: Int): IntArray {
|
||||
val han_x = hanIndex % JONG_COUNT
|
||||
val han_y = hanIndex / JONG_COUNT
|
||||
val ret = intArrayOf(han_x, han_y)
|
||||
return ret
|
||||
}
|
||||
|
||||
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 0xAC00..0xD7A3
|
||||
private fun isAscii(c: Char) = c.toInt() in 0x20..0xFF
|
||||
private fun isRunic(c: Char) = runicList.contains(c)
|
||||
private fun isExtA(c: Char) = c.toInt() in 0x100..0x17F
|
||||
private fun isExtB(c: Char) = c.toInt() in 0x180..0x24F
|
||||
private fun isKana(c: Char) = c.toInt() in 0x3040..0x30FF
|
||||
private fun isCJKPunct(c: Char) = c.toInt() in 0x3000..0x303F
|
||||
private fun isUniHan(c: Char) = c.toInt() in 0x3400..0x9FFF
|
||||
private fun isCyrilic(c: Char) = c.toInt() in 0x400..0x45F
|
||||
private fun isFullwidthUni(c: Char) = c.toInt() in 0xFF00..0xFF1F
|
||||
private fun isUniPunct(c: Char) = c.toInt() in 0x2000..0x206F
|
||||
private fun isGreek(c: Char) = c.toInt() in 0x370..0x3CE
|
||||
|
||||
|
||||
|
||||
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) = runicList.indexOf(c) % 16
|
||||
private fun runicIndexY(c: Char) = runicList.indexOf(c) / 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 unihanIndexX(c: Char) = (c.toInt() - 0x3400) % 256
|
||||
private fun unihanIndexY(c: Char) = (c.toInt() - 0x3400) / 256
|
||||
|
||||
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 greekIndexX(c: Char) = (c.toInt() - 0x370) % 16
|
||||
private fun greekIndexY(c: Char) = (c.toInt() - 0x370) / 16
|
||||
|
||||
private val unihanWidthSheets = arrayOf(
|
||||
SHEET_UNIHAN,
|
||||
SHEET_FW_UNI,
|
||||
SHEET_UNIHAN
|
||||
)
|
||||
private val zeroWidthSheets = arrayOf(
|
||||
SHEET_COLOURCODE
|
||||
)
|
||||
private val variableWidthSheets = arrayOf(
|
||||
SHEET_ASCII_VARW,
|
||||
SHEET_CYRILIC_VARW,
|
||||
SHEET_EXTA_VARW,
|
||||
SHEET_GREEK_VARW,
|
||||
SHEET_EXTB_VARW
|
||||
)
|
||||
|
||||
|
||||
override fun getWidth(s: String) = getWidthSubstr(s, s.length)
|
||||
|
||||
private fun getWidthSubstr(s: String, endIndex: Int): Int {
|
||||
var len = 0
|
||||
for (i in 0..endIndex - 1) {
|
||||
val chr = s[i]
|
||||
val ctype = getSheetType(s[i])
|
||||
|
||||
if (variableWidthSheets.contains(ctype)) {
|
||||
len += try {
|
||||
asciiWidths[chr.toInt()]!!
|
||||
}
|
||||
catch (e: kotlin.KotlinNullPointerException) {
|
||||
println("KotlinNullPointerException on glyph number ${Integer.toHexString(chr.toInt()).toUpperCase()}")
|
||||
//System.exit(1)
|
||||
W_LATIN_WIDE // failsafe
|
||||
}
|
||||
}
|
||||
else if (zeroWidthSheets.contains(ctype))
|
||||
len += 0
|
||||
else if (ctype == SHEET_CJK_PUNCT)
|
||||
len += W_ASIAN_PUNCT
|
||||
else if (ctype == SHEET_HANGUL)
|
||||
len += W_HANGUL
|
||||
else if (ctype == SHEET_KANA)
|
||||
len += W_KANA
|
||||
else if (unihanWidthSheets.contains(ctype))
|
||||
len += W_UNIHAN
|
||||
else
|
||||
len += W_LATIN_WIDE
|
||||
|
||||
if (i < endIndex - 1) len += interchar
|
||||
}
|
||||
return len * scale
|
||||
}
|
||||
|
||||
override fun getHeight(s: String) = H * scale
|
||||
|
||||
override fun getLineHeight() = H * scale
|
||||
|
||||
override fun drawString(x: Float, y: Float, s: String) = drawString(x, y, s, Color.white)
|
||||
|
||||
override fun drawString(x: Float, y: Float, s: String, color: Color) {
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glColorMask(true, true, true, true)
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
|
||||
var thisCol = color
|
||||
|
||||
// hangul fonts first
|
||||
//hangulSheet.startUse() // disabling texture binding to make the font coloured
|
||||
// JOHAB
|
||||
for (i in 0..s.length - 1) {
|
||||
val ch = s[i]
|
||||
|
||||
if (ch.isColourCode()) {
|
||||
thisCol = colourKey[ch]!!
|
||||
continue
|
||||
}
|
||||
|
||||
if (isHangul(ch)) {
|
||||
val hIndex = ch.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)
|
||||
|
||||
val glyphW = getWidth(ch.toString())
|
||||
|
||||
hangulSheet.getSubImage(indexCho, choRow).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
hangulSheet.getSubImage(indexJung, jungRow).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
hangulSheet.getSubImage(indexJong, jongRow).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
}
|
||||
}
|
||||
//hangulSheet.endUse()
|
||||
|
||||
// WenQuanYi
|
||||
//uniHan.startUse()
|
||||
|
||||
for (i in 0..s.length - 1) {
|
||||
val ch = s[i]
|
||||
|
||||
if (ch.isColourCode()) {
|
||||
thisCol = colourKey[ch]!!
|
||||
continue
|
||||
}
|
||||
|
||||
if (isUniHan(ch)) {
|
||||
val glyphW = getWidth("" + ch)
|
||||
uniHan.getSubImage(unihanIndexX(ch), unihanIndexY(ch)).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round((H - H_UNIHAN) / 2 + y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//uniHan.endUse()
|
||||
|
||||
// regular fonts
|
||||
var prevInstance = -1
|
||||
for (i in 0..s.length - 1) {
|
||||
val ch = s[i]
|
||||
|
||||
if (ch.isColourCode()) {
|
||||
thisCol = colourKey[ch]!!
|
||||
continue
|
||||
}
|
||||
|
||||
if (!isHangul(ch) && !isUniHan(ch)) {
|
||||
|
||||
// if not init, endUse first
|
||||
if (prevInstance != -1) {
|
||||
//sheetKey[prevInstance].endUse()
|
||||
}
|
||||
//sheetKey[getSheetType(ch)].startUse()
|
||||
prevInstance = getSheetType(ch)
|
||||
|
||||
val sheetX: Int
|
||||
val sheetY: Int
|
||||
when (prevInstance) {
|
||||
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 -> {
|
||||
sheetX = uniPunctIndexX(ch)
|
||||
sheetY = uniPunctIndexY(ch)
|
||||
}
|
||||
SHEET_GREEK_VARW -> {
|
||||
sheetX = greekIndexX(ch)
|
||||
sheetY = greekIndexY(ch)
|
||||
}
|
||||
else -> {
|
||||
sheetX = ch.toInt() % 16
|
||||
sheetY = ch.toInt() / 16
|
||||
}
|
||||
}
|
||||
|
||||
val glyphW = getWidth("" + ch)
|
||||
try {
|
||||
sheetKey[prevInstance]!!.getSubImage(sheetX, sheetY).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
}
|
||||
catch (e: ArrayIndexOutOfBoundsException) {
|
||||
// character that does not exist in the sheet. No render, pass.
|
||||
}
|
||||
catch (e1: RuntimeException) {
|
||||
// System.err.println("[GameFontBase] RuntimeException raised while processing character '$ch' (U+${Integer.toHexString(ch.toInt()).toUpperCase()})")
|
||||
// e1.printStackTrack()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (prevInstance != -1) {
|
||||
//sheetKey[prevInstance].endUse()
|
||||
}
|
||||
|
||||
GL11.glEnd()
|
||||
}
|
||||
|
||||
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
|
||||
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 (c.isColourCode())
|
||||
return SHEET_COLOURCODE
|
||||
else
|
||||
return SHEET_UNKNOWN// fixed width punctuations
|
||||
// fixed width
|
||||
// fallback
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw part of a string to the screen. Note that this will still position the text as though
|
||||
* it's part of the bigger string.
|
||||
* @param x
|
||||
* *
|
||||
* @param y
|
||||
* *
|
||||
* @param s
|
||||
* *
|
||||
* @param color
|
||||
* *
|
||||
* @param startIndex
|
||||
* *
|
||||
* @param endIndex
|
||||
*/
|
||||
override fun drawString(x: Float, y: Float, s: String, color: Color, startIndex: Int, endIndex: Int) {
|
||||
val unprintedHead = s.substring(0, startIndex)
|
||||
val printedBody = s.substring(startIndex, endIndex)
|
||||
val xoff = getWidth(unprintedHead)
|
||||
drawString(x + xoff, y, printedBody, color)
|
||||
}
|
||||
|
||||
fun Char.isColourCode() = colourKey.containsKey(this)
|
||||
|
||||
fun buildWidthTable(sheet: SpriteSheet, codeOffset: Int, codeRange: IntRange, rows: Int = 16) {
|
||||
fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this)
|
||||
|
||||
/** @return Intarray(R, G, B, A) */
|
||||
fun Texture.getPixel(x: Int, y: Int): IntArray {
|
||||
val textureWidth = this.textureWidth
|
||||
val hasAlpha = this.hasAlpha()
|
||||
|
||||
val offset = (if (hasAlpha) 4 else 3) * (textureWidth * y + x) // 4: # of channels (RGBA)
|
||||
|
||||
if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
|
||||
return intArrayOf(
|
||||
this.textureData[offset].toUint(),
|
||||
this.textureData[offset + 1].toUint(),
|
||||
this.textureData[offset + 2].toUint(),
|
||||
if (hasAlpha)
|
||||
this.textureData[offset + 3].toUint()
|
||||
else 255
|
||||
)
|
||||
}
|
||||
else {
|
||||
return intArrayOf(
|
||||
this.textureData[offset + 2].toUint(),
|
||||
this.textureData[offset + 1].toUint(),
|
||||
this.textureData[offset].toUint(),
|
||||
if (hasAlpha)
|
||||
this.textureData[offset + 3].toUint()
|
||||
else 255
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val binaryCodeOffset = 15
|
||||
|
||||
val cellW = sheet.getSubImage(0, 0).width + 1 // should be 16
|
||||
val cellH = sheet.getSubImage(0, 0).height + 1 // should be 20
|
||||
|
||||
// control chars
|
||||
for (ccode in codeRange) {
|
||||
val glyphX = ccode % rows
|
||||
val glyphY = ccode / rows
|
||||
|
||||
val codeStartX = (glyphX * cellW) + binaryCodeOffset
|
||||
val codeStartY = (glyphY * cellH)
|
||||
|
||||
var glyphWidth = 0
|
||||
for (downCtr in 0..3) {
|
||||
// if alpha is not zero, assume it's 1
|
||||
if (sheet.texture.getPixel(codeStartX, codeStartY + downCtr)[3] == 255) {
|
||||
glyphWidth = glyphWidth or (1 shl downCtr)
|
||||
}
|
||||
}
|
||||
|
||||
asciiWidths[codeOffset + ccode] = glyphWidth
|
||||
}
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
lateinit internal var hangulSheet: SpriteSheet
|
||||
lateinit internal var asciiSheet: SpriteSheet
|
||||
|
||||
internal val asciiWidths: HashMap<Int, Int> = HashMap()
|
||||
|
||||
lateinit internal var extASheet: SpriteSheet
|
||||
lateinit internal var extBSheet: SpriteSheet
|
||||
lateinit internal var kanaSheet: SpriteSheet
|
||||
lateinit internal var cjkPunct: SpriteSheet
|
||||
lateinit internal var uniHan: SpriteSheet
|
||||
lateinit internal var cyrilic: SpriteSheet
|
||||
lateinit internal var fullwidthForms: SpriteSheet
|
||||
lateinit internal var uniPunct: SpriteSheet
|
||||
lateinit internal var greekSheet: SpriteSheet
|
||||
|
||||
internal val JUNG_COUNT = 21
|
||||
internal val JONG_COUNT = 28
|
||||
|
||||
internal val W_ASIAN_PUNCT = 10
|
||||
internal val W_HANGUL = 11
|
||||
internal val W_KANA = 12
|
||||
internal val W_UNIHAN = 16
|
||||
internal val W_LATIN_WIDE = 9 // width of regular letters
|
||||
|
||||
internal val H = 20
|
||||
internal val H_UNIHAN = 16
|
||||
|
||||
internal val SHEET_ASCII_VARW = 0
|
||||
internal val SHEET_HANGUL = 1
|
||||
internal val SHEET_EXTA_VARW = 3
|
||||
internal val SHEET_EXTB_VARW = 4
|
||||
internal val SHEET_KANA = 5
|
||||
internal val SHEET_CJK_PUNCT = 6
|
||||
internal val SHEET_UNIHAN = 7
|
||||
internal val SHEET_CYRILIC_VARW = 8
|
||||
internal val SHEET_FW_UNI = 9
|
||||
internal val SHEET_UNI_PUNCT = 10
|
||||
internal val SHEET_GREEK_VARW = 11
|
||||
|
||||
|
||||
internal val SHEET_UNKNOWN = 254
|
||||
internal val SHEET_COLOURCODE = 255
|
||||
|
||||
lateinit internal var sheetKey: Array<SpriteSheet?>
|
||||
|
||||
/**
|
||||
* Runic letters list used for game. The set is
|
||||
* Younger Futhark + Medieval rune 'e' + Punct + Runic Almanac
|
||||
|
||||
* BEWARE OF SIMILAR-LOOKING RUNES, especially:
|
||||
|
||||
* * Algiz ᛉ instead of Maðr ᛘ
|
||||
|
||||
* * Short-Twig Hagall ᚽ instead of Runic Letter E ᛂ
|
||||
|
||||
* * Runic Letter OE ᚯ instead of Óss ᚬ
|
||||
|
||||
* Examples:
|
||||
* ᛭ᛋᛁᚴᚱᛁᚦᛦ᛭
|
||||
* ᛭ᛂᛚᛋᛅ᛭ᛏᚱᚢᛏᚾᛁᚾᚴᚢᚾᛅ᛬ᛅᚱᚾᛅᛏᛅᛚᛋ
|
||||
*/
|
||||
internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ')
|
||||
|
||||
internal var interchar = 0
|
||||
internal var scale = 1
|
||||
set(value) {
|
||||
if (value > 0) field = value
|
||||
else throw IllegalArgumentException("Font scale cannot be zero or negative (input: $value)")
|
||||
}
|
||||
|
||||
val colourKey = hashMapOf(
|
||||
Pair(0x10.toChar(), Color(0xFFFFFF)), //*w hite
|
||||
Pair(0x11.toChar(), Color(0xFFE080)), //*y ellow
|
||||
Pair(0x12.toChar(), Color(0xFFB020)), //o range
|
||||
Pair(0x13.toChar(), Color(0xFF8080)), //*r ed
|
||||
Pair(0x14.toChar(), Color(0xFFA0E0)), //f uchsia
|
||||
Pair(0x15.toChar(), Color(0xE0A0FF)), //*m agenta (purple)
|
||||
Pair(0x16.toChar(), Color(0x8080FF)), //*b lue
|
||||
Pair(0x17.toChar(), Color(0x80FFFF)), //c yan
|
||||
Pair(0x18.toChar(), Color(0x80FF80)), //*g reen
|
||||
Pair(0x19.toChar(), Color(0x008000)), //v iridian
|
||||
Pair(0x1A.toChar(), Color(0x805030)), //x (khaki)
|
||||
Pair(0x1B.toChar(), Color(0x808080)) //*k
|
||||
//* marked: commonly used
|
||||
)
|
||||
val colToCode = hashMapOf(
|
||||
Pair("w", 0x10.toChar()),
|
||||
Pair("y", 0x11.toChar()),
|
||||
Pair("o", 0x12.toChar()),
|
||||
Pair("r", 0x13.toChar()),
|
||||
Pair("f", 0x14.toChar()),
|
||||
Pair("m", 0x15.toChar()),
|
||||
Pair("b", 0x16.toChar()),
|
||||
Pair("c", 0x17.toChar()),
|
||||
Pair("g", 0x18.toChar()),
|
||||
Pair("v", 0x19.toChar()),
|
||||
Pair("x", 0x1A.toChar()),
|
||||
Pair("k", 0x1B.toChar())
|
||||
)
|
||||
val codeToCol = hashMapOf(
|
||||
Pair("w", colourKey[0x10.toChar()]),
|
||||
Pair("y", colourKey[0x11.toChar()]),
|
||||
Pair("o", colourKey[0x12.toChar()]),
|
||||
Pair("r", colourKey[0x13.toChar()]),
|
||||
Pair("f", colourKey[0x14.toChar()]),
|
||||
Pair("m", colourKey[0x15.toChar()]),
|
||||
Pair("b", colourKey[0x16.toChar()]),
|
||||
Pair("c", colourKey[0x17.toChar()]),
|
||||
Pair("g", colourKey[0x18.toChar()]),
|
||||
Pair("v", colourKey[0x19.toChar()]),
|
||||
Pair("x", colourKey[0x1A.toChar()]),
|
||||
Pair("k", colourKey[0x1B.toChar()])
|
||||
)
|
||||
}// end of companion object
|
||||
}
|
||||
|
||||
fun Image.drawWithShadow(x: Float, y: Float, color: Color) =
|
||||
this.drawWithShadow(x, y, 1f, color)
|
||||
|
||||
fun Image.drawWithShadow(x: Float, y: Float, scale: Float, color: Color) {
|
||||
this.draw(x + 1, y + 1, scale, color.darker(0.5f))
|
||||
this.draw(x , y + 1, scale, color.darker(0.5f))
|
||||
this.draw(x + 1, y , scale, color.darker(0.5f))
|
||||
|
||||
this.draw(x, y, scale, color)
|
||||
}
|
||||
@@ -1,73 +0,0 @@
|
||||
package net.torvald.imagefont
|
||||
|
||||
import net.torvald.terrarum.imagefont.GameFontDemo
|
||||
import org.newdawn.slick.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-01-20.
|
||||
*/
|
||||
class GameFontImpl : GameFontBase() {
|
||||
|
||||
init {
|
||||
|
||||
GameFontBase.hangulSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/hangul_johab.tga", GameFontBase.W_HANGUL, GameFontBase.H)
|
||||
GameFontBase.asciiSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/ascii_variable.tga", 15, 19, 1)
|
||||
GameFontBase.extASheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/LatinExtA_variable.tga", 15, 19, 1)
|
||||
GameFontBase.extBSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/LatinExtB_variable.tga", 15, 19, 1)
|
||||
GameFontBase.kanaSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/kana.tga", GameFontBase.W_KANA, GameFontBase.H)
|
||||
GameFontBase.cjkPunct = SpriteSheet(
|
||||
"./assets/graphics/fonts/cjkpunct.tga", GameFontBase.W_ASIAN_PUNCT, GameFontBase.H)
|
||||
GameFontBase.cyrilic = SpriteSheet(
|
||||
when (GameFontDemo.gameLocale.substring(0..1)) {
|
||||
"bg" -> "./assets/graphics/fonts/cyrilic_bulgarian_variable.tga"
|
||||
"sr" -> "./assets/graphics/fonts/cyrilic_serbian_variable.tga"
|
||||
else -> "./assets/graphics/fonts/cyrilic_variable.tga"
|
||||
}, 15, 19, 1)
|
||||
GameFontBase.fullwidthForms = SpriteSheet(
|
||||
"./assets/graphics/fonts/fullwidth_forms.tga", GameFontBase.W_UNIHAN, GameFontBase.H_UNIHAN)
|
||||
GameFontBase.uniPunct = SpriteSheet(
|
||||
"./assets/graphics/fonts/unipunct.tga", GameFontBase.W_LATIN_WIDE, GameFontBase.H)
|
||||
GameFontBase.uniHan = SpriteSheet(
|
||||
"./assets/graphics/fonts/wenquanyi.tga", 16, 16)
|
||||
GameFontBase.greekSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/greek_variable.tga", 15, 19, 1)
|
||||
|
||||
val shk = arrayOf(
|
||||
GameFontBase.asciiSheet,
|
||||
GameFontBase.hangulSheet,
|
||||
null, // here was customised runic sheet
|
||||
GameFontBase.extASheet,
|
||||
GameFontBase.extBSheet,
|
||||
GameFontBase.kanaSheet,
|
||||
GameFontBase.cjkPunct,
|
||||
GameFontBase.uniHan,
|
||||
GameFontBase.cyrilic,
|
||||
GameFontBase.fullwidthForms,
|
||||
GameFontBase.uniPunct,
|
||||
GameFontBase.greekSheet
|
||||
)
|
||||
GameFontBase.sheetKey = shk
|
||||
|
||||
|
||||
buildWidthTable(asciiSheet, 0, 0..0xFF)
|
||||
buildWidthTable(extASheet, 0x100, 0..0x7F)
|
||||
buildWidthTable(extBSheet, 0x180, 0..0xCF)
|
||||
buildWidthTable(cyrilic, 0x400, 0..0x5F)
|
||||
buildWidthTable(greekSheet, 0x370, 0..0x5F)
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
GameFontBase.cyrilic.destroy()
|
||||
GameFontBase.cyrilic = SpriteSheet(
|
||||
when (GameFontDemo.gameLocale.substring(0..1)) {
|
||||
"bg" -> "./assets/graphics/fonts/cyrilic_bulgarian_variable.tga"
|
||||
"sr" -> "./assets/graphics/fonts/cyrilic_serbian_variable.tga"
|
||||
else -> "./assets/graphics/fonts/cyrilic_variable.tga"
|
||||
}, 15, 19, 1)
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
Font implementations for Slick2d
|
||||
BIN
TerrarumSansBitmap.jar
Normal file
|
Before Width: | Height: | Size: 160 KiB After Width: | Height: | Size: 160 KiB |
|
Before Width: | Height: | Size: 260 KiB After Width: | Height: | Size: 260 KiB |
|
Before Width: | Height: | Size: 320 KiB After Width: | Height: | Size: 320 KiB |
|
Before Width: | Height: | Size: 50 KiB After Width: | Height: | Size: 50 KiB |
BIN
assets/cyrilic_bulgarian_variable.tga
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
assets/cyrilic_serbian_variable.tga
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
assets/cyrilic_variable.tga
Normal file
|
After Width: | Height: | Size: 380 KiB |
BIN
assets/fullwidth_forms.tga
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 79 KiB |
|
Before Width: | Height: | Size: 27 MiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 241 KiB After Width: | Height: | Size: 262 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
BIN
assets/insular_variable.tga
Normal file
|
After Width: | Height: | Size: 40 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 180 KiB After Width: | Height: | Size: 180 KiB |
BIN
assets/kartuli_variable.tga
Normal file
|
After Width: | Height: | Size: 60 KiB |
BIN
assets/puae000-e0ff.tga
Normal file
|
After Width: | Height: | Size: 324 KiB |
|
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 96 KiB After Width: | Height: | Size: 120 KiB |
BIN
assets/wenquanyi.tga.gz
Normal file
6
demo/.idea/kotlinc.xml
generated
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Kotlin2JvmCompilerArguments">
|
||||
<option name="jvmTarget" value="1.8" />
|
||||
</component>
|
||||
</project>
|
||||
319
demo/.idea/workspace.xml
generated
@@ -5,9 +5,6 @@
|
||||
<artifact name="unnamed" />
|
||||
</artifacts-to-build>
|
||||
</component>
|
||||
<component name="BookmarkManager">
|
||||
<bookmark url="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt" line="46" mnemonic="9" />
|
||||
</component>
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="fcc8c48a-4440-438f-9e38-d42425b5efd4" name="Default" comment="" />
|
||||
<ignored path="$PROJECT_DIR$/out/" />
|
||||
@@ -23,62 +20,32 @@
|
||||
</component>
|
||||
<component name="ExecutionTargetManager" SELECTED_TARGET="default_target" />
|
||||
<component name="FileEditorManager">
|
||||
<splitter split-orientation="horizontal" split-proportion="0.5">
|
||||
<split-first>
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file leaf-file-name="GameFontDemo.kt" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1008">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<folding>
|
||||
<element signature="e#40#238#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="GameFontImpl.kt" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="375">
|
||||
<caret line="36" column="22" lean-forward="false" selection-start-line="36" selection-start-column="22" selection-end-line="36" selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="e#31#108#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="text.txt" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/text.txt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="252">
|
||||
<caret line="18" column="0" lean-forward="false" selection-start-line="18" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</split-first>
|
||||
<split-second>
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file leaf-file-name="GameFontBase.kt" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="14">
|
||||
<caret line="36" column="19" lean-forward="false" selection-start-line="36" selection-start-column="19" selection-end-line="36" selection-end-column="19" />
|
||||
<folding>
|
||||
<element signature="e#31#171#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</split-second>
|
||||
</splitter>
|
||||
<leaf SIDE_TABS_SIZE_LIMIT_KEY="300">
|
||||
<file leaf-file-name="GameFontDemo.kt" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="602">
|
||||
<caret line="43" column="0" lean-forward="false" selection-start-line="43" selection-start-column="0" selection-end-line="43" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="GameFontBase.kt" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="8582">
|
||||
<caret line="613" column="0" lean-forward="false" selection-start-line="613" selection-start-column="0" selection-end-line="613" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="FileTemplateManagerImpl">
|
||||
<option name="RECENT_TEMPLATES">
|
||||
@@ -92,6 +59,7 @@
|
||||
<find>"|</find>
|
||||
<find>,\n</find>
|
||||
<find>main</find>
|
||||
<find>E7F</find>
|
||||
</findStrings>
|
||||
<replaceStrings>
|
||||
<replace>\n</replace>
|
||||
@@ -113,18 +81,21 @@
|
||||
<option value="$PROJECT_DIR$/text.properties" />
|
||||
<option value="$PROJECT_DIR$/config.properties" />
|
||||
<option value="$PROJECT_DIR$/META-INF/MANIFEST.MF" />
|
||||
<option value="$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt" />
|
||||
<option value="$PROJECT_DIR$/text.txt" />
|
||||
<option value="$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt" />
|
||||
<option value="$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<option value="$PROJECT_DIR$/lib/slick.jar!/org/newdawn/slick/opengl/Texture.class" />
|
||||
<option value="$PROJECT_DIR$/lib/slick.jar!/org/newdawn/slick/SpriteSheet.class" />
|
||||
<option value="$PROJECT_DIR$/lib/slick.jar!/org/newdawn/slick/Image.class" />
|
||||
<option value="$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt" />
|
||||
<option value="$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds">
|
||||
<option name="x" value="-8" />
|
||||
<option name="y" value="-8" />
|
||||
<option name="width" value="1936" />
|
||||
<option name="height" value="1176" />
|
||||
<option name="x" value="-1208" />
|
||||
<option name="y" value="-647" />
|
||||
<option name="width" value="1216" />
|
||||
<option name="height" value="1896" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
@@ -194,9 +165,8 @@
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="settings.editor.selected.configurable" value="project.kotlinCompiler" />
|
||||
<property name="settings.editor.splitter.proportion" value="0.2" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="project.structure.last.edited" value="Artifacts" />
|
||||
<property name="project.structure.last.edited" value="Modules" />
|
||||
<property name="project.structure.proportion" value="0.15" />
|
||||
<property name="project.structure.side.proportion" value="0.32068965" />
|
||||
</component>
|
||||
@@ -414,32 +384,32 @@
|
||||
<servers />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="-8" y="-8" width="1936" height="1176" extended-state="6" />
|
||||
<frame x="-1208" y="-647" width="1216" height="1896" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="Palette" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32917467" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Palette	" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="7" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Maven Projects" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32960597" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3292683" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32898468" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="9" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Designer" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.21634616" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="LuaJ" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32960597" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.17301038" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Structure" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.3054371" sideWeight="0.5" order="11" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="UI Designer" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.2581574" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.2580828" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="4" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="7" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Capture Tool" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="9" side_tool="false" content_ui="combo" />
|
||||
<window_info id="LuaJ" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32960597" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Code Iris" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.32960597" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Messages" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32898468" sideWeight="0.5" order="10" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Capture Analysis" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="8" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Documentation" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.1544196" sideWeight="0.4651163" order="10" side_tool="false" content_ui="tabs" x="1380" y="-157" width="1720" height="857" />
|
||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
@@ -451,7 +421,9 @@
|
||||
<option name="myLimit" value="2678400000" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager />
|
||||
<breakpoint-manager>
|
||||
<option name="time" value="1" />
|
||||
</breakpoint-manager>
|
||||
<watches-manager />
|
||||
</component>
|
||||
<component name="antWorkspaceConfiguration">
|
||||
@@ -461,10 +433,30 @@
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1008">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="8582">
|
||||
<caret line="613" column="0" lean-forward="false" selection-start-line="613" selection-start-column="0" selection-end-line="613" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="924">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<folding>
|
||||
<element signature="e#40#238#0" expanded="true" />
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -473,26 +465,16 @@
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="252">
|
||||
<caret line="18" column="0" lean-forward="false" selection-start-line="18" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="588">
|
||||
<caret line="42" column="46" lean-forward="true" selection-start-line="42" selection-start-column="46" selection-end-line="42" selection-end-column="46" />
|
||||
<folding>
|
||||
<element signature="e#31#108#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#31#171#0" expanded="true" />
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -502,26 +484,72 @@
|
||||
<state relative-caret-position="924">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<folding>
|
||||
<element signature="e#40#238#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="504">
|
||||
<caret line="37" column="41" lean-forward="false" selection-start-line="37" selection-start-column="41" selection-end-line="37" selection-end-column="41" />
|
||||
<folding>
|
||||
<element signature="e#31#108#0" expanded="true" />
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/text.txt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="252">
|
||||
<caret line="18" column="0" lean-forward="false" selection-start-line="18" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1008">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<folding>
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/text.txt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="252">
|
||||
<caret line="18" column="0" lean-forward="false" selection-start-line="18" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="924">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<folding>
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/text.txt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="252">
|
||||
<caret line="18" column="0" lean-forward="true" selection-start-line="18" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
@@ -530,7 +558,7 @@
|
||||
<state relative-caret-position="2800">
|
||||
<caret line="204" column="48" lean-forward="false" selection-start-line="204" selection-start-column="48" selection-end-line="204" selection-end-column="48" />
|
||||
<folding>
|
||||
<element signature="e#31#171#0" expanded="true" />
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -540,7 +568,7 @@
|
||||
<state relative-caret-position="924">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<folding>
|
||||
<element signature="e#40#238#0" expanded="true" />
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -550,27 +578,18 @@
|
||||
<state relative-caret-position="6846">
|
||||
<caret line="493" column="0" lean-forward="false" selection-start-line="493" selection-start-column="0" selection-end-line="493" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#31#171#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="658">
|
||||
<caret line="48" column="26" lean-forward="false" selection-start-line="48" selection-start-column="26" selection-end-line="48" selection-end-column="26" />
|
||||
<folding>
|
||||
<element signature="e#31#108#0" expanded="true" />
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="0" lean-forward="false" selection-start-line="0" selection-start-column="0" selection-end-line="0" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#40#238#0" expanded="true" />
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -580,7 +599,7 @@
|
||||
<state relative-caret-position="7168">
|
||||
<caret line="516" column="36" lean-forward="false" selection-start-line="516" selection-start-column="36" selection-end-line="516" selection-end-column="36" />
|
||||
<folding>
|
||||
<element signature="e#31#171#0" expanded="true" />
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -596,20 +615,10 @@
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
<caret line="0" column="95" lean-forward="false" selection-start-line="0" selection-start-column="95" selection-end-line="0" selection-end-column="95" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="392">
|
||||
<caret line="29" column="0" lean-forward="false" selection-start-line="29" selection-start-column="0" selection-end-line="29" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#31#108#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/META-INF/MANIFEST.MF">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="28">
|
||||
@@ -617,13 +626,7 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../Ba-AA/src/net/torvald/aa/demoplayer/BaAA.java">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="273">
|
||||
<caret line="428" column="8" lean-forward="false" selection-start-line="428" selection-start-column="8" selection-end-line="429" selection-end-column="87" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../Ba-AA/src/net/torvald/aa/demoplayer/BaAA.java" />
|
||||
<entry file="file://$PROJECT_DIR$/config.properties">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="0">
|
||||
@@ -638,40 +641,53 @@
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt" />
|
||||
<entry file="file://$PROJECT_DIR$/text.txt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="252">
|
||||
<caret line="18" column="0" lean-forward="false" selection-start-line="18" selection-start-column="0" selection-end-line="18" selection-end-column="0" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="jar://$PROJECT_DIR$/lib/slick.jar!/org/newdawn/slick/opengl/Texture.class">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="378">
|
||||
<caret line="30" column="11" lean-forward="false" selection-start-line="30" selection-start-column="11" selection-end-line="30" selection-end-column="11" />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="jar://$PROJECT_DIR$/lib/slick.jar!/org/newdawn/slick/Image.class">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="504">
|
||||
<caret line="48" column="14" lean-forward="false" selection-start-line="48" selection-start-column="14" selection-end-line="48" selection-end-column="14" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="jar://$PROJECT_DIR$/lib/slick.jar!/org/newdawn/slick/SpriteSheet.class">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="392">
|
||||
<caret line="34" column="11" lean-forward="false" selection-start-line="34" selection-start-column="11" selection-end-line="34" selection-end-column="11" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontBase.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="14">
|
||||
<caret line="36" column="19" lean-forward="false" selection-start-line="36" selection-start-column="19" selection-end-line="36" selection-end-column="19" />
|
||||
<state relative-caret-position="8582">
|
||||
<caret line="613" column="0" lean-forward="false" selection-start-line="613" selection-start-column="0" selection-end-line="613" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#31#171#0" expanded="true" />
|
||||
<element signature="e#48#391#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontDemo.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="1008">
|
||||
<caret line="72" column="55" lean-forward="false" selection-start-line="72" selection-start-column="55" selection-end-line="72" selection-end-column="55" />
|
||||
<state relative-caret-position="602">
|
||||
<caret line="43" column="0" lean-forward="false" selection-start-line="43" selection-start-column="0" selection-end-line="43" selection-end-column="0" />
|
||||
<folding>
|
||||
<element signature="e#40#238#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/src/net/torvald/terrarum/imagefont/GameFontImpl.kt">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="375">
|
||||
<caret line="36" column="22" lean-forward="false" selection-start-line="36" selection-start-column="22" selection-end-line="36" selection-end-column="22" />
|
||||
<folding>
|
||||
<element signature="e#31#108#0" expanded="true" />
|
||||
<element signature="e#40#255#0" expanded="true" />
|
||||
</folding>
|
||||
</state>
|
||||
</provider>
|
||||
@@ -700,7 +716,7 @@
|
||||
</state>
|
||||
<state key="FacetStructureConfigurable.UI">
|
||||
<settings>
|
||||
<last-edited>Kotlin</last-edited>
|
||||
<last-edited>Detection</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
@@ -735,12 +751,11 @@
|
||||
</state>
|
||||
<state key="ModuleStructureConfigurable.UI">
|
||||
<settings>
|
||||
<last-edited>TerrarumSansDemo</last-edited>
|
||||
<last-edited>Kotlin|TerrarumSansDemo</last-edited>
|
||||
<splitter-proportions>
|
||||
<option name="proportions">
|
||||
<list>
|
||||
<option value="0.32068965" />
|
||||
<option value="0.6" />
|
||||
</list>
|
||||
</option>
|
||||
</splitter-proportions>
|
||||
|
||||
@@ -2,31 +2,14 @@
|
||||
<module type="JAVA_MODULE" version="4">
|
||||
<component name="FacetManager">
|
||||
<facet type="kotlin-language" name="Kotlin">
|
||||
<configuration version="1">
|
||||
<option name="compilerInfo">
|
||||
<KotlinCompilerInfo>
|
||||
<option name="compilerSettings">
|
||||
<CompilerSettings />
|
||||
</option>
|
||||
<option name="k2jsCompilerArguments">
|
||||
<K2JSCompilerArguments />
|
||||
</option>
|
||||
<option name="k2jvmCompilerArguments">
|
||||
<K2JVMCompilerArguments />
|
||||
</option>
|
||||
<option name="_commonCompilerArguments">
|
||||
<DummyImpl />
|
||||
</option>
|
||||
</KotlinCompilerInfo>
|
||||
</option>
|
||||
<option name="useProjectSettings" value="false" />
|
||||
<option name="versionInfo">
|
||||
<KotlinVersionInfo>
|
||||
<option name="apiLevel" value="1.0" />
|
||||
<option name="languageLevel" value="1.0" />
|
||||
<option name="targetPlatformName" value="JVM 1.6" />
|
||||
</KotlinVersionInfo>
|
||||
</option>
|
||||
<configuration version="2" platform="JVM 1.6" useProjectSettings="false">
|
||||
<compilerSettings />
|
||||
<compilerArguments>
|
||||
<option name="jvmTarget" value="1.6" />
|
||||
<option name="languageVersion" value="1.1" />
|
||||
<option name="apiVersion" value="1.1" />
|
||||
<option name="coroutinesWarn" value="true" />
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</facet>
|
||||
</component>
|
||||
|
||||
@@ -1,27 +1,49 @@
|
||||
package net.torvald.imagefont
|
||||
package net.torvald.terrarumsansbitmap.slick2d
|
||||
|
||||
import org.lwjgl.opengl.GL11
|
||||
import org.newdawn.slick.*
|
||||
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.nio.ByteOrder
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.util.*
|
||||
import java.util.zip.GZIPInputStream
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-01-27.
|
||||
* LibGDX 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.
|
||||
*
|
||||
* @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.
|
||||
*/
|
||||
open class GameFontBase : Font {
|
||||
|
||||
private fun getHan(hanIndex: Int): IntArray {
|
||||
val han_x = hanIndex % JONG_COUNT
|
||||
val han_y = hanIndex / JONG_COUNT
|
||||
val ret = intArrayOf(han_x, han_y)
|
||||
return ret
|
||||
}
|
||||
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)
|
||||
@@ -54,18 +76,26 @@ open class GameFontBase : Font {
|
||||
9
|
||||
}
|
||||
|
||||
private fun isHangul(c: Char) = c.toInt() in 0xAC00..0xD7A3
|
||||
private fun isAscii(c: Char) = c.toInt() in 0x20..0xFF
|
||||
private fun isRunic(c: Char) = runicList.contains(c)
|
||||
private fun isExtA(c: Char) = c.toInt() in 0x100..0x17F
|
||||
private fun isExtB(c: Char) = c.toInt() in 0x180..0x24F
|
||||
private fun isKana(c: Char) = c.toInt() in 0x3040..0x30FF
|
||||
private fun isCJKPunct(c: Char) = c.toInt() in 0x3000..0x303F
|
||||
private fun isUniHan(c: Char) = c.toInt() in 0x3400..0x9FFF
|
||||
private fun isCyrilic(c: Char) = c.toInt() in 0x400..0x45F
|
||||
private fun isFullwidthUni(c: Char) = c.toInt() in 0xFF00..0xFF1F
|
||||
private fun isUniPunct(c: Char) = c.toInt() in 0x2000..0x206F
|
||||
private fun isGreek(c: Char) = c.toInt() in 0x370..0x3CE
|
||||
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) = runicList.contains(c)
|
||||
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]
|
||||
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]
|
||||
|
||||
|
||||
|
||||
@@ -75,8 +105,8 @@ open class GameFontBase : Font {
|
||||
private fun extBindexX(c: Char) = (c.toInt() - 0x180) % 16
|
||||
private fun extBindexY(c: Char) = (c.toInt() - 0x180) / 16
|
||||
|
||||
private fun runicIndexX(c: Char) = runicList.indexOf(c) % 16
|
||||
private fun runicIndexY(c: Char) = runicList.indexOf(c) / 16
|
||||
//private fun runicIndexX(c: Char) = runicList.indexOf(c) % 16
|
||||
//private fun runicIndexY(c: Char) = runicList.indexOf(c) / 16
|
||||
|
||||
private fun kanaIndexX(c: Char) = (c.toInt() - 0x3040) % 16
|
||||
private fun kanaIndexY(c: Char) = (c.toInt() - 0x3040) / 16
|
||||
@@ -84,9 +114,6 @@ open class GameFontBase : Font {
|
||||
private fun cjkPunctIndexX(c: Char) = (c.toInt() - 0x3000) % 16
|
||||
private fun cjkPunctIndexY(c: Char) = (c.toInt() - 0x3000) / 16
|
||||
|
||||
private fun unihanIndexX(c: Char) = (c.toInt() - 0x3400) % 256
|
||||
private fun unihanIndexY(c: Char) = (c.toInt() - 0x3400) / 256
|
||||
|
||||
private fun cyrilicIndexX(c: Char) = (c.toInt() - 0x400) % 16
|
||||
private fun cyrilicIndexY(c: Char) = (c.toInt() - 0x400) / 16
|
||||
|
||||
@@ -96,88 +123,244 @@ open class GameFontBase : Font {
|
||||
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 val unihanWidthSheets = arrayOf(
|
||||
SHEET_UNIHAN,
|
||||
SHEET_FW_UNI,
|
||||
SHEET_UNIHAN
|
||||
)
|
||||
private val zeroWidthSheets = arrayOf(
|
||||
SHEET_COLOURCODE
|
||||
SHEET_FW_UNI
|
||||
)
|
||||
private val variableWidthSheets = arrayOf(
|
||||
SHEET_ASCII_VARW,
|
||||
SHEET_CYRILIC_VARW,
|
||||
SHEET_EXTA_VARW,
|
||||
SHEET_EXTB_VARW,
|
||||
SHEET_CYRILIC_VARW,
|
||||
SHEET_UNI_PUNCT,
|
||||
SHEET_GREEK_VARW,
|
||||
SHEET_EXTB_VARW
|
||||
SHEET_THAI_VARW,
|
||||
SHEET_HAYEREN_VARW,
|
||||
SHEET_KARTULI_VARW,
|
||||
SHEET_IPA_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",
|
||||
"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,
|
||||
0xE000..0xE0FF
|
||||
)
|
||||
private val glyphWidths: HashMap<Int, Int> = HashMap() // if the value is negative, it's diacritics
|
||||
private val sheets: Array<SpriteSheet>
|
||||
|
||||
override fun getWidth(s: String) = getWidthSubstr(s, s.length)
|
||||
|
||||
private fun getWidthSubstr(s: String, endIndex: Int): Int {
|
||||
var len = 0
|
||||
for (i in 0..endIndex - 1) {
|
||||
val chr = s[i]
|
||||
val ctype = getSheetType(s[i])
|
||||
init {
|
||||
val sheetsPack = ArrayList<SpriteSheet>()
|
||||
|
||||
if (variableWidthSheets.contains(ctype)) {
|
||||
len += try {
|
||||
asciiWidths[chr.toInt()]!!
|
||||
}
|
||||
catch (e: kotlin.KotlinNullPointerException) {
|
||||
println("KotlinNullPointerException on glyph number ${Integer.toHexString(chr.toInt()).toUpperCase()}")
|
||||
//System.exit(1)
|
||||
W_LATIN_WIDE // failsafe
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
else if (zeroWidthSheets.contains(ctype))
|
||||
len += 0
|
||||
else if (ctype == SHEET_CJK_PUNCT)
|
||||
len += W_ASIAN_PUNCT
|
||||
else if (ctype == SHEET_HANGUL)
|
||||
len += W_HANGUL
|
||||
else if (ctype == SHEET_KANA)
|
||||
len += W_KANA
|
||||
else if (unihanWidthSheets.contains(ctype))
|
||||
len += W_UNIHAN
|
||||
else
|
||||
len += W_LATIN_WIDE
|
||||
|
||||
if (i < endIndex - 1) len += interchar
|
||||
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 throw IllegalArgumentException("[TerrarumSansBitmap] Unknown sheet index: $index")
|
||||
|
||||
|
||||
sheetsPack.add(texRegPack)
|
||||
}
|
||||
return len * scale
|
||||
|
||||
sheets = sheetsPack.toTypedArray()
|
||||
}
|
||||
|
||||
override fun getHeight(s: String) = H * scale
|
||||
private var localeBuffer = ""
|
||||
|
||||
override fun getLineHeight() = H * scale
|
||||
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)
|
||||
}
|
||||
|
||||
override fun drawString(x: Float, y: Float, s: String) = drawString(x, y, s, Color.white)
|
||||
localeBuffer = locale
|
||||
}
|
||||
|
||||
override fun drawString(x: Float, y: Float, s: String, color: Color) {
|
||||
GL11.glEnable(GL11.GL_BLEND)
|
||||
GL11.glColorMask(true, true, true, true)
|
||||
GL11.glBlendFunc(GL11.GL_SRC_ALPHA, GL11.GL_ONE_MINUS_SRC_ALPHA)
|
||||
override fun getLineHeight(): Int = H
|
||||
override fun getHeight(p0: String) = lineHeight
|
||||
|
||||
var thisCol = color
|
||||
|
||||
// hangul fonts first
|
||||
//hangulSheet.startUse() // disabling texture binding to make the font coloured
|
||||
// JOHAB
|
||||
for (i in 0..s.length - 1) {
|
||||
val ch = s[i]
|
||||
|
||||
if (ch.isColourCode()) {
|
||||
thisCol = colourKey[ch]!!
|
||||
continue
|
||||
}
|
||||
|
||||
if (isHangul(ch)) {
|
||||
val hIndex = ch.toInt() - 0xAC00
|
||||
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) {
|
||||
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()
|
||||
|
||||
|
||||
val mainCol = color
|
||||
val shadowCol = color.darker(0.5f)
|
||||
|
||||
|
||||
textBuffer.forEachIndexed { index, c ->
|
||||
val sheetID = getSheetType(c)
|
||||
val sheetXY = getSheetwisePosition(c)
|
||||
|
||||
//println("[TerrarumSansBitmap] sprite: $sheetID:${sheetXY[0]}x${sheetXY[1]}")
|
||||
|
||||
if (sheetID == SHEET_HANGUL) {
|
||||
val hangulSheet = sheets[SHEET_HANGUL]
|
||||
val hIndex = c.toInt() - 0xAC00
|
||||
|
||||
val indexCho = getHanChosung(hIndex)
|
||||
val indexJung = getHanJungseong(hIndex)
|
||||
@@ -187,133 +370,123 @@ open class GameFontBase : Font {
|
||||
val jungRow = getHanMedialRow(hIndex)
|
||||
val jongRow = getHanFinalRow(hIndex)
|
||||
|
||||
val glyphW = getWidth(ch.toString())
|
||||
|
||||
hangulSheet.getSubImage(indexCho, choRow).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
hangulSheet.getSubImage(indexJung, jungRow).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
hangulSheet.getSubImage(indexJong, jongRow).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
}
|
||||
}
|
||||
//hangulSheet.endUse()
|
||||
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)
|
||||
|
||||
// WenQuanYi
|
||||
//uniHan.startUse()
|
||||
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)
|
||||
|
||||
for (i in 0..s.length - 1) {
|
||||
val ch = s[i]
|
||||
|
||||
if (ch.isColourCode()) {
|
||||
thisCol = colourKey[ch]!!
|
||||
continue
|
||||
}
|
||||
|
||||
if (isUniHan(ch)) {
|
||||
val glyphW = getWidth("" + ch)
|
||||
uniHan.getSubImage(unihanIndexX(ch), unihanIndexY(ch)).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round((H - H_UNIHAN) / 2 + y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
//uniHan.endUse()
|
||||
|
||||
// regular fonts
|
||||
var prevInstance = -1
|
||||
for (i in 0..s.length - 1) {
|
||||
val ch = s[i]
|
||||
|
||||
if (ch.isColourCode()) {
|
||||
thisCol = colourKey[ch]!!
|
||||
continue
|
||||
}
|
||||
|
||||
if (!isHangul(ch) && !isUniHan(ch)) {
|
||||
|
||||
// if not init, endUse first
|
||||
if (prevInstance != -1) {
|
||||
//sheetKey[prevInstance].endUse()
|
||||
}
|
||||
//sheetKey[getSheetType(ch)].startUse()
|
||||
prevInstance = getSheetType(ch)
|
||||
|
||||
val sheetX: Int
|
||||
val sheetY: Int
|
||||
when (prevInstance) {
|
||||
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 -> {
|
||||
sheetX = uniPunctIndexX(ch)
|
||||
sheetY = uniPunctIndexY(ch)
|
||||
}
|
||||
SHEET_GREEK_VARW -> {
|
||||
sheetX = greekIndexX(ch)
|
||||
sheetY = greekIndexY(ch)
|
||||
}
|
||||
else -> {
|
||||
sheetX = ch.toInt() % 16
|
||||
sheetY = ch.toInt() / 16
|
||||
}
|
||||
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)
|
||||
}
|
||||
|
||||
val glyphW = getWidth("" + ch)
|
||||
|
||||
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 {
|
||||
sheetKey[prevInstance]!!.getSubImage(sheetX, sheetY).drawWithShadow(
|
||||
Math.round(x + getWidthSubstr(s, i + 1) - glyphW).toFloat(),
|
||||
Math.round(y).toFloat(),
|
||||
scale.toFloat(), thisCol
|
||||
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 (e: ArrayIndexOutOfBoundsException) {
|
||||
// character that does not exist in the sheet. No render, pass.
|
||||
}
|
||||
catch (e1: RuntimeException) {
|
||||
// System.err.println("[GameFontBase] RuntimeException raised while processing character '$ch' (U+${Integer.toHexString(ch.toInt()).toUpperCase()})")
|
||||
// e1.printStackTrack()
|
||||
catch (noSuchGlyph: ArrayIndexOutOfBoundsException) {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (prevInstance != -1) {
|
||||
//sheetKey[prevInstance].endUse()
|
||||
}
|
||||
|
||||
GL11.glEnd()
|
||||
}
|
||||
|
||||
|
||||
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 (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 {
|
||||
@@ -339,141 +512,163 @@ open class GameFontBase : Font {
|
||||
return SHEET_FW_UNI
|
||||
else if (isGreek(c))
|
||||
return SHEET_GREEK_VARW
|
||||
else if (c.isColourCode())
|
||||
return SHEET_COLOURCODE
|
||||
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
|
||||
return SHEET_UNKNOWN// fixed width punctuations
|
||||
return SHEET_UNKNOWN
|
||||
// fixed width
|
||||
// fallback
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw part of a string to the screen. Note that this will still position the text as though
|
||||
* it's part of the bigger string.
|
||||
* @param x
|
||||
* *
|
||||
* @param y
|
||||
* *
|
||||
* @param s
|
||||
* *
|
||||
* @param color
|
||||
* *
|
||||
* @param startIndex
|
||||
* *
|
||||
* @param endIndex
|
||||
*/
|
||||
override fun drawString(x: Float, y: Float, s: String, color: Color, startIndex: Int, endIndex: Int) {
|
||||
val unprintedHead = s.substring(0, startIndex)
|
||||
val printedBody = s.substring(startIndex, endIndex)
|
||||
val xoff = getWidth(unprintedHead)
|
||||
drawString(x + xoff, y, printedBody, color)
|
||||
}
|
||||
|
||||
fun Char.isColourCode() = colourKey.containsKey(this)
|
||||
|
||||
fun buildWidthTable(sheet: SpriteSheet, codeOffset: Int, codeRange: IntRange, rows: Int = 16) {
|
||||
fun Byte.toUint() = java.lang.Byte.toUnsignedInt(this)
|
||||
|
||||
/** @return Intarray(R, G, B, A) */
|
||||
fun Texture.getPixel(x: Int, y: Int): IntArray {
|
||||
val textureWidth = this.textureWidth
|
||||
val hasAlpha = this.hasAlpha()
|
||||
|
||||
val offset = (if (hasAlpha) 4 else 3) * (textureWidth * y + x) // 4: # of channels (RGBA)
|
||||
|
||||
if (ByteOrder.nativeOrder() == ByteOrder.LITTLE_ENDIAN) {
|
||||
return intArrayOf(
|
||||
this.textureData[offset].toUint(),
|
||||
this.textureData[offset + 1].toUint(),
|
||||
this.textureData[offset + 2].toUint(),
|
||||
if (hasAlpha)
|
||||
this.textureData[offset + 3].toUint()
|
||||
else 255
|
||||
)
|
||||
private fun getSheetwisePosition(ch: Char): IntArray {
|
||||
val sheetX: Int; val sheetY: Int
|
||||
when (getSheetType(ch)) {
|
||||
SHEET_UNIHAN -> {
|
||||
sheetX = unihanIndexX(ch)
|
||||
sheetY = unihanIndexY(ch)
|
||||
}
|
||||
else {
|
||||
return intArrayOf(
|
||||
this.textureData[offset + 2].toUint(),
|
||||
this.textureData[offset + 1].toUint(),
|
||||
this.textureData[offset].toUint(),
|
||||
if (hasAlpha)
|
||||
this.textureData[offset + 3].toUint()
|
||||
else 255
|
||||
)
|
||||
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 -> {
|
||||
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)
|
||||
}
|
||||
else -> {
|
||||
sheetX = ch.toInt() % 16
|
||||
sheetY = ch.toInt() / 16
|
||||
}
|
||||
}
|
||||
|
||||
val binaryCodeOffset = 15
|
||||
return intArrayOf(sheetX, sheetY)
|
||||
}
|
||||
|
||||
val cellW = sheet.getSubImage(0, 0).width + 1 // should be 16
|
||||
val cellH = sheet.getSubImage(0, 0).height + 1 // should be 20
|
||||
fun buildWidthTable(texture: Texture, codeRange: IntRange, cols: Int = 16) {
|
||||
val binaryCodeOffset = W_VAR_INIT
|
||||
|
||||
// control chars
|
||||
for (ccode in codeRange) {
|
||||
val glyphX = ccode % rows
|
||||
val glyphY = ccode / rows
|
||||
val cellW = W_VAR_INIT + 1
|
||||
val cellH = H
|
||||
|
||||
val codeStartX = (glyphX * cellW) + binaryCodeOffset
|
||||
val codeStartY = (glyphY * cellH)
|
||||
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 (sheet.texture.getPixel(codeStartX, codeStartY + downCtr)[3] == 255) {
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
asciiWidths[codeOffset + ccode] = glyphWidth
|
||||
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()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
lateinit internal var hangulSheet: SpriteSheet
|
||||
lateinit internal var asciiSheet: SpriteSheet
|
||||
|
||||
internal val asciiWidths: HashMap<Int, Int> = HashMap()
|
||||
|
||||
lateinit internal var extASheet: SpriteSheet
|
||||
lateinit internal var extBSheet: SpriteSheet
|
||||
lateinit internal var kanaSheet: SpriteSheet
|
||||
lateinit internal var cjkPunct: SpriteSheet
|
||||
lateinit internal var uniHan: SpriteSheet
|
||||
lateinit internal var cyrilic: SpriteSheet
|
||||
lateinit internal var fullwidthForms: SpriteSheet
|
||||
lateinit internal var uniPunct: SpriteSheet
|
||||
lateinit internal var greekSheet: SpriteSheet
|
||||
|
||||
internal val JUNG_COUNT = 21
|
||||
internal val JONG_COUNT = 28
|
||||
|
||||
internal val W_ASIAN_PUNCT = 10
|
||||
internal val W_HANGUL = 11
|
||||
internal val W_HANGUL = 12
|
||||
internal val W_KANA = 12
|
||||
internal val W_UNIHAN = 16
|
||||
internal val W_LATIN_WIDE = 9 // width of regular letters
|
||||
internal val W_VAR_INIT = 15
|
||||
|
||||
internal val HGAP_VAR = 1
|
||||
|
||||
internal val H = 20
|
||||
internal val H_UNIHAN = 16
|
||||
|
||||
internal val SHEET_ASCII_VARW = 0
|
||||
internal val SHEET_HANGUL = 1
|
||||
internal val SHEET_EXTA_VARW = 3
|
||||
internal val SHEET_EXTB_VARW = 4
|
||||
internal val SHEET_KANA = 5
|
||||
internal val SHEET_CJK_PUNCT = 6
|
||||
internal val SHEET_UNIHAN = 7
|
||||
internal val SHEET_CYRILIC_VARW = 8
|
||||
internal val SHEET_FW_UNI = 9
|
||||
internal val SHEET_UNI_PUNCT = 10
|
||||
internal val SHEET_GREEK_VARW = 11
|
||||
internal val SIZE_CUSTOM_SYM = 18
|
||||
|
||||
internal val SHEET_ASCII_VARW = 0
|
||||
internal val SHEET_HANGUL = 1
|
||||
internal val SHEET_EXTA_VARW = 2
|
||||
internal val SHEET_EXTB_VARW = 3
|
||||
internal val SHEET_KANA = 4
|
||||
internal val SHEET_CJK_PUNCT = 5
|
||||
internal val SHEET_UNIHAN = 6
|
||||
internal val SHEET_CYRILIC_VARW = 7
|
||||
internal val SHEET_FW_UNI = 8
|
||||
internal val SHEET_UNI_PUNCT = 9
|
||||
internal val SHEET_GREEK_VARW = 10
|
||||
internal val SHEET_THAI_VARW = 11
|
||||
internal val SHEET_HAYEREN_VARW = 12
|
||||
internal val SHEET_KARTULI_VARW = 13
|
||||
internal val SHEET_IPA_VARW = 14
|
||||
internal val SHEET_CUSTOM_SYM = 15
|
||||
|
||||
internal val SHEET_UNKNOWN = 254
|
||||
internal val SHEET_COLOURCODE = 255
|
||||
|
||||
lateinit internal var sheetKey: Array<SpriteSheet?>
|
||||
|
||||
/**
|
||||
* Runic letters list used for game. The set is
|
||||
@@ -491,68 +686,15 @@ open class GameFontBase : Font {
|
||||
* ᛭ᛋᛁᚴᚱᛁᚦᛦ᛭
|
||||
* ᛭ᛂᛚᛋᛅ᛭ᛏᚱᚢᛏᚾᛁᚾᚴᚢᚾᛅ᛬ᛅᚱᚾᛅᛏᛅᛚᛋ
|
||||
*/
|
||||
internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ')
|
||||
//internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ')
|
||||
// TODO expand to full Unicode runes
|
||||
|
||||
internal var interchar = 0
|
||||
internal var scale = 1
|
||||
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)")
|
||||
}
|
||||
}
|
||||
|
||||
val colourKey = hashMapOf(
|
||||
Pair(0x10.toChar(), Color(0xFFFFFF)), //*w hite
|
||||
Pair(0x11.toChar(), Color(0xFFE080)), //*y ellow
|
||||
Pair(0x12.toChar(), Color(0xFFB020)), //o range
|
||||
Pair(0x13.toChar(), Color(0xFF8080)), //*r ed
|
||||
Pair(0x14.toChar(), Color(0xFFA0E0)), //f uchsia
|
||||
Pair(0x15.toChar(), Color(0xE0A0FF)), //*m agenta (purple)
|
||||
Pair(0x16.toChar(), Color(0x8080FF)), //*b lue
|
||||
Pair(0x17.toChar(), Color(0x80FFFF)), //c yan
|
||||
Pair(0x18.toChar(), Color(0x80FF80)), //*g reen
|
||||
Pair(0x19.toChar(), Color(0x008000)), //v iridian
|
||||
Pair(0x1A.toChar(), Color(0x805030)), //x (khaki)
|
||||
Pair(0x1B.toChar(), Color(0x808080)) //*k
|
||||
//* marked: commonly used
|
||||
)
|
||||
val colToCode = hashMapOf(
|
||||
Pair("w", 0x10.toChar()),
|
||||
Pair("y", 0x11.toChar()),
|
||||
Pair("o", 0x12.toChar()),
|
||||
Pair("r", 0x13.toChar()),
|
||||
Pair("f", 0x14.toChar()),
|
||||
Pair("m", 0x15.toChar()),
|
||||
Pair("b", 0x16.toChar()),
|
||||
Pair("c", 0x17.toChar()),
|
||||
Pair("g", 0x18.toChar()),
|
||||
Pair("v", 0x19.toChar()),
|
||||
Pair("x", 0x1A.toChar()),
|
||||
Pair("k", 0x1B.toChar())
|
||||
)
|
||||
val codeToCol = hashMapOf(
|
||||
Pair("w", colourKey[0x10.toChar()]),
|
||||
Pair("y", colourKey[0x11.toChar()]),
|
||||
Pair("o", colourKey[0x12.toChar()]),
|
||||
Pair("r", colourKey[0x13.toChar()]),
|
||||
Pair("f", colourKey[0x14.toChar()]),
|
||||
Pair("m", colourKey[0x15.toChar()]),
|
||||
Pair("b", colourKey[0x16.toChar()]),
|
||||
Pair("c", colourKey[0x17.toChar()]),
|
||||
Pair("g", colourKey[0x18.toChar()]),
|
||||
Pair("v", colourKey[0x19.toChar()]),
|
||||
Pair("x", colourKey[0x1A.toChar()]),
|
||||
Pair("k", colourKey[0x1B.toChar()])
|
||||
)
|
||||
}// end of companion object
|
||||
}
|
||||
|
||||
fun Image.drawWithShadow(x: Float, y: Float, color: Color) =
|
||||
this.drawWithShadow(x, y, 1f, color)
|
||||
|
||||
fun Image.drawWithShadow(x: Float, y: Float, scale: Float, color: Color) {
|
||||
this.draw(x + 1, y + 1, scale, color.darker(0.5f))
|
||||
this.draw(x , y + 1, scale, color.darker(0.5f))
|
||||
this.draw(x + 1, y , scale, color.darker(0.5f))
|
||||
|
||||
this.draw(x, y, scale, color)
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
package net.torvald.terrarum.imagefont
|
||||
|
||||
import net.torvald.imagefont.GameFontImpl
|
||||
import net.torvald.terrarumsansbitmap.slick2d.GameFontBase
|
||||
import org.newdawn.slick.*
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
@@ -17,10 +17,11 @@ class GameFontDemo : BasicGame("Terrarum Sans Bitmap Demo") {
|
||||
lateinit var gameFont: Font
|
||||
|
||||
override fun init(p0: GameContainer?) {
|
||||
gameFont = GameFontImpl()
|
||||
gameFont = GameFontBase("assets/")
|
||||
}
|
||||
|
||||
override fun update(gc: GameContainer, delta: Int) {
|
||||
appgc!!.setTitle("Terrarum Sans Bitmap — F: ${gc.fps}")
|
||||
}
|
||||
|
||||
override fun render(gc: GameContainer, g: Graphics) {
|
||||
@@ -67,6 +68,8 @@ class GameFontDemo : BasicGame("Terrarum Sans Bitmap Demo") {
|
||||
}
|
||||
}
|
||||
|
||||
var appgc: AppGameContainer? = null
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
|
||||
System.setProperty("java.library.path", "lib")
|
||||
@@ -76,17 +79,17 @@ fun main(args: Array<String>) {
|
||||
val HEIGHT = 800
|
||||
|
||||
try {
|
||||
val appgc = AppGameContainer(GameFontDemo())
|
||||
appgc.setDisplayMode(WIDTH, HEIGHT, false)
|
||||
appgc = AppGameContainer(GameFontDemo())
|
||||
appgc!!.setDisplayMode(WIDTH, HEIGHT, false)
|
||||
|
||||
appgc.setMultiSample(0)
|
||||
appgc.setShowFPS(false)
|
||||
appgc!!.setMultiSample(0)
|
||||
appgc!!.setShowFPS(false)
|
||||
|
||||
// game will run normally even if it is not focused
|
||||
appgc.setUpdateOnlyWhenVisible(false)
|
||||
appgc.alwaysRender = true
|
||||
appgc!!.setUpdateOnlyWhenVisible(false)
|
||||
appgc!!.alwaysRender = true
|
||||
|
||||
appgc.start()
|
||||
appgc!!.start()
|
||||
}
|
||||
catch (ex: Exception) {
|
||||
ex.printStackTrace()
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
package net.torvald.imagefont
|
||||
|
||||
import net.torvald.terrarum.imagefont.GameFontDemo
|
||||
import org.newdawn.slick.*
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 16-01-20.
|
||||
*/
|
||||
class GameFontImpl : GameFontBase() {
|
||||
|
||||
init {
|
||||
|
||||
GameFontBase.hangulSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/hangul_johab.tga", GameFontBase.W_HANGUL, GameFontBase.H)
|
||||
GameFontBase.asciiSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/ascii_variable.tga", 15, 19, 1)
|
||||
GameFontBase.extASheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/LatinExtA_variable.tga", 15, 19, 1)
|
||||
GameFontBase.extBSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/LatinExtB_variable.tga", 15, 19, 1)
|
||||
GameFontBase.kanaSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/kana.tga", GameFontBase.W_KANA, GameFontBase.H)
|
||||
GameFontBase.cjkPunct = SpriteSheet(
|
||||
"./assets/graphics/fonts/cjkpunct.tga", GameFontBase.W_ASIAN_PUNCT, GameFontBase.H)
|
||||
GameFontBase.cyrilic = SpriteSheet(
|
||||
when (GameFontDemo.gameLocale.substring(0..1)) {
|
||||
"bg" -> "./assets/graphics/fonts/cyrilic_bulgarian_variable.tga"
|
||||
"sr" -> "./assets/graphics/fonts/cyrilic_serbian_variable.tga"
|
||||
else -> "./assets/graphics/fonts/cyrilic_variable.tga"
|
||||
}, 15, 19, 1)
|
||||
GameFontBase.fullwidthForms = SpriteSheet(
|
||||
"./assets/graphics/fonts/fullwidth_forms.tga", GameFontBase.W_UNIHAN, GameFontBase.H_UNIHAN)
|
||||
GameFontBase.uniPunct = SpriteSheet(
|
||||
"./assets/graphics/fonts/unipunct.tga", GameFontBase.W_LATIN_WIDE, GameFontBase.H)
|
||||
GameFontBase.uniHan = SpriteSheet(
|
||||
"./assets/graphics/fonts/wenquanyi.tga", 16, 16)
|
||||
GameFontBase.greekSheet = SpriteSheet(
|
||||
"./assets/graphics/fonts/greek_variable.tga", 15, 19, 1)
|
||||
|
||||
val shk = arrayOf(
|
||||
GameFontBase.asciiSheet,
|
||||
GameFontBase.hangulSheet,
|
||||
null, // here was customised runic sheet
|
||||
GameFontBase.extASheet,
|
||||
GameFontBase.extBSheet,
|
||||
GameFontBase.kanaSheet,
|
||||
GameFontBase.cjkPunct,
|
||||
GameFontBase.uniHan,
|
||||
GameFontBase.cyrilic,
|
||||
GameFontBase.fullwidthForms,
|
||||
GameFontBase.uniPunct,
|
||||
GameFontBase.greekSheet
|
||||
)
|
||||
GameFontBase.sheetKey = shk
|
||||
|
||||
|
||||
buildWidthTable(asciiSheet, 0, 0..0xFF)
|
||||
buildWidthTable(extASheet, 0x100, 0..0x7F)
|
||||
buildWidthTable(extBSheet, 0x180, 0..0xCF)
|
||||
buildWidthTable(cyrilic, 0x400, 0..0x5F)
|
||||
buildWidthTable(greekSheet, 0x370, 0..0x5F)
|
||||
}
|
||||
|
||||
fun reload() {
|
||||
GameFontBase.cyrilic.destroy()
|
||||
GameFontBase.cyrilic = SpriteSheet(
|
||||
when (GameFontDemo.gameLocale.substring(0..1)) {
|
||||
"bg" -> "./assets/graphics/fonts/cyrilic_bulgarian_variable.tga"
|
||||
"sr" -> "./assets/graphics/fonts/cyrilic_serbian_variable.tga"
|
||||
else -> "./assets/graphics/fonts/cyrilic_variable.tga"
|
||||
}, 15, 19, 1)
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,43 @@
|
||||
Set locale in config.properties to “bgBG” for alternative Bulgarian letters, “srSR” for Serbian.
|
||||
x86 се нарича общата микроархитектура на фамилия микропроцесори, основана на Intel 8086. Първите процесори от тази
|
||||
фамилия, разработени и произвеждани от Intel, са обозначавани с номера, завършващи на 86: 8086, 80186, 80286, 80386
|
||||
(впоследствие i386) и 486 (i486).
|
||||
|
||||
ABCDEFGHIJKLM NOPQRSTUVWXYZ 12345?
|
||||
abcdefghijklm nopqrstuvwxyz 67890!
|
||||
x86 — Intel 8086 prosessorunun arxitekturasının təlimatına əsasən yaradılan prosessor arxitekturası ailəsi.
|
||||
x86 (= 80x86) – IBM PC-uyumlu kompüterlərdə istifadə olunan Intel mikroprosessorları ailəsi (x = 1, ..., 5 və 8086
|
||||
üçün olmaya bilər). Bu ailəyə 086, 186, 286, 386, 486, Pentium, Pentium Pro, Pentium II aiddir.
|
||||
|
||||
The bitmap font for game developers who seek good font that has real multilingual support,
|
||||
for free (as in freedom AND without cost).
|
||||
Ο όρος x86 αναφέρεται σε μια οικογένεια από αρχιτεκτονικές συνόλου εντολών που βασίζονται στην CPU Intel 8086.
|
||||
Ο επεξεργαστής 8086 κυκλοφόρησε το 1978 σαν μια πλήρως 16-bit επέκταση του 8080 της Intel που βασιζόταν σε τεχνολογία
|
||||
8-bit, και εισήγαγε το segmentation για να ξεπεράσει το φράγμα των 16-bit διευθύνσεων της προηγούμενης σχεδίασης.
|
||||
|
||||
There are many bitmap fonts on the internet. You care for the multilingual support, but alas!
|
||||
most of them does not support your language, vector fonts takes too much time to be loaded,
|
||||
even then their legibility suffers because fuck built-in antialias.
|
||||
You somehow found a good font, and it makes your game look like a linux terminal, and you say:
|
||||
“what the fuck? Is this a game or should I rm -rf this shit‽”
|
||||
You speak Japanese, and you wish to support it, but then このクソなfontは only good for Japanese,
|
||||
and it is not multilingual, and you don't have a time for this shenanigan.
|
||||
Eventually you give up, saying “fuck it!” and just use the fonts that do not match well.
|
||||
x86 또는 80x86은 인텔이 개발한 마이크로프로세서 계열을 부르는 말이자, 이들과 호환되는 프로세서들에서 사용한 명령어 집합 구조들을 통칭하는
|
||||
말이다. x86 아키텍처는 데스크톱 컴퓨터 시장에서 매우 널리 쓰이며, PowerPC 같이 좀 더 근대적인 아키텍처를 사용한 프로세서들이 x86과 경쟁했으나
|
||||
그다지 많은 시장 점유율을 확보하지는 못했다.
|
||||
|
||||
No more suffering. This font has everything you need.
|
||||
x86(Intel 80x86)-ն ապարատային պլատֆորմ է, որը հանդիսանում է միկրոպրոցեսորի ճարտարապետություն և հրամանների
|
||||
համապատասխան հավաքածու։ Այն մշակված է և թողարկված, ինչպես Intel-ի, այնպես էլ նրա հետ համատեղելի պրոցեսորների
|
||||
համար, որոնք ստեղծվել են այլ արտադրողների կողմից։
|
||||
|
||||
while (isVisible(BadFonts)) { ripAndTear(BadFonts).scope(Guts); }
|
||||
How multilingual? Real multilingual!
|
||||
Pentium არის კომპანია ინტელის მიერ 1993 წელს გამოშვებული პროცესორი. იგი იყო წარმატებული i486-CPU სერიის
|
||||
ჩიპების მომდევნო თაობა. Pente (πέντε) – ბერძნული სიტყვაა და ხუთს ნიშნავს. იგი ხომ ინტელის სახლის x86 სერიის
|
||||
ჩიპების მეხუთე თაობას წარმოადგენდა.
|
||||
|
||||
Příliš žluťoučký kůň úpěl ďábelské ódy
|
||||
Victor jagt zwölf Boxkämpfer quer über den großen Sylter Deich
|
||||
διαφυλάξτε γενικά τη ζωή σας από βαθειά ψυχικά τραύματα
|
||||
ΔΙΑΦΥΛΆΞΤΕ ΓΕΝΙΚΆ ΤΗ ΖΩΉ ΣΑΣ ΑΠΌ ΒΑΘΕΙΆ ΨΥΧΙΚΆ ΤΡΑΎΜΑΤΑ
|
||||
Pack my box with five dozen liquor jugs
|
||||
Voix ambiguë d'un cœur qui au zéphyr préfère les jattes de kiwi
|
||||
정 참판 양반댁 규수 큰 교자 타고 혼례 치른 날 뚫훍뚫훍뚫(읗) 뚫훍뚫훍뚫(읗) 뚫훍뚫훍뚫 따다다
|
||||
Kæmi ný öxi hér, ykist þjófum nú bæði víl og ádrepa
|
||||
Árvíztűrő tükörfúrógép Kŕdeľ ďatľov učí koňa žrať kôru
|
||||
とりなくこゑす ゆめさませ みよあけわたる ひんかしを そらいろはえて おきつへに ほふねむれゐぬ もやのうち
|
||||
鳥啼く声す 夢覚ませ 見よ明け渡る 東を 空色栄えて 沖つ辺に 帆船群れゐぬ 靄の中
|
||||
Înjurând pițigăiat, zoofobul comandă vexat whisky și tequila
|
||||
Широкая электрификация южных губерний даст мощный толчок подъёму сельского хозяйства
|
||||
Pijamalı hasta yağız şoföre çabucak güvendi
|
||||
Also supports: ‛Unicode’ „quotation marks“—dashes…「括弧」‼
|
||||
ASCII Latin-1 Latin_Ext-A Latin_Ext-B Greek Cyrillic CJK-Ideo Kana Hangul_Syllables
|
||||
x86(エックスはちろく)は、Intel 8086、およびその後方互換性を持つマイクロプロセッサの命令セットアーキテクチャの総称。
|
||||
16ビットの8086で登場し、32ビット拡張の80386(後にIA-32と命名)、64ビット拡張のx64、広義には更にAMDなどの互換プロセッサを含む。
|
||||
|
||||
x86 (англ. Intel 80x86) — архитектура процессора c одноимённым набором команд, впервые реализованная в процессорах
|
||||
компании Intel. Название образовано от двух цифр, которыми заканчивались названия процессоров Intel ранних моделей —
|
||||
8086, 80186, 80286 (i286), 80386 (i386), 80486 (i486).
|
||||
|
||||
x86 on Intelin kehittämä ja valmistama suoritinarkkitehtuuri. Intel ei kuitenkaan ole arkkitehtuurin ainoa valmistaja
|
||||
vaan myös AMD, Cyrix, NEC, Transmeta, VIA ja Zilog ovat valmistaneet x86-yhteensopivia suorittimia.
|
||||
|
||||
เอกซ์86 (x86) เป็นชื่อทั่วไปของสถาปัตยกรรมคอมพิวเตอร์สำหรับไมโครโพรเซสเซอร์ที่สร้างโดยบริษัทอินเทล ปัจจุบันสถาปัตยกรรมแบบ x86
|
||||
เป็นสถาปัตยกรรมที่ได้รับความนิยมมากที่สุดในตลาดคอมพิวเตอร์เดสก์ท็อป, โน้ตบุ๊คและเซิร์ฟเวอร์ขนาดเล็ก นับตั้งแต่เริ่มใช้ในไอบีเอ็มพีซี ช่วงทศวรรษที่ 80
|
||||
|
||||
x86 (англ. Intel 80x86) — архітектура процесорів та ядра мікроконтролерів з однойменною системою команд. x86 або 80x86
|
||||
є загальною назвою мікропроцесорної архітектури та архітектури розробленої на її базі обчислювальної техніки.
|
||||
|
||||
x86是一個指令集架構家族,最早由英特爾在1978年面市的「Intel 8086」CPU上開發出來。
|
||||
該系列較早期的處理器名稱是以數字來表示80x86。由於以“86”作為結尾,包括Intel 8086、80186、80286、80386以及80486,因此其架
|
||||
構被稱為“x86”。由於數字並不能作為註冊商標,因此Intel及其競爭者均在新一代處理器使用可註冊的名稱,如Pentium。
|
||||
BIN
font_test_3.PNG
|
Before Width: | Height: | Size: 56 KiB After Width: | Height: | Size: 62 KiB |
3
samples/README.md
Normal file
@@ -0,0 +1,3 @@
|
||||
Following is a rendering of various versions of Wikipedia article "x86". The particular article was chosen because it contains good mixture of English and numbers.
|
||||
|
||||

|
||||
BIN
samples/wikipedia_x86.png
Normal file
|
After Width: | Height: | Size: 75 KiB |
745
src/net/torvald/terrarumsansbitmap/gdx/GameFontBase.kt
Normal file
@@ -0,0 +1,745 @@
|
||||
/*
|
||||
* 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.gdx
|
||||
|
||||
import com.badlogic.gdx.Gdx
|
||||
import com.badlogic.gdx.graphics.Pixmap
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.*
|
||||
import java.io.BufferedOutputStream
|
||||
import java.io.File
|
||||
import java.io.FileOutputStream
|
||||
import java.util.zip.GZIPInputStream
|
||||
|
||||
/**
|
||||
* LibGDX 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.
|
||||
*
|
||||
* @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, val flipY: Boolean = false) : BitmapFont() {
|
||||
|
||||
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) = runicList.contains(c)
|
||||
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]
|
||||
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 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) = runicList.indexOf(c) % 16
|
||||
//private fun runicIndexY(c: Char) = runicList.indexOf(c) / 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 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,
|
||||
SHEET_GREEK_VARW,
|
||||
SHEET_THAI_VARW,
|
||||
SHEET_HAYEREN_VARW,
|
||||
SHEET_KARTULI_VARW,
|
||||
SHEET_IPA_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",
|
||||
"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,
|
||||
0xE000..0xE0FF
|
||||
)
|
||||
private val glyphWidths: HashMap<Int, Int> = HashMap() // if the value is negative, it's diacritics
|
||||
private val sheets: Array<TextureRegionPack>
|
||||
|
||||
|
||||
init {
|
||||
val sheetsPack = ArrayList<TextureRegionPack>()
|
||||
|
||||
// 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 pixmap: Pixmap
|
||||
|
||||
|
||||
// unpack gz if applicable
|
||||
if (it.endsWith(".gz")) {
|
||||
val gzi = GZIPInputStream(Gdx.files.internal(fontParentDir + it).read(8192))
|
||||
val wholeFile = gzi.readBytes()
|
||||
gzi.close()
|
||||
val fos = BufferedOutputStream(FileOutputStream("tmp_wenquanyi.tga"))
|
||||
fos.write(wholeFile)
|
||||
fos.flush()
|
||||
fos.close()
|
||||
|
||||
pixmap = Pixmap(Gdx.files.internal("tmp_wenquanyi.tga"))
|
||||
|
||||
File("tmp_wenquanyi.tga").delete()
|
||||
}
|
||||
else {
|
||||
pixmap = Pixmap(Gdx.files.internal(fontParentDir + it))
|
||||
}
|
||||
|
||||
|
||||
if (isVariable) {
|
||||
println("[TerrarumSansBitmap] loading texture $it [VARIABLE]")
|
||||
buildWidthTable(pixmap, codeRange[index], 16)
|
||||
}
|
||||
else {
|
||||
println("[TerrarumSansBitmap] loading texture $it")
|
||||
}
|
||||
|
||||
val texture = Texture(pixmap)
|
||||
val texRegPack = if (isVariable) {
|
||||
TextureRegionPack(texture, W_VAR_INIT, H, HGAP_VAR, 0)
|
||||
}
|
||||
else if (index == SHEET_UNIHAN) {
|
||||
TextureRegionPack(texture, 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) {
|
||||
TextureRegionPack(texture, W_UNIHAN, H)
|
||||
}
|
||||
else if (index == SHEET_CJK_PUNCT) {
|
||||
TextureRegionPack(texture, W_ASIAN_PUNCT, H)
|
||||
}
|
||||
else if (index == SHEET_KANA) {
|
||||
TextureRegionPack(texture, W_KANA, H)
|
||||
}
|
||||
else if (index == SHEET_HANGUL) {
|
||||
TextureRegionPack(texture, W_HANGUL, H)
|
||||
}
|
||||
else if (index == SHEET_CUSTOM_SYM) {
|
||||
TextureRegionPack(texture, SIZE_CUSTOM_SYM, SIZE_CUSTOM_SYM) // TODO variable
|
||||
}
|
||||
else throw IllegalArgumentException("[TerrarumSansBitmap] Unknown sheet index: $index")
|
||||
|
||||
|
||||
sheetsPack.add(texRegPack)
|
||||
|
||||
pixmap.dispose() // you are terminated
|
||||
}
|
||||
|
||||
sheets = sheetsPack.toTypedArray()
|
||||
}
|
||||
|
||||
private var localeBuffer = ""
|
||||
|
||||
fun reload(locale: String) {
|
||||
if (!localeBuffer.startsWith("ru") && locale.startsWith("ru")) {
|
||||
val pixmap = Pixmap(Gdx.files.internal(fontParentDir + fileList[SHEET_CYRILIC_VARW]))
|
||||
val texture = Texture(pixmap)
|
||||
sheets[SHEET_CYRILIC_VARW].dispose()
|
||||
sheets[SHEET_CYRILIC_VARW] = TextureRegionPack(texture, W_VAR_INIT, H, HGAP_VAR, 0)
|
||||
pixmap.dispose()
|
||||
}
|
||||
else if (!localeBuffer.startsWith("bg") && locale.startsWith("bg")) {
|
||||
val pixmap = Pixmap(Gdx.files.internal(fontParentDir + cyrilic_bg))
|
||||
val texture = Texture(pixmap)
|
||||
sheets[SHEET_CYRILIC_VARW].dispose()
|
||||
sheets[SHEET_CYRILIC_VARW] = TextureRegionPack(texture, W_VAR_INIT, H, HGAP_VAR, 0)
|
||||
pixmap.dispose()
|
||||
}
|
||||
else if (!localeBuffer.startsWith("sr") && locale.startsWith("sr")) {
|
||||
val pixmap = Pixmap(Gdx.files.internal(fontParentDir + cyrilic_sr))
|
||||
val texture = Texture(pixmap)
|
||||
sheets[SHEET_CYRILIC_VARW].dispose()
|
||||
sheets[SHEET_CYRILIC_VARW] = TextureRegionPack(texture, W_VAR_INIT, H, HGAP_VAR, 0)
|
||||
pixmap.dispose()
|
||||
}
|
||||
|
||||
localeBuffer = locale
|
||||
}
|
||||
|
||||
override fun getLineHeight(): Float = H.toFloat()
|
||||
|
||||
override fun getXHeight() = lineHeight
|
||||
override fun getCapHeight() = lineHeight
|
||||
override fun getAscent() = 0f
|
||||
override fun getDescent() = 0f
|
||||
|
||||
override fun isFlipped() = false
|
||||
|
||||
override fun setFixedWidthGlyphs(glyphs: CharSequence) {
|
||||
throw UnsupportedOperationException("Nope, no monospace, and figures are already fixed width, bruv.")
|
||||
}
|
||||
|
||||
|
||||
init {
|
||||
setUseIntegerPositions(true)
|
||||
setOwnsTexture(true)
|
||||
}
|
||||
|
||||
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 draw(batch: Batch, str: CharSequence, x: Float, y: Float): GlyphLayout? {
|
||||
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()
|
||||
|
||||
|
||||
val mainCol = batch.color.cpy()
|
||||
val shadowCol = batch.color.cpy().mul(0.5f,0.5f,0.5f,1f)
|
||||
|
||||
|
||||
textBuffer.forEachIndexed { index, c ->
|
||||
val sheetID = getSheetType(c)
|
||||
val (sheetX, sheetY) = getSheetwisePosition(c)
|
||||
|
||||
//println("[TerrarumSansBitmap] sprite: $sheetID:${sheetX}x${sheetY}")
|
||||
|
||||
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) {
|
||||
batch.color = shadowCol
|
||||
|
||||
batch.draw(hangulSheet.get(indexCho, choRow ), x + textBWidth[index] + 1, y)
|
||||
batch.draw(hangulSheet.get(indexCho, choRow ), x + textBWidth[index] , y + if (flipY) 1 else -1)
|
||||
batch.draw(hangulSheet.get(indexCho, choRow ), x + textBWidth[index] + 1, y + if (flipY) 1 else -1)
|
||||
|
||||
batch.draw(hangulSheet.get(indexJung, jungRow), x + textBWidth[index] + 1, y)
|
||||
batch.draw(hangulSheet.get(indexJung, jungRow), x + textBWidth[index] , y + if (flipY) 1 else -1)
|
||||
batch.draw(hangulSheet.get(indexJung, jungRow), x + textBWidth[index] + 1, y + if (flipY) 1 else -1)
|
||||
|
||||
batch.draw(hangulSheet.get(indexJong, jongRow), x + textBWidth[index] + 1, y)
|
||||
batch.draw(hangulSheet.get(indexJong, jongRow), x + textBWidth[index] , y + if (flipY) 1 else -1)
|
||||
batch.draw(hangulSheet.get(indexJong, jongRow), x + textBWidth[index] + 1, y + if (flipY) 1 else -1)
|
||||
}
|
||||
|
||||
|
||||
batch.color = mainCol
|
||||
batch.draw(hangulSheet.get(indexCho, choRow) , x + textBWidth[index], y)
|
||||
batch.draw(hangulSheet.get(indexJung, jungRow), x + textBWidth[index], y)
|
||||
batch.draw(hangulSheet.get(indexJong, jongRow), x + textBWidth[index], y)
|
||||
}
|
||||
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) {
|
||||
batch.color = shadowCol
|
||||
batch.draw(
|
||||
sheets[sheetID].get(sheetX, sheetY),
|
||||
x + textBWidth[index] + 1 + offset,
|
||||
y + (if (sheetID == SHEET_UNIHAN) // evil exceptions
|
||||
offsetUnihan
|
||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
||||
offsetCustomSym
|
||||
else
|
||||
0) * if (flipY) 1 else -1
|
||||
)
|
||||
batch.draw(
|
||||
sheets[sheetID].get(sheetX, sheetY),
|
||||
x + textBWidth[index] + offset,
|
||||
y + (if (sheetID == SHEET_UNIHAN) // evil exceptions
|
||||
offsetUnihan + 1
|
||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
||||
offsetCustomSym + 1
|
||||
else
|
||||
1) * if (flipY) 1 else -1
|
||||
)
|
||||
batch.draw(
|
||||
sheets[sheetID].get(sheetX, sheetY),
|
||||
x + textBWidth[index] + 1 + offset,
|
||||
y + (if (sheetID == SHEET_UNIHAN) // evil exceptions
|
||||
offsetUnihan + 1
|
||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
||||
offsetCustomSym + 1
|
||||
else
|
||||
1) * if (flipY) 1 else -1
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
batch.color = mainCol
|
||||
batch.draw(
|
||||
sheets[sheetID].get(sheetX, sheetY),
|
||||
x + textBWidth[index] + offset,
|
||||
y +
|
||||
if (sheetID == SHEET_UNIHAN) // evil exceptions
|
||||
offsetUnihan
|
||||
else if (sheetID == SHEET_CUSTOM_SYM)
|
||||
offsetCustomSym
|
||||
else 0
|
||||
)
|
||||
}
|
||||
catch (noSuchGlyph: ArrayIndexOutOfBoundsException) {
|
||||
batch.color = mainCol
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
|
||||
override fun dispose() {
|
||||
super.dispose()
|
||||
|
||||
sheets.forEach { it.dispose() }
|
||||
}
|
||||
|
||||
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 (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
|
||||
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
|
||||
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 -> {
|
||||
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)
|
||||
}
|
||||
else -> {
|
||||
sheetX = ch.toInt() % 16
|
||||
sheetY = ch.toInt() / 16
|
||||
}
|
||||
}
|
||||
|
||||
return intArrayOf(sheetX, sheetY)
|
||||
}
|
||||
|
||||
fun buildWidthTable(pixmap: Pixmap, 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 (pixmap.getPixel(codeStartX, codeStartY + downCtr).and(0xFF) != 0) {
|
||||
glyphWidth = glyphWidth or (1 shl downCtr)
|
||||
}
|
||||
}
|
||||
|
||||
val isDiacritics = pixmap.getPixel(codeStartX, codeStartY + H - 1).and(0xFF) != 0
|
||||
if (isDiacritics)
|
||||
glyphWidth = -glyphWidth
|
||||
|
||||
glyphWidths[code] = glyphWidth
|
||||
}
|
||||
}
|
||||
|
||||
private val glyphLayout = GlyphLayout()
|
||||
|
||||
fun getWidth(text: String): Int {
|
||||
glyphLayout.setText(this, text)
|
||||
return glyphLayout.width.toInt()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
internal val JUNG_COUNT = 21
|
||||
internal val JONG_COUNT = 28
|
||||
|
||||
internal val W_ASIAN_PUNCT = 10
|
||||
internal val W_HANGUL = 12
|
||||
internal val W_KANA = 12
|
||||
internal val W_UNIHAN = 16
|
||||
internal val W_LATIN_WIDE = 9 // width of regular letters
|
||||
internal val W_VAR_INIT = 15
|
||||
|
||||
internal val HGAP_VAR = 1
|
||||
|
||||
internal val H = 20
|
||||
internal val H_UNIHAN = 16
|
||||
|
||||
internal val SIZE_CUSTOM_SYM = 18
|
||||
|
||||
internal val SHEET_ASCII_VARW = 0
|
||||
internal val SHEET_HANGUL = 1
|
||||
internal val SHEET_EXTA_VARW = 2
|
||||
internal val SHEET_EXTB_VARW = 3
|
||||
internal val SHEET_KANA = 4
|
||||
internal val SHEET_CJK_PUNCT = 5
|
||||
internal val SHEET_UNIHAN = 6
|
||||
internal val SHEET_CYRILIC_VARW = 7
|
||||
internal val SHEET_FW_UNI = 8
|
||||
internal val SHEET_UNI_PUNCT = 9
|
||||
internal val SHEET_GREEK_VARW = 10
|
||||
internal val SHEET_THAI_VARW = 11
|
||||
internal val SHEET_HAYEREN_VARW = 12
|
||||
internal val SHEET_KARTULI_VARW = 13
|
||||
internal val SHEET_IPA_VARW = 14
|
||||
internal val SHEET_CUSTOM_SYM = 15
|
||||
|
||||
internal val SHEET_UNKNOWN = 254
|
||||
|
||||
/**
|
||||
* Runic letters list used for game. The set is
|
||||
* Younger Futhark + Medieval rune 'e' + Punct + Runic Almanac
|
||||
|
||||
* BEWARE OF SIMILAR-LOOKING RUNES, especially:
|
||||
|
||||
* * Algiz ᛉ instead of Maðr ᛘ
|
||||
|
||||
* * Short-Twig Hagall ᚽ instead of Runic Letter E ᛂ
|
||||
|
||||
* * Runic Letter OE ᚯ instead of Óss ᚬ
|
||||
|
||||
* Examples:
|
||||
* ᛭ᛋᛁᚴᚱᛁᚦᛦ᛭
|
||||
* ᛭ᛂᛚᛋᛅ᛭ᛏᚱᚢᛏᚾᛁᚾᚴᚢᚾᛅ᛬ᛅᚱᚾᛅᛏᛅᛚᛋ
|
||||
*/
|
||||
//internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ')
|
||||
// TODO expand to full Unicode runes
|
||||
|
||||
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)")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
82
src/net/torvald/terrarumsansbitmap/gdx/TextureRegionPack.kt
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* 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.gdx
|
||||
|
||||
import com.badlogic.gdx.files.FileHandle
|
||||
import com.badlogic.gdx.graphics.Texture
|
||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||
|
||||
/**
|
||||
* Created by minjaesong on 2017-06-15.
|
||||
*/
|
||||
class TextureRegionPack(
|
||||
val texture: Texture,
|
||||
val tileW: Int,
|
||||
val tileH: Int,
|
||||
val hGap: Int = 0,
|
||||
val vGap: Int = 0,
|
||||
val hFrame: Int = 0,
|
||||
val vFrame: Int = 0
|
||||
) {
|
||||
|
||||
constructor(ref: String, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0) :
|
||||
this(Texture(ref), tileW, tileH, hGap, vGap, hFrame, vFrame)
|
||||
constructor(fileHandle: FileHandle, tileW: Int, tileH: Int, hGap: Int = 0, vGap: Int = 0, hFrame: Int = 0, vFrame: Int = 0) :
|
||||
this(Texture(fileHandle), tileW, tileH, hGap, vGap, hFrame, vFrame)
|
||||
|
||||
companion object {
|
||||
/** Intented for Y-down coord system, typically fon Non-GDX codebase */
|
||||
var globalFlipY = false
|
||||
}
|
||||
|
||||
val regions: Array<TextureRegion>
|
||||
|
||||
val horizontalCount = (texture.width - 2 * hFrame + hGap) / (tileW + hGap)
|
||||
val verticalCount = (texture.height - 2 * vFrame + vGap) / (tileH + vGap)
|
||||
|
||||
init {
|
||||
//println("texture: $texture, dim: ${texture.width} x ${texture.height}, grid: $horizontalCount x $verticalCount, cellDim: $tileW x $tileH")
|
||||
|
||||
regions = Array<TextureRegion>(horizontalCount * verticalCount, {
|
||||
val region = TextureRegion()
|
||||
val rx = (it % horizontalCount * (tileW + hGap)) + hFrame
|
||||
val ry = (it / horizontalCount * (tileH + vGap)) + vFrame
|
||||
|
||||
region.setRegion(texture)
|
||||
region.setRegion(rx, ry, tileW, tileH)
|
||||
|
||||
region.flip(false, globalFlipY)
|
||||
|
||||
/*return*/region
|
||||
})
|
||||
}
|
||||
|
||||
fun get(x: Int, y: Int) = regions[y * horizontalCount + x]
|
||||
|
||||
fun dispose() {
|
||||
texture.dispose()
|
||||
}
|
||||
|
||||
}
|
||||
1
src/net/torvald/terrarumsansbitmap/readme.md
Normal file
@@ -0,0 +1 @@
|
||||
This directory contains implementation of the font in various frameworks.
|
||||
724
src/net/torvald/terrarumsansbitmap/slick2d/GameFontBase.kt
Normal file
@@ -0,0 +1,724 @@
|
||||
/*
|
||||
* 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 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 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.
|
||||
*
|
||||
* @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) = runicList.contains(c)
|
||||
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]
|
||||
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 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) = runicList.indexOf(c) % 16
|
||||
//private fun runicIndexY(c: Char) = runicList.indexOf(c) / 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 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,
|
||||
SHEET_GREEK_VARW,
|
||||
SHEET_THAI_VARW,
|
||||
SHEET_HAYEREN_VARW,
|
||||
SHEET_KARTULI_VARW,
|
||||
SHEET_IPA_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",
|
||||
"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,
|
||||
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 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) {
|
||||
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()
|
||||
|
||||
|
||||
val mainCol = color
|
||||
val shadowCol = color.darker(0.5f)
|
||||
|
||||
|
||||
textBuffer.forEachIndexed { index, c ->
|
||||
val sheetID = getSheetType(c)
|
||||
val sheetXY = getSheetwisePosition(c)
|
||||
|
||||
//println("[TerrarumSansBitmap] sprite: $sheetID:${sheetXY[0]}x${sheetXY[1]}")
|
||||
|
||||
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) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
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 (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
|
||||
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
|
||||
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 -> {
|
||||
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)
|
||||
}
|
||||
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()
|
||||
}
|
||||
|
||||
companion object {
|
||||
|
||||
internal val JUNG_COUNT = 21
|
||||
internal val JONG_COUNT = 28
|
||||
|
||||
internal val W_ASIAN_PUNCT = 10
|
||||
internal val W_HANGUL = 12
|
||||
internal val W_KANA = 12
|
||||
internal val W_UNIHAN = 16
|
||||
internal val W_LATIN_WIDE = 9 // width of regular letters
|
||||
internal val W_VAR_INIT = 15
|
||||
|
||||
internal val HGAP_VAR = 1
|
||||
|
||||
internal val H = 20
|
||||
internal val H_UNIHAN = 16
|
||||
|
||||
internal val SIZE_CUSTOM_SYM = 18
|
||||
|
||||
internal val SHEET_ASCII_VARW = 0
|
||||
internal val SHEET_HANGUL = 1
|
||||
internal val SHEET_EXTA_VARW = 2
|
||||
internal val SHEET_EXTB_VARW = 3
|
||||
internal val SHEET_KANA = 4
|
||||
internal val SHEET_CJK_PUNCT = 5
|
||||
internal val SHEET_UNIHAN = 6
|
||||
internal val SHEET_CYRILIC_VARW = 7
|
||||
internal val SHEET_FW_UNI = 8
|
||||
internal val SHEET_UNI_PUNCT = 9
|
||||
internal val SHEET_GREEK_VARW = 10
|
||||
internal val SHEET_THAI_VARW = 11
|
||||
internal val SHEET_HAYEREN_VARW = 12
|
||||
internal val SHEET_KARTULI_VARW = 13
|
||||
internal val SHEET_IPA_VARW = 14
|
||||
internal val SHEET_CUSTOM_SYM = 15
|
||||
|
||||
internal val SHEET_UNKNOWN = 254
|
||||
|
||||
/**
|
||||
* Runic letters list used for game. The set is
|
||||
* Younger Futhark + Medieval rune 'e' + Punct + Runic Almanac
|
||||
|
||||
* BEWARE OF SIMILAR-LOOKING RUNES, especially:
|
||||
|
||||
* * Algiz ᛉ instead of Maðr ᛘ
|
||||
|
||||
* * Short-Twig Hagall ᚽ instead of Runic Letter E ᛂ
|
||||
|
||||
* * Runic Letter OE ᚯ instead of Óss ᚬ
|
||||
|
||||
* Examples:
|
||||
* ᛭ᛋᛁᚴᚱᛁᚦᛦ᛭
|
||||
* ᛭ᛂᛚᛋᛅ᛭ᛏᚱᚢᛏᚾᛁᚾᚴᚢᚾᛅ᛬ᛅᚱᚾᛅᛏᛅᛚᛋ
|
||||
*/
|
||||
//internal val runicList = arrayOf('ᚠ', 'ᚢ', 'ᚦ', 'ᚬ', 'ᚱ', 'ᚴ', 'ᚼ', 'ᚾ', 'ᛁ', 'ᛅ', 'ᛋ', 'ᛏ', 'ᛒ', 'ᛘ', 'ᛚ', 'ᛦ', 'ᛂ', '᛬', '᛫', '᛭', 'ᛮ', 'ᛯ', 'ᛰ')
|
||||
// TODO expand to full Unicode runes
|
||||
|
||||
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)")
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
BIN
width_bit_encoding_annotated.png
Normal file
|
After Width: | Height: | Size: 18 KiB |